141 lines
5.6 KiB
Python
141 lines
5.6 KiB
Python
from django.db import models
|
|
from django.conf import settings
|
|
|
|
class TranslationAllreadyRegistered(Exception):
|
|
pass
|
|
|
|
class TranslationOptions(object):
|
|
|
|
def __init__(self, options={}):
|
|
self.language_field = options.get('language_field', 'language')
|
|
self.translation_of_model = options.get('translation_of_model')
|
|
self.translated_model = options.get('translated_model')
|
|
self.translation_of_field = options.get('translation_of_field')
|
|
self.translations_of_accessor = options.get('translations_of_accessor')
|
|
self.translation_join_filter = options.get('translation_join_filter')
|
|
|
|
class TranslationPool(object):
|
|
|
|
discovered = False
|
|
translated_models_dict = {}
|
|
translation_models_dict = {}
|
|
|
|
def discover_translations(self):
|
|
if self.discovered:
|
|
return
|
|
for app in settings.INSTALLED_APPS:
|
|
__import__(app, {}, {}, ['simple_translate'])
|
|
self.discovered = True
|
|
|
|
def get_info(self, model):
|
|
self.discover_translations()
|
|
if model in self.translated_models_dict:
|
|
return self.translated_models_dict[model]
|
|
elif model in self.translation_models_dict:
|
|
return self.translated_models_dict[ \
|
|
self.translation_models_dict[model]
|
|
]
|
|
|
|
def register_translation(self, translation_of_model, translated_model, \
|
|
language_field='language'):
|
|
|
|
assert issubclass(translation_of_model, models.Model) \
|
|
and issubclass(translated_model, models.Model)
|
|
|
|
if translation_of_model in self.translated_models_dict:
|
|
raise TranslationAllreadyRegistered, \
|
|
"[%s] a translation for this model is already registered" \
|
|
% translation_of_model.__name__
|
|
|
|
options = {}
|
|
options['translated_model'] = translated_model
|
|
|
|
opts = translation_of_model._meta
|
|
for rel in opts.get_all_related_objects():
|
|
if rel.model == translated_model:
|
|
options['translation_of_field'] = rel.field.name
|
|
options['translations_of_accessor'] = rel.get_accessor_name()
|
|
|
|
options['translation_join_filter'] = translated_model.__name__.lower()
|
|
options['language_field'] = language_field
|
|
|
|
self.translated_models_dict[translation_of_model] = TranslationOptions(options)
|
|
# keep track both ways
|
|
self.translation_models_dict[translated_model] = translation_of_model
|
|
|
|
def unregister_translation(self, translation_of_model):
|
|
info = self.get_info(translation_of_model)
|
|
del self.translation_models_dict[info.translated_model]
|
|
del self.translated_models_dict[translation_of_model]
|
|
|
|
def annotate_with_translations(self, list_or_instance):
|
|
|
|
self.discover_translations()
|
|
if not list_or_instance:
|
|
return list_or_instance
|
|
languages = [language_code for language_code, language_name in settings.LANGUAGES]
|
|
|
|
model = list_or_instance.__class__ if isinstance(
|
|
list_or_instance, models.Model
|
|
) else list_or_instance[0].__class__
|
|
info = self.get_info(model)
|
|
|
|
# Helper function that sorts translations according to settings.LANGUAGES
|
|
def language_key(translation):
|
|
l = getattr(translation, info.language_field)
|
|
try:
|
|
return languages.index(l)
|
|
except ValueError:
|
|
pass
|
|
|
|
if isinstance(list_or_instance, models.Model):
|
|
instance = list_or_instance
|
|
if self.is_registered_translation(model):
|
|
instance = getattr(list_or_instance, \
|
|
info.translation_of_field)
|
|
|
|
translations = list(getattr(instance, \
|
|
info.translations_of_accessor).filter(**{'%s__in' % info.language_field: languages}))
|
|
|
|
list_or_instance.translations = sorted(translations, key=language_key)
|
|
|
|
return list_or_instance
|
|
else:
|
|
result_list = list_or_instance
|
|
if not len(result_list):
|
|
return result_list
|
|
|
|
id_list = [r.pk for r in result_list]
|
|
pk_index_map = dict([(pk, index) for index, pk in enumerate(id_list)])
|
|
|
|
translations = info.translated_model.objects.filter(**{
|
|
info.translation_of_field + '__in': id_list,
|
|
info.language_field + '__in': languages,
|
|
})
|
|
|
|
new_result_list = []
|
|
for obj in translations:
|
|
index = pk_index_map[getattr(obj, info.translation_of_field + '_id')]
|
|
if not hasattr(result_list[index], 'translations'):
|
|
result_list[index].translations = []
|
|
result_list[index].translations.append(obj)
|
|
|
|
for result in result_list:
|
|
result.translations = sorted(result.translations, key=language_key)
|
|
|
|
return result_list
|
|
|
|
def is_registered_translation(self, model):
|
|
self.discover_translations()
|
|
if model in self.translation_models_dict:
|
|
return True
|
|
return False
|
|
|
|
def is_registered(self, model):
|
|
self.discover_translations()
|
|
if model in self.translated_models_dict:
|
|
return True
|
|
return False
|
|
|
|
translation_pool = TranslationPool()
|