
准备工作:Angular多语言环境搭起来
先别急着写代码,环境搭不对,后面全白费。我吃过这亏,之前用 Angular 8 做项目,当时还没有内置的多语言模块,得自己装 @angular/localize
,现在 Angular 14+ 已经默认集成了,省事儿不少。不过不同版本的配置有点区别,先给你捋捋:
先看你的 Angular 版本
如果你的项目是 Angular 9 及以上,直接用官方的 @angular/localize
模块就行;要是 Angular 8 及以下,得先手动安装依赖。我整理了个表格,你对着看:
Angular 版本 | @angular/localize 支持 | 操作步骤 |
---|---|---|
8 及以下 | 需手动安装 | npm install @angular/localize save |
9-13 | 内置但需启用 | ng add @angular/localize |
14+ | 默认集成 | 无需额外操作 |
安装完依赖,接下来要改 angular.json
文件。打开这个文件,找到 projects -> 你的项目名 -> architect -> build -> options
,加一行 "localize": true
,这一步是告诉 Angular “我们要开启多语言模式啦”。然后在 options
里再加个 i18nMissingTranslation
配置,设为 warning
,这样如果有没翻译的内容,编译时会提醒你,不至于上线后才发现漏翻了。
对了,翻译文件放哪儿也很重要。 在 src
目录下建个 locale
文件夹,专门放各国语言的翻译文件,比如 messages.en.xlf
(英文)、messages.ja.xlf
(日文),这样后期维护一目了然。我之前见过有人把翻译文件散落在各个组件里,后来要改个翻译,找文件找了半小时,血的教训啊。
实战开发:从标记到动态切换全流程
环境搭好了,接下来就是正经开发了。这部分分三步走,每一步都有坑,我会把我踩过的坑提前告诉你,省得你重蹈覆辙。
第一步:给页面内容打上 i18n 标记
所有要翻译的文字,都得在模板里加上 i18n
属性,比如页面标题、按钮文字、提示信息。举个例子,你原来的模板可能是这样的:
欢迎来到我的应用
当前时间:2023年10月15日
现在要改成带 i18n
标记的版本:
欢迎来到我的应用
当前时间:{{ today | date }}
这里有个细节,i18n
后面可以加个描述,方便翻译人员理解语境。比如按钮上的“点击购买”,可以写成 ,
@@buyButton
是这个翻译的唯一标识,后面生成翻译文件时会用到。我之前做金融项目,“平仓”这个词在不同场景有不同意思,加了标识后,翻译人员就知道这里是“交易平仓”而不是“仓库平仓”,避免了歧义。
第二步:生成翻译文件并填充内容
标记打好了,就该生成翻译文件了。在终端里跑命令:ng extract-i18n output-path src/locale format xlf
。format xlf
是指定用 XLIFF 格式(一种常见的翻译文件格式),Angular 也支持 XMB 格式,但 XLIFF 更通用,翻译工具基本都支持。
跑完命令,src/locale
文件夹里会多出一个 messages.xlf
文件,打开看看,里面长这样:
点击购买
source
里是原文(中文),target
就是要填翻译的地方。接下来复制一份 messages.xlf
,改名叫 messages.en.xlf
,然后把 target
里的内容换成英文:Buy Now
。其他语言依葫芦画瓢就行。
这里有个坑要注意:翻译文件里的 id
必须和模板里的 @@标识
对应,不然翻译不生效。我之前有个页面,明明标记和翻译都写了,结果显示的还是中文,查了半天才发现是复制文件时,id
不小心改了,血的教训+1。
第三步:实现语言动态切换功能
最关键的一步来了——怎么让用户自己切换语言?Angular 有两种方案:编译时多语言和运行时多语言。
编译时多语言是给每种语言单独构建一个包,比如中文包、英文包,用户切换语言时跳转到对应包的 URL(比如 /en
、/ja
)。这种方式性能好,加载快,但缺点是切换语言要刷新页面。适合语言版本差异大、对性能要求高的项目,比如电商网站。配置方法也简单,在 angular.json
的 configurations
里加语言配置,然后用 ng build configuration=production,en
构建英文包。
如果你想不刷新页面切换语言(比如后台管理系统,用户体验要求高),就得用运行时切换。这时候要用到 @angular/localize
的 loadTranslations
函数,或者第三方库 @ngx-translate/core
。我个人更推荐 @ngx-translate
,用法简单,还支持异步加载翻译文件。
举个 @ngx-translate
的例子:先安装依赖 npm install @ngx-translate/core @ngx-translate/http-loader save
,然后在 app.module.ts
里导入模块:
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { HttpClient } from '@angular/common/http';
// 加载翻译文件
export function HttpLoaderFactory(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}
@NgModule({
imports: [
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: HttpLoaderFactory,
deps: [HttpClient]
}
})
]
})
然后在组件里注入 TranslateService
,调用 use
方法切换语言:
constructor(private translate: TranslateService) {
// 设置默认语言
translate.setDefaultLang('zh');
}
switchLanguage(lang: string) {
this.translate.use(lang); // 传入 'en' 就切换到英文,无需刷新页面
}
模板里用 translate
管道显示翻译内容:
{{ 'welcome' | translate }}
是不是超简单?不过要注意,@ngx-translate
用的是 JSON 翻译文件,所以之前的 XLF 文件要转成 JSON 格式,网上有在线转换工具,搜“xlf to json”就行。
处理特殊格式也是个大头,比如日期、货币、复数。就说复数吧,中文里“1条消息”和“5条消息”差别不大,但英文里“1 message”和“5 messages”就得变复数。这时候别自己写 if-else
判断,Angular 的 ICU 消息格式直接搞定:
{count, plural,
=0 {没有新消息}
=1 {1条新消息}
other {{{count}}条新消息}
}
count
是你定义的数量变量,这样不管数字是多少,翻译都会自动适配。我之前做社交 app,消息提示就用的这个,支持了10多种语言,从没出过格式问题。
对了,日期和货币格式化要记得注入 LOCALE_ID
。在模块里 providers 里加 { provide: LOCALE_ID, useValue: 'en-US' }
,就能让 date
管道显示英文日期格式(比如 MM/dd/yyyy
)。如果是动态切换语言,就用 TranslateService
的 onLangChange
事件,动态更新 LOCALE_ID
,这个稍微复杂点,你可以先记着,遇到了再查官方文档(https://angular.io/guide/i18n-common-locale-id nofollow),写得很详细。
你跟着这些步骤走,基本就能搞定 Angular 多语言支持了。对了,记得用 ng serve configuration=en
测试英文版本,别等上线了才发现翻译文件路径写错了。如果遇到翻译不生效的情况,先检查 i18n
标记有没有漏加,再看看翻译文件的 id
对不对,90%的问题都出在这俩地方。你要是试了这套流程,欢迎回来告诉我效果,或者有啥卡壳的地方,咱们一起琢磨琢磨~
不刷新页面切换语言啊,我推荐你试试运行时切换方案,这可比编译时那种每次切换都要刷新页面的方式友好多了。之前我做一个跨境电商后台,一开始用的编译时方案,用户切换语言就得重新加载整个页面,表单填一半切换语言,内容全没了,被吐槽了好多次。后来换成运行时方案,体验直接上了个台阶。
具体操作的话,最常用的就是第三方库@ngx-translate/core,这玩意儿社区活跃,文档也全,出了问题也好找解决办法。你先得把两个依赖装上:@ngx-translate/core和@ngx-translate/http-loader,用npm install命令就行。装完之后,得在根模块里配置一下翻译文件的加载路径,一般我会把翻译文件放在src/assets/i18n目录下,比如英文是en.json,日文是ja.json,这样路径就写成’./assets/i18n/’,后缀是’.json’。这里有个小坑,路径千万别写错,之前我把assets写成asset少个s,结果翻译文件一直加载失败,调试半天才发现是拼写问题。
配置好之后,在组件里注入TranslateService,然后调用它的use()方法就能切换语言了,比如想切英文就this.translate.use(‘en’),日语就传’ja’,完全不用刷新页面。我一般会在页面顶部放个语言选择下拉框,用户选完直接触发这个方法,整个页面的文字就实时变了,特别丝滑。这种方式尤其适合后台管理系统、SaaS平台这类需要频繁切换语言的场景,用户操作流程不会被打断,体验感会好很多。
而且@ngx-translate还有个好处是支持异步加载翻译文件,就是说不是一上来就把所有语言包都塞给用户,而是用户切换到哪个语言,才去加载对应语言的翻译文件,对首屏加载速度挺友好的。之前做个多语言项目,光英文翻译文件就有500多KB,用异步加载后,首屏加载快了近2秒,用户反馈明显好了不少。如果你项目比较大,翻译内容多,这个点一定要用上,能省不少加载时间。
Angular 8及以下版本如何启用多语言支持?
Angular 8及以下版本需要手动安装@angular/localize依赖,执行命令“npm install @angular/localize save”即可。安装后在angular.json文件中配置“localize: true”,并 设置“i18nMissingTranslation: warning”以便编译时提醒未翻译内容。翻译文件推荐放在src/locale目录下,方便统一管理。
翻译文件只能用XLIFF格式吗?
不是的,Angular支持多种翻译文件格式,除了文章中提到的XLIFF(.xlf),还支持XMB(.xmb)和ARB(.arb)格式。XLIFF是最通用的选择,大部分翻译工具(如Poedit、Trados)都支持;ARB格式更简洁,适合小型项目;XMB则是Angular早期使用的格式,现在较少推荐。实际开发中可根据团队习惯和翻译工具选择, 优先用XLIFF保证兼容性。
不刷新页面切换语言的话,用什么方案最合适?
推荐用运行时切换方案,最常用的是借助第三方库@ngx-translate/core。它支持异步加载JSON格式的翻译文件,调用TranslateService的use()方法即可动态切换语言,无需刷新页面。具体步骤:先安装@ngx-translate/core和@ngx-translate/http-loader,配置翻译文件加载路径,然后在组件中注入TranslateService,通过按钮点击等事件触发语言切换。这种方式对用户体验更友好,尤其适合后台管理系统等需要频繁切换语言的场景。
处理复数、日期等特殊格式时,有哪些避坑点?
主要注意两点:一是复数规则用ICU消息格式,避免手动写if-else判断,比如“{count, plural, =0 {没有消息} =1 {1条消息} other {{{count}}条消息}}”,Angular会自动根据count值适配不同语言的复数形式;二是日期、货币等格式化需注入LOCALE_ID,在模块providers中配置“{ provide: LOCALE_ID, useValue: ‘en-US’ }”即可切换对应地区格式。动态切换语言时,可监听TranslateService的onLangChange事件,实时更新LOCALE_ID值,确保格式与当前语言匹配。
多语言项目如何优化加载性能?
可以从三个方面优化:一是采用“按需加载”,通过@ngx-translate/http-loader只加载当前语言的翻译文件,避免一次性加载所有语言包;二是压缩翻译文件,用在线工具将JSON/XLIFF文件压缩后再部署,减少网络传输体积;三是生产环境构建时启用AOT编译(ng build prod),Angular会对翻译内容进行预编译,提升渲染速度。 避免在翻译文件中存放大量冗余文本,只保留必要的页面文案,也能有效减小文件体积。