web-dev-qa-db-fra.com

Comment pouvez-vous mettre en œuvre une approche de base de données pour Angular internationalisation?

J'ai lu le guide Angular i8n ici: https://angular.io/guide/i18n

J'aime les concepts, en utilisant des balises et des astuces dans le fichier.

Je n'aime pas que les ressources de texte soient bloquées dans un format de fichier étrange, facile à traduire une fois, mais très difficile à gérer par des externes.

Existe-t-il un moyen assez simple d’utiliser la façon dont Angular prend en charge i8n, mais remplace les fichiers texte statiques par des appels à une base de données - ou même quelque chose comme un fichier json généré par une base de données?

13
Kjensen

Voici mon approche concernant le traitement de i18n, y compris l'utilisation de ngx-translate lors du chargement des traductions à partir de la base de données database.

En ce qui concerne les traductions, mon backend et mon frontend sont séparés. Les traductions sont not incluses dans une version angulaire ou un ensemble de serveurs, mais via un appel HTTP repos qui a obtenu les informations du database sous-jacent. Toutes les traductions sont chargées au démarrage, insérées dans une structure JSON et peuvent ensuite être livrées au client, où ngx-translate s'occupe du reste. Voici un ordre simple d'événements pour charger avec succès la traduction depuis une base de données et la rendre accessible à le frontend.

  1. traductions sûres dans la base de données
  2. charger les traductions au démarrage du système (ou mettre en œuvre un mécanisme de rechargement, éventuellement via REST)
  3. mapper les traductions en objets JSON paire paire valeur-valeur
  4. rendre les objets JSON accessibles via une api REST
  5. frontend charge les objets JSON via cette api REST
  6. utiliser un objet JSON dans un angle avec ngx-translate

avantages

