uni-i18n.cjs.js 9.3 KB
Newer Older
fxy060608's avatar
fxy060608 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

const isObject = (val) => val !== null && typeof val === 'object';
class BaseFormatter {
    constructor() {
        this._caches = Object.create(null);
    }
    interpolate(message, values) {
        if (!values) {
            return [message];
        }
        let tokens = this._caches[message];
        if (!tokens) {
            tokens = parse(message);
            this._caches[message] = tokens;
        }
        return compile(tokens, values);
    }
}
const RE_TOKEN_LIST_VALUE = /^(?:\d)+/;
const RE_TOKEN_NAMED_VALUE = /^(?:\w)+/;
function parse(format) {
    const tokens = [];
    let position = 0;
    let text = '';
    while (position < format.length) {
        let char = format[position++];
        if (char === '{') {
            if (text) {
                tokens.push({ type: 'text', value: text });
            }
            text = '';
            let sub = '';
            char = format[position++];
            while (char !== undefined && char !== '}') {
                sub += char;
                char = format[position++];
            }
            const isClosed = char === '}';
            const type = RE_TOKEN_LIST_VALUE.test(sub)
                ? 'list'
                : isClosed && RE_TOKEN_NAMED_VALUE.test(sub)
                    ? 'named'
                    : 'unknown';
            tokens.push({ value: sub, type });
        }
        else if (char === '%') {
            // when found rails i18n syntax, skip text capture
            if (format[position] !== '{') {
                text += char;
            }
        }
        else {
            text += char;
        }
    }
    text && tokens.push({ type: 'text', value: text });
    return tokens;
}
function compile(tokens, values) {
    const compiled = [];
    let index = 0;
    const mode = Array.isArray(values)
        ? 'list'
        : isObject(values)
            ? 'named'
            : 'unknown';
    if (mode === 'unknown') {
        return compiled;
    }
    while (index < tokens.length) {
        const token = tokens[index];
        switch (token.type) {
            case 'text':
                compiled.push(token.value);
                break;
            case 'list':
                compiled.push(values[parseInt(token.value, 10)]);
                break;
            case 'named':
                if (mode === 'named') {
                    compiled.push(values[token.value]);
                }
                else {
                    if (process.env.NODE_ENV !== 'production') {
                        console.warn(`Type of token '${token.type}' and format of value '${mode}' don't match!`);
                    }
                }
                break;
            case 'unknown':
                if (process.env.NODE_ENV !== 'production') {
                    console.warn(`Detect 'unknown' type of token!`);
                }
                break;
        }
        index++;
    }
    return compiled;
}

fxy060608's avatar
fxy060608 已提交
103 104 105 106 107
const LOCALE_ZH_HANS = 'zh-Hans';
const LOCALE_ZH_HANT = 'zh-Hant';
const LOCALE_EN = 'en';
const LOCALE_FR = 'fr';
const LOCALE_ES = 'es';
fxy060608's avatar
fxy060608 已提交
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
const hasOwnProperty = Object.prototype.hasOwnProperty;
const hasOwn = (val, key) => hasOwnProperty.call(val, key);
const defaultFormatter = new BaseFormatter();
function include(str, parts) {
    return !!parts.find((part) => str.indexOf(part) !== -1);
}
function startsWith(str, parts) {
    return parts.find((part) => str.indexOf(part) === 0);
}
function normalizeLocale(locale, messages) {
    if (!locale) {
        return;
    }
    locale = locale.trim().replace(/_/g, '-');
    if (messages[locale]) {
        return locale;
    }
    locale = locale.toLowerCase();
    if (locale.indexOf('zh') === 0) {
        if (locale.indexOf('-hans') !== -1) {
fxy060608's avatar
fxy060608 已提交
128
            return LOCALE_ZH_HANS;
fxy060608's avatar
fxy060608 已提交
129 130
        }
        if (locale.indexOf('-hant') !== -1) {
fxy060608's avatar
fxy060608 已提交
131
            return LOCALE_ZH_HANT;
fxy060608's avatar
fxy060608 已提交
132 133
        }
        if (include(locale, ['-tw', '-hk', '-mo', '-cht'])) {
fxy060608's avatar
fxy060608 已提交
134
            return LOCALE_ZH_HANT;
fxy060608's avatar
fxy060608 已提交
135
        }
fxy060608's avatar
fxy060608 已提交
136
        return LOCALE_ZH_HANS;
fxy060608's avatar
fxy060608 已提交
137
    }
fxy060608's avatar
fxy060608 已提交
138
    const lang = startsWith(locale, [LOCALE_EN, LOCALE_FR, LOCALE_ES]);
fxy060608's avatar
fxy060608 已提交
139 140 141 142 143 144
    if (lang) {
        return lang;
    }
}
class I18n {
    constructor({ locale, fallbackLocale, messages, watcher, formater, }) {
fxy060608's avatar
fxy060608 已提交
145 146 147 148 149
        this.locale = LOCALE_EN;
        this.fallbackLocale = LOCALE_EN;
        this.message = {};
        this.messages = {};
        this.watchers = [];
fxy060608's avatar
fxy060608 已提交
150 151 152 153
        if (fallbackLocale) {
            this.fallbackLocale = fallbackLocale;
        }
        this.formater = formater || defaultFormatter;
fxy060608's avatar
fxy060608 已提交
154
        this.messages = messages || {};
fxy060608's avatar
fxy060608 已提交
155 156 157 158 159 160 161 162
        this.setLocale(locale);
        if (watcher) {
            this.watchLocale(watcher);
        }
    }
    setLocale(locale) {
        const oldLocale = this.locale;
        this.locale = normalizeLocale(locale, this.messages) || this.fallbackLocale;
fxy060608's avatar
fxy060608 已提交
163 164 165 166
        if (!this.messages[this.locale]) {
            // 可能初始化时不存在
            this.messages[this.locale] = {};
        }
fxy060608's avatar
fxy060608 已提交
167 168 169 170 171 172 173 174 175 176 177 178 179 180
        this.message = this.messages[this.locale];
        this.watchers.forEach((watcher) => {
            watcher(this.locale, oldLocale);
        });
    }
    getLocale() {
        return this.locale;
    }
    watchLocale(fn) {
        const index = this.watchers.push(fn) - 1;
        return () => {
            this.watchers.splice(index, 1);
        };
    }
fxy060608's avatar
fxy060608 已提交
181
    add(locale, message) {
fxy060608's avatar
fxy060608 已提交
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
        if (this.messages[locale]) {
            Object.assign(this.messages[locale], message);
        }
        else {
            this.messages[locale] = message;
        }
    }
    t(key, locale, values) {
        let message = this.message;
        if (typeof locale === 'string') {
            locale = normalizeLocale(locale, this.messages);
            locale && (message = this.messages[locale]);
        }
        else {
            values = locale;
        }
        if (!hasOwn(message, key)) {
            console.warn(`Cannot translate the value of keypath ${key}. Use the value of keypath as default.`);
            return key;
        }
        return this.formater.interpolate(message[key], values).join('');
    }
}

