This small Next.js project shows how I implemented internationalization (i18n) in a Next.js 14 application using sub-path
routing (app/[lang]/page.tsx
).
It is based on the official Next.js Documentation and uses the Feature-Sliced Design architecture for better project organization.
You need to install the following packages:
npm install negotiator @formatjs/intl-localematcher
The project is organized according to the Feature-Sliced Design (FSD) principles.
Here is an overview of the structure and the parts responsible for i18n implementation:
src
├── middleware.ts
├── app
│ ├── (routing)
│ │ └── [lang]
│ │ └── /**/*.{ts,tsx}
│ └── providers
│ └── DictionaryProvider.tsx
├── ...
└── shared
├── config
│ └── i18n
│ ├── constants
│ │ └── locales.ts
│ ├── dictionaries
│ │ ├── en.json
│ │ └── ...
│ └── helpers
│ └── get-locale.ts
│ └── get-dictionary.ts
│ └── locale-redirection.ts
├── lib
| ├── contexts
| │ └── DictionaryContext
| └── hooks
| └── useDictionary
└── ui
└── LanguageSwitcher
-
middleware.ts
: Handles locale detection and redirection based on the user's preferred language. -
DictionaryProvider.tsx
: Provides the dictionary context to the application.return ( <DictionaryContext.Provider value={{ dictionary, lang }}> {children} </DictionaryContext.Provider> );
-
shared/config/i18n/constants/locales.ts
: Defines the available locales and the default locale.const locales = [ { code: 'en', name: 'English' }, { code: 'de', name: 'Deutsch' }, { code: 'ru', name: 'Русский' }, { code: 'fr', name: 'Français' }, { code: 'es', name: 'Español' }, { code: 'it', name: 'Italiano' }, ]; const defaultLocale = locales[0].code;
-
shared/dictionaries/*.json
: JSON files containing the translations for each supported language.Example
en.json
:{ "home": { "hello": "Hello, friend" }, "about": { "about_text": "This is the about page." } ... }
-
DictionaryContext.tsx
: Creates the context for the dictionary data. -
useDictionary.ts
: Custom hook for accessing the dictionary context. -
LanguageSwitcher.tsx
: Example component for switching languages.
As simple as that:
'use client';
import { useDictionary } from '@/shared/lib/hooks';
const HomePage = () => {
const { dictionary } = useDictionary();
return (
<div>{dictionary.home.hello}</div> // you will get suggestions about your dictionary structure
);
};
This project provides a comprehensive setup for implementing internationalization in a Next.js 14 using Context API
, middleware
, and a bit of FSD-architecture
.
With this structure, you can easily extend
it for more languages and - of course - more complex dictionaries structures.
Feel free to adjust the styles, components, and structure
as needed for your specific project.
All functions and components are documented
within the code for easier understanding and maintenance.