Allow modules to modify route localization
Environment
- Nuxt:
^3.x - @nuxtjs/i18n:
^9.x - Package manager:
pnpm - Node:
>=18 - OS: macOS
Reproduction
🧩 What I'm trying to do
I want to dynamically disable translation for some pages, such as /admin or any route matching a certain pattern, by injecting into the i18n.pages config like this:
i18n: {
customRoutes: 'config',
pages: {
'admin': false
}
}
But I want to do this dynamically from another Nuxt module, based on logic like:
- Whether route path starts with
/admin - Whether the file name includes certain keywords
- Optional user-defined exclude rule function
📌 Problem
The pages:extend hook gives access to all generated Nuxt pages, and I can detect which pages I want to exclude, then inject:
nuxt.options.i18n.pages = {
...nuxt.options.i18n.pages,
...detectedPagesToExclude
}
However, @nuxtjs/i18n appears to snapshot the config too early, likely before pages:extend runs, and generates i18n-options.mjs using an internal ctx.options, so my dynamic changes to nuxt.options.i18n.pages do not reflect in the generated options.
Describe the bug
❓Question
Is there an official or recommended way to dynamically inject/disable page translation settings (customRoutes: 'config' + pages) at runtime or module time?
More specifically:
- Can you expose a Nuxt hook like
i18n:extendPagesConfig(pages)before generatingi18n-options.mjs? - Or is there a safe way to hook into
ctx.options.pagesin a custom module? - Or should we write a wrapper module that overrides the
i18nmodule setup?
🧪 What I tried
nuxt.hook('pages:extend', pages => {
for (const page of pages) {
if (page.path.startsWith('/admin') && page.name) {
nuxt.options.i18n.pages[page.name] = false
}
}
})
But this doesn't reflect in the generated .nuxt/i18n-options.mjs file.
🙏 Feature request?
Could you consider adding a hook like:
nuxt.hook('i18n:extendPagesConfig', (pages: NuxtPage[], currentConfig: Record<string, any>) => {
// modify and return updated pages config
})
So that other modules (like i18n-exclude) can safely hook in and modify translation strategy for specific routes?
Let me know if there's already a supported way to do this.
Thanks a lot for the amazing work on @nuxtjs/i18n 🙌
Additional context
No response
Logs
However, @nuxtjs/i18n appears to snapshot the config too early, likely before pages:extend runs, and generates i18n-options.mjs using an internal ctx.options, so my dynamic changes to nuxt.options.i18n.pages do not reflect in the generated options.
This is expected behavior since the configurations provided by all layers (inline + keyed) are merged at module setup, modifying i18n options after that will have no effect. The intended use of pages:extend or pages:resolved hooks are to modify pages through its argument so modifying nuxt options there would be unexpected.
Could you consider adding a hook
Providing a build-time hook to modify the custom routing configuration is something we might consider but I feel this may complicate configuration for end-users if a module decides to overwrite their config (it would be especially opaque if they use customRoutes: 'pages').
In v10 we support an additional custom route configuration method via route meta, I think it should be possible to directly set the route meta in the pages: hooks which should allow you to achieve the same thing.
Is there an official or recommended way to dynamically inject/disable page translation settings (customRoutes: 'config' + pages) at runtime or module time?
For customRoutes: 'config' I recommend using a layer to provide configuration so that options are merged and overwritten in a predictable way. For customRoutes: 'pages' there is no straightforward way to change user provided custom routes, but in the future this will likely be removed and replaced by the already mentioned customRoutes: 'meta' introduced in v10.
@BobbieGoede
Does this mean I switch to v10, then I can use
nuxt.hook('pages:extend', (pages) => {
for (const page of pages) {
if (page.path.startsWith('/admin')) {
page.meta = page.meta || {}
page.meta.i18n = false // close i18n
}
}
})
Whether the configuration is customRoutes: 'pages' or customRoutes: 'config'