Extract win32 localatiztion to a new file win32locale.py.
This commit is contained in:
parent
354e191ea0
commit
7051d3bf13
@ -48,8 +48,10 @@ if sys.platform == 'darwin':
|
|||||||
from . maclocale import mac_setup_localization
|
from . maclocale import mac_setup_localization
|
||||||
|
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
from ctypes import cdll
|
from .win32locale import (win32_locale_init_from_env,
|
||||||
|
win32_locale_bindtextdomain)
|
||||||
|
|
||||||
|
from .win32locale import _LOCALE_NAMES
|
||||||
|
|
||||||
LOG = logging.getLogger("." + __name__)
|
LOG = logging.getLogger("." + __name__)
|
||||||
LOG.propagate = True
|
LOG.propagate = True
|
||||||
@ -76,101 +78,11 @@ except ImportError:
|
|||||||
ICU_LOCALES = None
|
ICU_LOCALES = None
|
||||||
if HAVE_ICU:
|
if HAVE_ICU:
|
||||||
ICU_LOCALES = Locale.getAvailableLocales()
|
ICU_LOCALES = Locale.getAvailableLocales()
|
||||||
|
|
||||||
# Map of languages for converting to Microsoft locales and naming
|
|
||||||
# locales for display to the user. It's important to add to this list
|
|
||||||
# when a new translation is added. Note the dummy _(): That's just to
|
|
||||||
# get xgettext to include the string in gramps.pot; actual translation
|
|
||||||
# is done in _get_language_string() below.
|
|
||||||
# (The gramps officially-supported language list is ALL_LINGUAS in setup.py)
|
|
||||||
def _(msgid):
|
|
||||||
return msgid
|
|
||||||
|
|
||||||
_LOCALE_NAMES = {
|
|
||||||
'ar': ('Arabic_Saudi Arabia', '1256', _("Arabic")),
|
|
||||||
'bg': ('Bulgrian_Bulgaria', '1251', _("Bulgarian")),
|
|
||||||
#Windows has no translation for Breton
|
|
||||||
'br': (None, None, _("Breton")),
|
|
||||||
'ca': ('Catalan_Spain', '1252', _("Catalan")),
|
|
||||||
'cs': ('Czech_Czech Republic', '1250', _("Czech")),
|
|
||||||
'da': ('Danish_Denmark', '1252', _("Danish")),
|
|
||||||
'de': ('German_Germany', '1252', _("German")),
|
|
||||||
'de_AT': ('German_Austria', '1252', _("German (Austria)")),
|
|
||||||
'el': ('Greek_Greece', '1253', _("Greek")),
|
|
||||||
'en': ('English_United States', '1252', _("English (USA)")),
|
|
||||||
'en_GB': ('English_United Kingdom', '1252', _("English")),
|
|
||||||
#Windows has no translation for Esperanto
|
|
||||||
'eo': (None, None, _("Esperanto")),
|
|
||||||
'es': ('Spanish_Spain', '1252', _("Spanish")),
|
|
||||||
'fi': ('Finnish_Finland', '1252', _("Finnish")),
|
|
||||||
'fr': ('French_France', '1252', _("French")),
|
|
||||||
#Windows has no translation for Gaelic
|
|
||||||
'ga': (None, None, _("Gaelic")),
|
|
||||||
'he': ('Hebrew_Israel', '1255', _("Hebrew")),
|
|
||||||
'hr': ('Croatian_Croatia', '1250', _("Croatian")),
|
|
||||||
'hu': ('Hungarian_Hungary', '1250', _("Hungarian")),
|
|
||||||
'id': ('Indonesian', '1057', _("Indonesian")),
|
|
||||||
'is': ('Icelandic', '1252', _("Icelandic")),
|
|
||||||
'it': ('Italian_Italy', '1252', _("Italian")),
|
|
||||||
'ja': ('Japanese_Japan', '932', _("Japanese")),
|
|
||||||
'lt': ('Lithuanian_Lithuania', '1252', _("Lithuanian")),
|
|
||||||
#Windows has no translation for Macedonian
|
|
||||||
'mk': (None, None, _("Macedonian")),
|
|
||||||
'nb': ('Norwegian_Norway', '1252', _("Norwegian Bokmal")),
|
|
||||||
'nl': ('Dutch_Netherlands', '1252', _("Dutch")),
|
|
||||||
'nn': ('Norwegian-Nynorsk_Norway', '1252', _("Norwegian Nynorsk")),
|
|
||||||
'pl': ('Polish_Poland', '1250', _("Polish")),
|
|
||||||
'pt_BR': ('Portuguese_Brazil', '1252', _("Portuguese (Brazil)")),
|
|
||||||
'pt_PT': ('Portuguese_Portugal', '1252', _("Portuguese (Portugal)")),
|
|
||||||
'ro': ('Romanian_Romania', '1250', _("Romanian")),
|
|
||||||
'ru': ('Russian_Russia', '1251', _("Russian")),
|
|
||||||
'sk': ('Slovak_Slovakia', '1250', _("Slovak"),),
|
|
||||||
'sl': ('Slovenian_Slovenia', '1250', _("Slovenian")),
|
|
||||||
'sq': ('Albanian_Albania', '1250', _("Albanian")),
|
|
||||||
'sr': ('Serbian(Cyrillic)_Serbia and Montenegro', '1251', _("Serbian")),
|
|
||||||
'sv': ('Swedish_Sweden', '1252', _("Swedish")),
|
|
||||||
# Windows has no codepage for Tamil
|
|
||||||
'ta': (None, None, _("Tamil")),
|
|
||||||
'tr': ('Turkish_Turkey', '1254', _("Turkish")),
|
|
||||||
'uk': ('Ukrainian_Ukraine', '1251', _("Ukrainian")),
|
|
||||||
'vi': ('Vietnamese_Vietnam', '1258', _("Vietnamese")),
|
|
||||||
'zh_CN': ('Chinese_China', '936', _("Chinese (Simplified)")),
|
|
||||||
'zh_HK': ('Chinese_Hong Kong', '950', _("Chinese (Hong Kong)")),
|
|
||||||
'zh_TW': ('Chinese_Taiwan', '950', _("Chinese (Traditional)")),
|
|
||||||
}
|
|
||||||
|
|
||||||
# locales with right-to-left text
|
# locales with right-to-left text
|
||||||
_RTL_LOCALES = ('ar', 'he')
|
_RTL_LOCALES = ('ar', 'he')
|
||||||
|
|
||||||
# locales with less than 70% currently translated
|
# locales with less than 70% currently translated
|
||||||
INCOMPLETE_TRANSLATIONS = ('ar', 'bg', 'sq', 'ta', 'tr', 'zh_HK', 'zh_TW')
|
INCOMPLETE_TRANSLATIONS = ('ar', 'bg', 'sq', 'ta', 'tr', 'zh_HK', 'zh_TW')
|
||||||
|
|
||||||
def _check_mswin_locale(loc):
|
|
||||||
msloc = None
|
|
||||||
try:
|
|
||||||
msloc = _LOCALE_NAMES[loc[:5]][:2]
|
|
||||||
newloc = loc[:5]
|
|
||||||
except KeyError:
|
|
||||||
try:
|
|
||||||
msloc = _LOCALE_NAMES[loc[:2]][:2]
|
|
||||||
newloc = loc[:2]
|
|
||||||
except KeyError:
|
|
||||||
#US English is the outlier, all other English locales want
|
|
||||||
#real English:
|
|
||||||
if loc[:2] == ('en') and loc[:5] != 'en_US':
|
|
||||||
return ('en_GB', '1252')
|
|
||||||
return (None, None)
|
|
||||||
return (newloc, msloc)
|
|
||||||
|
|
||||||
def _check_mswin_locale_reverse(loc):
|
|
||||||
for (newloc, msloc) in _LOCALE_NAMES.items():
|
|
||||||
if msloc and newloc == msloc[0]:
|
|
||||||
return (newloc, msloc[1])
|
|
||||||
#US English is the outlier, all other English locales want real English:
|
|
||||||
if loc.startswith('English') and loc != 'English_United States':
|
|
||||||
return ('en_GB', '1252')
|
|
||||||
return (None, None)
|
|
||||||
|
|
||||||
def _check_gformat():
|
def _check_gformat():
|
||||||
"""
|
"""
|
||||||
Some OS environments do not support the locale.nl_langinfo() method
|
Some OS environments do not support the locale.nl_langinfo() method
|
||||||
@ -264,96 +176,8 @@ class GrampsLocale:
|
|||||||
matches = matches and (lang is None or self.lang == lang)
|
matches = matches and (lang is None or self.lang == lang)
|
||||||
matches = matches and (domain is None or self.localedomain == domain)
|
matches = matches and (domain is None or self.localedomain == domain)
|
||||||
return matches and (languages is None or len(languages) == 0 or
|
return matches and (languages is None or len(languages) == 0 or
|
||||||
self.languages == languages)
|
self.language == languages)
|
||||||
|
|
||||||
def _win_init_environment(self):
|
|
||||||
"""
|
|
||||||
The Windows implementation of Python ignores environment
|
|
||||||
variables when setting the locale; it only pays attention to
|
|
||||||
the control panel language settings -- which for practical
|
|
||||||
purposes limits one to the language for which one purchased
|
|
||||||
Windows. This function enables using alternative
|
|
||||||
localizations.
|
|
||||||
"""
|
|
||||||
|
|
||||||
if 'LANG' in os.environ:
|
|
||||||
(lang, loc) = _check_mswin_locale(os.environ['LANG'])
|
|
||||||
if loc:
|
|
||||||
locale.setlocale(locale.LC_ALL, '.'.join(loc))
|
|
||||||
self.lang = lang
|
|
||||||
self.encoding = loc[1]
|
|
||||||
else:
|
|
||||||
LOG.debug("%%LANG%% value %s not usable", os.environ['LANG'])
|
|
||||||
if not self.lang:
|
|
||||||
locale.setlocale(locale.LC_ALL, '')
|
|
||||||
locale_tuple = locale.getlocale()
|
|
||||||
lang = locale_tuple[0]
|
|
||||||
loc = _check_mswin_locale_reverse(lang)
|
|
||||||
if loc[0]:
|
|
||||||
self.lang = loc[0]
|
|
||||||
self.encoding = loc[1]
|
|
||||||
else:
|
|
||||||
(lang, loc) = _check_mswin_locale(locale.getlocale()[0])
|
|
||||||
if lang:
|
|
||||||
self.lang = lang
|
|
||||||
self.encoding = loc[1]
|
|
||||||
else:
|
|
||||||
LOG.debug("No usable locale found in environment")
|
|
||||||
|
|
||||||
if not self.lang:
|
|
||||||
self.lang = 'C'
|
|
||||||
self.encoding = 'cp1252'
|
|
||||||
|
|
||||||
if 'LC_MESSAGES' in os.environ:
|
|
||||||
lang = self.check_available_translations(os.environ['LC_MESSAGES'])
|
|
||||||
if lang:
|
|
||||||
self.language = [lang]
|
|
||||||
else:
|
|
||||||
LOG.debug("No translation for %%LC_MESSAGES%% locale")
|
|
||||||
if 'LANGUAGE' in os.environ:
|
|
||||||
language = [x for x in [self.check_available_translations(l)
|
|
||||||
for l in os.environ["LANGUAGE"].split(":")]
|
|
||||||
if x]
|
|
||||||
if language:
|
|
||||||
self.language = language
|
|
||||||
else:
|
|
||||||
LOG.debug("No languages with translations found "
|
|
||||||
"in %%LANGUAGES%%")
|
|
||||||
if not self.language:
|
|
||||||
self.language = [self.lang[:5]]
|
|
||||||
|
|
||||||
if 'COLLATION' in os.environ:
|
|
||||||
coll = os.environ['COLLATION']
|
|
||||||
if HAVE_ICU:
|
|
||||||
if coll[:2] in ICU_LOCALES:
|
|
||||||
self.collation = coll
|
|
||||||
else:
|
|
||||||
self.collation = self.lang
|
|
||||||
else:
|
|
||||||
(coll, loc) = _check_mswin_locale(coll)
|
|
||||||
if not loc:
|
|
||||||
(coll, loc) = _check_mswin_locale(self.lang)
|
|
||||||
self.collation = '.'.join(loc)
|
|
||||||
locale.setlocale(locale.LC_COLLATE, self.collation )
|
|
||||||
else:
|
|
||||||
if HAVE_ICU:
|
|
||||||
self.collation = self.lang
|
|
||||||
else:
|
|
||||||
(coll, loc) = _check_mswin_locale(self.lang)
|
|
||||||
if loc:
|
|
||||||
self.collation = '.'.join(loc)
|
|
||||||
else:
|
|
||||||
self.collation = 'C'
|
|
||||||
locale.setlocale(locale.LC_COLLATE, self.collation )
|
|
||||||
|
|
||||||
# We can't import datahandler stuff or we'll get a circular
|
|
||||||
# dependency, so we rely on the available translations list
|
|
||||||
if 'LC_TIME' in os.environ:
|
|
||||||
self.calendar = (
|
|
||||||
self.check_available_translations(os.environ['LC_TIME']) or
|
|
||||||
self.lang)
|
|
||||||
else:
|
|
||||||
self.calendar = self.lang
|
|
||||||
|
|
||||||
def _init_from_environment(self):
|
def _init_from_environment(self):
|
||||||
|
|
||||||
@ -439,21 +263,6 @@ class GrampsLocale:
|
|||||||
LOG.debug("The locale tformat for '%s' is '%s'",
|
LOG.debug("The locale tformat for '%s' is '%s'",
|
||||||
self.lang, _check_gformat())
|
self.lang, _check_gformat())
|
||||||
|
|
||||||
def _win_bindtextdomain(self, localedomain, localedir):
|
|
||||||
"""
|
|
||||||
Help routine for loading and setting up libintl attributes
|
|
||||||
Returns libintl
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
libintl = cdll.LoadLibrary('libintl-8')
|
|
||||||
libintl.bindtextdomain(localedomain, localedir)
|
|
||||||
libintl.textdomain(localedomain)
|
|
||||||
libintl.bind_textdomain_codeset(localedomain, "UTF-8")
|
|
||||||
|
|
||||||
except WindowsError:
|
|
||||||
LOG.warning("Localization library libintl not on %PATH%, "
|
|
||||||
"localization will be incomplete")
|
|
||||||
|
|
||||||
def __init_first_instance(self):
|
def __init_first_instance(self):
|
||||||
"""
|
"""
|
||||||
Initialize the primary locale from whatever might be
|
Initialize the primary locale from whatever might be
|
||||||
@ -477,7 +286,7 @@ class GrampsLocale:
|
|||||||
if sys.platform == 'darwin':
|
if sys.platform == 'darwin':
|
||||||
mac_setup_localization(self)
|
mac_setup_localization(self)
|
||||||
elif sys.platform == 'win32':
|
elif sys.platform == 'win32':
|
||||||
self._win_init_environment()
|
win32_locale_init_from_env(self, HAVE_ICU, ICU_LOCALES)
|
||||||
else:
|
else:
|
||||||
self._init_from_environment()
|
self._init_from_environment()
|
||||||
else:
|
else:
|
||||||
@ -540,13 +349,13 @@ class GrampsLocale:
|
|||||||
# GtkBuilder uses GLib's g_dgettext wrapper, which oddly is bound
|
# GtkBuilder uses GLib's g_dgettext wrapper, which oddly is bound
|
||||||
# with locale instead of gettext. Win32 doesn't support bindtextdomain.
|
# with locale instead of gettext. Win32 doesn't support bindtextdomain.
|
||||||
if self.localedir:
|
if self.localedir:
|
||||||
if sys.platform != 'win32':
|
if sys.platform == 'win32':
|
||||||
|
win32_locale_bindtextdomain(self.localedomain.encode('utf-8'),
|
||||||
|
self.localedir.encode('utf-8'))
|
||||||
|
else:
|
||||||
# bug12278, _build_popup_ui() under linux and macOS
|
# bug12278, _build_popup_ui() under linux and macOS
|
||||||
locale.textdomain(self.localedomain)
|
locale.textdomain(self.localedomain)
|
||||||
locale.bindtextdomain(self.localedomain, self.localedir)
|
locale.bindtextdomain(self.localedomain, self.localedir)
|
||||||
else:
|
|
||||||
self._win_bindtextdomain(self.localedomain.encode('utf-8'),
|
|
||||||
self.localedir.encode('utf-8'))
|
|
||||||
|
|
||||||
self.rtl_locale = False
|
self.rtl_locale = False
|
||||||
if self.language[0] in _RTL_LOCALES:
|
if self.language[0] in _RTL_LOCALES:
|
||||||
@ -895,21 +704,21 @@ class GrampsLocale:
|
|||||||
"""
|
"""
|
||||||
if not self.localedir:
|
if not self.localedir:
|
||||||
return None
|
return None
|
||||||
#Note that this isn't a typo for self.language; self.languages
|
#Note that this isn't a typo for self.language; self.language
|
||||||
#is cached so we don't have to query the file system every
|
#is cached so we don't have to query the file system every
|
||||||
#time this function is called.
|
#time this function is called.
|
||||||
if not hasattr(self, 'languages'):
|
if not hasattr(self, 'languages'):
|
||||||
self.languages = self.get_available_translations()
|
self.language = self.get_available_translations()
|
||||||
|
|
||||||
if not loc:
|
if not loc:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if loc[:5] in self.languages:
|
if loc[:5] in self.language:
|
||||||
return loc[:5]
|
return loc[:5]
|
||||||
#US English is the outlier, all other English locales want real English:
|
#US English is the outlier, all other English locales want real English:
|
||||||
if loc[:2] == 'en' and loc[:5] != 'en_US':
|
if loc[:2] == 'en' and loc[:5] != 'en_US':
|
||||||
return 'en_GB'
|
return 'en_GB'
|
||||||
if loc[:2] in self.languages:
|
if loc[:2] in self.language:
|
||||||
return loc[:2]
|
return loc[:2]
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -2,9 +2,7 @@
|
|||||||
#
|
#
|
||||||
# Gramps - a GTK+/GNOME based genealogy program
|
# Gramps - a GTK+/GNOME based genealogy program
|
||||||
#
|
#
|
||||||
# Copyright (C) 2000-2006 Donald N. Allingham
|
# Copyright (C) 2023 John Ralls
|
||||||
# Copyright (C) 2009 Brian G. Matherly
|
|
||||||
# Copyright (C) 2013 John Ralls
|
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# This program is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
233
gramps/gen/utils/win32locale.py
Normal file
233
gramps/gen/utils/win32locale.py
Normal file
@ -0,0 +1,233 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Gramps - a GTK+/GNOME based genealogy program
|
||||||
|
#
|
||||||
|
# Copyright (C) 2023 John Ralls
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
#
|
||||||
|
"""
|
||||||
|
win32locale provides l18n setup for the Microsoft Windows platform.
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import locale
|
||||||
|
from ctypes import cdll
|
||||||
|
import logging
|
||||||
|
|
||||||
|
LOG = logging.getLogger("." + __name__)
|
||||||
|
LOG.propagate = True
|
||||||
|
|
||||||
|
|
||||||
|
# Map of languages for converting to Microsoft locales and naming
|
||||||
|
# locales for display to the user. It's important to add to this list
|
||||||
|
# when a new translation is added. Note the dummy _(): That's just to
|
||||||
|
# get xgettext to include the string in gramps.pot; actual translation
|
||||||
|
# is done in _get_language_string() below.
|
||||||
|
# (The gramps officially-supported language list is ALL_LINGUAS in setup.py)
|
||||||
|
def _(msgid):
|
||||||
|
return msgid
|
||||||
|
|
||||||
|
_LOCALE_NAMES = {
|
||||||
|
'ar': ('Arabic_Saudi Arabia', '1256', _("Arabic")),
|
||||||
|
'bg': ('Bulgrian_Bulgaria', '1251', _("Bulgarian")),
|
||||||
|
#Windows has no translation for Breton
|
||||||
|
'br': (None, None, _("Breton")),
|
||||||
|
'ca': ('Catalan_Spain', '1252', _("Catalan")),
|
||||||
|
'cs': ('Czech_Czech Republic', '1250', _("Czech")),
|
||||||
|
'da': ('Danish_Denmark', '1252', _("Danish")),
|
||||||
|
'de': ('German_Germany', '1252', _("German")),
|
||||||
|
'de_AT': ('German_Austria', '1252', _("German (Austria)")),
|
||||||
|
'el': ('Greek_Greece', '1253', _("Greek")),
|
||||||
|
'en': ('English_United States', '1252', _("English (USA)")),
|
||||||
|
'en_GB': ('English_United Kingdom', '1252', _("English")),
|
||||||
|
#Windows has no translation for Esperanto
|
||||||
|
'eo': (None, None, _("Esperanto")),
|
||||||
|
'es': ('Spanish_Spain', '1252', _("Spanish")),
|
||||||
|
'fi': ('Finnish_Finland', '1252', _("Finnish")),
|
||||||
|
'fr': ('French_France', '1252', _("French")),
|
||||||
|
#Windows has no translation for Gaelic
|
||||||
|
'ga': (None, None, _("Gaelic")),
|
||||||
|
'he': ('Hebrew_Israel', '1255', _("Hebrew")),
|
||||||
|
'hr': ('Croatian_Croatia', '1250', _("Croatian")),
|
||||||
|
'hu': ('Hungarian_Hungary', '1250', _("Hungarian")),
|
||||||
|
'id': ('Indonesian', '1057', _("Indonesian")),
|
||||||
|
'is': ('Icelandic', '1252', _("Icelandic")),
|
||||||
|
'it': ('Italian_Italy', '1252', _("Italian")),
|
||||||
|
'ja': ('Japanese_Japan', '932', _("Japanese")),
|
||||||
|
'lt': ('Lithuanian_Lithuania', '1252', _("Lithuanian")),
|
||||||
|
#Windows has no translation for Macedonian
|
||||||
|
'mk': (None, None, _("Macedonian")),
|
||||||
|
'nb': ('Norwegian_Norway', '1252', _("Norwegian Bokmal")),
|
||||||
|
'nl': ('Dutch_Netherlands', '1252', _("Dutch")),
|
||||||
|
'nn': ('Norwegian-Nynorsk_Norway', '1252', _("Norwegian Nynorsk")),
|
||||||
|
'pl': ('Polish_Poland', '1250', _("Polish")),
|
||||||
|
'pt_BR': ('Portuguese_Brazil', '1252', _("Portuguese (Brazil)")),
|
||||||
|
'pt_PT': ('Portuguese_Portugal', '1252', _("Portuguese (Portugal)")),
|
||||||
|
'ro': ('Romanian_Romania', '1250', _("Romanian")),
|
||||||
|
'ru': ('Russian_Russia', '1251', _("Russian")),
|
||||||
|
'sk': ('Slovak_Slovakia', '1250', _("Slovak"),),
|
||||||
|
'sl': ('Slovenian_Slovenia', '1250', _("Slovenian")),
|
||||||
|
'sq': ('Albanian_Albania', '1250', _("Albanian")),
|
||||||
|
'sr': ('Serbian(Cyrillic)_Serbia and Montenegro', '1251', _("Serbian")),
|
||||||
|
'sv': ('Swedish_Sweden', '1252', _("Swedish")),
|
||||||
|
# Windows has no codepage for Tamil
|
||||||
|
'ta': (None, None, _("Tamil")),
|
||||||
|
'tr': ('Turkish_Turkey', '1254', _("Turkish")),
|
||||||
|
'uk': ('Ukrainian_Ukraine', '1251', _("Ukrainian")),
|
||||||
|
'vi': ('Vietnamese_Vietnam', '1258', _("Vietnamese")),
|
||||||
|
'zh_CN': ('Chinese_China', '936', _("Chinese (Simplified)")),
|
||||||
|
'zh_HK': ('Chinese_Hong Kong', '950', _("Chinese (Hong Kong)")),
|
||||||
|
'zh_TW': ('Chinese_Taiwan', '950', _("Chinese (Traditional)")),
|
||||||
|
}
|
||||||
|
|
||||||
|
def _check_mswin_locale(loc):
|
||||||
|
msloc = None
|
||||||
|
try:
|
||||||
|
msloc = _LOCALE_NAMES[loc[:5]][:2]
|
||||||
|
newloc = loc[:5]
|
||||||
|
except KeyError:
|
||||||
|
try:
|
||||||
|
msloc = _LOCALE_NAMES[loc[:2]][:2]
|
||||||
|
newloc = loc[:2]
|
||||||
|
except KeyError:
|
||||||
|
#US English is the outlier, all other English locales want
|
||||||
|
#real English:
|
||||||
|
if loc[:2] == ('en') and loc[:5] != 'en_US':
|
||||||
|
return ('en_GB', '1252')
|
||||||
|
return (None, None)
|
||||||
|
return (newloc, msloc)
|
||||||
|
|
||||||
|
def _check_mswin_locale_reverse(loc):
|
||||||
|
for (newloc, msloc) in _LOCALE_NAMES.items():
|
||||||
|
if msloc and newloc == msloc[0]:
|
||||||
|
return (newloc, msloc[1])
|
||||||
|
#US English is the outlier, all other English locales want real English:
|
||||||
|
if loc.startswith('English') and loc != 'English_United States':
|
||||||
|
return ('en_GB', '1252')
|
||||||
|
return (None, None)
|
||||||
|
|
||||||
|
def _set_lang(glocale):
|
||||||
|
if 'LANG' in os.environ:
|
||||||
|
(lang, loc) = _check_mswin_locale(os.environ['LANG'])
|
||||||
|
if loc:
|
||||||
|
locale.setlocale(locale.LC_ALL, '.'.join(loc))
|
||||||
|
glocale.lang = lang
|
||||||
|
glocale.encoding = loc[1]
|
||||||
|
else:
|
||||||
|
LOG.debug("%%LANG%% value %s not usable", os.environ['LANG'])
|
||||||
|
if not glocale.lang:
|
||||||
|
locale.setlocale(locale.LC_ALL, '')
|
||||||
|
locale_tuple = locale.getlocale()
|
||||||
|
lang = locale_tuple[0]
|
||||||
|
loc = _check_mswin_locale_reverse(lang)
|
||||||
|
if loc[0]:
|
||||||
|
glocale.lang = loc[0]
|
||||||
|
glocale.encoding = loc[1]
|
||||||
|
else:
|
||||||
|
(lang, loc) = _check_mswin_locale(locale.getlocale()[0])
|
||||||
|
if lang:
|
||||||
|
glocale.lang = lang
|
||||||
|
glocale.encoding = loc[1]
|
||||||
|
else:
|
||||||
|
LOG.debug("No usable locale found in environment")
|
||||||
|
|
||||||
|
if not glocale.lang:
|
||||||
|
glocale.lang = 'C'
|
||||||
|
glocale.encoding = 'cp1252'
|
||||||
|
|
||||||
|
def _set_languages(glocale):
|
||||||
|
lang = None
|
||||||
|
if 'LC_MESSAGES' in os.environ:
|
||||||
|
lang = glocale.check_available_translations(os.environ['LC_MESSAGES'])
|
||||||
|
if lang:
|
||||||
|
glocale.language = [lang]
|
||||||
|
else:
|
||||||
|
LOG.debug("No translation for %%LC_MESSAGES%% locale")
|
||||||
|
if 'LANGUAGE' in os.environ:
|
||||||
|
language = [x for x in [glocale.check_available_translations(l)
|
||||||
|
for l in os.environ["LANGUAGE"].split(":")]
|
||||||
|
if x]
|
||||||
|
if language:
|
||||||
|
glocale.language = language
|
||||||
|
else:
|
||||||
|
LOG.debug("No languages with translations found "
|
||||||
|
"in %%LANGUAGES%%")
|
||||||
|
if not glocale.language:
|
||||||
|
glocale.language = [glocale.lang[:5]]
|
||||||
|
|
||||||
|
def _set_collation(glocale, have_icu, icu_locales):
|
||||||
|
coll = None
|
||||||
|
if 'COLLATION' in os.environ:
|
||||||
|
coll = os.environ['COLLATION']
|
||||||
|
if have_icu:
|
||||||
|
if coll[:2] in icu_locales:
|
||||||
|
glocale.collation = coll
|
||||||
|
else:
|
||||||
|
glocale.collation = glocale.lang
|
||||||
|
else:
|
||||||
|
(coll, loc) = _check_mswin_locale(coll)
|
||||||
|
if not loc:
|
||||||
|
(coll, loc) = _check_mswin_locale(glocale.lang)
|
||||||
|
glocale.collation = '.'.join(loc)
|
||||||
|
locale.setlocale(locale.LC_COLLATE, glocale.collation )
|
||||||
|
else:
|
||||||
|
if have_icu:
|
||||||
|
glocale.collation = glocale.lang
|
||||||
|
else:
|
||||||
|
(coll, loc) = _check_mswin_locale(glocale.lang)
|
||||||
|
if loc:
|
||||||
|
glocale.collation = '.'.join(loc)
|
||||||
|
else:
|
||||||
|
glocale.collation = 'C'
|
||||||
|
locale.setlocale(locale.LC_COLLATE, glocale.collation )
|
||||||
|
|
||||||
|
def _set_calendar(glocale):
|
||||||
|
# We can't import datahandler stuff or we'll get a circular
|
||||||
|
# dependency, so we rely on the available translations list
|
||||||
|
if 'LC_TIME' in os.environ:
|
||||||
|
glocale.calendar = (
|
||||||
|
glocale.check_available_translations(os.environ['LC_TIME']) or
|
||||||
|
glocale.lang)
|
||||||
|
else:
|
||||||
|
glocale.calendar = glocale.lang
|
||||||
|
|
||||||
|
def win32_locale_init_from_env(glocale, have_icu, icu_locales):
|
||||||
|
"""
|
||||||
|
The Windows implementation of Python ignores environment
|
||||||
|
variables when setting the locale; it only pays attention to
|
||||||
|
the control panel language settings -- which for practical
|
||||||
|
purposes limits one to the language for which one purchased
|
||||||
|
Windows. This function enables using alternative
|
||||||
|
localizations.
|
||||||
|
"""
|
||||||
|
_set_lang(glocale)
|
||||||
|
_set_languages(glocale)
|
||||||
|
_set_collation(glocale, have_icu, icu_locales)
|
||||||
|
_set_calendar(glocale)
|
||||||
|
|
||||||
|
def win32_locale_bindtextdomain(localedomain, localedir):
|
||||||
|
"""
|
||||||
|
Help routine for loading and setting up libintl attributes
|
||||||
|
Returns libintl
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
libintl = cdll.LoadLibrary('libintl-8')
|
||||||
|
libintl.bindtextdomain(localedomain, localedir)
|
||||||
|
libintl.textdomain(localedomain)
|
||||||
|
libintl.bind_textdomain_codeset(localedomain, "UTF-8")
|
||||||
|
|
||||||
|
except WindowsError:
|
||||||
|
LOG.warning("Localization library libintl not on %PATH%, "
|
||||||
|
"localization will be incomplete")
|
Loading…
Reference in New Issue
Block a user