Web 上的字符串:语言和方向元数据

W3C 组说明

关于本文档的更多详细信息
此版本:
https://www.w3.org/TR/2024/NOTE-string-meta-20241017/
最新发布版本:
https://www.w3.org/TR/string-meta/
最新编辑草案:
https://w3c.github.io/string-meta/
历史:
https://www.w3.org/standards/history/string-meta/
提交历史
编辑:
(W3C)
(受邀专家)
反馈:
GitHub w3c/string-meta (拉取请求, 新问题, 未解决问题)

摘要

本文档描述了识别 Web 上所用字符串的语言和方向的最佳实践。

本文档状态

本节描述了本文档在发布时的状态。当前 W3C 出版物列表以及本技术报告的最新修订版,可在 https://www.w3.org/TR/ 的 W3C 技术 报告索引中找到。

我们欢迎对本文档提出意见,但为了更易于跟踪,请为每条意见分别提出问题, 并使用 URL 指向你所评论的章节。

本文档由 国际化 工作组作为 组说明使用 说明轨道发布。

本组说明由 国际化工作组认可,但不被 W3C 本身或其 成员认可。

这是一个草案文档,可能随时由其他文档更新、取代或废弃。 不应将本文档作为进行中的工作以外的内容来引用。

W3C 专利 政策 不对本文档施加任何许可要求或承诺。

本文档受 2023年11月03日 W3C 流程文档约束。

1. 引言

本文档是国际化工作组在一系列规范审查中的观察结果,这些审查涉及基于 JSON、WebIDL 以及其他非标记数据语言的格式。与 XML 等标记格式不同,这些数据语言通常不提供可扩展 属性,并且在设计时未内建语言或方向元数据。

本文档中的概念适用于 Web 上使用字符串的任何时候,无论它们是形式化数据结构的一部分, 还是仅仅来源于 JavaScript 脚本或任何已存储的字符串列表。

Web 上的自然语言 信息依赖语言和方向元数据的存在,并从中受益。与对 Unicode 的支持一起,用于包含和指定文本片段的 块方向自然语言的机制, 是为 Web 开发新格式和技术时关键的国际化考量之一。

HTML 和 XML 等标记格式,以及 CSS 和 XSL 等相关样式语言,已经相当成熟,并通过 内建特性为世界各地语言的交换和呈现提供支持。字符串和基于字符串的数据格式需要类似的机制, 以确保对世界各地语言和文化提供完整且一致的支持。

1.1 文档约定

在本文档中,[RFC2119] 中的斜体大写关键词 具有其通常含义。我们还使用以下样式约定:

定义以不同的背景色和装饰显示,如此处所示。

最佳实践以不同的背景色和装饰显示,如此处所示。

1.2 术语

本节给出理解本文档内容所必需的关键术语的简短定义。这里出现的大多数术语都取自 [I18N-GLOSSARY]:为方便起见,这里再次列出。

如果你不熟悉双向文本或从右到左的文本,这里有一篇基础 介绍文章。它会让你基本了解 Unicode 双向 算法如何工作,以及它与块方向之间的相互作用, 这将有助于你阅读本文档。其他材料可见于国际化工作组的 面向规范 开发者的最佳实践

元数据关于数据的数据: 它是包含在数据结构中的信息,用于提供额外的上下文、含义或呈现。在本文档中,元数据的作用是表达 关于方向和语言的信息。[I18N-GLOSSARY]

生产者是创建自然 语言字符串数据,以供后续存储、处理或交换的任何过程。[I18N-GLOSSARY]

消费者是接收 自然语言字符串以进行显示或处理的任何过程。[I18N-GLOSSARY]

序列化约定是生产者与消费者之间关于 字符串元数据序列化的共同理解:它应如何被理解、序列化、读取、传输、移除等。 [I18N-GLOSSARY]

Unicode 双向算法 [UAX9],也称为 UBA,定义了段落方向的概念。这是 “段落”的初始基方向,并解析为从左到右从右到左。术语“段落”在 UBA 内部具有特定含义。在 本文档的语境中,该术语具有误导性,因为通常 Web 上的字符串和其他数据并不是某种文档格式中的 “文本段落”。在本文档中,我们通常使用以下两个更具体的术语:

块方向。文本块的初始基方向, 它解析为从左到右从右到左。块指作为整体的一段文本单位, 例如文档中的段落或数据文件中的字符串。选择“块”这个名称是为了与行内方向相对。 Unicode 将这个值称为段落方向。 [I18N-GLOSSARY]

字符串方向。某个 特定字符串的整体方向,它表示字符串内部方向性片段的呈现顺序。在各种数据结构中传输的字符串 经常被插入到一个块中(例如段落)。在这种情况下,字符串方向需要作为该字符串 双向文本隔离的一部分。

在本文档中,我们关注的是识别整个字符串的字符串方向, 以及在各种上下文中显示字符串时如何传输和应用字符串方向。我们不讨论如何确定字符串内部文本片段的 方向或显示方式。

双向文本 算法主要关注基于字符属性来排列相邻字符。 块方向决定:(a) 强类型 LTRRTL 字符片段的视觉顺序和显示方向,以及 (b) 当存在弱方向性字符或中性字符(如标点)时,这些项目相对于其他内容的位置。

1.3 字符串生命周期

不可能在真空中考虑处理字符串元数据的替代方案:我们需要建立一个用于讨论字符串处理和数据格式的框架。

1.3.1 生产者

字符串可以通过多种方式创建,包括内容作者在纯文本编辑器、短信或编辑工具中输入字符串; 或脚本从网页中抓取文本;或从其他应用程序或仓库获取现有的一组字符串。在本文档所考虑的 数据格式中,许多字符串来自后端数据仓库或各种数据库。字符串来源可能会提供接口、API 或元数据,其中包含关于数据的字符串方向和语言的信息。有些还会在方向或语言未提供或未指定时 提供合适的默认值。在本文档中,字符串的生产者是创建或提供字符串以供 存储或传输的来源,无论它是人还是机制。

创建字符串时,有必要 (a) 检测或捕获与该字符串关联的适当语言和字符串方向,以及 (b) 在需要时采取步骤,以某种方式设置该字符串,使其能够存储并传达 语言和字符串方向

例如,对于从 HTML 表单中提取的字符串,可以从表单字段的计算值中检测 字符串方向。 这样的值可能继承自较早的元素,例如 html 元素,也可能使用 input 元素自身上的标记或样式来设置。用户也可以通过 使用 键盘快捷键来改变表单字段中文本的方向。dirname 属性提供了一种在表单提交时自动传达该值的方式。

类似地,HTML 表单中的语言信息通常会继承自 html 标签上的 lang 属性,或树中具有 lang 属性的祖先元素。

如果字符串的生产者是从某个位置接收该字符串,而该位置中的字符串是由另一个 生产者存储的,并且其字符串方向和语言已经建立,那么该生产者需要理解 语言和字符串方向已经设置,并理解如何为其消费者转换或编码该信息。

1.3.2 消费者

消费者是接收字符串以进行处理的应用程序或过程,并且可能会将其放入 一个会向用户暴露的上下文中。出于显示目的,它必须确保字符串的 块方向和语言在该上下文中被正确地应用到字符串。 出于处理目的,它至少必须保持语言和方向,并且可能需要使用语言和方向数据来执行 特定于语言的操作。

正确显示字符串需要把字符串 方向和语言提供给渲染文档或过程,方法可以是应用附加标记、添加控制码或设置显示属性。 这会向渲染软件指明在此显示上下文中应应用到该字符串的字符串方向或语言,以使字符串正确显示。对于语言和方向, 它必须明确语言适用的文本范围边界。对于文本方向,它还必须将嵌入的字符串与周围文本隔离, 以避免双向文本算法的溢出效应 [UAX9]。

注意,一种文档格式的消费者可能是另一种文档 格式的生产者

1.3.3 序列化约定

在任何生产者消费者之间, 都需要有一个关于文档格式包含什么以及每个字段或属性中的数据表示什么的 约定。每当字符串的生产者采取特殊步骤来收集和传达 关于该字符串的字符串方向或语言的信息时, 它都必须预期该字符串的消费者会理解生产者如何编码了这些信息。

如果生产者没有采取任何行动,消费者仍然必须决定遵循哪些规则,以便确定适当的 字符串方向和语言, 即使只是为了提供某种形式的默认值。

在某些系统或文档格式中,字符串的生产者和消费者所需的行为已被完整指定。 在其他情况下,这样的约定并不存在;用户需要自行提供约定,说明如何编码、传输以及之后解码 必要的语言或方向信息。JSON 等低层规范默认不提供字符串元数据结构,因此任何基于这些规范的 文档格式都需要自行提供这种“约定”。

1.4 不是可本地化 文本的字符串

