diff --git a/.gitignore b/.gitignore index d5ab24ca36c47..00002b14dc4b8 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,5 @@ node_modules images/settings gitlens-*.vsix tsconfig*.tsbuildinfo +vscode-gitlens-localization-export +vscode-translations-import \ No newline at end of file diff --git a/.vscodeignore b/.vscodeignore index f0761d316e620..831f76e782df3 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -35,3 +35,7 @@ tsconfig*.json tsconfig*.tsbuildinfo webpack.config*.js yarn.lock +i18n/** +vscode-gitlens-localization-export/** +vscode-translations-import/** +gulpfile.js \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 786a5d3655d76..8b02649fddecb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -115,3 +115,51 @@ Please follow all the instructions in the [PR template](.github/PULL_REQUEST_TEM This repository contains both OSS-licensed and non-OSS-licensed files. All files in or under any directory named "plus" fall under LICENSE.plus. The remaining files fall under LICENSE, the MIT license. If a pull request is submitted which contains changes to files in or under any directory named "plus", then you agree that GitKraken and/or its licensors (as applicable) retain all right, title and interest in and to all such modifications and/or patches. + +### String Localization + +[vscode-nls](https://github.com/microsoft/vscode-nls) is used to localize strings in TypeScript code. To use [vscode-nls](https://github.com/microsoft/vscode-nls), the source file must contain: + +```typescript +import * as nls from 'vscode-nls'; + +nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); +const localize: nls.LocalizeFunc = nls.loadMessageBundle(); +``` + +For each user-facing string, wrap the string in a call to localize: + +```typescript +const fetchReposMessage: string = localize( + 'quickPick.fetch.detail.willFetchRepos', + 'Will fetch {0}', + reposToFetch +); +``` + +The first parameter to localize should be a unique key for that string, not used by any other call to localize() in the file unless representing the same string. The second parameter is the string to localize. Both of these parameters must be string literals. Tokens such as {0} and {1} are supported in the localizable string, with replacement values passed as additional parameters to localize(). + +#### Adding a New Language +[Gulp](https://gulpjs.com/) is used to automate localized strings import and export. +To add new language support one should follow these steps: +1. Add target language to `gulpfile.js`. + +For example: +```javascript +const languages = [ + { id: 'ru', folderName: 'rus' }, +]; +``` + +2. Export internalized strings into `.xlf` file by calling `gulp translations-export` from a terminal +You can find the resulting file under `vscode-gitlens-localization-export/vscode-gitlens/gitlens.xlf` + +3. Translate the .xlf file using localization tool of your choice. (e.g. [Transifex](https://www.transifex.com/) or [Smartcat](https://smartcat.com)) + +4. Put localized file under `vscode-translations-import//vscode-gitlens/gitlens.xlf` + +5. Import localizations by calling `gulp translations-import` + +6. You can find imported localizations under `i18n/` + +7. Now you can build project and test your localization in work diff --git a/gulpfile.js b/gulpfile.js new file mode 100644 index 0000000000000..24be9993ba79d --- /dev/null +++ b/gulpfile.js @@ -0,0 +1,156 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +'use strict'; + +const gulp = require('gulp'); +const nls = require('vscode-nls-dev'); +const path = require('path'); +const minimist = require('minimist'); +const es = require('event-stream'); +const sourcemaps = require('gulp-sourcemaps'); +const ts = require('gulp-typescript'); +const typescript = require('typescript'); +const tsProject = ts.createProject('./tsconfig.json', { typescript, rootDir: '.' }); +tsProject.base = '/home/airaketa/vscode-gitlens'; +const filter = require('gulp-filter'); + +const languages = [ + // { id: "zh-tw", folderName: "cht", transifexId: "zh-hant" }, + // { id: "zh-cn", folderName: "chs", transifexId: "zh-hans" }, + // { id: "fr", folderName: "fra" }, + // { id: "de", folderName: "deu" }, + // { id: "it", folderName: "ita" }, + // { id: "es", folderName: "esn" }, + // { id: "ja", folderName: "jpn" }, + // { id: "ko", folderName: "kor" }, + // { id: 'ru', folderName: 'rus' }, + //{ id: "bg", folderName: "bul" }, // VS Code supports Bulgarian, but VS is not currently localized for it + //{ id: "hu", folderName: "hun" }, // VS Code supports Hungarian, but VS is not currently localized for it + // { id: "pt-br", folderName: "ptb", transifexId: "pt-BR" }, + // { id: "tr", folderName: "trk" }, + // { id: "cs", folderName: "csy" }, + // { id: "pl", folderName: "plk" } +]; + +// **************************** +// Command: translations-export +// The following is used to export and XLF file containing english strings for translations. +// The result will be written to: ../vscode-extensions-localization-export/ms-vscode/ +// **************************** + +const translationProjectName = 'vscode-gitlens'; +const translationExtensionName = 'gitlens'; + +// descriptionCallback(path, value, parent) is invoked for attributes +const traverseJson = (jsonTree, descriptionCallback, prefixPath) => { + for (let fieldName in jsonTree) { + if (jsonTree[fieldName] !== null) { + if ( + typeof jsonTree[fieldName] == 'string' && + (fieldName === 'description' || fieldName === 'markdownDescription') + ) { + descriptionCallback(prefixPath, jsonTree[fieldName], jsonTree); + } else if (typeof jsonTree[fieldName] == 'object') { + let path = prefixPath; + if (path !== '') path = path + '.'; + path = path + fieldName; + traverseJson(jsonTree[fieldName], descriptionCallback, path); + } + } + } +}; + +gulp.task('translations-export', done => { + // Transpile the TS to JS, and let vscode-nls-dev scan the files for calls to localize. + tsProject + .src() + .pipe(sourcemaps.init()) + .pipe(tsProject()) + .js.pipe(nls.createMetaDataFiles()) + + // Filter down to only the files we need + .pipe(filter(['**/*.nls.json', '**/*.nls.metadata.json'])) + + // Consoldate them into nls.metadata.json, which the xlf is built from. + .pipe(nls.bundleMetaDataFiles('vscode.gitlens', '.')) + + // filter down to just the resulting metadata files + .pipe(filter(['**/nls.metadata.header.json', '**/nls.metadata.json'])) + + // Add package.nls.json, used to localized package.json + .pipe(gulp.src(['package.nls.json'])) + + // package.nls.json and nls.metadata.json are used to generate the xlf file + // Does not re-queue any files to the stream. Outputs only the XLF file + .pipe(nls.createXlfFiles(translationProjectName, translationExtensionName)) + .pipe(gulp.dest(`${translationProjectName}-localization-export`)) + .pipe( + es.wait(() => { + done(); + }), + ); +}); + +// **************************** +// Command: translations-import +// The following is used to import an XLF file containing all language strings. +// This results in a i18n directory, which should be checked in. +// **************************** + +// Imports translations from raw localized MLCP strings to VS Code .i18n.json files +gulp.task('translations-import', done => { + let options = minimist(process.argv.slice(2), { + string: 'location', + default: { + location: 'vscode-translations-import', + }, + }); + es.merge( + languages.map(language => { + let id = language.transifexId || language.id; + return gulp + .src(path.join(options.location, id, translationProjectName, `${translationExtensionName}.xlf`)) + .pipe(nls.prepareJsonFiles()) + .pipe(gulp.dest(path.join('./i18n', language.folderName))); + }), + ).pipe( + es.wait(() => { + done(); + }), + ); +}); + +// **************************** +// Command: translations-generate +// The following is used to import an i18n directory structure and generate files used at runtime. +// **************************** + +// Generate package.nls.*.json files from: ./i18n/*/package.i18n.json +// Outputs to root path, as these nls files need to be along side package.json +const generateAdditionalLocFiles = () => { + return gulp + .src(['package.nls.json']) + .pipe(nls.createAdditionalLanguageFiles(languages, 'i18n')) + .pipe(gulp.dest('.')); +}; + +// Generates ./dist/nls.bundle..json from files in ./i18n/** *///.i18n.json +// Localized strings are read from these files at runtime. +const generateSrcLocBundle = () => { + // Transpile the TS to JS, and let vscode-nls-dev scan the files for calls to localize. + return tsProject + .src() + .pipe(sourcemaps.init()) + .pipe(tsProject()) + .js.pipe(nls.createMetaDataFiles()) + .pipe(nls.createAdditionalLanguageFiles(languages, 'i18n')) + .pipe(nls.bundleMetaDataFiles('vscode-gitlens', 'dist')) + .pipe(nls.bundleLanguageFiles()) + .pipe(filter(['**/nls.bundle.*.json', '**/nls.metadata.header.json', '**/nls.metadata.json'])) + .pipe(gulp.dest('dist')); +}; + +gulp.task('translations-generate', gulp.series(generateSrcLocBundle, generateAdditionalLocFiles)); diff --git a/package.json b/package.json index 3ee98aa6133c7..f047a94320978 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,12 @@ { "name": "gitlens", - "displayName": "GitLens — Git supercharged", - "description": "Supercharge Git within VS Code — Visualize code authorship at a glance via Git blame annotations and CodeLens, seamlessly navigate and explore Git repositories, gain valuable insights via rich visualizations and powerful comparison commands, and so much more", + "displayName": "%gitlens.displayName%", + "description": "%gitlens.description%", "version": "12.0.5", "engines": { "vscode": "^1.64.0" }, - "license": "SEE LICENSE IN LICENSE", + "license": "%gitlens.license%", "publisher": "eamodio", "author": { "name": "Eric Amodio", @@ -28,7 +28,7 @@ { "url": "https://img.shields.io/badge/vscode--dev--community-gitlens-blue.svg?logo=slack&labelColor=555555", "href": "https://vscode-slack.amod.io", - "description": "Join us in the #gitlens channel" + "description": "%gitlens.badges.joinUs.description%" } ], "categories": [ @@ -219,34 +219,34 @@ "configuration": [ { "id": "current-line-blame", - "title": "Current Line Blame", + "title": "%gitlens.contributes.configuration.currentLineBlame.title%", "order": 10, "properties": { "gitlens.currentLine.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to provide a blame annotation for the current line, by default. Use the `Toggle Line Blame Annotations` command (`gitlens.toggleLineBlame`) to toggle the annotations on and off for the current window", + "markdownDescription": "%gitlens.currentLine.enabled.markdownDescription%", "scope": "window", "order": 10 }, "gitlens.currentLine.pullRequests.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to provide information about the Pull Request (if any) that introduced the commit in the current line blame annotation. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.currentLine.pullRequests.enabled.markdownDescription%", "scope": "window", "order": 20 }, "gitlens.currentLine.format": { "type": "string", "default": "${author, }${agoOrDate}${' via 'pullRequest}${ • message|50?}", - "markdownDescription": "Specifies the format of the current line blame annotation. See [_Commit Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#commit-tokens) in the GitLens docs. Date formatting is controlled by the `#gitlens.currentLine.dateFormat#` setting", + "markdownDescription": "%gitlens.currentLine.format.markdownDescription%", "scope": "window", "order": 30 }, "gitlens.currentLine.scrollable": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether the current line blame annotation can be scrolled into view when it is outside the viewport. **NOTE**: Setting this to `false` will inhibit the hovers from showing over the annotation; Set `#gitlens.hovers.currentLine.over#` to `line` to enable the hovers to show anywhere over the line.", + "markdownDescription": "%gitlens.currentLine.scrollable.markdownDescription%", "scope": "window", "order": 40 }, @@ -256,7 +256,7 @@ "null" ], "default": null, - "markdownDescription": "Specifies how to format absolute dates (e.g. using the `${date}` token) for the current line blame annotation. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats", + "markdownDescription": "%gitlens.currentLine.dateFormat.markdownDescription%", "scope": "window", "order": 50 } @@ -264,20 +264,20 @@ }, { "id": "git-code-lens", - "title": "Git CodeLens", + "title": "%gitlens.contributes.configuration.gitCodeLens.title%", "order": 11, "properties": { "gitlens.codeLens.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to provide any Git CodeLens, by default. Use the `Toggle Git CodeLens` command (`gitlens.toggleCodeLens`) to toggle the Git CodeLens on and off for the current window", + "markdownDescription": "%gitlens.codeLens.enabled.markdownDescription%", "scope": "window", "order": 10 }, "gitlens.codeLens.authors.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to provide an _authors_ CodeLens, showing number of authors of the file or code block and the most prominent author (if there is more than one)", + "markdownDescription": "%gitlens.codeLens.authors.enabled.markdownDescription%", "scope": "window", "order": 20 }, @@ -305,32 +305,32 @@ "gitlens.copyRemoteFileUrl" ], "enumDescriptions": [ - "Disables click interaction", - "Toggles file blame", - "Toggles file heatmap", - "Toggles file changes since before the commit", - "Toggles file changes from the commit", - "Compares the current committed file with the previous commit", - "Reveals the commit in the Side Bar", - "Searches for commits within the range", - "Shows a commit details quick pick menu", - "Shows a commit file details quick pick menu", - "Shows a file history quick pick menu", - "Shows a branch history quick pick menu", - "Opens the commit on the remote service (when available)", - "Copies the remote commit url to the clipboard (when available)", - "Opens the file revision on the remote service (when available)", - "Copies the remote file url to the clipboard (when available)" + "%gitlens.codeLens.authors.command.disable.description%", + "%gitlens.codeLens.authors.command.toggleFileBlame.description%", + "%gitlens.codeLens.authors.command.toggleFileHeatmap.description%", + "%gitlens.codeLens.authors.command.toggleFileChanges.description%", + "%gitlens.codeLens.authors.command.toggleFileChangesOnly.description%", + "%gitlens.codeLens.authors.command.diffWithPrevious.description%", + "%gitlens.codeLens.authors.command.revealCommitInView.description%", + "%gitlens.codeLens.authors.command.showCommitsInView.description%", + "%gitlens.codeLens.authors.command.showQuickCommitDetails.description%", + "%gitlens.codeLens.authors.command.showQuickCommitFileDetails.description%", + "%gitlens.codeLens.authors.commandens.showQuickFileHistory.description%", + "%gitlens.codeLens.authors.command.showQuickRepoHistory.description%", + "%gitlens.codeLens.authors.command.openCommitOnRemote.description%", + "%gitlens.codeLens.authors.command.copyRemoteCommitUrl.description%", + "%gitlens.codeLens.authors.command.openFileOnRemote.description%", + "%gitlens.codeLens.authors.command.copyRemoteFileUrl.description%" ], "default": "gitlens.toggleFileBlame", - "markdownDescription": "Specifies the command to be executed when an _authors_ CodeLens is clicked", + "markdownDescription": "%gitlens.codeLens.authors.command.markdownDescription%", "scope": "window", "order": 21 }, "gitlens.codeLens.recentChange.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to provide a _recent change_ CodeLens, showing the author and date of the most recent commit for the file or code block", + "markdownDescription": "%gitlens.codeLens.recentChange.enabled.markdownDescription%", "scope": "window", "order": 30 }, @@ -358,25 +358,25 @@ "gitlens.copyRemoteFileUrl" ], "enumDescriptions": [ - "Disables click interaction", - "Toggles file blame", - "Toggles file heatmap", - "Toggles file changes since before the commit", - "Toggles file changes from the commit", - "Compares the current committed file with the previous commit", - "Reveals the commit in the Side Bar", - "Searches for the commit", - "Shows a commit details quick pick menu", - "Shows a commit file details quick pick menu", - "Shows a file history quick pick menu", - "Shows a branch history quick pick menu", - "Opens the commit on the remote service (when available)", - "Copies the remote commit url to the clipboard (when available)", - "Opens the file revision on the remote service (when available)", - "Copies the remote file url to the clipboard (when available)" + "%gitlens.codeLens.recentChange.command.disable.description%", + "%gitlens.codeLens.recentChange.command.toggleFileBlame.description%", + "%gitlens.codeLens.recentChange.command.toggleFileHeatmap.description%", + "%gitlens.codeLens.recentChange.command.toggleFileChanges.description%", + "%gitlens.codeLens.recentChange.command.toggleFileChangesOnly.description%", + "%gitlens.codeLens.recentChange.command.diffWithPrevious.description%", + "%gitlens.codeLens.recentChange.command.revealCommitInView.description%", + "%gitlens.codeLens.recentChange.command.showCommitsInView.description%", + "%gitlens.codeLens.recentChange.command.showQuickCommitDetails.description%", + "%gitlens.codeLens.recentChange.command.showQuickCommitFileDetails.description%", + "%gitlens.codeLens.recentChange.command.showQuickFileHistory.description%", + "%gitlens.codeLens.recentChange.command.showQuickRepoHistory.description%", + "%gitlens.codeLens.recentChange.command.openCommitOnRemote.description%", + "%gitlens.codeLens.recentChange.command.copyRemoteCommitUrl.description%", + "%gitlens.codeLens.recentChange.command.openFileOnRemote.description%", + "%gitlens.codeLens.recentChange.command.copyRemoteFileUrl.description%" ], "default": "gitlens.showQuickCommitFileDetails", - "markdownDescription": "Specifies the command to be executed when a _recent change_ CodeLens is clicked", + "markdownDescription": "%gitlens.codeLens.recentChange.command.markdownDescription%", "scope": "window", "order": 31 }, @@ -394,15 +394,15 @@ "blocks" ], "enumDescriptions": [ - "Adds CodeLens at the top of the document", - "Adds CodeLens at the start of container-like symbols (modules, classes, interfaces, etc)", - "Adds CodeLens at the start of block-like symbols (functions, methods, etc) lines" + "%gitlens.codeLens.scopes.document.description%", + "%gitlens.codeLens.scopes.containers.description%", + "%gitlens.codeLens.scopes.blocks.description%" ] }, "minItems": 0, "maxItems": 3, "uniqueItems": true, - "markdownDescription": "Specifies where Git CodeLens will be shown in the document", + "markdownDescription": "%gitlens.codeLens.scopes.markdownDescription%", "scope": "language-overridable", "order": 40 }, @@ -412,35 +412,35 @@ "type": "string" }, "uniqueItems": true, - "markdownDescription": "Specifies a set of document symbols where Git CodeLens will or will not be shown in the document. Prefix with `!` to avoid providing a Git CodeLens for the symbol. Must be a member of `SymbolKind`", + "markdownDescription": "%gitlens.codeLens.symbolScopes.markdownDescription%", "scope": "language-overridable", "order": 50 }, "gitlens.codeLens.includeSingleLineSymbols": { "type": "boolean", "default": false, - "markdownDescription": "Specifies whether to provide any Git CodeLens on symbols that span only a single line", + "markdownDescription": "%gitlens.codeLens.includeSingleLineSymbols.markdownDescription%", "scope": "window", "order": 60 }, "gitlens.strings.codeLens.unsavedChanges.recentChangeAndAuthors": { "type": "string", "default": "$(ellipsis)", - "markdownDescription": "Specifies the string to be shown in place of both the _recent change_ and _authors_ CodeLens when there are unsaved changes", + "markdownDescription": "%gitlens.strings.codeLens.unsavedChanges.recentChangeAndAuthors.markdownDescription%", "scope": "window", "order": 70 }, "gitlens.strings.codeLens.unsavedChanges.recentChangeOnly": { "type": "string", "default": "$(ellipsis)", - "markdownDescription": "Specifies the string to be shown in place of the _recent change_ CodeLens when there are unsaved changes", + "markdownDescription": "%gitlens.strings.codeLens.unsavedChanges.recentChangeOnly.markdownDescription%", "scope": "window", "order": 71 }, "gitlens.strings.codeLens.unsavedChanges.authorsOnly": { "type": "string", "default": "$(ellipsis)", - "markdownDescription": "Specifies the string to be shown in place of the _authors_ CodeLens when there are unsaved changes", + "markdownDescription": "%gitlens.strings.codeLens.unsavedChanges.authorsOnly.markdownDescription%", "scope": "window", "order": 72 }, @@ -450,39 +450,39 @@ "null" ], "default": null, - "markdownDescription": "Specifies how to format absolute dates in the Git CodeLens. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats", + "markdownDescription": "%gitlens.codeLens.dateFormat.markdownDescription%", "scope": "window", "order": 73 }, "gitlens.codeLens.scopesByLanguage": { - "deprecationMessage": "Deprecated. Use per-language `gitlens.codeLens.scopes` and `gitlens.codeLens.symbolScopes` settings instead", - "markdownDeprecationMessage": "Deprecated. Use the per-language `#gitlens.codeLens.scopes#` and `#gitlens.codeLens.symbolScopes#` settings instead" + "deprecationMessage": "%gitlens.codeLens.scopesByLanguage.deprecationMessage%", + "markdownDeprecationMessage": "%gitlens.codeLens.scopesByLanguage.markdownDeprecationMessage%" } } }, { "id": "status-bar-blame", - "title": "Status Bar Blame", + "title": "%gitlens.contributes.configuration.statusBarBlame.title%", "order": 12, "properties": { "gitlens.statusBar.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to provide blame information in the status bar", + "markdownDescription": "%gitlens.statusBar.enabled.markdownDescription%", "scope": "window", "order": 10 }, "gitlens.statusBar.pullRequests.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to provide information about the Pull Request (if any) that introduced the commit in the status bar. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.statusBar.pullRequests.enabled.markdownDescription%", "scope": "window", "order": 20 }, "gitlens.statusBar.format": { "type": "string", "default": "${author}, ${agoOrDate}${' via 'pullRequest}", - "markdownDescription": "Specifies the format of the blame information in the status bar. See [_Commit Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#commit-tokens) in the GitLens docs. Date formatting is controlled by the `#gitlens.statusBar.dateFormat#` setting", + "markdownDescription": "%gitlens.statusBar.format.markdownDescription%", "scope": "window", "order": 30 }, @@ -494,10 +494,10 @@ "right" ], "enumDescriptions": [ - "Aligns to the left", - "Aligns to the right" + "%gitlens.statusBar.alignment.left.description%", + "%gitlens.statusBar.alignment.right.description%" ], - "markdownDescription": "Specifies the blame alignment in the status bar", + "markdownDescription": "%gitlens.statusBar.alignment.markdownDescription%", "scope": "window", "order": 40 }, @@ -524,25 +524,25 @@ "gitlens.copyRemoteFileUrl" ], "enumDescriptions": [ - "Toggles file blame", - "Toggles file heatmap", - "Toggles file changes since before the commit", - "Toggles file changes from the commit", - "Toggles Git CodeLens", - "Compares the current line commit with the previous", - "Compares the current line commit with the working tree", - "Reveals the commit in the Side Bar", - "Searches for the commit", - "Shows a commit details quick pick menu", - "Shows a commit file details quick pick menu", - "Shows a file history quick pick menu", - "Shows a branch history quick pick menu", - "Opens the commit on the remote service (when available)", - "Copies the remote commit url to the clipboard (when available)", - "Opens the file revision on the remote service (when available)", - "Copies the remote file url to the clipboard (when available)" + "%gitlens.statusBar.command.toggleFileBlame.description%", + "%gitlens.statusBar.command.toggleFileHeatmap.description%", + "%gitlens.statusBar.command.toggleFileChanges.description%", + "%gitlens.statusBar.command.toggleFileChangesOnly.description%", + "%gitlens.statusBar.command.toggleCodeLens.description%", + "%gitlens.statusBar.command.diffWithPrevious.description%", + "%gitlens.statusBar.command.diffWithWorking.description%", + "%gitlens.statusBar.command.revealCommitInView.description%", + "%gitlens.statusBar.command.showCommitsInView.description%", + "%gitlens.statusBar.command.showQuickCommitDetails.description%", + "%gitlens.statusBar.command.showQuickCommitFileDetails.description%", + "%gitlens.statusBar.command.showQuickFileHistory.description%", + "%gitlens.statusBar.command.showQuickRepoHistory.description%", + "%gitlens.statusBar.command.openCommitOnRemote.description%", + "%gitlens.statusBar.command.copyRemoteCommitUrl.description%", + "%gitlens.statusBar.command.openFileOnRemote.description%", + "%gitlens.statusBar.command.copyRemoteFileUrl.description%" ], - "markdownDescription": "Specifies the command to be executed when the blame status bar item is clicked", + "markdownDescription": "%gitlens.statusBar.command.markdownDescription%", "scope": "window", "order": 50 }, @@ -550,14 +550,14 @@ "type": "string", "default": "${avatar}  __${author}__, ${ago}${' via 'pullRequest}   _(${date})_ \n\n${message}${\n\n---\n\nfootnotes}\n\n${commands}", "editPresentation": "multilineText", - "markdownDescription": "Specifies the format (in markdown) of hover shown over the blame information in the status bar. See [_Commit Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#commit-tokens) in the GitLens docs", + "markdownDescription": "%gitlens.statusBar.tooltipFormat.markdownDescription%", "scope": "window", "order": 60 }, "gitlens.statusBar.reduceFlicker": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to avoid clearing the previous blame information when changing lines to reduce status bar \"flashing\"", + "markdownDescription": "%gitlens.statusBar.reduceFlicker.markdownDescription%", "scope": "window", "order": 70 }, @@ -567,7 +567,7 @@ "null" ], "default": null, - "markdownDescription": "Specifies how to format absolute dates (e.g. using the `${date}` token) in the blame information in the status bar. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats", + "markdownDescription": "%gitlens.statusBar.dateFormat.markdownDescription%", "scope": "window", "order": 80 } @@ -575,55 +575,55 @@ }, { "id": "hovers", - "title": "Hovers", + "title": "%gitlens.contributes.configuration.hovers.title%", "order": 13, "properties": { "gitlens.hovers.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to provide any hovers", + "markdownDescription": "%gitlens.hovers.enabled.markdownDescription%", "scope": "window", "order": 10 }, "gitlens.hovers.avatars": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show avatar images in hovers", + "markdownDescription": "%gitlens.hovers.avatars.markdownDescription%", "scope": "window", "order": 20 }, "gitlens.hovers.avatarSize": { "type": "number", "default": 32, - "markdownDescription": "Specifies the size of the avatar images in hovers", + "markdownDescription": "%gitlens.hovers.avatarSize.markdownDescription%", "scope": "window", "order": 21 }, "gitlens.hovers.pullRequests.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to provide information about the Pull Request (if any) that introduced the commit in the hovers. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.hovers.pullRequests.enabled.markdownDescription%", "scope": "window", "order": 30 }, "gitlens.hovers.autolinks.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to automatically link external resources in commit messages", + "markdownDescription": "%gitlens.hovers.autolinks.enabled.markdownDescription%", "scope": "window", "order": 31 }, "gitlens.hovers.autolinks.enhanced": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to lookup additional details about automatically link external resources in commit messages. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.hovers.autolinks.enhanced.markdownDescription%", "scope": "window", "order": 32 }, "gitlens.hovers.currentLine.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to provide any hovers for the current line", + "markdownDescription": "%gitlens.hovers.currentLine.enabled.markdownDescription%", "scope": "window", "order": 40 }, @@ -635,31 +635,31 @@ "line" ], "enumDescriptions": [ - "Only shown when hovering over the line annotation", - "Shown when hovering anywhere over the line" + "%gitlens.hovers.currentLine.over.annotation.description%", + "%gitlens.hovers.currentLine.over.line.description%" ], - "markdownDescription": "Specifies when to trigger hovers for the current line", + "markdownDescription": "%gitlens.hovers.currentLine.over.markdownDescription%", "scope": "window", "order": 41 }, "gitlens.hovers.currentLine.details": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to provide a _commit details_ hover for the current line", + "markdownDescription": "%gitlens.hovers.currentLine.details.markdownDescription%", "scope": "window", "order": 42 }, "gitlens.hovers.currentLine.changes": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to provide a _changes (diff)_ hover for the current line", + "markdownDescription": "%gitlens.hovers.currentLine.changes.markdownDescription%", "scope": "window", "order": 43 }, "gitlens.hovers.annotations.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to provide any hovers when showing blame annotations", + "markdownDescription": "%gitlens.hovers.annotations.enabled.markdownDescription%", "scope": "window", "order": 50 }, @@ -671,24 +671,24 @@ "line" ], "enumDescriptions": [ - "Only shown when hovering over the line annotation", - "Shown when hovering anywhere over the line" + "%gitlens.hovers.annotations.over.annotation.description%", + "%gitlens.hovers.annotations.over.line.description%" ], - "markdownDescription": "Specifies when to trigger hovers when showing blame annotations", + "markdownDescription": "%gitlens.hovers.annotations.over.markdownDescription%", "scope": "window", "order": 51 }, "gitlens.hovers.annotations.details": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to provide a _commit details_ hover for all lines when showing blame annotations", + "markdownDescription": "%gitlens.hovers.annotations.details.markdownDescription%", "scope": "window", "order": 52 }, "gitlens.hovers.annotations.changes": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to provide a _changes (diff)_ hover for all lines when showing blame annotations", + "markdownDescription": "%gitlens.hovers.annotations.changes.markdownDescription%", "scope": "window", "order": 53 }, @@ -696,7 +696,7 @@ "type": "string", "default": "${avatar}  __${author}__, ${ago}${' via 'pullRequest}   _(${date})_ \n\n${message}${\n\n---\n\nfootnotes}\n\n${commands}", "editPresentation": "multilineText", - "markdownDescription": "Specifies the format (in markdown) of the _commit details_ hover. See [_Commit Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#commit-tokens) in the GitLens docs", + "markdownDescription": "%gitlens.hovers.detailsMarkdownFormat.markdownDescription%", "scope": "window", "order": 60 }, @@ -708,10 +708,10 @@ "hunk" ], "enumDescriptions": [ - "Shows only the changes to the line", - "Shows the set of related changes" + "%gitlens.hovers.changesDiff.line.description%", + "%gitlens.hovers.changesDiff.hunk.description%" ], - "markdownDescription": "Specifies whether to show just the changes to the line or the set of related changes in the _changes (diff)_ hover", + "markdownDescription": "%gitlens.hovers.changesDiff.markdownDescription%", "scope": "window", "order": 70 } @@ -719,117 +719,117 @@ }, { "id": "views", - "title": "Views", + "title": "%gitlens.contributes.configuration.views.title%", "order": 20, "properties": { "gitlens.views.defaultItemLimit": { "type": "number", "default": 10, - "markdownDescription": "Specifies the default number of items to show in a view list. Use 0 to specify no limit", + "markdownDescription": "%gitlens.views.defaultItemLimit.markdownDescription%", "scope": "window", "order": 10 }, "gitlens.views.pageItemLimit": { "type": "number", "default": 40, - "markdownDescription": "Specifies the number of items to show in a each page when paginating a view list. Use 0 to specify no limit", + "markdownDescription": "%gitlens.views.pageItemLimit.markdownDescription%", "scope": "window", "order": 11 }, "gitlens.views.showRelativeDateMarkers": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show relative date markers (_Less than a week ago_, _Over a week ago_, _Over a month ago_, etc) on revision (commit) histories in the views", + "markdownDescription": "%gitlens.views.showRelativeDateMarkers.markdownDescription%", "scope": "window", "order": 20 }, "gitlens.views.formats.commits.label": { "type": "string", "default": "${❰ tips ❱➤ }${message}", - "markdownDescription": "Specifies the format of commits in the views. See [_Commit Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#commit-tokens) in the GitLens docs", + "markdownDescription": "%gitlens.views.formats.commits.label.markdownDescription%", "scope": "window", "order": 30 }, "gitlens.views.formats.commits.description": { "type": "string", "default": "${author, }${agoOrDate}", - "markdownDescription": "Specifies the description format of commits in the views. See [_Commit Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#commit-tokens) in the GitLens docs", + "markdownDescription": "%gitlens.views.formats.commits.description.markdownDescription%", "scope": "window", "order": 31 }, "gitlens.views.formats.files.label": { "type": "string", "default": "${working }${file}", - "markdownDescription": "Specifies the format of a file in the views. See [_File Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#file-tokens) in the GitLens docs", + "markdownDescription": "%gitlens.views.formats.files.label.markdownDescription%", "scope": "window", "order": 32 }, "gitlens.views.formats.files.description": { "type": "string", "default": "${directory}${ ← originalPath}", - "markdownDescription": "Specifies the description format of a file in the views. See [_File Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#file-tokens) in the GitLens docs", + "markdownDescription": "%gitlens.views.formats.files.description.markdownDescription%", "scope": "window", "order": 33 }, "gitlens.views.formats.stashes.label": { "type": "string", "default": "${message}", - "markdownDescription": "Specifies the format of stashes in the views. See [_Commit Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#commit-tokens) in the GitLens docs", + "markdownDescription": "%gitlens.views.formats.stashes.label.markdownDescription%", "scope": "window", "order": 34 }, "gitlens.views.formats.stashes.description": { "type": "string", "default": "${agoOrDate}", - "markdownDescription": "Specifies the description format of stashes in the views. See [_Commit Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#commit-tokens) in the GitLens docs", + "markdownDescription": "%gitlens.views.formats.stashes.description.markdownDescription%", "scope": "window", "order": 35 }, "gitlens.views.commitFileFormat": { - "deprecationMessage": "Deprecated. Use `gitlens.views.formats.files.label` instead", - "markdownDeprecationMessage": "Deprecated. Use `#gitlens.views.formats.files.label#` instead" + "deprecationMessage": "%gitlens.views.commitFileFormat.deprecationMessage%", + "markdownDeprecationMessage": "%gitlens.views.commitFileFormat.markdownDeprecationMessage%" }, "gitlens.views.commitFileDescriptionFormat": { - "deprecationMessage": "Deprecated. Use `gitlens.views.formats.files.description` instead", - "markdownDeprecationMessage": "Deprecated. Use `#gitlens.views.formats.files.description#` instead" + "deprecationMessage": "%gitlens.views.commitFileDescriptionFormat.deprecationMessage%", + "markdownDeprecationMessage": "%gitlens.views.commitFileDescriptionFormat.markdownDeprecationMessage%" }, "gitlens.views.commitFormat": { - "deprecationMessage": "Deprecated. Use `gitlens.views.formats.commits.label` instead", - "markdownDeprecationMessage": "Deprecated. Use `#gitlens.views.commits.files.label#` instead" + "deprecationMessage": "%gitlens.views.commitFormat.deprecationMessage%", + "markdownDeprecationMessage": "%gitlens.views.commitFormat.markdownDeprecationMessage%" }, "gitlens.views.commitDescriptionFormat": { - "deprecationMessage": "Deprecated. Use `gitlens.views.formats.commits.description` instead", - "markdownDeprecationMessage": "Deprecated. Use `#gitlens.views.formats.commits.description#` instead" + "deprecationMessage": "%gitlens.views.commitDescriptionFormat.deprecationMessage%", + "markdownDeprecationMessage": "%gitlens.views.commitDescriptionFormat.markdownDeprecationMessage%" }, "gitlens.views.stashFileFormat": { - "deprecationMessage": "Deprecated. Use `gitlens.views.formats.files.label` instead", - "markdownDeprecationMessage": "Deprecated. Use `#gitlens.views.formats.files.label#` instead" + "deprecationMessage": "%gitlens.views.stashFileFormat.deprecationMessage%", + "markdownDeprecationMessage": "%gitlens.views.stashFileFormat.markdownDeprecationMessage%" }, "gitlens.views.stashFileDescriptionFormat": { - "deprecationMessage": "Deprecated. Use `gitlens.views.formats.files.description` instead", - "markdownDeprecationMessage": "Deprecated. Use `#gitlens.views.formats.files.description#` instead" + "deprecationMessage": "%gitlens.views.stashFileDescriptionFormat.deprecationMessage%", + "markdownDeprecationMessage": "%gitlens.views.stashFileDescriptionFormat.markdownDeprecationMessage%" }, "gitlens.views.stashFormat": { - "deprecationMessage": "Deprecated. Use `gitlens.views.formats.stashes.label` instead", - "markdownDeprecationMessage": "Deprecated. Use `#gitlens.views.stashes.files.label#` instead" + "deprecationMessage": "%gitlens.views.stashFormat.deprecationMessage%", + "markdownDeprecationMessage": "%gitlens.views.stashFormat.markdownDeprecationMessage%" }, "gitlens.views.stashDescriptionFormat": { - "deprecationMessage": "Deprecated. Use `gitlens.views.formats.stashes.description` instead", - "markdownDeprecationMessage": "Deprecated. Use `#gitlens.views.formats.stashes.description#` instead" + "deprecationMessage": "%gitlens.views.stashDescriptionFormat.deprecationMessage%", + "markdownDeprecationMessage": "%gitlens.views.stashDescriptionFormat.markdownDeprecationMessage%" }, "gitlens.views.statusFileFormat": { - "deprecationMessage": "Deprecated. Use `gitlens.views.formats.files.label` instead", - "markdownDeprecationMessage": "Deprecated. Use `#gitlens.views.formats.files.label#` instead" + "deprecationMessage": "%gitlens.views.statusFileFormat.deprecationMessage%", + "markdownDeprecationMessage": "%gitlens.views.statusFileFormat.markdownDeprecationMessage%" }, "gitlens.views.statusFileDescriptionFormat": { - "deprecationMessage": "Deprecated. Use `gitlens.views.formats.files.description` instead", - "markdownDeprecationMessage": "Deprecated. Use `#gitlens.views.formats.files.description#` instead" + "deprecationMessage": "%gitlens.views.statusFileDescriptionFormat.deprecationMessage%", + "markdownDeprecationMessage": "%gitlens.views.statusFileDescriptionFormat.markdownDeprecationMessage%" } } }, { "id": "commits-view", - "title": "Commits View", + "title": "%gitlens.contributes.configuration.commitsView.title%", "order": 21, "properties": { "gitlens.views.commits.showBranchComparison": { @@ -843,33 +843,33 @@ "working" ], "enumDescriptions": [ - "Hides the branch comparison", - "Compares the current branch with a user-selected reference", - "Compares the working tree with a user-selected reference" + "%gitlens.views.commits.showBranchComparison.hide.description%", + "%gitlens.views.commits.showBranchComparison.branch.description%", + "%gitlens.views.commits.showBranchComparison.working.description%" ], "default": "working", - "markdownDescription": "Specifies whether to show a comparison of the current branch or the working tree with a user-selected reference (branch, tag. etc) in the _Commits_ view", + "markdownDescription": "%gitlens.views.commits.showBranchComparison.markdownDescription%", "scope": "window", "order": 10 }, "gitlens.views.commits.pullRequests.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to query for pull requests associated with the current branch and commits in the _Commits_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.views.commits.pullRequests.enabled.markdownDescription%", "scope": "window", "order": 21 }, "gitlens.views.commits.pullRequests.showForBranches": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show pull requests (if any) associated with the current branch in the _Commits_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.views.commits.pullRequests.showForBranches.markdownDescription%", "scope": "window", "order": 21 }, "gitlens.views.commits.pullRequests.showForCommits": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show pull requests (if any) associated with commits in the _Commits_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.views.commits.pullRequests.showForCommits.markdownDescription%", "scope": "window", "order": 22 }, @@ -882,39 +882,39 @@ "tree" ], "enumDescriptions": [ - "Automatically switches between displaying files as a `tree` or `list` based on the `#gitlens.views.commits.files.threshold#` value and the number of files at each nesting level", - "Displays files as a list", - "Displays files as a tree" + "%gitlens.views.commits.files.layout.auto.description%", + "%gitlens.views.commits.files.layout.list.description%", + "%gitlens.views.commits.files.layout.tree.description%" ], - "markdownDescription": "Specifies how the _Commits_ view will display files", + "markdownDescription": "%gitlens.views.commits.files.layout.markdownDescription%", "scope": "window", "order": 30 }, "gitlens.views.commits.files.threshold": { "type": "number", "default": 5, - "markdownDescription": "Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the _Commits_ view. Only applies when `#gitlens.views.commits.files.layout#` is set to `auto`", + "markdownDescription": "%gitlens.views.commits.files.threshold.markdownDescription%", "scope": "window", "order": 31 }, "gitlens.views.commits.files.compact": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to compact (flatten) unnecessary file nesting in the _Commits_ view. Only applies when `#gitlens.views.commits.files.layout#` is set to `tree` or `auto`", + "markdownDescription": "%gitlens.views.commits.files.compact.markdownDescription%", "scope": "window", "order": 32 }, "gitlens.views.commits.avatars": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show avatar images instead of commit (or status) icons in the _Commits_ view", + "markdownDescription": "%gitlens.views.commits.avatars.markdownDescription%", "scope": "window", "order": 40 }, "gitlens.views.commits.reveal": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to reveal commits in the _Commits_ view, otherwise they revealed in the _Repositories_ view", + "markdownDescription": "%gitlens.views.commits.reveal.markdownDescription%", "scope": "window", "order": 50 } @@ -922,7 +922,7 @@ }, { "id": "repositories-view", - "title": "Repositories View", + "title": "%gitlens.contributes.configuration.repositoriesView.title%", "order": 22, "properties": { "gitlens.views.repositories.showBranchComparison": { @@ -936,124 +936,124 @@ "working" ], "enumDescriptions": [ - "Hides the branch comparison", - "Compares the current branch with a user-selected reference", - "Compares the working tree with a user-selected reference" + "%gitlens.views.repositories.showBranchComparison.hide.description%", + "%gitlens.views.repositories.showBranchComparison.branch.description%", + "%gitlens.views.repositories.showBranchComparison.working.description%" ], "default": "working", - "markdownDescription": "Specifies whether to show a comparison of the current branch or the working tree with a user-selected reference (branch, tag. etc) in the _Repositories_ view", + "markdownDescription": "%gitlens.views.repositories.showBranchComparison.markdownDescription%", "scope": "window", "order": 10 }, "gitlens.views.repositories.showUpstreamStatus": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show the upstream status of the current branch for each repository in the _Repositories_ view", + "markdownDescription": "%gitlens.views.repositories.showUpstreamStatus.markdownDescription%", "scope": "window", "order": 11 }, "gitlens.views.repositories.includeWorkingTree": { "type": "boolean", "default": false, - "markdownDescription": "Specifies whether to include working tree file status for each repository in the _Repositories_ view", + "markdownDescription": "%gitlens.views.repositories.includeWorkingTree.markdownDescription%", "scope": "window", "order": 12 }, "gitlens.views.repositories.pullRequests.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to query for pull requests associated with branches and commits in the _Repositories_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.views.repositories.pullRequests.enabled.markdownDescription%", "scope": "window", "order": 20 }, "gitlens.views.repositories.pullRequests.showForBranches": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show pull requests (if any) associated with branches in the _Repositories_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.views.repositories.pullRequests.showForBranches.markdownDescription%", "scope": "window", "order": 21 }, "gitlens.views.repositories.pullRequests.showForCommits": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show pull requests (if any) associated with commits in the _Repositories_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.views.repositories.pullRequests.showForCommits.markdownDescription%", "scope": "window", "order": 22 }, "gitlens.views.repositories.showCommits": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show the commits on the current branch for each repository in the _Repositories_ view", + "markdownDescription": "%gitlens.views.repositories.showCommits.markdownDescription%", "scope": "window", "order": 30 }, "gitlens.views.repositories.showBranches": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show the branches for each repository in the _Repositories_ view", + "markdownDescription": "%gitlens.views.repositories.showBranches.markdownDescription%", "scope": "window", "order": 31 }, "gitlens.views.repositories.showRemotes": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show the remotes for each repository in the _Repositories_ view", + "markdownDescription": "%gitlens.views.repositories.showRemotes.markdownDescription%", "scope": "window", "order": 32 }, "gitlens.views.repositories.showStashes": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show the stashes for each repository in the _Repositories_ view", + "markdownDescription": "%gitlens.views.repositories.showStashes.markdownDescription%", "scope": "window", "order": 33 }, "gitlens.views.repositories.showTags": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show the tags for each repository in the _Repositories_ view", + "markdownDescription": "%gitlens.views.repositories.showTags.markdownDescription%", "scope": "window", "order": 34 }, "gitlens.views.repositories.showContributors": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show the contributors for each repository in the _Repositories_ view", + "markdownDescription": "%gitlens.views.repositories.showContributors.markdownDescription%", "scope": "window", "order": 35 }, "gitlens.views.repositories.showWorktrees": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show the worktrees for each repository in the _Repositories_ view", + "markdownDescription": "%gitlens.views.repositories.showWorktrees.markdownDescription%", "scope": "window", "order": 36 }, "gitlens.views.repositories.showIncomingActivity": { "type": "boolean", "default": false, - "markdownDescription": "Specifies whether to show the experimental incoming activity for each repository in the _Repositories_ view", + "markdownDescription": "%gitlens.views.repositories.showIncomingActivity.markdownDescription%", "scope": "window", "order": 37 }, "gitlens.views.repositories.autoRefresh": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to automatically refresh the _Repositories_ view when the repository or the file system changes", + "markdownDescription": "%gitlens.views.repositories.autoRefresh.markdownDescription%", "scope": "window", "order": 40 }, "gitlens.views.repositories.autoReveal": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to automatically reveal repositories in the _Repositories_ view when opening files", + "markdownDescription": "%gitlens.views.repositories.autoReveal.markdownDescription%", "scope": "window", "order": 50 }, "gitlens.views.repositories.avatars": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show avatar images instead of commit (or status) icons in the _Repositories_ view", + "markdownDescription": "%gitlens.views.repositories.avatars.markdownDescription%", "scope": "window", "order": 60 }, @@ -1065,10 +1065,10 @@ "tree" ], "enumDescriptions": [ - "Displays branches as a list", - "Displays branches as a tree when branch names contain slashes `/`" + "%gitlens.views.repositories.branches.layout.list.description%", + "%gitlens.views.repositories.branches.layout.tree.description%" ], - "markdownDescription": "Specifies how the _Repositories_ view will display branches", + "markdownDescription": "%gitlens.views.repositories.branches.layout.markdownDescription%", "scope": "window", "order": 70 }, @@ -1081,32 +1081,32 @@ "tree" ], "enumDescriptions": [ - "Automatically switches between displaying files as a `tree` or `list` based on the `#gitlens.views.repositories.files.threshold#` value and the number of files at each nesting level", - "Displays files as a list", - "Displays files as a tree" + "%gitlens.views.repositories.files.layout.auto.description%", + "%gitlens.views.repositories.files.layout.list.description%", + "%gitlens.views.repositories.files.layout.tree.description%" ], - "markdownDescription": "Specifies how the _Repositories_ view will display files", + "markdownDescription": "%gitlens.views.repositories.files.layout.markdownDescription%", "scope": "window", "order": 80 }, "gitlens.views.repositories.files.threshold": { "type": "number", "default": 5, - "markdownDescription": "Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the _Repositories_ view. Only applies when `#gitlens.views.repositories.files.layout#` is set to `auto`", + "markdownDescription": "%gitlens.views.repositories.files.threshold.markdownDescription%", "scope": "window", "order": 81 }, "gitlens.views.repositories.files.compact": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to compact (flatten) unnecessary file nesting in the _Repositories_ view. Only applies when `#gitlens.views.repositories.files.layout#` is set to `tree` or `auto`", + "markdownDescription": "%gitlens.views.repositories.files.compact.markdownDescription%", "scope": "window", "order": 82 }, "gitlens.views.repositories.compact": { "type": "boolean", "default": false, - "markdownDescription": "Specifies whether to show the _Repositories_ view in a compact display density", + "markdownDescription": "%gitlens.views.repositories.compact.markdownDescription%", "scope": "window", "order": 90 }, @@ -1120,23 +1120,23 @@ "branch" ], "enumDescriptions": [ - "Hides the branch comparison", - "Compares the branch with a user-selected reference" + "%gitlens.views.repositories.branches.showBranchComparison.hide.description%", + "%gitlens.views.repositories.branches.showBranchComparison.branch.description%" ], "default": "branch", - "markdownDescription": "Specifies whether to show a comparison of the branch with a user-selected reference (branch, tag. etc) under each branch in the _Repositories_ view", + "markdownDescription": "%gitlens.views.repositories.branches.showBranchComparison.markdownDescription%", "scope": "window", "order": 100 }, "gitlens.views.repositories.enabled": { - "deprecationMessage": "Deprecated. This setting is no longer used", - "markdownDeprecationMessage": "Deprecated. This setting is no longer used" + "deprecationMessage": "%gitlens.views.repositories.enabled.deprecationMessage%", + "markdownDeprecationMessage": "%gitlens.views.repositories.enabled.markdownDeprecationMessage%" } } }, { "id": "file-history-view", - "title": "File History View", + "title": "%gitlens.contributes.configuration.fileHistoryView.title%", "order": 23, "properties": { "gitlens.views.fileHistory.files.layout": { @@ -1148,46 +1148,46 @@ "tree" ], "enumDescriptions": [ - "Automatically switches between displaying files as a `tree` or `list` based on the `#gitlens.views.fileHistory.files.threshold#` value and the number of files at each nesting level", - "Displays files as a list", - "Displays files as a tree" + "%gitlens.views.fileHistory.files.layout.auto.description%", + "%gitlens.views.fileHistory.files.layout.list.description%", + "%gitlens.views.fileHistory.files.layout.tree.description%" ], - "markdownDescription": "Specifies how the _File History_ view will display files when showing the history of a folder", + "markdownDescription": "%gitlens.views.fileHistory.files.layout.markdownDescription%", "scope": "window", "order": 10 }, "gitlens.views.fileHistory.files.threshold": { "type": "number", "default": 5, - "markdownDescription": "Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the _File History_ view. Only applies to folder history and when `#gitlens.views.fileHistory.files.layout#` is set to `auto`", + "markdownDescription": "%gitlens.views.fileHistory.files.threshold.markdownDescription%", "scope": "window", "order": 11 }, "gitlens.views.fileHistory.files.compact": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to compact (flatten) unnecessary file nesting in the _File History_ view. Only applies to folder history and when `#gitlens.views.fileHistory.files.layout#` is set to `tree` or `auto`", + "markdownDescription": "%gitlens.views.fileHistory.files.compact.markdownDescription%", "scope": "window", "order": 12 }, "gitlens.views.fileHistory.avatars": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show avatar images instead of status icons in the _File History_ view", + "markdownDescription": "%gitlens.views.fileHistory.avatars.markdownDescription%", "scope": "window", "order": 20 }, "gitlens.advanced.fileHistoryFollowsRenames": { "type": "boolean", "default": false, - "markdownDescription": "Specifies whether file histories will follow renames — will affect how merge commits are shown in histories", + "markdownDescription": "%gitlens.advanced.fileHistoryFollowsRenames.markdownDescription%", "scope": "window", "order": 100 }, "gitlens.advanced.fileHistoryShowAllBranches": { "type": "boolean", "default": false, - "markdownDescription": "Specifies whether file histories will show commits from all branches", + "markdownDescription": "%gitlens.advanced.fileHistoryShowAllBranches.markdownDescription%", "scope": "window", "order": 101 } @@ -1195,25 +1195,25 @@ }, { "id": "line-history-view", - "title": "Line History View", + "title": "%gitlens.contributes.configuration.lineHistoryView.title%", "order": 24, "properties": { "gitlens.views.lineHistory.avatars": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show avatar images instead of status icons in the _Line History_ view", + "markdownDescription": "%gitlens.views.lineHistory.avatars.markdownDescription%", "scope": "window", "order": 10 }, "gitlens.views.lineHistory.enabled": { - "deprecationMessage": "Deprecated. This setting is no longer used", - "markdownDeprecationMessage": "Deprecated. This setting is no longer used" + "deprecationMessage": "%gitlens.views.lineHistory.enabled.deprecationMessage%", + "markdownDeprecationMessage": "%gitlens.views.lineHistory.enabled.markdownDeprecationMessage%" } } }, { "id": "branches-view", - "title": "Branches View", + "title": "%gitlens.contributes.configuration.branchesView.title%", "order": 25, "properties": { "gitlens.views.branches.showBranchComparison": { @@ -1226,32 +1226,32 @@ "branch" ], "enumDescriptions": [ - "Hides the branch comparison", - "Compares the branch with a user-selected reference" + "%gitlens.views.branches.showBranchComparison.hide.description%", + "%gitlens.views.branches.showBranchComparison.branch.description%" ], "default": "branch", - "markdownDescription": "Specifies whether to show a comparison of the branch with a user-selected reference (branch, tag. etc) in the _Branches_ view", + "markdownDescription": "%gitlens.views.branches.showBranchComparison.markdownDescription%", "scope": "window", "order": 10 }, "gitlens.views.branches.pullRequests.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to query for pull requests associated with each branch and commits in the _Branches_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.views.branches.pullRequests.enabled.markdownDescription%", "scope": "window", "order": 20 }, "gitlens.views.branches.pullRequests.showForBranches": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show pull requests (if any) associated with each branch in the _Branches_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.views.branches.pullRequests.showForBranches.markdownDescription%", "scope": "window", "order": 21 }, "gitlens.views.branches.pullRequests.showForCommits": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show pull requests (if any) associated with commits in the _Branches_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.views.branches.pullRequests.showForCommits.markdownDescription%", "scope": "window", "order": 22 }, @@ -1263,10 +1263,10 @@ "tree" ], "enumDescriptions": [ - "Displays branches as a list", - "Displays branches as a tree when branch names contain slashes `/`" + "%gitlens.views.branches.branches.layout.list.description%", + "%gitlens.views.branches.branches.layout.tree.description%" ], - "markdownDescription": "Specifies how the _Branches_ view will display branches", + "markdownDescription": "%gitlens.views.branches.branches.layout.markdownDescription%", "scope": "window", "order": 30 }, @@ -1280,12 +1280,12 @@ "name:desc" ], "enumDescriptions": [ - "Sorts branches by the most recent commit date in descending order", - "Sorts branches by the most recent commit date in ascending order", - "Sorts branches by name in ascending order", - "Sorts branches by name in descending order" + "%gitlens.sortBranchesBy.dateDescending.description%", + "%gitlens.sortBranchesBy.dateAscending.description%", + "%gitlens.sortBranchesBy.nameAscending.description%", + "%gitlens.sortBranchesBy.nameDescending.description%" ], - "markdownDescription": "Specifies how branches are sorted in quick pick menus and views", + "markdownDescription": "%gitlens.sortBranchesBy.markdownDescription%", "scope": "window", "order": 40 }, @@ -1298,39 +1298,39 @@ "tree" ], "enumDescriptions": [ - "Automatically switches between displaying files as a `tree` or `list` based on the `#gitlens.views.branches.files.threshold#` value and the number of files at each nesting level", - "Displays files as a list", - "Displays files as a tree" + "%gitlens.views.branches.files.layout.auto.description%", + "%gitlens.views.branches.files.layout.list.description%", + "%gitlens.views.branches.files.layout.tree.description%" ], - "markdownDescription": "Specifies how the _Branches_ view will display files", + "markdownDescription": "%gitlens.views.branches.files.layout.markdownDescription%", "scope": "window", "order": 50 }, "gitlens.views.branches.files.threshold": { "type": "number", "default": 5, - "markdownDescription": "Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the _Branches_ view. Only applies when `#gitlens.views.branches.files.layout#` is set to `auto`", + "markdownDescription": "%gitlens.views.branches.files.threshold.markdownDescription%", "scope": "window", "order": 51 }, "gitlens.views.branches.files.compact": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to compact (flatten) unnecessary file nesting in the _Branches_ view. Only applies when `#gitlens.views.branches.files.layout#` is set to `tree` or `auto`", + "markdownDescription": "%gitlens.views.branches.files.compact.markdownDescription%", "scope": "window", "order": 52 }, "gitlens.views.branches.avatars": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show avatar images instead of commit (or status) icons in the _Branches_ view", + "markdownDescription": "%gitlens.views.branches.avatars.markdownDescription%", "scope": "window", "order": 60 }, "gitlens.views.branches.reveal": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to reveal branches in the _Branches_ view, otherwise they revealed in the _Repositories_ view", + "markdownDescription": "%gitlens.views.branches.reveal.markdownDescription%", "scope": "window", "order": 70 } @@ -1338,27 +1338,27 @@ }, { "id": "remotes-view", - "title": "Remotes View", + "title": "%gitlens.contributes.configuration.remotesView.title%", "order": 26, "properties": { "gitlens.views.remotes.pullRequests.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to query for pull requests associated with each branch and commits in the _Remotes_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.views.remotes.pullRequests.enabled.markdownDescription%", "scope": "window", "order": 10 }, "gitlens.views.remotes.pullRequests.showForBranches": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show pull requests (if any) associated with each branch in the _Remotes_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.views.remotes.pullRequests.showForBranches.markdownDescription%", "scope": "window", "order": 11 }, "gitlens.views.remotes.pullRequests.showForCommits": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show pull requests (if any) associated with commits in the _Remotes_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.views.remotes.pullRequests.showForCommits.markdownDescription%", "scope": "window", "order": 12 }, @@ -1370,10 +1370,10 @@ "tree" ], "enumDescriptions": [ - "Displays branches as a list", - "Displays branches as a tree when branch names contain slashes `/`" + "%gitlens.views.remotes.branches.layout.list.description%", + "%gitlens.views.remotes.branches.layout.tree.description%" ], - "markdownDescription": "Specifies how the _Remotes_ view will display branches", + "markdownDescription": "%gitlens.views.remotes.branches.layout.markdownDescription%", "scope": "window", "order": 20 }, @@ -1386,39 +1386,39 @@ "tree" ], "enumDescriptions": [ - "Automatically switches between displaying files as a `tree` or `list` based on the `#gitlens.views.remotes.files.threshold#` value and the number of files at each nesting level", - "Displays files as a list", - "Displays files as a tree" + "%gitlens.views.remotes.files.layout.auto.description%", + "%gitlens.views.remotes.files.layout.list.description%", + "%gitlens.views.remotes.files.layout.tree.description%" ], - "markdownDescription": "Specifies how the _Remotes_ view will display files", + "markdownDescription": "%gitlens.views.remotes.files.layout.markdownDescription%", "scope": "window", "order": 30 }, "gitlens.views.remotes.files.threshold": { "type": "number", "default": 5, - "markdownDescription": "Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the _Remotes_ view. Only applies when `#gitlens.views.remotes.files.layout#` is set to `auto`", + "markdownDescription": "%gitlens.views.remotes.files.threshold.markdownDescription%", "scope": "window", "order": 31 }, "gitlens.views.remotes.files.compact": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to compact (flatten) unnecessary file nesting in the _Remotes_ view. Only applies when `#gitlens.views.remotes.files.layout#` is set to `tree` or `auto`", + "markdownDescription": "%gitlens.views.remotes.files.compact.markdownDescription%", "scope": "window", "order": 32 }, "gitlens.views.remotes.avatars": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show avatar images instead of commit (or status) icons in the _Remotes_ view", + "markdownDescription": "%gitlens.views.remotes.avatars.markdownDescription%", "scope": "window", "order": 40 }, "gitlens.views.remotes.reveal": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to reveal remotes in the _Remotes_ view, otherwise they revealed in the _Repositories_ view", + "markdownDescription": "%gitlens.views.remotes.reveal.markdownDescription%", "scope": "window", "order": 50 } @@ -1426,7 +1426,7 @@ }, { "id": "stashes-view", - "title": "Stashes View", + "title": "%gitlens.views.stashes.title%", "order": 27, "properties": { "gitlens.views.stashes.files.layout": { @@ -1438,32 +1438,32 @@ "tree" ], "enumDescriptions": [ - "Automatically switches between displaying files as a `tree` or `list` based on the `#gitlens.views.stashes.files.threshold#` value and the number of files at each nesting level", - "Displays files as a list", - "Displays files as a tree" + "%gitlens.views.stashes.files.layout.auto.description%", + "%gitlens.views.stashes.files.layout.list.description%", + "%gitlens.views.stashes.files.layout.tree.description%" ], - "markdownDescription": "Specifies how the _Stashes_ view will display files", + "markdownDescription": "%gitlens.views.stashes.files.layout.markdownDescription%", "scope": "window", "order": 10 }, "gitlens.views.stashes.files.threshold": { "type": "number", "default": 5, - "markdownDescription": "Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the _Stashes_ view. Only applies when `#gitlens.views.stashes.files.layout#` is set to `auto`", + "markdownDescription": "%gitlens.views.stashes.files.threshold.markdownDescription%", "scope": "window", "order": 11 }, "gitlens.views.stashes.files.compact": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to compact (flatten) unnecessary file nesting in the _Stashes_ view. Only applies when `#gitlens.views.stashes.files.layout#` is set to `tree` or `auto`", + "markdownDescription": "%gitlens.views.stashes.files.compact.markdownDescription%", "scope": "window", "order": 12 }, "gitlens.views.stashes.reveal": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to reveal stashes in the _Stashes_ view, otherwise they revealed in the _Repositories_ view", + "markdownDescription": "%gitlens.views.stashes.reveal.markdownDescription%", "scope": "window", "order": 20 } @@ -1471,7 +1471,7 @@ }, { "id": "tags-view", - "title": "Tags View", + "title": "%gitlens.contributes.configuration.tagsView.title%", "order": 28, "properties": { "gitlens.views.tags.branches.layout": { @@ -1482,10 +1482,10 @@ "tree" ], "enumDescriptions": [ - "Displays tags as a list", - "Displays tags as a tree when tags names contain slashes `/`" + "%gitlens.views.tags.branches.layout.list.description%", + "%gitlens.views.tags.branches.layout.tree.description%" ], - "markdownDescription": "Specifies how the _Tags_ view will display tags", + "markdownDescription": "%gitlens.views.tags.branches.layout.markdownDescription%", "scope": "window", "order": 10 }, @@ -1499,12 +1499,12 @@ "name:desc" ], "enumDescriptions": [ - "Sorts tags by date in descending order", - "Sorts tags by date in ascending order", - "Sorts tags by name in ascending order", - "Sorts tags by name in descending order" + "%gitlens.sortTagsBy.dateDescending.description%", + "%gitlens.sortTagsBy.dateAscending.description%", + "%gitlens.sortTagsBy.nameAscending.description%", + "%gitlens.sortTagsBy.nameDescending.description%" ], - "markdownDescription": "Specifies how tags are sorted in quick pick menus and views", + "markdownDescription": "%gitlens.sortTagsBy.markdownDescription%", "scope": "window", "order": 20 }, @@ -1517,39 +1517,39 @@ "tree" ], "enumDescriptions": [ - "Automatically switches between displaying files as a `tree` or `list` based on the `#gitlens.views.tags.files.threshold#` value and the number of files at each nesting level", - "Displays files as a list", - "Displays files as a tree" + "%gitlens.views.tags.files.layout.auto.description%", + "%gitlens.views.tags.files.layout.list.description%", + "%gitlens.views.tags.files.layout.tree.description%" ], - "markdownDescription": "Specifies how the _Tags_ view will display files", + "markdownDescription": "%gitlens.views.tags.files.layout.markdownDescription%", "scope": "window", "order": 30 }, "gitlens.views.tags.files.threshold": { "type": "number", "default": 5, - "markdownDescription": "Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the _Tags_ view. Only applies when `#gitlens.views.tags.files.layout#` is set to `auto`", + "markdownDescription": "%gitlens.views.tags.files.threshold.markdownDescription%", "scope": "window", "order": 31 }, "gitlens.views.tags.files.compact": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to compact (flatten) unnecessary file nesting in the _Tags_ view. Only applies when `#gitlens.views.tags.files.layout#` is set to `tree` or `auto`", + "markdownDescription": "%gitlens.views.tags.files.compact.markdownDescription%", "scope": "window", "order": 32 }, "gitlens.views.tags.avatars": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show avatar images instead of commit (or status) icons in the _Tags_ view", + "markdownDescription": "%gitlens.views.tags.avatars.markdownDescription%", "scope": "window", "order": 40 }, "gitlens.views.tags.reveal": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to reveal tags in the _Tags_ view, otherwise they revealed in the _Repositories_ view", + "markdownDescription": "%gitlens.views.tags.reveal.markdownDescription%", "scope": "window", "order": 50 } @@ -1557,20 +1557,20 @@ }, { "id": "worktrees-view", - "title": "Worktrees View", + "title": "%gitlens.contributes.configuration.worktreesView.title%", "order": 29, "properties": { "gitlens.worktrees.promptForLocation": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to prompt for a path when creating new worktrees", + "markdownDescription": "%gitlens.worktrees.promptForLocation.markdownDescription%", "scope": "resource", "order": 10 }, "gitlens.worktrees.defaultLocation": { "type": "string", "default": null, - "markdownDescription": "Specifies the default path in which new worktrees will be created", + "markdownDescription": "%gitlens.worktrees.defaultLocation.markdownDescription%", "scope": "resource", "order": 11 }, @@ -1584,32 +1584,32 @@ "branch" ], "enumDescriptions": [ - "Hides the branch comparison", - "Compares the worktree branch with a user-selected reference" + "%gitlens.views.worktrees.showBranchComparison.hide.description%", + "%gitlens.views.worktrees.showBranchComparison.branch.description%" ], "default": "working", - "markdownDescription": "Specifies whether to show a comparison of the worktree branch with a user-selected reference (branch, tag. etc) in the _Worktrees_ view", + "markdownDescription": "%gitlens.views.worktrees.showBranchComparison.markdownDescription%", "scope": "window", "order": 20 }, "gitlens.views.worktrees.pullRequests.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to query for pull requests associated with the worktree branch and commits in the _Worktrees_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.views.worktrees.pullRequests.enabled.markdownDescription%", "scope": "window", "order": 30 }, "gitlens.views.worktrees.pullRequests.showForBranches": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show pull requests (if any) associated with the worktree branch in the _Worktrees_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.views.worktrees.pullRequests.showForBranches.markdownDescription%", "scope": "window", "order": 31 }, "gitlens.views.worktrees.pullRequests.showForCommits": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show pull requests (if any) associated with commits in the _Worktrees_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.views.worktrees.pullRequests.showForCommits.markdownDescription%", "scope": "window", "order": 32 }, @@ -1622,39 +1622,39 @@ "tree" ], "enumDescriptions": [ - "Automatically switches between displaying files as a `tree` or `list` based on the `#gitlens.views.worktrees.files.threshold#` value and the number of files at each nesting level", - "Displays files as a list", - "Displays files as a tree" + "%gitlens.views.worktrees.files.layout.auto.description%", + "%gitlens.views.worktrees.files.layout.list.description%", + "%gitlens.views.worktrees.files.layout.tree.description%" ], - "markdownDescription": "Specifies how the _Worktrees_ view will display files", + "markdownDescription": "%gitlens.views.worktrees.files.layout.markdownDescription%", "scope": "window", "order": 40 }, "gitlens.views.worktrees.files.threshold": { "type": "number", "default": 5, - "markdownDescription": "Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the _Worktrees_ view. Only applies when `#gitlens.views.worktrees.files.layout#` is set to `auto`", + "markdownDescription": "%gitlens.views.worktrees.files.threshold.markdownDescription%", "scope": "window", "order": 41 }, "gitlens.views.worktrees.files.compact": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to compact (flatten) unnecessary file nesting in the _Worktrees_ view. Only applies when `#gitlens.views.worktrees.files.layout#` is set to `tree` or `auto`", + "markdownDescription": "%gitlens.views.worktrees.files.compact.markdownDescription%", "scope": "window", "order": 42 }, "gitlens.views.worktrees.avatars": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show avatar images instead of commit (or status) icons in the _Worktrees_ view", + "markdownDescription": "%gitlens.views.worktrees.avatars.markdownDescription%", "scope": "window", "order": 50 }, "gitlens.views.worktrees.reveal": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to reveal worktrees in the _Worktrees_ view, otherwise they revealed in the _Repositories_ view", + "markdownDescription": "%gitlens.views.worktrees.reveal.markdownDescription%", "scope": "window", "order": 60 } @@ -1662,34 +1662,34 @@ }, { "id": "contributors-view", - "title": "Contributors View", + "title": "%gitlens.contributes.configuration.contributorsView.title%", "order": 30, "properties": { "gitlens.views.contributors.showAllBranches": { "type": "boolean", "default": false, - "markdownDescription": "Specifies whether to show commits from all branches in the _Contributors_ view", + "markdownDescription": "%gitlens.views.contributors.showAllBranches.markdownDescription%", "scope": "window", "order": 10 }, "gitlens.views.contributors.showStatistics": { "type": "boolean", "default": false, - "markdownDescription": "Specifies whether to show contributor statistics in the _Contributors_ view. This can take a while to compute depending on the repository size", + "markdownDescription": "%gitlens.views.contributors.showStatistics.markdownDescription%", "scope": "window", "order": 20 }, "gitlens.views.contributors.pullRequests.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to query for pull requests associated with branches and commits in the _Contributors_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.views.contributors.pullRequests.enabled.markdownDescription%", "scope": "window", "order": 30 }, "gitlens.views.contributors.pullRequests.showForCommits": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show pull requests (if any) associated with commits in the _Contributors_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.views.contributors.pullRequests.showForCommits.markdownDescription%", "scope": "window", "order": 31 }, @@ -1705,14 +1705,14 @@ "name:desc" ], "enumDescriptions": [ - "Sorts contributors by commit count in descending order", - "Sorts contributors by commit count in ascending order", - "Sorts contributors by the most recent commit date in descending order", - "Sorts contributors by the most recent commit date in ascending order", - "Sorts contributors by name in ascending order", - "Sorts contributors by name in descending order" + "%gitlens.sortContributorsBy.countDescending.description%", + "%gitlens.sortContributorsBy.countAscending.description%", + "%gitlens.sortContributorsBy.dateDescending.description%", + "%gitlens.sortContributorsBy.dateAscending.description%", + "%gitlens.sortContributorsBy.nameAscending.description%", + "%gitlens.sortContributorsBy.nameDescending.description%" ], - "markdownDescription": "Specifies how contributors are sorted in quick pick menus and views", + "markdownDescription": "%gitlens.sortContributorsBy.markdownDescription%", "scope": "window", "order": 40 }, @@ -1725,39 +1725,39 @@ "tree" ], "enumDescriptions": [ - "Automatically switches between displaying files as a `tree` or `list` based on the `#gitlens.views.contributors.files.threshold#` value and the number of files at each nesting level", - "Displays files as a list", - "Displays files as a tree" + "%gitlens.views.contributors.files.layout.auto.description%", + "%gitlens.views.contributors.files.layout.list.description%", + "%gitlens.views.contributors.files.layout.tree.description%" ], - "markdownDescription": "Specifies how the _Contributors_ view will display files", + "markdownDescription": "%gitlens.views.contributors.files.layout.markdownDescription%", "scope": "window", "order": 50 }, "gitlens.views.contributors.files.threshold": { "type": "number", "default": 5, - "markdownDescription": "Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the _Contributors_ view. Only applies when `#gitlens.views.contributors.files.layout#` is set to `auto`", + "markdownDescription": "%gitlens.views.contributors.files.threshold.markdownDescription%", "scope": "window", "order": 51 }, "gitlens.views.contributors.files.compact": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to compact (flatten) unnecessary file nesting in the _Contributors_ view. Only applies when `#gitlens.views.contributors.files.layout#` is set to `tree` or `auto`", + "markdownDescription": "%gitlens.views.contributors.files.compact.markdownDescription%", "scope": "window", "order": 52 }, "gitlens.views.contributors.avatars": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show avatar images instead of commit (or status) icons in the _Contributors_ view", + "markdownDescription": "%gitlens.views.contributors.avatars.markdownDescription%", "scope": "window", "order": 60 }, "gitlens.views.contributors.reveal": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to reveal contributors in the _Contributors_ view, otherwise they revealed in the _Repositories_ view", + "markdownDescription": "%gitlens.views.contributors.reveal.markdownDescription%", "scope": "window", "order": 20 } @@ -1765,20 +1765,20 @@ }, { "id": "search-compare-view", - "title": "Search & Compare View", + "title": "%gitlens.contributes.configuration.searchCompareView.title%", "order": 31, "properties": { "gitlens.views.searchAndCompare.pullRequests.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to query for pull requests associated with commits in the _Search & Compare_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.views.searchAndCompare.pullRequests.enabled.markdownDescription%", "scope": "window", "order": 10 }, "gitlens.views.searchAndCompare.pullRequests.showForCommits": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show pull requests (if any) associated with commits in the _Search & Compare_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "markdownDescription": "%gitlens.views.searchAndCompare.pullRequests.showForCommits.markdownDescription%", "scope": "window", "order": 11 }, @@ -1791,32 +1791,32 @@ "tree" ], "enumDescriptions": [ - "Automatically switches between displaying files as a `tree` or `list` based on the `#gitlens.views.searchAndCompare.files.threshold#` value and the number of files at each nesting level", - "Displays files as a list", - "Displays files as a tree" + "%gitlens.views.searchAndCompare.files.layout.auto.description%", + "%gitlens.views.searchAndCompare.files.layout.list.description%", + "%gitlens.views.searchAndCompare.files.layout.tree.description%" ], - "markdownDescription": "Specifies how the _Search & Compare_ view will display files", + "markdownDescription": "%gitlens.views.searchAndCompare.files.layout.markdownDescription%", "scope": "window", "order": 20 }, "gitlens.views.searchAndCompare.files.threshold": { "type": "number", "default": 5, - "markdownDescription": "Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the _Search & Compare_ view. Only applies when `#gitlens.views.searchAndCompare.files.layout#` is set to `auto`", + "markdownDescription": "%gitlens.views.searchAndCompare.files.threshold.markdownDescription%", "scope": "window", "order": 21 }, "gitlens.views.searchAndCompare.files.compact": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to compact (flatten) unnecessary file nesting in the _Search & Compare_ view. Only applies when `#gitlens.views.searchAndCompare.files.layout#` is set to `tree` or `auto`", + "markdownDescription": "%gitlens.views.searchAndCompare.files.compact.markdownDescription%", "scope": "window", "order": 22 }, "gitlens.views.searchAndCompare.avatars": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show avatar images instead of commit (or status) icons in the _Search & Compare_ view", + "markdownDescription": "%gitlens.views.searchAndCompare.avatars.markdownDescription%", "scope": "window", "order": 30 } @@ -1824,7 +1824,7 @@ }, { "id": "gutter-blame", - "title": "Gutter Blame", + "title": "%gitlens.contributes.configuration.gutterBlame.title%", "order": 100, "properties": { "gitlens.blame.toggleMode": { @@ -1835,24 +1835,24 @@ "window" ], "enumDescriptions": [ - "Toggles each file individually", - "Toggles the window, i.e. all files at once" + "%gitlens.blame.toggleMode.file.description%", + "%gitlens.blame.toggleMode.window.description%" ], - "markdownDescription": "Specifies how the gutter blame annotations will be toggled", + "markdownDescription": "%gitlens.blame.toggleMode.markdownDescription%", "scope": "window", "order": 10 }, "gitlens.blame.format": { "type": "string", "default": "${message|50?} ${agoOrDate|14-}", - "markdownDescription": "Specifies the format of the gutter blame annotations. See [_Commit Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#commit-tokens) in the GitLens docs. Date formatting is controlled by the `#gitlens.blame.dateFormat#` setting", + "markdownDescription": "%gitlens.blame.format.markdownDescription%", "scope": "window", "order": 20 }, "gitlens.blame.heatmap.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to provide a heatmap indicator in the gutter blame annotations", + "markdownDescription": "%gitlens.blame.heatmap.enabled.markdownDescription%", "scope": "window", "order": 30 }, @@ -1864,31 +1864,31 @@ "right" ], "enumDescriptions": [ - "Adds a heatmap indicator on the left edge of the gutter blame annotations", - "Adds a heatmap indicator on the right edge of the gutter blame annotations" + "%gitlens.blame.heatmap.location.left.description%", + "%gitlens.blame.heatmap.location.right.description%" ], - "markdownDescription": "Specifies where the heatmap indicators will be shown in the gutter blame annotations", + "markdownDescription": "%gitlens.blame.heatmap.location.markdownDescription%", "scope": "window", "order": 31 }, "gitlens.blame.avatars": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show avatar images in the gutter blame annotations", + "markdownDescription": "%gitlens.blame.avatars.markdownDescription%", "scope": "window", "order": 40 }, "gitlens.blame.compact": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to compact (deduplicate) matching adjacent gutter blame annotations", + "markdownDescription": "%gitlens.blame.compact.markdownDescription%", "scope": "window", "order": 50 }, "gitlens.blame.highlight.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to highlight lines associated with the current line", + "markdownDescription": "%gitlens.blame.highlight.enabled.markdownDescription%", "scope": "window", "order": 60 }, @@ -1907,22 +1907,22 @@ "overview" ], "enumDescriptions": [ - "Adds a gutter indicator", - "Adds a full-line highlight background color", - "Adds a decoration to the overview ruler (scroll bar)" + "%gitlens.blame.highlight.locations.gutter.description%", + "%gitlens.blame.highlight.locations.line.description%", + "%gitlens.blame.highlight.locations.overview.description%" ] }, "minItems": 1, "maxItems": 3, "uniqueItems": true, - "markdownDescription": "Specifies where the associated line highlights will be shown", + "markdownDescription": "%gitlens.blame.highlight.locations.markdownDescription%", "scope": "window", "order": 61 }, "gitlens.blame.separateLines": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether gutter blame annotations will be separated by a small gap", + "markdownDescription": "%gitlens.blame.separateLines.markdownDescription%", "scope": "window", "order": 70 }, @@ -1932,7 +1932,7 @@ "null" ], "default": null, - "markdownDescription": "Specifies how to format absolute dates (e.g. using the `${date}` token) in gutter blame annotations. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats", + "markdownDescription": "%gitlens.blame.dateFormat.markdownDescription%", "scope": "window", "order": 80 } @@ -1940,7 +1940,7 @@ }, { "id": "gutter-changes", - "title": "Gutter Changes", + "title": "%gitlens.contributes.configuration.gutterChanges.title%", "order": 101, "properties": { "gitlens.changes.toggleMode": { @@ -1951,10 +1951,10 @@ "window" ], "enumDescriptions": [ - "Toggles each file individually", - "Toggles the window, i.e. all files at once" + "%gitlens.changes.toggleMode.file.description%", + "%gitlens.changes.toggleMode.window.description%" ], - "markdownDescription": "Specifies how the gutter changes annotations will be toggled", + "markdownDescription": "%gitlens.changes.toggleMode.markdownDescription%", "scope": "window", "order": 10 }, @@ -1971,14 +1971,14 @@ "overview" ], "enumDescriptions": [ - "Adds a gutter indicator", - "Adds a decoration to the overview ruler (scroll bar)" + "%gitlens.changes.locations.gutter.description%", + "%gitlens.changes.locations.overview.description%" ] }, "minItems": 1, "maxItems": 2, "uniqueItems": true, - "markdownDescription": "Specifies where the indicators of the gutter changes annotations will be shown", + "markdownDescription": "%gitlens.changes.locations.markdownDescription%", "scope": "window", "order": 20 } @@ -1986,7 +1986,7 @@ }, { "id": "gutter-heatmap", - "title": "Gutter Heatmap", + "title": "%gitlens.contributes.configuration.gutterHeatmap.title%", "order": 102, "properties": { "gitlens.heatmap.toggleMode": { @@ -1997,10 +1997,10 @@ "window" ], "enumDescriptions": [ - "Toggles each file individually", - "Toggles the window, i.e. all files at once" + "%gitlens.heatmap.toggleMode.file.description%", + "%gitlens.heatmap.toggleMode.window.description%" ], - "markdownDescription": "Specifies how the gutter heatmap annotations will be toggled", + "markdownDescription": "%gitlens.heatmap.toggleMode.markdownDescription%", "scope": "window", "order": 10 }, @@ -2017,35 +2017,35 @@ "overview" ], "enumDescriptions": [ - "Adds a gutter indicator", - "Adds a decoration to the overview ruler (scroll bar)" + "%gitlens.heatmap.locations.gutter.description%", + "%gitlens.heatmap.locations.overview.description%" ] }, "minItems": 1, "maxItems": 2, "uniqueItems": true, - "markdownDescription": "Specifies where the indicators of the gutter heatmap annotations will be shown", + "markdownDescription": "%gitlens.heatmap.locations.markdownDescription%", "scope": "window", "order": 20 }, "gitlens.heatmap.ageThreshold": { "type": "number", "default": 90, - "markdownDescription": "Specifies the age of the most recent change (in days) after which the gutter heatmap annotations will be cold rather than hot (i.e. will use `#gitlens.heatmap.coldColor#` instead of `#gitlens.heatmap.hotColor#`)", + "markdownDescription": "%gitlens.heatmap.ageThreshold.markdownDescription%", "scope": "window", "order": 30 }, "gitlens.heatmap.coldColor": { "type": "string", "default": "#0a60f6", - "markdownDescription": "Specifies the base color of the gutter heatmap annotations when the most recent change is older (cold) than the `#gitlens.heatmap.ageThreshold#` value", + "markdownDescription": "%gitlens.heatmap.coldColor.markdownDescription%", "scope": "window", "order": 40 }, "gitlens.heatmap.hotColor": { "type": "string", "default": "#f66a0a", - "markdownDescription": "Specifies the base color of the gutter heatmap annotations when the most recent change is newer (hot) than the `#gitlens.heatmap.ageThreshold#` value", + "markdownDescription": "%gitlens.heatmap.hotColor.markdownDescription%", "scope": "window", "order": 50 } @@ -2053,7 +2053,7 @@ }, { "id": "git-command-palette", - "title": "Git Command Palette", + "title": "%gitlens.contributes.configuration.gitCommandPalette.title%", "order": 110, "properties": { "gitlens.gitCommands.sortBy": { @@ -2064,10 +2064,10 @@ "usage" ], "enumDescriptions": [ - "Sorts commands by name", - "Sorts commands by last used date" + "%gitlens.gitCommands.sortBy.name.description%", + "%gitlens.gitCommands.sortBy.usage.description%" ], - "markdownDescription": "Specifies how Git commands are sorted in the _Git Command Palette_", + "markdownDescription": "%gitlens.gitCommands.sortBy.markdownDescription%", "scope": "window", "order": 10 }, @@ -2103,39 +2103,39 @@ "tag-create:menu" ], "enumDescriptions": [ - "Skips branch create confirmations when run from a command, e.g. a view action", - "Skips branch create confirmations when run from the Git Command Palette", - "Skips co-author confirmations when run from a command, e.g. a view action", - "Skips co-author confirmations when run from the Git Command Palette", - "Skips fetch confirmations when run from a command, e.g. a view action", - "Skips fetch confirmations when run from the Git Command Palette", - "Skips pull confirmations when run from a command, e.g. a view action", - "Skips pull confirmations when run from the Git Command Palette", - "Skips push confirmations when run from a command, e.g. a view action", - "Skips push confirmations when run from the Git Command Palette", - "Skips stash apply confirmations when run from a command, e.g. a view action", - "Skips stash apply confirmations when run from the Git Command Palette", - "Skips stash pop confirmations when run from a command, e.g. a view action", - "Skips stash pop confirmations when run from the Git Command Palette", - "Skips stash push confirmations when run from a command, e.g. a view action", - "Skips stash push confirmations when run from the Git Command Palette", - "Skips switch confirmations when run from a command, e.g. a view action", - "Skips switch confirmations when run from the Git Command Palette", - "Skips tag create confirmations when run from a command, e.g. a view action", - "Skips tag create confirmations when run from the Git Command Palette" + "%gitlens.gitCommands.skipConfirmations.branchCreateCommand.description%", + "%gitlens.gitCommands.skipConfirmations.branchCreateMenu.description%", + "%gitlens.gitCommands.skipConfirmations.coauthorsCommand.description%", + "%gitlens.gitCommands.skipConfirmations.coauthorsMenu.description%", + "%gitlens.gitCommands.skipConfirmations.fetchCommand.description%", + "%gitlens.gitCommands.skipConfirmations.fetchMenu.description%", + "%gitlens.gitCommands.skipConfirmations.pullCommand.description%", + "%gitlens.gitCommands.skipConfirmations.pullMenu.description%", + "%gitlens.gitCommands.skipConfirmations.pushCommand.description%", + "%gitlens.gitCommands.skipConfirmations.pushMenu.description%", + "%gitlens.gitCommands.skipConfirmations.stashApplyCommand.description%", + "%gitlens.gitCommands.skipConfirmations.stashApplyMenu.description%", + "%gitlens.gitCommands.skipConfirmations.stashPopCommand.description%", + "%gitlens.gitCommands.skipConfirmations.stashPopMenu.description%", + "%gitlens.gitCommands.skipConfirmations.stashPushCommand.description%", + "%gitlens.gitCommands.skipConfirmations.stashPushMenu.description%", + "%gitlens.gitCommands.skipConfirmations.switchCommand.description%", + "%gitlens.gitCommands.skipConfirmations.switchMenu.description%", + "%gitlens.gitCommands.skipConfirmations.tagCreateCommand.description%", + "%gitlens.gitCommands.skipConfirmations.tagCreateMenu.description%" ] }, "minItems": 0, "maxItems": 14, "uniqueItems": true, - "markdownDescription": "Specifies which (and when) Git commands will skip the confirmation step, using the format: `git-command-name:(menu|command)`", + "markdownDescription": "%gitlens.gitCommands.skipConfirmations.markdownDescription%", "scope": "window", "order": 20 }, "gitlens.gitCommands.closeOnFocusOut": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to dismiss the _Git Command Palette_ when focus is lost (if not, press `ESC` to dismiss)", + "markdownDescription": "%gitlens.gitCommands.closeOnFocusOut.markdownDescription%", "scope": "window", "order": 30 }, @@ -2145,40 +2145,40 @@ "null" ], "default": null, - "markdownDescription": "Specifies whether to show the commit search results directly in the quick pick menu, in the Side Bar, or will be based on the context", + "markdownDescription": "%gitlens.gitCommands.search.showResultsInSideBar.markdownDescription%", "scope": "window", "order": 40 }, "gitlens.gitCommands.search.matchAll": { "type": "boolean", "default": false, - "markdownDescription": "Specifies whether to match all or any commit message search patterns", + "markdownDescription": "%gitlens.gitCommands.search.matchAll.markdownDescription%", "scope": "window", "order": 50 }, "gitlens.gitCommands.search.matchCase": { "type": "boolean", "default": false, - "markdownDescription": "Specifies whether to match commit search patterns with or without regard to casing", + "markdownDescription": "%gitlens.gitCommands.search.matchCase.markdownDescription%", "scope": "window", "order": 51 }, "gitlens.gitCommands.search.matchRegex": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to match commit search patterns using regular expressions", + "markdownDescription": "%gitlens.gitCommands.search.matchRegex.markdownDescription%", "scope": "window", "order": 52 }, "gitlens.gitCommands.search.showResultsInView": { - "deprecationMessage": "Deprecated. This setting has been renamed to gitlens.gitCommands.search.showResultsInSideBar", - "markdownDeprecationMessage": "Deprecated. This setting has been renamed to `#gitlens.gitCommands.search.showResultsInSideBar#`" + "deprecationMessage": "%gitlens.gitCommands.search.showResultsInView.deprecationMessage%", + "markdownDeprecationMessage": "%gitlens.gitCommands.search.showResultsInView.markdownDeprecationMessage%" } } }, { "id": "integrations", - "title": "Integrations", + "title": "%gitlens.contributes.configuration.integrations.title%", "order": 111, "properties": { "gitlens.autolinks": { @@ -2196,7 +2196,7 @@ "properties": { "prefix": { "type": "string", - "description": "Specifies the short prefix to use to generate autolinks for the external resource" + "description": "%gitlens.autolinks.prefix.description%" }, "title": { "type": [ @@ -2204,34 +2204,34 @@ "null" ], "default": null, - "description": "Specifies an optional title for the generated autolink. Use `` as the variable for the reference number" + "description": "%gitlens.autolinks.title.description%" }, "url": { "type": "string", - "description": "Specifies the url of the external resource you want to link to. Use `` as the variable for the reference number" + "description": "%gitlens.autolinks.url.description%" }, "alphanumeric": { "type": "boolean", - "description": "Specifies whether alphanumeric characters should be allowed in ``", + "description": "%gitlens.autolinks.alphanumeric.description%", "default": false }, "ignoreCase": { "type": "boolean", - "description": "Specifies whether case should be ignored when matching the prefix", + "description": "%gitlens.autolinks.ignoreCase.description%", "default": false } }, "additionalProperties": false }, "uniqueItems": true, - "markdownDescription": "Specifies autolinks to external resources in commit messages. Use `` as the variable for the reference number", + "markdownDescription": "%gitlens.autolinks.markdownDescription%", "scope": "window", "order": 10 }, "gitlens.integrations.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to enable rich integrations with any supported remote services", + "markdownDescription": "%gitlens.integrations.enabled.markdownDescription%", "scope": "window", "order": 20 }, @@ -2271,24 +2271,24 @@ "GitHub", "GitLab" ], - "description": "Specifies the type of the custom remote service" + "description": "%gitlens.remotes.type.description%" }, "domain": { "type": "string", - "description": "Specifies the domain name used to match this custom configuration to a Git remote" + "description": "%gitlens.remotes.domain.description%" }, "regex": { "type": "string", - "description": "Specifies a regular expression used to match this custom configuration to a Git remote and capture the \"domain name\" and \"path\"" + "description": "%gitlens.remotes.regex.description%" }, "name": { "type": "string", - "description": "Specifies an optional friendly name for the custom remote service" + "description": "%gitlens.remotes.name.description%" }, "protocol": { "type": "string", "default": "https", - "description": "Specifies an optional url protocol for the custom remote service" + "description": "%gitlens.remotes.protocol.description%" }, "urls": { "type": "object", @@ -2306,39 +2306,39 @@ "properties": { "repository": { "type": "string", - "markdownDescription": "Specifies the format of a repository url for the custom remote service\n\nAvailable tokens\\\n`${repo}` — repository path" + "markdownDescription": "%gitlens.remotes.urls.repository.markdownDescription%" }, "branches": { "type": "string", - "markdownDescription": "Specifies the format of a branches url for the custom remote service\n\nAvailable tokens\\\n`${repo}` — repository path\\\n`${branch}` — branch" + "markdownDescription": "%gitlens.remotes.urls.branches.markdownDescription%" }, "branch": { "type": "string", - "markdownDescription": "Specifies the format of a branch url for the custom remote service\n\nAvailable tokens\\\n`${repo}` — repository path\\\n`${branch}` — branch" + "markdownDescription": "%gitlens.remotes.urls.branch.markdownDescription%" }, "commit": { "type": "string", - "markdownDescription": "Specifies the format of a commit url for the custom remote service\n\nAvailable tokens\\\n`${repo}` — repository path\\\n`${id}` — commit SHA" + "markdownDescription": "%gitlens.remotes.urls.commit.markdownDescription%" }, "file": { "type": "string", - "markdownDescription": "Specifies the format of a file url for the custom remote service\n\nAvailable tokens\\\n`${repo}` — repository path\\\n`${file}` — file name\\\n`${line}` — formatted line information" + "markdownDescription": "%gitlens.remotes.urls.file.markdownDescription%" }, "fileInBranch": { "type": "string", - "markdownDescription": "Specifies the format of a branch file url for the custom remote service\n\nAvailable tokens\\\n`${repo}` — repository path\\\n`${file}` — file name\\\n`${branch}` — branch\\\n`${line}` — formatted line information" + "markdownDescription": "%gitlens.remotes.urls.fileInBranch.markdownDescription%" }, "fileInCommit": { "type": "string", - "markdownDescription": "Specifies the format of a commit file url for the custom remote service\n\nAvailable tokens\\\n`${repo}` — repository path\\\n`${file}` — file name\\\n`${id}` — commit SHA\\\n`${line}` — formatted line information" + "markdownDescription": "%gitlens.remotes.urls.fileInCommit.markdownDescription%" }, "fileLine": { "type": "string", - "markdownDescription": "Specifies the format of a line in a file url for the custom remote service\n\nAvailable tokens\\\n`${line}` — line" + "markdownDescription": "%gitlens.remotes.urls.fileLine.markdownDescription%" }, "fileRange": { "type": "string", - "markdownDescription": "Specifies the format of a range in a file url for the custom remote service\n\nAvailable tokens\\\n`${start}` — starting line\\\n`${end}` — ending line" + "markdownDescription": "%gitlens.remotes.urls.fileRange.markdownDescription%" } }, "additionalProperties": false @@ -2346,7 +2346,7 @@ } }, "uniqueItems": true, - "markdownDescription": "Specifies custom remote services to be matched with Git remotes to detect custom domains for built-in remote services or provide support for custom remote services", + "markdownDescription": "%gitlens.remotes.markdownDescription%", "scope": "resource", "order": 30 }, @@ -2361,21 +2361,21 @@ "enabled": { "type": "boolean", "default": true, - "description": "Specifies whether the partner integration should be shown" + "description": "%gitlens.partners.additionalProperties.enabled.description%" } }, "additionalProperties": true, - "description": "Specifies the configuration of a partner integration" + "description": "%gitlens.partners.additionalProperties.description%" }, "default": null, - "description": "Specifies the configuration of a partner integration", + "description": "%gitlens.partners.description%", "scope": "window", "order": 40 }, "gitlens.liveshare.allowGuestAccess": { "type": "boolean", "default": true, - "description": "Specifies whether to allow guest access to GitLens features when using Visual Studio Live Share", + "description": "%gitlens.liveshare.allowGuestAccess.description%", "scope": "window", "order": 50 } @@ -2383,33 +2383,33 @@ }, { "id": "terminal", - "title": "Terminal", + "title": "%gitlens.contributes.configuration.terminal.title%", "order": 112, "properties": { "gitlens.terminalLinks.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to enable terminal links — autolinks in the integrated terminal to quickly jump to more details for commits, branches, tags, and more", + "markdownDescription": "%gitlens.terminalLinks.enabled.markdownDescription%", "scope": "window" } } }, { "id": "visual-history", - "title": "Visual File History", + "title": "%gitlens.contributes.configuration.visualHistory.title%", "order": 113, "properties": { "gitlens.visualHistory.queryLimit": { "type": "number", "default": 20, - "markdownDescription": "Specifies the limit on the how many commits can be queried for statistics in the Visual File History, because of rate limits. Only applies to virtual workspaces.", + "markdownDescription": "%gitlens.visualHistory.queryLimit.markdownDescription%", "scope": "window" } } }, { "id": "date-times", - "title": "Date & Times", + "title": "%gitlens.contributes.configuration.dateTimes.title%", "order": 120, "properties": { "gitlens.defaultDateStyle": { @@ -2420,10 +2420,10 @@ "absolute" ], "enumDescriptions": [ - "e.g. 1 day ago", - "e.g. July 25th, 2018 7:18pm" + "%gitlens.defaultDateStyle.relative.description%", + "%gitlens.defaultDateStyle.absolute.description%" ], - "markdownDescription": "Specifies how dates will be displayed by default", + "markdownDescription": "%gitlens.defaultDateStyle.markdownDescription%", "scope": "window", "order": 10 }, @@ -2433,7 +2433,7 @@ "null" ], "default": null, - "markdownDescription": "Specifies how absolute dates will be formatted by default. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats", + "markdownDescription": "%gitlens.defaultDateFormat.markdownDescription%", "scope": "window", "order": 20 }, @@ -2443,7 +2443,7 @@ "null" ], "default": null, - "markdownDescription": "Specifies the locale, a [BCP 47 language tag](https://en.wikipedia.org/wiki/IETF_language_tag#List_of_major_primary_language_subtags), to use for date formatting, defaults to the VS Code locale. Use `system` to follow the current system locale, or choose a specific locale, e.g `en-US` — US English, `en-GB` — British English, `de-DE` — German, 'ja-JP = Japanese, etc.", + "markdownDescription": "%gitlens.defaultDateLocale.markdownDescription%", "scope": "window", "order": 21 }, @@ -2453,7 +2453,7 @@ "null" ], "default": null, - "markdownDescription": "Specifies how short absolute dates will be formatted by default. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats", + "markdownDescription": "%gitlens.defaultDateShortFormat.markdownDescription%", "scope": "window", "order": 22 }, @@ -2463,7 +2463,7 @@ "null" ], "default": null, - "markdownDescription": "Specifies how times will be formatted by default. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats", + "markdownDescription": "%gitlens.defaultTimeFormat.markdownDescription%", "scope": "window", "order": 30 }, @@ -2475,10 +2475,10 @@ "committed" ], "enumDescriptions": [ - "Uses the date when the changes were authored (i.e. originally written)", - "Uses the date when the changes were committed" + "%gitlens.defaultDateSource.authored.description%", + "%gitlens.defaultDateSource.committed.description%" ], - "markdownDescription": "Specifies whether commit dates should use the authored or committed date", + "markdownDescription": "%gitlens.defaultDateSource.markdownDescription%", "scope": "window", "order": 40 } @@ -2486,7 +2486,7 @@ }, { "id": "menus-toolbars", - "title": "Menus & Toolbars", + "title": "%gitlens.contributes.configuration.menusToolbars.title%", "order": 121, "properties": { "gitlens.menus": { @@ -2733,7 +2733,7 @@ "stash": true } }, - "markdownDescription": "Specifies which commands will be added to which menus", + "markdownDescription": "%gitlens.menus.markdownDescription%", "scope": "window", "order": 10 } @@ -2741,7 +2741,7 @@ }, { "id": "keyboard", - "title": "Keyboard Shortcuts", + "title": "%gitlens.contributes.configuration.keyboard.title%", "order": 122, "properties": { "gitlens.keymap": { @@ -2753,11 +2753,11 @@ "none" ], "enumDescriptions": [ - "Adds an alternate set of shortcut keys that start with `Alt` (⌥ on macOS)", - "Adds a chorded set of shortcut keys that start with `Ctrl+Alt+G` (`⌥⌘G` on macOS)", - "No shortcut keys will be added" + "%gitlens.keymap.alternate.description%", + "%gitlens.keymap.chorded.description%", + "%gitlens.keymap.none.description%" ], - "markdownDescription": "Specifies the keymap to use for GitLens shortcut keys", + "markdownDescription": "%gitlens.keymap.markdownDescription%", "scope": "window", "order": 10 } @@ -2765,13 +2765,13 @@ }, { "id": "modes", - "title": "Modes", + "title": "%gitlens.contributes.configuration.modes.title%", "order": 123, "properties": { "gitlens.mode.statusBar.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to provide the active GitLens mode in the status bar", + "markdownDescription": "%gitlens.mode.statusBar.enabled.markdownDescription%", "scope": "window", "order": 10 }, @@ -2783,16 +2783,16 @@ "right" ], "enumDescriptions": [ - "Aligns to the left", - "Aligns to the right" + "%gitlens.mode.statusBar.alignment.left.description%", + "%gitlens.mode.statusBar.alignment.right.description%" ], - "markdownDescription": "Specifies the active GitLens mode alignment in the status bar", + "markdownDescription": "%gitlens.mode.statusBar.alignment.markdownDescription%", "scope": "window", "order": 11 }, "gitlens.mode.active": { "type": "string", - "markdownDescription": "Specifies the active GitLens mode, if any", + "markdownDescription": "%gitlens.mode.active.markdownDescription%", "scope": "window", "order": 20 }, @@ -2804,31 +2804,31 @@ "properties": { "name": { "type": "string", - "description": "Specifies the friendly name of this user-defined mode" + "description": "%gitlens.modes.zen.name.description%" }, "statusBarItemName": { "type": "string", - "description": "Specifies the name shown in the status bar when this user-defined mode is active" + "description": "%gitlens.modes.zen.statusBarItemName.description%" }, "description": { "type": "string", - "description": "Specifies the description of this user-defined mode" + "description": "%gitlens.modes.zen.description.description%" }, "codeLens": { "type": "boolean", - "description": "Specifies whether to show any Git CodeLens when this user-defined mode is active" + "description": "%gitlens.modes.zen.codeLens.description%" }, "currentLine": { "type": "boolean", - "description": "Specifies whether to show a blame annotation for the current line when this user-defined mode is active" + "description": "%gitlens.modes.zen.currentLine.description%" }, "hovers": { "type": "boolean", - "description": "Specifies whether to show any hovers when this user-defined mode is active" + "description": "%gitlens.modes.zen.hovers.description%" }, "statusBar": { "type": "boolean", - "description": "Specifies whether to show blame information in the status bar when this user-defined mode is active" + "description": "%gitlens.modes.zen.statusBar.description%" } } }, @@ -2837,31 +2837,31 @@ "properties": { "name": { "type": "string", - "description": "Specifies the friendly name of this user-defined mode" + "description": "%gitlens.modes.review.name.description%" }, "statusBarItemName": { "type": "string", - "description": "Specifies the name shown in the status bar when this user-defined mode is active" + "description": "%gitlens.modes.review.statusBarItemName.description%" }, "description": { "type": "string", - "description": "Specifies the description of this user-defined mode" + "description": "%gitlens.modes.review.description.description%" }, "codeLens": { "type": "boolean", - "description": "Specifies whether to show any Git CodeLens when this user-defined mode is active" + "description": "%gitlens.modes.review.codeLens.description%" }, "currentLine": { "type": "boolean", - "description": "Specifies whether to show a blame annotation for the current line when this user-defined mode is active" + "description": "%gitlens.modes.review.currentLine.description%" }, "hovers": { "type": "boolean", - "description": "Specifies whether to show any hovers when this user-defined mode is active" + "description": "%gitlens.modes.review.hovers.description%" }, "statusBar": { "type": "boolean", - "description": "Specifies whether to show blame information in the status bar when this user-defined mode is active" + "description": "%gitlens.modes.review.statusBar.description%" } } } @@ -2874,15 +2874,15 @@ "properties": { "name": { "type": "string", - "description": "Specifies the friendly name of this user-defined mode" + "description": "%gitlens.modes.additionalProperties.name.description%" }, "statusBarItemName": { "type": "string", - "description": "Specifies the name shown in the status bar when this user-defined mode is active" + "description": "%gitlens.modes.additionalProperties.statusBarItemName.description%" }, "description": { "type": "string", - "description": "Specifies the description of this user-defined mode" + "description": "%gitlens.modes.additionalProperties.description.description%" }, "annotations": { "type": "string", @@ -2892,50 +2892,50 @@ "heatmap" ], "enumDescriptions": [ - "Shows the gutter blame annotations", - "Shows the gutter changes annotations", - "Shows the gutter heatmap annotations" + "%gitlens.modes.additionalProperties.annotations.blame.description%", + "%gitlens.modes.additionalProperties.annotations.changes.description%", + "%gitlens.modes.additionalProperties.annotations.heatmap.description%" ], - "description": "Specifies which (if any) file annotations will be shown when this user-defined mode is active" + "description": "%gitlens.modes.additionalProperties.annotations.description%" }, "codeLens": { "type": "boolean", - "description": "Specifies whether to show any Git CodeLens when this user-defined mode is active" + "description": "%gitlens.modes.additionalProperties.codeLens.description%" }, "currentLine": { "type": "boolean", - "description": "Specifies whether to show a blame annotation for the current line when this user-defined mode is active" + "description": "%gitlens.modes.additionalProperties.currentLine.description%" }, "hovers": { "type": "boolean", - "description": "Specifies whether to show any hovers when this user-defined mode is active" + "description": "%gitlens.modes.additionalProperties.hovers.description%" }, "statusBar": { "type": "boolean", - "description": "Specifies whether to show blame information in the status bar when this user-defined mode is active" + "description": "%gitlens.modes.additionalProperties.statusBar.description%" } } }, "default": { "zen": { - "name": "Zen", - "statusBarItemName": "Zen", - "description": "for a zen-like experience, disables many visual features", + "name": "%gitlens.modes.default.zen.name%", + "statusBarItemName": "%gitlens.modes.default.zen.statusBarItemName%", + "description": "%gitlens.modes.default.zen.description%", "codeLens": false, "currentLine": false, "hovers": false, "statusBar": false }, "review": { - "name": "Review", - "statusBarItemName": "Reviewing", - "description": "for reviewing code, enables many visual features", + "name": "%gitlens.modes.default.review.name%", + "statusBarItemName": "%gitlens.modes.default.review.statusBarItemName%", + "description": "%gitlens.modes.default.review.description%", "codeLens": true, "currentLine": true, "hovers": true } }, - "markdownDescription": "Specifies the user-defined GitLens modes", + "markdownDescription": "%gitlens.modes.markdownDescription%", "scope": "window", "order": 30 } @@ -2943,13 +2943,13 @@ }, { "id": "advanced", - "title": "Advanced", + "title": "%gitlens.contributes.configuration.advanced.title%", "order": 1000, "properties": { "gitlens.detectNestedRepositories": { "type": "boolean", "default": false, - "markdownDescription": "Specifies whether to attempt to detect nested repositories when opening files", + "markdownDescription": "%gitlens.detectNestedRepositories.markdownDescription%", "scope": "resource", "order": 0 }, @@ -2972,82 +2972,82 @@ "suppressCommitHasNoPreviousCommitWarning": { "type": "boolean", "default": false, - "description": "Commit Has No Previous Commit Warning" + "description": "%gitlens.advanced.messages.suppressCommitHasNoPreviousCommitWarning.description%" }, "suppressCommitNotFoundWarning": { "type": "boolean", "default": false, - "description": "Commit Not Found Warning" + "description": "%gitlens.advanced.messages.suppressCommitNotFoundWarning.description%" }, "suppressCreatePullRequestPrompt": { "type": "boolean", "default": false, - "description": "Create Pull Request Prompt" + "description": "%gitlens.advanced.messages.suppressCreatePullRequestPrompt.description%" }, "suppressDebugLoggingWarning": { "type": "boolean", "default": false, - "description": "Debug Logging Warning" + "description": "%gitlens.advanced.messages.suppressDebugLoggingWarning.description%" }, "suppressFileNotUnderSourceControlWarning": { "type": "boolean", "default": false, - "description": "File Not Under Source Control Warning" + "description": "%gitlens.advanced.messages.suppressFileNotUnderSourceControlWarning.description%" }, "suppressGitDisabledWarning": { "type": "boolean", "default": false, - "description": "Git Disabled Warning" + "description": "%gitlens.advanced.messages.suppressGitDisabledWarning.description%" }, "suppressGitMissingWarning": { "type": "boolean", "default": false, - "description": "Git Missing Warning" + "description": "%gitlens.advanced.messages.suppressGitMissingWarning.description%" }, "suppressGitVersionWarning": { "type": "boolean", "default": false, - "description": "Git Version Warning" + "description": "%gitlens.advanced.messages.suppressGitVersionWarning.description%" }, "suppressLineUncommittedWarning": { "type": "boolean", "default": false, - "description": "Line Uncommitted Warning" + "description": "%gitlens.advanced.messages.suppressLineUncommittedWarning.description%" }, "suppressNoRepositoryWarning": { "type": "boolean", "default": false, - "description": "No Repository Warning" + "description": "%gitlens.advanced.messages.suppressNoRepositoryWarning.description%" }, "suppressRebaseSwitchToTextWarning": { "type": "boolean", "default": false, - "description": "Rebase Switch To Text Warning" + "description": "%gitlens.advanced.messages.suppressRebaseSwitchToTextWarning.description%" } }, "additionalProperties": false, - "markdownDescription": "Specifies which messages should be suppressed", + "markdownDescription": "%gitlens.advanced.messages.markdownDescription%", "scope": "window", "order": 1 }, "gitlens.advanced.repositorySearchDepth": { "type": "number", - "default": null, - "markdownDescription": "Specifies how many folders deep to search for repositories. Defaults to `#git.repositoryScanMaxDepth#`", + "default": 1, + "markdownDescription": "%gitlens.advanced.repositorySearchDepth.markdownDescription%", "scope": "resource", "order": 10 }, "gitlens.advanced.abbreviatedShaLength": { "type": "number", "default": 7, - "markdownDescription": "Specifies the length of abbreviated commit SHAs", + "markdownDescription": "%gitlens.advanced.abbreviatedShaLength.markdownDescription%", "scope": "window", "order": 20 }, "gitlens.advanced.abbreviateShaOnCopy": { "type": "boolean", "default": false, - "markdownDescription": "Specifies whether to copy full or abbreviated commit SHAs to the clipboard. Abbreviates to the length of `#gitlens.advanced.abbreviatedShaLength#`.", + "markdownDescription": "%gitlens.advanced.abbreviateShaOnCopy.markdownDescription%", "scope": "window", "order": 21 }, @@ -3064,19 +3064,19 @@ "topo" ], "enumDescriptions": [ - "Shows commits in reverse chronological order", - "Shows commits in reverse chronological order of the commit timestamp", - "Shows commits in reverse chronological order of the author timestamp", - "Shows commits in reverse chronological order of the commit timestamp, but avoids intermixing multiple lines of history" + "%gitlens.advanced.commitOrdering.unspecified.description%", + "%gitlens.advanced.commitOrdering.date.description%", + "%gitlens.advanced.commitOrdering.authorDate.description%", + "%gitlens.advanced.commitOrdering.topo.description%" ], - "markdownDescription": "Specifies the order by which commits will be shown. If unspecified, commits will be shown in reverse chronological order", + "markdownDescription": "%gitlens.advanced.commitOrdering.markdownDescription%", "scope": "window", "order": 30 }, "gitlens.blame.ignoreWhitespace": { "type": "boolean", "default": false, - "markdownDescription": "Specifies whether to ignore whitespace when comparing revisions during blame operations", + "markdownDescription": "%gitlens.blame.ignoreWhitespace.markdownDescription%", "scope": "resource", "order": 40 }, @@ -3089,21 +3089,21 @@ "items": { "type": "string" }, - "markdownDescription": "Specifies additional arguments to pass to the `git blame` command", + "markdownDescription": "%gitlens.advanced.blame.customArguments.markdownDescription%", "scope": "resource", "order": 41 }, "gitlens.advanced.blame.delayAfterEdit": { "type": "number", "default": 5000, - "markdownDescription": "Specifies the time (in milliseconds) to wait before re-blaming an unsaved document after an edit. Use 0 to specify an infinite wait", + "markdownDescription": "%gitlens.advanced.blame.delayAfterEdit.markdownDescription%", "scope": "window", "order": 42 }, "gitlens.advanced.blame.sizeThresholdAfterEdit": { "type": "number", "default": 5000, - "markdownDescription": "Specifies the maximum document size (in lines) allowed to be re-blamed after an edit while still unsaved. Use 0 to specify no maximum", + "markdownDescription": "%gitlens.advanced.blame.sizeThresholdAfterEdit.markdownDescription%", "scope": "window", "order": 43 }, @@ -3113,7 +3113,7 @@ "null" ], "default": null, - "markdownDescription": "Specifies the amount (percent) of similarity a deleted and added file pair must have to be considered a rename", + "markdownDescription": "%gitlens.advanced.similarityThreshold.markdownDescription%", "scope": "window", "order": 50 }, @@ -3123,7 +3123,7 @@ "null" ], "default": null, - "markdownDescription": "Specifies an optional external diff tool to use when comparing files. Must be a configured [Git difftool](https://git-scm.com/docs/git-config#Documentation/git-config.txt-difftool).", + "markdownDescription": "%gitlens.advanced.externalDiffTool.markdownDescription%", "scope": "window", "order": 60 }, @@ -3133,67 +3133,67 @@ "null" ], "default": null, - "markdownDescription": "Specifies an optional external diff tool to use when comparing directories. Must be a configured [Git difftool](https://git-scm.com/docs/git-config#Documentation/git-config.txt-difftool).", + "markdownDescription": "%gitlens.advanced.externalDirectoryDiffTool.markdownDescription%", "scope": "window", "order": 61 }, "gitlens.advanced.quickPick.closeOnFocusOut": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to dismiss quick pick menus when focus is lost (if not, press `ESC` to dismiss)", + "markdownDescription": "%gitlens.advanced.quickPick.closeOnFocusOut.markdownDescription%", "scope": "window", "order": 70 }, "gitlens.advanced.maxListItems": { "type": "number", "default": 200, - "markdownDescription": "Specifies the maximum number of items to show in a list. Use 0 to specify no maximum", + "markdownDescription": "%gitlens.advanced.maxListItems.markdownDescription%", "scope": "window", "order": 80 }, "gitlens.advanced.maxSearchItems": { "type": "number", "default": 200, - "markdownDescription": "Specifies the maximum number of items to show in a search. Use 0 to specify no maximum", + "markdownDescription": "%gitlens.advanced.maxSearchItems.markdownDescription%", "scope": "window", "order": 81 }, "gitlens.advanced.caching.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether git output will be cached — changing the default is not recommended", + "markdownDescription": "%gitlens.advanced.caching.enabled.markdownDescription%", "scope": "window", "order": 90 }, "gitlens.debug": { "type": "boolean", "default": false, - "markdownDescription": "Specifies debug mode", + "markdownDescription": "%gitlens.debug.markdownDescription%", "scope": "window", "order": 100 }, "gitlens.advanced.useSymmetricDifferenceNotation": { - "deprecationMessage": "Deprecated. This setting is no longer used", - "markdownDescription": "Deprecated. This setting is no longer used" + "deprecationMessage": "%gitlens.advanced.useSymmetricDifferenceNotation.deprecationMessage%", + "markdownDescription": "%gitlens.advanced.useSymmetricDifferenceNotation.markdownDescription%" } } }, { "id": "general", - "title": "General", + "title": "%gitlens.contributes.configuration.general.title%", "order": 0, "properties": { "gitlens.showWelcomeOnInstall": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show the Welcome (Quick Setup) experience on first install", + "markdownDescription": "%gitlens.showWelcomeOnInstall.markdownDescription%", "scope": "window", "order": 10 }, "gitlens.showWhatsNewAfterUpgrades": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to show the What's New notification after upgrading to new feature releases", + "markdownDescription": "%gitlens.showWhatsNewAfterUpgrades.markdownDescription%", "scope": "window", "order": 20 }, @@ -3207,12 +3207,12 @@ "debug" ], "enumDescriptions": [ - "Logs nothing", - "Logs only errors", - "Logs all errors, warnings, and messages", - "Logs all errors, warnings, and messages with extra context useful for debugging" + "%gitlens.outputLevel.silent.description%", + "%gitlens.outputLevel.errors.description%", + "%gitlens.outputLevel.verbose.description%", + "%gitlens.outputLevel.debug.description%" ], - "markdownDescription": "Specifies how much (if any) output will be sent to the GitLens output channel", + "markdownDescription": "%gitlens.outputLevel.markdownDescription%", "scope": "window", "order": 30 }, @@ -3228,14 +3228,14 @@ "wavatar" ], "enumDescriptions": [ - "A geometric pattern", - "A simple, cartoon-style silhouetted outline of a person (does not vary by email hash)", - "A monster with different colors, faces, etc", - "8-bit arcade-style pixelated faces", - "A robot with different colors, faces, etc", - "A face with differing features and backgrounds" + "%gitlens.defaultGravatarsStyle.identicon.description%", + "%gitlens.defaultGravatarsStyle.mp.description%", + "%gitlens.defaultGravatarsStyle.monsterid.description%", + "%gitlens.defaultGravatarsStyle.retro.description%", + "%gitlens.defaultGravatarsStyle.robohash.description%", + "%gitlens.defaultGravatarsStyle.wavatar.description%" ], - "markdownDescription": "Specifies the style of the gravatar default (fallback) images", + "markdownDescription": "%gitlens.defaultGravatarsStyle.markdownDescription%", "scope": "window", "order": 40 }, @@ -3252,12 +3252,12 @@ "changes" ], "enumDescriptions": [ - "Shows a menu to choose which file annotations to toggle", - "Toggles gutter blame annotations", - "Toggles gutter heatmap annotations", - "Toggles gutter changes annotations" + "%gitlens.fileAnnotations.command.unspecified.description%", + "%gitlens.fileAnnotations.command.blame.description%", + "%gitlens.fileAnnotations.command.heatmap.description%", + "%gitlens.fileAnnotations.command.changes.description%" ], - "markdownDescription": "Specifies whether the file annotations button in the editor title shows a menu or immediately toggles the specified file annotations", + "markdownDescription": "%gitlens.fileAnnotations.command.markdownDescription%", "scope": "window", "order": 50 }, @@ -3280,38 +3280,38 @@ "null" ], "default": null, - "description": "Specifies the url of the proxy server to use" + "description": "%gitlens.proxy.url.description%" }, "strictSSL": { "type": "boolean", - "description": "Specifies whether the proxy server certificate should be verified against the list of supplied CAs", + "description": "%gitlens.proxy.strictSsl.description%", "default": true } }, "additionalProperties": false }, "uniqueItems": true, - "description": "Specifies the proxy configuration to use. If not specified, the proxy configuration will be determined based on VS Code or OS settings", + "description": "%gitlens.proxy.description%", "scope": "window", "order": 55 }, "gitlens.plusFeatures.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to enable GitLens+ features", + "markdownDescription": "%gitlens.plusFeatures.enabled.markdownDescription%", "scope": "window", "order": 60 }, "gitlens.virtualRepositories.enabled": { "type": "boolean", "default": true, - "markdownDescription": "Specifies whether to enable virtual repositories support", + "markdownDescription": "%gitlens.virtualRepositories.enabled.markdownDescription%", "scope": "window", "order": 70 }, "gitlens.insiders": { - "deprecationMessage": "Deprecated. Use the Insiders edition of GitLens instead", - "markdownDeprecationMessage": "Deprecated. Use the [Insiders edition](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens-insiders) of GitLens instead" + "deprecationMessage": "%gitlens.insiders.deprecationMessage%", + "markdownDeprecationMessage": "%gitlens.insiders.markdownDeprecationMessage%" } } } @@ -3386,7 +3386,7 @@ "colors": [ { "id": "gitlens.gutterBackgroundColor", - "description": "Specifies the background color of the gutter blame annotations", + "description": "%gitlens.gutterBackgroundColor.description%", "defaults": { "dark": "#FFFFFF13", "light": "#0000000C", @@ -3395,7 +3395,7 @@ }, { "id": "gitlens.gutterForegroundColor", - "description": "Specifies the foreground color of the gutter blame annotations", + "description": "%gitlens.gutterForegroundColor.description%", "defaults": { "dark": "#BEBEBE", "light": "#747474", @@ -3404,7 +3404,7 @@ }, { "id": "gitlens.gutterUncommittedForegroundColor", - "description": "Specifies the foreground color of an uncommitted line in the gutter blame annotations", + "description": "%gitlens.gutterUncommittedForegroundColor.description%", "defaults": { "dark": "#00BCF299", "light": "#00BCF299", @@ -3413,7 +3413,7 @@ }, { "id": "gitlens.trailingLineBackgroundColor", - "description": "Specifies the background color of the blame annotation for the current line", + "description": "%gitlens.trailingLineBackgroundColor.description%", "defaults": { "dark": "#00000000", "light": "#00000000", @@ -3422,7 +3422,7 @@ }, { "id": "gitlens.trailingLineForegroundColor", - "description": "Specifies the foreground color of the blame annotation for the current line", + "description": "%gitlens.trailingLineForegroundColor.description%", "defaults": { "dark": "#99999959", "light": "#99999959", @@ -3431,7 +3431,7 @@ }, { "id": "gitlens.lineHighlightBackgroundColor", - "description": "Specifies the background color of the associated line highlights in blame annotations", + "description": "%gitlens.lineHighlightBackgroundColor.description%", "defaults": { "dark": "#00BCF233", "light": "#00BCF233", @@ -3440,7 +3440,7 @@ }, { "id": "gitlens.lineHighlightOverviewRulerColor", - "description": "Specifies the overview ruler color of the associated line highlights in blame annotations", + "description": "%gitlens.lineHighlightOverviewRulerColor.description%", "defaults": { "dark": "#00BCF299", "light": "#00BCF299", @@ -3454,7 +3454,7 @@ "light": "#1a7f37", "highContrast": "#68ff79" }, - "description": "Specifies the icon color of open issues in the GitLens views" + "description": "%gitlens.openAutolinkedIssueIconColor.description%" }, { "id": "gitlens.closedAutolinkedIssueIconColor", @@ -3463,11 +3463,11 @@ "light": "#8250df", "highContrast": "#8945ff" }, - "description": "Specifies the icon color of closed issues in the GitLens views" + "description": "%gitlens.closedAutolinkedIssueIconColor.description%" }, { "id": "gitlens.closedPullRequestIconColor", - "description": "Specifies the icon color of closed pull requests in the GitLens views", + "description": "%gitlens.closedPullRequestIconColor.description%", "defaults": { "dark": "#f85149", "light": "#cf222e", @@ -3476,7 +3476,7 @@ }, { "id": "gitlens.openPullRequestIconColor", - "description": "Specifies the icon color of open pull requests in the GitLens views", + "description": "%gitlens.openPullRequestIconColor.description%", "defaults": { "dark": "#3fb950", "light": "#1a7f37", @@ -3485,7 +3485,7 @@ }, { "id": "gitlens.mergedPullRequestIconColor", - "description": "Specifies the icon color of merged pull requests in the GitLens views", + "description": "%gitlens.mergedPullRequestIconColor.description%", "defaults": { "dark": "#a371f7", "light": "#8250df", @@ -3494,7 +3494,7 @@ }, { "id": "gitlens.unpublishedChangesIconColor", - "description": "Specifies the icon color of unpublished changes in the GitLens views", + "description": "%gitlens.unpublishedChangesIconColor.description%", "defaults": { "dark": "#35b15e", "light": "#35b15e", @@ -3503,7 +3503,7 @@ }, { "id": "gitlens.unpublishedCommitIconColor", - "description": "Specifies the icon color of unpublished commits in the GitLens views", + "description": "%gitlens.unpublishedCommitIconColor.description%", "defaults": { "dark": "#35b15e", "light": "#35b15e", @@ -3512,7 +3512,7 @@ }, { "id": "gitlens.unpulledChangesIconColor", - "description": "Specifies the icon color of unpulled changes in the GitLens views", + "description": "%gitlens.unpulledChangesIconColor.description%", "defaults": { "dark": "#b15e35", "light": "#b15e35", @@ -3521,7 +3521,7 @@ }, { "id": "gitlens.decorations.addedForegroundColor", - "description": "Specifies the decoration foreground color of added files", + "description": "%gitlens.decorations.addedForegroundColor.description%", "defaults": { "light": "gitDecoration.addedResourceForeground", "dark": "gitDecoration.addedResourceForeground", @@ -3530,7 +3530,7 @@ }, { "id": "gitlens.decorations.copiedForegroundColor", - "description": "Specifies the decoration foreground color of copied files", + "description": "%gitlens.decorations.copiedForegroundColor.description%", "defaults": { "light": "gitDecoration.renamedResourceForeground", "dark": "gitDecoration.renamedResourceForeground", @@ -3539,7 +3539,7 @@ }, { "id": "gitlens.decorations.deletedForegroundColor", - "description": "Specifies the decoration foreground color of deleted files", + "description": "%gitlens.decorations.deletedForegroundColor.description%", "defaults": { "light": "gitDecoration.deletedResourceForeground", "dark": "gitDecoration.deletedResourceForeground", @@ -3548,7 +3548,7 @@ }, { "id": "gitlens.decorations.ignoredForegroundColor", - "description": "Specifies the decoration foreground color of ignored files", + "description": "%gitlens.decorations.ignoredForegroundColor.description%", "defaults": { "light": "gitDecoration.ignoredResourceForeground", "dark": "gitDecoration.ignoredResourceForeground", @@ -3557,7 +3557,7 @@ }, { "id": "gitlens.decorations.modifiedForegroundColor", - "description": "Specifies the decoration foreground color of modified files", + "description": "%gitlens.decorations.modifiedForegroundColor.description%", "defaults": { "light": "gitDecoration.modifiedResourceForeground", "dark": "gitDecoration.modifiedResourceForeground", @@ -3566,7 +3566,7 @@ }, { "id": "gitlens.decorations.untrackedForegroundColor", - "description": "Specifies the decoration foreground color of untracked files", + "description": "%gitlens.decorations.untrackedForegroundColor.description%", "defaults": { "light": "gitDecoration.untrackedResourceForeground", "dark": "gitDecoration.untrackedResourceForeground", @@ -3575,7 +3575,7 @@ }, { "id": "gitlens.decorations.renamedForegroundColor", - "description": "Specifies the decoration foreground color of renamed files", + "description": "%gitlens.decorations.renamedForegroundColor.description%", "defaults": { "light": "gitDecoration.renamedResourceForeground", "dark": "gitDecoration.renamedResourceForeground", @@ -3584,7 +3584,7 @@ }, { "id": "gitlens.decorations.branchAheadForegroundColor", - "description": "Specifies the decoration foreground color of branches that are ahead of their upstream", + "description": "%gitlens.decorations.branchAheadForegroundColor.description%", "defaults": { "dark": "#35b15e", "light": "#35b15e", @@ -3593,7 +3593,7 @@ }, { "id": "gitlens.decorations.branchBehindForegroundColor", - "description": "Specifies the decoration foreground color of branches that are behind their upstream", + "description": "%gitlens.decorations.branchBehindForegroundColor.description%", "defaults": { "dark": "#b15e35", "light": "#b15e35", @@ -3602,7 +3602,7 @@ }, { "id": "gitlens.decorations.branchDivergedForegroundColor", - "description": "Specifies the decoration foreground color of branches that are both ahead and behind their upstream", + "description": "%gitlens.decorations.branchDivergedForegroundColor.description%", "defaults": { "dark": "#D8AF1B", "light": "#D8AF1B", @@ -3611,7 +3611,7 @@ }, { "id": "gitlens.decorations.branchUpToDateForegroundColor", - "description": "Specifies the decoration foreground color of branches that are up to date with their upstream", + "description": "%gitlens.decorations.branchUpToDateForegroundColor.description%", "defaults": { "dark": "sideBar.foreground", "light": "sideBar.foreground", @@ -3620,7 +3620,7 @@ }, { "id": "gitlens.decorations.branchUnpublishedForegroundColor", - "description": "Specifies the decoration foreground color of branches that are not yet published to an upstream", + "description": "%gitlens.decorations.branchUnpublishedForegroundColor.description%", "defaults": { "dark": "#35b15e", "light": "#35b15e", @@ -3629,7 +3629,7 @@ }, { "id": "gitlens.decorations.branchMissingUpstreamForegroundColor", - "description": "Specifies the decoration foreground color of branches that have a missing upstream", + "description": "%gitlens.decorations.branchMissingUpstreamForegroundColor.description%", "defaults": { "light": "#ad0707", "dark": "#c74e39", @@ -3638,7 +3638,7 @@ }, { "id": "gitlens.decorations.worktreeView.hasUncommittedChangesForegroundColor", - "description": "Specifies the decoration foreground color for worktrees that have uncommitted changes", + "description": "%gitlens.decorations.worktreeView.hasUncommittedChangesForegroundColor.description%", "defaults": { "light": "#895503", "dark": "#E2C08D", @@ -3649,136 +3649,136 @@ "commands": [ { "command": "gitlens.plus.learn", - "title": "Learn about GitLens+ Features", - "category": "GitLens+" + "title": "%gitlens.plus.learn.title%", + "category": "%gitlens.commands.category.gitlensPlus.title%" }, { "command": "gitlens.plus.loginOrSignUp", - "title": "Sign In to GitLens+...", - "category": "GitLens+" + "title": "%gitlens.plus.loginOrSignUp.title%", + "category": "%gitlens.commands.category.gitlensPlus.title%" }, { "command": "gitlens.plus.logout", - "title": "Sign out of GitLens+", - "category": "GitLens+" + "title": "%gitlens.plus.logout.title%", + "category": "%gitlens.commands.category.gitlensPlus.title%" }, { "command": "gitlens.plus.startPreviewTrial", - "title": "Try GitLens+ Features Now", - "category": "GitLens+" + "title": "%gitlens.plus.startPreviewTrial.title%", + "category": "%gitlens.commands.category.gitlensPlus.title%" }, { "command": "gitlens.plus.manage", - "title": "Manage Your GitLens+ Account...", - "category": "GitLens+" + "title": "%gitlens.plus.manage.title%", + "category": "%gitlens.commands.category.gitlensPlus.title%" }, { "command": "gitlens.plus.purchase", - "title": "Upgrade Your GitLens+ Account...", - "category": "GitLens+" + "title": "%gitlens.plus.purchase.title%", + "category": "%gitlens.commands.category.gitlensPlus.title%" }, { "command": "gitlens.plus.hide", - "title": "Hide GitLens+ Features", - "category": "GitLens+" + "title": "%gitlens.plus.hide.title%", + "category": "%gitlens.commands.category.gitlensPlus.title%" }, { "command": "gitlens.plus.restore", - "title": "Restore GitLens+ Features", - "category": "GitLens+" + "title": "%gitlens.plus.restore.title%", + "category": "%gitlens.commands.category.gitlensPlus.title%" }, { "command": "gitlens.plus.reset", - "title": "Reset", - "category": "GitLens+" + "title": "%gitlens.plus.reset.title%", + "category": "%gitlens.commands.category.gitlensPlus.title%" }, { "command": "gitlens.getStarted", - "title": "Get Started", - "category": "GitLens" + "title": "%gitlens.getStarted.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showSettingsPage", - "title": "Open Settings", - "category": "GitLens", + "title": "%gitlens.showSettingsPage.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(gear)" }, { "command": "gitlens.showSettingsPage#views", - "title": "Open Settings", - "category": "GitLens", + "title": "%gitlens.showSettingsPage.views.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(gear)" }, { "command": "gitlens.showSettingsPage#branches-view", - "title": "Open View Settings", - "category": "GitLens", + "title": "%gitlens.showSettingsPage.branchesView.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(gear)" }, { "command": "gitlens.showSettingsPage#commits-view", - "title": "Open View Settings", - "category": "GitLens", + "title": "%gitlens.showSettingsPage.commitsView.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(gear)" }, { "command": "gitlens.showSettingsPage#contributors-view", - "title": "Open View Settings", - "category": "GitLens", + "title": "%gitlens.showSettingsPage.contributorsView.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(gear)" }, { "command": "gitlens.showSettingsPage#file-history-view", - "title": "Open View Settings", - "category": "GitLens", + "title": "%gitlens.showSettingsPage.fileHistoryView.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(gear)" }, { "command": "gitlens.showSettingsPage#line-history-view", - "title": "Open View Settings", - "category": "GitLens", + "title": "%gitlens.showSettingsPage.lineHistoryView.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(gear)" }, { "command": "gitlens.showSettingsPage#remotes-view", - "title": "Open View Settings", - "category": "GitLens", + "title": "%gitlens.showSettingsPage.remotesView.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(gear)" }, { "command": "gitlens.showSettingsPage#repositories-view", - "title": "Open View Settings", - "category": "GitLens", + "title": "%gitlens.showSettingsPage.repositoriesView.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(gear)" }, { "command": "gitlens.showSettingsPage#search-compare-view", - "title": "Open View Settings", - "category": "GitLens", + "title": "%gitlens.showSettingsPage.searchCompareView.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(gear)" }, { "command": "gitlens.showSettingsPage#stashes-view", - "title": "Open View Settings", - "category": "GitLens", + "title": "%gitlens.showSettingsPage.stashesView.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(gear)" }, { "command": "gitlens.showSettingsPage#tags-view", - "title": "Open View Settings", - "category": "GitLens", + "title": "%gitlens.showSettingsPage.tagsView.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(gear)" }, { "command": "gitlens.showSettingsPage#worktrees-view", - "title": "Open View Settings", - "category": "GitLens", + "title": "%gitlens.showSettingsPage.worktreesView.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(gear)" }, { "command": "gitlens.showTimelinePage", - "title": "Open Visual File History of Active File", - "category": "GitLens", + "title": "%gitlens.showTimelinePage.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-history.svg", "light": "images/light/icon-history.svg" @@ -3786,112 +3786,112 @@ }, { "command": "gitlens.refreshTimelinePage", - "title": "Refresh", - "category": "GitLens", + "title": "%gitlens.refreshTimelinePage.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(refresh)" }, { "command": "gitlens.showWelcomePage", - "title": "Welcome (Quick Setup)", - "category": "GitLens" + "title": "%gitlens.showWelcomePage.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showBranchesView", - "title": "Show Branches View", - "category": "GitLens" + "title": "%gitlens.showBranchesView.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showCommitsView", - "title": "Show Commits View", - "category": "GitLens" + "title": "%gitlens.showCommitsView.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showContributorsView", - "title": "Show Contributors View", - "category": "GitLens" + "title": "%gitlens.showContributorsView.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showFileHistoryView", - "title": "Show File History View", - "category": "GitLens" + "title": "%gitlens.showFileHistoryView.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showHomeView", - "title": "Show Home View", - "category": "GitLens" + "title": "%gitlens.showHomeView.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showLineHistoryView", - "title": "Show Line History View", - "category": "GitLens" + "title": "%gitlens.showLineHistoryView.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showRemotesView", - "title": "Show Remotes View", - "category": "GitLens" + "title": "%gitlens.showRemotesView.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showRepositoriesView", - "title": "Show Repositories View", - "category": "GitLens" + "title": "%gitlens.showRepositoriesView.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showSearchAndCompareView", - "title": "Show Search And Compare Commits View", - "category": "GitLens" + "title": "%gitlens.showSearchAndCompareView.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showStashesView", - "title": "Show Stashes View", - "category": "GitLens" + "title": "%gitlens.showStashesView.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showTagsView", - "title": "Show Tags View", - "category": "GitLens" + "title": "%gitlens.showTagsView.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showTimelineView", - "title": "Show Visual File History View", - "category": "GitLens" + "title": "%gitlens.showTimelineView.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showWorktreesView", - "title": "Show Worktrees View", - "category": "GitLens" + "title": "%gitlens.showWorktreesView.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.compareWith", - "title": "Compare References...", - "category": "GitLens", + "title": "%gitlens.compareWith.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(compare-changes)" }, { "command": "gitlens.compareHeadWith", - "title": "Compare HEAD with...", - "category": "GitLens", + "title": "%gitlens.compareHeadWith.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(compare-changes)" }, { "command": "gitlens.compareWorkingWith", - "title": "Compare Working Tree with...", - "category": "GitLens", + "title": "%gitlens.compareWorkingWith.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(compare-changes)" }, { "command": "gitlens.diffDirectory", - "title": "Open Directory Compare (difftool) with...", - "category": "GitLens" + "title": "%gitlens.diffDirectory.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.diffDirectoryWithHead", - "title": "Open Directory Compare (difftool)", - "category": "GitLens" + "title": "%gitlens.diffDirectoryWithHead.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.diffWithNext", - "title": "Open Changes with Next Revision", - "category": "GitLens", + "title": "%gitlens.diffWithNext.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-next-commit.svg", "light": "images/light/icon-next-commit.svg" @@ -3900,8 +3900,8 @@ }, { "command": "gitlens.diffWithNextInDiffLeft", - "title": "Open Changes with Next Revision", - "category": "GitLens", + "title": "%gitlens.diffWithNextInDiffLeft.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-next-commit.svg", "light": "images/light/icon-next-commit.svg" @@ -3910,8 +3910,8 @@ }, { "command": "gitlens.diffWithNextInDiffRight", - "title": "Open Changes with Next Revision", - "category": "GitLens", + "title": "%gitlens.diffWithNextInDiffRight.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-next-commit.svg", "light": "images/light/icon-next-commit.svg" @@ -3920,8 +3920,8 @@ }, { "command": "gitlens.diffWithPrevious", - "title": "Open Changes with Previous Revision", - "category": "GitLens", + "title": "%gitlens.diffWithPrevious.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-prev-commit.svg", "light": "images/light/icon-prev-commit.svg" @@ -3929,8 +3929,8 @@ }, { "command": "gitlens.diffWithPreviousInDiffLeft", - "title": "Open Changes with Previous Revision", - "category": "GitLens", + "title": "%gitlens.diffWithPreviousInDiffLeft.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-prev-commit.svg", "light": "images/light/icon-prev-commit.svg" @@ -3938,8 +3938,8 @@ }, { "command": "gitlens.diffWithPreviousInDiffRight", - "title": "Open Changes with Previous Revision", - "category": "GitLens", + "title": "%gitlens.diffWithPreviousInDiffRight.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-prev-commit.svg", "light": "images/light/icon-prev-commit.svg" @@ -3947,13 +3947,13 @@ }, { "command": "gitlens.diffLineWithPrevious", - "title": "Open Line Changes with Previous Revision", - "category": "GitLens" + "title": "%gitlens.diffLineWithPrevious.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.diffWithRevision", - "title": "Open Changes with Revision...", - "category": "GitLens", + "title": "%gitlens.diffWithRevision.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-prev-commit-menu.svg", "light": "images/light/icon-prev-commit-menu.svg" @@ -3961,13 +3961,13 @@ }, { "command": "gitlens.diffWithRevisionFrom", - "title": "Open Changes with Branch or Tag...", - "category": "GitLens" + "title": "%gitlens.diffWithRevisionFrom.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.diffWithWorking", - "title": "Open Changes with Working File", - "category": "GitLens", + "title": "%gitlens.diffWithWorking.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-compare-ref-working.svg", "light": "images/light/icon-compare-ref-working.svg" @@ -3975,8 +3975,8 @@ }, { "command": "gitlens.diffWithWorkingInDiffLeft", - "title": "Open Changes with Working File", - "category": "GitLens", + "title": "%gitlens.diffWithWorkingInDiffLeft.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-compare-ref-working.svg", "light": "images/light/icon-compare-ref-working.svg" @@ -3984,8 +3984,8 @@ }, { "command": "gitlens.diffWithWorkingInDiffRight", - "title": "Open Changes with Working File", - "category": "GitLens", + "title": "%gitlens.diffWithWorkingInDiffRight.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-compare-ref-working.svg", "light": "images/light/icon-compare-ref-working.svg" @@ -3993,23 +3993,23 @@ }, { "command": "gitlens.diffLineWithWorking", - "title": "Open Line Changes with Working File", - "category": "GitLens" + "title": "%gitlens.diffLineWithWorking.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.disableRebaseEditor", - "title": "Disable Interactive Rebase Editor", - "category": "GitLens" + "title": "%gitlens.disableRebaseEditor.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.enableRebaseEditor", - "title": "Enable Interactive Rebase Editor", - "category": "GitLens" + "title": "%gitlens.enableRebaseEditor.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.toggleFileBlame", - "title": "Toggle File Blame", - "category": "GitLens", + "title": "%gitlens.toggleFileBlame.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-git.svg", "light": "images/light/icon-git.svg" @@ -4017,8 +4017,8 @@ }, { "command": "gitlens.toggleFileBlameInDiffLeft", - "title": "Toggle File Blame", - "category": "GitLens", + "title": "%gitlens.toggleFileBlameInDiffLeft.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-git.svg", "light": "images/light/icon-git.svg" @@ -4026,8 +4026,8 @@ }, { "command": "gitlens.toggleFileBlameInDiffRight", - "title": "Toggle File Blame", - "category": "GitLens", + "title": "%gitlens.toggleFileBlameInDiffRight.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-git.svg", "light": "images/light/icon-git.svg" @@ -4035,8 +4035,8 @@ }, { "command": "gitlens.clearFileAnnotations", - "title": "Clear File Annotations", - "category": "GitLens", + "title": "%gitlens.clearFileAnnotations.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-git-orange.svg", "light": "images/light/icon-git-orange.svg" @@ -4044,8 +4044,8 @@ }, { "command": "gitlens.computingFileAnnotations", - "title": "Computing File Annotations...", - "category": "GitLens", + "title": "%gitlens.computingFileAnnotations.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-git-progress.svg", "light": "images/light/icon-git-progress.svg" @@ -4053,8 +4053,8 @@ }, { "command": "gitlens.toggleFileHeatmap", - "title": "Toggle File Heatmap", - "category": "GitLens", + "title": "%gitlens.toggleFileHeatmap.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-git.svg", "light": "images/light/icon-git.svg" @@ -4062,8 +4062,8 @@ }, { "command": "gitlens.toggleFileHeatmapInDiffLeft", - "title": "Toggle File Heatmap", - "category": "GitLens", + "title": "%gitlens.toggleFileHeatmapInDiffLeft.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-git.svg", "light": "images/light/icon-git.svg" @@ -4071,8 +4071,8 @@ }, { "command": "gitlens.toggleFileHeatmapInDiffRight", - "title": "Toggle File Heatmap", - "category": "GitLens", + "title": "%gitlens.toggleFileHeatmapInDiffRight.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-git.svg", "light": "images/light/icon-git.svg" @@ -4080,8 +4080,8 @@ }, { "command": "gitlens.toggleFileChanges", - "title": "Toggle File Changes", - "category": "GitLens", + "title": "%gitlens.toggleFileChanges.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-git.svg", "light": "images/light/icon-git.svg" @@ -4089,8 +4089,8 @@ }, { "command": "gitlens.toggleFileChangesOnly", - "title": "Toggle File Changes", - "category": "GitLens", + "title": "%gitlens.toggleFileChangesOnly.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-git.svg", "light": "images/light/icon-git.svg" @@ -4098,139 +4098,139 @@ }, { "command": "gitlens.toggleLineBlame", - "title": "Toggle Line Blame", - "category": "GitLens" + "title": "%gitlens.toggleLineBlame.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.toggleCodeLens", - "title": "Toggle Git CodeLens", - "category": "GitLens" + "title": "%gitlens.toggleCodeLens.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.gitCommands", - "title": "Git Command Palette", - "category": "GitLens" + "title": "%gitlens.gitCommands.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.gitCommands.branch", - "title": "Git Branch...", - "category": "GitLens" + "title": "%gitlens.gitCommands.branch.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.gitCommands.cherryPick", - "title": "Git Cherry Pick...", - "category": "GitLens" + "title": "%gitlens.gitCommands.cherryPick.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.gitCommands.merge", - "title": "Git Merge...", - "category": "GitLens" + "title": "%gitlens.gitCommands.merge.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.gitCommands.rebase", - "title": "Git Rebase...", - "category": "GitLens" + "title": "%gitlens.gitCommands.rebase.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.gitCommands.reset", - "title": "Git Reset...", - "category": "GitLens" + "title": "%gitlens.gitCommands.reset.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.gitCommands.revert", - "title": "Git Revert...", - "category": "GitLens" + "title": "%gitlens.gitCommands.revert.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.gitCommands.switch", - "title": "Git Switch...", - "category": "GitLens" + "title": "%gitlens.gitCommands.switch.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.gitCommands.tag", - "title": "Git Tag...", - "category": "GitLens" + "title": "%gitlens.gitCommands.tag.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.gitCommands.worktree", - "title": "Git Worktree...", - "category": "GitLens" + "title": "%gitlens.gitCommands.worktree.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.switchMode", - "title": "Switch Mode", - "category": "GitLens" + "title": "%gitlens.switchMode.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.toggleReviewMode", - "title": "Toggle Review Mode", - "category": "GitLens" + "title": "%gitlens.toggleReviewMode.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.toggleZenMode", - "title": "Toggle Zen Mode", - "category": "GitLens" + "title": "%gitlens.toggleZenMode.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.setViewsLayout", - "title": "Set Views Layout", - "category": "GitLens" + "title": "%gitlens.setViewsLayout.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showCommitSearch", - "title": "Search Commits", - "category": "GitLens", + "title": "%gitlens.showCommitSearch.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(search)" }, { "command": "gitlens.showLastQuickPick", - "title": "Show Last Opened Quick Pick", - "category": "GitLens" + "title": "%gitlens.showLastQuickPick.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.revealCommitInView", - "title": "Reveal Commit in Side Bar", - "category": "GitLens" + "title": "%gitlens.revealCommitInView.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showCommitInView", - "title": "Search for Commit in Side Bar", - "category": "GitLens" + "title": "%gitlens.showCommitInView.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showCommitsInView", - "title": "Search for Commits within Selection", - "category": "GitLens" + "title": "%gitlens.showCommitsInView.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showFileHistoryInView", - "title": "Open File History", - "category": "GitLens" + "title": "%gitlens.showFileHistoryInView.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.openFileHistory", - "title": "Open File History", - "category": "GitLens" + "title": "%gitlens.openFileHistory.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.openFolderHistory", - "title": "Open Folder History", - "category": "GitLens" + "title": "%gitlens.openFolderHistory.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showQuickCommitDetails", - "title": "Show Commit", - "category": "GitLens" + "title": "%gitlens.showQuickCommitDetails.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showQuickCommitFileDetails", - "title": "Show Line Commit", - "category": "GitLens" + "title": "%gitlens.showQuickCommitFileDetails.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showQuickRevisionDetails", - "title": "Show Revision Commit", - "category": "GitLens", + "title": "%gitlens.showQuickRevisionDetails.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-commit-horizontal.svg", "light": "images/light/icon-commit-horizontal.svg" @@ -4239,8 +4239,8 @@ }, { "command": "gitlens.showQuickRevisionDetailsInDiffLeft", - "title": "Show Revision Commit", - "category": "GitLens", + "title": "%gitlens.showQuickRevisionDetailsInDiffLeft.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-commit-horizontal.svg", "light": "images/light/icon-commit-horizontal.svg" @@ -4249,8 +4249,8 @@ }, { "command": "gitlens.showQuickRevisionDetailsInDiffRight", - "title": "Show Revision Commit", - "category": "GitLens", + "title": "%gitlens.showQuickRevisionDetailsInDiffRight.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-commit-horizontal.svg", "light": "images/light/icon-commit-horizontal.svg" @@ -4259,50 +4259,50 @@ }, { "command": "gitlens.showQuickFileHistory", - "title": "Show File History", - "category": "GitLens" + "title": "%gitlens.showQuickFileHistory.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.quickOpenFileHistory", - "title": "Quick Open File History", - "category": "GitLens" + "title": "%gitlens.quickOpenFileHistory.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showQuickBranchHistory", - "title": "Show Branch History", - "category": "GitLens" + "title": "%gitlens.showQuickBranchHistory.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showQuickRepoHistory", - "title": "Show Current Branch History", - "category": "GitLens" + "title": "%gitlens.showQuickRepoHistory.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showQuickRepoStatus", - "title": "Show Repository Status", - "category": "GitLens" + "title": "%gitlens.showQuickRepoStatus.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.showQuickStashList", - "title": "Show Stashes", - "category": "GitLens" + "title": "%gitlens.showQuickStashList.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.addAuthors", - "title": "Add Co-authors", - "category": "GitLens", + "title": "%gitlens.addAuthors.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(person-add)" }, { "command": "gitlens.connectRemoteProvider", - "title": "Connect to Remote", - "category": "GitLens", + "title": "%gitlens.connectRemoteProvider.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(plug)" }, { "command": "gitlens.disconnectRemoteProvider", - "title": "Disconnect from Remote", - "category": "GitLens", + "title": "%gitlens.disconnectRemoteProvider.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-unplug.svg", "light": "images/light/icon-unplug.svg" @@ -4310,185 +4310,185 @@ }, { "command": "gitlens.copyCurrentBranch", - "title": "Copy Current Branch Name", - "category": "GitLens", + "title": "%gitlens.copyCurrentBranch.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(copy)" }, { "command": "gitlens.copyMessageToClipboard", - "title": "Copy Message", - "category": "GitLens", + "title": "%gitlens.copyMessageToClipboard.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(copy)" }, { "command": "gitlens.copyShaToClipboard", - "title": "Copy SHA", - "category": "GitLens", + "title": "%gitlens.copyShaToClipboard.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(copy)" }, { "command": "gitlens.closeUnchangedFiles", - "title": "Close Unchanged Files", - "category": "GitLens" + "title": "%gitlens.closeUnchangedFiles.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.openChangedFiles", - "title": "Open Changed Files", - "category": "GitLens" + "title": "%gitlens.openChangedFiles.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.openBranchesOnRemote", - "title": "Open Branches on Remote", - "category": "GitLens", + "title": "%gitlens.openBranchesOnRemote.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(globe)" }, { "command": "gitlens.copyRemoteBranchesUrl", - "title": "Copy Remote Branches Url", - "category": "GitLens", + "title": "%gitlens.copyRemoteBranchesUrl.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(copy)" }, { "command": "gitlens.openBranchOnRemote", - "title": "Open Branch on Remote", - "category": "GitLens", + "title": "%gitlens.openBranchOnRemote.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(globe)" }, { "command": "gitlens.copyRemoteBranchUrl", - "title": "Copy Remote Branch Url", - "category": "GitLens", + "title": "%gitlens.copyRemoteBranchUrl.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(copy)" }, { "command": "gitlens.openCommitOnRemote", - "title": "Open Commit on Remote", - "category": "GitLens", + "title": "%gitlens.openCommitOnRemote.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(globe)" }, { "command": "gitlens.copyRemoteCommitUrl", - "title": "Copy Remote Commit Url", - "category": "GitLens", + "title": "%gitlens.copyRemoteCommitUrl.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(copy)" }, { "command": "gitlens.openComparisonOnRemote", - "title": "Open Comparison on Remote", - "category": "GitLens", + "title": "%gitlens.openComparisonOnRemote.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(globe)" }, { "command": "gitlens.copyRemoteComparisonUrl", - "title": "Copy Remote Comparison Url", - "category": "GitLens", + "title": "%gitlens.copyRemoteComparisonUrl.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(copy)" }, { "command": "gitlens.openFileFromRemote", - "title": "Open File from Remote", - "category": "GitLens" + "title": "%gitlens.openFileFromRemote.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.openFileOnRemote", - "title": "Open File on Remote", - "category": "GitLens", + "title": "%gitlens.openFileOnRemote.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(globe)" }, { "command": "gitlens.copyRemoteFileUrlToClipboard", - "title": "Copy Remote File Url", - "category": "GitLens", + "title": "%gitlens.copyRemoteFileUrlToClipboard.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(copy)" }, { "command": "gitlens.copyRemoteFileUrlWithoutRange", - "title": "Copy Remote File Url", - "category": "GitLens", + "title": "%gitlens.copyRemoteFileUrlWithoutRange.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(copy)" }, { "command": "gitlens.openFileOnRemoteFrom", - "title": "Open File on Remote From...", - "category": "GitLens", + "title": "%gitlens.openFileOnRemoteFrom.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(globe)" }, { "command": "gitlens.copyRemoteFileUrlFrom", - "title": "Copy Remote File Url From...", - "category": "GitLens", + "title": "%gitlens.copyRemoteFileUrlFrom.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(copy)" }, { "command": "gitlens.openBlamePriorToChange", - "title": "Open Blame Prior to Change", + "title": "%gitlens.openBlamePriorToChange.title%", "icon": "$(versions)", - "category": "GitLens" + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.openFileRevision", - "title": "Open File at Revision...", + "title": "%gitlens.openFileRevision.title%", "icon": { "dark": "images/dark/icon-open-revision.svg", "light": "images/light/icon-open-revision.svg" }, - "category": "GitLens" + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.openFileRevisionFrom", - "title": "Open File at Revision from...", + "title": "%gitlens.openFileRevisionFrom.title%", "icon": { "dark": "images/dark/icon-open-revision.svg", "light": "images/light/icon-open-revision.svg" }, - "category": "GitLens" + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.openIssueOnRemote", - "title": "Open Issue on Remote", - "category": "GitLens", + "title": "%gitlens.openIssueOnRemote.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(globe)" }, { "command": "gitlens.copyRemoteIssueUrl", - "title": "Copy Issue Url", - "category": "GitLens", + "title": "%gitlens.copyRemoteIssueUrl.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(copy)" }, { "command": "gitlens.openPullRequestOnRemote", - "title": "Open Pull Request on Remote", - "category": "GitLens", + "title": "%gitlens.openPullRequestOnRemote.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(globe)" }, { "command": "gitlens.copyRemotePullRequestUrl", - "title": "Copy Pull Request Url", - "category": "GitLens", + "title": "%gitlens.copyRemotePullRequestUrl.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(copy)" }, { "command": "gitlens.openAssociatedPullRequestOnRemote", - "title": "Open Associated Pull Request", - "category": "GitLens", + "title": "%gitlens.openAssociatedPullRequestOnRemote.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(git-pull-request)" }, { "command": "gitlens.openRepoOnRemote", - "title": "Open Repository on Remote", - "category": "GitLens", + "title": "%gitlens.openRepoOnRemote.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(globe)" }, { "command": "gitlens.copyRemoteRepositoryUrl", - "title": "Copy Remote Repository Url", - "category": "GitLens", + "title": "%gitlens.copyRemoteRepositoryUrl.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(copy)" }, { "command": "gitlens.openRevisionFile", - "title": "Open File at Revision", - "category": "GitLens", + "title": "%gitlens.openRevisionFile.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-open-revision.svg", "light": "images/light/icon-open-revision.svg" @@ -4497,8 +4497,8 @@ }, { "command": "gitlens.openRevisionFileInDiffLeft", - "title": "Open File at Revision", - "category": "GitLens", + "title": "%gitlens.openRevisionFileInDiffLeft.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-open-revision.svg", "light": "images/light/icon-open-revision.svg" @@ -4507,8 +4507,8 @@ }, { "command": "gitlens.openRevisionFileInDiffRight", - "title": "Open File at Revision", - "category": "GitLens", + "title": "%gitlens.openRevisionFileInDiffRight.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-open-revision.svg", "light": "images/light/icon-open-revision.svg" @@ -4517,26 +4517,26 @@ }, { "command": "gitlens.openWorkingFile", - "title": "Open File", - "category": "GitLens", + "title": "%gitlens.openWorkingFile.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(go-to-file)" }, { "command": "gitlens.openWorkingFileInDiffLeft", - "title": "Open File", - "category": "GitLens", + "title": "%gitlens.openWorkingFileInDiffLeft.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(go-to-file)" }, { "command": "gitlens.openWorkingFileInDiffRight", - "title": "Open File", - "category": "GitLens", + "title": "%gitlens.openWorkingFileInDiffRight.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(go-to-file)" }, { "command": "gitlens.stashApply", - "title": "Apply Stash", - "category": "GitLens", + "title": "%gitlens.stashApply.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-stash-pop.svg", "light": "images/light/icon-stash-pop.svg" @@ -4544,14 +4544,14 @@ }, { "command": "gitlens.views.deleteStash", - "title": "Delete Stash...", - "category": "GitLens", + "title": "%gitlens.views.deleteStash.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(trash)" }, { "command": "gitlens.stashSave", - "title": "Stash All Changes", - "category": "GitLens", + "title": "%gitlens.stashSave.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-stash-save.svg", "light": "images/light/icon-stash-save.svg" @@ -4559,8 +4559,8 @@ }, { "command": "gitlens.stashSaveFiles", - "title": "Stash Changes", - "category": "GitLens", + "title": "%gitlens.stashSaveFiles.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-stash-save.svg", "light": "images/light/icon-stash-save.svg" @@ -4568,120 +4568,120 @@ }, { "command": "gitlens.externalDiff", - "title": "Open Changes (difftool)", - "category": "GitLens" + "title": "%gitlens.externalDiff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.externalDiffAll", - "title": "Open All Changes (difftool)", - "category": "GitLens" + "title": "%gitlens.externalDiffAll.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.resetAvatarCache", - "title": "Reset Avatar Cache", - "category": "GitLens" + "title": "%gitlens.resetAvatarCache.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.resetSuppressedWarnings", - "title": "Reset Suppressed Warnings", - "category": "GitLens" + "title": "%gitlens.resetSuppressedWarnings.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.inviteToLiveShare", - "title": "Invite to Live Share", - "category": "GitLens", + "title": "%gitlens.inviteToLiveShare.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(live-share)" }, { "command": "gitlens.browseRepoAtRevision", - "title": "Browse Repository from Revision", - "category": "GitLens", + "title": "%gitlens.browseRepoAtRevision.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(folder-opened)", "enablement": "gitlens:activeFileStatus =~ /revision/ && resourceScheme != git" }, { "command": "gitlens.browseRepoAtRevisionInNewWindow", - "title": "Browse Repository from Revision in New Window", - "category": "GitLens", + "title": "%gitlens.browseRepoAtRevisionInNewWindow.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(folder-opened)", "enablement": "gitlens:activeFileStatus =~ /revision/ && resourceScheme != git" }, { "command": "gitlens.browseRepoBeforeRevision", - "title": "Browse Repository from Before Revision", - "category": "GitLens", + "title": "%gitlens.browseRepoBeforeRevision.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(folder-opened)", "enablement": "gitlens:activeFileStatus =~ /revision/ && resourceScheme != git" }, { "command": "gitlens.browseRepoBeforeRevisionInNewWindow", - "title": "Browse Repository from Before Revision in New Window", - "category": "GitLens", + "title": "%gitlens.browseRepoBeforeRevisionInNewWindow.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(folder-opened)", "enablement": "gitlens:activeFileStatus =~ /revision/ && resourceScheme != git" }, { "command": "gitlens.views.browseRepoAtRevision", - "title": "Repository from Here", - "category": "GitLens", + "title": "%gitlens.views.browseRepoAtRevision.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(folder-opened)" }, { "command": "gitlens.views.browseRepoAtRevisionInNewWindow", - "title": "Repository from Here in New Window", - "category": "GitLens", + "title": "%gitlens.views.browseRepoAtRevisionInNewWindow.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(folder-opened)" }, { "command": "gitlens.views.browseRepoBeforeRevision", - "title": "Repository from Before Here", - "category": "GitLens", + "title": "%gitlens.views.browseRepoBeforeRevision.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(folder-opened)" }, { "command": "gitlens.views.browseRepoBeforeRevisionInNewWindow", - "title": "Repository from Before Here in New Window", - "category": "GitLens", + "title": "%gitlens.views.browseRepoBeforeRevisionInNewWindow.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(folder-opened)" }, { "command": "gitlens.fetchRepositories", - "title": "Fetch", - "category": "GitLens", + "title": "%gitlens.fetchRepositories.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(sync)" }, { "command": "gitlens.pullRepositories", - "title": "Pull", - "category": "GitLens", + "title": "%gitlens.pullRepositories.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(arrow-down)" }, { "command": "gitlens.pushRepositories", - "title": "Push", - "category": "GitLens", + "title": "%gitlens.pushRepositories.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(arrow-up)" }, { "command": "gitlens.views.addRemote", - "title": "Add Remote", - "category": "GitLens", + "title": "%gitlens.views.addRemote.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(add)" }, { "command": "gitlens.views.highlightChanges", - "title": "Highlight All Changes Since Before this Commit", - "category": "GitLens" + "title": "%gitlens.views.highlightChanges.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.highlightRevisionChanges", - "title": "Highlight Changes from this Commit", - "category": "GitLens" + "title": "%gitlens.views.highlightRevisionChanges.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.restore", - "title": "Restore (Checkout)", - "category": "GitLens", + "title": "%gitlens.views.restore.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-checkout.svg", "light": "images/light/icon-checkout.svg" @@ -4689,8 +4689,8 @@ }, { "command": "gitlens.views.switchToAnotherBranch", - "title": "Switch to Another Branch...", - "category": "GitLens", + "title": "%gitlens.views.switchToAnotherBranch.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-checkout.svg", "light": "images/light/icon-checkout.svg" @@ -4698,8 +4698,8 @@ }, { "command": "gitlens.views.switchToBranch", - "title": "Switch to Branch...", - "category": "GitLens", + "title": "%gitlens.views.switchToBranch.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-checkout.svg", "light": "images/light/icon-checkout.svg" @@ -4707,8 +4707,8 @@ }, { "command": "gitlens.views.switchToCommit", - "title": "Switch to Commit...", - "category": "GitLens", + "title": "%gitlens.views.switchToCommit.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-checkout.svg", "light": "images/light/icon-checkout.svg" @@ -4716,8 +4716,8 @@ }, { "command": "gitlens.views.switchToTag", - "title": "Switch to Tag...", - "category": "GitLens", + "title": "%gitlens.views.switchToTag.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-checkout.svg", "light": "images/light/icon-checkout.svg" @@ -4725,49 +4725,49 @@ }, { "command": "gitlens.views.copy", - "title": "Copy", - "category": "GitLens", + "title": "%gitlens.views.copy.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(copy)" }, { "command": "gitlens.views.pruneRemote", - "title": "Prune", - "category": "GitLens" + "title": "%gitlens.views.pruneRemote.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.fetch", - "title": "Fetch", - "category": "GitLens", + "title": "%gitlens.views.fetch.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(sync)" }, { "command": "gitlens.views.publishBranch", - "title": "Publish Branch", - "category": "GitLens", + "title": "%gitlens.views.publishBranch.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(cloud-upload)" }, { "command": "gitlens.views.publishRepository", - "title": "Publish Repository", - "category": "GitLens", + "title": "%gitlens.views.publishRepository.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(cloud-upload)" }, { "command": "gitlens.views.pull", - "title": "Pull", - "category": "GitLens", + "title": "%gitlens.views.pull.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(arrow-down)" }, { "command": "gitlens.views.push", - "title": "Push", - "category": "GitLens", + "title": "%gitlens.views.push.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(arrow-up)" }, { "command": "gitlens.views.pushWithForce", - "title": "Push (force)", - "category": "GitLens", + "title": "%gitlens.views.pushWithForce.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-push-force.svg", "light": "images/light/icon-push-force.svg" @@ -4775,75 +4775,75 @@ }, { "command": "gitlens.views.openInTerminal", - "title": "Open in Terminal", - "category": "GitLens" + "title": "%gitlens.views.openInTerminal.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.setAsDefault", - "title": "Set as Default", - "category": "GitLens" + "title": "%gitlens.views.setAsDefault.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.unsetAsDefault", - "title": "Unset as Default", - "category": "GitLens" + "title": "%gitlens.views.unsetAsDefault.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.stageDirectory", - "title": "Stage All Changes", - "category": "GitLens", + "title": "%gitlens.views.stageDirectory.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(add)" }, { "command": "gitlens.views.stageFile", - "title": "Stage Changes", - "category": "GitLens", + "title": "%gitlens.views.stageFile.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(add)" }, { "command": "gitlens.views.unstageDirectory", - "title": "Unstage All Changes", - "category": "GitLens", + "title": "%gitlens.views.unstageDirectory.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(remove)" }, { "command": "gitlens.views.unstageFile", - "title": "Unstage Changes", - "category": "GitLens", + "title": "%gitlens.views.unstageFile.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(remove)" }, { "command": "gitlens.views.star", - "title": "Add to Favorites", - "category": "GitLens", + "title": "%gitlens.views.star.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(star-empty)" }, { "command": "gitlens.views.unstar", - "title": "Remove from Favorites", - "category": "GitLens", + "title": "%gitlens.views.unstar.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(star-full)" }, { "command": "gitlens.views.openDirectoryDiff", - "title": "Open Directory Compare", - "category": "GitLens" + "title": "%gitlens.views.openDirectoryDiff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.openDirectoryDiffWithWorking", - "title": "Open Directory Compare with Working Tree", - "category": "GitLens" + "title": "%gitlens.views.openDirectoryDiffWithWorking.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.openChanges", - "title": "Open Changes", - "category": "GitLens", + "title": "%gitlens.views.openChanges.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(compare-changes)" }, { "command": "gitlens.views.openChangesWithWorking", - "title": "Open Changes with Working File", - "category": "GitLens", + "title": "%gitlens.views.openChangesWithWorking.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-compare-ref-working.svg", "light": "images/light/icon-compare-ref-working.svg" @@ -4851,19 +4851,19 @@ }, { "command": "gitlens.views.openPreviousChangesWithWorking", - "title": "Open Previous Changes with Working File", - "category": "GitLens" + "title": "%gitlens.views.openPreviousChangesWithWorking.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.openFile", - "title": "Open File", - "category": "GitLens", + "title": "%gitlens.views.openFile.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(go-to-file)" }, { "command": "gitlens.views.openFileRevision", - "title": "Open File at Revision", - "category": "GitLens", + "title": "%gitlens.views.openFileRevision.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-open-revision.svg", "light": "images/light/icon-open-revision.svg" @@ -4871,74 +4871,74 @@ }, { "command": "gitlens.views.openChangedFiles", - "title": "Open Files", - "category": "GitLens" + "title": "%gitlens.views.openChangedFiles.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.openChangedFileDiffs", - "title": "Open All Changes", - "category": "GitLens" + "title": "%gitlens.views.openChangedFileDiffs.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.openChangedFileDiffsWithWorking", - "title": "Open All Changes with Working Tree", - "category": "GitLens" + "title": "%gitlens.views.openChangedFileDiffsWithWorking.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.openChangedFileRevisions", - "title": "Open Files at Revision", - "category": "GitLens" + "title": "%gitlens.views.openChangedFileRevisions.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.applyChanges", - "title": "Apply Changes", - "category": "GitLens" + "title": "%gitlens.views.applyChanges.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.closeRepository", - "title": "Close Repository", - "category": "GitLens" + "title": "%gitlens.views.closeRepository.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.compareAncestryWithWorking", - "title": "Compare Ancestry with Working Tree", - "category": "GitLens" + "title": "%gitlens.views.compareAncestryWithWorking.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.compareWithHead", - "title": "Compare with HEAD", - "category": "GitLens", + "title": "%gitlens.views.compareWithHead.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(compare-changes)" }, { "command": "gitlens.views.compareWithUpstream", - "title": "Compare with Upstream", - "category": "GitLens" + "title": "%gitlens.views.compareWithUpstream.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.compareWithSelected", - "title": "Compare with Selected", - "category": "GitLens" + "title": "%gitlens.views.compareWithSelected.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.selectForCompare", - "title": "Select for Compare", - "category": "GitLens" + "title": "%gitlens.views.selectForCompare.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.compareFileWithSelected", - "title": "Compare with Selected", - "category": "GitLens" + "title": "%gitlens.views.compareFileWithSelected.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.selectFileForCompare", - "title": "Select for Compare", - "category": "GitLens" + "title": "%gitlens.views.selectFileForCompare.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.compareWithWorking", - "title": "Compare with Working Tree", - "category": "GitLens", + "title": "%gitlens.views.compareWithWorking.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-compare-ref-working.svg", "light": "images/light/icon-compare-ref-working.svg" @@ -4946,193 +4946,193 @@ }, { "command": "gitlens.views.addAuthors", - "title": "Add Co-authors", - "category": "GitLens", + "title": "%gitlens.views.addAuthors.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(person-add)" }, { "command": "gitlens.views.addAuthor", - "title": "Add as Co-author", - "category": "GitLens", + "title": "%gitlens.views.addAuthor.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(person-add)" }, { "command": "gitlens.views.createWorktree", - "title": "Create Worktree...", - "category": "GitLens", + "title": "%gitlens.views.createWorktree.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(add)" }, { "command": "gitlens.views.deleteWorktree", - "title": "Delete Worktree...", - "category": "GitLens", + "title": "%gitlens.views.deleteWorktree.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(trash)" }, { "command": "gitlens.views.openWorktree", - "title": "Open Worktree", - "category": "GitLens", + "title": "%gitlens.views.openWorktree.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(window)" }, { "command": "gitlens.views.openWorktreeInNewWindow", - "title": "Open Worktree in New Window", - "category": "GitLens", + "title": "%gitlens.views.openWorktreeInNewWindow.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(empty-window)" }, { "command": "gitlens.views.revealWorktreeInExplorer", - "title": "Reveal Worktree in File Explorer", - "category": "GitLens" + "title": "%gitlens.views.revealWorktreeInExplorer.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.cherryPick", - "title": "Cherry Pick Commit...", - "category": "GitLens" + "title": "%gitlens.views.cherryPick.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.createBranch", - "title": "Create Branch...", - "category": "GitLens", + "title": "%gitlens.views.createBranch.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(add)" }, { "command": "gitlens.views.deleteBranch", - "title": "Delete Branch...", - "category": "GitLens", + "title": "%gitlens.views.deleteBranch.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(trash)" }, { "command": "gitlens.views.renameBranch", - "title": "Rename Branch...", - "category": "GitLens" + "title": "%gitlens.views.renameBranch.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.createTag", - "title": "Create Tag...", - "category": "GitLens", + "title": "%gitlens.views.createTag.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(add)" }, { "command": "gitlens.views.deleteTag", - "title": "Delete Tag...", - "category": "GitLens", + "title": "%gitlens.views.deleteTag.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(trash)" }, { "command": "gitlens.views.mergeBranchInto", - "title": "Merge Branch into Current Branch...", - "category": "GitLens" + "title": "%gitlens.views.mergeBranchInto.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.pushToCommit", - "title": "Push to Commit...", - "category": "GitLens", + "title": "%gitlens.views.pushToCommit.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(arrow-up)" }, { "command": "gitlens.views.rebaseOntoBranch", - "title": "Rebase Current Branch onto Branch...", - "category": "GitLens" + "title": "%gitlens.views.rebaseOntoBranch.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.rebaseOntoCommit", - "title": "Rebase Current Branch onto Commit...", - "category": "GitLens" + "title": "%gitlens.views.rebaseOntoCommit.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.rebaseOntoUpstream", - "title": "Rebase Current Branch onto Upstream...", - "category": "GitLens" + "title": "%gitlens.views.rebaseOntoUpstream.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.resetCommit", - "title": "Reset Current Branch to Previous Commit...", - "category": "GitLens" + "title": "%gitlens.views.resetCommit.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.resetToCommit", - "title": "Reset Current Branch to Commit...", - "category": "GitLens" + "title": "%gitlens.views.resetToCommit.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.revert", - "title": "Revert Commit...", - "category": "GitLens" + "title": "%gitlens.views.revert.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.undoCommit", - "title": "Undo Commit", - "category": "GitLens", + "title": "%gitlens.views.undoCommit.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(discard)" }, { "command": "gitlens.views.terminalRemoveRemote", - "title": "Remove Remote (via Terminal)", - "category": "GitLens" + "title": "%gitlens.views.terminalRemoveRemote.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.setBranchComparisonToWorking", - "title": "Toggle Compare with: Branch", - "category": "GitLens", + "title": "%gitlens.views.setBranchComparisonToWorking.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(compare-changes)" }, { "command": "gitlens.views.setBranchComparisonToBranch", - "title": "Toggle Compare with: Working Tree", - "category": "GitLens", + "title": "%gitlens.views.setBranchComparisonToBranch.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(compare-changes)" }, { "command": "gitlens.views.createPullRequest", - "title": "Create Pull Request...", - "category": "GitLens", + "title": "%gitlens.views.createPullRequest.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(git-pull-request-create)" }, { "command": "gitlens.views.openPullRequest", - "title": "Open Pull Request", - "category": "GitLens", + "title": "%gitlens.views.openPullRequest.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(git-pull-request)" }, { "command": "gitlens.views.clearNode", - "title": "Clear", - "category": "GitLens", + "title": "%gitlens.views.clearNode.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(close)" }, { "command": "gitlens.views.dismissNode", - "title": "Dismiss", - "category": "GitLens", + "title": "%gitlens.views.dismissNode.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(close)" }, { "command": "gitlens.views.editNode", - "title": "Edit...", - "category": "GitLens", + "title": "%gitlens.views.editNode.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(edit)" }, { "command": "gitlens.views.expandNode", - "title": "Expand", - "category": "GitLens" + "title": "%gitlens.views.expandNode.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.refreshNode", - "title": "Refresh", - "category": "GitLens", + "title": "%gitlens.views.refreshNode.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(refresh)" }, { "command": "gitlens.views.loadMoreChildren", - "title": "Load More", - "category": "GitLens" + "title": "%gitlens.views.loadMoreChildren.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.loadAllChildren", - "title": "Load All", - "category": "GitLens", + "title": "%gitlens.views.loadAllChildren.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-unfold.svg", "light": "images/light/icon-unfold.svg" @@ -5140,47 +5140,47 @@ }, { "command": "gitlens.views.setShowRelativeDateMarkersOn", - "title": "Show Date Markers", - "category": "GitLens" + "title": "%gitlens.views.setShowRelativeDateMarkersOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.setShowRelativeDateMarkersOff", - "title": "Hide Date Markers", - "category": "GitLens" + "title": "%gitlens.views.setShowRelativeDateMarkersOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.branches.copy", - "title": "Copy", - "category": "GitLens" + "title": "%gitlens.views.branches.copy.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.branches.refresh", - "title": "Refresh", - "category": "GitLens", + "title": "%gitlens.views.branches.refresh.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(refresh)" }, { "command": "gitlens.views.branches.setLayoutToList", - "title": "Toggle View: Tree", - "category": "GitLens", + "title": "%gitlens.views.branches.setLayoutToList.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-tree)" }, { "command": "gitlens.views.branches.setLayoutToTree", - "title": "Toggle View: List", - "category": "GitLens", + "title": "%gitlens.views.branches.setLayoutToTree.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-flat)" }, { "command": "gitlens.views.branches.setFilesLayoutToAuto", - "title": "Toggle Files View: Tree", - "category": "GitLens", + "title": "%gitlens.views.branches.setFilesLayoutToAuto.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-tree)" }, { "command": "gitlens.views.branches.setFilesLayoutToList", - "title": "Toggle Files View: Auto", - "category": "GitLens", + "title": "%gitlens.views.branches.setFilesLayoutToList.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-view-auto.svg", "light": "images/light/icon-view-auto.svg" @@ -5188,61 +5188,61 @@ }, { "command": "gitlens.views.branches.setFilesLayoutToTree", - "title": "Toggle Files View: List", - "category": "GitLens", + "title": "%gitlens.views.branches.setFilesLayoutToTree.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-flat)" }, { "command": "gitlens.views.branches.setShowAvatarsOn", - "title": "Show Avatars", - "category": "GitLens" + "title": "%gitlens.views.branches.setShowAvatarsOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.branches.setShowAvatarsOff", - "title": "Hide Avatars", - "category": "GitLens" + "title": "%gitlens.views.branches.setShowAvatarsOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.branches.setShowBranchComparisonOn", - "title": "Show Branch Comparisons", - "category": "GitLens" + "title": "%gitlens.views.branches.setShowBranchComparisonOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.branches.setShowBranchComparisonOff", - "title": "Hide Branch Comparisons", - "category": "GitLens" + "title": "%gitlens.views.branches.setShowBranchComparisonOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.branches.setShowBranchPullRequestOn", - "title": "Show Branch Pull Requests", - "category": "GitLens" + "title": "%gitlens.views.branches.setShowBranchPullRequestOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.branches.setShowBranchPullRequestOff", - "title": "Hide Branch Pull Requests", - "category": "GitLens" + "title": "%gitlens.views.branches.setShowBranchPullRequestOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.commits.copy", - "title": "Copy", - "category": "GitLens" + "title": "%gitlens.views.commits.copy.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.commits.refresh", - "title": "Refresh", - "category": "GitLens", + "title": "%gitlens.views.commits.refresh.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(refresh)" }, { "command": "gitlens.views.commits.setFilesLayoutToAuto", - "title": "Toggle Files View: Tree", - "category": "GitLens", + "title": "%gitlens.views.commits.setFilesLayoutToAuto.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-tree)" }, { "command": "gitlens.views.commits.setFilesLayoutToList", - "title": "Toggle Files View: Auto", - "category": "GitLens", + "title": "%gitlens.views.commits.setFilesLayoutToList.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-view-auto.svg", "light": "images/light/icon-view-auto.svg" @@ -5250,73 +5250,73 @@ }, { "command": "gitlens.views.commits.setFilesLayoutToTree", - "title": "Toggle Files View: List", - "category": "GitLens", + "title": "%gitlens.views.commits.setFilesLayoutToTree.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-flat)" }, { "command": "gitlens.views.commits.setMyCommitsOnlyOn", - "title": "Toggle Filter: All Commits", - "category": "GitLens", + "title": "%gitlens.views.commits.setMyCommitsOnlyOn.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(filter)" }, { "command": "gitlens.views.commits.setMyCommitsOnlyOff", - "title": "Toggle Filter: Only My Commits", - "category": "GitLens", + "title": "%gitlens.views.commits.setMyCommitsOnlyOff.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(filter-filled)" }, { "command": "gitlens.views.commits.setShowAvatarsOn", - "title": "Show Avatars", - "category": "GitLens" + "title": "%gitlens.views.commits.setShowAvatarsOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.commits.setShowAvatarsOff", - "title": "Hide Avatars", - "category": "GitLens" + "title": "%gitlens.views.commits.setShowAvatarsOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.commits.setShowBranchComparisonOn", - "title": "Show Branch Comparison", - "category": "GitLens" + "title": "%gitlens.views.commits.setShowBranchComparisonOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.commits.setShowBranchComparisonOff", - "title": "Hide Branch Comparison", - "category": "GitLens" + "title": "%gitlens.views.commits.setShowBranchComparisonOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.commits.setShowBranchPullRequestOn", - "title": "Show Current Branch Pull Request", - "category": "GitLens" + "title": "%gitlens.views.commits.setShowBranchPullRequestOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.commits.setShowBranchPullRequestOff", - "title": "Hide Current Branch Pull Request", - "category": "GitLens" + "title": "%gitlens.views.commits.setShowBranchPullRequestOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.contributors.copy", - "title": "Copy", - "category": "GitLens" + "title": "%gitlens.views.contributors.copy.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.contributors.refresh", - "title": "Refresh", - "category": "GitLens", + "title": "%gitlens.views.contributors.refresh.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(refresh)" }, { "command": "gitlens.views.contributors.setFilesLayoutToAuto", - "title": "Toggle Files View: Tree", - "category": "GitLens", + "title": "%gitlens.views.contributors.setFilesLayoutToAuto.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-tree)" }, { "command": "gitlens.views.contributors.setFilesLayoutToList", - "title": "Toggle Files View: Auto", - "category": "GitLens", + "title": "%gitlens.views.contributors.setFilesLayoutToList.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-view-auto.svg", "light": "images/light/icon-view-auto.svg" @@ -5324,193 +5324,193 @@ }, { "command": "gitlens.views.contributors.setFilesLayoutToTree", - "title": "Toggle Files View: List", - "category": "GitLens", + "title": "%gitlens.views.contributors.setFilesLayoutToTree.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-flat)" }, { "command": "gitlens.views.contributors.setShowAllBranchesOn", - "title": "Toggle Filter: Only Current Branch", - "category": "GitLens" + "title": "%gitlens.views.contributors.setShowAllBranchesOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.contributors.setShowAllBranchesOff", - "title": "Toggle Filter: All Branches", - "category": "GitLens" + "title": "%gitlens.views.contributors.setShowAllBranchesOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.contributors.setShowAvatarsOn", - "title": "Show Avatars", - "category": "GitLens" + "title": "%gitlens.views.contributors.setShowAvatarsOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.contributors.setShowAvatarsOff", - "title": "Hide Avatars", - "category": "GitLens" + "title": "%gitlens.views.contributors.setShowAvatarsOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.contributors.setShowStatisticsOn", - "title": "Show Statistics", - "category": "GitLens" + "title": "%gitlens.views.contributors.setShowStatisticsOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.contributors.setShowStatisticsOff", - "title": "Hide Statistics", - "category": "GitLens" + "title": "%gitlens.views.contributors.setShowStatisticsOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.fileHistory.changeBase", - "title": "Change Base...", - "category": "GitLens", + "title": "%gitlens.views.fileHistory.changeBase.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(history)" }, { "command": "gitlens.views.fileHistory.copy", - "title": "Copy", - "category": "GitLens" + "title": "%gitlens.views.fileHistory.copy.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.fileHistory.refresh", - "title": "Refresh", - "category": "GitLens", + "title": "%gitlens.views.fileHistory.refresh.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(refresh)" }, { "command": "gitlens.views.fileHistory.setCursorFollowingOn", - "title": "Toggle History by: File", - "category": "GitLens", + "title": "%gitlens.views.fileHistory.setCursorFollowingOn.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(file)", "enablement": "gitlens:views:fileHistory:editorFollowing" }, { "command": "gitlens.views.fileHistory.setCursorFollowingOff", - "title": "Toggle History by: Selected Line(s)", - "category": "GitLens", + "title": "%gitlens.views.fileHistory.setCursorFollowingOff.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-selection)", "enablement": "gitlens:views:fileHistory:editorFollowing || gitlens:views:fileHistory:cursorFollowing" }, { "command": "gitlens.views.fileHistory.setEditorFollowingOn", - "title": "Unpin the Current History", - "category": "GitLens", + "title": "%gitlens.views.fileHistory.setEditorFollowingOn.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(pinned)" }, { "command": "gitlens.views.fileHistory.setEditorFollowingOff", - "title": "Pin the Current History", - "category": "GitLens", + "title": "%gitlens.views.fileHistory.setEditorFollowingOff.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(pin)" }, { "command": "gitlens.views.fileHistory.setRenameFollowingOn", - "title": "Toggle Follow Renames: Off", - "category": "GitLens", + "title": "%gitlens.views.fileHistory.setRenameFollowingOn.title%", + "category": "%gitlens.commands.category.gitlens.title%", "enablement": "!config.gitlens.advanced.fileHistoryShowAllBranches" }, { "command": "gitlens.views.fileHistory.setRenameFollowingOff", - "title": "Toggle Follow Renames: On", - "category": "GitLens", + "title": "%gitlens.views.fileHistory.setRenameFollowingOff.title%", + "category": "%gitlens.commands.category.gitlens.title%", "enablement": "!config.gitlens.advanced.fileHistoryShowAllBranches" }, { "command": "gitlens.views.fileHistory.setShowAllBranchesOn", - "title": "Toggle Filter: Only Current Branch", - "category": "GitLens" + "title": "%gitlens.views.fileHistory.setShowAllBranchesOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.fileHistory.setShowAllBranchesOff", - "title": "Toggle Filter: All Branches", - "category": "GitLens" + "title": "%gitlens.views.fileHistory.setShowAllBranchesOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.fileHistory.setShowAvatarsOn", - "title": "Show Avatars", - "category": "GitLens" + "title": "%gitlens.views.fileHistory.setShowAvatarsOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.fileHistory.setShowAvatarsOff", - "title": "Hide Avatars", - "category": "GitLens" + "title": "%gitlens.views.fileHistory.setShowAvatarsOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.home.refresh", - "title": "Refresh", - "category": "GitLens", + "title": "%gitlens.views.home.refresh.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(refresh)" }, { "command": "gitlens.views.lineHistory.changeBase", - "title": "Change Base...", - "category": "GitLens", + "title": "%gitlens.views.lineHistory.changeBase.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(history)" }, { "command": "gitlens.views.lineHistory.copy", - "title": "Copy", - "category": "GitLens" + "title": "%gitlens.views.lineHistory.copy.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.lineHistory.refresh", - "title": "Refresh", - "category": "GitLens", + "title": "%gitlens.views.lineHistory.refresh.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(refresh)" }, { "command": "gitlens.views.lineHistory.setEditorFollowingOn", - "title": "Unpin the Current History", - "category": "GitLens", + "title": "%gitlens.views.lineHistory.setEditorFollowingOn.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(pinned)" }, { "command": "gitlens.views.lineHistory.setEditorFollowingOff", - "title": "Pin the Current History", - "category": "GitLens", + "title": "%gitlens.views.lineHistory.setEditorFollowingOff.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(pin)" }, { "command": "gitlens.views.lineHistory.setShowAvatarsOn", - "title": "Show Avatars", - "category": "GitLens" + "title": "%gitlens.views.lineHistory.setShowAvatarsOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.lineHistory.setShowAvatarsOff", - "title": "Hide Avatars", - "category": "GitLens" + "title": "%gitlens.views.lineHistory.setShowAvatarsOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.remotes.copy", - "title": "Copy", - "category": "GitLens" + "title": "%gitlens.views.remotes.copy.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.remotes.refresh", - "title": "Refresh", - "category": "GitLens", + "title": "%gitlens.views.remotes.refresh.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(refresh)" }, { "command": "gitlens.views.remotes.setLayoutToList", - "title": "Toggle View: Tree", - "category": "GitLens", + "title": "%gitlens.views.remotes.setLayoutToList.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-tree)" }, { "command": "gitlens.views.remotes.setLayoutToTree", - "title": "Toggle View: List", - "category": "GitLens", + "title": "%gitlens.views.remotes.setLayoutToTree.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-flat)" }, { "command": "gitlens.views.remotes.setFilesLayoutToAuto", - "title": "Toggle Files View: Tree", - "category": "GitLens", + "title": "%gitlens.views.remotes.setFilesLayoutToAuto.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-tree)" }, { "command": "gitlens.views.remotes.setFilesLayoutToList", - "title": "Toggle Files View: Auto", - "category": "GitLens", + "title": "%gitlens.views.remotes.setFilesLayoutToList.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-view-auto.svg", "light": "images/light/icon-view-auto.svg" @@ -5518,73 +5518,73 @@ }, { "command": "gitlens.views.remotes.setFilesLayoutToTree", - "title": "Toggle Files View: List", - "category": "GitLens", + "title": "%gitlens.views.remotes.setFilesLayoutToTree.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-flat)" }, { "command": "gitlens.views.remotes.setShowAvatarsOn", - "title": "Show Avatars", - "category": "GitLens" + "title": "%gitlens.views.remotes.setShowAvatarsOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.remotes.setShowAvatarsOff", - "title": "Hide Avatars", - "category": "GitLens" + "title": "%gitlens.views.remotes.setShowAvatarsOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.remotes.setShowBranchPullRequestOn", - "title": "Show Branch Pull Requests", - "category": "GitLens" + "title": "%gitlens.views.remotes.setShowBranchPullRequestOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.remotes.setShowBranchPullRequestOff", - "title": "Hide Branch Pull Requests", - "category": "GitLens" + "title": "%gitlens.views.remotes.setShowBranchPullRequestOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.copy", - "title": "Copy", - "category": "GitLens" + "title": "%gitlens.views.repositories.copy.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.refresh", - "title": "Refresh", - "category": "GitLens", + "title": "%gitlens.views.repositories.refresh.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(refresh)" }, { "command": "gitlens.views.repositories.setAutoRefreshToOn", - "title": "Enable Automatic Refresh", - "category": "GitLens" + "title": "%gitlens.views.repositories.setAutoRefreshToOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setAutoRefreshToOff", - "title": "Disable Automatic Refresh", - "category": "GitLens" + "title": "%gitlens.views.repositories.setAutoRefreshToOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setBranchesLayoutToList", - "title": "Toggle Branches View: Tree", - "category": "GitLens", + "title": "%gitlens.views.repositories.setBranchesLayoutToList.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-tree)" }, { "command": "gitlens.views.repositories.setBranchesLayoutToTree", - "title": "Toggle Branches View: List", - "category": "GitLens", + "title": "%gitlens.views.repositories.setBranchesLayoutToTree.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-flat)" }, { "command": "gitlens.views.repositories.setFilesLayoutToAuto", - "title": "Toggle Files View: Tree", - "category": "GitLens", + "title": "%gitlens.views.repositories.setFilesLayoutToAuto.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-tree)" }, { "command": "gitlens.views.repositories.setFilesLayoutToList", - "title": "Toggle Files View: Auto", - "category": "GitLens", + "title": "%gitlens.views.repositories.setFilesLayoutToList.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-view-auto.svg", "light": "images/light/icon-view-auto.svg" @@ -5592,176 +5592,176 @@ }, { "command": "gitlens.views.repositories.setFilesLayoutToTree", - "title": "Toggle Files View: List", - "category": "GitLens", + "title": "%gitlens.views.repositories.setFilesLayoutToTree.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-flat)" }, { "command": "gitlens.views.repositories.setShowAvatarsOn", - "title": "Show Avatars", - "category": "GitLens" + "title": "%gitlens.views.repositories.setShowAvatarsOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setShowAvatarsOff", - "title": "Hide Avatars", - "category": "GitLens" + "title": "%gitlens.views.repositories.setShowAvatarsOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setShowBranchComparisonOn", - "title": "Show Branch Comparison", - "category": "GitLens" + "title": "%gitlens.views.repositories.setShowBranchComparisonOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setShowBranchComparisonOff", - "title": "Hide Branch Comparison", - "category": "GitLens" + "title": "%gitlens.views.repositories.setShowBranchComparisonOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setBranchesShowBranchComparisonOn", - "title": "Show Branch Comparisons", - "category": "GitLens" + "title": "%gitlens.views.repositories.setBranchesShowBranchComparisonOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setBranchesShowBranchComparisonOff", - "title": "Hide Branch Comparisons", - "category": "GitLens" + "title": "%gitlens.views.repositories.setBranchesShowBranchComparisonOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setShowBranchesOn", - "title": "Show Branches", - "category": "GitLens" + "title": "%gitlens.views.repositories.setShowBranchesOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setShowBranchesOff", - "title": "Hide Branches", - "category": "GitLens" + "title": "%gitlens.views.repositories.setShowBranchesOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setShowCommitsOn", - "title": "Show Commits", - "category": "GitLens" + "title": "%gitlens.views.repositories.setShowCommitsOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setShowCommitsOff", - "title": "Hide Commits", - "category": "GitLens" + "title": "%gitlens.views.repositories.setShowCommitsOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setShowContributorsOn", - "title": "Show Contributors", - "category": "GitLens" + "title": "%gitlens.views.repositories.setShowContributorsOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setShowContributorsOff", - "title": "Hide Contributors", - "category": "GitLens" + "title": "%gitlens.views.repositories.setShowContributorsOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setShowRemotesOn", - "title": "Show Remotes", - "category": "GitLens" + "title": "%gitlens.views.repositories.setShowRemotesOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setShowRemotesOff", - "title": "Hide Remotes", - "category": "GitLens" + "title": "%gitlens.views.repositories.setShowRemotesOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setShowStashesOn", - "title": "Show Stashes", - "category": "GitLens" + "title": "%gitlens.views.repositories.setShowStashesOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setShowStashesOff", - "title": "Hide Stashes", - "category": "GitLens" + "title": "%gitlens.views.repositories.setShowStashesOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setShowTagsOn", - "title": "Show Tags", - "category": "GitLens" + "title": "%gitlens.views.repositories.setShowTagsOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setShowTagsOff", - "title": "Hide Tags", - "category": "GitLens" + "title": "%gitlens.views.repositories.setShowTagsOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setShowWorktreesOn", - "title": "Show Worktrees", - "category": "GitLens" + "title": "%gitlens.views.repositories.setShowWorktreesOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setShowWorktreesOff", - "title": "Hide Worktrees", - "category": "GitLens" + "title": "%gitlens.views.repositories.setShowWorktreesOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setShowUpstreamStatusOn", - "title": "Show Current Branch Status", - "category": "GitLens" + "title": "%gitlens.views.repositories.setShowUpstreamStatusOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setShowUpstreamStatusOff", - "title": "Hide Current Branch Status", - "category": "GitLens" + "title": "%gitlens.views.repositories.setShowUpstreamStatusOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.repositories.setShowSectionOff", - "title": "Hide", - "category": "GitLens" + "title": "%gitlens.views.repositories.setShowSectionOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.searchAndCompare.clear", - "title": "Clear Results", - "category": "GitLens", + "title": "%gitlens.views.searchAndCompare.clear.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(clear-all)" }, { "command": "gitlens.views.searchAndCompare.copy", - "title": "Copy", - "category": "GitLens" + "title": "%gitlens.views.searchAndCompare.copy.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.searchAndCompare.pin", - "title": "Pin", - "category": "GitLens", + "title": "%gitlens.views.searchAndCompare.pin.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(pin)" }, { "command": "gitlens.views.searchAndCompare.unpin", - "title": "Unpin", - "category": "GitLens", + "title": "%gitlens.views.searchAndCompare.unpin.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(pinned)" }, { "command": "gitlens.views.searchAndCompare.refresh", - "title": "Refresh", - "category": "GitLens", + "title": "%gitlens.views.searchAndCompare.refresh.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(refresh)" }, { "command": "gitlens.views.searchAndCompare.searchCommits", - "title": "Search Commits...", - "category": "GitLens", + "title": "%gitlens.views.searchAndCompare.searchCommits.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(search)" }, { "command": "gitlens.views.searchAndCompare.selectForCompare", - "title": "Compare References...", - "category": "GitLens", + "title": "%gitlens.views.searchAndCompare.selectForCompare.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(compare-changes)" }, { "command": "gitlens.views.searchAndCompare.setFilesLayoutToAuto", - "title": "Toggle Files View: Tree", - "category": "GitLens", + "title": "%gitlens.views.searchAndCompare.setFilesLayoutToAuto.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-tree)" }, { "command": "gitlens.views.searchAndCompare.setFilesLayoutToList", - "title": "Toggle Files View: Auto", - "category": "GitLens", + "title": "%gitlens.views.searchAndCompare.setFilesLayoutToList.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-view-auto.svg", "light": "images/light/icon-view-auto.svg" @@ -5769,76 +5769,76 @@ }, { "command": "gitlens.views.searchAndCompare.setFilesLayoutToTree", - "title": "Toggle Files View: List", - "category": "GitLens", + "title": "%gitlens.views.searchAndCompare.setFilesLayoutToTree.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-flat)" }, { "command": "gitlens.views.searchAndCompare.setKeepResultsToOn", - "title": "Keep Results", - "category": "GitLens", + "title": "%gitlens.views.searchAndCompare.setKeepResultsToOn.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(unlock)" }, { "command": "gitlens.views.searchAndCompare.setKeepResultsToOff", - "title": "Keep Results", - "category": "GitLens", + "title": "%gitlens.views.searchAndCompare.setKeepResultsToOff.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(lock)" }, { "command": "gitlens.views.searchAndCompare.setShowAvatarsOn", - "title": "Show Avatars", - "category": "GitLens" + "title": "%gitlens.views.searchAndCompare.setShowAvatarsOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.searchAndCompare.setShowAvatarsOff", - "title": "Hide Avatars", - "category": "GitLens" + "title": "%gitlens.views.searchAndCompare.setShowAvatarsOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.searchAndCompare.swapComparison", - "title": "Swap Comparison", - "category": "GitLens", + "title": "%gitlens.views.searchAndCompare.swapComparison.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(arrow-swap)" }, { "command": "gitlens.views.searchAndCompare.setFilesFilterOnLeft", - "title": "Show Left-side Files Only", - "category": "GitLens", + "title": "%gitlens.views.searchAndCompare.setFilesFilterOnLeft.title%", + "category": "%gitlens.commands.category.gitlens.title%", "enablement": "viewItem =~ /gitlens:results:files\\b(?!.*?\\b\\+filtered~left\\b)/" }, { "command": "gitlens.views.searchAndCompare.setFilesFilterOnRight", - "title": "Show Right-side Files Only", - "category": "GitLens", + "title": "%gitlens.views.searchAndCompare.setFilesFilterOnRight.title%", + "category": "%gitlens.commands.category.gitlens.title%", "enablement": "viewItem =~ /gitlens:results:files\\b(?!.*?\\b\\+filtered~right\\b)/" }, { "command": "gitlens.views.searchAndCompare.setFilesFilterOff", - "title": "Clear Filter", - "category": "GitLens" + "title": "%gitlens.views.searchAndCompare.setFilesFilterOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.stashes.copy", - "title": "Copy", - "category": "GitLens" + "title": "%gitlens.views.stashes.copy.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.stashes.refresh", - "title": "Refresh", - "category": "GitLens", + "title": "%gitlens.views.stashes.refresh.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(refresh)" }, { "command": "gitlens.views.stashes.setFilesLayoutToAuto", - "title": "Toggle Files View: Tree", - "category": "GitLens", + "title": "%gitlens.views.stashes.setFilesLayoutToAuto.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-tree)" }, { "command": "gitlens.views.stashes.setFilesLayoutToList", - "title": "Toggle Files View: Auto", - "category": "GitLens", + "title": "%gitlens.views.stashes.setFilesLayoutToList.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-view-auto.svg", "light": "images/light/icon-view-auto.svg" @@ -5846,43 +5846,43 @@ }, { "command": "gitlens.views.stashes.setFilesLayoutToTree", - "title": "Toggle Files View: List", - "category": "GitLens", + "title": "%gitlens.views.stashes.setFilesLayoutToTree.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-flat)" }, { "command": "gitlens.views.tags.copy", - "title": "Copy", - "category": "GitLens" + "title": "%gitlens.views.tags.copy.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.tags.refresh", - "title": "Refresh", - "category": "GitLens", + "title": "%gitlens.views.tags.refresh.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(refresh)" }, { "command": "gitlens.views.tags.setLayoutToList", - "title": "Toggle View: Tree", - "category": "GitLens", + "title": "%gitlens.views.tags.setLayoutToList.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-tree)" }, { "command": "gitlens.views.tags.setLayoutToTree", - "title": "Toggle View: List", - "category": "GitLens", + "title": "%gitlens.views.tags.setLayoutToTree.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-flat)" }, { "command": "gitlens.views.tags.setFilesLayoutToAuto", - "title": "Toggle Files View: Tree", - "category": "GitLens", + "title": "%gitlens.views.tags.setFilesLayoutToAuto.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-tree)" }, { "command": "gitlens.views.tags.setFilesLayoutToList", - "title": "Toggle Files View: Auto", - "category": "GitLens", + "title": "%gitlens.views.tags.setFilesLayoutToList.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-view-auto.svg", "light": "images/light/icon-view-auto.svg" @@ -5890,53 +5890,53 @@ }, { "command": "gitlens.views.tags.setFilesLayoutToTree", - "title": "Toggle Files View: List", - "category": "GitLens", + "title": "%gitlens.views.tags.setFilesLayoutToTree.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-flat)" }, { "command": "gitlens.views.tags.setShowAvatarsOn", - "title": "Show Avatars", - "category": "GitLens" + "title": "%gitlens.views.tags.setShowAvatarsOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.tags.setShowAvatarsOff", - "title": "Hide Avatars", - "category": "GitLens" + "title": "%gitlens.views.tags.setShowAvatarsOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.timeline.openInTab", - "title": "Open in Editor Area", - "category": "GitLens", + "title": "%gitlens.views.timeline.openInTab.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(link-external)" }, { "command": "gitlens.views.timeline.refresh", - "title": "Refresh", - "category": "GitLens", + "title": "%gitlens.views.timeline.refresh.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(refresh)" }, { "command": "gitlens.views.worktrees.copy", - "title": "Copy", - "category": "GitLens" + "title": "%gitlens.views.worktrees.copy.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.worktrees.refresh", - "title": "Refresh", - "category": "GitLens", + "title": "%gitlens.views.worktrees.refresh.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(refresh)" }, { "command": "gitlens.views.worktrees.setFilesLayoutToAuto", - "title": "Toggle Files View: Tree", - "category": "GitLens", + "title": "%gitlens.views.worktrees.setFilesLayoutToAuto.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-tree)" }, { "command": "gitlens.views.worktrees.setFilesLayoutToList", - "title": "Toggle Files View: Auto", - "category": "GitLens", + "title": "%gitlens.views.worktrees.setFilesLayoutToList.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": { "dark": "images/dark/icon-view-auto.svg", "light": "images/light/icon-view-auto.svg" @@ -5944,49 +5944,49 @@ }, { "command": "gitlens.views.worktrees.setFilesLayoutToTree", - "title": "Toggle Files View: List", - "category": "GitLens", + "title": "%gitlens.views.worktrees.setFilesLayoutToTree.title%", + "category": "%gitlens.commands.category.gitlens.title%", "icon": "$(list-flat)" }, { "command": "gitlens.views.worktrees.setShowAvatarsOn", - "title": "Show Avatars", - "category": "GitLens" + "title": "%gitlens.views.worktrees.setShowAvatarsOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.worktrees.setShowAvatarsOff", - "title": "Hide Avatars", - "category": "GitLens" + "title": "%gitlens.views.worktrees.setShowAvatarsOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.worktrees.setShowBranchComparisonOn", - "title": "Show Branch Comparison", - "category": "GitLens" + "title": "%gitlens.views.worktrees.setShowBranchComparisonOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.worktrees.setShowBranchComparisonOff", - "title": "Hide Branch Comparison", - "category": "GitLens" + "title": "%gitlens.views.worktrees.setShowBranchComparisonOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.worktrees.setShowBranchPullRequestOn", - "title": "Show Branch Pull Requests", - "category": "GitLens" + "title": "%gitlens.views.worktrees.setShowBranchPullRequestOn.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.views.worktrees.setShowBranchPullRequestOff", - "title": "Hide Branch Pull Requests", - "category": "GitLens" + "title": "%gitlens.views.worktrees.setShowBranchPullRequestOff.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.enableDebugLogging", - "title": "Enable Debug Logging", - "category": "GitLens" + "title": "%gitlens.enableDebugLogging.title%", + "category": "%gitlens.commands.category.gitlens.title%" }, { "command": "gitlens.disableDebugLogging", - "title": "Disable Debug Logging", - "category": "GitLens" + "title": "%gitlens.disableDebugLogging.title%", + "category": "%gitlens.commands.category.gitlens.title%" } ], "menus": { @@ -10291,31 +10291,31 @@ "submenus": [ { "id": "gitlens/commit/browse", - "label": "Browse" + "label": "%gitlens.submenus.gitlensCommitBrowse.label%" }, { "id": "gitlens/commit/copy", - "label": "Copy As" + "label": "%gitlens.submenus.gitlensCommitCopy.label%" }, { "id": "gitlens/commit/changes", - "label": "Open Changes" + "label": "%gitlens.submenus.gitlensCommitChanges.label%" }, { "id": "gitlens/commit/file/copy", - "label": "Copy As" + "label": "%gitlens.submenus.gitlensCommitFileCopy.label%" }, { "id": "gitlens/commit/file/commit", - "label": "Commit" + "label": "%gitlens.submenus.gitlensCommitFileCommit.label%" }, { "id": "gitlens/commit/file/changes", - "label": "Open Changes" + "label": "%gitlens.submenus.gitlensCommitFileChanges.label%" }, { "id": "gitlens/editor/annotations", - "label": "File Annotations", + "label": "%gitlens.submenus.gitlensEditorAnnotations.label%", "icon": { "dark": "images/dark/icon-git.svg", "light": "images/light/icon-git.svg" @@ -10323,36 +10323,36 @@ }, { "id": "gitlens/editor/context/changes", - "label": "Commit Changes" + "label": "%gitlens.submenus.gitlensEditorContextChanges.label%" }, { "id": "gitlens/editor/changes", - "label": "Commit Changes" + "label": "%gitlens.submenus.gitlensEditorChanges.label%" }, { "id": "gitlens/explorer/changes", - "label": "Commit Changes" + "label": "%gitlens.submenus.gitlensExplorerChanges.label%" }, { "id": "gitlens/scm/resourceGroup/changes", - "label": "Open Changes" + "label": "%gitlens.submenus.gitlensScmResourceGroupChanges.label%" }, { "id": "gitlens/scm/resourceState/changes", - "label": "Open Changes" + "label": "%gitlens.submenus.gitlensScmResourceStateChanges.label%" }, { "id": "gitlens/view/repositories/sections", - "label": "Sections" + "label": "%gitlens.submenus.gitlensViewRepositoriesSections.label%" }, { "id": "gitlens/view/searchAndCompare/new", - "label": "New Search or Compare", + "label": "%gitlens.submenus.gitlensViewSearchAndCompareNew.label%", "icon": "$(add)" }, { "id": "gitlens/view/searchAndCompare/comparison/filter", - "label": "Filter", + "label": "%gitlens.submenus.gitlensViewSearchAndCompareComparisonFilter.label%", "icon": "$(filter)" } ], @@ -10645,7 +10645,7 @@ "customEditors": [ { "viewType": "gitlens.rebase", - "displayName": "GitLens Interactive Rebase Editor", + "displayName": "%gitlens.rebase.displayName%", "selector": [ { "filenamePattern": "git-rebase-todo" @@ -10669,14 +10669,14 @@ "activitybar": [ { "id": "gitlens", - "title": "GitLens", + "title": "%gitlens.contributes.activitybar.gitlens.title%", "icon": "images/gitlens-activitybar.svg" } ], "panel": [ { "id": "gitlensPanel", - "title": "GitLens", + "title": "%gitlens.contributes.panel.gitlensPanel.title%", "icon": "images/views/history.svg" } ] @@ -10684,51 +10684,51 @@ "viewsWelcome": [ { "view": "gitlens.views.searchAndCompare", - "contents": "Search for commits by [message](command:gitlens.views.searchAndCompare.searchCommits?%7B%22search%22%3A%7B%22pattern%22%3A%22message%3A%22%7D%2C%22prefillOnly%22%3Atrue%7D), [author](command:gitlens.views.searchAndCompare.searchCommits?%7B%22search%22%3A%7B%22pattern%22%3A%22author%3A%22%7D%2C%22prefillOnly%22%3Atrue%7D), [SHA](command:gitlens.views.searchAndCompare.searchCommits?%7B%22search%22%3A%7B%22pattern%22%3A%22commit%3A%22%7D%2C%22prefillOnly%22%3Atrue%7D), [file](command:gitlens.views.searchAndCompare.searchCommits?%7B%22search%22%3A%7B%22pattern%22%3A%22file%3A%22%7D%2C%22prefillOnly%22%3Atrue%7D), or [changes](command:gitlens.views.searchAndCompare.searchCommits?%7B%22search%22%3A%7B%22pattern%22%3A%22change%3A%22%7D%2C%22prefillOnly%22%3Atrue%7D)\n\n[Search Commits...](command:gitlens.views.searchAndCompare.searchCommits)", + "contents": "%gitlens.views.searchAndCompare.welcome.search.noVirtualFolders.contents%", "when": "!gitlens:hasVirtualFolders" }, { "view": "gitlens.views.searchAndCompare", - "contents": "Search for commits by [message](command:gitlens.views.searchAndCompare.searchCommits?%7B%22search%22%3A%7B%22pattern%22%3A%22message%3A%22%7D%2C%22prefillOnly%22%3Atrue%7D), [author](command:gitlens.views.searchAndCompare.searchCommits?%7B%22search%22%3A%7B%22pattern%22%3A%22author%3A%22%7D%2C%22prefillOnly%22%3Atrue%7D), or [SHA](command:gitlens.views.searchAndCompare.searchCommits?%7B%22search%22%3A%7B%22pattern%22%3A%22commit%3A%22%7D%2C%22prefillOnly%22%3Atrue%7D)\n\n[Search Commits...](command:gitlens.views.searchAndCompare.searchCommits)", + "contents": "%gitlens.views.searchAndCompare.welcome.search.hasVirtualFolders.contents%", "when": "gitlens:hasVirtualFolders" }, { "view": "gitlens.views.searchAndCompare", - "contents": "Compare a with another \n\n[Compare References...](command:gitlens.views.searchAndCompare.selectForCompare)", + "contents": "%gitlens.views.searchAndCompare.welcome.compare.noVirtualFolders.contents%", "when": "!gitlens:hasVirtualFolders" }, { "view": "gitlens.views.worktrees", - "contents": "Worktrees allow you to easily work on different branches of a repository simultaneously. You can create multiple working trees, each of which can be opened in individual windows or all together in a single workspace." + "contents": "%gitlens.views.worktrees.welcome.contents%" }, { "view": "gitlens.views.worktrees", - "contents": "[Create Worktree...](command:gitlens.views.createWorktree)", + "contents": "%gitlens.views.worktrees.welcome.plusAllowed.contents%", "when": "gitlens:plus:allowed" }, { "view": "gitlens.views.worktrees", - "contents": "Please verify your email\n\nTo use Worktrees, please verify the email for the account you created.\n\n[Resend verification email](command:gitlens.plus.resendVerification)\n\n[Refresh verification status](command:gitlens.plus.validate)", + "contents": "%gitlens.views.worktrees.welcome.verifyEmail.contents%", "when": "gitlens:plus:state == -1" }, { "view": "gitlens.views.worktrees", - "contents": "Try worktrees now, without an account, for 3 days on public and private repos, or [sign in](command:gitlens.plus.loginOrSignUp \"Sign in to GitLens+\") for use on public repos.\n\n[Try worktrees now](command:gitlens.plus.startPreviewTrial)", + "contents": "%gitlens.views.worktrees.welcome.tryNow.contents%", "when": "gitlens:plus:state == 0" }, { "view": "gitlens.views.worktrees", - "contents": "Sign in to use worktrees and other GitLens+ features on public repos and get a free 7-day trial for both public and private repos.\n\n[Sign in to GitLens+](command:gitlens.plus.loginOrSignUp)", + "contents": "%gitlens.views.worktrees.welcome.signIn.contents%", "when": "gitlens:plus:state == 2" }, { "view": "gitlens.views.worktrees", - "contents": "[Upgrade your account](command:gitlens.plus.purchase)", + "contents": "%gitlens.views.worktrees.welcome.purchasePlan.contents%", "when": "gitlens:plus:state == 4" }, { "view": "gitlens.views.worktrees", - "contents": "✨ Worktrees are a [GitLens+ feature](command:gitlens.plus.learn) which can be used on public repos with a [free account](command:gitlens.plus.loginOrSignUp) and private repos with a [paid account](command:gitlens.plus.purchase).\n\n🛈 All other GitLens features can always be used on any repo, without an account.", + "contents": "%gitlens.views.worktrees.welcome.plusFeature.contents%", "when": "gitlens:plus:state > -1" } ], @@ -10737,9 +10737,9 @@ { "type": "webview", "id": "gitlens.views.home", - "name": "Home", - "when": "!gitlens:disabled && config.gitlens.plusFeatures.enabled", - "contextualTitle": "GitLens", + "name": "%gitlens.views.home.name%", + "when": "!gitlens:disabled && config.gitlens.plusFeatures.enable", + "contextualTitle": "%gitlens.views.contextualTitle%", "icon": "images/gitlens-activitybar.svg", "visibility": "visible" } @@ -10748,9 +10748,9 @@ { "type": "webview", "id": "gitlens.views.timeline", - "name": "Visual File History", + "name": "%gitlens.views.timeline.name%", "when": "!gitlens:disabled && config.gitlens.plusFeatures.enabled", - "contextualTitle": "GitLens", + "contextualTitle": "%gitlens.views.contextualTitle%", "icon": "images/views/history.svg", "visibility": "visible" } @@ -10758,89 +10758,89 @@ "scm": [ { "id": "gitlens.views.commits", - "name": "Commits", + "name": "%gitlens.views.commits.name%", "when": "!gitlens:disabled", - "contextualTitle": "GitLens", + "contextualTitle": "%gitlens.views.contextualTitle%", "icon": "images/views/commits.svg", "visibility": "visible" }, { "id": "gitlens.views.repositories", - "name": "Repositories", + "name": "%gitlens.views.repositories.name%", "when": "!gitlens:disabled && !gitlens:hasVirtualFolders", - "contextualTitle": "GitLens", + "contextualTitle": "%gitlens.views.contextualTitle%", "icon": "images/views/repositories.svg", "visibility": "hidden" }, { "id": "gitlens.views.fileHistory", - "name": "File History", + "name": "%gitlens.views.fileHistory.name%", "when": "!gitlens:disabled", - "contextualTitle": "GitLens", + "contextualTitle": "%gitlens.views.contextualTitle%", "icon": "images/views/history.svg", "visibility": "visible" }, { "id": "gitlens.views.lineHistory", - "name": "Line History", + "name": "%gitlens.views.lineHistory.name%", "when": "!gitlens:disabled && !gitlens:hasVirtualFolders", - "contextualTitle": "GitLens", + "contextualTitle": "%gitlens.views.contextualTitle%", "icon": "images/views/history.svg", "visibility": "hidden" }, { "id": "gitlens.views.branches", - "name": "Branches", + "name": "%gitlens.views.branches.name%", "when": "!gitlens:disabled", - "contextualTitle": "GitLens", + "contextualTitle": "%gitlens.views.contextualTitle%", "icon": "images/views/branches.svg", "visibility": "collapsed" }, { "id": "gitlens.views.remotes", - "name": "Remotes", + "name": "%gitlens.views.remotes.name%", "when": "!gitlens:disabled", - "contextualTitle": "GitLens", + "contextualTitle": "%gitlens.views.contextualTitle%", "icon": "images/views/remotes.svg", "visibility": "collapsed" }, { "id": "gitlens.views.stashes", - "name": "Stashes", + "name": "%gitlens.views.stashes.name%", "when": "!gitlens:disabled && !gitlens:hasVirtualFolders", - "contextualTitle": "GitLens", + "contextualTitle": "%gitlens.views.contextualTitle%", "icon": "images/views/stashes.svg", "visibility": "collapsed" }, { "id": "gitlens.views.tags", - "name": "Tags", + "name": "%gitlens.views.tags.name%", "when": "!gitlens:disabled", - "contextualTitle": "GitLens", + "contextualTitle": "%gitlens.views.contextualTitle%", "icon": "images/views/tags.svg", "visibility": "collapsed" }, { "id": "gitlens.views.worktrees", - "name": "Worktrees", + "name": "%gitlens.views.worktrees.name%", "when": "!gitlens:disabled && !gitlens:hasVirtualFolders && config.gitlens.plusFeatures.enabled", - "contextualTitle": "GitLens", + "contextualTitle": "%gitlens.views.contextualTitle%", "icon": "images/views/worktrees.svg", "visibility": "collapsed" }, { "id": "gitlens.views.contributors", - "name": "Contributors", + "name": "%gitlens.views.contributors.name%", "when": "!gitlens:disabled", - "contextualTitle": "GitLens", + "contextualTitle": "%gitlens.views.contextualTitle%", "icon": "images/views/contributors.svg", "visibility": "hidden" }, { "id": "gitlens.views.searchAndCompare", - "name": "Search & Compare", + "name": "%gitlens.views.searchAndCompare.name%", "when": "!gitlens:disabled", - "contextualTitle": "GitLens", + "contextualTitle": "%gitlens.views.contextualTitle%", "icon": "images/views/search.svg", "visibility": "collapsed" } @@ -10849,44 +10849,44 @@ "walkthroughs": [ { "id": "gitlens.welcome", - "title": "Get Started with GitLens", - "description": "Discover and personalize features that supercharge your Git experience", + "title": "%gitlens.welcome.title%", + "description": "%gitlens.welcome.description%", "steps": [ { "id": "gitlens.welcome.experience", - "title": "Get setup quickly", - "description": "Use the Quick Setup to easily configure frequently used GitLens features.\n\n[Open Quick Setup](command:gitlens.showWelcomePage?%22quick-setup%22 \"Opens the GitLens Quick Setup\")", + "title": "%gitlens.welcome.experience.title%", + "description": "%gitlens.welcome.experience.description%", "media": { "markdown": "walkthroughs/getting-started/1-setup.md" } }, { "id": "gitlens.welcome.settings", - "title": "Easily customize every aspect of GitLens", - "description": "A rich, interactive settings editor enables seemingly endless customization possibilities.\n\n[Open Settings](command:gitlens.showSettingsPage \"Opens the GitLens Interactive Settings\")", + "title": "%gitlens.welcome.settings.title%", + "description": "%gitlens.welcome.settings.description%", "media": { "markdown": "walkthroughs/getting-started/2-customize.md" } }, { "id": "gitlens.welcome.currentLineBlame", - "title": "See who made what changes at a glance", - "description": "Current line and status bar blame provide historical context about line changes.", + "title": "%gitlens.welcome.currentLineBlame.title%", + "description": "%gitlens.welcome.currentLineBlame.description%", "media": { "markdown": "walkthroughs/getting-started/3-current-line-blame.md" } }, { "id": "gitlens.welcome.gitCodeLens", - "title": "View Git authorship via CodeLens", - "description": "CodeLens adds contextual authorship information and links at the top of each file and at the beginning of each block of code.", + "title": "%gitlens.welcome.gitCodeLens.title%", + "description": "%gitlens.welcome.gitCodeLens.description%", "media": { "markdown": "walkthroughs/getting-started/4-git-codelens.md" } }, { "id": "gitlens.welcome.revisionHistory", - "title": "Easily navigate revision history", + "title": "%gitlens.welcome.revisionHistory.title%", "description": "", "media": { "markdown": "walkthroughs/getting-started/5-revision-history.md" @@ -10894,56 +10894,56 @@ }, { "id": "gitlens.welcome.fileAnnotations", - "title": "See more context with file annotations", - "description": "Whole file annotations place visual indicators in the gutter and scroll bar that provide additional context about changes.", + "title": "%gitlens.welcome.fileAnnotations.title%", + "description": "%gitlens.welcome.fileAnnotations.description%", "media": { "markdown": "walkthroughs/getting-started/6-file-annotations.md" } }, { "id": "gitlens.welcome.gitSideBarViews", - "title": "Explore repositories from the side bar", - "description": "Rich views expose even more Git functionality in your side bar.\n\n[Set Views Layout](command:gitlens.setViewsLayout)", + "title": "%gitlens.welcome.gitSideBarViews.title%", + "description": "%gitlens.welcome.gitSideBarViews.description%", "media": { "markdown": "walkthroughs/getting-started/7-git-side-bar-views.md" } }, { "id": "gitlens.welcome.hostingServiceIntegrations", - "title": "Integrate with Git hosting services", - "description": "Quickly gain insights from pull requests and issues without leaving your editor.", + "title": "%gitlens.welcome.hostingServiceIntegrations.title%", + "description": "%gitlens.welcome.hostingServiceIntegrations.description%", "media": { "markdown": "walkthroughs/getting-started/8-hosting-service-integrations.md" } }, { "id": "gitlens.welcome.gitCommandPalette", - "title": "Work faster with Git Command Palette", - "description": "Now you don't have to remember all those Git commands.\n\n[Open Git Command Palette](command:gitlens.gitCommands)", + "title": "%gitlens.welcome.gitCommandPalette.title%", + "description": "%gitlens.welcome.gitCommandPalette.description%", "media": { "markdown": "walkthroughs/getting-started/9-git-command-palette.md" } }, { "id": "gitlens.welcome.interactiveRebaseEditor", - "title": "Visualize interactive rebase operations", - "description": "A user-friendly interactive rebase editor to easily configure an interactive rebase session", + "title": "%gitlens.welcome.interactiveRebaseEditor.title%", + "description": "%gitlens.welcome.interactiveRebaseEditor.description%", "media": { "markdown": "walkthroughs/getting-started/10-interactive-rebase-editor.md" } }, { "id": "gitlens.welcome.terminal", - "title": "Jump to git details from the terminal", - "description": "Using ctrl/cmd+click on autolinks in the integrated terminal will quickly jump to more details for commits, branches, tags, and more.", + "title": "%gitlens.welcome.terminal.title%", + "description": "%gitlens.welcome.terminal.description%", "media": { "markdown": "walkthroughs/getting-started/11-terminal.md" } }, { "id": "gitlens.welcome.plus", - "title": "Introducing GitLens+", - "description": "Check out the all-new, completely optional, GitLens+ features.\n\n[Learn about GitLens+ features](command:gitlens.plus.learn?false \"Open the GitLens+ features walkthrough\")", + "title": "%gitlens.welcome.plus.title%", + "description": "%gitlens.welcome.plus.description%", "media": { "markdown": "walkthroughs/getting-started/12-plus.md" } @@ -10952,13 +10952,13 @@ }, { "id": "gitlens.plus", - "title": "Introducing GitLens+", - "description": "Get even more out of GitLens in VS Code!", + "title": "%gitlens.plus.title%", + "description": "%gitlens.plus.description%", "steps": [ { "id": "gitlens.plus.intro.tryNow", - "title": "Introducing GitLens+", - "description": "Try GitLens+ features now, without an account, for 3 days.\n\n[Try GitLens+ features now](command:gitlens.plus.startPreviewTrial)", + "title": "%gitlens.plus.intro.tryNow.title%", + "description": "%gitlens.plus.intro.tryNow.description%", "media": { "markdown": "walkthroughs/plus/1-intro.md" }, @@ -10966,8 +10966,8 @@ }, { "id": "gitlens.plus.intro.signIn", - "title": "Introducing GitLens+", - "description": "Sign in for use on public repos and get an additional 7 day trial for private repos.\n\n[Sign in to GitLens+](command:gitlens.plus.loginOrSignUp)", + "title": "%gitlens.plus.intro.signIn.title%", + "description": "%gitlens.plus.intro.signIn.description%", "media": { "markdown": "walkthroughs/plus/1-intro.md" }, @@ -10975,40 +10975,40 @@ }, { "id": "gitlens.plus.intro", - "title": "Introducing GitLens+", + "title": "%gitlens.plus.intro.title%", "media": { "markdown": "walkthroughs/plus/1-intro.md" }, "when": "gitlens:plus:state > 2" }, { - "id": "gitlens.plus.visualFileHistory", - "title": "Visualize file history", - "description": "A more visual way to analyze and explore changes made to a file.\n\n[Open Visual File History view](command:gitlens.showTimelineView)", + "id": "gitlens.premium.visualFileHistory", + "title": "%gitlens.plus.visualFileHistory.title%", + "description": "%gitlens.plus.visualFileHistory.description%", "media": { "markdown": "walkthroughs/plus/3-visual-file-history.md" } }, { "id": "gitlens.plus.worktrees", - "title": "Worktrees", - "description": "Create worktrees to have multiple branches checked-out at once on the same repository.\n\n[Open Worktrees view](command:gitlens.showWorktreesView)", + "title": "%gitlens.plus.worktrees.title%", + "description": "%gitlens.plus.worktrees.description%", "media": { "markdown": "walkthroughs/plus/2-worktrees.md" } }, { "id": "gitlens.plus.comingSoon", - "title": "More coming soon", - "description": "Stay tuned!", + "title": "%gitlens.plus.comingSoon.title%", + "description": "%gitlens.plus.comingSoon.description%", "media": { "markdown": "walkthroughs/plus/4-coming-soon.md" } }, { "id": "gitlens.plus.tryNow", - "title": "Try GitLens+ now", - "description": "Try GitLens+ features now, without an account, for 3 days.\n\n[Try GitLens+ features now](command:gitlens.plus.startPreviewTrial)", + "title": "%gitlens.plus.tryNow.title%", + "description": "%gitlens.plus.tryNow.description%", "media": { "markdown": "walkthroughs/plus/5-try-now.md" }, @@ -11016,8 +11016,8 @@ }, { "id": "gitlens.plus.signIn", - "title": "Get access to GitLens+ features on public repos", - "description": "Sign in for use on public repos and get an additional 7 day trial for private repos.\n\n[Sign in to GitLens+](command:gitlens.plus.loginOrSignUp)", + "title": "%gitlens.plus.signIn.title%", + "description": "%gitlens.plus.signIn.description%", "media": { "markdown": "walkthroughs/plus/5-try-now.md" }, @@ -11030,7 +11030,7 @@ "scripts": { "analyze:bundle": "webpack --mode production --env analyzeBundle", "analyze:deps": "webpack --env analyzeDeps", - "build": "webpack --mode development", + "build": "gulp translations-generate && webpack --mode development", "build:extension": "webpack --mode development --config-name extension", "build:webviews": "webpack --mode development --config-name webviews", "build:tests": "tsc -p tsconfig.test.json && tsc-alias -p tsconfig.test.json", @@ -11076,7 +11076,8 @@ "node-fetch": "2.6.7", "path-browserify": "1.0.1", "sortablejs": "1.14.0", - "uuid": "8.3.2" + "uuid": "8.3.2", + "vscode-nls": "^5.0.0" }, "devDependencies": { "@squoosh/lib": "0.4.0", @@ -11108,6 +11109,10 @@ "eslint-plugin-import": "2.25.4", "fork-ts-checker-webpack-plugin": "6.5.0", "glob": "7.2.0", + "gulp": "^4.0.2", + "gulp-filter": "^7.0.0", + "gulp-sourcemaps": "^3.0.0", + "gulp-typescript": "^6.0.0-alpha.1", "html-loader": "3.1.0", "html-webpack-plugin": "5.5.0", "image-minimizer-webpack-plugin": "3.2.1", @@ -11125,6 +11130,7 @@ "tsc-alias": "1.6.4", "typescript": "4.6.2", "vsce": "2.7.0", + "vscode-nls-dev": "^4.0.0", "webpack": "5.70.0", "webpack-bundle-analyzer": "4.5.0", "webpack-cli": "4.9.2", diff --git a/package.nls.json b/package.nls.json new file mode 100644 index 0000000000000..a90c480138c4f --- /dev/null +++ b/package.nls.json @@ -0,0 +1,1043 @@ +{ + "gitlens.displayName": "GitLens — Git supercharged", + "gitlens.description": "Supercharge Git within VS Code — Visualize code authorship at a glance via Git blame annotations and CodeLens, seamlessly navigate and explore Git repositories, gain valuable insights via rich visualizations and powerful comparison commands, and so much more", + "gitlens.license": "SEE LICENSE IN LICENSE", + "gitlens.badges.joinUs.description": "Join us in the #gitlens channel", + "gitlens.contributes.configuration.currentLineBlame.title": "Current Line Blame", + "gitlens.currentLine.enabled.markdownDescription": "Specifies whether to provide a blame annotation for the current line, by default. Use the `Toggle Line Blame Annotations` command (`gitlens.toggleLineBlame`) to toggle the annotations on and off for the current window", + "gitlens.currentLine.pullRequests.enabled.markdownDescription": "Specifies whether to provide information about the Pull Request (if any) that introduced the commit in the current line blame annotation. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.currentLine.format.markdownDescription": "Specifies the format of the current line blame annotation. See [_Commit Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#commit-tokens) in the GitLens docs. Date formatting is controlled by the `#gitlens.currentLine.dateFormat#` setting", + "gitlens.currentLine.scrollable.markdownDescription": "Specifies whether the current line blame annotation can be scrolled into view when it is outside the viewport. **NOTE**: Setting this to `false` will inhibit the hovers from showing over the annotation; Set `#gitlens.hovers.currentLine.over#` to `line` to enable the hovers to show anywhere over the line.", + "gitlens.currentLine.dateFormat.markdownDescription": "Specifies how to format absolute dates (e.g. using the `${date}` token) for the current line blame annotation. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats", + "gitlens.contributes.configuration.gitCodeLens.title": "Git CodeLens", + "gitlens.codeLens.enabled.markdownDescription": "Specifies whether to provide any Git CodeLens, by default. Use the `Toggle Git CodeLens` command (`gitlens.toggleCodeLens`) to toggle the Git CodeLens on and off for the current window", + "gitlens.codeLens.authors.enabled.markdownDescription": "Specifies whether to provide an _authors_ CodeLens, showing number of authors of the file or code block and the most prominent author (if there is more than one)", + "gitlens.codeLens.authors.command.disable.description": "Disables click interaction", + "gitlens.codeLens.authors.command.toggleFileBlame.description": "Toggles file blame", + "gitlens.codeLens.authors.command.toggleFileHeatmap.description": "Toggles file heatmap", + "gitlens.codeLens.authors.command.toggleFileChanges.description": "Toggles file changes since before the commit", + "gitlens.codeLens.authors.command.toggleFileChangesOnly.description": "Toggles file changes from the commit", + "gitlens.codeLens.authors.command.diffWithPrevious.description": "Compares the current committed file with the previous commit", + "gitlens.codeLens.authors.command.revealCommitInView.description": "Reveals the commit in the Side Bar", + "gitlens.codeLens.authors.command.showCommitsInView.description": "Searches for commits within the range", + "gitlens.codeLens.authors.command.showQuickCommitDetails.description": "Shows a commit details quick pick menu", + "gitlens.codeLens.authors.command.showQuickCommitFileDetails.description": "Shows a commit file details quick pick menu", + "gitlens.codeLens.authors.commandens.showQuickFileHistory.description": "Shows a file history quick pick menu", + "gitlens.codeLens.authors.command.showQuickRepoHistory.description": "Shows a branch history quick pick menu", + "gitlens.codeLens.authors.command.openCommitOnRemote.description": "Opens the commit on the remote service (when available)", + "gitlens.codeLens.authors.command.copyRemoteCommitUrl.description": "Copies the remote commit url to the clipboard (when available)", + "gitlens.codeLens.authors.command.openFileOnRemote.description": "Opens the file revision on the remote service (when available)", + "gitlens.codeLens.authors.command.copyRemoteFileUrl.description": "Copies the remote file url to the clipboard (when available)", + "gitlens.codeLens.authors.command.markdownDescription": "Specifies the command to be executed when an _authors_ CodeLens is clicked", + "gitlens.codeLens.recentChange.enabled.markdownDescription": "Specifies whether to provide a _recent change_ CodeLens, showing the author and date of the most recent commit for the file or code block", + "gitlens.codeLens.recentChange.command.disable.description": "Disables click interaction", + "gitlens.codeLens.recentChange.command.toggleFileBlame.description": "Toggles file blame", + "gitlens.codeLens.recentChange.command.toggleFileHeatmap.description": "Toggles file heatmap", + "gitlens.codeLens.recentChange.command.toggleFileChanges.description": "Toggles file changes since before the commit", + "gitlens.codeLens.recentChange.command.toggleFileChangesOnly.description": "Toggles file changes from the commit", + "gitlens.codeLens.recentChange.command.diffWithPrevious.description": "Compares the current committed file with the previous commit", + "gitlens.codeLens.recentChange.command.revealCommitInView.description": "Reveals the commit in the Side Bar", + "gitlens.codeLens.recentChange.command.showCommitsInView.description": "Searches for the commit", + "gitlens.codeLens.recentChange.command.showQuickCommitDetails.description": "Shows a commit details quick pick menu", + "gitlens.codeLens.recentChange.command.showQuickCommitFileDetails.description": "Shows a commit file details quick pick menu", + "gitlens.codeLens.recentChange.command.showQuickFileHistory.description": "Shows a file history quick pick menu", + "gitlens.codeLens.recentChange.command.showQuickRepoHistory.description": "Shows a branch history quick pick menu", + "gitlens.codeLens.recentChange.command.openCommitOnRemote.description": "Opens the commit on the remote service (when available)", + "gitlens.codeLens.recentChange.command.copyRemoteCommitUrl.description": "Copies the remote commit url to the clipboard (when available)", + "gitlens.codeLens.recentChange.command.openFileOnRemote.description": "Opens the file revision on the remote service (when available)", + "gitlens.codeLens.recentChange.command.copyRemoteFileUrl.description": "Copies the remote file url to the clipboard (when available)", + "gitlens.codeLens.recentChange.command.markdownDescription": "Specifies the command to be executed when a _recent change_ CodeLens is clicked", + "gitlens.codeLens.scopes.document.description": "Adds CodeLens at the top of the document", + "gitlens.codeLens.scopes.containers.description": "Adds CodeLens at the start of container-like symbols (modules, classes, interfaces, etc)", + "gitlens.codeLens.scopes.blocks.description": "Adds CodeLens at the start of block-like symbols (functions, methods, etc) lines", + "gitlens.codeLens.scopes.markdownDescription": "Specifies where Git CodeLens will be shown in the document", + "gitlens.codeLens.symbolScopes.markdownDescription": "Specifies a set of document symbols where Git CodeLens will or will not be shown in the document. Prefix with `!` to avoid providing a Git CodeLens for the symbol. Must be a member of `SymbolKind`", + "gitlens.codeLens.includeSingleLineSymbols.markdownDescription": "Specifies whether to provide any Git CodeLens on symbols that span only a single line", + "gitlens.strings.codeLens.unsavedChanges.recentChangeAndAuthors.markdownDescription": "Specifies the string to be shown in place of both the _recent change_ and _authors_ CodeLens when there are unsaved changes", + "gitlens.strings.codeLens.unsavedChanges.recentChangeOnly.markdownDescription": "Specifies the string to be shown in place of the _recent change_ CodeLens when there are unsaved changes", + "gitlens.strings.codeLens.unsavedChanges.authorsOnly.markdownDescription": "Specifies the string to be shown in place of the _authors_ CodeLens when there are unsaved changes", + "gitlens.codeLens.dateFormat.markdownDescription": "Specifies how to format absolute dates in the Git CodeLens. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats", + "gitlens.codeLens.scopesByLanguage.deprecationMessage": "Deprecated. Use per-language `gitlens.codeLens.scopes` and `gitlens.codeLens.symbolScopes` settings instead", + "gitlens.codeLens.scopesByLanguage.markdownDeprecationMessage": "Deprecated. Use the per-language `#gitlens.codeLens.scopes#` and `#gitlens.codeLens.symbolScopes#` settings instead", + "gitlens.contributes.configuration.statusBarBlame.title": "Status Bar Blame", + "gitlens.statusBar.enabled.markdownDescription": "Specifies whether to provide blame information in the status bar", + "gitlens.statusBar.pullRequests.enabled.markdownDescription": "Specifies whether to provide information about the Pull Request (if any) that introduced the commit in the status bar. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.statusBar.format.markdownDescription": "Specifies the format of the blame information in the status bar. See [_Commit Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#commit-tokens) in the GitLens docs. Date formatting is controlled by the `#gitlens.statusBar.dateFormat#` setting", + "gitlens.statusBar.alignment.left.description": "Aligns to the left", + "gitlens.statusBar.alignment.right.description": "Aligns to the right", + "gitlens.statusBar.alignment.markdownDescription": "Specifies the blame alignment in the status bar", + "gitlens.statusBar.command.toggleFileBlame.description": "Toggles file blame", + "gitlens.statusBar.command.toggleFileHeatmap.description": "Toggles file heatmap", + "gitlens.statusBar.command.toggleFileChanges.description": "Toggles file changes since before the commit", + "gitlens.statusBar.command.toggleFileChangesOnly.description": "Toggles file changes from the commit", + "gitlens.statusBar.command.toggleCodeLens.description": "Toggles Git CodeLens", + "gitlens.statusBar.command.diffWithPrevious.description": "Compares the current line commit with the previous", + "gitlens.statusBar.command.diffWithWorking.description": "Compares the current line commit with the working tree", + "gitlens.statusBar.command.revealCommitInView.description": "Reveals the commit in the Side Bar", + "gitlens.statusBar.command.showCommitsInView.description": "Searches for the commit", + "gitlens.statusBar.command.showQuickCommitDetails.description": "Shows a commit details quick pick menu", + "gitlens.statusBar.command.showQuickCommitFileDetails.description": "Shows a commit file details quick pick menu", + "gitlens.statusBar.command.showQuickFileHistory.description": "Shows a file history quick pick menu", + "gitlens.statusBar.command.showQuickRepoHistory.description": "Shows a branch history quick pick menu", + "gitlens.statusBar.command.openCommitOnRemote.description": "Opens the commit on the remote service (when available)", + "gitlens.statusBar.command.copyRemoteCommitUrl.description": "Copies the remote commit url to the clipboard (when available)", + "gitlens.statusBar.command.openFileOnRemote.description": "Opens the file revision on the remote service (when available)", + "gitlens.statusBar.command.copyRemoteFileUrl.description": "Copies the remote file url to the clipboard (when available)", + "gitlens.statusBar.command.markdownDescription": "Specifies the command to be executed when the blame status bar item is clicked", + "gitlens.statusBar.tooltipFormat.markdownDescription": "Specifies the format (in markdown) of hover shown over the blame information in the status bar. See [_Commit Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#commit-tokens) in the GitLens docs", + "gitlens.statusBar.reduceFlicker.markdownDescription": "Specifies whether to avoid clearing the previous blame information when changing lines to reduce status bar \"flashing\"", + "gitlens.statusBar.dateFormat.markdownDescription": "Specifies how to format absolute dates (e.g. using the `${date}` token) in the blame information in the status bar. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats", + "gitlens.contributes.configuration.hovers.title": "Hovers", + "gitlens.hovers.enabled.markdownDescription": "Specifies whether to provide any hovers", + "gitlens.hovers.avatars.markdownDescription": "Specifies whether to show avatar images in hovers", + "gitlens.hovers.avatarSize.markdownDescription": "Specifies the size of the avatar images in hovers", + "gitlens.hovers.pullRequests.enabled.markdownDescription": "Specifies whether to provide information about the Pull Request (if any) that introduced the commit in the hovers. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.hovers.autolinks.enabled.markdownDescription": "Specifies whether to automatically link external resources in commit messages", + "gitlens.hovers.autolinks.enhanced.markdownDescription": "Specifies whether to lookup additional details about automatically link external resources in commit messages. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.hovers.currentLine.enabled.markdownDescription": "Specifies whether to provide any hovers for the current line", + "gitlens.hovers.currentLine.over.annotation.description": "Only shown when hovering over the line annotation", + "gitlens.hovers.currentLine.over.line.description": "Shown when hovering anywhere over the line", + "gitlens.hovers.currentLine.over.markdownDescription": "Specifies when to trigger hovers for the current line", + "gitlens.hovers.currentLine.details.markdownDescription": "Specifies whether to provide a _commit details_ hover for the current line", + "gitlens.hovers.currentLine.changes.markdownDescription": "Specifies whether to provide a _changes (diff)_ hover for the current line", + "gitlens.hovers.annotations.enabled.markdownDescription": "Specifies whether to provide any hovers when showing blame annotations", + "gitlens.hovers.annotations.over.annotation.description": "Only shown when hovering over the line annotation", + "gitlens.hovers.annotations.over.line.description": "Shown when hovering anywhere over the line", + "gitlens.hovers.annotations.over.markdownDescription": "Specifies when to trigger hovers when showing blame annotations", + "gitlens.hovers.annotations.details.markdownDescription": "Specifies whether to provide a _commit details_ hover for all lines when showing blame annotations", + "gitlens.hovers.annotations.changes.markdownDescription": "Specifies whether to provide a _changes (diff)_ hover for all lines when showing blame annotations", + "gitlens.hovers.detailsMarkdownFormat.markdownDescription": "Specifies the format (in markdown) of the _commit details_ hover. See [_Commit Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#commit-tokens) in the GitLens docs", + "gitlens.hovers.changesDiff.line.description": "Shows only the changes to the line", + "gitlens.hovers.changesDiff.hunk.description": "Shows the set of related changes", + "gitlens.hovers.changesDiff.markdownDescription": "Specifies whether to show just the changes to the line or the set of related changes in the _changes (diff)_ hover", + "gitlens.contributes.configuration.views.title": "Views", + "gitlens.views.defaultItemLimit.markdownDescription": "Specifies the default number of items to show in a view list. Use 0 to specify no limit", + "gitlens.views.pageItemLimit.markdownDescription": "Specifies the number of items to show in a each page when paginating a view list. Use 0 to specify no limit", + "gitlens.views.showRelativeDateMarkers.markdownDescription": "Specifies whether to show relative date markers (_Less than a week ago_, _Over a week ago_, _Over a month ago_, etc) on revision (commit) histories in the views", + "gitlens.views.formats.commits.label.markdownDescription": "Specifies the format of commits in the views. See [_Commit Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#commit-tokens) in the GitLens docs", + "gitlens.views.formats.commits.description.markdownDescription": "Specifies the description format of commits in the views. See [_Commit Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#commit-tokens) in the GitLens docs", + "gitlens.views.formats.files.label.markdownDescription": "Specifies the format of a file in the views. See [_File Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#file-tokens) in the GitLens docs", + "gitlens.views.formats.files.description.markdownDescription": "Specifies the description format of a file in the views. See [_File Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#file-tokens) in the GitLens docs", + "gitlens.views.formats.stashes.label.markdownDescription": "Specifies the format of stashes in the views. See [_Commit Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#commit-tokens) in the GitLens docs", + "gitlens.views.formats.stashes.description.markdownDescription": "Specifies the description format of stashes in the views. See [_Commit Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#commit-tokens) in the GitLens docs", + "gitlens.views.commitFileFormat.deprecationMessage": "Deprecated. Use `gitlens.views.formats.files.label` instead", + "gitlens.views.commitFileFormat.markdownDeprecationMessage": "Deprecated. Use `#gitlens.views.formats.files.label#` instead", + "gitlens.views.commitFileDescriptionFormat.deprecationMessage": "Deprecated. Use `gitlens.views.formats.files.description` instead", + "gitlens.views.commitFileDescriptionFormat.markdownDeprecationMessage": "Deprecated. Use `#gitlens.views.formats.files.description#` instead", + "gitlens.views.commitFormat.deprecationMessage": "Deprecated. Use `gitlens.views.formats.commits.label` instead", + "gitlens.views.commitFormat.markdownDeprecationMessage": "Deprecated. Use `#gitlens.views.commits.files.label#` instead", + "gitlens.views.commitDescriptionFormat.deprecationMessage": "Deprecated. Use `gitlens.views.formats.commits.description` instead", + "gitlens.views.commitDescriptionFormat.markdownDeprecationMessage": "Deprecated. Use `#gitlens.views.formats.commits.description#` instead", + "gitlens.views.stashFileFormat.deprecationMessage": "Deprecated. Use `gitlens.views.formats.files.label` instead", + "gitlens.views.stashFileFormat.markdownDeprecationMessage": "Deprecated. Use `#gitlens.views.formats.files.label#` instead", + "gitlens.views.stashFileDescriptionFormat.deprecationMessage": "Deprecated. Use `gitlens.views.formats.files.description` instead", + "gitlens.views.stashFileDescriptionFormat.markdownDeprecationMessage": "Deprecated. Use `#gitlens.views.formats.files.description#` instead", + "gitlens.views.stashFormat.deprecationMessage": "Deprecated. Use `gitlens.views.formats.stashes.label` instead", + "gitlens.views.stashFormat.markdownDeprecationMessage": "Deprecated. Use `#gitlens.views.stashes.files.label#` instead", + "gitlens.views.stashDescriptionFormat.deprecationMessage": "Deprecated. Use `gitlens.views.formats.stashes.description` instead", + "gitlens.views.stashDescriptionFormat.markdownDeprecationMessage": "Deprecated. Use `#gitlens.views.formats.stashes.description#` instead", + "gitlens.views.statusFileFormat.deprecationMessage": "Deprecated. Use `gitlens.views.formats.files.label` instead", + "gitlens.views.statusFileFormat.markdownDeprecationMessage": "Deprecated. Use `#gitlens.views.formats.files.label#` instead", + "gitlens.views.statusFileDescriptionFormat.deprecationMessage": "Deprecated. Use `gitlens.views.formats.files.description` instead", + "gitlens.views.statusFileDescriptionFormat.markdownDeprecationMessage": "Deprecated. Use `#gitlens.views.formats.files.description#` instead", + "gitlens.contributes.configuration.commitsView.title": "Commits View", + "gitlens.views.commits.showBranchComparison.hide.description": "Hides the branch comparison", + "gitlens.views.commits.showBranchComparison.branch.description": "Compares the current branch with a user-selected reference", + "gitlens.views.commits.showBranchComparison.working.description": "Compares the working tree with a user-selected reference", + "gitlens.views.commits.showBranchComparison.markdownDescription": "Specifies whether to show a comparison of the current branch or the working tree with a user-selected reference (branch, tag. etc) in the _Commits_ view", + "gitlens.views.commits.pullRequests.enabled.markdownDescription": "Specifies whether to query for pull requests associated with the current branch and commits in the _Commits_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.views.commits.pullRequests.showForBranches.markdownDescription": "Specifies whether to show pull requests (if any) associated with the current branch in the _Commits_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.views.commits.pullRequests.showForCommits.markdownDescription": "Specifies whether to show pull requests (if any) associated with commits in the _Commits_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.views.commits.files.layout.auto.description": "Automatically switches between displaying files as a `tree` or `list` based on the `#gitlens.views.commits.files.threshold#` value and the number of files at each nesting level", + "gitlens.views.commits.files.layout.list.description": "Displays files as a list", + "gitlens.views.commits.files.layout.tree.description": "Displays files as a tree", + "gitlens.views.commits.files.layout.markdownDescription": "Specifies how the _Commits_ view will display files", + "gitlens.views.commits.files.threshold.markdownDescription": "Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the _Commits_ view. Only applies when `#gitlens.views.commits.files.layout#` is set to `auto`", + "gitlens.views.commits.files.compact.markdownDescription": "Specifies whether to compact (flatten) unnecessary file nesting in the _Commits_ view. Only applies when `#gitlens.views.commits.files.layout#` is set to `tree` or `auto`", + "gitlens.views.commits.avatars.markdownDescription": "Specifies whether to show avatar images instead of commit (or status) icons in the _Commits_ view", + "gitlens.views.commits.reveal.markdownDescription": "Specifies whether to reveal commits in the _Commits_ view, otherwise they revealed in the _Repositories_ view", + "gitlens.contributes.configuration.repositoriesView.title": "Repositories View", + "gitlens.views.repositories.showBranchComparison.hide.description": "Hides the branch comparison", + "gitlens.views.repositories.showBranchComparison.branch.description": "Compares the current branch with a user-selected reference", + "gitlens.views.repositories.showBranchComparison.working.description": "Compares the working tree with a user-selected reference", + "gitlens.views.repositories.showBranchComparison.markdownDescription": "Specifies whether to show a comparison of the current branch or the working tree with a user-selected reference (branch, tag. etc) in the _Repositories_ view", + "gitlens.views.repositories.showUpstreamStatus.markdownDescription": "Specifies whether to show the upstream status of the current branch for each repository in the _Repositories_ view", + "gitlens.views.repositories.includeWorkingTree.markdownDescription": "Specifies whether to include working tree file status for each repository in the _Repositories_ view", + "gitlens.views.repositories.pullRequests.enabled.markdownDescription": "Specifies whether to query for pull requests associated with branches and commits in the _Repositories_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.views.repositories.pullRequests.showForBranches.markdownDescription": "Specifies whether to show pull requests (if any) associated with branches in the _Repositories_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.views.repositories.pullRequests.showForCommits.markdownDescription": "Specifies whether to show pull requests (if any) associated with commits in the _Repositories_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.views.repositories.showCommits.markdownDescription": "Specifies whether to show the commits on the current branch for each repository in the _Repositories_ view", + "gitlens.views.repositories.showBranches.markdownDescription": "Specifies whether to show the branches for each repository in the _Repositories_ view", + "gitlens.views.repositories.showRemotes.markdownDescription": "Specifies whether to show the remotes for each repository in the _Repositories_ view", + "gitlens.views.repositories.showStashes.markdownDescription": "Specifies whether to show the stashes for each repository in the _Repositories_ view", + "gitlens.views.repositories.showTags.markdownDescription": "Specifies whether to show the tags for each repository in the _Repositories_ view", + "gitlens.views.repositories.showContributors.markdownDescription": "Specifies whether to show the contributors for each repository in the _Repositories_ view", + "gitlens.views.repositories.showWorktrees.markdownDescription": "Specifies whether to show the worktrees for each repository in the _Repositories_ view", + "gitlens.views.repositories.showIncomingActivity.markdownDescription": "Specifies whether to show the experimental incoming activity for each repository in the _Repositories_ view", + "gitlens.views.repositories.autoRefresh.markdownDescription": "Specifies whether to automatically refresh the _Repositories_ view when the repository or the file system changes", + "gitlens.views.repositories.autoReveal.markdownDescription": "Specifies whether to automatically reveal repositories in the _Repositories_ view when opening files", + "gitlens.views.repositories.avatars.markdownDescription": "Specifies whether to show avatar images instead of commit (or status) icons in the _Repositories_ view", + "gitlens.views.repositories.branches.layout.list.description": "Displays branches as a list", + "gitlens.views.repositories.branches.layout.tree.description": "Displays branches as a tree when branch names contain slashes `/`", + "gitlens.views.repositories.branches.layout.markdownDescription": "Specifies how the _Repositories_ view will display branches", + "gitlens.views.repositories.files.layout.auto.description": "Automatically switches between displaying files as a `tree` or `list` based on the `#gitlens.views.repositories.files.threshold#` value and the number of files at each nesting level", + "gitlens.views.repositories.files.layout.list.description": "Displays files as a list", + "gitlens.views.repositories.files.layout.tree.description": "Displays files as a tree", + "gitlens.views.repositories.files.layout.markdownDescription": "Specifies how the _Repositories_ view will display files", + "gitlens.views.repositories.files.threshold.markdownDescription": "Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the _Repositories_ view. Only applies when `#gitlens.views.repositories.files.layout#` is set to `auto`", + "gitlens.views.repositories.files.compact.markdownDescription": "Specifies whether to compact (flatten) unnecessary file nesting in the _Repositories_ view. Only applies when `#gitlens.views.repositories.files.layout#` is set to `tree` or `auto`", + "gitlens.views.repositories.compact.markdownDescription": "Specifies whether to show the _Repositories_ view in a compact display density", + "gitlens.views.repositories.branches.showBranchComparison.hide.description": "Hides the branch comparison", + "gitlens.views.repositories.branches.showBranchComparison.branch.description": "Compares the branch with a user-selected reference", + "gitlens.views.repositories.branches.showBranchComparison.markdownDescription": "Specifies whether to show a comparison of the branch with a user-selected reference (branch, tag. etc) under each branch in the _Repositories_ view", + "gitlens.views.repositories.enabled.deprecationMessage": "Deprecated. This setting is no longer used", + "gitlens.views.repositories.enabled.markdownDeprecationMessage": "Deprecated. This setting is no longer used", + "gitlens.contributes.configuration.fileHistoryView.title": "File History View", + "gitlens.views.fileHistory.files.layout.auto.description": "Automatically switches between displaying files as a `tree` or `list` based on the `#gitlens.views.fileHistory.files.threshold#` value and the number of files at each nesting level", + "gitlens.views.fileHistory.files.layout.list.description": "Displays files as a list", + "gitlens.views.fileHistory.files.layout.tree.description": "Displays files as a tree", + "gitlens.views.fileHistory.files.layout.markdownDescription": "Specifies how the _File History_ view will display files when showing the history of a folder", + "gitlens.views.fileHistory.files.threshold.markdownDescription": "Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the _File History_ view. Only applies to folder history and when `#gitlens.views.fileHistory.files.layout#` is set to `auto`", + "gitlens.views.fileHistory.files.compact.markdownDescription": "Specifies whether to compact (flatten) unnecessary file nesting in the _File History_ view. Only applies to folder history and when `#gitlens.views.fileHistory.files.layout#` is set to `tree` or `auto`", + "gitlens.views.fileHistory.avatars.markdownDescription": "Specifies whether to show avatar images instead of status icons in the _File History_ view", + "gitlens.advanced.fileHistoryFollowsRenames.markdownDescription": "Specifies whether file histories will follow renames — will affect how merge commits are shown in histories", + "gitlens.advanced.fileHistoryShowAllBranches.markdownDescription": "Specifies whether file histories will show commits from all branches", + "gitlens.contributes.configuration.lineHistoryView.title": "Line History View", + "gitlens.views.lineHistory.avatars.markdownDescription": "Specifies whether to show avatar images instead of status icons in the _Line History_ view", + "gitlens.views.lineHistory.enabled.deprecationMessage": "Deprecated. This setting is no longer used", + "gitlens.views.lineHistory.enabled.markdownDeprecationMessage": "Deprecated. This setting is no longer used", + "gitlens.contributes.configuration.branchesView.title": "Branches View", + "gitlens.views.branches.showBranchComparison.hide.description": "Hides the branch comparison", + "gitlens.views.branches.showBranchComparison.branch.description": "Compares the branch with a user-selected reference", + "gitlens.views.branches.showBranchComparison.markdownDescription": "Specifies whether to show a comparison of the branch with a user-selected reference (branch, tag. etc) in the _Branches_ view", + "gitlens.views.branches.pullRequests.enabled.markdownDescription": "Specifies whether to query for pull requests associated with each branch and commits in the _Branches_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.views.branches.pullRequests.showForBranches.markdownDescription": "Specifies whether to show pull requests (if any) associated with each branch in the _Branches_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.views.branches.pullRequests.showForCommits.markdownDescription": "Specifies whether to show pull requests (if any) associated with commits in the _Branches_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.views.branches.branches.layout.list.description": "Displays branches as a list", + "gitlens.views.branches.branches.layout.tree.description": "Displays branches as a tree when branch names contain slashes `/`", + "gitlens.views.branches.branches.layout.markdownDescription": "Specifies how the _Branches_ view will display branches", + "gitlens.sortBranchesBy.dateDescending.description": "Sorts branches by the most recent commit date in descending order", + "gitlens.sortBranchesBy.dateAscending.description": "Sorts branches by the most recent commit date in ascending order", + "gitlens.sortBranchesBy.nameAscending.description": "Sorts branches by name in ascending order", + "gitlens.sortBranchesBy.nameDescending.description": "Sorts branches by name in descending order", + "gitlens.sortBranchesBy.markdownDescription": "Specifies how branches are sorted in quick pick menus and views", + "gitlens.views.branches.files.layout.auto.description": "Automatically switches between displaying files as a `tree` or `list` based on the `#gitlens.views.branches.files.threshold#` value and the number of files at each nesting level", + "gitlens.views.branches.files.layout.list.description": "Displays files as a list", + "gitlens.views.branches.files.layout.tree.description": "Displays files as a tree", + "gitlens.views.branches.files.layout.markdownDescription": "Specifies how the _Branches_ view will display files", + "gitlens.views.branches.files.threshold.markdownDescription": "Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the _Branches_ view. Only applies when `#gitlens.views.branches.files.layout#` is set to `auto`", + "gitlens.views.branches.files.compact.markdownDescription": "Specifies whether to compact (flatten) unnecessary file nesting in the _Branches_ view. Only applies when `#gitlens.views.branches.files.layout#` is set to `tree` or `auto`", + "gitlens.views.branches.avatars.markdownDescription": "Specifies whether to show avatar images instead of commit (or status) icons in the _Branches_ view", + "gitlens.views.branches.reveal.markdownDescription": "Specifies whether to reveal branches in the _Branches_ view, otherwise they revealed in the _Repositories_ view", + "gitlens.contributes.configuration.remotesView.title": "Remotes View", + "gitlens.views.remotes.pullRequests.enabled.markdownDescription": "Specifies whether to query for pull requests associated with each branch and commits in the _Remotes_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.views.remotes.pullRequests.showForBranches.markdownDescription": "Specifies whether to show pull requests (if any) associated with each branch in the _Remotes_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.views.remotes.pullRequests.showForCommits.markdownDescription": "Specifies whether to show pull requests (if any) associated with commits in the _Remotes_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.views.remotes.branches.layout.list.description": "Displays branches as a list", + "gitlens.views.remotes.branches.layout.tree.description": "Displays branches as a tree when branch names contain slashes `/`", + "gitlens.views.remotes.branches.layout.markdownDescription": "Specifies how the _Remotes_ view will display branches", + "gitlens.views.remotes.files.layout.auto.description": "Automatically switches between displaying files as a `tree` or `list` based on the `#gitlens.views.remotes.files.threshold#` value and the number of files at each nesting level", + "gitlens.views.remotes.files.layout.list.description": "Displays files as a list", + "gitlens.views.remotes.files.layout.tree.description": "Displays files as a tree", + "gitlens.views.remotes.files.layout.markdownDescription": "Specifies how the _Remotes_ view will display files", + "gitlens.views.remotes.files.threshold.markdownDescription": "Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the _Remotes_ view. Only applies when `#gitlens.views.remotes.files.layout#` is set to `auto`", + "gitlens.views.remotes.files.compact.markdownDescription": "Specifies whether to compact (flatten) unnecessary file nesting in the _Remotes_ view. Only applies when `#gitlens.views.remotes.files.layout#` is set to `tree` or `auto`", + "gitlens.views.remotes.avatars.markdownDescription": "Specifies whether to show avatar images instead of commit (or status) icons in the _Remotes_ view", + "gitlens.views.remotes.reveal.markdownDescription": "Specifies whether to reveal remotes in the _Remotes_ view, otherwise they revealed in the _Repositories_ view", + "gitlens.views.stashes.title": "Stashes View", + "gitlens.views.stashes.files.layout.auto.description": "Automatically switches between displaying files as a `tree` or `list` based on the `#gitlens.views.stashes.files.threshold#` value and the number of files at each nesting level", + "gitlens.views.stashes.files.layout.list.description": "Displays files as a list", + "gitlens.views.stashes.files.layout.tree.description": "Displays files as a tree", + "gitlens.views.stashes.files.layout.markdownDescription": "Specifies how the _Stashes_ view will display files", + "gitlens.views.stashes.files.threshold.markdownDescription": "Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the _Stashes_ view. Only applies when `#gitlens.views.stashes.files.layout#` is set to `auto`", + "gitlens.views.stashes.files.compact.markdownDescription": "Specifies whether to compact (flatten) unnecessary file nesting in the _Stashes_ view. Only applies when `#gitlens.views.stashes.files.layout#` is set to `tree` or `auto`", + "gitlens.views.stashes.reveal.markdownDescription": "Specifies whether to reveal stashes in the _Stashes_ view, otherwise they revealed in the _Repositories_ view", + "gitlens.contributes.configuration.tagsView.title": "Tags View", + "gitlens.views.tags.branches.layout.list.description": "Displays tags as a list", + "gitlens.views.tags.branches.layout.tree.description": "Displays tags as a tree when tags names contain slashes `/`", + "gitlens.views.tags.branches.layout.markdownDescription": "Specifies how the _Tags_ view will display tags", + "gitlens.sortTagsBy.dateDescending.description": "Sorts tags by date in descending order", + "gitlens.sortTagsBy.dateAscending.description": "Sorts tags by date in ascending order", + "gitlens.sortTagsBy.nameAscending.description": "Sorts tags by name in ascending order", + "gitlens.sortTagsBy.nameDescending.description": "Sorts tags by name in descending order", + "gitlens.sortTagsBy.markdownDescription": "Specifies how tags are sorted in quick pick menus and views", + "gitlens.views.tags.files.layout.auto.description": "Automatically switches between displaying files as a `tree` or `list` based on the `#gitlens.views.tags.files.threshold#` value and the number of files at each nesting level", + "gitlens.views.tags.files.layout.list.description": "Displays files as a list", + "gitlens.views.tags.files.layout.tree.description": "Displays files as a tree", + "gitlens.views.tags.files.layout.markdownDescription": "Specifies how the _Tags_ view will display files", + "gitlens.views.tags.files.threshold.markdownDescription": "Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the _Tags_ view. Only applies when `#gitlens.views.tags.files.layout#` is set to `auto`", + "gitlens.views.tags.files.compact.markdownDescription": "Specifies whether to compact (flatten) unnecessary file nesting in the _Tags_ view. Only applies when `#gitlens.views.tags.files.layout#` is set to `tree` or `auto`", + "gitlens.views.tags.avatars.markdownDescription": "Specifies whether to show avatar images instead of commit (or status) icons in the _Tags_ view", + "gitlens.views.tags.reveal.markdownDescription": "Specifies whether to reveal tags in the _Tags_ view, otherwise they revealed in the _Repositories_ view", + "gitlens.contributes.configuration.worktreesView.title": "Worktrees View", + "gitlens.worktrees.promptForLocation.markdownDescription": "Specifies whether to prompt for a path when creating new worktrees", + "gitlens.worktrees.defaultLocation.markdownDescription": "Specifies the default path in which new worktrees will be created", + "gitlens.views.worktrees.showBranchComparison.hide.description": "Hides the branch comparison", + "gitlens.views.worktrees.showBranchComparison.branch.description": "Compares the worktree branch with a user-selected reference", + "gitlens.views.worktrees.showBranchComparison.markdownDescription": "Specifies whether to show a comparison of the worktree branch with a user-selected reference (branch, tag. etc) in the _Worktrees_ view", + "gitlens.views.worktrees.pullRequests.enabled.markdownDescription": "Specifies whether to query for pull requests associated with the worktree branch and commits in the _Worktrees_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.views.worktrees.pullRequests.showForBranches.markdownDescription": "Specifies whether to show pull requests (if any) associated with the worktree branch in the _Worktrees_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.views.worktrees.pullRequests.showForCommits.markdownDescription": "Specifies whether to show pull requests (if any) associated with commits in the _Worktrees_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.views.worktrees.files.layout.auto.description": "Automatically switches between displaying files as a `tree` or `list` based on the `#gitlens.views.worktrees.files.threshold#` value and the number of files at each nesting level", + "gitlens.views.worktrees.files.layout.list.description": "Displays files as a list", + "gitlens.views.worktrees.files.layout.tree.description": "Displays files as a tree", + "gitlens.views.worktrees.files.layout.markdownDescription": "Specifies how the _Worktrees_ view will display files", + "gitlens.views.worktrees.files.threshold.markdownDescription": "Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the _Worktrees_ view. Only applies when `#gitlens.views.worktrees.files.layout#` is set to `auto`", + "gitlens.views.worktrees.files.compact.markdownDescription": "Specifies whether to compact (flatten) unnecessary file nesting in the _Worktrees_ view. Only applies when `#gitlens.views.worktrees.files.layout#` is set to `tree` or `auto`", + "gitlens.views.worktrees.avatars.markdownDescription": "Specifies whether to show avatar images instead of commit (or status) icons in the _Worktrees_ view", + "gitlens.views.worktrees.reveal.markdownDescription": "Specifies whether to reveal worktrees in the _Worktrees_ view, otherwise they revealed in the _Repositories_ view", + "gitlens.contributes.configuration.contributorsView.title": "Contributors View", + "gitlens.views.contributors.showAllBranches.markdownDescription": "Specifies whether to show commits from all branches in the _Contributors_ view", + "gitlens.views.contributors.showStatistics.markdownDescription": "Specifies whether to show contributor statistics in the _Contributors_ view. This can take a while to compute depending on the repository size", + "gitlens.views.contributors.pullRequests.enabled.markdownDescription": "Specifies whether to query for pull requests associated with branches and commits in the _Contributors_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.views.contributors.pullRequests.showForCommits.markdownDescription": "Specifies whether to show pull requests (if any) associated with commits in the _Contributors_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.sortContributorsBy.countDescending.description": "Sorts contributors by commit count in descending order", + "gitlens.sortContributorsBy.countAscending.description": "Sorts contributors by commit count in ascending order", + "gitlens.sortContributorsBy.dateDescending.description": "Sorts contributors by the most recent commit date in descending order", + "gitlens.sortContributorsBy.dateAscending.description": "Sorts contributors by the most recent commit date in ascending order", + "gitlens.sortContributorsBy.nameAscending.description": "Sorts contributors by name in ascending order", + "gitlens.sortContributorsBy.nameDescending.description": "Sorts contributors by name in descending order", + "gitlens.sortContributorsBy.markdownDescription": "Specifies how contributors are sorted in quick pick menus and views", + "gitlens.views.contributors.files.layout.auto.description": "Automatically switches between displaying files as a `tree` or `list` based on the `#gitlens.views.contributors.files.threshold#` value and the number of files at each nesting level", + "gitlens.views.contributors.files.layout.list.description": "Displays files as a list", + "gitlens.views.contributors.files.layout.tree.description": "Displays files as a tree", + "gitlens.views.contributors.files.layout.markdownDescription": "Specifies how the _Contributors_ view will display files", + "gitlens.views.contributors.files.threshold.markdownDescription": "Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the _Contributors_ view. Only applies when `#gitlens.views.contributors.files.layout#` is set to `auto`", + "gitlens.views.contributors.files.compact.markdownDescription": "Specifies whether to compact (flatten) unnecessary file nesting in the _Contributors_ view. Only applies when `#gitlens.views.contributors.files.layout#` is set to `tree` or `auto`", + "gitlens.views.contributors.avatars.markdownDescription": "Specifies whether to show avatar images instead of commit (or status) icons in the _Contributors_ view", + "gitlens.views.contributors.reveal.markdownDescription": "Specifies whether to reveal contributors in the _Contributors_ view, otherwise they revealed in the _Repositories_ view", + "gitlens.contributes.configuration.searchCompareView.title": "Search & Compare View", + "gitlens.views.searchAndCompare.pullRequests.enabled.markdownDescription": "Specifies whether to query for pull requests associated with commits in the _Search & Compare_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.views.searchAndCompare.pullRequests.showForCommits.markdownDescription": "Specifies whether to show pull requests (if any) associated with commits in the _Search & Compare_ view. Requires a connection to a supported remote service (e.g. GitHub)", + "gitlens.views.searchAndCompare.files.layout.auto.description": "Automatically switches between displaying files as a `tree` or `list` based on the `#gitlens.views.searchAndCompare.files.threshold#` value and the number of files at each nesting level", + "gitlens.views.searchAndCompare.files.layout.list.description": "Displays files as a list", + "gitlens.views.searchAndCompare.files.layout.tree.description": "Displays files as a tree", + "gitlens.views.searchAndCompare.files.layout.markdownDescription": "Specifies how the _Search & Compare_ view will display files", + "gitlens.views.searchAndCompare.files.threshold.markdownDescription": "Specifies when to switch between displaying files as a `tree` or `list` based on the number of files in a nesting level in the _Search & Compare_ view. Only applies when `#gitlens.views.searchAndCompare.files.layout#` is set to `auto`", + "gitlens.views.searchAndCompare.files.compact.markdownDescription": "Specifies whether to compact (flatten) unnecessary file nesting in the _Search & Compare_ view. Only applies when `#gitlens.views.searchAndCompare.files.layout#` is set to `tree` or `auto`", + "gitlens.views.searchAndCompare.avatars.markdownDescription": "Specifies whether to show avatar images instead of commit (or status) icons in the _Search & Compare_ view", + "gitlens.contributes.configuration.gutterBlame.title": "Gutter Blame", + "gitlens.blame.toggleMode.file.description": "Toggles each file individually", + "gitlens.blame.toggleMode.window.description": "Toggles the window, i.e. all files at once", + "gitlens.blame.toggleMode.markdownDescription": "Specifies how the gutter blame annotations will be toggled", + "gitlens.blame.format.markdownDescription": "Specifies the format of the gutter blame annotations. See [_Commit Tokens_](https://github.com/gitkraken/vscode-gitlens/wiki/Custom-Formatting#commit-tokens) in the GitLens docs. Date formatting is controlled by the `#gitlens.blame.dateFormat#` setting", + "gitlens.blame.heatmap.enabled.markdownDescription": "Specifies whether to provide a heatmap indicator in the gutter blame annotations", + "gitlens.blame.heatmap.location.left.description": "Adds a heatmap indicator on the left edge of the gutter blame annotations", + "gitlens.blame.heatmap.location.right.description": "Adds a heatmap indicator on the right edge of the gutter blame annotations", + "gitlens.blame.heatmap.location.markdownDescription": "Specifies where the heatmap indicators will be shown in the gutter blame annotations", + "gitlens.blame.avatars.markdownDescription": "Specifies whether to show avatar images in the gutter blame annotations", + "gitlens.blame.compact.markdownDescription": "Specifies whether to compact (deduplicate) matching adjacent gutter blame annotations", + "gitlens.blame.highlight.enabled.markdownDescription": "Specifies whether to highlight lines associated with the current line", + "gitlens.blame.highlight.locations.gutter.description": "Adds a gutter indicator", + "gitlens.blame.highlight.locations.line.description": "Adds a full-line highlight background color", + "gitlens.blame.highlight.locations.overview.description": "Adds a decoration to the overview ruler (scroll bar)", + "gitlens.blame.highlight.locations.markdownDescription": "Specifies where the associated line highlights will be shown", + "gitlens.blame.separateLines.markdownDescription": "Specifies whether gutter blame annotations will be separated by a small gap", + "gitlens.blame.dateFormat.markdownDescription": "Specifies how to format absolute dates (e.g. using the `${date}` token) in gutter blame annotations. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats", + "gitlens.contributes.configuration.gutterChanges.title": "Gutter Changes", + "gitlens.changes.toggleMode.file.description": "Toggles each file individually", + "gitlens.changes.toggleMode.window.description": "Toggles the window, i.e. all files at once", + "gitlens.changes.toggleMode.markdownDescription": "Specifies how the gutter changes annotations will be toggled", + "gitlens.changes.locations.gutter.description": "Adds a gutter indicator", + "gitlens.changes.locations.overview.description": "Adds a decoration to the overview ruler (scroll bar)", + "gitlens.changes.locations.markdownDescription": "Specifies where the indicators of the gutter changes annotations will be shown", + "gitlens.contributes.configuration.gutterHeatmap.title": "Gutter Heatmap", + "gitlens.heatmap.toggleMode.file.description": "Toggles each file individually", + "gitlens.heatmap.toggleMode.window.description": "Toggles the window, i.e. all files at once", + "gitlens.heatmap.toggleMode.markdownDescription": "Specifies how the gutter heatmap annotations will be toggled", + "gitlens.heatmap.locations.gutter.description": "Adds a gutter indicator", + "gitlens.heatmap.locations.overview.description": "Adds a decoration to the overview ruler (scroll bar)", + "gitlens.heatmap.locations.markdownDescription": "Specifies where the indicators of the gutter heatmap annotations will be shown", + "gitlens.heatmap.ageThreshold.markdownDescription": "Specifies the age of the most recent change (in days) after which the gutter heatmap annotations will be cold rather than hot (i.e. will use `#gitlens.heatmap.coldColor#` instead of `#gitlens.heatmap.hotColor#`)", + "gitlens.heatmap.coldColor.markdownDescription": "Specifies the base color of the gutter heatmap annotations when the most recent change is older (cold) than the `#gitlens.heatmap.ageThreshold#` value", + "gitlens.heatmap.hotColor.markdownDescription": "Specifies the base color of the gutter heatmap annotations when the most recent change is newer (hot) than the `#gitlens.heatmap.ageThreshold#` value", + "gitlens.contributes.configuration.gitCommandPalette.title": "Git Command Palette", + "gitlens.gitCommands.sortBy.name.description": "Sorts commands by name", + "gitlens.gitCommands.sortBy.usage.description": "Sorts commands by last used date", + "gitlens.gitCommands.sortBy.markdownDescription": "Specifies how Git commands are sorted in the _Git Command Palette_", + "gitlens.gitCommands.skipConfirmations.branchCreateCommand.description": "Skips branch create confirmations when run from a command, e.g. a view action", + "gitlens.gitCommands.skipConfirmations.branchCreateMenu.description": "Skips branch create confirmations when run from the Git Command Palette", + "gitlens.gitCommands.skipConfirmations.coauthorsCommand.description": "Skips co-author confirmations when run from a command, e.g. a view action", + "gitlens.gitCommands.skipConfirmations.coauthorsMenu.description": "Skips co-author confirmations when run from the Git Command Palette", + "gitlens.gitCommands.skipConfirmations.fetchCommand.description": "Skips fetch confirmations when run from a command, e.g. a view action", + "gitlens.gitCommands.skipConfirmations.fetchMenu.description": "Skips fetch confirmations when run from the Git Command Palette", + "gitlens.gitCommands.skipConfirmations.pullCommand.description": "Skips pull confirmations when run from a command, e.g. a view action", + "gitlens.gitCommands.skipConfirmations.pullMenu.description": "Skips pull confirmations when run from the Git Command Palette", + "gitlens.gitCommands.skipConfirmations.pushCommand.description": "Skips push confirmations when run from a command, e.g. a view action", + "gitlens.gitCommands.skipConfirmations.pushMenu.description": "Skips push confirmations when run from the Git Command Palette", + "gitlens.gitCommands.skipConfirmations.stashApplyCommand.description": "Skips stash apply confirmations when run from a command, e.g. a view action", + "gitlens.gitCommands.skipConfirmations.stashApplyMenu.description": "Skips stash apply confirmations when run from the Git Command Palette", + "gitlens.gitCommands.skipConfirmations.stashPopCommand.description": "Skips stash pop confirmations when run from a command, e.g. a view action", + "gitlens.gitCommands.skipConfirmations.stashPopMenu.description": "Skips stash pop confirmations when run from the Git Command Palette", + "gitlens.gitCommands.skipConfirmations.stashPushCommand.description": "Skips stash push confirmations when run from a command, e.g. a view action", + "gitlens.gitCommands.skipConfirmations.stashPushMenu.description": "Skips stash push confirmations when run from the Git Command Palette", + "gitlens.gitCommands.skipConfirmations.switchCommand.description": "Skips switch confirmations when run from a command, e.g. a view action", + "gitlens.gitCommands.skipConfirmations.switchMenu.description": "Skips switch confirmations when run from the Git Command Palette", + "gitlens.gitCommands.skipConfirmations.tagCreateCommand.description": "Skips tag create confirmations when run from a command, e.g. a view action", + "gitlens.gitCommands.skipConfirmations.tagCreateMenu.description": "Skips tag create confirmations when run from the Git Command Palette", + "gitlens.gitCommands.skipConfirmations.markdownDescription": "Specifies which (and when) Git commands will skip the confirmation step, using the format: `git-command-name:(menu|command)`", + "gitlens.gitCommands.closeOnFocusOut.markdownDescription": "Specifies whether to dismiss the _Git Command Palette_ when focus is lost (if not, press `ESC` to dismiss)", + "gitlens.gitCommands.search.showResultsInSideBar.markdownDescription": "Specifies whether to show the commit search results directly in the quick pick menu, in the Side Bar, or will be based on the context", + "gitlens.gitCommands.search.matchAll.markdownDescription": "Specifies whether to match all or any commit message search patterns", + "gitlens.gitCommands.search.matchCase.markdownDescription": "Specifies whether to match commit search patterns with or without regard to casing", + "gitlens.gitCommands.search.matchRegex.markdownDescription": "Specifies whether to match commit search patterns using regular expressions", + "gitlens.gitCommands.search.showResultsInView.deprecationMessage": "Deprecated. This setting has been renamed to gitlens.gitCommands.search.showResultsInSideBar", + "gitlens.gitCommands.search.showResultsInView.markdownDeprecationMessage": "Deprecated. This setting has been renamed to `#gitlens.gitCommands.search.showResultsInSideBar#`", + "gitlens.contributes.configuration.integrations.title": "Integrations", + "gitlens.autolinks.prefix.description": "Specifies the short prefix to use to generate autolinks for the external resource", + "gitlens.autolinks.title.description": "Specifies an optional title for the generated autolink. Use `` as the variable for the reference number", + "gitlens.autolinks.url.description": "Specifies the url of the external resource you want to link to. Use `` as the variable for the reference number", + "gitlens.autolinks.alphanumeric.description": "Specifies whether alphanumeric characters should be allowed in ``", + "gitlens.autolinks.ignoreCase.description": "Specifies whether case should be ignored when matching the prefix", + "gitlens.autolinks.markdownDescription": "Specifies autolinks to external resources in commit messages. Use `` as the variable for the reference number", + "gitlens.integrations.enabled.markdownDescription": "Specifies whether to enable rich integrations with any supported remote services", + "gitlens.remotes.type.description": "Specifies the type of the custom remote service", + "gitlens.remotes.domain.description": "Specifies the domain name used to match this custom configuration to a Git remote", + "gitlens.remotes.regex.description": "Specifies a regular expression used to match this custom configuration to a Git remote and capture the \"domain name\" and \"path\"", + "gitlens.remotes.name.description": "Specifies an optional friendly name for the custom remote service", + "gitlens.remotes.protocol.description": "Specifies an optional url protocol for the custom remote service", + "gitlens.remotes.urls.repository.markdownDescription": "Specifies the format of a repository url for the custom remote service\n\nAvailable tokens\\\n`${repo}` — repository path", + "gitlens.remotes.urls.branches.markdownDescription": "Specifies the format of a branches url for the custom remote service\n\nAvailable tokens\\\n`${repo}` — repository path\\\n`${branch}` — branch", + "gitlens.remotes.urls.branch.markdownDescription": "Specifies the format of a branch url for the custom remote service\n\nAvailable tokens\\\n`${repo}` — repository path\\\n`${branch}` — branch", + "gitlens.remotes.urls.commit.markdownDescription": "Specifies the format of a commit url for the custom remote service\n\nAvailable tokens\\\n`${repo}` — repository path\\\n`${id}` — commit SHA", + "gitlens.remotes.urls.file.markdownDescription": "Specifies the format of a file url for the custom remote service\n\nAvailable tokens\\\n`${repo}` — repository path\\\n`${file}` — file name\\\n`${line}` — formatted line information", + "gitlens.remotes.urls.fileInBranch.markdownDescription": "Specifies the format of a branch file url for the custom remote service\n\nAvailable tokens\\\n`${repo}` — repository path\\\n`${file}` — file name\\\n`${branch}` — branch\\\n`${line}` — formatted line information", + "gitlens.remotes.urls.fileInCommit.markdownDescription": "Specifies the format of a commit file url for the custom remote service\n\nAvailable tokens\\\n`${repo}` — repository path\\\n`${file}` — file name\\\n`${id}` — commit SHA\\\n`${line}` — formatted line information", + "gitlens.remotes.urls.fileLine.markdownDescription": "Specifies the format of a line in a file url for the custom remote service\n\nAvailable tokens\\\n`${line}` — line", + "gitlens.remotes.urls.fileRange.markdownDescription": "Specifies the format of a range in a file url for the custom remote service\n\nAvailable tokens\\\n`${start}` — starting line\\\n`${end}` — ending line", + "gitlens.remotes.markdownDescription": "Specifies custom remote services to be matched with Git remotes to detect custom domains for built-in remote services or provide support for custom remote services", + "gitlens.partners.additionalProperties.enabled.description": "Specifies whether the partner integration should be shown", + "gitlens.partners.additionalProperties.description": "Specifies the configuration of a partner integration", + "gitlens.partners.description": "Specifies the configuration of a partner integration", + "gitlens.liveshare.allowGuestAccess.description": "Specifies whether to allow guest access to GitLens features when using Visual Studio Live Share", + "gitlens.contributes.configuration.terminal.title": "Terminal", + "gitlens.terminalLinks.enabled.markdownDescription": "Specifies whether to enable terminal links — autolinks in the integrated terminal to quickly jump to more details for commits, branches, tags, and more", + "gitlens.contributes.configuration.visualHistory.title": "Visual File History", + "gitlens.visualHistory.queryLimit.markdownDescription": "Specifies the limit on the how many commits can be queried for statistics in the Visual File History, because of rate limits. Only applies to virtual workspaces.", + "gitlens.contributes.configuration.dateTimes.title": "Date & Times", + "gitlens.defaultDateStyle.relative.description": "e.g. 1 day ago", + "gitlens.defaultDateStyle.absolute.description": "e.g. July 25th, 2018 7:18pm", + "gitlens.defaultDateStyle.markdownDescription": "Specifies how dates will be displayed by default", + "gitlens.defaultDateFormat.markdownDescription": "Specifies how absolute dates will be formatted by default. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats", + "gitlens.defaultDateLocale.markdownDescription": "Specifies the locale, a [BCP 47 language tag](https://en.wikipedia.org/wiki/IETF_language_tag#List_of_major_primary_language_subtags), to use for date formatting, defaults to the VS Code locale. Use `system` to follow the current system locale, or choose a specific locale, e.g `en-US` — US English, `en-GB` — British English, `de-DE` — German, 'ja-JP = Japanese, etc.", + "gitlens.defaultDateShortFormat.markdownDescription": "Specifies how short absolute dates will be formatted by default. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats", + "gitlens.defaultTimeFormat.markdownDescription": "Specifies how times will be formatted by default. See the [Moment.js docs](https://momentjs.com/docs/#/displaying/format/) for supported formats", + "gitlens.defaultDateSource.authored.description": "Uses the date when the changes were authored (i.e. originally written)", + "gitlens.defaultDateSource.committed.description": "Uses the date when the changes were committed", + "gitlens.defaultDateSource.markdownDescription": "Specifies whether commit dates should use the authored or committed date", + "gitlens.contributes.configuration.menusToolbars.title": "Menus & Toolbars", + "gitlens.menus.markdownDescription": "Specifies which commands will be added to which menus", + "gitlens.contributes.configuration.keyboard.title": "Keyboard Shortcuts", + "gitlens.keymap.alternate.description": "Adds an alternate set of shortcut keys that start with `Alt` (⌥ on macOS)", + "gitlens.keymap.chorded.description": "Adds a chorded set of shortcut keys that start with `Ctrl+Alt+G` (`⌥⌘G` on macOS)", + "gitlens.keymap.none.description": "No shortcut keys will be added", + "gitlens.keymap.markdownDescription": "Specifies the keymap to use for GitLens shortcut keys", + "gitlens.contributes.configuration.modes.title": "Modes", + "gitlens.mode.statusBar.enabled.markdownDescription": "Specifies whether to provide the active GitLens mode in the status bar", + "gitlens.mode.statusBar.alignment.left.description": "Aligns to the left", + "gitlens.mode.statusBar.alignment.right.description": "Aligns to the right", + "gitlens.mode.statusBar.alignment.markdownDescription": "Specifies the active GitLens mode alignment in the status bar", + "gitlens.mode.active.markdownDescription": "Specifies the active GitLens mode, if any", + "gitlens.modes.zen.name.description": "Specifies the friendly name of this user-defined mode", + "gitlens.modes.zen.statusBarItemName.description": "Specifies the name shown in the status bar when this user-defined mode is active", + "gitlens.modes.zen.description.description": "Specifies the description of this user-defined mode", + "gitlens.modes.zen.codeLens.description": "Specifies whether to show any Git CodeLens when this user-defined mode is active", + "gitlens.modes.zen.currentLine.description": "Specifies whether to show a blame annotation for the current line when this user-defined mode is active", + "gitlens.modes.zen.hovers.description": "Specifies whether to show any hovers when this user-defined mode is active", + "gitlens.modes.zen.statusBar.description": "Specifies whether to show blame information in the status bar when this user-defined mode is active", + "gitlens.modes.review.name.description": "Specifies the friendly name of this user-defined mode", + "gitlens.modes.review.statusBarItemName.description": "Specifies the name shown in the status bar when this user-defined mode is active", + "gitlens.modes.review.description.description": "Specifies the description of this user-defined mode", + "gitlens.modes.review.codeLens.description": "Specifies whether to show any Git CodeLens when this user-defined mode is active", + "gitlens.modes.review.currentLine.description": "Specifies whether to show a blame annotation for the current line when this user-defined mode is active", + "gitlens.modes.review.hovers.description": "Specifies whether to show any hovers when this user-defined mode is active", + "gitlens.modes.review.statusBar.description": "Specifies whether to show blame information in the status bar when this user-defined mode is active", + "gitlens.modes.additionalProperties.name.description": "Specifies the friendly name of this user-defined mode", + "gitlens.modes.additionalProperties.statusBarItemName.description": "Specifies the name shown in the status bar when this user-defined mode is active", + "gitlens.modes.additionalProperties.description.description": "Specifies the description of this user-defined mode", + "gitlens.modes.additionalProperties.annotations.blame.description": "Shows the gutter blame annotations", + "gitlens.modes.additionalProperties.annotations.changes.description": "Shows the gutter changes annotations", + "gitlens.modes.additionalProperties.annotations.heatmap.description": "Shows the gutter heatmap annotations", + "gitlens.modes.additionalProperties.annotations.description": "Specifies which (if any) file annotations will be shown when this user-defined mode is active", + "gitlens.modes.additionalProperties.codeLens.description": "Specifies whether to show any Git CodeLens when this user-defined mode is active", + "gitlens.modes.additionalProperties.currentLine.description": "Specifies whether to show a blame annotation for the current line when this user-defined mode is active", + "gitlens.modes.additionalProperties.hovers.description": "Specifies whether to show any hovers when this user-defined mode is active", + "gitlens.modes.additionalProperties.statusBar.description": "Specifies whether to show blame information in the status bar when this user-defined mode is active", + "gitlens.modes.default.zen.name": "Zen", + "gitlens.modes.default.zen.statusBarItemName": "Zen", + "gitlens.modes.default.zen.description": "for a zen-like experience, disables many visual features", + "gitlens.modes.default.review.name": "Review", + "gitlens.modes.default.review.statusBarItemName": "Reviewing", + "gitlens.modes.default.review.description": "for reviewing code, enables many visual features", + "gitlens.modes.markdownDescription": "Specifies the user-defined GitLens modes", + "gitlens.contributes.configuration.advanced.title": "Advanced", + "gitlens.detectNestedRepositories.markdownDescription": "Specifies whether to attempt to detect nested repositories when opening files", + "gitlens.advanced.messages.suppressCommitHasNoPreviousCommitWarning.description": "Commit Has No Previous Commit Warning", + "gitlens.advanced.messages.suppressCommitNotFoundWarning.description": "Commit Not Found Warning", + "gitlens.advanced.messages.suppressCreatePullRequestPrompt.description": "Create Pull Request Prompt", + "gitlens.advanced.messages.suppressDebugLoggingWarning.description": "Debug Logging Warning", + "gitlens.advanced.messages.suppressFileNotUnderSourceControlWarning.description": "File Not Under Source Control Warning", + "gitlens.advanced.messages.suppressGitDisabledWarning.description": "Git Disabled Warning", + "gitlens.advanced.messages.suppressGitMissingWarning.description": "Git Missing Warning", + "gitlens.advanced.messages.suppressGitVersionWarning.description": "Git Version Warning", + "gitlens.advanced.messages.suppressLineUncommittedWarning.description": "Line Uncommitted Warning", + "gitlens.advanced.messages.suppressNoRepositoryWarning.description": "No Repository Warning", + "gitlens.advanced.messages.suppressRebaseSwitchToTextWarning.description": "Rebase Switch To Text Warning", + "gitlens.advanced.messages.markdownDescription": "Specifies which messages should be suppressed", + "gitlens.advanced.repositorySearchDepth.markdownDescription": "Specifies how many folders deep to search for repositories. Defaults to `#git.repositoryScanMaxDepth#`", + "gitlens.advanced.abbreviatedShaLength.markdownDescription": "Specifies the length of abbreviated commit SHAs", + "gitlens.advanced.abbreviateShaOnCopy.markdownDescription": "Specifies whether to copy full or abbreviated commit SHAs to the clipboard. Abbreviates to the length of `#gitlens.advanced.abbreviatedShaLength#`.", + "gitlens.advanced.commitOrdering.unspecified.description": "Shows commits in reverse chronological order", + "gitlens.advanced.commitOrdering.date.description": "Shows commits in reverse chronological order of the commit timestamp", + "gitlens.advanced.commitOrdering.authorDate.description": "Shows commits in reverse chronological order of the author timestamp", + "gitlens.advanced.commitOrdering.topo.description": "Shows commits in reverse chronological order of the commit timestamp, but avoids intermixing multiple lines of history", + "gitlens.advanced.commitOrdering.markdownDescription": "Specifies the order by which commits will be shown. If unspecified, commits will be shown in reverse chronological order", + "gitlens.blame.ignoreWhitespace.markdownDescription": "Specifies whether to ignore whitespace when comparing revisions during blame operations", + "gitlens.advanced.blame.customArguments.markdownDescription": "Specifies additional arguments to pass to the `git blame` command", + "gitlens.advanced.blame.delayAfterEdit.markdownDescription": "Specifies the time (in milliseconds) to wait before re-blaming an unsaved document after an edit. Use 0 to specify an infinite wait", + "gitlens.advanced.blame.sizeThresholdAfterEdit.markdownDescription": "Specifies the maximum document size (in lines) allowed to be re-blamed after an edit while still unsaved. Use 0 to specify no maximum", + "gitlens.advanced.similarityThreshold.markdownDescription": "Specifies the amount (percent) of similarity a deleted and added file pair must have to be considered a rename", + "gitlens.advanced.externalDiffTool.markdownDescription": "Specifies an optional external diff tool to use when comparing files. Must be a configured [Git difftool](https://git-scm.com/docs/git-config#Documentation/git-config.txt-difftool).", + "gitlens.advanced.externalDirectoryDiffTool.markdownDescription": "Specifies an optional external diff tool to use when comparing directories. Must be a configured [Git difftool](https://git-scm.com/docs/git-config#Documentation/git-config.txt-difftool).", + "gitlens.advanced.quickPick.closeOnFocusOut.markdownDescription": "Specifies whether to dismiss quick pick menus when focus is lost (if not, press `ESC` to dismiss)", + "gitlens.advanced.maxListItems.markdownDescription": "Specifies the maximum number of items to show in a list. Use 0 to specify no maximum", + "gitlens.advanced.maxSearchItems.markdownDescription": "Specifies the maximum number of items to show in a search. Use 0 to specify no maximum", + "gitlens.advanced.caching.enabled.markdownDescription": "Specifies whether git output will be cached — changing the default is not recommended", + "gitlens.debug.markdownDescription": "Specifies debug mode", + "gitlens.advanced.useSymmetricDifferenceNotation.deprecationMessage": "Deprecated. This setting is no longer used", + "gitlens.advanced.useSymmetricDifferenceNotation.markdownDescription": "Deprecated. This setting is no longer used", + "gitlens.contributes.configuration.general.title": "General", + "gitlens.showWelcomeOnInstall.markdownDescription": "Specifies whether to show the Welcome (Quick Setup) experience on first install", + "gitlens.showWhatsNewAfterUpgrades.markdownDescription": "Specifies whether to show the What's New notification after upgrading to new feature releases", + "gitlens.outputLevel.silent.description": "Logs nothing", + "gitlens.outputLevel.errors.description": "Logs only errors", + "gitlens.outputLevel.verbose.description": "Logs all errors, warnings, and messages", + "gitlens.outputLevel.debug.description": "Logs all errors, warnings, and messages with extra context useful for debugging", + "gitlens.outputLevel.markdownDescription": "Specifies how much (if any) output will be sent to the GitLens output channel", + "gitlens.defaultGravatarsStyle.identicon.description": "A geometric pattern", + "gitlens.defaultGravatarsStyle.mp.description": "A simple, cartoon-style silhouetted outline of a person (does not vary by email hash)", + "gitlens.defaultGravatarsStyle.monsterid.description": "A monster with different colors, faces, etc", + "gitlens.defaultGravatarsStyle.retro.description": "8-bit arcade-style pixelated faces", + "gitlens.defaultGravatarsStyle.robohash.description": "A robot with different colors, faces, etc", + "gitlens.defaultGravatarsStyle.wavatar.description": "A face with differing features and backgrounds", + "gitlens.defaultGravatarsStyle.markdownDescription": "Specifies the style of the gravatar default (fallback) images", + "gitlens.fileAnnotations.command.unspecified.description": "Shows a menu to choose which file annotations to toggle", + "gitlens.fileAnnotations.command.blame.description": "Toggles gutter blame annotations", + "gitlens.fileAnnotations.command.heatmap.description": "Toggles gutter heatmap annotations", + "gitlens.fileAnnotations.command.changes.description": "Toggles gutter changes annotations", + "gitlens.fileAnnotations.command.markdownDescription": "Specifies whether the file annotations button in the editor title shows a menu or immediately toggles the specified file annotations", + "gitlens.proxy.url.description": "Specifies the url of the proxy server to use", + "gitlens.proxy.strictSsl.description": "Specifies whether the proxy server certificate should be verified against the list of supplied CAs", + "gitlens.proxy.description": "Specifies the proxy configuration to use. If not specified, the proxy configuration will be determined based on VS Code or OS settings", + "gitlens.plusFeatures.enabled.markdownDescription": "Specifies whether to enable GitLens+ features", + "gitlens.virtualRepositories.enabled.markdownDescription": "Specifies whether to enable virtual repositories support", + "gitlens.insiders.deprecationMessage": "Deprecated. Use the Insiders edition of GitLens instead", + "gitlens.insiders.markdownDeprecationMessage": "Deprecated. Use the [Insiders edition](https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens-insiders) of GitLens instead", + "gitlens.gutterBackgroundColor.description": "Specifies the background color of the gutter blame annotations", + "gitlens.gutterForegroundColor.description": "Specifies the foreground color of the gutter blame annotations", + "gitlens.gutterUncommittedForegroundColor.description": "Specifies the foreground color of an uncommitted line in the gutter blame annotations", + "gitlens.trailingLineBackgroundColor.description": "Specifies the background color of the blame annotation for the current line", + "gitlens.trailingLineForegroundColor.description": "Specifies the foreground color of the blame annotation for the current line", + "gitlens.lineHighlightBackgroundColor.description": "Specifies the background color of the associated line highlights in blame annotations", + "gitlens.lineHighlightOverviewRulerColor.description": "Specifies the overview ruler color of the associated line highlights in blame annotations", + "gitlens.openAutolinkedIssueIconColor.description": "Specifies the icon color of open issues in the GitLens views", + "gitlens.closedAutolinkedIssueIconColor.description": "Specifies the icon color of closed issues in the GitLens views", + "gitlens.closedPullRequestIconColor.description": "Specifies the icon color of closed pull requests in the GitLens views", + "gitlens.openPullRequestIconColor.description": "Specifies the icon color of open pull requests in the GitLens views", + "gitlens.mergedPullRequestIconColor.description": "Specifies the icon color of merged pull requests in the GitLens views", + "gitlens.unpublishedChangesIconColor.description": "Specifies the icon color of unpublished changes in the GitLens views", + "gitlens.unpublishedCommitIconColor.description": "Specifies the icon color of unpublished commits in the GitLens views", + "gitlens.unpulledChangesIconColor.description": "Specifies the icon color of unpulled changes in the GitLens views", + "gitlens.decorations.addedForegroundColor.description": "Specifies the decoration foreground color of added files", + "gitlens.decorations.copiedForegroundColor.description": "Specifies the decoration foreground color of copied files", + "gitlens.decorations.deletedForegroundColor.description": "Specifies the decoration foreground color of deleted files", + "gitlens.decorations.ignoredForegroundColor.description": "Specifies the decoration foreground color of ignored files", + "gitlens.decorations.modifiedForegroundColor.description": "Specifies the decoration foreground color of modified files", + "gitlens.decorations.untrackedForegroundColor.description": "Specifies the decoration foreground color of untracked files", + "gitlens.decorations.renamedForegroundColor.description": "Specifies the decoration foreground color of renamed files", + "gitlens.decorations.branchAheadForegroundColor.description": "Specifies the decoration foreground color of branches that are ahead of their upstream", + "gitlens.decorations.branchBehindForegroundColor.description": "Specifies the decoration foreground color of branches that are behind their upstream", + "gitlens.decorations.branchDivergedForegroundColor.description": "Specifies the decoration foreground color of branches that are both ahead and behind their upstream", + "gitlens.decorations.branchUpToDateForegroundColor.description": "Specifies the decoration foreground color of branches that are up to date with their upstream", + "gitlens.decorations.branchUnpublishedForegroundColor.description": "Specifies the decoration foreground color of branches that are not yet published to an upstream", + "gitlens.decorations.branchMissingUpstreamForegroundColor.description": "Specifies the decoration foreground color of branches that have a missing upstream", + "gitlens.decorations.worktreeView.hasUncommittedChangesForegroundColor.description": "Specifies the decoration foreground color for worktrees that have uncommitted changes", + "gitlens.commands.category.gitlens.title": "GitLens", + "gitlens.commands.category.gitlensPlus.title": "GitLens+", + "gitlens.plus.learn.title": "Learn about GitLens+ Features", + "gitlens.plus.loginOrSignUp.title": "Sign In to GitLens+...", + "gitlens.plus.logout.title": "Sign out of GitLens+", + "gitlens.plus.startPreviewTrial.title": "Try GitLens+ Features Now", + "gitlens.plus.manage.title": "Manage Your GitLens+ Account...", + "gitlens.plus.purchase.title": "Upgrade Your GitLens+ Account...", + "gitlens.plus.hide.title": "Hide GitLens+ Features", + "gitlens.plus.restore.title": "Restore GitLens+ Features", + "gitlens.plus.reset.title": "Reset", + "gitlens.getStarted.title": "Get Started", + "gitlens.showSettingsPage.title": "Open Settings", + "gitlens.showSettingsPage.views.title": "Open Settings", + "gitlens.showSettingsPage.branchesView.title": "Open View Settings", + "gitlens.showSettingsPage.commitsView.title": "Open View Settings", + "gitlens.showSettingsPage.contributorsView.title": "Open View Settings", + "gitlens.showSettingsPage.fileHistoryView.title": "Open View Settings", + "gitlens.showSettingsPage.lineHistoryView.title": "Open View Settings", + "gitlens.showSettingsPage.remotesView.title": "Open View Settings", + "gitlens.showSettingsPage.repositoriesView.title": "Open View Settings", + "gitlens.showSettingsPage.searchCompareView.title": "Open View Settings", + "gitlens.showSettingsPage.stashesView.title": "Open View Settings", + "gitlens.showSettingsPage.tagsView.title": "Open View Settings", + "gitlens.showSettingsPage.worktreesView.title": "Open View Settings", + "gitlens.showTimelinePage.title": "Open Visual File History of Active File", + "gitlens.refreshTimelinePage.title": "Refresh", + "gitlens.showWelcomePage.title": "Welcome (Quick Setup)", + "gitlens.showBranchesView.title": "Show Branches View", + "gitlens.showCommitsView.title": "Show Commits View", + "gitlens.showContributorsView.title": "Show Contributors View", + "gitlens.showFileHistoryView.title": "Show File History View", + "gitlens.showHomeView.title": "Show Home View", + "gitlens.showLineHistoryView.title": "Show Line History View", + "gitlens.showRemotesView.title": "Show Remotes View", + "gitlens.showRepositoriesView.title": "Show Repositories View", + "gitlens.showSearchAndCompareView.title": "Show Search And Compare Commits View", + "gitlens.showStashesView.title": "Show Stashes View", + "gitlens.showTagsView.title": "Show Tags View", + "gitlens.showTimelineView.title": "Show Visual File History View", + "gitlens.showWorktreesView.title": "Show Worktrees View", + "gitlens.compareWith.title": "Compare References...", + "gitlens.compareHeadWith.title": "Compare HEAD with...", + "gitlens.compareWorkingWith.title": "Compare Working Tree with...", + "gitlens.diffDirectory.title": "Open Directory Compare (difftool) with...", + "gitlens.diffDirectoryWithHead.title": "Open Directory Compare (difftool)", + "gitlens.diffWithNext.title": "Open Changes with Next Revision", + "gitlens.diffWithNextInDiffLeft.title": "Open Changes with Next Revision", + "gitlens.diffWithNextInDiffRight.title": "Open Changes with Next Revision", + "gitlens.diffWithPrevious.title": "Open Changes with Previous Revision", + "gitlens.diffWithPreviousInDiffLeft.title": "Open Changes with Previous Revision", + "gitlens.diffWithPreviousInDiffRight.title": "Open Changes with Previous Revision", + "gitlens.diffLineWithPrevious.title": "Open Line Changes with Previous Revision", + "gitlens.diffWithRevision.title": "Open Changes with Revision...", + "gitlens.diffWithRevisionFrom.title": "Open Changes with Branch or Tag...", + "gitlens.diffWithWorking.title": "Open Changes with Working File", + "gitlens.diffWithWorkingInDiffLeft.title": "Open Changes with Working File", + "gitlens.diffWithWorkingInDiffRight.title": "Open Changes with Working File", + "gitlens.diffLineWithWorking.title": "Open Line Changes with Working File", + "gitlens.disableRebaseEditor.title": "Disable Interactive Rebase Editor", + "gitlens.enableRebaseEditor.title": "Enable Interactive Rebase Editor", + "gitlens.toggleFileBlame.title": "Toggle File Blame", + "gitlens.toggleFileBlameInDiffLeft.title": "Toggle File Blame", + "gitlens.toggleFileBlameInDiffRight.title": "Toggle File Blame", + "gitlens.clearFileAnnotations.title": "Clear File Annotations", + "gitlens.computingFileAnnotations.title": "Computing File Annotations...", + "gitlens.toggleFileHeatmap.title": "Toggle File Heatmap", + "gitlens.toggleFileHeatmapInDiffLeft.title": "Toggle File Heatmap", + "gitlens.toggleFileHeatmapInDiffRight.title": "Toggle File Heatmap", + "gitlens.toggleFileChanges.title": "Toggle File Changes", + "gitlens.toggleFileChangesOnly.title": "Toggle File Changes", + "gitlens.toggleLineBlame.title": "Toggle Line Blame", + "gitlens.toggleCodeLens.title": "Toggle Git CodeLens", + "gitlens.gitCommands.title": "Git Command Palette", + "gitlens.gitCommands.branch.title": "Git Branch...", + "gitlens.gitCommands.cherryPick.title": "Git Cherry Pick...", + "gitlens.gitCommands.merge.title": "Git Merge...", + "gitlens.gitCommands.rebase.title": "Git Rebase...", + "gitlens.gitCommands.reset.title": "Git Reset...", + "gitlens.gitCommands.revert.title": "Git Revert...", + "gitlens.gitCommands.switch.title": "Git Switch...", + "gitlens.gitCommands.tag.title": "Git Tag...", + "gitlens.gitCommands.worktree.title": "Git Worktree...", + "gitlens.switchMode.title": "Switch Mode", + "gitlens.toggleReviewMode.title": "Toggle Review Mode", + "gitlens.toggleZenMode.title": "Toggle Zen Mode", + "gitlens.setViewsLayout.title": "Set Views Layout", + "gitlens.showCommitSearch.title": "Search Commits", + "gitlens.showLastQuickPick.title": "Show Last Opened Quick Pick", + "gitlens.revealCommitInView.title": "Reveal Commit in Side Bar", + "gitlens.showCommitInView.title": "Search for Commit in Side Bar", + "gitlens.showCommitsInView.title": "Search for Commits within Selection", + "gitlens.showFileHistoryInView.title": "Open File History", + "gitlens.openFileHistory.title": "Open File History", + "gitlens.openFolderHistory.title": "Open Folder History", + "gitlens.showQuickCommitDetails.title": "Show Commit", + "gitlens.showQuickCommitFileDetails.title": "Show Line Commit", + "gitlens.showQuickRevisionDetails.title": "Show Revision Commit", + "gitlens.showQuickRevisionDetailsInDiffLeft.title": "Show Revision Commit", + "gitlens.showQuickRevisionDetailsInDiffRight.title": "Show Revision Commit", + "gitlens.showQuickFileHistory.title": "Show File History", + "gitlens.quickOpenFileHistory.title": "Quick Open File History", + "gitlens.showQuickBranchHistory.title": "Show Branch History", + "gitlens.showQuickRepoHistory.title": "Show Current Branch History", + "gitlens.showQuickRepoStatus.title": "Show Repository Status", + "gitlens.showQuickStashList.title": "Show Stashes", + "gitlens.addAuthors.title": "Add Co-authors", + "gitlens.connectRemoteProvider.title": "Connect to Remote", + "gitlens.disconnectRemoteProvider.title": "Disconnect from Remote", + "gitlens.copyCurrentBranch.title": "Copy Current Branch Name", + "gitlens.copyMessageToClipboard.title": "Copy Message", + "gitlens.copyShaToClipboard.title": "Copy SHA", + "gitlens.closeUnchangedFiles.title": "Close Unchanged Files", + "gitlens.openChangedFiles.title": "Open Changed Files", + "gitlens.openBranchesOnRemote.title": "Open Branches on Remote", + "gitlens.copyRemoteBranchesUrl.title": "Copy Remote Branches Url", + "gitlens.openBranchOnRemote.title": "Open Branch on Remote", + "gitlens.copyRemoteBranchUrl.title": "Copy Remote Branch Url", + "gitlens.openCommitOnRemote.title": "Open Commit on Remote", + "gitlens.copyRemoteCommitUrl.title": "Copy Remote Commit Url", + "gitlens.openComparisonOnRemote.title": "Open Comparison on Remote", + "gitlens.copyRemoteComparisonUrl.title": "Copy Remote Comparison Url", + "gitlens.openFileFromRemote.title": "Open File from Remote", + "gitlens.openFileOnRemote.title": "Open File on Remote", + "gitlens.copyRemoteFileUrlToClipboard.title": "Copy Remote File Url", + "gitlens.copyRemoteFileUrlWithoutRange.title": "Copy Remote File Url", + "gitlens.openFileOnRemoteFrom.title": "Open File on Remote From...", + "gitlens.copyRemoteFileUrlFrom.title": "Copy Remote File Url From...", + "gitlens.openBlamePriorToChange.title": "Open Blame Prior to Change", + "gitlens.openFileRevision.title": "Open File at Revision...", + "gitlens.openFileRevisionFrom.title": "Open File at Revision from...", + "gitlens.openIssueOnRemote.title": "Open Issue on Remote", + "gitlens.copyRemoteIssueUrl.title": "Copy Issue Url", + "gitlens.openPullRequestOnRemote.title": "Open Pull Request on Remote", + "gitlens.copyRemotePullRequestUrl.title": "Copy Pull Request Url", + "gitlens.openAssociatedPullRequestOnRemote.title": "Open Associated Pull Request", + "gitlens.openRepoOnRemote.title": "Open Repository on Remote", + "gitlens.copyRemoteRepositoryUrl.title": "Copy Remote Repository Url", + "gitlens.openRevisionFile.title": "Open File at Revision", + "gitlens.openRevisionFileInDiffLeft.title": "Open File at Revision", + "gitlens.openRevisionFileInDiffRight.title": "Open File at Revision", + "gitlens.openWorkingFile.title": "Open File", + "gitlens.openWorkingFileInDiffLeft.title": "Open File", + "gitlens.openWorkingFileInDiffRight.title": "Open File", + "gitlens.stashApply.title": "Apply Stash", + "gitlens.views.deleteStash.title": "Delete Stash...", + "gitlens.stashSave.title": "Stash All Changes", + "gitlens.stashSaveFiles.title": "Stash Changes", + "gitlens.externalDiff.title": "Open Changes (difftool)", + "gitlens.externalDiffAll.title": "Open All Changes (difftool)", + "gitlens.resetAvatarCache.title": "Reset Avatar Cache", + "gitlens.resetSuppressedWarnings.title": "Reset Suppressed Warnings", + "gitlens.inviteToLiveShare.title": "Invite to Live Share", + "gitlens.browseRepoAtRevision.title": "Browse Repository from Revision", + "gitlens.browseRepoAtRevisionInNewWindow.title": "Browse Repository from Revision in New Window", + "gitlens.browseRepoBeforeRevision.title": "Browse Repository from Before Revision", + "gitlens.browseRepoBeforeRevisionInNewWindow.title": "Browse Repository from Before Revision in New Window", + "gitlens.views.browseRepoAtRevision.title": "Repository from Here", + "gitlens.views.browseRepoAtRevisionInNewWindow.title": "Repository from Here in New Window", + "gitlens.views.browseRepoBeforeRevision.title": "Repository from Before Here", + "gitlens.views.browseRepoBeforeRevisionInNewWindow.title": "Repository from Before Here in New Window", + "gitlens.fetchRepositories.title": "Fetch", + "gitlens.pullRepositories.title": "Pull", + "gitlens.pushRepositories.title": "Push", + "gitlens.views.addRemote.title": "Add Remote", + "gitlens.views.highlightChanges.title": "Highlight All Changes Since Before this Commit", + "gitlens.views.highlightRevisionChanges.title": "Highlight Changes from this Commit", + "gitlens.views.restore.title": "Restore (Checkout)", + "gitlens.views.switchToAnotherBranch.title": "Switch to Another Branch...", + "gitlens.views.switchToBranch.title": "Switch to Branch...", + "gitlens.views.switchToCommit.title": "Switch to Commit...", + "gitlens.views.switchToTag.title": "Switch to Tag...", + "gitlens.views.copy.title": "Copy", + "gitlens.views.pruneRemote.title": "Prune", + "gitlens.views.fetch.title": "Fetch", + "gitlens.views.publishBranch.title": "Publish Branch", + "gitlens.views.publishRepository.title": "Publish Repository", + "gitlens.views.pull.title": "Pull", + "gitlens.views.push.title": "Push", + "gitlens.views.pushWithForce.title": "Push (force)", + "gitlens.views.openInTerminal.title": "Open in Terminal", + "gitlens.views.setAsDefault.title": "Set as Default", + "gitlens.views.unsetAsDefault.title": "Unset as Default", + "gitlens.views.stageDirectory.title": "Stage All Changes", + "gitlens.views.stageFile.title": "Stage Changes", + "gitlens.views.unstageDirectory.title": "Unstage All Changes", + "gitlens.views.unstageFile.title": "Unstage Changes", + "gitlens.views.star.title": "Add to Favorites", + "gitlens.views.unstar.title": "Remove from Favorites", + "gitlens.views.openDirectoryDiff.title": "Open Directory Compare", + "gitlens.views.openDirectoryDiffWithWorking.title": "Open Directory Compare with Working Tree", + "gitlens.views.openChanges.title": "Open Changes", + "gitlens.views.openChangesWithWorking.title": "Open Changes with Working File", + "gitlens.views.openPreviousChangesWithWorking.title": "Open Previous Changes with Working File", + "gitlens.views.openFile.title": "Open File", + "gitlens.views.openFileRevision.title": "Open File at Revision", + "gitlens.views.openChangedFiles.title": "Open Files", + "gitlens.views.openChangedFileDiffs.title": "Open All Changes", + "gitlens.views.openChangedFileDiffsWithWorking.title": "Open All Changes with Working Tree", + "gitlens.views.openChangedFileRevisions.title": "Open Files at Revision", + "gitlens.views.applyChanges.title": "Apply Changes", + "gitlens.views.closeRepository.title": "Close Repository", + "gitlens.views.compareAncestryWithWorking.title": "Compare Ancestry with Working Tree", + "gitlens.views.compareWithHead.title": "Compare with HEAD", + "gitlens.views.compareWithUpstream.title": "Compare with Upstream", + "gitlens.views.compareWithSelected.title": "Compare with Selected", + "gitlens.views.selectForCompare.title": "Select for Compare", + "gitlens.views.compareFileWithSelected.title": "Compare with Selected", + "gitlens.views.selectFileForCompare.title": "Select for Compare", + "gitlens.views.compareWithWorking.title": "Compare with Working Tree", + "gitlens.views.addAuthors.title": "Add Co-authors", + "gitlens.views.addAuthor.title": "Add as Co-author", + "gitlens.views.createWorktree.title": "Create Worktree...", + "gitlens.views.deleteWorktree.title": "Delete Worktree...", + "gitlens.views.openWorktree.title": "Open Worktree", + "gitlens.views.openWorktreeInNewWindow.title": "Open Worktree in New Window", + "gitlens.views.revealWorktreeInExplorer.title": "Reveal Worktree in File Explorer", + "gitlens.views.cherryPick.title": "Cherry Pick Commit...", + "gitlens.views.createBranch.title": "Create Branch...", + "gitlens.views.deleteBranch.title": "Delete Branch...", + "gitlens.views.renameBranch.title": "Rename Branch...", + "gitlens.views.createTag.title": "Create Tag...", + "gitlens.views.deleteTag.title": "Delete Tag...", + "gitlens.views.mergeBranchInto.title": "Merge Branch into Current Branch...", + "gitlens.views.pushToCommit.title": "Push to Commit...", + "gitlens.views.rebaseOntoBranch.title": "Rebase Current Branch onto Branch...", + "gitlens.views.rebaseOntoCommit.title": "Rebase Current Branch onto Commit...", + "gitlens.views.rebaseOntoUpstream.title": "Rebase Current Branch onto Upstream...", + "gitlens.views.resetCommit.title": "Reset Current Branch to Previous Commit...", + "gitlens.views.resetToCommit.title": "Reset Current Branch to Commit...", + "gitlens.views.revert.title": "Revert Commit...", + "gitlens.views.undoCommit.title": "Undo Commit", + "gitlens.views.terminalRemoveRemote.title": "Remove Remote (via Terminal)", + "gitlens.views.setBranchComparisonToWorking.title": "Toggle Compare with: Branch", + "gitlens.views.setBranchComparisonToBranch.title": "Toggle Compare with: Working Tree", + "gitlens.views.createPullRequest.title": "Create Pull Request...", + "gitlens.views.openPullRequest.title": "Open Pull Request", + "gitlens.views.clearNode.title": "Clear", + "gitlens.views.dismissNode.title": "Dismiss", + "gitlens.views.editNode.title": "Edit...", + "gitlens.views.expandNode.title": "Expand", + "gitlens.views.refreshNode.title": "Refresh", + "gitlens.views.loadMoreChildren.title": "Load More", + "gitlens.views.loadAllChildren.title": "Load All", + "gitlens.views.setShowRelativeDateMarkersOn.title": "Show Date Markers", + "gitlens.views.setShowRelativeDateMarkersOff.title": "Hide Date Markers", + "gitlens.views.branches.copy.title": "Copy", + "gitlens.views.branches.refresh.title": "Refresh", + "gitlens.views.branches.setLayoutToList.title": "Toggle View: Tree", + "gitlens.views.branches.setLayoutToTree.title": "Toggle View: List", + "gitlens.views.branches.setFilesLayoutToAuto.title": "Toggle Files View: Tree", + "gitlens.views.branches.setFilesLayoutToList.title": "Toggle Files View: Auto", + "gitlens.views.branches.setFilesLayoutToTree.title": "Toggle Files View: List", + "gitlens.views.branches.setShowAvatarsOn.title": "Show Avatars", + "gitlens.views.branches.setShowAvatarsOff.title": "Hide Avatars", + "gitlens.views.branches.setShowBranchComparisonOn.title": "Show Branch Comparisons", + "gitlens.views.branches.setShowBranchComparisonOff.title": "Hide Branch Comparisons", + "gitlens.views.branches.setShowBranchPullRequestOn.title": "Show Branch Pull Requests", + "gitlens.views.branches.setShowBranchPullRequestOff.title": "Hide Branch Pull Requests", + "gitlens.views.commits.copy.title": "Copy", + "gitlens.views.commits.refresh.title": "Refresh", + "gitlens.views.commits.setFilesLayoutToAuto.title": "Toggle Files View: Tree", + "gitlens.views.commits.setFilesLayoutToList.title": "Toggle Files View: Auto", + "gitlens.views.commits.setFilesLayoutToTree.title": "Toggle Files View: List", + "gitlens.views.commits.setMyCommitsOnlyOn.title": "Toggle Filter: All Commits", + "gitlens.views.commits.setMyCommitsOnlyOff.title": "Toggle Filter: Only My Commits", + "gitlens.views.commits.setShowAvatarsOn.title": "Show Avatars", + "gitlens.views.commits.setShowAvatarsOff.title": "Hide Avatars", + "gitlens.views.commits.setShowBranchComparisonOn.title": "Show Branch Comparison", + "gitlens.views.commits.setShowBranchComparisonOff.title": "Hide Branch Comparison", + "gitlens.views.commits.setShowBranchPullRequestOn.title": "Show Current Branch Pull Request", + "gitlens.views.commits.setShowBranchPullRequestOff.title": "Hide Current Branch Pull Request", + "gitlens.views.contributors.copy.title": "Copy", + "gitlens.views.contributors.refresh.title": "Refresh", + "gitlens.views.contributors.setFilesLayoutToAuto.title": "Toggle Files View: Tree", + "gitlens.views.contributors.setFilesLayoutToList.title": "Toggle Files View: Auto", + "gitlens.views.contributors.setFilesLayoutToTree.title": "Toggle Files View: List", + "gitlens.views.contributors.setShowAllBranchesOn.title": "Toggle Filter: Only Current Branch", + "gitlens.views.contributors.setShowAllBranchesOff.title": "Toggle Filter: All Branches", + "gitlens.views.contributors.setShowAvatarsOn.title": "Show Avatars", + "gitlens.views.contributors.setShowAvatarsOff.title": "Hide Avatars", + "gitlens.views.contributors.setShowStatisticsOn.title": "Show Statistics", + "gitlens.views.contributors.setShowStatisticsOff.title": "Hide Statistics", + "gitlens.views.fileHistory.changeBase.title": "Change Base...", + "gitlens.views.fileHistory.copy.title": "Copy", + "gitlens.views.fileHistory.refresh.title": "Refresh", + "gitlens.views.fileHistory.setCursorFollowingOn.title": "Toggle History by: File", + "gitlens.views.fileHistory.setCursorFollowingOff.title": "Toggle History by: Selected Line(s)", + "gitlens.views.fileHistory.setEditorFollowingOn.title": "Unpin the Current History", + "gitlens.views.fileHistory.setEditorFollowingOff.title": "Pin the Current History", + "gitlens.views.fileHistory.setRenameFollowingOn.title": "Toggle Follow Renames: Off", + "gitlens.views.fileHistory.setRenameFollowingOff.title": "Toggle Follow Renames: On", + "gitlens.views.fileHistory.setShowAllBranchesOn.title": "Toggle Filter: Only Current Branch", + "gitlens.views.fileHistory.setShowAllBranchesOff.title": "Toggle Filter: All Branches", + "gitlens.views.fileHistory.setShowAvatarsOn.title": "Show Avatars", + "gitlens.views.fileHistory.setShowAvatarsOff.title": "Hide Avatars", + "gitlens.views.home.refresh.title": "Refresh", + "gitlens.views.lineHistory.changeBase.title": "Change Base...", + "gitlens.views.lineHistory.copy.title": "Copy", + "gitlens.views.lineHistory.refresh.title": "Refresh", + "gitlens.views.lineHistory.setEditorFollowingOn.title": "Unpin the Current History", + "gitlens.views.lineHistory.setEditorFollowingOff.title": "Pin the Current History", + "gitlens.views.lineHistory.setShowAvatarsOn.title": "Show Avatars", + "gitlens.views.lineHistory.setShowAvatarsOff.title": "Hide Avatars", + "gitlens.views.remotes.copy.title": "Copy", + "gitlens.views.remotes.refresh.title": "Refresh", + "gitlens.views.remotes.setLayoutToList.title": "Toggle View: Tree", + "gitlens.views.remotes.setLayoutToTree.title": "Toggle View: List", + "gitlens.views.remotes.setFilesLayoutToAuto.title": "Toggle Files View: Tree", + "gitlens.views.remotes.setFilesLayoutToList.title": "Toggle Files View: Auto", + "gitlens.views.remotes.setFilesLayoutToTree.title": "Toggle Files View: List", + "gitlens.views.remotes.setShowAvatarsOn.title": "Show Avatars", + "gitlens.views.remotes.setShowAvatarsOff.title": "Hide Avatars", + "gitlens.views.remotes.setShowBranchPullRequestOn.title": "Show Branch Pull Requests", + "gitlens.views.remotes.setShowBranchPullRequestOff.title": "Hide Branch Pull Requests", + "gitlens.views.repositories.copy.title": "Copy", + "gitlens.views.repositories.refresh.title": "Refresh", + "gitlens.views.repositories.setAutoRefreshToOn.title": "Enable Automatic Refresh", + "gitlens.views.repositories.setAutoRefreshToOff.title": "Disable Automatic Refresh", + "gitlens.views.repositories.setBranchesLayoutToList.title": "Toggle Branches View: Tree", + "gitlens.views.repositories.setBranchesLayoutToTree.title": "Toggle Branches View: List", + "gitlens.views.repositories.setFilesLayoutToAuto.title": "Toggle Files View: Tree", + "gitlens.views.repositories.setFilesLayoutToList.title": "Toggle Files View: Auto", + "gitlens.views.repositories.setFilesLayoutToTree.title": "Toggle Files View: List", + "gitlens.views.repositories.setShowAvatarsOn.title": "Show Avatars", + "gitlens.views.repositories.setShowAvatarsOff.title": "Hide Avatars", + "gitlens.views.repositories.setShowBranchComparisonOn.title": "Show Branch Comparison", + "gitlens.views.repositories.setShowBranchComparisonOff.title": "Hide Branch Comparison", + "gitlens.views.repositories.setBranchesShowBranchComparisonOn.title": "Show Branch Comparisons", + "gitlens.views.repositories.setBranchesShowBranchComparisonOff.title": "Hide Branch Comparisons", + "gitlens.views.repositories.setShowBranchesOn.title": "Show Branches", + "gitlens.views.repositories.setShowBranchesOff.title": "Hide Branches", + "gitlens.views.repositories.setShowCommitsOn.title": "Show Commits", + "gitlens.views.repositories.setShowCommitsOff.title": "Hide Commits", + "gitlens.views.repositories.setShowContributorsOn.title": "Show Contributors", + "gitlens.views.repositories.setShowContributorsOff.title": "Hide Contributors", + "gitlens.views.repositories.setShowRemotesOn.title": "Show Remotes", + "gitlens.views.repositories.setShowRemotesOff.title": "Hide Remotes", + "gitlens.views.repositories.setShowStashesOn.title": "Show Stashes", + "gitlens.views.repositories.setShowStashesOff.title": "Hide Stashes", + "gitlens.views.repositories.setShowTagsOn.title": "Show Tags", + "gitlens.views.repositories.setShowTagsOff.title": "Hide Tags", + "gitlens.views.repositories.setShowWorktreesOn.title": "Show Worktrees", + "gitlens.views.repositories.setShowWorktreesOff.title": "Hide Worktrees", + "gitlens.views.repositories.setShowUpstreamStatusOn.title": "Show Current Branch Status", + "gitlens.views.repositories.setShowUpstreamStatusOff.title": "Hide Current Branch Status", + "gitlens.views.repositories.setShowSectionOff.title": "Hide", + "gitlens.views.searchAndCompare.clear.title": "Clear Results", + "gitlens.views.searchAndCompare.copy.title": "Copy", + "gitlens.views.searchAndCompare.pin.title": "Pin", + "gitlens.views.searchAndCompare.unpin.title": "Unpin", + "gitlens.views.searchAndCompare.refresh.title": "Refresh", + "gitlens.views.searchAndCompare.searchCommits.title": "Search Commits...", + "gitlens.views.searchAndCompare.selectForCompare.title": "Compare References...", + "gitlens.views.searchAndCompare.setFilesLayoutToAuto.title": "Toggle Files View: Tree", + "gitlens.views.searchAndCompare.setFilesLayoutToList.title": "Toggle Files View: Auto", + "gitlens.views.searchAndCompare.setFilesLayoutToTree.title": "Toggle Files View: List", + "gitlens.views.searchAndCompare.setKeepResultsToOn.title": "Keep Results", + "gitlens.views.searchAndCompare.setKeepResultsToOff.title": "Keep Results", + "gitlens.views.searchAndCompare.setShowAvatarsOn.title": "Show Avatars", + "gitlens.views.searchAndCompare.setShowAvatarsOff.title": "Hide Avatars", + "gitlens.views.searchAndCompare.swapComparison.title": "Swap Comparison", + "gitlens.views.searchAndCompare.setFilesFilterOnLeft.title": "Show Left-side Files Only", + "gitlens.views.searchAndCompare.setFilesFilterOnRight.title": "Show Right-side Files Only", + "gitlens.views.searchAndCompare.setFilesFilterOff.title": "Clear Filter", + "gitlens.views.stashes.copy.title": "Copy", + "gitlens.views.stashes.refresh.title": "Refresh", + "gitlens.views.stashes.setFilesLayoutToAuto.title": "Toggle Files View: Tree", + "gitlens.views.stashes.setFilesLayoutToList.title": "Toggle Files View: Auto", + "gitlens.views.stashes.setFilesLayoutToTree.title": "Toggle Files View: List", + "gitlens.views.tags.copy.title": "Copy", + "gitlens.views.tags.refresh.title": "Refresh", + "gitlens.views.tags.setLayoutToList.title": "Toggle View: Tree", + "gitlens.views.tags.setLayoutToTree.title": "Toggle View: List", + "gitlens.views.tags.setFilesLayoutToAuto.title": "Toggle Files View: Tree", + "gitlens.views.tags.setFilesLayoutToList.title": "Toggle Files View: Auto", + "gitlens.views.tags.setFilesLayoutToTree.title": "Toggle Files View: List", + "gitlens.views.tags.setShowAvatarsOn.title": "Show Avatars", + "gitlens.views.tags.setShowAvatarsOff.title": "Hide Avatars", + "gitlens.views.timeline.openInTab.title": "Open in Editor Area", + "gitlens.views.timeline.refresh.title": "Refresh", + "gitlens.views.worktrees.copy.title": "Copy", + "gitlens.views.worktrees.refresh.title": "Refresh", + "gitlens.views.worktrees.setFilesLayoutToAuto.title": "Toggle Files View: Tree", + "gitlens.views.worktrees.setFilesLayoutToList.title": "Toggle Files View: Auto", + "gitlens.views.worktrees.setFilesLayoutToTree.title": "Toggle Files View: List", + "gitlens.views.worktrees.setShowAvatarsOn.title": "Show Avatars", + "gitlens.views.worktrees.setShowAvatarsOff.title": "Hide Avatars", + "gitlens.views.worktrees.setShowBranchComparisonOn.title": "Show Branch Comparison", + "gitlens.views.worktrees.setShowBranchComparisonOff.title": "Hide Branch Comparison", + "gitlens.views.worktrees.setShowBranchPullRequestOn.title": "Show Branch Pull Requests", + "gitlens.views.worktrees.setShowBranchPullRequestOff.title": "Hide Branch Pull Requests", + "gitlens.enableDebugLogging.title": "Enable Debug Logging", + "gitlens.disableDebugLogging.title": "Disable Debug Logging", + "gitlens.submenus.gitlensCommitBrowse.label": "Browse", + "gitlens.submenus.gitlensCommitCopy.label": "Copy As", + "gitlens.submenus.gitlensCommitChanges.label": "Open Changes", + "gitlens.submenus.gitlensCommitFileCopy.label": "Copy As", + "gitlens.submenus.gitlensCommitFileCommit.label": "Commit", + "gitlens.submenus.gitlensCommitFileChanges.label": "Open Changes", + "gitlens.submenus.gitlensEditorAnnotations.label": "File Annotations", + "gitlens.submenus.gitlensEditorContextChanges.label": "Commit Changes", + "gitlens.submenus.gitlensEditorChanges.label": "Commit Changes", + "gitlens.submenus.gitlensExplorerChanges.label": "Commit Changes", + "gitlens.submenus.gitlensScmResourceGroupChanges.label": "Open Changes", + "gitlens.submenus.gitlensScmResourceStateChanges.label": "Open Changes", + "gitlens.submenus.gitlensViewRepositoriesSections.label": "Sections", + "gitlens.submenus.gitlensViewSearchAndCompareNew.label": "New Search or Compare", + "gitlens.submenus.gitlensViewSearchAndCompareComparisonFilter.label": "Filter", + "gitlens.rebase.displayName": "GitLens Interactive Rebase Editor", + "gitlens.contributes.activitybar.gitlens.title": "GitLens", + "gitlens.contributes.panel.gitlensPanel.title": "GitLens", + "gitlens.views.searchAndCompare.welcome.search.noVirtualFolders.contents": "Search for commits by [message](command:gitlens.views.searchAndCompare.searchCommits?%7B%22search%22%3A%7B%22pattern%22%3A%22message%3A%22%7D%2C%22prefillOnly%22%3Atrue%7D), [author](command:gitlens.views.searchAndCompare.searchCommits?%7B%22search%22%3A%7B%22pattern%22%3A%22author%3A%22%7D%2C%22prefillOnly%22%3Atrue%7D), [SHA](command:gitlens.views.searchAndCompare.searchCommits?%7B%22search%22%3A%7B%22pattern%22%3A%22commit%3A%22%7D%2C%22prefillOnly%22%3Atrue%7D), [file](command:gitlens.views.searchAndCompare.searchCommits?%7B%22search%22%3A%7B%22pattern%22%3A%22file%3A%22%7D%2C%22prefillOnly%22%3Atrue%7D), or [changes](command:gitlens.views.searchAndCompare.searchCommits?%7B%22search%22%3A%7B%22pattern%22%3A%22change%3A%22%7D%2C%22prefillOnly%22%3Atrue%7D)\n\n[Search Commits...](command:gitlens.views.searchAndCompare.searchCommits)", + "gitlens.views.searchAndCompare.welcome.search.hasVirtualFolders.contents": "Search for commits by [message](command:gitlens.views.searchAndCompare.searchCommits?%7B%22search%22%3A%7B%22pattern%22%3A%22message%3A%22%7D%2C%22prefillOnly%22%3Atrue%7D), [author](command:gitlens.views.searchAndCompare.searchCommits?%7B%22search%22%3A%7B%22pattern%22%3A%22author%3A%22%7D%2C%22prefillOnly%22%3Atrue%7D), or [SHA](command:gitlens.views.searchAndCompare.searchCommits?%7B%22search%22%3A%7B%22pattern%22%3A%22commit%3A%22%7D%2C%22prefillOnly%22%3Atrue%7D)\n\n[Search Commits...](command:gitlens.views.searchAndCompare.searchCommits)", + "gitlens.views.searchAndCompare.welcome.compare.noVirtualFolders.contents": "Compare a with another \n\n[Compare References...](command:gitlens.views.searchAndCompare.selectForCompare)", + "gitlens.views.worktrees.welcome.contents": "Worktrees allow you to easily work on different branches of a repository simultaneously. You can create multiple working trees, each of which can be opened in individual windows or all together in a single workspace.", + "gitlens.views.worktrees.welcome.plusAllowed.contents": "[Create Worktree...](command:gitlens.views.createWorktree)", + "gitlens.views.worktrees.welcome.verifyEmail.contents": "Please verify your email\n\nTo use Worktrees, please verify the email for the account you created.\n\n[Resend verification email](command:gitlens.plus.resendVerification)\n\n[Refresh verification status](command:gitlens.plus.validate)", + "gitlens.views.worktrees.welcome.tryNow.contents": "Try worktrees now, without an account, for 3 days on public and private repos, or [sign in](command:gitlens.plus.loginOrSignUp \"Sign in to GitLens+\") for use on public repos.\n\n[Try worktrees now](command:gitlens.plus.startPreviewTrial)", + "gitlens.views.worktrees.welcome.signIn.contents": "Sign in to use worktrees and other GitLens+ features on public repos and get a free 7-day trial for both public and private repos.\n\n[Sign in to GitLens+](command:gitlens.plus.loginOrSignUp)", + "gitlens.views.worktrees.welcome.purchasePlan.contents": "[Upgrade your account](command:gitlens.plus.purchase)", + "gitlens.views.worktrees.welcome.plusFeature.contents": "✨ Worktrees are a [GitLens+ feature](command:gitlens.plus.learn) which can be used on public repos with a [free account](command:gitlens.plus.loginOrSignUp) and private repos with a [paid account](command:gitlens.plus.purchase).\n\n🛈 All other GitLens features can always be used on any repo, without an account.", + "gitlens.views.contextualTitle": "GitLens", + "gitlens.views.home.name": "Home", + "gitlens.views.timeline.name": "Visual File History", + "gitlens.views.commits.name": "Commits", + "gitlens.views.repositories.name": "Repositories", + "gitlens.views.fileHistory.name": "File History", + "gitlens.views.lineHistory.name": "Line History", + "gitlens.views.branches.name": "Branches", + "gitlens.views.remotes.name": "Remotes", + "gitlens.views.stashes.name": "Stashes", + "gitlens.views.tags.name": "Tags", + "gitlens.views.worktrees.name": "Worktrees", + "gitlens.views.contributors.name": "Contributors", + "gitlens.views.searchAndCompare.name": "Search & Compare", + "gitlens.welcome.title": "Get Started with GitLens", + "gitlens.welcome.description": "Discover and personalize features that supercharge your Git experience", + "gitlens.welcome.experience.title": "Get setup quickly", + "gitlens.welcome.experience.description": "Use the Quick Setup to easily configure frequently used GitLens features.\n\n[Open Quick Setup](command:gitlens.showWelcomePage?%22quick-setup%22 \"Opens the GitLens Quick Setup\")", + "gitlens.welcome.settings.title": "Easily customize every aspect of GitLens", + "gitlens.welcome.settings.description": "A rich, interactive settings editor enables seemingly endless customization possibilities.\n\n[Open Settings](command:gitlens.showSettingsPage \"Opens the GitLens Interactive Settings\")", + "gitlens.welcome.currentLineBlame.title": "See who made what changes at a glance", + "gitlens.welcome.currentLineBlame.description": "Current line and status bar blame provide historical context about line changes.", + "gitlens.welcome.gitCodeLens.title": "View Git authorship via CodeLens", + "gitlens.welcome.gitCodeLens.description": "CodeLens adds contextual authorship information and links at the top of each file and at the beginning of each block of code.", + "gitlens.welcome.revisionHistory.title": "Easily navigate revision history", + "gitlens.welcome.fileAnnotations.title": "See more context with file annotations", + "gitlens.welcome.fileAnnotations.description": "Whole file annotations place visual indicators in the gutter and scroll bar that provide additional context about changes.", + "gitlens.welcome.gitSideBarViews.title": "Explore repositories from the side bar", + "gitlens.welcome.gitSideBarViews.description": "Rich views expose even more Git functionality in your side bar.\n\n[Set Views Layout](command:gitlens.setViewsLayout)", + "gitlens.welcome.hostingServiceIntegrations.title": "Integrate with Git hosting services", + "gitlens.welcome.hostingServiceIntegrations.description": "Quickly gain insights from pull requests and issues without leaving your editor.", + "gitlens.welcome.gitCommandPalette.title": "Work faster with Git Command Palette", + "gitlens.welcome.gitCommandPalette.description": "Now you don't have to remember all those Git commands.\n\n[Open Git Command Palette](command:gitlens.gitCommands)", + "gitlens.welcome.interactiveRebaseEditor.title": "Visualize interactive rebase operations", + "gitlens.welcome.interactiveRebaseEditor.description": "A user-friendly interactive rebase editor to easily configure an interactive rebase session", + "gitlens.welcome.terminal.title": "Jump to git details from the terminal", + "gitlens.welcome.terminal.description": "Using ctrl/cmd+click on autolinks in the integrated terminal will quickly jump to more details for commits, branches, tags, and more.", + "gitlens.welcome.plus.title": "✨ Premium features", + "gitlens.welcome.plus.description": "Check out the all-new, completely optional, GitLens+ features.\n\n[Learn about GitLens+ features](command:gitlens.plus.learn?false \"Open the GitLens+ features walkthrough\")", + "gitlens.plus.title": "Introducing GitLens+", + "gitlens.plus.description": "Get even more out of GitLens in VS Code!", + "gitlens.plus.intro.tryNow.title": "Introducing GitLens+", + "gitlens.plus.intro.tryNow.description": "Try GitLens+ features now, without an account, for 3 days.\n\n[Try GitLens+ features now](command:gitlens.plus.startPreviewTrial)", + "gitlens.plus.intro.signIn.title": "Introducing GitLens+", + "gitlens.plus.intro.signIn.description": "Sign in for use on public repos and get an additional 7 day trial for private repos.\n\n[Sign in to GitLens+](command:gitlens.plus.loginOrSignUp)", + "gitlens.plus.intro.title": "Introducing GitLens+", + "gitlens.plus.visualFileHistory.title": "Visualize file history", + "gitlens.plus.visualFileHistory.description": "A more visual way to analyze and explore changes made to a file.\n\n[Open Visual File History view](command:gitlens.showTimelineView)", + "gitlens.plus.worktrees.title": "Worktrees", + "gitlens.plus.worktrees.description": "Create worktrees to have multiple branches checked-out at once on the same repository.\n\n[Open Worktrees view](command:gitlens.showWorktreesView)", + "gitlens.plus.comingSoon.title": "More coming soon", + "gitlens.plus.comingSoon.description": "Stay tuned!", + "gitlens.plus.tryNow.title": "Try GitLens+ now", + "gitlens.plus.tryNow.description": "Try GitLens+ features now, without an account, for 3 days.\n\n[Try GitLens+ features now](command:gitlens.plus.startPreviewTrial)", + "gitlens.plus.signIn.title": "Get access to GitLens+ features on public repos", + "gitlens.plus.signIn.description": "Sign in for use on public repos and get an additional 7 day trial for private repos.\n\n[Sign in to GitLens+](command:gitlens.plus.loginOrSignUp)" +} diff --git a/src/commands/git/branch.ts b/src/commands/git/branch.ts index 735e13ede2dff..f0f72ea133577 100644 --- a/src/commands/git/branch.ts +++ b/src/commands/git/branch.ts @@ -1,9 +1,9 @@ import { QuickInputButtons } from 'vscode'; +import * as nls from 'vscode-nls'; import type { Container } from '../../container'; import { GitBranchReference, GitReference, Repository } from '../../git/models'; import { QuickPickItemOfT } from '../../quickpicks/items/common'; import { FlagsQuickPickItem } from '../../quickpicks/items/flags'; -import { pluralize } from '../../system/string'; import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { appendReposToTitle, @@ -23,6 +23,7 @@ import { StepState, } from '../quickCommand'; +const localize = nls.loadMessageBundle(); interface Context { repos: Repository[]; associatedView: ViewsWithRepositoryFolders; @@ -96,12 +97,13 @@ function assertStateStepDeleteBranches( } const subcommandToTitleMap = new Map([ - ['create', 'Create'], - ['delete', 'Delete'], - ['rename', 'Rename'], + ['create', localize('subcommand.create.title', 'Create Branch')], + ['delete', localize('subcommand.delete.title', 'Delete Branch')], + ['rename', localize('subcommand.rename.title', 'Rename Branch')], ]); -function getTitle(title: string, subcommand: State['subcommand'] | undefined) { - return subcommand == null ? title : `${subcommandToTitleMap.get(subcommand)} ${title}`; + +function getTitle(placeholder: string, subcommand: State['subcommand'] | undefined) { + return subcommand == null ? placeholder : subcommandToTitleMap.get(subcommand) ?? placeholder; } export interface BranchGitCommandArgs { @@ -115,7 +117,7 @@ export class BranchGitCommand extends QuickCommand { constructor(container: Container, args?: BranchGitCommandArgs) { super(container, 'branch', 'branch', 'Branch', { - description: 'create, rename, or delete branches', + description: localize('description', 'create, rename, or delete branches'), }); let counter = 0; @@ -203,7 +205,7 @@ export class BranchGitCommand extends QuickCommand { this.subcommand = state.subcommand; - context.title = getTitle(state.subcommand === 'delete' ? 'Branches' : this.title, state.subcommand); + context.title = getTitle(this.title, state.subcommand); if (state.counter < 2 || state.repo == null || typeof state.repo === 'string') { skippedStepTwo = false; @@ -254,23 +256,23 @@ export class BranchGitCommand extends QuickCommand { private *pickSubcommandStep(state: PartialStepState): StepResultGenerator { const step = QuickCommand.createPickStep>({ title: this.title, - placeholder: `Choose a ${this.label} command`, + placeholder: localize('pickSubCommandStep.placeholder', 'Choose a {0} command', this.label), items: [ { - label: 'create', - description: 'creates a new branch', + label: localize('pickSubCommandStep.create.label', 'create'), + description: localize('pickSubCommandStep.create.description', 'creates a new branch'), picked: state.subcommand === 'create', item: 'create', }, { - label: 'delete', - description: 'deletes the specified branches', + label: localize('pickSubCommandStep.delete.label', 'delete'), + description: localize('pickSubCommandStep.delete.description', 'deletes the specified branches'), picked: state.subcommand === 'delete', item: 'delete', }, { - label: 'rename', - description: 'renames the specified branch', + label: localize('pickSubCommandStep.rename.label', 'rename'), + description: localize('pickSubCommandStep.rename.description', 'renames the specified branch'), picked: state.subcommand === 'rename', item: 'rename', }, @@ -290,9 +292,17 @@ export class BranchGitCommand extends QuickCommand { if (state.counter < 3 || state.reference == null) { const result = yield* pickBranchOrTagStep(state, context, { placeholder: context => - `Choose a branch${context.showTags ? ' or tag' : ''} to create the new branch from`, + context.showTags + ? localize( + 'create.pickBranchOrTagStep.placeholder.chooseBranchToCreateNewBranchFrom', + 'Choose a branch to create the new branch from', + ) + : localize( + 'create.pickBranchOrTagStep.placeholder.chooseBranchOrTagToCreateNewBranchFrom', + 'Choose a branch or tag to create the new branch from', + ), picked: state.reference?.ref ?? (await state.repo.getBranch())?.ref, - titleContext: ' from', + titleContext: ` ${localize('from', 'from')}`, value: GitReference.isRevision(state.reference) ? state.reference.ref : undefined, }); // Always break on the first step (so we will go back) @@ -303,12 +313,19 @@ export class BranchGitCommand extends QuickCommand { if (state.counter < 4 || state.name == null) { const result = yield* inputBranchNameStep(state, context, { - placeholder: 'Please provide a name for the new branch', - titleContext: ` from ${GitReference.toString(state.reference, { - capitalize: true, - icon: false, - label: state.reference.refType !== 'branch', - })}`, + placeholder: localize( + 'create.inputBranchNameStep.placeholder', + 'Please provide a name for the new branch', + ), + titleContext: ` ${localize( + 'fromRef', + 'from {0}', + GitReference.toString(state.reference, { + capitalize: true, + icon: false, + label: state.reference.refType !== 'branch', + }), + )}`, value: state.name ?? GitReference.getNameWithoutRemote(state.reference), }); if (result === StepResult.Break) continue; @@ -337,20 +354,26 @@ export class BranchGitCommand extends QuickCommand { context: Context, ): StepResultGenerator { const step: QuickPickStep> = QuickCommand.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), [ FlagsQuickPickItem.create(state.flags, [], { label: context.title, - detail: `Will create a new branch named ${state.name} from ${GitReference.toString( - state.reference, - )}`, + detail: localize( + 'createCommandConfirmStep.create.detail', + 'Will create a new branch named {0} from {1}', + state.name, + GitReference.toString(state.reference), + ), }), FlagsQuickPickItem.create(state.flags, ['--switch'], { - label: `${context.title} and Switch`, + label: localize('createCommandComfirmStep.createAndSwitch.label', '{0} and Switch', context.title), description: '--switch', - detail: `Will create and switch to a new branch named ${state.name} from ${GitReference.toString( - state.reference, - )}`, + detail: localize( + 'createCommandComfirmStep.createAndSwitch.detail.willCreateAndSwitchToBranchFromRef', + 'Will create and switch to a new branch named {0} from {1}', + state.name, + GitReference.toString(state.reference), + ), }), ], context, @@ -374,12 +397,12 @@ export class BranchGitCommand extends QuickCommand { state.references == null || (Array.isArray(state.references) && state.references.length === 0) ) { - context.title = getTitle('Branches', state.subcommand); + context.title = localize('subcommand.delete.title.plural', 'Delete Branches'); const result = yield* pickBranchesStep(state, context, { filter: b => !b.current, picked: state.references?.map(r => r.ref), - placeholder: 'Choose branches to delete', + placeholder: localize('deleteCommandSteps.placeholder', 'Choose branches to delete'), sort: { current: false, missingUpstream: true }, }); // Always break on the first step (so we will go back) @@ -388,10 +411,10 @@ export class BranchGitCommand extends QuickCommand { state.references = result; } - context.title = getTitle( - pluralize('Branch', state.references.length, { only: true, plural: 'Branches' }), - state.subcommand, - ); + context.title = + state.references.length === 1 + ? localize('subcommand.delete.title', 'Delete Branch') + : localize('subcommand.delete.title.plural', 'Delete Branches'); assertStateStepDeleteBranches(state); const result = yield* this.deleteCommandConfirmStep(state, context); @@ -414,44 +437,62 @@ export class BranchGitCommand extends QuickCommand { const confirmations: FlagsQuickPickItem[] = [ FlagsQuickPickItem.create(state.flags, [], { label: context.title, - detail: `Will delete ${GitReference.toString(state.references)}`, + detail: localize( + 'deleteCommandConfirmStep.delete.detail', + 'Will delete {0}', + GitReference.toString(state.references), + ), }), ]; if (!state.references.every(b => b.remote)) { confirmations.push( FlagsQuickPickItem.create(state.flags, ['--force'], { - label: `Force ${context.title}`, + label: localize('deleteCommandConfirmStep.force.label', 'Force {0}', context.title), description: '--force', - detail: `Will forcibly delete ${GitReference.toString(state.references)}`, + detail: localize( + 'deleteCommandConfirmStep.force.detail', + 'Will forcibly delete {0}', + GitReference.toString(state.references), + ), }), ); if (state.references.some(b => b.upstream != null)) { confirmations.push( FlagsQuickPickItem.create(state.flags, ['--remotes'], { - label: `${context.title} & Remote${ - state.references.filter(b => !b.remote).length > 1 ? 's' : '' - }`, + label: + state.references.filter(b => !b.remote).length > 1 + ? localize( + 'deleteCommandConfirmStep.remote.label.plural', + '{0} & Remotes', + context.title, + ) + : localize('deleteCommandConfirmStep.remote.label', '{0} & Remote', context.title), description: '--remotes', - detail: `Will delete ${GitReference.toString( - state.references, - )} and any remote tracking branches`, + detail: localize( + 'deleteCommandConfirmStep.remote.detail', + 'Will delete {0} and any remote tracking branches', + GitReference.toString(state.references), + ), }), FlagsQuickPickItem.create(state.flags, ['--force', '--remotes'], { - label: `Force ${context.title} & Remote${ - state.references.filter(b => !b.remote).length > 1 ? 's' : '' - }`, + label: + state.references.filter(b => !b.remote).length > 1 + ? localize('deleteCommandConfirmStep.forceRemote.label.plural', 'Force {0} & Remotes') + : localize('deleteCommandConfirmStep.forceRemote.label', 'Force {0} & Remote'), description: '--force --remotes', - detail: `Will forcibly delete ${GitReference.toString( - state.references, - )} and any remote tracking branches`, + detail: localize( + 'deleteCommandConfirmStep.forceRemote.detail', + 'Will forcibly delete {0} and any remote tracking branches', + GitReference.toString(state.references), + ), }), ); } } const step: QuickPickStep> = QuickCommand.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirmCommand', 'Confirm {0}', context.title), state, context), confirmations, context, ); @@ -469,7 +510,10 @@ export class BranchGitCommand extends QuickCommand { const result = yield* pickBranchStep(state, context, { filter: b => !b.remote, picked: state.reference?.ref, - placeholder: 'Choose a branch to rename', + placeholder: localize( + 'rename.pickBranchStep.placeholder.chooseBranchToRename', + 'Choose a branch to rename', + ), }); // Always break on the first step (so we will go back) if (result === StepResult.Break) break; @@ -479,9 +523,13 @@ export class BranchGitCommand extends QuickCommand { if (state.counter < 4 || state.name == null) { const result = yield* inputBranchNameStep(state, context, { - placeholder: `Please provide a new name for ${GitReference.toString(state.reference, { - icon: false, - })}`, + placeholder: localize( + 'rename.inputBranchNameStep.placeholder.provideNewNameForRef', + 'Please provide a new name for {0}', + GitReference.toString(state.reference, { + icon: false, + }), + ), titleContext: ` ${GitReference.toString(state.reference, false)}`, value: state.name ?? state.reference.name, }); @@ -505,11 +553,16 @@ export class BranchGitCommand extends QuickCommand { context: Context, ): StepResultGenerator { const step: QuickPickStep> = QuickCommand.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), [ FlagsQuickPickItem.create(state.flags, ['-m'], { label: context.title, - detail: `Will rename ${GitReference.toString(state.reference)} to ${state.name}`, + detail: localize( + 'renameCommandConfirmStep.detail.willRenameRefToName', + 'Will rename {0} to {1}', + GitReference.toString(state.reference), + state.name, + ), }), ], context, diff --git a/src/commands/git/cherry-pick.ts b/src/commands/git/cherry-pick.ts index a5d25a30d9e65..695e7df653026 100644 --- a/src/commands/git/cherry-pick.ts +++ b/src/commands/git/cherry-pick.ts @@ -1,3 +1,4 @@ +import * as nls from 'vscode-nls'; import { Container } from '../../container'; import { GitBranch, GitLog, GitReference, GitRevision, Repository } from '../../git/models'; import { FlagsQuickPickItem } from '../../quickpicks/items/flags'; @@ -17,6 +18,7 @@ import { StepState, } from '../quickCommand'; +const localize = nls.loadMessageBundle(); interface Context { repos: Repository[]; associatedView: ViewsWithRepositoryFolders; @@ -44,8 +46,8 @@ type CherryPickStepState = ExcludeSome, 'r export class CherryPickGitCommand extends QuickCommand { constructor(container: Container, args?: CherryPickGitCommandArgs) { - super(container, 'cherry-pick', 'cherry-pick', 'Cherry Pick', { - description: 'integrates changes from specified commits into the current branch', + super(container, 'cherry-pick', localize('label', 'cherry-pick'), localize('title', 'Cherry Pick'), { + description: localize('description', 'integrates changes from specified commits into the current branch'), }); let counter = 0; @@ -137,7 +139,15 @@ export class CherryPickGitCommand extends QuickCommand { { filter: { branches: b => b.id !== context.destination.id }, placeholder: context => - `Choose a branch${context.showTags ? ' or tag' : ''} to cherry-pick from`, + context.showTags + ? localize( + 'pickBranchOrTagStep.placeholder.chooseBranchOrTagToCherryPickFrom', + 'Choose a branch or tag to cherry-pick from', + ) + : localize( + 'pickBranchOrTagStep.placeholder.chooseBranchToCherryPickFrom', + 'Choose a branch to cherry-pick from', + ), picked: context.selectedBranchOrTag?.ref, value: context.selectedBranchOrTag == null ? state.references?.[0]?.ref : undefined, }, @@ -177,12 +187,20 @@ export class CherryPickGitCommand extends QuickCommand { picked: state.references?.map(r => r.ref), placeholder: (context, log) => log == null - ? `No pickable commits found on ${GitReference.toString(context.selectedBranchOrTag, { - icon: false, - })}` - : `Choose commits to cherry-pick into ${GitReference.toString(context.destination, { - icon: false, - })}`, + ? localize( + 'pickCommitsStep.placeholder.noPickableCommitsFoundOnBranchOrTag', + 'No pickable commits found on {0}', + GitReference.toString(context.selectedBranchOrTag, { + icon: false, + }), + ) + : localize( + 'pickCommitsStep.placeholder.chooseCommitsToCherryPickIntoBranch', + 'Choose commits to cherry-pick into {0}', + GitReference.toString(context.destination, { + icon: false, + }), + ), }, ); if (result === StepResult.Break) continue; @@ -206,27 +224,36 @@ export class CherryPickGitCommand extends QuickCommand { private *confirmStep(state: CherryPickStepState, context: Context): StepResultGenerator { const step: QuickPickStep> = QuickCommand.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirm', 'Confrim {0}', context.title), state, context), [ FlagsQuickPickItem.create(state.flags, [], { label: this.title, - detail: `Will apply ${GitReference.toString(state.references)} to ${GitReference.toString( - context.destination, - )}`, + detail: localize( + 'quickPick.detail', + 'Will apply {0} to {1}', + GitReference.toString(state.references), + GitReference.toString(context.destination), + ), }), FlagsQuickPickItem.create(state.flags, ['--edit'], { label: `${this.title} & Edit`, description: '--edit', - detail: `Will edit and apply ${GitReference.toString(state.references)} to ${GitReference.toString( - context.destination, - )}`, + detail: localize( + 'quickPick.edit.detail', + 'Will edit and apply {0} to {1}', + GitReference.toString(state.references), + GitReference.toString(context.destination), + ), }), FlagsQuickPickItem.create(state.flags, ['--no-commit'], { label: `${this.title} without Committing`, description: '--no-commit', - detail: `Will apply ${GitReference.toString(state.references)} to ${GitReference.toString( - context.destination, - )} without Committing`, + detail: localize( + 'quickPick.noCommit.detail', + 'Will apply {0} to {1} without Committing', + GitReference.toString(state.references), + GitReference.toString(context.destination), + ), }), ], context, diff --git a/src/commands/git/coauthors.ts b/src/commands/git/coauthors.ts index 2128e4dce29f3..4f748dd7d7d60 100644 --- a/src/commands/git/coauthors.ts +++ b/src/commands/git/coauthors.ts @@ -1,3 +1,4 @@ +import * as nls from 'vscode-nls'; import { CoreCommands } from '../../constants'; import type { Container } from '../../container'; import type { GitContributor, Repository } from '../../git/models'; @@ -14,6 +15,7 @@ import { StepState, } from '../quickCommand'; +const localize = nls.loadMessageBundle(); interface Context { repos: Repository[]; activeRepo: Repository | undefined; @@ -35,8 +37,8 @@ type CoAuthorStepState = ExcludeSome, 'rep export class CoAuthorsGitCommand extends QuickCommand { constructor(container: Container, args?: CoAuthorsGitCommandArgs) { - super(container, 'co-authors', 'co-authors', 'Add Co-Authors', { - description: 'adds co-authors to a commit message', + super(container, 'co-authors', localize('label', 'co-authors'), localize('title', 'Add Co-Authors'), { + description: localize('description', 'adds co-authors to a commit message'), }); let counter = 0; @@ -68,7 +70,8 @@ export class CoAuthorsGitCommand extends QuickCommand { let message = repo.inputBox.value; - const index = message.indexOf('Co-authored-by: '); + const coAuthoredBy = localize('coAuthoredBy', 'Co-authored-by: '); + const index = message.indexOf(coAuthoredBy); if (index !== -1) { message = message.substring(0, index - 1).trimRight(); } @@ -79,7 +82,7 @@ export class CoAuthorsGitCommand extends QuickCommand { for (const c of state.contributors) { let newlines; - if (message.includes('Co-authored-by: ')) { + if (message.includes(coAuthoredBy)) { newlines = '\n'; } else if (message.length !== 0 && message.endsWith('\n')) { newlines = '\n\n'; @@ -87,7 +90,7 @@ export class CoAuthorsGitCommand extends QuickCommand { newlines = '\n\n\n'; } - message += `${newlines}Co-authored-by: ${c.getCoauthor()}`; + message += `${newlines}${coAuthoredBy}${c.getCoauthor()}`; } repo.inputBox.value = message; @@ -146,7 +149,7 @@ export class CoAuthorsGitCommand extends QuickCommand { const result = yield* pickContributorsStep( state as CoAuthorStepState, context, - 'Choose contributors to add as co-authors', + localize('pickContributorsStep.label', 'Choose contributors to add as co-authors'), ); if (result === StepResult.Break) { // If we skipped the previous step, make sure we back up past it diff --git a/src/commands/git/fetch.ts b/src/commands/git/fetch.ts index e1f77fe3bece5..65be8b3ab76d3 100644 --- a/src/commands/git/fetch.ts +++ b/src/commands/git/fetch.ts @@ -1,3 +1,4 @@ +import * as nls from 'vscode-nls'; import { GlyphChars } from '../../constants'; import { Container } from '../../container'; import { GitBranchReference, GitReference, Repository } from '../../git/models'; @@ -19,6 +20,7 @@ import { StepState, } from '../quickCommand'; +const localize = nls.loadMessageBundle(); interface Context { repos: Repository[]; associatedView: ViewsWithRepositoryFolders; @@ -43,7 +45,9 @@ type FetchStepState = ExcludeSome, 'repos' export class FetchGitCommand extends QuickCommand { constructor(container: Container, args?: FetchGitCommandArgs) { - super(container, 'fetch', 'fetch', 'Fetch', { description: 'fetches changes from one or more remotes' }); + super(container, 'fetch', localize('label', 'fetch'), localize('title', 'Fetch'), { + description: localize('description', 'fetches changes from one or more remotes'), + }); let counter = 0; if (args?.state?.repos != null && (!Array.isArray(args.state.repos) || args.state.repos.length !== 0)) { @@ -134,7 +138,11 @@ export class FetchGitCommand extends QuickCommand { if (state.repos.length === 1) { const lastFetched = await state.repos[0].getLastFetched(); if (lastFetched !== 0) { - lastFetchedOn = `${pad(GlyphChars.Dot, 2, 2)}Last fetched ${fromNow(new Date(lastFetched))}`; + lastFetchedOn = `${pad(GlyphChars.Dot, 2, 2)}${localize( + 'lastFetchedTime', + 'Last fetched {0}', + fromNow(new Date(lastFetched)), + )}`; } } @@ -142,11 +150,15 @@ export class FetchGitCommand extends QuickCommand { if (state.repos.length === 1 && GitReference.isBranch(state.reference)) { step = this.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context, lastFetchedOn), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context, lastFetchedOn), [ FlagsQuickPickItem.create(state.flags, [], { label: this.title, - detail: `Will fetch ${GitReference.toString(state.reference)}`, + detail: localize( + 'quickPick.fetch.detail.willFetchRef', + 'Will fetch {0}', + GitReference.toString(state.reference), + ), }), ], ); @@ -154,29 +166,33 @@ export class FetchGitCommand extends QuickCommand { const reposToFetch = state.repos.length === 1 ? `$(repo) ${state.repos[0].formattedName}` - : `${state.repos.length} repositories`; + : localize('repositories', '{0} repositories'); step = QuickCommand.createConfirmStep( - appendReposToTitle(`Confirm ${this.title}`, state, context, lastFetchedOn), + appendReposToTitle(localize('confirm', 'Confirm {0}', this.title), state, context, lastFetchedOn), [ FlagsQuickPickItem.create(state.flags, [], { label: this.title, - detail: `Will fetch ${reposToFetch}`, + detail: localize('quickPick.fetch.detail.willFetchRepos', 'Will fetch {0}', reposToFetch), }), FlagsQuickPickItem.create(state.flags, ['--prune'], { label: `${this.title} & Prune`, description: '--prune', - detail: `Will fetch and prune ${reposToFetch}`, + detail: localize('quickPick.prune.detail', 'Will fetch and prune {0}', reposToFetch), }), FlagsQuickPickItem.create(state.flags, ['--all'], { label: `${this.title} All`, description: '--all', - detail: `Will fetch all remotes of ${reposToFetch}`, + detail: localize('quickPick.all.detail', 'Will fetch all remotes of {0}', reposToFetch), }), FlagsQuickPickItem.create(state.flags, ['--all', '--prune'], { label: `${this.title} All & Prune`, description: '--all --prune', - detail: `Will fetch and prune all remotes of ${reposToFetch}`, + detail: localize( + 'quickPick.allPrune.detail', + 'Will fetch and prune all remotes of {0}', + reposToFetch, + ), }), ], context, diff --git a/src/commands/git/log.ts b/src/commands/git/log.ts index 8414f2bf31a6e..9bae46067a443 100644 --- a/src/commands/git/log.ts +++ b/src/commands/git/log.ts @@ -1,3 +1,4 @@ +import * as nls from 'vscode-nls'; import { GlyphChars, quickPickTitleMaxChars } from '../../constants'; import { Container } from '../../container'; import { GitCommit, GitLog, GitReference, Repository } from '../../git/models'; @@ -15,6 +16,7 @@ import { StepResult, } from '../quickCommand'; +const localize = nls.loadMessageBundle(); interface Context { repos: Repository[]; associatedView: ViewsWithRepositoryFolders; @@ -48,8 +50,8 @@ export interface LogGitCommandArgs { export class LogGitCommand extends QuickCommand { constructor(container: Container, args?: LogGitCommandArgs) { - super(container, 'log', 'history', 'Commits', { - description: 'aka log, shows commit history', + super(container, 'log', localize('label', 'history'), localize('title', 'Commits'), { + description: localize('description', 'aka log, shows commit history'), }); let counter = 0; @@ -124,7 +126,10 @@ export class LogGitCommand extends QuickCommand { if (state.counter < 2 || state.reference == null) { const result = yield* pickBranchOrTagStep(state, context, { - placeholder: 'Choose a branch or tag to show its commit history', + placeholder: localize( + 'pickBranchOrTagStep.placeholder.chooseBranchOrTagToShowHistory', + 'Choose a branch or tag to show its commit history', + ), picked: context.selectedBranchOrTag?.ref, value: context.selectedBranchOrTag == null ? state.reference?.ref : undefined, ranges: true, @@ -176,10 +181,14 @@ export class LogGitCommand extends QuickCommand { onDidLoadMore: log => context.cache.set(ref, Promise.resolve(log)), placeholder: (context, log) => log == null - ? `No commits found in ${GitReference.toString(context.selectedBranchOrTag, { - icon: false, - })}` - : 'Choose a commit', + ? localize( + 'pickCommitStep.placeholder.noCommitsFoundInBranchOrTag', + 'No commits found in {0}', + GitReference.toString(context.selectedBranchOrTag, { + icon: false, + }), + ) + : localize('pickCommitStep.placeholder.chooseCommit', 'Choose a commit'), picked: state.reference?.ref, }); if (result === StepResult.Break) continue; diff --git a/src/commands/git/merge.ts b/src/commands/git/merge.ts index 6df7ce553a865..87e76db09f05b 100644 --- a/src/commands/git/merge.ts +++ b/src/commands/git/merge.ts @@ -1,8 +1,8 @@ +import * as nls from 'vscode-nls'; import { Container } from '../../container'; import { GitBranch, GitLog, GitReference, GitRevision, Repository } from '../../git/models'; import { Directive, DirectiveQuickPickItem } from '../../quickpicks/items/directive'; import { FlagsQuickPickItem } from '../../quickpicks/items/flags'; -import { pluralize } from '../../system/string'; import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { appendReposToTitle, @@ -20,6 +20,7 @@ import { StepState, } from '../quickCommand'; +const localize = nls.loadMessageBundle(); interface Context { repos: Repository[]; associatedView: ViewsWithRepositoryFolders; @@ -49,8 +50,8 @@ type MergeStepState = ExcludeSome, 'repo', export class MergeGitCommand extends QuickCommand { constructor(container: Container, args?: MergeGitCommandArgs) { - super(container, 'merge', 'merge', 'Merge', { - description: 'integrates changes from a specified branch into the current branch', + super(container, 'merge', localize('label', 'merge'), localize('title', 'Merge'), { + description: localize('description', 'integrates changes from a specified branch into the current branch'), }); let counter = 0; @@ -134,7 +135,16 @@ export class MergeGitCommand extends QuickCommand { }); const result: StepResult = yield* pickBranchOrTagStep(state as MergeStepState, context, { - placeholder: context => `Choose a branch${context.showTags ? ' or tag' : ''} to merge`, + placeholder: context => + context.showTags + ? localize( + 'pickBranchOrTagStep.placeholder.chooseBranchOrTagToMerge', + 'Choose a branch or tag to merge', + ) + : localize( + 'pickBranchOrTagStep.placeholder.chooseBranchToMerge', + 'Choose a branch to merge', + ), picked: context.selectedBranchOrTag?.ref, value: context.selectedBranchOrTag == null ? state.reference?.ref : undefined, additionalButtons: [pickCommitToggle], @@ -175,12 +185,20 @@ export class MergeGitCommand extends QuickCommand { onDidLoadMore: log => context.cache.set(ref, Promise.resolve(log)), placeholder: (context, log) => log == null - ? `No commits found on ${GitReference.toString(context.selectedBranchOrTag, { - icon: false, - })}` - : `Choose a commit to merge into ${GitReference.toString(context.destination, { - icon: false, - })}`, + ? localize( + 'pickCommitStep.placeholder.noCommitsFoundOnBranchOrTag', + 'No commits found on {0}', + GitReference.toString(context.selectedBranchOrTag, { + icon: false, + }), + ) + : localize( + 'pickCommitStep.placeholder.chooseCommitToMergeIntoBranch', + 'Choose a commit to merge into {0}', + GitReference.toString(context.destination, { + icon: false, + }), + ), picked: state.reference?.ref, }); if (result === StepResult.Break) continue; @@ -207,13 +225,18 @@ export class MergeGitCommand extends QuickCommand { const count = aheadBehind != null ? aheadBehind.ahead + aheadBehind.behind : 0; if (count === 0) { const step: QuickPickStep = this.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('comfirm', 'Confirm {0}', context.title), state, context), [], DirectiveQuickPickItem.create(Directive.Cancel, true, { - label: `Cancel ${this.title}`, - detail: `${GitReference.toString(context.destination, { - capitalize: true, - })} is up to date with ${GitReference.toString(state.reference)}`, + label: localize('quickPick.cancel.label', 'Cancel {0}', this.title), + detail: localize( + 'quickPick.cancle.detail', + '{0} is up to date with {1}', + GitReference.toString(context.destination, { + capitalize: true, + }), + GitReference.toString(state.reference), + ), }), ); const selection: StepSelection = yield step; @@ -222,44 +245,101 @@ export class MergeGitCommand extends QuickCommand { } const step: QuickPickStep> = this.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), [ FlagsQuickPickItem.create(state.flags, [], { label: this.title, - detail: `Will merge ${pluralize('commit', count)} from ${GitReference.toString( - state.reference, - )} into ${GitReference.toString(context.destination)}`, + detail: + count === 1 + ? localize( + 'quickPick.merge.detail.willMergeOneCommitFromRefIntoBranch', + 'Will merge 1 commit from {0} into {1}', + GitReference.toString(state.reference), + GitReference.toString(context.destination), + ) + : localize( + 'quickPick.merge.detail.willMergeCommitsFromRefIntoBranch', + 'Will merge {0} commits from {1} into {2}', + count, + GitReference.toString(state.reference), + GitReference.toString(context.destination), + ), }), FlagsQuickPickItem.create(state.flags, ['--ff-only'], { - label: `Fast-forward ${this.title}`, + label: localize('quickPick.fastForward.label', 'Fast-forward {0}', this.title), description: '--ff-only', - detail: `Will fast-forward merge ${pluralize('commit', count)} from ${GitReference.toString( - state.reference, - )} into ${GitReference.toString(context.destination)}`, + detail: + count === 1 + ? localize( + 'quickPick.fastForward.detail.willFastForwardMergeOneCommitFromRefIntoBranch', + 'Will fast-forward merge 1 commit from {0} into {1}', + GitReference.toString(state.reference), + GitReference.toString(context.destination), + ) + : localize( + 'quickPick.fastForward.detail.willFastForwardMergeCommitsFromRefIntoBranch', + 'Will fast-forward merge {0} commits from {1} into {2}', + count, + GitReference.toString(state.reference), + GitReference.toString(context.destination), + ), }), FlagsQuickPickItem.create(state.flags, ['--squash'], { - label: `Squash ${this.title}`, + label: localize('quickPick.squash.label', 'Squash {0}', this.title), description: '--squash', - detail: `Will squash ${pluralize('commit', count)} from ${GitReference.toString( - state.reference, - )} into one when merging into ${GitReference.toString(context.destination)}`, + detail: + count === 1 + ? localize( + 'quickPick.squash.detail.willSquashOneCommitFromRefWhenMergingIntoBranch', + 'Will squash 1 commit from {0} into one when merging into {1}', + GitReference.toString(state.reference), + GitReference.toString(context.destination), + ) + : localize( + 'quickPick.squash.detail.willSquashCommitsFromRefWhenMergingIntoBranch', + 'Will squash {0} commits from {1} into one when merging into {2}', + count, + GitReference.toString(state.reference), + GitReference.toString(context.destination), + ), }), FlagsQuickPickItem.create(state.flags, ['--no-ff'], { - label: `${this.title} without Fast-Forwarding`, + label: localize('quickPick.noff.label', '{0} without Fast-Forwarding', this.title), description: '--no-ff', - detail: `Will create a merge commit when merging ${pluralize( - 'commit', - count, - )} from ${GitReference.toString(state.reference)} into ${GitReference.toString( - context.destination, - )}`, + detail: + count === 1 + ? localize( + 'quickPick.noff.detail.willCreateMergeCommitWhenMergingOneCommitFromRefToBranch', + 'Will create a merge commit when merging 1 commit from {0} to {1}', + GitReference.toString(state.reference), + GitReference.toString(context.destination), + ) + : localize( + 'quickPick.noff.detail.willCreateMergeCommitWhenMergingCommitsFromRefToBranch', + 'Will create a merge commit when merging {0} commits from {1} to {2}', + count, + GitReference.toString(state.reference), + GitReference.toString(context.destination), + ), }), FlagsQuickPickItem.create(state.flags, ['--no-ff', '--no-commit'], { - label: `${this.title} without Fast-Forwarding or Committing`, + label: localize('quickPick.noffOrCommit', '{0} without Fast-Forwarding or Committing', this.title), description: '--no-ff --no-commit', - detail: `Will merge ${pluralize('commit', count)} from ${GitReference.toString( - state.reference, - )} into ${GitReference.toString(context.destination)} without Committing`, + detail: + count === 1 + ? localize( + 'quickPick.noffOrCommit.detail.willMergeOneCommitFromRefIntoBranchWithoutCommitting', + 'Will merge 1 commit from {0} into {1} without Committing', + GitReference.toString(state.reference), + GitReference.toString(context.destination), + ) + : localize( + 'quickPick.noffOrCommit.detail.willMergeCommitsFromRefIntoBranchWithoutCommitting', + 'Will merge {0} commits from {1} into {2} without Committing', + count, + GitReference.toString(state.reference), + GitReference.toString(context.destination), + ), }), ], ); diff --git a/src/commands/git/pull.ts b/src/commands/git/pull.ts index 1eaadc869f699..e403099b4aad7 100644 --- a/src/commands/git/pull.ts +++ b/src/commands/git/pull.ts @@ -1,3 +1,4 @@ +import * as nls from 'vscode-nls'; import { GlyphChars } from '../../constants'; import { Container } from '../../container'; import { GitBranch, GitBranchReference, GitReference, Repository } from '../../git/models'; @@ -5,7 +6,7 @@ import { Directive, DirectiveQuickPickItem } from '../../quickpicks/items/direct import { FlagsQuickPickItem } from '../../quickpicks/items/flags'; import { isStringArray } from '../../system/array'; import { fromNow } from '../../system/date'; -import { pad, pluralize } from '../../system/string'; +import { pad } from '../../system/string'; import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { appendReposToTitle, @@ -21,6 +22,7 @@ import { StepState, } from '../quickCommand'; +const localize = nls.loadMessageBundle(); interface Context { repos: Repository[]; associatedView: ViewsWithRepositoryFolders; @@ -45,8 +47,11 @@ type PullStepState = ExcludeSome, 'repos', export class PullGitCommand extends QuickCommand { constructor(container: Container, args?: PullGitCommandArgs) { - super(container, 'pull', 'pull', 'Pull', { - description: 'fetches and integrates changes from a remote into the current branch', + super(container, 'pull', localize('label', 'pull'), localize('title', 'Pull'), { + description: localize( + 'description', + 'fetches and integrates changes from a remote into the current branch', + ), }); let counter = 0; @@ -140,25 +145,46 @@ export class PullGitCommand extends QuickCommand { let step: QuickPickStep>; if (state.repos.length > 1) { - step = this.createConfirmStep(appendReposToTitle(`Confirm ${context.title}`, state, context), [ - FlagsQuickPickItem.create(state.flags, [], { - label: this.title, - detail: `Will pull ${state.repos.length} repositories`, - }), - FlagsQuickPickItem.create(state.flags, ['--rebase'], { - label: `${this.title} with Rebase`, - description: '--rebase', - detail: `Will pull ${state.repos.length} repositories by rebasing`, - }), - ]); + step = this.createConfirmStep( + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), + [ + FlagsQuickPickItem.create(state.flags, [], { + label: this.title, + detail: + state.repos.length === 1 + ? localize('quickPick.pull.detail.willPullOneRepository', 'Will pull 1 repository') + : localize( + 'quickPick.pull.detail.willPullRepositories', + 'Will pull {0} repositories', + state.repos.length, + ), + }), + FlagsQuickPickItem.create(state.flags, ['--rebase'], { + label: localize('quickPick.rebase.label', '{0} with Rebase', this.title), + description: '--rebase', + detail: + state.repos.length === 1 + ? localize( + 'quickPick.rebase.detail.willPullOneRepositoryByRebasing', + 'Will pull 1 repository by rebasing', + state.repos.length, + ) + : localize( + 'quickPick.rebase.detail.willPullRepositoriesByRebasing', + 'Will pull {0} repositories by rebasing', + state.repos.length, + ), + }), + ], + ); } else if (GitReference.isBranch(state.reference)) { if (state.reference.remote) { step = this.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), [], DirectiveQuickPickItem.create(Directive.Cancel, true, { - label: `Cancel ${this.title}`, - detail: 'Cannot pull a remote branch', + label: localize('cancel', 'Cancel {0}', this.title), + detail: localize('cannotPullRemoteBranch', 'Cannot pull a remote branch'), }), ); } else { @@ -167,26 +193,43 @@ export class PullGitCommand extends QuickCommand { if (branch?.upstream == null) { step = this.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), [], DirectiveQuickPickItem.create(Directive.Cancel, true, { - label: `Cancel ${this.title}`, - detail: 'Cannot pull a branch until it has been published', + label: localize('cancel', 'Cancel {0}', this.title), + detail: localize( + 'cannotPullBranchUntilItHasBeenPublished', + 'Cannot pull a branch until it has been published', + ), }), ); } else { - step = this.createConfirmStep(appendReposToTitle(`Confirm ${context.title}`, state, context), [ - FlagsQuickPickItem.create(state.flags, [], { - label: this.title, - detail: `Will pull${ - branch.state.behind - ? ` ${pluralize('commit', branch.state.behind)} into ${GitReference.toString( - branch, - )}` - : ` into ${GitReference.toString(branch)}` - }`, - }), - ]); + step = this.createConfirmStep( + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), + [ + FlagsQuickPickItem.create(state.flags, [], { + label: this.title, + detail: branch.state.behind + ? branch.state.behind === 1 + ? localize( + 'quickPick.pull.willPullOneCommitIntoBranch', + 'Will pull 1 commit into {0}', + GitReference.toString(branch), + ) + : localize( + 'quickPick.pull.willPullCommitsIntoBranch', + 'Will pull {0} commits into {1}', + branch.state.behind, + GitReference.toString(branch), + ) + : localize( + 'quickPick.pull.willPullIntoBranch', + 'Will pull into {0}', + GitReference.toString(branch), + ), + }), + ], + ); } } } else { @@ -195,25 +238,60 @@ export class PullGitCommand extends QuickCommand { let lastFetchedOn = ''; if (lastFetched !== 0) { - lastFetchedOn = `${pad(GlyphChars.Dot, 2, 2)}Last fetched ${fromNow(new Date(lastFetched))}`; + lastFetchedOn = `${pad(GlyphChars.Dot, 2, 2)}${localize( + 'lastFetchedTime', + 'Last fetched {0}', + fromNow(new Date(lastFetched)), + )}`; } - const pullDetails = - status?.state.behind != null - ? ` ${pluralize('commit', status.state.behind)} into $(repo) ${repo.formattedName}` - : ` into $(repo) ${repo.formattedName}`; - step = this.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context, lastFetchedOn), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context, lastFetchedOn), [ FlagsQuickPickItem.create(state.flags, [], { label: this.title, - detail: `Will pull${pullDetails}`, + detail: + status?.state.behind != null + ? status.state.behind === 1 + ? localize( + 'quickPick.pull.detail.willPullOneCommitIntoRepo', + 'Will pull 1 commit into {0}', + `$(repo) ${repo.formattedName}`, + ) + : localize( + 'quickPick.pull.detail.willPullCommitsIntoRepo', + 'Will pull {0} commits into {1}', + status.state.behind, + `$(repo) ${repo.formattedName}`, + ) + : localize( + 'quickPick.pull.detail.willPullIntoRepo', + 'Will pull into {0}', + `$(repo) ${repo.formattedName}`, + ), }), FlagsQuickPickItem.create(state.flags, ['--rebase'], { - label: `${this.title} with Rebase`, + label: localize('quickPick.rebase.title', '{0} with Rebase'), description: '--rebase', - detail: `Will pull and rebase${pullDetails}`, + detail: + status?.state.behind != null + ? status.state.behind === 1 + ? localize( + 'quickPick.rebase.detail.willPullAndRebaseOneCommitIntoRepo', + 'Will pull and rebase 1 commit into {0}', + `$(repo) ${repo.formattedName}`, + ) + : localize( + 'quickPick.rebase.detail.willPullAndRebaseCommitsIntoRepo', + 'Will pull and rebase {0} commits into {1}', + status.state.behind, + `$(repo) ${repo.formattedName}`, + ) + : localize( + 'quickPick.rebase.detail.willPullAndRebaseIntoRepo', + 'Will pull and rebase into {0}', + `$(repo) ${repo.formattedName}`, + ), }), ], undefined, @@ -222,9 +300,11 @@ export class PullGitCommand extends QuickCommand { onDidClickButton: async (quickpick, button) => { if (button !== QuickCommandButtons.Fetch || quickpick.busy) return false; - quickpick.title = `Confirm ${context.title}${pad(GlyphChars.Dot, 2, 2)}Fetching${ - GlyphChars.Ellipsis - }`; + quickpick.title = `${localize('confirm', 'Confirm {0}', context.title)}${pad( + GlyphChars.Dot, + 2, + 2, + )}${localize('fetching', 'Fetching')}${GlyphChars.Ellipsis}`; quickpick.busy = true; quickpick.enabled = false; diff --git a/src/commands/git/push.ts b/src/commands/git/push.ts index d9e63367db676..f664300f2ac7a 100644 --- a/src/commands/git/push.ts +++ b/src/commands/git/push.ts @@ -1,3 +1,4 @@ +import * as nls from 'vscode-nls'; import { configuration } from '../../configuration'; import { CoreGitConfiguration, GlyphChars } from '../../constants'; import { Container } from '../../container'; @@ -6,7 +7,7 @@ import { Directive, DirectiveQuickPickItem } from '../../quickpicks/items/direct import { FlagsQuickPickItem } from '../../quickpicks/items/flags'; import { isStringArray } from '../../system/array'; import { fromNow } from '../../system/date'; -import { pad, pluralize } from '../../system/string'; +import { pad } from '../../system/string'; import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { appendReposToTitle, @@ -23,6 +24,7 @@ import { StepState, } from '../quickCommand'; +const localize = nls.loadMessageBundle(); interface Context { repos: Repository[]; associatedView: ViewsWithRepositoryFolders; @@ -47,8 +49,8 @@ type PushStepState = ExcludeSome, 'repos', export class PushGitCommand extends QuickCommand { constructor(container: Container, args?: PushGitCommandArgs) { - super(container, 'push', 'push', 'Push', { - description: 'pushes changes from the current branch to a remote', + super(container, 'push', localize('label', 'push'), localize('title', 'Push'), { + description: localize('description', 'pushes changes from the current branch to a remote'), }); let counter = 0; @@ -157,19 +159,49 @@ export class PushGitCommand extends QuickCommand { let step: QuickPickStep>; if (state.repos.length > 1) { - step = this.createConfirmStep(appendReposToTitle(`Confirm ${context.title}`, state, context), [ - FlagsQuickPickItem.create(state.flags, [], { - label: this.title, - detail: `Will push ${state.repos.length} repositories`, - }), - FlagsQuickPickItem.create(state.flags, ['--force'], { - label: `Force ${this.title}${useForceWithLease ? ' (with lease)' : ''}`, - description: `--force${useForceWithLease ? '-with-lease' : ''}`, - detail: `Will force push${useForceWithLease ? ' (with lease)' : ''} ${ - state.repos.length - } repositories`, - }), - ]); + step = this.createConfirmStep( + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), + [ + FlagsQuickPickItem.create(state.flags, [], { + label: this.title, + detail: + state.repos.length === 1 + ? localize('quickPick.push.detail.willPushOneRepository', 'Will push 1 repository') + : localize( + 'quickPick.push.detail.willPushRepositories', + 'Will push {0} repositories', + state.repos.length, + ), + }), + FlagsQuickPickItem.create(state.flags, ['--force'], { + label: useForceWithLease + ? localize('quickPick.force.label.withLease', 'Force {0} (with lease)', this.title) + : localize('quickPick.force.label', 'Force {0}', this.title), + description: `--force${useForceWithLease ? '-with-lease' : ''}`, + detail: useForceWithLease + ? state.repos.length === 1 + ? localize( + 'quickPick.force.detail.WillForcePushWithLeaseOneRepository', + 'Will force push (with lease) 1 repository', + ) + : localize( + 'quickPick.force.detail.WillForcePushWithLeaseRepositories', + 'Will force push (with lease) {0} repositories', + state.repos.length, + ) + : state.repos.length === 1 + ? localize( + 'quickPick.force.detail.WillForcePushOneRepository', + 'Will force push 1 repository', + ) + : localize( + 'quickPick.force.detail.WillForcePushRepositories', + 'Will force push {0} repositories', + state.repos.length, + ), + }), + ], + ); } else { const [repo] = state.repos; @@ -178,11 +210,11 @@ export class PushGitCommand extends QuickCommand { if (GitReference.isBranch(state.reference)) { if (state.reference.remote) { step = this.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), [], DirectiveQuickPickItem.create(Directive.Cancel, true, { - label: `Cancel ${this.title}`, - detail: 'Cannot push remote branch', + label: localize('cancel', 'Cancel {0}', this.title), + detail: localize('quickPick.cannotPushRemote.detail', 'Cannot push remote branch'), }), ); } else { @@ -195,8 +227,18 @@ export class PushGitCommand extends QuickCommand { state.flags, ['--set-upstream', remote.name, branch.name], { - label: `Publish ${branch.name} to ${remote.name}`, - detail: `Will publish ${GitReference.toString(branch)} to ${remote.name}`, + label: localize( + 'quickPick.publish.label.publishBranchToRemote', + 'Publish {0} to {1}', + branch.name, + remote.name, + ), + detail: localize( + 'quickPick.publish.detail', + 'Will publish {0} to {1}', + GitReference.toString(branch), + remote.name, + ), }, ), ); @@ -204,70 +246,164 @@ export class PushGitCommand extends QuickCommand { if (items.length) { step = this.createConfirmStep( - appendReposToTitle('Confirm Publish', state, context), + appendReposToTitle(localize('confirmPublish', 'Confirm Publish'), state, context), items, undefined, - { placeholder: 'Confirm Publish' }, + { placeholder: localize('confirmPublish', 'Confirm Publish') }, ); } else { step = this.createConfirmStep( - appendReposToTitle('Confirm Publish', state, context), + appendReposToTitle(localize('confirmPublish', 'Confirm Publish'), state, context), [], DirectiveQuickPickItem.create(Directive.Cancel, true, { - label: 'Cancel Publish', - detail: 'Cannot publish; No remotes found', + label: localize('cancelPublish', 'Cancel Publish'), + detail: localize('cannotPublishNoRemotesFound', 'Cannot publish; No remotes found'), }), - { placeholder: 'Confirm Publish' }, + { placeholder: localize('confirmPublish', 'Confirm Publish') }, ); } } else if (branch != null && branch?.state.behind > 0) { const currentBranch = await repo.getBranch(); step = this.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), branch.id === currentBranch?.id ? [ FlagsQuickPickItem.create(state.flags, ['--force'], { - label: `Force ${this.title}${useForceWithLease ? ' (with lease)' : ''}`, + label: useForceWithLease + ? localize( + 'quickPick.force.label.withLease', + 'Force {0} (with lease)', + this.title, + ) + : localize('quickPick.force.label', 'Force {0}', this.title), description: `--force${useForceWithLease ? '-with-lease' : ''}`, - detail: `Will force push${useForceWithLease ? ' (with lease)' : ''} ${ - branch?.state.ahead ? ` ${pluralize('commit', branch.state.ahead)}` : '' - }${branch.getRemoteName() ? ` to ${branch.getRemoteName()}` : ''}${ - branch != null && branch.state.behind > 0 - ? `, overwriting ${pluralize('commit', branch.state.behind)}${ - branch?.getRemoteName() - ? ` on ${branch.getRemoteName()}` - : '' - }` - : '' - }`, + detail: `${ + useForceWithLease + ? branch?.state.ahead === 1 + ? branch?.getRemoteName() + ? localize( + 'quickPick.force.detail.willForcePushWithLeaseOneCommitToRemote', + 'Will force push (with lease) 1 commit to {0}', + branch?.getRemoteName(), + ) + : localize( + 'quickPick.force.detail.willForcePushWithLeaseOneCommit', + 'Will force push (with lease) 1 commit', + ) + : branch?.getRemoteName() + ? localize( + 'quickPick.force.detail.willForcePushWithLeaseCommitsToRemote', + 'Will force push (with lease) {0} commits to {1}', + branch.state.ahead, + branch.getRemoteName(), + ) + : localize( + 'quickPick.force.detail.willForcePushWithLeaseCommits', + 'Will force push (with lease) {0} commits', + branch.state.ahead, + ) + : branch?.state.ahead === 1 + ? branch?.getRemoteName() + ? localize( + 'quickPick.force.detail.willForcePushOneCommitToRemote', + 'Will force push 1 commit to {0}', + branch.getRemoteName(), + ) + : localize( + 'quickPick.force.detail.willForcePushOneCommit', + 'Will force push 1 commit', + ) + : branch?.getRemoteName() + ? localize( + 'quickPick.force.detail.willForcePushCommitsToRemote', + 'Will force push {0} commits to {1}', + branch.state.ahead, + branch.getRemoteName(), + ) + : localize( + 'quickPick.force.detail.willForcePushCommits', + 'Will force push {0} commits', + branch.state.ahead, + ) + } + ${ + branch != null && branch.state.behind > 0 + ? `, ${ + branch?.state.behind === 1 + ? branch?.getRemoteName() + ? localize( + 'quickPick.force.detail.overwritingOneCommitOnRemote', + 'overwiring 1 commit on {0}', + branch.getRemoteName(), + ) + : localize( + 'quickPick.force.detail.overwritingOneCommit', + 'overwiring 1 commit', + ) + : branch?.getRemoteName() + ? localize( + 'quickPick.force.detail.overwritingCommitsOnRemote', + 'overwiring {0} commits on {1}', + branch.state.behind, + branch.getRemoteName(), + ) + : localize( + 'quickPick.force.detail.overwritingCommits', + 'overwiring {0} commits', + branch.state.behind, + ) + }` + : '' + }`, }), ] : [], DirectiveQuickPickItem.create(Directive.Cancel, true, { - label: `Cancel ${this.title}`, - detail: `Cannot push; ${GitReference.toString( - branch, - )} is behind ${branch.getRemoteName()} by ${pluralize('commit', branch.state.behind)}`, + label: localize('cancel', 'Cancel {0}', this.title), + detail: + branch.state.behind === 1 + ? localize( + 'cannotPushBranchIsBehindByOneCommit', + 'Cannot push; {0} is behind by 1 commit', + GitReference.toString(branch), + ) + : localize( + 'cannotPushBranchIsBehindByCommits', + 'Cannot push; {0} is behind by {1} commits', + GitReference.toString(branch), + branch.state.behind, + ), }), ); } else if (branch != null && branch?.state.ahead > 0) { step = this.createConfirmStep(appendReposToTitle(`Confirm ${context.title}`, state, context), [ FlagsQuickPickItem.create(state.flags, [branch.getRemoteName()!], { label: this.title, - detail: `Will push ${pluralize( - 'commit', - branch.state.ahead, - )} from ${GitReference.toString(branch)} to ${branch.getRemoteName()}`, + detail: + branch.state.ahead === 1 + ? localize( + 'quickPick.push.detail.willPushOneCommitFromBranchToRemote', + 'Will push 1 commit from {0} to {1}', + GitReference.toString(branch), + branch.getRemoteName(), + ) + : localize( + 'quickPick.push.detail.willPushCommitsFromBranchToRemote', + 'Will push {0} commits from {1} to {2}', + branch.state.ahead, + GitReference.toString(branch), + branch.getRemoteName(), + ), }), ]); } else { step = this.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), [], DirectiveQuickPickItem.create(Directive.Cancel, true, { - label: `Cancel ${this.title}`, - detail: 'No commits found to push', + label: localize('cancel', 'Cancel {0}', this.title), + detail: localize('noCommitsFoundToPush', 'No commits found to push'), }), ); } @@ -293,8 +429,18 @@ export class PushGitCommand extends QuickCommand { state.flags, ['--set-upstream', remote.name, status.branch], { - label: `Publish ${branch.name} to ${remote.name}`, - detail: `Will publish ${GitReference.toString(branch)} to ${remote.name}`, + label: localize( + 'quickPick.publish.label', + 'Publish {0} to {1}', + branch.name, + remote.name, + ), + detail: localize( + 'quickPick.publish.detail', + 'Will publish {0} to {1}', + GitReference.toString(branch), + remote.name, + ), }, ), ); @@ -303,28 +449,32 @@ export class PushGitCommand extends QuickCommand { if (items.length) { step = this.createConfirmStep( - appendReposToTitle('Confirm Publish', state, context), + appendReposToTitle(localize('confirmPublish', 'Confirm Publish'), state, context), items, undefined, - { placeholder: 'Confirm Publish' }, + { placeholder: localize('confirmPublish', 'Confirm Publish') }, ); } else if (status.upstream == null) { step = this.createConfirmStep( - appendReposToTitle('Confirm Publish', state, context), + appendReposToTitle(localize('confirmPublish', 'Confirm Publish'), state, context), [], DirectiveQuickPickItem.create(Directive.Cancel, true, { - label: 'Cancel Publish', - detail: 'Cannot publish; No remotes found', + label: localize('cancelPublish', 'Cancel Publish'), + detail: localize('cannotPublishNoRemotesFound', 'Cannot publish; No remotes found'), }), - { placeholder: 'Confirm Publish' }, + { placeholder: localize('confirmPublish', 'Confirm Publish') }, ); } else { step = this.createConfirmStep( - appendReposToTitle('Confirm Push', state, context), + appendReposToTitle(localize('confirmPush', 'Confirm Push'), state, context), [], DirectiveQuickPickItem.create(Directive.Cancel, true, { - label: `Cancel ${this.title}`, - detail: `Cannot push; No commits ahead of ${GitBranch.getRemote(status.upstream)}`, + label: localize('cancel', 'Cancel {0}', this.title), + detail: localize( + 'cannotPushNoCommitsAheadOfRemote', + 'Cannot push; No commits ahead of {0}', + GitBranch.getRemote(status.upstream), + ), }), ); } @@ -333,42 +483,100 @@ export class PushGitCommand extends QuickCommand { const lastFetched = await repo.getLastFetched(); if (lastFetched !== 0) { - lastFetchedOn = `${pad(GlyphChars.Dot, 2, 2)}Last fetched ${fromNow(new Date(lastFetched))}`; + lastFetchedOn = `${pad(GlyphChars.Dot, 2, 2)}${localize( + 'lastFetchedTime', + 'Last fetched {0}', + fromNow(new Date(lastFetched)), + )}`; } let pushDetails; if (state.reference != null) { pushDetails = `${ status?.state.ahead - ? ` commits up to and including ${GitReference.toString(state.reference, { - label: false, - })}` + ? ` ${localize( + 'pushDetails.commitsUpToAndIncludingRef', + 'commits up to and including {0}', + GitReference.toString(state.reference, { label: false }), + )}` + : '' + }${ + status?.upstream + ? ` ${localize('pushDetails.toRemote', 'to {0}', GitBranch.getRemote(status.upstream))}` : '' - }${status?.upstream ? ` to ${GitBranch.getRemote(status.upstream)}` : ''}`; - } else { - pushDetails = `${status?.state.ahead ? ` ${pluralize('commit', status.state.ahead)}` : ''}${ - status?.upstream ? ` to ${GitBranch.getRemote(status.upstream)}` : '' }`; + } else { + pushDetails = status?.state.ahead + ? status.state.ahead === 1 + ? status?.upstream + ? localize('pushDetails.oneCommitToRemote', '1 commit to {0}', status.upstream) + : localize('pushDetails.oneCommitToRemote', '1 commit') + : status?.upstream + ? localize( + 'pushDetails.commitsToRemote', + '{0} commits to {1}', + status.state.ahead, + status.upstream, + ) + : localize('pushDetails.commitsToRemote', '{0} commits', status.state.ahead) + : ''; } step = this.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context, lastFetchedOn), + appendReposToTitle( + localize('confirm', 'Confirm {0}', context.title), + state, + context, + lastFetchedOn, + ), [ ...(status?.state.behind ? [] : [ FlagsQuickPickItem.create(state.flags, [], { label: this.title, - detail: `Will push${pushDetails}`, + detail: `${localize( + 'quickpick.push.detail.willPush', + 'Will push', + )}${pushDetails}`, }), ]), FlagsQuickPickItem.create(state.flags, ['--force'], { label: `Force ${this.title}${useForceWithLease ? ' (with lease)' : ''}`, description: `--force${useForceWithLease ? '-with-lease' : ''}`, - detail: `Will force push${useForceWithLease ? ' (with lease)' : ''} ${pushDetails}${ + detail: `${ + useForceWithLease + ? localize( + 'quickpick.push.detail.willForcePushWithLease', + 'Will force push (with lease)', + ) + : localize('quickpick.push.detail.willForcePush', 'Will force push') + }${pushDetails}${ status != null && status.state.behind > 0 - ? `, overwriting ${pluralize('commit', status.state.behind)}${ - status?.upstream ? ` on ${GitBranch.getRemote(status.upstream)}` : '' + ? `, ${ + status.state.behind === 1 + ? status?.upstream + ? localize( + 'quickPick.force.detail.overwritingOneCommitOnRemote', + 'overwiring 1 commit on {0}', + GitBranch.getRemote(status.upstream), + ) + : localize( + 'quickPick.force.detail.overwritingOneCommit', + 'overwiring 1 commit', + ) + : status?.upstream + ? localize( + 'quickPick.force.detail.overwritingCommitsOnRemote', + 'overwiring {0} commits on {1}', + status.state.behind, + GitBranch.getRemote(status.upstream), + ) + : localize( + 'quickPick.force.detail.overwritingCommits', + 'overwiring {0} commits', + status.state.behind, + ) }` : '' }`, @@ -376,10 +584,34 @@ export class PushGitCommand extends QuickCommand { ], status?.state.behind ? DirectiveQuickPickItem.create(Directive.Cancel, true, { - label: `Cancel ${this.title}`, - detail: `Cannot push; ${GitReference.toString(branch)} is behind${ - status?.upstream ? ` ${GitBranch.getRemote(status.upstream)}` : '' - } by ${pluralize('commit', status.state.behind)}`, + label: localize('cancel', 'Cancel {0}', this.title), + detail: status?.upstream + ? status?.state.behind === 1 + ? localize( + 'quickPick.cannotPushBranchIsBehindRemoteByOneCommit', + 'Cannot push; {0} is behind {1} by 1 commit', + GitReference.toString(branch), + GitBranch.getRemote(status.upstream), + ) + : localize( + 'quickPick.cannotPushBranchIsBehindRemoteByCommits', + 'Cannot push; {0} is behind {1} by {2} commits', + GitReference.toString(branch), + GitBranch.getRemote(status.upstream), + status.state.behind, + ) + : status?.state.behind === 1 + ? localize( + 'quickPick.cannotPushBranchIsBehindByOneCommit', + 'Cannot push; {0} is behind by 1 commit', + GitReference.toString(branch), + ) + : localize( + 'quickPick.cannotPushBranchIsBehindByCommits', + 'Cannot push; {0} is behind by {1} commits', + GitReference.toString(branch), + status.state.behind, + ), }) : undefined, ); @@ -388,9 +620,11 @@ export class PushGitCommand extends QuickCommand { step.onDidClickButton = async (quickpick, button) => { if (button !== QuickCommandButtons.Fetch || quickpick.busy) return false; - quickpick.title = `Confirm ${context.title}${pad(GlyphChars.Dot, 2, 2)}Fetching${ - GlyphChars.Ellipsis - }`; + quickpick.title = `${localize('confirm', 'Confirm {0}', context.title)}${pad( + GlyphChars.Dot, + 2, + 2, + )}${localize('fetching', 'Fetching')}${GlyphChars.Ellipsis}`; quickpick.busy = true; quickpick.enabled = false; diff --git a/src/commands/git/rebase.ts b/src/commands/git/rebase.ts index a38987d172208..6c97f872899e1 100644 --- a/src/commands/git/rebase.ts +++ b/src/commands/git/rebase.ts @@ -1,9 +1,9 @@ import { env } from 'vscode'; +import * as nls from 'vscode-nls'; import { Container } from '../../container'; import { GitBranch, GitLog, GitReference, GitRevision, Repository } from '../../git/models'; import { Directive, DirectiveQuickPickItem } from '../../quickpicks/items/directive'; import { FlagsQuickPickItem } from '../../quickpicks/items/flags'; -import { pluralize } from '../../system/string'; import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { appendReposToTitle, @@ -21,6 +21,7 @@ import { StepState, } from '../quickCommand'; +const localize = nls.loadMessageBundle(); interface Context { repos: Repository[]; associatedView: ViewsWithRepositoryFolders; @@ -50,9 +51,11 @@ type RebaseStepState = ExcludeSome, 'repo' export class RebaseGitCommand extends QuickCommand { constructor(container: Container, args?: RebaseGitCommandArgs) { - super(container, 'rebase', 'rebase', 'Rebase', { - description: + super(container, 'rebase', localize('label', 'rebase'), localize('title', 'Rebase'), { + description: localize( + 'description', 'integrates changes from a specified branch into the current branch, by changing the base of the branch and reapplying the commits on top', + ), }); let counter = 0; @@ -158,7 +161,16 @@ export class RebaseGitCommand extends QuickCommand { }); const result: StepResult = yield* pickBranchOrTagStep(state as RebaseStepState, context, { - placeholder: context => `Choose a branch${context.showTags ? ' or tag' : ''} to rebase`, + placeholder: context => + context.showTags + ? localize( + 'pickBranchOrTagStep.placeholder.chooseBranchToRebase', + 'Choose a branch to rebase', + ) + : localize( + 'pickBranchOrTagStep.placeholder.chooseBranchOrTagToRebase', + 'Choose a branch or tag to rebase', + ), picked: context.selectedBranchOrTag?.ref, value: context.selectedBranchOrTag == null ? state.reference?.ref : undefined, additionalButtons: [pickCommitToggle], @@ -199,12 +211,20 @@ export class RebaseGitCommand extends QuickCommand { onDidLoadMore: log => context.cache.set(ref, Promise.resolve(log)), placeholder: (context, log) => log == null - ? `No commits found on ${GitReference.toString(context.selectedBranchOrTag, { - icon: false, - })}` - : `Choose a commit to rebase ${GitReference.toString(context.destination, { - icon: false, - })} onto`, + ? localize( + 'pickCommitStep.placeholder.noCommitsFoundOnBranchOrTag', + 'No commits found on {0}', + GitReference.toString(context.selectedBranchOrTag, { + icon: false, + }), + ) + : localize( + 'pickCommitStep.placeholder.chooseCommitToRebaseBranchOnto', + 'Choose a commit to rebase {0} onto', + GitReference.toString(context.destination, { + icon: false, + }), + ), picked: state.reference?.ref, }); if (result === StepResult.Break) continue; @@ -234,13 +254,16 @@ export class RebaseGitCommand extends QuickCommand { const count = aheadBehind != null ? aheadBehind.ahead + aheadBehind.behind : 0; if (count === 0) { const step: QuickPickStep = this.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), [], DirectiveQuickPickItem.create(Directive.Cancel, true, { - label: `Cancel ${this.title}`, - detail: `${GitReference.toString(context.destination, { - capitalize: true, - })} is up to date with ${GitReference.toString(state.reference)}`, + label: localize('cancel', 'Cancel {0}', this.title), + detail: localize( + 'confirmStep.detail.branchIsUpToDateWithRef', + '{0} is up to date with {1}', + GitReference.toString(context.destination, { capitalize: true }), + GitReference.toString(state.reference), + ), }), ); const selection: StepSelection = yield step; @@ -249,21 +272,44 @@ export class RebaseGitCommand extends QuickCommand { } const step: QuickPickStep> = this.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), [ FlagsQuickPickItem.create(state.flags, [], { label: this.title, - detail: `Will update ${GitReference.toString(context.destination)} by applying ${pluralize( - 'commit', - count, - )} on top of ${GitReference.toString(state.reference)}`, + detail: + count === 1 + ? localize( + 'confirmStep.quickPick.rebase.detail.willUpdateBranchByApplyingOneCommitOnTopOfRef', + 'Will update {0} by applying 1 commit on top of {1}', + GitReference.toString(context.destination), + GitReference.toString(state.reference), + ) + : localize( + 'confirmStep.quickPick.rebase.detail.willUpdateBranchByApplyingCommitsOnTopOfRef', + 'Will update {0} by applying {1} commits on top of {2}', + GitReference.toString(context.destination), + count, + GitReference.toString(state.reference), + ), }), FlagsQuickPickItem.create(state.flags, ['--interactive'], { - label: `Interactive ${this.title}`, + label: localize('confirmStep.quickPick.interactive.label', 'Interactive {0}', this.title), description: '--interactive', - detail: `Will interactively update ${GitReference.toString( - context.destination, - )} by applying ${pluralize('commit', count)} on top of ${GitReference.toString(state.reference)}`, + detail: + count === 1 + ? localize( + 'confirmStep.quickPick.interactive.detail.willUpdateBranchByApplyingOneCommitOnTopOfRef', + 'Will interactively update {0} by applying 1 commit on top of {1}', + GitReference.toString(context.destination), + GitReference.toString(state.reference), + ) + : localize( + 'confirmStep.quickPick.interactive.detail.willUpdateBranchByApplyingCommitsOnTopOfRef', + 'Will interactively update {0} by applying {1} commits on top of {2}', + GitReference.toString(context.destination), + count, + GitReference.toString(state.reference), + ), }), ], ); diff --git a/src/commands/git/reset.ts b/src/commands/git/reset.ts index 208b28f34858f..0c3bd7e3a8b98 100644 --- a/src/commands/git/reset.ts +++ b/src/commands/git/reset.ts @@ -1,3 +1,4 @@ +import * as nls from 'vscode-nls'; import { Container } from '../../container'; import { GitBranch, GitLog, GitReference, GitRevisionReference, Repository } from '../../git/models'; import { FlagsQuickPickItem } from '../../quickpicks/items/flags'; @@ -16,6 +17,7 @@ import { StepState, } from '../quickCommand'; +const localize = nls.loadMessageBundle(); interface Context { repos: Repository[]; associatedView: ViewsWithRepositoryFolders; @@ -42,7 +44,9 @@ type ResetStepState = ExcludeSome, 'repo', export class ResetGitCommand extends QuickCommand { constructor(container: Container, args?: ResetGitCommandArgs) { - super(container, 'reset', 'reset', 'Reset', { description: 'resets the current branch to a specified commit' }); + super(container, 'reset', localize('label', 'reset'), localize('title', 'Reset'), { + description: localize('description', 'resets the current branch to a specified commit'), + }); let counter = 0; if (args?.state?.repo != null) { @@ -129,8 +133,16 @@ export class ResetGitCommand extends QuickCommand { onDidLoadMore: log => context.cache.set(ref, Promise.resolve(log)), placeholder: (context, log) => log == null - ? `${context.destination.name} has no commits` - : `Choose a commit to reset ${context.destination.name} to`, + ? localize( + 'pickCommitStep.placeholder.branchHasNoCommits', + '{0} has no commits', + context.destination.name, + ) + : localize( + 'pickCommitStep.placeholder.chooseCommitToResetBranchTo', + 'Choose a commit to reset {0} to', + context.destination.name, + ), picked: state.reference?.ref, }); if (result === StepResult.Break) { @@ -161,27 +173,36 @@ export class ResetGitCommand extends QuickCommand { private *confirmStep(state: ResetStepState, context: Context): StepResultGenerator { const step: QuickPickStep> = this.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), [ FlagsQuickPickItem.create(state.flags, [], { label: this.title, - detail: `Will reset (leaves changes in the working tree) ${GitReference.toString( - context.destination, - )} to ${GitReference.toString(state.reference)}`, + detail: localize( + 'confirmStep.quickPick.reset.detail', + 'Will reset (leaves changes in the working tree) {0} to {1}', + GitReference.toString(context.destination), + GitReference.toString(state.reference), + ), }), FlagsQuickPickItem.create(state.flags, ['--soft'], { - label: `Soft ${this.title}`, + label: localize('confirmStep.quickPick.soft.label', 'Soft {0}', this.title), description: '--soft', - detail: `Will soft reset (leaves changes in the index and working tree) ${GitReference.toString( - context.destination, - )} to ${GitReference.toString(state.reference)}`, + detail: localize( + 'confirmStep.quickPick.soft.detail', + 'Will soft reset (leaves changes in the index and working tree) {0} to {1}', + GitReference.toString(context.destination), + GitReference.toString(state.reference), + ), }), FlagsQuickPickItem.create(state.flags, ['--hard'], { - label: `Hard ${this.title}`, + label: localize('confirmStep.quikcPick.hard.label', 'Hard {0}', this.title), description: '--hard', - detail: `Will hard reset (discards all changes) ${GitReference.toString( - context.destination, - )} to ${GitReference.toString(state.reference)}`, + detail: localize( + 'confirmStep.quickPick.hard.detail', + 'Will hard reset (discrards all changes) {0} to {1}', + GitReference.toString(context.destination), + GitReference.toString(state.reference), + ), }), ], ); diff --git a/src/commands/git/revert.ts b/src/commands/git/revert.ts index e03cc5cbf46fa..cb0c1f37b23f6 100644 --- a/src/commands/git/revert.ts +++ b/src/commands/git/revert.ts @@ -1,3 +1,4 @@ +import * as nls from 'vscode-nls'; import { Container } from '../../container'; import { GitBranch, GitLog, GitReference, GitRevisionReference, Repository } from '../../git/models'; import { FlagsQuickPickItem } from '../../quickpicks/items/flags'; @@ -16,6 +17,7 @@ import { StepState, } from '../quickCommand'; +const localize = nls.loadMessageBundle(); interface Context { repos: Repository[]; associatedView: ViewsWithRepositoryFolders; @@ -41,8 +43,11 @@ type RevertStepState = ExcludeSome, 'repo' export class RevertGitCommand extends QuickCommand { constructor(container: Container, args?: RevertGitCommandArgs) { - super(container, 'revert', 'revert', 'Revert', { - description: 'undoes the changes of specified commits, by creating new commits with inverted changes', + super(container, 'revert', localize('label', 'revert'), localize('title', 'Revert'), { + description: localize( + 'description', + 'undoes the changes of specified commits, by creating new commits with inverted changes', + ), }); let counter = 0; @@ -135,7 +140,16 @@ export class RevertGitCommand extends QuickCommand { log: await log, onDidLoadMore: log => context.cache.set(ref, Promise.resolve(log)), placeholder: (context, log) => - log == null ? `${context.destination.name} has no commits` : 'Choose commits to revert', + log == null + ? localize( + 'pickCommitsStep.placeholder.branchHasNoCommits', + '{0} has no commits', + context.destination.name, + ) + : localize( + 'pickCommitsStep.placeholder.chooseCommitsToRevert', + 'Choose commits to revert', + ), picked: state.references?.map(r => r.ref), }, ); @@ -165,17 +179,25 @@ export class RevertGitCommand extends QuickCommand { private *confirmStep(state: RevertStepState, context: Context): StepResultGenerator { const step: QuickPickStep> = this.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), [ FlagsQuickPickItem.create(state.flags, ['--no-edit'], { label: this.title, description: '--no-edit', - detail: `Will revert ${GitReference.toString(state.references)}`, + detail: localize( + 'confirmStep.quickPick.noEdit.detail', + 'Will revert {0}', + GitReference.toString(state.references), + ), }), FlagsQuickPickItem.create(state.flags, ['--edit'], { - label: `${this.title} & Edit`, + label: localize('confirmStep.quickPick.edit.label', '{0} & Edit', this.title), description: '--edit', - detail: `Will revert and edit ${GitReference.toString(state.references)}`, + detail: localize( + 'confirmStep.quickPick.edit.detail', + 'Will revert and edit {0}', + GitReference.toString(state.references), + ), }), ], ); diff --git a/src/commands/git/search.ts b/src/commands/git/search.ts index 25ab36a117998..20f9a4ca67216 100644 --- a/src/commands/git/search.ts +++ b/src/commands/git/search.ts @@ -1,10 +1,10 @@ +import * as nls from 'vscode-nls'; import { ContextKeys, GlyphChars } from '../../constants'; import { Container } from '../../container'; import { getContext } from '../../context'; import { GitCommit, GitLog, Repository } from '../../git/models'; import { searchOperators, SearchOperators, SearchPattern } from '../../git/search'; import { ActionQuickPickItem, QuickPickItemOfT } from '../../quickpicks/items/common'; -import { pluralize } from '../../system/string'; import { SearchResultsNode } from '../../views/nodes'; import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { getSteps } from '../gitCommands.utils'; @@ -22,6 +22,7 @@ import { StepState, } from '../quickCommand'; +const localize = nls.loadMessageBundle(); interface Context { repos: Repository[]; associatedView: ViewsWithRepositoryFolders; @@ -44,25 +45,25 @@ export interface SearchGitCommandArgs { } const searchOperatorToTitleMap = new Map([ - ['', 'Search by Message'], - ['=:', 'Search by Message'], - ['message:', 'Search by Message'], - ['@:', 'Search by Author'], - ['author:', 'Search by Author'], - ['#:', 'Search by Commit SHA'], - ['commit:', 'Search by Commit SHA'], - ['?:', 'Search by File'], - ['file:', 'Search by File'], - ['~:', 'Search by Changes'], - ['change:', 'Search by Changes'], + ['', localize('pickSearchOperatorStep.title.searchByMessage', 'Search by Message')], + ['=:', localize('pickSearchOperatorStep.title.searchByMessage', 'Search by Message')], + ['message:', localize('pickSearchOperatorStep.title.searchByMessage', 'Search by Message')], + ['@:', localize('pickSearchOperatorStep.title.searchByAuthor', 'Search by Author')], + ['author:', localize('pickSearchOperatorStep.title.searchByAuthor', 'Search by Author')], + ['#:', localize('pickSearchOperatorStep.title.searchByComitSha', 'Search by Commit SHA')], + ['commit:', localize('pickSearchOperatorStep.title.searchByComitSha', 'Search by Commit SHA')], + ['?:', localize('pickSearchOperatorStep.title.searchByFile', 'Search by File')], + ['file:', localize('pickSearchOperatorStep.title.searchByFile', 'Search by File')], + ['~:', localize('pickSearchOperatorStep.title.searchByChanges', 'Search by Changes')], + ['change:', localize('pickSearchOperatorStep.title.searchByChanges', 'Search by Changes')], ]); type SearchStepState = ExcludeSome, 'repo', string>; export class SearchGitCommand extends QuickCommand { constructor(container: Container, args?: SearchGitCommandArgs) { - super(container, 'search', 'search', 'Commit Search', { - description: 'aka grep, searches for commits', + super(container, 'search', localize('label', 'search'), localize('title', 'Commit Search'), { + description: localize('description', 'aka grep, searches for commits'), }); let counter = 0; @@ -176,7 +177,7 @@ export class SearchGitCommand extends QuickCommand { state.repo.path, search, { - label: { label: `for ${state.pattern}` }, + label: { label: localize('label.forPattern', 'for {0}', state.pattern) }, }, context.resultsPromise, state.showResultsInSideBar instanceof SearchResultsNode ? state.showResultsInSideBar : undefined, @@ -193,19 +194,36 @@ export class SearchGitCommand extends QuickCommand { onDidLoadMore: log => (context.resultsPromise = Promise.resolve(log)), placeholder: (context, log) => log == null - ? `No results for ${state.pattern}` - : `${pluralize('result', log.count, { - format: c => (log.hasMore ? `${c}+` : undefined), - })} for ${state.pattern}`, + ? localize( + 'pickCommitStep.placeholder.noResultsForPattern', + 'No results for {0}', + state.pattern, + ) + : log.count === 1 + ? localize( + 'pickCommitStep.placeholder.resultForPattern', + '{0} result for {1}', + log.hasMore ? `${log.count}+` : log.count, + state.pattern, + ) + : localize( + 'pickCommitStep.placeholder.resultsForPattern', + '{0} results for {1}', + log.hasMore ? `${log.count}+` : log.count, + state.pattern, + ), picked: context.commit?.ref, showInSideBarCommand: new ActionQuickPickItem( - '$(link-external) Show Results in Side Bar', + `$(link-external) ${localize( + 'pickCommitStep.quickPick.showInSideBar.label', + 'Show Results in Side Bar', + )}`, () => void this.container.searchAndCompareView.search( repoPath, search, { - label: { label: `for ${state.pattern}` }, + label: { label: localize('label.forPattern', 'for {0}', state.pattern) }, reveal: { select: true, focus: false, @@ -222,7 +240,7 @@ export class SearchGitCommand extends QuickCommand { repoPath, search, { - label: { label: `for ${state.pattern}` }, + label: { label: localize('label.forPattern', 'for {0}', state.pattern) }, reveal: { select: true, focus: false, @@ -265,31 +283,40 @@ export class SearchGitCommand extends QuickCommand { const items: QuickPickItemOfT[] = [ { label: searchOperatorToTitleMap.get('')!, - description: `pattern or message: pattern or =: pattern ${GlyphChars.Dash} use quotes to search for phrases`, + description: `${localize( + 'pickSearchOperatorStep.description.patternOrMessage', + 'pattern or message: pattern or =: pattern', + )} ${GlyphChars.Dash} ${localize( + 'pickSearchOperatorStep.description.useQuotesToSearchForPhrases', + 'use quotes to search for phrases', + )}`, item: 'message:' as const, }, { label: searchOperatorToTitleMap.get('author:')!, - description: 'author: pattern or @: pattern', + description: localize('pickSearchOperatorStep.description.author', 'author: pattern or @: pattern'), item: 'author:' as const, }, { label: searchOperatorToTitleMap.get('commit:')!, - description: 'commit: sha or #: sha', + description: localize('pickSearchOperatorStep.description.commit', 'commit: sha or #: sha'), item: 'commit:' as const, }, context.hasVirtualFolders ? undefined : { label: searchOperatorToTitleMap.get('file:')!, - description: 'file: glob or ?: glob', + description: localize('pickSearchOperatorStep.description.file', 'file: glob or ?: glob'), item: 'file:' as const, }, context.hasVirtualFolders ? undefined : { label: searchOperatorToTitleMap.get('change:')!, - description: 'change: pattern or ~: pattern', + description: localize( + 'pickSearchOperatorStep.description.change', + 'change: pattern or ~: pattern', + ), item: 'change:' as const, }, ].filter((i?: T): i is T => i != null); @@ -300,7 +327,7 @@ export class SearchGitCommand extends QuickCommand { const step = QuickCommand.createPickStep>({ title: appendReposToTitle(context.title, state, context), - placeholder: 'e.g. "Updates dependencies" author:eamodio', + placeholder: localize('pickStep.quickPick.placeholder', 'e.g. "Updates dependencies" author:eamodio'), matchOnDescription: true, matchOnDetail: true, additionalButtons: [matchCaseButton, matchAllButton, matchRegexButton], @@ -343,7 +370,11 @@ export class SearchGitCommand extends QuickCommand { quickpick.title = appendReposToTitle( operations.size === 0 || operations.size > 1 ? context.title - : `Commit ${searchOperatorToTitleMap.get(operations.keys().next().value)!}`, + : localize( + 'quickPick.title.commitTitle', + 'Commit {0}', + searchOperatorToTitleMap.get(operations.keys().next().value), + ), state, context, ); @@ -357,7 +388,7 @@ export class SearchGitCommand extends QuickCommand { quickpick.items = [ { - label: 'Search for', + label: localize('quickPick.label.searchFor', 'Search for'), description: quickpick.value, item: quickpick.value as SearchOperators, }, diff --git a/src/commands/git/show.ts b/src/commands/git/show.ts index 4518ca7b22a06..5460502df219a 100644 --- a/src/commands/git/show.ts +++ b/src/commands/git/show.ts @@ -1,3 +1,4 @@ +import * as nls from 'vscode-nls'; import { Container } from '../../container'; import { GitCommit, GitRevisionReference, GitStashCommit, Repository } from '../../git/models'; import { CommitFilesQuickPickItem } from '../../quickpicks/items/commits'; @@ -16,6 +17,7 @@ import { StepResult, } from '../quickCommand'; +const localize = nls.loadMessageBundle(); interface Context { repos: Repository[]; associatedView: ViewsWithRepositoryFolders; @@ -62,8 +64,8 @@ function assertsStateStepFileName(state: CommitStepState): asserts state is File export class ShowGitCommand extends QuickCommand { constructor(container: Container, args?: ShowGitCommandArgs) { - super(container, 'show', 'show', 'Show', { - description: 'shows information about a git reference', + super(container, 'show', localize('label', 'show'), localize('title', 'Show'), { + description: localize('description', 'shows information about a git reference'), }); let counter = 0; @@ -154,7 +156,7 @@ export class ShowGitCommand extends QuickCommand { limit: undefined, hasMore: false, }, - placeholder: 'Enter a reference or commit SHA', + placeholder: localize('pickCommitStep.placeholder', 'Enter a reference or commit SHA'), picked: state.reference?.ref, }); if (result === StepResult.Break) { diff --git a/src/commands/git/stash.ts b/src/commands/git/stash.ts index 3c6a67a002bd4..1ca95ccf721e2 100644 --- a/src/commands/git/stash.ts +++ b/src/commands/git/stash.ts @@ -1,4 +1,5 @@ import { QuickInputButtons, QuickPickItem, Uri, window } from 'vscode'; +import * as nls from 'vscode-nls'; import { ContextKeys, GlyphChars } from '../../constants'; import { Container } from '../../container'; import { getContext } from '../../context'; @@ -29,6 +30,7 @@ import { StepState, } from '../quickCommand'; +const localize = nls.loadMessageBundle(); interface Context { repos: Repository[]; associatedView: ViewsWithRepositoryFolders; @@ -79,11 +81,11 @@ type PopStepState = StashStepState = StashStepState>; const subcommandToTitleMap = new Map([ - ['apply', 'Apply'], - ['drop', 'Drop'], - ['list', 'List'], - ['pop', 'Pop'], - ['push', 'Push'], + ['apply', localize('subcommand.apply.title', 'Apply')], + ['drop', localize('subcommand.drop.title', 'Drop')], + ['list', localize('subcommand.list.title', 'List')], + ['pop', localize('subcommand.pop.title', 'Pop')], + ['push', localize('subcommand.push.title', 'Push')], ]); function getTitle(title: string, subcommand: State['subcommand'] | undefined) { return subcommand == null ? title : `${subcommandToTitleMap.get(subcommand)} ${title}`; @@ -99,8 +101,8 @@ export class StashGitCommand extends QuickCommand { private subcommand: State['subcommand'] | undefined; constructor(container: Container, args?: StashGitCommandArgs) { - super(container, 'stash', 'stash', 'Stash', { - description: 'shelves (stashes) local changes to be reapplied later', + super(container, 'stash', localize('label', 'stash'), localize('title', 'Stash'), { + description: localize('description', 'shelves (stashes) local changes to be reapplied later'), }); let counter = 0; @@ -228,37 +230,44 @@ export class StashGitCommand extends QuickCommand { private *pickSubcommandStep(state: PartialStepState): StepResultGenerator { const step = QuickCommand.createPickStep>({ title: this.title, - placeholder: `Choose a ${this.label} command`, + placeholder: localize('pickSubcommandStep.placeholder', 'Choose a {0} command', this.label), items: [ { - label: 'apply', - description: 'integrates changes from the specified stash into the current branch', + label: localize('subcommand.apply.label', 'apply'), + description: localize( + 'subcommand.apply.description', + 'integrates changes from the specified stash into the current branch', + ), picked: state.subcommand === 'apply', item: 'apply', }, { - label: 'drop', - description: 'deletes the specified stash', + label: localize('subcommand.drop.label', 'drop'), + description: localize('subcommand.drop.description', 'deletes the specified stash'), picked: state.subcommand === 'drop', item: 'drop', }, { - label: 'list', - description: 'lists the saved stashes', + label: localize('subcommand.list.label', 'list'), + description: localize('subcommand.list.description', 'lists the saved stashes'), picked: state.subcommand === 'list', item: 'list', }, { - label: 'pop', - description: + label: localize('subcommand.pop.label', 'pop'), + description: localize( + 'subcommand.pop.description', 'integrates changes from the specified stash into the current branch and deletes the stash', + ), picked: state.subcommand === 'pop', item: 'pop', }, { - label: 'push', - description: + label: localize('subcommand.push.label', 'push'), + description: localize( + 'subcommand.push.description', 'saves your local changes to a new stash and discards them from the working tree and index', + ), picked: state.subcommand === 'push', item: 'push', }, @@ -276,8 +285,15 @@ export class StashGitCommand extends QuickCommand { stash: await this.container.git.getStash(state.repo.path), placeholder: (context, stash) => stash == null - ? `No stashes found in ${state.repo.formattedName}` - : 'Choose a stash to apply to your working tree', + ? localize( + 'applyOrPop.pickStashStep.placeholder.noStashesFoundInRepo', + 'No stashes found in {0}', + state.repo.formattedName, + ) + : localize( + 'applyOrPop.pickStashStep.placeholder.chooseStashToApplyYourWorkingTree', + 'Choose a stash to apply to your working tree', + ), picked: state.reference?.ref, }); // Always break on the first step (so we will go back) @@ -306,7 +322,10 @@ export class StashGitCommand extends QuickCommand { if (StashApplyError.is(ex, StashApplyErrorReason.WorkingChanges)) { void window.showWarningMessage( - 'Unable to apply stash. Your working tree changes would be overwritten. Please commit or stash your changes before trying again', + localize( + 'unableToApplyStashWarning.message', + 'Unable to apply stash. Your working tree changes would be overwritten. Please commit or stash your changes before trying again', + ), ); } else { void Messages.showGenericErrorMessage(ex.message); @@ -320,18 +339,22 @@ export class StashGitCommand extends QuickCommand { context: Context, ): StepResultGenerator<'apply' | 'pop'> { const step = this.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), [ { label: context.title, detail: state.subcommand === 'pop' - ? `Will delete ${GitReference.toString( - state.reference, - )} and apply the changes to the working tree` - : `Will apply the changes from ${GitReference.toString( - state.reference, - )} to the working tree`, + ? localize( + 'applyOrPopCommandConfirmStep.detail.pop', + 'Will delete {0} and apply the changes to the working tree', + GitReference.toString(state.reference), + ) + : localize( + 'applyOrPopCommandConfirmStep.detail', + 'Will apply the changes from {0} to the working tree', + GitReference.toString(state.reference), + ), item: state.subcommand, }, // Alternate confirmation (if pop then apply, and vice versa) @@ -339,18 +362,22 @@ export class StashGitCommand extends QuickCommand { label: getTitle(this.title, state.subcommand === 'pop' ? 'apply' : 'pop'), detail: state.subcommand === 'pop' - ? `Will apply the changes from ${GitReference.toString( - state.reference, - )} to the working tree` - : `Will delete ${GitReference.toString( - state.reference, - )} and apply the changes to the working tree`, + ? localize( + 'applyOrPopCommandConfirmStep.detail', + 'Will apply the changes from {0} to the working tree', + GitReference.toString(state.reference), + ) + : localize( + 'applyOrPopCommandConfirmStep.detail.pop', + 'Will delete {0} and apply the changes to the working tree', + GitReference.toString(state.reference), + ), item: state.subcommand === 'pop' ? 'apply' : 'pop', }, ], undefined, { - placeholder: `Confirm ${context.title}`, + placeholder: localize('confirm', 'Confirm {0}', context.title), additionalButtons: [QuickCommandButtons.RevealInSideBar], onDidClickButton: (quickpick, button) => { if (button === QuickCommandButtons.RevealInSideBar) { @@ -372,7 +399,16 @@ export class StashGitCommand extends QuickCommand { const result: StepResult = yield* pickStashStep(state, context, { stash: await this.container.git.getStash(state.repo.path), placeholder: (context, stash) => - stash == null ? `No stashes found in ${state.repo.formattedName}` : 'Choose a stash to delete', + stash == null + ? localize( + 'drop.pickStashStep.placeholder.noStashesFoundInRepo', + 'No stashes found in {0}', + state.repo.formattedName, + ) + : localize( + 'drop.pickStashStep.placeholder.chooseStashToDelete', + 'Choose a stash to delete', + ), picked: state.reference?.ref, }); // Always break on the first step (so we will go back) @@ -391,7 +427,7 @@ export class StashGitCommand extends QuickCommand { } catch (ex) { Logger.error(ex, context.title); - void Messages.showGenericErrorMessage('Unable to delete stash'); + void Messages.showGenericErrorMessage(localize('dropGenericError.message', 'Unable to delete stash')); return; } @@ -400,16 +436,20 @@ export class StashGitCommand extends QuickCommand { private *dropCommandConfirmStep(state: DropStepState, context: Context): StepResultGenerator { const step = this.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), [ { label: context.title, - detail: `Will delete ${GitReference.toString(state.reference)}`, + detail: localize( + 'dropCommandConfirmStep.detail', + 'Will delete {0}', + GitReference.toString(state.reference), + ), }, ], undefined, { - placeholder: `Confirm ${context.title}`, + placeholder: localize('confirm', 'Confirm {0}', context.title), additionalButtons: [QuickCommandButtons.RevealInSideBar], onDidClickButton: (quickpick, button) => { if (button === QuickCommandButtons.RevealInSideBar) { @@ -426,14 +466,20 @@ export class StashGitCommand extends QuickCommand { } private async *listCommandSteps(state: ListStepState, context: Context): StepGenerator { - context.title = 'Stashes'; + context.title = localize('listCommandSteps.title', 'Stashes'); while (this.canStepsContinue(state)) { if (state.counter < 3 || state.reference == null) { const result: StepResult = yield* pickStashStep(state, context, { stash: await this.container.git.getStash(state.repo.path), placeholder: (context, stash) => - stash == null ? `No stashes found in ${state.repo.formattedName}` : 'Choose a stash', + stash == null + ? localize( + 'list.pickStashStep.placeholder.noStashesFoundInRepo', + 'No stashes found in {0}', + state.repo.formattedName, + ) + : localize('list.pickStashStep.placeholder.chooseStash', 'Choose a stash'), picked: state.reference?.ref, }); // Always break on the first step (so we will go back) @@ -492,12 +538,14 @@ export class StashGitCommand extends QuickCommand { const msg: string = ex?.message ?? ex?.toString() ?? ''; if (msg.includes('newer version of Git')) { - void window.showErrorMessage(`Unable to stash changes. ${msg}`); + void window.showErrorMessage( + `${localize('unableToStashError.message', 'Unable to stash changes')}. ${msg}`, + ); return; } - void Messages.showGenericErrorMessage('Unable to stash changes'); + void Messages.showGenericErrorMessage(localize('stashGenericError.message', 'Unable to stash changes')); return; } @@ -517,13 +565,13 @@ export class StashGitCommand extends QuickCommand { ? `${pad(GlyphChars.Dot, 2, 2)}${ state.uris.length === 1 ? formatPath(state.uris[0], { fileOnly: true }) - : `${state.uris.length} files` + : localize('pushCommandInputMessageStep.files', '{0} files', state.uris.length) }` : undefined, ), - placeholder: 'Please provide a stash message', + placeholder: localize('pushCommandInputMessageStep.placeholder', 'Please provide a stash message'), value: state.message, - prompt: 'Enter stash message', + prompt: localize('pushCommandInputMessageStep.prompt', 'Enter stash message'), }); const value: StepSelection = yield step; @@ -539,44 +587,79 @@ export class StashGitCommand extends QuickCommand { private *pushCommandConfirmStep(state: PushStepState, context: Context): StepResultGenerator { const step: QuickPickStep> = this.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), state.uris == null || state.uris.length === 0 ? [ FlagsQuickPickItem.create(state.flags, [], { label: context.title, - detail: 'Will stash uncommitted changes', + detail: localize( + 'pushCommandConfirmStep.quickPick.stash.detail.willStashUncommittedChanges', + 'Will stash uncommitted changes', + ), }), FlagsQuickPickItem.create(state.flags, ['--include-untracked'], { - label: `${context.title} & Include Untracked`, + label: localize( + 'pushCommandConfirmStep.quickPick.includeUntracked.label', + '{0} & Include Untracked', + context.title, + ), description: '--include-untracked', - detail: 'Will stash uncommitted changes, including untracked files', + detail: localize( + 'pushCommandConfirmStep.quickPick.includeUntracked.detail', + 'Will stash uncommitted changes, including untracked files', + ), }), FlagsQuickPickItem.create(state.flags, ['--keep-index'], { - label: `${context.title} & Keep Staged`, + label: localize( + 'pushCommandConfirmStep.quickPick.keepStaged.label', + '{0} & Keep Staged', + context.title, + ), description: '--keep-index', - detail: 'Will stash uncommitted changes, but will keep staged files intact', + detail: localize( + 'pushCommandConfirmStep.quickPick.keepStaged.detail.willStashUncommittedChanges', + 'Will stash uncommitted changes, but will keep staged files intact', + ), }), ] : [ FlagsQuickPickItem.create(state.flags, [], { label: context.title, - detail: `Will stash changes from ${ + detail: state.uris.length === 1 - ? formatPath(state.uris[0], { fileOnly: true }) - : `${state.uris.length} files` - }`, + ? localize( + 'pushCommandConfirmStep.quickPick.stash.detail.willStashUncommittedChangesFromFile', + 'Will stash uncommitted changes from {0}', + formatPath(state.uris[0], { fileOnly: true }), + ) + : localize( + 'pushCommandConfirmStep.quickPick.stash.detail.willStashUncommittedChangesFromFiles', + 'Will stash uncommitted changes from {0} files', + state.uris.length, + ), }), FlagsQuickPickItem.create(state.flags, ['--keep-index'], { - label: `${context.title} & Keep Staged`, - detail: `Will stash changes from ${ + label: localize( + 'pushCommandConfirmStep.quickPick.keepStaged.label', + '{0} & Keep Staged', + context.title, + ), + detail: state.uris.length === 1 - ? formatPath(state.uris[0], { fileOnly: true }) - : `${state.uris.length} files` - }, but will keep staged files intact`, + ? localize( + 'pushCommandConfirmStep.quickPick.keepStaged.detail.willStashChangesFromFile', + 'Will stash changes from {0}, but will keep staged files intact', + formatPath(state.uris[0], { fileOnly: true }), + ) + : localize( + 'pushCommandConfirmStep.quickPick.keepStaged.detail.willStashChangesFromFiles', + 'Will stash changes from {0} files, but will keep staged files intact', + state.uris.length, + ), }), ], undefined, - { placeholder: `Confirm ${context.title}` }, + { placeholder: localize('confirm', 'Confirm {0}', context.title) }, ); const selection: StepSelection = yield step; return QuickCommand.canPickStepContinue(step, state, selection) ? selection[0].item : StepResult.Break; diff --git a/src/commands/git/status.ts b/src/commands/git/status.ts index 6d0328f2a1ec9..37d3601df7904 100644 --- a/src/commands/git/status.ts +++ b/src/commands/git/status.ts @@ -1,3 +1,4 @@ +import * as nls from 'vscode-nls'; import { GlyphChars } from '../../constants'; import { Container } from '../../container'; import { GitReference, GitStatus, Repository } from '../../git/models'; @@ -15,6 +16,7 @@ import { StepState, } from '../quickCommand'; +const localize = nls.loadMessageBundle(); interface Context { repos: Repository[]; associatedView: ViewsWithRepositoryFolders; @@ -35,8 +37,8 @@ type StatusStepState = ExcludeSome, 'repo' export class StatusGitCommand extends QuickCommand { constructor(container: Container, args?: StatusGitCommandArgs) { - super(container, 'status', 'status', 'Status', { - description: 'shows status information about a repository', + super(container, 'status', localize('label', 'status'), localize('title', 'Status'), { + description: localize('description', 'shows status information about a repository'), }); let counter = 0; diff --git a/src/commands/git/switch.ts b/src/commands/git/switch.ts index acf820b98d719..da2d290ffab1c 100644 --- a/src/commands/git/switch.ts +++ b/src/commands/git/switch.ts @@ -1,4 +1,5 @@ import { ProgressLocation, QuickPickItem, window } from 'vscode'; +import * as nls from 'vscode-nls'; import { BranchSorting } from '../../config'; import { Container } from '../../container'; import { GitReference, Repository } from '../../git/models'; @@ -19,6 +20,7 @@ import { StepState, } from '../quickCommand'; +const localize = nls.loadMessageBundle(); interface Context { repos: Repository[]; associatedView: ViewsWithRepositoryFolders; @@ -42,8 +44,8 @@ export interface SwitchGitCommandArgs { export class SwitchGitCommand extends QuickCommand { constructor(container: Container, args?: SwitchGitCommandArgs) { - super(container, 'switch', 'switch', 'Switch', { - description: 'aka checkout, switches the current branch to a specified branch', + super(container, 'switch', localize('label', 'switch'), localize('title', 'Switch'), { + description: localize('description', 'aka checkout, switches the current branch to a specified branch'), }); let counter = 0; @@ -66,9 +68,20 @@ export class SwitchGitCommand extends QuickCommand { return void (await window.withProgress( { location: ProgressLocation.Notification, - title: `Switching ${ - state.repos.length === 1 ? state.repos[0].formattedName : `${state.repos.length} repositories` - } to ${state.reference.name}`, + title: + state.repos.length === 1 + ? localize( + 'title.switchingRepoToRef', + 'Switching {0} to {1}', + state.repos[0].formattedName, + state.reference.name, + ) + : localize( + 'title.switchingNumberOfReposToRef', + 'Switching {0} repositories to {1}', + state.repos.length, + state.reference.name, + ), }, () => Promise.all( @@ -126,7 +139,16 @@ export class SwitchGitCommand extends QuickCommand { if (state.counter < 2 || state.reference == null) { const result = yield* pickBranchOrTagStepMultiRepo(state as SwitchStepState, context, { - placeholder: context => `Choose a branch${context.showTags ? ' or tag' : ''} to switch to`, + placeholder: context => + context.showTags + ? localize( + 'pickBranchOrTagStepMultiRepo.placeholder.chooseBranchToSwitchTo', + 'Choose a branch to switch to', + ) + : localize( + 'pickBranchOrTagStepMultiRepo.placeholder.chooseBranchOrTagToSwitchTo', + 'Choose a branch or tag to switch to', + ), }); if (result === StepResult.Break) { // If we skipped the previous step, make sure we back up past it @@ -141,7 +163,7 @@ export class SwitchGitCommand extends QuickCommand { } if (GitReference.isBranch(state.reference) && state.reference.remote) { - context.title = `Create Branch and ${this.title}`; + context.title = localize('createBranch.title', 'Create Branch and {0}', this.title); const { values: branches } = await this.container.git.getBranches(state.reference.repoPath, { filter: b => b.upstream?.name === state.reference!.name, @@ -150,10 +172,17 @@ export class SwitchGitCommand extends QuickCommand { if (branches.length === 0) { const result = yield* inputBranchNameStep(state as SwitchStepState, context, { - placeholder: 'Please provide a name for the new branch', - titleContext: ` based on ${GitReference.toString(state.reference, { - icon: false, - })}`, + placeholder: localize( + 'inputBranchNameStep.placeholder', + 'Please provider a name for the new branch', + ), + titleContext: ` ${localize( + 'inputBranchNameStep.titleContext', + 'based on {0}', + GitReference.toString(state.reference, { + icon: false, + }), + )}`, value: state.createBranch ?? GitReference.getNameWithoutRemote(state.reference), }); if (result === StepResult.Break) continue; @@ -180,26 +209,44 @@ export class SwitchGitCommand extends QuickCommand { private *confirmStep(state: SwitchStepState, context: Context): StepResultGenerator { const step: QuickPickStep = this.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), [ { label: context.title, description: state.createBranch ? '-b' : '', - detail: `Will ${ - state.createBranch - ? `create and switch to a new branch named ${ - state.createBranch - } from ${GitReference.toString(state.reference)}` - : `switch to ${GitReference.toString(state.reference)}` - } in ${ - state.repos.length === 1 - ? `$(repo) ${state.repos[0].formattedName}` - : `${state.repos.length} repositories` - }`, + detail: state.createBranch + ? state.repos.length === 1 + ? localize( + 'confirmStep.detail.willCreateAndSwitchToNewBranchNamedFromRefRepo', + 'Will create and switch to a new branch named {0} from {1} in {2}', + state.createBranch, + GitReference.toString(state.reference), + `$(repo) ${state.repos[0].formattedName}`, + ) + : localize( + 'confirmStep.detail.willCreateAndSwitchToNewBranchNamedFromRefInNumberOfRepos', + 'Will create and switch to a new branch named {0} from {1} in {2} repositories', + state.createBranch, + GitReference.toString(state.reference), + state.repos.length, + ) + : state.repos.length === 1 + ? localize( + 'confirmStep.detail.willSwitchToRefInRepo', + 'Will switch to {0} in {1}', + GitReference.toString(state.reference), + `$(repo) ${state.repos[0].formattedName}`, + ) + : localize( + 'confirmStep.detail.willSwitchToRefInNumberOfRepos', + 'Will switch to {0} in {1} repositories', + GitReference.toString(state.reference), + state.repos.length, + ), }, ], undefined, - { placeholder: `Confirm ${context.title}` }, + { placeholder: localize('confirm', 'Confirm {0}', context.title) }, ); const selection: StepSelection = yield step; return QuickCommand.canPickStepContinue(step, state, selection) ? undefined : StepResult.Break; diff --git a/src/commands/git/tag.ts b/src/commands/git/tag.ts index 0bf51be82d677..f7b82c1a201de 100644 --- a/src/commands/git/tag.ts +++ b/src/commands/git/tag.ts @@ -1,9 +1,9 @@ import { QuickInputButtons, QuickPickItem } from 'vscode'; +import * as nls from 'vscode-nls'; import { Container } from '../../container'; import { GitReference, GitTagReference, Repository } from '../../git/models'; import { QuickPickItemOfT } from '../../quickpicks/items/common'; import { FlagsQuickPickItem } from '../../quickpicks/items/flags'; -import { pluralize } from '../../system/string'; import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { appendReposToTitle, @@ -22,6 +22,8 @@ import { StepState, } from '../quickCommand'; +const localize = nls.loadMessageBundle(); + interface Context { repos: Repository[]; associatedView: ViewsWithRepositoryFolders; @@ -52,11 +54,12 @@ type CreateStepState = TagStepState = TagStepState>; const subcommandToTitleMap = new Map([ - ['create', 'Create'], - ['delete', 'Delete'], + ['create', localize('subcommand.create.title', 'Create Tag')], + ['delete', localize('subcommand.delete.title.plural', 'Delete Tags')], ]); -function getTitle(title: string, subcommand: State['subcommand'] | undefined) { - return subcommand == null ? title : `${subcommandToTitleMap.get(subcommand)} ${title}`; + +function getTitle(placeholder: string, subcommand: State['subcommand'] | undefined) { + return subcommand == null ? placeholder : subcommandToTitleMap.get(subcommand) ?? placeholder; } export interface TagGitCommandArgs { @@ -69,8 +72,8 @@ export class TagGitCommand extends QuickCommand { private subcommand: State['subcommand'] | undefined; constructor(container: Container, args?: TagGitCommandArgs) { - super(container, 'tag', 'tag', 'Tag', { - description: 'create, or delete tags', + super(container, 'tag', localize('label', 'tag'), localize('title', 'Tag'), { + description: localize('description', 'create, or delete tags'), }); let counter = 0; @@ -167,7 +170,10 @@ export class TagGitCommand extends QuickCommand { } } - context.title = getTitle(state.subcommand === 'delete' ? 'Tags' : this.title, state.subcommand); + context.title = getTitle( + state.subcommand === 'delete' ? localize('title.placeholder.tags', 'Tags') : this.title, + state.subcommand, + ); switch (state.subcommand) { case 'create': { @@ -196,17 +202,17 @@ export class TagGitCommand extends QuickCommand { private *pickSubcommandStep(state: PartialStepState): StepResultGenerator { const step = QuickCommand.createPickStep>({ title: this.title, - placeholder: `Choose a ${this.label} command`, + placeholder: localize('pickSubcommandStep.placeholder', 'Choose a {0} command', this.label), items: [ { - label: 'create', - description: 'creates a new tag', + label: localize('pickSubcommandStep.create.label', 'create'), + description: localize('pickSubcommandStep.create.description', 'creates a new tag'), picked: state.subcommand === 'create', item: 'create', }, { - label: 'delete', - description: 'deletes the specified tags', + label: localize('pickSubcommandStep.delete.label', 'delete'), + description: localize('pickSubcommandStep.delete.label', 'deletes the specified tags'), picked: state.subcommand === 'delete', item: 'delete', }, @@ -226,9 +232,17 @@ export class TagGitCommand extends QuickCommand { if (state.counter < 3 || state.reference == null) { const result = yield* pickBranchOrTagStep(state, context, { placeholder: context => - `Choose a branch${context.showTags ? ' or tag' : ''} to create the new tag from`, + context.showTags + ? localize( + 'pickBranchOrTagStep.placeholder.chooseBranchOrTagToCreateTagFrom', + 'Choose a branch or tag to create the new tag from', + ) + : localize( + 'pickBranchOrTagStep.placeholder.chooseBranchToCreateTagFrom', + 'Choose a branch to create the new tag from', + ), picked: state.reference?.ref ?? (await state.repo.getBranch())?.ref, - titleContext: ' from', + titleContext: ` ${localize('pickBranchOrTagStep.from', 'from')}`, value: GitReference.isRevision(state.reference) ? state.reference.ref : undefined, }); // Always break on the first step (so we will go back) @@ -239,8 +253,15 @@ export class TagGitCommand extends QuickCommand { if (state.counter < 4 || state.name == null) { const result = yield* inputTagNameStep(state, context, { - placeholder: 'Please provide a name for the new tag', - titleContext: ` at ${GitReference.toString(state.reference, { capitalize: true, icon: false })}`, + placeholder: localize( + 'inputTagNameStep.placeholder.provideNameForNewTag', + 'Please provide a name for the new tag', + ), + titleContext: ` ${localize( + 'inputTagNameStep.atRef', + 'at {0}', + GitReference.toString(state.reference, { capitalize: true, icon: false }), + )}`, value: state.name ?? GitReference.getNameWithoutRemote(state.reference), }); if (result === StepResult.Break) continue; @@ -282,13 +303,21 @@ export class TagGitCommand extends QuickCommand { ): AsyncStepResultGenerator { const step = QuickCommand.createInputStep({ title: appendReposToTitle( - `${context.title} at ${GitReference.toString(state.reference, { capitalize: true, icon: false })}`, + localize( + 'createCommandInputMessageStep.title.createOrDeleteTagAtRef', + '{0} at {1}', + context.title, + GitReference.toString(state.reference, { capitalize: true, icon: false }), + ), state, context, ), - placeholder: 'Please provide an optional message to annotate the tag', + placeholder: localize( + 'createCommandInputMessageStep.placeholder', + 'Please provide an optional message to annotate the tag', + ), value: state.message, - prompt: 'Enter optional message', + prompt: localize('createCommandInputMessageStep.prompt', 'Enter optional message'), }); const value: StepSelection = yield step; @@ -308,22 +337,30 @@ export class TagGitCommand extends QuickCommand { context: Context, ): StepResultGenerator { const step: QuickPickStep> = QuickCommand.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), [ FlagsQuickPickItem.create(state.flags, state.message.length !== 0 ? ['-m'] : [], { label: context.title, description: state.message.length !== 0 ? '-m' : '', - detail: `Will create a new tag named ${state.name} at ${GitReference.toString(state.reference)}`, + detail: localize( + 'createCommandConfirmStep.detail', + 'Will create a new tag named {0} at {1}', + state.name, + GitReference.toString(state.reference), + ), }), FlagsQuickPickItem.create( state.flags, state.message.length !== 0 ? ['--force', '-m'] : ['--force'], { - label: `Force ${context.title}`, + label: localize('createCommandConfirmStep.force.label', 'Force {0}', context.title), description: `--force${state.message.length !== 0 ? ' -m' : ''}`, - detail: `Will forcibly create a new tag named ${state.name} at ${GitReference.toString( - state.reference, - )}`, + detail: localize( + 'createCommandConfirmStep.force.detail', + 'Will forcibly create a new tag named {0} at {1}', + state.name, + GitReference.toString(state.reference), + ), }, ), ], @@ -340,11 +377,11 @@ export class TagGitCommand extends QuickCommand { } if (state.counter < 3 || state.references == null || state.references.length === 0) { - context.title = getTitle('Tags', state.subcommand); + context.title = localize('subcommand.delete.title.plural', 'Delete Tags'); const result = yield* pickTagsStep(state, context, { picked: state.references?.map(r => r.ref), - placeholder: 'Choose tags to delete', + placeholder: localize('pickTagsStep.placeholder', 'Choose tags to delete'), }); // Always break on the first step (so we will go back) if (result === StepResult.Break) break; @@ -352,7 +389,10 @@ export class TagGitCommand extends QuickCommand { state.references = result; } - context.title = getTitle(pluralize('Tag', state.references.length, { only: true }), state.subcommand); + context.title = + state.references.length === 1 + ? localize('subcommand.delete.title', 'Delete Tag') + : localize('subcommand.delete.title.plural', 'Delete Tags'); const result = yield* this.deleteCommandConfirmStep(state, context); if (result === StepResult.Break) continue; @@ -367,11 +407,15 @@ export class TagGitCommand extends QuickCommand { context: Context, ): StepResultGenerator { const step: QuickPickStep = QuickCommand.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), [ { label: context.title, - detail: `Will delete ${GitReference.toString(state.references)}`, + detail: localize( + 'deleteCommandConfirmStep.detail', + 'Will delete {0}', + GitReference.toString(state.references), + ), }, ], context, diff --git a/src/commands/git/worktree.ts b/src/commands/git/worktree.ts index 7c2af067d4a10..11affe28443aa 100644 --- a/src/commands/git/worktree.ts +++ b/src/commands/git/worktree.ts @@ -1,4 +1,5 @@ import { MessageItem, QuickInputButtons, Uri, window } from 'vscode'; +import * as nls from 'vscode-nls'; import { configuration } from '../../configuration'; import { Container } from '../../container'; import { PlusFeatures } from '../../features'; @@ -14,7 +15,7 @@ import { QuickPickItemOfT, QuickPickSeparator } from '../../quickpicks/items/com import { Directive } from '../../quickpicks/items/directive'; import { FlagsQuickPickItem } from '../../quickpicks/items/flags'; import { basename, isDescendent } from '../../system/path'; -import { pluralize, truncateLeft } from '../../system/string'; +import { truncateLeft } from '../../system/string'; import { OpenWorkspaceLocation } from '../../system/utils'; import { ViewsWithRepositoryFolders } from '../../views/viewBase'; import { GitActions } from '../gitCommands.actions'; @@ -38,6 +39,8 @@ import { StepState, } from '../quickCommand'; +const localize = nls.loadMessageBundle(); + interface Context { repos: Repository[]; associatedView: ViewsWithRepositoryFolders; @@ -84,12 +87,13 @@ type DeleteStepState = WorktreeStepState = WorktreeStepState>; const subcommandToTitleMap = new Map([ - ['create', 'Create'], - ['delete', 'Delete'], - ['open', 'Open'], + ['create', localize('subcommand.create.title', 'Create Worktree')], + ['delete', localize('subcommand.delete.title.plural', 'Delete Worktrees')], + ['open', localize('subcommand.open.title', 'Open Worktree')], ]); -function getTitle(title: string, subcommand: State['subcommand'] | undefined) { - return subcommand == null ? title : `${subcommandToTitleMap.get(subcommand)} ${title}`; + +function getTitle(placeholder: string, subcommand: State['subcommand'] | undefined) { + return subcommand == null ? placeholder : subcommandToTitleMap.get(subcommand) ?? placeholder; } export interface WorktreeGitCommandArgs { @@ -103,8 +107,8 @@ export class WorktreeGitCommand extends QuickCommand { private canSkipConfirmOverride: boolean | undefined; constructor(container: Container, args?: WorktreeGitCommandArgs) { - super(container, 'worktree', 'worktree', 'Worktree', { - description: 'open, create, or delete worktrees', + super(container, 'worktree', localize('label', 'worktree'), localize('title', 'Worktree'), { + description: localize('description', 'open, create, or delete worktrees'), }); let counter = 0; @@ -203,7 +207,10 @@ export class WorktreeGitCommand extends QuickCommand { const result = yield* ensureAccessStep(state as any, context, PlusFeatures.Worktrees); if (result === StepResult.Break) break; - context.title = getTitle(state.subcommand === 'delete' ? 'Worktrees' : this.title, state.subcommand); + context.title = getTitle( + state.subcommand === 'delete' ? localize('title.placeholder.worktrees', 'Worktrees') : this.title, + state.subcommand, + ); switch (state.subcommand) { case 'create': { @@ -241,23 +248,23 @@ export class WorktreeGitCommand extends QuickCommand { private *pickSubcommandStep(state: PartialStepState): StepResultGenerator { const step = QuickCommand.createPickStep>({ title: this.title, - placeholder: `Choose a ${this.label} command`, + placeholder: localize('pickSubcommandStep.placeholder', 'Choose a {0} command', this.label), items: [ { - label: 'open', - description: 'opens the specified worktree', + label: localize('pickSubcommandStep.open.label', 'open'), + description: localize('pickSubcommandStep.open.description', 'opens the specified worktree'), picked: state.subcommand === 'open', item: 'open', }, { - label: 'create', - description: 'creates a new worktree', + label: localize('pickSubcommandStep.create.label', 'create'), + description: localize('pickSubcommandStep.create.description', 'creates a new worktree'), picked: state.subcommand === 'create', item: 'create', }, { - label: 'delete', - description: 'deletes the specified worktrees', + label: localize('pickSubcommandStep.delete.label', 'delete'), + description: localize('pickSubcommandStep.delete.description', 'deletes the specified worktrees'), picked: state.subcommand === 'delete', item: 'delete', }, @@ -287,9 +294,17 @@ export class WorktreeGitCommand extends QuickCommand { if (state.counter < 3 || state.reference == null) { const result = yield* pickBranchOrTagStep(state, context, { placeholder: context => - `Choose a branch${context.showTags ? ' or tag' : ''} to create the new worktree for`, + context.showTags + ? localize( + 'pickBranchOrTagStep.placeholder.chooseBranchOrTagToCreateNewWorktreeFor', + 'Choose a branch or tag to create the new worktree for', + ) + : localize( + 'pickBranchOrTagStep.placeholder.chooseBranchToCreateNewWorktreeFor', + 'Choose a branch to create the new worktree for', + ), picked: state.reference?.ref ?? (await state.repo.getBranch())?.ref, - titleContext: ' for', + titleContext: ` ${localize('pickBranchOrTagStep.titleContext.for', 'for')}`, value: GitReference.isRevision(state.reference) ? state.reference.ref : undefined, }); // Always break on the first step (so we will go back) @@ -307,11 +322,15 @@ export class WorktreeGitCommand extends QuickCommand { state.uri = context.defaultUri; } else { const result = yield* this.createCommandChoosePathStep(state, context, { - titleContext: ` for ${GitReference.toString(state.reference, { - capitalize: true, - icon: false, - label: state.reference.refType !== 'branch', - })}`, + titleContext: ` ${localize( + 'choosePathStep.titleContext.forRef', + 'for {0}', + GitReference.toString(state.reference, { + capitalize: true, + icon: false, + label: state.reference.refType !== 'branch', + }), + )}`, }); if (result === StepResult.Break) continue; @@ -334,12 +353,19 @@ export class WorktreeGitCommand extends QuickCommand { if (state.flags.includes('-b') && state.createBranch == null) { const result = yield* inputBranchNameStep(state, context, { - placeholder: 'Please provide a name for the new branch', - titleContext: ` from ${GitReference.toString(state.reference, { - capitalize: true, - icon: false, - label: state.reference.refType !== 'branch', - })}`, + placeholder: localize( + 'inputBranchNameStep.placeholder', + 'Please provide a name for the new branch', + ), + titleContext: ` ${localize( + 'inputBranchNameStep.fromRef', + 'from {0}', + GitReference.toString(state.reference, { + capitalize: true, + icon: false, + label: state.reference.refType !== 'branch', + }), + )}`, value: state.createBranch ?? GitReference.getNameWithoutRemote(state.reference), }); if (result === StepResult.Break) { @@ -370,14 +396,26 @@ export class WorktreeGitCommand extends QuickCommand { WorktreeCreateError.is(ex, WorktreeCreateErrorReason.AlreadyCheckedOut) && !state.flags.includes('--force') ) { - const createBranch: MessageItem = { title: 'Create New Branch' }; - const force: MessageItem = { title: 'Create Anyway' }; - const cancel: MessageItem = { title: 'Cancel', isCloseAffordance: true }; + const createBranch: MessageItem = { + title: localize('alreadyCheckedOutWarning.createNewBranch', 'Create New Branch'), + }; + const force: MessageItem = { + title: localize('alreadyCheckedOutWarning.createAnyway', 'Create Anyway'), + }; + const cancel: MessageItem = { title: localize('cancel', 'Cancel'), isCloseAffordance: true }; const result = await window.showWarningMessage( - `Unable to create the new worktree because ${GitReference.toString(state.reference, { - icon: false, - quoted: true, - })} is already checked out.\n\nWould you like to create a new branch for this worktree or forcibly create it anyway?`, + `${localize( + 'alreadyCheckedOutWarning.message.unableToCreateWorktree', + 'Unable to create the new worktree because {0} is already checked out.', + GitReference.toString(state.reference, { + icon: false, + quoted: true, + }), + )} + \n\n${localize( + 'alreadyCheckedOutWarning.message.wouldYouLikeToCreateNewBranchOrForceCreateAnyway', + 'Would you like to create a new branch for this worktree or forcibly create it anyway?', + )}`, { modal: true }, createBranch, force, @@ -399,14 +437,20 @@ export class WorktreeGitCommand extends QuickCommand { } } else if (WorktreeCreateError.is(ex, WorktreeCreateErrorReason.AlreadyExists)) { void window.showErrorMessage( - `Unable to create a new worktree in '${GitWorktree.getFriendlyPath( - uri, - )}' because the folder already exists and is not empty.`, - 'OK', + localize( + 'alreadyExistsError.message', + 'Unable to create a new worktree in {0} because the folder already exists and is not empty.', + GitWorktree.getFriendlyPath(uri), + ), + localize('ok', 'OK'), ); } else { void Messages.showGenericErrorMessage( - `Unable to create a new worktree in '${GitWorktree.getFriendlyPath(uri)}.`, + localize( + 'genericError.message', + 'Unable to create a new worktree in {0}.', + GitWorktree.getFriendlyPath(uri), + ), ); } } @@ -427,12 +471,13 @@ export class WorktreeGitCommand extends QuickCommand { canSelectFolders: true, canSelectMany: false, defaultUri: context.pickedUri ?? state.uri ?? context.defaultUri, - openLabel: 'Select Worktree Location', - title: `${appendReposToTitle( - `Choose Worktree Location${options?.titleContext ?? ''}`, + openLabel: localize('choosePathStep.openLabel', 'Select Worktree Location'), + title: appendReposToTitle( + ` + ${localize('choosePathStep.title', 'Choose Worktree Location')}${options?.titleContext ?? ''}`, state, context, - )}`, + ), }); if (uris == null || uris.length === 0) return Directive.Back; @@ -496,15 +541,23 @@ export class WorktreeGitCommand extends QuickCommand { ); const step: QuickPickStep> = QuickCommand.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), [ FlagsQuickPickItem.create( state.flags, [], { label: context.title, - description: ` for ${GitReference.toString(state.reference)}`, - detail: `Will create worktree in $(folder) ${recommendedFriendlyPath}`, + description: ` ${localize( + 'quickPick.create.description', + 'for {0}', + GitReference.toString(state.reference), + )}`, + detail: localize( + 'quickPick.create.detail', + 'Will create worktree in {0}', + `$(folder) ${recommendedFriendlyPath}`, + ), }, recommendedRootUri, ), @@ -512,9 +565,17 @@ export class WorktreeGitCommand extends QuickCommand { state.flags, ['-b'], { - label: 'Create New Branch and Worktree', - description: ` from ${GitReference.toString(state.reference)}`, - detail: `Will create worktree in $(folder) ${recommendedNewBranchFriendlyPath}`, + label: localize('quickPick.createBranch.label', 'Create New Branch and Worktree'), + description: ` ${localize( + 'quickPick.createBranch.description', + 'from {0}', + GitReference.toString(state.reference), + )}`, + detail: localize( + 'quickPick.createBranch.detail', + 'Will create worktree in {0}', + `$(folder) ${recommendedNewBranchFriendlyPath}`, + ), }, recommendedRootUri, ), @@ -525,9 +586,21 @@ export class WorktreeGitCommand extends QuickCommand { state.flags, ['--direct'], { - label: `${context.title} (directly in folder)`, - description: ` for ${GitReference.toString(state.reference)}`, - detail: `Will create worktree directly in $(folder) ${pickedFriendlyPath}`, + label: localize( + 'quickPick.createDirect.label', + '{0} (directly in folder)', + context.title, + ), + description: ` ${localize( + 'quickPick.createDirect.description', + 'for {0}', + GitReference.toString(state.reference), + )}`, + detail: localize( + 'quickPick.createDirect.detail', + 'Will create wokrtree directly in {0}', + `$(folder) ${pickedFriendlyPath}`, + ), }, pickedUri, ), @@ -535,9 +608,20 @@ export class WorktreeGitCommand extends QuickCommand { state.flags, ['-b', '--direct'], { - label: 'Create New Branch and Worktree (directly in folder)', - description: ` from ${GitReference.toString(state.reference)}`, - detail: `Will create worktree directly in $(folder) ${pickedFriendlyPath}`, + label: localize( + 'quickPick.createBranchDirect', + 'Create New Branch and Worktree (directly in folder)', + ), + description: ` ${localize( + 'quickPick.description', + 'from {0}', + GitReference.toString(state.reference), + )}`, + detail: localize( + 'quickPick.createBranchDirect.detail', + 'Will create worktree directly in {0}', + `$(folder) ${pickedFriendlyPath}`, + ), }, pickedUri, ), @@ -561,13 +645,13 @@ export class WorktreeGitCommand extends QuickCommand { while (this.canStepsContinue(state)) { if (state.counter < 3 || state.uris == null || state.uris.length === 0) { - context.title = getTitle('Worktrees', state.subcommand); + context.title = localize('subcommand.delete.title.plural', 'Delete Worktrees'); const result = yield* pickWorktreesStep(state, context, { filter: wt => wt.main || !wt.opened, // Can't delete the main or opened worktree includeStatus: true, picked: state.uris?.map(uri => uri.toString()), - placeholder: 'Choose worktrees to delete', + placeholder: localize('pickWorktreesStep.placeholder', 'Choose worktrees to delete'), }); // Always break on the first step (so we will go back) if (result === StepResult.Break) break; @@ -575,7 +659,10 @@ export class WorktreeGitCommand extends QuickCommand { state.uris = result.map(w => w.uri); } - context.title = getTitle(pluralize('Worktree', state.uris.length, { only: true }), state.subcommand); + context.title = + state.uris.length === 1 + ? localize('subcommand.delete.title', 'Delete Worktree') + : localize('subcommand.delete.title.plural', 'Delete Worktrees'); const result = yield* this.deleteCommandConfirmStep(state, context); if (result === StepResult.Break) continue; @@ -595,10 +682,28 @@ export class WorktreeGitCommand extends QuickCommand { const worktree = context.worktrees.find(wt => wt.uri.toString() === uri.toString()); const status = await worktree?.getStatus(); if (status?.hasChanges ?? false) { - const confirm: MessageItem = { title: 'Force Delete' }; - const cancel: MessageItem = { title: 'Cancel', isCloseAffordance: true }; + const confirm: MessageItem = { + title: localize('deleteUncommittedChangesWarning.forceDelete', 'Force Delete'), + }; + const cancel: MessageItem = { + title: localize('cancel', 'Cancel'), + isCloseAffordance: true, + }; const result = await window.showWarningMessage( - `The worktree in '${uri.fsPath}' has uncommitted changes.\n\nDeleting it will cause those changes to be FOREVER LOST.\nThis is IRREVERSIBLE!\n\nAre you sure you still want to delete it?`, + `${localize( + 'deleteUncommittedChangesWarning.message.worktreeInPathHasUncommittedChanges', + "The worktree in '{0}' has uncommitted changes.", + uri.fsPath, + )} + \n\n${localize( + 'deleteUncommittedChangesWarning.message.deletingWorktreeWillCauseChangesToBeForeverLost', + 'Deleting it will cause those changes to be FOREVER LOST.', + )} + \n${localize('warning.thisIsIrreversible', 'This is IRREVERSIBLE!')} + \n\n${localize( + 'deleteUncommittedChangesWarning.message.areYouSureYouWantToDeleteWorktree', + 'Are you sure you still want to delete it?', + )}`, { modal: true }, confirm, cancel, @@ -612,14 +717,45 @@ export class WorktreeGitCommand extends QuickCommand { } catch (ex) { if (WorktreeDeleteError.is(ex)) { if (ex.reason === WorktreeDeleteErrorReason.MainWorkingTree) { - void window.showErrorMessage('Unable to delete the main worktree'); + void window.showErrorMessage( + localize( + 'unableToDeleteError.message.unableToDeleteMainWorktree', + 'Unable to delete the main worktree', + ), + ); } else if (!force) { - const confirm: MessageItem = { title: 'Force Delete' }; - const cancel: MessageItem = { title: 'Cancel', isCloseAffordance: true }; + const confirm: MessageItem = { + title: localize('unableToDeleteError.forceDelete', 'Force Delete'), + }; + const cancel: MessageItem = { + title: localize('cancel', 'Cancel'), + isCloseAffordance: true, + }; const result = await window.showErrorMessage( ex.reason === WorktreeDeleteErrorReason.HasChanges - ? `Unable to delete worktree because there are UNCOMMITTED changes in '${uri.fsPath}'.\n\nForcibly deleting it will cause those changes to be FOREVER LOST.\nThis is IRREVERSIBLE!\n\nWould you like to forcibly delete it?` - : `Unable to delete worktree in '${uri.fsPath}'.\n\nWould you like to try to forcibly delete it?`, + ? `${localize( + 'unableToDeleteError.message.unableToDeleteWorktreeBecauseUncommittedChanges', + "Unable to delete worktree because there are UNCOMMITTED changes in '{0}'.", + uri.fsPath, + )} + \n\n${localize( + 'unableToDeleteError.message.forciblyDeletingWorjtreeWillCauseChangesToBeForeverLost', + 'Forcibly deleting it will cause those changes to be FOREVER LOST.', + )} + \n${localize('warning.thisIsIrreversible', 'This is IRREVERSIBLE!')} + \n\n${localize( + 'unableToDeleteError.message.wouldYouLikeToForceDeleteWorktree', + 'Would you like to forcibly delete it?', + )}` + : `${localize( + 'unableToDeleteError.message.unableToDeleteWorktreeInDir', + "Unable to delete worktree in '{0}'.", + uri.fsPath, + )} + \n\n${localize( + 'unableToDeleteError.message.wouldYouLikeToTryToForceDeleteWorktree', + 'Would you like to try to forcibly delete it?', + )}`, { modal: true }, confirm, cancel, @@ -631,7 +767,13 @@ export class WorktreeGitCommand extends QuickCommand { } } } else { - void Messages.showGenericErrorMessage(`Unable to delete worktree in '${uri.fsPath}.`); + void Messages.showGenericErrorMessage( + localize( + 'genericDeleteError.message', + "Unable to delete worktree in '{0}'", + uri.fsPath, + ), + ); } } } while (retry); @@ -641,22 +783,38 @@ export class WorktreeGitCommand extends QuickCommand { private *deleteCommandConfirmStep(state: DeleteStepState, context: Context): StepResultGenerator { const step: QuickPickStep> = QuickCommand.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), [ FlagsQuickPickItem.create(state.flags, [], { label: context.title, - detail: `Will delete ${pluralize('worktree', state.uris.length, { - only: state.uris.length === 1, - })}${state.uris.length === 1 ? ` in $(folder) ${GitWorktree.getFriendlyPath(state.uris[0])}` : ''}`, + detail: + state.uris.length === 1 + ? localize( + 'quickPick.delete.detail.willDeleteWorktreeInDir', + 'Will delete worktree in {0}', + `$(folder) ${GitWorktree.getFriendlyPath(state.uris[0])}`, + ) + : localize( + 'quickPick.delete.detail.willDeleteWorktrees', + 'Will delete {0} worktrees', + state.uris.length, + ), }), FlagsQuickPickItem.create(state.flags, ['--force'], { - label: `Force ${context.title}`, - description: 'including ANY UNCOMMITTED changes', - detail: `Will forcibly delete ${pluralize('worktree', state.uris.length, { - only: state.uris.length === 1, - })} ${ - state.uris.length === 1 ? ` in $(folder) ${GitWorktree.getFriendlyPath(state.uris[0])}` : '' - }`, + label: localize('quickPick.forceDelete.title', 'Force {0}', context.title), + description: localize('quickPick.forceDelete.description', 'including ANY UNCOMMITTED changes'), + detail: + state.uris.length === 1 + ? localize( + 'quickPick.forceDelete.detail.willForciblyDeleteWorktreeInDir', + 'Will forcibly delete worktree in {0}', + `$(folder) ${GitWorktree.getFriendlyPath(state.uris[0])}`, + ) + : localize( + 'quickPick.forceDelete.detail.willForciblyDeleteWorktrees', + 'Will forcibly delete {0} worktrees', + state.uris.length, + ), }), ], context, @@ -675,12 +833,12 @@ export class WorktreeGitCommand extends QuickCommand { while (this.canStepsContinue(state)) { if (state.counter < 3 || state.uri == null) { - context.title = getTitle('Worktree', state.subcommand); + context.title = localize('subcommand.open.title', 'Open Worktree'); const result = yield* pickWorktreeStep(state, context, { includeStatus: true, picked: state.uri?.toString(), - placeholder: 'Choose worktree to open', + placeholder: localize('pickWorktreeStep.placeholder', 'Choose worktree to open'), }); // Always break on the first step (so we will go back) if (result === StepResult.Break) break; @@ -688,7 +846,7 @@ export class WorktreeGitCommand extends QuickCommand { state.uri = result.uri; } - context.title = getTitle('Worktree', state.subcommand); + context.title = localize('subcommand.open.title', 'Open Worktree'); const result = yield* this.openCommandConfirmStep(state, context); if (result === StepResult.Break) continue; @@ -712,25 +870,31 @@ export class WorktreeGitCommand extends QuickCommand { private *openCommandConfirmStep(state: OpenStepState, context: Context): StepResultGenerator { const step: QuickPickStep> = QuickCommand.createConfirmStep( - appendReposToTitle(`Confirm ${context.title}`, state, context), + appendReposToTitle(localize('confirm', 'Confirm {0}', context.title), state, context), [ FlagsQuickPickItem.create(state.flags, [], { label: context.title, - detail: `Will open, in the current window, the worktree in $(folder) ${GitWorktree.getFriendlyPath( - state.uri, - )}`, + detail: localize( + 'quickPick.open.detail', + 'Will open, in the current window, the worktree in {0}', + `$(folder) ${GitWorktree.getFriendlyPath(state.uri)}`, + ), }), FlagsQuickPickItem.create(state.flags, ['--new-window'], { - label: `${context.title} in a New Window`, - detail: `Will open, in a new window, the worktree in $(folder) ${GitWorktree.getFriendlyPath( - state.uri, - )}`, + label: localize('quickPick.openInNewWindow.label', '{0} in a New Window', context.title), + detail: localize( + 'quickPick.openInNewWindow.detail', + 'Will open, in a new window, the worktree in {0}', + `$(folder) ${GitWorktree.getFriendlyPath(state.uri)}`, + ), }), FlagsQuickPickItem.create(state.flags, ['--reveal-explorer'], { - label: `Reveal in File Explorer`, - detail: `Will open, in the File Explorer, the worktree in $(folder) ${GitWorktree.getFriendlyPath( - state.uri, - )}`, + label: localize('quickPick.revealExplorer.label', 'Reveal in File Explorer'), + detail: localize( + 'quickPick.revealExplorer.detail', + 'Will open, in the File Explorer, the worktree in {0}', + `$(folder) ${GitWorktree.getFriendlyPath(state.uri)}`, + ), }), ], context, diff --git a/src/configuration.ts b/src/configuration.ts index c45f27bbe3148..1ed44cd7e3a6d 100644 --- a/src/configuration.ts +++ b/src/configuration.ts @@ -9,9 +9,13 @@ import { ExtensionContext, workspace, } from 'vscode'; +import * as nls from 'vscode-nls'; import type { Config } from './config'; import { areEqual } from './system/object'; +// this call must go before all nls.loadMessageBundle() calls +// if localization does not work and default locale is loaded, the call order can possibly be the issue +nls.config({ messageFormat: nls.MessageFormat.bundle, bundleFormat: nls.BundleFormat.standalone })(); const configPrefix = 'gitlens'; export interface ConfigurationWillChangeEvent { diff --git a/src/extension.ts b/src/extension.ts index e4e429fc567ce..d8b292eae011f 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,4 +1,5 @@ import { version as codeVersion, env, ExtensionContext, extensions, window, workspace } from 'vscode'; +import * as nls from 'vscode-nls'; import { isWeb } from '@env/platform'; import { Api } from './api/api'; import type { CreatePullRequestActionContext, GitLensApi, OpenPullRequestActionContext } from './api/gitlens'; @@ -20,6 +21,8 @@ import { Stopwatch } from './system/stopwatch'; import { compare } from './system/version'; import { ViewNode } from './views/nodes'; +const localize = nls.loadMessageBundle(); + export async function activate(context: ExtensionContext): Promise { const insiders = context.extension.id === 'eamodio.gitlens-insiders'; const gitlensVersion = context.extension.packageJSON.version; @@ -183,7 +186,10 @@ function setKeysForSync(context: ExtensionContext, ...keys: (SyncedStorageKeys | function registerBuiltInActionRunners(container: Container): void { container.context.subscriptions.push( container.actionRunners.registerBuiltIn('createPullRequest', { - label: ctx => `Create Pull Request on ${ctx.remote?.provider?.name ?? 'Remote'}`, + label: ctx => + ctx.remote?.provider?.name + ? localize('createPullRequestOnProvider', 'Create Pull Request on {0}', ctx.remote.provider.name) + : localize('createPullRequestOnRemote', 'Create Pull Request on Remote'), run: async ctx => { if (ctx.type !== 'createPullRequest') return; @@ -200,7 +206,10 @@ function registerBuiltInActionRunners(container: Container): void { }, }), container.actionRunners.registerBuiltIn('openPullRequest', { - label: ctx => `Open Pull Request on ${ctx.provider?.name ?? 'Remote'}`, + label: ctx => + ctx.provider?.name + ? localize('openPullRequestOnProvider', 'Open Pull Request on {0}', ctx.provider.name) + : localize('openPullRequestOnRemote', 'Open Pull Request on Remote'), run: async ctx => { if (ctx.type !== 'openPullRequest') return; diff --git a/src/hovers/hovers.ts b/src/hovers/hovers.ts index f57550e026322..0080402a12712 100644 --- a/src/hovers/hovers.ts +++ b/src/hovers/hovers.ts @@ -1,4 +1,5 @@ import { CancellationToken, MarkdownString, TextDocument } from 'vscode'; +import * as nls from 'vscode-nls'; import { hrtime } from '@env/hrtime'; import { DiffWithCommand, ShowQuickCommitCommand } from '../commands'; import { GlyphChars } from '../constants'; @@ -11,6 +12,7 @@ import { count } from '../system/iterable'; import { PromiseCancelledError } from '../system/promise'; import { getDurationMilliseconds } from '../system/string'; +const localize = nls.loadMessageBundle(); export namespace Hovers { export async function changesMessage( commit: GitCommit, @@ -92,31 +94,33 @@ export namespace Hovers { previous = compareUris.previous.sha == null || compareUris.previous.isUncommitted ? `  _${GitRevision.shorten(compareUris.previous.sha, { - strings: { working: 'Working Tree' }, + strings: { working: localize('workingTree', 'Working Tree') }, })}_  ${GlyphChars.ArrowLeftRightLong}  ` : `  [$(git-commit) ${GitRevision.shorten( compareUris.previous.sha || '', - )}](${ShowQuickCommitCommand.getMarkdownCommandArgs( - compareUris.previous.sha || '', - )} "Show Commit")  ${GlyphChars.ArrowLeftRightLong}  `; + )}](${ShowQuickCommitCommand.getMarkdownCommandArgs(compareUris.previous.sha || '')} "${localize( + 'showCommit', + 'Show Commit', + )}")  ${GlyphChars.ArrowLeftRightLong}  `; current = compareUris.current.sha == null || compareUris.current.isUncommitted ? `_${GitRevision.shorten(compareUris.current.sha, { strings: { - working: 'Working Tree', + working: localize('workingTree', 'Working Tree'), }, })}_` : `[$(git-commit) ${GitRevision.shorten( compareUris.current.sha || '', - )}](${ShowQuickCommitCommand.getMarkdownCommandArgs( - compareUris.current.sha || '', - )} "Show Commit")`; + )}](${ShowQuickCommitCommand.getMarkdownCommandArgs(compareUris.current.sha || '')} "${localize( + 'showCommit', + 'Show Commit', + )}")`; } else { - message = `[$(compare-changes)](${DiffWithCommand.getMarkdownCommandArgs( - commit, - editorLine, - )} "Open Changes")`; + message = `[$(compare-changes)](${DiffWithCommand.getMarkdownCommandArgs(commit, editorLine)} "${localize( + 'openChanges', + 'Open Changes', + )}")`; if (previousSha === null) { previousSha = await commit.getPreviousSha(); @@ -124,17 +128,22 @@ export namespace Hovers { if (previousSha) { previous = `  [$(git-commit) ${GitRevision.shorten( previousSha, - )}](${ShowQuickCommitCommand.getMarkdownCommandArgs(previousSha)} "Show Commit")  ${ - GlyphChars.ArrowLeftRightLong - } `; + )}](${ShowQuickCommitCommand.getMarkdownCommandArgs(previousSha)} "${localize( + 'showCommit', + 'Show Commit', + )}")  ${GlyphChars.ArrowLeftRightLong} `; } current = `[$(git-commit) ${commit.shortSha}](${ShowQuickCommitCommand.getMarkdownCommandArgs( commit.sha, - )} "Show Commit")`; + )} "${localize('showCommit', 'Show Commit')}")`; } - message = `${diff}\n---\n\nChanges${previous ?? ' added in '}${current}   |   ${message}`; + message = `${diff}\n---\n\n${ + previous + ? localize('changesPreviousCommitCurrentCommit', 'Changes{0}{1}', previous, current) + : localize('ChangesAddedInCommit', 'Changes added in {0}', current) + }  |   ${message}`; const markdown = new MarkdownString(message, true); markdown.supportHtml = true; @@ -154,8 +163,8 @@ export namespace Hovers { let previous; let current; if (fromCommit == null) { - previous = '_Working Tree_'; - current = '_Unsaved_'; + previous = `_${localize('workingTree', 'Working Tree')}_`; + current = `_${localize('unsaved', 'Unsaved')}_`; } else { const file = await fromCommit.findFile(uri); if (file == null) return undefined; @@ -171,15 +180,15 @@ export namespace Hovers { }, repoPath: uri.repoPath!, line: editorLine, - })} "Open Changes")`; + })} "${localize('openChanges', 'Open Changes')}")`; previous = `[$(git-commit) ${fromCommit.shortSha}](${ShowQuickCommitCommand.getMarkdownCommandArgs( fromCommit.sha, - )} "Show Commit")`; + )} "${localize('showComit', 'Show Commit')}")`; - current = '_Working Tree_'; + current = `_${localize('workingTree', 'Working Tree')}_`; } - message = `${diff}\n---\n\nLocal Changes  ${previous}  ${ + message = `${diff}\n---\n\n${localize('localChanges', 'Local Changes')}  ${previous}  ${ GlyphChars.ArrowLeftRightLong }  ${current}${message == null ? '' : `   |   ${message}`}`; diff --git a/src/messages.ts b/src/messages.ts index 4923d6adaeb71..01c47423d9117 100644 --- a/src/messages.ts +++ b/src/messages.ts @@ -1,10 +1,12 @@ import { ConfigurationTarget, MessageItem, window } from 'vscode'; +import * as nls from 'vscode-nls'; import { configuration } from './configuration'; import { Commands } from './constants'; import { GitCommit } from './git/models'; import { Logger } from './logger'; import { executeCommand } from './system/command'; +const localize = nls.loadMessageBundle(); export const enum SuppressedMessages { CommitHasNoPreviousCommitWarning = 'suppressCommitHasNoPreviousCommitWarning', CommitNotFoundWarning = 'suppressCommitNotFoundWarning', @@ -24,13 +26,19 @@ export class Messages { if (commit == null) { return Messages.showMessage( 'info', - 'There is no previous commit.', + localize('commitHasNoPreviousCommitWarning.message', 'There is no previous commit.'), SuppressedMessages.CommitHasNoPreviousCommitWarning, ); } return Messages.showMessage( 'info', - `Commit ${commit.shortSha} (${commit.author.name}, ${commit.formattedDate}) has no previous commit.`, + localize( + 'commitHasNoPreviousCommitWarning.message', + 'Commit {0} ({1}, {2}) has no previous commit.', + commit.shortSha, + commit.author.name, + commit.formattedDate, + ), SuppressedMessages.CommitHasNoPreviousCommitWarning, ); } @@ -38,30 +46,37 @@ export class Messages { static showCommitNotFoundWarningMessage(message: string): Promise { return Messages.showMessage( 'warn', - `${message}. The commit could not be found.`, + `${message}. ${localize('commitNotFoundWarning.commitNotFound', 'The commit could not be found.')}`, SuppressedMessages.CommitNotFoundWarning, ); } static async showCreatePullRequestPrompt(branch: string): Promise { - const create = { title: 'Create Pull Request...' }; + const create = { title: localize('createPullRequestPrompt.title', 'Create Pull Request...') }; const result = await Messages.showMessage( 'info', - `Would you like to create a Pull Request for branch '${branch}'?`, + localize( + 'createPullRequestPrompt.message', + "Would you like to create a Pull Request for branch '{0}'?", + branch, + ), SuppressedMessages.CreatePullRequestPrompt, - { title: "Don't Show Again" }, + { title: localize('dontShowAgain', "Don't Show Again") }, create, ); return result === create; } static async showDebugLoggingWarningMessage(): Promise { - const disable = { title: 'Disable Debug Logging' }; + const disable = { title: localize('debugLoggingWarningMessage.title', 'Disable Debug Logging') }; const result = await Messages.showMessage( 'warn', - 'GitLens debug logging is currently enabled. Unless you are reporting an issue, it is recommended to be disabled. Would you like to disable it?', + localize( + 'debugLoggingWarningMessage.message', + 'GitLens debug logging is currently enabled. Unless you are reporting an issue, it is recommended to be disabled. Would you like to disable it?', + ), SuppressedMessages.SuppressDebugLoggingWarning, - { title: "Don't Show Again" }, + { title: localize('dontShowAgain', "Don't Show Again") }, disable, ); @@ -69,10 +84,10 @@ export class Messages { } static async showGenericErrorMessage(message: string): Promise { - const actions: MessageItem[] = [{ title: 'Open Output Channel' }]; + const actions: MessageItem[] = [{ title: localize('genericErrorMessage.title', 'Open Output Channel') }]; const result = await Messages.showMessage( 'error', - `${message}. See output channel for more details`, + `${message}. ${localize('genericErrorMessage.message', 'See output channel for more details')}`, undefined, null, ...actions, @@ -87,7 +102,10 @@ export class Messages { static showFileNotUnderSourceControlWarningMessage(message: string): Promise { return Messages.showMessage( 'warn', - `${message}. The file is probably not under source control.`, + `${message}. ${localize( + 'fileNotUnderSourceControlWarningMessage.message', + 'The file is probably not under source control.', + )}`, SuppressedMessages.FileNotUnderSourceControlWarning, ); } @@ -95,7 +113,10 @@ export class Messages { static showGitDisabledErrorMessage() { return Messages.showMessage( 'error', - 'GitLens requires Git to be enabled. Please re-enable Git \u2014 set `git.enabled` to true and reload.', + localize( + 'gitDisabledErrorMessage.message', + 'GitLens requires Git to be enabled. Please re-enable Git \u2014 set `git.enabled` to true and reload.', + ), SuppressedMessages.GitDisabledWarning, ); } @@ -103,14 +124,20 @@ export class Messages { static showGitInvalidConfigErrorMessage() { return Messages.showMessage( 'error', - 'GitLens is unable to use Git. Your Git configuration seems to be invalid. Please resolve any issues with your Git configuration and reload.', + localize( + 'gitInvalidConfigErrorMessage.message', + 'GitLens is unable to use Git. Your Git configuration seems to be invalid. Please resolve any issues with your Git configuration and reload.', + ), ); } static showGitMissingErrorMessage() { return Messages.showMessage( 'error', - "GitLens was unable to find Git. Please make sure Git is installed. Also ensure that Git is either in the PATH, or that 'git.path' is pointed to its installed location.", + localize( + 'gitMissingErrorMessage.message', + "GitLens was unable to find Git. Please make sure Git is installed. Also ensure that Git is either in the PATH, or that 'git.path' is pointed to its installed location.", + ), SuppressedMessages.GitMissingWarning, ); } @@ -118,7 +145,12 @@ export class Messages { static showGitVersionUnsupportedErrorMessage(version: string, required: string): Promise { return Messages.showMessage( 'error', - `GitLens requires a newer version of Git (>= ${required}) than is currently installed (${version}). Please install a more recent version of Git.`, + localize( + 'gitVersionUnsupportedErrorMessage.message', + 'GitLens requires a newer version of Git (>= {0}) than is currently installed ({1}). Please install a more recent version of Git.', + required, + version, + ), SuppressedMessages.GitVersionWarning, ); } @@ -126,7 +158,10 @@ export class Messages { static showInsidersErrorMessage() { return Messages.showMessage( 'error', - 'GitLens (Insiders) cannot be used while GitLens is also enabled. Please ensure that only one version is enabled.', + localize( + 'insidersErrorMessage.message', + 'GitLens (Insiders) cannot be used while GitLens is also enabled. Please ensure that only one version is enabled.', + ), SuppressedMessages.GitDisabledWarning, ); } @@ -134,7 +169,7 @@ export class Messages { static showLineUncommittedWarningMessage(message: string): Promise { return Messages.showMessage( 'warn', - `${message}. The line has uncommitted changes.`, + `${message}. ${localize('lineUncommittedWarningMessage.message', 'The line has uncommitted changes.')}`, SuppressedMessages.LineUncommittedWarning, ); } @@ -142,7 +177,7 @@ export class Messages { static showNoRepositoryWarningMessage(message: string): Promise { return Messages.showMessage( 'warn', - `${message}. No repository could be found.`, + `${message}. ${localize('noRepositoryWarningMessage.message', 'No repository could be found.')}`, SuppressedMessages.NoRepositoryWarning, ); } @@ -150,16 +185,19 @@ export class Messages { static showRebaseSwitchToTextWarningMessage(): Promise { return Messages.showMessage( 'warn', - 'Closing either the git-rebase-todo file or the Rebase Editor will start the rebase.', + localize( + 'rebaseSwitchToTextWarningMessage.message', + 'Closing either the git-rebase-todo file or the Rebase Editor will start the rebase.', + ), SuppressedMessages.RebaseSwitchToTextWarning, ); } static async showWhatsNewMessage(version: string) { - const whatsnew = { title: "See What's New" }; + const whatsnew = { title: localize('whatsNewMessage.title', "See What's New") }; const result = await Messages.showMessage( 'info', - `GitLens ${version} is here — check out what's new!`, + localize('WhatsNewMessage.message', "GitLens {0} is here — check out what's new!", version), undefined, null, whatsnew, @@ -174,7 +212,7 @@ export class Messages { type: 'info' | 'warn' | 'error', message: string, suppressionKey?: SuppressedMessages, - dontShowAgain: MessageItem | null = { title: "Don't Show Again" }, + dontShowAgain: MessageItem | null = { title: localize('dontShowAgain', "Don't Show Again") }, ...actions: MessageItem[] ): Promise { Logger.log(`ShowMessage(${type}, '${message}', ${suppressionKey}, ${JSON.stringify(dontShowAgain)})`); diff --git a/src/partners.ts b/src/partners.ts index e71d33705848a..4c32292dc3676 100644 --- a/src/partners.ts +++ b/src/partners.ts @@ -1,10 +1,12 @@ import { CancellationTokenSource, Extension, ExtensionContext, extensions, Uri } from 'vscode'; +import * as nls from 'vscode-nls'; import type { ActionContext, HoverCommandsActionContext } from './api/gitlens'; import type { InviteToLiveShareCommandArgs } from './commands'; import { Commands, CoreCommands } from './constants'; import { Container } from './container'; import { executeCommand, executeCoreCommand } from './system/command'; +const localize = nls.loadMessageBundle(); export async function installExtension( extensionId: string, tokenSource: CancellationTokenSource, @@ -62,16 +64,22 @@ function registerLiveShare(context: ExtensionContext) { label: (context: ActionContext) => { if (context.type === 'hover.commands') { if (context.commit.author.name !== 'You') { - return `$(live-share) Invite ${context.commit.author.name}${ + return `$(live-share) ${ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions context.commit.author.presence?.statusText - ? ` (${context.commit.author.presence?.statusText})` - : '' - } to a Live Share Session`; + ? localize( + 'inviteCommitAuthorWithStatusToLiveShareSession', + 'Invite {0} ({1}) to a Live Share Session', + ) + : localize( + 'inviteCommitAuthorToLiveShareSession', + 'Invite {0} to a Live Share Session', + ) + }`; } } - return '$(live-share) Start a Live Share Session'; + return `$(live-share) ${localize('startLiveShareSession', 'Start a Live Share Session')}`; }, run: async (context: ActionContext) => { if (context.type !== 'hover.commands' || context.commit.author.name === 'You') { diff --git a/src/plus/subscription/authenticationProvider.ts b/src/plus/subscription/authenticationProvider.ts index 1cd085c947c74..227b0ba7e0a05 100644 --- a/src/plus/subscription/authenticationProvider.ts +++ b/src/plus/subscription/authenticationProvider.ts @@ -9,12 +9,14 @@ import { extensions, window, } from 'vscode'; +import * as nls from 'vscode-nls'; import type { Container } from '../../container'; import { Logger } from '../../logger'; import { StorageKeys } from '../../storage'; import { debug } from '../../system/decorators/log'; import { ServerConnection } from './serverConnection'; +const localize = nls.loadMessageBundle(); interface StoredSession { id: string; accessToken: string; @@ -91,7 +93,9 @@ export class SubscriptionAuthenticationProvider implements AuthenticationProvide if (ex === 'Cancelled') throw ex; Logger.error(ex, cc); - void window.showErrorMessage(`Unable to sign in to GitLens+: ${ex}`); + void window.showErrorMessage( + localize('unableToSignInDueToError', 'Unable to sign in to GitLens+: {0}', ex), + ); throw ex; } } diff --git a/src/plus/subscription/serverConnection.ts b/src/plus/subscription/serverConnection.ts index f50bc9f59ce29..c4d1cff710185 100644 --- a/src/plus/subscription/serverConnection.ts +++ b/src/plus/subscription/serverConnection.ts @@ -11,6 +11,7 @@ import { UriHandler, window, } from 'vscode'; +import * as nls from 'vscode-nls'; import { fetch, getProxyAgent, Response } from '@env/fetch'; import { Container } from '../../container'; import { Logger } from '../../logger'; @@ -18,6 +19,7 @@ import { debug, log } from '../../system/decorators/log'; import { memoize } from '../../system/decorators/memoize'; import { DeferredEvent, DeferredEventExecutor, promisifyDeferred } from '../../system/event'; +const localize = nls.loadMessageBundle(); interface AccountInfo { id: string; accountName: string; @@ -238,8 +240,8 @@ export class ServerConnection implements Disposable { private updateStatusBarItem(signingIn?: boolean) { if (signingIn && this._statusBarItem == null) { this._statusBarItem = window.createStatusBarItem('gitlens.plus.signIn', StatusBarAlignment.Left); - this._statusBarItem.name = 'GitLens+ Sign in'; - this._statusBarItem.text = 'Signing in to GitLens+...'; + this._statusBarItem.name = localize('statusBarItem.name', 'GitLens+ Sign in'); + this._statusBarItem.text = localize('statusBar.text', 'Signing in to GitLens+...'); this._statusBarItem.show(); } diff --git a/src/plus/subscription/subscriptionService.ts b/src/plus/subscription/subscriptionService.ts index 89b7905248d19..a1c2e3ddb7db6 100644 --- a/src/plus/subscription/subscriptionService.ts +++ b/src/plus/subscription/subscriptionService.ts @@ -17,6 +17,7 @@ import { Uri, window, } from 'vscode'; +import * as nls from 'vscode-nls'; import { fetch, getProxyAgent } from '@env/fetch'; import { getPlatform } from '@env/platform'; import { configuration } from '../../configuration'; @@ -47,10 +48,10 @@ import { gate } from '../../system/decorators/gate'; import { debug, log } from '../../system/decorators/log'; import { memoize } from '../../system/decorators/memoize'; import { once } from '../../system/function'; -import { pluralize } from '../../system/string'; import { openWalkthrough } from '../../system/utils'; import { ensurePlusFeaturesEnabled } from './utils'; +const localize = nls.loadMessageBundle(); // TODO: What user-agent should we use? const userAgent = 'Visual-Studio-Code-GitLens'; @@ -232,10 +233,17 @@ export class SubscriptionService implements Disposable { } = this._subscription; if (account?.verified === false) { - const confirm: MessageItem = { title: 'Resend Verification', isCloseAffordance: true }; - const cancel: MessageItem = { title: 'Cancel' }; + const confirm: MessageItem = { + title: localize('resendVerification', 'Resend Verification'), + isCloseAffordance: true, + }; + const cancel: MessageItem = { title: localize('cancel', 'Cancel') }; const result = await window.showInformationMessage( - `Before you can access your ${actual.name} account, you must verify your email address.`, + localize( + 'beforeYouAccessAccountYoumustVerifyEmail', + 'Before you can access your {0} account, you must verify your email address.', + actual.name, + ), confirm, cancel, ); @@ -246,14 +254,29 @@ export class SubscriptionService implements Disposable { } else if (isSubscriptionTrial(this._subscription)) { const remaining = getSubscriptionTimeRemaining(this._subscription, 'days'); - const confirm: MessageItem = { title: 'OK', isCloseAffordance: true }; - const learn: MessageItem = { title: 'Learn More' }; + const confirm: MessageItem = { title: localize('ok', 'OK'), isCloseAffordance: true }; + const learn: MessageItem = { title: localize('learnMore', 'Learn More') }; + const daysRemaining = remaining ?? 0; const result = await window.showInformationMessage( - `You are now signed in to your ${ - actual.name - } account which gives you access to GitLens+ features on public repos.\n\nYou were also granted a trial of ${ - effective.name - } for both public and private repos for ${pluralize('more day', remaining ?? 0)}.`, + `${localize( + 'youAreSignedInToYourAccountWithPremiumFeaturesForPublicRepos', + 'You are now signed in to your {0} account which gives you access to GitLens+ features on public repos.', + actual.name, + )} + \n\n${ + daysRemaining === 1 + ? localize( + 'youWereGrantedPremiumTrialForOneMoreDay', + 'You were also granted a trial of {0} for both public and private repos for 1 more day.', + effective.name, + ) + : localize( + 'youWereGrantedPremiumTrialForMoreDays', + 'You were also granted a trial of {0} for both public and private repos for {1} more days.', + effective.name, + daysRemaining, + ) + }`, { modal: true }, confirm, learn, @@ -263,7 +286,10 @@ export class SubscriptionService implements Disposable { void this.learn(); } } else { - void window.showInformationMessage(`You are now signed in to your ${actual.name} account.`, 'OK'); + void window.showInformationMessage( + localize('youAreSignedInToYourAccount', 'You are now signed in to your {0} account.', actual.name), + localize('ok', 'OK'), + ); } } return loggedIn; @@ -345,15 +371,25 @@ export class SubscriptionService implements Disposable { debugger; Logger.error('', cc, `Unable to resend verification email; status=(${rsp.status}): ${rsp.statusText}`); - void window.showErrorMessage(`Unable to resend verification email; Status: ${rsp.statusText}`, 'OK'); + void window.showErrorMessage( + localize( + 'unableToResendVerificationEmailWithStatus', + 'Unable to resend verification email; Status: {0}', + rsp.statusText, + ), + localize('ok', 'OK'), + ); return; } - const confirm = { title: 'Recheck' }; - const cancel = { title: 'Cancel' }; + const confirm = { title: localize('recheck', 'Recheck') }; + const cancel = { title: localize('cancel', 'Cancel') }; const result = await window.showInformationMessage( - "Once you have verified your email address, click 'Recheck'.", + localize( + 'onceYouHaveVerifiedYourEmailClickRecheck', + "Once you have verified your email address, click 'Recheck'.", + ), confirm, cancel, ); @@ -364,7 +400,10 @@ export class SubscriptionService implements Disposable { Logger.error(ex, cc); debugger; - void window.showErrorMessage('Unable to resend verification email', 'OK'); + void window.showErrorMessage( + localize('unableToResendVerificationEmail', 'Unable to resend verification email'), + localize('ok', 'OK'), + ); } } @@ -391,10 +430,17 @@ export class SubscriptionService implements Disposable { void this.showHomeView(); if (plan.effective.id === SubscriptionPlanId.Free) { - const confirm: MessageItem = { title: 'Sign in to GitLens+', isCloseAffordance: true }; - const cancel: MessageItem = { title: 'Cancel' }; + const confirm: MessageItem = { + title: localize('signIn', 'Sign in to GitLens+'), + isCloseAffordance: true, + }; + const cancel: MessageItem = { title: localize('cancel', 'Cancel') }; const result = await window.showInformationMessage( - 'Your GitLens+ features trial has ended.\nPlease sign in to use GitLens+ features on public repos and get a free 7-day trial for both public and private repos.', + `${localize('yourGitLensPremiumTrialHasEnded', 'Your GitLens+ features trial has ended.')} + \n${localize( + 'pleaseSignInToUsePremiumFeatures', + 'Please sign in to use GitLens+ features on public repos and get a free 7-day trial for both public and private repos.', + )}`, { modal: true }, confirm, cancel, @@ -435,10 +481,14 @@ export class SubscriptionService implements Disposable { previewTrial: previewTrial, }); - const confirm: MessageItem = { title: 'OK', isCloseAffordance: true }; - const learn: MessageItem = { title: 'Learn More' }; + const confirm: MessageItem = { title: localize('ok', 'OK'), isCloseAffordance: true }; + const learn: MessageItem = { title: localize('learnMore', 'Learn More') }; const result = await window.showInformationMessage( - `You have started a ${days} day trial of GitLens+ features for both public and private repos.`, + localize( + 'youHaveStartedTrialOfGitlensForNumberOfDays', + 'You have started a {0} day trial of GitLens+ features for both public and private repos.', + days, + ), { modal: true }, confirm, learn, @@ -713,8 +763,13 @@ export class SubscriptionService implements Disposable { } } else { void window.showErrorMessage( - `Unable to sign in to your (${name}) GitLens+ account right now. Please try again in a few minutes. If this issue persists, please contact support. Error=${ex.message}`, - 'OK', + localize( + 'unableToSignIn', + 'Unable to sign in to your ({0}) GitLens+ account right now. Please try again in a few minutes. If this issue persists, please contact support. Error={1}', + name, + ex.message, + ), + localize('ok', 'OK'), ); } } @@ -853,29 +908,56 @@ export class SubscriptionService implements Disposable { ); } - this._statusBarSubscription.name = 'GitLens+ Subscription'; + this._statusBarSubscription.name = localize('gitlensPlusSubscription', 'GitLens+ Subscription'); this._statusBarSubscription.command = Commands.ShowHomeView; if (account?.verified === false) { - this._statusBarSubscription.text = `$(warning) ${effective.name} (Unverified)`; + this._statusBarSubscription.text = `$(warning) ${effective.name} (${localize( + 'account.unverified', + 'Unverified', + )})`; this._statusBarSubscription.backgroundColor = new ThemeColor('statusBarItem.warningBackground'); this._statusBarSubscription.tooltip = new MarkdownString( - trial - ? `**Please verify your email**\n\nBefore you can start your **${effective.name}** trial, please verify the email for the account you created.\n\nClick for details` - : `**Please verify your email**\n\nBefore you can use GitLens+ features, please verify the email for the account you created.\n\nClick for details`, + `**${localize('pleaseVerifyEmail', 'Please verify your email')}** + \n\n${ + trial + ? localize( + 'beforeYouCanStartYourTrialPleaseVerifyEmail', + 'Before you can start your **{0}** trial, please verify the email for the account you created.', + effective.name, + ) + : localize( + 'beforeYouUsePlusFeaturePleaseVerifyEmail', + 'Before you can use GitLens+ features, please verify the email for the account you created.', + ) + } + \n\n${localize('clickForDetails', 'Click for details')}`, true, ); } else { - const remaining = getSubscriptionTimeRemaining(this._subscription, 'days'); + const remaining = getSubscriptionTimeRemaining(this._subscription, 'days') ?? 0; - this._statusBarSubscription.text = `${effective.name} (Trial)`; + this._statusBarSubscription.text = `${effective.name} (${localize('account.trial', 'Trial')})`; this._statusBarSubscription.tooltip = new MarkdownString( - `You are currently trialing **${ - effective.name - }**, which gives you access to GitLens+ features on both public and private repos. You have ${pluralize( - 'day', - remaining ?? 0, - )} remaining in your trial.\n\nClick for details`, + `${localize( + 'youAreTrialingPremiumFeatures', + 'You are currently trialing **{0}**, which gives you access to GitLens+ features on both public and private repos.', + effective.name, + )} + ${ + remaining === 1 + ? localize( + 'youAreTrialingPremiumFeaturesYouHaveOneDayRemaining', + 'You have 1 day remaining in your trial', + ) + : localize( + 'YouHaveNumberOfDaysRemaining', + 'You have {0} days remaining in your trial', + effective.name, + remaining, + ) + } + \n\n${localize('clickForDetails', 'Click for details')}`, true, ); } diff --git a/src/quickpicks/commitPicker.ts b/src/quickpicks/commitPicker.ts index 79650f0227967..88d4de71c28ee 100644 --- a/src/quickpicks/commitPicker.ts +++ b/src/quickpicks/commitPicker.ts @@ -1,4 +1,5 @@ import { Disposable, window } from 'vscode'; +import * as nls from 'vscode-nls'; import { configuration } from '../configuration'; import { Container } from '../container'; import { GitCommit, GitLog, GitStash, GitStashCommit } from '../git/models'; @@ -10,6 +11,7 @@ import { getQuickPickIgnoreFocusOut } from '../system/utils'; import { Directive, DirectiveQuickPickItem } from './items/directive'; import { CommitQuickPickItem } from './items/gitCommands'; +const localize = nls.loadMessageBundle(); export namespace CommitPicker { export async function show( log: GitLog | undefined | Promise, @@ -38,7 +40,7 @@ export namespace CommitPicker { log = await log; if (log == null) { - quickpick.placeholder = 'Unable to show commit history'; + quickpick.placeholder = localize('commitPicker.placeholder', 'Unable to show commit history'); } } @@ -226,7 +228,11 @@ export namespace StashPicker { } if (stash == null || quickpick.items.length <= (options?.showOtherReferences?.length ?? 0)) { - quickpick.placeholder = stash == null ? 'No stashes found' : options?.empty ?? `No matching stashes found`; + quickpick.placeholder = + stash == null + ? localize('stashPicker.placeholder.noStashesFound', 'No stashes found') + : options?.empty ?? + localize('stashPicker.placeholder.noMatchingStashesFound', 'No matching stashes found'); quickpick.items = [DirectiveQuickPickItem.create(Directive.Cancel)]; } diff --git a/src/quickpicks/items/commits.ts b/src/quickpicks/items/commits.ts index 976bddb35ddbc..6a3e2230c0b64 100644 --- a/src/quickpicks/items/commits.ts +++ b/src/quickpicks/items/commits.ts @@ -1,4 +1,5 @@ import { QuickPickItem, window } from 'vscode'; +import * as nls from 'vscode-nls'; import { GitActions } from '../../commands/gitCommands.actions'; import { OpenChangedFilesCommandArgs } from '../../commands/openChangedFiles'; import { QuickCommandButtons } from '../../commands/quickCommand.buttons'; @@ -11,6 +12,7 @@ import { basename } from '../../system/path'; import { pad } from '../../system/string'; import { CommandQuickPickItem } from './common'; +const localize = nls.loadMessageBundle(); export class CommitFilesQuickPickItem extends CommandQuickPickItem { constructor( readonly commit: GitCommit, @@ -25,7 +27,7 @@ export class CommitFilesQuickPickItem extends CommandQuickPickItem { { label: commit.summary, description: `${CommitFormatter.fromTemplate(`\${author}, \${ago} $(git-commit) \${id}`, commit)}${ - options?.unpublished ? ' (unpublished)' : '' + options?.unpublished ? ` (${localize('commitFiles.commitUnpublished', 'unpublished')})` : '' }`, detail: `${ options?.file != null @@ -37,7 +39,7 @@ export class CommitFilesQuickPickItem extends CommandQuickPickItem { : `$(files) ${commit.formatStats({ expand: true, separator: ', ', - empty: 'No files changed', + empty: localize('commitFiles.noFilesChanged', 'No files changed'), })}` }${options?.hint != null ? `${pad(GlyphChars.Dash, 4, 2, GlyphChars.Space)}${options.hint}` : ''}`, alwaysShow: true, @@ -105,8 +107,23 @@ export class CommitBrowseRepositoryFromHereCommandQuickPickItem extends CommandQ ) { super( item ?? - `$(folder-opened) Browse Repository from${executeOptions?.before ? ' Before' : ''} Here${ - executeOptions?.openInNewWindow ? ' in New Window' : '' + `$(folder-opened) ${ + executeOptions?.before + ? executeOptions?.openInNewWindow + ? localize( + 'browseRepositoryFromHere.browseRepositoryFromBeforeHereInNewWindow', + 'Browse Repository from Before Here in New Window', + ) + : localize( + 'browseRepositoryFromHere.browseRepositoryFromBeforeHere', + 'Browse Repository from Before Here', + ) + : executeOptions?.openInNewWindow + ? localize( + 'browseRepositoryFromHere.browseRepositoryFromHereInNewWindow', + 'Browse Repository from Here in New Window', + ) + : localize('browseRepositoryFromHere.browseRepositoryFromHere', 'Browse Repository from Here') }`, ); } @@ -121,7 +138,7 @@ export class CommitBrowseRepositoryFromHereCommandQuickPickItem extends CommandQ export class CommitCompareWithHEADCommandQuickPickItem extends CommandQuickPickItem { constructor(private readonly commit: GitCommit, item?: QuickPickItem) { - super(item ?? '$(compare-changes) Compare with HEAD'); + super(item ?? `$(compare-changes) ${localize('compareWithHead.label', 'Compare with HEAD')}`); } override execute(_options: { preserveFocus?: boolean; preview?: boolean }): Promise { @@ -131,7 +148,7 @@ export class CommitCompareWithHEADCommandQuickPickItem extends CommandQuickPickI export class CommitCompareWithWorkingCommandQuickPickItem extends CommandQuickPickItem { constructor(private readonly commit: GitCommit, item?: QuickPickItem) { - super(item ?? '$(compare-changes) Compare with Working Tree'); + super(item ?? `$(compare-changes) ${localize('compareWithWorking.label', 'Compare with Working Tree')}`); } override execute(_options: { preserveFocus?: boolean; preview?: boolean }): Promise { @@ -141,7 +158,7 @@ export class CommitCompareWithWorkingCommandQuickPickItem extends CommandQuickPi export class CommitCopyIdQuickPickItem extends CommandQuickPickItem { constructor(private readonly commit: GitCommit, item?: QuickPickItem) { - super(item ?? '$(copy) Copy SHA'); + super(item ?? `$(copy) ${localize('copyId.copySha', 'Copy SHA')}`); } override execute(): Promise { @@ -150,13 +167,15 @@ export class CommitCopyIdQuickPickItem extends CommandQuickPickItem { override async onDidPressKey(key: Keys): Promise { await super.onDidPressKey(key); - void window.showInformationMessage('Commit SHA copied to the clipboard'); + void window.showInformationMessage( + localize('copyId.commitShaCopiedToClipboard', 'Commit SHA copied to the clipboard'), + ); } } export class CommitCopyMessageQuickPickItem extends CommandQuickPickItem { constructor(private readonly commit: GitCommit, item?: QuickPickItem) { - super(item ?? '$(copy) Copy Message'); + super(item ?? `$(copy) ${localize('copyMessage.label', 'Copy Message')}`); } override execute(): Promise { @@ -166,14 +185,18 @@ export class CommitCopyMessageQuickPickItem extends CommandQuickPickItem { override async onDidPressKey(key: Keys): Promise { await super.onDidPressKey(key); void window.showInformationMessage( - `${this.commit.stashName ? 'Stash' : 'Commit'} Message copied to the clipboard`, + `${ + this.commit.stashName + ? localize('copyMessage.stashMessageCopiedToClipboard', 'Stash Message copied to the clipboard') + : localize('copyMessage.commitMessageCopiedToClipboard', 'Commit Message copied to the clipboard') + }`, ); } } export class CommitOpenAllChangesCommandQuickPickItem extends CommandQuickPickItem { constructor(private readonly commit: GitCommit, item?: QuickPickItem) { - super(item ?? '$(git-compare) Open All Changes'); + super(item ?? `$(git-compare) ${localize('openAllChanges.label', 'Open All Changes')}`); } override execute(options: { preserveFocus?: boolean; preview?: boolean }): Promise { @@ -183,7 +206,7 @@ export class CommitOpenAllChangesCommandQuickPickItem extends CommandQuickPickIt export class CommitOpenAllChangesWithDiffToolCommandQuickPickItem extends CommandQuickPickItem { constructor(private readonly commit: GitCommit, item?: QuickPickItem) { - super(item ?? '$(git-compare) Open All Changes (difftool)'); + super(item ?? `$(git-compare) ${localize('openAllChangesWithDiffTool.label', 'Open All Changes (difftool)')}`); } override execute(): Promise { @@ -193,7 +216,10 @@ export class CommitOpenAllChangesWithDiffToolCommandQuickPickItem extends Comman export class CommitOpenAllChangesWithWorkingCommandQuickPickItem extends CommandQuickPickItem { constructor(private readonly commit: GitCommit, item?: QuickPickItem) { - super(item ?? '$(git-compare) Open All Changes with Working Tree'); + super( + item ?? + `$(git-compare) ${localize('openAllChangesWithWorking.label', 'Open All Changes with Working Tree')}`, + ); } override execute(options: { preserveFocus?: boolean; preview?: boolean }): Promise { @@ -203,7 +229,7 @@ export class CommitOpenAllChangesWithWorkingCommandQuickPickItem extends Command export class CommitOpenChangesCommandQuickPickItem extends CommandQuickPickItem { constructor(private readonly commit: GitCommit, private readonly file: string | GitFile, item?: QuickPickItem) { - super(item ?? '$(git-compare) Open Changes'); + super(item ?? `$(git-compare) ${localize('openChanges.label', 'Open Changes')}`); } override execute(options: { preserveFocus?: boolean; preview?: boolean }): Promise { @@ -213,7 +239,7 @@ export class CommitOpenChangesCommandQuickPickItem extends CommandQuickPickItem export class CommitOpenChangesWithDiffToolCommandQuickPickItem extends CommandQuickPickItem { constructor(private readonly commit: GitCommit, private readonly file: string | GitFile, item?: QuickPickItem) { - super(item ?? '$(git-compare) Open Changes (difftool)'); + super(item ?? `$(git-compare) ${localize('openChangesWithDiffTool.label', 'Open Changes (difftool)')}`); } override execute(): Promise { @@ -223,7 +249,7 @@ export class CommitOpenChangesWithDiffToolCommandQuickPickItem extends CommandQu export class CommitOpenChangesWithWorkingCommandQuickPickItem extends CommandQuickPickItem { constructor(private readonly commit: GitCommit, private readonly file: string | GitFile, item?: QuickPickItem) { - super(item ?? '$(git-compare) Open Changes with Working File'); + super(item ?? `$(git-compare) ${localize('openChangesWithWorking', 'Open Changes with Working File')}`); } override execute(options: { preserveFocus?: boolean; preview?: boolean }): Promise { @@ -233,7 +259,7 @@ export class CommitOpenChangesWithWorkingCommandQuickPickItem extends CommandQui export class CommitOpenDirectoryCompareCommandQuickPickItem extends CommandQuickPickItem { constructor(private readonly commit: GitCommit, item?: QuickPickItem) { - super(item ?? '$(git-compare) Open Directory Compare'); + super(item ?? `$(git-compare) ${localize('openDirectoryCompare.label', 'Open Directory Compare')}`); } override execute(): Promise { @@ -243,7 +269,13 @@ export class CommitOpenDirectoryCompareCommandQuickPickItem extends CommandQuick export class CommitOpenDirectoryCompareWithWorkingCommandQuickPickItem extends CommandQuickPickItem { constructor(private readonly commit: GitCommit, item?: QuickPickItem) { - super(item ?? '$(git-compare) Open Directory Compare with Working Tree'); + super( + item ?? + `$(git-compare) ${localize( + 'openDirectoryCompareWithWorking.label', + 'Open Directory Compare with Working Tree', + )}`, + ); } override execute(): Promise { @@ -253,7 +285,7 @@ export class CommitOpenDirectoryCompareWithWorkingCommandQuickPickItem extends C export class CommitOpenFilesCommandQuickPickItem extends CommandQuickPickItem { constructor(private readonly commit: GitCommit, item?: QuickPickItem) { - super(item ?? '$(files) Open Files'); + super(item ?? `$(files) ${localize('openFiles.label', 'Open Files')}`); } override execute(_options: { preserveFocus?: boolean; preview?: boolean }): Promise { @@ -263,7 +295,7 @@ export class CommitOpenFilesCommandQuickPickItem extends CommandQuickPickItem { export class CommitOpenFileCommandQuickPickItem extends CommandQuickPickItem { constructor(private readonly commit: GitCommit, private readonly file: string | GitFile, item?: QuickPickItem) { - super(item ?? '$(file) Open File'); + super(item ?? `$(file) ${localize('openFile.label', 'Open File')}`); } override execute(options?: { preserveFocus?: boolean; preview?: boolean }): Promise { @@ -273,7 +305,7 @@ export class CommitOpenFileCommandQuickPickItem extends CommandQuickPickItem { export class CommitOpenRevisionsCommandQuickPickItem extends CommandQuickPickItem { constructor(private readonly commit: GitCommit, item?: QuickPickItem) { - super(item ?? '$(files) Open Files at Revision'); + super(item ?? `$(files) ${localize('openRevisions.label', 'Open Files at Revision')}`); } override execute(_options: { preserveFocus?: boolean; preview?: boolean }): Promise { @@ -283,7 +315,7 @@ export class CommitOpenRevisionsCommandQuickPickItem extends CommandQuickPickIte export class CommitOpenRevisionCommandQuickPickItem extends CommandQuickPickItem { constructor(private readonly commit: GitCommit, private readonly file: string | GitFile, item?: QuickPickItem) { - super(item ?? '$(file) Open File at Revision'); + super(item ?? `$(file) ${localize('openRevision.label', 'Open File at Revision')}`); } override execute(options?: { preserveFocus?: boolean; preview?: boolean }): Promise { @@ -293,7 +325,7 @@ export class CommitOpenRevisionCommandQuickPickItem extends CommandQuickPickItem export class CommitApplyFileChangesCommandQuickPickItem extends CommandQuickPickItem { constructor(private readonly commit: GitCommit, private readonly file: string | GitFile, item?: QuickPickItem) { - super(item ?? 'Apply Changes'); + super(item ?? localize('applyFileChanges.label', 'Apply Changes')); } override async execute(): Promise { @@ -305,8 +337,8 @@ export class CommitRestoreFileChangesCommandQuickPickItem extends CommandQuickPi constructor(private readonly commit: GitCommit, private readonly file: string | GitFile, item?: QuickPickItem) { super( item ?? { - label: 'Restore', - description: 'aka checkout', + label: localize('restoreFileChanges.label', 'Restore'), + description: localize('restoreFileChanges.description', 'aka checkout'), }, ); } @@ -322,6 +354,10 @@ export class OpenChangedFilesCommandQuickPickItem extends CommandQuickPickItem { uris: files.map(f => f.uri), }; - super(item ?? '$(files) Open All Changed Files', Commands.OpenChangedFiles, [commandArgs]); + super( + item ?? `$(files) ${localize('openChangedFiles.label', 'Open All Changed Files')}`, + Commands.OpenChangedFiles, + [commandArgs], + ); } } diff --git a/src/quickpicks/items/directive.ts b/src/quickpicks/items/directive.ts index cab4e8083c7be..d35155e38c370 100644 --- a/src/quickpicks/items/directive.ts +++ b/src/quickpicks/items/directive.ts @@ -1,6 +1,8 @@ import { QuickPickItem } from 'vscode'; +import * as nls from 'vscode-nls'; import type { Subscription } from '../../subscription'; +const localize = nls.loadMessageBundle(); export enum Directive { Back, Cancel, @@ -34,33 +36,44 @@ export namespace DirectiveQuickPickItem { if (label == null) { switch (directive) { case Directive.Back: - label = 'Back'; + label = localize('directive.back.label', 'Back'); break; case Directive.Cancel: - label = 'Cancel'; + label = localize('directive.cancel.label', 'Cancel'); break; case Directive.LoadMore: - label = 'Load more'; + label = localize('directive.loadMore.label', 'Load more'); break; case Directive.Noop: - label = 'Try again'; + label = localize('directive.noop.label', 'Try again'); break; case Directive.StartPreviewTrial: - label = 'Try GitLens+ Features Now'; - detail = 'Try GitLens+ features now, without an account, for 3 days'; + label = localize('directive.startPreviewTrial.label', 'Try GitLens+ Features Now'); + detail = localize( + 'directive.startPreviewTrial.detail', + 'Try GitLens+ features now, without an account, for 3 days', + ); break; case Directive.RequiresVerification: - label = 'Resend Verification Email'; - detail = 'You must verify your account email address before you can continue'; + label = localize('directive.requiresVerification.label', 'Resend Verification Email'); + detail = localize( + 'directive.requiresVerification.detail', + 'You must verify your account email address before you can continue', + ); break; case Directive.RequiresFreeSubscription: - label = 'Sign in to GitLens+'; - detail = - 'To use GitLens+ features on public repos and get a free 7-day trial for both public and private repos'; + label = localize('directive.requiresFreeSubscription.label', 'Sign in to GitLens+'); + detail = localize( + 'directive.requiresFreeSubscription.detail', + 'To use GitLens+ features on public repos and get a free 7-day trial for both public and private repos', + ); break; case Directive.RequiresPaidSubscription: - label = 'Upgrade your account'; - detail = 'To use GitLens+ features on both public and private repos'; + label = localize('directive.requiresPaidSubscription.label', 'Upgrade your account'); + detail = localize( + 'directive.requiresPaidSubscription.detail', + 'To use GitLens+ features on both public and private repos', + ); break; } } diff --git a/src/quickpicks/items/gitCommands.ts b/src/quickpicks/items/gitCommands.ts index a24978f443c3f..cb81798796c2b 100644 --- a/src/quickpicks/items/gitCommands.ts +++ b/src/quickpicks/items/gitCommands.ts @@ -1,4 +1,5 @@ import { QuickInputButton, QuickPickItem } from 'vscode'; +import * as nls from 'vscode-nls'; import type { GitCommandsCommandArgs } from '../../commands/gitCommands'; import { getSteps } from '../../commands/gitCommands.utils'; import { Commands, GlyphChars } from '../../constants'; @@ -20,6 +21,7 @@ import { fromNow } from '../../system/date'; import { pad } from '../../system/string'; import { CommandQuickPickItem, QuickPickItemOfT } from './common'; +const localize = nls.loadMessageBundle(); export class GitCommandQuickPickItem extends CommandQuickPickItem<[GitCommandsCommandArgs]> { constructor(label: string, args: GitCommandsCommandArgs); constructor(item: QuickPickItem, args: GitCommandsCommandArgs); @@ -55,16 +57,16 @@ export namespace BranchQuickPickItem { let description = ''; if (options?.type === true) { if (options.current === true && branch.current) { - description = 'current branch'; + description = localize('branch.description.currentBranch', 'current branch'); } else { - description = 'branch'; + description = localize('branch.description.branch', 'branch'); } } else if (options?.type === 'remote') { if (branch.remote) { - description = 'remote branch'; + description = localize('branch.description.remoteBranch', 'remote branch'); } } else if (options?.current === true && branch.current) { - description = 'current branch'; + description = localize('branch.description.currentBranch', 'current branch'); } if (options?.status && !branch.remote && branch.upstream != null) { @@ -140,7 +142,7 @@ export namespace BranchQuickPickItem { } export class CommitLoadMoreQuickPickItem implements QuickPickItem { - readonly label = 'Load more'; + readonly label = localize('loadMore.label', 'Load more'); readonly alwaysShow = true; } @@ -255,7 +257,10 @@ export namespace RefQuickPickItem { ): RefQuickPickItem { if (ref === '') { return { - label: `${options?.icon ? `$(file-directory)${GlyphChars.Space}` : ''}Working Tree`, + label: `${options?.icon ? `$(file-directory)${GlyphChars.Space}` : ''}${localize( + 'ref.label.workingTree', + 'Working Tree', + )}`, description: '', alwaysShow: options?.alwaysShow, buttons: options?.buttons, @@ -291,7 +296,7 @@ export namespace RefQuickPickItem { if (GitRevision.isRange(ref)) { return { - label: `Range ${gitRef.name}`, + label: localize('ref.range', 'Range {0}', gitRef.name), description: '', alwaysShow: options?.alwaysShow, buttons: options?.buttons, @@ -304,7 +309,7 @@ export namespace RefQuickPickItem { } const item: RefQuickPickItem = { - label: `Commit ${gitRef.name}`, + label: localize('ref.label.commitRef', 'Commit {0}', gitRef.name), description: options?.ref ? `$(git-commit)${GlyphChars.Space}${ref}` : '', alwaysShow: options?.alwaysShow, buttons: options?.buttons, @@ -367,7 +372,11 @@ export namespace RepositoryQuickPickItem { if (options?.fetched) { const lastFetched = await repository.getLastFetched(); if (lastFetched !== 0) { - const fetched = `Last fetched ${fromNow(new Date(lastFetched))}`; + const fetched = localize( + 'repository.description.lastFetchedTime', + 'Last fetched {0}', + fromNow(new Date(lastFetched)), + ); description = `${description ? `${description}${pad(GlyphChars.Dot, 2, 2)}${fetched}` : fetched}`; } } @@ -465,15 +474,23 @@ export namespace WorktreeQuickPickItem { if (options?.status != null) { description += options.status.hasChanges - ? pad(`Uncommited changes (${options.status.getFormattedDiffStatus()})`, description ? 2 : 0, 0) - : pad('No changes', description ? 2 : 0, 0); + ? pad( + localize( + 'workTree.description.uncommitedChanges', + 'Uncommited changes ({0})', + options.status.getFormattedDiffStatus(), + ), + description ? 2 : 0, + 0, + ) + : pad(localize('workTree.description.noChanges', 'No changes'), description ? 2 : 0, 0); } let icon; let label; switch (worktree.type) { case 'bare': - label = '(bare)'; + label = `(${localize('workTree.label.bare', 'bare')})`; icon = '$(folder)'; break; case 'branch': @@ -489,7 +506,9 @@ export namespace WorktreeQuickPickItem { const item: WorktreeQuickPickItem = { label: `${icon}${GlyphChars.Space}${label}${options?.checked ? pad('$(check)', 2) : ''}`, description: description, - detail: options?.path ? `In $(folder) ${worktree.friendlyPath}` : undefined, + detail: options?.path + ? localize('worktree.inWorktreePath', 'In {0}', `$(folder) ${worktree.friendlyPath}`) + : undefined, alwaysShow: options?.alwaysShow, buttons: options?.buttons, picked: picked, diff --git a/src/quickpicks/modePicker.ts b/src/quickpicks/modePicker.ts index 65b5bfdcb1778..792d3742f98cb 100644 --- a/src/quickpicks/modePicker.ts +++ b/src/quickpicks/modePicker.ts @@ -1,7 +1,9 @@ import { QuickPickItem, window } from 'vscode'; +import * as nls from 'vscode-nls'; import { GlyphChars } from '../constants'; import { Container } from '../container'; +const localize = nls.loadMessageBundle(); export interface ModesQuickPickItem extends QuickPickItem { key: string | undefined; } @@ -19,9 +21,11 @@ export namespace ModePicker { const items = modeKeys.map(key => { const modeCfg = modes[key]; const item: ModesQuickPickItem = { - label: `${mode === key ? '$(check)\u00a0\u00a0' : '\u00a0\u00a0\u00a0\u00a0\u00a0'}${ - modeCfg.name - } mode`, + label: `${mode === key ? '$(check)\u00a0\u00a0' : '\u00a0\u00a0\u00a0\u00a0\u00a0'}${localize( + 'mode', + '{0} mode', + modeCfg.name, + )}`, description: modeCfg.description ? `\u00a0${GlyphChars.Dash}\u00a0 ${modeCfg.description}` : '', key: key, }; @@ -30,13 +34,13 @@ export namespace ModePicker { if (mode) { items.splice(0, 0, { - label: `Exit ${modes[mode].name} mode`, + label: localize('label', 'Exit {0} mode', modes[mode].name), key: undefined, }); } const pick = await window.showQuickPick(items, { - placeHolder: 'select a GitLens mode to enter', + placeHolder: localize('placeholder', 'select a GitLens mode to enter'), }); return pick; diff --git a/src/quickpicks/referencePicker.ts b/src/quickpicks/referencePicker.ts index ea2eb3899391a..cb256e9d5e7c3 100644 --- a/src/quickpicks/referencePicker.ts +++ b/src/quickpicks/referencePicker.ts @@ -1,4 +1,5 @@ import { CancellationTokenSource, Disposable, QuickPick, window } from 'vscode'; +import * as nls from 'vscode-nls'; import { GitActions } from '../commands/gitCommands.actions'; import { getBranchesAndOrTags, getValidateGitReferenceFn, QuickCommandButtons } from '../commands/quickCommand'; import { GlyphChars } from '../constants'; @@ -8,6 +9,7 @@ import { KeyboardScope, Keys } from '../keyboard'; import { getQuickPickIgnoreFocusOut } from '../system/utils'; import { BranchQuickPickItem, RefQuickPickItem, TagQuickPickItem } from './items/gitCommands'; +const localize = nls.loadMessageBundle(); export type ReferencesQuickPickItem = BranchQuickPickItem | TagQuickPickItem | RefQuickPickItem; export const enum ReferencesQuickPickIncludes { @@ -43,7 +45,10 @@ export namespace ReferencePicker { quickpick.title = title; quickpick.placeholder = options.allowEnteringRefs != null - ? `${placeHolder}${GlyphChars.Space.repeat(3)}(or enter a reference using #)` + ? `${placeHolder}${GlyphChars.Space.repeat(3)}(${localize( + 'placeholder.orEnterReferenceUsingHashChar', + 'or enter a reference using #', + )})` : placeHolder; quickpick.matchOnDescription = true; diff --git a/src/quickpicks/remoteProviderPicker.ts b/src/quickpicks/remoteProviderPicker.ts index bc59f484b1743..f7b90930d3d5c 100644 --- a/src/quickpicks/remoteProviderPicker.ts +++ b/src/quickpicks/remoteProviderPicker.ts @@ -1,4 +1,5 @@ import { Disposable, env, QuickInputButton, ThemeIcon, Uri, window } from 'vscode'; +import * as nls from 'vscode-nls'; import type { OpenOnRemoteCommandArgs } from '../commands'; import { Commands, GlyphChars } from '../constants'; import { Container } from '../container'; @@ -8,9 +9,15 @@ import { Keys } from '../keyboard'; import { CommandQuickPickItem } from '../quickpicks/items/common'; import { getQuickPickIgnoreFocusOut } from '../system/utils'; +const localize = nls.loadMessageBundle(); export class ConfigureCustomRemoteProviderCommandQuickPickItem extends CommandQuickPickItem { constructor() { - super({ label: 'See how to configure a custom remote provider...' }); + super({ + label: localize( + 'configureCustomRemoteProviderCommandQuickPickItem.label', + 'See how to configure a custom remote provider...', + ), + }); } override async execute(): Promise { @@ -99,9 +106,20 @@ export class CopyRemoteResourceCommandQuickPickItem extends CommandQuickPickItem clipboard: true, }; super( - `$(copy) Copy ${providers?.length ? providers[0].name : 'Remote'} ${getNameFromRemoteResource( - resource, - )} Url${providers?.length === 1 ? '' : GlyphChars.Ellipsis}`, + `$(copy) ${ + providers?.length + ? localize( + 'copyRemoteResourceCommandQuickPickItem.label.copyProviderUrl', + 'Copy {0} {1} Url', + providers[0].name, + getNameFromRemoteResource(resource), + ) + : localize( + 'copyRemoteResourceCommandQuickPickItem.label.copyRemoteUrl', + 'Copy Remote {0} Url', + getNameFromRemoteResource(resource), + ) + }${providers?.length === 1 ? '' : GlyphChars.Ellipsis}`, Commands.OpenOnRemote, [commandArgs], ); @@ -109,7 +127,7 @@ export class CopyRemoteResourceCommandQuickPickItem extends CommandQuickPickItem override async onDidPressKey(key: Keys): Promise { await super.onDidPressKey(key); - void window.showInformationMessage('Url copied to the clipboard'); + void window.showInformationMessage(localize('urlCopiedToClipboard', 'Url copied to the clipboard')); } } @@ -122,10 +140,28 @@ export class OpenRemoteResourceCommandQuickPickItem extends CommandQuickPickItem clipboard: false, }; super( - `$(link-external) Open ${getNameFromRemoteResource(resource)} on ${ + `$(link-external) ${ providers?.length === 1 - ? providers[0].name - : `${providers?.length ? providers[0].name : 'Remote'}${GlyphChars.Ellipsis}` + ? localize( + 'openRemoteResourceCommandQuickPickItem.label.openResourceOnProvider', + 'Open {0} on {1}', + getNameFromRemoteResource(resource), + providers[0].name, + ) + : `${ + providers?.length + ? localize( + 'openRemoteResourceCommandQuickPickItem.label.openResourceOnProvider', + 'Open {0} on {1}', + getNameFromRemoteResource(resource), + providers[0].name, + ) + : localize( + 'openRemoteResourceCommandQuickPickItem.label.openResourceOnRemote', + 'Open {0} on Remote', + getNameFromRemoteResource(resource), + ) + }${GlyphChars.Ellipsis}` }`, Commands.OpenOnRemote, [commandArgs], @@ -136,7 +172,7 @@ export class OpenRemoteResourceCommandQuickPickItem extends CommandQuickPickItem namespace QuickCommandButtons { export const SetRemoteAsDefault: QuickInputButton = { iconPath: new ThemeIcon('settings-gear'), - tooltip: 'Set as Default Remote', + tooltip: localize('setRemoteAsDefault.tooltip', 'Set as Default Remote'), }; } @@ -153,7 +189,10 @@ export namespace RemoteProviderPicker { let items: (ConfigureCustomRemoteProviderCommandQuickPickItem | CopyOrOpenRemoteCommandQuickPickItem)[]; if (remotes.length === 0) { items = [new ConfigureCustomRemoteProviderCommandQuickPickItem()]; - placeHolder = 'No auto-detected or configured remote providers found'; + placeHolder = localize( + 'placeholder.noAutoDetectedOrConfiguredRemoteProvidersFound', + 'No auto-detected or configured remote providers found', + ); } else { if (autoPick === 'default' && remotes.length > 1) { // If there is a default just execute it directly diff --git a/src/quickpicks/repositoryPicker.ts b/src/quickpicks/repositoryPicker.ts index 5c52dcbaca0ba..cb1796e76522f 100644 --- a/src/quickpicks/repositoryPicker.ts +++ b/src/quickpicks/repositoryPicker.ts @@ -1,4 +1,5 @@ import { Disposable, TextEditor, Uri, window } from 'vscode'; +import * as nls from 'vscode-nls'; import { Container } from '../container'; import { Repository } from '../git/models'; import { map } from '../system/iterable'; @@ -6,6 +7,7 @@ import { getQuickPickIgnoreFocusOut } from '../system/utils'; import { CommandQuickPickItem } from './items/common'; import { RepositoryQuickPickItem } from './items/gitCommands'; +const localize = nls.loadMessageBundle(); export namespace RepositoryPicker { export async function getBestRepositoryOrShow( uri: Uri | undefined, @@ -44,7 +46,7 @@ export namespace RepositoryPicker { export async function show( title: string | undefined, - placeholder: string = 'Choose a repository', + placeholder: string = localize('placeholder', 'Choose a repository'), repositories?: Repository[], ): Promise { const items: RepositoryQuickPickItem[] = await Promise.all([ diff --git a/src/statusbar/statusBarController.ts b/src/statusbar/statusBarController.ts index decc2288a0422..86a328f6db64b 100644 --- a/src/statusbar/statusBarController.ts +++ b/src/statusbar/statusBarController.ts @@ -10,6 +10,7 @@ import { Uri, window, } from 'vscode'; +import * as nls from 'vscode-nls'; import type { ToggleFileChangesAnnotationCommandArgs } from '../commands/toggleFileAnnotations'; import { configuration, FileAnnotationType, StatusBarCommand } from '../configuration'; import { Commands, GlyphChars } from '../constants'; @@ -25,6 +26,7 @@ import { PromiseCancelledError } from '../system/promise'; import { isTextEditor } from '../system/utils'; import { LinesChangeEvent } from '../trackers/gitLineTracker'; +const localize = nls.loadMessageBundle(); export class StatusBarController implements Disposable { private _pullRequestCancellation: CancellationTokenSource | undefined; private _tooltipCancellation: CancellationTokenSource | undefined; @@ -81,11 +83,14 @@ export class StatusBarController implements Disposable { alignment, alignment === StatusBarAlignment.Right ? 999 : 1, ); - this._statusBarMode.name = 'GitLens Modes'; + this._statusBarMode.name = localize('statusBar.mode.name', 'GitLens Modes'); this._statusBarMode.command = Commands.SwitchMode; this._statusBarMode.text = mode.statusBarItemName; this._statusBarMode.tooltip = new MarkdownString( - `**${mode.statusBarItemName}** ${GlyphChars.Dash} ${mode.description}\n\n---\n\nClick to Switch GitLens Mode`, + `**${mode.statusBarItemName}** ${GlyphChars.Dash} ${mode.description}\n\n---\n\n${localize( + 'statusBar.mode.tooltip', + 'Click to Switch GitLens Mode', + )}`, true, ); this._statusBarMode.show(); @@ -117,7 +122,7 @@ export class StatusBarController implements Disposable { alignment, alignment === StatusBarAlignment.Right ? 1000 : 0, ); - this._statusBarBlame.name = 'GitLens Current Line Blame'; + this._statusBarBlame.name = localize('statusBar.blame.name', 'GitLens Current Line Blame'); this._statusBarBlame.command = this.container.config.statusBar.command; if (configuration.changed(e, 'statusBar.enabled')) { @@ -227,54 +232,57 @@ export class StatusBarController implements Disposable { let tooltip: string; switch (cfg.command) { case StatusBarCommand.CopyRemoteCommitUrl: - tooltip = 'Click to Copy Remote Commit Url'; + tooltip = localize('command.copyRemoteCommitUrl.tooltip', 'Click to Copy Remote Commit Url'); break; case StatusBarCommand.CopyRemoteFileUrl: this._statusBarBlame.command = Commands.CopyRemoteFileUrl; - tooltip = 'Click to Copy Remote File Revision Url'; + tooltip = localize('command.copyRemoteFileUrl.tooltip', 'Click to Copy Remote File Revision Url'); break; case StatusBarCommand.DiffWithPrevious: this._statusBarBlame.command = Commands.DiffLineWithPrevious; - tooltip = 'Click to Open Line Changes with Previous Revision'; + tooltip = localize( + 'command.diffWithPrevious.tooltip', + 'Click to Open Line Changes with Previous Revision', + ); break; case StatusBarCommand.DiffWithWorking: this._statusBarBlame.command = Commands.DiffLineWithWorking; - tooltip = 'Click to Open Line Changes with Working File'; + tooltip = localize('command.diffWithWorking.tooltip', 'Click to Open Line Changes with Working File'); break; case StatusBarCommand.OpenCommitOnRemote: - tooltip = 'Click to Open Commit on Remote'; + tooltip = localize('command.openCommitOnRemote.tooltip', 'Click to Open Commit on Remote'); break; case StatusBarCommand.OpenFileOnRemote: - tooltip = 'Click to Open Revision on Remote'; + tooltip = localize('command.openFileOnRemote.tooltip', 'Click to Open Revision on Remote'); break; case StatusBarCommand.RevealCommitInView: - tooltip = 'Click to Reveal Commit in the Side Bar'; + tooltip = localize('command.revealCommitInView.tooltip', 'Click to Reveal Commit in the Side Bar'); break; case StatusBarCommand.ShowCommitsInView: - tooltip = 'Click to Search for Commit'; + tooltip = localize('command.showCommitsInView.tooltip', 'Click to Search for Commit'); break; case StatusBarCommand.ShowQuickCommitDetails: - tooltip = 'Click to Show Commit'; + tooltip = localize('command.showQuickCommitDetails.tooltip', 'Click to Show Commit'); break; case StatusBarCommand.ShowQuickCommitFileDetails: - tooltip = 'Click to Show Commit (file)'; + tooltip = localize('command.showQuickCommitFileDetails.tooltip', 'Click to Show Commit (file)'); break; case StatusBarCommand.ShowQuickCurrentBranchHistory: - tooltip = 'Click to Show Branch History'; + tooltip = localize('command.showQuickCurrentBranchHistory.tooltip', 'Click to Show Branch History'); break; case StatusBarCommand.ShowQuickFileHistory: - tooltip = 'Click to Show File History'; + tooltip = localize('command.showQuickFileHistory.tooltip', 'Click to Show File History'); break; case StatusBarCommand.ToggleCodeLens: - tooltip = 'Click to Toggle Git CodeLens'; + tooltip = localize('command.toggleCodeLens.tooltip', 'Click to Toggle Git CodeLens'); break; case StatusBarCommand.ToggleFileBlame: - tooltip = 'Click to Toggle File Blame'; + tooltip = localize('command.toggleFileBlame.tooltip', 'Click to Toggle File Blame'); break; case StatusBarCommand.ToggleFileChanges: { if (commit.file != null) { this._statusBarBlame.command = asCommand<[Uri, ToggleFileChangesAnnotationCommandArgs]>({ - title: 'Toggle File Changes', + title: localize('command.toggleFileChanges.title', 'Toggle File Changes'), command: Commands.ToggleFileChanges, arguments: [ commit.file.uri, @@ -285,13 +293,13 @@ export class StatusBarController implements Disposable { ], }); } - tooltip = 'Click to Toggle File Changes'; + tooltip = localize('command.toggleFileChanges.tooltip', 'Click to Toggle File Changes'); break; } case StatusBarCommand.ToggleFileChangesOnly: { if (commit.file != null) { this._statusBarBlame.command = asCommand<[Uri, ToggleFileChangesAnnotationCommandArgs]>({ - title: 'Toggle File Changes', + title: localize('command.toggleFileChangesOnly.title', 'Toggle File Changes'), command: Commands.ToggleFileChanges, arguments: [ commit.file.uri, @@ -302,11 +310,11 @@ export class StatusBarController implements Disposable { ], }); } - tooltip = 'Click to Toggle File Changes'; + tooltip = localize('command.toggleFileChangesOnly.tooltip', 'Click to Toggle File Changes'); break; } case StatusBarCommand.ToggleFileHeatmap: - tooltip = 'Click to Toggle File Heatmap'; + tooltip = localize('command.toggleFileHeatmap.tooltip', 'Click to Toggle File Heatmap'); break; } diff --git a/src/terminal/linkProvider.ts b/src/terminal/linkProvider.ts index 295bec3acb73a..59aa296973752 100644 --- a/src/terminal/linkProvider.ts +++ b/src/terminal/linkProvider.ts @@ -1,4 +1,5 @@ import { commands, Disposable, TerminalLink, TerminalLinkContext, TerminalLinkProvider, window } from 'vscode'; +import * as nls from 'vscode-nls'; import type { GitCommandsCommandArgs, ShowQuickBranchHistoryCommandArgs, @@ -9,6 +10,7 @@ import { Container } from '../container'; import { PagedResult } from '../git/gitProvider'; import { GitBranch, GitReference, GitTag } from '../git/models'; +const localize = nls.loadMessageBundle(); const commandsRegexShared = /\b(g(?:it)?\b\s*)\b(branch|checkout|cherry-pick|fetch|grep|log|merge|pull|push|rebase|reset|revert|show|stash|status|tag)\b/gi; // Since negative lookbehind isn't supported in all browsers, leave out the negative lookbehind condition `(? = { startIndex: match.index + git.length, length: command.length, - tooltip: 'Open in Git Command Palette', + tooltip: localize('openInGitCommandPalette', 'Open in Git Command Palette'), command: { command: Commands.GitCommands, args: { @@ -78,7 +80,7 @@ export class GitTerminalLinkProvider implements Disposable, TerminalLinkProvider const link: GitTerminalLink = { startIndex: match.index, length: ref.length, - tooltip: 'Show HEAD', + tooltip: localize('showHead', 'Show HEAD'), command: { command: Commands.ShowQuickBranchHistory, args: { @@ -102,7 +104,7 @@ export class GitTerminalLinkProvider implements Disposable, TerminalLinkProvider const link: GitTerminalLink = { startIndex: match.index, length: ref.length, - tooltip: 'Show Branch', + tooltip: localize('showBranch', 'Show Branch'), command: { command: Commands.ShowQuickBranchHistory, args: { repoPath: repoPath, branch: branch.name }, @@ -123,7 +125,7 @@ export class GitTerminalLinkProvider implements Disposable, TerminalLinkProvider const link: GitTerminalLink = { startIndex: match.index, length: ref.length, - tooltip: 'Show Tag', + tooltip: localize('showTag', 'Show Tag'), command: { command: Commands.ShowQuickBranchHistory, args: { repoPath: repoPath, tag: tag.name }, @@ -139,7 +141,7 @@ export class GitTerminalLinkProvider implements Disposable, TerminalLinkProvider const link: GitTerminalLink = { startIndex: match.index, length: ref.length, - tooltip: 'Show Commits', + tooltip: localize('showCommits', 'Show Commits'), command: { command: Commands.GitCommands, args: { @@ -161,7 +163,7 @@ export class GitTerminalLinkProvider implements Disposable, TerminalLinkProvider const link: GitTerminalLink = { startIndex: match.index, length: ref.length, - tooltip: 'Show Commit', + tooltip: localize('showCommit', 'Show Commit'), command: { command: Commands.ShowQuickCommit, args: { diff --git a/src/views/branchesView.ts b/src/views/branchesView.ts index 7c62369b67e92..23b190d6e520b 100644 --- a/src/views/branchesView.ts +++ b/src/views/branchesView.ts @@ -8,6 +8,7 @@ import { TreeItemCollapsibleState, window, } from 'vscode'; +import * as nls from 'vscode-nls'; import { BranchesViewConfig, configuration, @@ -40,6 +41,8 @@ import { } from './nodes'; import { ViewBase } from './viewBase'; +const localize = nls.loadMessageBundle(); + export class BranchesRepositoryNode extends RepositoryFolderNode { async getChildren(): Promise { if (this.child == null) { @@ -68,7 +71,7 @@ export class BranchesViewNode extends RepositoriesSubscribeableNode !b.remote }); if (branches.values.length === 0) { - this.view.message = 'No branches could be found.'; - this.view.title = 'Branches'; + this.view.message = localize('noBranchesFound', 'No branches could be found.'); + this.view.title = localize('branches', 'Branches'); void child.ensureSubscription(); @@ -95,7 +98,7 @@ export class BranchesViewNode extends RepositoriesSubscribeableNode protected readonly configKey = 'branches'; constructor(container: Container) { - super('gitlens.views.branches', 'Branches', container); + super('gitlens.views.branches', localize('branches', 'Branches'), container); } override get canReveal(): boolean { @@ -285,7 +288,11 @@ export class BranchesView extends ViewBase return window.withProgress( { location: ProgressLocation.Notification, - title: `Revealing ${GitReference.toString(branch, { icon: false, quoted: true })} in the side bar...`, + title: localize( + 'revealingBranchInSideBar', + 'Revealing {0} in the side bar...', + GitReference.toString(branch, { icon: false, quoted: true }), + ), cancellable: true, }, async (progress, token) => { @@ -311,7 +318,11 @@ export class BranchesView extends ViewBase return window.withProgress( { location: ProgressLocation.Notification, - title: `Revealing ${GitReference.toString(commit, { icon: false, quoted: true })} in the side bar...`, + title: localize( + 'revealingCommitInSideBar', + 'Revealing {0} in the side bar...', + GitReference.toString(commit, { icon: false, quoted: true }), + ), cancellable: true, }, async (progress, token) => { diff --git a/src/views/commitsView.ts b/src/views/commitsView.ts index 4d623b9cce4b8..d037adb253848 100644 --- a/src/views/commitsView.ts +++ b/src/views/commitsView.ts @@ -8,6 +8,7 @@ import { TreeItemCollapsibleState, window, } from 'vscode'; +import * as nls from 'vscode-nls'; import { CommitsViewConfig, configuration, ViewFilesLayout, ViewShowBranchComparison } from '../configuration'; import { Commands, ContextKeys, GlyphChars } from '../constants'; import { Container } from '../container'; @@ -36,12 +37,14 @@ import { } from './nodes'; import { ViewBase } from './viewBase'; +const localize = nls.loadMessageBundle(); + export class CommitsRepositoryNode extends RepositoryFolderNode { async getChildren(): Promise { if (this.child == null) { const branch = await this.repo.getBranch(); if (branch == null) { - this.view.message = 'No commits could be found.'; + this.view.message = localize('noCommitsFound', 'No commits could be found.'); return []; } @@ -126,7 +129,7 @@ export class CommitsViewNode extends RepositoriesSubscribeableNode { protected readonly configKey = 'commits'; constructor(container: Container) { - super('gitlens.views.commits', 'Commits', container); + super('gitlens.views.commits', localize('commits', 'Commits'), container); + this.title = localize('commits', 'Commits'); } override get canReveal(): boolean { @@ -345,7 +357,11 @@ export class CommitsView extends ViewBase { return window.withProgress( { location: ProgressLocation.Notification, - title: `Revealing ${GitReference.toString(commit, { icon: false, quoted: true })} in the side bar...`, + title: localize( + 'revealingCommitInSideBar', + 'Revealing {0} in the side bar...', + GitReference.toString(commit, { icon: false, quoted: true }), + ), cancellable: true, }, async (progress, token) => { diff --git a/src/views/contributorsView.ts b/src/views/contributorsView.ts index d100ef23eed45..c5b0ae34f2bdb 100644 --- a/src/views/contributorsView.ts +++ b/src/views/contributorsView.ts @@ -8,6 +8,7 @@ import { TreeItemCollapsibleState, window, } from 'vscode'; +import * as nls from 'vscode-nls'; import { Avatars } from '../avatars'; import { configuration, ContributorsViewConfig, ViewFilesLayout } from '../configuration'; import { Commands } from '../constants'; @@ -27,6 +28,8 @@ import { } from './nodes'; import { ViewBase } from './viewBase'; +const localize = nls.loadMessageBundle(); + export class ContributorsRepositoryNode extends RepositoryFolderNode { async getChildren(): Promise { if (this.child == null) { @@ -60,7 +63,7 @@ export class ContributorsViewNode extends RepositoriesSubscribeableNode { diff --git a/src/views/fileHistoryView.ts b/src/views/fileHistoryView.ts index 9337c58b79403..db3459b3528b1 100644 --- a/src/views/fileHistoryView.ts +++ b/src/views/fileHistoryView.ts @@ -1,4 +1,5 @@ import { commands, ConfigurationChangeEvent, Disposable } from 'vscode'; +import * as nls from 'vscode-nls'; import { configuration, FileHistoryViewConfig } from '../configuration'; import { Commands, ContextKeys } from '../constants'; import { Container } from '../container'; @@ -8,7 +9,8 @@ import { executeCommand } from '../system/command'; import { FileHistoryTrackerNode, LineHistoryTrackerNode } from './nodes'; import { ViewBase } from './viewBase'; -const pinnedSuffix = ' (pinned)'; +const localize = nls.loadMessageBundle(); +const pinnedSuffix = ` ${localize('pinnedSuffix', '(pinned)')}`; export class FileHistoryView extends ViewBase { protected readonly configKey = 'fileHistory'; @@ -17,7 +19,7 @@ export class FileHistoryView extends ViewBase { protected readonly configKey = 'lineHistory'; constructor(container: Container) { - super('gitlens.views.lineHistory', 'Line History', container); + super('gitlens.views.lineHistory', localize('lineHistory', 'Line History'), container); void setContext(ContextKeys.ViewsLineHistoryEditorFollowing, true); } diff --git a/src/views/nodes/UncommittedFileNode.ts b/src/views/nodes/UncommittedFileNode.ts index e7106f05c0c9b..7014cc3aa3014 100644 --- a/src/views/nodes/UncommittedFileNode.ts +++ b/src/views/nodes/UncommittedFileNode.ts @@ -1,4 +1,5 @@ import { Command, TreeItem, TreeItemCollapsibleState } from 'vscode'; +import * as nls from 'vscode-nls'; import { DiffWithPreviousCommandArgs } from '../../commands'; import { Commands } from '../../constants'; import { StatusFileFormatter } from '../../git/formatters'; @@ -9,6 +10,7 @@ import { ViewsWithCommits } from '../viewBase'; import { FileNode } from './folderNode'; import { ContextValues, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class UncommittedFileNode extends ViewNode implements FileNode { public readonly file: GitFile; public readonly repoPath: string; @@ -115,7 +117,7 @@ export class UncommittedFileNode extends ViewNode implements F }, }; return { - title: 'Open Changes with Previous Revision', + title: localize('openChangesWithPreviousRevision', 'Open Changes with Previous Revision'), command: Commands.DiffWithPrevious, arguments: [undefined, commandArgs], }; diff --git a/src/views/nodes/UncommittedFilesNode.ts b/src/views/nodes/UncommittedFilesNode.ts index 485ae5dd01b6e..861467baa3db8 100644 --- a/src/views/nodes/UncommittedFilesNode.ts +++ b/src/views/nodes/UncommittedFilesNode.ts @@ -1,5 +1,6 @@ 'use strict'; import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from 'vscode'; +import * as nls from 'vscode-nls'; import { ViewFilesLayout } from '../../config'; import { GitUri } from '../../git/gitUri'; import { @@ -22,6 +23,7 @@ import { RepositoryNode } from './repositoryNode'; import { UncommittedFileNode } from './UncommittedFileNode'; import { ContextValues, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class UncommittedFilesNode extends ViewNode { static key = ':uncommitted-files'; static getId(repoPath: string): string { @@ -103,7 +105,10 @@ export class UncommittedFilesNode extends ViewNode { ? ContextValues.PullRequest : ContextValues.AutolinkedIssue; - const linkTitle = ` "Open ${ - this.issue.type === IssueOrPullRequestType.PullRequest ? 'Pull Request' : 'Issue' - } \\#${this.issue.id} on ${this.issue.provider.name}"`; + const linkTitle = + this.issue.type === IssueOrPullRequestType.PullRequest + ? localize( + 'openPullRequest', + 'Open Pull Request \\#{0} on {1}', + this.issue.id, + this.issue.provider.name, + ) + : localize('openIssue', 'Open Issue \\#{0} on {1}', this.issue.id, this.issue.provider.name); const tooltip = new MarkdownString( `${IssueOrPullRequest.getMarkdownIcon(this.issue)} [**${this.issue.title.trim()}**](${ this.issue.url - }${linkTitle}) \\\n[#${this.issue.id}](${this.issue.url}${linkTitle}) was ${ - this.issue.closed ? 'closed' : 'opened' + }${linkTitle}) ${ + this.issue.closed + ? localize( + 'issueWasClosed', + '{0} was closed', + `\\\n[#${this.issue.id}](${this.issue.url}${linkTitle})`, + ) + : localize( + 'issueWasOpened', + '{0} was opened', + `\\\n[#${this.issue.id}](${this.issue.url}${linkTitle})`, + ) } ${relativeTime}`, true, ); diff --git a/src/views/nodes/autolinkedItemsNode.ts b/src/views/nodes/autolinkedItemsNode.ts index b7bd448f93472..5ada3e1843410 100644 --- a/src/views/nodes/autolinkedItemsNode.ts +++ b/src/views/nodes/autolinkedItemsNode.ts @@ -1,4 +1,5 @@ import { TreeItem, TreeItemCollapsibleState } from 'vscode'; +import * as nls from 'vscode-nls'; import { GitUri } from '../../git/gitUri'; import { GitFile, GitLog, GitRemote, IssueOrPullRequest, PullRequest } from '../../git/models'; import { RichRemoteProvider } from '../../git/remotes/provider'; @@ -11,6 +12,7 @@ import { LoadMoreNode, MessageNode } from './common'; import { PullRequestNode } from './pullRequestNode'; import { ContextValues, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export interface FilesQueryResults { label: string; files: GitFile[] | undefined; @@ -80,14 +82,20 @@ export class AutolinkedItemsNode extends ViewNode { } if (children == null || children.length === 0) { - children = [new MessageNode(this.view, this, 'No autolinked issues or pull requests could be found.')]; + children = [ + new MessageNode( + this.view, + this, + localize('noAutolinkedIssuesFound', 'No autolinked issues or pull requests could be found.'), + ), + ]; } if (this.log.hasMore) { children.push( new LoadMoreNode(this.view, this.parent as any, children[children.length - 1], { context: { expandAutolinks: true }, - message: 'Load more commits to search for autolinks', + message: localize('loadMoreCommitsToSearch', 'Load more commits to search for autolinks'), }), ); } @@ -99,7 +107,7 @@ export class AutolinkedItemsNode extends ViewNode { getTreeItem(): TreeItem { const item = new TreeItem( - 'Autolinked Issues and Pull Requests', + localize('autolinkedIssuesAndPullRequests', 'Autolinked Issues and Pull Requests'), this.expand ? TreeItemCollapsibleState.Expanded : TreeItemCollapsibleState.Collapsed, ); item.id = this.id; diff --git a/src/views/nodes/branchNode.ts b/src/views/nodes/branchNode.ts index 0e873538fd2ec..1e18ca68200f9 100644 --- a/src/views/nodes/branchNode.ts +++ b/src/views/nodes/branchNode.ts @@ -1,4 +1,5 @@ import { MarkdownString, ThemeColor, ThemeIcon, TreeItem, TreeItemCollapsibleState, Uri, window } from 'vscode'; +import * as nls from 'vscode-nls'; import { ViewBranchesLayout, ViewShowBranchComparison } from '../../configuration'; import { Colors, GlyphChars } from '../../constants'; import { Container } from '../../container'; @@ -31,6 +32,7 @@ import { RebaseStatusNode } from './rebaseStatusNode'; import { RepositoryNode } from './repositoryNode'; import { ContextValues, PageableViewNode, ViewNode, ViewRefNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class BranchNode extends ViewRefNode implements PageableViewNode @@ -104,7 +106,7 @@ export class BranchNode } get label(): string { - if (this.options.showAsCommits) return 'Commits'; + if (this.options.showAsCommits) return localize('commits', 'Commits'); const branchName = this.branch.getNameWithoutRemote(); return `${ @@ -116,7 +118,7 @@ export class BranchNode this.branch.starred ? branchName : this.branch.getBasename() - }${this.branch.rebasing ? ' (Rebasing)' : ''}`; + }${this.branch.rebasing ? ` ${localize('rebasing', '(Rebasing)')}` : ''}`; } get ref(): GitBranchReference { @@ -164,7 +166,9 @@ export class BranchNode : undefined, ], ); - if (log == null) return [new MessageNode(this.view, this, 'No commits could be found.')]; + if (log == null) { + return [new MessageNode(this.view, this, localize('noCommitsFound', 'No commits could be found.'))]; + } const children = []; @@ -302,9 +306,7 @@ export class BranchNode async getTreeItem(): Promise { this.splatted = false; - let tooltip: string | MarkdownString = `${ - this.current ? 'Current branch' : 'Branch' - } $(git-branch) ${this.branch.getNameWithoutRemote()}${this.branch.rebasing ? ' (Rebasing)' : ''}`; + let tooltip: string | MarkdownString = ''; let contextValue: string = ContextValues.Branch; if (this.current) { @@ -326,6 +328,7 @@ export class BranchNode let color: ThemeColor | undefined; let description; let iconSuffix = ''; + if (!this.branch.remote) { if (this.branch.upstream != null) { let arrows = GlyphChars.Dash; @@ -362,28 +365,140 @@ export class BranchNode description = this.options.showAsCommits ? `${this.branch.getTrackingStatus({ suffix: pad(GlyphChars.Dot, 1, 1), - })}${this.branch.getNameWithoutRemote()}${this.branch.rebasing ? ' (Rebasing)' : ''}${pad( - arrows, - 2, - 2, - )}${this.branch.upstream.name}` + })}${this.branch.getNameWithoutRemote()}${ + this.branch.rebasing ? ` ${localize('rebasing', '(Rebasing)')}` : '' + }${pad(arrows, 2, 2)}${this.branch.upstream.name}` : `${this.branch.getTrackingStatus({ suffix: `${GlyphChars.Space} ` })}${arrows}${ GlyphChars.Space } ${this.branch.upstream.name}`; - tooltip += ` is ${this.branch.getTrackingStatus({ - empty: this.branch.upstream.missing - ? `missing upstream $(git-branch) ${this.branch.upstream.name}` - : `up to date with $(git-branch) ${this.branch.upstream.name}${ - remote?.provider?.name ? ` on ${remote.provider.name}` : '' - }`, + tooltip = this.branch.getTrackingStatus({ + empty: this.current + ? this.branch.rebasing + ? this.branch.upstream.missing + ? localize( + 'currentBranchRebasingIsMissingUpstream', + 'Current branch {0} (Rebasing) is missing upstream {1}', + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + `$(git-branch) ${this.branch.upstream.name}`, + ) + : remote?.provider?.name + ? localize( + 'currentBranchRebasingIsUpToDateWithUpstreamOnProvider', + 'Current branch {0} (Rebasing) is up to date with {1} on {2}', + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + `$(git-branch) ${this.branch.upstream.name}`, + remote.provider.name, + ) + : localize( + 'currentBranchRebasingIsUpToDateWithUpstream', + 'Current branch {0} (Rebasing) is up to date with {1}', + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + `$(git-branch) ${this.branch.upstream.name}`, + ) + : this.branch.upstream.missing + ? localize( + 'currentBranchIsMissingUpstream', + 'Current branch {0} is missing upstream {1}', + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + `$(git-branch) ${this.branch.upstream.name}`, + ) + : remote?.provider?.name + ? localize( + 'currentBranchIsUpToDateWithUpstreamOnProvider', + 'Current branch {0} is up to date with {1} on {2}', + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + `$(git-branch) ${this.branch.upstream.name}`, + remote.provider.name, + ) + : localize( + 'currentBranchIsUpToDateWithUpstream', + 'Current branch {0} is up to date with {1}', + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + `$(git-branch) ${this.branch.upstream.name}`, + ) + : this.branch.rebasing + ? this.branch.upstream.missing + ? localize( + 'branchRebasingIsMissingUpstream', + 'Branch {0} (Rebasing) is missing upstream {1}', + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + `$(git-branch) ${this.branch.upstream.name}`, + ) + : remote?.provider?.name + ? localize( + 'branchRebasingIsUpToDateWithUpstreamOnProvider', + 'Branch {0} (Rebasing) is up to date with {1} on {2}', + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + `$(git-branch) ${this.branch.upstream.name}`, + remote.provider.name, + ) + : localize( + 'branchRebasingIsUpToDateWithUpstream', + 'Branch {0} (Rebasing) is up to date with {1}', + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + `$(git-branch) ${this.branch.upstream.name}`, + ) + : this.branch.upstream.missing + ? localize( + 'branchIsMissingUpstream', + 'Branch {0} is missing upstream {1}', + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + `$(git-branch) ${this.branch.upstream.name}`, + ) + : remote?.provider?.name + ? localize( + 'branchIsUpToDateWithUpstreamOnProvider', + 'Branch {0} is up to date with {1} on {2}', + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + `$(git-branch) ${this.branch.upstream.name}`, + remote.provider.name, + ) + : localize( + 'branchIsUpToDateWithUpstream', + 'Branch {0} is up to date with {1}', + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + `$(git-branch) ${this.branch.upstream.name}`, + ), expand: true, icons: true, separator: ', ', - suffix: ` $(git-branch) ${this.branch.upstream.name}${ - remote?.provider?.name ? ` on ${remote.provider.name}` : '' + prefix: `${ + this.current + ? this.branch.rebasing + ? localize( + 'currentBranchRebasingIs', + 'Current branch {0} (Rebasing) is', + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + ) + : localize( + 'currentBranchIs', + 'Current branch {0} is', + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + ) + : this.branch.rebasing + ? localize( + 'branchRebasingIs', + 'Branch {0} (Rebasing) is', + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + ) + : localize( + 'branchIs', + 'Branch {0} is', + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + ) + } `, + suffix: ` ${ + remote?.provider?.name + ? localize( + 'upstreamOnProvider', + '{0} on {1}', + `$(git-branch) ${this.branch.upstream.name}`, + remote.provider.name, + ) + : this.branch.upstream.name }`, - })}`; + }); if (this.branch.state.ahead || this.branch.state.behind) { if (this.branch.state.ahead) { @@ -403,8 +518,54 @@ export class BranchNode ); const providerName = providers?.length ? providers[0].name : undefined; - tooltip += ` hasn't been published to ${providerName ?? 'a remote'}`; + tooltip = this.current + ? this.branch.rebasing + ? localize( + 'currentBranchRebasingHasntBeenPublishedToProvider', + "Current branch {0} (Rebasing) hasn't been published to {1}", + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + providerName, + ) + : localize( + 'currentBranchHasntBeenPublishedToProvider', + "Current branch {0} hasn't been published to {1}", + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + providerName, + ) + : this.branch.rebasing + ? localize( + 'branchRebasingHasntBeenPublishedToProvider', + "Branch {0} (Rebasing) hasn't been published to {1}", + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + providerName, + ) + : localize( + 'branchHasntBeenPublishedToProvider', + "Branch {0} hasn't been published to {1}", + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + providerName, + ); } + } else { + tooltip = this.current + ? this.branch.rebasing + ? localize( + 'currentBranchRebasing', + 'Current branch {0} (Rebasing)', + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + ) + : localize( + 'currentBranch', + 'Current branch {0}', + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + ) + : this.branch.rebasing + ? localize( + 'branchRebasing', + 'Branch {0} (Rebasing)', + `$(git-branch) ${this.branch.getNameWithoutRemote()}`, + ) + : localize('branch', 'Branch {0}', `$(git-branch) ${this.branch.getNameWithoutRemote()}`); } if (this.branch.date != null) { @@ -412,9 +573,12 @@ export class BranchNode this.branch.formattedDate }`; - tooltip += `\n\nLast commit ${this.branch.formatDateFromNow()} (${this.branch.formatDate( - Container.instance.BranchDateFormatting.dateFormat, - )})`; + tooltip += `\n\n${localize( + 'lastCommitDate', + 'Last commit {0} ({1})', + this.branch.formatDateFromNow(), + this.branch.formatDate(Container.instance.BranchDateFormatting.dateFormat), + )}`; } tooltip = new MarkdownString(tooltip, true); @@ -422,7 +586,7 @@ export class BranchNode tooltip.isTrusted = true; if (this.branch.starred) { - tooltip.appendMarkdown('\\\n$(star-full) Favorited'); + tooltip.appendMarkdown(`\\\n$(star-full) ${localize('favorited', 'Favorited')}`); } const item = new TreeItem( diff --git a/src/views/nodes/branchTrackingStatusFilesNode.ts b/src/views/nodes/branchTrackingStatusFilesNode.ts index 5cb45557d632e..f0dac3499bab9 100644 --- a/src/views/nodes/branchTrackingStatusFilesNode.ts +++ b/src/views/nodes/branchTrackingStatusFilesNode.ts @@ -1,11 +1,12 @@ import { TreeItem, TreeItemCollapsibleState } from 'vscode'; +import * as nls from 'vscode-nls'; import { ViewFilesLayout } from '../../configuration'; import { GitUri } from '../../git/gitUri'; import { GitBranch, GitFileWithCommit, GitRevision } from '../../git/models'; import { groupBy, makeHierarchical } from '../../system/array'; import { filter, flatMap, map } from '../../system/iterable'; import { joinPaths, normalizePath } from '../../system/path'; -import { pluralize, sortCompare } from '../../system/string'; +import { sortCompare } from '../../system/string'; import { ViewsWithCommits } from '../viewBase'; import { BranchNode } from './branchNode'; import { BranchTrackingStatus } from './branchTrackingStatusNode'; @@ -13,6 +14,7 @@ import { FileNode, FolderNode } from './folderNode'; import { StatusFileNode } from './statusFileNode'; import { ContextValues, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class BranchTrackingStatusFilesNode extends ViewNode { static key = ':status-branch:files'; static getId(repoPath: string, name: string, root: boolean, upstream: string, direction: string): string { @@ -113,7 +115,10 @@ export class BranchTrackingStatusFilesNode extends ViewNode { ); const files = stats?.changedFiles ?? 0; - const label = `${pluralize('file', files)} changed`; + const label = + files === 1 + ? localize('oneFileChanged', '1 file changed') + : localize('filesChanged', '{0} files changed', files); const item = new TreeItem(label, TreeItemCollapsibleState.Collapsed); item.id = this.id; item.contextValue = ContextValues.BranchStatusFiles; diff --git a/src/views/nodes/branchTrackingStatusNode.ts b/src/views/nodes/branchTrackingStatusNode.ts index b4d1d63367f3a..dabb1bfa742ec 100644 --- a/src/views/nodes/branchTrackingStatusNode.ts +++ b/src/views/nodes/branchTrackingStatusNode.ts @@ -1,4 +1,5 @@ import { MarkdownString, ThemeColor, ThemeIcon, TreeItem, TreeItemCollapsibleState, window } from 'vscode'; +import * as nls from 'vscode-nls'; import { Colors } from '../../constants'; import { GitUri } from '../../git/gitUri'; import { GitBranch, GitLog, GitRemote, GitRevision, GitTrackingState } from '../../git/models'; @@ -6,7 +7,6 @@ import { fromNow } from '../../system/date'; import { gate } from '../../system/decorators/gate'; import { debug } from '../../system/decorators/log'; import { first, map } from '../../system/iterable'; -import { pluralize } from '../../system/string'; import { ViewsWithCommits } from '../viewBase'; import { BranchNode } from './branchNode'; import { BranchTrackingStatusFilesNode } from './branchTrackingStatusFilesNode'; @@ -15,6 +15,7 @@ import { LoadMoreNode } from './common'; import { insertDateMarkers } from './helpers'; import { ContextValues, PageableViewNode, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export interface BranchTrackingStatus { ref: string; repoPath: string; @@ -165,15 +166,56 @@ export class BranchTrackingStatusNode extends ViewNode impleme case 'ahead': { const remote = await this.branch.getRemote(); - label = `Changes to push to ${remote?.name ?? GitBranch.getRemote(this.status.upstream!)}${ - remote?.provider?.name ? ` on ${remote?.provider.name}` : '' - }`; - description = pluralize('commit', this.status.state.ahead); - tooltip = `Branch $(git-branch) ${this.branch.name} is ${pluralize('commit', this.status.state.ahead, { - infix: '$(arrow-up) ', - })} ahead of $(git-branch) ${this.status.upstream}${ - remote?.provider?.name ? ` on ${remote.provider.name}` : '' - }`; + label = remote?.provider?.name + ? localize( + 'changesToPushToRemoteOnProvider', + 'Changes to push to {0} on {1}', + remote?.name ?? GitBranch.getRemote(this.status.upstream!), + remote?.provider.name, + ) + : localize( + 'changesToPushToRemote', + 'Changes to push to {0}', + remote?.name ?? GitBranch.getRemote(this.status.upstream!), + ); + description = + this.status.state.ahead === 1 + ? localize('oneCommit', '1 commit', 1) + : localize('commits', '{0} commits', this.status.state.ahead); + tooltip = + this.status.state.ahead === 1 + ? remote?.provider?.name + ? localize( + 'branchIsOneCommitAheadOfUpstreamOnProvider', + 'Branch {0} is {1} commit ahead of {2} on {3}', + `$(git-branch) ${this.branch.name}`, + '1$(arrow-up)', + `$(git-branch) ${this.status.upstream}`, + remote.provider.name, + ) + : localize( + 'branchIsOneCommitAheadOfUpstream', + 'Branch {0} is {1} commit ahead of {2}', + `$(git-branch) ${this.branch.name}`, + '1$(arrow-up)', + `$(git-branch) ${this.status.upstream}`, + ) + : remote?.provider?.name + ? localize( + 'branchIsSeveralCommitsAheadOfUpstreamOnProvider', + 'Branch {0} is {1} commits ahead of {2} on {3}', + `$(git-branch) ${this.branch.name}`, + `${this.status.state.ahead}$(arrow-up)`, + `$(git-branch) ${this.status.upstream}`, + remote.provider.name, + ) + : localize( + 'branchIsSeveralCommitsAheadOfUpstream', + 'Branch {0} is {1} commits ahead of {2}', + `$(git-branch) ${this.branch.name}`, + `${this.status.state.ahead}$(arrow-up)`, + `$(git-branch) ${this.status.upstream}`, + ); collapsibleState = TreeItemCollapsibleState.Collapsed; contextValue = this.root @@ -186,15 +228,56 @@ export class BranchTrackingStatusNode extends ViewNode impleme case 'behind': { const remote = await this.branch.getRemote(); - label = `Changes to pull from ${remote?.name ?? GitBranch.getRemote(this.status.upstream!)}${ - remote?.provider?.name ? ` on ${remote.provider.name}` : '' - }`; - description = pluralize('commit', this.status.state.behind); - tooltip = `Branch $(git-branch) ${this.branch.name} is ${pluralize('commit', this.status.state.behind, { - infix: '$(arrow-down) ', - })} behind $(git-branch) ${this.status.upstream}${ - remote?.provider?.name ? ` on ${remote.provider.name}` : '' - }`; + label = remote?.provider?.name + ? localize( + 'changesToPullFromRemoteOnProvider', + 'Changes to pull from {0} on {1}', + remote?.name ?? GitBranch.getRemote(this.status.upstream!), + remote.provider.name, + ) + : localize( + 'changesToPullFromRemote', + 'Changes to pull from {0}', + remote?.name ?? GitBranch.getRemote(this.status.upstream!), + ); + description = + this.status.state.behind === 1 + ? localize('oneCommit', '1 commit') + : localize('commits', '{0} commits', this.status.state.behind); + tooltip = + this.status.state.behind === 1 + ? remote?.provider?.name + ? localize( + 'branchIsOneCommitBehindUpstreamOnProvider', + 'Branch {0} is {1} commit behind of {2} on {3}', + `$(git-branch) ${this.branch.name}`, + '1$(arrow-down)', + `$(git-branch) ${this.status.upstream}`, + remote.provider.name, + ) + : localize( + 'branchIsOneCommitBehindUpstream', + 'Branch {0} is {1} commit behind {2}', + `$(git-branch) ${this.branch.name}`, + '1$(arrow-down)', + `$(git-branch) ${this.status.upstream}`, + ) + : remote?.provider?.name + ? localize( + 'branchIsSeveralCommitsBehindUpstreamOnProvider', + 'Branch {0} is {1} commits behind {2} on {3}', + `$(git-branch) ${this.branch.name}`, + `${this.status.state.behind}$(arrow-down)`, + `$(git-branch) ${this.status.upstream}`, + remote.provider.name, + ) + : localize( + 'branchIsSeveralCommitsBehindUpstream', + 'Branch {0} is {1} commits behind {2}', + `$(git-branch) ${this.branch.name}`, + `${this.status.state.behind}$(arrow-down)`, + `$(git-branch) ${this.status.upstream}`, + ); collapsibleState = TreeItemCollapsibleState.Collapsed; contextValue = this.root @@ -207,13 +290,35 @@ export class BranchTrackingStatusNode extends ViewNode impleme case 'same': { const remote = await this.branch.getRemote(); - label = `Up to date with ${remote?.name ?? GitBranch.getRemote(this.status.upstream!)}${ - remote?.provider?.name ? ` on ${remote.provider.name}` : '' - }`; - description = lastFetched ? `Last fetched ${fromNow(new Date(lastFetched))}` : ''; - tooltip = `Branch $(git-branch) ${this.branch.name} is up to date with $(git-branch) ${ - this.status.upstream - }${remote?.provider?.name ? ` on ${remote.provider.name}` : ''}`; + label = remote?.provider?.name + ? localize( + 'upToDateWithRemoteOnProvider', + 'Up to date with {0} on {1}', + remote?.name ?? GitBranch.getRemote(this.status.upstream!), + remote.provider.name, + ) + : localize( + 'upToDateWithRemote', + 'Up to date with {0}', + remote?.name ?? GitBranch.getRemote(this.status.upstream!), + ); + description = lastFetched + ? localize('lastFetched', 'Last fetched {0}', fromNow(new Date(lastFetched))) + : ''; + tooltip = remote?.provider?.name + ? localize( + 'branchIsUpToDateWithUpstreamOnProvider', + 'Branch {0} is up to date with {1} on {2}', + `$(git-branch) ${this.branch.name}`, + `$(git-branch) ${this.status.upstream}`, + remote.provider.name, + ) + : localize( + 'branchIsUpToDateWithUpstream', + 'Branch {0} is up to date with {1}', + `$(git-branch) ${this.branch.name}`, + `$(git-branch) ${this.status.upstream}`, + ); collapsibleState = TreeItemCollapsibleState.None; contextValue = this.root @@ -228,10 +333,21 @@ export class BranchTrackingStatusNode extends ViewNode impleme const providers = GitRemote.getHighlanderProviders(remotes); const providerName = providers?.length ? providers[0].name : undefined; - label = `Publish ${this.branch.name} to ${providerName ?? 'a remote'}`; - tooltip = `Branch $(git-branch) ${this.branch.name} hasn't been published to ${ - providerName ?? 'a remote' - }`; + label = providerName + ? localize('publishBranchToProvider', 'Publish {0} to {1}', this.branch.name, providerName) + : localize('publishBranchToRemote', 'Publish {0} to a remote', this.branch.name); + tooltip = providerName + ? localize( + 'branchHasntBeenPublishedToProvider', + "Branch {0} hasn't been published to {1}", + `$(git-branch) ${this.branch.name}`, + providerName, + ) + : localize( + 'branchHasntBeenPublishedToRemote', + "Branch {0} hasn't been published to a remote", + `$(git-branch) ${this.branch.name}`, + ); collapsibleState = TreeItemCollapsibleState.None; contextValue = this.root ? ContextValues.StatusNoUpstream : ContextValues.BranchStatusNoUpstream; @@ -249,7 +365,7 @@ export class BranchTrackingStatusNode extends ViewNode impleme item.contextValue = contextValue; item.description = description; if (lastFetched) { - tooltip += `\n\nLast fetched ${fromNow(new Date(lastFetched))}`; + tooltip += `\n\n${localize('lastFetched', 'Last fetched {0}', fromNow(new Date(lastFetched)))}`; } item.iconPath = icon; diff --git a/src/views/nodes/branchesNode.ts b/src/views/nodes/branchesNode.ts index efc9d79d0831a..ebf321810614e 100644 --- a/src/views/nodes/branchesNode.ts +++ b/src/views/nodes/branchesNode.ts @@ -1,4 +1,5 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from 'vscode'; +import * as nls from 'vscode-nls'; import { ViewBranchesLayout } from '../../configuration'; import { GitUri } from '../../git/gitUri'; import { Repository } from '../../git/models'; @@ -13,6 +14,7 @@ import { MessageNode } from './common'; import { RepositoryNode } from './repositoryNode'; import { ContextValues, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class BranchesNode extends ViewNode { static key = ':branches'; static getId(repoPath: string): string { @@ -45,7 +47,9 @@ export class BranchesNode extends ViewNode { filter: b => !b.remote, sort: { current: false }, }); - if (branches.values.length === 0) return [new MessageNode(this.view, this, 'No branches could be found.')]; + if (branches.values.length === 0) { + return [new MessageNode(this.view, this, localize('noBranchesFound', 'No branches could be found.'))]; + } // TODO@eamodio handle paging const branchNodes = branches.values.map( @@ -87,7 +91,7 @@ export class BranchesNode extends ViewNode { } async getTreeItem(): Promise { - const item = new TreeItem('Branches', TreeItemCollapsibleState.Collapsed); + const item = new TreeItem(localize('branches', 'Branches'), TreeItemCollapsibleState.Collapsed); item.id = this.id; item.contextValue = ContextValues.Branches; if (await this.repo.hasRemotes()) { diff --git a/src/views/nodes/commitFileNode.ts b/src/views/nodes/commitFileNode.ts index 1ad8480c28a3f..a3c9d70ca73fd 100644 --- a/src/views/nodes/commitFileNode.ts +++ b/src/views/nodes/commitFileNode.ts @@ -1,4 +1,5 @@ import { Command, MarkdownString, Selection, TreeItem, TreeItemCollapsibleState, Uri } from 'vscode'; +import * as nls from 'vscode-nls'; import type { DiffWithPreviousCommandArgs } from '../../commands'; import { Commands } from '../../constants'; import { StatusFileFormatter } from '../../git/formatters'; @@ -9,6 +10,7 @@ import { FileHistoryView } from '../fileHistoryView'; import { View, ViewsWithCommits } from '../viewBase'; import { ContextValues, ViewNode, ViewRefFileNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class CommitFileNode extends ViewRefFileNode { constructor( view: TView, @@ -151,7 +153,7 @@ export class CommitFileNode { constructor( view: ViewsWithCommits | FileHistoryView, @@ -116,7 +118,7 @@ export class CommitNode extends ViewRefNode { static key = ':compare-branch'; static getId(repoPath: string, name: string, root: boolean): string { @@ -83,7 +84,7 @@ export class CompareBranchNode extends ViewNode`; + label = this.compareWithWorkingTree + ? localize('compareWorkingTreeWithBranchTagOrRef', 'Compare Working Tree with ') + : localize( + 'compareBranchWithBranchTagOrRef', + 'Compare {0} with ', + this.branch.name, + ); state = TreeItemCollapsibleState.None; - tooltip = `Click to compare ${ - this.compareWithWorkingTree ? 'Working Tree' : this.branch.name - } with a branch, tag, or ref`; + tooltip = this.compareWithWorkingTree + ? localize( + 'clickToCompareWorkingTreeWithBranchTagOrRef', + 'Click to compare Working Tree with a branch, tag, or ref', + ) + : localize( + 'clickToCompareBranchWithBranchTagOrRef', + 'Click to compare {0} with a branch, tag, or ref', + this.branch.name, + ); } else { - label = `Compare ${ - this.compareWithWorkingTree ? 'Working Tree' : this.branch.name - } with ${GitRevision.shorten(this._compareWith.ref, { - strings: { working: 'Working Tree' }, - })}`; + label = this.compareWithWorkingTree + ? localize( + 'compareWorkingTreeWith', + 'Compare Working Tree with {0}', + GitRevision.shorten(this._compareWith.ref, { + strings: { working: localize('workingTree', 'Working Tree') }, + }), + ) + : localize( + 'compareBranchWithReference', + 'Compare {0} with {1}', + this.branch.name, + GitRevision.shorten(this._compareWith.ref, { + strings: { working: localize('workingTree', 'Working Tree') }, + }), + ); state = TreeItemCollapsibleState.Collapsed; } @@ -169,9 +198,11 @@ export class CompareBranchNode extends ViewNode { let item; if (selectedRef == null) { item = new TreeItem( - 'Compare with ', + localize( + 'compareBranchTagOrRefWithBranchTagOrRef', + 'Compare with ', + ), TreeItemCollapsibleState.None, ); item.contextValue = ContextValues.ComparePicker; item.description = description; - item.tooltip = `Click to select or enter a reference for compare${GlyphChars.Ellipsis}`; + item.tooltip = `${localize( + 'clickToSelectOrEnterReferenceForCompare', + 'Click to select or enter a reference for compare', + )}${GlyphChars.Ellipsis}`; item.command = { - title: `Compare${GlyphChars.Ellipsis}`, + title: `${localize('compare', 'Compare')}${GlyphChars.Ellipsis}`, command: this.view.getQualifiedCommand('selectForCompare'), }; } else { item = new TreeItem( - `Compare ${selectedRef.label} with `, + localize( + 'compareSelectedRefWithBranchTagOrRef', + 'Compare {0} with ', + selectedRef.label, + ), TreeItemCollapsibleState.None, ); item.contextValue = ContextValues.ComparePickerWithRef; item.description = description; - item.tooltip = `Click to compare ${selectedRef.label} with${GlyphChars.Ellipsis}`; + item.tooltip = `${localize('clickToCompareSelectedRefWith', 'Click to compare {0} with')}${ + GlyphChars.Ellipsis + }`; item.command = { - title: `Compare ${selectedRef.label} with${GlyphChars.Ellipsis}`, + title: `${localize('compareSelectedRefWith', 'Compare {0} with', selectedRef.label)}${ + GlyphChars.Ellipsis + }`, command: this.view.getQualifiedCommand('compareWithSelected'), }; } diff --git a/src/views/nodes/compareResultsNode.ts b/src/views/nodes/compareResultsNode.ts index c92acb111c290..e5813efd27bd4 100644 --- a/src/views/nodes/compareResultsNode.ts +++ b/src/views/nodes/compareResultsNode.ts @@ -1,16 +1,18 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from 'vscode'; +import * as nls from 'vscode-nls'; import { GitUri } from '../../git/gitUri'; import { GitRevision } from '../../git/models'; import { NamedRef } from '../../storage'; import { gate } from '../../system/decorators/gate'; import { debug, log } from '../../system/decorators/log'; -import { md5, pluralize } from '../../system/string'; +import { md5 } from '../../system/string'; import { SearchAndCompareView } from '../searchAndCompareView'; import { RepositoryNode } from './repositoryNode'; import { CommitsQueryResults, ResultsCommitsNode } from './resultsCommitsNode'; import { FilesQueryResults, ResultsFilesNode } from './resultsFilesNode'; import { ContextValues, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); let instanceId = 0; export class CompareResultsNode extends ViewNode { @@ -87,7 +89,7 @@ export class CompareResultsNode extends ViewNode { this.view, this, this.uri.repoPath!, - 'Behind', + localize('behind', 'Behind'), { query: this.getCommitsQuery(GitRevision.createRange(behind.ref1, behind.ref2, '..')), comparison: behind, @@ -100,7 +102,10 @@ export class CompareResultsNode extends ViewNode { }, { id: 'behind', - description: pluralize('commit', aheadBehindCounts?.behind ?? 0), + description: + (aheadBehindCounts?.behind ?? 0) === 1 + ? localize('oneCommit', '1 commit') + : localize('commits', '{0} commits', aheadBehindCounts?.behind ?? 0), expand: false, }, ), @@ -108,7 +113,7 @@ export class CompareResultsNode extends ViewNode { this.view, this, this.uri.repoPath!, - 'Ahead', + localize('ahead', 'Ahead'), { query: this.getCommitsQuery(GitRevision.createRange(ahead.ref1, ahead.ref2, '..')), comparison: ahead, @@ -121,7 +126,10 @@ export class CompareResultsNode extends ViewNode { }, { id: 'ahead', - description: pluralize('commit', aheadBehindCounts?.ahead ?? 0), + description: + (aheadBehindCounts?.behind ?? 0) === 1 + ? localize('oneCommit', '1 commit') + : localize('commits', '{0} commits', aheadBehindCounts?.behind ?? 0), expand: false, }, ), @@ -150,12 +158,18 @@ export class CompareResultsNode extends ViewNode { } const item = new TreeItem( - `Comparing ${ - this._ref.label ?? GitRevision.shorten(this._ref.ref, { strings: { working: 'Working Tree' } }) - } with ${ + localize( + 'comparingRefWithRef', + 'Comparing {0} with {1}', + this._ref.label ?? + GitRevision.shorten(this._ref.ref, { + strings: { working: localize('workingTree', 'Working Tree') }, + }), this._compareWith.label ?? - GitRevision.shorten(this._compareWith.ref, { strings: { working: 'Working Tree' } }) - }`, + GitRevision.shorten(this._compareWith.ref, { + strings: { working: localize('withWorkingTree', 'Working Tree') }, + }), + ), TreeItemCollapsibleState.Collapsed, ); item.id = this.id; @@ -250,8 +264,14 @@ export class CompareResultsNode extends ViewNode { } } + const filesCount = files?.length ?? 0; return { - label: `${pluralize('file', files?.length ?? 0, { zero: 'No' })} changed`, + label: + filesCount === 0 + ? localize('noFilesChanged', 'No files changed') + : filesCount === 1 + ? localize('oneFileChanged', '1 file changed') + : localize('filesChanged', '{0} files changed', filesCount), files: files, }; } @@ -280,8 +300,14 @@ export class CompareResultsNode extends ViewNode { } } + const filesCount = files?.length ?? 0; return { - label: `${pluralize('file', files?.length ?? 0, { zero: 'No' })} changed`, + label: + filesCount === 0 + ? localize('noFilesChanged', 'No files changed') + : filesCount === 1 + ? localize('oneFileChanged', '1 file changed') + : localize('filesChanged', '{0} files changed', filesCount), files: files, }; } @@ -321,8 +347,14 @@ export class CompareResultsNode extends ViewNode { const files = await this.view.container.git.getDiffStatus(this.uri.repoPath!, comparison); + const filesCount = files?.length ?? 0; return { - label: `${pluralize('file', files?.length ?? 0, { zero: 'No' })} changed`, + label: + filesCount === 0 + ? localize('noFilesChanged', 'No files changed') + : filesCount === 1 + ? localize('oneFileChanged', '1 file changed') + : localize('filesChanged', '{0} files changed', filesCount), files: files, }; } diff --git a/src/views/nodes/contributorNode.ts b/src/views/nodes/contributorNode.ts index 119c0f6206c7d..10b2491ed95c3 100644 --- a/src/views/nodes/contributorNode.ts +++ b/src/views/nodes/contributorNode.ts @@ -1,4 +1,5 @@ import { MarkdownString, TreeItem, TreeItemCollapsibleState, window } from 'vscode'; +import * as nls from 'vscode-nls'; import { getPresenceDataUri } from '../../avatars'; import { GlyphChars } from '../../constants'; import { GitUri } from '../../git/gitUri'; @@ -6,7 +7,6 @@ import { GitContributor, GitLog } from '../../git/models'; import { gate } from '../../system/decorators/gate'; import { debug } from '../../system/decorators/log'; import { map } from '../../system/iterable'; -import { pluralize } from '../../system/string'; import { ContactPresence } from '../../vsls/vsls'; import { ContributorsView } from '../contributorsView'; import { RepositoriesView } from '../repositoriesView'; @@ -16,6 +16,7 @@ import { insertDateMarkers } from './helpers'; import { RepositoryNode } from './repositoryNode'; import { ContextValues, PageableViewNode, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class ContributorNode extends ViewNode implements PageableViewNode { static key = ':contributor'; static getId( @@ -56,7 +57,9 @@ export class ContributorNode extends ViewNode { const log = await this.getLog(); - if (log == null) return [new MessageNode(this.view, this, 'No commits could be found.')]; + if (log == null) { + return [new MessageNode(this.view, this, localize('noCommitsCouldBeFound', 'No commits could be found.'))]; + } const getBranchAndTagTips = await this.view.container.git.getBranchesAndTagsTipsFn(this.uri.repoPath); const children = [ @@ -79,7 +82,9 @@ export class ContributorNode extends ViewNode { static key = ':contributors'; static getId(repoPath: string): string { @@ -52,7 +54,15 @@ export class ContributorsNode extends ViewNode implements PageableViewNode { static key = ':history:file'; static getId(repoPath: string, uri: string): string { @@ -132,7 +134,15 @@ export class FileHistoryNode extends SubscribeableViewNode impl } } - if (children.length === 0) return [new MessageNode(this.view, this, 'No file history could be found.')]; + if (children.length === 0) { + return [ + new MessageNode( + this.view, + this, + localize('noFileHistoryCouldBeFound', 'No file history could be found.'), + ), + ]; + } return children; } @@ -148,7 +158,9 @@ export class FileHistoryNode extends SubscribeableViewNode impl }`; this.view.description = `${label}${ - this.parent instanceof FileHistoryTrackerNode && !this.parent.followingEditor ? ' (pinned)' : '' + this.parent instanceof FileHistoryTrackerNode && !this.parent.followingEditor + ? ` ${localize('pinned', '(pinned)')}` + : '' }`; return item; diff --git a/src/views/nodes/fileHistoryTrackerNode.ts b/src/views/nodes/fileHistoryTrackerNode.ts index 61d9d23e7fb9d..e8b5520a91dae 100644 --- a/src/views/nodes/fileHistoryTrackerNode.ts +++ b/src/views/nodes/fileHistoryTrackerNode.ts @@ -1,4 +1,5 @@ import { Disposable, FileType, TextEditor, TreeItem, TreeItemCollapsibleState, window, workspace } from 'vscode'; +import * as nls from 'vscode-nls'; import { UriComparer } from '../../comparers'; import { ContextKeys, Schemes } from '../../constants'; import { setContext } from '../../context'; @@ -13,6 +14,7 @@ import { FileHistoryView } from '../fileHistoryView'; import { FileHistoryNode } from './fileHistoryNode'; import { ContextValues, SubscribeableViewNode, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class FileHistoryTrackerNode extends SubscribeableViewNode { private _base: string | undefined; private _child: FileHistoryNode | undefined; @@ -41,7 +43,11 @@ export class FileHistoryTrackerNode extends SubscribeableViewNode { constructor( view: ViewsWithCommits | FileHistoryView | LineHistoryView, @@ -143,7 +145,7 @@ export class FileRevisionAsCommitNode extends ViewRefFileNode( diff --git a/src/views/nodes/lineHistoryNode.ts b/src/views/nodes/lineHistoryNode.ts index 77704556c7ea6..d317de9e8b974 100644 --- a/src/views/nodes/lineHistoryNode.ts +++ b/src/views/nodes/lineHistoryNode.ts @@ -1,4 +1,5 @@ import { Disposable, Selection, TreeItem, TreeItemCollapsibleState, window } from 'vscode'; +import * as nls from 'vscode-nls'; import type { GitUri } from '../../git/gitUri'; import { GitBranch, @@ -25,6 +26,7 @@ import { LineHistoryTrackerNode } from './lineHistoryTrackerNode'; import { RepositoryNode } from './repositoryNode'; import { ContextValues, PageableViewNode, SubscribeableViewNode, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class LineHistoryNode extends SubscribeableViewNode implements PageableViewNode @@ -59,7 +61,9 @@ export class LineHistoryNode async getChildren(): Promise { this.view.description = `${this.label}${ - this.parent instanceof LineHistoryTrackerNode && !this.parent.followingEditor ? ' (pinned)' : '' + this.parent instanceof LineHistoryTrackerNode && !this.parent.followingEditor + ? ` ${localize('pinned', '(pinned)')}` + : '' }`; const children: ViewNode[] = []; @@ -156,7 +160,11 @@ export class LineHistoryNode } } - if (children.length === 0) return [new MessageNode(this.view, this, 'No line history could be found.')]; + if (children.length === 0) { + return [ + new MessageNode(this.view, this, localize('noLineHistoryFound', 'No line history could be found.')), + ]; + } return children; } @@ -167,12 +175,18 @@ export class LineHistoryNode const item = new TreeItem(label, TreeItemCollapsibleState.Expanded); item.contextValue = ContextValues.LineHistory; item.description = this.uri.directory; - item.tooltip = `History of ${this.uri.fileName}${this.lines}\n${this.uri.directory}/${ - this.uri.sha == null ? '' : `\n\n${this.uri.sha}` - }`; + item.tooltip = localize( + 'historyOf', + 'History of {0}', + `${this.uri.fileName}${this.lines}\n${this.uri.directory}/${ + this.uri.sha == null ? '' : `\n\n${this.uri.sha}` + }`, + ); this.view.description = `${label}${ - this.parent instanceof LineHistoryTrackerNode && !this.parent.followingEditor ? ' (pinned)' : '' + this.parent instanceof LineHistoryTrackerNode && !this.parent.followingEditor + ? ` ${localize('pinned', '(pinned)')}` + : '' }`; return item; diff --git a/src/views/nodes/lineHistoryTrackerNode.ts b/src/views/nodes/lineHistoryTrackerNode.ts index 80030ed1d6c0b..76d13c1dba530 100644 --- a/src/views/nodes/lineHistoryTrackerNode.ts +++ b/src/views/nodes/lineHistoryTrackerNode.ts @@ -1,4 +1,5 @@ import { Selection, TreeItem, TreeItemCollapsibleState, window } from 'vscode'; +import * as nls from 'vscode-nls'; import { UriComparer } from '../../comparers'; import { ContextKeys } from '../../constants'; import { setContext } from '../../context'; @@ -15,6 +16,7 @@ import { LineHistoryView } from '../lineHistoryView'; import { LineHistoryNode } from './lineHistoryNode'; import { ContextValues, SubscribeableViewNode, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class LineHistoryTrackerNode extends SubscribeableViewNode { private _base: string | undefined; private _child: LineHistoryNode | undefined; @@ -45,14 +47,20 @@ export class LineHistoryTrackerNode extends SubscribeableViewNode { constructor( view: ViewsWithCommits | FileHistoryView | LineHistoryView, @@ -26,7 +29,7 @@ export class MergeConflictCurrentChangesNode extends ViewNode { const commit = await this.view.container.git.getCommit(this.status.repoPath, 'HEAD'); - const item = new TreeItem('Current changes', TreeItemCollapsibleState.None); + const item = new TreeItem(localize('currentChanges', 'Current changes'), TreeItemCollapsibleState.None); item.contextValue = ContextValues.MergeConflictCurrentChanges; item.description = `${GitReference.toString(this.status.current, { expand: false, icon: false })}${ commit != null ? ` (${GitReference.toString(commit, { expand: false, icon: false })})` : ' (HEAD)' @@ -37,9 +40,13 @@ export class MergeConflictCurrentChangesNode extends ViewNode implements FileNode { constructor( view: ViewsWithCommits, @@ -49,7 +51,11 @@ export class MergeConflictFileNode extends ViewNode implements item.contextValue = `${ContextValues.File}+conflicted`; const tooltip = StatusFileFormatter.fromTemplate( - `\${file}\${ \u2022 changesDetail}\${\\\\\ndirectory}\${\n\nstatus}\${ (originalPath)} in Index (staged)`, + localize( + 'fileInIndex', + '{0} in Index (staged)', + `\${file}\${ \u2022 changesDetail}\${\\\\\ndirectory}\${\n\nstatus}\${ (originalPath)}`, + ), this.file, ); const markdown = new MarkdownString(tooltip, true); @@ -118,7 +124,7 @@ export class MergeConflictFileNode extends ViewNode implements override getCommand(): Command | undefined { return { - title: 'Open File', + title: localize('openFile', 'Open File'), command: CoreCommands.Open, arguments: [ this.view.container.git.getAbsoluteUri(this.file.path, this.repoPath), diff --git a/src/views/nodes/mergeConflictIncomingChangesNode.ts b/src/views/nodes/mergeConflictIncomingChangesNode.ts index 227ff4dfd6c67..274abfb9d6d05 100644 --- a/src/views/nodes/mergeConflictIncomingChangesNode.ts +++ b/src/views/nodes/mergeConflictIncomingChangesNode.ts @@ -1,4 +1,5 @@ import { Command, MarkdownString, ThemeIcon, TreeItem, TreeItemCollapsibleState } from 'vscode'; +import * as nls from 'vscode-nls'; import type { DiffWithCommandArgs } from '../../commands'; import { Commands, CoreCommands, GlyphChars } from '../../constants'; import { CommitFormatter } from '../../git/formatters'; @@ -9,6 +10,7 @@ import { LineHistoryView } from '../lineHistoryView'; import { ViewsWithCommits } from '../viewBase'; import { ContextValues, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class MergeConflictIncomingChangesNode extends ViewNode { constructor( view: ViewsWithCommits | FileHistoryView | LineHistoryView, @@ -29,7 +31,7 @@ export class MergeConflictIncomingChangesNode extends ViewNode { static key = ':merge'; static getId(repoPath: string, name: string, root: boolean): string { @@ -63,25 +65,63 @@ export class MergeStatusNode extends ViewNode { getTreeItem(): TreeItem { const item = new TreeItem( - `${this.status?.hasConflicts ? 'Resolve conflicts before merging' : 'Merging'} ${ - this.mergeStatus.incoming != null - ? `${GitReference.toString(this.mergeStatus.incoming, { expand: false, icon: false })} ` - : '' - }into ${GitReference.toString(this.mergeStatus.current, { expand: false, icon: false })}`, + this.status?.hasConflicts + ? this.mergeStatus.incoming != null + ? localize( + 'resolveConflictsBeforeMergingBranchIntoBranch', + 'Resolve conflicts before merging {0} into {1}', + GitReference.toString(this.mergeStatus.incoming, { expand: false, icon: false }), + GitReference.toString(this.mergeStatus.current, { expand: false, icon: false }), + ) + : localize( + 'resolveConflictsBeforeMergingIntoBranch', + 'Resolve conflicts before merging into {0}', + GitReference.toString(this.mergeStatus.current, { expand: false, icon: false }), + ) + : this.mergeStatus.incoming != null + ? localize( + 'mergingBranchIntoBranch', + 'Merging {0} into {1}', + GitReference.toString(this.mergeStatus.incoming, { expand: false, icon: false }), + GitReference.toString(this.mergeStatus.current, { expand: false, icon: false }), + ) + : localize( + 'mergingIntoBranch', + 'Merging into {0}', + GitReference.toString(this.mergeStatus.current, { expand: false, icon: false }), + ), TreeItemCollapsibleState.Expanded, ); item.id = this.id; item.contextValue = ContextValues.Merge; - item.description = this.status?.hasConflicts ? pluralize('conflict', this.status.conflicts.length) : undefined; + item.description = this.status?.hasConflicts + ? this.status.conflicts.length === 1 + ? localize('oneConflict', '1 conflict') + : localize('conflicts', '{0} conflicts', this.status.conflicts.length) + : undefined; item.iconPath = this.status?.hasConflicts ? new ThemeIcon('warning', new ThemeColor('list.warningForeground')) : new ThemeIcon('debug-pause', new ThemeColor('list.foreground')); const markdown = new MarkdownString( - `${`Merging ${ - this.mergeStatus.incoming != null ? GitReference.toString(this.mergeStatus.incoming) : '' - }into ${GitReference.toString(this.mergeStatus.current)}`}${ - this.status?.hasConflicts ? `\n\n${pluralize('conflicted file', this.status.conflicts.length)}` : '' + `${ + this.mergeStatus.incoming != null + ? localize( + 'mergingBranchIntoBranch', + 'Merging {0} into {1}', + GitReference.toString(this.mergeStatus.incoming), + GitReference.toString(this.mergeStatus.current), + ) + : localize('mergingIntoBranch', 'Merging into {0}', GitReference.toString(this.mergeStatus.current)) + } + ${ + this.status?.hasConflicts + ? `\n\n${ + this.status.conflicts.length === 1 + ? localize('oneConflictedFile', '1 conflicted file') + : localize('conflictedFiles', '{0} conflicted files', this.status.conflicts.length) + }` + : '' }`, true, ); diff --git a/src/views/nodes/pullRequestNode.ts b/src/views/nodes/pullRequestNode.ts index d753a2b1cfc40..1986d088e442a 100644 --- a/src/views/nodes/pullRequestNode.ts +++ b/src/views/nodes/pullRequestNode.ts @@ -1,10 +1,12 @@ import { MarkdownString, TreeItem, TreeItemCollapsibleState } from 'vscode'; +import * as nls from 'vscode-nls'; import { GitUri } from '../../git/gitUri'; import { GitBranch, GitCommit, PullRequest, PullRequestState } from '../../git/models'; import { ViewsWithCommits } from '../viewBase'; import { RepositoryNode } from './repositoryNode'; import { ContextValues, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class PullRequestNode extends ViewNode { static key = ':pullrequest'; static getId(repoPath: string, id: string, refOrParent: string): string { @@ -62,21 +64,39 @@ export class PullRequestNode extends ViewNode { if (GitCommit.is(this.branchOrCommit)) { tooltip.appendMarkdown( - `Commit \`$(git-commit) ${this.branchOrCommit.shortSha}\` was introduced by $(git-pull-request) PR #${this.pullRequest.id}\n\n`, + `${localize( + 'commitWasIntroducedByPullRequest', + 'Commit `{0}` was introduced by {1}', + `$(git-commit) ${this.branchOrCommit.shortSha}`, + `$(git-pull-request) PR #${this.pullRequest.id}`, + )}\n\n`, ); } - const linkTitle = ` "Open Pull Request \\#${this.pullRequest.id} on ${this.pullRequest.provider.name}"`; + const linkTitle = ` "${localize( + 'openPullRequestOnProvider', + 'Open Pull Request {0} on {1}', + `\\#${this.pullRequest.id}`, + this.pullRequest.provider.name, + )}"`; tooltip.appendMarkdown( `${PullRequest.getMarkdownIcon(this.pullRequest)} [**${this.pullRequest.title.trim()}**](${ this.pullRequest.url - }${linkTitle}) \\\n[#${this.pullRequest.id}](${this.pullRequest.url}${linkTitle}) by [@${ - this.pullRequest.author.name - }](${this.pullRequest.author.url} "Open @${this.pullRequest.author.name} on ${ - this.pullRequest.provider.name - }") was ${ - this.pullRequest.state === PullRequestState.Open ? 'opened' : this.pullRequest.state.toLowerCase() - } ${this.pullRequest.formatDateFromNow()}`, + }${linkTitle}) \\\n${localize( + 'pullRequestByAuthorWasSetToStatusAtTime', + '{0} by {1} was {2} {3}', + `[#${this.pullRequest.id}](${this.pullRequest.url}${linkTitle})`, + `[@${this.pullRequest.author.name}](${this.pullRequest.author.url} "${localize( + 'openAuthorOnProvider', + 'Open {0} on {1}', + this.pullRequest.author.name, + this.pullRequest.provider.name, + )}")`, + this.pullRequest.state === PullRequestState.Open + ? localize('openedStatus', 'opened') + : this.pullRequest.state.toLowerCase(), + this.pullRequest.formatDateFromNow(), + )}`, ); item.tooltip = tooltip; diff --git a/src/views/nodes/rebaseStatusNode.ts b/src/views/nodes/rebaseStatusNode.ts index 899c816b47dfc..ac7b93086a8de 100644 --- a/src/views/nodes/rebaseStatusNode.ts +++ b/src/views/nodes/rebaseStatusNode.ts @@ -1,4 +1,5 @@ import { Command, MarkdownString, ThemeColor, ThemeIcon, TreeItem, TreeItemCollapsibleState, Uri } from 'vscode'; +import * as nls from 'vscode-nls'; import type { DiffWithPreviousCommandArgs } from '../../commands'; import { ViewFilesLayout } from '../../configuration'; import { Commands, CoreCommands } from '../../constants'; @@ -8,7 +9,7 @@ import { GitBranch, GitCommit, GitRebaseStatus, GitReference, GitRevisionReferen import { makeHierarchical } from '../../system/array'; import { executeCoreCommand } from '../../system/command'; import { joinPaths, normalizePath } from '../../system/path'; -import { pluralize, sortCompare } from '../../system/string'; +import { sortCompare } from '../../system/string'; import { ViewsWithCommits } from '../viewBase'; import { BranchNode } from './branchNode'; import { CommitFileNode } from './commitFileNode'; @@ -16,6 +17,7 @@ import { FileNode, FolderNode } from './folderNode'; import { MergeConflictFileNode } from './mergeConflictFileNode'; import { ContextValues, ViewNode, ViewRefNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class RebaseStatusNode extends ViewNode { static key = ':rebase'; static getId(repoPath: string, name: string, root: boolean): string { @@ -73,29 +75,71 @@ export class RebaseStatusNode extends ViewNode { getTreeItem(): TreeItem { const item = new TreeItem( - `${this.status?.hasConflicts ? 'Resolve conflicts to continue rebasing' : 'Rebasing'} ${ - this.rebaseStatus.incoming != null - ? `${GitReference.toString(this.rebaseStatus.incoming, { expand: false, icon: false })}` - : '' + `${ + this.status?.hasConflicts + ? this.rebaseStatus.incoming != null + ? localize( + 'resolveConflictsToContinueRebasingBranch', + 'Resolve conflicts to continue rebasing {0}', + GitReference.toString(this.rebaseStatus.incoming, { expand: false, icon: false }), + ) + : localize('resolveConflictsToContinueRebasing', 'Resolve conflicts to continue rebasing') + : this.rebaseStatus.incoming != null + ? localize( + 'rebasingBranch', + 'Rebasing {0}', + GitReference.toString(this.rebaseStatus.incoming, { expand: false, icon: false }), + ) + : localize('rebasing', 'Rebasing') } (${this.rebaseStatus.steps.current.number}/${this.rebaseStatus.steps.total})`, TreeItemCollapsibleState.Expanded, ); item.id = this.id; item.contextValue = ContextValues.Rebase; - item.description = this.status?.hasConflicts ? pluralize('conflict', this.status.conflicts.length) : undefined; + item.description = this.status?.hasConflicts + ? this.status.conflicts.length === 1 + ? localize('oneConflict', '1 conflict') + : localize('conflicts', '{0} conflicts', this.status.conflicts.length) + : undefined; item.iconPath = this.status?.hasConflicts ? new ThemeIcon('warning', new ThemeColor('list.warningForeground')) : new ThemeIcon('debug-pause', new ThemeColor('list.foreground')); const markdown = new MarkdownString( - `${`Rebasing ${ - this.rebaseStatus.incoming != null ? GitReference.toString(this.rebaseStatus.incoming) : '' - }onto ${GitReference.toString(this.rebaseStatus.current)}`}\n\nStep ${ - this.rebaseStatus.steps.current.number - } of ${this.rebaseStatus.steps.total}\\\nPaused at ${GitReference.toString( - this.rebaseStatus.steps.current.commit, - { icon: true }, - )}${this.status?.hasConflicts ? `\n\n${pluralize('conflicted file', this.status.conflicts.length)}` : ''}`, + `${ + this.rebaseStatus.incoming != null + ? localize( + 'rebasingBranchOntoBranch', + 'Rebasing {0} onto {1}', + GitReference.toString(this.rebaseStatus.incoming), + GitReference.toString(this.rebaseStatus.current), + ) + : localize( + 'rebasingOntoBranch', + 'Rebasing onto {0}', + GitReference.toString(this.rebaseStatus.current), + ) + } + \n\n${localize( + 'stepNumberOfTotal', + 'Step {0} of {1}', + this.rebaseStatus.steps.current.number, + this.rebaseStatus.steps.total, + )} + \\\n${localize( + 'pausedAtCommit', + 'Paused at {0}', + GitReference.toString(this.rebaseStatus.steps.current.commit, { icon: true }), + )} + ${ + this.status?.hasConflicts + ? `\n\n${ + this.status.conflicts.length === 1 + ? localize('oneConflictedFile', '1 conflicted file') + : localize('conflictedFiles', '{0} conflicted files', this.status.conflicts.length) + }` + : '' + }`, true, ); markdown.supportHtml = true; @@ -151,7 +195,10 @@ export class RebaseCommitNode extends ViewRefNode implements PageableViewNode { static key = ':reflog'; static getId(repoPath: string): string { @@ -31,7 +33,7 @@ export class ReflogNode extends ViewNode implements PageableVi const reflog = await this.getReflog(); if (reflog === undefined || reflog.records.length === 0) { - return [new MessageNode(this.view, this, 'No activity could be found.')]; + return [new MessageNode(this.view, this, localize('noActivityFound', 'No activity could be found.'))]; } children.push(...reflog.records.map(r => new ReflogRecordNode(this.view, this, r))); @@ -46,10 +48,13 @@ export class ReflogNode extends ViewNode implements PageableVi } getTreeItem(): TreeItem { - const item = new TreeItem('Incoming Activity', TreeItemCollapsibleState.Collapsed); + const item = new TreeItem( + localize('incomingActivity', 'Incoming Activity'), + TreeItemCollapsibleState.Collapsed, + ); item.id = this.id; item.contextValue = ContextValues.Reflog; - item.description = 'experimental'; + item.description = localize('experimental', 'experimental'); item.iconPath = { dark: this.view.container.context.asAbsolutePath('images/dark/icon-activity.svg'), light: this.view.container.context.asAbsolutePath('images/light/icon-activity.svg'), diff --git a/src/views/nodes/reflogRecordNode.ts b/src/views/nodes/reflogRecordNode.ts index 27cfa24103f91..682b270737796 100644 --- a/src/views/nodes/reflogRecordNode.ts +++ b/src/views/nodes/reflogRecordNode.ts @@ -1,4 +1,5 @@ import { TreeItem, TreeItemCollapsibleState, window } from 'vscode'; +import * as nls from 'vscode-nls'; import { GlyphChars } from '../../constants'; import { GitUri } from '../../git/gitUri'; import { GitLog, GitReflogRecord } from '../../git/models'; @@ -11,6 +12,7 @@ import { LoadMoreNode, MessageNode } from './common'; import { RepositoryNode } from './repositoryNode'; import { ContextValues, PageableViewNode, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class ReflogRecordNode extends ViewNode implements PageableViewNode { static key = ':reflog-record'; static getId( @@ -43,7 +45,9 @@ export class ReflogRecordNode extends ViewNode implements Page async getChildren(): Promise { const log = await this.getLog(); - if (log === undefined) return [new MessageNode(this.view, this, 'No commits could be found.')]; + if (log === undefined) { + return [new MessageNode(this.view, this, localize('noCommitsFound', 'No commits could be found.'))]; + } const children: (CommitNode | LoadMoreNode)[] = [ ...map(log.commits.values(), c => new CommitNode(this.view, this, c)), diff --git a/src/views/nodes/remoteNode.ts b/src/views/nodes/remoteNode.ts index 2adb8f3cb31b8..7aca3e3b7ea4a 100644 --- a/src/views/nodes/remoteNode.ts +++ b/src/views/nodes/remoteNode.ts @@ -1,4 +1,5 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState, Uri } from 'vscode'; +import * as nls from 'vscode-nls'; import { ViewBranchesLayout } from '../../configuration'; import { GlyphChars } from '../../constants'; import { GitUri } from '../../git/gitUri'; @@ -13,6 +14,7 @@ import { MessageNode } from './common'; import { RepositoryNode } from './repositoryNode'; import { ContextValues, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class RemoteNode extends ViewNode { static key = ':remote'; static getId(repoPath: string, name: string, id: string): string { @@ -43,7 +45,9 @@ export class RemoteNode extends ViewNode { filter: b => b.remote && b.name.startsWith(this.remote.name), sort: true, }); - if (branches.values.length === 0) return [new MessageNode(this.view, this, 'No branches could be found.')]; + if (branches.values.length === 0) { + return [new MessageNode(this.view, this, localize('noBranchesFound', 'No branches could be found.'))]; + } // TODO@eamodio handle paging const branchNodes = branches.values.map( @@ -126,7 +130,9 @@ export class RemoteNode extends ViewNode { item.contextValue = `${ContextValues.Remote}${connected ? '+connected' : '+disconnected'}`; item.tooltip = `${this.remote.name} (${provider.name} ${GlyphChars.Dash} ${ - connected ? 'connected' : 'not connected' + connected + ? localize('providerConnected', '{0} connected', `${provider.name} ${GlyphChars.Dash}`) + : localize('providerNotConnected', '{0} not connected', `${provider.name} ${GlyphChars.Dash}`) })\n${provider.displayPath}\n`; } else { item.contextValue = ContextValues.Remote; diff --git a/src/views/nodes/remotesNode.ts b/src/views/nodes/remotesNode.ts index 1fef2ad65cd32..488d3310ce507 100644 --- a/src/views/nodes/remotesNode.ts +++ b/src/views/nodes/remotesNode.ts @@ -1,4 +1,5 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from 'vscode'; +import * as nls from 'vscode-nls'; import { GitUri } from '../../git/gitUri'; import { Repository } from '../../git/models'; import { gate } from '../../system/decorators/gate'; @@ -10,6 +11,7 @@ import { RemoteNode } from './remoteNode'; import { RepositoryNode } from './repositoryNode'; import { ContextValues, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class RemotesNode extends ViewNode { static key = ':remotes'; static getId(repoPath: string): string { @@ -34,7 +36,7 @@ export class RemotesNode extends ViewNode { if (this._children == null) { const remotes = await this.repo.getRemotes({ sort: true }); if (remotes.length === 0) { - return [new MessageNode(this.view, this, 'No remotes could be found')]; + return [new MessageNode(this.view, this, localize('noRemotesFound', 'No remotes could be found'))]; } this._children = remotes.map(r => new RemoteNode(this.uri, this.view, this, r, this.repo)); @@ -44,7 +46,7 @@ export class RemotesNode extends ViewNode { } getTreeItem(): TreeItem { - const item = new TreeItem('Remotes', TreeItemCollapsibleState.Collapsed); + const item = new TreeItem(localize('remotes', 'Remotes'), TreeItemCollapsibleState.Collapsed); item.id = this.id; item.contextValue = ContextValues.Remotes; item.iconPath = new ThemeIcon('cloud'); diff --git a/src/views/nodes/repositoriesNode.ts b/src/views/nodes/repositoriesNode.ts index 31e7866b95203..41763c7760b6c 100644 --- a/src/views/nodes/repositoriesNode.ts +++ b/src/views/nodes/repositoriesNode.ts @@ -1,4 +1,5 @@ import { Disposable, TextEditor, TreeItem, TreeItemCollapsibleState, window } from 'vscode'; +import * as nls from 'vscode-nls'; import { RepositoriesChangeEvent } from '../../git/gitProviderService'; import { GitUri } from '../../git/gitUri'; import { Logger } from '../../logger'; @@ -10,6 +11,7 @@ import { MessageNode } from './common'; import { RepositoryNode } from './repositoryNode'; import { ContextValues, SubscribeableViewNode, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class RepositoriesNode extends SubscribeableViewNode { private _children: (RepositoryNode | MessageNode)[] | undefined; @@ -38,7 +40,15 @@ export class RepositoriesNode extends SubscribeableViewNode { getChildren(): ViewNode[] { if (this._children == null) { const repositories = this.view.container.git.openRepositories; - if (repositories.length === 0) return [new MessageNode(this.view, this, 'No repositories could be found.')]; + if (repositories.length === 0) { + return [ + new MessageNode( + this.view, + this, + localize('noRepositoriesFound', 'No repositories could be found.'), + ), + ]; + } this._children = repositories.map(r => new RepositoryNode(GitUri.fromRepoPath(r.path), this.view, this, r)); } @@ -47,7 +57,7 @@ export class RepositoriesNode extends SubscribeableViewNode { } getTreeItem(): TreeItem { - const item = new TreeItem('Repositories', TreeItemCollapsibleState.Expanded); + const item = new TreeItem(localize('repositories', 'Repositories'), TreeItemCollapsibleState.Expanded); item.contextValue = ContextValues.Repositories; return item; @@ -70,7 +80,9 @@ export class RepositoriesNode extends SubscribeableViewNode { if (repositories.length === 0 && (this._children == null || this._children.length === 0)) return; if (repositories.length === 0) { - this._children = [new MessageNode(this.view, this, 'No repositories could be found.')]; + this._children = [ + new MessageNode(this.view, this, localize('noRepositoriesFound', 'No repositories could be found.')), + ]; return; } diff --git a/src/views/nodes/repositoryNode.ts b/src/views/nodes/repositoryNode.ts index 9796d2bcbd42b..c11e895409637 100644 --- a/src/views/nodes/repositoryNode.ts +++ b/src/views/nodes/repositoryNode.ts @@ -1,4 +1,5 @@ import { Disposable, MarkdownString, TreeItem, TreeItemCollapsibleState } from 'vscode'; +import * as nls from 'vscode-nls'; import { GlyphChars } from '../../constants'; import { Features } from '../../features'; import { GitUri } from '../../git/gitUri'; @@ -34,6 +35,7 @@ import { TagsNode } from './tagsNode'; import { ContextValues, SubscribeableViewNode, ViewNode } from './viewNode'; import { WorktreesNode } from './worktreesNode'; +const localize = nls.loadMessageBundle(); export class RepositoryNode extends SubscribeableViewNode { static key = ':repository'; static getId(repoPath: string): string { @@ -186,7 +188,11 @@ export class RepositoryNode extends SubscribeableViewNode { let description; let tooltip = `${this.repo.formattedName ?? this.uri.repoPath ?? ''}${ lastFetched - ? `${pad(GlyphChars.Dash, 2, 2)}Last fetched ${Repository.formatLastFetched(lastFetched, false)}` + ? `${pad(GlyphChars.Dash, 2, 2)}${localize( + 'lastFetched', + 'Last fetched {0}', + Repository.formatLastFetched(lastFetched, false), + )}` : '' }${this.repo.formattedName ? `\n${this.uri.repoPath}` : ''}`; let iconSuffix = ''; @@ -199,8 +205,6 @@ export class RepositoryNode extends SubscribeableViewNode { const status = await this._status; if (status != null) { - tooltip += `\n\nCurrent branch $(git-branch) ${status.branch}${status.rebasing ? ' (Rebasing)' : ''}`; - if (this.view.config.includeWorkingTree && status.files.length !== 0) { workingStatus = status.getFormattedDiffStatus({ compact: true, @@ -212,7 +216,9 @@ export class RepositoryNode extends SubscribeableViewNode { suffix: pad(GlyphChars.Dot, 1, 1), }); - description = `${upstreamStatus}${status.branch}${status.rebasing ? ' (Rebasing)' : ''}${workingStatus}`; + description = `${upstreamStatus}${status.branch}${ + status.rebasing ? ` ${localize('rebasing', '(Rebasing)')}` : '' + }${workingStatus}`; let providerName; if (status.upstream != null) { @@ -226,16 +232,57 @@ export class RepositoryNode extends SubscribeableViewNode { } iconSuffix = workingStatus ? '-blue' : ''; + tooltip += '\n\n'; if (status.upstream != null) { - tooltip += ` is ${status.getUpstreamStatus({ - empty: `up to date with $(git-branch) ${status.upstream}${ - providerName ? ` on ${providerName}` : '' - }`, + tooltip += status.getUpstreamStatus({ + empty: status.rebasing + ? providerName + ? localize( + 'currentBranchRebasingIsUpToDateWithUpstreamOnProvider', + 'Current branch {0} (Rebasing) is up to date with {1} on {2}', + `$(git-branch) ${status.branch}`, + `$(git-branch) ${status.upstream}`, + providerName, + ) + : localize( + 'currentBranchRebasingIsUpToDateWithUpstream', + 'Current branch {0} (Rebasing) is up to date with {1}', + `$(git-branch) ${status.branch}`, + `$(git-branch) ${status.upstream}`, + ) + : providerName + ? localize( + 'currentBranchIsUpToDateWithUpstreamOnProvider', + 'Current branch {0} is up to date with {1} on {2}', + `$(git-branch) ${status.branch}`, + `$(git-branch) ${status.upstream}`, + providerName, + ) + : localize( + 'currentBranchIsUpToDateWithUpstream', + 'Current branch {0} is up to date with {1}', + `$(git-branch) ${status.branch}`, + `$(git-branch) ${status.upstream}`, + ), expand: true, icons: true, separator: ', ', - suffix: ` $(git-branch) ${status.upstream}${providerName ? ` on ${providerName}` : ''}`, - })}`; + prefix: status.rebasing + ? `${localize( + 'currentBranchRebasingIs', + 'Current branch {0} (Rebasing) is', + `$(git-branch) ${status.branch}`, + )} ` + : `${localize('currentBranchIs', 'Current branch {0} is', `$(git-branch) ${status.branch}`)} `, + suffix: providerName + ? ` ${localize( + 'upstreamOnProvider', + '{0} on {1}', + `$(git-branch) ${status.upstream}`, + providerName, + )}` + : `$(git-branch) ${status.upstream}`, + }); if (status.state.behind) { contextValue += '+behind'; @@ -245,14 +292,26 @@ export class RepositoryNode extends SubscribeableViewNode { iconSuffix = status.state.behind ? '-yellow' : '-green'; contextValue += '+ahead'; } + } else { + tooltip += status.rebasing + ? localize( + 'currentBranchRebasing', + 'Current branch {0} (Rebasing)', + `$(git-branch) ${status.branch}`, + ) + : localize('currentBranch', 'Current branch {0}', `$(git-branch) ${status.branch}`); } if (workingStatus) { - tooltip += `\n\nWorking tree has uncommitted changes${status.getFormattedDiffStatus({ - expand: true, - prefix: '\n', - separator: '\n', - })}`; + tooltip += `\n\n${localize( + 'workingTreeHasUncommittedChanges', + 'Working tree has uncommitted changes{0}', + status.getFormattedDiffStatus({ + expand: true, + prefix: '\n', + separator: '\n', + }), + )}`; } } @@ -260,7 +319,13 @@ export class RepositoryNode extends SubscribeableViewNode { item.id = this.id; item.contextValue = contextValue; item.description = `${description ?? ''}${ - lastFetched ? `${pad(GlyphChars.Dot, 1, 1)}Last fetched ${Repository.formatLastFetched(lastFetched)}` : '' + lastFetched + ? `${pad(GlyphChars.Dot, 1, 1)}${localize( + 'lastFetched', + 'Last fetched {0}', + Repository.formatLastFetched(lastFetched), + )}` + : '' }`; item.iconPath = { dark: this.view.container.context.asAbsolutePath(`images/dark/icon-repo${iconSuffix}.svg`), diff --git a/src/views/nodes/resultsFileNode.ts b/src/views/nodes/resultsFileNode.ts index ec577fcd2b97c..75730befd2ea9 100644 --- a/src/views/nodes/resultsFileNode.ts +++ b/src/views/nodes/resultsFileNode.ts @@ -1,4 +1,5 @@ import { Command, TreeItem, TreeItemCollapsibleState } from 'vscode'; +import * as nls from 'vscode-nls'; import type { DiffWithCommandArgs } from '../../commands'; import { Commands } from '../../constants'; import { StatusFileFormatter } from '../../git/formatters'; @@ -9,6 +10,7 @@ import { View } from '../viewBase'; import { FileNode } from './folderNode'; import { ContextValues, ViewNode, ViewRefFileNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class ResultsFileNode extends ViewRefFileNode implements FileNode { constructor( view: View, @@ -124,7 +126,7 @@ export class ResultsFileNode extends ViewRefFileNode implements FileNode { }, }; return { - title: 'Open Changes', + title: localize('openChanges', 'Open Changes'), command: Commands.DiffWith, arguments: [commandArgs], }; diff --git a/src/views/nodes/resultsFilesNode.ts b/src/views/nodes/resultsFilesNode.ts index c3e169e4b1992..1bdd004d01a8e 100644 --- a/src/views/nodes/resultsFilesNode.ts +++ b/src/views/nodes/resultsFilesNode.ts @@ -1,4 +1,5 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from 'vscode'; +import * as nls from 'vscode-nls'; import { ViewFilesLayout } from '../../configuration'; import { GitUri } from '../../git/gitUri'; import { GitFile } from '../../git/models'; @@ -14,6 +15,7 @@ import { FileNode, FolderNode } from './folderNode'; import { ResultsFileNode } from './resultsFileNode'; import { ContextValues, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export interface FilesQueryResults { label: string; files: GitFile[] | undefined; @@ -107,7 +109,7 @@ export class ResultsFilesNode extends ViewNode { files = (this.filtered ? results.filtered?.files : undefined) ?? results.files; if (this.filtered && results.filtered == null) { - label = 'files changed'; + label = localize('filesChanged', 'files changed'); icon = new ThemeIcon('ellipsis'); } @@ -122,7 +124,7 @@ export class ResultsFilesNode extends ViewNode { ex.promise.then(() => queueMicrotask(() => this.triggerChange(false))); } - label = 'files changed'; + label = localize('filesChanged', 'files changed'); icon = new ThemeIcon('ellipsis'); // Need to use Collapsed before we have results or the item won't show up in the view until the children are awaited // https://github.com/microsoft/vscode/issues/54806 & https://github.com/microsoft/vscode/issues/62214 @@ -130,7 +132,9 @@ export class ResultsFilesNode extends ViewNode { } const item = new TreeItem( - `${this.filtered && files != null ? `Showing ${files.length} of ` : ''}${label}`, + this.filtered && files != null + ? localize('showingFilesOfTotal', 'Showing {0} of {1}', files.length, label) + : label, state, ); item.id = this.id; diff --git a/src/views/nodes/searchResultsNode.ts b/src/views/nodes/searchResultsNode.ts index c05afbfb4bbb2..681dc8567deb3 100644 --- a/src/views/nodes/searchResultsNode.ts +++ b/src/views/nodes/searchResultsNode.ts @@ -1,4 +1,5 @@ import { ThemeIcon, TreeItem } from 'vscode'; +import * as nls from 'vscode-nls'; import { executeGitCommand } from '../../commands/gitCommands.actions'; import { GitUri } from '../../git/gitUri'; import { GitLog } from '../../git/models'; @@ -11,6 +12,7 @@ import { RepositoryNode } from './repositoryNode'; import { CommitsQueryResults, ResultsCommitsNode } from './resultsCommitsNode'; import { ContextValues, PageableViewNode, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); let instanceId = 0; interface SearchQueryResults { @@ -241,12 +243,16 @@ export class SearchResultsNode extends ViewNode implements const count = log?.count ?? 0; - const resultsType = - label.resultsType === undefined ? { singular: 'result', plural: 'results' } : label.resultsType; - - return `${pluralize(resultsType.singular, count, { + if (label.resultsType === undefined) { + return count === 0 + ? localize('noResults', 'No results') + : count === 1 + ? localize('result', '{0} result', log?.hasMore ? `${count}+` : count) + : localize('results', '{0} results', log?.hasMore ? `${count}+` : count); + } + return `${pluralize(label.resultsType.singular, count, { format: c => (log?.hasMore ? `${c}+` : undefined), - plural: resultsType.plural, + plural: label.resultsType.plural, zero: 'No', })} ${label.label}`; } diff --git a/src/views/nodes/stashesNode.ts b/src/views/nodes/stashesNode.ts index b32f642912f96..61743ec22a611 100644 --- a/src/views/nodes/stashesNode.ts +++ b/src/views/nodes/stashesNode.ts @@ -1,4 +1,5 @@ import { TreeItem, TreeItemCollapsibleState } from 'vscode'; +import * as nls from 'vscode-nls'; import { GitUri } from '../../git/gitUri'; import { Repository } from '../../git/models'; import { gate } from '../../system/decorators/gate'; @@ -11,6 +12,7 @@ import { RepositoryNode } from './repositoryNode'; import { StashNode } from './stashNode'; import { ContextValues, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class StashesNode extends ViewNode { static key = ':stashes'; static getId(repoPath: string): string { @@ -30,7 +32,9 @@ export class StashesNode extends ViewNode { async getChildren(): Promise { if (this._children == null) { const stash = await this.repo.getStash(); - if (stash == null) return [new MessageNode(this.view, this, 'No stashes could be found.')]; + if (stash == null) { + return [new MessageNode(this.view, this, localize('noStashesFound', 'No stashes could be found.'))]; + } this._children = [...map(stash.commits.values(), c => new StashNode(this.view, this, c))]; } @@ -39,7 +43,7 @@ export class StashesNode extends ViewNode { } getTreeItem(): TreeItem { - const item = new TreeItem('Stashes', TreeItemCollapsibleState.Collapsed); + const item = new TreeItem(localize('stashes', 'Stashes'), TreeItemCollapsibleState.Collapsed); item.id = this.id; item.contextValue = ContextValues.Stashes; diff --git a/src/views/nodes/statusFileNode.ts b/src/views/nodes/statusFileNode.ts index 9b952a2741752..16b960b27c751 100644 --- a/src/views/nodes/statusFileNode.ts +++ b/src/views/nodes/statusFileNode.ts @@ -1,4 +1,5 @@ import { Command, ThemeIcon, TreeItem, TreeItemCollapsibleState } from 'vscode'; +import * as nls from 'vscode-nls'; import type { DiffWithCommandArgs } from '../../commands'; import { DiffWithPreviousCommandArgs } from '../../commands/diffWithPrevious'; import { Commands } from '../../constants'; @@ -6,12 +7,12 @@ import { StatusFileFormatter } from '../../git/formatters/statusFormatter'; import { GitUri } from '../../git/gitUri'; import { GitCommit, GitFile } from '../../git/models'; import { joinPaths, relativeDir } from '../../system/path'; -import { pluralize } from '../../system/string'; import { ViewsWithCommits } from '../viewBase'; import { FileRevisionAsCommitNode } from './fileRevisionAsCommitNode'; import { FileNode } from './folderNode'; import { ContextValues, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class StatusFileNode extends ViewNode implements FileNode { public readonly commits: GitCommit[]; public readonly file: GitFile; @@ -76,13 +77,21 @@ export class StatusFileNode extends ViewNode implements FileNo if (this._hasStagedChanges) { item.contextValue += '+staged'; item.tooltip = StatusFileFormatter.fromTemplate( - `\${file}\n\${directory}/\n\n\${status}\${ (originalPath)} in Index (staged)`, + `\${file}\n\${directory}/\n\n${localize( + 'statusInIndex', + '{0} in Index (staged)', + `\${status}\${ (originalPath)}`, + )}`, this.file, ); } else { item.contextValue += '+unstaged'; item.tooltip = StatusFileFormatter.fromTemplate( - `\${file}\n\${directory}/\n\n\${status}\${ (originalPath)} in Working Tree`, + `\${file}\n\${directory}/\n\n${localize( + 'statusInWorkingTree', + '{0} in Working Tree', + `\${status}\${ (originalPath)}`, + )}`, this.file, ); } @@ -118,7 +127,12 @@ export class StatusFileNode extends ViewNode implements FileNo } item.tooltip = StatusFileFormatter.fromTemplate( - `\${file}\n\${directory}/\n\n\${status}\${ (originalPath)} in ${this.getChangedIn()}`, + `\${file}\n\${directory}/\n\n${localize( + 'statusIn', + '{0} in {1}', + `\${status}\${ (originalPath)}`, + this.getChangedIn(), + )}`, this.file, ); @@ -202,12 +216,12 @@ export class StatusFileNode extends ViewNode implements FileNo if (this._hasUnstagedChanges) { commits++; - changedIn.push('Working Tree'); + changedIn.push(localize('workingTree', 'Working Tree')); } if (this._hasStagedChanges) { commits++; - changedIn.push('Index (staged)'); + changedIn.push(localize('index', 'Index (staged)')); } if (this.commits.length > commits) { @@ -215,13 +229,15 @@ export class StatusFileNode extends ViewNode implements FileNo } if (commits > 0) { - changedIn.push(pluralize('commit', commits)); + changedIn.push( + commits === 1 ? localize('oneCommit', '1 commit') : localize('commits', '{0} commits', commits), + ); } if (changedIn.length > 2) { - changedIn[changedIn.length - 1] = `and ${changedIn[changedIn.length - 1]}`; + changedIn[changedIn.length - 1] = `${localize('and', 'and')} ${changedIn[changedIn.length - 1]}`; } - return changedIn.join(changedIn.length > 2 ? ', ' : ' and '); + return changedIn.join(changedIn.length > 2 ? ', ' : ` ${localize('and', 'and')} `); } override getCommand(): Command | undefined { @@ -236,7 +252,7 @@ export class StatusFileNode extends ViewNode implements FileNo }, }; return { - title: 'Open Changes with Previous Revision', + title: localize('openChangesWithPreviousRevision', 'Open Changes with Previous Revision'), command: Commands.DiffWithPrevious, arguments: [undefined, commandArgs], }; @@ -261,7 +277,7 @@ export class StatusFileNode extends ViewNode implements FileNo }, }; return { - title: 'Open Changes', + title: localize('openChanges', 'Open Changes'), command: Commands.DiffWith, arguments: [commandArgs], }; diff --git a/src/views/nodes/statusFilesNode.ts b/src/views/nodes/statusFilesNode.ts index e8fd34b395c55..7ac46f72dc994 100644 --- a/src/views/nodes/statusFilesNode.ts +++ b/src/views/nodes/statusFilesNode.ts @@ -1,11 +1,12 @@ import { TreeItem, TreeItemCollapsibleState } from 'vscode'; +import * as nls from 'vscode-nls'; import { ViewFilesLayout } from '../../configuration'; import { GitUri } from '../../git/gitUri'; import { GitCommit, GitFileWithCommit, GitLog, GitStatus, GitStatusFile, GitTrackingState } from '../../git/models'; import { groupBy, makeHierarchical } from '../../system/array'; import { filter, flatMap, map } from '../../system/iterable'; import { joinPaths, normalizePath } from '../../system/path'; -import { pluralize, sortCompare } from '../../system/string'; +import { sortCompare } from '../../system/string'; import { RepositoriesView } from '../repositoriesView'; import { WorktreesView } from '../worktreesView'; import { FileNode, FolderNode } from './folderNode'; @@ -13,6 +14,7 @@ import { RepositoryNode } from './repositoryNode'; import { StatusFileNode } from './statusFileNode'; import { ContextValues, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class StatusFilesNode extends ViewNode { static key = ':status-files'; static getId(repoPath: string): string { @@ -149,7 +151,12 @@ export class StatusFilesNode extends ViewNode } } - const label = files === -1 ? '?? files changed' : `${pluralize('file', files)} changed`; + const label = + files === -1 + ? localize('indefiniteFilesChanged', '?? files changed') + : files === 1 + ? localize('oneFileChanged', '1 file changed') + : localize('filesChanged', '{0} files changed', files); const item = new TreeItem(label, TreeItemCollapsibleState.Collapsed); item.id = this.id; item.contextValue = ContextValues.StatusFiles; diff --git a/src/views/nodes/tagNode.ts b/src/views/nodes/tagNode.ts index 4be2af0d37c54..ac4beb27cab75 100644 --- a/src/views/nodes/tagNode.ts +++ b/src/views/nodes/tagNode.ts @@ -1,4 +1,5 @@ import { TreeItem, TreeItemCollapsibleState, window } from 'vscode'; +import * as nls from 'vscode-nls'; import { ViewBranchesLayout } from '../../configuration'; import { GlyphChars } from '../../constants'; import { Container } from '../../container'; @@ -17,6 +18,7 @@ import { insertDateMarkers } from './helpers'; import { RepositoryNode } from './repositoryNode'; import { ContextValues, PageableViewNode, ViewNode, ViewRefNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class TagNode extends ViewRefNode implements PageableViewNode { static key = ':tag'; static getId(repoPath: string, name: string): string { @@ -45,7 +47,9 @@ export class TagNode extends ViewRefNode { const log = await this.getLog(); - if (log == null) return [new MessageNode(this.view, this, 'No commits could be found.')]; + if (log == null) { + return [new MessageNode(this.view, this, localize('noCommitsFound', 'No commits could be found.'))]; + } const getBranchAndTagTips = await this.view.container.git.getBranchesAndTagsTipsFn( this.uri.repoPath, diff --git a/src/views/nodes/tagsNode.ts b/src/views/nodes/tagsNode.ts index 17933714eeaa2..35300bcc812ad 100644 --- a/src/views/nodes/tagsNode.ts +++ b/src/views/nodes/tagsNode.ts @@ -1,4 +1,5 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from 'vscode'; +import * as nls from 'vscode-nls'; import { ViewBranchesLayout } from '../../configuration'; import { GitUri } from '../../git/gitUri'; import { Repository } from '../../git/models'; @@ -13,6 +14,7 @@ import { RepositoryNode } from './repositoryNode'; import { TagNode } from './tagNode'; import { ContextValues, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class TagsNode extends ViewNode { static key = ':tags'; static getId(repoPath: string): string { @@ -36,7 +38,9 @@ export class TagsNode extends ViewNode { async getChildren(): Promise { if (this._children == null) { const tags = await this.repo.getTags({ sort: true }); - if (tags.values.length === 0) return [new MessageNode(this.view, this, 'No tags could be found.')]; + if (tags.values.length === 0) { + return [new MessageNode(this.view, this, localize('noTagsFound', 'No tags could be found.'))]; + } // TODO@eamodio handle paging const tagNodes = tags.values.map( @@ -68,7 +72,7 @@ export class TagsNode extends ViewNode { } getTreeItem(): TreeItem { - const item = new TreeItem('Tags', TreeItemCollapsibleState.Collapsed); + const item = new TreeItem(localize('tags', 'Tags'), TreeItemCollapsibleState.Collapsed); item.id = this.id; item.contextValue = ContextValues.Tags; item.iconPath = new ThemeIcon('tag'); diff --git a/src/views/nodes/viewNode.ts b/src/views/nodes/viewNode.ts index 9af467ec0fa2d..c26af24508971 100644 --- a/src/views/nodes/viewNode.ts +++ b/src/views/nodes/viewNode.ts @@ -7,6 +7,7 @@ import { TreeItemCollapsibleState, TreeViewVisibilityChangeEvent, } from 'vscode'; +import * as nls from 'vscode-nls'; import { GlyphChars } from '../../constants'; import { RepositoriesChangeEvent } from '../../git/gitProviderService'; import { GitUri } from '../../git/gitUri'; @@ -28,6 +29,8 @@ import { is as isA, szudzikPairing } from '../../system/function'; import { pad } from '../../system/string'; import { TreeViewNodeCollapsibleStateChangeEvent, View } from '../viewBase'; +const localize = nls.loadMessageBundle(); + export const enum ContextValues { ActiveFileHistory = 'gitlens:history:active:file', ActiveLineHistory = 'gitlens:history:active:line', @@ -400,7 +403,11 @@ export abstract class RepositoryFolderNode< const status = branch.getTrackingStatus(); item.description = `${status ? `${status}${pad(GlyphChars.Dot, 1, 1)}` : ''}${branch.name}${ lastFetched - ? `${pad(GlyphChars.Dot, 1, 1)}Last fetched ${Repository.formatLastFetched(lastFetched)}` + ? `${pad(GlyphChars.Dot, 1, 1)}${localize( + 'lastFetchedTime', + 'Last fetched {0}', + Repository.formatLastFetched(lastFetched), + )}` : '' }`; @@ -418,29 +425,67 @@ export abstract class RepositoryFolderNode< item.tooltip = new MarkdownString( `${this.repo.formattedName ?? this.uri.repoPath ?? ''}${ lastFetched - ? `${pad(GlyphChars.Dash, 2, 2)}Last fetched ${Repository.formatLastFetched( - lastFetched, - false, + ? `${pad(GlyphChars.Dash, 2, 2)}${localize( + 'lastFetchedTime', + 'Last fetched {0}', + Repository.formatLastFetched(lastFetched, false), )}` : '' - }${this.repo.formattedName ? `\n${this.uri.repoPath}` : ''}\n\nCurrent branch $(git-branch) ${ - branch.name - }${ + }${this.repo.formattedName ? `\n${this.uri.repoPath}` : ''}\n\n${ branch.upstream != null - ? ` is ${branch.getTrackingStatus({ + ? branch.getTrackingStatus({ empty: branch.upstream.missing - ? `missing upstream $(git-branch) ${branch.upstream.name}` - : `up to date with $(git-branch) ${branch.upstream.name}${ - providerName ? ` on ${providerName}` : '' - }`, + ? localize( + 'currentBranchIsMissingUpstream', + 'Current branch {0} is missing upstream {1}', + `$(git-branch) ${branch.name}`, + `$(git-branch) ${branch.upstream.name}`, + ) + : providerName + ? localize( + 'currentBranchIsUpToDateWithUpstreamOnProvider', + 'Current branch {0} is up to date with {1}', + `$(git-branch) ${branch.name}`, + `$(git-branch) ${branch.upstream.name}`, + ) + : localize( + 'currentBranchIsUpToDateWithUpstream', + 'Current branch {0} is up to date with {1} on {2}', + `$(git-branch) ${branch.name}`, + `$(git-branch) ${branch.upstream.name}`, + providerName, + ), expand: true, icons: true, separator: ', ', - suffix: ` $(git-branch) ${branch.upstream.name}${ - providerName ? ` on ${providerName}` : '' + prefix: `${localize( + 'currentBranchIsStatus', + 'Current branch {0} is', + `$(git-branch) ${branch.name}`, + )} `, + suffix: ` ${ + providerName + ? localize( + 'upstreamOnProvider', + '{0} on {1}', + `$(git-branch) ${branch.upstream.name}`, + providerName, + ) + : `$(git-branch) ${branch.upstream.name}` }`, - })}` - : `hasn't been published to ${providerName ?? 'a remote'}` + }) + : providerName + ? localize( + 'currentBranchNotPublishedToProvider', + "Current branch {0} hasn't been published to {1}", + `$(git-branch) ${branch.name}`, + providerName, + ) + : localize( + 'currentBranchNotPublishedToRemote', + "Current branch {0} hasn't been published to a remote", + `$(git-branch) ${branch.name}`, + ) }`, true, ); diff --git a/src/views/nodes/worktreeNode.ts b/src/views/nodes/worktreeNode.ts index 221890ed3eb01..22f09ed9cb688 100644 --- a/src/views/nodes/worktreeNode.ts +++ b/src/views/nodes/worktreeNode.ts @@ -1,4 +1,5 @@ import { MarkdownString, ThemeIcon, TreeItem, TreeItemCollapsibleState, Uri, window } from 'vscode'; +import * as nls from 'vscode-nls'; import { GlyphChars } from '../../constants'; import { GitUri } from '../../git/gitUri'; import { @@ -25,6 +26,7 @@ import { RepositoryNode } from './repositoryNode'; import { UncommittedFilesNode } from './UncommittedFilesNode'; import { ContextValues, ViewNode } from './viewNode'; +const localize = nls.loadMessageBundle(); export class WorktreeNode extends ViewNode { static key = ':worktree'; static getId(repoPath: string, uri: Uri): string { @@ -86,7 +88,9 @@ export class WorktreeNode extends ViewNode { }) : undefined, ]); - if (log == null) return [new MessageNode(this.view, this, 'No commits could be found.')]; + if (log == null) { + return [new MessageNode(this.view, this, localize('noCommitsFound', 'No commits could be found.'))]; + } const children = []; @@ -170,9 +174,11 @@ export class WorktreeNode extends ViewNode { this.worktree.main || this.worktree.opened ? `${pad(GlyphChars.Dash, 2, 2)} ${ this.worktree.main - ? `_Main${this.worktree.opened ? ', Active_' : '_'}` + ? `_${localize('worktreeIndicatorMain', 'Main')}${ + this.worktree.opened ? `, ${localize('worktreeIndicatorActive', 'Active')}_` : '_' + }` : this.worktree.opened - ? '_Active_' + ? `_${localize('worktreeIndicatorActive', 'Active')}_` : '' } ` : ''; @@ -181,9 +187,11 @@ export class WorktreeNode extends ViewNode { case 'bare': icon = new ThemeIcon('folder'); tooltip.appendMarkdown( - `${this.worktree.main ? '$(pass) ' : ''}Bare Worktree${indicators}\\\n\`${ - this.worktree.friendlyPath - }\``, + `${this.worktree.main ? '$(pass) ' : ''}${localize( + 'bareWorktreeIndicators', + 'Bare worktree {0}', + indicators, + )}\\\n\`${this.worktree.friendlyPath}\``, ); break; case 'branch': { @@ -191,9 +199,12 @@ export class WorktreeNode extends ViewNode { this._branch = branch; tooltip.appendMarkdown( - `${this.worktree.main ? '$(pass) ' : ''}Worktree for Branch $(git-branch) ${ - branch?.getNameWithoutRemote() ?? this.worktree.branch - }${indicators}\\\n\`${this.worktree.friendlyPath}\``, + `${this.worktree.main ? '$(pass) ' : ''}${localize( + 'worktreeForBranchIndicators', + 'Worktree for Branch {0} {1}', + `$(git-branch) ${branch?.getNameWithoutRemote() ?? this.worktree.branch}`, + indicators, + )}\\\n\`${this.worktree.friendlyPath}\``, ); icon = new ThemeIcon('git-branch'); @@ -201,16 +212,15 @@ export class WorktreeNode extends ViewNode { hasChanges = status.hasChanges; tooltip.appendMarkdown( `\n\n${status.getFormattedDiffStatus({ - prefix: 'Has Uncommitted Changes\\\n', - empty: 'No Uncommitted Changes', + prefix: `${localize('hasUncommitedChanges', 'Has Uncommitted Changes')}\\\n`, + empty: localize('noUncommitedChanges', 'No Uncommitted Changes'), expand: true, })}`, ); } if (branch != null) { - tooltip.appendMarkdown(`\n\nBranch $(git-branch) ${branch.getNameWithoutRemote()}`); - + tooltip.appendMarkdown('\n\n'); if (!branch.remote) { if (branch.upstream != null) { let arrows = GlyphChars.Dash; @@ -250,27 +260,72 @@ export class WorktreeNode extends ViewNode { })}${branch.upstream.name}`; tooltip.appendMarkdown( - ` is ${branch.getTrackingStatus({ + branch.getTrackingStatus({ empty: branch.upstream.missing - ? `missing upstream $(git-branch) ${branch.upstream.name}` - : `up to date with $(git-branch) ${branch.upstream.name}${ - remote?.provider?.name ? ` on ${remote.provider.name}` : '' - }`, + ? localize( + 'branchIsMissingUpstream', + 'Branch {0} is missing upstream {1}', + `$(git-branch) ${branch.getNameWithoutRemote()}`, + `$(git-branch) ${branch.upstream.name}`, + ) + : remote?.provider?.name + ? localize( + 'branchIsUpToDateWithUpstreamOnProvider', + 'Branch {0} is up to date with {1} on {2}', + `$(git-branch) ${branch.getNameWithoutRemote()}`, + `$(git-branch) ${branch.upstream.name}`, + remote.provider.name, + ) + : localize( + 'branchIsUpToDateWithUpstream', + 'Branch {0} is up to date with {1}', + `$(git-branch) ${branch.getNameWithoutRemote()}`, + `$(git-branch) ${branch.upstream.name}`, + ), expand: true, icons: true, separator: ', ', - suffix: ` $(git-branch) ${branch.upstream.name}${ - remote?.provider?.name ? ` on ${remote.provider.name}` : '' + prefix: localize( + 'currentBranchIs', + 'Current branch {0} is', + `$(git-branch) ${branch.upstream.name}`, + ), + suffix: ` ${ + remote?.provider?.name + ? localize( + 'upstreamOnProvider', + '{0} on {1}', + `$(git-branch) ${branch.upstream.name}`, + remote.provider.name, + ) + : `$(git-branch) ${branch.upstream.name}` }`, - })}`, + }), ); } else { const providerName = GitRemote.getHighlanderProviderName( await this.view.container.git.getRemotesWithProviders(branch.repoPath), ); - tooltip.appendMarkdown(` hasn't been published to ${providerName ?? 'a remote'}`); + tooltip.appendMarkdown( + providerName + ? localize( + 'branchHasntBeenPublishedToProvider', + "Branch {0} hasn't been published to {1}", + `$(git-branch) ${branch.getNameWithoutRemote()}`, + providerName, + ) + : localize( + 'branchHasntBeenPublishedToRemote', + "Branch {0} hasn't been published to a remote", + `$(git-branch) ${branch.getNameWithoutRemote()}`, + ), + ); } + } else { + tooltip.appendMarkdown( + localize('branch', 'Branch {0}', `$(git-branch) ${branch.getNameWithoutRemote()}`), + ); } } @@ -279,8 +334,10 @@ export class WorktreeNode extends ViewNode { case 'detached': { icon = new ThemeIcon('git-commit'); tooltip.appendMarkdown( - `${this.worktree.main ? '$(pass) ' : ''}Detached Worktree at $(git-commit) ${GitRevision.shorten( - this.worktree.sha, + `${this.worktree.main ? '$(pass) ' : ''}${localize( + 'detachedWorktreeAtCommit', + 'Detached Worktree at {0}', + `$(git-commit) ${GitRevision.shorten(this.worktree.sha)}`, )}${indicators}\\\n\`${this.worktree.friendlyPath}\``, ); @@ -289,8 +346,8 @@ export class WorktreeNode extends ViewNode { hasChanges = status.hasChanges; tooltip.appendMarkdown( `\n\n${status.getFormattedDiffStatus({ - prefix: 'Has Uncommitted Changes', - empty: 'No Uncommitted Changes', + prefix: localize('hasUncommitedChanges', 'Has Uncommitted Changes'), + empty: localize('noUncommitedChanges', 'No Uncommitted Changes'), expand: true, })}`, ); diff --git a/src/views/nodes/worktreesNode.ts b/src/views/nodes/worktreesNode.ts index 62028bfafebf5..8c07b79b89756 100644 --- a/src/views/nodes/worktreesNode.ts +++ b/src/views/nodes/worktreesNode.ts @@ -1,4 +1,5 @@ import { ThemeIcon, TreeItem, TreeItemCollapsibleState } from 'vscode'; +import * as nls from 'vscode-nls'; import { GlyphChars } from '../../constants'; import { PlusFeatures } from '../../features'; import { GitUri } from '../../git/gitUri'; @@ -12,6 +13,7 @@ import { RepositoryNode } from './repositoryNode'; import { ContextValues, ViewNode } from './viewNode'; import { WorktreeNode } from './worktreeNode'; +const localize = nls.loadMessageBundle(); export class WorktreesNode extends ViewNode { static key = ':worktrees'; static getId(repoPath: string): string { @@ -43,7 +45,9 @@ export class WorktreesNode extends ViewNode { if (!access.allowed) return []; const worktrees = await this.repo.getWorktrees(); - if (worktrees.length === 0) return [new MessageNode(this.view, this, 'No worktrees could be found.')]; + if (worktrees.length === 0) { + return [new MessageNode(this.view, this, localize('noWorktreesFound', 'No worktrees could be found.'))]; + } this._children = worktrees.map(c => new WorktreeNode(this.uri, this.view, this, c)); } @@ -55,14 +59,17 @@ export class WorktreesNode extends ViewNode { const access = await this.repo.access(PlusFeatures.Worktrees); const item = new TreeItem( - 'Worktrees', + localize('worktrees', 'Worktrees'), access.allowed ? TreeItemCollapsibleState.Collapsed : TreeItemCollapsibleState.None, ); item.id = this.id; item.contextValue = ContextValues.Worktrees; item.description = access.allowed ? undefined - : ` ${GlyphChars.Warning} GitLens+ feature which requires an account`; + : ` ${GlyphChars.Warning} ${localize( + 'plusFeatureWhichRequiresAccount', + 'GitLens+ feature which requires an account', + )}`; // TODO@eamodio `folder` icon won't work here for some reason item.iconPath = new ThemeIcon('folder-opened'); return item; diff --git a/src/views/remotesView.ts b/src/views/remotesView.ts index 80e64034a03a1..4f310f911671f 100644 --- a/src/views/remotesView.ts +++ b/src/views/remotesView.ts @@ -8,6 +8,7 @@ import { TreeItemCollapsibleState, window, } from 'vscode'; +import * as nls from 'vscode-nls'; import { configuration, RemotesViewConfig, ViewBranchesLayout, ViewFilesLayout } from '../configuration'; import { Commands } from '../constants'; import { Container } from '../container'; @@ -37,6 +38,8 @@ import { } from './nodes'; import { ViewBase } from './viewBase'; +const localize = nls.loadMessageBundle(); + export class RemotesRepositoryNode extends RepositoryFolderNode { async getChildren(): Promise { if (this.child == null) { @@ -62,7 +65,7 @@ export class RemotesViewNode extends RepositoriesSubscribeableNode { protected readonly configKey = 'remotes'; constructor(container: Container) { - super('gitlens.views.remotes', 'Remotes', container); + super('gitlens.views.remotes', localize('remotes', 'Remotes'), container); } override get canReveal(): boolean { @@ -304,7 +307,11 @@ export class RemotesView extends ViewBase { return window.withProgress( { location: ProgressLocation.Notification, - title: `Revealing ${GitReference.toString(branch, { icon: false, quoted: true })} in the side bar...`, + title: localize( + 'revealingBranchInSideBar', + 'Revealing {0} in the side bar...', + GitReference.toString(branch, { icon: false, quoted: true }), + ), cancellable: true, }, async (progress, token) => { @@ -330,7 +337,11 @@ export class RemotesView extends ViewBase { return window.withProgress( { location: ProgressLocation.Notification, - title: `Revealing ${GitReference.toString(commit, { icon: false, quoted: true })} in the side bar...`, + title: localize( + 'revealingCommitInSideBar', + 'Revealing {0} in the side bar...', + GitReference.toString(commit, { icon: false, quoted: true }), + ), cancellable: true, }, async (progress, token) => { @@ -356,7 +367,7 @@ export class RemotesView extends ViewBase { return window.withProgress( { location: ProgressLocation.Notification, - title: `Revealing remote '${remote.name}' in the side bar...`, + title: localize('revealingRemoteInSideBar', 'Revealing remote {0} in the side bar...', remote.name), cancellable: true, }, async (progress, token) => { diff --git a/src/views/repositoriesView.ts b/src/views/repositoriesView.ts index 213282a31a162..9950f7707b168 100644 --- a/src/views/repositoriesView.ts +++ b/src/views/repositoriesView.ts @@ -8,6 +8,7 @@ import { ProgressLocation, window, } from 'vscode'; +import * as nls from 'vscode-nls'; import { configuration, RepositoriesViewConfig, @@ -54,11 +55,13 @@ import { } from './nodes'; import { ViewBase } from './viewBase'; +const localize = nls.loadMessageBundle(); + export class RepositoriesView extends ViewBase { protected readonly configKey = 'repositories'; constructor(container: Container) { - super('gitlens.views.repositories', 'Repositories', container); + super('gitlens.views.repositories', localize('repositories', 'Repositories'), container); } private _onDidChangeAutoRefresh = new EventEmitter(); @@ -529,10 +532,14 @@ export class RepositoriesView extends ViewBase { @@ -590,10 +597,14 @@ export class RepositoriesView extends ViewBase { @@ -619,7 +630,11 @@ export class RepositoriesView extends ViewBase { @@ -645,7 +660,7 @@ export class RepositoriesView extends ViewBase { @@ -694,10 +709,14 @@ export class RepositoriesView extends ViewBase { @@ -755,10 +774,14 @@ export class RepositoriesView extends ViewBase { @@ -816,7 +839,11 @@ export class RepositoriesView extends ViewBase { diff --git a/src/views/searchAndCompareView.ts b/src/views/searchAndCompareView.ts index 2a4560c63c498..4f0e6ebe67612 100644 --- a/src/views/searchAndCompareView.ts +++ b/src/views/searchAndCompareView.ts @@ -1,4 +1,5 @@ import { commands, ConfigurationChangeEvent, Disposable, TreeItem, TreeItemCollapsibleState } from 'vscode'; +import * as nls from 'vscode-nls'; import { configuration, SearchAndCompareViewConfig, ViewFilesLayout } from '../configuration'; import { Commands, ContextKeys } from '../constants'; import { Container } from '../container'; @@ -25,6 +26,8 @@ import { import { ComparePickerNode } from './nodes/comparePickerNode'; import { ViewBase } from './viewBase'; +const localize = nls.loadMessageBundle(); + interface DeprecatedPinnedComparison { path: string; ref1: NamedRef; @@ -70,7 +73,7 @@ export class SearchAndCompareViewNode extends ViewNode { getTreeItem(): TreeItem { this.splatted = false; - const item = new TreeItem('SearchAndCompare', TreeItemCollapsibleState.Expanded); + const item = new TreeItem(localize('searchAndCompare', 'SearchAndCompare'), TreeItemCollapsibleState.Expanded); item.contextValue = ContextValues.SearchAndCompare; return item; } @@ -150,8 +153,8 @@ export class SearchAndCompareViewNode extends ViewNode { if (ref == null) { const pick = await ReferencePicker.show( repoPath, - `Compare ${this.getRefName(selectedRef.ref)} with`, - 'Choose a reference to compare with', + localize('compareRefWith', 'Compare {0} with', this.getRefName(selectedRef.ref)), + localize('chooseReferenceToCompareWith', 'Choose a reference to compare with'), { allowEnteringRefs: true, picked: typeof selectedRef.ref === 'string' ? selectedRef.ref : selectedRef.ref.ref, @@ -181,7 +184,7 @@ export class SearchAndCompareViewNode extends ViewNode { async selectForCompare(repoPath?: string, ref?: string | NamedRef, options?: { prompt?: boolean }) { if (repoPath == null) { - repoPath = (await RepositoryPicker.getRepositoryOrShow('Compare'))?.path; + repoPath = (await RepositoryPicker.getRepositoryOrShow(localize('compare', 'Compare')))?.path; } if (repoPath == null) return; @@ -190,15 +193,20 @@ export class SearchAndCompareViewNode extends ViewNode { let prompt = options?.prompt ?? false; let ref2; if (ref == null) { - const pick = await ReferencePicker.show(repoPath, 'Compare', 'Choose a reference to compare', { - allowEnteringRefs: { ranges: true }, - // checkmarks: false, - include: - ReferencesQuickPickIncludes.BranchesAndTags | - ReferencesQuickPickIncludes.HEAD | - ReferencesQuickPickIncludes.WorkingTree, - sort: { branches: { current: true }, tags: {} }, - }); + const pick = await ReferencePicker.show( + repoPath, + localize('compare', 'Compare'), + localize('chooseReferenceToCompare', 'Choose a reference to compare'), + { + allowEnteringRefs: { ranges: true }, + // checkmarks: false, + include: + ReferencesQuickPickIncludes.BranchesAndTags | + ReferencesQuickPickIncludes.HEAD | + ReferencesQuickPickIncludes.WorkingTree, + sort: { branches: { current: true }, tags: {} }, + }, + ); if (pick == null) { await this.triggerChange(); @@ -237,7 +245,7 @@ export class SearchAndCompareViewNode extends ViewNode { private getRefName(ref: string | NamedRef) { return typeof ref === 'string' - ? GitRevision.shorten(ref, { strings: { working: 'Working Tree' } })! + ? GitRevision.shorten(ref, { strings: { working: localize('workingTree', 'Working Tree') } })! : ref.label ?? GitRevision.shorten(ref.ref)!; } @@ -260,7 +268,7 @@ export class SearchAndCompareView extends ViewBase { async getChildren(): Promise { if (this.child == null) { @@ -50,7 +53,7 @@ export class StashesViewNode extends RepositoriesSubscribeableNode { protected readonly configKey = 'stashes'; constructor(container: Container) { - super('gitlens.views.stashes', 'Stashes', container); + super('gitlens.views.stashes', localize('stashes', 'Stashes'), container); } override get canReveal(): boolean { @@ -208,7 +211,11 @@ export class StashesView extends ViewBase { return window.withProgress( { location: ProgressLocation.Notification, - title: `Revealing ${GitReference.toString(stash, { icon: false, quoted: true })} in the side bar...`, + title: localize( + 'revealingStashInSideBar', + 'Revealing {0} in the side bar...', + GitReference.toString(stash, { icon: false, quoted: true }), + ), cancellable: true, }, async (progress, token) => { diff --git a/src/views/tagsView.ts b/src/views/tagsView.ts index 80db66434362a..2630b4095bd7d 100644 --- a/src/views/tagsView.ts +++ b/src/views/tagsView.ts @@ -8,6 +8,7 @@ import { TreeItemCollapsibleState, window, } from 'vscode'; +import * as nls from 'vscode-nls'; import { configuration, TagsViewConfig, ViewBranchesLayout, ViewFilesLayout } from '../configuration'; import { Commands } from '../constants'; import { Container } from '../container'; @@ -31,6 +32,8 @@ import { } from './nodes'; import { ViewBase } from './viewBase'; +const localize = nls.loadMessageBundle(); + export class TagsRepositoryNode extends RepositoryFolderNode { async getChildren(): Promise { if (this.child == null) { @@ -50,7 +53,7 @@ export class TagsViewNode extends RepositoriesSubscribeableNode { protected readonly configKey = 'tags'; constructor(container: Container) { - super('gitlens.views.tags', 'Tags', container); + super('gitlens.views.tags', localize('tags', 'Tags'), container); } override get canReveal(): boolean { @@ -230,7 +233,11 @@ export class TagsView extends ViewBase { return window.withProgress( { location: ProgressLocation.Notification, - title: `Revealing ${GitReference.toString(tag, { icon: false, quoted: true })} in the side bar...`, + title: localize( + 'revealingTagInSideBar', + 'Revealing {0} in the side bar...', + GitReference.toString(tag, { icon: false, quoted: true }), + ), cancellable: true, }, async (progress, token) => { diff --git a/src/views/viewCommands.ts b/src/views/viewCommands.ts index 60f7b4cd2aaf3..98fe2a359b25f 100644 --- a/src/views/viewCommands.ts +++ b/src/views/viewCommands.ts @@ -1,4 +1,5 @@ import { commands, env, TextDocumentShowOptions, Uri, window } from 'vscode'; +import * as nls from 'vscode-nls'; import type { CreatePullRequestActionContext, OpenPullRequestActionContext } from '../api/gitlens'; import type { DiffWithCommandArgs, @@ -61,6 +62,8 @@ import { WorktreesNode, } from './nodes'; +const localize = nls.loadMessageBundle(); + interface CompareSelectedInfo { ref: string; repoPath: string | undefined; @@ -723,10 +726,14 @@ export class ViewCommands { if (commit?.hash !== node.ref.ref) { void window.showWarningMessage( - `Commit ${GitReference.toString(node.ref, { - capitalize: true, - icon: false, - })} cannot be undone, because it is no longer the most recent commit.`, + localize( + 'commitCannotBeUndoneBecauseItIsNoLongerMostRecent', + 'Commit {0} cannot be undone, because it is no longer the most recent commit.', + GitReference.toString(node.ref, { + capitalize: true, + icon: false, + }), + ), ); return; @@ -811,7 +818,12 @@ export class ViewCommands { return this.container.searchAndCompareView.compare( node.repoPath, - { ref: commonAncestor, label: `ancestry with ${node.ref.ref} (${GitRevision.shorten(commonAncestor)})` }, + { + ref: commonAncestor, + label: `${localize('ancestryWithRef', 'ancestry with {0}', node.ref.ref)} (${GitRevision.shorten( + commonAncestor, + )})`, + }, '', ); } diff --git a/src/views/viewDecorationProvider.ts b/src/views/viewDecorationProvider.ts index a48aabc182f9a..b0fadf589201e 100644 --- a/src/views/viewDecorationProvider.ts +++ b/src/views/viewDecorationProvider.ts @@ -9,9 +9,12 @@ import { Uri, window, } from 'vscode'; +import * as nls from 'vscode-nls'; import { GlyphChars } from '../constants'; import { GitBranchStatus } from '../git/models'; +const localize = nls.loadMessageBundle(); + export class ViewFileDecorationProvider implements FileDecorationProvider, Disposable { private readonly _onDidChange = new EventEmitter(); get onDidChange(): Event { @@ -66,43 +69,43 @@ export class ViewFileDecorationProvider implements FileDecorationProvider, Dispo return { badge: 'I', color: new ThemeColor('gitlens.decorations.ignoredForegroundColor'), - tooltip: 'Ignored', + tooltip: localize('commitFile.status.ignored', 'Ignored'), }; case '?': return { badge: 'U', color: new ThemeColor('gitlens.decorations.untrackedForegroundColor'), - tooltip: 'Untracked', + tooltip: localize('commitFile.status.untracked', 'Untracked'), }; case 'A': return { badge: 'A', color: new ThemeColor('gitlens.decorations.addedForegroundColor'), - tooltip: 'Added', + tooltip: localize('gitlens.viewDecorationProvider.commitFileStatusAdded', 'Added'), }; case 'C': return { badge: 'C', color: new ThemeColor('gitlens.decorations.copiedForegroundColor'), - tooltip: 'Copied', + tooltip: localize('commitFile.status.copied', 'Copied'), }; case 'D': return { badge: 'D', color: new ThemeColor('gitlens.decorations.deletedForegroundColor'), - tooltip: 'Deleted', + tooltip: localize('commitFile.status.deleted', 'Deleted'), }; case 'M': return { badge: 'M', // color: new ThemeColor('gitlens.decorations.modifiedForegroundColor'), - tooltip: 'Modified', + tooltip: localize('commitFile.status.modified', 'Modified'), }; case 'R': return { badge: 'R', color: new ThemeColor('gitlens.decorations.renamedForegroundColor'), - tooltip: 'Renamed', + tooltip: localize('commitFile.status.renamed', 'Renamed'), }; default: return undefined; @@ -117,37 +120,37 @@ export class ViewFileDecorationProvider implements FileDecorationProvider, Dispo return { badge: '▲', color: new ThemeColor('gitlens.decorations.branchAheadForegroundColor'), - tooltip: 'Ahead', + tooltip: localize('branch.status.ahead', 'Ahead'), }; case GitBranchStatus.Behind: return { badge: '▼', color: new ThemeColor('gitlens.decorations.branchBehindForegroundColor'), - tooltip: 'Behind', + tooltip: localize('branch.status.behind', 'Behind'), }; case GitBranchStatus.Diverged: return { badge: '▼▲', color: new ThemeColor('gitlens.decorations.branchDivergedForegroundColor'), - tooltip: 'Diverged', + tooltip: localize('branch.status.diverged', 'Diverged'), }; case GitBranchStatus.MissingUpstream: return { badge: '!', color: new ThemeColor('gitlens.decorations.branchMissingUpstreamForegroundColor'), - tooltip: 'Missing Upstream', + tooltip: localize('branch.status.missingUpstream', 'Missing Upstream'), }; case GitBranchStatus.UpToDate: return { badge: '', color: new ThemeColor('gitlens.decorations.branchUpToDateForegroundColor'), - tooltip: 'Up to Date', + tooltip: localize('branch.status.upToDate', 'Up to Date'), }; case GitBranchStatus.Unpublished: return { badge: '▲+', color: new ThemeColor('gitlens.decorations.branchUnpublishedForegroundColor'), - tooltip: 'Unpublished', + tooltip: localize('branch.status.unpublished', 'Unpublished'), }; default: return undefined; @@ -181,7 +184,7 @@ export class ViewFileDecorationProvider implements FileDecorationProvider, Dispo return { badge: GlyphChars.Check, color: color, - tooltip: 'Current Branch', + tooltip: localize('currentBranch', 'Current Branch'), }; } @@ -192,7 +195,7 @@ export class ViewFileDecorationProvider implements FileDecorationProvider, Dispo return { badge: GlyphChars.Check, - tooltip: 'Default Remote', + tooltip: localize('defaultRemote', 'Default Remote'), }; } } diff --git a/src/views/worktreesView.ts b/src/views/worktreesView.ts index c5b777a354d36..e67659c796dc4 100644 --- a/src/views/worktreesView.ts +++ b/src/views/worktreesView.ts @@ -10,6 +10,7 @@ import { TreeViewVisibilityChangeEvent, window, } from 'vscode'; +import * as nls from 'vscode-nls'; import { configuration, ViewFilesLayout, ViewShowBranchComparison, WorktreesViewConfig } from '../configuration'; import { Container } from '../container'; import { PlusFeatures } from '../features'; @@ -18,7 +19,6 @@ import { GitWorktree, RepositoryChange, RepositoryChangeComparisonMode, Reposito import { ensurePlusFeaturesEnabled } from '../plus/subscription/utils'; import { getSubscriptionTimeRemaining, SubscriptionState } from '../subscription'; import { gate } from '../system/decorators/gate'; -import { pluralize } from '../system/string'; import { RepositoriesSubscribeableNode, RepositoryFolderNode, @@ -29,6 +29,8 @@ import { } from './nodes'; import { ViewBase } from './viewBase'; +const localize = nls.loadMessageBundle(); + export class WorktreesRepositoryNode extends RepositoryFolderNode { getChildren(): Promise { if (this.child == null) { @@ -56,7 +58,7 @@ export class WorktreesViewNode extends RepositoriesSubscribeableNode { diff --git a/src/vsls/guest.ts b/src/vsls/guest.ts index d8c9401079965..4fd217abdd6e2 100644 --- a/src/vsls/guest.ts +++ b/src/vsls/guest.ts @@ -1,4 +1,5 @@ import { CancellationToken, Disposable, Uri, window } from 'vscode'; +import * as nls from 'vscode-nls'; import type { LiveShare, SharedServiceProxy } from '../@types/vsls'; import { Container } from '../container'; import { GitCommandOptions } from '../git/commandOptions'; @@ -7,6 +8,7 @@ import { debug, log } from '../system/decorators/log'; import { VslsHostService } from './host'; import { GetRepositoriesForUriRequestType, GitCommandRequestType, RepositoryProxy, RequestType } from './protocol'; +const localize = nls.loadMessageBundle(); export class VslsGuestService implements Disposable { @log() static async connect(api: LiveShare, container: Container) { @@ -48,7 +50,10 @@ export class VslsGuestService implements Disposable { void this.container.git.setEnabledContext(false); void window.showWarningMessage( - 'GitLens features will be unavailable. Unable to connect to the host GitLens service. The host may have disabled GitLens guest access or may not have GitLens installed.', + localize( + 'gitlensFeaturesWillBeUnavailableUnableToConnectToHostService', + 'GitLens features will be unavailable. Unable to connect to the host GitLens service. The host may have disabled GitLens guest access or may not have GitLens installed.', + ), ); } diff --git a/src/vsls/vsls.ts b/src/vsls/vsls.ts index c0badf908a35a..49a234d859798 100644 --- a/src/vsls/vsls.ts +++ b/src/vsls/vsls.ts @@ -1,4 +1,5 @@ import { Disposable, extensions, workspace } from 'vscode'; +import * as nls from 'vscode-nls'; import type { LiveShare, LiveShareExtension, SessionChangeEvent } from '../@types/vsls'; import { ContextKeys, Schemes } from '../constants'; import { Container } from '../container'; @@ -11,6 +12,7 @@ import { defer, Deferred } from '../system/promise'; import { VslsGuestService } from './guest'; import { VslsHostService } from './host'; +const localize = nls.loadMessageBundle(); export interface ContactPresence { status: ContactPresenceStatus; statusText: string; @@ -20,15 +22,15 @@ export type ContactPresenceStatus = 'online' | 'away' | 'busy' | 'dnd' | 'offlin function contactStatusToPresence(status: string | undefined): ContactPresence { switch (status) { case 'available': - return { status: 'online', statusText: 'Available' }; + return { status: 'online', statusText: localize('contact.status.available', 'Available') }; case 'away': - return { status: 'away', statusText: 'Away' }; + return { status: 'away', statusText: localize('contact.status.away', 'Away') }; case 'busy': - return { status: 'busy', statusText: 'Busy' }; + return { status: 'busy', statusText: localize('contact.status.busy', 'Busy') }; case 'doNotDisturb': - return { status: 'dnd', statusText: 'DND' }; + return { status: 'dnd', statusText: localize('contact.status.DND', 'DND') }; default: - return { status: 'offline', statusText: 'Offline' }; + return { status: 'offline', statusText: localize('contact.status.offline', 'Offline') }; } } diff --git a/webpack.config.js b/webpack.config.js index f92865cebf03d..feefd02bcab80 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -168,32 +168,40 @@ function getExtensionConfig(target, mode, env) { exclude: /\.d\.ts$/, include: path.join(__dirname, 'src'), test: /\.tsx?$/, - use: env.esbuild - ? { - loader: 'esbuild-loader', - options: { - implementation: esbuild, - loader: 'ts', - target: ['es2020', 'chrome91', 'node14.16'], - tsconfigRaw: resolveTSConfig( - path.join( + use: [ + { + loader: 'vscode-nls-dev/lib/webpack-loader', + options: { + base: __dirname, + }, + }, + env.esbuild + ? { + loader: 'esbuild-loader', + options: { + implementation: esbuild, + loader: 'ts', + target: ['es2020', 'chrome91', 'node14.16'], + tsconfigRaw: resolveTSConfig( + path.join( + __dirname, + target === 'webworker' ? 'tsconfig.browser.json' : 'tsconfig.json', + ), + ), + }, + } + : { + loader: 'ts-loader', + options: { + configFile: path.join( __dirname, target === 'webworker' ? 'tsconfig.browser.json' : 'tsconfig.json', ), - ), - }, - } - : { - loader: 'ts-loader', - options: { - configFile: path.join( - __dirname, - target === 'webworker' ? 'tsconfig.browser.json' : 'tsconfig.json', - ), - experimentalWatchApi: true, - transpileOnly: true, - }, - }, + experimentalWatchApi: true, + transpileOnly: true, + }, + }, + ], }, ], }, @@ -360,24 +368,32 @@ function getWebviewsConfig(mode, env) { exclude: /\.d\.ts$/, include: path.join(__dirname, 'src'), test: /\.tsx?$/, - use: env.esbuild - ? { - loader: 'esbuild-loader', - options: { - implementation: esbuild, - loader: 'ts', - target: 'es2020', - tsconfigRaw: resolveTSConfig(path.join(basePath, 'tsconfig.json')), - }, - } - : { - loader: 'ts-loader', - options: { - configFile: path.join(basePath, 'tsconfig.json'), - experimentalWatchApi: true, - transpileOnly: true, - }, - }, + use: [ + { + loader: 'vscode-nls-dev/lib/webpack-loader', + options: { + base: __dirname, + }, + }, + env.esbuild + ? { + loader: 'esbuild-loader', + options: { + implementation: esbuild, + loader: 'ts', + target: 'es2020', + tsconfigRaw: resolveTSConfig(path.join(basePath, 'tsconfig.json')), + }, + } + : { + loader: 'ts-loader', + options: { + configFile: path.join(basePath, 'tsconfig.json'), + experimentalWatchApi: true, + transpileOnly: true, + }, + }, + ], }, { test: /\.scss$/,