@scoutello/i18n-magic 0.42.1 → 0.43.1
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/README.md +19 -0
- package/dist/mcp-server.js +119 -4
- package/dist/mcp-server.js.map +1 -1
- package/package.json +1 -1
- package/src/mcp-server.ts +149 -7
package/README.md
CHANGED
|
@@ -346,11 +346,18 @@ You should see: `[i18n-magic MCP] Server started and ready to accept connections
|
|
|
346
346
|
|
|
347
347
|
### How it works
|
|
348
348
|
|
|
349
|
+
**Workflow 1: Adding individual keys**
|
|
349
350
|
1. While coding, the LLM identifies a missing translation key
|
|
350
351
|
2. The LLM calls the `add_translation_key` tool to add it with an English value
|
|
351
352
|
3. The key is automatically added to the `en` locale (regardless of your `defaultLocale`)
|
|
352
353
|
4. Run `i18n-magic sync` to translate the key to all other configured locales
|
|
353
354
|
|
|
355
|
+
**Workflow 2: Batch checking missing keys**
|
|
356
|
+
1. The LLM calls `list_untranslated_keys` to get a complete overview
|
|
357
|
+
2. Review all missing keys grouped by namespace
|
|
358
|
+
3. Add keys using `add_translation_key` or run `i18n-magic scan` for batch processing
|
|
359
|
+
4. Run `i18n-magic sync` to translate all new keys
|
|
360
|
+
|
|
354
361
|
### Available MCP Tools
|
|
355
362
|
|
|
356
363
|
**add_translation_key**: Add a new translation key with an English value
|
|
@@ -369,4 +376,16 @@ Example:
|
|
|
369
376
|
}
|
|
370
377
|
```
|
|
371
378
|
|
|
379
|
+
**list_untranslated_keys**: List all translation keys used in the codebase that are not yet defined
|
|
380
|
+
|
|
381
|
+
Parameters:
|
|
382
|
+
- `namespace` (optional): Check a specific namespace only (defaults to all namespaces)
|
|
383
|
+
|
|
384
|
+
Example:
|
|
385
|
+
```json
|
|
386
|
+
{}
|
|
387
|
+
```
|
|
388
|
+
|
|
389
|
+
Response shows all missing keys grouped by namespace with counts and next steps.
|
|
390
|
+
|
|
372
391
|
For detailed setup instructions and troubleshooting, see [MCP-SERVER.md](./MCP-SERVER.md).
|
package/dist/mcp-server.js
CHANGED
|
@@ -3,8 +3,7 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
3
3
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
4
|
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
5
5
|
import { z } from "zod";
|
|
6
|
-
import { addTranslationKey } from "./lib/utils.js";
|
|
7
|
-
import { loadConfig } from "./lib/utils.js";
|
|
6
|
+
import { addTranslationKey, getMissingKeys, loadConfig } from "./lib/utils.js";
|
|
8
7
|
import path from "path";
|
|
9
8
|
import fs from "fs";
|
|
10
9
|
import { fileURLToPath } from "url";
|
|
@@ -63,6 +62,13 @@ const AddTranslationKeySchema = z.object({
|
|
|
63
62
|
.optional()
|
|
64
63
|
.describe("Optional namespace to add the key to. If not provided, uses the default namespace from config."),
|
|
65
64
|
});
|
|
65
|
+
// Zod schema for the list_untranslated_keys tool parameters
|
|
66
|
+
const ListUntranslatedKeysSchema = z.object({
|
|
67
|
+
namespace: z
|
|
68
|
+
.string()
|
|
69
|
+
.optional()
|
|
70
|
+
.describe("Optional namespace to check. If not provided, checks all namespaces."),
|
|
71
|
+
});
|
|
66
72
|
class I18nMagicServer {
|
|
67
73
|
constructor() {
|
|
68
74
|
this.config = null;
|
|
@@ -122,6 +128,20 @@ class I18nMagicServer {
|
|
|
122
128
|
required: ["key", "value"],
|
|
123
129
|
},
|
|
124
130
|
},
|
|
131
|
+
{
|
|
132
|
+
name: "list_untranslated_keys",
|
|
133
|
+
description: "List all translation keys that are used in the codebase but are not yet defined in the locale files. This helps identify missing translations that need to be added. The tool scans the codebase for translation keys and compares them against existing locale files.",
|
|
134
|
+
inputSchema: {
|
|
135
|
+
type: "object",
|
|
136
|
+
properties: {
|
|
137
|
+
namespace: {
|
|
138
|
+
type: "string",
|
|
139
|
+
description: "Optional namespace to check. If not provided, checks all namespaces.",
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
required: [],
|
|
143
|
+
},
|
|
144
|
+
},
|
|
125
145
|
],
|
|
126
146
|
};
|
|
127
147
|
});
|
|
@@ -151,8 +171,6 @@ class I18nMagicServer {
|
|
|
151
171
|
// Restore console.log
|
|
152
172
|
console.log = originalConsoleLog;
|
|
153
173
|
}
|
|
154
|
-
// Log to stderr for debugging (this is safe in MCP)
|
|
155
|
-
console.error(`[i18n-magic MCP] Added key "${result.key}" to ${result.locale}/${result.namespace}`);
|
|
156
174
|
return {
|
|
157
175
|
content: [
|
|
158
176
|
{
|
|
@@ -206,6 +224,103 @@ class I18nMagicServer {
|
|
|
206
224
|
};
|
|
207
225
|
}
|
|
208
226
|
}
|
|
227
|
+
if (request.params.name === "list_untranslated_keys") {
|
|
228
|
+
try {
|
|
229
|
+
// Validate parameters
|
|
230
|
+
const params = ListUntranslatedKeysSchema.parse(request.params.arguments);
|
|
231
|
+
// Ensure config is loaded
|
|
232
|
+
const config = await this.ensureConfig();
|
|
233
|
+
// Suppress console.log to prevent interference with MCP JSON protocol
|
|
234
|
+
const originalConsoleLog = console.log;
|
|
235
|
+
console.log = () => { };
|
|
236
|
+
let missingKeys;
|
|
237
|
+
try {
|
|
238
|
+
// Get missing keys from the codebase
|
|
239
|
+
missingKeys = await getMissingKeys(config);
|
|
240
|
+
}
|
|
241
|
+
finally {
|
|
242
|
+
// Restore console.log
|
|
243
|
+
console.log = originalConsoleLog;
|
|
244
|
+
}
|
|
245
|
+
// Filter by namespace if specified
|
|
246
|
+
let filteredKeys = missingKeys;
|
|
247
|
+
if (params.namespace) {
|
|
248
|
+
filteredKeys = missingKeys.filter((item) => item.namespaces.includes(params.namespace));
|
|
249
|
+
}
|
|
250
|
+
// Format the results
|
|
251
|
+
const keysByNamespace = {};
|
|
252
|
+
for (const item of filteredKeys) {
|
|
253
|
+
for (const namespace of item.namespaces) {
|
|
254
|
+
if (!keysByNamespace[namespace]) {
|
|
255
|
+
keysByNamespace[namespace] = [];
|
|
256
|
+
}
|
|
257
|
+
keysByNamespace[namespace].push(item.key);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
// Create a summary
|
|
261
|
+
const summary = {
|
|
262
|
+
totalMissingKeys: filteredKeys.length,
|
|
263
|
+
namespaces: Object.entries(keysByNamespace).map(([namespace, keys]) => ({
|
|
264
|
+
namespace,
|
|
265
|
+
missingKeyCount: keys.length,
|
|
266
|
+
keys: keys.sort(),
|
|
267
|
+
})),
|
|
268
|
+
};
|
|
269
|
+
return {
|
|
270
|
+
content: [
|
|
271
|
+
{
|
|
272
|
+
type: "text",
|
|
273
|
+
text: JSON.stringify({
|
|
274
|
+
success: true,
|
|
275
|
+
message: filteredKeys.length === 0
|
|
276
|
+
? "No missing translation keys found! All keys used in the codebase are defined."
|
|
277
|
+
: `Found ${filteredKeys.length} missing translation key${filteredKeys.length === 1 ? "" : "s"}`,
|
|
278
|
+
...summary,
|
|
279
|
+
nextSteps: filteredKeys.length > 0
|
|
280
|
+
? [
|
|
281
|
+
"Use add_translation_key to add these keys with English values",
|
|
282
|
+
"Or run 'i18n-magic scan' to add them interactively",
|
|
283
|
+
]
|
|
284
|
+
: [],
|
|
285
|
+
}, null, 2),
|
|
286
|
+
},
|
|
287
|
+
],
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
catch (error) {
|
|
291
|
+
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
292
|
+
// Get more detailed error information
|
|
293
|
+
let errorDetails = errorMessage;
|
|
294
|
+
if (error instanceof Error) {
|
|
295
|
+
const cause = error.cause;
|
|
296
|
+
if (cause instanceof Error) {
|
|
297
|
+
errorDetails = `${errorMessage}\nCause: ${cause.message}\nStack: ${cause.stack}`;
|
|
298
|
+
}
|
|
299
|
+
else if (cause) {
|
|
300
|
+
errorDetails = `${errorMessage}\nCause: ${JSON.stringify(cause)}`;
|
|
301
|
+
}
|
|
302
|
+
if (error.stack) {
|
|
303
|
+
errorDetails = `${errorDetails}\nStack: ${error.stack}`;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
// Log detailed error to stderr for debugging
|
|
307
|
+
console.error(`[i18n-magic MCP] Error listing untranslated keys:`);
|
|
308
|
+
console.error(errorDetails);
|
|
309
|
+
return {
|
|
310
|
+
content: [
|
|
311
|
+
{
|
|
312
|
+
type: "text",
|
|
313
|
+
text: JSON.stringify({
|
|
314
|
+
success: false,
|
|
315
|
+
error: errorMessage,
|
|
316
|
+
details: errorDetails,
|
|
317
|
+
}, null, 2),
|
|
318
|
+
},
|
|
319
|
+
],
|
|
320
|
+
isError: true,
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
}
|
|
209
324
|
throw new Error(`Unknown tool: ${request.params.name}`);
|
|
210
325
|
});
|
|
211
326
|
}
|
package/dist/mcp-server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAA;AAClE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAChF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,oCAAoC,CAAA;AAC3C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,iBAAiB,EAAE,
|
|
1
|
+
{"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
|
|
3
3
|
"name": "@scoutello/i18n-magic",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.43.1",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"description": "Intelligent CLI toolkit that automates internationalization workflows with AI-powered translations for JavaScript/TypeScript projects",
|
package/src/mcp-server.ts
CHANGED
|
@@ -5,8 +5,7 @@ import {
|
|
|
5
5
|
ListToolsRequestSchema,
|
|
6
6
|
} from "@modelcontextprotocol/sdk/types.js"
|
|
7
7
|
import { z } from "zod"
|
|
8
|
-
import { addTranslationKey } from "./lib/utils.js"
|
|
9
|
-
import { loadConfig } from "./lib/utils.js"
|
|
8
|
+
import { addTranslationKey, getMissingKeys, loadConfig } from "./lib/utils.js"
|
|
10
9
|
import type { Configuration } from "./lib/types.js"
|
|
11
10
|
import path from "path"
|
|
12
11
|
import fs from "fs"
|
|
@@ -78,6 +77,16 @@ const AddTranslationKeySchema = z.object({
|
|
|
78
77
|
),
|
|
79
78
|
})
|
|
80
79
|
|
|
80
|
+
// Zod schema for the list_untranslated_keys tool parameters
|
|
81
|
+
const ListUntranslatedKeysSchema = z.object({
|
|
82
|
+
namespace: z
|
|
83
|
+
.string()
|
|
84
|
+
.optional()
|
|
85
|
+
.describe(
|
|
86
|
+
"Optional namespace to check. If not provided, checks all namespaces.",
|
|
87
|
+
),
|
|
88
|
+
})
|
|
89
|
+
|
|
81
90
|
class I18nMagicServer {
|
|
82
91
|
private server: Server
|
|
83
92
|
private config: Configuration | null = null
|
|
@@ -153,6 +162,22 @@ class I18nMagicServer {
|
|
|
153
162
|
required: ["key", "value"],
|
|
154
163
|
},
|
|
155
164
|
},
|
|
165
|
+
{
|
|
166
|
+
name: "list_untranslated_keys",
|
|
167
|
+
description:
|
|
168
|
+
"List all translation keys that are used in the codebase but are not yet defined in the locale files. This helps identify missing translations that need to be added. The tool scans the codebase for translation keys and compares them against existing locale files.",
|
|
169
|
+
inputSchema: {
|
|
170
|
+
type: "object",
|
|
171
|
+
properties: {
|
|
172
|
+
namespace: {
|
|
173
|
+
type: "string",
|
|
174
|
+
description:
|
|
175
|
+
"Optional namespace to check. If not provided, checks all namespaces.",
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
required: [],
|
|
179
|
+
},
|
|
180
|
+
},
|
|
156
181
|
],
|
|
157
182
|
}
|
|
158
183
|
})
|
|
@@ -186,11 +211,6 @@ class I18nMagicServer {
|
|
|
186
211
|
console.log = originalConsoleLog
|
|
187
212
|
}
|
|
188
213
|
|
|
189
|
-
// Log to stderr for debugging (this is safe in MCP)
|
|
190
|
-
console.error(
|
|
191
|
-
`[i18n-magic MCP] Added key "${result.key}" to ${result.locale}/${result.namespace}`,
|
|
192
|
-
)
|
|
193
|
-
|
|
194
214
|
return {
|
|
195
215
|
content: [
|
|
196
216
|
{
|
|
@@ -256,6 +276,128 @@ class I18nMagicServer {
|
|
|
256
276
|
}
|
|
257
277
|
}
|
|
258
278
|
|
|
279
|
+
if (request.params.name === "list_untranslated_keys") {
|
|
280
|
+
try {
|
|
281
|
+
// Validate parameters
|
|
282
|
+
const params = ListUntranslatedKeysSchema.parse(
|
|
283
|
+
request.params.arguments,
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
// Ensure config is loaded
|
|
287
|
+
const config = await this.ensureConfig()
|
|
288
|
+
|
|
289
|
+
// Suppress console.log to prevent interference with MCP JSON protocol
|
|
290
|
+
const originalConsoleLog = console.log
|
|
291
|
+
console.log = () => {}
|
|
292
|
+
|
|
293
|
+
let missingKeys
|
|
294
|
+
try {
|
|
295
|
+
// Get missing keys from the codebase
|
|
296
|
+
missingKeys = await getMissingKeys(config)
|
|
297
|
+
} finally {
|
|
298
|
+
// Restore console.log
|
|
299
|
+
console.log = originalConsoleLog
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Filter by namespace if specified
|
|
303
|
+
let filteredKeys = missingKeys
|
|
304
|
+
if (params.namespace) {
|
|
305
|
+
filteredKeys = missingKeys.filter((item) =>
|
|
306
|
+
item.namespaces.includes(params.namespace!),
|
|
307
|
+
)
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// Format the results
|
|
311
|
+
const keysByNamespace: Record<string, string[]> = {}
|
|
312
|
+
for (const item of filteredKeys) {
|
|
313
|
+
for (const namespace of item.namespaces) {
|
|
314
|
+
if (!keysByNamespace[namespace]) {
|
|
315
|
+
keysByNamespace[namespace] = []
|
|
316
|
+
}
|
|
317
|
+
keysByNamespace[namespace].push(item.key)
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Create a summary
|
|
322
|
+
const summary = {
|
|
323
|
+
totalMissingKeys: filteredKeys.length,
|
|
324
|
+
namespaces: Object.entries(keysByNamespace).map(
|
|
325
|
+
([namespace, keys]) => ({
|
|
326
|
+
namespace,
|
|
327
|
+
missingKeyCount: keys.length,
|
|
328
|
+
keys: keys.sort(),
|
|
329
|
+
}),
|
|
330
|
+
),
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
return {
|
|
334
|
+
content: [
|
|
335
|
+
{
|
|
336
|
+
type: "text",
|
|
337
|
+
text: JSON.stringify(
|
|
338
|
+
{
|
|
339
|
+
success: true,
|
|
340
|
+
message:
|
|
341
|
+
filteredKeys.length === 0
|
|
342
|
+
? "No missing translation keys found! All keys used in the codebase are defined."
|
|
343
|
+
: `Found ${filteredKeys.length} missing translation key${filteredKeys.length === 1 ? "" : "s"}`,
|
|
344
|
+
...summary,
|
|
345
|
+
nextSteps:
|
|
346
|
+
filteredKeys.length > 0
|
|
347
|
+
? [
|
|
348
|
+
"Use add_translation_key to add these keys with English values",
|
|
349
|
+
"Or run 'i18n-magic scan' to add them interactively",
|
|
350
|
+
]
|
|
351
|
+
: [],
|
|
352
|
+
},
|
|
353
|
+
null,
|
|
354
|
+
2,
|
|
355
|
+
),
|
|
356
|
+
},
|
|
357
|
+
],
|
|
358
|
+
}
|
|
359
|
+
} catch (error) {
|
|
360
|
+
const errorMessage =
|
|
361
|
+
error instanceof Error ? error.message : "Unknown error occurred"
|
|
362
|
+
|
|
363
|
+
// Get more detailed error information
|
|
364
|
+
let errorDetails = errorMessage
|
|
365
|
+
if (error instanceof Error) {
|
|
366
|
+
const cause = (error as any).cause
|
|
367
|
+
if (cause instanceof Error) {
|
|
368
|
+
errorDetails = `${errorMessage}\nCause: ${cause.message}\nStack: ${cause.stack}`
|
|
369
|
+
} else if (cause) {
|
|
370
|
+
errorDetails = `${errorMessage}\nCause: ${JSON.stringify(cause)}`
|
|
371
|
+
}
|
|
372
|
+
if (error.stack) {
|
|
373
|
+
errorDetails = `${errorDetails}\nStack: ${error.stack}`
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// Log detailed error to stderr for debugging
|
|
378
|
+
console.error(`[i18n-magic MCP] Error listing untranslated keys:`)
|
|
379
|
+
console.error(errorDetails)
|
|
380
|
+
|
|
381
|
+
return {
|
|
382
|
+
content: [
|
|
383
|
+
{
|
|
384
|
+
type: "text",
|
|
385
|
+
text: JSON.stringify(
|
|
386
|
+
{
|
|
387
|
+
success: false,
|
|
388
|
+
error: errorMessage,
|
|
389
|
+
details: errorDetails,
|
|
390
|
+
},
|
|
391
|
+
null,
|
|
392
|
+
2,
|
|
393
|
+
),
|
|
394
|
+
},
|
|
395
|
+
],
|
|
396
|
+
isError: true,
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
259
401
|
throw new Error(`Unknown tool: ${request.params.name}`)
|
|
260
402
|
})
|
|
261
403
|
}
|