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