nuxt-i18n-micro 1.85.1 → 1.87.0
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/dist/client/200.html +2 -2
- package/dist/client/404.html +2 -2
- package/dist/client/_nuxt/builds/latest.json +1 -1
- package/dist/client/_nuxt/builds/meta/8378fa7a-5fb5-44d9-986d-f34c5db00a22.json +1 -0
- package/dist/client/index.html +2 -2
- package/dist/module.json +1 -1
- package/dist/module.mjs +12 -1
- package/dist/runtime/composables/useLocaleHead.js +25 -9
- package/dist/runtime/plugins/03.define.js +17 -61
- package/dist/runtime/plugins/06.redirect.d.ts +2 -0
- package/dist/runtime/plugins/06.redirect.js +38 -0
- package/dist/runtime/server/routes/get.js +1 -1
- package/package.json +3 -2
- package/dist/client/_nuxt/builds/meta/73fe5312-b8b8-43c9-8321-d410f5f66e5c.json +0 -1
package/dist/client/200.html
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/BBbCCCx2.js">
|
|
9
9
|
<link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-500.BRj5A2lo.css">
|
|
10
10
|
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/CfVvufsh.js">
|
|
11
|
-
<script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/MjlAM4Ld.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},
|
|
12
|
-
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"
|
|
11
|
+
<script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/MjlAM4Ld.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1746387320983,false]</script>
|
|
12
|
+
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"8378fa7a-5fb5-44d9-986d-f34c5db00a22",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
|
package/dist/client/404.html
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/BBbCCCx2.js">
|
|
9
9
|
<link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-500.BRj5A2lo.css">
|
|
10
10
|
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/CfVvufsh.js">
|
|
11
|
-
<script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/MjlAM4Ld.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},
|
|
12
|
-
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"
|
|
11
|
+
<script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/MjlAM4Ld.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1746387320984,false]</script>
|
|
12
|
+
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"8378fa7a-5fb5-44d9-986d-f34c5db00a22",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"id":"
|
|
1
|
+
{"id":"8378fa7a-5fb5-44d9-986d-f34c5db00a22","timestamp":1746387315515}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"id":"8378fa7a-5fb5-44d9-986d-f34c5db00a22","timestamp":1746387315515,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
|
package/dist/client/index.html
CHANGED
|
@@ -8,5 +8,5 @@
|
|
|
8
8
|
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/BBbCCCx2.js">
|
|
9
9
|
<link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-500.BRj5A2lo.css">
|
|
10
10
|
<link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/CfVvufsh.js">
|
|
11
|
-
<script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/MjlAM4Ld.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},
|
|
12
|
-
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"
|
|
11
|
+
<script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/MjlAM4Ld.js" crossorigin></script></head><body><div id="__nuxt"></div><div id="teleports"></div><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1746387320984,false]</script>
|
|
12
|
+
<script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"8378fa7a-5fb5-44d9-986d-f34c5db00a22",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
|
package/dist/module.json
CHANGED
package/dist/module.mjs
CHANGED
|
@@ -493,6 +493,7 @@ const module = defineNuxtModule({
|
|
|
493
493
|
meta: true,
|
|
494
494
|
debug: false,
|
|
495
495
|
define: true,
|
|
496
|
+
redirects: true,
|
|
496
497
|
plugin: true,
|
|
497
498
|
hooks: true,
|
|
498
499
|
types: true,
|
|
@@ -511,6 +512,7 @@ const module = defineNuxtModule({
|
|
|
511
512
|
apiBaseUrl: "_locales",
|
|
512
513
|
routesLocaleLinks: {},
|
|
513
514
|
globalLocaleRoutes: {},
|
|
515
|
+
canonicalQueryWhitelist: ["page", "sort", "filter", "search", "q", "query", "tag"],
|
|
514
516
|
plural: (key, count, params, _locale, getTranslation) => {
|
|
515
517
|
const translation = getTranslation(key, params);
|
|
516
518
|
if (!translation) {
|
|
@@ -560,7 +562,8 @@ const module = defineNuxtModule({
|
|
|
560
562
|
hashMode: nuxt.options?.router?.options?.hashMode ?? false,
|
|
561
563
|
apiBaseUrl,
|
|
562
564
|
isSSG,
|
|
563
|
-
disablePageLocales: options.disablePageLocales ?? false
|
|
565
|
+
disablePageLocales: options.disablePageLocales ?? false,
|
|
566
|
+
canonicalQueryWhitelist: options.canonicalQueryWhitelist ?? []
|
|
564
567
|
};
|
|
565
568
|
if (typeof options.customRegexMatcher !== "undefined") {
|
|
566
569
|
const localeCodes = localeManager.locales.map((l) => l.code);
|
|
@@ -619,6 +622,14 @@ const module = defineNuxtModule({
|
|
|
619
622
|
order: 4
|
|
620
623
|
});
|
|
621
624
|
}
|
|
625
|
+
if (options.redirects) {
|
|
626
|
+
addPlugin({
|
|
627
|
+
src: resolver.resolve("./runtime/plugins/06.redirect"),
|
|
628
|
+
name: "i18n-plugin-redirect",
|
|
629
|
+
mode: "all",
|
|
630
|
+
order: 6
|
|
631
|
+
});
|
|
632
|
+
}
|
|
622
633
|
addServerHandler({
|
|
623
634
|
route: `/${apiBaseUrl}/:page/:locale/data.json`,
|
|
624
635
|
handler: resolver.resolve("./runtime/server/routes/get")
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { joinURL } from "ufo";
|
|
1
|
+
import { joinURL, parseURL, withQuery } from "ufo";
|
|
2
2
|
import { isPrefixExceptDefaultStrategy, isNoPrefixStrategy } from "nuxt-i18n-micro-core";
|
|
3
3
|
import { unref, useRoute, useRuntimeConfig, watch, onUnmounted, ref, useNuxtApp } from "#imports";
|
|
4
4
|
export const useLocaleHead = ({ addDirAttribute = true, identifierAttribute = "id", addSeoAttributes = true, baseUrl = "/" } = {}) => {
|
|
@@ -7,28 +7,43 @@ export const useLocaleHead = ({ addDirAttribute = true, identifierAttribute = "i
|
|
|
7
7
|
link: [],
|
|
8
8
|
meta: []
|
|
9
9
|
});
|
|
10
|
+
function filterQuery(fullPath, whitelist) {
|
|
11
|
+
const { pathname, search } = parseURL(fullPath);
|
|
12
|
+
const params = new URLSearchParams(search);
|
|
13
|
+
const filtered = {};
|
|
14
|
+
for (const key of whitelist) {
|
|
15
|
+
if (params.has(key)) {
|
|
16
|
+
filtered[key] = params.get(key);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return withQuery(pathname, filtered);
|
|
20
|
+
}
|
|
10
21
|
function updateMeta() {
|
|
11
|
-
const { defaultLocale, strategy } = useRuntimeConfig().public.i18nConfig;
|
|
22
|
+
const { defaultLocale, strategy, canonicalQueryWhitelist } = useRuntimeConfig().public.i18nConfig;
|
|
12
23
|
const { $getLocales, $getLocale } = useNuxtApp();
|
|
13
24
|
const route = useRoute();
|
|
14
25
|
const locale = unref($getLocale());
|
|
15
26
|
const locales = unref($getLocales());
|
|
16
27
|
const routeName = (route.name ?? "").toString();
|
|
17
28
|
const currentLocale = unref($getLocales().find((loc) => loc.code === locale));
|
|
18
|
-
if (!currentLocale)
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
29
|
+
if (!currentLocale) return;
|
|
21
30
|
const currentIso = currentLocale.iso || locale;
|
|
22
31
|
const currentDir = currentLocale.dir || "auto";
|
|
23
32
|
let fullPath = unref(route.fullPath);
|
|
24
|
-
let ogUrl = joinURL(unref(baseUrl), fullPath);
|
|
25
33
|
if (!fullPath.startsWith("/")) {
|
|
26
34
|
fullPath = `/${fullPath}`;
|
|
27
35
|
}
|
|
28
36
|
const matchedLocale = locales.find((locale2) => fullPath.startsWith(`/${locale2.code}`));
|
|
37
|
+
let localizedPath = fullPath;
|
|
38
|
+
let ogUrl;
|
|
39
|
+
let canonicalPath;
|
|
29
40
|
if (routeName.startsWith("localized-") && matchedLocale) {
|
|
30
|
-
|
|
31
|
-
|
|
41
|
+
localizedPath = fullPath.slice(matchedLocale.code.length + 1);
|
|
42
|
+
canonicalPath = filterQuery(localizedPath, canonicalQueryWhitelist ?? []);
|
|
43
|
+
ogUrl = joinURL(unref(baseUrl), locale, canonicalPath);
|
|
44
|
+
} else {
|
|
45
|
+
canonicalPath = filterQuery(fullPath, canonicalQueryWhitelist ?? []);
|
|
46
|
+
ogUrl = joinURL(unref(baseUrl), canonicalPath);
|
|
32
47
|
}
|
|
33
48
|
metaObject.value = {
|
|
34
49
|
htmlAttrs: {
|
|
@@ -61,7 +76,8 @@ export const useLocaleHead = ({ addDirAttribute = true, identifierAttribute = "i
|
|
|
61
76
|
href: ogUrl
|
|
62
77
|
};
|
|
63
78
|
const alternateLinks = isNoPrefixStrategy(strategy) ? [] : alternateLocales.flatMap((loc) => {
|
|
64
|
-
const
|
|
79
|
+
const localizedPath2 = defaultLocale === loc.code && isPrefixExceptDefaultStrategy(strategy) ? canonicalPath : joinURL(loc.code, canonicalPath);
|
|
80
|
+
const href = joinURL(unref(baseUrl), localizedPath2);
|
|
65
81
|
const links = [{
|
|
66
82
|
[identifierAttribute]: `i18n-alternate-${loc.code}`,
|
|
67
83
|
rel: "alternate",
|
|
@@ -1,68 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
return locales.reduce((acc, locale) => {
|
|
11
|
-
acc[locale] = {};
|
|
12
|
-
return acc;
|
|
13
|
-
}, {});
|
|
14
|
-
} else if (typeof locales === "object" && locales !== null) {
|
|
15
|
-
return locales;
|
|
16
|
-
}
|
|
17
|
-
return {};
|
|
18
|
-
};
|
|
19
|
-
const handleRedirect = async (to) => {
|
|
20
|
-
const currentLocale = nuxtApp.$getLocale().toString();
|
|
21
|
-
const { name } = to;
|
|
22
|
-
let defaultRouteName = name?.toString().replace("localized-", "").replace(new RegExp(`-${currentLocale}$`), "");
|
|
23
|
-
if (!to.params.locale) {
|
|
24
|
-
if (router.hasRoute(`localized-${to.name?.toString()}-${currentLocale}`)) {
|
|
25
|
-
defaultRouteName = `localized-${to.name?.toString()}-${currentLocale}`;
|
|
26
|
-
} else {
|
|
27
|
-
defaultRouteName = `localized-${to.name?.toString()}`;
|
|
28
|
-
}
|
|
29
|
-
if (!router.hasRoute(defaultRouteName)) {
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
const newParams = { ...to.params };
|
|
33
|
-
if (!isNoPrefixStrategy(i18nConfig.strategy)) {
|
|
34
|
-
newParams.locale = i18nConfig.defaultLocale;
|
|
35
|
-
}
|
|
36
|
-
return navigateTo({ name: defaultRouteName, params: newParams }, { redirectCode: 301, external: true });
|
|
37
|
-
}
|
|
38
|
-
};
|
|
39
|
-
if (import.meta.server) {
|
|
40
|
-
if (isPrefixStrategy(i18nConfig.strategy) || isNoPrefixStrategy(i18nConfig.strategy)) {
|
|
41
|
-
await handleRedirect(route);
|
|
42
|
-
}
|
|
1
|
+
import { defineNuxtPlugin, useNuxtApp, computed, watch, onUnmounted, unref } from "#imports";
|
|
2
|
+
const normalizeLocales = (locales) => {
|
|
3
|
+
if (Array.isArray(locales)) {
|
|
4
|
+
return locales.reduce((acc, locale) => {
|
|
5
|
+
acc[locale] = {};
|
|
6
|
+
return acc;
|
|
7
|
+
}, {});
|
|
8
|
+
} else if (typeof locales === "object" && locales !== null) {
|
|
9
|
+
return locales;
|
|
43
10
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
if (next) {
|
|
49
|
-
next();
|
|
50
|
-
}
|
|
51
|
-
});
|
|
11
|
+
return {};
|
|
12
|
+
};
|
|
13
|
+
export default defineNuxtPlugin(() => {
|
|
52
14
|
const defineI18nRoute = async (routeDefinition) => {
|
|
53
|
-
const { $getLocale } = useNuxtApp();
|
|
15
|
+
const { $getLocale, $mergeGlobalTranslations } = useNuxtApp();
|
|
54
16
|
let currentLocale = computed(() => $getLocale());
|
|
55
17
|
const normalizedLocales = normalizeLocales(routeDefinition.locales);
|
|
56
18
|
const updateTranslations = () => {
|
|
57
|
-
const
|
|
58
|
-
if (
|
|
59
|
-
|
|
60
|
-
const translation = normalizedLocales[currentLocaleValue];
|
|
61
|
-
const { $mergeGlobalTranslations } = useNuxtApp();
|
|
62
|
-
if ($mergeGlobalTranslations) {
|
|
63
|
-
$mergeGlobalTranslations(translation);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
19
|
+
const localeValue = unref(currentLocale);
|
|
20
|
+
if (localeValue && normalizedLocales[localeValue]) {
|
|
21
|
+
$mergeGlobalTranslations?.(normalizedLocales[localeValue]);
|
|
66
22
|
}
|
|
67
23
|
};
|
|
68
24
|
updateTranslations();
|
|
@@ -71,8 +27,8 @@ export default defineNuxtPlugin(async (nuxtApp) => {
|
|
|
71
27
|
onUnmounted(() => {
|
|
72
28
|
if (stopWatcher) {
|
|
73
29
|
stopWatcher();
|
|
74
|
-
currentLocale = null;
|
|
75
30
|
stopWatcher = null;
|
|
31
|
+
currentLocale = null;
|
|
76
32
|
}
|
|
77
33
|
});
|
|
78
34
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { isNoPrefixStrategy, isPrefixStrategy } from "nuxt-i18n-micro-core";
|
|
2
|
+
import { defineNuxtPlugin, useRuntimeConfig, useRoute, useRouter, navigateTo } from "#imports";
|
|
3
|
+
export default defineNuxtPlugin(async (nuxtApp) => {
|
|
4
|
+
const config = useRuntimeConfig();
|
|
5
|
+
const i18nConfig = config.public.i18nConfig;
|
|
6
|
+
const route = useRoute();
|
|
7
|
+
const router = useRouter();
|
|
8
|
+
const handleRedirect = async (to) => {
|
|
9
|
+
const currentLocale = nuxtApp.$getLocale().toString();
|
|
10
|
+
const name = to.name?.toString();
|
|
11
|
+
let defaultRouteName = name?.toString().replace("localized-", "").replace(new RegExp(`-${currentLocale}$`), "");
|
|
12
|
+
if (!to.params.locale) {
|
|
13
|
+
if (router.hasRoute(`localized-${name}-${currentLocale}`)) {
|
|
14
|
+
defaultRouteName = `localized-${name}-${currentLocale}`;
|
|
15
|
+
} else {
|
|
16
|
+
defaultRouteName = `localized-${name}`;
|
|
17
|
+
}
|
|
18
|
+
if (!router.hasRoute(defaultRouteName)) return;
|
|
19
|
+
const newParams = { ...to.params };
|
|
20
|
+
if (!isNoPrefixStrategy(i18nConfig.strategy)) {
|
|
21
|
+
newParams.locale = i18nConfig.defaultLocale;
|
|
22
|
+
}
|
|
23
|
+
return navigateTo({ name: defaultRouteName, params: newParams }, {
|
|
24
|
+
redirectCode: 301,
|
|
25
|
+
external: true
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
if (import.meta.server && (isPrefixStrategy(i18nConfig.strategy) || isNoPrefixStrategy(i18nConfig.strategy))) {
|
|
30
|
+
await handleRedirect(route);
|
|
31
|
+
}
|
|
32
|
+
router.beforeEach(async (to, from, next) => {
|
|
33
|
+
if (isPrefixStrategy(i18nConfig.strategy) || isNoPrefixStrategy(i18nConfig.strategy)) {
|
|
34
|
+
await handleRedirect(to);
|
|
35
|
+
}
|
|
36
|
+
next?.();
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -36,7 +36,7 @@ export default defineEventHandler(async (event) => {
|
|
|
36
36
|
const cacheName = join("_locales", getTranslationPath(locale, page));
|
|
37
37
|
const isThereAsset = await serverStorage.hasItem(cacheName);
|
|
38
38
|
if (isThereAsset) {
|
|
39
|
-
const rawContent = await serverStorage.
|
|
39
|
+
const rawContent = await serverStorage.getItemRaw(cacheName) ?? {};
|
|
40
40
|
return typeof rawContent === "string" ? JSON.parse(rawContent) : rawContent;
|
|
41
41
|
}
|
|
42
42
|
const createPaths = (locale2) => rootDirs.map((dir) => ({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nuxt-i18n-micro",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.87.0",
|
|
4
4
|
"description": "Nuxt I18n Micro is a lightweight, high-performance internationalization module for Nuxt, designed to handle multi-language support with minimal overhead, fast build times, and efficient runtime performance.",
|
|
5
5
|
"repository": "s00d/nuxt-i18n-micro",
|
|
6
6
|
"license": "MIT",
|
|
@@ -59,8 +59,8 @@
|
|
|
59
59
|
"globby": "^14.1.0",
|
|
60
60
|
"sirv": "^2.0.4",
|
|
61
61
|
"ufo": "^1.5.4",
|
|
62
|
+
"nuxt-i18n-micro-types": "1.0.6",
|
|
62
63
|
"nuxt-i18n-micro-core": "1.0.18",
|
|
63
|
-
"nuxt-i18n-micro-types": "1.0.4",
|
|
64
64
|
"nuxt-i18n-micro-test-utils": "1.0.6"
|
|
65
65
|
},
|
|
66
66
|
"devDependencies": {
|
|
@@ -108,6 +108,7 @@
|
|
|
108
108
|
"lint": "eslint .",
|
|
109
109
|
"lint:fix": "eslint . --fix",
|
|
110
110
|
"test": "playwright test",
|
|
111
|
+
"test:vitest": "vitest run",
|
|
111
112
|
"test:watch": "vitest watch",
|
|
112
113
|
"test:types": "vue-tsc --noEmit && cd playground && vue-tsc --noEmit",
|
|
113
114
|
"test:workspaces": "pnpm recursive run test",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"id":"73fe5312-b8b8-43c9-8321-d410f5f66e5c","timestamp":1745916998724,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
|