Completed
Push — master ( 0bffe1...d6203d )
by Diederik van der
11s
created

switch_language   A

Complexity

Total Complexity 7

Size/Duplication

Total Lines 53
Duplicated Lines 0 %
Metric Value
wmc 7
dl 0
loc 53
rs 10

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __exit__() 0 5 3
A __enter__() 0 10 3
A __init__() 0 5 1
1
"""
2
Context managers for temporary switching the language.
3
"""
4
from django.utils.translation import get_language, activate
5
6
__all__ = (
7
    'smart_override',
8
    'switch_language',
9
)
10
11
12
class smart_override(object):
13
    """
14
    This is a smarter version of :func:`translation.override <django.utils.translation.override>`
15
    which avoids switching the language if there is no change to make.
16
    This method can be used in place of :func:`translation.override <django.utils.translation.override>`:
17
18
    .. code-block:: python
19
20
        with smart_override(self.get_current_language()):
21
            return reverse('myobject-details', args=(self.id,))
22
23
    This makes sure that any URLs wrapped in :func:`~django.conf.urls.i18n.i18n_patterns`
24
    will receive the correct language code prefix.
25
    When the URL also contains translated fields (e.g. a slug), use :class:`switch_language` instead.
26
    """
27
28
    def __init__(self, language_code):
29
        self.language = language_code
30
        self.old_language = get_language()
31
32
    def __enter__(self):
33
        # Switch both Django language and object language.
34
        # For example, when using `object.get_absolute_url()`,
35
        # a i18n_url() may apply, and a translated database field.
36
        #
37
        # Be smarter then translation.override(), also avoid unneeded switches.
38
        if self.language != self.old_language:
39
            activate(self.language)
40
41
    def __exit__(self, exc_type, exc_value, traceback):
42
        if self.language != self.old_language:
43
            activate(self.old_language)
44
45
46
class switch_language(object):
47
    """
48
    A contextmanager to switch the translation of an object.
49
50
    It changes both the translation language, and object language temporary.
51
52
    This context manager can be used to switch the Django translations
53
    to the current object language.
54
    It can also be used to render objects in a different language:
55
56
    .. code-block:: python
57
58
        with switch_language(object, 'nl'):
59
            print object.title
60
61
    This is particularly useful for the :func:`~django.db.models.get_absolute_url` function.
62
    By using this context manager, the object language will be identical to the current Django language.
63
64
    .. code-block:: python
65
66
        def get_absolute_url(self):
67
            with switch_language(self):
68
                return reverse('myobject-details', args=(self.slug,))
69
70
    .. note::
71
72
       When the object is shared between threads, this is not thread-safe.
73
       Use :func:`~parler.models.TranslatableModel.safe_translation_getter` instead
74
       to read the specific field.
75
    """
76
77
    def __init__(self, object, language_code=None):
78
        self.object = object
79
        self.language = language_code or object.get_current_language()
80
        self.old_language = get_language()
81
        self.old_parler_language = object.get_current_language()
82
83
    def __enter__(self):
84
        # Switch both Django language and object language.
85
        # For example, when using `object.get_absolute_url()`,
86
        # a i18n_url() may apply, and a translated database field.
87
        #
88
        # Be smarter then translation.override(), also avoid unneeded switches.
89
        if self.language != self.old_language:
90
            activate(self.language)
91
        if self.language != self.old_parler_language:
92
            self.object.set_current_language(self.language)
93
94
    def __exit__(self, exc_type, exc_value, traceback):
95
        if self.language != self.old_language:
96
            activate(self.old_language)
97
        if self.language != self.old_parler_language:
98
            self.object.set_current_language(self.old_parler_language)
99