Fix #42447
This commit is contained in:
parent
75cf5c46bd
commit
191596365d
|
@ -66,6 +66,10 @@
|
|||
"name": "vs/workbench/parts/markers",
|
||||
"project": "vscode-workbench"
|
||||
},
|
||||
{
|
||||
"name": "vs/workbench/parts/localizations",
|
||||
"project": "vscode-workbench"
|
||||
},
|
||||
{
|
||||
"name": "vs/workbench/parts/logs",
|
||||
"project": "vscode-workbench"
|
||||
|
|
|
@ -28,9 +28,6 @@ export function activate(context: vscode.ExtensionContext): void {
|
|||
//extensions suggestions
|
||||
context.subscriptions.push(...registerExtensionsCompletions());
|
||||
|
||||
//locale suggestions
|
||||
context.subscriptions.push(registerLocaleCompletionsInLanguageDocument());
|
||||
|
||||
// launch.json decorations
|
||||
context.subscriptions.push(vscode.window.onDidChangeActiveTextEditor(editor => updateLaunchJsonDecorations(editor), null, context.subscriptions));
|
||||
context.subscriptions.push(vscode.workspace.onDidChangeTextDocument(event => {
|
||||
|
@ -109,20 +106,6 @@ function registerSettingsCompletions(): vscode.Disposable {
|
|||
});
|
||||
}
|
||||
|
||||
function registerLocaleCompletionsInLanguageDocument(): vscode.Disposable {
|
||||
return vscode.languages.registerCompletionItemProvider({ pattern: '**/locale.json' }, {
|
||||
provideCompletionItems(document, position, token) {
|
||||
const location = getLocation(document.getText(), document.offsetAt(position));
|
||||
const range = document.getWordRangeAtPosition(position) || new vscode.Range(position, position);
|
||||
if (location.path[0] === 'locale') {
|
||||
const extensionsContent = <IExtensionsContent>parse(document.getText());
|
||||
return provideContributedLocalesProposals(range);
|
||||
}
|
||||
return [];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function provideContributedLocalesProposals(range: vscode.Range): vscode.ProviderResult<vscode.CompletionItem[] | vscode.CompletionList> {
|
||||
const contributedLocales: string[] = [];
|
||||
for (const extension of vscode.extensions.all) {
|
||||
|
|
|
@ -8,11 +8,9 @@
|
|||
import { NodeCachedDataCleaner } from 'vs/code/electron-browser/sharedProcess/contrib/nodeCachedDataCleaner';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IDisposable, combinedDisposable } from 'vs/base/common/lifecycle';
|
||||
import { LanguagePacksCache } from 'vs/platform/localizations/node/localizations';
|
||||
|
||||
export function createSharedProcessContributions(service: IInstantiationService): IDisposable {
|
||||
return combinedDisposable([
|
||||
service.createInstance(NodeCachedDataCleaner),
|
||||
service.createInstance(LanguagePacksCache)
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -40,6 +40,9 @@ import { createSharedProcessContributions } from 'vs/code/electron-browser/share
|
|||
import { createSpdLogService } from 'vs/platform/log/node/spdlogService';
|
||||
import { ILogService, LogLevel } from 'vs/platform/log/common/log';
|
||||
import { LogLevelSetterChannelClient, FollowerLogService } from 'vs/platform/log/common/logIpc';
|
||||
import { LocalizationsService } from 'vs/platform/localizations/node/localizations';
|
||||
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
|
||||
import { LocalizationsChannel } from 'vs/platform/localizations/common/localizationsIpc';
|
||||
|
||||
export interface ISharedProcessConfiguration {
|
||||
readonly machineId: string;
|
||||
|
@ -141,6 +144,7 @@ function main(server: Server, initData: ISharedProcessInitData, configuration: I
|
|||
|
||||
services.set(IExtensionManagementService, new SyncDescriptor(ExtensionManagementService));
|
||||
services.set(IExtensionGalleryService, new SyncDescriptor(ExtensionGalleryService));
|
||||
services.set(ILocalizationsService, new SyncDescriptor(LocalizationsService));
|
||||
|
||||
const instantiationService2 = instantiationService.createChild(services);
|
||||
|
||||
|
@ -152,6 +156,10 @@ function main(server: Server, initData: ISharedProcessInitData, configuration: I
|
|||
// clean up deprecated extensions
|
||||
(extensionManagementService as ExtensionManagementService).removeDeprecatedExtensions();
|
||||
|
||||
const localizationsService = accessor.get(ILocalizationsService);
|
||||
const localizationsChannel = new LocalizationsChannel(localizationsService);
|
||||
server.registerChannel('localizations', localizationsChannel);
|
||||
|
||||
createSharedProcessContributions(instantiationService2);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import { ExtensionsRegistry } from 'vs/platform/extensions/common/extensionsRegistry';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import Event from 'vs/base/common/event';
|
||||
|
||||
export interface ILocalization {
|
||||
languageId: string;
|
||||
|
@ -23,6 +23,9 @@ export interface ITranslation {
|
|||
export const ILocalizationsService = createDecorator<ILocalizationsService>('localizationsService');
|
||||
export interface ILocalizationsService {
|
||||
_serviceBrand: any;
|
||||
|
||||
readonly onDidLanguagesChange: Event<void>;
|
||||
getLanguageIds(): TPromise<string[]>;
|
||||
}
|
||||
|
||||
export function isValidLocalization(localization: ILocalization): boolean {
|
||||
|
@ -47,51 +50,4 @@ export function isValidLocalization(localization: ILocalization): boolean {
|
|||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ExtensionsRegistry.registerExtensionPoint('localizations', [], {
|
||||
description: localize('vscode.extension.contributes.localizations', "Contributes localizations to the editor"),
|
||||
type: 'array',
|
||||
default: [],
|
||||
items: {
|
||||
type: 'object',
|
||||
required: ['languageId', 'translations'],
|
||||
defaultSnippets: [{ body: { languageId: '', languageName: '', languageNameLocalized: '', translations: [{ id: 'vscode', path: '' }] } }],
|
||||
properties: {
|
||||
languageId: {
|
||||
description: localize('vscode.extension.contributes.localizations.languageId', 'Id of the language into which the display strings are translated.'),
|
||||
type: 'string'
|
||||
},
|
||||
languageName: {
|
||||
description: localize('vscode.extension.contributes.localizations.languageName', 'Name of the language in English.'),
|
||||
type: 'string'
|
||||
},
|
||||
languageNameLocalized: {
|
||||
description: localize('vscode.extension.contributes.localizations.languageNameLocalized', 'Name of the language in contributed language.'),
|
||||
type: 'string'
|
||||
},
|
||||
translations: {
|
||||
description: localize('vscode.extension.contributes.localizations.translations', 'List of translations associated to the language.'),
|
||||
type: 'array',
|
||||
default: [{ id: 'vscode', path: '' }],
|
||||
items: {
|
||||
type: 'object',
|
||||
required: ['id', 'path'],
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: localize('vscode.extension.contributes.localizations.translations.id', "Id of VS Code or Extension for which this translation is contributed to. Id of VS Code is always `vscode` and of extension should be in format `publisherId.extensionName`."),
|
||||
pattern: '^((vscode)|([a-z0-9A-Z][a-z0-9\-A-Z]*)\\.([a-z0-9A-Z][a-z0-9\-A-Z]*))$',
|
||||
patternErrorMessage: localize('vscode.extension.contributes.localizations.translations.id.pattern', "Id should be `vscode` or in format `publisherId.extensionName` for translating VS code or an extension respectively.")
|
||||
},
|
||||
path: {
|
||||
type: 'string',
|
||||
description: localize('vscode.extension.contributes.localizations.translations.path', "A relative path to a file containing translations for the language.")
|
||||
}
|
||||
},
|
||||
defaultSnippets: [{ body: { id: '', path: '' } }],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
48
src/vs/platform/localizations/common/localizationsIpc.ts
Normal file
48
src/vs/platform/localizations/common/localizationsIpc.ts
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IChannel, eventToCall, eventFromCall } from 'vs/base/parts/ipc/common/ipc';
|
||||
import Event, { buffer } from 'vs/base/common/event';
|
||||
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
|
||||
|
||||
export interface ILocalizationsChannel extends IChannel {
|
||||
call(command: 'event:onDidLanguagesChange'): TPromise<void>;
|
||||
call(command: 'getLanguageIds'): TPromise<string[]>;
|
||||
call(command: string, arg?: any): TPromise<any>;
|
||||
}
|
||||
|
||||
export class LocalizationsChannel implements ILocalizationsChannel {
|
||||
|
||||
onDidLanguagesChange: Event<void>;
|
||||
|
||||
constructor(private service: ILocalizationsService) {
|
||||
this.onDidLanguagesChange = buffer(service.onDidLanguagesChange, true);
|
||||
}
|
||||
|
||||
call(command: string, arg?: any): TPromise<any> {
|
||||
switch (command) {
|
||||
case 'event:onDidLanguagesChange': return eventToCall(this.onDidLanguagesChange);
|
||||
case 'getLanguageIds': return this.service.getLanguageIds();
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export class LocalizationsChannelClient implements ILocalizationsService {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
constructor(private channel: ILocalizationsChannel) { }
|
||||
|
||||
private _onDidLanguagesChange = eventFromCall<void>(this.channel, 'event:onDidLanguagesChange');
|
||||
get onDidLanguagesChange(): Event<void> { return this._onDidLanguagesChange; }
|
||||
|
||||
getLanguageIds(): TPromise<string[]> {
|
||||
return this.channel.call('getLanguageIds');
|
||||
}
|
||||
}
|
|
@ -11,9 +11,12 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
|
|||
import { join } from 'vs/base/common/paths';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { Limiter } from 'vs/base/common/async';
|
||||
import { areSameExtensions, getGalleryExtensionIdFromLocal } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { areSameExtensions, getGalleryExtensionIdFromLocal, getIdFromLocalExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { isValidLocalization } from 'vs/platform/localizations/common/localizations';
|
||||
import { isValidLocalization, ILocalizationsService } from 'vs/platform/localizations/common/localizations';
|
||||
import product from 'vs/platform/node/product';
|
||||
import { distinct, equals } from 'vs/base/common/arrays';
|
||||
import Event, { Emitter } from 'vs/base/common/event';
|
||||
|
||||
interface ILanguagePack {
|
||||
hash: string;
|
||||
|
@ -24,10 +27,19 @@ interface ILanguagePack {
|
|||
translations: { [id: string]: string };
|
||||
}
|
||||
|
||||
export class LanguagePacksCache extends Disposable {
|
||||
const systemLanguages: string[] = ['de', 'en', 'en-US', 'es', 'fr', 'it', 'ja', 'ko', 'ru', 'zh-CN', 'zh-TW'];
|
||||
if (product.quality !== 'stable') {
|
||||
systemLanguages.push('hu');
|
||||
}
|
||||
|
||||
private languagePacksFilePath: string;
|
||||
private languagePacksFileLimiter: Limiter<void>;
|
||||
export class LocalizationsService extends Disposable implements ILocalizationsService {
|
||||
|
||||
_serviceBrand: any;
|
||||
|
||||
private readonly cache: LanguagePacksCache;
|
||||
|
||||
private readonly _onDidLanguagesChange: Emitter<void> = this._register(new Emitter<void>());
|
||||
readonly onDidLanguagesChange: Event<void> = this._onDidLanguagesChange.event;
|
||||
|
||||
constructor(
|
||||
@IExtensionManagementService private extensionManagementService: IExtensionManagementService,
|
||||
|
@ -35,37 +47,80 @@ export class LanguagePacksCache extends Disposable {
|
|||
@ILogService private logService: ILogService
|
||||
) {
|
||||
super();
|
||||
this.languagePacksFilePath = join(environmentService.userDataPath, 'languagepacks.json');
|
||||
this.languagePacksFileLimiter = new Limiter(1);
|
||||
this.cache = this._register(new LanguagePacksCache(environmentService, logService));
|
||||
|
||||
this._register(extensionManagementService.onDidInstallExtension(({ local }) => this.onDidInstallExtension(local)));
|
||||
this._register(extensionManagementService.onDidUninstallExtension(({ identifier }) => this.onDidUninstallExtension(identifier)));
|
||||
|
||||
this.reset();
|
||||
this.extensionManagementService.getInstalled().then(installed => this.cache.update(installed));
|
||||
}
|
||||
|
||||
getLanguageIds(): TPromise<string[]> {
|
||||
return this.cache.getLanguagePacks()
|
||||
.then(languagePacks => {
|
||||
const languages = [...systemLanguages, ...Object.keys(languagePacks)];
|
||||
return TPromise.as(distinct(languages));
|
||||
});
|
||||
}
|
||||
|
||||
private onDidInstallExtension(extension: ILocalExtension): void {
|
||||
if (extension && extension.manifest && extension.manifest.contributes && extension.manifest.contributes.localizations && extension.manifest.contributes.localizations.length) {
|
||||
this.logService.debug('Adding language packs from the extension', extension.identifier.id);
|
||||
this.reset();
|
||||
this.update();
|
||||
}
|
||||
}
|
||||
|
||||
private onDidUninstallExtension(identifier: IExtensionIdentifier): void {
|
||||
if (this.withLanguagePacks(languagePacks => Object.keys(languagePacks).some(language => languagePacks[language] && languagePacks[language].extensions.some(e => areSameExtensions(e.extensionIdentifier, identifier))))) {
|
||||
this.logService.debug('Removing language packs from the extension', identifier.id);
|
||||
this.reset();
|
||||
}
|
||||
this.cache.getLanguagePacks()
|
||||
.then(languagePacks => {
|
||||
identifier = { id: getIdFromLocalExtensionId(identifier.id), uuid: identifier.uuid };
|
||||
if (Object.keys(languagePacks).some(language => languagePacks[language] && languagePacks[language].extensions.some(e => areSameExtensions(e.extensionIdentifier, identifier)))) {
|
||||
this.logService.debug('Removing language packs from the extension', identifier.id);
|
||||
this.update();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private reset(): void {
|
||||
this.extensionManagementService.getInstalled()
|
||||
.then(installed => {
|
||||
this.withLanguagePacks(languagePacks => {
|
||||
Object.keys(languagePacks).forEach(language => languagePacks[language] = undefined);
|
||||
this.createLanguagePacksFromExtensions(languagePacks, ...installed);
|
||||
});
|
||||
});
|
||||
private update(): void {
|
||||
TPromise.join([this.cache.getLanguagePacks(), this.extensionManagementService.getInstalled()])
|
||||
.then(([current, installed]) => this.cache.update(installed)
|
||||
.then(updated => {
|
||||
if (!equals(Object.keys(current), Object.keys(updated))) {
|
||||
this._onDidLanguagesChange.fire();
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
class LanguagePacksCache extends Disposable {
|
||||
|
||||
private languagePacks: { [language: string]: ILanguagePack } = {};
|
||||
private languagePacksFilePath: string;
|
||||
private languagePacksFileLimiter: Limiter<void>;
|
||||
|
||||
constructor(
|
||||
@IEnvironmentService environmentService: IEnvironmentService,
|
||||
@ILogService private logService: ILogService
|
||||
) {
|
||||
super();
|
||||
this.languagePacksFilePath = join(environmentService.userDataPath, 'languagepacks.json');
|
||||
this.languagePacksFileLimiter = new Limiter(1);
|
||||
}
|
||||
|
||||
getLanguagePacks(): TPromise<{ [language: string]: ILanguagePack }> {
|
||||
// if queue is not empty, fetch from disk
|
||||
if (this.languagePacksFileLimiter.size) {
|
||||
return this.withLanguagePacks()
|
||||
.then(() => this.languagePacks);
|
||||
}
|
||||
return TPromise.as(this.languagePacks);
|
||||
}
|
||||
|
||||
update(extensions: ILocalExtension[]): TPromise<{ [language: string]: ILanguagePack }> {
|
||||
return this.withLanguagePacks(languagePacks => {
|
||||
Object.keys(languagePacks).forEach(language => languagePacks[language] = undefined);
|
||||
this.createLanguagePacksFromExtensions(languagePacks, ...extensions);
|
||||
}).then(() => this.languagePacks);
|
||||
}
|
||||
|
||||
private createLanguagePacksFromExtensions(languagePacks: { [language: string]: ILanguagePack }, ...extensions: ILocalExtension[]): void {
|
||||
|
@ -109,7 +164,7 @@ export class LanguagePacksCache extends Disposable {
|
|||
}
|
||||
}
|
||||
|
||||
private withLanguagePacks<T>(fn: (languagePacks: { [language: string]: ILanguagePack }) => T): TPromise<T> {
|
||||
private withLanguagePacks<T>(fn: (languagePacks: { [language: string]: ILanguagePack }) => T = () => null): TPromise<T> {
|
||||
return this.languagePacksFileLimiter.queue(() => {
|
||||
let result: T = null;
|
||||
return pfs.readFile(this.languagePacksFilePath, 'utf8')
|
||||
|
@ -122,7 +177,8 @@ export class LanguagePacksCache extends Disposable {
|
|||
delete languagePacks[language];
|
||||
}
|
||||
}
|
||||
const raw = JSON.stringify(languagePacks);
|
||||
this.languagePacks = languagePacks;
|
||||
const raw = JSON.stringify(this.languagePacks);
|
||||
this.logService.debug('Writing language packs', raw);
|
||||
return pfs.writeFile(this.languagePacksFilePath, raw);
|
||||
})
|
||||
|
|
|
@ -23,7 +23,7 @@ import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configur
|
|||
import { IExtensionManagementService, LocalExtensionType, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IWorkspaceConfigurationService } from 'vs/workbench/services/configuration/common/configuration';
|
||||
import paths = require('vs/base/common/paths');
|
||||
import { isMacintosh, isLinux, language } from 'vs/base/common/platform';
|
||||
import { isMacintosh, isLinux } from 'vs/base/common/platform';
|
||||
import { IQuickOpenService, IFilePickOpenEntry, ISeparator, IPickOpenAction, IPickOpenItem } from 'vs/platform/quickOpen/common/quickOpen';
|
||||
import * as browser from 'vs/base/browser/browser';
|
||||
import { IIntegrityService } from 'vs/platform/integrity/common/integrity';
|
||||
|
@ -40,11 +40,10 @@ import { getPathLabel, getBaseLabel } from 'vs/base/common/labels';
|
|||
import { IViewlet } from 'vs/workbench/common/viewlet';
|
||||
import { IPanel } from 'vs/workbench/common/panel';
|
||||
import { IWorkspaceIdentifier, getWorkspaceLabel, ISingleFolderWorkspaceIdentifier, isSingleFolderWorkspaceIdentifier } from 'vs/platform/workspaces/common/workspaces';
|
||||
import { FileKind, IFileService } from 'vs/platform/files/common/files';
|
||||
import { FileKind } from 'vs/platform/files/common/files';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtensionService, ActivationTimes } from 'vs/platform/extensions/common/extensions';
|
||||
import { getEntries } from 'vs/base/common/performance';
|
||||
import { IEditor } from 'vs/platform/editor/common/editor';
|
||||
import { IIssueService, IssueReporterData, IssueType, IssueReporterStyles } from 'vs/platform/issue/common/issue';
|
||||
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
|
||||
import { textLinkForeground, inputBackground, inputBorder, inputForeground, buttonBackground, buttonHoverBackground, buttonForeground, inputValidationErrorBorder, foreground, inputActiveOptionBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
|
@ -1605,46 +1604,4 @@ export class ToggleWindowTabsBar extends Action {
|
|||
public run(): TPromise<boolean> {
|
||||
return this.windowsService.toggleWindowTabsBar().then(() => true);
|
||||
}
|
||||
}
|
||||
|
||||
export class ConfigureLocaleAction extends Action {
|
||||
public static readonly ID = 'workbench.action.configureLocale';
|
||||
public static readonly LABEL = nls.localize('configureLocale', "Configure Language");
|
||||
|
||||
private static DEFAULT_CONTENT: string = [
|
||||
'{',
|
||||
`\t// ${nls.localize('displayLanguage', 'Defines VSCode\'s display language.')}`,
|
||||
`\t// ${nls.localize('doc', 'See {0} for a list of supported languages.', 'https://go.microsoft.com/fwlink/?LinkId=761051')}`,
|
||||
`\t// ${nls.localize('restart', 'Changing the value requires restarting VSCode.')}`,
|
||||
`\t"locale":"${language}"`,
|
||||
'}'
|
||||
].join('\n');
|
||||
|
||||
constructor(id: string, label: string,
|
||||
@IFileService private fileService: IFileService,
|
||||
@IWorkspaceContextService private contextService: IWorkspaceContextService,
|
||||
@IEnvironmentService private environmentService: IEnvironmentService,
|
||||
@IWorkbenchEditorService private editorService: IWorkbenchEditorService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
public run(event?: any): TPromise<IEditor> {
|
||||
const file = URI.file(paths.join(this.environmentService.appSettingsHome, 'locale.json'));
|
||||
return this.fileService.resolveFile(file).then(null, (error) => {
|
||||
return this.fileService.createFile(file, ConfigureLocaleAction.DEFAULT_CONTENT);
|
||||
}).then((stat) => {
|
||||
if (!stat) {
|
||||
return undefined;
|
||||
}
|
||||
return this.editorService.openEditor({
|
||||
resource: stat.resource,
|
||||
options: {
|
||||
forceOpen: true
|
||||
}
|
||||
});
|
||||
}, (error) => {
|
||||
throw new Error(nls.localize('fail.createSettings', "Unable to create '{0}' ({1}).", getPathLabel(file, this.contextService), error));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,15 +14,13 @@ import { IConfigurationRegistry, Extensions as ConfigurationExtensions } from 'v
|
|||
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
|
||||
import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { isWindows, isLinux, isMacintosh } from 'vs/base/common/platform';
|
||||
import { KeybindingsReferenceAction, OpenDocumentationUrlAction, OpenIntroductoryVideosUrlAction, OpenTipsAndTricksUrlAction, OpenIssueReporterAction, ReportPerformanceIssueUsingReporterAction, ZoomResetAction, ZoomOutAction, ZoomInAction, ToggleFullScreenAction, ToggleMenuBarAction, CloseWorkspaceAction, CloseCurrentWindowAction, SwitchWindow, NewWindowAction, CloseMessagesAction, NavigateUpAction, NavigateDownAction, NavigateLeftAction, NavigateRightAction, IncreaseViewSizeAction, DecreaseViewSizeAction, ShowStartupPerformance, ToggleSharedProcessAction, QuickSwitchWindow, QuickOpenRecentAction, inRecentFilesPickerContextKey, ConfigureLocaleAction } from 'vs/workbench/electron-browser/actions';
|
||||
import { KeybindingsReferenceAction, OpenDocumentationUrlAction, OpenIntroductoryVideosUrlAction, OpenTipsAndTricksUrlAction, OpenIssueReporterAction, ReportPerformanceIssueUsingReporterAction, ZoomResetAction, ZoomOutAction, ZoomInAction, ToggleFullScreenAction, ToggleMenuBarAction, CloseWorkspaceAction, CloseCurrentWindowAction, SwitchWindow, NewWindowAction, CloseMessagesAction, NavigateUpAction, NavigateDownAction, NavigateLeftAction, NavigateRightAction, IncreaseViewSizeAction, DecreaseViewSizeAction, ShowStartupPerformance, ToggleSharedProcessAction, QuickSwitchWindow, QuickOpenRecentAction, inRecentFilesPickerContextKey } from 'vs/workbench/electron-browser/actions';
|
||||
import { MessagesVisibleContext } from 'vs/workbench/electron-browser/workbench';
|
||||
import { IJSONSchema } from 'vs/base/common/jsonSchema';
|
||||
import { registerCommands } from 'vs/workbench/electron-browser/commands';
|
||||
import { AddRootFolderAction, GlobalRemoveRootFolderAction, OpenWorkspaceAction, SaveWorkspaceAsAction, OpenWorkspaceConfigFileAction, OpenFolderAsWorkspaceInNewWindowAction, OpenFileFolderAction, OpenFileAction, OpenFolderAction } from 'vs/workbench/browser/actions/workspaceActions';
|
||||
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { inQuickOpenContext, getQuickNavigateHandler } from 'vs/workbench/browser/parts/quickopen/quickopen';
|
||||
import { KeybindingsRegistry } from 'vs/platform/keybinding/common/keybindingsRegistry';
|
||||
import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
|
||||
|
||||
// Contribute Commands
|
||||
registerCommands();
|
||||
|
@ -425,38 +423,4 @@ configurationRegistry.registerConfiguration({
|
|||
'description': nls.localize('zenMode.restore', "Controls if a window should restore to zen mode if it was exited in zen mode.")
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Register action to configure locale and related settings
|
||||
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ConfigureLocaleAction, ConfigureLocaleAction.ID, ConfigureLocaleAction.LABEL), 'Configure Language');
|
||||
|
||||
let enumValues: string[] = ['de', 'en', 'en-US', 'es', 'fr', 'it', 'ja', 'ko', 'ru', 'zh-CN', 'zh-TW'];
|
||||
if (product.quality !== 'stable') {
|
||||
enumValues.push('hu');
|
||||
}
|
||||
|
||||
const schemaId = 'vscode://schemas/locale';
|
||||
// Keep en-US since we generated files with that content.
|
||||
const schema: IJSONSchema =
|
||||
{
|
||||
id: schemaId,
|
||||
allowComments: true,
|
||||
description: 'Locale Definition file',
|
||||
type: 'object',
|
||||
default: {
|
||||
'locale': 'en'
|
||||
},
|
||||
required: ['locale'],
|
||||
properties: {
|
||||
locale: {
|
||||
type: 'string',
|
||||
enum: enumValues,
|
||||
description: nls.localize('JsonSchema.locale', 'The UI Language to use.')
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const jsonRegistry = Registry.as<IJSONContributionRegistry>(JSONExtensions.JSONContribution);
|
||||
jsonRegistry.registerSchema(schemaId, schema);
|
||||
});
|
|
@ -90,6 +90,8 @@ import { ILogService } from 'vs/platform/log/common/log';
|
|||
import { WORKBENCH_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
import { stat } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { ILocalizationsChannel, LocalizationsChannelClient } from 'vs/platform/localizations/common/localizationsIpc';
|
||||
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
|
||||
|
||||
/**
|
||||
* Services that we require for the Shell
|
||||
|
@ -447,6 +449,9 @@ export class WorkbenchShell {
|
|||
|
||||
serviceCollection.set(IIntegrityService, new SyncDescriptor(IntegrityServiceImpl));
|
||||
|
||||
const localizationsChannel = getDelayedChannel<ILocalizationsChannel>(sharedProcess.then(c => c.getChannel('localizations')));
|
||||
serviceCollection.set(ILocalizationsService, new SyncDescriptor(LocalizationsChannelClient, localizationsChannel));
|
||||
|
||||
return [instantiationService, serviceCollection];
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IWorkbenchContribution, Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
|
||||
import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
|
||||
import { IWorkbenchActionRegistry, Extensions } from 'vs/workbench/common/actions';
|
||||
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { ConfigureLocaleAction } from 'vs/workbench/parts/localizations/browser/localizationsActions';
|
||||
import { ExtensionsRegistry } from 'vs/platform/extensions/common/extensionsRegistry';
|
||||
import { ILocalizationsService } from 'vs/platform/localizations/common/localizations';
|
||||
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { language } from 'vs/base/common/platform';
|
||||
|
||||
// Register action to configure locale and related settings
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(new SyncActionDescriptor(ConfigureLocaleAction, ConfigureLocaleAction.ID, ConfigureLocaleAction.LABEL), 'Configure Language');
|
||||
|
||||
export class LocalesSchemaUpdater extends Disposable implements IWorkbenchContribution {
|
||||
constructor(
|
||||
@ILocalizationsService private localizationService: ILocalizationsService
|
||||
) {
|
||||
super();
|
||||
this.update();
|
||||
this._register(this.localizationService.onDidLanguagesChange(() => this.update()));
|
||||
}
|
||||
|
||||
private update(): void {
|
||||
this.localizationService.getLanguageIds()
|
||||
.then(languageIds => registerLocaleDefinitionSchema(languageIds));
|
||||
}
|
||||
}
|
||||
|
||||
function registerLocaleDefinitionSchema(languages: string[]): void {
|
||||
const localeDefinitionFileSchemaId = 'vscode://schemas/locale';
|
||||
const jsonRegistry = Registry.as<IJSONContributionRegistry>(JSONExtensions.JSONContribution);
|
||||
// Keep en-US since we generated files with that content.
|
||||
jsonRegistry.registerSchema(localeDefinitionFileSchemaId, {
|
||||
id: localeDefinitionFileSchemaId,
|
||||
allowComments: true,
|
||||
description: 'Locale Definition file',
|
||||
type: 'object',
|
||||
default: {
|
||||
'locale': 'en'
|
||||
},
|
||||
required: ['locale'],
|
||||
properties: {
|
||||
locale: {
|
||||
type: 'string',
|
||||
enum: languages,
|
||||
description: localize('JsonSchema.locale', 'The UI Language to use.')
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
registerLocaleDefinitionSchema([language]);
|
||||
const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
|
||||
workbenchRegistry.registerWorkbenchContribution(LocalesSchemaUpdater, LifecyclePhase.Eventually);
|
||||
|
||||
ExtensionsRegistry.registerExtensionPoint('localizations', [], {
|
||||
description: localize('vscode.extension.contributes.localizations', "Contributes localizations to the editor"),
|
||||
type: 'array',
|
||||
default: [],
|
||||
items: {
|
||||
type: 'object',
|
||||
required: ['languageId', 'translations'],
|
||||
defaultSnippets: [{ body: { languageId: '', languageName: '', languageNameLocalized: '', translations: [{ id: 'vscode', path: '' }] } }],
|
||||
properties: {
|
||||
languageId: {
|
||||
description: localize('vscode.extension.contributes.localizations.languageId', 'Id of the language into which the display strings are translated.'),
|
||||
type: 'string'
|
||||
},
|
||||
languageName: {
|
||||
description: localize('vscode.extension.contributes.localizations.languageName', 'Name of the language in English.'),
|
||||
type: 'string'
|
||||
},
|
||||
languageNameLocalized: {
|
||||
description: localize('vscode.extension.contributes.localizations.languageNameLocalized', 'Name of the language in contributed language.'),
|
||||
type: 'string'
|
||||
},
|
||||
translations: {
|
||||
description: localize('vscode.extension.contributes.localizations.translations', 'List of translations associated to the language.'),
|
||||
type: 'array',
|
||||
default: [{ id: 'vscode', path: '' }],
|
||||
items: {
|
||||
type: 'object',
|
||||
required: ['id', 'path'],
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string',
|
||||
description: localize('vscode.extension.contributes.localizations.translations.id', "Id of VS Code or Extension for which this translation is contributed to. Id of VS Code is always `vscode` and of extension should be in format `publisherId.extensionName`."),
|
||||
pattern: '^((vscode)|([a-z0-9A-Z][a-z0-9\-A-Z]*)\\.([a-z0-9A-Z][a-z0-9\-A-Z]*))$',
|
||||
patternErrorMessage: localize('vscode.extension.contributes.localizations.translations.id.pattern', "Id should be `vscode` or in format `publisherId.extensionName` for translating VS code or an extension respectively.")
|
||||
},
|
||||
path: {
|
||||
type: 'string',
|
||||
description: localize('vscode.extension.contributes.localizations.translations.path', "A relative path to a file containing translations for the language.")
|
||||
}
|
||||
},
|
||||
defaultSnippets: [{ body: { id: '', path: '' } }],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
|
@ -0,0 +1,59 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { localize } from 'vs/nls';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { TPromise } from 'vs/base/common/winjs.base';
|
||||
import { IEditor } from 'vs/platform/editor/common/editor';
|
||||
import { join } from 'vs/base/common/paths';
|
||||
import URI from 'vs/base/common/uri';
|
||||
import { IWorkbenchEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { getPathLabel } from 'vs/base/common/labels';
|
||||
import { language } from 'vs/base/common/platform';
|
||||
|
||||
export class ConfigureLocaleAction extends Action {
|
||||
public static readonly ID = 'workbench.action.configureLocale';
|
||||
public static readonly LABEL = localize('configureLocale', "Configure Language");
|
||||
|
||||
private static DEFAULT_CONTENT: string = [
|
||||
'{',
|
||||
`\t// ${localize('displayLanguage', 'Defines VSCode\'s display language.')}`,
|
||||
`\t// ${localize('doc', 'See {0} for a list of supported languages.', 'https://go.microsoft.com/fwlink/?LinkId=761051')}`,
|
||||
`\t// ${localize('restart', 'Changing the value requires restarting VSCode.')}`,
|
||||
`\t"locale":"${language}"`,
|
||||
'}'
|
||||
].join('\n');
|
||||
|
||||
constructor(id: string, label: string,
|
||||
@IFileService private fileService: IFileService,
|
||||
@IWorkspaceContextService private contextService: IWorkspaceContextService,
|
||||
@IEnvironmentService private environmentService: IEnvironmentService,
|
||||
@IWorkbenchEditorService private editorService: IWorkbenchEditorService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
public run(event?: any): TPromise<IEditor> {
|
||||
const file = URI.file(join(this.environmentService.appSettingsHome, 'locale.json'));
|
||||
return this.fileService.resolveFile(file).then(null, (error) => {
|
||||
return this.fileService.createFile(file, ConfigureLocaleAction.DEFAULT_CONTENT);
|
||||
}).then((stat) => {
|
||||
if (!stat) {
|
||||
return undefined;
|
||||
}
|
||||
return this.editorService.openEditor({
|
||||
resource: stat.resource,
|
||||
options: {
|
||||
forceOpen: true
|
||||
}
|
||||
});
|
||||
}, (error) => {
|
||||
throw new Error(localize('fail.createSettings', "Unable to create '{0}' ({1}).", getPathLabel(file, this.contextService), error));
|
||||
});
|
||||
}
|
||||
}
|
|
@ -22,7 +22,7 @@ import 'vs/platform/actions/electron-browser/menusExtensionPoint';
|
|||
import 'vs/workbench/api/browser/viewsExtensionPoint';
|
||||
|
||||
// Localizations
|
||||
import 'vs/platform/localizations/common/localizations';
|
||||
import 'vs/workbench/parts/localizations/browser/localizations.contribution';
|
||||
|
||||
// Workbench
|
||||
import 'vs/workbench/browser/actions/toggleActivityBarVisibility';
|
||||
|
|
Loading…
Reference in a new issue