Skip to content

Commit

Permalink
chore: localize the extension (#478)
Browse files Browse the repository at this point in the history
  • Loading branch information
connor4312 authored Feb 1, 2024
1 parent 92a5082 commit e8335bc
Show file tree
Hide file tree
Showing 18 changed files with 257 additions and 137 deletions.
1 change: 1 addition & 0 deletions build/pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ parameters:
extends:
template: azure-pipelines/extension/stable.yml@templates
parameters:
l10nSourcePaths: ./src
buildSteps:
- script: npm ci
displayName: Install dependencies
Expand Down
13 changes: 7 additions & 6 deletions media/editor/copyPaste.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { MessageType, PasteMode } from "../../shared/protocol";
import _style from "./copyPaste.css";
import { useUniqueId } from "./hooks";
import { messageHandler } from "./state";
import { strings } from "./strings";
import { throwOnUndefinedAccessInDev } from "./util";
import { VsButton, VsWidgetPopover } from "./vscodeUi";

Expand Down Expand Up @@ -113,7 +114,7 @@ export const PastePopup: React.FC<{

return <VsWidgetPopover anchor={context?.target || null} hide={hide} visible={!!context}>
<div className={style.radioList}>
<span>Paste as:</span>
<span>{strings.pasteAs}:</span>
{encodings.map(e => <EncodingOption
key={e}
value={e}
Expand All @@ -124,15 +125,15 @@ export const PastePopup: React.FC<{
)}
</div>
<div className={style.radioList}>
<span>Paste mode:</span>
<InsertionOption label="Replace" checked={mode == PasteMode.Replace} value={PasteMode.Replace} onChecked={setMode} />
<InsertionOption label="Insert" checked={mode == PasteMode.Insert} value={PasteMode.Insert} onChecked={setMode} />
<span>{strings.pasteMode}:</span>
<InsertionOption label={strings.replace} checked={mode == PasteMode.Replace} value={PasteMode.Replace} onChecked={setMode} />
<InsertionOption label={strings.insert} checked={mode == PasteMode.Insert} value={PasteMode.Insert} onChecked={setMode} />
</div>
<div className={style.buttonWrap}>
<VsButton disabled={!decodedValid} onClick={doReplace}>
{decodedValid
? <>{mode === PasteMode.Replace ? "Replace" : "Insert"} {decoded.length} bytes</>
: "Encoding Error"}
? <>{mode === PasteMode.Replace ? strings.replace : strings.insert} {decoded.length} {strings.bytes}</>
: strings.encodingError}
</VsButton>
</div>
</VsWidgetPopover>;
Expand Down
7 changes: 4 additions & 3 deletions media/editor/dataDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { FocusedElement, dataCellCls, useDisplayContext, useIsFocused, useIsHove
import { DataInspectorAside } from "./dataInspector";
import { useGlobalHandler, useLastAsyncRecoilValue } from "./hooks";
import * as select from "./state";
import { strings } from "./strings";
import { clamp, clsx, getAsciiCharacter, getScrollDimensions, throwOnUndefinedAccessInDev } from "./util";

const style = throwOnUndefinedAccessInDev(_style);
Expand Down Expand Up @@ -59,7 +60,7 @@ export const DataHeader: React.FC = () => {
// Calculated decoded width so that the Data Inspector is displayed at the right position
// Flex-shrink prevents the data inspector overlapping on narrow screens
<DataCellGroup style={{ width: `calc(var(--cell-size) * ${editorSettings.columnWidth * textCellWidth})`, flexShrink: 0 }}>
Decoded Text
{strings.decodedText}
</DataCellGroup>
)}
{inspectorLocation === InspectorLocation.Aside && <DataInspector />}
Expand Down Expand Up @@ -294,7 +295,7 @@ const DataRows: React.FC = () => {

const LoadingDataRow: React.FC<{ width: number; showDecodedText: boolean }> = ({ width, showDecodedText }) => {
const cells: React.ReactNode[] = [];
const text = "LOADING";
const text = strings.loadingUpper;
for (let i = 0; i < width; i++) {
const str = (text[i * 2] || ".") + (text[i * 2 + 1] || ".");
cells.push(<span
Expand Down Expand Up @@ -458,7 +459,7 @@ const DataCell: React.FC<{
return;
}

if (e.key === "Backspace" || e.key === "Delete") {
if (e.key === "Delete") {
// this is a bit of a hack, but this is kind of tricky: we got a delete
// for a range, and the edit must be undoable, but we aren't ensured to
// have the data paged in for the range. So make a separate request
Expand Down
5 changes: 3 additions & 2 deletions media/editor/dataInspector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import _style from "./dataInspector.css";
import { inspectableTypes } from "./dataInspectorProperties";
import { useFileBytes, usePersistedState } from "./hooks";
import * as select from "./state";
import { strings } from "./strings";
import { throwOnUndefinedAccessInDev } from "./util";
import { VsTooltipPopover } from "./vscodeUi";

Expand Down Expand Up @@ -42,7 +43,7 @@ export const DataInspectorHover: React.FC = () => {
return <VsTooltipPopover
anchor={anchor}
hide={() => setInspected(undefined)} visible={true}>
<Suspense fallback="Loading...">
<Suspense fallback={strings.loadingDotDotDot}>
<InspectorContents columns={4} offset={inspected.byte} />
</Suspense>
</VsTooltipPopover>;
Expand Down Expand Up @@ -113,6 +114,6 @@ const EndiannessToggle: React.FC<{
checked={endianness === Endianness.Little}
onChange={evt => setEndianness(evt.target.checked ? Endianness.Little : Endianness.Big)}
/>
<label htmlFor="endian-checkbox">Little Endian</label>
<label htmlFor="endian-checkbox">{strings.littleEndian}</label>
</div>
);
36 changes: 19 additions & 17 deletions media/editor/findWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,13 @@ import React, { useCallback, useEffect, useRef, useState } from "react";
import { useRecoilState, useRecoilValue } from "recoil";
import { HexDocumentEditOp, HexDocumentReplaceEdit } from "../../shared/hexDocumentModel";
import { LiteralSearchQuery, MessageType, SearchRequestMessage, SearchResult, SearchResultsWithProgress } from "../../shared/protocol";
import { placeholder1 } from "../../shared/strings";
import { Range } from "../../shared/util/range";
import { FocusedElement, dataCellCls, useDisplayContext } from "./dataDisplayContext";
import _style from "./findWidget.css";
import { usePersistedState } from "./hooks";
import * as select from "./state";
import { strings } from "./strings";
import { clsx, hexDecode, isHexString, parseHexDigit, throwOnUndefinedAccessInDev } from "./util";
import { VsIconButton, VsIconCheckbox, VsProgressIndicator, VsTextFieldGroup } from "./vscodeUi";

Expand Down Expand Up @@ -71,15 +73,15 @@ const getReplaceOrError = (replace: string, isBinaryMode: boolean) => {
if (isBinaryMode) {
return isHexString(replace)
? hexDecode(replace)
: "Only hexadecimal characters (0-9 and a-f) are allowed";
: strings.onlyHexChars;
}

return new TextEncoder().encode(replace);
};

const getSearchQueryOrError = (query: string, isBinaryMode: boolean, isRegexp: boolean): SearchRequestMessage["query"] | string => {
if (isBinaryMode) {
return parseHexStringWithPlaceholders(query) || "Only hexadecimal characters (0-9, a-f, and ?? placeholders) are allowed";
return parseHexStringWithPlaceholders(query) || strings.onlyHexCharsAndPlaceholders;
}

if (isRegexp) {
Expand Down Expand Up @@ -322,33 +324,33 @@ export const FindWidget: React.FC = () => {
buttons={3}
ref={textFieldRef}
outerClassName={style.textField}
placeholder={isBinaryMode ? "Find Bytes (hex)" : "Find Text"}
placeholder={isBinaryMode ? strings.findBytes : strings.findText}
value={query}
onChange={onQueryChange}
onKeyDown={onFindKeyDown}
error={typeof queryOrError === "string" ? queryOrError : undefined}
>
{!isBinaryMode && <VsIconCheckbox checked={isRegexp} onToggle={setIsRegexp} title="Regular Expression Search">
{!isBinaryMode && <VsIconCheckbox checked={isRegexp} onToggle={setIsRegexp} title={strings.regexSearch}>
<RegexIcon />
</VsIconCheckbox>}
<VsIconCheckbox checked={isBinaryMode} onToggle={setIsBinaryMode} title="Search in Binary Mode">
<VsIconCheckbox checked={isBinaryMode} onToggle={setIsBinaryMode} title={strings.searchInBinaryMode}>
<BinaryFile />
</VsIconCheckbox>
<VsIconCheckbox checked={isCaseSensitive} onToggle={setIsCaseSensitive} title="Case Sensitive">
<VsIconCheckbox checked={isCaseSensitive} onToggle={setIsCaseSensitive} title={strings.caseSensitive}>
<CaseSensitive />
</VsIconCheckbox>
</VsTextFieldGroup>
<ResultBadge onUncap={() => setUncapped(true)} results={results} selectedResult={selectedResult} />
<VsIconButton title="Cancel Search" disabled={results.progress === 1} onClick={stopSearch}>
<VsIconButton title={strings.cancelSearch} disabled={results.progress === 1} onClick={stopSearch}>
<SearchStop />
</VsIconButton>
<VsIconButton disabled={results.results.length === 0} onClick={() => navigateResults(-1)} title="Previous Match">
<VsIconButton disabled={results.results.length === 0} onClick={() => navigateResults(-1)} title={strings.previousMatch}>
<ArrowUp />
</VsIconButton>
<VsIconButton disabled={results.results.length === 0} onClick={() => navigateResults(1)} title="Next Match">
<VsIconButton disabled={results.results.length === 0} onClick={() => navigateResults(1)} title={strings.nextMatch}>
<ArrowDown />
</VsIconButton>
<VsIconButton title="Close Widget (Esc)" onClick={closeWidget}>
<VsIconButton title={strings.closeWidget} onClick={closeWidget}>
<Close />
</VsIconButton>
</div>
Expand All @@ -359,13 +361,13 @@ export const FindWidget: React.FC = () => {
value={replace}
onChange={onReplaceChange}
onKeyDown={onReplaceKeyDown}
placeholder="Replace"
placeholder={strings.replace}
error={typeof replaceOrError === "string" ? replaceOrError : undefined}
/>
<VsIconButton disabled={typeof replaceOrError === "string" || selectedResult === undefined} onClick={replaceSelected} title="Replace Selected Match">
<VsIconButton disabled={typeof replaceOrError === "string" || selectedResult === undefined} onClick={replaceSelected} title={strings.replaceSelectedMatch}>
<Replace />
</VsIconButton>
<VsIconButton disabled={typeof replaceOrError === "string" || results.progress < 1 || !results.results.length} onClick={replaceAll} title="Replace All Matches">
<VsIconButton disabled={typeof replaceOrError === "string" || results.progress < 1 || !results.results.length} onClick={replaceAll} title={strings.replaceAllMatches}>
<ReplaceAll />
</VsIconButton>
</div>}
Expand All @@ -381,14 +383,14 @@ const ResultBadge: React.FC<{
}> = ({ results, selectedResult, onUncap }) => {
const resultCountStr = resultCountFormat.format(results.results.length);
const resultCountComponent = results.capped
? <a role="button" title={`More than ${results.results.length} results, click to find all`} onClick={onUncap}>{resultCountStr}+</a>
: <span title={`${results.results.length} results`}>{resultCountStr}</span>;
? <a role="button" title={strings.resultOverflow.replace(placeholder1, results.results.length.toString())} onClick={onUncap}>{resultCountStr}+</a>
: <span title={strings.resultCount.replace(placeholder1, results.results.length.toString())}>{resultCountStr}</span>;

return <div className={style.resultBadge}>
{results.progress < 1
? `Found ${resultCountStr}...`
? strings.foundNResults.replace(placeholder1, resultCountStr)
: !results.results.length
? "No results"
? strings.noResults
: selectedResult !== undefined
? <>{selectedFormat.format(selectedResult + 1)} of {resultCountComponent}</>
: <>{resultCountComponent} results</>}
Expand Down
3 changes: 2 additions & 1 deletion media/editor/hexEdit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { ReadonlyWarning } from "./readonlyWarning";
import { ScrollContainer } from "./scrollContainer";
import { SettingsGear } from "./settings";
import * as select from "./state";
import { strings } from "./strings";
import { throwOnUndefinedAccessInDev } from "./util";
import { VsProgressIndicator } from "./vscodeUi";

Expand Down Expand Up @@ -51,7 +52,7 @@ const Editor: React.FC = () => {

if (isLargeFile && !bypassLargeFilePrompt) {
return <div>
<p>Opening this large file may cause instability. <a id="open-anyway" role="button" onClick={() => setBypassLargeFile(true)}>Open anyways</a></p>
<p>{strings.openLargeFileWarning} <a id="open-anyway" role="button" onClick={() => setBypassLargeFile(true)}>{strings.openAnyways}</a></p>
</div>;
}

Expand Down
3 changes: 2 additions & 1 deletion media/editor/readonlyWarning.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { useCallback, useEffect } from "react";
import { useRecoilState } from "recoil";
import * as select from "./state";
import { strings } from "./strings";
import { VsTooltipPopover } from "./vscodeUi";

export const ReadonlyWarning: React.FC = () => {
Expand All @@ -17,6 +18,6 @@ export const ReadonlyWarning: React.FC = () => {
});

return <VsTooltipPopover anchor={anchor} hide={hide} visible={!!anchor}>
Cannot edit in read-only editor
{strings.readonlyWarning}
</VsTooltipPopover>;
};
7 changes: 4 additions & 3 deletions media/editor/settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React, { useState } from "react";
import { useRecoilState } from "recoil";
import _style from "./settings.css";
import * as select from "./state";
import { strings } from "./strings";
import { throwOnUndefinedAccessInDev } from "./util";
import { VsIconButton, VsTextField, VsWidgetPopover } from "./vscodeUi";

Expand All @@ -14,7 +15,7 @@ export const SettingsGear: React.FC = () => {

return (
<>
<VsIconButton title="Open Settings" className={style.gear} onClick={() => setIsOpen(!isOpen)} ref={setAnchor}>
<VsIconButton title={strings.openSettings} className={style.gear} onClick={() => setIsOpen(!isOpen)} ref={setAnchor}>
<SettingsGearIcon />
</VsIconButton>
<VsWidgetPopover anchor={anchor} hide={() => setIsOpen(false)} visible={isOpen}>
Expand All @@ -34,7 +35,7 @@ const TextCheckbox: React.FC = () => {

return (
<>
<label htmlFor="text-checkbox">Show Decoded Text</label>
<label htmlFor="text-checkbox">{strings.showDecodedText}</label>
<input
type="checkbox"
id="text-checkbox"
Expand All @@ -58,7 +59,7 @@ const ColumnWidth: React.FC = () => {

return (
<>
<label htmlFor="column-width">Bytes per Row</label>
<label htmlFor="column-width">{strings.bytesPerRow}</label>
<VsTextField
type="number"
id="column-width"
Expand Down
9 changes: 9 additions & 0 deletions media/editor/strings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/

import { ILocalizedStrings } from "../../shared/strings";

declare const LOC_STRINGS: ILocalizedStrings;

export const strings = LOC_STRINGS;
Loading

0 comments on commit e8335bc

Please sign in to comment.