Skip to content

Commit 0ffd3cc

Browse files
authored
Merge pull request #865 from remap-keys/i18n
Internationalization
2 parents efca0dc + a034576 commit 0ffd3cc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1428
-510
lines changed

package.json

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
"date-fns": "^3.6.0",
1515
"downloadjs": "^1.4.7",
1616
"firebase": "^8.2.1",
17+
"i18next": "^24.2.2",
18+
"i18next-browser-languagedetector": "^8.0.4",
1719
"immer": "^8.0.0",
1820
"intel-hex": "^0.1.2",
1921
"notistack": "^2.0.3",
@@ -25,6 +27,7 @@
2527
"react-draggable": "^4.4.6",
2628
"react-google-charts": "^4.0.1",
2729
"react-helmet-async": "^2.0.5",
30+
"react-i18next": "^15.4.1",
2831
"react-image-gallery": "^1.3.0",
2932
"react-redux": "^9.1.2",
3033
"react-router": "^7.0.1",

src/App.tsx

+21
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,27 @@ import { Firmware } from './services/firmware/ui/Firmware';
1111
import Documents from './components/documents/Documents.container';
1212
import OrganizationManagement from './components/organizations/OrganizationManagement.container';
1313
import { StyledComponentProps, withStyles } from '@mui/styles';
14+
import i18n from 'i18next';
15+
import { initReactI18next } from 'react-i18next';
16+
import enJson from './assets/locales/en.json';
17+
import jaJson from './assets/locales/ja.json';
18+
import LanguageDetector from 'i18next-browser-languagedetector';
19+
20+
i18n
21+
.use(LanguageDetector)
22+
.use(initReactI18next)
23+
.init({
24+
resources: {
25+
en: {
26+
translation: enJson,
27+
},
28+
ja: {
29+
translation: jaJson,
30+
},
31+
},
32+
fallbackLng: 'en',
33+
interpolation: { escapeValue: false },
34+
});
1435

