@itwin/core-i18n 5.3.0-dev.9 → 5.3.1

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.
@@ -19,7 +19,7 @@
19
19
  */
20
20
  function cov_ogldeftyv() {
21
21
  var path = "C:\\agent\\_work\\1\\s\\core\\i18n\\lib\\cjs\\ITwinLocalization.js";
22
- var hash = "d940188727f7c3f13464903c9fef76d730c540e6";
22
+ var hash = "113751a8262a3149163a15d970bf9098e64926ce";
23
23
  var global = new Function("return this")();
24
24
  var gcv = "__coverage__";
25
25
  var coverageData = {
@@ -2123,10 +2123,10 @@ function cov_ogldeftyv() {
2123
2123
  sources: ["C:\\agent\\_work\\1\\s\\core\\i18n\\src\\ITwinLocalization.ts"],
2124
2124
  names: [],
2125
2125
  mappings: ";AAAA;;;+FAG+F;AAC/F;;GAEG;;;;;;AAEH,sDAA2E;AAC3E,wGAAmG;AACnG,gFAAqF;AACrF,sDAA6C;AAG7C,MAAM,mBAAmB,GAAW,CAAC,CAAC,CAAC,8GAA8G;AAcrJ;;;GAGG;AACH,MAAa,iBAAiB;IACrB,OAAO,CAAO;IACJ,YAAY,CAAc;IAC1B,eAAe,CAAiB;IAChC,iBAAiB,CAAkB;IACnC,WAAW,GAAG,IAAI,GAAG,EAAyB,CAAC;IAEhE,YAAmB,OAA6B;QAC9C,IAAI,CAAC,OAAO,GAAG,iBAAO,CAAC,cAAc,EAAE,CAAC;QAExC,IAAI,CAAC,eAAe,GAAG;YACrB,QAAQ,EAAE,OAAO,EAAE,WAAW,IAAI,6BAA6B;YAC/D,WAAW,EAAE,IAAI;YACjB,GAAG,OAAO,EAAE,kBAAkB;SAC/B,CAAC;QAEF,IAAI,CAAC,iBAAiB,GAAG;YACvB,KAAK,EAAE,CAAC,aAAa,EAAE,WAAW,EAAE,SAAS,CAAC;YAC9C,iBAAiB,EAAE,KAAK;YACxB,MAAM,EAAE,EAAE;YACV,GAAG,OAAO,EAAE,eAAe;SAC5B,CAAC;QAEF,IAAI,CAAC,YAAY,GAAG;YAClB,aAAa,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE;YACpC,WAAW,EAAE,IAAI;YACjB,UAAU,EAAE,mBAAmB;YAC/B,OAAO,EAAE,IAAI,CAAC,eAAe;YAC7B,SAAS,EAAE,IAAI,CAAC,iBAAiB;YACjC,GAAG,OAAO,EAAE,WAAW;SACxB,CAAC;QAEF,IAAI,CAAC,OAAO;aACT,GAAG,CAAC,OAAO,EAAE,cAAc,IAAI,0CAA8B,CAAC;aAC9D,GAAG,CAAC,OAAO,EAAE,aAAa,IAAI,8BAAO,CAAC;aACtC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAC5B,CAAC;IAEM,KAAK,CAAC,UAAU,CAAC,UAAoB;QAE1C,mDAAmD;QACnD,MAAM,cAAc,GAAa,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACrE,MAAM,kBAAkB,GAAgB,IAAI,GAAG,CAAC,CAAC,GAAG,UAAU,EAAE,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,qBAAqB;QAE1G,MAAM,gBAAgB,GAAuC,IAAI,CAAC,YAAY,CAAC,SAAS,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;QAC1G,IAAI,gBAAgB;YAClB,kBAAkB,CAAC,GAAG,CAAC,gBAA0B,CAAC,CAAC,CAAC,oDAAoD;QAE1G,MAAM,WAAW,GAAgB;YAC/B,GAAG,IAAI,CAAC,YAAY;YACpB,SAAS,EAAE,gBAAgB;YAC3B,EAAE,EAAE,CAAC,GAAG,kBAAkB,CAAC;SAC5B,CAAC;QAEF,iDAAiD;QACjD,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa;YACxC,WAAW,CAAC,KAAK,GAAG,IAAI,CAAC;QAE3B,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,CAA6B,CAAC;QAE/E,KAAK,MAAM,EAAE,IAAI,UAAU;YACzB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;QAExC,OAAO,WAAW,CAAC;IACrB,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACI,gBAAgB,CAAC,IAAY;QAClC,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC;IACrF,CAAC;IAED;;;;;;;;;;;;OAYG;IACI,kBAAkB,CAAC,GAAsB,EAAE,OAAsB;QACtE,IAAI,OAAO,EAAE,aAAa,IAAI,OAAO,EAAE,aAAa,EAAE,CAAC;YACrD,MAAM,IAAI,KAAK,CAAC,sFAAsF,CAAC,CAAC;QAC1G,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAE3C,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACzD,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED;;;;;;OAMG;IACI,gBAAgB,CAAC,SAAiB,EAAE,GAAsB,EAAE,OAAsB;QACvF,IAAI,OAAO,EAAE,aAAa,IAAI,OAAO,EAAE,aAAa,EAAE,CAAC;YACrD,MAAM,IAAI,KAAK,CAAC,sFAAsF,CAAC,CAAC;QAC1G,CAAC;QAED,OAAO,GAAG;YACR,GAAG,OAAO;YACV,EAAE,EAAE,SAAS,EAAE,oCAAoC;SACpD,CAAC;QAEF,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC;QACnD,MAAM,GAAG,GAAG,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAC7B,IAAI,OAAO,GAAG,KAAK,QAAQ;YACzB,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAElD,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;;OAGG;IACI,mBAAmB,CAAC,IAAY;QACrC,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,gBAAgB;IACT,eAAe;QACpB,OAAO,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;IAChC,CAAC;IAED,qDAAqD;IAC9C,KAAK,CAAC,cAAc,CAAC,QAAgB;QAC1C,OAAO,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,QAAQ,CAA6B,CAAC;IAC3E,CAAC;IAED;;;;;;;OAOG;IACI,KAAK,CAAC,iBAAiB,CAAC,IAAY;QACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,QAAQ,KAAK,SAAS;YACxB,OAAO,QAAQ,CAAC;QAElB,MAAM,cAAc,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YACnD,mEAAmE;YACnE,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,EAAE;gBACxC,IAAI,CAAC,GAAG;oBACN,OAAO,OAAO,EAAE,CAAC;gBAEnB,qCAAqC;gBACrC,yHAAyH;gBACzH,2GAA2G;gBAC3G,8HAA8H;gBAC9H,8IAA8I;gBAC9I,IAAI,OAAO,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC,GAAG,CAAC,CAAC,UAAe,EAAE,EAAE,CAAC,IAAI,UAAU,GAAG,CAAC,CAAC;gBAEjF,IAAI,CAAC;oBACH,KAAK,MAAM,SAAS,IAAI,GAAG,EAAE,CAAC;wBAC5B,IAAI,OAAO,SAAS,KAAK,QAAQ;4BAC/B,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;oBAC9E,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,GAAG,EAAE,CAAC;gBACf,CAAC;gBACD,+DAA+D;gBAC/D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;oBACtB,qBAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,8BAA8B,IAAI,kBAAkB,CAAC,CAAC;gBAEhF,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QAC3C,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,gBAAgB;IACT,mBAAmB,CAAC,IAAY;QACrC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;CACF;AA7MD,8CA6MC;AAED,MAAM,iBAAiB;IACd,MAAM,CAAU,IAAI,GAAG,QAAQ,CAAC;IAChC,GAAG,CAAC,IAAc,IAAI,qBAAM,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5E,IAAI,CAAC,IAAc,IAAI,qBAAM,CAAC,UAAU,CAAC,MAAM,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAChF,KAAK,CAAC,IAAc,IAAI,qBAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,gBAAgB,CAAC,IAAc;QACrC,IAAI,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACtB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAC;YACrC,IAAI,OAAO,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ;gBAC7B,OAAO,IAAI,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAChC,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC",
2126
- sourcesContent: ["/*---------------------------------------------------------------------------------------------\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n* See LICENSE.md in the project root for license terms and full copyright notice.\n*--------------------------------------------------------------------------------------------*/\n/** @packageDocumentation\n * @module Localization\n */\n\nimport i18next, { i18n, InitOptions, Module, TOptionsBase } from \"i18next\";\nimport i18nextBrowserLanguageDetector, { DetectorOptions } from \"i18next-browser-languagedetector\";\nimport Backend, { HttpBackendOptions as BackendOptions } from \"i18next-http-backend\";\nimport { Logger } from \"@itwin/core-bentley\";\nimport type { Localization } from \"@itwin/core-common\";\n\nconst DEFAULT_MAX_RETRIES: number = 1; // a low number prevents wasted time and potential timeouts when requesting localization files throws an error\n\n/** Options for ITwinLocalization\n * @public\n */\nexport interface LocalizationOptions {\n urlTemplate?: string;\n backendPlugin?: Module;\n detectorPlugin?: Module;\n initOptions?: InitOptions;\n backendHttpOptions?: BackendOptions;\n detectorOptions?: DetectorOptions;\n}\n\n/** Supplies localizations for iTwin.js\n * @note this class uses the [i18next](https://www.i18next.com/) package.\n * @public\n */\nexport class ITwinLocalization implements Localization {\n public i18next: i18n;\n private readonly _initOptions: InitOptions;\n private readonly _backendOptions: BackendOptions;\n private readonly _detectionOptions: DetectorOptions;\n private readonly _namespaces = new Map<string, Promise<void>>();\n\n public constructor(options?: LocalizationOptions) {\n this.i18next = i18next.createInstance();\n\n this._backendOptions = {\n loadPath: options?.urlTemplate ?? \"locales/{{lng}}/{{ns}}.json\",\n crossDomain: true,\n ...options?.backendHttpOptions,\n };\n\n this._detectionOptions = {\n order: [\"querystring\", \"navigator\", \"htmlTag\"],\n lookupQuerystring: \"lng\",\n caches: [],\n ...options?.detectorOptions,\n };\n\n this._initOptions = {\n interpolation: { escapeValue: true },\n fallbackLng: \"en\",\n maxRetries: DEFAULT_MAX_RETRIES,\n backend: this._backendOptions,\n detection: this._detectionOptions,\n ...options?.initOptions,\n };\n\n this.i18next\n .use(options?.detectorPlugin ?? i18nextBrowserLanguageDetector)\n .use(options?.backendPlugin ?? Backend)\n .use(TranslationLogger);\n }\n\n public async initialize(namespaces: string[]): Promise<void> {\n\n // Also consider namespaces passed into constructor\n const initNamespaces: string[] = [this._initOptions.ns || []].flat();\n const combinedNamespaces: Set<string> = new Set([...namespaces, ...initNamespaces]); // without duplicates\n\n const defaultNamespace: string | false | readonly string[] = this._initOptions.defaultNS ?? namespaces[0];\n if (defaultNamespace)\n combinedNamespaces.add(defaultNamespace as string); // Make sure default namespace is in namespaces list\n\n const initOptions: InitOptions = {\n ...this._initOptions,\n defaultNS: defaultNamespace,\n ns: [...combinedNamespaces],\n };\n\n // if in a development environment, set debugging\n if (process.env.NODE_ENV === \"development\")\n initOptions.debug = true;\n\n const initPromise = this.i18next.init(initOptions) as unknown as Promise<void>;\n\n for (const ns of namespaces)\n this._namespaces.set(ns, initPromise);\n\n return initPromise;\n }\n\n /** Replace all instances of `%{key}` within a string with the translations of those keys.\n * For example:\n * ``` ts\n * \"MyKeys\": {\n * \"Key1\": \"First value\",\n * \"Key2\": \"Second value\"\n * }\n * ```\n *\n * ``` ts\n * i18.translateKeys(\"string with %{MyKeys.Key1} followed by %{MyKeys.Key2}!\"\") // returns \"string with First Value followed by Second Value!\"\n * ```\n * @param line The input line, potentially containing %{keys}.\n * @returns The line with all %{keys} translated\n * @public\n */\n public getLocalizedKeys(line: string): string {\n return line.replace(/\\%\\{(.+?)\\}/g, (_match, tag) => this.getLocalizedString(tag));\n }\n\n /** Return the translated value of a key.\n * @param key - the key that matches a property in the JSON localization file.\n * @note The key includes the namespace, which identifies the particular localization file that contains the property,\n * followed by a colon, followed by the property in the JSON file.\n * For example:\n * ``` ts\n * const dataString: string = IModelApp.localization.getLocalizedString(\"iModelJs:BackgroundMap.BingDataAttribution\");\n * ```\n * assigns to dataString the string with property BackgroundMap.BingDataAttribution from the iModelJs.json localization file.\n * @returns The string corresponding to the first key that resolves.\n * @throws Error if no keys resolve to a string.\n * @public\n */\n public getLocalizedString(key: string | string[], options?: TOptionsBase): string {\n if (options?.returnDetails || options?.returnObjects) {\n throw new Error(\"Translation key must map to a string, but the given options will result in an object\");\n }\n\n const value = this.i18next.t(key, options);\n\n if (typeof value !== \"string\") {\n throw new Error(\"Translation key(s) string not found\");\n }\n\n return value;\n }\n\n /** Gets the English translation.\n * @param namespace - the namespace that identifies the particular localization file that contains the property.\n * @param key - the key that matches a property in the JSON localization file.\n * @returns The string corresponding to the first key that resolves.\n * @throws Error if no keys resolve to a string.\n * @internal\n */\n public getEnglishString(namespace: string, key: string | string[], options?: TOptionsBase): string {\n if (options?.returnDetails || options?.returnObjects) {\n throw new Error(\"Translation key must map to a string, but the given options will result in an object\");\n }\n\n options = {\n ...options,\n ns: namespace, // ensure namespace argument is used\n };\n\n const en = this.i18next.getFixedT(\"en\", namespace);\n const str = en(key, options);\n if (typeof str !== \"string\")\n throw new Error(\"Translation key(s) not found\");\n\n return str;\n }\n\n /** Get the promise for an already registered Namespace.\n * @param name - the name of the namespace\n * @public\n */\n public getNamespacePromise(name: string): Promise<void> | undefined {\n return this._namespaces.get(name);\n }\n\n /** @internal */\n public getLanguageList(): readonly string[] {\n return this.i18next.languages;\n }\n\n /** override the language detected in the browser */\n public async changeLanguage(language: string) {\n return this.i18next.changeLanguage(language) as unknown as Promise<void>;\n }\n\n /** Register a new Namespace and return it. If the namespace is already registered, it will be returned.\n * @param name - the name of the namespace, which is the base name of the JSON file that contains the localization properties.\n * @note - The registerNamespace method starts fetching the appropriate version of the JSON localization file from the server,\n * based on the current locale. To make sure that fetch is complete before performing translations from this namespace, await\n * fulfillment of the readPromise Promise property of the returned LocalizationNamespace.\n * @see [Localization in iTwin.js]($docs/learning/frontend/Localization.md)\n * @public\n */\n public async registerNamespace(name: string): Promise<void> {\n const existing = this._namespaces.get(name);\n if (existing !== undefined)\n return existing;\n\n const theReadPromise = new Promise<void>((resolve) => {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n this.i18next.loadNamespaces(name, (err) => {\n if (!err)\n return resolve();\n\n // Here we got a non-null err object.\n // This method is called when the system has attempted to load the resources for the namespaces for each possible locale.\n // For example 'fr-ca' might be the most specific locale, in which case 'fr' and 'en' are fallback locales.\n // Using Backend from i18next-http-backend, err will be an array of strings of each namespace it tried to read and its locale.\n // There might be errs for some other namespaces as well as this one. We resolve the promise unless there's an error for each possible locale.\n let locales = this.getLanguageList().map((thisLocale: any) => `/${thisLocale}/`);\n\n try {\n for (const thisError of err) {\n if (typeof thisError === \"string\")\n locales = locales.filter((thisLocale) => !thisError.includes(thisLocale));\n }\n } catch {\n locales = [];\n }\n // if we removed every locale from the array, it wasn't loaded.\n if (locales.length === 0)\n Logger.logError(\"i18n\", `No resources for namespace ${name} could be loaded`);\n\n resolve();\n });\n });\n this._namespaces.set(name, theReadPromise);\n return theReadPromise;\n }\n\n /** @internal */\n public unregisterNamespace(name: string): void {\n this._namespaces.delete(name);\n }\n}\n\nclass TranslationLogger {\n public static readonly type = \"logger\";\n public log(args: string[]) { Logger.logInfo(\"i18n\", this.createLogMessage(args)); }\n public warn(args: string[]) { Logger.logWarning(\"i18n\", this.createLogMessage(args)); }\n public error(args: string[]) { Logger.logError(\"i18n\", this.createLogMessage(args)); }\n private createLogMessage(args: string[]) {\n let message = args[0];\n for (let i = 1; i < args.length; ++i) {\n if (typeof args[i] === \"string\")\n message += `\\n ${args[i]}`;\n }\n return message;\n }\n}\n"]
2126
+ sourcesContent: ["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Localization\r\n */\r\n\r\nimport i18next, { i18n, InitOptions, Module, TOptionsBase } from \"i18next\";\r\nimport i18nextBrowserLanguageDetector, { DetectorOptions } from \"i18next-browser-languagedetector\";\r\nimport Backend, { HttpBackendOptions as BackendOptions } from \"i18next-http-backend\";\r\nimport { Logger } from \"@itwin/core-bentley\";\r\nimport type { Localization } from \"@itwin/core-common\";\r\n\r\nconst DEFAULT_MAX_RETRIES: number = 1; // a low number prevents wasted time and potential timeouts when requesting localization files throws an error\r\n\r\n/** Options for ITwinLocalization\r\n * @public\r\n */\r\nexport interface LocalizationOptions {\r\n urlTemplate?: string;\r\n backendPlugin?: Module;\r\n detectorPlugin?: Module;\r\n initOptions?: InitOptions;\r\n backendHttpOptions?: BackendOptions;\r\n detectorOptions?: DetectorOptions;\r\n}\r\n\r\n/** Supplies localizations for iTwin.js\r\n * @note this class uses the [i18next](https://www.i18next.com/) package.\r\n * @public\r\n */\r\nexport class ITwinLocalization implements Localization {\r\n public i18next: i18n;\r\n private readonly _initOptions: InitOptions;\r\n private readonly _backendOptions: BackendOptions;\r\n private readonly _detectionOptions: DetectorOptions;\r\n private readonly _namespaces = new Map<string, Promise<void>>();\r\n\r\n public constructor(options?: LocalizationOptions) {\r\n this.i18next = i18next.createInstance();\r\n\r\n this._backendOptions = {\r\n loadPath: options?.urlTemplate ?? \"locales/{{lng}}/{{ns}}.json\",\r\n crossDomain: true,\r\n ...options?.backendHttpOptions,\r\n };\r\n\r\n this._detectionOptions = {\r\n order: [\"querystring\", \"navigator\", \"htmlTag\"],\r\n lookupQuerystring: \"lng\",\r\n caches: [],\r\n ...options?.detectorOptions,\r\n };\r\n\r\n this._initOptions = {\r\n interpolation: { escapeValue: true },\r\n fallbackLng: \"en\",\r\n maxRetries: DEFAULT_MAX_RETRIES,\r\n backend: this._backendOptions,\r\n detection: this._detectionOptions,\r\n ...options?.initOptions,\r\n };\r\n\r\n this.i18next\r\n .use(options?.detectorPlugin ?? i18nextBrowserLanguageDetector)\r\n .use(options?.backendPlugin ?? Backend)\r\n .use(TranslationLogger);\r\n }\r\n\r\n public async initialize(namespaces: string[]): Promise<void> {\r\n\r\n // Also consider namespaces passed into constructor\r\n const initNamespaces: string[] = [this._initOptions.ns || []].flat();\r\n const combinedNamespaces: Set<string> = new Set([...namespaces, ...initNamespaces]); // without duplicates\r\n\r\n const defaultNamespace: string | false | readonly string[] = this._initOptions.defaultNS ?? namespaces[0];\r\n if (defaultNamespace)\r\n combinedNamespaces.add(defaultNamespace as string); // Make sure default namespace is in namespaces list\r\n\r\n const initOptions: InitOptions = {\r\n ...this._initOptions,\r\n defaultNS: defaultNamespace,\r\n ns: [...combinedNamespaces],\r\n };\r\n\r\n // if in a development environment, set debugging\r\n if (process.env.NODE_ENV === \"development\")\r\n initOptions.debug = true;\r\n\r\n const initPromise = this.i18next.init(initOptions) as unknown as Promise<void>;\r\n\r\n for (const ns of namespaces)\r\n this._namespaces.set(ns, initPromise);\r\n\r\n return initPromise;\r\n }\r\n\r\n /** Replace all instances of `%{key}` within a string with the translations of those keys.\r\n * For example:\r\n * ``` ts\r\n * \"MyKeys\": {\r\n * \"Key1\": \"First value\",\r\n * \"Key2\": \"Second value\"\r\n * }\r\n * ```\r\n *\r\n * ``` ts\r\n * i18.translateKeys(\"string with %{MyKeys.Key1} followed by %{MyKeys.Key2}!\"\") // returns \"string with First Value followed by Second Value!\"\r\n * ```\r\n * @param line The input line, potentially containing %{keys}.\r\n * @returns The line with all %{keys} translated\r\n * @public\r\n */\r\n public getLocalizedKeys(line: string): string {\r\n return line.replace(/\\%\\{(.+?)\\}/g, (_match, tag) => this.getLocalizedString(tag));\r\n }\r\n\r\n /** Return the translated value of a key.\r\n * @param key - the key that matches a property in the JSON localization file.\r\n * @note The key includes the namespace, which identifies the particular localization file that contains the property,\r\n * followed by a colon, followed by the property in the JSON file.\r\n * For example:\r\n * ``` ts\r\n * const dataString: string = IModelApp.localization.getLocalizedString(\"iModelJs:BackgroundMap.BingDataAttribution\");\r\n * ```\r\n * assigns to dataString the string with property BackgroundMap.BingDataAttribution from the iModelJs.json localization file.\r\n * @returns The string corresponding to the first key that resolves.\r\n * @throws Error if no keys resolve to a string.\r\n * @public\r\n */\r\n public getLocalizedString(key: string | string[], options?: TOptionsBase): string {\r\n if (options?.returnDetails || options?.returnObjects) {\r\n throw new Error(\"Translation key must map to a string, but the given options will result in an object\");\r\n }\r\n\r\n const value = this.i18next.t(key, options);\r\n\r\n if (typeof value !== \"string\") {\r\n throw new Error(\"Translation key(s) string not found\");\r\n }\r\n\r\n return value;\r\n }\r\n\r\n /** Gets the English translation.\r\n * @param namespace - the namespace that identifies the particular localization file that contains the property.\r\n * @param key - the key that matches a property in the JSON localization file.\r\n * @returns The string corresponding to the first key that resolves.\r\n * @throws Error if no keys resolve to a string.\r\n * @internal\r\n */\r\n public getEnglishString(namespace: string, key: string | string[], options?: TOptionsBase): string {\r\n if (options?.returnDetails || options?.returnObjects) {\r\n throw new Error(\"Translation key must map to a string, but the given options will result in an object\");\r\n }\r\n\r\n options = {\r\n ...options,\r\n ns: namespace, // ensure namespace argument is used\r\n };\r\n\r\n const en = this.i18next.getFixedT(\"en\", namespace);\r\n const str = en(key, options);\r\n if (typeof str !== \"string\")\r\n throw new Error(\"Translation key(s) not found\");\r\n\r\n return str;\r\n }\r\n\r\n /** Get the promise for an already registered Namespace.\r\n * @param name - the name of the namespace\r\n * @public\r\n */\r\n public getNamespacePromise(name: string): Promise<void> | undefined {\r\n return this._namespaces.get(name);\r\n }\r\n\r\n /** @internal */\r\n public getLanguageList(): readonly string[] {\r\n return this.i18next.languages;\r\n }\r\n\r\n /** override the language detected in the browser */\r\n public async changeLanguage(language: string) {\r\n return this.i18next.changeLanguage(language) as unknown as Promise<void>;\r\n }\r\n\r\n /** Register a new Namespace and return it. If the namespace is already registered, it will be returned.\r\n * @param name - the name of the namespace, which is the base name of the JSON file that contains the localization properties.\r\n * @note - The registerNamespace method starts fetching the appropriate version of the JSON localization file from the server,\r\n * based on the current locale. To make sure that fetch is complete before performing translations from this namespace, await\r\n * fulfillment of the readPromise Promise property of the returned LocalizationNamespace.\r\n * @see [Localization in iTwin.js]($docs/learning/frontend/Localization.md)\r\n * @public\r\n */\r\n public async registerNamespace(name: string): Promise<void> {\r\n const existing = this._namespaces.get(name);\r\n if (existing !== undefined)\r\n return existing;\r\n\r\n const theReadPromise = new Promise<void>((resolve) => {\r\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\r\n this.i18next.loadNamespaces(name, (err) => {\r\n if (!err)\r\n return resolve();\r\n\r\n // Here we got a non-null err object.\r\n // This method is called when the system has attempted to load the resources for the namespaces for each possible locale.\r\n // For example 'fr-ca' might be the most specific locale, in which case 'fr' and 'en' are fallback locales.\r\n // Using Backend from i18next-http-backend, err will be an array of strings of each namespace it tried to read and its locale.\r\n // There might be errs for some other namespaces as well as this one. We resolve the promise unless there's an error for each possible locale.\r\n let locales = this.getLanguageList().map((thisLocale: any) => `/${thisLocale}/`);\r\n\r\n try {\r\n for (const thisError of err) {\r\n if (typeof thisError === \"string\")\r\n locales = locales.filter((thisLocale) => !thisError.includes(thisLocale));\r\n }\r\n } catch {\r\n locales = [];\r\n }\r\n // if we removed every locale from the array, it wasn't loaded.\r\n if (locales.length === 0)\r\n Logger.logError(\"i18n\", `No resources for namespace ${name} could be loaded`);\r\n\r\n resolve();\r\n });\r\n });\r\n this._namespaces.set(name, theReadPromise);\r\n return theReadPromise;\r\n }\r\n\r\n /** @internal */\r\n public unregisterNamespace(name: string): void {\r\n this._namespaces.delete(name);\r\n }\r\n}\r\n\r\nclass TranslationLogger {\r\n public static readonly type = \"logger\";\r\n public log(args: string[]) { Logger.logInfo(\"i18n\", this.createLogMessage(args)); }\r\n public warn(args: string[]) { Logger.logWarning(\"i18n\", this.createLogMessage(args)); }\r\n public error(args: string[]) { Logger.logError(\"i18n\", this.createLogMessage(args)); }\r\n private createLogMessage(args: string[]) {\r\n let message = args[0];\r\n for (let i = 1; i < args.length; ++i) {\r\n if (typeof args[i] === \"string\")\r\n message += `\\n ${args[i]}`;\r\n }\r\n return message;\r\n }\r\n}\r\n"]
2127
2127
  },
2128
2128
  _coverageSchema: "1a1c01bbd47fc00a2c39e90264f33305004495a9",
2129
- hash: "d940188727f7c3f13464903c9fef76d730c540e6"
2129
+ hash: "113751a8262a3149163a15d970bf9098e64926ce"
2130
2130
  };
2131
2131
  var coverage = global[gcv] || (global[gcv] = {});
2132
2132
  if (!coverage[path] || coverage[path].hash !== hash) {
@@ -17737,6 +17737,10 @@ var DbResult;
17737
17737
  DbResult[DbResult["BE_SQLITE_ERROR_SchemaUpgradeRecommended"] = 369098762] = "BE_SQLITE_ERROR_SchemaUpgradeRecommended";
17738
17738
  /** schema update require data transform */
17739
17739
  DbResult[DbResult["BE_SQLITE_ERROR_DataTransformRequired"] = 385875978] = "BE_SQLITE_ERROR_DataTransformRequired";
17740
+ /** Db not open */
17741
+ DbResult[DbResult["BE_SQLITE_ERROR_NOTOPEN"] = 16777217] = "BE_SQLITE_ERROR_NOTOPEN";
17742
+ /** Error propagating changes during commit */
17743
+ DbResult[DbResult["BE_SQLITE_ERROR_PropagateChangesFailed"] = 33554433] = "BE_SQLITE_ERROR_PropagateChangesFailed";
17740
17744
  DbResult[DbResult["BE_SQLITE_LOCKED_SHAREDCACHE"] = 262] = "BE_SQLITE_LOCKED_SHAREDCACHE";
17741
17745
  DbResult[DbResult["BE_SQLITE_BUSY_RECOVERY"] = 261] = "BE_SQLITE_BUSY_RECOVERY";
17742
17746
  DbResult[DbResult["BE_SQLITE_CANTOPEN_NOTEMPDIR"] = 270] = "BE_SQLITE_CANTOPEN_NOTEMPDIR";
@@ -20451,12 +20455,7 @@ var Guid;
20451
20455
  Guid.isV4Guid = isV4Guid;
20452
20456
  /** Create a new V4 Guid value */
20453
20457
  function createValue() {
20454
- // https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
20455
- return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
20456
- const r = Math.random() * 16 | 0;
20457
- const v = c === "x" ? r : (r & 0x3 | 0x8);
20458
- return v.toString(16);
20459
- });
20458
+ return crypto.randomUUID();
20460
20459
  }
