In the course of internationalizing components, we’ve been exposed to NumberFormatter, which allows us to convert numbers to standard formats, currencies, native languages, and so on. Today we’ll look at another class dedicated to information formatting, MessageFormatter, which is primarily for string operations.

MessageFormatter also follows the ICU specification, and the underlying ICU operations are in C, so there is not much difference in how c-related code is used.

formatting

/ / format
$fmt = new MessageFormatter("zh_CN"."{0,number, INTEGER} monkeys on {1,number,integer} trees, {2,number} monkeys on each tree");
echo $fmt->format([4560.123.4560 / 123]), PHP_EOL;
// 4,560 monkeys in 123 trees with 37.073 monkeys on each tree

$fmt = new MessageFormatter("de"."{0,number,integer} Affen auf {1,number,integer} Bäumen sind {2,number} Affen pro Baum");
echo $fmt->format([4560.123.4560 / 123]), PHP_EOL;
// 4.560 Affen auf 123 Bäumen sind 37,073 Affen pro Baum

echo MessageFormatter::formatMessage("zh_CN"."{0,number, INTEGER} monkeys on {1,number,integer} trees, {2,number} monkeys on each tree"[4560.123.4560 / 123]), PHP_EOL;
// 4,560 monkeys in 123 trees with 37.073 monkeys on each tree

echo MessageFormatter::formatMessage("de"."{0,number,integer} Affen auf {1,number,integer} Bäumen sind {2,number} Affen pro Baum"[4560.123.4560 / 123]), PHP_EOL;
// 4.560 Affen auf 123 Bäumen sind 37,073 Affen pro Baum
Copy the code

See? Similar to placeholders for precompiled operations in PDO. After you call the format() method, you can replace the contents of the placeholders with arguments from the method. We can specify the type and position of the argument to be used for the placeholder. {parameter subscript, type, extension type} is the regular definition of the placeholder for the information data formatting. It may seem simple, but there’s more to it than that, as we’ll see later. Note, however, that it only supports numbers, dates, and text fragments. The official documentation is available at the reference link at the end of this article.

MessageFormatter: : formatMessage () at the static method can specify the languages, pre operation statement and replace parameters, don’t need to be instantiated first and then call the format () method.

Unformat (get the parameter array according to the rule)

Can be formatted, of course, we can also according to the statement rules to unformat the relevant string to obtain the corresponding placeholder parameter list.

// Get rule parameters in reverse according to formatting rules
$fmt = new MessageFormatter('zh_CN'."{0,number, INTEGER} monkeys on {1,number,integer} trees, {2,number} monkeys on each tree");
$res = $fmt->parse("4,560 monkeys in 123 trees, each with 37.073 monkeys.");
var_export($res); // false
echo "ERROR: " . $fmt->getErrorMessage() . "(" . $fmt->getErrorCode() . ")\n";
// ERROR: Parsing failed: U_MESSAGE_PARSE_ERROR (6)

$fmt = new MessageFormatter('en_US'."{0,number,integer} monkeys on {1,number,integer} trees make {2,number} monkeys per tree");
$res = $fmt->parse("4,560 monkeys on 123 trees make 37.073 monkeys per tree");
var_export($res);
// array (
/ / 0 = > 4560,
/ / 1 = > 123,
/ / 2 = > 37.073,
/ /)

$fmt = new MessageFormatter('de'."{0,number,integer} Affen auf {1,number,integer} Bäumen sind {2,number} Affen pro Baum");
$res = $fmt->parse("4.560 Affen auf 123 Bäumen sind 37,073 Affen pro Baum");
var_export($res);
// array (
/ / 0 = > 4560,
/ / 1 = > 123,
/ / 2 = > 37.073,
/ /)

$fmt = MessageFormatter::parseMessage('de'."{0,number,integer} Affen auf {1,number,integer} Bäumen sind {2,number} Affen pro Baum"."4.560 Affen auf 123 Bäumen sind 37,073 Affen pro Baum");
var_export($fmt);
// array (
/ / 0 = > 4560,
/ / 1 = > 123,
/ / 2 = > 37.073,
/ /)
Copy the code

Using instantiated the parse () method or directly using a static method MessageFormatter: : parseMessage () will be able to achieve such operations. Note that this operation is problematic for zh_CN, the Chinese locale. GetErrorMessage () and getErrorCode() you can see the error message and the error code, and you can see that for Chinese the error message returned is a parsing failure.

Setting the Obtaining Rule

We can also modify rule statements dynamically within instantiated objects.

// Set the fetch rule
$fmt = new MessageFormatter("zh_CN"."{0, number} monkey on {1, number} tree");
echo "Default rule: '" . $fmt->getPattern(), PHP_EOL; // Default rule: '{0, number} monkey on {1, number} tree '
echo "Formatting result:" . $fmt->format(array(123.456)), PHP_EOL; // Format result: 123 monkeys in 456 trees

$fmt->setPattern("{0, number} tree with {1, number} monkey");
echo "New rule: '" . $fmt->getPattern(), PHP_EOL; // new rule: '{0, number} tree has {1, number} monkey '
echo "New rule formatting result:" . $fmt->format(array(123.456)), PHP_EOL; // New rule formatting result: 123 trees with 456 monkeys
Copy the code

