Skip to content

Commit 414e966

Browse files
Add missing translations for MUI and AgGrid (#714)
1 parent 4e612d7 commit 414e966

File tree

15 files changed

+115
-130
lines changed

15 files changed

+115
-130
lines changed

.eslintrc.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"warn",
2929
{
3030
"patterns": [{
31-
"group": ["@mui/*/*", "!@mui/material/colors"],
31+
"group": ["@mui/*/*", "!@mui/material/colors", "!@mui/material/locale"],
3232
"message": "Deep imports from MUI libraries are forbidden. Import only from the library root."
3333
}]
3434
}

demo/src/app.jsx

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,11 @@ import {
2626
Tooltip,
2727
Typography,
2828
} from '@mui/material';
29+
import { enUS, frFR } from '@mui/material/locale';
2930
import { Comment as CommentIcon } from '@mui/icons-material';
3031
import { BrowserRouter, useLocation, useMatch, useNavigate } from 'react-router';
3132
import { IntlProvider, useIntl } from 'react-intl';
32-
import { useCallback, useEffect, useRef, useState } from 'react';
33+
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3334
import translations from './demo_intl';
3435
import PowsyblLogo from '../images/powsybl_logo.svg?react'; // eslint-disable-line import/no-unresolved
3536
import AppPackage from '../../package.json';
@@ -100,6 +101,8 @@ import {
100101
commonButtonFr,
101102
networkModificationsEn,
102103
networkModificationsFr,
104+
logout,
105+
equipmentStyles,
103106
} from '../../src';
104107

105108
const messages = {
@@ -147,23 +150,23 @@ const messages = {
147150
},
148151
};
149152

150-
const lightTheme = createTheme({
153+
const lightTheme = {
151154
palette: {
152155
mode: 'light',
153156
},
154-
});
157+
};
155158

156-
const darkTheme = createTheme({
159+
const darkTheme = {
157160
palette: {
158161
mode: 'dark',
159162
},
160-
});
163+
};
161164

162-
const getMuiTheme = (theme) => {
163-
if (theme === LIGHT_THEME) {
164-
return lightTheme;
165-
}
166-
return darkTheme;
165+
const useMuiTheme = (theme, language) => {
166+
return useMemo(
167+
() => createTheme(theme === LIGHT_THEME ? lightTheme : darkTheme, language === LANG_FRENCH ? frFR : enUS),
168+
[language, theme]
169+
);
167170
};
168171

169172
const style = {
@@ -845,7 +848,7 @@ function AppContent({ language, onLanguageClick }) {
845848

846849
return (
847850
<StyledEngineProvider injectFirst>
848-
<ThemeProvider theme={getMuiTheme(theme)}>
851+
<ThemeProvider theme={useMuiTheme(theme, language)}>
849852
<SnackbarProvider hideIconVariant={false}>
850853
<CssBaseline />
851854
<CardErrorBoundary>

package-lock.json

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"licenses-check": "license-checker --summary --excludePrivatePackages --production --onlyAllow \"$( jq -r .onlyAllow[] license-checker-config.json | tr '\n' ';')\" --excludePackages \"$( jq -r .excludePackages[] license-checker-config.json | tr '\n' ';')\""
3535
},
3636
"dependencies": {
37+
"@ag-grid-community/locale": "^33.1.0",
3738
"@hello-pangea/dnd": "^18.0.1",
3839
"@react-querybuilder/dnd": "^8.2.0",
3940
"@react-querybuilder/material": "^8.2.0",

src/components/customAGGrid/customAggrid.style.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,4 @@ export const styles = {
4242
border: 'none !important',
4343
},
4444
}),
45-
noBorderRight: {
46-
// hides right border for header of "Edit" column due to column being pinned
47-
'& .ag-pinned-left-header': {
48-
borderRight: 'none',
49-
},
50-
},
5145
} as const satisfies Record<string, SxProps<Theme>>;

src/components/customAGGrid/customAggrid.tsx

Lines changed: 57 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -5,68 +5,73 @@
55
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
66
*/
77

8-
import React, { useCallback } from 'react';
9-
import { AgGridReact, AgGridReactProps } from 'ag-grid-react';
10-
import { useIntl } from 'react-intl';
8+
import { forwardRef, useMemo } from 'react';
9+
import { AgGridReact, type AgGridReactProps } from 'ag-grid-react';
1110
import 'ag-grid-community/styles/ag-grid.css';
1211
import 'ag-grid-community/styles/ag-theme-alpine.css';
13-
import { ColumnResizedEvent, GetLocaleTextParams } from 'ag-grid-community';
14-
import { Box, type SxProps, type Theme, useTheme } from '@mui/material';
12+
import type { ColumnResizedEvent } from 'ag-grid-community';
13+
import { AG_GRID_LOCALE_EN, AG_GRID_LOCALE_FR } from '@ag-grid-community/locale';
14+
import { useIntl } from 'react-intl';
15+
import { Box, type BoxProps, type Theme, useTheme } from '@mui/material';
1516
import { mergeSx } from '../../utils/styles';
1617
import { CUSTOM_AGGRID_THEME, styles } from './customAggrid.style';
18+
import { type GsLangUser, LANG_ENGLISH, LANG_FRENCH } from '../../utils/langs';
19+
20+
export type AgGridLocale = Partial<Record<keyof typeof AG_GRID_LOCALE_EN, string>>; // using EN for keyof because it's the only who has more keys, so more complete
21+
export type AgGridLocales = Record<GsLangUser, AgGridLocale>;
1722

18-
interface CustomAGGGridStyleProps {
19-
shouldHidePinnedHeaderRightBorder?: boolean;
23+
function useAgGridLocale(overrideLocales?: AgGridLocales) {
24+
const intl = useIntl();
25+
return useMemo((): Record<string, string> => {
26+
switch ((intl.locale || intl.defaultLocale).toLowerCase().substring(0, 2)) {
27+
case LANG_FRENCH:
28+
return {
29+
...AG_GRID_LOCALE_FR,
30+
thousandSeparator: ' ',
31+
decimalSeparator: ',',
32+
...overrideLocales?.[LANG_FRENCH],
33+
};
34+
case LANG_ENGLISH:
35+
default:
36+
return { ...AG_GRID_LOCALE_EN, ...overrideLocales?.[LANG_ENGLISH] };
37+
}
38+
}, [intl.defaultLocale, intl.locale, overrideLocales]);
2039
}
2140

22-
export interface CustomAGGridProps extends AgGridReactProps, CustomAGGGridStyleProps {}
41+
export type CustomAGGridProps<TData = any> = Omit<AgGridReactProps<TData>, 'localeText' | 'getLocaleText'> &
42+
Pick<BoxProps, 'sx'> & {
43+
overrideLocales?: AgGridLocales;
44+
};
2345

2446
// We have to define a minWidth to column to activate this feature
25-
const onColumnResized = (params: ColumnResizedEvent) => {
26-
const { column, finished } = params;
27-
const colDefinedMinWidth = column?.getColDef()?.minWidth;
28-
if (column && colDefinedMinWidth && finished) {
29-
const newWidth = column?.getActualWidth();
30-
if (newWidth < colDefinedMinWidth) {
31-
params.api.setColumnWidths([{ key: column, newWidth: colDefinedMinWidth }], finished, params.source);
47+
function onColumnResized({ api, column, finished, source }: ColumnResizedEvent) {
48+
if (column) {
49+
const colDefinedMinWidth = column.getColDef().minWidth;
50+
if (colDefinedMinWidth && finished && column.getActualWidth() < colDefinedMinWidth) {
51+
api.setColumnWidths([{ key: column, newWidth: colDefinedMinWidth }], finished, source);
3252
}
3353
}
34-
};
35-
36-
export const CustomAGGrid = React.forwardRef<AgGridReact, CustomAGGridProps>((props, ref) => {
37-
const { shouldHidePinnedHeaderRightBorder = false, ...agGridReactProps } = props;
38-
const theme = useTheme<Theme>();
39-
const intl = useIntl();
40-
41-
const GRID_PREFIX = 'grid.';
54+
}
4255

43-
const getLocaleText = useCallback(
44-
(params: GetLocaleTextParams) => {
45-
const key = GRID_PREFIX + params.key;
46-
return intl.formatMessage({
47-
id: key,
48-
defaultMessage: params.defaultValue,
49-
});
50-
},
51-
[intl]
52-
);
56+
export const CustomAGGrid = forwardRef<AgGridReact, CustomAGGridProps>(
57+
({ overrideLocales, sx, ...agGridReactProps }, ref) => {
58+
const theme = useTheme<Theme>();
5359

54-
return (
55-
<Box
56-
sx={mergeSx(
57-
styles.grid as SxProps | undefined,
58-
shouldHidePinnedHeaderRightBorder ? styles.noBorderRight : undefined
59-
)}
60-
className={`${theme.aggrid.theme} ${CUSTOM_AGGRID_THEME}`}
61-
>
62-
<AgGridReact
63-
ref={ref}
64-
getLocaleText={getLocaleText}
65-
onColumnResized={onColumnResized}
66-
enableCellTextSelection
67-
theme="legacy"
68-
{...agGridReactProps}
69-
/>
70-
</Box>
71-
);
72-
});
60+
return (
61+
<Box
62+
component="div"
63+
sx={mergeSx(styles.grid, sx)}
64+
className={`${theme.aggrid.theme} ${CUSTOM_AGGRID_THEME}`}
65+
>
66+
<AgGridReact
67+
ref={ref}
68+
localeText={useAgGridLocale(overrideLocales)}
69+
onColumnResized={onColumnResized}
70+
enableCellTextSelection
71+
theme="legacy"
72+
{...agGridReactProps}
73+
/>
74+
</Box>
75+
);
76+
}
77+
);

src/components/inputs/reactHookForm/agGridTable/CustomAgGridTable.tsx

Lines changed: 19 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,11 @@
77

88
import { useCallback, useEffect, useState } from 'react';
99
import { useFieldArray, useFormContext } from 'react-hook-form';
10-
import { AgGridReactProps } from 'ag-grid-react';
11-
import 'ag-grid-community/styles/ag-grid.css';
12-
import 'ag-grid-community/styles/ag-theme-alpine.css';
1310
import { Box, useTheme } from '@mui/material';
14-
import { useIntl } from 'react-intl';
15-
import { CellEditingStoppedEvent, ColumnState, SortChangedEvent } from 'ag-grid-community';
11+
import type { CellEditingStoppedEvent, ColumnState, SortChangedEvent } from 'ag-grid-community';
1612
import { BottomRightButtons } from './BottomRightButtons';
1713
import { FieldConstants } from '../../../../utils/constants/fieldConstants';
18-
import { CustomAGGrid } from '../../../customAGGrid';
14+
import { CustomAGGrid, type CustomAGGridProps } from '../../../customAGGrid';
1915

2016
const style = (customProps: any) => ({
2117
grid: (theme: any) => ({
@@ -75,32 +71,30 @@ const style = (customProps: any) => ({
7571
}),
7672
});
7773

78-
export interface CustomAgGridTableProps {
79-
name: string;
80-
columnDefs: any;
81-
makeDefaultRowData: any;
82-
csvProps: unknown;
83-
cssProps: unknown;
84-
defaultColDef: unknown;
85-
pagination: boolean;
86-
paginationPageSize: number;
87-
rowSelection?: AgGridReactProps['rowSelection'];
88-
alwaysShowVerticalScroll: boolean;
89-
stopEditingWhenCellsLoseFocus: boolean;
90-
}
74+
export type CustomAgGridTableProps = Required<
75+
Pick<
76+
CustomAGGridProps,
77+
| 'columnDefs'
78+
| 'defaultColDef'
79+
| 'pagination'
80+
| 'paginationPageSize'
81+
| 'alwaysShowVerticalScroll'
82+
| 'stopEditingWhenCellsLoseFocus'
83+
>
84+
> &
85+
Pick<CustomAGGridProps, 'rowSelection' | 'overrideLocales'> & {
86+
name: string;
87+
makeDefaultRowData: any;
88+
csvProps: unknown;
89+
cssProps: unknown;
90+
};
9191

9292
export function CustomAgGridTable({
9393
name,
94-
columnDefs,
9594
makeDefaultRowData,
9695
csvProps,
9796
cssProps,
98-
defaultColDef,
99-
pagination,
100-
paginationPageSize,
10197
rowSelection,
102-
alwaysShowVerticalScroll,
103-
stopEditingWhenCellsLoseFocus,
10498
...props
10599
}: Readonly<CustomAgGridTableProps>) {
106100
// FIXME: right type => Theme --> not defined there ( gridStudy and gridExplore definition not the same )
@@ -182,15 +176,6 @@ export function CustomAgGridTable({
182176
setNewRowAdded(true);
183177
};
184178

185-
const intl = useIntl();
186-
const getLocaleText = useCallback(
187-
(params: any) => {
188-
const key = `agGrid.${params.key}`;
189-
return intl.messages[key] || params.defaultValue;
190-
},
191-
[intl]
192-
);
193-
194179
const onGridReady = (params: any) => {
195180
setGridApi(params);
196181
};
@@ -227,13 +212,11 @@ export function CustomAgGridTable({
227212
<CustomAGGrid
228213
rowData={rowData}
229214
onGridReady={onGridReady}
230-
getLocaleText={getLocaleText}
231215
cacheOverflowSize={10}
232216
rowSelection={rowSelection ?? 'multiple'}
233217
rowDragEntireRow
234218
rowDragManaged
235219
onRowDragEnd={(e) => move(getIndex(e.node.data), e.overIndex)}
236-
columnDefs={columnDefs}
237220
detailRowAutoHeight
238221
onSelectionChanged={() => {
239222
setSelectedRows(gridApi.api.getSelectedRows());
@@ -242,10 +225,6 @@ export function CustomAgGridTable({
242225
onCellEditingStopped={onCellEditingStopped}
243226
onSortChanged={onSortChanged}
244227
getRowId={(row) => row.data[FieldConstants.AG_GRID_ROW_UUID]}
245-
pagination={pagination}
246-
paginationPageSize={paginationPageSize}
247-
alwaysShowVerticalScroll={alwaysShowVerticalScroll}
248-
stopEditingWhenCellsLoseFocus={stopEditingWhenCellsLoseFocus}
249228
theme="legacy"
250229
{...props}
251230
/>

src/components/topBar/TopBar.tsx

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,9 @@ import { LogoutProps } from '../authentication/Logout';
4949
import { useStateBoolean } from '../../hooks/customStates/useStateBoolean';
5050
import UserInformationDialog from './UserInformationDialog';
5151
import UserSettingsDialog from './UserSettingsDialog';
52-
import { Metadata } from '../../utils';
53-
import {
54-
DARK_THEME,
55-
LANG_ENGLISH,
56-
LANG_FRENCH,
57-
LANG_SYSTEM,
58-
LIGHT_THEME,
59-
} from '../../utils/constants/browserConstants';
52+
import { type Metadata } from '../../utils/types/metadata';
53+
import { DARK_THEME, type GsTheme, LIGHT_THEME } from '../../utils/styles';
54+
import { type GsLang, LANG_ENGLISH, LANG_FRENCH, LANG_SYSTEM } from '../../utils/langs';
6055
import MessageBanner from './MessageBanner';
6156

6257
const styles = {
@@ -155,10 +150,6 @@ const CustomListItemIcon = styled(ListItemIcon)({
155150
borderRadius: '25px',
156151
});
157152

158-
export type GsLangUser = typeof LANG_ENGLISH | typeof LANG_FRENCH;
159-
export type GsLang = GsLangUser | typeof LANG_SYSTEM;
160-
export type GsTheme = typeof LIGHT_THEME | typeof DARK_THEME;
161-
162153
function abbreviationFromUserName(name: string) {
163154
const tab = name.split(' ').map((x) => x.charAt(0));
164155
if (tab.length === 1) {

src/components/topBar/tests/TopBar.test.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { TopBar } from '../TopBar';
1515
import { Metadata } from '../../..';
1616

1717
import PowsyblLogo from './powsybl_logo.svg?react';
18-
import { LANG_ENGLISH } from '../../../utils/constants/browserConstants';
18+
import { LANG_ENGLISH } from '../../../utils/langs';
1919
import { topBarEn } from '../../../translations/en';
2020

2121
const apps: Metadata[] = [

src/hooks/useLocalizedCountries.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
99
import localizedCountries, { LocalizedCountries } from 'localized-countries';
1010
import countriesFr from 'localized-countries/data/fr';
1111
import countriesEn from 'localized-countries/data/en';
12-
import { LANG_ENGLISH, LANG_FRENCH, LANG_SYSTEM } from '../utils/constants/browserConstants';
12+
import { LANG_ENGLISH, LANG_FRENCH, LANG_SYSTEM } from '../utils/langs';
1313

1414
const supportedLanguages = [LANG_FRENCH, LANG_ENGLISH];
1515

0 commit comments

Comments
 (0)