【问题标题】:Calculating the length of a Japanese multibyte string with half-width kana in PHP在 PHP 中计算带有半角假名的日语多字节字符串的长度
【发布时间】:2011-08-03 17:35:07
【问题描述】:

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

如果我想要长度,我使用mb_strlen(),它会将这些长度中的每一个都计为 1。这对于大多数用途来说都很好。

但是,我被(一位日本客户)要求仅将半角假名计为 0.5(出于文本字段的最大长度的目的),因为显然日本网站就是这样做的。我使用mb_strwidth() 执行此操作,它将全角计为 2,将半角计为 1,然后我只需除以 2。

但是,这种方法也将罗马字字符计为 1,因此 Chocアイス 之类的值将计为 7 .. 然后我将除以 2 来计算汉字,我会得到 3.5。但我实际上想要 5.5(罗马字 4 + 3 个半角假名 1.5)。

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

// 额外编辑:像 ☆ 和 ♥ 这样的符号应该是 1,但是 mb_strwidth/2 方法将它们返回为 0.5

日本系统是否有一种标准的方法来计算字符串长度? 还是每个人都只是遍历他们的字符串并计算不符合标准宽度规则的字符?

【问题讨论】:

  • 我的自发想法是像往常一样使用mb_strlen,并减去Unicode代码点FF61和FF9F之间的字符出现次数。稍后我可能会解决这个问题......

标签: php unicode character-encoding


【解决方案1】:

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

它是Unicode::LineBreak 的基础组件,我发现它对于正确地对亚洲文字进行文本分割绝对必不可少。

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

【讨论】:

    【解决方案2】:

    所以,我没有找到答案。

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

    【讨论】:

      【解决方案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 相同?

      通常,“A”和“ア”等字符的宽度为 1,但“A”和“ア”的宽度为 2(mb_strwidth 就是这样做的)。我会小心翼翼地解决这个问题。


      鉴于您的编辑mb_strwidth(或mb_strwidth/2)完全符合您的要求。

      【讨论】:

      • 我真的应该澄清更多;但是符号(♥☆ 等)应该是 1,并且它们在 mb_strwidth/2 方法中返回 0.5。这一切都非常令人困惑,但我的问题是真正寻找这种类型的东西的“标准规则”是什么?还是我的客户只是随手编造? (他是一位非常成功且经验丰富的商人)。
      • 那些符号(♥☆)虽然不是全角的。至于标准规则,Unicode TR11 记录了字符如何分类为全角或半角。
      • 嗨,我知道根据我的代码它们不是全角的,但我被要求将它们计为 1 个长度。我的客户向我保证他的规则是标准的,并在一个流行的网站 (gnavi.co.jp) 上向我展示了一堆符合他规则的示例。我只是有点希望有一种比我根据他的解释手动编码规则更安全的方法。也许我需要用日语找到stackoverflow。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多