Open layerok opened 1 month ago
well I found something
instead of doing this
const { t } = useTranslation();
const columns = useMemo(() => [
{
field: "first_name",
headerName: t("first_name")
},
{
field: "last_name",
headerName: t("last_name")
},
], [t]);
I can do this
const columns = useMemo(() => [
{
field: "first_name",
renderHeader: () => <Trans i18nKey="first_name"/>
},
{
field: "last_name",
renderHeader: () => <Trans i18nKey="last_name"/>
},
], []);
Title of a custom filter operator also doesn't update when switching languages.
But if you pass the Trans
component instead of a simple string, it will update
const { t } = useTranslation();
const columns = useMemo(() => [
{
field: "first_name",
renderHeader: () => <Trans i18nKey="first_name"/>,
filterable: true,
filterOperators: [
{
value: "contains",
getApplyFilterFn: () => null,
// @ts-ignore
label: <Trans i18nKey="header-operators.mode.contains"/>, // <-- it will update when switching languages
// @ts-ignore
headerLabel: <Trans i18nKey="header-operators.mode.contains"/>, // <-- it will update when switching languages
},
{
value: "exact",
getApplyFilterFn: () => null,
label: t("header-operators.mode.exact"), // <-- it won't update when switching languages
headerLabel: t("header-operators.mode.exact"), // <-- it won't update when switching languages
},
// ... other filter operators
]
},
// ... other column definitions
], []);
I had to use ts-ignore
because typescript is unhappy about Trans
being passed to a property that accepts only a value of type string
Hey @layerok ... Sry for the late reply. I had some time off. It seems you solved your issue already. Is there anything else we can help you with?
@michelengelen I am not satisfied with my solution
Firstly, I don't like using ts-ignore
Secondly, I don't like using renderHeader
because I can't just return translation in the renderHeader
callback
because then the DataGrid
will render the unstyled header. I need to wrap it in some component first. And this wrapping makes column config larger and harder to maintain.
renderHeader: () => <HeaderCell><Trans i18nKey="some-key"/></HeaderCell>
I think this problem requires solution at the library level How I see a perfect solution
const columns = useMemo([
{
field: 'title',
headerName: () => t('title'),
filterOperators: [
{
label: () => t('contains'),
headerLabel: () => t('contains')
}
]
}
], []);
const apiRef = useGridApiRef();
useLayoutEffect(() => {
const forceUpdate = () => {
apiRef.current.forceUpdate();
apiRef.current.updateColumns(columns)
};
i18n.on("languageChanged", forceUpdate);
return () => i18n.off("languageChanged", forceUpdate);
}, [apiRef, columns]);
return <DataGrid columns={columns} />
but right now this is impossible because headerName
doesn't accept a callback value
I guess this issue is becoming more of a feature request than a question
const columnsRef = useRef<ExtendedGridColDef[]>([
{
field: 'title',
lazyHeaderName: () => t('title'),
headerName: "",
}
], []);
const apiRef = useGridApiRef();
useLayoutEffect(() => {
const forceUpdate = () => {
apiRef.current.forceUpdate();
apiRef.current.updateColumns(columnsRef.current.map((column) => ({
...column,
headerName: column.lazyHeaderName()
}));
};
i18n.on("languageChanged", forceUpdate);
return () => i18n.off("languageChanged", forceUpdate);
}, [apiRef, columnsRef.current]);
return <DataGrid columns={columnsRef.current}/>
I am not sure where the problem is: This does work for me.
const translations = {
first_name: {
en: 'First Name',
de: 'Vorname',
},
last_name: {
en: 'Last Name',
de: 'Nachname',
},
};
export default function DataGridDemo() {
const [lang, setLang] = React.useState<'en' | 'de'>('en');
// dummy function to just return some values from an object
const t = (key: keyof typeof translations) => translations[key][lang];
const HeaderCell = ({ labelKey }: { labelKey: keyof typeof translations }) => (
<div>{t(labelKey)}</div>
);
const columns = React.useMemo(
() => [
{ field: 'id', headerName: 'ID', width: 90 },
{
field: 'firstName',
width: 150,
editable: true,
renderHeader: () => <HeaderCell labelKey="first_name" />,
},
{
field: 'lastName',
width: 150,
editable: true,
renderHeader: () => <HeaderCell labelKey="last_name" />,
},
],
[t],
);
...
Wouldn't this be sufficient?
This does work like as well when using:
const columns = React.useMemo(
() => [
{ field: 'id', headerName: 'ID', width: 90 },
{
field: 'firstName',
headerName: t('first_name'),
width: 150,
editable: true,
},
{
field: 'lastName',
headerName: t('last_name'),
width: 150,
editable: true,
},
],
[t],
);
Is i18n not updating the t
function on a language change?
I would need setup a dev environment with next for this. This might take until tomorrow though. Would that be ok?
Yes, and you can use my sandbox. next is already there
Is i18n not updating the t function on a language change?
The problem is not with i18next but with the columns
prop.
The columns
prop must keep the reference between two rerenders. Otherwise, the datagrid state will be reset
So putting the t
function into dependency array of useMemo is not an option.
const columns = React.useMemo(() => [{ field: 'id', headerName: t('id'), width: 90 }], [t]);
If you don't put the t
function into the dependency array then the header won't be updated when the language changes
We can use renderHeader
to workaround this problem, but I've already explained why I don't like this solution. And also what to do with filterOperator label, it doesn't have a renderLabel
option.
OK, thanks ... got it. It does indeed look as if there is no satisfying solution (afaik) to this. I will add this to the board and see what the team has to say about it.
You could probably use apiRef.updateColumns and pass the new headers, but it's not the prettier solution imaginable.
The problem in depth
I know that
columns
prop should keep the same reference between two rerenders to avoid loosing data grid state. But If I don't updatecolumns
prop when switching language then column headers aren't translated. If I updatecolumns
prop then data grid state is reset. What should I do in this situation?Link to sandbox
Steps:
https://github.com/mui/mui-x/assets/18424848/c3513836-210d-46fe-a1cc-f54c6e2af806
Your environment
No response
Search keywords: i18next translation column language data grid Order ID: 74777