mirror of
https://github.com/jhd3197/ServerKit.git
synced 2026-10-30 16:47:01 +09:00
Plan 79 §E wave 1. The shell is first because it is on every screen: a translated page inside an English frame reads as broken, while a translated frame around an English page reads as in-progress. Converted: Sidebar (31 literals -> 1, the brand name, which must not be translated), sidebarItems, CommandPalette, PageTopbar, MobileTopBar, NotificationBell, EmptyState, ErrorState, ErrorBoundary, ConfirmDialog, AppLoader. Ceiling 8225 -> 8132, and es.json now covers all 98 keys, so the shell is provably bilingual rather than merely keyed. Three shapes needed real tooling rather than a t() call, and each was found by converting a file rather than by planning: - Labels in data files (sidebarItems, palette docs entries) cannot call t(): a table resolved at module load translates once, at import, and never follows a locale switch. They now declare `labelKey` beside `label`; the extractor collects the pair at its declaration site and useLabel resolves it at render. The ratchet understands the pairing, so converting a data file visibly moves the number (sidebarItems 27 -> 0). - Sentences with an element inside them (ConfirmDialog's "Type <x> to confirm") go through <Trans>, which the extractor now reads. Splitting them into prefix/suffix keys would have been untranslatable: word order around the value differs by language and a split sentence cannot be reordered. - Class components and module scope (ErrorBoundary, AppLoader) import a bare `t` from the i18n module. Reaching for `i18next.t` at the call site would have left that copy out of en.json, since the extractor matches bare calls. The declarative-pair heuristic initially swept up `archKey: 'amd64'` next to `arch: 'x64 (amd64)'` -- "Key" already means "identifier" in places -- so a pair now only counts when the value looks like a dotted translation key. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>