☝️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ệu
có 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
i18n
từserverSideTranslations()
vào.Bạn không sử dụng
namespacesRequired
đúng.Bạn dùng
I18nextProvider
thủ 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.tsx
next-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?