7 : 11 LRM文字, RLM文字, <bdi>

← 7‒10 p↑ もくじ i 7‒12 n →

[Unicode] 双方向アルゴリズム境界における句読点

2003年 3月12日
記事ID d30312

RLM文字(HTMLでは &rlm;)は、書式方向「右から左」のゼロ幅文字だ(幅がゼロなので、書いてあっても目には見えない)。 これは書式方向制御文字(ここから「右から左」にしろ、というたぐい)ではない。 どういうときに使うのだろうか。

ヘブライ語の例

例えば、「こんにちは!」という意味のヘブライ語「シャローム!」の最後につける感嘆符(びっくりマーク)について考える。 SHAを表す ש U+05E9, Lを表す ל U+05DC, Oを表す ו U+05D5, Mを表す ם U+05DD をこの論理的順序で並べて、最後に感嘆符 U+0021 をつけるとする。

バイナリー (UTF-16 BE)
05 E9 05 DC 05 D5 05 DD 00 21

大域的な書式方向が左から右になっているなかにこのコードを書くと、期待通りの効果が得られないだろう。

ヘブライ文字の部分はちゃんと右から左につながるが、感嘆符がヘブライ語の行頭(いちばん右)に来てしまう。 パーサが間違っているというより、上のコードがそれだけでは、あいまいだからだ。

どこがあいまいか?

この現象は、双方向アルゴリズムが作用する境界があいまいなために発生する。 パーサは、左から右へ進む文字なかで、U+05E9 に出会う。 これはヘブライ語の文字で右から左に結合すべきことが定められているので、ここから「右から左」ブロックになる。 U+05DC, U+05D5, U+05DD まで4文字を読み込んだあと(ここまではヘブライ文字)、感嘆符を発見する。 感嘆符のあとでは、ふたたび左から右へ進む文字が並んでいる。 — 「右から左」ブロックの最初の文字が U+05E9 であること、 U+05DC, U+05D5, U+05DD までの4文字は「右から左」ブロックに属すること、 感嘆符より後ろが「左から右」ブロックに属することは、確定的だが、 感嘆符そのものがどちらのブロックに属するかが、ハッキリしない。 特殊扱いすべきブロックに属する証拠がないので、パーサは、感嘆符をデフォルト扱いするだろう。 つまり「右から左」ブロックに含めないようにするだろう。

感嘆符がどっちのブロックに属するのか、形式的に判断する方法はない。 例えば、「ヘブライ語のあいさつはシャローム! 覚えておけ」と言うとき、 「ヘブライ語のあいさつはシャローム」ということを力説しているのか、 それとも「シャローム!」の感嘆符まで含めて引用しているのかハッキリしない。

感嘆符でなく、ピリオドや疑問符のようなほかの句読点でも、同じことが起きる。 HTMLであれば、dir属性を使って方向を強制することもできるが、プレインテキストを含むUnicode一般では、 dir属性のような上位の制御が利用できるとは限らないから、HTMLのdir属性はユニコードのレイヤにおける本質的な解決法ではない。

言い換えれば、ヘブライ語の部分が感嘆符でまだ終わりでないことがハッキリしているなら、 パーサは迷わず感嘆符を「右から左」ブロックに含める。 実際、「シャローム! シャローム!」と2回、繰り返して書けば、1つめの感嘆符はヘブライ語の一部と認識され、 正しい位置にくる。観察しやすくするため、2つめの感嘆符を疑問符に変えて調べてみよう。 「シャローム! シャローム?」

感嘆符は期待通りの位置 — ひとつめ(右側)のシャロームのうしろ(左) — に来るが、 疑問符は期待通りの位置 — ふたつめ(左側)のシャロームのうしろ(左) — に来ないで、 見かけ上、ヘブライ語部分の行頭(いちばん右)に現れるだろう。 これは「シャローム! シャローム」でヘブライ語ブロックが終了して、「?」はヘブライ語ブロックに続く次のブロックに属すると認識されたためだ。

幅なしRLM文字

以上から分かるように、「シャローム」につづく句読点(感嘆符、疑問符、ピリオドなど)もヘブライ語の部分に属することを明示するには、 句読点がブロックの境目にならないよう、句読点のあとでも、まだまだ右から左へ進む文字が続いているようにすれば良い。 実際にヘブライ語文がまだまだ続いていれば、何もしなくても良い。 実際には「シャローム!」で終わりにしたい場合、ユニコード的解決法としては、 感嘆符のうしろに「見えないヘブライ文字」があるようにすれば良い。 これが幅なしRLM文字 U+200F であり、 ヘブライ語に限らず、アラビア語での同様な問題を解決するのに使うことができる。 幅なし(zero-width)なので、このコードポイントは論理的に(バイナリーで)のみ存在し、表示上は見えない。

バイナリー (UTF-16 BE)
05 E9 05 DC 05 D5 05 DD 00 21 20 0F

逆に、感嘆符がヘブライ語に属さないことを明示的に示す一つの方法として、 感嘆符の前に幅なしLRM文字 U+200E を置くことも考えられる。

RLM文字は、HTMLでは、&rlm; として参照することもできる。

<!ENTITY lrm     CDATA "&#8206;" -- left-to-right mark, U+200E NEW RFC 2070 -->
<!ENTITY rlm     CDATA "&#8207;" -- right-to-left mark, U+200F NEW RFC 2070 -->

次の2つの例を比較せよ。

&#x05e9;&#x05dc;&#x05d5;&#x05dd;!
שלום!
&#x05e9;&#x05dc;&#x05d5;&#x05dd;!&rlm;
שלום!‏

ユニコードで、日本語や英語の文字は「左から右に書く」という文字単位の強い属性を持っている。 また、ヘブライ語やアラビア語の文字は「右から左に書く」という文字単位の強い属性を持っている。 句読点、例えばピリオドは、「左から右に書く」言語と「右から左に書く」言語で共用できるように、 それ自身では強い書式方向属性を持たず、 環境に依存する。より具体的には、同一の強い書式方向属性をもつ文字に囲まれると、その属性を継承して、弱い書式方向属性をおびる。 弱い書式方向属性をおびた句読点類は、いっそうニュートラルな空白類のレイアウトに影響を与えることが可能だが、 強い書式方向属性がある文字に逆に影響を与えることはできない。 したがって、ある句読点の手前に「右左」文字、その句読点の直後に「左右」文字がある場合、 その句読点の書式方向属性は直前、直後のブロックからは等しく影響を受けるので、 より大きな全体の属性に依存するが、 もし句読点の手前に「右左」文字があり、その句読点の直後にさらに「右左」文字(幅なしでも良い)があるなら、 その句読点は、より上位レベルを調べるまでもなく、ローカルな前後の環境から「右左」属性を継承する。