1536
class App extends React.Component<StyledComponentProps, {}> {
1637
constructor(

src/assets/locales/en.json

+310
Large diffs are not rendered by default.

src/assets/locales/ja.json

+333
Large diffs are not rendered by default.

src/components/catalog/content/Content.tsx

+5-4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
import { sendEventToGoogleAnalytics } from '../../../utils/GoogleAnalytics';
1515
import TweetButton from '../../common/twitter/TweetButton';
1616
import { useNavigate } from 'react-router';
17+
import { t } from 'i18next';
1718

1819
type ContentState = {};
1920
type OwnProps = {};
@@ -153,10 +154,10 @@ const CategoryKeyboardContent: React.FC<CategoryKeyboardContentProps> = ({
153154
/>
154155
<div className="catalog-content-nav">
155156
<Tabs value={value} indicatorColor="primary" onChange={onChangeTab}>
156-
<Tab label="Overview" />
157-
<Tab label="Keymap" />
158-
<Tab label="Firmware" />
159-
<Tab label="Build" />
157+
<Tab label={t('Overview')} />
158+
<Tab label={t('Keymap')} />
159+
<Tab label={t('Firmware')} />
160+
<Tab label={t('Build')} />
160161
</Tabs>
161162
<div className="catalog-share-buttons">
162163
<TweetButton url={url} />

src/components/catalog/keyboard/CatalogKeyboardHeader.tsx

+4-3
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
} from '@mui/material';
1616
import { Home, Store } from '@mui/icons-material';
1717
import './CatalogKeyboardHeader.scss';
18+
import { t } from 'i18next';
1819

1920
type CategoryHeaderProps = {
2021
definitionDocument: IKeyboardDefinitionDocument;
@@ -70,7 +71,7 @@ export const CatalogKeyboardHeader = ({
7071
<div className="catalog-keyboard-header-title">
7172
<Typography variant="h1">{definitionDocument.name}</Typography>
7273
<Typography variant="subtitle1">
73-
designed by{' '}
74+
{t('Designed by')}{' '}
7475
<a
7576
href={designerWebsiteUrl}
7677
target="_blank"
@@ -87,7 +88,7 @@ export const CatalogKeyboardHeader = ({
8788
<IconButton
8889
aria-controls="stores-menu"
8990
aria-haspopup={true}
90-
title="Stores"
91+
title={t('Stores')}
9192
onClick={onClickStoresMenu}
9293
>
9394
<Store htmlColor="white" fontSize="large" />
@@ -117,7 +118,7 @@ export const CatalogKeyboardHeader = ({
117118
href={definitionDocument.websiteUrl}
118119
target="_blank"
119120
rel="noreferrer"
120-
title="Keyboard Website"
121+
title={t('Keyboard Website')}
121122
>
122123
<Home htmlColor="white" fontSize="large" />
123124
</a>

src/components/catalog/keyboard/build/BuildParametersDialog.tsx

+11-8
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import {
4343
IBuildableFirmwareCodeParameterValues,
4444
IBuildableFirmwareCodeValueType,
4545
} from '../../../../store/state';
46+
import { t } from 'i18next';
4647

4748
type OwnProps = {
4849
open: boolean;
@@ -179,12 +180,12 @@ export default function BuildParametersDialog(
179180

180181
return (
181182
<Dialog open={props.open} maxWidth="lg" fullWidth>
182-
<DialogTitle>Build Parameters</DialogTitle>
183+
<DialogTitle>{t('Build Parameters')}</DialogTitle>
183184
<DialogContent dividers className="build-parameters-dialog-content">
184185
<TextField
185186
fullWidth
186-
label="Memorandum"
187-
placeholder="Fill in the memorandum of this build."
187+
label={t('Memorandum')}
188+
placeholder={t('Fill in the memorandum of this build.')}
188189
variant="outlined"
189190
sx={{ mb: 2 }}
190191
value={description}
@@ -201,7 +202,7 @@ export default function BuildParametersDialog(
201202
component="div"
202203
id="nested-list-subheader-firmware-files"
203204
>
204-
Firmware Files
205+
{t('Firmware Files')}
205206
</ListSubheader>
206207
}
207208
>
@@ -370,7 +371,7 @@ function EditorContainer(props: EditorContainerProps) {
370371
<React.Fragment>
371372
<FormControl fullWidth>
372373
<FormLabel id="buildParameterDialogEditorType">
373-
How do you want to customize this file?
374+
{t('How do you want to customize this file?')}
374375
</FormLabel>
375376
<RadioGroup
376377
row
@@ -386,12 +387,12 @@ function EditorContainer(props: EditorContainerProps) {
386387
<FormControlLabel
387388
value="parameters"
388389
control={<Radio />}
389-
label="By selecting and filling in each parameter"
390+
label={t('By selecting and filling in each parameter')}
390391
/>
391392
<FormControlLabel
392393
value="code"
393394
control={<Radio />}
394-
label="By editing a code"
395+
label={t('By editing a code')}
395396
/>
396397
</RadioGroup>
397398
</FormControl>
@@ -478,7 +479,9 @@ function ParameterEditors(props: ParameterEditorProps) {
478479
<Grid container spacing={2}>
479480
{parameterValueMapEntries.length === 0 ? (
480481
<Grid item xs={12}>
481-
<Typography variant="body1">No parameters available.</Typography>
482+
<Typography variant="body1">
483+
{t('No parameters available.')}
484+
</Typography>
482485
</Grid>
483486
) : (
484487
parameterValueMapEntries.map(([parameterName, parameter]) => (

src/components/catalog/keyboard/build/CatalogBuild.tsx

+7-5
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
} from '../../../../services/build/FirmwareCodeParser';
3030
import ConfirmDialog from '../../../common/confirm/ConfirmDialog';
3131
import { FirmwareBuildingTaskCard } from './FirmwareBuildingTaskCard';
32+
import { t } from 'i18next';
3233

3334
type OwnProps = {};
3435
type CatalogBuildProps = OwnProps &
@@ -278,24 +279,25 @@ export default function CatalogBuild(props: CatalogBuildProps) {
278279
{props.buildableFirmware == null ||
279280
!props.buildableFirmware.enabled ? (
280281
<Alert severity="info" sx={{ mb: 2 }}>
281-
The firmware building feature can&quot;t be used because firmware
282-
files for this keyboard are not registered by the owner yet.
282+
{t(
283+
'The firmware building feature can&quot;t be used because firmware files for this keyboard are not registered by the owner yet.'
284+
)}
283285
</Alert>
284286
) : null}
285287
<Box sx={{ display: 'flex', justifyContent: 'flex-end' }}>
286288
<FormControlLabel
287289
control={
288290
<Switch checked={autoReload} onChange={onChangeAutoReload} />
289291
}
290-
label="Auto"
292+
label={t('Auto')}
291293
/>
292294
<Button
293295
variant="outlined"
294296
sx={{ mr: '32px' }}
295297
onClick={onClickReload}
296298
disabled={!props.signedIn}
297299
>
298-
Reload
300+
{t('Reload')}
299301
</Button>
300302
<Button
301303
variant="contained"
@@ -306,7 +308,7 @@ export default function CatalogBuild(props: CatalogBuildProps) {
306308
!props.buildableFirmware.enabled
307309
}
308310
>
309-
Build Firmware
311+
{t('Build Firmware')}
310312
</Button>
311313
</Box>
312314
</Paper>

src/components/catalog/keyboard/build/FirmwareBuildingTaskCard.tsx

+30-19
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
Typography,
3030
} from '@mui/material';
3131
import { format } from 'date-fns';
32+
import { t } from 'i18next';
3233

3334
type ParameterNameValueMap = {
3435
[parameterName: string]: string;
@@ -258,12 +259,16 @@ export function FirmwareBuildingTaskCard(props: FirmwareBuildingTaskCardProps) {
258259
gridTemplateColumns: '1fr 1fr 1fr',
259260
}}
260261
>
261-
<Typography variant="subtitle1">Task ID: {props.task.id}</Typography>
262262
<Typography variant="subtitle1">
263-
Created at: {format(props.task.createdAt, 'yyyy-MM-dd hh:mm:ss')}
263+
{t('Task ID')}: {props.task.id}
264264
</Typography>
265265
<Typography variant="subtitle1">
266-
Updated at: {format(props.task.updatedAt, 'yyyy-MM-dd hh:mm:ss')}
266+
{t('Created at')}:{' '}
267+
{format(props.task.createdAt, 'yyyy-MM-dd hh:mm:ss')}
268+
</Typography>
269+
<Typography variant="subtitle1">
270+
{t('Updated at')}:{' '}
271+
{format(props.task.updatedAt, 'yyyy-MM-dd hh:mm:ss')}
267272
</Typography>
268273
</Box>
269274
<Stepper
@@ -275,35 +280,35 @@ export function FirmwareBuildingTaskCard(props: FirmwareBuildingTaskCardProps) {
275280
key={`firmware-building-task-${props.task.id}-waiting`}
276281
completed={props.task.status !== 'waiting'}
277282
>
278-
<StepLabel>Waiting</StepLabel>
283+
<StepLabel>{t('Waiting')}</StepLabel>
279284
</Step>
280285
<Step
281286
key={`firmware-building-task-${props.task.id}-building`}
282287
completed={isTaskCompleted(props.task)}
283288
>
284-
<StepLabel>Building</StepLabel>
289+
<StepLabel>{t('Building')}</StepLabel>
285290
</Step>
286291
{props.task.status === 'success' ? (
287292
<Step
288293
key={`firmware-building-task-${props.task.id}-success`}
289294
completed={true}
290295
>
291-
<StepLabel>Success</StepLabel>
296+
<StepLabel>{t('Success')}</StepLabel>
292297
</Step>
293298
) : props.task.status === 'failure' ? (
294299
<Step key={`firmware-building-task-${props.task.id}-failure`}>
295-
<StepLabel error={true}>Failure</StepLabel>
300+
<StepLabel error={true}>{t('Failure')}</StepLabel>
296301
</Step>
297302
) : (
298303
<Step key={`firmware-building-task-${props.task.id}-completed`}>
299-
<StepLabel>Completed</StepLabel>
304+
<StepLabel>{t('Completed')}</StepLabel>
300305
</Step>
301306
)}
302307
</Stepper>
303308
<Box sx={{ mb: 1 }}>
304309
<TextField
305310
variant="standard"
306-
label="Memorandum"
311+
label={t('Memorandum')}
307312
value={description}
308313
fullWidth
309314
sx={{ mt: 1 }}
@@ -318,21 +323,27 @@ export function FirmwareBuildingTaskCard(props: FirmwareBuildingTaskCardProps) {
318323
</Box>
319324
<Box sx={{ display: 'flex', flexDirection: 'column' }}>
320325
<Tabs value={logTabIndex} onChange={onLogTabChange}>
321-
<Tab label="Build Parameters" />
322-
<Tab label="Build Codes" />
326+
<Tab label={t('Build Parameters')} />
327+
<Tab label={t('Build Codes')} />
323328
{isTaskCompleted(props.task) && [
324-
<Tab label="Standard Output" key={`${props.task.id}-stdout}`} />,
325-
<Tab label="Standard Error" key={`${props.task.id}-stderr}`} />,
329+
<Tab
330+
label={t('Standard Output')}
331+
key={`${props.task.id}-stdout}`}
332+
/>,
333+
<Tab
334+
label={t('Standard Error')}
335+
key={`${props.task.id}-stderr}`}
336+
/>,
326337
]}
327338
</Tabs>
328339
{logTabIndex === 0 ? (
329340
<TableContainer sx={{ height: '148px', mt: 1 }}>
330341
<Table stickyHeader size="small">
331342
<TableHead>
332343
<TableRow>
333-
<TableCell>File</TableCell>
334-
<TableCell>Parameter</TableCell>
335-
<TableCell>Value</TableCell>
344+
<TableCell>{t('File')}</TableCell>
345+
<TableCell>{t('Parameter')}</TableCell>
346+
<TableCell>{t('Value')}</TableCell>
336347
</TableRow>
337348
</TableHead>
338349
<TableBody>
@@ -430,7 +441,7 @@ export function FirmwareBuildingTaskCard(props: FirmwareBuildingTaskCardProps) {
430441
props.onClickDownload(props.task);
431442
}}
432443
>
433-
Download
444+
{t('Download')}
434445
</Button>
435446
)}
436447
{props.task.status === 'success' && (
@@ -440,7 +451,7 @@ export function FirmwareBuildingTaskCard(props: FirmwareBuildingTaskCardProps) {
440451
props.onClickFlash(props.task);
441452
}}
442453
>
443-
Flash
454+
{t('Flash')}
444455
</Button>
445456
)}
446457
{isTaskCompleted(props.task) && (
@@ -450,7 +461,7 @@ export function FirmwareBuildingTaskCard(props: FirmwareBuildingTaskCardProps) {
450461
props.onClickDelete(props.task);
451462
}}
452463
>
453-
Delete
464+
{t('Delete')}
454465
</Button>
455466
)}
456467
</CardActions>

0 commit comments

Comments
 (0)