2017-05-25 19:40:03 +03:00

160 lines
4.2 KiB
Python

import collections
from django.conf import settings
from django.utils import translation
class LocalizedValue(dict):
"""Represents the value of a :see:LocalizedField."""
def __init__(self, keys: dict=None):
"""Initializes a new instance of :see:LocalizedValue.
Arguments:
keys:
The keys to initialize this value with. Every
key contains the value of this field in a
different language.
"""
super().__init__({})
self._interpret_value(keys)
def get(self, language: str=None) -> str:
"""Gets the underlying value in the specified or
primary language.
Arguments:
language:
The language to get the value in.
Returns:
The value in the current language, or
the primary language in case no language
was specified.
"""
language = language or settings.LANGUAGE_CODE
return super().get(language, None)
def set(self, language: str, value: str):
"""Sets the value in the specified language.
Arguments:
language:
The language to set the value in.
value:
The value to set.
"""
self[language] = value
self.__dict__.update(self)
return self
def deconstruct(self) -> dict:
"""Deconstructs this value into a primitive type.
Returns:
A dictionary with all the localized values
contained in this instance.
"""
path = 'localized_fields.fields.LocalizedValue'
return path, [self.__dict__], {}
def _interpret_value(self, value):
"""Interprets a value passed in the constructor as
a :see:LocalizedValue.
If string:
Assumes it's the default language.
If dict:
Each key is a language and the value a string
in that language.
If list:
Recurse into to apply rules above.
Arguments:
value:
The value to interpret.
"""
for lang_code, _ in settings.LANGUAGES:
self.set(lang_code, None)
if isinstance(value, str):
self.set(settings.LANGUAGE_CODE, value)
elif isinstance(value, dict):
for lang_code, _ in settings.LANGUAGES:
lang_value = value.get(lang_code) or None
self.set(lang_code, lang_value)
elif isinstance(value, collections.Iterable):
for val in value:
self._interpret_value(val)
def __str__(self) -> str:
"""Gets the value in the current language, or falls
back to the primary language if there's no value
in the current language."""
value = self.get(translation.get_language())
if not value:
value = self.get(settings.LANGUAGE_CODE)
return value or ''
def __eq__(self, other):
"""Compares :paramref:self to :paramref:other for
equality.
Returns:
True when :paramref:self is equal to :paramref:other.
And False when they are not.
"""
if not isinstance(other, type(self)):
if isinstance(other, str):
return self.__str__() == other
return False
for lang_code, _ in settings.LANGUAGES:
if self.get(lang_code) != other.get(lang_code):
return False
return True
def __ne__(self, other):
"""Compares :paramref:self to :paramerf:other for
in-equality.
Returns:
True when :paramref:self is not equal to :paramref:other.
And False when they are.
"""
return not self.__eq__(other)
def __setattr__(self, language: str, value: str):
"""Sets the value for a language with the specified name.
Arguments:
language:
The language to set the value in.
value:
The value to set.
"""
self.set(language, value)
def __repr__(self): # pragma: no cover
"""Gets a textual representation of this object."""
return 'LocalizedValue<%s> 0x%s' % (dict(self), id(self))