import { Injectable } from "@angular/core"; import { Response } from "@angular/http"; import { Message, MessageCode, Observable } from "jalhyd"; import { StringMap } from "../../stringmap"; import { ServiceFactory } from "../service-factory"; /* language tag : fr-FR primary subcode : fr optional subcode : FR */ export enum LanguageCode { FRENCH, ENGLISH, } 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; } } @Injectable() export class InternationalisationService extends Observable { private _currLang: Language; private _sLang: string; private _Messages: StringMap; private _languages: Language[]; public constructor() { 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) { for (const l of this._languages) { if (l.code === lc) { return l; } } throw new Message(MessageCode.ERROR_LANG_UNSUPPORTED); } private getLanguageFromTag(tag: string) { for (const l of this._languages) { if (l.tag === tag) { return l; } } const e = new Message(MessageCode.ERROR_LANG_UNSUPPORTED); e.extraVar["locale"] = tag; throw e; } public setLocale(lng: string | LanguageCode) { let oldLang; if (this._currLang !== undefined) { oldLang = this._currLang.code; } if (typeof lng === "string") { const t: string = lng.substr(0, 2).toLowerCase(); this._currLang = this.getLanguageFromTag(t); } 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); }); } } private httpGetMessages(): Promise<void> { const is: InternationalisationService = this; const processData = function (s: string) { // fermeture nécessaire pour capturer la valeur de this (undefined sinon) is._Messages = JSON.parse(s); }; let l: string; switch (this._currLang.code) { case LanguageCode.FRENCH: l = "fr"; break; default: l = "en"; } const f: string = "messages." + l + ".json"; return ServiceFactory.instance.httpService.httpGetRequestPromise(undefined, undefined, undefined, "locale/" + f).then( (res: any) => { is._Messages = res; } ); } private getMessageFromCode(c: MessageCode): string { if (this._Messages[MessageCode[c]] === undefined) { return `*** Message ${MessageCode[c]} non traduit ***`; } return this._Messages[MessageCode[c]]; } private replaceAll(str: string, find: string, replace: string) { 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 { const sCode: string = MessageCode[r.code]; let m: string = this.getMessageFromCode(r.code); 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); } } return m; } /** * 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 * @param messages Contenu du fichier de langua à utiliser (locale/error_message.xx.json par défaut) */ public localizeText(code: string, messages = this._Messages) { if (messages === undefined) { return `*** messages not loaded: ${code} ***`; } if (messages[code] === undefined) { return `*** message not exists: ${code} ***`; } 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 */ public getExtraResLabel(s: string) { 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()}`) + " n°" + (+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 un extraResult en fonction du libellé qui l'accompagne * Les extraResult avec le terme "ENUM_" sont traduit avec le message INFO_EXTRARES_ENUM_[Nom de la variable après ENUM_] */ public formatResult(label: string, value: number): string { const match = label.indexOf("ENUM_"); if (match > -1) { return this.localizeText(`INFO_EXTRARES_${label.substring(match).toUpperCase()}_${value}`); } const nDigits = ServiceFactory.instance.applicationSetupService.displayDigits; return value.toFixed(nDigits); } }