/*!
  * core-base v9.2.2
  * (c) 2022 kazuya kawaguchi
  * Released under the MIT License.
  */
var IntlifyCoreBase = (function (exports) {
  'use strict';

  /**
   * Original Utilities
   * written by kazuya kawaguchi
   */
  const inBrowser = typeof window !== 'undefined';
  let mark;
  let measure;
  {
      const perf = inBrowser && window.performance;
      if (perf &&
          perf.mark &&
          perf.measure &&
          perf.clearMarks &&
          perf.clearMeasures) {
          mark = (tag) => perf.mark(tag);
          measure = (name, startTag, endTag) => {
              perf.measure(name, startTag, endTag);
              perf.clearMarks(startTag);
              perf.clearMarks(endTag);
          };
      }
  }
  const RE_ARGS = /\{([0-9a-zA-Z]+)\}/g;
  /* eslint-disable */
  function format(message, ...args) {
      if (args.length === 1 && isObject(args[0])) {
          args = args[0];
      }
      if (!args || !args.hasOwnProperty) {
          args = {};
      }
      return message.replace(RE_ARGS, (match, identifier) => {
          return args.hasOwnProperty(identifier) ? args[identifier] : '';
      });
  }
  const generateFormatCacheKey = (locale, key, source) => friendlyJSONstringify({ l: locale, k: key, s: source });
  const friendlyJSONstringify = (json) => JSON.stringify(json)
      .replace(/\u2028/g, '\\u2028')
      .replace(/\u2029/g, '\\u2029')
      .replace(/\u0027/g, '\\u0027');
  const isNumber = (val) => typeof val === 'number' && isFinite(val);
  const isDate = (val) => toTypeString(val) === '[object Date]';
  const isRegExp = (val) => toTypeString(val) === '[object RegExp]';
  const isEmptyObject = (val) => isPlainObject(val) && Object.keys(val).length === 0;
  function warn(msg, err) {
      if (typeof console !== 'undefined') {
          console.warn(`[intlify] ` + msg);
          /* istanbul ignore if */
          if (err) {
              console.warn(err.stack);
          }
      }
  }
  const assign = Object.assign;
  function escapeHtml(rawText) {
      return rawText
          .replace(/</g, '&lt;')
          .replace(/>/g, '&gt;')
          .replace(/"/g, '&quot;')
          .replace(/'/g, '&apos;');
  }
  /* eslint-enable */
  /**
   * Useful Utilities By Evan you
   * Modified by kazuya kawaguchi
   * MIT License
   * https://github.com/vuejs/vue-next/blob/master/packages/shared/src/index.ts
   * https://github.com/vuejs/vue-next/blob/master/packages/shared/src/codeframe.ts
   */
  const isArray = Array.isArray;
  const isFunction = (val) => typeof val === 'function';
  const isString = (val) => typeof val === 'string';
  const isBoolean = (val) => typeof val === 'boolean';
  const isObject = (val) => // eslint-disable-line
   val !== null && typeof val === 'object';
  const objectToString = Object.prototype.toString;
  const toTypeString = (value) => objectToString.call(value);
  const isPlainObject = (val) => toTypeString(val) === '[object Object]';
  // for converting list and named values to displayed strings.
  const toDisplayString = (val) => {
      return val == null
          ? ''
          : isArray(val) || (isPlainObject(val) && val.toString === objectToString)
              ? JSON.stringify(val, null, 2)
              : String(val);
  };
  const RANGE = 2;
  function generateCodeFrame(source, start = 0, end = source.length) {
      const lines = source.split(/\r?\n/);
      let count = 0;
      const res = [];
      for (let i = 0; i < lines.length; i++) {
          count += lines[i].length + 1;
          if (count >= start) {
              for (let j = i - RANGE; j <= i + RANGE || end > count; j++) {
                  if (j < 0 || j >= lines.length)
                      continue;
                  const line = j + 1;
                  res.push(`${line}${' '.repeat(3 - String(line).length)}|  ${lines[j]}`);
                  const lineLength = lines[j].length;
                  if (j === i) {
                      // push underline
                      const pad = start - (count - lineLength) + 1;
                      const length = Math.max(1, end > count ? lineLength - pad : end - start);
                      res.push(`   |  ` + ' '.repeat(pad) + '^'.repeat(length));
                  }
                  else if (j > i) {
                      if (end > count) {
                          const length = Math.max(Math.min(end - count, lineLength), 1);
                          res.push(`   |  ` + '^'.repeat(length));
                      }
                      count += lineLength + 1;
                  }
              }
              break;
          }
      }
      return res.join('\n');
  }

  const CompileErrorCodes = {
      // tokenizer error codes
      EXPECTED_TOKEN: 1,
      INVALID_TOKEN_IN_PLACEHOLDER: 2,
      UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER: 3,
      UNKNOWN_ESCAPE_SEQUENCE: 4,
      INVALID_UNICODE_ESCAPE_SEQUENCE: 5,
      UNBALANCED_CLOSING_BRACE: 6,
      UNTERMINATED_CLOSING_BRACE: 7,
      EMPTY_PLACEHOLDER: 8,
      NOT_ALLOW_NEST_PLACEHOLDER: 9,
      INVALID_LINKED_FORMAT: 10,
      // parser error codes
      MUST_HAVE_MESSAGES_IN_PLURAL: 11,
      UNEXPECTED_EMPTY_LINKED_MODIFIER: 12,
      UNEXPECTED_EMPTY_LINKED_KEY: 13,
      UNEXPECTED_LEXICAL_ANALYSIS: 14,
      // Special value for higher-order compilers to pick up the last code
      // to avoid collision of error codes. This should always be kept as the last
      // item.
      __EXTEND_POINT__: 15
  };
  /** @internal */
  const errorMessages$1 = {
      // tokenizer error messages
      [CompileErrorCodes.EXPECTED_TOKEN]: `Expected token: '{0}'`,
      [CompileErrorCodes.INVALID_TOKEN_IN_PLACEHOLDER]: `Invalid token in placeholder: '{0}'`,
      [CompileErrorCodes.UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER]: `Unterminated single quote in placeholder`,
      [CompileErrorCodes.UNKNOWN_ESCAPE_SEQUENCE]: `Unknown escape sequence: \\{0}`,
      [CompileErrorCodes.INVALID_UNICODE_ESCAPE_SEQUENCE]: `Invalid unicode escape sequence: {0}`,
      [CompileErrorCodes.UNBALANCED_CLOSING_BRACE]: `Unbalanced closing brace`,
      [CompileErrorCodes.UNTERMINATED_CLOSING_BRACE]: `Unterminated closing brace`,
      [CompileErrorCodes.EMPTY_PLACEHOLDER]: `Empty placeholder`,
      [CompileErrorCodes.NOT_ALLOW_NEST_PLACEHOLDER]: `Not allowed nest placeholder`,
      [CompileErrorCodes.INVALID_LINKED_FORMAT]: `Invalid linked format`,
      // parser error messages
      [CompileErrorCodes.MUST_HAVE_MESSAGES_IN_PLURAL]: `Plural must have messages`,
      [CompileErrorCodes.UNEXPECTED_EMPTY_LINKED_MODIFIER]: `Unexpected empty linked modifier`,
      [CompileErrorCodes.UNEXPECTED_EMPTY_LINKED_KEY]: `Unexpected empty linked key`,
      [CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS]: `Unexpected lexical analysis in token: '{0}'`
  };
  function createCompileError(code, loc, options = {}) {
      const { domain, messages, args } = options;
      const msg = format((messages || errorMessages$1)[code] || '', ...(args || []))
          ;
      const error = new SyntaxError(String(msg));
      error.code = code;
      if (loc) {
          error.location = loc;
      }
      error.domain = domain;
      return error;
  }
  /** @internal */
  function defaultOnError(error) {
      throw error;
  }

  function createPosition(line, column, offset) {
      return { line, column, offset };
  }
  function createLocation(start, end, source) {
      const loc = { start, end };
      if (source != null) {
          loc.source = source;
      }
      return loc;
  }

  const CHAR_SP = ' ';
  const CHAR_CR = '\r';
  const CHAR_LF = '\n';
  const CHAR_LS = String.fromCharCode(0x2028);
  const CHAR_PS = String.fromCharCode(0x2029);
  function createScanner(str) {
      const _buf = str;
      let _index = 0;
      let _line = 1;
      let _column = 1;
      let _peekOffset = 0;
      const isCRLF = (index) => _buf[index] === CHAR_CR && _buf[index + 1] === CHAR_LF;
      const isLF = (index) => _buf[index] === CHAR_LF;
      const isPS = (index) => _buf[index] === CHAR_PS;
      const isLS = (index) => _buf[index] === CHAR_LS;
      const isLineEnd = (index) => isCRLF(index) || isLF(index) || isPS(index) || isLS(index);
      const index = () => _index;
      const line = () => _line;
      const column = () => _column;
      const peekOffset = () => _peekOffset;
      const charAt = (offset) => isCRLF(offset) || isPS(offset) || isLS(offset) ? CHAR_LF : _buf[offset];
      const currentChar = () => charAt(_index);
      const currentPeek = () => charAt(_index + _peekOffset);
      function next() {
          _peekOffset = 0;
          if (isLineEnd(_index)) {
              _line++;
              _column = 0;
          }
          if (isCRLF(_index)) {
              _index++;
          }
          _index++;
          _column++;
          return _buf[_index];
      }
      function peek() {
          if (isCRLF(_index + _peekOffset)) {
              _peekOffset++;
          }
          _peekOffset++;
          return _buf[_index + _peekOffset];
      }
      function reset() {
          _index = 0;
          _line = 1;
          _column = 1;
          _peekOffset = 0;
      }
      function resetPeek(offset = 0) {
          _peekOffset = offset;
      }
      function skipToPeek() {
          const target = _index + _peekOffset;
          // eslint-disable-next-line no-unmodified-loop-condition
          while (target !== _index) {
              next();
          }
          _peekOffset = 0;
      }
      return {
          index,
          line,
          column,
          peekOffset,
          charAt,
          currentChar,
          currentPeek,
          next,
          peek,
          reset,
          resetPeek,
          skipToPeek
      };
  }

  const EOF = undefined;
  const LITERAL_DELIMITER = "'";
  const ERROR_DOMAIN$1 = 'tokenizer';
  function createTokenizer(source, options = {}) {
      const location = options.location !== false;
      const _scnr = createScanner(source);
      const currentOffset = () => _scnr.index();
      const currentPosition = () => createPosition(_scnr.line(), _scnr.column(), _scnr.index());
      const _initLoc = currentPosition();
      const _initOffset = currentOffset();
      const _context = {
          currentType: 14 /* EOF */,
          offset: _initOffset,
          startLoc: _initLoc,
          endLoc: _initLoc,
          lastType: 14 /* EOF */,
          lastOffset: _initOffset,
          lastStartLoc: _initLoc,
          lastEndLoc: _initLoc,
          braceNest: 0,
          inLinked: false,
          text: ''
      };
      const context = () => _context;
      const { onError } = options;
      function emitError(code, pos, offset, ...args) {
          const ctx = context();
          pos.column += offset;
          pos.offset += offset;
          if (onError) {
              const loc = createLocation(ctx.startLoc, pos);
              const err = createCompileError(code, loc, {
                  domain: ERROR_DOMAIN$1,
                  args
              });
              onError(err);
          }
      }
      function getToken(context, type, value) {
          context.endLoc = currentPosition();
          context.currentType = type;
          const token = { type };
          if (location) {
              token.loc = createLocation(context.startLoc, context.endLoc);
          }
          if (value != null) {
              token.value = value;
          }
          return token;
      }
      const getEndToken = (context) => getToken(context, 14 /* EOF */);
      function eat(scnr, ch) {
          if (scnr.currentChar() === ch) {
              scnr.next();
              return ch;
          }
          else {
              emitError(CompileErrorCodes.EXPECTED_TOKEN, currentPosition(), 0, ch);
              return '';
          }
      }
      function peekSpaces(scnr) {
          let buf = '';
          while (scnr.currentPeek() === CHAR_SP || scnr.currentPeek() === CHAR_LF) {
              buf += scnr.currentPeek();
              scnr.peek();
          }
          return buf;
      }
      function skipSpaces(scnr) {
          const buf = peekSpaces(scnr);
          scnr.skipToPeek();
          return buf;
      }
      function isIdentifierStart(ch) {
          if (ch === EOF) {
              return false;
          }
          const cc = ch.charCodeAt(0);
          return ((cc >= 97 && cc <= 122) || // a-z
              (cc >= 65 && cc <= 90) || // A-Z
              cc === 95 // _
          );
      }
      function isNumberStart(ch) {
          if (ch === EOF) {
              return false;
          }
          const cc = ch.charCodeAt(0);
          return cc >= 48 && cc <= 57; // 0-9
      }
      function isNamedIdentifierStart(scnr, context) {
          const { currentType } = context;
          if (currentType !== 2 /* BraceLeft */) {
              return false;
          }
          peekSpaces(scnr);
          const ret = isIdentifierStart(scnr.currentPeek());
          scnr.resetPeek();
          return ret;
      }
      function isListIdentifierStart(scnr, context) {
          const { currentType } = context;
          if (currentType !== 2 /* BraceLeft */) {
              return false;
          }
          peekSpaces(scnr);
          const ch = scnr.currentPeek() === '-' ? scnr.peek() : scnr.currentPeek();
          const ret = isNumberStart(ch);
          scnr.resetPeek();
          return ret;
      }
      function isLiteralStart(scnr, context) {
          const { currentType } = context;
          if (currentType !== 2 /* BraceLeft */) {
              return false;
          }
          peekSpaces(scnr);
          const ret = scnr.currentPeek() === LITERAL_DELIMITER;
          scnr.resetPeek();
          return ret;
      }
      function isLinkedDotStart(scnr, context) {
          const { currentType } = context;
          if (currentType !== 8 /* LinkedAlias */) {
              return false;
          }
          peekSpaces(scnr);
          const ret = scnr.currentPeek() === "." /* LinkedDot */;
          scnr.resetPeek();
          return ret;
      }
      function isLinkedModifierStart(scnr, context) {
          const { currentType } = context;
          if (currentType !== 9 /* LinkedDot */) {
              return false;
          }
          peekSpaces(scnr);
          const ret = isIdentifierStart(scnr.currentPeek());
          scnr.resetPeek();
          return ret;
      }
      function isLinkedDelimiterStart(scnr, context) {
          const { currentType } = context;
          if (!(currentType === 8 /* LinkedAlias */ ||
              currentType === 12 /* LinkedModifier */)) {
              return false;
          }
          peekSpaces(scnr);
          const ret = scnr.currentPeek() === ":" /* LinkedDelimiter */;
          scnr.resetPeek();
          return ret;
      }
      function isLinkedReferStart(scnr, context) {
          const { currentType } = context;
          if (currentType !== 10 /* LinkedDelimiter */) {
              return false;
          }
          const fn = () => {
              const ch = scnr.currentPeek();
              if (ch === "{" /* BraceLeft */) {
                  return isIdentifierStart(scnr.peek());
              }
              else if (ch === "@" /* LinkedAlias */ ||
                  ch === "%" /* Modulo */ ||
                  ch === "|" /* Pipe */ ||
                  ch === ":" /* LinkedDelimiter */ ||
                  ch === "." /* LinkedDot */ ||
                  ch === CHAR_SP ||
                  !ch) {
                  return false;
              }
              else if (ch === CHAR_LF) {
                  scnr.peek();
                  return fn();
              }
              else {
                  // other characters
                  return isIdentifierStart(ch);
              }
          };
          const ret = fn();
          scnr.resetPeek();
          return ret;
      }
      function isPluralStart(scnr) {
          peekSpaces(scnr);
          const ret = scnr.currentPeek() === "|" /* Pipe */;
          scnr.resetPeek();
          return ret;
      }
      function detectModuloStart(scnr) {
          const spaces = peekSpaces(scnr);
          const ret = scnr.currentPeek() === "%" /* Modulo */ &&
              scnr.peek() === "{" /* BraceLeft */;
          scnr.resetPeek();
          return {
              isModulo: ret,
              hasSpace: spaces.length > 0
          };
      }
      function isTextStart(scnr, reset = true) {
          const fn = (hasSpace = false, prev = '', detectModulo = false) => {
              const ch = scnr.currentPeek();
              if (ch === "{" /* BraceLeft */) {
                  return prev === "%" /* Modulo */ ? false : hasSpace;
              }
              else if (ch === "@" /* LinkedAlias */ || !ch) {
                  return prev === "%" /* Modulo */ ? true : hasSpace;
              }
              else if (ch === "%" /* Modulo */) {
                  scnr.peek();
                  return fn(hasSpace, "%" /* Modulo */, true);
              }
              else if (ch === "|" /* Pipe */) {
                  return prev === "%" /* Modulo */ || detectModulo
                      ? true
                      : !(prev === CHAR_SP || prev === CHAR_LF);
              }
              else if (ch === CHAR_SP) {
                  scnr.peek();
                  return fn(true, CHAR_SP, detectModulo);
              }
              else if (ch === CHAR_LF) {
                  scnr.peek();
                  return fn(true, CHAR_LF, detectModulo);
              }
              else {
                  return true;
              }
          };
          const ret = fn();
          reset && scnr.resetPeek();
          return ret;
      }
      function takeChar(scnr, fn) {
          const ch = scnr.currentChar();
          if (ch === EOF) {
              return EOF;
          }
          if (fn(ch)) {
              scnr.next();
              return ch;
          }
          return null;
      }
      function takeIdentifierChar(scnr) {
          const closure = (ch) => {
              const cc = ch.charCodeAt(0);
              return ((cc >= 97 && cc <= 122) || // a-z
                  (cc >= 65 && cc <= 90) || // A-Z
                  (cc >= 48 && cc <= 57) || // 0-9
                  cc === 95 || // _
                  cc === 36 // $
              );
          };
          return takeChar(scnr, closure);
      }
      function takeDigit(scnr) {
          const closure = (ch) => {
              const cc = ch.charCodeAt(0);
              return cc >= 48 && cc <= 57; // 0-9
          };
          return takeChar(scnr, closure);
      }
      function takeHexDigit(scnr) {
          const closure = (ch) => {
              const cc = ch.charCodeAt(0);
              return ((cc >= 48 && cc <= 57) || // 0-9
                  (cc >= 65 && cc <= 70) || // A-F
                  (cc >= 97 && cc <= 102)); // a-f
          };
          return takeChar(scnr, closure);
      }
      function getDigits(scnr) {
          let ch = '';
          let num = '';
          while ((ch = takeDigit(scnr))) {
              num += ch;
          }
          return num;
      }
      function readModulo(scnr) {
          skipSpaces(scnr);
          const ch = scnr.currentChar();
          if (ch !== "%" /* Modulo */) {
              emitError(CompileErrorCodes.EXPECTED_TOKEN, currentPosition(), 0, ch);
          }
          scnr.next();
          return "%" /* Modulo */;
      }
      function readText(scnr) {
          let buf = '';
          while (true) {
              const ch = scnr.currentChar();
              if (ch === "{" /* BraceLeft */ ||
                  ch === "}" /* BraceRight */ ||
                  ch === "@" /* LinkedAlias */ ||
                  ch === "|" /* Pipe */ ||
                  !ch) {
                  break;
              }
              else if (ch === "%" /* Modulo */) {
                  if (isTextStart(scnr)) {
                      buf += ch;
                      scnr.next();
                  }
                  else {
                      break;
                  }
              }
              else if (ch === CHAR_SP || ch === CHAR_LF) {
                  if (isTextStart(scnr)) {
                      buf += ch;
                      scnr.next();
                  }
                  else if (isPluralStart(scnr)) {
                      break;
                  }
                  else {
                      buf += ch;
                      scnr.next();
                  }
              }
              else {
                  buf += ch;
                  scnr.next();
              }
          }
          return buf;
      }
      function readNamedIdentifier(scnr) {
          skipSpaces(scnr);
          let ch = '';
          let name = '';
          while ((ch = takeIdentifierChar(scnr))) {
              name += ch;
          }
          if (scnr.currentChar() === EOF) {
              emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
          }
          return name;
      }
      function readListIdentifier(scnr) {
          skipSpaces(scnr);
          let value = '';
          if (scnr.currentChar() === '-') {
              scnr.next();
              value += `-${getDigits(scnr)}`;
          }
          else {
              value += getDigits(scnr);
          }
          if (scnr.currentChar() === EOF) {
              emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
          }
          return value;
      }
      function readLiteral(scnr) {
          skipSpaces(scnr);
          eat(scnr, `\'`);
          let ch = '';
          let literal = '';
          const fn = (x) => x !== LITERAL_DELIMITER && x !== CHAR_LF;
          while ((ch = takeChar(scnr, fn))) {
              if (ch === '\\') {
                  literal += readEscapeSequence(scnr);
              }
              else {
                  literal += ch;
              }
          }
          const current = scnr.currentChar();
          if (current === CHAR_LF || current === EOF) {
              emitError(CompileErrorCodes.UNTERMINATED_SINGLE_QUOTE_IN_PLACEHOLDER, currentPosition(), 0);
              // TODO: Is it correct really?
              if (current === CHAR_LF) {
                  scnr.next();
                  eat(scnr, `\'`);
              }
              return literal;
          }
          eat(scnr, `\'`);
          return literal;
      }
      function readEscapeSequence(scnr) {
          const ch = scnr.currentChar();
          switch (ch) {
              case '\\':
              case `\'`:
                  scnr.next();
                  return `\\${ch}`;
              case 'u':
                  return readUnicodeEscapeSequence(scnr, ch, 4);
              case 'U':
                  return readUnicodeEscapeSequence(scnr, ch, 6);
              default:
                  emitError(CompileErrorCodes.UNKNOWN_ESCAPE_SEQUENCE, currentPosition(), 0, ch);
                  return '';
          }
      }
      function readUnicodeEscapeSequence(scnr, unicode, digits) {
          eat(scnr, unicode);
          let sequence = '';
          for (let i = 0; i < digits; i++) {
              const ch = takeHexDigit(scnr);
              if (!ch) {
                  emitError(CompileErrorCodes.INVALID_UNICODE_ESCAPE_SEQUENCE, currentPosition(), 0, `\\${unicode}${sequence}${scnr.currentChar()}`);
                  break;
              }
              sequence += ch;
          }
          return `\\${unicode}${sequence}`;
      }
      function readInvalidIdentifier(scnr) {
          skipSpaces(scnr);
          let ch = '';
          let identifiers = '';
          const closure = (ch) => ch !== "{" /* BraceLeft */ &&
              ch !== "}" /* BraceRight */ &&
              ch !== CHAR_SP &&
              ch !== CHAR_LF;
          while ((ch = takeChar(scnr, closure))) {
              identifiers += ch;
          }
          return identifiers;
      }
      function readLinkedModifier(scnr) {
          let ch = '';
          let name = '';
          while ((ch = takeIdentifierChar(scnr))) {
              name += ch;
          }
          return name;
      }
      function readLinkedRefer(scnr) {
          const fn = (detect = false, buf) => {
              const ch = scnr.currentChar();
              if (ch === "{" /* BraceLeft */ ||
                  ch === "%" /* Modulo */ ||
                  ch === "@" /* LinkedAlias */ ||
                  ch === "|" /* Pipe */ ||
                  !ch) {
                  return buf;
              }
              else if (ch === CHAR_SP) {
                  return buf;
              }
              else if (ch === CHAR_LF) {
                  buf += ch;
                  scnr.next();
                  return fn(detect, buf);
              }
              else {
                  buf += ch;
                  scnr.next();
                  return fn(true, buf);
              }
          };
          return fn(false, '');
      }
      function readPlural(scnr) {
          skipSpaces(scnr);
          const plural = eat(scnr, "|" /* Pipe */);
          skipSpaces(scnr);
          return plural;
      }
      // TODO: We need refactoring of token parsing ...
      function readTokenInPlaceholder(scnr, context) {
          let token = null;
          const ch = scnr.currentChar();
          switch (ch) {
              case "{" /* BraceLeft */:
                  if (context.braceNest >= 1) {
                      emitError(CompileErrorCodes.NOT_ALLOW_NEST_PLACEHOLDER, currentPosition(), 0);
                  }
                  scnr.next();
                  token = getToken(context, 2 /* BraceLeft */, "{" /* BraceLeft */);
                  skipSpaces(scnr);
                  context.braceNest++;
                  return token;
              case "}" /* BraceRight */:
                  if (context.braceNest > 0 &&
                      context.currentType === 2 /* BraceLeft */) {
                      emitError(CompileErrorCodes.EMPTY_PLACEHOLDER, currentPosition(), 0);
                  }
                  scnr.next();
                  token = getToken(context, 3 /* BraceRight */, "}" /* BraceRight */);
                  context.braceNest--;
                  context.braceNest > 0 && skipSpaces(scnr);
                  if (context.inLinked && context.braceNest === 0) {
                      context.inLinked = false;
                  }
                  return token;
              case "@" /* LinkedAlias */:
                  if (context.braceNest > 0) {
                      emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
                  }
                  token = readTokenInLinked(scnr, context) || getEndToken(context);
                  context.braceNest = 0;
                  return token;
              default:
                  let validNamedIdentifier = true;
                  let validListIdentifier = true;
                  let validLiteral = true;
                  if (isPluralStart(scnr)) {
                      if (context.braceNest > 0) {
                          emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
                      }
                      token = getToken(context, 1 /* Pipe */, readPlural(scnr));
                      // reset
                      context.braceNest = 0;
                      context.inLinked = false;
                      return token;
                  }
                  if (context.braceNest > 0 &&
                      (context.currentType === 5 /* Named */ ||
                          context.currentType === 6 /* List */ ||
                          context.currentType === 7 /* Literal */)) {
                      emitError(CompileErrorCodes.UNTERMINATED_CLOSING_BRACE, currentPosition(), 0);
                      context.braceNest = 0;
                      return readToken(scnr, context);
                  }
                  if ((validNamedIdentifier = isNamedIdentifierStart(scnr, context))) {
                      token = getToken(context, 5 /* Named */, readNamedIdentifier(scnr));
                      skipSpaces(scnr);
                      return token;
                  }
                  if ((validListIdentifier = isListIdentifierStart(scnr, context))) {
                      token = getToken(context, 6 /* List */, readListIdentifier(scnr));
                      skipSpaces(scnr);
                      return token;
                  }
                  if ((validLiteral = isLiteralStart(scnr, context))) {
                      token = getToken(context, 7 /* Literal */, readLiteral(scnr));
                      skipSpaces(scnr);
                      return token;
                  }
                  if (!validNamedIdentifier && !validListIdentifier && !validLiteral) {
                      // TODO: we should be re-designed invalid cases, when we will extend message syntax near the future ...
                      token = getToken(context, 13 /* InvalidPlace */, readInvalidIdentifier(scnr));
                      emitError(CompileErrorCodes.INVALID_TOKEN_IN_PLACEHOLDER, currentPosition(), 0, token.value);
                      skipSpaces(scnr);
                      return token;
                  }
                  break;
          }
          return token;
      }
      // TODO: We need refactoring of token parsing ...
      function readTokenInLinked(scnr, context) {
          const { currentType } = context;
          let token = null;
          const ch = scnr.currentChar();
          if ((currentType === 8 /* LinkedAlias */ ||
              currentType === 9 /* LinkedDot */ ||
              currentType === 12 /* LinkedModifier */ ||
              currentType === 10 /* LinkedDelimiter */) &&
              (ch === CHAR_LF || ch === CHAR_SP)) {
              emitError(CompileErrorCodes.INVALID_LINKED_FORMAT, currentPosition(), 0);
          }
          switch (ch) {
              case "@" /* LinkedAlias */:
                  scnr.next();
                  token = getToken(context, 8 /* LinkedAlias */, "@" /* LinkedAlias */);
                  context.inLinked = true;
                  return token;
              case "." /* LinkedDot */:
                  skipSpaces(scnr);
                  scnr.next();
                  return getToken(context, 9 /* LinkedDot */, "." /* LinkedDot */);
              case ":" /* LinkedDelimiter */:
                  skipSpaces(scnr);
                  scnr.next();
                  return getToken(context, 10 /* LinkedDelimiter */, ":" /* LinkedDelimiter */);
              default:
                  if (isPluralStart(scnr)) {
                      token = getToken(context, 1 /* Pipe */, readPlural(scnr));
                      // reset
                      context.braceNest = 0;
                      context.inLinked = false;
                      return token;
                  }
                  if (isLinkedDotStart(scnr, context) ||
                      isLinkedDelimiterStart(scnr, context)) {
                      skipSpaces(scnr);
                      return readTokenInLinked(scnr, context);
                  }
                  if (isLinkedModifierStart(scnr, context)) {
                      skipSpaces(scnr);
                      return getToken(context, 12 /* LinkedModifier */, readLinkedModifier(scnr));
                  }
                  if (isLinkedReferStart(scnr, context)) {
                      skipSpaces(scnr);
                      if (ch === "{" /* BraceLeft */) {
                          // scan the placeholder
                          return readTokenInPlaceholder(scnr, context) || token;
                      }
                      else {
                          return getToken(context, 11 /* LinkedKey */, readLinkedRefer(scnr));
                      }
                  }
                  if (currentType === 8 /* LinkedAlias */) {
                      emitError(CompileErrorCodes.INVALID_LINKED_FORMAT, currentPosition(), 0);
                  }
                  context.braceNest = 0;
                  context.inLinked = false;
                  return readToken(scnr, context);
          }
      }
      // TODO: We need refactoring of token parsing ...
      function readToken(scnr, context) {
          let token = { type: 14 /* EOF */ };
          if (context.braceNest > 0) {
              return readTokenInPlaceholder(scnr, context) || getEndToken(context);
          }
          if (context.inLinked) {
              return readTokenInLinked(scnr, context) || getEndToken(context);
          }
          const ch = scnr.currentChar();
          switch (ch) {
              case "{" /* BraceLeft */:
                  return readTokenInPlaceholder(scnr, context) || getEndToken(context);
              case "}" /* BraceRight */:
                  emitError(CompileErrorCodes.UNBALANCED_CLOSING_BRACE, currentPosition(), 0);
                  scnr.next();
                  return getToken(context, 3 /* BraceRight */, "}" /* BraceRight */);
              case "@" /* LinkedAlias */:
                  return readTokenInLinked(scnr, context) || getEndToken(context);
              default:
                  if (isPluralStart(scnr)) {
                      token = getToken(context, 1 /* Pipe */, readPlural(scnr));
                      // reset
                      context.braceNest = 0;
                      context.inLinked = false;
                      return token;
                  }
                  const { isModulo, hasSpace } = detectModuloStart(scnr);
                  if (isModulo) {
                      return hasSpace
                          ? getToken(context, 0 /* Text */, readText(scnr))
                          : getToken(context, 4 /* Modulo */, readModulo(scnr));
                  }
                  if (isTextStart(scnr)) {
                      return getToken(context, 0 /* Text */, readText(scnr));
                  }
                  break;
          }
          return token;
      }
      function nextToken() {
          const { currentType, offset, startLoc, endLoc } = _context;
          _context.lastType = currentType;
          _context.lastOffset = offset;
          _context.lastStartLoc = startLoc;
          _context.lastEndLoc = endLoc;
          _context.offset = currentOffset();
          _context.startLoc = currentPosition();
          if (_scnr.currentChar() === EOF) {
              return getToken(_context, 14 /* EOF */);
          }
          return readToken(_scnr, _context);
      }
      return {
          nextToken,
          currentOffset,
          currentPosition,
          context
      };
  }

  const ERROR_DOMAIN = 'parser';
  // Backslash backslash, backslash quote, uHHHH, UHHHHHH.
  const KNOWN_ESCAPES = /(?:\\\\|\\'|\\u([0-9a-fA-F]{4})|\\U([0-9a-fA-F]{6}))/g;
  function fromEscapeSequence(match, codePoint4, codePoint6) {
      switch (match) {
          case `\\\\`:
              return `\\`;
          case `\\\'`:
              return `\'`;
          default: {
              const codePoint = parseInt(codePoint4 || codePoint6, 16);
              if (codePoint <= 0xd7ff || codePoint >= 0xe000) {
                  return String.fromCodePoint(codePoint);
              }
              // invalid ...
              // Replace them with U+FFFD REPLACEMENT CHARACTER.
              return '�';
          }
      }
  }
  function createParser(options = {}) {
      const location = options.location !== false;
      const { onError } = options;
      function emitError(tokenzer, code, start, offset, ...args) {
          const end = tokenzer.currentPosition();
          end.offset += offset;
          end.column += offset;
          if (onError) {
              const loc = createLocation(start, end);
              const err = createCompileError(code, loc, {
                  domain: ERROR_DOMAIN,
                  args
              });
              onError(err);
          }
      }
      function startNode(type, offset, loc) {
          const node = {
              type,
              start: offset,
              end: offset
          };
          if (location) {
              node.loc = { start: loc, end: loc };
          }
          return node;
      }
      function endNode(node, offset, pos, type) {
          node.end = offset;
          if (type) {
              node.type = type;
          }
          if (location && node.loc) {
              node.loc.end = pos;
          }
      }
      function parseText(tokenizer, value) {
          const context = tokenizer.context();
          const node = startNode(3 /* Text */, context.offset, context.startLoc);
          node.value = value;
          endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
          return node;
      }
      function parseList(tokenizer, index) {
          const context = tokenizer.context();
          const { lastOffset: offset, lastStartLoc: loc } = context; // get brace left loc
          const node = startNode(5 /* List */, offset, loc);
          node.index = parseInt(index, 10);
          tokenizer.nextToken(); // skip brach right
          endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
          return node;
      }
      function parseNamed(tokenizer, key) {
          const context = tokenizer.context();
          const { lastOffset: offset, lastStartLoc: loc } = context; // get brace left loc
          const node = startNode(4 /* Named */, offset, loc);
          node.key = key;
          tokenizer.nextToken(); // skip brach right
          endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
          return node;
      }
      function parseLiteral(tokenizer, value) {
          const context = tokenizer.context();
          const { lastOffset: offset, lastStartLoc: loc } = context; // get brace left loc
          const node = startNode(9 /* Literal */, offset, loc);
          node.value = value.replace(KNOWN_ESCAPES, fromEscapeSequence);
          tokenizer.nextToken(); // skip brach right
          endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
          return node;
      }
      function parseLinkedModifier(tokenizer) {
          const token = tokenizer.nextToken();
          const context = tokenizer.context();
          const { lastOffset: offset, lastStartLoc: loc } = context; // get linked dot loc
          const node = startNode(8 /* LinkedModifier */, offset, loc);
          if (token.type !== 12 /* LinkedModifier */) {
              // empty modifier
              emitError(tokenizer, CompileErrorCodes.UNEXPECTED_EMPTY_LINKED_MODIFIER, context.lastStartLoc, 0);
              node.value = '';
              endNode(node, offset, loc);
              return {
                  nextConsumeToken: token,
                  node
              };
          }
          // check token
          if (token.value == null) {
              emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
          }
          node.value = token.value || '';
          endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
          return {
              node
          };
      }
      function parseLinkedKey(tokenizer, value) {
          const context = tokenizer.context();
          const node = startNode(7 /* LinkedKey */, context.offset, context.startLoc);
          node.value = value;
          endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
          return node;
      }
      function parseLinked(tokenizer) {
          const context = tokenizer.context();
          const linkedNode = startNode(6 /* Linked */, context.offset, context.startLoc);
          let token = tokenizer.nextToken();
          if (token.type === 9 /* LinkedDot */) {
              const parsed = parseLinkedModifier(tokenizer);
              linkedNode.modifier = parsed.node;
              token = parsed.nextConsumeToken || tokenizer.nextToken();
          }
          // asset check token
          if (token.type !== 10 /* LinkedDelimiter */) {
              emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
          }
          token = tokenizer.nextToken();
          // skip brace left
          if (token.type === 2 /* BraceLeft */) {
              token = tokenizer.nextToken();
          }
          switch (token.type) {
              case 11 /* LinkedKey */:
                  if (token.value == null) {
                      emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
                  }
                  linkedNode.key = parseLinkedKey(tokenizer, token.value || '');
                  break;
              case 5 /* Named */:
                  if (token.value == null) {
                      emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
                  }
                  linkedNode.key = parseNamed(tokenizer, token.value || '');
                  break;
              case 6 /* List */:
                  if (token.value == null) {
                      emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
                  }
                  linkedNode.key = parseList(tokenizer, token.value || '');
                  break;
              case 7 /* Literal */:
                  if (token.value == null) {
                      emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
                  }
                  linkedNode.key = parseLiteral(tokenizer, token.value || '');
                  break;
              default:
                  // empty key
                  emitError(tokenizer, CompileErrorCodes.UNEXPECTED_EMPTY_LINKED_KEY, context.lastStartLoc, 0);
                  const nextContext = tokenizer.context();
                  const emptyLinkedKeyNode = startNode(7 /* LinkedKey */, nextContext.offset, nextContext.startLoc);
                  emptyLinkedKeyNode.value = '';
                  endNode(emptyLinkedKeyNode, nextContext.offset, nextContext.startLoc);
                  linkedNode.key = emptyLinkedKeyNode;
                  endNode(linkedNode, nextContext.offset, nextContext.startLoc);
                  return {
                      nextConsumeToken: token,
                      node: linkedNode
                  };
          }
          endNode(linkedNode, tokenizer.currentOffset(), tokenizer.currentPosition());
          return {
              node: linkedNode
          };
      }
      function parseMessage(tokenizer) {
          const context = tokenizer.context();
          const startOffset = context.currentType === 1 /* Pipe */
              ? tokenizer.currentOffset()
              : context.offset;
          const startLoc = context.currentType === 1 /* Pipe */
              ? context.endLoc
              : context.startLoc;
          const node = startNode(2 /* Message */, startOffset, startLoc);
          node.items = [];
          let nextToken = null;
          do {
              const token = nextToken || tokenizer.nextToken();
              nextToken = null;
              switch (token.type) {
                  case 0 /* Text */:
                      if (token.value == null) {
                          emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
                      }
                      node.items.push(parseText(tokenizer, token.value || ''));
                      break;
                  case 6 /* List */:
                      if (token.value == null) {
                          emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
                      }
                      node.items.push(parseList(tokenizer, token.value || ''));
                      break;
                  case 5 /* Named */:
                      if (token.value == null) {
                          emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
                      }
                      node.items.push(parseNamed(tokenizer, token.value || ''));
                      break;
                  case 7 /* Literal */:
                      if (token.value == null) {
                          emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, getTokenCaption(token));
                      }
                      node.items.push(parseLiteral(tokenizer, token.value || ''));
                      break;
                  case 8 /* LinkedAlias */:
                      const parsed = parseLinked(tokenizer);
                      node.items.push(parsed.node);
                      nextToken = parsed.nextConsumeToken || null;
                      break;
              }
          } while (context.currentType !== 14 /* EOF */ &&
              context.currentType !== 1 /* Pipe */);
          // adjust message node loc
          const endOffset = context.currentType === 1 /* Pipe */
              ? context.lastOffset
              : tokenizer.currentOffset();
          const endLoc = context.currentType === 1 /* Pipe */
              ? context.lastEndLoc
              : tokenizer.currentPosition();
          endNode(node, endOffset, endLoc);
          return node;
      }
      function parsePlural(tokenizer, offset, loc, msgNode) {
          const context = tokenizer.context();
          let hasEmptyMessage = msgNode.items.length === 0;
          const node = startNode(1 /* Plural */, offset, loc);
          node.cases = [];
          node.cases.push(msgNode);
          do {
              const msg = parseMessage(tokenizer);
              if (!hasEmptyMessage) {
                  hasEmptyMessage = msg.items.length === 0;
              }
              node.cases.push(msg);
          } while (context.currentType !== 14 /* EOF */);
          if (hasEmptyMessage) {
              emitError(tokenizer, CompileErrorCodes.MUST_HAVE_MESSAGES_IN_PLURAL, loc, 0);
          }
          endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
          return node;
      }
      function parseResource(tokenizer) {
          const context = tokenizer.context();
          const { offset, startLoc } = context;
          const msgNode = parseMessage(tokenizer);
          if (context.currentType === 14 /* EOF */) {
              return msgNode;
          }
          else {
              return parsePlural(tokenizer, offset, startLoc, msgNode);
          }
      }
      function parse(source) {
          const tokenizer = createTokenizer(source, assign({}, options));
          const context = tokenizer.context();
          const node = startNode(0 /* Resource */, context.offset, context.startLoc);
          if (location && node.loc) {
              node.loc.source = source;
          }
          node.body = parseResource(tokenizer);
          // assert whether achieved to EOF
          if (context.currentType !== 14 /* EOF */) {
              emitError(tokenizer, CompileErrorCodes.UNEXPECTED_LEXICAL_ANALYSIS, context.lastStartLoc, 0, source[context.offset] || '');
          }
          endNode(node, tokenizer.currentOffset(), tokenizer.currentPosition());
          return node;
      }
      return { parse };
  }
  function getTokenCaption(token) {
      if (token.type === 14 /* EOF */) {
          return 'EOF';
      }
      const name = (token.value || '').replace(/\r?\n/gu, '\\n');
      return name.length > 10 ? name.slice(0, 9) + '…' : name;
  }

  function createTransformer(ast, options = {} // eslint-disable-line
  ) {
      const _context = {
          ast,
          helpers: new Set()
      };
      const context = () => _context;
      const helper = (name) => {
          _context.helpers.add(name);
          return name;
      };
      return { context, helper };
  }
  function traverseNodes(nodes, transformer) {
      for (let i = 0; i < nodes.length; i++) {
          traverseNode(nodes[i], transformer);
      }
  }
  function traverseNode(node, transformer) {
      // TODO: if we need pre-hook of transform, should be implemented to here
      switch (node.type) {
          case 1 /* Plural */:
              traverseNodes(node.cases, transformer);
              transformer.helper("plural" /* PLURAL */);
              break;
          case 2 /* Message */:
              traverseNodes(node.items, transformer);
              break;
          case 6 /* Linked */:
              const linked = node;
              traverseNode(linked.key, transformer);
              transformer.helper("linked" /* LINKED */);
              transformer.helper("type" /* TYPE */);
              break;
          case 5 /* List */:
              transformer.helper("interpolate" /* INTERPOLATE */);
              transformer.helper("list" /* LIST */);
              break;
          case 4 /* Named */:
              transformer.helper("interpolate" /* INTERPOLATE */);
              transformer.helper("named" /* NAMED */);
              break;
      }
      // TODO: if we need post-hook of transform, should be implemented to here
  }
  // transform AST
  function transform(ast, options = {} // eslint-disable-line
  ) {
      const transformer = createTransformer(ast);
      transformer.helper("normalize" /* NORMALIZE */);
      // traverse
      ast.body && traverseNode(ast.body, transformer);
      // set meta information
      const context = transformer.context();
      ast.helpers = Array.from(context.helpers);
  }

  function createCodeGenerator(ast, options) {
      const { sourceMap, filename, breakLineCode, needIndent: _needIndent } = options;
      const _context = {
          source: ast.loc.source,
          filename,
          code: '',
          column: 1,
          line: 1,
          offset: 0,
          map: undefined,
          breakLineCode,
          needIndent: _needIndent,
          indentLevel: 0
      };
      const context = () => _context;
      function push(code, node) {
          _context.code += code;
      }
      function _newline(n, withBreakLine = true) {
          const _breakLineCode = withBreakLine ? breakLineCode : '';
          push(_needIndent ? _breakLineCode + `  `.repeat(n) : _breakLineCode);
      }
      function indent(withNewLine = true) {
          const level = ++_context.indentLevel;
          withNewLine && _newline(level);
      }
      function deindent(withNewLine = true) {
          const level = --_context.indentLevel;
          withNewLine && _newline(level);
      }
      function newline() {
          _newline(_context.indentLevel);
      }
      const helper = (key) => `_${key}`;
      const needIndent = () => _context.needIndent;
      return {
          context,
          push,
          indent,
          deindent,
          newline,
          helper,
          needIndent
      };
  }
  function generateLinkedNode(generator, node) {
      const { helper } = generator;
      generator.push(`${helper("linked" /* LINKED */)}(`);
      generateNode(generator, node.key);
      if (node.modifier) {
          generator.push(`, `);
          generateNode(generator, node.modifier);
          generator.push(`, _type`);
      }
      else {
          generator.push(`, undefined, _type`);
      }
      generator.push(`)`);
  }
  function generateMessageNode(generator, node) {
      const { helper, needIndent } = generator;
      generator.push(`${helper("normalize" /* NORMALIZE */)}([`);
      generator.indent(needIndent());
      const length = node.items.length;
      for (let i = 0; i < length; i++) {
          generateNode(generator, node.items[i]);
          if (i === length - 1) {
              break;
          }
          generator.push(', ');
      }
      generator.deindent(needIndent());
      generator.push('])');
  }
  function generatePluralNode(generator, node) {
      const { helper, needIndent } = generator;
      if (node.cases.length > 1) {
          generator.push(`${helper("plural" /* PLURAL */)}([`);
          generator.indent(needIndent());
          const length = node.cases.length;
          for (let i = 0; i < length; i++) {
              generateNode(generator, node.cases[i]);
              if (i === length - 1) {
                  break;
              }
              generator.push(', ');
          }
          generator.deindent(needIndent());
          generator.push(`])`);
      }
  }
  function generateResource(generator, node) {
      if (node.body) {
          generateNode(generator, node.body);
      }
      else {
          generator.push('null');
      }
  }
  function generateNode(generator, node) {
      const { helper } = generator;
      switch (node.type) {
          case 0 /* Resource */:
              generateResource(generator, node);
              break;
          case 1 /* Plural */:
              generatePluralNode(generator, node);
              break;
          case 2 /* Message */:
              generateMessageNode(generator, node);
              break;
          case 6 /* Linked */:
              generateLinkedNode(generator, node);
              break;
          case 8 /* LinkedModifier */:
              generator.push(JSON.stringify(node.value), node);
              break;
          case 7 /* LinkedKey */:
              generator.push(JSON.stringify(node.value), node);
              break;
          case 5 /* List */:
              generator.push(`${helper("interpolate" /* INTERPOLATE */)}(${helper("list" /* LIST */)}(${node.index}))`, node);
              break;
          case 4 /* Named */:
              generator.push(`${helper("interpolate" /* INTERPOLATE */)}(${helper("named" /* NAMED */)}(${JSON.stringify(node.key)}))`, node);
              break;
          case 9 /* Literal */:
              generator.push(JSON.stringify(node.value), node);
              break;
          case 3 /* Text */:
              generator.push(JSON.stringify(node.value), node);
              break;
          default:
              {
                  throw new Error(`unhandled codegen node type: ${node.type}`);
              }
      }
  }
  // generate code from AST
  const generate = (ast, options = {} // eslint-disable-line
  ) => {
      const mode = isString(options.mode) ? options.mode : 'normal';
      const filename = isString(options.filename)
          ? options.filename
          : 'message.intl';
      const sourceMap = !!options.sourceMap;
      // prettier-ignore
      const breakLineCode = options.breakLineCode != null
          ? options.breakLineCode
          : mode === 'arrow'
              ? ';'
              : '\n';
      const needIndent = options.needIndent ? options.needIndent : mode !== 'arrow';
      const helpers = ast.helpers || [];
      const generator = createCodeGenerator(ast, {
          mode,
          filename,
          sourceMap,
          breakLineCode,
          needIndent
      });
      generator.push(mode === 'normal' ? `function __msg__ (ctx) {` : `(ctx) => {`);
      generator.indent(needIndent);
      if (helpers.length > 0) {
          generator.push(`const { ${helpers.map(s => `${s}: _${s}`).join(', ')} } = ctx`);
          generator.newline();
      }
      generator.push(`return `);
      generateNode(generator, ast);
      generator.deindent(needIndent);
      generator.push(`}`);
      const { code, map } = generator.context();
      return {
          ast,
          code,
          map: map ? map.toJSON() : undefined // eslint-disable-line @typescript-eslint/no-explicit-any
      };
  };

  function baseCompile(source, options = {}) {
      const assignedOptions = assign({}, options);
      // parse source codes
      const parser = createParser(assignedOptions);
      const ast = parser.parse(source);
      // transform ASTs
      transform(ast, assignedOptions);
      // generate javascript codes
      return generate(ast, assignedOptions);
  }

  const pathStateMachine =  [];
  pathStateMachine[0 /* BEFORE_PATH */] = {
      ["w" /* WORKSPACE */]: [0 /* BEFORE_PATH */],
      ["i" /* IDENT */]: [3 /* IN_IDENT */, 0 /* APPEND */],
      ["[" /* LEFT_BRACKET */]: [4 /* IN_SUB_PATH */],
      ["o" /* END_OF_FAIL */]: [7 /* AFTER_PATH */]
  };
  pathStateMachine[1 /* IN_PATH */] = {
      ["w" /* WORKSPACE */]: [1 /* IN_PATH */],
      ["." /* DOT */]: [2 /* BEFORE_IDENT */],
      ["[" /* LEFT_BRACKET */]: [4 /* IN_SUB_PATH */],
      ["o" /* END_OF_FAIL */]: [7 /* AFTER_PATH */]
  };
  pathStateMachine[2 /* BEFORE_IDENT */] = {
      ["w" /* WORKSPACE */]: [2 /* BEFORE_IDENT */],
      ["i" /* IDENT */]: [3 /* IN_IDENT */, 0 /* APPEND */],
      ["0" /* ZERO */]: [3 /* IN_IDENT */, 0 /* APPEND */]
  };
  pathStateMachine[3 /* IN_IDENT */] = {
      ["i" /* IDENT */]: [3 /* IN_IDENT */, 0 /* APPEND */],
      ["0" /* ZERO */]: [3 /* IN_IDENT */, 0 /* APPEND */],
      ["w" /* WORKSPACE */]: [1 /* IN_PATH */, 1 /* PUSH */],
      ["." /* DOT */]: [2 /* BEFORE_IDENT */, 1 /* PUSH */],
      ["[" /* LEFT_BRACKET */]: [4 /* IN_SUB_PATH */, 1 /* PUSH */],
      ["o" /* END_OF_FAIL */]: [7 /* AFTER_PATH */, 1 /* PUSH */]
  };
  pathStateMachine[4 /* IN_SUB_PATH */] = {
      ["'" /* SINGLE_QUOTE */]: [5 /* IN_SINGLE_QUOTE */, 0 /* APPEND */],
      ["\"" /* DOUBLE_QUOTE */]: [6 /* IN_DOUBLE_QUOTE */, 0 /* APPEND */],
      ["[" /* LEFT_BRACKET */]: [
          4 /* IN_SUB_PATH */,
          2 /* INC_SUB_PATH_DEPTH */
      ],
      ["]" /* RIGHT_BRACKET */]: [1 /* IN_PATH */, 3 /* PUSH_SUB_PATH */],
      ["o" /* END_OF_FAIL */]: 8 /* ERROR */,
      ["l" /* ELSE */]: [4 /* IN_SUB_PATH */, 0 /* APPEND */]
  };
  pathStateMachine[5 /* IN_SINGLE_QUOTE */] = {
      ["'" /* SINGLE_QUOTE */]: [4 /* IN_SUB_PATH */, 0 /* APPEND */],
      ["o" /* END_OF_FAIL */]: 8 /* ERROR */,
      ["l" /* ELSE */]: [5 /* IN_SINGLE_QUOTE */, 0 /* APPEND */]
  };
  pathStateMachine[6 /* IN_DOUBLE_QUOTE */] = {
      ["\"" /* DOUBLE_QUOTE */]: [4 /* IN_SUB_PATH */, 0 /* APPEND */],
      ["o" /* END_OF_FAIL */]: 8 /* ERROR */,
      ["l" /* ELSE */]: [6 /* IN_DOUBLE_QUOTE */, 0 /* APPEND */]
  };
  /**
   * Check if an expression is a literal value.
   */
  const literalValueRE = /^\s?(?:true|false|-?[\d.]+|'[^']*'|"[^"]*")\s?$/;
  function isLiteral(exp) {
      return literalValueRE.test(exp);
  }
  /**
   * Strip quotes from a string
   */
  function stripQuotes(str) {
      const a = str.charCodeAt(0);
      const b = str.charCodeAt(str.length - 1);
      return a === b && (a === 0x22 || a === 0x27) ? str.slice(1, -1) : str;
  }
  /**
   * Determine the type of a character in a keypath.
   */
  function getPathCharType(ch) {
      if (ch === undefined || ch === null) {
          return "o" /* END_OF_FAIL */;
      }
      const code = ch.charCodeAt(0);
      switch (code) {
          case 0x5b: // [
          case 0x5d: // ]
          case 0x2e: // .
          case 0x22: // "
          case 0x27: // '
              return ch;
          case 0x5f: // _
          case 0x24: // $
          case 0x2d: // -
              return "i" /* IDENT */;
          case 0x09: // Tab (HT)
          case 0x0a: // Newline (LF)
          case 0x0d: // Return (CR)
          case 0xa0: // No-break space (NBSP)
          case 0xfeff: // Byte Order Mark (BOM)
          case 0x2028: // Line Separator (LS)
          case 0x2029: // Paragraph Separator (PS)
              return "w" /* WORKSPACE */;
      }
      return "i" /* IDENT */;
  }
  /**
   * Format a subPath, return its plain form if it is
   * a literal string or number. Otherwise prepend the
   * dynamic indicator (*).
   */
  function formatSubPath(path) {
      const trimmed = path.trim();
      // invalid leading 0
      if (path.charAt(0) === '0' && isNaN(parseInt(path))) {
          return false;
      }
      return isLiteral(trimmed)
          ? stripQuotes(trimmed)
          : "*" /* ASTARISK */ + trimmed;
  }
  /**
   * Parse a string path into an array of segments
   */
  function parse(path) {
      const keys = [];
      let index = -1;
      let mode = 0 /* BEFORE_PATH */;
      let subPathDepth = 0;
      let c;
      let key; // eslint-disable-line
      let newChar;
      let type;
      let transition;
      let action;
      let typeMap;
      const actions = [];
      actions[0 /* APPEND */] = () => {
          if (key === undefined) {
              key = newChar;
          }
          else {
              key += newChar;
          }
      };
      actions[1 /* PUSH */] = () => {
          if (key !== undefined) {
              keys.push(key);
              key = undefined;
          }
      };
      actions[2 /* INC_SUB_PATH_DEPTH */] = () => {
          actions[0 /* APPEND */]();
          subPathDepth++;
      };
      actions[3 /* PUSH_SUB_PATH */] = () => {
          if (subPathDepth > 0) {
              subPathDepth--;
              mode = 4 /* IN_SUB_PATH */;
              actions[0 /* APPEND */]();
          }
          else {
              subPathDepth = 0;
              if (key === undefined) {
                  return false;
              }
              key = formatSubPath(key);
              if (key === false) {
                  return false;
              }
              else {
                  actions[1 /* PUSH */]();
              }
          }
      };
      function maybeUnescapeQuote() {
          const nextChar = path[index + 1];
          if ((mode === 5 /* IN_SINGLE_QUOTE */ &&
              nextChar === "'" /* SINGLE_QUOTE */) ||
              (mode === 6 /* IN_DOUBLE_QUOTE */ &&
                  nextChar === "\"" /* DOUBLE_QUOTE */)) {
              index++;
              newChar = '\\' + nextChar;
              actions[0 /* APPEND */]();
              return true;
          }
      }
      while (mode !== null) {
          index++;
          c = path[index];
          if (c === '\\' && maybeUnescapeQuote()) {
              continue;
          }
          type = getPathCharType(c);
          typeMap = pathStateMachine[mode];
          transition = typeMap[type] || typeMap["l" /* ELSE */] || 8 /* ERROR */;
          // check parse error
          if (transition === 8 /* ERROR */) {
              return;
          }
          mode = transition[0];
          if (transition[1] !== undefined) {
              action = actions[transition[1]];
              if (action) {
                  newChar = c;
                  if (action() === false) {
                      return;
                  }
              }
          }
          // check parse finish
          if (mode === 7 /* AFTER_PATH */) {
              return keys;
          }
      }
  }
  // path token cache
  const cache = new Map();
  /**
   * key-value message resolver
   *
   * @remarks
   * Resolves messages with the key-value structure. Note that messages with a hierarchical structure such as objects cannot be resolved
   *
   * @param obj - A target object to be resolved with path
   * @param path - A {@link Path | path} to resolve the value of message
   *
   * @returns A resolved {@link PathValue | path value}
   *
   * @VueI18nGeneral
   */
  function resolveWithKeyValue(obj, path) {
      return isObject(obj) ? obj[path] : null;
  }
  /**
   * message resolver
   *
   * @remarks
   * Resolves messages. messages with a hierarchical structure such as objects can be resolved. This resolver is used in VueI18n as default.
   *
   * @param obj - A target object to be resolved with path
   * @param path - A {@link Path | path} to resolve the value of message
   *
   * @returns A resolved {@link PathValue | path value}
   *
   * @VueI18nGeneral
   */
  function resolveValue(obj, path) {
      // check object
      if (!isObject(obj)) {
          return null;
      }
      // parse path
      let hit = cache.get(path);
      if (!hit) {
          hit = parse(path);
          if (hit) {
              cache.set(path, hit);
          }
      }
      // check hit
      if (!hit) {
          return null;
      }
      // resolve path value
      const len = hit.length;
      let last = obj;
      let i = 0;
      while (i < len) {
          const val = last[hit[i]];
          if (val === undefined) {
              return null;
          }
          last = val;
          i++;
      }
      return last;
  }

  const DEFAULT_MODIFIER = (str) => str;
  const DEFAULT_MESSAGE = (ctx) => ''; // eslint-disable-line
  const DEFAULT_MESSAGE_DATA_TYPE = 'text';
  const DEFAULT_NORMALIZE = (values) => values.length === 0 ? '' : values.join('');
  const DEFAULT_INTERPOLATE = toDisplayString;
  function pluralDefault(choice, choicesLength) {
      choice = Math.abs(choice);
      if (choicesLength === 2) {
          // prettier-ignore
          return choice
              ? choice > 1
                  ? 1
                  : 0
              : 1;
      }
      return choice ? Math.min(choice, 2) : 0;
  }
  function getPluralIndex(options) {
      // prettier-ignore
      const index = isNumber(options.pluralIndex)
          ? options.pluralIndex
          : -1;
      // prettier-ignore
      return options.named && (isNumber(options.named.count) || isNumber(options.named.n))
          ? isNumber(options.named.count)
              ? options.named.count
              : isNumber(options.named.n)
                  ? options.named.n
                  : index
          : index;
  }
  function normalizeNamed(pluralIndex, props) {
      if (!props.count) {
          props.count = pluralIndex;
      }
      if (!props.n) {
          props.n = pluralIndex;
      }
  }
  function createMessageContext(options = {}) {
      const locale = options.locale;
      const pluralIndex = getPluralIndex(options);
      const pluralRule = isObject(options.pluralRules) &&
          isString(locale) &&
          isFunction(options.pluralRules[locale])
          ? options.pluralRules[locale]
          : pluralDefault;
      const orgPluralRule = isObject(options.pluralRules) &&
          isString(locale) &&
          isFunction(options.pluralRules[locale])
          ? pluralDefault
          : undefined;
      const plural = (messages) => {
          return messages[pluralRule(pluralIndex, messages.length, orgPluralRule)];
      };
      const _list = options.list || [];
      const list = (index) => _list[index];
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      const _named = options.named || {};
      isNumber(options.pluralIndex) && normalizeNamed(pluralIndex, _named);
      const named = (key) => _named[key];
      function message(key) {
          // prettier-ignore
          const msg = isFunction(options.messages)
              ? options.messages(key)
              : isObject(options.messages)
                  ? options.messages[key]
                  : false;
          return !msg
              ? options.parent
                  ? options.parent.message(key) // resolve from parent messages
                  : DEFAULT_MESSAGE
              : msg;
      }
      const _modifier = (name) => options.modifiers
          ? options.modifiers[name]
          : DEFAULT_MODIFIER;
      const normalize = isPlainObject(options.processor) && isFunction(options.processor.normalize)
          ? options.processor.normalize
          : DEFAULT_NORMALIZE;
      const interpolate = isPlainObject(options.processor) &&
          isFunction(options.processor.interpolate)
          ? options.processor.interpolate
          : DEFAULT_INTERPOLATE;
      const type = isPlainObject(options.processor) && isString(options.processor.type)
          ? options.processor.type
          : DEFAULT_MESSAGE_DATA_TYPE;
      const linked = (key, ...args) => {
          const [arg1, arg2] = args;
          let type = 'text';
          let modifier = '';
          if (args.length === 1) {
              if (isObject(arg1)) {
                  modifier = arg1.modifier || modifier;
                  type = arg1.type || type;
              }
              else if (isString(arg1)) {
                  modifier = arg1 || modifier;
              }
          }
          else if (args.length === 2) {
              if (isString(arg1)) {
                  modifier = arg1 || modifier;
              }
              if (isString(arg2)) {
                  type = arg2 || type;
              }
          }
          let msg = message(key)(ctx);
          // The message in vnode resolved with linked are returned as an array by processor.nomalize
          if (type === 'vnode' && isArray(msg) && modifier) {
              msg = msg[0];
          }
          return modifier ? _modifier(modifier)(msg, type) : msg;
      };
      const ctx = {
          ["list" /* LIST */]: list,
          ["named" /* NAMED */]: named,
          ["plural" /* PLURAL */]: plural,
          ["linked" /* LINKED */]: linked,
          ["message" /* MESSAGE */]: message,
          ["type" /* TYPE */]: type,
          ["interpolate" /* INTERPOLATE */]: interpolate,
          ["normalize" /* NORMALIZE */]: normalize
      };
      return ctx;
  }

  const IntlifyDevToolsHooks =  {
      I18nInit: 'i18n:init',
      FunctionTranslate: 'function:translate'
  };

  let devtools = null;
  function setDevToolsHook(hook) {
      devtools = hook;
  }
  function getDevToolsHook() {
      return devtools;
  }
  function initI18nDevTools(i18n, version, meta) {
      // TODO: queue if devtools is undefined
      devtools &&
          devtools.emit(IntlifyDevToolsHooks.I18nInit, {
              timestamp: Date.now(),
              i18n,
              version,
              meta
          });
  }
  const translateDevTools = /* #__PURE__*/ createDevToolsHook(IntlifyDevToolsHooks.FunctionTranslate);
  function createDevToolsHook(hook) {
      return (payloads) => devtools && devtools.emit(hook, payloads);
  }

  const CoreWarnCodes = {
      NOT_FOUND_KEY: 1,
      FALLBACK_TO_TRANSLATE: 2,
      CANNOT_FORMAT_NUMBER: 3,
      FALLBACK_TO_NUMBER_FORMAT: 4,
      CANNOT_FORMAT_DATE: 5,
      FALLBACK_TO_DATE_FORMAT: 6,
      __EXTEND_POINT__: 7
  };
  /** @internal */
  const warnMessages = {
      [CoreWarnCodes.NOT_FOUND_KEY]: `Not found '{key}' key in '{locale}' locale messages.`,
      [CoreWarnCodes.FALLBACK_TO_TRANSLATE]: `Fall back to translate '{key}' key with '{target}' locale.`,
      [CoreWarnCodes.CANNOT_FORMAT_NUMBER]: `Cannot format a number value due to not supported Intl.NumberFormat.`,
      [CoreWarnCodes.FALLBACK_TO_NUMBER_FORMAT]: `Fall back to number format '{key}' key with '{target}' locale.`,
      [CoreWarnCodes.CANNOT_FORMAT_DATE]: `Cannot format a date value due to not supported Intl.DateTimeFormat.`,
      [CoreWarnCodes.FALLBACK_TO_DATE_FORMAT]: `Fall back to datetime format '{key}' key with '{target}' locale.`
  };
  function getWarnMessage(code, ...args) {
      return format(warnMessages[code], ...args);
  }

  /**
   * Fallback with simple implemenation
   *
   * @remarks
   * A fallback locale function implemented with a simple fallback algorithm.
   *
   * Basically, it returns the value as specified in the `fallbackLocale` props, and is processed with the fallback inside intlify.
   *
   * @param ctx - A {@link CoreContext | context}
   * @param fallback - A {@link FallbackLocale | fallback locale}
   * @param start - A starting {@link Locale | locale}
   *
   * @returns Fallback locales
   *
   * @VueI18nGeneral
   */
  function fallbackWithSimple(ctx, fallback, start // eslint-disable-line @typescript-eslint/no-unused-vars
  ) {
      // prettier-ignore
      return [...new Set([
              start,
              ...(isArray(fallback)
                  ? fallback
                  : isObject(fallback)
                      ? Object.keys(fallback)
                      : isString(fallback)
                          ? [fallback]
                          : [start])
          ])];
  }
  /**
   * Fallback with locale chain
   *
   * @remarks
   * A fallback locale function implemented with a fallback chain algorithm. It's used in VueI18n as default.
   *
   * @param ctx - A {@link CoreContext | context}
   * @param fallback - A {@link FallbackLocale | fallback locale}
   * @param start - A starting {@link Locale | locale}
   *
   * @returns Fallback locales
   *
   * @VueI18nSee [Fallbacking](../guide/essentials/fallback)
   *
   * @VueI18nGeneral
   */
  function fallbackWithLocaleChain(ctx, fallback, start) {
      const startLocale = isString(start) ? start : DEFAULT_LOCALE;
      const context = ctx;
      if (!context.__localeChainCache) {
          context.__localeChainCache = new Map();
      }
      let chain = context.__localeChainCache.get(startLocale);
      if (!chain) {
          chain = [];
          // first block defined by start
          let block = [start];
          // while any intervening block found
          while (isArray(block)) {
              block = appendBlockToChain(chain, block, fallback);
          }
          // prettier-ignore
          // last block defined by default
          const defaults = isArray(fallback) || !isPlainObject(fallback)
              ? fallback
              : fallback['default']
                  ? fallback['default']
                  : null;
          // convert defaults to array
          block = isString(defaults) ? [defaults] : defaults;
          if (isArray(block)) {
              appendBlockToChain(chain, block, false);
          }
          context.__localeChainCache.set(startLocale, chain);
      }
      return chain;
  }
  function appendBlockToChain(chain, block, blocks) {
      let follow = true;
      for (let i = 0; i < block.length && isBoolean(follow); i++) {
          const locale = block[i];
          if (isString(locale)) {
              follow = appendLocaleToChain(chain, block[i], blocks);
          }
      }
      return follow;
  }
  function appendLocaleToChain(chain, locale, blocks) {
      let follow;
      const tokens = locale.split('-');
      do {
          const target = tokens.join('-');
          follow = appendItemToChain(chain, target, blocks);
          tokens.splice(-1, 1);
      } while (tokens.length && follow === true);
      return follow;
  }
  function appendItemToChain(chain, target, blocks) {
      let follow = false;
      if (!chain.includes(target)) {
          follow = true;
          if (target) {
              follow = target[target.length - 1] !== '!';
              const locale = target.replace(/!/g, '');
              chain.push(locale);
              if ((isArray(blocks) || isPlainObject(blocks)) &&
                  blocks[locale] // eslint-disable-line @typescript-eslint/no-explicit-any
              ) {
                  // eslint-disable-next-line @typescript-eslint/no-explicit-any
                  follow = blocks[locale];
              }
          }
      }
      return follow;
  }

  /* eslint-disable @typescript-eslint/no-explicit-any */
  /**
   * Intlify core-base version
   * @internal
   */
  const VERSION = '9.2.2';
  const NOT_REOSLVED = -1;
  const DEFAULT_LOCALE = 'en-US';
  const MISSING_RESOLVE_VALUE = '';
  const capitalize = (str) => `${str.charAt(0).toLocaleUpperCase()}${str.substr(1)}`;
  function getDefaultLinkedModifiers() {
      return {
          upper: (val, type) => {
              // prettier-ignore
              return type === 'text' && isString(val)
                  ? val.toUpperCase()
                  : type === 'vnode' && isObject(val) && '__v_isVNode' in val
                      ? val.children.toUpperCase()
                      : val;
          },
          lower: (val, type) => {
              // prettier-ignore
              return type === 'text' && isString(val)
                  ? val.toLowerCase()
                  : type === 'vnode' && isObject(val) && '__v_isVNode' in val
                      ? val.children.toLowerCase()
                      : val;
          },
          capitalize: (val, type) => {
              // prettier-ignore
              return (type === 'text' && isString(val)
                  ? capitalize(val)
                  : type === 'vnode' && isObject(val) && '__v_isVNode' in val
                      ? capitalize(val.children)
                      : val);
          }
      };
  }
  let _compiler;
  function registerMessageCompiler(compiler) {
      _compiler = compiler;
  }
  let _resolver;
  /**
   * Register the message resolver
   *
   * @param resolver - A {@link MessageResolver} function
   *
   * @VueI18nGeneral
   */
  function registerMessageResolver(resolver) {
      _resolver = resolver;
  }
  let _fallbacker;
  /**
   * Register the locale fallbacker
   *
   * @param fallbacker - A {@link LocaleFallbacker} function
   *
   * @VueI18nGeneral
   */
  function registerLocaleFallbacker(fallbacker) {
      _fallbacker = fallbacker;
  }
  // Additional Meta for Intlify DevTools
  let _additionalMeta = null;
  const setAdditionalMeta =  (meta) => {
      _additionalMeta = meta;
  };
  const getAdditionalMeta =  () => _additionalMeta;
  let _fallbackContext = null;
  const setFallbackContext = (context) => {
      _fallbackContext = context;
  };
  const getFallbackContext = () => _fallbackContext;
  // ID for CoreContext
  let _cid = 0;
  function createCoreContext(options = {}) {
      // setup options
      const version = isString(options.version) ? options.version : VERSION;
      const locale = isString(options.locale) ? options.locale : DEFAULT_LOCALE;
      const fallbackLocale = isArray(options.fallbackLocale) ||
          isPlainObject(options.fallbackLocale) ||
          isString(options.fallbackLocale) ||
          options.fallbackLocale === false
          ? options.fallbackLocale
          : locale;
      const messages = isPlainObject(options.messages)
          ? options.messages
          : { [locale]: {} };
      const datetimeFormats = isPlainObject(options.datetimeFormats)
              ? options.datetimeFormats
              : { [locale]: {} }
          ;
      const numberFormats = isPlainObject(options.numberFormats)
              ? options.numberFormats
              : { [locale]: {} }
          ;
      const modifiers = assign({}, options.modifiers || {}, getDefaultLinkedModifiers());
      const pluralRules = options.pluralRules || {};
      const missing = isFunction(options.missing) ? options.missing : null;
      const missingWarn = isBoolean(options.missingWarn) || isRegExp(options.missingWarn)
          ? options.missingWarn
          : true;
      const fallbackWarn = isBoolean(options.fallbackWarn) || isRegExp(options.fallbackWarn)
          ? options.fallbackWarn
          : true;
      const fallbackFormat = !!options.fallbackFormat;
      const unresolving = !!options.unresolving;
      const postTranslation = isFunction(options.postTranslation)
          ? options.postTranslation
          : null;
      const processor = isPlainObject(options.processor) ? options.processor : null;
      const warnHtmlMessage = isBoolean(options.warnHtmlMessage)
          ? options.warnHtmlMessage
          : true;
      const escapeParameter = !!options.escapeParameter;
      const messageCompiler = isFunction(options.messageCompiler)
          ? options.messageCompiler
          : _compiler;
      const messageResolver = isFunction(options.messageResolver)
          ? options.messageResolver
          : _resolver || resolveWithKeyValue;
      const localeFallbacker = isFunction(options.localeFallbacker)
          ? options.localeFallbacker
          : _fallbacker || fallbackWithSimple;
      const fallbackContext = isObject(options.fallbackContext)
          ? options.fallbackContext
          : undefined;
      const onWarn = isFunction(options.onWarn) ? options.onWarn : warn;
      // setup internal options
      const internalOptions = options;
      const __datetimeFormatters = isObject(internalOptions.__datetimeFormatters)
              ? internalOptions.__datetimeFormatters
              : new Map()
          ;
      const __numberFormatters = isObject(internalOptions.__numberFormatters)
              ? internalOptions.__numberFormatters
              : new Map()
          ;
      const __meta = isObject(internalOptions.__meta) ? internalOptions.__meta : {};
      _cid++;
      const context = {
          version,
          cid: _cid,
          locale,
          fallbackLocale,
          messages,
          modifiers,
          pluralRules,
          missing,
          missingWarn,
          fallbackWarn,
          fallbackFormat,
          unresolving,
          postTranslation,
          processor,
          warnHtmlMessage,
          escapeParameter,
          messageCompiler,
          messageResolver,
          localeFallbacker,
          fallbackContext,
          onWarn,
          __meta
      };
      {
          context.datetimeFormats = datetimeFormats;
          context.numberFormats = numberFormats;
          context.__datetimeFormatters = __datetimeFormatters;
          context.__numberFormatters = __numberFormatters;
      }
      // for vue-devtools timeline event
      {
          context.__v_emitter =
              internalOptions.__v_emitter != null
                  ? internalOptions.__v_emitter
                  : undefined;
      }
      // NOTE: experimental !!
      {
          initI18nDevTools(context, version, __meta);
      }
      return context;
  }
  /** @internal */
  function isTranslateFallbackWarn(fallback, key) {
      return fallback instanceof RegExp ? fallback.test(key) : fallback;
  }
  /** @internal */
  function isTranslateMissingWarn(missing, key) {
      return missing instanceof RegExp ? missing.test(key) : missing;
  }
  /** @internal */
  function handleMissing(context, key, locale, missingWarn, type) {
      const { missing, onWarn } = context;
      // for vue-devtools timeline event
      {
          const emitter = context.__v_emitter;
          if (emitter) {
              emitter.emit("missing" /* MISSING */, {
                  locale,
                  key,
                  type,
                  groupId: `${type}:${key}`
              });
          }
      }
      if (missing !== null) {
          const ret = missing(context, locale, key, type);
          return isString(ret) ? ret : key;
      }
      else {
          if (isTranslateMissingWarn(missingWarn, key)) {
              onWarn(getWarnMessage(CoreWarnCodes.NOT_FOUND_KEY, { key, locale }));
          }
          return key;
      }
  }
  /** @internal */
  function updateFallbackLocale(ctx, locale, fallback) {
      const context = ctx;
      context.__localeChainCache = new Map();
      ctx.localeFallbacker(ctx, fallback, locale);
  }
  /* eslint-enable @typescript-eslint/no-explicit-any */

  const RE_HTML_TAG = /<\/?[\w\s="/.':;#-\/]+>/;
  const WARN_MESSAGE = `Detected HTML in '{source}' message. Recommend not using HTML messages to avoid XSS.`;
  function checkHtmlMessage(source, options) {
      const warnHtmlMessage = isBoolean(options.warnHtmlMessage)
          ? options.warnHtmlMessage
          : true;
      if (warnHtmlMessage && RE_HTML_TAG.test(source)) {
          warn(format(WARN_MESSAGE, { source }));
      }
  }
  const defaultOnCacheKey = (source) => source;
  let compileCache = Object.create(null);
  function clearCompileCache() {
      compileCache = Object.create(null);
  }
  function compileToFunction(source, options = {}) {
      {
          // check HTML message
          checkHtmlMessage(source, options);
          // check caches
          const onCacheKey = options.onCacheKey || defaultOnCacheKey;
          const key = onCacheKey(source);
          const cached = compileCache[key];
          if (cached) {
              return cached;
          }
          // compile error detecting
          let occurred = false;
          const onError = options.onError || defaultOnError;
          options.onError = (err) => {
              occurred = true;
              onError(err);
          };
          // compile
          const { code } = baseCompile(source, options);
          // evaluate function
          const msg = new Function(`return ${code}`)();
          // if occurred compile error, don't cache
          return !occurred ? (compileCache[key] = msg) : msg;
      }
  }

  let code = CompileErrorCodes.__EXTEND_POINT__;
  const inc = () => ++code;
  const CoreErrorCodes = {
      INVALID_ARGUMENT: code,
      INVALID_DATE_ARGUMENT: inc(),
      INVALID_ISO_DATE_ARGUMENT: inc(),
      __EXTEND_POINT__: inc() // 18
  };
  function createCoreError(code) {
      return createCompileError(code, null, { messages: errorMessages } );
  }
  /** @internal */
  const errorMessages = {
      [CoreErrorCodes.INVALID_ARGUMENT]: 'Invalid arguments',
      [CoreErrorCodes.INVALID_DATE_ARGUMENT]: 'The date provided is an invalid Date object.' +
          'Make sure your Date represents a valid date.',
      [CoreErrorCodes.INVALID_ISO_DATE_ARGUMENT]: 'The argument provided is not a valid ISO date string'
  };

  const NOOP_MESSAGE_FUNCTION = () => '';
  const isMessageFunction = (val) => isFunction(val);
  // implementation of `translate` function
  function translate(context, ...args) {
      const { fallbackFormat, postTranslation, unresolving, messageCompiler, fallbackLocale, messages } = context;
      const [key, options] = parseTranslateArgs(...args);
      const missingWarn = isBoolean(options.missingWarn)
          ? options.missingWarn
          : context.missingWarn;
      const fallbackWarn = isBoolean(options.fallbackWarn)
          ? options.fallbackWarn
          : context.fallbackWarn;
      const escapeParameter = isBoolean(options.escapeParameter)
          ? options.escapeParameter
          : context.escapeParameter;
      const resolvedMessage = !!options.resolvedMessage;
      // prettier-ignore
      const defaultMsgOrKey = isString(options.default) || isBoolean(options.default) // default by function option
          ? !isBoolean(options.default)
              ? options.default
              : (!messageCompiler ? () => key : key)
          : fallbackFormat // default by `fallbackFormat` option
              ? (!messageCompiler ? () => key : key)
              : '';
      const enableDefaultMsg = fallbackFormat || defaultMsgOrKey !== '';
      const locale = isString(options.locale) ? options.locale : context.locale;
      // escape params
      escapeParameter && escapeParams(options);
      // resolve message format
      // eslint-disable-next-line prefer-const
      let [formatScope, targetLocale, message] = !resolvedMessage
          ? resolveMessageFormat(context, key, locale, fallbackLocale, fallbackWarn, missingWarn)
          : [
              key,
              locale,
              messages[locale] || {}
          ];
      // NOTE:
      //  Fix to work around `ssrTransfrom` bug in Vite.
      //  https://github.com/vitejs/vite/issues/4306
      //  To get around this, use temporary variables.
      //  https://github.com/nuxt/framework/issues/1461#issuecomment-954606243
      let format = formatScope;
      // if you use default message, set it as message format!
      let cacheBaseKey = key;
      if (!resolvedMessage &&
          !(isString(format) || isMessageFunction(format))) {
          if (enableDefaultMsg) {
              format = defaultMsgOrKey;
              cacheBaseKey = format;
          }
      }
      // checking message format and target locale
      if (!resolvedMessage &&
          (!(isString(format) || isMessageFunction(format)) ||
              !isString(targetLocale))) {
          return unresolving ? NOT_REOSLVED : key;
      }
      if (isString(format) && context.messageCompiler == null) {
          warn(`The message format compilation is not supported in this build. ` +
              `Because message compiler isn't included. ` +
              `You need to pre-compilation all message format. ` +
              `So translate function return '${key}'.`);
          return key;
      }
      // setup compile error detecting
      let occurred = false;
      const errorDetector = () => {
          occurred = true;
      };
      // compile message format
      const msg = !isMessageFunction(format)
          ? compileMessageFormat(context, key, targetLocale, format, cacheBaseKey, errorDetector)
          : format;
      // if occurred compile error, return the message format
      if (occurred) {
          return format;
      }
      // evaluate message with context
      const ctxOptions = getMessageContextOptions(context, targetLocale, message, options);
      const msgContext = createMessageContext(ctxOptions);
      const messaged = evaluateMessage(context, msg, msgContext);
      // if use post translation option, proceed it with handler
      const ret = postTranslation
          ? postTranslation(messaged, key)
          : messaged;
      // NOTE: experimental !!
      {
          // prettier-ignore
          const payloads = {
              timestamp: Date.now(),
              key: isString(key)
                  ? key
                  : isMessageFunction(format)
                      ? format.key
                      : '',
              locale: targetLocale || (isMessageFunction(format)
                  ? format.locale
                  : ''),
              format: isString(format)
                  ? format
                  : isMessageFunction(format)
                      ? format.source
                      : '',
              message: ret
          };
          payloads.meta = assign({}, context.__meta, getAdditionalMeta() || {});
          translateDevTools(payloads);
      }
      return ret;
  }
  function escapeParams(options) {
      if (isArray(options.list)) {
          options.list = options.list.map(item => isString(item) ? escapeHtml(item) : item);
      }
      else if (isObject(options.named)) {
          Object.keys(options.named).forEach(key => {
              if (isString(options.named[key])) {
                  options.named[key] = escapeHtml(options.named[key]);
              }
          });
      }
  }
  function resolveMessageFormat(context, key, locale, fallbackLocale, fallbackWarn, missingWarn) {
      const { messages, onWarn, messageResolver: resolveValue, localeFallbacker } = context;
      const locales = localeFallbacker(context, fallbackLocale, locale); // eslint-disable-line @typescript-eslint/no-explicit-any
      let message = {};
      let targetLocale;
      let format = null;
      let from = locale;
      let to = null;
      const type = 'translate';
      for (let i = 0; i < locales.length; i++) {
          targetLocale = to = locales[i];
          if (locale !== targetLocale &&
              isTranslateFallbackWarn(fallbackWarn, key)) {
              onWarn(getWarnMessage(CoreWarnCodes.FALLBACK_TO_TRANSLATE, {
                  key,
                  target: targetLocale
              }));
          }
          // for vue-devtools timeline event
          if (locale !== targetLocale) {
              const emitter = context.__v_emitter;
              if (emitter) {
                  emitter.emit("fallback" /* FALBACK */, {
                      type,
                      key,
                      from,
                      to,
                      groupId: `${type}:${key}`
                  });
              }
          }
          message =
              messages[targetLocale] || {};
          // for vue-devtools timeline event
          let start = null;
          let startTag;
          let endTag;
          if (inBrowser) {
              start = window.performance.now();
              startTag = 'intlify-message-resolve-start';
              endTag = 'intlify-message-resolve-end';
              mark && mark(startTag);
          }
          if ((format = resolveValue(message, key)) === null) {
              // if null, resolve with object key path
              format = message[key]; // eslint-disable-line @typescript-eslint/no-explicit-any
          }
          // for vue-devtools timeline event
          if (inBrowser) {
              const end = window.performance.now();
              const emitter = context.__v_emitter;
              if (emitter && start && format) {
                  emitter.emit("message-resolve" /* MESSAGE_RESOLVE */, {
                      type: "message-resolve" /* MESSAGE_RESOLVE */,
                      key,
                      message: format,
                      time: end - start,
                      groupId: `${type}:${key}`
                  });
              }
              if (startTag && endTag && mark && measure) {
                  mark(endTag);
                  measure('intlify message resolve', startTag, endTag);
              }
          }
          if (isString(format) || isFunction(format))
              break;
          const missingRet = handleMissing(context, // eslint-disable-line @typescript-eslint/no-explicit-any
          key, targetLocale, missingWarn, type);
          if (missingRet !== key) {
              format = missingRet;
          }
          from = to;
      }
      return [format, targetLocale, message];
  }
  function compileMessageFormat(context, key, targetLocale, format, cacheBaseKey, errorDetector) {
      const { messageCompiler, warnHtmlMessage } = context;
      if (isMessageFunction(format)) {
          const msg = format;
          msg.locale = msg.locale || targetLocale;
          msg.key = msg.key || key;
          return msg;
      }
      if (messageCompiler == null) {
          const msg = (() => format);
          msg.locale = targetLocale;
          msg.key = key;
          return msg;
      }
      // for vue-devtools timeline event
      let start = null;
      let startTag;
      let endTag;
      if (inBrowser) {
          start = window.performance.now();
          startTag = 'intlify-message-compilation-start';
          endTag = 'intlify-message-compilation-end';
          mark && mark(startTag);
      }
      const msg = messageCompiler(format, getCompileOptions(context, targetLocale, cacheBaseKey, format, warnHtmlMessage, errorDetector));
      // for vue-devtools timeline event
      if (inBrowser) {
          const end = window.performance.now();
          const emitter = context.__v_emitter;
          if (emitter && start) {
              emitter.emit("message-compilation" /* MESSAGE_COMPILATION */, {
                  type: "message-compilation" /* MESSAGE_COMPILATION */,
                  message: format,
                  time: end - start,
                  groupId: `${'translate'}:${key}`
              });
          }
          if (startTag && endTag && mark && measure) {
              mark(endTag);
              measure('intlify message compilation', startTag, endTag);
          }
      }
      msg.locale = targetLocale;
      msg.key = key;
      msg.source = format;
      return msg;
  }
  function evaluateMessage(context, msg, msgCtx) {
      // for vue-devtools timeline event
      let start = null;
      let startTag;
      let endTag;
      if (inBrowser) {
          start = window.performance.now();
          startTag = 'intlify-message-evaluation-start';
          endTag = 'intlify-message-evaluation-end';
          mark && mark(startTag);
      }
      const messaged = msg(msgCtx);
      // for vue-devtools timeline event
      if (inBrowser) {
          const end = window.performance.now();
          const emitter = context.__v_emitter;
          if (emitter && start) {
              emitter.emit("message-evaluation" /* MESSAGE_EVALUATION */, {
                  type: "message-evaluation" /* MESSAGE_EVALUATION */,
                  value: messaged,
                  time: end - start,
                  groupId: `${'translate'}:${msg.key}`
              });
          }
          if (startTag && endTag && mark && measure) {
              mark(endTag);
              measure('intlify message evaluation', startTag, endTag);
          }
      }
      return messaged;
  }
  /** @internal */
  function parseTranslateArgs(...args) {
      const [arg1, arg2, arg3] = args;
      const options = {};
      if (!isString(arg1) && !isNumber(arg1) && !isMessageFunction(arg1)) {
          throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
      }
      // prettier-ignore
      const key = isNumber(arg1)
          ? String(arg1)
          : isMessageFunction(arg1)
              ? arg1
              : arg1;
      if (isNumber(arg2)) {
          options.plural = arg2;
      }
      else if (isString(arg2)) {
          options.default = arg2;
      }
      else if (isPlainObject(arg2) && !isEmptyObject(arg2)) {
          options.named = arg2;
      }
      else if (isArray(arg2)) {
          options.list = arg2;
      }
      if (isNumber(arg3)) {
          options.plural = arg3;
      }
      else if (isString(arg3)) {
          options.default = arg3;
      }
      else if (isPlainObject(arg3)) {
          assign(options, arg3);
      }
      return [key, options];
  }
  function getCompileOptions(context, locale, key, source, warnHtmlMessage, errorDetector) {
      return {
          warnHtmlMessage,
          onError: (err) => {
              errorDetector && errorDetector(err);
              {
                  const message = `Message compilation error: ${err.message}`;
                  const codeFrame = err.location &&
                      generateCodeFrame(source, err.location.start.offset, err.location.end.offset);
                  const emitter = context.__v_emitter;
                  if (emitter) {
                      emitter.emit("compile-error" /* COMPILE_ERROR */, {
                          message: source,
                          error: err.message,
                          start: err.location && err.location.start.offset,
                          end: err.location && err.location.end.offset,
                          groupId: `${'translate'}:${key}`
                      });
                  }
                  console.error(codeFrame ? `${message}\n${codeFrame}` : message);
              }
          },
          onCacheKey: (source) => generateFormatCacheKey(locale, key, source)
      };
  }
  function getMessageContextOptions(context, locale, message, options) {
      const { modifiers, pluralRules, messageResolver: resolveValue, fallbackLocale, fallbackWarn, missingWarn, fallbackContext } = context;
      const resolveMessage = (key) => {
          let val = resolveValue(message, key);
          // fallback to root context
          if (val == null && fallbackContext) {
              const [, , message] = resolveMessageFormat(fallbackContext, key, locale, fallbackLocale, fallbackWarn, missingWarn);
              val = resolveValue(message, key);
          }
          if (isString(val)) {
              let occurred = false;
              const errorDetector = () => {
                  occurred = true;
              };
              const msg = compileMessageFormat(context, key, locale, val, key, errorDetector);
              return !occurred
                  ? msg
                  : NOOP_MESSAGE_FUNCTION;
          }
          else if (isMessageFunction(val)) {
              return val;
          }
          else {
              // TODO: should be implemented warning message
              return NOOP_MESSAGE_FUNCTION;
          }
      };
      const ctxOptions = {
          locale,
          modifiers,
          pluralRules,
          messages: resolveMessage
      };
      if (context.processor) {
          ctxOptions.processor = context.processor;
      }
      if (options.list) {
          ctxOptions.list = options.list;
      }
      if (options.named) {
          ctxOptions.named = options.named;
      }
      if (isNumber(options.plural)) {
          ctxOptions.pluralIndex = options.plural;
      }
      return ctxOptions;
  }

  const intlDefined = typeof Intl !== 'undefined';
  const Availabilities = {
      dateTimeFormat: intlDefined && typeof Intl.DateTimeFormat !== 'undefined',
      numberFormat: intlDefined && typeof Intl.NumberFormat !== 'undefined'
  };

  // implementation of `datetime` function
  function datetime(context, ...args) {
      const { datetimeFormats, unresolving, fallbackLocale, onWarn, localeFallbacker } = context;
      const { __datetimeFormatters } = context;
      if (!Availabilities.dateTimeFormat) {
          onWarn(getWarnMessage(CoreWarnCodes.CANNOT_FORMAT_DATE));
          return MISSING_RESOLVE_VALUE;
      }
      const [key, value, options, overrides] = parseDateTimeArgs(...args);
      const missingWarn = isBoolean(options.missingWarn)
          ? options.missingWarn
          : context.missingWarn;
      const fallbackWarn = isBoolean(options.fallbackWarn)
          ? options.fallbackWarn
          : context.fallbackWarn;
      const part = !!options.part;
      const locale = isString(options.locale) ? options.locale : context.locale;
      const locales = localeFallbacker(context, // eslint-disable-line @typescript-eslint/no-explicit-any
      fallbackLocale, locale);
      if (!isString(key) || key === '') {
          return new Intl.DateTimeFormat(locale, overrides).format(value);
      }
      // resolve format
      let datetimeFormat = {};
      let targetLocale;
      let format = null;
      let from = locale;
      let to = null;
      const type = 'datetime format';
      for (let i = 0; i < locales.length; i++) {
          targetLocale = to = locales[i];
          if (locale !== targetLocale &&
              isTranslateFallbackWarn(fallbackWarn, key)) {
              onWarn(getWarnMessage(CoreWarnCodes.FALLBACK_TO_DATE_FORMAT, {
                  key,
                  target: targetLocale
              }));
          }
          // for vue-devtools timeline event
          if (locale !== targetLocale) {
              const emitter = context.__v_emitter;
              if (emitter) {
                  emitter.emit("fallback" /* FALBACK */, {
                      type,
                      key,
                      from,
                      to,
                      groupId: `${type}:${key}`
                  });
              }
          }
          datetimeFormat =
              datetimeFormats[targetLocale] || {};
          format = datetimeFormat[key];
          if (isPlainObject(format))
              break;
          handleMissing(context, key, targetLocale, missingWarn, type); // eslint-disable-line @typescript-eslint/no-explicit-any
          from = to;
      }
      // checking format and target locale
      if (!isPlainObject(format) || !isString(targetLocale)) {
          return unresolving ? NOT_REOSLVED : key;
      }
      let id = `${targetLocale}__${key}`;
      if (!isEmptyObject(overrides)) {
          id = `${id}__${JSON.stringify(overrides)}`;
      }
      let formatter = __datetimeFormatters.get(id);
      if (!formatter) {
          formatter = new Intl.DateTimeFormat(targetLocale, assign({}, format, overrides));
          __datetimeFormatters.set(id, formatter);
      }
      return !part ? formatter.format(value) : formatter.formatToParts(value);
  }
  /** @internal */
  const DATETIME_FORMAT_OPTIONS_KEYS = [
      'localeMatcher',
      'weekday',
      'era',
      'year',
      'month',
      'day',
      'hour',
      'minute',
      'second',
      'timeZoneName',
      'formatMatcher',
      'hour12',
      'timeZone',
      'dateStyle',
      'timeStyle',
      'calendar',
      'dayPeriod',
      'numberingSystem',
      'hourCycle',
      'fractionalSecondDigits'
  ];
  /** @internal */
  function parseDateTimeArgs(...args) {
      const [arg1, arg2, arg3, arg4] = args;
      const options = {};
      let overrides = {};
      let value;
      if (isString(arg1)) {
          // Only allow ISO strings - other date formats are often supported,
          // but may cause different results in different browsers.
          const matches = arg1.match(/(\d{4}-\d{2}-\d{2})(T|\s)?(.*)/);
          if (!matches) {
              throw createCoreError(CoreErrorCodes.INVALID_ISO_DATE_ARGUMENT);
          }
          // Some browsers can not parse the iso datetime separated by space,
          // this is a compromise solution by replace the 'T'/' ' with 'T'
          const dateTime = matches[3]
              ? matches[3].trim().startsWith('T')
                  ? `${matches[1].trim()}${matches[3].trim()}`
                  : `${matches[1].trim()}T${matches[3].trim()}`
              : matches[1].trim();
          value = new Date(dateTime);
          try {
              // This will fail if the date is not valid
              value.toISOString();
          }
          catch (e) {
              throw createCoreError(CoreErrorCodes.INVALID_ISO_DATE_ARGUMENT);
          }
      }
      else if (isDate(arg1)) {
          if (isNaN(arg1.getTime())) {
              throw createCoreError(CoreErrorCodes.INVALID_DATE_ARGUMENT);
          }
          value = arg1;
      }
      else if (isNumber(arg1)) {
          value = arg1;
      }
      else {
          throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
      }
      if (isString(arg2)) {
          options.key = arg2;
      }
      else if (isPlainObject(arg2)) {
          Object.keys(arg2).forEach(key => {
              if (DATETIME_FORMAT_OPTIONS_KEYS.includes(key)) {
                  overrides[key] = arg2[key];
              }
              else {
                  options[key] = arg2[key];
              }
          });
      }
      if (isString(arg3)) {
          options.locale = arg3;
      }
      else if (isPlainObject(arg3)) {
          overrides = arg3;
      }
      if (isPlainObject(arg4)) {
          overrides = arg4;
      }
      return [options.key || '', value, options, overrides];
  }
  /** @internal */
  function clearDateTimeFormat(ctx, locale, format) {
      const context = ctx;
      for (const key in format) {
          const id = `${locale}__${key}`;
          if (!context.__datetimeFormatters.has(id)) {
              continue;
          }
          context.__datetimeFormatters.delete(id);
      }
  }

  // implementation of `number` function
  function number(context, ...args) {
      const { numberFormats, unresolving, fallbackLocale, onWarn, localeFallbacker } = context;
      const { __numberFormatters } = context;
      if (!Availabilities.numberFormat) {
          onWarn(getWarnMessage(CoreWarnCodes.CANNOT_FORMAT_NUMBER));
          return MISSING_RESOLVE_VALUE;
      }
      const [key, value, options, overrides] = parseNumberArgs(...args);
      const missingWarn = isBoolean(options.missingWarn)
          ? options.missingWarn
          : context.missingWarn;
      const fallbackWarn = isBoolean(options.fallbackWarn)
          ? options.fallbackWarn
          : context.fallbackWarn;
      const part = !!options.part;
      const locale = isString(options.locale) ? options.locale : context.locale;
      const locales = localeFallbacker(context, // eslint-disable-line @typescript-eslint/no-explicit-any
      fallbackLocale, locale);
      if (!isString(key) || key === '') {
          return new Intl.NumberFormat(locale, overrides).format(value);
      }
      // resolve format
      let numberFormat = {};
      let targetLocale;
      let format = null;
      let from = locale;
      let to = null;
      const type = 'number format';
      for (let i = 0; i < locales.length; i++) {
          targetLocale = to = locales[i];
          if (locale !== targetLocale &&
              isTranslateFallbackWarn(fallbackWarn, key)) {
              onWarn(getWarnMessage(CoreWarnCodes.FALLBACK_TO_NUMBER_FORMAT, {
                  key,
                  target: targetLocale
              }));
          }
          // for vue-devtools timeline event
          if (locale !== targetLocale) {
              const emitter = context.__v_emitter;
              if (emitter) {
                  emitter.emit("fallback" /* FALBACK */, {
                      type,
                      key,
                      from,
                      to,
                      groupId: `${type}:${key}`
                  });
              }
          }
          numberFormat =
              numberFormats[targetLocale] || {};
          format = numberFormat[key];
          if (isPlainObject(format))
              break;
          handleMissing(context, key, targetLocale, missingWarn, type); // eslint-disable-line @typescript-eslint/no-explicit-any
          from = to;
      }
      // checking format and target locale
      if (!isPlainObject(format) || !isString(targetLocale)) {
          return unresolving ? NOT_REOSLVED : key;
      }
      let id = `${targetLocale}__${key}`;
      if (!isEmptyObject(overrides)) {
          id = `${id}__${JSON.stringify(overrides)}`;
      }
      let formatter = __numberFormatters.get(id);
      if (!formatter) {
          formatter = new Intl.NumberFormat(targetLocale, assign({}, format, overrides));
          __numberFormatters.set(id, formatter);
      }
      return !part ? formatter.format(value) : formatter.formatToParts(value);
  }
  /** @internal */
  const NUMBER_FORMAT_OPTIONS_KEYS = [
      'localeMatcher',
      'style',
      'currency',
      'currencyDisplay',
      'currencySign',
      'useGrouping',
      'minimumIntegerDigits',
      'minimumFractionDigits',
      'maximumFractionDigits',
      'minimumSignificantDigits',
      'maximumSignificantDigits',
      'compactDisplay',
      'notation',
      'signDisplay',
      'unit',
      'unitDisplay',
      'roundingMode',
      'roundingPriority',
      'roundingIncrement',
      'trailingZeroDisplay'
  ];
  /** @internal */
  function parseNumberArgs(...args) {
      const [arg1, arg2, arg3, arg4] = args;
      const options = {};
      let overrides = {};
      if (!isNumber(arg1)) {
          throw createCoreError(CoreErrorCodes.INVALID_ARGUMENT);
      }
      const value = arg1;
      if (isString(arg2)) {
          options.key = arg2;
      }
      else if (isPlainObject(arg2)) {
          Object.keys(arg2).forEach(key => {
              if (NUMBER_FORMAT_OPTIONS_KEYS.includes(key)) {
                  overrides[key] = arg2[key];
              }
              else {
                  options[key] = arg2[key];
              }
          });
      }
      if (isString(arg3)) {
          options.locale = arg3;
      }
      else if (isPlainObject(arg3)) {
          overrides = arg3;
      }
      if (isPlainObject(arg4)) {
          overrides = arg4;
      }
      return [options.key || '', value, options, overrides];
  }
  /** @internal */
  function clearNumberFormat(ctx, locale, format) {
      const context = ctx;
      for (const key in format) {
          const id = `${locale}__${key}`;
          if (!context.__numberFormatters.has(id)) {
              continue;
          }
          context.__numberFormatters.delete(id);
      }
  }

  exports.CompileErrorCodes = CompileErrorCodes;
  exports.CoreErrorCodes = CoreErrorCodes;
  exports.CoreWarnCodes = CoreWarnCodes;
  exports.DATETIME_FORMAT_OPTIONS_KEYS = DATETIME_FORMAT_OPTIONS_KEYS;
  exports.DEFAULT_LOCALE = DEFAULT_LOCALE;
  exports.DEFAULT_MESSAGE_DATA_TYPE = DEFAULT_MESSAGE_DATA_TYPE;
  exports.MISSING_RESOLVE_VALUE = MISSING_RESOLVE_VALUE;
  exports.NOT_REOSLVED = NOT_REOSLVED;
  exports.NUMBER_FORMAT_OPTIONS_KEYS = NUMBER_FORMAT_OPTIONS_KEYS;
  exports.VERSION = VERSION;
  exports.clearCompileCache = clearCompileCache;
  exports.clearDateTimeFormat = clearDateTimeFormat;
  exports.clearNumberFormat = clearNumberFormat;
  exports.compileToFunction = compileToFunction;
  exports.createCompileError = createCompileError;
  exports.createCoreContext = createCoreContext;
  exports.createCoreError = createCoreError;
  exports.createMessageContext = createMessageContext;
  exports.datetime = datetime;
  exports.fallbackWithLocaleChain = fallbackWithLocaleChain;
  exports.fallbackWithSimple = fallbackWithSimple;
  exports.getAdditionalMeta = getAdditionalMeta;
  exports.getDevToolsHook = getDevToolsHook;
  exports.getFallbackContext = getFallbackContext;
  exports.getWarnMessage = getWarnMessage;
  exports.handleMissing = handleMissing;
  exports.initI18nDevTools = initI18nDevTools;
  exports.isMessageFunction = isMessageFunction;
  exports.isTranslateFallbackWarn = isTranslateFallbackWarn;
  exports.isTranslateMissingWarn = isTranslateMissingWarn;
  exports.number = number;
  exports.parse = parse;
  exports.parseDateTimeArgs = parseDateTimeArgs;
  exports.parseNumberArgs = parseNumberArgs;
  exports.parseTranslateArgs = parseTranslateArgs;
  exports.registerLocaleFallbacker = registerLocaleFallbacker;
  exports.registerMessageCompiler = registerMessageCompiler;
  exports.registerMessageResolver = registerMessageResolver;
  exports.resolveValue = resolveValue;
  exports.resolveWithKeyValue = resolveWithKeyValue;
  exports.setAdditionalMeta = setAdditionalMeta;
  exports.setDevToolsHook = setDevToolsHook;
  exports.setFallbackContext = setFallbackContext;
  exports.translate = translate;
  exports.translateDevTools = translateDevTools;
  exports.updateFallbackLocale = updateFallbackLocale;

  Object.defineProperty(exports, '__esModule', { value: true });

  return exports;

})({});
