use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
pub enum Language {
#[default]
#[serde(rename = "en")]
En,
#[serde(rename = "ja")]
Ja,
}
macro_rules! i18n_messages {
( $( $name:ident { en: $en:expr, ja: $ja:expr } ),* $(,)? ) => {
impl Language {
$(
pub fn $name(self) -> &'static str {
match self {
Self::En => $en,
Self::Ja => $ja,
}
}
)*
}
};
}
impl Language {
pub fn toggle(self) -> Self {
match self {
Self::En => Self::Ja,
Self::Ja => Self::En,
}
}
pub fn health_scroll_close_quit(self) -> (&'static str, &'static str, &'static str) {
match self {
Self::En => (": scroll ", ": close ", ": quit"),
Self::Ja => (": スクロール ", ": 閉じる ", ": 終了"),
}
}
}
i18n_messages! {
label { en: "EN", ja: "JA" },
status { en: "Status", ja: "ステータス" },
commits { en: "Commits", ja: "コミット" },
branches { en: "Branches", ja: "ブランチ" },
files { en: "Files", ja: "ファイル" },
stash { en: "Stash", ja: "スタッシュ" },
main_summary { en: " Main: Summary ", ja: " メイン: サマリー " },
main_diff { en: " Main: Diff ", ja: " メイン: 差分 " },
main_branch_info { en: " Main: Branch Info ", ja: " メイン: ブランチ情報 " },
main_file_diff { en: " Main: File Diff ", ja: " メイン: ファイル差分 " },
main_stash_detail { en: " Main: Stash Detail ", ja: " メイン: スタッシュ詳細 " },
repo_label { en: "repo: ", ja: "リポジトリ: " },
on_label { en: "on: ", ja: "ブランチ: " },
author_stats { en: " Author Statistics ", ja: " 著者統計 " },
file_heatmap { en: " File Heatmap ", ja: " ファイルヒートマップ " },
activity_timeline { en: " Activity Timeline ", ja: " 活動タイムライン " },
code_ownership { en: " Code Ownership ", ja: " コード所有権 " },
impact_scores { en: " Impact Scores ", ja: " インパクトスコア " },
branch_topology { en: " Branch Topology ", ja: " ブランチトポロジー " },
topology { en: " Topology ", ja: " トポロジー " },
project_health { en: " Project Health Dashboard ", ja: " プロジェクト健全性 " },
change_coupling { en: " Change Coupling ", ja: " 変更結合度 " },
quality_scores { en: " Quality Scores ", ja: " 品質スコア " },
quick_actions { en: " Quick Actions ", ja: " クイックアクション " },
select_branch { en: " Select Branch ", ja: " ブランチ選択 " },
git_status { en: " Git Status ", ja: " Git ステータス " },
quick_commit { en: " Quick Commit ", ja: " クイックコミット " },
event_detail { en: " Event Detail ", ja: " イベント詳細 " },
timeline { en: " Timeline ", ja: " タイムライン " },
file_history { en: " File History ", ja: " ファイル履歴 " },
blame { en: " Blame ", ja: " Blame " },
stash_overlay { en: " Stash ", ja: " スタッシュ " },
related { en: " Related ", ja: " 関連 " },
save_filter_preset { en: " Save Filter Preset ", ja: " フィルタプリセット保存 " },
help { en: " Help ", ja: " ヘルプ " },
help_adaptive { en: " Help (Adaptive) ", ja: " ヘルプ " },
help_navigation { en: "Navigation", ja: "ナビゲーション" },
help_actions { en: "Actions", ja: "アクション" },
help_dashboard { en: "Dashboard", ja: "ダッシュボード" },
help_other { en: "Other", ja: "その他" },
help_move { en: "move", ja: "移動" },
help_move_down { en: "Move down", ja: "下へ移動" },
help_move_up { en: "Move up", ja: "上へ移動" },
help_go_top { en: "Go to top", ja: "先頭へ" },
help_go_bottom { en: "Go to bottom", ja: "末尾へ" },
help_page_down { en: "Page down", ja: "ページ下" },
help_page_up { en: "Page up", ja: "ページ上" },
help_next_branch { en: "Next branch", ja: "次のブランチ" },
help_prev_branch { en: "Prev branch", ja: "前のブランチ" },
help_show_detail { en: "Show detail", ja: "詳細表示" },
help_filter { en: "Filter", ja: "フィルタ" },
help_branch_select { en: "Branch select", ja: "ブランチ選択" },
help_status_view { en: "Status view", ja: "ステータス表示" },
help_stash_list { en: "Stash list", ja: "スタッシュ一覧" },
help_stash_save { en: "Stash save", ja: "スタッシュ保存" },
help_switch_panel { en: "Switch panel", ja: "パネル切替" },
help_toggle_focus { en: "Toggle focus", ja: "フォーカス切替" },
help_focus_side_main { en: "Focus side/main", ja: "サイド/メイン" },
help_fetch_remote { en: "Fetch remote", ja: "リモートフェッチ" },
help_cycle_view { en: "Cycle view mode", ja: "表示モード切替" },
help_toggle_summary { en: "Toggle summary line", ja: "サマリー行切替" },
help_branch_topology { en: "Branch topology", ja: "ブランチトポロジー" },
help_toggle_help { en: "Toggle help", ja: "ヘルプ切替" },
help_quit { en: "Quit", ja: "終了" },
help_top_bottom { en: "top/btm", ja: "先頭/末尾" },
help_detail { en: "detail", ja: "詳細" },
help_branch_status { en: "branch/status", ja: "ブランチ/ステータス" },
help_view_summary { en: "view/summary", ja: "表示/サマリー" },
help_help_quit { en: "help/quit", ja: "ヘルプ/終了" },
help_up_down { en: "up/down", ja: "上/下" },
help_top_bottom_full { en: "top/bottom", ja: "先頭/末尾" },
help_page_dn_up { en: "page dn/up", ja: "ページ上下" },
help_next_prev_branch { en: "next/prev branch", ja: "次/前ブランチ" },
help_branch { en: "branch", ja: "ブランチ" },
help_status { en: "status", ja: "ステータス" },
help_stash_save_short { en: "stash/save", ja: "スタッシュ/保存" },
help_fetch { en: "fetch", ja: "フェッチ" },
help_topology { en: "topology", ja: "トポロジー" },
footer_health { en: "Health", ja: "健全性" },
footer_authors { en: "Authors", ja: "著者" },
footer_heatmap { en: "Heatmap", ja: "ヒートマップ" },
footer_detail { en: "Detail", ja: "詳細" },
footer_copy_hash { en: "Copy hash", ja: "ハッシュコピー" },
footer_filter { en: "Filter", ja: "フィルタ" },
footer_switch { en: "Switch", ja: "切替" },
footer_new { en: "New", ja: "新規" },
footer_delete { en: "Delete", ja: "削除" },
footer_diff { en: "Diff", ja: "差分" },
footer_stage_all { en: "Stage all", ja: "全ステージ" },
footer_commit { en: "Commit", ja: "コミット" },
footer_apply { en: "Apply", ja: "適用" },
footer_drop { en: "Drop", ja: "破棄" },
footer_panel { en: "panel", ja: "パネル" },
footer_focus { en: "focus", ja: "フォーカス" },
footer_actions { en: "actions", ja: "アクション" },
footer_help { en: "help", ja: "ヘルプ" },
footer_quit { en: "quit", ja: "終了" },
footer_lang { en: "lang", ja: "言語" },
footer_watch { en: "Watch", ja: "監視" },
footer_pr { en: "PR", ja: "PR" },
footer_review { en: "Review", ja: "レビュー" },
footer_quick_action { en: "Quick Action", ja: "クイックアクション" },
quick_risk_summary { en: "Risk Summary", ja: "リスクサマリー" },
quick_review_pack { en: "Review Pack", ja: "レビューパック" },
quick_next_actions { en: "Next Actions", ja: "次のアクション" },
quick_verify { en: "Verify Patch Risk", ja: "パッチリスク検証" },
quick_timeline { en: "Timeline", ja: "タイムライン" },
quick_ownership { en: "Ownership", ja: "オーナーシップ" },
quick_impact_score { en: "Impact Score", ja: "インパクトスコア" },
quick_change_coupling { en: "Change Coupling", ja: "チェンジカップリング" },
quick_quality_score { en: "Quality Score", ja: "品質スコア" },
quick_author_stats { en: "Author Stats", ja: "著者統計" },
quick_heatmap { en: "File Heatmap", ja: "ファイルヒートマップ" },
health_overall_score { en: "Overall Score: ", ja: "総合スコア: " },
health_score_breakdown { en: "Score Breakdown:", ja: "スコア内訳:" },
health_quality { en: "Quality", ja: "品質" },
health_test { en: "Test Health", ja: "テスト健全性" },
health_bus_factor { en: "Bus Factor", ja: "バスファクター" },
health_tech_debt { en: "Tech Debt", ja: "技術的負債" },
health_code_churn { en: "Code Churn", ja: "コード変動" },
health_commit_cadence { en: "Commit Cadence", ja: "コミット頻度" },
health_alerts { en: "Alerts:", ja: "アラート:" },
health_commits { en: "Commits: ", ja: "コミット: " },
health_authors { en: "Authors: ", ja: "著者: " },
health_period { en: "Period: ", ja: "期間: " },
health_confidence { en: "Confidence: ", ja: "信頼度: " },
health_days { en: " days", ja: " 日" },
health_score_label { en: "Score: ", ja: "スコア: " },
confidence_high { en: "High", ja: "高" },
confidence_medium { en: "Medium", ja: "中" },
confidence_low { en: "Low", ja: "低" },
alert_low_commit_quality { en: "Low commit quality", ja: "コミット品質が低い" },
alert_low_test_coverage { en: "Low test coverage in commits", ja: "テストカバレッジが低い" },
alert_high_bus_factor_risk { en: "High bus factor risk", ja: "バスファクターリスクが高い" },
alert_moderate_bus_factor_risk { en: "Moderate bus factor risk", ja: "バスファクターリスクが中程度" },
alert_high_tech_debt { en: "High technical debt indicated", ja: "技術的負債が高い" },
alert_high_code_churn { en: "High code churn detected", ja: "コード変動が激しい" },
quick_handoff_claude { en: "Handoff (Claude)", ja: "ハンドオフ (Claude)" },
quick_handoff_codex { en: "Handoff (Codex)", ja: "ハンドオフ (Codex)" },
quick_handoff_copilot { en: "Handoff (Copilot)", ja: "ハンドオフ (Copilot)" },
status_fetching { en: "Fetching...", ja: "フェッチ中..." },
status_fetched { en: "Fetched", ja: "フェッチ完了" },
status_fetch_failed { en: "Fetch failed", ja: "フェッチ失敗" },
status_fetch_thread_crashed { en: "Fetch thread crashed", ja: "フェッチスレッドが異常終了" },
status_stashed { en: "Stashed changes", ja: "変更をスタッシュしました" },
status_stash_failed { en: "Stash failed", ja: "スタッシュ失敗" },
status_copied { en: "Copied", ja: "コピー済み" },
status_copy_failed { en: "Failed to copy to clipboard", ja: "クリップボードへのコピーに失敗" },
status_clipboard_unavailable { en: "Clipboard not available", ja: "クリップボードが利用できません" },
status_quick_action_failed { en: "Quick action failed", ja: "クイックアクション失敗" },
status_switched_to { en: "Switched to", ja: "切り替え完了" },
status_checkout_failed { en: "Checkout failed", ja: "チェックアウト失敗" },
status_deleted_branch { en: "Deleted branch", ja: "ブランチ削除完了" },
status_delete_failed { en: "Delete failed", ja: "削除失敗" },
status_created_branch { en: "Created branch", ja: "ブランチ作成完了" },
status_create_failed { en: "Create failed", ja: "作成失敗" },
status_all_staged { en: "All files staged", ja: "全ファイルをステージしました" },
status_all_unstaged { en: "All files unstaged", ja: "全ファイルをアンステージしました" },
status_no_staged_files { en: "No staged files", ja: "ステージされたファイルがありません" },
status_pulling { en: "Pulling...", ja: "プル中..." },
status_pulled { en: "Pulled successfully", ja: "プル完了" },
status_pull_failed { en: "Pull failed", ja: "プル失敗" },
status_pushed { en: "Pushed successfully", ja: "プッシュ完了" },
status_push_failed { en: "Push failed", ja: "プッシュ失敗" },
status_committed { en: "Committed", ja: "コミット完了" },
status_commit_failed { en: "Commit failed", ja: "コミット失敗" },
status_compare_failed { en: "Compare failed", ja: "比較失敗" },
status_applied_stash { en: "Applied", ja: "適用完了" },
status_apply_failed { en: "Apply failed", ja: "適用失敗" },
status_popped_stash { en: "Popped", ja: "ポップ完了" },
status_pop_failed { en: "Pop failed", ja: "ポップ失敗" },
status_dropped_stash { en: "Dropped", ja: "破棄完了" },
status_drop_failed { en: "Drop failed", ja: "破棄失敗" },
status_error { en: "Error", ja: "エラー" },
error_not_found { en: "File or path not found", ja: "ファイルまたはパスが見つかりません" },
error_permission_denied { en: "Permission denied", ja: "アクセス権限がありません" },
error_connection_refused { en: "Could not connect to remote", ja: "リモートに接続できません" },
error_connection_timeout { en: "Connection timed out", ja: "接続がタイムアウトしました" },
error_auth_failed { en: "Authentication failed - check your credentials", ja: "認証に失敗しました - 認証情報を確認してください" },
error_merge_conflict { en: "Merge conflict - resolve conflicts first", ja: "マージコンフリクトがあります - 先にコンフリクトを解消してください" },
error_dirty_worktree { en: "Uncommitted changes exist - commit or stash first", ja: "未コミットの変更があります - 先にコミットまたはスタッシュしてください" },
error_branch_not_found { en: "Branch not found", ja: "ブランチが見つかりません" },
error_branch_already_exists { en: "Branch already exists", ja: "ブランチはすでに存在します" },
error_not_a_repo { en: "Not a git repository", ja: "Gitリポジトリではありません" },
cli_analysis_cache_cleared { en: "Analysis cache cleared", ja: "分析キャッシュを削除しました" },
cli_metrics_reset { en: "Metrics reset", ja: "メトリクスをリセットしました" },
cli_help_title { en: "gitstack - Git history viewer with insights", ja: "gitstack - インサイト付きGit履歴ビューア" },
cli_help_usage { en: "USAGE:", ja: "使い方:" },
cli_help_analysis_options { en: "ANALYSIS OPTIONS:", ja: "分析オプション:" },
cli_help_format_options { en: "FORMAT OPTIONS:", ja: "フォーマットオプション:" },
cli_help_tui_options { en: "TUI OPTIONS (when no analysis option is used):", ja: "TUIオプション(分析オプション未指定時):" },
cli_help_general_options { en: "GENERAL OPTIONS:", ja: "一般オプション:" },
cli_help_no_options { en: "Without options, gitstack starts in interactive TUI mode.", ja: "オプションなしで実行すると対話的TUIモードで起動します。" },
cli_help_examples { en: "EXAMPLES:", ja: "使用例:" },
event_commit { en: "Commit", ja: "コミット" },
event_merge { en: "Merge", ja: "マージ" },
event_branch_switch { en: "Branch Switch", ja: "ブランチ切替" },
detail_type { en: "Type: ", ja: "種類: " },
detail_hash { en: "Hash: ", ja: "ハッシュ: " },
detail_message { en: "Message: ", ja: "メッセージ: " },
detail_author { en: "Author: ", ja: "著者: " },
detail_time { en: "Time: ", ja: "時刻: " },
loading_file_changes { en: " Loading file changes...", ja: " ファイル変更を読み込み中..." },
detail_footer { en: " j/k: navigate P: patch F: history B: blame Esc: close", ja: " j/k: 移動 P: パッチ F: 履歴 B: blame Esc: 閉じる" },
no_changes { en: " No changes", ja: " 変更なし" },
commit_message_label { en: " Message: ", ja: " メッセージ: " },
commit_suggestions { en: " ─── Suggestions ───", ja: " ─── 候補 ───" },
commit_footer_with_suggestions { en: "[1-3] Select [Enter] Commit [Esc] Cancel", ja: "[1-3] 選択 [Enter] コミット [Esc] キャンセル" },
commit_footer { en: "[Enter] Commit [Esc] Cancel", ja: "[Enter] コミット [Esc] キャンセル" },
help_nav_short { en: "Nav", ja: "移動" },
help_act_short { en: "Act", ja: "操作" },
help_etc_short { en: "Etc", ja: "他" },
help_scroll_diff_h { en: "Scroll diff H", ja: "差分横スクロール" },
loading_topology { en: "Loading topology...", ja: "トポロジーを読み込み中..." },
loading_statistics { en: "Loading statistics...", ja: "統計を読み込み中..." },
loading_heatmap { en: "Loading heatmap...", ja: "ヒートマップを読み込み中..." },
loading_timeline { en: "Loading timeline...", ja: "タイムラインを読み込み中..." },
loading_history { en: "Loading history...", ja: "履歴を読み込み中..." },
loading_blame { en: "Loading blame...", ja: "Blameを読み込み中..." },
loading_ownership { en: "Loading ownership...", ja: "オーナーシップを読み込み中..." },
loading_impact_scores { en: "Loading impact scores...", ja: "インパクトスコアを読み込み中..." },
loading_change_coupling { en: "Loading change coupling analysis...", ja: "変更結合度を分析中..." },
loading_quality_scores { en: "Loading quality scores...", ja: "品質スコアを読み込み中..." },
loading_health { en: "Loading health data...", ja: "ヘルスデータを読み込み中..." },
loading_diff { en: "Loading diff...", ja: "差分を読み込み中..." },
header_author { en: "Author", ja: "著者" },
header_commits { en: "Commits", ja: "コミット" },
header_plus_lines { en: "+Lines", ja: "+行数" },
header_minus_lines { en: "-Lines", ja: "-行数" },
header_file { en: "File", ja: "ファイル" },
header_changes { en: "Changes", ja: "変更数" },
header_heat { en: "Heat", ja: "温度" },
header_hash { en: "Hash", ja: "ハッシュ" },
header_date { en: "Date", ja: "日付" },
header_message { en: "Message", ja: "メッセージ" },
header_msg_short { en: "Msg", ja: "メッセージ" },
header_score { en: "Score", ja: "スコア" },
header_score_short { en: "Scr", ja: "Scr" },
header_path { en: "Path", ja: "パス" },
header_owner { en: "Owner", ja: "所有者" },
header_coupling { en: "Coupling ", ja: "結合度 " },
header_coupled_with { en: "Coupled With", ja: "結合先" },
hint_move { en: ": move ", ja: ": 移動 " },
hint_filter { en: ": filter ", ja: ": フィルタ " },
hint_close { en: ": close", ja: ": 閉じる" },
hint_checkout { en: ": checkout ", ja: ": チェックアウト " },
hint_show_diff { en: ": show diff ", ja: ": 差分表示 " },
hint_scroll { en: ": scroll ", ja: ": スクロール " },
hint_show_commit { en: ": show commit ", ja: ": コミット表示 " },
hint_detail { en: ": detail ", ja: ": 詳細 " },
hint_export { en: ": export ", ja: ": エクスポート " },
hint_switch { en: ": switch ", ja: ": 切替 " },
hint_save { en: ": save ", ja: ": 保存 " },
hint_cancel { en: ": cancel", ja: ": キャンセル" },
hint_apply { en: ": apply ", ja: ": 適用 " },
hint_pop { en: ": pop ", ja: ": ポップ " },
hint_drop { en: ": drop ", ja: ": 破棄 " },
topology_issues { en: " issues", ja: " 件の問題" },
topology_healthy { en: " ✓ healthy", ja: " ✓ 健全" },
topology_branches_count { en: " branches)", ja: " ブランチ)" },
topology_stale { en: " stale", ja: " 停滞" },
topology_long { en: " long", ja: " 長期" },
topology_behind { en: " behind", ja: " 遅延" },
topology_div { en: " div", ja: " 乖離" },
stash_list_label { en: "Stash List ", ja: "スタッシュ一覧 " },
no_stashes { en: " No stashes", ja: " スタッシュなし" },
no_commits { en: " No commits", ja: " コミットなし" },
no_related_files { en: " No related files found in commit history", ja: " コミット履歴に関連ファイルが見つかりません" },
no_related_files_short { en: " No related files", ja: " 関連ファイルなし" },
files_changed_together { en: " Files frequently changed together:", ja: " 頻繁に一緒に変更されるファイル:" },
compare_ahead { en: "Ahead", ja: "先行" },
compare_behind { en: "Behind", ja: "遅延" },
save_filter_title { en: "Save current filter to preset", ja: "現在のフィルタをプリセットに保存" },
filter_label { en: "Filter: ", ja: "フィルタ: " },
select_slot { en: "Select slot (1-5):", ja: "スロットを選択 (1-5):" },
name_label { en: "Name: ", ja: "名前: " },
preset_label { en: "Preset", ja: "プリセット" },
overwrite { en: "(overwrite)", ja: "(上書き)" },
empty_slot { en: "(empty)", ja: "(空)" },
no_commit_selected { en: "No commit selected", ja: "コミットが選択されていません" },
repository_summary { en: "Repository Summary", ja: "リポジトリサマリー" },
dashboard_name { en: "Name: ", ja: "名前: " },
dashboard_branch { en: "Branch: ", ja: "ブランチ: " },
dashboard_commits { en: "Commits: ", ja: "コミット: " },
dashboard_branches { en: "Branches: ", ja: "ブランチ: " },
dashboard_stashes { en: "Stashes: ", ja: "スタッシュ: " },
file_changes { en: "File Changes", ja: "ファイル変更" },
staged_label { en: " Staged: ", ja: " ステージ済: " },
modified_label { en: " Modified: ", ja: " 変更: " },
deleted_label { en: " Deleted: ", ja: " 削除: " },
untracked_label { en: " Untracked: ", ja: " 未追跡: " },
project_health_title { en: "Project Health", ja: "プロジェクト健全性" },
recent_commits { en: "Recent Commits", ja: "最近のコミット" },
branch_info { en: "Branch Info", ja: "ブランチ情報" },
branch_name_label { en: "Name: ", ja: "名前: " },
current_branch_label { en: "(current branch)", ja: "(現在のブランチ)" },
gone_label { en: "[gone] remote tracking branch deleted", ja: "[gone] リモート追跡ブランチが削除されています" },
status_label { en: "Status: ", ja: "状態: " },
active_label { en: "Active: ", ja: "最終: " },
commits_label { en: "Commits:", ja: "コミット:" },
ahead_label { en: " ahead", ja: " 先行" },
behind_label { en: " behind", ja: " 遅延" },
health_warnings { en: "Health Warnings", ja: "ヘルス警告" },
no_branch_selected { en: "No branch selected", ja: "ブランチが選択されていません" },
branch_recommendations { en: "Branch Recommendations", ja: "ブランチ推奨アクション" },
file_detail_title { en: "File Detail", ja: "ファイル詳細" },
file_staged_new { en: "Staged (New)", ja: "ステージ済 (新規)" },
file_staged_modified { en: "Staged (Modified)", ja: "ステージ済 (変更)" },
file_staged_deleted { en: "Staged (Deleted)", ja: "ステージ済 (削除)" },
file_modified { en: "Modified", ja: "変更" },
file_deleted { en: "Deleted", ja: "削除" },
file_untracked { en: "Untracked", ja: "未追跡" },
path_label { en: "Path: ", ja: "パス: " },
diff_label { en: "Diff: ", ja: "差分: " },
no_diff_available { en: "(no diff available)", ja: "(差分なし)" },
no_file_selected { en: "No file selected", ja: "ファイルが選択されていません" },
no_stash_entries { en: "No stash entries", ja: "スタッシュエントリなし" },
stash_detail_title { en: "Stash Detail", ja: "スタッシュ詳細" },
stash_total { en: "Total: ", ja: "合計: " },
stash_current { en: "Current: ", ja: "選択: " },
stash_index { en: "Index: ", ja: "インデックス: " },
all_stashes { en: "All Stashes", ja: "全スタッシュ" },
stash_entries { en: " stash entries", ja: " 件のスタッシュ" },
files_changed { en: " files changed", ja: " ファイル変更" },
total_label { en: " Total: ", ja: " 合計: " },
peak_label { en: " Peak: ", ja: " ピーク: " },
watch_mode_on { en: "[WATCH]", ja: "[監視]" },
watch_mode_enabled { en: "Watch mode enabled", ja: "ウォッチモード有効" },
watch_mode_disabled { en: "Watch mode disabled", ja: "ウォッチモード無効" },
risk_label { en: "Risk", ja: "リスク" },
risk_low { en: "Low", ja: "低" },
risk_medium { en: "Med", ja: "中" },
risk_high { en: "High", ja: "高" },
intent_feature { en: "Feature", ja: "機能" },
intent_fix { en: "Fix", ja: "修正" },
intent_refactor { en: "Refactor", ja: "リファクタ" },
intent_docs { en: "Docs", ja: "ドキュメント" },
intent_test { en: "Test", ja: "テスト" },
intent_chore { en: "Chore", ja: "雑務" },
intent_unknown { en: "Unknown", ja: "不明" },
session_label { en: "Session", ja: "セッション" },
session_commits { en: "commits", ja: "コミット" },
session_separator { en: "Session", ja: "セッション" },
pr_create_title { en: "Create Pull Request", ja: "プルリクエスト作成" },
pr_title_label { en: "Title", ja: "タイトル" },
pr_body_label { en: "Body", ja: "本文" },
pr_base_label { en: "Base", ja: "ベース" },
pr_create_success { en: "PR created successfully", ja: "PR作成成功" },
pr_create_failed { en: "PR creation failed", ja: "PR作成失敗" },
pr_gh_not_available { en: "gh CLI not available", ja: "gh CLI が利用できません" },
pr_switch_field { en: "Tab: switch field", ja: "Tab: フィールド切替" },
pr_submit { en: "Enter: create", ja: "Enter: 作成" },
review_queue_title { en: "Review Queue", ja: "レビューキュー" },
review_pending { en: "Pending", ja: "保留中" },
review_approved { en: "Approved", ja: "承認済" },
review_rejected { en: "Rejected", ja: "却下済" },
review_no_items { en: "No review items", ja: "レビュー項目なし" },
review_approve_key { en: "a: approve", ja: "a: 承認" },
review_reject_key { en: "x: reject", ja: "x: 却下" },
review_pending_badge { en: "Review", ja: "レビュー" },
staging_group_title { en: "Staging Groups", ja: "ステージンググループ" },
staging_suggest { en: "Suggested staging groups", ja: "推奨ステージンググループ" },
staging_no_groups { en: "No grouping suggestions", ja: "グループ提案なし" },
split_suggestion_title { en: "PR Split Suggestion", ja: "PR分割提案" },
split_no_suggestion { en: "No split needed", ja: "分割不要" },
help_watch_mode { en: "Watch mode", ja: "ウォッチモード" },
help_pr_create { en: "Create PR", ja: "PR作成" },
help_review_queue { en: "Review queue", ja: "レビューキュー" },
help_smart_staging { en: "Smart stage (status)", ja: "スマートステージ" },
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_language_is_en() {
let lang = Language::default();
assert_eq!(lang, Language::En);
}
#[test]
fn toggle_en_to_ja() {
assert_eq!(Language::En.toggle(), Language::Ja);
}
#[test]
fn toggle_ja_to_en() {
assert_eq!(Language::Ja.toggle(), Language::En);
}
#[test]
fn toggle_roundtrip() {
assert_eq!(Language::En.toggle().toggle(), Language::En);
assert_eq!(Language::Ja.toggle().toggle(), Language::Ja);
}
#[test]
fn label_en() {
assert_eq!(Language::En.label(), "EN");
}
#[test]
fn label_ja() {
assert_eq!(Language::Ja.label(), "JA");
}
#[test]
fn serde_serialize_en() {
let json = serde_json::to_string(&Language::En).unwrap();
assert_eq!(json, "\"en\"");
}
#[test]
fn serde_serialize_ja() {
let json = serde_json::to_string(&Language::Ja).unwrap();
assert_eq!(json, "\"ja\"");
}
#[test]
fn serde_deserialize_en() {
let lang: Language = serde_json::from_str("\"en\"").unwrap();
assert_eq!(lang, Language::En);
}
#[test]
fn serde_deserialize_ja() {
let lang: Language = serde_json::from_str("\"ja\"").unwrap();
assert_eq!(lang, Language::Ja);
}
#[test]
fn serde_roundtrip() {
for lang in [Language::En, Language::Ja] {
let json = serde_json::to_string(&lang).unwrap();
let deserialized: Language = serde_json::from_str(&json).unwrap();
assert_eq!(lang, deserialized);
}
}
#[test]
fn debug_format() {
assert_eq!(format!("{:?}", Language::En), "En");
assert_eq!(format!("{:?}", Language::Ja), "Ja");
}
macro_rules! assert_translation_non_empty {
($method:ident) => {
let en = Language::En.$method();
let ja = Language::Ja.$method();
assert!(
!en.is_empty(),
"Language::En.{}() returned empty string",
stringify!($method)
);
assert!(
!ja.is_empty(),
"Language::Ja.{}() returned empty string",
stringify!($method)
);
};
}
macro_rules! assert_translation_differs {
($method:ident) => {
let en = Language::En.$method();
let ja = Language::Ja.$method();
assert_ne!(
en,
ja,
"Language::En.{}() and Language::Ja.{}() should differ",
stringify!($method),
stringify!($method)
);
};
}
#[test]
fn all_panel_labels_non_empty() {
assert_translation_non_empty!(status);
assert_translation_non_empty!(commits);
assert_translation_non_empty!(branches);
assert_translation_non_empty!(files);
assert_translation_non_empty!(stash);
}
#[test]
fn all_panel_labels_differ_en_ja() {
assert_translation_differs!(status);
assert_translation_differs!(commits);
assert_translation_differs!(branches);
assert_translation_differs!(files);
assert_translation_differs!(stash);
}
#[test]
fn main_panel_titles_non_empty() {
assert_translation_non_empty!(main_summary);
assert_translation_non_empty!(main_diff);
assert_translation_non_empty!(main_branch_info);
assert_translation_non_empty!(main_file_diff);
assert_translation_non_empty!(main_stash_detail);
}
#[test]
fn main_panel_titles_differ() {
assert_translation_differs!(main_summary);
assert_translation_differs!(main_diff);
assert_translation_differs!(main_branch_info);
assert_translation_differs!(main_file_diff);
assert_translation_differs!(main_stash_detail);
}
#[test]
fn status_labels_non_empty() {
assert_translation_non_empty!(repo_label);
assert_translation_non_empty!(on_label);
}
#[test]
fn overlay_titles_non_empty() {
assert_translation_non_empty!(author_stats);
assert_translation_non_empty!(file_heatmap);
assert_translation_non_empty!(activity_timeline);
assert_translation_non_empty!(code_ownership);
assert_translation_non_empty!(impact_scores);
assert_translation_non_empty!(branch_topology);
assert_translation_non_empty!(topology);
assert_translation_non_empty!(project_health);
assert_translation_non_empty!(change_coupling);
assert_translation_non_empty!(quality_scores);
assert_translation_non_empty!(quick_actions);
assert_translation_non_empty!(select_branch);
assert_translation_non_empty!(git_status);
assert_translation_non_empty!(quick_commit);
assert_translation_non_empty!(event_detail);
assert_translation_non_empty!(timeline);
assert_translation_non_empty!(file_history);
assert_translation_non_empty!(blame);
assert_translation_non_empty!(stash_overlay);
assert_translation_non_empty!(related);
assert_translation_non_empty!(save_filter_preset);
}
#[test]
fn help_overlay_non_empty() {
assert_translation_non_empty!(help);
assert_translation_non_empty!(help_adaptive);
assert_translation_non_empty!(help_navigation);
assert_translation_non_empty!(help_actions);
assert_translation_non_empty!(help_dashboard);
assert_translation_non_empty!(help_other);
}
#[test]
fn help_items_non_empty() {
assert_translation_non_empty!(help_move);
assert_translation_non_empty!(help_move_down);
assert_translation_non_empty!(help_move_up);
assert_translation_non_empty!(help_go_top);
assert_translation_non_empty!(help_go_bottom);
assert_translation_non_empty!(help_page_down);
assert_translation_non_empty!(help_page_up);
assert_translation_non_empty!(help_next_branch);
assert_translation_non_empty!(help_prev_branch);
assert_translation_non_empty!(help_show_detail);
assert_translation_non_empty!(help_filter);
assert_translation_non_empty!(help_branch_select);
assert_translation_non_empty!(help_status_view);
assert_translation_non_empty!(help_stash_list);
assert_translation_non_empty!(help_stash_save);
assert_translation_non_empty!(help_switch_panel);
assert_translation_non_empty!(help_toggle_focus);
assert_translation_non_empty!(help_focus_side_main);
assert_translation_non_empty!(help_fetch_remote);
assert_translation_non_empty!(help_cycle_view);
assert_translation_non_empty!(help_toggle_summary);
assert_translation_non_empty!(help_branch_topology);
assert_translation_non_empty!(help_toggle_help);
assert_translation_non_empty!(help_quit);
}
#[test]
fn help_shorthand_non_empty() {
assert_translation_non_empty!(help_top_bottom);
assert_translation_non_empty!(help_detail);
assert_translation_non_empty!(help_branch_status);
assert_translation_non_empty!(help_view_summary);
assert_translation_non_empty!(help_help_quit);
assert_translation_non_empty!(help_up_down);
assert_translation_non_empty!(help_top_bottom_full);
assert_translation_non_empty!(help_page_dn_up);
assert_translation_non_empty!(help_next_prev_branch);
assert_translation_non_empty!(help_branch);
assert_translation_non_empty!(help_status);
assert_translation_non_empty!(help_stash_save_short);
assert_translation_non_empty!(help_fetch);
assert_translation_non_empty!(help_topology);
assert_translation_non_empty!(help_nav_short);
assert_translation_non_empty!(help_act_short);
assert_translation_non_empty!(help_etc_short);
assert_translation_non_empty!(help_scroll_diff_h);
}
#[test]
fn footer_hints_non_empty() {
assert_translation_non_empty!(footer_health);
assert_translation_non_empty!(footer_authors);
assert_translation_non_empty!(footer_heatmap);
assert_translation_non_empty!(footer_detail);
assert_translation_non_empty!(footer_copy_hash);
assert_translation_non_empty!(footer_filter);
assert_translation_non_empty!(footer_switch);
assert_translation_non_empty!(footer_new);
assert_translation_non_empty!(footer_delete);
assert_translation_non_empty!(footer_diff);
assert_translation_non_empty!(footer_stage_all);
assert_translation_non_empty!(footer_commit);
assert_translation_non_empty!(footer_apply);
assert_translation_non_empty!(footer_drop);
assert_translation_non_empty!(footer_panel);
assert_translation_non_empty!(footer_focus);
assert_translation_non_empty!(footer_actions);
assert_translation_non_empty!(footer_help);
assert_translation_non_empty!(footer_quit);
assert_translation_non_empty!(footer_lang);
}
#[test]
fn quick_action_labels_non_empty() {
assert_translation_non_empty!(quick_risk_summary);
assert_translation_non_empty!(quick_review_pack);
assert_translation_non_empty!(quick_next_actions);
assert_translation_non_empty!(quick_verify);
assert_translation_non_empty!(quick_timeline);
assert_translation_non_empty!(quick_ownership);
assert_translation_non_empty!(quick_impact_score);
assert_translation_non_empty!(quick_change_coupling);
assert_translation_non_empty!(quick_quality_score);
assert_translation_non_empty!(quick_author_stats);
assert_translation_non_empty!(quick_heatmap);
}
#[test]
fn health_labels_non_empty() {
assert_translation_non_empty!(health_overall_score);
assert_translation_non_empty!(health_score_breakdown);
assert_translation_non_empty!(health_quality);
assert_translation_non_empty!(health_test);
assert_translation_non_empty!(health_bus_factor);
assert_translation_non_empty!(health_tech_debt);
assert_translation_non_empty!(health_code_churn);
assert_translation_non_empty!(health_commit_cadence);
assert_translation_non_empty!(health_alerts);
assert_translation_non_empty!(health_commits);
assert_translation_non_empty!(health_authors);
assert_translation_non_empty!(health_period);
assert_translation_non_empty!(health_confidence);
assert_translation_non_empty!(health_days);
assert_translation_non_empty!(health_score_label);
}
#[test]
fn health_scroll_close_quit_non_empty() {
for lang in [Language::En, Language::Ja] {
let (scroll, close, quit) = lang.health_scroll_close_quit();
assert!(!scroll.is_empty());
assert!(!close.is_empty());
assert!(!quit.is_empty());
}
}
#[test]
fn confidence_levels_non_empty() {
assert_translation_non_empty!(confidence_high);
assert_translation_non_empty!(confidence_medium);
assert_translation_non_empty!(confidence_low);
}
#[test]
fn alert_messages_non_empty() {
assert_translation_non_empty!(alert_low_commit_quality);
assert_translation_non_empty!(alert_low_test_coverage);
assert_translation_non_empty!(alert_high_bus_factor_risk);
assert_translation_non_empty!(alert_moderate_bus_factor_risk);
assert_translation_non_empty!(alert_high_tech_debt);
assert_translation_non_empty!(alert_high_code_churn);
}
#[test]
fn handoff_labels_non_empty() {
assert_translation_non_empty!(quick_handoff_claude);
assert_translation_non_empty!(quick_handoff_codex);
assert_translation_non_empty!(quick_handoff_copilot);
}
#[test]
fn status_messages_non_empty() {
assert_translation_non_empty!(status_fetching);
assert_translation_non_empty!(status_fetched);
assert_translation_non_empty!(status_fetch_failed);
assert_translation_non_empty!(status_fetch_thread_crashed);
assert_translation_non_empty!(status_stashed);
assert_translation_non_empty!(status_stash_failed);
assert_translation_non_empty!(status_copied);
assert_translation_non_empty!(status_copy_failed);
assert_translation_non_empty!(status_clipboard_unavailable);
assert_translation_non_empty!(status_quick_action_failed);
assert_translation_non_empty!(status_switched_to);
assert_translation_non_empty!(status_checkout_failed);
assert_translation_non_empty!(status_deleted_branch);
assert_translation_non_empty!(status_delete_failed);
assert_translation_non_empty!(status_created_branch);
assert_translation_non_empty!(status_create_failed);
assert_translation_non_empty!(status_all_staged);
assert_translation_non_empty!(status_all_unstaged);
assert_translation_non_empty!(status_no_staged_files);
assert_translation_non_empty!(status_pulling);
assert_translation_non_empty!(status_pulled);
assert_translation_non_empty!(status_pull_failed);
assert_translation_non_empty!(status_pushed);
assert_translation_non_empty!(status_push_failed);
assert_translation_non_empty!(status_committed);
assert_translation_non_empty!(status_commit_failed);
assert_translation_non_empty!(status_compare_failed);
assert_translation_non_empty!(status_applied_stash);
assert_translation_non_empty!(status_apply_failed);
assert_translation_non_empty!(status_popped_stash);
assert_translation_non_empty!(status_pop_failed);
assert_translation_non_empty!(status_dropped_stash);
assert_translation_non_empty!(status_drop_failed);
assert_translation_non_empty!(status_error);
}
#[test]
fn error_messages_non_empty() {
assert_translation_non_empty!(error_not_found);
assert_translation_non_empty!(error_permission_denied);
assert_translation_non_empty!(error_connection_refused);
assert_translation_non_empty!(error_connection_timeout);
assert_translation_non_empty!(error_auth_failed);
assert_translation_non_empty!(error_merge_conflict);
assert_translation_non_empty!(error_dirty_worktree);
assert_translation_non_empty!(error_branch_not_found);
assert_translation_non_empty!(error_branch_already_exists);
assert_translation_non_empty!(error_not_a_repo);
}
#[test]
fn cli_messages_non_empty() {
assert_translation_non_empty!(cli_analysis_cache_cleared);
assert_translation_non_empty!(cli_metrics_reset);
assert_translation_non_empty!(cli_help_title);
assert_translation_non_empty!(cli_help_usage);
assert_translation_non_empty!(cli_help_analysis_options);
assert_translation_non_empty!(cli_help_format_options);
assert_translation_non_empty!(cli_help_tui_options);
assert_translation_non_empty!(cli_help_general_options);
assert_translation_non_empty!(cli_help_no_options);
assert_translation_non_empty!(cli_help_examples);
}
#[test]
fn event_types_non_empty() {
assert_translation_non_empty!(event_commit);
assert_translation_non_empty!(event_merge);
assert_translation_non_empty!(event_branch_switch);
}
#[test]
fn detail_labels_non_empty() {
assert_translation_non_empty!(detail_type);
assert_translation_non_empty!(detail_hash);
assert_translation_non_empty!(detail_message);
assert_translation_non_empty!(detail_author);
assert_translation_non_empty!(detail_time);
assert_translation_non_empty!(loading_file_changes);
assert_translation_non_empty!(detail_footer);
assert_translation_non_empty!(no_changes);
}
#[test]
fn commit_overlay_non_empty() {
assert_translation_non_empty!(commit_message_label);
assert_translation_non_empty!(commit_suggestions);
assert_translation_non_empty!(commit_footer_with_suggestions);
assert_translation_non_empty!(commit_footer);
}
#[test]
fn loading_messages_non_empty() {
assert_translation_non_empty!(loading_topology);
assert_translation_non_empty!(loading_statistics);
assert_translation_non_empty!(loading_heatmap);
assert_translation_non_empty!(loading_timeline);
assert_translation_non_empty!(loading_history);
assert_translation_non_empty!(loading_blame);
assert_translation_non_empty!(loading_ownership);
assert_translation_non_empty!(loading_impact_scores);
assert_translation_non_empty!(loading_change_coupling);
assert_translation_non_empty!(loading_quality_scores);
assert_translation_non_empty!(loading_health);
assert_translation_non_empty!(loading_diff);
}
#[test]
fn table_headers_non_empty() {
assert_translation_non_empty!(header_author);
assert_translation_non_empty!(header_commits);
assert_translation_non_empty!(header_plus_lines);
assert_translation_non_empty!(header_minus_lines);
assert_translation_non_empty!(header_file);
assert_translation_non_empty!(header_changes);
assert_translation_non_empty!(header_heat);
assert_translation_non_empty!(header_hash);
assert_translation_non_empty!(header_date);
assert_translation_non_empty!(header_message);
assert_translation_non_empty!(header_msg_short);
assert_translation_non_empty!(header_score);
assert_translation_non_empty!(header_score_short);
assert_translation_non_empty!(header_path);
assert_translation_non_empty!(header_owner);
assert_translation_non_empty!(header_coupling);
assert_translation_non_empty!(header_coupled_with);
}
#[test]
fn hint_labels_non_empty() {
assert_translation_non_empty!(hint_move);
assert_translation_non_empty!(hint_filter);
assert_translation_non_empty!(hint_close);
assert_translation_non_empty!(hint_checkout);
assert_translation_non_empty!(hint_show_diff);
assert_translation_non_empty!(hint_scroll);
assert_translation_non_empty!(hint_show_commit);
assert_translation_non_empty!(hint_detail);
assert_translation_non_empty!(hint_export);
assert_translation_non_empty!(hint_switch);
assert_translation_non_empty!(hint_save);
assert_translation_non_empty!(hint_cancel);
assert_translation_non_empty!(hint_apply);
assert_translation_non_empty!(hint_pop);
assert_translation_non_empty!(hint_drop);
}
#[test]
fn topology_labels_non_empty() {
assert_translation_non_empty!(topology_issues);
assert_translation_non_empty!(topology_healthy);
assert_translation_non_empty!(topology_branches_count);
assert_translation_non_empty!(topology_stale);
assert_translation_non_empty!(topology_long);
assert_translation_non_empty!(topology_behind);
assert_translation_non_empty!(topology_div);
}
#[test]
fn stash_labels_non_empty() {
assert_translation_non_empty!(stash_list_label);
assert_translation_non_empty!(no_stashes);
assert_translation_non_empty!(no_commits);
}
#[test]
fn related_files_labels_non_empty() {
assert_translation_non_empty!(no_related_files);
assert_translation_non_empty!(no_related_files_short);
assert_translation_non_empty!(files_changed_together);
}
#[test]
fn compare_labels_non_empty() {
assert_translation_non_empty!(compare_ahead);
assert_translation_non_empty!(compare_behind);
}
#[test]
fn preset_labels_non_empty() {
assert_translation_non_empty!(save_filter_title);
assert_translation_non_empty!(filter_label);
assert_translation_non_empty!(select_slot);
assert_translation_non_empty!(name_label);
assert_translation_non_empty!(preset_label);
assert_translation_non_empty!(overwrite);
assert_translation_non_empty!(empty_slot);
}
#[test]
fn dashboard_labels_non_empty() {
assert_translation_non_empty!(no_commit_selected);
assert_translation_non_empty!(repository_summary);
assert_translation_non_empty!(dashboard_name);
assert_translation_non_empty!(dashboard_branch);
assert_translation_non_empty!(dashboard_commits);
assert_translation_non_empty!(dashboard_branches);
assert_translation_non_empty!(dashboard_stashes);
assert_translation_non_empty!(file_changes);
assert_translation_non_empty!(staged_label);
assert_translation_non_empty!(modified_label);
assert_translation_non_empty!(deleted_label);
assert_translation_non_empty!(untracked_label);
assert_translation_non_empty!(project_health_title);
assert_translation_non_empty!(recent_commits);
assert_translation_non_empty!(branch_info);
assert_translation_non_empty!(branch_name_label);
assert_translation_non_empty!(current_branch_label);
assert_translation_non_empty!(gone_label);
assert_translation_non_empty!(status_label);
assert_translation_non_empty!(active_label);
assert_translation_non_empty!(commits_label);
assert_translation_non_empty!(ahead_label);
assert_translation_non_empty!(behind_label);
assert_translation_non_empty!(health_warnings);
assert_translation_non_empty!(no_branch_selected);
assert_translation_non_empty!(branch_recommendations);
}
#[test]
fn file_detail_labels_non_empty() {
assert_translation_non_empty!(file_detail_title);
assert_translation_non_empty!(file_staged_new);
assert_translation_non_empty!(file_staged_modified);
assert_translation_non_empty!(file_staged_deleted);
assert_translation_non_empty!(file_modified);
assert_translation_non_empty!(file_deleted);
assert_translation_non_empty!(file_untracked);
assert_translation_non_empty!(path_label);
assert_translation_non_empty!(diff_label);
assert_translation_non_empty!(no_diff_available);
assert_translation_non_empty!(no_file_selected);
}
#[test]
fn stash_detail_labels_non_empty() {
assert_translation_non_empty!(no_stash_entries);
assert_translation_non_empty!(stash_detail_title);
assert_translation_non_empty!(stash_total);
assert_translation_non_empty!(stash_current);
assert_translation_non_empty!(stash_index);
assert_translation_non_empty!(all_stashes);
assert_translation_non_empty!(stash_entries);
assert_translation_non_empty!(files_changed);
assert_translation_non_empty!(total_label);
assert_translation_non_empty!(peak_label);
}
}