Windows 2000 のメモ帳では、右クリックメニューから選ぶだけで、指定の場所にRLMほかを挿入できる(Microsoft Windows 2000 Professional ドキュメント)。 べんりな機能ではあるが、しょせんメモ帳なので、あまり使いやすくはない。

実際のヘブライ語圏のウェブページ

2003年3月現在、実際のヘブライ語圏のウェブページでは、dir属性を明示したりRLMを使うかわりに、 次のように「末尾に来る句読点を、あらかじめひっくり返しに書く(論理的な行頭に書く)」という妥協案で、 プレフォーマットされていることが多い。 (ヘブライ文字そのものをひっくり返しに書くわけでなく、パラグラフの最後の句読点のみ細工する。)

!&#x05e9;&#x05dc;&#x05d5;&#x05dd;
!שלום

この方法は、 パラグラフ末尾の「行末の句読点」をソースでは「行頭」にタイプしなければならず不自然だが、 比較的に古いブラウザでも期待通りの表示が得られるだろう。

リンク

関連記事

この記事のURL


HTML5 の bdi 要素と Unicode 6.3 の新しい双方向アルゴリズム

2012年12月 4日
記事ID e21204

ブログのコメント欄で起きる身近な例を出発点に「右から左に書く文字 + 数字」のパターンに潜む問題と解決法を探る。

HTMLdir 属性は「テキスト方向」を表すが挙動が複雑で役立たない場合もあるHTML5 で予定されている新しいタグ <bdi> を使うと問題は簡単に解決する将来的には「ユーザー入力欄などの動的に生成される語句はこのタグで隔離」というのが常識になるかもしれない。

目次

入門編

[この記事の目次へ]
なぜこんな表示に

例1: ブログのコメント欄でユーザー名 User のコメントが次のように表示されるとする:

Comment by User: 2012年11月23日 20時30分

ユーザー名が אלישע(エリーシャ)ならこうなってほしい:

Comment by אלישע‎: 2012年11月23日 20時30分

実際には次のように表示が乱れる:

Comment by אלישע: 2012年11月23日 20時30分

*

例2: エジプトの歴史を紹介するウェブページを作成中の人が「人名はオリジナルのつづりも表記したい」と思ってこう書こうとした:

ナセル(عبد الناصر‎, 1918–1970)は…

ところがソースで…

ナセル(<span lang="ar">عبد الناصر</span>, 1918–1970)は…

…と書くとブラウザ上では次のように表示が乱れてしまう:

ナセル(عبد الناصر, 1918–1970)は…

数字の位置がおかしい上生年と没年もあべこべだ。

そうなってしまう訳

「左から右に書く文字」・「右から左に書く文字」が混在するテキストの処理を双方向アルゴリズムと呼ぶが次のように動作する:

  1. アラビア文字・ヘブライ文字などの←「右から左」の文字に半角や全角の数字が後続する場合その数字は←「右から左」の範囲の一部となり従って文字の←左に表示される。
  2. 数字そのものはその位置で「左から右」→に並ぶ。
  3. 文字と後続の数字の間にスペースや句読点が含まれていても結果は変わらない。

例えば「エリーシャ - 123」はヘブライ語の文章の中では右から左へこう表示される:

אלישע - 123

一方「左から右」のインターフェースにおいて「ユーザー名 - 現在のスコア」のようなフォーマットが並んでいる場所なら同じ文字列を次の順番に表示する必要があるかもしれない:

אלישע - 123

このように「右から左」の文字と後続する数字の位置関係には2種類の可能性がある(「右から左」の表示それ自体は現在のソフトウェアなら自動で正しく行われる)

双方向アルゴリズムではデフォルトで前者のパターンになる。

「数字を含む現代ヘブライ語の文章」(前者のパターン)はいくらでも存在するが「ヘブライ文字と数字を含むヘブライ語でない文章」は比較的まれなのでこのデフォルト設定は妥当だろう。

例1・例2の「乱れた」表示も実は乱れているわけでなく仕様通りの正しい結果だ。

Comment by אלישע: 2012年11月23日 20時30分

上の例はヘブライ文字に続く数字「2012」が仕様通りに配置されたもの。

ナセル(عبد الناصر, 1918–1970)は…

この例で丸かっこ内の文字は次の順序で右から左に並んでいる: アラビア文字の部分カンマスペース1918ダッシュ1970」。

これらは正しいデフォルト表示だが意図する表示とは違うタグや制御文字を使って表示方法を指定する必要がある。

3種類の解決法

HTML ではテキストの方向を指定する dir 属性を使ってこの種の問題を解決できることがあるただし使い方にはこつがありやたらと付ければいいものではない例えばこの書き方はどうだろう:

例2a:

<p lang="ja" dir="ltr">
ナセル (<span lang="ar" dir="rtl">عبد الناصر</span>, 1918–1970) は…
</p>

パラグラフのテキスト方向が ltr(左から右)埋め込まれるアラビア文字部分が rtl(右から左)と明示され言語属性 lang もきちんと示されている一見筋の通った模範解答のようにも思えるだがこれだと結果は最初と変わらない:

ナセル (عبد الناصر, 1918–1970) は…

例2においてアラビア文字のテキスト方向はすでに正しいデフォルト表示で都合悪いのはアラビア文字の並び方ではなくその後ろの数字の位置だこの場合数字部分に dir 属性を指定すると問題が解決する。

例2b:

<p>
ナセル (<span lang="ar">عبد الناصر</span>, <span dir="ltr">1918–1970</span>) は…
</p>

ナセル (عبد الناصر, 1918–1970) は…

