@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.
Files changed (64) hide show
  1. package/dist/handlers/index.d.ts +7 -0
  2. package/dist/handlers/index.d.ts.map +1 -0
  3. package/dist/handlers/index.js +7 -0
  4. package/dist/handlers/index.js.map +1 -0
  5. package/dist/handlers/xcstrings-sync-handler.d.ts +72 -0
  6. package/dist/handlers/xcstrings-sync-handler.d.ts.map +1 -0
  7. package/dist/handlers/xcstrings-sync-handler.js +126 -0
  8. package/dist/handlers/xcstrings-sync-handler.js.map +1 -0
  9. package/dist/locale-detection/index.d.ts.map +1 -1
  10. package/dist/locale-detection/index.js +80 -7
  11. package/dist/locale-detection/index.js.map +1 -1
  12. package/dist/locale-detection/patterns.d.ts.map +1 -1
  13. package/dist/locale-detection/patterns.js +45 -0
  14. package/dist/locale-detection/patterns.js.map +1 -1
  15. package/dist/tools/get-translation-status.d.ts.map +1 -1
  16. package/dist/tools/get-translation-status.js +34 -6
  17. package/dist/tools/get-translation-status.js.map +1 -1
  18. package/dist/tools/list-local-locales.d.ts +1 -1
  19. package/dist/tools/list-local-locales.js +2 -2
  20. package/dist/tools/list-local-locales.js.map +1 -1
  21. package/dist/tools/sync-translations.d.ts.map +1 -1
  22. package/dist/tools/sync-translations.js +228 -42
  23. package/dist/tools/sync-translations.js.map +1 -1
  24. package/dist/utils/apple-common.d.ts +63 -0
  25. package/dist/utils/apple-common.d.ts.map +1 -0
  26. package/dist/utils/apple-common.js +118 -0
  27. package/dist/utils/apple-common.js.map +1 -0
  28. package/dist/utils/apple-common.test.d.ts +2 -0
  29. package/dist/utils/apple-common.test.d.ts.map +1 -0
  30. package/dist/utils/apple-common.test.js +108 -0
  31. package/dist/utils/apple-common.test.js.map +1 -0
  32. package/dist/utils/arb-parser.d.ts +77 -0
  33. package/dist/utils/arb-parser.d.ts.map +1 -0
  34. package/dist/utils/arb-parser.js +142 -0
  35. package/dist/utils/arb-parser.js.map +1 -0
  36. package/dist/utils/arb-parser.test.d.ts +2 -0
  37. package/dist/utils/arb-parser.test.d.ts.map +1 -0
  38. package/dist/utils/arb-parser.test.js +243 -0
  39. package/dist/utils/arb-parser.test.js.map +1 -0
  40. package/dist/utils/strings-parser.d.ts +62 -0
  41. package/dist/utils/strings-parser.d.ts.map +1 -0
  42. package/dist/utils/strings-parser.js +276 -0
  43. package/dist/utils/strings-parser.js.map +1 -0
  44. package/dist/utils/strings-parser.test.d.ts +2 -0
  45. package/dist/utils/strings-parser.test.d.ts.map +1 -0
  46. package/dist/utils/strings-parser.test.js +143 -0
  47. package/dist/utils/strings-parser.test.js.map +1 -0
  48. package/dist/utils/stringsdict-parser.d.ts +106 -0
  49. package/dist/utils/stringsdict-parser.d.ts.map +1 -0
  50. package/dist/utils/stringsdict-parser.js +473 -0
  51. package/dist/utils/stringsdict-parser.js.map +1 -0
  52. package/dist/utils/stringsdict-parser.test.d.ts +2 -0
  53. package/dist/utils/stringsdict-parser.test.d.ts.map +1 -0
  54. package/dist/utils/stringsdict-parser.test.js +244 -0
  55. package/dist/utils/stringsdict-parser.test.js.map +1 -0
  56. package/dist/utils/xcstrings-parser.d.ts +128 -0
  57. package/dist/utils/xcstrings-parser.d.ts.map +1 -0
  58. package/dist/utils/xcstrings-parser.js +216 -0
  59. package/dist/utils/xcstrings-parser.js.map +1 -0
  60. package/dist/utils/xcstrings-parser.test.d.ts +2 -0
  61. package/dist/utils/xcstrings-parser.test.d.ts.map +1 -0
  62. package/dist/utils/xcstrings-parser.test.js +157 -0
  63. package/dist/utils/xcstrings-parser.test.js.map +1 -0
  64. 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"}