195be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw"""Internationalization and localization support. 295be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 395be23dc8626684caa268df7ff7749fcb89adddfBarry WarsawThis module provides internationalization (I18N) and localization (L10N) 495be23dc8626684caa268df7ff7749fcb89adddfBarry Warsawsupport for your Python programs by providing an interface to the GNU gettext 595be23dc8626684caa268df7ff7749fcb89adddfBarry Warsawmessage catalog library. 695be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 795be23dc8626684caa268df7ff7749fcb89adddfBarry WarsawI18N refers to the operation by which a program is made aware of multiple 895be23dc8626684caa268df7ff7749fcb89adddfBarry Warsawlanguages. L10N refers to the adaptation of your program, once 933d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsawinternationalized, to the local language and cultural habits. 1095be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 1195be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw""" 1295be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 13fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw# This module represents the integration of work, contributions, feedback, and 14fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw# suggestions from the following people: 1595be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw# 1695be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw# Martin von Loewis, who wrote the initial implementation of the underlying 1795be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw# C-based libintlmodule (later renamed _gettext), along with a skeletal 1895be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw# gettext.py implementation. 1995be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw# 2095be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw# Peter Funk, who wrote fintl.py, a fairly complete wrapper around intlmodule, 2195be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw# which also included a pure-Python implementation to read .mo files if 2295be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw# intlmodule wasn't available. 2395be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw# 2495be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw# James Henstridge, who also wrote a gettext.py module, which has some 2595be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw# interesting, but currently unsupported experimental features: the notion of 2695be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw# a Catalog class and instances, and the ability to add to a catalog file via 2795be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw# a Python API. 2895be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw# 2995be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw# Barry Warsaw integrated these modules, wrote the .install() API and code, 3095be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw# and conformed all C and Python code to Python's coding standards. 3133d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# 3233d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# Francois Pinard and Marc-Andre Lemburg also contributed valuably to this 3333d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# module. 3433d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# 35a57dccdcd473f3c8187e68348ebcd71c904be9e3Martin v. Löwis# J. David Ibanez implemented plural forms. Bruno Haible fixed some bugs. 36d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis# 3733d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# TODO: 3833d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# - Lazy loading of .mo files. Currently the entire catalog is loaded into 3933d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# memory, but that's probably bad for large translated programs. Instead, 4033d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# the lexical sort of original strings in GNU .mo files should be exploited 4133d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# to do binary searches and lazy initializations. Or you might want to use 4233d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# the undocumented double-hash algorithm for .mo files with hash tables, but 4333d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# you'll need to study the GNU gettext code to do this. 4433d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# 4533d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# - Support Solaris .mo file formats. Unfortunately, we've been unable to 4633d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# find this format documented anywhere. 4795be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 48d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 497bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyerimport locale, copy, os, re, struct, sys 5033d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsawfrom errno import ENOENT 5195be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 52d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 53a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw__all__ = ['NullTranslations', 'GNUTranslations', 'Catalog', 54a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw 'find', 'translation', 'install', 'textdomain', 'bindtextdomain', 552ca7bb0ba20b6e508625733a75a1c6aae61983bfAndrew Kuchling 'bind_textdomain_codeset', 562ca7bb0ba20b6e508625733a75a1c6aae61983bfAndrew Kuchling 'dgettext', 'dngettext', 'gettext', 'lgettext', 'ldgettext', 572ca7bb0ba20b6e508625733a75a1c6aae61983bfAndrew Kuchling 'ldngettext', 'lngettext', 'ngettext', 58a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw ] 592dd4276559658e06eaf8b623c2c47373f1f50688Skip Montanaro 6033d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw_default_localedir = os.path.join(sys.prefix, 'share', 'locale') 6195be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 62a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka# Expression parsing for plural form selection. 63a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka# 64a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka# The gettext library supports a small subset of C syntax. The only 65a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka# incompatible difference is that integer literals starting with zero are 66a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka# decimal. 67a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka# 68a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka# https://www.gnu.org/software/gettext/manual/gettext.html#Plural-forms 69a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka# http://git.savannah.gnu.org/cgit/gettext.git/tree/gettext-runtime/intl/plural.y 70a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka 71a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka_token_pattern = re.compile(r""" 72a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka (?P<WHITESPACES>[ \t]+) | # spaces and horizontal tabs 73a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka (?P<NUMBER>[0-9]+\b) | # decimal integer 74a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka (?P<NAME>n\b) | # only n is allowed 75a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka (?P<PARENTHESIS>[()]) | 76a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka (?P<OPERATOR>[-*/%+?:]|[><!]=?|==|&&|\|\|) | # !, *, /, %, +, -, <, >, 77a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka # <=, >=, ==, !=, &&, ||, 78a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka # ? : 79a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka # unary and bitwise ops 80a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka # not allowed 81a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka (?P<INVALID>\w+|.) # invalid token 82a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka """, re.VERBOSE|re.DOTALL) 83a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka 84a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchakadef _tokenize(plural): 85a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka for mo in re.finditer(_token_pattern, plural): 86a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka kind = mo.lastgroup 87a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka if kind == 'WHITESPACES': 88a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka continue 89a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka value = mo.group(kind) 90a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka if kind == 'INVALID': 91a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka raise ValueError('invalid token in plural form: %s' % value) 92a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka yield value 93a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka yield '' 94a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka 95a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchakadef _error(value): 96a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka if value: 97a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka return ValueError('unexpected token in plural form: %s' % value) 98d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis else: 99a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka return ValueError('unexpected end of plural form') 100a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka 101a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka_binary_ops = ( 102a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka ('||',), 103a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka ('&&',), 104a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka ('==', '!='), 105a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka ('<', '>', '<=', '>='), 106a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka ('+', '-'), 107a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka ('*', '/', '%'), 108a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka) 109a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka_binary_ops = {op: i for i, ops in enumerate(_binary_ops, 1) for op in ops} 110a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka_c2py_ops = {'||': 'or', '&&': 'and', '/': '//'} 111a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka 112a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchakadef _parse(tokens, priority=-1): 113a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka result = '' 114a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka nexttok = next(tokens) 115a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka while nexttok == '!': 116a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka result += 'not ' 117a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka nexttok = next(tokens) 118a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka 119a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka if nexttok == '(': 120a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka sub, nexttok = _parse(tokens) 121a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka result = '%s(%s)' % (result, sub) 122a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka if nexttok != ')': 123a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka raise ValueError('unbalanced parenthesis in plural form') 124a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka elif nexttok == 'n': 125a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka result = '%s%s' % (result, nexttok) 126a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka else: 127a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka try: 128a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka value = int(nexttok, 10) 129a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka except ValueError: 130a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka raise _error(nexttok) 131a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka result = '%s%d' % (result, value) 132a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka nexttok = next(tokens) 133a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka 134a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka j = 100 135a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka while nexttok in _binary_ops: 136a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka i = _binary_ops[nexttok] 137a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka if i < priority: 138a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka break 139a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka # Break chained comparisons 140a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka if i in (3, 4) and j in (3, 4): # '==', '!=', '<', '>', '<=', '>=' 141a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka result = '(%s)' % result 142a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka # Replace some C operators by their Python equivalents 143a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka op = _c2py_ops.get(nexttok, nexttok) 144a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka right, nexttok = _parse(tokens, i + 1) 145a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka result = '%s %s %s' % (result, op, right) 146a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka j = i 147a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka if j == priority == 4: # '<', '>', '<=', '>=' 148a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka result = '(%s)' % result 149a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka 150a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka if nexttok == '?' and priority <= 0: 151a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka if_true, nexttok = _parse(tokens, 0) 152a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka if nexttok != ':': 153a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka raise _error(nexttok) 154a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka if_false, nexttok = _parse(tokens) 155a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka result = '%s if %s else %s' % (if_true, result, if_false) 156a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka if priority == 0: 157a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka result = '(%s)' % result 158a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka 159a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka return result, nexttok 160d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 161d3e6c9e4dcf3fd4e97a2526164cc7e28766b8e6dSerhiy Storchakadef _as_int(n): 162d3e6c9e4dcf3fd4e97a2526164cc7e28766b8e6dSerhiy Storchaka try: 163d3e6c9e4dcf3fd4e97a2526164cc7e28766b8e6dSerhiy Storchaka i = round(n) 164d3e6c9e4dcf3fd4e97a2526164cc7e28766b8e6dSerhiy Storchaka except TypeError: 165d3e6c9e4dcf3fd4e97a2526164cc7e28766b8e6dSerhiy Storchaka raise TypeError('Plural value must be an integer, got %s' % 166d3e6c9e4dcf3fd4e97a2526164cc7e28766b8e6dSerhiy Storchaka (n.__class__.__name__,)) 167d3e6c9e4dcf3fd4e97a2526164cc7e28766b8e6dSerhiy Storchaka return n 168d3e6c9e4dcf3fd4e97a2526164cc7e28766b8e6dSerhiy Storchaka 169d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwisdef c2py(plural): 170c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw """Gets a C expression as used in PO files for plural forms and returns a 171a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka Python function that implements an equivalent expression. 172d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis """ 173d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 174a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka if len(plural) > 1000: 175a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka raise ValueError('plural form expression is too long') 176a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka try: 177a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka result, nexttok = _parse(_tokenize(plural)) 178a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka if nexttok: 179a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka raise _error(nexttok) 180a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka 181a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka depth = 0 182a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka for c in result: 183a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka if c == '(': 184a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka depth += 1 185a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka if depth > 20: 186a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka # Python compiler limit is about 90. 187a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka # The most complex example has 2. 188a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka raise ValueError('plural form expression is too complex') 189a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka elif c == ')': 190a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka depth -= 1 191a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka 192d3e6c9e4dcf3fd4e97a2526164cc7e28766b8e6dSerhiy Storchaka ns = {'_as_int': _as_int} 193a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka exec('''if 1: 194a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka def func(n): 195a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka if not isinstance(n, int): 196d3e6c9e4dcf3fd4e97a2526164cc7e28766b8e6dSerhiy Storchaka n = _as_int(n) 197a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka return int(%s) 198a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka ''' % result, ns) 199a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka return ns['func'] 200a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka except RuntimeError: 201a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka # Recursion error can be raised in _parse() or exec(). 202a8760275bd59fb8d8be1f1bf05313fed31c08321Serhiy Storchaka raise ValueError('plural form expression is too complex') 203d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 20407e99cb77406e1bc84606f49b743e41b0de8a6d5Tim Peters 205fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsawdef _expand_lang(locale): 206fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw from locale import normalize 207fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw locale = normalize(locale) 208fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw COMPONENT_CODESET = 1 << 0 209fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw COMPONENT_TERRITORY = 1 << 1 210fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw COMPONENT_MODIFIER = 1 << 2 211fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw # split up the locale into its base components 212fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw mask = 0 213fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw pos = locale.find('@') 214fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw if pos >= 0: 215fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw modifier = locale[pos:] 216fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw locale = locale[:pos] 217fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw mask |= COMPONENT_MODIFIER 218fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw else: 219fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw modifier = '' 220fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw pos = locale.find('.') 221fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw if pos >= 0: 222fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw codeset = locale[pos:] 223fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw locale = locale[:pos] 224fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw mask |= COMPONENT_CODESET 225fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw else: 226fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw codeset = '' 227fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw pos = locale.find('_') 228fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw if pos >= 0: 229fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw territory = locale[pos:] 230fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw locale = locale[:pos] 231fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw mask |= COMPONENT_TERRITORY 232fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw else: 233fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw territory = '' 234fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw language = locale 235fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw ret = [] 236fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw for i in range(mask+1): 237fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw if not (i & ~mask): # if all components for this combo exist ... 238fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw val = language 239fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw if i & COMPONENT_TERRITORY: val += territory 240fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw if i & COMPONENT_CODESET: val += codeset 241fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw if i & COMPONENT_MODIFIER: val += modifier 242fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw ret.append(val) 243fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw ret.reverse() 244fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw return ret 245fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw 246fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw 24707e99cb77406e1bc84606f49b743e41b0de8a6d5Tim Peters 24833d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsawclass NullTranslations: 24933d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw def __init__(self, fp=None): 25033d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw self._info = {} 2516008cbd4c2b5b4f5e9941f312804e12c88aa6efeBarry Warsaw self._charset = None 2527bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer self._output_charset = None 253a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis self._fallback = None 254094662a16542d1cc56713b35dde39089490dec35Raymond Hettinger if fp is not None: 25533d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw self._parse(fp) 25695be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 25733d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw def _parse(self, fp): 25833d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw pass 25933d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw 260a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis def add_fallback(self, fallback): 261a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis if self._fallback: 262a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis self._fallback.add_fallback(fallback) 263a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis else: 264a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis self._fallback = fallback 265a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis 26633d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw def gettext(self, message): 267a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis if self._fallback: 268a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis return self._fallback.gettext(message) 26933d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw return message 27033d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw 2717bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer def lgettext(self, message): 2727bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer if self._fallback: 2737bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return self._fallback.lgettext(message) 2747bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return message 2757bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer 276d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis def ngettext(self, msgid1, msgid2, n): 277d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis if self._fallback: 278d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis return self._fallback.ngettext(msgid1, msgid2, n) 279d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis if n == 1: 280d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis return msgid1 281d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis else: 282d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis return msgid2 283d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 2847bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer def lngettext(self, msgid1, msgid2, n): 2857bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer if self._fallback: 2867bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return self._fallback.lngettext(msgid1, msgid2, n) 2877bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer if n == 1: 2887bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return msgid1 2897bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer else: 2907bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return msgid2 2917bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer 29233d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw def ugettext(self, message): 293a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis if self._fallback: 294a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis return self._fallback.ugettext(message) 29533d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw return unicode(message) 29633d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw 297d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis def ungettext(self, msgid1, msgid2, n): 298d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis if self._fallback: 299d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis return self._fallback.ungettext(msgid1, msgid2, n) 300d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis if n == 1: 301d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis return unicode(msgid1) 302d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis else: 303d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis return unicode(msgid2) 304d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 30533d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw def info(self): 30633d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw return self._info 30733d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw 30833d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw def charset(self): 30933d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw return self._charset 31033d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw 3117bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer def output_charset(self): 3127bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return self._output_charset 3137bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer 3147bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer def set_output_charset(self, charset): 3157bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer self._output_charset = charset 3167bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer 317602b9ba6b37c4ac4ed445f8c9e9dccd68d631899Georg Brandl def install(self, unicode=False, names=None): 31833d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw import __builtin__ 31933d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw __builtin__.__dict__['_'] = unicode and self.ugettext or self.gettext 320602b9ba6b37c4ac4ed445f8c9e9dccd68d631899Georg Brandl if hasattr(names, "__contains__"): 321602b9ba6b37c4ac4ed445f8c9e9dccd68d631899Georg Brandl if "gettext" in names: 322602b9ba6b37c4ac4ed445f8c9e9dccd68d631899Georg Brandl __builtin__.__dict__['gettext'] = __builtin__.__dict__['_'] 323602b9ba6b37c4ac4ed445f8c9e9dccd68d631899Georg Brandl if "ngettext" in names: 324602b9ba6b37c4ac4ed445f8c9e9dccd68d631899Georg Brandl __builtin__.__dict__['ngettext'] = (unicode and self.ungettext 325602b9ba6b37c4ac4ed445f8c9e9dccd68d631899Georg Brandl or self.ngettext) 326602b9ba6b37c4ac4ed445f8c9e9dccd68d631899Georg Brandl if "lgettext" in names: 327602b9ba6b37c4ac4ed445f8c9e9dccd68d631899Georg Brandl __builtin__.__dict__['lgettext'] = self.lgettext 328602b9ba6b37c4ac4ed445f8c9e9dccd68d631899Georg Brandl if "lngettext" in names: 329602b9ba6b37c4ac4ed445f8c9e9dccd68d631899Georg Brandl __builtin__.__dict__['lngettext'] = self.lngettext 33033d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw 33133d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw 33233d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsawclass GNUTranslations(NullTranslations): 33333d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw # Magic number of .mo files 33409707e363723fa24ba53e4e5d77cc26d4dea724fBarry Warsaw LE_MAGIC = 0x950412deL 33509707e363723fa24ba53e4e5d77cc26d4dea724fBarry Warsaw BE_MAGIC = 0xde120495L 33695be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 33795be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw def _parse(self, fp): 33895be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw """Override this method to support alternative .mo formats.""" 33995be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw unpack = struct.unpack 34095be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw filename = getattr(fp, 'name', '') 34195be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw # Parse the .mo file header, which consists of 5 little endian 32 34295be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw # bit words. 34333d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw self._catalog = catalog = {} 344a57dccdcd473f3c8187e68348ebcd71c904be9e3Martin v. Löwis self.plural = lambda n: int(n != 1) # germanic plural by default 34595be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw buf = fp.read() 3469a2d9d7f04f2ed08574c670bb5ee8ead2a4048ceBarry Warsaw buflen = len(buf) 34733d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw # Are we big endian or little endian? 34809707e363723fa24ba53e4e5d77cc26d4dea724fBarry Warsaw magic = unpack('<I', buf[:4])[0] 34933d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw if magic == self.LE_MAGIC: 35009707e363723fa24ba53e4e5d77cc26d4dea724fBarry Warsaw version, msgcount, masteridx, transidx = unpack('<4I', buf[4:20]) 35109707e363723fa24ba53e4e5d77cc26d4dea724fBarry Warsaw ii = '<II' 35233d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw elif magic == self.BE_MAGIC: 35309707e363723fa24ba53e4e5d77cc26d4dea724fBarry Warsaw version, msgcount, masteridx, transidx = unpack('>4I', buf[4:20]) 35409707e363723fa24ba53e4e5d77cc26d4dea724fBarry Warsaw ii = '>II' 35533d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw else: 35695be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw raise IOError(0, 'Bad magic number', filename) 35795be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw # Now put all messages from the .mo file buffer into the catalog 35895be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw # dictionary. 35995be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw for i in xrange(0, msgcount): 36033d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw mlen, moff = unpack(ii, buf[masteridx:masteridx+8]) 36109707e363723fa24ba53e4e5d77cc26d4dea724fBarry Warsaw mend = moff + mlen 36233d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw tlen, toff = unpack(ii, buf[transidx:transidx+8]) 36309707e363723fa24ba53e4e5d77cc26d4dea724fBarry Warsaw tend = toff + tlen 3649a2d9d7f04f2ed08574c670bb5ee8ead2a4048ceBarry Warsaw if mend < buflen and tend < buflen: 365d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis msg = buf[moff:mend] 36633d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw tmsg = buf[toff:tend] 36795be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw else: 36895be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw raise IOError(0, 'File is corrupt', filename) 36933d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw # See if we're looking at GNU .mo conventions for metadata 3706008cbd4c2b5b4f5e9941f312804e12c88aa6efeBarry Warsaw if mlen == 0: 37133d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw # Catalog description 372270b0586b0c13588ed6ffd86581f11235bb4d22aAndrew Kuchling lastk = None 373a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw for item in tmsg.splitlines(): 37433d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw item = item.strip() 37533d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw if not item: 37633d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw continue 377270b0586b0c13588ed6ffd86581f11235bb4d22aAndrew Kuchling k = v = None 3787de63f57c881cb94ba89c2a1dfaf79af1bba52bbBarry Warsaw if ':' in item: 3797de63f57c881cb94ba89c2a1dfaf79af1bba52bbBarry Warsaw k, v = item.split(':', 1) 3807de63f57c881cb94ba89c2a1dfaf79af1bba52bbBarry Warsaw k = k.strip().lower() 3817de63f57c881cb94ba89c2a1dfaf79af1bba52bbBarry Warsaw v = v.strip() 3827de63f57c881cb94ba89c2a1dfaf79af1bba52bbBarry Warsaw self._info[k] = v 3837de63f57c881cb94ba89c2a1dfaf79af1bba52bbBarry Warsaw lastk = k 3847de63f57c881cb94ba89c2a1dfaf79af1bba52bbBarry Warsaw elif lastk: 3857de63f57c881cb94ba89c2a1dfaf79af1bba52bbBarry Warsaw self._info[lastk] += '\n' + item 38633d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw if k == 'content-type': 38733d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw self._charset = v.split('charset=')[1] 388d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis elif k == 'plural-forms': 389d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis v = v.split(';') 390d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis plural = v[1].split('plural=')[1] 391d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis self.plural = c2py(plural) 392c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw # Note: we unconditionally convert both msgids and msgstrs to 393c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw # Unicode using the character encoding specified in the charset 394c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw # parameter of the Content-Type header. The gettext documentation 39524b07bcba350bb86c4d6ca446e1564647a199868Ezio Melotti # strongly encourages msgids to be us-ascii, but some applications 396c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw # require alternative encodings (e.g. Zope's ZCML and ZPT). For 397c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw # traditional gettext applications, the msgid conversion will 398c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw # cause no problems since us-ascii should always be a subset of 399c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw # the charset encoding. We may want to fall back to 8-bit msgids 400c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw # if the Unicode conversion fails. 401bac788a3cd348203a5fdabba52e5faf65bf35c5eRaymond Hettinger if '\x00' in msg: 4026008cbd4c2b5b4f5e9941f312804e12c88aa6efeBarry Warsaw # Plural forms 4036008cbd4c2b5b4f5e9941f312804e12c88aa6efeBarry Warsaw msgid1, msgid2 = msg.split('\x00') 4046008cbd4c2b5b4f5e9941f312804e12c88aa6efeBarry Warsaw tmsg = tmsg.split('\x00') 405c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw if self._charset: 4066008cbd4c2b5b4f5e9941f312804e12c88aa6efeBarry Warsaw msgid1 = unicode(msgid1, self._charset) 4076008cbd4c2b5b4f5e9941f312804e12c88aa6efeBarry Warsaw tmsg = [unicode(x, self._charset) for x in tmsg] 4086008cbd4c2b5b4f5e9941f312804e12c88aa6efeBarry Warsaw for i in range(len(tmsg)): 4096008cbd4c2b5b4f5e9941f312804e12c88aa6efeBarry Warsaw catalog[(msgid1, i)] = tmsg[i] 4106008cbd4c2b5b4f5e9941f312804e12c88aa6efeBarry Warsaw else: 411c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw if self._charset: 4126008cbd4c2b5b4f5e9941f312804e12c88aa6efeBarry Warsaw msg = unicode(msg, self._charset) 4136008cbd4c2b5b4f5e9941f312804e12c88aa6efeBarry Warsaw tmsg = unicode(tmsg, self._charset) 4146008cbd4c2b5b4f5e9941f312804e12c88aa6efeBarry Warsaw catalog[msg] = tmsg 41595be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw # advance to next entry in the seek tables 416fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw masteridx += 8 417fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw transidx += 8 41895be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 41933d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw def gettext(self, message): 420c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw missing = object() 421c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw tmsg = self._catalog.get(message, missing) 422c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw if tmsg is missing: 423a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis if self._fallback: 424a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis return self._fallback.gettext(message) 425a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis return message 426c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw # Encode the Unicode tmsg back to an 8-bit string, if possible 4277bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer if self._output_charset: 4287bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return tmsg.encode(self._output_charset) 4297bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer elif self._charset: 430c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw return tmsg.encode(self._charset) 431c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw return tmsg 43233d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw 4337bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer def lgettext(self, message): 4347bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer missing = object() 4357bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer tmsg = self._catalog.get(message, missing) 4367bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer if tmsg is missing: 4377bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer if self._fallback: 4387bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return self._fallback.lgettext(message) 4397bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return message 4407bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer if self._output_charset: 4417bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return tmsg.encode(self._output_charset) 4427bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return tmsg.encode(locale.getpreferredencoding()) 4437bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer 444d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis def ngettext(self, msgid1, msgid2, n): 445d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis try: 446c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw tmsg = self._catalog[(msgid1, self.plural(n))] 4477bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer if self._output_charset: 4487bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return tmsg.encode(self._output_charset) 4497bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer elif self._charset: 450c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw return tmsg.encode(self._charset) 451c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw return tmsg 452d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis except KeyError: 453d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis if self._fallback: 454d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis return self._fallback.ngettext(msgid1, msgid2, n) 455d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis if n == 1: 456d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis return msgid1 457d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis else: 458d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis return msgid2 459d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 4607bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer def lngettext(self, msgid1, msgid2, n): 4617bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer try: 4627bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer tmsg = self._catalog[(msgid1, self.plural(n))] 4637bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer if self._output_charset: 4647bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return tmsg.encode(self._output_charset) 4657bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return tmsg.encode(locale.getpreferredencoding()) 4667bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer except KeyError: 4677bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer if self._fallback: 4687bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return self._fallback.lngettext(msgid1, msgid2, n) 4697bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer if n == 1: 4707bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return msgid1 4717bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer else: 4727bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return msgid2 4737bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer 47433d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw def ugettext(self, message): 475a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw missing = object() 476a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw tmsg = self._catalog.get(message, missing) 477a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw if tmsg is missing: 478a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis if self._fallback: 479a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis return self._fallback.ugettext(message) 480c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw return unicode(message) 481a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw return tmsg 48295be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 483d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis def ungettext(self, msgid1, msgid2, n): 484d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis try: 485d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis tmsg = self._catalog[(msgid1, self.plural(n))] 486d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis except KeyError: 487d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis if self._fallback: 488d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis return self._fallback.ungettext(msgid1, msgid2, n) 489d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis if n == 1: 490c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw tmsg = unicode(msgid1) 491d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis else: 492c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw tmsg = unicode(msgid2) 493a1ce93f87cb221be9a7466c2f9d2b7dc494f458dBarry Warsaw return tmsg 494d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 49507e99cb77406e1bc84606f49b743e41b0de8a6d5Tim Peters 49695be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw# Locate a .mo file using the gettext strategy 497a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwisdef find(domain, localedir=None, languages=None, all=0): 49895be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw # Get some reasonable defaults for arguments that were not supplied 49995be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw if localedir is None: 50033d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw localedir = _default_localedir 50195be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw if languages is None: 50295be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw languages = [] 50395be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw for envar in ('LANGUAGE', 'LC_ALL', 'LC_MESSAGES', 'LANG'): 50495be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw val = os.environ.get(envar) 50595be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw if val: 50695be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw languages = val.split(':') 50795be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw break 50895be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw if 'C' not in languages: 50995be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw languages.append('C') 510fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw # now normalize and expand the languages 51175f8101c429e132472bba92f3972b7eac68f35f8Barry Warsaw nelangs = [] 512fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw for lang in languages: 513fa488ec2a0c60dc6a90d1be7b58d0a277db97b41Barry Warsaw for nelang in _expand_lang(lang): 51475f8101c429e132472bba92f3972b7eac68f35f8Barry Warsaw if nelang not in nelangs: 51575f8101c429e132472bba92f3972b7eac68f35f8Barry Warsaw nelangs.append(nelang) 51695be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw # select a language 517a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis if all: 518a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis result = [] 519a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis else: 520a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis result = None 52175f8101c429e132472bba92f3972b7eac68f35f8Barry Warsaw for lang in nelangs: 52295be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw if lang == 'C': 52395be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw break 52484314b72d65471b0ae68432aefe36a4691e3b04eBarry Warsaw mofile = os.path.join(localedir, lang, 'LC_MESSAGES', '%s.mo' % domain) 52533d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw if os.path.exists(mofile): 526a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis if all: 527a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis result.append(mofile) 528a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis else: 529a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis return mofile 530a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis return result 53195be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 53295be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 53307e99cb77406e1bc84606f49b743e41b0de8a6d5Tim Peters 53433d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# a mapping between absolute .mo file path and Translation object 53533d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw_translations = {} 53633d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw 5371be641987145f88d61e52d5b4714a8cc6c7e6da8Martin v. Löwisdef translation(domain, localedir=None, languages=None, 5387bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer class_=None, fallback=False, codeset=None): 53933d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw if class_ is None: 54033d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw class_ = GNUTranslations 541a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis mofiles = find(domain, localedir, languages, all=1) 542c4acc2bd32f14c22f9cd7a95021184809e096ebeBarry Warsaw if not mofiles: 5431be641987145f88d61e52d5b4714a8cc6c7e6da8Martin v. Löwis if fallback: 5441be641987145f88d61e52d5b4714a8cc6c7e6da8Martin v. Löwis return NullTranslations() 54533d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw raise IOError(ENOENT, 'No translation file found for domain', domain) 546293b03f73f5ad48719a0f07fb45857182dfb1d51Barry Warsaw # Avoid opening, reading, and parsing the .mo file after it's been done 547293b03f73f5ad48719a0f07fb45857182dfb1d51Barry Warsaw # once. 548a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis result = None 549a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis for mofile in mofiles: 550c17776f96e8654dc9510daf55d90987be2e4dec2Éric Araujo key = (class_, os.path.abspath(mofile)) 551a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis t = _translations.get(key) 552a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis if t is None: 55314c7bc2ad22f4fffdcf2b3d58b1358846a53079fBenjamin Peterson with open(mofile, 'rb') as fp: 55414c7bc2ad22f4fffdcf2b3d58b1358846a53079fBenjamin Peterson t = _translations.setdefault(key, class_(fp)) 5557bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer # Copy the translation object to allow setting fallbacks and 5567bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer # output charset. All other instance data is shared with the 5577bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer # cached object. 558a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis t = copy.copy(t) 5597bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer if codeset: 5607bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer t.set_output_charset(codeset) 561a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis if result is None: 562a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis result = t 563a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis else: 564a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis result.add_fallback(t) 565a55ffaeee9eb2fba62f280c364b3460fafd9efc9Martin v. Löwis return result 56633d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw 56707e99cb77406e1bc84606f49b743e41b0de8a6d5Tim Peters 568602b9ba6b37c4ac4ed445f8c9e9dccd68d631899Georg Brandldef install(domain, localedir=None, unicode=False, codeset=None, names=None): 5697bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer t = translation(domain, localedir, fallback=True, codeset=codeset) 570602b9ba6b37c4ac4ed445f8c9e9dccd68d631899Georg Brandl t.install(unicode, names) 57133d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw 57233d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw 57307e99cb77406e1bc84606f49b743e41b0de8a6d5Tim Peters 57433d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# a mapping b/w domains and locale directories 57533d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw_localedirs = {} 5767bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer# a mapping b/w domains and codesets 5777bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer_localecodesets = {} 57833d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# current global domain, `messages' used for compatibility w/ GNU gettext 57933d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw_current_domain = 'messages' 58095be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 58195be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 58295be23dc8626684caa268df7ff7749fcb89adddfBarry Warsawdef textdomain(domain=None): 58395be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw global _current_domain 58433d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw if domain is not None: 58595be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw _current_domain = domain 58633d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw return _current_domain 58795be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 58895be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 58933d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsawdef bindtextdomain(domain, localedir=None): 59033d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw global _localedirs 59133d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw if localedir is not None: 59233d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw _localedirs[domain] = localedir 59333d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw return _localedirs.get(domain, _default_localedir) 59495be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 59595be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 5967bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyerdef bind_textdomain_codeset(domain, codeset=None): 5977bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer global _localecodesets 5987bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer if codeset is not None: 5997bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer _localecodesets[domain] = codeset 6007bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return _localecodesets.get(domain) 6017bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer 6027bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer 60395be23dc8626684caa268df7ff7749fcb89adddfBarry Warsawdef dgettext(domain, message): 60433d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw try: 6057bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer t = translation(domain, _localedirs.get(domain, None), 6067bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer codeset=_localecodesets.get(domain)) 60733d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw except IOError: 60833d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw return message 60933d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw return t.gettext(message) 61007e99cb77406e1bc84606f49b743e41b0de8a6d5Tim Peters 6117bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyerdef ldgettext(domain, message): 6127bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer try: 6137bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer t = translation(domain, _localedirs.get(domain, None), 6147bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer codeset=_localecodesets.get(domain)) 6157bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer except IOError: 6167bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return message 6177bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return t.lgettext(message) 61895be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 619d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwisdef dngettext(domain, msgid1, msgid2, n): 620d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis try: 6217bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer t = translation(domain, _localedirs.get(domain, None), 6227bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer codeset=_localecodesets.get(domain)) 623d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis except IOError: 624d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis if n == 1: 625d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis return msgid1 626d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis else: 627d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis return msgid2 628d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis return t.ngettext(msgid1, msgid2, n) 629d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 6307bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyerdef ldngettext(domain, msgid1, msgid2, n): 6317bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer try: 6327bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer t = translation(domain, _localedirs.get(domain, None), 6337bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer codeset=_localecodesets.get(domain)) 6347bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer except IOError: 6357bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer if n == 1: 6367bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return msgid1 6377bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer else: 6387bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return msgid2 6397bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return t.lngettext(msgid1, msgid2, n) 640d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 64133d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsawdef gettext(message): 64233d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw return dgettext(_current_domain, message) 64395be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 6447bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyerdef lgettext(message): 6457bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return ldgettext(_current_domain, message) 64695be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 647d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwisdef ngettext(msgid1, msgid2, n): 648d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis return dngettext(_current_domain, msgid1, msgid2, n) 649d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 6507bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyerdef lngettext(msgid1, msgid2, n): 6517bd33c5e22c67e06042fb7ab1186f7587d78153dGustavo Niemeyer return ldngettext(_current_domain, msgid1, msgid2, n) 652d899605e30eef8e77f70184eac15fad1bf770586Martin v. Löwis 65333d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# dcgettext() has been deemed unnecessary and is not implemented. 65495be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 65533d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# James Henstridge's Catalog constructor from GNOME gettext. Documented usage 65633d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# was: 65733d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# 65833d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# import gettext 65933d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# cat = gettext.Catalog(PACKAGE, localedir=LOCALEDIR) 66033d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# _ = cat.gettext 66133d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# print _('Hello World') 66295be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 66333d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# The resulting catalog object currently don't support access through a 66433d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# dictionary API, which was supported (but apparently unused) in GNOME 66533d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry Warsaw# gettext. 66695be23dc8626684caa268df7ff7749fcb89adddfBarry Warsaw 66733d8d705b88ca6fb227d75d9b7f5bf8efda1d0a7Barry WarsawCatalog = translation 668