[CORE][I18n] Add I18n::_m_list, which formats an array of elements into a list. Limited to 5 elements, as that should be enough (tm) and ICU doesn't support this natively

This commit is contained in:
Hugo Sales 2022-03-01 12:23:47 +00:00
parent fc203e2e38
commit f73e9c12ba
Signed by: someonewithpc
GPG Key ID: 7D0C7EAFC9D835A0

View File

@ -39,6 +39,7 @@ declare(strict_types = 1);
namespace App\Core\I18n;
use App\Util\Common;
use App\Util\Exception\BugFoundException;
use App\Util\Exception\ServerException;
use App\Util\Formatting;
use InvalidArgumentException;
@ -302,7 +303,7 @@ abstract class I18n
*
* _m(string $msg) -- simple message
* _m(string $ctx, string $msg) -- message with context
* _m(string|string[] $msg, array $params) -- message
* _m(string|string[] $msg, array $params) -- parameterized message
* _m(string $ctx, string|string[] $msg, array $params) -- combination of the previous two
*
* @throws ServerException
@ -346,3 +347,42 @@ function _m(...$args): string
// @codeCoverageIgnoreEnd
}
}
/**
* Convert an array into a localized list
*
* This is needed because not add languages use the form of
* `item <sep> item <sep> item <last-sep> item` (probably)
*
* Note that this simply generates the ICU format, doesn't magically
* perform the translation if no translation is available
*
* @example en: ['foo', 'bar', 'quux'] => "foo, bar and quux"
* @example pt: ['foo', 'bar', 'quux'] => "foo, bar e quux"
* @example ch: ['foo', 'bar', 'quux'] => "foo, bar, quux"
*/
function _m_list(array $elements): string
{
if (\count($elements) > 5) {
// Could be generated dinamically for english, but we can't handle all languages
throw new BugFoundException('Currently only lists of 5 elements supported, as ICU does not support this natively');
}
$icu = I18n::formatICU(
[
0 => '',
1 => '%1$s',
2 => '%1$s and %2$s',
3 => '%1$s, %2$s and %3$s',
4 => '%1$s, %2$s, %3$s and %4$s',
5 => '%1$s, %2$s, %3$s, %4$s and %5$s',
6 => 'NULL',
],
// this uses a string count so the generated is a select, as it's not really a pluralization thing
['count' => (string) \count($elements)],
);
$format = I18n::$translator->trans($icu, ['count' => \count($elements)], I18n::_mdomain(''), Common::currentLanguage()->getLocale());
return sprintf($format, ...$elements);
}