diff --git a/docs/content/2.guide/13.extend-messages.md b/docs/content/2.guide/13.extend-messages.md index 31b963c7d..3f436d209 100644 --- a/docs/content/2.guide/13.extend-messages.md +++ b/docs/content/2.guide/13.extend-messages.md @@ -1,18 +1,22 @@ # Extending messages hook -Nuxt hook to extend app's messages. +Nuxt hooks to extend i18n messages in your project. --- -If you're a **module author** and want that module to provide extra messages for your project, you can merge them into the normally loaded messages by using the `i18n:extend-messages` hook. +For **module authors** that want to provide messages with their modules, there are now two options to add or merge them into the normally loaded messages. -To do this, in your module's setup file listen to the Nuxt hook and push your messages. `@nuxtjs/i18n` will do the rest. +This is particularly useful if your module uses translated content and you want to offer nice default translations. -This is particularly useful if your module use translated content and you want to offer to users nice default translations. +1. [The `i18n:extend-messages` hook](#i18nextend-messages) +2. [The `i18n:registerModule` hook](#i18nregistermodule) + +### `i18n:extend-messages` +In your module's setup file listen to the Nuxt `i18n:extend-messages` hook and push your messages. `@nuxtjs/i18n` will do the rest. Example: -```ts{}[my-module-exemple/module1.ts] +```ts{}[my-module-example/module1.ts] import { defineNuxtModule } from '@nuxt/kit' export default defineNuxtModule({ @@ -20,12 +24,12 @@ export default defineNuxtModule({ nuxt.hook('i18n:extend-messages', async (additionalMessages, localeCodes) => { additionalMessages.push({ en: { - 'my-module-exemple': { + 'my-module-example': { hello: 'Hello from external module' } }, fr: { - 'my-module-exemple': { + 'my-module-example': { hello: 'Bonjour depuis le module externe' } } @@ -36,29 +40,77 @@ export default defineNuxtModule({ ``` -Now the project has access to new messages and can use them through `$t('my-module-exemple.hello')`. +### `i18n:registerModule` +In your module's setup file listen to the Nuxt `i18n:registerModule` hook and register your i18n configuration, this is similar to how [lazy-load translations](./lazy-load-translations) are configured. -::alert{type="info"} +Translations added this way will be loaded after those added in your project, and before extended layers. + +Example: +::code-group + ::code-block{label="module.ts" active} + ```ts{}[my-module-example/module.ts] + import { createResolver, defineNuxtModule } from '@nuxt/kit' + + export default defineNuxtModule({ + async setup(options, nuxt) { + const { resolve } = createResolver(import.meta.url) + nuxt.hook('i18n:registerModule', register => { + register({ + // langDir path needs to be resolved + langDir: resolve('./lang'), + locales: [ + { + code: 'en', + file: 'en.json', + }, + { + code: 'fr', + file: 'fr.json', + }, + ] + }) + }) + } + }) + ``` + :: + ::code-block{label="en.json"} + ```json + { + "my-module-example": { + "hello": "Hello from external module" + } + } + ``` + :: + ::code-block{label="fr.json"} + ```json + { + "my-module-example": { + "hello": "Bonjour depuis le module externe" + } + } + ``` + :: +:: + +Now the project has access to new messages and can use them through `$t('my-module-example.hello')`. -The custom module that is use `i18n:extend-messages` hook should be inserted before nuxt i18n module. +::alert{type="info"} +These hooks will only work for modules registered before the `@nuxtjs/i18n` module. ```ts {}[nuxt.config.ts] -import CustomModule from './custom' // import your custom module +import ExampleModule from './my-module-example/module.ts' // import your custom module export default defineNuxtConfig({ modules: [ - CustomModule, + ExampleModule, '@nuxtjs/i18n', ], }) ``` - :: ::alert - -Because module's messages are merged with the project's ones, it's safer to prefix them. - -Main project messages **will always override** the module's ones. - +Because module's messages are merged with the project's ones, it's safer to prefix them. Main project messages **will always override** the module's ones. :: diff --git a/docs/content/4.API/5.nuxt.md b/docs/content/4.API/5.nuxt.md index 44556d19c..4b79181c5 100644 --- a/docs/content/4.API/5.nuxt.md +++ b/docs/content/4.API/5.nuxt.md @@ -73,4 +73,38 @@ export default defineNuxtModule({ } ``` -See also [Extending messages hook](/guide/extend-messages) +See also [Extending messages hook](/guide/extend-messages#i18nextend-messages) + +### `i18n:registerModule` Hook + +- **Arguments**: + - registerModule (type: `({ langDir: string, locales: LocaleObject[] }) => void`) + + +```ts{}[my-module-example/module.ts] +import { createResolver, defineNuxtModule } from '@nuxt/kit' + +export default defineNuxtModule({ + async setup(options, nuxt) { + const { resolve } = createResolver(import.meta.url) + nuxt.hook('i18n:registerModule', register => { + register({ + // langDir path needs to be resolved + langDir: resolve('./lang'), + locales: [ + { + code: 'en', + file: 'en.json', + }, + { + code: 'fr', + file: 'fr.json', + }, + ] + }) + }) + } +}) +``` + +See also [Extending messages hook](/guide/extend-messages#i18nregistermodule) diff --git a/playground/layer-module/index.ts b/playground/layer-module/index.ts new file mode 100644 index 000000000..ba83b9a32 --- /dev/null +++ b/playground/layer-module/index.ts @@ -0,0 +1,32 @@ +import { createResolver, defineNuxtModule } from '@nuxt/kit' + +export default defineNuxtModule({ + async setup(options, nuxt) { + const { resolve } = createResolver(import.meta.url) + nuxt.hook('i18n:registerModule', register => { + register({ + langDir: resolve('./locales'), + locales: [ + { + code: 'en', + iso: 'en-US', + file: 'en.json', + name: 'English' + }, + { + code: 'fr', + iso: 'fr-FR', + file: 'fr.json', + name: 'Francais' + }, + { + code: 'nl', + iso: 'nl-NL', + file: 'nl.json', + name: 'Nederlands' + } + ] + }) + }) + } +}) diff --git a/playground/layer-module/locales/en.json b/playground/layer-module/locales/en.json new file mode 100644 index 000000000..212faa58b --- /dev/null +++ b/playground/layer-module/locales/en.json @@ -0,0 +1,3 @@ +{ + "moduleLayerText": "This is a merged module layer locale key" +} \ No newline at end of file diff --git a/playground/layer-module/locales/fr.json b/playground/layer-module/locales/fr.json new file mode 100644 index 000000000..bc1f68593 --- /dev/null +++ b/playground/layer-module/locales/fr.json @@ -0,0 +1,3 @@ +{ + "moduleLayerText": "This is a merged module layer locale key in French" +} \ No newline at end of file diff --git a/playground/layer-module/locales/nl.json b/playground/layer-module/locales/nl.json new file mode 100644 index 000000000..f48bc663e --- /dev/null +++ b/playground/layer-module/locales/nl.json @@ -0,0 +1,3 @@ +{ + "moduleLayerText": "This is a merged module layer locale key in Dutch" +} \ No newline at end of file diff --git a/playground/layer-module/nuxt.config.ts b/playground/layer-module/nuxt.config.ts new file mode 100644 index 000000000..828fdbfba --- /dev/null +++ b/playground/layer-module/nuxt.config.ts @@ -0,0 +1,34 @@ +// import type { NuxtApp } from 'nuxt/dist/app/index' + +// https://nuxt.com/docs/guide/directory-structure/nuxt.config +export default defineNuxtConfig({ + modules: ['@nuxtjs/i18n'], + i18n: { + langDir: 'locales', + lazy: true, + baseUrl: 'http://localhost:3000', + locales: [ + { + code: 'en', + iso: 'en-US', + file: 'en.json', + // domain: 'localhost', + name: 'English' + }, + { + code: 'fr', + iso: 'fr-FR', + file: 'fr.json', + // domain: 'localhost', + name: 'Francais' + }, + { + code: 'nl', + iso: 'nl-NL', + file: 'nl.json', + // domain: 'localhost', + name: 'Nederlands' + } + ] + } +}) diff --git a/playground/nuxt.config.ts b/playground/nuxt.config.ts index 987a7a0ba..7465d79de 100644 --- a/playground/nuxt.config.ts +++ b/playground/nuxt.config.ts @@ -1,10 +1,19 @@ import Module1 from './module1' +import LayerModule from './layer-module' import type { NuxtApp } from 'nuxt/dist/app/index' // https://nuxt.com/docs/guide/directory-structure/nuxt.config export default defineNuxtConfig({ extends: ['layers/i18n-layer'], - modules: [Module1, '@nuxtjs/i18n', '@nuxt/devtools'], + modules: [ + (_, nuxt) => { + console.log(nuxt.options._installedModules) + }, + Module1, + LayerModule, + '@nuxtjs/i18n', + '@nuxt/devtools' + ], vite: { build: { minify: false @@ -19,7 +28,7 @@ export default defineNuxtConfig({ // } // } // }, - + debug: false, i18n: { experimental: { jsTsFormatResource: true @@ -61,7 +70,7 @@ export default defineNuxtConfig({ } ], // trailingSlash: true, - debug: true, + debug: false, defaultLocale: 'en', // strategy: 'no_prefix', // strategy: 'prefix', @@ -80,14 +89,14 @@ export default defineNuxtConfig({ }, // differentDomains: true, // skipSettingLocaleOnNavigate: true, - detectBrowserLanguage: false, - // detectBrowserLanguage: { - // useCookie: true, - // // alwaysRedirect: true - // // cookieKey: 'i18n_redirected', - // // // cookieKey: 'my_custom_cookie_name', - // // redirectOn: 'root' - // }, + // detectBrowserLanguage: false, + detectBrowserLanguage: { + useCookie: true + // alwaysRedirect: true + // cookieKey: 'i18n_redirected', + // // cookieKey: 'my_custom_cookie_name', + // redirectOn: 'root' + }, // vueI18n: './vue-i18n.options.ts' vueI18n: { legacy: false, diff --git a/specs/fixtures/basic_layer/layer-module/index.ts b/specs/fixtures/basic_layer/layer-module/index.ts new file mode 100644 index 000000000..ba83b9a32 --- /dev/null +++ b/specs/fixtures/basic_layer/layer-module/index.ts @@ -0,0 +1,32 @@ +import { createResolver, defineNuxtModule } from '@nuxt/kit' + +export default defineNuxtModule({ + async setup(options, nuxt) { + const { resolve } = createResolver(import.meta.url) + nuxt.hook('i18n:registerModule', register => { + register({ + langDir: resolve('./locales'), + locales: [ + { + code: 'en', + iso: 'en-US', + file: 'en.json', + name: 'English' + }, + { + code: 'fr', + iso: 'fr-FR', + file: 'fr.json', + name: 'Francais' + }, + { + code: 'nl', + iso: 'nl-NL', + file: 'nl.json', + name: 'Nederlands' + } + ] + }) + }) + } +}) diff --git a/specs/fixtures/basic_layer/layer-module/locales/en.json b/specs/fixtures/basic_layer/layer-module/locales/en.json new file mode 100644 index 000000000..212faa58b --- /dev/null +++ b/specs/fixtures/basic_layer/layer-module/locales/en.json @@ -0,0 +1,3 @@ +{ + "moduleLayerText": "This is a merged module layer locale key" +} \ No newline at end of file diff --git a/specs/fixtures/basic_layer/layer-module/locales/fr.json b/specs/fixtures/basic_layer/layer-module/locales/fr.json new file mode 100644 index 000000000..bc1f68593 --- /dev/null +++ b/specs/fixtures/basic_layer/layer-module/locales/fr.json @@ -0,0 +1,3 @@ +{ + "moduleLayerText": "This is a merged module layer locale key in French" +} \ No newline at end of file diff --git a/specs/fixtures/basic_layer/layer-module/locales/nl.json b/specs/fixtures/basic_layer/layer-module/locales/nl.json new file mode 100644 index 000000000..f48bc663e --- /dev/null +++ b/specs/fixtures/basic_layer/layer-module/locales/nl.json @@ -0,0 +1,3 @@ +{ + "moduleLayerText": "This is a merged module layer locale key in Dutch" +} \ No newline at end of file diff --git a/specs/fixtures/basic_layer/layer-module/nuxt.config.ts b/specs/fixtures/basic_layer/layer-module/nuxt.config.ts new file mode 100644 index 000000000..828fdbfba --- /dev/null +++ b/specs/fixtures/basic_layer/layer-module/nuxt.config.ts @@ -0,0 +1,34 @@ +// import type { NuxtApp } from 'nuxt/dist/app/index' + +// https://nuxt.com/docs/guide/directory-structure/nuxt.config +export default defineNuxtConfig({ + modules: ['@nuxtjs/i18n'], + i18n: { + langDir: 'locales', + lazy: true, + baseUrl: 'http://localhost:3000', + locales: [ + { + code: 'en', + iso: 'en-US', + file: 'en.json', + // domain: 'localhost', + name: 'English' + }, + { + code: 'fr', + iso: 'fr-FR', + file: 'fr.json', + // domain: 'localhost', + name: 'Francais' + }, + { + code: 'nl', + iso: 'nl-NL', + file: 'nl.json', + // domain: 'localhost', + name: 'Nederlands' + } + ] + } +}) diff --git a/specs/fixtures/basic_layer/nuxt.config.ts b/specs/fixtures/basic_layer/nuxt.config.ts index a936b7fef..164cd54aa 100644 --- a/specs/fixtures/basic_layer/nuxt.config.ts +++ b/specs/fixtures/basic_layer/nuxt.config.ts @@ -1,9 +1,9 @@ -import pathe from 'pathe' -import { resolveFiles } from '@nuxt/kit' +import LayerModule from './layer-module' // https://nuxt.com/docs/guide/directory-structure/nuxt.config export default defineNuxtConfig({ // extends: ['./layer'], modules: [ + LayerModule, '@nuxtjs/i18n' // async (_, nuxt) => { // const layers = nuxt.options._layers diff --git a/specs/fixtures/basic_layer/pages/index.vue b/specs/fixtures/basic_layer/pages/index.vue index 0bbe882f0..8e9ffd509 100644 --- a/specs/fixtures/basic_layer/pages/index.vue +++ b/specs/fixtures/basic_layer/pages/index.vue @@ -70,5 +70,8 @@ function onClick() {
{{ $t('moduleLayerText') }}
+