UTF-8のベトナム語から声調記号を落す

概要

ベトナム語文字コードは、最近は UTF-8 へ収束しつつあるようだベトナム語正書法は、アルファベット+声調記号である。だが、携帯電話やチャットなどの非公式の文章では、声調記号を省略することも多い。このプログラムは、声調記号付きのベトナム語 UTF-8 文字列から、声調記号を落としてプレーンなアルファベットにする。

使い方

ソースコードを utf8vn_converter.rb という名前で保存。

require ' utf8vn_converter'

UTF8VNConverter.toascii([ベトナム語 UTF-8 文字列]) # => プレーンアルファベット

これだけ。

UTF8VNConverter.toascii("phát triển") # => phat trien

ソースコード

class UTF8VNConverter

  @@map_source =<<EOS
A       0041
A       00C1
A       00C0
A       1EA2
A       00C3
A       1EA0
a       0061
a       00E1
a       00E0
a       1EA3
a       00E3
a       1EA1
A       0102
A       1EAE
A       1EB0
A       1EB2
A       1EB4
A       1EB6
a       0103
a       1EAF
a       1EB1
a       1EB3
a       1EB5
a       1EB7
A       00C2
A       1EA4
A       1EA6
A       1EA8
A       1EAA
A       1EAC
a       00E2
a       1EA5
a       1EA7
a       1EA9
a       1EAB
a       1EAD
E       0045
E       00C9
E       00C8
E       1EBA
E       1EBC
E       1EB8
e       0065
e       00E9
e       00E8
e       1EBB
e       1EBD
e       1EB9
E       00CA
E       1EBE
E       1EC0
E       1EC2
E       1EC4
E       1EC6
e       00EA
e       1EBF
e       1EC1
e       1EC3
e       1EC5
e       1EC7
I       0049
I       00CD
I       00CC
I       1EC8
I       0128
I       1ECA
i       0069
i       00ED
i       00EC
i       1EC9
i       0129
i       1ECB
O       004F
O       00D3
O       00D2
O       1ECE
O       00D5
O       1ECC
o       006F
o       00F3
o       00F2
o       1ECF
o       00F5
o       1ECD
O       00D4
O       1ED0
O       1ED2
O       1ED4
O       1ED6
O       1ED8
o       00F4
o       1ED1
o       1ED3
o       1ED5
o       1ED7
o       1ED9
O       01A0
O       1EDA
O       1EDC
O       1EDE
O       1EE0
O       1EE2
o       01A1
o       1EDB
o       1EDD
o       1EDF
o       1EE1
o       1EE3
U       0055
U       00DA
U       00D9
U       1EE6
U       0168
U       1EE4
u       0075
u       00FA
u       00F9
u       1EE7
u       0169
u       1EE5
U       01AF
U       1EE8
U       1EEA
U       1EEC
U       1EEE
U       1EF0
u       01B0
u       1EE9
u       1EEB
u       1EED
u       1EEF
u       1EF1
Y       0059
Y       00DD
Y       1EF2
Y       1EF6
Y       1EF8
Y       1EF4
y       0079
y       00FD
y       1EF3
y       1EF7
y       1EF9
y       1EF5
D       0110
d       0111
EOS

  @@instance = nil
  @map = nil

  def load_map
    @map = {}
    @@map_source.each do |line|
      ch, u = line.chomp.split(/\t/)
      uc = u.hex
      u8 = ucs2_to_utf8(uc)
      @map[u8] = ch
    end
  end

  def ucs2_to_utf8(c)
    raise if c < 0
    return sprintf("%c", c) if c <= 0x7F
    if c <= 0x07FF
        c1 = 0b1100_0000 | (c >> 6)
        c2 = 0b1000_0000 | (c & 0b111111)
        return sprintf("%c%c", c1, c2)
    end
    if c <= 0xFFFF
        c1 = 0b1110_0000 | (c >> 12)
        c2 = 0b1000_0000 | ((c >> 6) & 0b111111)
        c3 = 0b1000_0000 | (c & 0b111111)
        return sprintf("%c%c%c", c1, c2, c3)
    end
    raise
  end

  def utf8_to_ascii(ws)
    ws.split(//u).map { |w| @map[w] || w }.join('')
  end


  def initialize
    load_map
  end

  def self.instance
    unless @@instance
      @@instance = UTF8VNConverter.new
    end
    @@instance
  end

  def self.toascii(ws)
    instance.utf8_to_ascii(ws)
  end

end