- Published on
- ยท8 min read
Next.js - Creating a Multilingual (i18n) Blog Part 1
I apologize in advance for any awkward expressions in English. ๐
English is not my native language, and I have relied on ChatGPT's assistance to proceed with the translation.
Overview
For this blog, I'd like to have the default language as Korean
and add additional content in English
for specific posts.
Please note that this blog is based on the Tailwind CSS Blog Starter template code.
(I received it as a Pages Route-based code initially, but it seems to have been changed to App Route-based now.)
Since the content has become extensive, I'll be dividing it into Parts 1 through 4.
In Part 1, we'll implement multilingual support for the site using the next-i18next library. (Handling multilingual content for individual posts will be covered in Part 2.)
- Part 1: Installing next-i18next and Multilingual Site Setup
- Part 2: Multilingual Handling for Registered Posts
- Part 3: Handling Rss and Sitemap
- Part 4: Language, Alternate Tags, and Date Format Handling for SEO
I created this project with reference to gitHub, i18n-tailwind-nextjs-starter-blog.
If you've decided to use the Tailwind CSS Blog Starter template and are starting your project from scratch, it might be a good idea to start with the above project.
In my case, since the project was already in progress, I proceeded with it by referring to the mentioned project.
next-i18next
First, aside from translating the blog posts (md/mdx) into multiple languages, we use the next-i18next library for displaying language-specific content, such as error messages, according to the configured language.
If you don't require translation, you can skip this part and simply configure Next.js' default i18n (next.config.js) for your use.
Installation
You can find detailed installation and configuration instructions for next-i18next on their GitHub page.
First, install it by running the following command:
npm install next-i18next react-i18next i18next
Adding Translation Files
Create a
locales
folder under thepublic
directory.Within the
locales
folder, createen
andko
folders.Create a
public/locales/en/common.json
file and write it as follows:
{
"all": "All Posts"
}
- Create a
public/locales/ko/common.json
file and write it as follows:
{
"all": "์ ์ฒด ๊ธ"
}
- Please note that when adding key/value pairs during local development, you may need to restart the application to read the newly added values. Keep this in mind.
Project Configuration
- Create a
next-i18next.config.js
file in the top-level folder and add your desired language configurations.
(I've configured the default language as Korean and provided languages as Korean and English like this:)
/** @type {import('next-i18next').UserConfig} */
module.exports = {
i18n: {
defaultLocale: 'ko',
locales: ['ko', 'en']
}
}
- Open the
next.config.js
file and add the i18n configuration. (A restart is required.)
const { i18n } = require('./next-i18next.config') // Add
// ...
module.exports = withBundleAnalyzer({
i18n, // Add
reactStrictMode: true,
// ...
})
- Open the
pages/_app.js
file and addappWithTranslation
.
import { appWithTranslation } from 'next-i18next' // Add
function App({ Component, pageProps }) { // Remove export default
// ...
}
export default appWithTranslation(App) // Add appWithTranslation
It's all set up. Now it's time to check if it's working correctly.
Confirming Locale Functionality
Confirming that it's accessible at http://localhost:3000/en
. (There won't be any page changes yet since translation hasn't been applied.)
Display According to Language
Let's make changes to display the translated value for All Posts
on the Blog page.
- Modify
pages/blog.js
// ...
import { serverSideTranslations } from 'next-i18next/serverSideTranslations' // Add
import { useTranslation } from 'next-i18next' // Add
// ...
export async function getStaticProps({ locale }) { // Add { locale }
// ...
return {
props: {
...(await serverSideTranslations(locale, ['common'])), // Add
// ...
},
}
}
export default function Blog({ posts, initialDisplayPosts, pagination }) {
const { t } = useTranslation('common') // Add
return (
<>
// ...
<ListLayout
// ...
title={t('all')} // Fetch Translation for the Appropriate Language
/>
</>
)
}
- When you access
http://localhost:3000/blog
, you can see that it's displayed as์ ์ฒด ๊ธ
. - When you access
http://localhost:3000/en/blog
, you can see that it's displayed asAll Posts
.
It looks like the language-specific display is working correctly!
โ During the installation process of next-i18next, it seems that things got tangled as I repeated the installation, uninstallation, installation of other libraries, and reinstallation of next-i18next. There was no apparent reason why it wasn't working, but it couldn't read the translation files. In the end, I had to delete the 'node_modules' folder and reinstall it, and it started working correctly.
Adding Language Switching Links
Now, we will add links to easily switch between languages, as shown in the image below.
Adding Language Switching Component
- Create a
components/LanguageSwitch.js
file and write it as follows:
import { useRouter } from 'next/router'
import Link from 'next/link'
const LanguageSwitch = () => {
const { locales, locale, asPath } = useRouter()
if (!locales) {
return null
}
return (
<div className="rounded bg-gray-200 py-2 dark:bg-gray-800">
{locales.map((item) => (
<Link key={item} locale={item} href={asPath}>
<a
className={`p-2 font-medium text-gray-900 dark:text-gray-100 ${
item === locale ? 'rounded bg-gray-400 dark:bg-gray-600' : ''
}`}
>
{item}
</a>
</Link>
))}
</div>
)
}
export default LanguageSwitch
Applying the Language Switching Component
- In
components/LayoutWrapper.js
, use theLanguageSwitch
component.
import LanguageSwitch from '@/components/LanguageSwitch' // Add
const LayoutWrapper = ({ children }) => {
return (
<SectionContainer>
<div className="...">
<header className="...">
// ...
<div className="...">
// ...
<LanguageSwitch /> // Add
<ThemeSwitch />
<MobileNav />
</div>
</header>
</div>
</SectionContainer>
)
}
Now, for the text you want to display in different languages, you can pass serverSideTranslations
as a prop in the getStaticProps
of the respective page and handle it in the component using {t('key')}
.
Please refer to the modified section in pages/blog.js
for guidance.
Summary
To summarize the essential tasks from the work:
- Install and configure
next-i18next
. - Add translation files.
- Apply translation to pages (using getStaticProps, serverSideTranslations, and t('key')).
For blog posts that are read from .md(x) files, managing them as {t('key')}
isn't feasible.
You need to display registered posts differently based on the selected language, including post lists, tag lists, etc.
We'll continue with related content in Next.js - Creating a Multilingual (i18n) Blog Part 2.
Code
The updated code can be found in the commit history.