Skip to content
Snippets Groups Projects
internationalisation.service.ts 6.82 KiB
Newer Older
David Dorchies's avatar
David Dorchies committed
import { Injectable } from "@angular/core";
import { Response } from "@angular/http";
import { Message, MessageCode, Observable } from "jalhyd";
import { StringMap } from "../../stringmap";
David Dorchies's avatar
David Dorchies committed
import { ServiceFactory } from "../service-factory";
/*
  language tag : fr-FR
  primary subcode : fr
  optional subcode : FR
 */

export class Language {
    private _code: LanguageCode;
    private _tag: string;
    private _label: string;

    constructor(c: LanguageCode, t: string, l: string) {
        this._code = c;
        this._tag = t;
        this._label = l;
    }

    get code(): LanguageCode {
        return this._code;
    }

    get tag(): string {
        return this._tag;
    }

    get label(): string {
        return this._label;
    }
}

export class InternationalisationService extends Observable {
        super();
        this._languages = [];
        this._languages.push(new Language(LanguageCode.FRENCH, "fr", "Français"));
        this._languages.push(new Language(LanguageCode.ENGLISH, "en", "English"));
    public get languages() {
        return this._languages;
    }
    public get currentLanguage() {
        return this._currLang;
    }
    public get currentMap() {
        return this._Messages;
    }

    private getLanguageFromCode(lc: LanguageCode) {
David Dorchies's avatar
David Dorchies committed
        for (const l of this._languages) {
            if (l.code === lc) {
David Dorchies's avatar
David Dorchies committed
            }
        throw new Message(MessageCode.ERROR_LANG_UNSUPPORTED);
    private getLanguageFromTag(tag: string) {
David Dorchies's avatar
David Dorchies committed
        for (const l of this._languages) {
            if (l.tag === tag) {
David Dorchies's avatar
David Dorchies committed
            }
David Dorchies's avatar
David Dorchies committed
        const e = new Message(MessageCode.ERROR_LANG_UNSUPPORTED);
    public setLocale(lng: string | LanguageCode) {
David Dorchies's avatar
David Dorchies committed
        let oldLang;
        if (this._currLang !== undefined) {
            oldLang = this._currLang.code;
        }
David Dorchies's avatar
David Dorchies committed
            const t: string = lng.substr(0, 2).toLowerCase();
            this._currLang = this.getLanguageFromTag(t);
David Dorchies's avatar
David Dorchies committed
        } else {
            this._currLang = this.getLanguageFromCode(lng);
        if (this._currLang.code !== oldLang) {
            this._Messages = undefined;
            const prom = this.httpGetMessages();

            const is: InternationalisationService = this;
            prom.then((res) => {
                is.notifyObservers(undefined);
David Dorchies's avatar
David Dorchies committed
            });
    private httpGetMessages(): Promise<Response> {
David Dorchies's avatar
David Dorchies committed
        const is: InternationalisationService = this;
        const processData = function (s: string) {
            // fermeture nécessaire pour capturer la valeur de this (undefined sinon)
David Dorchies's avatar
David Dorchies committed
        };
        switch (this._currLang.code) {
            case LanguageCode.FRENCH:
        const f: string = "messages." + l + ".json";
        return ServiceFactory.instance.httpService.httpGetRequest(undefined, undefined, undefined, "locale/" + f, processData);
    private getMessageFromCode(c: MessageCode): string {
David Dorchies's avatar
David Dorchies committed
        const sCode: string = MessageCode[c];
        return this._Messages[MessageCode[c]];
    }

    private replaceAll(str: string, find: string, replace: string) {
David Dorchies's avatar
David Dorchies committed
        return str.replace(new RegExp(find, "g"), replace);
    /**
     * traduit un message
     * @param r message
     * @param nDigits nombre de chiffres à utiliser pour l'arrondi dans le cas de données numériques
     */
    public localizeMessage(r: Message, nDigits: number = 3): string {
David Dorchies's avatar
David Dorchies committed
        const sCode: string = MessageCode[r.code];
        let m: string = this.getMessageFromCode(r.code);
David Dorchies's avatar
David Dorchies committed
        for (const k in r.extraVar) {
            if (r.extraVar.hasOwnProperty(k)) {
                const v: any = r.extraVar[k];
                let s: string;
                if (typeof v === "number") {
                    s = v.toFixed(nDigits);
                } else {
                    s = v;
                }
                m = this.replaceAll(m, "%" + k + "%", s);
            }
David Dorchies's avatar
David Dorchies committed
     * Traduit un texte défini dans un fichier de langue (locale/error_message.xx.json par défaut)
     * Les ids dans ces fichiers sont soit un enum de JalHyd, soit une chaine libre correspondant au code passé àlocalizeText()
     * @param code id du texte
David Dorchies's avatar
David Dorchies committed
     * @param messages Contenu du fichier de langua à utiliser (locale/error_message.xx.json par défaut)
David Dorchies's avatar
David Dorchies committed
    public localizeText(code: string, messages = this._Messages) {
        if (messages === undefined) {
David Dorchies's avatar
David Dorchies committed
        if (messages[code] === undefined) {
            return `*** message not exists: ${code} ***`;
David Dorchies's avatar
David Dorchies committed
        return messages[code];
    /**
     * analyse un libellé du type ouvrage[n].XX
     */
    private parseLabel(lbl: string) {
        const re = /([A-Z,a-z]+)\[(\d+)\]\.(.+)/;
        return re.exec(lbl);
    }

    /**
     * Traduit un libellé qui peut être un code
        const key = "INFO_EXTRARES_LIB_";
        const match = this.parseLabel(s);
        if (match) {
            // Code du type "Ouvrage[n].XXX"
            // Les libellés correspondants sont INFO OUVRAGE et INFO_EXTRARES_LIB_OUVRAGE_XXX
            return this.localizeText(`INFO_${match[1].toUpperCase()}`) + "" + (+match[2] + 1) + ": " +
                this.localizeText(`${key}${match[1].toUpperCase()}_${match[3].toUpperCase()}`);
        } else {
            // Autres codes INFO_EXTRARES_LIB_XXX
            return this.localizeText(`${key}${s.toUpperCase()}`);

    /**
     * met en forme ou traduit un résultat en fonction du libellé qui l'accompagne
     * @todo Il manque un formalisme clair permettant de différencier les valeurs numériques des ENUM
     */
    public formatResult(label: string, value: number): string {
        const match = this.parseLabel(label);
        if (match) {
            if (match[3] !== "Q") { // Le débit est une valeur numérique, tous les autres sont des ENUM ???
                // Label du type ouvrage[n].XXX => message INFO_EXTRARES_ENUM_OUVRAGE_XXX_value
                return this.localizeText(`INFO_EXTRARES_ENUM_${match[1].toUpperCase()}_${match[3].toUpperCase()}_${value}`);
        const appSetupService = ServiceFactory.instance.applicationSetupService;
        const nDigits = appSetupService.displayDigits;
        return value.toFixed(nDigits);
    }