Skip to content

Commit

Permalink
Plural patch (#67)
Browse files Browse the repository at this point in the history
* Plural patch

* Apply fixes from StyleCI

* Update CHANGELOG

Co-authored-by: StyleCI Bot <[email protected]>
  • Loading branch information
arogachev and StyleCIBot authored Sep 9, 2022
1 parent f50dcb1 commit 17d4c34
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 13 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@

## 1.1.1 under development

- no changes in this release.
- Bug #67: Exclude number from "plural" formatted message, handle missing options' keys (@arogachev)

## 1.1.0 September 07, 2022

- Chg #25: Move `SimpleMessageFormatter` from `yiisoft/translator-formatter-simple` package (@DAGpro, @vjik)
- Enh #63: Add "plural" support to `SimpleMessageFormatter` (@arogachev)

## 1.0.2 July 26, 2022

Expand Down
32 changes: 25 additions & 7 deletions src/SimpleMessageFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public function format(string $message, array $parameters, string $locale = 'en_

switch ($format) {
case 'plural':
$options = $parts[2];
$options = $parts[2] ?? '';
$replacements[$match] = self::pluralize($value, $options);

break;
Expand All @@ -62,24 +62,42 @@ public function format(string $message, array $parameters, string $locale = 'en_
*/
private static function pluralize($value, string $options): string
{
if (!$options) {
throw new InvalidArgumentException('Missing plural keys: ' . self::formatList(self::PLURAL_KEYS) . '.');
}

if (!is_int($value)) {
throw new InvalidArgumentException('Only integer numbers are supported with plural format.');
}

preg_match_all('/([^{}\s]+)({(.*?)})/', $options, $pluralMatches);

foreach ($pluralMatches[1] as $match) {
$map = [];
foreach ($pluralMatches[1] as $index => $match) {
if (!in_array($match, self::PLURAL_KEYS, true)) {
$keysStr = implode(', ', array_map(fn (string $value): string => '"' . $value . '"', self::PLURAL_KEYS));
$keysStr = self::formatList(self::PLURAL_KEYS);

throw new InvalidArgumentException("Invalid plural key - \"$match\". The valid keys are $keysStr.");
}

$map[$match] = $pluralMatches[3][$index];
}

$map = array_combine($pluralMatches[1], $pluralMatches[3]);
$formattedValue = $value . ' ';
$formattedValue .= $value === 1 ? $map[self::PLURAL_ONE] : $map[self::PLURAL_OTHER];
$diff = array_diff(self::PLURAL_KEYS, $pluralMatches[1]);
if ($diff !== []) {
throw new InvalidArgumentException('Missing plural keys: ' . self::formatList($diff) . '.');
}

return $value === 1 ? $map[self::PLURAL_ONE] : $map[self::PLURAL_OTHER];
}

return $formattedValue;
/**
* @param string[] $items
*
* @return string
*/
private static function formatList(array $items): string
{
return implode(', ', array_map(fn (string $value): string => '"' . $value . '"', $items));
}
}
28 changes: 23 additions & 5 deletions tests/SimpleMessageFormatterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,22 +33,22 @@ public function formatProvider(): array
'plural, one' => [
'{min, plural, one{character} other{characters}}',
['min' => 1],
'1 character',
'character',
],
'plural, other' => [
'{min, plural, one{character} other{characters}}',
['min' => 2],
'2 characters',
'characters',
],
'plural, zero' => [
'{min, plural, one{character} other{characters}}',
['min' => 0],
'0 characters',
'characters',
],
'plural, reversed options' => [
'{min, plural, other{characters} one{character}}',
['min' => 1],
'1 character',
'character',
],
// not supported
'not supported' => [
Expand All @@ -61,7 +61,7 @@ public function formatProvider(): array
'text1 {param1} text2 {param2, number} text3 {param3, plural, one{item} other{items}} text4 {param4} ' .
'text5',
['param1' => 1, 'param2' => 2, 'param3' => 3, 'param4' => 4],
'text1 1 text2 2 text3 3 items text4 4 text5',
'text1 1 text2 2 text3 items text4 4 text5',
],
];
}
Expand Down Expand Up @@ -94,6 +94,24 @@ public function testFormatPluralWithNonInteger(): void
$formatter->format('{min, plural, one{character} other{characters}}', ['min' => 'str']);
}

public function testFormatPluralWithMissingKey(): void
{
$formatter = new SimpleMessageFormatter();

$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Missing plural keys: "other".');
$formatter->format('{min, plural, one{character}}', ['min' => 1]);
}

public function testFormatPluralWithMissingKeys(): void
{
$formatter = new SimpleMessageFormatter();

$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Missing plural keys: "one", "other".');
$formatter->format('{min, plural}', ['min' => 1]);
}

public function testFormatWithMissingParameters(): void
{
$formatter = new SimpleMessageFormatter();
Expand Down

0 comments on commit 17d4c34

Please sign in to comment.