def get_redirect_for_unsupported_locale( request) -> Optional[HttpResponseRedirect]: """ Given an HttpRequest, determines if it has a locale preference for an explicitly unsupported EvictionFreeNY.org locale, and if so, redirects the client to a page that offers alternative resources for users of that locale. """ if request.path_info == "/": site = get_site_from_request_or_default(request) if get_site_type(site) == SITE_CHOICES.EVICTIONFREE: accept = request.META.get("HTTP_ACCEPT_LANGUAGE", "") # Most of this is taken from: # https://github.com/django/django/blob/master/django/utils/translation/trans_real.py for accept_lang, _ in parse_accept_lang_header(accept): if accept_lang == "*": break if not language_code_re.search(accept_lang): continue if _is_language_supported(accept_lang): break twochar_lang = accept_lang.lower()[:2] if twochar_lang in UNSUPPORTED_LOCALE_CHOICE_SET: return HttpResponseRedirect( f"/unsupported-locale/{twochar_lang}") return None
def _get_language_from_request(request, user): """从请求中获取需要同步到用户个人信息的语言 """ supported_lang_codes = get_languages() # session 有language,说明在登录页面有进行修改或设置,则需要同步到用户个人信息中 lang_code = request.session.get(translation.LANGUAGE_SESSION_KEY) if lang_code in supported_lang_codes and lang_code is not None and check_for_language( lang_code): return lang_code # 个人信息中已有language if user.language: return None # session 情况不满足同步到用户个人信息,且目前个人信息中无language设置 # 查询header头 accept = request.META.get('HTTP_ACCEPT_LANGUAGE', '') for accept_lang, unused in parse_accept_lang_header(accept): if accept_lang == '*': break if not language_code_re.search(accept_lang): continue try: return get_supported_language_variant(accept_lang) except LookupError: continue # 使用settings默认设置 try: return get_supported_language_variant(settings.LANGUAGE_CODE) except LookupError: return settings.LANGUAGE_CODE
def get_language_from_request(request): """ Analyzes the request to find what language the user wants the system to show. Only languages listed in settings.LANGUAGES are taken into account. If the user requests a sublanguage where we have a main language, we send out the main language. """ global _supported if _supported is None: _supported = OrderedDict(settings.LANGUAGES) # Priority 1: User settings if request.user.is_authenticated(): lang_code = request.user.locale if lang_code in _supported and lang_code is not None and check_for_language(lang_code): return lang_code # Priority 2: Anonymous user settings (session, cookie) if hasattr(request, 'session'): lang_code = request.session.get(LANGUAGE_SESSION_KEY) if lang_code in _supported and lang_code is not None and check_for_language(lang_code): return lang_code lang_code = request.COOKIES.get(settings.LANGUAGE_COOKIE_NAME) try: return get_supported_language_variant(lang_code) except LookupError: pass # Priority 3: Event default if hasattr(request, 'event'): lang_code = request.event.locale try: return get_supported_language_variant(lang_code) except LookupError: pass # Priority 4: Browser default accept = request.META.get('HTTP_ACCEPT_LANGUAGE', '') for accept_lang, unused in parse_accept_lang_header(accept): if accept_lang == '*': break if not language_code_re.search(accept_lang): continue try: return get_supported_language_variant(accept_lang) except LookupError: continue try: return get_supported_language_variant(settings.LANGUAGE_CODE) except LookupError: return settings.LANGUAGE_CODE
def get_language_from_request(request): """ Analyzes the request to find what language the user wants the system to show. Only languages listed in settings.LANGUAGES are taken into account. If the user requests a sublanguage where we have a main language, we send out the main language. If there is a language code in the URL path prefix, then it is selected as the request language and other methods (language cookie, Accept-Language header) are skipped. In Django, the URL path prefix can be skipped with the check_path=False parameter, removed in this code. Based on Django 1.8.19's get_language_from_request from django/utils/translation/trans_real.py, with changes: * Always check the path * Don't check session language * Use LANGUAGE_CODE as the fallback language code, instead of passing it through get_supported_language_variant first """ lang_code = get_language_from_path(request.path_info) if lang_code is not None: return lang_code lang_code = request.COOKIES.get(settings.LANGUAGE_COOKIE_NAME) try: return get_supported_language_variant(lang_code) except LookupError: pass accept = request.META.get('HTTP_ACCEPT_LANGUAGE', '') for accept_lang, unused in parse_accept_lang_header(accept): if accept_lang == '*': break # The regex check was added with a security fix: # https://www.djangoproject.com/weblog/2007/oct/26/security-fix/ # In the Django version, non-matching accept_lang codes are skipped. # However, it doesn't seem possible for parse_accept_lang_header to # return codes that would fail this check. # The assertion keeps the security aspect, and gives us an opportunity # to add a test case to Kuma and Django. assert language_code_re.search(accept_lang) try: return get_supported_language_variant(accept_lang) except LookupError: continue # Fallback to default settings.LANGUAGE_CODE. # Django supports a case when LANGUAGE_CODE is not in LANGUAGES # (see https://github.com/django/django/pull/824). but our LANGUAGE_CODE is # always the first entry in LANGUAGES. return settings.LANGUAGE_CODE
def _language_from_browser(request, supported): accept_value = request.headers.get("Accept-Language", "") for accept_lang, _ in parse_accept_lang_header(accept_value): if accept_lang == "*": break if not language_code_re.search(accept_lang): continue with suppress(LookupError): val = get_supported_language_variant(accept_lang) if val and val in supported: return val
def get_language_from_browser(request: HttpRequest) -> str: accept = request.META.get('HTTP_ACCEPT_LANGUAGE', '') for accept_lang, unused in parse_accept_lang_header(accept): if accept_lang == '*': break if not language_code_re.search(accept_lang): continue try: return get_supported_language_variant(accept_lang) except LookupError: continue
def get_accept_headers_language(request): accept = request.META.get("HTTP_ACCEPT_LANGUAGE", "") for accept_lang, unused in parse_accept_lang_header(accept): if accept_lang == "*": break if not language_code_re.search(accept_lang): continue try: return get_supported_language_variant(accept_lang) except LookupError: continue
def get_language_from_browser(request) -> str: accept = request.META.get('HTTP_ACCEPT_LANGUAGE', '') for accept_lang, unused in parse_accept_lang_header(accept): if accept_lang == '*': break if not language_code_re.search(accept_lang): continue try: return get_supported_language_variant(accept_lang) except LookupError: continue
def get_language_from_browser(request: HttpRequest) -> str: accept = request.headers.get('Accept-Language', '') for accept_lang, unused in parse_accept_lang_header(accept): if accept_lang == '*': break if not language_code_re.search(accept_lang): continue try: return get_supported_language_variant(accept_lang) except LookupError: continue
def get_language_from_request(request): # noqa complexity-16 """ Analyzes the request to find what language the user wants the system to show. Only languages listed in settings.LANGUAGES are taken into account. If the user requests a sublanguage where we have a main language, we send out the main language. If check_path is True, the URL path prefix will be checked for a language code, otherwise this is skipped for backwards compatibility. """ global DEVICE_LANGUAGE supported_lang_codes = get_languages() if hasattr(request, 'session'): lang_code = request.session.get(LANGUAGE_SESSION_KEY) if lang_code in supported_lang_codes and lang_code is not None and check_for_language(lang_code): return lang_code lang_code = request.COOKIES.get(settings.LANGUAGE_COOKIE_NAME) try: return get_supported_language_variant(lang_code) except LookupError: pass accept = request.META.get('HTTP_ACCEPT_LANGUAGE', '') for accept_lang, unused in parse_accept_lang_header(accept): if accept_lang == '*': break if not language_code_re.search(accept_lang): continue try: return get_supported_language_variant(accept_lang) except LookupError: continue try: if DEVICE_LANGUAGE is None: DEVICE_LANGUAGE = DeviceSettings.objects.get().language_id return get_supported_language_variant(DEVICE_LANGUAGE) except (DeviceSettings.DoesNotExist, LookupError): pass try: return get_supported_language_variant(settings.LANGUAGE_CODE) except LookupError: return settings.LANGUAGE_CODE
def _language_from_browser(self, request, supported): accept_value = request.META.get('HTTP_ACCEPT_LANGUAGE', '') for accept_lang, unused in parse_accept_lang_header(accept_value): if accept_lang == '*': break if not language_code_re.search(accept_lang): continue try: val = get_supported_language_variant(accept_lang) if val and val in supported: return val except LookupError: continue
def _get_locale_from_language_header(self, request): # Copied from django.utils.translation.real_trans.get_language_from_request accept = request.META.get("HTTP_ACCEPT_LANGUAGE", "") for accept_lang, unused in parse_accept_lang_header(accept): if accept_lang == "*": break if not language_code_re.search(accept_lang): continue try: return get_supported_language_variant(accept_lang) except LookupError: continue return None
def _language_from_browser(request, supported): accept_value = request.headers.get('Accept-Language', '') for accept_lang, _ in parse_accept_lang_header(accept_value): if accept_lang == '*': break if not language_code_re.search(accept_lang): continue try: val = get_supported_language_variant(accept_lang) if val and val in supported: return val except LookupError: continue return None
def get_language_from_header(self, header): for accept_lang, unused in parse_accept_lang_header(header): if accept_lang == '*': break if not language_code_re.search(accept_lang): continue try: return get_supported_language_variant(accept_lang) except LookupError: continue try: return get_supported_language_variant(settings.LANGUAGE_CODE) except LookupError: return settings.LANGUAGE_CODE
def get_language_from_request(request, check_path=False): """ Analyze the request to find what language the user wants the system to show. Only languages listed in settings.LANGUAGES are taken into account. If the user requests a sublanguage where we have a main language, we send out the main language. If check_path is True, the URL path prefix will be checked for a language code, otherwise this is skipped for backwards compatibility. """ if check_path: lang_code = translation.get_language_from_path(request.path_info) if lang_code is not None: return lang_code lang_code = request.COOKIES.get(settings.LANGUAGE_COOKIE_NAME) try: return get_supported_language_variant(lang_code) except LookupError: pass accept = request.META.get('HTTP_ACCEPT_LANGUAGE', '') for accept_lang, unused in parse_accept_lang_header(accept): if accept_lang == '*': break # Если браузер настроен на русский язык, то считать украинский основным if accept_lang == 'ru': return settings.LANGUAGE_CODE if not language_code_re.search(accept_lang): continue try: return get_supported_language_variant(accept_lang) except LookupError: continue try: return get_supported_language_variant(settings.LANGUAGE_CODE) except LookupError: return settings.LANGUAGE_CODE
def _get_locale_from_language_header(self) -> Optional[str]: # Logic adapted from django.utils.translation.real_trans.get_language_from_request for accept_lang, unused in parse_accept_lang_header( self.accept_language_header): if accept_lang == "*": break if not language_code_re.search(accept_lang): continue try: locale_id = get_supported_language_variant(accept_lang) except LookupError: continue if is_supported(locale_id): return locale_id else: continue return None
def get_language_from_request(request, check_path=False): """ Replacement for django.utils.translation.get_language_from_request. The portion of code that is modified is identified below with a comment. """ if check_path: lang_code = get_language_from_path(request.path_info) if lang_code is not None: return lang_code lang_code = request.COOKIES.get(settings.LANGUAGE_COOKIE_NAME) if lang_code is not None and lang_code in get_languages( ) and check_for_language(lang_code): return lang_code try: return get_supported_language_variant(lang_code) except LookupError: pass accept = request.META.get('HTTP_ACCEPT_LANGUAGE', '') for accept_lang, unused in parse_accept_lang_header(accept): if accept_lang == '*': break # Convert lowercase region to uppercase before attempting to find a variant. # This is the only portion of code that is modified from the core function. accept_lang = language_code_to_iso_3166(accept_lang) if not language_code_re.search(accept_lang): continue try: return get_supported_language_variant(accept_lang) except LookupError: continue try: return get_supported_language_variant(settings.LANGUAGE_CODE) except LookupError: return settings.LANGUAGE_CODE
def get_language_from_scope(scope): """Get language from ASGI scope. Based on django.utils.translation.get_language_from_request """ accept = "" for k, v in scope["headers"]: if k == b"accept-language": accept = v.decode("latin1") for accept_lang, unused in parse_accept_lang_header(accept): if accept_lang == "*": break if not language_code_re.search(accept_lang): # pragma: no cover continue try: return get_supported_language_variant(accept_lang) except LookupError: # pragma: no cover continue try: return get_supported_language_variant(settings.LANGUAGE_CODE) except LookupError: # pragma: no cover return settings.LANGUAGE_CODE
def get_language_from_request(request): """ Analyzes the request to find what language the user wants the system to show. Only languages listed in settings.LANGUAGES are taken into account. If the user requests a sublanguage where we have a main language, we send out the main language. If there is a language code in the URL path prefix, then it is selected as the request language and other methods (language cookie, Accept-Language header) are skipped. In Django, the URL path prefix can be skipped with the check_path=False parameter, removed in this code. Based on Django 1.11.16's get_language_from_request from django/utils/translation/trans_real.py, with changes: * Always check the path. * Don't check session language. * Use LANGUAGE_CODE as the fallback language code, instead of passing it through get_supported_language_variant first. """ # Kuma: Always use the URL's langauge (force check_path=True) lang_code = get_language_from_path(request.path_info) if lang_code is not None: return lang_code # Kuma: Skip checking the session-stored language via LANGUAGE_SESSION_KEY # Use the (valid) language cookie override lang_code = request.COOKIES.get(settings.LANGUAGE_COOKIE_NAME) try: return get_supported_language_variant(lang_code) except LookupError: pass # Pick the closest langauge based on the Accept Language header accept = request.META.get('HTTP_ACCEPT_LANGUAGE', '') for accept_lang, unused in parse_accept_lang_header(accept): if accept_lang == '*': break # Kuma: Assert accept_lang fits the language code pattern # The regex check was added with a security fix: # https://www.djangoproject.com/weblog/2007/oct/26/security-fix/ # In the Django version, non-matching accept_lang codes are skipped. # However, it doesn't seem possible for parse_accept_lang_header to # return codes that would fail this check. # The assertion keeps the security aspect, and gives us an opportunity # to add a test case to Kuma and Django. assert language_code_re.search(accept_lang) try: return get_supported_language_variant(accept_lang) except LookupError: continue # Kuma: Fallback to default settings.LANGUAGE_CODE. # Django supports a case when LANGUAGE_CODE is not in LANGUAGES # (see https://github.com/django/django/pull/824). but our LANGUAGE_CODE is # always the first entry in LANGUAGES. return settings.LANGUAGE_CODE