Web 使用字符串和字符序列来编码大多数数据。撇开不同的数据类型不谈 (例如数字、时间值,或诸如 base64 之类的二进制数据序列化),仍然有一些值 被定义为使用字符串数据类型,但并不打算用作自然 语言数据值。例如,由规范定义的语法内容,例如 CSS 中的保留关键字或 WebIDL 文档中各种定义的名称,并不是其各自文档格式或协议的可本地化文本的一部分。

许多规范还允许用户在给定命名空间或文档格式中提供用户提供的值。 例如,Wifi 网络上的 SSID 是用户定义的。CSS 样式表中的类名也是如此。大多数规范允许 (并鼓励允许)在这些名称中使用范围广泛的 Unicode 字符。大多数用户会选择可识别为某种 自然语言中词语的值,因为这样会使这些值更容易使用。然而,即使这些字符串由自然语言中的词语组成, 这类字符串也不被视为可本地化 文本,并且不需要附加与语言或字符串方向相关的额外元数据。通常它们只是标识符, 用于使计算机能够匹配这些值。

一个有时有用的测试是:如果把该标识符替换为任意字符串,例如 tK0001.37B,仍然是允许的、功能正常的且“正常”的,那么它就不是可本地化 文本

例如,在下面的基础示例中,JSON 文档中的所有键 (idtitleauthorslanguagepublisher 等)都是语法内容。ISBN、语言标签和出版日期等数据值 也是语法内容。只有实际的书名、作者姓名和出版商名称是自然语言数据值,因此才是 可本地化文本

2. 最佳实践、建议与缺口

本节包含国际化(I18N)工作组的一组最佳实践,用于在 Web 上的数据格式中识别语言和 字符串方向。在某些情况下, 现有标准中存在缺口,即 I18N 工作组的建议需要额外的标准化,或者可能存在完全采用的障碍。

主要问题是如何在数据值的生产者与消费者之间建立共同的序列化约定, 使各方都知道如何编码、查找和解释每个数据字段的语言和字符串方向。 使用元数据来提供自然语言字符串字段的语言和字符串方向, 可确保必要信息存在,能够以最少处理量提供和提取,并且不要求生产者或消费者扫描或修改数据。

国际化工作组在每个规范中寻找的最基本最佳实践是:

§

对于包含自然语言文本的任何字符串字段,MUST 能够确定该特定字符串的语言和字符串方向。 这种确定SHOULD使用字符串级或文档级元数据,并且SHOULD NOT 依赖启发式方法。

2.2 当语言和方向未知时

§

指定在没有其他信息的情况下,默认方向和默认语言均为未知。

如果显式元数据可用,它会胜过应用启发式方法的需要。这是合理的,因为启发式方法无法可靠地 自行推断必要的方向,而如果元数据已被显式提供,则表明它意图作为权威信息。

消费者必须知道语言和方向是未知量,这样他们才知道何时对数据应用回退策略 (这可能包括语言检测,或用于方向的首个强字符启发式方法)。尤其是,默认方向不应设置为 LTR, 因为那会覆盖对首个强字符检测的需要,而后者更适合以 RTL 文字书写的字符串。

§

对于字符串 方向未知的情况,指定消费者应使用首个强字符启发式方法来识别每个字符串的 字符串方向

如果 元数据不可用,字符串消费者应使用启发式方法来检测字符串的基方向, 最好是基于 Unicode 标准的首个强字符检测算法。

首个强字符算法会查找字符串中的第一个强方向性字符 (跳过某些前置子字符串),并假定它代表整个字符串的字符串方向。但是,第一个强方向性字符并不总是 与整个字符串的实际或期望字符串方向一致,因此在需要时应能够提供元数据来解决此问题。

§

如果依赖首个强字符启发式方法,则允许内容开发者在有必要强制特定基方向时 在字符串开头使用 RLM/LRM,但不要将这些字符之一预置到现有字符串中。

§

在大多数情况下,不要依赖 RLM/LRM 格式化字符的可用性。

如果字符串数据由用户或内容开发者在 Web 表单或其他简单环境中提供, 用户可能无法输入这些格式化字符。事实上,大多数用户可能并不知道此类字符存在,也不知道如何使用。 如果 Web 表单为输入设置块方向(它应该这样做),就可以使这些字符在即时检查时变得不必要。

§

规范SHOULD NOT允许从可用语言元数据推断字符串方向,除非方向元数据不可用且无法以其他方式提供。

并非所有资源都会使用可用的元数据机制。语言标签的文字子标签(或基于 [BCP47] 和 [LDML] 的“可能的”文字子标签) 有时可在其他数据不可用时用于推断块方向字符串方向。使用语言信息是“最后手段”,规范SHOULD NOT 将其作为指示块方向的主要方式:应努力提供元数据。

2.3 在规范中定义双向关键字

包含自然语言文本值的文档格式或协议规范,需要定义一个数据字段或属性, 用于存储每个自然语言内容值的块方向。 这些定义需要在整个 Web 上保持一致,以确保互操作性,因为一种文档格式的消费者需要将它们接收的值的 块方向映射到它们产生的字段, 或者在显示内容时需要控制每个字符串的字符串方向。 本节描述如何提供这样的定义以及要使用的具体内容。

定义内容方向有两个常见用例:(i) 定义一个方向元数据字段, 用于将字符串方向作为数据结构中的字段进行存储和传输;或 (ii) 定义一个方向属性,用于将块方向与给定自然语言内容片段关联起来。

方向元数据字段。方向元数据字段(或简称 方向字段)是数据结构中的字段,用于将字符串方向与给定自然语言字符串字段或数据值关联起来。

方向属性。方向属性是 一个字段或值,通常在标记语言中表示为属性,用于提供关联自然语言字符串内容的 字符串方向

§

在数据结构或协议中定义方向元数据字段时, 使用字段名 direction

对于数据值,首选名称 direction。名称 dir 是可接受的替代项。

§

定义方向属性时,使用字段名 dir

对于属性(例如标记语言中的属性),首选名称 dir。 不建议将 direction 用作属性, 因为它较长且在此用例中相对少见。请注意,[HTML] 和 [XML10] 都内建了 dir 属性。dir 属性应在文档内具有作用域,并应定义为提供双向文本隔离。

§

定义方向元数据字段方向属性的值时,应包括并限于 ltrrtlauto

ltr 表示从左到右的方向,其方式与 CSS 书写模式 [CSS-WRITING-MODES-4] 所指示的完全相同。

rtl 表示从右到左的方向,其方式与 CSS 书写模式 [CSS-WRITING-MODES-4] 所指示的完全相同。

auto 表示用户代理使用 [HTML] 定义的 auto算法来确定 块方向(“段落 方向”)。此启发式方法会查找第一个具有强方向性的字符,其方式类似于双向算法中的 段落级别确定 [UAX9]。

auto 应用于多个字段或整个文档时, 它意味着方向应针对每个字段单独推导(字符串特定元数据可为无法自动确定的情况提供覆盖)。 当一组混合方向字符串中大多数字符串的字符串方向 可以使用首个强字符启发式方法可靠确定时,对该组进行标记可能很有用。 只要可能,应存储或交换单个字符串的实际字符串方向ltrrtl), 而不是 auto。当值确实未知时, 省略方向字段更可取。

2.4 在规范中编写示例

文档格式或协议规范通常会包含示例。示例必然包含自然语言文本字段。

§

在规范中创建示例时,对于包含自然 语言文本的字段,始终使用本文档中的序列化和最佳实践。如果格式或协议支持 资源范围默认值,则在示例中展示如何设置该默认值。 如果格式或协议不支持文档级默认值,或展示该默认值不方便,则在示例中使用 单语言可本地化文本 字段语言映射

2.5 生产者的指导

内容生产者, 包括实现本文档所述各种语言和方向元数据机制的规范实现者, 对如何实现这里的最佳实践拥有一定裁量权。例如,如果一种文档格式同时提供资源范围默认值和 单语言可本地化文本字段,用户应该优先使用哪一个?

§

如果文档格式或协议提供了语言的资源范围默认值, 它SHOULD始终设置为最适合文档内容的语言。 这通常是生成用户的区域设置

§

如果文档格式或协议提供了方向的资源范围默认值, 它SHOULD始终设置为与文档内容最相关的方向。 通常,如果提供了文档级语言默认值,此方向会与其一致。

例如,如果文档的资源范围语言是 en-US (英语,美国),那么文档的资源范围方向很可能应为 LTR, 因为从左到右是与该语言关联的方向。

§

生产者SHOULD NOT在已提供资源范围默认值且字符串特定值与该默认值一致时, 包含字符串特定语言或方向元数据。

§

如果给定字符串的值比资源范围默认值更具体或完全不同, 生产者SHOULD包含字符串特定语言元数据。

