Języki#

Kierunek tekstu#

Zdecydowana większość współczesnych języków operuje na znakach zapisywanych w naturalnej kolejności (od lewej strony do prawej). Zdarzają się jednak takie (np. hebrajski czy arabski), gdzie litery w wyrazach pisane są w odwrotnej kolejności lub/i wyrazy czytane są od prawej do lewej.

W (X)HTML-u mamy dwa strukturalne polecenia ustalające kierunek tekstu:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<bdo dir="wartość">...</bdo>

lub

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<element dir="wartość">...</element>

gdzie jako wartość możemy podać:

Informacja o kierunkowości tekstu może być wykorzystywana przez programy do prawidłowej wizualizacji treści. W przypadku przeglądarek internetowych ma ona wpływ na działanie dwukierunkowego algorytmu Unicode.

Działanie znacznika <bdo> opisałem już wcześniej, w początkowej fazie tworzenia kursu. Były to bardzo skąpe informacje. No cóż, większość kursów online nie poświęca wiele uwagi odnośnie tworzenia dwukierunkowych tekstów. W tym miejscu postaram się zamieścić bardziej treściwe informacje, w których przedstawię wiele szczegółowych przykładów i opisów.

Atrybut dir nie może być użyty z elementami: APPLET, BASE, BASEFONT, BR, FRAME, FRAMESET, IFRAME, PARAM, SCRIPT.

Podstawowe pojęcia#

Dwukierunkowy tekst (bidirectional lub bidi) jest skryptem/zapisem, w którym mogą pojawić się dwa odmienne sposoby zapisu znaków (od lewej do prawej, oraz od prawej do lewej). Przyjmijmy teraz, że dominującym językiem dokumentów z dowolną treścią jest język angielski. Oznacza to, że bazowym kierunkiem zapisu będzie lewo-prawo. Od czasu do czasu w tekście angielskim mogą pojawić się wstawki z arabskiego, hebrajskiego, czy syryjskiego. Dla tych wstawek naturalnym kierunkiem zapisu znaków jest prawo-lewo. W tekście z wymieszaną kierunkowością każdy znak powinien zostać zapisany zgodnie z jego kierunkowością. Czyli można mieszać różne sposoby zapisu, ale należy to robić we właściwy dla danego języka sposób.

Dwukierunkowy algorytm (bidirectional alghoritm) to wewnętrzny mechanizm w przeglądarce internetowej, który automatycznie rozpoznaje kierunkowość znaków i w razie potrzeby stosuje odpowiednie przekształcenia. Efektem końcowym będzie prawidłowa wizualizacja treści (np. na ekranie monitora), bez dodatkowej ingerencji autorów stron. Na dzień dzisiejszy przeglądarki stosują dwukierunkowy algorytm Unicode, który działa automatycznie, ale w razie konieczności udostępniają kilka możliwości jego kontroli.

Wrodzona kierunkowość znaku # jest cechą, którą posiada każdy znak zdefiniowany przez standard Unicode. Cecha ta występuje w różnych wariantach:

Opierając się o wrodzoną kierunkowość znaków, dwukierunkowy algorytm Unicode w razie konieczności wykona odpowiednie przekształcenia w całym tekście. Zrozumienie szczegółów tego mechanizmu do najłatwiejszych nie należy. W praktyce całość odbywa się samoczynnie, tylko w niewielu przypadkach zmuszani jesteśmy do interwencji.

Skrótowy zapis kierunku tekstu:

Czasami będę posługiwał się skrótami, żeby niepotrzebnie nie rozwlekać opisów.

Kolejność tekstu (wizualna lub fizyczna)#

Wizualna kolejność tekstu była powszechnym sposobem reprezentowania hebrajskiego w HTML-u przez użytkowników, którzy nie korzystali z oprogramowania obsługującego algorytm bidi Unicode. Z przyzwyczajenia jest ona jeszcze do pewnego stopnia używana po dziś dzień. Znaki, które tworzyły tekst, były zgromadzone w kodzie źródłowym w tej samej kolejności w jakiej widzi się je na ekranie czytając od lewej do prawej.

W niektórych przykładach (gdzie rezultatem jest efekt wizualny) umieściłem także logiczny zapis znaków (np. w edytorze), którego dla odróżnienia od prezentacji oznaczyłem kolorem szarym. Wariant logiczny można ukrywać/pokazywać poprzez kliknięcie na przycisku K w górnej części każdego przykładu.

Dla przykładu, weźmy hebrajski tekst z wymieszaną kierunkowością. Strzałki w poniższym przykładzie pokazują kolejność oraz kierunek czytania słów:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
פעילות הבינאום, W3C
פעילות הבינאום, W3C
-------------1--------------><--2---

Gdyby spojrzeć na te znaki z pamięci, jeden po drugim, można by zobaczyć taką postać dla logicznego i wizualnego układu kolejności znaków. Przedstawia ona także kolejność pisania, więc wizualny tekst hebrajski, względem wymowy, musiałby być pisany od końca (np. w edytorach tekstowych).

Kolejność logicznaKolejność wizualna
Encja HEXWyglądOpisEncja HEXWyglądOpis
&#x05E4;פHEBRAJSKA LITERA PE&#x0057;WŁACIŃSKA DUŻA LITERA W
&#x05E2;עHEBRAJSKA LITERA AYIN&#x0033;3CYFRA TRZY
&#x05D9;יHEBRAJSKA LITERA YOD&#x0043;CŁACIŃSKA DUŻA LITERA C
&#x05DC;לHEBRAJSKA LITERA LAMED&#x0020; SPACJA
&#x05D5;וHEBRAJSKA LITERA VAV&#x002C;,PRZECINEK
&#x05EA;תHEBRAJSKA LITERA TAV&#x05DD;םHEBRAJSKA LITERA MEM
&#x0020; SPACJA&#x05D5;וHEBRAJSKA LITERA VAV
&#x05D4;הHEBRAJSKA LITERA HE&#x05D0;אHEBRAJSKA LITERA ALEF
&#x05D1;בHEBRAJSKA LITERA BET&#x05E0;נHEBRAJSKA LITERA NUN
&#x05D9;יHEBRAJSKA LITERA YOD&#x05D9;יHEBRAJSKA LITERA YOD
&#x05E0;נHEBRAJSKA LITERA NUN&#x05D1;בHEBRAJSKA LITERA BET
&#x05D0;אHEBRAJSKA LITERA ALEF&#x05D4;הHEBRAJSKA LITERA HE
&#x05D5;וHEBRAJSKA LITERA VAV&#x0020; SPACJA
&#x05DD;םHEBRAJSKA LITERA MEM&#x05EA;תHEBRAJSKA LITERA TAV
&#x002C;,PRZECINEK&#x05D5;וHEBRAJSKA LITERA VAV
&#x0020; SPACJA&#x05DC;לEBRAJSKA LITERA LAMED
&#x0057;WW ŁACIŃSKA DUŻA LITERAW&#x05D9;יHEBRAJSKA LITERA YOD
&#x0033;3CYFRA TRZY&#x05E2;עHEBRAJSKA LITERA AYIN
&#x0043;CŁACIŃSKA DUŻA LITERA C&#x05E4;פHEBRAJSKA LITERA PE

