☝️Toàn bộ giải thích Triển khai i18next ở pages
C:\Users\Administrator\Desktop\study\next-i18next
Hydration failed because the server rendered HTML didn't match the client...
+ about_title
- Giới thiệucó nghĩa là SSR (server-side rendering) đã render một nội dung, nhưng client-side sau khi tải lại render nội dung khác — gây ra mismatch. Trong trường hợp của bạn, có vẻ như server render ra about_title (chưa dịch) nhưng client lại hiển thị "Giới thiệu" (bản dịch đúng).
🧠 Nguyên nhân phổ biến trong dự án next-i18next + [lang] dynamic
next-i18next + [lang] dynamicBạn dùng
useTranslation()nhưng chưa inject bản dịch đúng ởgetStaticProps.Bạn quên truyền
i18ntừserverSideTranslations()vào.Bạn không sử dụng
namespacesRequiredđúng.Bạn dùng
I18nextProviderthủ công (không cần nữa nếu đã cấu hìnhnext-i18next).Bạn dùng
i18n.changeLanguage()không đúng lúc — gây rehydrate sai.
✅ Cách sửa chính xác
1. Đảm bảo bạn có getStaticProps đúng:
getStaticProps đúng:import { GetStaticProps } from 'next';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import i18nextConfig from '../../../next-i18next.config.js';
export const getStaticProps: GetStaticProps = async ({ params }) => {
const locale = params?.lang as string;
return {
props: {
...(await serverSideTranslations(locale, ['translation'], i18nextConfig)),
},
};
};✅ Không cần truyền
i18n.changeLanguage()thủ công trong component nữa nếu đã dùng[lang]route.
2. Gọi useTranslation() đúng namespace và lang đến từ URL
useTranslation() đúng namespace và lang đến từ URLimport { useTranslation } from 'next-i18next';
const { t } = useTranslation('translation'); // namespace 'translation'3. Đảm bảo bạn không dùng I18nextProvider thủ công trong _app.tsx
I18nextProvider thủ công trong _app.tsxnext-i18next tự động inject provider qua appWithTranslation(App) — bạn nên dùng như sau:
// pages/_app.tsx
import { appWithTranslation } from 'next-i18next';
import '../styles/globals.css';
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />;
}
export default appWithTranslation(MyApp);4. Đảm bảo translation.json có key:
translation.json có key:{
"about_title": "Giới thiệu",
"about_content": "Nội dung giới thiệu"
}Đặt tại:
public/locales/vi/translation.json
public/locales/en/translation.json✅ Mẫu about.tsx đúng chuẩn
about.tsx đúng chuẩn// src/pages/[lang]/about.tsx
import { GetStaticPaths, GetStaticProps } from 'next';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import i18nextConfig from '../../../next-i18next.config';
import { useTranslation } from 'next-i18next';
export default function About() {
const { t } = useTranslation('translation');
return (
<div className="p-4">
<h1 className="text-xl font-bold">{t('about_title')}</h1>
<p>{t('about_content')}</p>
</div>
);
}
export const getStaticPaths: GetStaticPaths = async () => {
const paths = i18nextConfig.i18n.locales.map((lang) => ({
params: { lang },
}));
return { paths, fallback: false };
};
export const getStaticProps: GetStaticProps = async ({ params }) => {
const locale = params?.lang as string;
return {
props: {
...(await serverSideTranslations(locale, ['translation'], i18nextConfig)),
},
};
};Nếu bạn muốn, mình có thể kiểm tra tận gốc trong dự án bạn vừa zip hoặc gửi bản mẫu 100% đúng mà bạn chỉ cần copy vào là chạy được luôn.
Bạn muốn mình gửi bản mẫu không?
Last updated
Was this helpful?