例如,如果资源范围默认值fr(法语),而字符串关联的语言为 fr-FR(法语,法国),则生产者应生成带有更具体 fr-FR 标签的字符串特定元数据。 类似地,如果语言完全不同,例如 de(德语),生产者也应生成字符串特定元数据。

如果语言标签包含更多子标签, 则它更具体。

§

对于其字符串方向与所提供的资源范围默认值相反的任何内容, 生产者SHOULD包含字符串特定方向元数据,即使字符串本身是明确的。

许多字符串仅由与整体字符串方向一致的强方向性字符组成。 当此方向与资源范围默认值不一致(且存在默认值)时, 需要包含字符串方向,以便消费者不需要内省字符串来确定方向, 并且使过滤和选择等过程不会误判内容方向。

2.6 消费者的指导

收集、序列化和传输语言与字符串 方向元数据的目的,是让消费者能够使用它来正确显示和处理字符串数据。

§

消费者SHOULD在处理或显示关联字符串值时, 采用文档格式或协议提供的任何语言元数据。

§

消费者SHOULD在处理或显示关联字符串值时, 采用文档格式或协议提供的任何字符串方向元数据。

§

当字符串在文档中显示或插入到文档中时,消费者SHOULD将其与周围文本在方向上隔离。

§

消费者SHOULD在将字符串插入文档时应用方向元数据。 如果此字符串 方向由与字符串关联的元数据提供,消费者SHOULD使用该元数据。如果此类元数据不可用,则SHOULD 使用首个强字符启发式方法来分配方向。

用双向隔离包裹插入的字符串值绝不会造成问题,并且这样做会防止 溢出效应, 从而产生最佳结果。

§

消费者SHOULD在将字符串插入文档时应用语言元数据。 使用相关文档属性或 API 将任何可用的语言元数据应用到字符串。

为了在呈现(例如字体选择)或文本处理(例如断字)中获得最佳结果, 应在文档中或处理文本的 API 中设置插入文本的语言。在 [HTML] 中,这是通过设置 lang 属性完成的。 在 [XML] 中,这是通过设置 xml:lang 属性完成的。

§

消费者MAY规范化语言标签,以帮助确保互操作性。

例如,许多实现会使用 [CLDR] 中 语言标签 转换中的规范化。除其他事项外,此规范化会替换废弃子标签并按字母顺序排列变体。

§

同时也是生产者的消费者SHOULD注意将语言和方向元数据 传递给其下游消费者。


2.7 使用 JSON-LD

§

RECOMMENDED使用 [JSON-LD] @context 和 内建的 @language 属性作为文档级默认值。

对于使用它的文档格式,[JSON-LD] 包含一些数据结构, 有助于为字符串集合(包括整个资源)分配语言(但不是段落方向)元数据。 特别是,它以作用域受上下文限制的 @language 值形式 定义了它所谓的 “字符串国际化” ,该值可以与 JSON 块关联,也可以位于单个对象内部。 其中没有基方向的定义,因此 @context 机制 目前并未解决本文档提出的所有问题。

§

规范SHOULD使用 [JSON-LD] 1.1 中定义的用于 RDF 字面量的 i18n 命名空间特性。

§

i18n 命名空间不可用 或不适合使用时,规范SHOULD要求 [JSON-LD] 普通字符串字面量为自然语言值提供 字符串特定语言信息。

某些数据类型,例如 [RDF-PLAIN-LITERAL], 已经存在,并允许将语言元数据作为字符串值的一部分进行序列化。

2.8 属于旧式协议或格式一部分的字符串

§

对于因旧式格式原因而无法指定方向的字符串,规范SHOULD 指定每个字符串的字符串 方向依赖首个强字符启发式方法。

§

对于不是可本地化文本的字符串值和字符串字段, 规范SHOULD指定该字段在本质上是非语言的, 并建议将语言标签 zxx(“无语言内容”) 与每个字符串值关联起来。

§

对于已知包含可本地化文本、 但底层格式没有可能提供语言元数据的字符串值和字符串字段, 规范SHOULD指定内容语言未知,并建议将语言标签 und(“未确定”)与每个字符串关联起来。 在适当且作为最后手段的情况下,规范MAY允许使用启发式方法或从其他字段值推断语言。

许多协议或格式会使用意图让人能够理解的标记值, 但这些值并不意图作为自然语言文本。这使人们能够利用该值, 例如用于调试。这些值可能包括人们期望查看和交互的常见协议元素。

这些常见示例包括域名和电子邮件地址。随着这类值空间中 Unicode 可用性增强, 这些值在不同系统和环境中的显示可能会有所不同。例如,字体选择可能会因语言不同而变化, 在具有不同默认区域设置的系统上可能不同。

某些规范会与由现有协议或格式定义的字符串值交互。通常这些字符串没有关联语言或方向元数据, 或者不提供此类元数据。例如,许多 HTTP 标头定义其内容时,就好像其内容不是 可本地化文本, 即使这些内容预期是自然语言文本。作为这些字符串值的消费者生产者的规范, 无法发现语言或方向元数据是什么,也没有机制附加此类元数据。

2.9 其他最佳实践

§

规范SHOULD NOT使用 Unicode“语言标签” 字符(码点 U+E0000U+E007F)来进行语言标识。

[Unicode] 称,“……不强烈建议使用标签字符来 传达语言标签”,并且强烈不建议使用字符 U+E0001 LANGUAGE TAG

§

规范MUST NOT要求产生或使用 成对双向控制符

换句话说就是:不要要求实现修改从中经过的数据。 Unicode 双向控制字符可能出现在特定的字符串内容中,其中生产者或数据源使用它们来使文本正确显示。 也就是说,它们可能已经是数据的一部分。实现不应干扰它们发现的任何控制符——但也不应要求它们自行产生额外控制符。

§

Localizable 字符串可以为同一值提供多种语言时,规范SHOULD建议使用 语言索引

生产者有时需要 为同一内容项或数据记录提供多种语言值(见本地化 注意事项)。这种做法的一个用途是由消费者进行 语言协商

3. 需求和用例

:从这里开始

请阅读文章 Web 上双向文本 和语言元数据的用例,以了解详细用例,其中包括对溢出或基于区域设置的 渲染等问题的清晰说明。本节总结了该文档中与语言和方向元数据需求相关的一些要点。

3.1 为什么这很重要?

在处理和呈现可本地化文本时, 关于内容语言的信息很重要,原因多种多样。没有语言信息时,由此导致的外观或功能退化 可能会使用户感到沮丧,使内容无法理解,或禁用重要功能。受影响的一些过程包括:

类似地,方向元数据对于 Web 也很重要。当字符串包含以从右到左(RTL)方向运行的文字中的文本时, 必须能够在该字符串最终到达终端用户时正确显示它。为此,需要确定应将什么 字符串方向 应用于整个字符串。适当的字符串 方向并不总是能通过简单查看字符串来推断;即使可以推断,字符串的生产者和消费者 也需要使用相同的启发式方法来解释方向。

静态内容,例如 Web 页面的正文或电子书的内容,通常由文档格式 或作为内容元数据的一部分提供语言或方向信息。Web 上的数据格式 通常不提供此元数据。Microformats、WebIDL、JSON 等基础规范 往往将自然语言文本存储在字符串对象中,而没有额外元数据。

这给应用程序作者和数据格式设计者带来了负担,要求他们主动提供这些元数据。 当标准化格式没有处理由此产生的问题时,结果可能是,虽然数据完整到达, 但其处理或呈现无法完全恢复。

在分布式 Web 中,任何消费者也可以是某个其他 过程或系统的生产者。 因此,给定消费者可能需要将语言和方向元数据从一种文档格式(并使用一种 序列化约定)传递给使用不同 文档格式的另一个消费者。序列化约定中语言和方向元数据表示缺乏一致性, 会威胁互操作性,并成为一致实现的障碍。

3.2 一个示例

假设你正在构建一个 Web 页面,用于显示客户的电子书库。 这些电子书存在于一个数据目录中,并由常见的数据值组成。 单个条目的 JSON 文件可能类似于:

{
    "id": "978-111887164-5",
    "title": "HTML و CSS: تصميم و إنشاء مواقع الويب",
    "authors": [ "Jon Duckett" ],
    "language": "ar",
    "pubDate": "2008-01-01",
    "publisher": "مكتبة",
    "coverImage": "https://example.com/images/html_and_css_cover.jpg",
    // etc.
},

上述每一项都是某处数据库中的数据字段。甚至还有关于这本书所用语言的信息: ("language": "ar")。

一个经过良好国际化的目录会在上面所示内容之外包含额外元数据。也就是说, 对于包含可本地化文本的每个字段, 例如 titleauthors 字段,都应该有作为元数据存储的语言和 字符串方向信息。(也可能还有其他值, 例如用于对东亚语言信息排序的发音元数据。)这些元数据值由数据消费者使用, 以影响处理并以多种方式启用项目显示。由于 JSON 数据结构 没有存储或交换这些值的位置,因此构建国际化应用程序会更加困难。

