Javascript 中的 stable/neutral/culture 不敏感语言环境?

A stable/neutral/culture insensitive locale in Javascript?

我希望在 Java 脚本中有一个稳定的、定义明确的排序顺序。

它可以是任何定义的语言环境,但重点是让代码说 "just some neutral sort order used here".

Java 和 C# 有它们的 Neutral culture and ROOT locales 已用于此目的。

The Mozilla documentation 至少不会立即出现 提供这样的选择。

我的答案是使用 "en"localeCompare

根据我的以下测试,en 产生了最一致的结果。

下面是一个使用 localeCompare 的例子:

"å".localeCompare("ä", "en")

据我了解und(未确定的缩写) (也许 en-US-u-va-posix)应该是对原始问题的更好回答,但 und 似乎在 Firefox(以及 en-US-u-va-posix 在 NodeJS 中的行为取决于 ICU 数据的存在)。

也许如果您没有遇到 Firefox 问题,请考虑 使用 und 或仅使用无参数形式来传达 区域设置不重要的想法

我在研究这个过程中学到的一些相关知识(将它们添加到这里以防其他人陷入同一个兔子洞):

  • This very popular answer about using localeCompare 有很多有用的评论。
  • this old post 我了解到有一些 "special" 语言环境。
  • 使用旧版浏览器可能没有希望。引用 Mozilla 文档:"In older implementations, which ignore the locales and options arguments, the locale and sort order used are entirely implementation dependent."
  • NodeJS 似乎在后台使用 Project ICU icu4c library 来实现语言环境相关的功能。
  • icu 项目在线 tool to experiment with collation orders
  • 普通的 sort() 与其他选项不同,但在我测试的平台上似乎很稳定。
  • 角色在旧版本的 NodeJS 上触发了某种错误
  • 我的节点安装中不存在语言环境数据 and installing the icu data 使得 localeCompare 有不同的行为。

这是我最终使用的测试代码:

const testArray=["Ă","Â","Î","Ș","Ț","A","i","I","S","T","é","e","ä","a","","","Д","д", "å", "z"]
const locales=["POSIX", "en-US-u-va-posix", "und", "en", "da", "ru"]

console.log(`${testArray.sort().join("")} sort()`)

console.log(`${testArray.sort((a,b)=>a.localeCompare(b)).join("")} localeCompare(x)`)

locales.forEach(locale => {
    const f = (a,b) => a.localeCompare(b, locale)
    try{
        console.log(`${testArray.sort(f).join("")} ${locale}`)
    } catch(e) {
        console.log(`${locale}: ${e}`)
    }
})

在我的 Mac 上,NodeJS 13.5.0 和 full-icu 我得到这个输出:

AISTaeizÂÎäåéĂȘȚДд sort()
aAĂÂåäeéiIÎSȘTȚzдД localeCompare(x)
aAĂÂåäeéiIÎSȘTȚzдД POSIX
AĂÂIÎSȘTȚaåäeéizдД en-US-u-va-posix
aAĂÂåäeéiIÎSȘTȚzдД und
aAĂÂåäeéiIÎSȘTȚzдД en
AaĂÂeéIiÎSȘTȚzäåДд da
дДaAĂÂåäeéiIÎSȘTȚz ru

节点 v12.14.0 得到相同的结果。

没有 NODE_ICU_DATA,v12.14.0 给出:

AISTaeizÂÎäåéĂȘȚДд sort()
aAĂÂåäeéiIÎSȘTȚzдД localeCompare(x)
aAĂÂåäeéiIÎSȘTȚzдД POSIX
aAĂÂåäeéiIÎSȘTȚzдД en-US-u-va-posix
aAĂÂåäeéiIÎSȘTȚzдД und
aAĂÂåäeéiIÎSȘTȚzдД en
aAĂÂåäeéiIÎSȘTȚzдД da
aAĂÂåäeéiIÎSȘTȚzдД ru

我的 Chrome 浏览器给出了这个结果:

AISTaeizÂÎäåéĂȘȚДд sort()
aAĂÂåäeéiIÎSȘTȚzдД localeCompare(x)
aAĂÂåäeéiIÎSȘTȚzдД POSIX
aAĂÂåäeéiIÎSȘTȚzдД en-US-u-va-posix
aAĂÂåäeéiIÎSȘTȚzдД und
aAĂÂåäeéiIÎSȘTȚzдД en
AaĂÂeéIiÎSȘTȚzäåДд da
дДaAĂÂåäeéiIÎSȘTȚz ru

我 mac 上的 Safari 浏览器除了 da:

aAĂÂeéiIÎSȘTȚzäåдД da

我的 mac 上的 Firefox 给出了这个有些不同的结果:

AISTaeizÂÎäåéĂȘȚДд sort()
aAĂÂeéiIÎSȘTȚzåäдД localeCompare(x)
aAĂÂeéiIÎSȘTȚzåäдД POSIX
aAĂÂåäeéiIÎSȘTȚzдД en-US-u-va-posix
aAĂÂeéiIÎSȘTȚzåäдД und
aAĂÂåäeéiIÎSȘTȚzдД en
AaĂÂeéIiÎSȘTȚzäåДд da
дДaAĂÂåäeéiIÎSȘTȚz ru

还有函数Intl.getCanonicalLocales。以下是我发现的一些测试结果:

$ node
> Intl.getCanonicalLocales("en-US-POSIX")
[ 'en-US-u-va-posix' ]
  • 最近 Chrome 它在 NodeJS 中的工作方式与上述相同
  • 在最近的 Safari 中,getCanonicalLocales 似乎接受几乎任何字符串,并且 returns 该字符串
  • 最新的 Firefox 与最新的 Safari 相同

正如@Bergi 上面指出的那样,在许多情况下,您可以只在字符串上使用 <,它定义明确且不区分文化。

假设使用某种自定义排序,像这样的东西会起作用:

["foo", "bar"].sort((a, b)=> a < b ? -1 : 1)

(在那种简单的情况下 .sort() 当然是等效的和更简单的。)