@i18n-micro/route-strategy 1.1.3 → 1.1.4

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/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const w=require("node:path"),S=require("node:fs"),k=require("@i18n-micro/core"),b=l=>l.map(e=>({...e})),K=l=>!!(l.redirect&&!l.file),F=(l,e,t,a="localized-")=>t?`${a}${l}-${e}`:`${a}${l}`,C=(l,e)=>l??(e??"").replace(/[^a-z0-9]/gi,"-").replace(/^-+|-+$/g,""),M=(l,e,t)=>t&&l!==e.code,T=(l,e)=>(typeof l=="string"?l:l.code)===e.code,H=[/^\/sitemap.*\.xml$/,/^\/sitemap\.xml$/,/^\/robots\.txt$/,/^\/favicon\.ico$/,/^\/apple-touch-icon.*\.png$/,/^\/manifest\.json$/,/^\/sw\.js$/,/^\/workbox-.*\.js$/,/\.(xml|txt|ico|json|js|css|png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)$/];function E(l,e){if(/(?:^|\/)__[^/]+/.test(l))return!0;for(const t of H)if(t.test(l))return!0;if(e){for(const t of e)if(typeof t=="string"){if(t.includes("*")||t.includes("?")){if(new RegExp(t.replace(/\*/g,".*").replace(/\?/g,".")).test(l))return!0}else if(l===t||l.startsWith(t))return!0}else if(t instanceof RegExp&&t.test(l))return!0}return!1}function J(l,e){const t=l.reduce((o,s)=>{const i=o.find(r=>r.code===s.code);return i?Object.assign(i,s):o.push(s),o},[]).filter(o=>!o.disabled),a=t.find(o=>o.code===e)??{code:e};return{locales:t,defaultLocale:a}}function x(l){return l.split("/").map(e=>e.startsWith("[...")&&e.endsWith("]")?`:${e.substring(4,e.length-1)}(.*)*`:e.startsWith("[")&&e.endsWith("]")?`:${e.substring(1,e.length-1)}`:e).join("/")}const R=l=>{if(!l)return"";const e=w.posix.normalize(l).replace(/\/+$/,"");return e==="."?"":e},g=l=>l.startsWith("/")?l.slice(1):l;function O(...l){return w.posix.join(...l)}function Q(l){if(!(typeof l>"u"))return l.startsWith("/")&&l.endsWith("/")?l?.slice(1,-1):l}function V(l){return!l||!/[\u0080-\uFFFF]/.test(l)?l:l.split("/").map(e=>!e||e.startsWith(":")||!/[\u0080-\uFFFF]/.test(e)?e:encodeURI(e)).join("/")}function N(l,e,t){const a=Q(t?.toString()),o=a||(Array.isArray(l)?l.join("|"):l),s=V(e);return R(w.posix.join("/",`:locale(${o})`,s))}function I(l){const e=V(l);return R(e)}const X=(l,e)=>l??(e??"").replace(/[^a-z0-9]/gi,"-").replace(/^-+|-+$/g,"");function j(l){return g(l)||"/"}function _(l,e,t,a=""){const o={};return l.forEach(s=>{const i=X(s.name,s.path),r=R(O(a,s.path??"")),c=j(r),d=x(r),n=e[c]||e[d]||e[i];if(n)typeof n=="object"&&(o[c]=n);else{const h=t[i];h&&typeof h=="object"&&!Array.isArray(h)&&(o[c]=h)}if(s.children?.length){const h=R(O(a,s.path??""));Object.assign(o,_(s.children,e,t,h))}}),o}function Y(l){const e={};if(!l)return e;for(const t in l){const a=x(t),o=l[t];if(typeof o=="object"){const s={};for(const i in o){const r=o[i];r&&(s[i]=x(r))}e[a]=s}else e[a]=o}return e}class Z{constructor(e){this.locales=e.locales,this.defaultLocale=this.findLocaleByCode(e.locales,e.defaultLocaleCode)??{code:e.defaultLocaleCode},this.strategy=e.strategy,this.globalLocaleRoutes=Y(e.globalLocaleRoutes??{}),this.filesLocaleRoutes=e.filesLocaleRoutes??{},this.routeLocales=e.routeLocales??{},this.localizedPaths=_(e.pages,this.globalLocaleRoutes,this.filesLocaleRoutes),this.activeLocaleCodes=this.locales.filter(t=>t.code!==this.defaultLocale.code||k.isPrefixAndDefaultStrategy(this.strategy)||k.isPrefixStrategy(this.strategy)).map(t=>t.code),this.excludePatterns=e.excludePatterns,this.customRegex=e.customRegex,this.noPrefixRedirect=e.noPrefixRedirect??!1,this.localizedRouteNamePrefix=e.localizedRouteNamePrefix??"localized-",this.fallbackRedirectComponentPath=e.fallbackRedirectComponentPath,this.rawGlobalLocaleRoutes=e.rawGlobalLocaleRoutes}findLocaleByCode(e,t){return e.find(a=>a.code===t)}getAllowedLocales(e,t){const a=this.routeLocales[e]??this.routeLocales[t];return a?.length?a.filter(o=>this.locales.some(s=>s.code===o)):this.locales.map(o=>o.code)}getCustomPath(e,t){const a=j(e);return this.localizedPaths[a]?.[t]}getCustomPathsForPage(e,t){const a=j(e);return this.localizedPaths[a]??this.localizedPaths[t]}hasLocaleRestrictions(e,t){return!!(this.routeLocales[e]??this.routeLocales[t])}filterLocaleCodesWithoutCustomPaths(e){const t=j(e);return this.activeLocaleCodes.filter(a=>!this.localizedPaths[t]?.[a])}}function z(l,e){const t=(e??"").trim();return t.startsWith("/")?R(t):R(w.posix.join(l||"",t))}function p(l,e){const{path:t,name:a,children:o,meta:s,alias:i}=e,r={...l,path:t};return a!==void 0&&(r.name=a),o!==void 0&&(r.children=o),s!==void 0&&(r.meta={...l.meta,...s}),i!==void 0?(r.alias=i,r.meta={...r.meta,alias:i}):"alias"in e&&(r.alias=void 0,r.meta={...r.meta,alias:void 0}),r}function ee(l){const e=l.alias,t=l.meta?.alias,a=e??t;return Array.isArray(a)?a:[]}function D(l,e,t,a="localized-"){const o=ee(l);if(!o.length)return[];const s=[];for(const i of o){const r=N(e,i,t);s.push(p(l,{path:r,name:`${a}${l.name??""}`,alias:void 0,meta:{alias:void 0},children:l.children}))}return s}class W{processPage(e,t){if(e.path===void 0)throw new Error("page.path is required");if(K(e))return[e];if(e.path&&E(e.path,t.excludePatterns))return[e];const a=e.path??"",o=C(e.name,e.path),s=x(a);return t.globalLocaleRoutes[o]===!1||t.globalLocaleRoutes[s]===!1?[e]:this.generateVariants(e,t)}postProcess(e,t){return e}localizeChildren(e,t,a,o,s,i){return e.flatMap(r=>this.localizeChild(r,t,a,o,s,i))}localizeChildrenAllLocales(e,t,a,o,s){return e.flatMap(i=>this.localizeChildAllLocales(i,t,a,o,s))}localizeChildAllLocales(e,t,a,o,s){const i=z(a,e.path??""),r=z(t,e.path??""),c=j(r),d=s.localizedPaths[c];if(d)return o.flatMap(f=>{const P=d[f]??z(t,e.path??"");return this.localizeChild(e,P,a,f,s,!0)});const n=R(e.path??""),h=g(n),u=this.localizeChildrenAllLocales(b(e.children??[]),r,i,o,s),m=`${s.localizedRouteNamePrefix}${e.name??""}`;return[p(e,{path:h,name:m,children:u})]}localizeChild(e,t,a,o,s,i){const r=z(a,e.path??""),c=s.getCustomPath(r,o),d=g(R(c||(e.path??""))),n=c??z(t,e.path??""),h=this.localizeChildren(b(e.children??[]),n,r,o,s,i),u=C(e.name,e.path),m=`${s.localizedRouteNamePrefix}${u}-${o}`;return[p(e,{path:d,name:m,children:h})]}buildRoutePathForLocales(e,t,a,o,s,i,r){if(o){const c=e.includes(r);return i||!c?N(e,a,s):R(a)}return N(e,t,s)}}class te extends W{generateVariants(e,t){const a=e.path??"",o=C(e.name,e.path),s=t.getAllowedLocales(a,o),i=t.getCustomPathsForPage(a,o),r=b(e.children??[]),c=[];if(c.push(e),i)for(const d of s){const n=i[d];if(!n)continue;const h=R(n),u=R(a);if(h===u)continue;const m=I(n),f=F(o,d,!0),P=this.localizeChildrenForNoPrefix(r,h,a,a,d,t,1);c.push(p(e,{path:m,name:f,children:P,alias:[],meta:{alias:[]}})),t.noPrefixRedirect&&d===t.defaultLocale.code&&h!==u&&(e.redirect=h)}return c.push(...D(e,s,t.customRegex,t.localizedRouteNamePrefix)),c}localizeChildrenForNoPrefix(e,t,a,o,s,i,r){return e.map(c=>{const d=z(a,c.path??"");let n,h;if(r===1){const P=i.getCustomPath(d,s);if(P){const L=R(P);n=g(L),h=L}else{const L=R(c.path??"");n=g(L),h=z(t,c.path??"")}}else{const P=R(c.path??"");n=g(P),h=z(t,c.path??"")}const u=this.localizeChildrenForNoPrefix(b(c.children??[]),h,d,o,s,i,r+1),m=C(c.name,c.path),f=F(m,s,!0);return p(c,{path:n,name:f,children:u})})}}function ae(l){const e=l.alias??l.meta?.alias;return Array.isArray(e)?e:[]}class se extends W{generateVariants(e,t){const a=e.path??"",o=C(e.name,e.path),s=t.getAllowedLocales(a,o),i=t.getCustomPathsForPage(a,o),r=b(e.children??[]),c=[];if(i)for(const n of s){const h=i[n],u=h?R(h):a,m=N(n,u,t.customRegex),f=F(o,n,!!h,t.localizedRouteNamePrefix),P=h??a,L=this.localizeChildren(r,P,a,n,t,!0);c.push(p(e,{path:m,name:f,children:L,alias:[],meta:{alias:[]}}))}else{const n=N(s,a,t.customRegex),h=F(o,s[0],!1,t.localizedRouteNamePrefix),u=this.localizeChildrenAllLocales(r,a,a,s,t);c.push(p(e,{path:n,name:h,children:u,alias:[],meta:{alias:[]}}))}const d=ae(e);if(d.length)for(const n of d){const h=N(s,n,t.customRegex);c.push(p(e,{path:h,name:`${t.localizedRouteNamePrefix}${e.name??""}`,alias:void 0,meta:{alias:void 0}}))}return c}postProcess(e,t){const a=e.filter(s=>{if(s.name==="index"&&s.path==="/")return!1;const i=s.path??"";return!!(i&&E(i,t.excludePatterns)||t.globalLocaleRoutes[s.name??""]===!1||/^\/:locale/.test(i)||i==="/")}),o=t.defaultLocale.code;for(const[s,i]of Object.entries(t.globalLocaleRoutes)){if(i===!1||typeof i!="object")continue;const r=i[o];if(!r)continue;const c=s.startsWith("/")?s:`/${s}`,d=`/${o}${r.startsWith("/")?r:`/${r}`}`;c!==d&&a.push({path:c,name:`redirect-${s.replace(/\//g,"-")}`,redirect:d})}return t.fallbackRedirectComponentPath&&a.push({path:"/:pathMatch(.*)*",name:"custom-fallback-route",file:t.fallbackRedirectComponentPath,meta:{globalLocaleRoutes:t.rawGlobalLocaleRoutes??t.globalLocaleRoutes}}),a}}class oe extends W{generateVariants(e,t){const a=e.path??"",o=C(e.name,e.path),s=t.getAllowedLocales(a,o),i=t.getCustomPathsForPage(a,o),r=b(e.children??[]),c=[],d=t.defaultLocale.code;c.push(e);const n=t.locales.filter(u=>s.includes(u.code));if(n.length>0)if(i)for(const u of n){const m=i[u.code];if(m)if(u.code===d){const f=this.createLocalizedRoute(e,[u.code],r,!0,m,t.customRegex,!1,u.code,a,t);f&&c.push(f);const P=this.createLocalizedRoute(e,[u.code],r,!0,m,t.customRegex,!0,u.code,a,t);P&&c.push(P)}else{const f=this.createLocalizedRoute(e,[u.code],r,!0,m,t.customRegex,!1,u.code,a,t);f&&c.push(f)}else{const f=this.createLocalizedRoute(e,[u.code],r,!1,"",t.customRegex,!1,u.code,a,t);f&&c.push(f)}}else{const u=n.map(f=>f.code),m=this.createLocalizedRoute(e,u,r,!1,"",t.customRegex,!1,!0,a,t);m&&c.push(m)}const h=D(e,s,t.customRegex,t.localizedRouteNamePrefix);return h.length&&c.push(...h),c}postProcess(e,t){const a=[],o=[];for(const s of e){const i=s.name??"";typeof i=="string"&&i.startsWith(t.localizedRouteNamePrefix)?o.push(s):a.push(s)}return[...a,...o]}createLocalizedRoute(e,t,a,o,s="",i,r=!1,c=!1,d,n){const h=this.buildRoutePathForLocales(t,e.path??"",encodeURI(s),o,i,r,n.defaultLocale.code);if(!h||!(o&&s)&&h===e.path||t.length===0)return null;const m=t[0];if(!m)return null;const f=d??e.path??"",P=F(C(e.name??"",f),m,o,n.localizedRouteNamePrefix),L=r||m!==n.defaultLocale.code,y=t.length===1?this.localizeChildren(a,h,f,m,n,L):this.localizeChildrenAllLocales(a,h,f,t,n);return p(e,{path:h,name:P,children:y,alias:[],meta:{alias:[]}})}}class le extends W{generateVariants(e,t){const a=e.path??"",o=C(e.name,e.path),s=t.getAllowedLocales(a,o),i=t.getCustomPathsForPage(a,o),r=b(e.children??[]),c=[],d=t.defaultLocale.code;if(s.includes(d)){const u=i?.[d],m=u?R(u):a,f=u?{[d]:u}:{},P=this.createLocalizedChildren(r,a,[d],!1,!1,!1,f,t);c.push(p(e,{path:m,name:e.name,children:P}))}const n=t.locales.filter(u=>s.includes(u.code)&&u.code!==d);if(n.length)if(i)for(const u of n){const m=i[u.code];if(m){const f=this.createLocalizedRoute(e,[u.code],r,!0,m,t.customRegex,!1,u.code,a,t);f&&c.push(f)}else{const f=this.createLocalizedRoute(e,[u.code],r,!1,"",t.customRegex,!1,u.code,a,t);f&&c.push(f)}}else{const u=n.map(f=>f.code),m=this.createLocalizedRoute(e,u,r,!1,"",t.customRegex,!1,!0,a,t);m&&c.push(m)}const h=D(e,s,t.customRegex,t.localizedRouteNamePrefix);return h.length&&c.push(...h),c}postProcess(e,t){const a=[],o=[];for(const i of e){const r=i.name??"";typeof r=="string"&&r.startsWith(t.localizedRouteNamePrefix)?o.push(i):a.push(i)}const s=[...a,...o];return t.fallbackRedirectComponentPath&&s.push({path:"/:pathMatch(.*)*",name:"custom-fallback-route",file:t.fallbackRedirectComponentPath,meta:{globalLocaleRoutes:t.rawGlobalLocaleRoutes??t.globalLocaleRoutes}}),s}createLocalizedChildren(e,t,a,o=!0,s=!1,i=!1,r={},c){return e.flatMap(d=>this.createLocalizedVariants(d,t,a,o,s,i,r,c))}createLocalizedVariants(e,t,a,o,s,i=!1,r,c){const d=R(e.path??""),n=z(t,e.path??""),h=j(n),u=c.localizedPaths[h],m=!!u,f=[];if(!m){const P=g(d),L=this.createLocalizedChildren(b(e.children??[]),z(t,e.path??""),a,o,s,i,r,c),y=this.buildChildRouteName(e.name,i,c);return f.push(p(e,{path:P,name:y,children:L})),f}for(const P of a){const L=r?.[P],y=!!L,$=u?.[P];let A=R($||(e.path??""));y&&L&&($?A=R($):A=z(L,e.path??""));const v=M(P,c.defaultLocale,s)?N(P,A,c.customRegex):A,q=g(v),G=$?R($):y?L:z(t,e.path??""),B=this.createLocalizedChildren(b(e.children??[]),G,[P],o,s,P,{...r,[P]:G},c),U=this.buildLocalizedRouteName(C(e.name,e.path),P,o,!!u,c);f.push(p(e,{path:q,name:U,children:B}))}return f}buildChildRouteName(e,t,a){return t===!0?`${a.localizedRouteNamePrefix}${e}`:typeof t=="string"?`${a.localizedRouteNamePrefix}${e}-${t}`:e}createLocalizedRoute(e,t,a,o,s="",i,r=!1,c=!1,d,n){const h=this.buildRoutePathForLocales(t,e.path??"",encodeURI(s),o,i,r,n.defaultLocale.code);if(!h||h===e.path||t.length===0)return null;const u=t[0];if(!u)return null;const m=d??e.path??"",f=F(C(e.name??"",m),u,o,n.localizedRouteNamePrefix);return p(e,{path:h,name:f,children:this.createLocalizedChildren(a,m,t,!0,!1,c,{[u]:s},n),alias:[],meta:{alias:[]}})}buildLocalizedRouteName(e,t,a,o=!1,s){return a?o?`${s.localizedRouteNamePrefix}${e}-${t}`:t&&!T(t,s.defaultLocale)?`${s.localizedRouteNamePrefix}${e}-${t}`:`${s.localizedRouteNamePrefix}${e}`:e}}function ie(l){switch(l){case"no_prefix":return new te;case"prefix":return new se;case"prefix_and_default":return new oe;case"prefix_except_default":return new le;default:throw new Error(`Unknown route strategy: ${l}`)}}class re{constructor(e){this.localizedPaths={};const{locales:t,defaultLocaleCode:a,strategy:o,globalLocaleRoutes:s,filesLocaleRoutes:i={},routeLocales:r={},noPrefixRedirect:c,excludePatterns:d,localizedRouteNamePrefix:n="localized-",customRegexMatcher:h,fallbackRedirectComponentPath:u}=e,m=J(t,a);this.locales=m.locales,this.defaultLocale=m.defaultLocale,this.strategy=o,this.noPrefixRedirect=c,this.excludePatterns=d,this.localizedRouteNamePrefix=n,this.customRegex=h,this.fallbackRedirectComponentPath=u,this.activeLocaleCodes=this.computeActiveLocaleCodes();const f={};for(const P in s){const L=x(P),y=s[P];if(typeof y=="object"){const $={};for(const A in y){const v=y[A];v&&($[A]=x(v))}f[L]=$}else f[L]=y}this.globalLocaleRoutes=f,this.rawGlobalLocaleRoutes=s??{},this.filesLocaleRoutes=i??{},this.routeLocales=r??{}}computeActiveLocaleCodes(){return this.locales.filter(e=>e.code!==this.defaultLocale.code||k.isPrefixAndDefaultStrategy(this.strategy)||k.isPrefixStrategy(this.strategy)).map(e=>e.code)}extendPages(e){const t=new Z({locales:this.locales,defaultLocaleCode:this.defaultLocale.code,strategy:this.strategy,globalLocaleRoutes:this.globalLocaleRoutes,filesLocaleRoutes:this.filesLocaleRoutes,routeLocales:this.routeLocales,pages:e,excludePatterns:this.excludePatterns,customRegex:this.customRegex,noPrefixRedirect:this.noPrefixRedirect,localizedRouteNamePrefix:this.localizedRouteNamePrefix,fallbackRedirectComponentPath:this.fallbackRedirectComponentPath,rawGlobalLocaleRoutes:this.rawGlobalLocaleRoutes});this.localizedPaths=t.localizedPaths;const a=ie(this.strategy),o=[...e],s=[];for(const r of o)s.push(...a.processPage(r,t));const i=a.postProcess(s,t);e.length=0,e.push(...i)}extractLocalizedPaths(e,t=""){return _(e,this.globalLocaleRoutes,this.filesLocaleRoutes,t)}ensureTranslationFilesExist(e,t,a,o){this.locales.forEach(s=>{const i=w.join(a,t,`${s.code}.json`);this.ensureFileExists(i),o||e.forEach(r=>{const c=w.join(a,t,"pages",`${r}/${s.code}.json`);this.ensureFileExists(c)})})}ensureFileExists(e){try{const t=w.dirname(e);S.existsSync(t)||S.mkdirSync(t,{recursive:!0}),S.existsSync(e)||S.writeFileSync(e,JSON.stringify({}),"utf-8")}catch{}}resolveLocalizedPath(e,t){const a=x(e),o=g(a)||"/";let s;const i=this.globalLocaleRoutes[o],r=this.globalLocaleRoutes[a];i&&typeof i=="object"&&!Array.isArray(i)?s=i[t]:r&&typeof r=="object"&&!Array.isArray(r)&&(s=r[t]);const c=!!s,d=s?R(s):R(a)||"";let n=!1;if(this.strategy==="no_prefix"?n=!1:this.strategy==="prefix"||this.strategy==="prefix_and_default"?n=!0:this.strategy==="prefix_except_default"&&(n=t!==this.defaultLocale.code),t===this.defaultLocale.code&&!c&&(this.strategy==="prefix_except_default"||this.strategy==="no_prefix")&&(n=!1),!n)return R(d)||"/";const h=g(d);return h?R(`/${t}/${h}`):`/${t}`}generateDataRoutes(e,t,a){const o=[],s=e.map(i=>i.name).filter(i=>typeof i=="string"&&i.length>0);for(const i of this.locales)if(o.push(`/${t}/general/${i.code}/data.json`),!a)for(const r of s)o.push(`/${t}/${r}/${i.code}/data.json`);return o}}exports.RouteGenerator=re;exports.buildFullPath=N;exports.buildFullPathNoPrefix=I;exports.buildRouteName=F;exports.cloneArray=b;exports.extractLocalizedPaths=_;exports.isInternalPath=E;exports.isLocaleDefault=T;exports.isPageRedirectOnly=K;exports.normalizePath=R;exports.normalizeRouteKey=x;exports.removeLeadingSlash=g;exports.shouldAddLocalePrefix=M;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const w=require("node:path"),S=require("node:fs"),k=require("@i18n-micro/core"),b=l=>l.map(e=>({...e})),K=l=>!!(l.redirect&&!l.file),F=(l,e,t,a="localized-")=>t?`${a}${l}-${e}`:`${a}${l}`,C=(l,e)=>l??(e??"").replace(/[^a-z0-9]/gi,"-").replace(/^-+|-+$/g,""),M=(l,e,t)=>t&&l!==e.code,T=(l,e)=>(typeof l=="string"?l:l.code)===e.code,H=[/^\/sitemap.*\.xml$/,/^\/sitemap\.xml$/,/^\/robots\.txt$/,/^\/favicon\.ico$/,/^\/apple-touch-icon.*\.png$/,/^\/manifest\.json$/,/^\/sw\.js$/,/^\/workbox-.*\.js$/,/\.(xml|txt|ico|json|js|css|png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)$/];function E(l,e){if(/(?:^|\/)__[^/]+/.test(l))return!0;for(const t of H)if(t.test(l))return!0;if(e){for(const t of e)if(typeof t=="string"){if(t.includes("*")||t.includes("?")){if(new RegExp(t.replace(/\*/g,".*").replace(/\?/g,".")).test(l))return!0}else if(l===t||l.startsWith(t))return!0}else if(t instanceof RegExp&&t.test(l))return!0}return!1}function J(l,e){const t=l.reduce((o,s)=>{const r=o.find(i=>i.code===s.code);return r?Object.assign(r,s):o.push(s),o},[]).filter(o=>!o.disabled),a=t.find(o=>o.code===e)??{code:e};return{locales:t,defaultLocale:a}}function x(l){return l.split("/").map(e=>e.startsWith("[...")&&e.endsWith("]")?`:${e.substring(4,e.length-1)}(.*)*`:e.startsWith("[")&&e.endsWith("]")?`:${e.substring(1,e.length-1)}`:e).join("/")}const R=l=>{if(!l)return"";const e=w.posix.normalize(l).replace(/\/+$/,"");return e==="."?"":e},g=l=>l.startsWith("/")?l.slice(1):l;function O(...l){return w.posix.join(...l)}function Q(l){if(!(typeof l>"u"))return l.startsWith("/")&&l.endsWith("/")?l?.slice(1,-1):l}function V(l){return!l||!/[\u0080-\uFFFF]/.test(l)?l:l.split("/").map(e=>!e||e.startsWith(":")||!/[\u0080-\uFFFF]/.test(e)?e:encodeURI(e)).join("/")}function N(l,e,t){const a=Q(t?.toString()),o=a||(Array.isArray(l)?l.join("|"):l),s=V(e);return R(w.posix.join("/",`:locale(${o})`,s))}function I(l){const e=V(l);return R(e)}const X=(l,e)=>l??(e??"").replace(/[^a-z0-9]/gi,"-").replace(/^-+|-+$/g,"");function j(l){return g(l)||"/"}function _(l,e,t,a=""){const o={};return l.forEach(s=>{const r=X(s.name,s.path),i=R(O(a,s.path??"")),c=j(i),d=x(i),n=e[c]||e[d]||e[r];if(n)typeof n=="object"&&(o[c]=n);else{const h=t[r];h&&typeof h=="object"&&!Array.isArray(h)&&(o[c]=h)}if(s.children?.length){const h=R(O(a,s.path??""));Object.assign(o,_(s.children,e,t,h))}}),o}function Y(l){const e={};if(!l)return e;for(const t in l){const a=x(t),o=l[t];if(typeof o=="object"){const s={};for(const r in o){const i=o[r];i&&(s[r]=x(i))}e[a]=s}else e[a]=o}return e}class Z{constructor(e){this.locales=e.locales,this.defaultLocale=this.findLocaleByCode(e.locales,e.defaultLocaleCode)??{code:e.defaultLocaleCode},this.strategy=e.strategy,this.globalLocaleRoutes=Y(e.globalLocaleRoutes??{}),this.filesLocaleRoutes=e.filesLocaleRoutes??{},this.routeLocales=e.routeLocales??{},this.localizedPaths=_(e.pages,this.globalLocaleRoutes,this.filesLocaleRoutes),this.activeLocaleCodes=this.locales.filter(t=>t.code!==this.defaultLocale.code||k.isPrefixAndDefaultStrategy(this.strategy)||k.isPrefixStrategy(this.strategy)).map(t=>t.code),this.excludePatterns=e.excludePatterns,this.customRegex=e.customRegex,this.noPrefixRedirect=e.noPrefixRedirect??!1,this.localizedRouteNamePrefix=e.localizedRouteNamePrefix??"localized-",this.fallbackRedirectComponentPath=e.fallbackRedirectComponentPath,this.rawGlobalLocaleRoutes=e.rawGlobalLocaleRoutes}findLocaleByCode(e,t){return e.find(a=>a.code===t)}getAllowedLocales(e,t){const a=this.routeLocales[e]??this.routeLocales[t];return a?.length?a.filter(o=>this.locales.some(s=>s.code===o)):this.locales.map(o=>o.code)}getCustomPath(e,t){const a=j(e);return this.localizedPaths[a]?.[t]}getCustomPathsForPage(e,t){const a=j(e);return this.localizedPaths[a]??this.localizedPaths[t]}hasLocaleRestrictions(e,t){return!!(this.routeLocales[e]??this.routeLocales[t])}filterLocaleCodesWithoutCustomPaths(e){const t=j(e);return this.activeLocaleCodes.filter(a=>!this.localizedPaths[t]?.[a])}}function z(l,e){const t=(e??"").trim();return t.startsWith("/")?R(t):R(w.posix.join(l||"",t))}function p(l,e){const{path:t,name:a,children:o,meta:s,alias:r}=e,i={...l,path:t};return a!==void 0&&(i.name=a),o!==void 0&&(i.children=o),s!==void 0&&(i.meta={...l.meta,...s}),r!==void 0?(i.alias=r,i.meta={...i.meta,alias:r}):"alias"in e&&(i.alias=void 0,i.meta={...i.meta,alias:void 0}),i}function ee(l){const e=l.alias,t=l.meta?.alias,a=e??t;return Array.isArray(a)?a:[]}function D(l,e,t,a="localized-"){const o=ee(l);if(!o.length)return[];const s=[];for(const r of o){const i=N(e,r,t);s.push(p(l,{path:i,name:`${a}${l.name??""}`,alias:void 0,meta:{alias:void 0},children:l.children}))}return s}class W{processPage(e,t){if(e.path===void 0)throw new Error("page.path is required");if(K(e))return[e];if(e.path&&E(e.path,t.excludePatterns))return[e];const a=e.path??"",o=C(e.name,e.path),s=x(a);return t.globalLocaleRoutes[o]===!1||t.globalLocaleRoutes[s]===!1?[e]:this.generateVariants(e,t)}postProcess(e,t){return e}localizeChildren(e,t,a,o,s,r){return e.flatMap(i=>this.localizeChild(i,t,a,o,s,r))}localizeChildrenAllLocales(e,t,a,o,s){return e.flatMap(r=>this.localizeChildAllLocales(r,t,a,o,s))}localizeChildAllLocales(e,t,a,o,s){const r=z(a,e.path??""),i=z(t,e.path??""),c=j(i),d=s.localizedPaths[c];if(d)return o.flatMap(f=>{const P=d[f]??z(t,e.path??"");return this.localizeChild(e,P,a,f,s,!0)});const n=R(e.path??""),h=g(n),u=this.localizeChildrenAllLocales(b(e.children??[]),i,r,o,s),m=`${s.localizedRouteNamePrefix}${e.name??""}`;return[p(e,{path:h,name:m,children:u})]}localizeChild(e,t,a,o,s,r){const i=z(a,e.path??""),c=s.getCustomPath(i,o),d=g(R(c||(e.path??""))),n=c??z(t,e.path??""),h=this.localizeChildren(b(e.children??[]),n,i,o,s,r),u=C(e.name,e.path),m=`${s.localizedRouteNamePrefix}${u}-${o}`;return[p(e,{path:d,name:m,children:h})]}buildRoutePathForLocales(e,t,a,o,s,r,i){if(o){const c=e.includes(i);return r||!c?N(e,a,s):R(a)}return N(e,t,s)}}class te extends W{generateVariants(e,t){const a=e.path??"",o=C(e.name,e.path),s=t.getAllowedLocales(a,o),r=t.getCustomPathsForPage(a,o),i=b(e.children??[]),c=[];if(c.push(e),r)for(const d of s){const n=r[d];if(!n)continue;const h=R(n),u=R(a);if(h===u)continue;const m=I(n),f=F(o,d,!0),P=this.localizeChildrenForNoPrefix(i,h,a,a,d,t,1);c.push(p(e,{path:m,name:f,children:P,alias:[],meta:{alias:[]}})),t.noPrefixRedirect&&d===t.defaultLocale.code&&h!==u&&(e.redirect=h)}return c.push(...D(e,s,t.customRegex,t.localizedRouteNamePrefix)),c}localizeChildrenForNoPrefix(e,t,a,o,s,r,i){return e.map(c=>{const d=z(a,c.path??"");let n,h;if(i===1){const P=r.getCustomPath(d,s);if(P){const L=R(P);n=g(L),h=L}else{const L=R(c.path??"");n=g(L),h=z(t,c.path??"")}}else{const P=R(c.path??"");n=g(P),h=z(t,c.path??"")}const u=this.localizeChildrenForNoPrefix(b(c.children??[]),h,d,o,s,r,i+1),m=C(c.name,c.path),f=F(m,s,!0);return p(c,{path:n,name:f,children:u})})}}function ae(l){const e=l.alias??l.meta?.alias;return Array.isArray(e)?e:[]}class se extends W{generateVariants(e,t){const a=e.path??"",o=C(e.name,e.path),s=t.getAllowedLocales(a,o),r=t.getCustomPathsForPage(a,o),i=b(e.children??[]),c=[];if(r)for(const n of s){const h=r[n],u=h?R(h):a,m=N(n,u,t.customRegex),f=F(o,n,!!h,t.localizedRouteNamePrefix),P=h??a,L=this.localizeChildren(i,P,a,n,t,!0);c.push(p(e,{path:m,name:f,children:L,alias:[],meta:{alias:[]}}))}else{const n=N(s,a,t.customRegex),h=F(o,s[0],!1,t.localizedRouteNamePrefix),u=this.localizeChildrenAllLocales(i,a,a,s,t);c.push(p(e,{path:n,name:h,children:u,alias:[],meta:{alias:[]}}))}const d=ae(e);if(d.length)for(const n of d){const h=N(s,n,t.customRegex);c.push(p(e,{path:h,name:`${t.localizedRouteNamePrefix}${e.name??""}`,alias:void 0,meta:{alias:void 0}}))}return c}postProcess(e,t){const a=e.filter(s=>{if(s.name==="index"&&s.path==="/")return!1;const r=s.path??"";return!!(r&&E(r,t.excludePatterns)||t.globalLocaleRoutes[s.name??""]===!1||/^\/:locale/.test(r)||r==="/")}),o=t.defaultLocale.code;for(const[s,r]of Object.entries(t.globalLocaleRoutes)){if(r===!1||typeof r!="object")continue;const i=r[o];if(!i)continue;const c=s.startsWith("/")?s:`/${s}`,d=`/${o}${i.startsWith("/")?i:`/${i}`}`;c!==d&&a.push({path:c,name:`redirect-${s.replace(/\//g,"-")}`,redirect:d})}return t.fallbackRedirectComponentPath&&a.push({path:"/:pathMatch(.*)*",name:"custom-fallback-route",file:t.fallbackRedirectComponentPath,meta:{globalLocaleRoutes:t.rawGlobalLocaleRoutes??t.globalLocaleRoutes}}),a}}class oe extends W{generateVariants(e,t){const a=e.path??"",o=C(e.name,e.path),s=t.getAllowedLocales(a,o),r=t.getCustomPathsForPage(a,o),i=b(e.children??[]),c=[],d=t.defaultLocale.code;c.push(e);const n=t.locales.filter(u=>s.includes(u.code));if(n.length>0)if(r)for(const u of n){const m=r[u.code];if(m)if(u.code===d){const f=this.createLocalizedRoute(e,[u.code],i,!0,m,t.customRegex,!1,u.code,a,t);f&&c.push(f);const P=this.createLocalizedRoute(e,[u.code],i,!0,m,t.customRegex,!0,u.code,a,t);P&&c.push(P)}else{const f=this.createLocalizedRoute(e,[u.code],i,!0,m,t.customRegex,!1,u.code,a,t);f&&c.push(f)}else{const f=this.createLocalizedRoute(e,[u.code],i,!1,"",t.customRegex,!1,u.code,a,t);f&&c.push(f)}}else{const u=n.map(f=>f.code),m=this.createLocalizedRoute(e,u,i,!1,"",t.customRegex,!1,!0,a,t);m&&c.push(m)}const h=D(e,s,t.customRegex,t.localizedRouteNamePrefix);return h.length&&c.push(...h),c}postProcess(e,t){const a=[],o=[];for(const s of e){const r=s.name??"";typeof r=="string"&&r.startsWith(t.localizedRouteNamePrefix)?o.push(s):a.push(s)}return[...a,...o]}createLocalizedRoute(e,t,a,o,s="",r,i=!1,c=!1,d,n){const h=this.buildRoutePathForLocales(t,e.path??"",encodeURI(s),o,r,i,n.defaultLocale.code);if(!h||!(o&&s)&&h===e.path||t.length===0)return null;const m=t[0];if(!m)return null;const f=d??e.path??"",P=F(C(e.name??"",f),m,o,n.localizedRouteNamePrefix),L=i||m!==n.defaultLocale.code,y=t.length===1?this.localizeChildren(a,h,f,m,n,L):this.localizeChildrenAllLocales(a,h,f,t,n);return p(e,{path:h,name:P,children:y,alias:[],meta:{alias:[]}})}}class le extends W{generateVariants(e,t){const a=e.path??"",o=C(e.name,e.path),s=t.getAllowedLocales(a,o),r=t.getCustomPathsForPage(a,o),i=b(e.children??[]),c=[],d=t.defaultLocale.code;if(s.includes(d)){const u=r?.[d],m=u?R(u):a,f=u?{[d]:u}:{},P=this.createLocalizedChildren(i,a,[d],!1,!1,!1,f,t);c.push(p(e,{path:m,name:e.name,children:P}))}const n=t.locales.filter(u=>s.includes(u.code)&&u.code!==d);if(n.length)if(r)for(const u of n){const m=r[u.code];if(m){const f=this.createLocalizedRoute(e,[u.code],i,!0,m,t.customRegex,!1,u.code,a,t);f&&c.push(f)}else{const f=this.createLocalizedRoute(e,[u.code],i,!1,"",t.customRegex,!1,u.code,a,t);f&&c.push(f)}}else{const u=n.map(f=>f.code),m=this.createLocalizedRoute(e,u,i,!1,"",t.customRegex,!1,!0,a,t);m&&c.push(m)}const h=D(e,s,t.customRegex,t.localizedRouteNamePrefix);return h.length&&c.push(...h),c}postProcess(e,t){const a=[],o=[];for(const r of e){const i=r.name??"";typeof i=="string"&&i.startsWith(t.localizedRouteNamePrefix)?o.push(r):a.push(r)}const s=[...a,...o];return t.fallbackRedirectComponentPath&&s.push({path:"/:pathMatch(.*)*",name:"custom-fallback-route",file:t.fallbackRedirectComponentPath,meta:{globalLocaleRoutes:t.rawGlobalLocaleRoutes??t.globalLocaleRoutes}}),s}createLocalizedChildren(e,t,a,o=!0,s=!1,r=!1,i={},c){return e.flatMap(d=>this.createLocalizedVariants(d,t,a,o,s,r,i,c))}createLocalizedVariants(e,t,a,o,s,r=!1,i,c){const d=R(e.path??""),n=z(t,e.path??""),h=j(n),u=c.localizedPaths[h],m=!!u,f=[];if(!m){const P=g(d),L=this.createLocalizedChildren(b(e.children??[]),z(t,e.path??""),a,o,s,r,i,c),y=this.buildChildRouteName(e.name,r,c);return f.push(p(e,{path:P,name:y,children:L})),f}for(const P of a){const L=i?.[P],y=!!L,$=u?.[P];let A=R($||(e.path??""));y&&L&&($?A=R($):A=z(L,e.path??""));const v=M(P,c.defaultLocale,s)?N(P,A,c.customRegex):A,q=g(v),G=$?R($):y?L:z(t,e.path??""),B=this.createLocalizedChildren(b(e.children??[]),G,[P],o,s,P,{...i,[P]:G},c),U=this.buildLocalizedRouteName(C(e.name,e.path),P,o,!!u,c);f.push(p(e,{path:q,name:U,children:B}))}return f}buildChildRouteName(e,t,a){return t===!0?`${a.localizedRouteNamePrefix}${e}`:typeof t=="string"?`${a.localizedRouteNamePrefix}${e}-${t}`:e}createLocalizedRoute(e,t,a,o,s="",r,i=!1,c=!1,d,n){const h=this.buildRoutePathForLocales(t,e.path??"",encodeURI(s),o,r,i,n.defaultLocale.code);if(!h||h===e.path||t.length===0)return null;const u=t[0];if(!u)return null;const m=d??e.path??"",f=F(C(e.name??"",m),u,o,n.localizedRouteNamePrefix);return p(e,{path:h,name:f,children:this.createLocalizedChildren(a,m,t,!0,!1,c,{[u]:s},n),alias:[],meta:{alias:[]}})}buildLocalizedRouteName(e,t,a,o=!1,s){return a?o?`${s.localizedRouteNamePrefix}${e}-${t}`:t&&!T(t,s.defaultLocale)?`${s.localizedRouteNamePrefix}${e}-${t}`:`${s.localizedRouteNamePrefix}${e}`:e}}function ie(l){switch(l){case"no_prefix":return new te;case"prefix":return new se;case"prefix_and_default":return new oe;case"prefix_except_default":return new le;default:throw new Error(`Unknown route strategy: ${l}`)}}class re{constructor(e){this.localizedPaths={};const{locales:t,defaultLocaleCode:a,strategy:o,globalLocaleRoutes:s,filesLocaleRoutes:r={},routeLocales:i={},noPrefixRedirect:c,excludePatterns:d,localizedRouteNamePrefix:n="localized-",customRegexMatcher:h,fallbackRedirectComponentPath:u}=e,m=J(t,a);this.locales=m.locales,this.defaultLocale=m.defaultLocale,this.strategy=o,this.noPrefixRedirect=c,this.excludePatterns=d,this.localizedRouteNamePrefix=n,this.customRegex=h,this.fallbackRedirectComponentPath=u,this.activeLocaleCodes=this.computeActiveLocaleCodes();const f={};for(const P in s){const L=x(P),y=s[P];if(typeof y=="object"){const $={};for(const A in y){const v=y[A];v&&($[A]=x(v))}f[L]=$}else f[L]=y}this.globalLocaleRoutes=f,this.rawGlobalLocaleRoutes=s??{},this.filesLocaleRoutes=r??{},this.routeLocales=i??{}}computeActiveLocaleCodes(){return this.locales.filter(e=>e.code!==this.defaultLocale.code||k.isPrefixAndDefaultStrategy(this.strategy)||k.isPrefixStrategy(this.strategy)).map(e=>e.code)}extendPages(e){const t=new Z({locales:this.locales,defaultLocaleCode:this.defaultLocale.code,strategy:this.strategy,globalLocaleRoutes:this.globalLocaleRoutes,filesLocaleRoutes:this.filesLocaleRoutes,routeLocales:this.routeLocales,pages:e,excludePatterns:this.excludePatterns,customRegex:this.customRegex,noPrefixRedirect:this.noPrefixRedirect,localizedRouteNamePrefix:this.localizedRouteNamePrefix,fallbackRedirectComponentPath:this.fallbackRedirectComponentPath,rawGlobalLocaleRoutes:this.rawGlobalLocaleRoutes});this.localizedPaths=t.localizedPaths;const a=ie(this.strategy),o=[...e],s=[];for(const i of o)s.push(...a.processPage(i,t));const r=a.postProcess(s,t);e.length=0,e.push(...r)}extractLocalizedPaths(e,t=""){return _(e,this.globalLocaleRoutes,this.filesLocaleRoutes,t)}ensureTranslationFilesExist(e,t,a,o){this.locales.forEach(s=>{const r=w.join(a,t,`${s.code}.json`);this.ensureFileExists(r),o||e.forEach(i=>{const c=w.join(a,t,"pages",`${i}/${s.code}.json`);this.ensureFileExists(c)})})}ensureFileExists(e){try{const t=w.dirname(e);S.existsSync(t)||S.mkdirSync(t,{recursive:!0}),S.existsSync(e)||S.writeFileSync(e,JSON.stringify({}),"utf-8")}catch{}}resolveLocalizedPath(e,t){const a=x(e),o=g(a)||"/";let s;const r=this.globalLocaleRoutes[o],i=this.globalLocaleRoutes[a];r&&typeof r=="object"&&!Array.isArray(r)?s=r[t]:i&&typeof i=="object"&&!Array.isArray(i)&&(s=i[t]);const c=!!s,d=s?R(s):R(a)||"";let n=!1;if(this.strategy==="no_prefix"?n=!1:this.strategy==="prefix"||this.strategy==="prefix_and_default"?n=!0:this.strategy==="prefix_except_default"&&(n=t!==this.defaultLocale.code),t===this.defaultLocale.code&&!c&&(this.strategy==="prefix_except_default"||this.strategy==="no_prefix")&&(n=!1),!n)return R(d)||"/";const h=g(d);return h?R(`/${t}/${h}`):`/${t}`}generateDataRoutes(e,t,a){const o=[];for(const s of this.locales)if(o.push(`/${t}/index/${s.code}/data.json`),!a){const r=e.map(i=>i.name).filter(i=>typeof i=="string"&&i.length>0);for(const i of r)o.push(`/${t}/${i}/${s.code}/data.json`)}return o}}exports.RouteGenerator=re;exports.buildFullPath=N;exports.buildFullPathNoPrefix=I;exports.buildRouteName=F;exports.cloneArray=b;exports.extractLocalizedPaths=_;exports.isInternalPath=E;exports.isLocaleDefault=T;exports.isPageRedirectOnly=K;exports.normalizePath=R;exports.normalizeRouteKey=x;exports.removeLeadingSlash=g;exports.shouldAddLocalePrefix=M;
package/dist/index.mjs CHANGED
@@ -32,8 +32,8 @@ function K(l, e) {
32
32
  }