Teraz należałoby się zastanowić w jaki sposób wprowadzać powyższy tekst w edytorze tekstowym. Czy wpisywać znaki w kolejności wizualnej (najpierw W, potem 3, potem C, ...), co w rzeczywistości oznaczałoby, że zapisujemy wszystko od końca. Drugą możliwością byłoby wprowadzanie znaków zgodnie z kolejnością zapisu i wymowy (czyli kolejnością logiczną).

W przypadku wariantu wizualnego musielibyśmy sami zadbać o prawidłowe wyświetlenie tekstu przez przeglądarki internetowe. Wymagałoby to wyłączenia funkcji zawijanie wierszy (atrybut nowrap), jawnego dodawania linii przerwy (element <br>) i wyrównania tekstu do prawej (atrybut align="right"), szczególnie w tabelach. Dodatkowo, tekst musiałby być tak skonstruowany, aby zapobiec uruchomieniu algorytmu bidi Unicode w późniejszych podglądach (byłby on zbędny - formę wizualną tworzymy ręcznie).

Przykładowy kod HTML z użyciem tabelki:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<table width="50%" border="1">
	<tr>
		<td align="right" nowrap>
			<bdo dir="ltr">,INRIA-מ הפוריאב החראה יתוריש תא הפילחמ W3C<br></bdo>
			<bdo dir="ltr">W3C-ל רשפאמ יונישה .ERCIM-ל ,תפרצב תמקממ<br></bdo>
			<bdo dir="ltr">הרימש ךות ,הפוריא יבחרב רקחמה ירשק תא קימעהל<br></bdo>
			<bdo dir="ltr">ידסייממ דחא ,INRIA םע קזחה ירוטסיהה רשקה לע<br></bdo>
			<bdo dir="ltr">.2003 ראוניל 1 ב עצבתי יונישה .ERCIM</bdo>
		</td>
	</tr>
</table>

Efekt:

,INRIA-מ הפוריאב החראה יתוריש תא הפילחמ W3C
W3C-ל רשפאמ יונישה .ERCIM-ל ,תפרצב תמקממ
הרימש ךות ,הפוריא יבחרב רקחמה ירשק תא קימעהל
ידסייממ דחא ,INRIA םע קזחה ירוטסיהה רשקה לע
.2003 ראוניל 1 ב עצבתי יונישה .ERCIM

Takie rozwiązanie jest bardzo proste w użyciu. Można też na przykład znaleźć takie konstrukcje jak akapity z wyrównaniem do prawej, w którym każda linia zostaje otoczona przez tagi <nobr>...</nobr>.

Z praktycznego punktu widzenia powyższy przykład to bardzo delikatna konstrukcja, którą trudno utrzymać. Na przykład, poza trudnością zapisu tekstu hebrajskiego od tyłu, jeśli chce się dodać kilka słów w drugiej linii akapitu, trzeba dopasować koniec każdego wiersza. Trzeba też dodać i utrzymać oddzielne rozpiętości linków lub znaczniki emfazy dla każdej części tekstu, która wyszła na następną linię. Nie należałoby również zapominać o ręcznym przestawieniu kolejności komórek w przypadku tabeli. Jak widać, roboty co niemiara, metoda mało komfortowa.

Kolejność logiczna tekstu to o wiele lepsze rozwiązanie. W tym podejściu tekst jest przechowywany w pamięci w kolejności, w której jest pisany (i wymawiany). Dwukierunkowy algorytm Unicode sam przestawia kolejność, aby poprawnie wyświetlać tekst. Sprawia to, że tworzenie długich paragrafów ciągłego tekstu jest banalnie proste, bo tekst jest automatycznie zawijany. Łatwiejsze staje się też używanie czytników ekranu.

Dwukierunkowy algorytm Unicode działa na tekście o logicznej kolejności. Jeśli wolisz kolejność wizualną (graficzną) to możesz na tym już poprzestać, chociaż mógłbyś znacznie ułatwić sobie życie stosując kolejność logiczną.

Wizualna kolejność prawie nie występuje w arabskim. Ponieważ arabskie litery łączą się z sobą, istniała silniejsza motywacja po stronie arabskich użytkowników, aby korzystać z kolejności logicznej.

Dwukierunkowy algorytm Unicode#

Rozdział podzielę na dwie osobne części. W pierwszej będą teoretyczne opisy będące wprowadzeniem do działania dwukierunkowego algorytmu Unicode, ale z przykładami wyłącznie w języku polskim, co ma ułatwić zrozumienie materiału. Efekt poprawnego działania (interpretujący pewne znaki w odmienny sposób) będzie wymuszany odpowiednimi poleceniami.

W drugiej części opiszę mechanizmy rządzące dwukierunkowym algorytmem Unicode. Przykłady będą zbudowane ze znaków Unicode o różnych wrodzonych kierunkowościach. Co prawda konwersja odbywa się automatycznie, ale warto wiedzieć na jakiej zasadzie przebiega. Bez zrozumienia podstaw można się później pogubić przy stosowaniu poleceń HTML lub znaków kontrolnych Unicode.

Teoria#

Cały mechanizm najlepiej wyjaśnić na prostych przykładach teoretycznych. Załóżmy, że mamy do czynienia z mieszanką teksów w języku polskim (kierunek lewo-prawo) oraz w języku hebrajskim (kierunek prawo-lewo).

