Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 13730] ファイルの概要

  • src/pkg/exp/locale/collate/maketables.go: このファイルは、Unicode Collation Algorithm (UCA) のデータと CLDR (Common Locale Data Repository) のデータから、Go言語のロケール固有の照合(ソート)テーブルと見本文字(exemplar characters)を生成するためのツールです。
  • src/pkg/exp/locale/collate/tables.go: このファイルは、maketables.goによって生成されるGo言語のソースコードの一部であり、照合テーブルの実装を含んでいます。今回のコミットでは、このファイルのコメントが更新されています。

コミット

commit 5a78e5ea4c3cd4d6029882a9e45c0c5506c2babb
Author: Marcel van Lohuizen <mpvl@golang.org>
Date:   Sat Sep 1 14:15:00 2012 +0200

    exp/locale/collate: Added functionality to parse and process LDML files
    for both locale-specific exemplar characters and tailorings to
    the collation table.
    Some specifices:
    - Moved stringSet to the beginning of the file and added some functionality
      to parse command line files.
    - openReader now modifies the input URL for localFiles to guarantee that
      any http source listed in the generated file is indeed this source.
    - Note that the implementation of the Tailoring API used by maketables.go
      is not yet checked in. So for now adding tailorings are simply no-ops.
    - The generated file of exemplar characters will be used somewhere else.
      Here is a snippet of how the body of the generated file looks like:

      type exemplarType int
      const (
              exCharacters exemplarType = iota
              exContractions
              exPunctuation
              exAuxiliary
              exCurrency
              exIndex
              exN
      )

      var exemplarCharacters = map[string][exN]string{
              "af": [exN]string{
                      0: "a á â b c d e é è ê ë f g h i î ï j k l m n o ô ö p q r s t u û v w x y z",
                      3: "á à â ä ã æ ç é è ê ë í ì î ï ó ò ô ö ú ù û ü ý",
                      4: "a b c d e f g h i j k l m n o p q r s t u v w x y z",
              },
              ...
      }

    R=r
    CC=golang-dev
    https://golang.org/cl/6501070

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/5a78e5ea4c3cd4d6029882a9e45c0c5506c2babb

元コミット内容

このコミットは、exp/locale/collate パッケージに、LDML (Locale Data Markup Language) ファイルを解析および処理する機能を追加します。これにより、ロケール固有の見本文字(exemplar characters)と、照合テーブルへのテーラリング(カスタマイズ)の両方をサポートします。

主な変更点は以下の通りです。

  • stringSetユーティリティがファイルの先頭に移動され、コマンドラインファイルの解析機能が追加されました。
  • openReader関数が、ローカルファイルの場合にHTTPソースのURLを修正するようになりました。これにより、生成されるファイルにリストされるHTTPソースが、実際にそのソースであることを保証します。
  • maketables.goで使用されるテーラリングAPIの実装はまだチェックインされていません。そのため、現時点ではテーラリングの追加は単なるno-op(何もしない操作)です。
  • 生成される見本文字のファイルは、他の場所で使用される予定です。コミットメッセージには、生成されるファイルの本体の抜粋が示されています。

変更の背景

このコミットの背景には、Go言語の国際化(i18n)および地域化(l10n)サポートの強化があります。特に、文字列のソート順序は言語や地域によって大きく異なるため、これを正確に処理するためには、Unicode Collation Algorithm (UCA) と、各ロケールに特化したカスタマイズ(テーラリング)データが必要です。

これまでのmaketables.goは、主にDUCET (Default Unicode Collation Element Table) から基本的な照合データを生成していましたが、より詳細なロケール固有のルール(見本文字や特定の言語のソート順の調整)を取り込むためには、CLDR (Common Locale Data Repository) のLDMLファイルを直接解析する機能が必要でした。

この変更により、Go言語のexp/locale/collateパッケージが、より包括的で正確なロケール固有の照合機能を提供するための基盤が構築されます。特に、CLDRデータを取り込むことで、世界中の多様な言語のソート要件に対応できるようになります。

前提知識の解説

