@langapi/mcp-server 1.0.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 (67) hide show
  1. package/README.md +551 -0
  2. package/bin/langapi-mcp.js +11 -0
  3. package/dist/api/client.d.ts +24 -0
  4. package/dist/api/client.d.ts.map +1 -0
  5. package/dist/api/client.js +145 -0
  6. package/dist/api/client.js.map +1 -0
  7. package/dist/api/types.d.ts +56 -0
  8. package/dist/api/types.d.ts.map +1 -0
  9. package/dist/api/types.js +6 -0
  10. package/dist/api/types.js.map +1 -0
  11. package/dist/config/env.d.ts +18 -0
  12. package/dist/config/env.d.ts.map +1 -0
  13. package/dist/config/env.js +29 -0
  14. package/dist/config/env.js.map +1 -0
  15. package/dist/index.d.ts +15 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +25 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/locale-detection/index.d.ts +41 -0
  20. package/dist/locale-detection/index.d.ts.map +1 -0
  21. package/dist/locale-detection/index.js +188 -0
  22. package/dist/locale-detection/index.js.map +1 -0
  23. package/dist/locale-detection/patterns.d.ts +21 -0
  24. package/dist/locale-detection/patterns.d.ts.map +1 -0
  25. package/dist/locale-detection/patterns.js +135 -0
  26. package/dist/locale-detection/patterns.js.map +1 -0
  27. package/dist/server.d.ts +9 -0
  28. package/dist/server.d.ts.map +1 -0
  29. package/dist/server.js +24 -0
  30. package/dist/server.js.map +1 -0
  31. package/dist/tools/get-diff.d.ts +23 -0
  32. package/dist/tools/get-diff.d.ts.map +1 -0
  33. package/dist/tools/get-diff.js +88 -0
  34. package/dist/tools/get-diff.js.map +1 -0
  35. package/dist/tools/get-translation-status.d.ts +47 -0
  36. package/dist/tools/get-translation-status.d.ts.map +1 -0
  37. package/dist/tools/get-translation-status.js +176 -0
  38. package/dist/tools/get-translation-status.js.map +1 -0
  39. package/dist/tools/list-local-locales.d.ts +39 -0
  40. package/dist/tools/list-local-locales.d.ts.map +1 -0
  41. package/dist/tools/list-local-locales.js +52 -0
  42. package/dist/tools/list-local-locales.js.map +1 -0
  43. package/dist/tools/sync-translations.d.ts +35 -0
  44. package/dist/tools/sync-translations.d.ts.map +1 -0
  45. package/dist/tools/sync-translations.js +629 -0
  46. package/dist/tools/sync-translations.js.map +1 -0
  47. package/dist/utils/format-preserve.d.ts +25 -0
  48. package/dist/utils/format-preserve.d.ts.map +1 -0
  49. package/dist/utils/format-preserve.js +56 -0
  50. package/dist/utils/format-preserve.js.map +1 -0
  51. package/dist/utils/json-parser.d.ts +33 -0
  52. package/dist/utils/json-parser.d.ts.map +1 -0
  53. package/dist/utils/json-parser.js +92 -0
  54. package/dist/utils/json-parser.js.map +1 -0
  55. package/dist/utils/sync-cache.d.ts +40 -0
  56. package/dist/utils/sync-cache.d.ts.map +1 -0
  57. package/dist/utils/sync-cache.js +153 -0
  58. package/dist/utils/sync-cache.js.map +1 -0
  59. package/dist/utils/sync-cache.test.d.ts +2 -0
  60. package/dist/utils/sync-cache.test.d.ts.map +1 -0
  61. package/dist/utils/sync-cache.test.js +205 -0
  62. package/dist/utils/sync-cache.test.js.map +1 -0
  63. package/dist/utils/validation.d.ts +37 -0
  64. package/dist/utils/validation.d.ts.map +1 -0
  65. package/dist/utils/validation.js +67 -0
  66. package/dist/utils/validation.js.map +1 -0
  67. package/package.json +56 -0
