#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Lang {
En,
Jp,
}
impl Lang {
pub fn parse(s: &str) -> Self {
match s.trim().to_ascii_lowercase().as_str() {
"jp" | "ja" | "japanese" | "日本語" => Self::Jp,
_ => Self::En, }
}
pub fn resolve(s: &str) -> Self {
match s.trim().to_ascii_lowercase().as_str() {
"" | "auto" | "system" => Self::from_os(),
_ => Self::parse(s),
}
}
#[cfg(test)]
fn from_os() -> Self {
Self::En
}
#[cfg(not(test))]
fn from_os() -> Self {
if let Some(tag) = macos_preferred_language() {
return Self::from_lang_tag(&tag);
}
for key in ["LC_ALL", "LC_MESSAGES", "LANG"] {
if let Ok(v) = std::env::var(key) {
let v = v.trim();
if !v.is_empty() && v != "C" && v != "POSIX" {
return Self::from_lang_tag(v);
}
}
}
Self::En
}
fn from_lang_tag(s: &str) -> Self {
if s.trim().to_ascii_lowercase().starts_with("ja") {
Self::Jp
} else {
Self::En
}
}
}
#[cfg(not(test))]
fn macos_preferred_language() -> Option<String> {
let out = std::process::Command::new("defaults")
.args(["read", "-g", "AppleLanguages"])
.output()
.ok()?;
if !out.status.success() {
return None;
}
parse_apple_languages(&String::from_utf8_lossy(&out.stdout))
}
fn parse_apple_languages(text: &str) -> Option<String> {
text.lines()
.map(|l| l.trim().trim_end_matches(','))
.find_map(|l| l.strip_prefix('"').and_then(|s| s.strip_suffix('"')))
.map(|s| s.to_string())
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Msg {
GitNoBranchesItem,
GitNoChangesItem,
GitNoCommitsItem,
BmTitle,
DlgConfirmTitle,
DlgDropTitle,
HelpTitle,
InfoTitle,
DlgInputTitle,
DlgRenamePreviewTitle,
DlgDeletePermanentHint,
DlgForceDeleteHint,
BmEmpty,
GitNoChanges,
BatchRename,
GitCommitWorktreeDetail,
CommitMessage,
Committed,
Copied,
Create,
Created,
CreatedBranch,
StScrollHintCtrl,
CutDone,
DeleteTarget,
DeleteBranch,
DeletedBranch,
DeletedPermanently,
DiscardChangesTo,
Discarded,
StApplyClearHint,
StCommitHint,
StCreateHint,
StRenamePreviewHint,
StRenameHint,
StSearchHint,
TreeFile,
GitBranchesLabel,
GitChangesLabel,
TreeGitChangesHub,
GitGraphLabel,
GitLogLabel,
TreeGitStatus,
BmGlobal,
HelpGlobal,
BmLocal,
InfoModified,
Moved,
MovedToTrash,
NewBranch,
Pasted,
InfoPerm,
PreviewGitDiff,
PreviewImage,
PreviewTextMarkdown,
Rename,
Renamed,
TreeSelection,
InfoSize,
StPagerSpaceHint,
Staged,
StagedAll,
SwitchedTo,
HelpTabs,
InfoTarget,
TreeSection,
InfoType,
UncommittedChanges,
Unstaged,
UnstagedAll,
Highlighting,
StSortHint,
StPathAbs,
TreeAddedStaged,
AlreadyAtStartDir,
AlreadyRoot,
AnchorReset,
TreeAnchorRoot,
GitBack,
BackToGitView,
BackToChanges,
BackToTree,
TreeBookmarkHint,
PreviewBookmarkHint,
BookmarkTargetMissing,
Bookmarked,
GitBranches,
DlgCopyKey,
StCopyMoveHint,
CantCloseLastTab,
Canceled,
CannotDeleteCurrentBranch,
CannotEditDirectory,
CannotPasteIntoSelf,
GitCheckout,
ClipboardEmpty,
GitCloseView,
CloseTab,
GitCommit,
GitCommitDetail,
CopiedPrefix,
CopyHint,
CopyFailed,
CutHint,
CyclePathStyle,
GitDelete,
TreeDeleted,
GitDetail,
GitDiffAll,
TreeDiffFile,
DiffAuto,
DiffSideBySide,
DiffUnified,
InfoDirectory,
GitDiscardFile,
DiscardWholeFile,
TreeDragDrop,
TreeDropFiles,
DroppedItems,
EditExternal,
EditExternalEnv,
EditorFailed,
EnterDirectory,
Etc,
ExpandInPlace,
GitExternalTool,
Failed,
InfoFile,
GitFileDiff,
TreeFileInfo,
TreeFilter,
GitFilterByName,
FocusMdLink,
MdTaskToggleHelp,
GitToolFailed,
GlobalApp,
HScroll,
GitHScrollEnds,
StCloseHint,
InfoClose,
AnchorsUnsupported,
InvalidMarkKey,
Items,
InfoItems,
VisualOpsHint,
BranchesNavHint,
GitNavDetailHint,
GitNavDetailCommitHint,
GraphBaseSet,
GraphBaseCleared,
GraphBaseNeedsCommit,
GraphLegendHidden,
GraphPickerTitle,
GraphPickerFooter,
GraphPickerHeadLocked,
DiffScrollHint,
DiffScrollDiscardHint,
HelpJumpTab,
JustNow,
Keymap,
GitLayout,
LineStartEnd,
Loading,
Local,
GitLogGraph,
DlgMove,
MarkHint,
Match,
MessageEmpty,
TreeModified,
GitMove,
GitMoveCommit,
TreeMoveUpDown,
DlgCancel,
NameEmpty,
GitNewBranch,
HelpNewTab,
NoBookmark,
NoBranches,
NoChanges,
NoCommits,
NoCopyTarget,
NoFileToEdit,
NoMatch,
NoTarget,
NotAFile,
NotAGitRepo,
NotFound,
NothingStaged,
OpenFailed,
OpenLinkHint,
Opened,
OperationFailed,
PanHint,
PathLabel,
PrevNextTab,
Quit,
QuitOrCloseTab,
Refresh,
RelLabel,
TreeStatusRenamed,
ResetRoot,
ResetFit,
Root,
StGitHubKeys,
Scroll,
Scroll10Lines,
SearchHint,
SearchCodeTextOnly,
SelLabel,
SortHint,
StageHint,
Symlink,
ToParent,
ToggleHidden,
ToggleOne,
ToggleHelp,
TopBottom,
TrailingSlashFolder,
UnstageHint,
Untracked,
VisualRangeHint,
DlgTrash,
DlgApply,
DlgDeleteSafe,
DlgYesNo,
StTrashDelete,
StApply,
StDeleteForce,
Zoom,
BmActions,
Empty,
StBatchRename,
StBookmarks,
StBranch,
StChanges,
StCommit,
StCommitDiff,
StCreate,
StDelete,
StDiff,
StDrop,
QuitConfirm,
StQuit,
StQuitHint,
StFilter,
StGit,
StGraph,
StImage,
StInfo,
StLog,
StMark,
StPreview,
StRename,
StRenameConfirm,
StSearch,
StSort,
StTree,
StVisual,
HintAnchor,
WkCreate,
AgoDays,
WkDelete,
HintDiff,
HintEdit,
HintEnds,
HintEnter,
HintFileOps,
HintFilter,
HintFit,
WkFull,
HintGit,
HintBookmarks,
HintHelp,
HintHidden,
AgoHr,
HintHscroll,
HintInfo,
HintLineEnds,
HintLink,
HintMark,
HintToggle,
BusyGitScan,
BusyMedia,
BusyHighlight,
BusyImages,
TaskFileChanged,
AgoMin,
AgoMonths,
WkName,
HintOpen,
HintPage,
HintPan,
WkParent,
WkPaste,
HintPath,
HintPick,
HintQuit,
HintCloseTab,
HintRawSource,
HintRendered,
MdRawToggleHelp,
WkRelative,
WkRename,
HintSearch,
HintSort,
HintTab,
HintUp,
HintVisual,
AgoYears,
WkCopyPathTitle,
StTable,
PreviewTable,
WkTableCopyTitle,
WkCell,
WkRow,
WkColumn,
HintCell,
TableMoveHelp,
TableColsHelp,
PreviewVisualHint,
PreviewVisualLineHint,
PreviewSelectHelp,
StVisualLine,
WkAtRef,
StChangedOnly,
ChangedFilterHint,
NoChangedFiles,
JumpTargetHidden,
StFollow,
FollowOn,
FollowOff,
ChangedFilterHelp,
JumpChangeHelp,
FollowHelp,
AtRefHelp,
#[cfg_attr(not(feature = "git"), allow(dead_code))]
WkGitCopyTitle,
#[cfg_attr(not(feature = "git"), allow(dead_code))]
WkShortHash,
#[cfg_attr(not(feature = "git"), allow(dead_code))]
WkFullHash,
#[cfg_attr(not(feature = "git"), allow(dead_code))]
WkSubject,
#[cfg_attr(not(feature = "git"), allow(dead_code))]
WkMessage,
#[cfg_attr(not(feature = "git"), allow(dead_code))]
WkAuthor,
#[cfg_attr(not(feature = "git"), allow(dead_code))]
WkDate,
#[cfg_attr(not(feature = "git"), allow(dead_code))]
NoCommitToCopy,
ImageUnsupported,
PreviewTruncated,
VideoThumbUnavailable,
PdfPreviewUnavailable,
}
fn en(msg: Msg) -> &'static str {
use Msg::*;
match msg {
GitNoBranchesItem => " (no branches)",
GitNoChangesItem => " (no changes)",
GitNoCommitsItem => " (no commits)",
BmTitle => " Bookmarks ",
DlgConfirmTitle => " Confirm ",
DlgDropTitle => " Drop ",
HelpTitle => " Help (?/Esc to close, j/k to scroll) ",
InfoTitle => " Info ",
DlgInputTitle => " Input ",
DlgRenamePreviewTitle => " Rename preview ",
DlgDeletePermanentHint => "! = Delete permanently (no undo)",
DlgForceDeleteHint => "! = force delete (-D)",
BmEmpty => "(no bookmarks)",
GitNoChanges => "(no changes)",
BatchRename => "Batch rename",
GitCommitWorktreeDetail => "Commit / worktree detail",
CommitMessage => "Commit message",
Committed => "Committed",
Copied => "Copied",
Create => "Create",
Created => "Created",
CreatedBranch => "Created branch",
StScrollHintCtrl => "Ctrl-f/Ctrl-b page, Ctrl-d/Ctrl-u half (PgDn/Up too)",
CutDone => "Cut",
DeleteTarget => "Delete",
DeleteBranch => "Delete branch",
DeletedBranch => "Deleted branch",
DeletedPermanently => "Deleted permanently",
DiscardChangesTo => "Discard changes to",
Discarded => "Discarded",
StApplyClearHint => "Enter:apply Esc:clear",
StCommitHint => "Enter:commit Esc:cancel (uses staged index)",
StCreateHint => "Enter:create Esc:cancel (trailing / = folder)",
StRenamePreviewHint => "Enter:preview Esc:cancel {n} {n:0W} {name} {ext}",
StRenameHint => "Enter:rename Esc:cancel ←→ move Del erase",
StSearchHint => "Enter:search Esc:cancel",
TreeFile => "File",
GitBranchesLabel => "Git branches (b)",
GitChangesLabel => "Git changes (o)",
TreeGitChangesHub => "Git changes hub (stage/unstage/discard/commit; l=log g=graph b=branch)",
GitGraphLabel => "Git graph (g)",
GitLogLabel => "Git log (l)",
TreeGitStatus => "Git status (row markers)",
BmGlobal => "Global",
HelpGlobal => "Global",
BmLocal => "Local",
InfoModified => "Modified",
Moved => "Moved",
MovedToTrash => "Moved to Trash",
NewBranch => "New branch",
Pasted => "Pasted",
InfoPerm => "Perm",
PreviewGitDiff => "Preview: git diff",
PreviewImage => "Preview: image",
PreviewTextMarkdown => "Preview: text / Markdown",
Rename => "Rename",
Renamed => "Renamed",
TreeSelection => "Selection",
InfoSize => "Size",
StPagerSpaceHint => "Space/b page, d/u half (PgDn/Up too)",
Staged => "Staged",
StagedAll => "Staged all",
SwitchedTo => "Switched to",
HelpTabs => "Tabs",
InfoTarget => "Target",
TreeSection => "Tree",
InfoType => "Type",
UncommittedChanges => "Uncommitted changes",
Unstaged => "Unstaged",
UnstagedAll => "Unstaged all",
Highlighting => "[highlighting…] ",
StSortHint => "[n]ame [s]ize [m]od [e]xt [r]everse [.]dirs-1st Esc",
StPathAbs => "abs",
TreeAddedStaged => "added (staged)",
AlreadyAtStartDir => "already at start dir",
AlreadyRoot => "already root",
AnchorReset => "anchor reset",
TreeAnchorRoot => "anchor root at current location",
GitBack => "back",
BackToGitView => "back to Git view",
BackToChanges => "back to changes",
BackToTree => "back to tree",
TreeBookmarkHint => "bookmark cursor item: m=set, '=list (press a-z/A-Z to jump: file→preview/dir→cd)",
PreviewBookmarkHint => "bookmark this file (a-z local / A-Z global) / open bookmark list",
BookmarkTargetMissing => "bookmark target missing",
Bookmarked => "bookmarked",
GitBranches => "branches",
DlgCopyKey => "c = copy",
StCopyMoveHint => "c:copy m:move n/Esc:cancel",
CantCloseLastTab => "can't close the last tab",
Canceled => "canceled",
CannotDeleteCurrentBranch => "cannot delete the current branch",
CannotEditDirectory => "cannot edit a directory",
CannotPasteIntoSelf => "cannot paste into itself",
GitCheckout => "checkout",
ClipboardEmpty => "clipboard is empty",
GitCloseView => "close git view",
CloseTab => "close tab",
GitCommit => "commit (staged)",
GitCommitDetail => "commit detail (diff)",
CopiedPrefix => "copied: ",
CopyHint => "copy",
CopyFailed => "copy failed: ",
CutHint => "cut",
CyclePathStyle => "cycle path style (rel/~/abs)",
GitDelete => "delete (y=-d / !=-D)",
TreeDeleted => "deleted",
GitDetail => "detail (commit diff / worktree diff)",
GitDiffAll => "diff of all changes (worktree)",
TreeDiffFile => "diff of cursor file (git-changed)",
DiffAuto => "diff: auto",
DiffSideBySide => "diff: side-by-side",
DiffUnified => "diff: unified",
InfoDirectory => "directory",
GitDiscardFile => "discard file (confirm)",
DiscardWholeFile => "discard whole file (confirm)",
TreeDragDrop => "drag & drop",
TreeDropFiles => "drop file(s) → copy/move into cursor dir",
DroppedItems => "dropped item(s)",
EditExternal => "edit in external editor",
EditExternalEnv => "edit in external editor ($EDITOR / config)",
EditorFailed => "editor failed: ",
EnterDirectory => "enter directory / open file",
Etc => "etc.",
ExpandInPlace => "expand in place / open file",
GitExternalTool => "external git tool (lazygit)",
Failed => "failed",
InfoFile => "file",
GitFileDiff => "file diff",
TreeFileInfo => "file info (size/modified/permissions)",
TreeFilter => "filter / recursive find (Esc to clear)",
GitFilterByName => "filter by name",
FocusMdLink => "focus md link / checkbox",
MdTaskToggleHelp => "toggle focused checkbox (writes to the file)",
GitToolFailed => "git tool failed: ",
GlobalApp => "global",
HScroll => "horizontal scroll",
GitHScrollEnds => "hscroll / line ends",
StCloseHint => "i / Esc / q : close",
InfoClose => "i / Esc / q close",
AnchorsUnsupported => "in-page anchors are not supported",
InvalidMarkKey => "invalid mark key",
Items => "items",
InfoItems => "items",
VisualOpsHint => "j/k:extend a:this-dir A:all v:commit Space:ops(d/r/c/x) Esc:cancel",
BranchesNavHint => "j/k:nav Enter:checkout n:new d:delete /:search q/Esc:back",
GitNavDetailHint => "j/k:nav Enter:detail q/Esc:back",
GitNavDetailCommitHint => {
"j/k:nav Enter:detail s:base x:base off b:branches q/Esc:back"
}
GraphBaseSet => "base: ",
GraphBaseCleared => "base cleared",
GraphBaseNeedsCommit => "select a commit to set as base",
GraphLegendHidden => "hidden",
GraphPickerTitle => "Graph branches",
GraphPickerFooter => {
"Space:toggle J/K:reorder a:all n:current only Enter:apply q:cancel"
}
GraphPickerHeadLocked => "current branch (HEAD) is always shown",
DiffScrollHint => "j/k:scroll h/l:hscroll s:unified/split/auto g/G:ends q/Esc:back",
DiffScrollDiscardHint => "j/k:scroll n/N:next/prev file h/l:hscroll s:unified/split/auto x:discard q/Esc:back",
HelpJumpTab => "jump to tab by number",
JustNow => "just now",
Keymap => "keymap",
GitLayout => "layout: unified / split / auto",
LineStartEnd => "line start / line end (horizontal)",
Loading => "loading…",
Local => "local",
GitLogGraph => "log / graph",
DlgMove => "m = move",
MarkHint => "mark ▸ a-z = local / A-Z = global Esc",
Match => "match",
MessageEmpty => "message is empty",
TreeModified => "modified",
GitMove => "move",
GitMoveCommit => "move (commit / uncommitted)",
TreeMoveUpDown => "move up/down",
DlgCancel => "n / Esc = cancel",
NameEmpty => "name is empty",
GitNewBranch => "new branch",
HelpNewTab => "new tab",
NoBookmark => "no bookmark",
NoBranches => "no branches",
NoChanges => "no changes",
NoCommits => "no commits",
NoCopyTarget => "no copy target",
NoFileToEdit => "no file to edit",
NoMatch => "no match",
NoTarget => "no target",
NotAFile => "not a file",
NotAGitRepo => "not a git repo",
NotFound => "not found: ",
NothingStaged => "nothing staged",
OpenFailed => "open failed: ",
OpenLinkHint => "open link (URL=browser / local=konoma) / toggle checkbox",
Opened => "opened: ",
OperationFailed => "operation failed: ",
PanHint => "pan (when zoomed/clipped)",
PathLabel => "path:",
PrevNextTab => "prev / next tab",
Quit => "quit (back to tree in preview)",
QuitOrCloseTab => "close tab, or quit if it is the last one (back to tree in preview)",
Refresh => "refresh listing & git status",
RelLabel => "rel",
TreeStatusRenamed => "renamed / typechange / conflict",
ResetRoot => "reset root to start directory",
ResetFit => "reset to fit",
Root => "root",
StGitHubKeys => "s/S:stage(all) u/U:unstage(all) x:discard c:commit Enter:diff d:diff-all l:log g:graph b:branch !:tool q:close",
Scroll => "scroll",
Scroll10Lines => "scroll 10 lines",
SearchHint => "search (code/text); next / prev match",
SearchCodeTextOnly => "search: code/text preview only",
SelLabel => "sel",
SortHint => "sort: name/size/mod/ext, r=reverse, .=dirs first",
StageHint => "stage / stage all",
Symlink => "symlink",
ToParent => "to parent directory",
ToggleHidden => "toggle hidden files",
ToggleOne => "toggle one item (pick scattered), Esc = clear selection",
ToggleHelp => "toggle this help",
TopBottom => "top / bottom",
TrailingSlashFolder => "trailing / = folder",
UnstageHint => "unstage / unstage all",
Untracked => "untracked",
VisualRangeHint => "visual range: j/k extend, v/Esc commit, a=this dir / A=all, Space=ops",
DlgTrash => "y = Trash (recoverable)",
DlgApply => "y = apply Esc = cancel j/k = scroll",
DlgDeleteSafe => "y = delete (safe, -d)",
DlgYesNo => "y = yes n / Esc = no",
StTrashDelete => "y:Trash !:delete permanently n/Esc:cancel",
StApply => "y:apply Esc:cancel j/k:scroll",
StDeleteForce => "y:delete(-d) !:force(-D) n/Esc:cancel",
Zoom => "zoom",
BmActions => "a-Z jump ↵ open ^E edit ^D delete q close",
Empty => "",
StBatchRename => "BATCH RENAME",
StBookmarks => "BOOKMARKS",
StBranch => "BRANCH",
StChanges => "CHANGES",
StCommit => "COMMIT",
StCommitDiff => "COMMIT DIFF",
StCreate => "CREATE",
StDelete => "DELETE",
StDiff => "DIFF",
StDrop => "DROP",
QuitConfirm => "Quit konoma?",
StQuit => "QUIT",
StQuitHint => "y / q / Enter = quit n / Esc = cancel",
StFilter => "FILTER",
StGit => "GIT",
StGraph => "GRAPH",
StImage => "IMAGE",
StInfo => "INFO",
StLog => "LOG",
StMark => "MARK",
StPreview => "PREVIEW",
StTable => "TABLE",
PreviewTable => "CSV / TSV table",
WkTableCopyTitle => "Copy from table",
WkCell => "cell",
WkRow => "row",
WkColumn => "column",
HintCell => "cell",
TableMoveHelp => "move between cells",
TableColsHelp => "first / last column",
PreviewVisualHint => "h / j / k / l: extend y: copy Y: @ref v / Esc: cancel",
PreviewVisualLineHint => "j / k / g / G: extend y: copy lines Y: @ref V / Esc: cancel",
PreviewSelectHelp => "v: select a character range V: select whole lines (copy with y)",
StVisualLine => "V-LINE",
WkAtRef => "@ref",
StChangedOnly => "CHANGED",
ChangedFilterHint => "Enter: preview n / N: next / prev C / h: all files",
NoChangedFiles => "no changed files",
JumpTargetHidden => "target is inside a hidden directory (`.` to show hidden files)",
StFollow => "FOLLOW",
FollowOn => "follow: on (any key stops)",
FollowOff => "follow: off",
ChangedFilterHelp => "show changed files only (git)",
JumpChangeHelp => "jump to next / previous changed file",
FollowHelp => "follow mode: auto-preview externally changed files",
AtRefHelp => "copy @path#L reference of caret / selection",
StRename => "RENAME",
StRenameConfirm => "RENAME?",
StSearch => "SEARCH",
StSort => "SORT",
StTree => "TREE",
StVisual => "VISUAL",
HintAnchor => "anchor",
WkCreate => "create",
AgoDays => "days ago",
WkDelete => "delete",
HintDiff => "diff",
HintEdit => "edit",
HintEnds => "ends",
HintEnter => "enter",
HintFileOps => "file ops",
HintFilter => "filter",
HintFit => "fit",
WkFull => "full",
HintGit => "git",
HintBookmarks => "bookmarks",
HintHelp => "help",
HintHidden => "hidden",
AgoHr => "hr ago",
HintHscroll => "hscroll",
HintInfo => "info",
HintLineEnds => "line ends",
HintLink => "link",
HintMark => "mark",
HintToggle => "toggle",
BusyGitScan => "git scan",
BusyMedia => "loading media",
BusyHighlight => "highlighting",
BusyImages => "loading images",
TaskFileChanged => "file changed on disk — reloaded (toggle cancelled)",
AgoMin => "min ago",
AgoMonths => "months ago",
WkName => "name",
HintOpen => "open",
HintPage => "page",
HintPan => "pan",
WkParent => "parent",
WkPaste => "paste",
HintPath => "path",
HintPick => "pick",
HintQuit => "quit",
HintCloseTab => "close tab",
HintRawSource => "raw source",
HintRendered => "rendered",
MdRawToggleHelp => "toggle rendered / raw source (raw is selectable)",
WkRelative => "relative",
WkRename => "rename",
HintSearch => "search",
HintSort => "sort",
HintTab => "tab",
HintUp => "up",
HintVisual => "visual",
AgoYears => "years ago",
WkCopyPathTitle => "Copy path",
WkGitCopyTitle => "Copy commit",
WkShortHash => "short hash",
WkFullHash => "full hash",
WkSubject => "subject",
WkMessage => "message",
WkAuthor => "author",
WkDate => "date",
NoCommitToCopy => "no commit to copy",
ImageUnsupported => {
"[image] cannot display image in this terminal, or failed to load"
}
PreviewTruncated => "\n\n— (truncated: display limit reached) —",
VideoThumbUnavailable => {
"[video] no thumbnail — install ffmpegthumbnailer or ffmpeg (and use a kitty-graphics terminal)"
}
PdfPreviewUnavailable => {
"[pdf] cannot render — install poppler (pdftoppm), or use a kitty-graphics terminal"
}
}
}
fn jp(msg: Msg) -> &'static str {
use Msg::*;
match msg {
GitNoBranchesItem => " (ブランチなし)",
GitNoChangesItem => " (変更なし)",
GitNoCommitsItem => " (コミットなし)",
BmTitle => " ブックマーク ",
DlgConfirmTitle => " 確認 ",
DlgDropTitle => " ドロップ ",
HelpTitle => " ヘルプ (?/Esc で閉じる, j/k スクロール) ",
InfoTitle => " 情報 ",
DlgInputTitle => " 入力 ",
DlgRenamePreviewTitle => " リネーム確認 ",
DlgDeletePermanentHint => "! = 完全に削除 (復元不可)",
DlgForceDeleteHint => "! = 強制削除 (-D)",
BmEmpty => "(ブックマーク無し)",
GitNoChanges => "(変更なし)",
BatchRename => "一括リネーム",
GitCommitWorktreeDetail => "コミット / 作業ツリー詳細",
CommitMessage => "コミットメッセージ",
Committed => "コミットしました",
Copied => "コピー",
Create => "作成",
Created => "作成",
CreatedBranch => "ブランチ作成",
StScrollHintCtrl => "Ctrl-f/Ctrl-b ページ, Ctrl-d/Ctrl-u ハーフ (PgDn/Up 共通)",
CutDone => "カット",
DeleteTarget => "削除対象",
DeleteBranch => "ブランチ削除",
DeletedBranch => "ブランチ削除",
DeletedPermanently => "完全に削除しました",
DiscardChangesTo => "変更を破棄しますか:",
Discarded => "破棄",
StApplyClearHint => "Enter:確定 Esc:解除",
StCommitHint => "Enter:コミット Esc:取消 (ステージ済みを使用)",
StCreateHint => "Enter:作成 Esc:取消 (末尾 / でフォルダ)",
StRenamePreviewHint => "Enter:確認へ Esc:取消 {n} {n:0W} {name} {ext}",
StRenameHint => "Enter:リネーム Esc:取消 ←→ 移動 Del 削除",
StSearchHint => "Enter:検索 Esc:解除",
TreeFile => "ファイル管理",
GitBranchesLabel => "Git ブランチ (b)",
GitChangesLabel => "Git 変更ハブ (o)",
TreeGitChangesHub => "Git 変更ハブ (ステージ/解除/破棄/コミット; l=ログ g=グラフ b=ブランチ)",
GitGraphLabel => "Git グラフ (g)",
GitLogLabel => "Git ログ (l)",
TreeGitStatus => "Git 状態 (行頭マーカー)",
BmGlobal => "グローバル",
HelpGlobal => "共通 (Global)",
BmLocal => "ローカル",
InfoModified => "更新",
Moved => "移動",
MovedToTrash => "ゴミ箱へ送りました",
NewBranch => "新規ブランチ",
Pasted => "ペースト",
InfoPerm => "権限",
PreviewGitDiff => "プレビュー: git 差分",
PreviewImage => "プレビュー: 画像",
PreviewTextMarkdown => "プレビュー: テキスト/Markdown",
Rename => "リネーム",
Renamed => "リネーム",
TreeSelection => "選択",
InfoSize => "サイズ",
StPagerSpaceHint => "Space/b ページ, d/u ハーフ (PgDn/Up 共通)",
Staged => "ステージ",
StagedAll => "全てステージ",
SwitchedTo => "切替",
HelpTabs => "タブ (Tabs)",
InfoTarget => "リンク先",
TreeSection => "ツリー (Tree)",
InfoType => "種別",
UncommittedChanges => "未コミットの変更",
Unstaged => "アンステージ",
UnstagedAll => "全てアンステージ",
Highlighting => "[ハイライト中…] ",
StSortHint => "[n]名前 [s]サイズ [m]更新 [e]拡張子 [r]反転 [.]フォルダ先頭 Esc",
StPathAbs => "絶対",
TreeAddedStaged => "追加(ステージ済)",
AlreadyAtStartDir => "既に起動位置が基準",
AlreadyRoot => "既にルート",
AnchorReset => "アンカーを起動位置へ",
TreeAnchorRoot => "現在地をルートに固定 (アンカー)",
GitBack => "戻る",
BackToGitView => "Git ビューへ戻る",
BackToChanges => "変更ハブへ戻る",
BackToTree => "ツリーへ戻る",
TreeBookmarkHint => "ブックマーク(カーソル位置): m=登録, '=一覧(英字キーで直ジャンプ: ファイル→preview/dir→移動)",
PreviewBookmarkHint => "表示中ファイルをブックマーク(a-z ローカル/A-Z グローバル) / 一覧を開く",
BookmarkTargetMissing => "ブックマーク先が無い",
Bookmarked => "登録",
GitBranches => "ブランチ",
DlgCopyKey => "c = コピー",
StCopyMoveHint => "c:コピー m:移動 n/Esc:取消",
CantCloseLastTab => "最後のタブは閉じられません",
Canceled => "取消",
CannotDeleteCurrentBranch => "現在のブランチは削除できません",
CannotEditDirectory => "ディレクトリは編集できません",
CannotPasteIntoSelf => "自分自身へは貼れません",
GitCheckout => "切替",
ClipboardEmpty => "クリップボードが空",
GitCloseView => "Git ビューを閉じる",
CloseTab => "タブを閉じる",
GitCommit => "コミット (ステージ済み)",
GitCommitDetail => "コミット詳細 (差分)",
CopiedPrefix => "コピー: ",
CopyHint => "コピー",
CopyFailed => "コピー失敗: ",
CutHint => "カット",
CyclePathStyle => "パス表示の切替 (相対/~/絶対)",
GitDelete => "削除 (y=-d / !=-D)",
TreeDeleted => "削除",
GitDetail => "詳細 (コミット差分 / 作業ツリー差分)",
GitDiffAll => "全変更まとめ diff (作業ツリー)",
TreeDiffFile => "カーソルの変更ファイルの diff を直接開く",
DiffAuto => "diff: 自動(幅で縦/横)",
DiffSideBySide => "diff: 横並び",
DiffUnified => "diff: 縦(unified)",
InfoDirectory => "ディレクトリ",
GitDiscardFile => "ファイル破棄 (確認)",
DiscardWholeFile => "ファイル全体を破棄(確認)",
TreeDragDrop => "ドラッグ&ドロップ",
TreeDropFiles => "ファイルをドロップ → カーソル位置へコピー/移動",
DroppedItems => "個をドロップ",
EditExternal => "外部エディタで編集",
EditExternalEnv => "外部エディタで編集 ($EDITOR / 設定)",
EditorFailed => "エディタ起動失敗: ",
EnterDirectory => "ディレクトリへ降りる / ファイルを開く",
Etc => "他",
ExpandInPlace => "その場で展開 / ファイルを開く",
GitExternalTool => "外部 git ツール (lazygit)",
Failed => "失敗",
InfoFile => "ファイル",
GitFileDiff => "ファイル差分",
TreeFileInfo => "ファイル情報 (サイズ/更新/権限)",
TreeFilter => "絞り込み / 再帰検索 (Esc で解除)",
GitFilterByName => "名前で絞り込み",
FocusMdLink => "Markdown リンク/チェックボックスをフォーカス",
MdTaskToggleHelp => "フォーカス中のチェックボックスをトグル(ファイルに書込み)",
GitToolFailed => "git ツール起動失敗: ",
GlobalApp => "グローバル",
HScroll => "横スクロール(非折返し時)",
GitHScrollEnds => "横スクロール / 行頭・行末",
StCloseHint => "i / Esc / q : 閉じる",
InfoClose => "i / Esc / q 閉じる",
AnchorsUnsupported => "ページ内アンカーは未対応です",
InvalidMarkKey => "無効なマークキー",
Items => "件",
InfoItems => "項目",
VisualOpsHint => "j/k:範囲 a:同階層 A:全部 v:確定 Space:操作(d/r/c/x) Esc:取消",
BranchesNavHint => "j/k:移動 Enter:切替 n:新規 d:削除 /:検索 q/Esc:戻る",
GitNavDetailHint => "j/k:移動 Enter:詳細 q/Esc:戻る",
GitNavDetailCommitHint => "j/k:移動 Enter:詳細 s:基準 x:基準解除 b:ブランチ q/Esc:戻る",
GraphBaseSet => "基準: ",
GraphBaseCleared => "基準を解除しました",
GraphBaseNeedsCommit => "基準にするコミットを選んでください",
GraphLegendHidden => "非表示",
GraphPickerTitle => "グラフのブランチ",
GraphPickerFooter => "Space:切替 J/K:並替 a:全部 n:現在のみ Enter:適用 q:取消",
GraphPickerHeadLocked => "現在ブランチ(HEAD)は常に表示されます",
DiffScrollHint => "j/k:スクロール h/l:横移動 s:縦/横/Auto g/G:先頭/末尾 q/Esc:戻る",
DiffScrollDiscardHint => "j/k:スクロール n/N:次/前の変更 h/l:横移動 s:縦/横/Auto x:破棄 q/Esc:戻る",
HelpJumpTab => "番号でタブへジャンプ",
JustNow => "たった今",
Keymap => "キーマップ",
GitLayout => "並び: 縦 / 横 / Auto",
LineStartEnd => "行頭 / 行末へ(横)",
Loading => "読み込み中…",
Local => "ローカル",
GitLogGraph => "ログ / グラフ",
DlgMove => "m = 移動",
MarkHint => "登録 ▸ a-z=ローカル / A-Z=グローバル Esc",
Match => "一致",
MessageEmpty => "メッセージが空です",
TreeModified => "変更あり",
GitMove => "移動",
GitMoveCommit => "移動 (コミット / 未コミット)",
TreeMoveUpDown => "上下移動",
DlgCancel => "n / Esc = 取消",
NameEmpty => "名前が空です",
GitNewBranch => "新規ブランチ",
HelpNewTab => "新規タブ",
NoBookmark => "ブックマーク無し",
NoBranches => "ブランチなし",
NoChanges => "変更なし",
NoCommits => "コミットなし",
NoCopyTarget => "コピー対象がありません",
NoFileToEdit => "編集対象がありません",
NoMatch => "一致なし",
NoTarget => "対象がありません",
NotAFile => "ファイルではありません",
NotAGitRepo => "git リポジトリではありません",
NotFound => "見つかりません: ",
NothingStaged => "ステージ無し",
OpenFailed => "起動失敗: ",
OpenLinkHint => "リンクを開く (URL=ブラウザ/ローカル=konoma)・チェックボックスはトグル",
Opened => "開きました: ",
OperationFailed => "操作に失敗: ",
PanHint => "パン(拡大して見切れた時)",
PathLabel => "パス:",
PrevNextTab => "前 / 次のタブ",
Quit => "終了 (プレビュー中はツリーへ戻る)",
QuitOrCloseTab => "タブを閉じる・最後の1つなら終了 (プレビュー中はツリーへ戻る)",
Refresh => "一覧と git status を再読込",
RelLabel => "相対",
TreeStatusRenamed => "改名 / 種別変更 / 競合",
ResetRoot => "ルートを起動ディレクトリへ戻す",
ResetFit => "フィットに戻す",
Root => "ルート",
StGitHubKeys => "s/S:ステージ(全) u/U:解除(全) x:破棄 c:コミット Enter:差分 d:全変更差分 l:ログ g:グラフ b:ブランチ !:ツール q:閉じる",
Scroll => "スクロール",
Scroll10Lines => "10 行スクロール",
SearchHint => "検索(コード/テキスト); 次 / 前の一致",
SearchCodeTextOnly => "検索はコード/テキストのみ対応",
SelLabel => "選択",
SortHint => "並び替え: 名前/サイズ/更新/拡張子, r=反転, .=フォルダ先頭",
StageHint => "ステージ / 全ステージ",
Symlink => "シンボリックリンク",
ToParent => "親ディレクトリへ",
ToggleHidden => "隠しファイル表示の切替",
ToggleOne => "1件トグル(歯抜けを拾う), Esc = 選択クリア",
ToggleHelp => "このヘルプの開閉",
TopBottom => "先頭 / 末尾",
TrailingSlashFolder => "末尾 / でフォルダ",
UnstageHint => "アンステージ / 全アンステージ",
Untracked => "未追跡",
VisualRangeHint => "ビジュアル範囲: j/k で伸ばす, v/Esc 確定, a=同階層/A=表示全部, Space=操作",
DlgTrash => "y = ゴミ箱へ送る (復元可)",
DlgApply => "y = 適用 Esc = 取消 j/k = スクロール",
DlgDeleteSafe => "y = 削除 (安全 -d)",
DlgYesNo => "y = 実行 n / Esc = 取消",
StTrashDelete => "y:ゴミ箱 !:完全削除 n/Esc:取消",
StApply => "y:適用 Esc:取消 j/k:スクロール",
StDeleteForce => "y:削除(-d) !:強制(-D) n/Esc:取消",
Zoom => "ズーム",
BmActions => "a-Z ジャンプ ↵ 開く ^E 編集 ^D 削除 q 閉じる",
Empty => "",
StBatchRename => "一括リネーム",
StBookmarks => "ブックマーク",
StBranch => "ブランチ",
StChanges => "変更",
StCommit => "コミット",
StCommitDiff => "コミット差分",
StCreate => "作成",
StDelete => "削除確認",
StDiff => "差分",
StDrop => "ドロップ",
QuitConfirm => "konoma を終了しますか?",
StQuit => "終了確認",
StQuitHint => "y / q / Enter = 終了 n / Esc = 取消",
StFilter => "絞り込み",
StGit => "Git",
StGraph => "グラフ",
StImage => "画像",
StInfo => "情報",
StLog => "ログ",
StMark => "登録",
StPreview => "プレビュー",
StTable => "テーブル",
PreviewTable => "CSV / TSV テーブル",
WkTableCopyTitle => "テーブルからコピー",
WkCell => "セル",
WkRow => "行",
WkColumn => "列",
HintCell => "セル",
TableMoveHelp => "セル間を移動",
TableColsHelp => "先頭 / 末尾の列",
PreviewVisualHint => "h / j / k / l: 範囲拡張 y: コピー Y: @参照 v / Esc: 取消",
PreviewVisualLineHint => "j / k / g / G: 範囲拡張 y: 行コピー Y: @参照 V / Esc: 取消",
PreviewSelectHelp => "v: 文字範囲を選択 V: 行を選択(y でコピー)",
StVisualLine => "行ビジュアル",
WkAtRef => "@参照",
StChangedOnly => "変更のみ",
ChangedFilterHint => "Enter: プレビュー n / N: 次 / 前 C / h: 全ファイル",
NoChangedFiles => "変更ファイルはありません",
JumpTargetHidden => "対象が隠しディレクトリ配下です(`.` で隠しファイル表示)",
StFollow => "追尾",
FollowOn => "追尾: ON (何かキーを押すと解除)",
FollowOff => "追尾: OFF",
ChangedFilterHelp => "変更ファイルのみ表示 (git)",
JumpChangeHelp => "次 / 前の変更ファイルへジャンプ",
FollowHelp => "追尾モード: 外部で変更されたファイルを自動プレビュー",
AtRefHelp => "キャレット / 選択範囲の @path#L 参照をコピー",
StRename => "リネーム",
StRenameConfirm => "リネーム確認",
StSearch => "検索",
StSort => "並び替え",
StTree => "ツリー",
StVisual => "ビジュアル",
HintAnchor => "アンカー",
WkCreate => "作成",
AgoDays => "日前",
WkDelete => "削除",
HintDiff => "差分",
HintEdit => "編集",
HintEnds => "先頭/末尾",
HintEnter => "開く",
HintFileOps => "ファイル操作",
HintFilter => "絞り込み",
HintFit => "フィット",
WkFull => "フル",
HintGit => "Git",
HintBookmarks => "ブックマーク",
HintHelp => "ヘルプ",
HintHidden => "隠し",
AgoHr => "時間前",
HintHscroll => "横移動",
HintInfo => "情報",
HintLineEnds => "行頭/末",
HintLink => "リンク",
HintMark => "登録",
HintToggle => "トグル",
BusyGitScan => "git スキャン",
BusyMedia => "メディア読込",
BusyHighlight => "ハイライト準備",
BusyImages => "画像読込",
TaskFileChanged => "ファイルが外部で変更されたため再読込しました(トグル取消)",
AgoMin => "分前",
AgoMonths => "ヶ月前",
WkName => "名前",
HintOpen => "開く",
HintPage => "ページ",
HintPan => "パン",
WkParent => "親",
WkPaste => "貼付",
HintPath => "パス",
HintPick => "1件",
HintQuit => "終了",
HintCloseTab => "タブを閉じる",
HintRawSource => "ソース表示",
HintRendered => "装飾表示",
MdRawToggleHelp => "装飾表示 / ソース表示 を切替(ソースは選択可)",
WkRelative => "相対",
WkRename => "改名",
HintSearch => "検索",
HintSort => "並び",
HintTab => "タブ",
HintUp => "親へ",
HintVisual => "範囲",
AgoYears => "年前",
WkCopyPathTitle => "パスをコピー",
WkGitCopyTitle => "コミットをコピー",
WkShortHash => "短ハッシュ",
WkFullHash => "完全ハッシュ",
WkSubject => "件名",
WkMessage => "メッセージ",
WkAuthor => "著者",
WkDate => "日付",
NoCommitToCopy => "コピーするコミットがありません",
ImageUnsupported => "[image] この端末では画像を表示できません、または読み込みに失敗しました",
PreviewTruncated => "\n\n— (省略: 表示上限に達しました) —",
VideoThumbUnavailable => {
"[動画] サムネイル不可 — ffmpegthumbnailer か ffmpeg を導入してください(kitty graphics 対応端末が必要)"
}
PdfPreviewUnavailable => {
"[PDF] 表示不可 — poppler(pdftoppm) を導入するか kitty graphics 対応端末を使ってください"
}
}
}
pub fn tr(lang: Lang, msg: Msg) -> &'static str {
match lang {
Lang::En => en(msg),
Lang::Jp => jp(msg),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parse_defaults_to_en() {
assert_eq!(Lang::parse(""), Lang::En);
assert_eq!(Lang::parse("en"), Lang::En);
assert_eq!(Lang::parse("english"), Lang::En);
assert_eq!(Lang::parse("fr"), Lang::En, "未対応は英語");
assert_eq!(Lang::parse("jp"), Lang::Jp);
assert_eq!(Lang::parse("JA"), Lang::Jp);
assert_eq!(Lang::parse(" Japanese "), Lang::Jp);
}
#[test]
fn tr_selects_language() {
assert_eq!(tr(Lang::En, Msg::GitNoBranchesItem), " (no branches)");
assert_eq!(tr(Lang::Jp, Msg::GitNoBranchesItem), " (ブランチなし)");
assert_eq!(tr(Lang::En, Msg::GitNoChangesItem), " (no changes)");
assert_eq!(tr(Lang::Jp, Msg::GitNoChangesItem), " (変更なし)");
}
#[test]
fn from_lang_tag_detects_japanese() {
assert_eq!(Lang::from_lang_tag("ja"), Lang::Jp);
assert_eq!(Lang::from_lang_tag("ja-JP"), Lang::Jp);
assert_eq!(Lang::from_lang_tag("ja_JP.UTF-8"), Lang::Jp);
assert_eq!(Lang::from_lang_tag("en-US"), Lang::En);
assert_eq!(Lang::from_lang_tag("en_US.UTF-8"), Lang::En);
assert_eq!(Lang::from_lang_tag("fr-FR"), Lang::En);
assert_eq!(Lang::from_lang_tag("C"), Lang::En);
}
#[test]
fn resolve_explicit_overrides_auto() {
assert_eq!(Lang::resolve("jp"), Lang::Jp);
assert_eq!(Lang::resolve("en"), Lang::En);
assert_eq!(Lang::resolve(""), Lang::En);
assert_eq!(Lang::resolve("auto"), Lang::En);
assert_eq!(Lang::resolve(" System "), Lang::En);
}
#[test]
fn parse_apple_languages_takes_first_tag() {
assert_eq!(
parse_apple_languages("(\n \"ja-JP\",\n \"en-US\"\n)"),
Some("ja-JP".to_string())
);
assert_eq!(
parse_apple_languages("(\n \"en-US\"\n)"),
Some("en-US".to_string())
);
assert_eq!(parse_apple_languages("()"), None);
}
const ALL_MSGS: &[Msg] = &[
Msg::GitNoBranchesItem,
Msg::GitNoChangesItem,
Msg::GitNoCommitsItem,
Msg::BmTitle,
Msg::DlgConfirmTitle,
Msg::DlgDropTitle,
Msg::HelpTitle,
Msg::InfoTitle,
Msg::DlgInputTitle,
Msg::DlgRenamePreviewTitle,
Msg::DlgDeletePermanentHint,
Msg::DlgForceDeleteHint,
Msg::BmEmpty,
Msg::GitNoChanges,
Msg::BatchRename,
Msg::GitCommitWorktreeDetail,
Msg::CommitMessage,
Msg::Committed,
Msg::Copied,
Msg::Create,
Msg::Created,
Msg::CreatedBranch,
Msg::StScrollHintCtrl,
Msg::CutDone,
Msg::DeleteTarget,
Msg::DeleteBranch,
Msg::DeletedBranch,
Msg::DeletedPermanently,
Msg::DiscardChangesTo,
Msg::Discarded,
Msg::StApplyClearHint,
Msg::StCommitHint,
Msg::StCreateHint,
Msg::StRenamePreviewHint,
Msg::StRenameHint,
Msg::StSearchHint,
Msg::TreeFile,
Msg::GitBranchesLabel,
Msg::GitChangesLabel,
Msg::TreeGitChangesHub,
Msg::GitGraphLabel,
Msg::GitLogLabel,
Msg::TreeGitStatus,
Msg::BmGlobal,
Msg::HelpGlobal,
Msg::BmLocal,
Msg::InfoModified,
Msg::Moved,
Msg::MovedToTrash,
Msg::NewBranch,
Msg::Pasted,
Msg::InfoPerm,
Msg::PreviewGitDiff,
Msg::PreviewImage,
Msg::PreviewTextMarkdown,
Msg::Rename,
Msg::Renamed,
Msg::TreeSelection,
Msg::InfoSize,
Msg::StPagerSpaceHint,
Msg::Staged,
Msg::StagedAll,
Msg::SwitchedTo,
Msg::HelpTabs,
Msg::InfoTarget,
Msg::TreeSection,
Msg::InfoType,
Msg::UncommittedChanges,
Msg::Unstaged,
Msg::UnstagedAll,
Msg::Highlighting,
Msg::StSortHint,
Msg::StPathAbs,
Msg::TreeAddedStaged,
Msg::AlreadyAtStartDir,
Msg::AlreadyRoot,
Msg::AnchorReset,
Msg::TreeAnchorRoot,
Msg::GitBack,
Msg::BackToGitView,
Msg::BackToChanges,
Msg::BackToTree,
Msg::TreeBookmarkHint,
Msg::PreviewBookmarkHint,
Msg::BookmarkTargetMissing,
Msg::Bookmarked,
Msg::GitBranches,
Msg::DlgCopyKey,
Msg::StCopyMoveHint,
Msg::CantCloseLastTab,
Msg::Canceled,
Msg::CannotDeleteCurrentBranch,
Msg::CannotEditDirectory,
Msg::CannotPasteIntoSelf,
Msg::GitCheckout,
Msg::ClipboardEmpty,
Msg::GitCloseView,
Msg::CloseTab,
Msg::GitCommit,
Msg::GitCommitDetail,
Msg::CopiedPrefix,
Msg::CopyHint,
Msg::CopyFailed,
Msg::CutHint,
Msg::CyclePathStyle,
Msg::GitDelete,
Msg::TreeDeleted,
Msg::GitDetail,
Msg::GitDiffAll,
Msg::TreeDiffFile,
Msg::DiffAuto,
Msg::DiffSideBySide,
Msg::DiffUnified,
Msg::InfoDirectory,
Msg::GitDiscardFile,
Msg::DiscardWholeFile,
Msg::TreeDragDrop,
Msg::TreeDropFiles,
Msg::DroppedItems,
Msg::EditExternal,
Msg::EditExternalEnv,
Msg::EditorFailed,
Msg::EnterDirectory,
Msg::Etc,
Msg::ExpandInPlace,
Msg::GitExternalTool,
Msg::Failed,
Msg::InfoFile,
Msg::GitFileDiff,
Msg::TreeFileInfo,
Msg::TreeFilter,
Msg::GitFilterByName,
Msg::FocusMdLink,
Msg::MdTaskToggleHelp,
Msg::GitToolFailed,
Msg::GlobalApp,
Msg::HScroll,
Msg::GitHScrollEnds,
Msg::StCloseHint,
Msg::InfoClose,
Msg::AnchorsUnsupported,
Msg::InvalidMarkKey,
Msg::Items,
Msg::InfoItems,
Msg::VisualOpsHint,
Msg::BranchesNavHint,
Msg::GitNavDetailHint,
Msg::GitNavDetailCommitHint,
Msg::GraphBaseSet,
Msg::GraphBaseCleared,
Msg::GraphBaseNeedsCommit,
Msg::GraphLegendHidden,
Msg::GraphPickerTitle,
Msg::GraphPickerFooter,
Msg::GraphPickerHeadLocked,
Msg::DiffScrollHint,
Msg::DiffScrollDiscardHint,
Msg::HelpJumpTab,
Msg::JustNow,
Msg::Keymap,
Msg::GitLayout,
Msg::LineStartEnd,
Msg::Loading,
Msg::Local,
Msg::GitLogGraph,
Msg::DlgMove,
Msg::MarkHint,
Msg::Match,
Msg::MessageEmpty,
Msg::TreeModified,
Msg::GitMove,
Msg::GitMoveCommit,
Msg::TreeMoveUpDown,
Msg::DlgCancel,
Msg::NameEmpty,
Msg::GitNewBranch,
Msg::HelpNewTab,
Msg::NoBookmark,
Msg::NoBranches,
Msg::NoChanges,
Msg::NoCommits,
Msg::NoCopyTarget,
Msg::NoFileToEdit,
Msg::NoMatch,
Msg::NoTarget,
Msg::NotAFile,
Msg::NotAGitRepo,
Msg::NotFound,
Msg::NothingStaged,
Msg::OpenFailed,
Msg::OpenLinkHint,
Msg::Opened,
Msg::OperationFailed,
Msg::PanHint,
Msg::PathLabel,
Msg::PrevNextTab,
Msg::Quit,
Msg::Refresh,
Msg::RelLabel,
Msg::TreeStatusRenamed,
Msg::ResetRoot,
Msg::ResetFit,
Msg::Root,
Msg::StGitHubKeys,
Msg::Scroll,
Msg::Scroll10Lines,
Msg::SearchHint,
Msg::SearchCodeTextOnly,
Msg::SelLabel,
Msg::SortHint,
Msg::StageHint,
Msg::Symlink,
Msg::ToParent,
Msg::ToggleHidden,
Msg::ToggleOne,
Msg::ToggleHelp,
Msg::TopBottom,
Msg::TrailingSlashFolder,
Msg::UnstageHint,
Msg::Untracked,
Msg::VisualRangeHint,
Msg::DlgTrash,
Msg::DlgApply,
Msg::DlgDeleteSafe,
Msg::DlgYesNo,
Msg::StTrashDelete,
Msg::StApply,
Msg::StDeleteForce,
Msg::Zoom,
Msg::BmActions,
Msg::Empty,
Msg::StBatchRename,
Msg::StBookmarks,
Msg::StBranch,
Msg::StChanges,
Msg::StCommit,
Msg::StCommitDiff,
Msg::StCreate,
Msg::StDelete,
Msg::StDiff,
Msg::StDrop,
Msg::StFilter,
Msg::StGit,
Msg::StGraph,
Msg::StImage,
Msg::StInfo,
Msg::StLog,
Msg::StMark,
Msg::StPreview,
Msg::StRename,
Msg::StRenameConfirm,
Msg::StSearch,
Msg::StSort,
Msg::StTree,
Msg::StVisual,
Msg::HintAnchor,
Msg::WkCreate,
Msg::AgoDays,
Msg::WkDelete,
Msg::HintDiff,
Msg::HintEdit,
Msg::HintEnds,
Msg::HintEnter,
Msg::HintFileOps,
Msg::HintFilter,
Msg::HintFit,
Msg::WkFull,
Msg::HintGit,
Msg::HintBookmarks,
Msg::HintHelp,
Msg::HintHidden,
Msg::AgoHr,
Msg::HintHscroll,
Msg::HintInfo,
Msg::HintLineEnds,
Msg::HintLink,
Msg::HintMark,
Msg::HintToggle,
Msg::BusyGitScan,
Msg::BusyMedia,
Msg::BusyHighlight,
Msg::BusyImages,
Msg::TaskFileChanged,
Msg::AgoMin,
Msg::AgoMonths,
Msg::WkName,
Msg::HintOpen,
Msg::HintPage,
Msg::HintPan,
Msg::WkParent,
Msg::WkPaste,
Msg::HintPath,
Msg::HintPick,
Msg::HintQuit,
Msg::HintCloseTab,
Msg::HintRawSource,
Msg::HintRendered,
Msg::MdRawToggleHelp,
Msg::QuitOrCloseTab,
Msg::WkRelative,
Msg::WkRename,
Msg::HintSearch,
Msg::HintSort,
Msg::HintTab,
Msg::HintUp,
Msg::HintVisual,
Msg::AgoYears,
Msg::WkCopyPathTitle,
Msg::StTable,
Msg::PreviewTable,
Msg::WkTableCopyTitle,
Msg::WkCell,
Msg::WkRow,
Msg::WkColumn,
Msg::HintCell,
Msg::TableMoveHelp,
Msg::TableColsHelp,
Msg::PreviewVisualHint,
Msg::PreviewVisualLineHint,
Msg::PreviewSelectHelp,
Msg::StVisualLine,
Msg::WkAtRef,
Msg::StChangedOnly,
Msg::ChangedFilterHint,
Msg::NoChangedFiles,
Msg::JumpTargetHidden,
Msg::StFollow,
Msg::FollowOn,
Msg::FollowOff,
Msg::ChangedFilterHelp,
Msg::JumpChangeHelp,
Msg::FollowHelp,
Msg::AtRefHelp,
Msg::WkGitCopyTitle,
Msg::WkShortHash,
Msg::WkFullHash,
Msg::WkSubject,
Msg::WkMessage,
Msg::WkAuthor,
Msg::WkDate,
Msg::NoCommitToCopy,
Msg::ImageUnsupported,
Msg::PreviewTruncated,
Msg::VideoThumbUnavailable,
Msg::PdfPreviewUnavailable,
Msg::QuitConfirm,
Msg::StQuit,
Msg::StQuitHint,
];
#[test]
fn every_message_has_text_in_both_languages() {
for &m in ALL_MSGS {
let en = tr(Lang::En, m);
let jp = tr(Lang::Jp, m);
if m == Msg::Empty {
assert_eq!(en, "", "Empty は en で空文字のはず");
assert_eq!(jp, "", "Empty は jp で空文字のはず");
} else {
assert!(!en.is_empty(), "{m:?} の en 文言が空");
assert!(!jp.is_empty(), "{m:?} の jp 文言が空");
}
}
}
#[test]
fn message_catalog_is_unique_and_mostly_translated() {
for (i, &a) in ALL_MSGS.iter().enumerate() {
for &b in &ALL_MSGS[i + 1..] {
assert_ne!(a, b, "ALL_MSGS に重複 variant がある: {a:?}");
}
}
let differ = ALL_MSGS
.iter()
.filter(|&&m| tr(Lang::En, m) != tr(Lang::Jp, m))
.count();
assert!(
differ > ALL_MSGS.len() / 2,
"英日で異なる文言が過半数のはず: {differ}/{}",
ALL_MSGS.len()
);
}
}