タイ文字の読み

タイの唄の歌詞をカナ書きする必要があって、パソコンで先ずローマ字表記できないかと考えました。タイ文字は13世紀に某大王により制定されたそうですが、文字が読み方の順に並んでいたら、かなり楽だったと思います。Excel2003 で、正規表現の使用が可能だと知り、試作したので紹介します。 "VBScript.RegExp" は通常の環境で使えると思いますが、そうでない場合 WEB 上で調べてください。読み方はカラオケ歌詞ガイドを参考にした我流です。末尾にタイ文字の読み ( Ko Kai ) を表示します。

タイ文字の特徴

筆者が知る範囲では、文字順でない読み方をする言語は他にないと思います。読み方には一定のルールがありますが、例外もかなり多く、母音省略の仕方もルールが一様ではありません。日本語同様に " 分かち書き " をしないのも困難さに輪をかけています。

日本語の『 雨 』 と 『 飴 』 はイントネーション( 抑揚 ) に違いがありますが、文字だけではそれが分かりません。しかしタイ文字には 声調記号も備えています。このような言語も他では知りません。几帳面に声調も付していながら、明解かつ一様のルールがないなど、正に、マイペンライの国民性が伺え興味深く思います。

図1.実行例

声調とよく似た ไม้ไต่คู้ ( Maitaikhu ) と呼ばれる記号( ็ ) のある ก็ の扱いも厄介です。これは特殊な発音 ( KO ) を持つ 1つの単語 ( 図1. 上の ) であったり、また 通常の単語の一部の子音 ( 図1. 下の ) であったりします。しかも1つの単語としても使用頻度が非常に高いです。

図のように左方にタイ文字のあるセルをアクティブにして実行するとアクティブセルを含む領域に結果が表示されます。2番の歌詞の間に空白セルがあると2番は対象外になります。作業領域内が全て空白セルでないと実行されません。結構時間がかかるので変換の過程を表示しないようにしています。

VB エディターでタイ文字を表示できないので、タイのキーボード文字を ユーザー関数 Key2Str を使って文字を作成しています。 タイ語等タイプ入力 を参照してください。全く同じ方法です。

概要とパターン

表1.文字名称
3631Paiyannoi
3632Sara A
3633Mai Han-Akat
3634Sara Aa
3635Sara Am
3636Sara I
3637Sara Ii
3638Sara Ue
3639Sara Uee
3640Sara U
3641Sara Uu
3642Phinthu
3648Sara E
3649Sara Ae
3650Sara O
3651Sara Ai Maimuan
3652Sara Ai Maimalai
3653Lakkhangyao
3654Maiyamok
3655Maitaikhu
3656Mai Ek
3657Mai Tho
3658Mai Tri
3659Mai Chattawa
3660Thanthakhat
3661Nikhahit
3662Yamakkan

概要

VBA プロシージャでは、先ず主な不規則単語の変換をし声調記号などを消去し、明らかな単語の境界をマークします。区切り記号として "{" と "}" 等の括弧を使うとオリジナルテキストに影響を与えるので、消去済みの 声調記号を使っています。

ก็ の文字は Paiyannoi の文字に替えて退避させ、子音の1つとして扱うようにしています。

ใกล้ ( 近い ) の単語があります。これは、( Sara Ai Maimuan )( Ko Kai )( Lo Ling )( Mai Tho ) と称される4文字で成り立っていて、順に( AI の音 )( K の音 )( L の音 )( マイトゥの声調 ) を意味しています。読み方は 指定の声調で KLAI ( クライ ) と発声することになります。AIKL ( アイクル ) ではありません。

表1.に子音以外の主な文字の名称と文字コードを示しました。名称は 「 挿入 」 → 「 記号と特殊文字 」 で表示された名前を使っています。

เxือ のパターン 即ち Sara E, ( x ) Sara Uee, O Ang の順に並んだ語句は x UA と読ませています。x は子音ですが、二重子音も含まれます。ここで言う二重子音とは例えば clock のように2つの文字で1文字のように発声する文字のことで以下のような例があります。Digraph と名付けた ”集まり” を使って二重子音を処理します。

