Cet article présente principalement la méthode d'internationalisation des projets Angular. Maintenant, je le partage avec vous et vous donne une référence.
Comme le dit le site officiel d'Angular, l'internationalisation d'un projet est une tâche difficile qui nécessite des efforts multiformes, un dévouement et une détermination durables.
Cet article présentera le plan d'internationalisation du projet angulaire, impliquant l'internationalisation de fichiers statiques (html) et la rédaction de fichiers ts.
Angulaire : 5.0
Cli angulaire : 1.6.1(1.5.x Également disponible)
NG-ZORRO : 0.6.8
Modèle i18n Le processus de traduction comporte quatre étapes :
Marquez les informations de texte statique qui doivent être traduites dans le modèle de composant (c'est-à-dire ajoutez la balise i18n).
L'outil i18n d'Angular extrait les informations balisées dans un fichier source de traduction standard de l'industrie (tel qu'un fichier .xlf, en utilisant ng xi18n).
Le traducteur édite le fichier, traduit les informations textuelles extraites dans la langue cible et vous renvoie le fichier (nécessite un accès traducteur, cet article utilise le fichier xlf pour la sortie du fichier au format json , et enfin reconvertir le fichier json au format xlf).
Le compilateur Angular importe le fichier traduit, remplace les informations d'origine par le texte traduit et génère une nouvelle version en langue cible de l'application.
Vous pouvez créer et déployer des versions de projet distinctes pour chaque langue prise en charge en remplaçant simplement les fichiers XLF traduits.
Comment l'utiliser dans un fichier modèle ?
i18n propose plusieurs façons de l'utiliser, et propose également des méthodes de traduction pour les nombres singuliers et pluriels (je ne l'ai pas utilisé personnellement, donc je trouve cela peu pratique). Ensuite, un fichier HTML distinct sera utilisé pour présenter plusieurs méthodes d'utilisation.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Angular i18n</title> </head> <body> <h1 i18n="Site Header|An introduction header for i18n Project@@stTitle">Angular 国际化项目</h1> <p> <span i18n="@@agDescription">国际化是一项很具有挑战性,需要多方面的努力、持久的奉献和决心的任务。</span> <span class="delete" i18n-title="@@agDelete" title="删除"></span> </p> <p><ng-container i18n=@@agLetGo>让我们现在开始吧!</ng-container>朋友!</p> </body> </html>
Le code ci-dessus montre plusieurs façons d'utiliser i18n :
1. Utilisez les balises d'attribut i18n (une copie explicative peut être ajoutée, au format : title|description@@id, title et la description peut aider les traducteurs à mieux comprendre la signification de la copie. Le fait de les ajouter dépend des circonstances du projet)
peut être directement étiqueté avec i18n sur la balise statique, comme
<span i18n="@@agDescription"></span>
généré Le format du champ xlf (xml) est
<trans-unit id="agDescription" datatype="html"> <source>国际化是一项很具有挑战性,需要多方面的努力、持久的奉献和决心的任务。</source> <context-group purpose="location"> <context context-type="sourcefile">xxx.ts</context> <context context-type="linenumber">linenum</context> </context-group> </trans-unit>
2. Ajoutez des attributs i18n pour le titre
Pour les attributs de balise html, vous pouvez également ajouter i18n, tel que
<span class="delete" i18n-title="@@agDelete" title="删除"></span>
Le format xlf (xml) généré est le même que ci-dessus
3. Traduire le texte sans créer d'éléments
Nous avons parfois plusieurs fragments de phrase dans une seule phrase If span. et l'étiquette sont ajoutés à chaque fois. Si l'élément est enveloppé, cela peut sérieusement affecter la mise en page. À ce stade, nous pouvons utiliser ng-container pour envelopper la copie qui doit être traduite.
<p> <ng-container i18n=@@agLetGo>让我们现在开始吧!</ng-container>朋友! </p>
s'affiche sur la page sous la forme
<p> <!----> LET'S GO朋友! </p>
* ng-container devient un bloc de commentaires, ce qui n'affectera pas la mise en page (surtout lorsque le style est appliqué)
Après le balisage, il suffit d'exécuter ng xi18n pour créer automatiquement un fichier xlf, généralement message.xlf. Si vous avez besoin de le personnaliser, vous pouvez vous rendre sur le site officiel d'Angular CLI pour le visualiser.
Conversion XLF et JSON
Méthode xlf vers json
J'utilise personnellement la bibliothèque xml2js pour fonctionner, le code simple est le suivant :
const fs = require('fs'); xml2js = require('xml2js'); var parser = new xml2js.Parser(); fs.readFile(fileName, 'utf8', (err, data) => { parser.parseString(data, function (err, result) { // 读取新文件全部需要翻译的数据,并对比已翻译的进行取舍,具体转换成的格式结构可自行查看 result['xliff']['file'][0]['body'][0]['trans-unit'].forEach((item) => { var itemFormat = { "key" : item['$']['id'], "value": item['source'][0] }; // 执行相关操作,key-value形式是为了统一翻译文件结构,可按需定义 }) }); });
Méthode json vers xlf
function backToXLF(translatedParams) { // 文件格式可自行参考angular.cn官网的例子 var xlfFormat = { "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": [] } ] } ] } }; if (translatedParams instanceof Array) { // 获取原始名称 translatedParams.forEach((data) => { var tmp = { "$" : { "id" : data.key, "datatype": "html" }, "source": [i18nItemsOrigin[data.key]], // 这里的i18nItemsOrigin是json格式,属性名为key值,表示原始文案 "target": [data.value] }; // 数组,json项 xlfFormat['xliff']['file'][0]['body'][0]['trans-unit'].push(tmp); }); } var builder = new xml2js.Builder(); var xml = builder.buildObject(xlfFormat); return xml; }
De cette manière, l'extraction des informations de copie et la conversion du fichier traduit sont terminées. Ensuite, nous devons appliquer la copie traduite au projet. .
Créez un dossier de paramètres régionaux dans le répertoire src et enregistrez le fichier demo.en-US.xlf traduit dans le répertoire modifié
Créez un nouveau fichier i18n-providers.ts
import { LOCALE_ID, MissingTranslationStrategy, StaticProvider, TRANSLATIONS, TRANSLATIONS_FORMAT } from '@angular/core'; import { CompilerConfig } from '@angular/compiler'; import { Observable } from 'rxjs/Observable'; import { LOCALE_LANGUAGE } from './app.config'; // 自行定义配置位置 export function getTranslationProviders(): Promise<StaticProvider[]> { // get the locale string from the document const locale = LOCALE_LANGUAGE.toString(); // return no providers const noProviders: StaticProvider[] = []; // no locale or zh-CN: no translation providers if (!locale || locale === 'zh-CN') { return Promise.resolve(noProviders); } // Ex: 'locale/demo.zh-MO.xlf` const translationFile = `./locale/demo.${locale}.xlf`; return getTranslationsWithSystemJs(translationFile) .then((translations: string) => [ { provide: TRANSLATIONS, useValue: translations }, { provide: TRANSLATIONS_FORMAT, useValue: 'xlf' }, { provide: LOCALE_ID, useValue: locale }, { provide: CompilerConfig, useValue: new CompilerConfig({ missingTranslation: MissingTranslationStrategy.Error }) } ]).catch(() => noProviders); // ignore if file not found } declare var System: any; // 获取locale文件 function getTranslationsWithSystemJs(file: string) { let text = ''; const fileRequest = new XMLHttpRequest(); fileRequest.open('GET', file, false); fileRequest.onerror = function (err) { console.log(err); }; fileRequest.onreadystatechange = function () { if (fileRequest.readyState === 4) { if (fileRequest.status === 200 || fileRequest.status === 0) { text = fileRequest.responseText; } } }; fileRequest.send(); const observable = Observable.of(text); const prom = observable.toPromise(); return prom; }
main.ts dans le dossier de l'application et modifiez-le en
import { enableProdMode } from '@angular/core'; import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; import { AppModule } from './app/app.module'; import { environment } from './environments/environment'; import { getTranslationProviders } from './app/i18n-providers'; if (environment.production) { enableProdMode(); } getTranslationProviders().then(providers => { const options = { providers }; platformBrowserDynamic().bootstrapModule(AppModule, options) .catch(err => console.log(err)); });
N'oubliez pas d'ajouter le répertoire de paramètres régionaux à .angular-cli.json Venez l'emballer séparément.
De cette façon, notre traduction de copie statique est pratiquement terminée, mais comment devrions-nous traduire une copie dynamique telle qu'une copie dans des fichiers ts ou des attributs de frame tiers ? Ce qui suit présentera la solution de traduction de copie dynamique pour les fichiers ts et le framework NG-ZORRO.
Idées spécifiques
Appelez la méthode Service via Pipe et faites correspondre json en fonction de l'unique correspondant valeur id Les résultats de la traduction dans l'objet sont ensuite renvoyés au front-end pour le rendu, faisant référence au plan de mise en œuvre international du framework NG-ZORRO.
Nous définissons d'abord le format de l'objet de traduction json, qui est une structure à trois couches. Les variables dynamiques doivent être enveloppées par %%. La raison en est qu'elle est liée à la structure du projet et également. facilite l'unification du format avec i18n ultérieurement.
{ "app": { "base": { "hello": "文件文案", "userCount": "一共%num%人" } } }
Le format a été décidé, nous continuons à définir la méthode de traitement du Service
La solution d'internationalisation de NG-ZORRO est réutilisée ici, ce qui peut simplifier notre développement Si vous êtes intéressé. , vous pouvez vous référer à son code source .
*** TranslateService *** import { Injectable } from '@angular/core'; // 引入语言配置和国际化文件文案对象 import { LOCALE_LANGUAGE } from '../app.config'; import { enUS } from '../locales/demo.en-US'; import { zhCN } from '../locales/stream.zh-CN'; @Injectable() export class TranslateService { private _locale = LOCALE_LANGUAGE.toString() === 'zh-CN' ? zhCN : enUS; constructor() { } // path为app.base.hello格式的字符串,这里按json层级取匹配改变量 translate(path: string, data?: any): string { let content = this._getObjectPath(this._locale, path) as string; if (typeof content === 'string') { if (data) { Object.keys(data).forEach((key) => content = content.replace(new RegExp(`%${key}%`, 'g'), data[key])); } return content; } return path; } private _getObjectPath(obj: object, path: string): string | object { let res = obj; const paths = path.split('.'); const depth = paths.length; let index = 0; while (res && index < depth) { res = res[paths[index++]]; } return index === depth ? res : null; } }
De cette façon, il vous suffit d'appeler la méthode de traduction de Service dans Pipe
*** NzTranslateLocalePipe *** import { Pipe, PipeTransform } from '@angular/core'; import { TranslateService } from '../services/translate.service'; @Pipe({ name: 'nzTranslateLocale' }) export class NzTranslateLocalePipe implements PipeTransform { constructor(private _locale: TranslateService) { } transform(path: string, keyValue?: object): string { return this._locale.translate(path, keyValue); } }
D'accord, maintenant que notre logique de traitement est complètement terminée, présentons comment utiliser it
*** NG-ZORRO 控件 *** <nz-input [nzPlaceHolder]="'app.base.hello'|nzTranslateLocale"></nz-input> // 无动态参数 <nz-popconfirm [nzTitle]="'app.base.userCount'|nzTranslateLocale: {num:users.length}" ...> ... // 有动态参数 </nz-popconfirm> *** ts文件 *** export class AppComponent implements OnInit { demoTitle=''; users = ['Jack', 'Johnson', 'Lucy']; constructor(privete translateService: TranslateService) { } ngOnInit() { this.demoTitle = this.translateService.translate('app.base.hello'); } }
Le processus ci-dessus peut essentiellement répondre aux besoins d'internationalisation de la plupart des projets angulaires. Si une internationalisation plus complexe est nécessaire, la discussion est la bienvenue.
L'internationalisation d'Angular vers 5.0 a été relativement simple. Il suffit de taguer i18n à l'endroit approprié pour extraire facilement et rapidement la copie à traduire. Comment faire. Est-ce spécifiquement ? Le traitement des fichiers traduits varie d'une personne à l'autre, et plusieurs méthodes peuvent nous aider à convertir (comme cet article via nodejs).
Ce qui est plus compliqué, c'est le texte qui ne peut pas être traduit en tapant les balises i18n. La solution d'internationalisation de NG-ZORRO compense cette lacune, et lorsqu'elle est combinée, elle peut facilement compléter l'internationalisation du projet. S'il n'y a pas de support d'équipe dédié à l'internationalisation, la traduction sera très difficile, et il y a beaucoup de choses à considérer, comme le chinois traditionnel, le chinois traditionnel de Macao, le chinois traditionnel de Taiwan, etc., et la grammaire est également différente.
Répertoire de référence
Exemple en ligne d'internationalisation d'Angular (i18n)
Internationalisation locale NG-ZORRO
Ce qui précède est ce que j'ai compilé pour tout le monde Oui, j'espère que cela sera utile à tout le monde à l'avenir.
Articles associés :
Comment définir plusieurs classes à l'aide de Vue
Exemple de sélection de case à cocher et de transmission de valeur dans jQuery+SpringMVC_jquery
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!