diff --git a/README.md b/README.md index 72be632..822512a 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,6 @@ In production put a reverse proxy in front of the local web ui (on 127.0.0.1:800 Create `custom/templates` and put customized templates (from `src/capport/api/templates`) there. -Create `i18n/` folders to put localized templates into. +Create `i18n/` folders to put localized templates into (localized extends must use the full `i18n/.../basetmpl` paths though). Requests with a `setlang=` query parameter will set the language and try to store the choice in a session cookie. diff --git a/src/capport/api/app_cls.py b/src/capport/api/app_cls.py index e33e2b5..f7e8220 100644 --- a/src/capport/api/app_cls.py +++ b/src/capport/api/app_cls.py @@ -18,26 +18,6 @@ class DispatchingJinjaLoader(quart.templating.DispatchingJinjaLoader): def __init__(self, app: MyQuartApp) -> None: super().__init__(app) - def get_source( - self, environment: jinja2.Environment, template: str - ) -> typing.Tuple[str, typing.Optional[str], typing.Optional[typing.Callable[[], bool]]]: - """Returns the template source from the environment. - - This considers the loaders on the :attr:`app` and blueprints. - """ - langs: typing.List[str] = quart.g.langs - for loader in self._loaders(): - for lang in langs: - try: - return loader.get_source(environment, os.path.join('i18n', lang, template)) - except jinja2.TemplateNotFound: - continue - try: - return loader.get_source(environment, template) - except jinja2.TemplateNotFound: - continue - raise jinja2.TemplateNotFound(template) - def _loaders(self) -> typing.Generator[jinja2.BaseLoader, None, None]: if self.app.custom_loader: yield self.app.custom_loader diff --git a/src/capport/api/lang.py b/src/capport/api/lang.py index 0789b6c..5b9b033 100644 --- a/src/capport/api/lang.py +++ b/src/capport/api/lang.py @@ -3,6 +3,7 @@ from __future__ import annotations import re import typing import quart +import os.path from .app import app @@ -49,14 +50,15 @@ def detect_language(): g = quart.g r = quart.request s = quart.session - lang = r.args.get('setlang') - if lang: - lang = lang.strip().lower() + if 'setlang' in r.args: + lang = r.args.get('setlang').strip().lower() if lang and _VALID_LANGUAGE_NAMES.match(lang): - s = quart.session s['lang'] = lang g.langs = [lang] return + else: + # reset language + s.pop('lang') lang = s.get('lang') if lang: lang = lang.strip().lower() @@ -65,3 +67,15 @@ def detect_language(): 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) diff --git a/src/capport/api/views.py b/src/capport/api/views.py index ca92b8a..1066fb2 100644 --- a/src/capport/api/views.py +++ b/src/capport/api/views.py @@ -4,15 +4,16 @@ import ipaddress import logging import typing -import capport.database import capport.comm.hub import capport.comm.message +import capport.database import capport.utils.cli import capport.utils.ipneigh import quart from capport import cptypes from .app import app +from .lang import render_i18n_template _logger = logging.getLogger(__name__) @@ -99,11 +100,11 @@ async def user_lookup() -> cptypes.MacPublicState: async def index(): state = await user_lookup() if not state.mac: - return await quart.render_template('index_unknown.html', state=state) + return await render_i18n_template('index_unknown.html', state=state) elif state.allowed: - return await quart.render_template('index_active.html', state=state) + return await render_i18n_template('index_active.html', state=state) else: - return await quart.render_template('index_inactive.html', state=state) + return await render_i18n_template('index_inactive.html', state=state) @app.route('/login', methods=['POST'])