In the learning process of international components, we have come into contact with NumberFormatter, a number formatting operation, which allows us to convert numbers into standard formats, currencies, local languages and other forms. What we are going to learn today is another class MessageFormatter dedicated to formatting information, which is mainly for string operations.
MessageFormatter also follows the ICU specification. The bottom layer is the ICU operation in C, so there is not much difference between the use of C-related code.
format
// 格式化
$fmt = new MessageFormatter("zh_CN", "{0,number,integer} 只猴子在 {1,number,integer} 颗树上,每只树上有 {2,number} 只猴子");
echo $fmt->format([4560, 123, 4560 / 123]), PHP_EOL;
// 4,560 只猴子在 123 颗树上,每只树上有 37.073 只猴子
$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} 只猴子在 {1,number,integer} 颗树上,每只树上有 {2,number} 只猴子", [4560, 123, 4560 / 123]), PHP_EOL;
// 4,560 只猴子在 123 颗树上,每只树上有 37.073 只猴子
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
see it? Similar to the placeholder for precompiled operations in PDO. After calling the format() method, you can let the parameters in this method replace the content of the placeholder. We can specify the type and position of the parameter used in the placeholder, {parameter subscript, type, extended type} This is the rule definition of the placeholder for this information data formatting. It looks very simple, but in fact it has more functions, which we will see later. However, it should be noted that it only supports numbers, dates, and text fragment types. There is an official document for reference in the reference link at the end of the article.
MessageFormatter::formatMessage() is a static method that can specify the language, pre-operation statement, and replacement parameters all at once, without the need to instantiate and then call the format() method.
Unformat (get the parameter array according to the rules)
It can be formatted. Of course, we can also reverse-format the relevant string according to the sentence rules to obtain the parameter list corresponding to the placeholder.
// 根据格式化规则反向获取规则参数
$fmt = new MessageFormatter('zh_CN', "{0,number,integer} 只猴子在 {1,number,integer} 颗树上,每只树上有 {2,number} 只猴子");
$res = $fmt->parse("4,560 只猴子在 123 树上,每只树上有 37.073 只猴子");
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,
// )
This can be achieved by using the instantiated parse() method or directly using the static method MessageFormatter::parseMessage(). It should be noted that for zh_CN, that is, the Chinese language locale, this operation will cause problems. Through getErrorMessage() and getErrorCode(), you can see the error message and error code, and you can see that for Chinese, the error message directly returned is the parsing failure.
Set acquisition rules
In the instantiated object, we can also dynamically modify the rule statement.
// 设置获取规则
$fmt = new MessageFormatter("zh_CN", "{0, number} 猴子在 {1, number} 颗树上");
echo "默认规则: '" . $fmt->getPattern(), PHP_EOL; // 默认规则: '{0, number} 猴子在 {1, number} 颗树上'
echo "格式化结果:" . $fmt->format(array(123, 456)), PHP_EOL; // 格式化结果:123 猴子在 456 颗树上
$fmt->setPattern("{0, number} 颗树上有 {1, number} 猴子");
echo "新规则: '" . $fmt->getPattern(), PHP_EOL; // 新规则: '{0, number} 颗树上有 {1, number} 猴子'
echo "新规则格式化结果: " . $fmt->format(array(123, 456)), PHP_EOL; // 新规则格式化结果: 123 颗树上有 456 猴子
There are two very simple methods, setPattern() is used to set the formatting rules corresponding to the current instantiation, and getPattern() is used to obtain the formatting rules for viewing the current instantiated object. After setting the new rule, the format() or parse() is executed according to the new rule statement.
Format complete example
As mentioned above, in addition to numbers, there can also be placeholders in the date format. Let's demonstrate.
echo MessageFormatter::formatMessage('zh_CN', '今天是 {3, date, full},当前时间为 {3, time, ::Hms}, 我要准备开始 {0} 了,今天要和 {2,number,integer} 人见面,还不能忘了要交 {1,number,currency} 元的电费', ['上班', 35.33, 25, new DateTime()]), PHP_EOL;
// 今天是 2020年11月16日星期一,当前时间为 10:09:30, 我要准备开始 上班 了,今天要和 25 人见面,还不能忘了要交 ¥35.33 元的电费
In this statement, the order of the parameters we give is not in the order in which the placeholders appear in the statement. This has no effect. You only need to specify the index of the parameter array at the corresponding position, such as the first {3, date , full} specifies the 4th element in the parameter array (starting from 0). Date type and time type are all types that can be specified. Of course, we can also specify their date format. For example, in the second placeholder, we only display the current hour, minute, and second information.
If it is a string information, then only a simple {0} is needed, and the string does not need too many type settings. And the number type can be directly formatted as currency and other types, just like those types that can be specified in the NumberFormatter we mentioned before.
After reading this example, do you feel the power of this MessageFormatter? Don't worry, it has even more powerful capabilities.
Multi-number display according to the content of the parameter
For plurals, there is actually no such sentence in Chinese grammar. For example, a 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
Although the plural of the parameter type means plural, but in fact, we can regard it as the usage of a switch() statement.
echo MessageFormatter::formatMessage('zh_CN', '我{0, plural, =0{没有猫} other{有 # 只猫}}', [0]),PHP_EOL; // 我没有猫
echo MessageFormatter::formatMessage('zh_CN', '我{0, plural, =0{没有猫} other{有 # 只猫}}', [1]),PHP_EOL; // 我有 1 只猫
echo MessageFormatter::formatMessage('zh_CN', '我{0, plural, =0{没有猫} other{有 # 只猫}}', [2]),PHP_EOL; // 我有 2 只猫
The \# number is the original content of the corresponding parameter value. This set of grammar brings the MessageFormatter class to a higher level, and what else! Let's take a look at this problem first:
echo MessageFormatter::formatMessage('en_US', 'I Have {0, plural, =0{no cat} =1{a cat} other{# cats}}', [-1]),PHP_EOL; // I Have -1 cats
The parameter is passed wrong, -1 cat is wrong, it doesn't matter, there are other ways to solve this problem.
Select condition rules
// 选择表达式
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
You can see the word choice, which is a choice-related grammar. The latter parameter is actually an interval, which represents which content is used within the range of <= 0 | 1 | >=2. In addition, a placeholder rule can continue to set placeholder symbols.
Summarize
I opened my eyes again. There is no surprise in the first two parts of the article. After all, ordinary string replacement can be done, but it gets more and more exciting as it goes on. Of course, there should be more related rules and grammars, but these materials are very small, and neither the official PHP documents nor the official documents of ICU have found too much introduction. Therefore, we should report to the attitude of learning and understanding first to know that this is the case. In the future, we will find more interesting information and then share and learn. We also hope that friends who have used it will leave a message and discuss it together!
Test code:
Reference documents:
https://www.php.net/manual/zh/class.messageformatter.php
http://userguide.icu-project.org/formatparse/messages
===========
Searchable on their respective media platforms [Hardcore Project Manager]
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。