From b08998d5b0663c092a482c46b7edb777c9118580 Mon Sep 17 00:00:00 2001 From: Steven Enamakel <31011319+senamakel@users.noreply.github.com> Date: Sun, 24 May 2026 13:36:25 -0700 Subject: [PATCH] i18nize remaining React UI strings (#2577) --- app/src/components/AppUpdatePrompt.tsx | 2 +- .../BootCheckGate/BootCheckGate.tsx | 3 +- .../components/LocalAIDownloadSnackbar.tsx | 6 +- app/src/components/OpenhumanLinkModal.tsx | 2 +- app/src/components/ProgressIndicator.tsx | 9 +- .../components/RotatingTetrahedronCanvas.tsx | 5 +- .../components/channels/TelegramConfig.tsx | 5 +- .../channels/mcp/ConfigAssistantPanel.tsx | 27 +- .../components/channels/mcp/InstallDialog.tsx | 34 +- .../channels/mcp/InstalledServerDetail.tsx | 30 +- .../channels/mcp/InstalledServerList.tsx | 18 +- .../channels/mcp/McpCatalogBrowser.tsx | 81 +- .../components/channels/mcp/McpServersTab.tsx | 4 +- .../components/channels/mcp/McpToolList.tsx | 4 +- .../channels/mcp/SmitheryServerCard.tsx | 8 +- app/src/components/commands/Kbd.tsx | 4 +- .../composio/ComposioConnectModal.tsx | 7 +- .../intelligence/IntelligenceCallsTab.tsx | 8 +- .../intelligence/IntelligenceMemoryTab.tsx | 2 +- .../IntelligenceSubconsciousTab.tsx | 63 +- .../components/intelligence/VaultPanel.tsx | 131 +-- .../intelligence/WhatsAppMemorySection.tsx | 2 +- app/src/components/ios/MobileTabBar.tsx | 5 +- .../rewards/ReferralRewardsSection.tsx | 2 +- .../settings/components/SettingsHeader.tsx | 2 +- .../components/settings/panels/AIPanel.tsx | 291 ++++--- .../settings/panels/AgentChatPanel.tsx | 2 +- .../panels/AutocompleteDebugPanel.tsx | 168 ++-- .../settings/panels/CompanionPanel.tsx | 49 +- .../settings/panels/ComposioPanel.tsx | 6 +- .../settings/panels/ComposioTriagePanel.tsx | 13 +- .../settings/panels/DeveloperOptionsPanel.tsx | 2 +- .../settings/panels/DevicesPanel.tsx | 72 +- .../settings/panels/MascotPanel.tsx | 35 +- .../settings/panels/MemoryDebugPanel.tsx | 89 +- .../settings/panels/MigrationPanel.tsx | 4 +- .../panels/NotificationRoutingPanel.tsx | 44 +- .../settings/panels/PrivacyPanel.tsx | 7 +- .../panels/ProviderSetupErrorNotice.tsx | 63 +- .../panels/ScreenAwarenessDebugPanel.tsx | 72 +- .../settings/panels/TeamInvitesPanel.tsx | 50 +- .../settings/panels/TeamManagementPanel.tsx | 57 +- .../settings/panels/TeamMembersPanel.tsx | 72 +- .../settings/panels/VoiceDebugPanel.tsx | 50 +- .../components/settings/panels/VoicePanel.tsx | 168 ++-- .../settings/panels/WebhooksDebugPanel.tsx | 61 +- .../panels/__tests__/AIPanel.test.tsx | 2 +- .../__tests__/MemoryDebugPanel.test.tsx | 2 +- .../panels/autocomplete/AppFilterSection.tsx | 45 +- .../autocomplete/CompletionStyleSection.tsx | 15 +- .../panels/billing/AutoRechargeSection.tsx | 23 +- .../panels/billing/InferenceBudget.tsx | 375 ++++---- .../panels/devices/PairPhoneModal.tsx | 56 +- .../local-model/DeviceCapabilitySection.tsx | 14 +- .../local-model/ModelDownloadSection.tsx | 70 +- .../local-model/ModelStatusSection.test.tsx | 2 +- .../panels/local-model/ModelStatusSection.tsx | 52 +- .../components/skills/CreateSkillModal.tsx | 12 +- .../components/skills/InstallSkillDialog.tsx | 82 +- app/src/components/skills/MeetingBotsCard.tsx | 40 +- .../skills/ScreenIntelligenceSetupModal.tsx | 2 +- app/src/components/skills/skillIcons.tsx | 24 +- app/src/components/upsell/UpsellBanner.tsx | 5 +- app/src/lib/i18n/chunks/ar-1.ts | 660 ++++++++++++++ app/src/lib/i18n/chunks/ar-5.ts | 168 ++++ app/src/lib/i18n/chunks/bn-1.ts | 661 ++++++++++++++ app/src/lib/i18n/chunks/bn-5.ts | 168 ++++ app/src/lib/i18n/chunks/de-1.ts | 666 ++++++++++++++ app/src/lib/i18n/chunks/de-5.ts | 168 ++++ app/src/lib/i18n/chunks/en-1.ts | 650 +++++++++++++- app/src/lib/i18n/chunks/en-5.ts | 168 ++++ app/src/lib/i18n/chunks/es-1.ts | 664 ++++++++++++++ app/src/lib/i18n/chunks/es-5.ts | 168 ++++ app/src/lib/i18n/chunks/fr-1.ts | 666 ++++++++++++++ app/src/lib/i18n/chunks/fr-5.ts | 168 ++++ app/src/lib/i18n/chunks/hi-1.ts | 661 ++++++++++++++ app/src/lib/i18n/chunks/hi-5.ts | 168 ++++ app/src/lib/i18n/chunks/id-1.ts | 661 ++++++++++++++ app/src/lib/i18n/chunks/id-5.ts | 168 ++++ app/src/lib/i18n/chunks/it-1.ts | 661 ++++++++++++++ app/src/lib/i18n/chunks/it-5.ts | 168 ++++ app/src/lib/i18n/chunks/ko-1.ts | 661 ++++++++++++++ app/src/lib/i18n/chunks/ko-5.ts | 168 ++++ app/src/lib/i18n/chunks/pt-1.ts | 661 ++++++++++++++ app/src/lib/i18n/chunks/pt-5.ts | 168 ++++ app/src/lib/i18n/chunks/ru-1.ts | 661 ++++++++++++++ app/src/lib/i18n/chunks/ru-5.ts | 168 ++++ app/src/lib/i18n/chunks/zh-CN-1.ts | 660 ++++++++++++++ app/src/lib/i18n/chunks/zh-CN-5.ts | 168 ++++ app/src/lib/i18n/en.ts | 819 +++++++++++++++++- app/src/pages/Conversations.tsx | 38 +- app/src/pages/Home.tsx | 6 +- app/src/pages/Settings.tsx | 12 +- app/src/pages/Skills.tsx | 13 +- app/src/pages/Welcome.tsx | 23 +- .../Skills.composio-catalog.test.tsx | 2 +- app/src/pages/ios/MascotScreen.tsx | 81 +- app/src/pages/ios/PairScreen.tsx | 57 +- .../pages/onboarding/steps/ApiKeysStep.tsx | 8 +- .../pages/onboarding/steps/LocalAIStep.tsx | 18 +- app/src/pages/onboarding/steps/SkillsStep.tsx | 4 +- package.json | 1 + scripts/i18n-react-audit.ts | 208 +++++ 103 files changed, 13549 insertions(+), 1178 deletions(-) create mode 100644 scripts/i18n-react-audit.ts diff --git a/app/src/components/AppUpdatePrompt.tsx b/app/src/components/AppUpdatePrompt.tsx index 9aacbb805..2af06cdfd 100644 --- a/app/src/components/AppUpdatePrompt.tsx +++ b/app/src/components/AppUpdatePrompt.tsx @@ -108,7 +108,7 @@ const AppUpdatePrompt = (props: AppUpdatePromptProps) => { )} diff --git a/app/src/components/BootCheckGate/BootCheckGate.tsx b/app/src/components/BootCheckGate/BootCheckGate.tsx index 4df60a84a..d2c4d3fc7 100644 --- a/app/src/components/BootCheckGate/BootCheckGate.tsx +++ b/app/src/components/BootCheckGate/BootCheckGate.tsx @@ -315,7 +315,8 @@ function ModePicker({ onConfirm }: PickerProps) { /> {tokenError &&

{tokenError}

}

