* feat(i18n): add Traditional Chinese (zh-Hant) UI locale Adds 繁體中文 as a selectable UI language and derives its catalog from zh.json rather than translating English afresh, so the reviewed Simplified terminology and Orca glossary decisions carry over. The conversion needed three corrections beyond OpenCC's `cn -> twp`: - One pass only. `twp`'s phrase dictionary is not idempotent (it maps 進程->程序 and 程序->程式), and iterating to a fixed point makes output worse: it rewrites the correct Taiwan 游標 to 遊標, and 程序 to 程式 where the source meant an OS process. - 16 terms where `twp` emits a form Taiwan does not use, each confirmed against Microsoft's VS Code zh-Hant language pack (許可權 0 vs 權限 84, 賬戶 0 vs 帳戶 111, and so on). - 進程 vs 程序 collapse in `twp` output. Taiwan calls an OS process 行程, so the generator consults the Simplified source to disambiguate; daemon copy reads 守護行程, not 守護程式. Also pins `load: 'currentOnly'` on both i18next instances. i18next's default expands `zh-Hant` into ['zh-Hant', 'zh', 'en'], so a key missing from the Traditional catalog would silently render Simplified. zh-Hant.json is generated and compared byte-for-byte, so the new check is wired into verify:localization-catalogs to fail when a Simplified edit skips regeneration. Refs #10592 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * fix(i18n): fail the zh-Hant check on an unreadable zh.json The generator caught every error from reading and parsing zh.json, so a malformed or unreadable Simplified catalog logged "absent here" and exited 0 without ever comparing the generated Traditional catalog. Only ENOENT means there is nothing to derive, so every other failure now propagates. Tests cover the three paths the catch was conflating: an absent zh.json still passes for the combined verifier's synthetic fixtures, malformed JSON throws, and a directory where the catalog belongs throws EISDIR rather than reporting the file as missing. Co-Authored-By: Claude Code <noreply@anthropic.com> * feat(i18n): ship Traditional Chinese (Taiwan) as a maintained built-in catalog Keeps the zh-Hant locale from this PR and makes it a hand-maintained catalog like the other built-ins, without the OpenCC generator: - Catalog reconciled with current en.json. Per key it prefers the Taiwan-reviewed copy from #22402 (which carries #14223), falls back to the zh-derived copy here, and drops entries whose English changed. A review pass then applied Taiwan terms (代理程式, 工作階段, 存放庫, 分頁, 列/欄) and 「」 quotes. Glossary: config/i18n-traditional-chinese.md. - Label 繁體中文(台灣)in every catalog, the picker, onboarding and search. - Detection maps zh-TW/zh-HK/zh-MO/zh-Hant* to zh-Hant; zh-CN/zh-SG/zh-Hans stay on zh. Both i18next instances use load: 'currentOnly' so missing keys fall back to English, not Simplified. - Drops opencc-js, the generator scripts and their verify hook. Co-authored-by: hungchihsueh <84211143+hungchihsueh@users.noreply.github.com> Co-authored-by: chilung-cgu <b0423031@gmail.com> * feat(i18n): translate remaining Traditional Chinese (Taiwan) catalog keys Fill the 2,043 keys added to en since the source PRs branched, following the Taiwan glossary, and extend the glossary with skill, automation, usage, review, token and related terms. * fix(i18n): review Traditional Chinese (Taiwan) catalog wording Apply 629 reviewed corrections across the full catalog: 30 meaning or untranslated-text fixes and 599 glossary and phrasing fixes (終端機, 用量, API 金鑰, clearer counts and actions). Each edit was cross-checked by an independent review pass. * fix(i18n): polish sampled zh-Hant strings and drop redundant locale test Co-authored-by: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com> Co-authored-by: hungchihsueh <84211143+hungchihsueh@users.noreply.github.com> Co-authored-by: chilung-cgu <b0423031@gmail.com>
@orca/docs
This package contains the product documentation and public media intended to ship alongside Orca's source code.
Open-source product documentation for Orca, served at /docs (same URL shape as https://www.onorca.dev/docs).
This package is a self-contained Next.js app. It is intentionally not a root monorepo workspace member, so installing Electron app dependencies does not pull Next/fumadocs.
Local development
Use Node.js 24 and the pnpm version pinned in package.json. CI reads the
Node.js version from this package's engines.node field.
cd docs/site
pnpm install
pnpm dev
Open http://localhost:3004/docs.
Linting
Run pnpm lint inside this directory. The isolated Oxlint
configuration keeps the native equivalents of the previous Next.js, React,
React hooks and accessibility checks at their existing severities, including
alt text on Next.js Image components. Generated Next.js and MDX output is
excluded. Oxlint also reports its default correctness warnings.
The migration does not provide equivalents for React's deprecated-API check,
React Compiler configuration/gating diagnostics, or Next.js's relative
location.assign advisory. JSX variable-use bookkeeping is handled by Oxlint's
parser. Keep TypeScript and the production Next.js build in the validation
workflow; this is not a claim of complete ESLint rule parity.
Production build
cd docs/site
pnpm install
pnpm build
pnpm start
pnpm start serves the production build on port 3004. Paths:
| Path | Purpose |
|---|---|
/ |
Redirects to /docs |
/docs |
Docs index |
/docs/... |
Nested doc pages from content/docs |
/docs/api/search |
Fumadocs search index |
/docs/og/... |
Per-page Open Graph image route |
Layout
content/docs/— MDX pages +meta.jsonnavigationpublic/docs/— docs-only media, logo, and favicon (GIFs, posters, screenshots)src/app/docs/— fumadocs routes, OG imagessrc/components/— docs-scoped chrome (header/footer/search), not marketing site
Updating content
Treat the documentation tree as a deliberate publication boundary. Before importing source material, review the diff for internal references, credentials, third-party media rights, and feature/version claims, then copy only approved pages and assets. Keep the app shell and deployment configuration in this repository so a docs-only pull request can be reviewed and built independently.
Same-domain routing
The docs app is a separate Vercel project (the docs zone) and keeps the
public /docs URL namespace. The marketing site remains the default zone for
www.onorca.dev; configure its Next/Vercel proxy with these beforeFiles
rewrites, replacing DOCS_ORIGIN with the docs project's production URL:
return {
beforeFiles: [
{
source: '/docs',
destination: `${DOCS_ORIGIN}/docs`
},
{
source: '/docs/:path*',
destination: `${DOCS_ORIGIN}/docs/:path*`
},
{
source: '/docs-static/:path*',
destination: `${DOCS_ORIGIN}/docs-static/:path*`
}
]
}
/docs-static is the docs zone's assetPrefix; it prevents _next asset
collisions with the marketing zone. Keep the rewrites in the default zone and
use ordinary <a> links when navigating between zones. Do not add
basePath: '/docs' to this app: its route tree and Fumadocs baseUrl already
include /docs, so doing so would publish /docs/docs/... URLs. If a future
deployment needs basePath, first move the route tree to an unprefixed
src/app/[[...slug]] shape and update every generated/link URL together.
Deploy (Vercel)
- Create a Vercel project with Root Directory unset (
.). The workflow invokes Vercel fromdocs/site, so that directory is already the deployment root; setting it again would resolvedocs/site/docs/site. Leave automatic Git deployments disabled so this workflow remains the only deployment path. - Framework preset: Next.js. This package's
engines.nodeselects Node.js 24 for Vercel builds and functions.vercel.jsonpins install (pnpm install --frozen-lockfile) and build (pnpm build) over the dashboard settings; this package has its own lockfile beside the root workspace. - Set GitHub Actions secrets (required by the production deploy job):
VERCEL_TOKENVERCEL_ORG_IDVERCEL_PROJECT_ID(docs project, not the marketing site)
- Protect the
docs-productionGitHub environment with required reviewers and custom deployment branch policies formainandv*tags. The release-cut dispatch runs frommain; the direct published-release fallback runs from a stable tag, while the workflow still authorizes only exact stable tags. - Prepare the three rewrites above in the
www.onorca.devmarketing project, but leave them disabled until the docs deployment is verified. A Vercel custom domain cannot delegate only/docsby itself; the default zone must proxy both page/API/media requests and/docs-staticassets. Keep the marketing project's old docs routes available for rollback during the transition; putting the proxy rules inbeforeFilesensures they win once enabled. - Deploy a stable desktop tag that contains
docs/site, verify the docs origin, then enable the marketing rewrites. Tags cut before this package was added cannot bootstrap the docs project because production intentionally checks out the tag's exact commit. Remove the old marketing docs routes in a follow-up after the proxy is stable.
.github/workflows/docs.yml runs credential-free checks for every pull request.
It intentionally does not deploy PR previews: a PR-controlled build must not
receive Vercel credentials. A maintainer can add a separate trusted preview
workflow later. Production deploys only from an authorized stable desktop release: an exact
vX.Y.Z tag, a published non-prerelease release, and the
github-actions[bot] release author. Manual dispatch must run from the default
branch and name an existing release that meets the same checks. Mobile,
prerelease, draft, and human-authored releases are skipped. Fork pull requests
remain build-only because GitHub does not expose deployment secrets to fork
jobs.
Versioning
versioning.config.ts keeps the current unversioned /docs URLs stable while
reserving content/versions/<id> for future snapshots. Versioned routes are not
live yet; when they are needed, add the corresponding loader/routes and a
version entry. The release workflow can then deploy them without a trigger
change.
Isolation from the desktop app
- Own
package.json+pnpm-lock.yamlunderdocs/site/ - Not listed in the root
pnpm-workspace.yaml; its ownpnpm-workspace.yamlmakes it a separate workspace root and holds its pnpm settings, which pnpm 12 ignores under--ignore-workspace - Engineering notes remain in repo-root
docs/— do not confuse with this package