refactor: Set Language in HTTPHeader
Order of priority for setting language: 1. Form Dict => _lang 2. Cookie => preferred_language 3. Request Header => Accept-Language 4. User document => language 5. System Settings => language Cookie is placed at #2 since the language picker in the navbar depends on it. And the Accept-Language header sends values based on the client's locales. --- Form Dict _lang now accepts language codes too. Previously, language names were used...for whatever reason.
This commit is contained in:
parent
caafd9e2b5
commit
c47cbfd2ef
2 changed files with 59 additions and 32 deletions
|
|
@ -5,13 +5,13 @@ from frappe import _
|
|||
import frappe
|
||||
import frappe.database
|
||||
import frappe.utils
|
||||
from frappe.utils import cint, flt, get_datetime, datetime, date_diff, today
|
||||
from frappe.utils import cint, get_datetime, datetime, date_diff, today
|
||||
import frappe.utils.user
|
||||
from frappe import conf
|
||||
from frappe.sessions import Session, clear_sessions, delete_session
|
||||
from frappe.modules.patch_handler import check_session_stopped
|
||||
from frappe.translate import get_lang_code, guess_language
|
||||
from frappe.utils.password import check_password, delete_login_failed_cache
|
||||
from frappe.translate import guess_language
|
||||
from frappe.utils.password import check_password
|
||||
from frappe.core.doctype.activity_log.activity_log import add_authentication_log
|
||||
from frappe.twofactor import (should_run_2fa, authenticate_for_2factor,
|
||||
confirm_otp_token, get_cached_user_pass)
|
||||
|
|
@ -92,12 +92,7 @@ class HTTPRequest:
|
|||
frappe.throw(_("Invalid Request"), frappe.CSRFTokenError)
|
||||
|
||||
def set_lang(self):
|
||||
if frappe.form_dict._lang:
|
||||
lang = get_lang_code(frappe.form_dict._lang)
|
||||
if lang:
|
||||
frappe.local.lang = lang
|
||||
else:
|
||||
frappe.local.lang = guess_language()
|
||||
frappe.local.lang = guess_language()
|
||||
|
||||
def get_db_name(self):
|
||||
"""get database name from conf"""
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import io
|
|||
import itertools
|
||||
import json
|
||||
import operator
|
||||
import functools
|
||||
import os
|
||||
import re
|
||||
from csv import reader
|
||||
|
|
@ -21,36 +22,64 @@ from frappe.utils import is_html, strip, strip_html_tags
|
|||
|
||||
|
||||
def guess_language(lang_list=None):
|
||||
"""Set `frappe.local.lang` from HTTP headers at beginning of request"""
|
||||
"""Set `frappe.local.lang` from HTTP headers at beginning of request
|
||||
|
||||
Order of priority for setting language:
|
||||
1. Form Dict => _lang
|
||||
2. Cookie => preferred_language
|
||||
3. Request Header => Accept-Language
|
||||
4. User document => language
|
||||
5. System Settings => language
|
||||
"""
|
||||
|
||||
# fetch language from form_dict
|
||||
if frappe.form_dict._lang:
|
||||
language = get_lang_code(
|
||||
frappe.form_dict._lang or get_parent_language(frappe.form_dict._lang)
|
||||
)
|
||||
if language:
|
||||
return language
|
||||
|
||||
lang_set = set(lang_list or get_all_languages() or [])
|
||||
|
||||
# fetch language from cookie
|
||||
preferred_language_cookie = frappe.request.cookies.get('preferred_language')
|
||||
lang_codes = list(frappe.request.accept_languages.values())
|
||||
|
||||
if preferred_language_cookie:
|
||||
lang_codes.append(preferred_language_cookie)
|
||||
if preferred_language_cookie in lang_set:
|
||||
return preferred_language_cookie
|
||||
|
||||
if not lang_codes:
|
||||
return frappe.local.lang
|
||||
parent_language = get_parent_language(language)
|
||||
if parent_language in lang_set:
|
||||
return parent_language
|
||||
|
||||
guess = None
|
||||
if not lang_list:
|
||||
lang_list = get_all_languages() or []
|
||||
# fetch language from request headers
|
||||
accept_language = list(frappe.request.accept_languages.values())
|
||||
|
||||
for l in lang_codes:
|
||||
code = l.strip()
|
||||
if not isinstance(code, str):
|
||||
code = str(code, 'utf-8')
|
||||
if code in lang_list or code == "en":
|
||||
guess = code
|
||||
break
|
||||
for language in accept_language:
|
||||
if language in lang_set:
|
||||
return language
|
||||
|
||||
# check if parent language (pt) is setup, if variant (pt-BR)
|
||||
if "-" in code:
|
||||
code = code.split("-")[0]
|
||||
if code in lang_list:
|
||||
guess = code
|
||||
break
|
||||
parent_language = get_parent_language(language)
|
||||
if parent_language in lang_set:
|
||||
return parent_language
|
||||
|
||||
# fallback to language set in User or System Settings
|
||||
return frappe.local.lang
|
||||
|
||||
|
||||
@functools.lru_cache(maxsize=None)
|
||||
def get_parent_language(lang: str) -> str:
|
||||
"""If the passed language is a variant, return its parent
|
||||
|
||||
Eg:
|
||||
1. zh-TW -> zh
|
||||
2. sr-BA -> sr
|
||||
"""
|
||||
is_language_variant = "-" in lang
|
||||
if is_language_variant:
|
||||
return lang[:lang.index("-")]
|
||||
|
||||
return guess or frappe.local.lang
|
||||
|
||||
def get_user_lang(user=None):
|
||||
"""Set frappe.local.lang from user preferences on session beginning or resumption"""
|
||||
|
|
@ -75,7 +104,10 @@ def get_user_lang(user=None):
|
|||
return lang
|
||||
|
||||
def get_lang_code(lang):
|
||||
return frappe.db.get_value('Language', {'language_name': lang}) or lang
|
||||
return (
|
||||
frappe.db.get_value("Language", {"name": lang})
|
||||
or frappe.db.get_value("Language", {"language_name": lang})
|
||||
)
|
||||
|
||||
def set_default_language(lang):
|
||||
"""Set Global default language"""
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue