diff --git a/src/core/siteaddons/providers/siteaddons.ts b/src/core/siteaddons/providers/siteaddons.ts index d5e030e97..1633aae7c 100644 --- a/src/core/siteaddons/providers/siteaddons.ts +++ b/src/core/siteaddons/providers/siteaddons.ts @@ -105,6 +105,20 @@ export class CoreSiteAddonsProvider { return this.ROOT_CACHE_KEY + 'content:' + component + ':' + method + ':' + JSON.stringify(args); } + /** + * Given a handler's unique name, return the prefix to add to its string keys. + * + * @param {string} handlerName Handler's unique name (result of getHandlerUniqueName). + * @return {string} Prefix. + */ + protected getHandlerPrefixForStrings(handlerName: string): string { + if (handlerName) { + return 'addon.' + handlerName + '.'; + } + + return ''; + } + /** * Given a handler's unique name and the key of a string, return the full string key (prefixed). * @@ -113,11 +127,7 @@ export class CoreSiteAddonsProvider { * @return {string} Full string key. */ protected getHandlerPrefixedString(handlerName: string, key: string): string { - if (name) { - return 'addon.' + handlerName + '.' + key; - } - - return ''; + return this.getHandlerPrefixForStrings(handlerName) + key; } /** @@ -181,6 +191,25 @@ export class CoreSiteAddonsProvider { return false; } + /** + * Load the lang strings for a handler. + * + * @param {any} addon Data of the addon. + * @param {string} handlerName Name of the handler in the addon. + * @param {any} handlerSchema Data about the handler. + */ + loadHandlerLangStrings(addon: any, handlerName: string, handlerSchema: any): void { + if (!handlerSchema.lang) { + return; + } + + for (const lang in handlerSchema.lang) { + const prefix = this.getHandlerPrefixForStrings(this.getHandlerUniqueName(addon, handlerName)); + + this.langProvider.addSiteAddonsStrings(lang, handlerSchema.lang[lang], prefix); + } + } + /** * Load a site addon. * @@ -209,6 +238,8 @@ export class CoreSiteAddonsProvider { * @param {any} handlerSchema Data about the handler. */ registerHandler(addon: any, handlerName: string, handlerSchema: any): void { + this.loadHandlerLangStrings(addon, handlerName, handlerSchema); + switch (handlerSchema.delegate) { case 'CoreMainMenuDelegate': this.registerMainMenuHandler(addon, handlerName, handlerSchema); diff --git a/src/providers/lang.ts b/src/providers/lang.ts index f8b62fae2..71fc34ca0 100644 --- a/src/providers/lang.ts +++ b/src/providers/lang.ts @@ -28,8 +28,9 @@ import { Observable } from 'rxjs'; export class CoreLangProvider { protected fallbackLanguage = CoreConfigConstants.default_lang || 'en'; protected currentLanguage: string; // Save current language in a variable to speed up the get function. - protected customStrings = {}; + protected customStrings = {}; // Strings defined using the admin tool. protected customStringsRaw: string; + protected siteAddonsStrings = {}; // Strings defined by site addons. constructor(private translate: TranslateService, private configProvider: CoreConfigProvider, platform: Platform, private globalization: Globalization) { @@ -43,8 +44,47 @@ export class CoreLangProvider { moment.locale(language); }); }); + } - this.decorateTranslate(); + /** + * Add a set of site addons strings for a certain language. + * + * @param {string} lang The language where to add the strings. + * @param {any} strings Object with the strings to add. + * @param {string} [prefix] A prefix to add to all keys. + */ + addSiteAddonsStrings(lang: string, strings: any, prefix?: string): void { + // Initialize structures if they don't exist. + if (!this.siteAddonsStrings[lang]) { + this.siteAddonsStrings[lang] = {}; + } + if (!this.translate.translations[lang]) { + this.translate.translations[lang] = {}; + } + + for (const key in strings) { + const prefixedKey = prefix + key, + value = strings[key]; + + if (this.customStrings[lang] && this.customStrings[lang][prefixedKey]) { + // This string is overridden by a custom string, ignore it. + continue; + } + + if (!this.siteAddonsStrings[lang][prefixedKey]) { + // It's a new site addon string. Store the original value. + this.siteAddonsStrings[lang][prefixedKey] = { + original: this.translate.translations[lang][prefixedKey], + value: value + }; + } else { + // Site addon string already defined. Store the new value. + this.siteAddonsStrings[lang][prefixedKey].value = value; + } + + // Store the string in the translations table. + this.translate.translations[lang][prefixedKey] = value; + } } /** @@ -69,51 +109,17 @@ export class CoreLangProvider { * Clear current custom strings. */ clearCustomStrings(): void { + this.unloadStrings(this.customStrings); this.customStrings = {}; this.customStringsRaw = ''; } /** - * Function to "decorate" the TranslateService. - * Basically, it extends the translate functions to use the custom lang strings. + * Clear current site addons strings. */ - decorateTranslate(): void { - const originalGet = this.translate.get, - originalInstant = this.translate.instant; - - // Redefine translate.get. - this.translate.get = (key: string | string[], interpolateParams?: object): Observable => { - // Always call the original get function to avoid having to create our own Observables. - if (typeof key == 'string') { - const value = this.getCustomString(key); - if (typeof value != 'undefined') { - key = value; - } - } else { - key = this.getCustomStrings(key).translations; - } - - return originalGet.apply(this.translate, [key, interpolateParams]); - }; - - // Redefine translate.instant. - this.translate.instant = (key: string | string[], interpolateParams?: object): any => { - if (typeof key == 'string') { - const value = this.getCustomString(key); - if (typeof value != 'undefined') { - return value; - } - - return originalInstant.apply(this.translate, [key, interpolateParams]); - } else { - const result = this.getCustomStrings(key); - if (result.allFound) { - return result.translations; - } - - return originalInstant.apply(this.translate, [result.translations]); - } - }; + clearSiteAddonsStrings(): void { + this.unloadStrings(this.siteAddonsStrings); + this.siteAddonsStrings = {}; } /** @@ -125,6 +131,15 @@ export class CoreLangProvider { return this.customStrings; } + /** + * Get all current site addons strings. + * + * @return {any} Site addons strings. + */ + getAllSiteAddonsStrings(): any { + return this.siteAddonsStrings; + } + /** * Get current language. * @@ -174,57 +189,6 @@ export class CoreLangProvider { }); } - /** - * Get a custom string for a certain key. - * - * @param {string} key The key of the translation to get. - * @return {string} Translation, undefined if not found. - */ - getCustomString(key: string): string { - const customStrings = this.getCustomStringsForLanguage(); - if (customStrings && typeof customStrings[key] != 'undefined') { - return customStrings[key]; - } - } - - /** - * Get custom strings for several keys. - * - * @param {string[]} keys The keys of the translations to get. - * @return {any} Object with translations and a boolean indicating if all translations were found in custom strings. - */ - getCustomStrings(keys: string[]): any { - const customStrings = this.getCustomStringsForLanguage(), - translations = []; - let allFound = true; - - keys.forEach((key: string) => { - if (customStrings && typeof customStrings[key] != 'undefined') { - translations.push(customStrings[key]); - } else { - allFound = false; - translations.push(key); - } - }); - - return { - allFound: allFound, - translations: translations - }; - } - - /** - * Get custom strings for a certain language. - * - * @param {string} [lang] The language to get. If not defined, return current language. - * @return {any} Custom strings. - */ - getCustomStringsForLanguage(lang?: string): any { - lang = lang || this.currentLanguage; - - return this.customStrings[lang]; - } - /** * Load certain custom strings. * @@ -259,7 +223,36 @@ export class CoreLangProvider { this.customStrings[lang] = {}; } - this.customStrings[lang][values[0]] = values[1]; + // Store the original value of the custom string. + this.customStrings[lang][values[0]] = { + original: this.translate.translations[lang][values[0]], + value: values[1] + }; + + // Store the string in the translations table. + this.translate.translations[lang][values[0]] = values[1]; }); } + + /** + * Unload custom or site addon strings, removing the to the translations table. + * + * @param {any} strings Strings to unload. + */ + protected unloadStrings(strings: any): void { + // Iterate over all languages and strings. + for (const lang in strings) { + const langStrings = strings[lang]; + for (const key in langStrings) { + const entry = langStrings[key]; + if (entry.original) { + // The string had a value, restore it. + this.translate.translations[lang][key] = entry.original; + } else { + // The string didn't exist, delete it. + delete this.translate.translations[lang][key]; + } + } + } + } }