@scoutello/i18n-magic 0.54.0 → 0.55.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/src/mcp-server.ts CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  ListToolsRequestSchema,
6
6
  } from "@modelcontextprotocol/sdk/types.js"
7
7
  import { z } from "zod"
8
- import { addTranslationKey, getMissingKeys, loadConfig, loadLocalesFile } from "./lib/utils.js"
8
+ import { addTranslationKey, addTranslationKeys, getMissingKeys, loadConfig, loadLocalesFile } from "./lib/utils.js"
9
9
  import type { Configuration } from "./lib/types.js"
10
10
  import path from "path"
11
11
  import fs from "fs"
@@ -71,6 +71,15 @@ const AddTranslationKeySchema = z.object({
71
71
  language: z.string().optional().describe("The language code of the provided value (e.g., \"en\", \"de\", \"fr\"). Defaults to \"en\" (English) if not specified."),
72
72
  })
73
73
 
74
+ // Zod schema for the add_translation_keys (batch) tool parameters
75
+ const AddTranslationKeysSchema = z.object({
76
+ keys: z.array(z.object({
77
+ key: z.string().describe("The translation key to add (e.g., \"welcomeMessage\")"),
78
+ value: z.string().describe("The text value for this translation key"),
79
+ language: z.string().optional().describe("The language code of the provided value (e.g., \"en\", \"de\", \"fr\"). Defaults to \"en\" (English) if not specified."),
80
+ })).describe("Array of translation keys to add in batch. Use this for adding multiple keys at once for better performance."),
81
+ })
82
+
74
83
  // Zod schema for the list_untranslated_keys tool parameters
