@aidc-toolkit/core 1.0.38-beta → 1.0.39-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 +27 -9
- package/dist/locale/i18n.d.ts.map +1 -1
- package/dist/locale/i18n.js +42 -27
- package/dist/locale/i18n.js.map +1 -1
- package/package.json +2 -2
- package/src/locale/i18n.ts +49 -36
package/README.md
CHANGED
|
@@ -32,7 +32,9 @@ All AIDC Toolkit packages require internationalization. The localization functio
|
|
|
32
32
|
>
|
|
33
33
|
> For a complete example, including how to use application-specific resource bundles, see the AIDC Toolkit [demo source](https://github.com/aidc-toolkit/demo/tree/main/src/locale).
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
### Initialization
|
|
36
|
+
|
|
37
|
+
Packages initialize their resources as follows in `i18n.ts` or similar. Note that "dependency1" and "dependency2" are placeholders for the names of the packages on which the package depends, and "package" is the package itself.
|
|
36
38
|
|
|
37
39
|
```typescript
|
|
38
40
|
import { i18nCoreInit, type I18nEnvironment, i18nInit } from "@aidc-toolkit/core";
|
|
@@ -110,7 +112,9 @@ declare module "i18next" {
|
|
|
110
112
|
|
|
111
113
|
The declaration in `i18next.d.ts` exposes the resources of the dependencies to the package. The initialization process merges all the resources into a single resource bundle matching the declaration.
|
|
112
114
|
|
|
113
|
-
|
|
115
|
+
### Environment-Specific Language Detection
|
|
116
|
+
|
|
117
|
+
Language detection is available for the following environments:
|
|
114
118
|
|
|
115
119
|
- [Command-line interface](#command-line-interface)
|
|
116
120
|
- Unit tests
|
|
@@ -118,7 +122,19 @@ Support is available for the following environments:
|
|
|
118
122
|
- Web server - **NOT YET IMPLEMENTED**
|
|
119
123
|
- [Web browser](#web-browser)
|
|
120
124
|
|
|
121
|
-
|
|
125
|
+
When a package's `i18next` object is initialized:
|
|
126
|
+
|
|
127
|
+
Language detection starts with the full locale as provided by the environment then falls back as follows:
|
|
128
|
+
|
|
129
|
+
- the full locale minus the regional variant if any;
|
|
130
|
+
- the full locale minus the regional variant and the region if any; and
|
|
131
|
+
- the first locale as defined in the default resource bundle.
|
|
132
|
+
|
|
133
|
+
Caching (typically via the `i18nextLng` attribute in some form of storage) is disabled. Depending on the detector, this may still allow reading from a cache (e.g., the browser detector from local storage or session storage) but not writing. This leaves it to the application to decide how and when to persist the language setting.
|
|
134
|
+
|
|
135
|
+
#### Command-Line Interface
|
|
136
|
+
|
|
137
|
+
Language detection is implemented using [I18nextCLILanguageDetector](https://github.com/neet/i18next-cli-language-detector).
|
|
122
138
|
|
|
123
139
|
Initializing internationalization for a command-line interface application is straightforward:
|
|
124
140
|
|
|
@@ -126,7 +142,9 @@ Initializing internationalization for a command-line interface application is st
|
|
|
126
142
|
await i18nPackageInit(I18nEnvironment.CLI);
|
|
127
143
|
```
|
|
128
144
|
|
|
129
|
-
|
|
145
|
+
#### Web Browser
|
|
146
|
+
|
|
147
|
+
Language detection is implemented using [I18nextBrowserLanguageDetector](https://github.com/i18next/i18next-browser-languageDetector).
|
|
130
148
|
|
|
131
149
|
Initializing internationalization for a web browser requires awaiting the fulfillment of the `Promise` returned by the call to the initialization function before rendering any content. For example, in the React framework, this would be done before creating the root:
|
|
132
150
|
|
|
@@ -167,7 +185,7 @@ Parts of the AIDC Toolkit require persistent application data management, but th
|
|
|
167
185
|
|
|
168
186
|
The application data management functionality in this package provides a simple and consistent mechanism for managing application data. While not suitable for high-volumne or transactional data, it's sufficient for most applications that require simple key-value storage.
|
|
169
187
|
|
|
170
|
-
The [`AppData`](https://aidc-toolkit.com/api/Core/type-aliases/AppData.html) type alias is a simple constrained type of `string`, `number`, `boolean`, or `object`. An object type must be one of:
|
|
188
|
+
The [`AppData`](https://aidc-toolkit.com/v1.0/api/Core/type-aliases/AppData.html) type alias is a simple constrained type of `string`, `number`, `boolean`, or `object`. An object type must be one of:
|
|
171
189
|
|
|
172
190
|
- `Date`;
|
|
173
191
|
- `Uint8Array`;
|
|
@@ -181,13 +199,13 @@ Two functions `encodeAppData()` and `decodeAppData()` are provided to convert be
|
|
|
181
199
|
- encoding `Date` objects as ISO 8601 strings preceded by the string "dateTime:"; and
|
|
182
200
|
- encoding `Uint8Array` objects as [Base64](https://developer.mozilla.org/en-US/docs/Glossary/Base64) strings preceded by the string "binary:".
|
|
183
201
|
|
|
184
|
-
The functions are generally not called directly. Rather, they are called automatically by the [`ReadOnlyAppDataStorage`](https://aidc-toolkit.com/api/Core/classes/ReadOnlyAppDataStorage.html) and [`AppDataStorage`](https://aidc-toolkit.com/api/Core/classes/AppDataStorage.html) classes, which are used to manage application data in the AIDC Toolkit packages.
|
|
202
|
+
The functions are generally not called directly. Rather, they are called automatically by the [`ReadOnlyAppDataStorage`](https://aidc-toolkit.com/v1.0/api/Core/classes/ReadOnlyAppDataStorage.html) and [`AppDataStorage`](https://aidc-toolkit.com/v1.0/api/Core/classes/AppDataStorage.html) classes, which are used to manage application data in the AIDC Toolkit packages.
|
|
185
203
|
|
|
186
204
|
Internally, each storage provider defines whether it supports binary data natively. If so, a request to read binary data will return raw content as `Uint8Array` from the underlying storage mechanism and a request to write binary data will write the `Uint8Array` as-is. This applies only to top-level read and write operations, not to `Uint8Array` values stored in nested objects.
|
|
187
205
|
|
|
188
206
|
All storage providers take a path argument, which defines an implementation-specific location for the data. The following storage providers are provided by default:
|
|
189
207
|
|
|
190
|
-
- [`LocalAppDataStorage`](https://aidc-toolkit.com/api/Core/variables/LocalAppDataStorage.html)
|
|
208
|
+
- [`LocalAppDataStorage`](https://aidc-toolkit.com/v1.0/api/Core/variables/LocalAppDataStorage.html)
|
|
191
209
|
- Not a class, but rather a `Promise` of a constructor to one of the following implementations:
|
|
192
210
|
- File-based storage
|
|
193
211
|
- Supports binary data.
|
|
@@ -195,11 +213,11 @@ All storage providers take a path argument, which defines an implementation-spec
|
|
|
195
213
|
- Browser-based storage
|
|
196
214
|
- Does not support binary data.
|
|
197
215
|
- Maps the path by prepending it plus `/` to the key for use in [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage).
|
|
198
|
-
- [`RemoteAppDataStorage`](https://aidc-toolkit.com/api/Core/classes/RemoteAppDataStorage.html)
|
|
216
|
+
- [`RemoteAppDataStorage`](https://aidc-toolkit.com/v1.0/api/Core/classes/RemoteAppDataStorage.html)
|
|
199
217
|
- Read-only.
|
|
200
218
|
- Supports binary data.
|
|
201
219
|
- Maps the path to a base URL.
|
|
202
220
|
|
|
203
221
|
## Caching
|
|
204
222
|
|
|
205
|
-
The [`Cache`](https://aidc-toolkit.com/api/Core/classes/Cache.html) class provides a simple cache that can be used to maintain synchronization with an external source.
|
|
223
|
+
The [`Cache`](https://aidc-toolkit.com/v1.0/api/Core/classes/Cache.html) class provides a simple cache that can be used to maintain synchronization with an external source.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../src/locale/i18n.ts"],"names":[],"mappings":"AAAA,OAAgB,EACZ,KAAK,IAAI,EAKT,KAAK,QAAQ,EAChB,MAAM,SAAS,CAAC;AAGjB,OAAO,iBAAiB,MAAM,0BAA0B,CAAC;AAGzD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,MAAM,CAAC;CAC3C;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB;IACzB;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;CAEG,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,OAAO,gBAAgB,CAAC;AAE/D;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,gBAAgB,CAAC,kBAAkB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../src/locale/i18n.ts"],"names":[],"mappings":"AAAA,OAAgB,EACZ,KAAK,IAAI,EAKT,KAAK,QAAQ,EAChB,MAAM,SAAS,CAAC;AAGjB,OAAO,iBAAiB,MAAM,0BAA0B,CAAC;AAGzD;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,MAAM,CAAC;CAC3C;AAED;;GAEG;AACH,eAAO,MAAM,gBAAgB;IACzB;;OAEG;;IAGH;;OAEG;;IAGH;;OAEG;;CAEG,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,MAAM,OAAO,gBAAgB,CAAC;AAE/D;;GAEG;AACH,MAAM,MAAM,eAAe,GAAG,OAAO,gBAAgB,CAAC,kBAAkB,CAAC,CAAC;AAkB1E,eAAO,MAAM,MAAM,eAAe,CAAC;AAEnC;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,iBAAiB,CAAC;AAE3D;;GAEG;AACH,eAAO,MAAM,kBAAkB,EAAE,QAOhC,CAAC;AAGF,eAAO,MAAM,WAAW,EAAE,IAA+B,CAAC;AAE1D;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,QAAQ,CAAC,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,eAAe,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,qBAAqB,EAAE,QAAQ,EAAE,GAAG,mBAAmB,EAAE,KAAK,CAAC,CAAC,WAAW,EAAE,eAAe,EAAE,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CA4ErQ;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,YAAY,CAAC,WAAW,EAAE,eAAe,EAAE,KAAK,UAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAEjG"}
|
package/dist/locale/i18n.js
CHANGED
|
@@ -23,15 +23,17 @@ export const I18nEnvironments = {
|
|
|
23
23
|
/**
|
|
24
24
|
* Convert a string to lower case, skipping words that are all upper case.
|
|
25
25
|
*
|
|
26
|
-
* @param
|
|
27
|
-
*
|
|
26
|
+
* @param value
|
|
27
|
+
* Value.
|
|
28
28
|
*
|
|
29
29
|
* @returns
|
|
30
|
-
* Lower case string.
|
|
30
|
+
* Lower case string if value is a string. If not, value is returned as a string but not converted to lower case.
|
|
31
31
|
*/
|
|
32
|
-
function toLowerCase(
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
function toLowerCase(value) {
|
|
33
|
+
return typeof value === "string" ?
|
|
34
|
+
// Words with no lower case letters are preserved as they are likely mnemonics.
|
|
35
|
+
value.split(" ").map(word => /[a-z]/u.test(word) ? word.toLowerCase() : word).join(" ") :
|
|
36
|
+
String(value);
|
|
35
37
|
}
|
|
36
38
|
export const coreNS = "aidct_core";
|
|
37
39
|
/**
|
|
@@ -91,35 +93,48 @@ export async function i18nInit(i18next, environment, debug, defaultNS, defaultRe
|
|
|
91
93
|
const mergedLanguageResourceBundle = mergedResourceBundle[language];
|
|
92
94
|
// Merge namespaces.
|
|
93
95
|
for (const [namespace, resourceKey] of Object.entries(languageResourceBundle)) {
|
|
96
|
+
if (namespace in mergedLanguageResourceBundle) {
|
|
97
|
+
// Error prior to internationalization initialization; no localization possible.
|
|
98
|
+
throw new Error(`Duplicate namespace ${namespace} in merged resource bundle for language ${language}`);
|
|
99
|
+
}
|
|
94
100
|
mergedLanguageResourceBundle[namespace] = resourceKey;
|
|
95
101
|
}
|
|
96
102
|
}
|
|
97
103
|
}
|
|
98
104
|
mergeResourceBundle(defaultResourceBundle);
|
|
99
105
|
// Initialize dependencies and merge their resource bundles.
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
106
|
+
for (const i18nDependencyInit of i18nDependencyInits) {
|
|
107
|
+
// eslint-disable-next-line no-await-in-loop -- Dependencies must initialized first.
|
|
108
|
+
await i18nDependencyInit(environment, debug).then(mergeResourceBundle);
|
|
109
|
+
}
|
|
110
|
+
let module;
|
|
111
|
+
switch (environment) {
|
|
112
|
+
case I18nEnvironments.CLI:
|
|
113
|
+
// TODO Refactor when https://github.com/neet/i18next-cli-language-detector/issues/281 resolved.
|
|
114
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Per above.
|
|
115
|
+
module = I18nextCLILanguageDetector;
|
|
116
|
+
break;
|
|
117
|
+
case I18nEnvironments.Browser:
|
|
118
|
+
module = I18nextBrowserLanguageDetector;
|
|
119
|
+
break;
|
|
120
|
+
default:
|
|
121
|
+
throw new Error("Not supported");
|
|
122
|
+
}
|
|
123
|
+
await i18next.use(module).init({
|
|
116
124
|
debug,
|
|
125
|
+
defaultNS,
|
|
117
126
|
resources: mergedResourceBundle,
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
127
|
+
// Allow fallback by removing variant code then country code until match is found.
|
|
128
|
+
nonExplicitSupportedLngs: true,
|
|
129
|
+
// Fallback to first language defined.
|
|
130
|
+
fallbackLng: Object.keys(mergedResourceBundle)[0],
|
|
131
|
+
detection: {
|
|
132
|
+
// Disabling cache allows read but requires explicit saving of i18nextLng attribute (e.g., via UI).
|
|
133
|
+
caches: []
|
|
134
|
+
}
|
|
135
|
+
}).then(() => {
|
|
136
|
+
// Add toLowerCase formatter.
|
|
137
|
+
i18next.services.formatter?.add("toLowerCase", toLowerCase);
|
|
123
138
|
});
|
|
124
139
|
}
|
|
125
140
|
return defaultResourceBundle;
|
package/dist/locale/i18n.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../src/locale/i18n.ts"],"names":[],"mappings":"AAAA,OAAO,OAON,MAAM,SAAS,CAAC;AACjB,OAAO,8BAA8B,MAAM,kCAAkC,CAAC;AAC9E,OAAO,0BAA0B,MAAM,+BAA+B,CAAC;AACvE,OAAO,iBAAiB,MAAM,0BAA0B,CAAC;AACzD,OAAO,iBAAiB,MAAM,0BAA0B,CAAC;AASzD;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC5B;;OAEG;IACH,GAAG,EAAE,CAAC;IAEN;;OAEG;IACH,MAAM,EAAE,CAAC;IAET;;OAEG;IACH,OAAO,EAAE,CAAC;CACJ,CAAC;AAYX;;;;;;;;GAQG;AACH,SAAS,WAAW,CAAC,
|
|
1
|
+
{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../src/locale/i18n.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aidc-toolkit/core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.39-beta",
|
|
4
4
|
"description": "Core functionality for AIDC Toolkit",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"build:doc": "npm run build:non-prod"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
|
-
"@aidc-toolkit/dev": "1.0.
|
|
31
|
+
"@aidc-toolkit/dev": "1.0.38-beta"
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"base64-js": "^1.5.1",
|
package/src/locale/i18n.ts
CHANGED
|
@@ -51,15 +51,17 @@ export type I18nEnvironment = typeof I18nEnvironments[I18nEnvironmentKey];
|
|
|
51
51
|
/**
|
|
52
52
|
* Convert a string to lower case, skipping words that are all upper case.
|
|
53
53
|
*
|
|
54
|
-
* @param
|
|
55
|
-
*
|
|
54
|
+
* @param value
|
|
55
|
+
* Value.
|
|
56
56
|
*
|
|
57
57
|
* @returns
|
|
58
|
-
* Lower case string.
|
|
58
|
+
* Lower case string if value is a string. If not, value is returned as a string but not converted to lower case.
|
|
59
59
|
*/
|
|
60
|
-
function toLowerCase(
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
function toLowerCase(value: unknown): string {
|
|
61
|
+
return typeof value === "string" ?
|
|
62
|
+
// Words with no lower case letters are preserved as they are likely mnemonics.
|
|
63
|
+
value.split(" ").map(word => /[a-z]/u.test(word) ? word.toLowerCase() : word).join(" ") :
|
|
64
|
+
String(value);
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
export const coreNS = "aidct_core";
|
|
@@ -131,6 +133,11 @@ export async function i18nInit(i18next: i18n, environment: I18nEnvironment, debu
|
|
|
131
133
|
|
|
132
134
|
// Merge namespaces.
|
|
133
135
|
for (const [namespace, resourceKey] of Object.entries(languageResourceBundle)) {
|
|
136
|
+
if (namespace in mergedLanguageResourceBundle) {
|
|
137
|
+
// Error prior to internationalization initialization; no localization possible.
|
|
138
|
+
throw new Error(`Duplicate namespace ${namespace} in merged resource bundle for language ${language}`);
|
|
139
|
+
}
|
|
140
|
+
|
|
134
141
|
mergedLanguageResourceBundle[namespace] = resourceKey;
|
|
135
142
|
}
|
|
136
143
|
}
|
|
@@ -139,37 +146,43 @@ export async function i18nInit(i18next: i18n, environment: I18nEnvironment, debu
|
|
|
139
146
|
mergeResourceBundle(defaultResourceBundle);
|
|
140
147
|
|
|
141
148
|
// Initialize dependencies and merge their resource bundles.
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
module = I18nextBrowserLanguageDetector;
|
|
156
|
-
break;
|
|
157
|
-
|
|
158
|
-
default:
|
|
159
|
-
throw new Error("Not supported");
|
|
160
|
-
}
|
|
149
|
+
for (const i18nDependencyInit of i18nDependencyInits) {
|
|
150
|
+
// eslint-disable-next-line no-await-in-loop -- Dependencies must initialized first.
|
|
151
|
+
await i18nDependencyInit(environment, debug).then(mergeResourceBundle);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
let module: Module | Newable<Module> | NewableModule<Module>;
|
|
155
|
+
|
|
156
|
+
switch (environment) {
|
|
157
|
+
case I18nEnvironments.CLI:
|
|
158
|
+
// TODO Refactor when https://github.com/neet/i18next-cli-language-detector/issues/281 resolved.
|
|
159
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Per above.
|
|
160
|
+
module = I18nextCLILanguageDetector as unknown as LanguageDetectorModule;
|
|
161
|
+
break;
|
|
161
162
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
).
|
|
171
|
-
|
|
172
|
-
|
|
163
|
+
case I18nEnvironments.Browser:
|
|
164
|
+
module = I18nextBrowserLanguageDetector;
|
|
165
|
+
break;
|
|
166
|
+
|
|
167
|
+
default:
|
|
168
|
+
throw new Error("Not supported");
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
await i18next.use(module).init({
|
|
172
|
+
debug,
|
|
173
|
+
defaultNS,
|
|
174
|
+
resources: mergedResourceBundle,
|
|
175
|
+
// Allow fallback by removing variant code then country code until match is found.
|
|
176
|
+
nonExplicitSupportedLngs: true,
|
|
177
|
+
// Fallback to first language defined.
|
|
178
|
+
fallbackLng: Object.keys(mergedResourceBundle)[0],
|
|
179
|
+
detection: {
|
|
180
|
+
// Disabling cache allows read but requires explicit saving of i18nextLng attribute (e.g., via UI).
|
|
181
|
+
caches: []
|
|
182
|
+
}
|
|
183
|
+
}).then(() => {
|
|
184
|
+
// Add toLowerCase formatter.
|
|
185
|
+
i18next.services.formatter?.add("toLowerCase", toLowerCase);
|
|
173
186
|
});
|
|
174
187
|
}
|
|
175
188
|
|