React-admin多语言字段过滤问题求助:3个核心疑问
问题解决方案
1. 解决过滤器参数格式不匹配问题
react-admin 默认会将带点的 source(比如name.en)解析为嵌套对象 {"name":{"en":"example"}},但你的后端需要扁平的 {"name.en":"example"} 格式。可以通过两种方式处理:
方式一:用filterToQuery转换参数
import { Datagrid, List, TextInput, TextField } from 'react-admin'; function ManufacturerList() { const manufacturerFilter = [ <TextInput source='name_en' // 用临时扁平source避免自动嵌套 alwaysOn resettable label="Name" />, ]; // 把临时参数转成后端需要的格式 const filterToQuery = (filter) => { return { ...filter, 'name.en': filter.name_en, }; }; return ( <List sort={{ field: 'name', order: 'ASC' }} filters={manufacturerFilter} filterToQuery={filterToQuery} > <Datagrid rowClick='show' bulkActionButtons={false}> <TextField source={`name.en`} /> <TextField source={`name.fr`} /> <TextField source={`name.cn`} /> </Datagrid> </List> ); } export default ManufacturerList;
方式二:给TextInput自定义解析/格式化函数
<TextInput source='name.en' alwaysOn resettable parse={(value) => ({ 'name.en': value })} // 直接返回后端需要的键值对 format={(value) => value?.['name.en']} // 回显时读取对应值 />
2. 动态匹配当前用户选择的语言
使用 react-admin 内置的useLocale钩子获取当前语言,动态设置过滤器的参数:
import { Datagrid, List, TextInput, TextField, useLocale } from 'react-admin'; function ManufacturerList() { const locale = useLocale(); // 获取当前语言,如'en'/'fr'/'cn' const tempSource = `name_${locale}`; const targetSource = `name.${locale}`; const manufacturerFilter = [ <TextInput source={tempSource} alwaysOn resettable label="Name" />, ]; const filterToQuery = (filter) => { const newFilter = { ...filter }; if (newFilter[tempSource]) { newFilter[targetSource] = newFilter[tempSource]; delete newFilter[tempSource]; } return newFilter; }; return ( <List sort={{ field: 'name', order: 'ASC' }} filters={manufacturerFilter} filterToQuery={filterToQuery} > <Datagrid rowClick='show' bulkActionButtons={false}> <TextField source={`name.en`} /> <TextField source={`name.fr`} /> <TextField source={`name.cn`} /> </Datagrid> </List> ); } export default ManufacturerList;
切换语言时,过滤器会自动匹配当前语言对应的字段。
3. 结合多语言字段与部分匹配(like功能)
根据后端的like查询规则,调整filterToQuery函数包装参数:
场景1:后端支持name.en.like格式
import { Datagrid, List, TextInput, TextField, useLocale } from 'react-admin'; function ManufacturerList() { const locale = useLocale(); const tempSource = `name_${locale}`; const targetSource = `name.${locale}.like`; const manufacturerFilter = [ <TextInput source={tempSource} alwaysOn resettable label="Name" />, ]; const filterToQuery = (filter) => { const newFilter = { ...filter }; if (newFilter[tempSource]) { // 包装成%xxx%适配模糊查询 newFilter[targetSource] = `%${newFilter[tempSource]}%`; delete newFilter[tempSource]; } return newFilter; }; return ( <List sort={{ field: 'name', order: 'ASC' }} filters={manufacturerFilter} filterToQuery={filterToQuery} > <Datagrid rowClick='show' bulkActionButtons={false}> <TextField source={`name.en`} /> <TextField source={`name.fr`} /> <TextField source={`name.cn`} /> </Datagrid> </List> ); } export default ManufacturerList;
场景2:后端支持嵌套结构的like(如{"name":{"en":{"like":"example"}}})
const filterToQuery = (filter) => { const newFilter = { ...filter }; if (newFilter[tempSource]) { newFilter.name = { ...newFilter.name, [locale]: { like: `%${newFilter[tempSource]}%` } }; delete newFilter[tempSource]; } return newFilter; };
内容的提问来源于stack exchange,提问作者Zovitch
相关产品推荐
相关产品推荐