別解として「右から左」区間を終わらせたい場所にUnicode の特殊文字:
U+200E LEFT-TO-RIGHT MARK
を挿入する方法もあるこの文字は LRM と略称されHTML では&lrm; という簡単な表記で使える「右から左」の文字と数字の間にこれを挿入すれば「右から左」区間が数字の手前で終了するようにできる。

<p>
ナセル (<span lang="ar">عبد الناصر</span>&lrm;, 1918–1970) は…
</p>

この場合dir 属性を使う方法より簡潔で意図も明確だ。

HTML5 で予定されている <bdi> タグを使えば次のシンプルな表記で問題が解決する:

<p>
ナセル (<bdi lang="ar">عبد الناصر</bdi>, 1918–1970) は…
</p>

bdiBidirectional Isolate(双方向性における隔離区域)という意味で「この部分の方向性は独立しています後ろの数字とつながったりはしません切り離して考えてください」と指示する役割を持つ。

*

同様に次の表示を得るには…

Comment by אלישע‎: 2012年11月23日 20時30分

こう書けば良い:

Comment by אלישע: <span dir="ltr">2012年11月23日 20時30分</span>
<!-- または -->
Comment by אלישע&lrm;: 2012年11月23日 20時30分
<!-- HTML5では -->
Comment by <bdi>אלישע</bdi>: 2012年11月23日 20時30分

数字(例えば値段)が乱れて表示されると情報が正しく伝わらず場合によってはセキュリティー問題にもつながる「ユーザーが自由に入力できる欄によってその欄と関係ない隣の欄の表示が影響される」という状況は良くない将来的には「動的に生成される語句(ユーザー入力欄など)には <bdi> を付ける」というのが常識になるかもしれないそうしておけば世界中のどういう文字がそこに来ても周囲の表示は乱れないからだ。

普通の(静的な)ウェブページの作成でも日本語や西欧語の文章にアラビア文字・ヘブライ文字などの単語を混在させるとき<bdi> タグは役立つだろう。

まとめ

「右から左」の文字の直後にある数字はデフォルトで左側に表示される文字と数字の間にカンマハイフンなどがある場合も同様数字を右側に表示させる方法は3種類ある:

  1. 「右から左」区間を終了させたい場所に特殊文字 LRM を挿入。
  2. HTML では数字の部分に dir="ltr" を指定する方法もある。
  3. HTML5 には <bdi> という便利なタグがある。

*

(入門編・終わり)

事例研究

[この記事の目次へ]
かっこの表示が乱れるケース

例3: 次のように表示したい:

ガルディヤ(ގަރުދިޔަ‎)[12]モルディブの伝統的なツナ・スープ一般にお米と一緒に食べる付け合わせはライムチリなど。

かっこの中はモルディブのディベヒ語(Dhivehi, 言語コード: dv)の単語でターナ文字(Thaana)で書かれている「右から左」の文字だ[12] は注釈や文献番号だとする素直に書けば、

ガルディヤ(<span lang="dv">ގަރުދިޔަ</span>)<sup>[12]</sup>は…

…となるがそれだと表示が乱れる。

Unicode 6.2 時点での表示:

ガルディヤ(12]ގަރުދިޔަ]モルディブの伝統的な…

あなたのブラウザでは…

