npbackup/i18n/translator.py
2023-03-22 00:17:16 +01:00

115 lines
3.9 KiB
Python

from string import Template
from . import config
from . import resource_loader
from . import translations
from .custom_functions import get_function
class TranslationFormatter(Template, dict):
delimiter = config.get('placeholder_delimiter')
idpattern = r"""
\w+ # name
(
\(
[^\(\){}]* # arguments
\)
)?
"""
def __init__(self, translation_key, template):
super(TranslationFormatter, self).__init__(template)
self.translation_key = translation_key
def format(self, locale, **kwargs):
self.clear()
self.update(kwargs)
self.locale = locale
if config.get('on_missing_placeholder'):
return self.substitute(self)
else:
return self.safe_substitute(self)
def __getitem__(self, key: str):
try:
name, _, args = key.partition("(")
if args:
f = get_function(name, self.locale)
if f:
i = f(**self)
args = args.strip(')').split(config.get('argument_delimiter'))
try:
return args[i]
except (IndexError, TypeError) as e:
raise ValueError(
"No argument {0!r} for function {1!r} (in {2!r})"
.format(i, name, self.template)
) from e
raise KeyError(
"No function {0!r} found for locale {1!r} (in {2!r})"
.format(name, self.locale, self.template)
)
return super().__getitem__(key)
except KeyError:
on_missing = config.get('on_missing_placeholder')
if not on_missing or on_missing == "error":
raise
return on_missing(self.translation_key, self.locale, self.template, key)
def t(key, **kwargs):
locale = kwargs.pop('locale', config.get('locale'))
if translations.has(key, locale):
return translate(key, locale=locale, **kwargs)
else:
resource_loader.search_translation(key, locale)
if translations.has(key, locale):
return translate(key, locale=locale, **kwargs)
elif locale != config.get('fallback'):
return t(key, locale=config.get('fallback'), **kwargs)
if 'default' in kwargs:
return kwargs['default']
on_missing = config.get('on_missing_translation')
if on_missing == "error":
raise KeyError('key {0} not found'.format(key))
elif on_missing:
return on_missing(key, locale, **kwargs)
else:
return key
def translate(key, **kwargs):
locale = kwargs.pop('locale', config.get('locale'))
translation = translations.get(key, locale=locale)
if 'count' in kwargs:
translation = pluralize(key, locale, translation, kwargs['count'])
return TranslationFormatter(key, translation).format(locale, **kwargs)
def pluralize(key, locale, translation, count):
return_value = key
try:
if type(translation) != dict:
return_value = translation
raise KeyError('use of count witouth dict for key {0}'.format(key))
if count == 0:
if 'zero' in translation:
return translation['zero']
elif count == 1:
if 'one' in translation:
return translation['one']
elif count <= config.get('plural_few'):
if 'few' in translation:
return translation['few']
if 'many' in translation:
return translation['many']
else:
raise KeyError('"many" not defined for key {0}'.format(key))
except KeyError:
on_missing = config.get('on_missing_plural')
if on_missing == "error":
raise
elif on_missing:
return on_missing(key, locale, translation, count)
else:
return return_value