@langapi/mcp-server 1.0.6 → 1.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/handlers/index.d.ts +7 -0
- package/dist/handlers/index.d.ts.map +1 -0
- package/dist/handlers/index.js +7 -0
- package/dist/handlers/index.js.map +1 -0
- package/dist/handlers/xcstrings-sync-handler.d.ts +72 -0
- package/dist/handlers/xcstrings-sync-handler.d.ts.map +1 -0
- package/dist/handlers/xcstrings-sync-handler.js +126 -0
- package/dist/handlers/xcstrings-sync-handler.js.map +1 -0
- package/dist/locale-detection/index.d.ts.map +1 -1
- package/dist/locale-detection/index.js +80 -7
- package/dist/locale-detection/index.js.map +1 -1
- package/dist/locale-detection/patterns.d.ts.map +1 -1
- package/dist/locale-detection/patterns.js +45 -0
- package/dist/locale-detection/patterns.js.map +1 -1
- package/dist/tools/get-translation-status.d.ts.map +1 -1
- package/dist/tools/get-translation-status.js +34 -6
- package/dist/tools/get-translation-status.js.map +1 -1
- package/dist/tools/list-local-locales.d.ts +1 -1
- package/dist/tools/list-local-locales.js +2 -2
- package/dist/tools/list-local-locales.js.map +1 -1
- package/dist/tools/sync-translations.d.ts.map +1 -1
- package/dist/tools/sync-translations.js +228 -42
- package/dist/tools/sync-translations.js.map +1 -1
- package/dist/utils/apple-common.d.ts +63 -0
- package/dist/utils/apple-common.d.ts.map +1 -0
- package/dist/utils/apple-common.js +118 -0
- package/dist/utils/apple-common.js.map +1 -0
- package/dist/utils/apple-common.test.d.ts +2 -0
- package/dist/utils/apple-common.test.d.ts.map +1 -0
- package/dist/utils/apple-common.test.js +108 -0
- package/dist/utils/apple-common.test.js.map +1 -0
- package/dist/utils/arb-parser.d.ts +77 -0
- package/dist/utils/arb-parser.d.ts.map +1 -0
- package/dist/utils/arb-parser.js +142 -0
- package/dist/utils/arb-parser.js.map +1 -0
- package/dist/utils/arb-parser.test.d.ts +2 -0
- package/dist/utils/arb-parser.test.d.ts.map +1 -0
- package/dist/utils/arb-parser.test.js +243 -0
- package/dist/utils/arb-parser.test.js.map +1 -0
- package/dist/utils/strings-parser.d.ts +62 -0
- package/dist/utils/strings-parser.d.ts.map +1 -0
- package/dist/utils/strings-parser.js +276 -0
- package/dist/utils/strings-parser.js.map +1 -0
- package/dist/utils/strings-parser.test.d.ts +2 -0
- package/dist/utils/strings-parser.test.d.ts.map +1 -0
- package/dist/utils/strings-parser.test.js +143 -0
- package/dist/utils/strings-parser.test.js.map +1 -0
- package/dist/utils/stringsdict-parser.d.ts +106 -0
- package/dist/utils/stringsdict-parser.d.ts.map +1 -0
- package/dist/utils/stringsdict-parser.js +473 -0
- package/dist/utils/stringsdict-parser.js.map +1 -0
- package/dist/utils/stringsdict-parser.test.d.ts +2 -0
- package/dist/utils/stringsdict-parser.test.d.ts.map +1 -0
- package/dist/utils/stringsdict-parser.test.js +244 -0
- package/dist/utils/stringsdict-parser.test.js.map +1 -0
- package/dist/utils/xcstrings-parser.d.ts +128 -0
- package/dist/utils/xcstrings-parser.d.ts.map +1 -0
- package/dist/utils/xcstrings-parser.js +216 -0
- package/dist/utils/xcstrings-parser.js.map +1 -0
- package/dist/utils/xcstrings-parser.test.d.ts +2 -0
- package/dist/utils/xcstrings-parser.test.d.ts.map +1 -0
- package/dist/utils/xcstrings-parser.test.js +157 -0
- package/dist/utils/xcstrings-parser.test.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { isArbFile, isArbMetadataKey, isArbLocaleKey, parseArbContent, reconstructArbContent, mergeArbContent, getLocaleFileExtension, } from "./arb-parser.js";
|
|
3
|
+
describe("ARB Parser", () => {
|
|
4
|
+
describe("isArbFile", () => {
|
|
5
|
+
it("should return true for .arb files", () => {
|
|
6
|
+
expect(isArbFile("lib/l10n/app_en.arb")).toBe(true);
|
|
7
|
+
expect(isArbFile("/absolute/path/to/intl_de.arb")).toBe(true);
|
|
8
|
+
expect(isArbFile("simple.arb")).toBe(true);
|
|
9
|
+
});
|
|
10
|
+
it("should return false for non-ARB files", () => {
|
|
11
|
+
expect(isArbFile("locales/en.json")).toBe(false);
|
|
12
|
+
expect(isArbFile("file.arb.json")).toBe(false);
|
|
13
|
+
expect(isArbFile("file.txt")).toBe(false);
|
|
14
|
+
});
|
|
15
|
+
it("should be case-insensitive", () => {
|
|
16
|
+
expect(isArbFile("file.ARB")).toBe(true);
|
|
17
|
+
expect(isArbFile("file.Arb")).toBe(true);
|
|
18
|
+
expect(isArbFile("FILE.ARB")).toBe(true);
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
describe("getLocaleFileExtension", () => {
|
|
22
|
+
it("should return .arb for ARB files", () => {
|
|
23
|
+
expect(getLocaleFileExtension("app_en.arb")).toBe(".arb");
|
|
24
|
+
expect(getLocaleFileExtension("file.ARB")).toBe(".arb");
|
|
25
|
+
});
|
|
26
|
+
it("should return .json for non-ARB files", () => {
|
|
27
|
+
expect(getLocaleFileExtension("en.json")).toBe(".json");
|
|
28
|
+
expect(getLocaleFileExtension("file.txt")).toBe(".json");
|
|
29
|
+
expect(getLocaleFileExtension("noextension")).toBe(".json");
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
describe("isArbMetadataKey", () => {
|
|
33
|
+
it("should return true for @ prefixed keys", () => {
|
|
34
|
+
expect(isArbMetadataKey("@greeting")).toBe(true);
|
|
35
|
+
expect(isArbMetadataKey("@@locale")).toBe(true);
|
|
36
|
+
expect(isArbMetadataKey("@")).toBe(true);
|
|
37
|
+
});
|
|
38
|
+
it("should return false for regular keys", () => {
|
|
39
|
+
expect(isArbMetadataKey("greeting")).toBe(false);
|
|
40
|
+
expect(isArbMetadataKey("hello_world")).toBe(false);
|
|
41
|
+
expect(isArbMetadataKey("")).toBe(false);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
describe("isArbLocaleKey", () => {
|
|
45
|
+
it("should return true for @@locale", () => {
|
|
46
|
+
expect(isArbLocaleKey("@@locale")).toBe(true);
|
|
47
|
+
});
|
|
48
|
+
it("should return false for other keys", () => {
|
|
49
|
+
expect(isArbLocaleKey("@locale")).toBe(false);
|
|
50
|
+
expect(isArbLocaleKey("@@other")).toBe(false);
|
|
51
|
+
expect(isArbLocaleKey("locale")).toBe(false);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
describe("parseArbContent", () => {
|
|
55
|
+
it("should separate translatable keys from metadata", () => {
|
|
56
|
+
const arbData = {
|
|
57
|
+
"@@locale": "en",
|
|
58
|
+
greeting: "Hello, {name}!",
|
|
59
|
+
"@greeting": {
|
|
60
|
+
description: "A greeting message",
|
|
61
|
+
placeholders: {
|
|
62
|
+
name: { type: "String" },
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
farewell: "Goodbye!",
|
|
66
|
+
};
|
|
67
|
+
const result = parseArbContent(arbData);
|
|
68
|
+
expect(result.locale).toBe("en");
|
|
69
|
+
expect(result.translatableKeys).toEqual([
|
|
70
|
+
{ key: "greeting", value: "Hello, {name}!" },
|
|
71
|
+
{ key: "farewell", value: "Goodbye!" },
|
|
72
|
+
]);
|
|
73
|
+
expect(result.metadata["@@locale"]).toBe("en");
|
|
74
|
+
expect(result.metadata["@greeting"]).toEqual({
|
|
75
|
+
description: "A greeting message",
|
|
76
|
+
placeholders: {
|
|
77
|
+
name: { type: "String" },
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
it("should handle ARB files without metadata", () => {
|
|
82
|
+
const arbData = {
|
|
83
|
+
"@@locale": "en",
|
|
84
|
+
hello: "Hello",
|
|
85
|
+
world: "World",
|
|
86
|
+
};
|
|
87
|
+
const result = parseArbContent(arbData);
|
|
88
|
+
expect(result.locale).toBe("en");
|
|
89
|
+
expect(result.translatableKeys).toHaveLength(2);
|
|
90
|
+
expect(Object.keys(result.metadata)).toEqual(["@@locale"]);
|
|
91
|
+
});
|
|
92
|
+
it("should handle ARB files without @@locale", () => {
|
|
93
|
+
const arbData = {
|
|
94
|
+
greeting: "Hello",
|
|
95
|
+
"@greeting": { description: "A greeting" },
|
|
96
|
+
};
|
|
97
|
+
const result = parseArbContent(arbData);
|
|
98
|
+
expect(result.locale).toBeNull();
|
|
99
|
+
expect(result.translatableKeys).toEqual([{ key: "greeting", value: "Hello" }]);
|
|
100
|
+
expect(result.metadata["@greeting"]).toEqual({ description: "A greeting" });
|
|
101
|
+
});
|
|
102
|
+
it("should skip non-string translatable values", () => {
|
|
103
|
+
const arbData = {
|
|
104
|
+
"@@locale": "en",
|
|
105
|
+
validString: "Hello",
|
|
106
|
+
invalidNumber: 123,
|
|
107
|
+
invalidObject: { nested: "value" },
|
|
108
|
+
"@validString": { description: "Valid" },
|
|
109
|
+
};
|
|
110
|
+
const result = parseArbContent(arbData);
|
|
111
|
+
expect(result.translatableKeys).toEqual([{ key: "validString", value: "Hello" }]);
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
describe("reconstructArbContent", () => {
|
|
115
|
+
it("should reconstruct ARB with updated locale and preserved metadata", () => {
|
|
116
|
+
const translations = [
|
|
117
|
+
{ key: "greeting", value: "Hallo, {name}!" },
|
|
118
|
+
{ key: "farewell", value: "Auf Wiedersehen!" },
|
|
119
|
+
];
|
|
120
|
+
const metadata = {
|
|
121
|
+
"@@locale": "en",
|
|
122
|
+
"@greeting": { description: "A greeting message" },
|
|
123
|
+
};
|
|
124
|
+
const result = reconstructArbContent(translations, metadata, "de");
|
|
125
|
+
expect(result["@@locale"]).toBe("de");
|
|
126
|
+
expect(result["greeting"]).toBe("Hallo, {name}!");
|
|
127
|
+
expect(result["@greeting"]).toEqual({ description: "A greeting message" });
|
|
128
|
+
expect(result["farewell"]).toBe("Auf Wiedersehen!");
|
|
129
|
+
// farewell has no metadata, so @farewell should not exist
|
|
130
|
+
expect(result["@farewell"]).toBeUndefined();
|
|
131
|
+
});
|
|
132
|
+
it("should maintain key order: @@locale first, then key-metadata pairs", () => {
|
|
133
|
+
const translations = [
|
|
134
|
+
{ key: "alpha", value: "Alpha" },
|
|
135
|
+
{ key: "beta", value: "Beta" },
|
|
136
|
+
];
|
|
137
|
+
const metadata = {
|
|
138
|
+
"@@locale": "en",
|
|
139
|
+
"@alpha": { description: "First" },
|
|
140
|
+
"@beta": { description: "Second" },
|
|
141
|
+
};
|
|
142
|
+
const result = reconstructArbContent(translations, metadata, "fr");
|
|
143
|
+
const keys = Object.keys(result);
|
|
144
|
+
expect(keys[0]).toBe("@@locale");
|
|
145
|
+
expect(keys[1]).toBe("alpha");
|
|
146
|
+
expect(keys[2]).toBe("@alpha");
|
|
147
|
+
expect(keys[3]).toBe("beta");
|
|
148
|
+
expect(keys[4]).toBe("@beta");
|
|
149
|
+
});
|
|
150
|
+
it("should handle empty metadata", () => {
|
|
151
|
+
const translations = [{ key: "hello", value: "Bonjour" }];
|
|
152
|
+
const metadata = { "@@locale": "en" };
|
|
153
|
+
const result = reconstructArbContent(translations, metadata, "fr");
|
|
154
|
+
expect(result["@@locale"]).toBe("fr");
|
|
155
|
+
expect(result["hello"]).toBe("Bonjour");
|
|
156
|
+
expect(Object.keys(result)).toHaveLength(2);
|
|
157
|
+
});
|
|
158
|
+
});
|
|
159
|
+
describe("mergeArbContent", () => {
|
|
160
|
+
it("should merge new translations with existing content", () => {
|
|
161
|
+
const existingContent = {
|
|
162
|
+
"@@locale": "de",
|
|
163
|
+
greeting: "Hallo",
|
|
164
|
+
"@greeting": { description: "A greeting" },
|
|
165
|
+
farewell: "Tschüss",
|
|
166
|
+
};
|
|
167
|
+
const newTranslations = [
|
|
168
|
+
{ key: "greeting", value: "Hallo, {name}!" }, // Updated
|
|
169
|
+
];
|
|
170
|
+
const sourceMetadata = {
|
|
171
|
+
"@@locale": "en",
|
|
172
|
+
"@greeting": { description: "A greeting message" },
|
|
173
|
+
"@farewell": { description: "A farewell" },
|
|
174
|
+
};
|
|
175
|
+
const sourceKeys = new Set(["greeting", "farewell"]);
|
|
176
|
+
const result = mergeArbContent(existingContent, newTranslations, sourceMetadata, sourceKeys, "de");
|
|
177
|
+
expect(result["@@locale"]).toBe("de");
|
|
178
|
+
expect(result["greeting"]).toBe("Hallo, {name}!"); // New translation
|
|
179
|
+
expect(result["farewell"]).toBe("Tschüss"); // Preserved existing
|
|
180
|
+
expect(result["@greeting"]).toEqual({ description: "A greeting message" }); // Source metadata
|
|
181
|
+
expect(result["@farewell"]).toEqual({ description: "A farewell" }); // Source metadata
|
|
182
|
+
});
|
|
183
|
+
it("should remove keys not in source", () => {
|
|
184
|
+
const existingContent = {
|
|
185
|
+
"@@locale": "de",
|
|
186
|
+
greeting: "Hallo",
|
|
187
|
+
oldKey: "Should be removed",
|
|
188
|
+
};
|
|
189
|
+
const newTranslations = [];
|
|
190
|
+
const sourceMetadata = { "@@locale": "en" };
|
|
191
|
+
const sourceKeys = new Set(["greeting"]); // oldKey not in source
|
|
192
|
+
const result = mergeArbContent(existingContent, newTranslations, sourceMetadata, sourceKeys, "de");
|
|
193
|
+
expect(result["greeting"]).toBe("Hallo");
|
|
194
|
+
expect(result["oldKey"]).toBeUndefined(); // Removed
|
|
195
|
+
});
|
|
196
|
+
it("should handle empty existing content", () => {
|
|
197
|
+
const existingContent = {};
|
|
198
|
+
const newTranslations = [
|
|
199
|
+
{ key: "hello", value: "Bonjour" },
|
|
200
|
+
{ key: "world", value: "Monde" },
|
|
201
|
+
];
|
|
202
|
+
const sourceMetadata = {
|
|
203
|
+
"@@locale": "en",
|
|
204
|
+
"@hello": { description: "Hello message" },
|
|
205
|
+
};
|
|
206
|
+
const sourceKeys = new Set(["hello", "world"]);
|
|
207
|
+
const result = mergeArbContent(existingContent, newTranslations, sourceMetadata, sourceKeys, "fr");
|
|
208
|
+
expect(result["@@locale"]).toBe("fr");
|
|
209
|
+
expect(result["hello"]).toBe("Bonjour");
|
|
210
|
+
expect(result["world"]).toBe("Monde");
|
|
211
|
+
expect(result["@hello"]).toEqual({ description: "Hello message" });
|
|
212
|
+
});
|
|
213
|
+
it("should preserve existing translations when no new translations provided", () => {
|
|
214
|
+
const existingContent = {
|
|
215
|
+
"@@locale": "de",
|
|
216
|
+
greeting: "Hallo",
|
|
217
|
+
farewell: "Tschüss",
|
|
218
|
+
};
|
|
219
|
+
const newTranslations = [];
|
|
220
|
+
const sourceMetadata = { "@@locale": "en" };
|
|
221
|
+
const sourceKeys = new Set(["greeting", "farewell"]);
|
|
222
|
+
const result = mergeArbContent(existingContent, newTranslations, sourceMetadata, sourceKeys, "de");
|
|
223
|
+
expect(result["greeting"]).toBe("Hallo");
|
|
224
|
+
expect(result["farewell"]).toBe("Tschüss");
|
|
225
|
+
});
|
|
226
|
+
it("should use source metadata instead of existing metadata", () => {
|
|
227
|
+
const existingContent = {
|
|
228
|
+
"@@locale": "de",
|
|
229
|
+
greeting: "Hallo",
|
|
230
|
+
"@greeting": { description: "Old description" },
|
|
231
|
+
};
|
|
232
|
+
const newTranslations = [];
|
|
233
|
+
const sourceMetadata = {
|
|
234
|
+
"@@locale": "en",
|
|
235
|
+
"@greeting": { description: "New description from source" },
|
|
236
|
+
};
|
|
237
|
+
const sourceKeys = new Set(["greeting"]);
|
|
238
|
+
const result = mergeArbContent(existingContent, newTranslations, sourceMetadata, sourceKeys, "de");
|
|
239
|
+
expect(result["@greeting"]).toEqual({ description: "New description from source" });
|
|
240
|
+
});
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
//# sourceMappingURL=arb-parser.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"arb-parser.test.js","sourceRoot":"","sources":["../../src/utils/arb-parser.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Localizable.strings file parser
|
|
3
|
+
*
|
|
4
|
+
* Handles Apple's traditional localization format:
|
|
5
|
+
* - Key-value pairs: "key" = "value";
|
|
6
|
+
* - Comments: block and line comments
|
|
7
|
+
* - Escaped characters: quotes, newlines, tabs, backslashes, Unicode
|
|
8
|
+
*/
|
|
9
|
+
import type { KeyValue } from "../api/types.js";
|
|
10
|
+
/**
|
|
11
|
+
* Parsed content from a .strings file
|
|
12
|
+
*/
|
|
13
|
+
export interface StringsContent {
|
|
14
|
+
/** Key-value translation pairs */
|
|
15
|
+
entries: KeyValue[];
|
|
16
|
+
/** Comments associated with keys (key -> comment text) */
|
|
17
|
+
comments: Map<string, string>;
|
|
18
|
+
/** File-level header comment (at top of file) */
|
|
19
|
+
headerComment: string | null;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Parse a Localizable.strings file content
|
|
23
|
+
*
|
|
24
|
+
* Handles:
|
|
25
|
+
* - Basic key-value pairs: "key" = "value";
|
|
26
|
+
* - Block comments above entries for descriptions
|
|
27
|
+
* - Escaped quotes and special characters
|
|
28
|
+
* - Multi-line values
|
|
29
|
+
*
|
|
30
|
+
* @param content Raw file content
|
|
31
|
+
* @returns Parsed content with entries, comments, and header
|
|
32
|
+
*/
|
|
33
|
+
export declare function parseStringsContent(content: string): StringsContent;
|
|
34
|
+
/**
|
|
35
|
+
* Escape a string for use in a .strings file
|
|
36
|
+
*/
|
|
37
|
+
export declare function escapeStringsValue(value: string): string;
|
|
38
|
+
/**
|
|
39
|
+
* Reconstruct a .strings file from parsed content
|
|
40
|
+
*
|
|
41
|
+
* @param entries Translation key-value pairs
|
|
42
|
+
* @param comments Comments to associate with keys
|
|
43
|
+
* @param headerComment Optional file-level header comment
|
|
44
|
+
* @returns Formatted .strings file content
|
|
45
|
+
*/
|
|
46
|
+
export declare function reconstructStringsContent(entries: KeyValue[], comments: Map<string, string>, headerComment: string | null): string;
|
|
47
|
+
/**
|
|
48
|
+
* Merge new translations into existing .strings content
|
|
49
|
+
*
|
|
50
|
+
* - Preserves existing translations not in newTranslations
|
|
51
|
+
* - Updates with new translations
|
|
52
|
+
* - Removes keys not in sourceKeys
|
|
53
|
+
* - Preserves comments from source
|
|
54
|
+
*
|
|
55
|
+
* @param existingContent Existing target file content (raw string)
|
|
56
|
+
* @param newTranslations New/updated translations from API
|
|
57
|
+
* @param sourceComments Comments from source file
|
|
58
|
+
* @param sourceKeys Set of all keys in source file
|
|
59
|
+
* @returns Merged .strings file content
|
|
60
|
+
*/
|
|
61
|
+
export declare function mergeStringsContent(existingContent: string, newTranslations: KeyValue[], sourceComments: Map<string, string>, sourceKeys: Set<string>): string;
|
|
62
|
+
//# sourceMappingURL=strings-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strings-parser.d.ts","sourceRoot":"","sources":["../../src/utils/strings-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,kCAAkC;IAClC,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB,0DAA0D;IAC1D,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,iDAAiD;IACjD,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAmInE;AA2ED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOxD;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,QAAQ,EAAE,EACnB,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAC7B,aAAa,EAAE,MAAM,GAAG,IAAI,GAC3B,MAAM,CAoBR;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CACjC,eAAe,EAAE,MAAM,EACvB,eAAe,EAAE,QAAQ,EAAE,EAC3B,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EACnC,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,GACtB,MAAM,CA8BR"}
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Localizable.strings file parser
|
|
3
|
+
*
|
|
4
|
+
* Handles Apple's traditional localization format:
|
|
5
|
+
* - Key-value pairs: "key" = "value";
|
|
6
|
+
* - Comments: block and line comments
|
|
7
|
+
* - Escaped characters: quotes, newlines, tabs, backslashes, Unicode
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Parse a Localizable.strings file content
|
|
11
|
+
*
|
|
12
|
+
* Handles:
|
|
13
|
+
* - Basic key-value pairs: "key" = "value";
|
|
14
|
+
* - Block comments above entries for descriptions
|
|
15
|
+
* - Escaped quotes and special characters
|
|
16
|
+
* - Multi-line values
|
|
17
|
+
*
|
|
18
|
+
* @param content Raw file content
|
|
19
|
+
* @returns Parsed content with entries, comments, and header
|
|
20
|
+
*/
|
|
21
|
+
export function parseStringsContent(content) {
|
|
22
|
+
const entries = [];
|
|
23
|
+
const comments = new Map();
|
|
24
|
+
let headerComment = null;
|
|
25
|
+
// Track current position
|
|
26
|
+
let pos = 0;
|
|
27
|
+
let pendingComment = null;
|
|
28
|
+
let isFirstEntry = true;
|
|
29
|
+
while (pos < content.length) {
|
|
30
|
+
// Skip whitespace
|
|
31
|
+
while (pos < content.length && /\s/.test(content[pos])) {
|
|
32
|
+
pos++;
|
|
33
|
+
}
|
|
34
|
+
if (pos >= content.length)
|
|
35
|
+
break;
|
|
36
|
+
// Check for block comment /* ... */
|
|
37
|
+
if (content.slice(pos, pos + 2) === "/*") {
|
|
38
|
+
const commentEnd = content.indexOf("*/", pos + 2);
|
|
39
|
+
if (commentEnd === -1) {
|
|
40
|
+
// Unterminated comment, skip to end
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
const commentText = content.slice(pos + 2, commentEnd).trim();
|
|
44
|
+
pendingComment = commentText;
|
|
45
|
+
pos = commentEnd + 2;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
// Check for line comment // ...
|
|
49
|
+
if (content.slice(pos, pos + 2) === "//") {
|
|
50
|
+
const lineEnd = content.indexOf("\n", pos);
|
|
51
|
+
const commentText = lineEnd === -1
|
|
52
|
+
? content.slice(pos + 2).trim()
|
|
53
|
+
: content.slice(pos + 2, lineEnd).trim();
|
|
54
|
+
pendingComment = commentText;
|
|
55
|
+
pos = lineEnd === -1 ? content.length : lineEnd + 1;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
// Check for quoted key
|
|
59
|
+
if (content[pos] === '"') {
|
|
60
|
+
const keyResult = parseQuotedString(content, pos);
|
|
61
|
+
if (!keyResult) {
|
|
62
|
+
// Malformed, skip character
|
|
63
|
+
pos++;
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
const key = keyResult.value;
|
|
67
|
+
pos = keyResult.end;
|
|
68
|
+
// Skip whitespace
|
|
69
|
+
while (pos < content.length && /\s/.test(content[pos])) {
|
|
70
|
+
pos++;
|
|
71
|
+
}
|
|
72
|
+
// Expect '='
|
|
73
|
+
if (content[pos] !== "=") {
|
|
74
|
+
// Malformed, continue
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
pos++;
|
|
78
|
+
// Skip whitespace
|
|
79
|
+
while (pos < content.length && /\s/.test(content[pos])) {
|
|
80
|
+
pos++;
|
|
81
|
+
}
|
|
82
|
+
// Expect quoted value
|
|
83
|
+
if (content[pos] !== '"') {
|
|
84
|
+
// Malformed, continue
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
const valueResult = parseQuotedString(content, pos);
|
|
88
|
+
if (!valueResult) {
|
|
89
|
+
// Malformed, skip
|
|
90
|
+
pos++;
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const value = valueResult.value;
|
|
94
|
+
pos = valueResult.end;
|
|
95
|
+
// Skip whitespace
|
|
96
|
+
while (pos < content.length && /\s/.test(content[pos])) {
|
|
97
|
+
pos++;
|
|
98
|
+
}
|
|
99
|
+
// Expect ';'
|
|
100
|
+
if (content[pos] === ";") {
|
|
101
|
+
pos++;
|
|
102
|
+
}
|
|
103
|
+
// Store entry
|
|
104
|
+
entries.push({ key, value });
|
|
105
|
+
// Handle comment
|
|
106
|
+
if (pendingComment !== null) {
|
|
107
|
+
if (isFirstEntry && entries.length === 1) {
|
|
108
|
+
// Check if this looks like a file header comment (contains copyright, license, etc.)
|
|
109
|
+
if (/copyright|license|generated|created by/i.test(pendingComment)) {
|
|
110
|
+
headerComment = pendingComment;
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
comments.set(key, pendingComment);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
comments.set(key, pendingComment);
|
|
118
|
+
}
|
|
119
|
+
pendingComment = null;
|
|
120
|
+
}
|
|
121
|
+
isFirstEntry = false;
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
// Skip unknown character
|
|
125
|
+
pos++;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
// If there's a pending comment at the end with no entry, it might be a header
|
|
129
|
+
if (pendingComment !== null && entries.length === 0) {
|
|
130
|
+
headerComment = pendingComment;
|
|
131
|
+
}
|
|
132
|
+
return { entries, comments, headerComment };
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Parse a quoted string starting at the given position
|
|
136
|
+
*
|
|
137
|
+
* @returns Object with unescaped value and end position, or null if malformed
|
|
138
|
+
*/
|
|
139
|
+
function parseQuotedString(content, start) {
|
|
140
|
+
if (content[start] !== '"')
|
|
141
|
+
return null;
|
|
142
|
+
let pos = start + 1;
|
|
143
|
+
let value = "";
|
|
144
|
+
while (pos < content.length) {
|
|
145
|
+
const char = content[pos];
|
|
146
|
+
if (char === '"') {
|
|
147
|
+
// End of string
|
|
148
|
+
return { value, end: pos + 1 };
|
|
149
|
+
}
|
|
150
|
+
if (char === "\\") {
|
|
151
|
+
// Escape sequence
|
|
152
|
+
pos++;
|
|
153
|
+
if (pos >= content.length)
|
|
154
|
+
break;
|
|
155
|
+
const escaped = content[pos];
|
|
156
|
+
switch (escaped) {
|
|
157
|
+
case "n":
|
|
158
|
+
value += "\n";
|
|
159
|
+
break;
|
|
160
|
+
case "t":
|
|
161
|
+
value += "\t";
|
|
162
|
+
break;
|
|
163
|
+
case "r":
|
|
164
|
+
value += "\r";
|
|
165
|
+
break;
|
|
166
|
+
case '"':
|
|
167
|
+
value += '"';
|
|
168
|
+
break;
|
|
169
|
+
case "\\":
|
|
170
|
+
value += "\\";
|
|
171
|
+
break;
|
|
172
|
+
case "U":
|
|
173
|
+
case "u":
|
|
174
|
+
// Unicode escape: \U0000 or \u0000
|
|
175
|
+
const hexLength = escaped === "U" ? 4 : 4;
|
|
176
|
+
const hex = content.slice(pos + 1, pos + 1 + hexLength);
|
|
177
|
+
if (/^[0-9A-Fa-f]+$/.test(hex)) {
|
|
178
|
+
const codePoint = parseInt(hex, 16);
|
|
179
|
+
value += String.fromCodePoint(codePoint);
|
|
180
|
+
pos += hexLength;
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
// Invalid unicode, keep as-is
|
|
184
|
+
value += "\\" + escaped;
|
|
185
|
+
}
|
|
186
|
+
break;
|
|
187
|
+
default:
|
|
188
|
+
// Unknown escape, keep both characters
|
|
189
|
+
value += "\\" + escaped;
|
|
190
|
+
}
|
|
191
|
+
pos++;
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
value += char;
|
|
195
|
+
pos++;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// Unterminated string
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Escape a string for use in a .strings file
|
|
203
|
+
*/
|
|
204
|
+
export function escapeStringsValue(value) {
|
|
205
|
+
return value
|
|
206
|
+
.replace(/\\/g, "\\\\")
|
|
207
|
+
.replace(/"/g, '\\"')
|
|
208
|
+
.replace(/\n/g, "\\n")
|
|
209
|
+
.replace(/\r/g, "\\r")
|
|
210
|
+
.replace(/\t/g, "\\t");
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Reconstruct a .strings file from parsed content
|
|
214
|
+
*
|
|
215
|
+
* @param entries Translation key-value pairs
|
|
216
|
+
* @param comments Comments to associate with keys
|
|
217
|
+
* @param headerComment Optional file-level header comment
|
|
218
|
+
* @returns Formatted .strings file content
|
|
219
|
+
*/
|
|
220
|
+
export function reconstructStringsContent(entries, comments, headerComment) {
|
|
221
|
+
const lines = [];
|
|
222
|
+
// Add header comment if present
|
|
223
|
+
if (headerComment) {
|
|
224
|
+
lines.push(`/* ${headerComment} */`);
|
|
225
|
+
lines.push("");
|
|
226
|
+
}
|
|
227
|
+
// Add each entry with its comment
|
|
228
|
+
for (const { key, value } of entries) {
|
|
229
|
+
const comment = comments.get(key);
|
|
230
|
+
if (comment) {
|
|
231
|
+
lines.push(`/* ${comment} */`);
|
|
232
|
+
}
|
|
233
|
+
lines.push(`"${escapeStringsValue(key)}" = "${escapeStringsValue(value)}";`);
|
|
234
|
+
}
|
|
235
|
+
// Ensure trailing newline
|
|
236
|
+
return lines.join("\n") + "\n";
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Merge new translations into existing .strings content
|
|
240
|
+
*
|
|
241
|
+
* - Preserves existing translations not in newTranslations
|
|
242
|
+
* - Updates with new translations
|
|
243
|
+
* - Removes keys not in sourceKeys
|
|
244
|
+
* - Preserves comments from source
|
|
245
|
+
*
|
|
246
|
+
* @param existingContent Existing target file content (raw string)
|
|
247
|
+
* @param newTranslations New/updated translations from API
|
|
248
|
+
* @param sourceComments Comments from source file
|
|
249
|
+
* @param sourceKeys Set of all keys in source file
|
|
250
|
+
* @returns Merged .strings file content
|
|
251
|
+
*/
|
|
252
|
+
export function mergeStringsContent(existingContent, newTranslations, sourceComments, sourceKeys) {
|
|
253
|
+
// Parse existing content
|
|
254
|
+
const existing = parseStringsContent(existingContent);
|
|
255
|
+
const existingMap = new Map();
|
|
256
|
+
for (const { key, value } of existing.entries) {
|
|
257
|
+
existingMap.set(key, value);
|
|
258
|
+
}
|
|
259
|
+
// Create map of new translations
|
|
260
|
+
const newMap = new Map();
|
|
261
|
+
for (const { key, value } of newTranslations) {
|
|
262
|
+
newMap.set(key, value);
|
|
263
|
+
}
|
|
264
|
+
// Build merged entries - only include keys from source
|
|
265
|
+
const mergedEntries = [];
|
|
266
|
+
for (const key of sourceKeys) {
|
|
267
|
+
// Prefer new translation, then existing, skip if neither
|
|
268
|
+
const value = newMap.get(key) ?? existingMap.get(key);
|
|
269
|
+
if (value !== undefined) {
|
|
270
|
+
mergedEntries.push({ key, value });
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
// Use source comments, preserve existing header
|
|
274
|
+
return reconstructStringsContent(mergedEntries, sourceComments, existing.headerComment);
|
|
275
|
+
}
|
|
276
|
+
//# sourceMappingURL=strings-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strings-parser.js","sourceRoot":"","sources":["../../src/utils/strings-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strings-parser.test.d.ts","sourceRoot":"","sources":["../../src/utils/strings-parser.test.ts"],"names":[],"mappings":""}
|