Repository navigation
Prefer the closest locale in language negotiation - #51
Merged
Merged
Conversation
With both en and en-gb, L10n::langneg("en-GB") returned en: the first
locale with the same language subtag won. Now, for each header entry in
q order, the best match is the exact locale, then the same language and
region with another script, then the generic locale (en for en-AU), then
any locale of the language.
Both the generated L10n::langneg (via negotiate_languages) and
L10nLanguageVec::langneg use one shared best_match. The languages guide
shows the behaviour in examples that docs-check runs (with a new en-gb
locale there).
- Ranking takes scripts into account: a locale whose script conflicts with the requested one (sr-Cyrl for sr-Latn) is a last resort, the "same region" tier only applies when the request has a region, and a locale without an unrequested script wins ties (en over en-Latn). - Accept-Language entries with q=0 or an invalid q are skipped instead of matching (q=0) or being promoted to q=1 (invalid). Other parameters next to q are allowed. - best_match ranks each candidate once through a plain rank() function and takes a candidate accessor instead of a slice, so negotiate_languages no longer allocates per call. - negotiate_languages drops its unused PartialEq bound. - Docs list every tier, and both the docs and a test state the known limit: scripts aren't inferred from regions (zh-TW vs zh-Hans/Hant).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
With both
enanden-gbbuilt in,L10n::langneg("en-GB")returnedL10n::En. Negotiation compared only the language subtag and took the first locale that matched.Now each
Accept-Languageentry, inqorder, picks the closest locale:en-GB→en-gb);sr-Latn-RS→sr-RS);en-AU→en, even ifen-gbcomes first);en-AU→en-gbwhen there's noen);sr-Latn→sr-Cyrlonly when no othersrexists).Ties go to the locale without a script the request didn't ask for (
en→en, noten-Latn). The header's own order still comes first. Inde-AT, en-GB;q=0.5, a plaindebeats an exacten-gb, because the user prefers German.Entries with
q=0("not acceptable") or an invalidqare now skipped. Before, aq=0entry could still be picked, and an invalid weight counted asq=1.Known limit: scripts aren't inferred from regions, so
zh-TWwith bothzh-Hansandzh-Hantavailable takes the first one. Fixing that needs likely-subtags data (icu_locale). That would add 18 crates and about 17 KB tolangnegbuilds, so it's left for a separate decision. The docs and a test state this limit.Before and after, with
en,en-gbandfr:en-GBEnEnGben-USEnEnfr-CAFrFrChanges
prelude::best_matchranks each candidate once with a plainrankfunction. Both the generatedL10n::langneg(throughnegotiate_languages) andL10nLanguageVec::langneguse it, so they can't disagree, and neither allocates per call any more.negotiate_languagesno longer requiresPartialEqon the language type.negotiate_languageshad no tests; there are now tests for each tier and for header order.assert_eq!examples. docs-check runs them, now against an addeden-gblocale.This changes which locale some requests get, but only towards the exact or more generic match, so I've listed it as a fix rather than a breaking change.