@actual-app/api 26.6.0 → 26.7.0-nightly.20260603

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -329,12 +329,12 @@ var index_api_exports = /* @__PURE__ */ __exportAll({
329
329
  bundledDatabasePath: () => bundledDatabasePath,
330
330
  copyFile: () => copyFile,
331
331
  demoBudgetPath: () => demoBudgetPath,
332
- exists: () => exists$1,
332
+ exists: () => exists,
333
333
  getBudgetDir: () => getBudgetDir,
334
334
  getDataDir: () => getDataDir,
335
335
  getDocumentDir: () => getDocumentDir,
336
336
  getModifiedTime: () => getModifiedTime,
337
- init: () => init$5,
337
+ init: () => init$4,
338
338
  join: () => join$2,
339
339
  listDir: () => listDir,
340
340
  migrationsPath: () => migrationsPath,
@@ -346,7 +346,7 @@ var index_api_exports = /* @__PURE__ */ __exportAll({
346
346
  size: () => size,
347
347
  writeFile: () => writeFile
348
348
  });
349
- var init$5 = async () => {};
349
+ var init$4 = async () => {};
350
350
  var getDataDir = () => getDocumentDir();
351
351
  var bundledDatabasePath = path.join(__dirname, "default-db.sqlite");
352
352
  var migrationsPath = path.join(__dirname, "migrations");
@@ -359,7 +359,7 @@ var listDir = (filepath) => new Promise((resolve, reject) => {
359
359
  else resolve(files);
360
360
  });
361
361
  });
