diff --git a/files/en-us/web/progressive_web_apps/how_to/localize_an_app_manifest/index.md b/files/en-us/web/progressive_web_apps/how_to/localize_an_app_manifest/index.md new file mode 100644 index 000000000000000..e4fbd9c4d7db2d3 --- /dev/null +++ b/files/en-us/web/progressive_web_apps/how_to/localize_an_app_manifest/index.md @@ -0,0 +1,283 @@ +--- +title: Localize an app manifest +slug: Web/Progressive_web_apps/How_to/Localize_an_app_manifest +page-type: how-to +sidebar: pwasidebar +--- + +[Progressive Web App (PWA)](/en-US/docs/Web/Progressive_web_apps) manifests can be localized using a combination of localizable members, which have the suffix [`_localized`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/*_localized), and 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. + +Manifest localization allows the browser to choose between different text strings (for app names and descriptions, for example) and icons when loading the app to best suit the user's language preferences. + +This guide shows how to localize a PWA manifest. + +## Example non-localised PWA + +The rest of this guide develops a multilingual PWA manifest using the following example as a starting point. + +```json +{ + "name": "The SuperSausage sausage app", + "short_name": "SuperSausage", + "description": "Find information on all your favorite sausages!", + "start_url": "./", + "display": "standalone", + "background_color": "#ffffff", + "theme_color": "#ab510d", + "icons": [ + { + "src": "./icons/saus-128.png", + "sizes": "128x128", + "type": "image/png" + }, + { + "src": "./icons/saus-256.png", + "sizes": "256x256", + "type": "image/png" + } + ] +} +``` + +## 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`). + +Set a suitable default language and direction like so: + +```json +"lang": "en-US", +"dir": "ltr" +``` + +## Choose the manifest members you want to localize + +The following members support localized variants: + +- [`name`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/name) +- [`short_name`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/short_name) +- [`description`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/description) +- [`icons`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/icons) +- [`shortcuts`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/shortcuts) + +Our sample manifest has all of these except for `shortcuts`; we'll show how to localize each one. + +## Choose the languages you want to support + +Generally you should support all of the languages relevant to your major target audience locales. + +For this example, we'll choose French (`fr`), German (`de`), Urdu (`ur`), and Japanese (`ja`). + +## Localizing the `name` member + +Localized versions of the `name` member are contained in the `name_localized` member. Each property inside `name_localized` has to have a key equal to one of the target language's {{glossary("BCP 47 language tag", "BCP 47 language tags")}}, and a value equal to an object or a string representing the localized text for that language. + +Let's see what this could look like for our example: + +```json +"name_localized": { + "fr": "L'application de saucisse SuperSausage", + "de": "Die SuperWurst-App", + "ur": { + "dir": "rtl", + "value": "سپر ساسیج ساسیج ایپ" + }, + "ja": "スーパーソーセージのソーセージアプリ" +} +``` + +In this case, we've used the string form for all the languages, except for Urdu, which uses the object form. We've done it this way because Urdu is an RTL language, and we need to specify a `dir` value of `rtl` for it so that browsers will display it correctly. + +## Localizing the other text-based members + +We can follow the same pattern as we did for the `name` member to localize the `short_name` and `description` members: + +```json +"short_name_localized": { + "fr": { + "lang": "en-US", + "value": "SuperSausage" + }, + "de": "SuperWurst", + "ur": "سپر ساسیج", + "ja": "スーパーソーセージ" +}, +"description_localized": { + "fr": "Trouvez des informations sur toutes vos saucisses préférées !", + "de": "Finden Sie Informationen zu all Ihren Lieblingswürstchen!", + "ur": "اپنی تمام پسندیدہ ساسیجز کے بارے میں معلومات حاصل کریں!", + "ja": "お気に入りのソーセージの情報を全部見つけましょう!" +}, +``` + +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). + +## Localizing the `icon` member + +Localized images are handled somewhat differently to localized text. The properties of each `*_localized` member (`icon_localized`, in this case) are equal to an array of objects containing the same properties as the non-localized original (`icon`); each one provides details for a localized image. + +Let's see what this looks like: + +```json +"icons_localized": { + "fr": [ + { + "src": "./icons/l10n/fr/saus-128.png", + "sizes": "128x128", + "type": "image/png" + }, + { + "src": "./icons/l10n/fr/saus-256.png", + "sizes": "256x256", + "type": "image/png" + } + ], + "de": [ + { + "src": "./icons/l10n/de/saus-128.png", + "sizes": "128x128", + "type": "image/png" + }, + { + "src": "./icons/l10n/de/saus-256.png", + "sizes": "256x256", + "type": "image/png" + } + ], + "ur": [ + { + "src": "./icons/l10n/ur/saus-128.png", + "sizes": "128x128", + "type": "image/png" + }, + { + "src": "./icons/l10n/ur/saus-256.png", + "sizes": "256x256", + "type": "image/png" + } + ], + "ja": [ + { + "src": "./icons/l10n/ja/saus-128.png", + "sizes": "128x128", + "type": "image/png" + }, + { + "src": "./icons/l10n/ja/saus-256.png", + "sizes": "256x256", + "type": "image/png" + } + ], +} +``` + +## Finished manifest + +Putting this all together, the complete manifest looks like this: + +```json +{ + "name": "The SuperSausage sausage app", + "short_name": "SuperSausage", + "description": "Find information on all your favorite sausages!", + "start_url": "./", + "display": "standalone", + "background_color": "#ffffff", + "theme_color": "#ab510d", + "icons": [ + { + "src": "./icons/saus-128.png", + "sizes": "128x128", + "type": "image/png" + }, + { + "src": "./icons/saus-256.png", + "sizes": "256x256", + "type": "image/png" + } + ], + "lang": "en-US", + "dir": "ltr", + "name_localized": { + "fr": "L'application de saucisse SuperSausage", + "de": "Die SuperWurst-App", + "ur": { + "dir": "rtl", + "value": "سپر ساسیج ساسیج ایپ" + }, + "ja": "スーパーソーセージのソーセージアプリ" + }, + "short_name_localized": { + "fr": { + "lang": "en-US", + "value": "SuperSausage" + }, + "de": "SuperWurst", + "ur": "سپر ساسیج", + "ja": "スーパーソーセージ" + }, + "description_localized": { + "fr": "Trouvez des informations sur toutes vos saucisses préférées !", + "de": "Finden Sie Informationen zu all Ihren Lieblingswürstchen!", + "ur": "اپنی تمام پسندیدہ ساسیجز کے بارے میں معلومات حاصل کریں!", + "ja": "お気に入りのソーセージの情報を全部見つけましょう!" + }, + "icons_localized": { + "fr": [ + { + "src": "./icons/l10n/fr/saus-128.png", + "sizes": "128x128", + "type": "image/png" + }, + { + "src": "./icons/l10n/fr/saus-256.png", + "sizes": "256x256", + "type": "image/png" + } + ], + "de": [ + { + "src": "./icons/l10n/de/saus-128.png", + "sizes": "128x128", + "type": "image/png" + }, + { + "src": "./icons/l10n/de/saus-256.png", + "sizes": "256x256", + "type": "image/png" + } + ], + "ur": [ + { + "src": "./icons/l10n/ur/saus-128.png", + "sizes": "128x128", + "type": "image/png" + }, + { + "src": "./icons/l10n/ur/saus-256.png", + "sizes": "256x256", + "type": "image/png" + } + ], + "ja": [ + { + "src": "./icons/l10n/ja/saus-128.png", + "sizes": "128x128", + "type": "image/png" + }, + { + "src": "./icons/l10n/ja/saus-256.png", + "sizes": "256x256", + "type": "image/png" + } + ] + } +} +``` + +## See also + +- [`dir`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/dir) manifest member +- [`lang`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/lang) manifest member +- [`*_localized`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/*_localized) manifest members +- [Localization support for web app manifests](https://developer.chrome.com/blog/manifest-localization) on developer.chrome.com (2026) diff --git a/files/en-us/web/progressive_web_apps/manifest/reference/_star__localized/index.md b/files/en-us/web/progressive_web_apps/manifest/reference/_star__localized/index.md new file mode 100644 index 000000000000000..c10b623ea675dbf --- /dev/null +++ b/files/en-us/web/progressive_web_apps/manifest/reference/_star__localized/index.md @@ -0,0 +1,170 @@ +--- +title: "*_localized" +slug: Web/Progressive_web_apps/Manifest/Reference/*_localized +page-type: web-manifest-member +browser-compat: manifests.webapp.localizable_members +sidebar: pwasidebar +--- + +The `_localized` suffix is added to manifest members to create localized variants of those members. The browser will use the variant that best suits the user based on their language preferences. + +## Syntax + +```json-nolint +/* Localized text value */ +"member_localized": { + "lang1": text_l10n, + "lang2": text_l10n, + "langN": text_l10n, +} + +/* Localized image resource */ +"member_localized": { + "lang1": image_l10n, + "lang2": image_l10n, + "langN": image_l10n, +} +``` + +### Values + +- `member_localized` + - : An object specifying localized member variants. For example, `name_localized` would specify localized variants for the [`name`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/name) field. + - `lang1` ... `lang2` ... `langN` + - : Each object contains one or more properties with keys equal to a {{glossary("BCP 47 language tag")}} representing a language to provide a variant for. The property values can be one of two types: + - `text_l10n` + - : An object or a string containing a text localization; see [text localization](#text_localization). + - `image_l10n` + - : An array of objects containing references to localized image resources; see [image localization](#image_localization). + +#### Text localization + +When the localized variant is providing a localization of a text value, the property values can be objects or strings. + +The object representation can have the following properties: + +- `value` + - : A string containing the localized text. +- `dir` {{optional_inline}} + - : A string representing the text direction of the localized text, used in cases where the required direction of a localized string differs from the default direction set in the manifest (see [`dir`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/dir)). Valid values of `dir` are: + - `auto` + - : The default. Specifies that the text direction is unknown. The browser will use heuristics to estimate the display direction of the text. + - `ltr` + - : Specifies a left-to-right text direction. + - `rtl` + - : Specifies a right-to-left text direction. +- `lang` {{optional_inline}} + - : A string containing a BCP 47 language tag, used in cases where localized text needs to be presented in a different language from the user's locale. + +In cases where the `dir` and `lang` properties do not need to be specified, the shorthand string representation can be used. This consists of a string containing the localized text `value`. + +#### Image localization + +When the localized variant is providing a localization of an image resource, the property values are arrays containing one or more objects representing image choices. + +The exact properties contained within each object will be the same as the properties contained within the objects included with the non-localized versions of the members: + +- For `icons_localized`, the objects can have the same properties as the [`icons`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/icons) member: `src`, `sizes`, `type`, and `purpose`. +- For `shortcuts_localized`, the objects can have the same properties as the [`shortcuts`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/shortcuts) member: `name`, `short_name`, `description`, `url`, and [`icons`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/icons). + +## Description + +The `_localized` suffix, along with 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, are used to create localized manifests. + +You can add the `_localized` suffix to a supporting manifest member to create localized variants of that member. The browser will use the variant that best suits the user based on their language preferences. Each property of a localized variant has a key equal to a BCP47 language tag representing the locale language, and a value that represents the localized variant. + +Members for which localized variants are supported: + +- [`name`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/name) +- [`short_name`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/short_name) +- [`description`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/description) +- [`icons`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/icons) +- [`shortcuts`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/shortcuts) + +### Localized text + +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. + +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. + +```json +{ + "lang": "en-US", + "dir": "ltr", + "name": "Color Picker", + "name_localized": { + "de": "Farbwähler", + "fr": { "value": "Sélecteur de Couleur", "lang": "fr-CA", "dir": "ltr" }, + "ar": { "value": "`منتقي` `الألوان`", "dir": "rtl" } + } +} +``` + +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 + +A localized icon set will look like this: + +```json +{ + "icons": [ + { + "src": "./icons/icon-128.png", + "sizes": "128x128", + "type": "image/png" + } + ], + "icons_localized": { + "de": [ + { + "src": "./icons/localized_icons/de/icon-128.png", + "sizes": "128x128", + "type": "image/png" + } + ], + "ar": [ + { + "src": "./icons/localized_icons/ar/icon-128.png", + "sizes": "128x128", + "type": "image/png" + } + ], + "fr": [ + { + "src": "./icons/localized_icons/fr/icon-128.png", + "sizes": "128x128", + "type": "image/png" + } + ] + } +} +``` + +If the user has specified a preference for German, Arabic, or French, an entry from the appropriate `icons_localized` member will be used. + +The `icons` member specifies the default icon that will be used if no language more suitable for the user's language preferences than the default `lang` is found in the `icons_localized` variants. + +## Examples + +For complete demos, check out; + +- The [PWA manifest localization demo](https://microsoftedge.github.io/Demos/pwa-manifest-localization/) app ([see source code](https://github.com/MicrosoftEdge/Demos/tree/main/pwa-manifest-localization/)). +- Our [Localize an app manifest](/en-US/docs/Web/Progressive_web_apps/How_to/Localize_an_app_manifest) How to guide. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [`dir`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/dir) manifest member +- [`lang`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/lang) manifest member +- [Localize an app manifest](/en-US/docs/Web/Progressive_web_apps/How_to/Localize_an_app_manifest) +- [Localization support for web app manifests](https://developer.chrome.com/blog/manifest-localization) on developer.chrome.com (2026) diff --git a/files/en-us/web/progressive_web_apps/manifest/reference/dir/index.md b/files/en-us/web/progressive_web_apps/manifest/reference/dir/index.md new file mode 100644 index 000000000000000..2aea7f7df484c22 --- /dev/null +++ b/files/en-us/web/progressive_web_apps/manifest/reference/dir/index.md @@ -0,0 +1,65 @@ +--- +title: dir +slug: Web/Progressive_web_apps/Manifest/Reference/dir +page-type: web-manifest-member +browser-compat: manifests.webapp.dir +sidebar: pwasidebar +--- + +The `dir` manifest member is used to specify a default language directionality for your web application, which will be used unless overriden by a different `dir` value found in a [`*_localized`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/*_localized) member. +If not specifies, the default direction is inferred from the default language, as specfiied using [`lang`]. + +## Syntax + +```json-nolint +"dir": "auto" +"dir": "ltr" +"dir": "rtl" +``` + +### Values + +A string representing the app's text direction. Valid values of `dir` are: + +- `auto` + - : The default. Specifies that the text direction is unknown. The browser will use heuristics to infer the display direction of the text. +- `ltr` + - : Specifies a left-to-right text direction. +- `rtl` + - : Specifies a right-to-left text direction. + +## Examples + +### Basic usage + +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. + +```json +{ + "lang": "en-US", + "dir": "ltr", + "name": "Color Picker", + "name_localized": { + "de": "Farbwähler", + "fr": { "value": "Sélecteur de Couleur", "lang": "fr-CA", "dir": "ltr" }, + "ar": { "value": "`منتقي` `الألوان`", "dir": "rtl" } + } +} +``` + +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. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [`lang`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/lang) manifest member +- [`*_localized`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/*_localized) manifest members diff --git a/files/en-us/web/progressive_web_apps/manifest/reference/lang/index.md b/files/en-us/web/progressive_web_apps/manifest/reference/lang/index.md new file mode 100644 index 000000000000000..8ba6a36fa9f0624 --- /dev/null +++ b/files/en-us/web/progressive_web_apps/manifest/reference/lang/index.md @@ -0,0 +1,58 @@ +--- +title: lang +slug: Web/Progressive_web_apps/Manifest/Reference/lang +page-type: web-manifest-member +browser-compat: manifests.webapp.lang +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. + +## Syntax + +```json-nolint +"lang": "en-US" +"lang": "ja" +"lang": "uk" +``` + +### Values + +a {{glossary("BCP 47 language tag")}} representing the app's default language. + +## Examples + +### Basic usage + +In this example, the app's default `lang` is `en-US` and default `dir` is `ltr`. +The default `name` is "Color picker", but we have also defined 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 their selected language. + +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. + +```json +{ + "lang": "en-US", + "dir": "ltr", + "name": "Color Picker", + "name_localized": { + "de": "Farbwähler", + "fr": { "value": "Sélecteur de Couleur", "lang": "fr-CA", "dir": "ltr" }, + "ar": { "value": "`منتقي` `الألوان`", "dir": "rtl" } + } +} +``` + +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. + +## Specifications + +{{Specifications}} + +## Browser compatibility + +{{Compat}} + +## See also + +- [`dir`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/dir) manifest member +- [`*_localized`](/en-US/docs/Web/Progressive_web_apps/Manifest/Reference/*_localized) manifest members diff --git a/files/sidebars/pwasidebar.yaml b/files/sidebars/pwasidebar.yaml index 57250d2070e76d5..87c03b35fad0bf2 100644 --- a/files/sidebars/pwasidebar.yaml +++ b/files/sidebars/pwasidebar.yaml @@ -39,6 +39,7 @@ sidebar: - /Web/Progressive_web_apps/How_to/Expose_common_actions_as_shortcuts - /Web/Progressive_web_apps/How_to/Share_data_between_apps - /Web/Progressive_web_apps/How_to/Associate_files_with_your_PWA + - /Web/Progressive_web_apps/How_to/Localize_an_app_manifest - type: section link: /Web/Progressive_web_apps/Reference - /Web/Progressive_web_apps/Manifest