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.
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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<string, string> =>
|
||||
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}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user