362
- var exists$1 = (filepath) => new Promise((resolve) => {
362
+ var exists = (filepath) => new Promise((resolve) => {
363
363
  fs.access(filepath, fs.constants.F_OK, (err) => {
364
364
  return resolve(!err);
365
365
  });
@@ -436,7 +436,7 @@ var removeDir = (dirpath) => {
436
436
  });
437
437
  };
438
438
  var removeDirRecursively = async (dirpath) => {
439
- if (await exists$1(dirpath)) {
439
+ if (await exists(dirpath)) {
440
440
  for (const file of await listDir(dirpath)) {
441
441
  const fullpath = join$2(dirpath, file);
442
442
  if (fs.statSync(fullpath).isDirectory()) await removeDirRecursively(fullpath);
@@ -458,7 +458,7 @@ var getModifiedTime = (filepath) => {
458
458
  var getStorePath = () => (0, path.join)(getDataDir(), "global-store.json");
459
459
  var store;
460
460
  var persisted = true;
461
- var init$4 = function({ persist = true } = {}) {
461
+ var init$3 = function({ persist = true } = {}) {
462
462
  if (persist) try {
463
463
  store = JSON.parse(fs.readFileSync(getStorePath(), "utf8"));
464
464
  } catch {
@@ -1234,7 +1234,7 @@ function verifyParamTypes(sql, arr) {
1234
1234
  }
1235
1235
  });
1236
1236
  }
1237
- async function init$3() {}
1237
+ async function init$2() {}
1238
1238
  function prepare(db, sql) {
1239
1239
  return db.prepare(sql);
1240
1240
  }
@@ -6880,1998 +6880,6 @@ function sortByKey(arr, key) {
6880
6880
  });
6881
6881
  }
6882
6882
  //#endregion
6883
- //#region ../../node_modules/i18next/dist/esm/i18next.js
6884
- var isString$2 = (obj) => typeof obj === "string";
6885
- var defer = () => {
6886
- let res;
6887
- let rej;
6888
- const promise = new Promise((resolve, reject) => {
6889
- res = resolve;
6890
- rej = reject;
6891
- });
6892
- promise.resolve = res;
6893
- promise.reject = rej;
6894
- return promise;
6895
- };
6896
- var makeString = (object) => {
6897
- if (object == null) return "";
6898
- return "" + object;
6899
- };
6900
- var copy = (a, s, t) => {
6901
- a.forEach((m) => {
6902
- if (s[m]) t[m] = s[m];
6903
- });
6904
- };
6905
- var lastOfPathSeparatorRegExp = /###/g;
6906
- var cleanKey = (key) => key && key.indexOf("###") > -1 ? key.replace(lastOfPathSeparatorRegExp, ".") : key;
6907
- var canNotTraverseDeeper = (object) => !object || isString$2(object);
6908
- var getLastOfPath = (object, path, Empty) => {
6909
- const stack = !isString$2(path) ? path : path.split(".");
6910
- let stackIndex = 0;
6911
- while (stackIndex < stack.length - 1) {
6912
- if (canNotTraverseDeeper(object)) return {};
6913
- const key = cleanKey(stack[stackIndex]);
6914
- if (!object[key] && Empty) object[key] = new Empty();
6915
- if (Object.prototype.hasOwnProperty.call(object, key)) object = object[key];
6916
- else object = {};
6917
- ++stackIndex;
6918
- }
6919
- if (canNotTraverseDeeper(object)) return {};
6920
- return {
6921
- obj: object,
6922
- k: cleanKey(stack[stackIndex])
6923
- };
6924
- };
6925
- var setPath = (object, path, newValue) => {
6926
- const { obj, k } = getLastOfPath(object, path, Object);
6927
- if (obj !== void 0 || path.length === 1) {
6928
- obj[k] = newValue;
6929
- return;
6930
- }
6931
- let e = path[path.length - 1];
6932
- let p = path.slice(0, path.length - 1);
6933
- let last = getLastOfPath(object, p, Object);
6934
- while (last.obj === void 0 && p.length) {
6935
- e = `${p[p.length - 1]}.${e}`;
6936
- p = p.slice(0, p.length - 1);
6937
- last = getLastOfPath(object, p, Object);
6938
- if (last?.obj && typeof last.obj[`${last.k}.${e}`] !== "undefined") last.obj = void 0;
6939
- }
6940
- last.obj[`${last.k}.${e}`] = newValue;
6941
- };
6942
- var pushPath = (object, path, newValue, concat) => {
6943
- const { obj, k } = getLastOfPath(object, path, Object);
6944
- obj[k] = obj[k] || [];
6945
- obj[k].push(newValue);
6946
- };
6947
- var getPath = (object, path) => {
6948
- const { obj, k } = getLastOfPath(object, path);
6949
- if (!obj) return void 0;
6950
- if (!Object.prototype.hasOwnProperty.call(obj, k)) return void 0;
6951
- return obj[k];
6952
- };
6953
- var getPathWithDefaults = (data, defaultData, key) => {
6954
- const value = getPath(data, key);
6955
- if (value !== void 0) return value;
6956
- return getPath(defaultData, key);
6957
- };
6958
- var deepExtend = (target, source, overwrite) => {
6959
- for (const prop in source) if (prop !== "__proto__" && prop !== "constructor") if (prop in target) if (isString$2(target[prop]) || target[prop] instanceof String || isString$2(source[prop]) || source[prop] instanceof String) {
6960
- if (overwrite) target[prop] = source[prop];
6961
- } else deepExtend(target[prop], source[prop], overwrite);
6962
- else target[prop] = source[prop];
6963
- return target;
6964
- };
6965
- var regexEscape = (str) => str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
6966
- var _entityMap = {
6967
- "&": "&amp;",
6968
- "<": "&lt;",
6969
- ">": "&gt;",
6970
- "\"": "&quot;",
6971
- "'": "&#39;",
6972
- "/": "&#x2F;"
6973
- };
6974
- var escape = (data) => {
6975
- if (isString$2(data)) return data.replace(/[&<>"'\/]/g, (s) => _entityMap[s]);
6976
- return data;
6977
- };
6978
- var RegExpCache = class {
6979
- constructor(capacity) {
6980
- this.capacity = capacity;
6981
- this.regExpMap = /* @__PURE__ */ new Map();
6982
- this.regExpQueue = [];
6983
- }
6984
- getRegExp(pattern) {
6985
- const regExpFromCache = this.regExpMap.get(pattern);
6986
- if (regExpFromCache !== void 0) return regExpFromCache;
6987
- const regExpNew = new RegExp(pattern);
6988
- if (this.regExpQueue.length === this.capacity) this.regExpMap.delete(this.regExpQueue.shift());
6989
- this.regExpMap.set(pattern, regExpNew);
6990
- this.regExpQueue.push(pattern);
6991
- return regExpNew;
6992
- }
6993
- };
6994
- var chars = [
6995
- " ",
6996
- ",",
6997
- "?",
6998
- "!",
6999
- ";"
7000
- ];
7001
- var looksLikeObjectPathRegExpCache = new RegExpCache(20);
7002
- var looksLikeObjectPath = (key, nsSeparator, keySeparator) => {
7003
- nsSeparator = nsSeparator || "";
7004
- keySeparator = keySeparator || "";
7005
- const possibleChars = chars.filter((c) => nsSeparator.indexOf(c) < 0 && keySeparator.indexOf(c) < 0);
7006
- if (possibleChars.length === 0) return true;
7007
- const r = looksLikeObjectPathRegExpCache.getRegExp(`(${possibleChars.map((c) => c === "?" ? "\\?" : c).join("|")})`);
7008
- let matched = !r.test(key);
7009
- if (!matched) {
7010
- const ki = key.indexOf(keySeparator);
7011
- if (ki > 0 && !r.test(key.substring(0, ki))) matched = true;
7012
- }
7013
- return matched;
7014
- };
7015
- var deepFind = (obj, path, keySeparator = ".") => {
7016
- if (!obj) return void 0;
7017
- if (obj[path]) {
7018
- if (!Object.prototype.hasOwnProperty.call(obj, path)) return void 0;
7019
- return obj[path];
7020
- }
7021
- const tokens = path.split(keySeparator);
7022
- let current = obj;
7023
- for (let i = 0; i < tokens.length;) {
7024
- if (!current || typeof current !== "object") return;
7025
- let next;
7026
- let nextPath = "";
7027
- for (let j = i; j < tokens.length; ++j) {
7028
- if (j !== i) nextPath += keySeparator;
7029
- nextPath += tokens[j];
7030
- next = current[nextPath];
7031
- if (next !== void 0) {
7032
- if ([
7033
- "string",
7034
- "number",
7035
- "boolean"
7036
- ].indexOf(typeof next) > -1 && j < tokens.length - 1) continue;
7037
- i += j - i + 1;
7038
- break;
7039
- }
7040
- }
7041
- current = next;
7042
- }
7043
- return current;
7044
- };
7045
- var getCleanedCode = (code) => code?.replace(/_/g, "-");
7046
- var consoleLogger = {
7047
- type: "logger",
7048
- log(args) {
7049
- this.output("log", args);
7050
- },
7051
- warn(args) {
7052
- this.output("warn", args);
7053
- },
7054
- error(args) {
7055
- this.output("error", args);
7056
- },
7057
- output(type, args) {
7058
- console?.[type]?.apply?.(console, args);
7059
- }
7060
- };
7061
- var baseLogger = new class Logger {
7062
- constructor(concreteLogger, options = {}) {
7063
- this.init(concreteLogger, options);
7064
- }
7065
- init(concreteLogger, options = {}) {
7066
- this.prefix = options.prefix || "i18next:";
7067
- this.logger = concreteLogger || consoleLogger;
7068
- this.options = options;
7069
- this.debug = options.debug;
7070
- }
7071
- log(...args) {
7072
- return this.forward(args, "log", "", true);
7073
- }
7074
- warn(...args) {
7075
- return this.forward(args, "warn", "", true);
7076
- }
7077
- error(...args) {
7078
- return this.forward(args, "error", "");
7079
- }
7080
- deprecate(...args) {
7081
- return this.forward(args, "warn", "WARNING DEPRECATED: ", true);
7082
- }
7083
- forward(args, lvl, prefix, debugOnly) {
7084
- if (debugOnly && !this.debug) return null;
7085
- if (isString$2(args[0])) args[0] = `${prefix}${this.prefix} ${args[0]}`;
7086
- return this.logger[lvl](args);
7087
- }
7088
- create(moduleName) {
7089
- return new Logger(this.logger, {
7090
- prefix: `${this.prefix}:${moduleName}:`,
7091
- ...this.options
7092
- });
7093
- }
7094
- clone(options) {
7095
- options = options || this.options;
7096
- options.prefix = options.prefix || this.prefix;
7097
- return new Logger(this.logger, options);
7098
- }
7099
- }();
7100
- var EventEmitter = class {
7101
- constructor() {
7102
- this.observers = {};
7103
- }
7104
- on(events, listener) {
7105
- events.split(" ").forEach((event) => {
7106
- if (!this.observers[event]) this.observers[event] = /* @__PURE__ */ new Map();
7107
- const numListeners = this.observers[event].get(listener) || 0;
7108
- this.observers[event].set(listener, numListeners + 1);
7109
- });
7110
- return this;
7111
- }
7112
- off(event, listener) {
7113
- if (!this.observers[event]) return;
7114
- if (!listener) {
7115
- delete this.observers[event];
7116
- return;
7117
- }
7118
- this.observers[event].delete(listener);
7119
- }
7120
- emit(event, ...args) {
7121
- if (this.observers[event]) Array.from(this.observers[event].entries()).forEach(([observer, numTimesAdded]) => {
7122
- for (let i = 0; i < numTimesAdded; i++) observer(...args);
7123
- });
7124
- if (this.observers["*"]) Array.from(this.observers["*"].entries()).forEach(([observer, numTimesAdded]) => {
7125
- for (let i = 0; i < numTimesAdded; i++) observer.apply(observer, [event, ...args]);
7126
- });
7127
- }
7128
- };
7129
- var ResourceStore = class extends EventEmitter {
7130
- constructor(data, options = {
7131
- ns: ["translation"],
7132
- defaultNS: "translation"
7133
- }) {
7134
- super();
7135
- this.data = data || {};
7136
- this.options = options;
7137
- if (this.options.keySeparator === void 0) this.options.keySeparator = ".";
7138
- if (this.options.ignoreJSONStructure === void 0) this.options.ignoreJSONStructure = true;
7139
- }
7140
- addNamespaces(ns) {
7141
- if (this.options.ns.indexOf(ns) < 0) this.options.ns.push(ns);
7142
- }
7143
- removeNamespaces(ns) {
7144
- const index = this.options.ns.indexOf(ns);
7145
- if (index > -1) this.options.ns.splice(index, 1);
7146
- }
7147
- getResource(lng, ns, key, options = {}) {
7148
- const keySeparator = options.keySeparator !== void 0 ? options.keySeparator : this.options.keySeparator;
7149
- const ignoreJSONStructure = options.ignoreJSONStructure !== void 0 ? options.ignoreJSONStructure : this.options.ignoreJSONStructure;
7150
- let path;
7151
- if (lng.indexOf(".") > -1) path = lng.split(".");
7152
- else {
7153
- path = [lng, ns];
7154
- if (key) if (Array.isArray(key)) path.push(...key);
7155
- else if (isString$2(key) && keySeparator) path.push(...key.split(keySeparator));
7156
- else path.push(key);
7157
- }
7158
- const result = getPath(this.data, path);
7159
- if (!result && !ns && !key && lng.indexOf(".") > -1) {
7160
- lng = path[0];
7161
- ns = path[1];
7162
- key = path.slice(2).join(".");
7163
- }
7164
- if (result || !ignoreJSONStructure || !isString$2(key)) return result;
7165
- return deepFind(this.data?.[lng]?.[ns], key, keySeparator);
7166
- }
7167
- addResource(lng, ns, key, value, options = { silent: false }) {
7168
- const keySeparator = options.keySeparator !== void 0 ? options.keySeparator : this.options.keySeparator;
7169
- let path = [lng, ns];
7170
- if (key) path = path.concat(keySeparator ? key.split(keySeparator) : key);
7171
- if (lng.indexOf(".") > -1) {
7172
- path = lng.split(".");
7173
- value = ns;
7174
- ns = path[1];
7175
- }
7176
- this.addNamespaces(ns);
7177
- setPath(this.data, path, value);
7178
- if (!options.silent) this.emit("added", lng, ns, key, value);
7179
- }
7180
- addResources(lng, ns, resources, options = { silent: false }) {
7181
- for (const m in resources) if (isString$2(resources[m]) || Array.isArray(resources[m])) this.addResource(lng, ns, m, resources[m], { silent: true });
7182
- if (!options.silent) this.emit("added", lng, ns, resources);
7183
- }
7184
- addResourceBundle(lng, ns, resources, deep, overwrite, options = {
7185
- silent: false,
7186
- skipCopy: false
7187
- }) {
7188
- let path = [lng, ns];
7189
- if (lng.indexOf(".") > -1) {
7190
- path = lng.split(".");
7191
- deep = resources;
7192
- resources = ns;
7193
- ns = path[1];
7194
- }
7195
- this.addNamespaces(ns);
7196
- let pack = getPath(this.data, path) || {};
7197
- if (!options.skipCopy) resources = JSON.parse(JSON.stringify(resources));
7198
- if (deep) deepExtend(pack, resources, overwrite);
7199
- else pack = {
7200
- ...pack,
7201
- ...resources
7202
- };
7203
- setPath(this.data, path, pack);
7204
- if (!options.silent) this.emit("added", lng, ns, resources);
7205
- }
7206
- removeResourceBundle(lng, ns) {
7207
- if (this.hasResourceBundle(lng, ns)) delete this.data[lng][ns];
7208
- this.removeNamespaces(ns);
7209
- this.emit("removed", lng, ns);
7210
- }
7211
- hasResourceBundle(lng, ns) {
7212
- return this.getResource(lng, ns) !== void 0;
7213
- }
7214
- getResourceBundle(lng, ns) {
7215
- if (!ns) ns = this.options.defaultNS;
7216
- return this.getResource(lng, ns);
7217
- }
7218
- getDataByLanguage(lng) {
7219
- return this.data[lng];
7220
- }
7221
- hasLanguageSomeTranslations(lng) {
7222
- const data = this.getDataByLanguage(lng);
7223
- return !!(data && Object.keys(data) || []).find((v) => data[v] && Object.keys(data[v]).length > 0);
7224
- }
7225
- toJSON() {
7226
- return this.data;
7227
- }
7228
- };
7229
- var postProcessor = {
7230
- processors: {},
7231
- addPostProcessor(module) {
7232
- this.processors[module.name] = module;
7233
- },
7234
- handle(processors, value, key, options, translator) {
7235
- processors.forEach((processor) => {
7236
- value = this.processors[processor]?.process(value, key, options, translator) ?? value;
7237
- });
7238
- return value;
7239
- }
7240
- };
7241
- var PATH_KEY = Symbol("i18next/PATH_KEY");
7242
- function createProxy() {
7243
- const state = [];
7244
- const handler = Object.create(null);
7245
- let proxy;
7246
- handler.get = (target, key) => {
7247
- proxy?.revoke?.();
7248
- if (key === PATH_KEY) return state;
7249
- state.push(key);
7250
- proxy = Proxy.revocable(target, handler);
7251
- return proxy.proxy;
7252
- };
7253
- return Proxy.revocable(Object.create(null), handler).proxy;
7254
- }
7255
- function keysFromSelector(selector, opts) {
7256
- const { [PATH_KEY]: path } = selector(createProxy());
7257
- const keySeparator = opts?.keySeparator ?? ".";
7258
- const nsSeparator = opts?.nsSeparator ?? ":";
7259
- if (path.length > 1 && nsSeparator) {
7260
- const ns = opts?.ns;
7261
- const nsArray = Array.isArray(ns) ? ns : null;
7262
- if (nsArray && nsArray.length > 1 && nsArray.slice(1).includes(path[0])) return `${path[0]}${nsSeparator}${path.slice(1).join(keySeparator)}`;
7263
- }
7264
- return path.join(keySeparator);
7265
- }
7266
- var checkedLoadedFor = {};
7267
- var shouldHandleAsObject = (res) => !isString$2(res) && typeof res !== "boolean" && typeof res !== "number";
7268
- var Translator = class Translator extends EventEmitter {
7269
- constructor(services, options = {}) {
7270
- super();
7271
- copy([
7272
- "resourceStore",
7273
- "languageUtils",
7274
- "pluralResolver",
7275
- "interpolator",
7276
- "backendConnector",
7277
- "i18nFormat",
7278
- "utils"
7279
- ], services, this);
7280
- this.options = options;
7281
- if (this.options.keySeparator === void 0) this.options.keySeparator = ".";
7282
- this.logger = baseLogger.create("translator");
7283
- }
7284
- changeLanguage(lng) {
7285
- if (lng) this.language = lng;
7286
- }
7287
- exists(key, o = { interpolation: {} }) {
7288
- const opt = { ...o };
7289
- if (key == null) return false;
7290
- const resolved = this.resolve(key, opt);
7291
- if (resolved?.res === void 0) return false;
7292
- const isObject = shouldHandleAsObject(resolved.res);
7293
- if (opt.returnObjects === false && isObject) return false;
7294
- return true;
7295
- }
7296
- extractFromKey(key, opt) {
7297
- let nsSeparator = opt.nsSeparator !== void 0 ? opt.nsSeparator : this.options.nsSeparator;
7298
- if (nsSeparator === void 0) nsSeparator = ":";
7299
- const keySeparator = opt.keySeparator !== void 0 ? opt.keySeparator : this.options.keySeparator;
7300
- let namespaces = opt.ns || this.options.defaultNS || [];
7301
- const wouldCheckForNsInKey = nsSeparator && key.indexOf(nsSeparator) > -1;
7302
- const seemsNaturalLanguage = !this.options.userDefinedKeySeparator && !opt.keySeparator && !this.options.userDefinedNsSeparator && !opt.nsSeparator && !looksLikeObjectPath(key, nsSeparator, keySeparator);
7303
- if (wouldCheckForNsInKey && !seemsNaturalLanguage) {
7304
- const m = key.match(this.interpolator.nestingRegexp);
7305
- if (m && m.length > 0) return {
7306
- key,
7307
- namespaces: isString$2(namespaces) ? [namespaces] : namespaces
7308
- };
7309
- const parts = key.split(nsSeparator);
7310
- if (nsSeparator !== keySeparator || nsSeparator === keySeparator && this.options.ns.indexOf(parts[0]) > -1) namespaces = parts.shift();
7311
- key = parts.join(keySeparator);
7312
- }
7313
- return {
7314
- key,
7315
- namespaces: isString$2(namespaces) ? [namespaces] : namespaces
7316
- };
7317
- }
7318
- translate(keys, o, lastKey) {
7319
- let opt = typeof o === "object" ? { ...o } : o;
7320
- if (typeof opt !== "object" && this.options.overloadTranslationOptionHandler) opt = this.options.overloadTranslationOptionHandler(arguments);
7321
- if (typeof opt === "object") opt = { ...opt };
7322
- if (!opt) opt = {};
7323
- if (keys == null) return "";
7324
- if (typeof keys === "function") keys = keysFromSelector(keys, {
7325
- ...this.options,
7326
- ...opt
7327
- });
7328
- if (!Array.isArray(keys)) keys = [String(keys)];
7329
- keys = keys.map((k) => typeof k === "function" ? keysFromSelector(k, {
7330
- ...this.options,
7331
- ...opt
7332
- }) : String(k));
7333
- const returnDetails = opt.returnDetails !== void 0 ? opt.returnDetails : this.options.returnDetails;
7334
- const keySeparator = opt.keySeparator !== void 0 ? opt.keySeparator : this.options.keySeparator;
7335
- const { key, namespaces } = this.extractFromKey(keys[keys.length - 1], opt);
7336
- const namespace = namespaces[namespaces.length - 1];
7337
- let nsSeparator = opt.nsSeparator !== void 0 ? opt.nsSeparator : this.options.nsSeparator;
7338
- if (nsSeparator === void 0) nsSeparator = ":";
7339
- const lng = opt.lng || this.language;
7340
- const appendNamespaceToCIMode = opt.appendNamespaceToCIMode || this.options.appendNamespaceToCIMode;
7341
- if (lng?.toLowerCase() === "cimode") {
7342
- if (appendNamespaceToCIMode) {
7343
- if (returnDetails) return {
7344
- res: `${namespace}${nsSeparator}${key}`,
7345
- usedKey: key,
7346
- exactUsedKey: key,
7347
- usedLng: lng,
7348
- usedNS: namespace,
7349
- usedParams: this.getUsedParamsDetails(opt)
7350
- };
7351
- return `${namespace}${nsSeparator}${key}`;
7352
- }
7353
- if (returnDetails) return {
7354
- res: key,
7355
- usedKey: key,
7356
- exactUsedKey: key,
7357
- usedLng: lng,
7358
- usedNS: namespace,
7359
- usedParams: this.getUsedParamsDetails(opt)
7360
- };
7361
- return key;
7362
- }
7363
- const resolved = this.resolve(keys, opt);
7364
- let res = resolved?.res;
7365
- const resUsedKey = resolved?.usedKey || key;
7366
- const resExactUsedKey = resolved?.exactUsedKey || key;
7367
- const noObject = [
7368
- "[object Number]",
7369
- "[object Function]",
7370
- "[object RegExp]"
7371
- ];
7372
- const joinArrays = opt.joinArrays !== void 0 ? opt.joinArrays : this.options.joinArrays;
7373
- const handleAsObjectInI18nFormat = !this.i18nFormat || this.i18nFormat.handleAsObject;
7374
- const needsPluralHandling = opt.count !== void 0 && !isString$2(opt.count);
7375
- const hasDefaultValue = Translator.hasDefaultValue(opt);
7376
- const defaultValueSuffix = needsPluralHandling ? this.pluralResolver.getSuffix(lng, opt.count, opt) : "";
7377
- const defaultValueSuffixOrdinalFallback = opt.ordinal && needsPluralHandling ? this.pluralResolver.getSuffix(lng, opt.count, { ordinal: false }) : "";
7378
- const needsZeroSuffixLookup = needsPluralHandling && !opt.ordinal && opt.count === 0;
7379
- const defaultValue = needsZeroSuffixLookup && opt[`defaultValue${this.options.pluralSeparator}zero`] || opt[`defaultValue${defaultValueSuffix}`] || opt[`defaultValue${defaultValueSuffixOrdinalFallback}`] || opt.defaultValue;
7380
- let resForObjHndl = res;
7381
- if (handleAsObjectInI18nFormat && !res && hasDefaultValue) resForObjHndl = defaultValue;
7382
- const handleAsObject = shouldHandleAsObject(resForObjHndl);
7383
- const resType = Object.prototype.toString.apply(resForObjHndl);
7384
- if (handleAsObjectInI18nFormat && resForObjHndl && handleAsObject && noObject.indexOf(resType) < 0 && !(isString$2(joinArrays) && Array.isArray(resForObjHndl))) {
7385
- if (!opt.returnObjects && !this.options.returnObjects) {
7386
- if (!this.options.returnedObjectHandler) this.logger.warn("accessing an object - but returnObjects options is not enabled!");
7387
- const r = this.options.returnedObjectHandler ? this.options.returnedObjectHandler(resUsedKey, resForObjHndl, {
7388
- ...opt,
7389
- ns: namespaces
7390
- }) : `key '${key} (${this.language})' returned an object instead of string.`;
7391
- if (returnDetails) {
7392
- resolved.res = r;
7393
- resolved.usedParams = this.getUsedParamsDetails(opt);
7394
- return resolved;
7395
- }
7396
- return r;
7397
- }
7398
- if (keySeparator) {
7399
- const resTypeIsArray = Array.isArray(resForObjHndl);
7400
- const copy = resTypeIsArray ? [] : {};
7401
- const newKeyToUse = resTypeIsArray ? resExactUsedKey : resUsedKey;
7402
- for (const m in resForObjHndl) if (Object.prototype.hasOwnProperty.call(resForObjHndl, m)) {
7403
- const deepKey = `${newKeyToUse}${keySeparator}${m}`;
7404
- if (hasDefaultValue && !res) copy[m] = this.translate(deepKey, {
7405
- ...opt,
7406
- defaultValue: shouldHandleAsObject(defaultValue) ? defaultValue[m] : void 0,
7407
- joinArrays: false,
7408
- ns: namespaces
7409
- });
7410
- else copy[m] = this.translate(deepKey, {
7411
- ...opt,
7412
- joinArrays: false,
7413
- ns: namespaces
7414
- });
7415
- if (copy[m] === deepKey) copy[m] = resForObjHndl[m];
7416
- }
7417
- res = copy;
7418
- }
7419
- } else if (handleAsObjectInI18nFormat && isString$2(joinArrays) && Array.isArray(res)) {
7420
- res = res.join(joinArrays);
7421
- if (res) res = this.extendTranslation(res, keys, opt, lastKey);
7422
- } else {
7423
- let usedDefault = false;
7424
- let usedKey = false;
7425
- if (!this.isValidLookup(res) && hasDefaultValue) {
7426
- usedDefault = true;
7427
- res = defaultValue;
7428
- }
7429
- if (!this.isValidLookup(res)) {
7430
- usedKey = true;
7431
- res = key;
7432
- }
7433
- const resForMissing = (opt.missingKeyNoValueFallbackToKey || this.options.missingKeyNoValueFallbackToKey) && usedKey ? void 0 : res;
7434
- const updateMissing = hasDefaultValue && defaultValue !== res && this.options.updateMissing;
7435
- if (usedKey || usedDefault || updateMissing) {
7436
- this.logger.log(updateMissing ? "updateKey" : "missingKey", lng, namespace, key, updateMissing ? defaultValue : res);
7437
- if (keySeparator) {
7438
- const fk = this.resolve(key, {
7439
- ...opt,
7440
- keySeparator: false
7441
- });
7442
- if (fk && fk.res) this.logger.warn("Seems the loaded translations were in flat JSON format instead of nested. Either set keySeparator: false on init or make sure your translations are published in nested format.");
7443
- }
7444
- let lngs = [];
7445
- const fallbackLngs = this.languageUtils.getFallbackCodes(this.options.fallbackLng, opt.lng || this.language);
7446
- if (this.options.saveMissingTo === "fallback" && fallbackLngs && fallbackLngs[0]) for (let i = 0; i < fallbackLngs.length; i++) lngs.push(fallbackLngs[i]);
7447
- else if (this.options.saveMissingTo === "all") lngs = this.languageUtils.toResolveHierarchy(opt.lng || this.language);
7448
- else lngs.push(opt.lng || this.language);
7449
- const send = (l, k, specificDefaultValue) => {
7450
- const defaultForMissing = hasDefaultValue && specificDefaultValue !== res ? specificDefaultValue : resForMissing;
7451
- if (this.options.missingKeyHandler) this.options.missingKeyHandler(l, namespace, k, defaultForMissing, updateMissing, opt);
7452
- else if (this.backendConnector?.saveMissing) this.backendConnector.saveMissing(l, namespace, k, defaultForMissing, updateMissing, opt);
7453
- this.emit("missingKey", l, namespace, k, res);
7454
- };
7455
- if (this.options.saveMissing) if (this.options.saveMissingPlurals && needsPluralHandling) lngs.forEach((language) => {
7456
- const suffixes = this.pluralResolver.getSuffixes(language, opt);
7457
- if (needsZeroSuffixLookup && opt[`defaultValue${this.options.pluralSeparator}zero`] && suffixes.indexOf(`${this.options.pluralSeparator}zero`) < 0) suffixes.push(`${this.options.pluralSeparator}zero`);
7458
- suffixes.forEach((suffix) => {
7459
- send([language], key + suffix, opt[`defaultValue${suffix}`] || defaultValue);
7460
- });
7461
- });
7462
- else send(lngs, key, defaultValue);
7463
- }
7464
- res = this.extendTranslation(res, keys, opt, resolved, lastKey);
7465
- if (usedKey && res === key && this.options.appendNamespaceToMissingKey) res = `${namespace}${nsSeparator}${key}`;
7466
- if ((usedKey || usedDefault) && this.options.parseMissingKeyHandler) res = this.options.parseMissingKeyHandler(this.options.appendNamespaceToMissingKey ? `${namespace}${nsSeparator}${key}` : key, usedDefault ? res : void 0, opt);
7467
- }
7468
- if (returnDetails) {
7469
- resolved.res = res;
7470
- resolved.usedParams = this.getUsedParamsDetails(opt);
7471
- return resolved;
7472
- }
7473
- return res;
7474
- }
7475
- extendTranslation(res, key, opt, resolved, lastKey) {
7476
- if (this.i18nFormat?.parse) res = this.i18nFormat.parse(res, {
7477
- ...this.options.interpolation.defaultVariables,
7478
- ...opt
7479
- }, opt.lng || this.language || resolved.usedLng, resolved.usedNS, resolved.usedKey, { resolved });
7480
- else if (!opt.skipInterpolation) {
7481
- if (opt.interpolation) this.interpolator.init({
7482
- ...opt,
7483
- interpolation: {
7484
- ...this.options.interpolation,
7485
- ...opt.interpolation
7486
- }
7487
- });
7488
- const skipOnVariables = isString$2(res) && (opt?.interpolation?.skipOnVariables !== void 0 ? opt.interpolation.skipOnVariables : this.options.interpolation.skipOnVariables);
7489
- let nestBef;
7490
- if (skipOnVariables) {
7491
- const nb = res.match(this.interpolator.nestingRegexp);
7492
- nestBef = nb && nb.length;
7493
- }
7494
- let data = opt.replace && !isString$2(opt.replace) ? opt.replace : opt;
7495
- if (this.options.interpolation.defaultVariables) data = {
7496
- ...this.options.interpolation.defaultVariables,
7497
- ...data
7498
- };
7499
- res = this.interpolator.interpolate(res, data, opt.lng || this.language || resolved.usedLng, opt);
7500
- if (skipOnVariables) {
7501
- const na = res.match(this.interpolator.nestingRegexp);
7502
- const nestAft = na && na.length;
7503
- if (nestBef < nestAft) opt.nest = false;
7504
- }
7505
- if (!opt.lng && resolved && resolved.res) opt.lng = this.language || resolved.usedLng;
7506
- if (opt.nest !== false) res = this.interpolator.nest(res, (...args) => {
7507
- if (lastKey?.[0] === args[0] && !opt.context) {
7508
- this.logger.warn(`It seems you are nesting recursively key: ${args[0]} in key: ${key[0]}`);
7509
- return null;
7510
- }
7511
- return this.translate(...args, key);
7512
- }, opt);
7513
- if (opt.interpolation) this.interpolator.reset();
7514
- }
7515
- const postProcess = opt.postProcess || this.options.postProcess;
7516
- const postProcessorNames = isString$2(postProcess) ? [postProcess] : postProcess;
7517
- if (res != null && postProcessorNames?.length && opt.applyPostProcessor !== false) res = postProcessor.handle(postProcessorNames, res, key, this.options && this.options.postProcessPassResolved ? {
7518
- i18nResolved: {
7519
- ...resolved,
7520
- usedParams: this.getUsedParamsDetails(opt)
7521
- },
7522
- ...opt
7523
- } : opt, this);
7524
- return res;
7525
- }
7526
- resolve(keys, opt = {}) {
7527
- let found;
7528
- let usedKey;
7529
- let exactUsedKey;
7530
- let usedLng;
7531
- let usedNS;
7532
- if (isString$2(keys)) keys = [keys];
7533
- if (Array.isArray(keys)) keys = keys.map((k) => typeof k === "function" ? keysFromSelector(k, {
7534
- ...this.options,
7535
- ...opt
7536
- }) : k);
7537
- keys.forEach((k) => {
7538
- if (this.isValidLookup(found)) return;
7539
- const extracted = this.extractFromKey(k, opt);
7540
- const key = extracted.key;
7541
- usedKey = key;
7542
- let namespaces = extracted.namespaces;
7543
- if (this.options.fallbackNS) namespaces = namespaces.concat(this.options.fallbackNS);
7544
- const needsPluralHandling = opt.count !== void 0 && !isString$2(opt.count);
7545
- const needsZeroSuffixLookup = needsPluralHandling && !opt.ordinal && opt.count === 0;
7546
- const needsContextHandling = opt.context !== void 0 && (isString$2(opt.context) || typeof opt.context === "number") && opt.context !== "";
7547
- const codes = opt.lngs ? opt.lngs : this.languageUtils.toResolveHierarchy(opt.lng || this.language, opt.fallbackLng);
7548
- namespaces.forEach((ns) => {
7549
- if (this.isValidLookup(found)) return;
7550
- usedNS = ns;
7551
- if (!checkedLoadedFor[`${codes[0]}-${ns}`] && this.utils?.hasLoadedNamespace && !this.utils?.hasLoadedNamespace(usedNS)) {
7552
- checkedLoadedFor[`${codes[0]}-${ns}`] = true;
7553
- this.logger.warn(`key "${usedKey}" for languages "${codes.join(", ")}" won't get resolved as namespace "${usedNS}" was not yet loaded`, "This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!");
7554
- }
7555
- codes.forEach((code) => {
7556
- if (this.isValidLookup(found)) return;
7557
- usedLng = code;
7558
- const finalKeys = [key];
7559
- if (this.i18nFormat?.addLookupKeys) this.i18nFormat.addLookupKeys(finalKeys, key, code, ns, opt);
7560
- else {
7561
- let pluralSuffix;
7562
- if (needsPluralHandling) pluralSuffix = this.pluralResolver.getSuffix(code, opt.count, opt);
7563
- const zeroSuffix = `${this.options.pluralSeparator}zero`;
7564
- const ordinalPrefix = `${this.options.pluralSeparator}ordinal${this.options.pluralSeparator}`;
7565
- if (needsPluralHandling) {
7566
- if (opt.ordinal && pluralSuffix.indexOf(ordinalPrefix) === 0) finalKeys.push(key + pluralSuffix.replace(ordinalPrefix, this.options.pluralSeparator));
7567
- finalKeys.push(key + pluralSuffix);
7568
- if (needsZeroSuffixLookup) finalKeys.push(key + zeroSuffix);
7569
- }
7570
- if (needsContextHandling) {
7571
- const contextKey = `${key}${this.options.contextSeparator || "_"}${opt.context}`;
7572
- finalKeys.push(contextKey);
7573
- if (needsPluralHandling) {
7574
- if (opt.ordinal && pluralSuffix.indexOf(ordinalPrefix) === 0) finalKeys.push(contextKey + pluralSuffix.replace(ordinalPrefix, this.options.pluralSeparator));
7575
- finalKeys.push(contextKey + pluralSuffix);
7576
- if (needsZeroSuffixLookup) finalKeys.push(contextKey + zeroSuffix);
7577
- }
7578
- }
7579
- }
7580
- let possibleKey;
7581
- while (possibleKey = finalKeys.pop()) if (!this.isValidLookup(found)) {
7582
- exactUsedKey = possibleKey;
7583
- found = this.getResource(code, ns, possibleKey, opt);
7584
- }
7585
- });
7586
- });
7587
- });
7588
- return {
7589
- res: found,
7590
- usedKey,
7591
- exactUsedKey,
7592
- usedLng,
7593
- usedNS
7594
- };
7595
- }
7596
- isValidLookup(res) {
7597
- return res !== void 0 && !(!this.options.returnNull && res === null) && !(!this.options.returnEmptyString && res === "");
7598
- }
7599
- getResource(code, ns, key, options = {}) {
7600
- if (this.i18nFormat?.getResource) return this.i18nFormat.getResource(code, ns, key, options);
7601
- return this.resourceStore.getResource(code, ns, key, options);
7602
- }
7603
- getUsedParamsDetails(options = {}) {
7604
- const optionsKeys = [
7605
- "defaultValue",
7606
- "ordinal",
7607
- "context",
7608
- "replace",
7609
- "lng",
7610
- "lngs",
7611
- "fallbackLng",
7612
- "ns",
7613
- "keySeparator",
7614
- "nsSeparator",
7615
- "returnObjects",
7616
- "returnDetails",
7617
- "joinArrays",
7618
- "postProcess",
7619
- "interpolation"
7620
- ];
7621
- const useOptionsReplaceForData = options.replace && !isString$2(options.replace);
7622
- let data = useOptionsReplaceForData ? options.replace : options;
7623
- if (useOptionsReplaceForData && typeof options.count !== "undefined") data.count = options.count;
7624
- if (this.options.interpolation.defaultVariables) data = {
7625
- ...this.options.interpolation.defaultVariables,
7626
- ...data
7627
- };
7628
- if (!useOptionsReplaceForData) {
7629
- data = { ...data };
7630
- for (const key of optionsKeys) delete data[key];
7631
- }
7632
- return data;
7633
- }
7634
- static hasDefaultValue(options) {
7635
- const prefix = "defaultValue";
7636
- for (const option in options) if (Object.prototype.hasOwnProperty.call(options, option) && prefix === option.substring(0, 12) && void 0 !== options[option]) return true;
7637
- return false;
7638
- }
7639
- };
7640
- var LanguageUtil = class {
7641
- constructor(options) {
7642
- this.options = options;
7643
- this.supportedLngs = this.options.supportedLngs || false;
7644
- this.logger = baseLogger.create("languageUtils");
7645
- }
7646
- getScriptPartFromCode(code) {
7647
- code = getCleanedCode(code);
7648
- if (!code || code.indexOf("-") < 0) return null;
7649
- const p = code.split("-");
7650
- if (p.length === 2) return null;
7651
- p.pop();
7652
- if (p[p.length - 1].toLowerCase() === "x") return null;
7653
- return this.formatLanguageCode(p.join("-"));
7654
- }
7655
- getLanguagePartFromCode(code) {
7656
- code = getCleanedCode(code);
7657
- if (!code || code.indexOf("-") < 0) return code;
7658
- const p = code.split("-");
7659
- return this.formatLanguageCode(p[0]);
7660
- }
7661
- formatLanguageCode(code) {
7662
- if (isString$2(code) && code.indexOf("-") > -1) {
7663
- let formattedCode;
7664
- try {
7665
- formattedCode = Intl.getCanonicalLocales(code)[0];
7666
- } catch (e) {}
7667
- if (formattedCode && this.options.lowerCaseLng) formattedCode = formattedCode.toLowerCase();
7668
- if (formattedCode) return formattedCode;
7669
- if (this.options.lowerCaseLng) return code.toLowerCase();
7670
- return code;
7671
- }
7672
- return this.options.cleanCode || this.options.lowerCaseLng ? code.toLowerCase() : code;
7673
- }
7674
- isSupportedCode(code) {
7675
- if (this.options.load === "languageOnly" || this.options.nonExplicitSupportedLngs) code = this.getLanguagePartFromCode(code);
7676
- return !this.supportedLngs || !this.supportedLngs.length || this.supportedLngs.indexOf(code) > -1;
7677
- }
7678
- getBestMatchFromCodes(codes) {
7679
- if (!codes) return null;
7680
- let found;
7681
- codes.forEach((code) => {
7682
- if (found) return;
7683
- const cleanedLng = this.formatLanguageCode(code);
7684
- if (!this.options.supportedLngs || this.isSupportedCode(cleanedLng)) found = cleanedLng;
7685
- });
7686
- if (!found && this.options.supportedLngs) codes.forEach((code) => {
7687
- if (found) return;
7688
- const lngScOnly = this.getScriptPartFromCode(code);
7689
- if (this.isSupportedCode(lngScOnly)) return found = lngScOnly;
7690
- const lngOnly = this.getLanguagePartFromCode(code);
7691
- if (this.isSupportedCode(lngOnly)) return found = lngOnly;
7692
- found = this.options.supportedLngs.find((supportedLng) => {
7693
- if (supportedLng === lngOnly) return supportedLng;
7694
- if (supportedLng.indexOf("-") < 0 && lngOnly.indexOf("-") < 0) return;
7695
- if (supportedLng.indexOf("-") > 0 && lngOnly.indexOf("-") < 0 && supportedLng.substring(0, supportedLng.indexOf("-")) === lngOnly) return supportedLng;
7696
- if (supportedLng.indexOf(lngOnly) === 0 && lngOnly.length > 1) return supportedLng;
7697
- });
7698
- });
7699
- if (!found) found = this.getFallbackCodes(this.options.fallbackLng)[0];
7700
- return found;
7701
- }
7702
- getFallbackCodes(fallbacks, code) {
7703
- if (!fallbacks) return [];
7704
- if (typeof fallbacks === "function") fallbacks = fallbacks(code);
7705
- if (isString$2(fallbacks)) fallbacks = [fallbacks];
7706
- if (Array.isArray(fallbacks)) return fallbacks;
7707
- if (!code) return fallbacks.default || [];
7708
- let found = fallbacks[code];
7709
- if (!found) found = fallbacks[this.getScriptPartFromCode(code)];
7710
- if (!found) found = fallbacks[this.formatLanguageCode(code)];
7711
- if (!found) found = fallbacks[this.getLanguagePartFromCode(code)];
7712
- if (!found) found = fallbacks.default;
7713
- return found || [];
7714
- }
7715
- toResolveHierarchy(code, fallbackCode) {
7716
- const fallbackCodes = this.getFallbackCodes((fallbackCode === false ? [] : fallbackCode) || this.options.fallbackLng || [], code);
7717
- const codes = [];
7718
- const addCode = (c) => {
7719
- if (!c) return;
7720
- if (this.isSupportedCode(c)) codes.push(c);
7721
- else this.logger.warn(`rejecting language code not found in supportedLngs: ${c}`);
7722
- };
7723
- if (isString$2(code) && (code.indexOf("-") > -1 || code.indexOf("_") > -1)) {
7724
- if (this.options.load !== "languageOnly") addCode(this.formatLanguageCode(code));
7725
- if (this.options.load !== "languageOnly" && this.options.load !== "currentOnly") addCode(this.getScriptPartFromCode(code));
7726
- if (this.options.load !== "currentOnly") addCode(this.getLanguagePartFromCode(code));
7727
- } else if (isString$2(code)) addCode(this.formatLanguageCode(code));
7728
- fallbackCodes.forEach((fc) => {
7729
- if (codes.indexOf(fc) < 0) addCode(this.formatLanguageCode(fc));
7730
- });
7731
- return codes;
7732
- }
7733
- };
7734
- var suffixesOrder = {
7735
- zero: 0,
7736
- one: 1,
7737
- two: 2,
7738
- few: 3,
7739
- many: 4,
7740
- other: 5
7741
- };
7742
- var dummyRule = {
7743
- select: (count) => count === 1 ? "one" : "other",
7744
- resolvedOptions: () => ({ pluralCategories: ["one", "other"] })
7745
- };
7746
- var PluralResolver = class {
7747
- constructor(languageUtils, options = {}) {
7748
- this.languageUtils = languageUtils;
7749
- this.options = options;
7750
- this.logger = baseLogger.create("pluralResolver");
7751
- this.pluralRulesCache = {};
7752
- }
7753
- clearCache() {
7754
- this.pluralRulesCache = {};
7755
- }
7756
- getRule(code, options = {}) {
7757
- const cleanedCode = getCleanedCode(code === "dev" ? "en" : code);
7758
- const type = options.ordinal ? "ordinal" : "cardinal";
7759
- const cacheKey = JSON.stringify({
7760
- cleanedCode,
7761
- type
7762
- });
7763
- if (cacheKey in this.pluralRulesCache) return this.pluralRulesCache[cacheKey];
7764
- let rule;
7765
- try {
7766
- rule = new Intl.PluralRules(cleanedCode, { type });
7767
- } catch (err) {
7768
- if (typeof Intl === "undefined") {
7769
- this.logger.error("No Intl support, please use an Intl polyfill!");
7770
- return dummyRule;
7771
- }
7772
- if (!code.match(/-|_/)) return dummyRule;
7773
- const lngPart = this.languageUtils.getLanguagePartFromCode(code);
7774
- rule = this.getRule(lngPart, options);
7775
- }
7776
- this.pluralRulesCache[cacheKey] = rule;
7777
- return rule;
7778
- }
7779
- needsPlural(code, options = {}) {
7780
- let rule = this.getRule(code, options);
7781
- if (!rule) rule = this.getRule("dev", options);
7782
- return rule?.resolvedOptions().pluralCategories.length > 1;
7783
- }
7784
- getPluralFormsOfKey(code, key, options = {}) {
7785
- return this.getSuffixes(code, options).map((suffix) => `${key}${suffix}`);
7786
- }
7787
- getSuffixes(code, options = {}) {
7788
- let rule = this.getRule(code, options);
7789
- if (!rule) rule = this.getRule("dev", options);
7790
- if (!rule) return [];
7791
- return rule.resolvedOptions().pluralCategories.sort((pluralCategory1, pluralCategory2) => suffixesOrder[pluralCategory1] - suffixesOrder[pluralCategory2]).map((pluralCategory) => `${this.options.prepend}${options.ordinal ? `ordinal${this.options.prepend}` : ""}${pluralCategory}`);
7792
- }
7793
- getSuffix(code, count, options = {}) {
7794
- const rule = this.getRule(code, options);
7795
- if (rule) return `${this.options.prepend}${options.ordinal ? `ordinal${this.options.prepend}` : ""}${rule.select(count)}`;
7796
- this.logger.warn(`no plural rule found for: ${code}`);
7797
- return this.getSuffix("dev", count, options);
7798
- }
7799
- };
7800
- var deepFindWithDefaults = (data, defaultData, key, keySeparator = ".", ignoreJSONStructure = true) => {
7801
- let path = getPathWithDefaults(data, defaultData, key);
7802
- if (!path && ignoreJSONStructure && isString$2(key)) {
7803
- path = deepFind(data, key, keySeparator);
7804
- if (path === void 0) path = deepFind(defaultData, key, keySeparator);
7805
- }
7806
- return path;
7807
- };
7808
- var regexSafe = (val) => val.replace(/\$/g, "$$$$");
7809
- var Interpolator = class {
7810
- constructor(options = {}) {
7811
- this.logger = baseLogger.create("interpolator");
7812
- this.options = options;
7813
- this.format = options?.interpolation?.format || ((value) => value);
7814
- this.init(options);
7815
- }
7816
- init(options = {}) {
7817
- if (!options.interpolation) options.interpolation = { escapeValue: true };
7818
- const { escape: escape$1, escapeValue, useRawValueToEscape, prefix, prefixEscaped, suffix, suffixEscaped, formatSeparator, unescapeSuffix, unescapePrefix, nestingPrefix, nestingPrefixEscaped, nestingSuffix, nestingSuffixEscaped, nestingOptionsSeparator, maxReplaces, alwaysFormat } = options.interpolation;
7819
- this.escape = escape$1 !== void 0 ? escape$1 : escape;
7820
- this.escapeValue = escapeValue !== void 0 ? escapeValue : true;
7821
- this.useRawValueToEscape = useRawValueToEscape !== void 0 ? useRawValueToEscape : false;
7822
- this.prefix = prefix ? regexEscape(prefix) : prefixEscaped || "{{";
7823
- this.suffix = suffix ? regexEscape(suffix) : suffixEscaped || "}}";
7824
- this.formatSeparator = formatSeparator || ",";
7825
- this.unescapePrefix = unescapeSuffix ? "" : unescapePrefix || "-";
7826
- this.unescapeSuffix = this.unescapePrefix ? "" : unescapeSuffix || "";
7827
- this.nestingPrefix = nestingPrefix ? regexEscape(nestingPrefix) : nestingPrefixEscaped || regexEscape("$t(");
7828
- this.nestingSuffix = nestingSuffix ? regexEscape(nestingSuffix) : nestingSuffixEscaped || regexEscape(")");
7829
- this.nestingOptionsSeparator = nestingOptionsSeparator || ",";
7830
- this.maxReplaces = maxReplaces || 1e3;
7831
- this.alwaysFormat = alwaysFormat !== void 0 ? alwaysFormat : false;
7832
- this.resetRegExp();
7833
- }
7834
- reset() {
7835
- if (this.options) this.init(this.options);
7836
- }
7837
- resetRegExp() {
7838
- const getOrResetRegExp = (existingRegExp, pattern) => {
7839
- if (existingRegExp?.source === pattern) {
7840
- existingRegExp.lastIndex = 0;
7841
- return existingRegExp;
7842
- }
7843
- return new RegExp(pattern, "g");
7844
- };
7845
- this.regexp = getOrResetRegExp(this.regexp, `${this.prefix}(.+?)${this.suffix}`);
7846
- this.regexpUnescape = getOrResetRegExp(this.regexpUnescape, `${this.prefix}${this.unescapePrefix}(.+?)${this.unescapeSuffix}${this.suffix}`);
7847
- this.nestingRegexp = getOrResetRegExp(this.nestingRegexp, `${this.nestingPrefix}((?:[^()"']+|"[^"]*"|'[^']*'|\\((?:[^()]|"[^"]*"|'[^']*')*\\))*?)${this.nestingSuffix}`);
7848
- }
7849
- interpolate(str, data, lng, options) {
7850
- let match;
7851
- let value;
7852
- let replaces;
7853
- const defaultData = this.options && this.options.interpolation && this.options.interpolation.defaultVariables || {};
7854
- const handleFormat = (key) => {
7855
- if (key.indexOf(this.formatSeparator) < 0) {
7856
- const path = deepFindWithDefaults(data, defaultData, key, this.options.keySeparator, this.options.ignoreJSONStructure);
7857
- return this.alwaysFormat ? this.format(path, void 0, lng, {
7858
- ...options,
7859
- ...data,
7860
- interpolationkey: key
7861
- }) : path;
7862
- }
7863
- const p = key.split(this.formatSeparator);
7864
- const k = p.shift().trim();
7865
- const f = p.join(this.formatSeparator).trim();
7866
- return this.format(deepFindWithDefaults(data, defaultData, k, this.options.keySeparator, this.options.ignoreJSONStructure), f, lng, {
7867
- ...options,
7868
- ...data,
7869
- interpolationkey: k
7870
- });
7871
- };
7872
- this.resetRegExp();
7873
- const missingInterpolationHandler = options?.missingInterpolationHandler || this.options.missingInterpolationHandler;
7874
- const skipOnVariables = options?.interpolation?.skipOnVariables !== void 0 ? options.interpolation.skipOnVariables : this.options.interpolation.skipOnVariables;
7875
- [{
7876
- regex: this.regexpUnescape,
7877
- safeValue: (val) => regexSafe(val)
7878
- }, {
7879
- regex: this.regexp,
7880
- safeValue: (val) => this.escapeValue ? regexSafe(this.escape(val)) : regexSafe(val)
7881
- }].forEach((todo) => {
7882
- replaces = 0;
7883
- while (match = todo.regex.exec(str)) {
7884
- const matchedVar = match[1].trim();
7885
- value = handleFormat(matchedVar);
7886
- if (value === void 0) if (typeof missingInterpolationHandler === "function") {
7887
- const temp = missingInterpolationHandler(str, match, options);
7888
- value = isString$2(temp) ? temp : "";
7889
- } else if (options && Object.prototype.hasOwnProperty.call(options, matchedVar)) value = "";
7890
- else if (skipOnVariables) {
7891
- value = match[0];
7892
- continue;
7893
- } else {
7894
- this.logger.warn(`missed to pass in variable ${matchedVar} for interpolating ${str}`);
7895
- value = "";
7896
- }
7897
- else if (!isString$2(value) && !this.useRawValueToEscape) value = makeString(value);
7898
- const safeValue = todo.safeValue(value);
7899
- str = str.replace(match[0], safeValue);
7900
- if (skipOnVariables) {
7901
- todo.regex.lastIndex += value.length;
7902
- todo.regex.lastIndex -= match[0].length;
7903
- } else todo.regex.lastIndex = 0;
7904
- replaces++;
7905
- if (replaces >= this.maxReplaces) break;
7906
- }
7907
- });
7908
- return str;
7909
- }
7910
- nest(str, fc, options = {}) {
7911
- let match;
7912
- let value;
7913
- let clonedOptions;
7914
- const handleHasOptions = (key, inheritedOptions) => {
7915
- const sep = this.nestingOptionsSeparator;
7916
- if (key.indexOf(sep) < 0) return key;
7917
- const c = key.split(new RegExp(`${regexEscape(sep)}[ ]*{`));
7918
- let optionsString = `{${c[1]}`;
7919
- key = c[0];
7920
- optionsString = this.interpolate(optionsString, clonedOptions);
7921
- const matchedSingleQuotes = optionsString.match(/'/g);
7922
- const matchedDoubleQuotes = optionsString.match(/"/g);
7923
- if ((matchedSingleQuotes?.length ?? 0) % 2 === 0 && !matchedDoubleQuotes || (matchedDoubleQuotes?.length ?? 0) % 2 !== 0) optionsString = optionsString.replace(/'/g, "\"");
7924
- try {
7925
- clonedOptions = JSON.parse(optionsString);
7926
- if (inheritedOptions) clonedOptions = {
7927
- ...inheritedOptions,
7928
- ...clonedOptions
7929
- };
7930
- } catch (e) {
7931
- this.logger.warn(`failed parsing options string in nesting for key ${key}`, e);
7932
- return `${key}${sep}${optionsString}`;
7933
- }
7934
- if (clonedOptions.defaultValue && clonedOptions.defaultValue.indexOf(this.prefix) > -1) delete clonedOptions.defaultValue;
7935
- return key;
7936
- };
7937
- while (match = this.nestingRegexp.exec(str)) {
7938
- let formatters = [];
7939
- clonedOptions = { ...options };
7940
- clonedOptions = clonedOptions.replace && !isString$2(clonedOptions.replace) ? clonedOptions.replace : clonedOptions;
7941
- clonedOptions.applyPostProcessor = false;
7942
- delete clonedOptions.defaultValue;
7943
- const keyEndIndex = /{.*}/.test(match[1]) ? match[1].lastIndexOf("}") + 1 : match[1].indexOf(this.formatSeparator);
7944
- if (keyEndIndex !== -1) {
7945
- formatters = match[1].slice(keyEndIndex).split(this.formatSeparator).map((elem) => elem.trim()).filter(Boolean);
7946
- match[1] = match[1].slice(0, keyEndIndex);
7947
- }
7948
- value = fc(handleHasOptions.call(this, match[1].trim(), clonedOptions), clonedOptions);
7949
- if (value && match[0] === str && !isString$2(value)) return value;
7950
- if (!isString$2(value)) value = makeString(value);
7951
- if (!value) {
7952
- this.logger.warn(`missed to resolve ${match[1]} for nesting ${str}`);
7953
- value = "";
7954
- }
7955
- if (formatters.length) value = formatters.reduce((v, f) => this.format(v, f, options.lng, {
7956
- ...options,
7957
- interpolationkey: match[1].trim()
7958
- }), value.trim());
7959
- str = str.replace(match[0], value);
7960
- this.regexp.lastIndex = 0;
7961
- }
7962
- return str;
7963
- }
7964
- };
7965
- var parseFormatStr = (formatStr) => {
7966
- let formatName = formatStr.toLowerCase().trim();
7967
- const formatOptions = {};
7968
- if (formatStr.indexOf("(") > -1) {
7969
- const p = formatStr.split("(");
7970
- formatName = p[0].toLowerCase().trim();
7971
- const optStr = p[1].substring(0, p[1].length - 1);
7972
- if (formatName === "currency" && optStr.indexOf(":") < 0) {
7973
- if (!formatOptions.currency) formatOptions.currency = optStr.trim();
7974
- } else if (formatName === "relativetime" && optStr.indexOf(":") < 0) {
7975
- if (!formatOptions.range) formatOptions.range = optStr.trim();
7976
- } else optStr.split(";").forEach((opt) => {
7977
- if (opt) {
7978
- const [key, ...rest] = opt.split(":");
7979
- const val = rest.join(":").trim().replace(/^'+|'+$/g, "");
7980
- const trimmedKey = key.trim();
7981
- if (!formatOptions[trimmedKey]) formatOptions[trimmedKey] = val;
7982
- if (val === "false") formatOptions[trimmedKey] = false;
7983
- if (val === "true") formatOptions[trimmedKey] = true;
7984
- if (!isNaN(val)) formatOptions[trimmedKey] = parseInt(val, 10);
7985
- }
7986
- });
7987
- }
7988
- return {
7989
- formatName,
7990
- formatOptions
7991
- };
7992
- };
7993
- var createCachedFormatter = (fn) => {
7994
- const cache = {};
7995
- return (v, l, o) => {
7996
- let optForCache = o;
7997
- if (o && o.interpolationkey && o.formatParams && o.formatParams[o.interpolationkey] && o[o.interpolationkey]) optForCache = {
7998
- ...optForCache,
7999
- [o.interpolationkey]: void 0
8000
- };
8001
- const key = l + JSON.stringify(optForCache);
8002
- let frm = cache[key];
8003
- if (!frm) {
8004
- frm = fn(getCleanedCode(l), o);
8005
- cache[key] = frm;
8006
- }
8007
- return frm(v);
8008
- };
8009
- };
8010
- var createNonCachedFormatter = (fn) => (v, l, o) => fn(getCleanedCode(l), o)(v);
8011
- var Formatter = class {
8012
- constructor(options = {}) {
8013
- this.logger = baseLogger.create("formatter");
8014
- this.options = options;
8015
- this.init(options);
8016
- }
8017
- init(services, options = { interpolation: {} }) {
8018
- this.formatSeparator = options.interpolation.formatSeparator || ",";
8019
- const cf = options.cacheInBuiltFormats ? createCachedFormatter : createNonCachedFormatter;
8020
- this.formats = {
8021
- number: cf((lng, opt) => {
8022
- const formatter = new Intl.NumberFormat(lng, { ...opt });
8023
- return (val) => formatter.format(val);
8024
- }),
8025
- currency: cf((lng, opt) => {
8026
- const formatter = new Intl.NumberFormat(lng, {
8027
- ...opt,
8028
- style: "currency"
8029
- });
8030
- return (val) => formatter.format(val);
8031
- }),
8032
- datetime: cf((lng, opt) => {
8033
- const formatter = new Intl.DateTimeFormat(lng, { ...opt });
8034
- return (val) => formatter.format(val);
8035
- }),
8036
- relativetime: cf((lng, opt) => {
8037
- const formatter = new Intl.RelativeTimeFormat(lng, { ...opt });
8038
- return (val) => formatter.format(val, opt.range || "day");
8039
- }),
8040
- list: cf((lng, opt) => {
8041
- const formatter = new Intl.ListFormat(lng, { ...opt });
8042
- return (val) => formatter.format(val);
8043
- })
8044
- };
8045
- }
8046
- add(name, fc) {
8047
- this.formats[name.toLowerCase().trim()] = fc;
8048
- }
8049
- addCached(name, fc) {
8050
- this.formats[name.toLowerCase().trim()] = createCachedFormatter(fc);
8051
- }
8052
- format(value, format, lng, options = {}) {
8053
- const formats = format.split(this.formatSeparator);
8054
- if (formats.length > 1 && formats[0].indexOf("(") > 1 && formats[0].indexOf(")") < 0 && formats.find((f) => f.indexOf(")") > -1)) {
8055
- const lastIndex = formats.findIndex((f) => f.indexOf(")") > -1);
8056
- formats[0] = [formats[0], ...formats.splice(1, lastIndex)].join(this.formatSeparator);
8057
- }
8058
- return formats.reduce((mem, f) => {
8059
- const { formatName, formatOptions } = parseFormatStr(f);
8060
- if (this.formats[formatName]) {
8061
- let formatted = mem;
8062
- try {
8063
- const valOptions = options?.formatParams?.[options.interpolationkey] || {};
8064
- const l = valOptions.locale || valOptions.lng || options.locale || options.lng || lng;
8065
- formatted = this.formats[formatName](mem, l, {
8066
- ...formatOptions,
8067
- ...options,
8068
- ...valOptions
8069
- });
8070
- } catch (error) {
8071
- this.logger.warn(error);
8072
- }
8073
- return formatted;
8074
- } else this.logger.warn(`there was no format function for ${formatName}`);
8075
- return mem;
8076
- }, value);
8077
- }
8078
- };
8079
- var removePending = (q, name) => {
8080
- if (q.pending[name] !== void 0) {
8081
- delete q.pending[name];
8082
- q.pendingCount--;
8083
- }
8084
- };
8085
- var Connector = class extends EventEmitter {
8086
- constructor(backend, store, services, options = {}) {
8087
- super();
8088
- this.backend = backend;
8089
- this.store = store;
8090
- this.services = services;
8091
- this.languageUtils = services.languageUtils;
8092
- this.options = options;
8093
- this.logger = baseLogger.create("backendConnector");
8094
- this.waitingReads = [];
8095
- this.maxParallelReads = options.maxParallelReads || 10;
8096
- this.readingCalls = 0;
8097
- this.maxRetries = options.maxRetries >= 0 ? options.maxRetries : 5;
8098
- this.retryTimeout = options.retryTimeout >= 1 ? options.retryTimeout : 350;
8099
- this.state = {};
8100
- this.queue = [];
8101
- this.backend?.init?.(services, options.backend, options);
8102
- }
8103
- queueLoad(languages, namespaces, options, callback) {
8104
- const toLoad = {};
8105
- const pending = {};
8106
- const toLoadLanguages = {};
8107
- const toLoadNamespaces = {};
8108
- languages.forEach((lng) => {
8109
- let hasAllNamespaces = true;
8110
- namespaces.forEach((ns) => {
8111
- const name = `${lng}|${ns}`;
8112
- if (!options.reload && this.store.hasResourceBundle(lng, ns)) this.state[name] = 2;
8113
- else if (this.state[name] < 0);
8114
- else if (this.state[name] === 1) {
8115
- if (pending[name] === void 0) pending[name] = true;
8116
- } else {
8117
- this.state[name] = 1;
8118
- hasAllNamespaces = false;
8119
- if (pending[name] === void 0) pending[name] = true;
8120
- if (toLoad[name] === void 0) toLoad[name] = true;
8121
- if (toLoadNamespaces[ns] === void 0) toLoadNamespaces[ns] = true;
8122
- }
8123
- });
8124
- if (!hasAllNamespaces) toLoadLanguages[lng] = true;
8125
- });
8126
- if (Object.keys(toLoad).length || Object.keys(pending).length) this.queue.push({
8127
- pending,
8128
- pendingCount: Object.keys(pending).length,
8129
- loaded: {},
8130
- errors: [],
8131
- callback
8132
- });
8133
- return {
8134
- toLoad: Object.keys(toLoad),
8135
- pending: Object.keys(pending),
8136
- toLoadLanguages: Object.keys(toLoadLanguages),
8137
- toLoadNamespaces: Object.keys(toLoadNamespaces)
8138
- };
8139
- }
8140
- loaded(name, err, data) {
8141
- const s = name.split("|");
8142
- const lng = s[0];
8143
- const ns = s[1];
8144
- if (err) this.emit("failedLoading", lng, ns, err);
8145
- if (!err && data) this.store.addResourceBundle(lng, ns, data, void 0, void 0, { skipCopy: true });
8146
- this.state[name] = err ? -1 : 2;
8147
- if (err && data) this.state[name] = 0;
8148
- const loaded = {};
8149
- this.queue.forEach((q) => {
8150
- pushPath(q.loaded, [lng], ns);
8151
- removePending(q, name);
8152
- if (err) q.errors.push(err);
8153
- if (q.pendingCount === 0 && !q.done) {
8154
- Object.keys(q.loaded).forEach((l) => {
8155
- if (!loaded[l]) loaded[l] = {};
8156
- const loadedKeys = q.loaded[l];
8157
- if (loadedKeys.length) loadedKeys.forEach((n) => {
8158
- if (loaded[l][n] === void 0) loaded[l][n] = true;
8159
- });
8160
- });
8161
- q.done = true;
8162
- if (q.errors.length) q.callback(q.errors);
8163
- else q.callback();
8164
- }
8165
- });
8166
- this.emit("loaded", loaded);
8167
- this.queue = this.queue.filter((q) => !q.done);
8168
- }
8169
- read(lng, ns, fcName, tried = 0, wait = this.retryTimeout, callback) {
8170
- if (!lng.length) return callback(null, {});
8171
- if (this.readingCalls >= this.maxParallelReads) {
8172
- this.waitingReads.push({
8173
- lng,
8174
- ns,
8175
- fcName,
8176
- tried,
8177
- wait,
8178
- callback
8179
- });
8180
- return;
8181
- }
8182
- this.readingCalls++;
8183
- const resolver = (err, data) => {
8184
- this.readingCalls--;
8185
- if (this.waitingReads.length > 0) {
8186
- const next = this.waitingReads.shift();
8187
- this.read(next.lng, next.ns, next.fcName, next.tried, next.wait, next.callback);
8188
- }
8189
- if (err && data && tried < this.maxRetries) {
8190
- setTimeout(() => {
8191
- this.read.call(this, lng, ns, fcName, tried + 1, wait * 2, callback);
8192
- }, wait);
8193
- return;
8194
- }
8195
- callback(err, data);
8196
- };
8197
- const fc = this.backend[fcName].bind(this.backend);
8198
- if (fc.length === 2) {
8199
- try {
8200
- const r = fc(lng, ns);
8201
- if (r && typeof r.then === "function") r.then((data) => resolver(null, data)).catch(resolver);
8202
- else resolver(null, r);
8203
- } catch (err) {
8204
- resolver(err);
8205
- }
8206
- return;
8207
- }
8208
- return fc(lng, ns, resolver);
8209
- }
8210
- prepareLoading(languages, namespaces, options = {}, callback) {
8211
- if (!this.backend) {
8212
- this.logger.warn("No backend was added via i18next.use. Will not load resources.");
8213
- return callback && callback();
8214
- }
8215
- if (isString$2(languages)) languages = this.languageUtils.toResolveHierarchy(languages);
8216
- if (isString$2(namespaces)) namespaces = [namespaces];
8217
- const toLoad = this.queueLoad(languages, namespaces, options, callback);
8218
- if (!toLoad.toLoad.length) {
8219
- if (!toLoad.pending.length) callback();
8220
- return null;
8221
- }
8222
- toLoad.toLoad.forEach((name) => {
8223
- this.loadOne(name);
8224
- });
8225
- }
8226
- load(languages, namespaces, callback) {
8227
- this.prepareLoading(languages, namespaces, {}, callback);
8228
- }
8229
- reload(languages, namespaces, callback) {
8230
- this.prepareLoading(languages, namespaces, { reload: true }, callback);
8231
- }
8232
- loadOne(name, prefix = "") {
8233
- const s = name.split("|");
8234
- const lng = s[0];
8235
- const ns = s[1];
8236
- this.read(lng, ns, "read", void 0, void 0, (err, data) => {
8237
- if (err) this.logger.warn(`${prefix}loading namespace ${ns} for language ${lng} failed`, err);
8238
- if (!err && data) this.logger.log(`${prefix}loaded namespace ${ns} for language ${lng}`, data);
8239
- this.loaded(name, err, data);
8240
- });
8241
- }
8242
- saveMissing(languages, namespace, key, fallbackValue, isUpdate, options = {}, clb = () => {}) {
8243
- if (this.services?.utils?.hasLoadedNamespace && !this.services?.utils?.hasLoadedNamespace(namespace)) {
8244
- this.logger.warn(`did not save key "${key}" as the namespace "${namespace}" was not yet loaded`, "This means something IS WRONG in your setup. You access the t function before i18next.init / i18next.loadNamespace / i18next.changeLanguage was done. Wait for the callback or Promise to resolve before accessing it!!!");
8245
- return;
8246
- }
8247
- if (key === void 0 || key === null || key === "") return;
8248
- if (this.backend?.create) {
8249
- const opts = {
8250
- ...options,
8251
- isUpdate
8252
- };
8253
- const fc = this.backend.create.bind(this.backend);
8254
- if (fc.length < 6) try {
8255
- let r;
8256
- if (fc.length === 5) r = fc(languages, namespace, key, fallbackValue, opts);
8257
- else r = fc(languages, namespace, key, fallbackValue);
8258
- if (r && typeof r.then === "function") r.then((data) => clb(null, data)).catch(clb);
8259
- else clb(null, r);
8260
- } catch (err) {
8261
- clb(err);
8262
- }
8263
- else fc(languages, namespace, key, fallbackValue, clb, opts);
8264
- }
8265
- if (!languages || !languages[0]) return;
8266
- this.store.addResource(languages[0], namespace, key, fallbackValue);
8267
- }
8268
- };
8269
- var get$3 = () => ({
8270
- debug: false,
8271
- initAsync: true,
8272
- ns: ["translation"],
8273
- defaultNS: ["translation"],
8274
- fallbackLng: ["dev"],
8275
- fallbackNS: false,
8276
- supportedLngs: false,
8277
- nonExplicitSupportedLngs: false,
8278
- load: "all",
8279
- preload: false,
8280
- simplifyPluralSuffix: true,
8281
- keySeparator: ".",
8282
- nsSeparator: ":",
8283
- pluralSeparator: "_",
8284
- contextSeparator: "_",
8285
- partialBundledLanguages: false,
8286
- saveMissing: false,
8287
- updateMissing: false,
8288
- saveMissingTo: "fallback",
8289
- saveMissingPlurals: true,
8290
- missingKeyHandler: false,
8291
- missingInterpolationHandler: false,
8292
- postProcess: false,
8293
- postProcessPassResolved: false,
8294
- returnNull: false,
8295
- returnEmptyString: true,
8296
- returnObjects: false,
8297
- joinArrays: false,
8298
- returnedObjectHandler: false,
8299
- parseMissingKeyHandler: false,
8300
- appendNamespaceToMissingKey: false,
8301
- appendNamespaceToCIMode: false,
8302
- overloadTranslationOptionHandler: (args) => {
8303
- let ret = {};
8304
- if (typeof args[1] === "object") ret = args[1];
8305
- if (isString$2(args[1])) ret.defaultValue = args[1];
8306
- if (isString$2(args[2])) ret.tDescription = args[2];
8307
- if (typeof args[2] === "object" || typeof args[3] === "object") {
8308
- const options = args[3] || args[2];
8309
- Object.keys(options).forEach((key) => {
8310
- ret[key] = options[key];
8311
- });
8312
- }
8313
- return ret;
8314
- },
8315
- interpolation: {
8316
- escapeValue: true,
8317
- format: (value) => value,
8318
- prefix: "{{",
8319
- suffix: "}}",
8320
- formatSeparator: ",",
8321
- unescapePrefix: "-",
8322
- nestingPrefix: "$t(",
8323
- nestingSuffix: ")",
8324
- nestingOptionsSeparator: ",",
8325
- maxReplaces: 1e3,
8326
- skipOnVariables: true
8327
- },
8328
- cacheInBuiltFormats: true
8329
- });
8330
- var transformOptions = (options) => {
8331
- if (isString$2(options.ns)) options.ns = [options.ns];
8332
- if (isString$2(options.fallbackLng)) options.fallbackLng = [options.fallbackLng];
8333
- if (isString$2(options.fallbackNS)) options.fallbackNS = [options.fallbackNS];
8334
- if (options.supportedLngs?.indexOf?.("cimode") < 0) options.supportedLngs = options.supportedLngs.concat(["cimode"]);
8335
- if (typeof options.initImmediate === "boolean") options.initAsync = options.initImmediate;
8336
- return options;
8337
- };
8338
- var noop = () => {};
8339
- var bindMemberFunctions = (inst) => {
8340
- Object.getOwnPropertyNames(Object.getPrototypeOf(inst)).forEach((mem) => {
8341
- if (typeof inst[mem] === "function") inst[mem] = inst[mem].bind(inst);
8342
- });
8343
- };
8344
- var SUPPORT_NOTICE_KEY = "__i18next_supportNoticeShown";
8345
- var getSupportNoticeShown = () => {
8346
- if (typeof globalThis !== "undefined" && !!globalThis[SUPPORT_NOTICE_KEY]) return true;
8347
- if (typeof process !== "undefined" && process.env && process.env.I18NEXT_NO_SUPPORT_NOTICE) return true;
8348
- if (typeof process !== "undefined" && process.env && process.env.NODE_ENV === "production") return true;
8349
- return false;
8350
- };
8351
- var setSupportNoticeShown = () => {
8352
- if (typeof globalThis !== "undefined") globalThis[SUPPORT_NOTICE_KEY] = true;
8353
- };
8354
- var usesLocize = (inst) => {
8355
- if (inst?.modules?.backend?.name?.indexOf("Locize") > 0) return true;
8356
- if (inst?.modules?.backend?.constructor?.name?.indexOf("Locize") > 0) return true;
8357
- if (inst?.options?.backend?.backends) {
8358
- if (inst.options.backend.backends.some((b) => b?.name?.indexOf("Locize") > 0 || b?.constructor?.name?.indexOf("Locize") > 0)) return true;
8359
- }
8360
- if (inst?.options?.backend?.projectId) return true;
8361
- if (inst?.options?.backend?.backendOptions) {
8362
- if (inst.options.backend.backendOptions.some((b) => b?.projectId)) return true;
8363
- }
8364
- return false;
8365
- };
8366
- var instance = class I18n extends EventEmitter {
8367
- constructor(options = {}, callback) {
8368
- super();
8369
- this.options = transformOptions(options);
8370
- this.services = {};
8371
- this.logger = baseLogger;
8372
- this.modules = { external: [] };
8373
- bindMemberFunctions(this);
8374
- if (callback && !this.isInitialized && !options.isClone) {
8375
- if (!this.options.initAsync) {
8376
- this.init(options, callback);
8377
- return this;
8378
- }
8379
- setTimeout(() => {
8380
- this.init(options, callback);
8381
- }, 0);
8382
- }
8383
- }
8384
- init(options = {}, callback) {
8385
- this.isInitializing = true;
8386
- if (typeof options === "function") {
8387
- callback = options;
8388
- options = {};
8389
- }
8390
- if (options.defaultNS == null && options.ns) {
8391
- if (isString$2(options.ns)) options.defaultNS = options.ns;
8392
- else if (options.ns.indexOf("translation") < 0) options.defaultNS = options.ns[0];
8393
- }
8394
- const defOpts = get$3();
8395
- this.options = {
8396
- ...defOpts,
8397
- ...this.options,
8398
- ...transformOptions(options)
8399
- };
8400
- this.options.interpolation = {
8401
- ...defOpts.interpolation,
8402
- ...this.options.interpolation
8403
- };
8404
- if (options.keySeparator !== void 0) this.options.userDefinedKeySeparator = options.keySeparator;
8405
- if (options.nsSeparator !== void 0) this.options.userDefinedNsSeparator = options.nsSeparator;
8406
- if (typeof this.options.overloadTranslationOptionHandler !== "function") this.options.overloadTranslationOptionHandler = defOpts.overloadTranslationOptionHandler;
8407
- if (this.options.showSupportNotice !== false && !usesLocize(this) && !getSupportNoticeShown()) {
8408
- if (typeof console !== "undefined" && typeof console.info !== "undefined") console.info("🌐 i18next is made possible by our own product, Locize — consider powering your project with managed localization (AI, CDN, integrations): https://locize.com 💙");
8409
- setSupportNoticeShown();
8410
- }
8411
- const createClassOnDemand = (ClassOrObject) => {
8412
- if (!ClassOrObject) return null;
8413
- if (typeof ClassOrObject === "function") return new ClassOrObject();
8414
- return ClassOrObject;
8415
- };
8416
- if (!this.options.isClone) {
8417
- if (this.modules.logger) baseLogger.init(createClassOnDemand(this.modules.logger), this.options);
8418
- else baseLogger.init(null, this.options);
8419
- let formatter;
8420
- if (this.modules.formatter) formatter = this.modules.formatter;
8421
- else formatter = Formatter;
8422
- const lu = new LanguageUtil(this.options);
8423
- this.store = new ResourceStore(this.options.resources, this.options);
8424
- const s = this.services;
8425
- s.logger = baseLogger;
8426
- s.resourceStore = this.store;
8427
- s.languageUtils = lu;
8428
- s.pluralResolver = new PluralResolver(lu, {
8429
- prepend: this.options.pluralSeparator,
8430
- simplifyPluralSuffix: this.options.simplifyPluralSuffix
8431
- });
8432
- if (this.options.interpolation.format && this.options.interpolation.format !== defOpts.interpolation.format) this.logger.deprecate(`init: you are still using the legacy format function, please use the new approach: https://www.i18next.com/translation-function/formatting`);
8433
- if (formatter && (!this.options.interpolation.format || this.options.interpolation.format === defOpts.interpolation.format)) {
8434
- s.formatter = createClassOnDemand(formatter);
8435
- if (s.formatter.init) s.formatter.init(s, this.options);
8436
- this.options.interpolation.format = s.formatter.format.bind(s.formatter);
8437
- }
8438
- s.interpolator = new Interpolator(this.options);
8439
- s.utils = { hasLoadedNamespace: this.hasLoadedNamespace.bind(this) };
8440
- s.backendConnector = new Connector(createClassOnDemand(this.modules.backend), s.resourceStore, s, this.options);
8441
- s.backendConnector.on("*", (event, ...args) => {
8442
- this.emit(event, ...args);
8443
- });
8444
- if (this.modules.languageDetector) {
8445
- s.languageDetector = createClassOnDemand(this.modules.languageDetector);
8446
- if (s.languageDetector.init) s.languageDetector.init(s, this.options.detection, this.options);
8447
- }
8448
- if (this.modules.i18nFormat) {
8449
- s.i18nFormat = createClassOnDemand(this.modules.i18nFormat);
8450
- if (s.i18nFormat.init) s.i18nFormat.init(this);
8451
- }
8452
- this.translator = new Translator(this.services, this.options);
8453
- this.translator.on("*", (event, ...args) => {
8454
- this.emit(event, ...args);
8455
- });
8456
- this.modules.external.forEach((m) => {
8457
- if (m.init) m.init(this);
8458
- });
8459
- }
8460
- this.format = this.options.interpolation.format;
8461
- if (!callback) callback = noop;
8462
- if (this.options.fallbackLng && !this.services.languageDetector && !this.options.lng) {
8463
- const codes = this.services.languageUtils.getFallbackCodes(this.options.fallbackLng);
8464
- if (codes.length > 0 && codes[0] !== "dev") this.options.lng = codes[0];
8465
- }
8466
- if (!this.services.languageDetector && !this.options.lng) this.logger.warn("init: no languageDetector is used and no lng is defined");
8467
- [
8468
- "getResource",
8469
- "hasResourceBundle",
8470
- "getResourceBundle",
8471
- "getDataByLanguage"
8472
- ].forEach((fcName) => {
8473
- this[fcName] = (...args) => this.store[fcName](...args);
8474
- });
8475
- [
8476
- "addResource",
8477
- "addResources",
8478
- "addResourceBundle",
8479
- "removeResourceBundle"
8480
- ].forEach((fcName) => {
8481
- this[fcName] = (...args) => {
8482
- this.store[fcName](...args);
8483
- return this;
8484
- };
8485
- });
8486
- const deferred = defer();
8487
- const load = () => {
8488
- const finish = (err, t) => {
8489
- this.isInitializing = false;
8490
- if (this.isInitialized && !this.initializedStoreOnce) this.logger.warn("init: i18next is already initialized. You should call init just once!");
8491
- this.isInitialized = true;
8492
- if (!this.options.isClone) this.logger.log("initialized", this.options);
8493
- this.emit("initialized", this.options);
8494
- deferred.resolve(t);
8495
- callback(err, t);
8496
- };
8497
- if (this.languages && !this.isInitialized) return finish(null, this.t.bind(this));
8498
- this.changeLanguage(this.options.lng, finish);
8499
- };
8500
- if (this.options.resources || !this.options.initAsync) load();
8501
- else setTimeout(load, 0);
8502
- return deferred;
8503
- }
8504
- loadResources(language, callback = noop) {
8505
- let usedCallback = callback;
8506
- const usedLng = isString$2(language) ? language : this.language;
8507
- if (typeof language === "function") usedCallback = language;
8508
- if (!this.options.resources || this.options.partialBundledLanguages) {
8509
- if (usedLng?.toLowerCase() === "cimode" && (!this.options.preload || this.options.preload.length === 0)) return usedCallback();
8510
- const toLoad = [];
8511
- const append = (lng) => {
8512
- if (!lng) return;
8513
- if (lng === "cimode") return;
8514
- this.services.languageUtils.toResolveHierarchy(lng).forEach((l) => {
8515
- if (l === "cimode") return;
8516
- if (toLoad.indexOf(l) < 0) toLoad.push(l);
8517
- });
8518
- };
8519
- if (!usedLng) this.services.languageUtils.getFallbackCodes(this.options.fallbackLng).forEach((l) => append(l));
8520
- else append(usedLng);
8521
- this.options.preload?.forEach?.((l) => append(l));
8522
- this.services.backendConnector.load(toLoad, this.options.ns, (e) => {
8523
- if (!e && !this.resolvedLanguage && this.language) this.setResolvedLanguage(this.language);
8524
- usedCallback(e);
8525
- });
8526
- } else usedCallback(null);
8527
- }
8528
- reloadResources(lngs, ns, callback) {
8529
- const deferred = defer();
8530
- if (typeof lngs === "function") {
8531
- callback = lngs;
8532
- lngs = void 0;
8533
- }
8534
- if (typeof ns === "function") {
8535
- callback = ns;
8536
- ns = void 0;
8537
- }
8538
- if (!lngs) lngs = this.languages;
8539
- if (!ns) ns = this.options.ns;
8540
- if (!callback) callback = noop;
8541
- this.services.backendConnector.reload(lngs, ns, (err) => {
8542
- deferred.resolve();
8543
- callback(err);
8544
- });
8545
- return deferred;
8546
- }
8547
- use(module) {
8548
- if (!module) throw new Error("You are passing an undefined module! Please check the object you are passing to i18next.use()");
8549
- if (!module.type) throw new Error("You are passing a wrong module! Please check the object you are passing to i18next.use()");
8550
- if (module.type === "backend") this.modules.backend = module;
8551
- if (module.type === "logger" || module.log && module.warn && module.error) this.modules.logger = module;
8552
- if (module.type === "languageDetector") this.modules.languageDetector = module;
8553
- if (module.type === "i18nFormat") this.modules.i18nFormat = module;
8554
- if (module.type === "postProcessor") postProcessor.addPostProcessor(module);
8555
- if (module.type === "formatter") this.modules.formatter = module;
8556
- if (module.type === "3rdParty") this.modules.external.push(module);
8557
- return this;
8558
- }
8559
- setResolvedLanguage(l) {
8560
- if (!l || !this.languages) return;
8561
- if (["cimode", "dev"].indexOf(l) > -1) return;
8562
- for (let li = 0; li < this.languages.length; li++) {
8563
- const lngInLngs = this.languages[li];
8564
- if (["cimode", "dev"].indexOf(lngInLngs) > -1) continue;
8565
- if (this.store.hasLanguageSomeTranslations(lngInLngs)) {
8566
- this.resolvedLanguage = lngInLngs;
8567
- break;
8568
- }
8569
- }
8570
- if (!this.resolvedLanguage && this.languages.indexOf(l) < 0 && this.store.hasLanguageSomeTranslations(l)) {
8571
- this.resolvedLanguage = l;
8572
- this.languages.unshift(l);
8573
- }
8574
- }
8575
- changeLanguage(lng, callback) {
8576
- this.isLanguageChangingTo = lng;
8577
- const deferred = defer();
8578
- this.emit("languageChanging", lng);
8579
- const setLngProps = (l) => {
8580
- this.language = l;
8581
- this.languages = this.services.languageUtils.toResolveHierarchy(l);
8582
- this.resolvedLanguage = void 0;
8583
- this.setResolvedLanguage(l);
8584
- };
8585
- const done = (err, l) => {
8586
- if (l) {
8587
- if (this.isLanguageChangingTo === lng) {
8588
- setLngProps(l);
8589
- this.translator.changeLanguage(l);
8590
- this.isLanguageChangingTo = void 0;
8591
- this.emit("languageChanged", l);
8592
- this.logger.log("languageChanged", l);
8593
- }
8594
- } else this.isLanguageChangingTo = void 0;
8595
- deferred.resolve((...args) => this.t(...args));
8596
- if (callback) callback(err, (...args) => this.t(...args));
8597
- };
8598
- const setLng = (lngs) => {
8599
- if (!lng && !lngs && this.services.languageDetector) lngs = [];
8600
- const fl = isString$2(lngs) ? lngs : lngs && lngs[0];
8601
- const l = this.store.hasLanguageSomeTranslations(fl) ? fl : this.services.languageUtils.getBestMatchFromCodes(isString$2(lngs) ? [lngs] : lngs);
8602
- if (l) {
8603
- if (!this.language) setLngProps(l);
8604
- if (!this.translator.language) this.translator.changeLanguage(l);
8605
- this.services.languageDetector?.cacheUserLanguage?.(l);
8606
- }
8607
- this.loadResources(l, (err) => {
8608
- done(err, l);
8609
- });
8610
- };
8611
- if (!lng && this.services.languageDetector && !this.services.languageDetector.async) setLng(this.services.languageDetector.detect());
8612
- else if (!lng && this.services.languageDetector && this.services.languageDetector.async) if (this.services.languageDetector.detect.length === 0) this.services.languageDetector.detect().then(setLng);
8613
- else this.services.languageDetector.detect(setLng);
8614
- else setLng(lng);
8615
- return deferred;
8616
- }
8617
- getFixedT(lng, ns, keyPrefix) {
8618
- const fixedT = (key, opts, ...rest) => {
8619
- let o;
8620
- if (typeof opts !== "object") o = this.options.overloadTranslationOptionHandler([key, opts].concat(rest));
8621
- else o = { ...opts };
8622
- o.lng = o.lng || fixedT.lng;
8623
- o.lngs = o.lngs || fixedT.lngs;
8624
- o.ns = o.ns || fixedT.ns;
8625
- if (o.keyPrefix !== "") o.keyPrefix = o.keyPrefix || keyPrefix || fixedT.keyPrefix;
8626
- const selectorOpts = {
8627
- ...this.options,
8628
- ...o
8629
- };
8630
- if (typeof o.keyPrefix === "function") o.keyPrefix = keysFromSelector(o.keyPrefix, selectorOpts);
8631
- const keySeparator = this.options.keySeparator || ".";
8632
- let resultKey;
8633
- if (o.keyPrefix && Array.isArray(key)) resultKey = key.map((k) => {
8634
- if (typeof k === "function") k = keysFromSelector(k, selectorOpts);
8635
- return `${o.keyPrefix}${keySeparator}${k}`;
8636
- });
8637
- else {
8638
- if (typeof key === "function") key = keysFromSelector(key, selectorOpts);
8639
- resultKey = o.keyPrefix ? `${o.keyPrefix}${keySeparator}${key}` : key;
8640
- }
8641
- return this.t(resultKey, o);
8642
- };
8643
- if (isString$2(lng)) fixedT.lng = lng;
8644
- else fixedT.lngs = lng;
8645
- fixedT.ns = ns;
8646
- fixedT.keyPrefix = keyPrefix;
8647
- return fixedT;
8648
- }
8649
- t(...args) {
8650
- return this.translator?.translate(...args);
8651
- }
8652
- exists(...args) {
8653
- return this.translator?.exists(...args);
8654
- }
8655
- setDefaultNamespace(ns) {
8656
- this.options.defaultNS = ns;
8657
- }
8658
- hasLoadedNamespace(ns, options = {}) {
8659
- if (!this.isInitialized) {
8660
- this.logger.warn("hasLoadedNamespace: i18next was not initialized", this.languages);
8661
- return false;
8662
- }
8663
- if (!this.languages || !this.languages.length) {
8664
- this.logger.warn("hasLoadedNamespace: i18n.languages were undefined or empty", this.languages);
8665
- return false;
8666
- }
8667
- const lng = options.lng || this.resolvedLanguage || this.languages[0];
8668
- const fallbackLng = this.options ? this.options.fallbackLng : false;
8669
- const lastLng = this.languages[this.languages.length - 1];
8670
- if (lng.toLowerCase() === "cimode") return true;
8671
- const loadNotPending = (l, n) => {
8672
- const loadState = this.services.backendConnector.state[`${l}|${n}`];
8673
- return loadState === -1 || loadState === 0 || loadState === 2;
8674
- };
8675
- if (options.precheck) {
8676
- const preResult = options.precheck(this, loadNotPending);
8677
- if (preResult !== void 0) return preResult;
8678
- }
8679
- if (this.hasResourceBundle(lng, ns)) return true;
8680
- if (!this.services.backendConnector.backend || this.options.resources && !this.options.partialBundledLanguages) return true;
8681
- if (loadNotPending(lng, ns) && (!fallbackLng || loadNotPending(lastLng, ns))) return true;
8682
- return false;
8683
- }
8684
- loadNamespaces(ns, callback) {
8685
- const deferred = defer();
8686
- if (!this.options.ns) {
8687
- if (callback) callback();
8688
- return Promise.resolve();
8689
- }
8690
- if (isString$2(ns)) ns = [ns];
8691
- ns.forEach((n) => {
8692
- if (this.options.ns.indexOf(n) < 0) this.options.ns.push(n);
8693
- });
8694
- this.loadResources((err) => {
8695
- deferred.resolve();
8696
- if (callback) callback(err);
8697
- });
8698
- return deferred;
8699
- }
8700
- loadLanguages(lngs, callback) {
8701
- const deferred = defer();
8702
- if (isString$2(lngs)) lngs = [lngs];
8703
- const preloaded = this.options.preload || [];
8704
- const newLngs = lngs.filter((lng) => preloaded.indexOf(lng) < 0 && this.services.languageUtils.isSupportedCode(lng));
8705
- if (!newLngs.length) {
8706
- if (callback) callback();
8707
- return Promise.resolve();
8708
- }
8709
- this.options.preload = preloaded.concat(newLngs);
8710
- this.loadResources((err) => {
8711
- deferred.resolve();
8712
- if (callback) callback(err);
8713
- });
8714
- return deferred;
8715
- }
8716
- dir(lng) {
8717
- if (!lng) lng = this.resolvedLanguage || (this.languages?.length > 0 ? this.languages[0] : this.language);
8718
- if (!lng) return "rtl";
8719
- try {
8720
- const l = new Intl.Locale(lng);
8721
- if (l && l.getTextInfo) {
8722
- const ti = l.getTextInfo();
8723
- if (ti && ti.direction) return ti.direction;
8724
- }
8725
- } catch (e) {}
8726
- const rtlLngs = [
8727
- "ar",
8728
- "shu",
8729
- "sqr",
8730
- "ssh",
8731
- "xaa",
8732
- "yhd",
8733
- "yud",
8734
- "aao",
8735
- "abh",
8736
- "abv",
8737
- "acm",
8738
- "acq",
8739
- "acw",
8740
- "acx",
8741
- "acy",
8742
- "adf",
8743
- "ads",
8744
- "aeb",
8745
- "aec",
8746
- "afb",
8747
- "ajp",
8748
- "apc",
8749
- "apd",
8750
- "arb",
8751
- "arq",
8752
- "ars",
8753
- "ary",
8754
- "arz",
8755
- "auz",
8756
- "avl",
8757
- "ayh",
8758
- "ayl",
8759
- "ayn",
8760
- "ayp",
8761
- "bbz",
8762
- "pga",
8763
- "he",
8764
- "iw",
8765
- "ps",
8766
- "pbt",
8767
- "pbu",
8768
- "pst",
8769
- "prp",
8770
- "prd",
8771
- "ug",
8772
- "ur",
8773
- "ydd",
8774
- "yds",
8775
- "yih",
8776
- "ji",
8777
- "yi",
8778
- "hbo",
8779
- "men",
8780
- "xmn",
8781
- "fa",
8782
- "jpr",
8783
- "peo",
8784
- "pes",
8785
- "prs",
8786
- "dv",
8787
- "sam",
8788
- "ckb"
8789
- ];
8790
- const languageUtils = this.services?.languageUtils || new LanguageUtil(get$3());
8791
- if (lng.toLowerCase().indexOf("-latn") > 1) return "ltr";
8792
- return rtlLngs.indexOf(languageUtils.getLanguagePartFromCode(lng)) > -1 || lng.toLowerCase().indexOf("-arab") > 1 ? "rtl" : "ltr";
8793
- }
8794
- static createInstance(options = {}, callback) {
8795
- const instance = new I18n(options, callback);
8796
- instance.createInstance = I18n.createInstance;
8797
- return instance;
8798
- }
8799
- cloneInstance(options = {}, callback = noop) {
8800
- const forkResourceStore = options.forkResourceStore;
8801
- if (forkResourceStore) delete options.forkResourceStore;
8802
- const mergedOptions = {
8803
- ...this.options,
8804
- ...options,
8805
- isClone: true
8806
- };
8807
- const clone = new I18n(mergedOptions);
8808
- if (options.debug !== void 0 || options.prefix !== void 0) clone.logger = clone.logger.clone(options);
8809
- [
8810
- "store",
8811
- "services",
8812
- "language"
8813
- ].forEach((m) => {
8814
- clone[m] = this[m];
8815
- });
8816
- clone.services = { ...this.services };
8817
- clone.services.utils = { hasLoadedNamespace: clone.hasLoadedNamespace.bind(clone) };
8818
- if (forkResourceStore) {
8819
- clone.store = new ResourceStore(Object.keys(this.store.data).reduce((prev, l) => {
8820
- prev[l] = { ...this.store.data[l] };
8821
- prev[l] = Object.keys(prev[l]).reduce((acc, n) => {
8822
- acc[n] = { ...prev[l][n] };
8823
- return acc;
8824
- }, prev[l]);
8825
- return prev;
8826
- }, {}), mergedOptions);
8827
- clone.services.resourceStore = clone.store;
8828
- }
8829
- if (options.interpolation) {
8830
- const mergedInterpolation = {
8831
- ...get$3().interpolation,
8832
- ...this.options.interpolation,
8833
- ...options.interpolation
8834
- };
8835
- const mergedForInterpolator = {
8836
- ...mergedOptions,
8837
- interpolation: mergedInterpolation
8838
- };
8839
- clone.services.interpolator = new Interpolator(mergedForInterpolator);
8840
- }
8841
- clone.translator = new Translator(clone.services, mergedOptions);
8842
- clone.translator.on("*", (event, ...args) => {
8843
- clone.emit(event, ...args);
8844
- });
8845
- clone.init(mergedOptions, callback);
8846
- clone.translator.options = mergedOptions;
8847
- clone.translator.backendConnector.services.utils = { hasLoadedNamespace: clone.hasLoadedNamespace.bind(clone) };
8848
- return clone;
8849
- }
8850
- toJSON() {
8851
- return {
8852
- options: this.options,
8853
- store: this.store,
8854
- language: this.language,
8855
- languages: this.languages,
8856
- resolvedLanguage: this.resolvedLanguage
8857
- };
8858
- }
8859
- }.createInstance();
8860
- instance.createInstance;
8861
- instance.dir;
8862
- instance.init;
8863
- instance.loadResources;
8864
- instance.reloadResources;
8865
- instance.use;
8866
- instance.changeLanguage;
8867
- instance.getFixedT;
8868
- var t = instance.t;
8869
- instance.exists;
8870
- instance.setDefaultNamespace;
8871
- instance.hasLoadedNamespace;
8872
- instance.loadNamespaces;
8873
- instance.loadLanguages;
8874
- //#endregion
8875
6883
  //#region ../loot-core/src/platform/exceptions/index.ts
8876
6884
  var captureException = function(exc) {
8877
6885
  logger.error("[Exception]", exc);
@@ -15857,1525 +13865,6 @@ function memoizeOne(resultFn, isEqual) {
15857
13865
  return memoized;
15858
13866
  }
15859
13867
  //#endregion
15860
- //#region ../../node_modules/ua-parser-js/src/main/ua-parser.mjs
15861
- var LIBVERSION = "2.0.9", UA_MAX_LENGTH = 500, USER_AGENT = "user-agent", EMPTY = "", UNKNOWN = "?", TYPEOF = {
15862
- FUNCTION: "function",
15863
- OBJECT: "object",
15864
- STRING: "string",
15865
- UNDEFINED: "undefined"
15866
- }, BROWSER = "browser", CPU = "cpu", DEVICE = "device", ENGINE = "engine", OS = "os", RESULT = "result", NAME$1 = "name", TYPE = "type", VENDOR = "vendor", VERSION$1 = "version", ARCHITECTURE = "architecture", MAJOR = "major", MODEL = "model", CONSOLE = "console", MOBILE = "mobile", TABLET = "tablet", SMARTTV = "smarttv", WEARABLE = "wearable", XR = "xr", EMBEDDED = "embedded", FETCHER = "fetcher", INAPP = "inapp", BRANDS = "brands", FORMFACTORS = "formFactors", FULLVERLIST = "fullVersionList", PLATFORM = "platform", PLATFORMVER = "platformVersion", BITNESS = "bitness", CH = "sec-ch-ua", CH_FULL_VER_LIST = CH + "-full-version-list", CH_ARCH = CH + "-arch", CH_BITNESS = CH + "-" + BITNESS, CH_FORM_FACTORS = CH + "-form-factors", CH_MOBILE = CH + "-" + MOBILE, CH_MODEL = CH + "-" + MODEL, CH_PLATFORM = CH + "-" + PLATFORM, CH_PLATFORM_VER = CH_PLATFORM + "-version", CH_ALL_VALUES = [
15867
- BRANDS,
15868
- FULLVERLIST,
15869
- MOBILE,
15870
- MODEL,
15871
- PLATFORM,
15872
- PLATFORMVER,
15873
- ARCHITECTURE,
15874
- FORMFACTORS,
15875
- BITNESS
15876
- ], AMAZON = "Amazon", APPLE = "Apple", ASUS = "ASUS", BLACKBERRY = "BlackBerry", GOOGLE = "Google", HUAWEI = "Huawei", LENOVO = "Lenovo", HONOR = "Honor", LG = "LG", MICROSOFT = "Microsoft", MOTOROLA = "Motorola", NVIDIA = "Nvidia", ONEPLUS = "OnePlus", OPPO = "OPPO", SAMSUNG = "Samsung", SHARP = "Sharp", SONY = "Sony", XIAOMI = "Xiaomi", ZEBRA = "Zebra", CHROME = "Chrome", CHROMIUM = "Chromium", CHROMECAST = "Chromecast", EDGE = "Edge", FIREFOX = "Firefox", OPERA = "Opera", FACEBOOK = "Facebook", SOGOU = "Sogou", PREFIX_MOBILE = "Mobile ", SUFFIX_BROWSER = " Browser", WINDOWS = "Windows";
15877
- var NAVIGATOR = typeof window !== TYPEOF.UNDEFINED && window.navigator ? window.navigator : void 0, NAVIGATOR_UADATA = NAVIGATOR && NAVIGATOR.userAgentData ? NAVIGATOR.userAgentData : void 0;
15878
- var extend = function(defaultRgx, extensions) {
15879
- var mergedRgx = {};
15880
- var extraRgx = extensions;
15881
- if (!isExtensions(extensions)) {
15882
- extraRgx = {};
15883
- for (var i in extensions) for (var j in extensions[i]) extraRgx[j] = extensions[i][j].concat(extraRgx[j] ? extraRgx[j] : []);
15884
- }
15885
- for (var k in defaultRgx) mergedRgx[k] = extraRgx[k] && extraRgx[k].length % 2 === 0 ? extraRgx[k].concat(defaultRgx[k]) : defaultRgx[k];
15886
- return mergedRgx;
15887
- }, enumerize = function(arr) {
15888
- var enums = {};
15889
- for (var i = 0; i < arr.length; i++) enums[arr[i].toUpperCase()] = arr[i];
15890
- return enums;
15891
- }, has$1 = function(str1, str2) {
15892
- if (typeof str1 === TYPEOF.OBJECT && str1.length > 0) {
15893
- for (var i in str1) if (lowerize(str2) == lowerize(str1[i])) return true;
15894
- return false;
15895
- }
15896
- return isString$1(str1) ? lowerize(str2) == lowerize(str1) : false;
15897
- }, isExtensions = function(obj, deep) {
15898
- for (var prop in obj) return /^(browser|cpu|device|engine|os)$/.test(prop) || (deep ? isExtensions(obj[prop]) : false);
15899
- }, isString$1 = function(val) {
15900
- return typeof val === TYPEOF.STRING;
15901
- }, itemListToArray = function(header) {
15902
- if (!header) return void 0;
15903
- var arr = [];
15904
- var tokens = strip(/\\?\"/g, header).split(",");
15905
- for (var i = 0; i < tokens.length; i++) if (tokens[i].indexOf(";") > -1) {
15906
- var token = trim(tokens[i]).split(";v=");
15907
- arr[i] = {
15908
- brand: token[0],
15909
- version: token[1]
15910
- };
15911
- } else arr[i] = trim(tokens[i]);
15912
- return arr;
15913
- }, lowerize = function(str) {
15914
- return isString$1(str) ? str.toLowerCase() : str;
15915
- }, majorize = function(version) {
15916
- return isString$1(version) ? strip(/[^\d\.]/g, version).split(".")[0] : void 0;
15917
- }, setProps = function(arr) {
15918
- for (var i in arr) {
15919
- if (!arr.hasOwnProperty(i)) continue;
15920
- var propName = arr[i];
15921
- if (typeof propName == TYPEOF.OBJECT && propName.length == 2) this[propName[0]] = propName[1];
15922
- else this[propName] = void 0;
15923
- }
15924
- return this;
15925
- }, strip = function(pattern, str) {
15926
- return isString$1(str) ? str.replace(pattern, EMPTY) : str;
15927
- }, stripQuotes = function(str) {
15928
- return strip(/\\?\"/g, str);
15929
- }, trim = function(str, len) {
15930
- str = strip(/^\s\s*/, String(str));
15931
- return typeof len === TYPEOF.UNDEFINED ? str : str.substring(0, len);
15932
- };
15933
- var rgxMapper = function(ua, arrays) {
15934
- if (!ua || !arrays) return;
15935
- var i = 0, j, k, p, q, matches, match;
15936
- while (i < arrays.length && !matches) {
15937
- var regex = arrays[i], props = arrays[i + 1];
15938
- j = k = 0;
15939
- while (j < regex.length && !matches) {
15940
- if (!regex[j]) break;
15941
- matches = regex[j++].exec(ua);
15942
- if (!!matches) for (p = 0; p < props.length; p++) {
15943
- match = matches[++k];
15944
- q = props[p];
15945
- if (typeof q === TYPEOF.OBJECT && q.length > 0) {
15946
- if (q.length === 2) if (typeof q[1] == TYPEOF.FUNCTION) this[q[0]] = q[1].call(this, match);
15947
- else this[q[0]] = q[1];
15948
- else if (q.length >= 3) {
15949
- if (typeof q[1] === TYPEOF.FUNCTION && !(q[1].exec && q[1].test)) if (q.length > 3) this[q[0]] = match ? q[1].apply(this, q.slice(2)) : void 0;
15950
- else this[q[0]] = match ? q[1].call(this, match, q[2]) : void 0;
15951
- else if (q.length == 3) this[q[0]] = match ? match.replace(q[1], q[2]) : void 0;
15952
- else if (q.length == 4) this[q[0]] = match ? q[3].call(this, match.replace(q[1], q[2])) : void 0;
15953
- else if (q.length > 4) this[q[0]] = match ? q[3].apply(this, [match.replace(q[1], q[2])].concat(q.slice(4))) : void 0;
15954
- }
15955
- } else this[q] = match ? match : void 0;
15956
- }
15957
- }
15958
- i += 2;
15959
- }
15960
- }, strMapper = function(str, map) {
15961
- for (var i in map) if (typeof map[i] === TYPEOF.OBJECT && map[i].length > 0) {
15962
- for (var j = 0; j < map[i].length; j++) if (has$1(map[i][j], str)) return i === UNKNOWN ? void 0 : i;
15963
- } else if (has$1(map[i], str)) return i === UNKNOWN ? void 0 : i;
15964
- return map.hasOwnProperty("*") ? map["*"] : str;
15965
- };
15966
- var windowsVersionMap = {
15967
- "ME": "4.90",
15968
- "NT 3.51": "3.51",
15969
- "NT 4.0": "4.0",
15970
- "2000": ["5.0", "5.01"],
15971
- "XP": ["5.1", "5.2"],
15972
- "Vista": "6.0",
15973
- "7": "6.1",
15974
- "8": "6.2",
15975
- "8.1": "6.3",
15976
- "10": ["6.4", "10.0"],
15977
- "NT": ""
15978
- }, formFactorsMap = {
15979
- "embedded": "Automotive",
15980
- "mobile": "Mobile",
15981
- "tablet": ["Tablet", "EInk"],
15982
- "smarttv": "TV",
15983
- "wearable": "Watch",
15984
- "xr": ["VR", "XR"],
15985
- "?": ["Desktop", "Unknown"],
15986
- "*": void 0
15987
- }, browserHintsMap = {
15988
- "Chrome": "Google Chrome",
15989
- "Edge": "Microsoft Edge",
15990
- "Edge WebView2": "Microsoft Edge WebView2",
15991
- "Chrome WebView": "Android WebView",
15992
- "Chrome Headless": "HeadlessChrome",
15993
- "Huawei Browser": "HuaweiBrowser",
15994
- "MIUI Browser": "Miui Browser",
15995
- "Opera Mobi": "OperaMobile",
15996
- "Yandex": "YaBrowser"
15997
- };
15998
- var defaultRegexes = {
15999
- browser: [
16000
- [/\b(?:crmo|crios)\/([\w\.]+)/i],
16001
- [VERSION$1, [NAME$1, PREFIX_MOBILE + "Chrome"]],
16002
- [/webview.+edge\/([\w\.]+)/i],
16003
- [VERSION$1, [NAME$1, EDGE + " WebView"]],
16004
- [/edg(?:e|ios|a)?\/([\w\.]+)/i],
16005
- [VERSION$1, [NAME$1, "Edge"]],
16006
- [
16007
- /(opera mini)\/([-\w\.]+)/i,
16008
- /(opera [mobiletab]{3,6})\b.+version\/([-\w\.]+)/i,
16009
- /(opera)(?:.+version\/|[\/ ]+)([\w\.]+)/i
16010
- ],
16011
- [NAME$1, VERSION$1],
16012
- [/opios[\/ ]+([\w\.]+)/i],
16013
- [VERSION$1, [NAME$1, OPERA + " Mini"]],
16014
- [/\bop(?:rg)?x\/([\w\.]+)/i],
16015
- [VERSION$1, [NAME$1, OPERA + " GX"]],
16016
- [/\bopr\/([\w\.]+)/i],
16017
- [VERSION$1, [NAME$1, OPERA]],
16018
- [/\bb[ai]*d(?:uhd|[ub]*[aekoprswx]{5,6})[\/ ]?([\w\.]+)/i],
16019
- [VERSION$1, [NAME$1, "Baidu"]],
16020
- [/\b(?:mxbrowser|mxios|myie2)\/?([-\w\.]*)\b/i],
16021
- [VERSION$1, [NAME$1, "Maxthon"]],
16022
- [
16023
- /(kindle)\/([\w\.]+)/i,
16024
- /(lunascape|maxthon|netfront|jasmine|blazer|sleipnir)[\/ ]?([\w\.]*)/i,
16025
- /(avant|iemobile|slim(?:browser|boat|jet))[\/ ]?([\d\.]*)/i,
16026
- /(?:ms|\()(ie) ([\w\.]+)/i,
16027
- /(atlas|flock|rockmelt|midori|epiphany|silk|skyfire|bolt|iron|vivaldi|iridium|phantomjs|bowser|qupzilla|falkon|rekonq|puffin|whale(?!.+naver)|qqbrowserlite|duckduckgo|klar|helio|(?=comodo_)?dragon|otter|dooble|(?:hi|lg |ovi|qute)browser|palemoon)\/v?([-\w\.]+)/i,
16028
- /(brave)(?: chrome)?\/([\d\.]+)/i,
16029
- /(aloha|heytap|ovi|115|surf|qwant)browser\/([\d\.]+)/i,
16030
- /(qwant)(?:ios|mobile)\/([\d\.]+)/i,
16031
- /(ecosia|weibo)(?:__| \w+@)([\d\.]+)/i
16032
- ],
16033
- [NAME$1, VERSION$1],
16034
- [/quark(?:pc)?\/([-\w\.]+)/i],
16035
- [VERSION$1, [NAME$1, "Quark"]],
16036
- [/\bddg\/([\w\.]+)/i],
16037
- [VERSION$1, [NAME$1, "DuckDuckGo"]],
16038
- [/(?:\buc? ?browser|(?:juc.+)ucweb)[\/ ]?([\w\.]+)/i],
16039
- [VERSION$1, [NAME$1, "UCBrowser"]],
16040
- [
16041
- /microm.+\bqbcore\/([\w\.]+)/i,
16042
- /\bqbcore\/([\w\.]+).+microm/i,
16043
- /micromessenger\/([\w\.]+)/i
16044
- ],
16045
- [VERSION$1, [NAME$1, "WeChat"]],
16046
- [/konqueror\/([\w\.]+)/i],
16047
- [VERSION$1, [NAME$1, "Konqueror"]],
16048
- [/trident.+rv[: ]([\w\.]{1,9})\b.+like gecko/i],
16049
- [VERSION$1, [NAME$1, "IE"]],
16050
- [/ya(?:search)?browser\/([\w\.]+)/i],
16051
- [VERSION$1, [NAME$1, "Yandex"]],
16052
- [/slbrowser\/([\w\.]+)/i],
16053
- [VERSION$1, [NAME$1, "Smart " + LENOVO + SUFFIX_BROWSER]],
16054
- [/(av(?:ast|g|ira))\/([\w\.]+)/i],
16055
- [[
16056
- NAME$1,
16057
- /(.+)/,
16058
- "$1 Secure" + SUFFIX_BROWSER
16059
- ], VERSION$1],
16060
- [/norton\/([\w\.]+)/i],
16061
- [VERSION$1, [NAME$1, "Norton Private" + SUFFIX_BROWSER]],
16062
- [/\bfocus\/([\w\.]+)/i],
16063
- [VERSION$1, [NAME$1, FIREFOX + " Focus"]],
16064
- [/ mms\/([\w\.]+)$/i],
16065
- [VERSION$1, [NAME$1, OPERA + " Neon"]],
16066
- [/ opt\/([\w\.]+)$/i],
16067
- [VERSION$1, [NAME$1, OPERA + " Touch"]],
16068
- [/coc_coc\w+\/([\w\.]+)/i],
16069
- [VERSION$1, [NAME$1, "Coc Coc"]],
16070
- [/dolfin\/([\w\.]+)/i],
16071
- [VERSION$1, [NAME$1, "Dolphin"]],
16072
- [/coast\/([\w\.]+)/i],
16073
- [VERSION$1, [NAME$1, OPERA + " Coast"]],
16074
- [/miuibrowser\/([\w\.]+)/i],
16075
- [VERSION$1, [NAME$1, "MIUI" + SUFFIX_BROWSER]],
16076
- [/fxios\/([\w\.-]+)/i],
16077
- [VERSION$1, [NAME$1, PREFIX_MOBILE + FIREFOX]],
16078
- [/\bqihoobrowser\/?([\w\.]*)/i],
16079
- [VERSION$1, [NAME$1, "360"]],
16080
- [/\b(qq)\/([\w\.]+)/i],
16081
- [[
16082
- NAME$1,
16083
- /(.+)/,
16084
- "$1Browser"
16085
- ], VERSION$1],
16086
- [/(oculus|sailfish|huawei|vivo|pico)browser\/([\w\.]+)/i],
16087
- [[
16088
- NAME$1,
16089
- /(.+)/,
16090
- "$1" + SUFFIX_BROWSER
16091
- ], VERSION$1],
16092
- [/samsungbrowser\/([\w\.]+)/i],
16093
- [VERSION$1, [NAME$1, SAMSUNG + " Internet"]],
16094
- [/metasr[\/ ]?([\d\.]+)/i],
16095
- [VERSION$1, [NAME$1, SOGOU + " Explorer"]],
16096
- [/(sogou)mo\w+\/([\d\.]+)/i],
16097
- [[NAME$1, SOGOU + " Mobile"], VERSION$1],
16098
- [
16099
- /(electron)\/([\w\.]+) safari/i,
16100
- /(tesla)(?: qtcarbrowser|\/(20\d\d\.[-\w\.]+))/i,
16101
- /m?(qqbrowser|2345(?=browser|chrome|explorer))\w*[\/ ]?v?([\w\.]+)/i
16102
- ],
16103
- [NAME$1, VERSION$1],
16104
- [/(lbbrowser|luakit|rekonq|steam(?= (clie|tenf|gameo)))/i],
16105
- [NAME$1],
16106
- [/ome\/([\w\.]+).+(iron(?= saf)|360(?=[es]e$))/i],
16107
- [VERSION$1, NAME$1],
16108
- [/((?:fban\/fbios|fb_iab\/fb4a)(?!.+fbav)|;fbav\/([\w\.]+);)/i],
16109
- [
16110
- [NAME$1, FACEBOOK],
16111
- VERSION$1,
16112
- [TYPE, INAPP]
16113
- ],
16114
- [
16115
- /(kakao(?:talk|story))[\/ ]([\w\.]+)/i,
16116
- /(naver)\(.*?(\d+\.[\w\.]+).*\)/i,
16117
- /(daum)apps[\/ ]([\w\.]+)/i,
16118
- /safari (line)\/([\w\.]+)/i,
16119
- /\b(line)\/([\w\.]+)\/iab/i,
16120
- /(alipay)client\/([\w\.]+)/i,
16121
- /(twitter)(?:and| f.+e\/([\w\.]+))/i,
16122
- /(bing)(?:web|sapphire)\/([\w\.]+)/i,
16123
- /(instagram|snapchat|klarna)[\/ ]([-\w\.]+)/i
16124
- ],
16125
- [
16126
- NAME$1,
16127
- VERSION$1,
16128
- [TYPE, INAPP]
16129
- ],
16130
- [/\bgsa\/([\w\.]+) .*safari\//i],
16131
- [
16132
- VERSION$1,
16133
- [NAME$1, "GSA"],
16134
- [TYPE, INAPP]
16135
- ],
16136
- [/(?:musical_ly|trill)(?:.+app_?version\/|_)([\w\.]+)/i],
16137
- [
16138
- VERSION$1,
16139
- [NAME$1, "TikTok"],
16140
- [TYPE, INAPP]
16141
- ],
16142
- [/\[(linkedin)app\]/i],
16143
- [NAME$1, [TYPE, INAPP]],
16144
- [/(zalo(?:app)?)[\/\sa-z]*([\w\.-]+)/i],
16145
- [
16146
- [
16147
- NAME$1,
16148
- /(.+)/,
16149
- "Zalo"
16150
- ],
16151
- VERSION$1,
16152
- [TYPE, INAPP]
16153
- ],
16154
- [/(chromium)[\/ ]([-\w\.]+)/i],
16155
- [NAME$1, VERSION$1],
16156
- [/ome-(lighthouse)$/i],
16157
- [NAME$1, [TYPE, FETCHER]],
16158
- [/headlesschrome(?:\/([\w\.]+)| )/i],
16159
- [VERSION$1, [NAME$1, CHROME + " Headless"]],
16160
- [/wv\).+chrome\/([\w\.]+).+edgw\//i],
16161
- [VERSION$1, [NAME$1, EDGE + " WebView2"]],
16162
- [/ wv\).+(chrome)\/([\w\.]+)/i],
16163
- [[NAME$1, CHROME + " WebView"], VERSION$1],
16164
- [/droid.+ version\/([\w\.]+)\b.+(?:mobile safari|safari)/i],
16165
- [VERSION$1, [NAME$1, "Android" + SUFFIX_BROWSER]],
16166
- [/chrome\/([\w\.]+) mobile/i],
16167
- [VERSION$1, [NAME$1, PREFIX_MOBILE + "Chrome"]],
16168
- [/(chrome|omniweb|arora|[tizenoka]{5} ?browser)\/v?([\w\.]+)/i],
16169
- [NAME$1, VERSION$1],
16170
- [/version\/([\w\.\,]+) .*mobile(?:\/\w+ | ?)safari/i],
16171
- [VERSION$1, [NAME$1, PREFIX_MOBILE + "Safari"]],
16172
- [/iphone .*mobile(?:\/\w+ | ?)safari/i],
16173
- [[NAME$1, PREFIX_MOBILE + "Safari"]],
16174
- [/version\/([\w\.\,]+) .*(safari)/i],
16175
- [VERSION$1, NAME$1],
16176
- [/webkit.+?(mobile ?safari|safari)(\/[\w\.]+)/i],
16177
- [NAME$1, [VERSION$1, "1"]],
16178
- [/(webkit|khtml)\/([\w\.]+)/i],
16179
- [NAME$1, VERSION$1],
16180
- [/(?:mobile|tablet);.*(firefox)\/([\w\.-]+)/i],
16181
- [[NAME$1, PREFIX_MOBILE + FIREFOX], VERSION$1],
16182
- [/(navigator|netscape\d?)\/([-\w\.]+)/i],
16183
- [[NAME$1, "Netscape"], VERSION$1],
16184
- [/(wolvic|librewolf)\/([\w\.]+)/i],
16185
- [NAME$1, VERSION$1],
16186
- [/mobile vr; rv:([\w\.]+)\).+firefox/i],
16187
- [VERSION$1, [NAME$1, FIREFOX + " Reality"]],
16188
- [
16189
- /ekiohf.+(flow)\/([\w\.]+)/i,
16190
- /(swiftfox)/i,
16191
- /(icedragon|iceweasel|camino|chimera|fennec|maemo browser|minimo|conkeror)[\/ ]?([\w\.\+]+)/i,
16192
- /(seamonkey|k-meleon|icecat|iceape|firebird|phoenix|basilisk|waterfox)\/([-\w\.]+)$/i,
16193
- /(firefox)\/([\w\.]+)/i,
16194
- /(mozilla)\/([\w\.]+(?= .+rv\:.+gecko\/\d+)|[0-4][\w\.]+(?!.+compatible))/i,
16195
- /(amaya|dillo|doris|icab|ladybird|lynx|mosaic|netsurf|obigo|polaris|w3m|(?:go|ice|up)[\. ]?browser)[-\/ ]?v?([\w\.]+)/i,
16196
- /\b(links) \(([\w\.]+)/i
16197
- ],
16198
- [NAME$1, [
16199
- VERSION$1,
16200
- /_/g,
16201
- "."
16202
- ]],
16203
- [/(cobalt)\/([\w\.]+)/i],
16204
- [NAME$1, [
16205
- VERSION$1,
16206
- /[^\d\.]+./,
16207
- EMPTY
16208
- ]]
16209
- ],
16210
- cpu: [
16211
- [/\b((amd|x|x86[-_]?|wow|win)64)\b/i],
16212
- [[ARCHITECTURE, "amd64"]],
16213
- [/(ia32(?=;))/i, /\b((i[346]|x)86)(pc)?\b/i],
16214
- [[ARCHITECTURE, "ia32"]],
16215
- [/\b(aarch64|arm(v?[89]e?l?|_?64))\b/i],
16216
- [[ARCHITECTURE, "arm64"]],
16217
- [/\b(arm(v[67])?ht?n?[fl]p?)\b/i],
16218
- [[ARCHITECTURE, "armhf"]],
16219
- [/( (ce|mobile); ppc;|\/[\w\.]+arm\b)/i],
16220
- [[ARCHITECTURE, "arm"]],
16221
- [/ sun4\w[;\)]/i],
16222
- [[ARCHITECTURE, "sparc"]],
16223
- [
16224
- /\b(avr32|ia64(?=;)|68k(?=\))|\barm(?=v([1-7]|[5-7]1)l?|;|eabi)|(irix|mips|sparc)(64)?\b|pa-risc)/i,
16225
- /((ppc|powerpc)(64)?)( mac|;|\))/i,
16226
- /(?:osf1|[freopnt]{3,4}bsd) (alpha)/i
16227
- ],
16228
- [[
16229
- ARCHITECTURE,
16230
- /ower/,
16231
- EMPTY,
16232
- lowerize
16233
- ]],
16234
- [/mc680.0/i],
16235
- [[ARCHITECTURE, "68k"]],
16236
- [/winnt.+\[axp/i],
16237
- [[ARCHITECTURE, "alpha"]]
16238
- ],
16239
- device: [
16240
- [/\b(sch-i[89]0\d|shw-m380s|sm-[ptx]\w{2,4}|gt-[pn]\d{2,4}|sgh-t8[56]9|nexus 10)/i],
16241
- [
16242
- MODEL,
16243
- [VENDOR, SAMSUNG],
16244
- [TYPE, TABLET]
16245
- ],
16246
- [
16247
- /\b((?:s[cgp]h|gt|sm)-(?![lr])\w+|sc[g-]?[\d]+a?|galaxy nexus)/i,
16248
- /samsung[- ]((?!sm-[lr]|browser)[-\w]+)/i,
16249
- /sec-(sgh\w+)/i
16250
- ],
16251
- [
16252
- MODEL,
16253
- [VENDOR, SAMSUNG],
16254
- [TYPE, MOBILE]
16255
- ],
16256
- [/(?:\/|\()(ip(?:hone|od)[\w, ]*)[\/\);]/i],
16257
- [
16258
- MODEL,
16259
- [VENDOR, APPLE],
16260
- [TYPE, MOBILE]
16261
- ],
16262
- [/\b(?:ios|apple\w+)\/.+[\(\/](ipad)/i, /\b(ipad)[\d,]*[;\] ].+(mac |i(pad)?)os/i],
16263
- [
16264
- MODEL,
16265
- [VENDOR, APPLE],
16266
- [TYPE, TABLET]
16267
- ],
16268
- [/(macintosh);/i],
16269
- [MODEL, [VENDOR, APPLE]],
16270
- [/\b(sh-?[altvz]?\d\d[a-ekm]?)/i],
16271
- [
16272
- MODEL,
16273
- [VENDOR, SHARP],
16274
- [TYPE, MOBILE]
16275
- ],
16276
- [/\b((?:brt|eln|hey2?|gdi|jdn)-a?[lnw]09|(?:ag[rm]3?|jdn2|kob2)-a?[lw]0[09]hn)(?: bui|\)|;)/i],
16277
- [
16278
- MODEL,
16279
- [VENDOR, HONOR],
16280
- [TYPE, TABLET]
16281
- ],
16282
- [/honor([-\w ]+)[;\)]/i],
16283
- [
16284
- MODEL,
16285
- [VENDOR, HONOR],
16286
- [TYPE, MOBILE]
16287
- ],
16288
- [/\b((?:ag[rs][2356]?k?|bah[234]?|bg[2o]|bt[kv]|cmr|cpn|db[ry]2?|jdn2|got|kob2?k?|mon|pce|scm|sht?|[tw]gr|vrd)-[ad]?[lw][0125][09]b?|605hw|bg2-u03|(?:gem|fdr|m2|ple|t1)-[7a]0[1-4][lu]|t1-a2[13][lw]|mediapad[\w\. ]*(?= bui|\)))\b(?!.+d\/s)/i],
16289
- [
16290
- MODEL,
16291
- [VENDOR, HUAWEI],
16292
- [TYPE, TABLET]
16293
- ],
16294
- [/(?:huawei) ?([-\w ]+)[;\)]/i, /\b(nexus 6p|\w{2,4}e?-[atu]?[ln][\dx][\dc][adnt]?)\b(?!.+d\/s)/i],
16295
- [
16296
- MODEL,
16297
- [VENDOR, HUAWEI],
16298
- [TYPE, MOBILE]
16299
- ],
16300
- [/oid[^\)]+; (2[\dbc]{4}(182|283|rp\w{2})[cgl]|m2105k81a?c)(?: bui|\))/i, /\b(?:xiao)?((?:red)?mi[-_ ]?pad[\w- ]*)(?: bui|\))/i],
16301
- [
16302
- [
16303
- MODEL,
16304
- /_/g,
16305
- " "
16306
- ],
16307
- [VENDOR, XIAOMI],
16308
- [TYPE, TABLET]
16309
- ],
16310
- [
16311
- /\b; (\w+) build\/hm\1/i,
16312
- /\b(hm[-_ ]?note?[_ ]?(?:\d\w)?) bui/i,
16313
- /oid[^\)]+; (redmi[\-_ ]?(?:note|k)?[\w_ ]+|m?[12]\d[01]\d\w{3,6}|poco[\w ]+|(shark )?\w{3}-[ah]0|qin ?[1-3](s\+|ultra| pro)?)( bui|; wv|\))/i,
16314
- /\b(mi[-_ ]?(?:a\d|one|one[_ ]plus|note|max|cc)?[_ ]?(?:\d{0,2}\w?)[_ ]?(?:plus|se|lite|pro)?( 5g|lte)?)(?: bui|\))/i,
16315
- / ([\w ]+) miui\/v?\d/i
16316
- ],
16317
- [
16318
- [
16319
- MODEL,
16320
- /_/g,
16321
- " "
16322
- ],
16323
- [VENDOR, XIAOMI],
16324
- [TYPE, MOBILE]
16325
- ],
16326
- [/droid.+; (cph2[3-6]\d[13579]|((gm|hd)19|(ac|be|in|kb)20|(d[en]|eb|le|mt)21|ne22)[0-2]\d|p[g-l]\w[1m]10)\b/i, /(?:one)?(?:plus)? (a\d0\d\d)(?: b|\))/i],
16327
- [
16328
- MODEL,
16329
- [VENDOR, ONEPLUS],
16330
- [TYPE, MOBILE]
16331
- ],
16332
- [/; (\w+) bui.+ oppo/i, /\b(cph[12]\d{3}|p(?:af|c[al]|d\w|e[ar])[mt]\d0|x9007|a101op)\b/i],
16333
- [
16334
- MODEL,
16335
- [VENDOR, OPPO],
16336
- [TYPE, MOBILE]
16337
- ],
16338
- [/\b(opd2(\d{3}a?))(?: bui|\))/i],
16339
- [
16340
- MODEL,
16341
- [
16342
- VENDOR,
16343
- strMapper,
16344
- {
16345
- "OnePlus": [
16346
- "203",
16347
- "304",
16348
- "403",
16349
- "404",
16350
- "413",
16351
- "415"
16352
- ],
16353
- "*": OPPO
16354
- }
16355
- ],
16356
- [TYPE, TABLET]
16357
- ],
16358
- [/(vivo (5r?|6|8l?|go|one|s|x[il]?[2-4]?)[\w\+ ]*)(?: bui|\))/i],
16359
- [
16360
- MODEL,
16361
- [VENDOR, "BLU"],
16362
- [TYPE, MOBILE]
16363
- ],
16364
- [/; vivo (\w+)(?: bui|\))/i, /\b(v[12]\d{3}\w?[at])(?: bui|;)/i],
16365
- [
16366
- MODEL,
16367
- [VENDOR, "Vivo"],
16368
- [TYPE, MOBILE]
16369
- ],
16370
- [/\b(rmx[1-3]\d{3})(?: bui|;|\))/i],
16371
- [
16372
- MODEL,
16373
- [VENDOR, "Realme"],
16374
- [TYPE, MOBILE]
16375
- ],
16376
- [/(ideatab[-\w ]+|602lv|d-42a|a101lv|a2109a|a3500-hv|s[56]000|pb-6505[my]|tb-?x?\d{3,4}(?:f[cu]|xu|[av])|yt\d?-[jx]?\d+[lfmx])( bui|;|\)|\/)/i, /lenovo ?(b[68]0[08]0-?[hf]?|tab(?:[\w- ]+?)|tb[\w-]{6,7})( bui|;|\)|\/)/i],
16377
- [
16378
- MODEL,
16379
- [VENDOR, LENOVO],
16380
- [TYPE, TABLET]
16381
- ],
16382
- [/lenovo[-_ ]?([-\w ]+?)(?: bui|\)|\/)/i],
16383
- [
16384
- MODEL,
16385
- [VENDOR, LENOVO],
16386
- [TYPE, MOBILE]
16387
- ],
16388
- [
16389
- /\b(milestone|droid(?:[2-4x]| (?:bionic|x2|pro|razr))?:?( 4g)?)\b[\w ]+build\//i,
16390
- /\bmot(?:orola)?[- ]([\w\s]+)(\)| bui)/i,
16391
- /((?:moto(?! 360)[-\w\(\) ]+|xt\d{3,4}[cgkosw\+]?[-\d]*|nexus 6)(?= bui|\)))/i
16392
- ],
16393
- [
16394
- MODEL,
16395
- [VENDOR, MOTOROLA],
16396
- [TYPE, MOBILE]
16397
- ],
16398
- [/\b(mz60\d|xoom[2 ]{0,2}) build\//i],
16399
- [
16400
- MODEL,
16401
- [VENDOR, MOTOROLA],
16402
- [TYPE, TABLET]
16403
- ],
16404
- [/\b(?:lg)?([vl]k\-?\d{3}) bui| 3\.[-\w; ]{10}lg?-([06cv9]{3,4})/i],
16405
- [
16406
- MODEL,
16407
- [VENDOR, LG],
16408
- [TYPE, TABLET]
16409
- ],
16410
- [
16411
- /(lm(?:-?f100[nv]?|-[\w\.]+)(?= bui|\))|nexus [45])/i,
16412
- /\blg[-e;\/ ]+(?!.*(?:browser|netcast|android tv|watch|webos))(\w+)/i,
16413
- /\blg-?([\d\w]+) bui/i
16414
- ],
16415
- [
16416
- MODEL,
16417
- [VENDOR, LG],
16418
- [TYPE, MOBILE]
16419
- ],
16420
- [/(nokia) (t[12][01])/i],
16421
- [
16422
- VENDOR,
16423
- MODEL,
16424
- [TYPE, TABLET]
16425
- ],
16426
- [/(?:maemo|nokia).*(n900|lumia \d+|rm-\d+)/i, /nokia[-_ ]?(([-\w\. ]*?))( bui|\)|;|\/)/i],
16427
- [
16428
- [
16429
- MODEL,
16430
- /_/g,
16431
- " "
16432
- ],
16433
- [TYPE, MOBILE],
16434
- [VENDOR, "Nokia"]
16435
- ],
16436
- [/(pixel (c|tablet))\b/i],
16437
- [
16438
- MODEL,
16439
- [VENDOR, GOOGLE],
16440
- [TYPE, TABLET]
16441
- ],
16442
- [/droid.+;(?: google)? (g(01[13]a|020[aem]|025[jn]|1b60|1f8f|2ybb|4s1m|576d|5nz6|8hhn|8vou|a02099|c15s|d1yq|e2ae|ec77|gh2x|kv4x|p4bc|pj41|r83y|tt9q|ur25|wvk6)|pixel[\d ]*a?( pro)?( xl)?( fold)?( \(5g\))?)( bui|\))/i],
16443
- [
16444
- MODEL,
16445
- [VENDOR, GOOGLE],
16446
- [TYPE, MOBILE]
16447
- ],
16448
- [/(google) (pixelbook( go)?)/i],
16449
- [VENDOR, MODEL],
16450
- [/droid.+; (a?\d[0-2]{2}so|[c-g]\d{4}|so[-gl]\w+|xq-\w\w\d\d)(?= bui|\).+chrome\/(?![1-6]{0,1}\d\.))/i],
16451
- [
16452
- MODEL,
16453
- [VENDOR, SONY],
16454
- [TYPE, MOBILE]
16455
- ],
16456
- [/sony tablet [ps]/i, /\b(?:sony)?sgp\w+(?: bui|\))/i],
16457
- [
16458
- [MODEL, "Xperia Tablet"],
16459
- [VENDOR, SONY],
16460
- [TYPE, TABLET]
16461
- ],
16462
- [
16463
- /(alexa)webm/i,
16464
- /(kf[a-z]{2}wi|aeo(?!bc)\w\w)( bui|\))/i,
16465
- /(kf[a-z]+)( bui|\)).+silk\//i
16466
- ],
16467
- [
16468
- MODEL,
16469
- [VENDOR, AMAZON],
16470
- [TYPE, TABLET]
16471
- ],
16472
- [/((?:sd|kf)[0349hijorstuw]+)( bui|\)).+silk\//i],
16473
- [
16474
- [
16475
- MODEL,
16476
- /(.+)/g,
16477
- "Fire Phone $1"
16478
- ],
16479
- [VENDOR, AMAZON],
16480
- [TYPE, MOBILE]
16481
- ],
16482
- [/(playbook);[-\w\),; ]+(rim)/i],
16483
- [
16484
- MODEL,
16485
- VENDOR,
16486
- [TYPE, TABLET]
16487
- ],
16488
- [/\b((?:bb[a-f]|st[hv])100-\d)/i, /(?:blackberry|\(bb10;) (\w+)/i],
16489
- [
16490
- MODEL,
16491
- [VENDOR, BLACKBERRY],
16492
- [TYPE, MOBILE]
16493
- ],
16494
- [/(?:\b|asus_)(transfo[prime ]{4,10} \w+|eeepc|slider \w+|nexus 7|padfone|p00[cj])/i],
16495
- [
16496
- MODEL,
16497
- [VENDOR, ASUS],
16498
- [TYPE, TABLET]
16499
- ],
16500
- [/ (z[bes]6[027][012][km][ls]|zenfone \d\w?)\b/i],
16501
- [
16502
- MODEL,
16503
- [VENDOR, ASUS],
16504
- [TYPE, MOBILE]
16505
- ],
16506
- [/(nexus 9)/i],
16507
- [
16508
- MODEL,
16509
- [VENDOR, "HTC"],
16510
- [TYPE, TABLET]
16511
- ],
16512
- [
16513
- /(htc)[-;_ ]{1,2}([\w ]+(?=\)| bui)|\w+)/i,
16514
- /(zte)[- ]([\w ]+?)(?: bui|\/|\))/i,
16515
- /(alcatel|geeksphone|nexian|panasonic(?!(?:;|\.))|sony(?!-bra))[-_ ]?([-\w]*)/i
16516
- ],
16517
- [
16518
- VENDOR,
16519
- [
16520
- MODEL,
16521
- /_/g,
16522
- " "
16523
- ],
16524
- [TYPE, MOBILE]
16525
- ],
16526
- [/tcl (xess p17aa)/i, /droid [\w\.]+; ((?:8[14]9[16]|9(?:0(?:48|60|8[01])|1(?:3[27]|66)|2(?:6[69]|9[56])|466))[gqswx])(_\w(\w|\w\w))?(\)| bui)/i],
16527
- [
16528
- MODEL,
16529
- [VENDOR, "TCL"],
16530
- [TYPE, TABLET]
16531
- ],
16532
- [/droid [\w\.]+; (418(?:7d|8v)|5087z|5102l|61(?:02[dh]|25[adfh]|27[ai]|56[dh]|59k|65[ah])|a509dl|t(?:43(?:0w|1[adepqu])|50(?:6d|7[adju])|6(?:09dl|10k|12b|71[efho]|76[hjk])|7(?:66[ahju]|67[hw]|7[045][bh]|71[hk]|73o|76[ho]|79w|81[hks]?|82h|90[bhsy]|99b)|810[hs]))(_\w(\w|\w\w))?(\)| bui)/i],
16533
- [
16534
- MODEL,
16535
- [VENDOR, "TCL"],
16536
- [TYPE, MOBILE]
16537
- ],
16538
- [/(itel) ((\w+))/i],
16539
- [
16540
- [VENDOR, lowerize],
16541
- MODEL,
16542
- [
16543
- TYPE,
16544
- strMapper,
16545
- {
16546
- "tablet": ["p10001l", "w7001"],
16547
- "*": "mobile"
16548
- }
16549
- ]
16550
- ],
16551
- [/droid.+; ([ab][1-7]-?[0178a]\d\d?)/i],
16552
- [
16553
- MODEL,
16554
- [VENDOR, "Acer"],
16555
- [TYPE, TABLET]
16556
- ],
16557
- [/droid.+; (m[1-5] note) bui/i, /\bmz-([-\w]{2,})/i],
16558
- [
16559
- MODEL,
16560
- [VENDOR, "Meizu"],
16561
- [TYPE, MOBILE]
16562
- ],
16563
- [/; ((?:power )?armor(?:[\w ]{0,8}))(?: bui|\))/i],
16564
- [
16565
- MODEL,
16566
- [VENDOR, "Ulefone"],
16567
- [TYPE, MOBILE]
16568
- ],
16569
- [/; (energy ?\w+)(?: bui|\))/i, /; energizer ([\w ]+)(?: bui|\))/i],
16570
- [
16571
- MODEL,
16572
- [VENDOR, "Energizer"],
16573
- [TYPE, MOBILE]
16574
- ],
16575
- [/; cat (b35);/i, /; (b15q?|s22 flip|s48c|s62 pro)(?: bui|\))/i],
16576
- [
16577
- MODEL,
16578
- [VENDOR, "Cat"],
16579
- [TYPE, MOBILE]
16580
- ],
16581
- [/((?:new )?andromax[\w- ]+)(?: bui|\))/i],
16582
- [
16583
- MODEL,
16584
- [VENDOR, "Smartfren"],
16585
- [TYPE, MOBILE]
16586
- ],
16587
- [/droid.+; (a(in)?(0(15|59|6[35])|142)p?)/i],
16588
- [
16589
- MODEL,
16590
- [VENDOR, "Nothing"],
16591
- [TYPE, MOBILE]
16592
- ],
16593
- [/; (x67 5g|tikeasy \w+|ac[1789]\d\w+)( b|\))/i, /archos ?(5|gamepad2?|([\w ]*[t1789]|hello) ?\d+[\w ]*)( b|\))/i],
16594
- [
16595
- MODEL,
16596
- [VENDOR, "Archos"],
16597
- [TYPE, TABLET]
16598
- ],
16599
- [/archos ([\w ]+)( b|\))/i, /; (ac[3-6]\d\w{2,8})( b|\))/i],
16600
- [
16601
- MODEL,
16602
- [VENDOR, "Archos"],
16603
- [TYPE, MOBILE]
16604
- ],
16605
- [/; (n159v)/i],
16606
- [
16607
- MODEL,
16608
- [VENDOR, "HMD"],
16609
- [TYPE, MOBILE]
16610
- ],
16611
- [/(imo) (tab \w+)/i, /(infinix|tecno) (x1101b?|p904|dp(7c|8d|10a)( pro)?|p70[1-3]a?|p904|t1101)/i],
16612
- [
16613
- VENDOR,
16614
- MODEL,
16615
- [TYPE, TABLET]
16616
- ],
16617
- [
16618
- /(blackberry|benq|palm(?=\-)|sonyericsson|acer|asus(?! zenw)|dell|jolla|meizu|motorola|polytron|tecno|micromax|advan)[-_ ]?([-\w]*)/i,
16619
- /; (blu|hmd|imo|infinix|lava|oneplus|tcl|wiko)[_ ]([\w\+ ]+?)(?: bui|\)|; r)/i,
16620
- /(hp) ([\w ]+\w)/i,
16621
- /(microsoft); (lumia[\w ]+)/i,
16622
- /(oppo) ?([\w ]+) bui/i,
16623
- /(hisense) ([ehv][\w ]+)\)/i,
16624
- /droid[^;]+; (philips)[_ ]([sv-x][\d]{3,4}[xz]?)/i
16625
- ],
16626
- [
16627
- VENDOR,
16628
- MODEL,
16629
- [TYPE, MOBILE]
16630
- ],
16631
- [
16632
- /(kobo)\s(ereader|touch)/i,
16633
- /(hp).+(touchpad(?!.+tablet)|tablet)/i,
16634
- /(kindle)\/([\w\.]+)/i
16635
- ],
16636
- [
16637
- VENDOR,
16638
- MODEL,
16639
- [TYPE, TABLET]
16640
- ],
16641
- [/(surface duo)/i],
16642
- [
16643
- MODEL,
16644
- [VENDOR, MICROSOFT],
16645
- [TYPE, TABLET]
16646
- ],
16647
- [/droid [\d\.]+; (fp\du?)(?: b|\))/i],
16648
- [
16649
- MODEL,
16650
- [VENDOR, "Fairphone"],
16651
- [TYPE, MOBILE]
16652
- ],
16653
- [/((?:tegranote|shield t(?!.+d tv))[\w- ]*?)(?: b|\))/i],
16654
- [
16655
- MODEL,
16656
- [VENDOR, NVIDIA],
16657
- [TYPE, TABLET]
16658
- ],
16659
- [/(sprint) (\w+)/i],
16660
- [
16661
- VENDOR,
16662
- MODEL,
16663
- [TYPE, MOBILE]
16664
- ],
16665
- [/(kin\.[onetw]{3})/i],
16666
- [
16667
- [
16668
- MODEL,
16669
- /\./g,
16670
- " "
16671
- ],
16672
- [VENDOR, MICROSOFT],
16673
- [TYPE, MOBILE]
16674
- ],
16675
- [/droid.+; ([c6]+|et5[16]|mc[239][23]x?|vc8[03]x?)\)/i],
16676
- [
16677
- MODEL,
16678
- [VENDOR, ZEBRA],
16679
- [TYPE, TABLET]
16680
- ],
16681
- [/droid.+; (ec30|ps20|tc[2-8]\d[kx])\)/i],
16682
- [
16683
- MODEL,
16684
- [VENDOR, ZEBRA],
16685
- [TYPE, MOBILE]
16686
- ],
16687
- [/(philips)[\w ]+tv/i, /smart-tv.+(samsung)/i],
16688
- [VENDOR, [TYPE, SMARTTV]],
16689
- [/hbbtv.+maple;(\d+)/i],
16690
- [
16691
- [
16692
- MODEL,
16693
- /^/,
16694
- "SmartTV"
16695
- ],
16696
- [VENDOR, SAMSUNG],
16697
- [TYPE, SMARTTV]
16698
- ],
16699
- [/(vizio)(?: |.+model\/)(\w+-\w+)/i, /tcast.+(lg)e?. ([-\w]+)/i],
16700
- [
16701
- VENDOR,
16702
- MODEL,
16703
- [TYPE, SMARTTV]
16704
- ],
16705
- [/(nux; netcast.+smarttv|lg (netcast\.tv-201\d|android tv))/i],
16706
- [[VENDOR, LG], [TYPE, SMARTTV]],
16707
- [/(apple) ?tv/i],
16708
- [
16709
- VENDOR,
16710
- [MODEL, APPLE + " TV"],
16711
- [TYPE, SMARTTV]
16712
- ],
16713
- [/crkey.*devicetype\/chromecast/i],
16714
- [
16715
- [MODEL, CHROMECAST + " Third Generation"],
16716
- [VENDOR, GOOGLE],
16717
- [TYPE, SMARTTV]
16718
- ],
16719
- [/crkey.*devicetype\/([^/]*)/i],
16720
- [
16721
- [
16722
- MODEL,
16723
- /^/,
16724
- "Chromecast "
16725
- ],
16726
- [VENDOR, GOOGLE],
16727
- [TYPE, SMARTTV]
16728
- ],
16729
- [/fuchsia.*crkey/i],
16730
- [
16731
- [MODEL, CHROMECAST + " Nest Hub"],
16732
- [VENDOR, GOOGLE],
16733
- [TYPE, SMARTTV]
16734
- ],
16735
- [/crkey/i],
16736
- [
16737
- [MODEL, CHROMECAST],
16738
- [VENDOR, GOOGLE],
16739
- [TYPE, SMARTTV]
16740
- ],
16741
- [/(portaltv)/i],
16742
- [
16743
- MODEL,
16744
- [VENDOR, FACEBOOK],
16745
- [TYPE, SMARTTV]
16746
- ],
16747
- [/droid.+aft(\w+)( bui|\))/i],
16748
- [
16749
- MODEL,
16750
- [VENDOR, AMAZON],
16751
- [TYPE, SMARTTV]
16752
- ],
16753
- [/(shield \w+ tv)/i],
16754
- [
16755
- MODEL,
16756
- [VENDOR, NVIDIA],
16757
- [TYPE, SMARTTV]
16758
- ],
16759
- [/\(dtv[\);].+(aquos)/i, /(aquos-tv[\w ]+)\)/i],
16760
- [
16761
- MODEL,
16762
- [VENDOR, SHARP],
16763
- [TYPE, SMARTTV]
16764
- ],
16765
- [/(bravia[\w ]+)( bui|\))/i],
16766
- [
16767
- MODEL,
16768
- [VENDOR, SONY],
16769
- [TYPE, SMARTTV]
16770
- ],
16771
- [/(mi(tv|box)-?\w+) bui/i],
16772
- [
16773
- MODEL,
16774
- [VENDOR, XIAOMI],
16775
- [TYPE, SMARTTV]
16776
- ],
16777
- [/Hbbtv.*(technisat) (.*);/i],
16778
- [
16779
- VENDOR,
16780
- MODEL,
16781
- [TYPE, SMARTTV]
16782
- ],
16783
- [/\b(roku)[\dx]*[\)\/]((?:dvp-)?[\d\.]*)/i, /hbbtv\/\d+\.\d+\.\d+ +\([\w\+ ]*; *([\w\d][^;]*);([^;]*)/i],
16784
- [
16785
- [
16786
- VENDOR,
16787
- /.+\/(\w+)/,
16788
- "$1",
16789
- strMapper,
16790
- { "LG": "lge" }
16791
- ],
16792
- [MODEL, trim],
16793
- [TYPE, SMARTTV]
16794
- ],
16795
- [/(playstation \w+)/i],
16796
- [
16797
- MODEL,
16798
- [VENDOR, SONY],
16799
- [TYPE, CONSOLE]
16800
- ],
16801
- [/\b(xbox(?: one)?(?!; xbox))[\); ]/i],
16802
- [
16803
- MODEL,
16804
- [VENDOR, MICROSOFT],
16805
- [TYPE, CONSOLE]
16806
- ],
16807
- [
16808
- /(ouya)/i,
16809
- /(nintendo) (\w+)/i,
16810
- /(retroid) (pocket ([^\)]+))/i,
16811
- /(valve).+(steam deck)/i,
16812
- /droid.+; ((shield|rgcube|gr0006))( bui|\))/i
16813
- ],
16814
- [
16815
- [
16816
- VENDOR,
16817
- strMapper,
16818
- {
16819
- "Nvidia": "Shield",
16820
- "Anbernic": "RGCUBE",
16821
- "Logitech": "GR0006"
16822
- }
16823
- ],
16824
- MODEL,
16825
- [TYPE, CONSOLE]
16826
- ],
16827
- [/\b(sm-[lr]\d\d[0156][fnuw]?s?|gear live)\b/i],
16828
- [
16829
- MODEL,
16830
- [VENDOR, SAMSUNG],
16831
- [TYPE, WEARABLE]
16832
- ],
16833
- [/((pebble))app/i, /(asus|google|lg|oppo|xiaomi) ((pixel |zen)?watch[\w ]*)( bui|\))/i],
16834
- [
16835
- VENDOR,
16836
- MODEL,
16837
- [TYPE, WEARABLE]
16838
- ],
16839
- [/(ow(?:19|20)?we?[1-3]{1,3})/i],
16840
- [
16841
- MODEL,
16842
- [VENDOR, OPPO],
16843
- [TYPE, WEARABLE]
16844
- ],
16845
- [/(watch)(?: ?os[,\/]|\d,\d\/)[\d\.]+/i],
16846
- [
16847
- MODEL,
16848
- [VENDOR, APPLE],
16849
- [TYPE, WEARABLE]
16850
- ],
16851
- [/(opwwe\d{3})/i],
16852
- [
16853
- MODEL,
16854
- [VENDOR, ONEPLUS],
16855
- [TYPE, WEARABLE]
16856
- ],
16857
- [/(moto 360)/i],
16858
- [
16859
- MODEL,
16860
- [VENDOR, MOTOROLA],
16861
- [TYPE, WEARABLE]
16862
- ],
16863
- [/(smartwatch 3)/i],
16864
- [
16865
- MODEL,
16866
- [VENDOR, SONY],
16867
- [TYPE, WEARABLE]
16868
- ],
16869
- [/(g watch r)/i],
16870
- [
16871
- MODEL,
16872
- [VENDOR, LG],
16873
- [TYPE, WEARABLE]
16874
- ],
16875
- [/droid.+; (wt63?0{2,3})\)/i],
16876
- [
16877
- MODEL,
16878
- [VENDOR, ZEBRA],
16879
- [TYPE, WEARABLE]
16880
- ],
16881
- [/droid.+; (glass) \d/i],
16882
- [
16883
- MODEL,
16884
- [VENDOR, GOOGLE],
16885
- [TYPE, XR]
16886
- ],
16887
- [/(pico) ([\w ]+) os\d/i],
16888
- [
16889
- VENDOR,
16890
- MODEL,
16891
- [TYPE, XR]
16892
- ],
16893
- [/(quest( \d| pro)?s?).+vr/i],
16894
- [
16895
- MODEL,
16896
- [VENDOR, FACEBOOK],
16897
- [TYPE, XR]
16898
- ],
16899
- [/mobile vr; rv.+firefox/i],
16900
- [[TYPE, XR]],
16901
- [/(tesla)(?: qtcarbrowser|\/[-\w\.]+)/i],
16902
- [VENDOR, [TYPE, EMBEDDED]],
16903
- [/(aeobc)\b/i],
16904
- [
16905
- MODEL,
16906
- [VENDOR, AMAZON],
16907
- [TYPE, EMBEDDED]
16908
- ],
16909
- [/(homepod).+mac os/i],
16910
- [
16911
- MODEL,
16912
- [VENDOR, APPLE],
16913
- [TYPE, EMBEDDED]
16914
- ],
16915
- [/windows iot/i],
16916
- [[TYPE, EMBEDDED]],
16917
- [/droid.+; ([\w- ]+) (4k|android|smart|google)[- ]?tv/i],
16918
- [MODEL, [TYPE, SMARTTV]],
16919
- [/\b((4k|android|smart|opera)[- ]?tv|tv; rv:|large screen[\w ]+safari)\b/i],
16920
- [[TYPE, SMARTTV]],
16921
- [/droid .+?; ([^;]+?)(?: bui|; wv\)|\) applew|; hmsc).+?(mobile|vr|\d) safari/i],
16922
- [MODEL, [
16923
- TYPE,
16924
- strMapper,
16925
- {
16926
- "mobile": "Mobile",
16927
- "xr": "VR",
16928
- "*": TABLET
16929
- }
16930
- ]],
16931
- [/\b((tablet|tab)[;\/]|focus\/\d(?!.+mobile))/i],
16932
- [[TYPE, TABLET]],
16933
- [/(phone|mobile(?:[;\/]| [ \w\/\.]*safari)|pda(?=.+windows ce))/i],
16934
- [[TYPE, MOBILE]],
16935
- [/droid .+?; ([\w\. -]+)( bui|\))/i],
16936
- [MODEL, [VENDOR, "Generic"]]
16937
- ],
16938
- engine: [
16939
- [/windows.+ edge\/([\w\.]+)/i],
16940
- [VERSION$1, [NAME$1, EDGE + "HTML"]],
16941
- [/(arkweb)\/([\w\.]+)/i],
16942
- [NAME$1, VERSION$1],
16943
- [/webkit\/537\.36.+chrome\/(?!27)([\w\.]+)/i],
16944
- [VERSION$1, [NAME$1, "Blink"]],
16945
- [
16946
- /(presto)\/([\w\.]+)/i,
16947
- /(webkit|trident|netfront|netsurf|amaya|lynx|w3m|goanna|servo)\/([\w\.]+)/i,
16948
- /ekioh(flow)\/([\w\.]+)/i,
16949
- /(khtml|tasman|links|dillo)[\/ ]\(?([\w\.]+)/i,
16950
- /(icab)[\/ ]([23]\.[\d\.]+)/i,
16951
- /\b(libweb)/i
16952
- ],
16953
- [NAME$1, VERSION$1],
16954
- [/ladybird\//i],
16955
- [[NAME$1, "LibWeb"]],
16956
- [/rv\:([\w\.]{1,9})\b.+(gecko)/i],
16957
- [VERSION$1, NAME$1]
16958
- ],
16959
- os: [
16960
- [/(windows nt) (6\.[23]); arm/i],
16961
- [[
16962
- NAME$1,
16963
- /N/,
16964
- "R"
16965
- ], [
16966
- VERSION$1,
16967
- strMapper,
16968
- windowsVersionMap
16969
- ]],
16970
- [/(windows (?:phone|mobile|iot))(?: os)?[\/ ]?([\d\.]*( se)?)/i, /(windows)[\/ ](1[01]|2000|3\.1|7|8(\.1)?|9[58]|me|server 20\d\d( r2)?|vista|xp)/i],
16971
- [NAME$1, VERSION$1],
16972
- [/windows nt ?([\d\.\)]*)(?!.+xbox)/i, /\bwin(?=3| ?9|n)(?:nt| 9x )?([\d\.;]*)/i],
16973
- [[
16974
- VERSION$1,
16975
- /(;|\))/g,
16976
- "",
16977
- strMapper,
16978
- windowsVersionMap
16979
- ], [NAME$1, WINDOWS]],
16980
- [/(windows ce)\/?([\d\.]*)/i],
16981
- [NAME$1, VERSION$1],
16982
- [
16983
- /[adehimnop]{4,7}\b(?:.*os ([\w]+) like mac|; opera)/i,
16984
- /(?:ios;fbsv|ios(?=.+ip(?:ad|hone)|.+apple ?tv)|ip(?:ad|hone)(?: |.+i(?:pad)?)os|apple ?tv.+ios)[\/ ]([\w\.]+)/i,
16985
- /\btvos ?([\w\.]+)/i,
16986
- /cfnetwork\/.+darwin/i
16987
- ],
16988
- [[
16989
- VERSION$1,
16990
- /_/g,
16991
- "."
16992
- ], [NAME$1, "iOS"]],
16993
- [/(mac os x) ?([\w\. ]*)/i, /(macintosh|mac_powerpc\b)(?!.+(haiku|morphos))/i],
16994
- [[NAME$1, "macOS"], [
16995
- VERSION$1,
16996
- /_/g,
16997
- "."
16998
- ]],
16999
- [/android ([\d\.]+).*crkey/i],
17000
- [VERSION$1, [NAME$1, CHROMECAST + " Android"]],
17001
- [/fuchsia.*crkey\/([\d\.]+)/i],
17002
- [VERSION$1, [NAME$1, CHROMECAST + " Fuchsia"]],
17003
- [/crkey\/([\d\.]+).*devicetype\/smartspeaker/i],
17004
- [VERSION$1, [NAME$1, CHROMECAST + " SmartSpeaker"]],
17005
- [/linux.*crkey\/([\d\.]+)/i],
17006
- [VERSION$1, [NAME$1, CHROMECAST + " Linux"]],
17007
- [/crkey\/([\d\.]+)/i],
17008
- [VERSION$1, [NAME$1, CHROMECAST]],
17009
- [/droid ([\w\.]+)\b.+(android[- ]x86)/i],
17010
- [VERSION$1, NAME$1],
17011
- [/(ubuntu) ([\w\.]+) like android/i],
17012
- [[
17013
- NAME$1,
17014
- /(.+)/,
17015
- "$1 Touch"
17016
- ], VERSION$1],
17017
- [/(harmonyos)[\/ ]?([\d\.]*)/i, /(android|bada|blackberry|kaios|maemo|meego|openharmony|qnx|rim tablet os|sailfish|series40|symbian|tizen)\w*[-\/\.; ]?([\d\.]*)/i],
17018
- [NAME$1, VERSION$1],
17019
- [/\(bb(10);/i],
17020
- [VERSION$1, [NAME$1, BLACKBERRY]],
17021
- [/(?:symbian ?os|symbos|s60(?=;)|series ?60)[-\/ ]?([\w\.]*)/i],
17022
- [VERSION$1, [NAME$1, "Symbian"]],
17023
- [/mozilla\/[\d\.]+ \((?:mobile[;\w ]*|tablet|tv|[^\)]*(?:viera|lg(?:l25|-d300)|alcatel ?o.+|y300-f1)); rv:([\w\.]+)\).+gecko\//i],
17024
- [VERSION$1, [NAME$1, FIREFOX + " OS"]],
17025
- [/\b(?:hp)?wos(?:browser)?\/([\w\.]+)/i, /webos(?:[ \/]?|\.tv-20(?=2[2-9]))(\d[\d\.]*)/i],
17026
- [VERSION$1, [NAME$1, "webOS"]],
17027
- [/web0s;.+?(?:chr[o0]me|safari)\/(\d+)/i],
17028
- [[
17029
- VERSION$1,
17030
- strMapper,
17031
- {
17032
- "25": "120",
17033
- "24": "108",
17034
- "23": "94",
17035
- "22": "87",
17036
- "6": "79",
17037
- "5": "68",
17038
- "4": "53",
17039
- "3": "38",
17040
- "2": "538",
17041
- "1": "537",
17042
- "*": "TV"
17043
- }
17044
- ], [NAME$1, "webOS"]],
17045
- [/watch(?: ?os[,\/ ]|\d,\d\/)([\d\.]+)/i],
17046
- [VERSION$1, [NAME$1, "watchOS"]],
17047
- [/cros [\w]+(?:\)| ([\w\.]+)\b)/i],
17048
- [VERSION$1, [NAME$1, "Chrome OS"]],
17049
- [/kepler ([\w\.]+); (aft|aeo)/i],
17050
- [VERSION$1, [NAME$1, "Vega OS"]],
17051
- [
17052
- /(netrange)mmh/i,
17053
- /(nettv)\/(\d+\.[\w\.]+)/i,
17054
- /(nintendo|playstation) (\w+)/i,
17055
- /(xbox); +xbox ([^\);]+)/i,
17056
- /(pico) .+os([\w\.]+)/i,
17057
- /\b(joli|palm)\b ?(?:os)?\/?([\w\.]*)/i,
17058
- /linux.+(mint)[\/\(\) ]?([\w\.]*)/i,
17059
- /(mageia|vectorlinux|fuchsia|arcaos|arch(?= ?linux))[;l ]([\d\.]*)/i,
17060
- /([kxln]?ubuntu|debian|suse|opensuse|gentoo|slackware|fedora|mandriva|centos|pclinuxos|red ?hat|zenwalk|linpus|raspbian|plan 9|minix|risc os|contiki|deepin|manjaro|elementary os|sabayon|linspire|knoppix)(?: gnu[\/ ]linux)?(?: enterprise)?(?:[- ]linux)?(?:-gnu)?[-\/ ]?(?!chrom|package)([-\w\.]*)/i,
17061
- /((?:open)?solaris)[-\/ ]?([\w\.]*)/i,
17062
- /\b(aix)[; ]([1-9\.]{0,4})/i,
17063
- /(hurd|linux|morphos)(?: (?:arm|x86|ppc)\w*| ?)([\w\.]*)/i,
17064
- /(gnu) ?([\w\.]*)/i,
17065
- /\b([-frentopcghs]{0,5}bsd|dragonfly)[\/ ]?(?!amd|[ix346]{1,2}86)([\w\.]*)/i,
17066
- /(haiku) ?(r\d)?/i
17067
- ],
17068
- [NAME$1, VERSION$1],
17069
- [/(sunos) ?([\d\.]*)/i],
17070
- [[NAME$1, "Solaris"], VERSION$1],
17071
- [/\b(beos|os\/2|amigaos|openvms|hp-ux|serenityos)/i, /(unix) ?([\w\.]*)/i],
17072
- [NAME$1, VERSION$1]
17073
- ]
17074
- };
17075
- var defaultProps = (function() {
17076
- var props = {
17077
- init: {},
17078
- isIgnore: {},
17079
- isIgnoreRgx: {},
17080
- toString: {}
17081
- };
17082
- setProps.call(props.init, [
17083
- [BROWSER, [
17084
- NAME$1,
17085
- VERSION$1,
17086
- MAJOR,
17087
- TYPE
17088
- ]],
17089
- [CPU, [ARCHITECTURE]],
17090
- [DEVICE, [
17091
- TYPE,
17092
- MODEL,
17093
- VENDOR
17094
- ]],
17095
- [ENGINE, [NAME$1, VERSION$1]],
17096
- [OS, [NAME$1, VERSION$1]]
17097
- ]);
17098
- setProps.call(props.isIgnore, [
17099
- [BROWSER, [VERSION$1, MAJOR]],
17100
- [ENGINE, [VERSION$1]],
17101
- [OS, [VERSION$1]]
17102
- ]);
17103
- setProps.call(props.isIgnoreRgx, [[BROWSER, / ?browser$/i], [OS, / ?os$/i]]);
17104
- setProps.call(props.toString, [
17105
- [BROWSER, [NAME$1, VERSION$1]],
17106
- [CPU, [ARCHITECTURE]],
17107
- [DEVICE, [VENDOR, MODEL]],
17108
- [ENGINE, [NAME$1, VERSION$1]],
17109
- [OS, [NAME$1, VERSION$1]]
17110
- ]);
17111
- return props;
17112
- })();
17113
- var createIData = function(item, itemType) {
17114
- var init_props = defaultProps.init[itemType], is_ignoreProps = defaultProps.isIgnore[itemType] || 0, is_ignoreRgx = defaultProps.isIgnoreRgx[itemType] || 0, toString_props = defaultProps.toString[itemType] || 0;
17115
- function IData() {
17116
- setProps.call(this, init_props);
17117
- }
17118
- IData.prototype.getItem = function() {
17119
- return item;
17120
- };
17121
- IData.prototype.withClientHints = function() {
17122
- if (!NAVIGATOR_UADATA) return item.parseCH().get();
17123
- return NAVIGATOR_UADATA.getHighEntropyValues(CH_ALL_VALUES).then(function(res) {
17124
- return item.setCH(new UACHData(res, false)).parseCH().get();
17125
- });
17126
- };
17127
- IData.prototype.withFeatureCheck = function() {
17128
- return item.detectFeature().get();
17129
- };
17130
- if (itemType != RESULT) {
17131
- IData.prototype.is = function(strToCheck) {
17132
- var is = false;
17133
- for (var i in this) if (this.hasOwnProperty(i) && !has$1(is_ignoreProps, i) && lowerize(is_ignoreRgx ? strip(is_ignoreRgx, this[i]) : this[i]) == lowerize(is_ignoreRgx ? strip(is_ignoreRgx, strToCheck) : strToCheck)) {
17134
- is = true;
17135
- if (strToCheck != TYPEOF.UNDEFINED) break;
17136
- } else if (strToCheck == TYPEOF.UNDEFINED && is) {
17137
- is = !is;
17138
- break;
17139
- }
17140
- return is;
17141
- };
17142
- IData.prototype.toString = function() {
17143
- var str = EMPTY;
17144
- for (var i in toString_props) if (typeof this[toString_props[i]] !== TYPEOF.UNDEFINED) str += (str ? " " : EMPTY) + this[toString_props[i]];
17145
- return str || TYPEOF.UNDEFINED;
17146
- };
17147
- }
17148
- IData.prototype.then = function(cb) {
17149
- var that = this;
17150
- var IDataResolve = function() {
17151
- for (var prop in that) if (that.hasOwnProperty(prop)) this[prop] = that[prop];
17152
- };
17153
- IDataResolve.prototype = {
17154
- is: IData.prototype.is,
17155
- toString: IData.prototype.toString,
17156
- withClientHints: IData.prototype.withClientHints,
17157
- withFeatureCheck: IData.prototype.withFeatureCheck
17158
- };
17159
- var resolveData = new IDataResolve();
17160
- cb(resolveData);
17161
- return resolveData;
17162
- };
17163
- return new IData();
17164
- };
17165
- function UACHData(uach, isHttpUACH) {
17166
- uach = uach || {};
17167
- setProps.call(this, CH_ALL_VALUES);
17168
- if (isHttpUACH) setProps.call(this, [
17169
- [BRANDS, itemListToArray(uach[CH])],
17170
- [FULLVERLIST, itemListToArray(uach[CH_FULL_VER_LIST])],
17171
- [MOBILE, /\?1/.test(uach[CH_MOBILE])],
17172
- [MODEL, stripQuotes(uach[CH_MODEL])],
17173
- [PLATFORM, stripQuotes(uach[CH_PLATFORM])],
17174
- [PLATFORMVER, stripQuotes(uach[CH_PLATFORM_VER])],
17175
- [ARCHITECTURE, stripQuotes(uach[CH_ARCH])],
17176
- [FORMFACTORS, itemListToArray(uach[CH_FORM_FACTORS])],
17177
- [BITNESS, stripQuotes(uach[CH_BITNESS])]
17178
- ]);
17179
- else for (var prop in uach) if (this.hasOwnProperty(prop) && typeof uach[prop] !== TYPEOF.UNDEFINED) this[prop] = uach[prop];
17180
- }
17181
- function UAItem(itemType, ua, rgxMap, uaCH) {
17182
- setProps.call(this, [
17183
- ["itemType", itemType],
17184
- ["ua", ua],
17185
- ["uaCH", uaCH],
17186
- ["rgxMap", rgxMap],
17187
- ["data", createIData(this, itemType)]
17188
- ]);
17189
- return this;
17190
- }
17191
- UAItem.prototype.get = function(prop) {
17192
- if (!prop) return this.data;
17193
- return this.data.hasOwnProperty(prop) ? this.data[prop] : void 0;
17194
- };
17195
- UAItem.prototype.set = function(prop, val) {
17196
- this.data[prop] = val;
17197
- return this;
17198
- };
17199
- UAItem.prototype.setCH = function(ch) {
17200
- this.uaCH = ch;
17201
- return this;
17202
- };
17203
- UAItem.prototype.detectFeature = function() {
17204
- if (NAVIGATOR && NAVIGATOR.userAgent == this.ua) switch (this.itemType) {
17205
- case BROWSER:
17206
- if (NAVIGATOR.brave && typeof NAVIGATOR.brave.isBrave == TYPEOF.FUNCTION) this.set(NAME$1, "Brave");
17207
- break;
17208
- case DEVICE:
17209
- if (!this.get(TYPE) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[MOBILE]) this.set(TYPE, MOBILE);
17210
- if (this.get(MODEL) == "Macintosh" && NAVIGATOR && typeof NAVIGATOR.standalone !== TYPEOF.UNDEFINED && NAVIGATOR.maxTouchPoints && NAVIGATOR.maxTouchPoints > 2) this.set(MODEL, "iPad").set(TYPE, TABLET);
17211
- break;
17212
- case OS:
17213
- if (!this.get(NAME$1) && NAVIGATOR_UADATA && NAVIGATOR_UADATA[PLATFORM]) this.set(NAME$1, NAVIGATOR_UADATA[PLATFORM]);
17214
- break;
17215
- case RESULT:
17216
- var data = this.data;
17217
- var detect = function(itemType) {
17218
- return data[itemType].getItem().detectFeature().get();
17219
- };
17220
- this.set(BROWSER, detect(BROWSER)).set(CPU, detect(CPU)).set(DEVICE, detect(DEVICE)).set(ENGINE, detect(ENGINE)).set(OS, detect(OS));
17221
- }
17222
- return this;
17223
- };
17224
- UAItem.prototype.parseUA = function() {
17225
- if (this.itemType != RESULT) rgxMapper.call(this.data, this.ua, this.rgxMap);
17226
- switch (this.itemType) {
17227
- case BROWSER:
17228
- this.set(MAJOR, majorize(this.get(VERSION$1)));
17229
- break;
17230
- case OS:
17231
- if (this.get(NAME$1) == "iOS" && this.get(VERSION$1) == "18.6") {
17232
- var realVersion = /\) Version\/([\d\.]+)/.exec(this.ua);
17233
- if (realVersion && parseInt(realVersion[1].substring(0, 2), 10) >= 26) this.set(VERSION$1, realVersion[1]);
17234
- }
17235
- break;
17236
- }
17237
- return this;
17238
- };
17239
- UAItem.prototype.parseCH = function() {
17240
- var uaCH = this.uaCH, rgxMap = this.rgxMap;
17241
- switch (this.itemType) {
17242
- case BROWSER:
17243
- case ENGINE:
17244
- var brands = uaCH[FULLVERLIST] || uaCH[BRANDS], prevName;
17245
- if (brands) for (var i = 0; i < brands.length; i++) {
17246
- var brandName = brands[i].brand || brands[i], brandVersion = brands[i].version;
17247
- if (this.itemType == BROWSER && !/not.a.brand/i.test(brandName) && (!prevName || /Chrom/.test(prevName) && brandName != CHROMIUM || prevName == EDGE && /WebView2/.test(brandName))) {
17248
- brandName = strMapper(brandName, browserHintsMap);
17249
- prevName = this.get(NAME$1);
17250
- if (!(prevName && !/Chrom/.test(prevName) && /Chrom/.test(brandName))) this.set(NAME$1, brandName).set(VERSION$1, brandVersion).set(MAJOR, majorize(brandVersion));
17251
- prevName = brandName;
17252
- }
17253
- if (this.itemType == ENGINE && brandName == CHROMIUM) this.set(VERSION$1, brandVersion);
17254
- }
17255
- break;
17256
- case CPU:
17257
- var archName = uaCH[ARCHITECTURE];
17258
- if (archName) {
17259
- if (archName && uaCH[BITNESS] == "64") archName += "64";
17260
- rgxMapper.call(this.data, archName + ";", rgxMap);
17261
- }
17262
- break;
17263
- case DEVICE:
17264
- if (uaCH[MOBILE]) this.set(TYPE, MOBILE);
17265
- if (uaCH[MODEL]) {
17266
- this.set(MODEL, uaCH[MODEL]);
17267
- if (!this.get(TYPE) || !this.get(VENDOR)) {
17268
- var reParse = {};
17269
- rgxMapper.call(reParse, "droid 9; " + uaCH[MODEL] + ")", rgxMap);
17270
- if (!this.get(TYPE) && !!reParse.type) this.set(TYPE, reParse.type);
17271
- if (!this.get(VENDOR) && !!reParse.vendor) this.set(VENDOR, reParse.vendor);
17272
- }
17273
- }
17274
- if (uaCH[FORMFACTORS]) {
17275
- var ff;
17276
- if (typeof uaCH[FORMFACTORS] !== "string") {
17277
- var idx = 0;
17278
- while (!ff && idx < uaCH[FORMFACTORS].length) ff = strMapper(uaCH[FORMFACTORS][idx++], formFactorsMap);
17279
- } else ff = strMapper(uaCH[FORMFACTORS], formFactorsMap);
17280
- this.set(TYPE, ff);
17281
- }
17282
- break;
17283
- case OS:
17284
- var osName = uaCH[PLATFORM];
17285
- if (osName) {
17286
- var osVersion = uaCH[PLATFORMVER];
17287
- if (osName == WINDOWS) osVersion = parseInt(majorize(osVersion), 10) >= 13 ? "11" : "10";
17288
- this.set(NAME$1, osName).set(VERSION$1, osVersion);
17289
- }
17290
- if (this.get(NAME$1) == WINDOWS && uaCH[MODEL] == "Xbox") this.set(NAME$1, "Xbox").set(VERSION$1, void 0);
17291
- break;
17292
- case RESULT:
17293
- var data = this.data;
17294
- var parse = function(itemType) {
17295
- return data[itemType].getItem().setCH(uaCH).parseCH().get();
17296
- };
17297
- this.set(BROWSER, parse(BROWSER)).set(CPU, parse(CPU)).set(DEVICE, parse(DEVICE)).set(ENGINE, parse(ENGINE)).set(OS, parse(OS));
17298
- }
17299
- return this;
17300
- };
17301
- function UAParser(ua, extensions, headers) {
17302
- if (typeof ua === TYPEOF.OBJECT) {
17303
- if (isExtensions(ua, true)) {
17304
- if (typeof extensions === TYPEOF.OBJECT) headers = extensions;
17305
- extensions = ua;
17306
- } else {
17307
- headers = ua;
17308
- extensions = void 0;
17309
- }
17310
- ua = void 0;
17311
- } else if (typeof ua === TYPEOF.STRING && !isExtensions(extensions, true)) {
17312
- headers = extensions;
17313
- extensions = void 0;
17314
- }
17315
- if (headers) if (typeof headers.append === TYPEOF.FUNCTION) {
17316
- var kv = {};
17317
- headers.forEach(function(v, k) {
17318
- kv[String(k).toLowerCase()] = v;
17319
- });
17320
- headers = kv;
17321
- } else {
17322
- var normalized = {};
17323
- for (var header in headers) if (headers.hasOwnProperty(header)) normalized[String(header).toLowerCase()] = headers[header];
17324
- headers = normalized;
17325
- }
17326
- if (!(this instanceof UAParser)) return new UAParser(ua, extensions, headers).getResult();
17327
- var userAgent = typeof ua === TYPEOF.STRING ? ua : headers && headers[USER_AGENT] ? headers[USER_AGENT] : NAVIGATOR && NAVIGATOR.userAgent ? NAVIGATOR.userAgent : EMPTY, httpUACH = new UACHData(headers, true), regexMap = extensions ? extend(defaultRegexes, extensions) : defaultRegexes, createItemFunc = function(itemType) {
17328
- if (itemType == RESULT) return function() {
17329
- return new UAItem(itemType, userAgent, regexMap, httpUACH).set("ua", userAgent).set(BROWSER, this.getBrowser()).set(CPU, this.getCPU()).set(DEVICE, this.getDevice()).set(ENGINE, this.getEngine()).set(OS, this.getOS()).get();
17330
- };
17331
- else return function() {
17332
- return new UAItem(itemType, userAgent, regexMap[itemType], httpUACH).parseUA().get();
17333
- };
17334
- };
17335
- setProps.call(this, [
17336
- ["getBrowser", createItemFunc(BROWSER)],
17337
- ["getCPU", createItemFunc(CPU)],
17338
- ["getDevice", createItemFunc(DEVICE)],
17339
- ["getEngine", createItemFunc(ENGINE)],
17340
- ["getOS", createItemFunc(OS)],
17341
- ["getResult", createItemFunc(RESULT)],
17342
- ["getUA", function() {
17343
- return userAgent;
17344
- }],
17345
- ["setUA", function(ua) {
17346
- if (isString$1(ua)) userAgent = trim(ua, UA_MAX_LENGTH);
17347
- return this;
17348
- }]
17349
- ]).setUA(userAgent);
17350
- return this;
17351
- }
17352
- UAParser.VERSION = LIBVERSION;
17353
- UAParser.BROWSER = enumerize([
17354
- NAME$1,
17355
- VERSION$1,
17356
- MAJOR,
17357
- TYPE
17358
- ]);
17359
- UAParser.CPU = enumerize([ARCHITECTURE]);
17360
- UAParser.DEVICE = enumerize([
17361
- MODEL,
17362
- VENDOR,
17363
- TYPE,
17364
- CONSOLE,
17365
- MOBILE,
17366
- SMARTTV,
17367
- TABLET,
17368
- WEARABLE,
17369
- EMBEDDED
17370
- ]);
17371
- UAParser.ENGINE = UAParser.OS = enumerize([NAME$1, VERSION$1]);
17372
- navigator.platform && navigator.platform.toLowerCase();
17373
- navigator.platform && navigator.platform.toUpperCase().indexOf("MAC");
17374
- var isPlaywright = navigator.userAgent.includes("playwright");
17375
- var agent = UAParser(navigator.userAgent);
17376
- agent.browser.name;
17377
- agent.os.name;
17378
- //#endregion
17379
13868
  //#region ../loot-core/src/shared/months.ts
