Skip to content

show set display language action for lang pack extensions #154925

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion src/vs/platform/languagePacks/common/languagePacks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export interface ILanguagePackService {
readonly _serviceBrand: undefined;
getAvailableLanguages(): Promise<Array<ILanguagePackItem>>;
getInstalledLanguages(): Promise<Array<ILanguagePackItem>>;
getLocale(extension: IGalleryExtension): string | undefined;
}

export abstract class LanguagePackBaseService extends Disposable implements ILanguagePackService {
Expand Down Expand Up @@ -51,7 +52,7 @@ export abstract class LanguagePackBaseService extends Disposable implements ILan
const languagePackExtensions = result.firstPage.filter(e => e.properties.localizedLanguages?.length && e.tags.some(t => t.startsWith('lp-')));
const allFromMarketplace: ILanguagePackItem[] = languagePackExtensions.map(lp => {
const languageName = lp.properties.localizedLanguages?.[0];
const locale = lp.tags.find(t => t.startsWith('lp-'))!.split('lp-')[1];
const locale = this.getLocale(lp)!;
const baseQuickPick = this.createQuickPickItem({ locale, label: languageName });
return {
...baseQuickPick,
Expand All @@ -68,6 +69,10 @@ export abstract class LanguagePackBaseService extends Disposable implements ILan
return allFromMarketplace;
}

getLocale(extension: IGalleryExtension): string | undefined {
return extension.tags.find(t => t.startsWith('lp-'))?.split('lp-')[1];
}

protected createQuickPickItem(languageItem: { locale: string; label?: string | undefined }): IQuickPickItem {
const label = languageItem.label ?? languageItem.locale;
let description: string | undefined = languageItem.locale !== languageItem.label ? languageItem.locale : undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
UpdateAction, ReloadAction, EnableDropDownAction, DisableDropDownAction, ExtensionStatusLabelAction, SetFileIconThemeAction, SetColorThemeAction,
RemoteInstallAction, ExtensionStatusAction, LocalInstallAction, ToggleSyncExtensionAction, SetProductIconThemeAction,
ActionWithDropDownAction, InstallDropdownAction, InstallingLabelAction, UninstallAction, ExtensionActionWithDropdownActionViewItem, ExtensionDropDownAction,
InstallAnotherVersionAction, ExtensionEditorManageExtensionAction, WebInstallAction, SwitchToPreReleaseVersionAction, SwitchToReleasedVersionAction, MigrateDeprecatedExtensionAction
InstallAnotherVersionAction, ExtensionEditorManageExtensionAction, WebInstallAction, SwitchToPreReleaseVersionAction, SwitchToReleasedVersionAction, MigrateDeprecatedExtensionAction, SetLanguageAction
} from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
Expand Down Expand Up @@ -329,6 +329,7 @@ export class ExtensionEditor extends EditorPane {

this.instantiationService.createInstance(EnableDropDownAction),
this.instantiationService.createInstance(DisableDropDownAction),
this.instantiationService.createInstance(SetLanguageAction),
this.instantiationService.createInstance(RemoteInstallAction, false),
this.instantiationService.createInstance(LocalInstallAction),
this.instantiationService.createInstance(WebInstallAction),
Expand Down
61 changes: 55 additions & 6 deletions src/vs/workbench/contrib/extensions/browser/extensionsActions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ import { IContextMenuProvider } from 'vs/base/browser/contextmenu';
import { ILogService } from 'vs/platform/log/common/log';
import * as Constants from 'vs/workbench/contrib/logs/common/logConstants';
import { errorIcon, infoIcon, manageExtensionIcon, preReleaseIcon, syncEnabledIcon, syncIgnoredIcon, trustIcon, warningIcon } from 'vs/workbench/contrib/extensions/browser/extensionsIcons';
import { isIOS, isWeb } from 'vs/base/common/platform';
import { isIOS, isWeb, language } from 'vs/base/common/platform';
import { IExtensionManifestPropertiesService } from 'vs/workbench/services/extensions/common/extensionManifestPropertiesService';
import { IWorkspaceTrustEnablementService, IWorkspaceTrustManagementService } from 'vs/platform/workspace/common/workspaceTrust';
import { isVirtualWorkspace } from 'vs/platform/workspace/common/virtualWorkspace';
Expand All @@ -66,6 +66,7 @@ import { ViewContainerLocation } from 'vs/workbench/common/views';
import { flatten } from 'vs/base/common/arrays';
import { fromNow } from 'vs/base/common/date';
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
import { ILanguagePackService } from 'vs/platform/languagePacks/common/languagePacks';

export class PromptExtensionInstallFailureAction extends Action {

Expand Down Expand Up @@ -264,11 +265,18 @@ export abstract class AbstractInstallAction extends ExtensionAction {

protected async computeAndUpdateEnablement(): Promise<void> {
this.enabled = false;
if (this.extension && !this.extension.isBuiltin) {
if (this.extension.state === ExtensionState.Uninstalled && await this.extensionsWorkbenchService.canInstall(this.extension)) {
this.enabled = this.installPreReleaseVersion ? this.extension.hasPreReleaseVersion : this.extension.hasReleaseVersion;
this.updateLabel();
}
if (!this.extension) {
return;
}
if (this.extension.isBuiltin) {
return;
}
if (this.extensionsWorkbenchService.canSetLanguage(this.extension)) {
return;
}
Comment on lines +268 to +276
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: maybe combine these if's?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to have separate checks for each condition for readability (I think its personal :) )

if (this.extension.state === ExtensionState.Uninstalled && await this.extensionsWorkbenchService.canInstall(this.extension)) {
this.enabled = this.installPreReleaseVersion ? this.extension.hasPreReleaseVersion : this.extension.hasReleaseVersion;
this.updateLabel();
}
}

Expand Down Expand Up @@ -1767,6 +1775,43 @@ export class SetProductIconThemeAction extends ExtensionAction {
}
}

export class SetLanguageAction extends ExtensionAction {

static readonly ID = 'workbench.extensions.action.setLanguageTheme';
static readonly TITLE = { value: localize('workbench.extensions.action.setLanguageTheme', "Set Display Language"), original: 'Set Display Language' };

private static readonly EnabledClass = `${ExtensionAction.LABEL_ACTION_CLASS} theme`;
private static readonly DisabledClass = `${SetLanguageAction.EnabledClass} disabled`;

constructor(
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
@ILanguagePackService private readonly languagePackService: ILanguagePackService,
) {
super(SetLanguageAction.ID, SetLanguageAction.TITLE.value, SetLanguageAction.DisabledClass, false);
this.update();
}

update(): void {
this.enabled = false;
this.class = SetLanguageAction.DisabledClass;
if (!this.extension) {
return;
}
if (!this.extensionsWorkbenchService.canSetLanguage(this.extension)) {
return;
}
if (this.extension.gallery && language === this.languagePackService.getLocale(this.extension.gallery)) {
return;
}
this.enabled = true;
this.class = SetLanguageAction.EnabledClass;
}

override async run(): Promise<any> {
return this.extension && this.extensionsWorkbenchService.setLanguage(this.extension);
}
}

export class ShowRecommendedExtensionAction extends Action {

static readonly ID = 'workbench.extensions.action.showRecommendedExtension';
Expand Down Expand Up @@ -2259,6 +2304,10 @@ export class ExtensionStatusAction extends ExtensionAction {
return;
}

if (this.extensionsWorkbenchService.canSetLanguage(this.extension)) {
return;
}

if (this.extension.gallery && this.extension.state === ExtensionState.Uninstalled && !await this.extensionsWorkbenchService.canInstall(this.extension)) {
if (this.extensionManagementServerService.localExtensionManagementServer || this.extensionManagementServerService.remoteExtensionManagementServer) {
const targetPlatform = await (this.extensionManagementServerService.localExtensionManagementServer ? this.extensionManagementServerService.localExtensionManagementServer!.extensionManagementService.getTargetPlatform() : this.extensionManagementServerService.remoteExtensionManagementServer!.extensionManagementService.getTargetPlatform());
Expand Down
22 changes: 16 additions & 6 deletions src/vs/workbench/contrib/extensions/browser/extensionsList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
import { IPagedRenderer } from 'vs/base/browser/ui/list/listPaging';
import { Event } from 'vs/base/common/event';
import { IExtension, ExtensionContainers, ExtensionState, IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions';
import { UpdateAction, ManageExtensionAction, ReloadAction, ExtensionStatusLabelAction, RemoteInstallAction, ExtensionStatusAction, LocalInstallAction, ActionWithDropDownAction, InstallDropdownAction, InstallingLabelAction, ExtensionActionWithDropdownActionViewItem, ExtensionDropDownAction, WebInstallAction, SwitchToPreReleaseVersionAction, SwitchToReleasedVersionAction, MigrateDeprecatedExtensionAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { UpdateAction, ManageExtensionAction, ReloadAction, ExtensionStatusLabelAction, RemoteInstallAction, ExtensionStatusAction, LocalInstallAction, ActionWithDropDownAction, InstallDropdownAction, InstallingLabelAction, ExtensionActionWithDropdownActionViewItem, ExtensionDropDownAction, WebInstallAction, SwitchToPreReleaseVersionAction, SwitchToReleasedVersionAction, MigrateDeprecatedExtensionAction, SetLanguageAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { RatingsWidget, InstallCountWidget, RecommendationWidget, RemoteBadgeWidget, ExtensionPackCountWidget as ExtensionPackBadgeWidget, SyncIgnoredWidget, ExtensionHoverWidget, ExtensionActivationStatusWidget, PreReleaseBookmarkWidget, extensionVerifiedPublisherIconColor } from 'vs/workbench/contrib/extensions/browser/extensionsWidgets';
import { IExtensionService, toExtension } from 'vs/workbench/services/extensions/common/extensions';
Expand Down Expand Up @@ -123,6 +123,7 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
reloadAction,
this.instantiationService.createInstance(InstallDropdownAction),
this.instantiationService.createInstance(InstallingLabelAction),
this.instantiationService.createInstance(SetLanguageAction),
this.instantiationService.createInstance(RemoteInstallAction, false),
this.instantiationService.createInstance(LocalInstallAction),
this.instantiationService.createInstance(WebInstallAction),
Expand Down Expand Up @@ -186,16 +187,25 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {

data.extensionDisposables = dispose(data.extensionDisposables);

const updateEnablement = async () => {
let disabled = false;
const deprecated = !!extension.deprecationInfo;
const computeEnablement = async () => {
if (extension.state === ExtensionState.Uninstalled) {
disabled = deprecated || !(await this.extensionsWorkbenchService.canInstall(extension));
if (!!extension.deprecationInfo) {
return true;
}
if (this.extensionsWorkbenchService.canSetLanguage(extension)) {
return false;
}
return !(await this.extensionsWorkbenchService.canInstall(extension));
} else if (extension.local && !isLanguagePackExtension(extension.local.manifest)) {
const runningExtensions = await this.extensionService.getExtensions();
const runningExtension = runningExtensions.filter(e => areSameExtensions({ id: e.identifier.value, uuid: e.uuid }, extension.identifier))[0];
disabled = !(runningExtension && extension.server === this.extensionManagementServerService.getExtensionManagementServer(toExtension(runningExtension)));
return !(runningExtension && extension.server === this.extensionManagementServerService.getExtensionManagementServer(toExtension(runningExtension)));
}
return false;
};
const updateEnablement = async () => {
const disabled = await computeEnablement();
const deprecated = !!extension.deprecationInfo;
data.element.classList.toggle('deprecated', deprecated);
data.root.classList.toggle('disabled', disabled);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,10 @@ import { isBoolean, isUndefined } from 'vs/base/common/types';
import { IExtensionManifestPropertiesService } from 'vs/workbench/services/extensions/common/extensionManifestPropertiesService';
import { IExtensionService, IExtensionsStatus } from 'vs/workbench/services/extensions/common/extensions';
import { ExtensionEditor } from 'vs/workbench/contrib/extensions/browser/extensionEditor';
import { isWeb } from 'vs/base/common/platform';
import { isWeb, language } from 'vs/base/common/platform';
import { GDPRClassification } from 'vs/platform/telemetry/common/gdprTypings';
import { ILanguagePackService } from 'vs/platform/languagePacks/common/languagePacks';
import { ILocaleService } from 'vs/workbench/contrib/localization/common/locale';

interface IExtensionStateProvider<T> {
(extension: Extension): T;
Expand Down Expand Up @@ -710,6 +712,8 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
@IExtensionManifestPropertiesService private readonly extensionManifestPropertiesService: IExtensionManifestPropertiesService,
@ILogService private readonly logService: ILogService,
@IExtensionService private readonly extensionService: IExtensionService,
@ILanguagePackService private readonly languagePackService: ILanguagePackService,
@ILocaleService private readonly localeService: ILocaleService,
) {
super();
const preferPreReleasesValue = configurationService.getValue('_extensions.preferPreReleases');
Expand Down Expand Up @@ -1248,6 +1252,34 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
return this.installWithProgress(() => this.installFromGallery(extension, gallery, installOptions), gallery.displayName, progressLocation);
}

canSetLanguage(extension: IExtension): boolean {
if (!isWeb) {
return false;
}

if (!extension.gallery) {
return false;
}
Comment on lines +1256 to +1262
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: is 2 ifs really more readable than 1?


const locale = this.languagePackService.getLocale(extension.gallery);
if (!locale) {
return false;
}

return true;
}

async setLanguage(extension: IExtension): Promise<void> {
if (!this.canSetLanguage(extension)) {
throw new Error('Can not set language');
}
const locale = this.languagePackService.getLocale(extension.gallery!);
if (locale === language) {
return;
}
return this.localeService.setLocale({ id: locale, galleryExtension: extension.gallery, extensionId: extension.identifier.id, label: extension.displayName });
}

setEnablement(extensions: IExtension | IExtension[], enablementState: EnablementState): Promise<void> {
extensions = Array.isArray(extensions) ? extensions : [extensions];
return this.promptAndSetEnablement(extensions, enablementState);
Expand Down
2 changes: 2 additions & 0 deletions src/vs/workbench/contrib/extensions/common/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ export interface IExtensionsWorkbenchService {
uninstall(extension: IExtension): Promise<void>;
installVersion(extension: IExtension, version: string, installOptions?: InstallOptions): Promise<IExtension>;
reinstall(extension: IExtension): Promise<IExtension>;
canSetLanguage(extension: IExtension): boolean;
setLanguage(extension: IExtension): Promise<void>;
setEnablement(extensions: IExtension | IExtension[], enablementState: EnablementState): Promise<void>;
open(extension: IExtension, options?: IExtensionEditorOptions): Promise<void>;
checkForUpdates(): Promise<void>;
Expand Down