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