Rozważmy akapit zawierający następujący tekst (dla późniejszych odwołań nazywam go szablonem #):

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
polski1 HEBRAJSKI2 polski3 HEBRAJSKI4 polski5 HEBRAJSKI6

Wszystkie znaki z tego przykładu są przechowywane na komputerze w kolejności logicznej, czyli pierwszym symbolem w pliku jest "p", drugim "o", a ostatnim "6".

Przyjmijmy teraz, że dominującym językiem dokumentu, zawierającym powyższy akapit, jest język polski. Oznacza to, że bazowym kierunkiem będzie lewo-prawo. Poprawna wizualizacja szablonu będzie następująca:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
polski1 2IKSJARBEH polski3 4IKSJARBEH polski5 6IKSJARBEH
		<----H----		   <----H----		  <----H----

--------------------------P---------------------------->

Linie przerywane wskazują na strukturę tego zdania: dominuje język polski z domieszką tekstu hebrajskiego. Uzyskanie poprawnej prezentacji nie wymaga dodatkowych znaczników, ponieważ fragmenty hebrajskiego zostaną prawidłowo odwrócone przez przeglądarki internetowe (za pomocą dwukierunkowego algorytmu Unicode).

Tutaj przykład, gdzie na sztywno zastosowałem odpowiednie polecenia (X)HTML, by uzyskać taki efekt:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<p dir="ltr">polski1 <bdo dir="rtl">HEBRAJSKI2</bdo> polski3 <bdo dir="rtl">HEBRAJSKI4</bdo> polski5 <bdo dir="rtl">HEBRAJSKI6</bdo></p>

Efekt (porównaj z szablonem):

polski1 HEBRAJSKI2 polski3 HEBRAJSKI4 polski5 HEBRAJSKI6

Skąd taka dziwna konstrukcja w żywym przykładzie? Ponieważ moje "hebrajskie" wstawki (HEBRAJSKI2, HEBRAJSKI4, HEBRAJSKI6) to najzwyklejszy tekst z wrodzoną kierunkowością lewo-prawo ustaloną w Unicode. Żaden ze znaków użytych do zbudowania słów nie jest symbolem z języka hebrajskiego. Przeglądarki internetowe nie odwrócą kierunku tekstu, musiałem dodać odpowiednie polecenie <bdo dir="rtl">, które wymusza takie zachowanie na dowolnych znakach, niezależnie od ich wrodzonej kierunkowości.

Rozważmy jeszcze jeden wariant, w którym dominującym językiem będzie hebrajski (ustawienie z prawej strony oraz dodatkowe odwrócenie znaków). Wszystkie wstawki w języku polskim powinny zostać wyświetlone w naturalnym sposób dla tego języka (od lewej do prawej). Poprawna wizualizacja szablonu będzie następująca:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
6IKSJARBEH polski5 4IKSJARBEH polski3 2IKSJARBEH polski1
 ---P-->			---P-->			   ---P-->

--------------------------H---------------------------->

W tej wersji cały tekst hebrajski zostaje wyświetlony od prawej do lewej (automatyczna konwersja przez algorytm dwukierunkowy). Wstawki w języku polskim zostają wyświetlone bez dodatkowych zabiegów. Żywy przykład ze sztywnymi deklaracjami kierunku tekstu:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<p dir="rtl">
	<bdo dir="rtl">
		<bdo dir="ltr">polski1</bdo> HEBRAJSKI2 <bdo dir="ltr">polski3</bdo> HEBRAJSKI4 <bdo dir="ltr">polski5</bdo> HEBRAJSKI6
	</bdo>
</p>

Efekt (porównaj z szablonem):

polski1 HEBRAJSKI2 polski3 HEBRAJSKI4 polski5 HEBRAJSKI6

Podobnie jak w poprzedniej prezentacji, także i tutaj musiałem użyć wiele elementów <bdo>, gdyż nie wprowadziłem prawdziwych znaków hebrajskich. W rzeczywistych przykładach cała praca zostałaby wykonana automatycznie. Wystarczy określić kierunek bazowy dla całej strony lub pewnej części za pomocą atrybutu dir w dowolnym elemencie HTML.

Oczywiście są to tylko teoretyczne przykłady obrazujące ogólne działanie dwukierunkowego algorytmu Unicode. Można go kontrolować za pomocą poleceń xHTML jak i specjalnych znaków Unicode (o czym później). Z tego co widzę, to w CSS wprowadzono odpowiedniki dla dir i <bdo> (właściwości direction oraz unicode-bidi).

Oto alternatywa dla poprzedniego przykładu z wykorzystaniem poleceń CSS:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<p style="direction: rtl; unicode-bidi: bidi-override;">
	<span style="direction: ltr; unicode-bidi: bidi-override;">polski1</span> HEBRAJSKI2 <span style="direction: ltr; unicode-bidi: bidi-override;">polski3</span> HEBRAJSKI4 <span style="direction: ltr; unicode-bidi: bidi-override;">polski5</span> HEBRAJSKI6
</p>

Efekt:

polski1 HEBRAJSKI2 polski3 HEBRAJSKI4 polski5 HEBRAJSKI6

Kod powyższego przykładu może wydawać się bardzo rozwlekły (ze względu na stosowanie stylów lokalnych). Przenosząc wszystkie deklaracje do zewnętrznego arkusza stylów można w bardziej elastyczny sposób zapanować nad wyświetlaniem treści o dowolnym kierunku.

Z drugiej strony, określanie tak ważnego aspektu jak kierunek tekstu za pomocą samego CSS może powodować problemy w programach, które nie obsługują arkuszy stylów. Według niektórych źródeł, najwłaściwszym będzie określanie kierunku tekstu za pomocą Unikodu lub poleceń xHTML (w zależności od potrzeby najlepiej wybrać tylko jedną metodę). Polecenia CSS powinny być stosowane jedynie jako wzbogacenie prezentacji i nie powinny decydować o tak kluczowym aspekcie, jakim jest kierunek tekstu w treści dokumentu.

Kierunek tekstu należy określać bezpośrednio w strukturze znacznikowej dokumentów, dzięki czemu zwiększy się ich interoperacyjność. Programy zdolne do przetwarzania znaczników, ale bez obsługi CSS, będą w stanie odczytać informacje o kierunku poszczególnych treści.

Praktyka#

Pora na bardziej realistyczne przykłady.

Kierunek bazowy (kontekst kierunkowy)#

Działanie dwukierunkowego algorytmu Unicode zależy od ogólnego (bazowego) kontekstu kierunkowego, np. dla akapitu, bloku lub strony, na której jest używany. Kierunek bazowy jest ważnym pojęciem. Ustanawia on kontekst kierunkowy, do którego odwołuje się algorytm bidi przy różnych krokach wyświetlania tekstu.

W xHTML-u kierunek bazowy jest albo jawnie ustawiany przez najbliższy element nadrzędny, który posiada atrybut dir, lub w przypadku braku takiego atrybutu, zostaje odziedziczony z domyślnego kierunku dla dokumentu, którym jest LTR.

Aby ustawić domyślny kierunek RTL dla całego dokumentu xHTML, należy ustawić atrybut dir="rtl" dla elementu html. Będzie to oznaczało, że wszystkie elementy w dokumencie odziedziczą bazowy kierunek RTL, chyba że dla jakiegoś elementu użyjemy ponownie atrybutu dir, który zmieni bazowy kierunek w ramach tego elementu.

Kierunkowe wyświetlanie znaków#

Wiemy już, że sekwencja łacińskich znaków jest renderowana (wyświetlana) jeden po drugim od lewej do prawej (widać to na tej stronie). W takiej sytuacji algorytm bidi w ogóle nie musi pracować, żaden znak z zapisu logicznego nie musi zostać zaprezentowany w przestawionej kolejności.

Sytuacja ulega zmianie dla znaków o wrodzonej kierunkowości ustawionej na RTL, algorytm bidi będzie składał sekwencje takich znaków jeden po drugim od prawej do lewej.

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
egypt
egypt
---LTR---->

مصر
مصر
<--RTL--

Jest to niezależne od aktualnego kierunku bazowego, i działa, ponieważ każdy znak Unicode ma przypisaną cechę kierunkowości. Większość liter jest zapisana w silnej typizacji jako LTR. Litery z dwukierunkowych skryptów są zapisywane jako RTL.

Powyższy przykład prezentował pojedynczy wyraz. Jeśli byłoby ich więcej, to w każdym z nich litery zostałyby odwrócony, i dotyczy to nawet kolejności wyrazów, która zostałaby odwrócona.

Seria kierunkowa#

Kiedy tekst z różnymi kierunkami jest zmieszany w jednej linii, to algorytm bidi generuje każdą sekwencję znaków z tym samym kierunkiem jako osobną serię kierunkową. W poniższym przykładzie występują trzy cząstkowe serie kierunkowe:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
bahrajn مصر kuwejt
bahrajn مصر kuwejt
-----LTR---->  <-RTL-  ----LTR--->
--------------LTR---------------->

Zauważ, że nie potrzebujemy żadnych znaczników ani stylistyki aby uzyskać taki efekt. Znaki z kierunkowością RTL zostaną ułożone w sposób automatyczny.

Jedna mała uwaga. Kolejność, w jakiej serie kierunkowe są wyświetlane na stronie, zależy od aktualnego kierunku bazowego. W powyższym przykładzie, który ma kontekst bazowy LTR, powinniśmy przeczytać "Bahrajn", potem "مصر" (RTL), potem "Kuwejt":

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
bahrajn مصر kuwejt
bahrajn مصر kuwejt
      1			  2			3

Jeśli w powyższym przykładzie zmienimy kierunku bazowy (np. określając atrybut dir="rtl" dla elementu html), to sposób i kolejność wyświetlania serii kierunkowych ulegnie zmianie:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
bahrajn مصر kuwejt
bahrajn مصر kuwejt
	  1			 2			3

Moje przykłady umieszczam w elementach pre. W powyższej prezentacji przypisałem temu elementowi atrybut dir="rtl", przez co zmieniłem kierunek bazowy dla całej zawartości elementu. Jak łatwo zauważyć, oprócz zamiany kolejności wyświetlania serii kierunkowych, zmieniło się także wyrównanie względem marginesów. Wyprowadzanie tekstu rozpoczyna się od prawej strony.

Znaki w obu przypadkach są przechowywane w pamięci (zapisane w pliku) w dokładnie takiej samej kolejności, ale wizualne uporządkowanie serii kierunkowych, w czasie wyświetlania, zostaje odwrócone.

Znaki neutralne#

Spacje i znaki interpunkcyjne nie mają w Unicode ani kierunkowości LTR ani RTL, bo mogą być używane w każdym typie skryptu. Dlatego są klasyfikowane jako neutralne lub słabe. Znaki są zazwyczaj klasyfikowane jako słabe, kiedy są związane z liczbami. Mała część znaków interpunkcyjnych jest wstępnie określona jako słabe, ale w kontekście nienumerycznym są traktowane jako neutralne. W konsekwencji takiego podziału, w tej części będę odnosił się do znaków interpunkcyjnych o neutralnym charakterze.

I tu zaczyna się robić interesująco. Kiedy algorytm bidi napotka znaki z neutralnymi cechami (takie jak spacje i znaki interpunkcyjne) ustala jak je potraktować na podstawie otaczających je znaków.

Neutralny znak znajdujący się pomiędzy dwoma silnymi znakami pisanymi w tym samym kierunku przyjmie ten sam kierunek. Więc neutralny znak pomiędzy dwoma znakami RTL będzie traktowany jako znak RTL i w efekcie stanowić będzie przedłużenie serii kierunkowej. Dlatego trzy arabskie słowa (oddzielone neutralnymi znakami spacji, które przejmą kierunkowość od otaczających je znaków) w poniższym zdaniu czytane są od prawej do lewej jako jedna seria kierunkowa (strzałki pokazują kolejność czytania).

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
Tytuł to مفتاح معايير الويب po arabsku.
-------------->  <---------------------------------  ------------------>

Naprawdę interesujące zachowanie pojawia się wtedy gdy neutralny znak znajduje się pomiędzy dwoma silnymi znakami o różnych kierunkach. W takim wypadku neutralny znak (lub znaki) będzie traktowany tak, jakby miał kierunek identyczny z ogólnym kierunek kontekstu. Nawet jeśli jest kilka neutralnych znaków pomiędzy dwoma silnymi typami znaków, będą one traktowane na tych samych zasadach. Dzięki temu tworzy się granica pomiędzy poszczególnymi seriami kierunkowymi.

Wszystkie implikacje wspomnianego zachowania staną się jasne w trakcie omawiania kolejnych przykładów.

Cyfry#

Cyfry są wyjątkowe, bo w skryptach RTL są w kolejności od lewej do prawej w obrębie serii pisanej od prawej do lewej, ale algorytm bidi radzi sobie z nimi trochę inaczej niż ze słowami w tym sensie, że zawsze zapisuje je w kierunku od lewej do prawej. Mówi się, że cyfry mają słabą kierunkowość, ponieważ mogą przynależeć do danej serii kierunkowej, ale cyfry wchodzące w skład liczby nie ulegają przetasowaniu (zawsze mają kierunek LTR, niezależnie od stosowanego języka). Dwa poniższe przykłady ilustrują tę różnicę.

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
jeden dwa ثلاثة 1234 خمسة
---------------->  <-------------------------
jeden dwa ثلاثة ١٢٣٤ خمسة

Pierwszy przykład używa europejskich cyfr "1234", w drugim przykładzie te same cyfry wyrażone zostały za pomocą arabskiego zapisu "١٢٣٤". W obu przypadkach, cyfry w liczbach są czytane i wizualizowane od lewej do prawej.

Ze względu na słabą kierunkowość cyfr, cała liczba jest postrzegana jako część tekstu arabskiego, zatem dwa arabskie słowa otaczające liczbę są traktowane jako jedna seria kierunkowa - nawet jeśli sekwencji cyfr widoczna na ekranie to LTR.

Żeby zauważyć różnicę między tekstem a liczbami przeanalizujmy kolejny przykład.

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
jeden dwa ثلاثة cztery خمسة
---------------->  <------  ----------->  <------
jeden dwa ثلاثة 1234 خمسة
---------------->  <-------------------------

W pierwszym wierszu przykładu litery w wyrazie "cztery" mają silną kierunkowość, dlatego też przerywają arabski ciąg wyrazów, zwiększając tym samym ilość serii kierunkowych. W sumie wystąpią cztery serie (dwie skierowane od lewej do prawej, oraz dwie skierowane od prawej do lewej).

W drugim wierszu przykładu znaki o słabej kierunkowości "1234" widziane są jako część arabskiego tekstu, więc dwa arabskie słowa traktowane są jako część tej samej serii kierunkowej, mimo iż sekwencja cyfr ma kierunek LTR. Konsekwencją tego jest to, że kolejność wyświetlania słów z tej arabskiej serii kierunkowej również uległa zmianie.

A teraz efekt przy zamianie kierunku bazowego na dir="rtl", można przeanalizować sposób rozmieszczenia każdej serii kierunkowej:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
jeden dwa ثلاثة cztery خمسة
<----------------  ------>  <----------  ------>
jeden dwa ثلاثة 1234 خمسة
<---------------- ------------------------->

Wygląda na skomplikowane? Nie ma się czym martwić, zazwyczaj algorytm bidi załatwi wszystko za nas. Przedstawione tu informacje są dla tych, którzy widzą różnicę i zastanawiają się co się dzieje.

Należy zauważyć, że tak jak cyfry, niektóre inne znaki, jak na przykład symbole walut, będą traktowane raczej jako numer a nie znak neutralny.

Problemy#

W większości sytuacji algorytm bidi poradzi sobie z tekstem bez żadnych specjalnych znaczników, czy innej pomocy (znaki kontrolne Unicode) dzięki ogólnemu kierunkowi dokumentu. Jednak trzeba mieć wyjątkowe szczęście, żeby zawsze się to udawało.

Istnieją trzy główne scenariusze, które powodują problemy przy używaniu algorytmu bidi dla tekstu liniowego:

Przeanalizujmy osobno każdy z tych przypadków.

Przemieszczone znaki neutralne#

Widzieliśmy, że algorytm bidi radzi sobie z jednym poziomem tekstu dwukierunkowego i że może wyprowadzać wynik działania bez dodatkowych poleceń:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
Tytuł to "مفتاح معايير الويب" po arabsku.
---------> <----------------------- ------------>

Niestety, znaki neutralne pomiędzy różnymi seriami kierunkowymi mogą być czasami błędnie interpretowane. Napiszmy znak interpunkcyjny na końcu arabskiej frazy w ostatnim przykładzie. Zgodnie z ustawieniami domyślnymi zobaczymy:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
Tytuł to "مفتاح معايير الويب!" po arabsku.

Cudzysłów wygląda prawidłowo, ale wykrzyknik jest na złym miejscu. Powinien być na końcu arabskiego tekstu, czyli z lewej, tak jak tu:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
Tytuł to "!مفتاح معايير الويب" po arabsku.

Opierając się na zasadzie działania algorytmu bidi wiemy czemu tak się stało. Ponieważ wykrzyknik był pomiędzy ostatnim znakiem RTL "ب" (z lewej) i literą LTR "p" (wyrazu "po") jego kierunek został ustalony na podstawie ogólnego kontekstu akapitu (tutaj LTR). Zauważ, że nie ma różnicy, że są tam dwa znaki interpunkcyjne i spacja – wszystkie są neutralne, więc są jednakowo traktowane. Ponieważ wykrzyknik jest uznany za LTR zostaje dołączony do serii kierunkowej, w której wliczony jest tekst "po arabsku".

Jak więc umieścić znaki interpunkcyjne we właściwym miejscu? Wystarczy utworzyć nowy kontekst kierunkowy dla naszego arabskiego tekstu. Wystarczy otoczyć go nowym elementem (np. span) i ustawić jego bazowy kierunek na RTL. W xHTML-u może to wyglądać następująco:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
Tytuł to "<span dir="rtl">مفتاح معايير الويب!</span>" po arabsku.

Zauważmy, że znacznik span znajduje się wewnątrz cudzysłowu – to część otaczającego go polskiego tekstu. Sprawdźmy rezultat naszej nowej deklaracji:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
Tytuł to "مفتاح معايير الويب!" po arabsku.

Znak wykrzyknika przejął kierunek z nowego kontekstu (ustalonego dla elementu span), zamiast od domyślnego kierunku bazowego dla akapitu.

Grupowanie serii kierunkowych#

Algorytm bidi działa całkiem nieźle kiedy jest tylko jeden poziom mieszanego tekstu. Może się zdarzyć sytuacja, że osadzony tekst (ten w cudzysłowach) również będzie dwukierunkowy. Kiedy pojawią się dwa, lub więcej zgrupowanych poziomów różnokierunkowych tekstów, będziemy potrzebować innego rozwiązania. Oto przykład niepoprawnie ukierunkowanego tekstu przez algorytm bidi:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
Tytuł to "פעילות הבינאום, W3C" po hebrajsku.

Kolejność hebrajskich słów jest poprawna, ale ze względu na to, że tekst "W3C" jest częścią hebrajskiej frazy, powinien pojawić się z prawej strony lewego cudzysłowu, a przecinek pomiędzy hebrajskim tekstem i "W3C". Innymi słowy powinno to wyglądać tak:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
Tytuł to "W3C ,פעילות הבינאום" po hebrajsku.

Ten problem pojawia się, bo kierunki tekstu ustalane są na podstawie ogólnego kontekstu LTR akapitu. Jednak wewnątrz hebrajskiego cytatu domyślnym kierunkiem tekstu powinien być RTL.

Aby rozwiązać ten problem musimy utworzyć nowy poziom osadzania. Robimy to analogicznie jak w przypadku przemieszczonych znaków neutralnych. Wystarczy otoczyć hebrajską frazę elementem (np. span) i ustawić jego bazowy kierunek na RTL. W xHTML-u może to wyglądać następująco:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
Tytuł to "<span dir="rtl">פעילות הבינאום, W3C</span>" po hebrajsku.

Zauważmy, że znacznik span znajduje się wewnątrz cudzysłowu – to część otaczającego go polskiego tekstu. Sprawdźmy rezultat naszej nowej deklaracji:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
Tytuł to "פעילות הבינאום, W3C" po hebrajsku.

Przykłady prezentowane do tej pory były bardzo proste. Cała treść może mieć więcej serii kierunkowych, przez co poziom skomplikowania się zwiększa. Przeanalizujmy poniższy przykład, gdzie górna linia przedstawia oczekiwany wynik wyświetlania, ale dolna linia jest wynikiem domyślnego działania algorytmu bidi.

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
Tłumaczenie to "في XHMTL 1.0 يتم تحقيق ذلك بإضافة العنصر المضمن bdo."

Tłumaczenie to "في XHMTL 1.0 يتم تحقيق ذلك بإضافة العنصر المضمن bdo."

Żeby poprawnie (wiersz 1) rozmieścić wszystkie serie kierunkowe we frazie hebrajskiej, musiałem całą frazę hebrajską (z wiersza 2) umieścić w elemencie zawierającym atrybut dir="rtl".

Atrybut dir#

Atrybut dir pozwala określić bazowy kierunek (lub nowy kontekst), od którego zależy sposób rozmieszczania serii kierunkowych. Przeglądarki domyślnie renderują tekst od lewej do prawej.

Standard Unicode definiuje dla większości znaków wrodzony kierunek przy wyświetlaniu, określa także kompleksowy algorytm do właściwego ustalania kierunku dla tekstów mieszanych. Reguły rządzące algorytmem mogą być źródłem niechcianych zachowań; czasami ciężko określić jaki będzie efekt przekształceń.

Kiedy dokument nie zawiera znaków z kierunkowością RTL, to przeglądarka nie musi stosować dwukierunkowego algorytmu Unicode. Kiedy dokument zawiera takie znaki, oraz jest on wyświetlany, algorytm dwukierunkowy musi zostać zastosowany. Dzięki temu samodzielne określanie właściwej prezentacji na ekranie monitora staje się zbędne.

Oto prosty przykład, w którym odwracam kierunek wyświetlania tych znaków, które nie mają w Unicode zdefiniowanego wrodzonego kierunku (np. nawiasy czy cyfry):

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<!-- od lewej do prawej -->
<p dir="ltr">1 2 3 40 50 612 (713 [814</p>

<!-- od prawej do lewej -->
<p dir="rtl">1 2 3 40 50 612 (713 [814 </p>

Efekt:

1 2 3 40 50 612 (713 [814

1 2 3 40 50 612 (713 [814

Jeszcze jeden wariant (nieco inny niż ten powyższy):

1 2 3 4 ( 612 713 [ 814 5 6 7

1 2 3 4 ( 612 713 [ 814 5 6 7

Należy zwrócić uwagę, że nawiasy zostają odpowiednio odwrócone ("lustrzane odbicie"), tak żeby pasowały do tekstu pisanego od strony prawej. Przypomnę tylko, że cyfry w arabskim są zapisywane w kierunku LTR. Kolejność wyświetlania liczb jest zmieniana, ale cyfr w poszczególnych liczbach już nie. Pojedyncza cyfra, oddzielona od innych białymi znakami, jest traktowana jak liczba.

Oto prosty przykład dla tekstu (który ma zdefiniowany nowy kontekst kierunkowy):

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<div>Treść w języku polskim...Treść w języku polskim...Treść w języku polskim...
	<p dir="rtl">Akapit w języku arabskim!!!</p>
	...dalsza część akapitu...dalsza część akapitu...dalsza część akapitu.
</div>

Efekt:

Treść w języku polskim...Treść w języku polskim...Treść w języku polskim...

Akapit w języku arabskim!!!

...dalsza część akapitu...dalsza część akapitu...dalsza część akapitu.

Jak łatwo zauważyć, zastosowanie atrybutu dir w rzeczywistości nie odwróciło kolejności całego tekstu. Na pierwszy rzut oka atrybut spowodował zamianę wyrównania tekstu zawartego w elemencie blokowym, tak że każdy nowy wiersz zaczął się z prawej strony, pozostawiając nieco poszarpane krawędzie po stronie przeciwnej.

Wprawne oko zauważy, że część arabska jednak została nieco przekształcona (z "Akapit w języku arabskim!!!" na "!!!Akapit w języku arabskim"). Łatwo to wyjaśnić. Cała treść składa się z dwóch serii kierunkowych. Pierwsza ma silny typ LTR ("Akapit..."), dlatego kolejność znaków nie ulega zamianie, cała część umieszczona jest jako pierwsza z prawej strony. Druga seria kierunkowa "!!!" ma neutralną kierunkowość, nie znajduje się między żadnymi znakami o silnym typie, dlatego dziedziczy kierunkowość RTL od rodzica, a następnie zostaje dołączona jako druga z prawej strony, tuż za pierwszą.

Sytuacja uległaby zmianie, gdybym faktycznie zapisał akapit w języku arabskim. Wówczas do głosu doszłyby wewnętrzne mechanizmy przeglądarki. Nadpisanie wrodzonej kierunkowości we wszystkich znakach danego fragmentu można wykonać za pomocą elementu bdo.

W odróżnieniu od elementu bdo, atrybut dir może być również zastosowany dla tabeli. Dzięki niemu nastąpi odpowiednia zamiana kolejności wyświetlania poszczególnych komórek tabeli. Oto kod dla prostej tabeli (kierunek domyślny dir="ltr"):

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<table border="1" style="font-size: 150%">
	<tr>
		<th>European Digits</th><td>0</td><td>1</td><td>2</td><td>3</td><td>4</td><td>5</td><td>6</td><td>7</td><td>8</td><td>9</td>
	</tr>
	<tr>
		<th>Arabic Digits</th><td>٠</td><td>١</td><td>٢</td><td>٣</td><td>٤</td><td>٥</td><td>٦</td><td>٧</td><td>٨</td><td>٩</td>
	</tr>
	<tr>
</table>

Efekt:

European Digits0123456789
Arabic Digits٠١٢٣٤٥٦٧٨٩

Efekt dla tej samej tabeli z atrybutem dir="rtl":

European Digits0123456789
Arabic Digits٠١٢٣٤٥٦٧٨٩

Dziedziczenie atrybutu#

Dwukierunkowy algorytm Unicode wymaga określenia bazowego kierunku tekstu dla elementów blokowych. Można to wykonać za pomocą zadeklarowania dla tych elementów atrybutu dir. Domyślną wartością dla atrybutu jest dir="ltr" (od lewej do prawej).

Kiedy ustawimy atrybut dir dla elementu blokowego, odziedziczony zostaje przez wszystkie pozostałe zagnieżdżone elementy blokowe. Ustawienie atrybutu dla zagnieżdżonego elementu przesłania (nadpisuje) odziedziczoną wartość.

Aby ustawić bazowego kierunek dla tekstu w całym dokumencie, należy zadeklarować atrybutu dir dla elementu html. Krótki przykład:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
		"http://www.w3.org/TR/html4/strict.dtd">

<html dir="rtl">

	<head>
		<title>...tytuł od prawej do lewej....</title>
	</head>

	<body>
		...tekst od prawej do lewej...
		<p dir="ltr">...tekst od lewej do prawej...</p>
		<p>...tekst od prawej do lewej (ponownie)...</p>
	</body>

</html>

Element bdo#

Dwukierunkowy algorytm Unicode oraz atrybut dir (dla dowolnego elementu) na ogół wystarczają do zarządzania tekstem o różnych kierunkach (w jednym pliku). Za odwrotną prezentację poszczególnych znaków odpowiada przeglądarka, która odczytuje wrodzony kierunek znaków ze standardu Unicode, i jeśli to konieczne, automatycznie wykonuje przekształcenia. Czasami zdarzają się sytuacje, kiedy rezultatem dwukierunkowego algorytmu Unicode będzie niewłaściwa prezentacja. Element bdo pozwala autorom stron wyłączyć dwukierunkowy algorytm na wybranych fragmentach tekstu. Można powiedzieć, że atrybut dir dla elementu bdo nadpisuje pierwotny (wrodzony) kierunek zdefiniowany przez Unicode.

Atrybut dir dla elementu bdo jest obowiązkowy.

Powróćmy do naszego szablonu głównego:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
polski1 HEBRAJSKI2 polski3 HEBRAJSKI4 polski5 HEBRAJSKI6

Załóżmy, że tekst ten został już wysłany w wizualnym porządku. Powodem tego może być standard MIME (RFC2045, RFC1556), który sprzyja wizualnemu porządkowi, tzn. wszystkie sekwencje znaków prawo-lewo zostają umieszczone od prawej do lewej w bajtowym strumieniu. We wszystkich mailach, powyższy tekst zostałby sformatowany następująco (włącznie z liniami przerwy):

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
  polski1   2IKSJARBEH    polski3
4IKSJARBEH    polski5   6IKSJARBEH

Przy wyświetlaniu przez przeglądarki internetowe dojdzie do konfliktu, ponieważ dwukierunkowy algorytm Unicode będzie chciał drugi raz zamienić kolejność w 2IKSJARBEH, 4IKSJARBEH, 6IKSJARBEH. Słowa hebrajskie wyświetlone zostałyby od lewej do prawej, zamiast od prawej do lewej.

Rozwiązaniem w tym przypadku może być nadpisanie algorytmu dwukierunkowego. Wystarczy treść maila umieścić w elemencie pre (w celu zachowania podziału wierszy), a każdą linię otoczyć elementem bdo z atrybutem dir="ltr":

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<pre>
	<bdo dir="ltr">polski1 2IKSJARBEH polski3</bdo>
	<bdo dir="ltr">4IKSJARBEH polski5 6IKSJARBEH</bdo>
</pre>

Element bdo powinien być stosowany w sytuacjach, kiedy należy zachować absolutną kontrolę nad porządkiem w określonej sekwencji znaków (np. dla wielojęzycznych numerów katalogowych). Polecenie może zostać zastąpione przez specjalne znaki Unicode.

W żywych przykładach, przy objaśnianiu dwukierunkowego algorytmu Unicode, często sięgałem po element bdo. Dzięki niemu mogłem wywołać konwersję na dowolnych znakach (niezależnie od ich wrodzonej kierunkowość).

Znaki kontrolne Unicode#

W standardzie Unicode zdefiniowano specjalne znaki, które odpowiedzialne są za określenie kierunku tekstu. (X)HTML oferuje analogiczne metody wprowadzane za pomocą znacznika <bdo> oraz atrybutu dir="", które dla webmasterów mogą być bardziej intuicyjne. Oto one:

Nazwa (Unicode)Kod (Unicode)Encja HEXEncja DECOdpowiednik xHTML
LRE (Left-to-Right Embedding)U+202A&#x202A;&#8234;dir="ltr"
RLE (Right-to-Left Embedding)U+202B&#x202B;&#8235;dir="rtl"
PDF (Pop Directional Format)U+202C&#x202C;&#8236;</bdo>
LRO (Left-to-Right Override)U+202D&#x202D;&#8237;<bdo dir="ltr">
RLO (Right-to-Left Override)U+202E&#x202E;&#8238;<bdo dir="rtl">

Spójrzmy na dwa analogiczne przykłady:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<!-- zapis w xHTML -->
<q lang="he" dir="rtl">...cytat w języku hebrajskim....</q>

<!-- zapis w Unicode -->
&#x202B;&#x05F4;...cytat w języku hebrajskim...&#x05F4;&#x202C;

Dla osób, które mają opanowany język xHTML, pierwszy wariant zazwyczaj będzie łatwiejszy w zastosowaniu. Jeśli ktoś chciałby zapoznać się ze szczegółami algorytmu może sięgnąć do źródła.

Dwukierunkowy algorytm Unicode potrafi automatycznie odwracać znaki tylko na jednym poziomie zagnieżdżenia. Aby osiągnąć dodatkowe poziomy zmiany kierunku (np. w pewnej części w treści liniowej), należy skorzystać z atrybutu dir dla elementu liniowego. Powróćmy do wcześniejszego szablonu:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
polski1 HEBRAJSKI2 polski3 HEBRAJSKI4 polski5 HEBRAJSKI6

Załóżmy, że bazowym językiem dokumentu zawierającym ten akapit jest język polski. Ponadto, powyższa polska sentencja zawiera hebrajską sekcję rozciągającą się od HEBRAJSKI2 do HEBRAJSKI4. W tej hebrajskiej sekcji znajdują się polskie cudzysłowy polski3. Przetwarzanie tekstu powinno odbyć się w następujący sposób:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
polski1 HEBRAJSKI2 polski3 HEBRAJSKI4 polski5 HEBRAJSKI6
		<----H---- --P---> <----H----

		<-------------H---------------

----------------------P-------------------------------->

Aby osiągnąć dwa osadzone zmiany kierunku, musimy dostarczyć dodatkowych informacji, co robimy poprzez określenie drugiego osadzenia jawnie. W tym przypadku użyjemy dodatkowego elementu span z atrybutem dir:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
polski1 <span dir="rtl">HEBRAJSKI2 polski3 HEBRAJSKI4</span> polski5 HEBRAJSKI6

W powyższym przykładzie do zmiany wielu osadzonych kierunków można było skorzystać także z odpowiednich znaków Unicode:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
polski1 #x202B;HEBRAJSKI2 polski3 HEBRAJSKI4&#x202C; polski5 HEBRAJSKI6

Unicode wprowadza jeszcze jeden rodzaj kodów sterujących. W xHTML-u znakom tym przypisano odpowiadające odwołania do znaku:

Polecenia przydają się do ręcznego poprawiania błędnie wyświetlonych znaków o neutralnym charakterze (np. znaków interpunkcyjnych). Zamiast tworzyć nowy kontekst kierunkowy (za pomocą znaczników lub odpowiadających im kodów Unicode), lepiej wstawić znaki punktowe.

Prosty przykład (omawiany już wcześniej), w którym prezentuję trzy analogiczne rozwiązania, które prawidłowo wyświetlą znak wykrzyknika:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<p>Tytuł to "<span dir="rtl">مفتاح معايير الويب!</span>" po arabsku.</p>
<p>Tytuł to "&#x202E;مفتاح معايير الويب!&#x202C;" po arabsku.</p>
<p>Tytuł to "مفتاح معايير الويب!&#x200F;" po arabsku.</p>

Efekt:

Tytuł to "مفتاح معايير الويب!" po arabsku.

Tytuł to "‮مفتاح معايير الويب!‬" po arabsku.

Tytuł to "مفتاح معايير الويب!‏" po arabsku.

Znak punktowy pozwala utworzyć nowe serie kierunkowe, ponieważ może wpłynąć na dziedziczenie kierunkowości sąsiadujących z nim znaków neutralnych.

Na koniec jeszcze jeden przykład z zastosowaniem znaków specjalnych:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<!-- dir="rtl" -->
<p>&#x202B;0 1 2 3 4 5 6 7 8 9&#x202C;</p>
<!-- <bdo dir="rtl"> -->
<p>&#x202E;ALE WKOŁO JEST WESOŁO&#x202C;</p>

Efekt:

‫0 1 2 3 4 5 6 7 8 9‬

‮ALE WKOŁO JEST WESOŁO‬

Znaki kontrolne Unicode vs polecenia xHTML#

Przy stosowaniu znaków kontrolnych Unicode zawsze istnieje ryzyko niezamierzonego pozagnieżdżania lub niezakończenia zakresów - zwłaszcza, że znaki same w sobie (jeśli nie zastosujemy encji HTML) nie mają wizualnej prezentacji. W przypadku zastosowania poleceń xHTML problem zostaje zmarginalizowany.

Znaczniki ułatwiają stosowanie dziedziczenia w elementach. Korzystanie w tym celu z kodów Unicode wymaga większej pracy. Za pomocą kodów kontrolnych ciężko uzyskać efekt odwróconych komórek w tabeli, czy wyrównania tekstu do prawej krawędzi.

Sama specyfikacja HTML 4.01 w wielu miejscach przestrzega przed stosowaniem obu podejść jednocześnie z powodu większego prawdopodobieństwa niewłaściwego zagnieżdżenia. Zaleca stosowanie wyłącznie poleceń xHTML-a, ponieważ gwarantuje to lepszą integralność strukturalną oraz łagodzi pewne problemy w prostych edytorach tekstowych. Oczywiście w żaden sposób nie zakazuje używania znaków kontrolnych Unicode.

Ponadto, 20 raport techniczny Unicode dla XML-a idzie jeszcze dalej. Wyraźnie zaleca stosowanie jedynie znaczników. Zaleca także, aby ignorować kody kontrolne Unicode, jeśli wykryte zostały w kontekście przeglądarki, a także automatycznie zastępować je przez odpowiadające im znaczniki (w trybie edycji). W dokumencie zawarto wiele innych uwag odnośnie stosowania pozostałych znaków Unicode oraz ich odpowiedników w postaci znaczników.

W większości przypadków znaczniki xHTML oraz znaki kontrolne Unicode mogą być stosowane zamiennie. Zdarzają się jednak sytuacje (głównie w językach znacznikowych), gdzie jedyną możliwością wpływu na kierunek tekstu będą znaki Unicode. Najprostszym przykładem będzie deklaracja wartości atrybutu:

  1. L
  2. K
  3. T'
  4. T
  5. A
  6. O
  7. Z'
  8. Z
  9. #
<p title="&#x202E;żartem&#x202C;">Najedź kursorem myszki na akapit (<code>title="żartem"</code>)!</p>

Efekt:

Najedź kursorem myszki na akapit (title="żartem")!

Nie ma możliwości bezpośredniego stosowania poleceń xHTML (odpowiedzialnych za kierunek tekstu) wprost w treści atrybutów. Każdy taki tekst będzie musiał być oznaczony za pomocą kodów Unicode. Kolejnym często stosowanym atrybutem może być alt="", także i w jego przypadku możliwe będzie określenie kierunku tekstu tylko i wyłącznie za pomocą znaków Unicode.

Podsumowanie#

Przyznam szczerze, że zagadnienia dotyczące kierunku wyświetlania tekstu są najtrudniejszymi, z jakimi miałem do czynienia opanowując język (X)HTML. Bardzo ciężko weryfikować informacje, ponieważ dotyczą tekstu pisanego w odwrotnym kierunku. Same znaki języków arabskich (i pochodnych) wyglądają bardzo egzotycznie. Wszystkie kursy online opisują temat pobieżnie, krótka informacja na temat elementu bdo i atrybutu dir to za mało, żeby opanować choćby podstawy. Nigdzie nie wspomniano nawet o wrodzonym kierunku dla każdego symbolu Unicode, symbolach bez wrodzonego kierunku, bezpośrednich znakach Unicode do określania kierunku tekstu itd.

Na domiar złego, przy wprowadzaniu znaków RTL do edytora tekstowego (w kolejności logicznej) są one automatycznie przestawiane. Testowałem kilka edytorów, ale wszystkie mają taką cechę, nie wiem czy można ją gdzieś wyłączyć. Wygląda to tak, jakby w edytorach na bieżąco działał algorytm dwukierunkowy. Co ciekawe, przeglądarki nie uruchamiają ponownie algorytmu na takim tekście. Żeby w przeglądarkach zaobserwować każdy aspekt przestawiania znaków można by wstawiać je w postaci encji. Niestety manewrowanie takimi przykładami byłoby bardzo niekomfortowe, nieczytelna forma utrudnia analizę i ewentualne wprowadzanie zmian.

Jeśli ktoś dokładnie przeanalizuje kod (w źródle strony) moich przykładów zauważy, że znaki RTL w wyrazach są już odpowiednio uporządkowane. Czyli w pliku źródłowym nie stosuję czystego zapisu logicznego. Przeglądarka wykonuje tylko pozostałą pracę (np. porządkowanie serii kierunkowych). Opis teoretyczny algorytmu bidi jest poprawny, jedynie praktyczne wykonanie zostaje nieco "uproszczone".

Osobiście nie rozumiem wszystkich niuansów tego tematu, dlatego opis ten może wydawać się nieco chaotyczny. Może w przyszłości uzupełnię tekst o bardziej precyzyjne informacje (pod warunkiem, że trafię na jakieś sensowne/przystępne źródło informacji). Jeśli coś przedstawiłem niejasno (albo błędnie) można do mnie napisać, jestem otwarty na wszelką krytykę. Ciężki temat, dlatego wszelkie uwagi będą mile widziane.

Pasek społecznościowy

SPIS TREŚCI AKTUALNEJ STRONY

Języki (H1) Kierunek tekstu (H2) Podstawowe pojęcia (H3) Kolejność tekstu (wizualna lub fizyczna) (H3) Dwukierunkowy algorytm Unicode (H3) Teoria (H4) Praktyka (H4) Kierunek bazowy (kontekst kierunkowy) (H5) Kierunkowe wyświetlanie znaków (H5) Seria kierunkowa (H5) Znaki neutralne (H5) Cyfry (H5) Problemy (H4) Przemieszczone znaki neutralne (H5) Grupowanie serii kierunkowych (H5) Atrybut dir (H3) Dziedziczenie atrybutu (H4) Element bdo (H3) Znaki kontrolne Unicode (H3) Znaki kontrolne Unicode vs polecenia xHTML (H4) Podsumowanie (H3)