กร, กล, กว, คร, คล, คว, ฅร, ฅล, ฅว, บร, บล, บว, ปร, ปล, ปว, ผร, ผล, ผว, พร, พล, พว, หญ, หม, หล, หน

パターン

[ I ] 〜 [ XXIII ] に 各パターン を列記します。パターン中に VBA では ”DC" の表記があります。これは Digraph ( 二重子音 ) で その後 Consonant ( 単独子音 ) で 検索置換することを意味します。

[ I ]… เ x ือ  [ Sara E, ( x ) Sara Uee, O Ang ]  読み… x UA 例 เรือ 船(ルア) เสือ 虎(スア)

[ II ] …เ x ีย  [ Sara E, ( x ) Sara Ii, Yo Yak ]  読み… x IA 例 เสีย เรียก

[ III ] …เ x าะ  [ Sara E, ( x ) Sara Aa, Sara A ]  読み… x O 例 เกาะ

[ IV ] … เ x ิ   読み…  x AA

[ V ] … เ x า   読み…  x AU

[ VI ] … เ x อ   読み… x UA

[ VII ] …เ x ะ,  แ x ะ   読み… x E

[ VIII ] … ไ x,  ใ x  読み… x AI

[ IX ] … x ัว   読み…   x UA

[ X ] … x อะ  読み… x A

[ XI ]… โ x ะ   読み… x O

[ XII ]… เ x,  แ x  読み…  x E

[ XIII ]… โ x  読み x O

[ XIV ]…x ร ร ม  読み…  x AM

[ XV ]… x ร ร 読み…  x N

[ XVI }… x ะ, x ั, x า 読み…  x A

[ XVII ]… x ิ,  x ี  読み…  x I

[ XVIII ]… x ึ, x ื,  x ุ, x ู 読み…   x U

[ XIX ]… x ำ  読み… x AM

[ XX ]… x อ   読み…  x O

[ XXI ]… 語尾 ง   読み…   NG

[ XXII ] …語尾 ด   読み…  T

[ XXII ] …語尾 บ   読み…  P



Dim myRange As Range, RegEx As Object, Digraph, Consonant
Sub readThai()
Dim Arr(15), Src, Rep      '  ====== [ ReadThai Ver. 3.2 ] =======
 Call SetmyRange
 '========= 不規則特殊発音の語
   w = " 0ib: ^k9b .sPj vy:dAK clf: vijvp Lkl9iN l@kp m;ux z[w,h l6-4kr Liu"
         w = Key2Str(w):      Src = Split(w)
   w = " ching chat yai angkit sadeng aroy sat sabai tawipu ponlamai sukapap si"
                              Rep = Split(w)
For i = 0 To UBound(Src): myRange.Replace what:=Src(i), replacement:=Mai_Ek & Rep(i) & Mai_Tho
Next
 Application.ScreenUpdating = False  '========== 画面更新 OFF