J'expliquerai plus tard à quoi cela peut ressembler, juste une petite note sur les avantages de cette approche base de données-repos-apport:

  • toutes les traductions stockées au même endroit (une seule table)
  • les traductions manquantes pour une langue peuvent être évitées (contrôles NULL)
  • l'attribution de double clé peut être évitée (PRIMARY KEY)
  • mise à jour des traductions pendant l'exécution est possible
  • le processus de traduction peut se dérouler en dehors du projet (la mise à jour des fichiers dans la structure du projet n'est pas nécessaire)

Voyons comment cela peut être réalisé.

base de données

Les traductions sont généralement constituées de simples paires de valeurs-clés basées sur des fichiers de traduction, ce que je n’ai jamais vraiment aimé. Alors au lieu de cela, je sauvegarde mes traductions dans une seule table avec une colonne clé et une colonne traduction pour chaque langue que je connais, par exemple quelque chose comme KEY | EN | FR | DE avec des valeurs telles que button.close | close | près | schließen. La clé représente la même clé que dans un fichier normal, mais au lieu d'un fichier séparé par langue, les traductions sont enregistrées dans une seule colonne.

mappage d'arrière-plan aux objets JSON

J'aime charger toute la table à la fois pour préparer toutes les langues pour la livraison frontale à la fois. Cela peut généralement être fait une fois au démarrage du serveur et le résultat peut être conservé en mémoire afin d'éviter de nombreux appels à la base de données. La table doit être séparée en objets JSON paire paire valeur-valeur pour chaque colonne de langue. Chaque objet langage obtenu contient ensuite les clés de la base de données en tant que clés et les traductions en tant que valeurs. 

var EN = {
    ...
    "button.close": "close",
    ...
}
var FR = {
    ...
    "button.close": "près",
    ...
}
var DE = {
    ...
    "button.close": "schließen",
    ...
}

Ceci est juste un mappage tableau à objet qui, selon la langue du serveur, est généralement assez simple (je peux partager mon code pour node.js si nécessaire). Le résultat est une liste d'objets du langage JSON, chacun ayant sa traduction sous forme de paires clé-valeur, qui peuvent ensuite être consultés.

Appel de repos HTTP

Les traductions ont maintenant à peu près le même format qu'un fichier de traduction normal (paires clé-valeur), elles sont simplement conservées en mémoire et non dans un fichier. Avec un simple appel HTTP api pour une langue spécifique, vous pouvez accéder à cette liste, prendre l'objet de traduction de cette langue et l'envoyer directement à l'interface. Voici un exemple node.js express.

translationRouter.route('/:lang').get(function (request, response) {
    // load translation key-value-pair object for requested language
    response.send(translationService.getTranslations(request.params.lang));
});

ngx-translate

Le chemin ngx-translate est assez simple. Les traductions sont chargées dans l'application angulaire, les clés de traduction sont spécifiées dans l'application, puis remplacées de manière dynamique par les valeurs de traduction de la langue fournie. Comme indiqué par d’autres, il prend en charge différentes manières de charger les traductions, par exemple d’anciens fichiers de traduction ordinaires ou des chargeurs auto-installés, comme les chargeurs HTTP. Voici un chargeur HTTP simple qui charge les traductions via un appel REST (voir ci-dessus).

import { TranslateLoader } from '@ngx-translate/core';
import { Observable } from 'rxjs/Observable';
import { HttpClient } from '@angular/common/http';
import '../rxjs-operators';

export class TranslationLoader implements TranslateLoader {
    constructor(private http: HttpClient) { }

    getTranslation(lang: string): Observable<any> {
        return this.http.get("/api/translation/" + lang);
    }
}

La seule astuce consiste à spécifier ce chargeur en tant que chargeur principal, ce qui peut être fait dans le module app.module. Voici un exemple qui utilise le chargeur HTTP ci-dessus (et fonctionne également pour AOT).

import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
export function HttpLoaderFactory(http: HttpClient) {
    return new TranslationLoader(http);
}
...
@NgModule({
    imports: [..., 
        TranslateModule.forRoot({
            loader: {
                provide: TranslateLoader,
                useFactory: (HttpLoaderFactory),
                deps: [HttpClient]
            }
        }), ...]
})

Au lieu de demander un fichier, ngx-translate utilise le TranslationLoader spécifié pour obtenir ses paires clé-valeur, ce qui correspond exactement à ce que nous fournissons via notre appel repos. Peasy facile. Dans ce cas, une langue peut être spécifiée pour être chargée, plus une langue de secours au cas où une valeur ne serait pas trouvée. Voici un exemple de chargement des traductions d’une langue par défaut plus celles de la langue du navigateur.

// fallback language
this.translate.setDefaultLang('en');
// browser language
this.translate.use(this.translate.getBrowserLang());

La documentation de ngx-translate est assez bonne, il y a différentes façons de l'utiliser, par exemple via un service, une directive ou un tube, sans oublier de paramétrer les traductions.


information additionnelle

rechargement des traductions

Comme indiqué dans la liste des avantages, vous pouvez également recharger les traductions lors de l'exécution, ce qui est probablement une opération plus compliquée lors de l'intégration d'une application à la livraison. Vous pouvez simplement fournir aux administrateurs un appel HTTP de repos qui exécute exactement la même procédure de chargement de la traduction qu'au démarrage. De cette façon, les traductions peuvent être rechargées, remappées et stockées en mémoire. Les nouvelles demandes de page utiliseront automatiquement les objets de traduction rechargés.changement de langue en direct.

certaines façons d’utiliser ngx-translate autorisent les commutateurs de traduction instantanés (par exemple via la directive). De cette façon, charger une langue différente dans angular (via un simple appel this.translate.use(lang)) changera instantanément les traductions affichées sans recharger la page ou les composants visibles, ce qui est en fait assez chouette, mais ne fonctionne malheureusement pas pour tous les modes d'utilisation.

Limites de ngx-translate.

bien que ngx-translate soit vraiment facile à utiliser, il a des limites. L’une d’elles est par exemple l’utilisation de la directive ngx-translate en combinaison avec la plupart des directives angular material , car les directives de matériau angulaire (des boutons, par exemple) créeront des structures de sous-arbre et ngx-translate ne traduira que les clés sur le premier enfant (du moins je le pense). C'est donc cool à utiliser, mais parfois un peu délicat.

.



Je pense que c'est ça. J'utilise actuellement cette approche et je suis très heureux de la manière dont cela s'est passé. Cela demande un peu de travail, mais une fois que tout est en marche, cela peut être très utile.

I think that's it. I'm currently using this approach and I'm very happy with how it turned out. It's a little work to get it started but once everything is rolling it can be pretty useful.

17
Benedikt Schmidt

Je peux vous suggérer d'utiliser la bibliothèque ngx-translate (connue sous le nom de ng2-translate avant), qui possède une meilleure API que l'internationalisation intégrée à Angular ... De cette façon, vous pouvez charger des traductions à partir d'un fichier json statique (peut être généré par le backend ) ou par exemple ajoutez toml-loader et stockez vos traductions comme dans l'exemple ci-dessous (dans le fichier assets/i18n/en.toml):

[homepage]
title = "Homepage title"
contact = "Contact"

[auth]
login = "Log in"
logout = "Log out"

[settings]
settings = "Settings"
body = "<b>HTML</b> is fine here"

et l'utiliser de cette façon: 

<h2>{{'settings.settings' | translate}}</h2>
<p [innerHTML]="'settings.body' | translate"></p>
{{'auth.logout' | translate}}

Pour tout configurer, vous aurez besoin de quelques lignes de code:

import * as translation_en from 'toml-loader!../assets/i18n/en.toml';

@Injectable()
export class AppService {
    constructor(private translateService: TranslateService) {
        translateService.setDefaultLang('en');
        translateService.setTranslation('en', translation_en);
        translateService.use('en');
    }
}

J'espère que ça aide!

3
Daniel Kucal

Je vous suggère d'utiliser angular-l10n library. Ceci est une alternative open source à i18n pour la localisation angulaire. Il utilise le format JSON et prend également en charge le chargement à partir de services. Voici également le lien vers la documentation. configuration angular-l10n Recherchez "Chargement des données de traduction" sur la page pour trouver les informations sur le chargement à partir d’une API Web.

1
AlesD

N'oubliez pas que le créateur de ngx-translate fait maintenant partie de l'équipe principale de Angular i18n et que, dans le cadre de Angular 5.x, il travaille à l'amélioration de i18n. Par exemple. service de traduction, commutation de traduction en AOT, etc.

Voir ici: https://github.com/angular/angular/issues/11405#issuecomment-343933617

Je recommanderais donc de rester avec Angular i18n prêt à l'emploi. 

Pour le site Web de mon entreprise, nous utilisons Text United pour les traductions, et cela fonctionne plutôt bien ... Le seul problème que nous avons est que, par défaut, les balises HTML se retrouvent dans les outils de traduction. Notre solution est:

  • en utilisant XTB
  • Dans Text United, utilisez un analyseur XML personnalisé. Exclure les éléments ph.

Text United a payé des options pour engager des traducteurs dans n'importe quelle langue. Bien sûr, vous pouvez également le faire vous-même ... à chaque fois que vous téléchargez simplement la langue source et qu'elle correspond aux éléments déjà traduits.

1
Boland

Vous pouvez utiliser ngx-translate qui est la bibliothèque standard pour l’internationalisation dans Angular 2+

Vous pouvez importer la bibliothèque et créer un ensemble de fichiers json contenant les traductions et le placer dans le dossier assets.

Ensuite, vous pouvez le référencer dans le HTML. dis par exemple.

en.json a,

"guest.first-name": "first Name",

où le premier est la clé et le second est la valeur à afficher. et vous pouvez vous référer dans le HTML comme,

<input  [label]="'guest.first-name' | translate" type="text" name="form_name" [(ngModel)]="firstName" required="required" ></input>
1
Sajeetharan

Dans mon projet, les littéraux de chaîne (internationalisation requise) sont stockés dans un fichier séparé au format x.y.z="Hello World". Nous avons développé un script pour traduire cette chaîne en objet JSON en tant que

x { y { z: { default: "Hello World" } } }

nous avons ensuite utilisé la bibliothèque "ng2-translate" pour utiliser ce fichier JSON en vue de l'internationalisation dans le projet angular 4.

0
Ashish Patel