Two very simple methods, setPattern() is used to set the formatting rules for the current instantiation, and getPattern() is used to get the formatting rules for viewing the current instantiation object. When the new rules are set, format() or parse() is executed according to the new rule statement.

Complete formatting example

As mentioned above, in addition to numbers, you can also have placeholders in the format of dates, so let’s demonstrate that.

echo MessageFormatter::formatMessage('zh_CN'.{3, date, currency} {3, time, ::Hms} {3, time, ::Hms} {2,number,integer}['work'.35.33.25.new DateTime()]), PHP_EOL;
// Today is Monday, November 16th, 2020, the current time is 10:09:30, I have to get ready for work, I have to meet 25 people today, and I have to pay the electricity bill of 35.33 yuan
Copy the code

The first {3, date, full} element is the fourth element in the argument array (starting from 0). The date and time types can be specified, but we can also specify their date format. For example, the second placeholder will only display the current minute and second information.

If it’s a string, a simple {0} is all you need. Strings don’t require much typing. Numeric types, on the other hand, can be directly formatted to types like money, like those specified in the NumberFormatter we talked about earlier.

Do you see the power of the MessageFormatter after this example? Don’t worry. It’s got more than that.

The complex number is displayed according to the parameter content

For plural numbers, there is no such statement in Chinese grammar, such as one cat is a cat and two cats are two cats.

echo MessageFormatter::formatMessage('en_US'.'I Have {0, plural, =0{no cat} =1{a cat} other{# cats}}'[0]),PHP_EOL; // I Have no cat
echo MessageFormatter::formatMessage('en_US'.'I Have {0, plural, =0{no cat} =1{a cat} other{# cats}}'[1]),PHP_EOL; // I Have a cat
echo MessageFormatter::formatMessage('en_US'.'I Have {0, plural, =0{no cat} =1{a cat} other{# cats}}'[2]),PHP_EOL; // I Have 2 cats
Copy the code

There’s a plural argument type, but think of it as a switch() statement.

echo MessageFormatter::formatMessage('zh_CN'.{{plural, =0{there are no cats} other{there are # cats}}'[0]),PHP_EOL; // I don't have a cat
echo MessageFormatter::formatMessage('zh_CN'.{{plural, =0{there are no cats} other{there are # cats}}'[1]),PHP_EOL; // I have a cat
echo MessageFormatter::formatMessage('zh_CN'.{{plural, =0{there are no cats} other{there are # cats}}'[2]),PHP_EOL; // I have two cats
Copy the code

The # sign is the original value of the MessageFormatter. This syntax adds another level to the MessageFormatter class. Let’s start with this question:

echo MessageFormatter::formatMessage('en_US'.'I Have {0, plural, =0{no cat} =1{a cat} other{# cats}}'[-1]),PHP_EOL; // I Have -1 cats
Copy the code

Wrong parameter, -1 cat is not right, it doesn’t matter, there are other ways to solve this problem.

Selection condition rule

// Select the expression
echo MessageFormatter::formatMessage('en_US'.'I Have {0, choice, 0 #no cats| 1 #one cat | 2 #{0, number} cats}'[-1]),PHP_EOL; // I Have no cats
echo MessageFormatter::formatMessage('en_US'.'I Have {0, choice, 0 #no cats| 1 #one cat | 2 #{0, number} cats}'[0]),PHP_EOL; // I Have no cats
echo MessageFormatter::formatMessage('en_US'.'I Have {0, choice, 0 #no cats| 1 #one cat | 2 #{0, number} cats}'[1]),PHP_EOL; // I Have one cat
echo MessageFormatter::formatMessage('en_US'.'I Have {0, choice, 0 #no cats| 1 #one cat | 2 #{0, number} cats}'[2]),PHP_EOL; // I Have 2 cats
echo MessageFormatter::formatMessage('en_US'.'I Have {0, choice, 0 #no cats| 1 #one cat | 2 #{0, number} cats}'[10]),PHP_EOL; // I Have 10 cats
Copy the code

This is shown by the word “choice”, which is a choice related grammar. At the back of the parameter is an interval, represent the < = 0 | 1 | > = 2 which content within the scope of use. In addition, a placeholder rule can continue to cover placeholders.

conclusion

It was another eye-opener. The first two parts of this article aren’t really that exciting, since ordinary string substitutions can be done, but they get better and better as they go on. Of course, there should be more to the syntax of the rules, but this information is very sparse, and neither the OFFICIAL PHP documentation nor the OFFICIAL ICU documentation has much to say about it. So we still respond to learn to understand the attitude of the first to know that there is such a thing, in the future to find more interesting information to share learning, but also hope to have used the friends of the message together to discuss oh!

Test code:

Reference Documents:

www.php.net/manual/zh/c…

Userguide.icu-project.org/formatparse…

= = = = = = = = = = = = = = =

Follow the public account: [Hardcore project manager] to get the latest articles

Add WeChat/QQ friends: free xiaoyuezigonggong / 149844827 】 【 PHP, project management, learning materials

Zhihu, Public Account, Douyin, Toutiao Search [Hardcore Project Manager]

ID of station B: 482780532