From 4746b8bf3717b99ec7b280b9408cb855dc9e5d0e Mon Sep 17 00:00:00 2001 From: Softer Date: Tue, 28 Apr 2026 17:19:38 +0300 Subject: [PATCH 1/2] Offer to apply archinstall language to target system locale and timezone After picking an installer language with a known locale mapping, prompt the user to apply sys_lang, sys_enc, console_font, and (where the country maps to a single IANA zone) timezone to the target system. Each row is shown only when its target value differs from the current setting, so re-picking a language with fewer mappings resets stale fields too. default_timezone is set in languages.json only for unambiguous single mainland zones; multi-zone countries (en_US, ru_RU, es_ES, pt_BR, ...) and codes that span countries are left without a default. Timezone candidates are validated against list_timezones(). --- archinstall/lib/global_menu.py | 82 ++++++++++++++++++++- archinstall/lib/models/locale.py | 63 +++++++++++++++- archinstall/lib/translationhandler.py | 28 ++++++- archinstall/locales/base.pot | 6 ++ archinstall/locales/languages.json | 74 +++++++++---------- archinstall/locales/uk/LC_MESSAGES/base.mo | Bin 87112 -> 87407 bytes archinstall/locales/uk/LC_MESSAGES/base.po | 6 ++ 7 files changed, 214 insertions(+), 45 deletions(-) diff --git a/archinstall/lib/global_menu.py b/archinstall/lib/global_menu.py index cdd820a943..51b18869fa 100644 --- a/archinstall/lib/global_menu.py +++ b/archinstall/lib/global_menu.py @@ -8,11 +8,14 @@ from archinstall.lib.bootloader.utils import validate_bootloader_layout from archinstall.lib.configuration import ConfigurationOutput, save_config from archinstall.lib.disk.disk_menu import DiskLayoutConfigurationMenu +from archinstall.lib.exceptions import SysCallError from archinstall.lib.general.general_menu import select_hostname, select_ntp, select_timezone from archinstall.lib.general.system_menu import select_kernel, select_swap from archinstall.lib.hardware import SysInfo +from archinstall.lib.locale import list_timezones from archinstall.lib.locale.locale_menu import LocaleMenu from archinstall.lib.menu.abstract_menu import AbstractMenu, SpecialMenuKey +from archinstall.lib.menu.helpers import Confirmation from archinstall.lib.mirror.mirror_handler import MirrorListHandler from archinstall.lib.mirror.mirror_menu import MirrorMenu from archinstall.lib.models.application import ApplicationConfiguration, ZramConfiguration @@ -27,13 +30,14 @@ from archinstall.lib.models.pacman import PacmanConfiguration from archinstall.lib.models.profile import ProfileConfiguration from archinstall.lib.network.network_menu import select_network -from archinstall.lib.output import FormattedOutput +from archinstall.lib.output import FormattedOutput, debug from archinstall.lib.packages.packages import list_available_packages, select_additional_packages from archinstall.lib.pacman.config import PacmanConfig from archinstall.lib.pacman.pacman_menu import PacmanMenu -from archinstall.lib.translationhandler import Language, tr, translation_handler +from archinstall.lib.translationhandler import DEFAULT_TIMEZONE, Language, tr, translation_handler from archinstall.tui.ui.components import tui from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup +from archinstall.tui.ui.result import ResultType class GlobalMenu(AbstractMenu[None]): @@ -160,7 +164,7 @@ def _get_menu_options(self) -> list[MenuItem]: MenuItem( text=tr('Timezone'), action=select_timezone, - value='UTC', + value=DEFAULT_TIMEZONE, preview_action=self._prev_tz, key='timezone', ), @@ -254,8 +258,80 @@ async def _select_archinstall_language(self, preset: Language) -> Language: self._update_lang_text() + await self._maybe_apply_language_to_locale(language) + return language + async def _maybe_apply_language_to_locale(self, language: Language) -> None: + """Offer to mirror the selected archinstall language into the target system locale. + + Triggered only when the language has a sys_lang mapping, since otherwise + there is no target locale to offer. Console font and timezone rows are + added to the prompt only when their language-derived target value differs + from the current setting, so re-picking a language with fewer mappings + (for example switching from Ukrainian to German, which has no console_font + of its own) resets the stale Ukrainian font alongside the new locale. + """ + if not language.sys_lang: + return + + locale_item = self._item_group.find_by_key('locale_config') + locale_config: LocaleConfiguration | None = locale_item.value + if not locale_config: + return + + tz_item = self._item_group.find_by_key('timezone') + current_tz: str = tz_item.value or DEFAULT_TIMEZONE + target_tz = language.target_timezone + offer_tz = self._is_timezone_offerable(target_tz, current_tz) + + diff = locale_config.language_diff(language) + if diff.is_empty() and not offer_tz: + return + + rows = diff.labeled_rows() + if offer_tz: + rows.append((tr('Timezone'), target_tz)) + + if not await self._confirm_locale_apply(rows): + return + + locale_config.apply_language_diff(diff) + if offer_tz: + tz_item.value = target_tz + + def _is_timezone_offerable(self, target_tz: str, current_tz: str) -> bool: + """Return True when the candidate differs from the current and exists in tzdata. + + The same source the timezone menu reads from, so we never offer a value + the user could not have selected manually. UTC is always present, so this + is effectively a no-op for the reset-to-default case. + """ + if target_tz == current_tz: + return False + try: + return target_tz in list_timezones() + except SysCallError as err: + debug(f'Failed to validate target timezone {target_tz}: {err}') + return False + + async def _confirm_locale_apply(self, rows: list[tuple[str, str]]) -> bool: + """Render and show the confirmation dialog for the locale changes.""" + label_w = max(len(label) for label, _ in rows) + data_lines = [f' {label.ljust(label_w)} : {value}' for label, value in rows] + + question = tr('Use this language as the target system language as well?') + header = tr('The following settings will be applied:') + + # The TUI centers every line of the prompt independently, so pad all + # lines to a common width; otherwise the colon column drifts. + width = max(len(question), len(header), *(len(line) for line in data_lines)) + separator = '=' * width + prompt = question.ljust(width) + '\n\n' + header.ljust(width) + '\n' + separator + '\n' + '\n'.join(line.ljust(width) for line in data_lines) + '\n' + + result = await Confirmation(header=prompt, preset=True).show() + return result.type_ == ResultType.Selection and result.item() == MenuItem.yes() + def _prev_archinstall_language(self, item: MenuItem) -> str | None: if not item.value: return None diff --git a/archinstall/lib/models/locale.py b/archinstall/lib/models/locale.py index 8f58098915..e45df61cde 100644 --- a/archinstall/lib/models/locale.py +++ b/archinstall/lib/models/locale.py @@ -2,7 +2,36 @@ from typing import Any, Self from archinstall.lib.locale.utils import get_kb_layout -from archinstall.lib.translationhandler import tr +from archinstall.lib.translationhandler import DEFAULT_CONSOLE_FONT, Language, tr + + +@dataclass +class LocaleLanguageDiff: + """Locale fields to write when applying a Language to a LocaleConfiguration. + + Each field carries the new value, or None when no change is needed. sys_enc + is paired with sys_lang so the encoding row is shown alongside the locale + row in the confirmation dialog, even when the encoding portion itself does + not change. + """ + + sys_lang: str | None = None + sys_enc: str | None = None + console_font: str | None = None + + def is_empty(self) -> bool: + return self.sys_lang is None and self.sys_enc is None and self.console_font is None + + def labeled_rows(self) -> list[tuple[str, str]]: + """Return [(label, value)] for fields that would change.""" + rows: list[tuple[str, str]] = [] + if self.sys_lang is not None: + rows.append((tr('Locale language'), self.sys_lang)) + if self.sys_enc is not None: + rows.append((tr('Locale encoding'), self.sys_enc)) + if self.console_font is not None: + rows.append((tr('Console font'), self.console_font)) + return rows @dataclass @@ -14,7 +43,7 @@ class LocaleConfiguration: # can be checked using # zgrep "CONFIG_FONT" /proc/config.gz # https://wiki.archlinux.org/title/Linux_console#Font - console_font: str = 'default8x16' + console_font: str = DEFAULT_CONSOLE_FONT @classmethod def default(cls) -> Self: @@ -38,6 +67,36 @@ def preview(self) -> str: output += '{}: {}'.format(tr('Console font'), self.console_font) return output + def language_diff(self, language: Language) -> LocaleLanguageDiff: + """Compute the locale fields that would change if applying this language. + + Returns an empty diff for languages without a sys_lang mapping. console_font + is offered when the language-derived target value differs - so re-picking + a language with fewer mappings still resets stale fonts left over from a + previous pick. + """ + diff = LocaleLanguageDiff() + if not language.sys_lang: + return diff + + if self.sys_lang != language.sys_lang: + diff.sys_lang = language.sys_lang + diff.sys_enc = language.target_sys_enc or self.sys_enc + + target_font = language.target_console_font + if self.console_font != target_font: + diff.console_font = target_font + + return diff + + def apply_language_diff(self, diff: LocaleLanguageDiff) -> None: + if diff.sys_lang is not None: + self.sys_lang = diff.sys_lang + if diff.sys_enc is not None: + self.sys_enc = diff.sys_enc + if diff.console_font is not None: + self.console_font = diff.console_font + def _load_config(self, args: dict[str, str]) -> None: if 'sys_lang' in args: self.sys_lang = args['sys_lang'] diff --git a/archinstall/lib/translationhandler.py b/archinstall/lib/translationhandler.py index 093ca6dea1..1eda4f4313 100644 --- a/archinstall/lib/translationhandler.py +++ b/archinstall/lib/translationhandler.py @@ -21,12 +21,31 @@ class Language: translation_percent: int translated_lang: str | None console_font: str | None = None + sys_lang: str | None = None + default_timezone: str | None = None @property def display_name(self) -> str: name = self.name_en return f'{name} ({self.translation_percent}%)' + @property + def target_sys_enc(self) -> str | None: + """Encoding portion of sys_lang (e.g. 'UTF-8' from 'uk_UA.UTF-8'). None when sys_lang has no '.'.""" + if self.sys_lang and '.' in self.sys_lang: + return self.sys_lang.split('.', 1)[1] + return None + + @property + def target_console_font(self) -> str: + """Console font implied by this language; falls back to the system default.""" + return self.console_font or DEFAULT_CONSOLE_FONT + + @property + def target_timezone(self) -> str: + """Timezone implied by this language; falls back to UTC.""" + return self.default_timezone or DEFAULT_TIMEZONE + def is_match(self, lang_or_translated_lang: str) -> bool: if self.name_en == lang_or_translated_lang: return True @@ -38,7 +57,8 @@ def json(self) -> str: return self.name_en -_DEFAULT_FONT = 'default8x16' +DEFAULT_CONSOLE_FONT = 'default8x16' +DEFAULT_TIMEZONE = 'UTC' _ENV_FONT = os.environ.get('FONT') @@ -69,7 +89,7 @@ def _set_font(self, font_name: str | None) -> bool: if not running_from_iso(): return False - target = font_name or _DEFAULT_FONT + target = font_name or DEFAULT_CONSOLE_FONT try: SysCommand(['setfont', target]) return True @@ -132,6 +152,8 @@ def _get_translations(self) -> list[Language]: lang = mapping_entry['lang'] translated_lang = mapping_entry.get('translated_lang', None) console_font = mapping_entry.get('console_font', None) + sys_lang = mapping_entry.get('sys_lang', None) + default_timezone = mapping_entry.get('default_timezone', None) try: # get a translation for a specific language @@ -146,7 +168,7 @@ def _get_translations(self) -> list[Language]: # prevent cases where the .pot file is out of date and the percentage is above 100 percent = min(100, percent) - language = Language(abbr, lang, translation, percent, translated_lang, console_font) + language = Language(abbr, lang, translation, percent, translated_lang, console_font, sys_lang, default_timezone) languages.append(language) except FileNotFoundError as err: raise FileNotFoundError(f"Could not locate language file for '{lang}': {err}") diff --git a/archinstall/locales/base.pot b/archinstall/locales/base.pot index 31f5e1960f..4fd1bd68da 100644 --- a/archinstall/locales/base.pot +++ b/archinstall/locales/base.pot @@ -163,6 +163,12 @@ msgstr "" msgid "Archinstall language" msgstr "" +msgid "Use this language as the target system language as well?" +msgstr "" + +msgid "The following settings will be applied:" +msgstr "" + msgid "Wipe all selected drives and use a best-effort default partition layout" msgstr "" diff --git a/archinstall/locales/languages.json b/archinstall/locales/languages.json index 22c9c9ec87..8641461bb9 100644 --- a/archinstall/locales/languages.json +++ b/archinstall/locales/languages.json @@ -3,7 +3,7 @@ {"abbr": "af", "lang": "Afrikaans"}, {"abbr": "ak", "lang": "Akan"}, {"abbr": "am", "lang": "Amharic"}, - {"abbr": "ar", "lang": "Arabic"}, + {"abbr": "ar", "lang": "Arabic", "sys_lang": "ar_SA.UTF-8", "default_timezone": "Asia/Riyadh"}, {"abbr": "an", "lang": "Aragonese"}, {"abbr": "as", "lang": "Assamese"}, {"abbr": "av", "lang": "Avaric"}, @@ -19,8 +19,8 @@ {"abbr": "bs", "lang": "Bosnian"}, {"abbr": "br", "lang": "Breton"}, {"abbr": "bg", "lang": "Bulgarian"}, - {"abbr": "ca", "lang": "Catalan"}, - {"abbr": "cs", "lang": "Czech", "translated_lang": "čeština"}, + {"abbr": "ca", "lang": "Catalan", "sys_lang": "ca_ES.UTF-8"}, + {"abbr": "cs", "lang": "Czech", "translated_lang": "čeština", "sys_lang": "cs_CZ.UTF-8", "default_timezone": "Europe/Prague"}, {"abbr": "ch", "lang": "Chamorro"}, {"abbr": "ce", "lang": "Chechen"}, {"abbr": "cu", "lang": "Church Slavic"}, @@ -30,37 +30,37 @@ {"abbr": "cr", "lang": "Cree"}, {"abbr": "cy", "lang": "Welsh"}, {"abbr": "da", "lang": "Danish", "translated_lang": "Dansk"}, - {"abbr": "de", "lang": "German", "translated_lang": "Deutsch"}, + {"abbr": "de", "lang": "German", "translated_lang": "Deutsch", "sys_lang": "de_DE.UTF-8", "default_timezone": "Europe/Berlin"}, {"abbr": "dv", "lang": "Dhivehi"}, {"abbr": "dz", "lang": "Dzongkha"}, - {"abbr": "el", "lang": "Modern Greek (1453-)", "translated_lang": "Ελληνικά"}, - {"abbr": "en", "lang": "English"}, + {"abbr": "el", "lang": "Modern Greek (1453-)", "translated_lang": "Ελληνικά", "sys_lang": "el_GR.UTF-8", "default_timezone": "Europe/Athens"}, + {"abbr": "en", "lang": "English", "sys_lang": "en_US.UTF-8"}, {"abbr": "eo", "lang": "Esperanto"}, - {"abbr": "et", "lang": "Estonian", "translated_lang": "Eesti" }, + {"abbr": "et", "lang": "Estonian", "translated_lang": "Eesti", "sys_lang": "et_EE.UTF-8" , "default_timezone": "Europe/Tallinn"}, {"abbr": "eu", "lang": "Basque"}, {"abbr": "ee", "lang": "Ewe"}, {"abbr": "fo", "lang": "Faroese"}, {"abbr": "fa", "lang": "Persian"}, {"abbr": "fj", "lang": "Fijian"}, - {"abbr": "fi", "lang": "Finnish", "translated_lang": "Suomi"}, - {"abbr": "fr", "lang": "French", "translated_lang": "Français"}, + {"abbr": "fi", "lang": "Finnish", "translated_lang": "Suomi", "sys_lang": "fi_FI.UTF-8", "default_timezone": "Europe/Helsinki"}, + {"abbr": "fr", "lang": "French", "translated_lang": "Français", "sys_lang": "fr_FR.UTF-8", "default_timezone": "Europe/Paris"}, {"abbr": "fy", "lang": "Western Frisian"}, {"abbr": "ff", "lang": "Fulah"}, {"abbr": "gd", "lang": "Scottish Gaelic"}, - {"abbr": "ga", "lang": "Irish"}, - {"abbr": "gl", "lang": "Galician"}, + {"abbr": "ga", "lang": "Irish", "sys_lang": "ga_IE.UTF-8", "default_timezone": "Europe/Dublin"}, + {"abbr": "gl", "lang": "Galician", "sys_lang": "gl_ES.UTF-8"}, {"abbr": "gv", "lang": "Manx"}, {"abbr": "gn", "lang": "Guarani"}, {"abbr": "gu", "lang": "Gujarati"}, {"abbr": "ht", "lang": "Haitian"}, {"abbr": "ha", "lang": "Hausa"}, {"abbr": "sh", "lang": "Serbo-Croatian"}, - {"abbr": "he", "lang": "Hebrew"}, + {"abbr": "he", "lang": "Hebrew", "sys_lang": "he_IL.UTF-8", "default_timezone": "Asia/Jerusalem"}, {"abbr": "hz", "lang": "Herero"}, - {"abbr": "hi", "lang": "Hindi"}, + {"abbr": "hi", "lang": "Hindi", "sys_lang": "hi_IN.UTF-8", "default_timezone": "Asia/Kolkata"}, {"abbr": "ho", "lang": "Hiri Motu"}, {"abbr": "hr", "lang": "Croatian"}, - {"abbr": "hu", "lang": "Hungarian"}, + {"abbr": "hu", "lang": "Hungarian", "sys_lang": "hu_HU.UTF-8", "default_timezone": "Europe/Budapest"}, {"abbr": "hy", "lang": "Armenian"}, {"abbr": "ig", "lang": "Igbo"}, {"abbr": "io", "lang": "Ido"}, @@ -68,16 +68,16 @@ {"abbr": "iu", "lang": "Inuktitut"}, {"abbr": "ie", "lang": "Interlingue"}, {"abbr": "ia", "lang": "Interlingua (International Auxiliary Language Association)"}, - {"abbr": "id", "lang": "Indonesian", "translated_lang": "Indonesian"}, + {"abbr": "id", "lang": "Indonesian", "translated_lang": "Indonesian", "sys_lang": "id_ID.UTF-8"}, {"abbr": "ik", "lang": "Inupiaq"}, {"abbr": "is", "lang": "Icelandic"}, - {"abbr": "it", "lang": "Italian", "translated_lang": "Italiano"}, + {"abbr": "it", "lang": "Italian", "translated_lang": "Italiano", "sys_lang": "it_IT.UTF-8", "default_timezone": "Europe/Rome"}, {"abbr": "jv", "lang": "Javanese"}, - {"abbr": "ja", "lang": "Japanese"}, + {"abbr": "ja", "lang": "Japanese", "sys_lang": "ja_JP.UTF-8", "default_timezone": "Asia/Tokyo"}, {"abbr": "kl", "lang": "Kalaallisut"}, {"abbr": "kn", "lang": "Kannada"}, {"abbr": "ks", "lang": "Kashmiri"}, - {"abbr": "ka", "lang": "Georgian"}, + {"abbr": "ka", "lang": "Georgian", "sys_lang": "ka_GE.UTF-8", "default_timezone": "Asia/Tbilisi"}, {"abbr": "kr", "lang": "Kanuri"}, {"abbr": "kk", "lang": "Kazakh"}, {"abbr": "km", "lang": "Central Khmer"}, @@ -86,15 +86,15 @@ {"abbr": "ky", "lang": "Kirghiz"}, {"abbr": "kv", "lang": "Komi"}, {"abbr": "kg", "lang": "Kongo"}, - {"abbr": "ko", "lang": "Korean", "translated_lang": "한글", "external_dep": true}, + {"abbr": "ko", "lang": "Korean", "translated_lang": "한글", "external_dep": true, "sys_lang": "ko_KR.UTF-8", "default_timezone": "Asia/Seoul"}, {"abbr": "kj", "lang": "Kuanyama"}, - {"abbr": "ku", "lang": "Kurdish"}, + {"abbr": "ku", "lang": "Kurdish", "sys_lang": "ku_TR.UTF-8", "default_timezone": "Europe/Istanbul"}, {"abbr": "lo", "lang": "Lao"}, {"abbr": "la", "lang": "Latin"}, {"abbr": "lv", "lang": "Latvian"}, {"abbr": "li", "lang": "Limburgan"}, {"abbr": "ln", "lang": "Lingala"}, - {"abbr": "lt", "lang": "Lithuanian", "translated_lang": "Lietuvių"}, + {"abbr": "lt", "lang": "Lithuanian", "translated_lang": "Lietuvių", "sys_lang": "lt_LT.UTF-8", "default_timezone": "Europe/Vilnius"}, {"abbr": "lb", "lang": "Luxembourgish"}, {"abbr": "lu", "lang": "Luba-Katanga"}, {"abbr": "lg", "lang": "Ganda"}, @@ -113,8 +113,8 @@ {"abbr": "nr", "lang": "South Ndebele"}, {"abbr": "nd", "lang": "North Ndebele"}, {"abbr": "ng", "lang": "Ndonga"}, - {"abbr": "ne", "lang": "Nepali", "translated_lang": "नेपाली"}, - {"abbr": "nl", "lang": "Dutch", "translated_lang": "Nederlands"}, + {"abbr": "ne", "lang": "Nepali", "translated_lang": "नेपाली", "sys_lang": "ne_NP.UTF-8", "default_timezone": "Asia/Kathmandu"}, + {"abbr": "nl", "lang": "Dutch", "translated_lang": "Nederlands", "sys_lang": "nl_NL.UTF-8", "default_timezone": "Europe/Amsterdam"}, {"abbr": "nn", "lang": "Norwegian Nynorsk"}, {"abbr": "nb", "lang": "Norwegian Bokmål"}, {"abbr": "no", "lang": "Norwegian"}, @@ -126,15 +126,15 @@ {"abbr": "os", "lang": "Ossetian"}, {"abbr": "pa", "lang": "Panjabi"}, {"abbr": "pi", "lang": "Pali"}, - {"abbr": "pl", "lang": "Polish", "translated_lang": "Polski"}, - {"abbr": "pt", "lang": "Portuguese", "translated_lang": "Português"}, - {"abbr": "pt_BR", "lang": "Brazilian Portuguese", "translated_lang": "Português do Brasil"}, + {"abbr": "pl", "lang": "Polish", "translated_lang": "Polski", "sys_lang": "pl_PL.UTF-8", "default_timezone": "Europe/Warsaw"}, + {"abbr": "pt", "lang": "Portuguese", "translated_lang": "Português", "sys_lang": "pt_PT.UTF-8"}, + {"abbr": "pt_BR", "lang": "Brazilian Portuguese", "translated_lang": "Português do Brasil", "sys_lang": "pt_BR.UTF-8"}, {"abbr": "ps", "lang": "Pushto"}, {"abbr": "qu", "lang": "Quechua"}, {"abbr": "rm", "lang": "Romansh"}, - {"abbr": "ro", "lang": "Romanian", "translated_lang": "Română"}, + {"abbr": "ro", "lang": "Romanian", "translated_lang": "Română", "sys_lang": "ro_RO.UTF-8", "default_timezone": "Europe/Bucharest"}, {"abbr": "rn", "lang": "Rundi"}, - {"abbr": "ru", "lang": "Russian", "translated_lang": "Русский"}, + {"abbr": "ru", "lang": "Russian", "translated_lang": "Русский", "sys_lang": "ru_RU.UTF-8"}, {"abbr": "sg", "lang": "Sango"}, {"abbr": "sa", "lang": "Sanskrit"}, {"abbr": "si", "lang": "Sinhala"}, @@ -146,16 +146,16 @@ {"abbr": "sd", "lang": "Sindhi"}, {"abbr": "so", "lang": "Somali"}, {"abbr": "st", "lang": "Southern Sotho"}, - {"abbr": "es", "lang": "Spanish", "translated_lang": "Español"}, + {"abbr": "es", "lang": "Spanish", "translated_lang": "Español", "sys_lang": "es_ES.UTF-8"}, {"abbr": "sq", "lang": "Albanian"}, {"abbr": "sc", "lang": "Sardinian"}, {"abbr": "sr", "lang": "Serbian"}, {"abbr": "ss", "lang": "Swati"}, {"abbr": "su", "lang": "Sundanese"}, {"abbr": "sw", "lang": "Swahili (macrolanguage)"}, - {"abbr": "sv", "lang": "Swedish", "translated_lang": "Svenska"}, + {"abbr": "sv", "lang": "Swedish", "translated_lang": "Svenska", "sys_lang": "sv_SE.UTF-8", "default_timezone": "Europe/Stockholm"}, {"abbr": "ty", "lang": "Tahitian"}, - {"abbr": "ta", "lang": "Tamil", "translated_lang": "தமிழ்"}, + {"abbr": "ta", "lang": "Tamil", "translated_lang": "தமிழ்", "sys_lang": "ta_IN.UTF-8", "default_timezone": "Asia/Kolkata"}, {"abbr": "tt", "lang": "Tatar"}, {"abbr": "te", "lang": "Telugu"}, {"abbr": "tg", "lang": "Tajik"}, @@ -166,12 +166,12 @@ {"abbr": "tn", "lang": "Tswana"}, {"abbr": "ts", "lang": "Tsonga"}, {"abbr": "tk", "lang": "Turkmen"}, - {"abbr": "tr", "lang": "Turkish", "translated_lang" : "Türkçe"}, + {"abbr": "tr", "lang": "Turkish", "translated_lang" : "Türkçe", "sys_lang": "tr_TR.UTF-8", "default_timezone": "Europe/Istanbul"}, {"abbr": "tw", "lang": "Twi"}, {"abbr": "ug", "lang": "Uighur"}, - {"abbr": "uk", "lang": "Ukrainian", "console_font": "UniCyr_8x16"}, - {"abbr": "ur", "lang": "Urdu", "translated_lang": "اردو"}, - {"abbr": "uz", "lang": "Uzbek", "translated_lang": "O'zbek"}, + {"abbr": "uk", "lang": "Ukrainian", "console_font": "UniCyr_8x16", "sys_lang": "uk_UA.UTF-8", "default_timezone": "Europe/Kyiv"}, + {"abbr": "ur", "lang": "Urdu", "translated_lang": "اردو", "sys_lang": "ur_PK.UTF-8", "default_timezone": "Asia/Karachi"}, + {"abbr": "uz", "lang": "Uzbek", "translated_lang": "O'zbek", "sys_lang": "uz_UZ.UTF-8", "default_timezone": "Asia/Tashkent"}, {"abbr": "ve", "lang": "Venda"}, {"abbr": "vi", "lang": "Vietnamese"}, {"abbr": "vo", "lang": "Volapük"}, @@ -181,6 +181,6 @@ {"abbr": "yi", "lang": "Yiddish"}, {"abbr": "yo", "lang": "Yoruba"}, {"abbr": "za", "lang": "Zhuang"}, - {"abbr": "zh-CN", "lang": "Simplified Chinese", "translated_lang": "简体中文"}, - {"abbr": "zh-TW", "lang": "Traditional Chinese", "translated_lang": "繁體中文"}, + {"abbr": "zh-CN", "lang": "Simplified Chinese", "translated_lang": "简体中文", "sys_lang": "zh_CN.UTF-8"}, + {"abbr": "zh-TW", "lang": "Traditional Chinese", "translated_lang": "繁體中文", "sys_lang": "zh_TW.UTF-8", "default_timezone": "Asia/Taipei"}, {"abbr": "zu", "lang": "Zulu"}] diff --git a/archinstall/locales/uk/LC_MESSAGES/base.mo b/archinstall/locales/uk/LC_MESSAGES/base.mo index 7c0230e6ed8ccd09d2990c53220d643d0f3325d4..02eff84cd219af27d200816ac19d1a9ac1fb0f0f 100644 GIT binary patch delta 12557 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 delta 12324 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�gzKMxCCGjJA!-4L&1h3&*9Q(1o)dqcH z7t>a(NBv3ci{Im5YM)NjNQ>f+lJw5Sp;QpTn@ z6YpXePWhK@coD`E@4;}qfDw2DZ{q*(SG@Tdf565opWB8GeqqnMfFU}Lnu2>6sT4*1 z+kQdF#p=Y(v8qExP^)&(CA;mu!%*ViP#LQ5CFkL0+=Q>-NG!f=AH#3se&X?8S!1u* z#rg>*P@nfT`B#GjC}iSfRQwX=<56sd<*wR0SX)#|$KphM9(8`jYxW^i$Fmo5FEh(= zD;8Y0-yeR&IO3IMc8$DVM*btH2>Zr1l!UrtjrKf%O8M^?gtfo5#-VN`$*2zHU;qxl z$~Xk$a3XHN=e_#O@9eg2i_NL;`kl{S@Hr}!%GKBmw_^%kN8JZPzPGD88e@nHQ8$?3 zUi`G@M(jcTQPg$|yI~jWR7@uR6xFf+VLy!X{b2t}H5;`!ZsD`26*U5$L!J0L&cKo% z?O(kMva32CHKhe!+#faKS*Yu8!w2v(@@ z8h!_d;5T>`JFuzMK;mzQz(zwckQjQ1=b?ogBtN^jK(rAHhN$T2idtMXgW`^}@+`2z7p=x{iPU_e3qm zN z9;(4M@ircheTWa^J`D9GIOb^zC-7lxUEeV$aSiUkz6~6+4$CFlly1aA;%{*{CO2db zaTRLuR&V5(?{T1KVUpwj#Uv%!dINRcO^t0we1$2F`GSfqo=>IP5fnFZ{C`9mh1EIU zB+brQd(^k$p{R$;lc=?`0X6aiSRT*dVEh<|Vn(`S#^GAjqOO?X@37DGpr8{sp&l9m znf8Q-u{H5#RO-vH0Dr|`Y?|fxzeu#l-ozcT1#Ur2*)?p1G1>O|15ouRQO}feIgZ(= z+~rZ&PQ}0d75uLexsDk~9G&O*e_wwZ>kuD6Ey|BE6MymQ>o;}$f8B16sy~Wp_$w+i z3C$cc2Xiq9kKimkg`+fg?VH=w9Kh4Wu`TRszky0s-Ik93yWbd8rf#BEc~L97TV6(& z_znC9JGZvC<|b`yMh9UA^#@V6=o_fTTd6H;XDNk;DQHoBhuSuc^X(023+hHwyPdtz zJE#vB_gsExK7iSKk`|1YO- z?IAnY6FS>F)~l#(_FvSRh$?dYzhsWZBI2|zcKi5HYa^wr{d_CjOFRn$RNu`W&%i3g z?NE!f#EVCFWB->>@e~zWwI88wrJvy-OzZCWzYDtfDDfZIAA1(t?e`jL+eVc*{_p#f zJU>S@nAgKGB*5(EM@Bi;5M>VepO_TQ{2+p}6pG#MNs$$2a7q9*ZQLnI&7ubqt03b$WMT&*$QIiv7Jj%i0L z7uoLGl$dIryra6xZ@l}vXHzor+EL4G(d6I|-fKCsjQB_V2h*w3I@hZw@iWAFwRE#m z`#SsG6{#_mXHwUXW1Fy<`%Y?H;BZQ7-S1LkS`4Bzfn$1wQr2rJj^@45hGstH8l2OG z_$cqMdDkU=%x%*oVq{m2-Y0s4THTHN5$p9Lw)M)<9AC~mocA2wdQIinEXo&oucy3- zx}W?<_@d=~ZZc}q)Zv^p?ujNzZfbg<`%9C^#(g-lllL^<136j=KjX{@?8{rP7ciM) zlia+tW=^R)B`vAWbJV>?T^6SC)^`xSy7_;)N7GtX-bnRj!Z=*uR!mQF9&xkM8#rCu ze(5pJL+;GFoZU z8R^V&Yh@MI-9_yH-m`hH=Um+y_4K&OG;0c3fb0>L$8QPK-0yt(%kT^l-aVZsAVI$#=H8hjO}B>%bW` zxaRYy?`50a@Z2P4i`yo*LFH$?E9$Pb-JOyT0!TpP>uR9!^;EW4*=DWvFN3H4H%!xT%y_wUu_WuJf C)H^c( diff --git a/archinstall/locales/uk/LC_MESSAGES/base.po b/archinstall/locales/uk/LC_MESSAGES/base.po index fab48b2bc0..7cf3cd7b91 100644 --- a/archinstall/locales/uk/LC_MESSAGES/base.po +++ b/archinstall/locales/uk/LC_MESSAGES/base.po @@ -175,6 +175,12 @@ msgstr "Введіть бажаний тип файлової системи д msgid "Archinstall language" msgstr "Мова Archinstall" +msgid "Use this language as the target system language as well?" +msgstr "Використати цю мову як мову цільової системи також?" + +msgid "The following settings will be applied:" +msgstr "Будуть застосовані такі налаштування:" + msgid "Wipe all selected drives and use a best-effort default partition layout" msgstr "Стерти усі вибрані диски та використовувати отпимальну схему розмітки розділів" From 7041718909f50b4f1bfc5b39067cdb26a34d4e12 Mon Sep 17 00:00:00 2001 From: Softer Date: Tue, 28 Apr 2026 17:19:38 +0300 Subject: [PATCH 2/2] Remove Yes/No singleton cache on MenuItem MenuItem.yes() and .no() cached their first-call result on the class, so labels stayed stuck in the language active at first call. With the new locale-apply Confirmation firing right after a language switch this became user-visible. Drop the cache and construct fresh items per call - allocation cost is negligible and equality continues to work via the dataclass __eq__. --- archinstall/tui/ui/menu_item.py | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/archinstall/tui/ui/menu_item.py b/archinstall/tui/ui/menu_item.py index 4c10e275ef..ac198aa6ee 100644 --- a/archinstall/tui/ui/menu_item.py +++ b/archinstall/tui/ui/menu_item.py @@ -2,7 +2,7 @@ from dataclasses import dataclass, field from enum import Enum from functools import cached_property -from typing import Any, ClassVar, Self, override +from typing import Any, Self, override from archinstall.lib.translationhandler import tr @@ -23,9 +23,6 @@ class MenuItem: _id: str = '' - _yes: ClassVar[Self | None] = None - _no: ClassVar[Self | None] = None - def __post_init__(self) -> None: if self.key is not None: self._id = self.key @@ -45,17 +42,11 @@ def get_value(self) -> Any: @classmethod def yes(cls, action: Callable[[Any], Any] | None = None) -> Self: - if cls._yes is None: - cls._yes = cls(tr('Yes'), value=True, key='yes', action=action) - - return cls._yes + return cls(tr('Yes'), value=True, key='yes', action=action) @classmethod def no(cls, action: Callable[[Any], Any] | None = None) -> Self: - if cls._no is None: - cls._no = cls(tr('No'), value=False, key='no', action=action) - - return cls._no + return cls(tr('No'), value=False, key='no', action=action) def is_empty(self) -> bool: return self.text == '' or self.text is None