-
Notifications
You must be signed in to change notification settings - Fork 204
Adding PWA manifest localization demo #123
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
captainbrosset
merged 5 commits into
MicrosoftEdge:main
from
kyerebo:manifest-localization
Mar 19, 2026
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
5c3ca03
Add PWA manifest localization demo
akyereboah dd86774
Delete .vscode directory
kyerebo e537415
Apply suggestions from code review
captainbrosset c254221
Update pwa-manifest-localization/README.md
captainbrosset 5d80bff
Update pwa-manifest-localization/README.md
captainbrosset File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| # Manifest Localization for Web Apps | ||
|
|
||
| ➡️ **[Open the demo](https://microsoftedge.github.io/Demos/pwa-manifest-localization/)** ⬅️ | ||
|
|
||
| This demo showcases the use of `_localized` suffixed web app manifest members, which allow Progressive Web Apps (PWAs) to provide localized app metadata (such as name, description, and icons) for different languages directly in the manifest file. | ||
|
|
||
| The demo app is localized in English, German, and Arabic. | ||
|
|
||
| ## How to use the demo app | ||
|
|
||
| 1. In Microsoft Edge, open the [Manifest Localization Test App](https://microsoftedge.github.io/Demos/pwa-manifest-localization/) in a new window or tab. | ||
|
|
||
| 2. In the address bar, click the **App available** button to install the PWA on your device. | ||
|
|
||
| If your browser is set to English, German, or Arabic, the installed PWA displays the name, short name, icon, description, and shortcuts that are defined in the web app manifest file for that language. | ||
|
|
||
| 3. In Microsoft Edge, go to `edge://settings/languages`. | ||
|
|
||
| 4. Under **Preferred languages**, click **...** next to either English, German, or Arabic, choosing the one which your browser isn't already using. | ||
|
|
||
| 5. Select **Display Microsoft Edge in this language**. | ||
|
|
||
| 6. Restart the PWA. | ||
|
|
||
| You are prompted to update the installed PWA to the new localized values. | ||
|
|
||
| ## Links | ||
|
|
||
| - [Specification](https://www.w3.org/TR/appmanifest/#x_localized-members) | ||
| - [Chrome Platform Status entry](https://chromestatus.com/feature/5090807862394880?gate=4864426712891392) | ||
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| <!doctype html> | ||
| <html lang="en"> | ||
| <head> | ||
| <meta charset="UTF-8"> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
| <meta name="description" content="A Progressive Web App for testing manifest localization capabilities"> | ||
| <meta name="theme-color" content="#2196f3"> | ||
| <title>Manifest Localization Test App</title> | ||
| <link rel="manifest" href="manifest.json"> | ||
| <link rel="icon" type="image/png" sizes="128x128" href="icons/icon-128.png"> | ||
| <link rel="stylesheet" href="style.css"> | ||
| </head> | ||
| <body> | ||
| <div class="container"> | ||
| <header> | ||
| <h1>Manifest Localization Test App</h1> | ||
| <p class="subtitle">Testing PWA manifest localization capabilities</p> | ||
| </header> | ||
|
|
||
| <div class="content"> | ||
| <div class="section"> | ||
| <div class="info-box"> | ||
| <p> | ||
| This PWA demonstrates manifest localization using the <code>name_localized</code>, | ||
| <code>short_name_localized</code>, <code>icons_localized</code>, | ||
| <code>description_localized</code>, and <code>shortcuts_localized</code> fields. | ||
| The service worker caches the manifest for offline access. | ||
| </p> | ||
| </div> | ||
| <div id="sw-status" class="status">Checking Service Worker...</div> | ||
| </div> | ||
|
|
||
| <div class="section"> | ||
| <h2>Localized App Names and Icons</h2> | ||
| <table> | ||
| <thead> | ||
| <tr> | ||
| <th>Language</th> | ||
| <th>App Name</th> | ||
| <th>Short Name</th> | ||
| <th>Icon</th> | ||
| </tr> | ||
| </thead> | ||
| <tbody> | ||
| <tr> | ||
| <td><span class="language-code">Default (en)</span></td> | ||
| <td>Manifest Localization Test App</td> | ||
| <td>Localization Test</td> | ||
| <td> | ||
| <img src="./icons/icon-128.png" alt="Default icon" width="48" height="48"> | ||
| </td> | ||
| </tr> | ||
| <tr> | ||
| <td><span class="language-code">German (de)</span></td> | ||
| <td>Manifest-Lokalisierungstest-App</td> | ||
| <td>Lokalisierungstest</td> | ||
| <td> | ||
| <img src="./icons/localized_icons/de/icon-128.png" alt="German icon" width="48" height="48"> | ||
| </td> | ||
| </tr> | ||
| <tr> | ||
| <td><span class="language-code">Arabic (ar)</span></td> | ||
| <td>تطبيق اختبار توطين البيان</td> | ||
| <td>اختبار التوطين</td> | ||
| <td> | ||
| <img src="./icons/localized_icons/ar/icon-128.png" alt="Arabic icon" width="48" height="48"> | ||
| </td> | ||
| </tr> | ||
| </tbody> | ||
| </table> | ||
| </div> | ||
|
|
||
|
|
||
| </div> | ||
| </div> | ||
|
|
||
| <script src="main.js"></script> | ||
| </body> | ||
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| // Register service worker | ||
| if ('serviceWorker' in navigator) { | ||
| window.addEventListener('load', () => { | ||
| navigator.serviceWorker.register('service-worker.js') | ||
| .then((registration) => { | ||
| console.log('Service Worker registered successfully:', registration.scope); | ||
| updateStatus('Service Worker Active ✓', true); | ||
| }) | ||
| .catch((error) => { | ||
| console.error('Service Worker registration failed:', error); | ||
| updateStatus('Service Worker Failed ✗', false); | ||
| }); | ||
| }); | ||
|
|
||
| // Update status when service worker state changes | ||
| navigator.serviceWorker.ready.then(() => { | ||
| updateStatus('Service Worker Active ✓', true); | ||
| }); | ||
| } else { | ||
| updateStatus('Service Worker Not Supported ✗', false); | ||
| } | ||
|
|
||
| function updateStatus(message, isActive) { | ||
| const statusEl = document.getElementById('sw-status'); | ||
| statusEl.textContent = message; | ||
| statusEl.className = isActive ? 'status' : 'status offline'; | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,116 @@ | ||
| { | ||
| "name": "Manifest Localization Test App", | ||
| "short_name": "Localization Test", | ||
| "description": "A Progressive Web App for testing manifest localization capabilities", | ||
| "start_url": "./", | ||
| "display": "standalone", | ||
| "background_color": "#ffffff", | ||
| "theme_color": "#2196f3", | ||
| "icons": [ | ||
| { | ||
| "src": "./icons/icon-128.png", | ||
| "sizes": "128x128", | ||
| "type": "image/png" | ||
| }, | ||
| { | ||
| "src": "./icons/icon-192.png", | ||
| "sizes": "192x192", | ||
| "type": "image/png" | ||
| }, | ||
| { | ||
| "src": "./icons/icon-256.png", | ||
| "sizes": "256x256", | ||
| "type": "image/png" | ||
| }, | ||
| { | ||
| "src": "./icons/icon-512.png", | ||
| "sizes": "512x512", | ||
| "type": "image/png" | ||
| } | ||
| ], | ||
| "shortcuts": [ | ||
| { | ||
| "name": "Open Home", | ||
| "short_name": "Home", | ||
| "description": "Navigate to home page", | ||
| "url": "./", | ||
| "icons": [ | ||
| { | ||
| "src": "./icons/icon-128.png", | ||
| "sizes": "128x128", | ||
| "type": "image/png" | ||
| } | ||
| ] | ||
| } | ||
| ], | ||
| "name_localized": { | ||
| "de": "Manifest-Lokalisierungstest-App", | ||
| "ar": "تطبيق اختبار توطين البيان" | ||
| }, | ||
| "short_name_localized": { | ||
| "de": "Lokalisierungstest", | ||
| "ar": "اختبار التوطين" | ||
| }, | ||
| "description_localized": { | ||
| "de": "Eine Progressive Web App zum Testen der Manifest-Lokalisierungsfunktionen", | ||
| "ar": "تطبيق ويب تقدمي لاختبار قدرات توطين البيان" | ||
| }, | ||
| "icons_localized": { | ||
| "de": [ | ||
| { | ||
| "src": "./icons/localized_icons/de/icon-128.png", | ||
| "sizes": "128x128", | ||
| "type": "image/png" | ||
| }, | ||
| { | ||
| "src": "./icons/localized_icons/de/icon-256.png", | ||
| "sizes": "256x256", | ||
| "type": "image/png" | ||
| } | ||
| ], | ||
| "ar": [ | ||
| { | ||
| "src": "./icons/localized_icons/ar/icon-128.png", | ||
| "sizes": "128x128", | ||
| "type": "image/png" | ||
| }, | ||
| { | ||
| "src": "./icons/localized_icons/ar/icon-256.png", | ||
| "sizes": "256x256", | ||
| "type": "image/png" | ||
| } | ||
| ] | ||
| }, | ||
| "shortcuts_localized": { | ||
| "de": [ | ||
| { | ||
| "name": "Startseite öffnen", | ||
| "short_name": "Startseite", | ||
| "description": "Zur Startseite navigieren", | ||
| "url": "./", | ||
| "icons": [ | ||
| { | ||
| "src": "./icons/localized_icons/de/icon-128.png", | ||
| "sizes": "128x128", | ||
| "type": "image/png" | ||
| } | ||
| ] | ||
| } | ||
| ], | ||
| "ar": [ | ||
| { | ||
| "name": "فتح الصفحة الرئيسية", | ||
| "short_name": "الرئيسية", | ||
| "description": "الانتقال إلى الصفحة الرئيسية", | ||
| "url": "./", | ||
| "icons": [ | ||
| { | ||
| "src": "./icons/localized_icons/ar/icon-128.png", | ||
| "sizes": "128x128", | ||
| "type": "image/png" | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| const CACHE_NAME = 'manifest-localization-test-v2'; | ||
| const MANIFEST_URL = './manifest.json'; | ||
|
|
||
| // Files to cache | ||
| const urlsToCache = [ | ||
| './', | ||
| './index.html', | ||
| './manifest.json', | ||
| './style.css', | ||
| './main.js', | ||
| './icons/icon-128.png', | ||
| './icons/icon-192.png', | ||
| './icons/icon-256.png', | ||
| './icons/icon-512.png', | ||
| './icons/localized_icons/ar/icon-128.png', | ||
| './icons/localized_icons/ar/icon-256.png', | ||
| './icons/localized_icons/de/icon-128.png', | ||
| './icons/localized_icons/de/icon-256.png' | ||
| ]; | ||
|
|
||
| // Install event - cache files | ||
| self.addEventListener('install', (event) => { | ||
| console.log('Service Worker: Installing...'); | ||
| event.waitUntil( | ||
| caches.open(CACHE_NAME) | ||
| .then((cache) => { | ||
| console.log('Service Worker: Caching files'); | ||
| return cache.addAll(urlsToCache); | ||
| }) | ||
| .then(() => self.skipWaiting()) | ||
| ); | ||
| }); | ||
|
|
||
| // Activate event - clean up old caches | ||
| self.addEventListener('activate', (event) => { | ||
| console.log('Service Worker: Activating...'); | ||
| event.waitUntil( | ||
| caches.keys().then((cacheNames) => { | ||
| return Promise.all( | ||
| cacheNames.map((cache) => { | ||
| if (cache !== CACHE_NAME) { | ||
| console.log('Service Worker: Clearing old cache'); | ||
| return caches.delete(cache); | ||
| } | ||
| }) | ||
| ); | ||
| }).then(() => self.clients.claim()) | ||
| ); | ||
| }); | ||
|
|
||
| // Fetch event - serve from cache | ||
| self.addEventListener('fetch', (event) => { | ||
| const url = new URL(event.request.url); | ||
|
|
||
| // Special handling for manifest.json | ||
| if (url.pathname.endsWith('/manifest.json')) { | ||
| event.respondWith( | ||
| caches.match(event.request) | ||
| .then((cachedResponse) => { | ||
| if (cachedResponse) { | ||
| console.log('Service Worker: Serving cached manifest'); | ||
| return cachedResponse; | ||
| } | ||
|
|
||
| // If not in cache, fetch and cache it | ||
| return fetch(event.request) | ||
| .then((response) => { | ||
| const responseClone = response.clone(); | ||
| caches.open(CACHE_NAME) | ||
| .then((cache) => { | ||
| cache.put(event.request, responseClone); | ||
| }); | ||
| return response; | ||
| }); | ||
| }) | ||
| ); | ||
| return; | ||
| } | ||
|
|
||
| // Default fetch strategy - cache first, falling back to network | ||
| event.respondWith( | ||
| caches.match(event.request) | ||
| .then((response) => { | ||
| return response || fetch(event.request); | ||
| }) | ||
| ); | ||
| }); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.