From d8966eae0c38f8d168facb51769930cabf98440f Mon Sep 17 00:00:00 2001 From: Ewan Harris Date: Wed, 21 Jun 2023 18:51:58 +0100 Subject: [PATCH 1/7] chore: move commands to l10n --- src/commands/alloyGenerate.ts | 16 ++++++++-------- src/commands/buildApp.ts | 4 ++-- src/commands/buildModule.ts | 4 ++-- src/commands/clean.ts | 4 ++-- src/commands/createKeystore.ts | 8 ++++---- src/commands/createModule.ts | 6 +++--- src/commands/generateTask.ts | 14 +++++++------- src/commands/index.ts | 24 ++++++++++++------------ src/commands/packageApp.ts | 4 ++-- src/commands/packageModule.ts | 4 ++-- 10 files changed, 44 insertions(+), 44 deletions(-) diff --git a/src/commands/alloyGenerate.ts b/src/commands/alloyGenerate.ts index bb407f4f3..a9d9a597d 100644 --- a/src/commands/alloyGenerate.ts +++ b/src/commands/alloyGenerate.ts @@ -1,7 +1,7 @@ import * as fs from 'fs-extra'; import * as path from 'path'; -import { window, workspace } from 'vscode'; +import { l10n, window, workspace } from 'vscode'; import { inputBox, quickPick } from '../quickpicks'; import { capitalizeFirstLetter } from '../utils'; import { UserCancellation } from './common'; @@ -57,7 +57,7 @@ export interface AlloyModelGenerateOptions { async function promptForDetails (type: AlloyComponentType, folder: AlloyComponentFolder, extension: AlloyComponentExtension): Promise<{ cwd: string; filePaths: string[]; name: string; type: AlloyComponentType }> { - const name = await inputBox({ prompt: `Enter the name for your ${type}` }); + const name = await inputBox({ prompt: l10n.t('Enter the name for your {0}', type) }); const { folder: workspaceFolder } = await promptForWorkspaceFolder(); const cwd = workspaceFolder.uri.fsPath; @@ -73,7 +73,7 @@ Promise<{ cwd: string; filePaths: string[]; name: string; type: AlloyComponentTy filePaths.push(mainFile); } if (await fs.pathExists(mainFile)) { - const shouldDelete = await quickPick([ { id: 'yes', label: 'Yes' }, { id: 'no', label: 'No' } ], { placeHolder: `${name} already exists. Overwrite it?` }); + const shouldDelete = await quickPick([ { id: 'yes', label: l10n.t('Yes') }, { id: 'no', label: l10n.t('No') } ], { placeHolder: l10n.t('{0} already exists. Overwrite it?') }); if (shouldDelete.id === 'no') { throw new UserCancellation(); } @@ -95,7 +95,7 @@ export async function generateComponent (type: Exclude { let name; try { const creationArgs = await promptForDetails(AlloyComponentType.Model, AlloyComponentFolder.Model, AlloyComponentExtension.Model); - const adapterType = await quickPick([ { id: 'properties', label: 'properties' }, { id: 'sql', label: 'sql' } ], { canPickMany: false, placeHolder: 'Which adapter type?' }); + const adapterType = await quickPick([ { id: 'properties', label: 'properties' }, { id: 'sql', label: 'sql' } ], { canPickMany: false, placeHolder: l10n.t('Which adapter type?') }); const cwd = creationArgs.cwd; const filePaths = creationArgs.filePaths; name = creationArgs.name; @@ -126,7 +126,7 @@ export async function generateModel (): Promise { name, force: true }); - const shouldOpen = await window.showInformationMessage(`${capitalizeFirstLetter(AlloyComponentType.Model)} ${name} created successfully`, { title: 'Open' }); + const shouldOpen = await window.showInformationMessage(l10n.t('{0} {1} created successfully', capitalizeFirstLetter(AlloyComponentType.Model), name), { title: l10n.t('Open') }); if (shouldOpen) { for (const file of filePaths) { const document = await workspace.openTextDocument(file); @@ -137,7 +137,7 @@ export async function generateModel (): Promise { if (error instanceof UserCancellation) { return; } - window.showErrorMessage(`Failed to create Alloy ${AlloyComponentType.Model} ${name}`); + window.showErrorMessage(l10n.t('Failed to create Alloy {0} {1}', AlloyComponentType.Model, name as string)); } } diff --git a/src/commands/buildApp.ts b/src/commands/buildApp.ts index 8657532aa..2655eeb24 100644 --- a/src/commands/buildApp.ts +++ b/src/commands/buildApp.ts @@ -77,8 +77,8 @@ export async function buildApplication (node?: DeviceNode | OSVerNode | Platform } catch (error) { if (error instanceof InteractionError) { await handleInteractionError(error); - const choice = await vscode.window.showErrorMessage('Build App failed', { title: 'Rerun' }); - if (choice?.title === 'Rerun') { + const choice = await vscode.window.showErrorMessage(vscode.l10n.t('Build App failed'), { id: 'rerun', title: vscode.l10n.t('Rerun') }); + if (choice?.id === 'rerun') { buildApplication(node); } } diff --git a/src/commands/buildModule.ts b/src/commands/buildModule.ts index 4becfdfd1..b63740b25 100644 --- a/src/commands/buildModule.ts +++ b/src/commands/buildModule.ts @@ -51,8 +51,8 @@ export async function buildModule (node?: DeviceNode | OSVerNode | PlatformNode } catch (error) { if (error instanceof InteractionError) { await handleInteractionError(error); - const choice = await vscode.window.showErrorMessage('Build Module failed.', { title: 'Rerun' }); - if (choice?.title === 'Rerun') { + const choice = await vscode.window.showErrorMessage(vscode.l10n.t('Build Module failed.'), { id: 'rerun', title: vscode.l10n.t('Rerun') }); + if (choice?.id === 'rerun') { buildModule(node); } } diff --git a/src/commands/clean.ts b/src/commands/clean.ts index 7a503ca15..312ddb1c3 100644 --- a/src/commands/clean.ts +++ b/src/commands/clean.ts @@ -1,5 +1,5 @@ import * as path from 'path'; -import { ProgressLocation, window } from 'vscode'; +import { ProgressLocation, l10n, window } from 'vscode'; import * as fs from 'fs-extra'; import { ExtensionContainer } from '../container'; import { selectPlatform, promptForWorkspaceFolder } from '../quickpicks/common'; @@ -20,7 +20,7 @@ export async function cleanApplication (): Promise { } else { projectDir = folder.uri.fsPath; } - await window.withProgress({ cancellable: false, location: ProgressLocation.Notification, title: 'Cleaning project' }, async () => { + await window.withProgress({ cancellable: false, location: ProgressLocation.Notification, title: l10n.t('Cleaning project') }, async () => { const quotedArgs = [ 'clean', '--project-dir', projectDir, diff --git a/src/commands/createKeystore.ts b/src/commands/createKeystore.ts index 43c20bb7d..338c6664d 100644 --- a/src/commands/createKeystore.ts +++ b/src/commands/createKeystore.ts @@ -34,7 +34,7 @@ export async function createKeystore (): Promise { const choices = [ { id: 'browse', - label: 'Browse for location' + label: vscode.l10n.t('Browse for location') } ]; @@ -45,13 +45,13 @@ export async function createKeystore (): Promise { }); } - const choice = await quickPick(choices, { placeHolder: 'Select an open project to create the keystore in or browse for folder' }, { forceShow: true }); + const choice = await quickPick(choices, { placeHolder: vscode.l10n.t('Select an open project to create the keystore in or browse for folder') }, { forceShow: true }); if (choice.id === 'browse') { const selection = await vscode.window.showOpenDialog({ canSelectFolders: true, canSelectFiles: false, canSelectMany: false }); if (!selection) { - await vscode.window.showErrorMessage('No folder was selected'); + await vscode.window.showErrorMessage(vscode.l10n.t('No folder was selected')); return; } @@ -63,7 +63,7 @@ export async function createKeystore (): Promise { const keystorePath = path.join(folder, 'keystore'); if (await fs.pathExists(keystorePath)) { - vscode.window.showErrorMessage(`Keystore already exists at ${keystorePath}. Please delete it or choose a new location`); + vscode.window.showErrorMessage(vscode.l10n.t('Keystore already exists at {0}. Please delete it or choose a new location', keystorePath)); return reject(); } diff --git a/src/commands/createModule.ts b/src/commands/createModule.ts index 526df1dee..da26136be 100644 --- a/src/commands/createModule.ts +++ b/src/commands/createModule.ts @@ -1,7 +1,7 @@ import * as fs from 'fs-extra'; import * as path from 'path'; -import { commands, ProgressLocation, Uri, window, workspace } from 'vscode'; +import { commands, l10n, ProgressLocation, Uri, window, workspace } from 'vscode'; import { VSCodeCommands, WorkspaceState } from '../constants'; import { ExtensionContainer } from '../container'; import { inputBox, selectCodeBases, selectCreationLocation, selectPlatforms, yesNoQuestion } from '../quickpicks'; @@ -20,9 +20,9 @@ export async function createModule (): Promise { const logLevel = ExtensionContainer.config.general.logLevel; const lastCreationPath = ExtensionContainer.context.workspaceState.get(WorkspaceState.LastCreationPath); - const name = await inputBox({ prompt: 'Enter your module name' }); + const name = await inputBox({ prompt: l10n.t('Enter your module name') }); const id = await inputBox({ - prompt: 'Enter your module ID', + prompt: l10n.t('Enter your module ID'), validateInput: currentAppId => { const isValid = validateAppId(currentAppId); if (!isValid) { diff --git a/src/commands/generateTask.ts b/src/commands/generateTask.ts index cf2cf2523..b2b4e8f11 100644 --- a/src/commands/generateTask.ts +++ b/src/commands/generateTask.ts @@ -26,7 +26,7 @@ function isAppPackage (type: ProjectType, task: Partial { - const { type, folder } = await promptForWorkspaceFolder({ apps: true, modules: false, placeHolder: 'Select a project to generate a task definition for' }); + const { type, folder } = await promptForWorkspaceFolder({ apps: true, modules: false, placeHolder: vscode.l10n.t('Select a project to generate a task definition for') }); const tasksFileLocation = path.join(folder.uri.fsPath, '.vscode', 'tasks.json'); let fileContents; @@ -55,7 +55,7 @@ export async function generateTask (node: DeviceNode|DistributeNode): Promise { - const level = await quickPick([ 'Trace', 'Debug', 'Info', 'Warn', 'Error' ], { placeHolder: 'Select log level' }) as keyof typeof LogLevel; + const level = await quickPick([ 'Trace', 'Debug', 'Info', 'Warn', 'Error' ], { placeHolder: vscode.l10n.t('Select log level') }) as keyof typeof LogLevel; const actualLevel = LogLevel[level]; if (actualLevel) { await configuration.update('general.logLevel', actualLevel, vscode.ConfigurationTarget.Global); @@ -97,12 +97,12 @@ export function registerCommands (): void { registerCommand(Commands.EnableLiveView, async () => { await configuration.update('build.liveview', true, vscode.ConfigurationTarget.Global); - vscode.window.showInformationMessage('Enabled LiveView'); + vscode.window.showInformationMessage(vscode.l10n.t('Enabled LiveView')); }); registerCommand(Commands.DisableLiveView, async () => { await configuration.update('build.liveview', false, vscode.ConfigurationTarget.Global); - vscode.window.showInformationMessage('Disabled LiveView'); + vscode.window.showInformationMessage(vscode.l10n.t('Disabled LiveView')); }); registerCommand(Commands.GenerateAlloyController, () => generateComponent(AlloyComponentType.Controller, AlloyComponentFolder.Controller, AlloyComponentExtension.Controller)); @@ -137,7 +137,7 @@ export function registerCommands (): void { debugSessionInformation.set(DEBUG_SESSION_VALUE, node); - const { folder } = await promptForWorkspaceFolder({ apps: true, modules: true, placeHolder: 'Please select a project to debug' }); + const { folder } = await promptForWorkspaceFolder({ apps: true, modules: true, placeHolder: vscode.l10n.t('Please select a project to debug') }); await vscode.debug.startDebugging(folder, debugConfig); }); @@ -150,19 +150,19 @@ export function registerCommands (): void { } ExtensionContainer.context.globalState.update(GlobalState.HasUpdates, true); vscode.commands.executeCommand('setContext', GlobalState.HasUpdates, true); - const message = numberOfUpdates > 1 ? `There are ${numberOfUpdates} updates available` : `There is ${numberOfUpdates} update available`; - const choice = await vscode.window.showInformationMessage(message, { title: 'Install' }, { title: 'View' }); + const message = numberOfUpdates > 1 ? vscode.l10n.t('There are {0} updates available', numberOfUpdates) : vscode.l10n.t('There is {0} update available', numberOfUpdates); + const choice = await vscode.window.showInformationMessage(message, { id: 'install', title: vscode.l10n.t('Install') }, { id: 'view', title: vscode.l10n.t('View') }); if (!choice) { return; } - if (choice.title === 'Install') { + if (choice.title === 'install') { vscode.commands.executeCommand(Commands.SelectUpdates, updateInfo); - } else if (choice.title === 'View') { + } else if (choice.title === 'view') { // Focus the update view await vscode.commands.executeCommand(Commands.ShowUpdates); } } catch (error) { - vscode.window.showWarningMessage('Failed to check for updates'); + vscode.window.showWarningMessage(vscode.l10n.t('Failed to check for updates')); } }); @@ -189,7 +189,7 @@ export function registerCommands (): void { registerCommand(Commands.ImportSettings, async (settings?: { [key: string]: unknown }): Promise => { if (!settings) { - const openFile = await vscode.window.showInformationMessage('Please select the exported settings file', 'Open'); + const openFile = await vscode.window.showInformationMessage(vscode.l10n.t('Please select the exported settings file'), 'Open'); if (!openFile) { return; diff --git a/src/commands/packageApp.ts b/src/commands/packageApp.ts index c67758b14..ac006a692 100644 --- a/src/commands/packageApp.ts +++ b/src/commands/packageApp.ts @@ -74,8 +74,8 @@ export async function packageApplication (node?: PlatformNode | DistributeNode, } catch (error) { if (error instanceof InteractionError) { await handleInteractionError(error); - const choice = await vscode.window.showErrorMessage('Package App failed', { title: 'Rerun' }); - if (choice?.title === 'Rerun') { + const choice = await vscode.window.showErrorMessage(vscode.l10n.t('Package App failed'), { id: 'rerun', title: vscode.l10n.t('Rerun') }); + if (choice?.id === 'rerun') { packageApplication(node); } } diff --git a/src/commands/packageModule.ts b/src/commands/packageModule.ts index 994aaec99..de3d4cc72 100644 --- a/src/commands/packageModule.ts +++ b/src/commands/packageModule.ts @@ -39,8 +39,8 @@ export async function packageModule (node: DeviceNode | OSVerNode | PlatformNode } catch (error) { if (error instanceof InteractionError) { await handleInteractionError(error); - const choice = await vscode.window.showErrorMessage('Package Module failed', { title: 'Rerun' }); - if (choice?.title === 'Rerun') { + const choice = await vscode.window.showErrorMessage(vscode.l10n.t('Package Module failed'), { id: 'rerun', title: vscode.l10n.t('Rerun') }); + if (choice?.title === 'rerun') { packageModule(node); } } From 57f65148713e73b391ea405ccf7a0922cf23b676 Mon Sep 17 00:00:00 2001 From: Ewan Harris Date: Wed, 21 Jun 2023 21:01:58 +0100 Subject: [PATCH 2/7] chore: move providers to l10n --- src/providers/code-action/viewCodeActionProvider.ts | 2 +- src/providers/definition/common.ts | 10 +++++----- src/providers/hover/viewHoverProvider.ts | 2 +- src/providers/index.ts | 12 ++++++------ 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/providers/code-action/viewCodeActionProvider.ts b/src/providers/code-action/viewCodeActionProvider.ts index 87c66f62d..4df62f1cf 100644 --- a/src/providers/code-action/viewCodeActionProvider.ts +++ b/src/providers/code-action/viewCodeActionProvider.ts @@ -50,7 +50,7 @@ export class ViewCodeActionProvider extends BaseProvider implements vscode.CodeA } } else if (!definitions?.length && suggestion.i18nString) { codeActions.push({ - title: 'Generate i18n string', + title: vscode.l10n.t('Generate i18n string'), command: Commands.InsertI18nStringCommandId, arguments: [ word, project ] }); diff --git a/src/providers/definition/common.ts b/src/providers/definition/common.ts index aaa1e5730..4595ece2c 100644 --- a/src/providers/definition/common.ts +++ b/src/providers/definition/common.ts @@ -1,6 +1,6 @@ import * as path from 'path'; import * as related from '../../related'; -import { TextDocument } from 'vscode'; +import { TextDocument, l10n } from 'vscode'; import { ExtensionContainer } from '../../container'; import { Project } from '../../project'; @@ -36,7 +36,7 @@ export const viewSuggestions: DefinitionSuggestion[] = [ return new RegExp(`["']\\.${text}["'[]`, 'g'); }, title (fileName: string): string { - return `Generate style (${fileName})`; + return l10n.t('Generate style ({0})', fileName); }, insertText (text: string): string { // eslint-disable-next-line no-template-curly-in-string @@ -55,7 +55,7 @@ export const viewSuggestions: DefinitionSuggestion[] = [ return new RegExp(`["']#${text}["'[]`, 'g'); }, title (fileName: string): string { - return `Generate style (${fileName})`; + return l10n.t('Generate style ({0})', fileName); }, insertText (text: string): string { // eslint-disable-next-line no-template-curly-in-string @@ -74,7 +74,7 @@ export const viewSuggestions: DefinitionSuggestion[] = [ return new RegExp(`["']${text}`, 'g'); }, title (fileName: string): string { - return `Generate style (${fileName})`; + return l10n.t('Generate style ({0})', fileName); }, insertText (text: string): string|undefined { if ([ 'Alloy', 'Annotation', 'Collection', 'Menu', 'Model', 'Require', 'Widget' ].indexOf(text) !== -1 @@ -97,7 +97,7 @@ export const viewSuggestions: DefinitionSuggestion[] = [ return new RegExp(`(?:function ${text}\\s*?\\(|(?:var|let|const)\\s*?${text}\\s*?=\\s*?\\()`); }, title (fileName: string): string { - return `Generate function (${fileName})`; + return l10n.t('Generate function ({0})', fileName); }, insertText (text: string): string { // eslint-disable-next-line no-template-curly-in-string diff --git a/src/providers/hover/viewHoverProvider.ts b/src/providers/hover/viewHoverProvider.ts index b7a052518..0a31716cc 100644 --- a/src/providers/hover/viewHoverProvider.ts +++ b/src/providers/hover/viewHoverProvider.ts @@ -51,7 +51,7 @@ export class ViewHoverProvider extends BaseProvider implements vscode.HoverProvi filter: item => item.stats.isDirectory() || fileNameRegExp.test(item.path) }); let imageFile; - let imageString = 'Image not found'; + let imageString = vscode.l10n.t('Image not found'); if (files.length > 0) { imageFile = files[0]; imageString = `![${imageFile.path}](${imageFile.path}|height=100)`; diff --git a/src/providers/index.ts b/src/providers/index.ts index 6ef1bd383..07c6e2618 100644 --- a/src/providers/index.ts +++ b/src/providers/index.ts @@ -105,9 +105,9 @@ export async function generateCompletions (force = false, project: Project): Pro try { sdkVersion = project.sdk(); if (!sdkVersion) { - const error = new InteractionError('Errors found in tiapp.xml: no sdk-version found'); + const error = new InteractionError(vscode.l10n.t('Errors found in tiapp.xml: no sdk-version found')); error.interactionChoices.push({ - title: 'Open tiapp.xml', + title: vscode.l10n.t('Open tiapp.xml'), run: async () => { const file = path.join(project.filePath, 'tiapp.xml'); const document = await vscode.workspace.openTextDocument(file); @@ -116,9 +116,9 @@ export async function generateCompletions (force = false, project: Project): Pro }); throw error; } else if (sdkVersion.length > 1) { - const error = new InteractionError('Errors found in tiapp.xml: multiple sdk-version tags found.'); + const error = new InteractionError(vscode.l10n.t('Errors found in tiapp.xml: multiple sdk-version tags found.')); error.interactionChoices.push({ - title: 'Open tiapp.xml', + title: vscode.l10n.t('Open tiapp.xml'), run: async () => { const file = path.join(project.filePath, 'tiapp.xml'); const document = await vscode.workspace.openTextDocument(file); @@ -154,7 +154,7 @@ export async function generateCompletions (force = false, project: Project): Pro actions.push({ title: 'Install', run: () => { - vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: 'Titanium SDK Installation', cancellable: false }, async () => { + vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: vscode.l10n.t('Titanium SDK Installation'), cancellable: false }, async () => { try { await updates.titanium.sdk.installUpdate(sdkVersion as string); await ExtensionContainer.environment.getInfo(); @@ -167,7 +167,7 @@ export async function generateCompletions (force = false, project: Project): Pro }); } const message = error instanceof Error ? error.message : ''; - const install = await vscode.window.showErrorMessage(`Error generating autocomplete suggestions. ${message}`, ...actions); + const install = await vscode.window.showErrorMessage(vscode.l10n.t('Error generating autocomplete suggestions. {0}', message), ...actions); if (install) { await install.run(); } From 5f616bbd2ec6062f77baf7e39889a3ec1c0214e3 Mon Sep 17 00:00:00 2001 From: Ewan Harris Date: Wed, 21 Jun 2023 21:02:13 +0100 Subject: [PATCH 3/7] chore: move quickpicks to l10n --- src/quickpicks/build/android.ts | 32 ++++++++++++++++---------------- src/quickpicks/build/common.ts | 6 +++--- src/quickpicks/build/ios.ts | 21 +++++++++++---------- src/quickpicks/common.ts | 4 ++-- src/quickpicks/creation.ts | 4 ++-- 5 files changed, 34 insertions(+), 33 deletions(-) diff --git a/src/quickpicks/build/android.ts b/src/quickpicks/build/android.ts index 2b3b4f941..70eccee24 100644 --- a/src/quickpicks/build/android.ts +++ b/src/quickpicks/build/android.ts @@ -11,7 +11,7 @@ import { createKeystore } from '../../commands/createKeystore'; export function selectAndroidDevice (): Promise { const devices = ExtensionContainer.environment.androidDevices().map(({ id, name }: { id: string; name: string }) => ({ id, label: name, udid: id })); - return deviceQuickPick(devices, { placeHolder: 'Select Android device' }); + return deviceQuickPick(devices, { placeHolder: vscode.l10n.t('Select Android device') }); } export function selectAndroidEmulator (): Promise { @@ -34,33 +34,33 @@ export function selectAndroidEmulator (): Promise { }); } - return deviceQuickPick(options, { placeHolder: 'Select emulator' }); + return deviceQuickPick(options, { placeHolder: vscode.l10n.t('Select emulator') }); } export async function selectAndroidKeystore (workspaceFolder: vscode.WorkspaceFolder, lastUsed?: string, savedKeystorePath?: string): Promise { const items = [ { - label: 'Browse for keystore', + label: vscode.l10n.t('Browse for keystore'), id: 'browse' }, { - label: 'Create keystore', + label: vscode.l10n.t('Create keystore'), id: 'create' } ]; if (lastUsed) { items.push({ - label: `Last used ${lastUsed}`, + label: vscode.l10n.t('Last used {0}', lastUsed), id: 'last' }); } if (savedKeystorePath) { items.push({ - label: `Saved ${savedKeystorePath}`, + label: vscode.l10n.t('Saved {0}', savedKeystorePath), id: 'saved' }); } - const keystoreAction = await quickPick(items, { placeHolder: 'Browse, create, or use last keystore' }); + const keystoreAction = await quickPick(items, { placeHolder: vscode.l10n.t('Browse, create, or use last keystore') }); if (keystoreAction.id === 'browse') { const uri = await vscode.window.showOpenDialog({ canSelectFolders: false, canSelectMany: false }); if (!uri) { @@ -77,7 +77,7 @@ export async function selectAndroidKeystore (workspaceFolder: vscode.WorkspaceFo } else if (lastUsed) { return lastUsed; } else { - throw new Error('No keystore was selected'); + throw new Error(vscode.l10n.t('No keystore was selected')); } } @@ -101,7 +101,7 @@ async function resolveKeystorePath (keystorePath: string, folder: vscode.Workspa return resolvedPath; } - throw new Error(`Provided keystorePath value "${keystorePath}" does not exist`); + throw new Error(vscode.l10n.t('Provided keystorePath value "{0}" does not exist', keystorePath)); } /** @@ -141,14 +141,14 @@ export async function enterAndroidKeystoreInfo (workspaceFolder: vscode.Workspac if (storedInformation) { // eslint-disable-next-line promise/catch-or-return - vscode.window.showInformationMessage(`Using stored information for ${keystoreInfo.location}. If this is unexpected or your build errors, clear this information using the button below`, 'Delete Information') + vscode.window.showInformationMessage(vscode.l10n.t('Using stored information for {0}. If this is unexpected or your build errors, clear this information using the button below', keystoreInfo.location), vscode.l10n.t('Delete Information')) .then(async del => { if (del) { if (!keystoreInfo.location) { - return vscode.window.showErrorMessage('No keystore location was provided, so could not delete'); + return vscode.window.showErrorMessage(vscode.l10n.t('No keystore location was provided, so could not delete')); } await ExtensionContainer.context.secrets.delete(keystoreInfo.location); - await vscode.window.showInformationMessage(`Deleted stored information for ${keystoreInfo.location}`); + await vscode.window.showInformationMessage(vscode.l10n.t('Deleted stored information for {0}', keystoreInfo.location)); } return; }); @@ -157,19 +157,19 @@ export async function enterAndroidKeystoreInfo (workspaceFolder: vscode.Workspac } if (!keystoreInfo.alias) { - keystoreInfo.alias = await inputBox({ placeHolder: 'Enter your keystore alias', value: ExtensionContainer.config.android.keystoreAlias || '' }); + keystoreInfo.alias = await inputBox({ placeHolder: vscode.l10n.t('Enter your keystore alias'), value: ExtensionContainer.config.android.keystoreAlias || '' }); } if (!keystoreInfo.password) { - keystoreInfo.password = await enterPassword({ placeHolder: 'Enter your keystore password' }); + keystoreInfo.password = await enterPassword({ placeHolder: vscode.l10n.t('Enter your keystore password') }); } if (!keystoreInfo.privateKeyPassword) { - keystoreInfo.privateKeyPassword = await enterPassword({ placeHolder: 'Enter your keystore private key password (optional)' }); + keystoreInfo.privateKeyPassword = await enterPassword({ placeHolder: vscode.l10n.t('Enter your keystore private key password (optional)') }); } if (!storedInformation) { - const store = await yesNoQuestion({ placeHolder: 'Would you like to store this information?' }); + const store = await yesNoQuestion({ placeHolder: vscode.l10n.t('Would you like to store this information?') }); if (store) { ExtensionContainer.context.secrets.store(keystoreInfo.location, JSON.stringify(keystoreInfo)); diff --git a/src/quickpicks/build/common.ts b/src/quickpicks/build/common.ts index 5029fcdbb..f580f9b58 100644 --- a/src/quickpicks/build/common.ts +++ b/src/quickpicks/build/common.ts @@ -1,6 +1,6 @@ import * as utils from '../../utils'; import { Commands } from '../../commands/common'; -import { commands, QuickPickOptions } from 'vscode'; +import { commands, l10n, QuickPickOptions } from 'vscode'; import { quickPick, CustomQuickPick } from '../common'; import { selectAndroidDevice, selectAndroidEmulator } from './android'; import { selectiOSDevice, selectiOSSimulator } from './ios'; @@ -14,12 +14,12 @@ export interface DeviceQuickPickItem extends CustomQuickPick { export async function deviceQuickPick (deviceList: DeviceQuickPickItem[], quickPickOptions: QuickPickOptions): Promise { if (!deviceList.length) { - quickPickOptions.placeHolder = `${quickPickOptions.placeHolder}. None detected, refresh device information?`; + quickPickOptions.placeHolder = l10n.t('No devices detected, refresh device information?'); } deviceList.push({ id: 'refresh', - label: 'Refresh Devices', + label: l10n.t('Refresh Devices'), udid: 'refresh' }); return quickPick(deviceList, quickPickOptions, { forceShow: true }); diff --git a/src/quickpicks/build/ios.ts b/src/quickpicks/build/ios.ts index 8cdf010dc..ba484a5c3 100644 --- a/src/quickpicks/build/ios.ts +++ b/src/quickpicks/build/ios.ts @@ -3,21 +3,22 @@ import { Target } from '../..//types/cli'; import { IosCert, IosCertificateType, IosProvisioningType, ProvisioningProfile } from '../../types/common'; import { quickPick, CustomQuickPick } from '../common'; import { deviceQuickPick, DeviceQuickPickItem } from './common'; +import { l10n } from 'vscode'; export async function selectiOSCertificate (buildType: string): Promise { const certificateType: IosCertificateType = buildType === 'run' ? 'developer' : 'distribution'; const certificates = ExtensionContainer.environment.iOSCertificates(certificateType).map(cert => ({ - description: `Expires: ${new Date(cert.after).toLocaleString('en-US')}`, + description: l10n.t('Expires: {0}', new Date(cert.after).toLocaleString('en-US')), label: cert.fullname, pem: cert.pem, id: cert.fullname })); - const choice = await quickPick(certificates, { placeHolder: 'Select certificate' }); + const choice = await quickPick(certificates, { placeHolder: l10n.t('Select certificate') }); const certificate = ExtensionContainer.environment.iOSCertificates(certificateType).find(cert => cert.pem === choice.pem); if (!certificate) { - throw new Error(`Unable to resolve certificate ${choice.label}`); + throw new Error(l10n.t('Unable to resolve certificate {0}', choice.label)); } return certificate; @@ -33,17 +34,17 @@ export async function selectiOSProvisioningProfile (certificate: IosCert, target const profiles = ExtensionContainer.environment.iOSProvisioningProfiles(deployment, certificate, appId); const choices = profiles.map(({ expirationDate, name, uuid }) => ({ description: uuid, - detail: `Expires: ${new Date(expirationDate).toLocaleString('en-US')}`, + detail: l10n.t('Expires: {0}', new Date(expirationDate).toLocaleString('en-US')), label: name, uuid, id: uuid })); - const choice = await quickPick(choices, { placeHolder: 'Select provisioning profile' }); + const choice = await quickPick(choices, { placeHolder: l10n.t('Select provisioning profile') }); const profile = profiles.find(p => p.uuid === choice.uuid); if (!profile) { - throw new Error(`Unable to resolve provisioning profile ${choice.label}`); + throw new Error(l10n.t('Unable to resolve provisioning profile {0}', choice.label)); } return profile; @@ -51,12 +52,12 @@ export async function selectiOSProvisioningProfile (certificate: IosCert, target export function selectiOSDevice (): Promise { const devices = ExtensionContainer.environment.iOSDevices().map(device => ({ id: device.udid, label: device.name, udid: device.udid })); - return deviceQuickPick(devices, { placeHolder: 'Select device' }); + return deviceQuickPick(devices, { placeHolder: l10n.t('Select device') }); } export function selectiOSSimulatorVersion (): Promise { const versions = ExtensionContainer.environment.iOSSimulatorVersions().map(version => ({ id: version, label: version })); - return quickPick(versions, { placeHolder: 'Select simulator version' }); + return quickPick(versions, { placeHolder: l10n.t('Select simulator version') }); } export async function selectiOSSimulator (iOSVersion?: string): Promise { @@ -64,8 +65,8 @@ export async function selectiOSSimulator (iOSVersion?: string): Promise ({ label: `${name} (${iOSVersion})`, id: udid, udid, version: iOSVersion })); - return deviceQuickPick(simulators, { placeHolder: 'Select simulator' }); + return deviceQuickPick(simulators, { placeHolder: l10n.t('Select simulator') }); } diff --git a/src/quickpicks/common.ts b/src/quickpicks/common.ts index 6bdc153dc..c33bf8832 100644 --- a/src/quickpicks/common.ts +++ b/src/quickpicks/common.ts @@ -122,7 +122,7 @@ export async function selectCreationLocation (lastUsed?: string): Promise { } return Uri.file(defaultPath); } else if (directory.id === 'enter') { - const directory = await inputBox({ placeHolder: 'Enter your path' }); + const directory = await inputBox({ placeHolder: l10n.t('Enter your path') }); if (!await pathExists(directory)) { throw new Error(`${directory} does not exist`); } @@ -219,7 +219,7 @@ interface FolderDetails { * @param {Object} [options.modules=false] - Detect Titanium module projects * @returns {Promise} */ -export async function promptForWorkspaceFolder ({ apps = true, modules = false, placeHolder = 'Please select a folder to perform action within' }: WorkspaceFolderPromptOptions = {}): Promise { +export async function promptForWorkspaceFolder ({ apps = true, modules = false, placeHolder = l10n.t('Please select a folder to perform action within') }: WorkspaceFolderPromptOptions = {}): Promise { const folders = await getValidWorkspaceFolders({ apps, modules }); if (!folders.length) { throw new Error('No workspace folders are present'); diff --git a/src/quickpicks/creation.ts b/src/quickpicks/creation.ts index 4d25f06eb..5efe4c95d 100644 --- a/src/quickpicks/creation.ts +++ b/src/quickpicks/creation.ts @@ -47,11 +47,11 @@ export async function selectCodeBases(platforms: string[]): Promise([ { id: 'java', label: 'Java' }, { id: 'kotlin', label: 'Kotlin' } ], { canPickMany: false, placeHolder: 'Select Android codebase' })).id; + codeBases.android = (await quickPick([ { id: 'java', label: 'Java' }, { id: 'kotlin', label: 'Kotlin' } ], { canPickMany: false, placeHolder: l10n.t('Select Android codebase') })).id; } if (platforms.includes('ios')) { - codeBases.ios = (await quickPick([ { id: 'objc', label: 'Objective-C' }, { id: 'swift', label: 'Swift' } ], { canPickMany: false, placeHolder: 'Select iOS codebase' })).id; + codeBases.ios = (await quickPick([ { id: 'objc', label: 'Objective-C' }, { id: 'swift', label: 'Swift' } ], { canPickMany: false, placeHolder: l10n.t('Select iOS codebase') })).id; } From 0357d7fc2e8d7eb41961166f2b9f98a61c4c24e3 Mon Sep 17 00:00:00 2001 From: Ewan Harris Date: Wed, 21 Jun 2023 21:02:23 +0100 Subject: [PATCH 4/7] chore: move tasks to l10n --- src/tasks/buildTaskProvider.ts | 2 +- src/tasks/commandTaskProvider.ts | 8 ++++---- src/tasks/helpers/android.ts | 3 ++- src/tasks/helpers/base.ts | 18 +++++++++--------- src/tasks/helpers/ios.ts | 9 +++++---- src/tasks/packageTaskProvider.ts | 3 ++- src/tasks/taskPseudoTerminal.ts | 6 +++--- 7 files changed, 26 insertions(+), 23 deletions(-) diff --git a/src/tasks/buildTaskProvider.ts b/src/tasks/buildTaskProvider.ts index 4bdfffe06..9c8d2a7cc 100644 --- a/src/tasks/buildTaskProvider.ts +++ b/src/tasks/buildTaskProvider.ts @@ -157,7 +157,7 @@ export class BuildTaskProvider extends CommandTaskProvider { } return helper.resolveModuleBuildCommandLine(context, task.definition.titaniumBuild); } else { - throw new Error(`Unknown project type ${definition.titaniumBuild.projectType}`); + throw new Error(vscode.l10n.t('Unknown project type {0}', definition.titaniumBuild.projectType)); } } diff --git a/src/tasks/commandTaskProvider.ts b/src/tasks/commandTaskProvider.ts index 989849274..861742366 100644 --- a/src/tasks/commandTaskProvider.ts +++ b/src/tasks/commandTaskProvider.ts @@ -13,9 +13,9 @@ function getPlatform (task: TitaniumTaskBase): Platform { } else if (task.definition.titaniumBuild.platform === 'ios' || task.definition.titaniumBuild.ios !== undefined) { return 'ios'; } else if (task.definition.titaniumBuild.platform) { - throw new Error(`Unknown platform ${task.definition.titaniumBuild.platform}`); + throw new Error(vscode.l10n.t('Unknown platform {0}', task.definition.titaniumBuild.platform)); } else { - throw new Error('Invalid configuration, please specify a platform'); + throw new Error(vscode.l10n.t('Invalid configuration, please specify a platform')); } } @@ -68,13 +68,13 @@ export abstract class CommandTaskProvider implements vscode.TaskProvider { await this.executeTaskInternal(context, task); } catch (error) { - let message = 'Error running task'; + let message = vscode.l10n.t('Error running task'); if (error instanceof CommandError) { message = error.message; } else if (error instanceof InteractionError) { await handleInteractionError(error); } else if (error instanceof UserCancellation) { - context.terminal.writeWarningLine('Task cancelled as no selection occurred'); + context.terminal.writeWarningLine(vscode.l10n.t('Task cancelled as no selection occurred')); return 0; } else if (error instanceof Error) { message = `${message}\n${error.message}`; diff --git a/src/tasks/helpers/android.ts b/src/tasks/helpers/android.ts index 116466e18..4c5d796f5 100644 --- a/src/tasks/helpers/android.ts +++ b/src/tasks/helpers/android.ts @@ -7,6 +7,7 @@ import { AppBuildTaskTitaniumBuildBase, BuildTaskDefinitionBase, ModuleBuildTask import { AppPackageTaskTitaniumBuildBase, PackageTaskDefinitionBase, PackageTaskTitaniumBuildBase } from '../packageTaskProvider'; import { WorkspaceState } from '../../constants'; import { ExtensionContainer } from '../../container'; +import { l10n } from 'vscode'; export interface AndroidBuildTaskDefinition extends BuildTaskDefinitionBase { titaniumBuild: AndroidBuildTaskTitaniumBuildBase; @@ -38,7 +39,7 @@ export class AndroidHelper extends TaskHelper { if (definition.debug) { const port = definition.debugPort || ExtensionContainer.debugPorts.get(definition.projectDir); if (!port) { - throw new Error(`Failed to find debug port associated with ${definition.projectDir}. Please try setting a "port" property in the configuration.`); + throw new Error(l10n.t('Failed to find debug port associated with {0}. Please try setting a "port" property in the configuration.', definition.projectDir)); } builder.addOption('--debug-host', `/localhost:${port}`); } diff --git a/src/tasks/helpers/base.ts b/src/tasks/helpers/base.ts index 6eedab5c2..140ede69f 100644 --- a/src/tasks/helpers/base.ts +++ b/src/tasks/helpers/base.ts @@ -69,7 +69,7 @@ export abstract class TaskHelper { } if (!definition.target) { - throw new Error('No target provided'); + throw new Error(vscode.l10n.t('No "target" value provided')); } builder.addOption('--target', definition.target); @@ -92,7 +92,7 @@ export abstract class TaskHelper { } if (!definition.target) { - throw new Error('No target provided'); + throw new Error(vscode.l10n.t('No "target" value provided')); } builder.addOption('--target', definition.target); @@ -140,15 +140,15 @@ export abstract class TaskHelper { const defaultOutput = path.join(definition.projectDir, 'dist'); const defaultLabel = `Default: ${defaultOutput}`; - const options = [ defaultLabel, 'Browse' ]; + const options = [ defaultLabel, vscode.l10n.t('Browse') ]; if ((definition as AppPackageTaskTitaniumBuildBase).target === 'dist-appstore') { - options.push('Output Into Xcode'); + options.push(vscode.l10n.t('Output Into Xcode')); } const selected = await quickPick(options, { canPickMany: false, - placeHolder: 'Choose output location' + placeHolder: vscode.l10n.t('Choose output location') }, { forceShow: true }); @@ -164,7 +164,7 @@ export abstract class TaskHelper { definition.outputDirectory = defaultOutput; } } else if (!await fs.pathExists(definition.outputDirectory)) { - throw new Error(`Provided output directory ${definition.outputDirectory} cannot be found`); + throw new Error(vscode.l10n.t('Provided output directory {0} cannot be found', definition.outputDirectory)); } if (definition.outputDirectory) { builder.addQuotedOption('--output-dir', definition.outputDirectory); @@ -173,7 +173,7 @@ export abstract class TaskHelper { public async determineProjectType (directory: string, platform: string): Promise { if (!await fs.pathExists(directory)) { - throw new Error(`Project directory ${directory} does not exist`); + throw new Error(vscode.l10n.t('Project directory {0} does not exist', directory)); } if (await fs.pathExists(path.join(directory, 'tiapp.xml'))) { @@ -181,7 +181,7 @@ export abstract class TaskHelper { } else if (await fs.pathExists(path.join(directory, platform, 'timodule.xml'))) { return 'module'; } else { - throw new Error(`Unable to determine project type from ${directory}`); + throw new Error(vscode.l10n.t('Unable to determine project type from {0}', directory)); } } @@ -201,7 +201,7 @@ export abstract class TaskHelper { public getProject(projectDir: string): Project { const project = ExtensionContainer.projects.get(projectDir); if (!project) { - throw new Error(`Unable to find loaded project for ${projectDir}, please ensure it is active in the workspace`); + throw new Error(vscode.l10n.t('Unable to find loaded project for {0}, please ensure it is active in the workspace', projectDir)); } return project; } diff --git a/src/tasks/helpers/ios.ts b/src/tasks/helpers/ios.ts index ea795ae53..177aa7608 100644 --- a/src/tasks/helpers/ios.ts +++ b/src/tasks/helpers/ios.ts @@ -9,6 +9,7 @@ import { AppPackageTaskTitaniumBuildBase, PackageTaskDefinitionBase, PackageTask import { WorkspaceState } from '../../constants'; import { ExtensionContainer } from '../../container'; +import { l10n } from 'vscode'; export interface IosTitaniumBuildDefinition extends BuildTaskDefinitionBase { titaniumBuild: IosBuildTaskTitaniumBuildBase; @@ -55,7 +56,7 @@ export class IosHelper extends TaskHelper { } if (!certificate) { - throw new Error(`Unable to find certificate ${iosInfo.certificate}`); + throw new Error(l10n.t('Unable to find certificate {0}', iosInfo.certificate as string)); } iosInfo.certificate = getCorrectCertificateName(certificate.fullname, project.sdk()[0], 'developer'); @@ -65,7 +66,7 @@ export class IosHelper extends TaskHelper { } if (!iosInfo.provisioningProfile) { - throw new Error(`Unable to find valid provisioning profile for ${iosInfo.certificate}`); + throw new Error(l10n.t('Unable to find valid provisioning profile for {0}', iosInfo.certificate)); } definition.ios = iosInfo; @@ -97,7 +98,7 @@ export class IosHelper extends TaskHelper { } if (!certificate) { - throw new Error(`Unable to find certificate ${iosInfo.certificate}`); + throw new Error(l10n.t('Unable to find certificate {0}', iosInfo.certificate)); } iosInfo.certificate = getCorrectCertificateName(certificate.fullname, project.sdk()[0], 'distribution'); @@ -107,7 +108,7 @@ export class IosHelper extends TaskHelper { } if (!iosInfo.provisioningProfile) { - throw new Error(`Unable to find valid provisioning profile for ${iosInfo.certificate}`); + throw new Error(l10n.t('Unable to find valid provisioning profile for {0}', iosInfo.certificate)); } definition.ios = iosInfo; diff --git a/src/tasks/packageTaskProvider.ts b/src/tasks/packageTaskProvider.ts index f71c1645a..081ee20ba 100644 --- a/src/tasks/packageTaskProvider.ts +++ b/src/tasks/packageTaskProvider.ts @@ -6,6 +6,7 @@ import { selectDistributionTarget } from '../quickpicks/build/common'; import { DeploymentTarget } from '../types/cli'; import { Command } from './commandBuilder'; import { promptForWorkspaceFolder } from '../quickpicks'; +import { l10n } from 'vscode'; export interface PackageTask extends TitaniumTaskBase { definition: PackageTaskDefinitionBase; @@ -70,7 +71,7 @@ export class PackageTaskProvider extends CommandTaskProvider { definition.titaniumBuild.projectDir = path.join(definition.titaniumBuild.projectDir, definition.titaniumBuild.platform); return helper.resolveModulePackageCommandLine(context, definition.titaniumBuild); } else { - throw new Error(`Unknown project type ${definition.projectType}`); + throw new Error(l10n.t('Unknown project type {0}', definition.projectType)); } } diff --git a/src/tasks/taskPseudoTerminal.ts b/src/tasks/taskPseudoTerminal.ts index b4c0c7f27..847e33bd7 100644 --- a/src/tasks/taskPseudoTerminal.ts +++ b/src/tasks/taskPseudoTerminal.ts @@ -42,10 +42,10 @@ async function spawnCommand (command: string, args: string[], options: cp.SpawnO } if (token && token.isCancellationRequested) { - return reject(new Error('user cancelled')); + return reject(new Error(vscode.l10n.t('user cancelled'))); } else if (code) { // throw nice error - const error = new CommandError(`Process exited with ${code}`, command, code, output, signal); + const error = new CommandError(vscode.l10n.t('Process exited with {0}', code), command, code, output, signal); return reject(error); } @@ -164,7 +164,7 @@ export class TaskPseudoTerminal implements vscode.Pseudoterminal { private getProject (projectDir: string): vscode.WorkspaceFolder { const workspaceFolder = vscode.workspace.workspaceFolders?.find(folder => folder.uri.fsPath === projectDir); if (!workspaceFolder) { - throw new Error(`Unable to resolve workspace folder for ${projectDir}`); + throw new Error(vscode.l10n.t('Unable to resolve workspace folder for {0}', projectDir)); } return workspaceFolder; } From ecb7572b1690929ff523dbae47660a1d72897a93 Mon Sep 17 00:00:00 2001 From: Ewan Harris Date: Wed, 21 Jun 2023 21:02:38 +0100 Subject: [PATCH 5/7] chore: move updates to l10n --- src/updates/index.ts | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/updates/index.ts b/src/updates/index.ts index 72f22ae7d..7b9a0d674 100644 --- a/src/updates/index.ts +++ b/src/updates/index.ts @@ -9,11 +9,11 @@ import { GlobalState } from '../constants'; import { startup } from '../extension'; export async function installUpdates (updateInfo?: UpdateInfo[], promptForChoice?: boolean): Promise { - vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: 'Titanium Updates', cancellable: false }, async progress => { + vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: vscode.l10n.t('Titanium Updates'), cancellable: false }, async progress => { if (!updateInfo) { - progress.report({ message: 'Checking for latest updates' }); + progress.report({ message: vscode.l10n.t('Checking for latest updates') }); updateInfo = await ExtensionContainer.getUpdates(); - progress.report({ message: 'Please select updates' }); + progress.report({ message: vscode.l10n.t('Please select updates') }); } if (promptForChoice) { @@ -36,12 +36,12 @@ export async function installUpdates (updateInfo?: UpdateInfo[], promptForChoice for (const update of updateInfo) { const label = `${update.productName}: ${update.latestVersion}`; progress.report({ - message: `Installing ${label} (${counter}/${selectedUpdates})` + message: vscode.l10n.t('Installing {0} ({1}/{2})', label, counter, selectedUpdates) }); try { await update.action(update.latestVersion); progress.report({ - message: `Installed ${label} (${counter}/${selectedUpdates})`, + message: vscode.l10n.t('Installed {label} ({counter}/{selectedUpdates})', label, counter, selectedUpdates), increment: 100 / selectedUpdates }); succeeded++; @@ -53,14 +53,14 @@ export async function installUpdates (updateInfo?: UpdateInfo[], promptForChoice if (error instanceof InstallError && error.metadata) { const { metadata } = error; if (metadata.errorCode === 'EACCES') { - const runWithSudo = await vscode.window.showErrorMessage(`Failed to update to ${label} as it must be ran with sudo`, { + const runWithSudo = await vscode.window.showErrorMessage(vscode.l10n.t('Failed to update to {0} as it must be ran with sudo', label), { title: 'Install with Sudo' }); if (runWithSudo) { await executeAsTask(`sudo ${metadata.command}`, update.productName); } } else if (metadata.errorCode === 'ESELECTERROR') { - const select = await vscode.window.showErrorMessage(`Failed to set ${update.latestVersion} as the selected SDK. Would you like to manually select it?`, { title: 'Select' }); + const select = await vscode.window.showErrorMessage(vscode.l10n.t('Failed to set {0} as the selected SDK. Would you like to manually select it?', update.latestVersion), { id: 'select', title: vscode.l10n.t('Select') }); if (select) { await executeAsTask(`${metadata.command}`, update.productName); } @@ -68,7 +68,7 @@ export async function installUpdates (updateInfo?: UpdateInfo[], promptForChoice failed++; } else { // TODO should we show the error that we got passed? - await vscode.window.showErrorMessage(`Failed to update to ${label}`); + await vscode.window.showErrorMessage(vscode.l10n.t('Failed to update to {0}', label)); } } counter++; @@ -88,10 +88,14 @@ export async function installUpdates (updateInfo?: UpdateInfo[], promptForChoice vscode.commands.executeCommand(Commands.RefreshExplorer); vscode.commands.executeCommand(Commands.RefreshHelp); - let message = `Installed ${succeeded} ${succeeded === 1 ? 'update' : 'updates'}`; + let message = succeeded === 1 + ? vscode.l10n.t('Installed {0} update', succeeded) + : vscode.l10n.t('Installed {0} updates', succeeded); if (failed) { - message = `${message} and failed to install ${failed} ${failed === 1 ? 'update' : 'updates'}`; + message = failed === 1 + ? vscode.l10n.t('{0} and failed to install {1} update', message, failed) + : vscode.l10n.t('{0}and failed to install {1} updates', message, failed); } vscode.window.showInformationMessage(message); From 2764dcf7a0550a5731e875206d57050cee3196c0 Mon Sep 17 00:00:00 2001 From: Ewan Harris Date: Wed, 21 Jun 2023 21:02:59 +0100 Subject: [PATCH 6/7] chore: move remaining file to l10n --- src/environment-info.ts | 5 +++-- src/extension.ts | 6 +++--- src/project.ts | 12 ++++++------ src/related.ts | 12 ++++++------ src/terminal.ts | 4 ++-- src/utils.ts | 8 ++++---- 6 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/environment-info.ts b/src/environment-info.ts index e414f0de2..ed91deb6c 100644 --- a/src/environment-info.ts +++ b/src/environment-info.ts @@ -7,6 +7,7 @@ import { AndroidEmulator, EnvironmentInfo, IosDevice, IosSimulator, TitaniumSDK, import { iOSProvisioningProfileMatchesAppId } from './utils'; import { GlobalState } from './constants'; import { InteractionError } from './commands'; +import { l10n } from 'vscode'; export class Environment { @@ -32,9 +33,9 @@ export class Environment { proc.on('close', (code) => { ExtensionContainer.context.globalState.update(GlobalState.RefreshEnvironment, false); if (code) { - const error = new InteractionError('Failed to get environment information'); + const error = new InteractionError(l10n.t('Failed to get environment information')); error.interactionChoices.push({ - title: 'View Error', + title: l10n.t('View Error'), run() { ExtensionContainer.outputChannel.append(output); ExtensionContainer.outputChannel.show(); diff --git a/src/extension.ts b/src/extension.ts index 03a13ff1b..e610dc99a 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -90,7 +90,7 @@ export async function startup (): Promise { ExtensionContainer.setContext(GlobalState.EnvironmentIssues, true); const choice = await vscode.window.showWarningMessage(title, ...actions.map(action => action.title)); if (!choice) { - vscode.window.showErrorMessage('Cannot continue startup until all issues are resolved'); + vscode.window.showErrorMessage(vscode.l10n.t('Cannot continue startup until all issues are resolved')); return; } // eslint-disable-next-line @typescript-eslint/no-non-null-assertion @@ -119,7 +119,7 @@ export async function startup (): Promise { } progress.report({ - message: 'Fetching environment information' + message: vscode.l10n.t('Fetching environment information') }); try { @@ -129,7 +129,7 @@ export async function startup (): Promise { handleInteractionError(error); return; } - vscode.window.showErrorMessage('Error fetching Titanium environment'); + vscode.window.showErrorMessage(vscode.l10n.t('Error fetching Titanium environment')); return; } diff --git a/src/project.ts b/src/project.ts index 8ef88b679..dd7d28481 100644 --- a/src/project.ts +++ b/src/project.ts @@ -2,7 +2,7 @@ import * as fs from 'fs-extra'; import * as path from 'path'; import * as utils from './utils'; -import { Range, window, workspace } from 'vscode'; +import { Range, l10n, window, workspace } from 'vscode'; import { handleInteractionError, InteractionError } from './commands/common'; import { Platform, ProjectType } from './types/common'; import { parseXmlString } from './common/utils'; @@ -73,7 +73,7 @@ export class Project { if (this.type === 'app') { return String(this.tiapp.id); } - throw new Error('Project is not a Titanium application'); + throw new Error(l10n.t('Project is not a Titanium application')); } /** @@ -151,7 +151,7 @@ export class Project { } let line: number; let column: number; - let message = 'Errors found in tiapp.xml'; + let message = l10n.t('Errors found in tiapp.xml'); const columnExp = /Column: (.*?)(?:\s|$)/g; const lineExp = /Line: (.*?)(?:\s|$)/g; const columnMatch = columnExp.exec(err.message); @@ -159,17 +159,17 @@ export class Project { if (lineMatch) { line = parseInt(lineMatch[1], 10); - message = `${message} on line ${line + 1}`; + message = l10n.t('{0} on line {1}', message, line + 1); } if (columnMatch) { column = parseInt(columnMatch[1], 10); - message = `${message} in column ${column + 1}`; + message = l10n.t('{0} on line {1}', message, column + 1); } const error = new InteractionError(message); error.interactionChoices.push({ - title: 'Open tiapp.xml', + title: l10n.t('Open tiapp.xml'), run: async () => { const file = path.join(this.filePath, 'tiapp.xml'); const document = await workspace.openTextDocument(file); diff --git a/src/related.ts b/src/related.ts index 0fc6f842d..8b97372f8 100644 --- a/src/related.ts +++ b/src/related.ts @@ -2,7 +2,7 @@ import * as fs from 'fs-extra'; import * as path from 'path'; import * as utils from './utils'; -import { Uri, window, TextEditor, TextDocument } from 'vscode'; +import { Uri, window, TextEditor, TextDocument, l10n } from 'vscode'; import { ExtensionContainer } from './container'; import { Project } from './project'; import { handleInteractionError, InteractionError } from './commands'; @@ -23,19 +23,19 @@ const alloyDirectoryMap: { [key: string]: string } = { */ export async function getTargetPath (project: Project, type: string, currentFilePath = window.activeTextEditor?.document.fileName): Promise { if (!currentFilePath) { - throw new InteractionError('No active edtor'); + throw new InteractionError(l10n.t('No active edtor')); } const alloyRootPath = path.join(project.filePath, 'app'); if (!currentFilePath.includes(alloyRootPath)) { - throw new InteractionError('File is not part of an Alloy project'); + throw new InteractionError(l10n.t('File is not part of an Alloy project')); } const pathUnderAlloy = path.relative(alloyRootPath, currentFilePath); if (!/^(controllers|styles|views|widgets)/.test(pathUnderAlloy)) { - throw new InteractionError('File is not a controller, style, view or widget'); + throw new InteractionError(l10n.t('File is not a controller, style, view or widget')); } const pathSplitArr = pathUnderAlloy.split(path.sep); @@ -62,7 +62,7 @@ export async function getTargetPath (project: Project, type: string, currentFile } } - throw new InteractionError('Unable to find related file'); + throw new InteractionError(l10n.t('Unable to find related file')); } /** @@ -74,7 +74,7 @@ export async function getTargetPath (project: Project, type: string, currentFile */ export async function openRelatedFile (type: string, project?: Project): Promise { if (!window.activeTextEditor) { - window.showErrorMessage('No active editor'); + window.showErrorMessage(l10n.t('No active editor')); return; } diff --git a/src/terminal.ts b/src/terminal.ts index 6e146b84d..3a6a39cdd 100644 --- a/src/terminal.ts +++ b/src/terminal.ts @@ -1,5 +1,5 @@ import { spawn, SpawnOptions } from 'child_process'; -import { Terminal as VSTerminal, window } from 'vscode'; +import { l10n, Terminal as VSTerminal, window } from 'vscode'; import { CommandError, CommandResponse } from './common/utils'; export default class Terminal { @@ -56,7 +56,7 @@ export default class Terminal { proc.on('close', code => { if (code) { - const error = new CommandError('Failed to run command', `${command} ${args.join(' ')}`, code, output); + const error = new CommandError(l10n.t('Failed to run command'), `${command} ${args.join(' ')}`, code, output); return reject(error); } return resolve({ output }); diff --git a/src/utils.ts b/src/utils.ts index d61209ea9..0d8b355aa 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -5,7 +5,7 @@ import findUp from 'find-up'; import walkSync from 'klaw-sync'; import { platform } from 'os'; -import { tasks, Task, ShellExecution, TaskScope } from 'vscode'; +import { tasks, Task, ShellExecution, TaskScope, l10n } from 'vscode'; import { CreateOptions, CreateModuleOptions, PrettyDevelopmentTarget, PrettyTarget, Target } from './types/cli'; import { IosCert, IosCertificateType, Platform, PlatformPretty } from './types/common'; import { ExtensionContainer } from './container'; @@ -314,7 +314,7 @@ export function getCorrectCertificateName (certificateName: string, sdkVersion: const certificate = ExtensionContainer.environment.iOSCertificates(certificateType).find((cert: IosCert) => cert.fullname === certificateName); if (!certificate) { - throw new Error(`Failed to lookup certificate ${certificateName}`); + throw new Error(l10n.t('Failed to lookup certificate {0}', certificateName)); } const coerced = semver.coerce(sdkVersion); @@ -405,7 +405,7 @@ export function getDeviceNameFromId (deviceID: string, platform: Platform, targe } if (!deviceName) { - throw new Error(`Unable to find a name for ${deviceID}`); + throw new Error(l10n.t('Unable to find a name for {0}', deviceID)); } return deviceName; @@ -424,7 +424,7 @@ export async function findProjectDirectory (filePath: string): Promise { try { const tiappFile = await findUp('tiapp.xml', { cwd: filePath, type: 'file' }); if (!tiappFile) { - throw new Error(`Unable to find project dir for ${filePath}`); + throw new Error(l10n.t('Unable to find project dir for {0}', filePath)); } return path.dirname(tiappFile); From 0755a8982d5c9e2546b41b9172939ac54036babb Mon Sep 17 00:00:00 2001 From: Ewan Harris Date: Wed, 21 Jun 2023 21:06:09 +0100 Subject: [PATCH 7/7] chore: add l10n file --- l10n/bundle.l10n.json | 146 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 l10n/bundle.l10n.json diff --git a/l10n/bundle.l10n.json b/l10n/bundle.l10n.json new file mode 100644 index 000000000..94071dc51 --- /dev/null +++ b/l10n/bundle.l10n.json @@ -0,0 +1,146 @@ +{ + "Failed to lookup certificate {0}": "Failed to lookup certificate {0}", + "Unable to find a name for {0}": "Unable to find a name for {0}", + "Unable to find project dir for {0}": "Unable to find project dir for {0}", + "Failed to run command": "Failed to run command", + "No active edtor": "No active edtor", + "File is not part of an Alloy project": "File is not part of an Alloy project", + "File is not a controller, style, view or widget": "File is not a controller, style, view or widget", + "Unable to find related file": "Unable to find related file", + "No active editor": "No active editor", + "Project is not a Titanium application": "Project is not a Titanium application", + "Errors found in tiapp.xml": "Errors found in tiapp.xml", + "{0} on line {1}": "{0} on line {1}", + "Open tiapp.xml": "Open tiapp.xml", + "Cannot continue startup until all issues are resolved": "Cannot continue startup until all issues are resolved", + "Fetching environment information": "Fetching environment information", + "Error fetching Titanium environment": "Error fetching Titanium environment", + "Failed to get environment information": "Failed to get environment information", + "View Error": "View Error", + "Titanium Updates": "Titanium Updates", + "Checking for latest updates": "Checking for latest updates", + "Please select updates": "Please select updates", + "Installing {0} ({1}/{2})": "Installing {0} ({1}/{2})", + "Installed {label} ({counter}/{selectedUpdates})": "Installed {label} ({counter}/{selectedUpdates})", + "Failed to update to {0} as it must be ran with sudo": "Failed to update to {0} as it must be ran with sudo", + "Failed to set {0} as the selected SDK. Would you like to manually select it?": "Failed to set {0} as the selected SDK. Would you like to manually select it?", + "Select": "Select", + "Failed to update to {0}": "Failed to update to {0}", + "Installed {0} update": "Installed {0} update", + "Installed {0} updates": "Installed {0} updates", + "{0} and failed to install {1} update": "{0} and failed to install {1} update", + "{0}and failed to install {1} updates": "{0}and failed to install {1} updates", + "user cancelled": "user cancelled", + "Process exited with {0}": "Process exited with {0}", + "Unable to resolve workspace folder for {0}": "Unable to resolve workspace folder for {0}", + "Unknown project type {0}": "Unknown project type {0}", + "Unknown platform {0}": "Unknown platform {0}", + "Invalid configuration, please specify a platform": "Invalid configuration, please specify a platform", + "Error running task": "Error running task", + "Task cancelled as no selection occurred": "Task cancelled as no selection occurred", + "Unable to find certificate {0}": "Unable to find certificate {0}", + "Unable to find valid provisioning profile for {0}": "Unable to find valid provisioning profile for {0}", + "No \"target\" value provided": "No \"target\" value provided", + "Browse": "Browse", + "Output Into Xcode": "Output Into Xcode", + "Choose output location": "Choose output location", + "Provided output directory {0} cannot be found": "Provided output directory {0} cannot be found", + "Project directory {0} does not exist": "Project directory {0} does not exist", + "Unable to determine project type from {0}": "Unable to determine project type from {0}", + "Unable to find loaded project for {0}, please ensure it is active in the workspace": "Unable to find loaded project for {0}, please ensure it is active in the workspace", + "Failed to find debug port associated with {0}. Please try setting a \"port\" property in the configuration.": "Failed to find debug port associated with {0}. Please try setting a \"port\" property in the configuration.", + "Choose platforms": "Choose platforms", + "At least one platform must be selected": "At least one platform must be selected", + "Select Android codebase": "Select Android codebase", + "Select iOS codebase": "Select iOS codebase", + "Select where to create your project": "Select where to create your project", + "Enter your path": "Enter your path", + "Please select a folder to perform action within": "Please select a folder to perform action within", + "Expires: {0}": "Expires: {0}", + "Select certificate": "Select certificate", + "Unable to resolve certificate {0}": "Unable to resolve certificate {0}", + "Select provisioning profile": "Select provisioning profile", + "Unable to resolve provisioning profile {0}": "Unable to resolve provisioning profile {0}", + "Select device": "Select device", + "Select simulator version": "Select simulator version", + "iOS Version {0} does not exist": "iOS Version {0} does not exist", + "Select simulator": "Select simulator", + "No devices detected, refresh device information?": "No devices detected, refresh device information?", + "Refresh Devices": "Refresh Devices", + "Select Android device": "Select Android device", + "Select emulator": "Select emulator", + "Browse for keystore": "Browse for keystore", + "Create keystore": "Create keystore", + "Last used {0}": "Last used {0}", + "Saved {0}": "Saved {0}", + "Browse, create, or use last keystore": "Browse, create, or use last keystore", + "No keystore was selected": "No keystore was selected", + "Provided keystorePath value \"{0}\" does not exist": "Provided keystorePath value \"{0}\" does not exist", + "Using stored information for {0}. If this is unexpected or your build errors, clear this information using the button below": "Using stored information for {0}. If this is unexpected or your build errors, clear this information using the button below", + "Delete Information": "Delete Information", + "No keystore location was provided, so could not delete": "No keystore location was provided, so could not delete", + "Deleted stored information for {0}": "Deleted stored information for {0}", + "Enter your keystore alias": "Enter your keystore alias", + "Enter your keystore password": "Enter your keystore password", + "Enter your keystore private key password (optional)": "Enter your keystore private key password (optional)", + "Would you like to store this information?": "Would you like to store this information?", + "Errors found in tiapp.xml: no sdk-version found": "Errors found in tiapp.xml: no sdk-version found", + "Errors found in tiapp.xml: multiple sdk-version tags found.": "Errors found in tiapp.xml: multiple sdk-version tags found.", + "Autocomplete suggestions generated for": "Autocomplete suggestions generated for", + "Titanium SDK Installation": "Titanium SDK Installation", + "Error generating autocomplete suggestions. {0}": "Error generating autocomplete suggestions. {0}", + "Image not found": "Image not found", + "Generate style ({0})": "Generate style ({0})", + "Generate function ({0})": "Generate function ({0})", + "Generate i18n string": "Generate i18n string", + "Package Module failed": "Package Module failed", + "Rerun": "Rerun", + "Package App failed": "Package App failed", + "Please select a project to build": "Please select a project to build", + "Please select a project to package": "Please select a project to package", + "Select log level": "Select log level", + "Enabled LiveView": "Enabled LiveView", + "Disabled LiveView": "Disabled LiveView", + "Please select a project to debug": "Please select a project to debug", + "There are {0} updates available": "There are {0} updates available", + "There is {0} update available": "There is {0} update available", + "Install": "Install", + "View": "View", + "Failed to check for updates": "Failed to check for updates", + "Please select the exported settings file": "Please select the exported settings file", + "Select a project to generate a task definition for": "Select a project to generate a task definition for", + "Select signing information?": "Select signing information?", + "Select keystore information?": "Select keystore information?", + "Generated task {0}": "Generated task {0}", + "Show": "Show", + "Failed to generate task {0}": "Failed to generate task {0}", + "Enter your module name": "Enter your module name", + "Enter your module ID": "Enter your module ID", + "Browse for location": "Browse for location", + "Select an open project to create the keystore in or browse for folder": "Select an open project to create the keystore in or browse for folder", + "No folder was selected": "No folder was selected", + "Keystore already exists at {0}. Please delete it or choose a new location": "Keystore already exists at {0}. Please delete it or choose a new location", + "Enter your application name": "Enter your application name", + "Enter your application ID": "Enter your application ID", + "Invalid app id!": "Invalid app id!", + "That app already exists. Would you like to overwrite?": "That app already exists. Would you like to overwrite?", + "App already exists and chose to not overwrite": "App already exists and chose to not overwrite", + "Creating application": "Creating application", + "Creating Alloy project": "Creating Alloy project", + "Project created. Would you like to open it?": "Project created. Would you like to open it?", + "Open in new window": "Open in new window", + "Open in workspace": "Open in workspace", + "Failed to create application": "Failed to create application", + "Cleaning project": "Cleaning project", + "Build Module failed.": "Build Module failed.", + "Build App failed": "Build App failed", + "Enter the name for your {0}": "Enter the name for your {0}", + "Yes": "Yes", + "No": "No", + "{0} already exists. Overwrite it?": "{0} already exists. Overwrite it?", + "{0} {name} created successfully": "{0} {name} created successfully", + "Open": "Open", + "Failed to create Alloy {0} {1}": "Failed to create Alloy {0} {1}", + "Which adapter type?": "Which adapter type?", + "{0} {1} created successfully": "{0} {1} created successfully" +} \ No newline at end of file