ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

vue-i18n 翻译文件懒加载实战:基于 Webpack 动态 import 的按需加载方案

vue-i18n 翻译文件懒加载实战:基于 Webpack 动态 import 的按需加载方案 前端国际化【免费下载链接】vue-i18n:globe_with_meridians: Internationalization plugin for Vue.js项目地址https://gitcode.com/gh_mirrors/vu/vue-i18n点击查看免费下载导读本文基于 vue-i18n 官方指南中的《Lazy loading translations》章节完整讲解如何在 Vue.js vue-i18n 项目中实现翻译文件locale messages的懒加载。核心思路是把每种语言的翻译文件拆分为独立模块借助 Webpack 的动态import()实现按需异步加载并通过i18n.setLocaleMessage()在运行时注入消息、配合 vue-router 的导航守卫完成语言切换。读完本文你将掌握一套可直接落地、可复制到实际工程的翻译懒加载方案并理解其背后的响应式更新原理。为什么需要懒加载翻译文件在大型 Vue 应用中翻译文件往往不止一种语言。如果把所有语言的翻译文件都在应用初始化时一次性打包进主 bundle会带来两个直接问题首屏体积膨胀用户只使用一种语言却要下载全部语言的翻译内容加载无谓资源与一次加载全部相比按需加载显然更符合现代前端的性能优化理念。正如官方指南开篇所说一次性加载所有翻译文件是多余且不必要的Loading all of your translation files at once is overkill and unnecessary。而借助 Webpack懒加载lazy loading或异步加载翻译文件是一件非常简单的事情。这一思路与 Webpack 官方的代码分割code splitting能力一脉相承动态import()会让 Webpack 把被导入的模块单独拆成一个 chunk浏览器在真正需要时才发起请求加载它。项目目录结构与前置约定假设我们的项目目录结构如下наш-проект-отлично |-dist |-src |--routes |--store |--setup |---i18n-setup.js |--lang |---en.js |---it.js原文档使用俄语项目名示例实际工程中可替换为任意项目名如our-cool-project。其中lang目录存放所有语言的翻译文件例如en.js、it.js每种语言一个文件setup目录集中放置各类初始化文件比如 i18n 初始化、全局组件注册、插件初始化等本文的主角i18n-setup.js就位于这里routes/store路由与状态管理相关目录与本文方案配合使用。各语言的翻译文件是一个普通的 ES 模块通过export default导出翻译对象// src/lang/en.js export default { message: { hello: hello world } }核心实现i18n-setup.js 详解懒加载方案的完整实现集中在src/setup/i18n-setup.js中。下面逐段拆解官方指南给出的核心代码。第一步创建 VueI18n 实例并预加载默认语言// i18n-setup.js import Vue from vue import VueI18n from vue-i18n import messages from /lang/en import axios from axios Vue.use(VueI18n) export const i18n new VueI18n({ locale: en, // установка локализации设置语言 fallbackLocale: en, messages // установка сообщений локализации设置翻译消息 }) const loadedLanguages [en] // список локализаций, которые пред-загружены预加载的语言列表关键点说明locale: en指定默认语言fallbackLocale: en指定回退语言。当某个 key 在当前语言中缺失时vue-i18n 会按回退链查找从 src/index.js 的构造器实现可以看到若未显式传入locale与fallbackLocale的默认值都是en-USmessages这里只传入英文翻译作为预加载的默认语言loadedLanguages数组记录已经加载过的语言列表初始包含预加载的en后续每加载一种新语言就 push 进去避免重复请求。第二步setI18nLanguage —— 同步切换语言环境function setI18nLanguage(lang) { i18n.locale lang axios.defaults.headers.common[Accept-Language] lang document.querySelector(html).setAttribute(lang, lang) return lang }这个函数负责在语言切换时同步更新三处状态i18n.locale lang切换 vue-i18n 实例的当前语言驱动所有$t调用重新求值axios.defaults.headers.common[Accept-Language] lang同步更新 axios 的全局请求头保证后续 API 请求携带正确的语言偏好document.querySelector(html).setAttribute(lang, lang)更新html标签的lang属性这对无障碍a11y和 SEO 都很重要。在 src/index.js 中可以看到locale的 setter 实现set locale (locale: Locale): void { this._vm.$set(this._vm, locale, locale) }也就是说切换locale本质上是借助 Vue 的$set修改实例内部_vm上的响应式数据从而触发依赖它的组件视图更新。第三步loadLanguageAsync —— 按需异步加载翻译export function loadLanguageAsync(lang) { // Если локализация та же如果目标语言就是当前语言 if (i18n.locale lang) { return Promise.resolve(setI18nLanguage(lang)) } // Если локализация уже была загружена如果该语言已加载过 if (loadedLanguages.includes(lang)) { return Promise.resolve(setI18nLanguage(lang)) } // Если локализация ещё не была загружена如果该语言尚未加载 return import( /* webpackChunkName: lang-[request] */ /i18n/messages/${lang}.js ).then(messages { i18n.setLocaleMessage(lang, messages.default) loadedLanguages.push(lang) return setI18nLanguage(lang) }) }这个函数是整套方案的调度中枢包含三个分支目标语言 当前语言无需任何加载直接返回已解析的 Promise同时会再次调用setI18nLanguage保证状态一致目标语言已加载过不重新请求直接切换i18n.locale目标语言未加载过执行动态import()拉取该语言的翻译 chunk成功后调用i18n.setLocaleMessage(lang, messages.default)注入翻译消息记录到loadedLanguages最后切换语言。这里有两个值得注意的细节/* webpackChunkName: lang-[request] */魔法注释它告诉 Webpack 为每个按语言名动态导入的模块生成带lang-前缀的 chunk 名称例如lang-en.js、lang-it.js方便在构建产物中识别messages.default翻译文件通过export default导出因此在动态导入后的模块对象上翻译内容位于.default属性上。原文档示例中动态导入路径写作/i18n/messages/${lang}.js与早期 gitbook 版本中的/lang/${lang}略有差异请以你自己项目中实际的翻译文件目录为准为 Webpack 中配置的 src 别名。import()是 Webpack 提供的动态导入能力返回一个 Promise因此我们可以轻松地.then()等待加载完成再进行后续操作。setLocaleMessage 的底层实现loadLanguageAsync的第三分支依赖i18n.setLocaleMessage(lang, messages.default)完成运行时消息注入。查看 src/index.js 的实现setLocaleMessage (locale: Locale, message: LocaleMessageObject): void { if (this._warnHtmlInMessage warn || this._warnHtmlInMessage error) { this._checkLocaleMessage(locale, this._warnHtmlInMessage, message) } this._vm.$set(this._vm.messages, locale, message) }它通过this._vm.$set把新语言的消息挂到内部响应式数据messages上。结合 src/mixin.js 与 src/index.js 可以看到完整链路组件在beforeCreate阶段通过watchI18nData()订阅$data的深度变化一旦messages数据更新所有已订阅组件会在nextTick中收到$forceUpdate()强制刷新。这意味着翻译文件加载完成后页面上所有$t的结果会自动更新无需手动刷新。这一行为在 test/unit/message.test.js 中有对应测试验证先setLocaleMessage(en, ...)热替换英文消息再setLocaleMessage(ja, ...)并切换i18n.locale ja断言 DOM 文本随之更新。其它可选的同步状态setI18nLanguage中同步的三处状态i18n.locale、axios 请求头、html lang 属性只是最常见的例子。官方指南指出以及任何其它需要的地方and where ever else is needed实际项目中你还可以在这里统一处理第三方分析/埋点 SDK 的语言上报全局标题document.title的本地化日期、数字格式化组件的语言偏好同步等。把这类语言切换副作用集中收敛到setI18nLanguage一个函数中是保证工程可维护性的好习惯。与 vue-router 集成在 beforeEach 守卫中按路由切换语言loadLanguageAsync的典型使用场景是 vue-router 的beforeEach导航守卫。当路由参数中携带语言标识时在进入页面之前完成翻译加载router.beforeEach((to, from, next) { const lang to.params.lang loadLanguageAsync(lang).then(() next()) })它的工作流程是用户点击跳转到某个带:lang参数的路由例如/it/aboutbeforeEach守卫取出to.params.lang这里为it调用loadLanguageAsync(it)若未加载过先动态下载it.js的 chunk注入消息并切换语言Promise 完成后调用next()放行导航。这样用户在进入页面时看到的就已经是目标语言的界面避免了先看到默认语言、再闪变的体验问题。由于loadLanguageAsync内部对已加载语言做了缓存判断重复访问已加载过的语言只会触发纯同步的语言切换开销极低。进阶优化校验语言合法性并中断导航官方指南在文末给出了一个值得落地的优化方向检查传入的lang是否受支持若不支持则调用reject以便在beforeEach中捕获错误并阻止路由跳转。参考实现如下const supportedLanguages [en, it, ja] // 项目支持的语言白名单 export function loadLanguageAsync(lang) { return new Promise((resolve, reject) { // 不受支持的语言直接拒绝 if (!supportedLanguages.includes(lang)) { reject(new Error(Unsupported language: ${lang})) return } // 与当前语言相同 if (i18n.locale lang) { return resolve(setI18nLanguage(lang)) } // 已加载过 if (loadedLanguages.includes(lang)) { return resolve(setI18nLanguage(lang)) } // 尚未加载动态导入 import(/* webpackChunkName: lang-[request] */ /i18n/messages/${lang}.js) .then(messages { i18n.setLocaleMessage(lang, messages.default) loadedLanguages.push(lang) return resolve(setI18nLanguage(lang)) }) .catch(reject) // 网络失败、模块不存在等情况同样走 reject }) }配合路由守卫router.beforeEach((to, from, next) { const lang to.params.lang loadLanguageAsync(lang) .then(() next()) .catch(err { // 处理错误例如重定向到默认语言或 404 页面 next(/) }) })这样未知语言或加载失败都会中断当前导航而不是把用户带到一个没有翻译的页面。supportedLanguages白名单也可以直接从i18n.availableLocales参见 src/index.js 的 getter它返回已注册语言排序后的数组派生但要注意它只反映已注入的消息对尚未懒加载的语言需用独立白名单维护。懒加载 vs 一次性加载什么时候用哪种方案适用场景优点代价一次性全量加载messages直接传入所有语言语言数量少23 种、文件体积小实现最简单无异步时序问题首屏 bundle 携带全部语言内容懒加载本文方案语言数量多、翻译文件大、按路由区分语言每种语言独立 chunk按需下载配合守卫可在进入路由前完成切换需要管理loadedLanguages缓存与加载失败分支两种方式可以混合使用把用户最可能使用的默认语言通常是英文在初始化时预加载其余语言全部懒加载这正是本文loadedLanguages [en]的设计意图。总结本文从官方指南出发完整还原了 vue-i18n 翻译懒加载方案的工程实现目录约定翻译文件按语言拆成独立模块初始化脚本集中放在setup目录核心三要素loadedLanguages缓存列表 setI18nLanguage统一切换副作用 loadLanguageAsync异步调度底层原理动态import()拆包按需加载setLocaleMessage通过 Vue 响应式$set注入消息mixin 深度订阅数据变化自动刷新视图源码依据见 src/index.js、src/mixin.js、src/index.js路由集成beforeEach守卫中加载语言后放行导航并可扩展语言白名单校验与错误中断。这套方案不需要任何额外插件仅依赖 Webpack 原生能力与 vue-i18n 的运行时 API是 Vue 2 生态下本仓库对应 vue-i18n v8 版本VueI18n构造器 API 风格见 src/index.js最经典、最通用的翻译按需加载实践。官方指南中提到的 Webpack 动态导入更多细节可进一步查阅 Webpack 官方文档的 code splitting 与 dynamic imports 章节。赞分享前端国际化【免费下载链接】vue-i18n:globe_with_meridians: Internationalization plugin for Vue.js项目地址https://gitcode.com/gh_mirrors/vu/vue-i18n点击查看免费下载相关推荐Astryx为什么天生对AI友好人与Agent同一套工具链设计哲学Astryx为什么天生对AI友好人与Agent同一套工具链设计哲学 Astryx 是一个由 Meta 开源、为 AI 协作时代而生的 设计系统 提供 1前端国际化Mermaid.js按需加载动态导入与懒加载的实现方案Mermaid.js按需加载动态导入与懒加载的实现方案 痛点全量引入的性能瓶颈 在现代Web开发中前端应用的性能优化至关重要。Mermaid.js作为一个图表库前端数据可视化Vue Storefront 懒加载实现图片与组件的按需加载Vue Storefront 懒加载实现图片与组件的按需加载 你是否经常遇到电商网站图片加载缓慢的问题或者页面包含大量组件导致初始加载时间过长Vue St上一篇WezTerm WSL 域WslDomain配置完全指南让本地 WSL 发行版与多路复用域深度集成下一篇MAS Windows 激活与 Office 激活免费指南3 分钟跑通一键命令创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表