カスタム・ロケールの作成
この例では、カスタム・テーブルでカスタム・ロケールを作成するためのテンプレートを提供します。このカスタム・テーブルでは、EBCDIC (米国で使用される一般的な形式) と Latin-1 (ISO-8859–1) の間の変換を実行します。詳細は、各クラスのドキュメントを参照してください。
その他のすべてのテーブルについては、最初に、文字のマッピングの定義を取得する必要があります。この例では、http://source.icu-project.orgOpens in a new tab (International Components for Unicode) の Web サイトのデータ・ファイルを使用します。該当するデータ・ファイルOpens in a new tabは、シャープ記号 (#) で始まるコメント行の後に、以下の形式の一連の変換定義行が続く、テキスト・ファイルです。
ファイルの抜粋を以下に示します。
#
#UNICODE EBCDIC_US
#_______ _________
<U0000> \x00 |0
<U0001> \x01 |0
<U0002> \x02 |0
<U0003> \x03 |0
<U0004> \x37 |0
<U0005> \x2D |0
...
これらの行では、Unicode 文字 Uaaaa が EBCDIC 文字の \xbb にマッピングされることを示しています (ここで aaaa および bb は 16 進数の表現です)。このテーブルは逆変換が可能であり、EBCDIC 文字の \xbb を Unicode 文字の Uaaaa に再マッピングすることができると仮定しています。これにより、1 回のスキャンで、同じデータ・ファイルから両側 (つまり EBCDIC-to-Latin1 および Latin1-to-EBCDIC) を作成することができます。Unicode の範囲は 0 ~ 255 のみなので、これは実際には Latin-1 テーブルになります。
このプロセスでは、最初に SubTable オブジェクトを作成し、次に Table を作成し、最後に Locale を作成します。最初の手順として、このプロセスでは 2 つの SubTables オブジェクトを作成し、Name および Type プロパティを初期化して、定義ファイルから読み込んだデータで FromTo マッピング配列を埋めます。
SubTable の名前の形式は、Type–FromEncoding–ToEncoding です。通常の I/O 変換の Type は "XLT" であるので、SubTable の名前は XLT-yEBCDIC-Latin1 および XLT-yLatin1-EBCDIC になります。
以下のコードで SubTables オブジェクトを作成します。わかりやすくするために、ここでは省略していますが、実際のプログラムでは、何度もコードの整合性チェックが行われます。この例では、このサンプル・コードを何度も実行できるように、既存の以前のバージョンの同じオブジェクト (SubTables、Tables および Locales) を削除しています。厳密には、クラス・メソッド Exists() を使用して以前のオブジェクトの存在をチェックし、既に存在する場合は、別の処理を実行する必要があります。
// Names for the new SubTables (save for later)
Set nam1 = "XLT-Latin1-yEBCDIC"
Set nam2 = "XLT-yEBCDIC-Latin1"
// Delete existing SubTables instances with same ids
Do ##class(Config.NLS.SubTables).Delete(nam1)
Do ##class(Config.NLS.SubTables).Delete(nam2)
// Create two SubTable objects
Set sub1 = ##class(Config.NLS.SubTables).%New()
Set sub2 = ##class(Config.NLS.SubTables).%New()
// Set Name and Description
Set sub1.Name = nam1
Set sub1.Description = "ICU Latin-1->EBCDIC sub-table"
Set sub2.Name = nam2
Set sub2.Description = "ICU EBCDIC ->Latin-1 sub-table"
SubTables には、マルチバイトの変換を実行するかどうかを示す小さな整数である、type プロパティが含まれます。この例では、type は、シングルバイト・マッピングを示す 0 に設定されています。データ・ファイルに定義されていないコード・ポイント (文字) がそれ自体にマッピングされるように、このマッピングは初期化されています。
// Set Type (single-to-single)
Set sub1.Type = 0
Set sub2.Type = 0
// Initialize FromTo arrays
For i = 0 : 1 : 255
{
Do sub1.FromTo.SetAt(i, i)
Do sub2.FromTo.SetAt(i, i)
}
次に、アプリケーションがファイルを読み込みます。ファイルの定義が、既定のマッピングとして設定された定義をオーバーライドします。$ZHEX() 関数により、コードが 16 進数から 10 進数に変換されます。
// Assume file is in the mgr directory
Set file = "glibc-EBCDIC_US-2.1.2.ucm"
// Set EOF exit trap
Set $ZTRAP = "EOF"
// Make that file the default device
Open file
Use file
For
{
Read x
If x?1"<U"4AN1">".E
{
Set uni = $ZHEX($E(x,3,6)),ebcdic = $ZHEX($E(x,12,13))
Do sub1.FromTo.SetAt(ebcdic,uni)
Do sub2.FromTo.SetAt(uni,ebcdic)
}
}
EOF // No further data
Set $ZT = ""
Close file
// Save SubTable objects
Do sub1.%Save()
Do sub2.%Save()
これで文字のマッピングは完了です。次に、定義したばかりの SubTables オブジェクトを参照する Table オブジェクトを作成します。Table オブジェクトは実際には SubTables の記述子であり、プロパティはわずかしかありません。以下のコードによって、この 2 つが関連付けられます。
// Delete existing Tables instances with same ids
Do ##class(Config.NLS.SubTables).Delete("XLT", "Latin1", "yEBCDIC")
Do ##class(Config.NLS.SubTables).Delete("XLT", "yEBCDIC", "Latin1")
// Create two Table objects
Set tab1 = ##class(Config.NLS.Tables).%New()
Set tab2 = ##class(Config.NLS.Tables).%New()
// Set description
Set tab1.Description = "ICU loaded Latin-1 -> EBCDIC table"
Set tab2.Description = "ICU generated EBCDIC -> Latin-1 table"
// Set From/To encodings
Set tab1.NameFrom = "Latin1"
Set tab1.NameTo = "yEBCDIC"
Set tab2.NameFrom = "yEBCDIC"
Set tab2.NameTo = "Latin1"
// Set SubTable
Set tab1.SubTableName = nam1
Set tab2.SubTableName = nam2
// Set Type
Set tab1.Type = "XLT"
Set tab2.Type = "XLT"
// Set Default Action
// 1 = Replace with replacement value
Set tab1.XLTDefaultAction = 1
Set tab2.XLTDefaultAction = 1
// Set Replacement value of "?"
Set tab1.XLTReplacementValue = $ASCII("?")
Set tab2.XLTReplacementValue = $ASCII("?")
// Set Reversibility
// 1 = Reversible
// 2 = Generated
Set tab1.XLTReversibility = 1
Set tab2.XLTReversibility = 2
// Set Translation Type
// 0 = non-modal to non-modal
Set tab1.XLTType = 0
Set tab2.XLTType = 0
// Save Table objects
Do tab1.%Save()
Do tab2.%Save()
Tables が定義されたら、構築の最後の手順として、新しいテーブルを組み込むロケール・オブジェクトの定義を行います。アプリケーションで、空の Locale オブジェクトを作成し、各プロパティを埋め込みます。これは、Tables および SubTables の場合と同様です。ただし、Locale の場合はより大きく複雑です。このような単純な変更を行う最も簡単な方法は、既存のロケールをコピーして、必要箇所のみを変更することです。このプロセスでは、ソース・ロケールとして enu8 を使用し、yen8 という新しい名前を付けます。イニシャル y によって、これがカスタム・ロケールであることが明確になり、アップグレード時に削除されなくなります。
// Delete existing Locales instance with the same id
Do ##class(Config.NLS.Locales).Delete("yen8")
// Open source locale
Set oldloc = ##class(Config.NLS.Locales).%OpenId("enu8")
// Create clone
Set newloc = oldloc.%ConstructClone()
// Set new Name and Description
Set newloc.Name = "yen8"
Set newloc.Description = "New locale with EBCDIC table"
ロケールが適切に設定されると、プロセスでは、起動時にロードされる I/O テーブルのリストに EBCDIC テーブルを追加します。これは、以下のように、配列プロパティ XLTTables にノードを挿入することによって行われます。
XLTTables(<TableName>) = <components>
-
tableName により、このロケールの入力テーブルと出力テーブルのペアが特定されます。
この名前は y で始まる必要はないので、EBCDIC を使用します。
-
components は、以下のような 4 項目のリストです。
-
入力 “From” のエンコーディング
-
入力 “To” のエンコーディング
-
出力 “From” のエンコーディング
-
出力 “To” のエンコーディング
以下のコードで、使用可能なロケールのリストにテーブルを追加します。
// Add new table to locale
Set component = $LISTBUILD("yEBCDIC", "Latin1", "Latin1", "yEBCDIC")
Do newloc.XLTTables.SetAt(component, "EBCDIC")
InterSystems IRIS でロケールを使用できるようにするには、その内部形式にコンパイルする必要があります。これは、ロケールの検証と呼ばれることもあります。IsValid() クラス・メソッドは、詳細な分析を行い、ロケールが適切に定義されていない場合、人間が読むことのできるメッセージと共に、2 つの配列を返します。1 つはエラーの配列、もう 1 つは警告の配列です。
// Check locale consistency
If '##class(Config.NLS.Locales).IsValid("yen8", .Errors, .Warns)
{
Write !,"Errors: "
ZWrite Errors
Write !,"Warnings: "
ZWrite Warns
Quit
}
// Compile new locale
Set status = ##class(Config.NLS.Locales).Compile("yen8")
If (##class(%SYSTEM.Status).IsError(status))
{
Do $System.OBJ.DisplayError(status)
}
Else
{
Write !,"Locale yen8 successfully created."
}