fix(codex-auth): close remaining review gaps

This commit is contained in:
Tam Nhu Tran committed 2026-05-17 16:51:22 -04:00
1 parent 08fe63c626
commit 5c79df4311
20 files changed
+823 -93

No files matched your search

@@ -10,8 +10,9 @@
*/
import { Loader2 } from 'lucide-react';
import type { ReactNode } from 'react';
import type { TFunction } from 'i18next';
import { useTranslation } from 'react-i18next';
import { Trans, useTranslation } from 'react-i18next';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import {
@@ -28,6 +29,14 @@ import type { CodexAuthProfileEntry } from '@/hooks/use-codex-auth-profiles';
// ── Helpers ─────────────────────────────────────────────────────────────────
function InlineCode({ children }: { children?: ReactNode }) {
return (
<code className="rounded bg-muted px-1 py-0.5 font-mono text-[0.85em] text-foreground">
{children}
</code>
);
}
function formatLastUsed(iso: string | null): string {
if (!iso) return 'never';
try {
@@ -60,8 +69,6 @@ function sourceLabel(source: 'default' | 'env' | 'explicit-codex-home', t: TFunc
// ── Disabled action button with terminal-redirect tooltip ───────────────────
function TerminalOnlyButton({ label }: { label: string }) {
const { t } = useTranslation();
return (
<TooltipProvider>
<Tooltip>
@@ -73,7 +80,12 @@ function TerminalOnlyButton({ label }: { label: string }) {
</Button>
</span>
</TooltipTrigger>
<TooltipContent>{t('codex.auth.terminalOnlyTooltip')}</TooltipContent>
<TooltipContent>
<Trans
i18nKey="codex.auth.terminalOnlyTooltipRich"
components={{ code: <InlineCode /> }}
/>
</TooltipContent>
</Tooltip>
</TooltipProvider>
);
@@ -155,8 +167,12 @@ export function CodexAuthProfilesCard() {
if (data.profiles.length === 0) {
return (
<div className="rounded-md border bg-muted/30 px-4 py-3 text-sm text-muted-foreground space-y-1">
<p>{t('codex.auth.emptyRegistry')}</p>
<p>{t('codex.auth.legacyCodexHome')}</p>
<p>
<Trans i18nKey="codex.auth.emptyRegistryRich" components={{ code: <InlineCode /> }} />
</p>
<p>
<Trans i18nKey="codex.auth.legacyCodexHomeRich" components={{ code: <InlineCode /> }} />
</p>
</div>
);
}
@@ -166,7 +182,7 @@ export function CodexAuthProfilesCard() {
return (
<div className="space-y-3">
<div className="rounded-md border bg-muted/30 px-4 py-3 text-sm text-muted-foreground">
{t('codex.auth.legacyMode')}
<Trans i18nKey="codex.auth.legacyModeRich" components={{ code: <InlineCode /> }} />
</div>
<ProfileTable data={data} />
</div>
@@ -178,7 +194,11 @@ export function CodexAuthProfilesCard() {
return (
<div className="space-y-3">
<div className="rounded-md border bg-muted/30 px-4 py-3 text-sm text-muted-foreground">
{t('codex.auth.externalCodexHome', { path: data.active.codexHome })}
<Trans
i18nKey="codex.auth.externalCodexHomeRich"
values={{ path: data.active.codexHome }}
components={{ code: <InlineCode /> }}
/>
</div>
<ProfileTable data={data} />
</div>
+50
View File
@@ -2178,17 +2178,26 @@ const resources = {
auth: {
terminalOnlyTooltip:
'Use ccsx auth switch <name> or ccsx auth remove <name> in terminal.',
terminalOnlyTooltipRich:
'Use <code>ccsx auth switch &lt;name&gt;</code> or <code>ccsx auth remove &lt;name&gt;</code> in terminal.',
activeSourceBadge: '{{source}}',
statusOk: 'OK',
statusInvalid: '[!] auth invalid',
loading: 'Loading auth profiles...',
loadError: '[!] Failed to load codex-auth profiles.',
emptyRegistry: '[i] No codex-auth profiles. Run ccsx auth create <name> to create one.',
emptyRegistryRich:
'[i] No codex-auth profiles. Run <code>ccsx auth create &lt;name&gt;</code> to create one.',
legacyCodexHome: 'Codex will use the default ~/.codex location.',
legacyCodexHomeRich: 'Codex will use the default <code>~/.codex</code> location.',
legacyMode:
'[i] No active profile. Using ~/.codex (legacy). Run ccsx auth switch <name> in terminal to activate one.',
legacyModeRich:
'[i] No active profile. Using <code>~/.codex</code> (legacy). Run <code>ccsx auth switch &lt;name&gt;</code> in terminal to activate one.',
externalCodexHome:
'[i] $CODEX_HOME set externally to {{path}}. Profile registry not in use for this session.',
externalCodexHomeRich:
'[i] <code>$CODEX_HOME</code> set externally to <code>{{path}}</code>. Profile registry not in use for this session.',
activeProfile: 'Active profile:',
unknownProfile: '(unknown)',
planLabel: 'Plan:',
@@ -2659,6 +2668,7 @@ const resources = {
controlCenter: 'Control Center',
overview: 'Overview',
docs: 'Docs',
authProfiles: 'Auth Profiles',
nativeRuntime: 'Native Runtime',
ccsProvider: 'CCS Provider',
setup: 'Setup',
@@ -4772,16 +4782,25 @@ const resources = {
warningsTitle: '警告',
auth: {
terminalOnlyTooltip: '在终端使用 ccsx auth switch <name> 或 ccsx auth remove <name>。',
terminalOnlyTooltipRich:
'在终端使用 <code>ccsx auth switch &lt;name&gt;</code> 或 <code>ccsx auth remove &lt;name&gt;</code>。',
activeSourceBadge: '{{source}}',
statusOk: '正常',
statusInvalid: '[!] 认证无效',
loading: '正在加载认证配置...',
loadError: '[!] 加载 codex-auth 配置失败。',
emptyRegistry: '[i] 没有 codex-auth 配置。运行 ccsx auth create <name> 创建一个。',
emptyRegistryRich:
'[i] 没有 codex-auth 配置。运行 <code>ccsx auth create &lt;name&gt;</code> 创建一个。',
legacyCodexHome: 'Codex 将使用默认 ~/.codex 位置。',
legacyCodexHomeRich: 'Codex 将使用默认 <code>~/.codex</code> 位置。',
legacyMode:
'[i] 没有活动配置。正在使用 ~/.codex(旧模式)。在终端运行 ccsx auth switch <name> 激活一个。',
legacyModeRich:
'[i] 没有活动配置。正在使用 <code>~/.codex</code>(旧模式)。在终端运行 <code>ccsx auth switch &lt;name&gt;</code> 激活一个。',
externalCodexHome: '[i] $CODEX_HOME 外部设置为 {{path}}。本会话未使用配置注册表。',
externalCodexHomeRich:
'[i] <code>$CODEX_HOME</code> 外部设置为 <code>{{path}}</code>。本会话未使用配置注册表。',
activeProfile: '活动配置:',
unknownProfile: '(未知)',
planLabel: '套餐:',
@@ -5228,6 +5247,7 @@ const resources = {
controlCenter: '控制中心',
overview: '概览',
docs: '文档',
authProfiles: '认证配置',
nativeRuntime: '原生运行时',
ccsProvider: 'CCS 提供商',
setup: '安装',
@@ -7452,17 +7472,26 @@ const resources = {
auth: {
terminalOnlyTooltip:
'Dùng ccsx auth switch <name> hoặc ccsx auth remove <name> trong terminal.',
terminalOnlyTooltipRich:
'Dùng <code>ccsx auth switch &lt;name&gt;</code> hoặc <code>ccsx auth remove &lt;name&gt;</code> trong terminal.',
activeSourceBadge: '{{source}}',
statusOk: 'OK',
statusInvalid: '[!] auth không hợp lệ',
loading: 'Đang tải hồ sơ auth...',
loadError: '[!] Không tải được hồ sơ codex-auth.',
emptyRegistry: '[i] Chưa có hồ sơ codex-auth. Chạy ccsx auth create <name> để tạo.',
emptyRegistryRich:
'[i] Chưa có hồ sơ codex-auth. Chạy <code>ccsx auth create &lt;name&gt;</code> để tạo.',
legacyCodexHome: 'Codex sẽ dùng vị trí mặc định ~/.codex.',
legacyCodexHomeRich: 'Codex sẽ dùng vị trí mặc định <code>~/.codex</code>.',
legacyMode:
'[i] Chưa có hồ sơ active. Đang dùng ~/.codex (legacy). Chạy ccsx auth switch <name> trong terminal để kích hoạt.',
legacyModeRich:
'[i] Chưa có hồ sơ active. Đang dùng <code>~/.codex</code> (legacy). Chạy <code>ccsx auth switch &lt;name&gt;</code> trong terminal để kích hoạt.',
externalCodexHome:
'[i] $CODEX_HOME được đặt bên ngoài là {{path}}. Registry hồ sơ không dùng trong phiên này.',
externalCodexHomeRich:
'[i] <code>$CODEX_HOME</code> được đặt bên ngoài là <code>{{path}}</code>. Registry hồ sơ không dùng trong phiên này.',
activeProfile: 'Hồ sơ active:',
unknownProfile: '(không rõ)',
planLabel: 'Gói:',
@@ -7921,6 +7950,7 @@ const resources = {
controlCenter: 'Trung tâm điều khiển',
overview: 'Tổng quan',
docs: 'Tài liệu',
authProfiles: 'Hồ sơ auth',
nativeRuntime: 'Runtime gốc',
ccsProvider: 'CCS Provider',
setup: 'Thiết lập',
@@ -9859,6 +9889,8 @@ const resources = {
auth: {
terminalOnlyTooltip:
'ターミナルで ccsx auth switch <name> または ccsx auth remove <name> を使用します。',
terminalOnlyTooltipRich:
'ターミナルで <code>ccsx auth switch &lt;name&gt;</code> または <code>ccsx auth remove &lt;name&gt;</code> を使用します。',
activeSourceBadge: '{{source}}',
statusOk: 'OK',
statusInvalid: '[!] 認証が無効',
@@ -9866,11 +9898,18 @@ const resources = {
loadError: '[!] codex-auth プロファイルの読み込みに失敗しました。',
emptyRegistry:
'[i] codex-auth プロファイルがありません。ccsx auth create <name> を実行して作成します。',
emptyRegistryRich:
'[i] codex-auth プロファイルがありません。<code>ccsx auth create &lt;name&gt;</code> を実行して作成します。',
legacyCodexHome: 'Codex はデフォルトの ~/.codex を使用します。',
legacyCodexHomeRich: 'Codex はデフォルトの <code>~/.codex</code> を使用します。',
legacyMode:
'[i] アクティブなプロファイルがありません。~/.codex(レガシー)を使用中です。ターミナルで ccsx auth switch <name> を実行して有効化します。',
legacyModeRich:
'[i] アクティブなプロファイルがありません。<code>~/.codex</code>(レガシー)を使用中です。ターミナルで <code>ccsx auth switch &lt;name&gt;</code> を実行して有効化します。',
externalCodexHome:
'[i] $CODEX_HOME は外部で {{path}} に設定されています。このセッションではプロファイル registry は使われません。',
externalCodexHomeRich:
'[i] <code>$CODEX_HOME</code> は外部で <code>{{path}}</code> に設定されています。このセッションではプロファイル registry は使われません。',
activeProfile: 'アクティブプロファイル:',
unknownProfile: '(不明)',
planLabel: 'プラン:',
@@ -9894,6 +9933,7 @@ const resources = {
controlCenter: 'コントロールセンター',
overview: '概要',
docs: 'ドキュメント',
authProfiles: '認証プロファイル',
nativeRuntime: 'ネイティブランタイム',
ccsProvider: 'CCS プロバイダー',
setup: 'セットアップ',
@@ -12861,6 +12901,8 @@ const resources = {
auth: {
terminalOnlyTooltip:
'터미널에서 ccsx auth switch <name> 또는 ccsx auth remove <name>을 사용하세요.',
terminalOnlyTooltipRich:
'터미널에서 <code>ccsx auth switch &lt;name&gt;</code> 또는 <code>ccsx auth remove &lt;name&gt;</code>을 사용하세요.',
activeSourceBadge: '{{source}}',
statusOk: 'OK',
statusInvalid: '[!] 인증이 유효하지 않음',
@@ -12868,11 +12910,18 @@ const resources = {
loadError: '[!] codex-auth 프로필을 로드하지 못했습니다.',
emptyRegistry:
'[i] codex-auth 프로필이 없습니다. ccsx auth create <name>을 실행해 생성하세요.',
emptyRegistryRich:
'[i] codex-auth 프로필이 없습니다. <code>ccsx auth create &lt;name&gt;</code>을 실행해 생성하세요.',
legacyCodexHome: 'Codex는 기본 ~/.codex 위치를 사용합니다.',
legacyCodexHomeRich: 'Codex는 기본 <code>~/.codex</code> 위치를 사용합니다.',
legacyMode:
'[i] 활성 프로필이 없습니다. ~/.codex(레거시)를 사용 중입니다. 터미널에서 ccsx auth switch <name>을 실행해 활성화하세요.',
legacyModeRich:
'[i] 활성 프로필이 없습니다. <code>~/.codex</code>(레거시)를 사용 중입니다. 터미널에서 <code>ccsx auth switch &lt;name&gt;</code>을 실행해 활성화하세요.',
externalCodexHome:
'[i] $CODEX_HOME이 외부에서 {{path}}로 설정되었습니다. 이 세션에서는 프로필 registry를 사용하지 않습니다.',
externalCodexHomeRich:
'[i] <code>$CODEX_HOME</code>이 외부에서 <code>{{path}}</code>로 설정되었습니다. 이 세션에서는 프로필 registry를 사용하지 않습니다.',
activeProfile: '활성 프로필:',
unknownProfile: '(알 수 없음)',
planLabel: '플랜:',
@@ -13345,6 +13394,7 @@ const resources = {
controlCenter: '제어 센터',
overview: '개요',
docs: '문서',
authProfiles: '인증 프로필',
nativeRuntime: '네이티브 런타임',
ccsProvider: 'CCS 프로바이더',
setup: '설정',
+1 -4
View File
@@ -183,10 +183,7 @@ export function CodexPage() {
<TabsTrigger value="overview">{t('codexPage.overview')}</TabsTrigger>
<TabsTrigger value="controls">{t('codexPage.controlCenter')}</TabsTrigger>
<TabsTrigger value="docs">{t('codexPage.docs')}</TabsTrigger>
<TabsTrigger value="auth-profiles">
{/* TODO i18n: missing key codexPage.authProfiles */}
Auth Profiles
</TabsTrigger>
<TabsTrigger value="auth-profiles">{t('codexPage.authProfiles')}</TabsTrigger>
</TabsList>
</div>
+26 -3
View File
@@ -4,15 +4,31 @@ import i18n from '@/lib/i18n';
const locales = ['en', 'zh-CN', 'vi', 'ja', 'ko'] as const;
const codexAuthKeys = [
['codex.auth.terminalOnlyTooltip'],
['codex.auth.sourceDefault'],
['codex.auth.sourceEnv'],
['codex.auth.sourceExplicitCodexHome'],
['codex.auth.terminalOnlyTooltipRich'],
['codex.auth.activeSourceBadge', { source: 'default' }],
['codex.auth.statusOk'],
['codex.auth.statusInvalid'],
['codex.auth.loading'],
['codex.auth.loadError'],
['codex.auth.emptyRegistry'],
['codex.auth.externalCodexHome', { path: '/tmp/codex-home' }],
['codex.auth.emptyRegistryRich'],
['codex.auth.legacyCodexHomeRich'],
['codex.auth.legacyModeRich'],
['codex.auth.externalCodexHomeRich', { path: '/tmp/codex-home' }],
['codex.auth.activeProfile'],
['codex.auth.unknownProfile'],
['codex.auth.planLabel'],
['codex.auth.switchAction'],
['codex.auth.removeAction'],
['codex.auth.col.name'],
['codex.auth.col.email'],
['codex.auth.col.plan'],
['codex.auth.col.lastUsed'],
['codex.auth.col.status'],
['codex.auth.col.actions'],
['codexPage.authProfiles'],
] as const;
const originalLanguage = i18n.language;
@@ -30,6 +46,13 @@ describe('codex auth i18n', () => {
expect(translated).not.toBe(key);
expect(translated).not.toContain('codex.auth.');
expect(translated).not.toContain('codexPage.');
if (key === 'codex.auth.externalCodexHomeRich') {
expect(translated).toContain('/tmp/codex-home');
}
if (key === 'codex.auth.activeSourceBadge') {
expect(translated).toContain('default');
}
}
});
});