> ## Documentation Index
> Fetch the complete documentation index at: https://waffo.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# 收银台语言

> 哪个字段决定 Waffo 收银台的语言、准确的 BCP 47 格式与校验错误、收银台选择展示语言时使用的完整优先级顺序，以及收银台可渲染的全部语言列表。

本页只覆盖 Waffo 托管收银台的**语言**：你传的字段、它接受哪些值，以及当你
什么都不传时页面如何决定渲染哪种语言。

展示哪些支付方式、以什么顺序展示是另一个决策——见
[收银台支付方式展示规则](/docs/zh/support/cashier-display-rules-faq)。
国家切换、跳转 URL 与 `orderAction.actionType` 见
[收银台跳转与动作类型](/docs/zh/support/cashier-redirect-and-action-type-faq)。

## 哪个字段控制收银台的展示语言？

`paymentInfo.cashierLanguage`，在创建订单时传入。

| | |
| - | - |
| 字段 | `paymentInfo.cashierLanguage` |
| 是否必填 | 否 |
| 最大长度 | 24 个字符 |
| 格式 | IETF BCP 47 语言标签 |
| 校验时机 | 创建订单时——无效值会导致创建调用失败 |
| 作用范围 | 仅该笔订单。它不是账户级设置，因此需要每笔订单都传。 |

商户 Portal 中没有可以固定收银台语言的设置。如果你想要固定语言，
请在每笔订单上都传 `cashierLanguage`。

## `cashierLanguage` 必须是什么格式？

`language[-script][-region]`，不接受其他形式：

| 子标签 | 标准 | 规则 |
| - | - | - |
| language | ISO 639-1，两个字母 | 必填。必须是收银台支持的语言——集合是封闭的。 |
| script | ISO 15924，四个字母 | 可选。如果存在，必须是 `Hant` 或 `Hans`——集合是封闭的。 |
| region | ISO 3166-1 alpha-2，两个字母 | 可选。必须是有效的国家/地区代码。任何有效代码都会被接受，无论收银台是否有针对它的专门文案。 |

可以通过的示例：

| 值 | 含义 |
| - | - |
| `en` | 英语 |
| `en-HK` | 英语，香港 |
| `zh-Hant-HK` | 繁体中文，香港 |
| `zh-Hans-HK` | 简体中文，香港 |
| `ja-JP` | 日语，日本 |

会被拒绝的值：

* 下划线分隔——`en_US` 不是 BCP 47 标签。
* 变体子标签——`de-DE-1996`。
* 扩展子标签——`en-US-x-foo`。
* 任何超过 24 个字符的值。

大小写会为你自动规范化，所以 `en-us` 会被接受并存为 `en-US`。

## 值不对时我会收到什么错误？

两种不同的结果，含义也不同：

| 情形 | 错误 | 消息 |
| - | - | - |
| 标签结构无效、带有变体/扩展子标签，或 region 不是真实的 ISO 3166-1 alpha-2 代码 | `A0047` | `The cashier language format is invalid, it must follow IETF BCP 47: a two-letter ISO 639-1 language, an optional four-letter ISO 15924 script, and an optional two-letter ISO 3166-1 alpha-2 region` |
| 标签格式正确，但语言或 script 不在支持集合内 | `A0026` | `The cashier language specified by merchant currently is not supported` |

两者都在创建订单时以 HTTP 400 返回，所以错误的值永远不会到达收银台页面。
如果收到 `A0047`，修正字符串的形态。如果收到 `A0026`，形态没问题，但该语言
本身不是 Waffo 会渲染的语言——请核对下方列表。

## 订阅也能用同一个字段吗？

可以。`paymentInfo.cashierLanguage` 在创建订阅时同样存在，名称相同、同样
24 个字符上限、同样的 BCP 47 规则、同样的两个错误。它在订阅创建流程的同一
位置被校验。

## `cashierLanguage` 除了收银台页面还会影响别的东西吗？

对订阅来说，会：**面向终端用户的订阅通知复用同一个决策**。当 Waffo 向你的
客户发送订阅通知时，如果你提供了 `cashierLanguage`，语言就用它；否则根据
客户的支付币种推断。

注意与收银台页面的区别：通知不是浏览器会话，所以没有 `Accept-Language`
请求头可读，也没有国家 Tab 可读。通知的兜底是**基于币种**的；收银台页面的
兜底是**基于国家**的（见下一个问题）。

