@ui5/webcomponents-localization
Version:
Localization for UI5 Web Components
93 lines (92 loc) • 4.41 kB
JavaScript
/*!
* OpenUI5
* (c) Copyright 2009-2024 SAP SE or an SAP affiliate company.
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
*/
import assert from "../assert.js";
/**
* Pattern to analyze MessageFormat strings.
*
* Group 1: captures doubled single quotes within the string
* Group 2: captures quoted fragments within the string.
* Note that java.util.MessageFormat silently forgives a missing single quote at
* the end of a pattern. This special case is handled by the RegEx as well.
* Group 3: captures placeholders
* Checks only for numerical argument index, any remainder is ignored up to the next
* closing curly brace. Nested placeholders are not accepted!
* Group 4: captures any remaining curly braces and indicates syntax errors
*
* [-1] [----- quoted string -----] [------ placeholder ------] [--]
* @private
*/
var rMessageFormat = /('')|'([^']+(?:''[^']*)*)(?:'|$)|\{([0-9]+(?:\s*,[^{}]*)?)\}|[{}]/g;
/**
* Creates a string from a pattern by replacing placeholders with concrete values.
*
* The syntax of the pattern is inspired by (but not fully equivalent to) the
* java.util.MessageFormat.
*
* Placeholders have the form <code>{ integer }</code>, where any occurrence of
* <code>{0}</code> is replaced by the value with index 0 in <code>aValues</code>,
* <code>{1}</code> by the value with index 1 in <code>aValues</code> etc.
*
* To avoid interpretation of curly braces as placeholders, any non-placeholder fragment
* of the pattern can be enclosed in single quotes. The surrounding single quotes will be
* omitted from the result. Single quotes that are not meant to escape a fragment and
* that should appear in the result, need to be doubled. In the result, only a single
* single quote will occur.
*
* Example: Pattern Strings
* <pre>
* formatMessage("Say {0}", ["Hello"]) -> "Say Hello" // normal use case
* formatMessage("Say '{0}'", ["Hello"]) -> "Say {0}" // escaped placeholder
* formatMessage("Say ''{0}''", ["Hello"]) -> "Say 'Hello'" // doubled single quote
* formatMessage("Say '{0}'''", ["Hello"]) -> "Say {0}'" // doubled single quote in quoted fragment
* </pre>
* In contrast to java.util.MessageFormat, format types or format styles are not supported.
* Everything after the argument index and up to the first closing curly brace is ignored.
* Nested placeholders (as supported by java.lang.MessageFormat for the format type choice)
* are not ignored but reported as a parse error.
*
* This method throws an Error when the pattern syntax is not fulfilled (e.g. unbalanced curly
* braces, nested placeholders or a non-numerical argument index).
*
* This method can also be used as a formatter within a binding. The first part of a composite binding
* will be used as pattern, the following parts as aValues. If there is only one value and this
* value is an array it will be handled like the default described above.
*
* @function
* @since 1.58
* @alias module:sap/base/strings/formatMessage
* @param {string} sPattern A pattern string in the described syntax
* @param {any[]} [aValues=[]] The values to be used instead of the placeholders.
* @returns {string} The formatted result string
* @SecPassthrough {*|return}
* @public
*/
var fnFormatMessage = function (sPattern, aValues) {
assert(typeof sPattern === "string" || sPattern instanceof String, "pattern must be string");
if (arguments.length > 2 || aValues != null && !Array.isArray(aValues)) {
aValues = Array.prototype.slice.call(arguments, 1);
}
aValues = aValues || [];
return sPattern.replace(rMessageFormat, function ($0, $1, $2, $3, offset) {
if ($1) {
// a doubled single quote in a normal string fragment
// --> emit a single quote
return "'";
} else if ($2) {
// a quoted sequence of chars, potentially containing doubled single quotes again
// --> emit with doubled single quotes replaced by a single quote
return $2.replace(/''/g, "'");
} else if ($3) {
// a welformed curly brace
// --> emit the argument but ignore other parameters
return String(aValues[parseInt($3)]);
}
// e.g. malformed curly braces
// --> throw Error
throw new Error("formatMessage: pattern syntax error at pos. " + offset);
});
};
export default fnFormatMessage;