Skip to content

Commit c02b6a0

Browse files
rhamiltoclaude
andcommitted
feat(BulkSelect): add internationalization (i18n) support
Fixes #895 Adds optional props to allow customization of all user-facing strings in the BulkSelect component, enabling applications to support multiple languages and custom terminology. New props: - selectNoneLabel: Custom label for "Select none" option - selectPageLabel: Custom label formatter for "Select page" option - selectAllLabel: Custom label formatter for "Select all" option - selectedLabel: Custom label formatter for selected count All props are optional with sensible English defaults to maintain backward compatibility. The label props for page/all/selected are functions that receive counts as parameters for proper pluralization and formatting flexibility. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent b7f8002 commit c02b6a0

File tree

2 files changed

+48
-5
lines changed

2 files changed

+48
-5
lines changed

packages/module/src/BulkSelect/BulkSelect.test.tsx

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,35 @@ describe('BulkSelect component', () => {
6969
expect(toggleWrapper).toBeInTheDocument();
7070
expect(toggleWrapper).toHaveClass('custom-menu-toggle');
7171
});
72+
73+
test('should render with custom i18n labels', async () => {
74+
const user = userEvent.setup();
75+
render(
76+
<BulkSelect
77+
canSelectAll
78+
pageCount={5}
79+
totalCount={10}
80+
selectedCount={2}
81+
pageSelected={false}
82+
pagePartiallySelected={true}
83+
onSelect={() => null}
84+
selectNoneLabel="Aucune sélection (0)"
85+
selectPageLabel={(count) => `Sélectionner la page${count ? ` (${count})` : ''}`}
86+
selectAllLabel={(count) => `Tout sélectionner${count ? ` (${count})` : ''}`}
87+
selectedLabel={(count) => `${count} sélectionné${count > 1 ? 's' : ''}`}
88+
/>
89+
);
90+
91+
// Check custom selected label
92+
expect(screen.getByText('2 sélectionnés')).toBeInTheDocument();
93+
94+
// Open the dropdown to check option labels
95+
const toggleButton = screen.getByLabelText('Bulk select toggle');
96+
await user.click(toggleButton);
97+
98+
// Check custom dropdown labels
99+
expect(screen.getByText('Aucune sélection (0)')).toBeInTheDocument();
100+
expect(screen.getByText('Sélectionner la page (5)')).toBeInTheDocument();
101+
expect(screen.getByText('Tout sélectionner (10)')).toBeInTheDocument();
102+
});
72103
});

packages/module/src/BulkSelect/BulkSelect.tsx

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ export interface BulkSelectProps extends Omit<DropdownProps, 'toggle' | 'onSelec
5050
dropdownListProps?: Omit<DropdownListProps, 'children'>;
5151
/** Additional props for MenuToggleProps */
5252
menuToggleProps?: Omit<MenuToggleProps, 'children' | 'splitButtonItems' | 'ref' | 'isExpanded' | 'onClick'>;
53+
/** Custom label for "Select none" option. Defaults to "Select none (0)" */
54+
selectNoneLabel?: string;
55+
/** Custom label for "Select page" option. Receives pageCount as parameter. Defaults to "Select page (N)" */
56+
selectPageLabel?: (pageCount?: number) => string;
57+
/** Custom label for "Select all" option. Receives totalCount as parameter. Defaults to "Select all (N)" */
58+
selectAllLabel?: (totalCount?: number) => string;
59+
/** Custom label formatter for selected count. Receives count as parameter. Defaults to "N selected" */
60+
selectedLabel?: (count: number) => string;
5361
}
5462

5563
export const BulkSelect: FC<BulkSelectProps> = ({
@@ -65,6 +73,10 @@ export const BulkSelect: FC<BulkSelectProps> = ({
6573
menuToggleCheckboxProps,
6674
dropdownListProps,
6775
menuToggleProps,
76+
selectNoneLabel = 'Select none (0)',
77+
selectPageLabel = (pageCount?: number) => `Select page${pageCount ? ` (${pageCount})` : ''}`,
78+
selectAllLabel = (totalCount?: number) => `Select all${totalCount ? ` (${totalCount})` : ''}`,
79+
selectedLabel = (count: number) => `${count} selected`,
6880
...props
6981
}: BulkSelectProps) => {
7082
const [ isOpen, setOpen ] = useState(false);
@@ -73,21 +85,21 @@ export const BulkSelect: FC<BulkSelectProps> = ({
7385
() => (
7486
<>
7587
<DropdownItem ouiaId={`${ouiaId}-select-none`} value={BulkSelectValue.none} key={BulkSelectValue.none}>
76-
Select none (0)
88+
{selectNoneLabel}
7789
</DropdownItem>
7890
{isDataPaginated && (
7991
<DropdownItem ouiaId={`${ouiaId}-select-page`} value={BulkSelectValue.page} key={BulkSelectValue.page}>
80-
{`Select page${pageCount ? ` (${pageCount})` : ''}`}
92+
{selectPageLabel(pageCount)}
8193
</DropdownItem>
8294
)}
8395
{canSelectAll && (
8496
<DropdownItem ouiaId={`${ouiaId}-select-all`} value={BulkSelectValue.all} key={BulkSelectValue.all}>
85-
{`Select all${totalCount ? ` (${totalCount})` : ''}`}
97+
{selectAllLabel(totalCount)}
8698
</DropdownItem>
8799
)}
88100
</>
89101
),
90-
[ isDataPaginated, canSelectAll, ouiaId, pageCount, totalCount ]
102+
[ isDataPaginated, canSelectAll, ouiaId, pageCount, totalCount, selectNoneLabel, selectPageLabel, selectAllLabel ]
91103
);
92104

93105
const allOption = isDataPaginated ? BulkSelectValue.page : BulkSelectValue.all;
@@ -129,7 +141,7 @@ export const BulkSelect: FC<BulkSelectProps> = ({
129141
>
130142
{selectedCount > 0 ? (
131143
<span data-ouia-component-id={`${ouiaId}-text`}>
132-
{`${selectedCount} selected`}
144+
{selectedLabel(selectedCount)}
133145
</span>
134146
) : null}
135147
</MenuToggleCheckbox>

0 commit comments

Comments
 (0)