Skip to main content

gitstack/
i18n.rs

1//! Internationalization (i18n) module
2//!
3//! Supports switching between Japanese and English.
4//! Returns `&'static str` optimized for TUI re-rendering.
5
6use serde::{Deserialize, Serialize};
7
8/// Supported languages
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
10pub enum Language {
11    #[default]
12    #[serde(rename = "en")]
13    En,
14    #[serde(rename = "ja")]
15    Ja,
16}
17
18/// Macro to bulk-generate simple en/ja translation methods.
19///
20/// ```ignore
21/// i18n_messages! {
22///     method_name { en: "English", ja: "日本語" },
23/// }
24/// ```
25/// is equivalent to:
26/// ```ignore
27/// impl Language {
28///     pub fn method_name(self) -> &'static str {
29///         match self {
30///             Self::En => "English",
31///             Self::Ja => "日本語",
32///         }
33///     }
34/// }
35/// ```
36macro_rules! i18n_messages {
37    ( $( $name:ident { en: $en:expr, ja: $ja:expr } ),* $(,)? ) => {
38        impl Language {
39            $(
40                pub fn $name(self) -> &'static str {
41                    match self {
42                        Self::En => $en,
43                        Self::Ja => $ja,
44                    }
45                }
46            )*
47        }
48    };
49}
50
51impl Language {
52    /// Toggle the language
53    pub fn toggle(self) -> Self {
54        match self {
55            Self::En => Self::Ja,
56            Self::Ja => Self::En,
57        }
58    }
59
60    pub fn health_scroll_close_quit(self) -> (&'static str, &'static str, &'static str) {
61        match self {
62            Self::En => (": scroll  ", ": close  ", ": quit"),
63            Self::Ja => (": スクロール  ", ": 閉じる  ", ": 終了"),
64        }
65    }
66}
67
68i18n_messages! {
69    // Footer display labels
70    label { en: "EN", ja: "JA" },
71
72    // =========================================================================
73    // Panel labels
74    // =========================================================================
75    status { en: "Status", ja: "ステータス" },
76    commits { en: "Commits", ja: "コミット" },
77    branches { en: "Branches", ja: "ブランチ" },
78    files { en: "Files", ja: "ファイル" },
79    stash { en: "Stash", ja: "スタッシュ" },
80
81    // =========================================================================
82    // Main panel titles
83    // =========================================================================
84    main_summary { en: " Main: Summary ", ja: " メイン: サマリー " },
85    main_diff { en: " Main: Diff ", ja: " メイン: 差分 " },
86    main_branch_info { en: " Main: Branch Info ", ja: " メイン: ブランチ情報 " },
87    main_file_diff { en: " Main: File Diff ", ja: " メイン: ファイル差分 " },
88    main_stash_detail { en: " Main: Stash Detail ", ja: " メイン: スタッシュ詳細 " },
89
90    // =========================================================================
91    // Status panel labels
92    // =========================================================================
93    repo_label { en: "repo: ", ja: "リポジトリ: " },
94    on_label { en: "on: ", ja: "ブランチ: " },
95
96    // =========================================================================
97    // Overlay titles
98    // =========================================================================
99    author_stats { en: " Author Statistics ", ja: " 著者統計 " },
100    file_heatmap { en: " File Heatmap ", ja: " ファイルヒートマップ " },
101    activity_timeline { en: " Activity Timeline ", ja: " 活動タイムライン " },
102    code_ownership { en: " Code Ownership ", ja: " コード所有権 " },
103    impact_scores { en: " Impact Scores ", ja: " インパクトスコア " },
104    branch_topology { en: " Branch Topology ", ja: " ブランチトポロジー " },
105    topology { en: " Topology ", ja: " トポロジー " },
106    project_health { en: " Project Health Dashboard ", ja: " プロジェクト健全性 " },
107    change_coupling { en: " Change Coupling ", ja: " 変更結合度 " },
108    quality_scores { en: " Quality Scores ", ja: " 品質スコア " },
109    quick_actions { en: " Quick Actions ", ja: " クイックアクション " },
110    select_branch { en: " Select Branch ", ja: " ブランチ選択 " },
111    git_status { en: " Git Status ", ja: " Git ステータス " },
112    quick_commit { en: " Quick Commit ", ja: " クイックコミット " },
113    event_detail { en: " Event Detail ", ja: " イベント詳細 " },
114    timeline { en: " Timeline ", ja: " タイムライン " },
115    file_history { en: " File History ", ja: " ファイル履歴 " },
116    blame { en: " Blame ", ja: " Blame " },
117    stash_overlay { en: " Stash ", ja: " スタッシュ " },
118    related { en: " Related ", ja: " 関連 " },
119    save_filter_preset { en: " Save Filter Preset ", ja: " フィルタプリセット保存 " },
120
121    // =========================================================================
122    // Help overlay
123    // =========================================================================
124    help { en: " Help ", ja: " ヘルプ " },
125    help_adaptive { en: " Help (Adaptive) ", ja: " ヘルプ " },
126    help_navigation { en: "Navigation", ja: "ナビゲーション" },
127    help_actions { en: "Actions", ja: "アクション" },
128    help_dashboard { en: "Dashboard", ja: "ダッシュボード" },
129    help_other { en: "Other", ja: "その他" },
130    help_move { en: "move", ja: "移動" },
131    help_move_down { en: "Move down", ja: "下へ移動" },
132    help_move_up { en: "Move up", ja: "上へ移動" },
133    help_go_top { en: "Go to top", ja: "先頭へ" },
134    help_go_bottom { en: "Go to bottom", ja: "末尾へ" },
135    help_page_down { en: "Page down", ja: "ページ下" },
136    help_page_up { en: "Page up", ja: "ページ上" },
137    help_next_branch { en: "Next branch", ja: "次のブランチ" },
138    help_prev_branch { en: "Prev branch", ja: "前のブランチ" },
139    help_show_detail { en: "Show detail", ja: "詳細表示" },
140    help_filter { en: "Filter", ja: "フィルタ" },
141    help_branch_select { en: "Branch select", ja: "ブランチ選択" },
142    help_status_view { en: "Status view", ja: "ステータス表示" },
143    help_stash_list { en: "Stash list", ja: "スタッシュ一覧" },
144    help_stash_save { en: "Stash save", ja: "スタッシュ保存" },
145    help_switch_panel { en: "Switch panel", ja: "パネル切替" },
146    help_toggle_focus { en: "Toggle focus", ja: "フォーカス切替" },
147    help_focus_side_main { en: "Focus side/main", ja: "サイド/メイン" },
148    help_fetch_remote { en: "Fetch remote", ja: "リモートフェッチ" },
149    help_cycle_view { en: "Cycle view mode", ja: "表示モード切替" },
150    help_toggle_summary { en: "Toggle summary line", ja: "サマリー行切替" },
151    help_branch_topology { en: "Branch topology", ja: "ブランチトポロジー" },
152    help_toggle_help { en: "Toggle help", ja: "ヘルプ切替" },
153    help_quit { en: "Quit", ja: "終了" },
154    help_top_bottom { en: "top/btm", ja: "先頭/末尾" },
155    help_detail { en: "detail", ja: "詳細" },
156    help_branch_status { en: "branch/status", ja: "ブランチ/ステータス" },
157    help_view_summary { en: "view/summary", ja: "表示/サマリー" },
158    help_help_quit { en: "help/quit", ja: "ヘルプ/終了" },
159    help_up_down { en: "up/down", ja: "上/下" },
160    help_top_bottom_full { en: "top/bottom", ja: "先頭/末尾" },
161    help_page_dn_up { en: "page dn/up", ja: "ページ上下" },
162    help_next_prev_branch { en: "next/prev branch", ja: "次/前ブランチ" },
163    help_branch { en: "branch", ja: "ブランチ" },
164    help_status { en: "status", ja: "ステータス" },
165    help_stash_save_short { en: "stash/save", ja: "スタッシュ/保存" },
166    help_fetch { en: "fetch", ja: "フェッチ" },
167    help_topology { en: "topology", ja: "トポロジー" },
168
169    // =========================================================================
170    // Footer hints
171    // =========================================================================
172    footer_health { en: "Health", ja: "健全性" },
173    footer_authors { en: "Authors", ja: "著者" },
174    footer_heatmap { en: "Heatmap", ja: "ヒートマップ" },
175    footer_detail { en: "Detail", ja: "詳細" },
176    footer_copy_hash { en: "Copy hash", ja: "ハッシュコピー" },
177    footer_filter { en: "Filter", ja: "フィルタ" },
178    footer_switch { en: "Switch", ja: "切替" },
179    footer_new { en: "New", ja: "新規" },
180    footer_delete { en: "Delete", ja: "削除" },
181    footer_diff { en: "Diff", ja: "差分" },
182    footer_stage_all { en: "Stage all", ja: "全ステージ" },
183    footer_commit { en: "Commit", ja: "コミット" },
184    footer_apply { en: "Apply", ja: "適用" },
185    footer_drop { en: "Drop", ja: "破棄" },
186    footer_panel { en: "panel", ja: "パネル" },
187    footer_focus { en: "focus", ja: "フォーカス" },
188    footer_actions { en: "actions", ja: "アクション" },
189    footer_help { en: "help", ja: "ヘルプ" },
190    footer_quit { en: "quit", ja: "終了" },
191    footer_lang { en: "lang", ja: "言語" },
192    footer_watch { en: "Watch", ja: "監視" },
193    footer_pr { en: "PR", ja: "PR" },
194    footer_review { en: "Review", ja: "レビュー" },
195    footer_quick_action { en: "Quick Action", ja: "クイックアクション" },
196
197    // =========================================================================
198    // Quick actions
199    // =========================================================================
200    quick_risk_summary { en: "Risk Summary", ja: "リスクサマリー" },
201    quick_review_pack { en: "Review Pack", ja: "レビューパック" },
202    quick_next_actions { en: "Next Actions", ja: "次のアクション" },
203    quick_verify { en: "Verify Patch Risk", ja: "パッチリスク検証" },
204    quick_timeline { en: "Timeline", ja: "タイムライン" },
205    quick_ownership { en: "Ownership", ja: "オーナーシップ" },
206    quick_impact_score { en: "Impact Score", ja: "インパクトスコア" },
207    quick_change_coupling { en: "Change Coupling", ja: "チェンジカップリング" },
208    quick_quality_score { en: "Quality Score", ja: "品質スコア" },
209    quick_author_stats { en: "Author Stats", ja: "著者統計" },
210    quick_heatmap { en: "File Heatmap", ja: "ファイルヒートマップ" },
211
212    // =========================================================================
213    // Project Health
214    // =========================================================================
215    health_overall_score { en: "Overall Score: ", ja: "総合スコア: " },
216    health_score_breakdown { en: "Score Breakdown:", ja: "スコア内訳:" },
217    health_quality { en: "Quality", ja: "品質" },
218    health_test { en: "Test Health", ja: "テスト健全性" },
219    health_bus_factor { en: "Bus Factor", ja: "バスファクター" },
220    health_tech_debt { en: "Tech Debt", ja: "技術的負債" },
221    health_code_churn { en: "Code Churn", ja: "コード変動" },
222    health_commit_cadence { en: "Commit Cadence", ja: "コミット頻度" },
223    health_alerts { en: "Alerts:", ja: "アラート:" },
224    health_commits { en: "Commits: ", ja: "コミット: " },
225    health_authors { en: "Authors: ", ja: "著者: " },
226    health_period { en: "Period: ", ja: "期間: " },
227    health_confidence { en: "Confidence: ", ja: "信頼度: " },
228    health_days { en: " days", ja: " 日" },
229    health_score_label { en: "Score:   ", ja: "スコア:  " },
230
231    // =========================================================================
232    // Confidence levels
233    // =========================================================================
234    confidence_high { en: "High", ja: "高" },
235    confidence_medium { en: "Medium", ja: "中" },
236    confidence_low { en: "Low", ja: "低" },
237
238    // =========================================================================
239    // Health alert messages
240    // =========================================================================
241    alert_low_commit_quality { en: "Low commit quality", ja: "コミット品質が低い" },
242    alert_low_test_coverage { en: "Low test coverage in commits", ja: "テストカバレッジが低い" },
243    alert_high_bus_factor_risk { en: "High bus factor risk", ja: "バスファクターリスクが高い" },
244    alert_moderate_bus_factor_risk { en: "Moderate bus factor risk", ja: "バスファクターリスクが中程度" },
245    alert_high_tech_debt { en: "High technical debt indicated", ja: "技術的負債が高い" },
246    alert_high_code_churn { en: "High code churn detected", ja: "コード変動が激しい" },
247
248    // =========================================================================
249    // Quick actions: Handoff
250    // =========================================================================
251    quick_handoff_claude { en: "Handoff (Claude)", ja: "ハンドオフ (Claude)" },
252    quick_handoff_codex { en: "Handoff (Codex)", ja: "ハンドオフ (Codex)" },
253    quick_handoff_copilot { en: "Handoff (Copilot)", ja: "ハンドオフ (Copilot)" },
254
255    // =========================================================================
256    // Status messages
257    // =========================================================================
258    status_fetching { en: "Fetching...", ja: "フェッチ中..." },
259    status_fetched { en: "Fetched", ja: "フェッチ完了" },
260    status_fetch_failed { en: "Fetch failed", ja: "フェッチ失敗" },
261    status_fetch_thread_crashed { en: "Fetch thread crashed", ja: "フェッチスレッドが異常終了" },
262    status_stashed { en: "Stashed changes", ja: "変更をスタッシュしました" },
263    status_stash_failed { en: "Stash failed", ja: "スタッシュ失敗" },
264    status_copied { en: "Copied", ja: "コピー済み" },
265    status_copy_failed { en: "Failed to copy to clipboard", ja: "クリップボードへのコピーに失敗" },
266    status_clipboard_unavailable { en: "Clipboard not available", ja: "クリップボードが利用できません" },
267    status_quick_action_failed { en: "Quick action failed", ja: "クイックアクション失敗" },
268    status_switched_to { en: "Switched to", ja: "切り替え完了" },
269    status_checkout_failed { en: "Checkout failed", ja: "チェックアウト失敗" },
270    status_deleted_branch { en: "Deleted branch", ja: "ブランチ削除完了" },
271    status_delete_failed { en: "Delete failed", ja: "削除失敗" },
272    status_created_branch { en: "Created branch", ja: "ブランチ作成完了" },
273    status_create_failed { en: "Create failed", ja: "作成失敗" },
274    status_all_staged { en: "All files staged", ja: "全ファイルをステージしました" },
275    status_all_unstaged { en: "All files unstaged", ja: "全ファイルをアンステージしました" },
276    status_no_staged_files { en: "No staged files", ja: "ステージされたファイルがありません" },
277    status_pulling { en: "Pulling...", ja: "プル中..." },
278    status_pulled { en: "Pulled successfully", ja: "プル完了" },
279    status_pull_failed { en: "Pull failed", ja: "プル失敗" },
280    status_pushed { en: "Pushed successfully", ja: "プッシュ完了" },
281    status_push_failed { en: "Push failed", ja: "プッシュ失敗" },
282    status_committed { en: "Committed", ja: "コミット完了" },
283    status_commit_failed { en: "Commit failed", ja: "コミット失敗" },
284    status_compare_failed { en: "Compare failed", ja: "比較失敗" },
285    status_applied_stash { en: "Applied", ja: "適用完了" },
286    status_apply_failed { en: "Apply failed", ja: "適用失敗" },
287    status_popped_stash { en: "Popped", ja: "ポップ完了" },
288    status_pop_failed { en: "Pop failed", ja: "ポップ失敗" },
289    status_dropped_stash { en: "Dropped", ja: "破棄完了" },
290    status_drop_failed { en: "Drop failed", ja: "破棄失敗" },
291    status_error { en: "Error", ja: "エラー" },
292
293    // =========================================================================
294    // Friendly error messages
295    // =========================================================================
296    error_not_found { en: "File or path not found", ja: "ファイルまたはパスが見つかりません" },
297    error_permission_denied { en: "Permission denied", ja: "アクセス権限がありません" },
298    error_connection_refused { en: "Could not connect to remote", ja: "リモートに接続できません" },
299    error_connection_timeout { en: "Connection timed out", ja: "接続がタイムアウトしました" },
300    error_auth_failed { en: "Authentication failed - check your credentials", ja: "認証に失敗しました - 認証情報を確認してください" },
301    error_merge_conflict { en: "Merge conflict - resolve conflicts first", ja: "マージコンフリクトがあります - 先にコンフリクトを解消してください" },
302    error_dirty_worktree { en: "Uncommitted changes exist - commit or stash first", ja: "未コミットの変更があります - 先にコミットまたはスタッシュしてください" },
303    error_branch_not_found { en: "Branch not found", ja: "ブランチが見つかりません" },
304    error_branch_already_exists { en: "Branch already exists", ja: "ブランチはすでに存在します" },
305    error_not_a_repo { en: "Not a git repository", ja: "Gitリポジトリではありません" },
306
307    // =========================================================================
308    // CLI messages
309    // =========================================================================
310    cli_analysis_cache_cleared { en: "Analysis cache cleared", ja: "分析キャッシュを削除しました" },
311    cli_metrics_reset { en: "Metrics reset", ja: "メトリクスをリセットしました" },
312    cli_help_title { en: "gitstack - Git history viewer with insights", ja: "gitstack - インサイト付きGit履歴ビューア" },
313    cli_help_usage { en: "USAGE:", ja: "使い方:" },
314    cli_help_analysis_options { en: "ANALYSIS OPTIONS:", ja: "分析オプション:" },
315    cli_help_format_options { en: "FORMAT OPTIONS:", ja: "フォーマットオプション:" },
316    cli_help_tui_options { en: "TUI OPTIONS (when no analysis option is used):", ja: "TUIオプション(分析オプション未指定時):" },
317    cli_help_general_options { en: "GENERAL OPTIONS:", ja: "一般オプション:" },
318    cli_help_no_options { en: "Without options, gitstack starts in interactive TUI mode.", ja: "オプションなしで実行すると対話的TUIモードで起動します。" },
319    cli_help_examples { en: "EXAMPLES:", ja: "使用例:" },
320
321    // =========================================================================
322    // Event types
323    // =========================================================================
324    event_commit { en: "Commit", ja: "コミット" },
325    event_merge { en: "Merge", ja: "マージ" },
326    event_branch_switch { en: "Branch Switch", ja: "ブランチ切替" },
327
328    // =========================================================================
329    // Detail overlay labels
330    // =========================================================================
331    detail_type { en: "Type: ", ja: "種類: " },
332    detail_hash { en: "Hash: ", ja: "ハッシュ: " },
333    detail_message { en: "Message: ", ja: "メッセージ: " },
334    detail_author { en: "Author: ", ja: "著者: " },
335    detail_time { en: "Time: ", ja: "時刻: " },
336    loading_file_changes { en: " Loading file changes...", ja: " ファイル変更を読み込み中..." },
337    detail_footer { en: " j/k: navigate  P: patch  F: history  B: blame  Esc: close", ja: " j/k: 移動  P: パッチ  F: 履歴  B: blame  Esc: 閉じる" },
338    no_changes { en: "  No changes", ja: "  変更なし" },
339
340    // =========================================================================
341    // Quick commit overlay
342    // =========================================================================
343    commit_message_label { en: "  Message: ", ja: "  メッセージ: " },
344    commit_suggestions { en: "  ─── Suggestions ───", ja: "  ─── 候補 ───" },
345    commit_footer_with_suggestions { en: "[1-3] Select  [Enter] Commit  [Esc] Cancel", ja: "[1-3] 選択  [Enter] コミット  [Esc] キャンセル" },
346    commit_footer { en: "[Enter] Commit  [Esc] Cancel", ja: "[Enter] コミット  [Esc] キャンセル" },
347
348    // =========================================================================
349    // Help overlay (narrow width category labels)
350    // =========================================================================
351    help_nav_short { en: "Nav", ja: "移動" },
352    help_act_short { en: "Act", ja: "操作" },
353    help_etc_short { en: "Etc", ja: "他" },
354    help_scroll_diff_h { en: "Scroll diff H", ja: "差分横スクロール" },
355
356    // =========================================================================
357    // Loading messages
358    // =========================================================================
359    loading_topology { en: "Loading topology...", ja: "トポロジーを読み込み中..." },
360    loading_statistics { en: "Loading statistics...", ja: "統計を読み込み中..." },
361    loading_heatmap { en: "Loading heatmap...", ja: "ヒートマップを読み込み中..." },
362    loading_timeline { en: "Loading timeline...", ja: "タイムラインを読み込み中..." },
363    loading_history { en: "Loading history...", ja: "履歴を読み込み中..." },
364    loading_blame { en: "Loading blame...", ja: "Blameを読み込み中..." },
365    loading_ownership { en: "Loading ownership...", ja: "オーナーシップを読み込み中..." },
366    loading_impact_scores { en: "Loading impact scores...", ja: "インパクトスコアを読み込み中..." },
367    loading_change_coupling { en: "Loading change coupling analysis...", ja: "変更結合度を分析中..." },
368    loading_quality_scores { en: "Loading quality scores...", ja: "品質スコアを読み込み中..." },
369    loading_health { en: "Loading health data...", ja: "ヘルスデータを読み込み中..." },
370    loading_diff { en: "Loading diff...", ja: "差分を読み込み中..." },
371
372    // =========================================================================
373    // Table headers
374    // =========================================================================
375    header_author { en: "Author", ja: "著者" },
376    header_commits { en: "Commits", ja: "コミット" },
377    header_plus_lines { en: "+Lines", ja: "+行数" },
378    header_minus_lines { en: "-Lines", ja: "-行数" },
379    header_file { en: "File", ja: "ファイル" },
380    header_changes { en: "Changes", ja: "変更数" },
381    header_heat { en: "Heat", ja: "温度" },
382    header_hash { en: "Hash", ja: "ハッシュ" },
383    header_date { en: "Date", ja: "日付" },
384    header_message { en: "Message", ja: "メッセージ" },
385    header_msg_short { en: "Msg", ja: "メッセージ" },
386    header_score { en: "Score", ja: "スコア" },
387    header_score_short { en: "Scr", ja: "Scr" },
388    header_path { en: "Path", ja: "パス" },
389    header_owner { en: "Owner", ja: "所有者" },
390    header_coupling { en: "Coupling     ", ja: "結合度       " },
391    header_coupled_with { en: "Coupled With", ja: "結合先" },
392
393    // =========================================================================
394    // Footer action hints
395    // =========================================================================
396    hint_move { en: ": move  ", ja: ": 移動  " },
397    hint_filter { en: ": filter  ", ja: ": フィルタ  " },
398    hint_close { en: ": close", ja: ": 閉じる" },
399    hint_checkout { en: ": checkout  ", ja: ": チェックアウト  " },
400    hint_show_diff { en: ": show diff  ", ja: ": 差分表示  " },
401    hint_scroll { en: ": scroll  ", ja: ": スクロール  " },
402    hint_show_commit { en: ": show commit  ", ja: ": コミット表示  " },
403    hint_detail { en: ": detail  ", ja: ": 詳細  " },
404    hint_export { en: ": export  ", ja: ": エクスポート  " },
405    hint_switch { en: ": switch  ", ja: ": 切替  " },
406    hint_save { en: ": save  ", ja: ": 保存  " },
407    hint_cancel { en: ": cancel", ja: ": キャンセル" },
408    hint_apply { en: ": apply  ", ja: ": 適用  " },
409    hint_pop { en: ": pop  ", ja: ": ポップ  " },
410    hint_drop { en: ": drop  ", ja: ": 破棄  " },
411
412    // =========================================================================
413    // Topology related
414    // =========================================================================
415    topology_issues { en: " issues", ja: " 件の問題" },
416    topology_healthy { en: " ✓ healthy", ja: " ✓ 健全" },
417    topology_branches_count { en: " branches)", ja: " ブランチ)" },
418    topology_stale { en: " stale", ja: " 停滞" },
419    topology_long { en: " long", ja: " 長期" },
420    topology_behind { en: " behind", ja: " 遅延" },
421    topology_div { en: " div", ja: " 乖離" },
422
423    // =========================================================================
424    // Stash overlay
425    // =========================================================================
426    stash_list_label { en: "Stash List ", ja: "スタッシュ一覧 " },
427    no_stashes { en: "  No stashes", ja: "  スタッシュなし" },
428    no_commits { en: "  No commits", ja: "  コミットなし" },
429
430    // =========================================================================
431    // Related files overlay
432    // =========================================================================
433    no_related_files { en: "  No related files found in commit history", ja: "  コミット履歴に関連ファイルが見つかりません" },
434    no_related_files_short { en: "  No related files", ja: "  関連ファイルなし" },
435    files_changed_together { en: "  Files frequently changed together:", ja: "  頻繁に一緒に変更されるファイル:" },
436
437    // =========================================================================
438    // Branch comparison
439    // =========================================================================
440    compare_ahead { en: "Ahead", ja: "先行" },
441    compare_behind { en: "Behind", ja: "遅延" },
442
443    // =========================================================================
444    // Preset save dialog
445    // =========================================================================
446    save_filter_title { en: "Save current filter to preset", ja: "現在のフィルタをプリセットに保存" },
447    filter_label { en: "Filter: ", ja: "フィルタ: " },
448    select_slot { en: "Select slot (1-5):", ja: "スロットを選択 (1-5):" },
449    name_label { en: "Name: ", ja: "名前: " },
450    preset_label { en: "Preset", ja: "プリセット" },
451    overwrite { en: "(overwrite)", ja: "(上書き)" },
452    empty_slot { en: "(empty)", ja: "(空)" },
453
454    // =========================================================================
455    // Dashboard main panel
456    // =========================================================================
457    no_commit_selected { en: "No commit selected", ja: "コミットが選択されていません" },
458    repository_summary { en: "Repository Summary", ja: "リポジトリサマリー" },
459    dashboard_name { en: "Name:     ", ja: "名前:     " },
460    dashboard_branch { en: "Branch:   ", ja: "ブランチ: " },
461    dashboard_commits { en: "Commits:  ", ja: "コミット: " },
462    dashboard_branches { en: "Branches: ", ja: "ブランチ: " },
463    dashboard_stashes { en: "Stashes:  ", ja: "スタッシュ: " },
464    file_changes { en: "File Changes", ja: "ファイル変更" },
465    staged_label { en: "  Staged:    ", ja: "  ステージ済: " },
466    modified_label { en: "  Modified:  ", ja: "  変更:      " },
467    deleted_label { en: "  Deleted:   ", ja: "  削除:      " },
468    untracked_label { en: "  Untracked: ", ja: "  未追跡:    " },
469    project_health_title { en: "Project Health", ja: "プロジェクト健全性" },
470    recent_commits { en: "Recent Commits", ja: "最近のコミット" },
471    branch_info { en: "Branch Info", ja: "ブランチ情報" },
472    branch_name_label { en: "Name:   ", ja: "名前:   " },
473    current_branch_label { en: "(current branch)", ja: "(現在のブランチ)" },
474    gone_label { en: "[gone] remote tracking branch deleted", ja: "[gone] リモート追跡ブランチが削除されています" },
475    status_label { en: "Status: ", ja: "状態:   " },
476    active_label { en: "Active: ", ja: "最終:   " },
477    commits_label { en: "Commits:", ja: "コミット:" },
478    ahead_label { en: " ahead", ja: " 先行" },
479    behind_label { en: " behind", ja: " 遅延" },
480    health_warnings { en: "Health Warnings", ja: "ヘルス警告" },
481    no_branch_selected { en: "No branch selected", ja: "ブランチが選択されていません" },
482    branch_recommendations { en: "Branch Recommendations", ja: "ブランチ推奨アクション" },
483    file_detail_title { en: "File Detail", ja: "ファイル詳細" },
484    file_staged_new { en: "Staged (New)", ja: "ステージ済 (新規)" },
485    file_staged_modified { en: "Staged (Modified)", ja: "ステージ済 (変更)" },
486    file_staged_deleted { en: "Staged (Deleted)", ja: "ステージ済 (削除)" },
487    file_modified { en: "Modified", ja: "変更" },
488    file_deleted { en: "Deleted", ja: "削除" },
489    file_untracked { en: "Untracked", ja: "未追跡" },
490    path_label { en: "Path:   ", ja: "パス:   " },
491    diff_label { en: "Diff:   ", ja: "差分:   " },
492    no_diff_available { en: "(no diff available)", ja: "(差分なし)" },
493    no_file_selected { en: "No file selected", ja: "ファイルが選択されていません" },
494    no_stash_entries { en: "No stash entries", ja: "スタッシュエントリなし" },
495    stash_detail_title { en: "Stash Detail", ja: "スタッシュ詳細" },
496    stash_total { en: "Total:   ", ja: "合計:    " },
497    stash_current { en: "Current: ", ja: "選択:    " },
498    stash_index { en: "Index:   ", ja: "インデックス: " },
499    all_stashes { en: "All Stashes", ja: "全スタッシュ" },
500    stash_entries { en: " stash entries", ja: " 件のスタッシュ" },
501    files_changed { en: " files changed", ja: " ファイル変更" },
502    total_label { en: " Total: ", ja: " 合計: " },
503    peak_label { en: " Peak: ", ja: " ピーク: " },
504
505    // ===== v5.0.0: AI Terminal Cockpit =====
506
507    // Watch mode
508    watch_mode_on { en: "[WATCH]", ja: "[監視]" },
509    watch_mode_enabled { en: "Watch mode enabled", ja: "ウォッチモード有効" },
510    watch_mode_disabled { en: "Watch mode disabled", ja: "ウォッチモード無効" },
511
512    // Risk level
513    risk_label { en: "Risk", ja: "リスク" },
514    risk_low { en: "Low", ja: "低" },
515    risk_medium { en: "Med", ja: "中" },
516    risk_high { en: "High", ja: "高" },
517
518    // Intent labels
519    intent_feature { en: "Feature", ja: "機能" },
520    intent_fix { en: "Fix", ja: "修正" },
521    intent_refactor { en: "Refactor", ja: "リファクタ" },
522    intent_docs { en: "Docs", ja: "ドキュメント" },
523    intent_test { en: "Test", ja: "テスト" },
524    intent_chore { en: "Chore", ja: "雑務" },
525    intent_unknown { en: "Unknown", ja: "不明" },
526
527    // Session
528    session_label { en: "Session", ja: "セッション" },
529    session_commits { en: "commits", ja: "コミット" },
530    session_separator { en: "Session", ja: "セッション" },
531
532    // PR create
533    pr_create_title { en: "Create Pull Request", ja: "プルリクエスト作成" },
534    pr_title_label { en: "Title", ja: "タイトル" },
535    pr_body_label { en: "Body", ja: "本文" },
536    pr_base_label { en: "Base", ja: "ベース" },
537    pr_create_success { en: "PR created successfully", ja: "PR作成成功" },
538    pr_create_failed { en: "PR creation failed", ja: "PR作成失敗" },
539    pr_gh_not_available { en: "gh CLI not available", ja: "gh CLI が利用できません" },
540    pr_switch_field { en: "Tab: switch field", ja: "Tab: フィールド切替" },
541    pr_submit { en: "Enter: create", ja: "Enter: 作成" },
542
543    // Review queue
544    review_queue_title { en: "Review Queue", ja: "レビューキュー" },
545    review_pending { en: "Pending", ja: "保留中" },
546    review_approved { en: "Approved", ja: "承認済" },
547    review_rejected { en: "Rejected", ja: "却下済" },
548    review_no_items { en: "No review items", ja: "レビュー項目なし" },
549    review_approve_key { en: "a: approve", ja: "a: 承認" },
550    review_reject_key { en: "x: reject", ja: "x: 却下" },
551    review_pending_badge { en: "Review", ja: "レビュー" },
552
553    // Smart staging
554    staging_group_title { en: "Staging Groups", ja: "ステージンググループ" },
555    staging_suggest { en: "Suggested staging groups", ja: "推奨ステージンググループ" },
556    staging_no_groups { en: "No grouping suggestions", ja: "グループ提案なし" },
557
558    // PR split
559    split_suggestion_title { en: "PR Split Suggestion", ja: "PR分割提案" },
560    split_no_suggestion { en: "No split needed", ja: "分割不要" },
561
562    // Help overlay: v5.0.0 keys
563    help_watch_mode { en: "Watch mode", ja: "ウォッチモード" },
564    help_pr_create { en: "Create PR", ja: "PR作成" },
565    help_review_queue { en: "Review queue", ja: "レビューキュー" },
566    help_smart_staging { en: "Smart stage (status)", ja: "スマートステージ" },
567}
568
569#[cfg(test)]
570mod tests {
571    use super::*;
572
573    #[test]
574    fn default_language_is_en() {
575        let lang = Language::default();
576        assert_eq!(lang, Language::En);
577    }
578
579    #[test]
580    fn toggle_en_to_ja() {
581        assert_eq!(Language::En.toggle(), Language::Ja);
582    }
583
584    #[test]
585    fn toggle_ja_to_en() {
586        assert_eq!(Language::Ja.toggle(), Language::En);
587    }
588
589    #[test]
590    fn toggle_roundtrip() {
591        assert_eq!(Language::En.toggle().toggle(), Language::En);
592        assert_eq!(Language::Ja.toggle().toggle(), Language::Ja);
593    }
594
595    #[test]
596    fn label_en() {
597        assert_eq!(Language::En.label(), "EN");
598    }
599
600    #[test]
601    fn label_ja() {
602        assert_eq!(Language::Ja.label(), "JA");
603    }
604
605    #[test]
606    fn serde_serialize_en() {
607        let json = serde_json::to_string(&Language::En).unwrap();
608        assert_eq!(json, "\"en\"");
609    }
610
611    #[test]
612    fn serde_serialize_ja() {
613        let json = serde_json::to_string(&Language::Ja).unwrap();
614        assert_eq!(json, "\"ja\"");
615    }
616
617    #[test]
618    fn serde_deserialize_en() {
619        let lang: Language = serde_json::from_str("\"en\"").unwrap();
620        assert_eq!(lang, Language::En);
621    }
622
623    #[test]
624    fn serde_deserialize_ja() {
625        let lang: Language = serde_json::from_str("\"ja\"").unwrap();
626        assert_eq!(lang, Language::Ja);
627    }
628
629    #[test]
630    fn serde_roundtrip() {
631        for lang in [Language::En, Language::Ja] {
632            let json = serde_json::to_string(&lang).unwrap();
633            let deserialized: Language = serde_json::from_str(&json).unwrap();
634            assert_eq!(lang, deserialized);
635        }
636    }
637
638    #[test]
639    fn debug_format() {
640        assert_eq!(format!("{:?}", Language::En), "En");
641        assert_eq!(format!("{:?}", Language::Ja), "Ja");
642    }
643
644    /// Helper: calls a translation method for both languages and asserts non-empty
645    macro_rules! assert_translation_non_empty {
646        ($method:ident) => {
647            let en = Language::En.$method();
648            let ja = Language::Ja.$method();
649            assert!(
650                !en.is_empty(),
651                "Language::En.{}() returned empty string",
652                stringify!($method)
653            );
654            assert!(
655                !ja.is_empty(),
656                "Language::Ja.{}() returned empty string",
657                stringify!($method)
658            );
659        };
660    }
661
662    /// Helper: asserts translations are different between En and Ja
663    macro_rules! assert_translation_differs {
664        ($method:ident) => {
665            let en = Language::En.$method();
666            let ja = Language::Ja.$method();
667            assert_ne!(
668                en,
669                ja,
670                "Language::En.{}() and Language::Ja.{}() should differ",
671                stringify!($method),
672                stringify!($method)
673            );
674        };
675    }
676
677    #[test]
678    fn all_panel_labels_non_empty() {
679        assert_translation_non_empty!(status);
680        assert_translation_non_empty!(commits);
681        assert_translation_non_empty!(branches);
682        assert_translation_non_empty!(files);
683        assert_translation_non_empty!(stash);
684    }
685
686    #[test]
687    fn all_panel_labels_differ_en_ja() {
688        assert_translation_differs!(status);
689        assert_translation_differs!(commits);
690        assert_translation_differs!(branches);
691        assert_translation_differs!(files);
692        assert_translation_differs!(stash);
693    }
694
695    #[test]
696    fn main_panel_titles_non_empty() {
697        assert_translation_non_empty!(main_summary);
698        assert_translation_non_empty!(main_diff);
699        assert_translation_non_empty!(main_branch_info);
700        assert_translation_non_empty!(main_file_diff);
701        assert_translation_non_empty!(main_stash_detail);
702    }
703
704    #[test]
705    fn main_panel_titles_differ() {
706        assert_translation_differs!(main_summary);
707        assert_translation_differs!(main_diff);
708        assert_translation_differs!(main_branch_info);
709        assert_translation_differs!(main_file_diff);
710        assert_translation_differs!(main_stash_detail);
711    }
712
713    #[test]
714    fn status_labels_non_empty() {
715        assert_translation_non_empty!(repo_label);
716        assert_translation_non_empty!(on_label);
717    }
718
719    #[test]
720    fn overlay_titles_non_empty() {
721        assert_translation_non_empty!(author_stats);
722        assert_translation_non_empty!(file_heatmap);
723        assert_translation_non_empty!(activity_timeline);
724        assert_translation_non_empty!(code_ownership);
725        assert_translation_non_empty!(impact_scores);
726        assert_translation_non_empty!(branch_topology);
727        assert_translation_non_empty!(topology);
728        assert_translation_non_empty!(project_health);
729        assert_translation_non_empty!(change_coupling);
730        assert_translation_non_empty!(quality_scores);
731        assert_translation_non_empty!(quick_actions);
732        assert_translation_non_empty!(select_branch);
733        assert_translation_non_empty!(git_status);
734        assert_translation_non_empty!(quick_commit);
735        assert_translation_non_empty!(event_detail);
736        assert_translation_non_empty!(timeline);
737        assert_translation_non_empty!(file_history);
738        assert_translation_non_empty!(blame);
739        assert_translation_non_empty!(stash_overlay);
740        assert_translation_non_empty!(related);
741        assert_translation_non_empty!(save_filter_preset);
742    }
743
744    #[test]
745    fn help_overlay_non_empty() {
746        assert_translation_non_empty!(help);
747        assert_translation_non_empty!(help_adaptive);
748        assert_translation_non_empty!(help_navigation);
749        assert_translation_non_empty!(help_actions);
750        assert_translation_non_empty!(help_dashboard);
751        assert_translation_non_empty!(help_other);
752    }
753
754    #[test]
755    fn help_items_non_empty() {
756        assert_translation_non_empty!(help_move);
757        assert_translation_non_empty!(help_move_down);
758        assert_translation_non_empty!(help_move_up);
759        assert_translation_non_empty!(help_go_top);
760        assert_translation_non_empty!(help_go_bottom);
761        assert_translation_non_empty!(help_page_down);
762        assert_translation_non_empty!(help_page_up);
763        assert_translation_non_empty!(help_next_branch);
764        assert_translation_non_empty!(help_prev_branch);
765        assert_translation_non_empty!(help_show_detail);
766        assert_translation_non_empty!(help_filter);
767        assert_translation_non_empty!(help_branch_select);
768        assert_translation_non_empty!(help_status_view);
769        assert_translation_non_empty!(help_stash_list);
770        assert_translation_non_empty!(help_stash_save);
771        assert_translation_non_empty!(help_switch_panel);
772        assert_translation_non_empty!(help_toggle_focus);
773        assert_translation_non_empty!(help_focus_side_main);
774        assert_translation_non_empty!(help_fetch_remote);
775        assert_translation_non_empty!(help_cycle_view);
776        assert_translation_non_empty!(help_toggle_summary);
777        assert_translation_non_empty!(help_branch_topology);
778        assert_translation_non_empty!(help_toggle_help);
779        assert_translation_non_empty!(help_quit);
780    }
781
782    #[test]
783    fn help_shorthand_non_empty() {
784        assert_translation_non_empty!(help_top_bottom);
785        assert_translation_non_empty!(help_detail);
786        assert_translation_non_empty!(help_branch_status);
787        assert_translation_non_empty!(help_view_summary);
788        assert_translation_non_empty!(help_help_quit);
789        assert_translation_non_empty!(help_up_down);
790        assert_translation_non_empty!(help_top_bottom_full);
791        assert_translation_non_empty!(help_page_dn_up);
792        assert_translation_non_empty!(help_next_prev_branch);
793        assert_translation_non_empty!(help_branch);
794        assert_translation_non_empty!(help_status);
795        assert_translation_non_empty!(help_stash_save_short);
796        assert_translation_non_empty!(help_fetch);
797        assert_translation_non_empty!(help_topology);
798        assert_translation_non_empty!(help_nav_short);
799        assert_translation_non_empty!(help_act_short);
800        assert_translation_non_empty!(help_etc_short);
801        assert_translation_non_empty!(help_scroll_diff_h);
802    }
803
804    #[test]
805    fn footer_hints_non_empty() {
806        assert_translation_non_empty!(footer_health);
807        assert_translation_non_empty!(footer_authors);
808        assert_translation_non_empty!(footer_heatmap);
809        assert_translation_non_empty!(footer_detail);
810        assert_translation_non_empty!(footer_copy_hash);
811        assert_translation_non_empty!(footer_filter);
812        assert_translation_non_empty!(footer_switch);
813        assert_translation_non_empty!(footer_new);
814        assert_translation_non_empty!(footer_delete);
815        assert_translation_non_empty!(footer_diff);
816        assert_translation_non_empty!(footer_stage_all);
817        assert_translation_non_empty!(footer_commit);
818        assert_translation_non_empty!(footer_apply);
819        assert_translation_non_empty!(footer_drop);
820        assert_translation_non_empty!(footer_panel);
821        assert_translation_non_empty!(footer_focus);
822        assert_translation_non_empty!(footer_actions);
823        assert_translation_non_empty!(footer_help);
824        assert_translation_non_empty!(footer_quit);
825        assert_translation_non_empty!(footer_lang);
826    }
827
828    #[test]
829    fn quick_action_labels_non_empty() {
830        assert_translation_non_empty!(quick_risk_summary);
831        assert_translation_non_empty!(quick_review_pack);
832        assert_translation_non_empty!(quick_next_actions);
833        assert_translation_non_empty!(quick_verify);
834        assert_translation_non_empty!(quick_timeline);
835        assert_translation_non_empty!(quick_ownership);
836        assert_translation_non_empty!(quick_impact_score);
837        assert_translation_non_empty!(quick_change_coupling);
838        assert_translation_non_empty!(quick_quality_score);
839        assert_translation_non_empty!(quick_author_stats);
840        assert_translation_non_empty!(quick_heatmap);
841    }
842
843    #[test]
844    fn health_labels_non_empty() {
845        assert_translation_non_empty!(health_overall_score);
846        assert_translation_non_empty!(health_score_breakdown);
847        assert_translation_non_empty!(health_quality);
848        assert_translation_non_empty!(health_test);
849        assert_translation_non_empty!(health_bus_factor);
850        assert_translation_non_empty!(health_tech_debt);
851        assert_translation_non_empty!(health_code_churn);
852        assert_translation_non_empty!(health_commit_cadence);
853        assert_translation_non_empty!(health_alerts);
854        assert_translation_non_empty!(health_commits);
855        assert_translation_non_empty!(health_authors);
856        assert_translation_non_empty!(health_period);
857        assert_translation_non_empty!(health_confidence);
858        assert_translation_non_empty!(health_days);
859        assert_translation_non_empty!(health_score_label);
860    }
861
862    #[test]
863    fn health_scroll_close_quit_non_empty() {
864        for lang in [Language::En, Language::Ja] {
865            let (scroll, close, quit) = lang.health_scroll_close_quit();
866            assert!(!scroll.is_empty());
867            assert!(!close.is_empty());
868            assert!(!quit.is_empty());
869        }
870    }
871
872    #[test]
873    fn confidence_levels_non_empty() {
874        assert_translation_non_empty!(confidence_high);
875        assert_translation_non_empty!(confidence_medium);
876        assert_translation_non_empty!(confidence_low);
877    }
878
879    #[test]
880    fn alert_messages_non_empty() {
881        assert_translation_non_empty!(alert_low_commit_quality);
882        assert_translation_non_empty!(alert_low_test_coverage);
883        assert_translation_non_empty!(alert_high_bus_factor_risk);
884        assert_translation_non_empty!(alert_moderate_bus_factor_risk);
885        assert_translation_non_empty!(alert_high_tech_debt);
886        assert_translation_non_empty!(alert_high_code_churn);
887    }
888
889    #[test]
890    fn handoff_labels_non_empty() {
891        assert_translation_non_empty!(quick_handoff_claude);
892        assert_translation_non_empty!(quick_handoff_codex);
893        assert_translation_non_empty!(quick_handoff_copilot);
894    }
895
896    #[test]
897    fn status_messages_non_empty() {
898        assert_translation_non_empty!(status_fetching);
899        assert_translation_non_empty!(status_fetched);
900        assert_translation_non_empty!(status_fetch_failed);
901        assert_translation_non_empty!(status_fetch_thread_crashed);
902        assert_translation_non_empty!(status_stashed);
903        assert_translation_non_empty!(status_stash_failed);
904        assert_translation_non_empty!(status_copied);
905        assert_translation_non_empty!(status_copy_failed);
906        assert_translation_non_empty!(status_clipboard_unavailable);
907        assert_translation_non_empty!(status_quick_action_failed);
908        assert_translation_non_empty!(status_switched_to);
909        assert_translation_non_empty!(status_checkout_failed);
910        assert_translation_non_empty!(status_deleted_branch);
911        assert_translation_non_empty!(status_delete_failed);
912        assert_translation_non_empty!(status_created_branch);
913        assert_translation_non_empty!(status_create_failed);
914        assert_translation_non_empty!(status_all_staged);
915        assert_translation_non_empty!(status_all_unstaged);
916        assert_translation_non_empty!(status_no_staged_files);
917        assert_translation_non_empty!(status_pulling);
918        assert_translation_non_empty!(status_pulled);
919        assert_translation_non_empty!(status_pull_failed);
920        assert_translation_non_empty!(status_pushed);
921        assert_translation_non_empty!(status_push_failed);
922        assert_translation_non_empty!(status_committed);
923        assert_translation_non_empty!(status_commit_failed);
924        assert_translation_non_empty!(status_compare_failed);
925        assert_translation_non_empty!(status_applied_stash);
926        assert_translation_non_empty!(status_apply_failed);
927        assert_translation_non_empty!(status_popped_stash);
928        assert_translation_non_empty!(status_pop_failed);
929        assert_translation_non_empty!(status_dropped_stash);
930        assert_translation_non_empty!(status_drop_failed);
931        assert_translation_non_empty!(status_error);
932    }
933
934    #[test]
935    fn error_messages_non_empty() {
936        assert_translation_non_empty!(error_not_found);
937        assert_translation_non_empty!(error_permission_denied);
938        assert_translation_non_empty!(error_connection_refused);
939        assert_translation_non_empty!(error_connection_timeout);
940        assert_translation_non_empty!(error_auth_failed);
941        assert_translation_non_empty!(error_merge_conflict);
942        assert_translation_non_empty!(error_dirty_worktree);
943        assert_translation_non_empty!(error_branch_not_found);
944        assert_translation_non_empty!(error_branch_already_exists);
945        assert_translation_non_empty!(error_not_a_repo);
946    }
947
948    #[test]
949    fn cli_messages_non_empty() {
950        assert_translation_non_empty!(cli_analysis_cache_cleared);
951        assert_translation_non_empty!(cli_metrics_reset);
952        assert_translation_non_empty!(cli_help_title);
953        assert_translation_non_empty!(cli_help_usage);
954        assert_translation_non_empty!(cli_help_analysis_options);
955        assert_translation_non_empty!(cli_help_format_options);
956        assert_translation_non_empty!(cli_help_tui_options);
957        assert_translation_non_empty!(cli_help_general_options);
958        assert_translation_non_empty!(cli_help_no_options);
959        assert_translation_non_empty!(cli_help_examples);
960    }
961
962    #[test]
963    fn event_types_non_empty() {
964        assert_translation_non_empty!(event_commit);
965        assert_translation_non_empty!(event_merge);
966        assert_translation_non_empty!(event_branch_switch);
967    }
968
969    #[test]
970    fn detail_labels_non_empty() {
971        assert_translation_non_empty!(detail_type);
972        assert_translation_non_empty!(detail_hash);
973        assert_translation_non_empty!(detail_message);
974        assert_translation_non_empty!(detail_author);
975        assert_translation_non_empty!(detail_time);
976        assert_translation_non_empty!(loading_file_changes);
977        assert_translation_non_empty!(detail_footer);
978        assert_translation_non_empty!(no_changes);
979    }
980
981    #[test]
982    fn commit_overlay_non_empty() {
983        assert_translation_non_empty!(commit_message_label);
984        assert_translation_non_empty!(commit_suggestions);
985        assert_translation_non_empty!(commit_footer_with_suggestions);
986        assert_translation_non_empty!(commit_footer);
987    }
988
989    #[test]
990    fn loading_messages_non_empty() {
991        assert_translation_non_empty!(loading_topology);
992        assert_translation_non_empty!(loading_statistics);
993        assert_translation_non_empty!(loading_heatmap);
994        assert_translation_non_empty!(loading_timeline);
995        assert_translation_non_empty!(loading_history);
996        assert_translation_non_empty!(loading_blame);
997        assert_translation_non_empty!(loading_ownership);
998        assert_translation_non_empty!(loading_impact_scores);
999        assert_translation_non_empty!(loading_change_coupling);
1000        assert_translation_non_empty!(loading_quality_scores);
1001        assert_translation_non_empty!(loading_health);
1002        assert_translation_non_empty!(loading_diff);
1003    }
1004
1005    #[test]
1006    fn table_headers_non_empty() {
1007        assert_translation_non_empty!(header_author);
1008        assert_translation_non_empty!(header_commits);
1009        assert_translation_non_empty!(header_plus_lines);
1010        assert_translation_non_empty!(header_minus_lines);
1011        assert_translation_non_empty!(header_file);
1012        assert_translation_non_empty!(header_changes);
1013        assert_translation_non_empty!(header_heat);
1014        assert_translation_non_empty!(header_hash);
1015        assert_translation_non_empty!(header_date);
1016        assert_translation_non_empty!(header_message);
1017        assert_translation_non_empty!(header_msg_short);
1018        assert_translation_non_empty!(header_score);
1019        assert_translation_non_empty!(header_score_short);
1020        assert_translation_non_empty!(header_path);
1021        assert_translation_non_empty!(header_owner);
1022        assert_translation_non_empty!(header_coupling);
1023        assert_translation_non_empty!(header_coupled_with);
1024    }
1025
1026    #[test]
1027    fn hint_labels_non_empty() {
1028        assert_translation_non_empty!(hint_move);
1029        assert_translation_non_empty!(hint_filter);
1030        assert_translation_non_empty!(hint_close);
1031        assert_translation_non_empty!(hint_checkout);
1032        assert_translation_non_empty!(hint_show_diff);
1033        assert_translation_non_empty!(hint_scroll);
1034        assert_translation_non_empty!(hint_show_commit);
1035        assert_translation_non_empty!(hint_detail);
1036        assert_translation_non_empty!(hint_export);
1037        assert_translation_non_empty!(hint_switch);
1038        assert_translation_non_empty!(hint_save);
1039        assert_translation_non_empty!(hint_cancel);
1040        assert_translation_non_empty!(hint_apply);
1041        assert_translation_non_empty!(hint_pop);
1042        assert_translation_non_empty!(hint_drop);
1043    }
1044
1045    #[test]
1046    fn topology_labels_non_empty() {
1047        assert_translation_non_empty!(topology_issues);
1048        assert_translation_non_empty!(topology_healthy);
1049        assert_translation_non_empty!(topology_branches_count);
1050        assert_translation_non_empty!(topology_stale);
1051        assert_translation_non_empty!(topology_long);
1052        assert_translation_non_empty!(topology_behind);
1053        assert_translation_non_empty!(topology_div);
1054    }
1055
1056    #[test]
1057    fn stash_labels_non_empty() {
1058        assert_translation_non_empty!(stash_list_label);
1059        assert_translation_non_empty!(no_stashes);
1060        assert_translation_non_empty!(no_commits);
1061    }
1062
1063    #[test]
1064    fn related_files_labels_non_empty() {
1065        assert_translation_non_empty!(no_related_files);
1066        assert_translation_non_empty!(no_related_files_short);
1067        assert_translation_non_empty!(files_changed_together);
1068    }
1069
1070    #[test]
1071    fn compare_labels_non_empty() {
1072        assert_translation_non_empty!(compare_ahead);
1073        assert_translation_non_empty!(compare_behind);
1074    }
1075
1076    #[test]
1077    fn preset_labels_non_empty() {
1078        assert_translation_non_empty!(save_filter_title);
1079        assert_translation_non_empty!(filter_label);
1080        assert_translation_non_empty!(select_slot);
1081        assert_translation_non_empty!(name_label);
1082        assert_translation_non_empty!(preset_label);
1083        assert_translation_non_empty!(overwrite);
1084        assert_translation_non_empty!(empty_slot);
1085    }
1086
1087    #[test]
1088    fn dashboard_labels_non_empty() {
1089        assert_translation_non_empty!(no_commit_selected);
1090        assert_translation_non_empty!(repository_summary);
1091        assert_translation_non_empty!(dashboard_name);
1092        assert_translation_non_empty!(dashboard_branch);
1093        assert_translation_non_empty!(dashboard_commits);
1094        assert_translation_non_empty!(dashboard_branches);
1095        assert_translation_non_empty!(dashboard_stashes);
1096        assert_translation_non_empty!(file_changes);
1097        assert_translation_non_empty!(staged_label);
1098        assert_translation_non_empty!(modified_label);
1099        assert_translation_non_empty!(deleted_label);
1100        assert_translation_non_empty!(untracked_label);
1101        assert_translation_non_empty!(project_health_title);
1102        assert_translation_non_empty!(recent_commits);
1103        assert_translation_non_empty!(branch_info);
1104        assert_translation_non_empty!(branch_name_label);
1105        assert_translation_non_empty!(current_branch_label);
1106        assert_translation_non_empty!(gone_label);
1107        assert_translation_non_empty!(status_label);
1108        assert_translation_non_empty!(active_label);
1109        assert_translation_non_empty!(commits_label);
1110        assert_translation_non_empty!(ahead_label);
1111        assert_translation_non_empty!(behind_label);
1112        assert_translation_non_empty!(health_warnings);
1113        assert_translation_non_empty!(no_branch_selected);
1114        assert_translation_non_empty!(branch_recommendations);
1115    }
1116
1117    #[test]
1118    fn file_detail_labels_non_empty() {
1119        assert_translation_non_empty!(file_detail_title);
1120        assert_translation_non_empty!(file_staged_new);
1121        assert_translation_non_empty!(file_staged_modified);
1122        assert_translation_non_empty!(file_staged_deleted);
1123        assert_translation_non_empty!(file_modified);
1124        assert_translation_non_empty!(file_deleted);
1125        assert_translation_non_empty!(file_untracked);
1126        assert_translation_non_empty!(path_label);
1127        assert_translation_non_empty!(diff_label);
1128        assert_translation_non_empty!(no_diff_available);
1129        assert_translation_non_empty!(no_file_selected);
1130    }
1131
1132    #[test]
1133    fn stash_detail_labels_non_empty() {
1134        assert_translation_non_empty!(no_stash_entries);
1135        assert_translation_non_empty!(stash_detail_title);
1136        assert_translation_non_empty!(stash_total);
1137        assert_translation_non_empty!(stash_current);
1138        assert_translation_non_empty!(stash_index);
1139        assert_translation_non_empty!(all_stashes);
1140        assert_translation_non_empty!(stash_entries);
1141        assert_translation_non_empty!(files_changed);
1142        assert_translation_non_empty!(total_label);
1143        assert_translation_non_empty!(peak_label);
1144    }
1145}