大多数浏览器和
Developer App 均支持流媒体播放。
-
向左语言
探索如何开发您的 App,使其可本地化为向左书写的语言,如阿拉伯语和希伯来语。我们将介绍这些语言的重要注意事项,分享克服挑战的解决方案并提供在您的 App 中打造一流的向左语言体验的最佳实践。
资源
相关视频
WWDC22
WWDC21
-
下载
Rich Gillam: 大家好 我是Rich 今天我将帮助大家解决从右到左的 问题 您已经将 App 本地化为一系列语言 包括最常见的欧洲语言 和最常见的亚洲语言 所以现在您想将其它本地化为 阿拉伯语和希伯来语 会是个不错的选择 阿拉伯语是我们平台上最常用的 十种语言之一 但是它也带来了一些挑战 这些挑战是您在 开发其他语言时不会遇到的 这就是这次演讲的内容 如何开发您的 App 使其可以本地化为阿拉伯语 和希伯来语等语言 阿拉伯语和希伯来语通常被称为 “从右到左的语言” “right to left languages.” 为什么叫这个 英语 法语 中文 泰语 和许多其他语言的文字 都是像这样从左到右排列的 而在希伯来语中 字符则是像这样从右向左排列的 阿拉伯语也是一样 在阿拉伯语中 字符是粗略地连接在一起的 “salaam” 中的四个字母 分开写时是这样的
顺便说一下 不仅仅是 阿拉伯语和希伯来语这样排列 Apple 实际上支持15种 从右向左的语言的字体和键盘 这里有一段希伯来文 这是希伯来文版的 “Formulas & Functions Help”页面中的 请注意 这段文本在右边对齐 在左边参差不齐 而且许多行 包括最后一行 在左边都有标点符号 这一段中还有一个数字 数字仍然是从左到右排列 这表明 Numbers 支持超 250 个函数 如果我们放大视图 把另一个段落囊括进来 我们会看到这一段有一些英语单词 iWork 名称及其组成 App Pages Numbers 和 Keynote 这些也是从左到右写入的 甚至在希伯来语段落中也是如此 因此 对于许多段落来说 文本是双向的 这是阿拉伯语和希伯来语的固有属性 也是为什么它们经常被称为 “bidi” 语言的原因
如果我们进一步扩大视图 会看到整个页面是从右向左布局的 这里有一个表格 文本在图像的右侧 而不是左侧
如果我们进一步放大视图 会看到 Safari 浏览器的窗口框架 发现它并没有随着内容而停止 阿拉伯语和希伯来语文本行 从右侧开始 向左侧推进 因此很自然地会期望其他 UI 元素也这样做 正如读者希望文本从左边开始 向右边推进一样 阿拉伯语和希伯来语的读者 希望的恰恰相反 在这里 Safari 浏览器的工具栏 从右到左运行 红绿灯按钮在右上角 按钮向左移动 如果我们将焦点扩大到整个屏幕 会发现所有文本都是这样的 这是 Numbers 的帮助屏幕 我们看到 Numbers 的所有元素也改变了方向 侧边栏在左边 标签栏从右向左延伸 甚至文档本身也改变了方向 Mac 菜单栏和程序坞 也是从右向左运行的 做好这一切可能会很复杂 但好消息是 我们为您完成了大部分繁重的工作 大多数对从右到左的支持都是免费的 但有些事情需要记住 这就是我们将要讨论的内容 系统为您做了什么 您何时需要选择加入或退出 以及在实现您自己的设备 从右到左支持时应该考虑什么 我们将讨论文本 图像 控件方向和 UI 布局 我们还将介绍如何用 阿拉伯语显示数字 最后 我们将谈一谈如何测试 您的 App 是否能正确地从右向左操作 让我们开始吧 首先 我们将更多地讨论 文本的工作原理 并介绍一些术语 我们先说说写入方向的概念 正如我们看到的 英语是从左到右写入的 希伯来语是从右到左写入的 但如果我们把它们混在一起会怎么样
如果您要写这样一句多语种的句子 每个单独的成分仍然保持 它们的写入方向 但这意味着每个句子将由 三个成分组成 两个独立的母语文本片段 中间夹着一个不同语言的文本片段 当我们讨论一个段落的写入方向时 我们讨论的是这些片段的顺序 当我们说英语句子是 从左到右的写入方向时 是因为这三个方框从左到右排列 当我们说希伯来语句子是 从右到左的写入方向时 是因为这三个方框从右到左排列
另一个不同但相关的概念是文本对齐 如果您阅读的是从左到右的语言 您的眼睛会转向页面的左边 然后向右移动 如果您阅读的是从右到左的语言 情况正好相反 因此 文本在从右到左的语言中 靠右对齐 好消息是 大多数时候 您不必担心这些事情 CoreText 不仅负责在 一行或一段文本中 正确地安排所有字符 包括不同方向的文本混合在一行中时 而且我们所有的 UI 框架也自动 设置写入方向 和对齐方式 所有 UI 小组件都默认为 “自然写入方向” 和“自然对齐” 文本小组件的默认写入方向 与用户 UI 语言的 正常写入方向相匹配 也就是说 如果 UI 是希伯来语或阿拉伯语 则文本小组件的写入方向 默认为从右向左 自然对齐遵循写入方向 也就是说 如果文本小组件的 写入方向是从右到左 它也将右对齐 大多数情况下 这就是您需要的 但您可以重写默认值 我们将在控件方向一节中 更多地讨论这一点 现在是时候开始画一个术语图表了 我们这里说的是 自然对齐 在从左到右的语言中 对应于左对齐 在从右到左的语言中 对应于右对齐 我们会在这个图表中添加 但当然 您要担心的不仅仅是文本 以相反的方向阅读文本会对 您的 App 中 除文本之外的元素产生深远的影响 我们来谈谈它是如何 影响图标和其他图形元素的 这是英语和阿拉伯语的 Pages 工具栏 我们仔细看看工具栏中的一些图标 许多按钮 在两种语言中看起来是一样的 如“添加页面”和“媒体”按钮 这要么是因为它们是对称的 要么是因为它们的方向性 与语言无关 它们在两种语言中都毫无违和感 其他按钮 如“视图”和“文档”按钮 可以切换到阿拉伯语的映射 “视图”按钮会弹出 Pages 侧边栏 它出现在窗口的另一侧 以阿拉伯语显示 因此图标必须改变以反映这一点 “文档”按钮会发生变化 如果用户用阿拉伯语写入 页面会转向相反的方向 您可能会遇到图标完全改变的情况 “插入文本框”按钮上的字母 更改为不同的字母 以反映用户的语言
同样 好消息是 我们已经为您解决了很多类似问题 您必须考虑图像方向 而不是一般的 文字写入方向 但要完成这个任务很简单 这是英语和阿拉伯语的 Mac Pages 中的 View 菜单 请注意 “Show Ruler”图标会反转 在从右向左的语言中 垂直标尺在右手边 对于像标尺图标这样的自定义图像 从右到左的操作是在 Xcode 图像集编辑器中控制的 如果您的图像从左到右 和从右到左是相同的 那么您不需要做任何特别的操作 当您的 App 运行在与开发语言相反的 语言中时 系统还可以通过算法 来映射您的图像 您可以在 Xcode 的 图像集编辑器中请求此功能 在侧边栏中 您会找到一个 标记为“Direction”的控件 如果点击此控件 您会看到一个有四个选项的菜单 如果不管使用何种 UI 语言 图像都是相同的 则选择“Fixed” 如果需要算法映射 可选择其中一个“Mirrors”选项 这取决于开发语言的编写方向 如果图片无法通过算法进行映射 或者图片有多个元素 在 UI 改变方向时 表现方式不同 又或者您有不想移动的着色 可选择“Both" 并将三个新的孔添加到 图像集编辑器中 使您可以创建单独的图像 用于从左到右和从右到左的背景中 但如果您用来自 SF Symbol 的图像 就像 Pages 工具栏那样 事情就更简单了 几乎所有的工作都已为您完成了 从右到左的语言需要 更改的符号会自动更改 以这个项目符号列表图标为例 对于许多图像 SF Symbol 的侧边栏 有一个“本地化”部分 显示所选图像的 本地化版本 在这种情况下 项目符号列表图标 具有不同的从左到右和从右到左版本 它会自动映射
本地化功能不仅仅是 从右向左语言的映射 这是“插入文本框”图标的本地化标签 它不仅有拉丁和阿拉伯文字的 本地化版本 还有其他语种的版本
对于阿拉伯语支持来说 一个特别重要的例子就是问号 它经常被用作“帮助”图标 在阿拉伯语中 问号与拉丁语的问号 是相反的 使用 SF Symbol 中的图标 作为帮助图标 无需任何额外工作即可获得此版本 您必须仔细考虑的一类图像是 箭头和其他方向指示器 这里我们看到了 四个圆圈中的箭头图标 您会发现它们是两对 有两个指向左边 两个指向右边 如果我们只看指向左边的两个 您会看到其中一个叫做 “arrow.backward.circle.” 这个图表从右向左翻转指向右侧 另一个叫做 “arrow.left..circle” 而且不是从右向左翻转 SF Symbol 遵循这个命名惯例 您可能想要也可能不想要 从右到左的图标 “向前”和“向后”的键会翻转 而“左”和“右”的键不会 如果使用箭头或其他形状 传达“向前”或“向后”的概念 则需要使用翻转版本 如果使用箭头来传达绝对方向 则需要使用非翻转版本
让我们在术语表上加一行 在 SF Symbol 中选择图像时 请记住“左”和“右” 总是指向这些方向 而“向前”和“向后” 则根据 UI 语言的不同 指向不同的方向 现在让我们讨论一下控件 和其他 UI 小组件 是如何从右到左处理的 这是英语和阿拉伯语的 Mac Keynote 侧边栏 显示形状的格式检查器 请注意 所有对象的 Appearance 都从右向左翻转 我们有很多弹出式菜单按钮 菜单指示器从右向左移动到左侧 我们有几个复选框 在阿拉伯语中 复选框位于标签的右侧 阿拉伯语的不透明度滑块已更改 因此最小值在右侧 最大值在左侧 在此检查器中的所有 其他控件中依此类推 好消息是这些操作都是免费的 我们所有 UI 框架中的 所有标准 UI 控件 都会自动将它们的外观 转换为从右到左的语言 然而 在某些情况下 您可能不希望发生这种情况 或者您需要对发生的方式 有一定的控制 让我们看几个有趣的例子 我们来讨论一下上面 既有文本标签又有图标的按钮 这是显示“ Move In”动画的 Keynote 讲演动画检查器 这个检查器有两个按钮 既有标签又有图标 请注意 预览按钮上的箭头 随着 UI 方向的更改而翻转 但动画方向菜单上的箭头不会 这两者都与 UI 方向相反 但如果方向控件 是一组按钮而不是菜单 您可能不希望它改变方向
为了展示如何控制这个控件 我将这两个示例分离到 一个小型玩具 App 中
下面是在 SwiftUI 中构建该 UI 的代码 这里有一些有趣的事情需要注意 我们逐一查看它们 我们先从图像名称开始 正如我们之前看到的 对于 SF Symbol 的图像 您可以选择一个翻转的图标 或者一个不翻转的图标 这里我们使用 “arrowtriangle.forward.fill” 作为 Preview 按钮 名字中的“向前”表示 它是从右向左翻转的 我们使用“arrow.left” 和“arrow.right”作为方向按钮 名字中的“左”和“右”表示 它们不会从右到左翻转
如果末使用的是 AppKit 或 UIKit 则其工作方式相同 这是我在 Xcode storyboard 编辑器中的 App 选择了“Preview”按钮 您可以使用 Attribute 检查器中的 “Image”控件控制按钮的图标 在代码中 您可以使用 按钮的“Image”属性设置它 它在 AppKit 和 UIKit 中的 工作方式基本相同 回到我们的 SwiftUI 示例 下一个问题是 如何控制图标位于标签的哪一侧 您可以通过设置标签样式 来完成此操作 内置的 TitleAndIconLabelStyle 将图标放在 用户阅读方向的标签之前 我们可以用这个做“左”按钮 对于另外两个按钮 我们希望图标位于 用户阅读方向上的标签之后 为此 您需要一个自定义标签样式 但这很容易做到 您的标签样式的 makeBody() 方法 只需创建一个 HStack 并将标题和图标添加到其中 与任何 HStack 一样 您添加它们的 顺序决定了它们显示的顺序 并且在适合 UI 方向时 顺序会自动翻转 此技术适用于任何可以 获取标签的视图 而不仅仅是按钮 当然 您不希望“右”按钮上的 图标改变方向 无论 UI 方向如何 您都希望它始终位于右侧 这就引出了这段代码片段中 最后一件有趣的事情 SwiftUI 中的视图 从 SwiftUI 环境中 获取它们的方向性 您可以对其进行修改 要实现这一点 可以向视图添加 “环境”修改器 并为其指定 要更改的属性的键和新值 在这里 我们将重写 环境的 layoutDirection 属性 使其始终从左到右 而不管我们可能从父节点继承什么值 以这种方式改变环境适用于 所有响应用户 UI 方向的 SwiftUI 视图 请注意 我们对包含 “左”和“右”按钮的 HStack 应用了修改器 that contains the “Left” 对视图环境的任何改变都会被 它的子视图继承 所以把它放在这里 不仅可以防止 HStack 颠倒按钮的顺序 还可以防止两个按钮颠倒标签的布局 当然 我们没有将 环境修改器应用到 “Preview”按钮的父链中的任何东西 所以它仍然在适当的时候翻转 正如我们所希望的那样
总结一下 “左”按钮的图标在左边 因为我们使用了内置 TitleAndIconLabelStyle 而“Preview”和“右”按钮的图标在右边 因为我们用了一个自定义的标签样式 我们称之为 IconOnRightLabelStyle “左”和“左”按钮不会改变它们的顺序 或它们标签的内部排列 因为我们在包含它们的 HStack 中 添加了一个环境修改器 将布局方向设置为从左到右 “Preview”按钮改变了 其标签的内部排列方式 因为它没有此修改器 这在 AppKit 和 UIKit 中是不同的 在这两个框架中 图标相对于标签的位置 是由 Xcode 的 Attribute 检查器中的 “位置”控件控制的 如果点击这个控件 您会看到菜单中有两对选项 它们会将标签和图标水平对齐 您会看到“前缘”和“左” 还有“后缘”和“右” “前缘”和“后缘”根据 UI 方向 改变它们的含义 “左”和“右”则不会 在 AppKit 中 您可以用按钮的 imagePosition 属性来控制它 在 UIKit 中 则需要按钮配置上的 imagePlacement 属性来控制它 这可能意味着您需要 首先设置按钮的配置 “Preview”按钮上的图标会改变方向 因为我们将其位置设置为“后缘” 而“右”按钮上的图标不会改变方向 因为我们将其位置设置为“右” 这也使得我们填完了 术语表的最后一行 在讨论 UI 布局时 “前缘”和“后缘”这两个术语 会经常出现 就像“向前”和“向后”一样 您经常会看到它们与 “左”和“右”对比使用 “前缘”指的是 最靠近行首一侧的边缘 或者是读者开始阅读的 屏幕或窗口的边缘 从左到右 从右到左 后缘是相对的一侧 最接近直线的末端 从右到右为右 从右到左为左 大多数时候 您想用这些 来代替“左”和“右” 只有在与绝对方向相关的事情上 才使用“左”和“右”
我们来看看另一个有趣的案例 这是英语和阿拉伯语版的 iPhone 上 Keynote 中的 文本格式检查器的一部分 这个特殊的屏幕截图 有四个分段的控件 最上面的两个按钮 即检查器的页面选择器 和标准的“粗体/斜体/下划线” 样式按钮 会根据 UI 语言来颠倒句段的顺序 如果您不懂阿拉伯语 就必须相信页面选择器 与我们所看到的其他控件一样 这是默认设置 您可以免费试用此功能 另外两个分段控件 即对齐控件 不会颠倒其句段的顺序 这是因为它们在绝对方向上移动对象 左对齐就是左对齐 不管它是行首还是行尾 让我们看看如何防止这些控件翻转 我们已经知道如何在 SwiftUI 中实现这一点 您只需应用一个“环境”修改器 将环境的 layoutDirection 属性 更改为从左到右 在这里 我们使用这项技术来防止 对齐控件反转 但让样式控件像往常一样反转 在 UIKit 中 工作方式完全不同 这是 Xcode 中的一个玩具 App 用来模拟 分段控件的行为 我有两个分段控件 一个模仿粗体/斜体/下划线的行为 另一个模仿对齐控件 选择对齐控件 在属性检查器中 您会发现 一个标签为“Semantic”的菜单 如果点击这个菜单 会有五个选项 此菜单控制所谓的语义内容属性 您用它来说明这是什么类型的控件 系统用它来决定它是否 根据 UI 方向翻转其外观 默认值为“未指定” 这将导致控件翻转其外观 “Playback”表示该控件是一个 媒体播放控制面板 或一组播放控制面板的一部分 “Spatial”表示控件是一个空间控件 或一组控件的一部分 空间控件在空间中 以绝对方向移动对象 最后 您可以强制该控件 始终从左向右或从右向左布局 因此 粗体/斜体/下划线控件 从右到左翻转其片段 因为其语义内容属性 被设置为“未指定” 而对齐控件不翻转其片段 因为其语义内容属性 被设置为“空间的” 它的优点在于它不仅仅适用于 UISegmentedControl 所有的 UIView 都有一个语义内容属性 它控制所有控件从右到左的行为 对于任何具有子组件的 标准 UIKit 视图 语义内容属性将确定该视图的 子组件的位置是否基于 UI 语言翻转
在 AppKit 中 这类操作的方式有所不同 对于所有的 NSControls Xcode 属性检查器 都包含两个菜单 分别标记为 “Layout”和“Mirror.” “Layout”菜单对应于 控件的 userInterfaceLayoutDirection 属性 该属性指示控件应该使用 从左到右还是从右到左的布局 当您使用 Interface Builder 时 通常不会更改此选项 相反 您可以使用“Mirror”菜单 将其设置为“Always”会导致 userInterfaceLayoutDirection 当 nib 在从右向左的 用户的 UI 语言中加载时 控件的布局会被翻转 而将其设置为“Never” 则会破坏此行为 从而保持布局不变 通过将该值设置为“Never” 可以保持对齐控件的布局不变 如果您没有使用 Interface Builder 则可以通过直接将控件的 userInterfaceLayoutDirection 设置为从左到右 来完成相同的操作 顺便说一句 userInterfaceLayoutDirection 是 NSView 上的一个属性 但它只出现在 Interface Builder 中的 NSControl 实例上 因此 如果您想翻转 非 NSControl 的内容 就需要用到此处显示的代码
在我们继续之前 我想再谈谈文本 这是 Mac 版 iWork 中的 “设置文档密码”对话框 在阿拉伯语版本中 您会看到一切都颠倒了 注意标签的变化 在英语中 它们是右对齐的 这样它们就会 靠近编辑文本字段 在阿拉伯语中 它们是左对齐的 换句话说 这是与自然对齐相反的 尾缘对齐 如果您需要的话 在 Mac 上的 SwiftUI 中 获得这个布局非常简单 只需使用一个 Form 将文本字段聚集在一起 但如果像我们的示例那样 其中一个标签是多行的 这就会变得很有趣 如果我们将最后一个标签扩展为两行 就会得到这样的结果 两个单线标签正确对齐 但双线标签没有对齐 问题是 底部标签确实是右对齐的 只有它的边框是右对齐的 而不是边框内的文本行 可以通过向最后一个标签添加 multilineTextAlignment 修改器 来修复此问题 SwiftUI 中的文本对齐 仅在长度超过一行的 文本对象上起作用 对于单行文本对象 其边界框将文本本身紧紧包围 您可以通过对齐 整个文本对象来对齐它 还要注意 无论对齐文本的边界框 还是边界框内的多行文本 都可以选择前缘和后缘对齐 这将根据用户的 UI 方向改变含义 为了使对齐方式与 UI 方向无关 可以使用环境修改器 来更改环境的布局方向 如我们前面所见 在 UIKit 中 文本默认是对齐的 但您可以在必要时 将其更改为绝对方向 在 Interface Builder 中 该控件如下所示 并对应于 UILabel 和 UITextView 上的 textAlignment 属性 最右边带虚线的按钮 可以实现自然或前缘对齐方式 标签的对齐方式 将遵循标签的语义内容属性 其他按钮可实现固定的 左对齐 右对齐或居中对齐 而与 UI 方向或标签的 语义内容属性无关 没有用于后缘对齐的内置设置 您需要用代码来实现这一点 在 AppKit 中 情况略有不同 您仍然拥有对齐控件 它的工作原理与 UIKit 中的 基本相同 但它与 userInterfaceLayoutDirection 交互的方式不同 如果您将“Mirror” 设置为“Automatically” 并且系统将 userInterfaceLayoutDirection 设置为从右到左 则所有对齐设置的含义将颠倒 因此 如果将“Mirror” 设置为“Automatically” 则左对齐实际上是前缘对齐 而右对齐实际上是后缘对齐 我们已经讨论了所有的 标准 UI 小组件 如何自动翻转它们的布局 来匹配用户的写入方向 但在必要的时候 很容易避免这种情况 这扩展到在屏幕上排列单个 UI 小组件 如果您正在使用一个 标准视图或视图控制器 来处理它们的子视图的位置 那么所有的子视图都会在必要的时候 自动翻转它们的布局 而无需执行任何操作 表格视图和集合视图也能正确处理 从右向左语言的滚动 UINavigationController 会自动改变它的 segue 动画的方向 来反映用户的书写方向 并更改“后退”按钮以与之匹配 UIPageViewController 还会自动翻转翻页方向 和轻扫手势的含义 除了使用 stack 视图 定位子视图之外 您通常不希望重写这些内容 但所有视图都遵循 semanticContentAttribute 并使用它来告诉它们 如何布局子视图 标准 AppKit 视图也是如此 表视图和集合视图 也可以处理从右向左的滚动 视图都使用它们的 userInterfaceLayoutDirection 属性 来决定如何布局它们的子视图 尽管 Interface Builder 也会如此 您必须用代码来做 标准的 SwiftUI 视图也反映了 环境的 layoutDirection 属性
如果您使用 Auto Layout 而不是 stack 和网格视图 来布局您的视图 Auto Layout 还会根据 UI 方向自动翻转 如果您有水平约束 您将看到它们会自动将事物 连接到前缘和后缘 正如我们所看到的 “前缘”和“后缘”根据 UI 方向 有不同的含义 但如果需要 您可以将 Auto Layout 约束 设置为绝对左右方向 您可以点击约束一侧的方向 并在弹出的菜单中关闭 “遵循语言方向” 来完成此操作 这将约束两端的方向 从“前缘”和“后缘” 更改为“左”和“右” 在代码中设置 Auto Layout 约束有许多不同的方法 这是其中之一 无论您如何操作 要记住的是 使用“前缘”和“后缘” 而不是“左”和“右” 除非在相对较少的情况下 无论 UI 语言的 编写方向如何 您都希望使用相同的布局方向 好了 刚才的内容有点多 我们休息一下 主要的结论是 我们已经为您 完成了处理从右到左语言的 大部分工作 当您需要重写它时 有很多方法可以做到这一点 让我们再来看一下术语幻灯片 记住 “左”和“右”始终是左和右 而其他术语的含义 则取决于整个 UI 方向
在结束之前 让我们看一个更重要的问题 那就是如何显示数字 严格来说 这不是从右到左的问题 但对于许多开发者来说 阿拉伯语是他们本地化的第一种语言 因为它使用的数字字符 不同于英语中的数字字符 这些数字是这样的 数字的命名有很多不同的约定 但我将大多数欧洲语言中 使用的数字称为“拉丁”数字 而将阿拉伯语中使用的数字 称为“阿拉伯-印度”数字 还有其他语言也有自己的数字 这些是用于印地语的梵文数字 印地语是另一种 使用不同数字的通用语言 需要记住的一件重要的事是 阿拉伯语和印地语 都不太使用它们的本地数字 对于阿拉伯语 它取决于国家 一些国家 如沙特阿拉伯 使用本地数字 而另一些国家 如阿联酋 使用拉丁数字 个人用户也可以选择他们喜欢的数字 对于印地语 我们默认使用拉丁数字 但是用户可以选择使用本地数字
您已经知道像这样构造 UI 字符串不是个好主意 字符串是硬编码的 无法转换 消息不会更改为处理复数等等 但另一个不好的原因是 “peopleInChat” 的值 总是用拉丁数字表示 您可能也已经知道 解决这个问题的方法是 对字符串使用“本地化”的 init 方法 该方法将在 App 包中 查找实际的字符串 并在有 stringsdict 文件的情况下 正确处理复数 好消息是它还能正确处理数字 此处的“peopleInChat”插值的值 将根据用户的区域设置 和首选项使用正确的 本地化数字呈现 这也适用于 SwiftUI 中的文本视图 文本视图初始值设定项还将使用 正确本地化的数字 来呈现任何字符串插值 构造用户可见字符串时 始终使用 String(localization:) 许多其他可以格式化数字的 字符串 API 包括 +stringWithFormat: 和接受数字的 String init 函数 始终使用拉丁数字 需要注意的一个问题是 包含数字的静态字符串 比如这个 这有什么大不了的 您把它发送给翻译 他们翻译 然后您就会得到这个 这在很多地方都是正确的 但在沙特阿拉伯和其他一些国家 您会看到这个 除了 3 所使用的字符外 文本是相同的 当然 您可以为使用 阿拉伯-印度数字的 阿拉伯语地区 和使用拉丁数字的阿拉伯语地区 进行单独的本地化 但是没人这样做 这是一种浪费 更糟糕的是 在阿拉伯语和印地语中 用户可以选择他们想要使用的数字 所以您必须根据用户的偏好 来选择本地化 而不仅仅是根据他们的地区 解决方案是仍然只对 阿拉伯语或印地语进行本地化 但要在运行时将数字替换进去 尽管您在编译时就知道这个值 在 Swift 中 您可以使用 字符串插值来完成此操作
如果有其他元素和数字一起出现 它们相对于数字的位置也是一个挑战 甚至不是所有 从右到左的语言都是一样的 请注意 在阿拉伯语和希伯来语中 减号和百分号位于数字的不同侧 实际上 并不一定是 从右到左的语言才有这个问题 注意 在从左向右的土耳其语中 百分比符号也在左边 当然 请记住 如果您使用的是 本地阿拉伯数字 它们使用的是完全不同的百分比符号 换言之 您真的不想做这种事情 您要在后面加上百分号 或者货币符号 单位缩写 或者您自己加的任何东西 相反 使用数字格式化程序 添加百分号 货币符号或其他符号 在 Swift 中 对所有数值类型 使用 formatted() 方法 很容易做到这一点 如果它是更大字符串的一部分 如本例中所示 String(localized:) 还将确保 格式化的数字 或在运行时代入字符串的 任何其他内容 包括其他字符串 被标记包围 这样可以防止 格式化数字的书写方向 和周围消息相互混淆 最后 我想给您一个提示 用于测试您的 App 以确保您从右向左的操作是正确的 您不必在可执行文件中使用 阿拉伯语 或希伯来语本地化 就可以从右向左测试您的 App 实际上 您可以在开发语言中 测试从右到左的行为 为此 在 Xcode 中 打开方案编辑器 现在转到 Options 选项卡 寻找“App Language”菜单 在这个菜单的底部是一堆 “pseudolanguage”选项 这些都是假语言 它们以各种方式转换您的 UI 让您在没有实际本地化的情况下 检查本地化问题 选择“Right-to-left Pseudolanguage”选项 并点击运行 您的 App 仍然是 英语或其他开发语言 但 UI 会将全部从右到左翻转 这就是我要介绍的全部内容 从右向左语言的本地化 需要注意一些 与书写方向变化相关的问题 但是系统会为您完成 大部分繁重的工作 在某些情况下 通常是在绝对方向上 您可能希望选择这种行为 而这始终是可能的 请记住 并非所有语言 都使用拉丁数字来表示数字 记住这些东西 实现从右到左 并不难
-
-
12:55 - Control orientation example
struct ContentView: View { var body: some View { VStack(alignment: .leading) { Button(action: {}) { Label("Preview", systemImage: "arrowtriangle.forward.fill") }.labelStyle(IconOnRightLabelStyle()) HStack() { Button(action: {}) { Label("Left", systemImage: "arrow.left") }.labelStyle(TitleAndIconLabelStyle()) Button(action: {}) { Label("Right", systemImage: "arrow.right") }.labelStyle(IconOnRightLabelStyle()) }.environment(\.layoutDirection, .leftToRight) }.padding() } }
-
14:22 - Control orientation custom label style example
struct IconOnRightLabelStyle : LabelStyle { func makeBody(configuration: Configuration) -> some View { HStack { configuration.title configuration.icon } } }
-
14:43 - Control orientation example
struct ContentView: View { var body: some View { VStack(alignment: .leading) { Button(action: {}) { Label("Preview", systemImage: "arrowtriangle.forward.fill") }.labelStyle(IconOnRightLabelStyle()) HStack() { Button(action: {}) { Label("Left", systemImage: "arrow.left") }.labelStyle(TitleAndIconLabelStyle()) Button(action: {}) { Label("Right", systemImage: "arrow.right") }.labelStyle(IconOnRightLabelStyle()) }.environment(\.layoutDirection, .leftToRight) }.padding() } }
-
18:58 - Control orientation example—keeping controls from reversing
struct ContentView: View { var body: some View { VStack(alignment: .leading) { Picker(selection: $textStyle, label: Text("Text Style")) { Text("B").tag(TextStyle.bold) Text("I").tag(TextStyle.italic) Text("U").tag(TextStyle.underline) Text("S").tag(TextStyle.strikethrough) }.pickerStyle(.segmented) Picker(selection: $alignment, label: Text("Alignment")) { Image(systemName: "text.alignleft").tag(TextAlignment.left) Image(systemName: "text.aligncenter").tag(TextAlignment.center) Image(systemName: "text.alignright").tag(TextAlignment.right) }.pickerStyle(.segmented) .environment(\.layoutDirection, .leftToRight) } } }
-
22:38 - Control orientation example—form with multiline text alignment modifier
var body: some View { Form { TextField("Password:", text: $password) TextField("Verify:", text: $verifyPassword) TextField("Password Hint:\n(Recommended)", text: $passwordHint) .multilineTextAlignment(.trailing) }.padding() }
-
27:14 - Set up Auto Layout in code
myView.leadingAnchor.constraint(equalTo: mySuperView.leadingAnchor, constant:16)
-
29:05 - Digits in Arabic
myLabel.string = String(localized: "There are \(peopleInChat) people in this chat.", comment: "Label indicating number of chat participants") Text("There are \(peopleInChat) people in this chat.", comment: "Label indicating number of chat participants")
-
30:12 - Digits in Arabic
myLabel.string = String(localized: "This application supports \(3) file formats.", comment: "Label showing number of supported file formats (number is always 3)")
-
31:41 - Numbers in RTL text
myLabel.stringValue = String(localized: "\(percentComplete.formatted(.percent)) complete")
-
-
正在查找特定内容?在上方输入一个主题,就能直接跳转到相应的精彩内容。
提交你查询的内容时出现错误。请检查互联网连接,然后再试一次。