{"id":15681048,"url":"https://github.com/johannschopplich/nuxt-i18n","last_synced_at":"2025-04-30T22:22:27.003Z","repository":{"id":193432545,"uuid":"688792239","full_name":"johannschopplich/nuxt-i18n","owner":"johannschopplich","description":"💬 Minimal module for i18n with locale auto-imports \u0026 localized routing","archived":false,"fork":false,"pushed_at":"2024-10-22T18:24:30.000Z","size":3469,"stargazers_count":12,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-26T23:44:34.529Z","etag":null,"topics":["i18n","nuxt-i18n","nuxt-modules"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/johannschopplich.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-08T05:49:12.000Z","updated_at":"2024-10-22T18:24:34.000Z","dependencies_parsed_at":"2023-10-16T12:43:11.797Z","dependency_job_id":"7669a88f-72d7-447c-b54c-7097ab3d4546","html_url":"https://github.com/johannschopplich/nuxt-i18n","commit_stats":null,"previous_names":["johannschopplich/nuxt-i18n"],"tags_count":35,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johannschopplich%2Fnuxt-i18n","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johannschopplich%2Fnuxt-i18n/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johannschopplich%2Fnuxt-i18n/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/johannschopplich%2Fnuxt-i18n/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/johannschopplich","download_url":"https://codeload.github.com/johannschopplich/nuxt-i18n/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251516950,"owners_count":21601911,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["i18n","nuxt-i18n","nuxt-modules"],"created_at":"2024-10-03T16:48:27.283Z","updated_at":"2025-04-30T22:22:26.981Z","avatar_url":"https://github.com/johannschopplich.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"![Nuxt i18n module](./.github/og.jpg)\n\n# @byjohann/nuxt-i18n\n\n[Nuxt](https://nuxt.com) module for internationalization with locale auto-imports \u0026 localized routing.\n\nThis module's intention is not to provide a full-blown solution for internationalization like [@nuxtjs/i18n](https://i18n.nuxtjs.org), but offer a lean, effective and lightweight set of tools to cover your needs without the bloat of a full-blown solution.\n\n## Key Features\n\n- 🪡 Integration with [@byjohann/vue-i18n](https://github.com/johannschopplich/vue-i18n)\n- 🗜 Composable usage with [`useI18n`](#usei18n)\n- 🪢 [Auto-importable](#auto-importing--lazy-loading-translations) locale messages (JSON/YAML support)\n- 💇‍♀️ [Lazy-loading](#auto-importing--lazy-loading-translations) of translation messages\n- 🛣 [Automatic routes generation](#routing--strategies) and custom paths\n\n## Setup\n\n```bash\n# pnpm\npnpm add -D @byjohann/nuxt-i18n\n\n# npm\nnpm i -D @byjohann/nuxt-i18n\n```\n\n## Basic Usage\n\n\u003e [!TIP]\n\u003e [📖 Check out the playground](./playground/)\n\nAdd `@byjohann/nuxt-i18n` to your `nuxt.confg.ts`:\n\n```ts\nexport default defineNuxtConfig({\n  modules: ['@byjohann/nuxt-i18n']\n})\n```\n\nFor the most basic setup, add the `locales` and `defaultLocales` module options with a set of translation `messages`:\n\n```ts\nexport default defineNuxtConfig({\n  modules: ['@byjohann/nuxt-i18n'],\n\n  i18n: {\n    locales: ['en', 'de'],\n    defaultLocale: 'en',\n    messages: {\n      en: { welcome: 'Welcome' },\n      de: { welcome: 'Willkommen' }\n    }\n  }\n})\n```\n\nUse the globally available `useI18n` composable in your component's `setup` hook:\n\n```vue\n\u003cscript setup\u003e\nconst { locale, t } = useI18n()\n\u003c/script\u003e\n\n\u003ctemplate\u003e\n  \u003cdiv\u003eLanguage: {{ locale }}\u003c/div\u003e\n  \u003cp\u003e{{ t('welcome') }}\u003c/p\u003e\n\u003c/template\u003e\n```\n\n## Guide\n\n### Routing \u0026 Strategies\n\nYou can opt-in to override the Nuxt default routes with added locale prefixes to every URL by using one of the built-in routing strategies. By default, the generated routes stay untouched (`no_prefix` strategy).\n\nFor example, if your app supports two languages: German and English as the default language, and you have the following pages in your project:\n\n```\n└── pages/\n    ├── about/\n    │   └── index.vue\n    └── index.vue\n```\n\nThis would result in the following routes being generated for the `prefix_except_default` strategy:\n\n\u003cdetails\u003e\n\u003csummary\u003e🎄 Routes Tree\u003c/summary\u003e\n\n```ts\n[\n  {\n    path: '/',\n    name: 'index___en',\n    // ...\n  },\n  {\n    path: '/de/',\n    name: 'index___de',\n    // ...\n  },\n  {\n    path: '/about',\n    name: 'about___en',\n    // ...\n  },\n  {\n    path: '/de/about',\n    name: 'about___de',\n    // ...\n  }\n]\n```\n\n\u003c/details\u003e\n\n\u003e [!NOTE]\n\u003e Routes for the English version don't have a prefix because it is the default language.\n\n#### Available Strategies\n\nThere are 4 supported strategies in total that affect how the app's routes are generated.\n\n\u003ctable\u003e\u003ctr\u003e\u003ctd valign=\"top\"\u003e\n\n##### `no_prefix` (default)\n\n\u003c/td\u003e\u003ctd\u003e\u003cbr\u003e\n\nWith this strategy, routes stay as they are generated by Nuxt. No locale prefix will be added. The locale can be changed without changing the URL.\n\n\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd valign=\"top\"\u003e\n\n##### `prefix_except_default`\n\n\u003c/td\u003e\u003ctd\u003e\u003cbr\u003e\n\nUsing this strategy, all of your routes will have a locale prefix added except for the default language.\n\n\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd valign=\"top\"\u003e\n\n##### `prefix`\n\n\u003c/td\u003e\u003ctd\u003e\u003cbr\u003e\n\nWith this strategy, all routes will have a locale prefix.\n\n\u003c/td\u003e\u003c/tr\u003e\u003ctr\u003e\u003ctd valign=\"top\"\u003e\n\n##### `prefix_and_default`\n\n\u003c/td\u003e\u003ctd\u003e\u003cbr\u003e\n\nThis strategy combines both previous strategies behaviours, meaning that you will get URLs with prefixes for every language, but URLs for the default language will also have a non-prefixed version. This could lead to duplicated content. You will have to handle, which URL is preferred when navigating in your app.\n\n\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\n#### Configuration\n\nA strategy may be set using the `strategy` module option. Make sure that you have a `defaultLocale` defined in any case.\n\n```ts\nexport default defineNuxtConfig({\n  i18n: {\n    locales: ['en', 'de'],\n    defaultLocale: 'en',\n    strategy: 'prefix_except_default',\n  },\n})\n```\n\n### Custom Route Paths\n\nIn some cases, you might want to translate URLs in addition to having them prefixed with the locale code. For example, you might want to have a route like `/about` in English and `/ueber-uns` in German. You can achieve this by defining a custom path for the route in the `nuxt.config.ts` file:\n\n```ts\nexport default defineNuxtConfig({\n  i18n: {\n    locales: ['en', 'de', 'fr'],\n    defaultLocale: 'en',\n    pages: {\n      about: {\n        de: '/ueber-uns',\n        fr: '/a-propos'\n      }\n    }\n  }\n})\n```\n\n\u003e [!NOTE]\n\u003e Each key within the pages object should correspond to the relative file-based path (excluding the `.vue` file extension) of the route within your `pages` directory.\n\nCustomized route paths must start with a `/` and not include the locale prefix.\n\n### Auto-Importing \u0026 Lazy-Loading Translations\n\nFor apps that contain a lot of translated content, it is preferable not to bundle all the messages in the main bundle, but rather lazy-load only the language that the users selected. By defining a directory where translation files are located, locale messages can be dynamically imported when the app loads or when the user switches to another language.\n\nHowever, you can also benefit from the advantages of auto-import without enabling dynamic imports.\n\nHow to enable file-based translations with or without lazy-loading:\n\n- Set the `langImports` option to `true`.\n- Enable dynamic imports by setting the `lazy` option to `true`.\n- Optionally, configure the `langDir` option to a directory that contains your translation files. Defaults to `locales`.\n- Make sure the `locales` option covers possible languages.\n\n\u003e [!NOTE]\n\u003e Translation files must be called the same as their locale. Currently, JSON, JSON5 and YAML are supported.\n\nExample files structure:\n\n```\n├── locales/\n│   ├── en.json\n│   ├── es.json5\n│   ├── fr.yaml\n└── nuxt.config.js\n```\n\nConfiguration example:\n\n```ts\nexport default defineNuxtConfig({\n  i18n: {\n    locales: ['en', 'es', 'fr'],\n    defaultLocale: 'en',\n    langImports: true,\n    lazy: true\n  }\n})\n```\n\n\u003e [!TIP]\n\u003e If you prefer to import file-based translations but don't want to dynamically import them, omit the `lazy` module option, as it defaults to `false`.\n\n\u003e [!WARNING]\n\u003e The global route middleware to lazy-load translations when switching locales won't run when the `no_prefix` strategy is chosen. Use the `useLazyLocaleSwitch` composable for changing the language, it will load the corresponding translations beforehand.\n\n### Manual Translations\n\nInstead of auto-importing (with or without lazy-loading), you can manually import your translations and merge them into the global locale messages object:\n\n```ts\n// Import from JSON or an ES module\nimport en from './locales/en.json'\nimport de from './locales/de.json'\n\nexport default defineNuxtConfig({\n  i18n: {\n    locales: ['en', 'de'],\n    defaultLocale: 'en',\n    messages: {\n      en,\n      de,\n    },\n  },\n})\n```\n\nThe locale messages defined above will be passed as the `messages` option when initializing `@byjohann/vue-i18n` with `createI18n()`.\n\n## API\n\n### Module Options\n\n```ts\ninterface ModuleOptions {\n  /**\n   * List of locales supported by your app\n   *\n   * @remarks\n   * Intended to be an array of string codes, e.g. `['en', 'fr']`\n   *\n   * @default []\n   */\n  locales?: string[]\n\n  /**\n   * The app's default locale\n   *\n   * @remarks\n   * It's recommended to set this to some locale regardless of the chosen strategy, as it will be used as a fallback locale\n   *\n   * @default 'en'\n   */\n  defaultLocale?: string\n\n  /**\n   * Directory where your locale files are stored\n   *\n   * @remarks\n   * Expected to be a relative path from the project root\n   *\n   * @default 'locales'\n   */\n  langDir?: string\n\n  /**\n   * Whether to enable locale auto-importing\n   *\n   * @remarks\n   * When enabled, the module will automatically import all locale files from the `langDir` directory\n   *\n   * @default false\n   */\n  langImports?: boolean\n\n  /**\n   * Whether to lazy-load locale messages in the client\n   *\n   * @remarks\n   * If enabled, locale messages will be loaded on demand when the user navigates to a route with a different locale\n   *\n   * This has no effect if the `langImports` option is disabled\n   *\n   * Note: When `strategy` is set to `no_prefix`, use the `useLazyLocaleSwitch` composable to ensure the translation messages are loaded before switching locales\n   *\n   * @default false\n   */\n  lazy?: boolean\n\n  /**\n   * The app's default messages\n   *\n   * @remarks\n   * Can be omitted if auto-importing of locales is enabled\n   *\n   * @default {}\n   */\n  messages?: LocaleMessages\n\n  /**\n   * Routes strategy\n   *\n   * @remarks\n   * Can be set to one of the following:\n   *\n   * - `no_prefix`: routes won't have a locale prefix\n   * - `prefix_except_default`: locale prefix added for every locale except default\n   * - `prefix`: locale prefix added for every locale\n   * - `prefix_and_default`: locale prefix added for every locale and default\n   *\n   * @default 'no_prefix'\n   */\n  strategy?: Strategies\n\n  /**\n   * Customize the names of the paths for a specific locale\n   *\n   * @remarks\n   * In some cases, you might want to translate URLs in addition to having them prefixed with the locale code\n   *\n   * @example\n   * pages: {\n   *   about: {\n   *     en: '/about-us', // Accessible at `/en/about-us`\n   *     fr: '/a-propos', // Accessible at `/fr/a-propos`\n   *     es: '/sobre'     // Accessible at `/es/sobre`\n   *   }\n   * }\n   * @default {}\n   */\n  pages?: CustomRoutePages\n\n  /**\n   * Custom route overrides for the generated routes\n   *\n   * @example\n   * routeOverrides: {\n   *   // Use `en` catch-all page as fallback for non-existing pages\n   *   '/en/:id(.*)*': '/:id(.*)*'\n   * }\n   *\n   * @default {}\n   */\n  routeOverrides?: Record\u003cstring, string\u003e\n\n  /**\n   * Print verbose debug information to the console during development mode\n   *\n   * @remarks\n   * For example the list of localized routes (if enabled)\n   *\n   * @default false\n   */\n  logs?: boolean\n}\n```\n\n### Composables\n\n#### `useI18n`\n\nGives access to the current i18n instance.\n\n```ts\nfunction useI18n\u003cconst Locale extends string = string\u003e(): I18nInstance\u003cLocale\u003e\n\ninterface interface I18nInstance\u003c\n  Locale extends string = string,\n  Messages extends Record\u003cstring, unknown\u003e = Record\u003cstring, unknown\u003e,\n\u003e {\n  defaultLocale: Locale\n  locale: ComputedRef\u003cLocale\u003e\n  locales: readonly Locale[]\n  messages: LocaleMessages\u003cLocale, Messages\u003e\n  t: \u003cconst T\u003e(key: T, params?: MessageParameters) =\u003e string\n  setLocale: (locale: Locale) =\u003e void\n  getLocale: () =\u003e string\n}\n```\n\n#### `useRouteLocale`\n\nReturns the current locale based on the route name. Preferred for strategies other than `no_prefix`.\n\n**Type Declarations**\n\n```ts\nfunction useRouteLocale(): string\n```\n\n#### `useLocalizedPath`\n\nReturns a translated path for a given route. Preferred when working with all routing strategies except `no_prefix`.\n\n**Type Declarations**\n\n```ts\nfunction useLocalizedPath(\n  path: string,\n  locale: string,\n): string\n```\n\n**Example**\n\n```ts\nconst to = useLocalizedPath(useRoute().fullPath, 'de')\nuseRouter().push(to)\n```\n\n#### `useLazyLocaleSwitch`\n\nEnsures to load the translation messages for the given locale before switching to it. Mostly needed for the `no_prefix` strategy.\n\n**Type Declarations**\n\n```ts\nfunction useLazyLocaleSwitch(locale: string): Promise\u003cvoid\u003e\n```\n\n**Example**\n\n```ts\nawait useLazyLocaleSwitch('en')\n```\n\n## 💻 Development\n\n1. Clone this repository\n2. Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable`\n3. Install dependencies using `pnpm install`\n4. Run `pnpm run dev:prepare`\n5. Start development server using `pnpm run dev`\n\n## Credits\n\n- [Kazuya Kawaguchi](https://github.com/kazupon) for his work on [@intlify](https://github.com/intlify)'s [vue-i18n-next](https://github.com/intlify/vue-i18n-next), the next v8 alpha of [nuxt-i18n](https://github.com/kazupon/nuxt-i18n) as well as the i18n routing library [vue-i18n-routing](https://github.com/intlify/routing)\n\n## License\n\n[MIT](./LICENSE) License © 2022-PRESENT [Johann Schopplich](https://github.com/johannschopplich)\n\n[MIT](./LICENSE) License © 2022-2023 [LeanERA GmbH](https://github.com/leanera)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjohannschopplich%2Fnuxt-i18n","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjohannschopplich%2Fnuxt-i18n","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjohannschopplich%2Fnuxt-i18n/lists"}