update ui
This commit is contained in:
1 parent
d499edabbc
commit
b66afcf2c5
8 files changed
+567
-585
No files matched your search
+1
-1
@@ -12,7 +12,7 @@
|
||||
: matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
||||
document.documentElement.dataset.theme = theme;
|
||||
document.documentElement.style.colorScheme = theme;
|
||||
document.documentElement.style.backgroundColor = theme === 'dark' ? '#0b1220' : '#f4f7fb';
|
||||
document.documentElement.style.backgroundColor = theme === 'dark' ? '#111412' : '#f6f7f5';
|
||||
} catch {
|
||||
// The app applies the theme again during initialization.
|
||||
}
|
||||
|
||||
+6
-12
@@ -442,7 +442,7 @@ export const jaOverrides = {
|
||||
'agents.sessions.databaseMissing': 'セッションデータベースが見つかりません',
|
||||
'agents.sessions.repairTitle': '過去のセッションを復元',
|
||||
'agents.sessions.repairDescription': '他の Provider のセッションを現在のセッション Provider に同期します。',
|
||||
'agents.sessions.autoRepair': 'Codex 起動前に過去のセッションを自動復元',
|
||||
'agents.sessions.autoRepair': '過去のセッションを自動復元',
|
||||
'agents.sessions.settingLoading': '読み込み中',
|
||||
'agents.sessions.settingOn': 'オン',
|
||||
'agents.sessions.settingOff': 'オフ',
|
||||
@@ -517,17 +517,11 @@ export const jaOverrides = {
|
||||
'agents.modify.clear': '設定を消去',
|
||||
'agents.modify.invalid': '現在の設定を解析できません。「設定変更を適用」は最小の有効な設定を再構築し、「デフォルト設定」はファイル全体をリセットします。',
|
||||
'agents.modify.applied': 'アプリが管理するフィールドは適用済みで、それ以外のユーザー設定は保持されています。',
|
||||
'agents.footer.changed': 'モデル選択が変更されました。設定変更を適用すると新しいモデルが使用されます。',
|
||||
'agents.footer.applied': '設定変更は適用済みです。アプリは関連フィールドだけを管理します。',
|
||||
'agents.footer.invalidManaged': '設定が無効です。変更を適用して修復するか、デフォルト設定にリセットしてください。',
|
||||
'agents.footer.unsupported': '現在のシステムではこのクライアントを設定できません',
|
||||
'agents.footer.installFirst': 'クライアントをインストールしてから再検出してください',
|
||||
'agents.footer.noCommand': '設定ファイルは検出しましたが、クライアントコマンドが見つかりません',
|
||||
'agents.footer.invalidConfig': '元の設定形式が無効なため、安全に変更できません',
|
||||
'agents.launchMethods': 'Codex の起動方法',
|
||||
'agents.launch.enableFirst': '先に設定変更を適用してください',
|
||||
'agents.launch.applyFirst': '先に選択中のモデルを適用してください',
|
||||
'agents.launch.starting': '起動中',
|
||||
'agents.launch.startCli': 'CLI を起動',
|
||||
'agents.launch.startApp': 'App を起動',
|
||||
'agents.launch.start': '{target} を起動',
|
||||
'agents.launch.unavailable': '起動できません',
|
||||
'agents.launch.closeChatgpt': 'ChatGPT App を終了',
|
||||
@@ -791,9 +785,9 @@ export const jaOverrides = {
|
||||
'kernel.dialog.install': 'コアのインストール',
|
||||
'kernel.dialog.phase': '現在の段階',
|
||||
'kernel.dialog.unknownProgress': '進捗不明',
|
||||
'kernel.access.openaiDescription': 'OpenAI SDK、OpenCode などの互換クライアント向け',
|
||||
'kernel.access.claudeDescription': 'Claude SDK および Claude Code 向け',
|
||||
'kernel.access.geminiDescription': 'Gemini ネイティブ互換クライアント向け',
|
||||
'kernel.access.openaiDescription': 'OpenAI互換形式',
|
||||
'kernel.access.claudeDescription': 'Anthropic互換形式',
|
||||
'kernel.access.geminiDescription': 'Gemini互換形式',
|
||||
'authFiles.unnamed': '無名の認証ファイル',
|
||||
'management.notConfigured': '未設定',
|
||||
'management.error.upstream': '上流リクエストに失敗しました',
|
||||
|
||||
+12
-24
@@ -445,7 +445,7 @@ export const zhCN = {
|
||||
'agents.sessions.databaseMissing': '未发现会话数据库',
|
||||
'agents.sessions.repairTitle': '恢复历史会话',
|
||||
'agents.sessions.repairDescription': '将其他渠道的会话同步到当前会话',
|
||||
'agents.sessions.autoRepair': '启动 Codex 前自动恢复历史会话',
|
||||
'agents.sessions.autoRepair': '自动恢复历史会话',
|
||||
'agents.sessions.settingLoading': '读取中',
|
||||
'agents.sessions.settingOn': '已开启',
|
||||
'agents.sessions.settingOff': '已关闭',
|
||||
@@ -520,17 +520,11 @@ export const zhCN = {
|
||||
'agents.modify.clear': '清空配置',
|
||||
'agents.modify.invalid': '当前配置无法解析。点击“应用配置修改”会重建最小合法配置;“默认配置”会重置整个文件。',
|
||||
'agents.modify.applied': '软件负责的配置字段已应用,其他用户内容保持不变。',
|
||||
'agents.footer.changed': '模型选择已变化;应用配置修改后将使用新模型。',
|
||||
'agents.footer.applied': '配置修改已应用;软件只管理相关字段。',
|
||||
'agents.footer.invalidManaged': '配置当前无效,请应用修改进行修复,或重置为默认配置。',
|
||||
'agents.footer.unsupported': '当前系统无法配置该客户端',
|
||||
'agents.footer.installFirst': '请先安装客户端并重新检测',
|
||||
'agents.footer.noCommand': '检测到配置文件,但没有找到客户端命令',
|
||||
'agents.footer.invalidConfig': '原配置格式异常,无法安全修改',
|
||||
'agents.launchMethods': 'Codex 启动方式',
|
||||
'agents.launch.enableFirst': '请先应用配置修改',
|
||||
'agents.launch.applyFirst': '请先应用当前模型选择',
|
||||
'agents.launch.starting': '启动中',
|
||||
'agents.launch.startCli': '启动 CLI',
|
||||
'agents.launch.startApp': '启动 App',
|
||||
'agents.launch.start': '启动 {target}',
|
||||
'agents.launch.unavailable': '无法启动',
|
||||
'agents.launch.closeChatgpt': '关闭 ChatGPT App',
|
||||
@@ -794,9 +788,9 @@ export const zhCN = {
|
||||
'kernel.dialog.install': '内核安装',
|
||||
'kernel.dialog.phase': '当前阶段',
|
||||
'kernel.dialog.unknownProgress': '进度未知',
|
||||
'kernel.access.openaiDescription': '适用于 OpenAI SDK、OpenCode 等兼容客户端',
|
||||
'kernel.access.claudeDescription': '适用于 Claude SDK 与 Claude Code',
|
||||
'kernel.access.geminiDescription': '适用于 Gemini 原生兼容客户端',
|
||||
'kernel.access.openaiDescription': 'OpenAI兼容格式',
|
||||
'kernel.access.claudeDescription': 'Anthropic兼容格式',
|
||||
'kernel.access.geminiDescription': 'Gemini兼容格式',
|
||||
'authFiles.unnamed': '未命名认证文件',
|
||||
'management.notConfigured': '未配置',
|
||||
'management.error.upstream': '上游请求失败',
|
||||
@@ -1293,7 +1287,7 @@ export const en: Record<MessageKey, string> = {
|
||||
'agents.sessions.databaseMissing': 'No session database found',
|
||||
'agents.sessions.repairTitle': 'Restore Historical Sessions',
|
||||
'agents.sessions.repairDescription': 'Sync sessions from other providers to the current session provider.',
|
||||
'agents.sessions.autoRepair': 'Restore historical sessions before launching Codex',
|
||||
'agents.sessions.autoRepair': 'Automatically restore historical sessions',
|
||||
'agents.sessions.settingLoading': 'Loading',
|
||||
'agents.sessions.settingOn': 'On',
|
||||
'agents.sessions.settingOff': 'Off',
|
||||
@@ -1368,17 +1362,11 @@ export const en: Record<MessageKey, string> = {
|
||||
'agents.modify.clear': 'Clear Configuration',
|
||||
'agents.modify.invalid': 'The current configuration cannot be parsed. Apply Configuration Changes rebuilds a minimal valid configuration; Default Configuration resets the whole file.',
|
||||
'agents.modify.applied': 'The fields managed by the app are applied; all other user content remains unchanged.',
|
||||
'agents.footer.changed': 'The model selection changed. Apply the configuration to use the new model.',
|
||||
'agents.footer.applied': 'Configuration changes are applied; only the relevant fields are managed by the app.',
|
||||
'agents.footer.invalidManaged': 'The configuration is invalid. Apply changes to repair it or reset it to the default configuration.',
|
||||
'agents.footer.unsupported': 'This client cannot be configured on the current system',
|
||||
'agents.footer.installFirst': 'Install the client, then detect again',
|
||||
'agents.footer.noCommand': 'A configuration file was found, but no client command is available',
|
||||
'agents.footer.invalidConfig': 'The original configuration is invalid and cannot be modified safely',
|
||||
'agents.launchMethods': 'Codex launch methods',
|
||||
'agents.launch.enableFirst': 'Apply the configuration changes first',
|
||||
'agents.launch.applyFirst': 'Apply the selected model first',
|
||||
'agents.launch.starting': 'Starting',
|
||||
'agents.launch.startCli': 'Start CLI',
|
||||
'agents.launch.startApp': 'Start App',
|
||||
'agents.launch.start': 'Start {target}',
|
||||
'agents.launch.unavailable': 'Cannot Start',
|
||||
'agents.launch.closeChatgpt': 'Close ChatGPT App',
|
||||
@@ -1642,9 +1630,9 @@ export const en: Record<MessageKey, string> = {
|
||||
'kernel.dialog.install': 'Core Installation',
|
||||
'kernel.dialog.phase': 'Current Phase',
|
||||
'kernel.dialog.unknownProgress': 'Progress Unknown',
|
||||
'kernel.access.openaiDescription': 'For OpenAI SDK, OpenCode, and other compatible clients',
|
||||
'kernel.access.claudeDescription': 'For Claude SDK and Claude Code',
|
||||
'kernel.access.geminiDescription': 'For native Gemini-compatible clients',
|
||||
'kernel.access.openaiDescription': 'OpenAI-compatible format',
|
||||
'kernel.access.claudeDescription': 'Anthropic-compatible format',
|
||||
'kernel.access.geminiDescription': 'Gemini-compatible format',
|
||||
'authFiles.unnamed': 'Unnamed credential file',
|
||||
'management.notConfigured': 'Not configured',
|
||||
'management.error.upstream': 'Upstream request failed',
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
const phraseReplacements: ReadonlyArray<readonly [string, string]> = [
|
||||
['兼容格式', '相容格式'],
|
||||
['历史', '歷史'],
|
||||
['高级设置', '進階設定'],
|
||||
['繁体中文', '繁體中文'],
|
||||
['简体中文', '簡體中文'],
|
||||
|
||||
+73
-100
@@ -12,6 +12,7 @@ import { invoke } from '@tauri-apps/api/core';
|
||||
import { listen } from '@tauri-apps/api/event';
|
||||
import {
|
||||
AlertTriangle,
|
||||
AppWindow,
|
||||
BadgeCheck,
|
||||
Bot,
|
||||
Check,
|
||||
@@ -22,6 +23,7 @@ import {
|
||||
RefreshCw,
|
||||
Search,
|
||||
Sparkles,
|
||||
Terminal,
|
||||
Trash2,
|
||||
X,
|
||||
} from 'lucide-react';
|
||||
@@ -481,10 +483,11 @@ export function AgentsPage() {
|
||||
const [modelByClient, setModelByClient] = useState<Partial<Record<AgentClientId, string>>>(
|
||||
readAgentModelSelections,
|
||||
);
|
||||
const [launchTargetByClient, setLaunchTargetByClient] = useState<Partial<Record<AgentClientId, string>>>({});
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [modelLoading, setModelLoading] = useState(false);
|
||||
const [busyAction, setBusyAction] = useState<'apply' | 'default' | 'clear' | 'launch' | 'close-app' | null>(null);
|
||||
const [busyAction, setBusyAction] = useState<
|
||||
'apply' | 'default' | 'clear' | 'launch' | 'launch-cli' | 'launch-app' | 'close-app' | null
|
||||
>(null);
|
||||
const busy = busyAction !== null;
|
||||
const [detectionError, setDetectionError] = useState('');
|
||||
const [modelError, setModelError] = useState('');
|
||||
@@ -598,20 +601,6 @@ export function AgentsPage() {
|
||||
setCloseAppConfirmOpen(false);
|
||||
}, [selected]);
|
||||
|
||||
useEffect(() => {
|
||||
setLaunchTargetByClient((current) => agentDefinitions.reduce<Partial<Record<AgentClientId, string>>>(
|
||||
(next, definition) => {
|
||||
const targets = statuses.find((status) => status.id === definition.id)?.launchTargets ?? [];
|
||||
const previous = current[definition.id] ?? '';
|
||||
next[definition.id] = targets.some((target) => target.id === previous)
|
||||
? previous
|
||||
: targets[0]?.id ?? '';
|
||||
return next;
|
||||
},
|
||||
{},
|
||||
));
|
||||
}, [statuses]);
|
||||
|
||||
const activeDefinition = agentDefinitions.find((agent) => agent.id === selected)
|
||||
?? agentDefinitions[0];
|
||||
const activeStatus = statuses.find((status) => status.id === selected) ?? null;
|
||||
@@ -622,10 +611,9 @@ export function AgentsPage() {
|
||||
const selectedModelOption = findAgentModel(models, savedSelectedModel);
|
||||
const selectedModel = selectedModelOption?.name ?? '';
|
||||
const activeLaunchTargets = activeStatus?.launchTargets ?? [];
|
||||
const selectedLaunchTargetId = launchTargetByClient[selected] ?? activeLaunchTargets[0]?.id ?? '';
|
||||
const selectedLaunchTarget = activeLaunchTargets.find(
|
||||
(target) => target.id === selectedLaunchTargetId,
|
||||
) ?? activeLaunchTargets[0] ?? null;
|
||||
const defaultLaunchTarget = activeLaunchTargets[0] ?? null;
|
||||
const cliLaunchTarget = activeLaunchTargets.find((target) => target.id === 'cli') ?? null;
|
||||
const appLaunchTarget = activeLaunchTargets.find((target) => target.id === 'app') ?? null;
|
||||
const appliedModel = activeStatus?.appliedModel ?? activeStatus?.currentModel ?? '';
|
||||
const modelDraftChanged = Boolean(
|
||||
selectedModel.trim()
|
||||
@@ -641,13 +629,13 @@ export function AgentsPage() {
|
||||
&& !modelLoading
|
||||
&& selectedModelOption,
|
||||
);
|
||||
const canLaunch = Boolean(
|
||||
const launchEnabled = Boolean(
|
||||
activeStatus?.supportedPlatform
|
||||
&& activeStatus.installed
|
||||
&& selectedLaunchTarget
|
||||
&& (selected === 'codex'
|
||||
|| (activeStatus.modificationEnabled && activeStatus.modificationState === 'applied')),
|
||||
);
|
||||
const canLaunchTarget = (target: AgentLaunchTarget | null) => launchEnabled && Boolean(target);
|
||||
const modelHint = modelSelectionError
|
||||
|| modelError
|
||||
|| (modelLoading
|
||||
@@ -662,20 +650,6 @@ export function AgentsPage() {
|
||||
: activeStatus?.modificationState === 'applied'
|
||||
? t('agents.modify.applied')
|
||||
: '';
|
||||
const footerMessage = activeStatus?.modificationState === 'applied'
|
||||
? draftChanged
|
||||
? t('agents.footer.changed')
|
||||
: t('agents.footer.applied')
|
||||
: activeStatus?.modificationState === 'invalid'
|
||||
? t('agents.footer.invalidManaged')
|
||||
: !activeStatus?.supportedPlatform
|
||||
? t('agents.footer.unsupported')
|
||||
: !activeStatus.installed
|
||||
? t('agents.footer.installFirst')
|
||||
: activeStatus.launchTargets.length === 0
|
||||
? t('agents.footer.noCommand')
|
||||
: '';
|
||||
|
||||
const refreshModels = () => {
|
||||
void loadModels(selected);
|
||||
};
|
||||
@@ -776,14 +750,18 @@ export function AgentsPage() {
|
||||
}
|
||||
};
|
||||
|
||||
const launchAgent = async () => {
|
||||
setBusyAction('launch');
|
||||
const launchAgent = async (target: AgentLaunchTarget | null) => {
|
||||
if (!target) return;
|
||||
const launchAction = selected === 'codex'
|
||||
? target.id === 'cli' ? 'launch-cli' : 'launch-app'
|
||||
: 'launch';
|
||||
setBusyAction(launchAction);
|
||||
setLaunchError('');
|
||||
try {
|
||||
if (selected !== 'codex' && draftChanged) {
|
||||
throw new Error(t('agents.error.applyFirst'));
|
||||
}
|
||||
await invoke('launch_agent', { client: selected, target: selectedLaunchTarget?.id });
|
||||
await invoke('launch_agent', { client: selected, target: target.id });
|
||||
} catch (requestError) {
|
||||
setLaunchError(String(requestError));
|
||||
} finally {
|
||||
@@ -975,23 +953,26 @@ export function AgentsPage() {
|
||||
</div>
|
||||
<div className="agent-modification-control">
|
||||
{selected === 'codex' ? (
|
||||
<label
|
||||
className="agent-oauth-configuration"
|
||||
title={t('agents.modify.oauthConfiguration')}
|
||||
>
|
||||
<span>{t('agents.modify.oauthConfiguration')}</span>
|
||||
<span className="switch-control">
|
||||
<input
|
||||
type="checkbox"
|
||||
role="switch"
|
||||
checked={oauthConfiguration}
|
||||
onChange={(event) => setOauthConfigurationDraft(event.currentTarget.checked)}
|
||||
disabled={busy}
|
||||
aria-label={t('agents.modify.oauthConfiguration')}
|
||||
/>
|
||||
<span className="switch-track" />
|
||||
</span>
|
||||
</label>
|
||||
<div className="agent-codex-options">
|
||||
<CodexSessionAutoRestoreCard />
|
||||
<label
|
||||
className="agent-oauth-configuration"
|
||||
title={t('agents.modify.oauthConfiguration')}
|
||||
>
|
||||
<span>{t('agents.modify.oauthConfiguration')}</span>
|
||||
<span className="switch-control">
|
||||
<input
|
||||
type="checkbox"
|
||||
role="switch"
|
||||
checked={oauthConfiguration}
|
||||
onChange={(event) => setOauthConfigurationDraft(event.currentTarget.checked)}
|
||||
disabled={busy}
|
||||
aria-label={t('agents.modify.oauthConfiguration')}
|
||||
/>
|
||||
<span className="switch-track" />
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
) : null}
|
||||
<div className={`agent-modification-buttons ${selected === 'codex' ? 'codex' : ''}`}>
|
||||
<button
|
||||
@@ -1040,56 +1021,48 @@ export function AgentsPage() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{selected === 'codex' ? <CodexSessionAutoRestoreCard /> : null}
|
||||
|
||||
<div className="agent-config-footer">
|
||||
{footerMessage ? (
|
||||
<div className="agent-config-summary">
|
||||
{activeStatus?.modificationState === 'applied' ? <Check size={16} /> : <Sparkles size={16} />}
|
||||
<span>{footerMessage}</span>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="agent-launch-control">
|
||||
<div className="agent-launch-actions">
|
||||
{activeLaunchTargets.length > 1 ? (
|
||||
<div className="agent-launch-targets" aria-label={t('agents.launchMethods')}>
|
||||
{activeLaunchTargets.map((target) => (
|
||||
<button
|
||||
type="button"
|
||||
className={target.id === selectedLaunchTarget?.id ? 'active' : ''}
|
||||
key={target.id}
|
||||
onClick={() => setLaunchTargetByClient((current) => ({
|
||||
...current,
|
||||
[selected]: target.id,
|
||||
}))}
|
||||
disabled={busy}
|
||||
title={target.detail}
|
||||
>
|
||||
{target.label.replace('Codex ', '')}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
) : null}
|
||||
<button
|
||||
type="button"
|
||||
className="primary-button"
|
||||
onClick={() => void launchAgent()}
|
||||
disabled={
|
||||
busy
|
||||
|| !canLaunch
|
||||
|| (selected !== 'codex' && draftChanged)
|
||||
}
|
||||
title={selected === 'codex'
|
||||
? selectedLaunchTarget?.detail
|
||||
: draftChanged
|
||||
{selected === 'codex' ? (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
className="secondary-button agent-launch-button"
|
||||
onClick={() => void launchAgent(cliLaunchTarget)}
|
||||
disabled={busy || !canLaunchTarget(cliLaunchTarget)}
|
||||
title={cliLaunchTarget?.detail ?? t('agents.launch.unavailable')}
|
||||
>
|
||||
{busyAction === 'launch-cli' ? <LoaderCircle size={16} className="spin" /> : <Terminal size={16} />}
|
||||
{busyAction === 'launch-cli' ? t('agents.launch.starting') : t('agents.launch.startCli')}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="primary-button agent-launch-button"
|
||||
onClick={() => void launchAgent(appLaunchTarget)}
|
||||
disabled={busy || !canLaunchTarget(appLaunchTarget)}
|
||||
title={appLaunchTarget?.detail ?? t('agents.launch.unavailable')}
|
||||
>
|
||||
{busyAction === 'launch-app' ? <LoaderCircle size={16} className="spin" /> : <AppWindow size={16} />}
|
||||
{busyAction === 'launch-app' ? t('agents.launch.starting') : t('agents.launch.startApp')}
|
||||
</button>
|
||||
</>
|
||||
) : (
|
||||
<button
|
||||
type="button"
|
||||
className="primary-button agent-launch-button"
|
||||
onClick={() => void launchAgent(defaultLaunchTarget)}
|
||||
disabled={busy || !canLaunchTarget(defaultLaunchTarget) || draftChanged}
|
||||
title={draftChanged
|
||||
? t('agents.launch.applyFirst')
|
||||
: activeStatus?.modificationState === 'applied'
|
||||
? selectedLaunchTarget?.detail
|
||||
? defaultLaunchTarget?.detail
|
||||
: t('agents.launch.enableFirst')}
|
||||
>
|
||||
{busyAction === 'launch' ? <LoaderCircle size={16} className="spin" /> : <Play size={16} />}
|
||||
{busyAction === 'launch' ? t('agents.launch.starting') : selectedLaunchTarget ? t('agents.launch.start', { target: selectedLaunchTarget.label }) : t('agents.launch.unavailable')}
|
||||
</button>
|
||||
>
|
||||
{busyAction === 'launch' ? <LoaderCircle size={16} className="spin" /> : <Play size={16} />}
|
||||
{busyAction === 'launch' ? t('agents.launch.starting') : defaultLaunchTarget ? t('agents.launch.start', { target: defaultLaunchTarget.label }) : t('agents.launch.unavailable')}
|
||||
</button>
|
||||
)}
|
||||
{selected === 'codex' ? (
|
||||
<button
|
||||
type="button"
|
||||
|
||||
+450
-446
File diff suppressed because it is too large.
Load diff
+2
-2
@@ -5,8 +5,8 @@ export type AppTheme = 'light' | 'dark';
|
||||
|
||||
const STORAGE_KEY = 'easy-cli-proxy-api.theme';
|
||||
const WINDOW_BACKGROUND: Record<AppTheme, string> = {
|
||||
light: '#f4f7fb',
|
||||
dark: '#0b1220',
|
||||
light: '#f6f7f5',
|
||||
dark: '#111412',
|
||||
};
|
||||
|
||||
async function applyNativeTheme(theme: AppTheme): Promise<void> {
|
||||
|
||||
@@ -25,6 +25,27 @@ describe('i18n', () => {
|
||||
.toBe('1.2.3 をインストールしています');
|
||||
});
|
||||
|
||||
it('translates client API compatibility formats consistently', () => {
|
||||
expect(translate('zh-CN', 'kernel.access.openaiDescription')).toBe('OpenAI兼容格式');
|
||||
expect(translate('zh-TW', 'kernel.access.claudeDescription')).toBe('Anthropic相容格式');
|
||||
expect(translate('ja', 'kernel.access.geminiDescription')).toBe('Gemini互換形式');
|
||||
expect(translate('en', 'kernel.access.openaiDescription')).toBe('OpenAI-compatible format');
|
||||
});
|
||||
|
||||
it('translates direct Codex launch actions', () => {
|
||||
expect(translate('zh-CN', 'agents.launch.startCli')).toBe('启动 CLI');
|
||||
expect(translate('zh-TW', 'agents.launch.startApp')).toBe('啟動 App');
|
||||
expect(translate('ja', 'agents.launch.startCli')).toBe('CLI を起動');
|
||||
expect(translate('en', 'agents.launch.startApp')).toBe('Start App');
|
||||
});
|
||||
|
||||
it('uses the concise automatic session restoration label', () => {
|
||||
expect(translate('zh-CN', 'agents.sessions.autoRepair')).toBe('自动恢复历史会话');
|
||||
expect(translate('zh-TW', 'agents.sessions.autoRepair')).toBe('自動恢復歷史工作階段');
|
||||
expect(translate('ja', 'agents.sessions.autoRepair')).toBe('過去のセッションを自動復元');
|
||||
expect(translate('en', 'agents.sessions.autoRepair')).toBe('Automatically restore historical sessions');
|
||||
});
|
||||
|
||||
it('uses each language native name independently of the active locale', () => {
|
||||
expect(languageOptions).toEqual([
|
||||
{ value: 'zh-CN', nativeLabel: '简体中文' },
|
||||
|
||||
Reference in new issue
Block a user