Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Sichere ProgrammierungBreeze TTS 2 vs ElevenLabs: Open Source TTS Verdict(23.09.2026 um 05:44 Uhr)
Sichere ProgrammierungAgentic AI vs Generative AI: The 2026 Verdict(23.09.2026 um 05:44 Uhr)
Sichere ProgrammierungI made my agent prove every quote against the source document(23.09.2026 um 05:45 Uhr)
Sichere Programmierung8mb.video Alternative: Skip the Line, Skip the Upsell(23.09.2026 um 05:47 Uhr)
Sichere ProgrammierungBuilding a GTA 6 JSON API for entities and current status(23.09.2026 um 05:52 Uhr)
Sichere ProgrammierungEvery filter needs a documented exception(23.09.2026 um 06:01 Uhr)
Sichere ProgrammierungBreeze TTS 2 vs ElevenLabs: Open Source TTS Verdict(23.09.2026 um 05:44 Uhr)
Sichere ProgrammierungAgentic AI vs Generative AI: The 2026 Verdict(23.09.2026 um 05:44 Uhr)
Sichere ProgrammierungI made my agent prove every quote against the source document(23.09.2026 um 05:45 Uhr)
Sichere Programmierung8mb.video Alternative: Skip the Line, Skip the Upsell(23.09.2026 um 05:47 Uhr)
Sichere ProgrammierungBuilding a GTA 6 JSON API for entities and current status(23.09.2026 um 05:52 Uhr)
Sichere ProgrammierungEvery filter needs a documented exception(23.09.2026 um 06:01 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

How I Added i18n to My Next.js App Router Project

Hey everyone! I recently added multilingual support (Japanese + English) to my side project unsolved — a silly joke app that takes your everyday problems and generates a sci-fi story about how "humanity's collective wisdom" solved it. 😄…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

Hey everyone!



I recently added multilingual support (Japanese + English) to my side project unsolved — a silly joke app that takes your everyday problems and generates a sci-fi story about how "humanity's collective wisdom" solved it. 😄



Since the concept is kind of universal (everyone has problems, right?), I wanted English-speaking users to enjoy it too. So I went ahead and implemented i18n.



In this post, I'll walk through how I did it using next-intl — which turned out to be a great fit for Next.js App Router.






Why next-intl?



Next.js does have its own i18n config, but it doesn't play super nicely with App Router. After some research, next-intl seemed like the most App Router-friendly option out there, with solid TypeScript support to boot.



Installation is just:




npm install next-intl









File Structure Overview



Here's what the project looks like after setup:




src/
├── middleware.ts # Locale detection & redirect
├── i18n/
│ ├── routing.ts # Supported locales & default
│ ├── request.ts # Server-side message loading
│ └── navigation.ts # Locale-aware Link/useRouter
├── app/
│ └── [locale]/ # All pages live here
│ ├── layout.tsx
│ ├── page.tsx
│ └── LocaleSwitcher.tsx
└── messages/
├── ja.json
└── en.json






Let's go through each piece.






Define Your Locales ( src/i18n/routing.ts )






import { defineRouting } from 'next-intl/routing'

export const routing = defineRouting({
locales: ['ja', 'en'],
defaultLocale: 'ja',
localePrefix: 'as-needed',
})






With localePrefix: 'as-needed', the default language (Japanese) uses / and English uses /en/. Change it to always if you want /ja/ and /en/ for all locales.






Middleware ( src/middleware.ts )






import createMiddleware from 'next-intl/middleware'
import { routing } from './i18n/routing'

export default createMiddleware(routing)

export const config = {
matcher: ['/((?!api|_next|_vercel|.*\..*).*)'],
}






This middleware reads the browser's language setting and automatically redirects to the right locale. Visitors with English browsers get sent to /en/ — all handled by this one file.






Server-side Request Config ( src/i18n/request.ts )






import { getRequestConfig } from 'next-intl/server'
import { routing } from './routing'

export default getRequestConfig(async ({ requestLocale }) => {
let locale = await requestLocale
if (!locale || !(routing.locales as readonly string[]).includes(locale)) {
locale = routing.defaultLocale
}

const messages =
locale === 'en'
? (await import('../../messages/en.json')).default
: (await import('../../messages/ja.json')).default

return { locale, messages }
})






This loads the right translation file per request. Invalid locales fall back to the default — no worries about weird URLs.






next.config.ts






import type { NextConfig } from 'next'
import createNextIntlPlugin from 'next-intl/plugin'

const withNextIntl = createNextIntlPlugin('./src/i18n/request.ts')

const nextConfig: NextConfig = {}

export default withNextIntl(nextConfig)









Translation Files



messages/en.json




{
"metadata": {
"title": "Humanity Never Gives Up",
"description": "Solve your problems with the collective wisdom of humanity"
},
"header": {
"title": "Humanity Never Gives Up",
"sub": "You saved the world"
},
"input": {
"nameLabel": "Your Name",
"submitBtn": "Request a Solution"
}
}






Keys are nested and accessed with dot notation like t('header.title'). Simple and TypeScript-friendly.






Navigation Utilities ( src/i18n/navigation.ts )






import { createNavigation } from 'next-intl/navigation'
import { routing } from './routing'

export const { Link, redirect, usePathname, useRouter } = createNavigation(routing)






Use this Link instead of Next.js's built-in one — locale is carried over automatically.






The [locale] Layout ( src/app/[locale]/layout.tsx )



All pages go under app/[locale]/. This is the key structural change.




import { NextIntlClientProvider } from 'next-intl'
import { getMessages, getTranslations } from 'next-intl/server'
import { notFound } from 'next/navigation'
import { routing } from '@/i18n/routing'

type Props = {
children: React.ReactNode
params: Promise<{ locale: string }>
}

export async function generateMetadata({ params }: Props) {
const { locale } = await params
const t = await getTranslations({ locale, namespace: 'metadata' })
return {
title: t('title'),
description: t('description'),
}
}

export function generateStaticParams() {
return routing.locales.map((locale) => ({ locale }))
}

export default async function LocaleLayout({ children, params }: Props) {
const { locale } = await params
if (!routing.locales.includes(locale as 'ja' | 'en')) notFound()

const messages = await getMessages()

return (
<html lang={locale}>
<body>
<NextIntlClientProvider messages={messages}>
{children}
</NextIntlClientProvider>
</body>
</html>
)
}






NextIntlClientProvider passes translations down to Client Components too. Any unsupported locale hits notFound() and returns a 404.






Using Translations



In a Server Component, use getTranslations (async):




import { getTranslations } from 'next-intl/server'

export default async function Page() {
const t = await getTranslations('header')
return <h1>{t('title')}</h1>
}






In a Client Component, use the useTranslations hook:




'use client'

import { useTranslations } from 'next-intl'

export default function SubmitButton() {
const t = useTranslations('input')
return <button>{t('submitBtn')}</button>
}









Language Switcher Component



Here's the actual LocaleSwitcher from unsolved:




'use client'

import { useState } from 'react'
import { useLocale } from 'next-intl'
import { Link, usePathname } from '@/i18n/navigation'
import { routing } from '@/i18n/routing'

export default function LocaleSwitcher() {
const locale = useLocale()
const pathname = usePathname()
const [open, setOpen] = useState(false)

return (
<div>
<button onClick={() => setOpen(o => !o)}>
🌐 {locale.toUpperCase()}
</button>
{open && (
<div>
{routing.locales.map(l => (
<Link key={l} href={pathname} locale={l} onClick={() => setOpen(false)}>
{l.toUpperCase()}
</Link>
))}
</div>
)}
</div>
)
}






<Link href={pathname} locale={l}> keeps you on the same page and just swaps the locale — next-intl handles the URL conversion automatically.






Wrapping Up




  • next-intl works great with Next.js App Router and is easy to set up

  • The middleware handles automatic locale detection and redirects

  • Use getTranslations in Server Components, useTranslations in Client Components

  • Once the config is in place, adding new translations is just editing JSON files



You can see all of this running live at unsolved. It's a little joke app — type in a problem, and it generates a ridiculous sci-fi story about how AI saved the day. Hit the 🌐 button in the top right to switch languages!



Feel free to leave a comment if you have any questions!

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten How I Added i18n to My Next.js App Router Project

Thematisch verwandte Begriffe: Added, i18n, Nextjs, Router · 6 Treffer

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-18163 | IBM Financial Transaction Manager (FTM) for RedHat OpenShift could allow…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick