双方向テキスト(そうほうこうテキスト、英: bi-directional text)とは、左横書き(左から右に書く、`LTR`)と右横書き(右から左に書く、`RTL`)の混在するテキストを言う。英語の略語であるBiDi(バイダイ)もよく使われる。コンピューター上で双方向テキストを正しく処理するためのアルゴリズムを双方向アルゴリズムと呼ぶ。

## 概要

現代において右横書きが必要な文字体系にはヘブライ文字、アラビア文字、シリア文字、ターナ文字などがあるが、これらの文字体系はつねに右から左に書かれるわけではなく、数字(アラビア数字・インド数字)は左から右に書かなければならない。したがって、ひとつの言語だけで書かれる場合であっても、これらの文字体系では双方向テキスト処理を行う必要がある。

双方向テキスト処理は多言語の混在する環境ではとくに重要になる。

## 表示順と論理順

双方向テキストには表示順と論理順の2種類がある。表示順は、表示方向を(通常は左から右に)固定しておき、右から左に書くテキストは逆順にデータを格納する。この方法では、表示アルゴリズムは単純化されるが、右横書きのテキストを入力するには特殊なことをしなければならない。論理順では、左横書きでも右横書きでも、論理的に先に来るものを先に格納する。自然な方法だが、表示アルゴリズムは複雑になる。

MIMEの双方向テキストに関する規格である RFC-1556 では、アラビア文字(ISO/IEC 8859-6)およびヘブライ文字(ISO/IEC 8859-8)については表示順を既定とし、`iso-8859-6-e`、`iso-8859-8-e` を指定した場合は明示的に方向を指定、`iso-8859-6-i`、`iso-8859-8-i` では暗黙の論理的方向に従うとする。W3C では論理順を使用し、接尾辞 `-i` が付いた文字集合を指定することを推奨している。

Unicode は論理順を採用している。

以下の節ではいずれも論理順の場合に必要になるアルゴリズムを示す。

## 初期状態

Unicodeでは、段落ごとに、その最初の強い(後述)文字によって、その段落が左横書きであるか右横書きであるかを決定する。

現実にはこの方法では不便なことが多いため、Microsoft Windowsのメモ帳や macOSのテキストエディットなどでは方向を指定できるようになっている。

## 文字の種類による方向の決定

ラテン文字や漢字、かななどは既定で左横書きの文字、アラビア文字やヘブライ文字などは右横書きの文字である。両者を混在させた場合(以下の例ではわかりやすくするためラテン文字を右から左に書く文字として扱う)、左横書きの段落で「いろは ABC にほへ DEF とちり」は、

のように表示される。すなわち、右から左へ書く文字の部分だけが逆順に表示され、それ以外の部分は右方向へ進む。

しかし、右横書きの中に数字列があらわれる場合は、異なる処理が必要となる。例として「いろは ABC 123 DEF にほへ」は、

のように表示される。すなわち「123」は左から右へ表示されるが、「123」全体は先行する文字列の左に置かれ、「123」に後続する文字列もその左に書かれる。このような処理をする必要のある文字を「弱い左横書きの文字」という。弱い文字には、アラビア数字、インド数字、および数字につなげて書かれる単位(°、通貨記号)などがある。これに対して、上記のラテン文字・漢字・かななどは強い左横書きの文字、アラビア文字・ヘブライ文字などは強い右横書きの文字である。

Unicode ではアラビア文字とヘブライ文字の後ろで弱い文字の処理のしかたが異なり、「120%」を前者は「%120」のように表示するが、後者は「120%」のままになる。

スペースや記号類の多くは方向性を持たない中立の文字で、先行する文字が左から右の場合にはその右に、右から左の場合にはその左に書かれる。

現実には、このような文字の種類による暗黙の方向性だけではうまく処理できない場合があるため、明示的に方向を指定するための別の方法(タグづけや制御記号など)を併用する必要がある。

## 方向によって字形の変わる文字

括弧類や不等号の類は、左から右へ書かれるときと右から左へ書かれるときでは字形が左右反転する。

## 規格

### JIS X 0211

制御機能を定義した ECMA-48 の第5版(1991)、それを元にした ISO/IEC 6429:1992、およびそれに対応する日本の標準 JIS X 0211-1994 「符号化文字用制御機能」では、横書き(左から右、右から左)と縦書き(上から下、下から上)、行の進む方向として縦書きなら「左から右・右から左」、横書きなら「上から下・下から上」に対応している。表示方向は機能 SPD(表示方向選択)によって選択される。書字方向を指定する機能としては SCP(文字進路選択)、SDS(方向付き文字列開始)、SRS(逆文字列開始)、SIMD(自動移動方向選択)がある。