Q
qiang 已提交
206
const ignoreVueI18n = true;
fxy060608's avatar
fxy060608 已提交
207
function initLocaleWatcher(appVm, i18n) {
Q
qiang 已提交
208 209 210
    if (appVm.$i18n) {
        const vm = appVm.$i18n.vm ? appVm.$i18n.vm : appVm;
        vm.$watch(appVm.$i18n.vm ? 'locale' : () => appVm.$i18n.locale, (newLocale) => {
fxy060608's avatar
fxy060608 已提交
211 212 213 214
            i18n.setLocale(newLocale);
        }, {
            immediate: true,
        });
Q
qiang 已提交
215
    }
fxy060608's avatar
fxy060608 已提交
216
}
fxy060608's avatar
fxy060608 已提交
217 218 219 220 221 222 223 224 225 226
// function getDefaultLocale() {
//   if (typeof navigator !== 'undefined') {
//     return (navigator as any).userLanguage || navigator.language
//   }
//   if (typeof plus !== 'undefined') {
//     // TODO 待调整为最新的获取语言代码
//     return plus.os.language
//   }
//   return uni.getSystemInfoSync().language
// }
Q
qiang 已提交
227
function initVueI18n(locale = LOCALE_EN, messages = {}, fallbackLocale = LOCALE_EN, watcher) {
228 229 230 231
    // 兼容旧版本入参
    if (typeof locale !== 'string') {
        [locale, messages] = [messages, locale];
    }
fxy060608's avatar
fxy060608 已提交
232 233 234
    if (typeof locale !== 'string') {
        locale = fallbackLocale;
    }
fxy060608's avatar
fxy060608 已提交
235 236 237 238
    const i18n = new I18n({
        locale: locale || fallbackLocale,
        fallbackLocale,
        messages,
Q
qiang 已提交
239
        watcher,
fxy060608's avatar
fxy060608 已提交
240 241 242
    });
    let t = (key, values) => {
        if (typeof getApp !== 'function') {
fxy060608's avatar
fxy060608 已提交
243
            // app view
fxy060608's avatar
fxy060608 已提交
244 245 246 247 248 249 250
            /* eslint-disable no-func-assign */
            t = function (key, values) {
                return i18n.t(key, values);
            };
        }
        else {
            const appVm = getApp().$vm;
Q
qiang 已提交
251
            if (!appVm.$t || !appVm.$i18n || ignoreVueI18n) {
fxy060608's avatar
fxy060608 已提交
252 253 254
                // if (!locale) {
                //   i18n.setLocale(getDefaultLocale())
                // }
fxy060608's avatar
fxy060608 已提交
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
                /* eslint-disable no-func-assign */
                t = function (key, values) {
                    return i18n.t(key, values);
                };
            }
            else {
                initLocaleWatcher(appVm, i18n);
                /* eslint-disable no-func-assign */
                t = function (key, values) {
                    const $i18n = appVm.$i18n;
                    const silentTranslationWarn = $i18n.silentTranslationWarn;
                    $i18n.silentTranslationWarn = true;
                    const msg = appVm.$t(key, values);
                    $i18n.silentTranslationWarn = silentTranslationWarn;
                    if (msg !== key) {
                        return msg;
                    }
                    return i18n.t(key, $i18n.locale, values);
                };
            }
        }
        return t(key, values);
    };
    return {
fxy060608's avatar
fxy060608 已提交
279
        i18n,
fxy060608's avatar
fxy060608 已提交
280 281 282
        t(key, values) {
            return t(key, values);
        },
fxy060608's avatar
fxy060608 已提交
283 284 285
        add(locale, message) {
            return i18n.add(locale, message);
        },
fxy060608's avatar
fxy060608 已提交
286 287 288 289 290 291 292 293 294 295
        getLocale() {
            return i18n.getLocale();
        },
        setLocale(newLocale) {
            return i18n.setLocale(newLocale);
        },
    };
}

exports.I18n = I18n;
fxy060608's avatar
fxy060608 已提交
296 297 298 299 300
exports.LOCALE_EN = LOCALE_EN;
exports.LOCALE_ES = LOCALE_ES;
exports.LOCALE_FR = LOCALE_FR;
exports.LOCALE_ZH_HANS = LOCALE_ZH_HANS;
exports.LOCALE_ZH_HANT = LOCALE_ZH_HANT;
fxy060608's avatar
fxy060608 已提交
301
exports.initVueI18n = initVueI18n;