Skip to content

Technical review: Document web app manifest localization#44609

Open
chrisdavidmills wants to merge 8 commits into
mdn:mainfrom
chrisdavidmills:manifest-localization
Open

Technical review: Document web app manifest localization#44609
chrisdavidmills wants to merge 8 commits into
mdn:mainfrom
chrisdavidmills:manifest-localization

Conversation

@chrisdavidmills

Copy link
Copy Markdown
Contributor

Description

Chrome and Edge 148 desktop have added support for *_localized members, aka localizable web app manifests. See https://chromestatus.com/feature/5090807862394880.

This PR adds reference documentation for *_localized members and the dir and lang members, as well as a how-to guide covering how to localize a web app manifest.

Motivation

Additional details

Related issues and pull requests

@chrisdavidmills chrisdavidmills requested review from a team as code owners June 30, 2026 15:58
@chrisdavidmills chrisdavidmills requested review from dipikabh and hamishwillee and removed request for a team June 30, 2026 15:58
@github-actions github-actions Bot added Content:PWA Progressive Web Apps content size/l [PR only] 501-1000 LoC changed labels Jun 30, 2026
@github-actions

github-actions Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

@chrisdavidmills chrisdavidmills changed the title Document web app manifest localization Technical review: Document web app manifest localization Jun 30, 2026
Comment thread files/en-us/web/progressive_web_apps/manifest/reference/lang/index.md Outdated

in this example, the app's default `lang` is `en-US`, and its default `dir` is `ltr`. Its default `name` is "Color picker", but we've also specified localized variants in the `name_localized` member. Users that have their primary language preference set to German (`de`), French (`fr`), or Arabic (`ar`) will see the app's name displayed in a more suitable language for them.

The French variant is specified as French Canadian (`fr-CA`) in its `lang` property, with a direction (`dir`) of `ltr`, while the Arabic variant has its `dir` specified as `rtl`. The German variant doesn't need its `lang` or `dir` specified, so its value is a string containing the localized text.

@hamishwillee hamishwillee Jul 3, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't quite work because the French Canadian version doesn't need its direction set either.

