2017-12-19 280 views
10

Potrzebuję być w stanie używać przetłumaczonych ciągów w kodzie w mojej aplikacji Angular, ale z narzędziami i18n jeszcze nie do tego zadania, zaimplementowałem nieco hackowatą wersję, która wykorzystuje istniejące możliwości i18n Angulara, z intencją stopniowego moje rozwiązanie dla native Angular, ponieważ jego możliwości i18n doganiają moje potrzeby (powinny być 5.x release, kciuki).Czy treść tekstową elementu można odczytać w Angular bez czytania z DOM?

Zasadniczo mam TranslationDirective który czyta tekst z DOM, i emituje zdarzenia, gdy zmienia się tekst:

@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) {} 
} 

który przyzwyczaja się tak:

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

Ponieważ ciągi być przetłumaczył wszystkie rezydujące w szablonach, narzędzie Xi18n Angulara odczytuje je w porządku, a kompilator Angular zastąpi je przetłumaczonymi ciągami.

To jest funkcjonalne, ale nie świetne. Podejrzewam, że istnieje błąd związany z wyczekiwaniem na wyczucie czasu, który po prostu mnie nie zamanifestował. Istnieje nieefektywny i powolny cykl pisania do DOM-read-from-DOM, który byłby naprawdę miły do ​​wyeliminowania.

Chciałbym być w stanie wyeliminować jedno źródło problemów, omijając DOM, jeśli w ogóle mogę tego uniknąć. Czy Angular ma przechowywaną w pamięci kopię zawartości elementu, która jest dostępna bez przechodzenia przez DOM? Jeśli to możliwe, czy mogę całkowicie uniknąć pisania elementu tłumaczenia do DOM?

+0

Co na temat korzystania z ngModel? i proszę podać link plunker –

Odpowiedz

1

Wygląda na to, że duża część złożoności polega na tym, że chcesz wspierać tekst dynamiczny - tekst może się zmieniać w czasie wykonywania. Nie sądzę, że trzeba to zrobić, bo tekst i18n musi być statyczna, tak aby:

  1. To mogą być pozyskiwane w czasie kompilacji.

  2. Można to przetłumaczyć z góry, a wszystkie tłumaczenia są przechowywane w późniejszym czasie kompilacji.

Twój przykład "Dzisiaj jest ..." jest doskonałym przykładem nieprzetłumaczalnego tekstu. :-) Powinieneś to zmienić, aby po prostu "Today is" sam był fragmentem tekstu, a następnie data wyświetlana z bieżącym ustawieniem narodowym poza zasięgiem.

+0

Narzędzia Angular's i18n obsługują tłumaczenia w tym formacie. Potrzeba pochodzi z biblioteki innej firmy, która oczekuje, że tekst zostanie przesłany za pośrednictwem obiektów konfiguracyjnych, i potrzebuję tego tekstu do przetłumaczenia. – asgallant

+0

Wow, mój zły, nie wiedziałem, że narzędzie Angular i18n może sobie z tym poradzić. Jednak użyłeś podwójnego - {}, więc czy to nie sprawia, że ​​wyrażenie jest dynamicznie oceniane przez Angular, zanim zostanie wywołana twoja dyrektywa myAppTranslation? –

+0

Tak, zostanie to ocenione przed wywołaniem dyrektywy - jest to część punktu. Przykładowy przypadek użycia zawiera datę, która musi być zlokalizowana. Dołączanie daty do przetłumaczonego ciągu nie jest opcją, ponieważ tłumaczenie może przenieść położenie daty w ciągu znaków dla różnych języków. – asgallant