1use crate::AniError;
2
3pub struct I18n {
4 locale: Locale,
5}
6
7pub enum Locale {
8 En,
9 }
11
12impl Default for I18n {
13 fn default() -> Self {
14 Self::new(Locale::En)
15 }
16}
17
18impl I18n {
19 pub fn new(locale: Locale) -> Self {
20 Self { locale }
21 }
22
23 pub fn error(&self, error: &AniError) -> String {
24 match self.locale {
25 Locale::En => self.error_en(error),
26 }
27 }
28
29 fn error_en(&self, error: &AniError) -> String {
30 const DOCS_TROUBLESHOOTING: &str =
31 "https://vorlie.github.io/ani-cli-rs/support/troubleshooting/";
32 match error {
33 AniError::ProviderUnavailable { .. } => error.to_string(),
35 AniError::ProviderRequestFailed { .. } => error.to_string(),
36 AniError::ProviderInvalidResponse { .. } => error.to_string(),
37 AniError::ProviderCatalogError { .. } => error.to_string(),
38 AniError::ProviderUrlValidationFailed { .. } => error.to_string(),
39 AniError::ProviderResponseSizeExceeded { .. } => error.to_string(),
40 AniError::NoSearchResults => error.to_string(),
41 AniError::EmptySearchQuery => error.to_string(),
42 AniError::NoEpisodesAvailable { .. } => error.to_string(),
43 AniError::InvalidEpisodeSelection { .. } => error.to_string(),
44 AniError::SelectionOutOfRange { .. } => error.to_string(),
45 AniError::CommandRequiresQuery => error.to_string(),
46 AniError::NoPlayableSources { .. } => error.to_string(),
47 AniError::SourceResolutionFailed { .. } => error.to_string(),
48 AniError::NoDownloadTool => {
49 format!(
50 "HLS downloads require yt-dlp or FFmpeg to be installed and available in PATH.\n\
51 Help: {DOCS_TROUBLESHOOTING}#mpv-vlc-syncplay-aria2c-yt-dlp-or-ffmpeg-not-found"
52 )
53 }
54 AniError::StreamUnavailable { .. } => error.to_string(),
55 AniError::UnsupportedEmbedHost { .. } => error.to_string(),
56 AniError::NoNativeStreams { .. } => error.to_string(),
57 AniError::DownloadFailed { .. } => error.to_string(),
58 AniError::HlsDownloadFailed { .. } => error.to_string(),
59 AniError::SubtitleDownloadFailed { .. } => error.to_string(),
60 AniError::SubtitleSizeExceeded { .. } => error.to_string(),
61 AniError::DownloadOutputError { .. } => error.to_string(),
62 AniError::PlayerNotFound { .. } => error.to_string(),
63 AniError::PlayerLaunchFailed { .. } => error.to_string(),
64 AniError::PlayerExitedWithError { .. } => error.to_string(),
65 AniError::AndroidTerminalRequired => error.to_string(),
66 AniError::GeneralPlayerError { .. } => error.to_string(),
67 AniError::IoError { .. } => error.to_string(),
68 AniError::HistoryStateDirectoryError => error.to_string(),
69 AniError::HistoryOperationFailed { .. } => error.to_string(),
70 AniError::InvalidHistoryEntry { .. } => error.to_string(),
71 AniError::UpdateCheckFailed { .. } => error.to_string(),
72 AniError::InvalidReleaseTag { .. } => error.to_string(),
73 AniError::InstallerExecutionFailed { .. } => error.to_string(),
74 AniError::PlatformNotSupported { .. } => error.to_string(),
75 AniError::InternalError { .. } => error.to_string(),
76 AniError::JsonParsingError { .. } => error.to_string(),
77 AniError::UrlParsingError { .. } => error.to_string(),
78 AniError::InvalidInput { .. } => error.to_string(),
79
80 AniError::Network(msg) => format!("Network request failed: {msg}"),
82 AniError::Provider(msg) => format!(
83 "Provider returned invalid data: {msg}\n\
84 Help: {DOCS_TROUBLESHOOTING}#search-works-but-sources-fail"
85 ),
86 AniError::Catalog { provider, message } => {
87 format!(
88 "{provider} catalog error: {message}\n\
89 Help: {DOCS_TROUBLESHOOTING}#search-works-but-sources-fail"
90 )
91 }
92 AniError::ProviderRateLimited {
93 provider,
94 retry_after_seconds,
95 } => {
96 format!(
97 "{provider} is rate limiting requests. Try again in {retry_after_seconds} seconds.\n\
98 Help: {DOCS_TROUBLESHOOTING}#search-works-but-sources-fail"
99 )
100 }
101
102 AniError::Unavailable(msg) => format!("Episode unavailable: {msg}"),
103 AniError::Player(msg) => format!("Player failed: {msg}"),
104 AniError::Download(msg) => format!("Download failed: {msg}"),
105 AniError::History(msg) => format!("History operation failed: {msg}"),
106 AniError::Update(msg) => format!("Update failed: {msg}"),
107 AniError::Input(msg) => format!("Invalid input: {msg}"),
108
109 AniError::Io(msg) => format!("Could not access local data: {msg}"),
110 AniError::Json(msg) => format!("Could not process response data: {msg}"),
111 AniError::Url(msg) => format!("Invalid URL: {msg}"),
112
113 AniError::DownloadNoDownloader => format!(
114 "HLS downloads require yt-dlp or FFmpeg to be installed and available in PATH.\n\
115 Help: {DOCS_TROUBLESHOOTING}#mpv-vlc-syncplay-aria2c-yt-dlp-or-ffmpeg-not-found"
116 ),
117 AniError::HlsDownloadFailedLegacy => format!(
118 "HLS download failed.\n\
119 Help: {DOCS_TROUBLESHOOTING}#part-remains-after-a-download"
120 ),
121
122 AniError::HistoryStateDirectory => {
123 "Could not determine where to store history data.".to_string()
124 }
125
126 AniError::PlayerNotFoundLegacy => format!(
127 "Player executable not found. Make sure your configured player is installed.\n\
128 Help: {DOCS_TROUBLESHOOTING}#mpv-vlc-syncplay-aria2c-yt-dlp-or-ffmpeg-not-found"
129 ),
130
131 AniError::PlayerLaunchFailedLegacy => format!(
132 "Could not launch the player.\n\
133 Help: {DOCS_TROUBLESHOOTING}#mpv-vlc-syncplay-aria2c-yt-dlp-or-ffmpeg-not-found"
134 ),
135
136 AniError::PlayerExitFailed => format!(
137 "Player exited with an error.\n\
138 Help: {DOCS_TROUBLESHOOTING}#mpv-vlc-syncplay-aria2c-yt-dlp-or-ffmpeg-not-found"
139 ),
140
141 AniError::PlayerAndroidTerminalRequired => format!(
142 "Android HLS playback requires an interactive Termux terminal.\n\
143 Help: {DOCS_TROUBLESHOOTING}#termux-playback-stops-after-returning-to-the-terminal"
144 ),
145
146 AniError::InputSelectionOutOfRange => "Selection is out of range.".to_string(),
147
148 AniError::InputEmptyQuery => "Search query cannot be empty.".to_string(),
149
150 AniError::InputInvalidEpisode => "Invalid episode selection.".to_string(),
151
152 AniError::InputRequiresQuery => "This command requires an anime query.".to_string(),
153
154 AniError::UnavailableNoResults => "No results found.".to_string(),
155
156 AniError::UnavailableNoStreams => format!(
157 "No streams are available for this episode.\n\
158 Help: {DOCS_TROUBLESHOOTING}#search-works-but-sources-fail"
159 ),
160
161 AniError::UnavailableNoEpisodes => format!(
162 "No episodes are available.\n\
163 Help: {DOCS_TROUBLESHOOTING}#search-works-but-sources-fail"
164 ),
165 }
166 }
167}