Passed
Push — main ( 9bad59...cc181a )
by Greg
06:50
created

ModuleLanguageTrait::normalize()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 10
rs 10
c 0
b 0
f 0
1
<?php
2
3
/**
4
 * webtrees: online genealogy
5
 * Copyright (C) 2025 webtrees development team
6
 * This program is free software: you can redistribute it and/or modify
7
 * it under the terms of the GNU General Public License as published by
8
 * the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 * GNU General Public License for more details.
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16
 */
17
18
declare(strict_types=1);
19
20
namespace Fisharebest\Webtrees\Module;
21
22
use Fisharebest\ExtCalendar\CalendarInterface;
23
use Fisharebest\ExtCalendar\GregorianCalendar;
24
use Fisharebest\Localization\Locale\LocaleEnUs;
25
use Fisharebest\Localization\Locale\LocaleInterface;
26
use Fisharebest\Webtrees\I18N;
27
use Fisharebest\Webtrees\Relationship;
28
use Normalizer;
29
30
use function mb_substr;
31
use function normalizer_normalize;
32
33
/**
34
 * Default implementation of ModuleLanguageInterface.
35
 */
36
trait ModuleLanguageTrait
37
{
38
    private const array COMBINING_DIACRITICS = [
0 ignored issues
show
Bug introduced by
A parse error occurred: Syntax error, unexpected T_STRING, expecting '=' on line 38 at column 24
Loading history...
39
        "\u{0300}" => '',
40
        "\u{0301}" => '',
41
        "\u{0302}" => '',
42
        "\u{0303}" => '',
43
        "\u{0304}" => '',
44
        "\u{0305}" => '',
45
        "\u{0306}" => '',
46
        "\u{0307}" => '',
47
        "\u{0308}" => '',
48
        "\u{0309}" => '',
49
        "\u{030A}" => '',
50
        "\u{030B}" => '',
51
        "\u{030C}" => '',
52
        "\u{030D}" => '',
53
        "\u{030E}" => '',
54
        "\u{030F}" => '',
55
        "\u{0310}" => '',
56
        "\u{0311}" => '',
57
        "\u{0312}" => '',
58
        "\u{0313}" => '',
59
        "\u{0314}" => '',
60
        "\u{0315}" => '',
61
        "\u{0316}" => '',
62
        "\u{0317}" => '',
63
        "\u{0318}" => '',
64
        "\u{0319}" => '',
65
        "\u{031A}" => '',
66
        "\u{031B}" => '',
67
        "\u{031C}" => '',
68
        "\u{031D}" => '',
69
        "\u{031E}" => '',
70
        "\u{031F}" => '',
71
        "\u{0320}" => '',
72
        "\u{0321}" => '',
73
        "\u{0322}" => '',
74
        "\u{0323}" => '',
75
        "\u{0324}" => '',
76
        "\u{0325}" => '',
77
        "\u{0326}" => '',
78
        "\u{0327}" => '',
79
        "\u{0328}" => '',
80
        "\u{0329}" => '',
81
        "\u{032A}" => '',
82
        "\u{032B}" => '',
83
        "\u{032C}" => '',
84
        "\u{032D}" => '',
85
        "\u{032E}" => '',
86
        "\u{032F}" => '',
87
        "\u{0330}" => '',
88
        "\u{0331}" => '',
89
        "\u{0332}" => '',
90
        "\u{0333}" => '',
91
        "\u{0334}" => '',
92
        "\u{0335}" => '',
93
        "\u{0336}" => '',
94
        "\u{0337}" => '',
95
        "\u{0338}" => '',
96
        "\u{0339}" => '',
97
        "\u{033A}" => '',
98
        "\u{033B}" => '',
99
        "\u{033C}" => '',
100
        "\u{033D}" => '',
101
        "\u{033E}" => '',
102
        "\u{033F}" => '',
103
        "\u{0340}" => '',
104
        "\u{0341}" => '',
105
        "\u{0342}" => '',
106
        "\u{0343}" => '',
107
        "\u{0344}" => '',
108
        "\u{0345}" => '',
109
        "\u{0346}" => '',
110
        "\u{0347}" => '',
111
        "\u{0348}" => '',
112
        "\u{0349}" => '',
113
        "\u{034A}" => '',
114
        "\u{034B}" => '',
115
        "\u{034C}" => '',
116
        "\u{034D}" => '',
117
        "\u{034E}" => '',
118
        "\u{034F}" => '',
119
        "\u{0350}" => '',
120
        "\u{0351}" => '',
121
        "\u{0352}" => '',
122
        "\u{0353}" => '',
123
        "\u{0354}" => '',
124
        "\u{0355}" => '',
125
        "\u{0356}" => '',
126
        "\u{0357}" => '',
127
        "\u{0358}" => '',
128
        "\u{0359}" => '',
129
        "\u{035A}" => '',
130
        "\u{035B}" => '',
131
        "\u{035C}" => '',
132
        "\u{035D}" => '',
133
        "\u{035E}" => '',
134
        "\u{035F}" => '',
135
        "\u{0360}" => '',
136
        "\u{0361}" => '',
137
        "\u{0362}" => '',
138
        "\u{0363}" => '',
139
        "\u{0364}" => '',
140
        "\u{0365}" => '',
141
        "\u{0366}" => '',
142
        "\u{0367}" => '',
143
        "\u{0368}" => '',
144
        "\u{0369}" => '',
145
        "\u{036A}" => '',
146
        "\u{036B}" => '',
147
        "\u{036C}" => '',
148
        "\u{036D}" => '',
149
        "\u{036E}" => '',
150
        "\u{036F}" => '',
151
    ];
152
153
    /**
154
     * @return array<int,string>
155
     */
156
    public function alphabet(): array
157
    {
158
        return [
159
            'A',
160
            'B',
161
            'C',
162
            'D',
163
            'E',
164
            'F',
165
            'G',
166
            'H',
167
            'I',
168
            'J',
169
            'K',
170
            'L',
171
            'M',
172
            'N',
173
            'O',
174
            'P',
175
            'Q',
176
            'R',
177
            'S',
178
            'T',
179
            'U',
180
            'V',
181
            'W',
182
            'X',
183
            'Y',
184
            'Z',
185
        ];
186
    }
187
188
    public function calendar(): CalendarInterface
189
    {
190
        return new GregorianCalendar();
191
    }
192
193
    public function dateOrder(): string
194
    {
195
        return 'DMY';
196
    }
197
198
    public function initialLetter(string $string): string
199
    {
200
        return mb_substr($string, 0, 1);
201
    }
202
203
    /**
204
     * Ignore diacritics on letters - unless the language considers them a different letter.
205
     */
206
    public function normalize(string $text): string
207
    {
208
        // Decompose any combined characters.
209
        $decomposed = normalizer_normalize($text, Normalizer::FORM_KD);
210
211
        if ($decomposed === false) {
212
            // Invalid UTF8? INTL library not installed?
213
            $decomposed = $text;
214
        }
215
216
        // Keep any significant diacritics.
217
        $text = strtr($decomposed, $this->normalizeExceptions());
218
219
        // Remove other diacritics.
220
        return strtr($text, self::COMBINING_DIACRITICS);
221
    }
222
223
    /**
224
     * Letters with diacritics that are considered distinct letters in this language.
225
     *
226
     * @return array<string,string>
227
     */
228
    protected function normalizeExceptions(): array
229
    {
230
        return [];
231
    }
232
233
    public function title(): string
234
    {
235
        return  $this->locale()->endonym();
236
    }
237
238
    public function description(): string
239
    {
240
        return I18N::translate('Language') . ' — ' . $this->title() . ' — ' . $this->locale()->languageTag();
241
    }
242
243
    public function locale(): LocaleInterface
244
    {
245
        return new LocaleEnUs();
246
    }
247
248
    /**
249
     * @return array<Relationship>
250
     */
251
    public function relationships(): array
252
    {
253
        return [];
254
    }
255
}
256