このコミットを理解するためには、以下の概念について基本的な知識が必要です。

  1. Unicode Collation Algorithm (UCA):

    • Unicode Consortiumによって定義された、多言語テキストを適切にソートするためのアルゴリズムです。言語や地域によって文字のソート順が異なるため、UCAはこれらの違いを考慮した標準的なソート方法を提供します。
    • UCAは、各文字に「照合要素(collation element)」と呼ばれる重みを割り当てることで機能します。この重みは、プライマリ、セカンダリ、ターシャリなどのレベルに分かれており、それぞれ異なるソートの粒度(例:文字の基本形、アクセント、大文字・小文字)を表現します。
    • DUCET (Default Unicode Collation Element Table): UCAのデフォルトの照合要素テーブルです。allkeys.txtというファイル名で提供されることが多く、すべてのUnicode文字に対する基本的な照合重みが定義されています。
  2. CLDR (Common Locale Data Repository):

    • Unicode Consortiumが提供する、ロケール固有のデータ(日付、時刻、通貨、数値の書式、言語名、国名、ソート順など)の標準リポジトリです。
    • CLDRデータは、XML形式のLDML (Locale Data Markup Language) ファイルで構成されており、通常はZIPアーカイブ(例: core.zip)として配布されます。
    • CLDRには、各言語・地域に特化した照合ルール(テーラリング)や、その言語で使用される代表的な文字セット(見本文字)などの情報が含まれています。
  3. LDML (Locale Data Markup Language):

    • CLDRデータの基盤となるXMLベースのマークアップ言語です。ロケール固有の情報を構造化して表現するために使用されます。
    • 照合ルールはLDMLの<collation>要素内に定義され、見本文字は<exemplarCharacters>要素内に定義されます。
  4. Go言語のexp/locale/collateパッケージ:

    • Go言語の実験的なパッケージで、Unicodeの照合アルゴリズムをGoプログラムで利用するための機能を提供します。このパッケージは、文字列のソートや比較において、ロケール固有のルールを適用することを可能にします。
    • maketables.goは、このパッケージが使用するデータテーブルを生成するためのツールです。
  5. テーラリング (Tailoring):

    • UCAのデフォルトルールを特定の言語や地域の慣習に合わせてカスタマイズすることです。例えば、ドイツ語では「ä」が「a」と「e」の間にソートされるなど、言語固有の例外ルールを定義します。LDMLファイルにはこれらのテーラリング情報が含まれています。
  6. 見本文字 (Exemplar Characters):

    • 特定の言語やスクリプトで使用される代表的な文字のセットです。例えば、英語の見本文字はアルファベットのa-zなどです。LDMLファイルには、基本の見本文字、補助的な見本文字、句読点、通貨記号など、様々なカテゴリの見本文字が定義されています。

技術的詳細

