Skip to content

Commit 0553e8d

Browse files
committed
Support resource specific translations in EditButton
1 parent cbd6210 commit 0553e8d

File tree

3 files changed

+128
-8
lines changed

3 files changed

+128
-8
lines changed

packages/ra-ui-materialui/src/button/EditButton.spec.tsx

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as React from 'react';
22
import { fireEvent, render, screen, waitFor } from '@testing-library/react';
33
import expect from 'expect';
4-
import { Basic, AccessControl } from './EditButton.stories';
4+
import { Basic, AccessControl, Label } from './EditButton.stories';
55

66
const invalidButtonDomProps = {
77
redirect: 'list',
@@ -23,6 +23,22 @@ describe('<EditButton />', () => {
2323
spy.mockRestore();
2424
});
2525

26+
it('should provide a default label', async () => {
27+
render(<Label translations="default" />);
28+
await screen.findByText('Edit');
29+
fireEvent.click(screen.getByText('English', { selector: 'button' }));
30+
fireEvent.click(await screen.findByText('Français'));
31+
await screen.findByText('Éditer');
32+
});
33+
34+
it('should allow resource specific default title', async () => {
35+
render(<Label translations="resource specific" />);
36+
await screen.findByText('Change War and Peace');
37+
fireEvent.click(screen.getByText('English', { selector: 'button' }));
38+
fireEvent.click(await screen.findByText('Français'));
39+
await screen.findByText('Modifier War and Peace');
40+
});
41+
2642
it('should only render when users have the right to edit', async () => {
2743
render(<AccessControl />);
2844
await screen.findByText('War and Peace');

packages/ra-ui-materialui/src/button/EditButton.stories.tsx

Lines changed: 87 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import englishMessages from 'ra-language-english';
44
import frenchMessages from 'ra-language-french';
55
import {
66
AuthProvider,
7+
I18nProvider,
8+
memoryStore,
9+
mergeTranslations,
710
RecordContextProvider,
811
Resource,
912
ResourceContextProvider,
@@ -20,15 +23,53 @@ import { SimpleForm } from '../form/SimpleForm';
2023
import { TextInput } from '../input/TextInput';
2124
import { EditButton } from './EditButton';
2225
import { Edit } from '../detail/Edit';
26+
import { LocalesMenuButton } from './LocalesMenuButton';
2327

2428
export default { title: 'ra-ui-materialui/button/EditButton' };
2529

30+
const defaultI18nProvider = () =>
31+
polyglotI18nProvider(
32+
locale => (locale === 'fr' ? frenchMessages : englishMessages),
33+
'en',
34+
[
35+
{ locale: 'en', name: 'English' },
36+
{ locale: 'fr', name: 'Français' },
37+
]
38+
);
39+
40+
const customI18nProvider = polyglotI18nProvider(
41+
locale =>
42+
locale === 'fr'
43+
? mergeTranslations(frenchMessages, {
44+
resources: {
45+
books: {
46+
action: {
47+
edit: 'Modifier %{recordRepresentation}',
48+
},
49+
},
50+
},
51+
})
52+
: mergeTranslations(englishMessages, {
53+
resources: {
54+
books: {
55+
action: {
56+
edit: 'Change %{recordRepresentation}',
57+
},
58+
},
59+
},
60+
}),
61+
'en',
62+
[
63+
{ locale: 'en', name: 'English' },
64+
{ locale: 'fr', name: 'Français' },
65+
]
66+
);
67+
2668
export const Basic = ({ buttonProps }: { buttonProps?: any }) => (
2769
<TestMemoryRouter>
2870
<AdminContext
29-
i18nProvider={polyglotI18nProvider(locale =>
30-
locale === 'fr' ? frenchMessages : englishMessages
31-
)}
71+
i18nProvider={defaultI18nProvider()}
72+
store={memoryStore()}
3273
>
3374
<ResourceContextProvider value="books">
3475
<RecordContextProvider value={{ id: 1 }}>
@@ -39,6 +80,47 @@ export const Basic = ({ buttonProps }: { buttonProps?: any }) => (
3980
</TestMemoryRouter>
4081
);
4182

83+
export const Label = ({
84+
translations = 'default',
85+
i18nProvider = translations === 'default'
86+
? defaultI18nProvider()
87+
: customI18nProvider,
88+
label,
89+
}: {
90+
i18nProvider?: I18nProvider;
91+
translations?: 'default' | 'resource specific';
92+
label?: string;
93+
}) => (
94+
<TestMemoryRouter>
95+
<AdminContext
96+
dataProvider={dataProvider}
97+
i18nProvider={i18nProvider}
98+
store={memoryStore()}
99+
>
100+
<ResourceContextProvider value="books">
101+
<RecordContextProvider
102+
value={{ id: 1, title: 'War and Peace' }}
103+
>
104+
<div>
105+
<EditButton label={label} />
106+
</div>
107+
</RecordContextProvider>
108+
<LocalesMenuButton />
109+
</ResourceContextProvider>
110+
</AdminContext>
111+
</TestMemoryRouter>
112+
);
113+
114+
Label.args = {
115+
translations: 'default',
116+
};
117+
Label.argTypes = {
118+
translations: {
119+
options: ['default', 'resource specific'],
120+
control: { type: 'radio' },
121+
},
122+
};
123+
42124
export const AccessControl = () => {
43125
const queryClient = new QueryClient();
44126

@@ -79,10 +161,9 @@ const AccessControlAdmin = ({ queryClient }: { queryClient: QueryClient }) => {
79161
<AdminContext
80162
dataProvider={dataProvider}
81163
authProvider={authProvider}
82-
i18nProvider={polyglotI18nProvider(locale =>
83-
locale === 'fr' ? frenchMessages : englishMessages
84-
)}
164+
i18nProvider={defaultI18nProvider()}
85165
queryClient={queryClient}
166+
store={memoryStore()}
86167
>
87168
<AdminUI
88169
layout={({ children }) => (

packages/ra-ui-materialui/src/button/EditButton.tsx

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ import {
1414
useRecordContext,
1515
useCreatePath,
1616
useCanAccess,
17+
useTranslate,
18+
useGetResourceLabel,
19+
useGetRecordRepresentation,
1720
} from 'ra-core';
1821

1922
import { Button, ButtonProps } from './Button';
@@ -39,7 +42,7 @@ export const EditButton = <RecordType extends RaRecord = any>(
3942
});
4043
const {
4144
icon = defaultIcon,
42-
label = 'ra.action.edit',
45+
label: labelProp,
4346
scrollToTop = true,
4447
className,
4548
...rest
@@ -57,7 +60,27 @@ export const EditButton = <RecordType extends RaRecord = any>(
5760
resource,
5861
record,
5962
});
63+
const translate = useTranslate();
64+
const getResourceLabel = useGetResourceLabel();
65+
const getRecordRepresentation = useGetRecordRepresentation();
66+
const recordRepresentationValue = getRecordRepresentation(record);
67+
6068
if (!record || !canAccess || isPending) return null;
69+
70+
const recordRepresentation =
71+
typeof recordRepresentationValue === 'string'
72+
? recordRepresentationValue
73+
: recordRepresentationValue?.toString();
74+
const label =
75+
labelProp ??
76+
translate(`resources.${resource}.action.edit`, {
77+
recordRepresentation,
78+
_: translate(`ra.action.edit`, {
79+
name: getResourceLabel(resource, 1),
80+
recordRepresentation,
81+
}),
82+
});
83+
6184
return (
6285
<StyledButton
6386
component={Link}

0 commit comments

Comments
 (0)