MUI Data Grid列头国际化切换失效问题求助
MUI Data Grid 列头本地化语言切换不更新的解决办法
问题说明
用MUI Data Grid构建表格做i18n本地化时,列头配置是静态对象,初始化时调用i18next.t()生成翻译文本,但切换语言后,列头不会自动更新——因为静态数组只在模块加载时执行一次t(),语言变化后不会重新计算。
你的列配置代码
import { Box, Tooltip } from "@mui/material"; import { deliverTruckBulk, pickupTruckBulk, } from "assets/img/statuses/statusImages"; import { dateComparator, localizeDate, localizeTime } from "helpers/helpers"; import i18next from "i18next"; import StatusIcon from "../../../../StatusIcon/StatusIcon"; import { OrderTableCaption, OrderTableText, } from "../../../../Typography/OrderList"; export const OrderTableColumns = [ { field: "shippingDate", headerName: "Requested Date", sortComparator: dateComparator, renderCell: (params) => ( <Box> <OrderTableText sx={{ fontWeight: 500 }}> {localizeDate(params.value.date)} </OrderTableText> <OrderTableCaption> {`${localizeTime(params.value.startTime)} - ${localizeTime( params.value.endTime )}`} </OrderTableCaption> </Box> ), flex: 0, }, { field: "po-order", headerName: i18next.t("order.orderNumber"), renderCell: (params) => ( <Box> <OrderTableText>{params.value.customerReference}</OrderTableText> <OrderTableCaption>{params.value.orderNumber}</OrderTableCaption> </Box> ), flex: 1, sortable: false, }, { field: "destination", headerName: "Destination", renderCell: (params) => ( <Box sx={{ display: "flex", flexDirection: "column" }}> <OrderTableText>{params.value.siteName}</OrderTableText> <OrderTableCaption>{params.value.street}</OrderTableCaption> </Box> ), flex: 1, sortable: false, }, { field: "material", headerName: "Material", renderCell: (params) => <OrderTableText>{params.value}</OrderTableText>, flex: 1, sortable: false, }, { field: "ordered-delivered", headerName: "Ordered/Delivered", renderCell: ({ value }) => { const isShippingTypeCollect = value.shippingType === "collect"; const shippingType = isShippingTypeCollect ? pickupTruckBulk : deliverTruckBulk; const tooltipTitle = `${ isShippingTypeCollect ? "Pick-up" : "Delivery" } by bulk carrier`; return ( <Box sx={{ display: "flex", columnGap: "5px" }}> <OrderTableText> {value.quantity} {i18next.t("capacityTons1")} </OrderTableText> <Tooltip title={tooltipTitle}> <img src={shippingType} alt={shippingType} width="24px" /> </Tooltip> </Box> ); }, flex: 0, sortable: false, }, { field: "status", headerName: i18next.t("order.orderStatus"), renderCell: (params) => <StatusIcon status={params.value} />, flex: 0, maxWidth: 60, sortable: false, }, ];
解决方案
方案1:把列配置改成动态生成函数
放弃静态数组,改成返回列配置的函数,每次调用都会重新执行t()获取最新翻译。然后在表格组件中监听语言变化,触发重新生成列配置。
步骤1:修改列配置文件
import { Box, Tooltip } from "@mui/material"; import { deliverTruckBulk, pickupTruckBulk } from "assets/img/statuses/statusImages"; import { dateComparator, localizeDate, localizeTime } from "helpers/helpers"; import i18next from "i18next"; import StatusIcon from "../../../../StatusIcon/StatusIcon"; import { OrderTableCaption, OrderTableText } from "../../../../Typography/OrderList"; // 改成函数,每次调用都返回新的列配置数组 export const getOrderTableColumns = () => [ { field: "shippingDate", // 把硬编码文本换成翻译键 headerName: i18next.t("order.requestedDate"), sortComparator: dateComparator, renderCell: (params) => ( <Box> <OrderTableText sx={{ fontWeight: 500 }}> {localizeDate(params.value.date)} </OrderTableText> <OrderTableCaption> `${localizeTime(params.value.startTime)} - ${localizeTime(params.value.endTime)}` </OrderTableCaption> </Box> ), flex: 0, }, { field: "po-order", headerName: i18next.t("order.orderNumber"), renderCell: (params) => ( <Box> <OrderTableText>{params.value.customerReference}</OrderTableText> <OrderTableCaption>{params.value.orderNumber}</OrderTableCaption> </Box> ), flex: 1, sortable: false, }, { field: "destination", headerName: i18next.t("order.destination"), renderCell: (params) => ( <Box sx={{ display: "flex", flexDirection: "column" }}> <OrderTableText>{params.value.siteName}</OrderTableText> <OrderTableCaption>{params.value.street}</OrderTableCaption> </Box> ), flex: 1, sortable: false, }, { field: "material", headerName: i18next.t("order.material"), renderCell: (params) => <OrderTableText>{params.value}</OrderTableText>, flex: 1, sortable: false, }, { field: "ordered-delivered", headerName: i18next.t("order.orderedDelivered"), renderCell: ({ value }) => { const isShippingTypeCollect = value.shippingType === "collect"; const shippingType = isShippingTypeCollect ? pickupTruckBulk : deliverTruckBulk; // 替换硬编码tooltip文本 const tooltipTitle = `${i18next.t(isShippingTypeCollect ? "order.pickup" : "order.delivery")} ${i18next.t("order.byBulkCarrier")}`; return ( <Box sx={{ display: "flex", columnGap: "5px" }}> <OrderTableText> {value.quantity} {i18next.t("capacityTons1")} </OrderTableText> <Tooltip title={tooltipTitle}> <img src={shippingType} alt={shippingType} width="24px" /> </Tooltip> </Box> ); }, flex: 0, sortable: false, }, { field: "status", headerName: i18next.t("order.orderStatus"), renderCell: (params) => <StatusIcon status={params.value} />, flex: 0, maxWidth: 60, sortable: false, }, ];
步骤2:在表格组件中监听语言变化
import { useEffect, useState } from "react"; import { DataGrid } from "@mui/x-data-grid"; import { getOrderTableColumns } from "./path-to-your-columns-file"; import i18next from "i18next"; const OrderTable = () => { // 初始化列配置 const [columns, setColumns] = useState(getOrderTableColumns()); useEffect(() => { // 监听i18n语言变化事件 const handleLangChange = () => { // 重新生成列配置,触发更新 setColumns(getOrderTableColumns()); }; // 绑定事件 i18next.on("languageChanged", handleLangChange); // 组件卸载时解绑 return () => i18next.off("languageChanged", handleLangChange); }, []); return <DataGrid columns={columns} rows={yourRowsData} {...otherProps} />; }; export default OrderTable;
方案2:用headerRenderer渲染列头(推荐react-i18next用户)
MUI Data Grid支持用headerRenderer属性传入React组件来渲染列头,这样可以直接使用useTranslation钩子,自动响应语言变化。
步骤1:修改列配置(注意要在React组件内部定义,或者封装成组件)
import { useTranslation } from "react-i18next"; import { Box, Tooltip } from "@mui/material"; // 其他导入... // 如果要在组件外部复用,封装成独立的列头组件 const OrderNumberHeader = () => { const { t } = useTranslation(); return <span>{t("order.orderNumber")}</span>; }; // 在React组件内部定义列配置 const OrderTable = () => { const { t } = useTranslation(); const columns = [ { field: "po-order", // 用headerRenderer代替headerName headerRenderer: () => <OrderNumberHeader />, renderCell: (params) => ( <Box> <OrderTableText>{params.value.customerReference}</OrderTableText> <OrderTableCaption>{params.value.orderNumber}</OrderTableCaption> </Box> ), flex: 1, sortable: false, }, // 其他列同理,比如: { field: "status", headerRenderer: () => <span>{t("order.orderStatus")}</span>, renderCell: (params) => <StatusIcon status={params.value} />, flex: 0, maxWidth: 60, sortable: false, }, // 剩余列配置... ]; return <DataGrid columns={columns} rows={yourRowsData} />; };
这种方式下,只要useTranslation钩子感知到语言变化,列头组件就会自动重新渲染,更新翻译文本。
关键注意点
- 所有硬编码的文本(比如原来的"Requested Date")都要替换成对应的翻译键,确保全量本地化。
- 如果使用
react-i18next,优先用useTranslation钩子,它会自动订阅语言变化,比直接调用i18next.t()更省心。 renderCell里的动态文本(比如tooltip)也要换成翻译键,避免遗漏本地化。
内容的提问来源于stack exchange,提问作者magrega
相关产品推荐
相关产品推荐

