simple-translation/simple_translation/translation_pool.py

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()