## 收银台如何决定展示语言？有优先级顺序吗？

有——五层，从上到下依次评估。第一个产生值的层胜出。

| 层 | 来源 | 说明 |
| - | - | - |
| 0 | **冻结的展示语言** | 客户在支付方式选择页提交时实际正在查看的语言的快照。只有在该提交之后才存在。 |
| 1 | **`paymentInfo.cashierLanguage`** | 你的值，原样使用（已在创建订单时校验并规范化）。 |
| 2 | **浏览器 `Accept-Language`** | 只取请求头中优先级最高的一项。具体读取什么见下文。 |
| 3 | **国家推断** | 提交前，用客户的*真实*位置。提交后，用收银台的展示国家。见下文。 |
| 4 | **`en`** | 当第 3 层得不到可用结果时的最终兜底。 |

值得围绕其设计的两个后果：

* **第 0、1、2 层会锁定语言。** 一旦其中一层命中，语言就不再跟随国家：
  客户切换国家 Tab，文案保持不变。
* **只有第 3 层跟随国家 Tab。** 因此没有 `cashierLanguage`、也没有可用
  `Accept-Language` 的客户，在切换国家时会看到文案变化——而具备其中任一项
  的客户不会。

语言解析只影响展示。如果它因任何原因失败，支付本身不受影响。

## 第 3 层实际使用的是哪个国家？

取决于订单处于生命周期的哪个阶段，而且这个区分很重要，因为"展示国家"和
"客户所在国家"并不是一回事。

| 订单状态 | 第 3 层使用的国家 |
| - | - |
| 仍在支付方式选择页 | 客户的**真实**位置：如果他们切换到了一个真实国家的 Tab，就用该国家；否则用根据 IP 推断的国家。 |
| 提交后 | 收银台的**展示国家**（`countryCode`）。 |

在选择页上，当客户自己的国家不在订单的候选列表中时，展示国家可能会被回填为
候选列表中的某个国家——这个回填值并不描述客户在哪里，所以语言决策有意不使用它。

选择 **Global** Tab 不是一个位置，因此不会被当作位置处理：它会落到根据 IP
推断的国家。

## 什么是冻结的展示语言？为什么会有第 0 层？

当客户在支付方式选择页提交他们的选择时，收银台会把他们当时正在查看的语言
存到订单上。从此以后，这个值优先于其他一切。

它的存在是为了阻止语言在支付过程中漂移。一个全球可用的支付方式会把订单的
展示国家改为 **Global**，这是一个哨兵值而不是真实国家。如果没有这个快照，
一笔原本以本地语言展示的订单，会在客户选择全球支付方式的那一刻翻转为英语
兜底——客户会眼看着页面在选择和付款之间切换语言。快照把他们已经看到的
语言固定下来。

你无法设置或读取这个值；它由收银台在提交时写入。它对你集成的实际影响只有
这一点：**客户在选择页提交之后，就再没有任何东西会改变语言了。**

## 收银台究竟从 `Accept-Language` 中读取什么？

第 2 层比大多数人预期的更窄：

* 只考虑请求头中**权重最高**的那一项。如果它无法映射到受支持的语言，收银台
  **不会**尝试下一项——而是落到第 3 层。
* 只使用**主语言子标签**。请求头里的 `zh-Hant-TW` 会折叠为 `zh`；请求头中
  的 script 和 region 会被丢弃。
* 接受的主子标签为 `en`、`es`、`id`、`ja`、`ko`、`ms`、`pl`、`pt`、`th`、
  `tr`、`vi`、`zh`。其他任何值——`fr`、`ru` 等——都不产生结果，落到第 3 层。
* 格式错误的请求头（某些较旧的 App 内置浏览器会发出重复的 quality 值）
  会退化为读取原始字符串中的第一个语言标签，映射规则相同。

由于第 2 层在主子标签级别解析，来自浏览器的 `zh` 会渲染为**繁体**中文——
见下文的 script 兜底。

## 收银台支持哪些语言？

以下是 `cashierLanguage` 作为完整标签接受的值：

