Fix #139838: UI: Improve languages list and labels
Edit the language list to make it simpler to scan. - Display languages in a form "Language (Variant)", such as "English (US)" instead of "American English" and "Portuguese (Brazil)" instead of "Brazilian Portuguese". This allows alphabetical sorting by language first. This does not apply to endonyms (languages in their own language). - Use a dash instead of parentheses to separate the endonyms. - Deduplicate languages (Automatic, American English, British English), which all are in English and don't appear in another language. - Remove language categories as headers. They are replaced with percentages in the language tooltips. The percentages are generated in utils_languages_menu.py and stored in locale/languages. Co-authored-by: Bastien Montagne <bastien@blender.org> Pull Request: https://projects.blender.org/blender/blender/pulls/140087
This commit is contained in:
committed by
Bastien Montagne
parent
39a138aa92
commit
798f85a710
@@ -1128,9 +1128,6 @@ def dump_messages(do_messages, do_checks, settings):
|
||||
for lng in settings.LANGUAGES:
|
||||
process_msg(msgs, settings.DEFAULT_CONTEXT, lng[1], "Languages’ labels from bl_i18n_utils/settings.py",
|
||||
reports, None, settings)
|
||||
for cat in settings.LANGUAGES_CATEGORIES:
|
||||
process_msg(msgs, settings.DEFAULT_CONTEXT, cat[1],
|
||||
"Language categories’ labels from bl_i18n_utils/settings.py", reports, None, settings)
|
||||
|
||||
# Get strings from asset catalogs and blend files.
|
||||
# This loads each asset blend file in turn.
|
||||
|
||||
@@ -25,76 +25,70 @@ except ModuleNotFoundError:
|
||||
###############################################################################
|
||||
|
||||
# The languages defined in Blender.
|
||||
LANGUAGES_CATEGORIES = (
|
||||
# Min completeness level, UI English label.
|
||||
(0.95, "Complete"),
|
||||
(0.33, "In Progress"),
|
||||
(-1.0, "Starting"),
|
||||
)
|
||||
LANGUAGES = (
|
||||
# ID, UI English label, ISO code.
|
||||
(0, "Automatic (Automatic)", "DEFAULT"),
|
||||
(1, "American English (American English)", "en_US"),
|
||||
(2, "Japanese (日本語)", "ja_JP"),
|
||||
(3, "Dutch (Nederlands)", "nl_NL"),
|
||||
(4, "Italian (Italiano)", "it_IT"),
|
||||
(5, "German (Deutsch)", "de_DE"),
|
||||
(6, "Finnish (Suomi)", "fi_FI"),
|
||||
(7, "Swedish (Svenska)", "sv_SE"),
|
||||
(8, "French (Français)", "fr_FR"),
|
||||
(9, "Spanish (Español)", "es"),
|
||||
(10, "Catalan (Català)", "ca_AD"),
|
||||
(11, "Czech (Čeština)", "cs_CZ"),
|
||||
(12, "Portuguese (Português)", "pt_PT"),
|
||||
(13, "Simplified Chinese (简体中文)", "zh_HANS"),
|
||||
(14, "Traditional Chinese (繁體中文)", "zh_HANT"),
|
||||
(15, "Russian (Русский)", "ru_RU"),
|
||||
(16, "Croatian (Hrvatski)", "hr_HR"),
|
||||
(17, "Serbian (Српски)", "sr_RS"),
|
||||
(18, "Ukrainian (Українська)", "uk_UA"),
|
||||
(19, "Polish (Polski)", "pl_PL"),
|
||||
(20, "Romanian (Român)", "ro_RO"),
|
||||
(0, "Automatic", "DEFAULT"),
|
||||
(1, "English (US)", "en_US"),
|
||||
(2, "Japanese - 日本語", "ja_JP"),
|
||||
(3, "Dutch - Nederlands", "nl_NL"),
|
||||
(4, "Italian - Italiano", "it_IT"),
|
||||
(5, "German - Deutsch", "de_DE"),
|
||||
(6, "Finnish - Suomi", "fi_FI"),
|
||||
(7, "Swedish - Svenska", "sv_SE"),
|
||||
(8, "French - Français", "fr_FR"),
|
||||
(9, "Spanish - Español", "es"),
|
||||
(10, "Catalan - Català", "ca_AD"),
|
||||
(11, "Czech - Čeština", "cs_CZ"),
|
||||
(12, "Portuguese (Portugal) - Português europeu", "pt_PT"),
|
||||
(13, "Chinese (Simplified) - 简体中文", "zh_HANS"),
|
||||
(14, "Chinese (Traditional) - 繁體中文", "zh_HANT"),
|
||||
(15, "Russian - Русский", "ru_RU"),
|
||||
(16, "Croatian - Hrvatski", "hr_HR"),
|
||||
(17, "Serbian (Cyrillic) - Српски", "sr_RS"),
|
||||
(18, "Ukrainian - Українська", "uk_UA"),
|
||||
(19, "Polish - Polski", "pl_PL"),
|
||||
(20, "Romanian - Român", "ro_RO"),
|
||||
# Using the utf8 flipped form of Arabic (العربية).
|
||||
(21, "Arabic (ﺔﻴﺑﺮﻌﻟﺍ)", "ar_EG"),
|
||||
(22, "Bulgarian (Български)", "bg_BG"),
|
||||
(23, "Greek (Ελληνικά)", "el_GR"),
|
||||
(24, "Korean (한국어)", "ko_KR"),
|
||||
(25, "Nepali (नेपाली)", "ne_NP"),
|
||||
(21, "Arabic - ﺔﻴﺑﺮﻌﻟﺍ", "ar_EG"),
|
||||
(22, "Bulgarian - Български", "bg_BG"),
|
||||
(23, "Greek - Ελληνικά", "el_GR"),
|
||||
(24, "Korean - 한국어", "ko_KR"),
|
||||
(25, "Nepali - नेपाली", "ne_NP"),
|
||||
# Using the utf8 flipped form of Persian (فارسی).
|
||||
(26, "Persian (ﯽﺳﺭﺎﻓ)", "fa_IR"),
|
||||
(27, "Indonesian (Bahasa indonesia)", "id_ID"),
|
||||
(28, "Serbian Latin (Srpski latinica)", "sr_RS@latin"),
|
||||
(29, "Kyrgyz (Кыргыз тили)", "ky_KG"),
|
||||
(30, "Turkish (Türkçe)", "tr_TR"),
|
||||
(31, "Hungarian (Magyar)", "hu_HU"),
|
||||
(32, "Brazilian Portuguese (Português do Brasil)", "pt_BR"),
|
||||
(26, "Persian - ﯽﺳﺭﺎﻓ", "fa_IR"),
|
||||
(27, "Indonesian - Bahasa indonesia", "id_ID"),
|
||||
(28, "Serbian (Latin) - Srpski latinica", "sr_RS@latin"),
|
||||
(29, "Kyrgyz - Кыргыз тили", "ky_KG"),
|
||||
(30, "Turkish - Türkçe", "tr_TR"),
|
||||
(31, "Hungarian - Magyar", "hu_HU"),
|
||||
(32, "Portuguese (Brazil) - Português brasileiro", "pt_BR"),
|
||||
# Using the utf8 flipped form of Hebrew (עִבְרִית)).
|
||||
(33, "Hebrew (תירִבְעִ)", "he_IL"),
|
||||
(34, "Estonian (Eesti keel)", "et_EE"),
|
||||
(35, "Esperanto (Esperanto)", "eo"),
|
||||
(33, "Hebrew - תירִבְעִ", "he_IL"),
|
||||
(34, "Estonian - Eesti keel", "et_EE"),
|
||||
(35, "Esperanto - Esperanto", "eo"),
|
||||
# 36 is free, used to be 'Spanish from Spain' (`es_ES`).
|
||||
(37, "Amharic (አማርኛ)", "am_ET"),
|
||||
(38, "Uzbek (Oʻzbek)", "uz_UZ@latin"),
|
||||
(39, "Uzbek Cyrillic (Ўзбек)", "uz_UZ@cyrillic"),
|
||||
(40, "Hindi (हिन्दी)", "hi_IN"),
|
||||
(41, "Vietnamese (Tiếng Việt)", "vi_VN"),
|
||||
(42, "Basque (Euskara)", "eu_EU"),
|
||||
(43, "Hausa (Hausa)", "ha"),
|
||||
(44, "Kazakh (Қазақша)", "kk_KZ"),
|
||||
(45, "Abkhaz (Аԥсуа бызшәа)", "ab"),
|
||||
(46, "Thai (ภาษาไทย)", "th_TH"),
|
||||
(47, "Slovak (Slovenčina)", "sk_SK"),
|
||||
(48, "Georgian (ქართული)", "ka"),
|
||||
(49, "Tamil (தமிழ்)", "ta"),
|
||||
(50, "Khmer (ខ្មែរ)", "km"),
|
||||
(51, "Swahili (Kiswahili)", "sw"),
|
||||
(52, "Belarusian (беларуску)", "be"),
|
||||
(53, "Danish (Dansk)", "da"),
|
||||
(54, "Slovenian (Slovenščina)", "sl"),
|
||||
(37, "Amharic - አማርኛ", "am_ET"),
|
||||
(38, "Uzbek (Latin) - Oʻzbek", "uz_UZ@latin"),
|
||||
(39, "Uzbek (Cyrillic) - Ўзбек", "uz_UZ@cyrillic"),
|
||||
(40, "Hindi - हिन्दी", "hi_IN"),
|
||||
(41, "Vietnamese - Tiếng Việt", "vi_VN"),
|
||||
(42, "Basque - Euskara", "eu_EU"),
|
||||
(43, "Hausa - Hausa", "ha"),
|
||||
(44, "Kazakh - Қазақша", "kk_KZ"),
|
||||
(45, "Abkhaz - Аԥсуа бызшәа", "ab"),
|
||||
(46, "Thai - ภาษาไทย", "th_TH"),
|
||||
(47, "Slovak - Slovenčina", "sk_SK"),
|
||||
(48, "Georgian - ქართული", "ka"),
|
||||
(49, "Tamil - தமிழ்", "ta"),
|
||||
(50, "Khmer - ខ្មែរ", "km"),
|
||||
(51, "Swahili - Kiswahili", "sw"),
|
||||
(52, "Belarusian - беларуску", "be"),
|
||||
(53, "Danish - Dansk", "da"),
|
||||
(54, "Slovenian - Slovenščina", "sl"),
|
||||
# Using the utf8 flipped form of Urdu (اُردُو).
|
||||
(55, "Urdu (وُدرُا)", "ur"),
|
||||
(56, "Lithuanian (Lietuviškai)", "lt"),
|
||||
(57, "British English (British English)", "en_GB"),
|
||||
(55, "Urdu - وُدرُا", "ur"),
|
||||
(56, "Lithuanian - Lietuviškai", "lt"),
|
||||
(57, "English (UK)", "en_GB"),
|
||||
)
|
||||
|
||||
# Default context, in py (keep in sync with `BLT_translation.hh`)!
|
||||
|
||||
@@ -31,23 +31,22 @@ def gen_menu_file(stats, settings):
|
||||
else:
|
||||
tmp.append((0.0, uid_num, label, uid, MISSING))
|
||||
stats = tmp
|
||||
limits = sorted(settings.LANGUAGES_CATEGORIES, key=lambda it: it[0], reverse=True)
|
||||
idx = 0
|
||||
stats = sorted(stats, key=lambda it: it[0], reverse=True)
|
||||
langs_cats = [[] for i in range(len(limits))]
|
||||
langs = []
|
||||
highest_uid = 0
|
||||
for lvl, uid_num, label, uid, flag in stats:
|
||||
if lvl < limits[idx][0]:
|
||||
# Sub-sort languages by ISO-codes.
|
||||
langs_cats[idx].sort(key=lambda it: it[2])
|
||||
idx += 1
|
||||
if lvl < settings.IMPORT_MIN_LEVEL and flag == OK:
|
||||
flag = TOOLOW
|
||||
langs_cats[idx].append((uid_num, label, uid, flag))
|
||||
if uid_num == 0:
|
||||
# Insert default language (Automatic) at index 0, after sorting.
|
||||
default_lang = (uid_num, label, uid, flag, lvl)
|
||||
continue
|
||||
langs.append((uid_num, label, uid, flag, lvl))
|
||||
if abs(uid_num) > highest_uid:
|
||||
highest_uid = abs(uid_num)
|
||||
# Sub-sort last group of languages by ISO-codes!
|
||||
langs_cats[idx].sort(key=lambda it: it[2])
|
||||
# Sort languages by name.
|
||||
langs.sort(key=lambda it: it[1])
|
||||
langs.insert(0, default_lang)
|
||||
data_lines = [
|
||||
"# File used by Blender to know which languages (translations) are available, ",
|
||||
"# and to generate translation menu.",
|
||||
@@ -57,22 +56,13 @@ def gen_menu_file(stats, settings):
|
||||
"# ID must be unique, except for 0 value (marks categories for menu).",
|
||||
"# Line starting with a # are comments!",
|
||||
"#",
|
||||
"# Automatically generated by bl_i18n_utils/update_languages_menu.py script.",
|
||||
"# Automatically generated by bl_i18n_utils/utils_languages_menu.py script.",
|
||||
"# Highest ID currently in use: {}".format(highest_uid),
|
||||
]
|
||||
for cat, langs_cat in zip(limits, langs_cats):
|
||||
data_lines.append("#")
|
||||
# Write "category menu label"...
|
||||
if langs_cat:
|
||||
data_lines.append("0:{}:".format(cat[1]))
|
||||
for uid_num, label, uid, flag, lvl in langs:
|
||||
if flag == OK:
|
||||
data_lines.append("{}:{}:{}:{}%".format(uid_num, label, uid, round(lvl * 100)))
|
||||
else:
|
||||
# Do not write the category if it has no language!
|
||||
data_lines.append("# Void category! #0:{}:".format(cat[1]))
|
||||
# ...and all matching language entries!
|
||||
for uid_num, label, uid, flag in langs_cat:
|
||||
if flag == OK:
|
||||
data_lines.append("{}:{}:{}".format(uid_num, label, uid))
|
||||
else:
|
||||
# Non-existing, commented entry!
|
||||
data_lines.append("# {} #{}:{}:{}".format(FLAG_MESSAGES[flag], uid_num, label, uid))
|
||||
# Non-existing, commented entry!
|
||||
data_lines.append("# {} #{}:{}:{}:{}%".format(FLAG_MESSAGES[flag], uid_num, label, uid, round(lvl * 100)))
|
||||
return data_lines
|
||||
|
||||
@@ -50,18 +50,18 @@ static int num_locales_menu = 0;
|
||||
|
||||
static void free_locales()
|
||||
{
|
||||
if (locales) {
|
||||
if (locales_menu) {
|
||||
int idx = num_locales_menu - 1; /* Last item does not need to be freed! */
|
||||
while (idx--) {
|
||||
MEM_freeN(locales_menu[idx].identifier);
|
||||
MEM_freeN(locales_menu[idx].identifier); /* Also frees locales's relevant value! */
|
||||
MEM_freeN(locales_menu[idx].name);
|
||||
MEM_freeN(locales_menu[idx].description); /* Also frees locales's relevant value! */
|
||||
MEM_freeN(locales_menu[idx].description);
|
||||
}
|
||||
|
||||
MEM_freeN(locales);
|
||||
locales = nullptr;
|
||||
}
|
||||
MEM_SAFE_FREE(locales_menu);
|
||||
/* Allocated strings in #locales are shared with #locales_menu[idx].identifier, which are already
|
||||
* freed above, or are static strings. */
|
||||
MEM_SAFE_FREE(locales);
|
||||
num_locales = num_locales_menu = 0;
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ static void fill_locales()
|
||||
if (num_locales > 0) {
|
||||
locales = MEM_calloc_arrayN<const char *>(num_locales, __func__);
|
||||
while (line) {
|
||||
const char *loc, *sep1, *sep2, *sep3;
|
||||
const char *loc, *desc, *sep1, *sep2, *sep3;
|
||||
|
||||
char *str = (char *)line->link;
|
||||
if (ELEM(str[0], '#', '\0')) {
|
||||
@@ -133,14 +133,19 @@ static void fill_locales()
|
||||
|
||||
if (sep3) {
|
||||
locales_menu[idx].identifier = loc = BLI_strdupn(sep2, sep3 - sep2);
|
||||
|
||||
sep3++;
|
||||
desc = BLI_sprintfN("Locale code: %s. Translation progress: %s", loc, sep3);
|
||||
}
|
||||
else {
|
||||
locales_menu[idx].identifier = loc = BLI_strdup(sep2);
|
||||
desc = BLI_strdup(sep2);
|
||||
}
|
||||
|
||||
if (id == 0) {
|
||||
/* The DEFAULT/Automatic item... */
|
||||
if (BLI_strnlen(loc, 2)) {
|
||||
MEM_freeN(desc); /* Not used here. */
|
||||
locales[id] = "";
|
||||
/* Keep this tip in sync with the one in rna_userdef
|
||||
* (rna_enum_language_default_items). */
|
||||
@@ -148,13 +153,15 @@ static void fill_locales()
|
||||
"Automatically choose system's defined language "
|
||||
"if available, or fall-back to English");
|
||||
}
|
||||
/* Menu "label", not to be stored in locales! */
|
||||
/* Menu "label", not to be stored in locales!
|
||||
* NOTE: Not used since Blender 4.5. */
|
||||
else {
|
||||
locales_menu[idx].description = BLI_strdup("");
|
||||
locales_menu[idx].description = desc;
|
||||
}
|
||||
}
|
||||
else {
|
||||
locales[id] = locales_menu[idx].description = BLI_strdup(loc);
|
||||
locales[id] = loc;
|
||||
locales_menu[idx].description = desc;
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user