mnfst 0.5.60 → 0.5.61
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/manifest.localization.js +60 -10
- package/package.json +1 -1
|
@@ -93,6 +93,21 @@ function initializeLocalizationPlugin() {
|
|
|
93
93
|
return document.head?.querySelector('meta[name="manifest:prerendered"][content="1"]') !== null;
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
// Returns the set of locales the prerender actually generated URL paths for.
|
|
97
|
+
// Read from `<meta name="manifest:prerender-locales" content="en,fr,...">`.
|
|
98
|
+
// When the target locale isn't in this set, MPA locale switching should NOT
|
|
99
|
+
// navigate (it would 404) — instead, fall back to the in-page store update
|
|
100
|
+
// so locale-aware data sources (e.g. examples on a localization docs page)
|
|
101
|
+
// can re-render without leaving the current page.
|
|
102
|
+
function getPrerenderLocales() {
|
|
103
|
+
const meta = document.head?.querySelector('meta[name="manifest:prerender-locales"]');
|
|
104
|
+
const content = meta?.getAttribute('content') || '';
|
|
105
|
+
return content
|
|
106
|
+
.split(',')
|
|
107
|
+
.map(s => s.trim())
|
|
108
|
+
.filter(Boolean);
|
|
109
|
+
}
|
|
110
|
+
|
|
96
111
|
function buildLocaleNavigationUrl(newLang, availableLocales) {
|
|
97
112
|
const currentUrl = new URL(window.location.href);
|
|
98
113
|
const pathParts = currentUrl.pathname.split('/').filter(Boolean);
|
|
@@ -359,14 +374,44 @@ function initializeLocalizationPlugin() {
|
|
|
359
374
|
|
|
360
375
|
|
|
361
376
|
try {
|
|
362
|
-
// In prerendered static output, locale switching
|
|
363
|
-
//
|
|
377
|
+
// In prerendered static output, locale switching normally navigates
|
|
378
|
+
// to the target locale's URL. But only do this when the target
|
|
379
|
+
// locale was ACTUALLY prerendered — otherwise navigation would 404.
|
|
380
|
+
//
|
|
381
|
+
// When the host site has a single locale (e.g. an English docs site
|
|
382
|
+
// with locale-aware example data on one page), `prerender-locales`
|
|
383
|
+
// contains only that locale. Switching to any other locale falls
|
|
384
|
+
// through to the in-page store update below — locale-aware data
|
|
385
|
+
// re-loads via the `localechange` event and the page reflects the
|
|
386
|
+
// new locale without navigating.
|
|
387
|
+
// Track whether this is a "scoped" change (in-page only on a
|
|
388
|
+
// prerendered single-locale site). Scoped changes must NOT persist
|
|
389
|
+
// to localStorage or update the URL — the locale is a transient
|
|
390
|
+
// example/demo state, not a site-wide preference. Persisting would
|
|
391
|
+
// leak the demo locale to subsequent page loads via localStorage,
|
|
392
|
+
// making `<html lang>` mismatch the actual baked content (English
|
|
393
|
+
// article body with `lang="fr"`) and muddying the SEO signal.
|
|
394
|
+
let isScopedDemoChange = false;
|
|
364
395
|
if (isPrerenderedStaticBuild()) {
|
|
365
|
-
const
|
|
366
|
-
|
|
367
|
-
|
|
396
|
+
const prerenderLocales = getPrerenderLocales();
|
|
397
|
+
// Multi-locale site: navigate to the target locale's URL.
|
|
398
|
+
// Single-locale site: there are no other locale URLs to navigate
|
|
399
|
+
// to (the renderer skips the redundant default-locale mirror),
|
|
400
|
+
// so ALL switches must be treated as in-page demos.
|
|
401
|
+
const isMultiLocaleSite = prerenderLocales.length > 1;
|
|
402
|
+
const targetIsPrerendered =
|
|
403
|
+
prerenderLocales.length === 0 ||
|
|
404
|
+
prerenderLocales.includes(newLang);
|
|
405
|
+
if (isMultiLocaleSite && targetIsPrerendered) {
|
|
406
|
+
const targetUrl = buildLocaleNavigationUrl(newLang, store.available || []);
|
|
407
|
+
if (targetUrl !== window.location.href) {
|
|
408
|
+
window.location.assign(targetUrl);
|
|
409
|
+
}
|
|
410
|
+
return true;
|
|
368
411
|
}
|
|
369
|
-
|
|
412
|
+
// In-page demo: locale-aware data re-renders without navigating.
|
|
413
|
+
// Mark as scoped so we skip URL/localStorage persistence below.
|
|
414
|
+
isScopedDemoChange = true;
|
|
370
415
|
}
|
|
371
416
|
|
|
372
417
|
// Update store
|
|
@@ -382,16 +427,21 @@ function initializeLocalizationPlugin() {
|
|
|
382
427
|
console.error('[Manifest Localization] DOM update error:', domError);
|
|
383
428
|
}
|
|
384
429
|
|
|
385
|
-
// Update localStorage safely
|
|
386
|
-
|
|
430
|
+
// Update localStorage safely — but skip for scoped demo changes
|
|
431
|
+
// so the next page load doesn't restore a non-prerendered locale.
|
|
432
|
+
if (!isScopedDemoChange) {
|
|
433
|
+
safeStorage.set('lang', newLang);
|
|
434
|
+
}
|
|
387
435
|
|
|
388
|
-
// Update URL based on current URL state and updateUrl parameter
|
|
436
|
+
// Update URL based on current URL state and updateUrl parameter.
|
|
437
|
+
// Skip entirely for scoped demo changes — adding/replacing a locale
|
|
438
|
+
// prefix would point at a URL that wasn't prerendered (404).
|
|
389
439
|
try {
|
|
390
440
|
const currentUrl = new URL(window.location.href);
|
|
391
441
|
const pathParts = currentUrl.pathname.split('/').filter(Boolean);
|
|
392
442
|
const hasLanguageInUrl = pathParts[0] && store.available.includes(pathParts[0]);
|
|
393
443
|
|
|
394
|
-
if (updateUrl || hasLanguageInUrl) {
|
|
444
|
+
if (!isScopedDemoChange && (updateUrl || hasLanguageInUrl)) {
|
|
395
445
|
// Update URL if:
|
|
396
446
|
// 1. updateUrl is explicitly true (router navigation, initialization)
|
|
397
447
|
// 2. OR there's already a language code in the URL (user expects URL to update)
|