+1
docs/docs/CHANGELOG.md
+1
docs/docs/CHANGELOG.md
···
29
29
- Add translation for Turkish language ([#751](https://github.com/TecharoHQ/anubis/pull/751))
30
30
- Allow [Common Crawl](https://commoncrawl.org/) by default so scrapers have less incentive to scrape
31
31
- The [bbolt storage backend](./admin/policies.mdx#bbolt) now runs its cleanup every hour instead of every five minutes.
32
+
- Add translation for Traditional Chinese ([#759](https://github.com/TecharoHQ/anubis/pull/759))
32
33
33
34
### Potentially breaking changes
34
35
+1
-1
lib/localization/locales/manifest.json
+1
-1
lib/localization/locales/manifest.json
+63
lib/localization/locales/zh-TW.json
+63
lib/localization/locales/zh-TW.json
···
1
+
{
2
+
"loading": "載入中...",
3
+
"why_am_i_seeing": "為什麼我看到這個?",
4
+
"protected_by": "保護由",
5
+
"made_with": "在 🇨🇦 用 ❤️ 製作",
6
+
"mascot_design": "吉祥物由",
7
+
"ai_companies_explanation": "您會看到這個畫面,是因為網站管理員啟用了 Anubis 來保護伺服器,避免 AI 公司大量爬取網站內容。這類行為會導致網站當機,讓所有使用者都無法正常存取資源。",
8
+
"anubis_compromise": "Anubis 是一種折衷做法。它採用了類似 Hashcash 的工作量證明機制(Proof-of-Work),該機制最初是為了減少垃圾郵件而提出。其核心概念是:對個別使用者而言,額外的運算負擔可以忽略,但對大規模爬蟲來說,累積起來的成本將大幅增加,從而讓爬取行為變得更困難。",
9
+
"hack_purpose": "本質上,這是一種權宜的解法,目的是提供一個「夠用」的暫時性防護措施,好讓開發者有更多時間針對無頭瀏覽器進行指紋特徵辨識(例如:分析其字型渲染方式),以便未來不再需要對可能為合法使用者的訪客展示工作量證明頁面。",
10
+
"jshelter_note": "請注意,Anubis 需要使用現代 JavaScript 功能,而像 JShelter 這類外掛可能會阻擋這些功能。請為此網域停用 JShelter 或類似的插件。",
11
+
"version_info": "這個網站正在運行 Anubis 版本",
12
+
"try_again": "再試一次",
13
+
"go_home": "回首頁",
14
+
"contact_webmaster": "或者您覺得您不應該被封鎖,請聯絡站點管理員於",
15
+
"connection_security": "請稍等,我們需要在繼續之前檢閱您的連線安全性。",
16
+
"javascript_required": "很遺憾,您必須啟用 JavaScript 才能通過這項驗證。這是因為 AI 公司已經改變了網站託管的社會契約,因此我們必須採取這樣的保護機制。無需 JavaScript 的解法仍在開發中。",
17
+
"benchmark_requires_js": "執行基準測試工具需要啟用 JavaScript。",
18
+
"difficulty": "難度:",
19
+
"algorithm": "演算法:",
20
+
"compare": "比較:",
21
+
"time": "時間",
22
+
"iters": "迭代",
23
+
"time_a": "時間 A",
24
+
"iters_a": "迭代 A",
25
+
"time_b": "時間 B",
26
+
"iters_b": "迭代 B",
27
+
"static_check_endpoint": "這是提供給您的反向代理伺服器使用的檢查端點。",
28
+
"authorization_required": "需要認證",
29
+
"cookies_disabled": "您的瀏覽器目前已停用 Cookie,為了確認您是合法使用者,Anubis 需要啟用 Cookie。 請為此網域啟用 Cookie",
30
+
"access_denied": "拒絕存取:錯誤代碼",
31
+
"dronebl_entry": "DroneBL 回報了一筆紀錄",
32
+
"see_dronebl_lookup": "見",
33
+
"internal_server_error": "內部伺服器錯誤:管理員錯誤地配置了 Anubis。 請聯絡管理員要求他們檢閱日誌",
34
+
"invalid_redirect": "無效的重新導向",
35
+
"redirect_not_parseable": "重新導向 URL 無法解析",
36
+
"redirect_domain_not_allowed": "重新導向的網域並不允許",
37
+
"failed_to_sign_jwt": "簽署 JWT 失敗",
38
+
"invalid_invocation": "無效的 MakeChallenge 呼叫",
39
+
"client_error_browser": "客戶端錯誤:請確保您的瀏覽器是最新版本並稍候再試。",
40
+
"oh_noes": "哎呀糟糕了!",
41
+
"benchmarking_anubis": "正在進行 Anubis 效能測試!",
42
+
"you_are_not_a_bot": "你不是機器人!",
43
+
"making_sure_not_bot": "正在確認你是不是機器人!",
44
+
"celphase": "CELPHASE 設計",
45
+
"js_web_crypto_error": "您的瀏覽器無法正常使用 web.crypto 元件。您是否透過安全連線(HTTPS)檢視此網站?",
46
+
"js_web_workers_error": "您的瀏覽器並不支援 Web workers (Anubis 使用這個來避免凍結您的瀏覽器 )您有安裝像是 JShelter 之類的插件嗎?",
47
+
"js_cookies_error": "您的瀏覽器無法儲存 Cookie。 Anubis 會使用 Cookie 儲存簽署的憑證,以判斷使用者是否已通過驗證。請為此網域啟用 Cookie 儲存功能。 請注意,Anubis 儲存的 Cookie 名稱可能會變動,且其名稱與內容不屬於公開 API 的一部分。",
48
+
"js_context_not_secure": "您的內容並不安全",
49
+
"js_context_not_secure_msg": "請嘗試使用 HTTPS 連線,或聯繫網站管理員設定 HTTPS。更多資訊請參見 <a href=\"https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts#when_is_a_context_considered_secure\">MDN</a>。",
50
+
"js_calculating": "計算中...",
51
+
"js_missing_feature": "缺少功能",
52
+
"js_challenge_error": "挑戰錯誤!",
53
+
"js_challenge_error_msg": "解決檢查演算法失敗。 您可能會想要重整頁面。",
54
+
"js_calculating_difficulty": "計算中...<br/>難度:",
55
+
"js_speed": "速度:",
56
+
"js_verification_longer": "驗證所花的時間高於預期。 請不要重整頁面。",
57
+
"js_success": "成功!",
58
+
"js_done_took": "完成! 花費",
59
+
"js_iterations": "迭代",
60
+
"js_finished_reading": "我讀完了,繼續 →",
61
+
"js_calculation_error": "計算錯誤!",
62
+
"js_calculation_error_msg": "計算挑戰失敗:"
63
+
}
+23
lib/localization/localization_test.go
+23
lib/localization/localization_test.go
···
43
43
}
44
44
})
45
45
46
+
t.Run("Traditional Chinese localization", func(t *testing.T) {
47
+
localizer := service.GetLocalizer("zh-TW")
48
+
result := localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "loading"})
49
+
if result != "載入中..." {
50
+
t.Errorf("Expected '載入中...', got '%s'", result)
51
+
}
52
+
})
53
+
46
54
t.Run("All required keys exist in English", func(t *testing.T) {
47
55
localizer := service.GetLocalizer("en")
48
56
requiredKeys := []string{
···
75
83
76
84
t.Run("All required keys exist in Turkish", func(t *testing.T) {
77
85
localizer := service.GetLocalizer("tr")
86
+
requiredKeys := []string{
87
+
"loading", "why_am_i_seeing", "protected_by", "made_with",
88
+
"mascot_design", "try_again", "go_home", "javascript_required",
89
+
}
90
+
91
+
for _, key := range requiredKeys {
92
+
result := localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: key})
93
+
if result == "" {
94
+
t.Errorf("Key '%s' returned empty string", key)
95
+
}
96
+
}
97
+
})
98
+
99
+
t.Run("All required keys exist in Traditional Chinese", func(t *testing.T) {
100
+
localizer := service.GetLocalizer("zh-TW")
78
101
requiredKeys := []string{
79
102
"loading", "why_am_i_seeing", "protected_by", "made_with",
80
103
"mascot_design", "try_again", "go_home", "javascript_required",