Skip to content

Commit 201b86a

Browse files
committed
Add Language::list method
1 parent 29b943a commit 201b86a

File tree

3 files changed

+132
-0
lines changed

3 files changed

+132
-0
lines changed

.phpstorm.meta.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,3 +567,36 @@
567567
\Framework\Language\Language::getFallbackLevel(),
568568
argumentsSet('fallback_levels')
569569
);
570+
registerArgumentsSet(
571+
'intl_types',
572+
\IntlListFormatter::TYPE_AND,
573+
\IntlListFormatter::TYPE_OR,
574+
\IntlListFormatter::TYPE_UNITS,
575+
'and',
576+
'or',
577+
'units',
578+
);
579+
expectedArguments(
580+
\Framework\Language\Language::list(),
581+
1,
582+
argumentsSet('intl_types')
583+
);
584+
registerArgumentsSet(
585+
'intl_widths',
586+
\IntlListFormatter::WIDTH_WIDE,
587+
\IntlListFormatter::WIDTH_SHORT,
588+
\IntlListFormatter::WIDTH_NARROW,
589+
'wide',
590+
'short',
591+
'narrow',
592+
);
593+
expectedArguments(
594+
\Framework\Language\Language::list(),
595+
2,
596+
argumentsSet('intl_widths')
597+
);
598+
expectedArguments(
599+
\Framework\Language\Language::list(),
600+
3,
601+
argumentsSet('locales')
602+
);

src/Language.php

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@
1111

1212
use Framework\Helpers\Isolation;
1313
use Framework\Language\Debug\LanguageCollector;
14+
use IntlListFormatter;
1415
use InvalidArgumentException;
1516
use JetBrains\PhpStorm\ArrayShape;
1617
use JetBrains\PhpStorm\Pure;
18+
use ValueError;
1719

1820
/**
1921
* Class Language.
@@ -166,6 +168,43 @@ public function date(int $time, ?string $style = null, ?string $locale = null) :
166168
);
167169
}
168170

171+
/**
172+
* Gets a formatted list in a given locale.
173+
*
174+
* @param array<string> $strings The list of strings
175+
* @param int|string $type The {@see IntlListFormatter} type
176+
* @param int|string $width The {@see IntlListFormatter} width
177+
* @param string|null $locale A custom locale or null to use the current
178+
*
179+
* @throws InvalidArgumentException for invalid list type and width
180+
* @throws ValueError for invalid locale
181+
*
182+
* @return string
183+
*/
184+
public function list(
185+
array $strings,
186+
int | string $type = IntlListFormatter::TYPE_AND,
187+
int | string $width = IntlListFormatter::WIDTH_WIDE,
188+
?string $locale = null
189+
) : string {
190+
$type = match ($type) {
191+
IntlListFormatter::TYPE_AND, 'and' => IntlListFormatter::TYPE_AND,
192+
IntlListFormatter::TYPE_OR, 'or' => IntlListFormatter::TYPE_OR,
193+
IntlListFormatter::TYPE_UNITS, 'units' => IntlListFormatter::TYPE_UNITS,
194+
default => throw new InvalidArgumentException('Invalid list type: ' . $type),
195+
};
196+
$width = match ($width) {
197+
IntlListFormatter::WIDTH_WIDE, 'wide' => IntlListFormatter::WIDTH_WIDE,
198+
IntlListFormatter::WIDTH_SHORT, 'short' => IntlListFormatter::WIDTH_SHORT,
199+
IntlListFormatter::WIDTH_NARROW, 'narrow' => IntlListFormatter::WIDTH_NARROW,
200+
default => throw new InvalidArgumentException('Invalid list width: ' . $width),
201+
};
202+
$locale ??= $this->getCurrentLocale();
203+
$formatter = new IntlListFormatter($locale, $type, $width);
204+
// @phpstan-ignore-next-line
205+
return $formatter->format($strings);
206+
}
207+
169208
/**
170209
* Find for absolute file paths from where language lines can be loaded.
171210
*

tests/LanguageTest.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
use Framework\Language\FallbackLevel;
1313
use Framework\Language\Language;
14+
use IntlListFormatter;
1415
use PHPUnit\Framework\TestCase;
1516

1617
/**
@@ -89,6 +90,65 @@ public function testDateWithInvalidStyle() : void
8990
$this->language->date(\time(), 'unknown');
9091
}
9192

93+
public function testList() : void
94+
{
95+
$strings = ['a', 'b', 'c'];
96+
$list = $this->language->list($strings);
97+
self::assertSame('a, b, and c', $list);
98+
$list = $this->language->list($strings, 'and');
99+
self::assertSame('a, b, and c', $list);
100+
$list = $this->language->list($strings, IntlListFormatter::TYPE_OR);
101+
self::assertSame('a, b, or c', $list);
102+
$list = $this->language->list($strings, 'or');
103+
self::assertSame('a, b, or c', $list);
104+
$list = $this->language->list($strings, IntlListFormatter::TYPE_UNITS);
105+
self::assertSame('a, b, c', $list);
106+
$list = $this->language->list($strings, 'units');
107+
self::assertSame('a, b, c', $list);
108+
$list = $this->language->list($strings, locale: 'en_US');
109+
self::assertSame('a, b, and c', $list);
110+
$list = $this->language->list($strings, width: 'wide', locale: 'en_US');
111+
self::assertSame('a, b, and c', $list);
112+
$list = $this->language->list($strings, width: IntlListFormatter::WIDTH_SHORT, locale: 'en_US');
113+
self::assertSame('a, b, & c', $list);
114+
$list = $this->language->list($strings, width: 'short', locale: 'en_US');
115+
self::assertSame('a, b, & c', $list);
116+
$list = $this->language->list($strings, width: IntlListFormatter::WIDTH_NARROW, locale: 'en_US');
117+
self::assertSame('a, b, c', $list);
118+
$list = $this->language->list($strings, width: 'narrow', locale: 'en_US');
119+
self::assertSame('a, b, c', $list);
120+
$list = $this->language->list($strings, locale: 'DE');
121+
self::assertSame('a, b und c', $list);
122+
$list = $this->language->list($strings, locale: 'pt-Br');
123+
self::assertSame('a, b e c', $list);
124+
}
125+
126+
public function testListWithInvalidLocale() : void
127+
{
128+
$strings = ['a', 'b', 'c'];
129+
$this->expectException(\ValueError::class);
130+
$this->expectExceptionMessage(
131+
'IntlListFormatter::__construct(): Argument #1 ($locale) "foo" is invalid'
132+
);
133+
$this->language->list($strings, locale: 'foo');
134+
}
135+
136+
public function testListWithInvalidType() : void
137+
{
138+
$strings = ['a', 'b', 'c'];
139+
$this->expectException(\InvalidArgumentException::class);
140+
$this->expectExceptionMessage('Invalid list type: foo');
141+
$this->language->list($strings, type: 'foo');
142+
}
143+
144+
public function testListWithInvalidWidth() : void
145+
{
146+
$strings = ['a', 'b', 'c'];
147+
$this->expectException(\InvalidArgumentException::class);
148+
$this->expectExceptionMessage('Invalid list width: foo');
149+
$this->language->list($strings, width: 'foo');
150+
}
151+
92152
public function testDirectories() : void
93153
{
94154
self::assertSame([

0 commit comments

Comments
 (0)