'====== タイ文字の例
    Mo_Ma = ChrW(3617): Yo_Yak = ChrW(3618): Ro_Rua = ChrW(3619): O_ang = ChrW(3629)
    Paiyannoi = ChrW(3631): Sara_A = ChrW(3632): Mai_Han_Akat = ChrW(3633): Sara_Aa = ChrW(3634):
    Sara_AM = ChrW(3635): sara_I = ChrW(3636): Sara_Ii = ChrW(3637): sara_Ue = ChrW(3638):
    Sara_Uee = ChrW(3639): Sara_U = ChrW(3640): Sara_Uu = ChrW(3641): Phinthu = ChrW(3642):
    Sara_E = ChrW(3648): Sara_Ae = ChrW(3649): Sara_O = ChrW(3650): Sara_Ai_Maimuan = ChrW(3651):
    Sara_Ai_Maimalai = ChrW(3652): Lakkhangyao = ChrW(3653): Maiyamok = ChrW(3654): Maitaikhu = ChrW(3655):
    Mai_Ek = ChrW(3656): Mai_Tho = ChrW(3657): Mai_Tri = ChrW(3658): Mai_Chattawa = ChrW(3659):
    Thanthakhat = ChrW(3660): Nikhahit = ChrW(3661): Yamakkan = ChrW(3662):
   
   Consonant = "([" & ChrW(3585) & "-" & ChrW(3631) & "])"  '=== 全子音

    myRange.Replace what:=Paiyannoi, replacement:="…"  '===Paiyannoi を…に変換
    myRange.Replace what:=ChrW(3585) & ChrW(3655), replacement:=Paiyannoi '=== Ko Kai & Maitaikhu を退避
   
  w = "di|d[|d;|8i|8[|8;|}i|}[|};|@i|@[|@;|xi|x[|x;|zi|z[|z;|ri|r[|r;|sP|s,|s[|so": w = Key2Str(w)
     Digraph = "((" & w & "))"  '==================== 二重子音の集合
  
 '  ==================声調消去 Phinthu の(文字chrw(3642)) も消去
 For i = 3655 To 3659:     myRange.Replace what:=ChrW(i), replacement:=""
 Next:
     myRange.Replace what:=Phinthu, replacement:=""
       
 ' ===="VBScript.RegExp" の使用開始
  Set RegEx = CreateObject("VBScript.RegExp")
  
'==無声(Thanthakhat)消去と共にタイ文字以外をMai_Ek と Mai_Tho で隔離
With RegEx
        .Pattern = Consonant & Thanthakhat        '==========無声消去
        .Global = True                 '== 文字列全体を検索するように設定
   For Each c In myRange:
       c.Value = .Replace(c.Value, Mai_Ek & Mai_Tho)
   Next
       .Pattern = "([^" & ChrW(3585) & "-" & ChrW(3673) & "]+)"
   For Each c In myRange:       c.Value = .Replace(c.Value, Mai_Ek & "$1" & Mai_Tho)
  Next