| 标签 | 语言 |
| - | - |
| `en` | 英语 |
| `pt-BR` | 葡萄牙语（巴西） |
| `es-MX` | 西班牙语（墨西哥） |
| `es-PE` | 西班牙语（秘鲁） |
| `es-CO` | 西班牙语（哥伦比亚） |
| `es-CL` | 西班牙语（智利） |
| `id-ID` | 印尼语 |
| `vi-VN` | 越南语 |
| `ru-RU` | 俄语 |
| `th-TH` | 泰语 |
| `ja-JP` | 日语 |
| `ko-KR` | 韩语 |
| `ms-MY` | 马来语 |
| `pl-PL` | 波兰语 |
| `tr-TR` | 土耳其语 |
| `en-KE` | 英语（肯尼亚） |
| `en-NG` | 英语（尼日利亚） |
| `en-HK` | 英语（香港） |
| `zh-Hant-TW` | 繁体中文（台湾） |
| `zh-Hant-HK` | 繁体中文（香港） |
| `zh-Hans-HK` | 简体中文（香港） |
| `zh-Hans` | 简体中文 |

你并不局限于这些精确的字符串。校验是按子标签进行的，所以受支持语言、
可选的受支持 script 和有效 ISO region 的任意组合都会被接受——例如 `en-SG`。
*region* 会改变什么，见下一个问题。

## 我传了 `en-HK`，页面看起来和 `en` 一模一样。region 子标签是被忽略了吗？

对页面文案而言，实际上是的。收银台文案维护在 **13 个语言桶**中，标签只按
语言加 script 匹配到桶——region 子标签永远不会选中另一套文案：

| 桶 | 落入该桶的标签 |
| - | - |
| `en` | `en`、`en-HK`、`en-KE`、`en-NG`、任何 `en-*` |
| `pt` | `pt-BR`、任何 `pt-*` |
| `es` | `es-MX`、`es-PE`、`es-CO`、`es-CL`、任何 `es-*` |
| `zh-Hant` | `zh-Hant-TW`、`zh-Hant-HK`，以及裸 `zh` |
| `zh-Hans` | `zh-Hans`、`zh-Hans-HK` |
| `vi` | `vi-VN` |
| `th` | `th-TH` |
| `id` | `id-ID` |
| `ja` | `ja-JP` |
| `ko` | `ko-KR` |
| `ms` | `ms-MY` |
| `pl` | `pl-PL` |
| `tr` | `tr-TR` |

所以 `es-PE` 和 `es-CL` 渲染同一套西班牙语文案，`en-KE` 和 `en-NG` 渲染
同一套英语文案。region 子标签仍会带在订单上，并仍用于本地化格式化，但不会
分叉出不同的措辞。

两条让人意外的具体规则：

* **裸 `zh` 渲染繁体中文。** 没有 script 子标签时无法区分两者，所以收银台
  把 `zh` 解析为 `zh-Hant`。如果你想要简体，请显式传 `Hans` script——
  `zh-Hans` 或 `zh-Hans-HK`。
* **没有对应桶的语言渲染英语。** `ru-RU` 能通过校验，但俄语不在 13 个文案桶
  之中，所以页面以英语渲染。

## 我什么都没传。客户会看到什么语言？

由第 2 到第 4 层按顺序决定：

1. 如果客户的浏览器发送的请求头中排首位的一项是 12 个接受的主子标签之一，
   就使用该语言，并且切换国家 Tab 时不会改变。
2. 否则根据国家推断语言——提交前用他们的真实位置，提交后用展示国家——
   并且**会**随着他们切换 Tab 而改变。
3. 如果两者都得不到结果，页面为英语。

如果确定性的语言对你很重要——本地化品牌体验、受监管市场、基于截图的客服
流程——请传 `cashierLanguage`，而不是依赖这条链。

## 客户下载收据时可以选哪些语言？

同样的 13 个桶，以各语言自己的名称提供：English、Português、Español、
繁體中文、简体中文、Tiếng Việt、ไทย、Bahasa Indonesia、日本語、한국어、Bahasa
Melayu、Polski、Türkçe。

收据语言是客户在下载时自己的选择。它不由 `cashierLanguage` 驱动，选择某种
语言也不会改变收银台页面的语言。

## 我能让客户自己选择收银台语言吗？

收银台页面上没有语言选择器。语言就是五层链解析出来的结果。

客户*能*改变的是国家，在支付方式选择页上，而这只在链条到达第 3 层时才会改变
语言——也就是只在你没有传 `cashierLanguage`、且他们的浏览器请求头没有匹配时。
国家选择器在什么情况下才会显示，见
[收银台跳转与动作类型](/docs/zh/support/cashier-redirect-and-action-type-faq)。


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.