我们必须等到Angular 6 for angular-i18n才能支持错误消息等代码的翻译。
对于那些使用angular-i18n(例如,而不是ngx-translate)的人,你在做什么同时处理代码中的翻译?在我看来,如果没有很多字符串,那么一个简单的语言服务,其中包含通过语言代码和id进行翻译的方法,但我感兴趣的是更优雅的东西" angular"。
我不知道承诺的代码翻译支持会是什么样子,但任何临时解决方案在上线时都可以很容易地转换为angular-i18n方式。
那里有什么人来处理这个问题?有什么想法吗?
答案 0 :(得分:7)
这种polyfill似乎是现在最好的方法:
https://github.com/ngx-translate/i18n-polyfill
它允许您将要翻译的所有内容包装在i18n()
函数中(此API可能会在Angular的未来版本中保留-请参阅此答案底部的注释)。
polyfill主要由负责i18n的Angular团队成员Olivier Combe撰写:
对于Angular 5,安装时需要版本0.2.0:
npm install @ngx-translate/i18n-polyfill@0.2.0 --save
对于Angular 6,获取最新版本-当前为1.0.0:
npm install @ngx-translate/i18n-polyfill@1.0.0 --save
我在Angular 5的JIT和AOT编译中都使polyfill工作 (在Angular 6上也可以工作)。这是将语言翻译成一种语言所需的操作(这是一种有效的方法,您可以稍后再使用多种语言,我将在后面进行解释):
将以下导入添加到根Angular模块中:
import { TRANSLATIONS, TRANSLATIONS_FORMAT } from '@angular/core';
import { I18n } from '@ngx-translate/i18n-polyfill';
添加以下常量,并在根模块中指定提供程序:
// add this after import + export statements
// you need to specify the location for your translations file
// this is the translations file that will be used for translations in .ts files
const translations = require(`raw-loader!../locale/messages.fr.xlf`);
@NgModule({ ....
providers:
[
I18n,
{provide: TRANSLATIONS, useValue: translations},
{provide: TRANSLATIONS_FORMAT, useValue: 'xlf'},
...
使用AOT编译的注意事项:如果您使用AOT编译来 翻译您的模板,翻译.ts文件中的消息 仍将在运行时使用JIT编译完成(这就是为什么 需要引用
TRANSLATIONS
和TRANSLATIONS_FORMAT
而不是仅仅 在构建脚本中指定这些)。
在您要提供翻译的.ts文件中,添加以下内容:
import { I18n } from '@ngx-translate/i18n-polyfill';
constructor(private i18n: I18n) {
console.log(i18n("This is a test {{myVar}} !", {myVar: "^_^"}));
}
这表明您甚至可以在要翻译的消息中包括插值。
您可以像这样使用i18n定义(即,使用翻译'source'id,含义,描述来指定)
this.i18n({value: 'Some message', id: 'Some message id', meaning: 'Meaning of some message', description: 'Description of some message'})
您仍然需要提取消息,并且可以使用ngx-extractor工具执行此操作。当您安装polyfill时,这将包括在内,并且我在下面的npm脚本中添加了有关其用法的示例。另请参见polyfill page上的自述文件。
要支持在多种语言之间切换,您需要翻译的工厂提供者。有关polyfill page自述文件的详细信息。您的根模块中将需要这样的内容(或对于AOT编译,将localeFactory
的返回值替换为检测应用程序当前正在运行的AOT编译语言变体的函数)
export function localeFactory(): string {
return (window.clientInformation && window.clientInformation.language) || window.navigator.language;
}
providers:
[
{
provide: TRANSLATIONS,
useFactory: (locale) => {
locale = locale || 'en'; // default to english if no locale provided
return require(`raw-loader!../locale/messages.${locale}.xlf`);
},
deps: [LOCALE_ID]
},
{
provide: LOCALE_ID,
useFactory: localeFactory
},
所有这些都与xliffmerge兼容,这是一个很好的工具,可以自动合并您添加的所有 new 翻译,而不会覆盖现有翻译。 Xliffmerge还可以使用Google翻译自动执行翻译(您需要使用Google翻译API密钥)。为此,我按以下顺序进行提取和合并/翻译,即在之前我进行实际的AOT构建:
"extract-i18n-template-messages": "ng xi18n --outputPath=src/locale --i18n-format=xlf",
"extract-i18n-ts-messages": "ngx-extractor --input=\"src/**/*.ts\" --format=xlf --out-file=src/locale/messages.xlf",
"generate-new-translations": "xliffmerge --profile xliffmerge.json en fr es de zh"
网站的特定语言版本的AOT构建如下:
"build:fr": "ng build --aot --output-path=dist/fr --base-href /fr/ --i18nFile=src/locale/messages.fr.xlf --i18nFormat=xlf --locale=fr",
这主要由负责i18n的Angular团队成员Olivier Combe撰写。在此阶段,这是一个“推测性” polyfill,用于翻译.ts文件中的变量或字符串。它很可能会被Angular中内置的API取代,该API非常相似,因此以后的升级应该可以合理管理。这是Github页面上的免责声明:
该库是一个推测性的polyfill,这意味着它应该 替换将来会出现的API。 如果API不同,则将在可能的情况下提供迁移工具。
围绕即将发布的Angular 6的次要版本中对变量/字符串在代码中的转换的支持进行了一些讨论。
这是Olivier Combe(今年3月以来)的引言,摘自Github上的以下讨论:
https://github.com/angular/angular/issues/11405
用于运行时i18n的第一个PR已被合并到master中, 一个Hello World演示应用程序,我们将使用它来测试功能。有用 在运行时,即使在理论上也支持理论上的代码翻译 尚无服务。目前,它的支持非常少(静态 字符串),我们正在努力添加新功能(我将 下周进行提取工作,然后使用占位符动态提取字符串 和变量)。之后,我们将提供代码翻译服务。 新功能完成后,它将合并到主版本中 无需等待新的专业。
答案 1 :(得分:1)
我有一个" bizarro"变通 我们可以有两个组件
APP-text.component.ts
import { Component} from '@angular/core';
@Component({
selector: 'text',
template:`<ng-content></ng-content>`
})
export class AppTextComponent{}
和app-translation.component.ts
import { Component, QueryList, ElementRef, ContentChildren } from '@angular/core';
import { AppTextComponent } from './app-text.component';
@Component({
selector: 'app-translation',
template: `<ng-content></ng-content>`
})
export class AppTranslationComponent{
@ContentChildren(AppTextComponent, { read: ElementRef }) divs: QueryList<ElementRef>;
constructor() { }
translate(id: string): string {
let nativeElement: any = this.divs.find(e => e.nativeElement.id == id);
return nativeElement ? nativeElement.nativeElement.innerText : "";
}
}
然后,在一个组件中,我们可以有一些像
<app-translation #translations style="visibility:collapsed">
<text id="message1">Translation app</text>
<text id="message2">Hola Mundo</text>
</app-translation>
//In your code you can use a ViewChild and the function "traslate"
@ViewChild('translations') t;
alert(this.t.translate("message1"));
答案 2 :(得分:1)
自从我上次回复以来已经很长时间了,可以简化它。
如果我们的.html类似于
<!--at first we put all the translation in a hidden div-->
<div *ngIf="!yet" style="display: none">
<span #t id="message1">Translation app</span>
<span #t id="message2">Hola Mundo</span>
</div>
.ts中有一个简单的ViewChildren,一个变量“尚”和一个变量“ translation”
yet: boolean = false;
translation:any={}
@ViewChildren("t")
set translations(values: QueryList<any>) {
//when yet becomes true, values.length=0
if (values.length) {
values.forEach(c => {
this.translation[c.nativeElement.id]=c.nativeElement.innerHTML
})
//it's necesary enclosed this.yet=true in a setTime to avoid
//the error expresion changes After Exec
setTimeout(()=>{
this.yet=true;
})
}
}
然后我们可以写一些类似的东西
alert(this.translation['message1']);
更新 相同的想法:组件实现 你有一个组件
import { Component, QueryList, AfterViewInit, ContentChildren } from '@angular/core';
@Component({
selector: 'ng-translation',
template: `
<div *ngIf="!yet" [style.display]="'none'">
<ng-content></ng-content>
</div>
`
})
export class TranslationComponent implements AfterViewInit {
@ContentChildren("t") translations: QueryList<any>
data: any = {}
yet: boolean = false;
get(text: string) {
return this.data[text];
}
ngAfterViewInit(): void {
if (this.translations.length) {
this.translations.forEach(c => {
this.data[c.nativeElement.id] = c.nativeElement.innerHTML
})
setTimeout(() => {
this.yet = true;
})
}
}
}
在任何其他组件中
<ng-translation #translation>
<span #t id="message1">Translation app</span>
<span #t id="message2">Hola Mundo</span>
</ng-translation>
@ViewChild("translation") translation:TranslationComponent
click()
{
alert(this.translation.get('message1'));
}
答案 3 :(得分:1)
查看此博客条目:https://blog.ninja-squad.com/2019/12/10/angular-localize/
简而言之:
有$ localize可用于执行此操作。
@Component({
template: '{{ title }}'
})
export class HomeComponent {
title = $localize`You have 10 users`;
}
不幸的是,该功能尚未真正完成:
然后,您可以按照与模板相同的方式来翻译消息。但是,目前(v9.0.0),CLI并未像使用模板那样使用xi18n命令提取这些消息。
答案 4 :(得分:1)
从 Angular 11 和使用 Ivy 开始,您可以在 .ts 文件中使用 $localize 函数:
$localize `your text`
运行 extract-i18n 将此文本提取到 XLIFF 文件(在我的例子中),就像在模板中使用 i18n 属性一样。
来源:https://github.com/angular/angular/issues/11405#issuecomment-519697830
和这篇博客文章: https://blog.angular.io/angular-localization-with-ivy-4d8becefb6aa
答案 5 :(得分:0)
您可以尝试此套餐 ngx-dy-i18n
它支持本机解决方案