Code

Ticket #20125: locale.py

File locale.py, 4.0 KB (added by lwarx, 10 months ago)

rough concept of how locale selector might look like

Line 
1from __future__ import unicode_literals
2import locale
3import os
4
5from django.utils.translation.trans_real import (get_supported_language_variant,
6                                                 parse_accept_lang_header,
7                                                 get_language_from_path,
8                                                 check_for_language,
9                                                 all_locale_paths,
10                                                 to_locale,
11                                                 _accepted)
12
13# TODO: locale mapper (map locale in url to one of supported locales)
14#       this may be convenient to design localized url first (for SEO purposes)
15#       and add more locales later
16
17def LocaleSelector(object):
18    def __init__(self, check_path=False):
19        from django.conf import settings
20        self.supported = dict(settings.LANGUAGES)
21        self.cookie_name = settings.LANGUAGE_COOKIE_NAME
22        self.default_language_code = settings.LANGUAGE_CODE
23        self.check_path = check_path
24        self.selectors = [self.get_language_from_path,
25                          self.get_language_from_session,
26                          self.get_language_from_cookie,
27                          self.get_language_from_header,
28                          self.get_fallback_language] # last one should always return a result
29
30    def get_language_from_path(request):
31        if self.check_path:
32            lang_code = get_language_from_path(request.path_info, self.supported)
33            if lang_code is not None:
34                return lang_code
35
36    def get_language_from_session(request):
37        if hasattr(request, 'session'):
38            lang_code = request.session.get('django_language', None)
39            if lang_code in self.supported and lang_code is not None and check_for_language(lang_code):
40                return lang_code
41
42    def get_language_from_cookie(request):
43        lang_code = request.COOKIES.get(self.cookie_name)
44        try:
45            return get_supported_language_variant(lang_code, self.supported)
46        except LookupError:
47            pass
48
49    def get_language_from_header(request):
50        global _accepted
51
52        accept = request.META.get('HTTP_ACCEPT_LANGUAGE', '')
53        for accept_lang, unused in parse_accept_lang_header(accept):
54            if accept_lang == '*':
55                break
56
57            # We have a very restricted form for our language files (no encoding
58            # specifier, since they all must be UTF-8 and only one possible
59            # language each time. So we avoid the overhead of gettext.find() and
60            # work out the MO file manually.
61
62            # 'normalized' is the root name of the locale in POSIX format (which is
63            # the format used for the directories holding the MO files).
64            normalized = locale.locale_alias.get(to_locale(accept_lang, True))
65            if not normalized:
66                continue
67            # Remove the default encoding from locale_alias.
68            normalized = normalized.split('.')[0]
69
70            if normalized in _accepted:
71                # We've seen this locale before and have an MO file for it, so no
72                # need to check again.
73                return _accepted[normalized]
74
75            for lang, dirname in ((accept_lang, normalized),
76                    (accept_lang.split('-')[0], normalized.split('_')[0])):
77                if lang.lower() not in self.supported:
78                    continue
79                for path in all_locale_paths():
80                    if os.path.exists(os.path.join(path, dirname, 'LC_MESSAGES', 'django.mo')):
81                        _accepted[normalized] = lang
82                        return lang
83
84    def get_fallback_language(_request):
85        try:
86            return get_supported_language_variant(self.default_language_code, self.supported)
87        except LookupError:
88            return self.default_language_code
89
90    def select(request):
91        for selector in self.selectors:
92            lang_code = selector(request)
93            if lang_code is not None:
94                return lang_code