Skip to content

Commit 958a79b

Browse files
authored
Merge pull request #1000 from pybricks/dlech
i18n: use automatic type inference of translation keys
2 parents 3e10096 + d6df128 commit 958a79b

Some content is hidden

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

80 files changed

+402
-875
lines changed

src/about/AboutDialog.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
} from '../app/constants';
1717
import LicenseDialog from '../licenses/LicenseDialog';
1818
import ExternalLinkIcon from '../utils/ExternalLinkIcon';
19-
import { I18nId, useI18n } from './i18n';
19+
import { useI18n } from './i18n';
2020

2121
import './about.scss';
2222

@@ -32,7 +32,7 @@ const AboutDialog: React.VoidFunctionComponent<AboutDialogProps> = ({
3232

3333
return (
3434
<Dialog
35-
title={i18n.translate(I18nId.Title, { appName })}
35+
title={i18n.translate('title', { appName })}
3636
isOpen={isOpen}
3737
onClose={onClose}
3838
>
@@ -41,7 +41,7 @@ const AboutDialog: React.VoidFunctionComponent<AboutDialogProps> = ({
4141
<img src="favicon.ico" />
4242
</div>
4343
<p>
44-
<strong>{i18n.translate(I18nId.Description)}</strong>
44+
<strong>{i18n.translate('description')}</strong>
4545
</p>
4646
<p>{`v${firmwareVersion} (${appName} v${appVersion})`}</p>
4747
<p>{pybricksCopyright}</p>
@@ -52,14 +52,14 @@ const AboutDialog: React.VoidFunctionComponent<AboutDialogProps> = ({
5252
</p>
5353
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
5454
<Button onClick={() => setIsLicenseDialogOpen(true)}>
55-
{i18n.translate(I18nId.LicenseButtonLabel)}
55+
{i18n.translate('licenseButton.label')}
5656
</Button>
5757
<AnchorButton href={changelogUrl} target="blank_">
58-
{i18n.translate(I18nId.ChangelogButtonLabel)}
58+
{i18n.translate('changelogButton.label')}
5959
<ExternalLinkIcon />
6060
</AnchorButton>
6161
<AnchorButton href={pybricksWebsiteUrl} target="blank_">
62-
{i18n.translate(I18nId.WebsiteButtonLabel)}
62+
{i18n.translate('websiteButton.label')}
6363
<ExternalLinkIcon />
6464
</AnchorButton>
6565
</div>

src/about/i18n.test.ts

Lines changed: 0 additions & 12 deletions
This file was deleted.

src/about/i18n.ts

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,12 @@
11
// SPDX-License-Identifier: MIT
2-
// Copyright (c) 2021-2022 The Pybricks Authors
2+
// Copyright (c) 2022 The Pybricks Authors
33

4-
// About dialog translation keys.
4+
import { useI18n as useShopifyI18n } from '@shopify/react-i18n';
5+
import type { TypedI18n } from '../i18n';
6+
import type translations from './translations/en.json';
57

6-
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
7-
8-
export function useI18n(): I18n {
8+
export function useI18n(): TypedI18n<typeof translations> {
99
// istanbul ignore next: babel-loader rewrites this line
1010
const [i18n] = useShopifyI18n();
1111
return i18n;
1212
}
13-
14-
export enum I18nId {
15-
Title = 'title',
16-
Description = 'description',
17-
LicenseButtonLabel = 'licenseButton.label',
18-
ChangelogButtonLabel = 'changelogButton.label',
19-
WebsiteButtonLabel = 'websiteButton.label',
20-
}

src/activities/Activities.tsx

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import React, { useCallback, useEffect, useRef } from 'react';
77
import { useLocalStorage } from 'usehooks-ts';
88
import Explorer from '../explorer/Explorer';
99
import Settings from '../settings/Settings';
10-
import { I18nId, useI18n } from './i18n';
10+
import { useI18n } from './i18n';
1111

1212
/** Indicates the selected activity. */
1313
export enum Activity {
@@ -101,7 +101,7 @@ const Activities: React.VoidFunctionComponent = () => {
101101

102102
return (
103103
<Tabs
104-
aria-label={i18n.translate(I18nId.Title)}
104+
aria-label={i18n.translate('title')}
105105
vertical={true}
106106
className="pb-activities"
107107
selectedTabId={selectedActivity}
@@ -110,12 +110,12 @@ const Activities: React.VoidFunctionComponent = () => {
110110
ref={tabsRef}
111111
>
112112
<Tab
113-
aria-label={i18n.translate(I18nId.Explorer)}
113+
aria-label={i18n.translate('explorer')}
114114
className="pb-activities-tablist-tab"
115115
id={Activity.Explorer}
116116
title={
117117
<Icon
118-
htmlTitle={i18n.translate(I18nId.Explorer)}
118+
htmlTitle={i18n.translate('explorer')}
119119
size={35}
120120
icon="document"
121121
/>
@@ -125,15 +125,11 @@ const Activities: React.VoidFunctionComponent = () => {
125125
onMouseDown={(e) => e.stopPropagation()}
126126
/>
127127
<Tab
128-
aria-label={i18n.translate(I18nId.Settings)}
128+
aria-label={i18n.translate('settings')}
129129
className="pb-activities-tablist-tab"
130130
id={Activity.Settings}
131131
title={
132-
<Icon
133-
htmlTitle={i18n.translate(I18nId.Settings)}
134-
size={35}
135-
icon="cog"
136-
/>
132+
<Icon htmlTitle={i18n.translate('settings')} size={35} icon="cog" />
137133
}
138134
panel={<Settings />}
139135
panelClassName="pb-activities-tabview"

src/activities/i18n.test.ts

Lines changed: 0 additions & 12 deletions
This file was deleted.

src/activities/i18n.ts

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,12 @@
11
// SPDX-License-Identifier: MIT
22
// Copyright (c) 2022 The Pybricks Authors
3-
//
4-
// Explorer translation keys.
53

6-
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
4+
import { useI18n as useShopifyI18n } from '@shopify/react-i18n';
5+
import type { TypedI18n } from '../i18n';
6+
import type translations from './translations/en.json';
77

8-
export function useI18n(): I18n {
8+
export function useI18n(): TypedI18n<typeof translations> {
99
// istanbul ignore next: babel-loader rewrites this line
1010
const [i18n] = useShopifyI18n();
1111
return i18n;
1212
}
13-
14-
export enum I18nId {
15-
Title = 'title',
16-
Explorer = 'explorer',
17-
Settings = 'settings',
18-
}

src/alerts/UnexpectedErrorAlert.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { AnchorButton, Button, ButtonGroup, Collapse, Intent } from '@blueprintj
66
import React, { useState } from 'react';
77
import { useId } from 'react-aria';
88
import { CreateToast } from '../i18nToaster';
9-
import { I18nId, useI18n } from './i18n';
9+
import { useI18n } from './i18n';
1010

1111
type UnexpectedErrorAlertProps = {
1212
error: Error;
@@ -21,7 +21,7 @@ const UnexpectedErrorAlert: React.VoidFunctionComponent<UnexpectedErrorAlertProp
2121

2222
return (
2323
<>
24-
<p>{i18n.translate(I18nId.Message, { errorMessage: error.message })}</p>
24+
<p>{i18n.translate('message', { errorMessage: error.message })}</p>
2525
<span>
2626
<Button
2727
aria-labelledby={labelId}
@@ -30,7 +30,7 @@ const UnexpectedErrorAlert: React.VoidFunctionComponent<UnexpectedErrorAlertProp
3030
icon={isExpanded ? 'chevron-down' : 'chevron-right'}
3131
onClick={() => setIsExpanded((v) => !v)}
3232
/>
33-
<span id={labelId}>{i18n.translate(I18nId.TechnicalInfo)}</span>
33+
<span id={labelId}>{i18n.translate('technicalInfo')}</span>
3434
</span>
3535
<Collapse isOpen={isExpanded}>
3636
<pre className="pb-alerts-stack-trace">{error.stack}</pre>
@@ -46,7 +46,7 @@ const UnexpectedErrorAlert: React.VoidFunctionComponent<UnexpectedErrorAlertProp
4646
)
4747
}
4848
>
49-
{i18n.translate(I18nId.CopyErrorMessage)}
49+
{i18n.translate('copyErrorMessage')}
5050
</Button>
5151
<AnchorButton
5252
intent={Intent.DANGER}
@@ -56,7 +56,7 @@ const UnexpectedErrorAlert: React.VoidFunctionComponent<UnexpectedErrorAlertProp
5656
)}+${encodeURIComponent(error.message)}`}
5757
target="_blank"
5858
>
59-
{i18n.translate(I18nId.ReportBug)}
59+
{i18n.translate('reportBug')}
6060
</AnchorButton>
6161
</ButtonGroup>
6262
</div>

src/alerts/i18n.test.ts

Lines changed: 0 additions & 12 deletions
This file was deleted.

src/alerts/i18n.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
11
// SPDX-License-Identifier: MIT
2-
// Copyright (c) 2020-2022 The Pybricks Authors
2+
// Copyright (c) 2022 The Pybricks Authors
33

4-
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
4+
import { useI18n as useShopifyI18n } from '@shopify/react-i18n';
5+
import type { TypedI18n } from '../i18n';
6+
import type translations from './translations/en.json';
57

6-
export function useI18n(): I18n {
8+
export function useI18n(): TypedI18n<typeof translations> {
79
// istanbul ignore next: babel-loader rewrites this line
810
const [i18n] = useShopifyI18n();
911
return i18n;
1012
}
11-
12-
export enum I18nId {
13-
Message = 'message',
14-
TechnicalInfo = 'technicalInfo',
15-
CopyErrorMessage = 'copyErrorMessage',
16-
ReportBug = 'reportBug',
17-
}

src/ble/alerts/BluetoothNotAvailable.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
import { Intent } from '@blueprintjs/core';
55
import React from 'react';
66
import { CreateToast } from '../../i18nToaster';
7-
import { I18nId, useI18n } from './i18n';
7+
import { useI18n } from './i18n';
88

99
const BluetoothNotAvailable: React.VoidFunctionComponent = () => {
1010
const i18n = useI18n();
1111
return (
1212
<>
13-
<p>{i18n.translate(I18nId.BluetoothNotAvailableMessage)}</p>
14-
<p>{i18n.translate(I18nId.BluetoothNotAvailableSuggestion)}</p>
13+
<p>{i18n.translate('bluetoothNotAvailable.message')}</p>
14+
<p>{i18n.translate('bluetoothNotAvailable.suggestion')}</p>
1515
</>
1616
);
1717
};

0 commit comments

Comments
 (0)