このコミットは、maketables.goツールを大幅に拡張し、CLDRのLDMLファイルを直接処理できるようにすることで、Go言語の照合機能の精度と網羅性を向上させています。

  1. CLDR ZIPアーカイブの処理:

    • archive/zipパッケージが導入され、CLDRデータが配布されるcore.zipのようなZIPアーカイブを直接読み込めるようになりました。
    • openArchive関数が追加され、指定されたURL(またはローカルファイル)からZIPファイルをダウンロードし、その内容をメモリに読み込んでzip.Readerとして提供します。
  2. LDML XMLの解析:

    • encoding/xmlパッケージが導入され、LDMLファイルのXML構造をGoの構造体にマッピングして解析できるようになりました。
    • LDML, Attr, AttrValue, Collation, Rules, RuleElemなどのGo構造体が定義され、LDMLのXML要素と属性に対応しています。これにより、XMLデータをGoのオブジェクトとして簡単に操作できます。
    • decodeXML関数は、zip.FileからXMLを読み込み、対応するLDML構造体にデコードします。
  3. UCAデータソースの柔軟性向上:

    • --ducetフラグが--rootフラグに置き換えられ、DUCETデータソースとしてallkeys.txtだけでなく、allkeys_CLDR.txtを含むZIPファイルも指定できるようになりました。これにより、CLDRに準拠したUCAデータソースの利用が容易になります。
  4. 見本文字の抽出と生成:

    • parseMain関数が追加され、CLDRのmainディレクトリ内のXMLファイルを解析し、各ロケールの見本文字(<exemplarCharacters>要素)を抽出します。
    • 抽出された見本文字は、localeCharsというmap[string]charSets型の変数に格納されます。
    • printExemplarCharacters関数は、このlocaleCharsデータを使用して、Go言語のソースコードとしてexemplarCharactersマップを生成します。このマップは、ロケールごとに異なるカテゴリの見本文字(基本、収縮、句読点、補助、通貨、インデックス)を保持します。
  5. 照合テーラリングの処理:

    • parseCollation関数が追加され、CLDRのcollationディレクトリ内のXMLファイルを解析し、各ロケールに特化した照合テーラリングルールを抽出します。
    • LDMLの照合ルールは複雑な構造を持つため、RuleElem構造体とそのrewriteメソッドが、UnicodeエスケープシーケンスやXMLタグの正規化を行います。
    • insertTailoringおよびinsertCollation関数は、抽出されたテーラリングルールをbuild.Builder(照合テーブルを構築する内部構造)に挿入します。これにより、ロケール固有のソート順がGoの照合器に反映されます。
    • コミットメッセージにあるように、テーラリングAPIの実装はまだ完全ではないため、現時点では一部のテーラリングはno-opとして扱われますが、このコミットは将来的な完全なサポートのための基盤を築いています。
  6. コマンドラインフラグの拡張とstringSetの改善:

    • flagパッケージの利用が大幅に拡張され、--cldr, --short, --draft, --tags, --package, --tables, --exclude, --include, --typesといった新しいフラグが追加されました。これにより、生成されるテーブルの種類や対象ロケール、出力形式を細かく制御できるようになりました。
    • stringSet構造体と関連メソッド(flagStringSet, flagStringSetAllowAll, Set, add, values, contains, compact)が再設計され、より汎用的なコマンドライン引数のセット処理(カンマ区切りリストの解析、重複排除、ソート、許可された値の検証など)が可能になりました。これは、複数のテーブルやロケールを柔軟に指定するために不可欠な改善です。

コアとなるコードの変更箇所

主な変更はsrc/pkg/exp/locale/collate/maketables.goファイルに集中しています。

  • インポートの追加:
    import (
    	"archive/zip" // ZIPアーカイブの読み込み
    	"encoding/xml" // XMLの解析
    	"io/ioutil"    // ファイル読み込みユーティリティ
    	"unicode/utf8" // UTF-8文字列処理
    )
    
  • 新しいコマンドラインフラグの定義: root, cldr, test, localFiles, short, draft, tags, pkg, tables, exclude, include, typesといった多数のフラグが追加されました。
  • stringSetの実装の移動と拡張: ファイルの先頭に移動し、flag.Valueインターフェースを実装することで、コマンドラインフラグとして利用できるようになりました。flagStringSetflagStringSetAllowAllといったヘルパー関数も追加されています。
  • openReader関数の変更: localFilesフラグが設定されている場合、URLをローカルファイルパスに変換するロジックが追加されました。
  • openArchive関数の追加: ZIPアーカイブを開くための新しい関数です。
    func openArchive(url *string) *zip.Reader {
    	f, err := openReader(url)
    	failOnError(err)
    	buffer, err := ioutil.ReadAll(f)
    	f.Close()
    	failOnError(err)
    	archive, err := zip.NewReader(bytes.NewReader(buffer), int64(len(buffer)))
    	failOnError(err)
    	return archive
    }
    
  • parseUCA関数の変更: --rootフラグがZIPファイルを指す場合、その中のallkeys_CLDR.txtを読み込むように変更されました。
  • LDML XML構造体の定義: LDMLファイルのXML構造に対応するGoの構造体(LDML, Attr, AttrValue, Collation, Settings, Rules, RuleElemなど)が多数追加されました。
  • decodeXML関数の追加: XMLファイルをGo構造体にデコードします。
  • 見本文字関連の関数: charSets, localeChars, exemplarHeader, printExemplarCharacters, parseMain, parseCharactersといった見本文字の解析とGoコード生成のための関数が追加されました。
  • 照合テーラリング関連の関数: fileRe, parseCollation, lmap, cldrIndex, insertTailoring, insertCollationといった照合テーラリングの解析と適用を行う関数が追加されました。
  • main関数のロジック変更: 新しいフラグに基づいて、parseUCA, parseMain, parseCollationの呼び出しが条件付けされ、生成される出力もtablesフラグによって制御されるようになりました。

