nuxt-i18n-micro 3.30.0 → 3.30.1

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
- <!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><script type="importmap">{"imports":{"#entry":"/__nuxt-i18n-micro/_nuxt/UO0Glz5S.js"}}</script><link rel="stylesheet" href="/__nuxt-i18n-micro/_nuxt/entry.CJGrD2VA.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/UO0Glz5S.js"><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CUWB4CwN.js"><script type="module" src="/__nuxt-i18n-micro/_nuxt/UO0Glz5S.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-404.D9Svp6Hk.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/MokPP5zi.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/DAzShkZF.js"><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-500.B-mjI9_9.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CmUbe-uv.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"88fb7799-62d6-48e9-a0d3-deeed800130e",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1790588464421,false]</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><script type="importmap">{"imports":{"#entry":"/__nuxt-i18n-micro/_nuxt/BOxWElQP.js"}}</script><link rel="stylesheet" href="/__nuxt-i18n-micro/_nuxt/entry.BM-mexAv.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/BOxWElQP.js"><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CUWB4CwN.js"><script type="module" src="/__nuxt-i18n-micro/_nuxt/BOxWElQP.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-404.D9Svp6Hk.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/MokPP5zi.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/DAzShkZF.js"><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-500.B-mjI9_9.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CmUbe-uv.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"c2469972-2333-4f71-95c7-408fe74b12f4",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1792047356482,false]</script></body></html>
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><script type="importmap">{"imports":{"#entry":"/__nuxt-i18n-micro/_nuxt/UO0Glz5S.js"}}</script><link rel="stylesheet" href="/__nuxt-i18n-micro/_nuxt/entry.CJGrD2VA.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/UO0Glz5S.js"><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CUWB4CwN.js"><script type="module" src="/__nuxt-i18n-micro/_nuxt/UO0Glz5S.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-404.D9Svp6Hk.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/MokPP5zi.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/DAzShkZF.js"><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-500.B-mjI9_9.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CmUbe-uv.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"88fb7799-62d6-48e9-a0d3-deeed800130e",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1790588464422,false]</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><script type="importmap">{"imports":{"#entry":"/__nuxt-i18n-micro/_nuxt/BOxWElQP.js"}}</script><link rel="stylesheet" href="/__nuxt-i18n-micro/_nuxt/entry.BM-mexAv.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/BOxWElQP.js"><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CUWB4CwN.js"><script type="module" src="/__nuxt-i18n-micro/_nuxt/BOxWElQP.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-404.D9Svp6Hk.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/MokPP5zi.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/DAzShkZF.js"><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-500.B-mjI9_9.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CmUbe-uv.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"c2469972-2333-4f71-95c7-408fe74b12f4",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1792047356482,false]</script></body></html>
@@ -1 +1 @@
1
- {"id":"88fb7799-62d6-48e9-a0d3-deeed800130e","timestamp":1790588461763}
1
+ {"id":"c2469972-2333-4f71-95c7-408fe74b12f4","timestamp":1792047354090}
@@ -0,0 +1 @@
1
+ {"id":"c2469972-2333-4f71-95c7-408fe74b12f4","timestamp":1792047354090,"prerendered":[]}
@@ -1 +1 @@
1
- :root{--nui-c-context:125,125,125}html{background-color:#fff}html.dark{color:#fff;--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;background-color:#151515}::selection{background:#8884}.shiki .line{width:100%;display:inline-block;position:relative}.shiki.diff .line>span{filter:saturate(.75);opacity:.75}.shiki.diff .line-added,.shiki.diff .line-removed{scroll-margin:5em}.shiki.diff .line-added>span,.shiki.diff .line-removed>span{position:inherit;z-index:100;scroll-margin:20px;opacity:1!important}.shiki.diff .line-added>span{color:#218c3b!important}.shiki.diff .line-removed>span{color:#d15547!important}.shiki .line-added:after{background-color:#43885420}.shiki .line-added:after,.shiki .line-removed:after{content:"";display:block;position:absolute;inset:0}.shiki .line-removed:after{background-color:#8f4c3926}::view-transition-new(root){mix-blend-mode:normal;animation:none}::view-transition-old(root){mix-blend-mode:normal;animation:none}::view-transition-old(root){z-index:1}::view-transition-new(root){z-index:2147483646}.dark::view-transition-old(root){z-index:2147483646}.dark::view-transition-new(root){z-index:1}*,:after,:before{box-sizing:border-box;border-style:solid;border-width:0;border-color:var(--un-default-border-color,#e5e7eb)}:after,:before{--un-content:""}:host,html{-webkit-text-size-adjust:100%;tab-size:4;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}body{line-height:inherit;margin:0}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-feature-settings:normal;font-variation-settings:normal;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-feature-settings:inherit;font-variation-settings:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:#0000;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}menu,ol,ul{margin:0;padding:0;list-style:none}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder{opacity:1;color:#9ca3af}textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}@font-face{font-family:DM Mono;font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/dmmono/v16/aFTU7PB1QTsUX8KYthSQBK6PYK3EXw.woff2)format("woff2");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:DM Mono;font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/dmmono/v16/aFTU7PB1QTsUX8KYthqQBK6PYK0.woff2)format("woff2");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:DM Sans;font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/dmsans/v17/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAopxRR232RmYJp8I5zzw.woff2)format("woff2");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:DM Sans;font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/dmsans/v17/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAopxRSW32RmYJp8I5.woff2)format("woff2");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}*,:after,:before,::backdrop{--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:#93c5fd80;--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: }.container{width:100%}@media (width>=640px){.container{max-width:640px}}@media (width>=768px){.container{max-width:768px}}@media (width>=1024px){.container{max-width:1024px}}@media (width>=1280px){.container{max-width:1280px}}@media (width>=1536px){.container{max-width:1536px}}.grid{display:grid}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.max-w-520px{max-width:520px}.min-h-screen{min-height:100vh}.w-full{width:100%}.flex{display:flex}.place-content-center{place-content:center}.items-center{align-items:center}.justify-center{justify-content:center}.overflow-hidden{overflow:hidden}.bg-white{--un-bg-opacity:1;background-color:rgb(255 255 255/var(--un-bg-opacity))}.dark .dark\:bg-\[\#020420\]{--un-bg-opacity:1;background-color:rgb(2 4 32/var(--un-bg-opacity))}.px-2{padding-left:.5rem;padding-right:.5rem}.text-center{text-align:center}.text-\[80px\]{font-size:80px}.text-2xl{font-size:1.5rem;line-height:2rem}.text-sm{font-size:.875rem;line-height:1.25rem}.dark .dark\:text-white{--un-text-opacity:1;color:rgb(255 255 255/var(--un-text-opacity))}.text-\[\#020420\]{--un-text-opacity:1;color:rgb(2 4 32/var(--un-text-opacity))}.text-\[\#64748B\]{--un-text-opacity:1;color:rgb(100 116 139/var(--un-text-opacity))}.hover\:text-\[\#00DC82\]:hover{--un-text-opacity:1;color:rgb(0 220 130/var(--un-text-opacity))}.font-medium{font-weight:500}.font-semibold{font-weight:600}.leading-none{line-height:1}.tracking-wide{letter-spacing:.025em}.font-sans{font-family:DM Sans,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}.tabular-nums{--un-numeric-spacing:tabular-nums;font-variant-numeric:var(--un-ordinal) var(--un-slashed-zero) var(--un-numeric-figure) var(--un-numeric-spacing) var(--un-numeric-fraction)}.underline{text-decoration-line:underline}.underline-offset-3{text-underline-offset:3px}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media (width>=640px){.sm\:text-\[110px\]{font-size:110px}.sm\:text-3xl{font-size:1.875rem;line-height:2.25rem}}
1
+ :root{--nui-c-context:125,125,125}html{background-color:#fff}html.dark{color:#fff;--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark;background-color:#151515}::selection{background:#8884}.shiki .line{width:100%;display:inline-block;position:relative}.shiki.diff .line>span{filter:saturate(.75);opacity:.75}.shiki.diff .line-added,.shiki.diff .line-removed{scroll-margin:5em}.shiki.diff .line-added>span,.shiki.diff .line-removed>span{position:inherit;z-index:100;scroll-margin:20px;opacity:1!important}.shiki.diff .line-added>span{color:#218c3b!important}.shiki.diff .line-removed>span{color:#d15547!important}.shiki .line-added:after{background-color:#43885420}.shiki .line-added:after,.shiki .line-removed:after{content:"";display:block;position:absolute;inset:0}.shiki .line-removed:after{background-color:#8f4c3926}::view-transition-new(root){mix-blend-mode:normal;animation:none}::view-transition-old(root){mix-blend-mode:normal;animation:none}::view-transition-old(root){z-index:1}::view-transition-new(root){z-index:2147483646}.dark::view-transition-old(root){z-index:2147483646}.dark::view-transition-new(root){z-index:1}*,:after,:before{box-sizing:border-box;border-style:solid;border-width:0;border-color:var(--un-default-border-color,#e5e7eb)}:after,:before{--un-content:""}:host,html{-webkit-text-size-adjust:100%;tab-size:4;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}body{line-height:inherit;margin:0}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-feature-settings:normal;font-variation-settings:normal;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-feature-settings:inherit;font-variation-settings:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button;background-color:#0000;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}menu,ol,ul{margin:0;padding:0;list-style:none}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder{opacity:1;color:#9ca3af}textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}@font-face{font-family:DM Mono;font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/dmmono/v16/aFTU7PB1QTsUX8KYthSQBK6PYK3EXw.woff2)format("woff2");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C4,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:DM Mono;font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/dmmono/v16/aFTU7PB1QTsUX8KYthqQBK6PYK0.woff2)format("woff2");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:DM Sans;font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/dmsans/v17/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAopxRR232RmYJp8I5zzw.woff2)format("woff2");unicode-range:U+100-2BA,U+2BD-2C5,U+2C7-2CC,U+2CE-2D7,U+2DD-2FF,U+304,U+308,U+329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C4,U+2113,U+2C60-2C7F,U+A720-A7FF}@font-face{font-family:DM Sans;font-style:normal;font-weight:400;font-display:swap;src:url(https://fonts.gstatic.com/s/dmsans/v17/rP2tp2ywxg089UriI5-g4vlH9VoD8CmcqZG40F9JadbnoEwAopxRSW32RmYJp8I5.woff2)format("woff2");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+304,U+308,U+329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}*,:after,:before,::backdrop{--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:#93c5fd80;--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: }.container{width:100%}@media (width>=640px){.container{max-width:640px}}@media (width>=768px){.container{max-width:768px}}@media (width>=1024px){.container{max-width:1024px}}@media (width>=1280px){.container{max-width:1280px}}@media (width>=1536px){.container{max-width:1536px}}.grid{display:grid}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.max-w-520px{max-width:520px}.min-h-screen{min-height:100vh}.w-full{width:100%}.flex{display:flex}.place-content-center{place-content:center}.items-center{align-items:center}.justify-center{justify-content:center}.overflow-hidden{overflow:hidden}.bg-white{--un-bg-opacity:1;background-color:rgb(255 255 255/var(--un-bg-opacity))}.dark .dark\:bg-\[\#020420\]{--un-bg-opacity:1;background-color:rgb(2 4 32/var(--un-bg-opacity))}.px-2{padding-left:.5rem;padding-right:.5rem}.text-center{text-align:center}.text-\[80px\]{font-size:80px}.text-2xl{font-size:1.5rem;line-height:2rem}.text-sm{font-size:.875rem;line-height:1.25rem}.dark .dark\:text-white{--un-text-opacity:1;color:rgb(255 255 255/var(--un-text-opacity))}.text-\[\#020420\]{--un-text-opacity:1;color:rgb(2 4 32/var(--un-text-opacity))}.text-\[\#64748B\]{--un-text-opacity:1;color:rgb(100 116 139/var(--un-text-opacity))}.hover\:text-\[\#00DC82\]:hover{--un-text-opacity:1;color:rgb(0 220 130/var(--un-text-opacity))}.font-medium{font-weight:500}.font-semibold{font-weight:600}.leading-none{line-height:1}.tracking-wide{letter-spacing:.025em}.font-sans{font-family:DM Sans,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}.tabular-nums{--un-numeric-spacing:tabular-nums;font-variant-numeric:var(--un-ordinal) var(--un-slashed-zero) var(--un-numeric-figure) var(--un-numeric-spacing) var(--un-numeric-fraction)}.underline{text-decoration-line:underline}.underline-offset-3{text-underline-offset:3px}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}@media (width>=640px){.sm\:text-\[110px\]{font-size:110px}.sm\:text-3xl{font-size:1.875rem;line-height:2.25rem}}
@@ -1 +1 @@
1
- <!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><script type="importmap">{"imports":{"#entry":"/__nuxt-i18n-micro/_nuxt/UO0Glz5S.js"}}</script><link rel="stylesheet" href="/__nuxt-i18n-micro/_nuxt/entry.CJGrD2VA.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/UO0Glz5S.js"><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CUWB4CwN.js"><script type="module" src="/__nuxt-i18n-micro/_nuxt/UO0Glz5S.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-404.D9Svp6Hk.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/MokPP5zi.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/DAzShkZF.js"><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-500.B-mjI9_9.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CmUbe-uv.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"88fb7799-62d6-48e9-a0d3-deeed800130e",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1790588464422,false]</script></body></html>
1
+ <!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><script type="importmap">{"imports":{"#entry":"/__nuxt-i18n-micro/_nuxt/BOxWElQP.js"}}</script><link rel="stylesheet" href="/__nuxt-i18n-micro/_nuxt/entry.BM-mexAv.css" crossorigin><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/BOxWElQP.js"><link rel="modulepreload" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CUWB4CwN.js"><script type="module" src="/__nuxt-i18n-micro/_nuxt/BOxWElQP.js" crossorigin></script><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-404.D9Svp6Hk.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/MokPP5zi.js"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/DAzShkZF.js"><link rel="prefetch" as="style" crossorigin href="/__nuxt-i18n-micro/_nuxt/error-500.B-mjI9_9.css"><link rel="prefetch" as="script" crossorigin href="/__nuxt-i18n-micro/_nuxt/CmUbe-uv.js"></head><body><div id="__nuxt"></div><div id="teleports"></div><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/__nuxt-i18n-micro",buildId:"c2469972-2333-4f71-95c7-408fe74b12f4",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="application/json" data-nuxt-data="nuxt-app" data-ssr="false" id="__NUXT_DATA__">[{"prerenderedAt":1,"serverRendered":2},1792047356482,false]</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": "3.30.0",
4
+ "version": "3.30.1",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.3",
7
7
  "unbuild": "3.6.1"
package/dist/module.mjs CHANGED
@@ -615,6 +615,8 @@ function buildFullConfig(params) {
615
615
  function buildPrivateConfig(options, nuxt, apiConfig, locales, payloadFsDir, payloadPublicRel) {
616
616
  return {
617
617
  rootDir: nuxt.options.rootDir,
618
+ // Same order as build translation merge: extends first, project last (wins).
619
+ rootDirs: nuxt.options._layers.map((layer) => layer.config.rootDir).reverse(),
618
620
  debug: options.debug ?? false,
619
621
  locales: locales ?? [],
620
622
  fallbackLocale: options.fallbackLocale ?? void 0,
@@ -773,7 +775,7 @@ const module$1 = defineNuxtModule({
773
775
  const mergedLocalesDir = resolve(nuxt.options.buildDir, "i18n-merged");
774
776
  const sourceLocalesDir = resolve(nuxt.options.buildDir, "i18n-source");
775
777
  const translationDirName = options.translationDir || "locales";
776
- const translationsHash = hashTranslationSources(rootDirs, translationDirName, options.additionalTranslationDirs);
778
+ const translationsHash = options.dateBuild === void 0 ? hashTranslationSources(rootDirs, translationDirName, options.additionalTranslationDirs) : null;
777
779
  const translationPayloads = resolveTranslationPayloadOptions(options);
778
780
  const publicAssetsDir = translationPayloads.mode === "source" ? sourceLocalesDir : mergedLocalesDir;
779
781
  for (const warning of getTranslationPayloadMisconfigurationWarnings({
@@ -803,9 +805,10 @@ const module$1 = defineNuxtModule({
803
805
  }
804
806
  const localeInfos = [...localeInfosByCode.values()].filter((locale) => !locale.disabled).map(({ code, fallbackLocale }) => ({ code, fallbackLocale }));
805
807
  nuxt.hook("build:before", async () => {
806
- await buildTranslationSourceLayers(rootDirs, translationDirName, sourceLocalesDir, options.additionalTranslationDirs);
807
- logger.info(`Built compact translation source from ${rootDirs.length} layer(s) into ${sourceLocalesDir}`);
808
- if (translationPayloads.mode !== "source") {
808
+ if (translationPayloads.mode === "source") {
809
+ await buildTranslationSourceLayers(rootDirs, translationDirName, sourceLocalesDir, options.additionalTranslationDirs);
810
+ logger.info(`Built compact translation source from ${rootDirs.length} layer(s) into ${sourceLocalesDir}`);
811
+ } else {
809
812
  await preMergeLocales(
810
813
  rootDirs,
811
814
  translationDirName,
@@ -973,8 +976,13 @@ const module$1 = defineNuxtModule({
973
976
  });
974
977
  }
975
978
  if (nuxt.options.dev && (options.hmr ?? true)) {
976
- const translationsDir = join(nuxt.options.rootDir, options.translationDir || "locales");
977
- const files = await globby(["**/*.json"], { cwd: translationsDir, absolute: true });
979
+ const files = (await Promise.all(
980
+ rootDirs.map(async (layerRoot) => {
981
+ const translationsDir = join(layerRoot, options.translationDir || "locales");
982
+ if (!existsSync(translationsDir)) return [];
983
+ return globby(["**/*.json"], { cwd: translationsDir, absolute: true });
984
+ })
985
+ )).flat();
978
986
  const additionalRootFiles = (await Promise.all(
979
987
  (options.additionalTranslationDirs ?? []).flatMap(
980
988
  (extra) => rootDirs.map(async (layerRoot) => {
@@ -71,6 +71,12 @@ export default defineNuxtPlugin(async (nuxtApp) => {
71
71
  getLocaleFromRoute: (r) => getCurrentLocale(r)
72
72
  });
73
73
  const initialRouteName = getPluginRouteName(router.currentRoute.value, initialLocale);
74
+ if (import.meta.server && initialRouteName === "index") {
75
+ const preloaded = nuxtApp.ssrContext?.event?.context?.i18n?.translations;
76
+ if (preloaded && typeof preloaded === "object" && Object.keys(preloaded).length > 0) {
77
+ translationStorage.seed(initialLocale, "index", preloaded);
78
+ }
79
+ }
74
80
  try {
75
81
  await loader.switchContext(initialLocale, initialRouteName);
76
82
  } catch (e) {
@@ -1,18 +1,18 @@
1
1
  import { existsSync, readdirSync } from "node:fs";
2
2
  import path from "node:path";
3
- import { SERVER_CC_KEY, STORAGE_CC_KEY } from "@i18n-micro/hmr/cache-keys";
3
+ import { STORAGE_CC_KEY } from "@i18n-micro/hmr/cache-keys";
4
4
  import {
5
+ createTranslationDirReader,
5
6
  handleTranslationWatchChange,
6
- parseTranslationWatchRelativePath,
7
- readTranslationFile,
7
+ resolveLiveTranslationDirs,
8
8
  TranslationContentTracker
9
9
  } from "@i18n-micro/hmr/watcher";
10
- import { CacheControl } from "@i18n-micro/utils/cache-control";
11
- import { deepMergeTranslationsRecursive } from "@i18n-micro/utils/deep-merge";
10
+ import { parseTranslationRelativePath } from "@i18n-micro/utils/parse-path";
12
11
  import { watch } from "chokidar";
13
12
  import { defineNitroPlugin } from "nitropack/runtime";
14
13
  import { getI18nPrivateConfig } from "#i18n-internal/config";
15
14
  import { getI18nConfig } from "#i18n-internal/strategy";
15
+ import { getOrCreateServerTranslationCache } from "../utils/server-translation-cache.js";
16
16
  function getCacheByKey(key) {
17
17
  const g = globalThis;
18
18
  const cc = g[key];
@@ -21,19 +21,6 @@ function getCacheByKey(key) {
21
21
  }
22
22
  return null;
23
23
  }
24
- function getServerCache() {
25
- return getCacheByKey(SERVER_CC_KEY);
26
- }
27
- function getOrCreateServerCache() {
28
- const existing = getServerCache();
29
- if (existing) {
30
- return existing;
31
- }
32
- const g = globalThis;
33
- const created = new CacheControl();
34
- g[SERVER_CC_KEY] = created;
35
- return created;
36
- }
37
24
  function getStorageCache() {
38
25
  return getCacheByKey(STORAGE_CC_KEY);
39
26
  }
@@ -53,25 +40,20 @@ export default defineNitroPlugin((nitroApp) => {
53
40
  (Array.isArray(rawLocales) ? rawLocales : []).map((l) => l.code).filter((code) => typeof code === "string" && code.length > 0)
54
41
  );
55
42
  const routesLocaleLinks = i18nConfig.routesLocaleLinks || {};
56
- const translationsRoot = path.resolve(i18nConfig.rootDir, i18nConfig.translationDir);
57
- const additionalRoots = (i18nConfig.additionalTranslationDirs ?? []).map((dir) => path.resolve(i18nConfig.rootDir, dir));
58
- log(`Watching for translation changes in: ${translationsRoot}`, additionalRoots.length ? `(+${additionalRoots.length} additional)` : "");
43
+ const { translationRoots, additionalRoots } = resolveLiveTranslationDirs({
44
+ rootDirs: i18nConfig.rootDirs?.length ? i18nConfig.rootDirs : [i18nConfig.rootDir],
45
+ translationDir: i18nConfig.translationDir,
46
+ additionalTranslationDirs: i18nConfig.additionalTranslationDirs
47
+ });
48
+ log(`Watching for translation changes in: ${translationRoots.join(", ")}`, additionalRoots.length ? `(+${additionalRoots.length} additional)` : "");
59
49
  const contentTracker = new TranslationContentTracker();
60
- const readMergedLocaleFile = (relativeFilePath) => {
61
- if (!relativeFilePath.includes("/") && relativeFilePath.endsWith(".json")) {
62
- const locale = relativeFilePath.slice(0, -".json".length);
63
- let content = {};
64
- for (const extraRoot of additionalRoots) {
65
- content = deepMergeTranslationsRecursive(content, readTranslationFile(path.join(extraRoot, `${locale}.json`)));
66
- }
67
- return deepMergeTranslationsRecursive(content, readTranslationFile(path.join(translationsRoot, relativeFilePath)));
68
- }
69
- return readTranslationFile(path.join(translationsRoot, relativeFilePath));
70
- };
50
+ const readMergedLocaleFile = createTranslationDirReader(translationRoots, additionalRoots);
71
51
  const toWatchRelativePath = (filePath) => {
72
- const fromPrimary = path.relative(translationsRoot, filePath);
73
- if (!fromPrimary.startsWith("..") && !path.isAbsolute(fromPrimary)) {
74
- return fromPrimary.replace(/\\/g, "/");
52
+ for (const translationsRoot of translationRoots) {
53
+ const fromPrimary = path.relative(translationsRoot, filePath);
54
+ if (!fromPrimary.startsWith("..") && !path.isAbsolute(fromPrimary)) {
55
+ return fromPrimary.replace(/\\/g, "/");
56
+ }
75
57
  }
76
58
  for (const extraRoot of additionalRoots) {
77
59
  const fromExtra = path.relative(extraRoot, filePath);
@@ -95,17 +77,20 @@ export default defineNitroPlugin((nitroApp) => {
95
77
  relativePath,
96
78
  configuredLocales,
97
79
  listPageNames: () => {
98
- const pagesDir = path.join(translationsRoot, "pages");
99
- if (!existsSync(pagesDir)) {
100
- return [];
80
+ const names = /* @__PURE__ */ new Set();
81
+ for (const translationsRoot of translationRoots) {
82
+ const pagesDir = path.join(translationsRoot, "pages");
83
+ if (!existsSync(pagesDir)) continue;
84
+ for (const entry of readdirSync(pagesDir, { withFileTypes: true })) {
85
+ if (entry.isDirectory()) names.add(entry.name);
86
+ }
101
87
  }
102
- return readdirSync(pagesDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
88
+ return [...names];
103
89
  },
104
- serverCache: getOrCreateServerCache(),
90
+ serverCache: getOrCreateServerTranslationCache(),
105
91
  storageCache: getStorageCache(),
106
92
  routesLocaleLinks,
107
93
  mergeInput: {
108
- translationPayloadMode: runtimeConfig.translationPayloadMode,
109
94
  locales: runtimeConfig.locales,
110
95
  fallbackLocale: runtimeConfig.fallbackLocale,
111
96
  disablePageLocales: runtimeConfig.disablePageLocales,
@@ -113,14 +98,14 @@ export default defineNitroPlugin((nitroApp) => {
113
98
  }
114
99
  });
115
100
  if (result === "root") {
116
- const parsed = parseTranslationWatchRelativePath(relativePath);
101
+ const parsed = parseTranslationRelativePath(relativePath);
117
102
  if (parsed.type === "root") {
118
103
  log(`Re-merged ALL pages for locale '${parsed.locale}'`);
119
104
  }
120
105
  } else if (result === "page") {
121
106
  log(`Re-merged page cache for '${relativePath}'`);
122
107
  } else if (result === "ignored") {
123
- const parsed = parseTranslationWatchRelativePath(relativePath);
108
+ const parsed = parseTranslationRelativePath(relativePath);
124
109
  if (parsed.type === "root" && !configuredLocales.has(parsed.locale)) {
125
110
  warn(`Detected ${event} for '${relativePath}', but locale '${parsed.locale}' is not in i18n.locales. Update config and restart dev server.`);
126
111
  }
@@ -130,7 +115,7 @@ export default defineNitroPlugin((nitroApp) => {
130
115
  warn("Failed to refresh server cache for", filePath, e);
131
116
  }
132
117
  };
133
- const watchRoots = [translationsRoot, ...additionalRoots.filter((dir) => existsSync(dir))];
118
+ const watchRoots = [...translationRoots, ...additionalRoots.filter((dir) => existsSync(dir))];
134
119
  const watcher = watch(watchRoots, {
135
120
  persistent: true,
136
121
  ignoreInitial: true,
@@ -0,0 +1,2 @@
1
+ import type { ModuleOptionsExtend, Translations } from '@i18n-micro/types';
2
+ export declare function loadLiveDevTranslations(locale: string, pageName: string, config: ModuleOptionsExtend): Promise<Translations>;
@@ -0,0 +1,21 @@
1
+ import { createTranslationDirReader, mergeDevTranslations, resolveLiveTranslationDirs } from "@i18n-micro/hmr/watcher";
2
+ import { toTranslations } from "@i18n-micro/utils/normalize";
3
+ import { getI18nPrivateConfig } from "#i18n-internal/config";
4
+ export async function loadLiveDevTranslations(locale, pageName, config) {
5
+ const privateConfig = getI18nPrivateConfig();
6
+ const { translationRoots, additionalRoots } = resolveLiveTranslationDirs({
7
+ rootDirs: privateConfig.rootDirs?.length ? privateConfig.rootDirs : [privateConfig.rootDir],
8
+ translationDir: privateConfig.translationDir,
9
+ additionalTranslationDirs: privateConfig.additionalTranslationDirs
10
+ });
11
+ const readLocaleFile = createTranslationDirReader(translationRoots, additionalRoots);
12
+ const merged = await mergeDevTranslations({
13
+ locale,
14
+ pageName,
15
+ locales: config.locales,
16
+ fallbackLocale: config.fallbackLocale,
17
+ disablePageLocales: config.disablePageLocales,
18
+ readLocaleFile
19
+ });
20
+ return toTranslations(merged);
21
+ }
@@ -2,6 +2,7 @@
2
2
  * Server-side translation loader.
3
3
  * - Node: JSON from public locales dir (`#i18n-internal/payload-source` → fs)
4
4
  * - Edge: Nitro `serverAssets` (`assets:i18n`)
5
+ * - Dev cache miss: live locale-file merge (not stale `.nuxt/i18n-*`)
5
6
  * `premerged` reads one file; `source` merges root+page+fallback at runtime.
6
7
  */
7
8
  import type { Translations } from '@i18n-micro/types';
@@ -1,6 +1,4 @@
1
- import { SERVER_CC_KEY } from "@i18n-micro/hmr/cache-keys";
2
1
  import { isEnabledLocale } from "@i18n-micro/utils/active-locales";
3
- import { CacheControl } from "@i18n-micro/utils/cache-control";
4
2
  import { normalizeConfiguredLocales, toPremergedStorageKey } from "@i18n-micro/utils/merge-source";
5
3
  import { fetchTranslationPayloadFromHost } from "@i18n-micro/utils/payload-fetch";
6
4
  import { resolveTranslationPayloadPage } from "@i18n-micro/utils/payload-url";
@@ -10,16 +8,10 @@ import { toTranslations } from "@i18n-micro/utils/normalize";
10
8
  import { readPayload } from "#i18n-internal/payload-source";
11
9
  import { getI18nPrivateConfig } from "#i18n-internal/config";
12
10
  import { getI18nConfig } from "#i18n-internal/strategy";
13
- function getServerCacheControl() {
14
- const g = globalThis;
15
- if (!g[SERVER_CC_KEY]) {
16
- const cfg = resolveI18nConfigWithRuntimeOverrides(getI18nConfig());
17
- g[SERVER_CC_KEY] = new CacheControl({ maxSize: cfg.cacheMaxSize ?? 0, ttl: cfg.cacheTtl ?? 0 });
18
- }
19
- return g[SERVER_CC_KEY];
20
- }
11
+ import { loadLiveDevTranslations } from "./dev-live-translations.js";
12
+ import { getOrCreateServerTranslationCache } from "./server-translation-cache.js";
21
13
  export async function loadTranslationsFromServer(locale, routeName) {
22
- const cc = getServerCacheControl();
14
+ const cc = getOrCreateServerTranslationCache();
23
15
  const cacheKey = `${locale}:${routeName}`;
24
16
  const cached = cc.get(cacheKey);
25
17
  if (cached) {
@@ -46,21 +38,25 @@ export async function loadTranslationsFromServer(locale, routeName) {
46
38
  cc.set(cacheKey, entry2);
47
39
  return entry2;
48
40
  }
49
- const mode = config.translationPayloadMode === "source" ? "source" : "premerged";
50
41
  let data;
51
- if (mode === "source") {
52
- data = await loadSourceTranslationsFromStorage(
53
- { getItem: (key) => readPayload(key) },
54
- {
55
- locale,
56
- pageName: resolvedPage,
57
- locales: normalizeConfiguredLocales(config.locales),
58
- globalFallbackLocale: config.fallbackLocale,
59
- disablePageLocales: config.disablePageLocales
60
- }
61
- );
42
+ if (import.meta.dev) {
43
+ data = await loadLiveDevTranslations(locale, resolvedPage, config);
62
44
  } else {
63
- data = toTranslations(await readPayload(toPremergedStorageKey(resolvedPage, locale)));
45
+ const mode = config.translationPayloadMode === "source" ? "source" : "premerged";
46
+ if (mode === "source") {
47
+ data = await loadSourceTranslationsFromStorage(
48
+ { getItem: (key) => readPayload(key) },
49
+ {
50
+ locale,
51
+ pageName: resolvedPage,
52
+ locales: normalizeConfiguredLocales(config.locales),
53
+ globalFallbackLocale: config.fallbackLocale,
54
+ disablePageLocales: config.disablePageLocales
55
+ }
56
+ );
57
+ } else {
58
+ data = toTranslations(await readPayload(toPremergedStorageKey(resolvedPage, locale)));
59
+ }
64
60
  }
65
61
  const json = JSON.stringify(data).replace(/</g, "\\u003c");
66
62
  const entry = { data, json };
@@ -0,0 +1,11 @@
1
+ import type { Translations } from '@i18n-micro/types';
2
+ import { CacheControl } from '@i18n-micro/utils/cache-control';
3
+ export type ServerTranslationCacheEntry = {
4
+ data: Translations;
5
+ json: string;
6
+ };
7
+ /** Get or create the process-wide server translation cache (limits applied once at create). */
8
+ export declare function getOrCreateServerTranslationCache(limits?: {
9
+ maxSize: number;
10
+ ttl: number;
11
+ }): CacheControl<ServerTranslationCacheEntry>;
@@ -0,0 +1,20 @@
1
+ import { SERVER_CC_KEY } from "@i18n-micro/hmr/cache-keys";
2
+ import { CacheControl } from "@i18n-micro/utils/cache-control";
3
+ import { resolveI18nConfigWithRuntimeOverrides } from "@i18n-micro/utils/runtime-config";
4
+ import { getI18nConfig } from "#i18n-internal/strategy";
5
+ function isServerTranslationCache(value) {
6
+ return !!value && typeof value === "object" && typeof value.get === "function" && typeof value.set === "function" && typeof value.configure === "function";
7
+ }
8
+ function resolveLimits(limits) {
9
+ if (limits) return limits;
10
+ const cfg = resolveI18nConfigWithRuntimeOverrides(getI18nConfig());
11
+ return { maxSize: cfg.cacheMaxSize ?? 0, ttl: cfg.cacheTtl ?? 0 };
12
+ }
13
+ export function getOrCreateServerTranslationCache(limits) {
14
+ const g = globalThis;
15
+ const existing = g[SERVER_CC_KEY];
16
+ if (isServerTranslationCache(existing)) return existing;
17
+ const created = new CacheControl(resolveLimits(limits));
18
+ g[SERVER_CC_KEY] = created;
19
+ return created;
20
+ }
@@ -26,6 +26,8 @@ declare class TranslationStorage {
26
26
  private freezeChunk;
27
27
  private getCacheKey;
28
28
  private fetchTranslations;
29
+ /** Seed cache without fetching (e.g. `serverTranslationPreload` for index). */
30
+ seed(locale: string, routeName: string | undefined, data: Record<string, unknown>): void;
29
31
  /**
30
32
  * Synchronous cache check and retrieval.
31
33
  * Returns data if cached (and not expired), otherwise null.
@@ -54,6 +54,11 @@ class TranslationStorage {
54
54
  params: request.params
55
55
  });
56
56
  }
57
+ /** Seed cache without fetching (e.g. `serverTranslationPreload` for index). */
58
+ seed(locale, routeName, data) {
59
+ const cacheKey = this.getCacheKey(locale, routeName);
60
+ this.cc.set(cacheKey, this.freezeChunk(data));
61
+ }
57
62
  // ==========================================================================
58
63
  // PUBLIC API
59
64
  // ==========================================================================
package/internals.d.mts CHANGED
@@ -5,6 +5,8 @@ declare module '#build/i18n.plural.mjs' {
5
5
  /** Приватный конфиг i18n (серверный): rootDir, rootDirs, debug, translationDir и т.д. Копия полей ModulePrivateOptionsExtend без импорта. */
6
6
  interface I18nPrivateConfig {
7
7
  rootDir: string
8
+ /** Nuxt layer roots (extends first, project last) for live/HMR merge. */
9
+ rootDirs: string[]
8
10
  debug: boolean
9
11
  translationDir: string
10
12
  additionalTranslationDirs?: string[]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuxt-i18n-micro",
3
- "version": "3.30.0",
3
+ "version": "3.30.1",
4
4
  "description": "Fast, lightweight i18n for Nuxt with strategy-based routing and minimal overhead.",
5
5
  "keywords": [
6
6
  "i18n",
@@ -82,13 +82,13 @@
82
82
  "sirv": "^3.0.2",
83
83
  "ufo": "^1.6.4",
84
84
  "unplugin": "^1.16.1 || ^2.0.0 || ^3.4.0",
85
- "@i18n-micro/path-strategy": "^1.3.19",
86
- "@i18n-micro/route-strategy": "^1.1.28",
87
- "@i18n-micro/hmr": "^1.0.18",
88
- "@i18n-micro/core": "^1.3.21",
89
- "@i18n-micro/utils": "^1.0.26",
90
- "@i18n-micro/test-utils": "^1.2.18",
91
- "@i18n-micro/types": "^1.2.17"
85
+ "@i18n-micro/core": "^1.3.22",
86
+ "@i18n-micro/hmr": "^1.0.20",
87
+ "@i18n-micro/path-strategy": "^1.3.20",
88
+ "@i18n-micro/route-strategy": "^1.1.29",
89
+ "@i18n-micro/types": "^1.2.18",
90
+ "@i18n-micro/utils": "^1.0.27",
91
+ "@i18n-micro/test-utils": "^1.2.19"
92
92
  },
93
93
  "devDependencies": {
94
94
  "@nuxt/devtools": "^3.4.2",
@@ -129,6 +129,7 @@
129
129
  }
130
130
  },
131
131
  "scripts": {
132
+ "preinstall": "node -e \"const{existsSync}=require('fs');if(!existsSync('pnpm-workspace.yaml'))process.exit(0);const ua=process.env.npm_config_user_agent||'';if(!ua.includes('pnpm')){console.error('This repo requires pnpm (npm/yarn corrupt the TypeScript hoist). Use: pnpm install');process.exit(1)}\"",
132
133
  "dev": "nuxi dev playground",
133
134
  "dev:build": "nuxi build playground",
134
135
  "dev:prepare": "nuxt-module-build build --stub && nuxt-module-build prepare && nuxi prepare playground",
@@ -1 +0,0 @@
1
- {"id":"88fb7799-62d6-48e9-a0d3-deeed800130e","timestamp":1790588461763,"prerendered":[]}
File without changes