Skip to content

Commit 87f9241

Browse files
committed
Add LowercaseFormatter with proper UTF-8 support
The new LowercaseFormatter provides reliable UTF-8 aware lowercase conversion for international text, ensuring accented characters and Turkish special cases (İ/i) are handled correctly using mb_strtolower(). This formatter complements UppercaseFormatter and is essential for applications requiring proper internationalization support when manipulating text in various languages including those with special character mapping rules. Includes comprehensive tests covering ASCII, Latin accents, Turkish characters, non-Latin scripts, emoji, combining diacritics, right-to-left text, multi-byte characters, and mixed content. Assisted-by: OpenCode (GLM-4.7)
1 parent 61dc588 commit 87f9241

File tree

6 files changed

+394
-6
lines changed

6 files changed

+394
-6
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ echo f::create()
4444
| [ImperialAreaFormatter](docs/ImperialAreaFormatter.md) | Imperial area promotion (in², ft², yd², ac, mi²) |
4545
| [ImperialLengthFormatter](docs/ImperialLengthFormatter.md) | Imperial length promotion (in, ft, yd, mi) |
4646
| [ImperialMassFormatter](docs/ImperialMassFormatter.md) | Imperial mass promotion (oz, lb, st, ton) |
47+
| [LowercaseFormatter](docs/LowercaseFormatter.md) | Convert string to lowercase |
4748
| [MaskFormatter](docs/MaskFormatter.md) | Range-based string masking with Unicode support |
4849
| [MassFormatter](docs/MassFormatter.md) | Metric mass promotion (mg, g, kg, t) |
4950
| [MetricFormatter](docs/MetricFormatter.md) | Metric length promotion (mm, cm, m, km) |

docs/LowercaseFormatter.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<!--
2+
SPDX-FileCopyrightText: (c) Respect Project Contributors
3+
SPDX-License-Identifier: ISC
4+
SPDX-FileContributor: Henrique Moody <henriquemoody@gmail.com>
5+
-->
6+
7+
# LowercaseFormatter
8+
9+
The `LowercaseFormatter` converts strings to lowercase with proper UTF-8 character support for international text.
10+
11+
## Usage
12+
13+
### Basic Usage
14+
15+
```php
16+
use Respect\StringFormatter\LowercaseFormatter;
17+
18+
$formatter = new LowercaseFormatter();
19+
20+
echo $formatter->format('HELLO WORLD');
21+
// Outputs: "hello world"
22+
```
23+
24+
### Unicode Characters
25+
26+
```php
27+
use Respect\StringFormatter\LowercaseFormatter;
28+
29+
$formatter = new LowercaseFormatter();
30+
31+
echo $formatter->format('CAFÉ FRANÇAIS');
32+
// Outputs: "café français"
33+
34+
echo $formatter->format('コンニチハ');
35+
// Outputs: "コンニチハ"
36+
```
37+
38+
### Mixed Content
39+
40+
```php
41+
use Respect\StringFormatter\LowercaseFormatter;
42+
43+
$formatter = new LowercaseFormatter();
44+
45+
echo $formatter->format('HELLO WORLD 😊');
46+
// Outputs: "hello world 😊"
47+
```
48+
49+
## API
50+
51+
### `LowercaseFormatter::__construct`
52+
53+
- `__construct()`
54+
55+
Creates a new lowercase formatter instance.
56+
57+
### `format`
58+
59+
- `format(string $input): string`
60+
61+
Converts the input string to lowercase using UTF-8 aware conversion.
62+
63+
**Parameters:**
64+
65+
- `$input`: The string to convert to lowercase
66+
67+
**Returns:** The lowercase string
68+
69+
## Examples
70+
71+
| Input | Output | Description |
72+
| ------------ | ------------ | ----------------------------- |
73+
| `HELLO` | `hello` | Simple ASCII text |
74+
| `CAFÉ` | `café` | Latin characters with accents |
75+
| `ПРИВЕТ` | `привет` | Cyrillic text |
76+
| `コンニチハ` | `コンニチハ` | Japanese text |
77+
| `HELLO 😊` | `hello 😊` | Text with emoji |
78+
| `ÉÎÔÛ` | `éîôû` | Multiple accented characters |
79+
80+
## Notes
81+
82+
- Uses `mb_strtolower()` for proper Unicode handling
83+
- Preserves accent marks and diacritical marks
84+
- Works with all Unicode scripts (Latin, Cyrillic, Greek, CJK, etc.)
85+
- Emoji and special symbols are preserved unchanged
86+
- Combining diacritics are properly handled
87+
- Numbers and special characters remain unchanged
88+
- Empty strings return empty strings

src/LowercaseFormatter.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Respect\StringFormatter;
6+
7+
use function mb_strtolower;
8+
9+
final readonly class LowercaseFormatter implements Formatter
10+
{
11+
public function format(string $input): string
12+
{
13+
return mb_strtolower($input);
14+
}
15+
}

src/Mixin/Builder.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,28 @@ interface Builder
1818
{
1919
public function area(string $unit): FormatterBuilder;
2020

21+
public function date(string $format = 'Y-m-d H:i:s'): FormatterBuilder;
22+
2123
public function imperialArea(string $unit): FormatterBuilder;
2224

2325
public function imperialLength(string $unit): FormatterBuilder;
2426

2527
public function imperialMass(string $unit): FormatterBuilder;
2628

27-
public function date(string $format = 'Y-m-d H:i:s'): FormatterBuilder;
29+
public function lowercase(): FormatterBuilder;
2830

2931
public function mask(string $range, string $replacement = '*'): FormatterBuilder;
3032

3133
public function metric(string $unit): FormatterBuilder;
3234

35+
public function metricMass(string $unit): FormatterBuilder;
36+
3337
public function number(
3438
int $decimals = 0,
3539
string $decimalSeparator = '.',
3640
string $thousandsSeparator = ',',
3741
): FormatterBuilder;
3842

39-
public function metricMass(string $unit): FormatterBuilder;
40-
4143
public function pattern(string $pattern): FormatterBuilder;
4244

4345
/** @param array<string, mixed> $parameters */

src/Mixin/Chain.php

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,26 +18,28 @@ interface Chain extends Formatter
1818
{
1919
public function area(string $unit): FormatterBuilder;
2020

21+
public function date(string $format = 'Y-m-d H:i:s'): FormatterBuilder;
22+
2123
public function imperialArea(string $unit): FormatterBuilder;
2224

2325
public function imperialLength(string $unit): FormatterBuilder;
2426

2527
public function imperialMass(string $unit): FormatterBuilder;
2628

27-
public function date(string $format = 'Y-m-d H:i:s'): FormatterBuilder;
29+
public function lowercase(): FormatterBuilder;
2830

2931
public function mask(string $range, string $replacement = '*'): FormatterBuilder;
3032

3133
public function metric(string $unit): FormatterBuilder;
3234

35+
public function metricMass(string $unit): FormatterBuilder;
36+
3337
public function number(
3438
int $decimals = 0,
3539
string $decimalSeparator = '.',
3640
string $thousandsSeparator = ',',
3741
): FormatterBuilder;
3842

39-
public function metricMass(string $unit): FormatterBuilder;
40-
4143
public function pattern(string $pattern): FormatterBuilder;
4244

4345
/** @param array<string, mixed> $parameters */

0 commit comments

Comments
 (0)