根据用户区域设置过滤字符串列表

时间:2017-11-16 12:23:23

标签: javascript angularjs internationalization

使用AngularJS 1.6处理JavaScript项目时,我有一个我想要过滤的字符串列表。例如,假设我的列表包含árbolcigüeña nido tubo

当用西班牙语过滤字符串时,如果我过滤了“u”,我会期望出现cigüeña tubo ,这是最自然的结果。西班牙人然而,德语并非如此 - 你和ü是不同的字母,因此德国人不希望在名单上看到cigüeñ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;
}

不幸的是,这不起作用。将“u”和“ü”与德语和西班牙语语言环境进行比较时,localeCompare函数返回相同的值,因此这不是答案。我已经查看了reference for the localeCompare method并尝试了使用和灵敏度选项,但它们似乎没有多大帮助。

我怎么能调整我的代码才能使用?有没有能够正确处理这个问题的图书馆?

2 个答案:

答案 0 :(得分:3)

我将通过代表用户代理的navigatorsrc)直接从浏览器获取用户的语言环境:

var language = navigator.language;

这将为我的案例language分配en-US用户浏览器的区域设置代码。我发现this site有助于查找区域代码以测试世界其他地区。

我的strFromLocale功能与您的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);
}

请注意Intl.Collatorsrc)行。该行将变音符号与变音符号的标准化字母进行比较,并检查给定语言的字母表中的位置差异。因此:

/* 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函数的一些测试:

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

答案 1 :(得分:1)

您可能正在寻找ECMA 6 Intl库。这将允许您根据区域设置调整排序顺序,例如:

sensitivity: '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 选项会自动排序,有/无变音符号。

{{1}}

然后,您可以在填充UI小部件之前将列表排序为正确的顺序。