Skip to content

Commit 01a847e

Browse files
authored
Merge pull request #1738 from feifei325/i18n/fix_missing_settings_key
fix missing settings key and add find i18n key scripts
2 parents 4fd5e44 + fddb611 commit 01a847e

File tree

18 files changed

+429
-1
lines changed

18 files changed

+429
-1
lines changed

scripts/find-missing-i18n-key.js

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
const fs = require("fs")
2+
const path = require("path")
3+
4+
// Parse command-line arguments
5+
const args = process.argv.slice(2).reduce((acc, arg) => {
6+
if (arg === "--help") {
7+
acc.help = true
8+
} else if (arg.startsWith("--locale=")) {
9+
acc.locale = arg.split("=")[1]
10+
} else if (arg.startsWith("--file=")) {
11+
acc.file = arg.split("=")[1]
12+
}
13+
return acc
14+
}, {})
15+
16+
// Display help information
17+
if (args.help) {
18+
console.log(`
19+
Find missing i18n translations
20+
21+
A useful script to identify whether the i18n keys used in component files exist in all language files.
22+
23+
Usage:
24+
node scripts/find-missing-i18n-key.js [options]
25+
26+
Options:
27+
--locale=<locale> Only check a specific language (e.g., --locale=de)
28+
--file=<file> Only check a specific file (e.g., --file=chat.json)
29+
--help Display help information
30+
31+
Output:
32+
- Generate a report of missing translations
33+
`)
34+
process.exit(0)
35+
}
36+
37+
// Directory to traverse
38+
const TARGET_DIR = path.join(__dirname, "../webview-ui/src/components")
39+
const LOCALES_DIR = path.join(__dirname, "../webview-ui/src/i18n/locales")
40+
41+
// Regular expressions to match i18n keys
42+
const i18nPatterns = [
43+
/{t\("([^"]+)"\)}/g, // Match {t("key")} format
44+
/i18nKey="([^"]+)"/g, // Match i18nKey="key" format
45+
/t\("([a-zA-Z][a-zA-Z0-9_]*[:.][a-zA-Z0-9_.]+)"\)/g, // Match t("key") format, where key contains a colon or dot
46+
]
47+
48+
// Get all language directories
49+
function getLocaleDirs() {
50+
const allLocales = fs.readdirSync(LOCALES_DIR).filter((file) => {
51+
const stats = fs.statSync(path.join(LOCALES_DIR, file))
52+
return stats.isDirectory() // Do not exclude any language directories
53+
})
54+
55+
// Filter to a specific language if specified
56+
return args.locale ? allLocales.filter((locale) => locale === args.locale) : allLocales
57+
}
58+
59+
// Get the value from JSON by path
60+
function getValueByPath(obj, path) {
61+
const parts = path.split(".")
62+
let current = obj
63+
64+
for (const part of parts) {
65+
if (current === undefined || current === null) {
66+
return undefined
67+
}
68+
current = current[part]
69+
}
70+
71+
return current
72+
}
73+
74+
// Check if the key exists in all language files, return a list of missing language files
75+
function checkKeyInLocales(key, localeDirs) {
76+
const [file, ...pathParts] = key.split(":")
77+
const jsonPath = pathParts.join(".")
78+
79+
const missingLocales = []
80+
81+
localeDirs.forEach((locale) => {
82+
const filePath = path.join(LOCALES_DIR, locale, `${file}.json`)
83+
if (!fs.existsSync(filePath)) {
84+
missingLocales.push(`${locale}/${file}.json`)
85+
return
86+
}
87+
88+
const json = JSON.parse(fs.readFileSync(filePath, "utf8"))
89+
if (getValueByPath(json, jsonPath) === undefined) {
90+
missingLocales.push(`${locale}/${file}.json`)
91+
}
92+
})
93+
94+
return missingLocales
95+
}
96+
97+
// Recursively traverse the directory
98+
function findMissingI18nKeys() {
99+
const localeDirs = getLocaleDirs()
100+
const results = []
101+
102+
function walk(dir) {
103+
const files = fs.readdirSync(dir)
104+
105+
for (const file of files) {
106+
const filePath = path.join(dir, file)
107+
const stat = fs.statSync(filePath)
108+
109+
// Exclude test files
110+
if (filePath.includes(".test.")) continue
111+
112+
if (stat.isDirectory()) {
113+
walk(filePath) // Recursively traverse subdirectories
114+
} else if (stat.isFile() && [".ts", ".tsx", ".js", ".jsx"].includes(path.extname(filePath))) {
115+
const content = fs.readFileSync(filePath, "utf8")
116+
117+
// Match all i18n keys
118+
for (const pattern of i18nPatterns) {
119+
let match
120+
while ((match = pattern.exec(content)) !== null) {
121+
const key = match[1]
122+
const missingLocales = checkKeyInLocales(key, localeDirs)
123+
if (missingLocales.length > 0) {
124+
results.push({
125+
key,
126+
missingLocales,
127+
file: path.relative(TARGET_DIR, filePath),
128+
})
129+
}
130+
}
131+
}
132+
}
133+
}
134+
}
135+
136+
walk(TARGET_DIR)
137+
return results
138+
}
139+
140+
// Execute and output the results
141+
function main() {
142+
try {
143+
const localeDirs = getLocaleDirs()
144+
if (args.locale && localeDirs.length === 0) {
145+
console.error(`Error: Language '${args.locale}' not found in ${LOCALES_DIR}`)
146+
process.exit(1)
147+
}
148+
149+
console.log(`Checking ${localeDirs.length} non-English languages: ${localeDirs.join(", ")}`)
150+
151+
const missingKeys = findMissingI18nKeys()
152+
153+
if (missingKeys.length === 0) {
154+
console.log("\n✅ All i18n keys are present!")
155+
return
156+
}
157+
158+
console.log("\nMissing i18n keys:\n")
159+
missingKeys.forEach(({ key, missingLocales, file }) => {
160+
console.log(`File: ${file}`)
161+
console.log(`Key: ${key}`)
162+
console.log("Missing in:")
163+
missingLocales.forEach((file) => console.log(` - ${file}`))
164+
console.log("-------------------")
165+
})
166+
167+
// Exit code 1 indicates missing keys
168+
process.exit(1)
169+
} catch (error) {
170+
console.error("Error:", error.message)
171+
console.error(error.stack)
172+
process.exit(1)
173+
}
174+
}
175+
176+
main()

webview-ui/src/components/chat/ChatView.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
152152
setSecondaryButtonText(t("chat:reject.title"))
153153
break
154154
case "finishTask":
155-
setPrimaryButtonText(t("chat:completeSubtaskAndReturn.title"))
155+
setPrimaryButtonText(t("chat:completeSubtaskAndReturn"))
156156
setSecondaryButtonText(undefined)
157157
break
158158
default:

webview-ui/src/components/settings/ApiOptions.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,6 +1448,18 @@ const ApiOptions = ({
14481448
<span className="font-medium">Custom ARN</span>
14491449
</VSCodeTextField>
14501450
<div className="text-sm text-vscode-descriptionForeground -mt-2">
1451+
{t("settings:providers.awsCustomArnUse")}
1452+
<ul className="list-disc pl-5 mt-1">
1453+
<li>
1454+
arn:aws:bedrock:us-east-1:123456789012:foundation-model/anthropic.claude-3-sonnet-20240229-v1:0
1455+
</li>
1456+
<li>
1457+
arn:aws:bedrock:us-west-2:123456789012:provisioned-model/my-provisioned-model
1458+
</li>
1459+
<li>
1460+
arn:aws:bedrock:us-east-1:123456789012:default-prompt-router/anthropic.claude:1
1461+
</li>
1462+
</ul>
14511463
{t("settings:providers.awsCustomArnDesc")}
14521464
</div>
14531465
{apiConfiguration?.awsCustomArn &&

webview-ui/src/i18n/locales/ca/settings.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,20 @@
7474
"description": "Descripció",
7575
"apiProvider": "Proveïdor d'API",
7676
"openRouterApiKey": "Clau API d'OpenRouter",
77+
"nameEmpty": "El nom no pot estar buit",
78+
"nameExists": "Ja existeix un perfil amb aquest nom",
79+
"deleteProfile": "Esborrar perfil",
80+
"invalidArnFormat": "Format ARN no vàlid. Comprova els exemples anteriors.",
81+
"enterNewName": "Introduïu un nou nom",
82+
"addProfile": "Afegeix perfil",
83+
"renameProfile": "Canvia el nom del perfil",
84+
"newProfile": "Nou perfil de configuració",
85+
"enterProfileName": "Introduïu el nom del perfil",
86+
"createProfile": "Crea perfil",
87+
"cannotDeleteOnlyProfile": "No es pot eliminar l'únic perfil",
88+
"vscodeLmDescription": "L'API del model de llenguatge de VS Code us permet executar models proporcionats per altres extensions de VS Code (incloent-hi, però no limitat a, GitHub Copilot). La manera més senzilla de començar és instal·lar les extensions Copilot i Copilot Chat des del VS Code Marketplace.",
89+
"awsCustomArnUse": "Introduïu un ARN vàlid d'AWS Bedrock per al model que voleu utilitzar. Exemples de format:",
90+
"awsCustomArnDesc": "Assegureu-vos que la regió a l'ARN coincideix amb la regió d'AWS seleccionada anteriorment.",
7791
"apiKeyStorageNotice": "Les claus API s'emmagatzemen de forma segura a l'Emmagatzematge Secret de VSCode",
7892
"useCustomBaseUrl": "Utilitzar URL base personalitzada",
7993
"openRouterTransformsText": "Comprimir prompts i cadenes de missatges a la mida del context (<a>Transformacions d'OpenRouter</a>)",
@@ -104,6 +118,8 @@
104118
"awsSessionToken": "Token de sessió d'AWS",
105119
"awsRegion": "Regió d'AWS",
106120
"awsCrossRegion": "Utilitzar inferència entre regions",
121+
"vscodeLmModel": "Model de llenguatge",
122+
"vscodeLmWarning": "Nota: Aquesta és una integració molt experimental i el suport del proveïdor variarà. Si rebeu un error sobre un model no compatible, és un problema del proveïdor.",
107123
"googleCloudSetup": {
108124
"title": "Per utilitzar Google Cloud Vertex AI, necessiteu:",
109125
"step1": "1. Crear un compte de Google Cloud, habilitar l'API de Vertex AI i habilitar els models Claude necessaris.",

webview-ui/src/i18n/locales/de/settings.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,20 @@
7474
"description": "Beschreibung",
7575
"apiProvider": "API-Anbieter",
7676
"model": "Modell",
77+
"nameEmpty": "Name darf nicht leer sein",
78+
"nameExists": "Ein Profil mit diesem Namen existiert bereits",
79+
"deleteProfile": "Profil löschen",
80+
"invalidArnFormat": "Ungültiges ARN-Format. Überprüfen Sie die obigen Beispiele.",
81+
"enterNewName": "Neuen Namen eingeben",
82+
"addProfile": "Profil hinzufügen",
83+
"renameProfile": "Profil umbenennen",
84+
"newProfile": "Neues Konfigurationsprofil",
85+
"enterProfileName": "Profilnamen eingeben",
86+
"createProfile": "Profil erstellen",
87+
"cannotDeleteOnlyProfile": "Das einzige Profil kann nicht gelöscht werden",
88+
"vscodeLmDescription": "Die VS Code Language Model API ermöglicht das Ausführen von Modellen, die von anderen VS Code-Erweiterungen bereitgestellt werden (einschließlich, aber nicht beschränkt auf GitHub Copilot). Der einfachste Weg, um zu starten, besteht darin, die Erweiterungen Copilot und Copilot Chat aus dem VS Code Marketplace zu installieren.",
89+
"awsCustomArnUse": "Geben Sie eine gültige AWS Bedrock ARN für das Modell ein, das Sie verwenden möchten. Formatbeispiele:",
90+
"awsCustomArnDesc": "Stellen Sie sicher, dass die Region in der ARN mit Ihrer oben ausgewählten AWS-Region übereinstimmt.",
7791
"openRouterApiKey": "OpenRouter API-Schlüssel",
7892
"getOpenRouterApiKey": "OpenRouter API-Schlüssel erhalten",
7993
"apiKeyStorageNotice": "API-Schlüssel werden sicher im VSCode Secret Storage gespeichert",
@@ -104,6 +118,8 @@
104118
"awsSessionToken": "AWS Sitzungstoken",
105119
"awsRegion": "AWS Region",
106120
"awsCrossRegion": "Regionsübergreifende Inferenz verwenden",
121+
"vscodeLmModel": "Sprachmodell",
122+
"vscodeLmWarning": "Hinweis: Dies ist eine sehr experimentelle Integration und die Anbieterunterstützung variiert. Wenn Sie einen Fehler über ein nicht unterstütztes Modell erhalten, liegt das Problem auf Anbieterseite.",
107123
"googleCloudSetup": {
108124
"title": "Um Google Cloud Vertex AI zu verwenden, müssen Sie:",
109125
"step1": "1. Ein Google Cloud-Konto erstellen, die Vertex AI API aktivieren & die gewünschten Claude-Modelle aktivieren.",

webview-ui/src/i18n/locales/en/settings.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,20 @@
7474
"description": "Description",
7575
"apiProvider": "API Provider",
7676
"model": "Model",
77+
"nameEmpty": "Name cannot be empty",
78+
"nameExists": "A profile with this name already exists",
79+
"deleteProfile": "Delete Profile",
80+
"invalidArnFormat": "Invalid ARN format. Please check the examples above.",
81+
"enterNewName": "Enter new name",
82+
"addProfile": "Add Profile",
83+
"renameProfile": "Rename Profile",
84+
"newProfile": "New Configuration Profile",
85+
"enterProfileName": "Enter profile name",
86+
"createProfile": "Create Profile",
87+
"cannotDeleteOnlyProfile": "Cannot delete the only profile",
88+
"vscodeLmDescription": " The VS Code Language Model API allows you to run models provided by other VS Code extensions (including but not limited to GitHub Copilot). The easiest way to get started is to install the Copilot and Copilot Chat extensions from the VS Code Marketplace.",
89+
"awsCustomArnUse": "Enter a valid AWS Bedrock ARN for the model you want to use. Format examples:",
90+
"awsCustomArnDesc": "Make sure the region in the ARN matches your selected AWS Region above.",
7791
"openRouterApiKey": "OpenRouter API Key",
7892
"getOpenRouterApiKey": "Get OpenRouter API Key",
7993
"apiKeyStorageNotice": "API keys are stored securely in VSCode's Secret Storage",
@@ -104,6 +118,8 @@
104118
"awsSessionToken": "AWS Session Token",
105119
"awsRegion": "AWS Region",
106120
"awsCrossRegion": "Use cross-region inference",
121+
"vscodeLmModel": "Language Model",
122+
"vscodeLmWarning": "Note: This is a very experimental integration and provider support will vary. If you get an error about a model not being supported, that's an issue on the provider's end.",
107123
"googleCloudSetup": {
108124
"title": "To use Google Cloud Vertex AI, you need to:",
109125
"step1": "1. Create a Google Cloud account, enable the Vertex AI API & enable the desired Claude models.",

webview-ui/src/i18n/locales/es/settings.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,20 @@
7474
"description": "Descripción",
7575
"apiProvider": "Proveedor de API",
7676
"model": "Modelo",
77+
"nameEmpty": "El nombre no puede estar vacío",
78+
"nameExists": "Ya existe un perfil con este nombre",
79+
"deleteProfile": "Eliminar perfil",
80+
"invalidArnFormat": "Formato de ARN no válido. Verifica los ejemplos anteriores.",
81+
"enterNewName": "Ingrese un nuevo nombre",
82+
"addProfile": "Agregar perfil",
83+
"renameProfile": "Renombrar perfil",
84+
"newProfile": "Nuevo perfil de configuración",
85+
"enterProfileName": "Ingrese el nombre del perfil",
86+
"createProfile": "Crear perfil",
87+
"cannotDeleteOnlyProfile": "No se puede eliminar el único perfil",
88+
"vscodeLmDescription": "La API del Modelo de Lenguaje de VS Code le permite ejecutar modelos proporcionados por otras extensiones de VS Code (incluido, entre otros, GitHub Copilot). La forma más sencilla de empezar es instalar las extensiones Copilot y Copilot Chat desde el VS Code Marketplace.",
89+
"awsCustomArnUse": "Ingrese un ARN de AWS Bedrock válido para el modelo que desea utilizar. Ejemplos de formato:",
90+
"awsCustomArnDesc": "Asegúrese de que la región en el ARN coincida con la región de AWS seleccionada anteriormente.",
7791
"openRouterApiKey": "Clave API de OpenRouter",
7892
"getOpenRouterApiKey": "Obtener clave API de OpenRouter",
7993
"apiKeyStorageNotice": "Las claves API se almacenan de forma segura en el Almacenamiento Secreto de VSCode",
@@ -104,6 +118,8 @@
104118
"awsSessionToken": "Token de sesión de AWS",
105119
"awsRegion": "Región de AWS",
106120
"awsCrossRegion": "Usar inferencia entre regiones",
121+
"vscodeLmModel": "Modelo de lenguaje",
122+
"vscodeLmWarning": "Nota: Esta es una integración muy experimental y el soporte del proveedor variará. Si recibe un error sobre un modelo no compatible, es un problema del proveedor.",
107123
"googleCloudSetup": {
108124
"title": "Para usar Google Cloud Vertex AI, necesita:",
109125
"step1": "1. Crear una cuenta de Google Cloud, habilitar la API de Vertex AI y habilitar los modelos Claude deseados.",

webview-ui/src/i18n/locales/fr/settings.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,20 @@
7474
"description": "Description",
7575
"apiProvider": "Fournisseur d'API",
7676
"model": "Modèle",
77+
"nameEmpty": "Le nom ne peut pas être vide",
78+
"nameExists": "Un profil avec ce nom existe déjà",
79+
"deleteProfile": "Supprimer le profil",
80+
"invalidArnFormat": "Format ARN invalide. Veuillez vérifier les exemples ci-dessus.",
81+
"enterNewName": "Entrez un nouveau nom",
82+
"addProfile": "Ajouter un profil",
83+
"renameProfile": "Renommer le profil",
84+
"newProfile": "Nouveau profil de configuration",
85+
"enterProfileName": "Entrez le nom du profil",
86+
"createProfile": "Créer un profil",
87+
"cannotDeleteOnlyProfile": "Impossible de supprimer le seul profil",
88+
"vscodeLmDescription": "L'API du modèle de langage VS Code vous permet d'exécuter des modèles fournis par d'autres extensions VS Code (y compris, mais sans s'y limiter, GitHub Copilot). Le moyen le plus simple de commencer est d'installer les extensions Copilot et Copilot Chat depuis le VS Code Marketplace.",
89+
"awsCustomArnUse": "Entrez un ARN AWS Bedrock valide pour le modèle que vous souhaitez utiliser. Exemples de format :",
90+
"awsCustomArnDesc": "Assurez-vous que la région dans l'ARN correspond à la région AWS sélectionnée ci-dessus.",
7791
"openRouterApiKey": "Clé API OpenRouter",
7892
"getOpenRouterApiKey": "Obtenir la clé API OpenRouter",
7993
"apiKeyStorageNotice": "Les clés API sont stockées en toute sécurité dans le stockage sécurisé de VSCode",
@@ -104,6 +118,8 @@
104118
"awsSessionToken": "Jeton de session AWS",
105119
"awsRegion": "Région AWS",
106120
"awsCrossRegion": "Utiliser l'inférence inter-régions",
121+
"vscodeLmModel": "Modèle de langage",
122+
"vscodeLmWarning": "Remarque : Il s'agit d'une intégration très expérimentale et le support des fournisseurs variera. Si vous recevez une erreur concernant un modèle non pris en charge, c'est un problème du côté du fournisseur.",
107123
"googleCloudSetup": {
108124
"title": "Pour utiliser Google Cloud Vertex AI, vous devez :",
109125
"step1": "1. Créer un compte Google Cloud, activer l'API Vertex AI et activer les modèles Claude souhaités.",

webview-ui/src/i18n/locales/hi/settings.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,20 @@
7474
"description": "विवरण",
7575
"apiProvider": "API प्रदाता",
7676
"model": "मॉडल",
77+
"nameEmpty": "नाम खाली नहीं हो सकता",
78+
"nameExists": "इस नाम वाला प्रोफ़ाइल पहले से मौजूद है",
79+
"deleteProfile": "प्रोफ़ाइल हटाएं",
80+
"invalidArnFormat": "अमान्य ARN प्रारूप। कृपया ऊपर दिए गए उदाहरण देखें।",
81+
"enterNewName": "नया नाम दर्ज करें",
82+
"addProfile": "प्रोफ़ाइल जोड़ें",
83+
"renameProfile": "प्रोफ़ाइल का नाम बदलें",
84+
"newProfile": "नया कॉन्फ़िगरेशन प्रोफ़ाइल",
85+
"enterProfileName": "प्रोफ़ाइल नाम दर्ज करें",
86+
"createProfile": "प्रोफ़ाइल बनाएं",
87+
"cannotDeleteOnlyProfile": "केवल एकमात्र प्रोफ़ाइल को हटाया नहीं जा सकता",
88+
"vscodeLmDescription": "VS कोड भाषा मॉडल API आपको अन्य VS कोड एक्सटेंशन (जैसे GitHub Copilot) द्वारा प्रदान किए गए मॉडल चलाने की अनुमति देता है। शुरू करने का सबसे आसान तरीका VS कोड मार्केटप्लेस से Copilot और Copilot चैट एक्सटेंशन इंस्टॉल करना है।",
89+
"awsCustomArnUse": "आप जिस मॉडल का उपयोग करना चाहते हैं, उसके लिए एक वैध AWS बेडरॉक ARN दर्ज करें। प्रारूप उदाहरण:",
90+
"awsCustomArnDesc": "सुनिश्चित करें कि ARN में क्षेत्र ऊपर चयनित AWS क्षेत्र से मेल खाता है।",
7791
"openRouterApiKey": "OpenRouter API कुंजी",
7892
"getOpenRouterApiKey": "OpenRouter API कुंजी प्राप्त करें",
7993
"apiKeyStorageNotice": "API कुंजियाँ VSCode के सुरक्षित स्टोरेज में सुरक्षित रूप से संग्रहीत हैं",
@@ -104,6 +118,8 @@
104118
"awsSessionToken": "AWS सत्र टोकन",
105119
"awsRegion": "AWS क्षेत्र",
106120
"awsCrossRegion": "क्रॉस-क्षेत्र अनुमान का उपयोग करें",
121+
"vscodeLmModel": "भाषा मॉडल",
122+
"vscodeLmWarning": "नोट: यह एक बहुत ही प्रायोगिक एकीकरण है और प्रदाता समर्थन भिन्न होगा। यदि आपको किसी मॉडल के समर्थित न होने की त्रुटि मिलती है, तो यह प्रदाता की ओर से एक समस्या है।",
107123
"googleCloudSetup": {
108124
"title": "Google Cloud Vertex AI का उपयोग करने के लिए, आपको आवश्यकता है:",
109125
"step1": "1. Google Cloud खाता बनाएं, Vertex AI API सक्षम करें और वांछित Claude मॉडल सक्षम करें।",

0 commit comments

Comments
 (0)