# -*- coding: utf-8 -*- from django.conf import settings #default language # ZERO_LANGUAGE = 'ru' def fill_trans_fields(obj=None, data={}, lang=''): """ fills obj translated fields with data in data dictionary with one language uses 2 types of objects, example: 1) object new - obj = Country.objects.get(id=1) 2) object exist - obj =Country._meta.translations_model.objects.get(language_code = 'ru',master__id=1) list of fields in first object writes with _translated_field_names and return list of strings in second object writes with _meta.fields and return list of object. field name we must call obj[0].name """ #fills new object if '_translated_field_names' in dir(obj): list = obj._translated_field_names for field in list: n = data.get('%s_%s'%(field, lang)) if n != None: setattr(obj, str(field), n) #fill existing object else: list = obj._meta.fields for field in list: n = data.get('%s_%s'%(field.name,lang)) if n != None: setattr(obj, str(field.name), n) def fill_trans_fields_r(obj=None, data={}, lang=''): # filling and returnig an object fill_trans_fields(obj=obj, data=data, lang=lang) return obj def fill_trans_fields_all(Model, new_obj, data={}, id=None, zero_fields={}): """ Fills obj passing trough all languages id - used for checking existing object if id=None object doesn't exist and fills new_obj else fills existing Model object zero_fields used for generating dictionary which will be checking already populated fields """ for lid, (code, name) in enumerate(settings.LANGUAGES): #fills new object if not id: new_obj.translate(code) fill_trans_fields(new_obj, data,code) new_obj.save() #fills existing object # and fills zero_fields dictionary with data of zero language else: existing_obj = Model._meta.translations_model.objects.get(language_code = code,master__id=id) #access to translated fields if lid==0: list = existing_obj._meta.fields for field in list: zero_fields[field.name] = getattr(existing_obj, field.name)################### fill_trans_fields(existing_obj, data, code) existing_obj.save() def populate(obj=None, data={}, lang=ZERO_LANGUAGE, zero_fields={}): """ compare translated fields with empty values and values which was already populate(zero_language) and populate obj fields if it is true zero_fields fields block try for fields like id, Foreignkey... """ list = obj._meta.fields for field in list: #compare empty values if getattr(obj,field.name) == '': try: setattr(obj, field.name, data['%s_%s'%(field.name, ZERO_LANGUAGE)]) except: pass ##compare populated values if field.name in zero_fields: if getattr(obj,field.name) == zero_fields['%s'%field.name]: try: setattr(obj, field.name, data['%s_%s'%(field.name, ZERO_LANGUAGE)]) except: pass def populate_all(Model, data={}, id=None, zero_fields={}): for lid, (code, name) in enumerate(settings.LANGUAGES): if lid == 0: pass else: obj = Model._meta.translations_model.objects.get(language_code = code,master__id=id) populate(obj,data,code,zero_fields) obj.save() def fill_with_signal(model, obj, data): """ function useful when post_save signal what filling languages exist for this model """ all_langs = [code for code, lang in settings.LANGUAGES] # fields in translations model that doesn't need bad_fields = ['id', 'language_code', 'master_id'] # translated fields fields = [field.name for field in model.translations.related.editable_fields() if field.name not in bad_fields] # translate to first language(require) # ! first save method call signal that fill require language to all translated fields if not obj.id: # new object obj.translate(all_langs[0]) # go through all fields and set value for field in fields: value = data.get('%s_%s'%(field, all_langs[0]), '') if value: setattr(obj, field, value.strip()) obj.save() else: trans_obj = model._meta.translations_model.objects.get(language_code = all_langs[0], master__id=getattr(obj, 'id')) for field in fields: value = data.get('%s_%s'%(field, all_langs[0]), '') if value: setattr(trans_obj, field, value.strip()) trans_obj.save() # require translation. uses for substitution unfilled form fields require_transl = model._meta.translations_model.objects.get(language_code = all_langs[0],master__id=getattr(obj, 'id')) for code in all_langs[1:]: # fill translation objects # start from second language trans_obj = model._meta.translations_model.objects.get(language_code = code,master__id=getattr(obj, 'id')) for field in fields: val = data.get('%s_%s'%(field, code), '').strip() if val == '': # get value from require translation setattr(trans_obj, field, getattr(require_transl, field)) else: setattr(trans_obj, field, val) trans_obj.save() def get_translated_fields(obj, exclude_fields=[]): """ get translated fields """ # get hvad translation objects translation = obj.translations.all() # fields which present in database but don't need bad_fields = ['id', 'master', 'language_code'] # get translated fields without bad fields and exclude fields translated_fields = [i.name for i in translation[0]._meta.fields if i.name not in bad_fields and i.name not in exclude_fields] return translated_fields def get_all_fields(obj, exclude_fields=[]): """ Return all simple fields with translated hvad fields can exclude some fields """ # simple fields from django object fields = [i for i in obj._meta.get_all_field_names() if i not in exclude_fields] fields += get_translated_fields(obj) return fields def get_all_verbose_names(obj, fields): names = {} for field in fields: try: names[field] = obj._meta.get_field_by_name(field)[0].verbose_name except: translations = obj.translations.all() tr = translations[0] names[field] = tr._meta.get_field_by_name(field)[0].verbose_name return names