diff --git a/public/sw.js b/public/sw.js index 8c8141415..c1de63368 100644 --- a/public/sw.js +++ b/public/sw.js @@ -168,6 +168,17 @@ self.addEventListener("fetch", (event) => { return; } + // Locale-catalog boot script — cache-first. The URL is versioned + // (`/i18n/?v=`) and served immutable, so cache-first is + // correct and keeps the catalog available on an offline relaunch (the + // cached shell HTML references the same versioned URL it was rendered + // with). Carries no user data — same public strings as the repository's + // messages/*.json. + if (url.pathname.startsWith("/i18n/")) { + event.respondWith(cacheFirst(request, STATIC_CACHE)); + return; + } + // Static files (fonts, icons, images) — cache-first with long TTL if (/\.(png|svg|jpg|jpeg|gif|webp|ico|woff2?|ttf|eot)$/i.test(url.pathname)) { event.respondWith(cacheFirst(request, STATIC_CACHE)); diff --git a/src/app/i18n/[locale]/route.ts b/src/app/i18n/[locale]/route.ts new file mode 100644 index 000000000..244829fcb --- /dev/null +++ b/src/app/i18n/[locale]/route.ts @@ -0,0 +1,51 @@ +import { NextResponse } from "next/server"; + +import { locales, type Locale } from "@/lib/i18n/config"; +import { allMessages } from "@/lib/i18n/shared-resolve"; + +/** + * Locale-catalog boot script. + * + * The root layout emits `