mirror of
https://github.com/Flowseal/tg-ws-proxy.git
synced 2026-10-21 02:58:45 +00:00
Перевод secret и donate на русский язык (#1419)
This commit is contained in:
1 parent
3cda0f5446
commit
5f8820d41f
4 files changed
+77
-5
No files matched your search
@@ -0,0 +1,70 @@
|
||||
import json
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
LOCALES_DIR = Path(__file__).parents[1] / "ui" / "i18n"
|
||||
|
||||
# Values that are intentionally identical across locales
|
||||
# (brand names, technical terms, format-only strings).
|
||||
# Note: settings.language is deliberately "Language" in ru.json —
|
||||
# upstream keeps the language selector label in English on purpose.
|
||||
ALLOWED_UNTRANSLATED = frozenset({
|
||||
"app.name",
|
||||
"button.test_loading",
|
||||
"connectivity.cfworker_title",
|
||||
"connectivity.error_line",
|
||||
"first_run.manual_mtproto",
|
||||
"language.en",
|
||||
"language.ru",
|
||||
"section.cfproxy",
|
||||
"section.cfworker",
|
||||
"settings.language",
|
||||
})
|
||||
|
||||
|
||||
def _load(code: str) -> dict:
|
||||
with open(LOCALES_DIR / f"{code}.json", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
class I18nParityTest(unittest.TestCase):
|
||||
def test_en_ru_key_sets_match(self):
|
||||
en = _load("en")
|
||||
ru = _load("ru")
|
||||
self.assertEqual(
|
||||
set(en), set(ru),
|
||||
f"Missing in ru: {sorted(set(en) - set(ru))}; "
|
||||
f"missing in en: {sorted(set(ru) - set(en))}",
|
||||
)
|
||||
|
||||
def test_ru_has_no_untouched_english_leftovers(self):
|
||||
en = _load("en")
|
||||
ru = _load("ru")
|
||||
leftovers = sorted(
|
||||
key for key in set(en) & set(ru)
|
||||
if en[key] == ru[key] and key not in ALLOWED_UNTRANSLATED
|
||||
)
|
||||
self.assertEqual(leftovers, [])
|
||||
|
||||
def test_format_placeholders_match(self):
|
||||
import string
|
||||
|
||||
en = _load("en")
|
||||
ru = _load("ru")
|
||||
for key in set(en) & set(ru):
|
||||
en_fields = {
|
||||
name for _, name, _, _ in string.Formatter().parse(en[key])
|
||||
if name
|
||||
}
|
||||
ru_fields = {
|
||||
name for _, name, _, _ in string.Formatter().parse(ru[key])
|
||||
if name
|
||||
}
|
||||
self.assertEqual(
|
||||
en_fields, ru_fields,
|
||||
f"Placeholder mismatch for key {key!r}",
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -69,6 +69,7 @@
|
||||
"button.update": "Update",
|
||||
"button.page": "Page",
|
||||
"button.close": "Close",
|
||||
"button.donate": "Donate ♥",
|
||||
|
||||
"validation.bad_host": "Invalid IP address.",
|
||||
"validation.bad_port": "Port must be a number between 1 and 65535",
|
||||
|
||||
+5
-4
@@ -28,7 +28,7 @@
|
||||
|
||||
"label.host": "IP-адрес",
|
||||
"label.port": "Порт",
|
||||
"label.secret": "Secret",
|
||||
"label.secret": "Ключ",
|
||||
"label.dc_hint": "По одному правилу на строку, формат: номер:IP",
|
||||
"label.cf_enable": "Включить CF-прокси",
|
||||
"label.cf_custom_domain": "Свой домен",
|
||||
@@ -69,11 +69,12 @@
|
||||
"button.update": "Обновить",
|
||||
"button.page": "Страница",
|
||||
"button.close": "Закрыть",
|
||||
"button.donate": "Поддержать ♥",
|
||||
|
||||
"validation.bad_host": "Некорректный IP-адрес.",
|
||||
"validation.bad_port": "Порт должен быть числом 1-65535",
|
||||
"validation.bad_secret_len": "Secret должен содержать ровно 32 hex-символа (16 байт).",
|
||||
"validation.bad_secret_hex": "Secret должен состоять только из hex-символов (0-9, a-f).",
|
||||
"validation.bad_secret_len": "Ключ должен содержать ровно 32 hex-символа (16 байт).",
|
||||
"validation.bad_secret_hex": "Ключ должен состоять только из hex-символов (0-9, a-f).",
|
||||
"validation.dc_format": "Неверный формат DC:IP: {entry}",
|
||||
"validation.dc_invalid": "Неверная запись DC:IP: {entry}",
|
||||
|
||||
@@ -109,7 +110,7 @@
|
||||
"first_run.manual": " Вручную:",
|
||||
"first_run.manual_path": " Настройки → Продвинутые → Тип подключения → Прокси",
|
||||
"first_run.manual_mtproto": " MTProto → {host} : {port}",
|
||||
"first_run.manual_secret": " Secret: dd{secret}",
|
||||
"first_run.manual_secret": " Ключ: dd{secret}",
|
||||
"first_run.open_now": "Открыть прокси в Telegram сейчас",
|
||||
|
||||
"tray.open_telegram": "Открыть в Telegram ({host}:{port})",
|
||||
|
||||
+1
-1
@@ -135,7 +135,7 @@ def _create_header(ctk, frame, theme):
|
||||
).pack(side="right", padx=(4, 0))
|
||||
|
||||
ctk.CTkButton(
|
||||
header, text="Donate ♥", width=90, height=28,
|
||||
header, text=t("button.donate"), width=90, height=28,
|
||||
font=(theme.ui_font_family, 13, "bold"), corner_radius=8,
|
||||
fg_color="#22c55e", hover_color="#16a34a",
|
||||
text_color="#ffffff", border_width=0,
|
||||
|
||||
Reference in new issue
Block a user