nuxt-i18n-micro 1.61.0 → 1.62.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.
@@ -1 +1 @@
1
- import{_ as a,o as i,c as u,a as e,t as r,b as c,w as l,d,e as p}from"./C9njAg9E.js";import{u as f}from"./EwNUkbJF.js";const m={class:"antialiased bg-white dark:bg-black dark:text-white font-sans grid min-h-screen overflow-hidden place-content-center text-black"},g={class:"max-w-520px text-center z-20"},h=["textContent"],b=["textContent"],x={class:"flex items-center justify-center w-full"},y={__name:"error-404",props:{appName:{type:String,default:"Nuxt"},version:{type:String,default:""},statusCode:{type:Number,default:404},statusMessage:{type:String,default:"Not Found"},description:{type:String,default:"Sorry, the page you are looking for could not be found."},backHome:{type:String,default:"Go back home"}},setup(t){const n=t;return f({title:`${n.statusCode} - ${n.statusMessage} | ${n.appName}`,script:[{children:`!function(){const e=document.createElement("link").relList;if(!(e&&e.supports&&e.supports("modulepreload"))){for(const e of document.querySelectorAll('link[rel="modulepreload"]'))r(e);new MutationObserver((e=>{for(const o of e)if("childList"===o.type)for(const e of o.addedNodes)"LINK"===e.tagName&&"modulepreload"===e.rel&&r(e)})).observe(document,{childList:!0,subtree:!0})}function r(e){if(e.ep)return;e.ep=!0;const r=function(e){const r={};return e.integrity&&(r.integrity=e.integrity),e.referrerPolicy&&(r.referrerPolicy=e.referrerPolicy),"use-credentials"===e.crossOrigin?r.credentials="include":"anonymous"===e.crossOrigin?r.credentials="omit":r.credentials="same-origin",r}(e);fetch(e.href,r)}}();`}],style:[{children:'*,:after,:before{border-color:var(--un-default-border-color,#e5e7eb);border-style:solid;border-width:0;box-sizing:border-box}:after,:before{--un-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-moz-tab-size:4;tab-size:4;-webkit-tap-highlight-color:transparent}body{line-height:inherit;margin:0}h1{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}h1,p{margin:0}*,:after,:before{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 transparent;--un-ring-shadow:0 0 transparent;--un-shadow-inset: ;--un-shadow:0 0 transparent;--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgba(147,197,253,.5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }'}]}),(k,o)=>{const s=p;return i(),u("div",m,[o[0]||(o[0]=e("div",{class:"fixed left-0 right-0 spotlight z-10"},null,-1)),e("div",g,[e("h1",{class:"font-medium mb-8 sm:text-10xl text-8xl",textContent:r(t.statusCode)},null,8,h),e("p",{class:"font-light leading-tight mb-16 px-8 sm:px-0 sm:text-4xl text-xl",textContent:r(t.description)},null,8,b),e("div",x,[c(s,{to:"/",class:"cursor-pointer gradient-border px-4 py-2 sm:px-6 sm:py-3 sm:text-xl text-md"},{default:l(()=>[d(r(t.backHome),1)]),_:1})])])])}}},v=a(y,[["__scopeId","data-v-3074ece5"]]);export{v as default};
1
+ import{_ as a,o as i,c as u,a as e,t as r,b as c,w as l,d,e as p}from"./Ddb0iCRU.js";import{u as f}from"./AXE8DZQI.js";const m={class:"antialiased bg-white dark:bg-black dark:text-white font-sans grid min-h-screen overflow-hidden place-content-center text-black"},g={class:"max-w-520px text-center z-20"},h=["textContent"],b=["textContent"],x={class:"flex items-center justify-center w-full"},y={__name:"error-404",props:{appName:{type:String,default:"Nuxt"},version:{type:String,default:""},statusCode:{type:Number,default:404},statusMessage:{type:String,default:"Not Found"},description:{type:String,default:"Sorry, the page you are looking for could not be found."},backHome:{type:String,default:"Go back home"}},setup(t){const n=t;return f({title:`${n.statusCode} - ${n.statusMessage} | ${n.appName}`,script:[{children:`!function(){const e=document.createElement("link").relList;if(!(e&&e.supports&&e.supports("modulepreload"))){for(const e of document.querySelectorAll('link[rel="modulepreload"]'))r(e);new MutationObserver((e=>{for(const o of e)if("childList"===o.type)for(const e of o.addedNodes)"LINK"===e.tagName&&"modulepreload"===e.rel&&r(e)})).observe(document,{childList:!0,subtree:!0})}function r(e){if(e.ep)return;e.ep=!0;const r=function(e){const r={};return e.integrity&&(r.integrity=e.integrity),e.referrerPolicy&&(r.referrerPolicy=e.referrerPolicy),"use-credentials"===e.crossOrigin?r.credentials="include":"anonymous"===e.crossOrigin?r.credentials="omit":r.credentials="same-origin",r}(e);fetch(e.href,r)}}();`}],style:[{children:'*,:after,:before{border-color:var(--un-default-border-color,#e5e7eb);border-style:solid;border-width:0;box-sizing:border-box}:after,:before{--un-content:""}html{line-height:1.5;-webkit-text-size-adjust:100%;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-moz-tab-size:4;tab-size:4;-webkit-tap-highlight-color:transparent}body{line-height:inherit;margin:0}h1{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}h1,p{margin:0}*,:after,:before{--un-rotate:0;--un-rotate-x:0;--un-rotate-y:0;--un-rotate-z:0;--un-scale-x:1;--un-scale-y:1;--un-scale-z:1;--un-skew-x:0;--un-skew-y:0;--un-translate-x:0;--un-translate-y:0;--un-translate-z:0;--un-pan-x: ;--un-pan-y: ;--un-pinch-zoom: ;--un-scroll-snap-strictness:proximity;--un-ordinal: ;--un-slashed-zero: ;--un-numeric-figure: ;--un-numeric-spacing: ;--un-numeric-fraction: ;--un-border-spacing-x:0;--un-border-spacing-y:0;--un-ring-offset-shadow:0 0 transparent;--un-ring-shadow:0 0 transparent;--un-shadow-inset: ;--un-shadow:0 0 transparent;--un-ring-inset: ;--un-ring-offset-width:0px;--un-ring-offset-color:#fff;--un-ring-width:0px;--un-ring-color:rgba(147,197,253,.5);--un-blur: ;--un-brightness: ;--un-contrast: ;--un-drop-shadow: ;--un-grayscale: ;--un-hue-rotate: ;--un-invert: ;--un-saturate: ;--un-sepia: ;--un-backdrop-blur: ;--un-backdrop-brightness: ;--un-backdrop-contrast: ;--un-backdrop-grayscale: ;--un-backdrop-hue-rotate: ;--un-backdrop-invert: ;--un-backdrop-opacity: ;--un-backdrop-saturate: ;--un-backdrop-sepia: }'}]}),(k,o)=>{const s=p;return i(),u("div",m,[o[0]||(o[0]=e("div",{class:"fixed left-0 right-0 spotlight z-10"},null,-1)),e("div",g,[e("h1",{class:"font-medium mb-8 sm:text-10xl text-8xl",textContent:r(t.statusCode)},null,8,h),e("p",{class:"font-light leading-tight mb-16 px-8 sm:px-0 sm:text-4xl text-xl",textContent:r(t.description)},null,8,b),e("div",x,[c(s,{to:"/",class:"cursor-pointer gradient-border px-4 py-2 sm:px-6 sm:py-3 sm:text-xl text-md"},{default:l(()=>[d(r(t.backHome),1)]),_:1})])])])}}},v=a(y,[["__scopeId","data-v-c1463376"]]);export{v as default};
@@ -1 +1 @@
1
- {"id":"019df560-5b4f-4d25-8ca1-a8cad935e3d2","timestamp":1736953866014}
1
+ {"id":"c8228d06-262a-456f-a053-aa7994ec21bb","timestamp":1737022232581}
@@ -0,0 +1 @@
1
+ {"id":"c8228d06-262a-456f-a053-aa7994ec21bb","timestamp":1737022232581,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
@@ -0,0 +1 @@
1
+ .spotlight[data-v-c1463376]{background:linear-gradient(45deg,#00dc82,#36e4da 50%,#0047e1);bottom:-30vh;filter:blur(20vh);height:40vh}.gradient-border[data-v-c1463376]{-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-radius:.5rem;position:relative}@media (prefers-color-scheme:light){.gradient-border[data-v-c1463376]{background-color:#ffffff4d}.gradient-border[data-v-c1463376]:before{background:linear-gradient(90deg,#e2e2e2,#e2e2e2 25%,#00dc82,#36e4da 75%,#0047e1)}}@media (prefers-color-scheme:dark){.gradient-border[data-v-c1463376]{background-color:#1414144d}.gradient-border[data-v-c1463376]:before{background:linear-gradient(90deg,#303030,#303030 25%,#00dc82,#36e4da 75%,#0047e1)}}.gradient-border[data-v-c1463376]:before{background-size:400% auto;border-radius:.5rem;bottom:0;content:"";left:0;-webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask-composite:exclude;opacity:.5;padding:2px;position:absolute;right:0;top:0;transition:background-position .3s ease-in-out,opacity .2s ease-in-out;width:100%}.gradient-border[data-v-c1463376]:hover:before{background-position:-50% 0;opacity:1}.fixed[data-v-c1463376]{position:fixed}.left-0[data-v-c1463376]{left:0}.right-0[data-v-c1463376]{right:0}.z-10[data-v-c1463376]{z-index:10}.z-20[data-v-c1463376]{z-index:20}.grid[data-v-c1463376]{display:grid}.mb-16[data-v-c1463376]{margin-bottom:4rem}.mb-8[data-v-c1463376]{margin-bottom:2rem}.max-w-520px[data-v-c1463376]{max-width:520px}.min-h-screen[data-v-c1463376]{min-height:100vh}.w-full[data-v-c1463376]{width:100%}.flex[data-v-c1463376]{display:flex}.cursor-pointer[data-v-c1463376]{cursor:pointer}.place-content-center[data-v-c1463376]{place-content:center}.items-center[data-v-c1463376]{align-items:center}.justify-center[data-v-c1463376]{justify-content:center}.overflow-hidden[data-v-c1463376]{overflow:hidden}.bg-white[data-v-c1463376]{--un-bg-opacity:1;background-color:rgb(255 255 255/var(--un-bg-opacity))}.px-4[data-v-c1463376]{padding-left:1rem;padding-right:1rem}.px-8[data-v-c1463376]{padding-left:2rem;padding-right:2rem}.py-2[data-v-c1463376]{padding-bottom:.5rem;padding-top:.5rem}.text-center[data-v-c1463376]{text-align:center}.text-8xl[data-v-c1463376]{font-size:6rem;line-height:1}.text-xl[data-v-c1463376]{font-size:1.25rem;line-height:1.75rem}.text-black[data-v-c1463376]{--un-text-opacity:1;color:rgb(0 0 0/var(--un-text-opacity))}.font-light[data-v-c1463376]{font-weight:300}.font-medium[data-v-c1463376]{font-weight:500}.leading-tight[data-v-c1463376]{line-height:1.25}.font-sans[data-v-c1463376]{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.antialiased[data-v-c1463376]{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media (prefers-color-scheme:dark){.dark\:bg-black[data-v-c1463376]{--un-bg-opacity:1;background-color:rgb(0 0 0/var(--un-bg-opacity))}.dark\:text-white[data-v-c1463376]{--un-text-opacity:1;color:rgb(255 255 255/var(--un-text-opacity))}}@media (min-width:640px){.sm\:px-0[data-v-c1463376]{padding-left:0;padding-right:0}.sm\:px-6[data-v-c1463376]{padding-left:1.5rem;padding-right:1.5rem}.sm\:py-3[data-v-c1463376]{padding-bottom:.75rem;padding-top:.75rem}.sm\:text-4xl[data-v-c1463376]{font-size:2.25rem;line-height:2.5rem}.sm\:text-xl[data-v-c1463376]{font-size:1.25rem;line-height:1.75rem}}
@@ -0,0 +1 @@
1
+ .spotlight[data-v-05ddf355]{background:linear-gradient(45deg,#00dc82,#36e4da 50%,#0047e1);filter:blur(20vh)}.fixed[data-v-05ddf355]{position:fixed}.-bottom-1\/2[data-v-05ddf355]{bottom:-50%}.left-0[data-v-05ddf355]{left:0}.right-0[data-v-05ddf355]{right:0}.grid[data-v-05ddf355]{display:grid}.mb-16[data-v-05ddf355]{margin-bottom:4rem}.mb-8[data-v-05ddf355]{margin-bottom:2rem}.h-1\/2[data-v-05ddf355]{height:50%}.max-w-520px[data-v-05ddf355]{max-width:520px}.min-h-screen[data-v-05ddf355]{min-height:100vh}.place-content-center[data-v-05ddf355]{place-content:center}.overflow-hidden[data-v-05ddf355]{overflow:hidden}.bg-white[data-v-05ddf355]{--un-bg-opacity:1;background-color:rgb(255 255 255/var(--un-bg-opacity))}.px-8[data-v-05ddf355]{padding-left:2rem;padding-right:2rem}.text-center[data-v-05ddf355]{text-align:center}.text-8xl[data-v-05ddf355]{font-size:6rem;line-height:1}.text-xl[data-v-05ddf355]{font-size:1.25rem;line-height:1.75rem}.text-black[data-v-05ddf355]{--un-text-opacity:1;color:rgb(0 0 0/var(--un-text-opacity))}.font-light[data-v-05ddf355]{font-weight:300}.font-medium[data-v-05ddf355]{font-weight:500}.leading-tight[data-v-05ddf355]{line-height:1.25}.font-sans[data-v-05ddf355]{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.antialiased[data-v-05ddf355]{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media (prefers-color-scheme:dark){.dark\:bg-black[data-v-05ddf355]{--un-bg-opacity:1;background-color:rgb(0 0 0/var(--un-bg-opacity))}.dark\:text-white[data-v-05ddf355]{--un-text-opacity:1;color:rgb(255 255 255/var(--un-text-opacity))}}@media (min-width:640px){.sm\:px-0[data-v-05ddf355]{padding-left:0;padding-right:0}.sm\:text-4xl[data-v-05ddf355]{font-size:2.25rem;line-height:2.5rem}}
@@ -1,12 +1,12 @@
1
1
  <!DOCTYPE html><html data-capo=""><head><meta charset="utf-8">
2
2
  <meta name="viewport" content="width=device-width, initial-scale=1">
3
3
  <link rel="stylesheet" href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/entry.B5pGkSSX.css" crossorigin>
4
- <link rel="modulepreload" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/C9njAg9E.js">
4
+ <link rel="modulepreload" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/Ddb0iCRU.js">
5
5
  <link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/CG55hV0U.js">
6
- <link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-404.C8aNxDEl.css">
7
- <link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/BIRJeTBr.js">
8
- <link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/EwNUkbJF.js">
9
- <link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-500.C2JGrgZX.css">
10
- <link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/DuZjM2Ym.js">
11
- <script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/C9njAg9E.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},1736953870973,false]</script>
12
- <script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"019df560-5b4f-4d25-8ca1-a8cad935e3d2",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
6
+ <link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-404.vh32VtAd.css">
7
+ <link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/Deg2o1hP.js">
8
+ <link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/AXE8DZQI.js">
9
+ <link rel="prefetch" as="style" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/error-500.EgQ3RNLZ.css">
10
+ <link rel="prefetch" as="script" crossorigin href="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/D9gx-VEt.js">
11
+ <script type="module" src="/__NUXT_DEVTOOLS_I18N_BASE__/_nuxt/Ddb0iCRU.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},1737022239892,false]</script>
12
+ <script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__NUXT_DEVTOOLS_I18N_BASE__/",buildId:"c8228d06-262a-456f-a053-aa7994ec21bb",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script></body></html>
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "nuxt-i18n-micro",
3
3
  "configKey": "i18n",
4
- "version": "1.61.0",
4
+ "version": "1.62.0",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "0.8.4",
7
7
  "unbuild": "2.0.0"
package/dist/module.mjs CHANGED
@@ -1,8 +1,10 @@
1
1
  import path, { resolve } from 'node:path';
2
2
  import * as fs from 'node:fs';
3
3
  import fs__default, { readFileSync, existsSync, mkdirSync, writeFileSync } from 'node:fs';
4
+ import { readFile } from 'node:fs/promises';
4
5
  import { useNuxt, defineNuxtModule, useLogger, createResolver, addTemplate, addImportsDir, addPlugin, addServerHandler, addComponentsDir, addTypeTemplate, extendPages, addPrerenderRoutes } from '@nuxt/kit';
5
6
  import { watch } from 'chokidar';
7
+ import { globby } from 'globby';
6
8
  import { fileURLToPath } from 'node:url';
7
9
  import { onDevToolsInitialized, extendServerRpc } from '@nuxt/devtools-kit';
8
10
  import sirv from 'sirv';
@@ -22,6 +24,9 @@ function setupDevToolsUI(options, resolve2) {
22
24
  if (clientDirExists) {
23
25
  nuxt.hook("vite:serverCreated", (server) => {
24
26
  const indexHtmlPath = path.join(clientDir, "index.html");
27
+ if (!fs.existsSync(indexHtmlPath)) {
28
+ return;
29
+ }
25
30
  const indexContent = fs.readFileSync(indexHtmlPath);
26
31
  const handleStatic = sirv(clientDir, {
27
32
  dev: true,
@@ -374,6 +379,34 @@ declare module '#app' {
374
379
 
375
380
  export {}`;
376
381
  }
382
+ function deepMerge(target, source) {
383
+ if (typeof source !== "object" || source === null) {
384
+ return target === void 0 ? source : target;
385
+ }
386
+ if (Array.isArray(target)) {
387
+ return target;
388
+ }
389
+ if (source instanceof Object) {
390
+ if (!(target instanceof Object) || Array.isArray(target)) {
391
+ target = {};
392
+ }
393
+ for (const key in source) {
394
+ if (key === "__proto__" || key === "constructor")
395
+ continue;
396
+ if (target !== null && typeof target[key] === "object" && target[key] !== null) {
397
+ target[key] = deepMerge(
398
+ target[key],
399
+ source[key]
400
+ );
401
+ } else {
402
+ if (target instanceof Object && !(key in target)) {
403
+ target[key] = source[key];
404
+ }
405
+ }
406
+ }
407
+ }
408
+ return target;
409
+ }
377
410
  const module = defineNuxtModule({
378
411
  meta: {
379
412
  name: "nuxt-i18n-micro",
@@ -412,6 +445,7 @@ const module = defineNuxtModule({
412
445
  customRegexMatcher: void 0
413
446
  },
414
447
  async setup(options, nuxt) {
448
+ const defaultLocale = process.env.DEFAULT_LOCALE ?? options.defaultLocale ?? "en";
415
449
  const isSSG = nuxt.options._generate;
416
450
  const isCloudflarePages = nuxt.options.nitro.preset === "cloudflare_pages" || process.env.NITRO_PRESET === "cloudflare-pages";
417
451
  const logger = useLogger("nuxt-i18n-micro");
@@ -426,7 +460,7 @@ const module = defineNuxtModule({
426
460
  const resolver = createResolver(import.meta.url);
427
461
  const rootDirs = nuxt.options._layers.map((layer) => layer.config.rootDir).reverse();
428
462
  const localeManager = new LocaleManager(options, rootDirs);
429
- const pageManager = new PageManager(localeManager.locales, options.defaultLocale, options.strategy, options.globalLocaleRoutes);
463
+ const pageManager = new PageManager(localeManager.locales, defaultLocale, options.strategy, options.globalLocaleRoutes);
430
464
  addTemplate({
431
465
  filename: "i18n.plural.mjs",
432
466
  write: true,
@@ -441,7 +475,7 @@ const module = defineNuxtModule({
441
475
  define: options.define ?? true,
442
476
  disableWatcher: options.disableWatcher ?? false,
443
477
  disableUpdater: options.disableUpdater ?? false,
444
- defaultLocale: options.defaultLocale ?? "en",
478
+ defaultLocale,
445
479
  translationDir: options.translationDir ?? "locales",
446
480
  localeCookie: options.localeCookie ?? "user-locale",
447
481
  autoDetectLanguage: options.autoDetectLanguage ?? true,
@@ -505,7 +539,7 @@ const module = defineNuxtModule({
505
539
  }
506
540
  addServerHandler({
507
541
  route: `/${apiBaseUrl}/:page/:locale/data.json`,
508
- handler: resolver.resolve("./runtime/server/middleware/i18n-loader")
542
+ handler: resolver.resolve("./runtime/server/routes/get")
509
543
  });
510
544
  await addComponentsDir({
511
545
  path: resolver.resolve("./runtime/components"),
@@ -519,27 +553,8 @@ const module = defineNuxtModule({
519
553
  });
520
554
  }
521
555
  extendPages((pages) => {
522
- if (isNoPrefixStrategy(options.strategy)) {
523
- return;
524
- }
525
- const pagesNames = pages.map((page) => page.name).filter((name) => name !== void 0 && (!options.routesLocaleLinks || !options.routesLocaleLinks[name]));
526
- if (!options.disableWatcher) {
527
- localeManager.ensureTranslationFilesExist(pagesNames, options.translationDir, nuxt.options.rootDir);
528
- }
529
- pageManager.extendPages(pages, options.customRegexMatcher, isCloudflarePages);
530
- if (isPrefixStrategy(options.strategy) && !isCloudflarePages) {
531
- const fallbackRoute = {
532
- path: "/:pathMatch(.*)*",
533
- name: "custom-fallback-route",
534
- file: resolver.resolve("./runtime/components/locale-redirect.vue"),
535
- meta: {
536
- globalLocaleRoutes: options.globalLocaleRoutes
537
- }
538
- };
539
- pages.push(fallbackRoute);
540
- }
541
- nuxt.options.generate.routes = Array.isArray(nuxt.options.generate.routes) ? nuxt.options.generate.routes : [];
542
556
  const prerenderRoutes = [];
557
+ const pagesNames = pages.map((page) => page.name).filter((name) => name !== void 0 && (!options.routesLocaleLinks || !options.routesLocaleLinks[name]));
543
558
  localeManager.locales.forEach((locale) => {
544
559
  if (!options.disablePageLocales) {
545
560
  pagesNames.forEach((name) => {
@@ -548,36 +563,61 @@ const module = defineNuxtModule({
548
563
  }
549
564
  prerenderRoutes.push(`/${apiBaseUrl}/general/${locale.code}/data.json`);
550
565
  });
551
- if (isCloudflarePages) {
552
- const processPageWithChildren = (page, parentPath = "") => {
553
- if (!page.path)
554
- return;
555
- const fullPath = path.posix.normalize(`${parentPath}/${page.path}`);
556
- const localeSegmentMatch = fullPath.match(/:locale\(([^)]+)\)/);
557
- if (localeSegmentMatch) {
558
- const availableLocales = localeSegmentMatch[1].split("|");
559
- localeManager.locales.forEach((locale) => {
560
- const localeCode = locale.code;
561
- if (availableLocales.includes(localeCode)) {
562
- let localizedPath = fullPath;
563
- localizedPath = localizedPath.replace(/:locale\([^)]+\)/, localeCode);
564
- prerenderRoutes.push(localizedPath);
565
- }
566
- });
567
- } else {
568
- prerenderRoutes.push(fullPath);
569
- }
570
- if (page.children && page.children.length) {
571
- page.children.forEach((childPage) => processPageWithChildren(childPage, fullPath));
572
- }
573
- };
574
- pages.forEach((page) => {
575
- processPageWithChildren(page);
576
- });
566
+ if (!isNoPrefixStrategy(options.strategy)) {
567
+ if (!options.disableWatcher) {
568
+ localeManager.ensureTranslationFilesExist(pagesNames, options.translationDir, nuxt.options.rootDir);
569
+ }
570
+ pageManager.extendPages(pages, options.customRegexMatcher, isCloudflarePages);
571
+ if (isPrefixStrategy(options.strategy) && !isCloudflarePages) {
572
+ const fallbackRoute = {
573
+ path: "/:pathMatch(.*)*",
574
+ name: "custom-fallback-route",
575
+ file: resolver.resolve("./runtime/components/locale-redirect.vue"),
576
+ meta: {
577
+ globalLocaleRoutes: options.globalLocaleRoutes
578
+ }
579
+ };
580
+ pages.push(fallbackRoute);
581
+ }
582
+ nuxt.options.generate.routes = Array.isArray(nuxt.options.generate.routes) ? nuxt.options.generate.routes : [];
583
+ if (isCloudflarePages) {
584
+ const processPageWithChildren = (page, parentPath = "") => {
585
+ if (!page.path)
586
+ return;
587
+ const fullPath = path.posix.normalize(`${parentPath}/${page.path}`);
588
+ const localeSegmentMatch = fullPath.match(/:locale\(([^)]+)\)/);
589
+ if (localeSegmentMatch) {
590
+ const availableLocales = localeSegmentMatch[1].split("|");
591
+ localeManager.locales.forEach((locale) => {
592
+ const localeCode = locale.code;
593
+ if (availableLocales.includes(localeCode)) {
594
+ let localizedPath = fullPath;
595
+ localizedPath = localizedPath.replace(/:locale\([^)]+\)/, localeCode);
596
+ prerenderRoutes.push(localizedPath);
597
+ }
598
+ });
599
+ } else {
600
+ prerenderRoutes.push(fullPath);
601
+ }
602
+ if (page.children && page.children.length) {
603
+ page.children.forEach((childPage) => processPageWithChildren(childPage, fullPath));
604
+ }
605
+ };
606
+ pages.forEach((page) => {
607
+ processPageWithChildren(page);
608
+ });
609
+ }
577
610
  }
578
611
  addPrerenderRoutes(prerenderRoutes);
579
612
  });
580
613
  nuxt.hook("nitro:config", (nitroConfig) => {
614
+ nitroConfig.bundledStorage = nitroConfig.bundledStorage || [];
615
+ nitroConfig.bundledStorage.push("i18n-locales");
616
+ nitroConfig.devStorage = nitroConfig.devStorage || {};
617
+ nitroConfig.devStorage["i18n-locales"] = {
618
+ driver: "fs",
619
+ base: path.join(nuxt.options.rootDir, "server/assets/i18n-locales")
620
+ };
581
621
  if (nitroConfig.imports) {
582
622
  nitroConfig.imports.presets = nitroConfig.imports.presets || [];
583
623
  nitroConfig.imports.presets.push({
@@ -592,7 +632,7 @@ const module = defineNuxtModule({
592
632
  nuxt.options.generate.routes = Array.isArray(nuxt.options.generate.routes) ? nuxt.options.generate.routes : [];
593
633
  const pages = nuxt.options.generate.routes || [];
594
634
  localeManager.locales.forEach((locale) => {
595
- if (locale.code !== options.defaultLocale || withPrefixStrategy(options.strategy)) {
635
+ if (locale.code !== defaultLocale || withPrefixStrategy(options.strategy)) {
596
636
  pages.forEach((page) => {
597
637
  if (!/\.[a-z0-9]+$/i.test(page)) {
598
638
  routes.push(`/${locale.code}${page}`);
@@ -616,6 +656,64 @@ const module = defineNuxtModule({
616
656
  }
617
657
  }
618
658
  });
659
+ nuxt.hook("nitro:init", async (nitro) => {
660
+ logger.debug("[nuxt-i18n-micro] clear storage cache");
661
+ await nitro.storage.clear("i18n-locales");
662
+ if (!await nitro.storage.hasItem(`i18n-locales:.gitignore`)) {
663
+ const dir = path.join(nuxt.options.rootDir, "server/assets/i18n-locales");
664
+ fs__default.mkdirSync(dir, { recursive: true });
665
+ fs__default.writeFileSync(`${dir}/.gitignore`, "*");
666
+ }
667
+ const translationDir = options.translationDir ?? "";
668
+ const fallbackLocale = options.fallbackLocale ?? null;
669
+ const translationsByLocale = {};
670
+ try {
671
+ for (const rootDir of rootDirs) {
672
+ const baseDir = path.resolve(rootDir, translationDir);
673
+ const files = await globby("**/*.json", { cwd: baseDir });
674
+ const promises = files.map(async (file) => {
675
+ const filePath = path.join(baseDir, file);
676
+ const content = await readFile(filePath, "utf-8");
677
+ const data = JSON.parse(content);
678
+ const parts = file.split("/");
679
+ const locale = parts.pop()?.replace(".json", "") || "";
680
+ const pageKey = parts.pop() || "general";
681
+ if (!translationsByLocale[locale]) {
682
+ translationsByLocale[locale] = {};
683
+ }
684
+ translationsByLocale[locale] = deepMerge({
685
+ [pageKey]: data
686
+ }, translationsByLocale[locale]);
687
+ });
688
+ await Promise.all(promises);
689
+ }
690
+ const savePromises = [];
691
+ for (const [locale, translations] of Object.entries(translationsByLocale)) {
692
+ for (const [key, value] of Object.entries(translations)) {
693
+ const storageKey = `i18n-locales:${locale}:${key}`;
694
+ const promise = (async () => {
695
+ let translation = value;
696
+ if (fallbackLocale) {
697
+ translation = deepMerge(
698
+ translation,
699
+ translationsByLocale[fallbackLocale][key] ?? {}
700
+ );
701
+ }
702
+ if (typeof translation === "object" && translation !== null) {
703
+ await nitro.storage.setItem(storageKey, translation);
704
+ if (options.debug) {
705
+ logger.log(`[nuxt-i18n-micro] Translation saved to Nitro storage with key: ${storageKey}`);
706
+ }
707
+ }
708
+ })();
709
+ savePromises.push(promise);
710
+ }
711
+ }
712
+ await Promise.all(savePromises);
713
+ } catch (err) {
714
+ logger.error("[nuxt-i18n-micro] Error processing translations:", err);
715
+ }
716
+ });
619
717
  if (!options.disableUpdater) {
620
718
  nuxt.hook("nitro:build:before", async (_nitro) => {
621
719
  const isProd = nuxt.options.dev === false;
@@ -623,7 +721,7 @@ const module = defineNuxtModule({
623
721
  const translationPath = path.resolve(nuxt.options.rootDir, options.translationDir);
624
722
  logger.log("\u2139 add file watcher: " + translationPath);
625
723
  const watcherEvent = async (path2) => {
626
- watcher.close();
724
+ await watcher.close();
627
725
  logger.log("\u21BB update store item: " + path2);
628
726
  nuxt.callHook("restart");
629
727
  };
@@ -643,7 +741,7 @@ const module = defineNuxtModule({
643
741
  routesSet.forEach((route) => {
644
742
  if (!/\.[a-z0-9]+$/i.test(route)) {
645
743
  localeManager.locales.forEach((locale) => {
646
- if (locale.code !== options.defaultLocale) {
744
+ if (locale.code !== defaultLocale) {
647
745
  if (route === "/") {
648
746
  additionalRoutes.add(`/${locale.code}`);
649
747
  } else {
@@ -244,8 +244,13 @@ export default defineNuxtPlugin(async (nuxtApp) => {
244
244
  return;
245
245
  }
246
246
  const locale = i18nHelper.getLocale();
247
- const url = `/${apiBaseUrl}/${fRouteName}/${locale}/data.json?v=${i18nConfig.dateBuild}`.replace(/\/{2,}/g, "/");
248
- const data = await $fetch(url, { baseURL: runtimeConfig.app.baseURL });
247
+ const url = `/${apiBaseUrl}/${fRouteName}/${locale}/data.json`.replace(/\/{2,}/g, "/");
248
+ const data = await $fetch(url, {
249
+ baseURL: runtimeConfig.app.baseURL,
250
+ params: {
251
+ v: i18nConfig.dateBuild
252
+ }
253
+ });
249
254
  await i18nHelper.loadPageTranslations(routeName, data ?? {});
250
255
  }
251
256
  } catch (_error) {
@@ -270,9 +275,12 @@ export default defineNuxtPlugin(async (nuxtApp) => {
270
275
  }
271
276
  if (!i18nHelper.hasGeneralTranslation()) {
272
277
  const locale = i18nHelper.getLocale();
273
- const url = `/${apiBaseUrl}/general/${locale}/data.json?v=${i18nConfig.dateBuild}`.replace(/\/{2,}/g, "/");
278
+ const url = `/${apiBaseUrl}/general/${locale}/data.json`.replace(/\/{2,}/g, "/");
274
279
  const data = await $fetch(url, {
275
- baseURL: runtimeConfig.app.baseURL
280
+ baseURL: runtimeConfig.app.baseURL,
281
+ params: {
282
+ v: i18nConfig.dateBuild
283
+ }
276
284
  });
277
285
  await i18nHelper.loadTranslations(data ?? {});
278
286
  }
@@ -0,0 +1,17 @@
1
+ import { defineEventHandler } from "h3";
2
+ import { createError, useRuntimeConfig, useStorage } from "#imports";
3
+ export default defineEventHandler(async (event) => {
4
+ const { page, locale } = event.context.params;
5
+ const config = useRuntimeConfig();
6
+ const { customRegexMatcher, locales } = config.public.i18nConfig;
7
+ if (customRegexMatcher && locales && !locales.map((l) => l.code).includes(locale)) {
8
+ throw createError({ statusCode: 404 });
9
+ }
10
+ const cacheKey = `${locale}:${page}`;
11
+ const serverStorage = useStorage("i18n-locales");
12
+ if (await serverStorage.hasItem(cacheKey)) {
13
+ const rawContent = await serverStorage.getItem(cacheKey) || {};
14
+ return typeof rawContent === "string" ? JSON.parse(rawContent) : rawContent;
15
+ }
16
+ return {};
17
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-i18n-micro",
3
- "version": "1.61.0",
3
+ "version": "1.62.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",
@@ -48,31 +48,32 @@
48
48
  ],
49
49
  "dependencies": {
50
50
  "@nuxt/devtools-kit": "^1.7.0",
51
- "@nuxt/kit": "^3.15.1",
51
+ "@nuxt/kit": "^3.15.2",
52
52
  "chokidar": "^3.6.0",
53
+ "globby": "^14.0.2",
53
54
  "sirv": "^2.0.4",
54
55
  "ufo": "^1.5.4",
55
- "nuxt-i18n-micro-test-utils": "1.0.4",
56
- "nuxt-i18n-micro-core": "1.0.11"
56
+ "nuxt-i18n-micro-core": "1.0.11",
57
+ "nuxt-i18n-micro-test-utils": "1.0.4"
57
58
  },
58
59
  "devDependencies": {
59
- "@types/jest": "^29.5.14",
60
60
  "@nuxt/devtools": "^1.7.0",
61
61
  "@nuxt/devtools-ui-kit": "^1.7.0",
62
62
  "@nuxt/eslint-config": "0.7.4",
63
63
  "@nuxt/module-builder": "^0.8.4",
64
- "@nuxt/schema": "^3.15.1",
65
- "@nuxt/test-utils": "^3.15.1",
64
+ "@nuxt/schema": "^3.15.2",
65
+ "@nuxt/test-utils": "^3.15.4",
66
66
  "@playwright/test": "^1.49.1",
67
+ "@types/jest": "^29.5.14",
67
68
  "@types/node": "^20.17.10",
68
69
  "changelogen": "^0.5.7",
69
70
  "eslint": "^8.57.1",
70
- "nuxt": "^3.15.1",
71
+ "jest": "^29.7.0",
72
+ "nuxt": "^3.15.2",
73
+ "ts-jest": "^29.2.5",
71
74
  "typescript": "5.6.3",
72
75
  "vitepress": "^1.5.0",
73
76
  "vitest": "^2.1.8",
74
- "jest": "^29.7.0",
75
- "ts-jest": "^29.2.5",
76
77
  "vue-tsc": "2.1.10"
77
78
  },
78
79
  "optionalDependencies": {
@@ -1 +0,0 @@
1
- {"id":"019df560-5b4f-4d25-8ca1-a8cad935e3d2","timestamp":1736953866014,"matcher":{"static":{},"wildcard":{},"dynamic":{}},"prerendered":[]}
@@ -1 +0,0 @@
1
- .spotlight[data-v-3074ece5]{background:linear-gradient(45deg,#00dc82,#36e4da 50%,#0047e1);bottom:-30vh;filter:blur(20vh);height:40vh}.gradient-border[data-v-3074ece5]{-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border-radius:.5rem;position:relative}@media (prefers-color-scheme:light){.gradient-border[data-v-3074ece5]{background-color:#ffffff4d}.gradient-border[data-v-3074ece5]:before{background:linear-gradient(90deg,#e2e2e2,#e2e2e2 25%,#00dc82,#36e4da 75%,#0047e1)}}@media (prefers-color-scheme:dark){.gradient-border[data-v-3074ece5]{background-color:#1414144d}.gradient-border[data-v-3074ece5]:before{background:linear-gradient(90deg,#303030,#303030 25%,#00dc82,#36e4da 75%,#0047e1)}}.gradient-border[data-v-3074ece5]:before{background-size:400% auto;border-radius:.5rem;bottom:0;content:"";left:0;-webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask-composite:exclude;opacity:.5;padding:2px;position:absolute;right:0;top:0;transition:background-position .3s ease-in-out,opacity .2s ease-in-out;width:100%}.gradient-border[data-v-3074ece5]:hover:before{background-position:-50% 0;opacity:1}.fixed[data-v-3074ece5]{position:fixed}.left-0[data-v-3074ece5]{left:0}.right-0[data-v-3074ece5]{right:0}.z-10[data-v-3074ece5]{z-index:10}.z-20[data-v-3074ece5]{z-index:20}.grid[data-v-3074ece5]{display:grid}.mb-16[data-v-3074ece5]{margin-bottom:4rem}.mb-8[data-v-3074ece5]{margin-bottom:2rem}.max-w-520px[data-v-3074ece5]{max-width:520px}.min-h-screen[data-v-3074ece5]{min-height:100vh}.w-full[data-v-3074ece5]{width:100%}.flex[data-v-3074ece5]{display:flex}.cursor-pointer[data-v-3074ece5]{cursor:pointer}.place-content-center[data-v-3074ece5]{place-content:center}.items-center[data-v-3074ece5]{align-items:center}.justify-center[data-v-3074ece5]{justify-content:center}.overflow-hidden[data-v-3074ece5]{overflow:hidden}.bg-white[data-v-3074ece5]{--un-bg-opacity:1;background-color:rgb(255 255 255/var(--un-bg-opacity))}.px-4[data-v-3074ece5]{padding-left:1rem;padding-right:1rem}.px-8[data-v-3074ece5]{padding-left:2rem;padding-right:2rem}.py-2[data-v-3074ece5]{padding-bottom:.5rem;padding-top:.5rem}.text-center[data-v-3074ece5]{text-align:center}.text-8xl[data-v-3074ece5]{font-size:6rem;line-height:1}.text-xl[data-v-3074ece5]{font-size:1.25rem;line-height:1.75rem}.text-black[data-v-3074ece5]{--un-text-opacity:1;color:rgb(0 0 0/var(--un-text-opacity))}.font-light[data-v-3074ece5]{font-weight:300}.font-medium[data-v-3074ece5]{font-weight:500}.leading-tight[data-v-3074ece5]{line-height:1.25}.font-sans[data-v-3074ece5]{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.antialiased[data-v-3074ece5]{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media (prefers-color-scheme:dark){.dark\:bg-black[data-v-3074ece5]{--un-bg-opacity:1;background-color:rgb(0 0 0/var(--un-bg-opacity))}.dark\:text-white[data-v-3074ece5]{--un-text-opacity:1;color:rgb(255 255 255/var(--un-text-opacity))}}@media (min-width:640px){.sm\:px-0[data-v-3074ece5]{padding-left:0;padding-right:0}.sm\:px-6[data-v-3074ece5]{padding-left:1.5rem;padding-right:1.5rem}.sm\:py-3[data-v-3074ece5]{padding-bottom:.75rem;padding-top:.75rem}.sm\:text-4xl[data-v-3074ece5]{font-size:2.25rem;line-height:2.5rem}.sm\:text-xl[data-v-3074ece5]{font-size:1.25rem;line-height:1.75rem}}
@@ -1 +0,0 @@
1
- .spotlight[data-v-44593346]{background:linear-gradient(45deg,#00dc82,#36e4da 50%,#0047e1);filter:blur(20vh)}.fixed[data-v-44593346]{position:fixed}.-bottom-1\/2[data-v-44593346]{bottom:-50%}.left-0[data-v-44593346]{left:0}.right-0[data-v-44593346]{right:0}.grid[data-v-44593346]{display:grid}.mb-16[data-v-44593346]{margin-bottom:4rem}.mb-8[data-v-44593346]{margin-bottom:2rem}.h-1\/2[data-v-44593346]{height:50%}.max-w-520px[data-v-44593346]{max-width:520px}.min-h-screen[data-v-44593346]{min-height:100vh}.place-content-center[data-v-44593346]{place-content:center}.overflow-hidden[data-v-44593346]{overflow:hidden}.bg-white[data-v-44593346]{--un-bg-opacity:1;background-color:rgb(255 255 255/var(--un-bg-opacity))}.px-8[data-v-44593346]{padding-left:2rem;padding-right:2rem}.text-center[data-v-44593346]{text-align:center}.text-8xl[data-v-44593346]{font-size:6rem;line-height:1}.text-xl[data-v-44593346]{font-size:1.25rem;line-height:1.75rem}.text-black[data-v-44593346]{--un-text-opacity:1;color:rgb(0 0 0/var(--un-text-opacity))}.font-light[data-v-44593346]{font-weight:300}.font-medium[data-v-44593346]{font-weight:500}.leading-tight[data-v-44593346]{line-height:1.25}.font-sans[data-v-44593346]{font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji}.antialiased[data-v-44593346]{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media (prefers-color-scheme:dark){.dark\:bg-black[data-v-44593346]{--un-bg-opacity:1;background-color:rgb(0 0 0/var(--un-bg-opacity))}.dark\:text-white[data-v-44593346]{--un-text-opacity:1;color:rgb(255 255 255/var(--un-text-opacity))}}@media (min-width:640px){.sm\:px-0[data-v-44593346]{padding-left:0;padding-right:0}.sm\:text-4xl[data-v-44593346]{font-size:2.25rem;line-height:2.5rem}}
@@ -1,61 +0,0 @@
1
- import { resolve, join } from "node:path";
2
- import { readFile } from "node:fs/promises";
3
- import { defineEventHandler } from "h3";
4
- import { useRuntimeConfig, createError, useStorage } from "#imports";
5
- let storageInit = false;
6
- function deepMerge(target, source) {
7
- for (const key in source) {
8
- if (key === "__proto__" || key === "constructor") continue;
9
- if (Array.isArray(source[key])) {
10
- target[key] = source[key];
11
- } else if (source[key] instanceof Object) {
12
- target[key] = target[key] instanceof Object ? deepMerge(target[key], source[key]) : source[key];
13
- } else {
14
- target[key] = source[key];
15
- }
16
- }
17
- return target;
18
- }
19
- export default defineEventHandler(async (event) => {
20
- const { page, locale } = event.context.params;
21
- const config = useRuntimeConfig();
22
- const { rootDirs, debug } = config.i18nConfig;
23
- const { translationDir, fallbackLocale, customRegexMatcher, locales } = config.public.i18nConfig;
24
- if (customRegexMatcher && locales && !locales.map((l) => l.code).includes(locale)) {
25
- throw createError({ statusCode: 404 });
26
- }
27
- const getTranslationPath = (locale2, page2) => page2 === "general" ? `${locale2}.json` : `pages/${page2}/${locale2}.json`;
28
- const createPaths = (locale2) => rootDirs.map((dir) => ({
29
- translationPath: resolve(dir, translationDir, getTranslationPath(locale2, page)),
30
- name: `_locales/${getTranslationPath(locale2, page)}`
31
- }));
32
- const paths = [
33
- ...fallbackLocale && fallbackLocale !== locale ? createPaths(fallbackLocale) : [],
34
- ...createPaths(locale)
35
- ];
36
- let translations = {};
37
- const serverStorage = await useStorage("assets:server");
38
- if (!storageInit) {
39
- if (debug) console.log("[nuxt-i18n-micro] clear storage cache");
40
- await Promise.all((await serverStorage.getKeys()).map((key) => serverStorage.removeItem(key)));
41
- storageInit = true;
42
- }
43
- const cacheName = join("_locales", getTranslationPath(locale, page));
44
- const isThereAsset = await serverStorage.hasItem(cacheName);
45
- if (isThereAsset) {
46
- const rawContent = await serverStorage.getItem(cacheName) ?? {};
47
- return typeof rawContent === "string" ? JSON.parse(rawContent) : rawContent;
48
- }
49
- for (const { translationPath, name } of paths) {
50
- try {
51
- if (debug) console.log("[nuxt-i18n-micro] load locale", translationPath, name);
52
- const content = await readFile(translationPath, "utf-8");
53
- const fileContent = JSON.parse(content);
54
- translations = deepMerge(translations, fileContent);
55
- } catch (e) {
56
- if (debug) console.error("[nuxt-i18n-micro] load locale error", e);
57
- }
58
- }
59
- await serverStorage.setItem(cacheName, translations);
60
- return translations;
61
- });