- {t('bootCheck.storedLocally')} Authorization: Bearer … on every RPC. + {t('bootCheck.storedLocally')} Authorization: Bearer …{' '} + {t('bootCheck.rpcAuthSuffix')}

diff --git a/app/src/components/LocalAIDownloadSnackbar.tsx b/app/src/components/LocalAIDownloadSnackbar.tsx index d9e9ee3af..1dabfa0ca 100644 --- a/app/src/components/LocalAIDownloadSnackbar.tsx +++ b/app/src/components/LocalAIDownloadSnackbar.tsx @@ -119,7 +119,7 @@ const LocalAIDownloadSnackbar = () => { )} {!onApplySuggestedEnv && (

- Re-install with these values to apply them. + {t('mcp.configAssistant.reinstallHint')}

)} @@ -143,7 +148,7 @@ const ConfigAssistantPanel = ({ {sending && (
- Thinking... + {t('mcp.configAssistant.thinking')}
)} @@ -165,7 +170,7 @@ const ConfigAssistantPanel = ({ onChange={e => setInput(e.target.value)} onKeyDown={handleKeyDown} disabled={sending} - placeholder="Ask a question (Enter to send, Shift+Enter for newline)" + placeholder={t('mcp.configAssistant.inputPlaceholder')} className="flex-1 rounded-lg border border-stone-200 dark:border-neutral-700 bg-white dark:bg-neutral-900 px-3 py-1.5 text-sm text-stone-800 dark:text-neutral-100 placeholder:text-stone-400 dark:placeholder:text-neutral-500 focus:outline-none focus:ring-2 focus:ring-primary-500/40 disabled:opacity-50 resize-none" /> diff --git a/app/src/components/channels/mcp/InstallDialog.tsx b/app/src/components/channels/mcp/InstallDialog.tsx index c242c3028..f0a54fd5a 100644 --- a/app/src/components/channels/mcp/InstallDialog.tsx +++ b/app/src/components/channels/mcp/InstallDialog.tsx @@ -7,6 +7,7 @@ import debug from 'debug'; import { useCallback, useEffect, useRef, useState } from 'react'; +import { useT } from '../../../lib/i18n/I18nContext'; import { mcpClientsApi } from '../../../services/api/mcpClientsApi'; import type { InstalledServer, SmitheryServerDetail } from './types'; @@ -20,6 +21,7 @@ interface InstallDialogProps { } const InstallDialog = ({ qualifiedName, prefillEnv, onSuccess, onCancel }: InstallDialogProps) => { + const { t } = useT(); const [detail, setDetail] = useState(null); const [loadingDetail, setLoadingDetail] = useState(true); const [detailError, setDetailError] = useState(null); @@ -61,7 +63,7 @@ const InstallDialog = ({ qualifiedName, prefillEnv, onSuccess, onCancel }: Insta }) .catch(err => { if (latestQualifiedNameRef.current !== requestedName) return; - const msg = err instanceof Error ? err.message : 'Failed to load server details'; + const msg = err instanceof Error ? err.message : t('mcp.install.failedDetail'); log('detail error: %s', msg); setDetailError(msg); }) @@ -70,7 +72,7 @@ const InstallDialog = ({ qualifiedName, prefillEnv, onSuccess, onCancel }: Insta setLoadingDetail(false); } }); - }, [qualifiedName, prefillEnv]); + }, [qualifiedName, prefillEnv, t]); const toggleShowEnv = useCallback((key: string) => { setShowEnv(prev => ({ ...prev, [key]: !prev[key] })); @@ -86,7 +88,7 @@ const InstallDialog = ({ qualifiedName, prefillEnv, onSuccess, onCancel }: Insta // Validate required keys are filled. for (const key of detail.required_env_keys ?? []) { if (!envValues[key]?.trim()) { - setInstallError(`"${key}" is required`); + setInstallError(t('mcp.install.missingRequired').replace('{key}', key)); return; } } @@ -97,7 +99,7 @@ const InstallDialog = ({ qualifiedName, prefillEnv, onSuccess, onCancel }: Insta try { parsedConfig = JSON.parse(configJson.trim()); } catch { - setInstallError('Config JSON is not valid JSON'); + setInstallError(t('mcp.install.invalidJson')); return; } } @@ -115,18 +117,18 @@ const InstallDialog = ({ qualifiedName, prefillEnv, onSuccess, onCancel }: Insta log('install success server_id=%s', server.server_id); onSuccess(server); } catch (err) { - const msg = err instanceof Error ? err.message : 'Install failed'; + const msg = err instanceof Error ? err.message : t('mcp.install.failedInstall'); log('install error: %s', msg); setInstallError(msg); } finally { setInstalling(false); } - }, [detail, envValues, configJson, qualifiedName, onSuccess]); + }, [detail, envValues, configJson, qualifiedName, onSuccess, t]); if (loadingDetail) { return (
- Loading server details... + {t('mcp.install.loadingDetail')}
); } @@ -141,7 +143,7 @@ const InstallDialog = ({ qualifiedName, prefillEnv, onSuccess, onCancel }: Insta type="button" onClick={onCancel} className="text-sm text-stone-500 dark:text-neutral-400 hover:underline"> - Go back + {t('mcp.install.back')} ); @@ -166,7 +168,7 @@ const InstallDialog = ({ qualifiedName, prefillEnv, onSuccess, onCancel }: Insta )}