ガルディヤ(ގަރުދިޔަ[12]モルディブの伝統的な…

ターナ文字は単に「右から左」の文字の例でそれ自体が特殊なのではないかっこ内がアラビア文字・ヘブライ文字でも同じ現象が起きる。

この表示を理解するために、
ガルディヤ()は、[12]
という構造に注目しよう。
ガルディヤ(
…までは順調に表示されそこで「右から左」エリアに入る入門編で見たように「右から左」の文字の後ろに数字がある場合その数字も「右から左」エリアの一部なり文字の左側に来る間にかっこがある場合も同様だ。
[12
…の部分がこれに当たる「右から左」エリアではかっこは鏡像表示(ミラーリング)されるため見掛け上ターナ文字の末尾(左側)に
12]
…があるように出力されるこれはかっこを鏡像にしながら、
[12
…を逆順にしたものだ12という数字自体は「左から右」に並ぶ。
]は、
…の部分では「左から右」に戻り表示上そこで「右から左」エリアの右側に飛んでいる。

Unicode 6.3 では双方向アルゴリズムが改訂されかっこの扱いも若干改善されるしかし現時点の仕様予定(rev. 28d4)を見た限りでは上の例のかっこの表示は変更されない。 2013-08-23追記: かっこの処理は、上記の予定よりさらに改善される模様。

例1・例2と同様数字に dir 属性を設定するかまたはターナ文字の末尾に &lrm; を挿入することで問題を解決できる:

ガルディヤ(<span lang="dv">ގަރުދިޔަ</span>)<sup>[<span dir="ltr">12</span>]</sup>は…
<!-- これでも良い -->
ガルディヤ(<span lang="dv">ގަރުދިޔަ</span>)<sup dir="ltr">[12]</sup>は…
<!-- または -->
ガルディヤ(<span lang="dv">ގަރުދިޔަ</span>&lrm;)<sup>[12]</sup>は…
<!-- HTML5では -->
ガルディヤ(<bdi lang="dv">ގަރުދިޔަ</bdi>)<sup>[12]</sup>は…

ガルディヤ(ގަރުދިޔަ[12]は…

dir 属性が使えないケース

例4: 注釈の番号「12」を以下の位置に表示したい:

ワイツマン(ヘブライ語: חיים ויצמן12)はイスラエルの初代大統領で…

普通に書いたのではこうなってしまう:

ワイツマン(ヘブライ語: חיים ויצמן12)は…

ヘブライ語の単語に注釈を付けるのならこれはこれで正しい(単語の頭でなく末尾に注釈の印が付いている)しかしヘブライ語: חיים ויצמן」という「ヘブライ語の引用を含む日本語」に注を付けているのだとしたら12」は右側に来るべきだ。

12」に dir 属性を与えることではもはや解決できない:

例4a:

ワイツマン(ヘブライ語: <span lang="he">חיים ויצמן</span><sup dir="ltr">12</sup>)は…

ワイツマン(ヘブライ語: חיים ויצמן12)は…

もしヘブライ語の span と数字の span の間に1文字でも(半角スペース1個でも)あれば同じ方法でうまくいく。

例4b:

ワイツマン(ヘブライ語: <span lang="he">חיים ויצמן</span> <sup dir="ltr">12</sup>)は…

ワイツマン(ヘブライ語: חיים ויצמן 12)は…

だがスペースを入れると表示も少し変わってしまうここではヘブライ文字にぴったりくっつけて「12」を表示したいとしよう。

普通だったらこういう場合ゼロ幅のスペースが利用できるU+2060 WORD JOINERU+200B ZERO WIDTH SPACE(後者は改行禁則でないため「ぴったりくっつけて」という条件とは少しずれる)ところがこの二つの文字は双方向アルゴリズム上 BN(境界中立)というタイプで「あってもなくても同じ」という扱いになっている「あってもなくても同じ」なので挿入しても区間を切り離すことができない。

次善の策としてU+200A HAIR SPACE を挿入してみよう:

ワイツマン(ヘブライ語: <span lang="he">חיים ויצמן</span>&#x200A;<sup dir="ltr">12</sup>)は…

ワイツマン(ヘブライ語: חיים ויצמן12)は…

一応もっともらしい表示になったが髪の毛1本の幅(ヘア・スペース)の妥協とはいえ条件を満たせなかったdir 属性を使うのでは制御できないテキスト方向というものがあることが分かる。

この場合挿入すべき最善の文字はもちろん &lrm;その方法なら dir 属性は必要ない。

ワイツマン(ヘブライ語: <span lang="he">חיים ויצמן</span>&lrm;<sup>12</sup>)は…

ワイツマン(ヘブライ語: חיים ויצמן12)は…

一般にこの種の問題の解決法としてはdir 属性より LRM/RLM の方が優れている​(RLM は LRM と正反対の働きを持つ特殊文字この記事では使わない。)

特にプレーンテキストの場合HTML の dir 属性に相当する制御文字は2文字のペアで「ここから」・「ここまで」と範囲を指定しなければならないエディタで編集していると往々にしてペアの2文字の片方だけがコピーされたりして訳の分からない状態になるLRM/RLM なら1文字だけなのでこうした問題が起きにくい。

HTML5 ならいっそうすっきりする:

ワイツマン(ヘブライ語: <bdi lang="he">חיים ויצמן</bdi><sup>12</sup>)は…
<bdo> を使う方法

参考までに <bdo> を使う方法を挙げておく。

ワイツマン(ヘブライ語: <bdo dir="ltr" lang="he">ןמציו םייח</bdo><sup>12</sup>)は…

ワイツマン(ヘブライ語: ןמציו םייח12)は…

一応同じ表示が得られるが良い方法ではない単語や文を逆さまにタイプするのは面倒だし結果はワードラップ検索などの処理にもなじまない。

dir 属性における HTML のタグ構造の破綻

単純化した例で問題を再検討してみよう。

<span dir="rtl">אב</span><span dir="ltr">12</span>

HTML の常識で考えれば上のソースはこう表示されると期待される:

‎ב‎ א‎ 1 2
← ← → →

実際には暗黙にネストが起きる:

‎1 2 ב‎ א‎
← ← ← ←
→ →

つまり次の二つのソースが等価になってしまう:

<span dir="rtl">אב</span><span dir="ltr">12</span>

<span dir="rtl">אב<span dir="ltr">12</span></span>

HTML のタグ構造としては次の二つが同じだと言っているのと同じことで受け入れにくい:

<strong>bold</strong><em>italic</em>

<strong>bold<em>italic</em></strong>

さらに次の二つが全く異なる構造を表しておりこれも受け入れにくい:

<span dir="rtl">אב</span><span dir="ltr">12</span>

<span dir="rtl">אב</span> <span dir="ltr">12</span>

HTML と Unicode では設計の前提も理念も大きく異なる:

HTML は内部的に Unicode の双方向アルゴリズムを利用しており双方向性の処理では上記の二つの異なる原理が混在しているここではそれが表面化し「仕様的には正しいが感覚的におかしい」という状況が生じている。

双方向アルゴリズムの詳細

[この記事の目次へ]

この章ではこうした挙動の背景にある Unicode のアルゴリズムを紹介する次の単純化した例を考えよう:

「右から左」の文字に続く数字
論理的位置 1 2 3 4 5 6 7 8
文字 a b א ב 1 2

א(アレフ) と ב(ベート) はヘブライ文字で右から左に אב と表示されるテキストデータとしては א が前にある論理的位置は 0, 1, 2, … と 0 から数える方がよりコンピュータ的だがここでは 1, 2, 3, … としておく(本質的な違いはない)。

1. デフォルト

デフォルトではヘブライ文字に続く数字がヘブライ文字の左側に表示される。

ab אב <span>12</span>

結果:

ab אב 12

「ヘブライ語は右から左に進むので文字に続く数字は文字の左に来る」というだけのことだがアルゴリズム的には次のように動作する。

双方向性における文字タイプ(初期状態)
論理的位置 1 2 3 4 5 6 7 8
文字 a b א ב 1 2
文字タイプ L L N R R N EN EN
埋め込みレベル 0 0 0 0 0 0 0 0
1. 文字タイプ

これ以外の型もあるがここでは必要ない詳しくは仕様書(UAX #9)の Table 4. Bidirectional Character Typesまたは UAX #44の Table 13. Bidi_Class Values を参照各種の型は Bidi_Class と呼ばれ文字ごとに UnicodeData.txtフィールド4で定義されている同じ「右から左」でも RAL の区別があるのは数字の扱いが異なるため(付録参照)。

2. 弱タイプの解決

ENその位置から前へ前へとさかのぼって最初に出会う強タイプ(“支配者”)により次のように型が変わる: ①支配者が AL ならAN(「アラビア語数字」型)になる(規則 W2)。 ②支配者が L ならL になる(規則 W7)。 ③支配者が R ならEN のままになる。 ④区間始点に達した場合区間始点タイプに支配される(後述)ここでは③が適用される。

3. 中立タイプの解決

①同じ方向性の要素に挟まれた Nその方向性に同化して L または R に変わる(規則 N1ただしANおよびこの時点で残っている EN「右から左」の方向性を持つ。 ②それ以外の(=異なる方向性の要素に挟まれた)N埋め込みレベルに応じたデフォルトの方向性を持つ(規則 N2)。

HTML 4 ではdir 属性のデフォルト値は ltr(左から右)であり(仕様書 8.2.2パラグラフはデフォルトでその方向になるここではデフォルトのままだと仮定している従ってパラグラフの埋め込みレベルは 0 となる(規則 HL1これは「左から右」の基本状態を意味する結局位置 3 のスペースは N2 により L になり位置 6 のスペースは N1 により R になる。

上記は HTML における処理でありプレーンテキストのパラグラフとは扱いが異なるまた区間境界が絡む場合も扱いが異なる(後述)中立タイプの解決は暗黙レベルの解決より先に行われるためこの例では(この時点では)全文字がレベル 0 で区間境界は絡まない。

4. 暗黙レベルの解決

レベル 0 においてR の文字は暗黙にレベル 1 になりAN または EN の文字は暗黙にレベル 2 になる(規則 I1)。

弱タイプ・中立タイプ・暗黙レベルを解決した結果
論理的位置 1 2 3 4 5 6 7 8
文字 a b א ב 1 2
文字タイプ L L L R R R EN EN
埋め込みレベル 0 0 0 1 1 1 2 2
5. 表示順序の決定

これで全文字のレベルが定まったので規則 L2 により表示位置を決めることができる。

まずレベル 2 の区間を左右反転させる。

レベル 2 の文字(位置 7, 8)を左右反転
論理的位置 1 2 3 4 5 6 8 7
文字 a b א ב 2 1
埋め込みレベル 0 0 0 1 1 1 2 2

次に「レベル 1 以上が連続する範囲」(レベル 2 の区間を含む)を左右反転させるこの処理をするとレベル 2 の区間は合計2回反転されたことになり元の向きに戻る。

レベル 1–2 の文字(位置 4, 5, 6, 8, 7)を左右反転
論理的位置 1 2 3 7 8 6 5 4
文字 a b 1 2 ב א
埋め込みレベル 0 0 0 2 2 1 1 1
2. LRM使用

次のように特殊文字 LRM を挿入することで数字を「右から左」区間から切り離し右側に表示することができる:

ab אב&lrm; 12

結果:

ab אב‎ 12

ヘブライ文字の直後に LRM を挿入した場合
論理的位置 1 2 3 4 5 6 7 8 9
文字 a b א ב LRM 1 2
文字タイプ L L L R R L L L L
埋め込みレベル 0 0 0 1 1 0 0 0 0

LRM 文字は強タイプの L であり従って数字(位置 8, 9)は W7 により L になる位置 7 のスペースは N1 により L になる結局位置 4, 5 のヘブライ文字だけが「右から左」区間となる。

&lrm; についてはHTML 4 の仕様書の 8.2.5 参照。

3. dir 属性使用

次の書き方でも同じ結果が得られる:

ab אב <span dir="ltr">12</span>

結果:

ab אב 12

HTML でインライン要素に dir="ltr" 属性が指定された場合Unicode の言葉で言えば、

…があるのと同等だつまり内部的なデータは次のようになる:

明示的に埋め込まれたレベル
論理的位置 1 2 3 4 5 6 7 8 9 10
文字 a b א ב LRE 1 2 PDF
文字タイプ L L L R R N LRE EN EN PDF
埋め込みレベル 0 0 0 0 0 0 * 2 2 *

1. 明示的埋め込みの処理: 規則 X3 により位置 8, 9 は1段階上の偶数レベルつまりレベル 2 になるこのレベルはデフォルトの最終結果と変わらないしかしデフォルトでは暗黙に後からレベルが上がるのに対してLRE を用いると明示的に先にレベルが上がるこの順序の違いにより規則 W7 の適用結果が変わる。

規則 X9 によりLRE と PDF は除去される(以下無いものとして扱われる)。

2. 弱タイプの解決: EN(数字)はそこから前へ前へとさかのぼって最初に出会った強タイプに支配されるのだった(W2, W7)ただし区間始点(sor)に達したらそれ以上さかのぼらずに区間始点タイプを支配者とする。

直前の強タイプが L 型の区間始点であるときにも W7 が適用されるかどうかは明文規定されていないリファレンスコードを見るとその場合も W7 が適用される。

この例では数字は区間始点タイプに支配される区間始点の前方はレベル 0後方はレベル 2 だから区間始点タイプはレベル 2 に対応する L でありENL に変わる。

Unicode 6.2 以下においてLRE は定義上「強」カテゴリーの Lしかし弱タイプの解決前に除去されるためW7 には関係しない。

3. 中立タイプの解決: N の方向性は前後の要素の方向性によって決まるのであった(N1, N2)ただし前後を考えるのは現在の区間内に限る前方へさかのぼって方向性不明のまま区間始点に達したたら区間始点タイプを「前方の要素」とする後方へ進んで方向性不明のまま区間終点に達したら区間終点タイプ(区間始点タイプと同様に定義される)を「後方の要素」とする位置 6 のスペースはその前方(位置 5)が Rその後方(区間終点)が L でありN2 により L になる。

4. 暗黙のレベルの解決: 暗黙にレベル 1 になるのは位置 4, 5 のみこの区間は表示上左右が逆転する。

暗黙のレベルを解決した状態
論理的位置 1 2 3 4 5 6 7 8 9 10
文字 a b א ב LRE 1 2 PDF
文字タイプ L L L R R L LRE L L PDF
埋め込みレベル 0 0 0 1 1 0 * 2 2 *

L になってほしい数字がデフォルトでは EN のままなので数字に dir 属性を設定する」というのは一見筋が通っているし結果的にも望む表示が得られるしかし内部的には次のような回りくどい動作となる:

  1. dir 属性を明示した結果位置 8, 9 が独立した区間となった区間始点タイプが L になるので数字も L になった位置 6 のスペースから見れば区間終点タイプが L になるのでこのスペースも L になり暗黙にレベル 1 となる運命を免れた。
  2. これによりレベル 1 とレベル 2 の間にレベル 0 の部分ができレベル 2 区間はレベル 1 区間と分断されたそのため左右反転処理において「レベル 1 以上が連続する範囲」の反転のときレベル 2 区間が巻き込まれなかった。

核心は区間の分断だ実際dir 属性を明示して数字を L にしてもレベル 1 区間とレベル 2 区間が密着している場合は望む結果が得られないこの例では位置 6 にたまたまスペースがあったので両者は分断された。

4. dir 属性使用(前区間と密着)
ab אב<span dir="ltr"> 12</span>

結果:

ab אב 12

この例は前項とほとんど同じだが最終的な表示は大きく異なる一般に「右から左」区間と「左から右」区間をこの順序で密着させたい場合dir 属性ではうまくいかない。

レベル 1 区間とレベル 2 区間の密着(位置 6)
論理的位置 1 2 3 4 5 6 7 8 9 10
文字 a b א ב LRE 1 2 PDF
文字タイプ L L L R R LRE L L L PDF
埋め込みレベル 0 0 0 1 1 * 2 2 2 *

もし位置 6, 7(LRE とスペース)が入れ替われば前項と全く同じデータになり密着は起きない。

密着している場合数字はL 型の区間始点に支配されて L になる位置 7 のスペースは前後の型がいずれも L なので L になる(N1)位置 7 の前方の型とは区間始点タイプだ最後にR の区間は暗黙にレベル 1 になる。

表示位置の反転処理は次のように進みレベル 2 区間が「レベル 1 以上が連続する範囲」の反転に巻き込まれる:

レベル 2 の文字(位置 7, 8, 9)を左右反転
論理的位置 1 2 3 4 5 6 9 8 7 10
文字 a b א ב LRE 2 1 PDF
埋め込みレベル 0 0 0 1 1 * 2 2 2 *
レベル 1–2 の文字(位置 4, 5, 6, 9, 8, 7)を左右反転
論理的位置 1 2 3 7 8 9 6 5 4 10
文字 a b 1 2 LRE ב א PDF
埋め込みレベル 0 0 0 2 2 2 * 1 1 *

便宜上LRE(位置 6)も反転の範囲に含めているがこの制御文字はアルゴリズムの初めで除去されており実際には消滅している別の言い方をすればある範囲に span を設定して dir 属性を明示してもspan 要素の「ここからここまで」という情報は双方向アルゴリズムの初期において捨てられてしまう。

5. HTML5 の <bdi>(Unicode 6.3)

HTML5 の <bdi>Bidirectional Isolate)はそれ自体としてテキスト方向を指定するものではない方向区間を隔離するのが主な役目だHTML 4 の <bdo>Bidirectional Override)とは関係ない。

ab <bdi>אב</bdi> 12

結果(予想):

ab אב‎ 12

bdi 要素の機能に対応する Unicode 側のアルゴリズム改訂は次のバージョン 6.3 で暫定的に行われる見通しだ正式導入はUnicode 7 で予定されているこの節の説明は仕様草案(2012年10月26日付け draft 3)に基づく将来のアルゴリズムの予想仕様はまだ確定でないので今後内容が変わるかもしれない。

bdi 要素はUnicode の言葉で言えば、

…があるのと同等だこれら4種類の制御文字はUnicode 6.3 で追加が予定されている。

LRI/RLI/FSI の区別はbdi 要素の dir 属性値による"ltr" なら LRI"rtl" なら RLI"auto" なら FSI でデフォルトは "auto""auto" の場合内部的には "ltr" または "rtl" が(要素の内容に応じて)自動選択されるdir 属性が明示的に指定されなかった場合でも"auto" が設定されることに注意つまりbdi 要素は常に(明示的または暗黙的に)自分自身の dir 属性を持ち決して上位の dir 属性を継承しない。

dir 属性を持たないインライン要素が上位の dir 属性を継承しないのは一般的な規則だ(リンク先の最後のパラグラフ参照)一般に明示的な dir 属性を持たないインライン要素は dir 属性を継承もリセットもせず双方向的な埋め込みに一切関与しないところが明示的な dir 属性を持たない bdi 要素は要素の内容に応じて自動的に決定される暗黙の dir 属性を使って双方向的な埋め込みを行う。

隔離されたレベル
論理的位置 1 2 3 4 5 6 7 8 9 10
文字 a b FSI א ב PDI 1 2
文字タイプ L L N N R R N N EN EN
埋め込みレベル 0 0 0 0 1 1 0 0 0 0

1. 隔離: FSI と PDI により埋め込まれた区間において最初の強タイプが R または AL ならFSI を RLI とみなしそうでなければFSI を LRI とみなす(規則 X5c)ここでは前者のケースに当たる埋め込まれた区間のレベルは従来の LRE/RLE による埋め込みと同様に設定される隔離開始文字(LRI, RLI, FSI)と隔離終了文字(PDI)はそれらが囲む隔離区間には属さず埋め込みが行われるバックグラウンドの側に属する(この例ではレベル 0)。

区間列(定義 BD9): 有効な隔離開始文字で終わる区間と対応する隔離終了文字から始まる区間は処理上連続するそれ以外の2区間は処理上連続しない処理上連続する区間をつなげたものを区間列と呼ぶ処理上どの区間とも連続しない区間は独立した区間列(長さ1の列)と見なされる。

この例では、

  1. 位置 1, 2, 3, 4 から成る区間は有効な FSI で終わり、
  2. 位置 7, 8, 9, 10 から成る区間は対応する PDI で始まるので、

…それら2区間は処理上連続し一つの区間列を成す位置 5, 6 から成る区間は処理上どの区間とも連続せず長さ1の区間列となる。

区間とは同じ埋め込みレベルが続く範囲区間列は1個または2個以上の区間を並べたもの区間列を構成する区間は必ずしも位置的に連続しない。

区間列は区間の列区間は文字の列なので区間列は文字の列とも解釈できる。

隔離開始文字と隔離終了文字は正しい入れ子レベルで対応している場合にのみ有効と見なされるこの結果一つの区間列に属する全部の区間は同一の埋め込みレベルになる。

2. 弱タイプの解決: 位置 9 以降の数字のタイプを確定するため強タイプを求めてその位置から前方へさかのぼるただし従来は区間内をさかのぼったが拡張されたアルゴリズムでは区間列内をさかのぼる(最大で区間列始点まで)8→7→4→3→2 までさかのぼるとL に出会うよって数字は L になる(W2)。

3. 中立タイプの解決: 従来中立タイプの解決は区間内においてその文字の前方と後方の方向性に従って行われた拡張されたアルゴリズムでは区間列内で同じ判断を行う位置 2 の L と位置 9 の L一つの区間列内において4個の N を挟んでいるこれらの NL に変わる(N1)位置 5, 6 の R はこの区間列に属さない。

4. 暗黙レベルの解決: 位置 5, 6 は奇数レベルの R なのでレベルに変更はない。

弱タイプ・中立タイプ・暗黙レベルを解決した状態
論理的位置 1 2 3 4 5 6 7 8 9 10
文字 a b FSI א ב PDI 1 2
文字タイプ L L L L R R L L L L
埋め込みレベル 0 0 0 0 1 1 0 0 0 0

このほかUnicode 6.3 の新アルゴリズムではエラー処理の機能が提供される見通しだ例えば<bdi> 要素に「閉じていない双方向性制御文字」が含まれている場合その影響も隔離される。

付録

[この記事の目次へ]
「右から左」の文字システム一覧

双方向性の話では「アラビア文字・ヘブライ文字などの右から左に書く文字」という表現がよく使われるなど」というのは具体的に何を含んでいるのだろうか。

以下の記述で言語の分類・話者数は Ethnologue 第16版(2009)・第17版(2013)によるEthnologue の信頼性には限界があるが目安にはなる。

アラビア文字系

現在最も多く使われている「右から左」の文字はアラビア文字系のシステムだ。

標準アラビア語は2億5千万人によって話される国際語で国連の公用語アラビア文字で書かれるアラビア語にはこのほかエジプト・アラビア語アルジェリア・アラビア語スーダン・アラビア語など多くの変種があるがそれらは基本的に話し言葉で文字で書かれることは少ないようだ(従って「右から左」の話とは直接関係ない)。

ペルシャ文字はアラビア文字に数文字を加え一部の文字の形を変更したものペルシャ語を記すのに使われる狭義のペルシャ語(イラン・ペルシャ語)はイランの公用語で4700万人によって話されるアフガニスタンの公用語の一つダリー語(アフガン・ペルシャ語)は書き言葉としてはイランのペルシャ語と事実上同じだとされるおよそ1000万人の話者がいるタジキスタンの公用語タジク語もペルシャ語系だが今はペルシャ文字では書かれない一方イランのアゼルバイジャン語(南アゼルバイジャン語)は1000万人以上により話されペルシャ文字で記される。

ウルドゥー文字ペルシャ文字をさらに拡張したものでウルドゥー語を記すのに使われるウルドゥー語はインドパキスタンでそれぞれ公用語の一つであり6000万人の話者がいる。

書くのにアラビア文字を使う(またはかつて使った)言語は多い例えばパシュトー文字はアラビア文字系のシステムでパシュトー語を記すのに使われるパシュトー語はアフガニスタンのもう一つの公用語だ。

ヘブライ文字

ヘブライ文字世界で2番目に多く使われる「右から左」の文字旧約聖書の文字として知られ現代語でもイディッシュ語(話者1300万)や現代ヘブライ語(話者500万)の表記に使われる一部のヘブライ文字特にアレフは数学記号として国際的に使われる(ただしUnicode では数学記号としてのヘブライ文字には別のコードポイントが割り当てられている)。

ターナ文字

ターナ文字ディベヒ語を表記するのに使われる文字システムディベヒ語はインドの南の島国モルディブの公用語でインドのミニコイ島の主要言語でもある約34万人の話者がいる。

詳細については別記事「ターナ文字入門: 表記と発音」参照。

シリア文字

シリア文字古典シリア語を記すのに使われる文字システム宗教上では現在も使われる(アッシリア東方教会・カルデア教会・シリア正教会など)現代シリア語を記すのにも使われる別の文字とも言えるほど異なる3種類の字体を持つ。ヘブライ文字・アラビア文字とやや似ている

いわゆるアッシリア人(シリアック)の文字であり現代のシリア・アラブ共和国とは関係ないこの人々は中東がイスラム化される前からトルコ・シリア・イラク・イランなどの地域に住みキリスト教の文化を保ってきた現在は少数民族となっている現代シリア語には合計約50万人の話者がいるが(2013年の推計値)不穏な情勢のため国外に移住した人が多く世代が変わるにつれ言語使用者が減る傾向がある

現代シリア語のうちイラン北西部ウルミエなどの方言はアッシリア現代アラム語とも呼ばれるイラク北部アルコーシュなどの方言はカルデア現代アラム語とも呼ばれる両者は「東方言」と総称されることがあるトルコ南西部ミドヤトなどのアッシリア人(シリア人)が使うトゥロヨ語(スライト語)も近縁の言語であり「西方言」と呼ばれることがある

シリア文字は紀元1世紀にさかのぼる長い歴史を持ちこの文字で書かれた多くの著作物が存在するしかし現在日常生活でシリア文字が使われることは比較的少ない。

別記事「シリア文字メモ: Unicode規格書の問題、Firefoxの問題」も参照。

ンコ文字

ンコ文字1940年代にギニアで作られた文字システムで西アフリカのマンディング諸語の表記に使われることがある。マンディング諸語の主なものは:

バンバラ(バマナンカン)語 [bm][bam]
話者407万(主にマリ)
東マニンカ(東マニンカカン)語 [emk]
話者353万(主にギニア)
ジュラ(デュラ)語 [dyu]
話者255万(主にブルキナファソとコートジボワール)
マンディンカ語 [mnk]
話者135万(主にセネガルとガンビア)
マンダ文字

マンダ人はメソポタミア地域(現在のイラクなど)を故郷とする少数民族(民族的・宗教的コミュニティー)の一つこの人々が伝統的に使う言語がマンダ語(アラム語系)でマンダ文字により記される(シリア文字に似ている) マンダ人の総数はおよそ6–7万人とされる(2008年資料: N3485) ただし少数民族への迫害のため大部分は故郷を離れた。

古典マンダ語は民族の宗教において現在でも使用される 現代マンダ語は現代東アラム語の一種であり日常的にも使われることがある Ethnologue によればイラクに5000人の話者がいるという(2006年)

サマリア文字

このほかUnicode の基本多言語面にはサマリア文字が収録されているかつてサマリア人がサマリア・ヘブライ語などを記すために用いた文字だがサマリア人は総数約750人(2012年1月1日現在)の少数民族となってしまった(イスラエルパレスチナに住む)この人々はヘブライ語またはアラビア語を第1言語としておりサマリア文字は主に宗教的目的で使われる。

そのほか

補足多言語面には「右から左」の文字用になっているエリアが2カ所ありUnicode 6.2 の時点で10種類以上の文字システム(古代文字や歴史的システム)が収録されている。

アラビア文字型とヘブライ文字型の違い

Unicode の双方向アルゴリズムでは同じ「右から左」の強タイプでも RAL の区別がありアルゴリズム上R に支配される数字と AL に支配される数字は振る舞いが異なる。

次のソース例ではアラビア文字 اب とヘブライ文字 אב の後ろに同じ文字列をペーストしている:

<p dir="rtl">
<span>اب</span> / 2012-03-14 / 1+2<br />
<span>אב</span> / 2012-03-14 / 1+2
</p>

対応しているブラウザでは数字部分の表示に差ができるはずだ:

اب / 2012-03-14 / 1+2.
אב / 2012-03-14 / 1+2.

AL 型の文字
R 型の文字
アラビア文字などの部分に dir 属性は必要?

「左から右」区間内で「右から左」の語句をちょっと引用する程度なら不要。dir 属性が必要になるケースの代表は、引用部分がピリオドなどの句読点で終わっている場合(末尾の句読点が U+061F ARABIC QUESTION MARK [؟] のときは、dir 属性は必須ではない)。

インライン要素

アラビア文字・ヘブライ文字などの語句を引用するときに dir="rtl" を指定することは間違いではないがあまり意味がないこれらの文字は強タイプでどっちにしても dir 属性では文字タイプを設定(上書き)できないからだ実際逆方向の dir="ltr" を指定しても結果は変わらない「右から左」は暗黙レベルで十分で全体は一つの「左から右」区間に収まる。

「右から左」の枠を明示する必要があるのは特殊な場合のみ: ①引用部分が中立タイプの文字(句読点など)で終わる場合②アラビア文字・ヘブライ文字などの部分が内部に「左から右」の文字を含んでいる場合③数字で始まる場合など。

dir 属性は title 属性値(いわゆるツールチップ)にも適用されるため以下のような場合余計な指定をするとかえって表示が乱れる:

ナセル(<span title="アラビア文字。アブデンナセルと読む。">عبد الناصر</span>)は…

ナセル(عبد الناصر)は…

これを次のように書いてしまうとツールチップがおかしくなる:

ナセル(<span title="アラビア文字。アブデンナセルと読む。" dir="rtl">عبد الناصر</span>)は…

ナセル(عبد الناصر)は…

仕様書の dir 属性の項にはThis attribute specifies the base direction of directionally neutral text […] in an element's content and attribute values. とあり方向性の枠組みは要素の値と属性値の両方に及ぶこれを厳密に解釈するとすぐ上の例ではツールチップが
。アラビア文字。アブデンナセルと読む
…のように表示されてしまう。

厳密にはこう書くことができる:

ナセル(<span title="アラビア文字。アブデンナセルと読む。"><span lang="ar">عبد الناصر</span></span>)は…

この書き方ならアラビア文字に dir 属性を指定しても表示が乱れない。

ブロック要素

パラグラフ全体を右から始めたい場合ブロックレベルで dir="rtl" を指定する必要があるdir 属性はブロックレベルでは継承されるので最上位の「右から左」要素でまとめて指定できる。

参考文献

[この記事の目次へ]

HTML5 の bdi 要素と… > 更新履歴

  1. 2012年12月4日: 初版。
  2. 2012年12月5日: 入門編セクション3を一部改訂bdi 要素の意義を明確化。
  3. 2012年12月6日: 「右から左」の文字一覧シリア文字・ンコ文字・サマリア文字の項を改訂。
  4. 2012年12月7日: dir 属性が title 属性に影響する例を分かりやすいものに変えた。
  5. 2012年12月14日: 細部の調整。
  6. 2012年12月15日: ויצמן の片仮名表記を「ワイズマン」から「ワイツマン」に変更。
  7. 2013年1月16日: ターナ文字についての記述を更新ターナ文字入門: 表記と発音」へのリンク追加。
  8. 2013年1月27日: 「右から左」の文字一覧マンダ文字の項を追加。
  9. 2013年2月1日: 「右から左」の文字一覧シリア文字の項を少し改訂。
  10. 2013年2月11日: 「右から左」の文字一覧: 言語名 Tûrôyo (Ṣurayt, Surayt, Suryoyo) の日本語表記を「トゥロヨ語」から「スライト語」に変更。
  11. 2013年2月26日: 「右から左」の文字一覧: 「スライト語」を「トゥロヨ語(スライト語)」に変更。「シリア文字メモ」へのリンク追加。
  12. 2013年8月23日: (1) Unicode 6.3での「かっこの処理の改善」が最初の予定よりも充実する見通しであることを追記。 (2) 「西ファルシ語」という表記を「イラン・ペルシャ語」に変更。話者数も「2000万人以上」から「4700万人」に更新。これらの変更は Ethnologue 16→17版での更新に対応している。ペルシャ語では「ペルシャ語」を fārsi と呼ぶが、この場合、英語では現地名を使うべきではないという議論がある(Persian NOT Farsi: Iranian Identity Under Fire)。同様に「東ファルシ語」を「アフガン・ペルシャ語」に変更。
  13. 2013年11月29日: 「シリア文字」の項を改訂。現代シリア語の話者数を52万から50万に変更。これは、Ethnologue の第16版(2009)→第17版(2013)での更新に対応する。
  14. 2014年1月12日: 「ンコ文字」の項を整理。Ethnologue 第17版により話者数データなどを更新。
  15. 2014年2月23日: IE5.5対応を改善。
  16. 2014年4月27日: 「別の文字とも言えるほど異なる3種類の異なる字体」→「別の文字とも言えるほど異なる3種類の字体」。

この記事のURL



アドレス = 英語の「クリスマス」の最初の5文字 + アットマーク + faireal.net