'use strict'; var cookie = require('js-cookie'); const languageCodes = [ "af", "sq", "am", "ar", "hy", "as", "ay", "az", "bm", "ba", "eu", "be", "bn", "bh", "bi", "bs", "br", "bg", "my", "ca", "ch", "ce", "ny", "zh", "cv", "kw", "co", "cr", "hr", "cs", "da", "dv", "nl", "dz", "en", "eo", "et", "ee", "fo", "fj", "fi", "fr", "fy", "ga", "gd", "gl", "lg", "ka", "de", "ki", "el", "gn", "gu", "ht", "ha", "he", "hz", "hi", "ho", "hu", "is", "ig", "id", "ia", "ie", "iu", "ik", "in", "ga", "it", "ja", "jv", "kl", "kn", "kr", "ks", "kk", "km", "ki", "rw", "ko", "ku", "kj", "lo", "la", "lv", "li", "ln", "lt", "lb", "mk", "mg", "ms", "ml", "mt", "mi", "mr", "mh", "mn", "na", "nv", "nd", "ne", "ng", "nb", "nn", "no", "ii", "oc", "oj", "or", "om", "os", "pa", "pi", "fa", "pl", "pt", "ps", "qu", "rm", "ro", "ru", "sm", "sg", "sa", "sc", "sr", "sn", "sd", "si", "sk", "sl", "so", "st", "es", "su", "sw", "ss", "sv", "tl", "ty", "tg", "ta", "tt", "te", "th", "bo", "ti", "to", "tn", "tr", "tk", "tw", "ug", "uk", "ur", "uz", "ve", "vi", "vo", "cy", "wa", "wo", "xh", "yi", "yo", "zu" ]; let I18nObject = { locale: {}, locales: {}, localeId: 'languageId', defaultLocale: 'zh', useLocales: languageCodes }; const NotificationCenter = new Map(); // 消息中心 class Locale { language; dirNames = []; dirNameKeys = ''; dirNameValues = {}; constructor(dirNames, language) { this.language = getLanguage(language); this.initDirNameKeys(dirNames); this.initDirNameValues(); } initDirNameKeys(dirNames) { if (typeof dirNames === 'string') { dirNames = [dirNames]; } // 根据首字母排序 if (dirNames.length > 1) { dirNames.sort((a, b) => { let firstCharA = a.charAt(0).toLowerCase(); let firstCharB = b.charAt(0).toLowerCase(); if (firstCharA < firstCharB) { return -1; } if (firstCharA > firstCharB) { return 1; } return 0; }); } this.dirNames = dirNames; this.dirNameKeys = dirNames.join("-"); } initDirNameValues() { let locale = getLocale(this.language); for (let i = 0; i < this.dirNames.length; i++) { const name = this.dirNames[i]; if (locale && locale[name]) { const curLocale = locale[name] || {}; this.dirNameValues = { ...this.dirNameValues, ...curLocale }; } } } update(language) { this.language = getLanguage(language); this.initDirNameValues(); } } const initI18n = (options) => { if (options.locales) I18nObject['locales'] = options.locales; if (options.useLocales) I18nObject['useLocales'] = options.useLocales; if (options.localeId) I18nObject['localeId'] = options.localeId; if (options.defaultLocale) I18nObject['defaultLocale'] = options.defaultLocale; }; const getModules = (modules, type) => { if (type == "require") { return getModuleByRequireContext(modules); } else if (type == "glob") { return getModuleByMetaGlob(modules); } }; const getModuleByMetaGlob = (modules) => { let resources = {}; if (!modules) return {}; Object.keys(modules).forEach((key) => { if (modules[key].default) { const urlArr = key.split('/'); const matched = key.match(/([A-Za-z0-9-_]+)\./i); if (matched && matched.length > 1) { const dirName = urlArr.splice(-2, 1)[0]; // 获取目录名 const lang = matched[1]; // 语言类型 const context = modules[key].default; if (!resources[lang]) resources[lang] = {}; resources[lang][dirName] = context; } } }); return resources; }; const getModuleByRequireContext = (modules) => { let resources = {}; if (!modules) return {}; modules.keys().forEach((key) => { if (modules(key)) { const urlArr = key.split('/'); const matched = key.match(/([A-Za-z0-9-_]+)\./i); if (matched && matched.length > 1) { const dirName = urlArr.splice(-2, 1)[0]; // 获取目录名 const lang = matched[1]; // 语言类型 const context = modules(key); if (!resources[lang]) resources[lang] = {}; resources[lang][dirName] = context; } } }); return resources; }; const getLocale = (language) => { const languageId = getLanguage(language); const locales = getLocales(); if (locales && languageId && locales[languageId]) { return locales[languageId]; } return {}; }; const getLocales = () => I18nObject.locales; const getLanguage = (language) => { let langId = language ? language : cookie.get(I18nObject.localeId) || I18nObject.defaultLocale; if (!I18nObject.useLocales.includes(langId)) { console.warn('not found lang: ' + langId); langId = I18nObject.defaultLocale; } return langId; }; const setLanguage = (language) => { cookie.set(I18nObject.localeId, language); I18nObject.defaultLocale = language; // update watcher NotificationCenter.forEach((update) => update(language)); }; const getLang = (key, language) => { const local = getLocale(language); if (local && local[key]) { return local[key]; } return key; }; const useLang = (dirNames, language) => { if (Object.keys(I18nObject.locales).length == 0) { console.warn('Please initialize first and execute initI18n()'); } // 初始化页面级别的 hooks const locale = new Locale(dirNames, language); // 通过消息中心管理所有的 locale if (!NotificationCenter.has(locale.dirNameKeys)) { NotificationCenter.set(locale.dirNameKeys, (lang) => locale.update(lang)); } const t = (key, data) => { const lang = locale["dirNameValues"]; if (!lang[key]) { console.warn('missing lang key: ' + key); return ''; } let _lang = lang[key]; if (data && Object.keys(data).length > 0) { Object.keys(data).map((item) => { _lang = _lang.replace(`{${item}}`, data[item]); }); return _lang; } else return lang[key]; }; return { t, defaultLocale: locale.language, locale: locale.dirNameValues, locales: I18nObject.locales, localeId: I18nObject.localeId, useLocales: I18nObject.useLocales }; }; const resetI18n = ({ removeCookie = true }) => { I18nObject = { locale: {}, locales: {}, localeId: 'languageId', defaultLocale: 'zh', useLocales: languageCodes }; NotificationCenter.clear(); if (removeCookie) { cookie.remove(I18nObject.localeId); } }; exports.getLang = getLang; exports.getLanguage = getLanguage; exports.getLocale = getLocale; exports.getLocales = getLocales; exports.getModuleByMetaGlob = getModuleByMetaGlob; exports.getModuleByRequireContext = getModuleByRequireContext; exports.getModules = getModules; exports.initI18n = initI18n; exports.languageCodes = languageCodes; exports.resetI18n = resetI18n; exports.setLanguage = setLanguage; exports.useLang = useLang;