0.5: Django 3.2 support, drop Django<1.11, Python<3.6, remove some compatibility...
[fnpdjango.git] / fnpdjango / utils / models / translation.py
index dd1d515..de4fe92 100644 (file)
@@ -4,15 +4,23 @@ Utilities for creating multilingual fields in your apps.
 
 from copy import copy
 from django.conf import settings
+from django.db import models
 from django.utils.translation import get_language, string_concat
 
 
+def localize_field(name, lang=None):
+    if lang is None:
+        lang = get_language()
+    if lang not in (x[0] for x in settings.LANGUAGES):
+        lang = settings.LANGUAGE_CODE
+    return "%s_%s" % (name, lang)
+
 def field_getter(name):
     @property
     def getter(self):
-        val = getattr(self, "%s_%s" % (name, get_language()), None)
+        val = getattr(self, localize_field(name), None)
         if not val:
-            val = getattr(self, "%s_%s" % (name, settings.LANGUAGE_CODE))
+            val = getattr(self, localize_field(name, settings.LANGUAGE_CODE))
         return val
     return getter
 
@@ -26,7 +34,7 @@ def add_translatable(model, fields, languages=None):
             new_field = copy(field)
             if field.verbose_name:
                 new_field.verbose_name = string_concat(field.verbose_name, ' [%s]' % lang_code)
-            new_field.contribute_to_class(model, "%s_%s" % (name, lang_code))
+            new_field.contribute_to_class(model, localize_field(name, lang_code))
         setattr(model, name, field_getter(name))
         # add setter?
 
@@ -38,12 +46,12 @@ def add_translatable_index(index_class, fields, languages=None):
     for name, field in fields.items():
         for lang_code, lang_name in languages:
             new_field = copy(field)
-            fname = "%s_%s" % (name, lang_code)
+            fname = localize_field(name, lang_code)
             new_field.index_fieldname = new_field.index_fieldname \
-                and "%s_%s" % (new_field.index_fieldname, lang_code) \
+                and localize_field(new_field.index_fieldname, lang_code) \
                 or fname
             new_field.model_attr = new_field.model_attr \
-                and "%s_%s" % (new_field.model_attr, lang_code) \
+                and localize_field(new_field.model_attr, lang_code) \
                 or fname
             setattr(index_class, fname, new_field)
             index_class.fields[fname] = new_field
@@ -51,7 +59,14 @@ def add_translatable_index(index_class, fields, languages=None):
 
 def translated_fields(field_names, languages=settings.LANGUAGES):
     """Generate a tuple of field names in translated versions."""
-    return tuple("%s_%s" % (field_name, lang_code)
+    return tuple(localize_field(field_name, lang_code)
                 for field_name in field_names
                 for lang_code, lang_name in languages
                 )
+
+def tQ(**kwargs):
+    """ Creates a query (Q) with lookups on translated fields. """
+    trans_kwargs = {}
+    for k, v in kwargs.items():
+        trans_kwargs[localize_field(k)] = v
+    return models.Q(**trans_kwargs)