xref: /webtrees/app/Module/LanguageEnglishUnitedStates.php (revision 47fbabfaf6bcc9ddb84526bde50d7b213057cf67)
1<?php
2
3/**
4 * webtrees: online genealogy
5 * Copyright (C) 2023 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
18declare(strict_types=1);
19
20namespace Fisharebest\Webtrees\Module;
21
22use Fisharebest\Localization\Locale\LocaleEnUs;
23use Fisharebest\Localization\Locale\LocaleInterface;
24use Fisharebest\Webtrees\Relationship;
25
26use function abs;
27use function min;
28use function str_repeat;
29
30/**
31 * Class LanguageEnglishUnitedStates.
32 */
33class LanguageEnglishUnitedStates extends AbstractModule implements ModuleLanguageInterface
34{
35    use ModuleLanguageTrait;
36
37    protected const COUSIN = [
38        'sibling',
39        'first cousin',
40        'second cousin',
41        'third cousin',
42        'fourth cousin',
43        'fifth cousin',
44        'sixth cousin',
45        'seventh cousin',
46        'eighth cousin',
47        'ninth cousin',
48        'tenth cousin',
49        'eleventh cousin',
50        'twelfth cousin',
51        'thirteenth cousin',
52        'fourteenth cousin',
53        'fifteenth cousin',
54        'sixteenth cousin',
55        'seventeenth cousin',
56        'eighteenth cousin',
57        'nineteenth cousin',
58        'twentieth cousin',
59        'twenty-first cousin',
60        'twenty-second cousin',
61        'twenty-third cousin',
62        'twenty-fourth cousin',
63        'twenty-fifth cousin',
64        'twenty-sixth cousin',
65        'twenty-seventh cousin',
66        'twenty-eighth cousin',
67        'twenty-ninth cousin',
68        'thirtieth cousin',
69    ];
70
71    protected const REMOVED = [
72        '',
73        ' once removed',
74        ' twice removed',
75        ' three times removed',
76        ' four times removed',
77        ' five times removed',
78        ' six times removed',
79        ' seven times removed',
80        ' eight times removed',
81        ' nine times removed',
82        ' ten times removed',
83        ' eleven removed',
84        ' twelve removed',
85        ' thirteen removed',
86        ' fourteen times removed',
87        ' fifteen times removed',
88        ' sixteen times removed',
89        ' seventeen times removed',
90        ' eighteen times removed',
91        ' nineteen times removed',
92        ' twenty times removed',
93        ' twenty-one times removed',
94        ' twenty-two times removed',
95        ' twenty-three times removed',
96        ' twenty-four times removed',
97        ' twenty-five times removed',
98        ' twenty-six times removed',
99        ' twenty-seven times removed',
100        ' twenty-eight times removed',
101        ' twenty-nine times removed',
102    ];
103
104    protected const DIRECTION = [
105        -1 => ' descending',
106        0  => '',
107        1  => ' ascending',
108    ];
109
110    /**
111     * One of: 'DMY', 'MDY', 'YMD'.
112     *
113     * @return string
114     */
115    public function dateOrder(): string
116    {
117        return 'MDY';
118    }
119
120    /**
121     * @return LocaleInterface
122     */
123    public function locale(): LocaleInterface
124    {
125        return new LocaleEnUs();
126    }
127
128    /**
129     * @return array<Relationship>
130     */
131    public function relationships(): array
132    {
133        // Genitive forms in English are simple/regular, as no relationship name ends in "s".
134        $genitive = static fn (string $s): array => [$s, $s . '’s %s'];
135
136        $cousin = static fn (int $up, int $down): array => $genitive(
137            (static::COUSIN[min($up, $down)] ?? 'distant cousin') .
138            (static::REMOVED[abs($up - $down)] ?? ' many times removed') .
139            static::DIRECTION[$up <=> $down]
140        );
141
142        $great = static fn (int $n, string $prefix, string $suffix): array => $genitive(
143            $prefix . ($n > 3 ? 'great ×' . $n . ' ' : str_repeat('great-', $n)) . $suffix
144        );
145
146        return [
147            // Adopted
148            Relationship::fixed('adoptive-mother', 'adoptive-mother’s %s')->adoptive()->mother(),
149            Relationship::fixed('adoptive-father', 'adoptive-father’s %s')->adoptive()->father(),
150            Relationship::fixed('adoptive-parent', 'adoptive-parent’s %s')->adoptive()->parent(),
151            Relationship::fixed('adopted-daughter', 'adopted-daughter’s %s')->adopted()->daughter(),
152            Relationship::fixed('adopted-son', 'adopted-son’s %s')->adopted()->son(),
153            Relationship::fixed('adopted-child', 'adopted-child’s %s')->adopted()->child(),
154            // Fostered
155            Relationship::fixed('foster-mother', 'foster-mother’s %s')->fostering()->mother(),
156            Relationship::fixed('foster-father', 'foster-father’s %s')->fostering()->father(),
157            Relationship::fixed('foster-parent', 'foster-parent’s %s')->fostering()->parent(),
158            Relationship::fixed('foster-daughter', 'foster-daughter’s %s')->fostered()->daughter(),
159            Relationship::fixed('foster-son', 'foster-son’s %s')->fostered()->son(),
160            Relationship::fixed('foster-child', 'foster-child’s %s')->fostered()->child(),
161            // Parents
162            Relationship::fixed('mother', 'mother’s %s')->mother(),
163            Relationship::fixed('father', 'father’s %s')->father(),
164            Relationship::fixed('parent', 'parent’s %s')->parent(),
165            // Children
166            Relationship::fixed('daughter', 'daughter’s %s')->daughter(),
167            Relationship::fixed('son', 'son’s %s')->son(),
168            Relationship::fixed('child', 'child’s %s')->child(),
169            // Siblings
170            Relationship::fixed('twin sister', 'twin sister’s %s')->twin()->sister(),
171            Relationship::fixed('twin brother', 'twin brother’s %s')->twin()->brother(),
172            Relationship::fixed('twin sibling', 'twin sibling’s %s')->twin()->sibling(),
173            Relationship::fixed('elder sister', 'elder sister’s %s')->older()->sister(),
174            Relationship::fixed('elder brother', 'elder brother’s %s')->older()->brother(),
175            Relationship::fixed('elder sibling', 'elder sibling’s %s')->older()->sibling(),
176            Relationship::fixed('younger sister', 'younger sister’s %s')->younger()->sister(),
177            Relationship::fixed('younger brother', 'younger brother’s %s')->younger()->brother(),
178            Relationship::fixed('younger sibling', 'younger sibling’s %s')->younger()->sibling(),
179            Relationship::fixed('sister', 'sister’s %s')->sister(),
180            Relationship::fixed('brother', 'brother’s %s')->brother(),
181            Relationship::fixed('sibling', 'sibling’s %s')->sibling(),
182            // Half-siblings
183            Relationship::fixed('half-sister', 'half-sister’s %s')->parent()->daughter(),
184            Relationship::fixed('half-brother', 'half-brother’s %s')->parent()->son(),
185            Relationship::fixed('half-sibling', 'half-sibling’s %s')->parent()->child(),
186            // Stepfamily
187            Relationship::fixed('stepmother', 'stepmother’s %s')->parent()->wife(),
188            Relationship::fixed('stepfather', 'stepfather’s %s')->parent()->husband(),
189            Relationship::fixed('stepparent', 'stepparent’s %s')->parent()->married()->spouse(),
190            Relationship::fixed('stepdaughter', 'stepdaughter’s %s')->married()->spouse()->daughter(),
191            Relationship::fixed('stepson', 'stepson’s %s')->married()->spouse()->son(),
192            Relationship::fixed('stepchild', 'stepchild’s %s')->married()->spouse()->child(),
193            Relationship::fixed('stepsister', 'stepsister’s %s')->parent()->spouse()->daughter(),
194            Relationship::fixed('stepbrother', 'stepbrother’s %s')->parent()->spouse()->son(),
195            Relationship::fixed('stepsibling', 'stepsibling’s %s')->parent()->spouse()->child(),
196            // Partners
197            Relationship::fixed('ex-wife', 'ex-wife’s %s')->divorced()->partner()->female(),
198            Relationship::fixed('ex-husband', 'ex-husband’s %s')->divorced()->partner()->male(),
199            Relationship::fixed('ex-spouse', 'ex-spouse’s %s')->divorced()->partner(),
200            Relationship::fixed('fiancée', 'fiancée’s %s')->engaged()->partner()->female(),
201            Relationship::fixed('fiancé', 'fiancé’s %s')->engaged()->partner()->male(),
202            Relationship::fixed('wife', 'wife’s %s')->wife(),
203            Relationship::fixed('husband', 'husband’s %s')->husband(),
204            Relationship::fixed('spouse', 'spouse’s %s')->spouse(),
205            Relationship::fixed('partner', 'partner’s %s')->partner(),
206            // In-laws
207            Relationship::fixed('mother-in-law', 'mother-in-law’s %s')->married()->spouse()->mother(),
208            Relationship::fixed('father-in-law', 'father-in-law’s %s')->married()->spouse()->father(),
209            Relationship::fixed('parent-in-law', 'parent-in-law’s %s')->married()->spouse()->parent(),
210            Relationship::fixed('daughter-in-law', 'daughter-in-law’s %s')->child()->wife(),
211            Relationship::fixed('son-in-law', 'son-in-law’s %s')->child()->husband(),
212            Relationship::fixed('child-in-law', 'child-in-law’s %s')->child()->married()->spouse(),
213            Relationship::fixed('sister-in-law', 'sister-in-law’s %s')->sibling()->spouse()->sister(),
214            Relationship::fixed('brother-in-law', 'brother-in-law’s %s')->sibling()->spouse()->brother(),
215            Relationship::fixed('sibling-in-law', 'sibling-in-law’s %s')->sibling()->spouse()->sibling(),
216            Relationship::fixed('sister-in-law', 'sister-in-law’s %s')->spouse()->sister(),
217            Relationship::fixed('brother-in-law', 'brother-in-law’s %s')->spouse()->brother(),
218            Relationship::fixed('sibling-in-law', 'sibling-in-law’s %s')->spouse()->sibling(),
219            Relationship::fixed('sister-in-law', 'sister-in-law’s %s')->sibling()->wife(),
220            Relationship::fixed('brother-in-law', 'brother-in-law’s %s')->sibling()->husband(),
221            Relationship::fixed('sibling-in-law', 'sibling-in-law’s %s')->sibling()->spouse(),
222            // Grandparents
223            Relationship::fixed('maternal-grandmother', 'maternal-grandmother’s %s')->mother()->mother(),
224            Relationship::fixed('maternal-grandfather', 'maternal-grandfather’s %s')->mother()->father(),
225            Relationship::fixed('maternal-grandparent', 'maternal-grandfather’s %s')->mother()->parent(),
226            Relationship::fixed('paternal-grandmother', 'paternal-grandmother’s %s')->father()->mother(),
227            Relationship::fixed('paternal-grandfather', 'paternal-grandfather’s %s')->father()->father(),
228            Relationship::fixed('paternal-grandparent', 'paternal-grandfather’s %s')->father()->parent(),
229            Relationship::fixed('grandmother', 'grandmother’s %s')->parent()->mother(),
230            Relationship::fixed('grandfather', 'grandfather’s %s')->parent()->father(),
231            Relationship::fixed('grandparent', 'grandparent’s %s')->parent()->parent(),
232            // Grandchildren
233            Relationship::fixed('granddaughter', 'granddaughter’s %s')->child()->daughter(),
234            Relationship::fixed('grandson', 'grandson’s %s')->child()->son(),
235            Relationship::fixed('grandchild', 'grandchild’s %s')->child()->child(),
236            // Relationships with dynamically generated names
237            Relationship::dynamic(static fn (int $n) => $great($n - 1, '', 'aunt'))->ancestor()->sister(),
238            Relationship::dynamic(static fn (int $n) => $great($n - 1, '', 'aunt'))->ancestor()->sibling()->wife(),
239            Relationship::dynamic(static fn (int $n) => $great($n - 1, '', 'uncle'))->ancestor()->brother(),
240            Relationship::dynamic(static fn (int $n) => $great($n - 1, '', 'uncle'))->ancestor()->sibling()->husband(),
241            Relationship::dynamic(static fn (int $n) => $great($n - 1, '', 'niece'))->sibling()->descendant()->female(),
242            Relationship::dynamic(static fn (int $n) => $great($n - 1, '', 'niece'))->married()->spouse()->sibling()->descendant()->female(),
243            Relationship::dynamic(static fn (int $n) => $great($n - 1, '', 'nephew'))->sibling()->descendant()->male(),
244            Relationship::dynamic(static fn (int $n) => $great($n - 1, '', 'nephew'))->married()->spouse()->sibling()->descendant()->male(),
245            Relationship::dynamic(static fn (int $n) => $great($n - 1, 'maternal ', 'grandmother'))->mother()->ancestor()->female(),
246            Relationship::dynamic(static fn (int $n) => $great($n - 1, 'maternal ', 'grandfather'))->mother()->ancestor()->male(),
247            Relationship::dynamic(static fn (int $n) => $great($n - 1, 'paternal ', 'grandmother'))->father()->ancestor()->female(),
248            Relationship::dynamic(static fn (int $n) => $great($n - 1, 'paternal ', 'grandfather'))->father()->ancestor()->male(),
249            Relationship::dynamic(static fn (int $n) => $great($n - 1, '', 'grandparent'))->ancestor(),
250            Relationship::dynamic(static fn (int $n) => $great($n - 2, '', 'granddaughter'))->descendant()->female(),
251            Relationship::dynamic(static fn (int $n) => $great($n - 2, '', 'grandson'))->descendant()->male(),
252            Relationship::dynamic(static fn (int $n) => $great($n - 2, '', 'grandchild'))->descendant(),
253            Relationship::dynamic($cousin)->ancestor()->sibling()->descendant(),
254        ];
255    }
256}
257