一种变通方法可能是使用 HTML 和 Unicode 双向控制符的混合来编码这些值, 使数据值看起来像下面之一:

// following examples are NOT recommended
// contains HTML markup
"title": "<span lang='ar' dir='rtl'>HTML و CSS: تصميم و إنشاء مواقع الويب</span>",
// contains LRM as first character
"authors": [ "\u200eJon Duckett" ],

但是 JSON 是一种数据交换格式:内容最终不一定会在 HTML 上下文中显示 title 字段。 上面的 JSON 很可能会用于填充某个本地数据存储,例如,该存储使用原生控件显示标题, 而这些控件会将 HTML 视为字符串内容。数据的生产者和消费者可能并不期望内省数据, 以提供或移除额外数据,或将其暴露为元数据。大多数 JSON 库不了解它们正在序列化的内容结构。 生产者希望直接从本地数据存储(例如数据库)生成 JSON 文件。消费者希望存储或检索该值以供使用, 而无需额外考虑每个字符串的内容。此外,生产者或消费者也可能有其他考虑, 例如字段长度限制,而插入额外控制符或标记会影响这些限制。 这些考虑中的每一项都会给实现者带来特殊负担,迫使他们创建任意方式来序列化、反序列化、 管理和交换必要的元数据,而互操作性会在此过程中成为牺牲品。

(顺便说一句,请注意,上例中显示的标记实际上是为了让标题以及插入的标记 在浏览器中正确显示而需要的。)

3.3 Unicode 还不够吗?

[Unicode] 及其字符编码(例如 UTF-8)是 Web 及其格式的关键元素。它们提供了在整个 Internet 中一致地编码和交换任何 语言文本的能力。然而,Unicode 本身并不能保证自然语言文本的完美 呈现和处理,即使它确实保证了完美交换。

Unicode 的若干特性有时被建议作为提供语言和方向元数据的解决方案的一部分。 具体而言,有人建议使用 Unicode 双向控制符来处理方向元数据。 此外,Unicode 的 U+E0000 块中有“标签”字符, 最初意图用作语言标签(尽管这种用法现在已废弃)。

向交换格式中的数据添加字符不是一个好主意,原因有很多。这些包括:

最后这一点很重要,值得特别指出:文档格式通常使用多层代码来构建和序列化。 库(例如通用 JSON 库)被期望忠实地存储和检索传递给它们的数据。 更高层实现通常也关心对传递给它们的值进行忠实序列化和反序列化。 任何改变数据本身的过程都会引入不希望出现的可变性。例如,考虑应用程序的单元测试, 它检查从文档返回的字符串是否与用于生成该文档的数据目录中的字符串完全相同。 如果插入、移除或更改了双向控制符、HTML 标记或 Unicode 语言标签, 这些字符串可能比较为不相等,即使它们原本被期望是相同的。

3.4 消费者需要做什么来支持方向

鉴于双向文本的用例,很明显消费者不能只是简单地 将字符串插入目标位置,而不先进行一些额外工作或准备:首先要确定被插入字符串的适当 字符串方向, 其次要在该字符串周围应用双向文本隔离。

这要求字符串周围存在标记或 Unicode 格式化控制符。如果字符串的实际方向 与其要插入的内容方向相反,则标记或控制码需要紧密包裹该字符串。 相邻插入的字符串都需要分别包裹,以避免我们在上一节中看到的溢出问题。

[HTML] 在使用 dir 属性时,或使用 bdi 元素时,为任何行内元素提供基方向控制和隔离。将字符串插入纯文本环境时, 需要使用隔离 Unicode 格式化字符。(遗憾的是,对这些隔离字符的支持仍未普及, 尽管 Unicode 标准建议将其作为纯文本/非标记应用程序的默认做法。)

关键是确保标记或控制字符提供的方向信息反映该字符串的 字符串方向

4. 为识别字符串方向而考虑的方法

双向文本值的根本问题是,字符串的消费者在该字符串最终 显示给用户时,如何知道应为该字符串使用什么字符串方向。请注意,这些用于识别或估计方向的方法中, 有些在特定应用中有用,并且已在不同规范中使用,例如 [HTML]。这里的问题是, 哪些方法适合普遍采用,并指定为在文档格式中使用的最佳实践。

4.1 首个强字符属性 检测

此方法单独使用时不推荐,但建议作为与其他方法结合使用的回退方案。

4.1.1 它的工作方式

生产者不需要做任何事。

字符串按原样存储。

消费者必须查找字符串中第一个具有强 Unicode 方向属性的字符, 并将字符串方向设置为与其匹配。然后它们采取 适当行动,以确保字符串按需显示。这并不像看起来那么简单,原因如下:

  1. 字符串开头没有强方向的字符(例如标点、数字等) 以及字符串内部的隔离序列(即由 RLI/LRI/FSI...PDI 格式化 字符包围的字符序列)必须被跳过,以便找到第一个强字符。
  2. 检测算法需要能够处理字符串开头的标记。它需要能够判断该标记只是字符串文本, 还是需要在目标位置解析的标记——在后一种情况下,它必须理解该标记, 并理解该标记中携带的任何与方向相关的信息。

只有在所需字符串 方向尚未知晓时,才需要首个强字符检测。如果字符串的方向由元数据指示, 无论是字符串特定元数据还是通过资源范围声明指示,则不应调用首个强字符启发式方法。 例如,对于诸如 "HTML و CSS: تصميم و إنشاء مواقع الويب" 这样的字符串, 首个强字符启发式方法会产生错误结果。可以使用元数据来纠正这一点,使用元数据表示有意识的意图, 因此你不需要也不希望再应用会使结果变得不正确的启发式方法。

但是,如果没有应用元数据的机制,或者虽然存在这样的机制但内容开发者省略了使用, 则首个强字符启发式方法在很多情况下(但不是所有情况下)可以帮助建立基方向。 应用强方向性格式化字符可以帮助纯文本字符串(例如刚引用的示例)产生正确结果, 但并不总是能够应用这些字符(参见4.3 通过插入 RLM/LRM 标记增强 first-strong)。

4.1.2 优点

在可靠的情况下,可以在不更改字符串、也不需要支持带外元数据所需的约定和结构的情况下, 获得关于方向的信息。

4.1.3 问题

此方法的主要问题是,它会对以下情况产生错误结果:

  1. 以强字符开头,但该字符的方向性不同于整个字符串所需方向性的字符串 (例如以标签开头的阿拉伯语推文)
  2. 没有强方向性字符的字符串(例如电话号码),这些字符串在 RTL 上下文中 可能会显示不正确。
  3. 以标记开头的字符串,例如 span, 因为第一个强字符总会是 LTR。

如果整个字符串以 RLI/LRI/FSI...PDI 格式化字符开始和结束, 则无法按照 Unicode 双向算法检测第一个强字符。这是因为该算法要求从检测中排除 双向隔离文本。

如果在字符串中找不到强方向性字符,则方向可能应假定为 LTR, 并且消费者应以此为基础采取行动。不过,这一点尚未经过充分测试。

如果字符串包含将由消费者作为标记解析的标记,则还有其他问题。 搜索第一个强方向性字符时,还必须跳过字符串开头的任何此类标记。

如果字符串中的可解析标记包含关于字符串预期方向的信息 (例如 HTML 中值为 rtldir 属性), 则应使用该信息,而不是依赖首个强字符启发式方法。这在几个方面存在问题: (a) 它假定字符串的消费者理解标记语义,如果所有各方之间有约定只使用某种标记, 例如 HTML 标记,这或许可以接受;但在处理随机 XML 词汇表时就会有问题; (b) 消费者必须能够识别并处理只有字符串初始部分有标记的情况,也就是说, 该标记适用于一段行内文本,而不是整个字符串。

问题 1

不清楚下面段落中带有断开链接的示例在哪里,或以前在哪里。

但是,如果有意将尖括号内容作为标记的示例, 而不是实际标记,则不得跳过该标记——试图在 RTL 上下文中显示标记源代码会产生非常混乱的结果! 不过,字符串的消费者如何始终知道示例和可解析字符串之间的差异,并不清楚。

4.1.4 补充说明

虽然首个强字符检测在 Unicode 双向算法(UBA)[UAX9] 中有所概述, 但它并不是用于估计字符串方向的唯一可能高级协议。例如,X(以前称为 Twitter)和 Facebook 目前使用不同的默认启发式方法来猜测文本的基方向—— 两者都没有只使用简单的首个强字符检测,其中一个还使用了完全不同的方法。

4.2 元数据

推荐此方法。