33
33
  function X(l, e) {
34
34
  const t = l.reduce((o, s) => {
35
- const i = o.find((r) => r.code === s.code);
36
- return i ? Object.assign(i, s) : o.push(s), o;
35
+ const r = o.find((i) => i.code === s.code);
36
+ return r ? Object.assign(r, s) : o.push(s), o;
37
37
  }, []).filter((o) => !o.disabled), a = t.find((o) => o.code === e) ?? { code: e };
38
38
  return { locales: t, defaultLocale: a };
39
39
  }
@@ -71,11 +71,11 @@ function F(l) {
71
71
  function S(l, e, t, a = "") {
72
72
  const o = {};
73
73
  return l.forEach((s) => {
74
- const i = ee(s.name, s.path), r = R(G(a, s.path ?? "")), c = F(r), d = w(r), n = e[c] || e[d] || e[i];
74
+ const r = ee(s.name, s.path), i = R(G(a, s.path ?? "")), c = F(i), d = w(i), n = e[c] || e[d] || e[r];
75
75
  if (n)
76
76
  typeof n == "object" && (o[c] = n);
77
77
  else {
78
- const h = t[i];
78
+ const h = t[r];
79
79
  h && typeof h == "object" && !Array.isArray(h) && (o[c] = h);
80
80
  }
81
81
  if (s.children?.length) {
@@ -91,9 +91,9 @@ function te(l) {
91
91
  const a = w(t), o = l[t];
92
92
  if (typeof o == "object") {
93
93
  const s = {};
94
- for (const i in o) {
95
- const r = o[i];
96
- r && (s[i] = w(r));
94
+ for (const r in o) {
95
+ const i = o[r];
96
+ i && (s[r] = w(i));
97
97
  }
98
98
  e[a] = s;
99
99
  } else
@@ -142,11 +142,11 @@ function z(l, e) {
142
142
  return t.startsWith("/") ? R(t) : R(N.posix.join(l || "", t));
143
143
  }
144
144
  function p(l, e) {
145
- const { path: t, name: a, children: o, meta: s, alias: i } = e, r = {
145
+ const { path: t, name: a, children: o, meta: s, alias: r } = e, i = {
146
146
  ...l,
147
147
  path: t
148
148
  };
149
- return a !== void 0 && (r.name = a), o !== void 0 && (r.children = o), s !== void 0 && (r.meta = { ...l.meta, ...s }), i !== void 0 ? (r.alias = i, r.meta = { ...r.meta, alias: i }) : "alias" in e && (r.alias = void 0, r.meta = { ...r.meta, alias: void 0 }), r;
149
+ return a !== void 0 && (i.name = a), o !== void 0 && (i.children = o), s !== void 0 && (i.meta = { ...l.meta, ...s }), r !== void 0 ? (i.alias = r, i.meta = { ...i.meta, alias: r }) : "alias" in e && (i.alias = void 0, i.meta = { ...i.meta, alias: void 0 }), i;
150
150
  }
151
151
  function se(l) {
152
152
  const e = l.alias, t = l.meta?.alias, a = e ?? t;
@@ -156,11 +156,11 @@ function _(l, e, t, a = "localized-") {
156
156
  const o = se(l);
157
157
  if (!o.length) return [];
158
158
  const s = [];
159
- for (const i of o) {
160
- const r = A(e, i, t);
159
+ for (const r of o) {
160
+ const i = A(e, r, t);
161
161
  s.push(
162
162
  p(l, {
163
- path: r,
163
+ path: i,
164
164
  name: `${a}${l.name ?? ""}`,
165
165
  alias: void 0,
166
166
  meta: { alias: void 0 },
@@ -193,24 +193,24 @@ class k {
193
193
  * - parentLocalizedPath used for the final path,
194
194
  * and returns an array of localized child routes.
195
195
  */
196
- localizeChildren(e, t, a, o, s, i) {
197
- return e.flatMap((r) => this.localizeChild(r, t, a, o, s, i));
196
+ localizeChildren(e, t, a, o, s, r) {
197
+ return e.flatMap((i) => this.localizeChild(i, t, a, o, s, r));
198
198
  }
199
199
  /**
200
200
  * Variant for a single route with :locale(locale1|locale2) — without custom paths.
201
201
  * Returns a single child route with a relative path and recursively localized children.
202
202
  */
203
203
  localizeChildrenAllLocales(e, t, a, o, s) {
204
- return e.flatMap((i) => this.localizeChildAllLocales(i, t, a, o, s));
204
+ return e.flatMap((r) => this.localizeChildAllLocales(r, t, a, o, s));
205
205
  }
206
206
  localizeChildAllLocales(e, t, a, o, s) {
207
- const i = z(a, e.path ?? ""), r = z(t, e.path ?? ""), c = F(r), d = s.localizedPaths[c];
207
+ const r = z(a, e.path ?? ""), i = z(t, e.path ?? ""), c = F(i), d = s.localizedPaths[c];
208
208
  if (d)
209
209
  return o.flatMap((f) => {
210
210
  const P = d[f] ?? z(t, e.path ?? "");
211
211
  return this.localizeChild(e, P, a, f, s, !0);
212
212
  });
213
- const n = R(e.path ?? ""), h = y(n), u = this.localizeChildrenAllLocales($(e.children ?? []), r, i, o, s), m = `${s.localizedRouteNamePrefix}${e.name ?? ""}`;
213
+ const n = R(e.path ?? ""), h = y(n), u = this.localizeChildrenAllLocales($(e.children ?? []), i, r, o, s), m = `${s.localizedRouteNamePrefix}${e.name ?? ""}`;
214
214
  return [
215
215
  p(e, {
216
216
  path: h,
@@ -219,8 +219,8 @@ class k {
219
219
  })
220
220
  ];
221
221
  }
222
- localizeChild(e, t, a, o, s, i) {
223
- const r = z(a, e.path ?? ""), c = s.getCustomPath(r, o), d = y(R(c || (e.path ?? ""))), n = c ?? z(t, e.path ?? ""), h = this.localizeChildren($(e.children ?? []), n, r, o, s, i), u = b(e.name, e.path), m = `${s.localizedRouteNamePrefix}${u}-${o}`;
222
+ localizeChild(e, t, a, o, s, r) {
223
+ const i = z(a, e.path ?? ""), c = s.getCustomPath(i, o), d = y(R(c || (e.path ?? ""))), n = c ?? z(t, e.path ?? ""), h = this.localizeChildren($(e.children ?? []), n, i, o, s, r), u = b(e.name, e.path), m = `${s.localizedRouteNamePrefix}${u}-${o}`;
224
224
  return [
225
225
  p(e, {
226
226
  path: d,
@@ -236,25 +236,25 @@ class k {
236
236
  *
237
237
  * The logic matches what used to be duplicated in each strategy's buildRoutePath.
238
238
  */
239
- buildRoutePathForLocales(e, t, a, o, s, i, r) {
239
+ buildRoutePathForLocales(e, t, a, o, s, r, i) {
240
240
  if (o) {
241
- const c = e.includes(r);
242
- return i || !c ? A(e, a, s) : R(a);
241
+ const c = e.includes(i);
242
+ return r || !c ? A(e, a, s) : R(a);
243
243
  }
244
244
  return A(e, t, s);
245
245
  }
246
246
  }
247
247
  class oe extends k {
248
248
  generateVariants(e, t) {
249
- const a = e.path ?? "", o = b(e.name, e.path), s = t.getAllowedLocales(a, o), i = t.getCustomPathsForPage(a, o), r = $(e.children ?? []), c = [];
250
- if (c.push(e), i)
249
+ const a = e.path ?? "", o = b(e.name, e.path), s = t.getAllowedLocales(a, o), r = t.getCustomPathsForPage(a, o), i = $(e.children ?? []), c = [];
250
+ if (c.push(e), r)
251
251
  for (const d of s) {
252
- const n = i[d];
252
+ const n = r[d];
253
253
  if (!n) continue;
254
254
  const h = R(n), u = R(a);
255
255
  if (h === u)
256
256
  continue;
257
- const m = Z(n), f = j(o, d, !0), P = this.localizeChildrenForNoPrefix(r, h, a, a, d, t, 1);
257
+ const m = Z(n), f = j(o, d, !0), P = this.localizeChildrenForNoPrefix(i, h, a, a, d, t, 1);
258
258
  c.push(
259
259
  p(e, {
260
260
  path: m,
@@ -273,12 +273,12 @@ class oe extends k {
273
273
  * - on the first level, custom paths (globalLocaleRoutes/filesLocaleRoutes) are applied;
274
274
  * - on deeper levels, path stays as a segment (item, detail, etc.).
275
275
  */
276
- localizeChildrenForNoPrefix(e, t, a, o, s, i, r) {
276
+ localizeChildrenForNoPrefix(e, t, a, o, s, r, i) {
277
277
  return e.map((c) => {
278
278
  const d = z(a, c.path ?? "");
279
279
  let n, h;
280
- if (r === 1) {
281
- const P = i.getCustomPath(d, s);
280
+ if (i === 1) {
281
+ const P = r.getCustomPath(d, s);
282
282
  if (P) {
283
283
  const L = R(P);
284
284
  n = y(L), h = L;
@@ -296,8 +296,8 @@ class oe extends k {
296
296
  d,
297
297
  o,
298
298
  s,
299
- i,
300
- r + 1
299
+ r,
300
+ i + 1
301
301
  ), m = b(c.name, c.path), f = j(m, s, !0);
302
302
  return p(c, {
303
303
  path: n,
@@ -313,10 +313,10 @@ function le(l) {
313
313
  }
314
314
  class ie extends k {
315
315
  generateVariants(e, t) {
316
- const a = e.path ?? "", o = b(e.name, e.path), s = t.getAllowedLocales(a, o), i = t.getCustomPathsForPage(a, o), r = $(e.children ?? []), c = [];
317
- if (i)
316
+ const a = e.path ?? "", o = b(e.name, e.path), s = t.getAllowedLocales(a, o), r = t.getCustomPathsForPage(a, o), i = $(e.children ?? []), c = [];
317
+ if (r)
318
318
  for (const n of s) {
319
- const h = i[n], u = h ? R(h) : a, m = A(n, u, t.customRegex), f = j(o, n, !!h, t.localizedRouteNamePrefix), P = h ?? a, L = this.localizeChildren(r, P, a, n, t, !0);
319
+ const h = r[n], u = h ? R(h) : a, m = A(n, u, t.customRegex), f = j(o, n, !!h, t.localizedRouteNamePrefix), P = h ?? a, L = this.localizeChildren(i, P, a, n, t, !0);
320
320
  c.push(
321
321
  p(e, {
322
322
  path: m,
@@ -328,7 +328,7 @@ class ie extends k {
328
328
  );
329
329
  }
330
330
  else {
331
- const n = A(s, a, t.customRegex), h = j(o, s[0], !1, t.localizedRouteNamePrefix), u = this.localizeChildrenAllLocales(r, a, a, s, t);
331
+ const n = A(s, a, t.customRegex), h = j(o, s[0], !1, t.localizedRouteNamePrefix), u = this.localizeChildrenAllLocales(i, a, a, s, t);
332
332
  c.push(
333
333
  p(e, {
334
334
  path: n,
@@ -357,14 +357,14 @@ class ie extends k {
357
357
  postProcess(e, t) {
358
358
  const a = e.filter((s) => {
359
359
  if (s.name === "index" && s.path === "/") return !1;
360
- const i = s.path ?? "";
361
- return !!(i && K(i, t.excludePatterns) || t.globalLocaleRoutes[s.name ?? ""] === !1 || /^\/:locale/.test(i) || i === "/");
360
+ const r = s.path ?? "";
361
+ return !!(r && K(r, t.excludePatterns) || t.globalLocaleRoutes[s.name ?? ""] === !1 || /^\/:locale/.test(r) || r === "/");
362
362
  }), o = t.defaultLocale.code;
363
- for (const [s, i] of Object.entries(t.globalLocaleRoutes)) {
364
- if (i === !1 || typeof i != "object") continue;
365
- const r = i[o];
366
- if (!r) continue;
367
- const c = s.startsWith("/") ? s : `/${s}`, d = `/${o}${r.startsWith("/") ? r : `/${r}`}`;
363
+ for (const [s, r] of Object.entries(t.globalLocaleRoutes)) {
364
+ if (r === !1 || typeof r != "object") continue;
365
+ const i = r[o];
366
+ if (!i) continue;
367
+ const c = s.startsWith("/") ? s : `/${s}`, d = `/${o}${i.startsWith("/") ? i : `/${i}`}`;
368
368
  c !== d && a.push({
369
369
  path: c,
370
370
  name: `redirect-${s.replace(/\//g, "-")}`,
@@ -383,19 +383,19 @@ class ie extends k {
383
383
  }
384
384
  class re extends k {
385
385
  generateVariants(e, t) {
386
- const a = e.path ?? "", o = b(e.name, e.path), s = t.getAllowedLocales(a, o), i = t.getCustomPathsForPage(a, o), r = $(e.children ?? []), c = [], d = t.defaultLocale.code;
386
+ const a = e.path ?? "", o = b(e.name, e.path), s = t.getAllowedLocales(a, o), r = t.getCustomPathsForPage(a, o), i = $(e.children ?? []), c = [], d = t.defaultLocale.code;
387
387
  c.push(e);
388
388
  const n = t.locales.filter((u) => s.includes(u.code));
389
389
  if (n.length > 0)
390
- if (i)
390
+ if (r)
391
391
  for (const u of n) {
392
- const m = i[u.code];
392
+ const m = r[u.code];
393
393
  if (m)
394
394
  if (u.code === d) {
395
395
  const f = this.createLocalizedRoute(
396
396
  e,
397
397
  [u.code],
398
- r,
398
+ i,
399
399
  !0,
400
400
  m,
401
401
  t.customRegex,
@@ -408,7 +408,7 @@ class re extends k {
408
408
  const P = this.createLocalizedRoute(
409
409
  e,
410
410
  [u.code],
411
- r,
411
+ i,
412
412
  !0,
413
413
  m,
414
414
  t.customRegex,
@@ -422,7 +422,7 @@ class re extends k {
422
422
  const f = this.createLocalizedRoute(
423
423
  e,
424
424
  [u.code],
425
- r,
425
+ i,
426
426
  !0,
427
427
  m,
428
428
  t.customRegex,
@@ -437,7 +437,7 @@ class re extends k {
437
437
  const f = this.createLocalizedRoute(
438
438
  e,
439
439
  [u.code],
440
- r,
440
+ i,
441
441
  !1,
442
442
  "",
443
443
  t.customRegex,
@@ -453,7 +453,7 @@ class re extends k {
453
453
  const u = n.map((f) => f.code), m = this.createLocalizedRoute(
454
454
  e,
455
455
  u,
456
- r,
456
+ i,
457
457
  !1,
458
458
  "",
459
459
  t.customRegex,
@@ -470,19 +470,19 @@ class re extends k {
470
470
  postProcess(e, t) {
471
471
  const a = [], o = [];
472
472
  for (const s of e) {
473
- const i = s.name ?? "";
474
- typeof i == "string" && i.startsWith(t.localizedRouteNamePrefix) ? o.push(s) : a.push(s);
473
+ const r = s.name ?? "";
474
+ typeof r == "string" && r.startsWith(t.localizedRouteNamePrefix) ? o.push(s) : a.push(s);
475
475
  }
476
476
  return [...a, ...o];
477
477
  }
478
- createLocalizedRoute(e, t, a, o, s = "", i, r = !1, c = !1, d, n) {
478
+ createLocalizedRoute(e, t, a, o, s = "", r, i = !1, c = !1, d, n) {
479
479
  const h = this.buildRoutePathForLocales(
480
480
  t,
481
481
  e.path ?? "",
482
482
  encodeURI(s),
483
483
  o,
484
- i,
485
484
  r,
485
+ i,
486
486
  n.defaultLocale.code
487
487
  );
488
488
  if (!h || !(o && s) && h === e.path || t.length === 0) return null;
@@ -493,7 +493,7 @@ class re extends k {
493
493
  m,
494
494
  o,
495
495
  n.localizedRouteNamePrefix
496
- ), L = r || m !== n.defaultLocale.code, g = t.length === 1 ? this.localizeChildren(a, h, f, m, n, L) : this.localizeChildrenAllLocales(a, h, f, t, n);
496
+ ), L = i || m !== n.defaultLocale.code, g = t.length === 1 ? this.localizeChildren(a, h, f, m, n, L) : this.localizeChildrenAllLocales(a, h, f, t, n);
497
497
  return p(e, {
498
498
  path: h,
499
499
  name: P,
@@ -505,10 +505,10 @@ class re extends k {
505
505
  }
506
506
  class ce extends k {
507
507
  generateVariants(e, t) {
508
- const a = e.path ?? "", o = b(e.name, e.path), s = t.getAllowedLocales(a, o), i = t.getCustomPathsForPage(a, o), r = $(e.children ?? []), c = [], d = t.defaultLocale.code;
508
+ const a = e.path ?? "", o = b(e.name, e.path), s = t.getAllowedLocales(a, o), r = t.getCustomPathsForPage(a, o), i = $(e.children ?? []), c = [], d = t.defaultLocale.code;
509
509
  if (s.includes(d)) {
510
- const u = i?.[d], m = u ? R(u) : a, f = u ? { [d]: u } : {}, P = this.createLocalizedChildren(
511
- r,
510
+ const u = r?.[d], m = u ? R(u) : a, f = u ? { [d]: u } : {}, P = this.createLocalizedChildren(
511
+ i,
512
512
  a,
513
513
  [d],
514
514
  !1,
@@ -527,14 +527,14 @@ class ce extends k {
527
527
  }
528
528
  const n = t.locales.filter((u) => s.includes(u.code) && u.code !== d);
529
529
  if (n.length)
530
- if (i)
530
+ if (r)
531
531
  for (const u of n) {
532
- const m = i[u.code];
532
+ const m = r[u.code];
533
533
  if (m) {
534
534
  const f = this.createLocalizedRoute(
535
535
  e,
536
536
  [u.code],
537
- r,
537
+ i,
538
538
  !0,
539
539
  m,
540
540
  t.customRegex,
@@ -548,7 +548,7 @@ class ce extends k {
548
548
  const f = this.createLocalizedRoute(
549
549
  e,
550
550
  [u.code],
551
- r,
551
+ i,
552
552
  !1,
553
553
  "",
554
554
  t.customRegex,
@@ -564,7 +564,7 @@ class ce extends k {
564
564
  const u = n.map((f) => f.code), m = this.createLocalizedRoute(
565
565
  e,
566
566
  u,
567
- r,
567
+ i,
568
568
  !1,
569
569
  "",
570
570
  t.customRegex,
@@ -580,9 +580,9 @@ class ce extends k {
580
580
  }
581
581
  postProcess(e, t) {
582
582
  const a = [], o = [];
583
- for (const i of e) {
584
- const r = i.name ?? "";
585
- typeof r == "string" && r.startsWith(t.localizedRouteNamePrefix) ? o.push(i) : a.push(i);
583
+ for (const r of e) {
584
+ const i = r.name ?? "";
585
+ typeof i == "string" && i.startsWith(t.localizedRouteNamePrefix) ? o.push(r) : a.push(r);
586
586
  }
587
587
  const s = [...a, ...o];
588
588
  return t.fallbackRedirectComponentPath && s.push({
@@ -594,12 +594,12 @@ class ce extends k {
594
594
  }
595
595
  }), s;
596
596
  }
597
- createLocalizedChildren(e, t, a, o = !0, s = !1, i = !1, r = {}, c) {
597
+ createLocalizedChildren(e, t, a, o = !0, s = !1, r = !1, i = {}, c) {
598
598
  return e.flatMap(
599
- (d) => this.createLocalizedVariants(d, t, a, o, s, i, r, c)
599
+ (d) => this.createLocalizedVariants(d, t, a, o, s, r, i, c)
600
600
  );
601
601
  }
602
- createLocalizedVariants(e, t, a, o, s, i = !1, r, c) {
602
+ createLocalizedVariants(e, t, a, o, s, r = !1, i, c) {
603
603
  const d = R(e.path ?? ""), n = z(t, e.path ?? ""), h = F(n), u = c.localizedPaths[h], m = !!u, f = [];
604
604
  if (!m) {
605
605
  const P = y(d), L = this.createLocalizedChildren(
@@ -608,10 +608,10 @@ class ce extends k {
608
608
  a,
609
609
  o,
610
610
  s,
611
- i,
612
611
  r,
612
+ i,
613
613
  c
614
- ), g = this.buildChildRouteName(e.name, i, c);
614
+ ), g = this.buildChildRouteName(e.name, r, c);
615
615
  return f.push(
616
616
  p(e, {
617
617
  path: P,
@@ -621,7 +621,7 @@ class ce extends k {
621
621
  ), f;
622
622
  }
623
623
  for (const P of a) {
624
- const L = r?.[P], g = !!L, C = u?.[P];
624
+ const L = i?.[P], g = !!L, C = u?.[P];
625
625
  let x = R(C || (e.path ?? ""));
626
626
  g && L && (C ? x = R(C) : x = z(L, e.path ?? ""));
627
627
  const v = H(P, c.defaultLocale, s) ? A(P, x, c.customRegex) : x, T = y(v), W = C ? R(C) : g ? L : z(t, e.path ?? ""), V = this.createLocalizedChildren(
@@ -632,7 +632,7 @@ class ce extends k {
632
632
  s,
633
633
  P,
634
634
  {
635
- ...r,
635
+ ...i,
636
636
  [P]: W
637
637
  },
638
638
  c
@@ -656,14 +656,14 @@ class ce extends k {
656
656
  buildChildRouteName(e, t, a) {
657
657
  return t === !0 ? `${a.localizedRouteNamePrefix}${e}` : typeof t == "string" ? `${a.localizedRouteNamePrefix}${e}-${t}` : e;
658
658
  }
659
- createLocalizedRoute(e, t, a, o, s = "", i, r = !1, c = !1, d, n) {
659
+ createLocalizedRoute(e, t, a, o, s = "", r, i = !1, c = !1, d, n) {
660
660
  const h = this.buildRoutePathForLocales(
661
661
  t,
662
662
  e.path ?? "",
663
663
  encodeURI(s),
664
664
  o,
665
- i,
666
665
  r,
666
+ i,
667
667
  n.defaultLocale.code
668
668
  );
669
669
  if (!h || h === e.path || t.length === 0) return null;
@@ -718,8 +718,8 @@ class de {
718
718
  defaultLocaleCode: a,
719
719
  strategy: o,
720
720
  globalLocaleRoutes: s,
721
- filesLocaleRoutes: i = {},
722
- routeLocales: r = {},
721
+ filesLocaleRoutes: r = {},
722
+ routeLocales: i = {},
723
723
  noPrefixRedirect: c,
724
724
  excludePatterns: d,
725
725
  localizedRouteNamePrefix: n = "localized-",
@@ -740,7 +740,7 @@ class de {
740
740
  } else
741
741
  f[L] = g;
742
742
  }
743
- this.globalLocaleRoutes = f, this.rawGlobalLocaleRoutes = s ?? {}, this.filesLocaleRoutes = i ?? {}, this.routeLocales = r ?? {};
743
+ this.globalLocaleRoutes = f, this.rawGlobalLocaleRoutes = s ?? {}, this.filesLocaleRoutes = r ?? {}, this.routeLocales = i ?? {};
744
744
  }
745
745
  computeActiveLocaleCodes() {
746
746
  return this.locales.filter((e) => e.code !== this.defaultLocale.code || D(this.strategy) || O(this.strategy)).map((e) => e.code);
@@ -763,10 +763,10 @@ class de {
763
763
  });
764
764
  this.localizedPaths = t.localizedPaths;
765
765
  const a = ne(this.strategy), o = [...e], s = [];
766
- for (const r of o)
767
- s.push(...a.processPage(r, t));
768
- const i = a.postProcess(s, t);
769
- e.length = 0, e.push(...i);
766
+ for (const i of o)
767
+ s.push(...a.processPage(i, t));
768
+ const r = a.postProcess(s, t);
769
+ e.length = 0, e.push(...r);
770
770
  }
771
771
  extractLocalizedPaths(e, t = "") {
772
772
  return S(e, this.globalLocaleRoutes, this.filesLocaleRoutes, t);
@@ -776,9 +776,9 @@ class de {
776
776
  */
777
777
  ensureTranslationFilesExist(e, t, a, o) {
778
778
  this.locales.forEach((s) => {
779
- const i = N.join(a, t, `${s.code}.json`);
780
- this.ensureFileExists(i), o || e.forEach((r) => {
781
- const c = N.join(a, t, "pages", `${r}/${s.code}.json`);
779
+ const r = N.join(a, t, `${s.code}.json`);
780
+ this.ensureFileExists(r), o || e.forEach((i) => {
781
+ const c = N.join(a, t, "pages", `${i}/${s.code}.json`);
782
782
  this.ensureFileExists(c);
783
783
  });
784
784
  });
@@ -798,8 +798,8 @@ class de {
798
798
  resolveLocalizedPath(e, t) {
799
799
  const a = w(e), o = y(a) || "/";
800
800
  let s;
801
- const i = this.globalLocaleRoutes[o], r = this.globalLocaleRoutes[a];
802
- i && typeof i == "object" && !Array.isArray(i) ? s = i[t] : r && typeof r == "object" && !Array.isArray(r) && (s = r[t]);
801
+ const r = this.globalLocaleRoutes[o], i = this.globalLocaleRoutes[a];
802
+ r && typeof r == "object" && !Array.isArray(r) ? s = r[t] : i && typeof i == "object" && !Array.isArray(i) && (s = i[t]);
803
803
  const c = !!s, d = s ? R(s) : R(a) || "";
804
804
  let n = !1;
805
805
  if (this.strategy === "no_prefix" ? n = !1 : this.strategy === "prefix" || this.strategy === "prefix_and_default" ? n = !0 : this.strategy === "prefix_except_default" && (n = t !== this.defaultLocale.code), t === this.defaultLocale.code && !c && (this.strategy === "prefix_except_default" || this.strategy === "no_prefix") && (n = !1), !n)
@@ -808,14 +808,18 @@ class de {
808
808
  return h ? R(`/${t}/${h}`) : `/${t}`;
809
809
  }
810
810
  /**
811
- * Generates the list of data.json routes for prerender (general + per-page per locale).
811
+ * Generates the list of data.json routes for prerender.
812
+ * When disablePageLocales is true, only index routes are generated (all pages share root translations).
813
+ * Otherwise, generates index + per-page routes for each locale.
812
814
  */
813
815
  generateDataRoutes(e, t, a) {
814
- const o = [], s = e.map((i) => i.name).filter((i) => typeof i == "string" && i.length > 0);
815
- for (const i of this.locales)
816
- if (o.push(`/${t}/general/${i.code}/data.json`), !a)
817
- for (const r of s)
818
- o.push(`/${t}/${r}/${i.code}/data.json`);
816
+ const o = [];
817
+ for (const s of this.locales)
818
+ if (o.push(`/${t}/index/${s.code}/data.json`), !a) {
819
+ const r = e.map((i) => i.name).filter((i) => typeof i == "string" && i.length > 0);
820
+ for (const i of r)
821
+ o.push(`/${t}/${i}/${s.code}/data.json`);
822
+ }
819
823
  return o;
820
824
  }
821
825
  }
@@ -50,7 +50,9 @@ export declare class RouteGenerator {
50
50
  */
51
51
  resolveLocalizedPath(originalPath: string, localeCode: string): string;
52
52
  /**
53
- * Generates the list of data.json routes for prerender (general + per-page per locale).
53
+ * Generates the list of data.json routes for prerender.
54
+ * When disablePageLocales is true, only index routes are generated (all pages share root translations).
55
+ * Otherwise, generates index + per-page routes for each locale.
54
56
  */
55
57
  generateDataRoutes(pages: NuxtPage[], apiBaseUrl: string, disablePageLocales: boolean): string[];
56
58
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@i18n-micro/route-strategy",
3
- "version": "1.1.3",
3
+ "version": "1.1.4",
4
4
  "description": "Locale-aware route generator for Nuxt i18n micro",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
@@ -55,8 +55,8 @@
55
55
  "sideEffects": false,
56
56
  "dependencies": {
57
57
  "@nuxt/schema": "^3.18.1 || ^4.0.0",
58
- "@i18n-micro/core": "1.1.3",
59
- "@i18n-micro/types": "1.1.3"
58
+ "@i18n-micro/core": "1.2.0",
59
+ "@i18n-micro/types": "1.1.6"
60
60
  },
61
61
  "devDependencies": {
62
62
  "@types/jest": "^29.5.14",