在带有 Perl 5.26.1 的 Ubuntu 上,我在使用 Dancer::Logger::Console 时遇到了以下问题。我已将此代码从 Dancer2::Core::Role::Logger 中取出.
为了运行它,您需要生成以下区域设置:
sudo locale-gen de_DE.UTF-8
sudo locale-gen ko_KR.UTF-8
此示例代码使用韩语区域设置,失败时不会显示错误消息。 $@
为空。
$ LC_ALL=ko_KR.UTF-8 perl -MPOSIX -MEncode -E 'eval {
say Encode::decode("UTF-8", strftime("%b", localtime))
};
say $@;
'
Wide character at -e line 1.
当使用德语语言环境运行时,它会成功(但会抛出宽字符警告,我们可以在此测试中忽略该警告)。
$ LC_ALL=de_DE.UTF-8 perl -MPOSIX -MEncode -E 'eval {
say Encode::decode("UTF-8", strftime("%b", localtime))
};
say $@;
'
Wide character in say at -e line 2.
M�r
%b
格式是将月份缩写为本地化单词(请参阅 http://strftime.net/ )。
如果我们不Encode::decode("UTF-8", ...)
,它就会起作用,上面的韩语版本会生成 3월
.
这是怎么回事?
最佳答案
在 ko_KR.UTF-8
下,strftime("%b", localtime(1552997524))
返回 20.33.C6D4
。当解释为 Unicode 代码点时,这是“␠3월”(“三月”,带前导空格)。
在 de_DE.UTF-8
下,strftime("%b", localtime(1552997524))
返回 4D.E4.72
。当解释为 Unicode 代码点时,这是“Mär”(“März”、“March”的缩写形式)。
所以看起来解码文本(Unicode 代码点)正在返回,这是完美的。剩下要做的就是对输出进行编码。
$ LC_ALL=ko_KR.UTF-8 perl -CSD -MPOSIX -e'CORE::say strftime("%b", localtime)'
3월
$ LC_ALL=de_DE.UTF-8 perl -CSD -MPOSIX -e'CORE::say strftime("%b", localtime)'
Mär
在程序中(而不是单行程序),您可以使用类似以下内容来代替 -CSD
:
use open ':std', ':encoding(UTF-8)';
关于perl - 为什么使用非拉丁字母语言环境的 Encode::decode 在本地化 strftime 输出上会崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55240390/