Skip to content

Commit cb79577

Browse files
committed
Port Chinese translations from eagleon's fork
1 parent cb67374 commit cb79577

5 files changed

Lines changed: 108 additions & 6 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
### Added
66

7-
- Internationalization (i18n) support and initial German translation.
7+
- Internationalization (i18n) support and initial Chinese and German
8+
translations.
89

910

1011
## 3.6.2

Cargo.lock

Lines changed: 16 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/wastebin_server/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ wastebin_highlight = { path = "../wastebin_highlight/" }
3232
headers = "0.4.1"
3333

3434
[dev-dependencies]
35+
itertools = "0.14.0"
3536
reqwest = { version = "0.13", default-features = false, features = ["cookies", "form", "json", "query"] }
3637
tower = { version = "0.5", default-features = false, features = ["util", "make"] }
3738

crates/wastebin_server/src/handlers/extract.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ fn lang_from_tag(tag: &str) -> Option<Lang> {
200200
match tag.split('-').next()?.trim() {
201201
"en" | "eN" | "En" | "EN" => Some(Lang::En),
202202
"de" | "dE" | "De" | "DE" => Some(Lang::De),
203+
"zh" | "zH" | "Zh" | "ZH" => Some(Lang::Zh),
203204
_ => None,
204205
}
205206
}

crates/wastebin_server/src/i18n.rs

Lines changed: 88 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ pub(crate) enum Lang {
77
#[default]
88
En,
99
De,
10+
Zh,
1011
}
1112

1213
impl Lang {
@@ -15,6 +16,7 @@ impl Lang {
1516
match self {
1617
Lang::En => "en",
1718
Lang::De => "de",
19+
Lang::Zh => "zh",
1820
}
1921
}
2022

@@ -25,6 +27,7 @@ impl Lang {
2527
let map: &phf::Map<&'static str, &'static str> = match self {
2628
Lang::En => &EN,
2729
Lang::De => &DE,
30+
Lang::Zh => &ZH,
2831
};
2932

3033
map.get(key).or_else(|| EN.get(key)).copied().unwrap_or(key)
@@ -185,9 +188,84 @@ static DE: phf::Map<&'static str, &'static str> = phf_map! {
185188
"qr.label" => "QR-Code",
186189
};
187190

191+
static ZH: phf::Map<&'static str, &'static str> = phf_map! {
192+
"nav.home" => "主页",
193+
"nav.upload" => "上传",
194+
"nav.delete" => "删除剪贴",
195+
"nav.download" => "下载文件",
196+
"nav.raw" => "显示原始内容",
197+
"nav.copy" => "复制到剪贴板",
198+
"nav.qr" => "二维码",
199+
"nav.rendered" => "渲染视图",
200+
"nav.source" => "源码视图",
201+
202+
"theme.dark" => "深色模式",
203+
"theme.light" => "浅色模式",
204+
"theme.auto" => "自动模式",
205+
206+
"index.placeholder.paste" => "在此处粘贴、输入或拖放文件…",
207+
"index.drop" => "拖放以加载文件",
208+
"index.label.title" => "标题",
209+
"index.placeholder.title" => "无标题",
210+
"index.label.language" => "语言",
211+
"index.aria.language" => "语言",
212+
"index.placeholder.filter" => "过滤…",
213+
"index.label.expires" => "过期时间",
214+
"index.label.options" => "选项",
215+
"index.toggle.burn" => "阅后即焚",
216+
"index.toggle.burn.hint" => "首次查看后删除",
217+
"index.toggle.encrypt" => "加密",
218+
"index.toggle.encrypt.hint" => "使用密码保护剪贴",
219+
"index.placeholder.password" => "密码",
220+
"index.stat.lines" => "行",
221+
"index.stat.chars" => "字符",
222+
"index.stat.bytes" => "字节",
223+
"index.button.paste" => "粘贴",
224+
"index.button.paste.label" => "粘贴",
225+
226+
"paste.expires_in" => "过期于",
227+
"paste.toast.copied_content" => "已复制内容",
228+
"paste.toast.copied_url" => "已复制链接",
229+
"paste.toast.burned" => "内容已销毁,无法再次查看!",
230+
"paste.help.go_home" => "返回主页",
231+
"paste.help.go_here" => "返回此处",
232+
"paste.help.copy_url" => "复制链接",
233+
"paste.help.copy_content" => "复制内容",
234+
"paste.help.download" => "下载",
235+
"paste.help.show_qr" => "显示二维码",
236+
"paste.help.toggle_wrap" => "切换自动换行",
237+
"paste.help.toggle_rendered" => "切换渲染视图",
238+
"paste.help.toggle_help" => "切换帮助",
239+
240+
"password.show" => "显示密码",
241+
"password.hide" => "隐藏密码",
242+
243+
"stats.unit.kb" => "kb",
244+
"stats.unit.mb" => "mb",
245+
"stats.label.limit" => "限制",
246+
247+
"burn.title" => "阅后即焚",
248+
"burn.body" => "复制并发送 <a class=\"text-link\" href=\"/{0}\">此链接</a>。收件人将看到确认提示。在他们确认的那一刻,剪贴将被删除。",
249+
250+
"burn_confirm.body" => "此剪贴在显示的那一刻将被 <strong>永久删除</strong>。您将无法再次查看它。",
251+
"burn_confirm.cancel" => "取消",
252+
"burn_confirm.reveal" => "显示",
253+
254+
"encrypted.title" => "加密的剪贴",
255+
"encrypted.placeholder" => "密码…",
256+
"encrypted.cancel" => "取消",
257+
"encrypted.decrypt" => "解密",
258+
259+
"error.title" => "错误 😢",
260+
"error.back" => "返回",
261+
262+
"qr.label" => "二维码",
263+
};
264+
188265
#[cfg(test)]
189266
mod tests {
190267
use super::*;
268+
use itertools::Itertools;
191269

192270
#[test]
193271
fn falls_back_to_english_for_missing_keys() {
@@ -205,12 +283,17 @@ mod tests {
205283

206284
#[test]
207285
fn translations_intersect() {
208-
for key in EN.keys() {
209-
assert!(DE.contains_key(key));
210-
}
286+
for perms in [&DE, &EN, &ZH].iter().permutations(2) {
287+
let a = perms[0];
288+
let b = perms[1];
289+
290+
for key in a.keys() {
291+
assert!(b.contains_key(key));
292+
}
211293

212-
for key in DE.keys() {
213-
assert!(EN.contains_key(key));
294+
for key in b.keys() {
295+
assert!(a.contains_key(key));
296+
}
214297
}
215298
}
216299
}

0 commit comments

Comments
 (0)