core-base.mjs 64 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882
  1. /*!
  2. * core-base v11.1.3
  3. * (c) 2025 kazuya kawaguchi
  4. * Released under the MIT License.
  5. */
  6. import { getGlobalThis, isObject, hasOwn, isNumber, create, isString, isBoolean, warn, format as format$1, isFunction, isPromise, isArray, isPlainObject, assign, isRegExp, warnOnce, isEmptyObject, isDate, join, toDisplayString, escapeHtml, inBrowser, mark, measure, generateCodeFrame, generateFormatCacheKey } from '@intlify/shared';
  7. import { detectHtmlTag, defaultOnError, baseCompile as baseCompile$1, COMPILE_ERROR_CODES_EXTEND_POINT, createCompileError } from '@intlify/message-compiler';
  8. export { CompileErrorCodes, createCompileError } from '@intlify/message-compiler';
  9. /**
  10. * This is only called in esm-bundler builds.
  11. * istanbul-ignore-next
  12. */
  13. function initFeatureFlags() {
  14. if (typeof __INTLIFY_PROD_DEVTOOLS__ !== 'boolean') {
  15. getGlobalThis().__INTLIFY_PROD_DEVTOOLS__ = false;
  16. }
  17. if (typeof __INTLIFY_DROP_MESSAGE_COMPILER__ !== 'boolean') {
  18. getGlobalThis().__INTLIFY_DROP_MESSAGE_COMPILER__ = false;
  19. }
  20. }
  21. function isMessageAST(val) {
  22. return (isObject(val) &&
  23. resolveType(val) === 0 &&
  24. (hasOwn(val, 'b') || hasOwn(val, 'body')));
  25. }
  26. const PROPS_BODY = ['b', 'body'];
  27. function resolveBody(node) {
  28. return resolveProps(node, PROPS_BODY);
  29. }
  30. const PROPS_CASES = ['c', 'cases'];
  31. function resolveCases(node) {
  32. return resolveProps(node, PROPS_CASES, []);
  33. }
  34. const PROPS_STATIC = ['s', 'static'];
  35. function resolveStatic(node) {
  36. return resolveProps(node, PROPS_STATIC);
  37. }
  38. const PROPS_ITEMS = ['i', 'items'];
  39. function resolveItems(node) {
  40. return resolveProps(node, PROPS_ITEMS, []);
  41. }
  42. const PROPS_TYPE = ['t', 'type'];
  43. function resolveType(node) {
  44. return resolveProps(node, PROPS_TYPE);
  45. }
  46. const PROPS_VALUE = ['v', 'value'];
  47. function resolveValue$1(node, type) {
  48. const resolved = resolveProps(node, PROPS_VALUE);
  49. if (resolved != null) {
  50. return resolved;
  51. }
  52. else {
  53. throw createUnhandleNodeError(type);
  54. }
  55. }
  56. const PROPS_MODIFIER = ['m', 'modifier'];
  57. function resolveLinkedModifier(node) {
  58. return resolveProps(node, PROPS_MODIFIER);
  59. }
  60. const PROPS_KEY = ['k', 'key'];
  61. function resolveLinkedKey(node) {
  62. const resolved = resolveProps(node, PROPS_KEY);
  63. if (resolved) {
  64. return resolved;
  65. }
  66. else {
  67. throw createUnhandleNodeError(6 /* NodeTypes.Linked */);
  68. }
  69. }
  70. function resolveProps(node, props, defaultValue) {
  71. for (let i = 0; i < props.length; i++) {
  72. const prop = props[i];
  73. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  74. if (hasOwn(node, prop) && node[prop] != null) {
  75. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  76. return node[prop];
  77. }
  78. }
  79. return defaultValue;
  80. }
  81. const AST_NODE_PROPS_KEYS = [
  82. ...PROPS_BODY,
  83. ...PROPS_CASES,
  84. ...PROPS_STATIC,
  85. ...PROPS_ITEMS,
  86. ...PROPS_KEY,
  87. ...PROPS_MODIFIER,
  88. ...PROPS_VALUE,
  89. ...PROPS_TYPE
  90. ];
  91. function createUnhandleNodeError(type) {
  92. return new Error(`unhandled node type: ${type}`);
  93. }
  94. function format(ast) {
  95. const msg = (ctx) => formatParts(ctx, ast);
  96. return msg;
  97. }
  98. function formatParts(ctx, ast) {
  99. const body = resolveBody(ast);
  100. if (body == null) {
  101. throw createUnhandleNodeError(0 /* NodeTypes.Resource */);
  102. }
  103. const type = resolveType(body);
  104. if (type === 1 /* NodeTypes.Plural */) {
  105. const plural = body;
  106. const cases = resolveCases(plural);
  107. return ctx.plural(cases.reduce((messages, c) => [
  108. ...messages,
  109. formatMessageParts(ctx, c)
  110. ], []));
  111. }
  112. else {
  113. return formatMessageParts(ctx, body);
  114. }
  115. }
  116. function formatMessageParts(ctx, node) {
  117. const static_ = resolveStatic(node);
  118. if (static_ != null) {
  119. return ctx.type === 'text'
  120. ? static_
  121. : ctx.normalize([static_]);
  122. }
  123. else {
  124. const messages = resolveItems(node).reduce((acm, c) => [...acm, formatMessagePart(ctx, c)], []);
  125. return ctx.normalize(messages);
  126. }
  127. }
  128. function formatMessagePart(ctx, node) {
  129. const type = resolveType(node);
  130. switch (type) {
  131. case 3 /* NodeTypes.Text */: {
  132. return resolveValue$1(node, type);
  133. }
  134. case 9 /* NodeTypes.Literal */: {
  135. return resolveValue$1(node, type);
  136. }
  137. case 4 /* NodeTypes.Named */: {
  138. const named = node;
  139. if (hasOwn(named, 'k') && named.k) {
  140. return ctx.interpolate(ctx.named(named.k));
  141. }
  142. if (hasOwn(named, 'key') && named.key) {
  143. return ctx.interpolate(ctx.named(named.key));
  144. }
  145. throw createUnhandleNodeError(type);
  146. }
  147. case 5 /* NodeTypes.List */: {
  148. const list = node;
  149. if (hasOwn(list, 'i') && isNumber(list.i)) {
  150. return ctx.interpolate(ctx.list(list.i));
  151. }
  152. if (hasOwn(list, 'index') && isNumber(list.index)) {
  153. return ctx.interpolate(ctx.list(list.index));
  154. }
  155. throw createUnhandleNodeError(type);
  156. }
  157. case 6 /* NodeTypes.Linked */: {
  158. const linked = node;
  159. const modifier = resolveLinkedModifier(linked);
  160. const key = resolveLinkedKey(linked);
  161. return ctx.linked(formatMessagePart(ctx, key), modifier ? formatMessagePart(ctx, modifier) : undefined, ctx.type);
  162. }
  163. case 7 /* NodeTypes.LinkedKey */: {
  164. return resolveValue$1(node, type);
  165. }
  166. case 8 /* NodeTypes.LinkedModifier */: {
  167. return resolveValue$1(node, type);
  168. }
  169. default:
  170. throw new Error(`unhandled node on format message part: ${type}`);
  171. }
  172. }
  173. const WARN_MESSAGE = `Detected HTML in '{source}' message. Recommend not using HTML messages to avoid XSS.`;
  174. function checkHtmlMessage(source, warnHtmlMessage) {
  175. if (warnHtmlMessage && detectHtmlTag(source)) {
  176. warn(format$1(WARN_MESSAGE, { source }));
  177. }
  178. }
  179. const defaultOnCacheKey = (message) => message;
  180. let compileCache = create();
  181. function clearCompileCache() {
  182. compileCache = create();
  183. }
  184. function baseCompile(message, options = {}) {
  185. // error detecting on compile
  186. let detectError = false;
  187. const onError = options.onError || defaultOnError;
  188. options.onError = (err) => {
  189. detectError = true;
  190. onError(err);
  191. };
  192. // compile with mesasge-compiler
  193. return { ...baseCompile$1(message, options), detectError };
  194. }
  195. /* #__NO_SIDE_EFFECTS__ */
  196. function compile(message, context) {
  197. if ((!__INTLIFY_DROP_MESSAGE_COMPILER__) &&
  198. isString(message)) {
  199. // check HTML message
  200. const warnHtmlMessage = isBoolean(context.warnHtmlMessage)
  201. ? context.warnHtmlMessage
  202. : true;
  203. (process.env.NODE_ENV !== 'production') && checkHtmlMessage(message, warnHtmlMessage);
  204. // check caches
  205. const onCacheKey = context.onCacheKey || defaultOnCacheKey;
  206. const cacheKey = onCacheKey(message);
  207. const cached = compileCache[cacheKey];
  208. if (cached) {
  209. return cached;
  210. }
  211. // compile with JIT mode
  212. const { ast, detectError } = baseCompile(message, {
  213. ...context,
  214. location: (process.env.NODE_ENV !== 'production'),
  215. jit: true
  216. });
  217. // compose message function from AST
  218. const msg = format(ast);
  219. // if occurred compile error, don't cache
  220. return !detectError
  221. ? (compileCache[cacheKey] = msg)
  222. : msg;
  223. }
  224. else {
  225. if ((process.env.NODE_ENV !== 'production') && !isMessageAST(message)) {
  226. warn(`the message that is resolve with key '${context.key}' is not supported for jit compilation`);
  227. return (() => message);
  228. }
  229. // AST case (passed from bundler)
  230. const cacheKey = message.cacheKey;
  231. if (cacheKey) {
  232. const cached = compileCache[cacheKey];
  233. if (cached) {
  234. return cached;
  235. }
  236. // compose message function from message (AST)
  237. return (compileCache[cacheKey] =
  238. format(message));
  239. }
  240. else {
  241. return format(message);
  242. }
  243. }
  244. }
  245. let devtools = null;
  246. function setDevToolsHook(hook) {
  247. devtools = hook;
  248. }
  249. function getDevToolsHook() {
  250. return devtools;
  251. }
  252. function initI18nDevTools(i18n, version, meta) {
  253. // TODO: queue if devtools is undefined
  254. devtools &&
  255. devtools.emit('i18n:init', {
  256. timestamp: Date.now(),
  257. i18n,
  258. version,
  259. meta
  260. });
  261. }
  262. const translateDevTools =
  263. /* #__PURE__*/ createDevToolsHook('function:translate');
  264. function createDevToolsHook(hook) {
  265. return (payloads) => devtools && devtools.emit(hook, payloads);
  266. }
  267. const CoreErrorCodes = {
  268. INVALID_ARGUMENT: COMPILE_ERROR_CODES_EXTEND_POINT, // 17
  269. INVALID_DATE_ARGUMENT: 18,
  270. INVALID_ISO_DATE_ARGUMENT: 19,
  271. NOT_SUPPORT_NON_STRING_MESSAGE: 20,
  272. NOT_SUPPORT_LOCALE_PROMISE_VALUE: 21,
  273. NOT_SUPPORT_LOCALE_ASYNC_FUNCTION: 22,
  274. NOT_SUPPORT_LOCALE_TYPE: 23
  275. };
  276. const CORE_ERROR_CODES_EXTEND_POINT = 24;
  277. function createCoreError(code) {
  278. return createCompileError(code, null, (process.env.NODE_ENV !== 'production') ? { messages: errorMessages } : undefined);
  279. }
  280. /** @internal */
  281. const errorMessages = {
  282. [CoreErrorCodes.INVALID_ARGUMENT]: 'Invalid arguments',
  283. [CoreErrorCodes.INVALID_DATE_ARGUMENT]: 'The date provided is an invalid Date object.' +
  284. 'Make sure your Date represents a valid date.',
  285. [CoreErrorCodes.INVALID_ISO_DATE_ARGUMENT]: 'The argument provided is not a valid ISO date string',
  286. [CoreErrorCodes.NOT_SUPPORT_NON_STRING_MESSAGE]: 'Not support non-string message',
  287. [CoreErrorCodes.NOT_SUPPORT_LOCALE_PROMISE_VALUE]: 'cannot support promise value',
  288. [CoreErrorCodes.NOT_SUPPORT_LOCALE_ASYNC_FUNCTION]: 'cannot support async function',
  289. [CoreErrorCodes.NOT_SUPPORT_LOCALE_TYPE]: 'cannot support locale type'
  290. };
  291. /** @internal */
  292. function getLocale(context, options) {
  293. return options.locale != null
  294. ? resolveLocale(options.locale)
  295. : resolveLocale(context.locale);
  296. }
  297. let _resolveLocale;
  298. /** @internal */
  299. function resolveLocale(locale) {
  300. if (isString(locale)) {
  301. return locale;
  302. }
  303. else {
  304. if (isFunction(locale)) {
  305. if (locale.resolvedOnce && _resolveLocale != null) {
  306. return _resolveLocale;
  307. }
  308. else if (locale.constructor.name === 'Function') {
  309. const resolve = locale();
  310. if (isPromise(resolve)) {
  311. throw createCoreError(CoreErrorCodes.NOT_SUPPORT_LOCALE_PROMISE_VALUE);
  312. }
  313. return (_resolveLocale = resolve);
  314. }
  315. else {
  316. throw createCoreError(CoreErrorCodes.NOT_SUPPORT_LOCALE_ASYNC_FUNCTION);
  317. }
  318. }
  319. else {
  320. throw createCoreError(CoreErrorCodes.NOT_SUPPORT_LOCALE_TYPE);
  321. }
  322. }
  323. }
  324. /**
  325. * Fallback with simple implemenation
  326. *
  327. * @remarks
  328. * A fallback locale function implemented with a simple fallback algorithm.
  329. *
  330. * Basically, it returns the value as specified in the `fallbackLocale` props, and is processed with the fallback inside intlify.
  331. *
  332. * @param ctx - A {@link CoreContext | context}
  333. * @param fallback - A {@link FallbackLocale | fallback locale}
  334. * @param start - A starting {@link Locale | locale}
  335. *
  336. * @returns Fallback locales
  337. *
  338. * @VueI18nGeneral
  339. */
  340. function fallbackWithSimple(ctx, fallback, start) {
  341. // prettier-ignore
  342. return [...new Set([
  343. start,
  344. ...(isArray(fallback)
  345. ? fallback
  346. : isObject(fallback)
  347. ? Object.keys(fallback)
  348. : isString(fallback)
  349. ? [fallback]
  350. : [start])
  351. ])];
  352. }
  353. /**
  354. * Fallback with locale chain
  355. *
  356. * @remarks
  357. * A fallback locale function implemented with a fallback chain algorithm. It's used in VueI18n as default.
  358. *
  359. * @param ctx - A {@link CoreContext | context}
  360. * @param fallback - A {@link FallbackLocale | fallback locale}
  361. * @param start - A starting {@link Locale | locale}
  362. *
  363. * @returns Fallback locales
  364. *
  365. * @VueI18nSee [Fallbacking](../guide/essentials/fallback)
  366. *
  367. * @VueI18nGeneral
  368. */
  369. function fallbackWithLocaleChain(ctx, fallback, start) {
  370. const startLocale = isString(start) ? start : DEFAULT_LOCALE;
  371. const context = ctx;
  372. if (!context.__localeChainCache) {
  373. context.__localeChainCache = new Map();
  374. }
  375. let chain = context.__localeChainCache.get(startLocale);
  376. if (!chain) {
  377. chain = [];
  378. // first block defined by start
  379. let block = [start];
  380. // while any intervening block found
  381. while (isArray(block)) {
  382. block = appendBlockToChain(chain, block, fallback);
  383. }
  384. // prettier-ignore
  385. // last block defined by default
  386. const defaults = isArray(fallback) || !isPlainObject(fallback)
  387. ? fallback
  388. : fallback['default']
  389. ? fallback['default']
  390. : null;
  391. // convert defaults to array
  392. block = isString(defaults) ? [defaults] : defaults;
  393. if (isArray(block)) {
  394. appendBlockToChain(chain, block, false);
  395. }
  396. context.__localeChainCache.set(startLocale, chain);
  397. }
  398. return chain;
  399. }
  400. function appendBlockToChain(chain, block, blocks) {
  401. let follow = true;
  402. for (let i = 0; i < block.length && isBoolean(follow); i++) {
  403. const locale = block[i];
  404. if (isString(locale)) {
  405. follow = appendLocaleToChain(chain, block[i], blocks);
  406. }
  407. }
  408. return follow;
  409. }
  410. function appendLocaleToChain(chain, locale, blocks) {
  411. let follow;
  412. const tokens = locale.split('-');
  413. do {
  414. const target = tokens.join('-');
  415. follow = appendItemToChain(chain, target, blocks);
  416. tokens.splice(-1, 1);
  417. } while (tokens.length && follow === true);
  418. return follow;
  419. }
  420. function appendItemToChain(chain, target, blocks) {
  421. let follow = false;
  422. if (!chain.includes(target)) {
  423. follow = true;
  424. if (target) {
  425. follow = target[target.length - 1] !== '!';
  426. const locale = target.replace(/!/g, '');
  427. chain.push(locale);
  428. if ((isArray(blocks) || isPlainObject(blocks)) &&
  429. blocks[locale] // eslint-disable-line @typescript-eslint/no-explicit-any
  430. ) {
  431. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  432. follow = blocks[locale];
  433. }
  434. }
  435. }
  436. return follow;
  437. }
  438. const pathStateMachine = [];
  439. pathStateMachine[0 /* States.BEFORE_PATH */] = {
  440. ["w" /* PathCharTypes.WORKSPACE */]: [0 /* States.BEFORE_PATH */],
  441. ["i" /* PathCharTypes.IDENT */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
  442. ["[" /* PathCharTypes.LEFT_BRACKET */]: [4 /* States.IN_SUB_PATH */],
  443. ["o" /* PathCharTypes.END_OF_FAIL */]: [7 /* States.AFTER_PATH */]
  444. };
  445. pathStateMachine[1 /* States.IN_PATH */] = {
  446. ["w" /* PathCharTypes.WORKSPACE */]: [1 /* States.IN_PATH */],
  447. ["." /* PathCharTypes.DOT */]: [2 /* States.BEFORE_IDENT */],
  448. ["[" /* PathCharTypes.LEFT_BRACKET */]: [4 /* States.IN_SUB_PATH */],
  449. ["o" /* PathCharTypes.END_OF_FAIL */]: [7 /* States.AFTER_PATH */]
  450. };
  451. pathStateMachine[2 /* States.BEFORE_IDENT */] = {
  452. ["w" /* PathCharTypes.WORKSPACE */]: [2 /* States.BEFORE_IDENT */],
  453. ["i" /* PathCharTypes.IDENT */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
  454. ["0" /* PathCharTypes.ZERO */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */]
  455. };
  456. pathStateMachine[3 /* States.IN_IDENT */] = {
  457. ["i" /* PathCharTypes.IDENT */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
  458. ["0" /* PathCharTypes.ZERO */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
  459. ["w" /* PathCharTypes.WORKSPACE */]: [1 /* States.IN_PATH */, 1 /* Actions.PUSH */],
  460. ["." /* PathCharTypes.DOT */]: [2 /* States.BEFORE_IDENT */, 1 /* Actions.PUSH */],
  461. ["[" /* PathCharTypes.LEFT_BRACKET */]: [4 /* States.IN_SUB_PATH */, 1 /* Actions.PUSH */],
  462. ["o" /* PathCharTypes.END_OF_FAIL */]: [7 /* States.AFTER_PATH */, 1 /* Actions.PUSH */]
  463. };
  464. pathStateMachine[4 /* States.IN_SUB_PATH */] = {
  465. ["'" /* PathCharTypes.SINGLE_QUOTE */]: [5 /* States.IN_SINGLE_QUOTE */, 0 /* Actions.APPEND */],
  466. ["\"" /* PathCharTypes.DOUBLE_QUOTE */]: [6 /* States.IN_DOUBLE_QUOTE */, 0 /* Actions.APPEND */],
  467. ["[" /* PathCharTypes.LEFT_BRACKET */]: [
  468. 4 /* States.IN_SUB_PATH */,
  469. 2 /* Actions.INC_SUB_PATH_DEPTH */
  470. ],
  471. ["]" /* PathCharTypes.RIGHT_BRACKET */]: [1 /* States.IN_PATH */, 3 /* Actions.PUSH_SUB_PATH */],
  472. ["o" /* PathCharTypes.END_OF_FAIL */]: 8 /* States.ERROR */,
  473. ["l" /* PathCharTypes.ELSE */]: [4 /* States.IN_SUB_PATH */, 0 /* Actions.APPEND */]
  474. };
  475. pathStateMachine[5 /* States.IN_SINGLE_QUOTE */] = {
  476. ["'" /* PathCharTypes.SINGLE_QUOTE */]: [4 /* States.IN_SUB_PATH */, 0 /* Actions.APPEND */],
  477. ["o" /* PathCharTypes.END_OF_FAIL */]: 8 /* States.ERROR */,
  478. ["l" /* PathCharTypes.ELSE */]: [5 /* States.IN_SINGLE_QUOTE */, 0 /* Actions.APPEND */]
  479. };
  480. pathStateMachine[6 /* States.IN_DOUBLE_QUOTE */] = {
  481. ["\"" /* PathCharTypes.DOUBLE_QUOTE */]: [4 /* States.IN_SUB_PATH */, 0 /* Actions.APPEND */],
  482. ["o" /* PathCharTypes.END_OF_FAIL */]: 8 /* States.ERROR */,
  483. ["l" /* PathCharTypes.ELSE */]: [6 /* States.IN_DOUBLE_QUOTE */, 0 /* Actions.APPEND */]
  484. };
  485. /**
  486. * Check if an expression is a literal value.
  487. */
  488. const literalValueRE = /^\s?(?:true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/;
  489. function isLiteral(exp) {
  490. return literalValueRE.test(exp);
  491. }
  492. /**
  493. * Strip quotes from a string
  494. */
  495. function stripQuotes(str) {
  496. const a = str.charCodeAt(0);
  497. const b = str.charCodeAt(str.length - 1);
  498. return a === b && (a === 0x22 || a === 0x27) ? str.slice(1, -1) : str;
  499. }
  500. /**
  501. * Determine the type of a character in a keypath.
  502. */
  503. function getPathCharType(ch) {
  504. if (ch === undefined || ch === null) {
  505. return "o" /* PathCharTypes.END_OF_FAIL */;
  506. }
  507. const code = ch.charCodeAt(0);
  508. switch (code) {
  509. case 0x5b: // [
  510. case 0x5d: // ]
  511. case 0x2e: // .
  512. case 0x22: // "
  513. case 0x27: // '
  514. return ch;
  515. case 0x5f: // _
  516. case 0x24: // $
  517. case 0x2d: // -
  518. return "i" /* PathCharTypes.IDENT */;
  519. case 0x09: // Tab (HT)
  520. case 0x0a: // Newline (LF)
  521. case 0x0d: // Return (CR)
  522. case 0xa0: // No-break space (NBSP)
  523. case 0xfeff: // Byte Order Mark (BOM)
  524. case 0x2028: // Line Separator (LS)
  525. case 0x2029: // Paragraph Separator (PS)
  526. return "w" /* PathCharTypes.WORKSPACE */;
  527. }
  528. return "i" /* PathCharTypes.IDENT */;
  529. }
  530. /**
  531. * Format a subPath, return its plain form if it is
  532. * a literal string or number. Otherwise prepend the
  533. * dynamic indicator (*).
  534. */
  535. function formatSubPath(path) {
  536. const trimmed = path.trim();
  537. // invalid leading 0
  538. if (path.charAt(0) === '0' && isNaN(parseInt(path))) {
  539. return false;
  540. }
  541. return isLiteral(trimmed)
  542. ? stripQuotes(trimmed)
  543. : "*" /* PathCharTypes.ASTARISK */ + trimmed;
  544. }
  545. /**
  546. * Parse a string path into an array of segments
  547. */
  548. function parse(path) {
  549. const keys = [];
  550. let index = -1;
  551. let mode = 0 /* States.BEFORE_PATH */;
  552. let subPathDepth = 0;
  553. let c;
  554. let key; // eslint-disable-line
  555. let newChar;
  556. let type;
  557. let transition;
  558. let action;
  559. let typeMap;
  560. const actions = [];
  561. actions[0 /* Actions.APPEND */] = () => {
  562. if (key === undefined) {
  563. key = newChar;
  564. }
  565. else {
  566. key += newChar;
  567. }
  568. };
  569. actions[1 /* Actions.PUSH */] = () => {
  570. if (key !== undefined) {
  571. keys.push(key);
  572. key = undefined;
  573. }
  574. };
  575. actions[2 /* Actions.INC_SUB_PATH_DEPTH */] = () => {
  576. actions[0 /* Actions.APPEND */]();
  577. subPathDepth++;
  578. };
  579. actions[3 /* Actions.PUSH_SUB_PATH */] = () => {
  580. if (subPathDepth > 0) {
  581. subPathDepth--;
  582. mode = 4 /* States.IN_SUB_PATH */;
  583. actions[0 /* Actions.APPEND */]();
  584. }
  585. else {
  586. subPathDepth = 0;
  587. if (key === undefined) {
  588. return false;
  589. }
  590. key = formatSubPath(key);
  591. if (key === false) {
  592. return false;
  593. }
  594. else {
  595. actions[1 /* Actions.PUSH */]();
  596. }
  597. }
  598. };
  599. function maybeUnescapeQuote() {
  600. const nextChar = path[index + 1];
  601. if ((mode === 5 /* States.IN_SINGLE_QUOTE */ &&
  602. nextChar === "'" /* PathCharTypes.SINGLE_QUOTE */) ||
  603. (mode === 6 /* States.IN_DOUBLE_QUOTE */ &&
  604. nextChar === "\"" /* PathCharTypes.DOUBLE_QUOTE */)) {
  605. index++;
  606. newChar = '\\' + nextChar;
  607. actions[0 /* Actions.APPEND */]();
  608. return true;
  609. }
  610. }
  611. while (mode !== null) {
  612. index++;
  613. c = path[index];
  614. if (c === '\\' && maybeUnescapeQuote()) {
  615. continue;
  616. }
  617. type = getPathCharType(c);
  618. typeMap = pathStateMachine[mode];
  619. transition = typeMap[type] || typeMap["l" /* PathCharTypes.ELSE */] || 8 /* States.ERROR */;
  620. // check parse error
  621. if (transition === 8 /* States.ERROR */) {
  622. return;
  623. }
  624. mode = transition[0];
  625. if (transition[1] !== undefined) {
  626. action = actions[transition[1]];
  627. if (action) {
  628. newChar = c;
  629. if (action() === false) {
  630. return;
  631. }
  632. }
  633. }
  634. // check parse finish
  635. if (mode === 7 /* States.AFTER_PATH */) {
  636. return keys;
  637. }
  638. }
  639. }
  640. // path token cache
  641. const cache = new Map();
  642. /**
  643. * key-value message resolver
  644. *
  645. * @remarks
  646. * Resolves messages with the key-value structure. Note that messages with a hierarchical structure such as objects cannot be resolved
  647. *
  648. * @param obj - A target object to be resolved with path
  649. * @param path - A {@link Path | path} to resolve the value of message
  650. *
  651. * @returns A resolved {@link PathValue | path value}
  652. *
  653. * @VueI18nGeneral
  654. */
  655. function resolveWithKeyValue(obj, path) {
  656. return isObject(obj) ? obj[path] : null;
  657. }
  658. /**
  659. * message resolver
  660. *
  661. * @remarks
  662. * Resolves messages. messages with a hierarchical structure such as objects can be resolved. This resolver is used in VueI18n as default.
  663. *
  664. * @param obj - A target object to be resolved with path
  665. * @param path - A {@link Path | path} to resolve the value of message
  666. *
  667. * @returns A resolved {@link PathValue | path value}
  668. *
  669. * @VueI18nGeneral
  670. */
  671. function resolveValue(obj, path) {
  672. // check object
  673. if (!isObject(obj)) {
  674. return null;
  675. }
  676. // parse path
  677. let hit = cache.get(path);
  678. if (!hit) {
  679. hit = parse(path);
  680. if (hit) {
  681. cache.set(path, hit);
  682. }
  683. }
  684. // check hit
  685. if (!hit) {
  686. return null;
  687. }
  688. // resolve path value
  689. const len = hit.length;
  690. let last = obj;
  691. let i = 0;
  692. while (i < len) {
  693. const key = hit[i];
  694. /**
  695. * NOTE:
  696. * if `key` is intlify message format AST node key and `last` is intlify message format AST, skip it.
  697. * because the AST node is not a key-value structure.
  698. */
  699. if (AST_NODE_PROPS_KEYS.includes(key) && isMessageAST(last)) {
  700. return null;
  701. }
  702. const val = last[key];
  703. if (val === undefined) {
  704. return null;
  705. }
  706. if (isFunction(last)) {
  707. return null;
  708. }
  709. last = val;
  710. i++;
  711. }
  712. return last;
  713. }
  714. const CoreWarnCodes = {
  715. NOT_FOUND_KEY: 1,
  716. FALLBACK_TO_TRANSLATE: 2,
  717. CANNOT_FORMAT_NUMBER: 3,
  718. FALLBACK_TO_NUMBER_FORMAT: 4,
  719. CANNOT_FORMAT_DATE: 5,
  720. FALLBACK_TO_DATE_FORMAT: 6,
  721. EXPERIMENTAL_CUSTOM_MESSAGE_COMPILER: 7
  722. };
  723. const CORE_WARN_CODES_EXTEND_POINT = 8;
  724. /** @internal */
  725. const warnMessages = {
  726. [CoreWarnCodes.NOT_FOUND_KEY]: `Not found '{key}' key in '{locale}' locale messages.`,
  727. [CoreWarnCodes.FALLBACK_TO_TRANSLATE]: `Fall back to translate '{key}' key with '{target}' locale.`,
  728. [CoreWarnCodes.CANNOT_FORMAT_NUMBER]: `Cannot format a number value due to not supported Intl.NumberFormat.`,
  729. [CoreWarnCodes.FALLBACK_TO_NUMBER_FORMAT]: `Fall back to number format '{key}' key with '{target}' locale.`,
  730. [CoreWarnCodes.CANNOT_FORMAT_DATE]: `Cannot format a date value due to not supported Intl.DateTimeFormat.`,
  731. [CoreWarnCodes.FALLBACK_TO_DATE_FORMAT]: `Fall back to datetime format '{key}' key with '{target}' locale.`,
  732. [CoreWarnCodes.EXPERIMENTAL_CUSTOM_MESSAGE_COMPILER]: `This project is using Custom Message Compiler, which is an experimental feature. It may receive breaking changes or be removed in the future.`
  733. };
  734. function getWarnMessage(code, ...args) {
  735. return format$1(warnMessages[code], ...args);
  736. }
  737. /* eslint-disable @typescript-eslint/no-explicit-any */
  738. /**
  739. * Intlify core-base version
  740. * @internal
  741. */
  742. const VERSION = '11.1.3';
  743. const NOT_REOSLVED = -1;
  744. const DEFAULT_LOCALE = 'en-US';
  745. const MISSING_RESOLVE_VALUE = '';
  746. const capitalize = (str) => `${str.charAt(0).toLocaleUpperCase()}${str.substr(1)}`;
  747. function getDefaultLinkedModifiers() {
  748. return {
  749. upper: (val, type) => {
  750. // prettier-ignore
  751. return type === 'text' && isString(val)
  752. ? val.toUpperCase()
  753. : type === 'vnode' && isObject(val) && '__v_isVNode' in val
  754. ? val.children.toUpperCase()
  755. : val;
  756. },
  757. lower: (val, type) => {
  758. // prettier-ignore
  759. return type === 'text' && isString(val)
  760. ? val.toLowerCase()
  761. : type === 'vnode' && isObject(val) && '__v_isVNode' in val
  762. ? val.children.toLowerCase()
  763. : val;
  764. },
  765. capitalize: (val, type) => {
  766. // prettier-ignore
  767. return (type === 'text' && isString(val)
  768. ? capitalize(val)
  769. : type === 'vnode' && isObject(val) && '__v_isVNode' in val
  770. ? capitalize(val.children)
  771. : val);
  772. }
  773. };
  774. }
  775. let _compiler;
  776. function registerMessageCompiler(compiler) {
  777. _compiler = compiler;
  778. }
  779. let _resolver;
  780. /**
  781. * Register the message resolver
  782. *
  783. * @param resolver - A {@link MessageResolver} function
  784. *
  785. * @VueI18nGeneral
  786. */
  787. function registerMessageResolver(resolver) {
  788. _resolver = resolver;
  789. }
  790. let _fallbacker;
  791. /**
  792. * Register the locale fallbacker
  793. *
  794. * @param fallbacker - A {@link LocaleFallbacker} function
  795. *
  796. * @VueI18nGeneral
  797. */
  798. function registerLocaleFallbacker(fallbacker) {
  799. _fallbacker = fallbacker;
  800. }
  801. // Additional Meta for Intlify DevTools
  802. let _additionalMeta = null;
  803. /* #__NO_SIDE_EFFECTS__ */
  804. const setAdditionalMeta = (meta) => {
  805. _additionalMeta = meta;
  806. };
  807. /* #__NO_SIDE_EFFECTS__ */
  808. const getAdditionalMeta = () => _additionalMeta;
  809. let _fallbackContext = null;
  810. const setFallbackContext = (context) => {
  811. _fallbackContext = context;
  812. };
  813. const getFallbackContext = () => _fallbackContext;
  814. // ID for CoreContext
  815. let _cid = 0;
  816. function createCoreContext(options = {}) {
  817. // setup options
  818. const onWarn = isFunction(options.onWarn) ? options.onWarn : warn;
  819. const version = isString(options.version) ? options.version : VERSION;
  820. const locale = isString(options.locale) || isFunction(options.locale)
  821. ? options.locale
  822. : DEFAULT_LOCALE;
  823. const _locale = isFunction(locale) ? DEFAULT_LOCALE : locale;
  824. const fallbackLocale = isArray(options.fallbackLocale) ||
  825. isPlainObject(options.fallbackLocale) ||
  826. isString(options.fallbackLocale) ||
  827. options.fallbackLocale === false
  828. ? options.fallbackLocale
  829. : _locale;
  830. const messages = isPlainObject(options.messages)
  831. ? options.messages
  832. : createResources(_locale);
  833. const datetimeFormats = isPlainObject(options.datetimeFormats)
  834. ? options.datetimeFormats
  835. : createResources(_locale)
  836. ;
  837. const numberFormats = isPlainObject(options.numberFormats)
  838. ? options.numberFormats
  839. : createResources(_locale)
  840. ;
  841. const modifiers = assign(create(), options.modifiers, getDefaultLinkedModifiers());
  842. const pluralRules = options.pluralRules || create();
  843. const missing = isFunction(options.missing) ? options.missing : null;
  844. const missingWarn = isBoolean(options.missingWarn) || isRegExp(options.missingWarn)
  845. ? options.missingWarn
  846. : true;
  847. const fallbackWarn = isBoolean(options.fallbackWarn) || isRegExp(options.fallbackWarn)
  848. ? options.fallbackWarn
  849. : true;
  850. const fallbackFormat = !!options.fallbackFormat;
  851. const unresolving = !!options.unresolving;
  852. const postTranslation = isFunction(options.postTranslation)
  853. ? options.postTranslation
  854. : null;
  855. const processor = isPlainObject(options.processor) ? options.processor : null;
  856. const warnHtmlMessage = isBoolean(options.warnHtmlMessage)
  857. ? options.warnHtmlMessage
  858. : true;
  859. const escapeParameter = !!options.escapeParameter;
  860. const messageCompiler = isFunction(options.messageCompiler)
  861. ? options.messageCompiler
  862. : _compiler;
  863. if ((process.env.NODE_ENV !== 'production') &&
  864. !false &&
  865. !false &&
  866. isFunction(options.messageCompiler)) {
  867. warnOnce(getWarnMessage(CoreWarnCodes.EXPERIMENTAL_CUSTOM_MESSAGE_COMPILER));
  868. }
  869. const messageResolver = isFunction(options.messageResolver)
  870. ? options.messageResolver
  871. : _resolver || resolveWithKeyValue;
  872. const localeFallbacker = isFunction(options.localeFallbacker)
  873. ? options.localeFallbacker
  874. : _fallbacker || fallbackWithSimple;
  875. const fallbackContext = isObject(options.fallbackContext)
  876. ? options.fallbackContext
  877. : undefined;
  878. // setup internal options
  879. const internalOptions = options;
  880. const __datetimeFormatters = isObject(internalOptions.__datetimeFormatters)
  881. ? internalOptions.__datetimeFormatters
  882. : new Map()
  883. ;
  884. const __numberFormatters = isObject(internalOptions.__numberFormatters)
  885. ? internalOptions.__numberFormatters
  886. : new Map()
  887. ;
  888. const __meta = isObject(internalOptions.__meta) ? internalOptions.__meta : {};
  889. _cid++;
  890. const context = {
  891. version,
  892. cid: _cid,
  893. locale,
  894. fallbackLocale,
  895. messages,
  896. modifiers,
  897. pluralRules,
  898. missing,
  899. missingWarn,
  900. fallbackWarn,
  901. fallbackFormat,
  902. unresolving,
  903. postTranslation,
  904. processor,
  905. warnHtmlMessage,
  906. escapeParameter,
  907. messageCompiler,
  908. messageResolver,
  909. localeFallbacker,
  910. fallbackContext,
  911. onWarn,
  912. __meta
  913. };
  914. {
  915. context.datetimeFormats = datetimeFormats;
  916. context.numberFormats = numberFormats;
  917. context.__datetimeFormatters = __datetimeFormatters;
  918. context.__numberFormatters = __numberFormatters;
  919. }
  920. // for vue-devtools timeline event
  921. if ((process.env.NODE_ENV !== 'production')) {
  922. context.__v_emitter =
  923. internalOptions.__v_emitter != null
  924. ? internalOptions.__v_emitter
  925. : undefined;
  926. }
  927. // NOTE: experimental !!
  928. if ((process.env.NODE_ENV !== 'production') || __INTLIFY_PROD_DEVTOOLS__) {
  929. initI18nDevTools(context, version, __meta);
  930. }
  931. return context;
  932. }
  933. const createResources = (locale) => ({ [locale]: create() });
  934. /** @internal */
  935. function isTranslateFallbackWarn(fallback, key) {
  936. return fallback instanceof RegExp ? fallback.test(key) : fallback;
  937. }
  938. /** @internal */
  939. function isTranslateMissingWarn(missing, key) {
  940. return missing instanceof RegExp ? missing.test(key) : missing;
  941. }
  942. /** @internal */
  943. function handleMissing(context, key, locale, missingWarn, type) {
  944. const { missing, onWarn } = context;
  945. // for vue-devtools timeline event
  946. if ((process.env.NODE_ENV !== 'production')) {
  947. const emitter = context.__v_emitter;
  948. if (emitter) {
  949. emitter.emit('missing', {
  950. locale,
  951. key,
  952. type,
  953. groupId: `${type}:${key}`
  954. });
  955. }
  956. }
  957. if (missing !== null) {
  958. const ret = missing(context, locale, key, type);
  959. return isString(ret) ? ret : key;
  960. }
  961. else {
  962. if ((process.env.NODE_ENV !== 'production') && isTranslateMissingWarn(missingWarn, key)) {
  963. onWarn(getWarnMessage(CoreWarnCodes.NOT_FOUND_KEY, { key, locale }));
  964. }
  965. return key;
  966. }
  967. }
  968. /** @internal */
  969. function updateFallbackLocale(ctx, locale, fallback) {
  970. const context = ctx;
  971. context.__localeChainCache = new Map();
  972. ctx.localeFallbacker(ctx, fallback, locale);
  973. }
  974. /** @internal */
  975. function isAlmostSameLocale(locale, compareLocale) {
  976. if (locale === compareLocale)
  977. return false;
  978. return locale.split('-')[0] === compareLocale.split('-')[0];
  979. }
  980. /** @internal */
  981. function isImplicitFallback(targetLocale, locales) {
  982. const index = locales.indexOf(targetLocale);
  983. if (index === -1) {
  984. return false;
  985. }
  986. for (let i = index + 1; i < locales.length; i++) {
  987. if (isAlmostSameLocale(targetLocale, locales[i])) {
  988. return true;
  989. }
  990. }
  991. return false;
  992. }
  993. /* eslint-enable @typescript-eslint/no-explicit-any */
  994. const intlDefined = typeof Intl !== 'undefined';
  995. const Availabilities = {
  996. dateTimeFormat: intlDefined && typeof Intl.DateTimeFormat !== 'undefined',
  997. numberFormat: intlDefined && typeof Intl.NumberFormat !== 'undefined'
  998. };
  999. // implementation of `datetime` function
  1000. function datetime(context, ...args) {
  1001. const { datetimeFormats, unresolving, fallbackLocale, onWarn, localeFallbacker } = context;
  1002. const { __datetimeFormatters } = context;
  1003. if ((process.env.NODE_ENV !== 'production') && !Availabilities.dateTimeFormat) {
  1004. onWarn(getWarnMessage(CoreWarnCodes.CANNOT_FORMAT_DATE));
  1005. return MISSING_RESOLVE_VALUE;
  1006. }
  1007. const [key, value, options, overrides] = parseDateTimeArgs(...args);
  1008. const missingWarn = isBoolean(options.missingWarn)
  1009. ? options.missingWarn
  1010. : context.missingWarn;
  1011. const fallbackWarn = isBoolean(options.fallbackWarn)
  1012. ? options.fallbackWarn
  1013. : context.fallbackWarn;
  1014. const part = !!options.part;
  1015. const locale = getLocale(context, options);
  1016. const locales = localeFallbacker(context, // eslint-disable-line @typescript-eslint/no-explicit-any
  1017. fallbackLocale, locale);
  1018. if (!isString(key) || key === '') {
  1019. return new Intl.DateTimeFormat(locale, overrides).format(value);
  1020. }
  1021. // resolve format
  1022. let datetimeFormat = {};
  1023. let targetLocale;
  1024. let format = null;
  1025. let from = locale;
  1026. let to = null;
  1027. const type = 'datetime format';
  1028. for (let i = 0; i < locales.length; i++) {
  1029. targetLocale = to = locales[i];
  1030. if ((process.env.NODE_ENV !== 'production') &&
  1031. locale !== targetLocale &&
  1032. isTranslateFallbackWarn(fallbackWarn, key)) {
  1033. onWarn(getWarnMessage(CoreWarnCodes.FALLBACK_TO_DATE_FORMAT, {
  1034. key,
  1035. target: targetLocale
  1036. }));
  1037. }
  1038. // for vue-devtools timeline event
  1039. if ((process.env.NODE_ENV !== 'production') && locale !== targetLocale) {
  1040. const emitter = context.__v_emitter;
  1041. if (emitter) {
  1042. emitter.emit('fallback', {
  1043. type,
  1044. key,
  1045. from,
  1046. to,
  1047. groupId: `${type}:${key}`
  1048. });
  1049. }
  1050. }
  1051. datetimeFormat =
  1052. datetimeFormats[targetLocale] || {};
  1053. format = datetimeFormat[key];
  1054. if (isPlainObject(format))
  1055. break;
  1056. handleMissing(context, key, targetLocale, missingWarn, type); // eslint-disable-line @typescript-eslint/no-explicit-any
  1057. from = to;
  1058. }
  1059. // checking format and target locale
  1060. if (!isPlainObject(format) || !isString(targetLocale)) {
  1061. return unresolving ? NOT_REOSLVED : key;
  1062. }
  1063. let id = `${targetLocale}__${key}`;
  1064. if (!isEmptyObject(overrides)) {
  1065. id = `${id}__${JSON.stringify(overrides)}`;
  1066. }
  1067. let formatter = __datetimeFormatters.get(id);
  1068. if (!formatter) {
  1069. formatter = new Intl.DateTimeFormat(targetLocale, assign({}, format, overrides));
  1070. __datetimeFormatters.set(id, formatter);
  1071. }
  1072. return !part ? formatter.format(value) : formatter.formatToParts(value);
  1073. }
  1074. /** @internal */
  1075. const DATETIME_FORMAT_OPTIONS_KEYS = [
  1076. 'localeMatcher',
  1077. 'weekday',
  1078. 'era',
  1079. 'year',
  1080. 'month',
  1081. 'day',
  1082. 'hour',
  1083. 'minute',
  1084. 'second',
  1085. 'timeZoneName',
  1086. 'formatMatcher',
  1087. 'hour12',
  1088. 'timeZone',
  1089. 'dateStyle',
  1090. 'timeStyle',
  1091. 'calendar',
  1092. 'dayPeriod',
  1093. 'numberingSystem',
  1094. 'hourCycle',
  1095. 'fractionalSecondDigits'
  1096. ];
  1097. /** @internal */
  1098. function parseDateTimeArgs(...args) {
  1099. const [arg1, arg2, arg3, arg4] = args;
  1100. const options = create();
  1101. let overrides = create();
  1102. let value;
  1103. if (isString(arg1)) {
  1104. // Only allow ISO strings - other date formats are often supported,
  1105. // but may cause different results in different browsers.
  1106. const matches = arg1.match(/(\d{4}-\d{2}-\d{2})(T|\s)?(.*)/);
  1107. if (!matches) {
  1108. throw createCoreError(CoreErrorCodes.INVALID_ISO_DATE_ARGUMENT);
  1109. }
  1110. // Some browsers can not parse the iso datetime separated by space,
  1111. // this is a compromise solution by replace the 'T'/' ' with 'T'
  1112. const dateTime = matches[3]
  1113. ? matches[3].trim().startsWith('T')
  1114. ? `${matches[1].trim()}${matches[3].trim()}`
  1115. : `${matches[1].trim()}T${matches[3].trim()}`
  1116. : matches[1].trim();
  1117. value = new Date(dateTime);
  1118. try {
  1119. // This will fail if the date is not valid
  1120. value.toISOString();
  1121. }
  1122. catch {
  1123. throw createCoreError(CoreErrorCodes.INVALID_ISO_DATE_ARGUMENT);
  1124. }
  1125. }
  1126. else if (isDate(arg1)) {
  1127. if (isNaN(arg1.getTime())) {
  1128. throw createCoreError(CoreErrorCodes.INVALID_DATE_ARGUMENT);
  1129. }
  1130. value = arg1;
  1131. }
  1132. else if (isNumber(arg1)) {
  1133. value = arg1;
  1134. }
  1135. else {
  1136. throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
  1137. }
  1138. if (isString(arg2)) {
  1139. options.key = arg2;
  1140. }
  1141. else if (isPlainObject(arg2)) {
  1142. Object.keys(arg2).forEach(key => {
  1143. if (DATETIME_FORMAT_OPTIONS_KEYS.includes(key)) {
  1144. overrides[key] = arg2[key];
  1145. }
  1146. else {
  1147. options[key] = arg2[key];
  1148. }
  1149. });
  1150. }
  1151. if (isString(arg3)) {
  1152. options.locale = arg3;
  1153. }
  1154. else if (isPlainObject(arg3)) {
  1155. overrides = arg3;
  1156. }
  1157. if (isPlainObject(arg4)) {
  1158. overrides = arg4;
  1159. }
  1160. return [options.key || '', value, options, overrides];
  1161. }
  1162. /** @internal */
  1163. function clearDateTimeFormat(ctx, locale, format) {
  1164. const context = ctx;
  1165. for (const key in format) {
  1166. const id = `${locale}__${key}`;
  1167. if (!context.__datetimeFormatters.has(id)) {
  1168. continue;
  1169. }
  1170. context.__datetimeFormatters.delete(id);
  1171. }
  1172. }
  1173. // implementation of `number` function
  1174. function number(context, ...args) {
  1175. const { numberFormats, unresolving, fallbackLocale, onWarn, localeFallbacker } = context;
  1176. const { __numberFormatters } = context;
  1177. if ((process.env.NODE_ENV !== 'production') && !Availabilities.numberFormat) {
  1178. onWarn(getWarnMessage(CoreWarnCodes.CANNOT_FORMAT_NUMBER));
  1179. return MISSING_RESOLVE_VALUE;
  1180. }
  1181. const [key, value, options, overrides] = parseNumberArgs(...args);
  1182. const missingWarn = isBoolean(options.missingWarn)
  1183. ? options.missingWarn
  1184. : context.missingWarn;
  1185. const fallbackWarn = isBoolean(options.fallbackWarn)
  1186. ? options.fallbackWarn
  1187. : context.fallbackWarn;
  1188. const part = !!options.part;
  1189. const locale = getLocale(context, options);
  1190. const locales = localeFallbacker(context, // eslint-disable-line @typescript-eslint/no-explicit-any
  1191. fallbackLocale, locale);
  1192. if (!isString(key) || key === '') {
  1193. return new Intl.NumberFormat(locale, overrides).format(value);
  1194. }
  1195. // resolve format
  1196. let numberFormat = {};
  1197. let targetLocale;
  1198. let format = null;
  1199. let from = locale;
  1200. let to = null;
  1201. const type = 'number format';
  1202. for (let i = 0; i < locales.length; i++) {
  1203. targetLocale = to = locales[i];
  1204. if ((process.env.NODE_ENV !== 'production') &&
  1205. locale !== targetLocale &&
  1206. isTranslateFallbackWarn(fallbackWarn, key)) {
  1207. onWarn(getWarnMessage(CoreWarnCodes.FALLBACK_TO_NUMBER_FORMAT, {
  1208. key,
  1209. target: targetLocale
  1210. }));
  1211. }
  1212. // for vue-devtools timeline event
  1213. if ((process.env.NODE_ENV !== 'production') && locale !== targetLocale) {
  1214. const emitter = context.__v_emitter;
  1215. if (emitter) {
  1216. emitter.emit('fallback', {
  1217. type,
  1218. key,
  1219. from,
  1220. to,
  1221. groupId: `${type}:${key}`
  1222. });
  1223. }
  1224. }
  1225. numberFormat =
  1226. numberFormats[targetLocale] || {};
  1227. format = numberFormat[key];
  1228. if (isPlainObject(format))
  1229. break;
  1230. handleMissing(context, key, targetLocale, missingWarn, type); // eslint-disable-line @typescript-eslint/no-explicit-any
  1231. from = to;
  1232. }
  1233. // checking format and target locale
  1234. if (!isPlainObject(format) || !isString(targetLocale)) {
  1235. return unresolving ? NOT_REOSLVED : key;
  1236. }
  1237. let id = `${targetLocale}__${key}`;
  1238. if (!isEmptyObject(overrides)) {
  1239. id = `${id}__${JSON.stringify(overrides)}`;
  1240. }
  1241. let formatter = __numberFormatters.get(id);
  1242. if (!formatter) {
  1243. formatter = new Intl.NumberFormat(targetLocale, assign({}, format, overrides));
  1244. __numberFormatters.set(id, formatter);
  1245. }
  1246. return !part ? formatter.format(value) : formatter.formatToParts(value);
  1247. }
  1248. /** @internal */
  1249. const NUMBER_FORMAT_OPTIONS_KEYS = [
  1250. 'localeMatcher',
  1251. 'style',
  1252. 'currency',
  1253. 'currencyDisplay',
  1254. 'currencySign',
  1255. 'useGrouping',
  1256. 'minimumIntegerDigits',
  1257. 'minimumFractionDigits',
  1258. 'maximumFractionDigits',
  1259. 'minimumSignificantDigits',
  1260. 'maximumSignificantDigits',
  1261. 'compactDisplay',
  1262. 'notation',
  1263. 'signDisplay',
  1264. 'unit',
  1265. 'unitDisplay',
  1266. 'roundingMode',
  1267. 'roundingPriority',
  1268. 'roundingIncrement',
  1269. 'trailingZeroDisplay'
  1270. ];
  1271. /** @internal */
  1272. function parseNumberArgs(...args) {
  1273. const [arg1, arg2, arg3, arg4] = args;
  1274. const options = create();
  1275. let overrides = create();
  1276. if (!isNumber(arg1)) {
  1277. throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
  1278. }
  1279. const value = arg1;
  1280. if (isString(arg2)) {
  1281. options.key = arg2;
  1282. }
  1283. else if (isPlainObject(arg2)) {
  1284. Object.keys(arg2).forEach(key => {
  1285. if (NUMBER_FORMAT_OPTIONS_KEYS.includes(key)) {
  1286. overrides[key] = arg2[key];
  1287. }
  1288. else {
  1289. options[key] = arg2[key];
  1290. }
  1291. });
  1292. }
  1293. if (isString(arg3)) {
  1294. options.locale = arg3;
  1295. }
  1296. else if (isPlainObject(arg3)) {
  1297. overrides = arg3;
  1298. }
  1299. if (isPlainObject(arg4)) {
  1300. overrides = arg4;
  1301. }
  1302. return [options.key || '', value, options, overrides];
  1303. }
  1304. /** @internal */
  1305. function clearNumberFormat(ctx, locale, format) {
  1306. const context = ctx;
  1307. for (const key in format) {
  1308. const id = `${locale}__${key}`;
  1309. if (!context.__numberFormatters.has(id)) {
  1310. continue;
  1311. }
  1312. context.__numberFormatters.delete(id);
  1313. }
  1314. }
  1315. const DEFAULT_MODIFIER = (str) => str;
  1316. const DEFAULT_MESSAGE = (ctx) => ''; // eslint-disable-line
  1317. const DEFAULT_MESSAGE_DATA_TYPE = 'text';
  1318. const DEFAULT_NORMALIZE = (values) => values.length === 0 ? '' : join(values);
  1319. const DEFAULT_INTERPOLATE = toDisplayString;
  1320. function pluralDefault(choice, choicesLength) {
  1321. choice = Math.abs(choice);
  1322. if (choicesLength === 2) {
  1323. // prettier-ignore
  1324. return choice
  1325. ? choice > 1
  1326. ? 1
  1327. : 0
  1328. : 1;
  1329. }
  1330. return choice ? Math.min(choice, 2) : 0;
  1331. }
  1332. function getPluralIndex(options) {
  1333. // prettier-ignore
  1334. const index = isNumber(options.pluralIndex)
  1335. ? options.pluralIndex
  1336. : -1;
  1337. // prettier-ignore
  1338. return options.named && (isNumber(options.named.count) || isNumber(options.named.n))
  1339. ? isNumber(options.named.count)
  1340. ? options.named.count
  1341. : isNumber(options.named.n)
  1342. ? options.named.n
  1343. : index
  1344. : index;
  1345. }
  1346. function normalizeNamed(pluralIndex, props) {
  1347. if (!props.count) {
  1348. props.count = pluralIndex;
  1349. }
  1350. if (!props.n) {
  1351. props.n = pluralIndex;
  1352. }
  1353. }
  1354. function createMessageContext(options = {}) {
  1355. const locale = options.locale;
  1356. const pluralIndex = getPluralIndex(options);
  1357. const pluralRule = isObject(options.pluralRules) &&
  1358. isString(locale) &&
  1359. isFunction(options.pluralRules[locale])
  1360. ? options.pluralRules[locale]
  1361. : pluralDefault;
  1362. const orgPluralRule = isObject(options.pluralRules) &&
  1363. isString(locale) &&
  1364. isFunction(options.pluralRules[locale])
  1365. ? pluralDefault
  1366. : undefined;
  1367. const plural = (messages) => {
  1368. return messages[pluralRule(pluralIndex, messages.length, orgPluralRule)];
  1369. };
  1370. const _list = options.list || [];
  1371. const list = (index) => _list[index];
  1372. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  1373. const _named = options.named || create();
  1374. isNumber(options.pluralIndex) && normalizeNamed(pluralIndex, _named);
  1375. const named = (key) => _named[key];
  1376. function message(key, useLinked) {
  1377. // prettier-ignore
  1378. const msg = isFunction(options.messages)
  1379. ? options.messages(key, !!useLinked)
  1380. : isObject(options.messages)
  1381. ? options.messages[key]
  1382. : false;
  1383. return !msg
  1384. ? options.parent
  1385. ? options.parent.message(key) // resolve from parent messages
  1386. : DEFAULT_MESSAGE
  1387. : msg;
  1388. }
  1389. const _modifier = (name) => options.modifiers
  1390. ? options.modifiers[name]
  1391. : DEFAULT_MODIFIER;
  1392. const normalize = isPlainObject(options.processor) && isFunction(options.processor.normalize)
  1393. ? options.processor.normalize
  1394. : DEFAULT_NORMALIZE;
  1395. const interpolate = isPlainObject(options.processor) &&
  1396. isFunction(options.processor.interpolate)
  1397. ? options.processor.interpolate
  1398. : DEFAULT_INTERPOLATE;
  1399. const type = isPlainObject(options.processor) && isString(options.processor.type)
  1400. ? options.processor.type
  1401. : DEFAULT_MESSAGE_DATA_TYPE;
  1402. const linked = (key, ...args) => {
  1403. const [arg1, arg2] = args;
  1404. let type = 'text';
  1405. let modifier = '';
  1406. if (args.length === 1) {
  1407. if (isObject(arg1)) {
  1408. modifier = arg1.modifier || modifier;
  1409. type = arg1.type || type;
  1410. }
  1411. else if (isString(arg1)) {
  1412. modifier = arg1 || modifier;
  1413. }
  1414. }
  1415. else if (args.length === 2) {
  1416. if (isString(arg1)) {
  1417. modifier = arg1 || modifier;
  1418. }
  1419. if (isString(arg2)) {
  1420. type = arg2 || type;
  1421. }
  1422. }
  1423. const ret = message(key, true)(ctx);
  1424. const msg =
  1425. // The message in vnode resolved with linked are returned as an array by processor.nomalize
  1426. type === 'vnode' && isArray(ret) && modifier
  1427. ? ret[0]
  1428. : ret;
  1429. return modifier ? _modifier(modifier)(msg, type) : msg;
  1430. };
  1431. const ctx = {
  1432. ["list" /* HelperNameMap.LIST */]: list,
  1433. ["named" /* HelperNameMap.NAMED */]: named,
  1434. ["plural" /* HelperNameMap.PLURAL */]: plural,
  1435. ["linked" /* HelperNameMap.LINKED */]: linked,
  1436. ["message" /* HelperNameMap.MESSAGE */]: message,
  1437. ["type" /* HelperNameMap.TYPE */]: type,
  1438. ["interpolate" /* HelperNameMap.INTERPOLATE */]: interpolate,
  1439. ["normalize" /* HelperNameMap.NORMALIZE */]: normalize,
  1440. ["values" /* HelperNameMap.VALUES */]: assign(create(), _list, _named)
  1441. };
  1442. return ctx;
  1443. }
  1444. const NOOP_MESSAGE_FUNCTION = () => '';
  1445. const isMessageFunction = (val) => isFunction(val);
  1446. // implementation of `translate` function
  1447. function translate(context, ...args) {
  1448. const { fallbackFormat, postTranslation, unresolving, messageCompiler, fallbackLocale, messages } = context;
  1449. const [key, options] = parseTranslateArgs(...args);
  1450. const missingWarn = isBoolean(options.missingWarn)
  1451. ? options.missingWarn
  1452. : context.missingWarn;
  1453. const fallbackWarn = isBoolean(options.fallbackWarn)
  1454. ? options.fallbackWarn
  1455. : context.fallbackWarn;
  1456. const escapeParameter = isBoolean(options.escapeParameter)
  1457. ? options.escapeParameter
  1458. : context.escapeParameter;
  1459. const resolvedMessage = !!options.resolvedMessage;
  1460. // prettier-ignore
  1461. const defaultMsgOrKey = isString(options.default) || isBoolean(options.default) // default by function option
  1462. ? !isBoolean(options.default)
  1463. ? options.default
  1464. : (!messageCompiler ? () => key : key)
  1465. : fallbackFormat // default by `fallbackFormat` option
  1466. ? (!messageCompiler ? () => key : key)
  1467. : null;
  1468. const enableDefaultMsg = fallbackFormat ||
  1469. (defaultMsgOrKey != null &&
  1470. (isString(defaultMsgOrKey) || isFunction(defaultMsgOrKey)));
  1471. const locale = getLocale(context, options);
  1472. // escape params
  1473. escapeParameter && escapeParams(options);
  1474. // resolve message format
  1475. // eslint-disable-next-line prefer-const
  1476. let [formatScope, targetLocale, message] = !resolvedMessage
  1477. ? resolveMessageFormat(context, key, locale, fallbackLocale, fallbackWarn, missingWarn)
  1478. : [
  1479. key,
  1480. locale,
  1481. messages[locale] || create()
  1482. ];
  1483. // NOTE:
  1484. // Fix to work around `ssrTransfrom` bug in Vite.
  1485. // https://github.com/vitejs/vite/issues/4306
  1486. // To get around this, use temporary variables.
  1487. // https://github.com/nuxt/framework/issues/1461#issuecomment-954606243
  1488. let format = formatScope;
  1489. // if you use default message, set it as message format!
  1490. let cacheBaseKey = key;
  1491. if (!resolvedMessage &&
  1492. !(isString(format) ||
  1493. isMessageAST(format) ||
  1494. isMessageFunction(format))) {
  1495. if (enableDefaultMsg) {
  1496. format = defaultMsgOrKey;
  1497. cacheBaseKey = format;
  1498. }
  1499. }
  1500. // checking message format and target locale
  1501. if (!resolvedMessage &&
  1502. (!(isString(format) ||
  1503. isMessageAST(format) ||
  1504. isMessageFunction(format)) ||
  1505. !isString(targetLocale))) {
  1506. return unresolving ? NOT_REOSLVED : key;
  1507. }
  1508. // TODO: refactor
  1509. if ((process.env.NODE_ENV !== 'production') && isString(format) && context.messageCompiler == null) {
  1510. warn(`The message format compilation is not supported in this build. ` +
  1511. `Because message compiler isn't included. ` +
  1512. `You need to pre-compilation all message format. ` +
  1513. `So translate function return '${key}'.`);
  1514. return key;
  1515. }
  1516. // setup compile error detecting
  1517. let occurred = false;
  1518. const onError = () => {
  1519. occurred = true;
  1520. };
  1521. // compile message format
  1522. const msg = !isMessageFunction(format)
  1523. ? compileMessageFormat(context, key, targetLocale, format, cacheBaseKey, onError)
  1524. : format;
  1525. // if occurred compile error, return the message format
  1526. if (occurred) {
  1527. return format;
  1528. }
  1529. // evaluate message with context
  1530. const ctxOptions = getMessageContextOptions(context, targetLocale, message, options);
  1531. const msgContext = createMessageContext(ctxOptions);
  1532. const messaged = evaluateMessage(context, msg, msgContext);
  1533. // if use post translation option, proceed it with handler
  1534. const ret = postTranslation
  1535. ? postTranslation(messaged, key)
  1536. : messaged;
  1537. // NOTE: experimental !!
  1538. if ((process.env.NODE_ENV !== 'production') || __INTLIFY_PROD_DEVTOOLS__) {
  1539. // prettier-ignore
  1540. const payloads = {
  1541. timestamp: Date.now(),
  1542. key: isString(key)
  1543. ? key
  1544. : isMessageFunction(format)
  1545. ? format.key
  1546. : '',
  1547. locale: targetLocale || (isMessageFunction(format)
  1548. ? format.locale
  1549. : ''),
  1550. format: isString(format)
  1551. ? format
  1552. : isMessageFunction(format)
  1553. ? format.source
  1554. : '',
  1555. message: ret
  1556. };
  1557. payloads.meta = assign({}, context.__meta, getAdditionalMeta() || {});
  1558. translateDevTools(payloads);
  1559. }
  1560. return ret;
  1561. }
  1562. function escapeParams(options) {
  1563. if (isArray(options.list)) {
  1564. options.list = options.list.map(item => isString(item) ? escapeHtml(item) : item);
  1565. }
  1566. else if (isObject(options.named)) {
  1567. Object.keys(options.named).forEach(key => {
  1568. if (isString(options.named[key])) {
  1569. options.named[key] = escapeHtml(options.named[key]);
  1570. }
  1571. });
  1572. }
  1573. }
  1574. function resolveMessageFormat(context, key, locale, fallbackLocale, fallbackWarn, missingWarn) {
  1575. const { messages, onWarn, messageResolver: resolveValue, localeFallbacker } = context;
  1576. const locales = localeFallbacker(context, fallbackLocale, locale); // eslint-disable-line @typescript-eslint/no-explicit-any
  1577. let message = create();
  1578. let targetLocale;
  1579. let format = null;
  1580. let from = locale;
  1581. let to = null;
  1582. const type = 'translate';
  1583. for (let i = 0; i < locales.length; i++) {
  1584. targetLocale = to = locales[i];
  1585. if ((process.env.NODE_ENV !== 'production') &&
  1586. locale !== targetLocale &&
  1587. !isAlmostSameLocale(locale, targetLocale) &&
  1588. isTranslateFallbackWarn(fallbackWarn, key)) {
  1589. onWarn(getWarnMessage(CoreWarnCodes.FALLBACK_TO_TRANSLATE, {
  1590. key,
  1591. target: targetLocale
  1592. }));
  1593. }
  1594. // for vue-devtools timeline event
  1595. if ((process.env.NODE_ENV !== 'production') && locale !== targetLocale) {
  1596. const emitter = context.__v_emitter;
  1597. if (emitter) {
  1598. emitter.emit('fallback', {
  1599. type,
  1600. key,
  1601. from,
  1602. to,
  1603. groupId: `${type}:${key}`
  1604. });
  1605. }
  1606. }
  1607. message =
  1608. messages[targetLocale] || create();
  1609. // for vue-devtools timeline event
  1610. let start = null;
  1611. let startTag;
  1612. let endTag;
  1613. if ((process.env.NODE_ENV !== 'production') && inBrowser) {
  1614. start = window.performance.now();
  1615. startTag = 'intlify-message-resolve-start';
  1616. endTag = 'intlify-message-resolve-end';
  1617. mark && mark(startTag);
  1618. }
  1619. if ((format = resolveValue(message, key)) === null) {
  1620. // if null, resolve with object key path
  1621. format = message[key]; // eslint-disable-line @typescript-eslint/no-explicit-any
  1622. }
  1623. // for vue-devtools timeline event
  1624. if ((process.env.NODE_ENV !== 'production') && inBrowser) {
  1625. const end = window.performance.now();
  1626. const emitter = context.__v_emitter;
  1627. if (emitter && start && format) {
  1628. emitter.emit('message-resolve', {
  1629. type: 'message-resolve',
  1630. key,
  1631. message: format,
  1632. time: end - start,
  1633. groupId: `${type}:${key}`
  1634. });
  1635. }
  1636. if (startTag && endTag && mark && measure) {
  1637. mark(endTag);
  1638. measure('intlify message resolve', startTag, endTag);
  1639. }
  1640. }
  1641. if (isString(format) || isMessageAST(format) || isMessageFunction(format)) {
  1642. break;
  1643. }
  1644. if (!isImplicitFallback(targetLocale, locales)) {
  1645. const missingRet = handleMissing(context, // eslint-disable-line @typescript-eslint/no-explicit-any
  1646. key, targetLocale, missingWarn, type);
  1647. if (missingRet !== key) {
  1648. format = missingRet;
  1649. }
  1650. }
  1651. from = to;
  1652. }
  1653. return [format, targetLocale, message];
  1654. }
  1655. function compileMessageFormat(context, key, targetLocale, format, cacheBaseKey, onError) {
  1656. const { messageCompiler, warnHtmlMessage } = context;
  1657. if (isMessageFunction(format)) {
  1658. const msg = format;
  1659. msg.locale = msg.locale || targetLocale;
  1660. msg.key = msg.key || key;
  1661. return msg;
  1662. }
  1663. if (messageCompiler == null) {
  1664. const msg = (() => format);
  1665. msg.locale = targetLocale;
  1666. msg.key = key;
  1667. return msg;
  1668. }
  1669. // for vue-devtools timeline event
  1670. let start = null;
  1671. let startTag;
  1672. let endTag;
  1673. if ((process.env.NODE_ENV !== 'production') && inBrowser) {
  1674. start = window.performance.now();
  1675. startTag = 'intlify-message-compilation-start';
  1676. endTag = 'intlify-message-compilation-end';
  1677. mark && mark(startTag);
  1678. }
  1679. const msg = messageCompiler(format, getCompileContext(context, targetLocale, cacheBaseKey, format, warnHtmlMessage, onError));
  1680. // for vue-devtools timeline event
  1681. if ((process.env.NODE_ENV !== 'production') && inBrowser) {
  1682. const end = window.performance.now();
  1683. const emitter = context.__v_emitter;
  1684. if (emitter && start) {
  1685. emitter.emit('message-compilation', {
  1686. type: 'message-compilation',
  1687. message: format,
  1688. time: end - start,
  1689. groupId: `${'translate'}:${key}`
  1690. });
  1691. }
  1692. if (startTag && endTag && mark && measure) {
  1693. mark(endTag);
  1694. measure('intlify message compilation', startTag, endTag);
  1695. }
  1696. }
  1697. msg.locale = targetLocale;
  1698. msg.key = key;
  1699. msg.source = format;
  1700. return msg;
  1701. }
  1702. function evaluateMessage(context, msg, msgCtx) {
  1703. // for vue-devtools timeline event
  1704. let start = null;
  1705. let startTag;
  1706. let endTag;
  1707. if ((process.env.NODE_ENV !== 'production') && inBrowser) {
  1708. start = window.performance.now();
  1709. startTag = 'intlify-message-evaluation-start';
  1710. endTag = 'intlify-message-evaluation-end';
  1711. mark && mark(startTag);
  1712. }
  1713. const messaged = msg(msgCtx);
  1714. // for vue-devtools timeline event
  1715. if ((process.env.NODE_ENV !== 'production') && inBrowser) {
  1716. const end = window.performance.now();
  1717. const emitter = context.__v_emitter;
  1718. if (emitter && start) {
  1719. emitter.emit('message-evaluation', {
  1720. type: 'message-evaluation',
  1721. value: messaged,
  1722. time: end - start,
  1723. groupId: `${'translate'}:${msg.key}`
  1724. });
  1725. }
  1726. if (startTag && endTag && mark && measure) {
  1727. mark(endTag);
  1728. measure('intlify message evaluation', startTag, endTag);
  1729. }
  1730. }
  1731. return messaged;
  1732. }
  1733. /** @internal */
  1734. function parseTranslateArgs(...args) {
  1735. const [arg1, arg2, arg3] = args;
  1736. const options = create();
  1737. if (!isString(arg1) &&
  1738. !isNumber(arg1) &&
  1739. !isMessageFunction(arg1) &&
  1740. !isMessageAST(arg1)) {
  1741. throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
  1742. }
  1743. // prettier-ignore
  1744. const key = isNumber(arg1)
  1745. ? String(arg1)
  1746. : isMessageFunction(arg1)
  1747. ? arg1
  1748. : arg1;
  1749. if (isNumber(arg2)) {
  1750. options.plural = arg2;
  1751. }
  1752. else if (isString(arg2)) {
  1753. options.default = arg2;
  1754. }
  1755. else if (isPlainObject(arg2) && !isEmptyObject(arg2)) {
  1756. options.named = arg2;
  1757. }
  1758. else if (isArray(arg2)) {
  1759. options.list = arg2;
  1760. }
  1761. if (isNumber(arg3)) {
  1762. options.plural = arg3;
  1763. }
  1764. else if (isString(arg3)) {
  1765. options.default = arg3;
  1766. }
  1767. else if (isPlainObject(arg3)) {
  1768. assign(options, arg3);
  1769. }
  1770. return [key, options];
  1771. }
  1772. function getCompileContext(context, locale, key, source, warnHtmlMessage, onError) {
  1773. return {
  1774. locale,
  1775. key,
  1776. warnHtmlMessage,
  1777. onError: (err) => {
  1778. onError && onError(err);
  1779. if ((process.env.NODE_ENV !== 'production')) {
  1780. const _source = getSourceForCodeFrame(source);
  1781. const message = `Message compilation error: ${err.message}`;
  1782. const codeFrame = err.location &&
  1783. _source &&
  1784. generateCodeFrame(_source, err.location.start.offset, err.location.end.offset);
  1785. const emitter = context.__v_emitter;
  1786. if (emitter && _source) {
  1787. emitter.emit('compile-error', {
  1788. message: _source,
  1789. error: err.message,
  1790. start: err.location && err.location.start.offset,
  1791. end: err.location && err.location.end.offset,
  1792. groupId: `${'translate'}:${key}`
  1793. });
  1794. }
  1795. console.error(codeFrame ? `${message}\n${codeFrame}` : message);
  1796. }
  1797. else {
  1798. throw err;
  1799. }
  1800. },
  1801. onCacheKey: (source) => generateFormatCacheKey(locale, key, source)
  1802. };
  1803. }
  1804. function getSourceForCodeFrame(source) {
  1805. if (isString(source)) {
  1806. return source;
  1807. }
  1808. else {
  1809. if (source.loc && source.loc.source) {
  1810. return source.loc.source;
  1811. }
  1812. }
  1813. }
  1814. function getMessageContextOptions(context, locale, message, options) {
  1815. const { modifiers, pluralRules, messageResolver: resolveValue, fallbackLocale, fallbackWarn, missingWarn, fallbackContext } = context;
  1816. const resolveMessage = (key, useLinked) => {
  1817. let val = resolveValue(message, key);
  1818. // fallback
  1819. if (val == null && (fallbackContext || useLinked)) {
  1820. const [, , message] = resolveMessageFormat(fallbackContext || context, // NOTE: if has fallbackContext, fallback to root, else if use linked, fallback to local context
  1821. key, locale, fallbackLocale, fallbackWarn, missingWarn);
  1822. val = resolveValue(message, key);
  1823. }
  1824. if (isString(val) || isMessageAST(val)) {
  1825. let occurred = false;
  1826. const onError = () => {
  1827. occurred = true;
  1828. };
  1829. const msg = compileMessageFormat(context, key, locale, val, key, onError);
  1830. return !occurred
  1831. ? msg
  1832. : NOOP_MESSAGE_FUNCTION;
  1833. }
  1834. else if (isMessageFunction(val)) {
  1835. return val;
  1836. }
  1837. else {
  1838. // TODO: should be implemented warning message
  1839. return NOOP_MESSAGE_FUNCTION;
  1840. }
  1841. };
  1842. const ctxOptions = {
  1843. locale,
  1844. modifiers,
  1845. pluralRules,
  1846. messages: resolveMessage
  1847. };
  1848. if (context.processor) {
  1849. ctxOptions.processor = context.processor;
  1850. }
  1851. if (options.list) {
  1852. ctxOptions.list = options.list;
  1853. }
  1854. if (options.named) {
  1855. ctxOptions.named = options.named;
  1856. }
  1857. if (isNumber(options.plural)) {
  1858. ctxOptions.pluralIndex = options.plural;
  1859. }
  1860. return ctxOptions;
  1861. }
  1862. {
  1863. initFeatureFlags();
  1864. }
  1865. export { AST_NODE_PROPS_KEYS, CORE_ERROR_CODES_EXTEND_POINT, CORE_WARN_CODES_EXTEND_POINT, CoreErrorCodes, CoreWarnCodes, DATETIME_FORMAT_OPTIONS_KEYS, DEFAULT_LOCALE, DEFAULT_MESSAGE_DATA_TYPE, MISSING_RESOLVE_VALUE, NOT_REOSLVED, NUMBER_FORMAT_OPTIONS_KEYS, VERSION, clearCompileCache, clearDateTimeFormat, clearNumberFormat, compile, createCoreContext, createCoreError, createMessageContext, datetime, fallbackWithLocaleChain, fallbackWithSimple, getAdditionalMeta, getDevToolsHook, getFallbackContext, getLocale, getWarnMessage, handleMissing, initI18nDevTools, isAlmostSameLocale, isImplicitFallback, isMessageAST, isMessageFunction, isTranslateFallbackWarn, isTranslateMissingWarn, number, parse, parseDateTimeArgs, parseNumberArgs, parseTranslateArgs, registerLocaleFallbacker, registerMessageCompiler, registerMessageResolver, resolveLocale, resolveValue, resolveWithKeyValue, setAdditionalMeta, setDevToolsHook, setFallbackContext, translate, translateDevTools, updateFallbackLocale };