17380
13869
  function _parse(value) {
17381
13870
  if (typeof value === "string") {
@@ -17401,15 +13890,15 @@ function dayFromDate(date) {
17401
13890
  return format$2(_parse(date), "yyyy-MM-dd");
17402
13891
  }
17403
13892
  function currentMonth() {
17404
- if (global.IS_TESTING || isPlaywright) return global.currentMonth || "2017-01";
13893
+ if (global.IS_TESTING || false) return global.currentMonth || "2017-01";
17405
13894
  else return format$2(/* @__PURE__ */ new Date(), "yyyy-MM");
17406
13895
  }
17407
13896
  function currentDate() {
17408
- if (global.IS_TESTING || isPlaywright) return parse$1(currentDay(), "yyyy-MM-dd", /* @__PURE__ */ new Date());
13897
+ if (global.IS_TESTING || false) return parse$1(currentDay(), "yyyy-MM-dd", /* @__PURE__ */ new Date());
17409
13898
  return /* @__PURE__ */ new Date();
17410
13899
  }
17411
13900
  function currentDay() {
17412
- if (global.IS_TESTING || isPlaywright) return "2017-01-01";
13901
+ if (global.IS_TESTING || false) return "2017-01-01";
17413
13902
  else return format$2(/* @__PURE__ */ new Date(), "yyyy-MM-dd");
17414
13903
  }
17415
13904
  function nextMonth(month) {
@@ -17806,6 +14295,7 @@ var schema = {
17806
14295
  show_hidden: f("integer", { default: 0 }),
17807
14296
  show_uncategorized: f("integer", { default: 0 }),
17808
14297
  trim_intervals: f("integer", { default: 0 }),
14298
+ show_trend_lines: f("integer", { default: 0 }),
17809
14299
  include_current: f("integer", { default: 0 }),
17810
14300
  graph_type: f("string", { default: "BarGraph" }),
17811
14301
  conditions: f("json"),
@@ -18983,6 +15473,14 @@ var currencies = [
18983
15473
  numberFormat: "comma-dot-in",
18984
15474
  symbolFirst: true
18985
15475
  },
15476
+ {
15477
+ code: "IRR",
15478
+ name: "Iranian Rial",
15479
+ symbol: "﷼",
15480
+ decimalPlaces: 0,
15481
+ numberFormat: "comma-dot",
15482
+ symbolFirst: false
15483
+ },
18986
15484
  {
18987
15485
  code: "JMD",
18988
15486
  name: "Jamaican Dollar",
@@ -19039,6 +15537,14 @@ var currencies = [
19039
15537
  numberFormat: "comma-dot",
19040
15538
  symbolFirst: true
19041
15539
  },
15540
+ {
15541
+ code: "PKR",
15542
+ name: "Pakistani Rupee",
15543
+ symbol: "Rs.",
15544
+ decimalPlaces: 2,
15545
+ numberFormat: "comma-dot",
15546
+ symbolFirst: true
15547
+ },
19042
15548
  {
19043
15549
  code: "PLN",
19044
15550
  name: "Polish Złoty",
@@ -66202,11 +62708,11 @@ async function importBuffer(fileData, buffer) {
66202
62708
  encryptKeyId: fileData.encryptMeta ? fileData.encryptMeta.keyId : null
66203
62709
  };
66204
62710
  const budgetDir = getBudgetDir(meta.id);
66205
- if (await exists$1(budgetDir)) {
62711
+ if (await exists(budgetDir)) {
66206
62712
  const dbFile = join$2(budgetDir, "db.sqlite");
66207
62713
  const metaFile = join$2(budgetDir, "metadata.json");
66208
- if (await exists$1(dbFile)) await removeFile$1(dbFile);
66209
- if (await exists$1(metaFile)) await removeFile$1(metaFile);
62714
+ if (await exists(dbFile)) await removeFile$1(dbFile);
62715
+ if (await exists(metaFile)) await removeFile$1(metaFile);
66210
62716
  } else await mkdir(budgetDir);
66211
62717
  await writeFile(join$2(budgetDir, "db.sqlite"), dbContent);
66212
62718
  await writeFile(join$2(budgetDir, "metadata.json"), JSON.stringify(meta));
@@ -107616,7 +104122,8 @@ var TYPE_INFO = {
107616
104122
  "isNot",
107617
104123
  "doesNotContain",
107618
104124
  "notOneOf",
107619
- "hasTags"
104125
+ "hasTags",
104126
+ "hasAnyTag"
107620
104127
  ],
107621
104128
  nullable: true
107622
104129
  },
@@ -107640,7 +104147,7 @@ var TYPE_INFO = {
107640
104147
  var FIELD_INFO = {
107641
104148
  imported_payee: {
107642
104149
  type: "string",
107643
- disallowedOps: new Set(["hasTags"])
104150
+ disallowedOps: new Set(["hasTags", "hasAnyTag"])
107644
104151
  },
107645
104152
  payee: {
107646
104153
  type: "id",
@@ -111005,6 +107512,7 @@ var OP_SCORES = {
111005
107512
  doesNotContain: 0,
111006
107513
  matches: 0,
111007
107514
  hasTags: 0,
107515
+ hasAnyTag: 0,
111008
107516
  onBudget: 0,
111009
107517
  offBudget: 0
111010
107518
  };
@@ -111397,6 +107905,21 @@ var Action = class {
111397
107905
  }
111398
107906
  };
111399
107907
  //#endregion
107908
+ //#region ../loot-core/src/shared/tags.ts
107909
+ function extractTagsForFilter(value) {
107910
+ if (!value) return [];
107911
+ const tagValues = [];
107912
+ const seenTags = /* @__PURE__ */ new Set();
107913
+ for (const [_, tag] of value.matchAll(/#*([^#\s]+)/g)) {
107914
+ const tagWithHash = "#" + tag;
107915
+ if (!seenTags.has(tagWithHash)) {
107916
+ seenTags.add(tagWithHash);
107917
+ tagValues.push(tagWithHash);
107918
+ }
107919
+ }
107920
+ return tagValues;
107921
+ }
107922
+ //#endregion
111400
107923
  //#region ../loot-core/src/server/rules/condition.ts
111401
107924
  var CONDITION_TYPES = {
111402
107925
  date: {
@@ -111448,7 +107971,8 @@ var CONDITION_TYPES = {
111448
107971
  "isNot",
111449
107972
  "doesNotContain",
111450
107973
  "notOneOf",
111451
- "hasTags"
107974
+ "hasTags",
107975
+ "hasAnyTag"
111452
107976
  ],
111453
107977
  nullable: true,
111454
107978
  parse(op, value, fieldName) {
@@ -111457,8 +107981,8 @@ var CONDITION_TYPES = {
111457
107981
  return value.filter(Boolean).map((val) => val.toLowerCase());
111458
107982
  }
111459
107983
  assert(typeof value === "string", "not-string", `Invalid string value (field: ${fieldName})`);
111460
- if (op === "contains" || op === "matches" || op === "doesNotContain" || op === "hasTags") assert(value.length > 0, "no-empty-string", `${op} must have non-empty string (field: ${fieldName})`);
111461
- if (op === "hasTags") return value;
107984
+ if (op === "contains" || op === "matches" || op === "doesNotContain" || op === "hasTags" || op === "hasAnyTag") assert(value.length > 0, "no-empty-string", `${op} must have non-empty string (field: ${fieldName})`);
107985
+ if (op === "hasTags" || op === "hasAnyTag") return value;
111462
107986
  return value.toLowerCase();
111463
107987
  }
111464
107988
  },
@@ -111582,7 +108106,19 @@ var Condition = class {
111582
108106
  return this.value.indexOf(fieldValue) !== -1;
111583
108107
  case "hasTags":
111584
108108
  if (fieldValue === null) return false;
111585
- return String(fieldValue).indexOf(this.value) !== -1;
108109
+ const normalizedFieldValue = String(fieldValue);
108110
+ return !extractTagsForFilter(this.value).some((tag) => {
108111
+ const escapedTag = tag.toLowerCase().replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
108112
+ return !new RegExp(`(?<!#)${escapedTag}([\\s#]|$)`).test(normalizedFieldValue);
108113
+ });
108114
+ case "hasAnyTag": {
108115
+ if (fieldValue === null) return false;
108116
+ const normalizedFieldValue = String(fieldValue);
108117
+ return extractTagsForFilter(this.value).some((tag) => {
108118
+ const escapedTag = tag.toLowerCase().replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
108119
+ return new RegExp(`(?<!#)${escapedTag}([\\s#]|$)`).test(normalizedFieldValue);
108120
+ });
108121
+ }
111586
108122
  case "notOneOf":
111587
108123
  if (fieldValue === null) return false;
111588
108124
  return this.value.indexOf(fieldValue) === -1;
@@ -112355,7 +108891,7 @@ function conditionsToAQL(conditions, { recurDateBounds = 100, applySpecialCases
112355
108891
  }
112356
108892
  return { amount: { [aqlOp]: value } };
112357
108893
  } else if (type === "string") return { [field]: {
112358
- $transform: op !== "hasTags" ? "$lower" : void 0,
108894
+ $transform: !["hasTags", "hasAnyTag"].includes(op) ? "$lower" : void 0,
112359
108895
  [aqlOp]: value
112360
108896
  } };
112361
108897
  else if (type === "date") return { [field]: { [aqlOp]: value.date } };
@@ -112409,18 +108945,17 @@ function conditionsToAQL(conditions, { recurDateBounds = 100, applySpecialCases
112409
108945
  if (values.length === 0) return { id: null };
112410
108946
  return { $or: values.map((v) => apply(field, "$eq", v)) };
112411
108947
  case "hasTags": {
112412
- const tagValues = [];
112413
- const seenTags = /* @__PURE__ */ new Set();
112414
- for (const [_, tag] of value.matchAll(/(?<!#)(#[^#\s]+)/g)) if (!seenTags.has(tag)) {
112415
- seenTags.add(tag);
112416
- tagValues.push(tag);
112417
- }
108948
+ const tagValues = extractTagsForFilter(value);
112418
108949
  if (tagValues.length === 0) return { id: null };
112419
108950
  return { $and: tagValues.map((v) => {
112420
108951
  const pattern = `(?<!#)${v.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\\\$/g, "[$]")}([\\s#]|$)`;
112421
108952
  return apply(field, "$regexp", pattern);
112422
108953
  }) };
112423
108954
  }
108955
+ case "hasAnyTag": return { $or: extractTagsForFilter(value).map((v) => {
108956
+ const pattern = `(?<!#)${v.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\\\$/g, "[$]")}([\\s#]|$)`;
108957
+ return apply(field, "$regexp", pattern);
108958
+ }) };
112424
108959
  case "notOneOf":
112425
108960
  const notValues = value;
112426
108961
  if (notValues.length === 0) return { id: null };
@@ -113684,7 +110219,7 @@ async function linkGoCardlessAccount({ requisitionId, account, upgradingId, offB
113684
110219
  }
113685
110220
  async function linkSimpleFinAccount({ externalAccount, upgradingId, offBudget = false, startingDate, startingBalance }) {
113686
110221
  let id;
113687
- const bank = await findOrCreateBank({ name: externalAccount.institution ?? t("Unknown") }, externalAccount.orgDomain ?? externalAccount.orgId);
110222
+ const bank = await findOrCreateBank({ name: externalAccount.institution ?? null }, externalAccount.orgDomain ?? externalAccount.orgId);
113688
110223
  if (upgradingId) {
113689
110224
  const accRow = await first$2("SELECT * FROM accounts WHERE id = ?", [upgradingId]);
113690
110225
  if (!accRow) throw new Error(`Account with ID ${upgradingId} not found.`);
@@ -113720,7 +110255,7 @@ async function linkSimpleFinAccount({ externalAccount, upgradingId, offBudget =
113720
110255
  }
113721
110256
  async function linkPluggyAiAccount({ externalAccount, upgradingId, offBudget = false, startingDate, startingBalance }) {
113722
110257
  let id;
113723
- const bank = await findOrCreateBank({ name: externalAccount.institution ?? t("Unknown") }, externalAccount.orgDomain ?? externalAccount.orgId);
110258
+ const bank = await findOrCreateBank({ name: externalAccount.institution ?? null }, externalAccount.orgDomain ?? externalAccount.orgId);
113724
110259
  if (upgradingId) {
113725
110260
  const accRow = await first$2("SELECT * FROM accounts WHERE id = ?", [upgradingId]);
113726
110261
  if (!accRow) throw new Error(`Account with ID ${upgradingId} not found.`);
@@ -113756,7 +110291,7 @@ async function linkPluggyAiAccount({ externalAccount, upgradingId, offBudget = f
113756
110291
  }
113757
110292
  async function linkEnableBankingAccount({ externalAccount, upgradingId, offBudget = false, startingDate, startingBalance }) {
113758
110293
  let id;
113759
- const bank = await findOrCreateBank({ name: externalAccount.institution ?? t("Unknown") }, externalAccount.account_id);
110294
+ const bank = await findOrCreateBank({ name: externalAccount.institution ?? null }, externalAccount.account_id);
113760
110295
  if (upgradingId) {
113761
110296
  const accRow = await first$2("SELECT * FROM accounts WHERE id = ?", [upgradingId]);
113762
110297
  if (!accRow) throw new Error(`Account with ID ${upgradingId} not found.`);
@@ -114441,38 +110976,44 @@ async function ownerCreated() {
114441
110976
  }
114442
110977
  //#endregion
114443
110978
  //#region ../loot-core/src/shared/errors.ts
110979
+ function isDatabaseSchemaMismatch(meta) {
110980
+ if (meta && typeof meta === "object" && "error" in meta && meta.error && typeof meta.error === "object" && "message" in meta.error && typeof meta.error.message === "string") return /no such (column|table)/i.test(meta.error.message);
110981
+ return false;
110982
+ }
110983
+ function getSchemaMismatchError() {
110984
+ return "This budget could not be loaded because it uses a newer database schema than this version of Actual supports. Make sure you are using the latest version, then try again.";
110985
+ }
114444
110986
  function getDownloadError({ reason, meta, fileName }) {
110987
+ if (reason === "invalid-schema" && isDatabaseSchemaMismatch(meta)) return getSchemaMismatchError();
114445
110988
  switch (reason) {
114446
110989
  case "network":
114447
- case "download-failure": return t("Downloading the file failed. Check your network connection.");
110990
+ case "download-failure": return "Downloading the file failed. Check your network connection.";
114448
110991
  case "not-zip-file":
114449
110992
  case "invalid-zip-file":
114450
- case "invalid-meta-file": return t("Downloaded file is invalid, sorry! Visit https://actualbudget.org/contact/ for support.");
110993
+ case "invalid-meta-file": return "Downloaded file is invalid, sorry! Visit https://actualbudget.org/contact/ for support.";
114451
110994
  case "decrypt-failure": return "Unable to decrypt file " + (fileName || "(unknown)") + ". To change your key, first download this file with the proper password.";
114452
- case "out-of-sync-migrations": return t("This budget cannot be loaded with this version of the app. Make sure the app is up-to-date.");
114453
- case "clock-drift": return t("Failed to download the budget because your device time differs too much from the server. Please check your device time settings and ensure they are correct.");
114454
- default: return t("Something went wrong trying to download that file, sorry! Visit https://actualbudget.org/contact/ for support. reason: {{reason}}{{info}}", {
114455
- reason,
114456
- info: meta && typeof meta === "object" && "fileId" in meta && meta.fileId ? `, fileId: ${String(meta.fileId)}` : ""
114457
- });
110995
+ case "out-of-sync-migrations": return "This budget cannot be loaded with this version of the app. Make sure the app is up-to-date.";
110996
+ case "clock-drift": return "Failed to download the budget because your device time differs too much from the server. Please check your device time settings and ensure they are correct.";
110997
+ default: return `Something went wrong trying to download that file, sorry! Visit https://actualbudget.org/contact/ for support. reason: ${reason}${meta && typeof meta === "object" && "fileId" in meta && meta.fileId ? `, fileId: ${String(meta.fileId)}` : ""}`;
114458
110998
  }
114459
110999
  }
114460
111000
  function getTestKeyError({ reason }) {
114461
111001
  switch (reason) {
114462
- case "network": return t("Unable to connect to the server. We need to access the server to get some information about your keys.");
114463
- case "old-key-style": return t("This file is encrypted with an old unsupported key style. Recreate the key on a device where the file is available, or use an older version of Actual to download it.");
114464
- case "decrypt-failure": return t("Unable to decrypt file with this password. Please try again.");
114465
- default: return t("Something went wrong trying to create a key, sorry! Visit https://actualbudget.org/contact/ for support.");
111002
+ case "network": return "Unable to connect to the server. We need to access the server to get some information about your keys.";
111003
+ case "old-key-style": return "This file is encrypted with an old unsupported key style. Recreate the key on a device where the file is available, or use an older version of Actual to download it.";
111004
+ case "decrypt-failure": return "Unable to decrypt file with this password. Please try again.";
111005
+ default: return "Something went wrong trying to create a key, sorry! Visit https://actualbudget.org/contact/ for support.";
114466
111006
  }
114467
111007
  }
114468
- function getSyncError(error, id) {
114469
- if (error === "out-of-sync-migrations" || error === "out-of-sync-data") return t("This budget cannot be loaded with this version of the app.");
114470
- else if (error === "budget-not-found") return t("Budget \"{{id}}\" not found. Check the ID of your budget in the Advanced section of the settings page.", { id });
114471
- else if (error === "clock-drift") return t("Failed to sync because your device time differs too much from the server. Please check your device time settings and ensure they are correct.");
114472
- else return t("We had an unknown problem opening \"{{id}}\".", { id });
111008
+ function getSyncError(error, id, meta) {
111009
+ if (error === "out-of-sync-migrations" || error === "out-of-sync-data") return "This budget cannot be loaded with this version of the app.";
111010
+ else if (error === "invalid-schema" && isDatabaseSchemaMismatch(meta)) return getSchemaMismatchError();
111011
+ else if (error === "budget-not-found") return `Budget "${id}" not found. Check the ID of your budget in the Advanced section of the settings page.`;
111012
+ else if (error === "clock-drift") return "Failed to sync because your device time differs too much from the server. Please check your device time settings and ensure they are correct.";
111013
+ else return `We had an unknown problem opening "${id}".`;
114473
111014
  }
114474
111015
  function getBankSyncError(error) {
114475
- return error.message || t("We had an unknown problem syncing the account.");
111016
+ return error.message || "We had an unknown problem syncing the account.";
114476
111017
  }
114477
111018
  //#endregion
114478
111019
  //#region ../loot-core/src/server/api-models.ts
@@ -114738,7 +111279,7 @@ handlers$1["api/download-budget"] = async function({ syncId, password }) {
114738
111279
  if (localBudget) {
114739
111280
  await handlers$1["load-budget"]({ id: localBudget.id });
114740
111281
  const result = await handlers$1["sync-budget"]();
114741
- if (result.error) throw new Error(getSyncError(result.error.reason, localBudget.id));
111282
+ if (result.error) throw new Error(getSyncError(result.error.reason, localBudget.id, result.error.meta));
114742
111283
  return;
114743
111284
  }
114744
111285
  const result = await handlers$1["download-budget"]({ cloudFileId: remoteBudget.fileId });
@@ -114756,7 +111297,7 @@ handlers$1["api/get-budgets"] = async function() {
114756
111297
  handlers$1["api/sync"] = async function() {
114757
111298
  const { id } = getPrefs();
114758
111299
  const result = await handlers$1["sync-budget"]();
114759
- if (result.error) throw new Error(getSyncError(result.error.reason, id));
111300
+ if (result.error) throw new Error(getSyncError(result.error.reason, id, result.error.meta));
114760
111301
  };
114761
111302
  handlers$1["api/bank-sync"] = async function(args) {
114762
111303
  const batchSync = args?.accountId == null;
@@ -116811,6 +113352,9 @@ async function checkIfScheduleExists(name, scheduleId) {
116811
113352
  if (scheduleId) return idForName["id"] !== scheduleId;
116812
113353
  return true;
116813
113354
  }
113355
+ function normalizeScheduleName(name) {
113356
+ return name?.trim() || null;
113357
+ }
116814
113358
  async function createSchedule$1({ schedule = null, conditions = [] } = {}) {
116815
113359
  const scheduleId = schedule?.id || v4();
116816
113360
  const { date: dateCond } = extractScheduleConds(conditions);
@@ -116818,9 +113362,15 @@ async function createSchedule$1({ schedule = null, conditions = [] } = {}) {
116818
113362
  if (dateCond.value == null) throw new Error("Date is required");
116819
113363
  const nextDate = getNextDate(dateCond);
116820
113364
  const nextDateRepr = nextDate ? toDateRepr(nextDate) : null;
116821
- if (schedule) if (schedule.name) {
116822
- if (await checkIfScheduleExists(schedule.name, scheduleId)) throw new Error("Cannot create schedules with the same name");
116823
- } else schedule.name = null;
113365
+ const scheduleFields = schedule && {
113366
+ ...schedule,
113367
+ name: normalizeScheduleName(schedule.name)
113368
+ };
113369
+ if (scheduleFields) {
113370
+ if (scheduleFields.name) {
113371
+ if (await checkIfScheduleExists(scheduleFields.name, scheduleId)) throw new Error("Cannot create schedules with the same name");
113372
+ }
113373
+ }
116824
113374
  const ruleId = await insertRule({
116825
113375
  stage: null,
116826
113376
  conditionsOp: "and",
@@ -116839,7 +113389,7 @@ async function createSchedule$1({ schedule = null, conditions = [] } = {}) {
116839
113389
  base_next_date_ts: now
116840
113390
  });
116841
113391
  await insertWithSchema("schedules", {
116842
- ...schedule,
113392
+ ...scheduleFields,
116843
113393
  id: scheduleId,
116844
113394
  rule: ruleId
116845
113395
  });
@@ -116847,6 +113397,11 @@ async function createSchedule$1({ schedule = null, conditions = [] } = {}) {
116847
113397
  }
116848
113398
  async function updateSchedule$1({ schedule, conditions, resetNextDate }) {
116849
113399
  if (schedule.rule) throw new Error("You cannot change the rule of a schedule");
113400
+ const scheduleFields = { ...schedule };
113401
+ if ("name" in scheduleFields) {
113402
+ scheduleFields.name = normalizeScheduleName(scheduleFields.name);
113403
+ if (scheduleFields.name && await checkIfScheduleExists(scheduleFields.name, scheduleFields.id)) throw new Error("Cannot update schedules with the same name");
113404
+ }
116850
113405
  let rule;
116851
113406
  if (conditions) {
116852
113407
  const { date: dateCond } = extractScheduleConds(conditions);
@@ -116872,9 +113427,9 @@ async function updateSchedule$1({ schedule, conditions, resetNextDate }) {
116872
113427
  id: schedule.id,
116873
113428
  reset: true
116874
113429
  });
116875
- await updateWithSchema("schedules", schedule);
113430
+ await updateWithSchema("schedules", scheduleFields);
116876
113431
  });
116877
- return schedule.id;
113432
+ return scheduleFields.id;
116878
113433
  }
116879
113434
  async function deleteSchedule$1({ id }) {
116880
113435
  const { data: ruleId } = await aqlQuery$1(q$1("schedules").filter({ id }).calculate("rule"));
@@ -123044,7 +119599,7 @@ async function idFromBudgetName(name) {
123044
119599
  let id = name.replace(/( |[^A-Za-z0-9])/g, "-") + "-" + v4().slice(0, 7);
123045
119600
  let index = 0;
123046
119601
  let budgetDir = getBudgetDir(id);
123047
- while (await exists$1(budgetDir)) {
119602
+ while (await exists(budgetDir)) {
123048
119603
  index++;
123049
119604
  budgetDir = getBudgetDir(id + index.toString());
123050
119605
  }
@@ -123058,7 +119613,7 @@ var serviceInterval = null;
123058
119613
  async function getBackups$1(id) {
123059
119614
  const backupDir = join$2(getBudgetDir(id), "backups");
123060
119615
  let paths = [];
123061
- if (await exists$1(backupDir)) {
119616
+ if (await exists(backupDir)) {
123062
119617
  paths = await listDir(backupDir);
123063
119618
  paths = paths.filter((file) => file.match(/\.zip$/));
123064
119619
  }
@@ -123077,7 +119632,7 @@ async function getBackups$1(id) {
123077
119632
  return backups;
123078
119633
  }
123079
119634
  async function getLatestBackup(id) {
123080
- if (await exists$1(join$2(getBudgetDir(id), LATEST_BACKUP_FILENAME))) return {
119635
+ if (await exists(join$2(getBudgetDir(id), LATEST_BACKUP_FILENAME))) return {
123081
119636
  id: LATEST_BACKUP_FILENAME,
123082
119637
  date: null,
123083
119638
  isLatest: true
@@ -123111,9 +119666,9 @@ async function updateBackups(backups) {
123111
119666
  }
123112
119667
  async function makeBackup$1(id) {
123113
119668
  const budgetDir = getBudgetDir(id);
123114
- if (await exists$1(join$2(budgetDir, LATEST_BACKUP_FILENAME))) await removeFile$1(join$2(getBudgetDir(id), LATEST_BACKUP_FILENAME));
119669
+ if (await exists(join$2(budgetDir, LATEST_BACKUP_FILENAME))) await removeFile$1(join$2(getBudgetDir(id), LATEST_BACKUP_FILENAME));
123115
119670
  const backupPath = join$2(budgetDir, "backups", `${format$2(/* @__PURE__ */ new Date(), "yyyy-MM-dd_HH-mm-ss")}.zip`);
123116
- if (!await exists$1(join$2(budgetDir, "backups"))) await mkdir(join$2(budgetDir, "backups"));
119671
+ if (!await exists(join$2(budgetDir, "backups"))) await mkdir(join$2(budgetDir, "backups"));
123117
119672
  const tempDbPath = join$2(budgetDir, "backups", `db.${Date.now()}.sqlite.tmp`);
123118
119673
  await copyFile(join$2(budgetDir, "db.sqlite"), tempDbPath);
123119
119674
  let db;
@@ -123127,7 +119682,7 @@ async function makeBackup$1(id) {
123127
119682
  zip.writeZip(backupPath);
123128
119683
  } finally {
123129
119684
  if (db) closeDatabase$1(db);
123130
- if (await exists$1(tempDbPath)) await removeFile$1(tempDbPath);
119685
+ if (await exists(tempDbPath)) await removeFile$1(tempDbPath);
123131
119686
  }
123132
119687
  const toRemove = await updateBackups(await getBackups$1(id));
123133
119688
  for (const id of toRemove) await removeFile$1(join$2(budgetDir, "backups", id));
@@ -123135,7 +119690,7 @@ async function makeBackup$1(id) {
123135
119690
  }
123136
119691
  async function loadBackup$1(id, backupId) {
123137
119692
  const budgetDir = getBudgetDir(id);
123138
- if (!await exists$1(join$2(budgetDir, LATEST_BACKUP_FILENAME))) {
119693
+ if (!await exists(join$2(budgetDir, LATEST_BACKUP_FILENAME))) {
123139
119694
  await copyFile(join$2(budgetDir, "db.sqlite"), join$2(budgetDir, LATEST_BACKUP_FILENAME));
123140
119695
  await copyFile(join$2(budgetDir, "metadata.json"), join$2(budgetDir, "metadata.latest.json"));
123141
119696
  stopBackupService();
@@ -123216,7 +119771,7 @@ async function getBudgets$1() {
123216
119771
  const paths = await listDir(getDocumentDir());
123217
119772
  return (await Promise.all(paths.map(async (name) => {
123218
119773
  const prefsPath = join$2(getDocumentDir(), name, "metadata.json");
123219
- if (await exists$1(prefsPath)) {
119774
+ if (await exists(prefsPath)) {
123220
119775
  let prefs;
123221
119776
  try {
123222
119777
  prefs = JSON.parse(await readFile(prefsPath));
@@ -123358,7 +119913,7 @@ async function duplicateBudget({ id, newName, cloudSync, open }) {
123358
119913
  } catch (error) {
123359
119914
  try {
123360
119915
  const newBudgetDir = getBudgetDir(newId);
123361
- if (await exists$1(newBudgetDir)) await removeDirRecursively(newBudgetDir);
119916
+ if (await exists(newBudgetDir)) await removeDirRecursively(newBudgetDir);
123362
119917
  } catch {}
123363
119918
  throw new Error(`Failed to duplicate budget file: ${error.message}`);
123364
119919
  }
@@ -123382,7 +119937,7 @@ async function createBudget({ budgetName, avoidUpload, testMode, testBudgetId }
123382
119937
  if (testMode) {
123383
119938
  budgetName = budgetName || "Test Budget";
123384
119939
  id = testBudgetId || TEST_BUDGET_ID;
123385
- if (await exists$1(getBudgetDir(id))) {
119940
+ if (await exists(getBudgetDir(id))) {
123386
119941
  if (getPrefs()?.id === id) await closeBudget();
123387
119942
  await removeDirRecursively(getBudgetDir(id));
123388
119943
  }
@@ -123407,7 +119962,7 @@ async function createBudget({ budgetName, avoidUpload, testMode, testBudgetId }
123407
119962
  }
123408
119963
  async function importBudget({ filepath, type }) {
123409
119964
  try {
123410
- if (!await exists$1(filepath)) throw new Error(`File not found at the provided path: ${filepath}`);
119965
+ if (!await exists(filepath)) throw new Error(`File not found at the provided path: ${filepath}`);
123411
119966
  return await handleBudgetImport(type, filepath, Buffer.from(await readFile(filepath, "binary"))) || {};
123412
119967
  } catch (err) {
123413
119968
  err.message = "Error importing budget: " + err.message;
@@ -123442,7 +119997,7 @@ async function _loadBudget(id) {
123442
119997
  return { error: "budget-not-found" };
123443
119998
  }
123444
119999
  captureBreadcrumb({ message: "Loading budget " + dir });
123445
- if (!await exists$1(dir)) {
120000
+ if (!await exists(dir)) {
123446
120001
  captureException(/* @__PURE__ */ new Error("budget directory does not exist"));
123447
120002
  return { error: "budget-not-found" };
123448
120003
  }
@@ -123520,7 +120075,7 @@ async function makeBackup({ id }) {
123520
120075
  async function getLastOpenedBackup() {
123521
120076
  const id = await getItem("lastBudget");
123522
120077
  if (id && id !== "") {
123523
- if (await exists$1(getBudgetDir(id))) return id;
120078
+ if (await exists(getBudgetDir(id))) return id;
123524
120079
  }
123525
120080
  return null;
123526
120081
  }
@@ -125515,6 +122070,7 @@ var reportModel = {
125515
122070
  showHiddenCategories: row.show_hidden === 1,
125516
122071
  showUncategorized: row.show_uncategorized === 1,
125517
122072
  trimIntervals: row.trim_intervals === 1,
122073
+ showTrendLines: row.show_trend_lines === 1,
125518
122074
  includeCurrentInterval: row.include_current === 1,
125519
122075
  graphType: row.graph_type,
125520
122076
  conditions: row.conditions ?? [],
@@ -125540,6 +122096,7 @@ var reportModel = {
125540
122096
  show_hidden: report.showHiddenCategories ? 1 : 0,
125541
122097
  show_uncategorized: report.showUncategorized ? 1 : 0,
125542
122098
  trim_intervals: report.trimIntervals ? 1 : 0,
122099
+ show_trend_lines: report.showTrendLines ? 1 : 0,
125543
122100
  include_current: report.includeCurrentInterval ? 1 : 0,
125544
122101
  graph_type: report.graphType,
125545
122102
  conditions: report.conditions,
@@ -125701,7 +122258,7 @@ async function copyDashboardWidget({ id, targetDashboardPageId }) {
125701
122258
  }
125702
122259
  async function importDashboard({ filePath, dashboardPageId }) {
125703
122260
  try {
125704
- if (!await exists$1(filePath)) throw new Error(`File not found at the provided path: ${filePath}`);
122261
+ if (!await exists(filePath)) throw new Error(`File not found at the provided path: ${filePath}`);
125705
122262
  const content = await readFile(filePath);
125706
122263
  const parsedContent = JSON.parse(content);
125707
122264
  exportModel.validate(parsedContent);
@@ -126671,7 +123228,7 @@ async function saveGlobalPrefs(prefs) {
126671
123228
  if (!prefs) return "ok";
126672
123229
  if (prefs.maxMonths !== void 0) await setItem("max-months", "" + prefs.maxMonths);
126673
123230
  if (prefs.categoryExpandedState !== void 0) await setItem("category-expanded-state", "" + prefs.categoryExpandedState);
126674
- if (prefs.documentDir !== void 0 && await exists$1(prefs.documentDir)) await setItem("document-dir", prefs.documentDir);
123231
+ if (prefs.documentDir !== void 0 && await exists(prefs.documentDir)) await setItem("document-dir", prefs.documentDir);
126675
123232
  if (prefs.floatingSidebar !== void 0) await setItem("floating-sidebar", "" + prefs.floatingSidebar);
126676
123233
  if (prefs.language !== void 0) await setItem("language", prefs.language);
126677
123234
  if (prefs.theme !== void 0) await setItem("theme", prefs.theme);
@@ -133809,9 +130366,9 @@ async function init$1(config) {
133809
130366
  dataDir = process.env.ACTUAL_DATA_DIR;
133810
130367
  serverURL = process.env.ACTUAL_SERVER_URL;
133811
130368
  }
133812
- await init$3();
133813
- init$4({ persist: false });
133814
- await init$5();
130369
+ await init$2();
130370
+ init$3({ persist: false });
130371
+ await init$4();
133815
130372
  _setDocumentDir(dataDir || process.cwd());
133816
130373
  if (serverURL) {
133817
130374
  setServer(serverURL);