2016-12-12 5 views
26

Ich versuche Angular offiziellen Internationalisierungs-Tools mit Winkel universal zu verwenden. Bisher bin ich in der Lage, das Client-Seite-Rendering mit dem folgende Verfahren (dank diese Antwort https://stackoverflow.com/a/40930110/1110635) zu übersetzen:Angular Universal mit i18n (Server Side Rendering)

mich hinzufügen „i18n“ Attribute wie in der Dokumentation in meinen Vorlagen angegeben:

./src /+app/about/about.component.html:

<h1 i18n="H1 of the about component">About</h1> 
... 

Dann laufe ich:

./node_modules/.bin/ng-xi18n 

die Basis m zu erzeugen, essages.xlf Datei.

Dann kopiere ich diese Datei für jedes Gebietsschema I als unterstützen möchten "Nachrichten. [Locale] .xlf" in einem "locale" Ordner. Wenn Sie bereit sind, erstelle ich eine "Nachrichten [locale] .ts." Für jede XLF-Datei eine exportierte Zeichenfolge ihres Inhalts enthalten:

./locale/messages.fr.ts:

// TRANSLATION_FR is only for "messages.fr.ts" of course. 
// I would create a TRANSLATION_ES const inside "messages.es.ts" for spanish for example. 
export const TRANSLATION_FR: string = `<?xml version="1.0" encoding="UTF-8" ?> 
<xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"> 
    <file source-language="en" datatype="plaintext" original="ng2.template"> 
    <body> 
     <trans-unit id="004b222ff9ef9dd4771b777950ca1d0e4cd4348a" datatype="html"> 
     <source>About</source> 
     <target>A propos</target> 
     <note priority="1" from="description">H1 of the about component</note> 
     </trans-unit> 
    </body> 
    </file> 
</xliff> 
`; 

Schließlich meine client.ts Datei sieht wie folgt aus:

./src/client.ts:

[...] 

// i18n 
import { TRANSLATIONS, TRANSLATIONS_FORMAT, LOCALE_ID } from '@angular/core'; 
import { TRANSLATION_FR } from '../locale/messages.fr'; 

import { MainModule } from './browser.module'; 

export const platformRef = platformUniversalDynamic(); 

// on document ready bootstrap Angular 2 
export function main() { 
    return platformRef.bootstrapModule(MainModule, { 
     providers: [ 
      {provide: TRANSLATIONS, useValue: TRANSLATION_FR}, 
      {provide: TRANSLATIONS_FORMAT, useValue: "xlf"}, 
      {provide: LOCALE_ID, useValue: 'fr'} 
     ] 
    }); 
} 
bootloader(main); 

Das funktioniert und die Anwendung "Clientseite" funktioniert wie erwartet. "Über" wird ersetzt durch "A propos". ABER, weil eckige universelle vor-rendern die Seite auf der Serverseite mit Express der Text wird nicht übersetzt, bis das Client-Bootstrapping erfolgt ist.

Also, wenn Sie zum ersten Mal auf der Seite gehen sehen Sie „über“ für ca. 1 Sekunde, bevor die Client-Seite Tritte in einem ersetzen Sie es mit „A propos“.

Die Lösung scheint offensichtlich, führen Sie einfach den Übersetzungsdienst auf der Serverseite! Aber ich habe keine Ahnung, wie ich das machen soll.

Mein server.ts wie folgt aussieht:

./src/server.ts

[...] 

// i18n 
import { TRANSLATIONS, TRANSLATIONS_FORMAT, LOCALE_ID } from '@angular/core'; 
import { TRANSLATION_FR } from '../locale/messages.fr'; 

const app = express(); 
const ROOT = path.join(path.resolve(__dirname, '..', 'dist')); 

// Express View 
app.engine('.html', createEngine({ 
    ngModule: MainModule, 
    providers: [ 
     /** 
     * HERE IS THE IMPORTANT PART. 
     * I tried to declare providers but it has no effect. 
     */ 
     {provide: TRANSLATIONS, useValue: TRANSLATION_FR}, 
     {provide: TRANSLATIONS_FORMAT, useValue: "xlf"}, 
     {provide: LOCALE_ID, useValue: 'fr'} 
    ] 
})); 
app.set('port', process.env.PORT || 3000); 
app.set('views', ROOT); 
app.set('view engine', 'html'); 
[...] 

function ngApp(req, res) { 
    res.render('index', { 
     req, 
     res, 
     preboot: false, 
     baseUrl: '/', 
     requestUrl: req.originalUrl, 
     originUrl: `http://localhost:${ app.get('port') }` 
    }); 
} 
app.get('*', ngApp); 

// Server 
let server = app.listen(app.get('port'),() => { 
    console.log(`Listening on: http://localhost:${server.address().port}`); 
}); 

Ich habe keinen direkten Zugriff auf die bootstrapModule Methode wie auf der Client-Seite. Der Provider Schlüssel auf dem "createEngine" Parameterobjekt war bereits dort in der original server.ts code.

Was fehlt mir?

+0

Hallo, ich versuche, dies zu tun, aber ich will nicht * verwenden .ts Dateien für Übersetzungen aber es ist so schwierig. Also, hast du es gelöst? – IvanMoreno

+0

Nein, ich benutze ng2-translate, weil ich keine Möglichkeit gefunden habe, das native Modul auf der Serverseite arbeiten zu lassen. Aber Sie können es wie oben beschrieben tun und Ihr Build-Tool (webpack oder gulp oder irgendetwas anderes) die .ts-Dateien aus .xlf-Dateien erstellen lassen. – Stnaire

+2

Es löst das Problem nicht wirklich, aber haben Sie in Betracht gezogen, das weit verbreitete nx-translate-Modul zu verwenden? https://github.com/ngx-translate/core –

Antwort

1

Eine Lösung besteht darin, Pakete für jede Sprache vorab zu erstellen, und ein Proxy erkennt, welches Paket als Standard dienen soll.

Vom Angular docs on i8n:

Merge mit dem AOT-Compiler Die AOT (Ahead-of-Time) Compiler ist Teil eines Build-Prozesses, der eine kleine, schnelle, ready-to-run produziert Anwendung Paket.

Wenn Sie mit den AOT-Compiler internationalisieren, müssen Sie ein separates Anwendungspaket für jede Sprache und dienen dazu, das entsprechende Paket basierend auf jeder serverseitigen Spracherkennung oder URL-Parameter Pre-Build.

Sie müssen auch den AOT-Compiler anweisen, Ihre Übersetzung -Datei zu verwenden. Dazu verwenden Sie drei Optionen mit den Befehlen ng serve oder ng build :

--i18nFile: Der Pfad zur Übersetzungsdatei. --i18nFormat: Das Format der Übersetzungsdatei. --locale: die Gebietsschema-ID. Das folgende Beispiel zeigt, wie die Französisch-Sprachdatei in früheren Abschnitten dieses Handbuch beliefern:

ng build --aot --i18nFile=src/locale/messages.fr.xlf --i18nFormat=xlf --locale=fr 
+0

Das ist die richtige Antwort, denke ich. Die Lösung besteht einfach darin, die serverseitige Version Ihrer App mit den entsprechenden Befehlszeilenoptionen zu erstellen, um das Gebietsschema und die Übersetzungen einzubetten, im Wesentlichen genau die gleiche Aktivität wie bei der Erstellung des Browserpakets für die i18n-Unterstützung. Denken Sie daran, dass Sie für jedes Gebietsschema eine Knoten-App (Server- und Browser-Bundle) erstellen und zwischen ihnen mit einem Proxy oder ähnlichem wechseln müssen, sodass eine erweiterte Backend-Konfiguration erforderlich ist. – WildService

Verwandte Themen