6

我有一个日文项目需要验证半角和全角日文字符,半角允许 14 个字符,全角允许 7 个字符。

有谁知道如何实现它?

现在在我的模型上

class Customer
   validates_length_of :name, :maximum => 14
end

不是一个好的选择

我目前使用的是 ror 2.3.5 全角和半角都可以

4

2 回答 2

11

首先,全角(全角)和半角(半角)的概念只存在于日语中的两种字符:

  • 罗马字符(即拉丁文)
  • 片假名字符

韩文也有类似的概念,但日文平假名和汉字都没有。

对于片假名,半角字符有自己的 Unicode 代码点,它们呈现为全角字符大小的一半,尽管它们在其他方面的形状相同。例子:

全角“ka”:カ<br> 半角“ka”:カ</p>

半角版本中不存在组合字符(即带有像 ガ 这样的变音符号);它们必须被编码为两个单独的字符:カ + ゙,这可能是您的任务中允许半角字符数量增加两倍的原因。(请注意,这些两个代码点的组合被视为组合字符,通常呈现为一个。)

对于罗马(拉丁)字符,通常的 ASCII 字符称为半角,但 Unicode 的日语代码范围(以及传统的日本特定字符集)为全角版本提供了单独的代码范围。例子:

全宽:L<br> 半宽:L

非 ASCII 拉丁语衍生字符(例如德语变音符号)不存在全角版本,重音版本也不存在。但是,它们确实存在于数字和一些标点符号中。

同样,平假名和汉字没有半角版本。

要检查字符是全角字符还是半角字符,请将代码点与相关代码范围进行比较。范围如下:

半角片假名:0xff61通过0xff9f
全角片假名:0x30a0通过0x30ff
半角罗马:0x21通过0x7e(这是 ASCII)
全角罗马:0xff01通过0xff60
平假名:0x3041通过0x309f
汉字(即统一表意文字范围):0x4e00通过0x9fcc

这是一个简单的 Ruby 程序,它基于每个字符执行检查:

# -*- coding: utf-8 -*-

def is_halfwidth_katakana(c)
  return (c.ord >= 0xff61 and c.ord <= 0xff9f)
end

def is_fullwidth_katakana(c)
  return (c.ord >= 0x30a0 and c.ord <= 0x30ff)
end

def is_halfwidth_roman(c)
  return (c.ord >= 0x21 and c.ord <= 0x7e)
end

def is_fullwidth_roman(c)
  return (c.ord >= 0xff01 and c.ord <= 0xff60)
end

def is_hiragana(c)
  return (c.ord >= 0x3041 and c.ord <= 0x309f)
end

def is_kanji(c)
  return (c.ord >= 0x4e00 and c.ord <= 0x9fcc)
end

text = "Hello World、こんにちは、半角カタカナ、全角カタカナ、fullwidth 0-9\n"

text.split("").each do |c|
  if is_halfwidth_katakana(c)
    type = "halfwidth katakana"
  elsif is_fullwidth_katakana(c)
    type = "fullwidth katakana"
  elsif is_halfwidth_roman(c)
    type = "halfwidth roman"
  elsif is_fullwidth_roman(c)
    type = "fullwidth roman"
  elsif is_hiragana(c)
    type = "hiragana"
  elsif is_kanji(c)
    type = "kanji"
  end

  printf("%c (%x) %s\n",c,c.ord,type)
end

补充说明

  1. 上面的代码范围是每种字符类型的官方 Unicode 范围(请参阅Unicode Fullwidth formsUnicode Hiragana)。这些包括某些旧/传统形式或特殊标点字符的全角/半角版本。如果您只需要 Web 表单中常用的字符(例如供人们输入他们的姓名),您可能需要稍微缩小范围。

  2. 建议:如果这是用于人们可以输入姓名的 Web 表单,您可能需要做的不仅仅是检查半角或全角。这在日本网站和注册表中非常常见,尤其是。对于银行,要求人们以纯半角(通常用于拉丁语)或纯全角(通常用于片假名)输入他们的姓名。不幸的是,这使得输入数据非常不方便。启用日文输入法后,拉丁字符通常以全角形式出现,然后 Web 表单将拒绝数据,因为它不是纯半角。而不是拒绝它,它应该自动转换它它需要的任何形式。您可以通过从一个代码范围转换到另一个代码范围来轻松实现这一点(只需添加相关常量),并使人们的生活更轻松。

于 2013-03-27T03:09:22.213 回答
5

下面的代码可能会让您越过界限,以尽可能最短的时间满足您迄今为止指定的确切要求。它使用Moji gem日语文档),它提供了许多方便的方法来确定日语字符串的内容。

它验证 a 中最多 14 个字符(name半角字符组成),以及names 中最多 7 个字符(包括包含半角和全角字符组合的名称,即即使存在一个全角字符)字符串中的宽度字符将使整个字符串被视为“全角”)。

class Customer 

  validates_length_of :name, :maximum => 14, 
    :if => Proc.new { |customer| half_width?(customer.name) }
  validates_length_of :name, :maximum => 7
    :unless => Proc.new { |customer| half_width?(customer.name) }

  def half_width?(string)
    Moji.type?(string, Moji::HAN_KATA)
  end

end

假设

  1. 系统内的数据编码为UTF-8,并以UTF-8的形式存储在数据库中;任何进一步必要的重新编码(例如将数据传递到遗留系统等)都在另一个模块中完成。
  2. 在将数据保存到数据库之前不会自动将半角字符转换为全角字符,即数据库中允许使用半角字符,原因可能是遗留系统集成、正确保存实际用户输入(!)和/或美学半角字符的值(!)
  3. 半角字符中的变音符号被视为它们自己的单独字符(即没有解析カ和゙被视为一个字符以确定字符串长度)
  4. 您指定的只有一个名称字段,而不是现在很常见 的四个(对于 surname,surname furigana,given name,given name furigana )。
于 2013-03-27T07:21:29.550 回答