为什么 Encode::decode 与非拉丁字母区域设置在本地化 strftime 输出上爆炸?
Why does Encode::decode with non-latin letter locales blow up on localised strftime output?
在 Ubuntu 上使用 Perl 5.26.1 我在 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))
returns 20.33.C6D4
下。当解释为 Unicode 代码点时,这是“␠3월”("March",前导 space)。
在 de_DE.UTF-8
、strftime("%b", localtime(1552997524))
returns 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)';
在 Ubuntu 上使用 Perl 5.26.1 我在 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))
returns 20.33.C6D4
下。当解释为 Unicode 代码点时,这是“␠3월”("March",前导 space)。
在 de_DE.UTF-8
、strftime("%b", localtime(1552997524))
returns 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)';