所谓“元数据”,我们指的是数据格式中与特定字符串或一组字符串关联的基于字段的信息, 或内建于字符串数据类型中的信息(另见4.7 创建新的双向数据类型)。

一个示例如下:

{
    "title": "HTML و CSS: تصميم و إنشاء مواقع الويب",
    "direction": "rtl",
    "language": "ar",
},

也可以使用适当字段来设置表示资源中所有字符串默认方向的元数据。

4.2.1 它的工作方式

生产者确定字符串的字符串方向, 并将其添加到一个元数据字段中,该字段在字符串被存储或传输时随字符串一起提供。

使用元数据有几种方法:

  1. 为每个字符串标记字符串方向
  2. 块方向提供文档级默认值, 并且只为值不同的字符串包含元数据。当字符串方向未知时,使用值 auto
  3. 依赖消费者进行首个强字符检测, 并且只标记那些会产生错误结果的字符串(即以从左到右强字符开头的从右到左字符串)。

如果一次存储或传输一组字符串,那么有一个面向整个资源的字段会很有帮助, 它设置一个全局默认字符串方向, 该方向可由资源中的所有字符串继承。请注意,除了全局字段之外,在字符串的 字符串方向与默认值不同时, 仍然需要能够附加字符串特定元数据字段。设置在单个字符串上的 字符串方向必须始终覆盖默认值。

消费者需要理解如何读取随字符串发送的元数据,并且在没有元数据时需要应用首个强字符启发式方法。

对于基于 JSON 的文档格式中的单个值,RECOMMENDED使用 Localizable 字典结构, 因为它结合了语言和方向元数据,并且如果被一致采用,会使不同格式之间的交换更加容易。

这里所述,[JSON-LD] 包含一些有助于为字符串集合(包括整个资源)分配语言(但不是方向)元数据的数据结构。 对资源级或项目级预构建元数据支持方面的这些缺口,是开发本文档的关键原因之一。

4.2.2 优点

将元数据作为独立于字符串的数据值传递,提供了一种简单、有效且高效的方法, 用于传达预期的字符串 方向,而不影响字符串的实际内容。

如果每个字符串都标记了方向,或者所有字符串的方向都可以通过应用全局设置和任何字符串特定偏差来确定, 则可以避免检查每个单独字符串并运行启发式方法来确定其 字符串 方向

4.2.3 问题

带外信息需要与字符串关联并随字符串一起保留。对于某些不属于已定义框架的字符串数据集, 这可能会有问题。

特别是,JSON-LD 不允许像处理语言那样,将方向与单个字符串关联起来。

4.3 通过插入 RLM/LRM 标记增强 first-strong

此方法并不适用于所有情况。

4.3.1 它的工作方式

生产者确定字符串的字符串方向, 并在字符串开头添加一个标记字符(U+200F RIGHT-TO-LEFT MARK (RLM) 或 U+200E LEFT-TO-RIGHT MARK (LRM))。 该标记不是功能性的,也就是说,它不会自动为字符串应用可供消费者使用的基方向, 它只是一个标记。

有几种可能的方法:

  1. 向每个字符串添加标记(不推荐)。
  2. 依赖消费者进行首个强字符检测, 并只向那些会产生错误结果的字符串添加标记(例如以 LTR 强字符开头的 RTL 字符串)。
  3. 假定默认值为 LTR(无标记),并且只应用 RLM 标记。

消费者应用首个强字符启发式方法来检测字符串的 字符串 方向。RLM 和 LRM 字符在方向上是强类型字符,因此应会导致检测到适当的基方向。

4.1 首个强字符属性检测中所述, 如果方向信息通过元数据提供,则此方法不相关。

4.3.2 优点

只要生产者能够可靠地应用标记,它就提供了一种可靠指示基方向的方式。

理论上,只要在字符串前预置了正确的 RLM/LRM,就应该更容易发现以标记开头的字符串中的 首个强字符。

4.3.3 问题

如果生产者是人,理论上他们可以在创建字符串时应用这些字符之一,以表示方向性。

这种做法的一个重大问题,尤其是在移动设备上,是输入 RLM/LRM 字符的可用性或不便性。 移动设备的键盘通常不提供 RLM/LRM 字符的按键。也许更重要的是, 由于这些字符是不可见的,并且 Unicode 双向文本很复杂,用户可能很难知道如何有效使用该字符。 事实上,很大比例的用户实际上并不知道这些字符是什么,也不知道它们做什么。

此外,如果用户在 RTL 页面中的 HTML 表单中输入信息,或者使用快捷键设置表单字段的方向, 字符串看起来会是正确的,无需添加 RLM/LRM。但是,在该上下文之外使用时, 除非它与所需块 方向的信息关联,否则字符串看起来会不正确。类似地,从设置了 dir=rtlhtml 元素的网页中抓取的字符串,在 HTML 中通常不会也不需要在字符串开头有 RLM/LRM 字符。

生产者使用的步骤也许可以包括检查字符串原始上下文中的方向信息 (例如,通过测试 HTML 表单字段的计算方向),然后在必要时将 RLM/LRM 标记自动插入到字符串开头。 此方法的问题在于它会改变字符串值和身份。这也可能给处理字符串长度或指针位置带来问题, 尤其是在有些生产者添加标记而另一些没有添加标记时。

如果方向信息包含在将由消费者作为标记解析的标记中(例如 HTML 中的 dir=rtl),则字符串生产者需要理解该标记, 以便适当地设置或不设置 RLM/LRM 字符。如果生产者总是在此类字符串开头添加 RLM/LRM, 则消费者也应知道这一点。如果生产者转而依赖标记被理解, 则消费者也应理解该标记。

字符串的生产者不应自动在字符串开头应用 RLM 或 LRM, 而应测试是否需要它。例如,如果文本中已经有 RLM,则无需再添加一个。 如果上下文能够由首个强字符启发式方法正确传达,也无需添加额外字符。 但是请注意,只有在生产者能够访问并且知道自己能够访问字符串的原始上下文时, 才能测试是否需要这种补充方向信息。许多文档格式是由远离原始上下文存储的数据生成的。 例如,上面原始示例中的图书目录, 与输入双向文本的用户相脱离。

4.4 成对格式化字符

不推荐此方法。

4.4.1 它的工作方式

生产者确定字符串的字符串方向, 并在字符串开头添加一个方向性格式化字符(U+2066 LEFT-TO-RIGHT ISOLATE (LRI)、U+2067 RIGHT-TO-LEFT ISOLATE (RLI)、 U+2068 FIRST STRONG ISOLATE (FSI)、 U+202A LEFT-TO-RIGHT EMBEDDING (LRE) 或 U+202B RIGHT-TO-LEFT EMBEDDING (RLE) 之一),并在结尾添加 U+2069 POP DIRECTIONAL ISOLATE (PDI) 或 U+202C POP DIRECTIONAL FORMATTING (PDF)。

有几种可能的方法:

  1. 向每个字符串添加格式化代码。
  2. 依赖消费者进行首个强字符检测, 并只向那些会产生错误结果的字符串添加标记(例如以 LTR 强字符开头的 RTL 字符串)。

理论上,消费者只需将字符串插入它将显示的位置,并依赖格式化代码来管理方向性。 但是,事情并不那么简单(见下文)。

成对格式化字符有两种类型。原始的一组控制符提供了向 Unicode 双向算法添加额外一层 双向“嵌入”的能力。后来,Unicode 添加了一组互补的“隔离”控制符。 隔离控制符用于包围字符串。字符串内部被视为其自身的双向序列,并且该字符串会受到保护, 以避免与任何周围文本相关的溢出效应。外层字符串会将整个被包围字符串作为一个单元处理, 并在双向重排时忽略它。此问题在这里描述。

码点 缩写 描述 码点 缩写 描述
U+200A LRE 从左到右嵌入 U+2066 LRI 从左到右隔离
U+200B RLE 从右到左嵌入 U+2067 RLI 从右到左隔离
U+2068 FSI 首个强字符隔离
U+200C PDF 弹出方向性格式化(结束嵌入) U+2069 PDI 弹出方向性隔离(结束隔离)

如果使用成对格式化字符,它们应该是隔离性的,也就是说,以 RLI、LRI、FSI 开始, 而不是以 RLE 或 LRE 开始。

4.4.2 优点

使用此方法没有真正的优点。

4.4.3 问题

只有在可以接受更改字符串值时,此方法才适用。除了可能出现字符串长度或指针位置改变等问题外, 此方法还存在真实且严重的风险:成对字符之一可能会因处理错误、文本截断等原因丢失。

字符串的生产者和消费者需要识别并处理这样一种情况:字符串以成对格式化字符开头, 但并不以它结束,因为格式化字符只描述字符串的一部分。

