diff --git a/Makefile b/Makefile index cb137a5..594e2f3 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ lint-fix: venv/bin/ruff --fix format: - venv/bin/ruff format + venv/bin/ruff format requirements.txt: deps-top.txt recreate-venv venv/bin/pip install -r deps-top.txt @@ -40,11 +40,11 @@ test_single: venv/bin/pytest tests/api/test_file_api.py test_logging: - #--capture=no + #--capture=no venv/bin/pytest --capture=sys --log-cli-level=DEBUG tests/base/test_logging.py babel-update-po: - venv/bin/pybabel extract -F babel.cfg -k lazy_gettext -o messages.pot app + venv/bin/pybabel extract -F babel.cfg -k lazy_gettext -k hardcode_text -o messages.pot app venv/bin/pybabel update -i messages.pot -d app/translations babel-update-mo: babel-update-po @@ -52,4 +52,4 @@ babel-update-mo: babel-update-po babel-translate-po: venv/bin/python app/scripts/fill_zh_translations.py - venv/bin/python app/scripts/fill_en_translations.py \ No newline at end of file + venv/bin/python app/scripts/fill_en_translations.py diff --git a/app/models/language.py b/app/models/language.py index d5c8b3f..35f00b2 100644 --- a/app/models/language.py +++ b/app/models/language.py @@ -1,14 +1,23 @@ import logging -from flask_babel import gettext from mongoengine import Document, BooleanField, StringField, IntField, QuerySet from app.exceptions.language import LanguageNotExistError -from typing import List, Any, Dict +from app.translations import hardcode_text, gettext, server_gettext +from typing import List, Any, Dict, TypedDict, Optional logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) +class LanguageData(TypedDict): + en_name: str + lo_name: str + code: str + g_tra_code: str + g_ocr_code: str + no_space: Optional[bool] + + class Language(Document): en_name: str = StringField(db_field="e") # 英文名称 lo_name: str = StringField(db_field="c") # 系统名称(中文),用于翻译成 i18n_name @@ -20,10 +29,10 @@ class Language(Document): g_ocr_code: str = StringField(db_field="go", default="") # 谷歌ocr hint sort: int = IntField(db_field="s", default=0) - SYSTEM_LANGUAGES_DATA = [ + SYSTEM_LANGUAGES_DATA: list[LanguageData] = [ { "en_name": "Japanese", - "lo_name": "日语", + "lo_name": hardcode_text("日语"), "code": "ja", "g_tra_code": "ja", "g_ocr_code": "ja", @@ -31,14 +40,14 @@ class Language(Document): }, { "en_name": "English", - "lo_name": "英语", + "lo_name": hardcode_text("英语"), "code": "en", "g_tra_code": "en", "g_ocr_code": "en", }, { "en_name": "Korean", - "lo_name": "朝鲜语(韩语)", + "lo_name": hardcode_text("韩语") or hardcode_text("朝鲜语(韩语)"), "code": "ko", "g_tra_code": "ko", "g_ocr_code": "ko", @@ -46,7 +55,7 @@ class Language(Document): }, { "en_name": "Chinese (Simplified)", - "lo_name": "中文(简体)", + "lo_name": hardcode_text("中文(简体)"), "code": "zh-CN", "g_tra_code": "zh-CN", "g_ocr_code": "zh", @@ -54,7 +63,7 @@ class Language(Document): }, { "en_name": "Chinese (Traditional)", - "lo_name": "中文(繁体)", + "lo_name": hardcode_text("中文(繁体)"), "code": "zh-TW", "g_tra_code": "zh-TW", "g_ocr_code": "zh", @@ -62,196 +71,196 @@ class Language(Document): }, { "en_name": "Afrikaans", - "lo_name": "南非荷兰语", + "lo_name": hardcode_text("南非荷兰语"), "code": "af", "g_tra_code": "af", "g_ocr_code": "af", }, { "en_name": "Albanian", - "lo_name": "阿尔巴尼亚语", + "lo_name": hardcode_text("阿尔巴尼亚语"), "code": "sq", "g_tra_code": "sq", "g_ocr_code": "", }, { "en_name": "Amharic", - "lo_name": "阿姆哈拉语", + "lo_name": hardcode_text("阿姆哈拉语"), "code": "am", "g_tra_code": "am", "g_ocr_code": "", }, { "en_name": "Assamese", - "lo_name": "阿萨姆语", + "lo_name": hardcode_text("阿萨姆语"), "code": "as", "g_tra_code": "", "g_ocr_code": "as", }, { "en_name": "Arabic", - "lo_name": "阿拉伯语", + "lo_name": hardcode_text("阿拉伯语"), "code": "ar", "g_tra_code": "ar", "g_ocr_code": "ar", }, { "en_name": "Armenian", - "lo_name": "亚美尼亚语", + "lo_name": hardcode_text("亚美尼亚语"), "code": "hy", "g_tra_code": "hy", "g_ocr_code": "", }, { "en_name": "Azerbaijani", - "lo_name": "阿塞拜疆语", + "lo_name": hardcode_text("阿塞拜疆语"), "code": "az", "g_tra_code": "az", "g_ocr_code": "az", }, { "en_name": "Basque", - "lo_name": "巴斯克语", + "lo_name": hardcode_text("巴斯克语"), "code": "eu", "g_tra_code": "eu", "g_ocr_code": "", }, { "en_name": "Belarusian", - "lo_name": "白俄罗斯语", + "lo_name": hardcode_text("白俄罗斯语"), "code": "be", "g_tra_code": "be", "g_ocr_code": "be", }, { "en_name": "Bengali", - "lo_name": "孟加拉语", + "lo_name": hardcode_text("孟加拉语"), "code": "bn", "g_tra_code": "bn", "g_ocr_code": "bn", }, { "en_name": "Bosnian", - "lo_name": "波斯尼亚语", + "lo_name": hardcode_text("波斯尼亚语"), "code": "bs", "g_tra_code": "bs", "g_ocr_code": "", }, { "en_name": "Bulgarian", - "lo_name": "保加利亚语", + "lo_name": hardcode_text("保加利亚语"), "code": "bg", "g_tra_code": "bg", "g_ocr_code": "bg", }, { "en_name": "Catalan", - "lo_name": "加泰罗尼亚语", + "lo_name": hardcode_text("加泰罗尼亚语"), "code": "ca", "g_tra_code": "ca", "g_ocr_code": "ca", }, { "en_name": "Cebuano", - "lo_name": "宿务语", + "lo_name": hardcode_text("宿务语"), "code": "ceb", "g_tra_code": "ceb", "g_ocr_code": "", }, { "en_name": "Corsican", - "lo_name": "科西嘉语", + "lo_name": hardcode_text("科西嘉语"), "code": "co", "g_tra_code": "co", "g_ocr_code": "", }, { "en_name": "Croatian", - "lo_name": "克罗地亚语", + "lo_name": hardcode_text("克罗地亚语"), "code": "hr", "g_tra_code": "hr", "g_ocr_code": "hr", }, { "en_name": "Czech", - "lo_name": "捷克语", + "lo_name": hardcode_text("捷克语"), "code": "cs", "g_tra_code": "cs", "g_ocr_code": "cs", }, { "en_name": "Danish", - "lo_name": "丹麦语", + "lo_name": hardcode_text("丹麦语"), "code": "da", "g_tra_code": "da", "g_ocr_code": "da", }, { "en_name": "Dutch", - "lo_name": "荷兰语", + "lo_name": hardcode_text("荷兰语"), "code": "nl", "g_tra_code": "nl", "g_ocr_code": "nl", }, { "en_name": "Esperanto", - "lo_name": "世界语", + "lo_name": hardcode_text("世界语"), "code": "eo", "g_tra_code": "eo", "g_ocr_code": "", }, { "en_name": "Estonian", - "lo_name": "爱沙尼亚语", + "lo_name": hardcode_text("爱沙尼亚语"), "code": "et", "g_tra_code": "et", "g_ocr_code": "et", }, { "en_name": "Finnish", - "lo_name": "芬兰语", + "lo_name": hardcode_text("芬兰语"), "code": "fi", "g_tra_code": "fi", "g_ocr_code": "fi", }, { "en_name": "French", - "lo_name": "法语", + "lo_name": hardcode_text("法语"), "code": "fr", "g_tra_code": "fr", "g_ocr_code": "fr", }, { "en_name": "Frisian", - "lo_name": "弗里斯兰语", + "lo_name": hardcode_text("弗里斯兰语"), "code": "fy", "g_tra_code": "fy", "g_ocr_code": "", }, { "en_name": "Galician", - "lo_name": "加利西亚语", + "lo_name": hardcode_text("加利西亚语"), "code": "gl", "g_tra_code": "gl", "g_ocr_code": "", }, { "en_name": "Georgian", - "lo_name": "格鲁吉亚语", + "lo_name": hardcode_text("格鲁吉亚语"), "code": "ka", "g_tra_code": "ka", "g_ocr_code": "", }, { "en_name": "German", - "lo_name": "德语", + "lo_name": hardcode_text("德语"), "code": "de", "g_tra_code": "de", "g_ocr_code": "de", }, { "en_name": "Greek", - "lo_name": "希腊语", + "lo_name": hardcode_text("希腊语"), "code": "el", "g_tra_code": "el", "g_ocr_code": "el", @@ -259,98 +268,98 @@ class Language(Document): }, { "en_name": "Gujarati", - "lo_name": "古吉拉特语", + "lo_name": hardcode_text("古吉拉特语"), "code": "gu", "g_tra_code": "gu", "g_ocr_code": "", }, { "en_name": "Haitian Creole", - "lo_name": "海地克里奥尔语", + "lo_name": hardcode_text("海地克里奥尔语"), "code": "ht", "g_tra_code": "ht", "g_ocr_code": "", }, { "en_name": "Hausa", - "lo_name": "豪萨语", + "lo_name": hardcode_text("豪萨语"), "code": "ha", "g_tra_code": "ha", "g_ocr_code": "", }, { "en_name": "Hawaiian", - "lo_name": "夏威夷语", + "lo_name": hardcode_text("夏威夷语"), "code": "haw", "g_tra_code": "haw", "g_ocr_code": "", }, { "en_name": "Hebrew", - "lo_name": "希伯来语", + "lo_name": hardcode_text("希伯来语"), "code": "iw", "g_tra_code": "iw", "g_ocr_code": "iw", }, { "en_name": "Hindi", - "lo_name": "印地语", + "lo_name": hardcode_text("印地语"), "code": "hi", "g_tra_code": "hi", "g_ocr_code": "hi", }, { "en_name": "Hmong", - "lo_name": "苗语", + "lo_name": hardcode_text("苗语"), "code": "hmn", "g_tra_code": "hmn", "g_ocr_code": "", }, { "en_name": "Hungarian", - "lo_name": "匈牙利语", + "lo_name": hardcode_text("匈牙利语"), "code": "hu", "g_tra_code": "hu", "g_ocr_code": "hu", }, { "en_name": "Icelandic", - "lo_name": "冰岛语", + "lo_name": hardcode_text("冰岛语"), "code": "is", "g_tra_code": "is", "g_ocr_code": "is", }, { "en_name": "Igbo", - "lo_name": "伊博语", + "lo_name": hardcode_text("伊博语"), "code": "ig", "g_tra_code": "ig", "g_ocr_code": "", }, { "en_name": "Indonesian", - "lo_name": "印度尼西亚语", + "lo_name": hardcode_text("印度尼西亚语"), "code": "id", "g_tra_code": "id", "g_ocr_code": "id", }, { "en_name": "Irish", - "lo_name": "爱尔兰语", + "lo_name": hardcode_text("爱尔兰语"), "code": "ga", "g_tra_code": "ga", "g_ocr_code": "", }, { "en_name": "Italian", - "lo_name": "意大利语", + "lo_name": hardcode_text("意大利语"), "code": "it", "g_tra_code": "it", "g_ocr_code": "it", }, { "en_name": "Javanese", - "lo_name": "爪哇语", + "lo_name": hardcode_text("爪哇语"), "code": "jw", "g_tra_code": "jw", "g_ocr_code": "", @@ -358,21 +367,21 @@ class Language(Document): }, { "en_name": "Kannada", - "lo_name": "卡纳达语", + "lo_name": hardcode_text("卡纳达语"), "code": "kn", "g_tra_code": "kn", "g_ocr_code": "", }, { "en_name": "Kazakh", - "lo_name": "哈萨克语", + "lo_name": hardcode_text("哈萨克语"), "code": "kk", "g_tra_code": "kk", "g_ocr_code": "kk", }, { "en_name": "Khmer", - "lo_name": "高棉语", + "lo_name": hardcode_text("高棉语"), "code": "km", "g_tra_code": "km", "g_ocr_code": "", @@ -380,21 +389,21 @@ class Language(Document): }, { "en_name": "Kurdish", - "lo_name": "库尔德语", + "lo_name": hardcode_text("库尔德语"), "code": "ku", "g_tra_code": "ku", "g_ocr_code": "", }, { "en_name": "Kyrgyz", - "lo_name": "吉尔吉斯语", + "lo_name": hardcode_text("吉尔吉斯语"), "code": "ky", "g_tra_code": "ky", "g_ocr_code": "ky", }, { "en_name": "Lao", - "lo_name": "老挝语", + "lo_name": hardcode_text("老挝语"), "code": "lo", "g_tra_code": "lo", "g_ocr_code": "", @@ -402,7 +411,7 @@ class Language(Document): }, { "en_name": "Latin", - "lo_name": "拉丁语", + "lo_name": hardcode_text("拉丁语"), "code": "la", "g_tra_code": "la", "g_ocr_code": "", @@ -410,84 +419,84 @@ class Language(Document): }, { "en_name": "Latvian", - "lo_name": "拉脱维亚语", + "lo_name": hardcode_text("拉脱维亚语"), "code": "lv", "g_tra_code": "lv", "g_ocr_code": "lv", }, { "en_name": "Lithuanian", - "lo_name": "立陶宛语", + "lo_name": hardcode_text("立陶宛语"), "code": "lt", "g_tra_code": "lt", "g_ocr_code": "lt", }, { "en_name": "Luxembourgish", - "lo_name": "卢森堡语", + "lo_name": hardcode_text("卢森堡语"), "code": "lb", "g_tra_code": "lb", "g_ocr_code": "", }, { "en_name": "Macedonian", - "lo_name": "马其顿语", + "lo_name": hardcode_text("马其顿语"), "code": "mk", "g_tra_code": "mk", "g_ocr_code": "mk", }, { "en_name": "Malagasy", - "lo_name": "马尔加什语", + "lo_name": hardcode_text("马尔加什语"), "code": "mg", "g_tra_code": "mg", "g_ocr_code": "", }, { "en_name": "Malay", - "lo_name": "马来语", + "lo_name": hardcode_text("马来语"), "code": "ms", "g_tra_code": "ms", "g_ocr_code": "", }, { "en_name": "Malayalam", - "lo_name": "马拉雅拉姆语", + "lo_name": hardcode_text("马拉雅拉姆语"), "code": "ml", "g_tra_code": "ml", "g_ocr_code": "", }, { "en_name": "Maltese", - "lo_name": "马耳他语", + "lo_name": hardcode_text("马耳他语"), "code": "mt", "g_tra_code": "mt", "g_ocr_code": "", }, { "en_name": "Maori", - "lo_name": "毛利语", + "lo_name": hardcode_text("毛利语"), "code": "mi", "g_tra_code": "mi", "g_ocr_code": "", }, { "en_name": "Marathi", - "lo_name": "马拉语", + "lo_name": hardcode_text("马拉地语") or hardcode_text("马拉语"), "code": "mr", "g_tra_code": "mr", "g_ocr_code": "mr", }, { "en_name": "Mongolian", - "lo_name": "蒙古语", + "lo_name": hardcode_text("蒙古语"), "code": "mn", "g_tra_code": "mn", "g_ocr_code": "mn", }, { "en_name": "Myanmar (Burmese)", - "lo_name": "缅甸语", + "lo_name": hardcode_text("缅甸语"), "code": "my", "g_tra_code": "my", "g_ocr_code": "", @@ -495,280 +504,281 @@ class Language(Document): }, { "en_name": "Nepali", - "lo_name": "尼泊尔语", + "lo_name": hardcode_text("尼泊尔语"), "code": "ne", "g_tra_code": "ne", "g_ocr_code": "ne", }, { "en_name": "Norwegian", - "lo_name": "挪威语", + "lo_name": hardcode_text("挪威语"), "code": "no", "g_tra_code": "no", "g_ocr_code": "no", }, { "en_name": "Nyanja (Chichewa)", - "lo_name": "齐切瓦语", + "lo_name": hardcode_text("齐切瓦语 (尼扬贾语)") + or hardcode_text("齐切瓦语"), "code": "ny", "g_tra_code": "ny", "g_ocr_code": "", }, { "en_name": "Pashto", - "lo_name": "普什图语", + "lo_name": hardcode_text("普什图语"), "code": "ps", "g_tra_code": "ps", "g_ocr_code": "ps", }, { "en_name": "Persian", - "lo_name": "波斯语", + "lo_name": hardcode_text("波斯语"), "code": "fa", "g_tra_code": "fa", "g_ocr_code": "fa", }, { "en_name": "Polish", - "lo_name": "波兰语", + "lo_name": hardcode_text("波兰语"), "code": "pl", "g_tra_code": "pl", "g_ocr_code": "pl", }, { "en_name": "Portuguese (Portugal, Brazil)", - "lo_name": "葡萄牙语", + "lo_name": hardcode_text("葡萄牙语"), "code": "pt", "g_tra_code": "pt", "g_ocr_code": "pt", }, { "en_name": "Punjabi", - "lo_name": "旁遮普语", + "lo_name": hardcode_text("旁遮普语"), "code": "pa", "g_tra_code": "pa", "g_ocr_code": "", }, { "en_name": "Romanian", - "lo_name": "罗马尼亚语", + "lo_name": hardcode_text("罗马尼亚语"), "code": "ro", "g_tra_code": "ro", "g_ocr_code": "ro", }, { "en_name": "Russian", - "lo_name": "俄语", + "lo_name": hardcode_text("俄语"), "code": "ru", "g_tra_code": "ru", "g_ocr_code": "ru", }, { "en_name": "Samoan", - "lo_name": "萨摩亚语", + "lo_name": hardcode_text("萨摩亚语"), "code": "sm", "g_tra_code": "sm", "g_ocr_code": "", }, { "en_name": "Scots Gaelic", - "lo_name": "苏格兰盖尔语", + "lo_name": hardcode_text("苏格兰盖尔语"), "code": "gd", "g_tra_code": "gd", "g_ocr_code": "", }, { "en_name": "Sanskrit", - "lo_name": "梵文", + "lo_name": hardcode_text("梵文"), "code": "sa", "g_tra_code": "", "g_ocr_code": "sa", }, { "en_name": "Serbian", - "lo_name": "塞尔维亚语", + "lo_name": hardcode_text("塞尔维亚语"), "code": "sr", "g_tra_code": "sr", "g_ocr_code": "sr", }, { "en_name": "Sesotho", - "lo_name": "塞索托语", + "lo_name": hardcode_text("塞索托语"), "code": "st", "g_tra_code": "st", "g_ocr_code": "", }, { "en_name": "Shona", - "lo_name": "绍纳语", + "lo_name": hardcode_text("绍纳语"), "code": "sn", "g_tra_code": "sn", "g_ocr_code": "", }, { "en_name": "Sindhi", - "lo_name": "信德语", + "lo_name": hardcode_text("信德语"), "code": "sd", "g_tra_code": "sd", "g_ocr_code": "", }, { "en_name": "Sinhala (Sinhalese)", - "lo_name": "僧伽罗语", + "lo_name": hardcode_text("僧伽罗语"), "code": "si", "g_tra_code": "si", "g_ocr_code": "", }, { "en_name": "Slovak", - "lo_name": "斯洛伐克语", + "lo_name": hardcode_text("斯洛伐克语"), "code": "sk", "g_tra_code": "sk", "g_ocr_code": "sk", }, { "en_name": "Slovenian", - "lo_name": "斯卡洛文语", + "lo_name": hardcode_text("斯洛文尼亚语") or hardcode_text("斯卡洛文语"), "code": "sl", "g_tra_code": "sl", "g_ocr_code": "sl", }, { "en_name": "Somali", - "lo_name": "索马里语", + "lo_name": hardcode_text("索马里语"), "code": "so", "g_tra_code": "so", "g_ocr_code": "", }, { "en_name": "Spanish", - "lo_name": "西班牙语", + "lo_name": hardcode_text("西班牙语"), "code": "es", "g_tra_code": "es", "g_ocr_code": "es", }, { "en_name": "Sundanese", - "lo_name": "巽他语", + "lo_name": hardcode_text("巽他语"), "code": "su", "g_tra_code": "su", "g_ocr_code": "", }, { "en_name": "Swahili", - "lo_name": "斯瓦希里语", + "lo_name": hardcode_text("斯瓦希里语"), "code": "sw", "g_tra_code": "sw", "g_ocr_code": "", }, { "en_name": "Swedish", - "lo_name": "瑞典语", + "lo_name": hardcode_text("瑞典语"), "code": "sv", "g_tra_code": "sv", "g_ocr_code": "sv", }, { "en_name": "Tagalog (Filipino)", - "lo_name": "他加禄语(菲律宾语)", + "lo_name": hardcode_text("他加禄语(菲律宾语)"), "code": "tl", "g_tra_code": "tl", "g_ocr_code": "tl", }, { "en_name": "Tajik", - "lo_name": "塔吉克语", + "lo_name": hardcode_text("塔吉克语"), "code": "tg", "g_tra_code": "tg", "g_ocr_code": "", }, { "en_name": "Tamil", - "lo_name": "泰米尔语", + "lo_name": hardcode_text("泰米尔语"), "code": "ta", "g_tra_code": "ta", "g_ocr_code": "ta", }, { "en_name": "Telugu", - "lo_name": "泰卢固语", + "lo_name": hardcode_text("泰卢固语"), "code": "te", "g_tra_code": "te", "g_ocr_code": "", }, { "en_name": "Thai", - "lo_name": "泰语", + "lo_name": hardcode_text("泰语"), "code": "th", "g_tra_code": "th", "g_ocr_code": "th", }, { "en_name": "Turkish", - "lo_name": "土耳其语", + "lo_name": hardcode_text("土耳其语"), "code": "tr", "g_tra_code": "tr", "g_ocr_code": "tr", }, { "en_name": "Ukrainian", - "lo_name": "乌克兰语", + "lo_name": hardcode_text("乌克兰语"), "code": "uk", "g_tra_code": "uk", "g_ocr_code": "uk", }, { "en_name": "Urdu", - "lo_name": "乌尔都语", + "lo_name": hardcode_text("乌尔都语"), "code": "ur", "g_tra_code": "ur", "g_ocr_code": "ur", }, { "en_name": "Uzbek", - "lo_name": "乌兹别克语", + "lo_name": hardcode_text("乌兹别克语"), "code": "uz", "g_tra_code": "uz", "g_ocr_code": "uz", }, { "en_name": "Vietnamese", - "lo_name": "越南语", + "lo_name": hardcode_text("越南语"), "code": "vi", "g_tra_code": "vi", "g_ocr_code": "vi", }, { "en_name": "Welsh", - "lo_name": "威尔士语", + "lo_name": hardcode_text("威尔士语"), "code": "cy", "g_tra_code": "cy", "g_ocr_code": "", }, { "en_name": "Xhosa", - "lo_name": "科萨语", + "lo_name": hardcode_text("科萨语"), "code": "xh", "g_tra_code": "xh", "g_ocr_code": "", }, { "en_name": "Yiddish", - "lo_name": "意第绪语", + "lo_name": hardcode_text("意第绪语"), "code": "yi", "g_tra_code": "yi", "g_ocr_code": "", }, { "en_name": "Yoruba", - "lo_name": "约鲁巴语", + "lo_name": hardcode_text("约鲁巴语"), "code": "yo", "g_tra_code": "yo", "g_ocr_code": "", }, { "en_name": "Zulu", - "lo_name": "祖鲁语", + "lo_name": hardcode_text("祖鲁语"), "code": "zu", "g_tra_code": "zu", "g_ocr_code": "", @@ -779,7 +789,7 @@ class Language(Document): def init_system_languages(cls) -> None: """初始化语言表""" if cls.objects.count() > 0: - logger.debug("已存在语言表,跳过初始化") + logger.info(server_gettext("Language collection already initialized.")) return sort = 0 for lang in cls.SYSTEM_LANGUAGES_DATA: @@ -793,7 +803,9 @@ def init_system_languages(cls) -> None: sort=sort, ).save() sort += 1 - logger.debug(f"初始化语言表,共添加{len(cls.SYSTEM_LANGUAGES_DATA)}种语言") + logger.debug( + server_gettext("Initialized Language collection with %d languages"), sort + ) @classmethod def create( @@ -888,7 +900,7 @@ def codes(cls) -> List[str]: def clear(self) -> None: """禁止删除语言""" - pass + raise AssertionError(gettext("Language can not be deleted")) def to_api(self) -> Dict[str, Any]: """ @@ -898,7 +910,9 @@ def to_api(self) -> Dict[str, Any]: return { "id": str(self.id), "en_name": self.en_name, - "lo_name": self.lo_name, + # in non-zh locales gettext(hardcoded_id) should return localized name + # otherwise the hardcoded_id is just zh + "lo_name": gettext(self.lo_name) or self.lo_name, "i18n_name": self.i18n_name, "no_space": self.no_space, "code": self.code, diff --git a/app/translations/__init__.py b/app/translations/__init__.py index f40f4e9..33b5ff3 100644 --- a/app/translations/__init__.py +++ b/app/translations/__init__.py @@ -3,6 +3,7 @@ from flask import g, request from app.constants.locale import Locale import flask_babel +import app.config as _app_config logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) @@ -50,3 +51,15 @@ def lazy_gettext(msgid: str): translated = flask_babel.LazyString(lambda: gettext(msgid)) # logger.debug(f"lazy_get_text({msgid}) -> {translated}") return translated + + +def hardcode_text(msgid: str) -> str: + """ + used to capture hardcoded string as msgid + """ + return msgid + + +def server_gettext(msgid: str): + with flask_babel.force_locale(_app_config.BABEL_DEFAULT_LOCALE): + return gettext(msgid) diff --git a/app/translations/en/LC_MESSAGES/messages.po b/app/translations/en/LC_MESSAGES/messages.po index b60c075..2aa7e30 100644 --- a/app/translations/en/LC_MESSAGES/messages.po +++ b/app/translations/en/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2024-11-30 01:30+0900\n" +"POT-Creation-Date: 2024-12-15 18:26+0900\n" "PO-Revision-Date: 2017-04-14 15:38+0800\n" "Last-Translator: FULL NAME \n" "Language: en_US\n" @@ -368,11 +368,11 @@ msgstr "Auto" msgid "遵循浏览器设置" msgstr "Follow browser settings." -#: app/constants/locale.py:16 +#: app/constants/locale.py:16 app/models/language.py:58 msgid "中文(简体)" msgstr "Chinese (Simplified)" -#: app/constants/locale.py:17 +#: app/constants/locale.py:17 app/models/language.py:66 msgid "中文(繁体)" msgstr "Chinese (Traditional)" @@ -1034,6 +1034,442 @@ msgstr "Rejected." msgid "已被同意" msgstr "Agreed." +#: app/models/language.py:35 +msgid "日语" +msgstr "Japanese" + +#: app/models/language.py:43 +msgid "英语" +msgstr "English" + +#: app/models/language.py:50 +msgid "韩语" +msgstr "Korean" + +#: app/models/language.py:50 +msgid "朝鲜语(韩语)" +msgstr "Korean" + +#: app/models/language.py:74 +msgid "南非荷兰语" +msgstr "Afrikaans" + +#: app/models/language.py:81 +msgid "阿尔巴尼亚语" +msgstr "Albanian" + +#: app/models/language.py:88 +msgid "阿姆哈拉语" +msgstr "Amharic" + +#: app/models/language.py:95 +msgid "阿萨姆语" +msgstr "Assamese" + +#: app/models/language.py:102 +msgid "阿拉伯语" +msgstr "Arabic" + +#: app/models/language.py:109 +msgid "亚美尼亚语" +msgstr "Armenian" + +#: app/models/language.py:116 +msgid "阿塞拜疆语" +msgstr "Azerbaijani" + +#: app/models/language.py:123 +msgid "巴斯克语" +msgstr "Basque" + +#: app/models/language.py:130 +msgid "白俄罗斯语" +msgstr "Belarusian" + +#: app/models/language.py:137 +msgid "孟加拉语" +msgstr "Bengali" + +#: app/models/language.py:144 +msgid "波斯尼亚语" +msgstr "Bosnian" + +#: app/models/language.py:151 +msgid "保加利亚语" +msgstr "Bulgarian" + +#: app/models/language.py:158 +msgid "加泰罗尼亚语" +msgstr "Catalan" + +#: app/models/language.py:165 +msgid "宿务语" +msgstr "Cebuano" + +#: app/models/language.py:172 +msgid "科西嘉语" +msgstr "Corsican" + +#: app/models/language.py:179 +msgid "克罗地亚语" +msgstr "Croatian" + +#: app/models/language.py:186 +msgid "捷克语" +msgstr "Czech" + +#: app/models/language.py:193 +msgid "丹麦语" +msgstr "Danish" + +#: app/models/language.py:200 +msgid "荷兰语" +msgstr "Dutch" + +#: app/models/language.py:207 +msgid "世界语" +msgstr "Esperanto" + +#: app/models/language.py:214 +msgid "爱沙尼亚语" +msgstr "Estonian" + +#: app/models/language.py:221 +msgid "芬兰语" +msgstr "Finnish" + +#: app/models/language.py:228 +msgid "法语" +msgstr "French" + +#: app/models/language.py:235 +msgid "弗里斯兰语" +msgstr "Frisian" + +#: app/models/language.py:242 +msgid "加利西亚语" +msgstr "Galician" + +#: app/models/language.py:249 +msgid "格鲁吉亚语" +msgstr "Georgian" + +#: app/models/language.py:256 +msgid "德语" +msgstr "German" + +#: app/models/language.py:263 +msgid "希腊语" +msgstr "Greek" + +#: app/models/language.py:271 +msgid "古吉拉特语" +msgstr "Gujarati" + +#: app/models/language.py:278 +msgid "海地克里奥尔语" +msgstr "Haitian Creole" + +#: app/models/language.py:285 +msgid "豪萨语" +msgstr "Hausa" + +#: app/models/language.py:292 +msgid "夏威夷语" +msgstr "Hawaiian" + +#: app/models/language.py:299 +msgid "希伯来语" +msgstr "Hebrew" + +#: app/models/language.py:306 +msgid "印地语" +msgstr "Hindi" + +#: app/models/language.py:313 +msgid "苗语" +msgstr "Hmong" + +#: app/models/language.py:320 +msgid "匈牙利语" +msgstr "Hungarian" + +#: app/models/language.py:327 +msgid "冰岛语" +msgstr "Icelandic" + +#: app/models/language.py:334 +msgid "伊博语" +msgstr "Igbo" + +#: app/models/language.py:341 +msgid "印度尼西亚语" +msgstr "Indonesian" + +#: app/models/language.py:348 +msgid "爱尔兰语" +msgstr "Irish" + +#: app/models/language.py:355 +msgid "意大利语" +msgstr "Italian" + +#: app/models/language.py:362 +msgid "爪哇语" +msgstr "Javanese" + +#: app/models/language.py:370 +msgid "卡纳达语" +msgstr "Kannada" + +#: app/models/language.py:377 +msgid "哈萨克语" +msgstr "Kazakh" + +#: app/models/language.py:384 +msgid "高棉语" +msgstr "Khmer" + +#: app/models/language.py:392 +msgid "库尔德语" +msgstr "Kurdish" + +#: app/models/language.py:399 +msgid "吉尔吉斯语" +msgstr "Kyrgyz" + +#: app/models/language.py:406 +msgid "老挝语" +msgstr "Lao" + +#: app/models/language.py:414 +msgid "拉丁语" +msgstr "Latin" + +#: app/models/language.py:422 +msgid "拉脱维亚语" +msgstr "Latvian" + +#: app/models/language.py:429 +msgid "立陶宛语" +msgstr "Lithuanian" + +#: app/models/language.py:436 +msgid "卢森堡语" +msgstr "Luxembourgish" + +#: app/models/language.py:443 +msgid "马其顿语" +msgstr "Macedonian" + +#: app/models/language.py:450 +msgid "马尔加什语" +msgstr "Malagasy" + +#: app/models/language.py:457 +msgid "马来语" +msgstr "Malay" + +#: app/models/language.py:464 +msgid "马拉雅拉姆语" +msgstr "Malayalam" + +#: app/models/language.py:471 +msgid "马耳他语" +msgstr "Maltese" + +#: app/models/language.py:478 +msgid "毛利语" +msgstr "Maori" + +#: app/models/language.py:485 +msgid "马拉地语" +msgstr "Marathi" + +#: app/models/language.py:485 +msgid "马拉语" +msgstr "Marathi" + +#: app/models/language.py:492 +msgid "蒙古语" +msgstr "Mongolian" + +#: app/models/language.py:499 +msgid "缅甸语" +msgstr "Myanmar (Burmese)" + +#: app/models/language.py:507 +msgid "尼泊尔语" +msgstr "Nepali" + +#: app/models/language.py:514 +msgid "挪威语" +msgstr "Norwegian" + +#: app/models/language.py:521 +msgid "齐切瓦语 (尼扬贾语)" +msgstr "Nyanja (Chichewa)" + +#: app/models/language.py:522 +msgid "齐切瓦语" +msgstr "Nyanja (Chichewa)" + +#: app/models/language.py:529 +msgid "普什图语" +msgstr "Pashto" + +#: app/models/language.py:536 +msgid "波斯语" +msgstr "Persian" + +#: app/models/language.py:543 +msgid "波兰语" +msgstr "Polish" + +#: app/models/language.py:550 +msgid "葡萄牙语" +msgstr "Portuguese" + +#: app/models/language.py:557 +msgid "旁遮普语" +msgstr "Punjabi" + +#: app/models/language.py:564 +msgid "罗马尼亚语" +msgstr "Romanian" + +#: app/models/language.py:571 +msgid "俄语" +msgstr "Russian" + +#: app/models/language.py:578 +msgid "萨摩亚语" +msgstr "Samoan" + +#: app/models/language.py:585 +msgid "苏格兰盖尔语" +msgstr "Scots Gaelic" + +#: app/models/language.py:592 +msgid "梵文" +msgstr "Sanskrit" + +#: app/models/language.py:599 +msgid "塞尔维亚语" +msgstr "Serbian" + +#: app/models/language.py:606 +msgid "塞索托语" +msgstr "Sesotho" + +#: app/models/language.py:613 +msgid "绍纳语" +msgstr "Shona" + +#: app/models/language.py:620 +msgid "信德语" +msgstr "Sindhi" + +#: app/models/language.py:627 +msgid "僧伽罗语" +msgstr "Sinhala (Sinhalese)" + +#: app/models/language.py:634 +msgid "斯洛伐克语" +msgstr "Slovak" + +#: app/models/language.py:641 +msgid "斯洛文尼亚语" +msgstr "Slovenian" + +#: app/models/language.py:641 +msgid "斯卡洛文语" +msgstr "Slovenian" + +#: app/models/language.py:648 +msgid "索马里语" +msgstr "Somali" + +#: app/models/language.py:655 +msgid "西班牙语" +msgstr "Spanish" + +#: app/models/language.py:662 +msgid "巽他语" +msgstr "Sundanese" + +#: app/models/language.py:669 +msgid "斯瓦希里语" +msgstr "Swahili" + +#: app/models/language.py:676 +msgid "瑞典语" +msgstr "Swedish" + +#: app/models/language.py:683 +msgid "他加禄语(菲律宾语)" +msgstr "Tagalog (Filipino)" + +#: app/models/language.py:690 +msgid "塔吉克语" +msgstr "Tajik" + +#: app/models/language.py:697 +msgid "泰米尔语" +msgstr "Tamil" + +#: app/models/language.py:704 +msgid "泰卢固语" +msgstr "Telugu" + +#: app/models/language.py:711 +msgid "泰语" +msgstr "Thai" + +#: app/models/language.py:718 +msgid "土耳其语" +msgstr "Turkish" + +#: app/models/language.py:725 +msgid "乌克兰语" +msgstr "Ukrainian" + +#: app/models/language.py:732 +msgid "乌尔都语" +msgstr "Urdu" + +#: app/models/language.py:739 +msgid "乌兹别克语" +msgstr "Uzbek" + +#: app/models/language.py:746 +msgid "越南语" +msgstr "Vietnamese" + +#: app/models/language.py:753 +msgid "威尔士语" +msgstr "Welsh" + +#: app/models/language.py:760 +msgid "科萨语" +msgstr "Xhosa" + +#: app/models/language.py:767 +msgid "意第绪语" +msgstr "Yiddish" + +#: app/models/language.py:774 +msgid "约鲁巴语" +msgstr "Yoruba" + +#: app/models/language.py:781 +msgid "祖鲁语" +msgstr "Zulu" + +#: app/models/language.py:903 +msgid "Language can not be deleted" +msgstr "" + #: app/models/message.py:41 msgid "非系统消息类型" msgstr "Non-system message type" @@ -1278,11 +1714,11 @@ msgstr "Create a project set within the team." #: app/models/team.py:109 msgid "设置项目集" -msgstr "Set Portfolio" +msgstr "Project set configuration" #: app/models/team.py:110 msgid "修改团队内项目集的设置" -msgstr "Modify the settings of the project collection within the team." +msgstr "Modify the settings of the project sets within the team." #: app/models/team.py:113 msgid "删除项目集" @@ -1290,7 +1726,7 @@ msgstr "Delete project set" #: app/models/team.py:114 msgid "删除团队内的项目集" -msgstr "Delete the portfolio within the team." +msgstr "Delete the project sets within the team." #: app/models/team.py:117 msgid "使用自动标记额度" @@ -1443,6 +1879,9 @@ msgstr "No valid parameters." #~ msgid "此邮箱已存在,您可以直接登录或尝试其他邮箱" #~ msgstr "" -#~ msgid "站点支持语言: " -#~ msgstr "" +#~ msgid "Language collection already initialized." +#~ msgstr "已存在语言表,跳过初始化" + +#~ msgid "Initialized Language collection with %d languages" +#~ msgstr "初始化语言表,共添加 %d 种语言" diff --git a/app/translations/zh/LC_MESSAGES/messages.po b/app/translations/zh/LC_MESSAGES/messages.po index 257fb17..932900c 100644 --- a/app/translations/zh/LC_MESSAGES/messages.po +++ b/app/translations/zh/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2024-11-30 01:30+0900\n" +"POT-Creation-Date: 2024-12-15 18:26+0900\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language: zh\n" @@ -350,11 +350,11 @@ msgstr "自动" msgid "遵循浏览器设置" msgstr "遵循浏览器设置" -#: app/constants/locale.py:16 +#: app/constants/locale.py:16 app/models/language.py:58 msgid "中文(简体)" msgstr "中文(简体)" -#: app/constants/locale.py:17 +#: app/constants/locale.py:17 app/models/language.py:66 msgid "中文(繁体)" msgstr "中文(繁体)" @@ -1006,6 +1006,442 @@ msgstr "已被拒绝" msgid "已被同意" msgstr "已被同意" +#: app/models/language.py:35 +msgid "日语" +msgstr "" + +#: app/models/language.py:43 +msgid "英语" +msgstr "" + +#: app/models/language.py:50 +msgid "韩语" +msgstr "" + +#: app/models/language.py:50 +msgid "朝鲜语(韩语)" +msgstr "" + +#: app/models/language.py:74 +msgid "南非荷兰语" +msgstr "" + +#: app/models/language.py:81 +msgid "阿尔巴尼亚语" +msgstr "" + +#: app/models/language.py:88 +msgid "阿姆哈拉语" +msgstr "" + +#: app/models/language.py:95 +msgid "阿萨姆语" +msgstr "" + +#: app/models/language.py:102 +msgid "阿拉伯语" +msgstr "" + +#: app/models/language.py:109 +msgid "亚美尼亚语" +msgstr "" + +#: app/models/language.py:116 +msgid "阿塞拜疆语" +msgstr "" + +#: app/models/language.py:123 +msgid "巴斯克语" +msgstr "" + +#: app/models/language.py:130 +msgid "白俄罗斯语" +msgstr "" + +#: app/models/language.py:137 +msgid "孟加拉语" +msgstr "" + +#: app/models/language.py:144 +msgid "波斯尼亚语" +msgstr "" + +#: app/models/language.py:151 +msgid "保加利亚语" +msgstr "" + +#: app/models/language.py:158 +msgid "加泰罗尼亚语" +msgstr "" + +#: app/models/language.py:165 +msgid "宿务语" +msgstr "" + +#: app/models/language.py:172 +msgid "科西嘉语" +msgstr "" + +#: app/models/language.py:179 +msgid "克罗地亚语" +msgstr "" + +#: app/models/language.py:186 +msgid "捷克语" +msgstr "" + +#: app/models/language.py:193 +msgid "丹麦语" +msgstr "" + +#: app/models/language.py:200 +msgid "荷兰语" +msgstr "" + +#: app/models/language.py:207 +msgid "世界语" +msgstr "" + +#: app/models/language.py:214 +msgid "爱沙尼亚语" +msgstr "" + +#: app/models/language.py:221 +msgid "芬兰语" +msgstr "" + +#: app/models/language.py:228 +msgid "法语" +msgstr "" + +#: app/models/language.py:235 +msgid "弗里斯兰语" +msgstr "" + +#: app/models/language.py:242 +msgid "加利西亚语" +msgstr "" + +#: app/models/language.py:249 +msgid "格鲁吉亚语" +msgstr "" + +#: app/models/language.py:256 +msgid "德语" +msgstr "" + +#: app/models/language.py:263 +msgid "希腊语" +msgstr "" + +#: app/models/language.py:271 +msgid "古吉拉特语" +msgstr "" + +#: app/models/language.py:278 +msgid "海地克里奥尔语" +msgstr "" + +#: app/models/language.py:285 +msgid "豪萨语" +msgstr "" + +#: app/models/language.py:292 +msgid "夏威夷语" +msgstr "" + +#: app/models/language.py:299 +msgid "希伯来语" +msgstr "" + +#: app/models/language.py:306 +msgid "印地语" +msgstr "" + +#: app/models/language.py:313 +msgid "苗语" +msgstr "" + +#: app/models/language.py:320 +msgid "匈牙利语" +msgstr "" + +#: app/models/language.py:327 +msgid "冰岛语" +msgstr "" + +#: app/models/language.py:334 +msgid "伊博语" +msgstr "" + +#: app/models/language.py:341 +msgid "印度尼西亚语" +msgstr "" + +#: app/models/language.py:348 +msgid "爱尔兰语" +msgstr "" + +#: app/models/language.py:355 +msgid "意大利语" +msgstr "" + +#: app/models/language.py:362 +msgid "爪哇语" +msgstr "" + +#: app/models/language.py:370 +msgid "卡纳达语" +msgstr "" + +#: app/models/language.py:377 +msgid "哈萨克语" +msgstr "" + +#: app/models/language.py:384 +msgid "高棉语" +msgstr "" + +#: app/models/language.py:392 +msgid "库尔德语" +msgstr "" + +#: app/models/language.py:399 +msgid "吉尔吉斯语" +msgstr "" + +#: app/models/language.py:406 +msgid "老挝语" +msgstr "" + +#: app/models/language.py:414 +msgid "拉丁语" +msgstr "" + +#: app/models/language.py:422 +msgid "拉脱维亚语" +msgstr "" + +#: app/models/language.py:429 +msgid "立陶宛语" +msgstr "" + +#: app/models/language.py:436 +msgid "卢森堡语" +msgstr "" + +#: app/models/language.py:443 +msgid "马其顿语" +msgstr "" + +#: app/models/language.py:450 +msgid "马尔加什语" +msgstr "" + +#: app/models/language.py:457 +msgid "马来语" +msgstr "" + +#: app/models/language.py:464 +msgid "马拉雅拉姆语" +msgstr "" + +#: app/models/language.py:471 +msgid "马耳他语" +msgstr "" + +#: app/models/language.py:478 +msgid "毛利语" +msgstr "" + +#: app/models/language.py:485 +msgid "马拉地语" +msgstr "" + +#: app/models/language.py:485 +msgid "马拉语" +msgstr "" + +#: app/models/language.py:492 +msgid "蒙古语" +msgstr "" + +#: app/models/language.py:499 +msgid "缅甸语" +msgstr "" + +#: app/models/language.py:507 +msgid "尼泊尔语" +msgstr "" + +#: app/models/language.py:514 +msgid "挪威语" +msgstr "" + +#: app/models/language.py:521 +msgid "齐切瓦语 (尼扬贾语)" +msgstr "" + +#: app/models/language.py:522 +msgid "齐切瓦语" +msgstr "" + +#: app/models/language.py:529 +msgid "普什图语" +msgstr "" + +#: app/models/language.py:536 +msgid "波斯语" +msgstr "" + +#: app/models/language.py:543 +msgid "波兰语" +msgstr "" + +#: app/models/language.py:550 +msgid "葡萄牙语" +msgstr "" + +#: app/models/language.py:557 +msgid "旁遮普语" +msgstr "" + +#: app/models/language.py:564 +msgid "罗马尼亚语" +msgstr "" + +#: app/models/language.py:571 +msgid "俄语" +msgstr "" + +#: app/models/language.py:578 +msgid "萨摩亚语" +msgstr "" + +#: app/models/language.py:585 +msgid "苏格兰盖尔语" +msgstr "" + +#: app/models/language.py:592 +msgid "梵文" +msgstr "" + +#: app/models/language.py:599 +msgid "塞尔维亚语" +msgstr "" + +#: app/models/language.py:606 +msgid "塞索托语" +msgstr "" + +#: app/models/language.py:613 +msgid "绍纳语" +msgstr "" + +#: app/models/language.py:620 +msgid "信德语" +msgstr "" + +#: app/models/language.py:627 +msgid "僧伽罗语" +msgstr "" + +#: app/models/language.py:634 +msgid "斯洛伐克语" +msgstr "" + +#: app/models/language.py:641 +msgid "斯洛文尼亚语" +msgstr "" + +#: app/models/language.py:641 +msgid "斯卡洛文语" +msgstr "" + +#: app/models/language.py:648 +msgid "索马里语" +msgstr "" + +#: app/models/language.py:655 +msgid "西班牙语" +msgstr "" + +#: app/models/language.py:662 +msgid "巽他语" +msgstr "" + +#: app/models/language.py:669 +msgid "斯瓦希里语" +msgstr "" + +#: app/models/language.py:676 +msgid "瑞典语" +msgstr "" + +#: app/models/language.py:683 +msgid "他加禄语(菲律宾语)" +msgstr "" + +#: app/models/language.py:690 +msgid "塔吉克语" +msgstr "" + +#: app/models/language.py:697 +msgid "泰米尔语" +msgstr "" + +#: app/models/language.py:704 +msgid "泰卢固语" +msgstr "" + +#: app/models/language.py:711 +msgid "泰语" +msgstr "" + +#: app/models/language.py:718 +msgid "土耳其语" +msgstr "" + +#: app/models/language.py:725 +msgid "乌克兰语" +msgstr "" + +#: app/models/language.py:732 +msgid "乌尔都语" +msgstr "" + +#: app/models/language.py:739 +msgid "乌兹别克语" +msgstr "" + +#: app/models/language.py:746 +msgid "越南语" +msgstr "" + +#: app/models/language.py:753 +msgid "威尔士语" +msgstr "" + +#: app/models/language.py:760 +msgid "科萨语" +msgstr "" + +#: app/models/language.py:767 +msgid "意第绪语" +msgstr "" + +#: app/models/language.py:774 +msgid "约鲁巴语" +msgstr "" + +#: app/models/language.py:781 +msgid "祖鲁语" +msgstr "" + +#: app/models/language.py:903 +msgid "Language can not be deleted" +msgstr "" + #: app/models/message.py:41 msgid "非系统消息类型" msgstr "非系统消息类型" @@ -1384,3 +1820,21 @@ msgstr "没有有效参数" #~ msgid "站点支持语言: " #~ msgstr "" +#~ msgid "弗里西亚语" +#~ msgstr "" + +#~ msgid "印尼语" +#~ msgstr "" + +#~ msgid "尼扬扎语(奇切瓦语)" +#~ msgstr "" + +#~ msgid "葡萄牙语(葡萄牙,巴西)" +#~ msgstr "" + +#~ msgid "Language collection already initialized." +#~ msgstr "" + +#~ msgid "Initialized Language collection with %d languages" +#~ msgstr "" +