diff --git a/src/vs/workbench/services/extensionManagement/browser/builtinExtensionsScannerService.ts b/src/vs/workbench/services/extensionManagement/browser/builtinExtensionsScannerService.ts index 089434c2a84..f1ad01f892b 100644 --- a/src/vs/workbench/services/extensionManagement/browser/builtinExtensionsScannerService.ts +++ b/src/vs/workbench/services/extensionManagement/browser/builtinExtensionsScannerService.ts @@ -3,14 +3,17 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { IBuiltinExtensionsScannerService, ExtensionType, IExtensionManifest, IExtension, TargetPlatform } from 'vs/platform/extensions/common/extensions'; -import { isWeb } from 'vs/base/common/platform'; +import { IBuiltinExtensionsScannerService, ExtensionType, IExtensionManifest, TargetPlatform, IExtension } from 'vs/platform/extensions/common/extensions'; +import { isWeb, Language } from 'vs/base/common/platform'; import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService'; import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity'; import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil'; import { FileAccess } from 'vs/base/common/network'; -import { localizeManifest } from 'vs/platform/extensionManagement/common/extensionNls'; +import { URI } from 'vs/base/common/uri'; +import { IExtensionResourceLoaderService } from 'vs/workbench/services/extensionResourceLoader/common/extensionResourceLoader'; +import { IProductService } from 'vs/platform/product/common/productService'; +import { ITranslations, localizeManifest } from 'vs/platform/extensionManagement/common/extensionNls'; interface IBundledExtension { extensionPath: string; @@ -24,13 +27,22 @@ export class BuiltinExtensionsScannerService implements IBuiltinExtensionsScanne declare readonly _serviceBrand: undefined; - private readonly builtinExtensions: IExtension[] = []; + private readonly builtinExtensionsPromises: Promise[] = []; + + private nlsUrl: URI | undefined; constructor( @IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService, @IUriIdentityService uriIdentityService: IUriIdentityService, + @IExtensionResourceLoaderService private readonly extensionResourceLoaderService: IExtensionResourceLoaderService, + @IProductService productService: IProductService ) { if (isWeb) { + const nlsBaseUrl = productService.extensionsGallery?.nlsBaseUrl; + if (nlsBaseUrl && productService.commit) { + this.nlsUrl = URI.joinPath(URI.parse(nlsBaseUrl), productService.commit, productService.version, Language.value()); + } + const builtinExtensionsServiceUrl = FileAccess.asBrowserUri('../../../../../../extensions', require); if (builtinExtensionsServiceUrl) { let bundledExtensions: IBundledExtension[] = []; @@ -49,24 +61,42 @@ export class BuiltinExtensionsScannerService implements IBuiltinExtensionsScanne } } - this.builtinExtensions = bundledExtensions.map(e => ({ - identifier: { id: getGalleryExtensionId(e.packageJSON.publisher, e.packageJSON.name) }, - location: uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.extensionPath), - type: ExtensionType.System, - isBuiltin: true, - manifest: e.packageNLS ? localizeManifest(e.packageJSON, e.packageNLS) : e.packageJSON, - readmeUrl: e.readmePath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.readmePath) : undefined, - changelogUrl: e.changelogPath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.changelogPath) : undefined, - targetPlatform: TargetPlatform.WEB, - validations: [], - isValid: true - })); + this.builtinExtensionsPromises = bundledExtensions.map(async e => { + const id = getGalleryExtensionId(e.packageJSON.publisher, e.packageJSON.name); + return { + identifier: { id }, + location: uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.extensionPath), + type: ExtensionType.System, + isBuiltin: true, + manifest: e.packageNLS ? await this.localizeManifest(id, e.packageJSON, e.packageNLS) : e.packageJSON, + readmeUrl: e.readmePath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.readmePath) : undefined, + changelogUrl: e.changelogPath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.changelogPath) : undefined, + targetPlatform: TargetPlatform.WEB, + validations: [], + isValid: true + }; + }); } } } async scanBuiltinExtensions(): Promise { - return [...this.builtinExtensions]; + return [...await Promise.all(this.builtinExtensionsPromises)]; + } + + private async localizeManifest(extensionId: string, manifest: IExtensionManifest, translations: ITranslations): Promise { + if (!this.nlsUrl) { + return localizeManifest(manifest, translations); + } + // the `package` endpoint returns the translations in a key-value format similar to the package.nls.json file. + const uri = URI.joinPath(this.nlsUrl, extensionId, 'package'); + try { + const res = await this.extensionResourceLoaderService.readExtensionResource(uri); + const json = JSON.parse(res.toString()); + return localizeManifest(manifest, json); + } catch (e) { + return localizeManifest(manifest, translations); + } } }