DEV Community

Vu Hoang Lam
Vu Hoang Lam

Posted on

Integrating Multi-Language in Next.js with Custom Hooks and Redux

Image description
Today, I'll walk you through implementing multi-language support in Next.js using only custom hooks and Redux. The beauty of this method is its compatibility with any version of Next.js or even React.js. Let's dive in!

Firstly, let's set up a Redux reducer using Redux Toolkit called LanguageStore:

import { createSlice } from '@reduxjs/toolkit'

export const LanguageStore = createSlice({
    name: 'LanguageStore',
    initialState: {
        language: 'vi',
    },
    reducers: {
        setLanguage: (state, actions) => {
            state.language = actions.payload
        },
    }
})

export const { setLanguage } = LanguageStore.actions

export default LanguageStore.reducer;
Enter fullscreen mode Exit fullscreen mode

Next, create language data files. I've prepared two language files: vi.json for Vietnamese and en.json for English.

Here's an example of vi.json:

{
    "about": "Giới thiệu",
    "menu": "Thực đơn",
    "news": "Tin tức",
    "gallery": "Thư viện",
    "order": "Đặt bàn ngay",
}
Enter fullscreen mode Exit fullscreen mode

And en.json:

{
    "about": "About us",
    "menu": "Menu",
    "news": "News",
    "gallery": "Library",
    "order": "Book Now",
}
Enter fullscreen mode Exit fullscreen mode

Now, let's create useLanguage.js, a custom hook:

import { useSelector } from 'react-redux';
import vi from "../helper/translates/vi.json"
import en from "../helper/translates/en.json"
const useLanguage = () => {
    const LanguageStore = useSelector((state) => state?.LanguageStore)
    const listLangue = {
        en: en,
        vi: vi,
    }

    const t = (text_params) => {
        let text = ''
        const langValue = LanguageStore?.language
        const getTextList = listLangue?.[langValue]
        if (listLangue?.[langValue]) {
            if (getTextList?.[text_params]) {
                text = getTextList?.[text_params]
            }
        }
        return text
    }
    return {
        t
    };
};

export default useLanguage;
Enter fullscreen mode Exit fullscreen mode

Great! Now, let's put it to use:

// Navbar.jsx
import useLanguage from "@/app/hooks/useLanguage";
import { setLanguage } from "@/app/store/reducer/LanguageStore";
import { useDispatch, useSelector } from "react-redux";
export const linkList = [
    {
      id: 1,
      url: "/ve-chung-toi",
      languageFlag: "about",
      title: "Giới thiệu",
    },
    {
      id: 2,
      url: "/menu",
      languageFlag: "menu",
      title: "Thực đơn",
    },
    {
      id: 3,
      url: "/tin-tuc",
      languageFlag: "news",
      title: "Tin tức",
    },
    {
      id: 4,
      url: "/thu-vien",
      languageFlag: "gallery",
      title: "Thư viện",
    },
  ];
function Navbar() {
  const { t } = useLanguage();
  const { language } = useSelector((state) => state.LanguageStore);
 const handleLanguageChange = (value) => {
    dispatch(setLanguage(value.value));
  };
  const languageOptions = [
    {
      value: "vi",
      label: (
        <Stack direction={"row"} alignItems="center" gap={"4px"}>
          <Image alt="" src={"/vn-language.svg"} width={24} height={24} />
          <Typography>VN</Typography>
        </Stack>
      ),
    },
    {
      value: "en",
      label: (
        <Stack direction={"row"} alignItems="center" gap={"4px"}>
          <Image alt="" src={"/en-language.svg"} width={24} height={24} />
          <Typography>EN</Typography>
        </Stack>
      ),
    },
  ];
return (
   <>
            {linkList.map((item) => (
              <Link 
                   href={item.url} 
                   key={item.id}>
                <Typography
                  textTransform={"uppercase"}
                  color={"#88231F"}
                  fontWeight={router.pathname === item.url ? 700 : 400}
                  fontSize={"14px"}
                  lineHeight={"24px"}
                >
                  {/* {item.title} */}
                  {t(item.languageFlag)}
                </Typography>
              </Link>
            ))}
            <CustomSelect
              options={languageOptions}
              defaultValue= 
                  {languageOptions.find((item) => 
                    item.value === language)}
              handleChange={handleLanguageChange}
            />
   </>
  )
}
Enter fullscreen mode Exit fullscreen mode

And that's it! You're all set to use multi-language support in your Next.js app. I hope you find this tutorial helpful. Happy coding!

Top comments (0)