When i am integrating localization in nextjs getting many issues. so can create post for it. I have implement in client side.
First you need to create file for language which you want to include.
like
public/locales/
en.json , ar.json, de.json
en.json
{ "HEADING":"My First Page" }
de.json
{ "HEADING":"Meine erste Seite" }
like this you can add language keys.
package.json
{ "name": "translation-project", "version": "0.1.0", "private": true, "scripts": { "dev": "next dev --turbopack", "build": "next build", "start": "next start", "lint": "next lint" }, "dependencies": { "aos": "^2.3.4", "bootstrap": "^5.3.3", "i18next": "^24.2.2", "i18next-browser-languagedetector": "^8.0.4", "i18next-http-backend": "^3.0.2", "next": "15.1.6", "react": "^19.0.0", "react-bootstrap": "^2.10.8", "react-dom": "^19.0.0", "react-i18next": "^15.4.1" }, "devDependencies": { "@eslint/eslintrc": "^3", "@types/node": "22.12.0", "eslint": "^9", "eslint-config-next": "15.1.6", "sass": "^1.85.1", "sass-loader": "^16.0.5", "typescript": "5.7.3" } }
Base.tsx
import React, { useEffect, useState } from 'react' import Footer from '../footer/page'; import { I18nextProvider, useTranslation } from "react-i18next"; import i18n from "../../../utils/i18n"; const Base = ({children}) => { const { i18n: i18nInstance } = useTranslation(); const [loading, setLoading] = useState(true); useEffect(() => { if (i18nInstance.isInitialized) { setLoading(false); } }, [i18nInstance.isInitialized]); if (loading) { return ( <div className="global-loading"> </div> ); } return ( <I18nextProvider i18n={i18n}> {children} <Footer /> </I18nextProvider> ) } export default Base;
i18n.ts
"use client"; import i18n from "i18next"; import { initReactI18next } from "react-i18next"; import HttpApi from "i18next-http-backend"; import LanguageDetector from "i18next-browser-languagedetector"; if (typeof window !== "undefined") { i18n .use(HttpApi) // Load translations dynamically .use(LanguageDetector) .use(initReactI18next) .init({ supportedLngs: ["en", "ar"], fallbackLng: "en", debug: false, // Set false in production detection: { order: ["localStorage", "cookie", "navigator"], caches: ["localStorage"] }, backend: { loadPath: "/locales/{{lng}}.json" }, interpolation: { escapeValue: false } }); } export default i18n;
In this file i have show that how you can change language & use it.
Footer.tsx
"use client"; import React, { useEffect } from 'react'; import Link from 'next/link'; import './style.scss'; import { PolicyMenu, SocialMenu } from "../../../constant/const"; import { useTranslation } from 'react-i18next'; export default function Footer() { const { t, i18n } = useTranslation(); const change = (lang) => { if (i18n?.language == lang) return; i18n?.changeLanguage(lang); } return ( <div className='footer-wrapper'> <div className='container'> <div className='row align-items-center justify-content-center gap-8'> <div className='col-md-3'> <p className='mb-0 text-white'>{t("SITE_BY")}</p> </div> <div className='col-md-6'> <ul className='social-menu d-flex gap-8 justify-content-center flex-wrap'> {SocialMenu.map((item, index) => ( <li key={index}><Link target="_blank" href={item.url}>{item.icon}</Link></li> ))} </ul> </div> <div className='col-md-3'> <ul className='footer-links d-flex flex-wrap'> {PolicyMenu.map((value, index) => ( <li key={index}><Link className='text-white' href={value.url}>{t(value.name)}</Link></li> )) } <div className='d-flex gap-2 text-white lang-active'> <span className={ 'cursor-pointer ' +(i18n?.language=='en' && "active")} onClick={() => change('en')}>EN</span> <span className={ 'cursor-pointer ' +(i18n?.language=='ar' && "active")} onClick={() => change('ar')}>AR</span> </div> </ul> </div> </div> </div> </div> ) }
Top comments (0)