Nuxt 3 中动态从 API 加载 i18n 多语言配置的完整实践方案

胖杰大大_5317

胖杰大大_5317

2026-05-11

274人浏览

原创

Nuxt 3 中动态从 API 加载 i18n 多语言配置的完整实践方案

本文详解如何在 Nuxt 3 中绕过 defineNuxtConfig 的同步限制,通过插件 + setLocaleMessage 动态加载并注入远程 locales 和翻译资源,兼容路由国际化、语言切换与 SSR/SSG 场景。

本文详解如何在 nuxt 3 中绕过 `definenuxtconfig` 的同步限制,通过插件 + `setlocalemessage` 动态加载并注入远程 locales 和翻译资源,兼容路由国际化、语言切换与 ssr/ssg 场景。

在 Nuxt 3 中集成 @nuxtjs/i18n 时,若需从 CMS(如 Prismic)或自定义 API 动态获取 locales 列表及对应翻译资源,直接在 nuxt.config.ts 中硬编码 locales 显然不适用——因为配置阶段无法执行异步操作。而简单地在插件中赋值 $i18n.locales = [...] 也无法触发路由系统重初始化,导致 /en/、/zh/ 等前缀路由失效。正确的解法是分两层动态注入:

  1. 预设静态 locales 结构(供路由系统识别路径),
  2. 运行时按需加载并注入翻译消息(setLocaleMessage),同时支持语言切换时热更新。

✅ 正确实现步骤

1. 预设最小化 locales(必需)

在 nuxt.config.ts 中声明所有可能的 locale code(即使内容暂空),确保 i18n 路由器能正确解析 URL 前缀:

// nuxt.config.ts
export default defineNuxtConfig({
  modules: ['@nuxtjs/i18n'],
  i18n: {
    lazy: true,
    langDir: 'locales',
    strategy: 'prefix_except_default',
    locales: [
      { code: 'en-US', name: 'English', iso: 'en-US' },
      { code: 'zh-TW', name: '繁體中文', iso: 'zh-TW' },
      { code: 'pl-PL', name: 'Polski', iso: 'pl-PL' },
      // 注意:无需 file 字段,因翻译将动态加载
    ],
    defaultLocale: 'en-US',
    detectBrowserLanguage: false, // 避免与动态逻辑冲突
  }
})

⚠️ 关键点:locales 数组必须包含所有目标语言的 code,否则 useI18n().locales 不会返回完整列表,前端下拉菜单和 路由生成均会出错。

2. 创建动态翻译加载工具函数

封装可复用的异步加载逻辑,支持按语言码请求翻译 JSON 并注入:

// utils/i18n.ts
export const fetchAndApplyTranslations = async (
  lang: string,
  setLocaleMessage: (locale: string, messages: Record<string any>) => void
) => {
  try {
    // 假设 API 返回纯 JSON 格式翻译对象,如 { "hello": "你好", "welcome": "欢迎" }
    const translations = await $fetch<record string>>(`/api/locales?lang=${lang}`)
    if (translations && Object.keys(translations).length > 0) {
      setLocaleMessage(lang, translations)
      console.log(`✅ Translations loaded for ${lang}`)
    } else {
      console.warn(`⚠️ Empty translations received for ${lang}`)
    }
  } catch (error) {
    console.error(`❌ Failed to fetch translations for ${lang}:`, error)
  }
}</record></string>

3. 初始化插件:首次访问加载当前语言

在插件中调用上述函数,确保首屏渲染即使用服务端/客户端最新翻译:

Opera’s AI Browser Operator
Opera’s AI Browser Operator

一款AI开发辅助工具,主要用于Opera推出的浏览器AI智能体助手,适合需要提升相关任务效率的用户。

下载
// plugins/i18n.client.ts (仅客户端执行,避免 SSR 时 $fetch 报错)
import { fetchAndApplyTranslations } from '~/utils/i18n'

export default defineNuxtPlugin(async (nuxtApp) => {
  const { $i18n } = nuxtApp
  // 确保 locale 已初始化(如通过 cookie / header / query)
  const currentLang = $i18n.locale.value || 'en-US'
  await fetchAndApplyTranslations(currentLang, $i18n.setLocaleMessage)
})

? 提示:若需 SSR 支持,请改用 plugins/i18n.server.ts + useAsyncData 在页面级加载,但注意 setLocaleMessage 仅在客户端生效,服务端渲染仍依赖 vueI18n 配置的初始消息。

4. 语言切换时动态加载新语言

在组件中监听语言变更,并触发对应翻译加载:

<!-- components/LanguageSwitcher.vue -->
<script setup>
import { fetchAndApplyTranslations } from '~/utils/i18n'