- Install {detail.display_name} + {t('mcp.install.title').replace('{name}', detail.display_name)}

{detail.description && (

@@ -180,7 +182,7 @@ const InstallDialog = ({ qualifiedName, prefillEnv, onSuccess, onCancel }: Insta {(detail.required_env_keys ?? []).length > 0 && (

- Required environment variables + {t('mcp.install.requiredEnv')}

{detail.required_env_keys!.map(key => (
@@ -195,7 +197,7 @@ const InstallDialog = ({ qualifiedName, prefillEnv, onSuccess, onCancel }: Insta type={showEnv[key] ? 'text' : 'password'} value={envValues[key] ?? ''} onChange={e => handleEnvChange(key, e.target.value)} - placeholder={`Enter ${key}`} + placeholder={t('mcp.install.enterValue').replace('{key}', key)} disabled={installing} className="flex-1 rounded-lg border border-stone-200 dark:border-neutral-700 bg-white dark:bg-neutral-900 px-3 py-1.5 text-sm text-stone-800 dark:text-neutral-100 placeholder:text-stone-400 dark:placeholder:text-neutral-500 focus:outline-none focus:ring-2 focus:ring-primary-500/40 disabled:opacity-50" /> @@ -204,7 +206,7 @@ const InstallDialog = ({ qualifiedName, prefillEnv, onSuccess, onCancel }: Insta onClick={() => toggleShowEnv(key)} disabled={installing} className="shrink-0 rounded-lg border border-stone-200 dark:border-neutral-700 px-2 py-1 text-xs text-stone-500 dark:text-neutral-400 hover:border-stone-300 dark:hover:border-neutral-600 disabled:opacity-50"> - {showEnv[key] ? 'Hide' : 'Show'} + {showEnv[key] ? t('mcp.install.hide') : t('mcp.install.show')}
@@ -217,7 +219,7 @@ const InstallDialog = ({ qualifiedName, prefillEnv, onSuccess, onCancel }: Insta