[I18N] Overhaul _m() implementation to support ICU message formats

This commit is contained in:
Hugo Sales 2020-06-07 16:50:11 +00:00 committed by Hugo Sales
parent a65a46f14e
commit 10ca51e72a
Signed by untrusted user: someonewithpc
GPG Key ID: 7D0C7EAFC9D835A0
2 changed files with 62 additions and 20 deletions

View File

@ -88,28 +88,33 @@ function _m(string $msg /*, ...*/): string
$args = func_get_args();
switch (count($args)) {
case 1:
// Empty parameters
// Empty parameters, simple message
return I18nHelper::$translator->trans($msg, [], $domain);
case 2:
$context = $args[0];
$msg_single = $args[1];
// ASCII 4 is EOT, used to separate context from string
return I18nHelper::$translator->trans($context . '\004' . $msg_single, [], $domain);
case 3:
// '|' separates the singular from the plural version
$msg_single = $args[0];
$msg_plural = $args[1];
$n = $args[2];
return I18nHelper::$translator->trans($msg_single . '|' . $msg_plural, ['%d' => $n], $domain);
case 4:
// Combine both
$context = $args[0];
$msg_single = $args[1];
$msg_plural = $args[2];
$n = $args[3];
return I18nHelper::$translator->trans($context . '\004' . $msg_single . '|' . $msg_plural,
['%d' => $n], $domain);
if (is_int($args[2])) {
throw new Exception('Calling `_m()` with an explicit number is deprecated, ' .
'use an explicit parameter');
}
// Falthrough
// no break
case 2:
if (is_string($args[0]) && !is_array($args[1])) {
// ASCII 4 is EOT, used to separate context from string
$context = array_shift($args) . '\004';
}
if (is_array($args[0])) {
$args[0] = I18nHelper::formatICU($args[0], $args[1]);
}
if (is_string($args[0])) {
$msg = $args[0];
$params = $args[1] ?? [];
return I18nHelper::$translator->trans($context ?? '' . $msg, $params, $domain);
}
// Fallthrough
// no break
default:
throw new InvalidArgumentException('Bad parameter count to _m()');
throw new InvalidArgumentException('Bad parameters to `_m()`');
}
}

View File

@ -214,4 +214,41 @@ abstract class I18nHelper
'vi' => ['q' => 0.8, 'lang' => 'vi', 'name' => 'Vietnamese', 'direction' => 'ltr'],
];
}
public static function formatICU(array $messages, array $params): string
{
$msg = '';
foreach ($params as $var => $val) {
if (is_int($var)) {
$pref = '=';
$op = 'plural';
} elseif (is_string($var)) {
$pref = '';
$op = 'select,';
} else {
throw new Exception('Invalid key type. (int|string) only');
}
$res = "{{$var}, {$op} ";
$i = 1;
$cnt = count($messages);
foreach ($messages as $val => $m) {
if (is_array($m)) {
array_shift($params);
$res .= "{$pref}{$val} {" . self::formatICU($m, $params) . '} ';
} elseif (is_string($m)) {
if ($i !== $cnt) {
$res .= "{$pref}{$val} {{$m}} ";
} else {
$res .= "other {{$m}}}";
}
} else {
throw new Exception('Invalid message array');
}
++$i;
}
$msg .= $res;
}
return $msg;
}
}