blob: 818d6ff37b81daf2335254c66e1d5b54e3489b13 [file] [log] [blame]
vidorteg1fd76f82020-08-26 18:09:201// Copyright 2020 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4import * as Platform from '../platform/platform.js';
5
6// eslint-disable-next-line
vidorteg3e2942e2020-09-17 04:16:567import i18nBundle from '../third_party/i18n/i18n.js';
vidorteg1fd76f82020-08-26 18:09:208
9/**
10 * The locale that DevTools displays
11 * @param {string} locale
12 * @param {*} lhlMessages
13 */
14export const registerLocaleData = i18nBundle.registerLocaleData;
15
16/**
17 * The locale that DevTools displays
Kalon Hinds3cb4a092020-11-24 22:55:3118 * @type {string|undefined}
vidorteg1fd76f82020-08-26 18:09:2019 */
20export let registeredLocale;
21
22/**
vidorteg8bce4b02020-10-09 01:16:2123 * The strings from the module.json file
Kalon Hinds3cb4a092020-11-24 22:55:3124 * @type {!Object|undefined}
vidorteg8bce4b02020-10-09 01:16:2125 */
26let moduleJSONStrings;
27
28/**
Kalon Hinds3cb4a092020-11-24 22:55:3129 * Returns an instance of an object of formatted strings based on locale. If the instance is not
30 * set at the time of calling, it is created.
31 * @return {!Object}
Kalon Hinds3cb4a092020-11-24 22:55:3132 */
33function getOrSetModuleJSONStrings() {
34 if (!registeredLocale) {
35 throw new Error(`Unsupported locale '${registeredLocale}'`);
36 }
37
38 moduleJSONStrings = moduleJSONStrings || i18nBundle.getRendererFormattedStrings(registeredLocale);
39 return moduleJSONStrings;
40}
41
42/**
vidorteg1fd76f82020-08-26 18:09:2043 * Take the locale passed in from the browser(host), run through the fallback logic (example: es-419 -> es)
44 * to find the DevTools supported locale and register it.
45 * @param {string} locale
46 */
47export function registerLocale(locale) {
48 registeredLocale = i18nBundle.lookupLocale(locale);
49}
50
51/**
52 * Retrieve the localized string.
53 * @param {function(string, ?Object):string} str_
54 * @param {string} id
55 * @param {!Object} values
Tim van der Lippe3b1f7452021-01-08 11:25:1356 * @return {!Platform.UIString.LocalizedString} the localized version of the
vidorteg1fd76f82020-08-26 18:09:2057 */
58export function getLocalizedString(str_, id, values = {}) {
Kalon Hinds3cb4a092020-11-24 22:55:3159 if (!registeredLocale) {
60 throw new Error(`Unsupported locale '${registeredLocale}'`);
61 }
62
vidorteg1fd76f82020-08-26 18:09:2063 const icuMessage = str_(id, values);
Tim van der Lippe3b1f7452021-01-08 11:25:1364 return /** @type {!Platform.UIString.LocalizedString} */ (i18nBundle.getFormatted(icuMessage, registeredLocale));
vidorteg1fd76f82020-08-26 18:09:2065}
66
67/**
68 * Register a file's UIStrings with i18n, return function to generate the string ids.
69 * @param {string} path
vidorteg8bce4b02020-10-09 01:16:2170 * @param {!Object} stringStructure
vidorteg1fd76f82020-08-26 18:09:2071 * @return {function(string, ?Object):string} return function to generate the string ids.
72 */
vidorteg8bce4b02020-10-09 01:16:2173export function registerUIStrings(path, stringStructure) {
vidorteg1fd76f82020-08-26 18:09:2074 /**
75 * Convert a message string & replacement values into an
76 * indexed id value in the form '{messageid} | # {index}'.
77 *
78 * @param {string} id
79 * @param {?Object} value
80 * */
81 const str = (id, value) => {
82 try {
vidorteg8bce4b02020-10-09 01:16:2183 const i18nInstance = i18nBundle.createMessageInstanceIdFn(path, stringStructure);
vidorteg1fd76f82020-08-26 18:09:2084 return i18nInstance(id, value);
85 } catch (e) {
vidorteg8bce4b02020-10-09 01:16:2186 // ID was not in the main file search for module.json strings
87 if (e instanceof i18nBundle.idNotInMainDictionaryException) {
Kalon Hinds3cb4a092020-11-24 22:55:3188 const stringMappingArray = Object.getOwnPropertyNames(getOrSetModuleJSONStrings());
vidorteg8bce4b02020-10-09 01:16:2189 const index = stringMappingArray.indexOf(id);
90 if (index >= 0) {
91 return stringMappingArray[index];
92 }
93 }
94
vidorteg1fd76f82020-08-26 18:09:2095 return id;
96 }
97 };
98
99 return str;
100}
101
102/**
103 * Returns a span element that may contains other DOM element as placeholders
104 * @param {function(string, ?Object):string} str_
105 * @param {string} stringId
Christy Chen2e411e22020-10-29 19:19:40106 * @param {!Object<string, *>} placeholders
vidorteg1fd76f82020-08-26 18:09:20107 * @return {!Element} the localized result
108 */
Christy Chen2e411e22020-10-29 19:19:40109export function getFormatLocalizedString(str_, stringId, placeholders) {
Kalon Hinds3cb4a092020-11-24 22:55:31110 if (!registeredLocale) {
111 throw new Error(`Unsupported locale '${registeredLocale}'`);
112 }
113
vidorteg1fd76f82020-08-26 18:09:20114 const icuMessage = str_(stringId, placeholders);
115 const formatter = i18nBundle.getFormatter(icuMessage, registeredLocale);
116
117 const icuElements = formatter.getAst().elements;
118 const args = [];
119 let formattedString = '';
120 for (const element of icuElements) {
121 if (element.type === 'argumentElement') {
122 const placeholderValue = placeholders[element.id];
123 if (placeholderValue) {
124 args.push(placeholderValue);
125 element.value = '%s'; // convert the {PH} back to %s to use StringUtilities
126 }
127 }
128 formattedString += element.value;
129 }
130 return formatLocalized(formattedString, args);
131}
132
133/**
134 * @param {string} formattedString
135 * @param {?ArrayLike<?>} args
136 * @return {!Element} the formatted result.
137 */
138export function formatLocalized(formattedString, args) {
139 /** @type {function(string):string} */
140 const substitution = substitution => {
141 return substitution;
142 };
143
144 /**
145 * @param {!Element} a
146 * @param {?} b
147 * @return {!Element}
148 */
149 function append(a, b) {
150 a.appendChild(typeof b === 'string' ? document.createTextNode(b) : b);
151 return a;
152 }
153
154 const formatters = {s: substitution};
155 return Platform.StringUtilities.format(formattedString, args, formatters, document.createElement('span'), append)
156 .formattedResult;
157}