June 11, 2024
3 min read
#nextjs
#frontend
#beginners
#webdev
3 min read
Before I dive into implementing the new feature (Next-Intl) I added to my portfolio, you might want to check it out first at my portfolio.
Internationalization (often abbreviated as i18n) is an important aspect of web development, especially for websites that cater to a global audience. Here are some key features and benefits of using internationalization on your website:
Because I'm using Next JS as my tech to build my portfolio, I use the Next-Intl so it will be compatible with my website. To implement Next-Intl as I did in my portfolio you can follow this step(I will demonstrate this with my web code):
npm i next-intl
├── locales (1)
│ ├── en.json
│ └── ... // your others locales file (e.g. id.json)
├── next.config.js (2)
├── i18n.ts (3)
├── middleware.ts (4)
└── app
└── [locale]
├── layout.tsx (5)
└── page.tsx (6)
You can follow my folder structure example
Add JSON files in your project based on locales(e.g. en.json, id.json)
en.json
"Project": {
"label": "My Projects"
},
Add this code to your next.config.js
next.config.js
// @ts-check
const createNextIntlPlugin = require('next-intl/plugin')
const withNextIntl = createNextIntlPlugin()
/** @type {import('next').NextConfig} */
const config = {}
module.exports = withNextIntl(config)
Add this code to your i18n.ts
i18n.ts
import { notFound } from 'next/navigation'
import { getRequestConfig } from 'next-intl/server'
const locales = ['en', ...] // Add your other locales here
export default getRequestConfig(async ({ locale }) => {
// Validate that the incoming `locale` parameter is valid
if (!locales.includes(locale as any)) notFound()
return {
messages: (await import(`./locales/${locale}.json`)).default,
}
})
Add this code to your middleware.ts
middleware.ts
import createMiddleware from 'next-intl/middleware'
export default createMiddleware({
// A list of all locales that are supported
locales: ['en', ...], // Add your other locales
// Used when no locale matches
defaultLocale: 'en',
})
export const config = {
// Match only internationalized pathnames
matcher: ['/', '/(id|en)/:path*'],
}
Add this code to your app/[locale]/layout.tsx
app/[locale]/layout.tsx
import { NextIntlClientProvider } from 'next-intl'
import { getMessages } from 'next-intl/server'
type Props = {
children: ReactNode
params: { locale: string }
}
export default async function RootLayout({
children,
params: { locale },
}: Props) {
const messages = await getMessages()
return (
<html lang={locale}>
<body>
<NextIntlClientProvider messages={messages}
{children}
</NextIntlClientProvider>
</body>
</html>
)
}
Call your translation using useTranslation
in your page components or anywhere else!
e.g. Projects.tsx
import { useTranslations } from 'next-intl'
export default function Projects() {
const t = useTranslations('Project')
return (<p>{t('label')}</p>)
}
You can make a language toggler button to switch language as you wish, but before that you guys need to make a routing using Next-Intl so follow this step:
Create config.ts
on your root folder and add this code
config.ts
export const locales = ['en', 'id'] as const
// Use the default: `always`
export const localePrefix = undefined
Create navigation.ts
on your root folder and add this code
navigation.ts
import { createSharedPathnamesNavigation } from 'next-intl/navigation'
import { locales, localePrefix } from './config'
export const { Link, redirect, usePathname, useRouter } =
createSharedPathnamesNavigation({
locales,
localePrefix,
})
If you done two of the previous step you can make the language button toggler
LangToggler.tsx
'use client'
import { useTransition } from 'react'
import { useRouter, usePathname } from '../navigation'
import { useLocale } from 'next-intl'
import inaIcon from '@/public/ina-icon.svg'
import enIcon from '@/public/en-icon.svg'
import Image from 'next/image'
export default function LangToggler() {
const router = useRouter()
const [isPending, startTransition] = useTransition()
const pathname = usePathname()
const locale = useLocale()
const nextLocale = locale === 'en' ? 'id' : 'en'
function onButtonClick() {
startTransition(() => {
router.replace(pathname, { locale: nextLocale })
})
}
return (
<button
disabled={isPending}
onClick={onButtonClick}
>
<Image
src={locale === 'en' ? inaIcon : enIcon}
alt='language flag icon'
className='w-4'
/>
</button>
)
}
Voila, you have done adding Next-Intl to your application. This is an example of my portfolio website
Happy coding guys, Thankyou!
Comments (2)
Jan Amann
The animated language toggle is 💯!
Bramsurya Johannes Paulus
Thankyou very much, appreciate it!!😁👐