# lang、dir 与 *_localized 清单成员

> lang 与 dir 设定清单的默认语言和文字方向；*_localized 成员按语言携带 name、short_name、description 与 icons 的译文，Chrome 与 Edge 148 已实现。

清单有三件本地化工具。`lang` 说明清单文本成员所用的语言，`dir` 说明它们的书写方向，
`*_localized` 成员（`name_localized`、`short_name_localized`、`description_localized`、
`icons_localized`）按 BCP 47 语言标签携带各语言版本，普通成员则作为回退。不存在单独的
`translations` 成员；本地化是按字段进行的。

Chrome 148 与 Edge 148 读取 `name`、`short_name`、`description`、`icons` 的 `*_localized`
成员，以及每个 `shortcuts` 条目内同样的四个字段（developer.chrome.com 的清单本地化公告）。
MDN 记录顶层的 `dir` 与 `lang` 没有任何浏览器实现；Chromium 读取的是本地化值内部的 `lang` 与
`dir` 覆盖。Firefox 157 与 Safari 27 丢弃所有 `*_localized` 成员，只显示普通的 `name`。

## 成员

- **`lang`**：字符串，BCP 47 语言标签，例如 `en-AU` 或 `zh-Hans-CN`，比较时不区分大小写。
  默认值：未设置，语言未知。格式错误的标签会被丢弃。
- **`dir`**：字符串，取 `ltr`、`rtl`、`auto` 之一。默认值：`auto`，让浏览器根据文本估计方向。
  无法识别的值解析为 `auto`。
- **`*_localized`**：以语言标签为键的对象。文本成员的每个值是字符串，或形如
  `{ "value": "...", "lang": "...", "dir": "..." }` 的对象；`icons_localized` 的每个值是一个与
  `icons` 形状相同的完整图标数组。默认值：缺省，所有语言都使用普通成员。
- **示例值**：`"name_localized": { "de": "Farbwähler", "en-GB": { "value": "Colour Picker" } }`。

匹配时选取最贴合浏览器语言列表的条目，没有匹配时回退到普通成员；规范把具体的标签匹配算法留给
浏览器。本地化图标数组会整体替换该语言下的 `icons`，而不是与之合并，所以每个语言条目都要带上
完整的尺寸集合。`shortcuts` 没有 `shortcuts_localized`；四个 `*_localized` 成员嵌套在每个快捷
方式对象内部。

`*_localized` 的值不是对象时，解析器用通用提示 `property 'name_localized' ignored, type object
expected.` 丢弃它，普通成员照常生效。

:::observed
Chrome 155（macOS 26，英文界面）的 DevTools > Application > Manifest：清单写
`"name_localized": "Farbwähler"`（该写对象却写了字符串）时，**Errors and warnings** 一节显示
`property 'name_localized' ignored, type object expected.`，**Identity > Name** 仍显示普通的
`name`。同一份清单在 Firefox 157 中没有任何控制台输出：Firefox 读取 `name` 并丢弃这个未知成员。
:::

## 示例

示例按团队通常的添加顺序展开：先是名称，然后是只保留一种语言的品牌名，最后是图标。

### 本地化名称与描述，并以普通成员回退

普通的 `name` 与 `description` 是所有没有条目的语言的回退。`lang` 与 `dir` 描述的就是这些
普通值，所以一个德语优先的应用把 `lang` 设为 `de`，把英文文本放在 `name_localized.en` 下。

```json
{
  "lang": "de",
  "dir": "ltr",
  "name": "Farbwähler",
  "description": "Farben aus Bildern auswählen und als Palette speichern.",
  "name_localized": {
    "en": "Color Picker",
    "en-GB": "Colour Picker",
    "fr": "Sélecteur de couleur"
  },
  "description_localized": {
    "en": "Pick colors from images and save them as a palette."
  }
}
```

设为 `en-US` 的浏览器从 `en` 条目得到 `Color Picker`；设为 `en-GB` 的得到更具体的拼法；设为
西班牙语的回退到德语普通值，这正是该补一个 `es` 条目的信号。

### 在从右到左的区域设置里保留英文品牌名

当值的语言或方向与键所暗示的不同时，用值对象携带自己的 `lang` 与 `dir`。这里阿拉伯语条目保留
拉丁字母的品牌名，并在一份从右到左的清单里把它标记为从左到右的英文。

```json
{
  "lang": "ar",
  "dir": "rtl",
  "name": "منتقي الألوان",
  "short_name_localized": {
    "ar": { "value": "ColorPick", "lang": "en", "dir": "ltr" },
    "en": "ColorPick"
  }
}
```

没有逐值的 `dir`，双向文本渲染器可能把拉丁标签错放在启动器中的阿拉伯文旁边；这个覆盖正是规范
为此提供的修正手段。

### 提供本地化图标并检查浏览器解析出的结果

含有文字的图标需要按语言给出数组。随后脚本读取清单，报告浏览器会为自己的语言选择哪个条目，
没有匹配时回退到普通的 `icons`，这也正是不支持 `*_localized` 的浏览器的做法。

```json
{
  "icons": [{ "src": "/icons/en-512.png", "sizes": "512x512", "type": "image/png" }],
  "icons_localized": {
    "ja": [{ "src": "/icons/ja-512.png", "sizes": "512x512", "type": "image/png" }]
  }
}
```

```js
async function resolvedIcons() {
  const link = document.querySelector('link[rel="manifest"]');
  if (!link) return [];
  const manifest = await fetch(link.href).then((r) => r.json());
  const localized = manifest.icons_localized ?? {};
  const tag = navigator.languages.find((l) => localized[l] || localized[l.split('-')[0]]);
  if (!tag) return manifest.icons ?? [];               // 无匹配或不支持：普通图标
  return localized[tag] ?? localized[tag.split('-')[0]];
}
```

该函数复刻的是回退规则，不是浏览器的精确匹配器，所以它的输出只能当作设置页里的预览，不能当作
操作系统一定会显示的图标。

## 另请参阅

- [name 与 short_name 清单成员](/zh/reference/manifest/name-short-name/)
- [description 清单成员](/zh/reference/manifest/description/)
- [icons 清单成员](/zh/reference/manifest/icons/)
- [shortcuts 清单成员](/zh/reference/manifest/shortcuts/)
- [Web Application Manifest: lang member](https://www.w3.org/TR/appmanifest/#lang-member)（w3.org）
- [Localization support for web app manifests](https://developer.chrome.com/blog/manifest-localization)（developer.chrome.com）
- [*_localized](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/*_localized)（developer.mozilla.org）