Skip to content

Add an extractor for the user language #2197

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

Open
1 task done
frenetisch-applaudierend opened this issue Aug 27, 2023 · 6 comments
Open
1 task done

Add an extractor for the user language #2197

frenetisch-applaudierend opened this issue Aug 27, 2023 · 6 comments
Labels
A-axum-extra C-feature-request Category: A feature request, i.e: not implemented / a PR.

Comments

@frenetisch-applaudierend
  • I have looked for existing issues (including closed) about this

Feature Request

Add an extractor for the preferred language for a user

Motivation

It is not uncommon to want to return a response in the users language, especially when building user interfaces. While it is not hard to implement this on your own, it is nevertheless some boilerplate code that could be avoided.

Additionally, having a canonical way to get the request language would allow other extractors and middleware to rely on that extractor to get the user language, e.g. to return localized error responses.

Proposal

Add a UserLanguage extractor that reads from the request a list of preferred user languages and makes them available for the user. Standard sources of languages could include the Accept-Language header, a :lang path segment and a lang query parameter.

It may make sense to make the language sources configurable as well as allowing to add custom sources, such as reading the language from a cookie.

Alternatives

This could also be implemented in a crate outside of axum. The advantage being less maintenance overhead for axum and allow for more diversity in implementations. The main drawback would be that there is no canonical way for library crates to read the preferred user language. Relying on a specific third party crate may not be desirable in such cases.

Implementation

If this feature is something that would fit into the scope of axum, I would like to contribute this in a pull request.

@davidpdrsn
Copy link
Member

davidpdrsn commented Aug 27, 2023

Sounds like a good fit for axum-extra. Then we can move it to axum when it’s matured.

@davidpdrsn davidpdrsn added C-feature-request Category: A feature request, i.e: not implemented / a PR. A-axum-extra labels Aug 27, 2023
@frenetisch-applaudierend
Copy link
Author

Great, I'll take a stab at it then! Thanks!

@martinetd
Copy link

hi @frenetisch-applaudierend

I've read the PR from a couple of years back, did you publish anything in a separate crate or did you end up just having the code in your own app?

Considering the amount of work required to get something clean working, I pretty much agree this doesn't belong to axum:

  • (for some reason headers disabled AcceptLanguage and the quality value parsing, so the parsing needs to be reimplemented as was done in Add extractor for user language #2198)
  • even if we get a clean list, need to decide which languages we want to support and properly find the highest value one that is convenient enough (e.g. if we provide japanese and english with japanese default if no value, we'd probably still want to give english for en or en-* so decide of some semantically correct matching?)
  • and at that point ideally keep the templates language neutral and have translations done in something similar to a .po file that is easier to keep up to date than raw html copies

So, yeah, quite a bit of work depending on how the later part would be done - I can understand not wanting to maintain all this.

Even if it's not a crate, having an example to build on would be great instead of starting over.

@frenetisch-applaudierend
Copy link
Author

Hi @martinetd
I ended up using a simpler version of what I implemented in my PR. To be precise, the PR only tried to address the first point: given a list of sources for the user language, build a list of user preferred languages and make this available to the app. Selecting a language and translation would be in the responsibility of the application. Depending on your use case this is not that hard to do and you can draw a lot of examples from the PR. Much of the complexity of the PR comes from the fact that it tries to make the sources configurable. If you don't need that, you can get away with a much simpler solution.

@ianthetechie
Copy link

Interesting to see this getting so much activity suddenly! I just had a quick read over #2198. I've also created my own internal implementation recently 😅

My code also only aims to address the getting the ranked list. I believe that, whether or not it's directly an axum or axum-extra, the point of this extractor should be to get just the ranked list. Then the app decides what to do with it. I also supported an override via query arg, and it looks like the PR from years past went even further with path based config too.

As was already pointed out, it would be nice if this could be built on typed headers. I see there's a disabled implementation, but couldn't figure out the backstory on that, so I just asked: hyperium/headers#206.

I guess the biggest question is probably which language tags are accepted. There are a bunch of crates in the space, from isolang to oxilang, to language_tags to unic-langid, and... oh my 😅 It's not clear that there is a "winner" crate here yet, and in my own testing, it seems some crates don't necessarily accept all valid identifiers.

So I guess the best option for the moment is to probably accept any input that might be valid and then let the user decide if they want stricter typing on top.

@martinetd
Copy link

@frenetisch-applaudierend Thanks!
I agree, will probably just pick the header parsing bits from the PR if we need it soon, localization went to the back burner for now :)

@ianthetechie Thanks! I agree having a typed header would be the cleanest way to get this first part handled easily in axum. Happy to help as free time allows.
I guess that for the second part we'll handle actual translations themselves manually with a huge struct in the askama template... Oh, the last comment of askama-rs/askama-old#202 with rust-i18n actually looks neat enough.

Might also be worth spending a moment to add an axum example with it once the typed header is available if @davidpdrsn is ok with that, so we have a "blessed" way documented/tested.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-axum-extra C-feature-request Category: A feature request, i.e: not implemented / a PR.
Projects
None yet
Development

No branches or pull requests

4 participants