Nuxt i18n
指南

自定义路由路径

为特定语言环境自定义路径名称。

在某些情况下,您可能希望除了添加语言代码作为前缀之外,还能翻译 URL。有两种配置自定义路径的方法,一种是通过模块配置,另一种是通过每个页面组件中进行配置。

使用 definePageMeta() 设置的自定义路径会在所有 customRoutes 模式下生效,该模式会配置要使用的额外来源:

如果一个路由从多个来源获取了自定义路径,则 definePageMeta() 的值优先,并且会在构建期间记录警告。这样可以逐步完成迁移:您可以一次将一个路由的自定义路径从 pages 选项(或已弃用的宏)迁移到页面组件中,而无需切换模式。

当使用 'no_prefix'策略 时,除非结合使用 differentDomains,否则不支持自定义路径。

模块配置

确保将 customRoutes 选项设置为 'config',并在 pages 选项中添加您的自定义路径:

nuxt.config.ts
export default defineNuxtConfig({
  i18n: {
    customRoutes: 'config', // 从 `pages` 选项启用自定义路由
    pages: {
      about: {
        en: '/about-us', // -> 在 /about-us 可访问(默认语言无前缀)
        fr: '/a-propos', // -> 在 /fr/a-propos 可访问
        es: '/sobre'     // -> 在 /es/sobre 可访问
      }
    }
  }
})

注意,pages 对象中的每个键应对应要本地化的路由名称

自定义的路由路径必须以 / 开头,且不能包含语言前缀

您现在可以使用 localePath() 函数或 <NuxtLinkLocale> 组件,但请确保使用命名路由。例如,路由 '/services/advanced' 应该写为 'services-advanced'

<script setup>
const { t } = useI18n()
</script>

<template>
  <NuxtLinkLocale to="about"> {{ t('about') }} </NuxtLinkLocale>
  <NuxtLinkLocale to="services-advanced"> {{ t('advanced') }} </NuxtLinkLocale>
</template>

或者:

<script setup>
const { t } = useI18n()
const localePath = useLocalePath()
</script>

<template>
  <NuxtLink :to="localePath('about')"> {{ t('about') }} </NuxtLink>
  <NuxtLink :to="localePath('services-advanced')"> {{ t('advanced') }} </NuxtLink>
</template>
目前不支持传递路径给 localePath()

示例 1:基本的 URL 本地化

假设您的 pages 目录结构如下:

目录结构
-| pages/
---| parent/
-----| child.vue
---| parent.vue
嵌套路由中的子路由依赖于存在同名文件夹的页面组件来渲染子路由。
详情请见 嵌套路由

您需要这样设置 pages 属性:

nuxt.config.ts
export default defineNuxtConfig({
  i18n: {
    customRoutes: 'config',
    pages: {
      parent: {
        en: '/parent',
        ca: '/pare'
      },
      'parent-child': {
        en: '/parent/child',
        ca: '/pare/fill'
      }
    }
  }
})
所有 URL 必须以 / 开头。

示例 2:本地化 URL 的部分路径

假设您的 pages 目录结构如下:

目录结构
-| pages/
---| about.vue
---| services/
-----| coaching.vue
-----| development/
-------| app.vue
-------| website.vue
-----| development.vue
---| services.vue

您需要这样设置 pages 属性:

nuxt.config.ts
export default defineNuxtConfig({
  i18n: {
    customRoutes: 'config',
    pages: {
      about: {
        fr: '/a-propos'
      },
      services: {
        fr: '/offres'
      },
      'services-development': {
        fr: '/offres/developement'
      },
      'services-development-app': {
        fr: '/offres/developement/app'
      },
      'services-development-website': {
        fr: '/offres/developement/site-web'
      },
      'services-coaching': {
        fr: '/offres/formation'
      }
    }
  }
})

如果某个语言环境缺少自定义路径,则使用设置的 defaultLocale 自定义路径(如果有设置)。

示例 3:动态路由

假设您有如下动态路由:

目录结构
-| pages/
---| blog/
-----| [date]/
-------| [slug].vue

您应在配置中这样配置这些页面:

nuxt.config.ts
export default defineNuxtConfig({
  i18n: {
    customRoutes: 'config',
    pages: {
      'blog-date-slug': {
        // 参数需要像 Nuxt 动态路由一样写回这里
        // https://nuxt.com/docs/guide/directory-structure/pages#dynamic-routes
        ja: '/blog/tech/[date]/[slug]'
        // ...
      }
    }
  }
})

definePageMeta

您可以在 definePageMeta() 中使用 i18n 属性为每个页面组件设置自定义路径,这适用于所有 customRoutes 模式,并且优先级高于其他方法。

您可以在 nuxt.config.ts 中设置 customRoutes: 'meta',使其成为自定义路径的唯一来源:

nuxt.config.ts
export default defineNuxtConfig({
  i18n: {
    customRoutes: 'meta'
  }
})

然后每个页面可以这样定义自己的本地化路径:

pages/about.vue
<script setup>
definePageMeta({
  i18n: {
    paths: {
      en: '/about-us', // -> 在 /about-us 可访问(默认语言无前缀)
      fr: '/a-propos', // -> 在 /fr/a-propos 可访问
      es: '/sobre'     // -> 在 /es/sobre 可访问
    }
  }
})
</script>

