Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/api/common/extHostLocalizationService.ts
3296 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { LANGUAGE_DEFAULT } from '../../../base/common/platform.js';
7
import { format2 } from '../../../base/common/strings.js';
8
import { URI } from '../../../base/common/uri.js';
9
import { IExtensionDescription } from '../../../platform/extensions/common/extensions.js';
10
import { createDecorator } from '../../../platform/instantiation/common/instantiation.js';
11
import { ILogService } from '../../../platform/log/common/log.js';
12
import { ExtHostLocalizationShape, IStringDetails, MainContext, MainThreadLocalizationShape } from './extHost.protocol.js';
13
import { IExtHostInitDataService } from './extHostInitDataService.js';
14
import { IExtHostRpcService } from './extHostRpcService.js';
15
16
export class ExtHostLocalizationService implements ExtHostLocalizationShape {
17
readonly _serviceBrand: undefined;
18
19
private readonly _proxy: MainThreadLocalizationShape;
20
private readonly currentLanguage: string;
21
private readonly isDefaultLanguage: boolean;
22
23
private readonly bundleCache: Map<string, { contents: { [key: string]: string }; uri: URI }> = new Map();
24
25
constructor(
26
@IExtHostInitDataService initData: IExtHostInitDataService,
27
@IExtHostRpcService rpc: IExtHostRpcService,
28
@ILogService private readonly logService: ILogService
29
) {
30
this._proxy = rpc.getProxy(MainContext.MainThreadLocalization);
31
this.currentLanguage = initData.environment.appLanguage;
32
this.isDefaultLanguage = this.currentLanguage === LANGUAGE_DEFAULT;
33
}
34
35
getMessage(extensionId: string, details: IStringDetails): string {
36
const { message, args, comment } = details;
37
if (this.isDefaultLanguage) {
38
return format2(message, (args ?? {}));
39
}
40
41
let key = message;
42
if (comment && comment.length > 0) {
43
key += `/${Array.isArray(comment) ? comment.join('') : comment}`;
44
}
45
const str = this.bundleCache.get(extensionId)?.contents[key];
46
if (!str) {
47
this.logService.warn(`Using default string since no string found in i18n bundle that has the key: ${key}`);
48
}
49
return format2(str ?? message, (args ?? {}));
50
}
51
52
getBundle(extensionId: string): { [key: string]: string } | undefined {
53
return this.bundleCache.get(extensionId)?.contents;
54
}
55
56
getBundleUri(extensionId: string): URI | undefined {
57
return this.bundleCache.get(extensionId)?.uri;
58
}
59
60
async initializeLocalizedMessages(extension: IExtensionDescription): Promise<void> {
61
if (this.isDefaultLanguage
62
|| (!extension.l10n && !extension.isBuiltin)
63
) {
64
return;
65
}
66
67
if (this.bundleCache.has(extension.identifier.value)) {
68
return;
69
}
70
71
let contents: { [key: string]: string } | undefined;
72
const bundleUri = await this.getBundleLocation(extension);
73
if (!bundleUri) {
74
this.logService.error(`No bundle location found for extension ${extension.identifier.value}`);
75
return;
76
}
77
78
try {
79
const response = await this._proxy.$fetchBundleContents(bundleUri);
80
const result = JSON.parse(response);
81
// 'contents.bundle' is a well-known key in the language pack json file that contains the _code_ translations for the extension
82
contents = extension.isBuiltin ? result.contents?.bundle : result;
83
} catch (e) {
84
this.logService.error(`Failed to load translations for ${extension.identifier.value} from ${bundleUri}: ${e.message}`);
85
return;
86
}
87
88
if (contents) {
89
this.bundleCache.set(extension.identifier.value, {
90
contents,
91
uri: bundleUri
92
});
93
}
94
}
95
96
private async getBundleLocation(extension: IExtensionDescription): Promise<URI | undefined> {
97
if (extension.isBuiltin) {
98
const uri = await this._proxy.$fetchBuiltInBundleUri(extension.identifier.value, this.currentLanguage);
99
return URI.revive(uri);
100
}
101
102
return extension.l10n
103
? URI.joinPath(extension.extensionLocation, extension.l10n, `bundle.l10n.${this.currentLanguage}.json`)
104
: undefined;
105
}
106
}
107
108
export const IExtHostLocalizationService = createDecorator<IExtHostLocalizationService>('IExtHostLocalizationService');
109
export interface IExtHostLocalizationService extends ExtHostLocalizationService { }
110
111