Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ The repository is a Cargo + pnpm workspace:
- `crates/bsk-cli` — `bsk` CLI and local daemon
- `crates/bsk-protocol` — shared wire types and JSON schemas
- `apps/extension` — browser extension
- `packages/ui` and [`packages/i18n`](packages/i18n/README.md) — shared extension UI support, including English, Simplified Chinese and Korean localization
- `packages/ui` and [`packages/i18n`](packages/i18n/README.md) — shared extension UI support, including English, Simplified Chinese, Traditional Chinese, Korean, Japanese, French, Italian, Spanish, German and Brazilian Portuguese localization
- `packages/dsh-plugin-browserskill` — DeepSeek Harness plugin (`@wxg-prc-cpg/browser-skill-dsh-plugin`)
- [`evals/browser`](evals/browser/README.md) — deterministic local pages and agent-neutral browser capability evaluation

Expand Down
2 changes: 1 addition & 1 deletion README.zh-CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ Agent 不直接与浏览器通信。它通过 `bsk` CLI 下发浏览器任务;
- `crates/bsk-cli` — `bsk` CLI 与本地 daemon
- `crates/bsk-protocol` — 共享协议类型与 JSON Schema
- `apps/extension` — 浏览器扩展
- `packages/ui` 和 [`packages/i18n`](packages/i18n/README.md) — 扩展 UI 共享支持,包含英文、简体中文和韩语本地化
- `packages/ui` 和 [`packages/i18n`](packages/i18n/README.md) — 扩展 UI 共享支持,包含英文、简体中文、繁体中文、韩语、日语、法语、意大利语、西班牙语、德语和巴西葡萄牙语本地化
- `packages/dsh-plugin-browserskill` — DeepSeek Harness 插件(`@wxg-prc-cpg/browser-skill-dsh-plugin`)
- [`evals/browser`](evals/browser/README.zh-CN.md) — 确定性本地页面与 Agent 无关的浏览器能力测试台

Expand Down
15 changes: 11 additions & 4 deletions packages/i18n/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
# Extension localization

The extension ships English (`en-US`), Simplified Chinese (`zh-CN`) and Korean
(`ko-KR`) in the `common` and `extension` namespaces. These resources cover the
popup, page overlays and extension notifications; they do not translate CLI
output or extension store metadata.
The extension ships English (`en-US`), Simplified Chinese (`zh-CN`),
Traditional Chinese (`zh-TW`), Korean (`ko-KR`), Japanese (`ja-JP`), French
(`fr-FR`), Italian (`it-IT`), Spanish (`es-ES`), German (`de-DE`) and
Brazilian Portuguese (`pt-BR`) in the `common` and `extension` namespaces.
These resources cover the popup, page overlays and extension notifications;
they do not translate CLI output or extension store metadata.

Locale resources are registered automatically: dropping a
`src/locales/<locale>/{common,extension}.json` pair in place is enough for
`i18n.ts` to pick it up (see `i18n.ts`'s `import.meta.glob` scan) — no code
change is required to ship a new language.

## Language selection

Expand Down
52 changes: 31 additions & 21 deletions packages/i18n/src/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { Resource, ResourceLanguage } from "i18next";
import i18n from "i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import { initReactI18next } from "react-i18next";
Expand All @@ -7,27 +8,36 @@ import {
chromeUiLanguageDetector,
getLanguageDetectionOptions,
} from "./chrome-storage-sync";
import enUSCommon from "./locales/en-US/common.json";
import enUSExtension from "./locales/en-US/extension.json";
import koKRCommon from "./locales/ko-KR/common.json";
import koKRExtension from "./locales/ko-KR/extension.json";
import zhCNCommon from "./locales/zh-CN/common.json";
import zhCNExtension from "./locales/zh-CN/extension.json";

const resources = {
"zh-CN": {
common: zhCNCommon,
extension: zhCNExtension,
},
"en-US": {
common: enUSCommon,
extension: enUSExtension,
},
"ko-KR": {
common: koKRCommon,
extension: koKRExtension,
},
} as const;

/**
* Every `locales/<locale>/<namespace>.json` is registered automatically, so
* shipping a new language means adding its resource files — no code change.
*/
const localeModules = import.meta.glob<ResourceLanguage>("./locales/*/*.json", {
eager: true,
import: "default",
});

function buildResources(): Resource {
const resources: Resource = {};
for (const [path, messages] of Object.entries(localeModules)) {
const match = /^\.\/locales\/([^/]+)\/([^/]+)\.json$/.exec(path);
if (!match) {
continue;
}
const [, locale, namespace] = match;
const namespaces = resources[locale] ?? {};
namespaces[namespace] = messages;
resources[locale] = namespaces;
}
return resources;
}

// Sort the keys: multi-candidate locale resolution reads the order of
// `Object.keys(resources)`, so it must not depend on filesystem enumeration.
const resources = Object.fromEntries(
Object.entries(buildResources()).sort(([left], [right]) => left.localeCompare(right)),
);

const languageDetector = new LanguageDetector();
languageDetector.addDetector(chromeUiLanguageDetector);
Expand Down
6 changes: 6 additions & 0 deletions packages/i18n/src/locales/de-DE/common.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"app": {
"name": "browser-skill",
"description": "Steuere deinen angemeldeten Browser von KI-Agents aus über die bsk-CLI"
}
}
Loading