コアとなるコードの解説

このコミットの核心は、CLDRのLDMLファイルをGo言語の照合システムに統合するためのデータパイプラインを構築した点にあります。

  1. データソースの抽象化と拡張:

    • 以前はDUCETのallkeys.txtに限定されていたUCAデータソースが、--rootフラグによってZIPファイル内のallkeys_CLDR.txtもサポートするようになりました。
    • --cldrフラグの導入により、CLDRのcore.zipを直接指定できるようになり、世界中のロケールデータへのアクセスが可能になりました。
    • openArchive関数は、HTTPまたはローカルファイルシステムからZIPファイルを透過的に読み込む役割を担い、データ取得の柔軟性を高めています。
  2. LDML XMLの構造化された解析:

    • encoding/xmlパッケージと、LDMLのXMLスキーマに厳密に対応するGo構造体(LDML, Collation, Rules, RuleElemなど)の定義が、LDMLファイルの複雑な階層構造をGoプログラム内で扱いやすくしています。
    • decodeXML関数は、XMLデータをこれらのGo構造体にマッピングすることで、XMLのパースを簡素化し、データの整合性を保ちます。
  3. 見本文字の処理フロー:

    • parseMain関数は、CLDRのmainディレクトリにあるロケールXMLファイルから<exemplarCharacters>要素を特定し、その内容を抽出します。
    • parseCharacters関数は、抽出された見本文字の文字列(例: "[a b c {ch}]")を解析し、個々の文字や文字シーケンスのリストに変換します。この関数は、Unicodeエスケープや特殊な記号の処理も行います。
    • 最終的に、printExemplarCharacters関数が、これらの解析された見本文字データをGoのmap[string][exN]string形式のソースコードとして出力します。これにより、Goプログラム内でロケールごとの見本文字に簡単にアクセスできるようになります。
  4. 照合テーラリングの処理フロー:

    • parseCollation関数は、CLDRのcollationディレクトリにあるロケールXMLファイルから<collation>要素を特定し、その内容を抽出します。
    • 抽出された照合ルール(<rules>要素内)は、RuleElem構造体として表現されます。この構造体は、リセットポイント、コンテキスト、拡張、およびプライマリ/セカンダリ/ターシャリ/アイデンティティレベルでの照合要素の変更など、UCAの複雑なテーラリングルールをカプセル化します。
    • RuleElem.rewrite()メソッドは、XML内のUnicodeエスケープ(例: &#xXXXX;)や特定のタグ形式を正規化し、Goプログラムで扱いやすい文字列形式に変換します。
    • insertTailoringおよびinsertCollation関数は、これらの解析・正規化されたテーラリングルールをbuild.Builderに渡し、Goの照合器が使用する内部データ構造に組み込みます。これにより、特定のロケールにおける文字のソート順序が、CLDRの定義に従ってカスタマイズされます。
  5. stringSetの汎用化:

    • stringSetは、コマンドライン引数として渡されるカンマ区切りの文字列リスト(例: --tables=collate,chars)を効率的に処理するための汎用的なユーティリティとして再設計されました。
    • この改善により、ユーザーは生成したいテーブルの種類、含める/除外する言語、特定のデータタイプなどを柔軟に指定できるようになり、maketables.goの使いやすさと機能性が大幅に向上しました。

これらの変更は、Go言語がより堅牢で国際化に対応したアプリケーションを構築するための重要なステップであり、特に多言語環境での正確な文字列ソート機能の提供に貢献します。

関連リンク

参考にした情報源リンク