const { locales, locale, setLocale, setLocaleMessage } = useI18n()
const languageItems = computed(() =>
  locales.value.map((loc) => ({
    code: loc.code,
    name: loc.name,
    action: async () => {
      await setLocale(loc.code) // 触发路由跳转 & locale 更新
      await fetchAndApplyTranslations(loc.code, setLocaleMessage)
    }
  }))
</script><template><div class="switcher">
    <button v-for="item in languageItems" :key="item.code" :class="{ active: locale === item.code }">
      {{ item.name }}
    </button>
  </div>
</template>

5. 后端 API 示例(供参考)

确保你的 /api/locales 接口返回标准 JSON 格式:

// server/api/locales.get.ts
export default defineEventHandler(async (event) => {
  const lang = getQuery(event).lang as string
  const supported = ['en-US', 'zh-TW', 'pl-PL']
  if (!supported.includes(lang)) {
    throw createError({ status: 400, message: 'Unsupported locale' })
  }
  // 此处可对接 Prismic、数据库等
  return {
    hello: lang === 'zh-TW' ? '你好' : lang === 'pl-PL' ? 'Witaj' : 'Hello',
    welcome: lang === 'zh-TW' ? '欢迎' : lang === 'pl-PL' ? 'Witamy' : 'Welcome'
  }
})

✅ 最佳实践总结

  • ✅ 不要覆盖 $i18n.locales 数组:它仅用于路由匹配和 UI 展示,应静态声明;动态内容靠 setLocaleMessage 注入。
  • ✅ 区分 locales(结构)与 messages(内容):前者决定路由是否生效,后者决定文案显示。
  • ✅ 语言切换必须 setLocale + setLocaleMessage 组合调用:单独调用任一方法均不完整。
  • ✅ 禁用 detectBrowserLanguage: true:避免与你的动态逻辑竞争。
  • ✅ 启用 lazy: true:配合 langDir 可保留本地 fallback,增强健壮性。

通过该方案,你既能满足 CMS 驱动的多语言需求,又完全兼容 Nuxt 3 的 SSR、静态生成与客户端导航能力,真正实现“配置即代码,内容即服务”。

大量免费API接口:立即使用
涵盖生活服务API、金融科技API、企业工商API、等相关的API接口服务。免费API接口可安全、合规地连接上下游,为数据API应用能力赋能!

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

多语言

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
js获取数组长度的方法
js获取数组长度的方法

在js中,可以利用array对象的length属性来获取数组长度,该属性可设置或返回数组中元素的数目,只需要使用“array.length”语句即可返回表示数组对象的元素个数的数值,也就是长度值。php中文网还提供JavaScript数组的相关下载、相关课程等内容,供大家免费下载使用。

2023.06.20

4826

5

js刷新当前页面
js刷新当前页面

js刷新当前页面的方法:1、reload方法,该方法强迫浏览器刷新当前页面,语法为“location.reload([bForceGet]) ”;2、replace方法,该方法通过指定URL替换当前缓存在历史里(客户端)的项目,因此当使用replace方法之后,不能通过“前进”和“后退”来访问已经被替换的URL,语法为“location.replace(URL) ”。php中文网为大家带来了js刷新当前页面的相关知识、以及相关文章等内容

2023.07.04

1209

3

js四舍五入
js四舍五入

js四舍五入的方法:1、tofixed方法,可把 Number 四舍五入为指定小数位数的数字;2、round() 方法,可把一个数字舍入为最接近的整数。php中文网为大家带来了js四舍五入的相关知识、以及相关文章等内容

2023.07.04

4764

6

js删除节点的方法
js删除节点的方法

js删除节点的方法有:1、removeChild()方法,用于从父节点中移除指定的子节点,它需要两个参数,第一个参数是要删除的子节点,第二个参数是父节点;2、parentNode.removeChild()方法,可以直接通过父节点调用来删除子节点;3、remove()方法,可以直接删除节点,而无需指定父节点;4、innerHTML属性,用于删除节点的内容。

2023.09.01

940

4

JavaScript转义字符
JavaScript转义字符

JavaScript中的转义字符是反斜杠和引号,可以在字符串中表示特殊字符或改变字符的含义。本专题为大家提供转义字符相关的文章、下载、课程内容,供大家免费下载体验。

2023.09.04

1856

5

js生成随机数的方法
js生成随机数的方法

js生成随机数的方法有:1、使用random函数生成0-1之间的随机数;2、使用random函数和特定范围来生成随机整数;3、使用random函数和round函数生成0-99之间的随机整数;4、使用random函数和其他函数生成更复杂的随机数;5、使用random函数和其他函数生成范围内的随机小数;6、使用random函数和其他函数生成范围内的随机整数或小数。

2023.09.04

3425

4

如何启用JavaScript
如何启用JavaScript

JavaScript启用方法有内联脚本、内部脚本、外部脚本和异步加载。详细介绍:1、内联脚本是将JavaScript代码直接嵌入到HTML标签中;2、内部脚本是将JavaScript代码放置在HTML文件的`<script>`标签中;3、外部脚本是将JavaScript代码放置在一个独立的文件;4、外部脚本是将JavaScript代码放置在一个独立的文件。

2023.09.12

4453

6

Js中Symbol类详解
Js中Symbol类详解

javascript中的Symbol数据类型是一种基本数据类型,用于表示独一无二的值。Symbol的特点:1、独一无二,每个Symbol值都是唯一的,不会与其他任何值相等;2、不可变性,Symbol值一旦创建,就不能修改或者重新赋值;3、隐藏性,Symbol值不会被隐式转换为其他类型;4、无法枚举,Symbol值作为对象的属性名时,默认是不可枚举的。

2023.09.20

2920

5

java访问控制修饰符介绍
java访问控制修饰符介绍

java访问控制修饰符有四种,分别是public、protected、private、默认访问修饰符。详细介绍:1、public,public是最宽松的访问控制修饰符,被修饰的类、方法和变量可以被任何其他类访问,当一个类、方法或变量被声明为public时,它们可以在任何地方被访问,无论是同一个包中的类还是不同包中的类;2、protected修饰符等等。

2023.09.20

928

7

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Visual Studio 新手学习
Visual Studio 新手学习

共0课时 | 0人学习

可灵 VIDEO 3.0官方使用手册
可灵 VIDEO 3.0官方使用手册

共0课时 | 0人学习

Codex官方文档
Codex官方文档

共0课时 | 0人学习