From d2c4286669a4237ef21dadc747c302d23cd60480 Mon Sep 17 00:00:00 2001 From: Sandeep Somavarapu Date: Mon, 23 Apr 2018 12:21:55 +0200 Subject: [PATCH] Ask user to install core language packe extension --- .../localizations/common/localizations.ts | 7 ++- .../localizations/common/localizationsIpc.ts | 8 +-- .../localizations/node/localizations.ts | 9 ++- .../localizations.contribution.ts | 56 ++++++++++++++++--- .../localizationsActions.ts | 0 src/vs/workbench/workbench.main.ts | 2 +- 6 files changed, 66 insertions(+), 16 deletions(-) rename src/vs/workbench/parts/localizations/{browser => electron-browser}/localizations.contribution.ts (74%) rename src/vs/workbench/parts/localizations/{browser => electron-browser}/localizationsActions.ts (100%) diff --git a/src/vs/platform/localizations/common/localizations.ts b/src/vs/platform/localizations/common/localizations.ts index 10ecbea2021..5f091c4f6f3 100644 --- a/src/vs/platform/localizations/common/localizations.ts +++ b/src/vs/platform/localizations/common/localizations.ts @@ -20,12 +20,17 @@ export interface ITranslation { path: string; } +export enum LanguageType { + Core = 1, + Contributed +} + export const ILocalizationsService = createDecorator('localizationsService'); export interface ILocalizationsService { _serviceBrand: any; readonly onDidLanguagesChange: Event; - getLanguageIds(): TPromise; + getLanguageIds(type?: LanguageType): TPromise; } export function isValidLocalization(localization: ILocalization): boolean { diff --git a/src/vs/platform/localizations/common/localizationsIpc.ts b/src/vs/platform/localizations/common/localizationsIpc.ts index ae5305352f7..51b6fb34147 100644 --- a/src/vs/platform/localizations/common/localizationsIpc.ts +++ b/src/vs/platform/localizations/common/localizationsIpc.ts @@ -8,7 +8,7 @@ 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'; +import { ILocalizationsService, LanguageType } from 'vs/platform/localizations/common/localizations'; export interface ILocalizationsChannel extends IChannel { call(command: 'event:onDidLanguagesChange'): TPromise; @@ -27,7 +27,7 @@ export class LocalizationsChannel implements ILocalizationsChannel { call(command: string, arg?: any): TPromise { switch (command) { case 'event:onDidLanguagesChange': return eventToCall(this.onDidLanguagesChange); - case 'getLanguageIds': return this.service.getLanguageIds(); + case 'getLanguageIds': return this.service.getLanguageIds(arg); } return undefined; } @@ -42,7 +42,7 @@ export class LocalizationsChannelClient implements ILocalizationsService { private _onDidLanguagesChange = eventFromCall(this.channel, 'event:onDidLanguagesChange'); get onDidLanguagesChange(): Event { return this._onDidLanguagesChange; } - getLanguageIds(): TPromise { - return this.channel.call('getLanguageIds'); + getLanguageIds(type?: LanguageType): TPromise { + return this.channel.call('getLanguageIds', type); } } \ No newline at end of file diff --git a/src/vs/platform/localizations/node/localizations.ts b/src/vs/platform/localizations/node/localizations.ts index 608533b89f9..0b9207c60fd 100644 --- a/src/vs/platform/localizations/node/localizations.ts +++ b/src/vs/platform/localizations/node/localizations.ts @@ -13,7 +13,7 @@ import { TPromise } from 'vs/base/common/winjs.base'; import { Limiter } from 'vs/base/common/async'; import { areSameExtensions, getGalleryExtensionIdFromLocal, getIdFromLocalExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { ILogService } from 'vs/platform/log/common/log'; -import { isValidLocalization, ILocalizationsService } from 'vs/platform/localizations/common/localizations'; +import { isValidLocalization, ILocalizationsService, LanguageType } 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'; @@ -55,10 +55,13 @@ export class LocalizationsService extends Disposable implements ILocalizationsSe this.extensionManagementService.getInstalled().then(installed => this.cache.update(installed)); } - getLanguageIds(): TPromise { + getLanguageIds(type: LanguageType): TPromise { + if (type === LanguageType.Core) { + return TPromise.as([...systemLanguages]); + } return this.cache.getLanguagePacks() .then(languagePacks => { - const languages = [...systemLanguages, ...Object.keys(languagePacks)]; + const languages = type === LanguageType.Contributed ? Object.keys(languagePacks) : [...systemLanguages, ...Object.keys(languagePacks)]; return TPromise.as(distinct(languages)); }); } diff --git a/src/vs/workbench/parts/localizations/browser/localizations.contribution.ts b/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.ts similarity index 74% rename from src/vs/workbench/parts/localizations/browser/localizations.contribution.ts rename to src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.ts index 1c89acd7c6f..a745f3b7200 100644 --- a/src/vs/workbench/parts/localizations/browser/localizations.contribution.ts +++ b/src/vs/workbench/parts/localizations/electron-browser/localizations.contribution.ts @@ -10,12 +10,12 @@ import { IJSONContributionRegistry, Extensions as JSONExtensions } from 'vs/plat 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 { ConfigureLocaleAction } from 'vs/workbench/parts/localizations/electron-browser/localizationsActions'; import { ExtensionsRegistry } from 'vs/workbench/services/extensions/common/extensionsRegistry'; -import { ILocalizationsService } from 'vs/platform/localizations/common/localizations'; +import { ILocalizationsService, LanguageType } from 'vs/platform/localizations/common/localizations'; import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle'; -import { language } from 'vs/base/common/platform'; -import { IExtensionManagementService, DidInstallExtensionEvent } from 'vs/platform/extensionManagement/common/extensionManagement'; +import * as platform from 'vs/base/common/platform'; +import { IExtensionManagementService, DidInstallExtensionEvent, LocalExtensionType, IExtensionGalleryService, IGalleryExtension } from 'vs/platform/extensionManagement/common/extensionManagement'; import { INotificationService } from 'vs/platform/notification/common/notification'; import Severity from 'vs/base/common/severity'; import { IJSONEditingService } from 'vs/workbench/services/configuration/common/jsonEditing'; @@ -24,6 +24,8 @@ import URI from 'vs/base/common/uri'; import { join } from 'vs/base/common/paths'; import { IWindowsService } from 'vs/platform/windows/common/windows'; import { IStorageService, } from 'vs/platform/storage/common/storage'; +import { TPromise } from 'vs/base/common/winjs.base'; +import product from 'vs/platform/node/product'; // Register action to configure locale and related settings const registry = Registry.as(Extensions.WorkbenchActions); @@ -37,10 +39,12 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo @IEnvironmentService private environmentService: IEnvironmentService, @IWindowsService private windowsService: IWindowsService, @IStorageService private storageService: IStorageService, - @IExtensionManagementService private extensionManagementService: IExtensionManagementService + @IExtensionManagementService private extensionManagementService: IExtensionManagementService, + @IExtensionGalleryService private galleryService: IExtensionGalleryService, ) { super(); this.updateLocaleDefintionSchema(); + this.checkAndInstall(); this._register(this.localizationService.onDidLanguagesChange(() => this.updateLocaleDefintionSchema())); this._register(this.extensionManagementService.onDidInstallExtension(e => this.onDidInstallExtension(e))); } @@ -63,7 +67,7 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo const donotAskUpdateKey = 'langugage.update.donotask'; if (!this.storageService.getBoolean(donotAskUpdateKey) && e.local && e.local.manifest.contributes && e.local.manifest.contributes.localizations && e.local.manifest.contributes.localizations.length) { const locale = e.local.manifest.contributes.localizations[0].languageId; - if (language !== locale) { + if (platform.language !== locale) { this.notificationService.prompt( Severity.Info, localize('updateLocale', "Would you like to change VS Code's UI language to {0} and restart?", e.local.manifest.contributes.localizations[0].languageName || e.local.manifest.contributes.localizations[0].languageId), @@ -86,6 +90,44 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo } } } + + private checkAndInstall(): void { + const language = platform.language; + if (language !== 'en' && language !== 'en_us') { + this.isLanguageInstalled(language) + .then(installed => { + if (!installed) { + this.getLanguagePackExtension(language) + .then(extension => { + if (extension) { + this.notificationService.prompt(Severity.Warning, localize('install language pack', "Please install '{0}' extension to continue to show VS Code's UI in '{1}' language. In the future, VS Code will only support language packs from the Marketplace.", extension.displayName || extension.displayName, language), + [ + { label: localize('install', "Install"), run: () => this.extensionManagementService.installFromGallery(extension) }, + { label: localize('more information', "More Information..."), run: () => window.open('https://go.microsoft.com/fwlink/?linkid=830387') } + ]); + } + }); + } + }); + } + } + + private getLanguagePackExtension(language: string): TPromise { + return this.localizationService.getLanguageIds(LanguageType.Core) + .then(coreLanguages => { + const extensionId = coreLanguages.some(c => c.toLowerCase() === language) ? product.quality !== 'insider' ? `MS-CEINTL.vscode-insiders-language-pack-${language}` : `MS-CEINTL.vscode-language-pack-${language}` : null; + if (extensionId) { + return this.galleryService.query({ names: [extensionId], pageSize: 1 }) + .then(result => result.total === 1 ? result.firstPage[0] : null); + } + return null; + }); + } + + private isLanguageInstalled(language: string): TPromise { + return this.extensionManagementService.getInstalled(LocalExtensionType.User) + .then(installed => installed.some(i => i.manifest && i.manifest.contributes && i.manifest.contributes.localizations && i.manifest.contributes.localizations.length && i.manifest.contributes.localizations.some(l => l.languageId.toLowerCase() === language))); + } } function registerLocaleDefinitionSchema(languages: string[]): void { @@ -111,7 +153,7 @@ function registerLocaleDefinitionSchema(languages: string[]): void { }); } -registerLocaleDefinitionSchema([language]); +registerLocaleDefinitionSchema([platform.language]); const workbenchRegistry = Registry.as(WorkbenchExtensions.Workbench); workbenchRegistry.registerWorkbenchContribution(LocalizationWorkbenchContribution, LifecyclePhase.Eventually); diff --git a/src/vs/workbench/parts/localizations/browser/localizationsActions.ts b/src/vs/workbench/parts/localizations/electron-browser/localizationsActions.ts similarity index 100% rename from src/vs/workbench/parts/localizations/browser/localizationsActions.ts rename to src/vs/workbench/parts/localizations/electron-browser/localizationsActions.ts diff --git a/src/vs/workbench/workbench.main.ts b/src/vs/workbench/workbench.main.ts index f9cf799d7fe..e5cbc7ad2bf 100644 --- a/src/vs/workbench/workbench.main.ts +++ b/src/vs/workbench/workbench.main.ts @@ -23,7 +23,7 @@ import 'vs/workbench/api/browser/viewsContainersExtensionPoint'; import 'vs/workbench/api/browser/viewsExtensionPoint'; // Localizations -import 'vs/workbench/parts/localizations/browser/localizations.contribution'; +import 'vs/workbench/parts/localizations/electron-browser/localizations.contribution'; // Workbench import 'vs/workbench/browser/actions/toggleActivityBarVisibility'; -- GitLab