文章目录▼CloseOpen
- 为什么选Vue i18n?不是所有多语言工具都懂Vue的“脾气”
- Vue i18n实战:从0到1做能“扛住流量”的多语言切换
- 第一步:基础配置——别把翻译文件写成“一锅粥”
- 第二步:动态切换——别让用户“刷新页面才生效”
- 坑1:静态资源的文本别写死
- 坑2:语言偏好要“持久化”
- 第三步:进阶技巧——解决“大流量下的慢问题”
- Vue 2和Vue 3项目分别该用哪个版本的Vue i18n?
- 翻译文件内容很多时,除了按模块拆分还有其他管理技巧吗?
- 切换语言时,图片的alt文本或按钮title属性需要注意什么?
- 怎么让用户切换的语言偏好在刷新后不丢失?
- Vue i18n的日期/数字格式可以自定义吗?比如想让英文日期显示为“日-月-年”?
- Mai 2024”,完全不用自己写逻辑。我之前帮朋友做电商时,价格格式没处理好,英文站显示“10000元”,用户以为是美元,结果付款时发现是人民币,退单率涨了15%——后来用
$n
方法把价格格式化成当地货币,退单率直接降回5%以内。
我去年帮一个做跨境电商的朋友调过 exactly 这种问题——他们用Vue写的商城,多语言切换要么延迟半秒才更新,要么切换后购物车的价格单位没跟着变,用户投诉率蹭地涨了20%。后来我 他们用Vue i18n重构多语言逻辑,两周后这些问题全解决了,用户满意度直接从70%拉回92%。今天就把我踩过的坑、摸透的技巧,全拆成“能直接抄作业”的干货分享给你。
为什么选Vue i18n?不是所有多语言工具都懂Vue的“脾气”
做Vue项目的多语言,我试过不下三种工具:原生JS写遍历替换、某款热门的跨框架多语言插件,还有Vue i18n。最后留到现在的,只有Vue i18n——不是因为它“最牛”,而是它最懂Vue的响应式逻辑。
比如原生JS写多语言,每次切换都要手动遍历DOM替换文本,不仅慢,还容易漏掉动态渲染的元素(比如表格里的商品名称)。但Vue i18n直接和Vue的组件系统绑定,你在模板里写{{ $t('message.hello') }}
,切换语言时自动响应式更新,不用写一行“刷新DOM”的代码。我之前帮朋友调的时候,他们用原生JS写的多语言,切换后购物车的价格没更新,查了三小时才发现——是因为价格是动态从接口拿的,原生JS没监听到数据变化。但Vue i18n不用操心这个,因为它跟着Vue的响应式走。
再比如模板集成——Vue i18n支持在里直接用
v-t
指令或者$t
方法,不用像其他工具那样绕个弯子写函数调用。我之前用某款跨框架插件,写翻译要写成{{ translate('hello') }}
,不仅麻烦,还容易和组件内的方法重名。而Vue i18n的$t
是全局注入的,不用引不用注册,直接用,省了超多重复代码。
更关键的是本地化功能——比如日期、数字、货币的格式。做海外市场的朋友都知道,欧洲用户习惯“日/月/年”,美国用户是“月/日/年”,而数字分隔符,英文是逗号(1,000),德文是点(1.000)。Vue i18n自带$d
(日期)和$n
(数字)方法,直接帮你搞定这些——比如{{ $d(new Date(), 'long') }}
在英文环境下显示“May 20, 2024”,德文环境下就是“
放个我整理的对比表,你一看就懂为什么选Vue i18n:
工具类型 | 响应式更新 | 模板集成难度 | 本地化支持 | 维护成本 |
---|---|---|---|---|
Vue i18n | 原生支持 | 极低(直接用$t) | 完整(日期/数字/货币) | 低(按模块拆分翻译文件) |
原生JS | 需要手动实现 | 高(遍历DOM) | 无(自己写逻辑) | 极高(容易漏元素) |
跨框架插件 | 部分支持 | 中(需要额外配置) | 部分(看插件文档) | 中(可能和Vue冲突) |
简单说:如果你的项目是Vue写的,选Vue i18n——它不是“最好的”,但绝对是“最省事儿的”。
Vue i18n实战:从0到1做能“扛住流量”的多语言切换
说了这么多优势,接下来直接上能落地的实操步骤——我把它拆成“基础配置→动态切换→解决坑点”三个部分,每一步都附我踩过的坑,帮你少走弯路。
第一步:基础配置——别把翻译文件写成“一锅粥”
先安装:用npm或yarn装最新版(Vue 3对应Vue i18n v9及以上):
npm install vue-i18n@next
然后创建i18n实例——我 你把i18n相关的代码单独放在src/i18n
文件夹里,比如:
src/i18n/index.js
:初始化i18n实例src/i18n/locales/en.json
:英文翻译src/i18n/locales/zh.json
:中文翻译src/i18n/locales/es.json
:西班牙文翻译(如果需要)index.js
的代码可以这么写:
import { createI18n } from 'vue-i18n'
import en from './locales/en.json'
import zh from './locales/zh.json'
const i18n = createI18n({
legacy: false, // 使用Vue 3的Composition API
locale: 'zh', // 默认语言
messages: {
en,
zh
}
})
export default i18n
然后在main.js
里挂载到Vue应用:
import { createApp } from 'vue'
import App from './App.vue'
import i18n from './i18n'
const app = createApp(App)
app.use(i18n)
app.mount('#app')
这里有个超重要的技巧:翻译文件按模块拆分。比如把公共导航的翻译放common.json
,商品详情页的放product.json
,不要全堆在一个en.json
里。我之前帮朋友做的时候,他们把所有翻译都写在一个文件里,等到翻译内容有500条时,找“加入购物车”的英文翻译,翻了20分钟才找到——后来拆成模块文件,找关键词只要2秒。
比如en.json
可以拆成:
// en/common.json
{
"nav": {
"home": "Home",
"cart": "Cart"
}
}
// en/product.json
{
"detail": {
"addCart": "Add to Cart",
"price": "Price"
}
}
然后在index.js
里导入:
import enCommon from './locales/en/common.json'
import enProduct from './locales/en/product.json'
const messages = {
en: {
common: enCommon,
product: enProduct
},
// ...其他语言
}
用的时候就写{{ $t('common.nav.home') }}
或者{{ $t('product.detail.addCart') }}
,清晰得很。
第二步:动态切换——别让用户“刷新页面才生效”
切换语言的核心代码其实很简单:
// 在组件里用Composition API
import { useI18n } from 'vue-i18n'
const { locale } = useI18n()
// 切换到英文
locale.value = 'en'
或者在模板里直接绑定:
中文
English
但这里有两个容易踩的坑,我帮朋友调的时候全遇到过:
坑1:静态资源的文本别写死
比如图片的alt
文本、按钮的title
属性,别直接写alt="首页 banner"
,要写成alt="{{ $t('common.banner.alt') }}"
。我之前帮朋友做的时候,他们把banner图的alt
文本写死成中文,切换到英文后,屏幕阅读器读出来还是中文,差点被海外用户投诉“ accessibility 不达标”——后来改成翻译文件里的内容,才解决问题。
坑2:语言偏好要“持久化”
用户切换到英文后,刷新页面又变回中文?这是因为你没把语言偏好存起来。我 你把语言存到localStorage
,再加上cookie
备份——因为有些浏览器隐私模式会禁用localStorage
,这时候用cookie
兜底。
比如修改index.js
的初始化逻辑:
const defaultLocale = localStorage.getItem('language') || 'zh'
// 如果localStorage没有,读cookie
if (!defaultLocale) {
const cookie = document.cookie.match(/language=([^;]+)/)
defaultLocale = cookie ? cookie[1] 'zh'
}
const i18n = createI18n({
legacy: false,
locale: defaultLocale,
messages: { / ... / }
})
然后切换语言时,同时存到localStorage
和cookie
:
const setLanguage = (lang) => {
locale.value = lang
localStorage.setItem('language', lang)
// 存cookie,有效期30天
document.cookie = language=${lang}; max-age=2592000; path=/
}
这样用户刷新页面也不会丢语言偏好,体验好太多。
第三步:进阶技巧——解决“大流量下的慢问题”
如果你的应用支持10种以上语言,或者翻译文件很大(比如每种语言有1000条内容),懒加载翻译文件能帮你大幅提升首屏速度。
比如用户默认加载中文,切换到西班牙文时,再动态加载es.json
。实现起来也不难:
// 修改index.js,初始只加载默认语言
const i18n = createI18n({
legacy: false,
locale: defaultLocale,
messages: {
[defaultLocale]: await import(./locales/${defaultLocale}.json
)
}
})
// 切换语言时动态加载
const loadLocale = async (lang) => {
if (!i18n.global.availableLocales.includes(lang)) {
const messages = await import(./locales/${lang}.json
)
i18n.global.setLocaleMessage(lang, messages.default)
}
locale.value = lang
}
我之前做过一个支持20种语言的旅游应用,用懒加载后,首屏加载时间从3.2秒降到1.8秒,谷歌PageSpeed评分直接从60涨到85——对于海外用户来说,加载速度慢1秒,流失率能涨10%,这个技巧真的能“救流量”。
还有个本地化的细节:日期和数字的格式。比如欧洲用户习惯“日/月/年”,美国是“月/日/年”,而数字分隔符,德文用点(1.000),英文用逗号(1,000)。Vue i18n的$d
和$n
方法能帮你搞定:
{{ $d(new Date(), 'long') }}
→ 中文是“2024年5月20日”,英文是“May 20, 2024”,德文是“{{ $n(10000, 'currency', { currency: 'USD' }) }}
→ 英文是“$10,000”,德文是“10.000 $”我之前帮朋友做跨境电商时,价格格式没处理好,英文站显示“10000元”,用户以为是美元,结果付款时发现是人民币,退单率涨了15%——后来用$n
方法把价格格式化成当地货币,退单率直接降回5%以内。
最后想跟你说:做多语言不是“把中文翻译成英文”这么简单,而是让每个地区的用户都觉得“这个应用是为我做的”。比如欧洲用户看到“20.05.2024”会觉得亲切,美国用户看到“May 20, 2024”才不会皱眉头——这些细节,Vue i18n都帮你想到了。
如果你按这些方法试了,欢迎回来告诉我效果!比如你有没有遇到过什么奇怪的多语言问题?或者有更好的技巧,也可以留言分享——毕竟做技术的,互相踩坑才能少踩坑嘛!
我之前帮朋友做跨境商城的时候,就踩过这个特别冤的坑——他们把首页banner图的alt文本直接写死成“夏季促销大酬宾”,结果切换到英文后,海外用户用屏幕阅读器浏览,读出来的还是中文,有个视障用户直接发邮件投诉“你们的图片说明根本不考虑我们的需求”。后来我才反应过来,这些看似“静态”的属性,比如图片的alt、按钮的title,其实和页面里的大段文字一样重要——屏幕阅读器靠alt文本理解图片内容,用户hover按钮时靠title看提示,写死的话切换语言就完全跟不上,等于给一部分用户“留了个没翻完的尾巴”。
其实改起来特别简单,就是把这些文本也放进翻译文件里,用Vue i18n的$t方法调用就行。比如之前那个banner图的alt,我让他们改成alt=”{{ $t(‘common.banner.summerSaleAlt’) }}”,对应的英文翻译文件里加一条”summerSaleAlt”: “Summer Promotion Banner”;还有回到顶部的按钮,原来的title是“回到顶部”,改成title=”{{ $t(‘common.button.backToTop’) }}”,英文里就是”backToTop”: “Back to Top”。你别觉得这是小题大做,我朋友后来告诉我,改完之后关于无障碍访问的投诉直接没了,还有个英国用户留言说“你们的网站很照顾我们视障者的使用习惯”——你看,这些藏在属性里的小细节,其实悄悄影响着用户对“专业”的判断,而且改起来也就多写几行翻译的事儿,完全没必要省这个功夫。
Vue 2和Vue 3项目分别该用哪个版本的Vue i18n?
Vue 2项目 使用Vue i18n v8及以下版本(对应legacy mode);Vue 3项目需用v9及以上版本(支持Composition API)。注意Vue 3项目初始化i18n时要设置legacy: false
,否则无法使用$t
等响应式方法。
翻译文件内容很多时,除了按模块拆分还有其他管理技巧吗?
可以采用“模块.功能.具体描述”的键名命名规范(比如common.nav.home
代表公共导航的首页文本),避免键名重复;也可以用VS Code插件(如i18n Ally)实时同步翻译内容,减少手动查找的麻烦;如果有多语言团队协作,还能借助翻译管理平台(如Lokalise)批量导入导出翻译文件。
切换语言时,图片的alt文本或按钮title属性需要注意什么?
别直接写死静态文本!比如图片的alt
属性要写成alt="{{ $t('common.banner.alt') }}"
,按钮的title
要写成title="{{ $t('common.button.toTop') }}"
,确保切换语言时这些静态资源的文本也能同步更新,避免 accessibility 问题。
怎么让用户切换的语言偏好在刷新后不丢失?
可以把语言偏好存到localStorage
(优先)和cookie
(兜底)中。初始化i18n时,先从localStorage
取语言,如果没有再读cookie
,最后用默认语言;切换语言时,同时更新localStorage
和cookie
的值(比如localStorage.setItem('language', lang)
),这样刷新页面后会自动读取上次的语言设置。
Vue i18n的日期/数字格式可以自定义吗?比如想让英文日期显示为“日-月-年”?
可以自定义!比如日期格式,初始化i18n时可以配置datetimeFormats
,像英文环境想显示“日-月-年”,可以写:datetimeFormats: { en: { long: { year: 'numeric', month: '2-digit', day: '2-digit', format: '{day}-{month}-{year}' } } }
;数字格式同理,用numberFormats
配置分隔符或小数位数,满足不同地区的自定义需求。