from collections import Mapping
import flask
from flask_babel import lazy_gettext as _
from xmm.util.i18n import LanguageDict
from .collection import DictField
class MultilingualField(DictField):
"""A language mapping field."""
field_name = _('Mehrsprachig')
type_name = 'i18n'
def __init__(self, field, *args, **kwargs):
kwargs['field'] = field
super().__init__(*args, **kwargs)
def __set__(self, instance, value):
if not isinstance(value, LanguageDict):
if isinstance(value, Mapping):
value = LanguageDict(value, instance, self.name)
for k, v in list(value.items()):
if v is None:
del value[k]
else:
old_value = instance._data.get(self.name) or {}
if value is None:
if flask.g.lang_code in old_value:
del old_value[flask.g.lang_code]
else:
old_value[flask.g.lang_code] = value
value = old_value
super().__set__(instance, value)
def __get__(self, instance, owner):
if instance is None:
return self
dct = super().__get__(instance, owner)
if dct is None:
dct = {}
dct = LanguageDict(dct, instance, self.name)
super().__set__(instance, dct)
elif not isinstance(dct, LanguageDict):
dct = LanguageDict(dct, instance, self.name)
super().__set__(instance, dct)
return dct
def __getattr__(self, item):
if hasattr(self.field, item):
field = self.get_field()
return getattr(field, item)
raise AttributeError(item)
def _to_thing(self, thing, value, **options):
if not isinstance(value, dict):
value = {flask.current_app.config['DEFAULT_LANGUAGE']: value}
thing_fun = getattr(self.get_field(), 'to_{}'.format(thing))
mapped = {}
langs = options.get('langs') or flask.current_app.config['LANGUAGES']
for lang in langs:
if thing == 'json':
options['lang'] = lang
mapped[lang] = thing_fun(value.get(lang), **options)
return LanguageDict(mapped, None, self.name)
def to_type(self, value):
return self._to_thing('type', value)
def to_json(self, value, **options):
return self._to_thing('json', value, **options)
def to_python(self, value):
return self._to_thing('python', value)
def to_mongo(self, value):
if isinstance(value, Mapping):
return self._to_thing('mongo', value)
return super().to_mongo(value)
def to_str(self, value, format_spec=None):
if isinstance(value, LanguageDict):
if format_spec is None:
value = value.get(flask.current_app.config['LANGUAGES'])
else:
value = value.get(format_spec)
ret = self.get_field().to_str(value)
if ret is None:
return None
return str(ret)