#[derive(Debug, Clone)]
pub struct HelpEntry {
pub keys: String,
pub desc: String,
}
#[derive(Debug, Clone)]
pub struct HelpSection {
pub title: String,
pub entries: Vec<HelpEntry>,
}
#[derive(Debug, Clone)]
pub struct Strings {
pub title_old_prefix: String,
pub title_new_prefix: String,
pub title_files_panel: String,
pub title_help: String,
#[allow(dead_code)]
pub status_no_changes: String,
#[allow(dead_code)]
pub status_no_diff: String,
pub status_auto_reloaded: String,
pub status_hint_default: String,
pub status_hint_help_open: String,
pub help_sections: Vec<HelpSection>,
pub help_review_sections: Vec<HelpSection>,
}
impl Strings {
pub fn for_lang(lang: &str) -> Self {
match lang {
"ja" | "ja-JP" | "ja_JP" => Self::japanese(),
_ => Self::english(),
}
}
pub fn english() -> Self {
Self {
title_old_prefix: " [Old] ".into(),
title_new_prefix: " [New] ".into(),
title_files_panel: " [Files] ".into(),
title_help: " [Help] ".into(),
status_no_changes: "no changes".into(),
status_no_diff: "(no diff)".into(),
status_auto_reloaded: "auto-reloaded".into(),
status_hint_default:
"j/k scroll J/K hunk click select+snap = resync n/p file Tab focus ? help q quit"
.into(),
status_hint_help_open: "press ? to close help".into(),
help_sections: vec![
HelpSection {
title: "Navigation".into(),
entries: vec![
e("j / k", "scroll both panes 1:1"),
e("J / K", "jump to next / prev change hunk"),
e("ctrl-d / ctrl-u", "half-page down / up"),
e("g / G", "top / bottom"),
e("n / p", "next / prev file"),
],
},
HelpSection {
title: "Alignment".into(),
entries: vec![
e("click", "select that line; the *other* pane snaps"),
e("[ / ]", "nudge alignment row up / down"),
e("wheel", "scroll pane under pointer (diff only)"),
e("=", "re-snap non-anchor pane to alignment row"),
],
},
HelpSection {
title: "Display".into(),
entries: vec![
e("Tab", "toggle focus (Files / Diff)"),
e("F", "show / hide the files panel"),
e("r", "manual reload"),
],
},
HelpSection {
title: "App".into(),
entries: vec![
e("? / Esc", "toggle / close this help"),
e("q", "quit"),
],
},
],
help_review_sections: vec![HelpSection {
title: "Review".into(),
entries: vec![
e("c", "open comment modal at cursor row"),
e("d", "list buffered drafts (Enter edit · x delete)"),
e("S", "open submit modal (verdict + body)"),
e("ctrl-s", "save draft (in comment) / submit (in submit modal)"),
e("Tab", "(in submit) switch verdict ↔ body focus"),
e("a / c / r", "(in submit · verdict) Approve / Comment / Request changes"),
e("Esc", "close modal without saving"),
],
}],
}
}
pub fn japanese() -> Self {
Self {
title_old_prefix: " [旧] ".into(),
title_new_prefix: " [新] ".into(),
title_files_panel: " [ファイル] ".into(),
title_help: " [ヘルプ] ".into(),
status_no_changes: "差分なし".into(),
status_no_diff: "(差分なし)".into(),
status_auto_reloaded: "自動再読込".into(),
status_hint_default:
"j/k スクロール J/K ハンク クリック選択 = 再同期 n/p ファイル Tab フォーカス ? ヘルプ q 終了"
.into(),
status_hint_help_open: "? でヘルプを閉じる".into(),
help_sections: vec![
HelpSection {
title: "ナビゲーション".into(),
entries: vec![
e("j / k", "両ペインを 1:1 でスクロール"),
e("J / K", "次 / 前の変更ブロックへ"),
e("ctrl-d / ctrl-u", "半ページ 上 / 下"),
e("g / G", "先頭 / 末尾"),
e("n / p", "次 / 前のファイル"),
],
},
HelpSection {
title: "整列".into(),
entries: vec![
e("click", "その行を選択 — 反対ペインがスナップ"),
e("[ / ]", "整列行を 1 行上 / 下へ"),
e("wheel", "ポインタ下のペインをスクロール (Diff のみ)"),
e("=", "非アンカー側を整列行に再同期"),
],
},
HelpSection {
title: "表示".into(),
entries: vec![
e("Tab", "フォーカス切替 (ファイル / Diff)"),
e("F", "ファイルパネルの表示切替"),
e("r", "手動再読込"),
],
},
HelpSection {
title: "アプリ".into(),
entries: vec![
e("? / Esc", "ヘルプの開閉"),
e("q", "終了"),
],
},
],
help_review_sections: vec![HelpSection {
title: "レビュー".into(),
entries: vec![
e("c", "カーソル行にコメントモーダルを開く"),
e("d", "ドラフト一覧 (Enter で編集・x で削除)"),
e("S", "提出モーダルを開く (verdict + 本文)"),
e("ctrl-s", "コメント保存 / 提出モーダルでは送信"),
e("Tab", "提出モーダルで verdict ↔ 本文 を切替"),
e("a / c / r", "提出 verdict 切替 (Approve / Comment / Request changes)"),
e("Esc", "モーダルを閉じる (保存しない)"),
],
}],
}
}
}
fn e(keys: &str, desc: &str) -> HelpEntry {
HelpEntry {
keys: keys.into(),
desc: desc.into(),
}
}