Unicode 指定了有效嵌入数量的限制,并且嵌入可能会随着时间累积而超过该限制。

消费应用程序需要识别并适当地处理隔离格式化字符。目前对 RLI/LRI/FSI 的此类支持 还远未普及。

如果由不了解此方法的消费者使用, 此方法会使字符串不适合 UBA 首个强字符启发式方法,因为 Unicode 双向算法无法确定 以 RLI/LRI/FSI 开头并以 PDI 结尾的字符串的基方向。这是因为该算法会跳过隔离序列, 并将它们视为中性字符。字符串的消费者在这种情况下 必须采取特殊步骤来定位第一个强字符。

4.5 文字子标签

仅建议在阻止使用元数据的情况下,将此方法作为变通方案。

4.5.1 它的工作方式

生产者 为字符串提供语言元数据,并在必要时指定所使用的文字。

有几种可能的方法:

  1. 为每个字符串标记语言,并根据需要包含文字子标签。当生产者未提供文字子标签时, 消费者可能需要计算该子标签。
  2. 可以合理地假定所有字符串默认都是 LTR,除非标有文字子标签(无论是存在还是隐含) 表示 RTL 的语言标签。
  3. 或者,将文字子标签元数据的使用限制在预期首个强字符启发式方法会失败的情况——前提是能够识别此类情况, 并且生产者采取适当行动(并不总是可靠)。然后,在没有文字子标签时, 消费者需要使用 首个强字符启发式方法来识别适当的字符串方向。 但是,文字子标签的使用不应限制于需要指示方向的字符串;将文字子标签与任何字符串关联 都是完全有效的。
  4. 在较高层级为一组字符串设置默认语言,但提供一种机制,在需要时为给定字符串覆盖该默认值。

消费者从与每个字符串 关联的语言标签中提取文字子标签,并在必要时计算字符串的 字符串方向。与 RTL 文字关联的文字子标签用于为其关联字符串 分配 RTL 方向。

语言信息MUST使用 [BCP47] 语言标签。携带该信息的语言标签部分 是文字子标签,而不是主语言子标签。例如,阿塞拜疆语可以用 LTR(拉丁或西里尔文字) 或 RTL(阿拉伯文字)书写。因此,子标签 az 不足以阐明预期的块方向。而像 az-Arab(用阿拉伯文字书写的阿塞拜疆语)这样的语言标签, 通常可以依赖它来表明块方向应为 RTL。

4.5.2 优点

无需检查或更改字符串本身。

当首个强字符不能指示字符串所需字符串 方向时,此方法避免了与首个强字符检测相关的问题,也避免了与解释标记相关的问题。

请注意,以设置字符串文本内容语言的标记开头的字符串(例如 <cite lang="zh-Hans">)在这里不是问题, 因为不期望该语言声明参与字符串方向的设置。

4.5.3 问题

如果可用,上面概述的使用元数据的方法要好得多。这种与文字相关的方法仅用于 因旧式原因而无法使用该方法的情况。

有许多字符串并非特定于语言,但为了正确消费,绝对需要与特定 块方向关联。 例如,插入 RTL 上下文中的 MAC 地址需要以 LTR 整体基方向显示,并且也需要与周围文本隔离。 不清楚如何将这些情况与其他情况区分开来(以使用方向元数据时可行的方式)。 特殊语言标签,例如 zxx(非语言),可用于识别此类内容, 但通常这类数据字段会完全省略语言信息,因为它并不适用。

文字子标签列表将来可能会增加。在这种情况下,任何表示默认 RTL 方向的子标签 都需要添加到字符串消费者所使用的列表中。

存在一些罕见情况,无法从文字子标签识别适当的段落 方向,但这些情况实际上仅限于古旧文本用法。例如,二战以前的日文和中文文本 经常写作 RTL,而不是 LTR。使用埃及象形文字或提非纳格柏柏尔文字书写的语言, 过去可以写作 LTR 或 RTL,不过学术研究中的默认方向倾向于 LTR。

4.5.4 其他评论

这里概述的方法只适用于声明与字符串关联的整体 字符串方向的信息。我们建议 使用语言数据来指示字符串内部的文本方向,因为这些使用模式不可互换。

4.6 要求为内容提供双向文本标记

不推荐此方法,除非是在预期专门交换 HTML 或 XML 标记数据的 序列化约定下。

4.6.1 它的工作方式

生产者确保所有字符串都以指示该字符串适当基方向的标记开始和结束。 这要求生产者检查字符串。如果字符串没有由带有方向信息的标记界定, 生产者必须添加带有 dirits:direction [ITS20] 属性的元素来包裹字符串,或添加适合给定 XML 应用的其他标记。如果字符串已经 由标记界定,但该标记是诸如 HTML h1 元素之类的内容,则生产者需要将方向信息引入现有标记中,而不是简单地用 span 包围该字符串。

此示例使用 HTML 标记。(只是为了使示例更易读,它显示的是字符串文本内容应显示的样子, 而不是字符存储的顺序。)

然后消费者在显示字符串的文本内容时,依赖该标记来设置其周围的基方向。 (请注意,除非提供额外元数据,否则消费者无法在将字符串集成到目标位置之前移除标记, 因为它无法判断哪些标记是生产者添加的,哪些标记原本就存在。一般来说, 此类添加的标记是无害的。)

4.6.2 优点

对于已经使用标记的内容,其好处很明显。内容已经提供了显示和处理文本所需的完整标记, 或者可以从源页面上下文中提取。HTML 和 XML 处理器已经知道如何处理这些标记, 并提供现成的验证。

对于 HTML,dir 属性会将内容与周围文本进行双向隔离, 从而消除溢出冲突。这减少了消费者的工作。

标记还可用于字符串内部的方向信息,这是单靠字符串方向无法解决的。

4.6.3 问题

实际上,所有实现栈层级都必须参与理解标记(或确保它们不会造成损害)。

如果系统端到端使用 HTML,则适当的标记可用且其语义可被理解 (即 dir 属性,以及 bdibdo 元素)。 但是,对于 XML 应用,没有用于双向文本支持的标准标记。此类标记需要先被定义, 然后由生产者和消费者共同理解。

此方法的一个主要缺点是,许多数据值只是字符串。与添加 Unicode 标签或 Unicode 双向控制符一样, 向字符串添加标记会改变原始字符串内容。更改内容长度可能会给执行任意限制的过程带来问题, 也可能给通过转义尖括号等 HTML/XML 不安全字符来“净化”内容的过程带来问题。

另一个问题是生产者需要检查字符串并按需添加标记,这需要工作量和复杂性。

Unicode 双向算法允许的嵌入数量有限。消费者需要确保在将字符串嵌入更广泛上下文时 不会超过此限制。

添加标记还要求消费者防范与标记插入相关的常见问题,例如 XSS 攻击。

4.7 创建新的双向数据类型

此方法已添加到 [JSON-LD] 1.1。

4.7.1 它的工作方式

这类似于前面讨论的随字符串发送元数据的想法,但元数据不是存储在完全独立的字段中 (如4.2 元数据),也不是插入字符串本身 (如4.3 通过插入 RLM/LRM 标记增强 first-strong),而是作为字符串序列化格式的一部分与字符串关联。

某些数据类型,例如 [RDF-PLAIN-LITERAL], 已经存在,并允许将语言元数据作为字符串值的一部分进行序列化。 但是,这些数据类型没有考虑方向。可以通过定义一种新的数据类型(或扩展现有数据类型) 来解决此问题,文档格式随后可以使用它来序列化同时包含语言和方向元数据的自然语言字符串。

[JSON-LD] 1.1 添加了 i18n 命名空间,以允许 JSON 文档直接随字符串值序列化语言和方向元数据。 它为需要 RDF 的规范提供了到 RDF 的反序列化。

请注意,最后一个字符串不包含语言信息,因为它是内部数据值, 但确实包含方向信息,因为这类字符串必须以 LTR 顺序呈现。

生产者需要根据需要 将字符串方向附加到每个字符串。

每个消费者 都应对不使用此方法或不包含字符串方向的字符串使用 首个强字符启发式方法。然后,只有在首个强字符方法否则会产生错误结果时, 生产者才会添加 字符串方向信息。这可能会简化字符串管理和要传输的数据量, 因为需要元数据的字符串数量相对较少。

消费者 会查看字符串是否有关联的元数据;如果有,则设置所指示的 字符串方向。否则,它会使用首个强字符启发式方法 来确定该字符串的字符串方向。

4.7.2 优点

如果向 JSON 添加一种新数据类型以支持自然语言字符串,那么规范就可以轻松指定在文档格式中使用该类型。 由于格式是标准化的,当方向或语言信息被编码时, 生产者消费者 不需要猜测这些信息。

4.7.3 问题

