# lang, dir, and *_localized manifest members

> lang and dir set the default language and text direction of a manifest; the *_localized members carry per-language name, short_name, description, and icons, shipped in Chrome and Edge 148.

A manifest has three localization tools. `lang` names the language of the manifest's text
members, `dir` names their writing direction, and the `*_localized` members (`name_localized`,
`short_name_localized`, `description_localized`, `icons_localized`) carry per-language variants
keyed by BCP 47 tag, with the plain member as the fallback. There is no single `translations`
member; localization is per field.

Chrome 148 and Edge 148 read the `*_localized` members for `name`, `short_name`,
`description`, `icons`, and the same four fields inside each `shortcuts` entry
(developer.chrome.com, manifest localization announcement). MDN records `dir` and `lang` as
not implemented by any browser as top-level members; Chromium reads the `lang` and `dir`
overrides inside a localized value. Firefox 157 and Safari 27 drop every `*_localized` member
and show the plain `name`.

## Member

- **`lang`**: string, a BCP 47 language tag such as `en-AU` or `zh-Hans-CN`, compared
  case-insensitively. Default: unset, the language is unknown. An ill-formed tag is dropped.
- **`dir`**: string, one of `ltr`, `rtl`, or `auto`. Default: `auto`, which asks the browser to
  estimate direction from the text. An unrecognized value resolves to `auto`.
- **`*_localized`**: object keyed by language tag. For text members each value is either a
  string or an object `{ "value": "...", "lang": "...", "dir": "..." }`; for `icons_localized`
  each value is a complete icon array in the shape of `icons`. Default: absent, the plain member
  is used for every language.
- **Example value**: `"name_localized": { "de": "Farbwähler", "en-GB": { "value": "Colour Picker" } }`.

Matching picks the entry that best fits the browser's language list and falls back to the plain
member when nothing matches; the specification leaves the exact tag-matching algorithm to the
browser. A localized icon array replaces `icons` wholesale for that language, it is not merged
with it, so every language entry needs its full set of sizes. `shortcuts` has no
`shortcuts_localized`; the four `*_localized` members nest inside each shortcut object instead.

A `*_localized` value that is not an object is dropped with the generic parser message
`property 'name_localized' ignored, type object expected.`, and the plain member keeps working.

:::observed
Chrome 155 on macOS 26 (English UI), DevTools > Application > Manifest: with `"name_localized":
"Farbwähler"` (a string where an object is required) the **Errors and warnings** section reads
`property 'name_localized' ignored, type object expected.` and **Identity > Name** still shows
the plain `name`. The same manifest in Firefox 157 produces no console output: Firefox reads
`name` and discards the unknown member.
:::

## Examples

The examples add localization in the order a team usually does: names first, then a brand
kept in one language, then icons.

### Localizing the name and description with a plain-member fallback

The plain `name` and `description` are the fallback for every language without an entry.
`lang` and `dir` describe those plain values, so a German-first app sets `lang` to `de` and
puts the English text under `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."
  }
}
```

A browser set to `en-US` gets `Color Picker` from the `en` entry; one set to `en-GB` gets the
more specific spelling; one set to Spanish falls back to the German plain value, which is the
cue to add an `es` entry.

### Keeping a brand name in English for a right-to-left locale

A value object carries its own `lang` and `dir` when they differ from what the key implies.
Here the Arabic entry keeps the Latin brand name and marks it as left-to-right English inside a
right-to-left manifest.

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

Without the per-value `dir`, a bidirectional renderer may place the Latin label incorrectly
beside Arabic text in the launcher; the override is the fix the spec provides for exactly this.

### Shipping localized icons and checking what the browser resolved

Icons with embedded text need a per-language array. The script then reads the manifest and
reports which entry the browser will pick for its own language, with a fallback to the plain
`icons` when no entry matches, which is also what a browser without `*_localized` support does.

```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 ?? [];               // no match or no support: plain icons
  return localized[tag] ?? localized[tag.split('-')[0]];
}
```

The function mirrors the fallback rule rather than the browser's exact matcher, so treat its
output as a preview for a settings page, not as the icon the OS is guaranteed to show.

## See also

- [name and short_name manifest members](/reference/manifest/name-short-name/)
- [description manifest member](/reference/manifest/description/)
- [icons manifest member](/reference/manifest/icons/)
- [shortcuts manifest member](/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)