20461
20460
  Guid.createValue = createValue;
20462
20461
  /**
@@ -25685,9 +25684,14 @@ describe("ITwinLocalization", () => {
25685
25684
  chai_1.assert.equal(localization.getLocalizedString("SecondTrivial.MissingString"), "SecondTrivial.MissingString");
25686
25685
  chai_1.assert.equal(localization.getLocalizedString(["NotExist", "MissingKeyObject.MissingString"]), "MissingKeyObject.MissingString");
25687
25686
  });
25688
- it("read from en-US fallback", () => {
25689
- chai_1.assert.equal(localization.getLocalizedString("OnlyEnglishUS"), "HelloUS");
25690
- });
25687
+ // TODO: Fix test on Linux CI environment
25688
+ // On current Linux CI environment, "@POSIX" is appended as a suffix to the locale,
25689
+ // which means that the en-US locales do not get loaded.
25690
+ if (!navigator.userAgent.toLowerCase().includes("linux")) {
25691
+ it("read from en-US fallback", () => {
25692
+ chai_1.assert.equal(localization.getLocalizedString("OnlyEnglishUS"), "HelloUS");
25693
+ });
25694
+ }
25691
25695
  });
25692
25696
  describe("Default Namespace (German)", () => {
25693
25697
  it("first level with no substitution", () => {
@@ -25784,9 +25788,14 @@ describe("ITwinLocalization", () => {
25784
25788
  chai_1.assert.equal(localization.getLocalizedString("Test:SecondTrivial.MissingString"), "SecondTrivial.MissingString");
25785
25789
  chai_1.assert.equal(localization.getLocalizedString("Test:MissingKeyObject.MissingString"), "MissingKeyObject.MissingString");
25786
25790
  });
25787
- it("read from en-US fallback", () => {
25788
- chai_1.assert.equal(localization.getLocalizedString("Default:OnlyEnglishUS"), "HelloUS");
25789
- });
25791
+ // TODO: Fix test on Linux CI environment
25792
+ // On current Linux CI environment, "@POSIX" is appended as a suffix to the locale,
25793
+ // which means that the en-US locales do not get loaded.
25794
+ if (!navigator.userAgent.toLowerCase().includes("linux")) {
25795
+ it("read from en-US fallback", () => {
25796
+ chai_1.assert.equal(localization.getLocalizedString("Default:OnlyEnglishUS"), "HelloUS");
25797
+ });
25798
+ }
25790
25799
  });
25791
25800
  describe("Given Namespace (German)", () => {
25792
25801
  it("first level with no substitution", () => {
@@ -26189,13 +26198,18 @@ describe("ITwinLocalization", () => {
26189
26198
  // });
26190
26199
  describe("#getLanguageList", () => {
26191
26200
  let languages;
26192
- it("english language list includes en and en-US", async () => {
26193
- localization = new ITwinLocalization_1.ITwinLocalization();
26194
- await localization.initialize([]);
26195
- languages = localization.getLanguageList();
26196
- chai_1.assert.isTrue(languages.includes("en-US"));
26197
- chai_1.assert.isTrue(languages.includes("en"));
26198
- });
26201
+ // TODO: Fix test on Linux CI environment
26202
+ // On current Linux CI environment, "@POSIX" is appended as a suffix to the locale,
26203
+ // which means that the en-US locales do not get loaded.
26204
+ if (!navigator.userAgent.toLowerCase().includes("linux")) {
26205
+ it("english language list includes en and en-US", async () => {
26206
+ localization = new ITwinLocalization_1.ITwinLocalization();
26207
+ await localization.initialize([]);
26208
+ languages = localization.getLanguageList();
26209
+ chai_1.assert.isTrue(languages.includes("en-US"));
26210
+ chai_1.assert.isTrue(languages.includes("en"));
26211
+ });
26212
+ }
26199
26213
  it("when non-english language is set as default, that language and english are included in langauge list", async () => {
26200
26214
  germanLocalization = new ITwinLocalization_1.ITwinLocalization({ initOptions: { lng: "de" } });
26201
26215
  await germanLocalization.initialize([]);