Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tree: 756e8ce11d
Fetching contributors…

Cannot retrieve contributors at this time

file 154 lines (130 sloc) 6.356 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
import re

from django.core.urlresolvers import RegexURLResolver, RegexURLPattern
from django.utils.datastructures import MultiValueDict
from django.utils.encoding import force_unicode
from django.utils.regex_helper import normalize
from django.utils.translation import get_language

from i18nurls.monkeypatch import monkeypatch_class


class I18NRegexURLPattern(RegexURLPattern):
    # Monkeypatch for the origiginal RegexURLPattern class.

    __metaclass__ = monkeypatch_class

    def __init__(self, regex, callback, default_args=None, name=None):
        # This is almost the same as django.core.urlresolvers.RegexURLPattern
        # except that we are not going to set self.regex.
        if callable(callback):
            self._callback = callback
        else:
            self._callback = None
            self._callback_str = callback
        self.default_args = default_args or {}
        self.name = name

        # Some new variables.
        self._i18n_regex = regex
        self._i18n_regex_dict = {}

    @property
    def regex(self):
        language_code = get_language()

        if language_code not in self._i18n_regex_dict:
            if isinstance(self._i18n_regex, basestring):
                compiled_regex = re.compile(self._i18n_regex, re.UNICODE)
            else:
                regex = force_unicode(self._i18n_regex)
                compiled_regex = re.compile(regex, re.UNICODE)
            self._i18n_regex_dict[language_code] = compiled_regex
        return self._i18n_regex_dict[language_code]


class I18NRegexURLResolver(RegexURLResolver):
    # Monkeypatch for the origiginal RegexURLResolver class.

    __metaclass__ = monkeypatch_class

    def __init__(self, regex, urlconf_name, default_kwargs=None, app_name=None, namespace=None):
        # This is almost the same as django.core.urlresolvers.RegexURLResolver
        # except that we are not going to set self.regex and we are going to
        # set some more variables for caching.
        self.urlconf_name = urlconf_name
        if not isinstance(urlconf_name, basestring):
            self._urlconf_module = self.urlconf_name
        self.callback = None
        self.default_kwargs = default_kwargs or {}
        self.namespace = namespace
        self.app_name = app_name

        # Some new variables
        self._i18n_regex = regex
        self._i18n_regex_dict = {}
        self._i18n_reverse_dict = {}
        self._i18n_namespace_dict = {}
        self._i18n_app_dict = {}

    @property
    def regex(self):
        language_code = get_language()

        if language_code not in self._i18n_regex_dict:
            if isinstance(self._i18n_regex, basestring):
                compiled_regex = re.compile(self._i18n_regex, re.UNICODE)
            else:
                regex = force_unicode(self._i18n_regex)
                compiled_regex = re.compile(regex, re.UNICODE)
            self._i18n_regex_dict[language_code] = compiled_regex
        return self._i18n_regex_dict[language_code]

    def _populate(self):
        # Almost the same as the original `_populate` function, except the last
        # 4 lines of code.
        lookups = MultiValueDict()
        namespaces = {}
        apps = {}
        language_code = get_language()
        for pattern in reversed(self.url_patterns):
            p_pattern = pattern.regex.pattern
            if p_pattern.startswith('^'):
                p_pattern = p_pattern[1:]
            if isinstance(pattern, RegexURLResolver):
                if pattern.namespace:
                    namespaces[pattern.namespace] = (p_pattern, pattern)
                    if pattern.app_name:
                        apps.setdefault(pattern.app_name, []).append(pattern.namespace)
                else:
                    parent = normalize(pattern.regex.pattern)
                    for name in pattern.reverse_dict:
                        for matches, pat in pattern.reverse_dict.getlist(name):
                            new_matches = []
                            for piece, p_args in parent:
                                new_matches.extend([(piece + suffix, p_args + args) for (suffix, args) in matches])
                            lookups.appendlist(name, (new_matches, p_pattern + pat))
                    for namespace, (prefix, sub_pattern) in pattern.namespace_dict.items():
                        namespaces[namespace] = (p_pattern + prefix, sub_pattern)
                    for app_name, namespace_list in pattern.app_dict.items():
                        apps.setdefault(app_name, []).extend(namespace_list)
            else:
                bits = normalize(p_pattern)
                lookups.appendlist(pattern.callback, (bits, p_pattern))
                if pattern.name is not None:
                    lookups.appendlist(pattern.name, (bits, p_pattern))

        self._i18n_reverse_dict[language_code] = lookups
        self._i18n_namespace_dict[language_code] = namespaces
        self._i18n_app_dict[language_code] = apps

    def _get_reverse_dict(self):
        language_code = get_language()
        if language_code not in self._i18n_reverse_dict:
            self._populate()
        return self._i18n_reverse_dict[language_code]
    reverse_dict = property(_get_reverse_dict)

    def _get_namespace_dict(self):
        language_code = get_language()
        if language_code not in self._i18n_namespace_dict:
            self._populate()
        return self._i18n_namespace_dict[language_code]
    namespace_dict = property(_get_namespace_dict)

    def _get_app_dict(self):
        language_code = get_language()
        if language_code not in self._i18n_app_dict:
            self._populate()
        return self._i18n_app_dict[language_code]
    app_dict = property(_get_app_dict)


class LocaleRegexURLResolver(RegexURLResolver):
    def __init__(self, urlconf_name, default_kwargs=None, app_name=None, namespace=None):
        super(LocaleRegexURLResolver, self).__init__(
            None, urlconf_name, default_kwargs, app_name, namespace)

    @property
    def regex(self):
        language_code = get_language()
        if language_code not in self._i18n_regex_dict:
            regex_compiled = re.compile('^%s/' % language_code, re.UNICODE)
            self._i18n_regex_dict[language_code] = regex_compiled
        return self._i18n_regex_dict[language_code]
Something went wrong with that request. Please try again.