fix(i18n): localize the Codex auth button (Closes #4852) (#4992)

This commit is contained in:
Mega Mind
2026-07-18 06:42:21 +03:00
committed by GitHub
parent aa037b3468
commit 2db2dcb439
16 changed files with 54 additions and 3 deletions
@@ -3319,7 +3319,7 @@ const AIPanel = ({ embedded = false }: AIPanelProps = {}) => {
disabled={busyAction === 'codex-auth' || busyAction === 'toggle-openai'}>
{busyAction === 'codex-auth' || busyAction === 'toggle-openai'
? t('settings.ai.connecting')
: t('settings.ai.codexAuthButton', 'Codex 인증')}
: t('settings.ai.codexAuthButton', 'Connect Codex')}
</Button>
<span className="text-xs text-content-muted">
{t(
@@ -893,6 +893,26 @@ describe('AIPanel', () => {
expect(screen.queryByRole('switch', { name: /Disconnect OpenAI/i })).not.toBeInTheDocument();
});
// Regression for #4852: the Codex auth button had a hardcoded Korean fallback
// (`Codex 인증`) because the `settings.ai.codexAuthButton` key was missing from
// every locale, so the English UI rendered Korean text. Assert the English
// label renders and no Korean survives.
it('renders the Codex auth button with the active-locale (English) label', async () => {
vi.mocked(loadAISettings).mockResolvedValue({ ...baseSettings, cloudProviders: [] });
renderWithProviders(<AIPanel />);
await waitFor(() =>
expect(screen.getByRole('switch', { name: /Connect OpenAI/i })).toBeInTheDocument()
);
const codexButton = screen.getByRole('button', { name: /Connect Codex/i });
expect(codexButton).toBeInTheDocument();
// The Korean fallback must be gone from the English onboarding screen.
expect(screen.queryByText(/인증/)).not.toBeInTheDocument();
expect(screen.queryByRole('button', { name: /Codex 인증/i })).not.toBeInTheDocument();
});
it('connects OpenAI through Codex CLI auth without storing an API key', async () => {
vi.mocked(loadAISettings).mockResolvedValue({ ...baseSettings, cloudProviders: [] });
@@ -902,7 +922,7 @@ describe('AIPanel', () => {
expect(screen.getByRole('switch', { name: /Connect OpenAI/i })).toBeInTheDocument()
);
fireEvent.click(screen.getByRole('button', { name: /Codex 인증/i }));
fireEvent.click(screen.getByRole('button', { name: /Connect Codex/i }));
await waitFor(() => expect(vi.mocked(importOpenAiCodexCliAuth)).toHaveBeenCalledTimes(1));
expect(vi.mocked(startOpenAiCodexOAuth)).not.toHaveBeenCalled();
@@ -947,7 +967,7 @@ describe('AIPanel', () => {
expect(screen.getByRole('switch', { name: /Connect OpenAI/i })).toBeInTheDocument()
);
fireEvent.click(screen.getByRole('button', { name: /Codex 인증/i }));
fireEvent.click(screen.getByRole('button', { name: /Connect Codex/i }));
await waitFor(() => expect(screen.getByRole('alert')).toHaveTextContent(expectedMessage));
expect(vi.mocked(setCloudProviderKey)).not.toHaveBeenCalled();
+2
View File
@@ -4523,6 +4523,8 @@ const messages: TranslationMap = {
'settings.ai.openRouterOauthDescription':
'وقع مع OpenRouter وإستيراد مفتاح ×xxxxx متحكم به مستخدماً',
'settings.ai.connecting': 'جارٍ الاتصال...',
'settings.ai.codexAuthButton': 'ربط Codex',
'settings.ai.codexAuthHelper': 'يستخدم تسجيل دخول Codex CLI الحالي من ~/.codex/auth.json.',
'settings.ai.backgroundLoops': 'حلقات الخلفية',
'settings.ai.backgroundLoopsDesc':
'شاهدْ ما يَعْملُ بدون رسالةِ دردشةِ، يَتوقّفُ عملَ نبضات القلب، ويَتفحصُ مؤخراً دفترِ دفاترِ الإئتمانِ.',
+2
View File
@@ -4638,6 +4638,8 @@ const messages: TranslationMap = {
'settings.ai.openRouterOauthDescription':
'xqxqxx সহযোগে সাইন করুন এবং xqxyqx ব্যবহার করে একটি ব্যবহারকারী xxqx কী ইম্পোর্ট করুন',
'settings.ai.connecting': 'সংযোগ করা হচ্ছে...',
'settings.ai.codexAuthButton': 'Codex সংযুক্ত করুন',
'settings.ai.codexAuthHelper': '~/.codex/auth.json থেকে বিদ্যমান Codex CLI লগইন ব্যবহার করে।',
'settings.ai.backgroundLoops': 'ব্যাকগ্রাউন্ড লুপস',
'settings.ai.backgroundLoopsDesc':
'লক্ষ্য করুন যে, কোন আড্ডা ছাড়াই কি করা হয়, হার্টবিটের কাজ বিরতি দিন এবং সম্প্রতি ক্রেডিট কার্ড পরীক্ষা করুন ।',
+3
View File
@@ -4769,6 +4769,9 @@ const messages: TranslationMap = {
'settings.ai.openRouterOauthDescription':
'Melden Sie sich mit OpenRouter an und importieren Sie einen benutzergesteuerten API-Schlüssel mit PKCE.',
'settings.ai.connecting': 'Verbindung wird hergestellt...',
'settings.ai.codexAuthButton': 'Codex verbinden',
'settings.ai.codexAuthHelper':
'Verwendet die vorhandene Codex-CLI-Anmeldung aus ~/.codex/auth.json.',
'settings.ai.backgroundLoops': 'Hintergrundschleifen',
'settings.ai.backgroundLoopsDesc':
'Sehen Sie, was ohne Chat-Nachricht läuft, pausieren Sie die Herzschlagarbeit und überprüfen Sie die letzten Kreditbuchzeilen.',
+2
View File
@@ -5344,6 +5344,8 @@ const en: TranslationMap = {
'settings.ai.openRouterOauthDescription':
'Sign in with OpenRouter and import a user-controlled API key using PKCE.',
'settings.ai.connecting': 'Connecting...',
'settings.ai.codexAuthButton': 'Connect Codex',
'settings.ai.codexAuthHelper': 'Uses the existing Codex CLI login from ~/.codex/auth.json.',
'settings.ai.backgroundLoops': 'Background loops',
'settings.ai.backgroundLoopsDesc':
'See what runs without a chat message, pause heartbeat work, and inspect recent credit ledger rows.',
+3
View File
@@ -4717,6 +4717,9 @@ const messages: TranslationMap = {
'settings.ai.openRouterOauthDescription':
'Inicia sesión con OpenRouter e importa una clave API controlada por el usuario usando PKCE.',
'settings.ai.connecting': 'Conectando...',
'settings.ai.codexAuthButton': 'Conectar Codex',
'settings.ai.codexAuthHelper':
'Usa el inicio de sesión existente de Codex CLI desde ~/.codex/auth.json.',
'settings.ai.backgroundLoops': 'Bucles de fondo',
'settings.ai.backgroundLoopsDesc':
'Vea qué se ejecuta sin un mensaje de chat, pause el trabajo de latido y examine las filas recientes del libro mayor de créditos.',
+3
View File
@@ -4746,6 +4746,9 @@ const messages: TranslationMap = {
'settings.ai.openRouterOauthDescription':
"Connectez-vous avec OpenRouter et importez une clé API contrôlée par l'utilisateur en utilisant PKCE.",
'settings.ai.connecting': 'Connexion...',
'settings.ai.codexAuthButton': 'Connecter Codex',
'settings.ai.codexAuthHelper':
'Utilise la connexion Codex CLI existante depuis ~/.codex/auth.json.',
'settings.ai.backgroundLoops': 'Boucles de fond',
'settings.ai.backgroundLoopsDesc':
"Voyez ce qui s'exécute sans message de discussion, interrompez le travail du battement de cœur et inspectez les lignes récentes du grand livre de crédit.",
+2
View File
@@ -4637,6 +4637,8 @@ const messages: TranslationMap = {
'settings.ai.openRouterOauthDescription':
'OpenRouter के साथ साइन इन करें और PKCE का उपयोग करके उपयोगकर्ता नियंत्रित API कुंजी आयात करें।',
'settings.ai.connecting': 'कनेक्ट हो रहा है...',
'settings.ai.codexAuthButton': 'Codex कनेक्ट करें',
'settings.ai.codexAuthHelper': '~/.codex/auth.json से मौजूदा Codex CLI लॉगिन का उपयोग करता है।',
'settings.ai.backgroundLoops': 'पृष्ठभूमि लूप',
'settings.ai.backgroundLoopsDesc':
'क्या एक चैट संदेश के बिना चलाता है, दिल की धड़कन काम को रोकें, और हाल ही में क्रेडिट लेजर पंक्तियों का निरीक्षण करें।',
+2
View File
@@ -4653,6 +4653,8 @@ const messages: TranslationMap = {
'settings.ai.openRouterOauthDescription':
'Masuk dengan kunci OpenRouter dan impor sebuah user yang dikendalikan API menggunakan PKCE.',
'settings.ai.connecting': 'Menghubungkan...',
'settings.ai.codexAuthButton': 'Hubungkan Codex',
'settings.ai.codexAuthHelper': 'Menggunakan login Codex CLI yang ada dari ~/.codex/auth.json.',
'settings.ai.backgroundLoops': 'Perulangan latar belakang',
'settings.ai.backgroundLoopsDesc':
'Lihat apa yang berjalan tanpa pesan obrolan, jeda kerja detak jantung, dan memeriksa buku kas kredit baru-baru ini.',
+2
View File
@@ -4711,6 +4711,8 @@ const messages: TranslationMap = {
'settings.ai.openRouterOauthDescription':
"Accedi con OpenRouter e importa una chiave API controllata dall'utente usando PKCE.",
'settings.ai.connecting': 'Connessione in corso...',
'settings.ai.codexAuthButton': 'Connetti Codex',
'settings.ai.codexAuthHelper': 'Usa il login Codex CLI esistente da ~/.codex/auth.json.',
'settings.ai.backgroundLoops': 'Loop in background',
'settings.ai.backgroundLoopsDesc':
'Vedi cosa funziona senza un messaggio di chat, metti in pausa il lavoro del battito cardiaco e ispeziona le righe recenti del libro mastro dei crediti.',
+2
View File
@@ -4585,6 +4585,8 @@ const messages: TranslationMap = {
'settings.ai.openRouterOauthDescription':
'OpenRouter로 로그인하고 PKCE를 사용해 사용자가 제어하는 API 키를 가져옵니다.',
'settings.ai.connecting': '연결 중...',
'settings.ai.codexAuthButton': 'Codex 연결',
'settings.ai.codexAuthHelper': '~/.codex/auth.json의 기존 Codex CLI 로그인을 사용합니다.',
'settings.ai.backgroundLoops': '백그라운드 루프',
'settings.ai.backgroundLoopsDesc':
'채팅 메시지 없이 실행되는 항목을 확인하고, 하트비트 작업을 일시 중지하며, 최근 크레딧 원장 행을 검사합니다.',
+2
View File
@@ -4707,6 +4707,8 @@ const messages: TranslationMap = {
'settings.ai.openRouterOauthDescription':
'Zaloguj się przez OpenRouter i zaimportuj kontrolowany przez użytkownika klucz API z użyciem PKCE.',
'settings.ai.connecting': 'Łączenie...',
'settings.ai.codexAuthButton': 'Połącz Codex',
'settings.ai.codexAuthHelper': 'Używa istniejącego logowania Codex CLI z ~/.codex/auth.json.',
'settings.ai.backgroundLoops': 'Pętle w tle',
'settings.ai.backgroundLoopsDesc':
'Zobacz, co działa bez wiadomości na czacie, wstrzymaj pracę heartbeat i sprawdź ostatnie wiersze księgi kredytów.',
+2
View File
@@ -4704,6 +4704,8 @@ const messages: TranslationMap = {
'settings.ai.openRouterOauthDescription':
'Faça login com OpenRouter e importe uma chave API controlada pelo usuário usando PKCE.',
'settings.ai.connecting': 'Conectando...',
'settings.ai.codexAuthButton': 'Conectar Codex',
'settings.ai.codexAuthHelper': 'Usa o login existente da CLI do Codex de ~/.codex/auth.json.',
'settings.ai.backgroundLoops': 'Loops de segundo plano.',
'settings.ai.backgroundLoopsDesc':
'Veja o que funciona sem uma mensagem de chat, pause o trabalho do pulso e inspecione as linhas recentes do livro razão de créditos.',
+2
View File
@@ -4681,6 +4681,8 @@ const messages: TranslationMap = {
'settings.ai.openRouterOauthDescription':
'Войдите в систему с помощью OpenRouter и импортируйте управляемый пользователем ключ API с помощью PKCE.',
'settings.ai.connecting': 'Подключение...',
'settings.ai.codexAuthButton': 'Подключить Codex',
'settings.ai.codexAuthHelper': 'Использует существующий вход Codex CLI из ~/.codex/auth.json.',
'settings.ai.backgroundLoops': 'Фоновые циклы',
'settings.ai.backgroundLoopsDesc':
'Посмотрите, что выполняется без сообщения чата, приостановите работу Heartbeat и проверьте последние строки кредитной книги.',
+2
View File
@@ -4387,6 +4387,8 @@ const messages: TranslationMap = {
'settings.ai.openRouterOauthDescription':
'使用 OpenRouter 登录,并通过 PKCE 导入由用户控制的 API 密钥。',
'settings.ai.connecting': '正在连接...',
'settings.ai.codexAuthButton': '连接 Codex',
'settings.ai.codexAuthHelper': '使用来自 ~/.codex/auth.json 的现有 Codex CLI 登录。',
'settings.ai.backgroundLoops': '背景循环',
'settings.ai.backgroundLoopsDesc':
'查看没有聊天消息时运行的内容,暂停心跳任务,并检查最近的额度账本行。',