-
-
Notifications
You must be signed in to change notification settings - Fork 41
Description
Let's make the request
Accept-Language: zh, zh-CN;q=0.9
and
We provided backlist: ['zh-CN', 'zh-TW']
Coding:
const n = new require('negotiator')({ headers: { 'accept-language': 'zh, zh-CN;q=0.9' } })
n.language(['zh-CN', 'zh-TW'])Actual:
'zh-TW'
Expect:
'zh-CN' for sure
Analysis:
In the code, we get two comparing code snippets:
function getLanguagePriority(language, accepted, index) {
var priority = {
o: -1,
q: 0,
s: 0
};
for (var i = 0; i < accepted.length; i++) {
var spec = specify(language, accepted[i], index);
// this means `s`(the matching level) > `q`(the quality) > `o`(the index of accepted)
if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
priority = spec;
}
}
return priority;
}But when codes come here
function compareSpecs(a, b) {
// `q`(the quality) > `s`(the matching level) > `o`(the accepted index) > `i`(comparing index)
return (b.q - a.q) || (b.s - a.s) || (a.o - b.o) || (a.i - b.i) || 0;
}WHICH LEADS:
when comparing zh-CN to accepted zh, zh-CN;q=0.9,
we get a high matching level zh-CN with a lower quality weight 0.9
and then comparing zh-TW to accepted zh, zh-CN;q=0.9,
we get the the only half-matched zh with a high quality weight 1
finally, we use compareSpecs to select a higher quality language zh-TW rather than the lower but 100% percent matched one zh-CN
Read the rfc4647, it is not defined whether this expectation should be reasonable.
It only reads:
If the user cannot be sure which scheme is being used (or
if more than one might be applied to a given request), the user
SHOULD specify the most specific (largest number of subtags) range
first and then supply shorter prefixes later in the list to ensure
that filtering returns a complete set of tags.
So the accepted language with zh, zh-CN;q=0.9 is not comformed to this user decision.
But I think, the comparing logic should be the same ( q > s > o), such that
n.languages(['zh-CN', 'zh-HK']) // returns ['zh-CN', 'zh-HK']
n.languages(['zh-HK', 'zh-CN']) // returns ['zh-HK', 'zh-CN']