Path: blob/main/src/vs/platform/extensionManagement/common/extensionNls.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 { isObject, isString } from '../../../base/common/types.js';6import { ILocalizedString } from '../../action/common/action.js';7import { IExtensionManifest } from '../../extensions/common/extensions.js';8import { localize } from '../../../nls.js';9import { ILogger } from '../../log/common/log.js';1011export interface ITranslations {12[key: string]: string | { message: string; comment: string[] } | undefined;13}1415export function localizeManifest(logger: ILogger, extensionManifest: IExtensionManifest, translations: ITranslations, fallbackTranslations?: ITranslations): IExtensionManifest {16try {17replaceNLStrings(logger, extensionManifest, translations, fallbackTranslations);18} catch (error) {19logger.error(error?.message ?? error);20/*Ignore Error*/21}22return extensionManifest;23}2425/**26* This routine makes the following assumptions:27* The root element is an object literal28*/29function replaceNLStrings(logger: ILogger, extensionManifest: IExtensionManifest, messages: ITranslations, originalMessages?: ITranslations): void {30const processEntry = (obj: any, key: string | number, command?: boolean) => {31const value = obj[key];32if (isString(value)) {33const str = <string>value;34const length = str.length;35if (length > 1 && str[0] === '%' && str[length - 1] === '%') {36const messageKey = str.substr(1, length - 2);37let translated = messages[messageKey];38// If the messages come from a language pack they might miss some keys39// Fill them from the original messages.40if (translated === undefined && originalMessages) {41translated = originalMessages[messageKey];42}43const message: string | undefined = typeof translated === 'string' ? translated : translated?.message;4445// This branch returns ILocalizedString's instead of Strings so that the Command Palette can contain both the localized and the original value.46const original = originalMessages?.[messageKey];47const originalMessage: string | undefined = typeof original === 'string' ? original : original?.message;4849if (!message) {50if (!originalMessage) {51logger.warn(`[${extensionManifest.name}]: ${localize('missingNLSKey', "Couldn't find message for key {0}.", messageKey)}`);52}53return;54}5556if (57// if we are translating the title or category of a command58command && (key === 'title' || key === 'category') &&59// and the original value is not the same as the translated value60originalMessage && originalMessage !== message61) {62const localizedString: ILocalizedString = {63value: message,64original: originalMessage65};66obj[key] = localizedString;67} else {68obj[key] = message;69}70}71} else if (isObject(value)) {72for (const k in value) {73if (value.hasOwnProperty(k)) {74k === 'commands' ? processEntry(value, k, true) : processEntry(value, k, command);75}76}77} else if (Array.isArray(value)) {78for (let i = 0; i < value.length; i++) {79processEntry(value, i, command);80}81}82};8384for (const key in extensionManifest) {85if (extensionManifest.hasOwnProperty(key)) {86processEntry(extensionManifest, key);87}88}89}909192