← Back to home@kaluosifa

dsh-plugin-skill2cn

Translate the English description of a skill into Chinese and restore the original in one click; a newly installed skill is surfaced right away.

Stars
0
Language
TypeScript
Created
Sep 17, 2026
Updated
Sep 20, 2026

Introduction

Skill2CN · Skill Localization (dsh-plugin-skill2cn)

English | 简体中文

Translate the English description of DSH skills into Simplified Chinese, with one-click restore.

  • Single entry point: a dedicated "技能汉化 / Skill Localization" section page in the DSH settings UI (3 tabs: Untranslated / Translated / Model Settings), plus a bottom-right prompt card when new skills appear
  • Translation granularity: only the description value in SKILL.md frontmatter; name and the skill body are left byte-for-byte intact
  • Write-to-disk: the translation is written straight back to the SKILL.md on disk (rationale in docs/adr/0001-write-to-disk-translation.md); DSH hot-reloads it, so no restart is needed
  • Single source of truth: the manifest.json backup ledger. The panel reconciles "disk ↔ ledger" to derive each skill's state: untranslated / translated / no-translation-needed / stale

Skill2CN usage poster

Features

FeatureWhat it does
Untranslated tabGroups skills by source (workspace / global / plugin package), with a Translate button per skill and a Translate All batch action
Translated tabPer-skill Restore, View original toggle, and a Restore All batch action
Batch jobsAsync with a concurrency cap of 3, live progress, and a success/failure summary; failed items stay on the panel with a Retry button
New-skill promptA shell.overlay card in the bottom-right corner asking whether to translate newly discovered skills (deprecated ones are never re-asked)
Model Settings tabThree translation routes — follow the current session route, pick a configured provider/model, or use a custom endpoint (OpenAI- or Anthropic-compatible protocol) — plus a Test button
Upgrade reconcileOn panel open, entries overwritten by a package upgrade are either silently cleared or marked stale, and can be re-translated
CJK heuristicDescriptions that are already Chinese are marked "no translation needed" and skipped by batch runs

Demo video

https://github.com/user-attachments/assets/a98d7649-052b-4912-8ff5-1a472abf2dda

The intro video and the usage poster above (source HTML) were made by our teammate 阿根 (Agen). The video file is also kept in the repo at docs/assets/introduction-video.mp4.

Install

dsh plugin --profile <profile> add <path-to-this-repo-or-tarball>

A link: install (local path) does not run prepare, so no allowBuilds entry is needed. Restart DSH once after installing (this loads the host half for the first time). After that:

  • change the host (src/service.ts, src/core/**) → pnpm build, then restart DSH
  • change the client (src/client/**) → pnpm build, then reload the browser

Uninstall

Click Restore All on the Translated tab first. Write-to-disk changes are not undone automatically by uninstalling (ADR-0001, Consequences).

dsh plugin --profile <profile> remove dsh-plugin-skill2cn

The ledger at $DSH_HOME/skill2cn/manifest.json is left behind (harmless, safe to delete by hand).

Development

pnpm install
pnpm dev          # tsdown watch (tsc transpiles standard decorators into lib-tsc first, then bundles)
pnpm test         # core unit tests (vitest)
pnpm typecheck    # both tsconfigs: host + client
pnpm build        # emits lib/index.js (host ESM) + lib/client.js (closure-factory CJS)

Requirements: Node ≥ 22.13 and pnpm 11. (pnpm 11 requires Node ≥ 22.13 and is also the version that produced pnpm-lock.yaml.)

Build pipeline

The @Remote decorator needs TypeScript's standard-decorator transpilation, which esbuild/tsdown does not perform, so the build runs in two steps: tsc -p tsconfig.build.json emits lib-tsc/, then tsdown bundles from the lib-tsc/index.js entry into lib/index.js. lib-tsc/ is an intermediate artifact (already covered by .gitignore and regenerated by pnpm build).

Translation routing

The Model Settings tab offers three routes:

  1. Follow the current DSH session route (default) — reuses the provider/model of the most recent session request. If no route has been captured yet, Test asks you to send a session message first.

  2. Use a configured provider/model — the dropdown is populated from ctx.remote.llm.listConfigurableProviders(); Discover models calls discoverModels on the provider's settingsNs. Some providers register no discovery capability, in which case you can type the model name manually.

  3. Custom endpoint — pick a protocol (OpenAI-compatible / Anthropic-compatible) under Advanced, then fill in Base URL / API key / model name. Both are non-streaming:

    • OpenAI-compatible → POST {baseURL}/chat/completions (Authorization: Bearer)
    • Anthropic-compatible → POST {baseURL}/messages (sends both x-api-key and Authorization: Bearer so official and proxy endpoints both work; anthropic-version: 2023-06-01, max_tokens required)

    The Base URL must include the version segment (e.g. https://api.deepseek.com/v1 or https://api.anthropic.com/v1) — the resource path is appended by the plugin. Note this differs from how you configure an anthropic provider inside DSH, where the base excludes /v1 (the SDK owns the path); copying that style here gives you a 404.

Test runs one real, small translation through the current route and reports a verdict first: a green "configuration succeeded" or a red "configuration failed", with details on the second line (translation + latency + the actual model name; on failure, the host's original reason). The sample sentence is fixed in the host (Use when translating skill descriptions into Simplified Chinese.) — deliberately this plugin's own self-description, so a passing test also demonstrates that the route can translate the very thing you need translated, and the skill identifier in it doubles as a check of the built-in "do not translate identifiers" rule.

How it works

Translation is write-to-disk (ADR-0001): the plugin reads the target SKILL.md, records the English original in the backup ledger, calls the LLM, then rewrites only the description: line of the frontmatter. DSH's chokidar watcher fires skills/change, so the next model step already sees the Chinese description. The ledger — not any guess about a file's language — is the only thing that decides translated vs. untranslated.

Known limitations

  • The workspace group follows the session workspace (session.header.cwd; falling back to the most recent session with a header, and only then to the process cwd). So "workspace" means the project you have open in DSH, not the directory DSH was started from — starting DSH from inside a checkout does not make that checkout's own project skills a translation target.
  • Enumeration uses the ctx.skills registry winner set: skills that lost a same-name override, and in-memory provider skills with no file on disk, do not appear on the panel.
  • The "no translation needed" heuristic treats a description as Chinese when it has ≥ 4 CJK ideographs and at least half as many CJK characters as Latin letters. Chinese descriptions routinely carry identifiers and product names (dingtalk-*, Shadcn/ui, utility-first, spec/tickets), which a strict "more CJK than Latin" rule would misjudge as needing translation. See the acceptance record for the real-data verification.
  • The "configured route" dropdown lists DSH's provider catalog, which is not the same as the providers with a registered adapter on your machine: picking an unregistered one makes Test report no adapter registered for provider "..." (surfaced verbatim rather than swallowed).
  • Skills from the plugin package source are overwritten when the npm package is upgraded or reinstalled; their badge carries a ⚠️ and the automatic reconcile on panel open handles the fallout (silently clearing the record or marking it stale).

Testing

pnpm test        # 12 spec files, 94 test cases

Acceptance

The itemized, measured results for all nine SPEC §7 acceptance criteria are in docs/ACCEPTANCE.md (including the DSH API mismatches found during implementation and the defects they exposed).

Documentation

Contributing

See CONTRIBUTING.md. This repository is a published snapshot: development happens in a private working tree, and this directory is re-synced on each release, so a PR may be re-applied onto that tree rather than merged directly.

License

MIT