I recently built a multilingual fan site for The Duskbloods, an upcoming FromSoftware game.
The challenge: 9 languages (English, Japanese, Korean, Chinese, Spanish, French, German, Italian, Portuguese), static generation, and no middleware — all deployed on Cloudflare Workers.
Here's how I did it and what I learned.
The Architecture The site uses Next.js 15 App Router with next-intl v4 for internationalization.
The key constraint: I wanted to avoid middleware to keep Cloudflare Worker costs down.
Route Groups for Language Separation Instead of using middleware to detect locale, I use route groups: — English content at the root path — Other languages at , , , etc.
This means English gets clean URLs () while other languages get prefixed URLs ().
Good for SEO — English is the default, and other languages have clear URL signals.
Why No Middleware?
Cloudflare Workers charge per request.
Middleware runs on every request.
For a static site with 9 languages, that's 9x the middleware invocations for every page load.
By handling locale in the route, I skip middleware entirely.
This pre-generates all locale variants at build time.
Zero runtime locale detection.
The Translation System Message Files Each locale has a JSON message file: Components Are Language-Agnostic The same view component renders all languages — only the message file changes: Handling Structured Content For arrays and objects, I use : Optional Sections with Safe Loading Some content exists in some languages but not others.
I created a helper: This way, sections gracefully degrade when translations are missing.
Content Sourcing The game has an official gameplay guide in 9 languages.
I fetched each version and extracted structured content: This gave me official translations for all 9 languages — no machine translation needed.
External Images The game's official CDN hosts screenshots and gameplay images.
I reference them directly: No need to host images myself.
The CDN is fast and reliable.
Deployment on Cloudflare Workers I use OpenNext to build for Cloudflare: The build outputs static HTML for all 9 language variants.
Cloudflare serves them globally with zero cold starts.
SEO Considerations Sitemap Structured Data Each page includes JSON-LD breadcrumbs: What I Learned Route groups > middleware for static multilingual sites.
Simpler, cheaper, better for SEO. is your friend.
Don't try to translate arrays with — use and type the result.
Safe loading prevents crashes.
Missing translations shouldn't break the build.
Use try/catch and null checks.
Official translations beat machine translation.
If the content exists in multiple languages from the source, use it.
Cloudflare Workers + OpenNext works well for static multilingual sites.
No cold starts, global CDN, reasonable cost.
The site is live at duskbloods.net with all 9 languages fully translated.
The code is a standard Next.js 15 project — if you're building something similar, the patterns above should work for you.
Questions or suggestions?
Drop a comment below.