I implement Next-Intl into my Portfolio (Next JS & App Router)

I implement Next-Intl into my Portfolio (Next JS & App Router)

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):

1. Add Next-Intl into your application

npm i next-intl

2. 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

3. Setup the files

Add JSON files in your project based on locales(e.g. en.json, id.json)

locales/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>
<ThemeContextProvider>
<ActiveSectionContextProvider>
<NextIntlClientProvider messages={messages}>
{children}
</NextIntlClientProvider>
</ActiveSectionContextProvider>
</ThemeContextProvider>
</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:

1. Create config.ts on your root folder and add this code

config.ts

import { Pathnames } from ‘next-intl/navigation’

export const locales = [‘en’, ‘id’] as const

export const pathnames = {
‘/’: ‘/’,
} satisfies Pathnames<typeof locales>

// Use the default: `always`
export const localePrefix = undefined

export type AppPathnames = keyof typeof pathnames

2. Create navigation.ts on your root folder and add this code

navigation.ts

import { createLocalizedPathnamesNavigation } from ‘next-intl/navigation’
import { locales, pathnames, localePrefix } from ‘./config’

export const { Link, redirect, usePathname, useRouter } =
createLocalizedPathnamesNavigation({
locales,
pathnames,
localePrefix,
})

3. 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!