/*!
|
* @intlify/core-base v9.1.7
|
* (c) 2021 kazuya kawaguchi
|
* Released under the MIT License.
|
*/
|
'use strict';
|
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
var messageResolver = require('@intlify/message-resolver');
|
var runtime = require('@intlify/runtime');
|
var messageCompiler = require('@intlify/message-compiler');
|
var shared = require('@intlify/shared');
|
var devtoolsIf = require('@intlify/devtools-if');
|
|
let devtools = null;
|
function setDevToolsHook(hook) {
|
devtools = hook;
|
}
|
function getDevToolsHook() {
|
return devtools;
|
}
|
function initI18nDevTools(i18n, version, meta) {
|
// TODO: queue if devtools is undefined
|
devtools &&
|
devtools.emit(devtoolsIf.IntlifyDevToolsHooks.I18nInit, {
|
timestamp: Date.now(),
|
i18n,
|
version,
|
meta
|
});
|
}
|
const translateDevTools = /* #__PURE__*/ createDevToolsHook(devtoolsIf.IntlifyDevToolsHooks.FunctionTranslate);
|
function createDevToolsHook(hook) {
|
return (payloads) => devtools && devtools.emit(hook, payloads);
|
}
|
|
/** @internal */
|
const warnMessages = {
|
[0 /* NOT_FOUND_KEY */]: `Not found '{key}' key in '{locale}' locale messages.`,
|
[1 /* FALLBACK_TO_TRANSLATE */]: `Fall back to translate '{key}' key with '{target}' locale.`,
|
[2 /* CANNOT_FORMAT_NUMBER */]: `Cannot format a number value due to not supported Intl.NumberFormat.`,
|
[3 /* FALLBACK_TO_NUMBER_FORMAT */]: `Fall back to number format '{key}' key with '{target}' locale.`,
|
[4 /* CANNOT_FORMAT_DATE */]: `Cannot format a date value due to not supported Intl.DateTimeFormat.`,
|
[5 /* FALLBACK_TO_DATE_FORMAT */]: `Fall back to datetime format '{key}' key with '{target}' locale.`
|
};
|
function getWarnMessage(code, ...args) {
|
return shared.format(warnMessages[code], ...args);
|
}
|
|
/**
|
* Intlify core-base version
|
* @internal
|
*/
|
const VERSION = '9.1.7';
|
const NOT_REOSLVED = -1;
|
const MISSING_RESOLVE_VALUE = '';
|
function getDefaultLinkedModifiers() {
|
return {
|
upper: (val) => (shared.isString(val) ? val.toUpperCase() : val),
|
lower: (val) => (shared.isString(val) ? val.toLowerCase() : val),
|
// prettier-ignore
|
capitalize: (val) => (shared.isString(val)
|
? `${val.charAt(0).toLocaleUpperCase()}${val.substr(1)}`
|
: val)
|
};
|
}
|
let _compiler;
|
function registerMessageCompiler(compiler) {
|
_compiler = compiler;
|
}
|
// Additional Meta for Intlify DevTools
|
let _additionalMeta = null;
|
const setAdditionalMeta = /* #__PURE__*/ (meta) => {
|
_additionalMeta = meta;
|
};
|
const getAdditionalMeta = /* #__PURE__*/ () => _additionalMeta;
|
// ID for CoreContext
|
let _cid = 0;
|
function createCoreContext(options = {}) {
|
// setup options
|
const version = shared.isString(options.version) ? options.version : VERSION;
|
const locale = shared.isString(options.locale) ? options.locale : 'en-US';
|
const fallbackLocale = shared.isArray(options.fallbackLocale) ||
|
shared.isPlainObject(options.fallbackLocale) ||
|
shared.isString(options.fallbackLocale) ||
|
options.fallbackLocale === false
|
? options.fallbackLocale
|
: locale;
|
const messages = shared.isPlainObject(options.messages)
|
? options.messages
|
: { [locale]: {} };
|
const datetimeFormats = shared.isPlainObject(options.datetimeFormats)
|
? options.datetimeFormats
|
: { [locale]: {} };
|
const numberFormats = shared.isPlainObject(options.numberFormats)
|
? options.numberFormats
|
: { [locale]: {} };
|
const modifiers = shared.assign({}, options.modifiers || {}, getDefaultLinkedModifiers());
|
const pluralRules = options.pluralRules || {};
|
const missing = shared.isFunction(options.missing) ? options.missing : null;
|
const missingWarn = shared.isBoolean(options.missingWarn) || shared.isRegExp(options.missingWarn)
|
? options.missingWarn
|
: true;
|
const fallbackWarn = shared.isBoolean(options.fallbackWarn) || shared.isRegExp(options.fallbackWarn)
|
? options.fallbackWarn
|
: true;
|
const fallbackFormat = !!options.fallbackFormat;
|
const unresolving = !!options.unresolving;
|
const postTranslation = shared.isFunction(options.postTranslation)
|
? options.postTranslation
|
: null;
|
const processor = shared.isPlainObject(options.processor) ? options.processor : null;
|
const warnHtmlMessage = shared.isBoolean(options.warnHtmlMessage)
|
? options.warnHtmlMessage
|
: true;
|
const escapeParameter = !!options.escapeParameter;
|
const messageCompiler = shared.isFunction(options.messageCompiler)
|
? options.messageCompiler
|
: _compiler;
|
const onWarn = shared.isFunction(options.onWarn) ? options.onWarn : shared.warn;
|
// setup internal options
|
const internalOptions = options;
|
const __datetimeFormatters = shared.isObject(internalOptions.__datetimeFormatters)
|
? internalOptions.__datetimeFormatters
|
: new Map();
|
const __numberFormatters = shared.isObject(internalOptions.__numberFormatters)
|
? internalOptions.__numberFormatters
|
: new Map();
|
const __meta = shared.isObject(internalOptions.__meta) ? internalOptions.__meta : {};
|
_cid++;
|
const context = {
|
version,
|
cid: _cid,
|
locale,
|
fallbackLocale,
|
messages,
|
datetimeFormats,
|
numberFormats,
|
modifiers,
|
pluralRules,
|
missing,
|
missingWarn,
|
fallbackWarn,
|
fallbackFormat,
|
unresolving,
|
postTranslation,
|
processor,
|
warnHtmlMessage,
|
escapeParameter,
|
messageCompiler,
|
onWarn,
|
__datetimeFormatters,
|
__numberFormatters,
|
__meta
|
};
|
// for vue-devtools timeline event
|
{
|
context.__v_emitter =
|
internalOptions.__v_emitter != null
|
? internalOptions.__v_emitter
|
: undefined;
|
}
|
// NOTE: experimental !!
|
{
|
initI18nDevTools(context, version, __meta);
|
}
|
return context;
|
}
|
/** @internal */
|
function isTranslateFallbackWarn(fallback, key) {
|
return fallback instanceof RegExp ? fallback.test(key) : fallback;
|
}
|
/** @internal */
|
function isTranslateMissingWarn(missing, key) {
|
return missing instanceof RegExp ? missing.test(key) : missing;
|
}
|
/** @internal */
|
function handleMissing(context, key, locale, missingWarn, type) {
|
const { missing, onWarn } = context;
|
// for vue-devtools timeline event
|
{
|
const emitter = context.__v_emitter;
|
if (emitter) {
|
emitter.emit("missing" /* MISSING */, {
|
locale,
|
key,
|
type,
|
groupId: `${type}:${key}`
|
});
|
}
|
}
|
if (missing !== null) {
|
const ret = missing(context, locale, key, type);
|
return shared.isString(ret) ? ret : key;
|
}
|
else {
|
if (isTranslateMissingWarn(missingWarn, key)) {
|
onWarn(getWarnMessage(0 /* NOT_FOUND_KEY */, { key, locale }));
|
}
|
return key;
|
}
|
}
|
/** @internal */
|
function getLocaleChain(ctx, fallback, start) {
|
const context = ctx;
|
if (!context.__localeChainCache) {
|
context.__localeChainCache = new Map();
|
}
|
let chain = context.__localeChainCache.get(start);
|
if (!chain) {
|
chain = [];
|
// first block defined by start
|
let block = [start];
|
// while any intervening block found
|
while (shared.isArray(block)) {
|
block = appendBlockToChain(chain, block, fallback);
|
}
|
// prettier-ignore
|
// last block defined by default
|
const defaults = shared.isArray(fallback)
|
? fallback
|
: shared.isPlainObject(fallback)
|
? fallback['default']
|
? fallback['default']
|
: null
|
: fallback;
|
// convert defaults to array
|
block = shared.isString(defaults) ? [defaults] : defaults;
|
if (shared.isArray(block)) {
|
appendBlockToChain(chain, block, false);
|
}
|
context.__localeChainCache.set(start, chain);
|
}
|
return chain;
|
}
|
function appendBlockToChain(chain, block, blocks) {
|
let follow = true;
|
for (let i = 0; i < block.length && shared.isBoolean(follow); i++) {
|
const locale = block[i];
|
if (shared.isString(locale)) {
|
follow = appendLocaleToChain(chain, block[i], blocks);
|
}
|
}
|
return follow;
|
}
|
function appendLocaleToChain(chain, locale, blocks) {
|
let follow;
|
const tokens = locale.split('-');
|
do {
|
const target = tokens.join('-');
|
follow = appendItemToChain(chain, target, blocks);
|
tokens.splice(-1, 1);
|
} while (tokens.length && follow === true);
|
return follow;
|
}
|
function appendItemToChain(chain, target, blocks) {
|
let follow = false;
|
if (!chain.includes(target)) {
|
follow = true;
|
if (target) {
|
follow = target[target.length - 1] !== '!';
|
const locale = target.replace(/!/g, '');
|
chain.push(locale);
|
if ((shared.isArray(blocks) || shared.isPlainObject(blocks)) &&
|
blocks[locale] // eslint-disable-line @typescript-eslint/no-explicit-any
|
) {
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
follow = blocks[locale];
|
}
|
}
|
}
|
return follow;
|
}
|
/** @internal */
|
function updateFallbackLocale(ctx, locale, fallback) {
|
const context = ctx;
|
context.__localeChainCache = new Map();
|
getLocaleChain(ctx, fallback, locale);
|
}
|
|
const RE_HTML_TAG = /<\/?[\w\s="/.':;#-\/]+>/;
|
const WARN_MESSAGE = `Detected HTML in '{source}' message. Recommend not using HTML messages to avoid XSS.`;
|
function checkHtmlMessage(source, options) {
|
const warnHtmlMessage = shared.isBoolean(options.warnHtmlMessage)
|
? options.warnHtmlMessage
|
: true;
|
if (warnHtmlMessage && RE_HTML_TAG.test(source)) {
|
shared.warn(shared.format(WARN_MESSAGE, { source }));
|
}
|
}
|
const defaultOnCacheKey = (source) => source;
|
let compileCache = Object.create(null);
|
function clearCompileCache() {
|
compileCache = Object.create(null);
|
}
|
function compileToFunction(source, options = {}) {
|
{
|
// check HTML message
|
checkHtmlMessage(source, options);
|
// check caches
|
const onCacheKey = options.onCacheKey || defaultOnCacheKey;
|
const key = onCacheKey(source);
|
const cached = compileCache[key];
|
if (cached) {
|
return cached;
|
}
|
// compile error detecting
|
let occurred = false;
|
const onError = options.onError || messageCompiler.defaultOnError;
|
options.onError = (err) => {
|
occurred = true;
|
onError(err);
|
};
|
// compile
|
const { code } = messageCompiler.baseCompile(source, options);
|
// evaluate function
|
const msg = new Function(`return ${code}`)();
|
// if occurred compile error, don't cache
|
return !occurred ? (compileCache[key] = msg) : msg;
|
}
|
}
|
|
function createCoreError(code) {
|
return messageCompiler.createCompileError(code, null, { messages: errorMessages } );
|
}
|
/** @internal */
|
const errorMessages = {
|
[14 /* INVALID_ARGUMENT */]: 'Invalid arguments',
|
[15 /* INVALID_DATE_ARGUMENT */]: 'The date provided is an invalid Date object.' +
|
'Make sure your Date represents a valid date.',
|
[16 /* INVALID_ISO_DATE_ARGUMENT */]: 'The argument provided is not a valid ISO date string'
|
};
|
|
const NOOP_MESSAGE_FUNCTION = () => '';
|
const isMessageFunction = (val) => shared.isFunction(val);
|
// implementation of `translate` function
|
function translate(context, ...args) {
|
const { fallbackFormat, postTranslation, unresolving, fallbackLocale, messages } = context;
|
const [key, options] = parseTranslateArgs(...args);
|
const missingWarn = shared.isBoolean(options.missingWarn)
|
? options.missingWarn
|
: context.missingWarn;
|
const fallbackWarn = shared.isBoolean(options.fallbackWarn)
|
? options.fallbackWarn
|
: context.fallbackWarn;
|
const escapeParameter = shared.isBoolean(options.escapeParameter)
|
? options.escapeParameter
|
: context.escapeParameter;
|
const resolvedMessage = !!options.resolvedMessage;
|
// prettier-ignore
|
const defaultMsgOrKey = shared.isString(options.default) || shared.isBoolean(options.default) // default by function option
|
? !shared.isBoolean(options.default)
|
? options.default
|
: key
|
: fallbackFormat // default by `fallbackFormat` option
|
? key
|
: '';
|
const enableDefaultMsg = fallbackFormat || defaultMsgOrKey !== '';
|
const locale = shared.isString(options.locale) ? options.locale : context.locale;
|
// escape params
|
escapeParameter && escapeParams(options);
|
// resolve message format
|
// eslint-disable-next-line prefer-const
|
let [format, targetLocale, message] = !resolvedMessage
|
? resolveMessageFormat(context, key, locale, fallbackLocale, fallbackWarn, missingWarn)
|
: [
|
key,
|
locale,
|
messages[locale] || {}
|
];
|
// if you use default message, set it as message format!
|
let cacheBaseKey = key;
|
if (!resolvedMessage &&
|
!(shared.isString(format) || isMessageFunction(format))) {
|
if (enableDefaultMsg) {
|
format = defaultMsgOrKey;
|
cacheBaseKey = format;
|
}
|
}
|
// checking message format and target locale
|
if (!resolvedMessage &&
|
(!(shared.isString(format) || isMessageFunction(format)) ||
|
!shared.isString(targetLocale))) {
|
return unresolving ? NOT_REOSLVED : key;
|
}
|
if (shared.isString(format) && context.messageCompiler == null) {
|
shared.warn(`The message format compilation is not supported in this build. ` +
|
`Because message compiler isn't included. ` +
|
`You need to pre-compilation all message format. ` +
|
`So translate function return '${key}'.`);
|
return key;
|
}
|
// setup compile error detecting
|
let occurred = false;
|
const errorDetector = () => {
|
occurred = true;
|
};
|
// compile message format
|
const msg = !isMessageFunction(format)
|
? compileMessageFormat(context, key, targetLocale, format, cacheBaseKey, errorDetector)
|
: format;
|
// if occurred compile error, return the message format
|
if (occurred) {
|
return format;
|
}
|
// evaluate message with context
|
const ctxOptions = getMessageContextOptions(context, targetLocale, message, options);
|
const msgContext = runtime.createMessageContext(ctxOptions);
|
const messaged = evaluateMessage(context, msg, msgContext);
|
// if use post translation option, proceed it with handler
|
const ret = postTranslation ? postTranslation(messaged) : messaged;
|
// NOTE: experimental !!
|
{
|
// prettier-ignore
|
const payloads = {
|
timestamp: Date.now(),
|
key: shared.isString(key)
|
? key
|
: isMessageFunction(format)
|
? format.key
|
: '',
|
locale: targetLocale || (isMessageFunction(format)
|
? format.locale
|
: ''),
|
format: shared.isString(format)
|
? format
|
: isMessageFunction(format)
|
? format.source
|
: '',
|
message: ret
|
};
|
payloads.meta = shared.assign({}, context.__meta, getAdditionalMeta() || {});
|
translateDevTools(payloads);
|
}
|
return ret;
|
}
|
function escapeParams(options) {
|
if (shared.isArray(options.list)) {
|
options.list = options.list.map(item => shared.isString(item) ? shared.escapeHtml(item) : item);
|
}
|
else if (shared.isObject(options.named)) {
|
Object.keys(options.named).forEach(key => {
|
if (shared.isString(options.named[key])) {
|
options.named[key] = shared.escapeHtml(options.named[key]);
|
}
|
});
|
}
|
}
|
function resolveMessageFormat(context, key, locale, fallbackLocale, fallbackWarn, missingWarn) {
|
const { messages, onWarn } = context;
|
const locales = getLocaleChain(context, fallbackLocale, locale);
|
let message = {};
|
let targetLocale;
|
let format = null;
|
let from = locale;
|
let to = null;
|
const type = 'translate';
|
for (let i = 0; i < locales.length; i++) {
|
targetLocale = to = locales[i];
|
if (locale !== targetLocale &&
|
isTranslateFallbackWarn(fallbackWarn, key)) {
|
onWarn(getWarnMessage(1 /* FALLBACK_TO_TRANSLATE */, {
|
key,
|
target: targetLocale
|
}));
|
}
|
// for vue-devtools timeline event
|
if (locale !== targetLocale) {
|
const emitter = context.__v_emitter;
|
if (emitter) {
|
emitter.emit("fallback" /* FALBACK */, {
|
type,
|
key,
|
from,
|
to,
|
groupId: `${type}:${key}`
|
});
|
}
|
}
|
message =
|
messages[targetLocale] || {};
|
// for vue-devtools timeline event
|
let start = null;
|
let startTag;
|
let endTag;
|
if (shared.inBrowser) {
|
start = window.performance.now();
|
startTag = 'intlify-message-resolve-start';
|
endTag = 'intlify-message-resolve-end';
|
shared.mark && shared.mark(startTag);
|
}
|
if ((format = messageResolver.resolveValue(message, key)) === null) {
|
// if null, resolve with object key path
|
format = message[key]; // eslint-disable-line @typescript-eslint/no-explicit-any
|
}
|
// for vue-devtools timeline event
|
if (shared.inBrowser) {
|
const end = window.performance.now();
|
const emitter = context.__v_emitter;
|
if (emitter && start && format) {
|
emitter.emit("message-resolve" /* MESSAGE_RESOLVE */, {
|
type: "message-resolve" /* MESSAGE_RESOLVE */,
|
key,
|
message: format,
|
time: end - start,
|
groupId: `${type}:${key}`
|
});
|
}
|
if (startTag && endTag && shared.mark && shared.measure) {
|
shared.mark(endTag);
|
shared.measure('intlify message resolve', startTag, endTag);
|
}
|
}
|
if (shared.isString(format) || shared.isFunction(format))
|
break;
|
const missingRet = handleMissing(context, key, targetLocale, missingWarn, type);
|
if (missingRet !== key) {
|
format = missingRet;
|
}
|
from = to;
|
}
|
return [format, targetLocale, message];
|
}
|
function compileMessageFormat(context, key, targetLocale, format, cacheBaseKey, errorDetector) {
|
const { messageCompiler, warnHtmlMessage } = context;
|
if (isMessageFunction(format)) {
|
const msg = format;
|
msg.locale = msg.locale || targetLocale;
|
msg.key = msg.key || key;
|
return msg;
|
}
|
// for vue-devtools timeline event
|
let start = null;
|
let startTag;
|
let endTag;
|
if (shared.inBrowser) {
|
start = window.performance.now();
|
startTag = 'intlify-message-compilation-start';
|
endTag = 'intlify-message-compilation-end';
|
shared.mark && shared.mark(startTag);
|
}
|
const msg = messageCompiler(format, getCompileOptions(context, targetLocale, cacheBaseKey, format, warnHtmlMessage, errorDetector));
|
// for vue-devtools timeline event
|
if (shared.inBrowser) {
|
const end = window.performance.now();
|
const emitter = context.__v_emitter;
|
if (emitter && start) {
|
emitter.emit("message-compilation" /* MESSAGE_COMPILATION */, {
|
type: "message-compilation" /* MESSAGE_COMPILATION */,
|
message: format,
|
time: end - start,
|
groupId: `${'translate'}:${key}`
|
});
|
}
|
if (startTag && endTag && shared.mark && shared.measure) {
|
shared.mark(endTag);
|
shared.measure('intlify message compilation', startTag, endTag);
|
}
|
}
|
msg.locale = targetLocale;
|
msg.key = key;
|
msg.source = format;
|
return msg;
|
}
|
function evaluateMessage(context, msg, msgCtx) {
|
// for vue-devtools timeline event
|
let start = null;
|
let startTag;
|
let endTag;
|
if (shared.inBrowser) {
|
start = window.performance.now();
|
startTag = 'intlify-message-evaluation-start';
|
endTag = 'intlify-message-evaluation-end';
|
shared.mark && shared.mark(startTag);
|
}
|
const messaged = msg(msgCtx);
|
// for vue-devtools timeline event
|
if (shared.inBrowser) {
|
const end = window.performance.now();
|
const emitter = context.__v_emitter;
|
if (emitter && start) {
|
emitter.emit("message-evaluation" /* MESSAGE_EVALUATION */, {
|
type: "message-evaluation" /* MESSAGE_EVALUATION */,
|
value: messaged,
|
time: end - start,
|
groupId: `${'translate'}:${msg.key}`
|
});
|
}
|
if (startTag && endTag && shared.mark && shared.measure) {
|
shared.mark(endTag);
|
shared.measure('intlify message evaluation', startTag, endTag);
|
}
|
}
|
return messaged;
|
}
|
/** @internal */
|
function parseTranslateArgs(...args) {
|
const [arg1, arg2, arg3] = args;
|
const options = {};
|
if (!shared.isString(arg1) && !shared.isNumber(arg1) && !isMessageFunction(arg1)) {
|
throw createCoreError(14 /* INVALID_ARGUMENT */);
|
}
|
// prettier-ignore
|
const key = shared.isNumber(arg1)
|
? String(arg1)
|
: isMessageFunction(arg1)
|
? arg1
|
: arg1;
|
if (shared.isNumber(arg2)) {
|
options.plural = arg2;
|
}
|
else if (shared.isString(arg2)) {
|
options.default = arg2;
|
}
|
else if (shared.isPlainObject(arg2) && !shared.isEmptyObject(arg2)) {
|
options.named = arg2;
|
}
|
else if (shared.isArray(arg2)) {
|
options.list = arg2;
|
}
|
if (shared.isNumber(arg3)) {
|
options.plural = arg3;
|
}
|
else if (shared.isString(arg3)) {
|
options.default = arg3;
|
}
|
else if (shared.isPlainObject(arg3)) {
|
shared.assign(options, arg3);
|
}
|
return [key, options];
|
}
|
function getCompileOptions(context, locale, key, source, warnHtmlMessage, errorDetector) {
|
return {
|
warnHtmlMessage,
|
onError: (err) => {
|
errorDetector && errorDetector(err);
|
{
|
const message = `Message compilation error: ${err.message}`;
|
const codeFrame = err.location &&
|
shared.generateCodeFrame(source, err.location.start.offset, err.location.end.offset);
|
const emitter = context
|
.__v_emitter;
|
if (emitter) {
|
emitter.emit("compile-error" /* COMPILE_ERROR */, {
|
message: source,
|
error: err.message,
|
start: err.location && err.location.start.offset,
|
end: err.location && err.location.end.offset,
|
groupId: `${'translate'}:${key}`
|
});
|
}
|
console.error(codeFrame ? `${message}\n${codeFrame}` : message);
|
}
|
},
|
onCacheKey: (source) => shared.generateFormatCacheKey(locale, key, source)
|
};
|
}
|
function getMessageContextOptions(context, locale, message, options) {
|
const { modifiers, pluralRules } = context;
|
const resolveMessage = (key) => {
|
const val = messageResolver.resolveValue(message, key);
|
if (shared.isString(val)) {
|
let occurred = false;
|
const errorDetector = () => {
|
occurred = true;
|
};
|
const msg = compileMessageFormat(context, key, locale, val, key, errorDetector);
|
return !occurred
|
? msg
|
: NOOP_MESSAGE_FUNCTION;
|
}
|
else if (isMessageFunction(val)) {
|
return val;
|
}
|
else {
|
// TODO: should be implemented warning message
|
return NOOP_MESSAGE_FUNCTION;
|
}
|
};
|
const ctxOptions = {
|
locale,
|
modifiers,
|
pluralRules,
|
messages: resolveMessage
|
};
|
if (context.processor) {
|
ctxOptions.processor = context.processor;
|
}
|
if (options.list) {
|
ctxOptions.list = options.list;
|
}
|
if (options.named) {
|
ctxOptions.named = options.named;
|
}
|
if (shared.isNumber(options.plural)) {
|
ctxOptions.pluralIndex = options.plural;
|
}
|
return ctxOptions;
|
}
|
|
const intlDefined = typeof Intl !== 'undefined';
|
const Availabilities = {
|
dateTimeFormat: intlDefined && typeof Intl.DateTimeFormat !== 'undefined',
|
numberFormat: intlDefined && typeof Intl.NumberFormat !== 'undefined'
|
};
|
|
// implementation of `datetime` function
|
function datetime(context, ...args) {
|
const { datetimeFormats, unresolving, fallbackLocale, onWarn } = context;
|
const { __datetimeFormatters } = context;
|
if (!Availabilities.dateTimeFormat) {
|
onWarn(getWarnMessage(4 /* CANNOT_FORMAT_DATE */));
|
return MISSING_RESOLVE_VALUE;
|
}
|
const [key, value, options, overrides] = parseDateTimeArgs(...args);
|
const missingWarn = shared.isBoolean(options.missingWarn)
|
? options.missingWarn
|
: context.missingWarn;
|
const fallbackWarn = shared.isBoolean(options.fallbackWarn)
|
? options.fallbackWarn
|
: context.fallbackWarn;
|
const part = !!options.part;
|
const locale = shared.isString(options.locale) ? options.locale : context.locale;
|
const locales = getLocaleChain(context, fallbackLocale, locale);
|
if (!shared.isString(key) || key === '') {
|
return new Intl.DateTimeFormat(locale).format(value);
|
}
|
// resolve format
|
let datetimeFormat = {};
|
let targetLocale;
|
let format = null;
|
let from = locale;
|
let to = null;
|
const type = 'datetime format';
|
for (let i = 0; i < locales.length; i++) {
|
targetLocale = to = locales[i];
|
if (locale !== targetLocale &&
|
isTranslateFallbackWarn(fallbackWarn, key)) {
|
onWarn(getWarnMessage(5 /* FALLBACK_TO_DATE_FORMAT */, {
|
key,
|
target: targetLocale
|
}));
|
}
|
// for vue-devtools timeline event
|
if (locale !== targetLocale) {
|
const emitter = context.__v_emitter;
|
if (emitter) {
|
emitter.emit("fallback" /* FALBACK */, {
|
type,
|
key,
|
from,
|
to,
|
groupId: `${type}:${key}`
|
});
|
}
|
}
|
datetimeFormat =
|
datetimeFormats[targetLocale] || {};
|
format = datetimeFormat[key];
|
if (shared.isPlainObject(format))
|
break;
|
handleMissing(context, key, targetLocale, missingWarn, type);
|
from = to;
|
}
|
// checking format and target locale
|
if (!shared.isPlainObject(format) || !shared.isString(targetLocale)) {
|
return unresolving ? NOT_REOSLVED : key;
|
}
|
let id = `${targetLocale}__${key}`;
|
if (!shared.isEmptyObject(overrides)) {
|
id = `${id}__${JSON.stringify(overrides)}`;
|
}
|
let formatter = __datetimeFormatters.get(id);
|
if (!formatter) {
|
formatter = new Intl.DateTimeFormat(targetLocale, shared.assign({}, format, overrides));
|
__datetimeFormatters.set(id, formatter);
|
}
|
return !part ? formatter.format(value) : formatter.formatToParts(value);
|
}
|
/** @internal */
|
function parseDateTimeArgs(...args) {
|
const [arg1, arg2, arg3, arg4] = args;
|
let options = {};
|
let overrides = {};
|
let value;
|
if (shared.isString(arg1)) {
|
// Only allow ISO strings - other date formats are often supported,
|
// but may cause different results in different browsers.
|
if (!/\d{4}-\d{2}-\d{2}(T.*)?/.test(arg1)) {
|
throw createCoreError(16 /* INVALID_ISO_DATE_ARGUMENT */);
|
}
|
value = new Date(arg1);
|
try {
|
// This will fail if the date is not valid
|
value.toISOString();
|
}
|
catch (e) {
|
throw createCoreError(16 /* INVALID_ISO_DATE_ARGUMENT */);
|
}
|
}
|
else if (shared.isDate(arg1)) {
|
if (isNaN(arg1.getTime())) {
|
throw createCoreError(15 /* INVALID_DATE_ARGUMENT */);
|
}
|
value = arg1;
|
}
|
else if (shared.isNumber(arg1)) {
|
value = arg1;
|
}
|
else {
|
throw createCoreError(14 /* INVALID_ARGUMENT */);
|
}
|
if (shared.isString(arg2)) {
|
options.key = arg2;
|
}
|
else if (shared.isPlainObject(arg2)) {
|
options = arg2;
|
}
|
if (shared.isString(arg3)) {
|
options.locale = arg3;
|
}
|
else if (shared.isPlainObject(arg3)) {
|
overrides = arg3;
|
}
|
if (shared.isPlainObject(arg4)) {
|
overrides = arg4;
|
}
|
return [options.key || '', value, options, overrides];
|
}
|
/** @internal */
|
function clearDateTimeFormat(ctx, locale, format) {
|
const context = ctx;
|
for (const key in format) {
|
const id = `${locale}__${key}`;
|
if (!context.__datetimeFormatters.has(id)) {
|
continue;
|
}
|
context.__datetimeFormatters.delete(id);
|
}
|
}
|
|
// implementation of `number` function
|
function number(context, ...args) {
|
const { numberFormats, unresolving, fallbackLocale, onWarn } = context;
|
const { __numberFormatters } = context;
|
if (!Availabilities.numberFormat) {
|
onWarn(getWarnMessage(2 /* CANNOT_FORMAT_NUMBER */));
|
return MISSING_RESOLVE_VALUE;
|
}
|
const [key, value, options, overrides] = parseNumberArgs(...args);
|
const missingWarn = shared.isBoolean(options.missingWarn)
|
? options.missingWarn
|
: context.missingWarn;
|
const fallbackWarn = shared.isBoolean(options.fallbackWarn)
|
? options.fallbackWarn
|
: context.fallbackWarn;
|
const part = !!options.part;
|
const locale = shared.isString(options.locale) ? options.locale : context.locale;
|
const locales = getLocaleChain(context, fallbackLocale, locale);
|
if (!shared.isString(key) || key === '') {
|
return new Intl.NumberFormat(locale).format(value);
|
}
|
// resolve format
|
let numberFormat = {};
|
let targetLocale;
|
let format = null;
|
let from = locale;
|
let to = null;
|
const type = 'number format';
|
for (let i = 0; i < locales.length; i++) {
|
targetLocale = to = locales[i];
|
if (locale !== targetLocale &&
|
isTranslateFallbackWarn(fallbackWarn, key)) {
|
onWarn(getWarnMessage(3 /* FALLBACK_TO_NUMBER_FORMAT */, {
|
key,
|
target: targetLocale
|
}));
|
}
|
// for vue-devtools timeline event
|
if (locale !== targetLocale) {
|
const emitter = context.__v_emitter;
|
if (emitter) {
|
emitter.emit("fallback" /* FALBACK */, {
|
type,
|
key,
|
from,
|
to,
|
groupId: `${type}:${key}`
|
});
|
}
|
}
|
numberFormat =
|
numberFormats[targetLocale] || {};
|
format = numberFormat[key];
|
if (shared.isPlainObject(format))
|
break;
|
handleMissing(context, key, targetLocale, missingWarn, type);
|
from = to;
|
}
|
// checking format and target locale
|
if (!shared.isPlainObject(format) || !shared.isString(targetLocale)) {
|
return unresolving ? NOT_REOSLVED : key;
|
}
|
let id = `${targetLocale}__${key}`;
|
if (!shared.isEmptyObject(overrides)) {
|
id = `${id}__${JSON.stringify(overrides)}`;
|
}
|
let formatter = __numberFormatters.get(id);
|
if (!formatter) {
|
formatter = new Intl.NumberFormat(targetLocale, shared.assign({}, format, overrides));
|
__numberFormatters.set(id, formatter);
|
}
|
return !part ? formatter.format(value) : formatter.formatToParts(value);
|
}
|
/** @internal */
|
function parseNumberArgs(...args) {
|
const [arg1, arg2, arg3, arg4] = args;
|
let options = {};
|
let overrides = {};
|
if (!shared.isNumber(arg1)) {
|
throw createCoreError(14 /* INVALID_ARGUMENT */);
|
}
|
const value = arg1;
|
if (shared.isString(arg2)) {
|
options.key = arg2;
|
}
|
else if (shared.isPlainObject(arg2)) {
|
options = arg2;
|
}
|
if (shared.isString(arg3)) {
|
options.locale = arg3;
|
}
|
else if (shared.isPlainObject(arg3)) {
|
overrides = arg3;
|
}
|
if (shared.isPlainObject(arg4)) {
|
overrides = arg4;
|
}
|
return [options.key || '', value, options, overrides];
|
}
|
/** @internal */
|
function clearNumberFormat(ctx, locale, format) {
|
const context = ctx;
|
for (const key in format) {
|
const id = `${locale}__${key}`;
|
if (!context.__numberFormatters.has(id)) {
|
continue;
|
}
|
context.__numberFormatters.delete(id);
|
}
|
}
|
|
exports.createCompileError = messageCompiler.createCompileError;
|
exports.MISSING_RESOLVE_VALUE = MISSING_RESOLVE_VALUE;
|
exports.NOT_REOSLVED = NOT_REOSLVED;
|
exports.VERSION = VERSION;
|
exports.clearCompileCache = clearCompileCache;
|
exports.clearDateTimeFormat = clearDateTimeFormat;
|
exports.clearNumberFormat = clearNumberFormat;
|
exports.compileToFunction = compileToFunction;
|
exports.createCoreContext = createCoreContext;
|
exports.createCoreError = createCoreError;
|
exports.datetime = datetime;
|
exports.getAdditionalMeta = getAdditionalMeta;
|
exports.getDevToolsHook = getDevToolsHook;
|
exports.getLocaleChain = getLocaleChain;
|
exports.getWarnMessage = getWarnMessage;
|
exports.handleMissing = handleMissing;
|
exports.initI18nDevTools = initI18nDevTools;
|
exports.isMessageFunction = isMessageFunction;
|
exports.isTranslateFallbackWarn = isTranslateFallbackWarn;
|
exports.isTranslateMissingWarn = isTranslateMissingWarn;
|
exports.number = number;
|
exports.parseDateTimeArgs = parseDateTimeArgs;
|
exports.parseNumberArgs = parseNumberArgs;
|
exports.parseTranslateArgs = parseTranslateArgs;
|
exports.registerMessageCompiler = registerMessageCompiler;
|
exports.setAdditionalMeta = setAdditionalMeta;
|
exports.setDevToolsHook = setDevToolsHook;
|
exports.translate = translate;
|
exports.translateDevTools = translateDevTools;
|
exports.updateFallbackLocale = updateFallbackLocale;
|
Object.keys(messageResolver).forEach(function (k) {
|
if (k !== 'default' && !exports.hasOwnProperty(k)) exports[k] = messageResolver[k];
|
});
|
Object.keys(runtime).forEach(function (k) {
|
if (k !== 'default' && !exports.hasOwnProperty(k)) exports[k] = runtime[k];
|
});
|