End With

 For Each c In myRange: c.Value = Mai_Tho & c.Value & Mai_Ek: Next
      ' [ I 〜 XXIII ] ============= 各パターン の列記 コメント、正規表現、置換文字の順
  Arr(1) = Array("[ I ]   例 船(ルア)", Sara_E, "DC", Sara_Uee, O_ang, "UA")
  Arr(2) = Array("[ II ]  例(シア)", Sara_E, "DC", Sara_Ii, Yo_Yak, "IA")
  Arr(3) = Array("[ III ] 例 島(コ)", Sara_E, "DC", Sara_Aa, Sara_A, "O")
  Arr(4) = Array("[ IV ]", Sara_E, "DC", sara_I, "Aa")
  Arr(5) = Array("[ V ] ", Sara_E, "DC", Sara_Aa, "AU")
  Arr(6) = Array("[ VI ]  TUA ", Sara_E, "DC", O_ang, "UR")
  Arr(7) = Array("[ VII ]) E", "[" & Sara_E & Sara_Ae & "]", "DC", Sara_A, "E")
  Arr(8) = Array("[ VIII ] maimalai", "[" & Sara_Ai_Maimalai & Sara_Ai_Maimuan & "]", "DC", "AI")
  Arr(9) = Array("[ XI ] HUA", "DC", Mai_Han_Akat & ChrW(3623), "UA")
  Arr(10) = Array("[ X ] AA", "DC", O_ang & Sara_A, "A")
  
 For i = 1 To 10:    Call RegExReplace(Arr(i)):      Next
 
      myRange.Replace what:=O_ang & Yo_Yak, replacement:=Yo_Yak
  
  Arr(1) = Array("[ XI ] OO", Sara_O, "DC", Sara_A, "o")
  Arr(2) = Array("[ XII ] E ", "[" & Sara_E & Sara_Ae & "]", "DC", "E")
  Arr(3) = Array("[ XIII ] o", Sara_O, "DC", "O")
  Arr(4) = Array("[ XIV ] rr", "DC", Ro_Rua & Ro_Rua & Mo_Ma, "am")
  Arr(5) = Array("[ XV ] rr2", "DC", Ro_Rua & Ro_Rua, "n")
  Arr(6) = Array("[ XVI ] vowel a]", "DC", "[" & Sara_A & "-" & Sara_Aa & "]", "a")
  Arr(7) = Array("[ XVII ]vowel i]", "DC", "[" & sara_I & Sara_Ii & "]", "i")
  Arr(8) = Array("[ XIII ]vowel u]", "DC", "[" & sara_Ue & "-" & Sara_Uu & "]", "u")
  Arr(9) = Array("[ XIX ]vowel am]", "DC", Sara_AM, "am")
  Arr(10) = Array("[ XX ] oang", "DC", O_ang, "o")
  Arr(11) = Array("[ XXI ] g ng", "([a-zA-Z]" & Mai_Tho & ")" & ChrW(3591), "NG")
  Arr(12) = Array("[ XXII ] d i", "([a-zA-Z]" & Mai_Tho & ")" & ChrW(3604), "T")
  Arr(13) = Array("[ XXIII ] b p", "([a-zA-Z]" & Mai_Tho & ")" & ChrW(3610), "P")

   For i = 1 To 13:    Call RegExReplace(Arr(i)):   Next
 
   '===Ho Hip (ChrW(3627) に続く文字により変化
       myRange.Replace what:=ChrW(3627) & Mo_Ma, replacement:="M"      ' HM
       myRange.Replace what:=ChrW(3627) & ChrW(3621), replacement:="L" ' HL
       myRange.Replace what:=ChrW(3627) & ChrW(3609), replacement:="N" ' HN
   '===子音が2つ続いている場合、途中に "O"を入れる
      RegEx.Pattern = Mai_Tho & Consonant & Consonant & Mai_Ek
  For Each c In myRange
       c.Value = RegEx.Replace(c.Value, Mai_Ek & "$1" & "O" & "$2" & Mai_Tho)
  Next
'==Paiyannoi の処理
    myRange.Replace what:=Mai_Tho & Paiyannoi & Mai_Ek, replacement:="ko"
    myRange.Replace what:=Paiyannoi, replacement:="k"
 '=== 末尾の b,d,g を p, t, ng に変換
    myRange.Replace what:=ChrW(3591) & Mai_Tho, replacement:="NG"
    myRange.Replace what:=ChrW(3604) & Mai_Tho, replacement:="T"
    myRange.Replace what:=ChrW(3610) & Mai_Tho, replacement:="P"
    myRange.Replace what:=ChrW(3598) & Mai_Tho, replacement:="T"
    myRange.Replace what:=Mai_Tho & Ro_Rua & Mai_Ek, replacement:="N"

'=== 全ての子音をアルファベット表示
  w = " K K K K T K G CH CH CH S N Y D T T T T N D T T T T N B P P F P F P M Y R R L L W S S S H R   H"
   Rep = Split(w)
  For i = 1 To UBound(Rep):        myRange.Replace what:=ChrW(3584 + i), replacement:=Rep(i)
  Next
       myRange.Replace what:=Mai_Ek, replacement:="":   myRange.Replace what:=Mai_Tho, replacement:=""
  For Each c In myRange:   c.Value = LCase(c.Value):  Next
  Application.ScreenUpdating = True
End Sub
Function Key2Str(st)
 '  ===== ここは typethai の記述と同じ
  w = " d - ] 8 } S : 0 C ^ + G P E D ` R < I f 9 5 m T o @ x z / r a 4 , p i A [ ? ; L" & _
     " K l s > v V O t y k e b u 7 n 6 &      ' g c F . w  q H j h U J N    Q " & Chr(34) & _
     " # $ % ( ) _ = ~ ": kAr = Split(w)
  For i = 1 To UBound(kAr):          st = Replace(st, kAr(i), ChrW(3584 + i))
  Next:          Key2Str = st
