opentable / accept-language-parser

It parses the accept-language header from an HTTP request
https://www.npmjs.com/package/accept-language-parser
MIT License
163 stars 23 forks source link

.pick ignores quality? #34

Open mrkurt opened 5 years ago

mrkurt commented 5 years ago

I'm trying to use incoming HTTP headers to serve up the most appropriate translation of a site, and it seems like .pick is exactly what I need, but it's not respecting the quality value of headers. When I run this:

parser.pick(["en", "nl"], "en-GB,nl;q=0.5"

I would expect it to return en, but it's giving me nl. Is this on purpose or would you like a PR to fix it?

matteofigus commented 5 years ago

This is correct. In the pick, you should use the full languages you support, like ['en-GB', 'nl-NL']. In that scenario, the picked would be en-GB. If you want to have just en check the loose option in the README.

mrkurt commented 5 years ago

Ah! loose actually returns the same, presumably because nl is an exact match?

Bramzor commented 5 years ago

I would advise to put full locales and nog languages in the array of options. Together with loose, you will in that case always get the full locale and will solve your issue:

parser.pick(["en-US", "nl-BE"], "en-GB,nl;q=0.5"

Should in this case indeed return en-US as language matches. Using split you can extract the language from the locale.

bamapookie commented 4 years ago

I added some tests for the readme examples and corrected the readme based on the results here: https://github.com/opentable/accept-language-parser/pull/35

FMCorz commented 3 years ago

I ran into specificity issues as well.

acceptLanguageParser.pick(['en-GB', 'es', 'en'], 'en')

The expected result, to me, would be en as it's a perfect match, but instead if returns en-GB.

alex-piccione commented 2 years ago
parser.pick(["en", "nl"], "en-GB,nl;q=0.5"

I think It is correct to return "nl" for this scenario.
"nl" and "en-GB" have the same priority (q=0.5), so why a non-matching locale should be preferred to a matching one?
The user expects "nl" or "en-GB", why give him "en" instead of something that is what they asks for? ("en" is also much more like en-US than en-GB in terms of date-time formats).
Typical Accept-Language values are:

"en-GB,nl" is like the first example replacing "fr" with "nl", so why it should provide "fr" if "en" or "de" are accepted (also within the same q in your scenario)?
In that scenario, the missing "en" seems to indicate it really doesn't want it.

bamapookie commented 2 years ago

I believe in this case, en-GB has a weight of 1. When the ;q= is missing, the q value is 1.

See here: https://developer.mozilla.org/en-US/docs/Glossary/Quality_values

Since this is a strict search, though, nl wins because that value is in the supported language array.

danjunger commented 2 years ago

pick does ignore quality though. if you look at the source, there's literally nothing in there that even looks at the quality number.

// en-GB: 0.2, en-US: 0.4
// this returns en-GB because it's the first match
parser.pick(['en-GB','fr-FR','en-US'], 'zh-CN,zh;q=0.8,en;q=0.6,en-US;q=0.4,en-GB;q=0.2')