From f2cd5ca6c65ee61d8abca0823eec0d227eed30a4 Mon Sep 17 00:00:00 2001 From: Arturo Espinosa Date: Sat, 5 Jul 2025 19:39:55 -0600 Subject: [PATCH 1/4] maint: avoid warning related to locale.getdefaultlocale deprecation When tkfilebrowser is used inside a project, the code produces a DeprecationWarning due to the use of locale.getdefaultlocale. See https://github.com/python/cpython/issues/90817 Solution based on getdefaultlocale's help and CPython's own code in the calendar.LocaleTextCalendar class. Commit: https://github.com/python/cpython/commit/4fccf910738d1442852cb900747e6dccb8fe03ef --- tkfilebrowser/constants.py | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/tkfilebrowser/constants.py b/tkfilebrowser/constants.py index 05346be..0b56c7c 100644 --- a/tkfilebrowser/constants.py +++ b/tkfilebrowser/constants.py @@ -79,8 +79,33 @@ IM_RECENT_24 = os.path.join(PATH, "images", "recent_24.png") # --- translation +class _different_locale: + def __init__(self, _locale): + self.locale = _locale + self.oldlocale = None + + def __enter__(self): + self.oldlocale = locale.setlocale(locale.LC_MESSAGES, None) + locale.setlocale(locale.LC_MESSAGES, self.locale) + + def __exit__(self, *args): + if self.oldlocale is None: + return + locale.setlocale(locale.LC_MESSAGES, self.oldlocale) + + +def _getdefaultlocale(): + _locale = locale.setlocale(locale.LC_MESSAGES, None) + if _locale == 'C': + with _different_locale(''): + # The LC_MESSAGES locale does not seem to be configured: + # get the user preferred locale. + _locale = locale.setlocale(locale.LC_MESSAGES, None) + return _locale.split('.') + + try: - LANG = locale.getdefaultlocale()[0] + LANG = _getdefaultlocale()[0] except ValueError: LANG = 'en' From 8b9e1e6b27cbc9e6cc84fba4c4beeb6fae0e7ddf Mon Sep 17 00:00:00 2001 From: Arturo Espinosa Date: Sat, 5 Jul 2025 20:32:52 -0600 Subject: [PATCH 2/4] fix: Handle missing LC_MESSAGES on non-POSIX systems --- tkfilebrowser/constants.py | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/tkfilebrowser/constants.py b/tkfilebrowser/constants.py index 0b56c7c..a8bf832 100644 --- a/tkfilebrowser/constants.py +++ b/tkfilebrowser/constants.py @@ -83,24 +83,29 @@ class _different_locale: def __init__(self, _locale): self.locale = _locale self.oldlocale = None + try: + self.category = locale.LC_MESSAGES + except AttributeError: + # LC_MESSAGES may not be available on non-POSIX OSes + self.category = locale.LC_ALL def __enter__(self): - self.oldlocale = locale.setlocale(locale.LC_MESSAGES, None) - locale.setlocale(locale.LC_MESSAGES, self.locale) + self.oldlocale = locale.setlocale(self.category, None) + locale.setlocale(self.category, self.locale) def __exit__(self, *args): if self.oldlocale is None: return - locale.setlocale(locale.LC_MESSAGES, self.oldlocale) + locale.setlocale(self.category, self.oldlocale) def _getdefaultlocale(): - _locale = locale.setlocale(locale.LC_MESSAGES, None) + _locale = locale.setlocale(self.category, None) if _locale == 'C': with _different_locale(''): # The LC_MESSAGES locale does not seem to be configured: # get the user preferred locale. - _locale = locale.setlocale(locale.LC_MESSAGES, None) + _locale = locale.setlocale(self.category, None) return _locale.split('.') From 2b58f641e09e0aa3f54f2475bda8a6706ce49e8e Mon Sep 17 00:00:00 2001 From: Arturo Espinosa Date: Sat, 5 Jul 2025 20:52:15 -0600 Subject: [PATCH 3/4] refactor: locale category calculated in new function so it can be obtained within _getdefaultlocale --- tkfilebrowser/constants.py | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/tkfilebrowser/constants.py b/tkfilebrowser/constants.py index a8bf832..03559d0 100644 --- a/tkfilebrowser/constants.py +++ b/tkfilebrowser/constants.py @@ -79,15 +79,20 @@ IM_RECENT_24 = os.path.join(PATH, "images", "recent_24.png") # --- translation +def _get_locale_messages_category(): + try: + category = locale.LC_MESSAGES + except AttributeError: + # LC_MESSAGES may not be available on non-POSIX OSes + category = locale.LC_ALL + return category + + class _different_locale: def __init__(self, _locale): self.locale = _locale self.oldlocale = None - try: - self.category = locale.LC_MESSAGES - except AttributeError: - # LC_MESSAGES may not be available on non-POSIX OSes - self.category = locale.LC_ALL + self.category = _get_locale_messages_category() def __enter__(self): self.oldlocale = locale.setlocale(self.category, None) @@ -100,12 +105,13 @@ def __exit__(self, *args): def _getdefaultlocale(): - _locale = locale.setlocale(self.category, None) + category = _get_locale_messages_category() + _locale = locale.setlocale(category, None) if _locale == 'C': with _different_locale(''): # The LC_MESSAGES locale does not seem to be configured: # get the user preferred locale. - _locale = locale.setlocale(self.category, None) + _locale = locale.setlocale(category, None) return _locale.split('.') From 7cc4da8a4fe265304f1e411aa4513e0c518804c5 Mon Sep 17 00:00:00 2001 From: Arturo Espinosa Date: Sat, 5 Jul 2025 21:52:18 -0600 Subject: [PATCH 4/4] fix: use babel.Locale class instead of LANG string. Try to fix MSwin Do some shennanigans with what Windows returns to try to get a valid language parse using babel Locale aliases. Using babel.Locale preserves more locale information for the formatting function calls. --- tkfilebrowser/constants.py | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/tkfilebrowser/constants.py b/tkfilebrowser/constants.py index 03559d0..256ba59 100644 --- a/tkfilebrowser/constants.py +++ b/tkfilebrowser/constants.py @@ -112,13 +112,20 @@ def _getdefaultlocale(): # The LC_MESSAGES locale does not seem to be configured: # get the user preferred locale. _locale = locale.setlocale(category, None) - return _locale.split('.') + lang = _locale.split('.')[0] + if len(lang) > 2 and lang[2] != '_': + lang = lang[:2] + from babel import Locale + from babel.core import UnknownLocaleError + try: + babel_locale = Locale.parse(lang) + except UnknownLocaleError: + babel_locale = Locale.parse('en') + return babel_locale -try: - LANG = _getdefaultlocale()[0] -except ValueError: - LANG = 'en' + +LOCALE = _getdefaultlocale() EN = {} FR = {"B": "octets", "MB": "Mo", "kB": "ko", "GB": "Go", "TB": "To", @@ -131,8 +138,8 @@ def _getdefaultlocale(): "Shortcuts": "Raccourcis", "Save As": "Enregistrer sous", "Recent": "Récents", "Recently used": "Récemment utilisés"} LANGUAGES = {"fr": FR, "en": EN} -if LANG[:2] == "fr": - TR = LANGUAGES["fr"] +if LOCALE.language in LANGUAGES: + TR = LANGUAGES[LOCALE.language] else: TR = LANGUAGES["en"] @@ -146,15 +153,15 @@ def _(text): def locale_date(date=None): - return format_date(date, 'short', locale=LANG) + return format_date(date, 'short', locale=LOCALE) def locale_datetime(date=None): - return format_datetime(date, 'EEEE HH:mm', locale=LANG) + return format_datetime(date, 'EEEE HH:mm', locale=LOCALE) def locale_number(nb): - return format_number(nb, locale=LANG) + return format_number(nb, locale=LOCALE) SIZES = [_("B"), _("kB"), _("MB"), _("GB"), _("TB")] @@ -162,7 +169,7 @@ def locale_number(nb): # --- locale settings for dates TODAY = locale_date() YEAR = datetime.now().year -DAY = int(format_date(None, 'D', locale=LANG)) +DAY = int(format_date(None, 'D', locale=LOCALE)) # --- functions