add tQ for filtering on translated fields
[fnpdjango.git] / fnpdjango / utils / models / translation.py
1 """
2 Utilities for creating multilingual fields in your apps.
3 """
4
5 from copy import copy
6 from django.conf import settings
7 from django.db import models
8 from django.utils.translation import get_language, string_concat
9
10
11 def localize_field(name, lang=None):
12     if lang is None:
13         lang = get_language()
14     if lang not in (x[0] for x in settings.LANGUAGES):
15         lang = settings.LANGUAGE_CODE
16     return "%s_%s" % (name, lang)
17
18 def field_getter(name):
19     @property
20     def getter(self):
21         val = getattr(self, localize_field(name), None)
22         if not val:
23             val = getattr(self, localize_field(name, settings.LANGUAGE_CODE))
24         return val
25     return getter
26
27
28 def add_translatable(model, fields, languages=None):
29     """Adds some translatable fields to a model, and a getter."""
30     if languages is None:
31         languages = settings.LANGUAGES
32     for name, field in fields.items():
33         for lang_code, lang_name in languages:
34             new_field = copy(field)
35             if field.verbose_name:
36                 new_field.verbose_name = string_concat(field.verbose_name, ' [%s]' % lang_code)
37             new_field.contribute_to_class(model, localize_field(name, lang_code))
38         setattr(model, name, field_getter(name))
39         # add setter?
40
41
42 def add_translatable_index(index_class, fields, languages=None):
43     """Adds some translatable fields to a search index."""
44     if languages is None:
45         languages = settings.LANGUAGES
46     for name, field in fields.items():
47         for lang_code, lang_name in languages:
48             new_field = copy(field)
49             fname = localize_field(name, lang_code)
50             new_field.index_fieldname = new_field.index_fieldname \
51                 and localize_field(new_field.index_fieldname, lang_code) \
52                 or fname
53             new_field.model_attr = new_field.model_attr \
54                 and localize_field(new_field.model_attr, lang_code) \
55                 or fname
56             setattr(index_class, fname, new_field)
57             index_class.fields[fname] = new_field
58
59
60 def translated_fields(field_names, languages=settings.LANGUAGES):
61     """Generate a tuple of field names in translated versions."""
62     return tuple(localize_field(field_name, lang_code)
63                 for field_name in field_names
64                 for lang_code, lang_name in languages
65                 )
66
67 def tQ(**kwargs):
68     """ Creates a query (Q) with lookups on translated fields. """
69     trans_kwargs = {}
70     for k, v in kwargs.items():
71         trans_kwargs[localize_field(k)] = v
72     return models.Q(**trans_kwargs)