What I want to do: create URLs that add a language prefix depending on the session language. There is a ton of endpoints already defined so this needs to be a somewhat plug-and-play solution.
Flask has some helpers which can do this:
- https://medium.com/@nicolas_84494/flask-create-a-multilingual-web-application-with-language-specific-urls-5d994344f5fd
- https://www.peterspython.com/en/blog/building-a-multilanguage-flask-website-with-flask-babel
As my app has lots of endpoints that are already defined, and there doesn’t seem like there is an easy way to do this, I’ve hacked together a solution that appears to be working — but I’m wondering if this is at all sound.
My solution is to add a class called SBlueprint
which inherits Blueprint
, and when .add_route()
is called, have it also automatically add all the language specific routes by adding them to language specific blueprints. I have tested on some of my existing blueprint definition and simply change the class imports:
from sanic import Blueprint
from app.utils.blueprint import SBlueprint
It appears to be working but I am wondering if there are better ways of doing this before I go down this rabbit hole to redo the entire app (which contains a ton of endpoints).
Thoughts?
from sanic import Blueprint
language_keys = ['en', 'es', 'fr', 'de', 'pl', 'pt', 'ja', 'zh', 'zh_Hant']
bp_langs = []
for key in language_keys:
bp_lang = Blueprint(f'lang_{key}', url_prefix=f'/{key}')
bp_langs.append(bp_lang)
def init_app(app: Sanic):
for bp_lang in bp_langs:
app.blueprint(bp_lang)
@app.middleware('request')
async def app_language(request):
for key in language_keys:
if request.path.startswith(f'/{key}/'):
request['session']['language'] = key
class SBlueprint(Blueprint):
def add_route(
self,
handler,
uri,
methods=frozenset({"GET"}),
host=None,
strict_slashes=None,
version=None,
name=None,
stream=False,
):
"""Create a blueprint route from a function.
:param handler: function for handling uri requests. Accepts function,
or class instance with a view_class method.
:param uri: endpoint at which the route will be accessible.
:param methods: list of acceptable HTTP methods.
:param host: IP Address of FQDN for the sanic server to use.
:param strict_slashes: Enforce the API urls are requested with a
training */*
:param version: Blueprint Version
:param name: user defined route name for url_for
:param stream: boolean specifying if the handler is a stream handler
:return: function or class instance
"""
super().add_route(
handler,
uri,
methods=methods,
host=host,
strict_slashes=strict_slashes,
version=version,
name=name,
stream=stream
)
for bp_lang in bp_langs:
bp_lang.add_route(
handler,
uri,
methods=methods,
host=host,
strict_slashes=strict_slashes,
version=version,
name=name,
stream=stream
)