在PHP中使用半角假名计算日语多字节字符串的长度

时间:2011-04-12 09:26:07

标签: php unicode character-encoding

所以我有一个UTF-8编码的字符串,可以包含全宽汉字,全角假名,半角假名,罗马字,数字或卡哇伊日语符号,如★或♥。

如果我想要长度,我使用mb_strlen(),并将每个长度计为1。这对大多数用途来说都没问题。

但是,我(有一个日本客户)被要求只计算半宽假名为0.5(为了文本字段的最大长度),因为显然这就是日本网站的做法。我这样做是使用mb_strwidth()将全宽计为2,将半宽计为1,然后我除以2。

然而,这个方法也将罗马字符计为1,所以像Chocアイス这样的东西会算作7 ..然后我除以2来计算汉字,我得到3.5。但我实际上想要5.5(罗马吉为4,半宽假名为1.5)。

//编辑: 更多信息:任何具有全部和半部的字符(甚至非假名)应该是全宽1和0.5半宽。例如,像¥、3@(这样的字符应该都是1,但像¥,3@(这样的字符应该都是0.5

// EXTRA EDIT:像☆和♥这样的符号应为1,但mb_strwidth / 2方法将它们返回为0.5

日本系统是否有标准方式计算字符串长度? 或者每个人都只是通过他们的字符串循环并计算与标准宽度规则不匹配的字符?

3 个答案:

答案 0 :(得分:3)

一种方法是将半角片假名转换为全宽,并从原始长度中减去宽度差:

$raw = 'Chocアイス';
$full = mb_convert_kana($raw, 'K');
$len = mb_strlen($raw) - (mb_strwidth($full) - mb_strwidth($raw))/2;
assert($len === 5.5);

<击>

然而,您确定您应该将基本拉丁字符视为全角?确实存在基本拉丁字符的全宽种类 - 也就是说Choc应该被视为与Choc相同吗?

通常,字符如&#34; A&#34;和&#34;ア&#34;宽度为1,但是&#34; A&#34;和&#34;ア&#34;宽度为2(这是mb_strwidth的作用)。我必须谨慎行事。


根据您的修改mb_strwidth(或mb_strwidth/2)完全符合您的要求。

答案 1 :(得分:0)

所以,我没有找到答案。

我通过逐字迭代修复它并检查每个字符并手动应用我的客户要求的计数规则。

答案 2 :(得分:0)

查看Perl的Unicode::GCString模块:它为所有Unicode提供正确的列,包括东亚的东西。

它是Unicode::LineBreak的基础组件,我发现它对于对亚洲脚本进行适当的文本分割绝对不可或缺。

正如您可能想象的那样,两者都是 Made in Japan™。  :)