2017-12-19 26 views
10

Angularアプリケーションのコードで翻訳された文字列を使用できるようにする必要がありますが、i18nツールをまだ使用していない場合は、Angularの既存のi18n機能を利用して、 i18nの機能が私のニーズに追いつくようにネイティブのAngularのための私の解決策を出してください(5.x release、指が交差するはずです)。要素のテキストコンテンツをDOMから読み取らずにAngularで読み取ることはできますか?

基本的に、私はDOMからテキストを読み込んで、ときにテキストの変更イベントを発するTranslationDirectiveあります

@Directive({ 
    selector: '[myAppTranslation]' 
}) 
export class TranslationDirective implements AfterViewChecked, OnChanges { 
    /** 
    * dependencies takes an array of the values needed to calculate the output translation 
    * we use this for change detection, to minimize the DOM interaction to only when it is necessary 
    */ 
    @Input() dependencies: any[]; 
    isDirty = true; 
    @Input() messageKey: string; 
    message: string; 
    @Output() messageUpdated = new EventEmitter<TranslationEvent>(); 

    constructor(public el: ElementRef) {} 

    /** 
    * sets the translated message and triggers the TranslationEvent 
    */ 
    setMessage() { 
    const message = (this.el.nativeElement.textContent || '').trim(); 
    const oldMessage = (this.message || ''); 
    if (oldMessage !== message) { 
     this.message = message; 
     this.isDirty = false; 
     this.triggerTranslationEvent(); 
    } 
    } 

    ngOnChanges() { 
    this.isDirty = true; 
    } 

    ngAfterViewChecked() { 
    if (this.isDirty) { 
     this.setMessage(); 
    } 
    } 

    /** 
    * triggers the messageUpdated EventEmitter with the TranslationEvent 
    */ 
    triggerTranslationEvent() { 
    // need to delay a tick so Angular doesn't throw an ExpressionChangedAfterItHasBeenCheckedError 
    setTimeout(() => { 
     const event = new TranslationEvent(this.messageKey, this.message); 
     this.messageUpdated.emit(event); 
    }); 
    } 
} 

export class TranslationEvent { 
    constructor(public messageKey: string, public message: string) {} 
} 

次のように使用されます:する文字列ので

<span 
    myAppTranslation 
    i18n 
    [dependencies]="[today]" 
    [messageKey]="todaysDateKey" 
    (messageUpdated)="setTodaysDateTranslation($event)" 
> 
    Today is {{today | date:'short'}} 
</span> 

をテンプレート内のすべての言語に翻訳され、Angularのxi18nツールはそれらを正確に読み取り、Angularコンパイラはそれらを翻訳された文字列で置き換えます。

これは機能的ですが、それほど大きくありません。私はただまだ明らかにされていない私をかむことを待っているタイミングのバグがあると思う。非効率的かつ遅いDOMへのwrite-to-DOMのサイクルがあり、排除するのが本当にうれしいです。

DOMをバイパスして問題の原因を取り除くことができたら、私はそれを避けることができます。 Angularは、DOMを経由せずにアクセス可能な要素のコンテンツのメモリ内コピーを保持しますか?可能であれば、翻訳要素をDOMに完全に書き込まないようにすることはできますか?

+0

ngModelの使用についてはどうですか?プランナーリンクを提供してください –

答えて

1

動的なテキストをサポートする必要があるため、実行時にテキストが変更される可能性があるため、複雑さが増しているようです。これは、コンパイル時に抽出することができ

  1. :国際化テキストがよう静的にする必要があるので、私は、あなたがそれを行うために必要とは思いません。

  2. 事前に翻訳することができ、すべての翻訳は後でコンパイル時に保存されます。

あなたの例「今日は...」は、翻訳不能なテキストの完全な例です。 :-) "Today is"をテキストチャンクだけにして、現在のロケールで表示される日付をの外にあるの外に変更する必要があります。

+0

Angularのi18nツールは、その形式の翻訳をサポートしています。この必要性は、構成オブジェクトを介してテキストが渡されることを期待する第三者図書館の必要性から来ており、そのテキストを翻訳する必要があります。 – asgallant

+0

うわー、私の悪い、私は角度i18nツールがそれを処理できるか分からなかった。しかし、double - {}を使用したので、myAppTranslationディレクティブが呼び出される前に、式をAngularで動的に評価する必要はありませんか? –

+0

はい、ディレクティブが呼び出される前に評価されます - それはポイントの一部です。使用例の例には、ローカライズが必要な日付が含まれています。翻訳された文字列に日付を追加することは、文字列内の日付の場所を異なる言語に移動できるため、オプションではありません。 – asgallant

関連する問題