mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-09-12 17:45:22 +00:00
i18n: use automatic type inference of translation keys
Finally figured out a way to make typescript strongly type translation keys so we can avoid the tedium of creating enums of translation keys.
This commit is contained in:
+11
-11
@@ -35,7 +35,7 @@ import { useSelector } from '../reducers';
|
||||
import { useSettingIsShowDocsEnabled } from '../settings/hooks';
|
||||
import { isMacOS } from '../utils/os';
|
||||
import { editorActivateFile, editorCloseFile } from './actions';
|
||||
import { I18nId, useI18n } from './i18n';
|
||||
import { useI18n } from './i18n';
|
||||
import * as pybricksMicroPython from './pybricksMicroPython';
|
||||
import { pybricksMicroPythonId } from './pybricksMicroPython';
|
||||
import { UntitledHintContribution } from './untitledHint';
|
||||
@@ -129,9 +129,9 @@ const EditorContextMenu: React.VoidFunctionComponent<EditorContextMenuProps> = (
|
||||
const canRedo = model && model.canRedo();
|
||||
|
||||
return (
|
||||
<Menu aria-label={i18n.translate(I18nId.ContextMenuLabel)} role="menu">
|
||||
<Menu aria-label={i18n.translate('contextMenu.label')} role="menu">
|
||||
<EditorContextMenuItem
|
||||
label={i18n.translate(I18nId.Copy)}
|
||||
label={i18n.translate('copy')}
|
||||
icon="duplicate"
|
||||
keyboardShortcut={isMacOS() ? 'Cmd-C' : 'Ctrl-C'}
|
||||
disabled={!hasSelection}
|
||||
@@ -139,7 +139,7 @@ const EditorContextMenu: React.VoidFunctionComponent<EditorContextMenuProps> = (
|
||||
editorAction="editor.action.clipboardCopyAction"
|
||||
/>
|
||||
<EditorContextMenuItem
|
||||
label={i18n.translate(I18nId.Paste)}
|
||||
label={i18n.translate('paste')}
|
||||
icon="clipboard"
|
||||
keyboardShortcut={isMacOS() ? 'Cmd-V' : 'Ctrl-V'}
|
||||
disabled={!model}
|
||||
@@ -147,7 +147,7 @@ const EditorContextMenu: React.VoidFunctionComponent<EditorContextMenuProps> = (
|
||||
editorAction="editor.action.clipboardPasteAction"
|
||||
/>
|
||||
<EditorContextMenuItem
|
||||
label={i18n.translate(I18nId.SelectAll)}
|
||||
label={i18n.translate('selectAll')}
|
||||
icon="blank"
|
||||
keyboardShortcut={isMacOS() ? 'Cmd-A' : 'Ctrl-A'}
|
||||
disabled={!model}
|
||||
@@ -156,7 +156,7 @@ const EditorContextMenu: React.VoidFunctionComponent<EditorContextMenuProps> = (
|
||||
/>
|
||||
<MenuDivider />
|
||||
<EditorContextMenuItem
|
||||
label={i18n.translate(I18nId.Undo)}
|
||||
label={i18n.translate('undo')}
|
||||
icon="undo"
|
||||
keyboardShortcut={isMacOS() ? 'Cmd-Z' : 'Ctrl-Z'}
|
||||
disabled={!canUndo}
|
||||
@@ -164,7 +164,7 @@ const EditorContextMenu: React.VoidFunctionComponent<EditorContextMenuProps> = (
|
||||
editorAction="undo"
|
||||
/>
|
||||
<EditorContextMenuItem
|
||||
label={i18n.translate(I18nId.Redo)}
|
||||
label={i18n.translate('redo')}
|
||||
icon="redo"
|
||||
keyboardShortcut={isMacOS() ? 'Cmd-Shift-Z' : 'Ctrl-Shift-Z'}
|
||||
disabled={!canRedo}
|
||||
@@ -214,7 +214,7 @@ const TabCloseButton: React.VoidFunctionComponent<TabCloseButtonProps> = ({ uuid
|
||||
|
||||
return (
|
||||
<Button
|
||||
title={i18n.translate(I18nId.CloseFileTooltip, {
|
||||
title={i18n.translate('closeFile.tooltip', {
|
||||
fileName,
|
||||
})}
|
||||
minimal={true}
|
||||
@@ -369,7 +369,7 @@ const Editor: React.VFC = () => {
|
||||
(editor) => {
|
||||
const contrib = new UntitledHintContribution(
|
||||
editor,
|
||||
i18n.translate(I18nId.Placeholder),
|
||||
i18n.translate('placeholder'),
|
||||
);
|
||||
return () => contrib.dispose();
|
||||
},
|
||||
@@ -380,7 +380,7 @@ const Editor: React.VFC = () => {
|
||||
editor,
|
||||
() => ({
|
||||
id: 'pybricks.action.toggleDocs',
|
||||
label: i18n.translate(I18nId.ToggleDocs),
|
||||
label: i18n.translate('toggleDocs'),
|
||||
run: () => toggleIsSettingShowDocsEnabled(),
|
||||
keybindings: [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KeyD],
|
||||
}),
|
||||
@@ -391,7 +391,7 @@ const Editor: React.VFC = () => {
|
||||
editor,
|
||||
() => ({
|
||||
id: 'pybricks.action.check',
|
||||
label: i18n.translate(I18nId.Check),
|
||||
label: i18n.translate('check'),
|
||||
run: (e) => {
|
||||
// for checking, use the most recent compiler
|
||||
dispatch(compile(e.getValue(), 6, []));
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020-2022 The Pybricks Authors
|
||||
|
||||
import { lookup } from '../../test';
|
||||
import { I18nId as I18nId } from './i18n';
|
||||
import en from './translations/en.json';
|
||||
|
||||
describe('Ensure .json file has matches for I18nId', () => {
|
||||
test.each(Object.values(I18nId))('%s', (id) => {
|
||||
expect(lookup(en, id)).toBeDefined();
|
||||
});
|
||||
});
|
||||
+5
-18
@@ -1,25 +1,12 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020-2022 The Pybricks Authors
|
||||
//
|
||||
// Editor translation keys.
|
||||
// Copyright (c) 2022 The Pybricks Authors
|
||||
|
||||
import { I18n, useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
import { useI18n as useShopifyI18n } from '@shopify/react-i18n';
|
||||
import type { TypedI18n } from '../i18n';
|
||||
import type translations from './translations/en.json';
|
||||
|
||||
export function useI18n(): I18n {
|
||||
export function useI18n(): TypedI18n<typeof translations> {
|
||||
// istanbul ignore next: babel-loader rewrites this line
|
||||
const [i18n] = useShopifyI18n();
|
||||
return i18n;
|
||||
}
|
||||
|
||||
export enum I18nId {
|
||||
Placeholder = 'placeholder',
|
||||
Check = 'check',
|
||||
ToggleDocs = 'toggleDocs',
|
||||
Copy = 'copy',
|
||||
Paste = 'paste',
|
||||
SelectAll = 'selectAll',
|
||||
Undo = 'undo',
|
||||
Redo = 'redo',
|
||||
CloseFileTooltip = 'closeFile.tooltip',
|
||||
ContextMenuLabel = 'contextMenu.label',
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user