Internationalization
Configuration
- Plugin:
@nuxtjs/i18n9.3.1 - Strategy:
no_prefix— locale is NOT in the URL path - Default locale:
en_GB
Supported Locales
| Code | Language | RTL? |
|---|---|---|
ar_SA | Arabic (Saudi Arabia) | ✓ |
de_DE | German (Germany) | |
en_GB | English (UK) — default | |
en_US | English (US) | |
es_ES | Spanish (Spain) | |
fr_FR | French (France) | |
pl_PL | Polish (Poland) | |
pt_PT | Portuguese (Portugal) | |
ru_RU | Russian (Russia) | |
sv_SE | Swedish (Sweden) |
Locale Files
Translation JSON files are in i18n/locales/ at the project root (not inside app/):
i18n/locales/
├── ar_SA.json
├── de_DE.json
├── en_GB.json
├── en_US.json
├── es_ES.json
├── fr_FR.json
├── pl_PL.json
├── pt_PT.json
├── ru_RU.json
└── sv_SE.jsonAll translation keys must exist in all 10 locale files.
Usage in Components
ts
// Composition API
const { t, locale } = useI18n();
// In template
{
{
t("home.questionnaire.start_button");
}
}Adding Translations
- Add the key to all 10 locale JSON files
- Use descriptive, namespaced keys:
section.subsection.element - Avoid HTML in translations; if required,
escapeHtml: falseis already configured
Key naming convention
Use snake_case with dot-separated namespaces: home.questionnaire.start_button Never use camelCase or hyphens in i18n keys.
Locale Codes — Underscores, Not Hyphens
Critical convention
Locale codes use underscores: en_GB, de_DE, ar_SA.
The locale objects have a separate language property (en-GB) used only for the HTML lang attribute. Everywhere else — Pinia store, i18n plugin, locale filenames, comparisons — use the underscore format.
Locale Persistence
- On startup: resolved from persisted user preference → device language → fallback
en_GB - Stored in
device.userLocale(Pinia) and persisted viauseLocalConfig() - Synced to the
@nuxtjs/i18nplugin inapp/pages/index.vueon locale changes
RTL Support
Arabic (ar_SA) is the only RTL locale.
- The
<html dir="rtl">attribute is set automatically by the i18n plugin - Use logical CSS properties (
margin-inline-startinstead ofmargin-left) in components - Always test new layout changes with Arabic locale active