[{"data":1,"prerenderedAt":1041},["ShallowReactive",2],{"navigation":3,"/blog/nuxt-i18n-routing":146,"surround-nuxt-i18n-routing":1028},[4],{"title":5,"path":6,"stem":7,"children":8,"page":145},"Blog","/blog","blog",[9,13,17,21,25,29,33,37,41,45,49,53,57,61,65,69,73,77,81,85,89,93,97,101,105,109,113,117,121,125,129,133,137,141],{"title":10,"path":11,"stem":12},"How to Increase Free Tier Memory on AWS EC2","/blog/aws-ec2-ram","blog/aws-ec2-ram",{"title":14,"path":15,"stem":16},"Blooper: The Disappearing Cloudflare Variables","/blog/blooper-cloudflare-env-vars","blog/blooper-cloudflare-env-vars",{"title":18,"path":19,"stem":20},"Blooper: Hardcoded Content Links cause 404s","/blog/blooper-hardcoded-nuxt-content-links","blog/blooper-hardcoded-nuxt-content-links",{"title":22,"path":23,"stem":24},"Blooper: The Invisible SEO","/blog/blooper-nuxt-seo-env","blog/blooper-nuxt-seo-env",{"title":26,"path":27,"stem":28},"Blooper: The SSR Crash of Doom","/blog/blooper-ssr-feedback-form","blog/blooper-ssr-feedback-form",{"title":30,"path":31,"stem":32},"Blooper: The YouTube Crawl Budget Killer","/blog/blooper-video-crawl-budget","blog/blooper-video-crawl-budget",{"title":34,"path":35,"stem":36},"Blooper: PWA Redirecting SPA Routes","/blog/blooper-vite-pwa-ssr-redirects","blog/blooper-vite-pwa-ssr-redirects",{"title":38,"path":39,"stem":40},"The Developer's Guide to Avoiding Cloud Billing Traps in 2026","/blog/cloud-billing-traps-2026","blog/cloud-billing-traps-2026",{"title":42,"path":43,"stem":44},"Disk Management in Linux","/blog/disk-management-in-linux","blog/disk-management-in-linux",{"title":46,"path":47,"stem":48},"Docker Devtools Stage | Powerlevel, OhMyZSH, tmux, fuzzy finder, autocomplete etc","/blog/docker-devtools","blog/docker-devtools",{"title":50,"path":51,"stem":52},"Docker container | Resolving Permission Denied Woes: A Decade-Long Struggle Unraveled","/blog/docker-non-root-user-perms","blog/docker-non-root-user-perms",{"title":54,"path":55,"stem":56},"The Ultimate Guide to Free Tier Hosting Platforms (Serverless & Containers)","/blog/free-hosting-platforms-guide","blog/free-hosting-platforms-guide",{"title":58,"path":59,"stem":60},"Git commands | underrated","/blog/git-commands-underrated","blog/git-commands-underrated",{"title":62,"path":63,"stem":64},"Journey: Taming Edge Caching and KV Storage","/blog/journey-github-streak-caching","blog/journey-github-streak-caching",{"title":66,"path":67,"stem":68},"Kubernetes Cluster Setup Guide","/blog/k8s-setup","blog/k8s-setup",{"title":70,"path":71,"stem":72},"Linux WiFi Drivers","/blog/linux-wifi-drivers","blog/linux-wifi-drivers",{"title":74,"path":75,"stem":76},"4 Common Routing Traps When Migrating to Nuxt i18n","/blog/nuxt-i18n-routing","blog/nuxt-i18n-routing",{"title":78,"path":79,"stem":80},"pfSense basic firewall setup","/blog/pfsense-basic-firewall-setup","blog/pfsense-basic-firewall-setup",{"title":82,"path":83,"stem":84},"pfSense Quickstart","/blog/pfsense-quickstart","blog/pfsense-quickstart",{"title":86,"path":87,"stem":88},"Postmortem: Cloudflare Worker Missing Dependency on Deploy","/blog/postmortem-cloudflare-worker-dependency-deploy","blog/postmortem-cloudflare-worker-dependency-deploy",{"title":90,"path":91,"stem":92},"Postmortem: Serverless HTTP Driver Transaction Failures","/blog/postmortem-neon-http-transactions","blog/postmortem-neon-http-transactions",{"title":94,"path":95,"stem":96},"Postmortem: The Ghost in the Chrome Cache (Nuxt & Cloudflare Pages)","/blog/postmortem-nuxt-cloudflare-chunk-error","blog/postmortem-nuxt-cloudflare-chunk-error",{"title":98,"path":99,"stem":100},"Postmortem: Nuxt Content 404s on Staging Deployments","/blog/postmortem-nuxt-content-404-staging","blog/postmortem-nuxt-content-404-staging",{"title":102,"path":103,"stem":104},"Postmortem: 500 Internal Server Error on ISR Routes","/blog/postmortem-nuxt-content-payload-extraction","blog/postmortem-nuxt-content-payload-extraction",{"title":106,"path":107,"stem":108},"Post-Mortem: Intrusive Database Driver Refactoring","/blog/postmortem-proxy-re-architecting","blog/postmortem-proxy-re-architecting",{"title":110,"path":111,"stem":112},"Post-Mortem: Cloudflare Worker Connection Hang & Resilient DB Fallbacks","/blog/postmortem-worker-db-connection-hang","blog/postmortem-worker-db-connection-hang",{"title":114,"path":115,"stem":116},"Pro Tip: Sandboxing Cloudflare Workers for AI Agents","/blog/pro-tip-wrangler-local-dev-trick","blog/pro-tip-wrangler-local-dev-trick",{"title":118,"path":119,"stem":120},"Proxmox DNS Management","/blog/proxmox-dns","blog/proxmox-dns",{"title":122,"path":123,"stem":124},"Proxmox Recovery","/blog/proxmox-recovery","blog/proxmox-recovery",{"title":126,"path":127,"stem":128},"Proxmox WiFi Connection Story","/blog/proxmox-wifi","blog/proxmox-wifi",{"title":130,"path":131,"stem":132},"roadauth-rails api jwt cors","/blog/rodauth-jwt","blog/rodauth-jwt",{"title":134,"path":135,"stem":136},"SOCKS5 Proxy Quickstart","/blog/sock5-proxy","blog/sock5-proxy",{"title":138,"path":139,"stem":140},"tmux status bar toggle","/blog/tmux-status","blog/tmux-status",{"title":142,"path":143,"stem":144},"UFW - Cheatsheet","/blog/ufw-cheatsheet","blog/ufw-cheatsheet",false,{"id":147,"title":74,"authors":148,"badge":154,"body":156,"date":1019,"description":1020,"extension":1021,"image":1022,"imageComponent":1022,"meta":1023,"navigation":248,"path":75,"pinned":145,"seo":1024,"seoImage":1025,"stem":76,"__hash__":1027},"posts/blog/nuxt-i18n-routing.md",[149],{"name":150,"to":151,"avatar":152},"Rahul Dhole","/",{"src":153},"/profile.png",{"label":155},"Nuxt",{"type":157,"value":158,"toc":1010},"minimark",[159,176,203,206,209,212,217,220,226,285,308,313,320,323,358,361,380,382,386,389,393,427,430,442,456,489,503,557,559,563,566,571,586,601,606,619,634,657,659,663,666,670,709,722,729,737,864,868,874,907,910,912,917,925,1003,1006],[160,161,162,163,167,168,175],"p",{},"If you're adding translations to your NuxtJS app using ",[164,165,166],"code",{},"@nuxtjs/i18n",", you probably expect it to be a simple config change. But there is a massive gotcha that caught me totally off guard while translating ",[169,170,174],"a",{"href":171,"rel":172},"https://neoncv.ai",[173],"nofollow","neoncv.ai",": your URLs are no longer static.",[160,177,178,179,182,183,186,187,190,191,194,195,198,199,202],{},"Depending on your i18n routing strategy (like ",[164,180,181],{},"prefix_except_default"," or ",[164,184,185],{},"prefix","), that predictable ",[164,188,189],{},"/dashboard"," route dynamically shifts to ",[164,192,193],{},"/fr/dashboard",", ",[164,196,197],{},"/ja/dashboard",", or ",[164,200,201],{},"/es/dashboard",".",[160,204,205],{},"This one detail shatters standard Vue routing logic relying on exact path strings. After untangling broken links and missing transitions, I realized most tutorials skip the painful part: retrofitting a large, existing codebase.",[160,207,208],{},"Here are 4 architectural traps you will hit, and the senior-level patterns you should use instead.",[210,211],"hr",{},[213,214,216],"h2",{"id":215},"trap-1-brittle-path-checking","Trap 1: Brittle Path Checking",[160,218,219],{},"It's common to check if a user is inside a specific section of the app to trigger middleware, animations, or load third-party scripts (like a support chat widget only on marketing pages).",[160,221,222],{},[223,224,225],"strong",{},"The Mistake:",[227,228,233],"pre",{"className":229,"code":230,"language":231,"meta":232,"style":232},"language-javascript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","const route = useRoute()\n\n// ❌ Breaks instantly on localized paths like /fr/tracker\nconst isTrackerChild = route.path.startsWith('/tracker/')\n\n// ❌ A fragile string-sniffing workaround\nconst routeName = String(route.name || '')\nconst isTrackerChildWorkaround = routeName.startsWith('tracker-')\n","javascript","",[164,234,235,243,250,256,262,267,273,279],{"__ignoreMap":232},[236,237,240],"span",{"class":238,"line":239},"line",1,[236,241,242],{},"const route = useRoute()\n",[236,244,246],{"class":238,"line":245},2,[236,247,249],{"emptyLinePlaceholder":248},true,"\n",[236,251,253],{"class":238,"line":252},3,[236,254,255],{},"// ❌ Breaks instantly on localized paths like /fr/tracker\n",[236,257,259],{"class":238,"line":258},4,[236,260,261],{},"const isTrackerChild = route.path.startsWith('/tracker/')\n",[236,263,265],{"class":238,"line":264},5,[236,266,249],{"emptyLinePlaceholder":248},[236,268,270],{"class":238,"line":269},6,[236,271,272],{},"// ❌ A fragile string-sniffing workaround\n",[236,274,276],{"class":238,"line":275},7,[236,277,278],{},"const routeName = String(route.name || '')\n",[236,280,282],{"class":238,"line":281},8,[236,283,284],{},"const isTrackerChildWorkaround = routeName.startsWith('tracker-')\n",[160,286,287,288,291,292,295,296,299,300,303,304,307],{},"Relying on ",[164,289,290],{},"route.path"," fails because the path changes with locales. Switching to ",[164,293,294],{},"route.name.startsWith()"," is slightly better, but replaces one brittle hack with another. What if someone renames ",[164,297,298],{},"tracker/[id].vue"," to ",[164,301,302],{},"tracker/detail-[id].vue","? Or what if ",[164,305,306],{},"tracker-settings.vue"," accidentally triggers it?",[160,309,310],{},[223,311,312],{},"The Senior Fix: Route Meta",[160,314,315,316,319],{},"Use Vue Router's native ",[164,317,318],{},"route.meta",". It's immune to locale prefixes, renaming, and string sniffing.",[160,321,322],{},"Define it in your pages:",[227,324,326],{"className":229,"code":325,"language":231,"meta":232,"style":232},"// pages/tracker/[id].vue\ndefinePageMeta({\n  section: 'tracker',\n  requiresAuth: true,\n  loadSupportChat: false\n})\n",[164,327,328,333,338,343,348,353],{"__ignoreMap":232},[236,329,330],{"class":238,"line":239},[236,331,332],{},"// pages/tracker/[id].vue\n",[236,334,335],{"class":238,"line":245},[236,336,337],{},"definePageMeta({\n",[236,339,340],{"class":238,"line":252},[236,341,342],{},"  section: 'tracker',\n",[236,344,345],{"class":238,"line":258},[236,346,347],{},"  requiresAuth: true,\n",[236,349,350],{"class":238,"line":264},[236,351,352],{},"  loadSupportChat: false\n",[236,354,355],{"class":238,"line":269},[236,356,357],{},"})\n",[160,359,360],{},"Check it in your middleware or computed properties:",[227,362,364],{"className":229,"code":363,"language":231,"meta":232,"style":232},"// middleware/auth.ts or chat widget logic\nconst route = useRoute()\nconst isTrackerChild = route.meta.section === 'tracker'\n",[164,365,366,371,375],{"__ignoreMap":232},[236,367,368],{"class":238,"line":239},[236,369,370],{},"// middleware/auth.ts or chat widget logic\n",[236,372,373],{"class":238,"line":245},[236,374,242],{},[236,376,377],{"class":238,"line":252},[236,378,379],{},"const isTrackerChild = route.meta.section === 'tracker'\n",[210,381],{},[213,383,385],{"id":384},"trap-2-context-blind-navigation","Trap 2: Context-Blind Navigation",[160,387,388],{},"If you have custom \"go back\" buttons or logic that redirects users, you likely have navigation calls scattered everywhere.",[160,390,391],{},[223,392,225],{},[227,394,396],{"className":229,"code":395,"language":231,"meta":232,"style":232},"const router = useRouter()\n\n// ❌ Kicks the user out of their localized environment\nfunction goBack() {\n  router.push('/pricing')\n}\n",[164,397,398,403,407,412,417,422],{"__ignoreMap":232},[236,399,400],{"class":238,"line":239},[236,401,402],{},"const router = useRouter()\n",[236,404,405],{"class":238,"line":245},[236,406,249],{"emptyLinePlaceholder":248},[236,408,409],{"class":238,"line":252},[236,410,411],{},"// ❌ Kicks the user out of their localized environment\n",[236,413,414],{"class":238,"line":258},[236,415,416],{},"function goBack() {\n",[236,418,419],{"class":238,"line":264},[236,420,421],{},"  router.push('/pricing')\n",[236,423,424],{"class":238,"line":269},[236,425,426],{},"}\n",[160,428,429],{},"If a user from Japan reading your pricing page triggers this, they are instantly kicked back to the default English route.",[160,431,432],{},[223,433,434,435,438,439],{},"The Fix: ",[164,436,437],{},"navigateTo"," and ",[164,440,441],{},"\u003CNuxtLinkLocale>",[160,443,444,445,448,449,451,452,455],{},"For programmatic navigation, wrap the path in ",[164,446,447],{},"useLocalePath()"," and use Nuxt's ",[164,450,437],{}," (which safely handles SSR context and cross-environment navigation, unlike raw ",[164,453,454],{},"router.push",").",[227,457,459],{"className":229,"code":458,"language":231,"meta":232,"style":232},"const localePath = useLocalePath()\n\n// ✅ Safely navigates while preserving locale and SSR context\nasync function goBack() {\n  await navigateTo(localePath('/pricing'))\n}\n",[164,460,461,466,470,475,480,485],{"__ignoreMap":232},[236,462,463],{"class":238,"line":239},[236,464,465],{},"const localePath = useLocalePath()\n",[236,467,468],{"class":238,"line":245},[236,469,249],{"emptyLinePlaceholder":248},[236,471,472],{"class":238,"line":252},[236,473,474],{},"// ✅ Safely navigates while preserving locale and SSR context\n",[236,476,477],{"class":238,"line":258},[236,478,479],{},"async function goBack() {\n",[236,481,482],{"class":238,"line":264},[236,483,484],{},"  await navigateTo(localePath('/pricing'))\n",[236,486,487],{"class":238,"line":269},[236,488,426],{},[160,490,491,492,495,496,498,499,502],{},"For template navigation, stop hardcoding ",[164,493,494],{},"\u003CNuxtLink to=\"/pricing\">",". Use the built-in ",[164,497,441],{}," component instead. It automatically wraps your paths in ",[164,500,501],{},"localePath()"," under the hood.",[227,504,508],{"className":505,"code":506,"language":507,"meta":232,"style":232},"language-vue shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u003C!-- ✅ Automatically resolves to /fr/pricing for French users -->\n\u003CNuxtLinkLocale to=\"/pricing\">Pricing\u003C/NuxtLinkLocale>\n","vue",[164,509,510,516],{"__ignoreMap":232},[236,511,512],{"class":238,"line":239},[236,513,515],{"class":514},"sHwdD","\u003C!-- ✅ Automatically resolves to /fr/pricing for French users -->\n",[236,517,518,522,526,530,533,536,540,542,545,549,552,554],{"class":238,"line":245},[236,519,521],{"class":520},"sMK4o","\u003C",[236,523,525],{"class":524},"swJcz","NuxtLinkLocale",[236,527,529],{"class":528},"spNyl"," to",[236,531,532],{"class":520},"=",[236,534,535],{"class":520},"\"",[236,537,539],{"class":538},"sfazB","/pricing",[236,541,535],{"class":520},[236,543,544],{"class":520},">",[236,546,548],{"class":547},"sTEyZ","Pricing",[236,550,551],{"class":520},"\u003C/",[236,553,525],{"class":524},[236,555,556],{"class":520},">\n",[210,558],{},[213,560,562],{"id":561},"trap-3-reinventing-active-link-states","Trap 3: Reinventing Active Link States",[160,564,565],{},"When building a custom sidebar or navigation menu, you need to highlight the active route.",[160,567,568,570],{},[223,569,225],{},"\nManually hacking active link detection by comparing strings.",[227,572,574],{"className":229,"code":573,"language":231,"meta":232,"style":232},"// ❌ Custom logic that fails on nested routes and edge cases\nconst isActive = (path) => route.path.startsWith(localePath(path))\n",[164,575,576,581],{"__ignoreMap":232},[236,577,578],{"class":238,"line":239},[236,579,580],{},"// ❌ Custom logic that fails on nested routes and edge cases\n",[236,582,583],{"class":238,"line":245},[236,584,585],{},"const isActive = (path) => route.path.startsWith(localePath(path))\n",[160,587,588,589,592,593,596,597,600],{},"This gets messy incredibly fast, and edge cases (like ",[164,590,591],{},"/tracker"," matching ",[164,594,595],{},"/tracker-archive"," due to ",[164,598,599],{},".startsWith()",") will inevitably cause bugs.",[160,602,603],{},[223,604,605],{},"The Fix: Native Router Link Resolution",[160,607,608,609,611,612,438,615,618],{},"Don't reinvent the wheel. ",[164,610,441],{}," natively applies standard ",[164,613,614],{},"router-link-active",[164,616,617],{},"router-link-exact-active"," classes automatically.",[160,620,621,622,626,627,629,630,633],{},"If you ",[623,624,625],"em",{},"must"," build a highly custom wrapper component that can't use ",[164,628,441],{}," directly, leverage Vue Router's ",[164,631,632],{},"useLink"," with the localized path to tap into its robust resolution engine.",[227,635,637],{"className":229,"code":636,"language":231,"meta":232,"style":232},"const localePath = useLocalePath()\n\n// Leverage Vue Router's bulletproof logic\nconst { isActive, isExactActive } = useLink({ to: localePath('/dashboard') })\n",[164,638,639,643,647,652],{"__ignoreMap":232},[236,640,641],{"class":238,"line":239},[236,642,465],{},[236,644,645],{"class":238,"line":245},[236,646,249],{"emptyLinePlaceholder":248},[236,648,649],{"class":238,"line":252},[236,650,651],{},"// Leverage Vue Router's bulletproof logic\n",[236,653,654],{"class":238,"line":258},[236,655,656],{},"const { isActive, isExactActive } = useLink({ to: localePath('/dashboard') })\n",[210,658],{},[213,660,662],{"id":661},"trap-4-locale-switching-query-preservation","Trap 4: Locale Switching & Query Preservation",[160,664,665],{},"Adding a language toggle seems easy until your users try it mid-session on a dynamic route or a page with active filters.",[160,667,668],{},[223,669,225],{},[227,671,673],{"className":505,"code":672,"language":507,"meta":232,"style":232},"\u003C!-- ❌ Loses route parameters and query strings -->\n\u003Ca href=\"/fr/search\">Français\u003C/a>\n",[164,674,675,680],{"__ignoreMap":232},[236,676,677],{"class":238,"line":239},[236,678,679],{"class":514},"\u003C!-- ❌ Loses route parameters and query strings -->\n",[236,681,682,684,686,689,691,693,696,698,700,703,705,707],{"class":238,"line":245},[236,683,521],{"class":520},[236,685,169],{"class":524},[236,687,688],{"class":528}," href",[236,690,532],{"class":520},[236,692,535],{"class":520},[236,694,695],{"class":538},"/fr/search",[236,697,535],{"class":520},[236,699,544],{"class":520},[236,701,702],{"class":547},"Français",[236,704,551],{"class":520},[236,706,169],{"class":524},[236,708,556],{"class":520},[160,710,711,712,715,716,718,719,202],{},"If a user is on ",[164,713,714],{},"/search?q=nuxt"," and clicks your language toggle, redirecting them strictly to ",[164,717,695],{}," wipes out their search query. The same happens on dynamic routes like ",[164,720,721],{},"/users/123",[160,723,724],{},[223,725,434,726],{},[164,727,728],{},"switchLocalePath()",[160,730,731,733,734,736],{},[164,732,166],{}," provides a ",[164,735,728],{}," composable specifically for this. It takes the current route context (including dynamic parameters and query strings) and safely translates it to the target language.",[227,738,740],{"className":505,"code":739,"language":507,"meta":232,"style":232},"\u003Cscript setup>\nconst switchLocalePath = useSwitchLocalePath()\n\u003C/script>\n\n\u003Ctemplate>\n  \u003Cdiv>\n    \u003C!-- ✅ Preserves /search?q=nuxt -> /fr/search?q=nuxt -->\n    \u003CNuxtLink :to=\"switchLocalePath('fr')\">\n      Français\n    \u003C/NuxtLink>\n  \u003C/div>\n\u003C/template>\n",[164,741,742,754,771,779,783,792,802,807,829,835,845,855],{"__ignoreMap":232},[236,743,744,746,749,752],{"class":238,"line":239},[236,745,521],{"class":520},[236,747,748],{"class":524},"script",[236,750,751],{"class":528}," setup",[236,753,556],{"class":520},[236,755,756,759,762,764,768],{"class":238,"line":245},[236,757,758],{"class":528},"const",[236,760,761],{"class":547}," switchLocalePath ",[236,763,532],{"class":520},[236,765,767],{"class":766},"s2Zo4"," useSwitchLocalePath",[236,769,770],{"class":547},"()\n",[236,772,773,775,777],{"class":238,"line":252},[236,774,551],{"class":520},[236,776,748],{"class":524},[236,778,556],{"class":520},[236,780,781],{"class":238,"line":258},[236,782,249],{"emptyLinePlaceholder":248},[236,784,785,787,790],{"class":238,"line":264},[236,786,521],{"class":520},[236,788,789],{"class":524},"template",[236,791,556],{"class":520},[236,793,794,797,800],{"class":238,"line":269},[236,795,796],{"class":520},"  \u003C",[236,798,799],{"class":524},"div",[236,801,556],{"class":520},[236,803,804],{"class":238,"line":275},[236,805,806],{"class":514},"    \u003C!-- ✅ Preserves /search?q=nuxt -> /fr/search?q=nuxt -->\n",[236,808,809,812,815,818,820,822,825,827],{"class":238,"line":281},[236,810,811],{"class":520},"    \u003C",[236,813,814],{"class":524},"NuxtLink",[236,816,817],{"class":528}," :to",[236,819,532],{"class":520},[236,821,535],{"class":520},[236,823,824],{"class":538},"switchLocalePath('fr')",[236,826,535],{"class":520},[236,828,556],{"class":520},[236,830,832],{"class":238,"line":831},9,[236,833,834],{"class":547},"      Français\n",[236,836,838,841,843],{"class":238,"line":837},10,[236,839,840],{"class":520},"    \u003C/",[236,842,814],{"class":524},[236,844,556],{"class":520},[236,846,848,851,853],{"class":238,"line":847},11,[236,849,850],{"class":520},"  \u003C/",[236,852,799],{"class":524},[236,854,556],{"class":520},[236,856,858,860,862],{"class":238,"line":857},12,[236,859,551],{"class":520},[236,861,789],{"class":524},[236,863,556],{"class":520},[213,865,867],{"id":866},"wrapping-up","Wrapping up",[160,869,870,871,873],{},"Integrating ",[164,872,166],{}," into a production codebase taught me these vital rules:",[875,876,877,886,898,901],"ol",{},[878,879,880,881,883,884,202],"li",{},"Ditch ",[164,882,290],{}," checking in favor of ",[164,885,318],{},[878,887,888,889,892,893,438,896,202],{},"Replace hardcoded ",[164,890,891],{},"router.push()"," with ",[164,894,895],{},"navigateTo(localePath())",[164,897,441],{},[878,899,900],{},"Let Vue Router handle active link states.",[878,902,903,904,906],{},"Always use ",[164,905,728],{}," for language toggles.",[160,908,909],{},"Adopt these architectural patterns early, and you'll save yourself massive headaches taking your app global.",[210,911],{},[913,914,916],"h3",{"id":915},"bonus-the-ai-refactoring-prompt","Bonus: The AI Refactoring Prompt",[160,918,919,920,438,922,924],{},"If you are retrofitting a large, existing codebase and don't want to hunt down every single ",[164,921,454],{},[164,923,290],{}," manually, drop this prompt into your AI coding assistant (like GitHub Copilot, Cursor, or Gemini):",[926,927,928,945,948,974,977],"blockquote",{},[160,929,930,931,933,934,194,937,940,941,944],{},"\"I am migrating my Nuxt 3 application to ",[164,932,166],{},". Scan my ",[164,935,936],{},"pages",[164,938,939],{},"components",", and ",[164,942,943],{},"middleware"," directories for Nuxt routing anti-patterns.",[160,946,947],{},"Specifically, look for:",[875,949,950,958,967],{},[878,951,952,953,182,955,202],{},"Hardcoded string checks against ",[164,954,290],{},[164,956,957],{},"route.name",[878,959,960,961,182,963,966],{},"Direct usage of ",[164,962,891],{},[164,964,965],{},"navigateTo()"," with static strings.",[878,968,969,970,973],{},"Standard ",[164,971,972],{},"\u003CNuxtLink>"," components or manual active link logic.",[160,975,976],{},"Refactor them using Nuxt i18n best practices:",[978,979,980,985,990,997],"ul",{},[878,981,982,983,202],{},"Replace route path checking with ",[164,984,318],{},[878,986,987,988,202],{},"Wrap programmatic navigation paths in ",[164,989,501],{},[878,991,992,993,892,995,202],{},"Replace standard ",[164,994,972],{},[164,996,441],{},[878,998,999,1000,1002],{},"Use ",[164,1001,728],{}," for language toggles.\"",[160,1004,1005],{},"Let the AI do the heavy lifting, and enjoy your newly localized app!",[1007,1008,1009],"style",{},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sHwdD, html code.shiki .sHwdD{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic}html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .swJcz, html code.shiki .swJcz{--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178}html pre.shiki code .spNyl, html code.shiki .spNyl{--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA}html pre.shiki code .sfazB, html code.shiki .sfazB{--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html pre.shiki code .s2Zo4, html code.shiki .s2Zo4{--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF}",{"title":232,"searchDepth":245,"depth":245,"links":1011},[1012,1013,1014,1015,1016],{"id":215,"depth":245,"text":216},{"id":384,"depth":245,"text":385},{"id":561,"depth":245,"text":562},{"id":661,"depth":245,"text":662},{"id":866,"depth":245,"text":867,"children":1017},[1018],{"id":915,"depth":252,"text":916},"2026-09-28","How to fix broken navigation, missing widgets, and active links when migrating a NuxtJS app to @nuxtjs/i18n.","md",null,{},{"title":74,"description":1020},{"src":1026},"https://placehold.co/800x400/0f172a/3b82f6?text=Nuxt+i18n+Routing","RLyEVtMsks4KOCaCnvkKnQo3JtJN8Zui_dbSAWJ_smY",[1029,1035],{"title":70,"path":71,"stem":72,"description":1030,"imageComponent":1031,"seoImage":1033,"children":-1},"Linux WiFi Drivers - Dive into the details of linux wifi drivers with this quick guide.",{"type":1032},"Linux",{"src":1034},"https://placehold.co/800x400/0f172a/3b82f6?text=Linux+WiFi+Drivers",{"title":78,"path":79,"stem":80,"description":1036,"imageComponent":1037,"seoImage":1039,"children":-1},"pfSense basic firewall setup - Dive into the details of pfsense basic firewall setup with this quick guide.",{"type":1038},"Networking",{"src":1040},"https://placehold.co/800x400/0f172a/3b82f6?text=pfSense+basic+firewall+setup",1790624691474]