Lewati ke konten

Merender HTML Arab kanan-ke-kiri

Render HTML kanan-ke-kiri (RTL) menjadi PDF dengan writeHtml(). Tetapkan properti CSS direction: rtl dan daftarkan font yang mendukung Arab. Mesin menata ulang teks ke urutan visual dengan Unicode Bidirectional Algorithm (UAX #9) dan membentuk huruf Arab ke bentuk kontekstualnya. Resep ini merender faktur kecil berbahasa Arab. RTL berlaku untuk bahasa Arab, Ibrani, Persia, dan Urdu. Teks Ibrani ditata ulang tetapi tidak dibentuk, dan hal itu memang tepat untuk aksara tersebut.

Terminal window
composer require nextpdf/core

Anda juga memerlukan font TrueType atau OpenType yang mendukung Arab. Peta karakter font tersebut harus mencakup blok Arabic Presentation Forms-B. Noto Naskh Arabic dan Amiri adalah jenis huruf berlisensi terbuka yang cocok.

Untuk rendering RTL, Anda memerlukan dua masukan: properti CSS direction: rtl dan font Arab yang terdaftar.

direction: rtl memberi tahu tata letak agar menempatkan teks dari kanan ke kiri. Mesin kemudian menggunakan Unicode Bidirectional Algorithm (UAX #9) untuk menyelesaikan urutan visual. Konten campuran tersusun dengan benar: kata Latin, kata Arab, dan angka masing-masing mempertahankan arahnya sendiri. Sebuah angka yang mengikuti teks Arab tetap mempertahankan urutan digit dari kiri ke kanan.

Aksara Arab adalah aksara kursif, sehingga setiap huruf memakai glif yang berbeda berdasarkan huruf-huruf di sekitarnya. Mesin memilih bentuk awal, tengah, akhir, atau terpisah untuk setiap huruf dan menerapkan ligatur Lam-Alef. Pembentukan kontekstual ini memerlukan font yang peta karakternya mencakup blok Arabic Presentation Forms-B. Font yang hanya berisi Latin, termasuk jenis huruf standard-14, tidak dapat menggambar Arab.

Di dalam tabel, setiap sel ditata ulang dan dibentuk secara terpisah, lalu sel-sel disejajarkan ke tepi awal: tepi kanan di bawah direction: rtl. Nilai logis text-align start dan end diselesaikan terhadap arah, sehingga start dipetakan ke tepi kanan untuk konten RTL.

Tetapkan arah dengan properti CSS direction. Atribut HTML dir tidak dipetakan ke properti tersebut. Lihat RTL — batasan saat ini untuk mengetahui batas implementasi saat ini.

SimbolLokasiPeran
Document::writeHtml(string $html): staticNextPDF\Core\Concerns\HasTextOutputMerender fragmen HTML di posisi kursor saat ini.
FontRegistry::register(string $fontFile, string $alias = '', int $fontIndex = 0): FontInfoNextPDF\Typography\FontRegistryMendaftarkan jenis huruf Arab dengan sebuah alias.
DocumentFactory::create(): DocumentNextPDF\Core\DocumentFactoryMembuat dokumen yang membaca registry yang telah Anda isi.

Contoh ini menggunakan properti CSS berikut: direction, font-family, text-align. Rujuk font yang sudah terdaftar di CSS font-family melalui alias registry-nya.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\DocumentFactory;
use NextPDF\Graphics\ImageRegistry;
use NextPDF\Typography\FontRegistry;
$fontRegistry = new FontRegistry();
$fontRegistry->register(__DIR__ . '/NotoNaskhArabic-Regular.ttf', alias: 'ArabicFont');
$documentFactory = new DocumentFactory($fontRegistry, new ImageRegistry(maxCacheBytes: 0));
$doc = $documentFactory->create();
$doc->addPage();
$doc->writeHtml(
'<div style="direction: rtl; font-family: \'ArabicFont\';">'
. '<h1>فاتورة</h1>'
. '<p>المبلغ الإجمالي 380.00</p>'
. '</div>'
);
$doc->save(__DIR__ . '/rtl-arabic.pdf');

Judul dirender dari kanan ke kiri, sementara digit 380.00 tetap dari kiri ke kanan di dalam kalimat Arab.

Contoh mandiri ini merender tabel faktur berbahasa Arab. Setiap sel memiliki direction: rtl dan font Arab yang terdaftar, sehingga mesin menata ulang serta membentuk setiap baris, lalu menyejajarkan sel ke tepi kanan.

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\DocumentFactory;
use NextPDF\Graphics\ImageRegistry;
use NextPDF\Typography\FontRegistry;
// Supply an Arabic-capable face whose cmap covers Arabic Presentation Forms-B.
// Embed only fonts you are licensed to embed.
$fontPath = __DIR__ . '/NotoNaskhArabic-Regular.ttf';
if (!is_file($fontPath)) {
fwrite(STDERR, "Arabic font not found at {$fontPath}\n");
exit(1);
}
$fontRegistry = new FontRegistry();
$fontRegistry->register($fontPath, alias: 'ArabicFont');
$documentFactory = new DocumentFactory($fontRegistry, new ImageRegistry(maxCacheBytes: 0));
$doc = $documentFactory->create();
$doc->setTitle('Arabic invoice');
$doc->addPage();
$html = <<<'HTML'
<div style="direction: rtl; font-family: 'ArabicFont'; font-size: 12pt;">
<h1>فاتورة</h1>
<table style="width: 100%; border-collapse: collapse;">
<tr>
<th style="border: 1px solid #333; padding: 6px;">الوصف</th>
<th style="border: 1px solid #333; padding: 6px;">المبلغ</th>
</tr>
<tr>
<td style="border: 1px solid #333; padding: 6px;">خدمات استشارية</td>
<td style="border: 1px solid #333; padding: 6px;">380.00</td>
</tr>
<tr>
<td style="border: 1px solid #333; padding: 6px;">الإجمالي</td>
<td style="border: 1px solid #333; padding: 6px;">380.00</td>
</tr>
</table>
</div>
HTML;
$doc->writeHtml($html);
$out = getenv('NEXTPDF_OUT');
$doc->save($out !== false ? $out : __DIR__ . '/render-rtl-arabic-html.pdf');
echo "Wrote the Arabic invoice PDF\n";
HTML;$doc->writeHtml($html);$out = getenv('NEXTPDF_OUT');$doc->save($out !== false ? $out : __DIR__ . '/render-rtl-arabic-html.pdf');echo "Wrote the Arabic invoice PDF\n";">
  • Daftarkan font sebelum Anda membangun dokumen. Document::createStandalone() membangun registry-nya sendiri dan tidak dapat melihat jenis huruf yang Anda daftarkan di tempat lain. Bangun dokumen melalui DocumentFactory agar penulis membaca registry Anda, seperti pada kedua contoh.
  • Cocokkan CSS font-family dengan alias registry. Nama yang Anda berikan ke register(..., alias: 'ArabicFont') adalah nama yang Anda rujuk dalam CSS.
  • Gunakan CSS direction, bukan atribut HTML dir. Hanya properti CSS yang mengubah tata letak.
  • Angka setelah teks Arab tetap dari kiri ke kanan. Ini mengikuti UAX #9: sebuah angka Eropa setelah huruf Arab diselesaikan menjadi angka Arab dan mempertahankan urutan digitnya, sehingga 380.00 tidak dibalik.

Implementasi saat ini menata ulang dan membentuk teks RTL serta menyejajarkan sel tabel. Batasan berikut masih ada. Ke depannya, masing-masing memerlukan kotak baris inline-formatting per baris:

  • Perataan blok dan inline di luar tabel. Teks tingkat blok dan inline di luar sel tabel ditata ulang dan dibentuk, tetapi dirender dari tepi awal (kiri). Perataan kanan atau tengah untuk teks non-tabel, serta distribusi text-align: justify, belum diterapkan. Sel tabel sudah disejajarkan.
  • Atribut HTML dir tidak dipetakan ke direction. Setel arah dengan properti CSS direction.
  • Resolusi bidirectional bersifat per text run. Karakter netral tidak diselesaikan melintasi dua elemen inline, seperti sebuah <span> di samping sebuah <b>, pada baris yang sama.
  • Kolom Arab yang sempit diukur berdasarkan teks logis. Pemenggalan baris diukur berdasarkan teks logis sebelum pembentukan, sehingga kolom Arab yang sangat sempit dapat memenggal baris sedikit lebih awal atau lebih lambat.
  • Arab yang dibentuk memerlukan cakupan Presentation Forms-B. Jenis huruf harus mencakup blok Arabic Presentation Forms-B. Dukungan untuk font yang hanya mengandalkan substitusi OpenType GSUB, serta jalur pembentukan HarfBuzz, merupakan pekerjaan di masa depan. Font non-Arab tidak dapat menggambar Arab.

Rendering berskala linier terhadap jumlah glif. Penataan ulang bidirectional dan pembentukan kontekstual berjalan per baris dan menambahkan faktor konstan kecil dibandingkan dengan teks kiri-ke-kanan. Anggaran resep ini adalah wall_ms: 1500, peak_mb: 64.

Validasi panjang string yang dipasok pengguna agar ukuran keluaran tetap terbatas. Mesin merender teks, tidak menafsirkannya, dan tidak menjalankan skrip apa pun. Jika Anda memuat font dari sumber @font-face jarak jauh, kebijakan sumber daya eksternal yang aman mengatur proses pengambilannya; sebaiknya gunakan berkas font lokal agar keluaran dapat diprediksi.

PernyataanSpesifikasiKlausareference_id
Urutan visual dihasilkan dengan membalik character run dari level tertinggi hingga level ganjil terendah.Unicode UAX #9§3.3.6 Rule L2 (uax9#3.3.6.p13)814977a77019d728dc562a612098a82dc260f6844f5998eca5fe7a3baf3394af
Sebuah angka Eropa setelah huruf Arab diselesaikan menjadi angka Arab, sehingga digitnya mempertahankan urutan kiri-ke-kanan.Unicode UAX #9§3.3.4 Rule W2 (uax9#3.3.4.p9)5747405357772797d62b3f4ba79328557fa0c4273a1dd5ffa8d996f24c78e120

Pembentukan kontekstual Arab (bentuk awal, tengah, akhir, dan terpisah ditambah ligatur Lam-Alef) adalah kapabilitas mesin terverifikasi yang dicakup oleh suite pengujian, bukan klaim konformansi tersendiri. Ini memerlukan font yang peta karakternya mencakup blok Arabic Presentation Forms-B.

Tidak berlaku.