除了目前这实际上不可行之外,添加数据类型的缺点在于,JSON 是一种被广泛实现的格式, 包括许多临时实现。任何新的序列化形式都可能破坏这些现有实现,或导致互操作性问题。 JSON 并不是设计为“带版本”的格式。使用的任何序列化形式都需要对现有 JSON 处理器透明, 因此可能会向现有字符串和格式引入不需要的数据或数据损坏。

5. 为识别内容语言 而考虑的方法

本节处理确定或传达字符串值语言的不同方式。

5.1 元数据

推荐此方法。

5.1.1 它的工作方式

生产者确定 字符串的语言(通常来自上游提供的元数据),并将该信息包含在一个元数据字段中, 该字段在字符串被存储或传输时随字符串一起提供。

一次存储或传输一组字符串时,有一个面向整个资源的字段会很有帮助, 它设置一种可由资源中所有字符串继承的语言。请注意,除了全局字段之外, 在字符串的语言不是默认语言的情况下,仍然需要能够附加字符串特定元数据字段。 设置在单个字符串上的语言必须覆盖任何资源级值。

消费者需要 理解如何读取与字符串关联的元数据,并将其应用到它生成的显示、处理或数据结构中。 请注意,这可能包括在序列化或交换单个值时应用资源级默认语言的需要。

5.1.2 优点

使用一致且定义良好的数据结构,更有可能使不同标准可组合,并无缝协同工作。

可以在不影响内容本身的情况下提供元数据。

当元数据不可用时,可以省略。

消费者和生产者无需在正常处理之外内省数据。

5.1.3 问题

使用该字典及其数据值的序列化文件将包含额外字段,因此可能更难阅读。

对于现有文档格式,这表示对正在交换的值进行更改。

5.2 要求为内容提供标记

不推荐此方法,除非在特殊情况下,所交换的内容预期由给定标记语言中的 字面量值组成并且被限制为此类值。

5.2.1 它的工作方式

当文档预期由 HTML 或 XML 片段组成,并且会严格在标记上下文中处理和显示时, 生产者可以使用标记来传达 内容的语言,方法是用带有 langxml:lang 属性的元素 包裹字符串。

5.2.2 优点

此方法以及其优点,实际上与本节中的内容相同。

5.2.3 问题

上文

5.3 使用 Unicode 语言标签 字符

不推荐此方法。

警告

5.3.1 它的工作方式

生产者将 Unicode 标签字符插入数据中,以为字符串标记语言。

消费者处理 Unicode 标签字符,并使用它们来分配语言。

Unicode 定义了可用作语言标签的特殊字符。这些字符是“默认可忽略的”,并且不应有任何视觉外观。 Unicode 标签应按如下方式工作:

每个标签都是一个字符序列。该序列以标签标识字符开头。目前唯一已定义的是 U+E0001,它标识 [BCP47] 语言标签。通过私有约定,也可以使用其他类型的标签。 该 Unicode 标签块中用于形成标签的其余字符会映射可打印 ASCII 字符。 也就是说,U+E0020 是空格(映射 U+0020), U+E0041 是大写 A(映射 U+0041),依此类推。 在标签标识字符之后,生产者使用每个标签字符,通过大小写字母、数字和连字符拼出一个 [BCP47] 语言标签。给定的源语言标签由 ASCII 字母、 数字和连字符组成,可通过向每个字符的码点添加 0xE0000 转换为标签。 其他结构,例如语言优先级列表(见 [RFC4647]),可能会使用其他字符(例如逗号或分号)构造, 尽管 Unicode 没有定义甚至不一定允许这样做。

标签作用域的结束由字符串结尾表示,或者可以使用取消标签字符 U+E007F 显式表示, 该字符可以单独使用(取消所有标签),也可以前置语言标签标识字符 U+E0001(即序列 <U+E0001,U+E007F>,仅结束语言标签)。

因此,标签最少包含三个字符,并且很容易达到 12 个或更多字符。此外,这些字符是补充字符。 也就是说,它们在 UTF-8 中每个字符使用 4 字节编码,在 UTF-16 中编码为代理对 (两个 16 位码元)。在 Java 和 JavaScript 等内部使用 UTF-16 的语言中, 需要使用代理项在字符串类型中编码这些字符。代理项的使用会使字符串有些不透明。 例如,U+E0020 在 UTF-16 中编码为 0xDB40.DC20, 在 UTF-8 中编码为字节序列 0xF3.A0.80.A0

5.3.2 优点

这些语言标签字符可以作为普通 Unicode 文本的一部分使用,而无需修改文档格式的结构。

5.3.3 问题

Unicode 联盟强烈不建议使用 Unicode 标签字符进行语言标识(因此已废弃)。 这些标签字符原本用于纯文本上下文中的语言标记,并且经常被建议作为提供带内非标记语言标记的替代方式。 我们不知道有任何实现将它们用作语言标签。

将这些字符视为未知 Unicode 字符的应用程序会把它们显示为豆腐块 (空心方框替换字符),并且可能将它们计入长度限制等。因此,只有当应用程序或交换机制 完全了解它们,并能够适当地移除或忽略它们时,它们才有用。尽管这些字符本不应显示或 对文本处理产生任何影响,但在实践中它们可能会干扰正常文本处理,例如截断、换行、断字、 拼写检查等等。

按设计,[BCP47] 语言标签意图以 ASCII 大小写不敏感方式处理。 处理 Unicode 标签字符的应用程序必须应用类似的大小写不敏感性,以确保正确识别语言。 (Unicode 数据没有为这些字符指定大小写转换配对;这会使使用标签字符编码的语言标签值的 处理和匹配变得复杂。)

此外,语言标签需要由有效子标签组成,以符合 [BCP47]。有效子标签保存在 IANA 注册表中, 并且会定期添加新的子标签,因此处理这种标记的应用程序需要始终根据注册表的最新版本检查每个子标签。

语言标签字符不允许语言标签嵌套。例如,如果一个字符串包含两种语言, 例如英文句子中的法语引文,Unicode 标签字符只能指示一种语言从哪里开始。 要指示嵌套语言,需要将标签嵌入文本中,而不只是前缀到开头。

虽然从未实现,但其他类型的标签也可以使用 Unicode 标签字符嵌入到字符串或文档中。 这些标签可能与标有语言标签的文本区段重叠。

最后,Unicode 最近将这些字符“再利用”于组成次区域旗帜, 例如苏格兰旗(🏴),它由以下序列组成:

  • 🏴 [U+1F3F4 WAVING BLACK FLAG]
  • [U+E0067 TAG LATIN SMALL LETTER G]
  • [U+E0062 TAG LATIN SMALL LETTER B]
  • [U+E0073 TAG LATIN SMALL LETTER S]
  • [U+E0063 TAG LATIN SMALL LETTER C]
  • [U+E0074 TAG LATIN SMALL LETTER T]
  • [U+E007F CANCEL TAG]
编辑者 注

