2016-05-02 12 views
0

Ich muss meine Angular 2 App nach Sprache lokalisieren, die durch die Lokalisierung des Browsers definiert wurde (Senden der POST-Anfrage an die Datenbank - gib mir Übersetzungen für diese Sprache, die im Header angegeben ist).Sprachlokalisierung von Angular 2 App

Was ich jetzt umgesetzt haben:

Ich habe einige gemeinsame Variable, zum Beispiel Wörterbuch in dictionary.ts Datei. Sehen Sie, dass ich es standardmäßig auf Englisch eingestellt habe.

export let Dictionary = { 
    1 : "engishVar1", 
    2 : "englishVar2" 
} 

In meinem AppComponent, die der Einstiegspunkt meiner App ist (weil ich Bootstrap (AppComponent) mache ich so etwas wie dies in Konstruktor:

this._appService.translationRequest(aptxIdsToTranslatePost) 
    .subscribe(
      data => this.handleResponse(data), 
      err => console.log("[App component] Error " + JSON.stringify(err)), 
     () => console.log("[App component] GET translations finished: " + JSON.stringify(this.responseOnTranslationRequest)) 
     ); 

aptxIdsToTranslatePost ist JSON Körper , die ich meinem Backend-Server erzähle, gib mir die IDs 1 und 2 und die Sprache wird vom http POST-Header übernommen .. Jetzt gibt der Server mir die IDs wieder mit der Sprache zurück

In der HandleResponse-Methode mache ich das:

Wie ich oben gesehen habe, ist mein Wörterbuch etwas wie Schlüsselwertspeicher. Was ist das Problem? Wenn der POST verzögert wird, wird meine App nicht lokalisiert, da die Ansicht gerendert wird, bevor das Wörterbuch festgelegt wird. Wenn ich die Seite neu lade, wird die Ansicht vollständig lokalisiert, weil die Übersetzung zwischengespeichert ist und ich nicht auf die POST-Antwort warten kann. Jetzt in meinen Komponenten, ich schaff' Lokalisierung im Konstruktor, zum Beispiel:

constructor() { 
     this.welcomeTitle = Dictionary[1]; 
     this.welcomeDescription = Dictionary[2]; 
     this.welcomeBuyText = Dictionary[3]; 
     this.welcomeBuyTicket = Dictionary[4]; 
    } 

ich über drei weitere Lösungen denken, aber ich denke, dass keiner von ihnen ist gut.

Zuerst ist, dass ich meine Lokalisierung vom Konstruktor der Komponente zu etwas später von angular 2 Lebenszyklus, in der Regel ngAfterViewInit oder etwas Ähnliches transformieren werde. Auch hier gibt es keine Garantie, dass die Antwort auf POST zurückkehrt, vielleicht ja, vielleicht nein.

Als nächstes ist, dass ich POST synchron, nicht async erstellen werde, aber das ist eine schlechte Idee, weil meine App einfrieren kann (einige Probleme mit der Übersetzung von POST).

Die letzte ist (die ich heute implementiert, aber es funktioniert nicht), dass ich Dictionary-Klasse (jetzt JSON-Variable) erstellen und auf jeder Komponente werde ich Instanz davon erstellen. Dann werde ich auf AppComponent die Antwort (handleResponse) wie im obigen Beispiel subskribieren und in handleResponse werde ich eine Methode vom Typ EventEmitter() aufrufen. Also auf meiner anderen Komponente, werde ich es unterzeichnen (in Konstruktor der Komponente), in der Regel:

//in AppComponent after handleResponse 
this._sharedService.dictionaryTranslationEvent.emit(this.dictionary); 

//subscription in my component on new instance of Dictionary 
this._sharedService.dictionaryTranslationEvent.subscribe(
     (dictionary) => { 
      this.dictionary = dictionary; 
      this.welcomeTitle = this.dictionary.getDictionary[1]; 
      this.welcomeDescription = this.dictionary.getDictionary[2]; 
      this.welcomeBuyText = this.dictionary.getDictionary[3]; 
      this.welcomeBuyTicket = this.dictionary.getDictionary[4]; 
}); 

Um sicher zu sein, lege ich dictionary.ts jetzt:

export class Dictionary { 

    private dict: any; 

    constructor() { 
     this.dict = { 
      1: "englishVar1", 
      2: "englishVar2", 
     } 
    } 

    /* GET */ 
    get getDictionary(): any { 
     return this.dict; 
    } 

    /* SET */ 
    set setDictionary(dictionary: any) { 
     this.dict = dictionary; 
    } 
} 

Also, was ist die beste Idee, um die Lokalisierung von angular 2 App zu erstellen? Vielen Dank.

Antwort

2

Angesichts eines ähnlichen Problems habe ich die folgende Strategie gewählt.

1) Erstellen Sie eine DictionaryService Klasse, die die Dictionary-Rolle implementiert; Diese Klasse enthält ein JSON-Objekt, das für jede Zeichenfolge einen Eintrag speichert, die übersetzt werden muss, und eine Methode, die die übersetzte Zeichenfolge für ein geben stringID und LanguageId, also so etwas wie

 @Injectable() 
    export class LabelDictionaryService { 
     public dictionary: {}; 

     constructor(private _session: Session) { 
      this.dictionary = this.getDictionary(); 
     } 

    getDictionary() { 
     return { 
     stringId1: {en: 'String1InEnglish', it: 'String1InItalian', sp: 'String1InSpanish', ....}, 
     stringId2: {en: 'String2InEnglish', it: 'String2InItalian', sp: 'String2InSpanish', ....} 
     .... 
     } 
    } 

    getTranslation(inStringId: string, inLanguageId?: string) { 
      let langId; 
      if (inLanguageId) { 
       langId = inLanguageId; 
      } else { 
       langId = getDefualtLanguageId(); //getDefualtLanguageId() needs to be implemented in the DictionaryService class and retrieves the default language from the environment 
      } 
      let translation; 
      if (this.dictionary[inLabelId]) { 
       translation = labelTexts[langId]; 
      } 
      if (translation == null) { 
       text = inLabelId; 
       console.error(inStringId + ' has no defined text for language ' + langId); 
      } 
      return translation; 
     } 

    } 

2) Verwenden Sie Dependency Injection bietet bewegen das Wörterbuch um die Anwendung herum, so dass Komponenten, die den Dictionary-Dienst benötigen, darauf zugreifen können

Diese Lösung adressiert nicht direkt die Last des Wörterbuch-Inhalts von einem externen Dienst, aber ich denke, Sie können diese Anforderung anpassen leicht die oben genannten Codebeispiel tp implementieren Sie die Last des Wörterbuch Inhalt in der ngOnInit() Methode Ihrer AppComponent. Wenn Sie auch einen Mechanismus implementieren müssen, der verhindert, dass der Benutzer mit Ihrer App fortfährt, bevor das Wörterbuch geladen wird (was für mich Sinn macht), müssen Sie die eleganteste Möglichkeit finden, die Benutzeroberfläche zu deaktivieren, bis das Wörterbuch geladen ist (möglicherweise mit ein Timeout-Fluch). Ich hoffe, dies hilft

+0

Vielen Dank. –