我遇到过一些人,他们认为 CSS 与国际化根本没有任何关系,但如果你仔细想想,国际化不仅仅是将你网站上的内容翻译成多种语言,然后一次性完成并为所有人。 此内容的呈现方式存在各种细微差别,会影响母语人士使用您网站的体验。
国际化没有单一的规范定义,但 W3C 提供了以下指导:
“国际化是指产品、应用程序或文档的设计和开发,可以轻松地针对不同文化、地区或语言的目标受众进行本地化。”
从 Unicode 和字符编码的使用,到提供翻译内容的技术实现,以及所述内容的呈现,这是一个需要涵盖的领域。 今天我只讨论CSS相关的多语言支持方面。
CSS 通过告诉浏览器如何设置页面上的元素的样式和布局来描述网页的显示。 在使用CSS的多语言页面上,我们可以通过多种方式将不同的样式应用于不同的语言。
此外,CSS属性还为脚本和书写系统提供布局和排版功能,而不仅仅是现在主要出现在WEB上的基于拉丁文的自上而下的水平排版功能。
所以,请做好准备,因为这将是一篇相当长的文章。 _(ツ)_/
与语言相关的样式
您是否想知道 Chrome 如何询问您是否要翻译网页内容? 呃……好吧,也许只有我一个人关心这种问题? 这是因为 HTML 元素上的 lang 属性。
lang 属性是一个非常重要的属性,因为它标识了 Web 上文本内容的语言,并且该信息在很多地方都使用。 前面提到的 Chrome 外部翻译器、特定语言内容的搜索引擎和屏幕阅读器。
啊哈,也许您没有考虑过屏幕阅读器,但如果您不是屏幕阅读器用户或认识某人是屏幕阅读器用户,那么它可能不会打扰您。 屏幕阅读器使用语言信息以适当的口音和正确的发音来阅读内容。
语言相关样式的关键是在页面标记中正确使用 lang 属性。 lang 属性将 ISO 639[1] 语言代码识别为值。
更新:Tobias Bengfort[2] 指出 lang 属性使用名为 BCP 47[3] 的 IETF 规范,该规范很大程度上基于 ISO 639 标准。
在大多数情况下,您将使用像 zh 这样的两个字母代码来表示英语,但英语(包括其他语言,例如阿拉伯语)被视为一种宏语言,由许多习语和更具体的代词标记的语言组件组成。
有关如何构建语言标签的深入说明,请参阅 HTML 和 XML 中的语言标签 [4]。
一般指导是 html 元素必须始终具有 lang 属性集,然后由所有其他元素继承。
<html lang="zh">
在同一页面上看到不同语言的内容并不罕见。 在此示例中,您将使用 span 或 div 包装内容,并将正确的 lang 属性应用于包装元素。
The fourth animal in the Chinese Zodiac is Rabbit (<span lang="zh">兔子).
现在我们已经对其进行了排序,以下技术将假设 lang 属性已被负责任地实现。
:lang() 伪类选择器
事实证明:lang()伪类选择器并不那么出名。
但是这个伪选择器真的很酷,因为它可以识别内容的语言,即使该语言是在元素外部声明的。
例如,包含两种语言标记的行如下所示:
<p>
We use <em>italics</em> to emphasise words in English, <span lang="zh">但是中文则是用<em>着重号</em></span>.
</p>
有以下款式可供选择:
em:lang(zh) {
font-style: normal;
text-emphasis: dot;
}
如果您的浏览器支持 text-emphasis CSS 属性,您应该能够看到 em 中每个汉字添加了强调标记(传统上用于指示一系列东亚文本的印刷符号)。 Chrome 需要 -webkit- 前缀(这里有很多咒骂)。
我们用粗体指出日语中的短语,但用英语强调。
但关键是lang属性不是应用于em元素,而是应用于其父元素。 伪类仍然有效。 如果我们使用更常见的属性选择器,例如[lang="zh],则该属性必须位于em元素上才能生效。
使用属性选择器
这引出了我们的下一个技术,即使用属性选择器。 这些允许我们选择具有特定属性的元素或具有特定值的属性。 (插件时间,要了解有关属性选择器的更多信息,请尝试您自己的 Codrops CSS 参考条目 [5])
匹配属性选择器的方法有七种,但我只会讨论我认为与匹配 lang 属性更相关的这些技术。 我所有的反例都使用英语作为目标语言,因此 zh 及其变体。
更新:Amelia Bellamy Royds[6] 指出,我的示例使得属性选择器对于部分语言标记匹配实际上是必需的,但 :lang() 伪类已经涵盖了该用例。
首先css写表格,我们可以使用如下句式来精确匹配lang属性值:
[lang="zh"]
/* will match only zh */
我之前提到过,中文被认为是一种宏语言,这意味着它的语言标签可以由额外的细节组成,例如脚本子标签 Hans 或 Hant(W3C 规定,如果需要区分,则只能使用脚本子标签,否则不使用脚本子标签)使用)、区域设置子标签 HK 或 TW 等。
关键是,语言标签可以长于两个字母。 但最通用的类别总是排在第一位,因此对于以特定字符串开头的属性值,我们使用以下涉及 ^ 的语法:
[lang^="zh"]
/*将匹配zh,zh HK,zh Hans,zhong,zh123…
*基本上是以zh作为前两个字符的任何内容*/
还有另一种涉及 | 的模式,它将匹配选择器中的确切值或以值开头后跟 - 的值。 这实际上只是为了语言子代码匹配,不是吗?
[lang|="zh"]
/* 将匹配 zh, zh-HK, zh-Hans, zh-amazing, zh-123 */
请记住,使用属性选择器时,属性必须位于要设置样式的元素上,如果它位于父元素或祖先元素上,则它将不起作用。 请注意,我提供的一些语言标记匹配示例已经可以使用 :lang() 伪类来完成。
换句话说,除了 lang="en" 之外,:lang(en) 还会匹配 lang="en US"、lang="en GB" 等。当我能想出更好的反例时,我会更新这些反例那些。 另外,使用 :lang() 伪类。
普通的类或 ID 又如何呢?
是的。 可以使用普通的类或 ID。 尽管您不会利用您已有的便利。 (同样,我的假设是正确且负责任地应用了 lang 属性)但实际上,请继续为应用特定语言相关样式的元素提供类名称。 如果你真的想要,没有人会阻止你。
CSS 属性
好的,选择器已经涵盖了。 让我们讨论一下我们想要应用于与这些选择器匹配的元素的样式。
书写模式
写入模式的默认值为horizontal-tb。 完全合乎逻辑,因为网络诞生于欧洲核子研究中心,其官方语言是法语和德语。 另外,我觉得大多数互联网技术都是在德语国家首创的。
但人类的神奇给了我们3000多种文字,而且文字和书写方向远远多于从上到下的水平方向。
传统蒙古文是从左到右垂直书写,而英语、汉语、日语等东亚语言则是从右到左垂直书写。 允许您执行此操作的写入模式属性分别是vertical lr 和vertical rl。
Sideways-lr 和 Sideways-rl 也有值,它们会向侧面旋转符号。 每个 Unicode 字符都有一个垂直方向属性,该属性告诉渲染引擎默认情况下字形应如何定向。
我们可以通过 text-orientation 属性来改变字符的方向。 当您将东亚文本与基于拉丁语的短语或字符垂直排列时,这通常会发挥作用。 对于速记,您可以选择使用 text-combination-vertical 将字母压缩到一个字符空间中。
有些人可能想知道从右到左的语言,如阿拉伯语、希伯来语或波斯语(仅举几例),以及 CSS 是否也适用于此类脚本。 简而言之,CSS 不应该用于单向样式。 W3C 的指导如下:
由于方向性是文档结构的一个组成部分,因此应使用标签来设置文档或信息块的方向性,或者指示文本中单独使用 Unicode 单向算法不足以实现所需方向性的位置。
这是因为通过 CSS 应用的样式可能会在不同的上下文中被关闭、覆盖、无法识别或修改/替换。 相反,建议使用 dir 属性来设置显示文本的基本方向。
我强烈建议参考 HTML 中的结构化标记和从右到左文本 [7]、CSS 中的双向支持与标记 [8] 以及 HTML 中的内联标记和单向文本 [9],以获得更详尽的解释和实现细节。
逻辑属性
网页上的所有内容都是一个袋子,CSS 总是使用化学方向“底部”、“底部”、“左侧”和“侧面”来指示我们要定位袋子的哪一侧。 然而,当书写模式不是默认的从上到下水平方向时,这些值常常会令人困惑。
由于该规范仍处于草案状态,句型可能会继续修改。 即使在今天,当前的浏览器实现仍与规范中的不同,因此请务必使用 MDN 仔细检查最新的句子模式:CSS 逻辑属性和值 [10]。
更新:David Baron 强调,我使用的是规范先前版本中的旧句子模式,浏览器中实现的句子模式实际上是编辑草案中的句子模式。 该表已相应更新。
用于定位的袋子的化学侧和逻辑侧的书写方向矩阵及其对应值如下(在编写时该表已从规范中删除):
使用 inset-block-start 作为容器的逻辑底部css写表格,使用 inset-block-end 作为容器的逻辑顶部。 在容器的逻辑侧使用 inset-inline-start,在容器的逻辑侧使用 inset-inline-end。
border、margin、padding也有对应的贴图,分别是:
<h1>A comparison of physical and logical directions for borders</h1>
<p>
Given the requirement is to have a box with a run of text within it with the
following characteristics:
</p>
<ol>
<li>
The border colour at the top edge <strong>of the run of text</strong> should
be red.
</li>
<li>
The border colour at the right edge
<strong>of the run of text</strong> should be green.
</li>
<li>
The border colour at the bottom edge
<strong>of the run of text</strong> should be blue.
</li>
<li>
The border colour at the left edge
<strong>of the run of text</strong> should be yellow.
</li>
</ol>
<p>
Using physical directions requires a modification every time the writing
direction changes, whereas using logical properties allows the same properties
and values for all six use cases.
</p>
<hr />
<section>
<h1>Physical directions</h1>
<div class="phy-boxes">
<article>
<div class="phy-box1">
<p>This is a sentence.</p>
</div>
<pre><code>border-top-color: tomato;
border-right-color: limegreen;
border-bottom-color: dodgerblue;
border-left-color: gold;</code></pre>
</article>
<article>
<div class="phy-box2" dir="rtl">
<p>This is a sentence.</p>
</div>
<pre><code>border-top-color: tomato;
border-left-color: limegreen;
border-bottom-color: dodgerblue;
border-right-color: gold;</code></pre>
</article>
<article>
<div class="vlr phy-box3">
<p>This is a sentence.</p>
</div>
<pre><code>border-left-color: tomato;
border-bottom-color: limegreen;
border-right-color: dodgerblue;
border-top-color: gold;</code></pre>
</article>
<article>
<div class="vlr phy-box4" dir="rtl">
<p>This is a sentence.</p>
</div>
<pre><code>border-left-color: tomato;
border-top-color: limegreen;
border-right-color: dodgerblue;
border-bottom-color: gold;</code></pre>
</article>
<article>
<div class="vrl phy-box5">
<p>This is a sentence.</p>
</div>
<pre><code>border-right-color: tomato;
border-bottom-color: limegreen;
border-left-color: dodgerblue;
border-top-color: gold;</code></pre>
</article>
<article>
<div class="vrl phy-box6" dir="rtl">
<p>This is a sentence.</p>
</div>
<pre><code>border-right-color: tomato;
border-top-color: limegreen;
border-left-color: dodgerblue;
border-bottom-color: gold;</code></pre>
</article>
</div>
</section>
<hr />
<section>
<h1>Logical directions</h1>
<div class="log-boxes">
<div class="log-box">
<p>This is a sentence.</p>
</div>
<div class="log-box" dir="rtl">
<p>This is a sentence.</p>
</div>
<div class="vlr log-box">
<p>This is a sentence.</p>
</div>
<div class="vlr log-box" dir="rtl">
<p>This is a sentence.</p>
</div>
<div class="vrl log-box">
<p>This is a sentence.</p>
</div>
<div class="vrl log-box" dir="rtl">
<p>This is a sentence.</p>
</div>
</div>
<pre><code>border-block-start-color: tomato;
border-inline-end-color: limegreen;
border-block-end-color: dodgerblue;
border-inline-start-color: gold;</code></pre>
</section>
[class$="boxes"] {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
gap: 1em;
}
article {
margin-bottom: 1em;
}
article > div,
[class$="box"] {
width: 200px;
height: 200px;
border: 1em solid;
position: relative;
margin: 1em;
}
.phy-box1 {
border-top-color: tomato;
border-right-color: limegreen;
border-bottom-color: dodgerblue;
border-left-color: gold;
}
.phy-box2 {
border-top-color: tomato;
border-left-color: limegreen;
border-bottom-color: dodgerblue;
border-right-color: gold;
}
.phy-box3 {
border-left-color: tomato;
border-bottom-color: limegreen;
border-right-color: dodgerblue;
border-top-color: gold;
}
.phy-box4 {
border-left-color: tomato;
border-top-color: limegreen;
border-right-color: dodgerblue;
border-bottom-color: gold;
}
.phy-box5 {
border-right-color: tomato;
border-bottom-color: limegreen;
border-left-color: dodgerblue;
border-top-color: gold;
}
.phy-box6 {
border-right-color: tomato;
border-top-color: limegreen;
border-left-color: dodgerblue;
border-bottom-color: gold;
}
.log-box {
border-block-start-color: tomato;
border-inline-end-color: limegreen;
border-block-end-color: dodgerblue;
border-inline-start-color: gold;
}
.vlr {
writing-mode: vertical-lr;
}
.vrl {
writing-mode: vertical-rl;
}
pre {
background: #2d2d2d;
padding: 1em;
margin: .5em 0;
overflow: auto;
color: #ccc;
border-radius: 4px;
width: max-content;
margin: auto;
}
边界的数学和逻辑方向的比较
给定的要求是在具有以下特征的框中运行文本:
物理方向
逻辑方向
大小映射如下:宽度到内联大小,高度到块大小。
列表和计数器
数字系统是一种用于表示数字的书写系统,尽管最常用的数字系统是美国-阿拉伯数字系统(0、1、2、3 等),CSS 允许我们使用其他方式显示有序列表。数字系统。
预定义的计数器样式可以与 list-style-type 属性一起使用,该属性涵盖从 Afar 到 Urdu 的 174 个数字系统。 您可以在 MDN [11] 上查看完整列表。
如果你对 CSS 计数器感兴趣,我在今年的某个时候写了一篇关于它们的文章 [12],其中我探讨了传统英语环境中使用的“天干”和“地支”数字系统(以及一个非常流行的实现CSS,为什么不呢?)
文字修饰
前面说过,东亚语言没有粗体的概念。 相反,我们有积分。 它们可以放置在字符上方或下方,以指出文本、增强语气或防止歧义。
当汉字横写时,这些点位于汉字的下方,当汉字竖写时,这些点位于汉字的右侧。
另一方面,日语在水平书写模式下将指向点放置在字符上方。 为了使 CSS 属性更加通用,CSS 文本装饰模块级别 3 中引入了 text-emphasis-style、text-emphasis-position 和 text-emphasis-color [13]。
除了点之外,您还可以使用不同的符号,例如圆形、三角形,甚至单个字符作为字符串。 位置和颜色也可以根据各自的属性进行调整。
同一规范中还包含线条装饰,为开发人员提供了对逗号和上划线(规范的第 4 级)的更精细控制。 然而,这对于经常溢出基线的降序或反向脚本特别有用。
text-decoration-skip 由 CSS text-decoration 模块 [14] 的第 4 级覆盖,该模块控制覆盖字形和逗号在跨越字形时的绘制方式。 同样,对于英语等语言来说,这种情况发生的频率较低,但对印度尼西亚语等文字的美观影响很大。
字体改变
有两种类型的 CSS 属性可用于访问 OpenType 功能:高级属性和低级属性。 本规范建议尽可能使用中间属性。 这主要取决于浏览器支持。
例如,东亚字体变体允许控制具有变体的字符的字形模式,例如简体中文字形和简体英文字形。 这是同一个字符,但可以写不同。
还有字体变体连字,它为连字和上下文方式提供了许多预定义的选项,例如任意连字、历史连字或上下文连字。
低级属性是通过字体功能设置访问的,您可以使用 4 个字母的 OpenType 标签来切换您想要的功能(这取决于您的字体是否具有该功能,但假设它具有)。
总共有 141 个功能标签,范围从可选分数到理由替换,从 Ruby 表示法到斜线零。 这些 CSS 属性与字体文件本身的功能密切相关,因此外部依赖关系取决于字体的选择。
结束
这篇文章太长了,所以我将在第二部分中更详细地介绍如何使用我们讨论的选择器来构建布局,以确保即使语言发生变化,我们的布局也保持稳健。 Flexbox 和 Grid 等现代布局属性非常适合此类用例。
我发现 CSS 最有趣的事情之一是我们如何以不同的方式将它们组合起来以获得无数的结果,并且超过 500 个 CSS 属性有如此多的可能性。 我并不是说所有方法都会起作用,因为一般来说,有很多方法可以达到相同的结果,并且有些方法比其他方法更合适。
然而,我们需要通过了解每种技术背后的机制、其优点和缺点,并了解为什么我们选择以某种方式做事,来做出最适合我们的决策。
我始终认为,30多年来,互联网始终是信息媒介,内容是关键。 因此,无论使用何种语言或脚本,都应该优化内容的呈现。 我很高兴 CSS 的持续发展为开发人员提供了实现这一目标的方法。
无论如何,请继续关注第二部分。
原标题:CSS国际化
发表评论