Skip to content

Commit 2e5ce15

Browse files
committed
Support resource specific translations in ShowButton
1 parent 0553e8d commit 2e5ce15

File tree

3 files changed

+128
-8
lines changed

3 files changed

+128
-8
lines changed

packages/ra-ui-materialui/src/button/ShowButton.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 './ShowButton.stories';
4+
import { Basic, AccessControl, Label } from './ShowButton.stories';
55

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

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

packages/ra-ui-materialui/src/button/ShowButton.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,
@@ -19,15 +22,53 @@ import { TextField } from '../field/TextField';
1922
import ShowButton from './ShowButton';
2023
import { Show } from '../detail/Show';
2124
import { SimpleShowLayout } from '../detail/SimpleShowLayout';
25+
import { LocalesMenuButton } from './LocalesMenuButton';
2226

2327
export default { title: 'ra-ui-materialui/button/ShowButton' };
2428

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

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

@@ -78,10 +160,9 @@ const AccessControlAdmin = ({ queryClient }: { queryClient: QueryClient }) => {
78160
<AdminContext
79161
dataProvider={dataProvider}
80162
authProvider={authProvider}
81-
i18nProvider={polyglotI18nProvider(locale =>
82-
locale === 'fr' ? frenchMessages : englishMessages
83-
)}
163+
i18nProvider={defaultI18nProvider()}
84164
queryClient={queryClient}
165+
store={memoryStore()}
85166
>
86167
<AdminUI
87168
layout={({ children }) => (

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

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ import {
88
useRecordContext,
99
useCreatePath,
1010
useCanAccess,
11+
useTranslate,
12+
useGetResourceLabel,
13+
useGetRecordRepresentation,
1114
} from 'ra-core';
1215

1316
import { Button, ButtonProps } from './Button';
@@ -30,7 +33,7 @@ const ShowButton = <RecordType extends RaRecord = any>(
3033
) => {
3134
const {
3235
icon = defaultIcon,
33-
label = 'ra.action.show',
36+
label: labelProp,
3437
record: recordProp,
3538
resource: resourceProp,
3639
scrollToTop = true,
@@ -49,7 +52,27 @@ const ShowButton = <RecordType extends RaRecord = any>(
4952
resource,
5053
record,
5154
});
55+
const translate = useTranslate();
56+
const getResourceLabel = useGetResourceLabel();
57+
const getRecordRepresentation = useGetRecordRepresentation();
58+
const recordRepresentationValue = getRecordRepresentation(record);
59+
5260
if (!record || !canAccess || isPending) return null;
61+
62+
const recordRepresentation =
63+
typeof recordRepresentationValue === 'string'
64+
? recordRepresentationValue
65+
: recordRepresentationValue?.toString();
66+
const label =
67+
labelProp ??
68+
translate(`resources.${resource}.action.show`, {
69+
recordRepresentation,
70+
_: translate(`ra.action.show`, {
71+
name: getResourceLabel(resource, 1),
72+
recordRepresentation,
73+
}),
74+
});
75+
5376
return (
5477
<Button
5578
component={Link}

0 commit comments

Comments
 (0)