> For the complete documentation index, see [llms.txt](https://ayakaleaf-pro.ayaka.space/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ayakaleaf-pro.ayaka.space/latex/zh-cn/shen-du-wen-zhang/51-unicode-utf-8-and-multilingual-text-an-introduction.md).

# Unicode、UTF-8 和多语言文本：简介

## Unicode 与 OpenType：字符与字形

现代 TeX 引擎，即 XeTeX 和 LuaTeX，之所以从 Knuth 最初的 TeX 引擎演进而来，很大程度上是为了跟上技术环境的发展，尤其是 Unicode（用于文本）和 OpenType（用于字体）。如今，通过使用诸如 [fontspec](https://ctan.org/pkg/fontspec?lang=en) 和 [unicode-math](https://ctan.org/pkg/unicode-math?lang=en)之类的包，LaTeX 用户可以访问由 OpenType 字体提供的极其复杂的排版能力——包括高级多语言排版和基于 OpenType 的数学排版（[由 Microsoft 首创](https://blogs.msdn.microsoft.com/murrays)).

然而，要想在 XeTeX/LuaTeX 中充分发挥 OpenType 字体的作用，熟悉一些背景主题/概念会很有帮助——尤其是在排查问题或为更高级/复杂的工作铺路时。例如，你可能会读到 XeTeX 和 LuaTeX 引擎使用“UTF-8 输入”，或者它们是“Unicode 感知”的；而进一步阅读 OpenType 字体时，还可能会提到诸如“Unicode 编码”、“OpenType‘字体特性’”、“字形”、“字形 ID”、“字形名称”等主题。我们的目标是对这些术语/主题做一个介绍，并搭建一个基本框架，说明它们之间的关系，并希望能为进一步的工作或问题解决提供支持。

我们打算涵盖的主题大致可以整齐地分为两个主要领域： *Unicode* 实际上，它所处的是文本/字符与文本编码的世界，而 *OpenType* 它所处的世界则是字体和字形的世界；当然，这两个世界是相互关联的，即使在这篇入门文章中也会有一些交叉。

### 我们要讨论哪些主题？

本文的主要重点是一些与 Unicode 相关的主题：从讨论“字符”的含义开始，再介绍文字系统/语言、Unicode 编码和 UTF-8——并辅以一个处理多语言文本文件的示例。后续文章将以本文为基础，涵盖与 OpenType 字体技术相关的背景主题。显然，在一篇博客文章的篇幅内，不可能试图对我们希望讨论的所有领域进行“深入探究”：我们明确的目标是提供一个总体框架，说明几个关键概念之间如何关联并协同工作。我们先从最基本的概念开始： *@*.

## 字符：一个基本构件

我们讨论的核心（以及 Unicode 的核心）有一个基本思想/概念，那就是“字符”的含义：这是那些在日常工作和交流中经常因使用而被“默认”的词之一。然而，从 Unicode、排版和字体技术的角度来看，我们需要更精确一些，明确“字符”到底是什么意思。例如，我们很自然地会把 **a** 和 *a* 看作不同的“字符”：‘粗体 a’ 和 ‘斜体 a’。但事实并非如此：它们只是同一个基本字符的不同视觉表示，Unicode 赋予它的正式名称是 [LATIN SMALL LETTER A](http://unicode.org/charts/PDF/U0000.pdf).

Unicode [将字符定义为](http://www.unicode.org/glossary/#character) 如下：

> “书面语言中具有语义价值的最小组成部分；指抽象的含义和/或形状，而不是某个特定的形状……”

它清楚地区分了字符的具体 *外观* 形状 *和含义*.

你可以把字符看作语言的基本单元，或者更准确地说，是一种 *文字系统*文字系统 *和含义* 字符的抽象身份 *作用和用途* ，也就是作为最终构成文字系统/语言的一组构件中的一个。

### 文字系统与语言

有两个重要概念值得简要提及： *文字系统* 和 *语言*和语言。Unicode 网站提供了一个很有用的 [文字系统定义](https://www.unicode.org/standard/supported.html):

> “Unicode 标准编码的是文字系统，而不是语言。当有多种语言的书写系统共享一组历史上有关联的图形符号时，这些图形符号的并集会被视为一组用于编码的字符，并被识别为单一的文字系统。”

以 [维基百科上的一个例子](https://en.wikipedia.org/wiki/Script_\(Unicode\))来看，拉丁文字系统由一组特定的 [字符集合](http://unicode.org/charts/) 构成，这些字符被用于多种语言：英语、法语、德语、意大利语等等。当然，并非所有在拉丁文字系统中定义的字符都会被所有基于拉丁文字系统的语言使用——例如，英语字母表中不包含法语或德语等其他欧洲语言中常见的带重音字符。

### OpenType 字体：文字系统与语言

到这里，我们将从 Unicode 过渡到 OpenType 字体，因为文字系统和语言这两个概念在 OpenType 字体技术中也扮演着极其重要的角色。

使用同一种 [文字系统](http://www.unicode.org/glossary/#script) 文字系统的语言，在显示（排版）某种语言文本时，可能各自拥有不同的排版传统。一个很好的例子就是土耳其语以及 [无点 i 的行为](https://en.wikipedia.org/wiki/Dotted_and_dotless_I) （见该页关于连字的说明）。与文字系统/语言相关的排版“规则”通过所谓的文字系统和语言 *标签* 标签 [fontspec 宏包](https://ctan.org/pkg/fontspec?lang=en).

#### 深入查看一个 OpenType 字体：文字系统/语言

为了更清楚起见，这里有一张截图，展示了免费的 [Scheherazade OpenType 字体](http://software.sil.org/scheherazade/download/) 在（同样免费的） [Microsoft VOLT](https://www.microsoft.com/en-us/Typography/volt.aspx) 字体编辑软件中打开的样子。在这张图里，你可以看到 Scheherazade 中内置的文字系统、语言和排版特性——使用 VOLT 你可以为 Scheherazade 添加额外的特性和功能，但这已经远远超出了本文的范围！

![在 Microsoft VOLT 中打开的 Scheherazade OpenType（TrueType 风格）字体](/files/cf18d85c3e4d4501ef41aa252eb35dcd7b2bb183)

从这张截图可以看出，Scheherazade 支持阿拉伯文和拉丁文字系统，并且为若干使用阿拉伯文字系统的语言提供了进一步的专门支持——这些支持通过上方绿色边框框中的所谓 OpenType 特性来实现。我们不会深入介绍这些特性的细节，但这里想传达的信息是：高质量的 OpenType 字体内部包含了大量智能信息，随时可供能够利用字体内部排版规则的排版软件使用。

感兴趣的读者可以浏览 OpenType 标签注册表，查看 [文字系统标签](https://www.microsoft.com/typography/otspec/scripttags.htm) 和 [语言标签](https://www.microsoft.com/typography/developers/opentype/languagetags.aspx) 在 OpenType 规范中当前使用的情况。

### 回到字符：不同的字符角色

构成一个文字系统（或语言）基本元素的字符，并不都扮演相同的角色。例如，在大多数语言中都有用于 *标点*的字符、用于数字 *数字* 的字符，以及我们认为是 *字母* 的字符，而对于某些文字系统，这些字母还存在大写和小写形式。字符这一概念相当宽泛，Unicode 标准还包括一些专门字符，它们 *并不设计用于显示* ，而其作用是“控制文本的解释或显示”。例如，在排版某些阿拉伯文时，你可能希望强制或阻止某些字符的连接行为；Unicode 标准提供了特殊的控制字符来实现这一点：所谓的 [ZERO WIDTH JOINER](https://en.wikipedia.org/wiki/Zero-width_joiner) 和 [ZERO WIDTH NON-JOINER](https://en.wikipedia.org/wiki/Zero-width_non-joiner)。这些字符并不是为了显示而设计的，软件在处理文本以产生预期的视觉效果时，会把它们“吸收”掉。

Unicode 标准中规定的所有字符都会被分配一组属性，这些属性实际上描述了 Unicode 编码中每个字符的作用和用途——诸如 LATIN SMALL LETTER A 这样的字符名称，只是字符属性列表中的一个元素。这些属性在 [Unicode 字符数据库（UCD）](http://www.unicode.org/reports/tr44/) 中有完整说明，并广泛用于计算机文本处理操作，例如搜索、排序、拼写检查等等。列出 Unicode 字符属性的数据文件也 [可供下载](http://www.unicode.org/Public/UCD/latest/).

在分配给每个字符的属性中，与我们的讨论最相关的是一个 *数字标识符* ，它由其 Unicode 编码分配；我们现在就来谈这一点。

### 字符：数字与编码

这显然是老生常谈，但计算机和其他数字设备本来就是用来存储和处理数字数据的：那么这和文本有什么关系呢？当你使用电脑键盘输入文本，或者轻触移动设备屏幕时，你的按键会被转换成数字，这些数字代表着你正在输入的字符序列。

在某个时刻，你可能希望通过电子邮件、短信，或者通过推文或某种社交媒体帖子之类的在线通信传递那段文本（一个数字序列）。显然，你编写文本的设备以及其接收者使用的设备必须以某种方式就哪些数字代表哪些字符达成一致。否则，你的文本可能无法在接收者的设备上正确显示。

要让今天的全球通信正常运作，发送和接收设备需要某种“双方约定的约定”，以便用一组特定数字来表示一组特定字符。这种约定叫做 *编码*码位 *事实上已成为* 全球标准。

## Unicode：用于存储文本的比特与字节

Unicode 是一个极其庞大的标准，涵盖的远不止文本编码，但这里我们只关注它提供的编码部分。

#### 比特、字节以及多少个字符？

我们提到过，设备以数字的形式存储和表示文本——更具体地说，字符会以整数形式存储：即整个数字。为了理解这对 Unicode 编码意味着什么，我们需要做一个 *非常* 简短的、 *非常* 基础的回顾，了解计算机如何存储整数（我们并不打算深入计算机科学）。

长话短说，如今的台式机或手持设备以离散的“块”来存储整数，这些块可以是 1、2、4 或 8 字节长。每种存储单元都能存储一个整数，其可存储的最大正值取决于每个存储单元所包含的比特总数：

* 1 字节（8 位）：最大正整数为 255；
* 2 字节（16 位）：最大正整数为 65535；
* 4 字节（32 位）：最大正整数为 4,294,967,295；
* 8 字节（64 位）：最大正整数为 18,446,744,073,709,551,615。

实际上，Unicode 标准使用 0 到 1,114,111 之间的数字来编码世界上所有字符，因此只需要 21 位就能编码完整范围。我们可以通过注意到：包含 n 位的存储单元可以表示从 0 到某个最大值的任意正整数，来理解这一点 $$2^n -1$$；因此：

* 20 位中可存储的最大值是 $$2^{20} -1 = 1,048,575$$ （太小）；
* 21 位中可存储的最大值是 $$2^{21} -1 = 2,097,151$$ （足够大）。

我们已经注意到，计算机以 1、2、4（或 8）字节的单位存储数据（数字），那么如果我们必须存储最大 Unicode 值 1,114,111 以下的数值，存储单元需要多大呢？显然，1 字节大小的存储单元最多只能容纳 255，而 2 字节可以存储 65535：这两者都不足以存储 Unicode 编码的全部字符范围。下一个可用选项是 4 字节大小的存储单元，它最多可以存储 4,294,967,295，这远远超过我们的实际需要。因此，如果我们选择 4 字节作为存储单元，当然有足够空间存储所有 Unicode 值，每个字符都将作为一个需要 4 字节（32 位）的整数来存储。然而，用 4 字节来存储所有内容会非常浪费空间，因为即使是最大的 Unicode 值也只需要最多 21 位——这意味着如果用 32 位来存储，那么这 32 位中的 11 位将永远不会被使用。

**注意**：虽然 Unicode 的范围从 0 到 1,114,111，但该范围内并非每个值都实际使用：出于技术原因，有些值被认为不能作为实际的 Unicode 字符使用。

### 那么，什么是 UTF-8？

如果你阅读有关 XeTeX 或 LuaTeX 的资料，你几乎一定会遇到这样的说明：这些 TeX 引擎以“UTF-8 格式”读取文本和 LaTeX 输入文件。那么“UTF-8 格式”是什么，它与 Unicode 又有什么关系？在 Unicode 术语中，用于编码世界上字符的 1,114,112 个值（范围从 0 到 1,114,111）中的每一个都称为一个 [码位](http://www.unicode.org/glossary/#code_point).

我们已经看到， *理论上*，为了表示 Unicode 代码点的完整范围，我们需要以每个字符 4 字节的方式存储所有 Unicode 编码文本。然而，在实践中，一些相当聪明的人发明了一种简单方法，可以把单个 Unicode 数字（码位）表示为一个 *序列* 由更小的数字组成的序列，而这些较小数字中的每一个都存储在一个字节中：这一过程 *把* 一个单个（更大的）整数转换成一串更小的（按字节计的）整数。由于这种转换，我们文本文件中的字符不再各自由一个单一数值表示：每个字符都会变成一个 *多字节序列*——文本文件中的 1 到 4 个（连续）字节都可以表示一个单独的 Unicode 字符（即其码位值）。

UTF 代表 *Unicode 转换格式* 这里的关键词是 *转换*。本质上，你可以把 UTF-8 看作一种“配方”或算法，用来把单个 Unicode 码位值转换成由 1 到 4 个按字节计的部分组成的序列。Unicode 码位值越大，使用 UTF-8 格式表示它所需的单字节数量也就越多。

创建 UTF-8 有技术和历史上的原因，UTF-8 的发明故事 [记录在一封 2003 年的引人入胜的电子邮件中](https://www.cl.cam.ac.uk/~mgk25/ucs/utf-8-history.txt)，其中在邮件开头附近有这样一句：

> “That’s not true. UTF-8 was designed, in front of my eyes, on a placemat in a New Jersey diner one night in September or so 1992.”

#### 示例：阿拉伯字母 ل

让我们以阿拉伯字母 ل（Unicode 名称为 ARABIC LETTER LAM）为例，它被分配的 Unicode 码位值是 1604（十进制）或 0644（十六进制）：它在 UTF-8 中的表示是 *一个两字节* 序列 D9 84（十六进制），换算成十进制则是 217 132。将 UTF-8 用作文本存储格式时，与其用文本文件中的单个数字 1604 来表示 ل，不如把它转换成两个按字节计的值：217 和 132——字符 ل 于是被存储为一个 *两字节序列*。希望更深入探索 UTF-8 算法的读者，可以在我的 [个人博客网站](http://www.readytext.co.uk/?p=1284).

当某个软件（例如 XeTeX 或 LuaTeX）以 UTF-8 格式读取文本时，该软件需要确定该文件中每个字符的 Unicode 值，因此它会使用一种算法来 *反向执行* 逆转 UTF-8 转换过程。通过那个“反向算法”，这两个字节（217 和 132）会重新组合生成整数 1604，然后就能将其识别为阿拉伯字母 ل 的 Unicode 码位值。

因此，总的来说，UTF-8 实际上只是一种用于存储和传输 Unicode 编码文本的中间数据格式。

**注意**：有些系统选择使用每个字符 32 位来存储/表示文本，这称为 [UTF-32](https://en.wikipedia.org/wiki/UTF-32)——另外还有 [UTF-16](https://en.wikipedia.org/wiki/UTF-16) ，但 UTF-8 是存储 Unicode 编码文本最常见的方式。

## 多语言 TeX 文件：XeTeX 和 LuaTeX

XeTeX 和 LuaTeX 都能够进行非常复杂的多语言排版，不过它们实现这一点的机制相当不同，反映了各自引擎的设计/开发理念。我们不会深入探讨这一点，只是指出 XeTeX 引擎包含一些（内置于其可执行文件中的）软件组件，而这些组件在 LuaTeX 中并不存在——最显著的是用于一种称为 *OpenType 字形塑造* （例如，通过一个名为 [HarfBuzz](https://www.freedesktop.org/wiki/Software/HarfBuzz/)).

相比之下，LuaTeX 采用了不同的方法：它并不把功能直接构建进实际的 TeX 引擎中，而是提供了极其丰富的一组命令（TeX 原语）以及一个非常强大的 [基于 Lua 的 API](/latex/zh-cn/shen-du-wen-zhang/07-an-introduction-to-luatex-part-1-what-is-it-and-what-makes-it-so-different.md) ，开发者可以通过它构建同样先进的多语言排版解决方案。尽管 LuaTeX 的理念可能会给 LaTeX 包开发者带来额外工作，但它提供了很大的额外灵活性，因为解决方案并不是被“硬编码”在 LuaTeX 引擎本身中，而是由 TeX 和 Lua 代码——或者用 C/C++ 编写的插件——构建出来的。

**补充说明**：希望进一步探索迷人但复杂的 OpenType 字形塑造世界的读者，可能会有兴趣阅读关于一个出色的开源库 [HarfBuzz](https://www.freedesktop.org/wiki/Software/HarfBuzz/)——它被许多应用程序使用，包括 Firefox、Chrome 和 LibreOffice，当然也包括 XeTeX。本文作者曾使用 HarfBuzz 创建 [用于阿拉伯语排版的 LuaTeX 插件](http://www.readytext.co.uk/?p=3186).

如今很常见（例如在社交媒体上）传输包含多种语言字符的文本，而存储多语言文本的 UTF-8 文本文件很容易包含在 UTF-8 中表示长度为 1、2、3 或 4 个字节的字符。因此，从效果上说，UTF-8 文本文件只是一个单字节流，但该文件中的每个实际字符都可能占用 1 到 4 个字节：单个字符已经变成了 *多字节序列*.

为了进一步探讨处理（排版）多语言文本的一些关键方面，我们将使用一个包含阿拉伯文字系统的示例，因为阿拉伯语为我们提供了讨论多个概念的空间。

#### 补充说明：阿拉伯文字系统

该 [阿拉伯文字系统](https://en.wikipedia.org/wiki/Arabic_script) 以连写风格书写，从右到左阅读和书写。每个阿拉伯字母理论上可根据以下情况采用 4 种不同形状之一：

* 它是否以单独、独立（孤立）的字符形式显示（不与其他任何内容相连）；
* 它是否出现在一个词中——位于词首、词中或词尾：分别称为 *初始*, *中间* 和 *定稿* 形式，分别如此。

阿拉伯文字系统中的每个字符都有自己的一套连接规则，并且在其左侧、右侧或左右两侧有其他字符时，形状/外观可能会改变，也可能不会改变。想进一步探索的读者可以找到一个 [完整列表见维基百科](https://en.wikipedia.org/wiki/Template:Arabic_alphabet_shapes/joining).

#### 示例：UTF-8 中的阿拉伯文和英文文本

假设我们创建一个包含英文和阿拉伯文单行文本的 UTF-8 文本文件：This is العَرَبِيَّة text!

这一行文本包含 3 个空格字符、11 个英文（拉丁文字系统）字符和 12 个阿拉伯字符（尽管这可能并不马上显而易见）。当将其保存为 UTF-8 文本文件时，它占用了 38 字节的存储空间，原因如下：

* **拉丁文字系统**：空格加英文文本：14 × 1 字节字符 = 14 字节；
* **阿拉伯文字系统**：12 个阿拉伯字符 × 每个字符 2 字节 = 24 字节。

合计为 14 + 24 = 38 字节。

#### 进一步深入

如果我们把示例文本保存为一个名为 `arabic.txt` 的 UTF-8 文件，并在十六进制编辑器中打开它，就可以检查其中的实际字节。通过研究下面这张带注释的截图，你可以看到阿拉伯文本按每个字符 2 个字节存储：

![一个在十六进制编辑器中打开的、包含英文和阿拉伯文的 UTF-8 文本文件。](/files/e1dfd4ffacf610707e69a711f38deeb228d44eea)

一个在十六进制编辑器中打开的、包含英文和阿拉伯文的 UTF-8 文本文件。你可以清楚地看到，拉丁文字系统的字符只需一个字节，而阿拉伯文字系统的字符则按每个字符两个字节存储。

你可以从这张截图中得出几点观察：

* 阿拉伯文本按从左到右的顺序存储，而字符是阿拉伯字母和元音符号的原始未塑形（孤立）版本；
* 在拉丁文字 “This is ” 之后，没有任何额外信息告诉读取该文件的任何软件，下一个字符属于阿拉伯文字系统。

如果你要排版一个多语言文档（例如同时包含英文和阿拉伯文），那么在读取/处理输入文本文件（作为字节流）时，XeTeX 或 LuaTeX 必须能够检测每个字符的起始和结束，并读取正确数量的字节，以便逆转 UTF-8 转换并生成相应的 Unicode 码位。正是 UTF-8 算法本身使软件能够做到这一点：它能检测每个单独字符的第一个字节，以及为了计算相应 Unicode 码位需要读取多少个字节。UTF-8 使用起来很简单，但确实相当巧妙。

#### 逻辑顺序、显示顺序与 OpenType 字形塑造

如果你仔细看上面的阿拉伯文（العَرَبِيَّة），可能很难看出我们的文本文件确实包含 12 个独立的阿拉伯字符——尤其是如果你不熟悉阿拉伯文字系统的话！不过，如果你仔细数一下上面截图右侧显示的阿拉伯字符，就会发现总共有 12 个。

对于阿拉伯语等复杂文字系统语言，我们的文本文件 *存储* 以及你 *在屏幕上看到的* 确实大不相同！当你在例如浏览器中查看那段文本时，所看到的内容是（取决于所用字体）： *非常* 确实大不相同！当你在例如浏览器中查看那段文本时，所看到的内容是（取决于所用字体）：

![排版后的阿拉伯文本图像](/files/23d8f417c80c4245ec045ebdd33eca4bda09bb91)

但正如上面的截图所示，UTF-8 文本文件实际包含的是：

![未排版的阿拉伯文本图像（孤立字符）](/files/e41ba6ccdad2af1b5bc4e44fb68a76654a3cab5c)

即使你不熟悉阿拉伯文字系统的连写特性，也能清楚地看到：当阿拉伯字符从文本文件传递到屏幕上的排版和/或显示（作为字形）时，“某些东西”已经发生了变化。如果你习惯于用 TeX/LaTeX 处理简单文字系统语言，例如基于拉丁字母的语言，这确实会非常令人困惑！

这里涉及一些重要概念，因为 Unicode 文本文件负责存储……也就是文本（Unicode），而排版和显示系统则负责使用字体和字形（OpenType）：

* 文本文件把阿拉伯字符按从左到右的顺序保存，但阿拉伯语是从右到左阅读/显示的：文本文件以所谓的 *逻辑顺序*;
* 文本文件中包含的单个字符，看起来与屏幕上呈现的实际显示效果截然不同：文本文件中存放的是阿拉伯字符的孤立、未连接形式。

#### 这是怎么回事？

在文本文件中，阿拉伯文以从左到右的孤立形式字符序列存储：如果你想想看，文本文件保存阿拉伯文本的顺序/序列 *就是其输入时的顺序* （ *逻辑顺序*）。只有当该文本被处理用于显示，或进行排版时，它才会以正确的阅读顺序显示，这通常称为 *视觉顺序* 或 *显示顺序*；此外，阿拉伯字符的孤立形式会被 *塑形* 成排版上正确的显示版本。可以这样理解：一个简单的文本文件必须以最基本的形式存储文本（Unicode 字符）：原始、未塑形的单个文本字符——系统软件的任务是根据显示设备上可用的操作系统、字体以及排版/渲染软件，将这些字符渲染出来供显示。

当该文件中的阿拉伯文本被排版/显示时，它会经历一个称为 *整形*。单个阿拉伯字符会被转换为经过塑形的字形，这些字形可根据阿拉伯文字系统和书写系统的连接规则，正确表示每个字符所需的变体。此外，使用优质 OpenType 字体的高质量排版软件还会通过一个称为 *OpenType 字形塑造*——一种涵盖广泛排版操作的过程，这些操作可能包括：

* 将多个单独的字形替换为一个复杂的连字字形（在阿拉伯语中非常常见），或
* 定位操作，例如根据阿拉伯语元音位于哪个字形的上方或下方来调整它们的位置。

![显示阿拉伯文在排版时所经历的变换的图像](/files/341391e50ff41ef80be382d73ac82aa16748a732)

逻辑顺序与视觉（显示）顺序之间的差异。在这张图中，你可以看到，存储在文本文件中的阿拉伯字符在显示或排版时会经历重新排序和字形整形。

先进的 OpenType 字体的设计者和创作者会投入大量时间与专业知识，以提供字体中内置的复杂排版功能。

要关闭应用于阿拉伯文本的字形整形，我们可以使用优秀且免费的 [BabelPad](http://www.babelstone.co.uk/Software/BabelPad.html) Unicode 文本编辑器（仅限 Windows），它允许你禁用字形整形，以查看文本文件中实际存在的原始、单独未连接（未整形）字符——请参见这个组合截图的下半部分：

![显示 BabelPad 文本编辑器关闭 OpenType 字形整形能力的图像](/files/d38b23c1c7cb223c6acace2fe8ea119d9ae9d21e)

使用 BabelPad Unicode 文本编辑器开启 OpenType 字形整形（上图）或将其关闭（下图）。关闭 OpenType 字形整形会使编辑阿拉伯文本容易得多。

逻辑顺序与显示顺序的概念，再加上字形整形的过程，在你第一次在编辑或排版包含阿拉伯语等复杂文字脚本的多语言文本文件时，可能会相当令人困惑：希望以上内容已经有助于避免一些初始的困惑。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://ayakaleaf-pro.ayaka.space/latex/zh-cn/shen-du-wen-zhang/51-unicode-utf-8-and-multilingual-text-an-introduction.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
