【问题标题】:Get "list separator" character for any locale获取任何语言环境的“列表分隔符”字符
【发布时间】:2013-01-18 15:40:41
【问题描述】:

仅从客户端提供的区域设置标识符名称(字符串)开始,我如何或在哪里查找该区域设置的默认“列表分隔符”字符?

“列表分隔符”设置是许多不同类型的应用程序和编程语言在连接或拆分字符串和数组时可能用作默认分组字符的字符。这对于在电子表格程序中打开 CSV 文件尤其重要。虽然这通常是逗号“,”,但此默认字符可能会因机器的区域设置而异。它甚至可能因操作系统而异。

我对我自己的服务器环境不感兴趣。相反,我需要根据客户提供给我的语言环境标识符来了解更多关于客户的信息,因此我自己的服务器设置是无关紧要的。同样对于此解决方案,我无法更改此服务器上的区域设置以匹配整个当前进程的客户端作为查找此值的快捷方式。

如果这是在 ICU 库中定义的,我无法找到任何方法来使用 INTL extension 查找此值。

有什么提示吗?

【问题讨论】:

  • @Mark Ba​​ker:这个解决方案不能使用注册表——安全问题,希望有跨操作系统的解决方案。另外,我只想根据语言环境名称查找字符,而不是我自己的服务器计算机配置使用的字符。在那篇文章中,romeok 给出了猜测角色的好方法,但这仍然只是猜测。
  • 巧合的是,我目前正在使用尝试通过检查小数和数字分组分隔符来推断列表分隔符。但是在编程的世界里,恕我直言,仅仅基于一些完全不相关的值来假设一个值是危险的。
  • 当客户向您发送他们的语言环境时,您是否有办法在客户的机器上运行一些代码?比如说,在 Javascript 中,您可以与语言环境一起发送连接数组或格式化的日期对象,然后可以从中派生分隔符。
  • @Boris:当我说许多不同的编程语言都使用这个字符时,也许我说得太早了。无论系统设置如何,Javascript 在join() 中默认使用逗号,并且在数组上使用toLocaleString() 来发现该字符仅在 IE 中有效。此外,在我提供要下载的文件(如 csv)的情况下,那时我真的无法选择运行客户端脚本。

标签: php csv locale intl


【解决方案1】:

我不确定我的回答是否能满足您的要求,但我建议(尤其是当您不想更改服务器上的语言环境时)使用可以为您提供答案的函数:

据我所知 (and also Wikipedia's it seems) CSV 中的列表分隔符是逗号,除非语言环境的小数点是逗号,在这种情况下列表分隔符是分号。

因此,您可以使用以下命令获取使用逗号 (Unicode U+002C) 作为分隔符的所有语言环境的列表:

cd /usr/share/i18n/locales/
grep decimal_point.*2C *_* -l

然后您可以使用此列表来确定适当的列表分隔符:

function get_csv_list_separator($locale) {
    $locales_with_comma_separator =  "az_AZ be_BY bg_BG bs_BA ca_ES crh_UA cs_CZ da_DK de_AT de_BE de_DE de_LU el_CY el_GR es_AR es_BO es_CL es_CO es_CR es_EC es_ES es_PY es_UY es_VE et_EE eu_ES eu_ES@euro ff_SN fi_FI fr_BE fr_CA fr_FR fr_LU gl_ES hr_HR ht_HT hu_HU id_ID is_IS it_IT ka_GE kk_KZ ky_KG lt_LT lv_LV mg_MG mk_MK mn_MN nb_NO nl_AW nl_NL nn_NO pap_AN pl_PL pt_BR pt_PT ro_RO ru_RU ru_UA rw_RW se_NO sk_SK sl_SI sq_AL sq_MK sr_ME sr_RS sr_RS@latin sv_SE tg_TJ tr_TR tt_RU@iqtelif uk_UA vi_VN wo_SN");
    if (stripos($locales_with_comma_separator, $locale) !== false) {
        return ";";
    }
    return ",";
}

(语言环境列表取自我自己的Debian机器,我不知道列表的完整性)

如果您不想拥有这个静态的语言环境列表(尽管我假设这不会经常更改 那个),您当然可以使用上面的命令生成列表并缓存它。

最后一点,根据RFC4180 section 2.6,列表分隔符实际上永远不会改变,而是包含逗号的字段(因此这也意味着浮动数字,取决于语言环境)应该用双引号引起来。虽然(如上链接)没有多少人遵循 RFC 标准。

【讨论】:

  • @akrirk:谢谢。可能会奏效。我会尽快给您回复。我手头没有 Linux 系统来将语言环境设置文件与 Windows 进行比较。也许我可以挖一个或者只是设置一个虚拟机。由于您似乎已经有了一个使用分号的语言环境列表,这应该会有所帮助。使用列表分隔符,这是操作系统(可能只是 WIN)的错误。如果列用引号括起来,则无关紧要,因为实际的列/列表分隔符在某些客户端计算机上可能是分号。他们的操作系统解析 csv 文件并看不到分号字符,因此它只是假设整行是单列
  • 我不太明白操作系统与此有什么关系。 CSV 可能会被 MS Excel 等应用程序处理,不是吗?
  • MS Excel 在解析和打开 CSV 文件时取决于控制面板>区域和语言设置中定义的“列表分隔符”。如果 Windows 用户的“列表分隔符”定义为“;”与某些欧洲设置一样,它无法正确解析使用逗号的 CSV 文件。当然,您可以使用 Excel 向导“导入”一个 CSV 文件并手动指定逗号,但我希望避免让用户采取这些额外步骤来打开我的 CSV 文件。用户需要一个电子表格,如果他们不熟悉 Windows 来自行更正格式,他们会感到困惑。
【解决方案2】:

没有像“列表分隔符”这样的区域设置,它可能是特定于软件的,但我怀疑它是特定于用户的。

但是...您可以检测用户的语言环境并尝试匹配设置。

  1. 获取浏览器区域设置:$accept_lang = $_SERVER['HTTP_ACCEPT_LANGUAGE']; 这可能包含逗号分隔值的列表。一些浏览器虽然不发送这个。 more here...

  2. 接下来您可以使用setlocale(LC_ALL, $accept_lang); 并使用$locale_info = localeconv(); more here... 获取可用的区域设置

【讨论】:

  • 我实际上是在使用“Accept-Language”标头和 INTL 的 locale_accept_from_http 函数来获取客户端的确切语言环境,如果无法解决,则恢复为逗号.所以我有了他们的语言环境,现在我只需要列表分隔符。尽管如此,我还是不能使用setlocale,因为这会改变我自己服务器的区域设置并影响访问我网站的所有其他无关客户端。
猜你喜欢
  • 1970-01-01
  • 2011-09-25
  • 2023-03-05
  • 1970-01-01
  • 1970-01-01
  • 2023-03-21
  • 2022-12-10
  • 2023-04-09
相关资源
最近更新 更多