Javascript 根据用户区域设置筛选字符串列表
在使用AngularJS 1.6进行JavaScript项目时,我有一个要筛选的字符串列表。例如,假设我的列表中包含阿尔波尔、库埃尼亚、尼多和图博 在用西班牙语过滤字符串时,如果我过滤“u”,我希望同时出现cigüeña和tubo,这对西班牙人来说是最自然的结果。然而,德语并非如此——u和ü是不同的字母,因此德国人不会希望看到cigüeña出现在名单上。因此,我正在寻找一种方法,使我的列表过滤了解用户的区域设置 我碰巧有一个包含很多变音符号的对象,例如:Javascript 根据用户区域设置筛选字符串列表,javascript,angularjs,internationalization,Javascript,Angularjs,Internationalization,在使用AngularJS 1.6进行JavaScript项目时,我有一个要筛选的字符串列表。例如,假设我的列表中包含阿尔波尔、库埃尼亚、尼多和图博 在用西班牙语过滤字符串时,如果我过滤“u”,我希望同时出现cigüeña和tubo,这对西班牙人来说是最自然的结果。然而,德语并非如此——u和ü是不同的字母,因此德国人不会希望看到cigüeña出现在名单上。因此,我正在寻找一种方法,使我的列表过滤了解用户的区域设置 我碰巧有一个包含很多变音符号的对象,例如: diacritics["á"] = "a
diacritics["á"] = "a";
diacritics["ü"] = "u";
// and so on...
这就是我的筛选代码的样子:
function matches(word, search) {
var cleanWord = removeDiacritics(word.toLowerCase());
var cleanSearch = removeDiacritics(search.toLowerCase());
return cleanWord.indexOf(cleanSearch) > -1;
}
function removeDiacritics(word) {
function match(a) {
return diacritics[a] || a;
}
return text.replace(/[^\u0000-\u007E]/g, match);
}
上面的代码只是删除了所有的发音符号,所以我想让它知道用户的语言环境。因此,我将match()函数更改为:
function match(a) {
if (diacritics[a] && a.localeCompare(diacritics[a] === 0) {
return diacritics[a];
}
return a;
}
不幸的是,这不起作用。localeCompare函数在将“u”和“ü”与德语和西班牙语地区进行比较时返回相同的值,因此这里的答案并非如此。我已经看过了,并尝试了使用和灵敏度选项,但它们在这里似乎没有多大帮助
我如何调整我的代码使其工作?是否有任何库可以为我正确处理此问题?您可能正在寻找ECMA 6库。这将允许您根据区域设置调整排序顺序,例如:
// in German, ä sorts with a
console.log(new Intl.Collator('de').compare('ä', 'z'));
// → a negative value
// in Swedish, ä sorts after z
console.log(new Intl.Collator('sv').compare('ä', 'z'));
// → a positive value
敏感度:'base'
选项将自动使用/不使用变音符号进行排序
// in German, ä has a as the base letter
console.log(new Intl.Collator('de', { sensitivity: 'base' }).compare('ä', 'a'));
// → 0
// in Swedish, ä and a are separate base letters
console.log(new Intl.Collator('sv', { sensitivity: 'base' }).compare('ä', 'a'));
// → a positive value
然后,您可以在填充UI小部件之前将列表按正确的顺序排序。我将通过
导航器
()直接从浏览器获取用户的区域设置,该对象表示用户代理:
var language = navigator.language;
这将分配语言
用户浏览器的区域设置代码,在我的例子中是en-US
。我发现找到地区代码有助于测试世界其他地区
MystrFromLocale
函数与您的removeDiacritics
函数相当:
function strFromLocale(str) {
function match(letter) {
function letterMatch(letter, normalizedLetter) {
var location = new Intl.Collator(language, {usage: 'search', sensitivity: 'base' }).compare(letter, normalizedLetter);
return (location == 0)
}
normalizedLetter = letter.normalize('NFD').replace(/[\u0300-\u036f]/gi, "")
if ( letterMatch(letter, normalizedLetter) ) {
return normalizedLetter;
} else {
return letter;
}
}
return str.replace(/[^\u0000-\u007E]/g, match);
}
var language = navigator.language; // en-US
strFromLocale("cigüeña");
>>> ciguena
var language = 'sv' // Swedish
strFromLocale("cigüeña");
>>> cigüena
var language = 'de' // German
strFromLocale("cigüeña");
>>> cigüena
var language = 'es-mx' // Spanish - Mexico
strFromLocale("cigüeña");
>>> cigueña
注意带有Intl.Collator
()的行。这一行将变音符号与变音符号的规范化字母进行比较,并检查给定语言的字母表是否存在位置差异。因此:
/* English */
new Intl.Collator('en-US', {usage: 'search', sensitivity: 'base' }).compare('u', 'ü');
>>> 0
/* Swedish */
new Intl.Collator('sv', {usage: 'search', sensitivity: 'base' }).compare('u', 'ü');
>>> -1
/* German */
new Intl.Collator('de', {usage: 'search', sensitivity: 'base' }).compare('u', 'ü');
>>> -1
正如您在letterMatch
函数中所看到的,当且仅当Intl.Collator
的结果为0
时,它才会返回true,这表明该语言字母表中的字母没有位置差异,这意味着可以安全地替换
下面是对strFromLocale
函数的一些测试:
function strFromLocale(str) {
function match(letter) {
function letterMatch(letter, normalizedLetter) {
var location = new Intl.Collator(language, {usage: 'search', sensitivity: 'base' }).compare(letter, normalizedLetter);
return (location == 0)
}
normalizedLetter = letter.normalize('NFD').replace(/[\u0300-\u036f]/gi, "")
if ( letterMatch(letter, normalizedLetter) ) {
return normalizedLetter;
} else {
return letter;
}
}
return str.replace(/[^\u0000-\u007E]/g, match);
}
var language = navigator.language; // en-US
strFromLocale("cigüeña");
>>> ciguena
var language = 'sv' // Swedish
strFromLocale("cigüeña");
>>> cigüena
var language = 'de' // German
strFromLocale("cigüeña");
>>> cigüena
var language = 'es-mx' // Spanish - Mexico
strFromLocale("cigüeña");
>>> cigueña
可悲的是,这不起作用。这与我在localeCompare()中提到的基本相同:当比较“u”和“u”时,西班牙语和德语的结果是相同的。Collator和localeCompare()都会出现这种情况,这并不奇怪,因为它们是同一个API的一部分。在阅读了Cole的回答后,我意识到我的方法和您的解决方案都缺少的是同时使用usage=“search”和sensition=“base”。一旦我们这样做了,整理者就会意识到西班牙语和德语的“u”和“u”之间的区别,如果我们不使用“用法”,这是不会发生的。我认为你的最后一个片段中有一个小错误。我认为“location”变量应该称为“language”。除此之外,它是完美的@哎呀,现在修好了