Files
EJClaw/apps/dashboard/src/i18n.ts

981 lines
22 KiB
TypeScript

export const LOCALES = ['ko', 'en', 'zh', 'ja'] as const;
export type Locale = (typeof LOCALES)[number];
export interface Messages {
app: {
loading: string;
};
actions: {
close: string;
refresh: string;
refreshing: string;
retry: string;
};
nav: {
aria: string;
drawerAria: string;
drawerNavAria: string;
menuOpen: string;
menuClose: string;
operations: string;
updated: string;
health: string;
inbox: string;
usage: string;
rooms: string;
scheduled: string;
};
language: {
label: string;
};
error: {
api: string;
};
control: {
aria: string;
queue: string;
activeRooms: string;
pendingRooms: string;
};
metrics: {
agents: string;
rooms: string;
ciWatchers: string;
};
panels: {
health: string;
heartbeat: string;
healthSignals: string;
inbox: string;
inboxQueue: string;
usage: string;
usageWindow: string;
rooms: string;
queue: string;
scheduled: string;
promptPreviews: string;
};
service: {
empty: string;
heartbeat: string;
service: string;
rooms: string;
updated: string;
};
health: {
system: string;
signals: string;
services: string;
fresh: string;
stale: string;
queue: string;
ciFailures: string;
affectedServices: string;
levels: {
ok: string;
stale: string;
down: string;
};
};
inbox: {
empty: string;
cardsAria: string;
summary: string;
total: string;
filters: string;
all: string;
noSummary: string;
occurred: string;
source: string;
target: string;
openTask: string;
openRoom: string;
kinds: {
'pending-room': string;
'reviewer-request': string;
approval: string;
'arbiter-request': string;
'ci-failure': string;
mention: string;
};
severity: {
info: string;
warn: string;
error: string;
};
};
rooms: {
empty: string;
cardsAria: string;
room: string;
service: string;
agent: string;
status: string;
queue: string;
elapsed: string;
details: string;
};
usage: {
empty: string;
current: string;
tightest: string;
watch: string;
remaining: string;
speed: string;
inUse: string;
reset: string;
noReset: string;
limitBasis: {
h5: string;
d7: string;
};
usage: string;
groupPrimary: string;
groupCodex: string;
risk: {
ok: string;
warn: string;
critical: string;
};
speedLabel: {
ok: string;
warn: string;
critical: string;
};
};
tasks: {
empty: string;
cardsAria: string;
groups: {
watchers: string;
scheduled: string;
paused: string;
completed: string;
};
count: string;
groupEmpty: string;
task: string;
status: string;
schedule: string;
next: string;
last: string;
context: string;
ciWatch: string;
emptyPrompt: string;
prompt: string;
until: string;
suspendedUntil: string;
lastResult: string;
result: string;
resultOk: string;
resultFail: string;
noResult: string;
noTime: string;
now: string;
};
status: {
processing: string;
waiting: string;
inactive: string;
active: string;
paused: string;
completed: string;
};
units: {
second: string;
minute: string;
hour: string;
task: string;
messageShort: string;
chars: string;
};
}
export const languageNames: Record<Locale, string> = {
ko: '한국어',
en: 'English',
zh: '简体中文',
ja: '日本語',
};
export const localeTags: Record<Locale, string> = {
ko: 'ko-KR',
en: 'en-US',
zh: 'zh-CN',
ja: 'ja-JP',
};
export const messages = {
ko: {
app: {
loading: '대시보드 로딩 중',
},
actions: {
close: '닫기',
refresh: '새로고침',
refreshing: '새로고침 중',
retry: '다시 시도',
},
nav: {
aria: '대시보드 섹션',
drawerAria: '대시보드 메뉴',
drawerNavAria: '대시보드 메뉴 섹션',
menuOpen: '메뉴 열기',
menuClose: '메뉴 닫기',
operations: '운영',
updated: '갱신',
health: '상태',
inbox: '인입',
usage: '사용량',
rooms: '룸',
scheduled: '예약',
},
language: {
label: '언어',
},
error: {
api: 'API 오류',
},
control: {
aria: '컨트롤 플레인 요약',
queue: '작업 큐',
activeRooms: '처리 + 대기 룸',
pendingRooms: '메시지 대기 룸',
},
metrics: {
agents: '에이전트',
rooms: '룸',
ciWatchers: 'CI 감시',
},
panels: {
health: '상태',
heartbeat: '하트비트',
healthSignals: '운영 신호',
inbox: '인입',
inboxQueue: '대기 항목',
usage: '사용량',
usageWindow: '남음 / 속도',
rooms: '룸',
queue: '큐',
scheduled: '예약',
promptPreviews: '프롬프트 미리보기',
},
service: {
empty: '하트비트 없음. 서비스 로그 확인.',
heartbeat: '하트비트',
service: '서비스',
rooms: '룸',
updated: '갱신',
},
health: {
system: '시스템',
signals: '헬스 신호',
services: '서비스',
fresh: '정상',
stale: '지연',
queue: '큐',
ciFailures: 'CI 실패',
affectedServices: '이상 서비스',
levels: {
ok: '정상',
stale: '주의',
down: '중단',
},
},
inbox: {
empty: '인입 없음.',
cardsAria: '인입 항목',
summary: '인입 요약',
total: '전체',
filters: '인입 필터',
all: '전체',
noSummary: '요약 없음',
occurred: '발생',
source: '소스',
target: '대상',
openTask: '예약 보기',
openRoom: '룸 보기',
kinds: {
'pending-room': '대기 룸',
'reviewer-request': '리뷰 요청',
approval: '승인',
'arbiter-request': '중재 요청',
'ci-failure': 'CI 실패',
mention: '멘션',
},
severity: {
info: '정보',
warn: '주의',
error: '위험',
},
},
rooms: {
empty: '룸 없음.',
cardsAria: '룸 상태 카드',
room: '룸',
service: '서비스',
agent: '에이전트',
status: '상태',
queue: '큐',
elapsed: '경과',
details: '세부',
},
usage: {
empty: '사용량 스냅샷 없음. 수집기 확인.',
current: '사용중',
tightest: '가장 적음',
watch: '주의',
remaining: '남음',
speed: '속도',
inUse: '사용중',
reset: '리셋',
noReset: '리셋 없음',
limitBasis: {
h5: '5시간 기준',
d7: '7일 기준',
},
usage: '사용량',
groupPrimary: 'Claude / Kimi',
groupCodex: 'Codex',
risk: {
ok: '여유',
warn: '주의',
critical: '위험',
},
speedLabel: {
ok: '보통',
warn: '빠름',
critical: '너무 빠름',
},
},
tasks: {
empty: '예약 작업 없음.',
cardsAria: '예약 작업 카드',
groups: {
watchers: 'CI 감시',
scheduled: '예약',
paused: '일시정지',
completed: '완료',
},
count: '개',
groupEmpty: '해당 없음',
task: '작업',
status: '상태',
schedule: '스케줄',
next: '다음',
last: '최근',
context: '컨텍스트',
ciWatch: 'CI 감시',
emptyPrompt: '(빈 미리보기)',
prompt: '프롬프트',
until: '까지',
suspendedUntil: '정지 해제',
lastResult: '최근 결과',
result: '결과 없음',
resultOk: '정상',
resultFail: '실패',
noResult: '결과 없음',
noTime: '-',
now: '지금',
},
status: {
processing: '처리중',
waiting: '대기',
inactive: '휴면',
active: '활성',
paused: '일시정지',
completed: '완료',
},
units: {
second: '초',
minute: '분',
hour: '시간',
task: '작업',
messageShort: '메시지',
chars: '자',
},
},
en: {
app: {
loading: 'Loading dashboard',
},
actions: {
close: 'Close',
refresh: 'Refresh',
refreshing: 'Refreshing',
retry: 'Retry',
},
nav: {
aria: 'Dashboard sections',
drawerAria: 'Dashboard menu',
drawerNavAria: 'Dashboard menu sections',
menuOpen: 'Open menu',
menuClose: 'Close menu',
operations: 'Ops',
updated: 'Updated',
health: 'Health',
inbox: 'Inbox',
usage: 'Usage',
rooms: 'Rooms',
scheduled: 'Scheduled',
},
language: {
label: 'Language',
},
error: {
api: 'API error',
},
control: {
aria: 'Control plane summary',
queue: 'Work queue',
activeRooms: 'processing + waiting rooms',
pendingRooms: 'rooms with pending messages',
},
metrics: {
agents: 'agents',
rooms: 'rooms',
ciWatchers: 'CI watchers',
},
panels: {
health: 'Health',
heartbeat: 'Heartbeat',
healthSignals: 'Signals',
inbox: 'Inbox',
inboxQueue: 'Work intake',
usage: 'Usage',
usageWindow: 'Remaining / speed',
rooms: 'Rooms',
queue: 'Queue',
scheduled: 'Scheduled',
promptPreviews: 'Prompt previews',
},
service: {
empty: 'No heartbeat yet. Check service logs.',
heartbeat: 'heartbeat',
service: 'service',
rooms: 'rooms',
updated: 'updated',
},
health: {
system: 'System',
signals: 'Health signals',
services: 'Services',
fresh: 'Fresh',
stale: 'stale',
queue: 'Queue',
ciFailures: 'CI failures',
affectedServices: 'Affected services',
levels: {
ok: 'OK',
stale: 'Watch',
down: 'Down',
},
},
inbox: {
empty: 'No inbound work.',
cardsAria: 'Inbox items',
summary: 'Inbox summary',
total: 'Total',
filters: 'Inbox filters',
all: 'All',
noSummary: 'No summary',
occurred: 'Occurred',
source: 'Source',
target: 'Target',
openTask: 'Open scheduled',
openRoom: 'Open room',
kinds: {
'pending-room': 'Pending room',
'reviewer-request': 'Review request',
approval: 'Approval',
'arbiter-request': 'Arbiter request',
'ci-failure': 'CI failure',
mention: 'Mention',
},
severity: {
info: 'Info',
warn: 'Warn',
error: 'Risk',
},
},
rooms: {
empty: 'No rooms yet.',
cardsAria: 'Room status cards',
room: 'room',
service: 'service',
agent: 'agent',
status: 'status',
queue: 'queue',
elapsed: 'elapsed',
details: 'details',
},
usage: {
empty: 'No usage snapshot. Check collector.',
current: 'In use',
tightest: 'Lowest',
watch: 'Watch',
remaining: 'Left',
speed: 'Speed',
inUse: 'in use',
reset: 'reset',
noReset: 'no reset',
limitBasis: {
h5: '5h basis',
d7: '7d basis',
},
usage: 'usage',
groupPrimary: 'Claude / Kimi',
groupCodex: 'Codex',
risk: {
ok: 'Clear',
warn: 'Watch',
critical: 'Limit risk',
},
speedLabel: {
ok: 'Normal',
warn: 'Fast',
critical: 'Too fast',
},
},
tasks: {
empty: 'No scheduled work.',
cardsAria: 'Scheduled task cards',
groups: {
watchers: 'CI watch',
scheduled: 'Scheduled',
paused: 'Paused',
completed: 'Completed',
},
count: 'items',
groupEmpty: 'None',
task: 'task',
status: 'status',
schedule: 'schedule',
next: 'next',
last: 'last',
context: 'context',
ciWatch: 'CI Watch',
emptyPrompt: '(empty preview)',
prompt: 'prompt',
until: 'until',
suspendedUntil: 'resume',
lastResult: 'last result',
result: 'no result',
resultOk: 'ok',
resultFail: 'failed',
noResult: 'no result',
noTime: '-',
now: 'now',
},
status: {
processing: 'processing',
waiting: 'waiting',
inactive: 'inactive',
active: 'active',
paused: 'paused',
completed: 'completed',
},
units: {
second: 's',
minute: 'm',
hour: 'h',
task: 'task',
messageShort: 'msg',
chars: 'chars',
},
},
zh: {
app: {
loading: '正在加载仪表盘',
},
actions: {
close: '关闭',
refresh: '刷新',
refreshing: '刷新中',
retry: '重试',
},
nav: {
aria: '仪表盘分区',
drawerAria: '仪表盘菜单',
drawerNavAria: '仪表盘菜单分区',
menuOpen: '打开菜单',
menuClose: '关闭菜单',
operations: '运营',
updated: '更新',
health: '健康',
inbox: '收件',
usage: '用量',
rooms: '房间',
scheduled: '计划',
},
language: {
label: '语言',
},
error: {
api: 'API 错误',
},
control: {
aria: '控制平面摘要',
queue: '任务队列',
activeRooms: '处理中 + 等待房间',
pendingRooms: '有待处理消息的房间',
},
metrics: {
agents: '代理',
rooms: '房间',
ciWatchers: 'CI 监控',
},
panels: {
health: '健康',
heartbeat: '心跳',
healthSignals: '运行信号',
inbox: '收件',
inboxQueue: '待处理',
usage: '用量',
usageWindow: '剩余 / 速度',
rooms: '房间',
queue: '队列',
scheduled: '计划',
promptPreviews: '提示预览',
},
service: {
empty: '暂无心跳。检查服务日志。',
heartbeat: '心跳',
service: '服务',
rooms: '房间',
updated: '更新',
},
health: {
system: '系统',
signals: '健康信号',
services: '服务',
fresh: '正常',
stale: '延迟',
queue: '队列',
ciFailures: 'CI 失败',
affectedServices: '异常服务',
levels: {
ok: '正常',
stale: '关注',
down: '中断',
},
},
inbox: {
empty: '暂无收件。',
cardsAria: '收件项',
summary: '收件摘要',
total: '全部',
filters: '收件筛选',
all: '全部',
noSummary: '无摘要',
occurred: '发生',
source: '来源',
target: '目标',
openTask: '查看计划',
openRoom: '查看房间',
kinds: {
'pending-room': '待处理房间',
'reviewer-request': '评审请求',
approval: '审批',
'arbiter-request': '仲裁请求',
'ci-failure': 'CI 失败',
mention: '提及',
},
severity: {
info: '信息',
warn: '关注',
error: '风险',
},
},
rooms: {
empty: '暂无房间。',
cardsAria: '房间状态卡片',
room: '房间',
service: '服务',
agent: '代理',
status: '状态',
queue: '队列',
elapsed: '耗时',
details: '详情',
},
usage: {
empty: '暂无用量快照。检查采集器。',
current: '使用中',
tightest: '剩余最少',
watch: '关注',
remaining: '剩余',
speed: '速度',
inUse: '使用中',
reset: '重置',
noReset: '无重置',
limitBasis: {
h5: '按5小时',
d7: '按7天',
},
usage: '用量',
groupPrimary: 'Claude / Kimi',
groupCodex: 'Codex',
risk: {
ok: '充足',
warn: '关注',
critical: '接近上限',
},
speedLabel: {
ok: '正常',
warn: '较快',
critical: '过快',
},
},
tasks: {
empty: '暂无计划任务。',
cardsAria: '计划任务卡片',
groups: {
watchers: 'CI 监控',
scheduled: '计划',
paused: '暂停',
completed: '完成',
},
count: '项',
groupEmpty: '无',
task: '任务',
status: '状态',
schedule: '计划',
next: '下次',
last: '最近',
context: '上下文',
ciWatch: 'CI 监控',
emptyPrompt: '(空预览)',
prompt: '提示',
until: '直到',
suspendedUntil: '恢复',
lastResult: '最近结果',
result: '无结果',
resultOk: '正常',
resultFail: '失败',
noResult: '无结果',
noTime: '-',
now: '现在',
},
status: {
processing: '处理中',
waiting: '等待',
inactive: '空闲',
active: '活跃',
paused: '暂停',
completed: '完成',
},
units: {
second: '秒',
minute: '分',
hour: '小时',
task: '任务',
messageShort: '消息',
chars: '字',
},
},
ja: {
app: {
loading: 'ダッシュボードを読み込み中',
},
actions: {
close: '閉じる',
refresh: '更新',
refreshing: '更新中',
retry: '再試行',
},
nav: {
aria: 'ダッシュボードセクション',
drawerAria: 'ダッシュボードメニュー',
drawerNavAria: 'ダッシュボードメニューセクション',
menuOpen: 'メニューを開く',
menuClose: 'メニューを閉じる',
operations: '運用',
updated: '更新',
health: '状態',
inbox: '受信',
usage: '使用量',
rooms: 'ルーム',
scheduled: '予定',
},
language: {
label: '言語',
},
error: {
api: 'API エラー',
},
control: {
aria: 'コントロールプレーン概要',
queue: '作業キュー',
activeRooms: '処理中 + 待機ルーム',
pendingRooms: 'メッセージ待ちルーム',
},
metrics: {
agents: 'エージェント',
rooms: 'ルーム',
ciWatchers: 'CI監視',
},
panels: {
health: '状態',
heartbeat: 'ハートビート',
healthSignals: '運用シグナル',
inbox: '受信',
inboxQueue: '対応待ち',
usage: '使用量',
usageWindow: '残量 / 速度',
rooms: 'ルーム',
queue: 'キュー',
scheduled: '予定',
promptPreviews: 'プロンプトプレビュー',
},
service: {
empty: 'ハートビートなし。サービスログを確認。',
heartbeat: 'ハートビート',
service: 'サービス',
rooms: 'ルーム',
updated: '更新',
},
health: {
system: 'システム',
signals: '状態シグナル',
services: 'サービス',
fresh: '正常',
stale: '遅延',
queue: 'キュー',
ciFailures: 'CI失敗',
affectedServices: '異常サービス',
levels: {
ok: '正常',
stale: '注意',
down: '停止',
},
},
inbox: {
empty: '受信なし。',
cardsAria: '受信項目',
summary: '受信サマリー',
total: '全体',
filters: '受信フィルター',
all: '全体',
noSummary: '概要なし',
occurred: '発生',
source: 'ソース',
target: '対象',
openTask: '予定を見る',
openRoom: 'ルームを見る',
kinds: {
'pending-room': '待機ルーム',
'reviewer-request': 'レビュー依頼',
approval: '承認',
'arbiter-request': '仲裁依頼',
'ci-failure': 'CI失敗',
mention: 'メンション',
},
severity: {
info: '情報',
warn: '注意',
error: '危険',
},
},
rooms: {
empty: 'ルームなし。',
cardsAria: 'ルーム状態カード',
room: 'ルーム',
service: 'サービス',
agent: 'エージェント',
status: '状態',
queue: 'キュー',
elapsed: '経過',
details: '詳細',
},
usage: {
empty: '使用量スナップショットなし。収集器を確認。',
current: '使用中',
tightest: '残量最少',
watch: '注意',
remaining: '残量',
speed: '速度',
inUse: '使用中',
reset: 'リセット',
noReset: 'リセットなし',
limitBasis: {
h5: '5時間基準',
d7: '7日基準',
},
usage: '使用量',
groupPrimary: 'Claude / Kimi',
groupCodex: 'Codex',
risk: {
ok: '余裕',
warn: '注意',
critical: '上限注意',
},
speedLabel: {
ok: '通常',
warn: '速い',
critical: '速すぎ',
},
},
tasks: {
empty: '予定作業なし。',
cardsAria: '予定作業カード',
groups: {
watchers: 'CI監視',
scheduled: '予定',
paused: '一時停止',
completed: '完了',
},
count: '件',
groupEmpty: 'なし',
task: '作業',
status: '状態',
schedule: '予定',
next: '次回',
last: '直近',
context: 'コンテキスト',
ciWatch: 'CI監視',
emptyPrompt: '(空のプレビュー)',
prompt: 'プロンプト',
until: 'まで',
suspendedUntil: '再開',
lastResult: '直近結果',
result: '結果なし',
resultOk: '正常',
resultFail: '失敗',
noResult: '結果なし',
noTime: '-',
now: '今',
},
status: {
processing: '処理中',
waiting: '待機',
inactive: '休止',
active: '有効',
paused: '一時停止',
completed: '完了',
},
units: {
second: '秒',
minute: '分',
hour: '時間',
task: '作業',
messageShort: 'メッセージ',
chars: '字',
},
},
} satisfies Record<Locale, Messages>;
export function isLocale(value: string | null | undefined): value is Locale {
return LOCALES.includes(value as Locale);
}
export function matchLocale(value: string | null | undefined): Locale | null {
if (!value) return null;
const normalized = value.toLowerCase();
if (normalized.startsWith('ko')) return 'ko';
if (normalized.startsWith('en')) return 'en';
if (normalized.startsWith('zh')) return 'zh';
if (normalized.startsWith('ja')) return 'ja';
return null;
}