Cómo internacionalizar una aplicación Angular con angular-cli

Translation into Spanish of an interesting article by Philippe Martin, a French software engineer working for Red Hat.

ANGULARinternationalizationtranslation into spanish
15 April, 2022 Translate an Angular app using angular-cli
15 April, 2022 Translate an Angular app using angular-cli

A translation by Chema, a Spanish translator specializing in technical English to Spanish translations

An original text written by Philippe Martin, originally published in
https://feloy.medium.com/deploying-an-i18n-angular-app-with-angular-cli-fc788f17e358

* * *

Existe una revisión más reciente de este artículo publicada en: https://dev.to/angular/deploying-an-i18n-angular-app-with-angular-cli-2fb9

Explicaré en este artículo cómo crear desde cero una aplicación Angular internacionalizada (i18n) mediante angular-cli, y cómo implementarla en un servidor web Apache.

Utilizaremos:

  • angular/cli: 1.0.0
  • angular: 4.0.0
  • apache 2.4

La aplicación descrita está disponible en: https://github.com/feloy/angular-cli-i18n-sample

Una nueva aplicación i18n

Primero creamos una nueva aplicación Angular con la ayuda de angular-cli:

$ ng nuevo angular-cli-i18n-muestra

Realizamos algunos cambios para agregar texto traducible, en app.component.html:

<h1 i18n > ¡Hola, mundo! </h1>

Ahora necesitamos crear un xlfarchivo con las cadenas traducibles. Podemos generar el archivo src/i18n/messages.xlfcon el siguiente comando:

$ ng xi18n --output-path src/i18n

Ahora creamos traducciones para diferentes idiomas, aquí en inglés con un archivo nuevo src/i18n/messages.en.xlfcopiado de src/i18n/messages.xlf:

[...] 
<trans-unit id="[...]" datatype="html">
<source>¡Hola mundo!</source>
<target>¡Hola mundo!</target>
</trans-unit>
[...]

en francés con src/i18n/messages.fr.xlf:

[...] 
<trans-unit id="[...]" datatype="html">
<source>¡Hola mundo!</source>
<target>Salut la foule!</target>
</trans-unit >
[...]

y en español con src/i18n/messages.es.xlf:

[...] 
<trans-unit id="[...]" datatype="html">
<source>¡Hola Mundo!</source>
<target>¿hola, qué tal?</target>
</trans -unidad>
[...]

Ahora angular-cli puede servir la aplicación con el idioma elegido, aquí por ejemplo en español:

$ ng servir --aot \ 
--i18n-file=src/i18n/messages.es.xlf \
--locale=es \
--i18n-format=xlf

¡Accede a la aplicación en http://localhost:4200y verás que efectivamente muestra la cadena en español!

Preparación de la aplicación para producción

En producción, nos gustaría que la aplicación estuviera ordenada en diferentes subdirectorios, según el idioma; por ejemplo, la versión en español estaría accesible en http://myapp.com/es/y la francesa en http://myapp.com/fr/También nos gustaría contar con una redirección desde la url base http://myapp.com/a la url del idioma escogido.

Para esto necesitamos cambiar el href base a esenfr, según el idioma de destino. Pero angular-cli tiene una opción de línea de comando especial para esto, --bh,que permite declarar el href base en el momento de la compilación desde la línea de comandos.

Usuarios de Linux/macOS

Aquí está el comando Shell que podemos usar para crear los diferentes paquetes de los diferentes idiomas:

$ para lang en es en fr; hacer \ 
ng build --output-path=dist/$lang \
--aot \
-prod \
--bh /$lang/ \
--i18n-file=src/i18n/messages.$lang.xlf \
--i18n -formato=xlf \
--locale=$idioma; \
hecho

Podemos crear una definición de script package.jsonpara este comando y ejecutarlo con npm run build-i18n:

{ 
[...]
"scripts": {
[...]
"build-i18n": " for lang in en es fr; do ng build --output-path=dist/$lang --aot -prod -- bh /$lang/ --i18n-file=src/i18n/messages.$lang.xlf --i18n-format=xlf --locale=$lang; done "
}
[...]
}

En este punto tenemos tres directorios en/, es/ y fr/ en el directorio dist/, que contiene los diferentes paquetes.

Usuarios de Windows

Como usuario de Windows, puedes usar estos comandos para crear los diferentes paquetes para cada idioma:

> ng build --output-path=dist/fr --aot -prod --bh /fr/ --i18n-file=src/i18n/messages.fr.xlf --i18n-format=xlf --locale=fr

> ng build --output-path=dist/es --aot -prod --bh /es/ --i18n-file=src/i18n/messages.es.xlf --i18n-format=xlf --locale=es

> ng build --output-path=dist/en --aot -prod --bh /en/ --i18n-file=src/i18n/messages.en.xlf --i18n-format=xlf --locale=en

Podemos crear definiciones de script package.jsonpara estos comandos y una adicional para ejecutar todos estos comandos a la vez y ejecutar el último con npm run build-i18n:

"scripts": { 
"build-i18n:fr": "ng build --output-path=dist/fr --aot -prod --bh /fr/ --i18n-file=src/i18n/messages.fr. xlf --i18n-format=xlf --locale=fr",
"build-i18n:es": "ng build --output-path=dist/es --aot -prod --bh /es/ --i18n- file=src/i18n/messages.es.xlf --i18n-format=xlf --locale=es",
"build-i18n:en": "ng build --output-path=dist/en --aot -prod --bh /en/ --i18n-file=src/i18n/messages.en.xlf --i18n-format=xlf --locale=en",
"build-i18n": "npm run build-i18n:en && npm ejecuta build-i18n:es && npm ejecuta build-i18n:fr"
}

