对于angular的插件我以前的做法就是上网找个例子然后拿过来就用,用完了框架怎么搭建进来的,后期升级怎么处理就要重新去看去找。而且如果想优化时一头雾水。
写代码就像电视剧请回答1988中的台词一样,人这一辈子,在自己的人生之纸上涂抹颜料,五彩斑斓、浓墨重彩,最终叠加成一纸漆黑。回忆模糊,再也想不出来当时那些红粉蓝绿的笔痕,是以怎样的姿态划过白纸,又发出了何种声响,沙哑还是清脆。都记不清了。仿佛那些多彩的故事,从来都没有发生过,只是我美好的想象。
我理解关于程序的大意是程序本来就像一张白纸,你画一些,他画一些,最终变成一张黑纸,我们都看不清彼此的痕迹。
导入ngx-translate
运行下面命令安装@ngx-translate/core和@ngx-translate/http-loader:
npm install @ngx-translate/core --save
npm install @ngx-translate/http-loader --save
然后在根模块(一般是app.module.ts)下引入TranslateModule
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import {HttpClient} from "@angular/common/http";
import {TranslateLoader, TranslateModule} from "@ngx-translate/core";
import {TranslateHttpLoader} from "@ngx-translate/http-loader";
import { AppComponent } from './app.component';
// 为AOT(Ahead-of-Time,预编译)准备
export function createTranslateLoader(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}
这里使用了TranslateHttpLoader 来加载我们定义好的语言文件。"/assets/i18n/[lang].json"这里的lang就是当前正在使用的语言。这里"/assets/i18n/[lang].json"在前后分离的项目中,如果想通过访问后台接口,可以在这里替换为以下。
//用于根据语言类型获取页面所有该语言的键值
export function createTranslateLoader(http: HttpClient, configProvider: ConfigProvider) {
return new TranslateHttpLoader(http, `${configProvider.getWebApiUri()}api/Translate/GetValues?ValueType=`, '');
}
这里Translate/GetValues替换成你后台代码的Controller名/method名。
注意:如果当前采用的是AOT编译方式或者是ionic工程,那么useFactory对应的必须是一个export的自定义方法而非内联方法。
@NgModule({
imports: [
BrowserModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: (createTranslateLoader),
deps: [HttpClient]
}
})
],
declarations: [AppComponent],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
如果Angular版本小于4.3,可以使用[email protected],并用@angular/http中的Http代替HttpClient
。
为了方便在其他模块下使用,在sharedModule下面导入TranslateModule:
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import {TranslateModule} from "@ngx-translate/core";
const sharedModule = [
CommonModule,
TranslateModule
];
@NgModule({
imports: sharedModule,
declarations: [],
exports: sharedModule
})
export class SharedModule { }
这样在其他模块下导入sharedModule就可以使用ngx-translate了。
使用ngx-translate
在/assets/i18n/目录下新建en.json和zh.json两个文件,如果用Angular-Cli新建的工程,默认会有这两个文件。这个目录下的json文件名会作为ngx-translate中的语言名称使用,比如translate.use(‘zh’)中的zh就是zh.json的文件名,如果json文件改成zh-CN,相应代码中的也要更改为translate.use(‘zh-CN’)。
不建议用以上删除线表达的用法。不利于后期维护。
建议在数据库中创建一个表将每种语言分别作为一列进行维护。如果页面元素重复性很低,并且需要信息量大请结合项目本身情况在项目初期设计每张表的多语言架构。
TypeScript:
import { Injectable } from '@angular/core';
import { TranslateService, LangChangeEvent } from '@ngx-translate/core';
import { take } from 'rxjs/operators';
import { ReplaySubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AppTranslateService {
translations: any = {};
language$ = new ReplaySubject(1);
constructor(private translateService: TranslateService) { }
//设置初始语言
setInitState(){
//添加语言
const availableLangs = ['en', 'zh-cn'];
this.translateService.addLangs(availableLangs);
//获取当前语言类型
let lang = localStorage.getItem('translate');
//如果url上没有语言类型,则默认中文
if (lang === null || lang.length === 0) {
// const browserLang = (this.translateService.getBrowserLang().includes('zh')) ? 'zh-cn' : 'en';
const browserLang = 'zh-cn';
lang = browserLang;
localStorage.setItem('translate', lang);
} //如果url上的语言类型不在列表中,则默认英文
else {
if (availableLangs.indexOf(lang) < 0) {
lang = 'en';
localStorage.setItem('translate', lang);
}
}
this.setLang(lang);
}
//当语言改变时使用新语言
setLang(lang: string) {
//注册Lang的监听事件(只要注册过,一旦发生change事件,即会调用)
this.translateService.onLangChange.pipe(take(1)).subscribe(result => {
this.language$.next(result);
this.translations = result.translations;
console.log(this.translations);
});
//使用这个Lang
this.translateService.use(lang);
}
//根据key获取对应的值,用于导航栏部分第一次获取不到值,异步获取值
async translate(key: string): Promise {
return await this.translateService.get(key).toPromise();
}
//根据key获取对应的值
translateText(key: string): string{
const text: string = this.translateService.instant(key);
return text;
}
HTML:
{{'Edit'' | translate}}
TranslateService仅需在要使用该服务的地方注入,在不需要的组件中,可以不注入,直接使用管道在HTMl翻译对应的内容。
在HTML中还可以使用属性指令来翻译:
如果在ts文件中获取对应语言可以用
Edit = this.translate.translations['Edit '] === undefined? '编辑':this.translate.translations['Edit '];
或者
Edit = '';
ngOnInit() {
this.Edit = this.translate.translations.Edit ;
}
翻译TypeScript中的内容
可以使用TranslateService中的instant()方法配合订阅onLangChange来实现。onLangChange是一个监听语言变化的EventEmitter,可以实现跨模块通讯,比如A模块中切换成英文,onLangChange会通知所有模块下语言都切换成英文,此时去B模块下,界面也是英文状态的。
后端采用C#写法
Controller
[HttpGet("[action]")]
public async Task GetValues(string valueType)
{
var translateValues = await translateManager.GetTranslateValues(valueType);
return Ok(translateValues);
}
Service
//获取Json文件
public async Task GetTranslateValues(string languageCode)
{
string sqlBase = "SELECT [TextKey], [{0}] [TextValue] FROM [App].[TextValue] WHERE [IsDisabled] = 0 and [IsDeleted] = 0 ";
string textValue = string.Empty;
switch (languageCode)
{
case "en":
textValue = "TextValueEN";
break;
case "zh-cn":
textValue = "TextValueCN";
break;
default:
textValue = "TextValueEN";
break;
}
string sql = string.Format(sqlBase, textValue);
var result = await dbContext.Database.GetDbConnection().QueryAsync(sql);
JObject json = new JObject();
foreach (var row in result)
{
json.Add(row.TextKey, row.TextValue);
}
return json;
}
对于以上内容如有争议,欢迎大家留言给我,也为方便国内Angular使用者,谢谢大家。
链接:
[1]: https://tc9011.com/2017/12/16/angular%E4%B8%ADngx-translate%E4%BD%BF%E7%94%A8%E7%AE%80%E4%BB%8B/
[2]:https://www.jb51.net/article/121841.htm