要配置动态路由的自定义路径,您需要在路径中使用双中括号,类似于 Nuxt 动态路由 的用法:

pages/articles/[name].vue
<script setup>
definePageMeta({
  i18n: {
    paths: {
      en: '/articles/[name]',
      es: '/artículo/[name]'
    }
  }
})
</script>
i18n 属性会在构建时被使用并从路由元数据中移除,运行时只有布尔值形式(i18n: false,请参阅忽略本地化路由)可用。

Hooks 和模块

路由元数据中的 i18n 属性是构建时自定义路径的规范来源,definePageMeta() 和其他来源会在路由本地化之前被规范化到其中。这意味着项目和模块可以在它们添加或修改路由的 pages:extend 钩子中设置自定义路径:

nuxt.config.ts
export default defineNuxtConfig({
  hooks: {
    'pages:extend'(pages) {
      pages.push({
        name: 'soup',
        path: '/soup',
        file: '~/pages/soup.vue',
        meta: {
          i18n: {
            paths: { fr: '/soupe' } // -> 可通过 /soup 和 /fr/soupe 访问
          }
        }
      })
    }
  }
})

除了 paths 之外,元数据值还接受 locales,用于限制该路由进行本地化时使用的语言环境,而 i18n: false 则会完全禁用该路由的本地化。

使用 Nuxt 默认的 experimental.scanPageMeta: 'after-resolve' 时,路由会在 pages:resolved 钩子中进行本地化,因此在任何 pages:extend 钩子中添加的路径都会被处理。使用 scanPageMeta: true 时,本地化会在 pages:extend 本身中运行,因此只有更早注册的钩子(例如由列在 @nuxtjs/i18n 之前的模块注册的钩子)才会被处理。

defineI18nRoute

该方法已废弃,推荐使用 definePageMeta(),将在 v11 版本中移除。

您可以使用 defineI18nRoute() 编译宏为每个页面组件设置自定义路径。

pages/about.vue
<script setup>
defineI18nRoute({
  paths: {
    en: '/about-us', // -> 在 /about-us 可访问(默认语言无前缀)
    fr: '/a-propos', // -> 在 /fr/a-propos 可访问
    es: '/sobre'     // -> 在 /es/sobre 可访问
  }
})
</script>

要为动态路由配置自定义路径,也需在路径中使用双中括号,类似于 Nuxt 动态路由 的写法:

pages/articles/[name].vue
<script setup>
defineI18nRoute({
  paths: {
    en: '/articles/[name]',
    es: '/artículo/[name]'
  }
})
</script>
defineI18nRoute() 编译宏会在构建时被进行 tree-shaking 优化,不会包含在分发文件中。

动态路由参数

处理动态路由参数需要更多工作,因为您需要向 Nuxt i18n 模块 提供参数翻译。可使用组合式函数 useSetI18nParams 来设置路由参数的翻译,这既用于设置 SEO 标签,也用于更改 <SwitchLocalePathLink> 渲染的路由。

switchLocalePath 会返回使用 setI18nParams 翻译参数的本地化路由,这可能导致之前使用 switchLocalePath 渲染的链接出现 hydration 问题。
请改用 <SwitchLocalePathLink> 组件,该组件会在发送渲染响应之前更新路由。

示例(将 slug 替换为对应路由参数):

<script setup>
// 从 API 拉取产品数据...(红色杯子)

const setI18nParams = useSetI18nParams()
setI18nParams({
  en: { slug: data.slugs.en }, // slug: 'red-mug'
  nl: { slug: data.slugs.nl }  // slug: 'rode-mok'
})

const switchLocalePath = useSwitchLocalePath()
switchLocalePath('en') // /products/red-mug
switchLocalePath('nl') // /nl/products/rode-mok
</script>

<template>
  <!-- pages/products/[slug].vue -->
</template>

对于名为 [...pathMatch].vue 的特殊捕获所有路由,对象的键名需使用 pathMatch。例如:

<script>
const setI18nParams = useSetI18nParams()
setI18nParams({
  en: { pathMatch: ['not-found-my-post'] },
  fr: { pathMatch: ['not-found-mon-article'] }
})
</script>

<template>
  <!-- pages/[...pathMatch].vue -->
</template>

请注意,捕获所有路由定义为数组。此处仅包含一个元素,但如果您想使用子路径,比如 '/not-found/post',应定义多个元素,如 ['not-found', 'post']

Nuxt i18n 模块 不会帮您重置参数翻译,这意味着如果不同路由使用相同参数,在路由切换时可能出现参数冲突。请确保在此类情况下始终设置参数翻译。 ::񎟀

definePageMeta({ name: '...' }) 注意事项

默认情况下,Nuxt 会在构建时覆盖生成的路由值,这会导致自定义命名路由(通过 definePageMeta() 设置 name)在解析本地化路径时失效。Nuxt v3.10 引入了实验性功能 scanPageMeta,需要启用此功能才能使 Nuxt I18n 的自定义命名路由正常工作。您可以按如下方式启用此实验功能:
nuxt.config.ts
export default defineNuxtConfig({
  experimental: {
    scanPageMeta: true
  }
})
Copyright © 2026