使用渲染器进行国际化?

7

我最近读到了@yearofmoo关于Angular2 Renderer的非常有趣的文章。它给了我一个想法,可能可以使用Renderer进行i18n国际化。基本上使用这个功能:

  createText(parentElement: any, value: string): any {
    // this is called for every text node in the template
  }

只需要将 value 映射到不同的语言即可进行转换:

let es = { "Hello": "Hola" }

value = "Hello"
value = es[value]

我简要查看了issuesdesign docs,但在深入探究之前,我想先确认一下是否有任何与此有关的经验。是否有任何可能阻止此功能工作的问题?有我不知道的任何重大变化吗?对于这种方法有什么意见?

由于Renderer是Web Workers安全的,所以我们应该使用它,不应该出现问题。关于重大变更...很难说,我不认为Renderer会在未来发生巨大变化,如果有的话。i18n将得到官方支持,对我来说这是一个“停滞点”,但这只是我的个人观点,玩转Angular2并没有错。 - Eric Martinez
同Günter和Thierry一致,感谢分享Sasxa! - Langley
希望官方能提供支持,但希望他们不要把它弄得太复杂或者太强大。我现在会试着用渲染器来进行音译的实验。 - Sasxa
2个回答

1
我们使用渲染器来设置由属性提供的翻译。
import { Directive, ElementRef, Input, Renderer, OnInit} from '@angular/core';
import { TranslateService } from './translate.service';

@Directive({ selector: '[translate]' })
export class TranslateDirective  implements OnInit{

    @Input() translate :string;

   constructor(private el: ElementRef, private renderer: Renderer, private _translateService : TranslateService) {}

   ngOnInit(): void {
        this.renderer.setText(this.el.nativeElement,this._translateService.instant(this.translate));
   }
}

请查看plunker以获取演示。

希望这是您正在寻找的内容。


0

这是一个老问题,但也许其他人会偶然发现它。:)

我知道Angular有内置的i18n机制,但出于几个原因,我们不想使用它们。主要是因为我们已经在另一个产品中拥有数千个翻译短语映射,并且我们希望重复使用所有这些内容。所以我们将现有的映射转换为json格式,然后在我们的angular项目中:

  1. 创建一个服务(例如I18nService),其中包含一个函数:
export class I18nService {
    phraseMap: Map<string, string>; // fill this however you like

    translatePage(elements: QueryList<ElementRef>, renderer: Renderer2) {
        elements.forEach((el: ElementRef) => {
           let key:string = el.nativeElement.innerText;
           let phrase = this.phraseMap.get(key);
           if (phrase) {
              renderer.setProperty(el.nativeElement, 'innerText', phrase);
           }
        }
    }

// ...

this.phraseMap 是一个包含键值对的 Map<string, string>,例如 key: "PH_HELLO",value: "Bonjour"

在你的组件模板中,使用模板变量(我使用了 #i18n,但可以是任何名称)来装饰你的元素,并用短语键替换文本,例如:

   <span #i18n>PH_HELLO</span>
   <div #i18n>PH_LOGOUT</div>

在你的组件类中,使用 ViewChildren 收集所有适当的元素。注入你的服务和 Angular Renderer2,并实现 AfterViewInit:
export class MyComponent implements AfterViewInit {

   @ViewChildren('i18n', {read:ElementRef}) i18nElements: QueryList<ElementRef>;

   constructor(
      private i18nService: I18nService,
      private renderer: Renderer2 // from @angular/core
   ) {}

   ngAfterViewInit() {
      this.i18nService.translatePage(this.i18nElements, this.renderer);
   }


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接