更新
This commit is contained in:
+989
@@ -0,0 +1,989 @@
|
||||
/*!
|
||||
* @intlify/core-base v9.1.9
|
||||
* (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.9';
|
||||
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];
|
||||
});
|
||||
+735
@@ -0,0 +1,735 @@
|
||||
/*!
|
||||
* @intlify/core-base v9.1.9
|
||||
* (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.9';
|
||||
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
|
||||
};
|
||||
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;
|
||||
if (missing !== null) {
|
||||
const ret = missing(context, locale, key, type);
|
||||
return shared.isString(ret) ? ret : key;
|
||||
}
|
||||
else {
|
||||
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 defaultOnCacheKey = (source) => source;
|
||||
let compileCache = Object.create(null);
|
||||
function clearCompileCache() {
|
||||
compileCache = Object.create(null);
|
||||
}
|
||||
function compileToFunction(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, undefined);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
// 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;
|
||||
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;
|
||||
const type = 'translate';
|
||||
for (let i = 0; i < locales.length; i++) {
|
||||
targetLocale = locales[i];
|
||||
message =
|
||||
messages[targetLocale] || {};
|
||||
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
|
||||
}
|
||||
if (shared.isString(format) || shared.isFunction(format))
|
||||
break;
|
||||
const missingRet = handleMissing(context, key, targetLocale, missingWarn, type);
|
||||
if (missingRet !== key) {
|
||||
format = missingRet;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
const msg = messageCompiler(format, getCompileOptions(context, targetLocale, cacheBaseKey, format, warnHtmlMessage, errorDetector));
|
||||
msg.locale = targetLocale;
|
||||
msg.key = key;
|
||||
msg.source = format;
|
||||
return msg;
|
||||
}
|
||||
function evaluateMessage(context, msg, msgCtx) {
|
||||
const messaged = msg(msgCtx);
|
||||
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);
|
||||
{
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
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;
|
||||
}
|
||||
|
||||
// implementation of `datetime` function
|
||||
function datetime(context, ...args) {
|
||||
const { datetimeFormats, unresolving, fallbackLocale, onWarn } = context;
|
||||
const { __datetimeFormatters } = context;
|
||||
const [key, value, options, overrides] = parseDateTimeArgs(...args);
|
||||
const missingWarn = shared.isBoolean(options.missingWarn)
|
||||
? options.missingWarn
|
||||
: context.missingWarn;
|
||||
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;
|
||||
const type = 'datetime format';
|
||||
for (let i = 0; i < locales.length; i++) {
|
||||
targetLocale = locales[i];
|
||||
datetimeFormat =
|
||||
datetimeFormats[targetLocale] || {};
|
||||
format = datetimeFormat[key];
|
||||
if (shared.isPlainObject(format))
|
||||
break;
|
||||
handleMissing(context, key, targetLocale, missingWarn, type);
|
||||
}
|
||||
// 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;
|
||||
const [key, value, options, overrides] = parseNumberArgs(...args);
|
||||
const missingWarn = shared.isBoolean(options.missingWarn)
|
||||
? options.missingWarn
|
||||
: context.missingWarn;
|
||||
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;
|
||||
const type = 'number format';
|
||||
for (let i = 0; i < locales.length; i++) {
|
||||
targetLocale = locales[i];
|
||||
numberFormat =
|
||||
numberFormats[targetLocale] || {};
|
||||
format = numberFormat[key];
|
||||
if (shared.isPlainObject(format))
|
||||
break;
|
||||
handleMissing(context, key, targetLocale, missingWarn, type);
|
||||
}
|
||||
// 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];
|
||||
});
|
||||
+576
@@ -0,0 +1,576 @@
|
||||
import { CompileError } from '@intlify/message-compiler';
|
||||
import { CompileErrorCodes } from '@intlify/message-compiler';
|
||||
import type { CompileOptions } from '@intlify/message-compiler';
|
||||
import type { CoreMissingType } from '@intlify/runtime';
|
||||
import { createCompileError } from '@intlify/message-compiler';
|
||||
import type { FallbackLocale } from '@intlify/runtime';
|
||||
import type { IntlifyDevToolsEmitter } from '@intlify/devtools-if';
|
||||
import type { IntlifyDevToolsHookPayloads } from '@intlify/devtools-if';
|
||||
import { IntlifyDevToolsHooks } from '@intlify/devtools-if';
|
||||
import type { LinkedModifiers } from '@intlify/runtime';
|
||||
import type { Locale } from '@intlify/runtime';
|
||||
import type { MessageFunction } from '@intlify/runtime';
|
||||
import type { MessageProcessor } from '@intlify/runtime';
|
||||
import type { MessageType } from '@intlify/runtime';
|
||||
import type { NamedValue } from '@intlify/runtime';
|
||||
import type { Path } from '@intlify/message-resolver';
|
||||
import type { PluralizationRules } from '@intlify/runtime';
|
||||
import type { VueDevToolsEmitter } from '@intlify/vue-devtools';
|
||||
|
||||
export declare function clearCompileCache(): void;
|
||||
|
||||
/* Excluded from this release type: clearDateTimeFormat */
|
||||
|
||||
/* Excluded from this release type: clearNumberFormat */
|
||||
export { CompileError }
|
||||
export { CompileErrorCodes }
|
||||
|
||||
export declare function compileToFunction<T = string>(source: string, options?: CompileOptions): MessageFunction<T>;
|
||||
|
||||
export declare interface CoreCommonContext<Message = string> {
|
||||
cid: number;
|
||||
version: string;
|
||||
locale: Locale;
|
||||
fallbackLocale: FallbackLocale;
|
||||
missing: CoreMissingHandler<Message> | null;
|
||||
missingWarn: boolean | RegExp;
|
||||
fallbackWarn: boolean | RegExp;
|
||||
fallbackFormat: boolean;
|
||||
unresolving: boolean;
|
||||
onWarn(msg: string, err?: Error): void;
|
||||
}
|
||||
|
||||
export declare interface CoreContext<Messages = {}, DateTimeFormats = {}, NumberFormats = {}, Message = string> extends CoreTranslationContext<Messages, Message>, CoreDateTimeContext<DateTimeFormats, Message>, CoreNumberContext<NumberFormats, Message> {
|
||||
}
|
||||
|
||||
export declare interface CoreDateTimeContext<DateTimeFormats = {}, Message = string> extends CoreCommonContext<Message> {
|
||||
datetimeFormats: DateTimeFormats;
|
||||
}
|
||||
|
||||
export declare interface CoreError extends CompileError {
|
||||
code: CoreErrorCodes;
|
||||
}
|
||||
|
||||
export declare const enum CoreErrorCodes {
|
||||
INVALID_ARGUMENT = 14,
|
||||
INVALID_DATE_ARGUMENT = 15,
|
||||
INVALID_ISO_DATE_ARGUMENT = 16,
|
||||
__EXTEND_POINT__ = 17
|
||||
}
|
||||
|
||||
export declare interface CoreInternalContext {
|
||||
__datetimeFormatters: Map<string, Intl.DateTimeFormat>;
|
||||
__numberFormatters: Map<string, Intl.NumberFormat>;
|
||||
__localeChainCache?: Map<Locale, Locale[]>;
|
||||
__v_emitter?: VueDevToolsEmitter;
|
||||
__meta: MetaInfo;
|
||||
}
|
||||
|
||||
export declare interface CoreInternalOptions {
|
||||
__datetimeFormatters?: Map<string, Intl.DateTimeFormat>;
|
||||
__numberFormatters?: Map<string, Intl.NumberFormat>;
|
||||
__v_emitter?: VueDevToolsEmitter;
|
||||
__meta?: MetaInfo;
|
||||
}
|
||||
|
||||
export declare type CoreMissingHandler<Message = string> = (context: CoreCommonContext<Message>, locale: Locale, key: Path, type: CoreMissingType, ...values: unknown[]) => string | void;
|
||||
|
||||
export declare interface CoreNumberContext<NumberFormats = {}, Message = string> extends CoreCommonContext<Message> {
|
||||
numberFormats: NumberFormats;
|
||||
}
|
||||
|
||||
export declare interface CoreOptions<Message = string> {
|
||||
version?: string;
|
||||
locale?: Locale;
|
||||
fallbackLocale?: FallbackLocale;
|
||||
messages?: LocaleMessages<Message>;
|
||||
datetimeFormats?: DateTimeFormats;
|
||||
numberFormats?: NumberFormats;
|
||||
modifiers?: LinkedModifiers<Message>;
|
||||
pluralRules?: PluralizationRules;
|
||||
missing?: CoreMissingHandler<Message>;
|
||||
missingWarn?: boolean | RegExp;
|
||||
fallbackWarn?: boolean | RegExp;
|
||||
fallbackFormat?: boolean;
|
||||
unresolving?: boolean;
|
||||
postTranslation?: PostTranslationHandler<Message>;
|
||||
processor?: MessageProcessor<Message>;
|
||||
warnHtmlMessage?: boolean;
|
||||
escapeParameter?: boolean;
|
||||
messageCompiler?: MessageCompiler<Message>;
|
||||
onWarn?: (msg: string, err?: Error) => void;
|
||||
}
|
||||
|
||||
export declare interface CoreTranslationContext<Messages = {}, Message = string> extends CoreCommonContext<Message> {
|
||||
messages: Messages;
|
||||
modifiers: LinkedModifiers<Message>;
|
||||
pluralRules?: PluralizationRules;
|
||||
postTranslation: PostTranslationHandler<Message> | null;
|
||||
processor: MessageProcessor<Message> | null;
|
||||
warnHtmlMessage: boolean;
|
||||
escapeParameter: boolean;
|
||||
messageCompiler: MessageCompiler<Message> | null;
|
||||
}
|
||||
|
||||
export declare const enum CoreWarnCodes {
|
||||
NOT_FOUND_KEY = 0,
|
||||
FALLBACK_TO_TRANSLATE = 1,
|
||||
CANNOT_FORMAT_NUMBER = 2,
|
||||
FALLBACK_TO_NUMBER_FORMAT = 3,
|
||||
CANNOT_FORMAT_DATE = 4,
|
||||
FALLBACK_TO_DATE_FORMAT = 5,
|
||||
__EXTEND_POINT__ = 6
|
||||
}
|
||||
export { createCompileError }
|
||||
|
||||
export declare function createCoreContext<Message = string, Options extends CoreOptions<Message> = object, Messages extends Record<keyof Options['messages'], LocaleMessageDictionary<Message>> = Record<keyof Options['messages'], LocaleMessageDictionary<Message>>, DateTimeFormats extends Record<keyof Options['datetimeFormats'], DateTimeFormat> = Record<keyof Options['datetimeFormats'], DateTimeFormat>, NumberFormats extends Record<keyof Options['numberFormats'], NumberFormat> = Record<keyof Options['numberFormats'], NumberFormat>>(options?: Options): CoreContext<Options['messages'], Options['datetimeFormats'], Options['numberFormats'], Message>;
|
||||
|
||||
export declare function createCoreError(code: CoreErrorCodes): CoreError;
|
||||
|
||||
/**
|
||||
* number
|
||||
*/
|
||||
export declare type CurrencyDisplay = 'symbol' | 'code' | 'name';
|
||||
|
||||
export declare interface CurrencyNumberFormatOptions extends Intl.NumberFormatOptions {
|
||||
style: 'currency';
|
||||
currency: string;
|
||||
currencyDisplay?: CurrencyDisplay;
|
||||
localeMatcher?: LocaleMatcher;
|
||||
formatMatcher?: FormatMatcher;
|
||||
}
|
||||
|
||||
export declare function datetime<DateTimeFormats, Message = string>(context: CoreDateTimeContext<DateTimeFormats, Message>, value: number | Date): string | number | Intl.DateTimeFormatPart[];
|
||||
|
||||
export declare function datetime<DateTimeFormats, Message = string>(context: CoreDateTimeContext<DateTimeFormats, Message>, value: number | Date, key: string): string | number | Intl.DateTimeFormatPart[];
|
||||
|
||||
export declare function datetime<DateTimeFormats, Message = string>(context: CoreDateTimeContext<DateTimeFormats, Message>, value: number | Date, key: string, locale: Locale): string | number | Intl.DateTimeFormatPart[];
|
||||
|
||||
export declare function datetime<DateTimeFormats, Message = string>(context: CoreDateTimeContext<DateTimeFormats, Message>, value: number | Date, options: DateTimeOptions): string | number | Intl.DateTimeFormatPart[];
|
||||
|
||||
export declare function datetime<DateTimeFormats, Message = string>(context: CoreDateTimeContext<DateTimeFormats, Message>, ...args: unknown[]): string | number | Intl.DateTimeFormatPart[];
|
||||
|
||||
export declare type DateTimeDigital = 'numeric' | '2-digit';
|
||||
|
||||
export declare type DateTimeFormat = {
|
||||
[key: string]: DateTimeFormatOptions;
|
||||
};
|
||||
|
||||
export declare type DateTimeFormatOptions = Intl.DateTimeFormatOptions | SpecificDateTimeFormatOptions;
|
||||
|
||||
export declare type DateTimeFormats = {
|
||||
[locale: string]: DateTimeFormat;
|
||||
};
|
||||
|
||||
/**
|
||||
* datetime
|
||||
*/
|
||||
export declare type DateTimeHumanReadable = 'long' | 'short' | 'narrow';
|
||||
|
||||
/**
|
||||
* # datetime
|
||||
*
|
||||
* ## usages:
|
||||
* // for example `context.datetimeFormats` below
|
||||
* 'en-US': {
|
||||
* short: {
|
||||
* year: 'numeric', month: '2-digit', day: '2-digit',
|
||||
* hour: '2-digit', minute: '2-digit'
|
||||
* }
|
||||
* },
|
||||
* 'ja-JP': { ... }
|
||||
*
|
||||
* // datetimeable value only
|
||||
* datetime(context, value)
|
||||
*
|
||||
* // key argument
|
||||
* datetime(context, value, 'short')
|
||||
*
|
||||
* // key & locale argument
|
||||
* datetime(context, value, 'short', 'ja-JP')
|
||||
*
|
||||
* // object sytle argument
|
||||
* datetime(context, value, { key: 'short', locale: 'ja-JP' })
|
||||
*
|
||||
* // suppress localize miss warning option, override context.missingWarn
|
||||
* datetime(context, value, { key: 'short', locale: 'ja-JP', missingWarn: false })
|
||||
*
|
||||
* // suppress localize fallback warning option, override context.fallbackWarn
|
||||
* datetime(context, value, { key: 'short', locale: 'ja-JP', fallbackWarn: false })
|
||||
*
|
||||
* // if you specify `part` options, you can get an array of objects containing the formatted datetime in parts
|
||||
* datetime(context, value, { key: 'short', part: true })
|
||||
*
|
||||
* // orverride context.datetimeFormats[locale] options with functino options
|
||||
* datetime(cnotext, value, 'short', { currency: 'EUR' })
|
||||
* datetime(cnotext, value, 'short', 'ja-JP', { currency: 'EUR' })
|
||||
* datetime(context, value, { key: 'short', part: true }, { currency: 'EUR'})
|
||||
*/
|
||||
/**
|
||||
* DateTime options
|
||||
*
|
||||
* @remarks
|
||||
* Options for Datetime formatting API
|
||||
*
|
||||
* @VueI18nGeneral
|
||||
*/
|
||||
export declare interface DateTimeOptions {
|
||||
/**
|
||||
* @remarks
|
||||
* The target format key
|
||||
*/
|
||||
key?: string;
|
||||
/**
|
||||
* @remarks
|
||||
* The locale of localization
|
||||
*/
|
||||
locale?: Locale;
|
||||
/**
|
||||
* @remarks
|
||||
* Whether suppress warnings outputted when localization fails
|
||||
*/
|
||||
missingWarn?: boolean;
|
||||
/**
|
||||
* @remarks
|
||||
* Whether do resolve on format keys when your language lacks a formatting for a key
|
||||
*/
|
||||
fallbackWarn?: boolean;
|
||||
/**
|
||||
* @remarks
|
||||
* Whether to use [Intel.DateTimeFormat#formatToParts](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/formatToParts)
|
||||
*/
|
||||
part?: boolean;
|
||||
}
|
||||
|
||||
export declare type FormatMatcher = 'basic' | 'best fit';
|
||||
|
||||
export declare type FormattedNumberPart = {
|
||||
type: FormattedNumberPartType;
|
||||
value: string;
|
||||
};
|
||||
|
||||
export declare type FormattedNumberPartType = 'currency' | 'decimal' | 'fraction' | 'group' | 'infinity' | 'integer' | 'literal' | 'minusSign' | 'nan' | 'plusSign' | 'percentSign';
|
||||
|
||||
export declare const getAdditionalMeta: () => MetaInfo | null;
|
||||
|
||||
export declare function getDevToolsHook(): IntlifyDevToolsEmitter | null;
|
||||
|
||||
/* Excluded from this release type: getLocaleChain */
|
||||
|
||||
export declare function getWarnMessage(code: CoreWarnCodes, ...args: unknown[]): string;
|
||||
|
||||
/* Excluded from this release type: handleMissing */
|
||||
|
||||
export declare function initI18nDevTools(i18n: unknown, version: string, meta?: Record<string, unknown>): void;
|
||||
|
||||
export declare const isMessageFunction: <T>(val: unknown) => val is MessageFunction<T>;
|
||||
|
||||
/* Excluded from this release type: isTranslateFallbackWarn */
|
||||
|
||||
/* Excluded from this release type: isTranslateMissingWarn */
|
||||
|
||||
export declare type LocaleMatcher = 'lookup' | 'best fit';
|
||||
|
||||
/** @VueI18nGeneral */
|
||||
export declare interface LocaleMessageArray<Message = string> extends Array<LocaleMessageValue<Message>> {
|
||||
}
|
||||
|
||||
/** @VueI18nGeneral */
|
||||
export declare type LocaleMessageDictionary<Message = string> = {
|
||||
[property: string]: LocaleMessageValue<Message>;
|
||||
};
|
||||
|
||||
/** @VueI18nGeneral */
|
||||
export declare type LocaleMessages<Message = string> = Record<Locale, LocaleMessageDictionary<Message>>;
|
||||
|
||||
/** @VueI18nGeneral */
|
||||
export declare type LocaleMessageValue<Message = string> = string | MessageFunction<Message> | LocaleMessageDictionary<Message> | LocaleMessageArray<Message>;
|
||||
|
||||
export declare type MessageCompiler<Message = string> = (source: string, options?: CompileOptions) => MessageFunction<Message>;
|
||||
|
||||
export declare interface MetaInfo {
|
||||
[field: string]: unknown;
|
||||
}
|
||||
|
||||
export declare const MISSING_RESOLVE_VALUE = "";
|
||||
|
||||
export declare const NOT_REOSLVED = -1;
|
||||
|
||||
export declare function number<NumberFormats, Message = string>(context: CoreNumberContext<NumberFormats, Message>, value: number): string | number | Intl.NumberFormatPart[];
|
||||
|
||||
export declare function number<NumberFormats, Message = string>(context: CoreNumberContext<NumberFormats, Message>, value: number, key: string): string | number | Intl.NumberFormatPart[];
|
||||
|
||||
export declare function number<NumberFormats, Message = string>(context: CoreNumberContext<NumberFormats, Message>, value: number, key: string, locale: Locale): string | number | Intl.NumberFormatPart[];
|
||||
|
||||
export declare function number<NumberFormats, Message = string>(context: CoreNumberContext<NumberFormats, Message>, value: number, options: NumberOptions): string | number | Intl.NumberFormatPart[];
|
||||
|
||||
export declare function number<NumberFormats, Message = string>(context: CoreNumberContext<NumberFormats, Message>, ...args: unknown[]): string | number | Intl.NumberFormatPart[];
|
||||
|
||||
export declare type NumberFormat = {
|
||||
[key: string]: NumberFormatOptions;
|
||||
};
|
||||
|
||||
export declare type NumberFormatOptions = Intl.NumberFormatOptions | SpecificNumberFormatOptions | CurrencyNumberFormatOptions;
|
||||
|
||||
export declare type NumberFormats = {
|
||||
[locale: string]: NumberFormat;
|
||||
};
|
||||
|
||||
export declare type NumberFormatToPartsResult = {
|
||||
[index: number]: FormattedNumberPart;
|
||||
};
|
||||
|
||||
/**
|
||||
* # number
|
||||
*
|
||||
* ## usages
|
||||
* // for example `context.numberFormats` below
|
||||
* 'en-US': {
|
||||
* 'currency': {
|
||||
* style: 'currency', currency: 'USD', currencyDisplay: 'symbol'
|
||||
* }
|
||||
* },
|
||||
* 'ja-JP: { ... }
|
||||
*
|
||||
* // value only
|
||||
* number(context, value)
|
||||
*
|
||||
* // key argument
|
||||
* number(context, value, 'currency')
|
||||
*
|
||||
* // key & locale argument
|
||||
* number(context, value, 'currency', 'ja-JP')
|
||||
*
|
||||
* // object sytle argument
|
||||
* number(context, value, { key: 'currency', locale: 'ja-JP' })
|
||||
*
|
||||
* // suppress localize miss warning option, override context.missingWarn
|
||||
* number(context, value, { key: 'currency', locale: 'ja-JP', missingWarn: false })
|
||||
*
|
||||
* // suppress localize fallback warning option, override context.fallbackWarn
|
||||
* number(context, value, { key: 'currency', locale: 'ja-JP', fallbackWarn: false })
|
||||
*
|
||||
* // if you specify `part` options, you can get an array of objects containing the formatted number in parts
|
||||
* number(context, value, { key: 'currenty', part: true })
|
||||
*
|
||||
* // orverride context.numberFormats[locale] options with functino options
|
||||
* number(cnotext, value, 'currency', { year: '2-digit' })
|
||||
* number(cnotext, value, 'currency', 'ja-JP', { year: '2-digit' })
|
||||
* number(context, value, { key: 'currenty', part: true }, { year: '2-digit'})
|
||||
*/
|
||||
/**
|
||||
* Number Options
|
||||
*
|
||||
* @remarks
|
||||
* Options for Number formatting API
|
||||
*
|
||||
* @VueI18nGeneral
|
||||
*/
|
||||
export declare interface NumberOptions {
|
||||
/**
|
||||
* @remarks
|
||||
* The target format key
|
||||
*/
|
||||
key?: string;
|
||||
/**
|
||||
* @remarks
|
||||
* The locale of localization
|
||||
*/
|
||||
locale?: Locale;
|
||||
/**
|
||||
* @remarks
|
||||
* Whether suppress warnings outputted when localization fails
|
||||
*/
|
||||
missingWarn?: boolean;
|
||||
/**
|
||||
* @remarks
|
||||
* Whether do resolve on format keys when your language lacks a formatting for a key
|
||||
*/
|
||||
fallbackWarn?: boolean;
|
||||
/**
|
||||
* @remarks
|
||||
* Whether to use [Intel.NumberFormat#formatToParts](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/formatToParts)
|
||||
*/
|
||||
part?: boolean;
|
||||
}
|
||||
|
||||
/* Excluded from this release type: parseDateTimeArgs */
|
||||
|
||||
/* Excluded from this release type: parseNumberArgs */
|
||||
|
||||
/* Excluded from this release type: parseTranslateArgs */
|
||||
|
||||
/** @VueI18nGeneral */
|
||||
export declare type PostTranslationHandler<Message = string> = (translated: MessageType<Message>) => MessageType<Message>;
|
||||
|
||||
export declare function registerMessageCompiler<Message>(compiler: MessageCompiler<Message>): void;
|
||||
|
||||
export declare const setAdditionalMeta: (meta: MetaInfo | null) => void;
|
||||
|
||||
export declare function setDevToolsHook(hook: IntlifyDevToolsEmitter | null): void;
|
||||
|
||||
export declare interface SpecificDateTimeFormatOptions extends Intl.DateTimeFormatOptions {
|
||||
year?: DateTimeDigital;
|
||||
month?: DateTimeDigital | DateTimeHumanReadable;
|
||||
day?: DateTimeDigital;
|
||||
hour?: DateTimeDigital;
|
||||
minute?: DateTimeDigital;
|
||||
second?: DateTimeDigital;
|
||||
weekday?: DateTimeHumanReadable;
|
||||
era?: DateTimeHumanReadable;
|
||||
timeZoneName?: 'long' | 'short';
|
||||
localeMatcher?: LocaleMatcher;
|
||||
formatMatcher?: FormatMatcher;
|
||||
}
|
||||
|
||||
export declare interface SpecificNumberFormatOptions extends Intl.NumberFormatOptions {
|
||||
style?: 'decimal' | 'percent';
|
||||
currency?: string;
|
||||
currencyDisplay?: CurrencyDisplay;
|
||||
localeMatcher?: LocaleMatcher;
|
||||
formatMatcher?: FormatMatcher;
|
||||
}
|
||||
|
||||
export declare function translate<Messages, Message = string>(context: CoreTranslationContext<Messages, Message>, key: Path | number): MessageType<Message> | number;
|
||||
|
||||
export declare function translate<Messages, Message = string>(context: CoreTranslationContext<Messages, Message>, key: Path | number, plural: number): MessageType<Message> | number;
|
||||
|
||||
export declare function translate<Messages, Message = string>(context: CoreTranslationContext<Messages, Message>, key: Path | number, plural: number, options: TranslateOptions): MessageType<Message> | number;
|
||||
|
||||
export declare function translate<Messages, Message = string>(context: CoreTranslationContext<Messages, Message>, message: MessageFunction<Message> | string, plural: number, options: TranslateOptions): MessageType<Message> | number;
|
||||
|
||||
export declare function translate<Messages, Message = string>(context: CoreTranslationContext<Messages, Message>, key: Path | number, defaultMsg: string): MessageType<Message> | number;
|
||||
|
||||
export declare function translate<Messages, Message = string>(context: CoreTranslationContext<Messages, Message>, key: Path | number, defaultMsg: string, options: TranslateOptions): MessageType<Message> | number;
|
||||
|
||||
export declare function translate<Messages, Message = string>(context: CoreTranslationContext<Messages, Message>, key: Path | number, list: unknown[]): MessageType<Message> | number;
|
||||
|
||||
export declare function translate<Messages, Message = string>(context: CoreTranslationContext<Messages, Message>, key: Path | number, list: unknown[], plural: number): MessageType<Message> | number;
|
||||
|
||||
export declare function translate<Messages, Message = string>(context: CoreTranslationContext<Messages, Message>, key: Path | number, list: unknown[], defaultMsg: string): MessageType<Message> | number;
|
||||
|
||||
export declare function translate<Messages, Message = string>(context: CoreTranslationContext<Messages, Message>, key: Path | number, list: unknown[], options: TranslateOptions): MessageType<Message> | number;
|
||||
|
||||
export declare function translate<Messages, Message = string>(context: CoreTranslationContext<Messages, Message>, message: MessageFunction<Message> | string, list: unknown[], options: TranslateOptions): MessageType<Message> | number;
|
||||
|
||||
export declare function translate<Messages, Message = string>(context: CoreTranslationContext<Messages, Message>, key: Path | number, named: NamedValue): MessageType<Message> | number;
|
||||
|
||||
export declare function translate<Messages, Message = string>(context: CoreTranslationContext<Messages, Message>, key: Path | number, named: NamedValue, plural: number): MessageType<Message> | number;
|
||||
|
||||
export declare function translate<Messages, Message = string>(context: CoreTranslationContext<Messages, Message>, key: Path | number, named: NamedValue, defaultMsg: string): MessageType<Message> | number;
|
||||
|
||||
export declare function translate<Messages, Message = string>(context: CoreTranslationContext<Messages, Message>, key: Path | number, named: NamedValue, options: TranslateOptions): MessageType<Message> | number;
|
||||
|
||||
export declare function translate<Messages, Message = string>(context: CoreTranslationContext<Messages, Message>, message: MessageFunction<Message> | string, named: NamedValue, options: TranslateOptions): MessageType<Message> | number;
|
||||
|
||||
export declare function translate<Messages, Message = string>(context: CoreTranslationContext<Messages, Message>, ...args: unknown[]): MessageType<Message> | number;
|
||||
|
||||
export declare const translateDevTools: (payloads: IntlifyDevToolsHookPayloads[IntlifyDevToolsHooks]) => void | null;
|
||||
|
||||
/**
|
||||
* # translate
|
||||
*
|
||||
* ## usages:
|
||||
* // for example, locale messages key
|
||||
* { 'foo.bar': 'hi {0} !' or 'hi {name} !' }
|
||||
*
|
||||
* // no argument, context & path only
|
||||
* translate(context, 'foo.bar')
|
||||
*
|
||||
* // list argument
|
||||
* translate(context, 'foo.bar', ['kazupon'])
|
||||
*
|
||||
* // named argument
|
||||
* translate(context, 'foo.bar', { name: 'kazupon' })
|
||||
*
|
||||
* // plural choice number
|
||||
* translate(context, 'foo.bar', 2)
|
||||
*
|
||||
* // plural choice number with name argument
|
||||
* translate(context, 'foo.bar', { name: 'kazupon' }, 2)
|
||||
*
|
||||
* // default message argument
|
||||
* translate(context, 'foo.bar', 'this is default message')
|
||||
*
|
||||
* // default message with named argument
|
||||
* translate(context, 'foo.bar', { name: 'kazupon' }, 'Hello {name} !')
|
||||
*
|
||||
* // use key as default message
|
||||
* translate(context, 'hi {0} !', ['kazupon'], { default: true })
|
||||
*
|
||||
* // locale option, override context.locale
|
||||
* translate(context, 'foo.bar', { name: 'kazupon' }, { locale: 'ja' })
|
||||
*
|
||||
* // suppress localize miss warning option, override context.missingWarn
|
||||
* translate(context, 'foo.bar', { name: 'kazupon' }, { missingWarn: false })
|
||||
*
|
||||
* // suppress localize fallback warning option, override context.fallbackWarn
|
||||
* translate(context, 'foo.bar', { name: 'kazupon' }, { fallbackWarn: false })
|
||||
*
|
||||
* // escape parameter option, override context.escapeParameter
|
||||
* translate(context, 'foo.bar', { name: 'kazupon' }, { escapeParameter: true })
|
||||
*/
|
||||
/**
|
||||
* Translate Options
|
||||
*
|
||||
* @remarks
|
||||
* Options for Translation API
|
||||
*
|
||||
* @VueI18nGeneral
|
||||
*/
|
||||
export declare interface TranslateOptions {
|
||||
/**
|
||||
* @remarks
|
||||
* List interpolation
|
||||
*/
|
||||
list?: unknown[];
|
||||
/**
|
||||
* @remarks
|
||||
* Named interpolation
|
||||
*/
|
||||
named?: NamedValue;
|
||||
/**
|
||||
* @remarks
|
||||
* Plulralzation choice number
|
||||
*/
|
||||
plural?: number;
|
||||
/**
|
||||
* @remarks
|
||||
* Default message when is occurred translation missing
|
||||
*/
|
||||
default?: string | boolean;
|
||||
/**
|
||||
* @remarks
|
||||
* The locale of localization
|
||||
*/
|
||||
locale?: Locale;
|
||||
/**
|
||||
* @remarks
|
||||
* Whether suppress warnings outputted when localization fails
|
||||
*/
|
||||
missingWarn?: boolean;
|
||||
/**
|
||||
* @remarks
|
||||
* Whether do template interpolation on translation keys when your language lacks a translation for a key
|
||||
*/
|
||||
fallbackWarn?: boolean;
|
||||
/**
|
||||
* @remarks
|
||||
* Whether do escape parameter for list or named interpolation values
|
||||
*/
|
||||
escapeParameter?: boolean;
|
||||
/**
|
||||
* @remarks
|
||||
* Whether the message has been resolved
|
||||
*/
|
||||
resolvedMessage?: boolean;
|
||||
}
|
||||
|
||||
/* Excluded from this release type: updateFallbackLocale */
|
||||
|
||||
/* Excluded from this release type: VERSION */
|
||||
|
||||
export * from "@intlify/message-resolver";
|
||||
export * from "@intlify/runtime";
|
||||
|
||||
export { }
|
||||
+2766
File diff suppressed because it is too large
Load Diff
+6
File diff suppressed because one or more lines are too long
+965
@@ -0,0 +1,965 @@
|
||||
/*!
|
||||
* @intlify/core-base v9.1.9
|
||||
* (c) 2021 kazuya kawaguchi
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
import { format, isString, isArray, isPlainObject, assign, isFunction, isBoolean, isRegExp, warn, isObject, escapeHtml, inBrowser, mark, measure, generateCodeFrame, generateFormatCacheKey, isNumber, isEmptyObject, isDate, getGlobalThis } from '@intlify/shared';
|
||||
import { resolveValue } from '@intlify/message-resolver';
|
||||
export * from '@intlify/message-resolver';
|
||||
import { createMessageContext } from '@intlify/runtime';
|
||||
export * from '@intlify/runtime';
|
||||
import { defaultOnError, baseCompile, createCompileError } from '@intlify/message-compiler';
|
||||
export { createCompileError } from '@intlify/message-compiler';
|
||||
import { IntlifyDevToolsHooks } from '@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(IntlifyDevToolsHooks.I18nInit, {
|
||||
timestamp: Date.now(),
|
||||
i18n,
|
||||
version,
|
||||
meta
|
||||
});
|
||||
}
|
||||
const translateDevTools = /* #__PURE__*/ createDevToolsHook(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 format(warnMessages[code], ...args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Intlify core-base version
|
||||
* @internal
|
||||
*/
|
||||
const VERSION = '9.1.9';
|
||||
const NOT_REOSLVED = -1;
|
||||
const MISSING_RESOLVE_VALUE = '';
|
||||
function getDefaultLinkedModifiers() {
|
||||
return {
|
||||
upper: (val) => (isString(val) ? val.toUpperCase() : val),
|
||||
lower: (val) => (isString(val) ? val.toLowerCase() : val),
|
||||
// prettier-ignore
|
||||
capitalize: (val) => (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 = isString(options.version) ? options.version : VERSION;
|
||||
const locale = isString(options.locale) ? options.locale : 'en-US';
|
||||
const fallbackLocale = isArray(options.fallbackLocale) ||
|
||||
isPlainObject(options.fallbackLocale) ||
|
||||
isString(options.fallbackLocale) ||
|
||||
options.fallbackLocale === false
|
||||
? options.fallbackLocale
|
||||
: locale;
|
||||
const messages = isPlainObject(options.messages)
|
||||
? options.messages
|
||||
: { [locale]: {} };
|
||||
const datetimeFormats = isPlainObject(options.datetimeFormats)
|
||||
? options.datetimeFormats
|
||||
: { [locale]: {} };
|
||||
const numberFormats = isPlainObject(options.numberFormats)
|
||||
? options.numberFormats
|
||||
: { [locale]: {} };
|
||||
const modifiers = assign({}, options.modifiers || {}, getDefaultLinkedModifiers());
|
||||
const pluralRules = options.pluralRules || {};
|
||||
const missing = isFunction(options.missing) ? options.missing : null;
|
||||
const missingWarn = isBoolean(options.missingWarn) || isRegExp(options.missingWarn)
|
||||
? options.missingWarn
|
||||
: true;
|
||||
const fallbackWarn = isBoolean(options.fallbackWarn) || isRegExp(options.fallbackWarn)
|
||||
? options.fallbackWarn
|
||||
: true;
|
||||
const fallbackFormat = !!options.fallbackFormat;
|
||||
const unresolving = !!options.unresolving;
|
||||
const postTranslation = isFunction(options.postTranslation)
|
||||
? options.postTranslation
|
||||
: null;
|
||||
const processor = isPlainObject(options.processor) ? options.processor : null;
|
||||
const warnHtmlMessage = isBoolean(options.warnHtmlMessage)
|
||||
? options.warnHtmlMessage
|
||||
: true;
|
||||
const escapeParameter = !!options.escapeParameter;
|
||||
const messageCompiler = isFunction(options.messageCompiler)
|
||||
? options.messageCompiler
|
||||
: _compiler;
|
||||
const onWarn = isFunction(options.onWarn) ? options.onWarn : warn;
|
||||
// setup internal options
|
||||
const internalOptions = options;
|
||||
const __datetimeFormatters = isObject(internalOptions.__datetimeFormatters)
|
||||
? internalOptions.__datetimeFormatters
|
||||
: new Map();
|
||||
const __numberFormatters = isObject(internalOptions.__numberFormatters)
|
||||
? internalOptions.__numberFormatters
|
||||
: new Map();
|
||||
const __meta = 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
|
||||
if ((process.env.NODE_ENV !== 'production')) {
|
||||
context.__v_emitter =
|
||||
internalOptions.__v_emitter != null
|
||||
? internalOptions.__v_emitter
|
||||
: undefined;
|
||||
}
|
||||
// NOTE: experimental !!
|
||||
if ((process.env.NODE_ENV !== 'production') || __INTLIFY_PROD_DEVTOOLS__) {
|
||||
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
|
||||
if ((process.env.NODE_ENV !== 'production')) {
|
||||
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 isString(ret) ? ret : key;
|
||||
}
|
||||
else {
|
||||
if ((process.env.NODE_ENV !== 'production') && 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 (isArray(block)) {
|
||||
block = appendBlockToChain(chain, block, fallback);
|
||||
}
|
||||
// prettier-ignore
|
||||
// last block defined by default
|
||||
const defaults = isArray(fallback)
|
||||
? fallback
|
||||
: isPlainObject(fallback)
|
||||
? fallback['default']
|
||||
? fallback['default']
|
||||
: null
|
||||
: fallback;
|
||||
// convert defaults to array
|
||||
block = isString(defaults) ? [defaults] : defaults;
|
||||
if (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 && isBoolean(follow); i++) {
|
||||
const locale = block[i];
|
||||
if (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 ((isArray(blocks) || 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 = isBoolean(options.warnHtmlMessage)
|
||||
? options.warnHtmlMessage
|
||||
: true;
|
||||
if (warnHtmlMessage && RE_HTML_TAG.test(source)) {
|
||||
warn(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
|
||||
(process.env.NODE_ENV !== 'production') && 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 || defaultOnError;
|
||||
options.onError = (err) => {
|
||||
occurred = true;
|
||||
onError(err);
|
||||
};
|
||||
// compile
|
||||
const { code } = 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 createCompileError(code, null, (process.env.NODE_ENV !== 'production') ? { messages: errorMessages } : undefined);
|
||||
}
|
||||
/** @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) => isFunction(val);
|
||||
// implementation of `translate` function
|
||||
function translate(context, ...args) {
|
||||
const { fallbackFormat, postTranslation, unresolving, fallbackLocale, messages } = context;
|
||||
const [key, options] = parseTranslateArgs(...args);
|
||||
const missingWarn = isBoolean(options.missingWarn)
|
||||
? options.missingWarn
|
||||
: context.missingWarn;
|
||||
const fallbackWarn = isBoolean(options.fallbackWarn)
|
||||
? options.fallbackWarn
|
||||
: context.fallbackWarn;
|
||||
const escapeParameter = isBoolean(options.escapeParameter)
|
||||
? options.escapeParameter
|
||||
: context.escapeParameter;
|
||||
const resolvedMessage = !!options.resolvedMessage;
|
||||
// prettier-ignore
|
||||
const defaultMsgOrKey = isString(options.default) || isBoolean(options.default) // default by function option
|
||||
? !isBoolean(options.default)
|
||||
? options.default
|
||||
: key
|
||||
: fallbackFormat // default by `fallbackFormat` option
|
||||
? key
|
||||
: '';
|
||||
const enableDefaultMsg = fallbackFormat || defaultMsgOrKey !== '';
|
||||
const locale = 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 &&
|
||||
!(isString(format) || isMessageFunction(format))) {
|
||||
if (enableDefaultMsg) {
|
||||
format = defaultMsgOrKey;
|
||||
cacheBaseKey = format;
|
||||
}
|
||||
}
|
||||
// checking message format and target locale
|
||||
if (!resolvedMessage &&
|
||||
(!(isString(format) || isMessageFunction(format)) ||
|
||||
!isString(targetLocale))) {
|
||||
return unresolving ? NOT_REOSLVED : key;
|
||||
}
|
||||
if ((process.env.NODE_ENV !== 'production') && isString(format) && context.messageCompiler == null) {
|
||||
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 = 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 !!
|
||||
if ((process.env.NODE_ENV !== 'production') || __INTLIFY_PROD_DEVTOOLS__) {
|
||||
// prettier-ignore
|
||||
const payloads = {
|
||||
timestamp: Date.now(),
|
||||
key: isString(key)
|
||||
? key
|
||||
: isMessageFunction(format)
|
||||
? format.key
|
||||
: '',
|
||||
locale: targetLocale || (isMessageFunction(format)
|
||||
? format.locale
|
||||
: ''),
|
||||
format: isString(format)
|
||||
? format
|
||||
: isMessageFunction(format)
|
||||
? format.source
|
||||
: '',
|
||||
message: ret
|
||||
};
|
||||
payloads.meta = assign({}, context.__meta, getAdditionalMeta() || {});
|
||||
translateDevTools(payloads);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
function escapeParams(options) {
|
||||
if (isArray(options.list)) {
|
||||
options.list = options.list.map(item => isString(item) ? escapeHtml(item) : item);
|
||||
}
|
||||
else if (isObject(options.named)) {
|
||||
Object.keys(options.named).forEach(key => {
|
||||
if (isString(options.named[key])) {
|
||||
options.named[key] = 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 ((process.env.NODE_ENV !== 'production') &&
|
||||
locale !== targetLocale &&
|
||||
isTranslateFallbackWarn(fallbackWarn, key)) {
|
||||
onWarn(getWarnMessage(1 /* FALLBACK_TO_TRANSLATE */, {
|
||||
key,
|
||||
target: targetLocale
|
||||
}));
|
||||
}
|
||||
// for vue-devtools timeline event
|
||||
if ((process.env.NODE_ENV !== 'production') && 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 ((process.env.NODE_ENV !== 'production') && inBrowser) {
|
||||
start = window.performance.now();
|
||||
startTag = 'intlify-message-resolve-start';
|
||||
endTag = 'intlify-message-resolve-end';
|
||||
mark && mark(startTag);
|
||||
}
|
||||
if ((format = 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 ((process.env.NODE_ENV !== 'production') && 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 && mark && measure) {
|
||||
mark(endTag);
|
||||
measure('intlify message resolve', startTag, endTag);
|
||||
}
|
||||
}
|
||||
if (isString(format) || 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 ((process.env.NODE_ENV !== 'production') && inBrowser) {
|
||||
start = window.performance.now();
|
||||
startTag = 'intlify-message-compilation-start';
|
||||
endTag = 'intlify-message-compilation-end';
|
||||
mark && mark(startTag);
|
||||
}
|
||||
const msg = messageCompiler(format, getCompileOptions(context, targetLocale, cacheBaseKey, format, warnHtmlMessage, errorDetector));
|
||||
// for vue-devtools timeline event
|
||||
if ((process.env.NODE_ENV !== 'production') && 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 && mark && measure) {
|
||||
mark(endTag);
|
||||
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 ((process.env.NODE_ENV !== 'production') && inBrowser) {
|
||||
start = window.performance.now();
|
||||
startTag = 'intlify-message-evaluation-start';
|
||||
endTag = 'intlify-message-evaluation-end';
|
||||
mark && mark(startTag);
|
||||
}
|
||||
const messaged = msg(msgCtx);
|
||||
// for vue-devtools timeline event
|
||||
if ((process.env.NODE_ENV !== 'production') && 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 && mark && measure) {
|
||||
mark(endTag);
|
||||
measure('intlify message evaluation', startTag, endTag);
|
||||
}
|
||||
}
|
||||
return messaged;
|
||||
}
|
||||
/** @internal */
|
||||
function parseTranslateArgs(...args) {
|
||||
const [arg1, arg2, arg3] = args;
|
||||
const options = {};
|
||||
if (!isString(arg1) && !isNumber(arg1) && !isMessageFunction(arg1)) {
|
||||
throw createCoreError(14 /* INVALID_ARGUMENT */);
|
||||
}
|
||||
// prettier-ignore
|
||||
const key = isNumber(arg1)
|
||||
? String(arg1)
|
||||
: isMessageFunction(arg1)
|
||||
? arg1
|
||||
: arg1;
|
||||
if (isNumber(arg2)) {
|
||||
options.plural = arg2;
|
||||
}
|
||||
else if (isString(arg2)) {
|
||||
options.default = arg2;
|
||||
}
|
||||
else if (isPlainObject(arg2) && !isEmptyObject(arg2)) {
|
||||
options.named = arg2;
|
||||
}
|
||||
else if (isArray(arg2)) {
|
||||
options.list = arg2;
|
||||
}
|
||||
if (isNumber(arg3)) {
|
||||
options.plural = arg3;
|
||||
}
|
||||
else if (isString(arg3)) {
|
||||
options.default = arg3;
|
||||
}
|
||||
else if (isPlainObject(arg3)) {
|
||||
assign(options, arg3);
|
||||
}
|
||||
return [key, options];
|
||||
}
|
||||
function getCompileOptions(context, locale, key, source, warnHtmlMessage, errorDetector) {
|
||||
return {
|
||||
warnHtmlMessage,
|
||||
onError: (err) => {
|
||||
errorDetector && errorDetector(err);
|
||||
if ((process.env.NODE_ENV !== 'production')) {
|
||||
const message = `Message compilation error: ${err.message}`;
|
||||
const codeFrame = err.location &&
|
||||
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);
|
||||
}
|
||||
else {
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
onCacheKey: (source) => generateFormatCacheKey(locale, key, source)
|
||||
};
|
||||
}
|
||||
function getMessageContextOptions(context, locale, message, options) {
|
||||
const { modifiers, pluralRules } = context;
|
||||
const resolveMessage = (key) => {
|
||||
const val = resolveValue(message, key);
|
||||
if (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 (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 ((process.env.NODE_ENV !== 'production') && !Availabilities.dateTimeFormat) {
|
||||
onWarn(getWarnMessage(4 /* CANNOT_FORMAT_DATE */));
|
||||
return MISSING_RESOLVE_VALUE;
|
||||
}
|
||||
const [key, value, options, overrides] = parseDateTimeArgs(...args);
|
||||
const missingWarn = isBoolean(options.missingWarn)
|
||||
? options.missingWarn
|
||||
: context.missingWarn;
|
||||
const fallbackWarn = isBoolean(options.fallbackWarn)
|
||||
? options.fallbackWarn
|
||||
: context.fallbackWarn;
|
||||
const part = !!options.part;
|
||||
const locale = isString(options.locale) ? options.locale : context.locale;
|
||||
const locales = getLocaleChain(context, fallbackLocale, locale);
|
||||
if (!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 ((process.env.NODE_ENV !== 'production') &&
|
||||
locale !== targetLocale &&
|
||||
isTranslateFallbackWarn(fallbackWarn, key)) {
|
||||
onWarn(getWarnMessage(5 /* FALLBACK_TO_DATE_FORMAT */, {
|
||||
key,
|
||||
target: targetLocale
|
||||
}));
|
||||
}
|
||||
// for vue-devtools timeline event
|
||||
if ((process.env.NODE_ENV !== 'production') && 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 (isPlainObject(format))
|
||||
break;
|
||||
handleMissing(context, key, targetLocale, missingWarn, type);
|
||||
from = to;
|
||||
}
|
||||
// checking format and target locale
|
||||
if (!isPlainObject(format) || !isString(targetLocale)) {
|
||||
return unresolving ? NOT_REOSLVED : key;
|
||||
}
|
||||
let id = `${targetLocale}__${key}`;
|
||||
if (!isEmptyObject(overrides)) {
|
||||
id = `${id}__${JSON.stringify(overrides)}`;
|
||||
}
|
||||
let formatter = __datetimeFormatters.get(id);
|
||||
if (!formatter) {
|
||||
formatter = new Intl.DateTimeFormat(targetLocale, 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 (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 (isDate(arg1)) {
|
||||
if (isNaN(arg1.getTime())) {
|
||||
throw createCoreError(15 /* INVALID_DATE_ARGUMENT */);
|
||||
}
|
||||
value = arg1;
|
||||
}
|
||||
else if (isNumber(arg1)) {
|
||||
value = arg1;
|
||||
}
|
||||
else {
|
||||
throw createCoreError(14 /* INVALID_ARGUMENT */);
|
||||
}
|
||||
if (isString(arg2)) {
|
||||
options.key = arg2;
|
||||
}
|
||||
else if (isPlainObject(arg2)) {
|
||||
options = arg2;
|
||||
}
|
||||
if (isString(arg3)) {
|
||||
options.locale = arg3;
|
||||
}
|
||||
else if (isPlainObject(arg3)) {
|
||||
overrides = arg3;
|
||||
}
|
||||
if (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 ((process.env.NODE_ENV !== 'production') && !Availabilities.numberFormat) {
|
||||
onWarn(getWarnMessage(2 /* CANNOT_FORMAT_NUMBER */));
|
||||
return MISSING_RESOLVE_VALUE;
|
||||
}
|
||||
const [key, value, options, overrides] = parseNumberArgs(...args);
|
||||
const missingWarn = isBoolean(options.missingWarn)
|
||||
? options.missingWarn
|
||||
: context.missingWarn;
|
||||
const fallbackWarn = isBoolean(options.fallbackWarn)
|
||||
? options.fallbackWarn
|
||||
: context.fallbackWarn;
|
||||
const part = !!options.part;
|
||||
const locale = isString(options.locale) ? options.locale : context.locale;
|
||||
const locales = getLocaleChain(context, fallbackLocale, locale);
|
||||
if (!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 ((process.env.NODE_ENV !== 'production') &&
|
||||
locale !== targetLocale &&
|
||||
isTranslateFallbackWarn(fallbackWarn, key)) {
|
||||
onWarn(getWarnMessage(3 /* FALLBACK_TO_NUMBER_FORMAT */, {
|
||||
key,
|
||||
target: targetLocale
|
||||
}));
|
||||
}
|
||||
// for vue-devtools timeline event
|
||||
if ((process.env.NODE_ENV !== 'production') && 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 (isPlainObject(format))
|
||||
break;
|
||||
handleMissing(context, key, targetLocale, missingWarn, type);
|
||||
from = to;
|
||||
}
|
||||
// checking format and target locale
|
||||
if (!isPlainObject(format) || !isString(targetLocale)) {
|
||||
return unresolving ? NOT_REOSLVED : key;
|
||||
}
|
||||
let id = `${targetLocale}__${key}`;
|
||||
if (!isEmptyObject(overrides)) {
|
||||
id = `${id}__${JSON.stringify(overrides)}`;
|
||||
}
|
||||
let formatter = __numberFormatters.get(id);
|
||||
if (!formatter) {
|
||||
formatter = new Intl.NumberFormat(targetLocale, 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 (!isNumber(arg1)) {
|
||||
throw createCoreError(14 /* INVALID_ARGUMENT */);
|
||||
}
|
||||
const value = arg1;
|
||||
if (isString(arg2)) {
|
||||
options.key = arg2;
|
||||
}
|
||||
else if (isPlainObject(arg2)) {
|
||||
options = arg2;
|
||||
}
|
||||
if (isString(arg3)) {
|
||||
options.locale = arg3;
|
||||
}
|
||||
else if (isPlainObject(arg3)) {
|
||||
overrides = arg3;
|
||||
}
|
||||
if (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);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if (typeof __INTLIFY_PROD_DEVTOOLS__ !== 'boolean') {
|
||||
getGlobalThis().__INTLIFY_PROD_DEVTOOLS__ = false;
|
||||
}
|
||||
}
|
||||
|
||||
export { MISSING_RESOLVE_VALUE, NOT_REOSLVED, VERSION, clearCompileCache, clearDateTimeFormat, clearNumberFormat, compileToFunction, createCoreContext, createCoreError, datetime, getAdditionalMeta, getDevToolsHook, getLocaleChain, getWarnMessage, handleMissing, initI18nDevTools, isMessageFunction, isTranslateFallbackWarn, isTranslateMissingWarn, number, parseDateTimeArgs, parseNumberArgs, parseTranslateArgs, registerMessageCompiler, setAdditionalMeta, setDevToolsHook, translate, translateDevTools, updateFallbackLocale };
|
||||
+2809
File diff suppressed because it is too large
Load Diff
+6
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user