@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,143 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { parseStringsContent, reconstructStringsContent, mergeStringsContent, escapeStringsValue, } from "./strings-parser.js";
|
|
3
|
+
describe("Strings Parser", () => {
|
|
4
|
+
describe("parseStringsContent", () => {
|
|
5
|
+
it("should parse simple key-value pairs", () => {
|
|
6
|
+
const content = `"greeting" = "Hello";
|
|
7
|
+
"farewell" = "Goodbye";`;
|
|
8
|
+
const result = parseStringsContent(content);
|
|
9
|
+
expect(result.entries).toEqual([
|
|
10
|
+
{ key: "greeting", value: "Hello" },
|
|
11
|
+
{ key: "farewell", value: "Goodbye" },
|
|
12
|
+
]);
|
|
13
|
+
});
|
|
14
|
+
it("should handle escaped quotes", () => {
|
|
15
|
+
const content = `"message" = "He said \\"Hello\\"";`;
|
|
16
|
+
const result = parseStringsContent(content);
|
|
17
|
+
expect(result.entries).toEqual([
|
|
18
|
+
{ key: "message", value: 'He said "Hello"' },
|
|
19
|
+
]);
|
|
20
|
+
});
|
|
21
|
+
it("should handle escaped special characters", () => {
|
|
22
|
+
const content = `"message" = "Line1\\nLine2\\tTabbed";`;
|
|
23
|
+
const result = parseStringsContent(content);
|
|
24
|
+
expect(result.entries).toEqual([
|
|
25
|
+
{ key: "message", value: "Line1\nLine2\tTabbed" },
|
|
26
|
+
]);
|
|
27
|
+
});
|
|
28
|
+
it("should preserve comments above entries", () => {
|
|
29
|
+
const content = `/* User greeting */
|
|
30
|
+
"greeting" = "Hello";
|
|
31
|
+
/* User farewell */
|
|
32
|
+
"farewell" = "Goodbye";`;
|
|
33
|
+
const result = parseStringsContent(content);
|
|
34
|
+
expect(result.entries).toHaveLength(2);
|
|
35
|
+
expect(result.comments.get("greeting")).toBe("User greeting");
|
|
36
|
+
expect(result.comments.get("farewell")).toBe("User farewell");
|
|
37
|
+
});
|
|
38
|
+
it("should handle empty file", () => {
|
|
39
|
+
const result = parseStringsContent("");
|
|
40
|
+
expect(result.entries).toEqual([]);
|
|
41
|
+
expect(result.comments.size).toBe(0);
|
|
42
|
+
});
|
|
43
|
+
it("should handle file-level header comment", () => {
|
|
44
|
+
const content = `/* Copyright 2024 Company */
|
|
45
|
+
"greeting" = "Hello";`;
|
|
46
|
+
const result = parseStringsContent(content);
|
|
47
|
+
expect(result.headerComment).toBe("Copyright 2024 Company");
|
|
48
|
+
expect(result.entries).toHaveLength(1);
|
|
49
|
+
});
|
|
50
|
+
it("should handle line comments", () => {
|
|
51
|
+
const content = `// This is a greeting
|
|
52
|
+
"greeting" = "Hello";`;
|
|
53
|
+
const result = parseStringsContent(content);
|
|
54
|
+
expect(result.comments.get("greeting")).toBe("This is a greeting");
|
|
55
|
+
});
|
|
56
|
+
it("should parse Unicode escape sequences", () => {
|
|
57
|
+
const content = `"char" = "caf\\U00E9";`;
|
|
58
|
+
const result = parseStringsContent(content);
|
|
59
|
+
expect(result.entries).toEqual([
|
|
60
|
+
{ key: "char", value: "café" },
|
|
61
|
+
]);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
describe("escapeStringsValue", () => {
|
|
65
|
+
it("should escape quotes", () => {
|
|
66
|
+
expect(escapeStringsValue('Say "Hello"')).toBe('Say \\"Hello\\"');
|
|
67
|
+
});
|
|
68
|
+
it("should escape newlines and tabs", () => {
|
|
69
|
+
expect(escapeStringsValue("Line1\nLine2")).toBe("Line1\\nLine2");
|
|
70
|
+
expect(escapeStringsValue("Col1\tCol2")).toBe("Col1\\tCol2");
|
|
71
|
+
});
|
|
72
|
+
it("should escape backslashes", () => {
|
|
73
|
+
expect(escapeStringsValue("path\\to\\file")).toBe("path\\\\to\\\\file");
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
describe("reconstructStringsContent", () => {
|
|
77
|
+
it("should rebuild with proper formatting", () => {
|
|
78
|
+
const entries = [
|
|
79
|
+
{ key: "greeting", value: "Hello" },
|
|
80
|
+
{ key: "farewell", value: "Goodbye" },
|
|
81
|
+
];
|
|
82
|
+
const comments = new Map();
|
|
83
|
+
const result = reconstructStringsContent(entries, comments, null);
|
|
84
|
+
expect(result).toBe('"greeting" = "Hello";\n"farewell" = "Goodbye";\n');
|
|
85
|
+
});
|
|
86
|
+
it("should preserve comments", () => {
|
|
87
|
+
const entries = [{ key: "greeting", value: "Hello" }];
|
|
88
|
+
const comments = new Map([["greeting", "User greeting"]]);
|
|
89
|
+
const result = reconstructStringsContent(entries, comments, null);
|
|
90
|
+
expect(result).toBe('/* User greeting */\n"greeting" = "Hello";\n');
|
|
91
|
+
});
|
|
92
|
+
it("should add header comment", () => {
|
|
93
|
+
const entries = [{ key: "key", value: "value" }];
|
|
94
|
+
const comments = new Map();
|
|
95
|
+
const result = reconstructStringsContent(entries, comments, "Header");
|
|
96
|
+
expect(result).toContain("/* Header */");
|
|
97
|
+
});
|
|
98
|
+
it("should escape special characters in output", () => {
|
|
99
|
+
const entries = [{ key: "msg", value: 'Say "Hi"\nOK' }];
|
|
100
|
+
const comments = new Map();
|
|
101
|
+
const result = reconstructStringsContent(entries, comments, null);
|
|
102
|
+
expect(result).toBe('"msg" = "Say \\"Hi\\"\\nOK";\n');
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
describe("mergeStringsContent", () => {
|
|
106
|
+
it("should merge new translations", () => {
|
|
107
|
+
const existing = '"greeting" = "Hallo";';
|
|
108
|
+
const newTranslations = [{ key: "farewell", value: "Auf Wiedersehen" }];
|
|
109
|
+
const sourceComments = new Map();
|
|
110
|
+
const sourceKeys = new Set(["greeting", "farewell"]);
|
|
111
|
+
const result = mergeStringsContent(existing, newTranslations, sourceComments, sourceKeys);
|
|
112
|
+
expect(result).toContain('"greeting" = "Hallo"');
|
|
113
|
+
expect(result).toContain('"farewell" = "Auf Wiedersehen"');
|
|
114
|
+
});
|
|
115
|
+
it("should preserve existing translations not updated", () => {
|
|
116
|
+
const existing = '"greeting" = "Hallo";\n"farewell" = "Tschüss";';
|
|
117
|
+
const newTranslations = [{ key: "greeting", value: "Guten Tag" }];
|
|
118
|
+
const sourceComments = new Map();
|
|
119
|
+
const sourceKeys = new Set(["greeting", "farewell"]);
|
|
120
|
+
const result = mergeStringsContent(existing, newTranslations, sourceComments, sourceKeys);
|
|
121
|
+
expect(result).toContain('"greeting" = "Guten Tag"');
|
|
122
|
+
expect(result).toContain('"farewell" = "Tschüss"');
|
|
123
|
+
});
|
|
124
|
+
it("should remove keys not in source", () => {
|
|
125
|
+
const existing = '"greeting" = "Hallo";\n"deleted" = "To be removed";';
|
|
126
|
+
const newTranslations = [];
|
|
127
|
+
const sourceComments = new Map();
|
|
128
|
+
const sourceKeys = new Set(["greeting"]);
|
|
129
|
+
const result = mergeStringsContent(existing, newTranslations, sourceComments, sourceKeys);
|
|
130
|
+
expect(result).toContain('"greeting" = "Hallo"');
|
|
131
|
+
expect(result).not.toContain("deleted");
|
|
132
|
+
});
|
|
133
|
+
it("should preserve comment associations from source", () => {
|
|
134
|
+
const existing = '"greeting" = "Hallo";';
|
|
135
|
+
const newTranslations = [];
|
|
136
|
+
const sourceComments = new Map([["greeting", "User greeting"]]);
|
|
137
|
+
const sourceKeys = new Set(["greeting"]);
|
|
138
|
+
const result = mergeStringsContent(existing, newTranslations, sourceComments, sourceKeys);
|
|
139
|
+
expect(result).toContain("/* User greeting */");
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
//# sourceMappingURL=strings-parser.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"strings-parser.test.js","sourceRoot":"","sources":["../../src/utils/strings-parser.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stringsdict (.stringsdict) file parser
|
|
3
|
+
*
|
|
4
|
+
* Stringsdict files are XML plist files used for pluralization and
|
|
5
|
+
* gender rules in iOS/macOS applications.
|
|
6
|
+
*
|
|
7
|
+
* Structure:
|
|
8
|
+
* <dict>
|
|
9
|
+
* <key>items_count</key>
|
|
10
|
+
* <dict>
|
|
11
|
+
* <key>NSStringLocalizedFormatKey</key>
|
|
12
|
+
* <string>%#@count@</string>
|
|
13
|
+
* <key>count</key>
|
|
14
|
+
* <dict>
|
|
15
|
+
* <key>NSStringFormatSpecTypeKey</key>
|
|
16
|
+
* <string>NSStringPluralRuleType</string>
|
|
17
|
+
* <key>one</key>
|
|
18
|
+
* <string>%d item</string>
|
|
19
|
+
* <key>other</key>
|
|
20
|
+
* <string>%d items</string>
|
|
21
|
+
* </dict>
|
|
22
|
+
* </dict>
|
|
23
|
+
* </dict>
|
|
24
|
+
*/
|
|
25
|
+
import type { KeyValue } from "../api/types.js";
|
|
26
|
+
/**
|
|
27
|
+
* Plural variant types supported by iOS
|
|
28
|
+
*/
|
|
29
|
+
export type PluralVariant = "zero" | "one" | "two" | "few" | "many" | "other";
|
|
30
|
+
/**
|
|
31
|
+
* All possible plural variants
|
|
32
|
+
*/
|
|
33
|
+
export declare const PLURAL_VARIANTS: PluralVariant[];
|
|
34
|
+
/**
|
|
35
|
+
* Plural rule definition for a single variable
|
|
36
|
+
*/
|
|
37
|
+
export interface PluralRule {
|
|
38
|
+
/** The format spec type (usually NSStringPluralRuleType) */
|
|
39
|
+
specTypeKey: string;
|
|
40
|
+
/** Optional format value type */
|
|
41
|
+
formatValueTypeKey?: string;
|
|
42
|
+
/** Plural variant values: zero, one, two, few, many, other */
|
|
43
|
+
variants: Partial<Record<PluralVariant, string>>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* A single stringsdict entry with its plural rules
|
|
47
|
+
*/
|
|
48
|
+
export interface StringsDictEntry {
|
|
49
|
+
/** The key name (e.g., "items_count") */
|
|
50
|
+
key: string;
|
|
51
|
+
/** The NSStringLocalizedFormatKey value (e.g., "%#@count@") */
|
|
52
|
+
formatKey: string;
|
|
53
|
+
/** Plural rules keyed by variable name (e.g., "count") */
|
|
54
|
+
pluralRules: Record<string, PluralRule>;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Parsed content from a .stringsdict file
|
|
58
|
+
*/
|
|
59
|
+
export interface StringsDictContent {
|
|
60
|
+
/** Parsed entries */
|
|
61
|
+
entries: StringsDictEntry[];
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Parse a .stringsdict file content
|
|
65
|
+
*
|
|
66
|
+
* @param content Raw XML content
|
|
67
|
+
* @returns Parsed content or null if invalid
|
|
68
|
+
*/
|
|
69
|
+
export declare function parseStringsDictContent(content: string): StringsDictContent | null;
|
|
70
|
+
/**
|
|
71
|
+
* Flatten stringsdict entries for API translation
|
|
72
|
+
*
|
|
73
|
+
* Converts plural entries to flat key-value pairs using dot notation:
|
|
74
|
+
* - "items_count.one" = "%d item"
|
|
75
|
+
* - "items_count.other" = "%d items"
|
|
76
|
+
*
|
|
77
|
+
* @param entries Stringsdict entries
|
|
78
|
+
* @returns Flattened key-value pairs
|
|
79
|
+
*/
|
|
80
|
+
export declare function flattenStringsDictForApi(entries: StringsDictEntry[]): KeyValue[];
|
|
81
|
+
/**
|
|
82
|
+
* Unflatten API translations back to stringsdict structure
|
|
83
|
+
*
|
|
84
|
+
* @param translations Flattened translations from API
|
|
85
|
+
* @param sourceEntries Source stringsdict entries (for structure reference)
|
|
86
|
+
* @returns Reconstructed stringsdict entries
|
|
87
|
+
*/
|
|
88
|
+
export declare function unflattenStringsDictFromApi(translations: KeyValue[], sourceEntries: StringsDictEntry[]): StringsDictEntry[];
|
|
89
|
+
/**
|
|
90
|
+
* Reconstruct a .stringsdict file from entries
|
|
91
|
+
*
|
|
92
|
+
* @param entries Stringsdict entries
|
|
93
|
+
* @returns Valid XML plist content
|
|
94
|
+
*/
|
|
95
|
+
export declare function reconstructStringsDictContent(entries: StringsDictEntry[]): string;
|
|
96
|
+
/**
|
|
97
|
+
* Merge new translations into existing stringsdict content
|
|
98
|
+
*
|
|
99
|
+
* @param existingContent Existing target file content (raw XML)
|
|
100
|
+
* @param newTranslations New/updated translations (flattened format)
|
|
101
|
+
* @param sourceEntries Source stringsdict entries (for structure)
|
|
102
|
+
* @param sourceKeys Set of all entry keys in source
|
|
103
|
+
* @returns Merged stringsdict XML content
|
|
104
|
+
*/
|
|
105
|
+
export declare function mergeStringsDictContent(existingContent: string, newTranslations: KeyValue[], sourceEntries: StringsDictEntry[], sourceKeys: Set<string>): string;
|
|
106
|
+
//# sourceMappingURL=stringsdict-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stringsdict-parser.d.ts","sourceRoot":"","sources":["../../src/utils/stringsdict-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;AAE9E;;GAEG;AACH,eAAO,MAAM,eAAe,EAAE,aAAa,EAO1C,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,4DAA4D;IAC5D,WAAW,EAAE,MAAM,CAAC;IACpB,iCAAiC;IACjC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,8DAA8D;IAC9D,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC,CAAC;CAClD;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,yCAAyC;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACzC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,qBAAqB;IACrB,OAAO,EAAE,gBAAgB,EAAE,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,MAAM,GACd,kBAAkB,GAAG,IAAI,CAgC3B;AAyPD;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,gBAAgB,EAAE,GAC1B,QAAQ,EAAE,CAsBZ;AAED;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CACzC,YAAY,EAAE,QAAQ,EAAE,EACxB,aAAa,EAAE,gBAAgB,EAAE,GAChC,gBAAgB,EAAE,CAkDpB;AAED;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,gBAAgB,EAAE,GAC1B,MAAM,CAgDR;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CACrC,eAAe,EAAE,MAAM,EACvB,eAAe,EAAE,QAAQ,EAAE,EAC3B,aAAa,EAAE,gBAAgB,EAAE,EACjC,UAAU,EAAE,GAAG,CAAC,MAAM,CAAC,GACtB,MAAM,CAqER"}
|