MOBILE-2413 lang: Fix custom and plugins strings
parent
4c222b79af
commit
7e8332d978
|
@ -18,7 +18,9 @@ import { StatusBar } from '@ionic-native/status-bar';
|
|||
import { SplashScreen } from '@ionic-native/splash-screen';
|
||||
import { CoreAppProvider } from '@providers/app';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreLangProvider } from '@providers/lang';
|
||||
import { CoreLoggerProvider } from '@providers/logger';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreLoginHelperProvider } from '@core/login/providers/helper';
|
||||
|
||||
@Component({
|
||||
|
@ -33,7 +35,7 @@ export class MoodleMobileApp implements OnInit {
|
|||
|
||||
constructor(private platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen, logger: CoreLoggerProvider,
|
||||
private eventsProvider: CoreEventsProvider, private loginHelper: CoreLoginHelperProvider,
|
||||
private appProvider: CoreAppProvider) {
|
||||
private appProvider: CoreAppProvider, private langProvider: CoreLangProvider, private sitesProvider: CoreSitesProvider) {
|
||||
this.logger = logger.getInstance('AppComponent');
|
||||
|
||||
platform.ready().then(() => {
|
||||
|
@ -49,9 +51,12 @@ export class MoodleMobileApp implements OnInit {
|
|||
* Component being initialized.
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
// Go to sites page when user is logged out.
|
||||
this.eventsProvider.on(CoreEventsProvider.LOGOUT, () => {
|
||||
// Go to sites page when user is logged out.
|
||||
this.appProvider.getRootNavController().setRoot('CoreLoginSitesPage');
|
||||
|
||||
// Unload lang custom strings.
|
||||
this.langProvider.clearCustomStrings();
|
||||
});
|
||||
|
||||
// Listen for session expired events.
|
||||
|
@ -111,5 +116,25 @@ export class MoodleMobileApp implements OnInit {
|
|||
this.eventsProvider.on(CoreEventsProvider.APP_LAUNCHED_URL, (url) => {
|
||||
this.loginHelper.appLaunchedByURL(url);
|
||||
});
|
||||
|
||||
// Load custom lang strings. This cannot be done inside the lang provider because it causes circular dependencies.
|
||||
const loadCustomStrings = (): void => {
|
||||
const currentSite = this.sitesProvider.getCurrentSite(),
|
||||
customStrings = currentSite && currentSite.getStoredConfig('tool_mobile_customlangstrings');
|
||||
|
||||
if (typeof customStrings != 'undefined') {
|
||||
this.langProvider.loadCustomStrings(customStrings);
|
||||
}
|
||||
};
|
||||
|
||||
this.eventsProvider.on(CoreEventsProvider.LOGIN, () => {
|
||||
loadCustomStrings();
|
||||
});
|
||||
|
||||
this.eventsProvider.on(CoreEventsProvider.SITE_UPDATED, (siteId) => {
|
||||
if (siteId == this.sitesProvider.getCurrentSiteId()) {
|
||||
loadCustomStrings();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,13 +53,10 @@ export class CoreLangProvider {
|
|||
* @param {string} [prefix] A prefix to add to all keys.
|
||||
*/
|
||||
addSitePluginsStrings(lang: string, strings: any, prefix?: string): void {
|
||||
// Initialize structures if they don't exist.
|
||||
// Initialize structure if it doesn't exist.
|
||||
if (!this.sitePluginsStrings[lang]) {
|
||||
this.sitePluginsStrings[lang] = {};
|
||||
}
|
||||
if (!this.translate.translations[lang]) {
|
||||
this.translate.translations[lang] = {};
|
||||
}
|
||||
|
||||
for (const key in strings) {
|
||||
const prefixedKey = prefix + key;
|
||||
|
@ -75,19 +72,8 @@ export class CoreLangProvider {
|
|||
// Make sure we didn't add to many brackets in some case.
|
||||
value = value.replace(/{{{([^ ]+)}}}/gm, '{{$1}}');
|
||||
|
||||
if (!this.sitePluginsStrings[lang][prefixedKey]) {
|
||||
// It's a new site plugin string. Store the original value.
|
||||
this.sitePluginsStrings[lang][prefixedKey] = {
|
||||
original: this.translate.translations[lang][prefixedKey],
|
||||
value: value
|
||||
};
|
||||
} else {
|
||||
// Site plugin string already defined. Store the new value.
|
||||
this.sitePluginsStrings[lang][prefixedKey].value = value;
|
||||
}
|
||||
|
||||
// Store the string in the translations table.
|
||||
this.translate.translations[lang][prefixedKey] = value;
|
||||
// Load the string.
|
||||
this.loadString(this.sitePluginsStrings, lang, prefixedKey, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,13 +86,38 @@ export class CoreLangProvider {
|
|||
changeCurrentLanguage(language: string): Promise<any> {
|
||||
const promises = [];
|
||||
|
||||
promises.push(this.translate.use(language));
|
||||
// Change the language, resolving the promise when we receive the first value.
|
||||
promises.push(new Promise((resolve, reject): void => {
|
||||
const subscription = this.translate.use(language).subscribe((data) => {
|
||||
resolve(data);
|
||||
|
||||
// Data received, unsubscribe. Use a timeout because we can receive a value immediately.
|
||||
setTimeout(() => {
|
||||
subscription.unsubscribe();
|
||||
});
|
||||
}, (error) => {
|
||||
reject(error);
|
||||
|
||||
// Error received, unsubscribe. Use a timeout because we can receive a value immediately.
|
||||
setTimeout(() => {
|
||||
subscription.unsubscribe();
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
// Change the config.
|
||||
promises.push(this.configProvider.set('current_language', language));
|
||||
|
||||
moment.locale(language);
|
||||
this.currentLanguage = language;
|
||||
|
||||
return Promise.all(promises);
|
||||
return Promise.all(promises).finally(() => {
|
||||
// Load the custom and site plugins strings for the language.
|
||||
if (this.loadLangStrings(this.customStrings, language) || this.loadLangStrings(this.sitePluginsStrings, language)) {
|
||||
// Some lang strings have changed, emit an event to update the pipes.
|
||||
this.translate.onLangChange.emit({lang: language, translations: this.translate.translations[language]});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -227,15 +238,75 @@ export class CoreLangProvider {
|
|||
this.customStrings[lang] = {};
|
||||
}
|
||||
|
||||
// Store the original value of the custom string.
|
||||
this.customStrings[lang][values[0]] = {
|
||||
original: this.translate.translations[lang][values[0]],
|
||||
value: values[1]
|
||||
// Convert old keys format to new one.
|
||||
const key = values[0].replace(/^mm\.core/, 'core').replace(/^mm\./, 'core.').replace(/^mma\./, 'addon.')
|
||||
.replace(/^core\.sidemenu/, 'core.mainmenu').replace(/^addon\.grades/, 'core.grades')
|
||||
.replace(/^addon\.participants/, 'core.user');
|
||||
|
||||
this.loadString(this.customStrings, lang, key, values[1]);
|
||||
});
|
||||
|
||||
this.customStringsRaw = strings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load custom strings for a certain language that weren't loaded because the language wasn't active.
|
||||
*
|
||||
* @param {any} langObject The object with the strings to load.
|
||||
* @param {string} lang Language to load.
|
||||
* @return {boolean} Whether the translation table was modified.
|
||||
*/
|
||||
loadLangStrings(langObject: any, lang: string): boolean {
|
||||
let langApplied = false;
|
||||
|
||||
if (langObject[lang]) {
|
||||
for (const key in langObject[lang]) {
|
||||
const entry = langObject[lang][key];
|
||||
|
||||
if (!entry.applied) {
|
||||
// Store the original value of the string.
|
||||
entry.original = this.translate.translations[lang][key];
|
||||
|
||||
// Store the string in the translations table.
|
||||
this.translate.translations[lang][key] = entry.value;
|
||||
|
||||
entry.applied = true;
|
||||
langApplied = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return langApplied;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a string in a certain lang object and in the translate table if the lang is loaded.
|
||||
*
|
||||
* @param {any} langObject The object where to store the lang.
|
||||
* @param {string} lang Language code.
|
||||
* @param {string} key String key.
|
||||
* @param {string} value String value.
|
||||
*/
|
||||
loadString(langObject: any, lang: string, key: string, value: string): void {
|
||||
if (this.translate.translations[lang]) {
|
||||
// The language is loaded.
|
||||
// Store the original value of the string.
|
||||
langObject[lang][key] = {
|
||||
original: this.translate.translations[lang][key],
|
||||
value: value,
|
||||
applied: true
|
||||
};
|
||||
|
||||
// Store the string in the translations table.
|
||||
this.translate.translations[lang][values[0]] = values[1];
|
||||
});
|
||||
this.translate.translations[lang][key] = value;
|
||||
} else {
|
||||
// The language isn't loaded.
|
||||
// Save it in our object but not in the translations table, it will be loaded when the lang is loaded.
|
||||
langObject[lang][key] = {
|
||||
value: value,
|
||||
applied: false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -246,6 +317,11 @@ export class CoreLangProvider {
|
|||
protected unloadStrings(strings: any): void {
|
||||
// Iterate over all languages and strings.
|
||||
for (const lang in strings) {
|
||||
if (!this.translate.translations[lang]) {
|
||||
// Language isn't loaded, nothing to unload.
|
||||
continue;
|
||||
}
|
||||
|
||||
const langStrings = strings[lang];
|
||||
for (const key in langStrings) {
|
||||
const entry = langStrings[key];
|
||||
|
|
Loading…
Reference in New Issue