Configuración en Apache2

Aquí hay una configuración de host virtual que servirá los diferentes paquetes desde el directorio /var/: deberás copiar allí los tres directorios en/, es/ y fr/ generados anteriormente.

Con esta configuración, la url http://www.myapp.redirige al subdirectorio del idioma preferido definido en la configuración de su navegador (o lleva al idioma por defecto –en-,si no se encuentra un idioma preferido) y aún tiene acceso a los otros idiomas accediendo a los otros subdirectorios.

<VirtualHost *:80> 
ServerName www.myapp.com
DocumentRoot /var/www
<Directorio "/var/www">
RewriteEngine en
RewriteBase / Regla de reescritura ^../index\.html$ - [L] RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (..) $1/index.html [L] RewriteCond %{HTTP:Accept-Language} ^fr [NC]
RewriteRule ^$ /fr/ [R] RewriteCond %{HTTP:Accept-Language} ^es [NC]
RewriteRule ^$ /es/ [R] RewriteCond %{HTTP:Accept-Language} !^es [NC]
RewriteCond %{HTTP:Accept-Language} !^fr [NC]
RewriteRule ^$ /en/ [R]
</Directory>
</VirtualHost>

Bonus 1: enlaces a los diferentes idiomas

Sería interesante tener algunos enlaces en la aplicación para que el usuario pueda navegar a otros idiomas. Los enlaces apuntarán a /en//es//fr/.

Un dato útil: el idioma actual está disponible en el LOCALE_IDtoken.

Así es como puede obtener el LOCALE_IDvalor y mostrar la lista de idiomas, diferenciando el idioma actual:

// aplicación.componente.ts

importar { Componente, LOCALE_ID, Inyectar } desde ' @angular/core ';

@Component ({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})

exportar clase AppComponent {
idiomas = [
{ código: 'en', etiqueta: 'English'},
{ código: 'es', etiqueta: 'Español'},
{ código: 'fr', etiqueta: 'Français'}
];
constructor( @Inject (LOCALE_ID) protegido localeId: cadena) {}
}

<!-- aplicación.componente.html --><h1 i18n>¡Hola, mundo!</h1>
<template ngFor let-lang [ngForOf]="languages">
<span *ngIf="lang.code !== localeId">
<a href="/{{lang. código}}/">{{lang.label}}</a> </span>
<span *ngIf="lang.code === localeId">{{lang.label}} </span>
</template >

Bonus 2: i18n después de la expulsión

Desde angular-cli es posible exportar una configuración de paquete web para un idioma en particular. Aquí está el comando para exportar la configuración del paquete web para el idioma inglés. Ten en cuenta que el comando es muy similar al comando ng buildcomando utilizado anteriormente:

ng eject \ 
--output-path=dist/en \
--aot \
-prod \
--bh /en/ \
--i18n-file=src/i18n/messages.en.xlf \
--i18n-format=xlf \
--locale=es

Este comando creará un archivo webpack.config.jsque se usará para construir la versión en inglés cuando se ejecute el comando npm run build.

Ahora puedes copiar este archivo webpack.config.en 3 archivos distintos para los 3 idiomas diferentes, por ejemplo webpack.en.config.jswebpack.es.config.jswebpack.fr.config.js, y luego adaptar estos archivos específicos para cada idioma específico. Aquí está el resultado de un diffdespués de los cambios requeridos para el idioma francés:

--- webpack.config.js 
+++ webpack.fr.config.js
@@ -44,7 +44,7 @@
]
},
"salida": {
- "ruta": ruta.join(proceso.cwd (), "dist/ en "),
+ "ruta": ruta.join(proceso.cwd(), "dist/ fr "),
"nombre de archivo": "[nombre].[chunkhash:20].bundle.js ",
"chunkFilename": "[id].[chunkhash:20].chunk.js"
},
@@ -220,7 +220,7 @@
}
}),
nuevo BaseHrefWebpackPlugin({
- "baseHref": "/ en /"
+ "baseHref": "/ fr /"
}),
nuevo CommonsChunkPlugin({
"nombre": "en línea",
@@ -283,9 +283,9 @@
new AotPlugin({
"tsConfigPath": "src/tsconfig.json",
"mainPath": "main.ts",
- "i18nFile": "src/i18n/messages. en .xlf",
+ "i18nFile": "src/i18n/messages. fr .xlf",
"i18nFormat": "xlf",
- "locale": " en ",
+ "locale": " fr ",
"hostReplacementPaths ": {
"entornos/entorno.ts": "entornos/entorno.prod.ts"
},

También debes modificar el archivopackage.para que el comando ejecute el webpack de cada configuración:

{ 
[...]
"scripts": {
[...]
"construir": "webpack --config webpack.fr.config.js && webpack --config webpack.en.config.js && webpack --config webpack .es.config.js"
}
[...]
}

Ahora puedes ejecutar npm run buildpara generar los tres paquetes en dist/enndist/esdist/fr.

Bonus 3: aplicación de traductor angular

Este fin de semana para AngularAttack 2017, he creado una aplicación que definitivamente puede ayudar a traducir aplicaciones Angular. Todavía está en desarrollo, cualquier comentario será bienvenidos: http://angular-translator.elol.fr/ .

¡Buenas traducciones!

Valora este artículo