Conversation
- Add src/locales/zh-Hans/translation.json covering the full en key set (terminology aligned with the LibreChat main zh-Hans translation) - Register zh-Hans in i18n init with LibreChat-style locale normalization and detection (stored choice > navigator, alias mapping zh/zh-CN/zh-SG), replacing the browser-languagedetector whose nonExplicitSupportedLngs handling rejected zh-Hans - Render the SSR loading shell in the default locale deterministically and suppress the expected hydration text mismatch - Guard en/zh key-set and placeholder parity plus language switching in locales.test.ts
- Add a language row with a Select dropdown (English / 中文(简体)) below the theme row, reusing the existing click-ui Select component - Persist the choice via i18nextLng (the detection cache key) and keep document.documentElement.lang in sync
- CreateUserDialog role select rendered raw SystemRoles values (USER/ADMIN); use localized labels instead - Audit log target-type filter rendered raw PrincipalType enum values; map them to localized labels
New /tools route lists the full Tool Gateway catalog (disabled included) via the LibreChat proxy /api/terravox/tools/all: tool id, version, exposure fronts, allowed groups, renderer and enable state, with search and zh-Hans/en localization.
- Add GiteaImportDialog: owner/repo dropdowns from the anonymous repo listing, check report (error blocks, warn allows continuing), prefill into the edit dialog; manual-create secondary path - ToolEditDialog: desktop execution now registers owner/repo distribution (tool.json fields as optional fallback), prefill support - Desktop manifest assembly uses the distribution form (catalog_tool_id contract change); owner+repo required, sha256 format validated - Tool create/update toasts; com_tools_gitea_* / dist field locales
Misclicks on the overlay discarded filled-in forms. All admin-panel dialogs now ignore pointer-downs outside the content; explicit close, cancel buttons and Escape still close.
Pending updates governance (contracts 2.8.0): repo releases ahead of the approved manifest are hidden from users until an admin confirms them. - getPendingUpdatesFn + pendingUpdatesQueryOptions (60s poll, aligned with the gateway's resolver cache TTL) - ToolCatalogTab: amber pending section above the table; Review & confirm runs the existing Gitea check endpoint, prefills the edit dialog via buildPrefill with repo content fields while governance fields (tool_id/expose/allowed_groups/enabled) stay as approved — submitting the dialog is the existing PUT confirm - export buildPrefill from GiteaImportDialog (shared by import + update) - com_tools_pending_* locale keys (en/zh-Hans) - vitest: panel render/empty, confirm merge, check failure, query failure, catalog loading
…ds repo omits Confirming a pending update prefilled the dialog from tool.json@tag, so a stale tool.json version clobbered the release-tag version and the pending row looped forever. buildUpdateMerge now: - sets version (top-level + distribution) from the pending target (tag); the tag is the distribution identity resolver/Toolhost install by - keeps approved values for anything the repo does not provide (parameters/form/result/dangerous/description/display_name/sha256/ launcher/runtime) instead of overwriting with undefined/fallbacks - keeps governance fields (tool_id/expose/allowed_groups/enabled) Check results are now surfaced in the pending panel: hard errors block the dialog with a notice; warns (e.g. version_mismatch) show as a notice. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
…o error) Gateway check_repo returns version_mismatch as a hard error when tool.json@tag carries a version that differs from the tag, so the confirm flow blocks with the reason instead of opening a dialog for a version the Toolhost would refuse to install. Missing version stays a warn (manifest fallback at install). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
- server fns: paged GET + full export (200/page, 10k cap) against the gateway admin run-reports endpoint, zod-parsed like the rest - /usage route, sidebar entry, en/zh-Hans locales (parity-tested) - AuditLogTab pattern reuse: DatePickerCell extracted to shared - CSV built client-side with UTF-8 BOM + RFC 4180 escaping
toolsQueryOptions is a static queryOptions object in the server module, but UsagePage invoked it as a factory (toolsQueryOptions()), throwing "is not a function" in the production bundle. The spec's @/server mock shaped it as a function, which is why tests stayed green — the mock now mirrors the real export shape.
- ToolEditDialog: exec kind extends to plugin/web; web gets a URL field, plugin gets host_launcher + host-root candidates + install/ uninstall script fields; desktop distribution block shared - GiteaImportDialog: import-kind selector — desktop/plugin run the existing check flow (plugin prefill carries host fields from tool.json), web skips the check and takes a required URL with the repo as optional name/description prefill - locales +13 keys en/zh-Hans (parity-checked); 859 tests green
…oup visibility); tool editor gains display_group/help_url/usage_stats; dashboard quick links
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
with terminology aligned to the LibreChat main zh-Hans translation (shared
com_*strings reuse the official wording so the panel and chat UI read consistently)
Selectdropdown (English /中文(简体)) below the theme row, persisting the choice via the
i18nextLngcache key and keeping
document.documentElement.langin syncshowed
USER/ADMIN; audit-log target-type filter showed raw principal types)Locale detection
Detection is adapted from the LibreChat client implementation
(
client/src/locales/i18n.ts): explicit stored choice wins, then navigator language,normalized through an alias table (
zh,zh-CN,zh-SG→zh-Hans). This replacesi18next-browser-languagedetector, whosenonExplicitSupportedLngshandling stripszh-Hanstozhbefore the whitelist check — meaning a registeredzh-Hanslocalecould never actually be resolved.
SSR renders the pre-hydration loading shell in the default locale deterministically,
and the shell text suppresses the expected hydration mismatch (
<html lang>alreadyhad
suppressHydrationWarning).Tests
src/locales/locales.test.tsguards en/zh key-set parity, interpolationplaceholder parity, language switching (incl.
zh-CN/zhresolution), andlocale normalization
bun run test, 831 tests)Notes for reviewers
Three commits, intentionally split for reviewability:
🌐 feat: Add Simplified Chinese (zh-Hans) locale🌐 feat: Add language setting to settings dialog🐛 fix: Localize role and target type dropdown optionsHappy to adjust the translation wording or split/merge commits as preferred.