From 18b1b2943ba941b1f37401b079e0e06da194def6 Mon Sep 17 00:00:00 2001 From: Fabian Andres Parra Sanchez Date: Mon, 20 Jul 2026 07:33:50 -0500 Subject: [PATCH 1/3] fix(i18n): use Settings.roles namespace in settings-overview MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The identity card at the top of the Settings overview was calling useTranslations('roles') (root-level) instead of useTranslations ('Settings.roles'). The root 'roles' namespace only exists in the es-CO translation as a workaround added to mask this bug — in English the chip rendered the raw keypath (e.g. 'roles.admin'). Aligns with invite-member-dialog.tsx:78 and members-tab.tsx:129, which already use the 'Settings.roles' namespace. Part of #375 --- src/components/settings/settings-overview.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/settings/settings-overview.tsx b/src/components/settings/settings-overview.tsx index ce992f8..24183ca 100644 --- a/src/components/settings/settings-overview.tsx +++ b/src/components/settings/settings-overview.tsx @@ -40,7 +40,7 @@ export function SettingsOverview({ useAuth(); const { mode, theme } = useTheme(); const t = useTranslations('Settings.overview'); - const tRoles = useTranslations('roles'); + const tRoles = useTranslations('Settings.roles'); const tSections = useTranslations('Settings.sections'); const [counts, setCounts] = useState(null); From 4f02b4cf58759e7baddf99dde0e835a3fab9c873 Mon Sep 17 00:00:00 2001 From: Fabian Andres Parra Sanchez Date: Mon, 20 Jul 2026 07:33:54 -0500 Subject: [PATCH 2/3] fix(i18n): strip className from scopesHint rich tag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit next-intl rich tags must be attribute-less. The className on the wrapping 'GET /api/v1/me' was being silently dropped, so the 'text-[11px]' Tailwind utility was a phantom — the code rendered at the surrounding text size anyway. This strips the className from both en.json and ko.json so the rich tag is parsed correctly. The element still renders at default size; the smaller styling can be restored globally via CSS ('code { font-size: ... }') if desired. Part of #375 --- messages/en.json | 2 +- messages/ko.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/messages/en.json b/messages/en.json index a3dd25f..846be95 100644 --- a/messages/en.json +++ b/messages/en.json @@ -1600,7 +1600,7 @@ "nameLabel": "Name", "namePlaceholder": "e.g. Zapier automation", "scopesLabel": "Scopes", - "scopesHint": "A key with no scopes can still call GET /api/v1/me to verify it works.", + "scopesHint": "A key with no scopes can still call GET /api/v1/me to verify it works.", "cancel": "Cancel", "creating": "Creating…", "createKey": "Create key", diff --git a/messages/ko.json b/messages/ko.json index 7c54fc9..6d0b1d5 100644 --- a/messages/ko.json +++ b/messages/ko.json @@ -1598,7 +1598,7 @@ "nameLabel": "이름", "namePlaceholder": "예: Zapier 자동화", "scopesLabel": "권한 범위", - "scopesHint": "권한 범위가 없는 키도 GET /api/v1/me를 호출해 동작을 확인할 수 있습니다.", + "scopesHint": "권한 범위가 없는 키도 GET /api/v1/me를 호출해 동작을 확인할 수 있습니다.", "cancel": "취소", "creating": "만드는 중…", "createKey": "키 생성", From 999a080a29839b79481a9fefb9688a70f4854449 Mon Sep 17 00:00:00 2001 From: Fabian Andres Parra Sanchez Date: Mon, 20 Jul 2026 07:33:59 -0500 Subject: [PATCH 3/3] fix(i18n): render translated label inside role SelectValue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Base UI's with no children does not reliably extract text from the selected when the item's children is a function call (e.g. tRoles(r.value)) — the trigger falls back to displaying the raw enum string ('admin', 'agent', 'viewer'). Render the translated label explicitly as children of so the trigger always shows the human-readable role name. Scope: only the two role selectors in Settings (matches this PR's theme). The same pattern affects ~5 other sites (template-manager header format, button type; ai-config provider and handoff target; flows/broadcasts) — those are left as follow-up and tracked in #375. Part of #375 --- src/components/settings/invite-member-dialog.tsx | 2 +- src/components/settings/members-tab.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/settings/invite-member-dialog.tsx b/src/components/settings/invite-member-dialog.tsx index b211491..ca29b70 100644 --- a/src/components/settings/invite-member-dialog.tsx +++ b/src/components/settings/invite-member-dialog.tsx @@ -274,7 +274,7 @@ export function InviteMemberDialog({ onValueChange={(v) => v && setRole(v as InviteRole)} > - + {tRoles(role)} {tRoles('admin')} diff --git a/src/components/settings/members-tab.tsx b/src/components/settings/members-tab.tsx index 6aa296f..8661ae1 100644 --- a/src/components/settings/members-tab.tsx +++ b/src/components/settings/members-tab.tsx @@ -428,7 +428,7 @@ export function MembersTab() { className="w-32 bg-muted border-border text-foreground" disabled={isBusy} > - + {tRoles(member.role)} {EDITABLE_ROLES.map((r) => (