UNPKG

petite-vue-i18n-lite

Version:

A super lightweight and minimal plugin that introduces internationalization into your [Petite Vue](https://github.com/vuejs/petite-vue) app with a simple API.

158 lines (153 loc) 4.22 kB
/*! * petite-vue-i18n-lite v1.0.2 * (c) 2021 Erik Pham & niu tech * @license MIT */ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); const disallowedKeys = ['__proto__', 'prototype', 'constructor']; /** * Is object * @param value */ function isObject(value) { const type = typeof value; return value !== null && (type === 'object' || type === 'function'); } /** * Check is empty * @param obj */ function isEmpty(obj) { return !(Array.isArray(obj) ? obj.length : Object.keys(obj).length); } /** * Is valid path * @param segments */ function isValidPath(segments) { return !segments.some((segment) => disallowedKeys.indexOf(segment) !== -1); } /** * Parse path * @param path */ function parsePath(path) { const pathArray = path.split('.'); const parts = []; for (let i = 0; i < pathArray.length; i++) { let p = pathArray[i]; while (p[p.length - 1] === '\\' && pathArray[i + 1] !== undefined) { p = p.slice(0, -1) + '.'; p += pathArray[++i]; } parts.push(p); } if (!isValidPath(parts)) { return []; } return parts; } /** * Get object value by path * @param object * @param path */ function getMessage(object, path) { if (!isObject(object)) { return ''; } const paths = parsePath(path); if (paths.length === 0) { return ''; } let rawObject = Object.assign({}, object); for (let i = 0; i < paths.length; i++) { if (typeof rawObject[paths[i]] === 'string') { return rawObject[paths[i]]; } rawObject = rawObject[paths[i]]; if (rawObject === undefined || rawObject === null) { if (i !== paths.length - 1) { return ''; } break; } } return ''; } /** * Parse locale values * @param message * @param values */ function parseLocaleValues(message, values) { if (Array.isArray(values)) { const parseValues = {}; const matches = [...message.matchAll(/{(.+?)}/g)]; if (matches) { matches.forEach((match, index) => { if (values[index]) { parseValues[match[1]] = values[index]; } }); } return parseValues; } return values; } /** * Replace locale values to message * @param message * @param values */ function replaceLocaleValues(message, values) { for (const key in values) { message = message.replace(`{${key}}`, String(values[key])); } return message; } /** * Creates a I18n instance that can be used by a Petite Vue app. * * @param options - {@link I18nOptions} */ function createI18n(options) { const initOptions = Object.assign({ locale: 'en', fallbackLocale: 'en', messages: {} }, options); const current = initOptions.locale; const locales = initOptions.messages; return { t(key, option) { if (!key) { return ''; } const locale = typeof option === 'string' && option ? option : this.current; let message = getMessage(locales[locale], key) || getMessage(locales[initOptions.fallbackLocale], key); if (option && typeof option !== 'string') { const values = parseLocaleValues(message, option); if (!isEmpty(values)) { message = replaceLocaleValues(message, values); } } return message || key; }, current, options: options || {}, changeLocale(locale) { this.current = locale; }, setLocaleMessage(locale, messages) { locales[locale] = Object.assign({}, locales[locale] || {}, messages); }, getLocaleMessage(locale) { return locales[locale] || {}; }, }; } /** * Super lightweight internationalization (i18n) plugin for Petite Vue * * @packageDocumentation */ exports.createI18n = createI18n;