New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Internationalization & Localisation #279
Comments
First things to consider:
The Django middleware is a good place to look for what behaviour we might want from an internationalization middleware: https://docs.djangoproject.com/en/2.1/topics/i18n/translation/#how-django-discovers-language-preference Essentially we'd want to set a
|
I am also interested in this topic. Using @tomchristie what are the plans about translator? would you like to go with own implementation or integrate one of the existing libraries (babel?)? Also, from my experience, various translation catalog loaders are also a good idea. To be more precise, my use cases are:
|
It's also worth noting that I don't think Starlette itself currently has any strings that we ought to mark as translatable. (The plaintext responses like 404 Not Found I would count as technical messages that aren't anyway intended to end up in front of end-users in a production setup.) However it's possible that at some point it might have some default login views that could include translatable text, and it will certainly end up recommending some third party libs that'll have translatable text strings (https://github.com/encode/typesystem is upcoming shortly, and would also tie in with any ORM implementation) We'll likely want:
|
@tomchristie thanks for reply. |
I've run into this need as well, and have added this option using the official Jinja i18n extension in the Starlette Jinja2Templates class. Some good news: It's not a large change, and will give Starlette full internationalisation / localisation support through it's template system, in a very standard way. I will be filing a pull request shortly, after I've finished the new documentation. |
Also thought it'd be worth mentioning: No additional packages are required, as the extension comes with Jinja by default. |
Update: So after some digging and double checking of my work, I've realised both gettext and Babel from within Jinja's i18n extension use a global language state, and therefore I believe are unsuitable for Starlette. Even if the translations were pre-cached and installed/uninstalled very quickly, there would be unforseen side effects because there could only be 1 active translation within the runtime at once. A future solution will probably need to have all translations loaded at once, and the current translation for one specific render to be passed into the template system. |
So there's a very easy way to do this per-request using simple dictionaries, using a format of your choice, without any sort of extra jinja2 extension or gettext or babel:
|
Should we just recommend https://github.com/klen/asgi-babel on our docs, and close this? |
Haven't had the opportunity to audit or test performance on that middleware, but at a glance, it looks like a fair choice for leveraging babel for translations. |
What is the recommended way for the Jinja2 templates? In a attempt to migrate an application from Flask to Starlette, I have created a new class that inherit from # possible configuration with extension
env = jinja2.Environment(
loader=loader,
autoescape=True,
trim_blocks=True,
lstrip_blocks=True,
auto_reload=False,
extensions=[
'jinja2.ext.loopcontrols',
'jinja2.ext.i18n'
],
) Is there a better way? |
@dalf jinja2's i18n extension is unusable for async python: #279 (comment) |
So although https://github.com/bigbag/starlette-i18n is functional, you cannot recommend it for production? Can you explain consequences of using jinja2's i18n and the recommended alternative a bit more, @gnat? Does https://github.com/klen/asgi-babel overcome these problems and how? If one needs to implement i18n, what are the practical considerations to start with? |
Regarding Jinja templates, another solution I imagined was to subclass the class LocaleJinja2Templates(Jinja2Templates):
def _create_env(self, directory):
env = super()._create_env(directory)
env.add_extension("jinja2.ext.i18n")
return env
def LocaleTemplateResponse(
self,
name: str,
context: dict,
translations: gettext.NullTranslations,
status_code: int = 200,
headers: dict = None,
media_type: str = None,
background: BackgroundTasks = None,
):
self.env.install_gettext_translations(translations, newstyle=True) # type: ignore
return super().TemplateResponse(
name, context, status_code, headers, media_type, background
)
templates = LocaleJinja2Templates(directory='templates') Then in a route, we just have to pass the gettext translations when calling async def homepage(request):
return templates.LocaleTemplateResponse('index.html', {'request': request}, translations=request.scope["translations"]) The way we retrieve the translations object can be anything we want. Here, I supposed we have a middleware setting it in the scope of the request. Maybe a bit more verbose and less "magic" than the traditional ways, but it has the benefit to be very explicit. |
First of all, thank you for excellent framework! I've started used it for one personal project and find it very useful. Also i saw roadmap of framework - it look nice. But there are some things which would be very helpful if they will have integrated with Stralette and unfortunately, i didn't find any mentions about.
Among of them is localization and internationalization. Are any plans to do this via Middleware or something else? Let's discuss how it can be implemented...)
The text was updated successfully, but these errors were encountered: