Ticket #11585: i18nurls.diff
File i18nurls.diff, 34.3 KB (added by , 13 years ago) |
---|
-
AUTHORS
94 94 Sean Brant 95 95 Andrew Brehaut <http://brehaut.net/blog> 96 96 David Brenneman <http://davidbrenneman.com> 97 Orne Brocaar <http://brocaar.com/> 97 98 brut.alll@gmail.com 98 99 bthomas 99 100 btoll@bestweb.net -
docs/topics/i18n/internationalization.txt
769 769 cases where you really need it (for example, in conjunction with ``ngettext`` 770 770 to produce proper pluralizations). 771 771 772 .. _url-internationalization: 773 774 Specifying translation strings: In URL patterns 775 =============================================== 776 777 .. versionadded:: 1.4 778 779 Django provides two meganism to internationalize URL patterns: 780 781 * Adding the language-prefix to the root of the URL patterns to make it possible 782 for the ``LocaleMiddleware`` to detect the language to activate from the requested 783 URL. 784 785 * Making URL patterns translatable by using the ``ugettext_lazy()`` function. 786 787 788 Language prefix in URL patterns 789 ------------------------------- 790 791 By using the ``i18n_patterns()`` function instead of the ``patterns()`` function, 792 Django will add the current active language automatically to all the URL patterns 793 defined within this function. Example URL patterns:: 794 795 from django.conf.urls.defaults import patterns, i18n_patterns, include, url 796 797 urlpatterns = patterns('' 798 url(r'^sitemap\.xml$', 'sitemap.view', name='sitemap_xml'), 799 ) 800 801 news_patterns = patterns('' 802 url(r'^$', 'news.views.index', name='index'), 803 url(r'^category/(?P<slug>[\w-]+)/$', 'news.views.category', name='category'), 804 url(r'^(?P<slug>[\w-]+)/$', 'news.views.details', name='detail'), 805 ) 806 807 urlpatterns += i18n_patterns('', 808 url(r'^about/$', 'about.view', name='about'), 809 url(r'^news/$', include(news_patterns, namespace='news')), 810 ) 811 812 813 After defining these URL patterns, Django will automatically add the language-prefix 814 to the URL patterns within the ``i18n_patterns`` function. Example:: 815 816 from django.core.urlresolvers import reverse 817 from django.utils.translation import activate 818 819 >>> activate('en') 820 >>> reverse('sitemap_xml') 821 '/sitemap.xml' 822 >>> reverse('news:index') 823 '/en/news/' 824 825 >>> activate('nl') 826 >>> reverse('news:detail', kwargs={'slug': 'news-slug'}) 827 '/nl/news/news-slug/' 828 829 .. warning:: 830 831 * The ``i18n_patterns()`` function is only allowed at rootlevel of the URL patterns. 832 When including a pattern which contains one or more ``i18n_patterns()`` patterns, 833 an exception will be thrown. 834 835 * Make sure the automatically added language-prefix does not cause collision 836 with other non-prefixed URL patterns. 837 838 839 Translating URL patterns 840 ------------------------ 841 842 URL patterns can be marked translatable by using the ``ugettext_lazy()`` function. 843 Example:: 844 845 from django.conf.urls.defaults import patterns, i18n_patterns, include, url 846 from django.utils.translation import ugettext_lazy 847 848 urlpatterns = patterns('' 849 url(r'^sitemap\.xml$', 'sitemap.view', name='sitemap_xml'), 850 ) 851 852 news_patterns = patterns('' 853 url(r'^$', 'news.views.index', name='index'), 854 url(_(r'^category/(?P<slug>[\w-]+)/$'), 'news.views.category', name='category'), 855 url(r'^(?P<slug>[\w-]+)/$', 'news.views.details', name='detail'), 856 ) 857 858 urlpatterns += i18n_patterns('', 859 url(_(r'^about/$'), 'about.view', name='about'), 860 url(_(r'^news/$'), include(news_patterns, namespace='news')), 861 ) 862 863 864 After creating the translations (see :doc:`localization` for more information), 865 the ``reverse()`` function will return the URL in the active language. Example:: 866 867 from django.core.urlresolvers import reverse 868 from django.utils.translation import activate 869 870 >>> activate('en') 871 >>> reverse('news:category', kwargs={'slug': 'recent'}) 872 '/en/news/news-slug/' 873 874 >>> activate('nl') 875 >>> reverse('news:category', kwargs={'slug': 'recent'}) 876 '/nl/nieuws/categorie/recent/' 877 878 .. warning:: 879 880 Unless you are using your own middleware to detect the language to activate 881 from the requested URL, always use translatable URL patterns together with 882 the ``i18n_patterns()`` function. Django is not able to resolve a URL when 883 the correct language is not activated. 884 885 772 886 .. _set_language-redirect-view: 773 887 774 888 The ``set_language`` redirect view -
docs/topics/i18n/deployment.txt
59 59 60 60 * Make sure it's one of the first middlewares installed. 61 61 * It should come after ``SessionMiddleware``, because ``LocaleMiddleware`` 62 makes use of session data. 62 makes use of session data. As well it should come before ``CommonMiddleware`` 63 because ``CommonMiddleware`` depends on a activated language when it needs 64 to resolve the requested URL. 63 65 * If you use ``CacheMiddleware``, put ``LocaleMiddleware`` after it. 64 66 65 67 For example, your :setting:`MIDDLEWARE_CLASSES` might look like this:: … … 76 78 ``LocaleMiddleware`` tries to determine the user's language preference by 77 79 following this algorithm: 78 80 79 * First, it looks for a ``django_language`` key in the current user's 81 * First, it looks for the language-prefix in the requested URL. 82 This is only performed when you are using the ``i18n_patterns`` function. 83 See :ref:`url-internationalization` for more information about the 84 language-prefix and how to internationalize URL patterns. 85 86 * Failing that, it looks for a ``django_language`` key in the current user's 80 87 session. 81 88 82 89 * Failing that, it looks for a cookie. -
django/conf/urls/defaults.py
1 from django.core.urlresolvers import RegexURLPattern, RegexURLResolver 1 from django.core.urlresolvers import (RegexURLPattern, RegexURLResolver, 2 LanguagePrefixedRegexURLResolver, get_resolver) 2 3 from django.core.exceptions import ImproperlyConfigured 4 from django.utils.importlib import import_module 3 5 6 4 7 __all__ = ['handler404', 'handler500', 'include', 'patterns', 'url'] 5 8 6 9 handler404 = 'django.views.defaults.page_not_found' … … 15 18 else: 16 19 # No namespace hint - use manually provided namespace 17 20 urlconf_module = arg 21 22 # Test if the LanguagePrefixedRegexURLResolver is used within the include, 23 # this should throw an error since this is not allowed! 24 if isinstance(urlconf_module, basestring): 25 urlconf_module = import_module(urlconf_module) 26 patterns = getattr(urlconf_module, 'urlpatterns', urlconf_module) 27 28 # Make sure we can iterate through the patterns (without this, some testcases 29 # will break). 30 if isinstance(patterns, (list, tuple)): 31 for url_pattern in patterns: 32 if isinstance(url_pattern, LanguagePrefixedRegexURLResolver): 33 raise ImproperlyConfigured('Using i18n_patterns inside an include is not allowed') 34 18 35 return (urlconf_module, app_name, namespace) 19 36 20 37 def patterns(prefix, *args): … … 27 44 pattern_list.append(t) 28 45 return pattern_list 29 46 47 def i18n_patterns(prefix, *args): 48 """ 49 This will add the language-code prefix to every URLPattern within this 50 function. It is only allowed to use this at rootlevel of your URLConf. 51 """ 52 pattern_list = patterns(prefix, *args) 53 return [LanguagePrefixedRegexURLResolver(pattern_list)] 54 30 55 def url(regex, view, kwargs=None, name=None, prefix=''): 31 56 if isinstance(view, (list,tuple)): 32 57 # For include(...) processing. … … 39 64 if prefix: 40 65 view = prefix + '.' + view 41 66 return RegexURLPattern(regex, view, kwargs, name) 42 -
django/core/urlresolvers.py
18 18 from django.utils.functional import memoize, lazy 19 19 from django.utils.importlib import import_module 20 20 from django.utils.regex_helper import normalize 21 from django.utils.translation import get_language 21 22 23 22 24 _resolver_cache = {} # Maps URLconf modules to RegexURLResolver instances. 23 25 _callable_cache = {} # Maps view and url pattern names to their view functions. 24 26 … … 117 119 118 120 class RegexURLPattern(object): 119 121 def __init__(self, regex, callback, default_args=None, name=None): 120 # regex is a string representing a regular expression. 122 # regex is eighter a string representing a regular expression, or a 123 # translatable string (using ugettext_lazy) representing a regular 124 # expression. 121 125 # callback is either a string like 'foo.views.news.stories.story_detail' 122 126 # which represents the path to a module and a view function name, or a 123 127 # callable object (view). 124 self.regex = re.compile(regex, re.UNICODE) 128 self._regex = regex 129 self._i18n_regex_dict = {} 125 130 if callable(callback): 126 131 self._callback = callback 127 132 else: … … 129 134 self._callback_str = callback 130 135 self.default_args = default_args or {} 131 136 self.name = name 137 138 @property 139 def regex(self): 140 """ 141 Returns a compiled regular expression, depending upon the activated 142 language-code. 143 """ 144 language_code = get_language() 145 146 if language_code not in self._i18n_regex_dict: 147 if isinstance(self._regex, basestring): 148 compiled_regex = re.compile(self._regex, re.UNICODE) 149 else: 150 regex = unicode(self._regex) 151 compiled_regex = re.compile(regex, re.UNICODE) 152 self._i18n_regex_dict[language_code] = compiled_regex 153 154 return self._i18n_regex_dict[language_code] 132 155 133 156 def __repr__(self): 134 157 return smart_str(u'<%s %s %s>' % (self.__class__.__name__, self.name, self.regex.pattern)) … … 175 198 def __init__(self, regex, urlconf_name, default_kwargs=None, app_name=None, namespace=None): 176 199 # regex is a string representing a regular expression. 177 200 # urlconf_name is a string representing the module containing URLconfs. 178 self.regex = re.compile(regex, re.UNICODE) 201 self._regex = regex 202 self._i18n_regex_dict = {} 179 203 self.urlconf_name = urlconf_name 180 204 if not isinstance(urlconf_name, basestring): 181 205 self._urlconf_module = self.urlconf_name … … 183 207 self.default_kwargs = default_kwargs or {} 184 208 self.namespace = namespace 185 209 self.app_name = app_name 186 self._ reverse_dict = None187 self._ namespace_dict = None188 self._ app_dict = None210 self._i18n_reverse_dict = {} 211 self._i18n_namespace_dict = {} 212 self._i18n_app_dict = {} 189 213 214 @property 215 def regex(self): 216 """ 217 Returns a compiled regular expression, depending upon the activated 218 language-code. 219 """ 220 language_code = get_language() 221 222 if language_code not in self._i18n_regex_dict: 223 if isinstance(self._regex, basestring): 224 compiled_regex = re.compile(self._regex, re.UNICODE) 225 else: 226 regex = unicode(self._regex) 227 compiled_regex = re.compile(regex, re.UNICODE) 228 self._i18n_regex_dict[language_code] = compiled_regex 229 230 return self._i18n_regex_dict[language_code] 231 190 232 def __repr__(self): 191 233 return smart_str(u'<%s %s (%s:%s) %s>' % (self.__class__.__name__, self.urlconf_name, self.app_name, self.namespace, self.regex.pattern)) 192 234 … … 220 262 lookups.appendlist(pattern.callback, (bits, p_pattern, pattern.default_args)) 221 263 if pattern.name is not None: 222 264 lookups.appendlist(pattern.name, (bits, p_pattern, pattern.default_args)) 223 self._reverse_dict = lookups 224 self._namespace_dict = namespaces 225 self._app_dict = apps 265 266 language_code = get_language() 267 self._i18n_reverse_dict[language_code] = lookups 268 self._i18n_namespace_dict[language_code] = namespaces 269 self._i18n_app_dict[language_code] = apps 226 270 227 def _get_reverse_dict(self): 228 if self._reverse_dict is None: 271 @property 272 def reverse_dict(self): 273 language_code = get_language() 274 if language_code not in self._i18n_reverse_dict: 229 275 self._populate() 230 return self._reverse_dict 231 reverse_dict = property(_get_reverse_dict) 276 return self._i18n_reverse_dict[language_code] 232 277 233 def _get_namespace_dict(self): 234 if self._namespace_dict is None: 278 @property 279 def namespace_dict(self): 280 language_code = get_language() 281 if language_code not in self._i18n_namespace_dict: 235 282 self._populate() 236 return self._namespace_dict 237 namespace_dict = property(_get_namespace_dict) 283 return self._i18n_namespace_dict[language_code] 238 284 239 def _get_app_dict(self): 240 if self._app_dict is None: 285 @property 286 def app_dict(self): 287 language_code = get_language() 288 if language_code not in self._i18n_app_dict: 241 289 self._populate() 242 return self._app_dict 243 app_dict = property(_get_app_dict) 290 return self._i18n_app_dict[language_code] 244 291 245 292 def resolve(self, path): 246 293 tried = [] … … 343 390 raise NoReverseMatch("Reverse for '%s' with arguments '%s' and keyword " 344 391 "arguments '%s' not found." % (lookup_view_s, args, kwargs)) 345 392 393 class LanguagePrefixedRegexURLResolver(RegexURLResolver): 394 """ 395 The ``__init__`` function does not take an regex argument. Instead, we are 396 overriding the ``regex`` function to always return the active language-code 397 as regex. 398 """ 399 400 def __init__(self, urlconf_name, default_kwargs=None, app_name=None, namespace=None): 401 super(LanguagePrefixedRegexURLResolver, self).__init__(None, urlconf_name, 402 default_kwargs, app_name, namespace) 403 404 @property 405 def regex(self): 406 language_code = get_language() 407 if language_code not in self._i18n_regex_dict: 408 regex_compiled = re.compile('^%s/' % language_code, re.UNICODE) 409 self._i18n_regex_dict[language_code] = regex_compiled 410 return self._i18n_regex_dict[language_code] 411 346 412 def resolve(path, urlconf=None): 347 413 if urlconf is None: 348 414 urlconf = get_urlconf() -
django/middleware/locale.py
1 1 "this is the locale selecting middleware that will look at accept headers" 2 2 3 import re 4 5 from django.conf import settings 6 from django.core import urlresolvers 7 from django.http import HttpResponseRedirect 3 8 from django.utils.cache import patch_vary_headers 4 9 from django.utils import translation 5 10 11 12 language_code_prefix_regex = re.compile(r'^/([\w-]+)/') 13 6 14 class LocaleMiddleware(object): 7 15 """ 8 16 This is a very simple middleware that parses a request … … 13 21 """ 14 22 15 23 def process_request(self, request): 16 language = translation.get_language_from_request(request) 24 language = _language_code_from_path(request.path_info) 25 26 if not language: 27 language = translation.get_language_from_request(request) 28 17 29 translation.activate(language) 18 30 request.LANGUAGE_CODE = translation.get_language() 19 31 20 32 def process_response(self, request, response): 33 language = translation.get_language() 34 translation.deactivate() 35 36 if (response.status_code == 404 and not _language_code_from_path(request.path_info) 37 and _is_language_prefix_patterns_used()): 38 prefixed_request_path = '/%s%s' % (language, request.get_full_path()) 39 return HttpResponseRedirect(prefixed_request_path) 40 21 41 patch_vary_headers(response, ('Accept-Language',)) 22 42 if 'Content-Language' not in response: 23 response['Content-Language'] = translation.get_language() 24 translation.deactivate() 43 response['Content-Language'] = language 25 44 return response 45 46 def _language_code_from_path(path): 47 """ 48 Returns the language-code if there is a valid language-code found in the 49 `path`. 50 """ 51 regex_match = language_code_prefix_regex.match(path) 52 if regex_match: 53 if regex_match.group(1) in dict(settings.LANGUAGES): 54 return regex_match.group(1) 55 return None 56 57 def _is_language_prefix_patterns_used(): 58 """ 59 Returns `True` if the `LanguagePrefixedRegexURLResolver` is used at rootlevel 60 of the urlpatterns, else it returns `False`. 61 """ 62 resolver = urlresolvers.get_resolver(None) 63 for url_pattern in resolver.url_patterns: 64 if isinstance(url_pattern, urlresolvers.LanguagePrefixedRegexURLResolver): 65 return True 66 return False -
tests/regressiontests/i18n/wrong_urls_namespace.py
1 from django.conf.urls.defaults import i18n_patterns, include, url 2 from django.utils.translation import ugettext_lazy as _ 3 from django.views.generic import TemplateView 4 5 6 view = TemplateView.as_view(template_name='dummy.html') 7 8 urlpatterns = i18n_patterns('', 9 url(_(r'^register/$'), view, name='register'), 10 ) -
tests/regressiontests/i18n/urls_namespace.py
1 from django.conf.urls.defaults import patterns, include, url 2 from django.utils.translation import ugettext_lazy as _ 3 from django.views.generic import TemplateView 4 5 6 view = TemplateView.as_view(template_name='dummy.html') 7 8 urlpatterns = patterns('', 9 url(_(r'^register/$'), view, name='register'), 10 ) -
tests/regressiontests/i18n/wrong_urls.py
1 from django.conf.urls.defaults import patterns, i18n_patterns, include, url 2 from django.utils.translation import ugettext_lazy as _ 3 4 5 urlpatterns = i18n_patterns('', 6 url(_(r'^account/'), include('regressiontests.i18n.wrong_urls_namespace', namespace='account')), 7 ) -
tests/regressiontests/i18n/tests.py
8 8 from threading import local 9 9 10 10 from django.conf import settings 11 from django.core.exceptions import ImproperlyConfigured 12 from django.core.urlresolvers import reverse, get_resolver, clear_url_caches 11 13 from django.template import Template, Context 12 14 from django.test import TestCase 15 from django.test.utils import override_settings 13 16 from django.utils.formats import (get_format, date_format, time_format, 14 17 localize, localize_input, iter_format_modules, get_format_modules) 15 18 from django.utils.importlib import import_module … … 828 831 with translation.override('nl'): 829 832 self.assertEqual(t.render(Context({})), 'Nee') 830 833 834 835 class URLTestCaseBase(TestCase): 836 """ 837 TestCase base-class for the URL tests. 838 """ 839 def setUp(self): 840 # Make sure the cache is empty before we are doing our tests. 841 clear_url_caches() 842 843 def tearDown(self): 844 # Make sure we will leave an empty cache for other testcases. 845 clear_url_caches() 846 847 848 URLTestCaseBase = override_settings( 849 ROOT_URLCONF='regressiontests.i18n.urls', 850 LOCALE_PATHS=(os.path.join(os.path.dirname(__file__), 'test_locale'), ), 851 TEMPLATE_DIRS=(os.path.join(os.path.dirname(__file__), 'test_templates'), ), 852 LANGUAGE_CODE='en', 853 LANGUAGES=( 854 ('nl', 'Dutch'), 855 ('en', 'English'), 856 ('pt-br', 'Brazilian Portuguese'), 857 ), 858 MIDDLEWARE_CLASSES=( 859 'django.middleware.locale.LocaleMiddleware', 860 'django.middleware.common.CommonMiddleware', 861 ), 862 )(URLTestCaseBase) 863 864 865 class URLPrefixTests(URLTestCaseBase): 866 """ 867 Tests if the `i18n_patterns` is adding the prefix correctly. 868 """ 869 def test_not_prefixed(self): 870 with translation.override('en'): 871 self.assertEqual(reverse('not-prefixed'), '/not-prefixed/') 872 with translation.override('nl'): 873 self.assertEqual(reverse('not-prefixed'), '/not-prefixed/') 874 875 def test_prefixed(self): 876 with translation.override('en'): 877 self.assertEqual(reverse('prefixed'), '/en/prefixed/') 878 with translation.override('nl'): 879 self.assertEqual(reverse('prefixed'), '/nl/prefixed/') 880 881 @override_settings(ROOT_URLCONF='regressiontests.i18n.wrong_urls') 882 def test_invalid_prefix_use(self): 883 self.assertRaises(ImproperlyConfigured, lambda: reverse('account:register')) 884 885 886 class URLTranslationTests(URLTestCaseBase): 887 """ 888 Tests if the pattern-strings are translated correctly (within the 889 `i18n_patterns` and the normal `patterns` function). 890 """ 891 def test_no_prefix_translated(self): 892 with translation.override('en'): 893 self.assertEqual(reverse('no-prefix-translated'), '/translated/') 894 895 with translation.override('nl'): 896 self.assertEqual(reverse('no-prefix-translated'), '/vertaald/') 897 898 with translation.override('pt-br'): 899 self.assertEqual(reverse('no-prefix-translated'), '/traduzidos/') 900 901 def test_users_url(self): 902 with translation.override('en'): 903 self.assertEqual(reverse('users'), '/en/users/') 904 905 with translation.override('nl'): 906 self.assertEqual(reverse('users'), '/nl/gebruikers/') 907 908 with translation.override('pt-br'): 909 self.assertEqual(reverse('users'), '/pt-br/usuarios/') 910 911 912 class URLNamespaceTests(URLTestCaseBase): 913 """ 914 Tests if the translations are still working within namespaces. 915 """ 916 def test_account_register(self): 917 with translation.override('en'): 918 self.assertEqual(reverse('account:register'), '/en/account/register/') 919 920 with translation.override('nl'): 921 self.assertEqual(reverse('account:register'), '/nl/profiel/registeren/') 922 923 924 class URLRedirectTests(URLTestCaseBase): 925 """ 926 Tests if the user gets redirected to the right URL when there is no 927 language-prefix in the request URL. 928 """ 929 def test_no_prefix_response(self): 930 response = self.client.get('/not-prefixed/') 931 self.assertEqual(response.status_code, 200) 932 933 def test_en_redirect(self): 934 response = self.client.get('/account/register/', HTTP_ACCEPT_LANGUAGE='en') 935 self.assertRedirects(response, 'http://testserver/en/account/register/') 936 937 response = self.client.get(response['location']) 938 self.assertEqual(response.status_code, 200) 939 940 def test_en_redirect_wrong_url(self): 941 response = self.client.get('/profiel/registeren/', HTTP_ACCEPT_LANGUAGE='en') 942 self.assertEqual(response.status_code, 302) 943 self.assertEqual(response['location'], 'http://testserver/en/profiel/registeren/') 944 945 response = self.client.get(response['location']) 946 self.assertEqual(response.status_code, 404) 947 948 def test_nl_redirect(self): 949 response = self.client.get('/profiel/registeren/', HTTP_ACCEPT_LANGUAGE='nl') 950 self.assertRedirects(response, 'http://testserver/nl/profiel/registeren/') 951 952 response = self.client.get(response['location']) 953 self.assertEqual(response.status_code, 200) 954 955 def test_nl_redirect_wrong_url(self): 956 response = self.client.get('/account/register/', HTTP_ACCEPT_LANGUAGE='nl') 957 self.assertEqual(response.status_code, 302) 958 self.assertEqual(response['location'], 'http://testserver/nl/account/register/') 959 960 response = self.client.get(response['location']) 961 self.assertEqual(response.status_code, 404) 962 963 def test_pt_br_redirect(self): 964 response = self.client.get('/conta/registre-se/', HTTP_ACCEPT_LANGUAGE='pt-br') 965 self.assertRedirects(response, 'http://testserver/pt-br/conta/registre-se/') 966 967 response = self.client.get(response['location']) 968 self.assertEqual(response.status_code, 200) 969 970 971 class URLRedirectWithoutTrailingSlashTests(URLTestCaseBase): 972 """ 973 Tests the redirect when the requested URL doesn't end with a slash 974 (`settings.APPEND_SLASH=True`). 975 """ 976 def test_not_prefixed_redirect(self): 977 response = self.client.get('/not-prefixed', HTTP_ACCEPT_LANGUAGE='en') 978 self.assertEqual(response.status_code, 301) 979 self.assertEqual(response['location'], 'http://testserver/not-prefixed/') 980 981 def test_en_redirect(self): 982 response = self.client.get('/account/register', HTTP_ACCEPT_LANGUAGE='en') 983 self.assertEqual(response.status_code, 302) 984 self.assertEqual(response['location'], 'http://testserver/en/account/register') 985 986 response = self.client.get(response['location']) 987 self.assertEqual(response.status_code, 301) 988 self.assertEqual(response['location'], 'http://testserver/en/account/register/') 989 990 991 class URLRedirectWithoutTrailingSlashSettingTests(URLTestCaseBase): 992 """ 993 Tests the redirect when the requested URL doesn't end with a slash 994 (`settings.APPEND_SLASH=False`). 995 """ 996 @override_settings(APPEND_SLASH=False) 997 def test_not_prefixed_redirect(self): 998 response = self.client.get('/not-prefixed', HTTP_ACCEPT_LANGUAGE='en') 999 self.assertEqual(response.status_code, 302) 1000 self.assertEqual(response['location'], 'http://testserver/en/not-prefixed') 1001 1002 response = self.client.get(response['location']) 1003 self.assertEqual(response.status_code, 404) 1004 1005 @override_settings(APPEND_SLASH=False) 1006 def test_en_redirect(self): 1007 response = self.client.get('/account/register', HTTP_ACCEPT_LANGUAGE='en') 1008 self.assertEqual(response.status_code, 302) 1009 self.assertEqual(response['location'], 'http://testserver/en/account/register') 1010 1011 response = self.client.get(response['location']) 1012 self.assertEqual(response.status_code, 404) 1013 1014 1015 class URLResponseTests(URLTestCaseBase): 1016 """ 1017 Tests if the response has the right language-code. 1018 """ 1019 def test_not_prefixed_with_prefix(self): 1020 response = self.client.get('/en/not-prefixed/') 1021 self.assertEqual(response.status_code, 404) 1022 1023 def test_en_url(self): 1024 response = self.client.get('/en/account/register/') 1025 self.assertEqual(response.status_code, 200) 1026 self.assertEqual(response['content-language'], 'en') 1027 self.assertEqual(response.context['LANGUAGE_CODE'], 'en') 1028 1029 def test_nl_url(self): 1030 response = self.client.get('/nl/profiel/registeren/') 1031 self.assertEqual(response.status_code, 200) 1032 self.assertEqual(response['content-language'], 'nl') 1033 self.assertEqual(response.context['LANGUAGE_CODE'], 'nl') 1034 1035 def test_wrong_en_prefix(self): 1036 response = self.client.get('/en/profiel/registeren/') 1037 self.assertEqual(response.status_code, 404) 1038 1039 def test_wrong_nl_prefix(self): 1040 response = self.client.get('/nl/account/register/') 1041 self.assertEqual(response.status_code, 404) 1042 1043 def test_pt_br_url(self): 1044 response = self.client.get('/pt-br/conta/registre-se/') 1045 self.assertEqual(response.status_code, 200) 1046 self.assertEqual(response['content-language'], 'pt-br') 1047 self.assertEqual(response.context['LANGUAGE_CODE'], 'pt-br') -
tests/regressiontests/i18n/urls.py
1 from django.conf.urls.defaults import patterns, i18n_patterns, include, url 2 from django.utils.translation import ugettext_lazy as _ 3 from django.views.generic import TemplateView 4 5 6 view = TemplateView.as_view(template_name='dummy.html') 7 8 urlpatterns = patterns('', 9 url(r'^not-prefixed/$', view, name='not-prefixed'), 10 url(_(r'^translated/$'), view, name='no-prefix-translated'), 11 ) 12 13 urlpatterns += i18n_patterns('', 14 url(r'^prefixed/$', view, name='prefixed'), 15 url(_(r'^users/$'), view, name='users'), 16 url(_(r'^account/'), include('regressiontests.i18n.urls_namespace', namespace='account')), 17 ) -
tests/regressiontests/i18n/test_locale/en/LC_MESSAGES/django.po
1 # SOME DESCRIPTIVE TITLE. 2 # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 # This file is distributed under the same license as the PACKAGE package. 4 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. 5 # 6 #, fuzzy 7 msgid "" 8 msgstr "" 9 "Project-Id-Version: PACKAGE VERSION\n" 10 "Report-Msgid-Bugs-To: \n" 11 "POT-Creation-Date: 2011-06-10 11:53+0200\n" 12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" 14 "Language-Team: LANGUAGE <LL@li.org>\n" 15 "Language: \n" 16 "MIME-Version: 1.0\n" 17 "Content-Type: text/plain; charset=UTF-8\n" 18 "Content-Transfer-Encoding: 8bit\n" 19 20 #: urls.py:10 21 msgid "^translated/$" 22 msgstr "^translated/$" 23 24 #: urls.py:15 25 msgid "^users/$" 26 msgstr "^users/$" 27 28 #: urls.py:16 29 msgid "^account/" 30 msgstr "^account/" 31 32 #: urls_namespace.py:9 33 msgid "^register/$" 34 msgstr "^register/$" -
tests/regressiontests/i18n/test_locale/pt_BR/LC_MESSAGES/django.po
Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: tests/regressiontests/i18n/test_locale/en/LC_MESSAGES/django.mo ___________________________________________________________________ Added: svn:mime-type + application/octet-stream
1 # SOME DESCRIPTIVE TITLE. 2 # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 # This file is distributed under the same license as the PACKAGE package. 4 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. 5 # 6 #, fuzzy 7 msgid "" 8 msgstr "" 9 "Project-Id-Version: PACKAGE VERSION\n" 10 "Report-Msgid-Bugs-To: \n" 11 "POT-Creation-Date: 2011-06-10 13:56+0200\n" 12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" 14 "Language-Team: LANGUAGE <LL@li.org>\n" 15 "Language: \n" 16 "MIME-Version: 1.0\n" 17 "Content-Type: text/plain; charset=UTF-8\n" 18 "Content-Transfer-Encoding: 8bit\n" 19 "Plural-Forms: nplurals=2; plural=(n > 1)\n" 20 21 #: urls.py:10 22 msgid "^translated/$" 23 msgstr "^traduzidos/$" 24 25 #: urls.py:15 26 msgid "^users/$" 27 msgstr "^usuarios/$" 28 29 #: urls.py:16 wrong_urls.py:6 30 msgid "^account/" 31 msgstr "^conta/" 32 33 #: urls_namespace.py:9 wrong_urls_namespace.py:9 34 msgid "^register/$" 35 msgstr "^registre-se/$" -
tests/regressiontests/i18n/test_locale/nl/LC_MESSAGES/django.po
Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: tests/regressiontests/i18n/test_locale/pt_BR/LC_MESSAGES/django.mo ___________________________________________________________________ Added: svn:mime-type + application/octet-stream
1 # SOME DESCRIPTIVE TITLE. 2 # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 # This file is distributed under the same license as the PACKAGE package. 4 # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR. 5 # 6 #, fuzzy 7 msgid "" 8 msgstr "" 9 "Project-Id-Version: PACKAGE VERSION\n" 10 "Report-Msgid-Bugs-To: \n" 11 "POT-Creation-Date: 2011-06-10 11:53+0200\n" 12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" 13 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" 14 "Language-Team: LANGUAGE <LL@li.org>\n" 15 "Language: \n" 16 "MIME-Version: 1.0\n" 17 "Content-Type: text/plain; charset=UTF-8\n" 18 "Content-Transfer-Encoding: 8bit\n" 19 "Plural-Forms: nplurals=2; plural=(n != 1)\n" 20 21 #: urls.py:10 22 msgid "^translated/$" 23 msgstr "^vertaald/$" 24 25 #: urls.py:15 26 msgid "^users/$" 27 msgstr "^gebruikers/$" 28 29 #: urls.py:16 30 msgid "^account/" 31 msgstr "^profiel/" 32 33 #: urls_namespace.py:9 34 msgid "^register/$" 35 msgstr "^registeren/$"