@aidc-toolkit/core 0.9.7-beta → 0.9.8-beta
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/README.md +60 -8
- package/dist/index.cjs +40 -55
- package/dist/index.d.cts +25 -29
- package/dist/index.d.ts +25 -29
- package/dist/index.js +39 -52
- package/package.json +3 -3
- package/src/index.ts +0 -1
- package/src/locale/i18n.ts +86 -114
- /package/resource/{toolkit_icon.png → toolkit-icon.png} +0 -0
package/README.md
CHANGED
|
@@ -5,29 +5,81 @@ any of the functionality of the AIDC Toolkit. It is a required dependency for al
|
|
|
5
5
|
|
|
6
6
|
All AIDC Toolkit packages require localization. The localization functionality in this package simplifies initialization
|
|
7
7
|
and allows packages to share a common internationalization engine, whose initialization is the responsibility of the
|
|
8
|
-
client application.
|
|
8
|
+
client application. Each package requires its own internationalization object and each is responsible for initializing
|
|
9
|
+
those of its dependencies.
|
|
10
|
+
|
|
11
|
+
Packages install their resources as follows in `i18n.ts` or similar:
|
|
9
12
|
|
|
10
13
|
```typescript
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
14
|
+
import { i18nAssertValidResources, i18nCoreInit, type I18NEnvironment } from "@aidc-toolkit/core";
|
|
15
|
+
import { i18nDependency1Init, dependency1Resources } from "@aidc-toolkit/dependency1";
|
|
16
|
+
import { i18nDependency2Init, dependency2Resources } from "@aidc-toolkit/dependency2";
|
|
17
|
+
import i18next from "i18next";
|
|
18
|
+
import { localeStrings as enLocaleStrings } from "./en/locale-strings.js";
|
|
19
|
+
import { localeStrings as frLocaleStrings } from "./fr/locale-strings.js";
|
|
13
20
|
|
|
14
21
|
export const packageNS = "aidct_package";
|
|
15
22
|
|
|
16
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Locale strings type is extracted from the English locale strings object.
|
|
25
|
+
*/
|
|
26
|
+
export type PackageLocaleStrings = typeof enLocaleStrings;
|
|
27
|
+
|
|
28
|
+
i18nAssertValidResources(enLocaleStrings, "fr", frLocaleStrings);
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Package resources.
|
|
32
|
+
*/
|
|
33
|
+
export const packageResources = {
|
|
34
|
+
en: {
|
|
35
|
+
aidct_package: enLocaleStrings
|
|
36
|
+
},
|
|
37
|
+
fr: {
|
|
38
|
+
aidct_package: frLocaleStrings
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export const i18nextPackage = i18next.createInstance();
|
|
17
43
|
|
|
18
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Initialize internationalization.
|
|
46
|
+
*
|
|
47
|
+
* @param environment
|
|
48
|
+
* Environment in which the application is running.
|
|
49
|
+
*
|
|
50
|
+
* @param debug
|
|
51
|
+
* Debug setting.
|
|
52
|
+
*
|
|
53
|
+
* @returns
|
|
54
|
+
* Void promise.
|
|
55
|
+
*/
|
|
56
|
+
export async function i18nPackageInit(environment: I18NEnvironment, debug = false): Promise<void> {
|
|
57
|
+
await i18nDependency1Init(environment, debug);
|
|
58
|
+
await i18nDependency2Init(environment, debug);
|
|
59
|
+
await i18nCoreInit(i18nextPackage, environment, debug, packageNS, dependency1Resources, dependency2Resources, packageResources);
|
|
60
|
+
}
|
|
19
61
|
```
|
|
20
62
|
|
|
21
63
|
The resource types are declared in `i18next.d.ts` or similar:
|
|
22
64
|
|
|
23
65
|
```typescript
|
|
24
|
-
import type {
|
|
66
|
+
import type { Dependency1LocaleStrings } from "@aidc-toolkit/dependency1";
|
|
67
|
+
import type { Dependency2LocaleStrings } from "@aidc-toolkit/dependency2";
|
|
68
|
+
import type { PackageLocaleStrings } from "./i18n.js";
|
|
25
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Internationalization module.
|
|
72
|
+
*/
|
|
26
73
|
declare module "i18next" {
|
|
74
|
+
/**
|
|
75
|
+
* Custom type options for this package.
|
|
76
|
+
*/
|
|
27
77
|
interface CustomTypeOptions {
|
|
78
|
+
defaultNS: "aidct_package";
|
|
28
79
|
resources: {
|
|
29
|
-
|
|
30
|
-
|
|
80
|
+
aidct_dependency1: Dependency1LocaleStrings;
|
|
81
|
+
aidct_dependency2: Dependency2LocaleStrings;
|
|
82
|
+
aidct_package: PackageLocaleStrings;
|
|
31
83
|
};
|
|
32
84
|
}
|
|
33
85
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -31,71 +31,20 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var src_exports = {};
|
|
32
32
|
__export(src_exports, {
|
|
33
33
|
I18NEnvironment: () => I18NEnvironment,
|
|
34
|
-
i18nAddResourceBundle: () => i18nAddResourceBundle,
|
|
35
34
|
i18nAssertValidResources: () => i18nAssertValidResources,
|
|
36
|
-
|
|
37
|
-
i18next: () => i18n_default
|
|
35
|
+
i18nCoreInit: () => i18nCoreInit
|
|
38
36
|
});
|
|
39
37
|
module.exports = __toCommonJS(src_exports);
|
|
40
38
|
|
|
41
39
|
// src/locale/i18n.ts
|
|
42
|
-
var import_i18next = __toESM(require("i18next"), 1);
|
|
43
40
|
var import_i18next_browser_languagedetector = __toESM(require("i18next-browser-languagedetector"), 1);
|
|
44
41
|
var import_i18next_cli_language_detector = __toESM(require("i18next-cli-language-detector"), 1);
|
|
45
|
-
var i18n_default = import_i18next.default;
|
|
46
|
-
var pendingResourceBundles = [];
|
|
47
42
|
var I18NEnvironment = /* @__PURE__ */ ((I18NEnvironment2) => {
|
|
48
43
|
I18NEnvironment2[I18NEnvironment2["CLI"] = 0] = "CLI";
|
|
49
44
|
I18NEnvironment2[I18NEnvironment2["Server"] = 1] = "Server";
|
|
50
45
|
I18NEnvironment2[I18NEnvironment2["Browser"] = 2] = "Browser";
|
|
51
46
|
return I18NEnvironment2;
|
|
52
47
|
})(I18NEnvironment || {});
|
|
53
|
-
function toLowerCase(s) {
|
|
54
|
-
return s.split(" ").map((word) => /[a-z]/.test(word) ? word.toLowerCase() : word).join(" ");
|
|
55
|
-
}
|
|
56
|
-
async function i18nInit(environment, debug = false) {
|
|
57
|
-
let initialized;
|
|
58
|
-
if (pendingResourceBundles !== void 0) {
|
|
59
|
-
initialized = true;
|
|
60
|
-
let module2;
|
|
61
|
-
switch (environment) {
|
|
62
|
-
case 0 /* CLI */:
|
|
63
|
-
module2 = import_i18next_cli_language_detector.default;
|
|
64
|
-
break;
|
|
65
|
-
case 2 /* Browser */:
|
|
66
|
-
module2 = import_i18next_browser_languagedetector.default;
|
|
67
|
-
break;
|
|
68
|
-
default:
|
|
69
|
-
throw new Error("Not supported");
|
|
70
|
-
}
|
|
71
|
-
const initResourceBundles = pendingResourceBundles;
|
|
72
|
-
pendingResourceBundles = void 0;
|
|
73
|
-
await import_i18next.default.use(module2).init({
|
|
74
|
-
fallbackLng: "en",
|
|
75
|
-
debug,
|
|
76
|
-
resources: {}
|
|
77
|
-
}).then(() => {
|
|
78
|
-
import_i18next.default.services.formatter?.add("toLowerCase", (value) => typeof value === "string" ? toLowerCase(value) : String(value));
|
|
79
|
-
for (const initResourceBundle of initResourceBundles) {
|
|
80
|
-
i18nAddResourceBundle(initResourceBundle.lng, initResourceBundle.ns, initResourceBundle.resources);
|
|
81
|
-
}
|
|
82
|
-
});
|
|
83
|
-
} else {
|
|
84
|
-
initialized = false;
|
|
85
|
-
}
|
|
86
|
-
return initialized;
|
|
87
|
-
}
|
|
88
|
-
function i18nAddResourceBundle(lng, ns, resources) {
|
|
89
|
-
if (pendingResourceBundles !== void 0) {
|
|
90
|
-
pendingResourceBundles.push({
|
|
91
|
-
lng,
|
|
92
|
-
ns,
|
|
93
|
-
resources
|
|
94
|
-
});
|
|
95
|
-
} else {
|
|
96
|
-
import_i18next.default.addResourceBundle(lng, ns, resources);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
48
|
function i18nAssertValidResources(enResources, lng, lngResources, parent) {
|
|
100
49
|
const enResourcesMap = new Map(Object.entries(enResources));
|
|
101
50
|
const lngResourcesMap = new Map(Object.entries(lngResources));
|
|
@@ -121,11 +70,47 @@ function i18nAssertValidResources(enResources, lng, lngResources, parent) {
|
|
|
121
70
|
}
|
|
122
71
|
}
|
|
123
72
|
}
|
|
73
|
+
function toLowerCase(s) {
|
|
74
|
+
return s.split(" ").map((word) => /[a-z]/.test(word) ? word.toLowerCase() : word).join(" ");
|
|
75
|
+
}
|
|
76
|
+
async function i18nCoreInit(i18next, environment, debug, defaultNS, ...resources) {
|
|
77
|
+
if (!i18next.isInitialized) {
|
|
78
|
+
const mergedResource = {};
|
|
79
|
+
for (const resource of resources) {
|
|
80
|
+
for (const [language, resourceLanguage] of Object.entries(resource)) {
|
|
81
|
+
if (!(language in mergedResource)) {
|
|
82
|
+
mergedResource[language] = {};
|
|
83
|
+
}
|
|
84
|
+
const mergedResourceLanguage = mergedResource[language];
|
|
85
|
+
for (const [namespace, resourceKey] of Object.entries(resourceLanguage)) {
|
|
86
|
+
mergedResourceLanguage[namespace] = resourceKey;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
let module2;
|
|
91
|
+
switch (environment) {
|
|
92
|
+
case 0 /* CLI */:
|
|
93
|
+
module2 = import_i18next_cli_language_detector.default;
|
|
94
|
+
break;
|
|
95
|
+
case 2 /* Browser */:
|
|
96
|
+
module2 = import_i18next_browser_languagedetector.default;
|
|
97
|
+
break;
|
|
98
|
+
default:
|
|
99
|
+
throw new Error("Not supported");
|
|
100
|
+
}
|
|
101
|
+
await i18next.use(module2).init({
|
|
102
|
+
debug,
|
|
103
|
+
resources: mergedResource,
|
|
104
|
+
fallbackLng: "en",
|
|
105
|
+
defaultNS
|
|
106
|
+
}).then(() => {
|
|
107
|
+
i18next.services.formatter?.add("toLowerCase", (value) => typeof value === "string" ? toLowerCase(value) : String(value));
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
124
111
|
// Annotate the CommonJS export names for ESM import in node:
|
|
125
112
|
0 && (module.exports = {
|
|
126
113
|
I18NEnvironment,
|
|
127
|
-
i18nAddResourceBundle,
|
|
128
114
|
i18nAssertValidResources,
|
|
129
|
-
|
|
130
|
-
i18next
|
|
115
|
+
i18nCoreInit
|
|
131
116
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
export { default as i18next } from 'i18next';
|
|
1
|
+
import { i18n, Resource } from 'i18next';
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* Internationalization operating environment.
|
|
@@ -18,32 +17,6 @@ declare enum I18NEnvironment {
|
|
|
18
17
|
*/
|
|
19
18
|
Browser = 2
|
|
20
19
|
}
|
|
21
|
-
/**
|
|
22
|
-
* Initialize internationalization.
|
|
23
|
-
*
|
|
24
|
-
* @param environment
|
|
25
|
-
* Environment in which the application is running.
|
|
26
|
-
*
|
|
27
|
-
* @param debug
|
|
28
|
-
* Debug setting.
|
|
29
|
-
*
|
|
30
|
-
* @returns
|
|
31
|
-
* True if initialization was completed, false if skipped (already initialized).
|
|
32
|
-
*/
|
|
33
|
-
declare function i18nInit(environment: I18NEnvironment, debug?: boolean): Promise<boolean>;
|
|
34
|
-
/**
|
|
35
|
-
* Add a resource bundle.
|
|
36
|
-
*
|
|
37
|
-
* @param lng
|
|
38
|
-
* Language.
|
|
39
|
-
*
|
|
40
|
-
* @param ns
|
|
41
|
-
* Namespace.
|
|
42
|
-
*
|
|
43
|
-
* @param resources
|
|
44
|
-
* Resources.
|
|
45
|
-
*/
|
|
46
|
-
declare function i18nAddResourceBundle(lng: string, ns: string, resources: object): void;
|
|
47
20
|
/**
|
|
48
21
|
* Assert that language resources are a type match for English (default) resources.
|
|
49
22
|
*
|
|
@@ -60,5 +33,28 @@ declare function i18nAddResourceBundle(lng: string, ns: string, resources: objec
|
|
|
60
33
|
* Parent key name (set recursively).
|
|
61
34
|
*/
|
|
62
35
|
declare function i18nAssertValidResources(enResources: object, lng: string, lngResources: object, parent?: string): void;
|
|
36
|
+
/**
|
|
37
|
+
* Initialize internationalization.
|
|
38
|
+
*
|
|
39
|
+
* @param i18next
|
|
40
|
+
* Internationalization object. As multiple objects exists, this parameter represents the one for the module for which
|
|
41
|
+
* internationalization is being initialized.
|
|
42
|
+
*
|
|
43
|
+
* @param environment
|
|
44
|
+
* Environment in which the application is running.
|
|
45
|
+
*
|
|
46
|
+
* @param debug
|
|
47
|
+
* Debug setting.
|
|
48
|
+
*
|
|
49
|
+
* @param defaultNS
|
|
50
|
+
* Default namespace.
|
|
51
|
+
*
|
|
52
|
+
* @param resources
|
|
53
|
+
* Resources.
|
|
54
|
+
*
|
|
55
|
+
* @returns
|
|
56
|
+
* Void promise.
|
|
57
|
+
*/
|
|
58
|
+
declare function i18nCoreInit(i18next: i18n, environment: I18NEnvironment, debug: boolean, defaultNS: string, ...resources: Resource[]): Promise<void>;
|
|
63
59
|
|
|
64
|
-
export { I18NEnvironment,
|
|
60
|
+
export { I18NEnvironment, i18nAssertValidResources, i18nCoreInit };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
export { default as i18next } from 'i18next';
|
|
1
|
+
import { i18n, Resource } from 'i18next';
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* Internationalization operating environment.
|
|
@@ -18,32 +17,6 @@ declare enum I18NEnvironment {
|
|
|
18
17
|
*/
|
|
19
18
|
Browser = 2
|
|
20
19
|
}
|
|
21
|
-
/**
|
|
22
|
-
* Initialize internationalization.
|
|
23
|
-
*
|
|
24
|
-
* @param environment
|
|
25
|
-
* Environment in which the application is running.
|
|
26
|
-
*
|
|
27
|
-
* @param debug
|
|
28
|
-
* Debug setting.
|
|
29
|
-
*
|
|
30
|
-
* @returns
|
|
31
|
-
* True if initialization was completed, false if skipped (already initialized).
|
|
32
|
-
*/
|
|
33
|
-
declare function i18nInit(environment: I18NEnvironment, debug?: boolean): Promise<boolean>;
|
|
34
|
-
/**
|
|
35
|
-
* Add a resource bundle.
|
|
36
|
-
*
|
|
37
|
-
* @param lng
|
|
38
|
-
* Language.
|
|
39
|
-
*
|
|
40
|
-
* @param ns
|
|
41
|
-
* Namespace.
|
|
42
|
-
*
|
|
43
|
-
* @param resources
|
|
44
|
-
* Resources.
|
|
45
|
-
*/
|
|
46
|
-
declare function i18nAddResourceBundle(lng: string, ns: string, resources: object): void;
|
|
47
20
|
/**
|
|
48
21
|
* Assert that language resources are a type match for English (default) resources.
|
|
49
22
|
*
|
|
@@ -60,5 +33,28 @@ declare function i18nAddResourceBundle(lng: string, ns: string, resources: objec
|
|
|
60
33
|
* Parent key name (set recursively).
|
|
61
34
|
*/
|
|
62
35
|
declare function i18nAssertValidResources(enResources: object, lng: string, lngResources: object, parent?: string): void;
|
|
36
|
+
/**
|
|
37
|
+
* Initialize internationalization.
|
|
38
|
+
*
|
|
39
|
+
* @param i18next
|
|
40
|
+
* Internationalization object. As multiple objects exists, this parameter represents the one for the module for which
|
|
41
|
+
* internationalization is being initialized.
|
|
42
|
+
*
|
|
43
|
+
* @param environment
|
|
44
|
+
* Environment in which the application is running.
|
|
45
|
+
*
|
|
46
|
+
* @param debug
|
|
47
|
+
* Debug setting.
|
|
48
|
+
*
|
|
49
|
+
* @param defaultNS
|
|
50
|
+
* Default namespace.
|
|
51
|
+
*
|
|
52
|
+
* @param resources
|
|
53
|
+
* Resources.
|
|
54
|
+
*
|
|
55
|
+
* @returns
|
|
56
|
+
* Void promise.
|
|
57
|
+
*/
|
|
58
|
+
declare function i18nCoreInit(i18next: i18n, environment: I18NEnvironment, debug: boolean, defaultNS: string, ...resources: Resource[]): Promise<void>;
|
|
63
59
|
|
|
64
|
-
export { I18NEnvironment,
|
|
60
|
+
export { I18NEnvironment, i18nAssertValidResources, i18nCoreInit };
|
package/dist/index.js
CHANGED
|
@@ -1,61 +1,12 @@
|
|
|
1
1
|
// src/locale/i18n.ts
|
|
2
|
-
import i18next from "i18next";
|
|
3
2
|
import I18nextBrowserLanguageDetector from "i18next-browser-languagedetector";
|
|
4
3
|
import I18nextCLILanguageDetector from "i18next-cli-language-detector";
|
|
5
|
-
var i18n_default = i18next;
|
|
6
|
-
var pendingResourceBundles = [];
|
|
7
4
|
var I18NEnvironment = /* @__PURE__ */ ((I18NEnvironment2) => {
|
|
8
5
|
I18NEnvironment2[I18NEnvironment2["CLI"] = 0] = "CLI";
|
|
9
6
|
I18NEnvironment2[I18NEnvironment2["Server"] = 1] = "Server";
|
|
10
7
|
I18NEnvironment2[I18NEnvironment2["Browser"] = 2] = "Browser";
|
|
11
8
|
return I18NEnvironment2;
|
|
12
9
|
})(I18NEnvironment || {});
|
|
13
|
-
function toLowerCase(s) {
|
|
14
|
-
return s.split(" ").map((word) => /[a-z]/.test(word) ? word.toLowerCase() : word).join(" ");
|
|
15
|
-
}
|
|
16
|
-
async function i18nInit(environment, debug = false) {
|
|
17
|
-
let initialized;
|
|
18
|
-
if (pendingResourceBundles !== void 0) {
|
|
19
|
-
initialized = true;
|
|
20
|
-
let module;
|
|
21
|
-
switch (environment) {
|
|
22
|
-
case 0 /* CLI */:
|
|
23
|
-
module = I18nextCLILanguageDetector;
|
|
24
|
-
break;
|
|
25
|
-
case 2 /* Browser */:
|
|
26
|
-
module = I18nextBrowserLanguageDetector;
|
|
27
|
-
break;
|
|
28
|
-
default:
|
|
29
|
-
throw new Error("Not supported");
|
|
30
|
-
}
|
|
31
|
-
const initResourceBundles = pendingResourceBundles;
|
|
32
|
-
pendingResourceBundles = void 0;
|
|
33
|
-
await i18next.use(module).init({
|
|
34
|
-
fallbackLng: "en",
|
|
35
|
-
debug,
|
|
36
|
-
resources: {}
|
|
37
|
-
}).then(() => {
|
|
38
|
-
i18next.services.formatter?.add("toLowerCase", (value) => typeof value === "string" ? toLowerCase(value) : String(value));
|
|
39
|
-
for (const initResourceBundle of initResourceBundles) {
|
|
40
|
-
i18nAddResourceBundle(initResourceBundle.lng, initResourceBundle.ns, initResourceBundle.resources);
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
} else {
|
|
44
|
-
initialized = false;
|
|
45
|
-
}
|
|
46
|
-
return initialized;
|
|
47
|
-
}
|
|
48
|
-
function i18nAddResourceBundle(lng, ns, resources) {
|
|
49
|
-
if (pendingResourceBundles !== void 0) {
|
|
50
|
-
pendingResourceBundles.push({
|
|
51
|
-
lng,
|
|
52
|
-
ns,
|
|
53
|
-
resources
|
|
54
|
-
});
|
|
55
|
-
} else {
|
|
56
|
-
i18next.addResourceBundle(lng, ns, resources);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
10
|
function i18nAssertValidResources(enResources, lng, lngResources, parent) {
|
|
60
11
|
const enResourcesMap = new Map(Object.entries(enResources));
|
|
61
12
|
const lngResourcesMap = new Map(Object.entries(lngResources));
|
|
@@ -81,10 +32,46 @@ function i18nAssertValidResources(enResources, lng, lngResources, parent) {
|
|
|
81
32
|
}
|
|
82
33
|
}
|
|
83
34
|
}
|
|
35
|
+
function toLowerCase(s) {
|
|
36
|
+
return s.split(" ").map((word) => /[a-z]/.test(word) ? word.toLowerCase() : word).join(" ");
|
|
37
|
+
}
|
|
38
|
+
async function i18nCoreInit(i18next, environment, debug, defaultNS, ...resources) {
|
|
39
|
+
if (!i18next.isInitialized) {
|
|
40
|
+
const mergedResource = {};
|
|
41
|
+
for (const resource of resources) {
|
|
42
|
+
for (const [language, resourceLanguage] of Object.entries(resource)) {
|
|
43
|
+
if (!(language in mergedResource)) {
|
|
44
|
+
mergedResource[language] = {};
|
|
45
|
+
}
|
|
46
|
+
const mergedResourceLanguage = mergedResource[language];
|
|
47
|
+
for (const [namespace, resourceKey] of Object.entries(resourceLanguage)) {
|
|
48
|
+
mergedResourceLanguage[namespace] = resourceKey;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
let module;
|
|
53
|
+
switch (environment) {
|
|
54
|
+
case 0 /* CLI */:
|
|
55
|
+
module = I18nextCLILanguageDetector;
|
|
56
|
+
break;
|
|
57
|
+
case 2 /* Browser */:
|
|
58
|
+
module = I18nextBrowserLanguageDetector;
|
|
59
|
+
break;
|
|
60
|
+
default:
|
|
61
|
+
throw new Error("Not supported");
|
|
62
|
+
}
|
|
63
|
+
await i18next.use(module).init({
|
|
64
|
+
debug,
|
|
65
|
+
resources: mergedResource,
|
|
66
|
+
fallbackLng: "en",
|
|
67
|
+
defaultNS
|
|
68
|
+
}).then(() => {
|
|
69
|
+
i18next.services.formatter?.add("toLowerCase", (value) => typeof value === "string" ? toLowerCase(value) : String(value));
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
84
73
|
export {
|
|
85
74
|
I18NEnvironment,
|
|
86
|
-
i18nAddResourceBundle,
|
|
87
75
|
i18nAssertValidResources,
|
|
88
|
-
|
|
89
|
-
i18n_default as i18next
|
|
76
|
+
i18nCoreInit
|
|
90
77
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aidc-toolkit/core",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.8-beta",
|
|
4
4
|
"description": "Core functionality for AIDC Toolkit",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"build-doc": "npm run build && tsc src/index.ts --outDir dist --target esnext --moduleResolution nodenext --module nodenext --emitDeclarationOnly --declaration --declarationMap"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@aidc-toolkit/dev": "^0.9.
|
|
27
|
+
"@aidc-toolkit/dev": "^0.9.8-beta",
|
|
28
28
|
"eslint": "^9.16.0",
|
|
29
29
|
"ts-node": "^10.9.2",
|
|
30
30
|
"tsup": "^8.3.5",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"@rollup/rollup-linux-x64-gnu": "^4.28.1",
|
|
35
|
-
"i18next": "^24.0
|
|
35
|
+
"i18next": "^24.1.0",
|
|
36
36
|
"i18next-browser-languagedetector": "^8.0.2",
|
|
37
37
|
"i18next-cli-language-detector": "^1.1.8"
|
|
38
38
|
}
|
package/src/index.ts
CHANGED
package/src/locale/i18n.ts
CHANGED
|
@@ -1,23 +1,7 @@
|
|
|
1
|
-
import
|
|
1
|
+
import type { i18n, LanguageDetectorModule, Resource } from "i18next";
|
|
2
2
|
import I18nextBrowserLanguageDetector from "i18next-browser-languagedetector";
|
|
3
3
|
import I18nextCLILanguageDetector from "i18next-cli-language-detector";
|
|
4
4
|
|
|
5
|
-
export default i18next;
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Internal type to maintain resource bundles added before initialization.
|
|
9
|
-
*/
|
|
10
|
-
interface ResourceBundle {
|
|
11
|
-
lng: string;
|
|
12
|
-
ns: string;
|
|
13
|
-
resources: object;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Internal array to maintain resource bundles added before initialization.
|
|
18
|
-
*/
|
|
19
|
-
let pendingResourceBundles: ResourceBundle[] | undefined = [];
|
|
20
|
-
|
|
21
5
|
/**
|
|
22
6
|
* Internationalization operating environment.
|
|
23
7
|
*/
|
|
@@ -38,6 +22,54 @@ export enum I18NEnvironment {
|
|
|
38
22
|
Browser
|
|
39
23
|
}
|
|
40
24
|
|
|
25
|
+
/**
|
|
26
|
+
* Assert that language resources are a type match for English (default) resources.
|
|
27
|
+
*
|
|
28
|
+
* @param enResources
|
|
29
|
+
* English resources.
|
|
30
|
+
*
|
|
31
|
+
* @param lng
|
|
32
|
+
* Language.
|
|
33
|
+
*
|
|
34
|
+
* @param lngResources
|
|
35
|
+
* Language resources.
|
|
36
|
+
*
|
|
37
|
+
* @param parent
|
|
38
|
+
* Parent key name (set recursively).
|
|
39
|
+
*/
|
|
40
|
+
export function i18nAssertValidResources(enResources: object, lng: string, lngResources: object, parent?: string): void {
|
|
41
|
+
const enResourcesMap = new Map<string, object>(Object.entries(enResources));
|
|
42
|
+
const lngResourcesMap = new Map<string, object>(Object.entries(lngResources));
|
|
43
|
+
|
|
44
|
+
const isLocale = lng.includes("-");
|
|
45
|
+
|
|
46
|
+
for (const [enKey, enValue] of enResourcesMap) {
|
|
47
|
+
const lngValue = lngResourcesMap.get(enKey);
|
|
48
|
+
|
|
49
|
+
if (lngValue !== undefined) {
|
|
50
|
+
const enValueType = typeof enValue;
|
|
51
|
+
const lngValueType = typeof lngValue;
|
|
52
|
+
|
|
53
|
+
if (lngValueType !== enValueType) {
|
|
54
|
+
throw new Error(`Invalid value type ${lngValueType} for key ${parent === undefined ? "" : `${parent}.`}${enKey} in ${lng} resources`);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (enValueType === "object") {
|
|
58
|
+
i18nAssertValidResources(enValue, lng, lngValue, `${parent === undefined ? "" : `${parent}.`}${enKey}`);
|
|
59
|
+
}
|
|
60
|
+
// Locale falls back to raw language so ignore if missing.
|
|
61
|
+
} else if (!isLocale) {
|
|
62
|
+
throw new Error(`Missing key ${parent === undefined ? "" : `${parent}.`}${enKey} from ${lng} resources`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
for (const [lngKey] of lngResourcesMap) {
|
|
67
|
+
if (!enResourcesMap.has(lngKey)) {
|
|
68
|
+
throw new Error(`Extraneous key ${parent === undefined ? "" : `${parent}.`}${lngKey} in ${lng} resources`);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
41
73
|
/**
|
|
42
74
|
* Convert a string to lower case, skipping words that are all upper case.
|
|
43
75
|
*
|
|
@@ -55,27 +87,53 @@ function toLowerCase(s: string): string {
|
|
|
55
87
|
/**
|
|
56
88
|
* Initialize internationalization.
|
|
57
89
|
*
|
|
90
|
+
* @param i18next
|
|
91
|
+
* Internationalization object. As multiple objects exists, this parameter represents the one for the module for which
|
|
92
|
+
* internationalization is being initialized.
|
|
93
|
+
*
|
|
58
94
|
* @param environment
|
|
59
95
|
* Environment in which the application is running.
|
|
60
96
|
*
|
|
61
97
|
* @param debug
|
|
62
98
|
* Debug setting.
|
|
63
99
|
*
|
|
100
|
+
* @param defaultNS
|
|
101
|
+
* Default namespace.
|
|
102
|
+
*
|
|
103
|
+
* @param resources
|
|
104
|
+
* Resources.
|
|
105
|
+
*
|
|
64
106
|
* @returns
|
|
65
|
-
*
|
|
107
|
+
* Void promise.
|
|
66
108
|
*/
|
|
67
|
-
export async function
|
|
68
|
-
|
|
109
|
+
export async function i18nCoreInit(i18next: i18n, environment: I18NEnvironment, debug: boolean, defaultNS: string, ...resources: Resource[]): Promise<void> {
|
|
110
|
+
// Initialization may be called more than once.
|
|
111
|
+
if (!i18next.isInitialized) {
|
|
112
|
+
const mergedResource: Resource = {};
|
|
113
|
+
|
|
114
|
+
// Merge resources.
|
|
115
|
+
for (const resource of resources) {
|
|
116
|
+
// Merge languages.
|
|
117
|
+
for (const [language, resourceLanguage] of Object.entries(resource)) {
|
|
118
|
+
if (!(language in mergedResource)) {
|
|
119
|
+
mergedResource[language] = {};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const mergedResourceLanguage = mergedResource[language];
|
|
123
|
+
|
|
124
|
+
// Merge namespaces.
|
|
125
|
+
for (const [namespace, resourceKey] of Object.entries(resourceLanguage)) {
|
|
126
|
+
mergedResourceLanguage[namespace] = resourceKey;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
69
130
|
|
|
70
|
-
// Skip if initialization is not pending.
|
|
71
|
-
if (pendingResourceBundles !== undefined) {
|
|
72
|
-
initialized = true;
|
|
73
|
-
|
|
74
131
|
let module: Parameters<typeof i18next.use>[0];
|
|
75
132
|
|
|
76
133
|
switch (environment) {
|
|
77
134
|
case I18NEnvironment.CLI:
|
|
78
|
-
//
|
|
135
|
+
// TODO Refactor when https://github.com/neet/i18next-cli-language-detector/issues/281 resolved.
|
|
136
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Per above.
|
|
79
137
|
module = I18nextCLILanguageDetector as unknown as LanguageDetectorModule;
|
|
80
138
|
break;
|
|
81
139
|
|
|
@@ -87,100 +145,14 @@ export async function i18nInit(environment: I18NEnvironment, debug = false): Pro
|
|
|
87
145
|
throw new Error("Not supported");
|
|
88
146
|
}
|
|
89
147
|
|
|
90
|
-
const initResourceBundles = pendingResourceBundles;
|
|
91
|
-
|
|
92
|
-
// No need to manage pending resource bundles past this point.
|
|
93
|
-
pendingResourceBundles = undefined;
|
|
94
|
-
|
|
95
148
|
await i18next.use(module).init({
|
|
96
|
-
fallbackLng: "en",
|
|
97
149
|
debug,
|
|
98
|
-
resources:
|
|
150
|
+
resources: mergedResource,
|
|
151
|
+
fallbackLng: "en",
|
|
152
|
+
defaultNS
|
|
99
153
|
}).then(() => {
|
|
100
154
|
// Add toLowerCase function.
|
|
101
155
|
i18next.services.formatter?.add("toLowerCase", value => typeof value === "string" ? toLowerCase(value) : String(value));
|
|
102
|
-
|
|
103
|
-
// Add pending resource bundles.
|
|
104
|
-
for (const initResourceBundle of initResourceBundles) {
|
|
105
|
-
i18nAddResourceBundle(initResourceBundle.lng, initResourceBundle.ns, initResourceBundle.resources);
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
} else {
|
|
109
|
-
initialized = false;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return initialized;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Add a resource bundle.
|
|
117
|
-
*
|
|
118
|
-
* @param lng
|
|
119
|
-
* Language.
|
|
120
|
-
*
|
|
121
|
-
* @param ns
|
|
122
|
-
* Namespace.
|
|
123
|
-
*
|
|
124
|
-
* @param resources
|
|
125
|
-
* Resources.
|
|
126
|
-
*/
|
|
127
|
-
export function i18nAddResourceBundle(lng: string, ns: string, resources: object): void {
|
|
128
|
-
if (pendingResourceBundles !== undefined) {
|
|
129
|
-
pendingResourceBundles.push({
|
|
130
|
-
lng,
|
|
131
|
-
ns,
|
|
132
|
-
resources
|
|
133
156
|
});
|
|
134
|
-
} else {
|
|
135
|
-
// Already initialized; add resource bundle directly.
|
|
136
|
-
i18next.addResourceBundle(lng, ns, resources);
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Assert that language resources are a type match for English (default) resources.
|
|
142
|
-
*
|
|
143
|
-
* @param enResources
|
|
144
|
-
* English resources.
|
|
145
|
-
*
|
|
146
|
-
* @param lng
|
|
147
|
-
* Language.
|
|
148
|
-
*
|
|
149
|
-
* @param lngResources
|
|
150
|
-
* Language resources.
|
|
151
|
-
*
|
|
152
|
-
* @param parent
|
|
153
|
-
* Parent key name (set recursively).
|
|
154
|
-
*/
|
|
155
|
-
export function i18nAssertValidResources(enResources: object, lng: string, lngResources: object, parent?: string): void {
|
|
156
|
-
const enResourcesMap = new Map<string, object>(Object.entries(enResources));
|
|
157
|
-
const lngResourcesMap = new Map<string, object>(Object.entries(lngResources));
|
|
158
|
-
|
|
159
|
-
const isLocale = lng.includes("-");
|
|
160
|
-
|
|
161
|
-
for (const [enKey, enValue] of enResourcesMap) {
|
|
162
|
-
const lngValue = lngResourcesMap.get(enKey);
|
|
163
|
-
|
|
164
|
-
if (lngValue !== undefined) {
|
|
165
|
-
const enValueType = typeof enValue;
|
|
166
|
-
const lngValueType = typeof lngValue;
|
|
167
|
-
|
|
168
|
-
if (lngValueType !== enValueType) {
|
|
169
|
-
throw new Error(`Invalid value type ${lngValueType} for key ${parent === undefined ? "" : `${parent}.`}${enKey} in ${lng} resources`);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
if (enValueType === "object") {
|
|
173
|
-
i18nAssertValidResources(enValue, lng, lngValue, `${parent === undefined ? "" : `${parent}.`}${enKey}`);
|
|
174
|
-
}
|
|
175
|
-
// Locale falls back to raw language so ignore if missing.
|
|
176
|
-
} else if (!isLocale) {
|
|
177
|
-
throw new Error(`Missing key ${parent === undefined ? "" : `${parent}.`}${enKey} from ${lng} resources`);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
for (const [lngKey] of lngResourcesMap) {
|
|
182
|
-
if (!enResourcesMap.has(lngKey)) {
|
|
183
|
-
throw new Error(`Extraneous key ${parent === undefined ? "" : `${parent}.`}${lngKey} in ${lng} resources`);
|
|
184
|
-
}
|
|
185
157
|
}
|
|
186
158
|
}
|
|
File without changes
|