1<?php 2 3/** 4 * webtrees: online genealogy 5 * Copyright (C) 2022 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 * @return LocaleInterface 112 */ 113 public function locale(): LocaleInterface 114 { 115 return new LocaleEnUs(); 116 } 117 118 /** 119 * @return array<Relationship> 120 */ 121 public function relationships(): array 122 { 123 // Genitive forms in English are simple/regular, as no relationship name ends in "s". 124 $genitive = static fn (string $s): array => [$s, $s . '’s %s']; 125 126 $cousin = static fn (int $up, int $down): array => $genitive( 127 (static::COUSIN[min($up, $down)] ?? 'distant cousin') . 128 (static::REMOVED[abs($up - $down)] ?? ' many times removed') . 129 static::DIRECTION[$up <=> $down] 130 ); 131 132 $great = static fn (int $n, string $prefix, string $suffix): array => $genitive( 133 $prefix . ($n > 3 ? 'great ×' . $n . ' ' : str_repeat('great-', $n)) . $suffix 134 ); 135 136 return [ 137 // Adopted 138 Relationship::fixed('adoptive-mother', 'adoptive-mother’s %s')->adoptive()->mother(), 139 Relationship::fixed('adoptive-father', 'adoptive-father’s %s')->adoptive()->father(), 140 Relationship::fixed('adoptive-parent', 'adoptive-parent’s %s')->adoptive()->parent(), 141 Relationship::fixed('adopted-daughter', 'adopted-daughter’s %s')->adopted()->daughter(), 142 Relationship::fixed('adopted-son', 'adopted-son’s %s')->adopted()->son(), 143 Relationship::fixed('adopted-child', 'adopted-child’s %s')->adopted()->child(), 144 // Fostered 145 Relationship::fixed('foster-mother', 'foster-mother’s %s')->fostering()->mother(), 146 Relationship::fixed('foster-father', 'foster-father’s %s')->fostering()->father(), 147 Relationship::fixed('foster-parent', 'foster-parent’s %s')->fostering()->parent(), 148 Relationship::fixed('foster-daughter', 'foster-daughter’s %s')->fostered()->daughter(), 149 Relationship::fixed('foster-son', 'foster-son’s %s')->fostered()->son(), 150 Relationship::fixed('foster-child', 'foster-child’s %s')->fostered()->child(), 151 // Parents 152 Relationship::fixed('mother', 'mother’s %s')->mother(), 153 Relationship::fixed('father', 'father’s %s')->father(), 154 Relationship::fixed('parent', 'parent’s %s')->parent(), 155 // Children 156 Relationship::fixed('daughter', 'daughter’s %s')->daughter(), 157 Relationship::fixed('son', 'son’s %s')->son(), 158 Relationship::fixed('child', 'child’s %s')->child(), 159 // Siblings 160 Relationship::fixed('twin sister', 'twin sister’s %s')->twin()->sister(), 161 Relationship::fixed('twin brother', 'twin brother’s %s')->twin()->brother(), 162 Relationship::fixed('twin sibling', 'twin sibling’s %s')->twin()->sibling(), 163 Relationship::fixed('elder sister', 'elder sister’s %s')->older()->sister(), 164 Relationship::fixed('elder brother', 'elder brother’s %s')->older()->brother(), 165 Relationship::fixed('elder sibling', 'elder sibling’s %s')->older()->sibling(), 166 Relationship::fixed('younger sister', 'younger sister’s %s')->younger()->sister(), 167 Relationship::fixed('younger brother', 'younger brother’s %s')->younger()->brother(), 168 Relationship::fixed('younger sibling', 'younger sibling’s %s')->younger()->sibling(), 169 Relationship::fixed('sister', 'sister’s %s')->sister(), 170 Relationship::fixed('brother', 'brother’s %s')->brother(), 171 Relationship::fixed('sibling', 'sibling’s %s')->sibling(), 172 // Half-siblings 173 Relationship::fixed('half-sister', 'half-sister’s %s')->parent()->daughter(), 174 Relationship::fixed('half-brother', 'half-brother’s %s')->parent()->son(), 175 Relationship::fixed('half-sibling', 'half-sibling’s %s')->parent()->child(), 176 // Stepfamily 177 Relationship::fixed('stepmother', 'stepmother’s %s')->parent()->wife(), 178 Relationship::fixed('stepfather', 'stepfather’s %s')->parent()->husband(), 179 Relationship::fixed('stepparent', 'stepparent’s %s')->parent()->married()->spouse(), 180 Relationship::fixed('stepdaughter', 'stepdaughter’s %s')->married()->spouse()->daughter(), 181 Relationship::fixed('stepson', 'stepson’s %s')->married()->spouse()->son(), 182 Relationship::fixed('stepchild', 'stepchild’s %s')->married()->spouse()->child(), 183 Relationship::fixed('stepsister', 'stepsister’s %s')->parent()->spouse()->daughter(), 184 Relationship::fixed('stepbrother', 'stepbrother’s %s')->parent()->spouse()->son(), 185 Relationship::fixed('stepsibling', 'stepsibling’s %s')->parent()->spouse()->child(), 186 // Partners 187 Relationship::fixed('ex-wife', 'ex-wife’s %s')->divorced()->partner()->female(), 188 Relationship::fixed('ex-husband', 'ex-husband’s %s')->divorced()->partner()->male(), 189 Relationship::fixed('ex-spouse', 'ex-spouse’s %s')->divorced()->partner(), 190 Relationship::fixed('fiancée', 'fiancée’s %s')->engaged()->partner()->female(), 191 Relationship::fixed('fiancé', 'fiancé’s %s')->engaged()->partner()->male(), 192 Relationship::fixed('wife', 'wife’s %s')->wife(), 193 Relationship::fixed('husband', 'husband’s %s')->husband(), 194 Relationship::fixed('spouse', 'spouse’s %s')->spouse(), 195 Relationship::fixed('partner', 'partner’s %s')->partner(), 196 // In-laws 197 Relationship::fixed('mother-in-law', 'mother-in-law’s %s')->married()->spouse()->mother(), 198 Relationship::fixed('father-in-law', 'father-in-law’s %s')->married()->spouse()->father(), 199 Relationship::fixed('parent-in-law', 'parent-in-law’s %s')->married()->spouse()->parent(), 200 Relationship::fixed('daughter-in-law', 'daughter-in-law’s %s')->child()->wife(), 201 Relationship::fixed('son-in-law', 'son-in-law’s %s')->child()->husband(), 202 Relationship::fixed('child-in-law', 'child-in-law’s %s')->child()->married()->spouse(), 203 Relationship::fixed('sister-in-law', 'sister-in-law’s %s')->sibling()->spouse()->sister(), 204 Relationship::fixed('brother-in-law', 'brother-in-law’s %s')->sibling()->spouse()->brother(), 205 Relationship::fixed('sibling-in-law', 'sibling-in-law’s %s')->sibling()->spouse()->sibling(), 206 Relationship::fixed('sister-in-law', 'sister-in-law’s %s')->spouse()->sister(), 207 Relationship::fixed('brother-in-law', 'brother-in-law’s %s')->spouse()->brother(), 208 Relationship::fixed('sibling-in-law', 'sibling-in-law’s %s')->spouse()->sibling(), 209 Relationship::fixed('sister-in-law', 'sister-in-law’s %s')->sibling()->wife(), 210 Relationship::fixed('brother-in-law', 'brother-in-law’s %s')->sibling()->husband(), 211 Relationship::fixed('sibling-in-law', 'sibling-in-law’s %s')->sibling()->spouse(), 212 // Grandparents 213 Relationship::fixed('maternal-grandmother', 'maternal-grandmother’s %s')->mother()->mother(), 214 Relationship::fixed('maternal-grandfather', 'maternal-grandfather’s %s')->mother()->father(), 215 Relationship::fixed('maternal-grandparent', 'maternal-grandfather’s %s')->mother()->parent(), 216 Relationship::fixed('paternal-grandmother', 'paternal-grandmother’s %s')->father()->mother(), 217 Relationship::fixed('paternal-grandfather', 'paternal-grandfather’s %s')->father()->father(), 218 Relationship::fixed('paternal-grandparent', 'paternal-grandfather’s %s')->father()->parent(), 219 Relationship::fixed('grandmother', 'grandmother’s %s')->parent()->mother(), 220 Relationship::fixed('grandfather', 'grandfather’s %s')->parent()->father(), 221 Relationship::fixed('grandparent', 'grandparent’s %s')->parent()->parent(), 222 // Grandchildren 223 Relationship::fixed('granddaughter', 'granddaughter’s %s')->child()->daughter(), 224 Relationship::fixed('grandson', 'grandson’s %s')->child()->son(), 225 Relationship::fixed('grandchild', 'grandchild’s %s')->child()->child(), 226 // Relationships with dynamically generated names 227 Relationship::dynamic(static fn (int $n) => $great($n - 1, '', 'aunt'))->ancestor()->sister(), 228 Relationship::dynamic(static fn (int $n) => $great($n - 1, '', 'aunt'))->ancestor()->sibling()->wife(), 229 Relationship::dynamic(static fn (int $n) => $great($n - 1, '', 'uncle'))->ancestor()->brother(), 230 Relationship::dynamic(static fn (int $n) => $great($n - 1, '', 'uncle'))->ancestor()->sibling()->husband(), 231 Relationship::dynamic(static fn (int $n) => $great($n - 1, '', 'niece'))->sibling()->descendant()->female(), 232 Relationship::dynamic(static fn (int $n) => $great($n - 1, '', 'niece'))->married()->spouse()->sibling()->descendant()->female(), 233 Relationship::dynamic(static fn (int $n) => $great($n - 1, '', 'nephew'))->sibling()->descendant()->male(), 234 Relationship::dynamic(static fn (int $n) => $great($n - 1, '', 'nephew'))->married()->spouse()->sibling()->descendant()->male(), 235 Relationship::dynamic(static fn (int $n) => $great($n - 2, 'maternal ', 'grandmother'))->mother()->ancestor()->female(), 236 Relationship::dynamic(static fn (int $n) => $great($n - 1, 'maternal ', 'grandfather'))->mother()->ancestor()->male(), 237 Relationship::dynamic(static fn (int $n) => $great($n - 1, 'paternal ', 'grandmother'))->father()->ancestor()->female(), 238 Relationship::dynamic(static fn (int $n) => $great($n - 1, 'paternal ', 'grandfather'))->father()->ancestor()->male(), 239 Relationship::dynamic(static fn (int $n) => $great($n - 1, '', 'grandparent'))->ancestor(), 240 Relationship::dynamic(static fn (int $n) => $great($n - 2, '', 'granddaughter'))->descendant()->female(), 241 Relationship::dynamic(static fn (int $n) => $great($n - 2, '', 'grandson'))->descendant()->male(), 242 Relationship::dynamic(static fn (int $n) => $great($n - 2, '', 'grandchild'))->descendant(), 243 Relationship::dynamic($cousin)->ancestor()->sibling()->descendant(), 244 ]; 245 } 246} 247