core-base.global.js 131 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586
  1. /*!
  2. * core-base v9.13.1
  3. * (c) 2024 kazuya kawaguchi
  4. * Released under the MIT License.
  5. */
  6. var IntlifyCoreBase = (function (exports) {
  7. 'use strict';
  8. /**
  9. * Original Utilities
  10. * written by kazuya kawaguchi
  11. */
  12. const inBrowser = typeof window !== 'undefined';
  13. let mark;
  14. let measure;
  15. {
  16. const perf = inBrowser && window.performance;
  17. if (perf &&
  18. perf.mark &&
  19. perf.measure &&
  20. perf.clearMarks &&
  21. // @ts-ignore browser compat
  22. perf.clearMeasures) {
  23. mark = (tag) => {
  24. perf.mark(tag);
  25. };
  26. measure = (name, startTag, endTag) => {
  27. perf.measure(name, startTag, endTag);
  28. perf.clearMarks(startTag);
  29. perf.clearMarks(endTag);
  30. };
  31. }
  32. }
  33. const RE_ARGS = /\{([0-9a-zA-Z]+)\}/g;
  34. /* eslint-disable */
  35. function format$1(message, ...args) {
  36. if (args.length === 1 && isObject(args[0])) {
  37. args = args[0];
  38. }
  39. if (!args || !args.hasOwnProperty) {
  40. args = {};
  41. }
  42. return message.replace(RE_ARGS, (match, identifier) => {
  43. return args.hasOwnProperty(identifier) ? args[identifier] : '';
  44. });
  45. }
  46. const generateFormatCacheKey = (locale, key, source) => friendlyJSONstringify({ l: locale, k: key, s: source });
  47. const friendlyJSONstringify = (json) => JSON.stringify(json)
  48. .replace(/\u2028/g, '\\u2028')
  49. .replace(/\u2029/g, '\\u2029')
  50. .replace(/\u0027/g, '\\u0027');
  51. const isNumber = (val) => typeof val === 'number' && isFinite(val);
  52. const isDate = (val) => toTypeString(val) === '[object Date]';
  53. const isRegExp = (val) => toTypeString(val) === '[object RegExp]';
  54. const isEmptyObject = (val) => isPlainObject(val) && Object.keys(val).length === 0;
  55. const assign = Object.assign;
  56. function escapeHtml(rawText) {
  57. return rawText
  58. .replace(/</g, '&lt;')
  59. .replace(/>/g, '&gt;')
  60. .replace(/"/g, '&quot;')
  61. .replace(/'/g, '&apos;');
  62. }
  63. /* eslint-enable */
  64. /**
  65. * Useful Utilities By Evan you
  66. * Modified by kazuya kawaguchi
  67. * MIT License
  68. * https://github.com/vuejs/vue-next/blob/master/packages/shared/src/index.ts
  69. * https://github.com/vuejs/vue-next/blob/master/packages/shared/src/codeframe.ts
  70. */
  71. const isArray = Array.isArray;
  72. const isFunction = (val) => typeof val === 'function';
  73. const isString = (val) => typeof val === 'string';
  74. const isBoolean = (val) => typeof val === 'boolean';
  75. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  76. const isObject = (val) => val !== null && typeof val === 'object';
  77. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  78. const isPromise = (val) => {
  79. return isObject(val) && isFunction(val.then) && isFunction(val.catch);
  80. };
  81. const objectToString = Object.prototype.toString;
  82. const toTypeString = (value) => objectToString.call(value);
  83. const isPlainObject = (val) => {
  84. if (!isObject(val))
  85. return false;
  86. const proto = Object.getPrototypeOf(val);
  87. return proto === null || proto.constructor === Object;
  88. };
  89. // for converting list and named values to displayed strings.
  90. const toDisplayString = (val) => {
  91. return val == null
  92. ? ''
  93. : isArray(val) || (isPlainObject(val) && val.toString === objectToString)
  94. ? JSON.stringify(val, null, 2)
  95. : String(val);
  96. };
  97. function join(items, separator = '') {
  98. return items.reduce((str, item, index) => (index === 0 ? str + item : str + separator + item), '');
  99. }
  100. const RANGE = 2;
  101. function generateCodeFrame(source, start = 0, end = source.length) {
  102. const lines = source.split(/\r?\n/);
  103. let count = 0;
  104. const res = [];
  105. for (let i = 0; i < lines.length; i++) {
  106. count += lines[i].length + 1;
  107. if (count >= start) {
  108. for (let j = i - RANGE; j <= i + RANGE || end > count; j++) {
  109. if (j < 0 || j >= lines.length)
  110. continue;
  111. const line = j + 1;
  112. res.push(`${line}${' '.repeat(3 - String(line).length)}| ${lines[j]}`);
  113. const lineLength = lines[j].length;
  114. if (j === i) {
  115. // push underline
  116. const pad = start - (count - lineLength) + 1;
  117. const length = Math.max(1, end > count ? lineLength - pad : end - start);
  118. res.push(` | ` + ' '.repeat(pad) + '^'.repeat(length));
  119. }
  120. else if (j > i) {
  121. if (end > count) {
  122. const length = Math.max(Math.min(end - count, lineLength), 1);
  123. res.push(` | ` + '^'.repeat(length));
  124. }
  125. count += lineLength + 1;
  126. }
  127. }
  128. break;
  129. }
  130. }
  131. return res.join('\n');
  132. }
  133. function incrementer(code) {
  134. let current = code;
  135. return () => ++current;
  136. }
  137. function warn(msg, err) {
  138. if (typeof console !== 'undefined') {
  139. console.warn(`[intlify] ` + msg);
  140. /* istanbul ignore if */
  141. if (err) {
  142. console.warn(err.stack);
  143. }
  144. }
  145. }
  146. function createPosition(line, column, offset) {
  147. return { line, column, offset };
  148. }
  149. function createLocation(start, end, source) {
  150. const loc = { start, end };
  151. if (source != null) {
  152. loc.source = source;
  153. }
  154. return loc;
  155. }
  156. const CompileWarnCodes = {
  157. USE_MODULO_SYNTAX: 1,
  158. __EXTEND_POINT__: 2
  159. };
  160. /** @internal */
  161. const warnMessages$1 = {
  162. [CompileWarnCodes.USE_MODULO_SYNTAX]: `Use modulo before '{{0}}'.`
  163. };
  164. function createCompileWarn(code, loc, ...args) {
  165. const msg = format$1(warnMessages$1[code] || '', ...(args || [])) ;
  166. const message = { message: String(msg), code };
  167. if (loc) {
  168. message.location = loc;
  169. }
  170. return message;
  171. }
  172. const CompileErrorCodes = {
  173. // tokenizer error codes
  174. EXPECTED_TOKEN: 1,
  175. INVALID_TOKEN_IN_PLACEHOLDER: 2,
  176. UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER: 3,
  177. UNKNOWN_ESCAPE_SEQUENCE: 4,
  178. INVALID_UNICODE_ESCAPE_SEQUENCE: 5,
  179. UNBALANCED_CLOSING_BRACE: 6,
  180. UNTERMINATED_CLOSING_BRACE: 7,
  181. EMPTY_PLACEHOLDER: 8,
  182. NOT_ALLOW_NEST_PLACEHOLDER: 9,
  183. INVALID_LINKED_FORMAT: 10,
  184. // parser error codes
  185. MUST_HAVE_MESSAGES_IN_PLURAL: 11,
  186. UNEXPECTED_EMPTY_LINKED_MODIFIER: 12,
  187. UNEXPECTED_EMPTY_LINKED_KEY: 13,
  188. UNEXPECTED_LEXICAL_ANALYSIS: 14,
  189. // generator error codes
  190. UNHANDLED_CODEGEN_NODE_TYPE: 15,
  191. // minifier error codes
  192. UNHANDLED_MINIFIER_NODE_TYPE: 16,
  193. // Special value for higher-order compilers to pick up the last code
  194. // to avoid collision of error codes. This should always be kept as the last
  195. // item.
  196. __EXTEND_POINT__: 17
  197. };
  198. /** @internal */
  199. const errorMessages$1 = {
  200. // tokenizer error messages
  201. [CompileErrorCodes.EXPECTED_TOKEN]: `Expected token: '{0}'`,
  202. [CompileErrorCodes.INVALID_TOKEN_IN_PLACEHOLDER]: `Invalid token in placeholder: '{0}'`,
  203. [CompileErrorCodes.UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER]: `Unterminated single quote in placeholder`,
  204. [CompileErrorCodes.UNKNOWN_ESCAPE_SEQUENCE]: `Unknown escape sequence: \\{0}`,
  205. [CompileErrorCodes.INVALID_UNICODE_ESCAPE_SEQUENCE]: `Invalid unicode escape sequence: {0}`,
  206. [CompileErrorCodes.UNBALANCED_CLOSING_BRACE]: `Unbalanced closing brace`,
  207. [CompileErrorCodes.UNTERMINATED_CLOSING_BRACE]: `Unterminated closing brace`,
  208. [CompileErrorCodes.EMPTY_PLACEHOLDER]: `Empty placeholder`,
  209. [CompileErrorCodes.NOT_ALLOW_NEST_PLACEHOLDER]: `Not allowed nest placeholder`,
  210. [CompileErrorCodes.INVALID_LINKED_FORMAT]: `Invalid linked format`,
  211. // parser error messages
  212. [CompileErrorCodes.MUST_HAVE_MESSAGES_IN_PLURAL]: `Plural must have messages`,
  213. [CompileErrorCodes.UNEXPECTED_EMPTY_LINKED_MODIFIER]: `Unexpected empty linked modifier`,
  214. [CompileErrorCodes.UNEXPECTED_EMPTY_LINKED_KEY]: `Unexpected empty linked key`,
  215. [CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS]: `Unexpected lexical analysis in token: '{0}'`,
  216. // generator error messages
  217. [CompileErrorCodes.UNHANDLED_CODEGEN_NODE_TYPE]: `unhandled codegen node type: '{0}'`,
  218. // minimizer error messages
  219. [CompileErrorCodes.UNHANDLED_MINIFIER_NODE_TYPE]: `unhandled mimifier node type: '{0}'`
  220. };
  221. function createCompileError(code, loc, options = {}) {
  222. const { domain, messages, args } = options;
  223. const msg = format$1((messages || errorMessages$1)[code] || '', ...(args || []))
  224. ;
  225. const error = new SyntaxError(String(msg));
  226. error.code = code;
  227. if (loc) {
  228. error.location = loc;
  229. }
  230. error.domain = domain;
  231. return error;
  232. }
  233. /** @internal */
  234. function defaultOnError(error) {
  235. throw error;
  236. }
  237. // eslint-disable-next-line no-useless-escape
  238. const RE_HTML_TAG = /<\/?[\w\s="/.':;#-\/]+>/;
  239. const detectHtmlTag = (source) => RE_HTML_TAG.test(source);
  240. const CHAR_SP = ' ';
  241. const CHAR_CR = '\r';
  242. const CHAR_LF = '\n';
  243. const CHAR_LS = String.fromCharCode(0x2028);
  244. const CHAR_PS = String.fromCharCode(0x2029);
  245. function createScanner(str) {
  246. const _buf = str;
  247. let _index = 0;
  248. let _line = 1;
  249. let _column = 1;
  250. let _peekOffset = 0;
  251. const isCRLF = (index) => _buf[index] === CHAR_CR && _buf[index + 1] === CHAR_LF;
  252. const isLF = (index) => _buf[index] === CHAR_LF;
  253. const isPS = (index) => _buf[index] === CHAR_PS;
  254. const isLS = (index) => _buf[index] === CHAR_LS;
  255. const isLineEnd = (index) => isCRLF(index) || isLF(index) || isPS(index) || isLS(index);
  256. const index = () => _index;
  257. const line = () => _line;
  258. const column = () => _column;
  259. const peekOffset = () => _peekOffset;
  260. const charAt = (offset) => isCRLF(offset) || isPS(offset) || isLS(offset) ? CHAR_LF : _buf[offset];
  261. const currentChar = () => charAt(_index);
  262. const currentPeek = () => charAt(_index + _peekOffset);
  263. function next() {
  264. _peekOffset = 0;
  265. if (isLineEnd(_index)) {
  266. _line++;
  267. _column = 0;
  268. }
  269. if (isCRLF(_index)) {
  270. _index++;
  271. }
  272. _index++;
  273. _column++;
  274. return _buf[_index];
  275. }
  276. function peek() {
  277. if (isCRLF(_index + _peekOffset)) {
  278. _peekOffset++;
  279. }
  280. _peekOffset++;
  281. return _buf[_index + _peekOffset];
  282. }
  283. function reset() {
  284. _index = 0;
  285. _line = 1;
  286. _column = 1;
  287. _peekOffset = 0;
  288. }
  289. function resetPeek(offset = 0) {
  290. _peekOffset = offset;
  291. }
  292. function skipToPeek() {
  293. const target = _index + _peekOffset;
  294. // eslint-disable-next-line no-unmodified-loop-condition
  295. while (target !== _index) {
  296. next();
  297. }
  298. _peekOffset = 0;
  299. }
  300. return {
  301. index,
  302. line,
  303. column,
  304. peekOffset,
  305. charAt,
  306. currentChar,
  307. currentPeek,
  308. next,
  309. peek,
  310. reset,
  311. resetPeek,
  312. skipToPeek
  313. };
  314. }
  315. const EOF = undefined;
  316. const DOT = '.';
  317. const LITERAL_DELIMITER = "'";
  318. const ERROR_DOMAIN$3 = 'tokenizer';
  319. function createTokenizer(source, options = {}) {
  320. const location = options.location !== false;
  321. const _scnr = createScanner(source);
  322. const currentOffset = () => _scnr.index();
  323. const currentPosition = () => createPosition(_scnr.line(), _scnr.column(), _scnr.index());
  324. const _initLoc = currentPosition();
  325. const _initOffset = currentOffset();
  326. const _context = {
  327. currentType: 14 /* TokenTypes.EOF */,
  328. offset: _initOffset,
  329. startLoc: _initLoc,
  330. endLoc: _initLoc,
  331. lastType: 14 /* TokenTypes.EOF */,
  332. lastOffset: _initOffset,
  333. lastStartLoc: _initLoc,
  334. lastEndLoc: _initLoc,
  335. braceNest: 0,
  336. inLinked: false,
  337. text: ''
  338. };
  339. const context = () => _context;
  340. const { onError } = options;
  341. function emitError(code, pos, offset, ...args) {
  342. const ctx = context();
  343. pos.column += offset;
  344. pos.offset += offset;
  345. if (onError) {
  346. const loc = location ? createLocation(ctx.startLoc, pos) : null;
  347. const err = createCompileError(code, loc, {
  348. domain: ERROR_DOMAIN$3,
  349. args
  350. });
  351. onError(err);
  352. }
  353. }
  354. function getToken(context, type, value) {
  355. context.endLoc = currentPosition();
  356. context.currentType = type;
  357. const token = { type };
  358. if (location) {
  359. token.loc = createLocation(context.startLoc, context.endLoc);
  360. }
  361. if (value != null) {
  362. token.value = value;
  363. }
  364. return token;
  365. }
  366. const getEndToken = (context) => getToken(context, 14 /* TokenTypes.EOF */);
  367. function eat(scnr, ch) {
  368. if (scnr.currentChar() === ch) {
  369. scnr.next();
  370. return ch;
  371. }
  372. else {
  373. emitError(CompileErrorCodes.EXPECTED_TOKEN, currentPosition(), 0, ch);
  374. return '';
  375. }
  376. }
  377. function peekSpaces(scnr) {
  378. let buf = '';
  379. while (scnr.currentPeek() === CHAR_SP || scnr.currentPeek() === CHAR_LF) {
  380. buf += scnr.currentPeek();
  381. scnr.peek();
  382. }
  383. return buf;
  384. }
  385. function skipSpaces(scnr) {
  386. const buf = peekSpaces(scnr);
  387. scnr.skipToPeek();
  388. return buf;
  389. }
  390. function isIdentifierStart(ch) {
  391. if (ch === EOF) {
  392. return false;
  393. }
  394. const cc = ch.charCodeAt(0);
  395. return ((cc >= 97 && cc <= 122) || // a-z
  396. (cc >= 65 && cc <= 90) || // A-Z
  397. cc === 95 // _
  398. );
  399. }
  400. function isNumberStart(ch) {
  401. if (ch === EOF) {
  402. return false;
  403. }
  404. const cc = ch.charCodeAt(0);
  405. return cc >= 48 && cc <= 57; // 0-9
  406. }
  407. function isNamedIdentifierStart(scnr, context) {
  408. const { currentType } = context;
  409. if (currentType !== 2 /* TokenTypes.BraceLeft */) {
  410. return false;
  411. }
  412. peekSpaces(scnr);
  413. const ret = isIdentifierStart(scnr.currentPeek());
  414. scnr.resetPeek();
  415. return ret;
  416. }
  417. function isListIdentifierStart(scnr, context) {
  418. const { currentType } = context;
  419. if (currentType !== 2 /* TokenTypes.BraceLeft */) {
  420. return false;
  421. }
  422. peekSpaces(scnr);
  423. const ch = scnr.currentPeek() === '-' ? scnr.peek() : scnr.currentPeek();
  424. const ret = isNumberStart(ch);
  425. scnr.resetPeek();
  426. return ret;
  427. }
  428. function isLiteralStart(scnr, context) {
  429. const { currentType } = context;
  430. if (currentType !== 2 /* TokenTypes.BraceLeft */) {
  431. return false;
  432. }
  433. peekSpaces(scnr);
  434. const ret = scnr.currentPeek() === LITERAL_DELIMITER;
  435. scnr.resetPeek();
  436. return ret;
  437. }
  438. function isLinkedDotStart(scnr, context) {
  439. const { currentType } = context;
  440. if (currentType !== 8 /* TokenTypes.LinkedAlias */) {
  441. return false;
  442. }
  443. peekSpaces(scnr);
  444. const ret = scnr.currentPeek() === "." /* TokenChars.LinkedDot */;
  445. scnr.resetPeek();
  446. return ret;
  447. }
  448. function isLinkedModifierStart(scnr, context) {
  449. const { currentType } = context;
  450. if (currentType !== 9 /* TokenTypes.LinkedDot */) {
  451. return false;
  452. }
  453. peekSpaces(scnr);
  454. const ret = isIdentifierStart(scnr.currentPeek());
  455. scnr.resetPeek();
  456. return ret;
  457. }
  458. function isLinkedDelimiterStart(scnr, context) {
  459. const { currentType } = context;
  460. if (!(currentType === 8 /* TokenTypes.LinkedAlias */ ||
  461. currentType === 12 /* TokenTypes.LinkedModifier */)) {
  462. return false;
  463. }
  464. peekSpaces(scnr);
  465. const ret = scnr.currentPeek() === ":" /* TokenChars.LinkedDelimiter */;
  466. scnr.resetPeek();
  467. return ret;
  468. }
  469. function isLinkedReferStart(scnr, context) {
  470. const { currentType } = context;
  471. if (currentType !== 10 /* TokenTypes.LinkedDelimiter */) {
  472. return false;
  473. }
  474. const fn = () => {
  475. const ch = scnr.currentPeek();
  476. if (ch === "{" /* TokenChars.BraceLeft */) {
  477. return isIdentifierStart(scnr.peek());
  478. }
  479. else if (ch === "@" /* TokenChars.LinkedAlias */ ||
  480. ch === "%" /* TokenChars.Modulo */ ||
  481. ch === "|" /* TokenChars.Pipe */ ||
  482. ch === ":" /* TokenChars.LinkedDelimiter */ ||
  483. ch === "." /* TokenChars.LinkedDot */ ||
  484. ch === CHAR_SP ||
  485. !ch) {
  486. return false;
  487. }
  488. else if (ch === CHAR_LF) {
  489. scnr.peek();
  490. return fn();
  491. }
  492. else {
  493. // other characters
  494. return isTextStart(scnr, false);
  495. }
  496. };
  497. const ret = fn();
  498. scnr.resetPeek();
  499. return ret;
  500. }
  501. function isPluralStart(scnr) {
  502. peekSpaces(scnr);
  503. const ret = scnr.currentPeek() === "|" /* TokenChars.Pipe */;
  504. scnr.resetPeek();
  505. return ret;
  506. }
  507. function detectModuloStart(scnr) {
  508. const spaces = peekSpaces(scnr);
  509. const ret = scnr.currentPeek() === "%" /* TokenChars.Modulo */ &&
  510. scnr.peek() === "{" /* TokenChars.BraceLeft */;
  511. scnr.resetPeek();
  512. return {
  513. isModulo: ret,
  514. hasSpace: spaces.length > 0
  515. };
  516. }
  517. function isTextStart(scnr, reset = true) {
  518. const fn = (hasSpace = false, prev = '', detectModulo = false) => {
  519. const ch = scnr.currentPeek();
  520. if (ch === "{" /* TokenChars.BraceLeft */) {
  521. return prev === "%" /* TokenChars.Modulo */ ? false : hasSpace;
  522. }
  523. else if (ch === "@" /* TokenChars.LinkedAlias */ || !ch) {
  524. return prev === "%" /* TokenChars.Modulo */ ? true : hasSpace;
  525. }
  526. else if (ch === "%" /* TokenChars.Modulo */) {
  527. scnr.peek();
  528. return fn(hasSpace, "%" /* TokenChars.Modulo */, true);
  529. }
  530. else if (ch === "|" /* TokenChars.Pipe */) {
  531. return prev === "%" /* TokenChars.Modulo */ || detectModulo
  532. ? true
  533. : !(prev === CHAR_SP || prev === CHAR_LF);
  534. }
  535. else if (ch === CHAR_SP) {
  536. scnr.peek();
  537. return fn(true, CHAR_SP, detectModulo);
  538. }
  539. else if (ch === CHAR_LF) {
  540. scnr.peek();
  541. return fn(true, CHAR_LF, detectModulo);
  542. }
  543. else {
  544. return true;
  545. }
  546. };
  547. const ret = fn();
  548. reset && scnr.resetPeek();
  549. return ret;
  550. }
  551. function takeChar(scnr, fn) {
  552. const ch = scnr.currentChar();
  553. if (ch === EOF) {
  554. return EOF;
  555. }
  556. if (fn(ch)) {
  557. scnr.next();
  558. return ch;
  559. }
  560. return null;
  561. }
  562. function isIdentifier(ch) {
  563. const cc = ch.charCodeAt(0);
  564. return ((cc >= 97 && cc <= 122) || // a-z
  565. (cc >= 65 && cc <= 90) || // A-Z
  566. (cc >= 48 && cc <= 57) || // 0-9
  567. cc === 95 || // _
  568. cc === 36 // $
  569. );
  570. }
  571. function takeIdentifierChar(scnr) {
  572. return takeChar(scnr, isIdentifier);
  573. }
  574. function isNamedIdentifier(ch) {
  575. const cc = ch.charCodeAt(0);
  576. return ((cc >= 97 && cc <= 122) || // a-z
  577. (cc >= 65 && cc <= 90) || // A-Z
  578. (cc >= 48 && cc <= 57) || // 0-9
  579. cc === 95 || // _
  580. cc === 36 || // $
  581. cc === 45 // -
  582. );
  583. }
  584. function takeNamedIdentifierChar(scnr) {
  585. return takeChar(scnr, isNamedIdentifier);
  586. }
  587. function isDigit(ch) {
  588. const cc = ch.charCodeAt(0);
  589. return cc >= 48 && cc <= 57; // 0-9
  590. }
  591. function takeDigit(scnr) {
  592. return takeChar(scnr, isDigit);
  593. }
  594. function isHexDigit(ch) {
  595. const cc = ch.charCodeAt(0);
  596. return ((cc >= 48 && cc <= 57) || // 0-9
  597. (cc >= 65 && cc <= 70) || // A-F
  598. (cc >= 97 && cc <= 102)); // a-f
  599. }
  600. function takeHexDigit(scnr) {
  601. return takeChar(scnr, isHexDigit);
  602. }
  603. function getDigits(scnr) {
  604. let ch = '';
  605. let num = '';
  606. while ((ch = takeDigit(scnr))) {
  607. num += ch;
  608. }
  609. return num;
  610. }
  611. function readModulo(scnr) {
  612. skipSpaces(scnr);
  613. const ch = scnr.currentChar();
  614. if (ch !== "%" /* TokenChars.Modulo */) {
  615. emitError(CompileErrorCodes.EXPECTED_TOKEN, currentPosition(), 0, ch);
  616. }
  617. scnr.next();
  618. return "%" /* TokenChars.Modulo */;
  619. }
  620. function readText(scnr) {
  621. let buf = '';
  622. // eslint-disable-next-line no-constant-condition
  623. while (true) {
  624. const ch = scnr.currentChar();
  625. if (ch === "{" /* TokenChars.BraceLeft */ ||
  626. ch === "}" /* TokenChars.BraceRight */ ||
  627. ch === "@" /* TokenChars.LinkedAlias */ ||
  628. ch === "|" /* TokenChars.Pipe */ ||
  629. !ch) {
  630. break;
  631. }
  632. else if (ch === "%" /* TokenChars.Modulo */) {
  633. if (isTextStart(scnr)) {
  634. buf += ch;
  635. scnr.next();
  636. }
  637. else {
  638. break;
  639. }
  640. }
  641. else if (ch === CHAR_SP || ch === CHAR_LF) {
  642. if (isTextStart(scnr)) {
  643. buf += ch;
  644. scnr.next();
  645. }
  646. else if (isPluralStart(scnr)) {
  647. break;
  648. }
  649. else {
  650. buf += ch;
  651. scnr.next();
  652. }
  653. }
  654. else {
  655. buf += ch;
  656. scnr.next();
  657. }
  658. }
  659. return buf;
  660. }
  661. function readNamedIdentifier(scnr) {
  662. skipSpaces(scnr);
  663. let ch = '';
  664. let name = '';
  665. while ((ch = takeNamedIdentifierChar(scnr))) {
  666. name += ch;
  667. }
  668. if (scnr.currentChar() === EOF) {
  669. emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
  670. }
  671. return name;
  672. }
  673. function readListIdentifier(scnr) {
  674. skipSpaces(scnr);
  675. let value = '';
  676. if (scnr.currentChar() === '-') {
  677. scnr.next();
  678. value += `-${getDigits(scnr)}`;
  679. }
  680. else {
  681. value += getDigits(scnr);
  682. }
  683. if (scnr.currentChar() === EOF) {
  684. emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
  685. }
  686. return value;
  687. }
  688. function isLiteral(ch) {
  689. return ch !== LITERAL_DELIMITER && ch !== CHAR_LF;
  690. }
  691. function readLiteral(scnr) {
  692. skipSpaces(scnr);
  693. // eslint-disable-next-line no-useless-escape
  694. eat(scnr, `\'`);
  695. let ch = '';
  696. let literal = '';
  697. while ((ch = takeChar(scnr, isLiteral))) {
  698. if (ch === '\\') {
  699. literal += readEscapeSequence(scnr);
  700. }
  701. else {
  702. literal += ch;
  703. }
  704. }
  705. const current = scnr.currentChar();
  706. if (current === CHAR_LF || current === EOF) {
  707. emitError(CompileErrorCodes.UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER, currentPosition(), 0);
  708. // TODO: Is it correct really?
  709. if (current === CHAR_LF) {
  710. scnr.next();
  711. // eslint-disable-next-line no-useless-escape
  712. eat(scnr, `\'`);
  713. }
  714. return literal;
  715. }
  716. // eslint-disable-next-line no-useless-escape
  717. eat(scnr, `\'`);
  718. return literal;
  719. }
  720. function readEscapeSequence(scnr) {
  721. const ch = scnr.currentChar();
  722. switch (ch) {
  723. case '\\':
  724. case `\'`: // eslint-disable-line no-useless-escape
  725. scnr.next();
  726. return `\\${ch}`;
  727. case 'u':
  728. return readUnicodeEscapeSequence(scnr, ch, 4);
  729. case 'U':
  730. return readUnicodeEscapeSequence(scnr, ch, 6);
  731. default:
  732. emitError(CompileErrorCodes.UNKNOWN_ESCAPE_SEQUENCE, currentPosition(), 0, ch);
  733. return '';
  734. }
  735. }
  736. function readUnicodeEscapeSequence(scnr, unicode, digits) {
  737. eat(scnr, unicode);
  738. let sequence = '';
  739. for (let i = 0; i < digits; i++) {
  740. const ch = takeHexDigit(scnr);
  741. if (!ch) {
  742. emitError(CompileErrorCodes.INVALID_UNICODE_ESCAPE_SEQUENCE, currentPosition(), 0, `\\${unicode}${sequence}${scnr.currentChar()}`);
  743. break;
  744. }
  745. sequence += ch;
  746. }
  747. return `\\${unicode}${sequence}`;
  748. }
  749. function isInvalidIdentifier(ch) {
  750. return (ch !== "{" /* TokenChars.BraceLeft */ &&
  751. ch !== "}" /* TokenChars.BraceRight */ &&
  752. ch !== CHAR_SP &&
  753. ch !== CHAR_LF);
  754. }
  755. function readInvalidIdentifier(scnr) {
  756. skipSpaces(scnr);
  757. let ch = '';
  758. let identifiers = '';
  759. while ((ch = takeChar(scnr, isInvalidIdentifier))) {
  760. identifiers += ch;
  761. }
  762. return identifiers;
  763. }
  764. function readLinkedModifier(scnr) {
  765. let ch = '';
  766. let name = '';
  767. while ((ch = takeIdentifierChar(scnr))) {
  768. name += ch;
  769. }
  770. return name;
  771. }
  772. function readLinkedRefer(scnr) {
  773. const fn = (buf) => {
  774. const ch = scnr.currentChar();
  775. if (ch === "{" /* TokenChars.BraceLeft */ ||
  776. ch === "%" /* TokenChars.Modulo */ ||
  777. ch === "@" /* TokenChars.LinkedAlias */ ||
  778. ch === "|" /* TokenChars.Pipe */ ||
  779. ch === "(" /* TokenChars.ParenLeft */ ||
  780. ch === ")" /* TokenChars.ParenRight */ ||
  781. !ch) {
  782. return buf;
  783. }
  784. else if (ch === CHAR_SP) {
  785. return buf;
  786. }
  787. else if (ch === CHAR_LF || ch === DOT) {
  788. buf += ch;
  789. scnr.next();
  790. return fn(buf);
  791. }
  792. else {
  793. buf += ch;
  794. scnr.next();
  795. return fn(buf);
  796. }
  797. };
  798. return fn('');
  799. }
  800. function readPlural(scnr) {
  801. skipSpaces(scnr);
  802. const plural = eat(scnr, "|" /* TokenChars.Pipe */);
  803. skipSpaces(scnr);
  804. return plural;
  805. }
  806. // TODO: We need refactoring of token parsing ...
  807. function readTokenInPlaceholder(scnr, context) {
  808. let token = null;
  809. const ch = scnr.currentChar();
  810. switch (ch) {
  811. case "{" /* TokenChars.BraceLeft */:
  812. if (context.braceNest >= 1) {
  813. emitError(CompileErrorCodes.NOT_ALLOW_NEST_PLACEHOLDER, currentPosition(), 0);
  814. }
  815. scnr.next();
  816. token = getToken(context, 2 /* TokenTypes.BraceLeft */, "{" /* TokenChars.BraceLeft */);
  817. skipSpaces(scnr);
  818. context.braceNest++;
  819. return token;
  820. case "}" /* TokenChars.BraceRight */:
  821. if (context.braceNest > 0 &&
  822. context.currentType === 2 /* TokenTypes.BraceLeft */) {
  823. emitError(CompileErrorCodes.EMPTY_PLACEHOLDER, currentPosition(), 0);
  824. }
  825. scnr.next();
  826. token = getToken(context, 3 /* TokenTypes.BraceRight */, "}" /* TokenChars.BraceRight */);
  827. context.braceNest--;
  828. context.braceNest > 0 && skipSpaces(scnr);
  829. if (context.inLinked && context.braceNest === 0) {
  830. context.inLinked = false;
  831. }
  832. return token;
  833. case "@" /* TokenChars.LinkedAlias */:
  834. if (context.braceNest > 0) {
  835. emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
  836. }
  837. token = readTokenInLinked(scnr, context) || getEndToken(context);
  838. context.braceNest = 0;
  839. return token;
  840. default: {
  841. let validNamedIdentifier = true;
  842. let validListIdentifier = true;
  843. let validLiteral = true;
  844. if (isPluralStart(scnr)) {
  845. if (context.braceNest > 0) {
  846. emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
  847. }
  848. token = getToken(context, 1 /* TokenTypes.Pipe */, readPlural(scnr));
  849. // reset
  850. context.braceNest = 0;
  851. context.inLinked = false;
  852. return token;
  853. }
  854. if (context.braceNest > 0 &&
  855. (context.currentType === 5 /* TokenTypes.Named */ ||
  856. context.currentType === 6 /* TokenTypes.List */ ||
  857. context.currentType === 7 /* TokenTypes.Literal */)) {
  858. emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
  859. context.braceNest = 0;
  860. return readToken(scnr, context);
  861. }
  862. if ((validNamedIdentifier = isNamedIdentifierStart(scnr, context))) {
  863. token = getToken(context, 5 /* TokenTypes.Named */, readNamedIdentifier(scnr));
  864. skipSpaces(scnr);
  865. return token;
  866. }
  867. if ((validListIdentifier = isListIdentifierStart(scnr, context))) {
  868. token = getToken(context, 6 /* TokenTypes.List */, readListIdentifier(scnr));
  869. skipSpaces(scnr);
  870. return token;
  871. }
  872. if ((validLiteral = isLiteralStart(scnr, context))) {
  873. token = getToken(context, 7 /* TokenTypes.Literal */, readLiteral(scnr));
  874. skipSpaces(scnr);
  875. return token;
  876. }
  877. if (!validNamedIdentifier && !validListIdentifier && !validLiteral) {
  878. // TODO: we should be re-designed invalid cases, when we will extend message syntax near the future ...
  879. token = getToken(context, 13 /* TokenTypes.InvalidPlace */, readInvalidIdentifier(scnr));
  880. emitError(CompileErrorCodes.INVALID_TOKEN_IN_PLACEHOLDER, currentPosition(), 0, token.value);
  881. skipSpaces(scnr);
  882. return token;
  883. }
  884. break;
  885. }
  886. }
  887. return token;
  888. }
  889. // TODO: We need refactoring of token parsing ...
  890. function readTokenInLinked(scnr, context) {
  891. const { currentType } = context;
  892. let token = null;
  893. const ch = scnr.currentChar();
  894. if ((currentType === 8 /* TokenTypes.LinkedAlias */ ||
  895. currentType === 9 /* TokenTypes.LinkedDot */ ||
  896. currentType === 12 /* TokenTypes.LinkedModifier */ ||
  897. currentType === 10 /* TokenTypes.LinkedDelimiter */) &&
  898. (ch === CHAR_LF || ch === CHAR_SP)) {
  899. emitError(CompileErrorCodes.INVALID_LINKED_FORMAT, currentPosition(), 0);
  900. }
  901. switch (ch) {
  902. case "@" /* TokenChars.LinkedAlias */:
  903. scnr.next();
  904. token = getToken(context, 8 /* TokenTypes.LinkedAlias */, "@" /* TokenChars.LinkedAlias */);
  905. context.inLinked = true;
  906. return token;
  907. case "." /* TokenChars.LinkedDot */:
  908. skipSpaces(scnr);
  909. scnr.next();
  910. return getToken(context, 9 /* TokenTypes.LinkedDot */, "." /* TokenChars.LinkedDot */);
  911. case ":" /* TokenChars.LinkedDelimiter */:
  912. skipSpaces(scnr);
  913. scnr.next();
  914. return getToken(context, 10 /* TokenTypes.LinkedDelimiter */, ":" /* TokenChars.LinkedDelimiter */);
  915. default:
  916. if (isPluralStart(scnr)) {
  917. token = getToken(context, 1 /* TokenTypes.Pipe */, readPlural(scnr));
  918. // reset
  919. context.braceNest = 0;
  920. context.inLinked = false;
  921. return token;
  922. }
  923. if (isLinkedDotStart(scnr, context) ||
  924. isLinkedDelimiterStart(scnr, context)) {
  925. skipSpaces(scnr);
  926. return readTokenInLinked(scnr, context);
  927. }
  928. if (isLinkedModifierStart(scnr, context)) {
  929. skipSpaces(scnr);
  930. return getToken(context, 12 /* TokenTypes.LinkedModifier */, readLinkedModifier(scnr));
  931. }
  932. if (isLinkedReferStart(scnr, context)) {
  933. skipSpaces(scnr);
  934. if (ch === "{" /* TokenChars.BraceLeft */) {
  935. // scan the placeholder
  936. return readTokenInPlaceholder(scnr, context) || token;
  937. }
  938. else {
  939. return getToken(context, 11 /* TokenTypes.LinkedKey */, readLinkedRefer(scnr));
  940. }
  941. }
  942. if (currentType === 8 /* TokenTypes.LinkedAlias */) {
  943. emitError(CompileErrorCodes.INVALID_LINKED_FORMAT, currentPosition(), 0);
  944. }
  945. context.braceNest = 0;
  946. context.inLinked = false;
  947. return readToken(scnr, context);
  948. }
  949. }
  950. // TODO: We need refactoring of token parsing ...
  951. function readToken(scnr, context) {
  952. let token = { type: 14 /* TokenTypes.EOF */ };
  953. if (context.braceNest > 0) {
  954. return readTokenInPlaceholder(scnr, context) || getEndToken(context);
  955. }
  956. if (context.inLinked) {
  957. return readTokenInLinked(scnr, context) || getEndToken(context);
  958. }
  959. const ch = scnr.currentChar();
  960. switch (ch) {
  961. case "{" /* TokenChars.BraceLeft */:
  962. return readTokenInPlaceholder(scnr, context) || getEndToken(context);
  963. case "}" /* TokenChars.BraceRight */:
  964. emitError(CompileErrorCodes.UNBALANCED_CLOSING_BRACE, currentPosition(), 0);
  965. scnr.next();
  966. return getToken(context, 3 /* TokenTypes.BraceRight */, "}" /* TokenChars.BraceRight */);
  967. case "@" /* TokenChars.LinkedAlias */:
  968. return readTokenInLinked(scnr, context) || getEndToken(context);
  969. default: {
  970. if (isPluralStart(scnr)) {
  971. token = getToken(context, 1 /* TokenTypes.Pipe */, readPlural(scnr));
  972. // reset
  973. context.braceNest = 0;
  974. context.inLinked = false;
  975. return token;
  976. }
  977. const { isModulo, hasSpace } = detectModuloStart(scnr);
  978. if (isModulo) {
  979. return hasSpace
  980. ? getToken(context, 0 /* TokenTypes.Text */, readText(scnr))
  981. : getToken(context, 4 /* TokenTypes.Modulo */, readModulo(scnr));
  982. }
  983. if (isTextStart(scnr)) {
  984. return getToken(context, 0 /* TokenTypes.Text */, readText(scnr));
  985. }
  986. break;
  987. }
  988. }
  989. return token;
  990. }
  991. function nextToken() {
  992. const { currentType, offset, startLoc, endLoc } = _context;
  993. _context.lastType = currentType;
  994. _context.lastOffset = offset;
  995. _context.lastStartLoc = startLoc;
  996. _context.lastEndLoc = endLoc;
  997. _context.offset = currentOffset();
  998. _context.startLoc = currentPosition();
  999. if (_scnr.currentChar() === EOF) {
  1000. return getToken(_context, 14 /* TokenTypes.EOF */);
  1001. }
  1002. return readToken(_scnr, _context);
  1003. }
  1004. return {
  1005. nextToken,
  1006. currentOffset,
  1007. currentPosition,
  1008. context
  1009. };
  1010. }
  1011. const ERROR_DOMAIN$2 = 'parser';
  1012. // Backslash backslash, backslash quote, uHHHH, UHHHHHH.
  1013. const KNOWN_ESCAPES = /(?:\\\\|\\'|\\u([0-9a-fA-F]{4})|\\U([0-9a-fA-F]{6}))/g;
  1014. function fromEscapeSequence(match, codePoint4, codePoint6) {
  1015. switch (match) {
  1016. case `\\\\`:
  1017. return `\\`;
  1018. // eslint-disable-next-line no-useless-escape
  1019. case `\\\'`:
  1020. // eslint-disable-next-line no-useless-escape
  1021. return `\'`;
  1022. default: {
  1023. const codePoint = parseInt(codePoint4 || codePoint6, 16);
  1024. if (codePoint <= 0xd7ff || codePoint >= 0xe000) {
  1025. return String.fromCodePoint(codePoint);
  1026. }
  1027. // invalid ...
  1028. // Replace them with U+FFFD REPLACEMENT CHARACTER.
  1029. return '�';
  1030. }
  1031. }
  1032. }
  1033. function createParser(options = {}) {
  1034. const location = options.location !== false;
  1035. const { onError, onWarn } = options;
  1036. function emitError(tokenzer, code, start, offset, ...args) {
  1037. const end = tokenzer.currentPosition();
  1038. end.offset += offset;
  1039. end.column += offset;
  1040. if (onError) {
  1041. const loc = location ? createLocation(start, end) : null;
  1042. const err = createCompileError(code, loc, {
  1043. domain: ERROR_DOMAIN$2,
  1044. args
  1045. });
  1046. onError(err);
  1047. }
  1048. }
  1049. function emitWarn(tokenzer, code, start, offset, ...args) {
  1050. const end = tokenzer.currentPosition();
  1051. end.offset += offset;
  1052. end.column += offset;
  1053. if (onWarn) {
  1054. const loc = location ? createLocation(start, end) : null;
  1055. onWarn(createCompileWarn(code, loc, args));
  1056. }
  1057. }
  1058. function startNode(type, offset, loc) {
  1059. const node = { type };
  1060. if (location) {
  1061. node.start = offset;
  1062. node.end = offset;
  1063. node.loc = { start: loc, end: loc };
  1064. }
  1065. return node;
  1066. }
  1067. function endNode(node, offset, pos, type) {
  1068. if (type) {
  1069. node.type = type;
  1070. }
  1071. if (location) {
  1072. node.end = offset;
  1073. if (node.loc) {
  1074. node.loc.end = pos;
  1075. }
  1076. }
  1077. }
  1078. function parseText(tokenizer, value) {
  1079. const context = tokenizer.context();
  1080. const node = startNode(3 /* NodeTypes.Text */, context.offset, context.startLoc);
  1081. node.value = value;
  1082. endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
  1083. return node;
  1084. }
  1085. function parseList(tokenizer, index) {
  1086. const context = tokenizer.context();
  1087. const { lastOffset: offset, lastStartLoc: loc } = context; // get brace left loc
  1088. const node = startNode(5 /* NodeTypes.List */, offset, loc);
  1089. node.index = parseInt(index, 10);
  1090. tokenizer.nextToken(); // skip brach right
  1091. endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
  1092. return node;
  1093. }
  1094. function parseNamed(tokenizer, key, modulo) {
  1095. const context = tokenizer.context();
  1096. const { lastOffset: offset, lastStartLoc: loc } = context; // get brace left loc
  1097. const node = startNode(4 /* NodeTypes.Named */, offset, loc);
  1098. node.key = key;
  1099. if (modulo === true) {
  1100. node.modulo = true;
  1101. }
  1102. tokenizer.nextToken(); // skip brach right
  1103. endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
  1104. return node;
  1105. }
  1106. function parseLiteral(tokenizer, value) {
  1107. const context = tokenizer.context();
  1108. const { lastOffset: offset, lastStartLoc: loc } = context; // get brace left loc
  1109. const node = startNode(9 /* NodeTypes.Literal */, offset, loc);
  1110. node.value = value.replace(KNOWN_ESCAPES, fromEscapeSequence);
  1111. tokenizer.nextToken(); // skip brach right
  1112. endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
  1113. return node;
  1114. }
  1115. function parseLinkedModifier(tokenizer) {
  1116. const token = tokenizer.nextToken();
  1117. const context = tokenizer.context();
  1118. const { lastOffset: offset, lastStartLoc: loc } = context; // get linked dot loc
  1119. const node = startNode(8 /* NodeTypes.LinkedModifier */, offset, loc);
  1120. if (token.type !== 12 /* TokenTypes.LinkedModifier */) {
  1121. // empty modifier
  1122. emitError(tokenizer, CompileErrorCodes.UNEXPECTED_EMPTY_LINKED_MODIFIER, context.lastStartLoc, 0);
  1123. node.value = '';
  1124. endNode(node, offset, loc);
  1125. return {
  1126. nextConsumeToken: token,
  1127. node
  1128. };
  1129. }
  1130. // check token
  1131. if (token.value == null) {
  1132. emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
  1133. }
  1134. node.value = token.value || '';
  1135. endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
  1136. return {
  1137. node
  1138. };
  1139. }
  1140. function parseLinkedKey(tokenizer, value) {
  1141. const context = tokenizer.context();
  1142. const node = startNode(7 /* NodeTypes.LinkedKey */, context.offset, context.startLoc);
  1143. node.value = value;
  1144. endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
  1145. return node;
  1146. }
  1147. function parseLinked(tokenizer) {
  1148. const context = tokenizer.context();
  1149. const linkedNode = startNode(6 /* NodeTypes.Linked */, context.offset, context.startLoc);
  1150. let token = tokenizer.nextToken();
  1151. if (token.type === 9 /* TokenTypes.LinkedDot */) {
  1152. const parsed = parseLinkedModifier(tokenizer);
  1153. linkedNode.modifier = parsed.node;
  1154. token = parsed.nextConsumeToken || tokenizer.nextToken();
  1155. }
  1156. // asset check token
  1157. if (token.type !== 10 /* TokenTypes.LinkedDelimiter */) {
  1158. emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
  1159. }
  1160. token = tokenizer.nextToken();
  1161. // skip brace left
  1162. if (token.type === 2 /* TokenTypes.BraceLeft */) {
  1163. token = tokenizer.nextToken();
  1164. }
  1165. switch (token.type) {
  1166. case 11 /* TokenTypes.LinkedKey */:
  1167. if (token.value == null) {
  1168. emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
  1169. }
  1170. linkedNode.key = parseLinkedKey(tokenizer, token.value || '');
  1171. break;
  1172. case 5 /* TokenTypes.Named */:
  1173. if (token.value == null) {
  1174. emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
  1175. }
  1176. linkedNode.key = parseNamed(tokenizer, token.value || '');
  1177. break;
  1178. case 6 /* TokenTypes.List */:
  1179. if (token.value == null) {
  1180. emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
  1181. }
  1182. linkedNode.key = parseList(tokenizer, token.value || '');
  1183. break;
  1184. case 7 /* TokenTypes.Literal */:
  1185. if (token.value == null) {
  1186. emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
  1187. }
  1188. linkedNode.key = parseLiteral(tokenizer, token.value || '');
  1189. break;
  1190. default: {
  1191. // empty key
  1192. emitError(tokenizer, CompileErrorCodes.UNEXPECTED_EMPTY_LINKED_KEY, context.lastStartLoc, 0);
  1193. const nextContext = tokenizer.context();
  1194. const emptyLinkedKeyNode = startNode(7 /* NodeTypes.LinkedKey */, nextContext.offset, nextContext.startLoc);
  1195. emptyLinkedKeyNode.value = '';
  1196. endNode(emptyLinkedKeyNode, nextContext.offset, nextContext.startLoc);
  1197. linkedNode.key = emptyLinkedKeyNode;
  1198. endNode(linkedNode, nextContext.offset, nextContext.startLoc);
  1199. return {
  1200. nextConsumeToken: token,
  1201. node: linkedNode
  1202. };
  1203. }
  1204. }
  1205. endNode(linkedNode, tokenizer.currentOffset(), tokenizer.currentPosition());
  1206. return {
  1207. node: linkedNode
  1208. };
  1209. }
  1210. function parseMessage(tokenizer) {
  1211. const context = tokenizer.context();
  1212. const startOffset = context.currentType === 1 /* TokenTypes.Pipe */
  1213. ? tokenizer.currentOffset()
  1214. : context.offset;
  1215. const startLoc = context.currentType === 1 /* TokenTypes.Pipe */
  1216. ? context.endLoc
  1217. : context.startLoc;
  1218. const node = startNode(2 /* NodeTypes.Message */, startOffset, startLoc);
  1219. node.items = [];
  1220. let nextToken = null;
  1221. let modulo = null;
  1222. do {
  1223. const token = nextToken || tokenizer.nextToken();
  1224. nextToken = null;
  1225. switch (token.type) {
  1226. case 0 /* TokenTypes.Text */:
  1227. if (token.value == null) {
  1228. emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
  1229. }
  1230. node.items.push(parseText(tokenizer, token.value || ''));
  1231. break;
  1232. case 6 /* TokenTypes.List */:
  1233. if (token.value == null) {
  1234. emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
  1235. }
  1236. node.items.push(parseList(tokenizer, token.value || ''));
  1237. break;
  1238. case 4 /* TokenTypes.Modulo */:
  1239. modulo = true;
  1240. break;
  1241. case 5 /* TokenTypes.Named */:
  1242. if (token.value == null) {
  1243. emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
  1244. }
  1245. node.items.push(parseNamed(tokenizer, token.value || '', !!modulo));
  1246. if (modulo) {
  1247. emitWarn(tokenizer, CompileWarnCodes.USE_MODULO_SYNTAX, context.lastStartLoc, 0, getTokenCaption(token));
  1248. modulo = null;
  1249. }
  1250. break;
  1251. case 7 /* TokenTypes.Literal */:
  1252. if (token.value == null) {
  1253. emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
  1254. }
  1255. node.items.push(parseLiteral(tokenizer, token.value || ''));
  1256. break;
  1257. case 8 /* TokenTypes.LinkedAlias */: {
  1258. const parsed = parseLinked(tokenizer);
  1259. node.items.push(parsed.node);
  1260. nextToken = parsed.nextConsumeToken || null;
  1261. break;
  1262. }
  1263. }
  1264. } while (context.currentType !== 14 /* TokenTypes.EOF */ &&
  1265. context.currentType !== 1 /* TokenTypes.Pipe */);
  1266. // adjust message node loc
  1267. const endOffset = context.currentType === 1 /* TokenTypes.Pipe */
  1268. ? context.lastOffset
  1269. : tokenizer.currentOffset();
  1270. const endLoc = context.currentType === 1 /* TokenTypes.Pipe */
  1271. ? context.lastEndLoc
  1272. : tokenizer.currentPosition();
  1273. endNode(node, endOffset, endLoc);
  1274. return node;
  1275. }
  1276. function parsePlural(tokenizer, offset, loc, msgNode) {
  1277. const context = tokenizer.context();
  1278. let hasEmptyMessage = msgNode.items.length === 0;
  1279. const node = startNode(1 /* NodeTypes.Plural */, offset, loc);
  1280. node.cases = [];
  1281. node.cases.push(msgNode);
  1282. do {
  1283. const msg = parseMessage(tokenizer);
  1284. if (!hasEmptyMessage) {
  1285. hasEmptyMessage = msg.items.length === 0;
  1286. }
  1287. node.cases.push(msg);
  1288. } while (context.currentType !== 14 /* TokenTypes.EOF */);
  1289. if (hasEmptyMessage) {
  1290. emitError(tokenizer, CompileErrorCodes.MUST_HAVE_MESSAGES_IN_PLURAL, loc, 0);
  1291. }
  1292. endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
  1293. return node;
  1294. }
  1295. function parseResource(tokenizer) {
  1296. const context = tokenizer.context();
  1297. const { offset, startLoc } = context;
  1298. const msgNode = parseMessage(tokenizer);
  1299. if (context.currentType === 14 /* TokenTypes.EOF */) {
  1300. return msgNode;
  1301. }
  1302. else {
  1303. return parsePlural(tokenizer, offset, startLoc, msgNode);
  1304. }
  1305. }
  1306. function parse(source) {
  1307. const tokenizer = createTokenizer(source, assign({}, options));
  1308. const context = tokenizer.context();
  1309. const node = startNode(0 /* NodeTypes.Resource */, context.offset, context.startLoc);
  1310. if (location && node.loc) {
  1311. node.loc.source = source;
  1312. }
  1313. node.body = parseResource(tokenizer);
  1314. if (options.onCacheKey) {
  1315. node.cacheKey = options.onCacheKey(source);
  1316. }
  1317. // assert whether achieved to EOF
  1318. if (context.currentType !== 14 /* TokenTypes.EOF */) {
  1319. emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, source[context.offset] || '');
  1320. }
  1321. endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
  1322. return node;
  1323. }
  1324. return { parse };
  1325. }
  1326. function getTokenCaption(token) {
  1327. if (token.type === 14 /* TokenTypes.EOF */) {
  1328. return 'EOF';
  1329. }
  1330. const name = (token.value || '').replace(/\r?\n/gu, '\\n');
  1331. return name.length > 10 ? name.slice(0, 9) + '…' : name;
  1332. }
  1333. function createTransformer(ast, options = {} // eslint-disable-line
  1334. ) {
  1335. const _context = {
  1336. ast,
  1337. helpers: new Set()
  1338. };
  1339. const context = () => _context;
  1340. const helper = (name) => {
  1341. _context.helpers.add(name);
  1342. return name;
  1343. };
  1344. return { context, helper };
  1345. }
  1346. function traverseNodes(nodes, transformer) {
  1347. for (let i = 0; i < nodes.length; i++) {
  1348. traverseNode(nodes[i], transformer);
  1349. }
  1350. }
  1351. function traverseNode(node, transformer) {
  1352. // TODO: if we need pre-hook of transform, should be implemented to here
  1353. switch (node.type) {
  1354. case 1 /* NodeTypes.Plural */:
  1355. traverseNodes(node.cases, transformer);
  1356. transformer.helper("plural" /* HelperNameMap.PLURAL */);
  1357. break;
  1358. case 2 /* NodeTypes.Message */:
  1359. traverseNodes(node.items, transformer);
  1360. break;
  1361. case 6 /* NodeTypes.Linked */: {
  1362. const linked = node;
  1363. traverseNode(linked.key, transformer);
  1364. transformer.helper("linked" /* HelperNameMap.LINKED */);
  1365. transformer.helper("type" /* HelperNameMap.TYPE */);
  1366. break;
  1367. }
  1368. case 5 /* NodeTypes.List */:
  1369. transformer.helper("interpolate" /* HelperNameMap.INTERPOLATE */);
  1370. transformer.helper("list" /* HelperNameMap.LIST */);
  1371. break;
  1372. case 4 /* NodeTypes.Named */:
  1373. transformer.helper("interpolate" /* HelperNameMap.INTERPOLATE */);
  1374. transformer.helper("named" /* HelperNameMap.NAMED */);
  1375. break;
  1376. }
  1377. // TODO: if we need post-hook of transform, should be implemented to here
  1378. }
  1379. // transform AST
  1380. function transform(ast, options = {} // eslint-disable-line
  1381. ) {
  1382. const transformer = createTransformer(ast);
  1383. transformer.helper("normalize" /* HelperNameMap.NORMALIZE */);
  1384. // traverse
  1385. ast.body && traverseNode(ast.body, transformer);
  1386. // set meta information
  1387. const context = transformer.context();
  1388. ast.helpers = Array.from(context.helpers);
  1389. }
  1390. function optimize(ast) {
  1391. const body = ast.body;
  1392. if (body.type === 2 /* NodeTypes.Message */) {
  1393. optimizeMessageNode(body);
  1394. }
  1395. else {
  1396. body.cases.forEach(c => optimizeMessageNode(c));
  1397. }
  1398. return ast;
  1399. }
  1400. function optimizeMessageNode(message) {
  1401. if (message.items.length === 1) {
  1402. const item = message.items[0];
  1403. if (item.type === 3 /* NodeTypes.Text */ || item.type === 9 /* NodeTypes.Literal */) {
  1404. message.static = item.value;
  1405. delete item.value; // optimization for size
  1406. }
  1407. }
  1408. else {
  1409. const values = [];
  1410. for (let i = 0; i < message.items.length; i++) {
  1411. const item = message.items[i];
  1412. if (!(item.type === 3 /* NodeTypes.Text */ || item.type === 9 /* NodeTypes.Literal */)) {
  1413. break;
  1414. }
  1415. if (item.value == null) {
  1416. break;
  1417. }
  1418. values.push(item.value);
  1419. }
  1420. if (values.length === message.items.length) {
  1421. message.static = join(values);
  1422. for (let i = 0; i < message.items.length; i++) {
  1423. const item = message.items[i];
  1424. if (item.type === 3 /* NodeTypes.Text */ || item.type === 9 /* NodeTypes.Literal */) {
  1425. delete item.value; // optimization for size
  1426. }
  1427. }
  1428. }
  1429. }
  1430. }
  1431. const ERROR_DOMAIN$1 = 'minifier';
  1432. /* eslint-disable @typescript-eslint/no-explicit-any */
  1433. function minify(node) {
  1434. node.t = node.type;
  1435. switch (node.type) {
  1436. case 0 /* NodeTypes.Resource */: {
  1437. const resource = node;
  1438. minify(resource.body);
  1439. resource.b = resource.body;
  1440. delete resource.body;
  1441. break;
  1442. }
  1443. case 1 /* NodeTypes.Plural */: {
  1444. const plural = node;
  1445. const cases = plural.cases;
  1446. for (let i = 0; i < cases.length; i++) {
  1447. minify(cases[i]);
  1448. }
  1449. plural.c = cases;
  1450. delete plural.cases;
  1451. break;
  1452. }
  1453. case 2 /* NodeTypes.Message */: {
  1454. const message = node;
  1455. const items = message.items;
  1456. for (let i = 0; i < items.length; i++) {
  1457. minify(items[i]);
  1458. }
  1459. message.i = items;
  1460. delete message.items;
  1461. if (message.static) {
  1462. message.s = message.static;
  1463. delete message.static;
  1464. }
  1465. break;
  1466. }
  1467. case 3 /* NodeTypes.Text */:
  1468. case 9 /* NodeTypes.Literal */:
  1469. case 8 /* NodeTypes.LinkedModifier */:
  1470. case 7 /* NodeTypes.LinkedKey */: {
  1471. const valueNode = node;
  1472. if (valueNode.value) {
  1473. valueNode.v = valueNode.value;
  1474. delete valueNode.value;
  1475. }
  1476. break;
  1477. }
  1478. case 6 /* NodeTypes.Linked */: {
  1479. const linked = node;
  1480. minify(linked.key);
  1481. linked.k = linked.key;
  1482. delete linked.key;
  1483. if (linked.modifier) {
  1484. minify(linked.modifier);
  1485. linked.m = linked.modifier;
  1486. delete linked.modifier;
  1487. }
  1488. break;
  1489. }
  1490. case 5 /* NodeTypes.List */: {
  1491. const list = node;
  1492. list.i = list.index;
  1493. delete list.index;
  1494. break;
  1495. }
  1496. case 4 /* NodeTypes.Named */: {
  1497. const named = node;
  1498. named.k = named.key;
  1499. delete named.key;
  1500. break;
  1501. }
  1502. default:
  1503. {
  1504. throw createCompileError(CompileErrorCodes.UNHANDLED_MINIFIER_NODE_TYPE, null, {
  1505. domain: ERROR_DOMAIN$1,
  1506. args: [node.type]
  1507. });
  1508. }
  1509. }
  1510. delete node.type;
  1511. }
  1512. /* eslint-enable @typescript-eslint/no-explicit-any */
  1513. // eslint-disable-next-line @typescript-eslint/triple-slash-reference
  1514. /// <reference types="source-map-js" />
  1515. const ERROR_DOMAIN = 'parser';
  1516. function createCodeGenerator(ast, options) {
  1517. const { sourceMap, filename, breakLineCode, needIndent: _needIndent } = options;
  1518. const location = options.location !== false;
  1519. const _context = {
  1520. filename,
  1521. code: '',
  1522. column: 1,
  1523. line: 1,
  1524. offset: 0,
  1525. map: undefined,
  1526. breakLineCode,
  1527. needIndent: _needIndent,
  1528. indentLevel: 0
  1529. };
  1530. if (location && ast.loc) {
  1531. _context.source = ast.loc.source;
  1532. }
  1533. const context = () => _context;
  1534. function push(code, node) {
  1535. _context.code += code;
  1536. }
  1537. function _newline(n, withBreakLine = true) {
  1538. const _breakLineCode = withBreakLine ? breakLineCode : '';
  1539. push(_needIndent ? _breakLineCode + ` `.repeat(n) : _breakLineCode);
  1540. }
  1541. function indent(withNewLine = true) {
  1542. const level = ++_context.indentLevel;
  1543. withNewLine && _newline(level);
  1544. }
  1545. function deindent(withNewLine = true) {
  1546. const level = --_context.indentLevel;
  1547. withNewLine && _newline(level);
  1548. }
  1549. function newline() {
  1550. _newline(_context.indentLevel);
  1551. }
  1552. const helper = (key) => `_${key}`;
  1553. const needIndent = () => _context.needIndent;
  1554. return {
  1555. context,
  1556. push,
  1557. indent,
  1558. deindent,
  1559. newline,
  1560. helper,
  1561. needIndent
  1562. };
  1563. }
  1564. function generateLinkedNode(generator, node) {
  1565. const { helper } = generator;
  1566. generator.push(`${helper("linked" /* HelperNameMap.LINKED */)}(`);
  1567. generateNode(generator, node.key);
  1568. if (node.modifier) {
  1569. generator.push(`, `);
  1570. generateNode(generator, node.modifier);
  1571. generator.push(`, _type`);
  1572. }
  1573. else {
  1574. generator.push(`, undefined, _type`);
  1575. }
  1576. generator.push(`)`);
  1577. }
  1578. function generateMessageNode(generator, node) {
  1579. const { helper, needIndent } = generator;
  1580. generator.push(`${helper("normalize" /* HelperNameMap.NORMALIZE */)}([`);
  1581. generator.indent(needIndent());
  1582. const length = node.items.length;
  1583. for (let i = 0; i < length; i++) {
  1584. generateNode(generator, node.items[i]);
  1585. if (i === length - 1) {
  1586. break;
  1587. }
  1588. generator.push(', ');
  1589. }
  1590. generator.deindent(needIndent());
  1591. generator.push('])');
  1592. }
  1593. function generatePluralNode(generator, node) {
  1594. const { helper, needIndent } = generator;
  1595. if (node.cases.length > 1) {
  1596. generator.push(`${helper("plural" /* HelperNameMap.PLURAL */)}([`);
  1597. generator.indent(needIndent());
  1598. const length = node.cases.length;
  1599. for (let i = 0; i < length; i++) {
  1600. generateNode(generator, node.cases[i]);
  1601. if (i === length - 1) {
  1602. break;
  1603. }
  1604. generator.push(', ');
  1605. }
  1606. generator.deindent(needIndent());
  1607. generator.push(`])`);
  1608. }
  1609. }
  1610. function generateResource(generator, node) {
  1611. if (node.body) {
  1612. generateNode(generator, node.body);
  1613. }
  1614. else {
  1615. generator.push('null');
  1616. }
  1617. }
  1618. function generateNode(generator, node) {
  1619. const { helper } = generator;
  1620. switch (node.type) {
  1621. case 0 /* NodeTypes.Resource */:
  1622. generateResource(generator, node);
  1623. break;
  1624. case 1 /* NodeTypes.Plural */:
  1625. generatePluralNode(generator, node);
  1626. break;
  1627. case 2 /* NodeTypes.Message */:
  1628. generateMessageNode(generator, node);
  1629. break;
  1630. case 6 /* NodeTypes.Linked */:
  1631. generateLinkedNode(generator, node);
  1632. break;
  1633. case 8 /* NodeTypes.LinkedModifier */:
  1634. generator.push(JSON.stringify(node.value), node);
  1635. break;
  1636. case 7 /* NodeTypes.LinkedKey */:
  1637. generator.push(JSON.stringify(node.value), node);
  1638. break;
  1639. case 5 /* NodeTypes.List */:
  1640. generator.push(`${helper("interpolate" /* HelperNameMap.INTERPOLATE */)}(${helper("list" /* HelperNameMap.LIST */)}(${node.index}))`, node);
  1641. break;
  1642. case 4 /* NodeTypes.Named */:
  1643. generator.push(`${helper("interpolate" /* HelperNameMap.INTERPOLATE */)}(${helper("named" /* HelperNameMap.NAMED */)}(${JSON.stringify(node.key)}))`, node);
  1644. break;
  1645. case 9 /* NodeTypes.Literal */:
  1646. generator.push(JSON.stringify(node.value), node);
  1647. break;
  1648. case 3 /* NodeTypes.Text */:
  1649. generator.push(JSON.stringify(node.value), node);
  1650. break;
  1651. default:
  1652. {
  1653. throw createCompileError(CompileErrorCodes.UNHANDLED_CODEGEN_NODE_TYPE, null, {
  1654. domain: ERROR_DOMAIN,
  1655. args: [node.type]
  1656. });
  1657. }
  1658. }
  1659. }
  1660. // generate code from AST
  1661. const generate = (ast, options = {} // eslint-disable-line
  1662. ) => {
  1663. const mode = isString(options.mode) ? options.mode : 'normal';
  1664. const filename = isString(options.filename)
  1665. ? options.filename
  1666. : 'message.intl';
  1667. const sourceMap = !!options.sourceMap;
  1668. // prettier-ignore
  1669. const breakLineCode = options.breakLineCode != null
  1670. ? options.breakLineCode
  1671. : mode === 'arrow'
  1672. ? ';'
  1673. : '\n';
  1674. const needIndent = options.needIndent ? options.needIndent : mode !== 'arrow';
  1675. const helpers = ast.helpers || [];
  1676. const generator = createCodeGenerator(ast, {
  1677. mode,
  1678. filename,
  1679. sourceMap,
  1680. breakLineCode,
  1681. needIndent
  1682. });
  1683. generator.push(mode === 'normal' ? `function __msg__ (ctx) {` : `(ctx) => {`);
  1684. generator.indent(needIndent);
  1685. if (helpers.length > 0) {
  1686. generator.push(`const { ${join(helpers.map(s => `${s}: _${s}`), ', ')} } = ctx`);
  1687. generator.newline();
  1688. }
  1689. generator.push(`return `);
  1690. generateNode(generator, ast);
  1691. generator.deindent(needIndent);
  1692. generator.push(`}`);
  1693. delete ast.helpers;
  1694. const { code, map } = generator.context();
  1695. return {
  1696. ast,
  1697. code,
  1698. map: map ? map.toJSON() : undefined // eslint-disable-line @typescript-eslint/no-explicit-any
  1699. };
  1700. };
  1701. function baseCompile$1(source, options = {}) {
  1702. const assignedOptions = assign({}, options);
  1703. const jit = !!assignedOptions.jit;
  1704. const enalbeMinify = !!assignedOptions.minify;
  1705. const enambeOptimize = assignedOptions.optimize == null ? true : assignedOptions.optimize;
  1706. // parse source codes
  1707. const parser = createParser(assignedOptions);
  1708. const ast = parser.parse(source);
  1709. if (!jit) {
  1710. // transform ASTs
  1711. transform(ast, assignedOptions);
  1712. // generate javascript codes
  1713. return generate(ast, assignedOptions);
  1714. }
  1715. else {
  1716. // optimize ASTs
  1717. enambeOptimize && optimize(ast);
  1718. // minimize ASTs
  1719. enalbeMinify && minify(ast);
  1720. // In JIT mode, no ast transform, no code generation.
  1721. return { ast, code: '' };
  1722. }
  1723. }
  1724. const pathStateMachine = [];
  1725. pathStateMachine[0 /* States.BEFORE_PATH */] = {
  1726. ["w" /* PathCharTypes.WORKSPACE */]: [0 /* States.BEFORE_PATH */],
  1727. ["i" /* PathCharTypes.IDENT */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
  1728. ["[" /* PathCharTypes.LEFT_BRACKET */]: [4 /* States.IN_SUB_PATH */],
  1729. ["o" /* PathCharTypes.END_OF_FAIL */]: [7 /* States.AFTER_PATH */]
  1730. };
  1731. pathStateMachine[1 /* States.IN_PATH */] = {
  1732. ["w" /* PathCharTypes.WORKSPACE */]: [1 /* States.IN_PATH */],
  1733. ["." /* PathCharTypes.DOT */]: [2 /* States.BEFORE_IDENT */],
  1734. ["[" /* PathCharTypes.LEFT_BRACKET */]: [4 /* States.IN_SUB_PATH */],
  1735. ["o" /* PathCharTypes.END_OF_FAIL */]: [7 /* States.AFTER_PATH */]
  1736. };
  1737. pathStateMachine[2 /* States.BEFORE_IDENT */] = {
  1738. ["w" /* PathCharTypes.WORKSPACE */]: [2 /* States.BEFORE_IDENT */],
  1739. ["i" /* PathCharTypes.IDENT */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
  1740. ["0" /* PathCharTypes.ZERO */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */]
  1741. };
  1742. pathStateMachine[3 /* States.IN_IDENT */] = {
  1743. ["i" /* PathCharTypes.IDENT */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
  1744. ["0" /* PathCharTypes.ZERO */]: [3 /* States.IN_IDENT */, 0 /* Actions.APPEND */],
  1745. ["w" /* PathCharTypes.WORKSPACE */]: [1 /* States.IN_PATH */, 1 /* Actions.PUSH */],
  1746. ["." /* PathCharTypes.DOT */]: [2 /* States.BEFORE_IDENT */, 1 /* Actions.PUSH */],
  1747. ["[" /* PathCharTypes.LEFT_BRACKET */]: [4 /* States.IN_SUB_PATH */, 1 /* Actions.PUSH */],
  1748. ["o" /* PathCharTypes.END_OF_FAIL */]: [7 /* States.AFTER_PATH */, 1 /* Actions.PUSH */]
  1749. };
  1750. pathStateMachine[4 /* States.IN_SUB_PATH */] = {
  1751. ["'" /* PathCharTypes.SINGLE_QUOTE */]: [5 /* States.IN_SINGLE_QUOTE */, 0 /* Actions.APPEND */],
  1752. ["\"" /* PathCharTypes.DOUBLE_QUOTE */]: [6 /* States.IN_DOUBLE_QUOTE */, 0 /* Actions.APPEND */],
  1753. ["[" /* PathCharTypes.LEFT_BRACKET */]: [
  1754. 4 /* States.IN_SUB_PATH */,
  1755. 2 /* Actions.INC_SUB_PATH_DEPTH */
  1756. ],
  1757. ["]" /* PathCharTypes.RIGHT_BRACKET */]: [1 /* States.IN_PATH */, 3 /* Actions.PUSH_SUB_PATH */],
  1758. ["o" /* PathCharTypes.END_OF_FAIL */]: 8 /* States.ERROR */,
  1759. ["l" /* PathCharTypes.ELSE */]: [4 /* States.IN_SUB_PATH */, 0 /* Actions.APPEND */]
  1760. };
  1761. pathStateMachine[5 /* States.IN_SINGLE_QUOTE */] = {
  1762. ["'" /* PathCharTypes.SINGLE_QUOTE */]: [4 /* States.IN_SUB_PATH */, 0 /* Actions.APPEND */],
  1763. ["o" /* PathCharTypes.END_OF_FAIL */]: 8 /* States.ERROR */,
  1764. ["l" /* PathCharTypes.ELSE */]: [5 /* States.IN_SINGLE_QUOTE */, 0 /* Actions.APPEND */]
  1765. };
  1766. pathStateMachine[6 /* States.IN_DOUBLE_QUOTE */] = {
  1767. ["\"" /* PathCharTypes.DOUBLE_QUOTE */]: [4 /* States.IN_SUB_PATH */, 0 /* Actions.APPEND */],
  1768. ["o" /* PathCharTypes.END_OF_FAIL */]: 8 /* States.ERROR */,
  1769. ["l" /* PathCharTypes.ELSE */]: [6 /* States.IN_DOUBLE_QUOTE */, 0 /* Actions.APPEND */]
  1770. };
  1771. /**
  1772. * Check if an expression is a literal value.
  1773. */
  1774. const literalValueRE = /^\s?(?:true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/;
  1775. function isLiteral(exp) {
  1776. return literalValueRE.test(exp);
  1777. }
  1778. /**
  1779. * Strip quotes from a string
  1780. */
  1781. function stripQuotes(str) {
  1782. const a = str.charCodeAt(0);
  1783. const b = str.charCodeAt(str.length - 1);
  1784. return a === b && (a === 0x22 || a === 0x27) ? str.slice(1, -1) : str;
  1785. }
  1786. /**
  1787. * Determine the type of a character in a keypath.
  1788. */
  1789. function getPathCharType(ch) {
  1790. if (ch === undefined || ch === null) {
  1791. return "o" /* PathCharTypes.END_OF_FAIL */;
  1792. }
  1793. const code = ch.charCodeAt(0);
  1794. switch (code) {
  1795. case 0x5b: // [
  1796. case 0x5d: // ]
  1797. case 0x2e: // .
  1798. case 0x22: // "
  1799. case 0x27: // '
  1800. return ch;
  1801. case 0x5f: // _
  1802. case 0x24: // $
  1803. case 0x2d: // -
  1804. return "i" /* PathCharTypes.IDENT */;
  1805. case 0x09: // Tab (HT)
  1806. case 0x0a: // Newline (LF)
  1807. case 0x0d: // Return (CR)
  1808. case 0xa0: // No-break space (NBSP)
  1809. case 0xfeff: // Byte Order Mark (BOM)
  1810. case 0x2028: // Line Separator (LS)
  1811. case 0x2029: // Paragraph Separator (PS)
  1812. return "w" /* PathCharTypes.WORKSPACE */;
  1813. }
  1814. return "i" /* PathCharTypes.IDENT */;
  1815. }
  1816. /**
  1817. * Format a subPath, return its plain form if it is
  1818. * a literal string or number. Otherwise prepend the
  1819. * dynamic indicator (*).
  1820. */
  1821. function formatSubPath(path) {
  1822. const trimmed = path.trim();
  1823. // invalid leading 0
  1824. if (path.charAt(0) === '0' && isNaN(parseInt(path))) {
  1825. return false;
  1826. }
  1827. return isLiteral(trimmed)
  1828. ? stripQuotes(trimmed)
  1829. : "*" /* PathCharTypes.ASTARISK */ + trimmed;
  1830. }
  1831. /**
  1832. * Parse a string path into an array of segments
  1833. */
  1834. function parse(path) {
  1835. const keys = [];
  1836. let index = -1;
  1837. let mode = 0 /* States.BEFORE_PATH */;
  1838. let subPathDepth = 0;
  1839. let c;
  1840. let key; // eslint-disable-line
  1841. let newChar;
  1842. let type;
  1843. let transition;
  1844. let action;
  1845. let typeMap;
  1846. const actions = [];
  1847. actions[0 /* Actions.APPEND */] = () => {
  1848. if (key === undefined) {
  1849. key = newChar;
  1850. }
  1851. else {
  1852. key += newChar;
  1853. }
  1854. };
  1855. actions[1 /* Actions.PUSH */] = () => {
  1856. if (key !== undefined) {
  1857. keys.push(key);
  1858. key = undefined;
  1859. }
  1860. };
  1861. actions[2 /* Actions.INC_SUB_PATH_DEPTH */] = () => {
  1862. actions[0 /* Actions.APPEND */]();
  1863. subPathDepth++;
  1864. };
  1865. actions[3 /* Actions.PUSH_SUB_PATH */] = () => {
  1866. if (subPathDepth > 0) {
  1867. subPathDepth--;
  1868. mode = 4 /* States.IN_SUB_PATH */;
  1869. actions[0 /* Actions.APPEND */]();
  1870. }
  1871. else {
  1872. subPathDepth = 0;
  1873. if (key === undefined) {
  1874. return false;
  1875. }
  1876. key = formatSubPath(key);
  1877. if (key === false) {
  1878. return false;
  1879. }
  1880. else {
  1881. actions[1 /* Actions.PUSH */]();
  1882. }
  1883. }
  1884. };
  1885. function maybeUnescapeQuote() {
  1886. const nextChar = path[index + 1];
  1887. if ((mode === 5 /* States.IN_SINGLE_QUOTE */ &&
  1888. nextChar === "'" /* PathCharTypes.SINGLE_QUOTE */) ||
  1889. (mode === 6 /* States.IN_DOUBLE_QUOTE */ &&
  1890. nextChar === "\"" /* PathCharTypes.DOUBLE_QUOTE */)) {
  1891. index++;
  1892. newChar = '\\' + nextChar;
  1893. actions[0 /* Actions.APPEND */]();
  1894. return true;
  1895. }
  1896. }
  1897. while (mode !== null) {
  1898. index++;
  1899. c = path[index];
  1900. if (c === '\\' && maybeUnescapeQuote()) {
  1901. continue;
  1902. }
  1903. type = getPathCharType(c);
  1904. typeMap = pathStateMachine[mode];
  1905. transition = typeMap[type] || typeMap["l" /* PathCharTypes.ELSE */] || 8 /* States.ERROR */;
  1906. // check parse error
  1907. if (transition === 8 /* States.ERROR */) {
  1908. return;
  1909. }
  1910. mode = transition[0];
  1911. if (transition[1] !== undefined) {
  1912. action = actions[transition[1]];
  1913. if (action) {
  1914. newChar = c;
  1915. if (action() === false) {
  1916. return;
  1917. }
  1918. }
  1919. }
  1920. // check parse finish
  1921. if (mode === 7 /* States.AFTER_PATH */) {
  1922. return keys;
  1923. }
  1924. }
  1925. }
  1926. // path token cache
  1927. const cache = new Map();
  1928. /**
  1929. * key-value message resolver
  1930. *
  1931. * @remarks
  1932. * Resolves messages with the key-value structure. Note that messages with a hierarchical structure such as objects cannot be resolved
  1933. *
  1934. * @param obj - A target object to be resolved with path
  1935. * @param path - A {@link Path | path} to resolve the value of message
  1936. *
  1937. * @returns A resolved {@link PathValue | path value}
  1938. *
  1939. * @VueI18nGeneral
  1940. */
  1941. function resolveWithKeyValue(obj, path) {
  1942. return isObject(obj) ? obj[path] : null;
  1943. }
  1944. /**
  1945. * message resolver
  1946. *
  1947. * @remarks
  1948. * Resolves messages. messages with a hierarchical structure such as objects can be resolved. This resolver is used in VueI18n as default.
  1949. *
  1950. * @param obj - A target object to be resolved with path
  1951. * @param path - A {@link Path | path} to resolve the value of message
  1952. *
  1953. * @returns A resolved {@link PathValue | path value}
  1954. *
  1955. * @VueI18nGeneral
  1956. */
  1957. function resolveValue(obj, path) {
  1958. // check object
  1959. if (!isObject(obj)) {
  1960. return null;
  1961. }
  1962. // parse path
  1963. let hit = cache.get(path);
  1964. if (!hit) {
  1965. hit = parse(path);
  1966. if (hit) {
  1967. cache.set(path, hit);
  1968. }
  1969. }
  1970. // check hit
  1971. if (!hit) {
  1972. return null;
  1973. }
  1974. // resolve path value
  1975. const len = hit.length;
  1976. let last = obj;
  1977. let i = 0;
  1978. while (i < len) {
  1979. const val = last[hit[i]];
  1980. if (val === undefined) {
  1981. return null;
  1982. }
  1983. if (isFunction(last)) {
  1984. return null;
  1985. }
  1986. last = val;
  1987. i++;
  1988. }
  1989. return last;
  1990. }
  1991. const DEFAULT_MODIFIER = (str) => str;
  1992. const DEFAULT_MESSAGE = (ctx) => ''; // eslint-disable-line
  1993. const DEFAULT_MESSAGE_DATA_TYPE = 'text';
  1994. const DEFAULT_NORMALIZE = (values) => values.length === 0 ? '' : join(values);
  1995. const DEFAULT_INTERPOLATE = toDisplayString;
  1996. function pluralDefault(choice, choicesLength) {
  1997. choice = Math.abs(choice);
  1998. if (choicesLength === 2) {
  1999. // prettier-ignore
  2000. return choice
  2001. ? choice > 1
  2002. ? 1
  2003. : 0
  2004. : 1;
  2005. }
  2006. return choice ? Math.min(choice, 2) : 0;
  2007. }
  2008. function getPluralIndex(options) {
  2009. // prettier-ignore
  2010. const index = isNumber(options.pluralIndex)
  2011. ? options.pluralIndex
  2012. : -1;
  2013. // prettier-ignore
  2014. return options.named && (isNumber(options.named.count) || isNumber(options.named.n))
  2015. ? isNumber(options.named.count)
  2016. ? options.named.count
  2017. : isNumber(options.named.n)
  2018. ? options.named.n
  2019. : index
  2020. : index;
  2021. }
  2022. function normalizeNamed(pluralIndex, props) {
  2023. if (!props.count) {
  2024. props.count = pluralIndex;
  2025. }
  2026. if (!props.n) {
  2027. props.n = pluralIndex;
  2028. }
  2029. }
  2030. function createMessageContext(options = {}) {
  2031. const locale = options.locale;
  2032. const pluralIndex = getPluralIndex(options);
  2033. const pluralRule = isObject(options.pluralRules) &&
  2034. isString(locale) &&
  2035. isFunction(options.pluralRules[locale])
  2036. ? options.pluralRules[locale]
  2037. : pluralDefault;
  2038. const orgPluralRule = isObject(options.pluralRules) &&
  2039. isString(locale) &&
  2040. isFunction(options.pluralRules[locale])
  2041. ? pluralDefault
  2042. : undefined;
  2043. const plural = (messages) => {
  2044. return messages[pluralRule(pluralIndex, messages.length, orgPluralRule)];
  2045. };
  2046. const _list = options.list || [];
  2047. const list = (index) => _list[index];
  2048. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  2049. const _named = options.named || {};
  2050. isNumber(options.pluralIndex) && normalizeNamed(pluralIndex, _named);
  2051. const named = (key) => _named[key];
  2052. function message(key) {
  2053. // prettier-ignore
  2054. const msg = isFunction(options.messages)
  2055. ? options.messages(key)
  2056. : isObject(options.messages)
  2057. ? options.messages[key]
  2058. : false;
  2059. return !msg
  2060. ? options.parent
  2061. ? options.parent.message(key) // resolve from parent messages
  2062. : DEFAULT_MESSAGE
  2063. : msg;
  2064. }
  2065. const _modifier = (name) => options.modifiers
  2066. ? options.modifiers[name]
  2067. : DEFAULT_MODIFIER;
  2068. const normalize = isPlainObject(options.processor) && isFunction(options.processor.normalize)
  2069. ? options.processor.normalize
  2070. : DEFAULT_NORMALIZE;
  2071. const interpolate = isPlainObject(options.processor) &&
  2072. isFunction(options.processor.interpolate)
  2073. ? options.processor.interpolate
  2074. : DEFAULT_INTERPOLATE;
  2075. const type = isPlainObject(options.processor) && isString(options.processor.type)
  2076. ? options.processor.type
  2077. : DEFAULT_MESSAGE_DATA_TYPE;
  2078. const linked = (key, ...args) => {
  2079. const [arg1, arg2] = args;
  2080. let type = 'text';
  2081. let modifier = '';
  2082. if (args.length === 1) {
  2083. if (isObject(arg1)) {
  2084. modifier = arg1.modifier || modifier;
  2085. type = arg1.type || type;
  2086. }
  2087. else if (isString(arg1)) {
  2088. modifier = arg1 || modifier;
  2089. }
  2090. }
  2091. else if (args.length === 2) {
  2092. if (isString(arg1)) {
  2093. modifier = arg1 || modifier;
  2094. }
  2095. if (isString(arg2)) {
  2096. type = arg2 || type;
  2097. }
  2098. }
  2099. const ret = message(key)(ctx);
  2100. const msg =
  2101. // The message in vnode resolved with linked are returned as an array by processor.nomalize
  2102. type === 'vnode' && isArray(ret) && modifier
  2103. ? ret[0]
  2104. : ret;
  2105. return modifier ? _modifier(modifier)(msg, type) : msg;
  2106. };
  2107. const ctx = {
  2108. ["list" /* HelperNameMap.LIST */]: list,
  2109. ["named" /* HelperNameMap.NAMED */]: named,
  2110. ["plural" /* HelperNameMap.PLURAL */]: plural,
  2111. ["linked" /* HelperNameMap.LINKED */]: linked,
  2112. ["message" /* HelperNameMap.MESSAGE */]: message,
  2113. ["type" /* HelperNameMap.TYPE */]: type,
  2114. ["interpolate" /* HelperNameMap.INTERPOLATE */]: interpolate,
  2115. ["normalize" /* HelperNameMap.NORMALIZE */]: normalize,
  2116. ["values" /* HelperNameMap.VALUES */]: assign({}, _list, _named)
  2117. };
  2118. return ctx;
  2119. }
  2120. let devtools = null;
  2121. function setDevToolsHook(hook) {
  2122. devtools = hook;
  2123. }
  2124. function getDevToolsHook() {
  2125. return devtools;
  2126. }
  2127. function initI18nDevTools(i18n, version, meta) {
  2128. // TODO: queue if devtools is undefined
  2129. devtools &&
  2130. devtools.emit("i18n:init" /* IntlifyDevToolsHooks.I18nInit */, {
  2131. timestamp: Date.now(),
  2132. i18n,
  2133. version,
  2134. meta
  2135. });
  2136. }
  2137. const translateDevTools = /* #__PURE__*/ createDevToolsHook("function:translate" /* IntlifyDevToolsHooks.FunctionTranslate */);
  2138. function createDevToolsHook(hook) {
  2139. return (payloads) => devtools && devtools.emit(hook, payloads);
  2140. }
  2141. const code$1 = CompileWarnCodes.__EXTEND_POINT__;
  2142. const inc$1 = incrementer(code$1);
  2143. const CoreWarnCodes = {
  2144. NOT_FOUND_KEY: code$1, // 2
  2145. FALLBACK_TO_TRANSLATE: inc$1(), // 3
  2146. CANNOT_FORMAT_NUMBER: inc$1(), // 4
  2147. FALLBACK_TO_NUMBER_FORMAT: inc$1(), // 5
  2148. CANNOT_FORMAT_DATE: inc$1(), // 6
  2149. FALLBACK_TO_DATE_FORMAT: inc$1(), // 7
  2150. EXPERIMENTAL_CUSTOM_MESSAGE_COMPILER: inc$1(), // 8
  2151. __EXTEND_POINT__: inc$1() // 9
  2152. };
  2153. /** @internal */
  2154. const warnMessages = {
  2155. [CoreWarnCodes.NOT_FOUND_KEY]: `Not found '{key}' key in '{locale}' locale messages.`,
  2156. [CoreWarnCodes.FALLBACK_TO_TRANSLATE]: `Fall back to translate '{key}' key with '{target}' locale.`,
  2157. [CoreWarnCodes.CANNOT_FORMAT_NUMBER]: `Cannot format a number value due to not supported Intl.NumberFormat.`,
  2158. [CoreWarnCodes.FALLBACK_TO_NUMBER_FORMAT]: `Fall back to number format '{key}' key with '{target}' locale.`,
  2159. [CoreWarnCodes.CANNOT_FORMAT_DATE]: `Cannot format a date value due to not supported Intl.DateTimeFormat.`,
  2160. [CoreWarnCodes.FALLBACK_TO_DATE_FORMAT]: `Fall back to datetime format '{key}' key with '{target}' locale.`,
  2161. [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.`
  2162. };
  2163. function getWarnMessage(code, ...args) {
  2164. return format$1(warnMessages[code], ...args);
  2165. }
  2166. const code = CompileErrorCodes.__EXTEND_POINT__;
  2167. const inc = incrementer(code);
  2168. const CoreErrorCodes = {
  2169. INVALID_ARGUMENT: code, // 17
  2170. INVALID_DATE_ARGUMENT: inc(), // 18
  2171. INVALID_ISO_DATE_ARGUMENT: inc(), // 19
  2172. NOT_SUPPORT_NON_STRING_MESSAGE: inc(), // 20
  2173. NOT_SUPPORT_LOCALE_PROMISE_VALUE: inc(), // 21
  2174. NOT_SUPPORT_LOCALE_ASYNC_FUNCTION: inc(), // 22
  2175. NOT_SUPPORT_LOCALE_TYPE: inc(), // 23
  2176. __EXTEND_POINT__: inc() // 24
  2177. };
  2178. function createCoreError(code) {
  2179. return createCompileError(code, null, { messages: errorMessages } );
  2180. }
  2181. /** @internal */
  2182. const errorMessages = {
  2183. [CoreErrorCodes.INVALID_ARGUMENT]: 'Invalid arguments',
  2184. [CoreErrorCodes.INVALID_DATE_ARGUMENT]: 'The date provided is an invalid Date object.' +
  2185. 'Make sure your Date represents a valid date.',
  2186. [CoreErrorCodes.INVALID_ISO_DATE_ARGUMENT]: 'The argument provided is not a valid ISO date string',
  2187. [CoreErrorCodes.NOT_SUPPORT_NON_STRING_MESSAGE]: 'Not support non-string message',
  2188. [CoreErrorCodes.NOT_SUPPORT_LOCALE_PROMISE_VALUE]: 'cannot support promise value',
  2189. [CoreErrorCodes.NOT_SUPPORT_LOCALE_ASYNC_FUNCTION]: 'cannot support async function',
  2190. [CoreErrorCodes.NOT_SUPPORT_LOCALE_TYPE]: 'cannot support locale type'
  2191. };
  2192. /** @internal */
  2193. function getLocale(context, options) {
  2194. return options.locale != null
  2195. ? resolveLocale(options.locale)
  2196. : resolveLocale(context.locale);
  2197. }
  2198. let _resolveLocale;
  2199. /** @internal */
  2200. function resolveLocale(locale) {
  2201. if (isString(locale)) {
  2202. return locale;
  2203. }
  2204. else {
  2205. if (isFunction(locale)) {
  2206. if (locale.resolvedOnce && _resolveLocale != null) {
  2207. return _resolveLocale;
  2208. }
  2209. else if (locale.constructor.name === 'Function') {
  2210. const resolve = locale();
  2211. if (isPromise(resolve)) {
  2212. throw createCoreError(CoreErrorCodes.NOT_SUPPORT_LOCALE_PROMISE_VALUE);
  2213. }
  2214. return (_resolveLocale = resolve);
  2215. }
  2216. else {
  2217. throw createCoreError(CoreErrorCodes.NOT_SUPPORT_LOCALE_ASYNC_FUNCTION);
  2218. }
  2219. }
  2220. else {
  2221. throw createCoreError(CoreErrorCodes.NOT_SUPPORT_LOCALE_TYPE);
  2222. }
  2223. }
  2224. }
  2225. /**
  2226. * Fallback with simple implemenation
  2227. *
  2228. * @remarks
  2229. * A fallback locale function implemented with a simple fallback algorithm.
  2230. *
  2231. * Basically, it returns the value as specified in the `fallbackLocale` props, and is processed with the fallback inside intlify.
  2232. *
  2233. * @param ctx - A {@link CoreContext | context}
  2234. * @param fallback - A {@link FallbackLocale | fallback locale}
  2235. * @param start - A starting {@link Locale | locale}
  2236. *
  2237. * @returns Fallback locales
  2238. *
  2239. * @VueI18nGeneral
  2240. */
  2241. function fallbackWithSimple(ctx, fallback, start // eslint-disable-line @typescript-eslint/no-unused-vars
  2242. ) {
  2243. // prettier-ignore
  2244. return [...new Set([
  2245. start,
  2246. ...(isArray(fallback)
  2247. ? fallback
  2248. : isObject(fallback)
  2249. ? Object.keys(fallback)
  2250. : isString(fallback)
  2251. ? [fallback]
  2252. : [start])
  2253. ])];
  2254. }
  2255. /**
  2256. * Fallback with locale chain
  2257. *
  2258. * @remarks
  2259. * A fallback locale function implemented with a fallback chain algorithm. It's used in VueI18n as default.
  2260. *
  2261. * @param ctx - A {@link CoreContext | context}
  2262. * @param fallback - A {@link FallbackLocale | fallback locale}
  2263. * @param start - A starting {@link Locale | locale}
  2264. *
  2265. * @returns Fallback locales
  2266. *
  2267. * @VueI18nSee [Fallbacking](../guide/essentials/fallback)
  2268. *
  2269. * @VueI18nGeneral
  2270. */
  2271. function fallbackWithLocaleChain(ctx, fallback, start) {
  2272. const startLocale = isString(start) ? start : DEFAULT_LOCALE;
  2273. const context = ctx;
  2274. if (!context.__localeChainCache) {
  2275. context.__localeChainCache = new Map();
  2276. }
  2277. let chain = context.__localeChainCache.get(startLocale);
  2278. if (!chain) {
  2279. chain = [];
  2280. // first block defined by start
  2281. let block = [start];
  2282. // while any intervening block found
  2283. while (isArray(block)) {
  2284. block = appendBlockToChain(chain, block, fallback);
  2285. }
  2286. // prettier-ignore
  2287. // last block defined by default
  2288. const defaults = isArray(fallback) || !isPlainObject(fallback)
  2289. ? fallback
  2290. : fallback['default']
  2291. ? fallback['default']
  2292. : null;
  2293. // convert defaults to array
  2294. block = isString(defaults) ? [defaults] : defaults;
  2295. if (isArray(block)) {
  2296. appendBlockToChain(chain, block, false);
  2297. }
  2298. context.__localeChainCache.set(startLocale, chain);
  2299. }
  2300. return chain;
  2301. }
  2302. function appendBlockToChain(chain, block, blocks) {
  2303. let follow = true;
  2304. for (let i = 0; i < block.length && isBoolean(follow); i++) {
  2305. const locale = block[i];
  2306. if (isString(locale)) {
  2307. follow = appendLocaleToChain(chain, block[i], blocks);
  2308. }
  2309. }
  2310. return follow;
  2311. }
  2312. function appendLocaleToChain(chain, locale, blocks) {
  2313. let follow;
  2314. const tokens = locale.split('-');
  2315. do {
  2316. const target = tokens.join('-');
  2317. follow = appendItemToChain(chain, target, blocks);
  2318. tokens.splice(-1, 1);
  2319. } while (tokens.length && follow === true);
  2320. return follow;
  2321. }
  2322. function appendItemToChain(chain, target, blocks) {
  2323. let follow = false;
  2324. if (!chain.includes(target)) {
  2325. follow = true;
  2326. if (target) {
  2327. follow = target[target.length - 1] !== '!';
  2328. const locale = target.replace(/!/g, '');
  2329. chain.push(locale);
  2330. if ((isArray(blocks) || isPlainObject(blocks)) &&
  2331. blocks[locale] // eslint-disable-line @typescript-eslint/no-explicit-any
  2332. ) {
  2333. // eslint-disable-next-line @typescript-eslint/no-explicit-any
  2334. follow = blocks[locale];
  2335. }
  2336. }
  2337. }
  2338. return follow;
  2339. }
  2340. /* eslint-disable @typescript-eslint/no-explicit-any */
  2341. /**
  2342. * Intlify core-base version
  2343. * @internal
  2344. */
  2345. const VERSION = '9.13.1';
  2346. const NOT_REOSLVED = -1;
  2347. const DEFAULT_LOCALE = 'en-US';
  2348. const MISSING_RESOLVE_VALUE = '';
  2349. const capitalize = (str) => `${str.charAt(0).toLocaleUpperCase()}${str.substr(1)}`;
  2350. function getDefaultLinkedModifiers() {
  2351. return {
  2352. upper: (val, type) => {
  2353. // prettier-ignore
  2354. return type === 'text' && isString(val)
  2355. ? val.toUpperCase()
  2356. : type === 'vnode' && isObject(val) && '__v_isVNode' in val
  2357. ? val.children.toUpperCase()
  2358. : val;
  2359. },
  2360. lower: (val, type) => {
  2361. // prettier-ignore
  2362. return type === 'text' && isString(val)
  2363. ? val.toLowerCase()
  2364. : type === 'vnode' && isObject(val) && '__v_isVNode' in val
  2365. ? val.children.toLowerCase()
  2366. : val;
  2367. },
  2368. capitalize: (val, type) => {
  2369. // prettier-ignore
  2370. return (type === 'text' && isString(val)
  2371. ? capitalize(val)
  2372. : type === 'vnode' && isObject(val) && '__v_isVNode' in val
  2373. ? capitalize(val.children)
  2374. : val);
  2375. }
  2376. };
  2377. }
  2378. let _compiler;
  2379. function registerMessageCompiler(compiler) {
  2380. _compiler = compiler;
  2381. }
  2382. let _resolver;
  2383. /**
  2384. * Register the message resolver
  2385. *
  2386. * @param resolver - A {@link MessageResolver} function
  2387. *
  2388. * @VueI18nGeneral
  2389. */
  2390. function registerMessageResolver(resolver) {
  2391. _resolver = resolver;
  2392. }
  2393. let _fallbacker;
  2394. /**
  2395. * Register the locale fallbacker
  2396. *
  2397. * @param fallbacker - A {@link LocaleFallbacker} function
  2398. *
  2399. * @VueI18nGeneral
  2400. */
  2401. function registerLocaleFallbacker(fallbacker) {
  2402. _fallbacker = fallbacker;
  2403. }
  2404. // Additional Meta for Intlify DevTools
  2405. let _additionalMeta = null;
  2406. /* #__NO_SIDE_EFFECTS__ */
  2407. const setAdditionalMeta = (meta) => {
  2408. _additionalMeta = meta;
  2409. };
  2410. /* #__NO_SIDE_EFFECTS__ */
  2411. const getAdditionalMeta = () => _additionalMeta;
  2412. let _fallbackContext = null;
  2413. const setFallbackContext = (context) => {
  2414. _fallbackContext = context;
  2415. };
  2416. const getFallbackContext = () => _fallbackContext;
  2417. // ID for CoreContext
  2418. let _cid = 0;
  2419. function createCoreContext(options = {}) {
  2420. // setup options
  2421. const onWarn = isFunction(options.onWarn) ? options.onWarn : warn;
  2422. const version = isString(options.version) ? options.version : VERSION;
  2423. const locale = isString(options.locale) || isFunction(options.locale)
  2424. ? options.locale
  2425. : DEFAULT_LOCALE;
  2426. const _locale = isFunction(locale) ? DEFAULT_LOCALE : locale;
  2427. const fallbackLocale = isArray(options.fallbackLocale) ||
  2428. isPlainObject(options.fallbackLocale) ||
  2429. isString(options.fallbackLocale) ||
  2430. options.fallbackLocale === false
  2431. ? options.fallbackLocale
  2432. : _locale;
  2433. const messages = isPlainObject(options.messages)
  2434. ? options.messages
  2435. : { [_locale]: {} };
  2436. const datetimeFormats = isPlainObject(options.datetimeFormats)
  2437. ? options.datetimeFormats
  2438. : { [_locale]: {} }
  2439. ;
  2440. const numberFormats = isPlainObject(options.numberFormats)
  2441. ? options.numberFormats
  2442. : { [_locale]: {} }
  2443. ;
  2444. const modifiers = assign({}, options.modifiers || {}, getDefaultLinkedModifiers());
  2445. const pluralRules = options.pluralRules || {};
  2446. const missing = isFunction(options.missing) ? options.missing : null;
  2447. const missingWarn = isBoolean(options.missingWarn) || isRegExp(options.missingWarn)
  2448. ? options.missingWarn
  2449. : true;
  2450. const fallbackWarn = isBoolean(options.fallbackWarn) || isRegExp(options.fallbackWarn)
  2451. ? options.fallbackWarn
  2452. : true;
  2453. const fallbackFormat = !!options.fallbackFormat;
  2454. const unresolving = !!options.unresolving;
  2455. const postTranslation = isFunction(options.postTranslation)
  2456. ? options.postTranslation
  2457. : null;
  2458. const processor = isPlainObject(options.processor) ? options.processor : null;
  2459. const warnHtmlMessage = isBoolean(options.warnHtmlMessage)
  2460. ? options.warnHtmlMessage
  2461. : true;
  2462. const escapeParameter = !!options.escapeParameter;
  2463. const messageCompiler = isFunction(options.messageCompiler)
  2464. ? options.messageCompiler
  2465. : _compiler;
  2466. const messageResolver = isFunction(options.messageResolver)
  2467. ? options.messageResolver
  2468. : _resolver || resolveWithKeyValue;
  2469. const localeFallbacker = isFunction(options.localeFallbacker)
  2470. ? options.localeFallbacker
  2471. : _fallbacker || fallbackWithSimple;
  2472. const fallbackContext = isObject(options.fallbackContext)
  2473. ? options.fallbackContext
  2474. : undefined;
  2475. // setup internal options
  2476. const internalOptions = options;
  2477. const __datetimeFormatters = isObject(internalOptions.__datetimeFormatters)
  2478. ? internalOptions.__datetimeFormatters
  2479. : new Map()
  2480. ;
  2481. const __numberFormatters = isObject(internalOptions.__numberFormatters)
  2482. ? internalOptions.__numberFormatters
  2483. : new Map()
  2484. ;
  2485. const __meta = isObject(internalOptions.__meta) ? internalOptions.__meta : {};
  2486. _cid++;
  2487. const context = {
  2488. version,
  2489. cid: _cid,
  2490. locale,
  2491. fallbackLocale,
  2492. messages,
  2493. modifiers,
  2494. pluralRules,
  2495. missing,
  2496. missingWarn,
  2497. fallbackWarn,
  2498. fallbackFormat,
  2499. unresolving,
  2500. postTranslation,
  2501. processor,
  2502. warnHtmlMessage,
  2503. escapeParameter,
  2504. messageCompiler,
  2505. messageResolver,
  2506. localeFallbacker,
  2507. fallbackContext,
  2508. onWarn,
  2509. __meta
  2510. };
  2511. {
  2512. context.datetimeFormats = datetimeFormats;
  2513. context.numberFormats = numberFormats;
  2514. context.__datetimeFormatters = __datetimeFormatters;
  2515. context.__numberFormatters = __numberFormatters;
  2516. }
  2517. // for vue-devtools timeline event
  2518. {
  2519. context.__v_emitter =
  2520. internalOptions.__v_emitter != null
  2521. ? internalOptions.__v_emitter
  2522. : undefined;
  2523. }
  2524. // NOTE: experimental !!
  2525. {
  2526. initI18nDevTools(context, version, __meta);
  2527. }
  2528. return context;
  2529. }
  2530. /** @internal */
  2531. function isTranslateFallbackWarn(fallback, key) {
  2532. return fallback instanceof RegExp ? fallback.test(key) : fallback;
  2533. }
  2534. /** @internal */
  2535. function isTranslateMissingWarn(missing, key) {
  2536. return missing instanceof RegExp ? missing.test(key) : missing;
  2537. }
  2538. /** @internal */
  2539. function handleMissing(context, key, locale, missingWarn, type) {
  2540. const { missing, onWarn } = context;
  2541. // for vue-devtools timeline event
  2542. {
  2543. const emitter = context.__v_emitter;
  2544. if (emitter) {
  2545. emitter.emit("missing" /* VueDevToolsTimelineEvents.MISSING */, {
  2546. locale,
  2547. key,
  2548. type,
  2549. groupId: `${type}:${key}`
  2550. });
  2551. }
  2552. }
  2553. if (missing !== null) {
  2554. const ret = missing(context, locale, key, type);
  2555. return isString(ret) ? ret : key;
  2556. }
  2557. else {
  2558. if (isTranslateMissingWarn(missingWarn, key)) {
  2559. onWarn(getWarnMessage(CoreWarnCodes.NOT_FOUND_KEY, { key, locale }));
  2560. }
  2561. return key;
  2562. }
  2563. }
  2564. /** @internal */
  2565. function updateFallbackLocale(ctx, locale, fallback) {
  2566. const context = ctx;
  2567. context.__localeChainCache = new Map();
  2568. ctx.localeFallbacker(ctx, fallback, locale);
  2569. }
  2570. /** @internal */
  2571. function isAlmostSameLocale(locale, compareLocale) {
  2572. if (locale === compareLocale)
  2573. return false;
  2574. return locale.split('-')[0] === compareLocale.split('-')[0];
  2575. }
  2576. /** @internal */
  2577. function isImplicitFallback(targetLocale, locales) {
  2578. const index = locales.indexOf(targetLocale);
  2579. if (index === -1) {
  2580. return false;
  2581. }
  2582. for (let i = index + 1; i < locales.length; i++) {
  2583. if (isAlmostSameLocale(targetLocale, locales[i])) {
  2584. return true;
  2585. }
  2586. }
  2587. return false;
  2588. }
  2589. /* eslint-enable @typescript-eslint/no-explicit-any */
  2590. function format(ast) {
  2591. const msg = (ctx) => formatParts(ctx, ast);
  2592. return msg;
  2593. }
  2594. function formatParts(ctx, ast) {
  2595. const body = ast.b || ast.body;
  2596. if ((body.t || body.type) === 1 /* NodeTypes.Plural */) {
  2597. const plural = body;
  2598. const cases = plural.c || plural.cases;
  2599. return ctx.plural(cases.reduce((messages, c) => [
  2600. ...messages,
  2601. formatMessageParts(ctx, c)
  2602. ], []));
  2603. }
  2604. else {
  2605. return formatMessageParts(ctx, body);
  2606. }
  2607. }
  2608. function formatMessageParts(ctx, node) {
  2609. const _static = node.s || node.static;
  2610. if (_static) {
  2611. return ctx.type === 'text'
  2612. ? _static
  2613. : ctx.normalize([_static]);
  2614. }
  2615. else {
  2616. const messages = (node.i || node.items).reduce((acm, c) => [...acm, formatMessagePart(ctx, c)], []);
  2617. return ctx.normalize(messages);
  2618. }
  2619. }
  2620. function formatMessagePart(ctx, node) {
  2621. const type = node.t || node.type;
  2622. switch (type) {
  2623. case 3 /* NodeTypes.Text */: {
  2624. const text = node;
  2625. return (text.v || text.value);
  2626. }
  2627. case 9 /* NodeTypes.Literal */: {
  2628. const literal = node;
  2629. return (literal.v || literal.value);
  2630. }
  2631. case 4 /* NodeTypes.Named */: {
  2632. const named = node;
  2633. return ctx.interpolate(ctx.named(named.k || named.key));
  2634. }
  2635. case 5 /* NodeTypes.List */: {
  2636. const list = node;
  2637. return ctx.interpolate(ctx.list(list.i != null ? list.i : list.index));
  2638. }
  2639. case 6 /* NodeTypes.Linked */: {
  2640. const linked = node;
  2641. const modifier = linked.m || linked.modifier;
  2642. return ctx.linked(formatMessagePart(ctx, linked.k || linked.key), modifier ? formatMessagePart(ctx, modifier) : undefined, ctx.type);
  2643. }
  2644. case 7 /* NodeTypes.LinkedKey */: {
  2645. const linkedKey = node;
  2646. return (linkedKey.v || linkedKey.value);
  2647. }
  2648. case 8 /* NodeTypes.LinkedModifier */: {
  2649. const linkedModifier = node;
  2650. return (linkedModifier.v || linkedModifier.value);
  2651. }
  2652. default:
  2653. throw new Error(`unhandled node type on format message part: ${type}`);
  2654. }
  2655. }
  2656. const WARN_MESSAGE = `Detected HTML in '{source}' message. Recommend not using HTML messages to avoid XSS.`;
  2657. function checkHtmlMessage(source, warnHtmlMessage) {
  2658. if (warnHtmlMessage && detectHtmlTag(source)) {
  2659. warn(format$1(WARN_MESSAGE, { source }));
  2660. }
  2661. }
  2662. const defaultOnCacheKey = (message) => message;
  2663. let compileCache = Object.create(null);
  2664. function onCompileWarn(_warn) {
  2665. if (_warn.code === CompileWarnCodes.USE_MODULO_SYNTAX) {
  2666. warn(`The use of named interpolation with modulo syntax is deprecated. ` +
  2667. `It will be removed in v10.\n` +
  2668. `reference: https://vue-i18n.intlify.dev/guide/essentials/syntax#rails-i18n-format \n` +
  2669. `(message compiler warning message: ${_warn.message})`);
  2670. }
  2671. }
  2672. function clearCompileCache() {
  2673. compileCache = Object.create(null);
  2674. }
  2675. const isMessageAST = (val) => isObject(val) &&
  2676. (val.t === 0 || val.type === 0) &&
  2677. ('b' in val || 'body' in val);
  2678. function baseCompile(message, options = {}) {
  2679. // error detecting on compile
  2680. let detectError = false;
  2681. const onError = options.onError || defaultOnError;
  2682. options.onError = (err) => {
  2683. detectError = true;
  2684. onError(err);
  2685. };
  2686. // compile with mesasge-compiler
  2687. return { ...baseCompile$1(message, options), detectError };
  2688. }
  2689. /* #__NO_SIDE_EFFECTS__ */
  2690. const compileToFunction = (message, context) => {
  2691. if (!isString(message)) {
  2692. throw createCoreError(CoreErrorCodes.NOT_SUPPORT_NON_STRING_MESSAGE);
  2693. }
  2694. // set onWarn
  2695. {
  2696. context.onWarn = onCompileWarn;
  2697. }
  2698. {
  2699. // check HTML message
  2700. const warnHtmlMessage = isBoolean(context.warnHtmlMessage)
  2701. ? context.warnHtmlMessage
  2702. : true;
  2703. checkHtmlMessage(message, warnHtmlMessage);
  2704. // check caches
  2705. const onCacheKey = context.onCacheKey || defaultOnCacheKey;
  2706. const cacheKey = onCacheKey(message);
  2707. const cached = compileCache[cacheKey];
  2708. if (cached) {
  2709. return cached;
  2710. }
  2711. // compile
  2712. const { code, detectError } = baseCompile(message, context);
  2713. // evaluate function
  2714. const msg = new Function(`return ${code}`)();
  2715. // if occurred compile error, don't cache
  2716. return !detectError
  2717. ? (compileCache[cacheKey] = msg)
  2718. : msg;
  2719. }
  2720. };
  2721. function compile(message, context) {
  2722. // set onWarn
  2723. {
  2724. context.onWarn = onCompileWarn;
  2725. }
  2726. if (isString(message)) {
  2727. // check HTML message
  2728. const warnHtmlMessage = isBoolean(context.warnHtmlMessage)
  2729. ? context.warnHtmlMessage
  2730. : true;
  2731. checkHtmlMessage(message, warnHtmlMessage);
  2732. // check caches
  2733. const onCacheKey = context.onCacheKey || defaultOnCacheKey;
  2734. const cacheKey = onCacheKey(message);
  2735. const cached = compileCache[cacheKey];
  2736. if (cached) {
  2737. return cached;
  2738. }
  2739. // compile with JIT mode
  2740. const { ast, detectError } = baseCompile(message, {
  2741. ...context,
  2742. location: true,
  2743. jit: true
  2744. });
  2745. // compose message function from AST
  2746. const msg = format(ast);
  2747. // if occurred compile error, don't cache
  2748. return !detectError
  2749. ? (compileCache[cacheKey] = msg)
  2750. : msg;
  2751. }
  2752. else {
  2753. if (!isMessageAST(message)) {
  2754. warn(`the message that is resolve with key '${context.key}' is not supported for jit compilation`);
  2755. return (() => message);
  2756. }
  2757. // AST case (passed from bundler)
  2758. const cacheKey = message.cacheKey;
  2759. if (cacheKey) {
  2760. const cached = compileCache[cacheKey];
  2761. if (cached) {
  2762. return cached;
  2763. }
  2764. // compose message function from message (AST)
  2765. return (compileCache[cacheKey] =
  2766. format(message));
  2767. }
  2768. else {
  2769. return format(message);
  2770. }
  2771. }
  2772. }
  2773. const NOOP_MESSAGE_FUNCTION = () => '';
  2774. const isMessageFunction = (val) => isFunction(val);
  2775. // implementation of `translate` function
  2776. function translate(context, ...args) {
  2777. const { fallbackFormat, postTranslation, unresolving, messageCompiler, fallbackLocale, messages } = context;
  2778. const [key, options] = parseTranslateArgs(...args);
  2779. const missingWarn = isBoolean(options.missingWarn)
  2780. ? options.missingWarn
  2781. : context.missingWarn;
  2782. const fallbackWarn = isBoolean(options.fallbackWarn)
  2783. ? options.fallbackWarn
  2784. : context.fallbackWarn;
  2785. const escapeParameter = isBoolean(options.escapeParameter)
  2786. ? options.escapeParameter
  2787. : context.escapeParameter;
  2788. const resolvedMessage = !!options.resolvedMessage;
  2789. // prettier-ignore
  2790. const defaultMsgOrKey = isString(options.default) || isBoolean(options.default) // default by function option
  2791. ? !isBoolean(options.default)
  2792. ? options.default
  2793. : (!messageCompiler ? () => key : key)
  2794. : fallbackFormat // default by `fallbackFormat` option
  2795. ? (!messageCompiler ? () => key : key)
  2796. : '';
  2797. const enableDefaultMsg = fallbackFormat || defaultMsgOrKey !== '';
  2798. const locale = getLocale(context, options);
  2799. // escape params
  2800. escapeParameter && escapeParams(options);
  2801. // resolve message format
  2802. // eslint-disable-next-line prefer-const
  2803. let [formatScope, targetLocale, message] = !resolvedMessage
  2804. ? resolveMessageFormat(context, key, locale, fallbackLocale, fallbackWarn, missingWarn)
  2805. : [
  2806. key,
  2807. locale,
  2808. messages[locale] || {}
  2809. ];
  2810. // NOTE:
  2811. // Fix to work around `ssrTransfrom` bug in Vite.
  2812. // https://github.com/vitejs/vite/issues/4306
  2813. // To get around this, use temporary variables.
  2814. // https://github.com/nuxt/framework/issues/1461#issuecomment-954606243
  2815. let format = formatScope;
  2816. // if you use default message, set it as message format!
  2817. let cacheBaseKey = key;
  2818. if (!resolvedMessage &&
  2819. !(isString(format) ||
  2820. isMessageAST(format) ||
  2821. isMessageFunction(format))) {
  2822. if (enableDefaultMsg) {
  2823. format = defaultMsgOrKey;
  2824. cacheBaseKey = format;
  2825. }
  2826. }
  2827. // checking message format and target locale
  2828. if (!resolvedMessage &&
  2829. (!(isString(format) ||
  2830. isMessageAST(format) ||
  2831. isMessageFunction(format)) ||
  2832. !isString(targetLocale))) {
  2833. return unresolving ? NOT_REOSLVED : key;
  2834. }
  2835. // TODO: refactor
  2836. if (isString(format) && context.messageCompiler == null) {
  2837. warn(`The message format compilation is not supported in this build. ` +
  2838. `Because message compiler isn't included. ` +
  2839. `You need to pre-compilation all message format. ` +
  2840. `So translate function return '${key}'.`);
  2841. return key;
  2842. }
  2843. // setup compile error detecting
  2844. let occurred = false;
  2845. const onError = () => {
  2846. occurred = true;
  2847. };
  2848. // compile message format
  2849. const msg = !isMessageFunction(format)
  2850. ? compileMessageFormat(context, key, targetLocale, format, cacheBaseKey, onError)
  2851. : format;
  2852. // if occurred compile error, return the message format
  2853. if (occurred) {
  2854. return format;
  2855. }
  2856. // evaluate message with context
  2857. const ctxOptions = getMessageContextOptions(context, targetLocale, message, options);
  2858. const msgContext = createMessageContext(ctxOptions);
  2859. const messaged = evaluateMessage(context, msg, msgContext);
  2860. // if use post translation option, proceed it with handler
  2861. const ret = postTranslation
  2862. ? postTranslation(messaged, key)
  2863. : messaged;
  2864. // NOTE: experimental !!
  2865. {
  2866. // prettier-ignore
  2867. const payloads = {
  2868. timestamp: Date.now(),
  2869. key: isString(key)
  2870. ? key
  2871. : isMessageFunction(format)
  2872. ? format.key
  2873. : '',
  2874. locale: targetLocale || (isMessageFunction(format)
  2875. ? format.locale
  2876. : ''),
  2877. format: isString(format)
  2878. ? format
  2879. : isMessageFunction(format)
  2880. ? format.source
  2881. : '',
  2882. message: ret
  2883. };
  2884. payloads.meta = assign({}, context.__meta, getAdditionalMeta() || {});
  2885. translateDevTools(payloads);
  2886. }
  2887. return ret;
  2888. }
  2889. function escapeParams(options) {
  2890. if (isArray(options.list)) {
  2891. options.list = options.list.map(item => isString(item) ? escapeHtml(item) : item);
  2892. }
  2893. else if (isObject(options.named)) {
  2894. Object.keys(options.named).forEach(key => {
  2895. if (isString(options.named[key])) {
  2896. options.named[key] = escapeHtml(options.named[key]);
  2897. }
  2898. });
  2899. }
  2900. }
  2901. function resolveMessageFormat(context, key, locale, fallbackLocale, fallbackWarn, missingWarn) {
  2902. const { messages, onWarn, messageResolver: resolveValue, localeFallbacker } = context;
  2903. const locales = localeFallbacker(context, fallbackLocale, locale); // eslint-disable-line @typescript-eslint/no-explicit-any
  2904. let message = {};
  2905. let targetLocale;
  2906. let format = null;
  2907. let from = locale;
  2908. let to = null;
  2909. const type = 'translate';
  2910. for (let i = 0; i < locales.length; i++) {
  2911. targetLocale = to = locales[i];
  2912. if (locale !== targetLocale &&
  2913. !isAlmostSameLocale(locale, targetLocale) &&
  2914. isTranslateFallbackWarn(fallbackWarn, key)) {
  2915. onWarn(getWarnMessage(CoreWarnCodes.FALLBACK_TO_TRANSLATE, {
  2916. key,
  2917. target: targetLocale
  2918. }));
  2919. }
  2920. // for vue-devtools timeline event
  2921. if (locale !== targetLocale) {
  2922. const emitter = context.__v_emitter;
  2923. if (emitter) {
  2924. emitter.emit("fallback" /* VueDevToolsTimelineEvents.FALBACK */, {
  2925. type,
  2926. key,
  2927. from,
  2928. to,
  2929. groupId: `${type}:${key}`
  2930. });
  2931. }
  2932. }
  2933. message =
  2934. messages[targetLocale] || {};
  2935. // for vue-devtools timeline event
  2936. let start = null;
  2937. let startTag;
  2938. let endTag;
  2939. if (inBrowser) {
  2940. start = window.performance.now();
  2941. startTag = 'intlify-message-resolve-start';
  2942. endTag = 'intlify-message-resolve-end';
  2943. mark && mark(startTag);
  2944. }
  2945. if ((format = resolveValue(message, key)) === null) {
  2946. // if null, resolve with object key path
  2947. format = message[key]; // eslint-disable-line @typescript-eslint/no-explicit-any
  2948. }
  2949. // for vue-devtools timeline event
  2950. if (inBrowser) {
  2951. const end = window.performance.now();
  2952. const emitter = context.__v_emitter;
  2953. if (emitter && start && format) {
  2954. emitter.emit("message-resolve" /* VueDevToolsTimelineEvents.MESSAGE_RESOLVE */, {
  2955. type: "message-resolve" /* VueDevToolsTimelineEvents.MESSAGE_RESOLVE */,
  2956. key,
  2957. message: format,
  2958. time: end - start,
  2959. groupId: `${type}:${key}`
  2960. });
  2961. }
  2962. if (startTag && endTag && mark && measure) {
  2963. mark(endTag);
  2964. measure('intlify message resolve', startTag, endTag);
  2965. }
  2966. }
  2967. if (isString(format) || isMessageAST(format) || isMessageFunction(format)) {
  2968. break;
  2969. }
  2970. if (!isImplicitFallback(targetLocale, locales)) {
  2971. const missingRet = handleMissing(context, // eslint-disable-line @typescript-eslint/no-explicit-any
  2972. key, targetLocale, missingWarn, type);
  2973. if (missingRet !== key) {
  2974. format = missingRet;
  2975. }
  2976. }
  2977. from = to;
  2978. }
  2979. return [format, targetLocale, message];
  2980. }
  2981. function compileMessageFormat(context, key, targetLocale, format, cacheBaseKey, onError) {
  2982. const { messageCompiler, warnHtmlMessage } = context;
  2983. if (isMessageFunction(format)) {
  2984. const msg = format;
  2985. msg.locale = msg.locale || targetLocale;
  2986. msg.key = msg.key || key;
  2987. return msg;
  2988. }
  2989. if (messageCompiler == null) {
  2990. const msg = (() => format);
  2991. msg.locale = targetLocale;
  2992. msg.key = key;
  2993. return msg;
  2994. }
  2995. // for vue-devtools timeline event
  2996. let start = null;
  2997. let startTag;
  2998. let endTag;
  2999. if (inBrowser) {
  3000. start = window.performance.now();
  3001. startTag = 'intlify-message-compilation-start';
  3002. endTag = 'intlify-message-compilation-end';
  3003. mark && mark(startTag);
  3004. }
  3005. const msg = messageCompiler(format, getCompileContext(context, targetLocale, cacheBaseKey, format, warnHtmlMessage, onError));
  3006. // for vue-devtools timeline event
  3007. if (inBrowser) {
  3008. const end = window.performance.now();
  3009. const emitter = context.__v_emitter;
  3010. if (emitter && start) {
  3011. emitter.emit("message-compilation" /* VueDevToolsTimelineEvents.MESSAGE_COMPILATION */, {
  3012. type: "message-compilation" /* VueDevToolsTimelineEvents.MESSAGE_COMPILATION */,
  3013. message: format,
  3014. time: end - start,
  3015. groupId: `${'translate'}:${key}`
  3016. });
  3017. }
  3018. if (startTag && endTag && mark && measure) {
  3019. mark(endTag);
  3020. measure('intlify message compilation', startTag, endTag);
  3021. }
  3022. }
  3023. msg.locale = targetLocale;
  3024. msg.key = key;
  3025. msg.source = format;
  3026. return msg;
  3027. }
  3028. function evaluateMessage(context, msg, msgCtx) {
  3029. // for vue-devtools timeline event
  3030. let start = null;
  3031. let startTag;
  3032. let endTag;
  3033. if (inBrowser) {
  3034. start = window.performance.now();
  3035. startTag = 'intlify-message-evaluation-start';
  3036. endTag = 'intlify-message-evaluation-end';
  3037. mark && mark(startTag);
  3038. }
  3039. const messaged = msg(msgCtx);
  3040. // for vue-devtools timeline event
  3041. if (inBrowser) {
  3042. const end = window.performance.now();
  3043. const emitter = context.__v_emitter;
  3044. if (emitter && start) {
  3045. emitter.emit("message-evaluation" /* VueDevToolsTimelineEvents.MESSAGE_EVALUATION */, {
  3046. type: "message-evaluation" /* VueDevToolsTimelineEvents.MESSAGE_EVALUATION */,
  3047. value: messaged,
  3048. time: end - start,
  3049. groupId: `${'translate'}:${msg.key}`
  3050. });
  3051. }
  3052. if (startTag && endTag && mark && measure) {
  3053. mark(endTag);
  3054. measure('intlify message evaluation', startTag, endTag);
  3055. }
  3056. }
  3057. return messaged;
  3058. }
  3059. /** @internal */
  3060. function parseTranslateArgs(...args) {
  3061. const [arg1, arg2, arg3] = args;
  3062. const options = {};
  3063. if (!isString(arg1) &&
  3064. !isNumber(arg1) &&
  3065. !isMessageFunction(arg1) &&
  3066. !isMessageAST(arg1)) {
  3067. throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
  3068. }
  3069. // prettier-ignore
  3070. const key = isNumber(arg1)
  3071. ? String(arg1)
  3072. : isMessageFunction(arg1)
  3073. ? arg1
  3074. : arg1;
  3075. if (isNumber(arg2)) {
  3076. options.plural = arg2;
  3077. }
  3078. else if (isString(arg2)) {
  3079. options.default = arg2;
  3080. }
  3081. else if (isPlainObject(arg2) && !isEmptyObject(arg2)) {
  3082. options.named = arg2;
  3083. }
  3084. else if (isArray(arg2)) {
  3085. options.list = arg2;
  3086. }
  3087. if (isNumber(arg3)) {
  3088. options.plural = arg3;
  3089. }
  3090. else if (isString(arg3)) {
  3091. options.default = arg3;
  3092. }
  3093. else if (isPlainObject(arg3)) {
  3094. assign(options, arg3);
  3095. }
  3096. return [key, options];
  3097. }
  3098. function getCompileContext(context, locale, key, source, warnHtmlMessage, onError) {
  3099. return {
  3100. locale,
  3101. key,
  3102. warnHtmlMessage,
  3103. onError: (err) => {
  3104. onError && onError(err);
  3105. {
  3106. const _source = getSourceForCodeFrame(source);
  3107. const message = `Message compilation error: ${err.message}`;
  3108. const codeFrame = err.location &&
  3109. _source &&
  3110. generateCodeFrame(_source, err.location.start.offset, err.location.end.offset);
  3111. const emitter = context.__v_emitter;
  3112. if (emitter && _source) {
  3113. emitter.emit("compile-error" /* VueDevToolsTimelineEvents.COMPILE_ERROR */, {
  3114. message: _source,
  3115. error: err.message,
  3116. start: err.location && err.location.start.offset,
  3117. end: err.location && err.location.end.offset,
  3118. groupId: `${'translate'}:${key}`
  3119. });
  3120. }
  3121. console.error(codeFrame ? `${message}\n${codeFrame}` : message);
  3122. }
  3123. },
  3124. onCacheKey: (source) => generateFormatCacheKey(locale, key, source)
  3125. };
  3126. }
  3127. function getSourceForCodeFrame(source) {
  3128. if (isString(source)) {
  3129. return source;
  3130. }
  3131. else {
  3132. if (source.loc && source.loc.source) {
  3133. return source.loc.source;
  3134. }
  3135. }
  3136. }
  3137. function getMessageContextOptions(context, locale, message, options) {
  3138. const { modifiers, pluralRules, messageResolver: resolveValue, fallbackLocale, fallbackWarn, missingWarn, fallbackContext } = context;
  3139. const resolveMessage = (key) => {
  3140. let val = resolveValue(message, key);
  3141. // fallback to root context
  3142. if (val == null && fallbackContext) {
  3143. const [, , message] = resolveMessageFormat(fallbackContext, key, locale, fallbackLocale, fallbackWarn, missingWarn);
  3144. val = resolveValue(message, key);
  3145. }
  3146. if (isString(val) || isMessageAST(val)) {
  3147. let occurred = false;
  3148. const onError = () => {
  3149. occurred = true;
  3150. };
  3151. const msg = compileMessageFormat(context, key, locale, val, key, onError);
  3152. return !occurred
  3153. ? msg
  3154. : NOOP_MESSAGE_FUNCTION;
  3155. }
  3156. else if (isMessageFunction(val)) {
  3157. return val;
  3158. }
  3159. else {
  3160. // TODO: should be implemented warning message
  3161. return NOOP_MESSAGE_FUNCTION;
  3162. }
  3163. };
  3164. const ctxOptions = {
  3165. locale,
  3166. modifiers,
  3167. pluralRules,
  3168. messages: resolveMessage
  3169. };
  3170. if (context.processor) {
  3171. ctxOptions.processor = context.processor;
  3172. }
  3173. if (options.list) {
  3174. ctxOptions.list = options.list;
  3175. }
  3176. if (options.named) {
  3177. ctxOptions.named = options.named;
  3178. }
  3179. if (isNumber(options.plural)) {
  3180. ctxOptions.pluralIndex = options.plural;
  3181. }
  3182. return ctxOptions;
  3183. }
  3184. const intlDefined = typeof Intl !== 'undefined';
  3185. const Availabilities = {
  3186. dateTimeFormat: intlDefined && typeof Intl.DateTimeFormat !== 'undefined',
  3187. numberFormat: intlDefined && typeof Intl.NumberFormat !== 'undefined'
  3188. };
  3189. // implementation of `datetime` function
  3190. function datetime(context, ...args) {
  3191. const { datetimeFormats, unresolving, fallbackLocale, onWarn, localeFallbacker } = context;
  3192. const { __datetimeFormatters } = context;
  3193. if (!Availabilities.dateTimeFormat) {
  3194. onWarn(getWarnMessage(CoreWarnCodes.CANNOT_FORMAT_DATE));
  3195. return MISSING_RESOLVE_VALUE;
  3196. }
  3197. const [key, value, options, overrides] = parseDateTimeArgs(...args);
  3198. const missingWarn = isBoolean(options.missingWarn)
  3199. ? options.missingWarn
  3200. : context.missingWarn;
  3201. const fallbackWarn = isBoolean(options.fallbackWarn)
  3202. ? options.fallbackWarn
  3203. : context.fallbackWarn;
  3204. const part = !!options.part;
  3205. const locale = getLocale(context, options);
  3206. const locales = localeFallbacker(context, // eslint-disable-line @typescript-eslint/no-explicit-any
  3207. fallbackLocale, locale);
  3208. if (!isString(key) || key === '') {
  3209. return new Intl.DateTimeFormat(locale, overrides).format(value);
  3210. }
  3211. // resolve format
  3212. let datetimeFormat = {};
  3213. let targetLocale;
  3214. let format = null;
  3215. let from = locale;
  3216. let to = null;
  3217. const type = 'datetime format';
  3218. for (let i = 0; i < locales.length; i++) {
  3219. targetLocale = to = locales[i];
  3220. if (locale !== targetLocale &&
  3221. isTranslateFallbackWarn(fallbackWarn, key)) {
  3222. onWarn(getWarnMessage(CoreWarnCodes.FALLBACK_TO_DATE_FORMAT, {
  3223. key,
  3224. target: targetLocale
  3225. }));
  3226. }
  3227. // for vue-devtools timeline event
  3228. if (locale !== targetLocale) {
  3229. const emitter = context.__v_emitter;
  3230. if (emitter) {
  3231. emitter.emit("fallback" /* VueDevToolsTimelineEvents.FALBACK */, {
  3232. type,
  3233. key,
  3234. from,
  3235. to,
  3236. groupId: `${type}:${key}`
  3237. });
  3238. }
  3239. }
  3240. datetimeFormat =
  3241. datetimeFormats[targetLocale] || {};
  3242. format = datetimeFormat[key];
  3243. if (isPlainObject(format))
  3244. break;
  3245. handleMissing(context, key, targetLocale, missingWarn, type); // eslint-disable-line @typescript-eslint/no-explicit-any
  3246. from = to;
  3247. }
  3248. // checking format and target locale
  3249. if (!isPlainObject(format) || !isString(targetLocale)) {
  3250. return unresolving ? NOT_REOSLVED : key;
  3251. }
  3252. let id = `${targetLocale}__${key}`;
  3253. if (!isEmptyObject(overrides)) {
  3254. id = `${id}__${JSON.stringify(overrides)}`;
  3255. }
  3256. let formatter = __datetimeFormatters.get(id);
  3257. if (!formatter) {
  3258. formatter = new Intl.DateTimeFormat(targetLocale, assign({}, format, overrides));
  3259. __datetimeFormatters.set(id, formatter);
  3260. }
  3261. return !part ? formatter.format(value) : formatter.formatToParts(value);
  3262. }
  3263. /** @internal */
  3264. const DATETIME_FORMAT_OPTIONS_KEYS = [
  3265. 'localeMatcher',
  3266. 'weekday',
  3267. 'era',
  3268. 'year',
  3269. 'month',
  3270. 'day',
  3271. 'hour',
  3272. 'minute',
  3273. 'second',
  3274. 'timeZoneName',
  3275. 'formatMatcher',
  3276. 'hour12',
  3277. 'timeZone',
  3278. 'dateStyle',
  3279. 'timeStyle',
  3280. 'calendar',
  3281. 'dayPeriod',
  3282. 'numberingSystem',
  3283. 'hourCycle',
  3284. 'fractionalSecondDigits'
  3285. ];
  3286. /** @internal */
  3287. function parseDateTimeArgs(...args) {
  3288. const [arg1, arg2, arg3, arg4] = args;
  3289. const options = {};
  3290. let overrides = {};
  3291. let value;
  3292. if (isString(arg1)) {
  3293. // Only allow ISO strings - other date formats are often supported,
  3294. // but may cause different results in different browsers.
  3295. const matches = arg1.match(/(\d{4}-\d{2}-\d{2})(T|\s)?(.*)/);
  3296. if (!matches) {
  3297. throw createCoreError(CoreErrorCodes.INVALID_ISO_DATE_ARGUMENT);
  3298. }
  3299. // Some browsers can not parse the iso datetime separated by space,
  3300. // this is a compromise solution by replace the 'T'/' ' with 'T'
  3301. const dateTime = matches[3]
  3302. ? matches[3].trim().startsWith('T')
  3303. ? `${matches[1].trim()}${matches[3].trim()}`
  3304. : `${matches[1].trim()}T${matches[3].trim()}`
  3305. : matches[1].trim();
  3306. value = new Date(dateTime);
  3307. try {
  3308. // This will fail if the date is not valid
  3309. value.toISOString();
  3310. }
  3311. catch (e) {
  3312. throw createCoreError(CoreErrorCodes.INVALID_ISO_DATE_ARGUMENT);
  3313. }
  3314. }
  3315. else if (isDate(arg1)) {
  3316. if (isNaN(arg1.getTime())) {
  3317. throw createCoreError(CoreErrorCodes.INVALID_DATE_ARGUMENT);
  3318. }
  3319. value = arg1;
  3320. }
  3321. else if (isNumber(arg1)) {
  3322. value = arg1;
  3323. }
  3324. else {
  3325. throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
  3326. }
  3327. if (isString(arg2)) {
  3328. options.key = arg2;
  3329. }
  3330. else if (isPlainObject(arg2)) {
  3331. Object.keys(arg2).forEach(key => {
  3332. if (DATETIME_FORMAT_OPTIONS_KEYS.includes(key)) {
  3333. overrides[key] = arg2[key];
  3334. }
  3335. else {
  3336. options[key] = arg2[key];
  3337. }
  3338. });
  3339. }
  3340. if (isString(arg3)) {
  3341. options.locale = arg3;
  3342. }
  3343. else if (isPlainObject(arg3)) {
  3344. overrides = arg3;
  3345. }
  3346. if (isPlainObject(arg4)) {
  3347. overrides = arg4;
  3348. }
  3349. return [options.key || '', value, options, overrides];
  3350. }
  3351. /** @internal */
  3352. function clearDateTimeFormat(ctx, locale, format) {
  3353. const context = ctx;
  3354. for (const key in format) {
  3355. const id = `${locale}__${key}`;
  3356. if (!context.__datetimeFormatters.has(id)) {
  3357. continue;
  3358. }
  3359. context.__datetimeFormatters.delete(id);
  3360. }
  3361. }
  3362. // implementation of `number` function
  3363. function number(context, ...args) {
  3364. const { numberFormats, unresolving, fallbackLocale, onWarn, localeFallbacker } = context;
  3365. const { __numberFormatters } = context;
  3366. if (!Availabilities.numberFormat) {
  3367. onWarn(getWarnMessage(CoreWarnCodes.CANNOT_FORMAT_NUMBER));
  3368. return MISSING_RESOLVE_VALUE;
  3369. }
  3370. const [key, value, options, overrides] = parseNumberArgs(...args);
  3371. const missingWarn = isBoolean(options.missingWarn)
  3372. ? options.missingWarn
  3373. : context.missingWarn;
  3374. const fallbackWarn = isBoolean(options.fallbackWarn)
  3375. ? options.fallbackWarn
  3376. : context.fallbackWarn;
  3377. const part = !!options.part;
  3378. const locale = getLocale(context, options);
  3379. const locales = localeFallbacker(context, // eslint-disable-line @typescript-eslint/no-explicit-any
  3380. fallbackLocale, locale);
  3381. if (!isString(key) || key === '') {
  3382. return new Intl.NumberFormat(locale, overrides).format(value);
  3383. }
  3384. // resolve format
  3385. let numberFormat = {};
  3386. let targetLocale;
  3387. let format = null;
  3388. let from = locale;
  3389. let to = null;
  3390. const type = 'number format';
  3391. for (let i = 0; i < locales.length; i++) {
  3392. targetLocale = to = locales[i];
  3393. if (locale !== targetLocale &&
  3394. isTranslateFallbackWarn(fallbackWarn, key)) {
  3395. onWarn(getWarnMessage(CoreWarnCodes.FALLBACK_TO_NUMBER_FORMAT, {
  3396. key,
  3397. target: targetLocale
  3398. }));
  3399. }
  3400. // for vue-devtools timeline event
  3401. if (locale !== targetLocale) {
  3402. const emitter = context.__v_emitter;
  3403. if (emitter) {
  3404. emitter.emit("fallback" /* VueDevToolsTimelineEvents.FALBACK */, {
  3405. type,
  3406. key,
  3407. from,
  3408. to,
  3409. groupId: `${type}:${key}`
  3410. });
  3411. }
  3412. }
  3413. numberFormat =
  3414. numberFormats[targetLocale] || {};
  3415. format = numberFormat[key];
  3416. if (isPlainObject(format))
  3417. break;
  3418. handleMissing(context, key, targetLocale, missingWarn, type); // eslint-disable-line @typescript-eslint/no-explicit-any
  3419. from = to;
  3420. }
  3421. // checking format and target locale
  3422. if (!isPlainObject(format) || !isString(targetLocale)) {
  3423. return unresolving ? NOT_REOSLVED : key;
  3424. }
  3425. let id = `${targetLocale}__${key}`;
  3426. if (!isEmptyObject(overrides)) {
  3427. id = `${id}__${JSON.stringify(overrides)}`;
  3428. }
  3429. let formatter = __numberFormatters.get(id);
  3430. if (!formatter) {
  3431. formatter = new Intl.NumberFormat(targetLocale, assign({}, format, overrides));
  3432. __numberFormatters.set(id, formatter);
  3433. }
  3434. return !part ? formatter.format(value) : formatter.formatToParts(value);
  3435. }
  3436. /** @internal */
  3437. const NUMBER_FORMAT_OPTIONS_KEYS = [
  3438. 'localeMatcher',
  3439. 'style',
  3440. 'currency',
  3441. 'currencyDisplay',
  3442. 'currencySign',
  3443. 'useGrouping',
  3444. 'minimumIntegerDigits',
  3445. 'minimumFractionDigits',
  3446. 'maximumFractionDigits',
  3447. 'minimumSignificantDigits',
  3448. 'maximumSignificantDigits',
  3449. 'compactDisplay',
  3450. 'notation',
  3451. 'signDisplay',
  3452. 'unit',
  3453. 'unitDisplay',
  3454. 'roundingMode',
  3455. 'roundingPriority',
  3456. 'roundingIncrement',
  3457. 'trailingZeroDisplay'
  3458. ];
  3459. /** @internal */
  3460. function parseNumberArgs(...args) {
  3461. const [arg1, arg2, arg3, arg4] = args;
  3462. const options = {};
  3463. let overrides = {};
  3464. if (!isNumber(arg1)) {
  3465. throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
  3466. }
  3467. const value = arg1;
  3468. if (isString(arg2)) {
  3469. options.key = arg2;
  3470. }
  3471. else if (isPlainObject(arg2)) {
  3472. Object.keys(arg2).forEach(key => {
  3473. if (NUMBER_FORMAT_OPTIONS_KEYS.includes(key)) {
  3474. overrides[key] = arg2[key];
  3475. }
  3476. else {
  3477. options[key] = arg2[key];
  3478. }
  3479. });
  3480. }
  3481. if (isString(arg3)) {
  3482. options.locale = arg3;
  3483. }
  3484. else if (isPlainObject(arg3)) {
  3485. overrides = arg3;
  3486. }
  3487. if (isPlainObject(arg4)) {
  3488. overrides = arg4;
  3489. }
  3490. return [options.key || '', value, options, overrides];
  3491. }
  3492. /** @internal */
  3493. function clearNumberFormat(ctx, locale, format) {
  3494. const context = ctx;
  3495. for (const key in format) {
  3496. const id = `${locale}__${key}`;
  3497. if (!context.__numberFormatters.has(id)) {
  3498. continue;
  3499. }
  3500. context.__numberFormatters.delete(id);
  3501. }
  3502. }
  3503. exports.CompileErrorCodes = CompileErrorCodes;
  3504. exports.CoreErrorCodes = CoreErrorCodes;
  3505. exports.CoreWarnCodes = CoreWarnCodes;
  3506. exports.DATETIME_FORMAT_OPTIONS_KEYS = DATETIME_FORMAT_OPTIONS_KEYS;
  3507. exports.DEFAULT_LOCALE = DEFAULT_LOCALE;
  3508. exports.DEFAULT_MESSAGE_DATA_TYPE = DEFAULT_MESSAGE_DATA_TYPE;
  3509. exports.MISSING_RESOLVE_VALUE = MISSING_RESOLVE_VALUE;
  3510. exports.NOT_REOSLVED = NOT_REOSLVED;
  3511. exports.NUMBER_FORMAT_OPTIONS_KEYS = NUMBER_FORMAT_OPTIONS_KEYS;
  3512. exports.VERSION = VERSION;
  3513. exports.clearCompileCache = clearCompileCache;
  3514. exports.clearDateTimeFormat = clearDateTimeFormat;
  3515. exports.clearNumberFormat = clearNumberFormat;
  3516. exports.compile = compile;
  3517. exports.compileToFunction = compileToFunction;
  3518. exports.createCompileError = createCompileError;
  3519. exports.createCoreContext = createCoreContext;
  3520. exports.createCoreError = createCoreError;
  3521. exports.createMessageContext = createMessageContext;
  3522. exports.datetime = datetime;
  3523. exports.fallbackWithLocaleChain = fallbackWithLocaleChain;
  3524. exports.fallbackWithSimple = fallbackWithSimple;
  3525. exports.getAdditionalMeta = getAdditionalMeta;
  3526. exports.getDevToolsHook = getDevToolsHook;
  3527. exports.getFallbackContext = getFallbackContext;
  3528. exports.getLocale = getLocale;
  3529. exports.getWarnMessage = getWarnMessage;
  3530. exports.handleMissing = handleMissing;
  3531. exports.initI18nDevTools = initI18nDevTools;
  3532. exports.isAlmostSameLocale = isAlmostSameLocale;
  3533. exports.isImplicitFallback = isImplicitFallback;
  3534. exports.isMessageAST = isMessageAST;
  3535. exports.isMessageFunction = isMessageFunction;
  3536. exports.isTranslateFallbackWarn = isTranslateFallbackWarn;
  3537. exports.isTranslateMissingWarn = isTranslateMissingWarn;
  3538. exports.number = number;
  3539. exports.parse = parse;
  3540. exports.parseDateTimeArgs = parseDateTimeArgs;
  3541. exports.parseNumberArgs = parseNumberArgs;
  3542. exports.parseTranslateArgs = parseTranslateArgs;
  3543. exports.registerLocaleFallbacker = registerLocaleFallbacker;
  3544. exports.registerMessageCompiler = registerMessageCompiler;
  3545. exports.registerMessageResolver = registerMessageResolver;
  3546. exports.resolveLocale = resolveLocale;
  3547. exports.resolveValue = resolveValue;
  3548. exports.resolveWithKeyValue = resolveWithKeyValue;
  3549. exports.setAdditionalMeta = setAdditionalMeta;
  3550. exports.setDevToolsHook = setDevToolsHook;
  3551. exports.setFallbackContext = setFallbackContext;
  3552. exports.translate = translate;
  3553. exports.translateDevTools = translateDevTools;
  3554. exports.updateFallbackLocale = updateFallbackLocale;
  3555. return exports;
  3556. })({});