@scoutello/i18n-magic 0.65.0 → 0.67.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/README.md +16 -10
- package/dist/cli.js +20 -15
- package/dist/cli.js.map +1 -1
- package/dist/commands/check-missing.d.ts +11 -1
- package/dist/commands/check-missing.d.ts.map +1 -1
- package/dist/commands/check-missing.js +56 -96
- package/dist/commands/check-missing.js.map +1 -1
- package/dist/commands/replace.d.ts +6 -0
- package/dist/commands/replace.d.ts.map +1 -1
- package/dist/commands/replace.js +48 -29
- package/dist/commands/replace.js.map +1 -1
- package/dist/commands/scan.d.ts.map +1 -1
- package/dist/commands/scan.js +114 -80
- package/dist/commands/scan.js.map +1 -1
- package/dist/commands/sync-locales.d.ts.map +1 -1
- package/dist/commands/sync-locales.js +21 -28
- package/dist/commands/sync-locales.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/locale-storage.d.ts +7 -0
- package/dist/lib/locale-storage.d.ts.map +1 -0
- package/dist/lib/locale-storage.js +49 -0
- package/dist/lib/locale-storage.js.map +1 -0
- package/dist/lib/mcp-write-schemas.d.ts +56 -0
- package/dist/lib/mcp-write-schemas.d.ts.map +1 -0
- package/dist/lib/mcp-write-schemas.js +36 -0
- package/dist/lib/mcp-write-schemas.js.map +1 -0
- package/dist/lib/translation-response.d.ts +8 -0
- package/dist/lib/translation-response.d.ts.map +1 -0
- package/dist/lib/translation-response.js +43 -0
- package/dist/lib/translation-response.js.map +1 -0
- package/dist/lib/types.d.ts +1 -1
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/update-translation-key.d.ts +16 -0
- package/dist/lib/update-translation-key.d.ts.map +1 -0
- package/dist/lib/update-translation-key.js +67 -0
- package/dist/lib/update-translation-key.js.map +1 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/lib/utils.d.ts.map +1 -1
- package/dist/lib/utils.js +69 -51
- package/dist/lib/utils.js.map +1 -1
- package/dist/mcp-server.js +30 -117
- package/dist/mcp-server.js.map +1 -1
- package/package.json +5 -9
- package/src/cli.ts +26 -18
- package/src/commands/check-missing.ts +83 -137
- package/src/commands/replace.ts +81 -43
- package/src/commands/scan.ts +130 -108
- package/src/commands/sync-locales.ts +41 -63
- package/src/index.ts +6 -1
- package/src/lib/locale-storage.ts +76 -0
- package/src/lib/mcp-write-schemas.ts +46 -0
- package/src/lib/translation-response.ts +59 -0
- package/src/lib/types.ts +1 -1
- package/src/lib/update-translation-key.ts +119 -0
- package/src/lib/utils.ts +92 -76
- package/src/mcp-server.ts +38 -167
package/src/mcp-server.ts
CHANGED
|
@@ -9,7 +9,14 @@ import OpenAI from "openai"
|
|
|
9
9
|
import path from "path"
|
|
10
10
|
import { fileURLToPath } from "url"
|
|
11
11
|
import { z } from "zod"
|
|
12
|
+
import {
|
|
13
|
+
AddTranslationKeySchema,
|
|
14
|
+
AddTranslationKeysSchema,
|
|
15
|
+
MCP_WRITE_REQUIRED_FIELDS,
|
|
16
|
+
UpdateTranslationKeySchema,
|
|
17
|
+
} from "./lib/mcp-write-schemas.js"
|
|
12
18
|
import type { Configuration } from "./lib/types.js"
|
|
19
|
+
import { updateTranslationKeyOperation } from "./lib/update-translation-key.js"
|
|
13
20
|
import {
|
|
14
21
|
addTranslationKey,
|
|
15
22
|
addTranslationKeys,
|
|
@@ -150,46 +157,6 @@ function resolveProjectRoot(): string {
|
|
|
150
157
|
return cwd
|
|
151
158
|
}
|
|
152
159
|
|
|
153
|
-
// Zod schema for the add_translation_key tool parameters
|
|
154
|
-
const AddTranslationKeySchema = z.object({
|
|
155
|
-
key: z
|
|
156
|
-
.string()
|
|
157
|
-
.describe(
|
|
158
|
-
'The translation key to add (e.g., "welcomeMessage").',
|
|
159
|
-
),
|
|
160
|
-
value: z.string().describe("The text value for this translation key"),
|
|
161
|
-
language: z
|
|
162
|
-
.string()
|
|
163
|
-
.optional()
|
|
164
|
-
.describe(
|
|
165
|
-
'The language code of the provided value (e.g., "en", "de", "fr"). Defaults to "en" (English) if not specified.',
|
|
166
|
-
),
|
|
167
|
-
})
|
|
168
|
-
|
|
169
|
-
// Zod schema for the add_translation_keys (batch) tool parameters
|
|
170
|
-
const AddTranslationKeysSchema = z.object({
|
|
171
|
-
keys: z
|
|
172
|
-
.array(
|
|
173
|
-
z.object({
|
|
174
|
-
key: z
|
|
175
|
-
.string()
|
|
176
|
-
.describe(
|
|
177
|
-
'The translation key to add (e.g., "welcomeMessage").',
|
|
178
|
-
),
|
|
179
|
-
value: z.string().describe("The text value for this translation key"),
|
|
180
|
-
language: z
|
|
181
|
-
.string()
|
|
182
|
-
.optional()
|
|
183
|
-
.describe(
|
|
184
|
-
'The language code of the provided value (e.g., "en", "de", "fr"). Defaults to "en" (English) if not specified.',
|
|
185
|
-
),
|
|
186
|
-
}),
|
|
187
|
-
)
|
|
188
|
-
.describe(
|
|
189
|
-
"Array of translation keys to add in batch. Use this for adding multiple keys at once for better performance.",
|
|
190
|
-
),
|
|
191
|
-
})
|
|
192
|
-
|
|
193
160
|
// Zod schema for the list_untranslated_keys tool parameters
|
|
194
161
|
const ListUntranslatedKeysSchema = z.object({})
|
|
195
162
|
|
|
@@ -200,20 +167,6 @@ const GetTranslationKeySchema = z.object({
|
|
|
200
167
|
.describe('The translation key to retrieve (e.g., "welcomeMessage")'),
|
|
201
168
|
})
|
|
202
169
|
|
|
203
|
-
// Zod schema for the update_translation_key tool parameters
|
|
204
|
-
const UpdateTranslationKeySchema = z.object({
|
|
205
|
-
key: z
|
|
206
|
-
.string()
|
|
207
|
-
.describe('The translation key to update (e.g., "welcomeMessage")'),
|
|
208
|
-
value: z.string().describe("The new text value for this translation key"),
|
|
209
|
-
language: z
|
|
210
|
-
.string()
|
|
211
|
-
.optional()
|
|
212
|
-
.describe(
|
|
213
|
-
'The language code of the provided value (e.g., "en", "de", "fr"). Defaults to "en" (English) if not specified.',
|
|
214
|
-
),
|
|
215
|
-
})
|
|
216
|
-
|
|
217
170
|
// Zod schema for the search_translations tool parameters
|
|
218
171
|
const SearchTranslationsSchema = z.object({
|
|
219
172
|
query: z
|
|
@@ -299,7 +252,7 @@ class I18nMagicServer {
|
|
|
299
252
|
{
|
|
300
253
|
name: "add_translation_key",
|
|
301
254
|
description:
|
|
302
|
-
"Add a new translation key with a text value. The destination translation file is resolved automatically from project configuration and code usage.
|
|
255
|
+
"Add a new translation key with a text value and its explicit source language. The destination translation file is resolved automatically from project configuration and code usage. For adding multiple keys at once, use add_translation_keys instead for better performance. NOTE: This tool can only ADD keys, it will NEVER remove any existing keys.",
|
|
303
256
|
inputSchema: {
|
|
304
257
|
type: "object",
|
|
305
258
|
properties: {
|
|
@@ -315,10 +268,10 @@ class I18nMagicServer {
|
|
|
315
268
|
language: {
|
|
316
269
|
type: "string",
|
|
317
270
|
description:
|
|
318
|
-
|
|
271
|
+
"Required configured language code of the provided value (for example, en or de).",
|
|
319
272
|
},
|
|
320
273
|
},
|
|
321
|
-
required: [
|
|
274
|
+
required: [...MCP_WRITE_REQUIRED_FIELDS],
|
|
322
275
|
},
|
|
323
276
|
},
|
|
324
277
|
{
|
|
@@ -346,10 +299,10 @@ class I18nMagicServer {
|
|
|
346
299
|
language: {
|
|
347
300
|
type: "string",
|
|
348
301
|
description:
|
|
349
|
-
|
|
302
|
+
"Required configured language code of the provided value (for example, en or de).",
|
|
350
303
|
},
|
|
351
304
|
},
|
|
352
|
-
required: [
|
|
305
|
+
required: [...MCP_WRITE_REQUIRED_FIELDS],
|
|
353
306
|
},
|
|
354
307
|
},
|
|
355
308
|
},
|
|
@@ -385,7 +338,7 @@ class I18nMagicServer {
|
|
|
385
338
|
{
|
|
386
339
|
name: "update_translation_key",
|
|
387
340
|
description:
|
|
388
|
-
"Update an existing translation key with a new text value
|
|
341
|
+
"Update an existing translation key with a new text value and its explicit source language. With a provider, every locale is translated before writes begin. Without a provider, only the supplied locale is updated and other locales are returned as pending. NOTE: This tool can only UPDATE existing keys, it will NEVER remove any keys.",
|
|
389
342
|
inputSchema: {
|
|
390
343
|
type: "object",
|
|
391
344
|
properties: {
|
|
@@ -401,10 +354,10 @@ class I18nMagicServer {
|
|
|
401
354
|
language: {
|
|
402
355
|
type: "string",
|
|
403
356
|
description:
|
|
404
|
-
|
|
357
|
+
"Required configured language code of the provided value (for example, en or de).",
|
|
405
358
|
},
|
|
406
359
|
},
|
|
407
|
-
required: [
|
|
360
|
+
required: [...MCP_WRITE_REQUIRED_FIELDS],
|
|
408
361
|
},
|
|
409
362
|
},
|
|
410
363
|
{
|
|
@@ -448,7 +401,7 @@ class I18nMagicServer {
|
|
|
448
401
|
return await addTranslationKey({
|
|
449
402
|
key: params.key,
|
|
450
403
|
value: params.value,
|
|
451
|
-
language: params.language
|
|
404
|
+
language: params.language,
|
|
452
405
|
config,
|
|
453
406
|
})
|
|
454
407
|
})
|
|
@@ -467,7 +420,7 @@ class I18nMagicServer {
|
|
|
467
420
|
message: `Successfully added translation key "${result.key}"`,
|
|
468
421
|
key: result.key,
|
|
469
422
|
value: result.value,
|
|
470
|
-
providedLanguage:
|
|
423
|
+
providedLanguage: result.providedLanguage,
|
|
471
424
|
locales: result.locale,
|
|
472
425
|
nextStep: result.locale.includes(",")
|
|
473
426
|
? "Key was automatically translated to multiple locales"
|
|
@@ -564,7 +517,7 @@ class I18nMagicServer {
|
|
|
564
517
|
keys: params.keys.map((k) => ({
|
|
565
518
|
key: k.key,
|
|
566
519
|
value: k.value,
|
|
567
|
-
language: k.language
|
|
520
|
+
language: k.language,
|
|
568
521
|
})),
|
|
569
522
|
config,
|
|
570
523
|
})
|
|
@@ -691,7 +644,7 @@ class I18nMagicServer {
|
|
|
691
644
|
nextSteps:
|
|
692
645
|
missingKeys.length > 0
|
|
693
646
|
? [
|
|
694
|
-
"Use add_translation_key
|
|
647
|
+
"Use add_translation_key with each value and its explicit source language (for example, language: \"en\")",
|
|
695
648
|
"Or run 'i18n-magic scan' to add them interactively",
|
|
696
649
|
]
|
|
697
650
|
: [],
|
|
@@ -892,102 +845,14 @@ class I18nMagicServer {
|
|
|
892
845
|
console.log = () => {}
|
|
893
846
|
|
|
894
847
|
try {
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
const keys = await loadLocalesFile(
|
|
904
|
-
config.loadPath,
|
|
905
|
-
"en",
|
|
906
|
-
namespace,
|
|
907
|
-
)
|
|
908
|
-
if (Object.hasOwn(keys, params.key)) {
|
|
909
|
-
targetNamespaces.push(namespace)
|
|
910
|
-
}
|
|
911
|
-
} catch (error) {
|
|
912
|
-
// Namespace file doesn't exist, continue
|
|
913
|
-
}
|
|
914
|
-
}
|
|
915
|
-
|
|
916
|
-
if (targetNamespaces.length === 0) {
|
|
917
|
-
throw new Error(
|
|
918
|
-
`Key "${params.key}" does not exist in translation files. Use add_translation_key to create it.`,
|
|
919
|
-
)
|
|
920
|
-
}
|
|
921
|
-
|
|
922
|
-
// Build translation cache with new value
|
|
923
|
-
const inputLanguage = params.language || "en"
|
|
924
|
-
const translationCache: Record<string, string> = {
|
|
925
|
-
[inputLanguage]: params.value,
|
|
926
|
-
}
|
|
927
|
-
|
|
928
|
-
// Translate to all other locales
|
|
929
|
-
const otherLocales = config.locales.filter(
|
|
930
|
-
(l) => l !== inputLanguage,
|
|
931
|
-
)
|
|
932
|
-
if (otherLocales.length > 0 && config.openai) {
|
|
933
|
-
const { translateKey } = await import("./lib/utils.js")
|
|
934
|
-
|
|
935
|
-
await Promise.all(
|
|
936
|
-
otherLocales.map(async (locale) => {
|
|
937
|
-
const translation = await translateKey({
|
|
938
|
-
context: config.context || "",
|
|
939
|
-
inputLanguage: inputLanguage,
|
|
940
|
-
outputLanguage: locale,
|
|
941
|
-
object: {
|
|
942
|
-
[params.key]: params.value,
|
|
943
|
-
},
|
|
944
|
-
openai: config.openai!,
|
|
945
|
-
model: config.model,
|
|
946
|
-
})
|
|
947
|
-
translationCache[locale] = translation[params.key]
|
|
948
|
-
}),
|
|
949
|
-
)
|
|
950
|
-
}
|
|
951
|
-
|
|
952
|
-
// Update the key in all relevant namespaces and locales
|
|
953
|
-
// Process sequentially to avoid race conditions
|
|
954
|
-
const { writeLocalesFile } = await import("./lib/utils.js")
|
|
955
|
-
|
|
956
|
-
for (const namespace of targetNamespaces) {
|
|
957
|
-
for (const locale of config.locales) {
|
|
958
|
-
const newValue = translationCache[locale] || params.value
|
|
959
|
-
|
|
960
|
-
// Load existing keys
|
|
961
|
-
const existingKeys = await loadLocalesFile(
|
|
962
|
-
config.loadPath,
|
|
963
|
-
locale,
|
|
964
|
-
namespace,
|
|
965
|
-
)
|
|
966
|
-
|
|
967
|
-
const originalKeyCount = Object.keys(existingKeys).length
|
|
968
|
-
|
|
969
|
-
// Update the specific key
|
|
970
|
-
existingKeys[params.key] = newValue
|
|
971
|
-
|
|
972
|
-
const newKeyCount = Object.keys(existingKeys).length
|
|
973
|
-
|
|
974
|
-
// Safety check: we should only be updating, not removing
|
|
975
|
-
// Key count should stay same (update) or increase by 1 (add)
|
|
976
|
-
if (newKeyCount < originalKeyCount) {
|
|
977
|
-
throw new Error(
|
|
978
|
-
`Safety check failed: Updating locale "${locale}" would reduce keys from ${originalKeyCount} to ${newKeyCount}. Aborting.`,
|
|
979
|
-
)
|
|
980
|
-
}
|
|
981
|
-
|
|
982
|
-
await writeLocalesFile(
|
|
983
|
-
config.savePath,
|
|
984
|
-
locale,
|
|
985
|
-
namespace,
|
|
986
|
-
existingKeys,
|
|
987
|
-
)
|
|
988
|
-
}
|
|
989
|
-
}
|
|
990
|
-
})
|
|
848
|
+
const result = await translationMutex.withLock(async () =>
|
|
849
|
+
updateTranslationKeyOperation({
|
|
850
|
+
config,
|
|
851
|
+
key: params.key,
|
|
852
|
+
value: params.value,
|
|
853
|
+
language: params.language,
|
|
854
|
+
}),
|
|
855
|
+
)
|
|
991
856
|
|
|
992
857
|
return {
|
|
993
858
|
content: [
|
|
@@ -996,11 +861,17 @@ class I18nMagicServer {
|
|
|
996
861
|
text: JSON.stringify(
|
|
997
862
|
{
|
|
998
863
|
success: true,
|
|
999
|
-
message: `Successfully updated translation key "${
|
|
1000
|
-
key:
|
|
1001
|
-
newValue:
|
|
1002
|
-
providedLanguage:
|
|
1003
|
-
|
|
864
|
+
message: `Successfully updated translation key "${result.key}" in ${result.updatedLocales.length} locale(s)`,
|
|
865
|
+
key: result.key,
|
|
866
|
+
newValue: result.value,
|
|
867
|
+
providedLanguage: result.sourceLocale,
|
|
868
|
+
updatedLocales: result.updatedLocales,
|
|
869
|
+
pendingLocales: result.pendingLocales,
|
|
870
|
+
locales: result.updatedLocales,
|
|
871
|
+
nextStep:
|
|
872
|
+
result.pendingLocales.length > 0
|
|
873
|
+
? "Run 'i18n-magic sync' with a configured provider to translate pending locales."
|
|
874
|
+
: "All configured locales were updated.",
|
|
1004
875
|
},
|
|
1005
876
|
null,
|
|
1006
877
|
2,
|