@@ -18,6 +18,7 @@ | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import styled from '@emotion/styled'; | |||
import classNames from 'classnames'; | |||
import tw from 'twin.macro'; | |||
import { themeColor, themeContrast } from '../helpers'; | |||
import { Key } from '../helpers/keyboard'; | |||
@@ -35,6 +36,8 @@ export const mappedKeys = { | |||
[Key.Click]: 'click', | |||
}; | |||
const NON_KEY_SYMBOLS = ['+', ' ']; | |||
export function KeyboardHintKeys({ command }: { command: string }) { | |||
const keys = command | |||
.trim() | |||
@@ -42,11 +45,19 @@ export function KeyboardHintKeys({ command }: { command: string }) { | |||
.map((key, index) => { | |||
const uniqueKey = `${key}-${index}`; | |||
if (!(Object.keys(mappedKeys).includes(key) || Object.values(mappedKeys).includes(key))) { | |||
if (NON_KEY_SYMBOLS.includes(key)) { | |||
return <span key={uniqueKey}>{key}</span>; | |||
} | |||
return <KeyBox key={uniqueKey}>{mappedKeys[key as keyof typeof mappedKeys] || key}</KeyBox>; | |||
const isNonMappedKey = !( | |||
Object.keys(mappedKeys).includes(key) || Object.values(mappedKeys).includes(key) | |||
); | |||
return ( | |||
<KeyBox className={classNames({ 'sw-px-1': isNonMappedKey })} key={uniqueKey}> | |||
{Object.keys(mappedKeys).includes(key) ? mappedKeys[key as keyof typeof mappedKeys] : key} | |||
</KeyBox> | |||
); | |||
}); | |||
return <div className="sw-flex sw-gap-1">{keys}</div>; |
@@ -46,12 +46,12 @@ exports[`renders on mac 1`] = ` | |||
class="sw-flex sw-gap-1" | |||
> | |||
<span | |||
class="emotion-2 emotion-3" | |||
class=" emotion-2 emotion-3" | |||
> | |||
⌘ | |||
</span> | |||
<span | |||
class="emotion-2 emotion-3" | |||
class=" emotion-2 emotion-3" | |||
> | |||
⌥ | |||
</span> | |||
@@ -106,12 +106,12 @@ exports[`renders on windows 1`] = ` | |||
class="sw-flex sw-gap-1" | |||
> | |||
<span | |||
class="emotion-2 emotion-3" | |||
class=" emotion-2 emotion-3" | |||
> | |||
Ctrl | |||
</span> | |||
<span | |||
class="emotion-2 emotion-3" | |||
class=" emotion-2 emotion-3" | |||
> | |||
Alt | |||
</span> | |||
@@ -138,6 +138,26 @@ exports[`renders with command 1`] = ` | |||
color: rgb(106,117,144); | |||
} | |||
.emotion-2 { | |||
display: -webkit-box; | |||
display: -webkit-flex; | |||
display: -ms-flexbox; | |||
display: flex; | |||
-webkit-align-items: center; | |||
-webkit-box-align: center; | |||
-ms-flex-align: center; | |||
align-items: center; | |||
-webkit-box-pack: center; | |||
-ms-flex-pack: center; | |||
-webkit-justify-content: center; | |||
justify-content: center; | |||
padding-left: 0.125rem; | |||
padding-right: 0.125rem; | |||
border-radius: 0.125rem; | |||
background-color: rgb(225,230,243); | |||
color: rgb(62,67,87); | |||
} | |||
<div> | |||
<div | |||
class="emotion-0 emotion-1" | |||
@@ -145,7 +165,9 @@ exports[`renders with command 1`] = ` | |||
<div | |||
class="sw-flex sw-gap-1" | |||
> | |||
<span> | |||
<span | |||
class="sw-px-1 emotion-2 emotion-3" | |||
> | |||
command | |||
</span> | |||
</div> | |||
@@ -204,7 +226,7 @@ exports[`renders with title 1`] = ` | |||
class="sw-flex sw-gap-1" | |||
> | |||
<span | |||
class="emotion-2 emotion-3" | |||
class=" emotion-2 emotion-3" | |||
> | |||
click | |||
</span> | |||
@@ -259,7 +281,7 @@ exports[`renders without title 1`] = ` | |||
class="sw-flex sw-gap-1" | |||
> | |||
<span | |||
class="emotion-2 emotion-3" | |||
class=" emotion-2 emotion-3" | |||
> | |||
click | |||
</span> |
@@ -26,7 +26,7 @@ exports[`should render Alt 1`] = ` | |||
class="sw-flex sw-gap-1" | |||
> | |||
<span | |||
class="emotion-0 emotion-1" | |||
class=" emotion-0 emotion-1" | |||
> | |||
Alt | |||
</span> | |||
@@ -60,7 +60,7 @@ exports[`should render ArrowDown 1`] = ` | |||
class="sw-flex sw-gap-1" | |||
> | |||
<span | |||
class="emotion-0 emotion-1" | |||
class=" emotion-0 emotion-1" | |||
> | |||
<svg | |||
aria-hidden="true" | |||
@@ -108,7 +108,7 @@ exports[`should render ArrowLeft 1`] = ` | |||
class="sw-flex sw-gap-1" | |||
> | |||
<span | |||
class="emotion-0 emotion-1" | |||
class=" emotion-0 emotion-1" | |||
> | |||
<svg | |||
aria-hidden="true" | |||
@@ -156,7 +156,7 @@ exports[`should render ArrowRight 1`] = ` | |||
class="sw-flex sw-gap-1" | |||
> | |||
<span | |||
class="emotion-0 emotion-1" | |||
class=" emotion-0 emotion-1" | |||
> | |||
<svg | |||
aria-hidden="true" | |||
@@ -204,7 +204,7 @@ exports[`should render ArrowUp 1`] = ` | |||
class="sw-flex sw-gap-1" | |||
> | |||
<span | |||
class="emotion-0 emotion-1" | |||
class=" emotion-0 emotion-1" | |||
> | |||
<svg | |||
aria-hidden="true" | |||
@@ -252,7 +252,7 @@ exports[`should render Click 1`] = ` | |||
class="sw-flex sw-gap-1" | |||
> | |||
<span | |||
class="emotion-0 emotion-1" | |||
class=" emotion-0 emotion-1" | |||
> | |||
click | |||
</span> | |||
@@ -286,7 +286,7 @@ exports[`should render Command 1`] = ` | |||
class="sw-flex sw-gap-1" | |||
> | |||
<span | |||
class="emotion-0 emotion-1" | |||
class=" emotion-0 emotion-1" | |||
> | |||
⌘ | |||
</span> | |||
@@ -320,7 +320,7 @@ exports[`should render Control 1`] = ` | |||
class="sw-flex sw-gap-1" | |||
> | |||
<span | |||
class="emotion-0 emotion-1" | |||
class=" emotion-0 emotion-1" | |||
> | |||
Ctrl | |||
</span> | |||
@@ -354,7 +354,7 @@ exports[`should render Option 1`] = ` | |||
class="sw-flex sw-gap-1" | |||
> | |||
<span | |||
class="emotion-0 emotion-1" | |||
class=" emotion-0 emotion-1" | |||
> | |||
⌥ | |||
</span> | |||
@@ -388,7 +388,7 @@ exports[`should render a default text if no keys match 1`] = ` | |||
class="sw-flex sw-gap-1" | |||
> | |||
<span | |||
class="emotion-0 emotion-1" | |||
class=" emotion-0 emotion-1" | |||
> | |||
Ctrl | |||
</span> | |||
@@ -396,7 +396,7 @@ exports[`should render a default text if no keys match 1`] = ` | |||
+ | |||
</span> | |||
<span | |||
class="emotion-0 emotion-1" | |||
class=" emotion-0 emotion-1" | |||
> | |||
click | |||
</span> | |||
@@ -429,11 +429,13 @@ exports[`should render multiple keys 1`] = ` | |||
<div | |||
class="sw-flex sw-gap-1" | |||
> | |||
<span> | |||
<span | |||
class="sw-px-1 emotion-0 emotion-1" | |||
> | |||
Use | |||
</span> | |||
<span | |||
class="emotion-0 emotion-1" | |||
class=" emotion-0 emotion-1" | |||
> | |||
Ctrl | |||
</span> | |||
@@ -441,7 +443,7 @@ exports[`should render multiple keys 1`] = ` | |||
+ | |||
</span> | |||
<span | |||
class="emotion-0 emotion-1" | |||
class=" emotion-0 emotion-1" | |||
> | |||
<svg | |||
aria-hidden="true" | |||
@@ -460,7 +462,7 @@ exports[`should render multiple keys 1`] = ` | |||
</svg> | |||
</span> | |||
<span | |||
class="emotion-0 emotion-1" | |||
class=" emotion-0 emotion-1" | |||
> | |||
<svg | |||
aria-hidden="true" | |||
@@ -508,7 +510,7 @@ exports[`should render multiple keys with non-key symbols 1`] = ` | |||
class="sw-flex sw-gap-1" | |||
> | |||
<span | |||
class="emotion-0 emotion-1" | |||
class=" emotion-0 emotion-1" | |||
> | |||
Ctrl | |||
</span> | |||
@@ -516,7 +518,7 @@ exports[`should render multiple keys with non-key symbols 1`] = ` | |||
+ | |||
</span> | |||
<span | |||
class="emotion-0 emotion-1" | |||
class=" emotion-0 emotion-1" | |||
> | |||
<svg | |||
aria-hidden="true" | |||
@@ -535,7 +537,7 @@ exports[`should render multiple keys with non-key symbols 1`] = ` | |||
</svg> | |||
</span> | |||
<span | |||
class="emotion-0 emotion-1" | |||
class=" emotion-0 emotion-1" | |||
> | |||
<svg | |||
aria-hidden="true" |
@@ -19,6 +19,7 @@ | |||
*/ | |||
export * from './colors'; | |||
export * from './constants'; | |||
export * from './keyboard'; | |||
export * from './positioning'; | |||
export * from './tabs'; | |||
export * from './theme'; |
@@ -18,115 +18,148 @@ | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
import { | |||
ContentCell, | |||
Key, | |||
KeyboardHint, | |||
Link, | |||
Modal, | |||
SubTitle, | |||
Table, | |||
TableRow, | |||
} from 'design-system'; | |||
import * as React from 'react'; | |||
import Link from '../../components/common/Link'; | |||
import Modal from '../../components/controls/Modal'; | |||
import { Button } from '../../components/controls/buttons'; | |||
import { isInput } from '../../helpers/keyboardEventHelpers'; | |||
import { KeyboardKeys } from '../../helpers/keycodes'; | |||
import { translate } from '../../helpers/l10n'; | |||
import { getKeyboardShortcutEnabled } from '../../helpers/preferences'; | |||
type Shortcuts = Array<{ | |||
category: string; | |||
shortcuts: Array<{ | |||
keys: string[]; | |||
action: string; | |||
}>; | |||
}>; | |||
const CATEGORIES: { left: Shortcuts; right: Shortcuts } = { | |||
left: [ | |||
{ | |||
category: 'global', | |||
shortcuts: [ | |||
{ keys: ['s'], action: 'search' }, | |||
{ keys: ['?'], action: 'open_shortcuts' }, | |||
], | |||
}, | |||
{ | |||
category: 'issues_page', | |||
shortcuts: [ | |||
{ keys: ['↑', '↓'], action: 'navigate' }, | |||
{ keys: ['→'], action: 'source_code' }, | |||
{ keys: ['←'], action: 'back' }, | |||
{ keys: ['alt', '+', '↑', '↓'], action: 'navigate_locations' }, | |||
{ keys: ['alt', '+', '←', '→'], action: 'switch_flows' }, | |||
{ keys: ['f'], action: 'transition' }, | |||
{ keys: ['a'], action: 'assign' }, | |||
{ keys: ['m'], action: 'assign_to_me' }, | |||
{ keys: ['i'], action: 'severity' }, | |||
{ keys: ['ctrl', '+', 'enter'], action: 'submit_comment' }, | |||
{ keys: ['t'], action: 'tags' }, | |||
], | |||
}, | |||
], | |||
right: [ | |||
{ | |||
category: 'code_page', | |||
shortcuts: [ | |||
{ keys: ['↑', '↓'], action: 'select_files' }, | |||
{ keys: ['→'], action: 'open_file' }, | |||
{ keys: ['←'], action: 'back' }, | |||
], | |||
}, | |||
{ | |||
category: 'measures_page', | |||
shortcuts: [ | |||
{ keys: ['↑', '↓'], action: 'select_files' }, | |||
{ keys: ['→'], action: 'open_file' }, | |||
{ keys: ['←'], action: 'back' }, | |||
], | |||
}, | |||
{ | |||
category: 'rules_page', | |||
shortcuts: [ | |||
{ keys: ['↑', '↓'], action: 'navigate' }, | |||
{ keys: ['→'], action: 'rule_details' }, | |||
{ keys: ['←'], action: 'back' }, | |||
], | |||
}, | |||
], | |||
type Section = { | |||
rows: Array<{ command: string; description: string }>; | |||
subTitle: string; | |||
}; | |||
function renderShortcuts(list: Shortcuts) { | |||
return ( | |||
<> | |||
{list.map(({ category, shortcuts }) => ( | |||
<div key={category} className="spacer-bottom"> | |||
<h3 className="null-spacer-top">{translate('keyboard_shortcuts', category, 'title')}</h3> | |||
<table> | |||
<thead> | |||
<tr> | |||
<th>{translate('keyboard_shortcuts.shortcut')}</th> | |||
<th>{translate('keyboard_shortcuts.action')}</th> | |||
</tr> | |||
</thead> | |||
<tbody> | |||
{shortcuts.map(({ action, keys }) => ( | |||
<tr key={action}> | |||
<td> | |||
{keys.map((k) => | |||
k === '+' ? ( | |||
<span key={k} className="little-spacer-right"> | |||
{k} | |||
</span> | |||
) : ( | |||
<code key={k} className="little-spacer-right"> | |||
{k} | |||
</code> | |||
), | |||
)} | |||
</td> | |||
<td>{translate('keyboard_shortcuts', category, action)}</td> | |||
</tr> | |||
))} | |||
</tbody> | |||
</table> | |||
</div> | |||
))} | |||
</> | |||
); | |||
const FILE_ROWS = [ | |||
{ | |||
command: `${Key.ArrowUp} ${Key.ArrowDown}`, | |||
description: 'keyboard_shortcuts_modal.code_page.select_files', | |||
}, | |||
{ | |||
command: `${Key.ArrowRight}`, | |||
description: 'keyboard_shortcuts_modal.code_page.open_file', | |||
}, | |||
{ | |||
command: `${Key.ArrowLeft}`, | |||
description: 'keyboard_shortcuts_modal.return_back_to_the_list', | |||
}, | |||
]; | |||
export const SECTIONS: Array<Section> = [ | |||
{ | |||
rows: [ | |||
{ | |||
command: 's', | |||
description: 'keyboard_shortcuts_modal.global.open_search_bar', | |||
}, | |||
{ | |||
command: '?', | |||
description: 'keyboard_shortcuts_modal.global.open_keyboard_shortcuts_modal', | |||
}, | |||
], | |||
subTitle: 'keyboard_shortcuts_modal.global', | |||
}, | |||
{ | |||
rows: [ | |||
{ | |||
command: `${Key.ArrowUp} ${Key.ArrowDown}`, | |||
description: 'keyboard_shortcuts_modal.navigate_between_issues', | |||
}, | |||
{ | |||
command: `${Key.ArrowRight}`, | |||
description: 'keyboard_shortcuts_modal.open_issue', | |||
}, | |||
{ | |||
command: `${Key.ArrowLeft}`, | |||
description: 'keyboard_shortcuts_modal.return_back_to_the_list', | |||
}, | |||
{ | |||
command: `${Key.Alt} + ${Key.ArrowUp} ${Key.ArrowDown}`, | |||
description: 'keyboard_shortcuts_modal.issue_details_page.navigate_issue_locations', | |||
}, | |||
{ | |||
command: `${Key.Alt} + ${Key.ArrowLeft} ${Key.ArrowRight}`, | |||
description: 'keyboard_shortcuts_modal.issue_details_page.switch_flows', | |||
}, | |||
{ | |||
command: 'f', | |||
description: 'keyboard_shortcuts_modal.do_issue_transition', | |||
}, | |||
{ | |||
command: 'a', | |||
description: 'keyboard_shortcuts_modal.assign_issue', | |||
}, | |||
{ | |||
command: 'm', | |||
description: 'keyboard_shortcuts_modal.assign_issue_to_me', | |||
}, | |||
{ | |||
command: 't', | |||
description: 'keyboard_shortcuts_modal.change_tags_of_issue', | |||
}, | |||
{ | |||
command: `${Key.Control} + ${Key.Enter}`, | |||
description: 'keyboard_shortcuts_modal.issue_details_page.submit_comment', | |||
}, | |||
], | |||
subTitle: 'keyboard_shortcuts_modal.issues_page', | |||
}, | |||
{ | |||
rows: FILE_ROWS, | |||
subTitle: 'keyboard_shortcuts_modal.code_page', | |||
}, | |||
{ | |||
rows: FILE_ROWS, | |||
subTitle: 'keyboard_shortcuts_modal.measures_page', | |||
}, | |||
{ | |||
rows: [ | |||
{ | |||
command: `${Key.ArrowUp} ${Key.ArrowDown}`, | |||
description: 'keyboard_shortcuts_modal.rules_page.navigate_between_rule', | |||
}, | |||
{ | |||
command: `${Key.ArrowRight}`, | |||
description: 'keyboard_shortcuts_modal.rules_page.open_rule', | |||
}, | |||
{ | |||
command: `${Key.ArrowLeft}`, | |||
description: 'keyboard_shortcuts_modal.return_back_to_the_list', | |||
}, | |||
], | |||
subTitle: 'keyboard_shortcuts_modal.rules_page', | |||
}, | |||
]; | |||
function renderSection() { | |||
return SECTIONS.map((section) => ( | |||
<div key={section.subTitle} className="sw-mb-4"> | |||
<SubTitle>{translate(section.subTitle)}</SubTitle> | |||
<Table columnCount={2} columnWidths={['30%', '70%']}> | |||
{section.rows.map((row) => ( | |||
<TableRow key={row.command}> | |||
<ContentCell className="sw-justify-center"> | |||
<KeyboardHint command={row.command} title="" /> | |||
</ContentCell> | |||
<ContentCell>{translate(row.description)}</ContentCell> | |||
</TableRow> | |||
))} | |||
</Table> | |||
</div> | |||
)); | |||
} | |||
export default function KeyboardShortcutsModal() { | |||
@@ -158,31 +191,29 @@ export default function KeyboardShortcutsModal() { | |||
return null; | |||
} | |||
const title = translate('keyboard_shortcuts.title'); | |||
const title = translate('keyboard_shortcuts_modal.title'); | |||
const body = ( | |||
<> | |||
<Link | |||
to="/account" | |||
onClick={() => { | |||
setDisplay(false); | |||
return true; | |||
}} | |||
> | |||
{translate('keyboard_shortcuts_modal.disable_link')} | |||
</Link> | |||
<div className="sw-mt-4">{renderSection()}</div> | |||
</> | |||
); | |||
return ( | |||
<Modal contentLabel={title} onRequestClose={() => setDisplay(false)} size="medium"> | |||
<div className="modal-head display-flex-space-between"> | |||
<h2>{title}</h2> | |||
<Link | |||
to="/account" | |||
onClick={() => { | |||
setDisplay(false); | |||
return true; | |||
}} | |||
> | |||
{translate('keyboard_shortcuts.disable_link')} | |||
</Link> | |||
</div> | |||
<div className="modal-body modal-container markdown display-flex-start shortcuts-modal"> | |||
<div className="flex-1">{renderShortcuts(CATEGORIES.left)}</div> | |||
<div className="flex-1 huge-spacer-left">{renderShortcuts(CATEGORIES.right)}</div> | |||
</div> | |||
<div className="modal-foot"> | |||
<Button onClick={() => setDisplay(false)}>{translate('close')}</Button> | |||
</div> | |||
</Modal> | |||
<Modal | |||
headerTitle={title} | |||
onClose={() => setDisplay(false)} | |||
body={body} | |||
secondaryButtonLabel={translate('close')} | |||
/> | |||
); | |||
} |
@@ -69,7 +69,7 @@ function renderKeyboardShortcutsModal() { | |||
} | |||
const ui = { | |||
modalTitle: byRole('heading', { name: 'keyboard_shortcuts.title' }), | |||
modalTitle: byRole('heading', { name: 'keyboard_shortcuts_modal.title' }), | |||
closeButton: byRole('button', { name: 'close' }), | |||
textInput: byRole('textbox'), |
@@ -3454,40 +3454,32 @@ formatting.example.link.example=[link label](https://www.domain.com) | |||
# KEYBOARD SHORTCUTS | |||
# | |||
#------------------------------------------------------------------------------ | |||
keyboard_shortcuts.title=Keyboard Shortcuts | |||
keyboard_shortcuts.disable_link=Disable shortcuts | |||
keyboard_shortcuts.shortcut=Shortcut | |||
keyboard_shortcuts.action=Action | |||
keyboard_shortcuts.global.title=Global | |||
keyboard_shortcuts.global.search=Open the search bar | |||
keyboard_shortcuts.global.open_shortcuts=Open this panel | |||
keyboard_shortcuts.code_page.title=Code Page | |||
keyboard_shortcuts.code_page.select_files=Select files | |||
keyboard_shortcuts.code_page.open_file=Open the selected file | |||
keyboard_shortcuts.code_page.back=Return back to the list | |||
keyboard_shortcuts.issues_page.title=Issues Page | |||
keyboard_shortcuts.issues_page.navigate=navigate between issues | |||
keyboard_shortcuts.issues_page.source_code=go from the list of issues to the source code | |||
keyboard_shortcuts.issues_page.back=return back to the list | |||
keyboard_shortcuts.issues_page.navigate_locations=to navigate issue locations | |||
keyboard_shortcuts.issues_page.switch_flows=to switch flows | |||
keyboard_shortcuts.issues_page.transition=do an issue transition | |||
keyboard_shortcuts.issues_page.assign=assign issue | |||
keyboard_shortcuts.issues_page.assign_to_me=assign issue to the current user | |||
keyboard_shortcuts.issues_page.severity=change severity of issue | |||
keyboard_shortcuts.issues_page.comment=comment issue | |||
keyboard_shortcuts.issues_page.submit_comment=submit comment | |||
keyboard_shortcuts.issues_page.tags=change tags of issue | |||
keyboard_shortcuts.measures_page.title=Measures Page | |||
keyboard_shortcuts.measures_page.select_files=Select files | |||
keyboard_shortcuts.measures_page.open_file=Open the selected file | |||
keyboard_shortcuts.measures_page.back=Return back to the list | |||
keyboard_shortcuts.rules_page.title=Rules Page | |||
keyboard_shortcuts.rules_page.navigate=navigate between rules | |||
keyboard_shortcuts.rules_page.rule_details=go from the list of rules to the rule details | |||
keyboard_shortcuts.rules_page.back=Return back to the list | |||
keyboard_shortcuts_modal.title=Keyboard Shortcuts | |||
keyboard_shortcuts_modal.disable_link=Disable shortcuts | |||
keyboard_shortcuts_modal.description= You can use the following shortcuts when navigating within SonarCloud | |||
keyboard_shortcuts_modal.global= Global | |||
keyboard_shortcuts_modal.global.open_search_bar= Open search bar | |||
keyboard_shortcuts_modal.global.open_keyboard_shortcuts_modal= Open keyboard shortcuts modal | |||
keyboard_shortcuts_modal.navigate_between_issues= Navigate between issues | |||
keyboard_shortcuts_modal.open_issue= Open issue | |||
keyboard_shortcuts_modal.return_back_to_the_list= Return back to the list | |||
keyboard_shortcuts_modal.do_issue_transition= Do an issue transition | |||
keyboard_shortcuts_modal.assign_issue= Assign issue | |||
keyboard_shortcuts_modal.assign_issue_to_me= Assign issue to me | |||
keyboard_shortcuts_modal.change_tags_of_issue= Change tags of issue | |||
keyboard_shortcuts_modal.select_an_issue= Select an issue | |||
keyboard_shortcuts_modal.issues_page= Issues page | |||
keyboard_shortcuts_modal.issue_details_page.navigate_issue_locations= To navigate issue locations | |||
keyboard_shortcuts_modal.issue_details_page.switch_flows= To switch flows | |||
keyboard_shortcuts_modal.issue_details_page.comment_an_issue= Comment an issue | |||
keyboard_shortcuts_modal.issue_details_page.submit_comment= Submit comment | |||
keyboard_shortcuts_modal.code_page= Code page | |||
keyboard_shortcuts_modal.code_page.select_files= Select files | |||
keyboard_shortcuts_modal.code_page.open_file= Open file | |||
keyboard_shortcuts_modal.measures_page= Measures page | |||
keyboard_shortcuts_modal.rules_page= Rules page | |||
keyboard_shortcuts_modal.rules_page.navigate_between_rule= Navigate between rules | |||
keyboard_shortcuts_modal.rules_page.open_rule= Open rule | |||
#------------------------------------------------------------------------------ | |||
# |