ai-localize-locale-engine 3.0.0 → 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/CHANGELOG.md +7 -0
- package/dist/index.d.mts +29 -2
- package/dist/index.d.ts +29 -2
- package/dist/index.js +8 -4
- package/dist/index.mjs +8 -4
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# ai-localize-locale-engine
|
|
2
2
|
|
|
3
|
+
## 3.1.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- **`copyDefaultValues` option in `LocaleExtractor`** — Added `copyDefaultValues?: boolean` to `ExtractOptions`. When `true`, target language locale files are pre-populated with the default language's source text values instead of empty strings. Defaults to `false` for backward compatibility.
|
|
8
|
+
- **`copyDefaultValues` option in `LocaleSynchronizer`** — Added `SyncOptions` interface with `copyDefaultValues?: boolean`. When `true`, newly added keys in target language files are seeded from the default language file instead of using empty strings.
|
|
9
|
+
|
|
3
10
|
## 3.0.0
|
|
4
11
|
|
|
5
12
|
### Major Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -24,6 +24,18 @@ interface ExtractOptions {
|
|
|
24
24
|
* }
|
|
25
25
|
*/
|
|
26
26
|
staticKeys?: Record<string, string>;
|
|
27
|
+
/**
|
|
28
|
+
* When `true`, target language locale files are pre-populated with the same
|
|
29
|
+
* source text values as the default language instead of empty strings.
|
|
30
|
+
*
|
|
31
|
+
* This ensures the app always has a visible fallback value while translators
|
|
32
|
+
* work on proper translations. Empty-string values cause the UI to show
|
|
33
|
+
* nothing at all for untranslated keys.
|
|
34
|
+
*
|
|
35
|
+
* Defaults to `false` to preserve backward-compatible behaviour (empty
|
|
36
|
+
* strings for target languages).
|
|
37
|
+
*/
|
|
38
|
+
copyDefaultValues?: boolean;
|
|
27
39
|
}
|
|
28
40
|
interface ExtractionResult {
|
|
29
41
|
localeFiles: LocaleFile[];
|
|
@@ -88,14 +100,29 @@ declare function deduplicateTexts(texts: DetectedText[]): DetectedText[];
|
|
|
88
100
|
declare function filterAlreadyTranslated(texts: DetectedText[], existingKeys: Set<string>): DetectedText[];
|
|
89
101
|
declare function findUnusedKeys(localeKeys: string[], sourceKeys: string[]): string[];
|
|
90
102
|
|
|
103
|
+
interface SyncOptions {
|
|
104
|
+
/**
|
|
105
|
+
* When `true`, newly added keys in target language files are pre-populated
|
|
106
|
+
* with the same source text value from the default language file instead of
|
|
107
|
+
* an empty string.
|
|
108
|
+
*
|
|
109
|
+
* This ensures the app always has a visible fallback value while translators
|
|
110
|
+
* work on proper translations. Empty-string values cause the UI to show
|
|
111
|
+
* nothing at all for untranslated keys.
|
|
112
|
+
*
|
|
113
|
+
* Defaults to `false` to preserve backward-compatible behaviour.
|
|
114
|
+
*/
|
|
115
|
+
copyDefaultValues?: boolean;
|
|
116
|
+
}
|
|
91
117
|
declare class LocaleSynchronizer {
|
|
92
118
|
private localesDir;
|
|
93
119
|
private defaultLanguage;
|
|
94
|
-
|
|
120
|
+
private options;
|
|
121
|
+
constructor(localesDir: string, defaultLanguage?: string, options?: SyncOptions);
|
|
95
122
|
sync(): {
|
|
96
123
|
updated: string[];
|
|
97
124
|
addedKeys: number;
|
|
98
125
|
};
|
|
99
126
|
}
|
|
100
127
|
|
|
101
|
-
export { type ExtractOptions, type ExtractionResult, LocaleExtractor, LocaleSynchronizer, LocaleWriter, type WriteOptions, deduplicateTexts, filterAlreadyTranslated, findUnusedKeys };
|
|
128
|
+
export { type ExtractOptions, type ExtractionResult, LocaleExtractor, LocaleSynchronizer, LocaleWriter, type SyncOptions, type WriteOptions, deduplicateTexts, filterAlreadyTranslated, findUnusedKeys };
|
package/dist/index.d.ts
CHANGED
|
@@ -24,6 +24,18 @@ interface ExtractOptions {
|
|
|
24
24
|
* }
|
|
25
25
|
*/
|
|
26
26
|
staticKeys?: Record<string, string>;
|
|
27
|
+
/**
|
|
28
|
+
* When `true`, target language locale files are pre-populated with the same
|
|
29
|
+
* source text values as the default language instead of empty strings.
|
|
30
|
+
*
|
|
31
|
+
* This ensures the app always has a visible fallback value while translators
|
|
32
|
+
* work on proper translations. Empty-string values cause the UI to show
|
|
33
|
+
* nothing at all for untranslated keys.
|
|
34
|
+
*
|
|
35
|
+
* Defaults to `false` to preserve backward-compatible behaviour (empty
|
|
36
|
+
* strings for target languages).
|
|
37
|
+
*/
|
|
38
|
+
copyDefaultValues?: boolean;
|
|
27
39
|
}
|
|
28
40
|
interface ExtractionResult {
|
|
29
41
|
localeFiles: LocaleFile[];
|
|
@@ -88,14 +100,29 @@ declare function deduplicateTexts(texts: DetectedText[]): DetectedText[];
|
|
|
88
100
|
declare function filterAlreadyTranslated(texts: DetectedText[], existingKeys: Set<string>): DetectedText[];
|
|
89
101
|
declare function findUnusedKeys(localeKeys: string[], sourceKeys: string[]): string[];
|
|
90
102
|
|
|
103
|
+
interface SyncOptions {
|
|
104
|
+
/**
|
|
105
|
+
* When `true`, newly added keys in target language files are pre-populated
|
|
106
|
+
* with the same source text value from the default language file instead of
|
|
107
|
+
* an empty string.
|
|
108
|
+
*
|
|
109
|
+
* This ensures the app always has a visible fallback value while translators
|
|
110
|
+
* work on proper translations. Empty-string values cause the UI to show
|
|
111
|
+
* nothing at all for untranslated keys.
|
|
112
|
+
*
|
|
113
|
+
* Defaults to `false` to preserve backward-compatible behaviour.
|
|
114
|
+
*/
|
|
115
|
+
copyDefaultValues?: boolean;
|
|
116
|
+
}
|
|
91
117
|
declare class LocaleSynchronizer {
|
|
92
118
|
private localesDir;
|
|
93
119
|
private defaultLanguage;
|
|
94
|
-
|
|
120
|
+
private options;
|
|
121
|
+
constructor(localesDir: string, defaultLanguage?: string, options?: SyncOptions);
|
|
95
122
|
sync(): {
|
|
96
123
|
updated: string[];
|
|
97
124
|
addedKeys: number;
|
|
98
125
|
};
|
|
99
126
|
}
|
|
100
127
|
|
|
101
|
-
export { type ExtractOptions, type ExtractionResult, LocaleExtractor, LocaleSynchronizer, LocaleWriter, type WriteOptions, deduplicateTexts, filterAlreadyTranslated, findUnusedKeys };
|
|
128
|
+
export { type ExtractOptions, type ExtractionResult, LocaleExtractor, LocaleSynchronizer, LocaleWriter, type SyncOptions, type WriteOptions, deduplicateTexts, filterAlreadyTranslated, findUnusedKeys };
|
package/dist/index.js
CHANGED
|
@@ -48,7 +48,8 @@ var LocaleExtractor = class {
|
|
|
48
48
|
defaultLanguage: options.defaultLanguage || "en",
|
|
49
49
|
targetLanguages: options.targetLanguages || [],
|
|
50
50
|
namespaceSplitting: options.namespaceSplitting ?? true,
|
|
51
|
-
staticKeys: options.staticKeys ?? {}
|
|
51
|
+
staticKeys: options.staticKeys ?? {},
|
|
52
|
+
copyDefaultValues: options.copyDefaultValues ?? false
|
|
52
53
|
};
|
|
53
54
|
}
|
|
54
55
|
extract(detectedTexts) {
|
|
@@ -91,7 +92,7 @@ var LocaleExtractor = class {
|
|
|
91
92
|
for (const lang of allLanguages) {
|
|
92
93
|
for (const [namespace, entries] of namespaceMap) {
|
|
93
94
|
const isDefault = lang === this.options.defaultLanguage;
|
|
94
|
-
const langEntries = isDefault ? { ...entries } : Object.fromEntries(Object.keys(entries).map((k) => [k, ""]));
|
|
95
|
+
const langEntries = isDefault || this.options.copyDefaultValues ? { ...entries } : Object.fromEntries(Object.keys(entries).map((k) => [k, ""]));
|
|
95
96
|
localeFiles.push({ language: lang, namespace, entries: langEntries, filePath: "" });
|
|
96
97
|
}
|
|
97
98
|
}
|
|
@@ -235,15 +236,18 @@ var fs = __toESM(require("fs"));
|
|
|
235
236
|
var path2 = __toESM(require("path"));
|
|
236
237
|
var import_ai_localize_shared3 = require("ai-localize-shared");
|
|
237
238
|
var LocaleSynchronizer = class {
|
|
238
|
-
constructor(localesDir, defaultLanguage = "en") {
|
|
239
|
+
constructor(localesDir, defaultLanguage = "en", options = {}) {
|
|
239
240
|
this.localesDir = localesDir;
|
|
240
241
|
this.defaultLanguage = defaultLanguage;
|
|
242
|
+
this.options = options;
|
|
241
243
|
}
|
|
242
244
|
localesDir;
|
|
243
245
|
defaultLanguage;
|
|
246
|
+
options;
|
|
244
247
|
sync() {
|
|
245
248
|
const updated = [];
|
|
246
249
|
let addedKeys = 0;
|
|
250
|
+
const copyDefaultValues = this.options.copyDefaultValues ?? false;
|
|
247
251
|
const defaultDir = path2.join(this.localesDir, this.defaultLanguage);
|
|
248
252
|
if (!fs.existsSync(defaultDir)) return { updated, addedKeys };
|
|
249
253
|
const defaultFiles = fs.readdirSync(defaultDir).filter((f) => f.endsWith(".json"));
|
|
@@ -258,7 +262,7 @@ var LocaleSynchronizer = class {
|
|
|
258
262
|
let changed = false;
|
|
259
263
|
for (const key of Object.keys(defaultEntries)) {
|
|
260
264
|
if (!(key in existing)) {
|
|
261
|
-
existing[key] = "";
|
|
265
|
+
existing[key] = copyDefaultValues ? defaultEntries[key] ?? "" : "";
|
|
262
266
|
addedKeys++;
|
|
263
267
|
changed = true;
|
|
264
268
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -11,7 +11,8 @@ var LocaleExtractor = class {
|
|
|
11
11
|
defaultLanguage: options.defaultLanguage || "en",
|
|
12
12
|
targetLanguages: options.targetLanguages || [],
|
|
13
13
|
namespaceSplitting: options.namespaceSplitting ?? true,
|
|
14
|
-
staticKeys: options.staticKeys ?? {}
|
|
14
|
+
staticKeys: options.staticKeys ?? {},
|
|
15
|
+
copyDefaultValues: options.copyDefaultValues ?? false
|
|
15
16
|
};
|
|
16
17
|
}
|
|
17
18
|
extract(detectedTexts) {
|
|
@@ -54,7 +55,7 @@ var LocaleExtractor = class {
|
|
|
54
55
|
for (const lang of allLanguages) {
|
|
55
56
|
for (const [namespace, entries] of namespaceMap) {
|
|
56
57
|
const isDefault = lang === this.options.defaultLanguage;
|
|
57
|
-
const langEntries = isDefault ? { ...entries } : Object.fromEntries(Object.keys(entries).map((k) => [k, ""]));
|
|
58
|
+
const langEntries = isDefault || this.options.copyDefaultValues ? { ...entries } : Object.fromEntries(Object.keys(entries).map((k) => [k, ""]));
|
|
58
59
|
localeFiles.push({ language: lang, namespace, entries: langEntries, filePath: "" });
|
|
59
60
|
}
|
|
60
61
|
}
|
|
@@ -198,15 +199,18 @@ import * as fs from "fs";
|
|
|
198
199
|
import * as path2 from "path";
|
|
199
200
|
import { readJsonSafe as readJsonSafe2, writeJson as writeJson2, ensureDir as ensureDir2 } from "ai-localize-shared";
|
|
200
201
|
var LocaleSynchronizer = class {
|
|
201
|
-
constructor(localesDir, defaultLanguage = "en") {
|
|
202
|
+
constructor(localesDir, defaultLanguage = "en", options = {}) {
|
|
202
203
|
this.localesDir = localesDir;
|
|
203
204
|
this.defaultLanguage = defaultLanguage;
|
|
205
|
+
this.options = options;
|
|
204
206
|
}
|
|
205
207
|
localesDir;
|
|
206
208
|
defaultLanguage;
|
|
209
|
+
options;
|
|
207
210
|
sync() {
|
|
208
211
|
const updated = [];
|
|
209
212
|
let addedKeys = 0;
|
|
213
|
+
const copyDefaultValues = this.options.copyDefaultValues ?? false;
|
|
210
214
|
const defaultDir = path2.join(this.localesDir, this.defaultLanguage);
|
|
211
215
|
if (!fs.existsSync(defaultDir)) return { updated, addedKeys };
|
|
212
216
|
const defaultFiles = fs.readdirSync(defaultDir).filter((f) => f.endsWith(".json"));
|
|
@@ -221,7 +225,7 @@ var LocaleSynchronizer = class {
|
|
|
221
225
|
let changed = false;
|
|
222
226
|
for (const key of Object.keys(defaultEntries)) {
|
|
223
227
|
if (!(key in existing)) {
|
|
224
|
-
existing[key] = "";
|
|
228
|
+
existing[key] = copyDefaultValues ? defaultEntries[key] ?? "" : "";
|
|
225
229
|
addedKeys++;
|
|
226
230
|
changed = true;
|
|
227
231
|
}
|