From 10ca51e72ae01676dc0ddb46f85fdcceb933b934 Mon Sep 17 00:00:00 2001 From: Hugo Sales Date: Sun, 7 Jun 2020 16:50:11 +0000 Subject: [PATCH] [I18N] Overhaul _m() implementation to support ICU message formats --- src/Core/I18n/I18n.php | 45 ++++++++++++++++++++---------------- src/Core/I18n/I18nHelper.php | 37 +++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 20 deletions(-) diff --git a/src/Core/I18n/I18n.php b/src/Core/I18n/I18n.php index 448028fb86..fbc1344293 100644 --- a/src/Core/I18n/I18n.php +++ b/src/Core/I18n/I18n.php @@ -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()`'); } } diff --git a/src/Core/I18n/I18nHelper.php b/src/Core/I18n/I18nHelper.php index 568d0d93bc..4bd1888384 100644 --- a/src/Core/I18n/I18nHelper.php +++ b/src/Core/I18n/I18nHelper.php @@ -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; + } }