End Function
Sub Msg()
  MsgBox "左にタイ文字があり、作業領域全部が空のセルをアクティブにしてください": End
End Sub
Sub RegExReplace(Arr)
 '===== 先ず Digraph で検索置換、続いて Consonant
    n = UBound(Arr): b = "": w = Arr(n):
 If InStr(w, ChrW(3657)) Then Else w = ChrW(3656) & "$1" & Arr(n) & ChrW(3657)
       For i = 1 To n - 1:     b = b & Arr(i):        Next
  If InStr(b, "DC") Then
     RegEx.Pattern = Replace(b, "DC", Digraph)
          For Each c In myRange:    c.Value = RegEx.Replace(c.Value, w)
          Next
     RegEx.Pattern = Replace(b, "DC", Consonant)
          For Each c In myRange:    c.Value = RegEx.Replace(c.Value, w)
          Next:                 Exit Sub
  End If
      RegEx.Pattern = b
        For Each c In myRange:    c.Value = RegEx.Replace(c.Value, w)
        Next
End Sub
Sub SetmyRange()
 If ActiveCell.Column = 1 Then Msg
     Set c = ActiveCell.Offset(0, -1):  If c.Value = "" Then Msg
     Set a = c.End(xlUp): Set b = c.End(xlDown): If b.Row > 20000 Then Set b = c
     Set c = Range(a, b): Set myRange = Range(a.Range("b1"), b.Range("b1"))
 If WorksheetFunction.CountA(myRange) > 0 Or WorksheetFunction.CountA(c) = 0 Then Msg
    c.Copy a.Range("b1")
End Sub


余録

タイ文字、正規表現、VBA コード いずれも暗号のようなもので取っ付き難いです。外国人からみれば日本語の方がはるかに厄介だと思います。”未曾有” などの読み方には明快なルールがなく、コンピューターで読ませて 100 % 完全なものにするには莫大な容量で個々の単語などを登録しないといけないと思います。ここで扱った方法では ざっと 3 〜 40 % 位でしょうか。

コウウィコウカイ

間違いがあるかもしれません。未校正
ก เอ๋ย ก ไก่
ข ไข่ ในเล้า
ฃ ฃวด ของเรา
ค ควาย เข้านา
ฅ คน ขึงขัง
ฆ ระฆัง ข้างฟา
ง งู ใจกล้า
จ จาน ใช้ดี
ฉ ฉิ่ง ตีดัง
ช ช้าง วิ่งหนี
ซ โซ่ ล่ามที
ฌ เฌอ คู่กัน
ญ หญิง โสภา
ฎ ชฎา สวมพลัน
ฏ ปฏัก หุนหัน
ฐ ฐาน เข้ามารอง
ฑ มณโฑ หน้าขาว
ฒ ผู้เฒ่า เดินย่อง
ณ เณร ไม่มอง
ด เด็ก ต้องนิมนต์
ต เต่า หลังตุง
ถ ถุง แบกขน
ท ทหาร อดทน
ธ ธง คนนิยม
น หนู ขวักไขว่
บ ใบไม้ ทับถม
ป ปลา ตากลม
ผ ผึ้ ทำรัง
ฝ ฝา ทนทาน
พ พาน วางตั้ง
ฟ ฟัน สะอาดจัง
ภ สำเภา กางใบ
ม ม้าคึกคัก
ย ยักษ์ เขี้ยวใหญ่
ร เรือ พายไป
ล ลิง ไต่ราว
ว แหวน ลงยา
ศ ศาลา เงียบเหงา
ษ ฤาษี หนวดยาว
ส เสือ ดาวคะนอง
ห หีบ ใส่ผ้า
ฬ จุฬา ท่าผยอง
อ อ่าง เนืองนอง
ฮ นกฮูก ตาโต
 

このサイトで扱った項目