"name": "Color Picker",
"name_localized": {
"de": "Farbwähler",
"fr": { "value": "Sélecteur de Couleur", "lang": "fr-CA", "dir": "ltr" },

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does this work - i.e this is fr, but you also have a lang that is "fr-CA". However I know lang sets the default language.

My guess is that this should omit lang and fix up the key.

    "fr-CA": { "value": "Sélecteur de Couleur", "dir": "ltr" },

Further, in the intro it says "will see the app's name displayed in a more suitable language for them."

I would like to understand the fallback here. If my language is set to fr, will it choose "fr-CA" or will it choose English ? Can I declare both "fr" and "fr-CA", and so on. The example could show a case or two.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread files/en-us/web/progressive_web_apps/manifest/reference/dir/index.md Outdated
---

The `lang` manifest member is used to specify a default language for your web application, which will be used unless overriden by a different `lang` value found in a [`*_localized`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/*_localized) member.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a default lang assumed?

Comment thread files/en-us/web/progressive_web_apps/manifest/reference/dir/index.md Outdated

in this example, the app's default `lang` is `en-US`, and its default `dir` is `ltr`. Its default `name` is "Color picker", but we've also specified localized variants in the `name_localized` member. Users that have their primary language preference set to German (`de`), French (`fr`), or Arabic (`ar`) will see the app's name displayed in a more suitable language for them.

The French variant is specified as French Canadian (`fr-CA`) in its `lang` property, with a direction (`dir`) of `ltr`, while the Arabic variant has its `dir` specified as `rtl`. The German variant doesn't need its `lang` or `dir` specified, so its value is a string containing the localized text.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comments as for the lang case.

Note also that this is a dir topic. I'd show a screen shot or explicitly state at least somewhere that the text will be drawn LTR and show it.

page-type: how-to
sidebar: pwasidebar
---

@hamishwillee hamishwillee Jul 3, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do I localise the rest of the app? We should at least mention that (or if it can't be done, state that too). I assume perhaps we can specify a key for the default language entry point?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Localizing the rest of the app is a huge topic and out of scope for this article. How you would go about localizing it depends on what kind of app it is, what stack you've used, etc.

https://github.com/oh-jon-paul/awesome-i18n gives you an idea of what's available.

Comment thread files/en-us/web/progressive_web_apps/how_to/localize_an_app_manifest/index.md Outdated
Comment thread files/en-us/web/progressive_web_apps/how_to/localize_an_app_manifest/index.md Outdated

## Set a default language and direction

The [`lang`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/lang) and [`dir`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/dir) members define a default language and language direction for the app. These will be assumed by the browser if no language and direction more suitable for the user's preferences are found in the [`*_localized`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/*_localized) variants. In such cases, the non-prefixed members are used (for example, `name`).

@hamishwillee hamishwillee Jul 3, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. What if I don't set a default language or dir, what is used?

  2. While I understand exactly what you mean, this doesn't feel quite right

    These will be assumed by the browser if no language and direction more suitable for the user's preferences are found in the *_localized variants.

    It's because the languages will be used but it isn't lang and dir that will be used. What will be used is the other non-localized members. You clarify this in the next sentence, but "These" still grates.

Comment thread files/en-us/web/progressive_web_apps/how_to/localize_an_app_manifest/index.md Outdated
sidebar: pwasidebar
---

The `lang` manifest member is used to specify a default language for your web application, which will be used unless overriden by a different `lang` value found in a [`*_localized`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/*_localized) member.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm nearing the end of my review, and I realize that this first doc that I read in the review is confusing:

overriden by a different lang value found in a *_localized member.

If it specifies the default language for my web application, what sense does it make to override?

},
```

The French (`fr`) `short_name` translation shows typical usage of the object value form being used to specify a `lang` property. In this case, our French audience knows our app by its English brand name — "SuperSausage" — and we want to specify that this should be handled as English rather than French (for example, for the purposes of pronounciation).

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See https://github.com/mdn/content/pull/44609/changes#r3517481036 - lang in a translation needs additional explanation there. I think I get it now, finally on this the second last doc - this allows you to specify that the value from some other language key should be used for a translation, instead of providing your own, or using the default?

Typo too

Suggested change
The French (`fr`) `short_name` translation shows typical usage of the object value form being used to specify a `lang` property. In this case, our French audience knows our app by its English brand name — "SuperSausage" — and we want to specify that this should be handled as English rather than French (for example, for the purposes of pronounciation).
The French (`fr`) `short_name` translation shows typical usage of the object value form being used to specify a `lang` property. In this case, our French audience knows our app by its English brand name — "SuperSausage" — and we want to specify that this should be handled as English rather than French (for example, for the purposes of pronunciation).

Comment thread files/en-us/web/progressive_web_apps/how_to/localize_an_app_manifest/index.md Outdated

## Finished manifest

Putting this all together, the complete manifest looks like this:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you need your shortcuts - I want to know how to select my language version.


Localized text field properties have values equal to objects or strings.

in this example, the app's default `en-US` language `name` is "Color picker", but we've also specified localized variants in the `name_localized` member. Users that have their primary language preference set to German (`de`), French (`fr`), or Arabic (`ar`) will see the app's name displayed in a more suitable language for them.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
in this example, the app's default `en-US` language `name` is "Color picker", but we've also specified localized variants in the `name_localized` member. Users that have their primary language preference set to German (`de`), French (`fr`), or Arabic (`ar`) will see the app's name displayed in a more suitable language for them.
In this example, the app's default `en-US` language `name` is "Color picker", but we've also specified localized variants in the `name_localized` member. Users that have their primary language preference set to German (`de`), French (`fr`), or Arabic (`ar`) will see the app's name displayed in a more suitable language for them.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But also see my other comment on lang - this could be better worded.


in this example, the app's default `en-US` language `name` is "Color picker", but we've also specified localized variants in the `name_localized` member. Users that have their primary language preference set to German (`de`), French (`fr`), or Arabic (`ar`) will see the app's name displayed in a more suitable language for them.

The French variant is specified as French Canadian (`fr-CA`) in its `lang` property, with a direction (`dir`) of `ltr`, while the Arabic variant has its `dir` specified as `rtl`. The German variant doesn't need its `lang` or `dir` specified, so its value is a string containing the localized text.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It isn't clear why the French version needs a lang and dir and the german version does not - same thing as https://github.com/mdn/content/pull/44609/changes#r3517444725

Somewhere else, perhaps in the how to, you indicate that lange in a localized member takes a language from somewhere else. So here you're saying that for French ou take your language from "fr-CA". But then there are two more questions:

  • If you are taking it from fr-CA, where is your fr-CA definition?
  • If you are taking it from fr-CA, why do you have a value?

I suspect the answer might be "take it from fr-CA if defined and otherwise fall back to the specified value. But that feels like poor design to me.


The `lang` and `dir` members define a default language and language direction that will be assumed by the browser if no language more suitable for the user's preferences is found in the `name_localized` variants. In such cases, the `name` member is used.

### Localized images

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it icons or image or both? If it can only be icons we should say that. If icons and other images are different we should say that. We should also note "somewhere" whether the localised set can have diferrent sets of icons or must match the same sizes

chrisdavidmills and others added 7 commits July 3, 2026 08:59
…ndex.md

Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
…dex.md

Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
…dex.md

Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
…nifest/index.md

Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
…nifest/index.md

Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
…nifest/index.md

Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
…nifest/index.md

Co-authored-by: Hamish Willee <hamishwillee@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Content:PWA Progressive Web Apps content size/l [PR only] 501-1000 LoC changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants