fix(i18n): polish Japanese dashboard copy

This commit is contained in:
Tam Nhu Tran
2026-03-10 16:46:11 +07:00
parent 8b5158bec5
commit e28f87bc9c
4 changed files with 131 additions and 86 deletions
@@ -171,8 +171,7 @@ export function HistorySyncLearningMap({
{legacyTargetCount > 0 && ( {legacyTargetCount > 0 && (
<div className="mt-2 rounded-md border border-amber-500/50 bg-amber-500/10 px-3 py-2 text-xs text-amber-800 dark:text-amber-300"> <div className="mt-2 rounded-md border border-amber-500/50 bg-amber-500/10 px-3 py-2 text-xs text-amber-800 dark:text-amber-300">
{legacyTargetCount} legacy account {t('historySyncLearningMap.legacyConfirmation', { count: legacyTargetCount })}
{legacyTargetCount > 1 ? 's still need' : ' still needs'} explicit confirmation.
</div> </div>
)} )}
</CollapsibleContent> </CollapsibleContent>
+90 -83
View File
@@ -418,6 +418,8 @@ const resources = {
historySyncGroup: 'History Sync Group', historySyncGroup: 'History Sync Group',
historySyncGroupDesc: historySyncGroupDesc:
'Same group means shared project context lane. Default fallback is default.', 'Same group means shared project context lane. Default fallback is default.',
legacyConfirmation_one: '{{count}} legacy account still needs explicit confirmation.',
legacyConfirmation_other: '{{count}} legacy accounts still need explicit confirmation.',
}, },
accountsTable: { accountsTable: {
name: 'Name', name: 'Name',
@@ -1567,6 +1569,8 @@ const resources = {
modeSwitchDesc: '同步对话框可让用户在隔离/共享间切换并选择更深连续性。', modeSwitchDesc: '同步对话框可让用户在隔离/共享间切换并选择更深连续性。',
historySyncGroup: '历史同步分组', historySyncGroup: '历史同步分组',
historySyncGroupDesc: '同一分组即共享项目上下文。默认回退为 default。', historySyncGroupDesc: '同一分组即共享项目上下文。默认回退为 default。',
legacyConfirmation_one: '{{count}} 个旧账号仍需要显式确认。',
legacyConfirmation_other: '{{count}} 个旧账号仍需要显式确认。',
}, },
accountsTable: { accountsTable: {
name: '名称', name: '名称',
@@ -2719,6 +2723,8 @@ const resources = {
historySyncGroup: 'Nhóm đồng bộ hóa lịch sử', historySyncGroup: 'Nhóm đồng bộ hóa lịch sử',
historySyncGroupDesc: historySyncGroupDesc:
'Cùng một nhóm nghĩa là chia sẻ cùng bối cảnh project. Nếu để trống sẽ dùng nhóm mặc định.', 'Cùng một nhóm nghĩa là chia sẻ cùng bối cảnh project. Nếu để trống sẽ dùng nhóm mặc định.',
legacyConfirmation_one: '{{count}} tài khoản cũ vẫn cần xác nhận rõ ràng.',
legacyConfirmation_other: '{{count}} tài khoản cũ vẫn cần xác nhận rõ ràng.',
}, },
accountsTable: { accountsTable: {
name: 'Tên', name: 'Tên',
@@ -3613,8 +3619,7 @@ const resources = {
presetNameOptional: 'プリセット名 (任意)', presetNameOptional: 'プリセット名 (任意)',
presetNamePlaceholder: '例: My Custom Config', presetNamePlaceholder: '例: My Custom Config',
codexTipPrefix: 'Codex のヒント: サフィックス', codexTipPrefix: 'Codex のヒント: サフィックス',
codexTipSuffix: codexTipSuffix: 'で推論強度を固定できます。サフィックスなしのモデルは思考設定を使います。',
'で effort を固定できます。サフィックスなしのモデルは Thinking 設定を使います。',
defaultModel: 'デフォルトモデル', defaultModel: 'デフォルトモデル',
defaultModelDesc: '特定のティア指定がない場合に使用', defaultModelDesc: '特定のティア指定がない場合に使用',
opusModel: 'Opus (最上位)', opusModel: 'Opus (最上位)',
@@ -3667,7 +3672,7 @@ const resources = {
createAuthProfileDialog: { createAuthProfileDialog: {
title: '新しいアカウントを作成', title: '新しいアカウントを作成',
description: description:
'認証プロファイルには Claude CLI へのログインが必要です。以下のコマンドをターミナルで実行してください。同期モード、グループ、継続性の深さは後で Accounts テーブルから編集できます。', '認証プロファイルには Claude CLI へのログインが必要です。以下のコマンドをターミナルで実行してください。同期モード、グループ、継続性の深さは後でアカウント一覧から編集できます。',
profileName: 'プロファイル名', profileName: 'プロファイル名',
profileNamePlaceholder: '例: work, personal, client', profileNamePlaceholder: '例: work, personal, client',
invalidProfileName: '名前は英字で始め、英数字、ハイフン、アンダースコアのみ使用できます。', invalidProfileName: '名前は英字で始め、英数字、ハイフン、アンダースコアのみ使用できます。',
@@ -3687,7 +3692,7 @@ const resources = {
afterRunStep1: 'ブラウザで Claude のログインを完了します', afterRunStep1: 'ブラウザで Claude のログインを完了します',
afterRunStep2: 'ここに戻って更新し、新しいアカウントを確認します', afterRunStep2: 'ここに戻って更新し、新しいアカウントを確認します',
poolingHint: poolingHint:
'Claude OAuth のプールルーティングを使う場合は、Accounts ページのアクションボタンから CLIProxy Claude pool を利用してください。', 'Claude OAuth のプールルーティングを使う場合は、アカウントページのアクションボタンから CLIProxy Claude Pool を利用してください。',
close: '閉じる', close: '閉じる',
copied: 'コピーしました!', copied: 'コピーしました!',
copyCommand: 'コマンドをコピー', copyCommand: 'コマンドをコピー',
@@ -3806,7 +3811,7 @@ const resources = {
title: 'プロファイルをローカル CLIProxy に同期', title: 'プロファイルをローカル CLIProxy に同期',
description: 'CCS の API プロファイルをローカルの CLIProxy config.yaml に同期します。', description: 'CCS の API プロファイルをローカルの CLIProxy config.yaml に同期します。',
noProfiles: '同期するプロファイルがありません。', noProfiles: '同期するプロファイルがありません。',
createProfilesFirst: '先に Profiles タブで API プロファイルを作成してください。', createProfilesFirst: '先にプロファイルタブで API プロファイルを作成してください。',
modelLabel: 'モデル:', modelLabel: 'モデル:',
ready: '準備完了', ready: '準備完了',
profilesToSync_one: '{{count}} 件のプロファイルを同期', profilesToSync_one: '{{count}} 件のプロファイルを同期',
@@ -3830,7 +3835,7 @@ const resources = {
tabHeaders: 'ヘッダー', tabHeaders: 'ヘッダー',
tabRequest: 'リクエスト', tabRequest: 'リクエスト',
tabResponse: 'レスポンス', tabResponse: 'レスポンス',
tabRaw: 'Raw', tabRaw: '生データ',
modelLabel: 'モデル:', modelLabel: 'モデル:',
quotaResetsIn: 'クォータのリセットまで ', quotaResetsIn: 'クォータのリセットまで ',
method: 'メソッド', method: 'メソッド',
@@ -3839,7 +3844,7 @@ const resources = {
endpoint: 'エンドポイント', endpoint: 'エンドポイント',
url: 'URL', url: 'URL',
timestamp: 'タイムスタンプ', timestamp: 'タイムスタンプ',
na: 'N/A', na: '該当なし',
noHeaders: '利用可能なヘッダーはありません', noHeaders: '利用可能なヘッダーはありません',
noRequestBody: 'リクエストボディなし', noRequestBody: 'リクエストボディなし',
noResponseBody: 'レスポンスボディなし', noResponseBody: 'レスポンスボディなし',
@@ -3848,7 +3853,7 @@ const resources = {
rateLimitedMsgNoModel: rateLimitedMsgNoModel:
'レート制限です。別のアカウントに切り替えるか、クォータのリセットを待ってください。', 'レート制限です。別のアカウントに切り替えるか、クォータのリセットを待ってください。',
authFailedMsg: authFailedMsg:
'認証に失敗しました。CLIProxy Settings で再認証するか、API キーを確認してください。', '認証に失敗しました。CLIProxy 設定で再認証するか、API キーを確認してください。',
notFoundMsg: notFoundMsg:
'エンドポイントが見つかりません。このプロバイダーには存在しない可能性があります。', 'エンドポイントが見つかりません。このプロバイダーには存在しない可能性があります。',
serverErrorMsg: serverErrorMsg:
@@ -3863,12 +3868,12 @@ const resources = {
'"{{name}}" が他の CCS auth アカウントと履歴や継続性を共有する方法を設定します。', '"{{name}}" が他の CCS auth アカウントと履歴や継続性を共有する方法を設定します。',
syncMode: '同期モード', syncMode: '同期モード',
selectContextMode: 'コンテキストモードを選択', selectContextMode: 'コンテキストモードを選択',
isolatedOption: 'isolated(同期なし)', isolatedOption: '分離(同期なし)',
sharedOption: 'shared(同期あり)', sharedOption: '共有(同期あり)',
sharedModeHint: sharedModeHint:
'Shared モードでは、同じ履歴同期グループ内のアカウントでワークスペースコンテキストを再利用します。', '共有モードでは、同じ履歴同期グループ内のアカウントでワークスペースコンテキストを再利用します。',
isolatedModeHint: isolatedModeHint:
'Isolated モードでは、このアカウントを他の CCS auth アカウントから完全に離します。', '分離モードでは、このアカウントを他の CCS auth アカウントから完全に切り離します。',
historySyncGroup: '履歴同期グループ', historySyncGroup: '履歴同期グループ',
groupPlaceholder: 'default', groupPlaceholder: 'default',
groupHint: groupHint:
@@ -3876,8 +3881,8 @@ const resources = {
invalidGroup: '英字で始まる有効なグループ名を入力してください。', invalidGroup: '英字で始まる有効なグループ名を入力してください。',
continuityDepth: '継続性レベル', continuityDepth: '継続性レベル',
selectContinuityDepth: '継続性レベルを選択', selectContinuityDepth: '継続性レベルを選択',
standardOption: 'standard(プロジェクトのみ)', standardOption: '標準(プロジェクトのみ)',
deeperOption: 'deeper continuity(上級者向け)', deeperOption: '拡張継続性(上級者向け)',
deeperHint: deeperHint:
'上級モードでは、session-env、file-history、shell-snapshots、todos も同期します。', '上級モードでは、session-env、file-history、shell-snapshots、todos も同期します。',
standardHint: '標準モードでは、プロジェクトのワークスペースコンテキストのみ同期します。', standardHint: '標準モードでは、プロジェクトのワークスペースコンテキストのみ同期します。',
@@ -3889,22 +3894,24 @@ const resources = {
}, },
historySyncLearningMap: { historySyncLearningMap: {
title: '履歴同期の仕組み', title: '履歴同期の仕組み',
description: 'Isolated -> Shared -> Deeper。変更は各行の Sync から行います。', description: '分離 -> 共有 -> 拡張共有。変更は各行の「同期」から行います。',
learningMap: '概要図', learningMap: '概要図',
isolated: 'Isolated', isolated: '分離',
shared: 'Shared', shared: '共有',
deeper: 'Deeper', deeper: '拡張共有',
cliproxyManaged_one: cliproxyManaged_one:
'{{count}} 件の CLIProxy Claude プールアカウントは Action Center / CLIProxy ページで管理されます。', '{{count}} 件の CLIProxy Claude Pool アカウントはCLIProxy ページで管理ます。',
cliproxyManaged_other: cliproxyManaged_other:
'{{count}} 件の CLIProxy Claude プールアカウントは Action Center / CLIProxy ページで管理されます。', '{{count}} 件の CLIProxy Claude Pool アカウントはCLIProxy ページで管理ます。',
showDetails: '詳細を表示: グループ、切り替え、レガシーポリシー', showDetails: '詳細を表示: グループ、切り替え、レガシーポリシー',
modeSwitch: 'モード切り替え', modeSwitch: 'モード切り替え',
modeSwitchDesc: modeSwitchDesc:
'Sync ダイアログから isolated / shared の切り替えと deeper continuity の選択ができます。', '「同期」ダイアログでは、分離/共有の切り替えと、より深い継続性の選択ができます。',
historySyncGroup: '履歴同期グループ', historySyncGroup: '履歴同期グループ',
historySyncGroupDesc: historySyncGroupDesc:
'同じグループ同じプロジェクトコンテキストレーンを共有します。既定のフォールバックは default す。', '同じグループのアカウントは、同じプロジェクトコンテキストレーンを共有します。未設定時は default を使います。',
legacyConfirmation_one: '{{count}} 件のレガシーアカウントで明示的な確認がまだ必要です。',
legacyConfirmation_other: '{{count}} 件のレガシーアカウントで明示的な確認がまだ必要です。',
}, },
accountsTable: { accountsTable: {
name: '名前', name: '名前',
@@ -3915,7 +3922,7 @@ const resources = {
historySync: '履歴同期', historySync: '履歴同期',
actions: '操作', actions: '操作',
syncTitle: '同期モード、グループ、継続性レベルを編集', syncTitle: '同期モード、グループ、継続性レベルを編集',
confirmLegacyTitle: 'この legacy アカウントの現在のモードを明示的に確定', confirmLegacyTitle: 'このレガシーアカウントの現在のモードを明示的に確定する',
sync: '同期', sync: '同期',
confirm: '確定', confirm: '確定',
active: '有効', active: '有効',
@@ -3924,17 +3931,17 @@ const resources = {
cannotDeleteDefault: '既定のアカウントは削除できません', cannotDeleteDefault: '既定のアカウントは削除できません',
noAccounts: noAccounts:
'CCS auth アカウントが見つかりません。追加するには ccs auth create を使ってください。', 'CCS auth アカウントが見つかりません。追加するには ccs auth create を使ってください。',
resetToDefault: 'CCS Default に戻す', resetToDefault: 'CCS の既定値に戻す',
deleteDialogTitle: 'アカウントを削除', deleteDialogTitle: 'アカウントを削除',
deleteDialogDesc: deleteDialogDesc:
'アカウント "{{name}}" を削除しますか? この操作でプロファイルと関連するすべてのセッションデータが削除されます。この操作は元に戻せません。', 'アカウント "{{name}}" を削除しますか? この操作でプロファイルと関連するすべてのセッションデータが削除されます。この操作は元に戻せません。',
cancel: 'キャンセル', cancel: 'キャンセル',
delete: '削除', delete: '削除',
sharedGroupStandard: 'shared{{group}}、標準)', sharedGroupStandard: '共有{{group}}、標準)',
sharedGroupDeeper: 'shared{{group}}、deeper', sharedGroupDeeper: '共有{{group}}、拡張',
sharedGroupLegacy: 'shared{{group}}、標準・legacy', sharedGroupLegacy: '共有{{group}}、標準・レガシー',
isolatedLegacy: 'isolated(レガシー既定)', isolatedLegacy: '分離(旧既定',
isolated: 'isolated', isolated: '分離',
}, },
addAccountDialog: { addAccountDialog: {
title: '{{displayName}} アカウントを追加', title: '{{displayName}} アカウントを追加',
@@ -3946,7 +3953,7 @@ const resources = {
'認証をクリックすると OAuth URL を取得します。任意のブラウザーで開いてサインインしてください。', '認証をクリックすると OAuth URL を取得します。任意のブラウザーで開いてサインインしてください。',
powerUserEnabled: '上級者モードが有効です', powerUserEnabled: '上級者モードが有効です',
powerUserSkipped: powerUserSkipped:
'Settings > Proxy で AGY responsibility checklist をスキップしています。OAuth / アカウントリスクはすべて自己責任す。', '設定 > プロキシで AGY の責任確認チェックをスキップしています。OAuth / アカウントに関するリスクはすべて自己責任となります。',
authMethod: '認証方法', authMethod: '認証方法',
selectKiroAuthMethod: 'Kiro の認証方法を選択', selectKiroAuthMethod: 'Kiro の認証方法を選択',
nicknameRequired: 'ニックネーム(必須)', nicknameRequired: 'ニックネーム(必須)',
@@ -4042,7 +4049,7 @@ const resources = {
secondLine: secondLine:
'OAuth とアカウントアクセスのリスクをすべて自己責任で負う場合のみ続行してください。', 'OAuth とアカウントアクセスのリスクをすべて自己責任で負う場合のみ続行してください。',
issueLabel: 'Issue #509 を読む', issueLabel: 'Issue #509 を読む',
proxySettingsLabel: 'Gemini + AGY の設定: Settings > Proxy', proxySettingsLabel: 'Gemini + AGY の設定: 設定 > プロキシ',
}, },
cliproxyDialog: { cliproxyDialog: {
name: '名前', name: '名前',
@@ -4103,9 +4110,9 @@ const resources = {
configFileNotFound: '設定ファイルが見つかりません', configFileNotFound: '設定ファイルが見つかりません',
}, },
settingsTabs: { settingsTabs: {
web: 'Web', web: 'Web検索',
env: '環境', env: '環境変数',
think: 'Thinking', think: '思考',
proxy: 'プロキシ', proxy: 'プロキシ',
auth: '認証', auth: '認証',
backup: 'バックアップ', backup: 'バックアップ',
@@ -4138,11 +4145,11 @@ const resources = {
}, },
settingsGlobalEnv: { settingsGlobalEnv: {
description: description:
'Claude 以外のサブスクリプションプロファイル(gemini、codex、agy、ghcp など)に注入する環境変数', 'Claude 以外のサブスクリプションプロファイル(gemini、codex、agy、ghcp など)に注入する環境変数',
enabled: 'Global Env を有効化', enabled: 'グローバル環境変数を有効化',
disabled: 'Global Env を無効化', disabled: 'グローバル環境変数を無効化',
enabledDesc: 'Env 変数をサードパーティープロファイル注入します', enabledDesc: '環境変数をサードパーティープロファイル注入します',
disabledDesc: 'Env 変数は注入されません', disabledDesc: '環境変数は注入されません',
envVars: '環境変数', envVars: '環境変数',
noneConfigured: '環境変数は未設定です', noneConfigured: '環境変数は未設定です',
addNew: '変数を追加', addNew: '変数を追加',
@@ -4219,7 +4226,7 @@ const resources = {
safety: '安全設定', safety: '安全設定',
agyModeTitle: 'Antigravity パワーユーザーモード', agyModeTitle: 'Antigravity パワーユーザーモード',
agyModeDesc: agyModeDesc:
'Add Account 画面と `ccs agy` フローで AGY の責任チェックリストをスキップします。', 'アカウント追加画面と `ccs agy` フローでAGY の責任確認チェックをスキップします。',
agyWarning: agyWarning:
'OAuth の停止/BAN リスクパターン (#509) を十分理解している場合にのみ使用してください。CCS はアカウント喪失の責任を負いません。', 'OAuth の停止/BAN リスクパターン (#509) を十分理解している場合にのみ使用してください。CCS はアカウント喪失の責任を負いません。',
finalConfirm: '最終確認', finalConfirm: '最終確認',
@@ -4275,15 +4282,14 @@ const resources = {
backendApi: 'CLIProxyAPI', backendApi: 'CLIProxyAPI',
}, },
settingsThinking: { settingsThinking: {
description: '対応モデルの拡張 Thinking / Reasoning を設定します。', description: '対応モデルの高度な思考 / 推論設定を行います。',
supportedProviders: '対応プロバイダー', supportedProviders: '対応プロバイダー',
modeTitle: 'Thinking モード', modeTitle: '思考モード',
modeAutoDesc: 'モデルのティアに応じて Thinking を自動設定します', modeAutoDesc: 'モデルのティアに応じて思考レベルを自動設定します',
modeOffDesc: '拡張 Thinking を無効化します', modeOffDesc: '高度な思考を無効化します',
modeManualDesc: '永続的な上書きレベルを設定するか、実行ごとに CLI フラグを使います', modeManualDesc: '永続的な上書きレベルを設定するか、実行ごとに CLI フラグを使います',
tierDefaults: 'ティア別デフォルト', tierDefaults: 'ティア別デフォルト',
tierDefaultsDesc: tierDefaultsDesc: '自動モード時に各モデルティアへ適用する既定の思考レベルです。',
'Auto モード時に各モデルティアへ適用するデフォルトの Thinking レベルです。',
persistentOverride: '永続オーバーライド', persistentOverride: '永続オーバーライド',
persistentOverrideDesc: 'すべてのセッションに適用されます。CLI フラグが優先されます。', persistentOverrideDesc: 'すべてのセッションに適用されます。CLI フラグが優先されます。',
enterCustomBudget: 'カスタム予算を入力', enterCustomBudget: 'カスタム予算を入力',
@@ -4293,15 +4299,15 @@ const resources = {
'特定のプロバイダーに対してティア別デフォルトを上書きします。必要に応じてカスタムのプロバイダーキーを追加してください。', '特定のプロバイダーに対してティア別デフォルトを上書きします。必要に応じてカスタムのプロバイダーキーを追加してください。',
addProviderPlaceholder: 'プロバイダーキーを追加(例: qwen)', addProviderPlaceholder: 'プロバイダーキーを追加(例: qwen)',
showWarnings: '警告を表示', showWarnings: '警告を表示',
showWarningsDesc: 'Thinking 値が制限または調整された場合に警告を表示します', showWarningsDesc: '思考値が制限または調整された場合に警告を表示します',
cliEnvOverride: 'CLI / Env オーバーライド', cliEnvOverride: 'CLI / 環境変数の上書き',
supportLine1Prefix: 'Thinking budget:', supportLine1Prefix: '思考予算:',
supportLine1Suffix: '(token ベース)', supportLine1Suffix: '(トークンベース',
supportLine2Prefix: 'Reasoning effort:', supportLine2Prefix: '推論強度:',
supportLine2SuffixPrefix: '(suffix または ', supportLine2SuffixPrefix: '(サフィックス、または ',
supportLine2SuffixPostfix: ': medium/high/xhigh)', supportLine2SuffixPostfix: ': medium/high/xhigh)',
supportLine3Prefix: 'Codex の suffix は effort を固定します(例: ', supportLine3Prefix: 'Codex のサフィックスは推論強度を固定します(例: ',
supportLine3Suffix: ')。suffix なしのモデルは Thinking mode を使用します。', supportLine3Suffix: ')。サフィックスなしのモデルは思考モードを使います。',
}, },
analytics: { analytics: {
title: '分析', title: '分析',
@@ -4322,15 +4328,15 @@ const resources = {
tokensSubtitle: '{{value}} トークン', tokensSubtitle: '{{value}} トークン',
}, },
apiProfiles: { apiProfiles: {
title: 'APIプロファイル', title: 'API プロファイル',
new: '新規', new: '新規',
searchPlaceholder: 'プロファイルを検索...', searchPlaceholder: 'プロファイルを検索...',
loadingProfiles: 'プロファイルを読み込み中...', loadingProfiles: 'プロファイルを読み込み中...',
failedLoadTitle: 'プロファイルを読み込めませんでした', failedLoadTitle: 'プロファイルを読み込めませんでした',
failedLoadDesc: 'APIプロファイルを取得できませんでした。もう一度お試しください。', failedLoadDesc: 'API プロファイルを取得できませんでした。もう一度お試しください。',
retry: '再試行', retry: '再試行',
noProfilesYet: 'APIプロファイルがまだありません', noProfilesYet: 'API プロファイルがまだありません',
noProfilesDesc: '最初のプロファイルを作成して、カスタムAPIエンドポイントに接続します', noProfilesDesc: '最初のプロファイルを作成して、カスタム API エンドポイントに接続します',
createProfile: 'プロファイルを作成', createProfile: 'プロファイルを作成',
noProfileMatch: '"{{query}}" に一致するプロファイルはありません', noProfileMatch: '"{{query}}" に一致するプロファイルはありません',
profileCount: '{{count}} 件のプロファイル', profileCount: '{{count}} 件のプロファイル',
@@ -4347,14 +4353,14 @@ const resources = {
}, },
accountsPage: { accountsPage: {
title: 'アカウント', title: 'アカウント',
managePrefix: '', managePrefix: '一つの画面で',
manageSuffix: 'のアカウント管理とプール導線を一元化。', manageSuffix: 'のアカウント管理とプール導線をまとめて扱えます。',
mobileManageSuffix: 'の継続性設定を管理。', mobileManageSuffix: 'の継続性設定をまとめて管理できます。',
primaryActions: '主要アクション', primaryActions: '主要アクション',
createAccount: 'アカウントを作成', createAccount: 'アカウントを作成',
authClaudeInPool: 'PoolClaudeを認証', authClaudeInPool: 'PoolClaude を認証',
openClaudePoolSettings: 'Claude Pool設定を開く', openClaudePoolSettings: 'Claude Pool設定を開く',
openCliProxyClaudePool: 'CLIProxy Claude Poolを開く', openCliProxyClaudePool: 'CLIProxy Claude Pool を開く',
migrationFollowup: '移行フォローアップ', migrationFollowup: '移行フォローアップ',
legacyContextPending: '{{count}} 件のアカウントで初回モード確認がまだ必要です。', legacyContextPending: '{{count}} 件のアカウントで初回モード確認がまだ必要です。',
legacyContextPending_other: '{{count}} 件のアカウントで初回モード確認がまだ必要です。', legacyContextPending_other: '{{count}} 件のアカウントで初回モード確認がまだ必要です。',
@@ -4362,7 +4368,7 @@ const resources = {
legacyContinuityPending_other: legacyContinuityPending_other:
'{{count}} 件の共有アカウントが標準のレガシー継続深度のままです。', '{{count}} 件の共有アカウントが標準のレガシー継続深度のままです。',
confirmingLegacy: 'レガシーポリシーを確認中...', confirmingLegacy: 'レガシーポリシーを確認中...',
confirmLegacy: 'レガシーポリシーを確認 ({{count}})', confirmLegacy: 'レガシーポリシーを確認{{count}}',
noLegacyFollowup: '保留中のレガシーフォローアップはありません。', noLegacyFollowup: '保留中のレガシーフォローアップはありません。',
continuityGuide: '継続性ガイド', continuityGuide: '継続性ガイド',
expandWhenNeeded: '必要なときだけ展開。', expandWhenNeeded: '必要なときだけ展開。',
@@ -4370,19 +4376,20 @@ const resources = {
sharedStandardDesc: sharedStandardDesc:
'プロジェクトワークスペースの同期のみ。ほとんどのチームに最適な既定値です。', 'プロジェクトワークスペースの同期のみ。ほとんどのチームに最適な既定値です。',
sharedDeeper: '共有拡張', sharedDeeper: '共有拡張',
sharedDeeperPrefix: '追加:', sharedDeeperPrefix: '追加',
isolated: '分離', isolated: '分離',
isolatedDesc: 'リンクなし。厳密な分離に最適です。', isolatedDesc: 'リンクなし。厳密な分離に最適です。',
quickCommands: 'クイックコマンド', quickCommands: 'クイックコマンド',
quickCommandsDesc: 'コピーしてターミナルで実行します。', quickCommandsDesc: 'コピーしてターミナルで実行します。',
workspaceBadge: 'ccs auth ワークスペース', workspaceBadge: 'ccs auth ワークスペース',
historySyncBadge: '履歴同期コントロール', historySyncBadge: '履歴同期設定',
authAccounts: '認証アカウント', authAccounts: '認証アカウント',
tableScopePrefix: '', tableScopePrefix: 'この表では',
tableScopeMiddle: 'のアカウントのみを表示します。モード/グループ/深度の変更は', tableScopeMiddle: 'のアカウントのみを表示します。モード/グループ/継続性の変更は',
tableScopeSuffix: 'を使ってください。', tableScopeSuffix: 'を使ってください。',
accountMatrix: 'アカウントマトリクス', accountMatrix: 'アカウント一覧',
sharedTotalDesc: '共有合計: {{count}}。操作にはSync設定とレガシー確認が含まれます。', sharedTotalDesc:
'共有アカウント合計: {{count}}。ここから同期設定とレガシー確認を行えます。',
loadingAccounts: 'アカウントを読み込み中...', loadingAccounts: 'アカウントを読み込み中...',
}, },
health: { health: {
@@ -4444,7 +4451,7 @@ const resources = {
viaProvider: '{{provider}} 経由', viaProvider: '{{provider}} 経由',
emptyTitle: 'CCS プロファイルマネージャー', emptyTitle: 'CCS プロファイルマネージャー',
emptyDesc: emptyDesc:
'CLIProxyプロバイダー向けのOAuth認証、アカウント設定、モデル選択を管理します。CCSが各AIバックエンドへのリクエストをどうルーティングするかを設定できます。', 'CLIProxy プロバイダー向けの OAuth 認証、アカウント設定、モデル選択を管理します。CCS が各 AI バックエンドへのリクエストをどうルーティングするかを設定できます。',
emptyControlPanelPrefix: 'ライブ利用統計とリアルタイム監視は', emptyControlPanelPrefix: 'ライブ利用統計とリアルタイム監視は',
controlPanel: 'コントロールパネルで確認できます', controlPanel: 'コントロールパネルで確認できます',
quickSetup: 'クイックセットアップ', quickSetup: 'クイックセットアップ',
@@ -4627,23 +4634,23 @@ const resources = {
customModelsTitle: 'カスタムモデル', customModelsTitle: 'カスタムモデル',
modelName: '名前 / モデル', modelName: '名前 / モデル',
provider: 'プロバイダー', provider: 'プロバイダー',
baseUrl: 'Base URL', baseUrl: 'ベース URL',
noCustomModels: 'カスタムモデルはありません', noCustomModels: 'カスタムモデルはありません',
docsAlignedNotes: 'ドキュメント整合メモ', docsAlignedNotes: 'ドキュメント整合メモ',
factoryDocs: 'Factory Docs', factoryDocs: 'Factory Docs',
providerFactCheckDocs: 'プロバイダー検証ドキュメント', providerFactCheckDocs: 'プロバイダー検証ドキュメント',
providerValues: 'プロバイダー値: {{value}}', providerValues: 'プロバイダー値: {{value}}',
settingsHierarchy: '設定階層: {{value}}', settingsHierarchy: '設定階層: {{value}}',
settingsTitle: 'Droid BYOK設定', settingsTitle: 'Droid BYOK 設定',
fixJsonBeforeQuickSettings: 'クイック設定を使う前にJSON構文を修正してください。', fixJsonBeforeQuickSettings: 'クイック設定を使う前に JSON 構文を修正してください。',
fixJsonBeforeReasoning: 'BYOK推論設定を更新する前にJSON構文を修正してください。', fixJsonBeforeReasoning: 'BYOK 推論設定を更新する前に JSON 構文を修正してください。',
unableUpdateReasoning: '選択したBYOKモデルの推論設定を更新できません。', unableUpdateReasoning: '選択した BYOK モデルの推論設定を更新できません。',
fixJsonBeforeBudget: 'thinking budgetを更新する前にJSON構文を修正してください。', fixJsonBeforeBudget: '思考予算を更新する前に JSON 構文を修正してください。',
anthropicOnlyBudget: 'thinking budget はAnthropicBYOKモデルでのみ利用できます。', anthropicOnlyBudget: '思考予算は AnthropicBYOK モデルでのみ利用できます。',
invalidJson: 'JSONが不正です: {{value}}', invalidJson: 'JSON が不正です: {{value}}',
saved: 'Droid設定を保存しました', saved: 'Droid 設定を保存しました',
changedExternally: 'Droid設定が外部で変更されました。更新して再試行してください。', changedExternally: 'Droid 設定が外部で変更されました。更新して再試行してください。',
failedSave: 'Droid設定の保存に失敗しました', failedSave: 'Droid 設定の保存に失敗しました',
}, },
sharedPage: { sharedPage: {
commands: 'コマンド', commands: 'コマンド',
+1 -1
View File
@@ -232,7 +232,7 @@ export function AccountsPage() {
{t('accountsPage.tableScopePrefix')} {t('accountsPage.tableScopePrefix')}
<code className="mx-1 rounded bg-muted px-1 py-0.5">ccs auth</code> <code className="mx-1 rounded bg-muted px-1 py-0.5">ccs auth</code>
{t('accountsPage.tableScopeMiddle')} {t('accountsPage.tableScopeMiddle')}
<code className="mx-1 rounded bg-muted px-1 py-0.5">Sync</code> <code className="mx-1 rounded bg-muted px-1 py-0.5">{t('accountsTable.sync')}</code>
{t('accountsPage.tableScopeSuffix')} {t('accountsPage.tableScopeSuffix')}
</p> </p>
</div> </div>
@@ -2,6 +2,7 @@ import { beforeEach, describe, expect, it, vi } from 'vitest';
import { render, screen, userEvent, waitFor } from '@tests/setup/test-utils'; import { render, screen, userEvent, waitFor } from '@tests/setup/test-utils';
import i18n from '@/lib/i18n'; import i18n from '@/lib/i18n';
import { LanguageSwitcher } from '@/components/layout/language-switcher'; import { LanguageSwitcher } from '@/components/layout/language-switcher';
import { HistorySyncLearningMap } from '@/components/account/history-sync-learning-map';
import { TabNavigation } from '@/pages/settings/components/tab-navigation'; import { TabNavigation } from '@/pages/settings/components/tab-navigation';
import { import {
getInitialLocale, getInitialLocale,
@@ -126,6 +127,44 @@ describe('Dashboard i18n', () => {
expect(screen.getByText('认证')).toBeInTheDocument(); expect(screen.getByText('认证')).toBeInTheDocument();
}); });
it('shows Japanese labels on translated settings tabs', async () => {
await i18n.changeLanguage('ja');
render(<TabNavigation activeTab="websearch" onTabChange={() => {}} />);
expect(screen.getByText('Web検索')).toBeInTheDocument();
expect(screen.getByText('環境変数')).toBeInTheDocument();
expect(screen.getByText('思考')).toBeInTheDocument();
});
it('renders Japanese history sync guidance without fallback English copy', async () => {
await i18n.changeLanguage('ja');
render(
<HistorySyncLearningMap
isolatedCount={1}
sharedStandardCount={2}
deeperSharedCount={3}
sharedGroups={['default']}
legacyTargetCount={2}
cliproxyCount={1}
/>
);
expect(screen.getByText('履歴同期の仕組み')).toBeInTheDocument();
expect(
screen.getByText('1 件の CLIProxy Claude Pool アカウントは、CLIProxy ページで管理します。')
).toBeInTheDocument();
await userEvent.click(
screen.getByRole('button', { name: '詳細を表示: グループ、切り替え、レガシーポリシー' })
);
expect(
screen.getByText('2 件のレガシーアカウントで明示的な確認がまだ必要です。')
).toBeInTheDocument();
});
it.each(SUPPORTED_LOCALES.filter((locale) => locale !== 'en'))( it.each(SUPPORTED_LOCALES.filter((locale) => locale !== 'en'))(
'keeps %s translation keys in parity with en and preserves placeholders', 'keeps %s translation keys in parity with en and preserves placeholders',
(locale) => { (locale) => {