Internationalization

Multi-language support with next-intl

Installation

1

Included by Default

Internationalization is included by default in every Codelesskit project. No installation is required.

When you initialize a new Codelesskit project with codelesskit init, internationalization support is automatically set up and ready to use.

File Tree

The following files are installed when you add Internationalization:

File Structure
1
2
3
4
5
6
7
├─ i18n/
│ ├─ request.ts
│ └─ routing.ts
└─ messages/
├─ en.json
├─ es.json
└─ fr.json

Usage

Once you've installed Internationalization, you can start using the following actions:

Adding Translations

Add translations to your message files. Structure your translations using namespaces for better organization. Here's an example structure:

messages/en.json
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"common": {
"welcome": "Welcome",
"hello": "Hello, {name}!",
"save": "Save",
"cancel": "Cancel"
},
"homePage": {
"title": "Welcome to our App",
"description": "Get started with our amazing features"
},
"navigation": {
"home": "Home",
"about": "About",
"contact": "Contact"
}
}

getTranslations

Server-side function to get translations in Server Components or API routes. Use this in async Server Components.

app/page.tsx
1
2
3
4
5
6
7
8
9
10
11
12
import { getTranslations } from 'next-intl/server'
 
export default async function Page() {
const t = await getTranslations('common')
return (
<div>
<h1>{t('welcome')}</h1>
<p>{t('hello', { name: 'John' })}</p>
</div>
)
}

useTranslations

React hook to translate text in client components. Returns a function to get translated strings.

components/my-component.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
'use client'
 
import { useTranslations } from 'next-intl'
 
export function MyComponent() {
const t = useTranslations('common')
return (
<div>
<h1>{t('welcome')}</h1>
<p>{t('hello', { name: 'John' })}</p>
<button>{t('save')}</button>
</div>
)
}

Changing Locale

Change the language/locale using next-intl's navigation helpers. Import useRouter and usePathname from your i18n/routing file.

components/language-switcher.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
'use client'
 
import { useRouter, usePathname } from '@/i18n/routing'
 
export function LanguageSwitcher() {
const router = useRouter()
const pathname = usePathname()
const switchLocale = (locale: string) => {
router.replace(pathname, { locale })
}
return (
<select onChange={(e) => switchLocale(e.target.value)}>
<option value="en">English</option>
<option value="es">Español</option>
<option value="fr">Français</option>
</select>
)
}

Router-Based Translations

Set up router-based translations using Next.js middleware. This enables locale prefixes in your URLs (e.g., /en/about, /es/about). How it works: When a user visits /about, the middleware detects their preferred language and redirects to /en/about (or /es/about, etc.). Your app structure uses [locale] dynamic segments (e.g., app/[locale]/about/page.tsx) to handle different languages. The middleware automatically handles locale detection, redirects, and rewrites. Create a middleware.ts file in your project root (or src folder) to enable this feature.

middleware.ts
1
2
3
4
5
6
7
8
9
10
11
import createMiddleware from 'next-intl/middleware'
import { routing } from './i18n/routing'
 
export default createMiddleware(routing)
 
export const config = {
// Match all pathnames except for
// - … if they start with `/api`, `/trpc`, `/_next` or `/_vercel`
// - … the ones containing a dot (e.g. `favicon.ico`)
matcher: '/((?!api|trpc|_next|_vercel|.*\\..*).*)'
}

References

For more information about Internationalization, check out these resources:

next-intl Documentation
Complete documentation for next-intl, including setup, translations, routing, middleware, and advanced features.
next-intl Middleware Guide
Learn how to set up router-based translations with locale prefixes using Next.js middleware.
Internationalization | Codelesskit