From 6c3e51956a4a17e4ced28f2d84146ca1a782a885 Mon Sep 17 00:00:00 2001 From: Bohdan Triapitsyn Date: Sat, 5 Sep 2026 14:46:05 +0300 Subject: [PATCH] fix(vscode): complete the Turkish extension bundles The inline-comment feature added its manifest and runtime strings to English and French only, so Turkish users saw English command titles, thread labels and warnings. Adds the ten missing keys and a test that fails whenever a locale bundle drifts from the English key set or its placeholders. --- packages/vscode/l10n/bundle.l10n.tr.json | 7 +++ packages/vscode/package.nls.tr.json | 3 ++ packages/vscode/src/DOCUMENTATION.md | 14 ++++++ .../vscode/src/localizationBundles.test.ts | 45 +++++++++++++++++++ 4 files changed, 69 insertions(+) create mode 100644 packages/vscode/src/localizationBundles.test.ts diff --git a/packages/vscode/l10n/bundle.l10n.tr.json b/packages/vscode/l10n/bundle.l10n.tr.json index 99518c7f..ca5f9134 100644 --- a/packages/vscode/l10n/bundle.l10n.tr.json +++ b/packages/vscode/l10n/bundle.l10n.tr.json @@ -13,6 +13,13 @@ "OpenChamber [Improve Code]: No active editor": "OpenChamber [Kodu İyileştir]: Aktif düzenleyici yok", "OpenChamber [Improve Code]: No text selected": "OpenChamber [Kodu İyileştir]: Metin seçilmedi", "Improve the following Code:": "Aşağıdaki Kodu iyileştir:", + "OpenChamber [Add Comment]: No active editor": "OpenChamber [Yorum Ekle]: Aktif düzenleyici yok", + "OpenChamber [Add Comment]: File is outside the workspace": "OpenChamber [Yorum Ekle]: Dosya çalışma alanının dışında", + "OpenChamber [Add Comment]: The comment never reached the chat and was discarded": "OpenChamber [Yorum Ekle]: Yorum sohbete ulaşmadı ve atıldı", + "Comment on line {0}": "{0}. satıra yorum", + "Comment on lines {0}-{1}": "{0}-{1}. satırlara yorum", + "OpenChamber": "OpenChamber", + "Not sent yet": "Henüz gönderilmedi", "OpenCode CLI not found. Install it and ensure it's in PATH.": "OpenCode CLI bulunamadı. Yükleyin ve PATH içinde olduğundan emin olun.", "OpenCode CLI not found. Please install it and ensure it's in PATH.": "OpenCode CLI bulunamadı. Lütfen yükleyin ve PATH içinde olduğundan emin olun.", "More Info": "Daha fazla bilgi", diff --git a/packages/vscode/package.nls.tr.json b/packages/vscode/package.nls.tr.json index a59693a6..2a61279c 100644 --- a/packages/vscode/package.nls.tr.json +++ b/packages/vscode/package.nls.tr.json @@ -10,6 +10,9 @@ "command.openNewSessionInEditor.title": "Düzenleyicide yeni oturum aç", "command.openCurrentOrNewSessionInEditor.title": "Oturumu düzenleyicide aç", "command.addToContext.title": "Bağlama ekle", + "command.addLineComment.title": "Yorum ekle", + "command.submitLineComment.title": "Yorum yap", + "command.removeLineComment.title": "Yorumu kaldır", "command.explain.title": "Açıkla", "command.improveCode.title": "Kodu iyileştir", "command.newSession.title": "Yeni oturum", diff --git a/packages/vscode/src/DOCUMENTATION.md b/packages/vscode/src/DOCUMENTATION.md index 79d843ff..8cabb2b6 100644 --- a/packages/vscode/src/DOCUMENTATION.md +++ b/packages/vscode/src/DOCUMENTATION.md @@ -190,3 +190,17 @@ resolves `$XDG_CONFIG_HOME/opencode` at extension startup, falling back to No files are migrated. The behavior GET bridge response includes the effective `path` for both existing and missing AGENTS.md files; shared Settings uses it in the warning. + +## Extension localization + +Two bundles carry extension-host text: `package.nls*.json` for the manifest +`%token%` strings and `l10n/bundle.l10n*.json` for the `t(...)` call sites. +Every locale file must cover the full English key set with the same `{0}` +placeholders — VS Code silently falls back to English per missing key, so a +half-translated locale looks like a shipped feature. `localizationBundles.test.ts` +enforces that, and it is the check to run whenever a feature adds a new string. + +The pre-bundle loading splash in `webviewHtml.ts` is separate: its strings are +inlined in the generated HTML and chosen from OpenChamber's own saved locale +(`openchamber.i18n.v1` in webview localStorage), not from VS Code's display +language, because the splash renders before the webview bundle loads. diff --git a/packages/vscode/src/localizationBundles.test.ts b/packages/vscode/src/localizationBundles.test.ts new file mode 100644 index 00000000..45a31c07 --- /dev/null +++ b/packages/vscode/src/localizationBundles.test.ts @@ -0,0 +1,45 @@ +import assert from 'node:assert/strict'; +import * as fs from 'node:fs'; +import * as path from 'node:path'; +import { describe, test } from 'node:test'; + +const packageRoot = path.resolve(__dirname, '..'); + +const readJson = (relativePath: string): Record => + JSON.parse(fs.readFileSync(path.join(packageRoot, relativePath), 'utf8')); + +const placeholders = (value: string): string[] => (value.match(/\{\d+\}/g) ?? []).sort(); + +const localeFiles = (directory: string, prefix: string, suffix: string): string[] => + fs + .readdirSync(path.join(packageRoot, directory)) + .filter((name) => name.startsWith(prefix) && name.endsWith(suffix) && name !== `${prefix}${suffix}`) + .map((name) => path.join(directory, name)); + +describe('extension localization bundles', () => { + test('every runtime string bundle covers the English keys with matching placeholders', () => { + const english = readJson('l10n/bundle.l10n.json'); + for (const file of localeFiles('l10n', 'bundle.l10n', '.json')) { + const translated = readJson(file); + for (const [key, source] of Object.entries(english)) { + const value = translated[key]; + assert.equal(typeof value, 'string', `${file} is missing the key ${JSON.stringify(key)}`); + assert.deepEqual( + placeholders(value), + placeholders(source), + `${file} changes the placeholders of ${JSON.stringify(key)}` + ); + } + } + }); + + test('every manifest bundle covers the English keys', () => { + const english = readJson('package.nls.json'); + for (const file of localeFiles('.', 'package.nls', '.json')) { + const translated = readJson(file); + for (const key of Object.keys(english)) { + assert.equal(typeof translated[key], 'string', `${file} is missing the key ${key}`); + } + } + }); +});