# Nuxt I18n Reference **Last Updated:** 2025-11 (v10.2.0) **Check:** `@nuxtjs/i18n` in package.json Nuxt I18n v10 provides internationalization (i18n) for Nuxt applications with auto-imports, locale routing, SEO support, and integration with Vue I18n v11. ## Installation & Setup ```bash pnpm add @nuxtjs/i18n ``` **nuxt.config.ts:** ```typescript export default defineNuxtConfig({ modules: ["@nuxtjs/i18n"], i18n: { locales: [ { code: "en", iso: "en-US", name: "English", file: "en.json" }, { code: "fr", iso: "fr-FR", name: "Français", file: "fr.json" }, { code: "es", iso: "es-ES", name: "Español", file: "es.json" }, ], defaultLocale: "en", langDir: "locales/", strategy: "prefix_except_default", // or 'prefix', 'no_prefix' detectBrowserLanguage: { useCookie: true, cookieKey: "i18n_redirected", redirectOn: "root", }, }, }) ``` ## Directory Structure ``` locales/ ├── en.json ├── fr.json └── es.json ``` **Example locale file (en.json):** ```json { "welcome": "Welcome", "hello": "Hello {name}", "nav": { "home": "Home", "about": "About", "contact": "Contact" }, "products": { "title": "Our Products", "description": "Browse our collection" } } ``` ## Basic Usage ### Translation in Templates ```vue ``` ### Translation in Script ```vue ``` ## Routing ### Route Strategies **prefix_except_default** (recommended): - Default locale: `/about` - Other locales: `/fr/about`, `/es/about` **prefix**: - All locales: `/en/about`, `/fr/about`, `/es/about` **no_prefix**: - All locales use same path: `/about` - Locale detected from cookie/browser ### Locale Links ```vue ``` ### Programmatic Navigation ```vue ``` ## Composables ### useI18n Main composable for translations: ```vue ``` ### useLocalePath Generate localized paths: ```vue ``` ### useSwitchLocalePath Generate paths for locale switching: ```vue ``` ### useRouteBaseName Get route name without locale prefix: ```vue ``` ### useBrowserLocale Detect browser locale: ```vue ``` ## Common Patterns ### Language Switcher ```vue ``` ### Dropdown Language Switcher ```vue ``` ### SEO with I18n ```vue ``` ### Per-Page Translations ```vue { "en": { "title": "About Us", "description": "Learn more about our company" }, "fr": { "title": "À propos", "description": "En savoir plus sur notre entreprise" } } ``` ### Dynamic Content Translation ```vue ``` ### Lazy Loading Translations For large translation files: ```typescript // nuxt.config.ts export default defineNuxtConfig({ i18n: { lazy: true, langDir: "locales/", locales: [ { code: "en", file: "en.json" }, { code: "fr", file: "fr.json" }, { code: "es", file: "es.json" }, ], }, }) ``` ## Number & Date Formatting ### Number Formatting Define formats in config: ```typescript // nuxt.config.ts export default defineNuxtConfig({ i18n: { numberFormats: { en: { currency: { style: "currency", currency: "USD", }, decimal: { style: "decimal", minimumFractionDigits: 2, }, }, fr: { currency: { style: "currency", currency: "EUR", }, decimal: { style: "decimal", minimumFractionDigits: 2, }, }, }, }, }) ``` Usage: ```vue ``` ### Date Formatting Define formats in config: ```typescript // nuxt.config.ts export default defineNuxtConfig({ i18n: { datetimeFormats: { en: { short: { year: "numeric", month: "short", day: "numeric", }, long: { year: "numeric", month: "long", day: "numeric", weekday: "long", }, }, fr: { short: { year: "numeric", month: "short", day: "numeric", }, long: { year: "numeric", month: "long", day: "numeric", weekday: "long", }, }, }, }, }) ``` Usage: ```vue ``` ## Pluralization **Translation file:** ```json { "items": "no items | one item | {count} items", "cart": "You have {n} item in your cart | You have {n} items in your cart" } ``` **Usage:** ```vue ``` ## TypeScript Support ### Typed Translations ```typescript // types/i18n.ts export interface LocaleMessages { welcome: string hello: (params: { name: string }) => string nav: { home: string about: string contact: string } } ``` Usage: ```vue ``` ## API Routes with I18n ```typescript // server/api/products.get.ts export default defineEventHandler(async (event) => { const locale = getCookie(event, "i18n_redirected") || "en" const products = await db.products.findMany({ include: { translations: { where: { locale }, }, }, }) return products.map((product) => ({ ...product, name: product.translations[0]?.name || product.name, description: product.translations[0]?.description || product.description, })) }) ``` ## Best Practices 1. **Use prefix_except_default strategy** - Better UX for default locale users 2. **Enable browser detection** - Auto-redirect to user's preferred language 3. **Provide language switcher** - Always visible on every page 4. **Use lazy loading for large apps** - Load translations on demand 5. **Organize translations by feature** - Use nested keys (`nav.home`, `products.title`) 6. **Include locale in SEO** - Use `hreflang` links and `og:locale` 7. **Handle missing translations** - Provide fallback locale 8. **Use placeholders consistently** - `{name}` for simple, `{n}` for pluralization 9. **Test all locales** - Verify layout with longer translations (German, French) 10. **Keep keys consistent** - Same structure across all locale files ## Troubleshooting ### Translations Not Loading Check: 1. `@nuxtjs/i18n` in `modules` array 2. Locale files in correct `langDir` path 3. File names match `file` property in config 4. JSON is valid (no trailing commas) ### Routes Not Localized 1. Verify `strategy` is set correctly 2. Check `defaultLocale` matches one of your locales 3. Ensure you're using `localePath()` for links ### Browser Detection Not Working ```typescript // nuxt.config.ts export default defineNuxtConfig({ i18n: { detectBrowserLanguage: { useCookie: true, cookieKey: "i18n_redirected", redirectOn: "root", alwaysRedirect: true, fallbackLocale: "en", }, }, }) ``` ### Missing Translations Enable warnings in development: ```typescript // nuxt.config.ts export default defineNuxtConfig({ i18n: { compilation: { strictMessage: false, }, vueI18n: "./i18n.config.ts", }, }) ``` ```typescript // i18n.config.ts export default { legacy: false, locale: "en", missingWarn: true, fallbackWarn: true, } ``` ## v10 Changes from v9 ### Key Updates 1. **Vue I18n v11** - Upgraded from v10 with JIT compilation as default 2. **Improved Nuxt 4 Support** - Better compatibility with Nuxt 4 3. **Custom Routes** - Use `definePageMeta` for per-page locale configuration 4. **Server-Side Redirects** - Improved server-side redirection behavior 5. **Strict SEO** - Experimental strict SEO head management 6. **Fixed Behaviors** - `strategy` and `redirectOn` combinations now work as expected ### Migration Notes - `$tc()` API integrated into `$t()` (from Vue I18n v10→v11 upgrade) - JIT compilation now default (no need for `jit` option) - New directory structure: i18n files resolved from `/i18n` (configurable with `restructureDir`) - Context functions require `$` prefix: use `$localePath()` not `localePath()` in templates ## Official Resources - **Documentation:** https://i18n.nuxtjs.org - **Migration Guide:** https://i18n.nuxtjs.org/docs/guide/migrating - **API Reference:** https://i18n.nuxtjs.org/api - **Vue I18n Docs:** https://vue-i18n.intlify.dev - **Examples:** https://i18n.nuxtjs.org/examples - **GitHub:** https://github.com/nuxt-modules/i18n --- **Note:** This reference covers Nuxt I18n v10 (latest as of 2025-11) with Vue I18n v11. For v9 projects, consult the migration guide.