上述内容是 Unicode 10.0(UTR#51 版本 5.0)于 2017 年 6 月添加的 emoji 新特性。 正确显示取决于你的系统是否采用了此版本。

5.4 使用语言检测启发式方法

不推荐此方法。

5.4.1 它的工作方式

生产者什么也不做。

消费者运行 语言检测算法来确定文本语言。这些通常是基于统计的启发式方法,例如使用某种语言中的 n-gram 频率,并可能结合其他数据。

5.4.2 优点

此方法没有根本性优点。

5.4.3 问题

被扫描的文本越长、越具代表性,启发式方法就越准确。短字符串可能无法很好地检测。

语言检测受限于拥有检测器的语言。

包含项,例如另一种语言或文字中的人名或品牌名,可能会干扰检测。

语言检测往往较慢,并且可能占用大量内存。简单消费者可能负担不起确定语言所需的复杂性。

6. 本地化注意事项

有时,生产者可以 通过在生产者消费者之间执行某种 语言 协商,为给定内容项或数据记录提供本地化值。然后在 生产者中使用协商出的 语言来选择返回内容,从而完成本地化。此方法可以节省文件大小(这会影响延迟)和复杂性, 因为只需返回消费者需要的语言。

但是,由于这并不总是可能,规范有时允许为给定字段返回多个不同语言值。 这可能是为了支持运行时本地化,或者因为生产者有多个 不同语言值,且无法适当地预先选择它们。

在这些情况下,内容项的本地化是通过让生产者为该项目返回多个语言表示, 并让消费者选择要显示的值来完成的。 当生产者无法协商语言 (例如生成的文件被缓存给多个用户使用)且语言数量相对较少时,此方法很有帮助。 大量语言集合可能会导致文档过大且难以处理。

语言 索引是一种使用语言标签来组织给定字段不同 语言版本的策略,使消费者能够选择最合适的值。 规范可以使用数据结构,例如LanguageMap,为给定字段提供多个语言版本。 给定字段的值定义为映射。映射中的键是语言标签。与每个语言标签关联的值 是字符串,理想情况下是LanguageEntry对象。

语言标签用作映射中值的键, 可以快速选择给定请求的正确值。请注意,当与语言标签关联的值是 LanguageEntry时,语言可能会在值中重复 (或被覆盖)。这不是必需的,因为值中的LanguageTag是可选的。 (除非它能增加价值,否则不要包含它。)

例如,如果请求的语言是美国英语(en-US), 此格式使匹配并提取最合适的 title 对象 {"value": "Learning Web Design"} 更容易。 一个额外的潜在优点是,被索引的语言标签可以单独指示该值的目标受众, 与实际数据值的语言标签分开。一个例子可能是使用语言范围 [RFC4647],如下例所示,其中更具体的语言值可能被 较不具体的语言标签包裹。在此示例中,内容已用特定语言标签(de-DE) 标记,但它也可用于并适用于说其他德语变体的用户,例如 de-CHde-AT

较不常见的示例是,系统提供与索引语言标签不同(“错误”)语言的特定值, 也许是因为实际翻译值缺失:

此方法的主要问题是,需要从内容中提取索引语言标签以生成索引。 生产者也可能需要与 消费者就索引语言标签是否会以任何方式规范化达成 序列化约定。例如,语言标签 cel-gaulish 是 [BCP47] 中祖父化语言标签之一。 某些实现,例如遵循 [CLDR] 中规则的实现, 会出于语言协商目的,倾向于将该标签替换为现代等价形式 (在此情况下为 xtg-x-cel-gaulish)。

[JSON-LD] 定义了语言索引的具体实现, 它依赖于使用 @context 结构。此结构不支持使用 LanguageEntry 值 (仅支持字符串或字符串数组),因此需要进行更改,才能在 [JSON-LD] 文档中允许上述某些能力。

A. 数据结构的 WebIDL 定义

本节包含上文主文档中描述的各种结构的 WebIDL 定义。

为了有效,规范作者应一致使用相同的格式和数据结构,以便大多数数据格式能够互操作 (换句话说,使数据能够在许多格式之间复制,而无需应用额外处理)。我们建议对 单语言可本地化文本字段采用 Localizable, 并对语言映射采用 LanguageMap

通过以 WebIDL 字典形式定义语言和方向,规范可以简洁地为给定 String 值合入语言和方向元数据。 实现可以直接复用该字典实现。

A.1 LanguageTag typedef

WebIDLtypedef DOMString LanguageTag;
LanguageTag typedef
一个 DOMString,包含一个 有效的 [BCP47] 语言标签

A.2 Localizable 字典

WebIDLdictionary Localizable {
    DOMString value;
    LanguageTag lang;
    TextDirection dir = "auto";
};
value 成员
包含此字段数据值的字符串。
lang 成员
一个 [BCP47] 语言标签, 指定继承字典中人类可读成员值的主要语言。
dir 成员
指定继承字典中人类可读成员的字符串方向

A.3 LanguageMap typedef

WebIDLtypedef record<DOMString,LanguageEntry> LanguageMap;
LanguageMap record
一个映射,其键为LanguageTag,其值为 LanguageEntry,包含与键关联的本地化字符串值, 以及任何覆盖元数据。

A.4 LanguageEntry 字典

WebIDLdictionary LanguageEntry {
    DOMString value;
    LanguageTag? lang;   // Optional property for language tag
    TextDirection? dir;  // Optional property for text direction
};
value 成员
包含此字段数据值(本地化文本)的字符串。
lang 成员
(可选)一个LanguageTag,用于覆盖 或修正 LanguageMapLanguageEntrylang 成员。此字段很少使用。
dir 成员
(可选)该值的TextDirection

A.5 TextDirection enum

WebIDLenum TextDirection {    
    "auto",
    "ltr",    
    "rtl"
};

文本方向值如下,这意味着人类可读成员的值默认为:

auto
方向性由 Unicode 双向算法 [UAX9] 算法确定。
ltr
从左到右文本。
rtl
从右到左文本。

B. 致谢

国际化(I18N)工作组感谢 以下对本文档作出贡献的人: Mati Allouche, David Baron, Ivan Herman, Tobie Langel, Emil Lundberg, Sangwhan Moon, Felix Sasaki, Najib Tounsi, 以及许多其他人。

以下页面构成了本文档的初始基础:

C. 参考文献

C.1 资料性参考文献

[BCP47]
用于识别语言的标签. A. Phillips, Ed.; M. Davis, Ed.. IETF. 2009 年 9 月。当前最佳实践。URL:https://www.rfc-editor.org/rfc/rfc5646
[CLDR]
Unicode 公共区域设置数据仓库. Unicode Consortium. URL:https://cldr.unicode.org/
[CSS-WRITING-MODES-4]
CSS 书写模式 Level 4. Elika Etemad; Koji Ishii. W3C. 2019 年 7 月 30 日。W3C 候选推荐。URL:https://www.w3.org/TR/css-writing-modes-4/
[HTML]
HTML 标准. Anne van Kesteren; Domenic Denicola; Dominic Farolino; Ian Hickson; Philip Jägenstedt; Simon Pieters. WHATWG. 现行标准。 URL:https://html.spec.whatwg.org/multipage/
[I18N-GLOSSARY]
国际化术语表. Richard Ishida; Addison Phillips. W3C. 2024 年 4 月 22 日。W3C 工作组说明。URL:https://www.w3.org/TR/i18n-glossary/
[INTERNATIONAL-SPECS]
面向规范开发者的国际化最佳实践. Richard Ishida; Addison Phillips. W3C. 2024 年 3 月 21 日。W3C 工作组说明。URL:https://www.w3.org/TR/international-specs/
[ITS20]
国际化标签集(ITS)版本 2.0. David Filip; Shaun McCance; David Lewis; Christian Lieske; Arle Lommel; Jirka Kosek; Felix Sasaki; Yves Savourel. W3C. 2013 年 10 月 29 日。W3C 推荐。URL:https://www.w3.org/TR/its20/
[JSON-LD]
JSON-LD 1.0. Manu Sporny; Gregg Kellogg; Markus Lanthaler. W3C. 2020 年 11 月 3 日。W3C 推荐。URL:https://www.w3.org/TR/json-ld/
[LDML]
Unicode 技术标准 #35:Unicode 区域设置 数据标记语言(LDML). Mark Davis; CLDR Contributors. URL:https://unicode.org/reports/tr35/
[LOCALIZABLE-MANIFESTS]
开发可本地化 清单. Addison Phillips. W3C. 2023 年 12 月 6 日。W3C 工作组说明。URL: https://www.w3.org/TR/localizable-manifests/
[RDF-PLAIN-LITERAL]
rdf:PlainLiteral:RDF 普通 字面量的数据类型(第二版). Jie Bao; Sandro Hawke; Boris Motik; Peter Patel-Schneider; Axel Polleres. W3C. 2012 年 12 月 11 日。W3C 推荐。URL:https://www.w3.org/TR/rdf-plain-literal/
[RFC2119]
用于 RFC 中表示 要求级别的关键词. S. Bradner. IETF. 1997 年 3 月。当前最佳实践。URL:https://www.rfc-editor.org/rfc/rfc2119
[RFC4647]
语言标签匹配. A. Phillips, Ed.; M. Davis, Ed.. IETF. 2006 年 9 月。当前最佳实践。URL:https://www.rfc-editor.org/rfc/rfc4647
[RFC9000]
QUIC:基于 UDP 的多路复用与安全 传输. J. Iyengar, Ed.; M. Thomson, Ed.. IETF. 2021 年 5 月。拟议标准。 URL:https://www.rfc-editor.org/rfc/rfc9000
[UAX9]
Unicode 双向 算法. Manish Goregaokar मनीष गोरेगांवकर; Robin Leroy. Unicode Consortium. 2024 年 9 月 2 日。 Unicode 标准附录 #9。URL:https://www.unicode.org/reports/tr9/tr9-50.html
[Unicode]
Unicode 标准. Unicode Consortium. URL:https://www.unicode.org/versions/latest/
[WebIDL]
Web IDL 标准. Edgar Chen; Timothy Gu. WHATWG. 现行标准。URL:https://webidl.spec.whatwg.org/
[Webtransport]
WebTransport. Bernard Aboba; Nidhi Jaju; Victor Vasiliev. W3C. 2024 年 5 月 31 日。W3C 工作草案。URL:https://www.w3.org/TR/webtransport/
[XML10]
可扩展标记语言(XML)1.0(第五 版). Tim Bray; Jean Paoli; Michael Sperberg-McQueen; Eve Maler; François Yergeau et al. W3C. 2008 年 11 月 26 日。W3C 推荐。URL:https://www.w3.org/TR/xml/