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:
- Language Localization: Internationalization allows your website to be translated into different languages. This makes your content accessible to users around the world, regardless of their native language.
- Improved User Experience: By providing content in a user’s native language and adhering to their cultural norms, you enhance their experience and engagement with your website.
- SEO Benefits: Search engines favor websites that cater to a global audience. By having your website content available in multiple languages, you can improve your search engine rankings.
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):
- Add Next-Intl into your application
npm i next-intl
- Create this folder structure
├── 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
-
Setup the files
- 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!
Top comments (5)
The animated language toggle is 💯!
Thankyou very much, appreciate it!!😁👐