mirror of https://github.com/wekan/wekan
The Open Source kanban (built with Meteor). Keep variable/table/field names camelCase. For translations, only add Pull Request changes to wekan/i18n/en.i18n.json , other translations are done at https://transifex.com/wekan/wekan only.
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.9 KiB
94 lines
2.9 KiB
import { ReactiveCache } from '/imports/reactiveCache';
|
|
import { Meteor } from 'meteor/meteor';
|
|
import { ReactiveVar } from 'meteor/reactive-var';
|
|
import Translation from '/models/translation';
|
|
import i18next from 'i18next';
|
|
import sprintf from 'i18next-sprintf-postprocessor';
|
|
import languages from './languages';
|
|
|
|
const DEFAULT_NAMESPACE = 'translation';
|
|
const DEFAULT_LANGUAGE = 'en';
|
|
|
|
// Carefully reproduced tap:i18n API
|
|
export const TAPi18n = {
|
|
i18n: null,
|
|
current: new ReactiveVar(DEFAULT_LANGUAGE),
|
|
async init() {
|
|
this.i18n = i18next.createInstance().use(sprintf);
|
|
await this.i18n.init({
|
|
fallbackLng: DEFAULT_LANGUAGE,
|
|
cleanCode: true,
|
|
// Show translations debug messages only when DEBUG=true
|
|
// OLD: debug: Meteor.isDevelopment,
|
|
debug: process.env.DEBUG === 'true',
|
|
supportedLngs: Object.values(languages).map(({ tag }) => tag),
|
|
ns: DEFAULT_NAMESPACE,
|
|
defaultNs: DEFAULT_NAMESPACE,
|
|
postProcess: ["sprintf"],
|
|
// Default values to match tap:i18n behaviour
|
|
interpolation: {
|
|
prefix: '__',
|
|
suffix: '__',
|
|
escapeValue: false,
|
|
},
|
|
resources: {},
|
|
});
|
|
// Load the current language data
|
|
await TAPi18n.loadLanguage(DEFAULT_LANGUAGE);
|
|
},
|
|
isLanguageSupported(language) {
|
|
return Object.values(languages).some(({ tag }) => tag === language);
|
|
},
|
|
getSupportedLanguages() {
|
|
return Object.values(languages).map(({ name, code, tag }) => ({ name, code, tag }));
|
|
},
|
|
getLanguage() {
|
|
return this.current.get();
|
|
},
|
|
loadTranslation(language) {
|
|
return new Promise((resolve, reject) => {
|
|
if (Meteor.isClient) {
|
|
const translationSubscription = Meteor.subscribe('translation', {language: language}, 0, {
|
|
onReady() {
|
|
resolve(translationSubscription);
|
|
},
|
|
onError(error) {
|
|
reject(error);
|
|
}
|
|
});
|
|
} else {
|
|
resolve();
|
|
}
|
|
});
|
|
},
|
|
async loadLanguage(language) {
|
|
if (language in languages && 'load' in languages[language]) {
|
|
let data = await languages[language].load();
|
|
|
|
let custom_translations = [];
|
|
await this.loadTranslation(language);
|
|
custom_translations = ReactiveCache.getTranslations({language: language}, {fields: { text: true, translationText: true }});
|
|
|
|
if (custom_translations && custom_translations.length > 0) {
|
|
data = custom_translations.reduce((acc, cur) => (acc[cur.text]=cur.translationText, acc), data);
|
|
}
|
|
|
|
this.i18n.addResourceBundle(language, DEFAULT_NAMESPACE, data);
|
|
} else {
|
|
throw new Error(`Language ${language} is not supported`);
|
|
}
|
|
},
|
|
async setLanguage(language) {
|
|
await this.loadLanguage(language);
|
|
await this.i18n.changeLanguage(language);
|
|
this.current.set(language);
|
|
},
|
|
// Return translation by key
|
|
__(key, options, language) {
|
|
this.current.dep.depend();
|
|
return this.i18n.t(key, {
|
|
...options,
|
|
lng: language,
|
|
});
|
|
}
|
|
};
|
|
|