gpodder/src/gpodder/utilwin32locale.py

358 lines
15 KiB
Python

# -*- coding: utf-8 -*-
#
# Copyright © 2007-2010 Dieter Verfaillie <dieterv@optionexplicit.be>
#
# This file is part of elib.intl.
#
# elib.intl is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# elib.intl 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 Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with elib.intl. If not, see <http://www.gnu.org/licenses/>.
'''
This code is adapted from the elib.intl module available on GitHub at
https://github.com/dieterv/elib.intl, commit 49d5797 on 1 Sep 2017.
It has been stripped down to the necessary code for UI localization
using Gtk.Builder in gPodder on Windows (msys2) and adapted to python 3.
The elib.intl module provides enhanced internationalization (I18N) services for
your Python modules and applications.
This module adds the following on Microsoft Windows systems:
- automatic detection of the current screen language (not necessarily the same
as the installation language) provided by MUI packs,
- makes sure internationalized C libraries which internally invoke gettext() or
dcgettext() can properly locate their message catalogs. This fixes a known
limitation in gettext's Windows support when using eg. gtk.builder or gtk.glade.
See http://www.gnu.org/software/gettext/FAQ.html#windows_setenv for more
information.
'''
__version__ = '0.0.3'
__docformat__ = 'restructuredtext'
import gettext
import locale
import os
import sys
from logging import getLogger
logger = getLogger(__name__)
def _localefromlcid(lcid):
'''
:param lcid: Microsoft Windows LCID
:returns: name of the supported gPodder locale or ISO 639-1 language code for a given lcid. If there is no
ISO 639-1 language code assigned to the language specified by lcid,
the ISO 639-2 language code is returned. If the language specified
by lcid is unknown in the ISO 639-x database, None is returned.
More information can be found on the following websites:
- List of ISO 639-1 and ISO 639-2 language codes: http://www.loc.gov/standards/iso639-2/
- List of language identifiers: https://msdn.microsoft.com/library/windows/desktop/dd318693(v=vs.85).aspx
'''
mapping = {1078: 'af', # Afrikaans - South Africa
1052: 'sq', # Albanian - Albania
1118: 'am', # Amharic - Ethiopia
1025: 'ar', # Arabic - Saudi Arabia
5121: 'ar', # Arabic - Algeria
15361: 'ar', # Arabic - Bahrain
3073: 'ar', # Arabic - Egypt
2049: 'ar', # Arabic - Iraq
11265: 'ar', # Arabic - Jordan
13313: 'ar', # Arabic - Kuwait
12289: 'ar', # Arabic - Lebanon
4097: 'ar', # Arabic - Libya
6145: 'ar', # Arabic - Morocco
8193: 'ar', # Arabic - Oman
16385: 'ar', # Arabic - Qatar
10241: 'ar', # Arabic - Syria
7169: 'ar', # Arabic - Tunisia
14337: 'ar', # Arabic - U.A.E.
9217: 'ar', # Arabic - Yemen
1067: 'hy', # Armenian - Armenia
1101: 'as', # Assamese
2092: 'az', # Azeri (Cyrillic)
1068: 'az', # Azeri (Latin)
0x042D: 'eu', # Basque
1059: 'be', # Belarusian
1093: 'bn', # Bengali (India)
2117: 'bn', # Bengali (Bangladesh)
5146: 'bs', # Bosnian (Bosnia/Herzegovina)
1026: 'bg', # Bulgarian
1109: 'my', # Burmese
0x0403: 'ca', # Catalan
1116: 'chr', # Cherokee - United States
# we have only one zh_CN.po translation. Applying to all.
2052: 'zh_CN', # Chinese - People's Republic of China
4100: 'zh_CN', # Chinese - Singapore
1028: 'zh_CN', # Chinese - Taiwan
3076: 'zh_CN', # Chinese - Hong Kong SAR
5124: 'zh_CN', # Chinese - Macao SAR
1050: 'hr', # Croatian
4122: 'hr', # Croatian (Bosnia/Herzegovina)
# we have cs and cs_CZ translations. cs_CZ seems more up to date
0x0405: 'cs_CZ', # Czech
0x0406: 'da', # Danish
1125: 'dv', # Divehi
1043: 'nl', # Dutch - Netherlands
0x0813: 'nl', # Dutch - Belgium
1126: 'bin', # Edo
1033: 'en', # English - United States
2057: 'en', # English - United Kingdom
3081: 'en', # English - Australia
10249: 'en', # English - Belize
4105: 'en', # English - Canada
9225: 'en', # English - Caribbean
15369: 'en', # English - Hong Kong SAR
16393: 'en', # English - India
14345: 'en', # English - Indonesia
6153: 'en', # English - Ireland
8201: 'en', # English - Jamaica
17417: 'en', # English - Malaysia
5129: 'en', # English - New Zealand
13321: 'en', # English - Philippines
18441: 'en', # English - Singapore
7177: 'en', # English - South Africa
11273: 'en', # English - Trinidad
12297: 'en', # English - Zimbabwe
1061: 'et', # Estonian
1080: 'fo', # Faroese
0x0429: 'fa_IR', # Persian - Iran
1124: 'fil', # Filipino
0x040B: 'fi', # Finnish
0x040C: 'fr', # French - France
2060: 'fr', # French - Belgium
11276: 'fr', # French - Cameroon
3084: 'fr', # French - Canada
9228: 'fr', # French - Democratic Rep. of Congo
12300: 'fr', # French - Cote d'Ivoire
15372: 'fr', # French - Haiti
5132: 'fr', # French - Luxembourg
13324: 'fr', # French - Mali
6156: 'fr', # French - Monaco
14348: 'fr', # French - Morocco
58380: 'fr', # French - North Africa
8204: 'fr', # French - Reunion
10252: 'fr', # French - Senegal
4108: 'fr', # French - Switzerland
7180: 'fr', # French - West Indies
1122: 'fy', # Frisian - Netherlands
1127: None, # TODO: Fulfulde - Nigeria
1071: 'mk', # FYRO Macedonian
2108: 'ga', # Gaelic (Ireland)
1084: 'gd', # Gaelic (Scotland)
0x0456: 'gl', # Galician
1079: 'ka', # Georgian
0x0407: 'de', # German - Germany
3079: 'de', # German - Austria
5127: 'de', # German - Liechtenstein
4103: 'de', # German - Luxembourg
2055: 'de', # German - Switzerland
0x0408: 'el', # Greek
1140: 'gn', # Guarani - Paraguay
1095: 'gu', # Gujarati
1128: 'ha', # Hausa - Nigeria
1141: 'haw', # Hawaiian - United States
0x040D: 'he', # Hebrew
1081: 'hi', # Hindi
0x040E: 'hu', # Hungarian
1129: None, # TODO: Ibibio - Nigeria
1039: 'is', # Icelandic
1136: 'ig', # Igbo - Nigeria
0x0421: 'id_ID', # Indonesian
1117: 'iu', # Inuktitut
0x0410: 'it', # Italian - Italy
2064: 'it', # Italian - Switzerland
1041: 'ja', # Japanese
1099: 'kn', # Kannada
1137: 'kr', # Kanuri - Nigeria
2144: 'ks', # Kashmiri
1120: 'ks', # Kashmiri (Arabic)
0x043F: 'kk', # Kazakh
1107: 'km', # Khmer
1111: 'kok', # Konkani
0x0412: 'ko_KR', # Korean
1088: 'ky', # Kyrgyz (Cyrillic)
1108: 'lo', # Lao
1142: 'la', # Latin
1062: 'lv', # Latvian
1063: 'lt', # Lithuanian
1086: 'ms', # Malay - Malaysia
2110: 'ms', # Malay - Brunei Darussalam
1100: 'ml', # Malayalam
1082: 'mt', # Maltese
1112: 'mni', # Manipuri
1153: 'mi', # Maori - New Zealand
1102: 'mr', # Marathi
1104: 'mn', # Mongolian (Cyrillic)
2128: 'mn', # Mongolian (Mongolian)
1121: 'ne', # Nepali
2145: 'ne', # Nepali - India
0x0414: 'nb', # Norwegian (Bokmᅢᆬl)
0x0814: 'nn', # Norwegian (Nynorsk)
1096: 'or', # Oriya
1138: 'om', # Oromo
1145: 'pap', # Papiamentu
1123: 'ps', # Pashto
0x0415: 'pl', # Polish
0x0416: 'pt_BR', # Portuguese - Brazil
0x0816: 'pt', # Portuguese - Portugal
1094: 'pa', # Punjabi
2118: 'pa', # Punjabi (Pakistan)
1131: 'qu', # Quecha - Bolivia
2155: 'qu', # Quecha - Ecuador
3179: 'qu', # Quecha - Peru
1047: 'rm', # Rhaeto-Romanic
0x0418: 'ro', # Romanian
2072: 'ro', # Romanian - Moldava
0x0419: 'ru', # Russian
2073: 'ru', # Russian - Moldava
1083: 'se', # Sami (Lappish)
1103: 'sa', # Sanskrit
1132: 'nso', # Sepedi
3098: 'sr', # Serbian (Cyrillic)
2074: 'sr', # Serbian (Latin)
1113: 'sd', # Sindhi - India
2137: 'sd', # Sindhi - Pakistan
1115: 'si', # Sinhalese - Sri Lanka
1051: 'sk', # Slovak
1060: 'sl', # Slovenian
1143: 'so', # Somali
1070: 'wen', # Sorbian
0x0C0A: 'es', # Spanish - Spain (Modern Sort)
0x040A: 'es', # Spanish - Spain (Traditional Sort)
11274: 'es', # Spanish - Argentina
16394: 'es', # Spanish - Bolivia
13322: 'es', # Spanish - Chile
9226: 'es', # Spanish - Colombia
5130: 'es', # Spanish - Costa Rica
7178: 'es', # Spanish - Dominican Republic
12298: 'es', # Spanish - Ecuador
17418: 'es', # Spanish - El Salvador
4106: 'es', # Spanish - Guatemala
18442: 'es', # Spanish - Honduras
58378: 'es', # Spanish - Latin America
0x080A: 'es_MX', # Spanish - Mexico
19466: 'es', # Spanish - Nicaragua
6154: 'es', # Spanish - Panama
15370: 'es', # Spanish - Paraguay
10250: 'es', # Spanish - Peru
20490: 'es', # Spanish - Puerto Rico
21514: 'es', # Spanish - United States
14346: 'es', # Spanish - Uruguay
8202: 'es', # Spanish - Venezuela
1072: None, # TODO: Sutu
1089: 'sw', # Swahili
0x041D: 'sv', # Swedish
2077: 'sv', # Swedish - Finland
1114: 'syr', # Syriac
1064: 'tg', # Tajik
1119: None, # TODO: Tamazight (Arabic)
2143: None, # TODO: Tamazight (Latin)
1097: 'ta', # Tamil
1092: 'tt', # Tatar
1098: 'te', # Telugu
1054: 'th', # Thai
2129: 'bo', # Tibetan - Bhutan
1105: 'bo', # Tibetan - People's Republic of China
2163: 'ti', # Tigrigna - Eritrea
1139: 'ti', # Tigrigna - Ethiopia
1073: 'ts', # Tsonga
1074: 'tn', # Tswana
# we have tr and tr_TR translations. tr seems more complete
0x041F: 'tr', # Turkish
1090: 'tk', # Turkmen
1152: 'ug', # Uighur - China
0x0422: 'uk', # Ukrainian
1056: 'ur', # Urdu
2080: 'ur', # Urdu - India
2115: 'uz', # Uzbek (Cyrillic)
1091: 'uz', # Uzbek (Latin)
1075: 've', # Venda
1066: 'vi', # Vietnamese
1106: 'cy', # Welsh
1076: 'xh', # Xhosa
1144: 'ii', # Yi
1085: 'yi', # Yiddish
1130: 'yo', # Yoruba
1077: 'zu'} # Zulu
return mapping[lcid]
def _getscreenlanguage():
'''
:returns: the locale for this session.
If the LANGUAGE environment variable is set, it's value overrides the
screen language detection. Otherwise the screen language is determined by
the currently selected Microsoft Windows MUI language pack or the Microsoft
Windows installation language.
Works on Microsoft Windows 2000 and up.
'''
# Start with nothing
lang = None
# Check the LANGUAGE environment variable
lang = os.getenv('LANGUAGE')
if lang is None:
# Start with nothing
lcid = None
try:
from ctypes import windll
lcid = windll.kernel32.GetUserDefaultUILanguage()
except:
logger.warning('Failed to get current screen language with \'GetUserDefaultUILanguage\'')
finally:
if lcid is None:
lang = 'C'
else:
lang = _localefromlcid(lcid)
logger.info('Windows screen language is \'%s\' (lcid %s)', lang, lcid)
return lang
def install(domain, localedir):
'''
:param domain: translation domain
:param localedir: locale directory
'''
# prep locale system
locale.setlocale(locale.LC_ALL, '')
# on windows systems, set the LANGUAGE environment variable
if sys.platform == 'win32' or sys.platform == 'nt':
os.environ['LANGUAGE'] = _getscreenlanguage()
# initialize Python's gettext interface
gettext.bindtextdomain(domain, localedir)
# on windows systems, initialize libintl
if sys.platform == 'win32' or sys.platform == 'nt':
from ctypes import cdll
libintl = cdll.LoadLibrary('libintl-8.dll')
libintl.bindtextdomain(domain.encode('mbcs'), localedir.encode('mbcs'))
del libintl