75
84
  const ListUntranslatedKeysSchema = z.object({
76
85
  namespace: z
@@ -184,7 +193,7 @@ class I18nMagicServer {
184
193
  tools: [
185
194
  {
186
195
  name: "add_translation_key",
187
- description: "Add a new translation key with a text value. You can optionally specify the language of the value you're providing (defaults to English).",
196
+ description: "Add a new translation key with a text value. You can optionally specify the language of the value you're providing (defaults to English). For adding multiple keys at once, use add_translation_keys instead for better performance.",
188
197
  inputSchema: {
189
198
  type: "object",
190
199
  properties: {
@@ -207,6 +216,38 @@ class I18nMagicServer {
207
216
  required: ["key", "value"],
208
217
  },
209
218
  },
219
+ {
220
+ name: "add_translation_keys",
221
+ description: "Add multiple translation keys in batch. This is optimized for performance - when adding 2 or more keys, prefer this over multiple add_translation_key calls. It performs a single codebase scan, batches file I/O operations, and batches translations for much better performance.",
222
+ inputSchema: {
223
+ type: "object",
224
+ properties: {
225
+ keys: {
226
+ type: "array",
227
+ description: "Array of translation keys to add in batch",
228
+ items: {
229
+ type: "object",
230
+ properties: {
231
+ key: {
232
+ type: "string",
233
+ description: "The translation key to add (e.g., \"welcomeMessage\")",
234
+ },
235
+ value: {
236
+ type: "string",
237
+ description: "The text value for this translation key",
238
+ },
239
+ language: {
240
+ type: "string",
241
+ description: "The language code of the provided value (e.g., \"en\" for English, \"de\" for German, \"fr\" for French). Defaults to \"en\" if not specified.",
242
+ },
243
+ },
244
+ required: ["key", "value"],
245
+ },
246
+ },
247
+ },
248
+ required: ["keys"],
249
+ },
250
+ },
210
251
  {
211
252
  name: "list_untranslated_keys",
212
253
  description:
@@ -399,6 +440,131 @@ class I18nMagicServer {
399
440
  }
400
441
  }
401
442
 
443
+ if (request.params.name === "add_translation_keys") {
444
+ try {
445
+ // Validate parameters
446
+ const params = AddTranslationKeysSchema.parse(request.params.arguments)
447
+
448
+ if (!params.keys || params.keys.length === 0) {
449
+ return {
450
+ content: [
451
+ {
452
+ type: "text",
453
+ text: JSON.stringify(
454
+ {
455
+ success: false,
456
+ error: "No keys provided. The 'keys' array must contain at least one key-value pair.",
457
+ },
458
+ null,
459
+ 2,
460
+ ),
461
+ },
462
+ ],
463
+ isError: true,
464
+ }
465
+ }
466
+
467
+ // Ensure config is loaded
468
+ const config = await this.ensureConfig()
469
+
470
+ // Capture console.log output for diagnostics
471
+ const originalConsoleLog = console.log
472
+ const logMessages: string[] = []
473
+ console.log = (...args: any[]) => {
474
+ const message = args.map(arg =>
475
+ typeof arg === 'object' ? JSON.stringify(arg) : String(arg)
476
+ ).join(' ')
477
+ logMessages.push(message)
478
+ // Also log to stderr for debugging
479
+ console.error(`[i18n-magic] ${message}`)
480
+ }
481
+
482
+ let result
483
+ try {
484
+ // Add the translation keys in batch
485
+ result = await addTranslationKeys({
486
+ keys: params.keys.map(k => ({
487
+ key: k.key,
488
+ value: k.value,
489
+ language: k.language || "en",
490
+ })),
491
+ config,
492
+ })
493
+ } finally {
494
+ // Restore console.log
495
+ console.log = originalConsoleLog
496
+ }
497
+
498
+ return {
499
+ content: [
500
+ {
501
+ type: "text",
502
+ text: JSON.stringify(
503
+ {
504
+ success: true,
505
+ message: `Successfully added ${result.results.length} translation key(s) in batch`,
506
+ results: result.results,
507
+ performance: result.performance,
508
+ summary: {
509
+ totalKeys: result.results.length,
510
+ totalTime: `${result.performance.totalTime.toFixed(2)}ms`,
511
+ averageTimePerKey: `${(result.performance.totalTime / result.results.length).toFixed(2)}ms`,
512
+ scanTime: `${result.performance.scanTime.toFixed(2)}ms`,
513
+ translationTime: `${result.performance.translationTime.toFixed(2)}ms`,
514
+ fileIOTime: `${result.performance.fileIOTime.toFixed(2)}ms`,
515
+ },
516
+ diagnostics: logMessages.join('\n'),
517
+ },
518
+ null,
519
+ 2,
520
+ ),
521
+ },
522
+ ],
523
+ }
524
+ } catch (error) {
525
+ const errorMessage =
526
+ error instanceof Error ? error.message : "Unknown error occurred"
527
+
528
+ // Get more detailed error information
529
+ let errorDetails = errorMessage
530
+ if (error instanceof Error) {
531
+ // Check if there's a cause
532
+ const cause = (error as any).cause
533
+ if (cause instanceof Error) {
534
+ errorDetails = `${errorMessage}\nCause: ${cause.message}\nStack: ${cause.stack}`
535
+ } else if (cause) {
536
+ errorDetails = `${errorMessage}\nCause: ${JSON.stringify(cause)}`
537
+ }
538
+ // Include stack trace
539
+ if (error.stack) {
540
+ errorDetails = `${errorDetails}\nStack: ${error.stack}`
541
+ }
542
+ }
543
+
544
+ // Log detailed error to stderr for debugging
545
+ console.error(`[i18n-magic MCP] Error adding translation keys in batch:`)
546
+ console.error(errorDetails)
547
+
548
+ return {
549
+ content: [
550
+ {
551
+ type: "text",
552
+ text: JSON.stringify(
553
+ {
554
+ success: false,
555
+ error: errorMessage,
556
+ details: errorDetails,
557
+ },
558
+ null,
559
+ 2,
560
+ ),
561
+ },
562
+ ],
563
+ isError: true,
564
+ }
565
+ }
566
+ }
567
+
402
568
  if (request.params.name === "list_untranslated_keys") {
403
569
  try {
404
570
  // Validate parameters