Path: blob/main/src/vs/platform/languagePacks/common/languagePacks.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { CancellationTokenSource } from '../../../base/common/cancellation.js';6import { Disposable } from '../../../base/common/lifecycle.js';7import { language } from '../../../base/common/platform.js';8import { URI } from '../../../base/common/uri.js';9import { IQuickPickItem } from '../../quickinput/common/quickInput.js';10import { localize } from '../../../nls.js';11import { IExtensionGalleryService, IGalleryExtension } from '../../extensionManagement/common/extensionManagement.js';12import { createDecorator } from '../../instantiation/common/instantiation.js';1314export function getLocale(extension: IGalleryExtension): string | undefined {15return extension.tags.find(t => t.startsWith('lp-'))?.split('lp-')[1];16}1718export const ILanguagePackService = createDecorator<ILanguagePackService>('languagePackService');1920export interface ILanguagePackItem extends IQuickPickItem {21readonly extensionId?: string;22readonly galleryExtension?: IGalleryExtension;23}2425export interface ILanguagePackService {26readonly _serviceBrand: undefined;27getAvailableLanguages(): Promise<Array<ILanguagePackItem>>;28getInstalledLanguages(): Promise<Array<ILanguagePackItem>>;29getBuiltInExtensionTranslationsUri(id: string, language: string): Promise<URI | undefined>;30}3132export abstract class LanguagePackBaseService extends Disposable implements ILanguagePackService {33declare readonly _serviceBrand: undefined;3435constructor(@IExtensionGalleryService protected readonly extensionGalleryService: IExtensionGalleryService) {36super();37}3839abstract getBuiltInExtensionTranslationsUri(id: string, language: string): Promise<URI | undefined>;4041abstract getInstalledLanguages(): Promise<Array<ILanguagePackItem>>;4243async getAvailableLanguages(): Promise<ILanguagePackItem[]> {44const timeout = new CancellationTokenSource();45setTimeout(() => timeout.cancel(), 1000);4647let result;48try {49result = await this.extensionGalleryService.query({50text: 'category:"language packs"',51pageSize: 2052}, timeout.token);53} catch (_) {54// This method is best effort. So, we ignore any errors.55return [];56}5758const languagePackExtensions = result.firstPage.filter(e => e.properties.localizedLanguages?.length && e.tags.some(t => t.startsWith('lp-')));59const allFromMarketplace: ILanguagePackItem[] = languagePackExtensions.map(lp => {60const languageName = lp.properties.localizedLanguages?.[0];61const locale = getLocale(lp)!;62const baseQuickPick = this.createQuickPickItem(locale, languageName, lp);63return {64...baseQuickPick,65extensionId: lp.identifier.id,66galleryExtension: lp67};68});6970allFromMarketplace.push(this.createQuickPickItem('en', 'English'));7172return allFromMarketplace;73}7475protected createQuickPickItem(locale: string, languageName?: string, languagePack?: IGalleryExtension): IQuickPickItem {76const label = languageName ?? locale;77let description: string | undefined;78if (label !== locale) {79description = `(${locale})`;80}8182if (locale.toLowerCase() === language.toLowerCase()) {83description ??= '';84description += localize('currentDisplayLanguage', " (Current)");85}8687if (languagePack?.installCount) {88description ??= '';8990const count = languagePack.installCount;91let countLabel: string;92if (count > 1000000) {93countLabel = `${Math.floor(count / 100000) / 10}M`;94} else if (count > 1000) {95countLabel = `${Math.floor(count / 1000)}K`;96} else {97countLabel = String(count);98}99description += ` $(cloud-download) ${countLabel}`;100}101102return {103id: locale,104label,105description106};107}108}109110111