84 lines
2.3 KiB
Python
84 lines
2.3 KiB
Python
from __future__ import annotations
|
|
|
|
import os.path
|
|
import re
|
|
import typing
|
|
|
|
import quart
|
|
|
|
from .app import app
|
|
|
|
_VALID_LANGUAGE_NAMES = re.compile(r'^[-a-z0-9_]+$')
|
|
|
|
|
|
def parse_accept_language(value: str) -> typing.List[str]:
|
|
value = value.strip()
|
|
if not value or value == '*':
|
|
return []
|
|
tuples = []
|
|
for entry in value.split(','):
|
|
attrs = entry.split(';')
|
|
name = attrs.pop(0).strip().lower()
|
|
q = 1.0
|
|
for attr in attrs:
|
|
if not '=' in attr: continue
|
|
key, value = attr.split('=', maxsplit=1)
|
|
if key.strip().lower() == 'q':
|
|
try:
|
|
q = float(value.strip())
|
|
except ValueError:
|
|
q = 0.0
|
|
if q >= 0.0:
|
|
tuples.append((q, name))
|
|
tuples.sort()
|
|
have = set()
|
|
result = []
|
|
for (_q, name) in tuples:
|
|
if name in have: continue
|
|
if name == '*': break
|
|
have.add(name)
|
|
if _VALID_LANGUAGE_NAMES.match(name):
|
|
result.append(name)
|
|
short_name = name.split('-', maxsplit=1)[0].split('_', maxsplit=1)[0]
|
|
if not short_name or short_name in have: continue
|
|
have.add(short_name)
|
|
result.append(short_name)
|
|
return result
|
|
|
|
|
|
@app.before_request
|
|
def detect_language():
|
|
g = quart.g
|
|
r = quart.request
|
|
s = quart.session
|
|
if 'setlang' in r.args:
|
|
lang = r.args.get('setlang').strip().lower()
|
|
if lang and _VALID_LANGUAGE_NAMES.match(lang):
|
|
if s.get('lang') != lang:
|
|
s['lang'] = lang
|
|
g.langs = [lang]
|
|
return
|
|
else:
|
|
# reset language
|
|
s.pop('lang', None)
|
|
lang = s.get('lang')
|
|
if lang:
|
|
lang = lang.strip().lower()
|
|
if lang and _VALID_LANGUAGE_NAMES.match(lang):
|
|
g.langs = [lang]
|
|
return
|
|
acc_lang = ','.join(r.headers.get_all('Accept-Language'))
|
|
g.langs = parse_accept_language(acc_lang)
|
|
|
|
|
|
async def render_i18n_template(template, /, **kwargs) -> str:
|
|
langs: typing.List[str] = quart.g.langs
|
|
if not langs:
|
|
return await quart.render_template(template, **kwargs)
|
|
names = [
|
|
os.path.join('i18n', lang, template)
|
|
for lang in langs
|
|
]
|
|
names.append(template)
|
|
return await quart.render_template(names, **kwargs)
|