@diia-inhouse/i18n 2.8.23 → 3.1.0
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.d.ts +4 -0
- package/dist/index.js +5 -19
- package/dist/interfaces/metrics/index.d.ts +12 -0
- package/dist/interfaces/services/i18n.d.ts +16 -0
- package/dist/interfaces/services/i18n.js +6 -7
- package/dist/metrics/index.d.ts +8 -0
- package/dist/metrics/index.js +6 -7
- package/dist/services/i18n.d.ts +43 -0
- package/dist/services/i18n.js +68 -74
- package/dist/services/i18next.d.ts +26 -0
- package/dist/services/i18next.js +116 -167
- package/dist/services/index.d.ts +2 -0
- package/dist/services/index.js +3 -19
- package/package.json +36 -40
- package/dist/index.js.map +0 -1
- package/dist/interfaces/metrics/index.js +0 -3
- package/dist/interfaces/metrics/index.js.map +0 -1
- package/dist/interfaces/services/i18n.js.map +0 -1
- package/dist/metrics/index.js.map +0 -1
- package/dist/services/i18n.js.map +0 -1
- package/dist/services/i18next.js.map +0 -1
- package/dist/services/index.js.map +0 -1
- package/dist/types/index.d.ts +0 -2
- package/dist/types/interfaces/metrics/index.d.ts +0 -8
- package/dist/types/interfaces/services/i18n.d.ts +0 -12
- package/dist/types/metrics/index.d.ts +0 -4
- package/dist/types/services/i18n.d.ts +0 -39
- package/dist/types/services/i18next.d.ts +0 -25
- package/dist/types/services/index.d.ts +0 -2
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { I18nService } from "./services/i18n.js";
|
|
2
|
+
import { I18nextService, TranslationFunction } from "./services/i18next.js";
|
|
3
|
+
import { missedInterpolationParamsTotalMetric, missedLocaleKeysTotalMetric } from "./metrics/index.js";
|
|
4
|
+
export { I18nService, I18nextService, TranslationFunction, missedInterpolationParamsTotalMetric, missedLocaleKeysTotalMetric };
|
package/dist/index.js
CHANGED
|
@@ -1,19 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./services"), exports);
|
|
18
|
-
__exportStar(require("./metrics"), exports);
|
|
19
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
import { I18nService } from "./services/i18n.js";
|
|
2
|
+
import { missedInterpolationParamsTotalMetric, missedLocaleKeysTotalMetric } from "./metrics/index.js";
|
|
3
|
+
import { I18nextService } from "./services/i18next.js";
|
|
4
|
+
import "./services/index.js";
|
|
5
|
+
export { I18nService, I18nextService, missedInterpolationParamsTotalMetric, missedLocaleKeysTotalMetric };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { LocaleType } from "../services/i18n.js";
|
|
2
|
+
|
|
3
|
+
//#region src/interfaces/metrics/index.d.ts
|
|
4
|
+
interface MissedLocaleKeysTotalLabelsMap {
|
|
5
|
+
locale: LocaleType;
|
|
6
|
+
status: "missing" | "fallback_used";
|
|
7
|
+
}
|
|
8
|
+
interface MissedInterpolationParamsTotalLabelsMap {
|
|
9
|
+
locale: LocaleType;
|
|
10
|
+
}
|
|
11
|
+
//#endregion
|
|
12
|
+
export { MissedInterpolationParamsTotalLabelsMap, MissedLocaleKeysTotalLabelsMap };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Paths } from "type-fest";
|
|
2
|
+
|
|
3
|
+
//#region src/interfaces/services/i18n.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* @deprecated I18nKey is deprecated along with I18nService. Use I18nextService with TranslationFunction<T> instead.
|
|
6
|
+
*/
|
|
7
|
+
type I18nKey<L> = L extends object ? Paths<L, {
|
|
8
|
+
maxRecursionDepth: 15;
|
|
9
|
+
}> : string;
|
|
10
|
+
declare const LOCALE: {
|
|
11
|
+
readonly uk: "uk";
|
|
12
|
+
readonly en: "en";
|
|
13
|
+
};
|
|
14
|
+
type LocaleType = (typeof LOCALE)[keyof typeof LOCALE];
|
|
15
|
+
//#endregion
|
|
16
|
+
export { I18nKey, LocaleType };
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
uk: 'uk',
|
|
6
|
-
en: 'en',
|
|
1
|
+
//#region src/interfaces/services/i18n.ts
|
|
2
|
+
const LOCALE = {
|
|
3
|
+
uk: "uk",
|
|
4
|
+
en: "en"
|
|
7
5
|
};
|
|
8
|
-
//#
|
|
6
|
+
//#endregion
|
|
7
|
+
export { LOCALE };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { MissedInterpolationParamsTotalLabelsMap, MissedLocaleKeysTotalLabelsMap } from "../interfaces/metrics/index.js";
|
|
2
|
+
import { Counter } from "@diia-inhouse/diia-metrics";
|
|
3
|
+
|
|
4
|
+
//#region src/metrics/index.d.ts
|
|
5
|
+
declare const missedLocaleKeysTotalMetric: Counter<MissedLocaleKeysTotalLabelsMap>;
|
|
6
|
+
declare const missedInterpolationParamsTotalMetric: Counter<MissedInterpolationParamsTotalLabelsMap>;
|
|
7
|
+
//#endregion
|
|
8
|
+
export { missedInterpolationParamsTotalMetric, missedLocaleKeysTotalMetric };
|
package/dist/metrics/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
import { Counter } from "@diia-inhouse/diia-metrics";
|
|
2
|
+
//#region src/metrics/index.ts
|
|
3
|
+
const missedLocaleKeysTotalMetric = new Counter("diia_i18n_missed_locale_keys_total", ["locale", "status"], "Track amount of missed locale keys");
|
|
4
|
+
const missedInterpolationParamsTotalMetric = new Counter("diia_i18n_missed_interpolation_params_total", ["locale"], "Track amount of missed interpolation params");
|
|
5
|
+
//#endregion
|
|
6
|
+
export { missedInterpolationParamsTotalMetric, missedLocaleKeysTotalMetric };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { I18nKey } from "../interfaces/services/i18n.js";
|
|
2
|
+
import { Replacements } from "i18n";
|
|
3
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
4
|
+
import { AlsData } from "@diia-inhouse/types";
|
|
5
|
+
|
|
6
|
+
//#region src/services/i18n.d.ts
|
|
7
|
+
/**
|
|
8
|
+
* @deprecated I18nService is deprecated. Use I18nextService instead.
|
|
9
|
+
*
|
|
10
|
+
* Migration guide:
|
|
11
|
+
* 1. Replace I18nService with I18nextService in your constructor
|
|
12
|
+
* 2. Use the ns() method to create namespaced translation functions
|
|
13
|
+
* 3. Replace get() calls with the namespaced translation function
|
|
14
|
+
*
|
|
15
|
+
* Example:
|
|
16
|
+
* ```typescript
|
|
17
|
+
* // Old way
|
|
18
|
+
* constructor(private readonly i18n: I18nService) {}
|
|
19
|
+
* const text = this.i18n.get('key.path.to.translation')
|
|
20
|
+
*
|
|
21
|
+
* // New way
|
|
22
|
+
* constructor(private readonly i18next: I18nextService) {}
|
|
23
|
+
* private readonly t = this.i18next.ns<LocalesType>('namespace/path')
|
|
24
|
+
* const text = this.t('key.path.to.translation')
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
declare class I18nService<L = string> {
|
|
28
|
+
private readonly asyncLocalStorage;
|
|
29
|
+
private readonly i18n;
|
|
30
|
+
private readonly headerName;
|
|
31
|
+
constructor(asyncLocalStorage: AsyncLocalStorage<AlsData>, localesDirectory?: string);
|
|
32
|
+
/**
|
|
33
|
+
* @deprecated Use I18nextService with namespaced translation functions instead.
|
|
34
|
+
*/
|
|
35
|
+
get(key: I18nKey<L>, valuesToReplace?: Replacements, returnKeyIfNotFound?: boolean): string;
|
|
36
|
+
/**
|
|
37
|
+
* @deprecated Use I18nextService.getLocale() instead.
|
|
38
|
+
*/
|
|
39
|
+
getLocale(): string;
|
|
40
|
+
private getLocaleFromStore;
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { I18nService };
|
package/dist/services/i18n.js
CHANGED
|
@@ -1,75 +1,69 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.I18nService = void 0;
|
|
7
|
-
const he_1 = __importDefault(require("he"));
|
|
8
|
-
const i18n_1 = require("i18n");
|
|
9
|
-
const i18n_2 = require("../interfaces/services/i18n");
|
|
1
|
+
import { LOCALE } from "../interfaces/services/i18n.js";
|
|
2
|
+
import he from "he";
|
|
3
|
+
import { I18n } from "i18n";
|
|
4
|
+
//#region src/services/i18n.ts
|
|
10
5
|
/**
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
//# sourceMappingURL=i18n.js.map
|
|
6
|
+
* @deprecated I18nService is deprecated. Use I18nextService instead.
|
|
7
|
+
*
|
|
8
|
+
* Migration guide:
|
|
9
|
+
* 1. Replace I18nService with I18nextService in your constructor
|
|
10
|
+
* 2. Use the ns() method to create namespaced translation functions
|
|
11
|
+
* 3. Replace get() calls with the namespaced translation function
|
|
12
|
+
*
|
|
13
|
+
* Example:
|
|
14
|
+
* ```typescript
|
|
15
|
+
* // Old way
|
|
16
|
+
* constructor(private readonly i18n: I18nService) {}
|
|
17
|
+
* const text = this.i18n.get('key.path.to.translation')
|
|
18
|
+
*
|
|
19
|
+
* // New way
|
|
20
|
+
* constructor(private readonly i18next: I18nextService) {}
|
|
21
|
+
* private readonly t = this.i18next.ns<LocalesType>('namespace/path')
|
|
22
|
+
* const text = this.t('key.path.to.translation')
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
var I18nService = class {
|
|
26
|
+
asyncLocalStorage;
|
|
27
|
+
i18n;
|
|
28
|
+
headerName = "appLocale";
|
|
29
|
+
constructor(asyncLocalStorage, localesDirectory = "./dist/locales") {
|
|
30
|
+
this.asyncLocalStorage = asyncLocalStorage;
|
|
31
|
+
this.i18n = new I18n();
|
|
32
|
+
this.i18n.configure({
|
|
33
|
+
directory: localesDirectory,
|
|
34
|
+
fallbacks: {
|
|
35
|
+
"en-*": LOCALE.en,
|
|
36
|
+
"uk-*": LOCALE.uk
|
|
37
|
+
},
|
|
38
|
+
autoReload: false,
|
|
39
|
+
updateFiles: false,
|
|
40
|
+
objectNotation: true,
|
|
41
|
+
header: this.headerName,
|
|
42
|
+
defaultLocale: LOCALE.uk
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* @deprecated Use I18nextService with namespaced translation functions instead.
|
|
47
|
+
*/
|
|
48
|
+
get(key, valuesToReplace, returnKeyIfNotFound = true) {
|
|
49
|
+
const locale = this.getLocaleFromStore();
|
|
50
|
+
const foundItem = this.i18n.__({
|
|
51
|
+
locale,
|
|
52
|
+
phrase: key
|
|
53
|
+
}, valuesToReplace || {});
|
|
54
|
+
if (!foundItem && returnKeyIfNotFound) return key;
|
|
55
|
+
return he.decode(foundItem);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* @deprecated Use I18nextService.getLocale() instead.
|
|
59
|
+
*/
|
|
60
|
+
getLocale() {
|
|
61
|
+
const locale = this.getLocaleFromStore();
|
|
62
|
+
return this.i18n.setLocale({}, locale);
|
|
63
|
+
}
|
|
64
|
+
getLocaleFromStore() {
|
|
65
|
+
return this.asyncLocalStorage.getStore()?.headers?.[this.headerName] || "";
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
//#endregion
|
|
69
|
+
export { I18nService };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as i18next from "i18next";
|
|
2
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
3
|
+
import { AlsData, Logger } from "@diia-inhouse/types";
|
|
4
|
+
|
|
5
|
+
//#region src/services/i18next.d.ts
|
|
6
|
+
type DotNestedKeys<T> = T extends object ? { [K in keyof T]: K extends string ? (T[K] extends object ? `${K}.${DotNestedKeys<T[K]>}` | K : K) : never }[keyof T & string] : "";
|
|
7
|
+
type TranslationFunction<TResource> = <K extends DotNestedKeys<TResource>>(key: K, options?: i18next.TOptions) => string;
|
|
8
|
+
declare class I18nextService {
|
|
9
|
+
private readonly localesDirectory;
|
|
10
|
+
private readonly initOptions;
|
|
11
|
+
private readonly asyncLocalStorage;
|
|
12
|
+
private readonly logger;
|
|
13
|
+
private readonly i18nextInstance;
|
|
14
|
+
private readonly headerName;
|
|
15
|
+
constructor(localesDirectory: string | undefined, initOptions: Partial<i18next.InitOptions> | undefined, asyncLocalStorage: AsyncLocalStorage<AlsData>, logger: Logger);
|
|
16
|
+
ns<TResource>(namespace: string): TranslationFunction<TResource>;
|
|
17
|
+
get(key: string, options?: object): string;
|
|
18
|
+
getLocale(): string;
|
|
19
|
+
getInstance(): i18next.i18n;
|
|
20
|
+
private getLocaleFromStore;
|
|
21
|
+
private initializeI18next;
|
|
22
|
+
private findAllNamespaces;
|
|
23
|
+
private findJsonFiles;
|
|
24
|
+
}
|
|
25
|
+
//#endregion
|
|
26
|
+
export { I18nextService, TranslationFunction };
|
package/dist/services/i18next.js
CHANGED
|
@@ -1,168 +1,117 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
1
|
+
import { LOCALE } from "../interfaces/services/i18n.js";
|
|
2
|
+
import { missedInterpolationParamsTotalMetric, missedLocaleKeysTotalMetric } from "../metrics/index.js";
|
|
3
|
+
import { lstatSync, readdirSync } from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import * as i18next from "i18next";
|
|
6
|
+
import FsBackend from "i18next-fs-backend";
|
|
7
|
+
//#region src/services/i18next.ts
|
|
8
|
+
var I18nextService = class {
|
|
9
|
+
localesDirectory;
|
|
10
|
+
initOptions;
|
|
11
|
+
asyncLocalStorage;
|
|
12
|
+
logger;
|
|
13
|
+
i18nextInstance;
|
|
14
|
+
headerName = "appLocale";
|
|
15
|
+
constructor(localesDirectory = "./dist/locales", initOptions = {}, asyncLocalStorage, logger) {
|
|
16
|
+
this.localesDirectory = localesDirectory;
|
|
17
|
+
this.initOptions = initOptions;
|
|
18
|
+
this.asyncLocalStorage = asyncLocalStorage;
|
|
19
|
+
this.logger = logger;
|
|
20
|
+
this.i18nextInstance = this.initializeI18next();
|
|
21
|
+
}
|
|
22
|
+
ns(namespace) {
|
|
23
|
+
return (key, options = {}) => {
|
|
24
|
+
const locale = this.getLocaleFromStore();
|
|
25
|
+
return this.i18nextInstance.t(key, {
|
|
26
|
+
lng: locale,
|
|
27
|
+
ns: namespace,
|
|
28
|
+
...options
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
get(key, options = {}) {
|
|
33
|
+
const locale = this.getLocaleFromStore();
|
|
34
|
+
return this.i18nextInstance.t(key, {
|
|
35
|
+
lng: locale,
|
|
36
|
+
...options
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
getLocale() {
|
|
40
|
+
return this.getLocaleFromStore();
|
|
41
|
+
}
|
|
42
|
+
getInstance() {
|
|
43
|
+
return this.i18nextInstance;
|
|
44
|
+
}
|
|
45
|
+
getLocaleFromStore() {
|
|
46
|
+
return this.asyncLocalStorage.getStore()?.headers?.[this.headerName] || LOCALE.uk;
|
|
47
|
+
}
|
|
48
|
+
initializeI18next() {
|
|
49
|
+
const namespaces = this.findAllNamespaces();
|
|
50
|
+
this.logger.info(`Found namespaces: ${namespaces.join(", ")}`);
|
|
51
|
+
const mergedOptions = {
|
|
52
|
+
fallbackLng: LOCALE.uk,
|
|
53
|
+
lng: LOCALE.uk,
|
|
54
|
+
returnEmptyString: false,
|
|
55
|
+
returnNull: false,
|
|
56
|
+
returnObjects: true,
|
|
57
|
+
initImmediate: false,
|
|
58
|
+
initAsync: false,
|
|
59
|
+
saveMissing: true,
|
|
60
|
+
interpolation: { escapeValue: false },
|
|
61
|
+
backend: { loadPath: path.join(this.localesDirectory, "{{lng}}/{{ns}}.json") },
|
|
62
|
+
ns: namespaces.length > 0 ? namespaces : ["translation"],
|
|
63
|
+
defaultNS: namespaces.length > 0 ? namespaces[0] : "translation",
|
|
64
|
+
missingKeyHandler: (_lngs, ns, key, fallbackValue) => {
|
|
65
|
+
const requestedLocale = this.getLocaleFromStore();
|
|
66
|
+
if (fallbackValue && fallbackValue !== key) {
|
|
67
|
+
missedLocaleKeysTotalMetric.increment({
|
|
68
|
+
locale: requestedLocale,
|
|
69
|
+
status: "fallback_used"
|
|
70
|
+
});
|
|
71
|
+
this.logger.warn(`Using fallback for key: ${key} in locale: ${requestedLocale}, namespace: ${ns}`);
|
|
72
|
+
} else {
|
|
73
|
+
missedLocaleKeysTotalMetric.increment({
|
|
74
|
+
locale: requestedLocale,
|
|
75
|
+
status: "missing"
|
|
76
|
+
});
|
|
77
|
+
this.logger.error(`Missing translation key: ${key} for locale: ${requestedLocale}, namespace: ${ns}`);
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
missingInterpolationHandler: (text, value) => {
|
|
81
|
+
const requestedLocale = this.getLocaleFromStore();
|
|
82
|
+
missedInterpolationParamsTotalMetric.increment({ locale: requestedLocale });
|
|
83
|
+
this.logger.error(`Missing interpolation parameter: ${value[1]} in text: ${text} for locale: ${requestedLocale}`);
|
|
84
|
+
},
|
|
85
|
+
...this.initOptions
|
|
86
|
+
};
|
|
87
|
+
const instance = i18next.createInstance();
|
|
88
|
+
instance.use(FsBackend).init(mergedOptions);
|
|
89
|
+
return instance;
|
|
90
|
+
}
|
|
91
|
+
findAllNamespaces() {
|
|
92
|
+
const namespaces = [];
|
|
93
|
+
try {
|
|
94
|
+
const langDirs = readdirSync(this.localesDirectory).filter((dir) => lstatSync(path.join(this.localesDirectory, dir)).isDirectory());
|
|
95
|
+
for (const lang of langDirs) {
|
|
96
|
+
const langDir = path.join(this.localesDirectory, lang);
|
|
97
|
+
this.findJsonFiles(langDir, namespaces);
|
|
98
|
+
}
|
|
99
|
+
} catch (err) {
|
|
100
|
+
this.logger.error(`Error finding namespaces: ${String(err)}`);
|
|
101
|
+
}
|
|
102
|
+
return namespaces;
|
|
103
|
+
}
|
|
104
|
+
findJsonFiles(dir, namespaces, prefix = "") {
|
|
105
|
+
const entries = readdirSync(dir);
|
|
106
|
+
for (const entry of entries) {
|
|
107
|
+
const fullPath = path.join(dir, entry);
|
|
108
|
+
if (lstatSync(fullPath).isDirectory()) this.findJsonFiles(fullPath, namespaces, `${prefix}${entry}/`);
|
|
109
|
+
else if (entry.endsWith(".json")) {
|
|
110
|
+
const ns = `${prefix}${entry.replace(".json", "")}`;
|
|
111
|
+
if (!namespaces.includes(ns)) namespaces.push(ns);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
37
115
|
};
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
const node_fs_1 = require("node:fs");
|
|
41
|
-
const node_path_1 = __importDefault(require("node:path"));
|
|
42
|
-
const i18next = __importStar(require("i18next"));
|
|
43
|
-
const i18next_fs_backend_1 = __importDefault(require("i18next-fs-backend"));
|
|
44
|
-
const i18n_1 = require("../interfaces/services/i18n");
|
|
45
|
-
const metrics_1 = require("../metrics");
|
|
46
|
-
class I18nextService {
|
|
47
|
-
localesDirectory;
|
|
48
|
-
initOptions;
|
|
49
|
-
asyncLocalStorage;
|
|
50
|
-
logger;
|
|
51
|
-
i18nextInstance;
|
|
52
|
-
headerName = 'appLocale';
|
|
53
|
-
constructor(localesDirectory = './dist/locales', initOptions = {}, asyncLocalStorage, logger) {
|
|
54
|
-
this.localesDirectory = localesDirectory;
|
|
55
|
-
this.initOptions = initOptions;
|
|
56
|
-
this.asyncLocalStorage = asyncLocalStorage;
|
|
57
|
-
this.logger = logger;
|
|
58
|
-
this.i18nextInstance = this.initializeI18next();
|
|
59
|
-
}
|
|
60
|
-
ns(namespace) {
|
|
61
|
-
return (key, options = {}) => {
|
|
62
|
-
const locale = this.getLocaleFromStore();
|
|
63
|
-
return this.i18nextInstance.t(key, {
|
|
64
|
-
lng: locale,
|
|
65
|
-
ns: namespace,
|
|
66
|
-
...options,
|
|
67
|
-
});
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
get(key, options = {}) {
|
|
71
|
-
const locale = this.getLocaleFromStore();
|
|
72
|
-
return this.i18nextInstance.t(key, {
|
|
73
|
-
lng: locale,
|
|
74
|
-
...options,
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
getLocale() {
|
|
78
|
-
return this.getLocaleFromStore();
|
|
79
|
-
}
|
|
80
|
-
getInstance() {
|
|
81
|
-
return this.i18nextInstance;
|
|
82
|
-
}
|
|
83
|
-
getLocaleFromStore() {
|
|
84
|
-
const store = this.asyncLocalStorage.getStore();
|
|
85
|
-
return store?.headers?.[this.headerName] || i18n_1.LOCALE.uk;
|
|
86
|
-
}
|
|
87
|
-
initializeI18next() {
|
|
88
|
-
const namespaces = this.findAllNamespaces();
|
|
89
|
-
this.logger.info(`Found namespaces: ${namespaces.join(', ')}`);
|
|
90
|
-
const defaultOptions = {
|
|
91
|
-
fallbackLng: i18n_1.LOCALE.uk,
|
|
92
|
-
lng: i18n_1.LOCALE.uk,
|
|
93
|
-
returnEmptyString: false,
|
|
94
|
-
returnNull: false,
|
|
95
|
-
returnObjects: true,
|
|
96
|
-
initImmediate: false,
|
|
97
|
-
initAsync: false,
|
|
98
|
-
saveMissing: true,
|
|
99
|
-
interpolation: {
|
|
100
|
-
escapeValue: false,
|
|
101
|
-
},
|
|
102
|
-
backend: {
|
|
103
|
-
loadPath: node_path_1.default.join(this.localesDirectory, '{{lng}}/{{ns}}.json'),
|
|
104
|
-
},
|
|
105
|
-
ns: namespaces.length > 0 ? namespaces : ['translation'],
|
|
106
|
-
defaultNS: namespaces.length > 0 ? namespaces[0] : 'translation',
|
|
107
|
-
missingKeyHandler: (_lngs, ns, key, fallbackValue) => {
|
|
108
|
-
const requestedLocale = this.getLocaleFromStore();
|
|
109
|
-
const isFallbackUsed = fallbackValue && fallbackValue !== key;
|
|
110
|
-
if (isFallbackUsed) {
|
|
111
|
-
metrics_1.missedLocaleKeysTotalMetric.increment({ locale: requestedLocale, status: 'fallback_used' });
|
|
112
|
-
this.logger.warn(`Using fallback for key: ${key} in locale: ${requestedLocale}, namespace: ${ns}`);
|
|
113
|
-
}
|
|
114
|
-
else {
|
|
115
|
-
metrics_1.missedLocaleKeysTotalMetric.increment({ locale: requestedLocale, status: 'missing' });
|
|
116
|
-
this.logger.error(`Missing translation key: ${key} for locale: ${requestedLocale}, namespace: ${ns}`);
|
|
117
|
-
}
|
|
118
|
-
},
|
|
119
|
-
missingInterpolationHandler: (text, value) => {
|
|
120
|
-
const requestedLocale = this.getLocaleFromStore();
|
|
121
|
-
metrics_1.missedInterpolationParamsTotalMetric.increment({ locale: requestedLocale });
|
|
122
|
-
this.logger.error(`Missing interpolation parameter: ${value[1]} in text: ${text} for locale: ${requestedLocale}`);
|
|
123
|
-
},
|
|
124
|
-
};
|
|
125
|
-
const mergedOptions = { ...defaultOptions, ...this.initOptions };
|
|
126
|
-
const instance = i18next.createInstance();
|
|
127
|
-
void instance.use(i18next_fs_backend_1.default).init(mergedOptions);
|
|
128
|
-
return instance;
|
|
129
|
-
}
|
|
130
|
-
findAllNamespaces() {
|
|
131
|
-
const namespaces = [];
|
|
132
|
-
try {
|
|
133
|
-
// eslint-disable-next-line security/detect-non-literal-fs-filename
|
|
134
|
-
const dirs = (0, node_fs_1.readdirSync)(this.localesDirectory); // nosemgrep: eslint.detect-non-literal-fs-filename
|
|
135
|
-
const langDirs = dirs.filter((dir) =>
|
|
136
|
-
// eslint-disable-next-line security/detect-non-literal-fs-filename
|
|
137
|
-
(0, node_fs_1.lstatSync)(node_path_1.default.join(this.localesDirectory, dir)).isDirectory());
|
|
138
|
-
for (const lang of langDirs) {
|
|
139
|
-
const langDir = node_path_1.default.join(this.localesDirectory, lang);
|
|
140
|
-
this.findJsonFiles(langDir, namespaces);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
catch (err) {
|
|
144
|
-
this.logger.error(`Error finding namespaces: ${err}`);
|
|
145
|
-
}
|
|
146
|
-
return namespaces;
|
|
147
|
-
}
|
|
148
|
-
findJsonFiles(dir, namespaces, prefix = '') {
|
|
149
|
-
// eslint-disable-next-line security/detect-non-literal-fs-filename
|
|
150
|
-
const entries = (0, node_fs_1.readdirSync)(dir); // nosemgrep: eslint.detect-non-literal-fs-filename
|
|
151
|
-
for (const entry of entries) {
|
|
152
|
-
const fullPath = node_path_1.default.join(dir, entry);
|
|
153
|
-
// eslint-disable-next-line security/detect-non-literal-fs-filename
|
|
154
|
-
const isDir = (0, node_fs_1.lstatSync)(fullPath).isDirectory(); // nosemgrep: eslint.detect-non-literal-fs-filename
|
|
155
|
-
if (isDir) {
|
|
156
|
-
this.findJsonFiles(fullPath, namespaces, `${prefix}${entry}/`);
|
|
157
|
-
}
|
|
158
|
-
else if (entry.endsWith('.json')) {
|
|
159
|
-
const ns = `${prefix}${entry.replace('.json', '')}`;
|
|
160
|
-
if (!namespaces.includes(ns)) {
|
|
161
|
-
namespaces.push(ns);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
exports.I18nextService = I18nextService;
|
|
168
|
-
//# sourceMappingURL=i18next.js.map
|
|
116
|
+
//#endregion
|
|
117
|
+
export { I18nextService };
|
package/dist/services/index.js
CHANGED
|
@@ -1,19 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
-
};
|
|
16
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./i18n"), exports);
|
|
18
|
-
__exportStar(require("./i18next"), exports);
|
|
19
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
import "./i18n.js";
|
|
2
|
+
import "./i18next.js";
|
|
3
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,24 +1,32 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@diia-inhouse/i18n",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.1.0",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"description": "Internationalization package",
|
|
5
6
|
"repository": "https://github.com/diia-open-source/be-pkg-i18n",
|
|
6
7
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
7
8
|
"author": "Diia",
|
|
8
9
|
"main": "dist/index.js",
|
|
9
|
-
"types": "dist/
|
|
10
|
+
"types": "dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"default": "./dist/index.js"
|
|
15
|
+
},
|
|
16
|
+
"./package.json": "./package.json"
|
|
17
|
+
},
|
|
10
18
|
"files": [
|
|
11
19
|
"dist"
|
|
12
20
|
],
|
|
13
21
|
"engines": {
|
|
14
|
-
"node": ">=
|
|
22
|
+
"node": ">=24"
|
|
15
23
|
},
|
|
16
24
|
"scripts": {
|
|
17
25
|
"prebuild": "rimraf dist",
|
|
18
|
-
"build": "
|
|
26
|
+
"build": "tsdown",
|
|
19
27
|
"find-circulars": "madge --circular ./",
|
|
20
|
-
"lint": "
|
|
21
|
-
"lint-fix": "
|
|
28
|
+
"lint": "oxlint && oxfmt --check .",
|
|
29
|
+
"lint-fix": "oxlint --fix && oxfmt .",
|
|
22
30
|
"lint:lockfile": "lockfile-lint --path package-lock.json --allowed-hosts registry.npmjs.org --validate-https",
|
|
23
31
|
"prepare": "npm run build",
|
|
24
32
|
"semantic-release": "semantic-release",
|
|
@@ -28,23 +36,6 @@
|
|
|
28
36
|
"commitlint": {
|
|
29
37
|
"extends": "@diia-inhouse/configs/dist/commitlint"
|
|
30
38
|
},
|
|
31
|
-
"prettier": "@diia-inhouse/eslint-config/prettier",
|
|
32
|
-
"eslintConfig": {
|
|
33
|
-
"extends": "@diia-inhouse/eslint-config",
|
|
34
|
-
"overrides": [
|
|
35
|
-
{
|
|
36
|
-
"files": [
|
|
37
|
-
"*.ts"
|
|
38
|
-
],
|
|
39
|
-
"parserOptions": {
|
|
40
|
-
"project": [
|
|
41
|
-
"./tsconfig.json",
|
|
42
|
-
"./tests/tsconfig.json"
|
|
43
|
-
]
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
]
|
|
47
|
-
},
|
|
48
39
|
"release": {
|
|
49
40
|
"branches": [
|
|
50
41
|
"main"
|
|
@@ -52,36 +43,41 @@
|
|
|
52
43
|
"extends": "@diia-inhouse/configs/dist/semantic-release/package"
|
|
53
44
|
},
|
|
54
45
|
"dependencies": {
|
|
55
|
-
"@diia-inhouse/diia-logger": "
|
|
56
|
-
"@diia-inhouse/diia-metrics": "
|
|
46
|
+
"@diia-inhouse/diia-logger": "4.2.4",
|
|
47
|
+
"@diia-inhouse/diia-metrics": "7.1.5",
|
|
57
48
|
"@types/i18n": "0.13.12",
|
|
58
|
-
"glob": "
|
|
49
|
+
"glob": "13.0.6",
|
|
59
50
|
"he": "1.2.0",
|
|
60
51
|
"i18n": "0.15.3",
|
|
61
52
|
"i18next": "25.8.13",
|
|
62
|
-
"i18next-fs-backend": "2.6.
|
|
63
|
-
"type-fest": "
|
|
53
|
+
"i18next-fs-backend": "2.6.5",
|
|
54
|
+
"type-fest": "5.6.0"
|
|
64
55
|
},
|
|
65
56
|
"devDependencies": {
|
|
66
57
|
"@commitlint/cli": "20.4.2",
|
|
67
|
-
"@diia-inhouse/configs": "
|
|
68
|
-
"@diia-inhouse/eslint-config": "8.8.
|
|
69
|
-
"@diia-inhouse/
|
|
70
|
-
"@diia-inhouse/
|
|
58
|
+
"@diia-inhouse/configs": "7.0.0",
|
|
59
|
+
"@diia-inhouse/eslint-config": "8.8.3",
|
|
60
|
+
"@diia-inhouse/oxc-config": "1.10.0",
|
|
61
|
+
"@diia-inhouse/test": "8.2.1",
|
|
62
|
+
"@diia-inhouse/types": "13.2.0",
|
|
71
63
|
"@types/he": "1.2.3",
|
|
72
|
-
"@types/node": "25.
|
|
73
|
-
"@vitest/coverage-v8": "4.
|
|
74
|
-
"@vitest/ui": "4.
|
|
75
|
-
"lockfile-lint": "
|
|
64
|
+
"@types/node": "25.6.2",
|
|
65
|
+
"@vitest/coverage-v8": "4.1.5",
|
|
66
|
+
"@vitest/ui": "4.1.5",
|
|
67
|
+
"lockfile-lint": "5.0.0",
|
|
76
68
|
"madge": "8.0.0",
|
|
69
|
+
"oxfmt": "0.48.0",
|
|
70
|
+
"oxlint": "1.63.0",
|
|
71
|
+
"oxlint-tsgolint": "0.22.1",
|
|
77
72
|
"rimraf": "6.1.3",
|
|
78
|
-
"semantic-release": "
|
|
73
|
+
"semantic-release": "25.0.3",
|
|
74
|
+
"tsdown": "0.22.0",
|
|
79
75
|
"vite-tsconfig-paths": "6.1.1",
|
|
80
|
-
"vitest": "4.
|
|
81
|
-
"vitest-mock-extended": "
|
|
76
|
+
"vitest": "4.1.5",
|
|
77
|
+
"vitest-mock-extended": "4.0.0"
|
|
82
78
|
},
|
|
83
79
|
"peerDependencies": {
|
|
84
|
-
"@diia-inhouse/types": ">=1.0
|
|
80
|
+
"@diia-inhouse/types": ">=13.1.0"
|
|
85
81
|
},
|
|
86
82
|
"madge": {
|
|
87
83
|
"tsConfig": "./tsconfig.json"
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,6CAA0B;AAE1B,4CAAyB"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/interfaces/metrics/index.ts"],"names":[],"mappings":""}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../../src/interfaces/services/i18n.ts"],"names":[],"mappings":";;;AAOa,QAAA,MAAM,GAAG;IAClB,EAAE,EAAE,IAAI;IACR,EAAE,EAAE,IAAI;CACX,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/metrics/index.ts"],"names":[],"mappings":";;;AAEA,6DAAoD;AAEvC,QAAA,2BAA2B,GAAG,IAAI,sBAAO,CAClD,oCAAoC,EACpC,CAAC,QAAQ,EAAE,QAAQ,CAAC,EACpB,oCAAoC,CACvC,CAAA;AAEY,QAAA,oCAAoC,GAAG,IAAI,sBAAO,CAC3D,6CAA6C,EAC7C,CAAC,QAAQ,CAAC,EACV,6CAA6C,CAChD,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../src/services/i18n.ts"],"names":[],"mappings":";;;;;;AAEA,4CAAmB;AACnB,+BAAyC;AAIzC,sDAA6D;AAE7D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAa,WAAW;IAMC;IALJ,IAAI,CAAM;IAEV,UAAU,GAAG,WAAW,CAAA;IAEzC,YACqB,iBAA6C,EAC9D,gBAAgB,GAAG,gBAAgB;QADlB,sBAAiB,GAAjB,iBAAiB,CAA4B;QAG9D,IAAI,CAAC,IAAI,GAAG,IAAI,WAAI,EAAE,CAAA;QAEtB,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;YAChB,SAAS,EAAE,gBAAgB;YAC3B,SAAS,EAAE;gBACP,MAAM,EAAE,aAAM,CAAC,EAAE;gBACjB,MAAM,EAAE,aAAM,CAAC,EAAE;aACpB;YACD,UAAU,EAAE,KAAK;YACjB,WAAW,EAAE,KAAK;YAClB,cAAc,EAAE,IAAI;YACpB,MAAM,EAAE,IAAI,CAAC,UAAU;YACvB,aAAa,EAAE,aAAM,CAAC,EAAE;SAC3B,CAAC,CAAA;IACN,CAAC;IAED;;OAEG;IACH,GAAG,CAAC,GAAe,EAAE,eAA8B,EAAE,mBAAmB,GAAG,IAAI;QAC3E,MAAM,MAAM,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAA;QAExC,gDAAgD;QAChD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,GAAa,EAAE,EAAE,eAAe,IAAI,EAAE,CAAC,CAAA;QAExF,IAAI,CAAC,SAAS,IAAI,mBAAmB,EAAE,CAAC;YACpC,OAAO,GAAa,CAAA;QACxB,CAAC;QAED,OAAO,YAAE,CAAC,MAAM,CAAC,SAAS,CAAC,CAAA;IAC/B,CAAC;IAED;;OAEG;IACH,SAAS;QACL,MAAM,MAAM,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAA;QAExC,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,MAAM,CAAsB,CAAA;IAC/D,CAAC;IAEO,kBAAkB;QACtB,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAA;QAE/C,OAAO,KAAK,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAA;IAClD,CAAC;CACJ;AAvDD,kCAuDC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"i18next.js","sourceRoot":"","sources":["../../src/services/i18next.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,qCAAgD;AAChD,0DAA4B;AAE5B,iDAAkC;AAClC,4EAAgE;AAIhE,sDAAoD;AACpD,wCAA8F;AAQ9F,MAAa,cAAc;IAKF;IACA;IACA;IACA;IAPJ,eAAe,CAAc;IAC7B,UAAU,GAAG,WAAW,CAAA;IAEzC,YACqB,mBAAmB,gBAAgB,EACnC,cAA4C,EAAE,EAC9C,iBAA6C,EAC7C,MAAc;QAHd,qBAAgB,GAAhB,gBAAgB,CAAmB;QACnC,gBAAW,GAAX,WAAW,CAAmC;QAC9C,sBAAiB,GAAjB,iBAAiB,CAA4B;QAC7C,WAAM,GAAN,MAAM,CAAQ;QAE/B,IAAI,CAAC,eAAe,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAA;IACnD,CAAC;IAED,EAAE,CAAY,SAAiB;QAC3B,OAAO,CAAC,GAA6B,EAAE,UAA4B,EAAE,EAAU,EAAE;YAC7E,MAAM,MAAM,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAA;YAExC,OAAO,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,GAAG,EAAE;gBAC/B,GAAG,EAAE,MAAM;gBACX,EAAE,EAAE,SAAS;gBACb,GAAG,OAAO;aACb,CAAC,CAAA;QACN,CAAC,CAAA;IACL,CAAC;IAED,GAAG,CAAC,GAAW,EAAE,UAAkB,EAAE;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAA;QAExC,OAAO,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,GAAG,EAAE;YAC/B,GAAG,EAAE,MAAM;YACX,GAAG,OAAO;SACb,CAAC,CAAA;IACN,CAAC;IAED,SAAS;QACL,OAAO,IAAI,CAAC,kBAAkB,EAAE,CAAA;IACpC,CAAC;IAED,WAAW;QACP,OAAO,IAAI,CAAC,eAAe,CAAA;IAC/B,CAAC;IAEO,kBAAkB;QACtB,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAA;QAE/C,OAAO,KAAK,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,aAAM,CAAC,EAAE,CAAA;IACzD,CAAC;IAEO,iBAAiB;QACrB,MAAM,UAAU,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAA;QAE3C,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,qBAAqB,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAE9D,MAAM,cAAc,GAAiC;YACjD,WAAW,EAAE,aAAM,CAAC,EAAE;YACtB,GAAG,EAAE,aAAM,CAAC,EAAE;YACd,iBAAiB,EAAE,KAAK;YACxB,UAAU,EAAE,KAAK;YACjB,aAAa,EAAE,IAAI;YACnB,aAAa,EAAE,KAAK;YACpB,SAAS,EAAE,KAAK;YAChB,WAAW,EAAE,IAAI;YACjB,aAAa,EAAE;gBACX,WAAW,EAAE,KAAK;aACrB;YACD,OAAO,EAAE;gBACL,QAAQ,EAAE,mBAAI,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,qBAAqB,CAAC;aACpE;YACD,EAAE,EAAE,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;YACxD,SAAS,EAAE,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa;YAChE,iBAAiB,EAAE,CAAC,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,aAAa,EAAE,EAAE;gBACjD,MAAM,eAAe,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAA;gBACjD,MAAM,cAAc,GAAG,aAAa,IAAI,aAAa,KAAK,GAAG,CAAA;gBAE7D,IAAI,cAAc,EAAE,CAAC;oBACjB,qCAA2B,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC,CAAA;oBAC3F,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,2BAA2B,GAAG,eAAe,eAAe,gBAAgB,EAAE,EAAE,CAAC,CAAA;gBACtG,CAAC;qBAAM,CAAC;oBACJ,qCAA2B,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CAAA;oBACrF,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,4BAA4B,GAAG,gBAAgB,eAAe,gBAAgB,EAAE,EAAE,CAAC,CAAA;gBACzG,CAAC;YACL,CAAC;YACD,2BAA2B,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;gBACzC,MAAM,eAAe,GAAG,IAAI,CAAC,kBAAkB,EAAE,CAAA;gBAEjD,8CAAoC,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC,CAAA;gBAC3E,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,oCAAoC,KAAK,CAAC,CAAC,CAAC,aAAa,IAAI,gBAAgB,eAAe,EAAE,CAAC,CAAA;YACrH,CAAC;SACJ,CAAA;QAED,MAAM,aAAa,GAAG,EAAE,GAAG,cAAc,EAAE,GAAG,IAAI,CAAC,WAAW,EAAE,CAAA;QAEhE,MAAM,QAAQ,GAAG,OAAO,CAAC,cAAc,EAAE,CAAA;QAEzC,KAAK,QAAQ,CAAC,GAAG,CAAC,4BAAS,CAAC,CAAC,IAAI,CAAC,aAAuD,CAAC,CAAA;QAE1F,OAAO,QAAQ,CAAA;IACnB,CAAC;IAEO,iBAAiB;QACrB,MAAM,UAAU,GAAa,EAAE,CAAA;QAE/B,IAAI,CAAC;YACD,mEAAmE;YACnE,MAAM,IAAI,GAAG,IAAA,qBAAW,EAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA,CAAC,mDAAmD;YACnG,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CACxB,CAAC,GAAG,EAAE,EAAE;YACJ,mEAAmE;YACnE,IAAA,mBAAS,EAAC,mBAAI,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CACrE,CAAA;YAED,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;gBAC1B,MAAM,OAAO,GAAG,mBAAI,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAA;gBAEtD,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;YAC3C,CAAC;QACL,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,6BAA6B,GAAG,EAAE,CAAC,CAAA;QACzD,CAAC;QAED,OAAO,UAAU,CAAA;IACrB,CAAC;IAEO,aAAa,CAAC,GAAW,EAAE,UAAoB,EAAE,MAAM,GAAG,EAAE;QAChE,mEAAmE;QACnE,MAAM,OAAO,GAAG,IAAA,qBAAW,EAAC,GAAG,CAAC,CAAA,CAAC,mDAAmD;QAEpF,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC1B,MAAM,QAAQ,GAAG,mBAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAA;YACtC,mEAAmE;YACnE,MAAM,KAAK,GAAG,IAAA,mBAAS,EAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAA,CAAC,mDAAmD;YAEnG,IAAI,KAAK,EAAE,CAAC;gBACR,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,UAAU,EAAE,GAAG,MAAM,GAAG,KAAK,GAAG,CAAC,CAAA;YAClE,CAAC;iBAAM,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBACjC,MAAM,EAAE,GAAG,GAAG,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAA;gBAEnD,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;oBAC3B,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;gBACvB,CAAC;YACL,CAAC;QACL,CAAC;IACL,CAAC;CACJ;AA/ID,wCA+IC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,yCAAsB;AAEtB,4CAAyB"}
|
package/dist/types/index.d.ts
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { Paths } from 'type-fest';
|
|
2
|
-
/**
|
|
3
|
-
* @deprecated I18nKey is deprecated along with I18nService. Use I18nextService with TranslationFunction<T> instead.
|
|
4
|
-
*/
|
|
5
|
-
export type I18nKey<L> = L extends object ? Paths<L, {
|
|
6
|
-
maxRecursionDepth: 15;
|
|
7
|
-
}> : string;
|
|
8
|
-
export declare const LOCALE: {
|
|
9
|
-
uk: string;
|
|
10
|
-
en: string;
|
|
11
|
-
};
|
|
12
|
-
export type LocaleType = (typeof LOCALE)[keyof typeof LOCALE];
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import { MissedInterpolationParamsTotalLabelsMap, MissedLocaleKeysTotalLabelsMap } from 'src/interfaces/metrics';
|
|
2
|
-
import { Counter } from '@diia-inhouse/diia-metrics';
|
|
3
|
-
export declare const missedLocaleKeysTotalMetric: Counter<MissedLocaleKeysTotalLabelsMap>;
|
|
4
|
-
export declare const missedInterpolationParamsTotalMetric: Counter<MissedInterpolationParamsTotalLabelsMap>;
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
|
-
import { Replacements } from 'i18n';
|
|
3
|
-
import { AlsData } from '@diia-inhouse/types';
|
|
4
|
-
import { I18nKey } from '../interfaces/services/i18n';
|
|
5
|
-
/**
|
|
6
|
-
* @deprecated I18nService is deprecated. Use I18nextService instead.
|
|
7
|
-
*
|
|
8
|
-
* Migration guide:
|
|
9
|
-
* 1. Replace I18nService with I18nextService in your constructor
|
|
10
|
-
* 2. Use the ns() method to create namespaced translation functions
|
|
11
|
-
* 3. Replace get() calls with the namespaced translation function
|
|
12
|
-
*
|
|
13
|
-
* Example:
|
|
14
|
-
* ```typescript
|
|
15
|
-
* // Old way
|
|
16
|
-
* constructor(private readonly i18n: I18nService) {}
|
|
17
|
-
* const text = this.i18n.get('key.path.to.translation')
|
|
18
|
-
*
|
|
19
|
-
* // New way
|
|
20
|
-
* constructor(private readonly i18next: I18nextService) {}
|
|
21
|
-
* private readonly t = this.i18next.ns<LocalesType>('namespace/path')
|
|
22
|
-
* const text = this.t('key.path.to.translation')
|
|
23
|
-
* ```
|
|
24
|
-
*/
|
|
25
|
-
export declare class I18nService<L = string> {
|
|
26
|
-
private readonly asyncLocalStorage;
|
|
27
|
-
private readonly i18n;
|
|
28
|
-
private readonly headerName;
|
|
29
|
-
constructor(asyncLocalStorage: AsyncLocalStorage<AlsData>, localesDirectory?: string);
|
|
30
|
-
/**
|
|
31
|
-
* @deprecated Use I18nextService with namespaced translation functions instead.
|
|
32
|
-
*/
|
|
33
|
-
get(key: I18nKey<L>, valuesToReplace?: Replacements, returnKeyIfNotFound?: boolean): string;
|
|
34
|
-
/**
|
|
35
|
-
* @deprecated Use I18nextService.getLocale() instead.
|
|
36
|
-
*/
|
|
37
|
-
getLocale(): string;
|
|
38
|
-
private getLocaleFromStore;
|
|
39
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
|
-
import * as i18next from 'i18next';
|
|
3
|
-
import { AlsData, Logger } from '@diia-inhouse/types';
|
|
4
|
-
type DotNestedKeys<T> = T extends object ? {
|
|
5
|
-
[K in keyof T]: K extends string ? (T[K] extends object ? `${K}.${DotNestedKeys<T[K]>}` | K : K) : never;
|
|
6
|
-
}[keyof T & string] : '';
|
|
7
|
-
export type TranslationFunction<TResource> = <K extends DotNestedKeys<TResource>>(key: K, options?: i18next.TOptions) => string;
|
|
8
|
-
export declare class I18nextService {
|
|
9
|
-
private readonly localesDirectory;
|
|
10
|
-
private readonly initOptions;
|
|
11
|
-
private readonly asyncLocalStorage;
|
|
12
|
-
private readonly logger;
|
|
13
|
-
private readonly i18nextInstance;
|
|
14
|
-
private readonly headerName;
|
|
15
|
-
constructor(localesDirectory: string | undefined, initOptions: Partial<i18next.InitOptions> | undefined, asyncLocalStorage: AsyncLocalStorage<AlsData>, logger: Logger);
|
|
16
|
-
ns<TResource>(namespace: string): TranslationFunction<TResource>;
|
|
17
|
-
get(key: string, options?: object): string;
|
|
18
|
-
getLocale(): string;
|
|
19
|
-
getInstance(): i18next.i18n;
|
|
20
|
-
private getLocaleFromStore;
|
|
21
|
-
private initializeI18next;
|
|
22
|
-
private findAllNamespaces;
|
|
23
|
-
private findJsonFiles;
|
|
24
|
-
}
|
|
25
|
-
export {};
|