diff --git a/app/Module/LanguageGerman.php b/app/Module/LanguageGerman.php index 043b363297a..94d6ea45215 100644 --- a/app/Module/LanguageGerman.php +++ b/app/Module/LanguageGerman.php @@ -21,12 +21,19 @@ use Fisharebest\Localization\Locale\LocaleDe; use Fisharebest\Localization\Locale\LocaleInterface; +use Fisharebest\Webtrees\Relationship; use Fisharebest\Webtrees\Encodings\UTF8; +/** + * Class LanguageGerman. + */ class LanguageGerman extends AbstractModule implements ModuleLanguageInterface { use ModuleLanguageTrait; + /** + * @return LocaleInterface + */ public function locale(): LocaleInterface { return new LocaleDe(); @@ -50,4 +57,163 @@ protected function normalizeExceptions(): array UTF8::LATIN_SMALL_LETTER_SHARP_S => 'ss', ]; } + + public function relationships(): array + { + $genitive = static fn (string $prefix, string $suffix, string $gender): array => [ + $prefix . $suffix, + '%s ' . ($gender === 'M' ? 'des ' . $prefix . 's' : '%s der ' . $prefix) . $suffix, + ]; + + // $n <= -1 -> '' + // $n == 0 -> Ur + // $n == 1 -> Urur + // $n >= 2 -> $n+1 ' x Ur' + $ur = static fn (int $n, string $simpleGreat, string $suffix, string $gender): array => $genitive( + (($n > 1) ? ($n + 1) . ' x Ur' : (($n > -1) ? 'Ur' . str_repeat('ur', $n) : '')) . $simpleGreat, + $suffix, + $gender + ); + + return [ + // Adopted + Relationship::fixed('Adoptivmutter', '%s der Adoptivmutter')->adoptive()->mother(), + Relationship::fixed('Adoptivvater', '%s des Adoptivvaters')->adoptive()->father(), + Relationship::fixed('Adoptiveltern', '%s der Adoptiveltern')->adoptive()->parent(), + Relationship::fixed('Adoptivtochter', '%s der Adoptivtochter')->adopted()->daughter(), + Relationship::fixed('Adoptivsohn', '%s des Adoptivsohnes')->adopted()->son(), + Relationship::fixed('Adoptivkind', '%s des Adoptivkindes')->adopted()->child(), + // Fostered + Relationship::fixed('Pflegemutter', '%s der Pflegemutter')->fostering()->mother(), + Relationship::fixed('Pflegevater', '%s des Pflegevaters')->fostering()->father(), + Relationship::fixed('Pflegeeltern', '%s der Pflegeeltern')->fostering()->parent(), + Relationship::fixed('Pflegetochter', '%s der Pflegetochter')->fostered()->daughter(), + Relationship::fixed('Pflegesohn', '%s des Pflegesohnes')->fostered()->son(), + Relationship::fixed('Pflegekind', '%s des Pflegekindes')->fostered()->child(), + // Parents + Relationship::fixed('Mutter', '%s der Mutter')->mother(), + Relationship::fixed('Vater', '%s des Vaters')->father(), + Relationship::fixed('Elternteil', '%s der Eltern')->parent(), + // Children + Relationship::fixed('Tochter', '%s der Tochter')->daughter(), + Relationship::fixed('Sohn', '%s des Sohnes')->son(), + Relationship::fixed('Kind', '%s des Kindes')->child(), + // Siblings + Relationship::fixed('Zwillingsschwester', '%s der Zwillingsschwester')->twin()->sister(), + Relationship::fixed('Zwillingsbruder', '%s des Zwillingsbruders')->twin()->brother(), + Relationship::fixed('Zwillingsgeschwister', '%s des Zwillingsgeschwisters')->twin()->sibling(), + Relationship::fixed('Ältere Schwester', '%s der älterer Schwester')->older()->sister(), + Relationship::fixed('Älterer Bruder', '%s des älteren Bruders')->older()->brother(), + Relationship::fixed('Älteres Geschwister', '%s des älteren Geschwisters')->older()->sibling(), + Relationship::fixed('Jüngere Schwester', '%s der jüngeren Schwester')->younger()->sister(), + Relationship::fixed('Jüngerer Bruder', '%s des jüngeren Bruders')->younger()->brother(), + Relationship::fixed('Jüngeres Geschwister', '%s des jüngeres Geschwisters')->younger()->sibling(), + Relationship::fixed('Schwester', '%s der Schwester')->sister(), + Relationship::fixed('Bruder', '%s des Bruders')->brother(), + Relationship::fixed('Geschwister', '%s der Geschwister')->sibling(), + // Half-siblings + Relationship::fixed('Halbschwester', '%s der Halbschwester')->parent()->daughter(), + Relationship::fixed('Halbbruder', '%s des Halbbruders')->parent()->son(), + Relationship::fixed('Halbgeschwister', '%s der Halbgeschwister')->parent()->child(), + // Stepfamily + Relationship::fixed('Stiefmutter', '%s der Stiefmutter')->parent()->wife(), + Relationship::fixed('Stiefvater', '%s des Stiefvaters')->parent()->husband(), + Relationship::fixed('Stiefelternteil', '%s des Stiefelternteils')->parent()->married()->spouse(), + Relationship::fixed('Stieftochter', '%s der Stieftochter')->married()->spouse()->daughter(), + Relationship::fixed('Stiefsohn', '%s des Stiefsohnes')->married()->spouse()->son(), + Relationship::fixed('Stiefkind', '%s des Stiefkindes')->married()->spouse()->child(), + Relationship::fixed('Stiefschwester', '%s der Stiefschwester')->parent()->spouse()->daughter(), + Relationship::fixed('Stiefbruder', '%s des Stiefbruders')->parent()->spouse()->son(), + Relationship::fixed('Stiefgeschwister', '%s der Stiefgeschwister')->parent()->spouse()->child(), + // Cousins + Relationship::fixed('Cousin', '%s des Cousins')->parent()->sibling()->son(), + Relationship::fixed('Cousine', '%s der Cousine')->parent()->sibling()->daughter(), + Relationship::fixed('Cousin/Cousine', '%s des Cousins/der Cousine')->parent()->sibling()->child(), + // Partners + Relationship::fixed('Ex-Frau', '%s der Ex-Frau')->divorced()->partner()->female(), + Relationship::fixed('Ex-Mann', '%s des Ex-Mannes')->divorced()->partner()->male(), + Relationship::fixed('Ex-Ehepartner', '%s des Ex-Ehepartners')->divorced()->partner(), + Relationship::fixed('Verlobte', '%s der Verlobten')->engaged()->partner()->female(), + Relationship::fixed('Verlobter', '%s des Verlobten')->engaged()->partner()->male(), + Relationship::fixed('Ehefrau', '%s der Ehefrau')->wife(), + Relationship::fixed('Ehemann', '%s des Ehemannes')->husband(), + Relationship::fixed('Ehepartner', '%s des Ehepartners')->spouse(), + Relationship::fixed('Partner', '%s des Partners')->partner(), + // In-laws + Relationship::fixed('Schwiegermutter', '%s der Schwiegermutter')->married()->spouse()->mother(), + Relationship::fixed('Schwiegervater', '%s des Schwiegervaters')->married()->spouse()->father(), + Relationship::fixed('Schwiegereltern', '%s der Schwiegereltern')->married()->spouse()->parent(), + Relationship::fixed('Schwiegertochter', '%s der Schwiegertochter')->child()->wife(), + Relationship::fixed('Schwiegersohn', '%s des Schwiegersohnes')->child()->husband(), + Relationship::fixed('Schwiegerkind', '%s des Schwiegerkindes')->child()->married()->spouse(), + // + Relationship::fixed('Schwägerin', '%s der Schwägerin')->sibling()->spouse()->sister(), + Relationship::fixed('Schwager', '%s des Schwagers')->sibling()->spouse()->brother(), + Relationship::fixed('Schwager/Schwägerin', '%s des Schwagers / der Schwägerin')->sibling()->spouse()->sibling(), + Relationship::fixed('Schwägerin', '%s der Schwägerin')->spouse()->sister(), + Relationship::fixed('Schwager', '%s des Schwagers')->spouse()->brother(), + Relationship::fixed('Schwager/Schwägerin', '%s des Schwagers / der Schwägerin')->spouse()->sibling(), + Relationship::fixed('Schwägerin', '%s der Schwägerin')->sibling()->wife(), + Relationship::fixed('Schwager', '%s des Schwagers')->sibling()->husband(), + Relationship::fixed('Schwager/Schwägerin', '%s des Schwagers / der Schwägerin')->sibling()->spouse(), + // Grandparents + Relationship::fixed('Großmutter mütterlicherseits', '%s der Großmutter (mütterlicherseits)')->mother()->mother(), + Relationship::fixed('Großvater mütterlicherseits', '%s des Großvaters (mütterlicherseits)')->mother()->father(), + Relationship::fixed('Großeltern mütterlicherseits', '%s der Großeltern (mütterlicherseits)')->mother()->parent(), + Relationship::fixed('Großmutter väterlicherseits', '%s der Großmutter (väterlicherseits)')->father()->mother(), + Relationship::fixed('Großvater väterlicherseits', '%s des Großvaters (väterlicherseits)')->father()->father(), + Relationship::fixed('Großeltern väterlicherseits', '%s der Großeltern (väterlicherseits)')->father()->parent(), + Relationship::fixed('Großmutter', '%s der Großmutter')->parent()->mother(), + Relationship::fixed('Großvater', '%s des Großvaters')->parent()->father(), + Relationship::fixed('Großeltern', '%s der Großeltern')->parent()->parent(), + // Grandchildren + Relationship::fixed('Enkelin', '%s der Enkelin')->child()->daughter(), + Relationship::fixed('Enkel', '%s des Enkels')->child()->son(), + Relationship::fixed('Enkelin/Enkel', '%s der Enkelin/des Enkels')->child()->child(), + // Nichte / Neffe + Relationship::fixed('Nichte', '%s der Nichte')->sibling()->daughter(), + Relationship::fixed('Nichte', '%s der Nichte')->married()->spouse()->sibling()->daughter(), + Relationship::fixed('Neffe', '%s des Neffen')->sibling()->son(), + Relationship::fixed('Neffe', '%s des Neffen')->married()->spouse()->sibling()->son(), + Relationship::fixed('Nichte/Neffe', '%s der Nichte / des Neffen')->sibling()->child(), + Relationship::fixed('Nichte/Neffe', '%s der Nichte/ des Neffen')->married()->spouse()->sibling()->child(), + // Großnichte / Großneffe + Relationship::fixed('Großnichte', '%s der Großnichte')->sibling()->child()->child()->female(), + Relationship::fixed('Großnichte', '%s der Großnichte')->married()->spouse()->sibling()->child()->child()->female(), + Relationship::fixed('Großneffe', '%s des Großneffen')->sibling()->child()->child()->male(), + Relationship::fixed('Großneffe', '%s des Großneffen')->married()->spouse()->sibling()->child()->child()->male(), + // Tante / Onkel + Relationship::fixed('Tante', '%s der Tante')->parent()->sister(), + Relationship::fixed('Tante', '%s der Tante')->parent()->brother()->wife(), + Relationship::fixed('Onkel', '%s des Onkels')->parent()->sister()->husband(), + Relationship::fixed('Onkel', '%s des Onkels')->parent()->brother(), + // Großtante / Großonkel + Relationship::fixed('Großtante', '%s der Großtante')->parent()->parent()->sister(), + Relationship::fixed('Großtante', '%s der Großtante')->parent()->parent()->brother()->wife(), + Relationship::fixed('Großonkel', '%s des Großonkels')->parent()->parent()->brother(), + Relationship::fixed('Großonkel', '%s des Großonkels')->parent()->parent()->sister()->husband(), + // Relationships with dynamically generated names + // ancestors: n=2 -> Urgroßmutter (mütterlicherseits) / Großmutter der Mutter + Relationship::dynamic(static fn (int $n) => $ur($n - 2, 'großmutter', ' (mütterlicherseits)', 'F'))->mother()->ancestor()->female(), + Relationship::dynamic(static fn (int $n) => $ur($n - 2, 'großvater', ' (mütterlicherseits)', 'M'))->mother()->ancestor()->male(), + Relationship::dynamic(static fn (int $n) => $ur($n - 2, 'großmutter', ' (väterlicherseits)', 'F'))->father()->ancestor()->female(), + Relationship::dynamic(static fn (int $n) => $ur($n - 2, 'großvater', ' (väterlicherseits)', 'M'))->father()->ancestor()->male(), + // + Relationship::dynamic(static fn (int $n) => $ur($n - 2, 'großeltern', ' (väterlicherseits)', 'U'))->father()->ancestor(), + Relationship::dynamic(static fn (int $n) => $ur($n - 2, 'großeltern', ' (mütterlicherseits)', 'U'))->mother()->ancestor(), + // + Relationship::dynamic(static fn (int $n) => $ur($n - 3, 'großtante', '', 'F'))->ancestor()->sister(), + Relationship::dynamic(static fn (int $n) => $ur($n - 3, 'großtante', '', 'F'))->ancestor()->sibling()->wife(), + Relationship::dynamic(static fn (int $n) => $ur($n - 3, 'großonkel', '', 'M'))->ancestor()->brother(), + Relationship::dynamic(static fn (int $n) => $ur($n - 3, 'großonkel', '', 'M'))->ancestor()->sibling()->husband(), + // descendants + Relationship::dynamic(static fn (int $n) => $ur($n - 3, 'großnichte', '', 'F'))->sibling()->descendant()->female(), + Relationship::dynamic(static fn (int $n) => $ur($n - 3, 'großnichte', '', 'F'))->married()->spouse()->sibling()->descendant()->female(), + Relationship::dynamic(static fn (int $n) => $ur($n - 3, 'großneffe', '', 'M'))->sibling()->descendant()->male(), + Relationship::dynamic(static fn (int $n) => $ur($n - 3, 'großneffe', '', 'M'))->married()->spouse()->sibling()->descendant()->male(), + Relationship::dynamic(static fn (int $n) => $ur($n - 3, 'enkelin', '', 'F'))->descendant()->female(), + Relationship::dynamic(static fn (int $n) => $ur($n - 3, 'enkel', '', 'M'))->descendant()->male(), + Relationship::dynamic(static fn (int $n) => $ur($n - 3, 'enkelin/enkel', '', 'U'))->descendant(), + ]; + } } diff --git a/tests/feature/RelationshipNamesTest.php b/tests/feature/RelationshipNamesTest.php index 1d8673e0902..6db793170a5 100644 --- a/tests/feature/RelationshipNamesTest.php +++ b/tests/feature/RelationshipNamesTest.php @@ -25,6 +25,7 @@ use Fisharebest\Webtrees\Module\LanguageEnglishGreatBritain; use Fisharebest\Webtrees\Module\LanguageEnglishUnitedStates; use Fisharebest\Webtrees\Module\LanguageFrench; +use Fisharebest\Webtrees\Module\LanguageGerman; use Fisharebest\Webtrees\Module\LanguageSlovakian; use Fisharebest\Webtrees\Module\ModuleLanguageInterface; use Fisharebest\Webtrees\Services\RelationshipService; @@ -371,6 +372,57 @@ public function testRelationshipNames(): void self::assertRelationships('druhostupňový bratranec starej matky', 'vnuk druhostupňovej sesternice', [$i1m, $f4m, $i11m, $f7, $i17f, $f8, $i18m, $f9, $i21f, $f10, $i24m, $f11m, $i26f, $f12, $i29m], $sk); self::assertRelationships('pra-pra-dcéra prastrýka', 'pravnuk bratranca', [$i1m, $f4m, $i11m, $f7, $i17f, $f8, $i18m, $f9, $i21f, $f10, $i24m, $f11m, $i26f], $sk); // Compound relationships self::assertRelationships('exmanžel manželky', 'manžel exmanželky', [$i1m, $f1m, $i2f, $f2d, $i6m], $sk); + + /////////////////////////////////////////////////////////////////////// + // German + /////////////////////////////////////////////////////////////////////// + + $en = new LanguageGerman(); + + self::assertRelationships('Ehefrau', 'Ehemann', [$i1m, $f1m, $i2f], $en); + self::assertRelationships('Partner', 'Partner', [$i9u, $f6, $i15u], $en); + self::assertRelationships('Ex-Mann', 'Ex-Frau', [$i2f, $f2d, $i6m], $en); + self::assertRelationships('Verlobter', 'Verlobte', [$i10f, $f3e, $i3m], $en); + self::assertRelationships('Sohn', 'Vater', [$i1m, $f1m, $i3m], $en); + self::assertRelationships('Tochter', 'Mutter', [$i2f, $f1m, $i4f], $en); + self::assertRelationships('Kind', 'Vater', [$i1m, $f1m, $i5u], $en); + self::assertRelationships('Älterer Bruder', 'Jüngere Schwester', [$i4f, $f1m, $i3m], $en); + self::assertRelationships('Jüngeres Geschwister', 'Älterer Bruder', [$i3m, $f1m, $i5u], $en); + self::assertRelationships('Bruder', 'Schwester', [$i8f, $f2d, $i7ma], $en); + self::assertRelationships('Geschwister', 'Bruder', [$i7ma, $f2d, $i9u], $en); + self::assertRelationships('Adoptivmutter', 'Adoptivsohn', [$i7ma, $f2d, $i2f], $en); + self::assertRelationships('Stiefvater', 'Stiefkind', [$i9u, $f2d, $i2f, $f1m, $i1m], $en); + self::assertRelationships('Stieftochter', 'Stiefmutter', [$i2f, $f1m, $i2f, $f2d, $i8f], $en); + self::assertRelationships('Stiefschwester', 'Stiefgeschwister', [$i9u, $f2d, $i6m, $f13m, $i31m, $f14d, $i33f], $en); + self::assertRelationships('Halbbruder', 'Halbschwester', [$i8f, $f2d, $i2f, $f1m, $i3m], $en); + self::assertRelationships('Schwiegermutter', 'Schwiegertochter', [$i2f, $f1m, $i1m, $f4m, $i12f], $en); + self::assertRelationships('Großvater väterlicherseits', 'Enkel', [$i3m, $f1m, $i1m, $f4m, $i11m], $en); + self::assertRelationships('Großmutter väterlicherseits', 'Enkelin', [$i4f, $f1m, $i1m, $f4m, $i12f], $en); + self::assertRelationships('Großvater mütterlicherseits', 'Enkel', [$i3m, $f1m, $i2f, $f5m, $i13m], $en); + self::assertRelationships('Großmutter mütterlicherseits', 'Enkelin/Enkel', [$i5u, $f1m, $i2f, $f5m, $i14f], $en); + self::assertRelationships('Urgroßvater (väterlicherseits)', 'Urenkel', [$i3m, $f1m, $i1m, $f4m, $i11m, $f7, $i16m], $en); + // self::assertRelationships('paternal great-grandmother', 'great-granddaughter', [$i4f, $f1m, $i1m, $f4m, $i11m, $f7, $i17f], $en); + // self::assertRelationships('paternal great-great-grandfather', 'great-great-grandson', [$i3m, $f1m, $i1m, $f4m, $i11m, $f7, $i17f, $f8, $i18m], $en); + // self::assertRelationships('paternal great-great-grandmother', 'great-great-granddaughter', [$i4f, $f1m, $i1m, $f4m, $i11m, $f7, $i17f, $f8, $i19f], $en); + // self::assertRelationships('paternal great-great-great-grandfather', 'great-great-great-grandson', [$i3m, $f1m, $i1m, $f4m, $i11m, $f7, $i17f, $f8, $i18m, $f9, $i20m], $en); + // self::assertRelationships('paternal great-great-great-grandmother', 'great-great-great-granddaughter', [$i4f, $f1m, $i1m, $f4m, $i11m, $f7, $i17f, $f8, $i18m, $f9, $i21f], $en); + // self::assertRelationships('paternal great ×4 grandfather', 'great ×4 grandson', [$i3m, $f1m, $i1m, $f4m, $i11m, $f7, $i17f, $f8, $i18m, $f9, $i21f, $f10, $i22m], $en); + // self::assertRelationships('paternal great ×4 grandmother', 'great ×4 granddaughter', [$i4f, $f1m, $i1m, $f4m, $i11m, $f7, $i17f, $f8, $i18m, $f9, $i21f, $f10, $i23f], $en); + self::assertRelationships('Tante', 'Nichte', [$i38f, $f7, $i17f, $f8, $i37f], $en); + self::assertRelationships('Großonkel', 'Großneffe', [$i30m, $f8, $i18m, $f9, $i21f, $f10, $i24m], $en); + self::assertRelationships('Urgroßonkel', 'Urgroßneffe', [$i11m, $f7, $i17f, $f8, $i18m, $f9, $i21f, $f10, $i24m], $en); + self::assertRelationships('Neffe', 'Onkel', [$i24m, $f10, $i21f, $f9, $i18m], $en); + self::assertRelationships('Großnichte', 'Großonkel', [$i24m, $f10, $i21f, $f9, $i18m, $f8, $i17f], $en); + self::assertRelationships('Urgroßneffe', 'Urgroßonkel', [$i24m, $f10, $i21f, $f9, $i18m, $f8, $i17f, $f7, $i11m], $en); + // self::assertRelationships('first cousin', 'first cousin', [$i18m, $f9, $i21f, $f10, $i24m, $f11m, $i26f], $en); + // self::assertRelationships('second cousin', 'second cousin', [$i17f, $f8, $i18m, $f9, $i21f, $f10, $i24m, $f11m, $i26f, $f12, $i29m], $en); + // self::assertRelationships('first cousin once removed ascending', 'first cousin once removed descending', [$i17f, $f8, $i18m, $f9, $i21f, $f10, $i24m, $f11m, $i26f], $en); + // self::assertRelationships('third cousin', 'third cousin', [$i11m, $f7, $i17f, $f8, $i18m, $f9, $i21f, $f10, $i24m, $f11m, $i26f, $f12, $i29m, $f15, $i34f], $en); + // self::assertRelationships('second cousin once removed ascending', 'second cousin once removed descending', [$i11m, $f7, $i17f, $f8, $i18m, $f9, $i21f, $f10, $i24m, $f11m, $i26f, $f12, $i29m], $en); + // self::assertRelationships('first cousin twice removed ascending', 'first cousin twice removed descending', [$i11m, $f7, $i17f, $f8, $i18m, $f9, $i21f, $f10, $i24m, $f11m, $i26f], $en); + // self::assertRelationships('fourth cousin', 'fourth cousin', [$i1m, $f4m, $i11m, $f7, $i17f, $f8, $i18m, $f9, $i21f, $f10, $i24m, $f11m, $i26f, $f12, $i29m, $f15, $i34f, $f16, $i35m], $en); + // self::assertRelationships('third cousin once removed ascending', 'third cousin once removed descending', [$i1m, $f4m, $i11m, $f7, $i17f, $f8, $i18m, $f9, $i21f, $f10, $i24m, $f11m, $i26f, $f12, $i29m, $f15, $i34f], $en); + // self::assertRelationships('second cousin twice removed ascending', 'second cousin twice removed descending', [$i1m, $f4m, $i11m, $f7, $i17f, $f8, $i18m, $f9, $i21f, $f10, $i24m, $f11m, $i26f, $f12, $i29m], $en); } /**