Conversation
A registrant adds translations next to its plain title:
`titleLocales: { 'zh-CN': '构建', ja: 'ビルド' }`. The plain title stays the
default, so a reader that ignores the map keeps working. resolveTitle()
and matchLocale() from @devframes/hub pick the closest tag; the reference
hub UI resolves every entry and command against its own language setting,
and the example hosts resolve against the browser language.
refs #398
◈ PR Lens
Architecture 6 components touched across 3 lanes. Play the interactive walkthrough Inside the changed components — 2 viewsComponent view — Locale resolution The title resolution and BCP 47 matching helpers exported by the client runtime Component view — UI title localization Reactive localization across dock entries, command hierarchies, and launchers in the hub UI Data flow
Follow each request, response and payload View
Tip The diagrams are links. Click one to open it on the canvas, then press W or click play to walk through the change 🪧 More tips
Thanks for using PR Lens! It's built by Coldtea, free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
👁️🗨️ Review this pull request with grouped, summarized diffs at: raw result💭 analyzed by {
"headSha": "2de14085667434d8da644fbc8c0254f1c551f20f",
"result": {
"overallSummary": "Adds an optional `titleLocales` translation map alongside the existing `title` on dock entries, commands and launchers (and `DevframeDockDefaults`), with shared `resolveTitle`/`matchLocale` helpers exported from `@devframes/hub`. The reference hub UI and both example hosts resolve titles through these helpers at their rendering choke points so the dock, palette and settings rows follow the active language, with docs and tsnapi snapshots updated to match.",
"groups": [
{
"key": "core-locale",
"label": "Shared title localization",
"summary": "Adds the sidecar `titleLocales` field to dock entries, commands, launchers and `DevframeDockDefaults`, plus the shared `resolveTitle`/`matchLocale` helpers (`@devframes/hub` and `/client`) that pick the closest translation without breaking existing plain-`title` readers.",
"category": "core",
"filePaths": [
"packages/hub/src/index.ts",
"packages/hub/src/locale.ts",
"packages/hub/src/locale.test.ts",
"packages/hub/src/client/index.ts",
"packages/hub/src/types/commands.ts",
"packages/hub/src/types/docks.ts",
"packages/hub/src/types/index.ts",
"packages/hub/src/types/locale.ts",
"packages/devframe/src/types/devframe.ts"
]
},
{
"key": "hub-ui",
"label": "hub-ui localized titles",
"summary": "Wires the reference hub UI to resolve `title` through the shared `matchLocale`/`resolveTitle` at its `entries`/`commands` choke points (recursing through command `children`), so the dock rail, tooltips, palette and shortcut rows follow the Language setting; hub-ui's own `matchLocale` now delegates to the shared one, and the playground seeds a localized group/command to exercise it.",
"category": "ui",
"filePaths": [
"packages/hub-ui/src/locales.ts",
"packages/hub-ui/src/client/i18n/index.ts",
"packages/hub-ui/src/client/i18n/i18n.test.ts",
"packages/hub-ui/src/client/state/locale.ts",
"packages/hub-ui/src/client/state/locale.test.ts",
"packages/hub-ui/src/client/state/commands.ts",
"packages/hub-ui/src/client/state/context.ts",
"packages/hub-ui/src/client/components/views/ViewLauncher.vue",
"packages/hub-ui/playground/seed.ts"
]
},
{
"key": "example-hosts",
"label": "Example hub hosts",
"summary": "Both reference hosts resolve dock/command titles against `navigator.language` via the new `resolveTitle`, keeping parity with the hub-ui reference implementation.",
"category": "examples",
"filePaths": [
"examples/custom-hub-next/src/client/app/page.tsx",
"examples/custom-hub-vite/src/client/main.ts"
]
},
{
"key": "docs",
"label": "Docs for titleLocales",
"summary": "Documents the new `titleLocales` field and `resolveTitle` helper in the hub guide, the build-your-own-hub-UI guide and the hub API reference.",
"category": "docs",
"filePaths": [
"docs/content/1.guide/16.hub.md",
"docs/content/1.guide/22.build-your-own-hub-ui.md",
"docs/content/8.references/6.hub-api.md"
]
},
{
"key": "tsnapi-snapshots",
"label": "tsnapi API snapshots",
"summary": "Updates the public API surface snapshots to reflect the two new functions (`matchLocale`, `resolveTitle`) and two new types (`DevframeTitled`, `DevframeTitleLocales`), inlined rather than via `extends` so the diff reads as purely additive.",
"category": "tests",
"filePaths": [
"tests/__snapshots__/tsnapi/@devframes/hub/client.snapshot.d.ts",
"tests/__snapshots__/tsnapi/@devframes/hub/client.snapshot.js",
"tests/__snapshots__/tsnapi/@devframes/hub/index.snapshot.d.ts",
"tests/__snapshots__/tsnapi/@devframes/hub/index.snapshot.js",
"tests/__snapshots__/tsnapi/@devframes/hub/types.snapshot.d.ts",
"tests/__snapshots__/tsnapi/devframe/index.snapshot.d.ts"
]
}
],
"schemaVersion": 1,
"source": "llm",
"generatedAt": "2026-10-01T01:02:57.767Z",
"model": "vercel-ai-gateway/anthropic/claude-sonnet-5",
"locale": "en"
}
} |
Stacked on #415. Refs #398.
What
titleLocales: Record<BCP47 tag, string>next to their plaintitle. The plaintitlestays the default, so every existing reader keeps working and a registrant adds languages without a breaking change.DevframeDockDefaultsgets the same field so a devframe can localize the dock a hub synthesizes for it.@devframes/hub(and/client) exportresolveTitle(titled, locale)andmatchLocale(tag, available): exact tag first, then the Traditional Chinese family (zh-HK→zh-TW), then the language prefix (pt-PT→pt-BR,en-GB→en), else the plaintitle.children) against its own language setting at its two choke points (entriesandcommandscomputeds), so the dock rail, tooltips, settings rows, palette and shortcut rows follow the Language select from feat(hub-ui): translate the hub UI and add a language setting #415 with no per-component change. hub-ui's ownmatchLocalenow delegates to the shared one.examples/custom-hub-vite,examples/custom-hub-next) resolve againstnavigator.language, keeping parity.Verified in the playground: with the UI set to Japanese the group reads プレイグラウンドツール in the dock rail and the command palette, and an untranslated command still shows its English title.
Design notes
Sidecar field instead of widening
titleto a union: widening would have broken everyentry.titlereader (threelocaleComparesorts,.toLowerCase()filters,iframe.titleassignments the e2e specs select on, the MCP tool title), including third-party hub UI providers. Titles only for now; descriptions and launcher button text can follow the same*Localespattern if wanted.The tsnapi snapshots gain the two functions and two types. The declarations are inlined rather than
extends DevframeTitledso tsnapi reads the change as additive.Created with the help of an agent.