@@ -0,0 +1,145 @@
1
+ /**
2
+ * LangAPI client for making API requests
3
+ */
4
+ import { API_BASE_URL, getApiKey } from "../config/env.js";
5
+ /** Default request timeout in milliseconds (30 seconds) */
6
+ const DEFAULT_TIMEOUT_MS = 30000;
7
+ /**
8
+ * Type guard for SyncDryRunResponse
9
+ */
10
+ function isSyncDryRunResponse(data) {
11
+ if (typeof data !== "object" || data === null)
12
+ return false;
13
+ const obj = data;
14
+ return (obj.success === true &&
15
+ typeof obj.delta === "object" &&
16
+ obj.delta !== null &&
17
+ typeof obj.cost === "object" &&
18
+ obj.cost !== null &&
19
+ "wordsToTranslate" in obj.cost);
20
+ }
21
+ /**
22
+ * Type guard for SyncExecuteResponse
23
+ */
24
+ function isSyncExecuteResponse(data) {
25
+ if (typeof data !== "object" || data === null)
26
+ return false;
27
+ const obj = data;
28
+ return (obj.success === true &&
29
+ Array.isArray(obj.results) &&
30
+ typeof obj.cost === "object" &&
31
+ obj.cost !== null &&
32
+ "creditsUsed" in obj.cost);
33
+ }
34
+ export class LangAPIClient {
35
+ apiKey;
36
+ baseUrl;
37
+ timeoutMs;
38
+ constructor(apiKey, baseUrl = API_BASE_URL, timeoutMs = DEFAULT_TIMEOUT_MS) {
39
+ this.apiKey = apiKey;
40
+ this.baseUrl = baseUrl;
41
+ this.timeoutMs = timeoutMs;
42
+ }
43
+ /**
44
+ * Create a client instance using the configured API key
45
+ * @throws Error if no API key is configured
46
+ */
47
+ static create() {
48
+ const apiKey = getApiKey();
49
+ if (!apiKey) {
50
+ throw new Error("No API key configured. Set the LANGAPI_API_KEY environment variable.");
51
+ }
52
+ return new LangAPIClient(apiKey);
53
+ }
54
+ /**
55
+ * Check if client can be created (API key is configured)
56
+ */
57
+ static canCreate() {
58
+ return !!getApiKey();
59
+ }
60
+ /**
61
+ * Sync translations with the LangAPI service
62
+ */
63
+ async sync(request) {
64
+ // Create abort controller for timeout
65
+ const controller = new AbortController();
66
+ const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);
67
+ try {
68
+ const response = await fetch(`${this.baseUrl}/api/v1/sync`, {
69
+ method: "POST",
70
+ headers: {
71
+ "Content-Type": "application/json",
72
+ Authorization: `Bearer ${this.apiKey}`,
73
+ },
74
+ body: JSON.stringify(request),
75
+ signal: controller.signal,
76
+ });
77
+ const data = await response.json();
78
+ if (!response.ok) {
79
+ // Parse error response safely
80
+ const errorObj = typeof data === "object" && data !== null
81
+ ? data
82
+ : {};
83
+ const errorData = typeof errorObj.error === "object" && errorObj.error !== null
84
+ ? errorObj.error
85
+ : {};
86
+ return {
87
+ success: false,
88
+ error: {
89
+ code: typeof errorData.code === "string" ? errorData.code : "API_ERROR",
90
+ message: typeof errorData.message === "string"
91
+ ? errorData.message
92
+ : `HTTP ${response.status}`,
93
+ currentBalance: typeof errorData.currentBalance === "number"
94
+ ? errorData.currentBalance
95
+ : undefined,
96
+ requiredCredits: typeof errorData.requiredCredits === "number"
97
+ ? errorData.requiredCredits
98
+ : undefined,
99
+ topUpUrl: typeof errorData.topUpUrl === "string"
100
+ ? errorData.topUpUrl
101
+ : undefined,
102
+ },
103
+ };
104
+ }
105
+ // Validate successful response using type guards
106
+ if (isSyncDryRunResponse(data)) {
107
+ return data;
108
+ }
109
+ if (isSyncExecuteResponse(data)) {
110
+ return data;
111
+ }
112
+ // Unknown response format
113
+ return {
114
+ success: false,
115
+ error: {
116
+ code: "INVALID_RESPONSE",
117
+ message: "API returned an unexpected response format",
118
+ },
119
+ };
120
+ }
121
+ catch (error) {
122
+ // Handle timeout and network errors
123
+ if (error instanceof Error && error.name === "AbortError") {
124
+ return {
125
+ success: false,
126
+ error: {
127
+ code: "TIMEOUT",
128
+ message: `Request timed out after ${this.timeoutMs}ms`,
129
+ },
130
+ };
131
+ }
132
+ return {
133
+ success: false,
134
+ error: {
135
+ code: "NETWORK_ERROR",
136
+ message: error instanceof Error ? error.message : "Unknown network error",
137
+ },
138
+ };
139
+ }
140
+ finally {
141
+ clearTimeout(timeoutId);
142
+ }
143
+ }
144
+ }
145
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * API request/response types for LangAPI
3
+ * These types match the langapi-api sync endpoint
4
+ */
5
+ export interface KeyValue {
6
+ key: string;
7
+ value: string;
8
+ }
9
+ export interface SyncRequest {
10
+ source_lang: string;
11
+ target_langs: string[];
12
+ content: KeyValue[];
13
+ dry_run: boolean;
14
+ }
15
+ export interface SyncDelta {
16
+ newKeys: string[];
17
+ changedKeys: string[];
18
+ unchangedKeys: string[];
19
+ totalKeysToSync: number;
20
+ }
21
+ export interface SyncCostEstimate {
22
+ wordsToTranslate: number;
23
+ creditsRequired: number;
24
+ currentBalance: number;
25
+ balanceAfterSync: number;
26
+ }
27
+ export interface SyncDryRunResponse {
28
+ success: true;
29
+ delta: SyncDelta;
30
+ cost: SyncCostEstimate;
31
+ }
32
+ export interface SyncLanguageResult {
33
+ language: string;
34
+ translatedCount: number;
35
+ translations: KeyValue[];
36
+ }
37
+ export interface SyncExecuteResponse {
38
+ success: true;
39
+ results: SyncLanguageResult[];
40
+ cost: {
41
+ creditsUsed: number;
42
+ balanceAfterSync: number;
43
+ };
44
+ }
45
+ export interface SyncErrorResponse {
46
+ success: false;
47
+ error: {
48
+ code: string;
49
+ message: string;
50
+ currentBalance?: number;
51
+ requiredCredits?: number;
52
+ topUpUrl?: string;
53
+ };
54
+ }
55
+ export type SyncResponse = SyncDryRunResponse | SyncExecuteResponse | SyncErrorResponse;
56
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,MAAM,WAAW,QAAQ;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAGD,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,OAAO,EAAE,QAAQ,EAAE,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;CAClB;AAGD,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;CACzB;AAGD,MAAM,WAAW,gBAAgB;IAC/B,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAGD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,IAAI,CAAC;IACd,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,gBAAgB,CAAC;CACxB;AAGD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,QAAQ,EAAE,CAAC;CAC1B;AAGD,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,IAAI,CAAC;IACd,OAAO,EAAE,kBAAkB,EAAE,CAAC;IAC9B,IAAI,EAAE;QACJ,WAAW,EAAE,MAAM,CAAC;QACpB,gBAAgB,EAAE,MAAM,CAAC;KAC1B,CAAC;CACH;AAGD,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,CAAC,EAAE,MAAM,CAAC;QACxB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,CAAC;CACH;AAGD,MAAM,MAAM,YAAY,GACpB,kBAAkB,GAClB,mBAAmB,GACnB,iBAAiB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * API request/response types for LangAPI
3
+ * These types match the langapi-api sync endpoint
4
+ */
5
+ export {};
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Environment variable configuration for LangAPI MCP Server
3
+ */
4
+ export declare const API_BASE_URL: string;
5
+ /**
6
+ * Get the API key from environment variable
7
+ * @returns The API key or null if not configured
8
+ */
9
+ export declare function getApiKey(): string | null;
10
+ /**
11
+ * Check if the API key is configured
12
+ */
13
+ export declare function isApiKeyConfigured(): boolean;
14
+ /**
15
+ * Get masked API key for display (shows first 10 and last 4 chars)
16
+ */
17
+ export declare function getMaskedApiKey(): string | null;
18
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,YAAY,QACgC,CAAC;AAE1D;;;GAGG;AACH,wBAAgB,SAAS,IAAI,MAAM,GAAG,IAAI,CAEzC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C;AAED;;GAEG;AACH,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAK/C"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Environment variable configuration for LangAPI MCP Server
3
+ */
4
+ export const API_BASE_URL = process.env.LANGAPI_API_URL || "https://api.langapi.io";
5
+ /**
6
+ * Get the API key from environment variable
7
+ * @returns The API key or null if not configured
8
+ */
9
+ export function getApiKey() {
10
+ return process.env.LANGAPI_API_KEY || null;
11
+ }
12
+ /**
13
+ * Check if the API key is configured
14
+ */
15
+ export function isApiKeyConfigured() {
16
+ return !!getApiKey();
17
+ }
18
+ /**
19
+ * Get masked API key for display (shows first 10 and last 4 chars)
20
+ */
21
+ export function getMaskedApiKey() {
22
+ const key = getApiKey();
23
+ if (!key)
24
+ return null;
25
+ if (key.length <= 14)
26
+ return "***";
27
+ return `${key.slice(0, 10)}...${key.slice(-4)}`;
28
+ }
29
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/config/env.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,CAAC,MAAM,YAAY,GACvB,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,wBAAwB,CAAC;AAE1D;;;GAGG;AACH,MAAM,UAAU,SAAS;IACvB,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,IAAI,CAAC;AAC7C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO,CAAC,CAAC,SAAS,EAAE,CAAC;AACvB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,IAAI,GAAG,CAAC,MAAM,IAAI,EAAE;QAAE,OAAO,KAAK,CAAC;IACnC,OAAO,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAClD,CAAC"}
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * LangAPI MCP Server Entry Point
4
+ *
5
+ * This MCP server enables AI assistants to manage i18n translations
6
+ * in developer projects via the LangAPI service.
7
+ *
8
+ * Tools available:
9
+ * - list_local_locales: Scan project for locale files
10
+ * - get_translation_status: Compare source vs target locales
11
+ * - sync_translations: Sync translations via LangAPI API
12
+ * - get_diff: Compare source against sync cache for delta detection
13
+ */
14
+ export {};
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG"}
package/dist/index.js ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * LangAPI MCP Server Entry Point
4
+ *
5
+ * This MCP server enables AI assistants to manage i18n translations
6
+ * in developer projects via the LangAPI service.
7
+ *
8
+ * Tools available:
9
+ * - list_local_locales: Scan project for locale files
10
+ * - get_translation_status: Compare source vs target locales
11
+ * - sync_translations: Sync translations via LangAPI API
12
+ * - get_diff: Compare source against sync cache for delta detection
13
+ */
14
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
15
+ import { createServer } from "./server.js";
16
+ async function main() {
17
+ const server = createServer();
18
+ const transport = new StdioServerTransport();
19
+ await server.connect(transport);
20
+ }
21
+ main().catch((error) => {
22
+ console.error("Failed to start LangAPI MCP server:", error);
23
+ process.exit(1);
24
+ });
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,KAAK,UAAU,IAAI;IACjB,MAAM,MAAM,GAAG,YAAY,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAE7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;IAC5D,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Locale detection orchestrator
3
+ * Detects i18n framework and locale files in a project
4
+ */
5
+ export interface LocaleFile {
6
+ /** Absolute path to the file */
7
+ path: string;
8
+ /** Relative path from project root */
9
+ relativePath: string;
10
+ /** Namespace if applicable (from directory name) */
11
+ namespace: string | null;
12
+ /** Number of translation keys */
13
+ keyCount: number;
14
+ }
15
+ export interface DetectedLocale {
16
+ /** Language code */
17
+ lang: string;
18
+ /** Files for this language */
19
+ files: LocaleFile[];
20
+ /** Total key count across all files */
21
+ totalKeys: number;
22
+ }
23
+ export interface LocaleDetectionResult {
24
+ /** Detected framework */
25
+ framework: string;
26
+ /** Confidence level */
27
+ confidence: "high" | "medium" | "low";
28
+ /** Path to locales directory (relative) */
29
+ localesPath: string | null;
30
+ /** Detected source language */
31
+ sourceLang: string | null;
32
+ /** All detected locales */
33
+ locales: DetectedLocale[];
34
+ /** Path to i18n config file if found */
35
+ configFile: string | null;
36
+ }
37
+ /**
38
+ * Detect i18n framework and locale files in a project
39
+ */
40
+ export declare function detectLocales(projectPath: string, includeKeyCount?: boolean): Promise<LocaleDetectionResult>;
41
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/locale-detection/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAaH,MAAM,WAAW,UAAU;IACzB,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,sCAAsC;IACtC,YAAY,EAAE,MAAM,CAAC;IACrB,oDAAoD;IACpD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,8BAA8B;IAC9B,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,uCAAuC;IACvC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,qBAAqB;IACpC,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,uBAAuB;IACvB,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACtC,2CAA2C;IAC3C,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,+BAA+B;IAC/B,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,2BAA2B;IAC3B,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,wCAAwC;IACxC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,eAAe,UAAO,GACrB,OAAO,CAAC,qBAAqB,CAAC,CAgChC"}
@@ -0,0 +1,188 @@
1
+ /**
2
+ * Locale detection orchestrator
3
+ * Detects i18n framework and locale files in a project
4
+ */
5
+ import { glob } from "glob";
6
+ import { readFile } from "fs/promises";
7
+ import { join, basename, dirname, relative } from "path";
8
+ import { existsSync } from "fs";
9
+ import { FRAMEWORK_PATTERNS, isLikelyLanguageCode, } from "./patterns.js";
10
+ import { countKeys, parseJsonSafe } from "../utils/json-parser.js";
11
+ /**
12
+ * Detect i18n framework and locale files in a project
13
+ */
14
+ export async function detectLocales(projectPath, includeKeyCount = true) {
15
+ // Try to detect framework from config files
16
+ const { framework, configFile, confidence } = await detectFramework(projectPath);
17
+ // Get the pattern for this framework
18
+ const pattern = FRAMEWORK_PATTERNS[framework] || FRAMEWORK_PATTERNS.generic;
19
+ // Find locale files
20
+ const localeFiles = await findLocaleFiles(projectPath, pattern);
21
+ // Group by language
22
+ const locales = await groupByLanguage(projectPath, localeFiles, includeKeyCount);
23
+ // Determine locales path
24
+ const localesPath = determineLocalesPath(localeFiles, projectPath);
25
+ // Try to detect source language (usually 'en' if present, or first one)
26
+ const sourceLang = locales.find((l) => l.lang === "en")?.lang || locales[0]?.lang || null;
27
+ return {
28
+ framework,
29
+ confidence,
30
+ localesPath,
31
+ sourceLang,
32
+ locales,
33
+ configFile,
34
+ };
35
+ }
36
+ /**
37
+ * Detect the i18n framework from config files
38
+ */
39
+ async function detectFramework(projectPath) {
40
+ // Check frameworks in order of specificity
41
+ for (const [frameworkName, pattern] of Object.entries(FRAMEWORK_PATTERNS)) {
42
+ if (frameworkName === "generic")
43
+ continue;
44
+ for (const configFile of pattern.configFiles) {
45
+ const fullPath = join(projectPath, configFile);
46
+ if (existsSync(fullPath)) {
47
+ // Read file and check content pattern
48
+ if (pattern.configPattern) {
49
+ try {
50
+ const content = await readFile(fullPath, "utf-8");
51
+ if (pattern.configPattern.test(content)) {
52
+ return {
53
+ framework: frameworkName,
54
+ configFile: configFile,
55
+ confidence: "high",
56
+ };
57
+ }
58
+ }
59
+ catch {
60
+ // Ignore read errors
61
+ }
62
+ }
63
+ else {
64
+ return {
65
+ framework: frameworkName,
66
+ configFile: configFile,
67
+ confidence: "medium",
68
+ };
69
+ }
70
+ }
71
+ }
72
+ }
73
+ // Fall back to generic
74
+ return { framework: "generic", configFile: null, confidence: "low" };
75
+ }
76
+ /**
77
+ * Find locale files matching the framework patterns
78
+ */
79
+ async function findLocaleFiles(projectPath, pattern) {
80
+ const allFiles = [];
81
+ for (const globPattern of pattern.localeGlobs) {
82
+ try {
83
+ const files = await glob(globPattern, {
84
+ cwd: projectPath,
85
+ absolute: true,
86
+ nodir: true,
87
+ });
88
+ allFiles.push(...files);
89
+ }
90
+ catch {
91
+ // Ignore glob errors
92
+ }
93
+ }
94
+ // Deduplicate
95
+ return [...new Set(allFiles)];
96
+ }
97
+ /**
98
+ * Group locale files by language
99
+ */
100
+ async function groupByLanguage(projectPath, files, includeKeyCount) {
101
+ const languageMap = new Map();
102
+ for (const filePath of files) {
103
+ const lang = extractLanguageFromPath(filePath);
104
+ if (!lang)
105
+ continue;
106
+ let keyCount = 0;
107
+ if (includeKeyCount) {
108
+ try {
109
+ const content = await readFile(filePath, "utf-8");
110
+ const parsed = parseJsonSafe(content);
111
+ if (parsed) {
112
+ keyCount = countKeys(parsed);
113
+ }
114
+ }
115
+ catch {
116
+ // Ignore read errors
117
+ }
118
+ }
119
+ const relativePath = relative(projectPath, filePath);
120
+ const dirName = basename(dirname(filePath));
121
+ const namespace = dirName !== lang && !isLikelyLanguageCode(dirName) ? dirName : null;
122
+ const localeFile = {
123
+ path: filePath,
124
+ relativePath,
125
+ namespace,
126
+ keyCount,
127
+ };
128
+ if (!languageMap.has(lang)) {
129
+ languageMap.set(lang, []);
130
+ }
131
+ languageMap.get(lang).push(localeFile);
132
+ }
133
+ // Convert to array and calculate totals
134
+ return Array.from(languageMap.entries()).map(([lang, files]) => ({
135
+ lang,
136
+ files,
137
+ totalKeys: files.reduce((sum, f) => sum + f.keyCount, 0),
138
+ }));
139
+ }
140
+ /**
141
+ * Extract language code from file path
142
+ * Supports patterns like: /locales/en.json, /messages/en/common.json, /public/locales/en/translation.json
143
+ */
144
+ function extractLanguageFromPath(filePath) {
145
+ const parts = filePath.split("/");
146
+ const fileName = basename(filePath, ".json");
147
+ // Check if filename is a language code (e.g., en.json)
148
+ if (isLikelyLanguageCode(fileName)) {
149
+ return fileName;
150
+ }
151
+ // Check parent directories for language code
152
+ for (let i = parts.length - 2; i >= 0; i--) {
153
+ if (isLikelyLanguageCode(parts[i])) {
154
+ return parts[i];
155
+ }
156
+ }
157
+ return null;
158
+ }
159
+ /**
160
+ * Determine the common locales directory path
161
+ */
162
+ function determineLocalesPath(files, projectPath) {
163
+ if (files.length === 0)
164
+ return null;
165
+ // Find common parent directory
166
+ const relativePaths = files.map((f) => relative(projectPath, f));
167
+ if (relativePaths.length === 0)
168
+ return null;
169
+ // Get the first path's directory parts
170
+ const firstDir = dirname(relativePaths[0]).split("/");
171
+ // Find common prefix
172
+ let commonParts = [...firstDir];
173
+ for (const relPath of relativePaths) {
174
+ const parts = dirname(relPath).split("/");
175
+ const newCommon = [];
176
+ for (let i = 0; i < Math.min(commonParts.length, parts.length); i++) {
177
+ if (commonParts[i] === parts[i]) {
178
+ newCommon.push(commonParts[i]);
179
+ }
180
+ else {
181
+ break;
182
+ }
183
+ }
184
+ commonParts = newCommon;
185
+ }
186
+ return commonParts.length > 0 ? commonParts.join("/") : null;
187
+ }
188
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/locale-detection/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Framework-specific patterns for detecting i18n locale files
3
+ */
4
+ export interface FrameworkPattern {
5
+ /** Config files that identify this framework */
6
+ configFiles: string[];
7
+ /** Glob patterns for locale files */
8
+ localeGlobs: string[];
9
+ /** Regex pattern to identify framework in config content */
10
+ configPattern?: RegExp;
11
+ }
12
+ export declare const FRAMEWORK_PATTERNS: Record<string, FrameworkPattern>;
13
+ /**
14
+ * Common language codes
15
+ */
16
+ export declare const COMMON_LANGUAGE_CODES: string[];
17
+ /**
18
+ * Check if a string looks like a language code
19
+ */
20
+ export declare function isLikelyLanguageCode(str: string): boolean;
21
+ //# sourceMappingURL=patterns.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patterns.d.ts","sourceRoot":"","sources":["../../src/locale-detection/patterns.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,gBAAgB;IAC/B,gDAAgD;IAChD,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,qCAAqC;IACrC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,4DAA4D;IAC5D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CA+D/D,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,UAoDjC,CAAC;AAEF;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAOzD"}