Initial commit
This commit is contained in:
276
env/lib/python3.10/site-packages/l18n/translation.py
vendored
Normal file
276
env/lib/python3.10/site-packages/l18n/translation.py
vendored
Normal file
@@ -0,0 +1,276 @@
|
||||
import os
|
||||
import gettext
|
||||
import bisect
|
||||
from locale import getdefaultlocale
|
||||
from copy import copy, deepcopy
|
||||
|
||||
import six
|
||||
|
||||
from .compat import MutableMapping
|
||||
|
||||
|
||||
class Trans(object):
|
||||
|
||||
def __init__(self):
|
||||
self.registry = {}
|
||||
self.current = None
|
||||
self.set(getdefaultlocale()[0])
|
||||
|
||||
def __getitem__(self, language):
|
||||
if language:
|
||||
try:
|
||||
return self.registry[language]
|
||||
except KeyError:
|
||||
self.registry[language] = gettext.translation(
|
||||
'l18n',
|
||||
os.path.join(os.path.dirname(__file__), 'locale'),
|
||||
languages=[language],
|
||||
fallback=True
|
||||
)
|
||||
return self.registry[language]
|
||||
else:
|
||||
return None
|
||||
|
||||
def set(self, language):
|
||||
self.current = self[language]
|
||||
|
||||
def gettext(self, s):
|
||||
try:
|
||||
return self.current.gettext(s)
|
||||
except AttributeError:
|
||||
return s
|
||||
|
||||
if six.PY2:
|
||||
def ugettext(self, s):
|
||||
try:
|
||||
return self.current.ugettext(s)
|
||||
except AttributeError:
|
||||
return s
|
||||
|
||||
|
||||
_trans = Trans()
|
||||
|
||||
|
||||
def set_language(language=None):
|
||||
_trans.set(language)
|
||||
|
||||
|
||||
if six.PY2:
|
||||
def translate(s, utf8=True, trans=_trans):
|
||||
if trans:
|
||||
if utf8:
|
||||
return trans.ugettext(s)
|
||||
return trans.gettext(s)
|
||||
else:
|
||||
return s
|
||||
else:
|
||||
def translate(s, utf8=True, trans=_trans):
|
||||
if trans:
|
||||
t = trans.gettext(s)
|
||||
if utf8:
|
||||
return t
|
||||
return t.encode()
|
||||
else:
|
||||
return s
|
||||
|
||||
|
||||
class L18NLazyObject(object):
|
||||
|
||||
def _value(self, utf8=True):
|
||||
raise NotImplementedError
|
||||
|
||||
def __str__(self):
|
||||
return self._value(utf8=six.PY3)
|
||||
|
||||
def __bytes__(self):
|
||||
return self._value(utf8=False)
|
||||
|
||||
def __unicode__(self):
|
||||
return self._value(utf8=True)
|
||||
|
||||
|
||||
class L18NLazyString(L18NLazyObject):
|
||||
|
||||
def __init__(self, s):
|
||||
self._str = s
|
||||
|
||||
def __copy__(self):
|
||||
return self.__class__(self._str)
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
result = self.__copy__()
|
||||
memo[id(self)] = result
|
||||
return result
|
||||
|
||||
def _value(self, utf8=True):
|
||||
return translate(self._str, utf8)
|
||||
|
||||
def __repr__(self):
|
||||
return 'L18NLazyString <%s>' % repr(self._str)
|
||||
|
||||
def __getattr__(self, name):
|
||||
# fallback to call the value's attribute in case it's not found in
|
||||
# L18NLazyString
|
||||
return getattr(self._value(), name)
|
||||
|
||||
|
||||
class L18NLazyStringsList(L18NLazyObject):
|
||||
|
||||
def __init__(self, sep='/', *s):
|
||||
# we assume that the separator and the strings have the same encoding
|
||||
# (text_type)
|
||||
self._sep = sep
|
||||
self._strings = s
|
||||
|
||||
def __copy__(self):
|
||||
return self.__class__(self._sep, *self._strings)
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
result = self.__copy__()
|
||||
memo[id(self)] = result
|
||||
return result
|
||||
|
||||
def _value(self, utf8=True):
|
||||
sep = self._sep
|
||||
if utf8 and isinstance(sep, six.binary_type):
|
||||
sep = sep.decode(encoding='utf-8')
|
||||
elif not utf8 and isinstance(sep, str):
|
||||
sep = sep.encode(encoding='utf-8')
|
||||
return sep.join([translate(s, utf8)
|
||||
for s in self._strings])
|
||||
|
||||
def __repr__(self):
|
||||
return 'L18NLazyStringsList <%s>' % self._sep.join([
|
||||
repr(s) for s in self._strings
|
||||
])
|
||||
|
||||
def __getattr__(self, name):
|
||||
# fallback to call the value's attribute in case it's not found in
|
||||
# L18NLazyStringsList
|
||||
return getattr(self._value(), name)
|
||||
|
||||
|
||||
class L18NBaseMap(MutableMapping):
|
||||
"""
|
||||
Generic dictionary that returns lazy string or lazy string lists
|
||||
"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.store = dict(*args, **kwargs)
|
||||
self.sorted = {}
|
||||
|
||||
def __copy__(self):
|
||||
result = self.__class__()
|
||||
result.store = self.store
|
||||
result.sorted = self.sorted
|
||||
return result
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
result = self.__class__()
|
||||
memo[id(self)] = result
|
||||
result.store = deepcopy(self.store, memo)
|
||||
result.sorted = deepcopy(self.sorted, memo)
|
||||
return result
|
||||
|
||||
def __getitem__(self, key):
|
||||
raise NotImplementedError
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
self.store[key] = value
|
||||
for locale, (keys, values) in six.iteritems(self.sorted):
|
||||
tr = translate(value, trans=_trans[locale])
|
||||
i = bisect.bisect_left(values, tr)
|
||||
keys.insert(i, key)
|
||||
values.insert(i, tr)
|
||||
|
||||
def __delitem__(self, key):
|
||||
del self.store[key]
|
||||
for keys, values in self.sorted.values():
|
||||
i = keys.index(key)
|
||||
del keys[i]
|
||||
del values[i]
|
||||
|
||||
def __iter__(self):
|
||||
loc = _trans.current._info['language'] if _trans.current else None
|
||||
try:
|
||||
return iter(self.sorted[loc][0])
|
||||
except KeyError:
|
||||
keys = []
|
||||
values = []
|
||||
# we can't use iteritems here, as we need to call __getitem__
|
||||
# via self[key]
|
||||
for key in iter(self.store):
|
||||
value = str(self[key])
|
||||
i = bisect.bisect_left(values, value)
|
||||
keys.insert(i, key)
|
||||
values.insert(i, value)
|
||||
self.sorted[loc] = (keys, values)
|
||||
return iter(keys)
|
||||
|
||||
def __len__(self):
|
||||
return len(self.store)
|
||||
|
||||
def subset(self, keys):
|
||||
"""
|
||||
Generates a subset of the current map (e.g. to retrieve only tzs in
|
||||
common_timezones from the tz_cities or tz_fullnames maps)
|
||||
"""
|
||||
sub = self.__class__()
|
||||
|
||||
self_keys = set(self.store.keys())
|
||||
subset_keys = self_keys.intersection(keys)
|
||||
removed_keys = self_keys.difference(subset_keys)
|
||||
|
||||
sub.store = {k: self.store[k] for k in subset_keys}
|
||||
for loc, sorted_items in six.iteritems(self.sorted):
|
||||
loc_keys = copy(self.sorted[loc][0])
|
||||
loc_values = copy(self.sorted[loc][1])
|
||||
for k in removed_keys:
|
||||
i = loc_keys.index(k)
|
||||
del loc_keys[i]
|
||||
del loc_values[i]
|
||||
sub.sorted[loc] = (loc_keys, loc_values)
|
||||
return sub
|
||||
|
||||
|
||||
class L18NMap(L18NBaseMap):
|
||||
|
||||
def __getitem__(self, key):
|
||||
return L18NLazyString(self.store[key])
|
||||
|
||||
|
||||
class L18NListMap(L18NBaseMap):
|
||||
|
||||
def __init__(self, sep='/', aux=None, *args, **kwargs):
|
||||
self._sep = sep
|
||||
self._aux = aux
|
||||
super(L18NListMap, self).__init__(*args, **kwargs)
|
||||
|
||||
def __copy__(self):
|
||||
result = super(L18NListMap, self).__copy__()
|
||||
result._sep = self._sep
|
||||
result._aux = self._aux
|
||||
return result
|
||||
|
||||
def __deepcopy__(self, memo):
|
||||
result = super(L18NListMap, self).__deepcopy__(memo)
|
||||
result._sep = self._sep
|
||||
result._aux = None if self._aux is None else deepcopy(self._aux, memo)
|
||||
return result
|
||||
|
||||
def __getitem__(self, key):
|
||||
strs = key.split(self._sep)
|
||||
strs[-1] = key
|
||||
lst = []
|
||||
for s in strs:
|
||||
try:
|
||||
lst.append(self.store[s])
|
||||
except KeyError:
|
||||
lst.append(self._aux[s])
|
||||
return L18NLazyStringsList(self._sep, *lst)
|
||||
|
||||
def subset(self, keys):
|
||||
sub = super(L18NListMap, self).subset(keys)
|
||||
sub._sep = self._sep
|
||||
sub._aux = deepcopy(self._aux)
|
||||
return sub
|
||||
Reference in New Issue
Block a user