双方向テキストの取り扱い方とその問題点については ECMA TR-53 (1991) にまとめられており、JIS X 0211 もこの文献を参照している。

### Unicode

Unicodeでは、各文字は暗黙の方向に関する属性(Bidirectional Class)を持っている。見かけが同じようであっても、ヘブライ文字の א‎ (U+05D0 Hebrew Letter Alef) は R(強い右横書きの文字)、数学記号の א (U+2135 Alef Symbol) は L(強い左横書きの文字)である。

くわえて、明示的に文字の方向を変えるための以下の記号を定義している。

| コード | 名称 |
| --- | --- |
| U+061C | Arabic letter mark (ALM) |
| U+200E | Left-to-right mark (LRM) |
| U+200F | Right-to-left mark (RLM) |
| U+202A | Left-to-right embedding (LRE) |
| U+202B | Right-to-left embedding (RLE) |
| U+202C | Pop directional formatting (PDF) |
| U+202D | Left-to-right override (LRO) |
| U+202E | Right-to-left override (RLO) |
| U+2066 | Left-to-right isolate (LRI) |
| U+2067 | Right-to-left isolate (RLI) |
| U+2068 | First strong isolate (FSI) |
| U+2069 | Pop directional isolate (PDI) |

この中で LRM と RLM と ALM が最もよく使われる。LRM は表示されない強い左横書きの文字として働く。RLM と ALM は同様に強い右横書きの文字として働く。LRM と RLMは ISO/IEC 8859-6 にも存在する。ALM はアラビア文字用で、Unicode 6.3 で追加された。

LRO は以降の文字列を強制的に左から右へ(RLO は右から左へ)表示する。

LRE は以降の文字列を左から右(RLE は右から左)の方向性に置く。右から左へ書かれる文章の中で引用句として左から右へ書かれる文章を使いたいときに使用する。たとえば「いろは ABC にほへ」は、

- 左から右の段落では「いろは CBA にほへ」
- 右から左の段落では「にほへ CBA いろは」

と書かれるが、右から左への段落でも「いろは CBA にほへ」の順序で書きたいときに LRE を使用する。

PDF は、LRE, RLE, LRO, RLO ではじまる状態を終わらせる。

LRI、RLI、PDI、FSI は Unicode 6.3 で新しく追加されたもので、最初の3つは LRE, RLE, PDF に似ているが、指定した文字列全体は中立な文字列として働き、周囲の文字列の方向に影響を与えない。FSI は LRI/RLI に似ているが、右横書きであるか左横書きであるかが後続する最初の強い文字の種類によって決定される。

LRO、RLO の使用はセキュリティ上の問題から非推奨となっている。

### HTML

HTML 4.01 では、暗黙の文字の進行方向は左横書きに固定されている。dir 属性によって方向を変更することができる。また、通常の表示順を変更することのできる BDO 要素があり、たとえば表示順に並んでいるテクストを正しく表示するのに使うことができる。これは Unicode の LRO/RLO/PDF と同じ役割を果たす。

Unicode の LRM と RLM は、それぞれ文字実体参照 `&lrm;` と `&rlm;` として定義されている。

HTML5 では、BDI (Text directionality isolation) 要素が追加され、要素の中のテキストが周辺に影響を及ぼさないように分離することができる。

### CSS

CSS 2 では `direction` と `unicode-bidi` の2つの属性が定義されている。`direction` 属性には値として `rtl` と `ltr` のいずれかを指定する。`unicode-bidi` 属性には値として `normal`、`embed`、`bidi-override` のいずれかを指定する。`embed` は Unicode の LRE/RLE による方法、`bidi-override` は同 LRO/RLO と同様の方法を使用する。

CSS 3 では `unicode-bidi` に `isolate`、`isolate-override`、`plaintext` が追加されている。

## 脆弱性

双方向テキストの処理は複雑であり、実装の不備をついた攻撃が存在する。

また、双方向テキストの制御文字を使って拡張子を偽装し、マルウェアを画像やテキストファイルに見せかける手口も存在する。人間のレビューアの目を逃れて危険なコードを挿入するために双方向テキストの制御文字を使う手法も指摘されている。