@sdjzwiki/next-locale
v1.0.1
Published
A simple and powerful i18n translation system for Next.js 14+.
Downloads
127
Readme
NextLocale
NextLocale is a multilingual (internationalization) solution built specifically for Next.js 14+ projects. It's simple, lightweight, and allows you to easily switch project languages while automatically handling the loading and caching of language files.
Why I Created NextLocale
I was using Next.js version 14, and it completely clashed with popular translation libraries like i18next
and react-intl
, causing constant errors. It got so frustrating that I was about to have a cyber meltdown. These libraries are also often overcomplicated, requiring a lot of extra configuration.
So, I decided to create a lightweight but powerful solution, specifically designed for Next.js 14+, to solve these compatibility issues and reduce unnecessary complexity.
The main goal of NextLocale is that with just a few steps of configuration, you can bring global multilingual support to your Next.js project. It comes with smooth animation transitions, caching support, and allows easy dynamic language switching. No more manually tweaking your page logic for different languages.
Installation
First, install the library in your project:
pnpm add @sdjzwiki/next-locale
Or if you're using npm or yarn:
npm install @sdjzwiki/next-locale
yarn add @sdjzwiki/next-locale
Step 1: Configure Language Files
We first need to create a file to define the languages supported by the system. This file is called languages.ts
.
Its purpose is to manage the available language options (like display names and language codes) and will be used in the language-switching logic.
1. Create src/lib/languages.ts
In your project, create a new file called src/lib/languages.ts
and add the following content:
// Define the format for supported languages
export interface Language {
code: string; // The language code, like 'en' for English
name: string; // The language name, like 'English'
translationKey: string; // The name of the translation file, like 'translation_en'
beta?: boolean; // Optional property to mark a language as beta
}
// Define the list of supported languages
export const defaultLanguages: Language[] = [
{ code: 'en', name: 'English', translationKey: 'translation_en' },
{ code: 'zh_cn', name: '简体中文', translationKey: 'translation_zh_cn', beta: true },
{ code: 'es', name: 'Español', translationKey: 'translation_es' },
];
Explanation:
- code: The shorthand for the language, like 'en' for English, 'zh_cn' for Simplified Chinese.
- name: The display name of the language, which will be shown in the user interface, like "简体中文" or "Español."
- translationKey: Used to find the corresponding translation file, which you'll use later.
- beta: An optional field to mark a language as a beta version. For example, you might be developing the translation for a new language.
Step 2: Create Middleware
This middleware will detect the user's browser language or existing language cookie and automatically switch languages based on this information.
1. Create middleware.ts
In the root directory of your project, create a new file called middleware.ts
with the following content:
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
// Define the list of supported languages
const supportedLanguages = new Set([
'en', 'zh_cn', 'es'
]);
export function middleware(req: NextRequest) {
const url = req.nextUrl.clone();
const acceptLanguage = req.headers.get('Accept-Language');
let lang = 'en'; // Default language
const cookieLang = req.cookies.get('NEXT_LOCALE');
if (cookieLang) {
lang = cookieLang.value.toLowerCase();
} else if (acceptLanguage) {
const languages = acceptLanguage.split(',').map(l => l.split(';')[0].trim().toLowerCase());
for (const l of languages) {
const formattedLang = l.replace('-', '_');
if (supportedLanguages.has(formattedLang)) {
lang = formattedLang;
break;
}
}
}
if (!cookieLang && lang) {
const response = NextResponse.redirect(url);
response.cookies.set('NEXT_LOCALE', lang, { path: '/' });
return response;
}
return NextResponse.next();
}
export const config = {
matcher: ['/((?!api|_next|favicon.ico).*)'],
};
Explanation:
- This middleware checks the user's language on every request and sets a
NEXT_LOCALE
cookie that stores their language preference. - Accept-Language is a request header sent by the browser that contains the user's preferred language. We extract the preferred language from this header.
- If the user has previously selected a language, the system will remember and use their chosen language.
- If no language has been selected before, we automatically choose one based on the browser's language settings and set a cookie.
- If the user manually switches languages on the frontend, the cookie will be updated to reflect the new language.
Step 3: Wrap the LanguageProvider
Next, you need to wrap the root of your app with a LanguageProvider
to provide multilingual support throughout your app.
1. Modify _app.tsx
Open your _app.tsx
file and wrap the LanguageProvider
:
import { LanguageProvider } from '@sdjzwiki/next-locale';
function MyApp({ Component, pageProps }) {
return (
<LanguageProvider>
<Component {...pageProps} />
</LanguageProvider>
);
}
export default MyApp;
If you're using layout.tsx
, it works similarly:
import { LanguageProvider } from '@sdjzwiki/next-locale';
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<LanguageProvider>
{children}
</LanguageProvider>
);
}
Step 4: Use the useTranslation
Hook
NextLocale
provides a useTranslation
Hook to get the current language and perform translation operations.
Here are two demos to help you understand how to use it:
1. Translating Text
Suppose you have a component that needs to display different text based on the current language:
import { useTranslation } from '@sdjzwiki/next-locale';
const Component = () => {
const { t } = useTranslation();
return (
<div>
<p>{t('welcome_message')}</p>
</div>
);
};
export default Component;
2. Getting and Switching Languages
import { useTranslation } from '@sdjzwiki/next-locale';
import { defaultLanguages } from '@/lib/languages';
const LanguageSwitcher = () => {
const { language, setLanguage } = useTranslation(); // Get translation function and language switcher
return (
<div>
{/* Language switch buttons */}
{defaultLanguages.map((lang) => (
<button key={lang.code} onClick={() => setLanguage(lang.code)}>
{lang.name}
</button>
))}
</div>
);
};
export default LanguageSwitcher;
Explanation:
- The
useTranslation
Hook returns an object that contains thet
function, thelanguage
property, and thesetLanguage
function. - The
t
function is used to translate text; it takes a key as an argument and returns the corresponding translation. - The
language
property represents the current language. - The
setLanguage
function is used to switch languages, accepting a language code as an argument and updating the current language. It automatically updates theNEXT_LOCALE
cookie, ensuring the correct language is used on the next visit.
Step 5: Add Translation Files
In the last step, you'll need to create a translation file for each language under the public
folder. For example:
1. Create Translation Files
In your project, create the following directory and files:
public/
└── locales/
├── en/
│ └── common.json
├── zh_cn/
│ └── common.json
└── es/
└── common.json
Each common.json
file contains the text you want to translate. For example, the public/locales/en/common.json
file would look like this:
{
"welcome_message": "Welcome to our website!"
}
And public/locales/zh_cn/common.json
could look like this:
{
"welcome_message": "欢迎来到我们的网站!"
}
The
common.json
file is used to store translation content for each language. Thet('welcome_message')
function will look up this key in the file. Each language has its own folder underpublic/locales
.
License
This project is licensed under the MIT License, meaning you can use and modify it freely, but don't forget to give credit.
If you think it's cool, give it a star ✨!