Skip to content

Commit a18c8ae

Browse files
committed
implemented async-only locale middleware
1 parent 02a1ea8 commit a18c8ae

File tree

1 file changed

+81
-0
lines changed

1 file changed

+81
-0
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
from django.conf import settings
2+
from django.conf.urls.i18n import is_language_prefix_patterns_used
3+
from django.http import HttpResponseRedirect
4+
from django.urls import get_script_prefix, is_valid_path
5+
from django.utils import translation
6+
from django.utils.cache import patch_vary_headers
7+
8+
from django_async_extensions.amiddleware.base import AsyncMiddlewareMixin
9+
10+
11+
class AsyncLocaleMiddleware(AsyncMiddlewareMixin):
12+
"""
13+
Parse a request and decide what translation object to install in the
14+
current thread context. This allows pages to be dynamically translated to
15+
the language the user desires (if the language is available).
16+
"""
17+
18+
response_redirect_class = HttpResponseRedirect
19+
20+
async def process_request(self, request):
21+
urlconf = getattr(request, "urlconf", settings.ROOT_URLCONF)
22+
(
23+
i18n_patterns_used,
24+
prefixed_default_language,
25+
) = is_language_prefix_patterns_used(urlconf)
26+
language = translation.get_language_from_request(
27+
request, check_path=i18n_patterns_used
28+
)
29+
language_from_path = translation.get_language_from_path(request.path_info)
30+
if (
31+
not language_from_path
32+
and i18n_patterns_used
33+
and not prefixed_default_language
34+
):
35+
language = settings.LANGUAGE_CODE
36+
translation.activate(language)
37+
request.LANGUAGE_CODE = translation.get_language()
38+
39+
async def process_response(self, request, response):
40+
language = translation.get_language()
41+
language_from_path = translation.get_language_from_path(request.path_info)
42+
urlconf = getattr(request, "urlconf", settings.ROOT_URLCONF)
43+
(
44+
i18n_patterns_used,
45+
prefixed_default_language,
46+
) = is_language_prefix_patterns_used(urlconf)
47+
48+
if (
49+
response.status_code == 404
50+
and not language_from_path
51+
and i18n_patterns_used
52+
and prefixed_default_language
53+
):
54+
# Maybe the language code is missing in the URL? Try adding the
55+
# language prefix and redirecting to that URL.
56+
language_path = "/%s%s" % (language, request.path_info)
57+
path_valid = is_valid_path(language_path, urlconf)
58+
path_needs_slash = not path_valid and (
59+
settings.APPEND_SLASH
60+
and not language_path.endswith("/")
61+
and is_valid_path("%s/" % language_path, urlconf)
62+
)
63+
64+
if path_valid or path_needs_slash:
65+
script_prefix = get_script_prefix()
66+
# Insert language after the script prefix and before the
67+
# rest of the URL
68+
language_url = request.get_full_path(
69+
force_append_slash=path_needs_slash
70+
).replace(script_prefix, "%s%s/" % (script_prefix, language), 1)
71+
# Redirect to the language-specific URL as detected by
72+
# get_language_from_request(). HTTP caches may cache this
73+
# redirect, so add the Vary header.
74+
redirect = self.response_redirect_class(language_url)
75+
patch_vary_headers(redirect, ("Accept-Language", "Cookie"))
76+
return redirect
77+
78+
if not (i18n_patterns_used and language_from_path):
79+
patch_vary_headers(response, ("Accept-Language",))
80+
response.headers.setdefault("Content-Language", language)
81+
return response

0 commit comments

Comments
 (0)