xref: /webtrees/app/Services/RelationshipService.php (revision d35568b467207589ea9059739da0bf1f7e785a0d)
16fcafd02SGreg Roach<?php
26fcafd02SGreg Roach
36fcafd02SGreg Roach/**
46fcafd02SGreg Roach * webtrees: online genealogy
5d11be702SGreg Roach * Copyright (C) 2023 webtrees development team
66fcafd02SGreg Roach * This program is free software: you can redistribute it and/or modify
76fcafd02SGreg Roach * it under the terms of the GNU General Public License as published by
86fcafd02SGreg Roach * the Free Software Foundation, either version 3 of the License, or
96fcafd02SGreg Roach * (at your option) any later version.
106fcafd02SGreg Roach * This program is distributed in the hope that it will be useful,
116fcafd02SGreg Roach * but WITHOUT ANY WARRANTY; without even the implied warranty of
126fcafd02SGreg Roach * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
136fcafd02SGreg Roach * GNU General Public License for more details.
146fcafd02SGreg Roach * You should have received a copy of the GNU General Public License
156fcafd02SGreg Roach * along with this program. If not, see <https://www.gnu.org/licenses/>.
166fcafd02SGreg Roach */
176fcafd02SGreg Roach
186fcafd02SGreg Roachdeclare(strict_types=1);
196fcafd02SGreg Roach
206fcafd02SGreg Roachnamespace Fisharebest\Webtrees\Services;
216fcafd02SGreg Roach
226fcafd02SGreg Roachuse Fisharebest\Webtrees\Auth;
236fcafd02SGreg Roachuse Fisharebest\Webtrees\Fact;
246fcafd02SGreg Roachuse Fisharebest\Webtrees\Family;
256fcafd02SGreg Roachuse Fisharebest\Webtrees\I18N;
266fcafd02SGreg Roachuse Fisharebest\Webtrees\Individual;
276fcafd02SGreg Roachuse Fisharebest\Webtrees\Module\ModuleLanguageInterface;
28*d35568b4SGreg Roachuse Fisharebest\Webtrees\Registry;
296fcafd02SGreg Roachuse Fisharebest\Webtrees\Relationship;
306fcafd02SGreg Roach
316fcafd02SGreg Roachuse function abs;
326fcafd02SGreg Roachuse function array_key_exists;
336fcafd02SGreg Roachuse function array_merge;
346fcafd02SGreg Roachuse function array_reduce;
356fcafd02SGreg Roachuse function array_slice;
366fcafd02SGreg Roachuse function count;
376fcafd02SGreg Roachuse function implode;
386fcafd02SGreg Roachuse function intdiv;
396fcafd02SGreg Roachuse function min;
406fcafd02SGreg Roachuse function preg_match;
416fcafd02SGreg Roachuse function sprintf;
426fcafd02SGreg Roachuse function strlen;
436fcafd02SGreg Roachuse function substr;
446fcafd02SGreg Roach
456fcafd02SGreg Roach/**
466fcafd02SGreg Roach * Names for relationships.
476fcafd02SGreg Roach */
486fcafd02SGreg Roachclass RelationshipService
496fcafd02SGreg Roach{
506fcafd02SGreg Roach    private const COMPONENTS = [
516fcafd02SGreg Roach        'CHIL' => [
526fcafd02SGreg Roach            'CHIL' => Relationship::SIBLINGS,
536fcafd02SGreg Roach            'HUSB' => Relationship::PARENTS,
546fcafd02SGreg Roach            'WIFE' => Relationship::PARENTS,
556fcafd02SGreg Roach        ],
566fcafd02SGreg Roach        'HUSB' => [
576fcafd02SGreg Roach            'CHIL' => Relationship::CHILDREN,
586fcafd02SGreg Roach            'HUSB' => Relationship::SPOUSES,
596fcafd02SGreg Roach            'WIFE' => Relationship::SPOUSES,
606fcafd02SGreg Roach        ],
616fcafd02SGreg Roach        'WIFE' => [
626fcafd02SGreg Roach            'CHIL' => Relationship::CHILDREN,
636fcafd02SGreg Roach            'HUSB' => Relationship::SPOUSES,
646fcafd02SGreg Roach            'WIFE' => Relationship::SPOUSES,
656fcafd02SGreg Roach        ],
666fcafd02SGreg Roach    ];
676fcafd02SGreg Roach
686fcafd02SGreg Roach    /**
696fcafd02SGreg Roach     * For close family relationships, such as the families tab, associates, and the family navigator.
706fcafd02SGreg Roach     *
716fcafd02SGreg Roach     * @param Individual $individual1
726fcafd02SGreg Roach     * @param Individual $individual2
736fcafd02SGreg Roach     *
746fcafd02SGreg Roach     * @return string
756fcafd02SGreg Roach     */
766fcafd02SGreg Roach    public function getCloseRelationshipName(Individual $individual1, Individual $individual2): string
776fcafd02SGreg Roach    {
78*d35568b4SGreg Roach        $language = Registry::container()->get(ModuleService::class)
796fcafd02SGreg Roach            ->findByInterface(ModuleLanguageInterface::class, true)
806fcafd02SGreg Roach            ->first(fn (ModuleLanguageInterface $language): bool => $language->locale()->languageTag() === I18N::languageTag());
816fcafd02SGreg Roach
826fcafd02SGreg Roach        $path = $this->getCloseRelationship($individual1, $individual2);
836fcafd02SGreg Roach
846fcafd02SGreg Roach        // No relationship found?
856fcafd02SGreg Roach        if ($path === []) {
866fcafd02SGreg Roach            return '';
876fcafd02SGreg Roach        }
886fcafd02SGreg Roach
896fcafd02SGreg Roach        return $this->nameFromPath($path, $language);
906fcafd02SGreg Roach    }
916fcafd02SGreg Roach
926fcafd02SGreg Roach    /**
936fcafd02SGreg Roach     * Get relationship between two individuals in the gedcom.  This function
946fcafd02SGreg Roach     * takes account of pending changes, so we can display names of newly added
956fcafd02SGreg Roach     * relations.
966fcafd02SGreg Roach     *
976fcafd02SGreg Roach     * @param Individual $individual1
986fcafd02SGreg Roach     * @param Individual $individual2
996fcafd02SGreg Roach     * @param int        $maxlength
1006fcafd02SGreg Roach     *
1016fcafd02SGreg Roach     * @return array<Individual|Family> An array of nodes on the relationship path
1026fcafd02SGreg Roach     */
1036fcafd02SGreg Roach    private function getCloseRelationship(Individual $individual1, Individual $individual2, int $maxlength = 4): array
1046fcafd02SGreg Roach    {
1056fcafd02SGreg Roach        if ($individual1 === $individual2) {
1066fcafd02SGreg Roach            return [$individual1];
1076fcafd02SGreg Roach        }
1086fcafd02SGreg Roach
1096fcafd02SGreg Roach        // Only examine each individual once
1106fcafd02SGreg Roach        $visited = [
1116fcafd02SGreg Roach            $individual1->xref() => true,
1126fcafd02SGreg Roach        ];
1136fcafd02SGreg Roach
1146fcafd02SGreg Roach        // Build paths out from the first individual
1156fcafd02SGreg Roach        $paths = [
1166fcafd02SGreg Roach            [$individual1],
1176fcafd02SGreg Roach        ];
1186fcafd02SGreg Roach
1196fcafd02SGreg Roach        // Loop over paths of length 1, 2, 3, ...
1206fcafd02SGreg Roach        while ($maxlength >= 0) {
1216fcafd02SGreg Roach            $maxlength--;
1226fcafd02SGreg Roach
1236fcafd02SGreg Roach            foreach ($paths as $i => $path) {
1246fcafd02SGreg Roach                // Try each new relation from the end of the path
1256fcafd02SGreg Roach                $indi = $path[count($path) - 1];
1266fcafd02SGreg Roach
1276fcafd02SGreg Roach                // Parents and siblings
1286fcafd02SGreg Roach                foreach ($indi->childFamilies(Auth::PRIV_HIDE) as $family) {
1296fcafd02SGreg Roach                    $visited[$family->xref()] = true;
1306fcafd02SGreg Roach                    foreach ($family->spouses(Auth::PRIV_HIDE) as $spouse) {
1316fcafd02SGreg Roach                        if (!isset($visited[$spouse->xref()])) {
1326fcafd02SGreg Roach                            $new_path   = $path;
1336fcafd02SGreg Roach                            $new_path[] = $family;
1346fcafd02SGreg Roach                            $new_path[] = $spouse;
1356fcafd02SGreg Roach                            if ($spouse === $individual2) {
1366fcafd02SGreg Roach                                return $new_path;
1376fcafd02SGreg Roach                            }
1386fcafd02SGreg Roach
1396fcafd02SGreg Roach                            $paths[]                  = $new_path;
1406fcafd02SGreg Roach                            $visited[$spouse->xref()] = true;
1416fcafd02SGreg Roach                        }
1426fcafd02SGreg Roach                    }
1436fcafd02SGreg Roach                    foreach ($family->children(Auth::PRIV_HIDE) as $child) {
1446fcafd02SGreg Roach                        if (!isset($visited[$child->xref()])) {
1456fcafd02SGreg Roach                            $new_path   = $path;
1466fcafd02SGreg Roach                            $new_path[] = $family;
1476fcafd02SGreg Roach                            $new_path[] = $child;
1486fcafd02SGreg Roach                            if ($child === $individual2) {
1496fcafd02SGreg Roach                                return $new_path;
1506fcafd02SGreg Roach                            }
1516fcafd02SGreg Roach
1526fcafd02SGreg Roach                            $paths[]                 = $new_path;
1536fcafd02SGreg Roach                            $visited[$child->xref()] = true;
1546fcafd02SGreg Roach                        }
1556fcafd02SGreg Roach                    }
1566fcafd02SGreg Roach                }
1576fcafd02SGreg Roach
1586fcafd02SGreg Roach                // Spouses and children
1596fcafd02SGreg Roach                foreach ($indi->spouseFamilies(Auth::PRIV_HIDE) as $family) {
1606fcafd02SGreg Roach                    $visited[$family->xref()] = true;
1616fcafd02SGreg Roach                    foreach ($family->spouses(Auth::PRIV_HIDE) as $spouse) {
1626fcafd02SGreg Roach                        if (!isset($visited[$spouse->xref()])) {
1636fcafd02SGreg Roach                            $new_path   = $path;
1646fcafd02SGreg Roach                            $new_path[] = $family;
1656fcafd02SGreg Roach                            $new_path[] = $spouse;
1666fcafd02SGreg Roach                            if ($spouse === $individual2) {
1676fcafd02SGreg Roach                                return $new_path;
1686fcafd02SGreg Roach                            }
1696fcafd02SGreg Roach
1706fcafd02SGreg Roach                            $paths[]                  = $new_path;
1716fcafd02SGreg Roach                            $visited[$spouse->xref()] = true;
1726fcafd02SGreg Roach                        }
1736fcafd02SGreg Roach                    }
1746fcafd02SGreg Roach                    foreach ($family->children(Auth::PRIV_HIDE) as $child) {
1756fcafd02SGreg Roach                        if (!isset($visited[$child->xref()])) {
1766fcafd02SGreg Roach                            $new_path   = $path;
1776fcafd02SGreg Roach                            $new_path[] = $family;
1786fcafd02SGreg Roach                            $new_path[] = $child;
1796fcafd02SGreg Roach                            if ($child === $individual2) {
1806fcafd02SGreg Roach                                return $new_path;
1816fcafd02SGreg Roach                            }
1826fcafd02SGreg Roach
1836fcafd02SGreg Roach                            $paths[]                 = $new_path;
1846fcafd02SGreg Roach                            $visited[$child->xref()] = true;
1856fcafd02SGreg Roach                        }
1866fcafd02SGreg Roach                    }
1876fcafd02SGreg Roach                }
1886fcafd02SGreg Roach                unset($paths[$i]);
1896fcafd02SGreg Roach            }
1906fcafd02SGreg Roach        }
1916fcafd02SGreg Roach
1926fcafd02SGreg Roach        return [];
1936fcafd02SGreg Roach    }
1946fcafd02SGreg Roach
1956fcafd02SGreg Roach    /**
1966fcafd02SGreg Roach     * @param array<Individual|Family> $nodes
1976fcafd02SGreg Roach     * @param ModuleLanguageInterface  $language
1986fcafd02SGreg Roach     *
1996fcafd02SGreg Roach     * @return string
2006fcafd02SGreg Roach     */
2016fcafd02SGreg Roach    public function nameFromPath(array $nodes, ModuleLanguageInterface $language): string
2026fcafd02SGreg Roach    {
2036fcafd02SGreg Roach        // The relationship matching algorithm could be used for this, but it is more efficient to check it here.
2046fcafd02SGreg Roach        if (count($nodes) === 1) {
2056fcafd02SGreg Roach            return $this->reflexivePronoun($nodes[0]);
2066fcafd02SGreg Roach        }
2076fcafd02SGreg Roach
2086fcafd02SGreg Roach        // The relationship definitions for the language.
2096fcafd02SGreg Roach        $relationships = $language->relationships();
2106fcafd02SGreg Roach
2116fcafd02SGreg Roach        // We don't strictly need this, as all the information is contained in the nodes.
2126fcafd02SGreg Roach        // But it gives us simpler code and better performance.
2136fcafd02SGreg Roach        // It is also needed for the legacy algorithm.
2146fcafd02SGreg Roach        $pattern = $this->components($nodes);
2156fcafd02SGreg Roach
2166fcafd02SGreg Roach        // No definitions for this language?  Use the legacy algorithm.
2176fcafd02SGreg Roach        if ($relationships === []) {
2186fcafd02SGreg Roach            return $this->legacyNameAlgorithm(implode('', $pattern), $nodes[0], $nodes[count($nodes) - 1]);
2196fcafd02SGreg Roach        }
2206fcafd02SGreg Roach
2216fcafd02SGreg Roach        // Match the relationship, using a longest-substring algorithm.
2226fcafd02SGreg Roach        $relationships = $this->matchRelationships($nodes, $pattern, $relationships);
2236fcafd02SGreg Roach
2246fcafd02SGreg Roach        // Reduce the genitive-nominative chain to a single string.
2256fcafd02SGreg Roach        return array_reduce($relationships, static function (array $carry, array $item): array {
2266fcafd02SGreg Roach            return [sprintf($carry[1], $item[0]), sprintf($carry[1], $item[1])];
227b6adeac8SJonathan Jaubart        }, [0 => '', 1 => '%s'])[0];
2286fcafd02SGreg Roach    }
2296fcafd02SGreg Roach
2306fcafd02SGreg Roach    /**
2316fcafd02SGreg Roach     * Generate a reflexive pronoun for an individual
2326fcafd02SGreg Roach     *
2336fcafd02SGreg Roach     * @param Individual $individual
2346fcafd02SGreg Roach     *
2356fcafd02SGreg Roach     * @return string
2366fcafd02SGreg Roach     */
2376fcafd02SGreg Roach    protected function reflexivePronoun(Individual $individual): string
2386fcafd02SGreg Roach    {
2396fcafd02SGreg Roach        switch ($individual->sex()) {
2406fcafd02SGreg Roach            case 'M':
2416fcafd02SGreg Roach                /* I18N: reflexive pronoun */
2426fcafd02SGreg Roach                return I18N::translate('himself');
2436fcafd02SGreg Roach            case 'F':
2446fcafd02SGreg Roach                /* I18N: reflexive pronoun */
2456fcafd02SGreg Roach                return I18N::translate('herself');
2466fcafd02SGreg Roach            default:
2476fcafd02SGreg Roach                /* I18N: reflexive pronoun - gender neutral version of himself/herself */
2486fcafd02SGreg Roach                return I18N::translate('themself');
2496fcafd02SGreg Roach        }
2506fcafd02SGreg Roach    }
2516fcafd02SGreg Roach
2526fcafd02SGreg Roach    /**
2536fcafd02SGreg Roach     * Convert a relationship path into its component pieces; brother, wife, mother, daughter, etc.
2546fcafd02SGreg Roach     *
255e5766395SGreg Roach     * @param array<Individual|Family> $nodes Alternating list of Individual and Family objects
2566fcafd02SGreg Roach     *
2576fcafd02SGreg Roach     * @return array<string>
2586fcafd02SGreg Roach     */
2596fcafd02SGreg Roach    private function components(array $nodes): array
2606fcafd02SGreg Roach    {
2616fcafd02SGreg Roach        $pattern = [];
2626fcafd02SGreg Roach
2636fcafd02SGreg Roach        $count = count($nodes);
2646fcafd02SGreg Roach
2656fcafd02SGreg Roach        for ($i = 1; $i < $count; $i += 2) {
2666fcafd02SGreg Roach            $prev   = $nodes[$i - 1];
2676fcafd02SGreg Roach            $family = $nodes[$i];
2686fcafd02SGreg Roach            $next   = $nodes[$i + 1];
2696fcafd02SGreg Roach
2706fcafd02SGreg Roach            preg_match('/\n1 (HUSB|WIFE|CHIL) @' . $prev->xref() . '@/', $family->gedcom(), $match);
2716fcafd02SGreg Roach            $rel1 = $match[1] ?? 'xxx';
2726fcafd02SGreg Roach
2736fcafd02SGreg Roach            preg_match('/\n1 (HUSB|WIFE|CHIL) @' . $next->xref() . '@/', $family->gedcom(), $match);
2746fcafd02SGreg Roach            $rel2 = $match[1] ?? 'xxx';
2756fcafd02SGreg Roach
2766fcafd02SGreg Roach            $pattern[] = self::COMPONENTS[$rel1][$rel2][$next->sex()] ?? 'xxx';
2776fcafd02SGreg Roach        }
2786fcafd02SGreg Roach
2796fcafd02SGreg Roach        return $pattern;
2806fcafd02SGreg Roach    }
2816fcafd02SGreg Roach
2826fcafd02SGreg Roach    /**
2836fcafd02SGreg Roach     * @param array<Individual|Family> $nodes
2846fcafd02SGreg Roach     * @param array<string>            $pattern
2856fcafd02SGreg Roach     * @param array<Relationship>      $relationships
2866fcafd02SGreg Roach     *
2876fcafd02SGreg Roach     * @return array<Relationship>
2886fcafd02SGreg Roach     */
2896fcafd02SGreg Roach    protected function matchRelationships(array $nodes, array $pattern, array $relationships): array
2906fcafd02SGreg Roach    {
2916fcafd02SGreg Roach        $count = count($pattern);
2926fcafd02SGreg Roach
2936fcafd02SGreg Roach        // Look for the longest matchable series of components
2946fcafd02SGreg Roach        for ($length = $count; $length > 0; $length--) {
2956fcafd02SGreg Roach            for ($start = $count - $length; $start >= 0; $start--) {
2966fcafd02SGreg Roach                foreach ($relationships as $relationship) {
2976fcafd02SGreg Roach                    $path_slice    = array_slice($nodes, $start * 2, $length * 2 + 1);
2986fcafd02SGreg Roach                    $pattern_slice = array_slice($pattern, $start, $length);
2996fcafd02SGreg Roach                    $result        = $relationship->match($path_slice, $pattern_slice);
3006fcafd02SGreg Roach
3016fcafd02SGreg Roach                    if ($result !== null) {
3026fcafd02SGreg Roach                        $nodes_before   = array_slice($nodes, 0, $start * 2 + 1);
3036fcafd02SGreg Roach                        $pattern_before = array_slice($pattern, 0, $start);
3046fcafd02SGreg Roach                        $result_before  = $this->matchRelationships($nodes_before, $pattern_before, $relationships);
3056fcafd02SGreg Roach
3066fcafd02SGreg Roach                        $nodes_after   = array_slice($nodes, ($start + $length) * 2);
3076fcafd02SGreg Roach                        $pattern_after = array_slice($pattern, $start + $length);
3086fcafd02SGreg Roach                        $result_after  = $this->matchRelationships($nodes_after, $pattern_after, $relationships);
3096fcafd02SGreg Roach
3106fcafd02SGreg Roach                        return array_merge($result_before, [$result], $result_after);
3116fcafd02SGreg Roach                    }
3126fcafd02SGreg Roach                }
3136fcafd02SGreg Roach            }
3146fcafd02SGreg Roach        }
3156fcafd02SGreg Roach
3166fcafd02SGreg Roach        return [];
3176fcafd02SGreg Roach    }
3186fcafd02SGreg Roach
3196fcafd02SGreg Roach    /**
32073d58381SGreg Roach     * @param string          $path
32173d58381SGreg Roach     * @param Individual|null $person1
32273d58381SGreg Roach     * @param Individual|null $person2
3236fcafd02SGreg Roach     *
3246fcafd02SGreg Roach     * @return string
3256fcafd02SGreg Roach     *
3266fcafd02SGreg Roach     * @deprecated This code was originally Functions::getRelationshipNameFromPath
3276fcafd02SGreg Roach     */
3286fcafd02SGreg Roach    public function legacyNameAlgorithm(string $path, Individual $person1 = null, Individual $person2 = null): string
3296fcafd02SGreg Roach    {
3306fcafd02SGreg Roach        // The path does not include the starting person. In some languages, the
3316fcafd02SGreg Roach        // translation for a man’s (relative) is different from a woman’s (relative),
3326fcafd02SGreg Roach        // due to inflection.
3336fcafd02SGreg Roach        $sex1 = $person1 ? $person1->sex() : 'U';
3346fcafd02SGreg Roach
3356fcafd02SGreg Roach        // The sex of the last person in the relationship determines the name in
3366fcafd02SGreg Roach        // many cases. e.g. great-aunt / great-uncle
337ef475b14SGreg Roach        if (preg_match('/(fat|hus|son|bro)$/', $path) === 1) {
3386fcafd02SGreg Roach            $sex2 = 'M';
339ef475b14SGreg Roach        } elseif (preg_match('/(mot|wif|dau|sis)$/', $path) === 1) {
3406fcafd02SGreg Roach            $sex2 = 'F';
3416fcafd02SGreg Roach        } else {
3426fcafd02SGreg Roach            $sex2 = 'U';
3436fcafd02SGreg Roach        }
3446fcafd02SGreg Roach
3456fcafd02SGreg Roach        switch ($path) {
3466fcafd02SGreg Roach            case '':
3476fcafd02SGreg Roach                return I18N::translate('self');
3486fcafd02SGreg Roach                //  Level One relationships
3496fcafd02SGreg Roach            case 'mot':
3506fcafd02SGreg Roach                return I18N::translate('mother');
3516fcafd02SGreg Roach            case 'fat':
3526fcafd02SGreg Roach                return I18N::translate('father');
3536fcafd02SGreg Roach            case 'par':
3546fcafd02SGreg Roach                return I18N::translate('parent');
3556fcafd02SGreg Roach            case 'hus':
3566fcafd02SGreg Roach                if ($person1 instanceof Individual && $person2 instanceof Individual) {
3576fcafd02SGreg Roach                    // We had the linking family earlier, but lost it.  Find it again.
3586fcafd02SGreg Roach                    foreach ($person1->spouseFamilies(Auth::PRIV_HIDE) as $family) {
3596fcafd02SGreg Roach                        if ($person2 === $family->spouse($person1)) {
3606fcafd02SGreg Roach                            $event = $family->facts(['ANUL', 'DIV', 'ENGA', 'MARR'], true, Auth::PRIV_HIDE, true)->last();
3616fcafd02SGreg Roach
3626fcafd02SGreg Roach                            if ($event instanceof Fact) {
3636fcafd02SGreg Roach                                switch ($event->tag()) {
3646fcafd02SGreg Roach                                    case 'FAM:ANUL':
3656fcafd02SGreg Roach                                    case 'FAM:DIV':
3666fcafd02SGreg Roach                                        return I18N::translate('ex-husband');
3676fcafd02SGreg Roach                                    case 'FAM:MARR':
3686fcafd02SGreg Roach                                        return I18N::translate('husband');
3696fcafd02SGreg Roach                                    case 'FAM:ENGA':
3706fcafd02SGreg Roach                                        return I18N::translate('fiancé');
3716fcafd02SGreg Roach                                }
3726fcafd02SGreg Roach                            }
3736fcafd02SGreg Roach                        }
3746fcafd02SGreg Roach                    }
3756fcafd02SGreg Roach                }
3766fcafd02SGreg Roach
3776fcafd02SGreg Roach                return I18N::translateContext('MALE', 'partner');
3786fcafd02SGreg Roach
3796fcafd02SGreg Roach            case 'wif':
3806fcafd02SGreg Roach                if ($person1 instanceof Individual && $person2 instanceof Individual) {
3816fcafd02SGreg Roach                    // We had the linking family earlier, but lost it.  Find it again.
3826fcafd02SGreg Roach                    foreach ($person1->spouseFamilies(Auth::PRIV_HIDE) as $family) {
3836fcafd02SGreg Roach                        if ($person2 === $family->spouse($person1)) {
3846fcafd02SGreg Roach                            $event = $family->facts(['ANUL', 'DIV', 'ENGA', 'MARR'], true, Auth::PRIV_HIDE, true)->last();
3856fcafd02SGreg Roach
3866fcafd02SGreg Roach                            if ($event instanceof Fact) {
3876fcafd02SGreg Roach                                switch ($event->tag()) {
3886fcafd02SGreg Roach                                    case 'FAM:ANUL':
3896fcafd02SGreg Roach                                    case 'FAM:DIV':
3906fcafd02SGreg Roach                                        return I18N::translate('ex-wife');
3916fcafd02SGreg Roach                                    case 'FAM:MARR':
3926fcafd02SGreg Roach                                        return I18N::translate('wife');
3936fcafd02SGreg Roach                                    case 'FAM:ENGA':
3946fcafd02SGreg Roach                                        return I18N::translate('fiancée');
3956fcafd02SGreg Roach                                }
3966fcafd02SGreg Roach                            }
3976fcafd02SGreg Roach                        }
3986fcafd02SGreg Roach                    }
3996fcafd02SGreg Roach                }
4006fcafd02SGreg Roach
4016fcafd02SGreg Roach                return I18N::translateContext('FEMALE', 'partner');
4026fcafd02SGreg Roach            case 'spo':
4036fcafd02SGreg Roach                if ($person1 instanceof Individual && $person2 instanceof Individual) {
4046fcafd02SGreg Roach                    // We had the linking family earlier, but lost it.  Find it again.
4056fcafd02SGreg Roach                    foreach ($person1->spouseFamilies(Auth::PRIV_HIDE) as $family) {
4066fcafd02SGreg Roach                        if ($person2 === $family->spouse($person1)) {
4076fcafd02SGreg Roach                            $event = $family->facts(['ANUL', 'DIV', 'ENGA', 'MARR'], true, Auth::PRIV_HIDE, true)->last();
4086fcafd02SGreg Roach
4096fcafd02SGreg Roach                            if ($event instanceof Fact) {
4106fcafd02SGreg Roach                                switch ($event->tag()) {
4116fcafd02SGreg Roach                                    case 'FAM:ANUL':
4126fcafd02SGreg Roach                                    case 'FAM:DIV':
4136fcafd02SGreg Roach                                        return I18N::translate('ex-spouse');
4146fcafd02SGreg Roach                                    case 'FAM:MARR':
4156fcafd02SGreg Roach                                        return I18N::translate('spouse');
4166fcafd02SGreg Roach                                    case 'FAM:ENGA':
4176fcafd02SGreg Roach                                        return I18N::translate('fiancé(e)');
4186fcafd02SGreg Roach                                }
4196fcafd02SGreg Roach                            }
4206fcafd02SGreg Roach                        }
4216fcafd02SGreg Roach                    }
4226fcafd02SGreg Roach                }
4236fcafd02SGreg Roach
4246fcafd02SGreg Roach                return I18N::translate('partner');
4256fcafd02SGreg Roach
4266fcafd02SGreg Roach            case 'son':
4276fcafd02SGreg Roach                return I18N::translate('son');
4286fcafd02SGreg Roach            case 'dau':
4296fcafd02SGreg Roach                return I18N::translate('daughter');
4306fcafd02SGreg Roach            case 'chi':
4316fcafd02SGreg Roach                return I18N::translate('child');
4326fcafd02SGreg Roach            case 'bro':
4336fcafd02SGreg Roach                if ($person1 && $person2) {
4346fcafd02SGreg Roach                    $dob1 = $person1->getBirthDate();
4356fcafd02SGreg Roach                    $dob2 = $person2->getBirthDate();
4366fcafd02SGreg Roach                    if ($dob1->isOK() && $dob2->isOK()) {
4376fcafd02SGreg Roach                        if (abs($dob1->julianDay() - $dob2->julianDay()) < 2 && $dob1->minimumDate()->day > 0 && $dob2->minimumDate()->day > 0) {
4386fcafd02SGreg Roach                            // Exclude BEF, AFT, etc.
4396fcafd02SGreg Roach                            return I18N::translate('twin brother');
4406fcafd02SGreg Roach                        }
4416fcafd02SGreg Roach
4426fcafd02SGreg Roach                        if ($dob1->maximumJulianDay() < $dob2->minimumJulianDay()) {
4436fcafd02SGreg Roach                            return I18N::translate('younger brother');
4446fcafd02SGreg Roach                        }
4456fcafd02SGreg Roach
4466fcafd02SGreg Roach                        if ($dob1->minimumJulianDay() > $dob2->maximumJulianDay()) {
4476fcafd02SGreg Roach                            return I18N::translate('elder brother');
4486fcafd02SGreg Roach                        }
4496fcafd02SGreg Roach                    }
4506fcafd02SGreg Roach                }
4516fcafd02SGreg Roach
4526fcafd02SGreg Roach                return I18N::translate('brother');
4536fcafd02SGreg Roach            case 'sis':
4546fcafd02SGreg Roach                if ($person1 && $person2) {
4556fcafd02SGreg Roach                    $dob1 = $person1->getBirthDate();
4566fcafd02SGreg Roach                    $dob2 = $person2->getBirthDate();
4576fcafd02SGreg Roach                    if ($dob1->isOK() && $dob2->isOK()) {
4586fcafd02SGreg Roach                        if (abs($dob1->julianDay() - $dob2->julianDay()) < 2 && $dob1->minimumDate()->day > 0 && $dob2->minimumDate()->day > 0) {
4596fcafd02SGreg Roach                            // Exclude BEF, AFT, etc.
4606fcafd02SGreg Roach                            return I18N::translate('twin sister');
4616fcafd02SGreg Roach                        }
4626fcafd02SGreg Roach
4636fcafd02SGreg Roach                        if ($dob1->maximumJulianDay() < $dob2->minimumJulianDay()) {
4646fcafd02SGreg Roach                            return I18N::translate('younger sister');
4656fcafd02SGreg Roach                        }
4666fcafd02SGreg Roach
4676fcafd02SGreg Roach                        if ($dob1->minimumJulianDay() > $dob2->maximumJulianDay()) {
4686fcafd02SGreg Roach                            return I18N::translate('elder sister');
4696fcafd02SGreg Roach                        }
4706fcafd02SGreg Roach                    }
4716fcafd02SGreg Roach                }
4726fcafd02SGreg Roach
4736fcafd02SGreg Roach                return I18N::translate('sister');
4746fcafd02SGreg Roach            case 'sib':
4756fcafd02SGreg Roach                if ($person1 && $person2) {
4766fcafd02SGreg Roach                    $dob1 = $person1->getBirthDate();
4776fcafd02SGreg Roach                    $dob2 = $person2->getBirthDate();
4786fcafd02SGreg Roach                    if ($dob1->isOK() && $dob2->isOK()) {
4796fcafd02SGreg Roach                        if (abs($dob1->julianDay() - $dob2->julianDay()) < 2 && $dob1->minimumDate()->day > 0 && $dob2->minimumDate()->day > 0) {
4806fcafd02SGreg Roach                            // Exclude BEF, AFT, etc.
4816fcafd02SGreg Roach                            return I18N::translate('twin sibling');
4826fcafd02SGreg Roach                        }
4836fcafd02SGreg Roach
4846fcafd02SGreg Roach                        if ($dob1->maximumJulianDay() < $dob2->minimumJulianDay()) {
4856fcafd02SGreg Roach                            return I18N::translate('younger sibling');
4866fcafd02SGreg Roach                        }
4876fcafd02SGreg Roach
4886fcafd02SGreg Roach                        if ($dob1->minimumJulianDay() > $dob2->maximumJulianDay()) {
4896fcafd02SGreg Roach                            return I18N::translate('elder sibling');
4906fcafd02SGreg Roach                        }
4916fcafd02SGreg Roach                    }
4926fcafd02SGreg Roach                }
4936fcafd02SGreg Roach
4946fcafd02SGreg Roach                return I18N::translate('sibling');
4956fcafd02SGreg Roach
4966fcafd02SGreg Roach                // Level Two relationships
4976fcafd02SGreg Roach            case 'brochi':
4986fcafd02SGreg Roach                return I18N::translateContext('brother’s child', 'nephew/niece');
4996fcafd02SGreg Roach            case 'brodau':
5006fcafd02SGreg Roach                return I18N::translateContext('brother’s daughter', 'niece');
5016fcafd02SGreg Roach            case 'broson':
5026fcafd02SGreg Roach                return I18N::translateContext('brother’s son', 'nephew');
5036fcafd02SGreg Roach            case 'browif':
5046fcafd02SGreg Roach                return I18N::translateContext('brother’s wife', 'sister-in-law');
5056fcafd02SGreg Roach            case 'chichi':
5066fcafd02SGreg Roach                return I18N::translateContext('child’s child', 'grandchild');
5076fcafd02SGreg Roach            case 'chidau':
5086fcafd02SGreg Roach                return I18N::translateContext('child’s daughter', 'granddaughter');
5096fcafd02SGreg Roach            case 'chihus':
5106fcafd02SGreg Roach                return I18N::translateContext('child’s husband', 'son-in-law');
5116fcafd02SGreg Roach            case 'chison':
5126fcafd02SGreg Roach                return I18N::translateContext('child’s son', 'grandson');
5136fcafd02SGreg Roach            case 'chispo':
5146fcafd02SGreg Roach                return I18N::translateContext('child’s spouse', 'son/daughter-in-law');
5156fcafd02SGreg Roach            case 'chiwif':
5166fcafd02SGreg Roach                return I18N::translateContext('child’s wife', 'daughter-in-law');
5176fcafd02SGreg Roach            case 'dauchi':
5186fcafd02SGreg Roach                return I18N::translateContext('daughter’s child', 'grandchild');
5196fcafd02SGreg Roach            case 'daudau':
5206fcafd02SGreg Roach                return I18N::translateContext('daughter’s daughter', 'granddaughter');
5216fcafd02SGreg Roach            case 'dauhus':
5226fcafd02SGreg Roach                return I18N::translateContext('daughter’s husband', 'son-in-law');
5236fcafd02SGreg Roach            case 'dauson':
5246fcafd02SGreg Roach                return I18N::translateContext('daughter’s son', 'grandson');
5256fcafd02SGreg Roach            case 'fatbro':
5266fcafd02SGreg Roach                return I18N::translateContext('father’s brother', 'uncle');
5276fcafd02SGreg Roach            case 'fatchi':
5286fcafd02SGreg Roach                return I18N::translateContext('father’s child', 'half-sibling');
5296fcafd02SGreg Roach            case 'fatdau':
5306fcafd02SGreg Roach                return I18N::translateContext('father’s daughter', 'half-sister');
5316fcafd02SGreg Roach            case 'fatfat':
5326fcafd02SGreg Roach                return I18N::translateContext('father’s father', 'paternal grandfather');
5336fcafd02SGreg Roach            case 'fatmot':
5346fcafd02SGreg Roach                return I18N::translateContext('father’s mother', 'paternal grandmother');
5356fcafd02SGreg Roach            case 'fatpar':
5366fcafd02SGreg Roach                return I18N::translateContext('father’s parent', 'paternal grandparent');
5376fcafd02SGreg Roach            case 'fatsib':
5386fcafd02SGreg Roach                return I18N::translateContext('father’s sibling', 'aunt/uncle');
5396fcafd02SGreg Roach            case 'fatsis':
5406fcafd02SGreg Roach                return I18N::translateContext('father’s sister', 'aunt');
5416fcafd02SGreg Roach            case 'fatson':
5426fcafd02SGreg Roach                return I18N::translateContext('father’s son', 'half-brother');
5436fcafd02SGreg Roach            case 'fatwif':
5446fcafd02SGreg Roach                return I18N::translateContext('father’s wife', 'step-mother');
5456fcafd02SGreg Roach            case 'husbro':
5466fcafd02SGreg Roach                return I18N::translateContext('husband’s brother', 'brother-in-law');
5476fcafd02SGreg Roach            case 'huschi':
5486fcafd02SGreg Roach                return I18N::translateContext('husband’s child', 'step-child');
5496fcafd02SGreg Roach            case 'husdau':
5506fcafd02SGreg Roach                return I18N::translateContext('husband’s daughter', 'step-daughter');
5516fcafd02SGreg Roach            case 'husfat':
5526fcafd02SGreg Roach                return I18N::translateContext('husband’s father', 'father-in-law');
5536fcafd02SGreg Roach            case 'husmot':
5546fcafd02SGreg Roach                return I18N::translateContext('husband’s mother', 'mother-in-law');
5556fcafd02SGreg Roach            case 'hussib':
5566fcafd02SGreg Roach                return I18N::translateContext('husband’s sibling', 'brother/sister-in-law');
5576fcafd02SGreg Roach            case 'hussis':
5586fcafd02SGreg Roach                return I18N::translateContext('husband’s sister', 'sister-in-law');
5596fcafd02SGreg Roach            case 'husson':
5606fcafd02SGreg Roach                return I18N::translateContext('husband’s son', 'step-son');
5616fcafd02SGreg Roach            case 'motbro':
5626fcafd02SGreg Roach                return I18N::translateContext('mother’s brother', 'uncle');
5636fcafd02SGreg Roach            case 'motchi':
5646fcafd02SGreg Roach                return I18N::translateContext('mother’s child', 'half-sibling');
5656fcafd02SGreg Roach            case 'motdau':
5666fcafd02SGreg Roach                return I18N::translateContext('mother’s daughter', 'half-sister');
5676fcafd02SGreg Roach            case 'motfat':
5686fcafd02SGreg Roach                return I18N::translateContext('mother’s father', 'maternal grandfather');
5696fcafd02SGreg Roach            case 'mothus':
5706fcafd02SGreg Roach                return I18N::translateContext('mother’s husband', 'step-father');
5716fcafd02SGreg Roach            case 'motmot':
5726fcafd02SGreg Roach                return I18N::translateContext('mother’s mother', 'maternal grandmother');
5736fcafd02SGreg Roach            case 'motpar':
5746fcafd02SGreg Roach                return I18N::translateContext('mother’s parent', 'maternal grandparent');
5756fcafd02SGreg Roach            case 'motsib':
5766fcafd02SGreg Roach                return I18N::translateContext('mother’s sibling', 'aunt/uncle');
5776fcafd02SGreg Roach            case 'motsis':
5786fcafd02SGreg Roach                return I18N::translateContext('mother’s sister', 'aunt');
5796fcafd02SGreg Roach            case 'motson':
5806fcafd02SGreg Roach                return I18N::translateContext('mother’s son', 'half-brother');
5816fcafd02SGreg Roach            case 'parbro':
5826fcafd02SGreg Roach                return I18N::translateContext('parent’s brother', 'uncle');
5836fcafd02SGreg Roach            case 'parchi':
5846fcafd02SGreg Roach                return I18N::translateContext('parent’s child', 'half-sibling');
5856fcafd02SGreg Roach            case 'pardau':
5866fcafd02SGreg Roach                return I18N::translateContext('parent’s daughter', 'half-sister');
5876fcafd02SGreg Roach            case 'parfat':
5886fcafd02SGreg Roach                return I18N::translateContext('parent’s father', 'grandfather');
5896fcafd02SGreg Roach            case 'parmot':
5906fcafd02SGreg Roach                return I18N::translateContext('parent’s mother', 'grandmother');
5916fcafd02SGreg Roach            case 'parpar':
5926fcafd02SGreg Roach                return I18N::translateContext('parent’s parent', 'grandparent');
5936fcafd02SGreg Roach            case 'parsib':
5946fcafd02SGreg Roach                return I18N::translateContext('parent’s sibling', 'aunt/uncle');
5956fcafd02SGreg Roach            case 'parsis':
5966fcafd02SGreg Roach                return I18N::translateContext('parent’s sister', 'aunt');
5976fcafd02SGreg Roach            case 'parson':
5986fcafd02SGreg Roach                return I18N::translateContext('parent’s son', 'half-brother');
5996fcafd02SGreg Roach            case 'parspo':
6006fcafd02SGreg Roach                return I18N::translateContext('parent’s spouse', 'step-parent');
6016fcafd02SGreg Roach            case 'sibchi':
6026fcafd02SGreg Roach                return I18N::translateContext('sibling’s child', 'nephew/niece');
6036fcafd02SGreg Roach            case 'sibdau':
6046fcafd02SGreg Roach                return I18N::translateContext('sibling’s daughter', 'niece');
6056fcafd02SGreg Roach            case 'sibson':
6066fcafd02SGreg Roach                return I18N::translateContext('sibling’s son', 'nephew');
6076fcafd02SGreg Roach            case 'sibspo':
6086fcafd02SGreg Roach                return I18N::translateContext('sibling’s spouse', 'brother/sister-in-law');
6096fcafd02SGreg Roach            case 'sischi':
6106fcafd02SGreg Roach                return I18N::translateContext('sister’s child', 'nephew/niece');
6116fcafd02SGreg Roach            case 'sisdau':
6126fcafd02SGreg Roach                return I18N::translateContext('sister’s daughter', 'niece');
6136fcafd02SGreg Roach            case 'sishus':
6146fcafd02SGreg Roach                return I18N::translateContext('sister’s husband', 'brother-in-law');
6156fcafd02SGreg Roach            case 'sisson':
6166fcafd02SGreg Roach                return I18N::translateContext('sister’s son', 'nephew');
6176fcafd02SGreg Roach            case 'sonchi':
6186fcafd02SGreg Roach                return I18N::translateContext('son’s child', 'grandchild');
6196fcafd02SGreg Roach            case 'sondau':
6206fcafd02SGreg Roach                return I18N::translateContext('son’s daughter', 'granddaughter');
6216fcafd02SGreg Roach            case 'sonson':
6226fcafd02SGreg Roach                return I18N::translateContext('son’s son', 'grandson');
6236fcafd02SGreg Roach            case 'sonwif':
6246fcafd02SGreg Roach                return I18N::translateContext('son’s wife', 'daughter-in-law');
6256fcafd02SGreg Roach            case 'spobro':
6266fcafd02SGreg Roach                return I18N::translateContext('spouse’s brother', 'brother-in-law');
6276fcafd02SGreg Roach            case 'spochi':
6286fcafd02SGreg Roach                return I18N::translateContext('spouse’s child', 'step-child');
6296fcafd02SGreg Roach            case 'spodau':
6306fcafd02SGreg Roach                return I18N::translateContext('spouse’s daughter', 'step-daughter');
6316fcafd02SGreg Roach            case 'spofat':
6326fcafd02SGreg Roach                return I18N::translateContext('spouse’s father', 'father-in-law');
6336fcafd02SGreg Roach            case 'spomot':
6346fcafd02SGreg Roach                return I18N::translateContext('spouse’s mother', 'mother-in-law');
6356fcafd02SGreg Roach            case 'sposis':
6366fcafd02SGreg Roach                return I18N::translateContext('spouse’s sister', 'sister-in-law');
6376fcafd02SGreg Roach            case 'sposon':
6386fcafd02SGreg Roach                return I18N::translateContext('spouse’s son', 'step-son');
6396fcafd02SGreg Roach            case 'spopar':
6406fcafd02SGreg Roach                return I18N::translateContext('spouse’s parent', 'mother/father-in-law');
6416fcafd02SGreg Roach            case 'sposib':
6426fcafd02SGreg Roach                return I18N::translateContext('spouse’s sibling', 'brother/sister-in-law');
6436fcafd02SGreg Roach            case 'wifbro':
6446fcafd02SGreg Roach                return I18N::translateContext('wife’s brother', 'brother-in-law');
6456fcafd02SGreg Roach            case 'wifchi':
6466fcafd02SGreg Roach                return I18N::translateContext('wife’s child', 'step-child');
6476fcafd02SGreg Roach            case 'wifdau':
6486fcafd02SGreg Roach                return I18N::translateContext('wife’s daughter', 'step-daughter');
6496fcafd02SGreg Roach            case 'wiffat':
6506fcafd02SGreg Roach                return I18N::translateContext('wife’s father', 'father-in-law');
6516fcafd02SGreg Roach            case 'wifmot':
6526fcafd02SGreg Roach                return I18N::translateContext('wife’s mother', 'mother-in-law');
6536fcafd02SGreg Roach            case 'wifsib':
6546fcafd02SGreg Roach                return I18N::translateContext('wife’s sibling', 'brother/sister-in-law');
6556fcafd02SGreg Roach            case 'wifsis':
6566fcafd02SGreg Roach                return I18N::translateContext('wife’s sister', 'sister-in-law');
6576fcafd02SGreg Roach            case 'wifson':
6586fcafd02SGreg Roach                return I18N::translateContext('wife’s son', 'step-son');
6596fcafd02SGreg Roach
6606fcafd02SGreg Roach                // Level Three relationships
6616fcafd02SGreg Roach            case 'brochichi':
6626fcafd02SGreg Roach                if ($sex1 === 'M') {
6636fcafd02SGreg Roach                    return I18N::translateContext('(a man’s) brother’s child’s child', 'great-nephew/niece');
6646fcafd02SGreg Roach                }
6656fcafd02SGreg Roach
6666fcafd02SGreg Roach                return I18N::translateContext('(a woman’s) brother’s child’s child', 'great-nephew/niece');
6676fcafd02SGreg Roach            case 'brochidau':
6686fcafd02SGreg Roach                if ($sex1 === 'M') {
6696fcafd02SGreg Roach                    return I18N::translateContext('(a man’s) brother’s child’s daughter', 'great-niece');
6706fcafd02SGreg Roach                }
6716fcafd02SGreg Roach
6726fcafd02SGreg Roach                return I18N::translateContext('(a woman’s) brother’s child’s daughter', 'great-niece');
6736fcafd02SGreg Roach            case 'brochison':
6746fcafd02SGreg Roach                if ($sex1 === 'M') {
6756fcafd02SGreg Roach                    return I18N::translateContext('(a man’s) brother’s child’s son', 'great-nephew');
6766fcafd02SGreg Roach                }
6776fcafd02SGreg Roach
6786fcafd02SGreg Roach                return I18N::translateContext('(a woman’s) brother’s child’s son', 'great-nephew');
6796fcafd02SGreg Roach            case 'brodauchi':
6806fcafd02SGreg Roach                if ($sex1 === 'M') {
6816fcafd02SGreg Roach                    return I18N::translateContext('(a man’s) brother’s daughter’s child', 'great-nephew/niece');
6826fcafd02SGreg Roach                }
6836fcafd02SGreg Roach
6846fcafd02SGreg Roach                return I18N::translateContext('(a woman’s) brother’s daughter’s child', 'great-nephew/niece');
6856fcafd02SGreg Roach            case 'brodaudau':
6866fcafd02SGreg Roach                if ($sex1 === 'M') {
6876fcafd02SGreg Roach                    return I18N::translateContext('(a man’s) brother’s daughter’s daughter', 'great-niece');
6886fcafd02SGreg Roach                }
6896fcafd02SGreg Roach
6906fcafd02SGreg Roach                return I18N::translateContext('(a woman’s) brother’s daughter’s daughter', 'great-niece');
6916fcafd02SGreg Roach            case 'brodauhus':
6926fcafd02SGreg Roach                return I18N::translateContext('brother’s daughter’s husband', 'nephew-in-law');
6936fcafd02SGreg Roach            case 'brodauson':
6946fcafd02SGreg Roach                if ($sex1 === 'M') {
6956fcafd02SGreg Roach                    return I18N::translateContext('(a man’s) brother’s daughter’s son', 'great-nephew');
6966fcafd02SGreg Roach                }
6976fcafd02SGreg Roach
6986fcafd02SGreg Roach                return I18N::translateContext('(a woman’s) brother’s daughter’s son', 'great-nephew');
6996fcafd02SGreg Roach            case 'brosonchi':
7006fcafd02SGreg Roach                if ($sex1 === 'M') {
7016fcafd02SGreg Roach                    return I18N::translateContext('(a man’s) brother’s son’s child', 'great-nephew/niece');
7026fcafd02SGreg Roach                }
7036fcafd02SGreg Roach
7046fcafd02SGreg Roach                return I18N::translateContext('(a woman’s) brother’s son’s child', 'great-nephew/niece');
7056fcafd02SGreg Roach            case 'brosondau':
7066fcafd02SGreg Roach                if ($sex1 === 'M') {
7076fcafd02SGreg Roach                    return I18N::translateContext('(a man’s) brother’s son’s daughter', 'great-niece');
7086fcafd02SGreg Roach                }
7096fcafd02SGreg Roach
7106fcafd02SGreg Roach                return I18N::translateContext('(a woman’s) brother’s son’s daughter', 'great-niece');
7116fcafd02SGreg Roach            case 'brosonson':
7126fcafd02SGreg Roach                if ($sex1 === 'M') {
7136fcafd02SGreg Roach                    return I18N::translateContext('(a man’s) brother’s son’s son', 'great-nephew');
7146fcafd02SGreg Roach                }
7156fcafd02SGreg Roach
7166fcafd02SGreg Roach                return I18N::translateContext('(a woman’s) brother’s son’s son', 'great-nephew');
7176fcafd02SGreg Roach            case 'brosonwif':
7186fcafd02SGreg Roach                return I18N::translateContext('brother’s son’s wife', 'niece-in-law');
7196fcafd02SGreg Roach            case 'browifbro':
7206fcafd02SGreg Roach                return I18N::translateContext('brother’s wife’s brother', 'brother-in-law');
7216fcafd02SGreg Roach            case 'browifsib':
7226fcafd02SGreg Roach                return I18N::translateContext('brother’s wife’s sibling', 'brother/sister-in-law');
7236fcafd02SGreg Roach            case 'browifsis':
7246fcafd02SGreg Roach                return I18N::translateContext('brother’s wife’s sister', 'sister-in-law');
7256fcafd02SGreg Roach            case 'chichichi':
7266fcafd02SGreg Roach                return I18N::translateContext('child’s child’s child', 'great-grandchild');
7276fcafd02SGreg Roach            case 'chichidau':
7286fcafd02SGreg Roach                return I18N::translateContext('child’s child’s daughter', 'great-granddaughter');
7296fcafd02SGreg Roach            case 'chichison':
7306fcafd02SGreg Roach                return I18N::translateContext('child’s child’s son', 'great-grandson');
7316fcafd02SGreg Roach            case 'chidauchi':
7326fcafd02SGreg Roach                return I18N::translateContext('child’s daughter’s child', 'great-grandchild');
7336fcafd02SGreg Roach            case 'chidaudau':
7346fcafd02SGreg Roach                return I18N::translateContext('child’s daughter’s daughter', 'great-granddaughter');
7356fcafd02SGreg Roach            case 'chidauhus':
7366fcafd02SGreg Roach                return I18N::translateContext('child’s daughter’s husband', 'granddaughter’s husband');
7376fcafd02SGreg Roach            case 'chidauson':
7386fcafd02SGreg Roach                return I18N::translateContext('child’s daughter’s son', 'great-grandson');
7396fcafd02SGreg Roach            case 'chisonchi':
7406fcafd02SGreg Roach                return I18N::translateContext('child’s son’s child', 'great-grandchild');
7416fcafd02SGreg Roach            case 'chisondau':
7426fcafd02SGreg Roach                return I18N::translateContext('child’s son’s daughter', 'great-granddaughter');
7436fcafd02SGreg Roach            case 'chisonson':
7446fcafd02SGreg Roach                return I18N::translateContext('child’s son’s son', 'great-grandson');
7456fcafd02SGreg Roach            case 'chisonwif':
7466fcafd02SGreg Roach                return I18N::translateContext('child’s son’s wife', 'grandson’s wife');
7476fcafd02SGreg Roach            case 'dauchichi':
7486fcafd02SGreg Roach                return I18N::translateContext('daughter’s child’s child', 'great-grandchild');
7496fcafd02SGreg Roach            case 'dauchidau':
7506fcafd02SGreg Roach                return I18N::translateContext('daughter’s child’s daughter', 'great-granddaughter');
7516fcafd02SGreg Roach            case 'dauchison':
7526fcafd02SGreg Roach                return I18N::translateContext('daughter’s child’s son', 'great-grandson');
7536fcafd02SGreg Roach            case 'daudauchi':
7546fcafd02SGreg Roach                return I18N::translateContext('daughter’s daughter’s child', 'great-grandchild');
7556fcafd02SGreg Roach            case 'daudaudau':
7566fcafd02SGreg Roach                return I18N::translateContext('daughter’s daughter’s daughter', 'great-granddaughter');
7576fcafd02SGreg Roach            case 'daudauhus':
7586fcafd02SGreg Roach                return I18N::translateContext('daughter’s daughter’s husband', 'granddaughter’s husband');
7596fcafd02SGreg Roach            case 'daudauson':
7606fcafd02SGreg Roach                return I18N::translateContext('daughter’s daughter’s son', 'great-grandson');
7616fcafd02SGreg Roach            case 'dauhusfat':
7626fcafd02SGreg Roach                return I18N::translateContext('daughter’s husband’s father', 'son-in-law’s father');
7636fcafd02SGreg Roach            case 'dauhusmot':
7646fcafd02SGreg Roach                return I18N::translateContext('daughter’s husband’s mother', 'son-in-law’s mother');
7656fcafd02SGreg Roach            case 'dauhuspar':
7666fcafd02SGreg Roach                return I18N::translateContext('daughter’s husband’s parent', 'son-in-law’s parent');
7676fcafd02SGreg Roach            case 'dausonchi':
7686fcafd02SGreg Roach                return I18N::translateContext('daughter’s son’s child', 'great-grandchild');
7696fcafd02SGreg Roach            case 'dausondau':
7706fcafd02SGreg Roach                return I18N::translateContext('daughter’s son’s daughter', 'great-granddaughter');
7716fcafd02SGreg Roach            case 'dausonson':
7726fcafd02SGreg Roach                return I18N::translateContext('daughter’s son’s son', 'great-grandson');
7736fcafd02SGreg Roach            case 'dausonwif':
7746fcafd02SGreg Roach                return I18N::translateContext('daughter’s son’s wife', 'grandson’s wife');
7756fcafd02SGreg Roach            case 'fatbrochi':
7766fcafd02SGreg Roach                return I18N::translateContext('father’s brother’s child', 'first cousin');
7776fcafd02SGreg Roach            case 'fatbrodau':
7786fcafd02SGreg Roach                return I18N::translateContext('father’s brother’s daughter', 'first cousin');
7796fcafd02SGreg Roach            case 'fatbroson':
7806fcafd02SGreg Roach                return I18N::translateContext('father’s brother’s son', 'first cousin');
7816fcafd02SGreg Roach            case 'fatbrowif':
7826fcafd02SGreg Roach                return I18N::translateContext('father’s brother’s wife', 'aunt');
7836fcafd02SGreg Roach            case 'fatfatbro':
7846fcafd02SGreg Roach                return I18N::translateContext('father’s father’s brother', 'great-uncle');
7856fcafd02SGreg Roach            case 'fatfatfat':
7866fcafd02SGreg Roach                return I18N::translateContext('father’s father’s father', 'great-grandfather');
7876fcafd02SGreg Roach            case 'fatfatmot':
7886fcafd02SGreg Roach                return I18N::translateContext('father’s father’s mother', 'great-grandmother');
7896fcafd02SGreg Roach            case 'fatfatpar':
7906fcafd02SGreg Roach                return I18N::translateContext('father’s father’s parent', 'great-grandparent');
7916fcafd02SGreg Roach            case 'fatfatsib':
7926fcafd02SGreg Roach                return I18N::translateContext('father’s father’s sibling', 'great-aunt/uncle');
7936fcafd02SGreg Roach            case 'fatfatsis':
7946fcafd02SGreg Roach                return I18N::translateContext('father’s father’s sister', 'great-aunt');
7956fcafd02SGreg Roach            case 'fatmotbro':
7966fcafd02SGreg Roach                return I18N::translateContext('father’s mother’s brother', 'great-uncle');
7976fcafd02SGreg Roach            case 'fatmotfat':
7986fcafd02SGreg Roach                return I18N::translateContext('father’s mother’s father', 'great-grandfather');
7996fcafd02SGreg Roach            case 'fatmotmot':
8006fcafd02SGreg Roach                return I18N::translateContext('father’s mother’s mother', 'great-grandmother');
8016fcafd02SGreg Roach            case 'fatmotpar':
8026fcafd02SGreg Roach                return I18N::translateContext('father’s mother’s parent', 'great-grandparent');
8036fcafd02SGreg Roach            case 'fatmotsib':
8046fcafd02SGreg Roach                return I18N::translateContext('father’s mother’s sibling', 'great-aunt/uncle');
8056fcafd02SGreg Roach            case 'fatmotsis':
8066fcafd02SGreg Roach                return I18N::translateContext('father’s mother’s sister', 'great-aunt');
8076fcafd02SGreg Roach            case 'fatparbro':
8086fcafd02SGreg Roach                return I18N::translateContext('father’s parent’s brother', 'great-uncle');
8096fcafd02SGreg Roach            case 'fatparfat':
8106fcafd02SGreg Roach                return I18N::translateContext('father’s parent’s father', 'great-grandfather');
8116fcafd02SGreg Roach            case 'fatparmot':
8126fcafd02SGreg Roach                return I18N::translateContext('father’s parent’s mother', 'great-grandmother');
8136fcafd02SGreg Roach            case 'fatparpar':
8146fcafd02SGreg Roach                return I18N::translateContext('father’s parent’s parent', 'great-grandparent');
8156fcafd02SGreg Roach            case 'fatparsib':
8166fcafd02SGreg Roach                return I18N::translateContext('father’s parent’s sibling', 'great-aunt/uncle');
8176fcafd02SGreg Roach            case 'fatparsis':
8186fcafd02SGreg Roach                return I18N::translateContext('father’s parent’s sister', 'great-aunt');
8196fcafd02SGreg Roach            case 'fatsischi':
8206fcafd02SGreg Roach                return I18N::translateContext('father’s sister’s child', 'first cousin');
8216fcafd02SGreg Roach            case 'fatsisdau':
8226fcafd02SGreg Roach                return I18N::translateContext('father’s sister’s daughter', 'first cousin');
8236fcafd02SGreg Roach            case 'fatsishus':
8246fcafd02SGreg Roach                return I18N::translateContext('father’s sister’s husband', 'uncle');
8256fcafd02SGreg Roach            case 'fatsisson':
8266fcafd02SGreg Roach                return I18N::translateContext('father’s sister’s son', 'first cousin');
8276fcafd02SGreg Roach            case 'fatwifchi':
8286fcafd02SGreg Roach                return I18N::translateContext('father’s wife’s child', 'step-sibling');
8296fcafd02SGreg Roach            case 'fatwifdau':
8306fcafd02SGreg Roach                return I18N::translateContext('father’s wife’s daughter', 'step-sister');
8316fcafd02SGreg Roach            case 'fatwifson':
8326fcafd02SGreg Roach                return I18N::translateContext('father’s wife’s son', 'step-brother');
8336fcafd02SGreg Roach            case 'husbrowif':
8346fcafd02SGreg Roach                return I18N::translateContext('husband’s brother’s wife', 'sister-in-law');
8356fcafd02SGreg Roach            case 'hussishus':
8366fcafd02SGreg Roach                return I18N::translateContext('husband’s sister’s husband', 'brother-in-law');
8376fcafd02SGreg Roach            case 'hussibchi':
8386fcafd02SGreg Roach                return I18N::translateContext('husband’s sibling’s child', 'nephew/niece');
8396fcafd02SGreg Roach            case 'hussischi':
8406fcafd02SGreg Roach                return I18N::translateContext('husband’s sister’s child', 'nephew/niece');
8416fcafd02SGreg Roach            case 'husbrochi':
8426fcafd02SGreg Roach                return I18N::translateContext('husband’s brother’s child', 'nephew/niece');
8436fcafd02SGreg Roach            case 'hussibdau':
8446fcafd02SGreg Roach                return I18N::translateContext('husband’s sibling’s daughter', 'niece');
8456fcafd02SGreg Roach            case 'hussisdau':
8466fcafd02SGreg Roach                return I18N::translateContext('husband’s sister’s daughter', 'niece');
8476fcafd02SGreg Roach            case 'husbrodau':
8486fcafd02SGreg Roach                return I18N::translateContext('husband’s brother’s daughter', 'niece');
8496fcafd02SGreg Roach            case 'hussibson':
8506fcafd02SGreg Roach                return I18N::translateContext('husband’s sibling’s son', 'nephew');
8516fcafd02SGreg Roach            case 'hussisson':
8526fcafd02SGreg Roach                return I18N::translateContext('husband’s sister’s son', 'nephew');
8536fcafd02SGreg Roach            case 'husbroson':
8546fcafd02SGreg Roach                return I18N::translateContext('husband’s brother’s son', 'nephew');
8556fcafd02SGreg Roach            case 'motbrochi':
8566fcafd02SGreg Roach                return I18N::translateContext('mother’s brother’s child', 'first cousin');
8576fcafd02SGreg Roach            case 'motbrodau':
8586fcafd02SGreg Roach                return I18N::translateContext('mother’s brother’s daughter', 'first cousin');
8596fcafd02SGreg Roach            case 'motbroson':
8606fcafd02SGreg Roach                return I18N::translateContext('mother’s brother’s son', 'first cousin');
8616fcafd02SGreg Roach            case 'motbrowif':
8626fcafd02SGreg Roach                return I18N::translateContext('mother’s brother’s wife', 'aunt');
8636fcafd02SGreg Roach            case 'motfatbro':
8646fcafd02SGreg Roach                return I18N::translateContext('mother’s father’s brother', 'great-uncle');
8656fcafd02SGreg Roach            case 'motfatfat':
8666fcafd02SGreg Roach                return I18N::translateContext('mother’s father’s father', 'great-grandfather');
8676fcafd02SGreg Roach            case 'motfatmot':
8686fcafd02SGreg Roach                return I18N::translateContext('mother’s father’s mother', 'great-grandmother');
8696fcafd02SGreg Roach            case 'motfatpar':
8706fcafd02SGreg Roach                return I18N::translateContext('mother’s father’s parent', 'great-grandparent');
8716fcafd02SGreg Roach            case 'motfatsib':
8726fcafd02SGreg Roach                return I18N::translateContext('mother’s father’s sibling', 'great-aunt/uncle');
8736fcafd02SGreg Roach            case 'motfatsis':
8746fcafd02SGreg Roach                return I18N::translateContext('mother’s father’s sister', 'great-aunt');
8756fcafd02SGreg Roach            case 'mothuschi':
8766fcafd02SGreg Roach                return I18N::translateContext('mother’s husband’s child', 'step-sibling');
8776fcafd02SGreg Roach            case 'mothusdau':
8786fcafd02SGreg Roach                return I18N::translateContext('mother’s husband’s daughter', 'step-sister');
8796fcafd02SGreg Roach            case 'mothusson':
8806fcafd02SGreg Roach                return I18N::translateContext('mother’s husband’s son', 'step-brother');
8816fcafd02SGreg Roach            case 'motmotbro':
8826fcafd02SGreg Roach                return I18N::translateContext('mother’s mother’s brother', 'great-uncle');
8836fcafd02SGreg Roach            case 'motmotfat':
8846fcafd02SGreg Roach                return I18N::translateContext('mother’s mother’s father', 'great-grandfather');
8856fcafd02SGreg Roach            case 'motmotmot':
8866fcafd02SGreg Roach                return I18N::translateContext('mother’s mother’s mother', 'great-grandmother');
8876fcafd02SGreg Roach            case 'motmotpar':
8886fcafd02SGreg Roach                return I18N::translateContext('mother’s mother’s parent', 'great-grandparent');
8896fcafd02SGreg Roach            case 'motmotsib':
8906fcafd02SGreg Roach                return I18N::translateContext('mother’s mother’s sibling', 'great-aunt/uncle');
8916fcafd02SGreg Roach            case 'motmotsis':
8926fcafd02SGreg Roach                return I18N::translateContext('mother’s mother’s sister', 'great-aunt');
8936fcafd02SGreg Roach            case 'motparbro':
8946fcafd02SGreg Roach                return I18N::translateContext('mother’s parent’s brother', 'great-uncle');
8956fcafd02SGreg Roach            case 'motparfat':
8966fcafd02SGreg Roach                return I18N::translateContext('mother’s parent’s father', 'great-grandfather');
8976fcafd02SGreg Roach            case 'motparmot':
8986fcafd02SGreg Roach                return I18N::translateContext('mother’s parent’s mother', 'great-grandmother');
8996fcafd02SGreg Roach            case 'motparpar':
9006fcafd02SGreg Roach                return I18N::translateContext('mother’s parent’s parent', 'great-grandparent');
9016fcafd02SGreg Roach            case 'motparsib':
9026fcafd02SGreg Roach                return I18N::translateContext('mother’s parent’s sibling', 'great-aunt/uncle');
9036fcafd02SGreg Roach            case 'motparsis':
9046fcafd02SGreg Roach                return I18N::translateContext('mother’s parent’s sister', 'great-aunt');
9056fcafd02SGreg Roach            case 'motsischi':
9066fcafd02SGreg Roach                return I18N::translateContext('mother’s sister’s child', 'first cousin');
9076fcafd02SGreg Roach            case 'motsisdau':
9086fcafd02SGreg Roach                return I18N::translateContext('mother’s sister’s daughter', 'first cousin');
9096fcafd02SGreg Roach            case 'motsishus':
9106fcafd02SGreg Roach                return I18N::translateContext('mother’s sister’s husband', 'uncle');
9116fcafd02SGreg Roach            case 'motsisson':
9126fcafd02SGreg Roach                return I18N::translateContext('mother’s sister’s son', 'first cousin');
9136fcafd02SGreg Roach            case 'parbrowif':
9146fcafd02SGreg Roach                return I18N::translateContext('parent’s brother’s wife', 'aunt');
9156fcafd02SGreg Roach            case 'parfatbro':
9166fcafd02SGreg Roach                return I18N::translateContext('parent’s father’s brother', 'great-uncle');
9176fcafd02SGreg Roach            case 'parfatfat':
9186fcafd02SGreg Roach                return I18N::translateContext('parent’s father’s father', 'great-grandfather');
9196fcafd02SGreg Roach            case 'parfatmot':
9206fcafd02SGreg Roach                return I18N::translateContext('parent’s father’s mother', 'great-grandmother');
9216fcafd02SGreg Roach            case 'parfatpar':
9226fcafd02SGreg Roach                return I18N::translateContext('parent’s father’s parent', 'great-grandparent');
9236fcafd02SGreg Roach            case 'parfatsib':
9246fcafd02SGreg Roach                return I18N::translateContext('parent’s father’s sibling', 'great-aunt/uncle');
9256fcafd02SGreg Roach            case 'parfatsis':
9266fcafd02SGreg Roach                return I18N::translateContext('parent’s father’s sister', 'great-aunt');
9276fcafd02SGreg Roach            case 'parmotbro':
9286fcafd02SGreg Roach                return I18N::translateContext('parent’s mother’s brother', 'great-uncle');
9296fcafd02SGreg Roach            case 'parmotfat':
9306fcafd02SGreg Roach                return I18N::translateContext('parent’s mother’s father', 'great-grandfather');
9316fcafd02SGreg Roach            case 'parmotmot':
9326fcafd02SGreg Roach                return I18N::translateContext('parent’s mother’s mother', 'great-grandmother');
9336fcafd02SGreg Roach            case 'parmotpar':
9346fcafd02SGreg Roach                return I18N::translateContext('parent’s mother’s parent', 'great-grandparent');
9356fcafd02SGreg Roach            case 'parmotsib':
9366fcafd02SGreg Roach                return I18N::translateContext('parent’s mother’s sibling', 'great-aunt/uncle');
9376fcafd02SGreg Roach            case 'parmotsis':
9386fcafd02SGreg Roach                return I18N::translateContext('parent’s mother’s sister', 'great-aunt');
9396fcafd02SGreg Roach            case 'parparbro':
9406fcafd02SGreg Roach                return I18N::translateContext('parent’s parent’s brother', 'great-uncle');
9416fcafd02SGreg Roach            case 'parparfat':
9426fcafd02SGreg Roach                return I18N::translateContext('parent’s parent’s father', 'great-grandfather');
9436fcafd02SGreg Roach            case 'parparmot':
9446fcafd02SGreg Roach                return I18N::translateContext('parent’s parent’s mother', 'great-grandmother');
9456fcafd02SGreg Roach            case 'parparpar':
9466fcafd02SGreg Roach                return I18N::translateContext('parent’s parent’s parent', 'great-grandparent');
9476fcafd02SGreg Roach            case 'parparsib':
9486fcafd02SGreg Roach                return I18N::translateContext('parent’s parent’s sibling', 'great-aunt/uncle');
9496fcafd02SGreg Roach            case 'parparsis':
9506fcafd02SGreg Roach                return I18N::translateContext('parent’s parent’s sister', 'great-aunt');
9516fcafd02SGreg Roach            case 'parsishus':
9526fcafd02SGreg Roach                return I18N::translateContext('parent’s sister’s husband', 'uncle');
9536fcafd02SGreg Roach            case 'parspochi':
9546fcafd02SGreg Roach                return I18N::translateContext('parent’s spouse’s child', 'step-sibling');
9556fcafd02SGreg Roach            case 'parspodau':
9566fcafd02SGreg Roach                return I18N::translateContext('parent’s spouse’s daughter', 'step-sister');
9576fcafd02SGreg Roach            case 'parsposon':
9586fcafd02SGreg Roach                return I18N::translateContext('parent’s spouse’s son', 'step-brother');
9596fcafd02SGreg Roach            case 'sibchichi':
9606fcafd02SGreg Roach                return I18N::translateContext('sibling’s child’s child', 'great-nephew/niece');
9616fcafd02SGreg Roach            case 'sibchidau':
9626fcafd02SGreg Roach                return I18N::translateContext('sibling’s child’s daughter', 'great-niece');
9636fcafd02SGreg Roach            case 'sibchison':
9646fcafd02SGreg Roach                return I18N::translateContext('sibling’s child’s son', 'great-nephew');
9656fcafd02SGreg Roach            case 'sibdauchi':
9666fcafd02SGreg Roach                return I18N::translateContext('sibling’s daughter’s child', 'great-nephew/niece');
9676fcafd02SGreg Roach            case 'sibdaudau':
9686fcafd02SGreg Roach                return I18N::translateContext('sibling’s daughter’s daughter', 'great-niece');
9696fcafd02SGreg Roach            case 'sibdauhus':
9706fcafd02SGreg Roach                return I18N::translateContext('sibling’s daughter’s husband', 'nephew-in-law');
9716fcafd02SGreg Roach            case 'sibdauson':
9726fcafd02SGreg Roach                return I18N::translateContext('sibling’s daughter’s son', 'great-nephew');
9736fcafd02SGreg Roach            case 'sibsonchi':
9746fcafd02SGreg Roach                return I18N::translateContext('sibling’s son’s child', 'great-nephew/niece');
9756fcafd02SGreg Roach            case 'sibsondau':
9766fcafd02SGreg Roach                return I18N::translateContext('sibling’s son’s daughter', 'great-niece');
9776fcafd02SGreg Roach            case 'sibsonson':
9786fcafd02SGreg Roach                return I18N::translateContext('sibling’s son’s son', 'great-nephew');
9796fcafd02SGreg Roach            case 'sibsonwif':
9806fcafd02SGreg Roach                return I18N::translateContext('sibling’s son’s wife', 'niece-in-law');
9816fcafd02SGreg Roach            case 'sischichi':
9826fcafd02SGreg Roach                if ($sex1 === 'M') {
9836fcafd02SGreg Roach                    return I18N::translateContext('(a man’s) sister’s child’s child', 'great-nephew/niece');
9846fcafd02SGreg Roach                }
9856fcafd02SGreg Roach
9866fcafd02SGreg Roach                return I18N::translateContext('(a woman’s) sister’s child’s child', 'great-nephew/niece');
9876fcafd02SGreg Roach            case 'sischidau':
9886fcafd02SGreg Roach                if ($sex1 === 'M') {
9896fcafd02SGreg Roach                    return I18N::translateContext('(a man’s) sister’s child’s daughter', 'great-niece');
9906fcafd02SGreg Roach                }
9916fcafd02SGreg Roach
9926fcafd02SGreg Roach                return I18N::translateContext('(a woman’s) sister’s child’s daughter', 'great-niece');
9936fcafd02SGreg Roach            case 'sischison':
9946fcafd02SGreg Roach                if ($sex1 === 'M') {
9956fcafd02SGreg Roach                    return I18N::translateContext('(a man’s) sister’s child’s son', 'great-nephew');
9966fcafd02SGreg Roach                }
9976fcafd02SGreg Roach
9986fcafd02SGreg Roach                return I18N::translateContext('(a woman’s) sister’s child’s son', 'great-nephew');
9996fcafd02SGreg Roach            case 'sisdauchi':
10006fcafd02SGreg Roach                if ($sex1 === 'M') {
10016fcafd02SGreg Roach                    return I18N::translateContext('(a man’s) sister’s daughter’s child', 'great-nephew/niece');
10026fcafd02SGreg Roach                }
10036fcafd02SGreg Roach
10046fcafd02SGreg Roach                return I18N::translateContext('(a woman’s) sister’s daughter’s child', 'great-nephew/niece');
10056fcafd02SGreg Roach            case 'sisdaudau':
10066fcafd02SGreg Roach                if ($sex1 === 'M') {
10076fcafd02SGreg Roach                    return I18N::translateContext('(a man’s) sister’s daughter’s daughter', 'great-niece');
10086fcafd02SGreg Roach                }
10096fcafd02SGreg Roach
10106fcafd02SGreg Roach                return I18N::translateContext('(a woman’s) sister’s daughter’s daughter', 'great-niece');
10116fcafd02SGreg Roach            case 'sisdauhus':
10126fcafd02SGreg Roach                return I18N::translateContext('sisters’s daughter’s husband', 'nephew-in-law');
10136fcafd02SGreg Roach            case 'sisdauson':
10146fcafd02SGreg Roach                if ($sex1 === 'M') {
10156fcafd02SGreg Roach                    return I18N::translateContext('(a man’s) sister’s daughter’s son', 'great-nephew');
10166fcafd02SGreg Roach                }
10176fcafd02SGreg Roach
10186fcafd02SGreg Roach                return I18N::translateContext('(a woman’s) sister’s daughter’s son', 'great-nephew');
10196fcafd02SGreg Roach            case 'sishusbro':
10206fcafd02SGreg Roach                return I18N::translateContext('sister’s husband’s brother', 'brother-in-law');
10216fcafd02SGreg Roach            case 'sishussib':
10226fcafd02SGreg Roach                return I18N::translateContext('sister’s husband’s sibling', 'brother/sister-in-law');
10236fcafd02SGreg Roach            case 'sishussis':
10246fcafd02SGreg Roach                return I18N::translateContext('sister’s husband’s sister', 'sister-in-law');
10256fcafd02SGreg Roach            case 'sissonchi':
10266fcafd02SGreg Roach                if ($sex1 === 'M') {
10276fcafd02SGreg Roach                    return I18N::translateContext('(a man’s) sister’s son’s child', 'great-nephew/niece');
10286fcafd02SGreg Roach                }
10296fcafd02SGreg Roach
10306fcafd02SGreg Roach                return I18N::translateContext('(a woman’s) sister’s son’s child', 'great-nephew/niece');
10316fcafd02SGreg Roach            case 'sissondau':
10326fcafd02SGreg Roach                if ($sex1 === 'M') {
10336fcafd02SGreg Roach                    return I18N::translateContext('(a man’s) sister’s son’s daughter', 'great-niece');
10346fcafd02SGreg Roach                }
10356fcafd02SGreg Roach
10366fcafd02SGreg Roach                return I18N::translateContext('(a woman’s) sister’s son’s daughter', 'great-niece');
10376fcafd02SGreg Roach            case 'sissonson':
10386fcafd02SGreg Roach                if ($sex1 === 'M') {
10396fcafd02SGreg Roach                    return I18N::translateContext('(a man’s) sister’s son’s son', 'great-nephew');
10406fcafd02SGreg Roach                }
10416fcafd02SGreg Roach
10426fcafd02SGreg Roach                return I18N::translateContext('(a woman’s) sister’s son’s son', 'great-nephew');
10436fcafd02SGreg Roach            case 'sissonwif':
10446fcafd02SGreg Roach                return I18N::translateContext('sisters’s son’s wife', 'niece-in-law');
10456fcafd02SGreg Roach            case 'sonchichi':
10466fcafd02SGreg Roach                return I18N::translateContext('son’s child’s child', 'great-grandchild');
10476fcafd02SGreg Roach            case 'sonchidau':
10486fcafd02SGreg Roach                return I18N::translateContext('son’s child’s daughter', 'great-granddaughter');
10496fcafd02SGreg Roach            case 'sonchison':
10506fcafd02SGreg Roach                return I18N::translateContext('son’s child’s son', 'great-grandson');
10516fcafd02SGreg Roach            case 'sondauchi':
10526fcafd02SGreg Roach                return I18N::translateContext('son’s daughter’s child', 'great-grandchild');
10536fcafd02SGreg Roach            case 'sondaudau':
10546fcafd02SGreg Roach                return I18N::translateContext('son’s daughter’s daughter', 'great-granddaughter');
10556fcafd02SGreg Roach            case 'sondauhus':
10566fcafd02SGreg Roach                return I18N::translateContext('son’s daughter’s husband', 'granddaughter’s husband');
10576fcafd02SGreg Roach            case 'sondauson':
10586fcafd02SGreg Roach                return I18N::translateContext('son’s daughter’s son', 'great-grandson');
10596fcafd02SGreg Roach            case 'sonsonchi':
10606fcafd02SGreg Roach                return I18N::translateContext('son’s son’s child', 'great-grandchild');
10616fcafd02SGreg Roach            case 'sonsondau':
10626fcafd02SGreg Roach                return I18N::translateContext('son’s son’s daughter', 'great-granddaughter');
10636fcafd02SGreg Roach            case 'sonsonson':
10646fcafd02SGreg Roach                return I18N::translateContext('son’s son’s son', 'great-grandson');
10656fcafd02SGreg Roach            case 'sonsonwif':
10666fcafd02SGreg Roach                return I18N::translateContext('son’s son’s wife', 'grandson’s wife');
10676fcafd02SGreg Roach            case 'sonwiffat':
10686fcafd02SGreg Roach                return I18N::translateContext('son’s wife’s father', 'daughter-in-law’s father');
10696fcafd02SGreg Roach            case 'sonwifmot':
10706fcafd02SGreg Roach                return I18N::translateContext('son’s wife’s mother', 'daughter-in-law’s mother');
10716fcafd02SGreg Roach            case 'sonwifpar':
10726fcafd02SGreg Roach                return I18N::translateContext('son’s wife’s parent', 'daughter-in-law’s parent');
10736fcafd02SGreg Roach            case 'wifbrowif':
10746fcafd02SGreg Roach                return I18N::translateContext('wife’s brother’s wife', 'sister-in-law');
10756fcafd02SGreg Roach            case 'wifsishus':
10766fcafd02SGreg Roach                return I18N::translateContext('wife’s sister’s husband', 'brother-in-law');
10776fcafd02SGreg Roach            case 'wifsibchi':
10786fcafd02SGreg Roach                return I18N::translateContext('wife’s sibling’s child', 'nephew/niece');
10796fcafd02SGreg Roach            case 'wifsischi':
10806fcafd02SGreg Roach                return I18N::translateContext('wife’s sister’s child', 'nephew/niece');
10816fcafd02SGreg Roach            case 'wifbrochi':
10826fcafd02SGreg Roach                return I18N::translateContext('wife’s brother’s child', 'nephew/niece');
10836fcafd02SGreg Roach            case 'wifsibdau':
10846fcafd02SGreg Roach                return I18N::translateContext('wife’s sibling’s daughter', 'niece');
10856fcafd02SGreg Roach            case 'wifsisdau':
10866fcafd02SGreg Roach                return I18N::translateContext('wife’s sister’s daughter', 'niece');
10876fcafd02SGreg Roach            case 'wifbrodau':
10886fcafd02SGreg Roach                return I18N::translateContext('wife’s brother’s daughter', 'niece');
10896fcafd02SGreg Roach            case 'wifsibson':
10906fcafd02SGreg Roach                return I18N::translateContext('wife’s sibling’s son', 'nephew');
10916fcafd02SGreg Roach            case 'wifsisson':
10926fcafd02SGreg Roach                return I18N::translateContext('wife’s sister’s son', 'nephew');
10936fcafd02SGreg Roach            case 'wifbroson':
10946fcafd02SGreg Roach                return I18N::translateContext('wife’s brother’s son', 'nephew');
10956fcafd02SGreg Roach
10966fcafd02SGreg Roach                // Some “special case” level four relationships that have specific names in certain languages
10976fcafd02SGreg Roach            case 'fatfatbrowif':
10986fcafd02SGreg Roach                return I18N::translateContext('father’s father’s brother’s wife', 'great-aunt');
10996fcafd02SGreg Roach            case 'fatfatsibspo':
11006fcafd02SGreg Roach                return I18N::translateContext('father’s father’s sibling’s spouse', 'great-aunt/uncle');
11016fcafd02SGreg Roach            case 'fatfatsishus':
11026fcafd02SGreg Roach                return I18N::translateContext('father’s father’s sister’s husband', 'great-uncle');
11036fcafd02SGreg Roach            case 'fatmotbrowif':
11046fcafd02SGreg Roach                return I18N::translateContext('father’s mother’s brother’s wife', 'great-aunt');
11056fcafd02SGreg Roach            case 'fatmotsibspo':
11066fcafd02SGreg Roach                return I18N::translateContext('father’s mother’s sibling’s spouse', 'great-aunt/uncle');
11076fcafd02SGreg Roach            case 'fatmotsishus':
11086fcafd02SGreg Roach                return I18N::translateContext('father’s mother’s sister’s husband', 'great-uncle');
11096fcafd02SGreg Roach            case 'fatparbrowif':
11106fcafd02SGreg Roach                return I18N::translateContext('father’s parent’s brother’s wife', 'great-aunt');
11116fcafd02SGreg Roach            case 'fatparsibspo':
11126fcafd02SGreg Roach                return I18N::translateContext('father’s parent’s sibling’s spouse', 'great-aunt/uncle');
11136fcafd02SGreg Roach            case 'fatparsishus':
11146fcafd02SGreg Roach                return I18N::translateContext('father’s parent’s sister’s husband', 'great-uncle');
11156fcafd02SGreg Roach            case 'motfatbrowif':
11166fcafd02SGreg Roach                return I18N::translateContext('mother’s father’s brother’s wife', 'great-aunt');
11176fcafd02SGreg Roach            case 'motfatsibspo':
11186fcafd02SGreg Roach                return I18N::translateContext('mother’s father’s sibling’s spouse', 'great-aunt/uncle');
11196fcafd02SGreg Roach            case 'motfatsishus':
11206fcafd02SGreg Roach                return I18N::translateContext('mother’s father’s sister’s husband', 'great-uncle');
11216fcafd02SGreg Roach            case 'motmotbrowif':
11226fcafd02SGreg Roach                return I18N::translateContext('mother’s mother’s brother’s wife', 'great-aunt');
11236fcafd02SGreg Roach            case 'motmotsibspo':
11246fcafd02SGreg Roach                return I18N::translateContext('mother’s mother’s sibling’s spouse', 'great-aunt/uncle');
11256fcafd02SGreg Roach            case 'motmotsishus':
11266fcafd02SGreg Roach                return I18N::translateContext('mother’s mother’s sister’s husband', 'great-uncle');
11276fcafd02SGreg Roach            case 'motparbrowif':
11286fcafd02SGreg Roach                return I18N::translateContext('mother’s parent’s brother’s wife', 'great-aunt');
11296fcafd02SGreg Roach            case 'motparsibspo':
11306fcafd02SGreg Roach                return I18N::translateContext('mother’s parent’s sibling’s spouse', 'great-aunt/uncle');
11316fcafd02SGreg Roach            case 'motparsishus':
11326fcafd02SGreg Roach                return I18N::translateContext('mother’s parent’s sister’s husband', 'great-uncle');
11336fcafd02SGreg Roach            case 'parfatbrowif':
11346fcafd02SGreg Roach                return I18N::translateContext('parent’s father’s brother’s wife', 'great-aunt');
11356fcafd02SGreg Roach            case 'parfatsibspo':
11366fcafd02SGreg Roach                return I18N::translateContext('parent’s father’s sibling’s spouse', 'great-aunt/uncle');
11376fcafd02SGreg Roach            case 'parfatsishus':
11386fcafd02SGreg Roach                return I18N::translateContext('parent’s father’s sister’s husband', 'great-uncle');
11396fcafd02SGreg Roach            case 'parmotbrowif':
11406fcafd02SGreg Roach                return I18N::translateContext('parent’s mother’s brother’s wife', 'great-aunt');
11416fcafd02SGreg Roach            case 'parmotsibspo':
11426fcafd02SGreg Roach                return I18N::translateContext('parent’s mother’s sibling’s spouse', 'great-aunt/uncle');
11436fcafd02SGreg Roach            case 'parmotsishus':
11446fcafd02SGreg Roach                return I18N::translateContext('parent’s mother’s sister’s husband', 'great-uncle');
11456fcafd02SGreg Roach            case 'parparbrowif':
11466fcafd02SGreg Roach                return I18N::translateContext('parent’s parent’s brother’s wife', 'great-aunt');
11476fcafd02SGreg Roach            case 'parparsibspo':
11486fcafd02SGreg Roach                return I18N::translateContext('parent’s parent’s sibling’s spouse', 'great-aunt/uncle');
11496fcafd02SGreg Roach            case 'parparsishus':
11506fcafd02SGreg Roach                return I18N::translateContext('parent’s parent’s sister’s husband', 'great-uncle');
11516fcafd02SGreg Roach            case 'fatfatbrodau':
11526fcafd02SGreg Roach                return I18N::translateContext('father’s father’s brother’s daughter', 'first cousin once removed ascending');
11536fcafd02SGreg Roach            case 'fatfatbroson':
11546fcafd02SGreg Roach                return I18N::translateContext('father’s father’s brother’s son', 'first cousin once removed ascending');
11556fcafd02SGreg Roach            case 'fatfatbrochi':
11566fcafd02SGreg Roach                return I18N::translateContext('father’s father’s brother’s child', 'first cousin once removed ascending');
11576fcafd02SGreg Roach            case 'fatfatsisdau':
11586fcafd02SGreg Roach                return I18N::translateContext('father’s father’s sister’s daughter', 'first cousin once removed ascending');
11596fcafd02SGreg Roach            case 'fatfatsisson':
11606fcafd02SGreg Roach                return I18N::translateContext('father’s father’s sister’s son', 'first cousin once removed ascending');
11616fcafd02SGreg Roach            case 'fatfatsischi':
11626fcafd02SGreg Roach                return I18N::translateContext('father’s father’s sister’s child', 'first cousin once removed ascending');
11636fcafd02SGreg Roach            case 'fatmotbrodau':
11646fcafd02SGreg Roach                return I18N::translateContext('father’s mother’s brother’s daughter', 'first cousin once removed ascending');
11656fcafd02SGreg Roach            case 'fatmotbroson':
11666fcafd02SGreg Roach                return I18N::translateContext('father’s mother’s brother’s son', 'first cousin once removed ascending');
11676fcafd02SGreg Roach            case 'fatmotbrochi':
11686fcafd02SGreg Roach                return I18N::translateContext('father’s mother’s brother’s child', 'first cousin once removed ascending');
11696fcafd02SGreg Roach            case 'fatmotsisdau':
11706fcafd02SGreg Roach                return I18N::translateContext('father’s mother’s sister’s daughter', 'first cousin once removed ascending');
11716fcafd02SGreg Roach            case 'fatmotsisson':
11726fcafd02SGreg Roach                return I18N::translateContext('father’s mother’s sister’s son', 'first cousin once removed ascending');
11736fcafd02SGreg Roach            case 'fatmotsischi':
11746fcafd02SGreg Roach                return I18N::translateContext('father’s mother’s sister’s child', 'first cousin once removed ascending');
11756fcafd02SGreg Roach            case 'motfatbrodau':
11766fcafd02SGreg Roach                return I18N::translateContext('mother’s father’s brother’s daughter', 'first cousin once removed ascending');
11776fcafd02SGreg Roach            case 'motfatbroson':
11786fcafd02SGreg Roach                return I18N::translateContext('mother’s father’s brother’s son', 'first cousin once removed ascending');
11796fcafd02SGreg Roach            case 'motfatbrochi':
11806fcafd02SGreg Roach                return I18N::translateContext('mother’s father’s brother’s child', 'first cousin once removed ascending');
11816fcafd02SGreg Roach            case 'motfatsisdau':
11826fcafd02SGreg Roach                return I18N::translateContext('mother’s father’s sister’s daughter', 'first cousin once removed ascending');
11836fcafd02SGreg Roach            case 'motfatsisson':
11846fcafd02SGreg Roach                return I18N::translateContext('mother’s father’s sister’s son', 'first cousin once removed ascending');
11856fcafd02SGreg Roach            case 'motfatsischi':
11866fcafd02SGreg Roach                return I18N::translateContext('mother’s father’s sister’s child', 'first cousin once removed ascending');
11876fcafd02SGreg Roach            case 'motmotbrodau':
11886fcafd02SGreg Roach                return I18N::translateContext('mother’s mother’s brother’s daughter', 'first cousin once removed ascending');
11896fcafd02SGreg Roach            case 'motmotbroson':
11906fcafd02SGreg Roach                return I18N::translateContext('mother’s mother’s brother’s son', 'first cousin once removed ascending');
11916fcafd02SGreg Roach            case 'motmotbrochi':
11926fcafd02SGreg Roach                return I18N::translateContext('mother’s mother’s brother’s child', 'first cousin once removed ascending');
11936fcafd02SGreg Roach            case 'motmotsisdau':
11946fcafd02SGreg Roach                return I18N::translateContext('mother’s mother’s sister’s daughter', 'first cousin once removed ascending');
11956fcafd02SGreg Roach            case 'motmotsisson':
11966fcafd02SGreg Roach                return I18N::translateContext('mother’s mother’s sister’s son', 'first cousin once removed ascending');
11976fcafd02SGreg Roach            case 'motmotsischi':
11986fcafd02SGreg Roach                return I18N::translateContext('mother’s mother’s sister’s child', 'first cousin once removed ascending');
11996fcafd02SGreg Roach        }
12006fcafd02SGreg Roach
12016fcafd02SGreg Roach        // Some “special case” level five relationships that have specific names in certain languages
1202ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)fatbro(son|dau|chi)dau$/', $path) === 1) {
12036fcafd02SGreg Roach            return I18N::translateContext('grandfather’s brother’s granddaughter', 'second cousin');
12046fcafd02SGreg Roach        }
12056fcafd02SGreg Roach
1206ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)fatbro(son|dau|chi)son$/', $path) === 1) {
12076fcafd02SGreg Roach            return I18N::translateContext('grandfather’s brother’s grandson', 'second cousin');
12086fcafd02SGreg Roach        }
12096fcafd02SGreg Roach
1210ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)fatbro(son|dau|chi)chi$/', $path) === 1) {
12116fcafd02SGreg Roach            return I18N::translateContext('grandfather’s brother’s grandchild', 'second cousin');
12126fcafd02SGreg Roach        }
12136fcafd02SGreg Roach
1214ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)fatsis(son|dau|chi)dau$/', $path) === 1) {
12156fcafd02SGreg Roach            return I18N::translateContext('grandfather’s sister’s granddaughter', 'second cousin');
12166fcafd02SGreg Roach        }
12176fcafd02SGreg Roach
1218ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)fatsis(son|dau|chi)son$/', $path) === 1) {
12196fcafd02SGreg Roach            return I18N::translateContext('grandfather’s sister’s grandson', 'second cousin');
12206fcafd02SGreg Roach        }
12216fcafd02SGreg Roach
1222ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)fatsis(son|dau|chi)chi$/', $path) === 1) {
12236fcafd02SGreg Roach            return I18N::translateContext('grandfather’s sister’s grandchild', 'second cousin');
12246fcafd02SGreg Roach        }
12256fcafd02SGreg Roach
1226ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)fatsib(son|dau|chi)dau$/', $path) === 1) {
12276fcafd02SGreg Roach            return I18N::translateContext('grandfather’s sibling’s granddaughter', 'second cousin');
12286fcafd02SGreg Roach        }
12296fcafd02SGreg Roach
1230ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)fatsib(son|dau|chi)son$/', $path) === 1) {
12316fcafd02SGreg Roach            return I18N::translateContext('grandfather’s sibling’s grandson', 'second cousin');
12326fcafd02SGreg Roach        }
12336fcafd02SGreg Roach
1234ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)fatsib(son|dau|chi)chi$/', $path) === 1) {
12356fcafd02SGreg Roach            return I18N::translateContext('grandfather’s sibling’s grandchild', 'second cousin');
12366fcafd02SGreg Roach        }
12376fcafd02SGreg Roach
1238ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)motbro(son|dau|chi)dau$/', $path) === 1) {
12396fcafd02SGreg Roach            return I18N::translateContext('grandmother’s brother’s granddaughter', 'second cousin');
12406fcafd02SGreg Roach        }
12416fcafd02SGreg Roach
1242ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)motbro(son|dau|chi)son$/', $path) === 1) {
12436fcafd02SGreg Roach            return I18N::translateContext('grandmother’s brother’s grandson', 'second cousin');
12446fcafd02SGreg Roach        }
12456fcafd02SGreg Roach
1246ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)motbro(son|dau|chi)chi$/', $path) === 1) {
12476fcafd02SGreg Roach            return I18N::translateContext('grandmother’s brother’s grandchild', 'second cousin');
12486fcafd02SGreg Roach        }
12496fcafd02SGreg Roach
1250ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)motsis(son|dau|chi)dau$/', $path) === 1) {
12516fcafd02SGreg Roach            return I18N::translateContext('grandmother’s sister’s granddaughter', 'second cousin');
12526fcafd02SGreg Roach        }
12536fcafd02SGreg Roach
1254ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)motsis(son|dau|chi)son$/', $path) === 1) {
12556fcafd02SGreg Roach            return I18N::translateContext('grandmother’s sister’s grandson', 'second cousin');
12566fcafd02SGreg Roach        }
12576fcafd02SGreg Roach
1258ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)motsis(son|dau|chi)chi$/', $path) === 1) {
12596fcafd02SGreg Roach            return I18N::translateContext('grandmother’s sister’s grandchild', 'second cousin');
12606fcafd02SGreg Roach        }
12616fcafd02SGreg Roach
1262ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)motsib(son|dau|chi)dau$/', $path) === 1) {
12636fcafd02SGreg Roach            return I18N::translateContext('grandmother’s sibling’s granddaughter', 'second cousin');
12646fcafd02SGreg Roach        }
12656fcafd02SGreg Roach
1266ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)motsib(son|dau|chi)son$/', $path) === 1) {
12676fcafd02SGreg Roach            return I18N::translateContext('grandmother’s sibling’s grandson', 'second cousin');
12686fcafd02SGreg Roach        }
12696fcafd02SGreg Roach
1270ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)motsib(son|dau|chi)chi$/', $path) === 1) {
12716fcafd02SGreg Roach            return I18N::translateContext('grandmother’s sibling’s grandchild', 'second cousin');
12726fcafd02SGreg Roach        }
12736fcafd02SGreg Roach
1274ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)parbro(son|dau|chi)dau$/', $path) === 1) {
12756fcafd02SGreg Roach            return I18N::translateContext('grandparent’s brother’s granddaughter', 'second cousin');
12766fcafd02SGreg Roach        }
12776fcafd02SGreg Roach
1278ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)parbro(son|dau|chi)son$/', $path) === 1) {
12796fcafd02SGreg Roach            return I18N::translateContext('grandparent’s brother’s grandson', 'second cousin');
12806fcafd02SGreg Roach        }
12816fcafd02SGreg Roach
1282ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)parbro(son|dau|chi)chi$/', $path) === 1) {
12836fcafd02SGreg Roach            return I18N::translateContext('grandparent’s brother’s grandchild', 'second cousin');
12846fcafd02SGreg Roach        }
12856fcafd02SGreg Roach
1286ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)parsis(son|dau|chi)dau$/', $path) === 1) {
12876fcafd02SGreg Roach            return I18N::translateContext('grandparent’s sister’s granddaughter', 'second cousin');
12886fcafd02SGreg Roach        }
12896fcafd02SGreg Roach
1290ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)parsis(son|dau|chi)son$/', $path) === 1) {
12916fcafd02SGreg Roach            return I18N::translateContext('grandparent’s sister’s grandson', 'second cousin');
12926fcafd02SGreg Roach        }
12936fcafd02SGreg Roach
1294ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)parsis(son|dau|chi)chi$/', $path) === 1) {
12956fcafd02SGreg Roach            return I18N::translateContext('grandparent’s sister’s grandchild', 'second cousin');
12966fcafd02SGreg Roach        }
12976fcafd02SGreg Roach
1298ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)parsib(son|dau|chi)dau$/', $path) === 1) {
12996fcafd02SGreg Roach            return I18N::translateContext('grandparent’s sibling’s granddaughter', 'second cousin');
13006fcafd02SGreg Roach        }
13016fcafd02SGreg Roach
1302ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)parsib(son|dau|chi)son$/', $path) === 1) {
13036fcafd02SGreg Roach            return I18N::translateContext('grandparent’s sibling’s grandson', 'second cousin');
13046fcafd02SGreg Roach        }
13056fcafd02SGreg Roach
1306ef475b14SGreg Roach        if (preg_match('/^(mot|fat|par)parsib(son|dau|chi)chi$/', $path) === 1) {
13076fcafd02SGreg Roach            return I18N::translateContext('grandparent’s sibling’s grandchild', 'second cousin');
13086fcafd02SGreg Roach        }
13096fcafd02SGreg Roach
13106fcafd02SGreg Roach        // Look for generic/pattern relationships.
1311ef475b14SGreg Roach        if (preg_match('/^((?:mot|fat|par)+)(bro|sis|sib)$/', $path, $match) === 1) {
13126fcafd02SGreg Roach            // siblings of direct ancestors
13136fcafd02SGreg Roach            $up       = intdiv(strlen($match[1]), 3);
13146fcafd02SGreg Roach            $bef_last = substr($path, -6, 3);
13156fcafd02SGreg Roach            switch ($up) {
13166fcafd02SGreg Roach                case 3:
13176fcafd02SGreg Roach                    if ($sex2 === 'M') {
13186fcafd02SGreg Roach                        if ($bef_last === 'fat') {
13196fcafd02SGreg Roach                            return I18N::translateContext('great-grandfather’s brother', 'great-great-uncle');
13206fcafd02SGreg Roach                        }
13216fcafd02SGreg Roach
13226fcafd02SGreg Roach                        if ($bef_last === 'mot') {
13236fcafd02SGreg Roach                            return I18N::translateContext('great-grandmother’s brother', 'great-great-uncle');
13246fcafd02SGreg Roach                        }
13256fcafd02SGreg Roach
13266fcafd02SGreg Roach                        return I18N::translateContext('great-grandparent’s brother', 'great-great-uncle');
13276fcafd02SGreg Roach                    }
13286fcafd02SGreg Roach
13296fcafd02SGreg Roach                    if ($sex2 === 'F') {
13306fcafd02SGreg Roach                        return I18N::translate('great-great-aunt');
13316fcafd02SGreg Roach                    }
13326fcafd02SGreg Roach
13336fcafd02SGreg Roach                    return I18N::translate('great-great-aunt/uncle');
13346fcafd02SGreg Roach
13356fcafd02SGreg Roach                case 4:
13366fcafd02SGreg Roach                    if ($sex2 === 'M') {
13376fcafd02SGreg Roach                        if ($bef_last === 'fat') {
13386fcafd02SGreg Roach                            return I18N::translateContext('great-great-grandfather’s brother', 'great-great-great-uncle');
13396fcafd02SGreg Roach                        }
13406fcafd02SGreg Roach
13416fcafd02SGreg Roach                        if ($bef_last === 'mot') {
13426fcafd02SGreg Roach                            return I18N::translateContext('great-great-grandmother’s brother', 'great-great-great-uncle');
13436fcafd02SGreg Roach                        }
13446fcafd02SGreg Roach
13456fcafd02SGreg Roach                        return I18N::translateContext('great-great-grandparent’s brother', 'great-great-great-uncle');
13466fcafd02SGreg Roach                    }
13476fcafd02SGreg Roach
13486fcafd02SGreg Roach                    if ($sex2 === 'F') {
13496fcafd02SGreg Roach                        return I18N::translate('great-great-great-aunt');
13506fcafd02SGreg Roach                    }
13516fcafd02SGreg Roach
13526fcafd02SGreg Roach                    return I18N::translate('great-great-great-aunt/uncle');
13536fcafd02SGreg Roach
13546fcafd02SGreg Roach                case 5:
13556fcafd02SGreg Roach                    if ($sex2 === 'M') {
13566fcafd02SGreg Roach                        if ($bef_last === 'fat') {
13576fcafd02SGreg Roach                            return I18N::translateContext('great-great-great-grandfather’s brother', 'great ×4 uncle');
13586fcafd02SGreg Roach                        }
13596fcafd02SGreg Roach
13606fcafd02SGreg Roach                        if ($bef_last === 'mot') {
13616fcafd02SGreg Roach                            return I18N::translateContext('great-great-great-grandmother’s brother', 'great ×4 uncle');
13626fcafd02SGreg Roach                        }
13636fcafd02SGreg Roach
13646fcafd02SGreg Roach                        return I18N::translateContext('great-great-great-grandparent’s brother', 'great ×4 uncle');
13656fcafd02SGreg Roach                    }
13666fcafd02SGreg Roach
13676fcafd02SGreg Roach                    if ($sex2 === 'F') {
13686fcafd02SGreg Roach                        return I18N::translate('great ×4 aunt');
13696fcafd02SGreg Roach                    }
13706fcafd02SGreg Roach
13716fcafd02SGreg Roach                    return I18N::translate('great ×4 aunt/uncle');
13726fcafd02SGreg Roach
13736fcafd02SGreg Roach                case 6:
13746fcafd02SGreg Roach                    if ($sex2 === 'M') {
13756fcafd02SGreg Roach                        if ($bef_last === 'fat') {
13766fcafd02SGreg Roach                            return I18N::translateContext('great ×4 grandfather’s brother', 'great ×5 uncle');
13776fcafd02SGreg Roach                        }
13786fcafd02SGreg Roach
13796fcafd02SGreg Roach                        if ($bef_last === 'mot') {
13806fcafd02SGreg Roach                            return I18N::translateContext('great ×4 grandmother’s brother', 'great ×5 uncle');
13816fcafd02SGreg Roach                        }
13826fcafd02SGreg Roach
13836fcafd02SGreg Roach                        return I18N::translateContext('great ×4 grandparent’s brother', 'great ×5 uncle');
13846fcafd02SGreg Roach                    }
13856fcafd02SGreg Roach
13866fcafd02SGreg Roach                    if ($sex2 === 'F') {
13876fcafd02SGreg Roach                        return I18N::translate('great ×5 aunt');
13886fcafd02SGreg Roach                    }
13896fcafd02SGreg Roach
13906fcafd02SGreg Roach                    return I18N::translate('great ×5 aunt/uncle');
13916fcafd02SGreg Roach
13926fcafd02SGreg Roach                case 7:
13936fcafd02SGreg Roach                    if ($sex2 === 'M') {
13946fcafd02SGreg Roach                        if ($bef_last === 'fat') {
13956fcafd02SGreg Roach                            return I18N::translateContext('great ×5 grandfather’s brother', 'great ×6 uncle');
13966fcafd02SGreg Roach                        }
13976fcafd02SGreg Roach
13986fcafd02SGreg Roach                        if ($bef_last === 'mot') {
13996fcafd02SGreg Roach                            return I18N::translateContext('great ×5 grandmother’s brother', 'great ×6 uncle');
14006fcafd02SGreg Roach                        }
14016fcafd02SGreg Roach
14026fcafd02SGreg Roach                        return I18N::translateContext('great ×5 grandparent’s brother', 'great ×6 uncle');
14036fcafd02SGreg Roach                    }
14046fcafd02SGreg Roach
14056fcafd02SGreg Roach                    if ($sex2 === 'F') {
14066fcafd02SGreg Roach                        return I18N::translate('great ×6 aunt');
14076fcafd02SGreg Roach                    }
14086fcafd02SGreg Roach
14096fcafd02SGreg Roach                    return I18N::translate('great ×6 aunt/uncle');
14106fcafd02SGreg Roach
14116fcafd02SGreg Roach                case 8:
14126fcafd02SGreg Roach                    if ($sex2 === 'M') {
14136fcafd02SGreg Roach                        if ($bef_last === 'fat') {
14146fcafd02SGreg Roach                            return I18N::translateContext('great ×6 grandfather’s brother', 'great ×7 uncle');
14156fcafd02SGreg Roach                        }
14166fcafd02SGreg Roach
14176fcafd02SGreg Roach                        if ($bef_last === 'mot') {
14186fcafd02SGreg Roach                            return I18N::translateContext('great ×6 grandmother’s brother', 'great ×7 uncle');
14196fcafd02SGreg Roach                        }
14206fcafd02SGreg Roach
14216fcafd02SGreg Roach                        return I18N::translateContext('great ×6 grandparent’s brother', 'great ×7 uncle');
14226fcafd02SGreg Roach                    }
14236fcafd02SGreg Roach
14246fcafd02SGreg Roach                    if ($sex2 === 'F') {
14256fcafd02SGreg Roach                        return I18N::translate('great ×7 aunt');
14266fcafd02SGreg Roach                    }
14276fcafd02SGreg Roach
14286fcafd02SGreg Roach                    return I18N::translate('great ×7 aunt/uncle');
14296fcafd02SGreg Roach
14306fcafd02SGreg Roach                default:
14316fcafd02SGreg Roach                    // Different languages have different rules for naming generations.
14326fcafd02SGreg Roach                    // An English great ×12 uncle is a Danish great ×10 uncle.
14336fcafd02SGreg Roach                    //
14346fcafd02SGreg Roach                    // Need to find out which languages use which rules.
14356fcafd02SGreg Roach                    switch (I18N::languageTag()) {
14366fcafd02SGreg Roach                        case 'da':
14376fcafd02SGreg Roach                            if ($sex2 === 'M') {
14386fcafd02SGreg Roach                                return I18N::translate('great ×%s uncle', I18N::number($up - 4));
14396fcafd02SGreg Roach                            }
14406fcafd02SGreg Roach
14416fcafd02SGreg Roach                            if ($sex2 === 'F') {
14426fcafd02SGreg Roach                                return I18N::translate('great ×%s aunt', I18N::number($up - 4));
14436fcafd02SGreg Roach                            }
14446fcafd02SGreg Roach
14456fcafd02SGreg Roach                            return I18N::translate('great ×%s aunt/uncle', I18N::number($up - 4));
14466fcafd02SGreg Roach
14476fcafd02SGreg Roach                        case 'pl':
14486fcafd02SGreg Roach                            if ($sex2 === 'M') {
14496fcafd02SGreg Roach                                if ($bef_last === 'fat') {
14506fcafd02SGreg Roach                                    return I18N::translateContext('great ×(%s-1) grandfather’s brother', 'great ×%s uncle', I18N::number($up - 2));
14516fcafd02SGreg Roach                                }
14526fcafd02SGreg Roach
14536fcafd02SGreg Roach                                if ($bef_last === 'mot') {
14546fcafd02SGreg Roach                                    return I18N::translateContext('great ×(%s-1) grandmother’s brother', 'great ×%s uncle', I18N::number($up - 2));
14556fcafd02SGreg Roach                                }
14566fcafd02SGreg Roach
14576fcafd02SGreg Roach                                return I18N::translateContext('great ×(%s-1) grandparent’s brother', 'great ×%s uncle', I18N::number($up - 2));
14586fcafd02SGreg Roach                            }
14596fcafd02SGreg Roach
14606fcafd02SGreg Roach                            if ($sex2 === 'F') {
14616fcafd02SGreg Roach                                return I18N::translate('great ×%s aunt', I18N::number($up - 2));
14626fcafd02SGreg Roach                            }
14636fcafd02SGreg Roach
14646fcafd02SGreg Roach                            return I18N::translate('great ×%s aunt/uncle', I18N::number($up - 2));
14656fcafd02SGreg Roach
146682566d1aSGreg Roach                        case 'ko': // Source : Jeongwan Nam (jeongwann@gmail.com)
146782566d1aSGreg Roach                            if ($sex2 === 'M') {
146882566d1aSGreg Roach                                // I18N: if you need a different number for %s, contact the developers, as a code-change is required
146982566d1aSGreg Roach                                return I18N::translate('great ×%s uncle', I18N::number($up + 1));
147082566d1aSGreg Roach                            }
147182566d1aSGreg Roach
147282566d1aSGreg Roach                            if ($sex2 === 'F') {
147382566d1aSGreg Roach                                return I18N::translate('great ×%s aunt', I18N::number($up + 1));
147482566d1aSGreg Roach                            }
147582566d1aSGreg Roach
147682566d1aSGreg Roach                            return I18N::translate('great ×%s aunt/uncle', I18N::number($up + 1));
147782566d1aSGreg Roach
14786fcafd02SGreg Roach                        case 'hi': // Source: MrQD
14796fcafd02SGreg Roach                            if ($sex2 === 'M') {
14806fcafd02SGreg Roach                                // I18N: if you need a different number for %s, contact the developers, as a code-change is required
14816fcafd02SGreg Roach                                return I18N::translate('great ×%s uncle', I18N::number($up - 2));
14826fcafd02SGreg Roach                            }
14836fcafd02SGreg Roach
14846fcafd02SGreg Roach                            if ($sex2 === 'F') {
14856fcafd02SGreg Roach                                return I18N::translate('great ×%s aunt', I18N::number($up - 2));
14866fcafd02SGreg Roach                            }
14876fcafd02SGreg Roach
14886fcafd02SGreg Roach                            return I18N::translate('great ×%s aunt/uncle', I18N::number($up - 2));
14896fcafd02SGreg Roach
14906fcafd02SGreg Roach                        case 'zh-Hans': // Source: xmlf
14916fcafd02SGreg Roach                        case 'zh-Hant':
14926fcafd02SGreg Roach                            if ($sex2 === 'M') {
14936fcafd02SGreg Roach                                return I18N::translate('great ×%s uncle', I18N::number($up));
14946fcafd02SGreg Roach                            }
14956fcafd02SGreg Roach                            if ($sex2 === 'F') {
14966fcafd02SGreg Roach                                return I18N::translate('great ×%s aunt', I18N::number($up));
14976fcafd02SGreg Roach                            }
14986fcafd02SGreg Roach
14996fcafd02SGreg Roach                            return I18N::translate('great ×%s aunt/uncle', I18N::number($up));
15006fcafd02SGreg Roach
15016fcafd02SGreg Roach                        case 'it': // Source: Michele Locati
15026fcafd02SGreg Roach                        case 'en_AU':
15036fcafd02SGreg Roach                        case 'en_GB':
15046fcafd02SGreg Roach                        case 'en_US':
15056fcafd02SGreg Roach                        default:
15066fcafd02SGreg Roach                            if ($sex2 === 'M') {
15076fcafd02SGreg Roach                                // I18N: if you need a different number for %s, contact the developers, as a code-change is required
15086fcafd02SGreg Roach                                return I18N::translate('great ×%s uncle', I18N::number($up - 1));
15096fcafd02SGreg Roach                            }
15106fcafd02SGreg Roach
15116fcafd02SGreg Roach                            if ($sex2 === 'F') {
15126fcafd02SGreg Roach                                return I18N::translate('great ×%s aunt', I18N::number($up - 1));
15136fcafd02SGreg Roach                            }
15146fcafd02SGreg Roach
15156fcafd02SGreg Roach                            return I18N::translate('great ×%s aunt/uncle', I18N::number($up - 1));
15166fcafd02SGreg Roach                    }
15176fcafd02SGreg Roach            }
15186fcafd02SGreg Roach        }
1519ef475b14SGreg Roach        if (preg_match('/^(?:bro|sis|sib)((?:son|dau|chi)+)$/', $path, $match) === 1) {
15206fcafd02SGreg Roach            // direct descendants of siblings
15216fcafd02SGreg Roach            $down  = intdiv(strlen($match[1]), 3) + 1; // Add one, as we count generations from the common ancestor
15226fcafd02SGreg Roach            $first = substr($path, 0, 3);
15236fcafd02SGreg Roach            switch ($down) {
15246fcafd02SGreg Roach                case 4:
15256fcafd02SGreg Roach                    if ($sex2 === 'M') {
15266fcafd02SGreg Roach                        if ($first === 'bro' && $sex1 === 'M') {
15276fcafd02SGreg Roach                            return I18N::translateContext('(a man’s) brother’s great-grandson', 'great-great-nephew');
15286fcafd02SGreg Roach                        }
15296fcafd02SGreg Roach
15306fcafd02SGreg Roach                        if ($first === 'sis' && $sex1 === 'M') {
15316fcafd02SGreg Roach                            return I18N::translateContext('(a man’s) sister’s great-grandson', 'great-great-nephew');
15326fcafd02SGreg Roach                        }
15336fcafd02SGreg Roach
15346fcafd02SGreg Roach                        return I18N::translateContext('(a woman’s) great-great-nephew', 'great-great-nephew');
15356fcafd02SGreg Roach                    }
15366fcafd02SGreg Roach
15376fcafd02SGreg Roach                    if ($sex2 === 'F') {
15386fcafd02SGreg Roach                        if ($first === 'bro' && $sex1 === 'M') {
15396fcafd02SGreg Roach                            return I18N::translateContext('(a man’s) brother’s great-granddaughter', 'great-great-niece');
15406fcafd02SGreg Roach                        }
15416fcafd02SGreg Roach
15426fcafd02SGreg Roach                        if ($first === 'sis' && $sex1 === 'M') {
15436fcafd02SGreg Roach                            return I18N::translateContext('(a man’s) sister’s great-granddaughter', 'great-great-niece');
15446fcafd02SGreg Roach                        }
15456fcafd02SGreg Roach
15466fcafd02SGreg Roach                        return I18N::translateContext('(a woman’s) great-great-niece', 'great-great-niece');
15476fcafd02SGreg Roach                    }
15486fcafd02SGreg Roach
15496fcafd02SGreg Roach                    if ($first === 'bro' && $sex1 === 'M') {
15506fcafd02SGreg Roach                        return I18N::translateContext('(a man’s) brother’s great-grandchild', 'great-great-nephew/niece');
15516fcafd02SGreg Roach                    }
15526fcafd02SGreg Roach
15536fcafd02SGreg Roach                    if ($first === 'sis' && $sex1 === 'M') {
15546fcafd02SGreg Roach                        return I18N::translateContext('(a man’s) sister’s great-grandchild', 'great-great-nephew/niece');
15556fcafd02SGreg Roach                    }
15566fcafd02SGreg Roach
15576fcafd02SGreg Roach                    return I18N::translateContext('(a woman’s) great-great-nephew/niece', 'great-great-nephew/niece');
15586fcafd02SGreg Roach
15596fcafd02SGreg Roach                case 5:
15606fcafd02SGreg Roach                    if ($sex2 === 'M') {
15616fcafd02SGreg Roach                        if ($first === 'bro' && $sex1 === 'M') {
15626fcafd02SGreg Roach                            return I18N::translateContext('(a man’s) brother’s great-great-grandson', 'great-great-great-nephew');
15636fcafd02SGreg Roach                        }
15646fcafd02SGreg Roach
15656fcafd02SGreg Roach                        if ($first === 'sis' && $sex1 === 'M') {
15666fcafd02SGreg Roach                            return I18N::translateContext('(a man’s) sister’s great-great-grandson', 'great-great-great-nephew');
15676fcafd02SGreg Roach                        }
15686fcafd02SGreg Roach
15696fcafd02SGreg Roach                        return I18N::translateContext('(a woman’s) great-great-great-nephew', 'great-great-great-nephew');
15706fcafd02SGreg Roach                    }
15716fcafd02SGreg Roach
15726fcafd02SGreg Roach                    if ($sex2 === 'F') {
15736fcafd02SGreg Roach                        if ($first === 'bro' && $sex1 === 'M') {
15746fcafd02SGreg Roach                            return I18N::translateContext('(a man’s) brother’s great-great-granddaughter', 'great-great-great-niece');
15756fcafd02SGreg Roach                        }
15766fcafd02SGreg Roach
15776fcafd02SGreg Roach                        if ($first === 'sis' && $sex1 === 'M') {
15786fcafd02SGreg Roach                            return I18N::translateContext('(a man’s) sister’s great-great-granddaughter', 'great-great-great-niece');
15796fcafd02SGreg Roach                        }
15806fcafd02SGreg Roach
15816fcafd02SGreg Roach                        return I18N::translateContext('(a woman’s) great-great-great-niece', 'great-great-great-niece');
15826fcafd02SGreg Roach                    }
15836fcafd02SGreg Roach
15846fcafd02SGreg Roach                    if ($first === 'bro' && $sex1 === 'M') {
15856fcafd02SGreg Roach                        return I18N::translateContext('(a man’s) brother’s great-great-grandchild', 'great-great-great-nephew/niece');
15866fcafd02SGreg Roach                    }
15876fcafd02SGreg Roach
15886fcafd02SGreg Roach                    if ($first === 'sis' && $sex1 === 'M') {
15896fcafd02SGreg Roach                        return I18N::translateContext('(a man’s) sister’s great-great-grandchild', 'great-great-great-nephew/niece');
15906fcafd02SGreg Roach                    }
15916fcafd02SGreg Roach
15926fcafd02SGreg Roach                    return I18N::translateContext('(a woman’s) great-great-great-nephew/niece', 'great-great-great-nephew/niece');
15936fcafd02SGreg Roach
15946fcafd02SGreg Roach                case 6:
15956fcafd02SGreg Roach                    if ($sex2 === 'M') {
15966fcafd02SGreg Roach                        if ($first === 'bro' && $sex1 === 'M') {
15976fcafd02SGreg Roach                            return I18N::translateContext('(a man’s) brother’s great-great-great-grandson', 'great ×4 nephew');
15986fcafd02SGreg Roach                        }
15996fcafd02SGreg Roach
16006fcafd02SGreg Roach                        if ($first === 'sis' && $sex1 === 'M') {
16016fcafd02SGreg Roach                            return I18N::translateContext('(a man’s) sister’s great-great-great-grandson', 'great ×4 nephew');
16026fcafd02SGreg Roach                        }
16036fcafd02SGreg Roach
16046fcafd02SGreg Roach                        return I18N::translateContext('(a woman’s) great ×4 nephew', 'great ×4 nephew');
16056fcafd02SGreg Roach                    }
16066fcafd02SGreg Roach
16076fcafd02SGreg Roach                    if ($sex2 === 'F') {
16086fcafd02SGreg Roach                        if ($first === 'bro' && $sex1 === 'M') {
16096fcafd02SGreg Roach                            return I18N::translateContext('(a man’s) brother’s great-great-great-granddaughter', 'great ×4 niece');
16106fcafd02SGreg Roach                        }
16116fcafd02SGreg Roach
16126fcafd02SGreg Roach                        if ($first === 'sis' && $sex1 === 'M') {
16136fcafd02SGreg Roach                            return I18N::translateContext('(a man’s) sister’s great-great-great-granddaughter', 'great ×4 niece');
16146fcafd02SGreg Roach                        }
16156fcafd02SGreg Roach
16166fcafd02SGreg Roach                        return I18N::translateContext('(a woman’s) great ×4 niece', 'great ×4 niece');
16176fcafd02SGreg Roach                    }
16186fcafd02SGreg Roach
16196fcafd02SGreg Roach                    if ($first === 'bro' && $sex1 === 'M') {
16206fcafd02SGreg Roach                        return I18N::translateContext('(a man’s) brother’s great-great-great-grandchild', 'great ×4 nephew/niece');
16216fcafd02SGreg Roach                    }
16226fcafd02SGreg Roach
16236fcafd02SGreg Roach                    if ($first === 'sis' && $sex1 === 'M') {
16246fcafd02SGreg Roach                        return I18N::translateContext('(a man’s) sister’s great-great-great-grandchild', 'great ×4 nephew/niece');
16256fcafd02SGreg Roach                    }
16266fcafd02SGreg Roach
16276fcafd02SGreg Roach                    return I18N::translateContext('(a woman’s) great ×4 nephew/niece', 'great ×4 nephew/niece');
16286fcafd02SGreg Roach
16296fcafd02SGreg Roach                case 7:
16306fcafd02SGreg Roach                    if ($sex2 === 'M') {
16316fcafd02SGreg Roach                        if ($first === 'bro' && $sex1 === 'M') {
16326fcafd02SGreg Roach                            return I18N::translateContext('(a man’s) brother’s great ×4 grandson', 'great ×5 nephew');
16336fcafd02SGreg Roach                        }
16346fcafd02SGreg Roach
16356fcafd02SGreg Roach                        if ($first === 'sis' && $sex1 === 'M') {
16366fcafd02SGreg Roach                            return I18N::translateContext('(a man’s) sister’s great ×4 grandson', 'great ×5 nephew');
16376fcafd02SGreg Roach                        }
16386fcafd02SGreg Roach
16396fcafd02SGreg Roach                        return I18N::translateContext('(a woman’s) great ×5 nephew', 'great ×5 nephew');
16406fcafd02SGreg Roach                    }
16416fcafd02SGreg Roach
16426fcafd02SGreg Roach                    if ($sex2 === 'F') {
16436fcafd02SGreg Roach                        if ($first === 'bro' && $sex1 === 'M') {
16446fcafd02SGreg Roach                            return I18N::translateContext('(a man’s) brother’s great ×4 granddaughter', 'great ×5 niece');
16456fcafd02SGreg Roach                        }
16466fcafd02SGreg Roach
16476fcafd02SGreg Roach                        if ($first === 'sis' && $sex1 === 'M') {
16486fcafd02SGreg Roach                            return I18N::translateContext('(a man’s) sister’s great ×4 granddaughter', 'great ×5 niece');
16496fcafd02SGreg Roach                        }
16506fcafd02SGreg Roach
16516fcafd02SGreg Roach                        return I18N::translateContext('(a woman’s) great ×5 niece', 'great ×5 niece');
16526fcafd02SGreg Roach                    }
16536fcafd02SGreg Roach
16546fcafd02SGreg Roach                    if ($first === 'bro' && $sex1 === 'M') {
16556fcafd02SGreg Roach                        return I18N::translateContext('(a man’s) brother’s great ×4 grandchild', 'great ×5 nephew/niece');
16566fcafd02SGreg Roach                    }
16576fcafd02SGreg Roach
16586fcafd02SGreg Roach                    if ($first === 'sis' && $sex1 === 'M') {
16596fcafd02SGreg Roach                        return I18N::translateContext('(a man’s) sister’s great ×4 grandchild', 'great ×5 nephew/niece');
16606fcafd02SGreg Roach                    }
16616fcafd02SGreg Roach
16626fcafd02SGreg Roach                    return I18N::translateContext('(a woman’s) great ×5 nephew/niece', 'great ×5 nephew/niece');
16636fcafd02SGreg Roach
16646fcafd02SGreg Roach                default:
16656fcafd02SGreg Roach                    // Different languages have different rules for naming generations.
16666fcafd02SGreg Roach                    // An English great ×12 nephew is a Polish great ×11 nephew.
16676fcafd02SGreg Roach                    //
16686fcafd02SGreg Roach                    // Need to find out which languages use which rules.
16696fcafd02SGreg Roach                    switch (I18N::languageTag()) {
16706fcafd02SGreg Roach                        case 'pl': // Source: Lukasz Wilenski
16716fcafd02SGreg Roach                            if ($sex2 === 'M') {
16726fcafd02SGreg Roach                                if ($first === 'bro' && $sex1 === 'M') {
16736fcafd02SGreg Roach                                    return I18N::translateContext('(a man’s) brother’s great ×(%s-1) grandson', 'great ×%s nephew', I18N::number($down - 3));
16746fcafd02SGreg Roach                                }
16756fcafd02SGreg Roach
16766fcafd02SGreg Roach                                if ($first === 'sis' && $sex1 === 'M') {
16776fcafd02SGreg Roach                                    return I18N::translateContext('(a man’s) sister’s great ×(%s-1) grandson', 'great ×%s nephew', I18N::number($down - 3));
16786fcafd02SGreg Roach                                }
16796fcafd02SGreg Roach
16806fcafd02SGreg Roach                                return I18N::translateContext('(a woman’s) great ×%s nephew', 'great ×%s nephew', I18N::number($down - 3));
16816fcafd02SGreg Roach                            }
16826fcafd02SGreg Roach
16836fcafd02SGreg Roach                            if ($sex2 === 'F') {
16846fcafd02SGreg Roach                                if ($first === 'bro' && $sex1 === 'M') {
16856fcafd02SGreg Roach                                    return I18N::translateContext('(a man’s) brother’s great ×(%s-1) granddaughter', 'great ×%s niece', I18N::number($down - 3));
16866fcafd02SGreg Roach                                }
16876fcafd02SGreg Roach
16886fcafd02SGreg Roach                                if ($first === 'sis' && $sex1 === 'M') {
16896fcafd02SGreg Roach                                    return I18N::translateContext('(a man’s) sister’s great ×(%s-1) granddaughter', 'great ×%s niece', I18N::number($down - 3));
16906fcafd02SGreg Roach                                }
16916fcafd02SGreg Roach
16926fcafd02SGreg Roach                                return I18N::translateContext('(a woman’s) great ×%s niece', 'great ×%s niece', I18N::number($down - 3));
16936fcafd02SGreg Roach                            }
16946fcafd02SGreg Roach
16956fcafd02SGreg Roach                            if ($first === 'bro' && $sex1 === 'M') {
16966fcafd02SGreg Roach                                return I18N::translateContext('(a man’s) brother’s great ×(%s-1) grandchild', 'great ×%s nephew/niece', I18N::number($down - 3));
16976fcafd02SGreg Roach                            }
16986fcafd02SGreg Roach
16996fcafd02SGreg Roach                            if ($first === 'sis' && $sex1 === 'M') {
17006fcafd02SGreg Roach                                return I18N::translateContext('(a man’s) sister’s great ×(%s-1) grandchild', 'great ×%s nephew/niece', I18N::number($down - 3));
17016fcafd02SGreg Roach                            }
17026fcafd02SGreg Roach
17036fcafd02SGreg Roach                            return I18N::translateContext('(a woman’s) great ×%s nephew/niece', 'great ×%s nephew/niece', I18N::number($down - 3));
17046fcafd02SGreg Roach
170582566d1aSGreg Roach                        case 'ko': // Source: Jeongwan Nam (jeongwann@gmail.com)
170682566d1aSGreg Roach                            if ($sex2 === 'M') {
170782566d1aSGreg Roach                                if ($first === 'bro' && $sex1 === 'M') {
170882566d1aSGreg Roach                                    return I18N::translateContext('(a man’s) brother’s great ×(%s-1) grandson', 'great ×%s nephew', I18N::number($down - 0));
170982566d1aSGreg Roach                                }
171082566d1aSGreg Roach
171182566d1aSGreg Roach                                if ($first === 'sis' && $sex1 === 'M') {
171282566d1aSGreg Roach                                    return I18N::translateContext('(a man’s) sister’s great ×(%s-1) grandson', 'great ×%s nephew', I18N::number($down - 0));
171382566d1aSGreg Roach                                }
171482566d1aSGreg Roach
171582566d1aSGreg Roach                                return I18N::translateContext('(a woman’s) great ×%s nephew', 'great ×%s nephew', I18N::number($down - 0));
171682566d1aSGreg Roach                            }
171782566d1aSGreg Roach
171882566d1aSGreg Roach                            if ($sex2 === 'F') {
171982566d1aSGreg Roach                                if ($first === 'bro' && $sex1 === 'M') {
172082566d1aSGreg Roach                                    return I18N::translateContext('(a man’s) brother’s great ×(%s-1) granddaughter', 'great ×%s niece', I18N::number($down - 3));
172182566d1aSGreg Roach                                }
172282566d1aSGreg Roach
172382566d1aSGreg Roach                                if ($first === 'sis' && $sex1 === 'M') {
172482566d1aSGreg Roach                                    return I18N::translateContext('(a man’s) sister’s great ×(%s-1) granddaughter', 'great ×%s niece', I18N::number($down - 3));
172582566d1aSGreg Roach                                }
172682566d1aSGreg Roach
172782566d1aSGreg Roach                                return I18N::translateContext('(a woman’s) great ×%s niece', 'great ×%s niece', I18N::number($down - 3));
172882566d1aSGreg Roach                            }
172982566d1aSGreg Roach
173082566d1aSGreg Roach                            if ($first === 'bro' && $sex1 === 'M') {
173182566d1aSGreg Roach                                return I18N::translateContext('(a man’s) brother’s great ×(%s-1) grandchild', 'great ×%s nephew/niece', I18N::number($down - 3));
173282566d1aSGreg Roach                            }
173382566d1aSGreg Roach
173482566d1aSGreg Roach                            if ($first === 'sis' && $sex1 === 'M') {
173582566d1aSGreg Roach                                return I18N::translateContext('(a man’s) sister’s great ×(%s-1) grandchild', 'great ×%s nephew/niece', I18N::number($down - 3));
173682566d1aSGreg Roach                            }
173782566d1aSGreg Roach
173882566d1aSGreg Roach                            return I18N::translateContext('(a woman’s) great ×%s nephew/niece', 'great ×%s nephew/niece', I18N::number($down - 3));
173982566d1aSGreg Roach
17406fcafd02SGreg Roach                        case 'zh-Hans': // Source: xmlf
17416fcafd02SGreg Roach                        case 'zh-Hant':
17426fcafd02SGreg Roach                            if ($sex2 === 'M') {
17436fcafd02SGreg Roach                                if ($first === 'bro' && $sex1 === 'M') {
17446fcafd02SGreg Roach                                    return I18N::translateContext('(a man’s) brother’s great ×(%s-1) grandson', 'great ×%s nephew', I18N::number($down - 1));
17456fcafd02SGreg Roach                                }
17466fcafd02SGreg Roach                                if ($first === 'sis' && $sex1 === 'M') {
17476fcafd02SGreg Roach                                    return I18N::translateContext('(a man’s) sister’s great ×(%s-1) grandson', 'great ×%s nephew', I18N::number($down - 1));
17486fcafd02SGreg Roach                                }
17496fcafd02SGreg Roach
17506fcafd02SGreg Roach                                return I18N::translateContext('(a woman’s) great ×%s nephew', 'great ×%s nephew', I18N::number($down - 1));
17516fcafd02SGreg Roach                            }
17526fcafd02SGreg Roach                            if ($sex2 === 'F') {
17536fcafd02SGreg Roach                                if ($first === 'bro' && $sex1 === 'M') {
17546fcafd02SGreg Roach                                    return I18N::translateContext('(a man’s) brother’s great ×(%s-1) granddaughter', 'great ×%s niece', I18N::number($down - 1));
17556fcafd02SGreg Roach                                }
17566fcafd02SGreg Roach                                if ($first === 'sis' && $sex1 === 'M') {
17576fcafd02SGreg Roach                                    return I18N::translateContext('(a man’s) sister’s great ×(%s-1) granddaughter', 'great ×%s niece', I18N::number($down - 1));
17586fcafd02SGreg Roach                                }
17596fcafd02SGreg Roach
17606fcafd02SGreg Roach                                return I18N::translateContext('(a woman’s) great ×%s niece', 'great ×%s niece', I18N::number($down - 1));
17616fcafd02SGreg Roach                            }
17626fcafd02SGreg Roach                            if ($first === 'bro' && $sex1 === 'M') {
17636fcafd02SGreg Roach                                return I18N::translateContext('(a man’s) brother’s great ×(%s-1) grandchild', 'great ×%s nephew/niece', I18N::number($down - 1));
17646fcafd02SGreg Roach                            }
17656fcafd02SGreg Roach                            if ($first === 'sis' && $sex1 === 'M') {
17666fcafd02SGreg Roach                                return I18N::translateContext('(a man’s) sister’s great ×(%s-1) grandchild', 'great ×%s nephew/niece', I18N::number($down - 1));
17676fcafd02SGreg Roach                            }
17686fcafd02SGreg Roach
17696fcafd02SGreg Roach                            return I18N::translateContext('(a woman’s) great ×%s nephew/niece', 'great ×%s nephew/niece', I18N::number($down - 1));
17706fcafd02SGreg Roach
17716fcafd02SGreg Roach                        case 'he': // Source: Meliza Amity
17726fcafd02SGreg Roach                            if ($sex2 === 'M') {
17736fcafd02SGreg Roach                                return I18N::translate('great ×%s nephew', I18N::number($down - 1));
17746fcafd02SGreg Roach                            }
17756fcafd02SGreg Roach
17766fcafd02SGreg Roach                            if ($sex2 === 'F') {
17776fcafd02SGreg Roach                                return I18N::translate('great ×%s niece', I18N::number($down - 1));
17786fcafd02SGreg Roach                            }
17796fcafd02SGreg Roach
17806fcafd02SGreg Roach                            return I18N::translate('great ×%s nephew/niece', I18N::number($down - 1));
17816fcafd02SGreg Roach
17826fcafd02SGreg Roach                        case 'hi': // Source: MrQD.
17836fcafd02SGreg Roach                            if ($sex2 === 'M') {
17846fcafd02SGreg Roach                                // I18N: if you need a different number for %s, contact the developers, as a code-change is required
17856fcafd02SGreg Roach                                return I18N::translate('great ×%s nephew', I18N::number($down - 3));
17866fcafd02SGreg Roach                            }
17876fcafd02SGreg Roach
17886fcafd02SGreg Roach                            if ($sex2 === 'F') {
17896fcafd02SGreg Roach                                return I18N::translate('great ×%s niece', I18N::number($down - 3));
17906fcafd02SGreg Roach                            }
17916fcafd02SGreg Roach
17926fcafd02SGreg Roach                            return I18N::translate('great ×%s nephew/niece', I18N::number($down - 3));
17936fcafd02SGreg Roach
17946fcafd02SGreg Roach                        case 'it': // Source: Michele Locati.
17956fcafd02SGreg Roach                        case 'en_AU':
17966fcafd02SGreg Roach                        case 'en_GB':
17976fcafd02SGreg Roach                        case 'en_US':
17986fcafd02SGreg Roach                        default:
17996fcafd02SGreg Roach                            if ($sex2 === 'M') {
18006fcafd02SGreg Roach                                // I18N: if you need a different number for %s, contact the developers, as a code-change is required
18016fcafd02SGreg Roach                                return I18N::translate('great ×%s nephew', I18N::number($down - 2));
18026fcafd02SGreg Roach                            }
18036fcafd02SGreg Roach
18046fcafd02SGreg Roach                            if ($sex2 === 'F') {
18056fcafd02SGreg Roach                                return I18N::translate('great ×%s niece', I18N::number($down - 2));
18066fcafd02SGreg Roach                            }
18076fcafd02SGreg Roach
18086fcafd02SGreg Roach                            return I18N::translate('great ×%s nephew/niece', I18N::number($down - 2));
18096fcafd02SGreg Roach                    }
18106fcafd02SGreg Roach            }
18116fcafd02SGreg Roach        }
1812ef475b14SGreg Roach        if (preg_match('/^((?:mot|fat|par)*)$/', $path, $match) === 1) {
18136fcafd02SGreg Roach            // direct ancestors
18146fcafd02SGreg Roach            $up = intdiv(strlen($match[1]), 3);
18156fcafd02SGreg Roach            switch ($up) {
18166fcafd02SGreg Roach                case 4:
18176fcafd02SGreg Roach                    if ($sex2 === 'M') {
18186fcafd02SGreg Roach                        return I18N::translate('great-great-grandfather');
18196fcafd02SGreg Roach                    }
18206fcafd02SGreg Roach
18216fcafd02SGreg Roach                    if ($sex2 === 'F') {
18226fcafd02SGreg Roach                        return I18N::translate('great-great-grandmother');
18236fcafd02SGreg Roach                    }
18246fcafd02SGreg Roach
18256fcafd02SGreg Roach                    return I18N::translate('great-great-grandparent');
18266fcafd02SGreg Roach
18276fcafd02SGreg Roach                case 5:
18286fcafd02SGreg Roach                    if ($sex2 === 'M') {
18296fcafd02SGreg Roach                        return I18N::translate('great-great-great-grandfather');
18306fcafd02SGreg Roach                    }
18316fcafd02SGreg Roach
18326fcafd02SGreg Roach                    if ($sex2 === 'F') {
18336fcafd02SGreg Roach                        return I18N::translate('great-great-great-grandmother');
18346fcafd02SGreg Roach                    }
18356fcafd02SGreg Roach
18366fcafd02SGreg Roach                    return I18N::translate('great-great-great-grandparent');
18376fcafd02SGreg Roach
18386fcafd02SGreg Roach                case 6:
18396fcafd02SGreg Roach                    if ($sex2 === 'M') {
18406fcafd02SGreg Roach                        return I18N::translate('great ×4 grandfather');
18416fcafd02SGreg Roach                    }
18426fcafd02SGreg Roach
18436fcafd02SGreg Roach                    if ($sex2 === 'F') {
18446fcafd02SGreg Roach                        return I18N::translate('great ×4 grandmother');
18456fcafd02SGreg Roach                    }
18466fcafd02SGreg Roach
18476fcafd02SGreg Roach                    return I18N::translate('great ×4 grandparent');
18486fcafd02SGreg Roach
18496fcafd02SGreg Roach                case 7:
18506fcafd02SGreg Roach                    if ($sex2 === 'M') {
18516fcafd02SGreg Roach                        return I18N::translate('great ×5 grandfather');
18526fcafd02SGreg Roach                    }
18536fcafd02SGreg Roach
18546fcafd02SGreg Roach                    if ($sex2 === 'F') {
18556fcafd02SGreg Roach                        return I18N::translate('great ×5 grandmother');
18566fcafd02SGreg Roach                    }
18576fcafd02SGreg Roach
18586fcafd02SGreg Roach                    return I18N::translate('great ×5 grandparent');
18596fcafd02SGreg Roach
18606fcafd02SGreg Roach                case 8:
18616fcafd02SGreg Roach                    if ($sex2 === 'M') {
18626fcafd02SGreg Roach                        return I18N::translate('great ×6 grandfather');
18636fcafd02SGreg Roach                    }
18646fcafd02SGreg Roach
18656fcafd02SGreg Roach                    if ($sex2 === 'F') {
18666fcafd02SGreg Roach                        return I18N::translate('great ×6 grandmother');
18676fcafd02SGreg Roach                    }
18686fcafd02SGreg Roach
18696fcafd02SGreg Roach                    return I18N::translate('great ×6 grandparent');
18706fcafd02SGreg Roach
18716fcafd02SGreg Roach                case 9:
18726fcafd02SGreg Roach                    if ($sex2 === 'M') {
18736fcafd02SGreg Roach                        return I18N::translate('great ×7 grandfather');
18746fcafd02SGreg Roach                    }
18756fcafd02SGreg Roach
18766fcafd02SGreg Roach                    if ($sex2 === 'F') {
18776fcafd02SGreg Roach                        return I18N::translate('great ×7 grandmother');
18786fcafd02SGreg Roach                    }
18796fcafd02SGreg Roach
18806fcafd02SGreg Roach                    return I18N::translate('great ×7 grandparent');
18816fcafd02SGreg Roach
18826fcafd02SGreg Roach                default:
18836fcafd02SGreg Roach                    // Different languages have different rules for naming generations.
18846fcafd02SGreg Roach                    // An English great ×12 grandfather is a Danish great ×11 grandfather.
18856fcafd02SGreg Roach                    //
18866fcafd02SGreg Roach                    // Need to find out which languages use which rules.
18876fcafd02SGreg Roach                    switch (I18N::languageTag()) {
18886fcafd02SGreg Roach                        case 'da': // Source: Patrick Sorensen
18896fcafd02SGreg Roach                            if ($sex2 === 'M') {
18906fcafd02SGreg Roach                                return I18N::translate('great ×%s grandfather', I18N::number($up - 3));
18916fcafd02SGreg Roach                            }
18926fcafd02SGreg Roach
18936fcafd02SGreg Roach                            if ($sex2 === 'F') {
18946fcafd02SGreg Roach                                return I18N::translate('great ×%s grandmother', I18N::number($up - 3));
18956fcafd02SGreg Roach                            }
18966fcafd02SGreg Roach
18976fcafd02SGreg Roach                            return I18N::translate('great ×%s grandparent', I18N::number($up - 3));
18986fcafd02SGreg Roach
18996fcafd02SGreg Roach                        case 'it': // Source: Michele Locati
19006fcafd02SGreg Roach                        case 'zh-Hans': // Source: xmlf
19016fcafd02SGreg Roach                        case 'zh-Hant':
19026fcafd02SGreg Roach                        case 'es': // Source: Wes Groleau
19036fcafd02SGreg Roach                            if ($sex2 === 'M') {
19046fcafd02SGreg Roach                                return I18N::translate('great ×%s grandfather', I18N::number($up));
19056fcafd02SGreg Roach                            }
19066fcafd02SGreg Roach
19076fcafd02SGreg Roach                            if ($sex2 === 'F') {
19086fcafd02SGreg Roach                                return I18N::translate('great ×%s grandmother', I18N::number($up));
19096fcafd02SGreg Roach                            }
19106fcafd02SGreg Roach
19116fcafd02SGreg Roach                            return I18N::translate('great ×%s grandparent', I18N::number($up));
19126fcafd02SGreg Roach
19136fcafd02SGreg Roach                        case 'fr': // Source: Jacqueline Tetreault
19146fcafd02SGreg Roach                        case 'fr_CA':
19156fcafd02SGreg Roach                            if ($sex2 === 'M') {
19166fcafd02SGreg Roach                                return I18N::translate('great ×%s grandfather', I18N::number($up - 1));
19176fcafd02SGreg Roach                            }
19186fcafd02SGreg Roach
19196fcafd02SGreg Roach                            if ($sex2 === 'F') {
19206fcafd02SGreg Roach                                return I18N::translate('great ×%s grandmother', I18N::number($up - 1));
19216fcafd02SGreg Roach                            }
19226fcafd02SGreg Roach
19236fcafd02SGreg Roach                            return I18N::translate('great ×%s grandparent', I18N::number($up - 1));
19246fcafd02SGreg Roach
192582566d1aSGreg Roach                        case 'ko': // Source : Jeongwan Nam (jeongwann@gmail.com)
192682566d1aSGreg Roach                            if ($sex2 === 'M') {
192782566d1aSGreg Roach                                return I18N::translate('great ×%s grandfather', I18N::number($up + 1));
192882566d1aSGreg Roach                            }
192982566d1aSGreg Roach
193082566d1aSGreg Roach                            if ($sex2 === 'F') {
193182566d1aSGreg Roach                                return I18N::translate('great ×%s grandmother', I18N::number($up + 1));
193282566d1aSGreg Roach                            }
193382566d1aSGreg Roach
193482566d1aSGreg Roach                            return I18N::translate('great ×%s grandparent', I18N::number($up + 1));
193582566d1aSGreg Roach
19366fcafd02SGreg Roach                        case 'nn': // Source: Hogne Røed Nilsen (https://bugs.launchpad.net/webtrees/+bug/1168553)
19376fcafd02SGreg Roach                        case 'nb':
19386fcafd02SGreg Roach                            if ($sex2 === 'M') {
19396fcafd02SGreg Roach                                // I18N: if you need a different number for %s, contact the developers, as a code-change is required
19406fcafd02SGreg Roach                                return I18N::translate('great ×%s grandfather', I18N::number($up - 3));
19416fcafd02SGreg Roach                            }
19426fcafd02SGreg Roach
19436fcafd02SGreg Roach                            if ($sex2 === 'F') {
19446fcafd02SGreg Roach                                // I18N: if you need a different number for %s, contact the developers, as a code-change is required
19456fcafd02SGreg Roach                                return I18N::translate('great ×%s grandmother', I18N::number($up - 3));
19466fcafd02SGreg Roach                            }
19476fcafd02SGreg Roach
19486fcafd02SGreg Roach                            // I18N: if you need a different number for %s, contact the developers, as a code-change is required
19496fcafd02SGreg Roach                            return I18N::translate('great ×%s grandparent', I18N::number($up - 3));
19506fcafd02SGreg Roach                        case 'en_AU':
19516fcafd02SGreg Roach                        case 'en_GB':
19526fcafd02SGreg Roach                        case 'en_US':
19536fcafd02SGreg Roach                        default:
19546fcafd02SGreg Roach                            if ($sex2 === 'M') {
19556fcafd02SGreg Roach                                // I18N: if you need a different number for %s, contact the developers, as a code-change is required
19566fcafd02SGreg Roach                                return I18N::translate('great ×%s grandfather', I18N::number($up - 2));
19576fcafd02SGreg Roach                            }
19586fcafd02SGreg Roach
19596fcafd02SGreg Roach                            if ($sex2 === 'F') {
19606fcafd02SGreg Roach                                // I18N: if you need a different number for %s, contact the developers, as a code-change is required
19616fcafd02SGreg Roach                                return I18N::translate('great ×%s grandmother', I18N::number($up - 2));
19626fcafd02SGreg Roach                            }
19636fcafd02SGreg Roach
19646fcafd02SGreg Roach                            // I18N: if you need a different number for %s, contact the developers, as a code-change is required
19656fcafd02SGreg Roach                            return I18N::translate('great ×%s grandparent', I18N::number($up - 2));
19666fcafd02SGreg Roach                    }
19676fcafd02SGreg Roach            }
19686fcafd02SGreg Roach        }
1969ef475b14SGreg Roach        if (preg_match('/^((?:son|dau|chi)*)$/', $path, $match) === 1) {
19706fcafd02SGreg Roach            // direct descendants
19716fcafd02SGreg Roach            $up = intdiv(strlen($match[1]), 3);
19726fcafd02SGreg Roach            switch ($up) {
19736fcafd02SGreg Roach                case 4:
19746fcafd02SGreg Roach                    if ($sex2 === 'M') {
19756fcafd02SGreg Roach                        return I18N::translate('great-great-grandson');
19766fcafd02SGreg Roach                    }
19776fcafd02SGreg Roach
19786fcafd02SGreg Roach                    if ($sex2 === 'F') {
19796fcafd02SGreg Roach                        return I18N::translate('great-great-granddaughter');
19806fcafd02SGreg Roach                    }
19816fcafd02SGreg Roach
19826fcafd02SGreg Roach                    return I18N::translate('great-great-grandchild');
19836fcafd02SGreg Roach
19846fcafd02SGreg Roach                case 5:
19856fcafd02SGreg Roach                    if ($sex2 === 'M') {
19866fcafd02SGreg Roach                        return I18N::translate('great-great-great-grandson');
19876fcafd02SGreg Roach                    }
19886fcafd02SGreg Roach
19896fcafd02SGreg Roach                    if ($sex2 === 'F') {
19906fcafd02SGreg Roach                        return I18N::translate('great-great-great-granddaughter');
19916fcafd02SGreg Roach                    }
19926fcafd02SGreg Roach
19936fcafd02SGreg Roach                    return I18N::translate('great-great-great-grandchild');
19946fcafd02SGreg Roach
19956fcafd02SGreg Roach                case 6:
19966fcafd02SGreg Roach                    if ($sex2 === 'M') {
19976fcafd02SGreg Roach                        return I18N::translate('great ×4 grandson');
19986fcafd02SGreg Roach                    }
19996fcafd02SGreg Roach
20006fcafd02SGreg Roach                    if ($sex2 === 'F') {
20016fcafd02SGreg Roach                        return I18N::translate('great ×4 granddaughter');
20026fcafd02SGreg Roach                    }
20036fcafd02SGreg Roach
20046fcafd02SGreg Roach                    return I18N::translate('great ×4 grandchild');
20056fcafd02SGreg Roach
20066fcafd02SGreg Roach                case 7:
20076fcafd02SGreg Roach                    if ($sex2 === 'M') {
20086fcafd02SGreg Roach                        return I18N::translate('great ×5 grandson');
20096fcafd02SGreg Roach                    }
20106fcafd02SGreg Roach
20116fcafd02SGreg Roach                    if ($sex2 === 'F') {
20126fcafd02SGreg Roach                        return I18N::translate('great ×5 granddaughter');
20136fcafd02SGreg Roach                    }
20146fcafd02SGreg Roach
20156fcafd02SGreg Roach                    return I18N::translate('great ×5 grandchild');
20166fcafd02SGreg Roach
20176fcafd02SGreg Roach                case 8:
20186fcafd02SGreg Roach                    if ($sex2 === 'M') {
20196fcafd02SGreg Roach                        return I18N::translate('great ×6 grandson');
20206fcafd02SGreg Roach                    }
20216fcafd02SGreg Roach
20226fcafd02SGreg Roach                    if ($sex2 === 'F') {
20236fcafd02SGreg Roach                        return I18N::translate('great ×6 granddaughter');
20246fcafd02SGreg Roach                    }
20256fcafd02SGreg Roach
20266fcafd02SGreg Roach                    return I18N::translate('great ×6 grandchild');
20276fcafd02SGreg Roach
20286fcafd02SGreg Roach                case 9:
20296fcafd02SGreg Roach                    if ($sex2 === 'M') {
20306fcafd02SGreg Roach                        return I18N::translate('great ×7 grandson');
20316fcafd02SGreg Roach                    }
20326fcafd02SGreg Roach
20336fcafd02SGreg Roach                    if ($sex2 === 'F') {
20346fcafd02SGreg Roach                        return I18N::translate('great ×7 granddaughter');
20356fcafd02SGreg Roach                    }
20366fcafd02SGreg Roach
20376fcafd02SGreg Roach                    return I18N::translate('great ×7 grandchild');
20386fcafd02SGreg Roach
20396fcafd02SGreg Roach                default:
20406fcafd02SGreg Roach                    // Different languages have different rules for naming generations.
20416fcafd02SGreg Roach                    // An English great ×12 grandson is a Danish great ×11 grandson.
20426fcafd02SGreg Roach                    //
20436fcafd02SGreg Roach                    // Need to find out which languages use which rules.
20446fcafd02SGreg Roach                    switch (I18N::languageTag()) {
20456fcafd02SGreg Roach                        case 'nn': // Source: Hogne Røed Nilsen
20466fcafd02SGreg Roach                        case 'nb':
20476fcafd02SGreg Roach                        case 'da': // Source: Patrick Sorensen
20486fcafd02SGreg Roach                            if ($sex2 === 'M') {
20496fcafd02SGreg Roach                                return I18N::translate('great ×%s grandson', I18N::number($up - 3));
20506fcafd02SGreg Roach                            }
20516fcafd02SGreg Roach
20526fcafd02SGreg Roach                            if ($sex2 === 'F') {
20536fcafd02SGreg Roach                                return I18N::translate('great ×%s granddaughter', I18N::number($up - 3));
20546fcafd02SGreg Roach                            }
20556fcafd02SGreg Roach
20566fcafd02SGreg Roach                            return I18N::translate('great ×%s grandchild', I18N::number($up - 3));
20576fcafd02SGreg Roach
205882566d1aSGreg Roach                        case 'ko': // Source : Jeongwan Nam (jeongwann@gmail.com)
205982566d1aSGreg Roach                            if ($sex2 === 'M') {
206082566d1aSGreg Roach                                return I18N::translate('great ×%s grandson', I18N::number($up + 1));
206182566d1aSGreg Roach                            }
206282566d1aSGreg Roach
206382566d1aSGreg Roach                            if ($sex2 === 'F') {
206482566d1aSGreg Roach                                return I18N::translate('great ×%s granddaughter', I18N::number($up + 1));
206582566d1aSGreg Roach                            }
206682566d1aSGreg Roach
206782566d1aSGreg Roach                            return I18N::translate('great ×%s grandchild', I18N::number($up + 1));
206882566d1aSGreg Roach
20696fcafd02SGreg Roach                        case 'zh-Hans': // Source: xmlf
20706fcafd02SGreg Roach                        case 'zh-Hant':
20716fcafd02SGreg Roach                            if ($sex2 === 'M') {
20726fcafd02SGreg Roach                                return I18N::translate('great ×%s grandson', I18N::number($up));
20736fcafd02SGreg Roach                            }
20746fcafd02SGreg Roach                            if ($sex2 === 'F') {
20756fcafd02SGreg Roach                                return I18N::translate('great ×%s granddaughter', I18N::number($up));
20766fcafd02SGreg Roach                            }
20776fcafd02SGreg Roach
20786fcafd02SGreg Roach                            return I18N::translate('great ×%s grandchild', I18N::number($up));
20796fcafd02SGreg Roach
20806fcafd02SGreg Roach                        case 'it':
20816fcafd02SGreg Roach                            // Source: Michele Locati
20826fcafd02SGreg Roach                        case 'es':
20836fcafd02SGreg Roach                            // Source: Wes Groleau (adding doesn’t change behavior, but needs to be better researched)
20846fcafd02SGreg Roach                        case 'en_AU':
20856fcafd02SGreg Roach                        case 'en_GB':
20866fcafd02SGreg Roach                        case 'en_US':
20876fcafd02SGreg Roach                        default:
20886fcafd02SGreg Roach                            if ($sex2 === 'M') {
20896fcafd02SGreg Roach                                // I18N: if you need a different number for %s, contact the developers, as a code-change is required
20906fcafd02SGreg Roach                                return I18N::translate('great ×%s grandson', I18N::number($up - 2));
20916fcafd02SGreg Roach                            }
20926fcafd02SGreg Roach
20936fcafd02SGreg Roach                            if ($sex2 === 'F') {
20946fcafd02SGreg Roach                                // I18N: if you need a different number for %s, contact the developers, as a code-change is required
20956fcafd02SGreg Roach                                return I18N::translate('great ×%s granddaughter', I18N::number($up - 2));
20966fcafd02SGreg Roach                            }
20976fcafd02SGreg Roach
20986fcafd02SGreg Roach                            // I18N: if you need a different number for %s, contact the developers, as a code-change is required
20996fcafd02SGreg Roach                            return I18N::translate('great ×%s grandchild', I18N::number($up - 2));
21006fcafd02SGreg Roach                    }
21016fcafd02SGreg Roach            }
21026fcafd02SGreg Roach        }
2103ef475b14SGreg Roach        if (preg_match('/^((?:mot|fat|par)+)(?:bro|sis|sib)((?:son|dau|chi)+)$/', $path, $match) === 1) {
21046fcafd02SGreg Roach            // cousins in English
21056fcafd02SGreg Roach            $ascent  = $match[1];
21066fcafd02SGreg Roach            $descent = $match[2];
21076fcafd02SGreg Roach            $up      = intdiv(strlen($ascent), 3);
21086fcafd02SGreg Roach            $down    = intdiv(strlen($descent), 3);
21096fcafd02SGreg Roach            $cousin  = min($up, $down); // Moved out of switch (en/default case) so that
21106fcafd02SGreg Roach            $removed = abs($down - $up); // Spanish (and other languages) can use it, too.
21116fcafd02SGreg Roach
21126fcafd02SGreg Roach            // Different languages have different rules for naming cousins. For example,
21136fcafd02SGreg Roach            // an English “second cousin once removed” is a Polish “cousin of 7th degree”.
21146fcafd02SGreg Roach            //
21156fcafd02SGreg Roach            // Need to find out which languages use which rules.
21166fcafd02SGreg Roach            switch (I18N::languageTag()) {
21176fcafd02SGreg Roach                case 'pl': // Source: Lukasz Wilenski
21186fcafd02SGreg Roach                    return self::legacyCousinName($up + $down + 2, $sex2);
21196fcafd02SGreg Roach                case 'it':
21206fcafd02SGreg Roach                    // Source: Michele Locati. See italian_cousins_names.zip
21216fcafd02SGreg Roach                    // https://webtrees.net/forums/8-translation/1200-great-xn-grandparent?limit=6&start=6
21226fcafd02SGreg Roach                    return self::legacyCousinName($up + $down - 3, $sex2);
21236fcafd02SGreg Roach                case 'es':
21246fcafd02SGreg Roach                    if ($down === $up) {
21256fcafd02SGreg Roach                        return self::legacyCousinName($cousin, $sex2);
21266fcafd02SGreg Roach                    }
21276fcafd02SGreg Roach
21286fcafd02SGreg Roach                    if ($down < $up) {
21296fcafd02SGreg Roach                        return self::legacyCousinName2($cousin + 1, $sex2, $this->legacyNameAlgorithm('sib' . $descent));
21306fcafd02SGreg Roach                    }
21316fcafd02SGreg Roach
21326fcafd02SGreg Roach                    if ($sex2 === 'M') {
21336fcafd02SGreg Roach                        return self::legacyCousinName2($cousin + 1, $sex2, $this->legacyNameAlgorithm('bro' . $descent));
21346fcafd02SGreg Roach                    }
21356fcafd02SGreg Roach
21366fcafd02SGreg Roach                    if ($sex2 === 'F') {
21376fcafd02SGreg Roach                        return self::legacyCousinName2($cousin + 1, $sex2, $this->legacyNameAlgorithm('sis' . $descent));
21386fcafd02SGreg Roach                    }
21396fcafd02SGreg Roach
21406fcafd02SGreg Roach                    return self::legacyCousinName2($cousin + 1, $sex2, $this->legacyNameAlgorithm('sib' . $descent));
21416fcafd02SGreg Roach
2142ad3143ccSGreg Roach                case 'en_AU': // See: https://en.wikipedia.org/wiki/File:CousinTree.svg
21436fcafd02SGreg Roach                case 'en_GB':
21446fcafd02SGreg Roach                case 'en_US':
21456fcafd02SGreg Roach                default:
21466fcafd02SGreg Roach                    switch ($removed) {
21476fcafd02SGreg Roach                        case 0:
21486fcafd02SGreg Roach                            return self::legacyCousinName($cousin, $sex2);
21496fcafd02SGreg Roach                        case 1:
21506fcafd02SGreg Roach                            if ($up > $down) {
2151ad3143ccSGreg Roach                                /* I18N: %s=“fifth cousin”, etc. */
21526fcafd02SGreg Roach                                return I18N::translate('%s once removed ascending', self::legacyCousinName($cousin, $sex2));
21536fcafd02SGreg Roach                            }
21546fcafd02SGreg Roach
2155ad3143ccSGreg Roach                            /* I18N: %s=“fifth cousin”, etc. */
21566fcafd02SGreg Roach
21576fcafd02SGreg Roach                            return I18N::translate('%s once removed descending', self::legacyCousinName($cousin, $sex2));
21586fcafd02SGreg Roach                        case 2:
21596fcafd02SGreg Roach                            if ($up > $down) {
21606fcafd02SGreg Roach                                /* I18N: %s=“fifth cousin”, etc. */
21616fcafd02SGreg Roach                                return I18N::translate('%s twice removed ascending', self::legacyCousinName($cousin, $sex2));
21626fcafd02SGreg Roach                            }
21636fcafd02SGreg Roach
21646fcafd02SGreg Roach                            /* I18N: %s=“fifth cousin”, etc. */
21656fcafd02SGreg Roach
21666fcafd02SGreg Roach                            return I18N::translate('%s twice removed descending', self::legacyCousinName($cousin, $sex2));
21676fcafd02SGreg Roach                        case 3:
21686fcafd02SGreg Roach                            if ($up > $down) {
21696fcafd02SGreg Roach                                /* I18N: %s=“fifth cousin”, etc. */
21706fcafd02SGreg Roach                                return I18N::translate('%s three times removed ascending', self::legacyCousinName($cousin, $sex2));
21716fcafd02SGreg Roach                            }
21726fcafd02SGreg Roach
21736fcafd02SGreg Roach                            /* I18N: %s=“fifth cousin”, etc. */
21746fcafd02SGreg Roach
21756fcafd02SGreg Roach                            return I18N::translate('%s three times removed descending', self::legacyCousinName($cousin, $sex2));
21766fcafd02SGreg Roach                        default:
21776fcafd02SGreg Roach                            if ($up > $down) {
21786fcafd02SGreg Roach                                /* I18N: %1$s=“fifth cousin”, etc., %2$s>=4 */
21796fcafd02SGreg Roach                                return I18N::translate('%1$s %2$s times removed ascending', self::legacyCousinName($cousin, $sex2), I18N::number($removed));
21806fcafd02SGreg Roach                            }
21816fcafd02SGreg Roach
21826fcafd02SGreg Roach                            /* I18N: %1$s=“fifth cousin”, etc., %2$s>=4 */
21836fcafd02SGreg Roach
21846fcafd02SGreg Roach                            return I18N::translate('%1$s %2$s times removed descending', self::legacyCousinName($cousin, $sex2), I18N::number($removed));
21856fcafd02SGreg Roach                    }
21866fcafd02SGreg Roach            }
21876fcafd02SGreg Roach        }
21886fcafd02SGreg Roach
21896fcafd02SGreg Roach        // Split the relationship into sub-relationships, e.g., third-cousin’s great-uncle.
21906fcafd02SGreg Roach        // Try splitting at every point, and choose the path with the shorted translated name.
21916fcafd02SGreg Roach        // But before starting to recursively go through all combinations, do a cache look-up
21926fcafd02SGreg Roach
21936fcafd02SGreg Roach        static $relationshipsCache;
21946fcafd02SGreg Roach        $relationshipsCache ??= [];
21956fcafd02SGreg Roach        if (array_key_exists($path, $relationshipsCache)) {
21966fcafd02SGreg Roach            return $relationshipsCache[$path];
21976fcafd02SGreg Roach        }
21986fcafd02SGreg Roach
219903c56546SGreg Roach        $relationship = '';
22006fcafd02SGreg Roach        $path1        = substr($path, 0, 3);
22016fcafd02SGreg Roach        $path2        = substr($path, 3);
220203c56546SGreg Roach        while ($path2 !== '') {
22036fcafd02SGreg Roach            // I18N: A complex relationship, such as “third-cousin’s great-uncle”
22046fcafd02SGreg Roach            $tmp = I18N::translate(
22056fcafd02SGreg Roach                '%1$s’s %2$s',
22066fcafd02SGreg Roach                $this->legacyNameAlgorithm($path1),
22076fcafd02SGreg Roach                $this->legacyNameAlgorithm($path2)
22086fcafd02SGreg Roach            );
220903c56546SGreg Roach            if ($relationship === '' || strlen($tmp) < strlen($relationship)) {
22106fcafd02SGreg Roach                $relationship = $tmp;
22116fcafd02SGreg Roach            }
22126fcafd02SGreg Roach            $path1 .= substr($path2, 0, 3);
22136fcafd02SGreg Roach            $path2 = substr($path2, 3);
22146fcafd02SGreg Roach        }
22156fcafd02SGreg Roach        // and store the result in the cache
22166fcafd02SGreg Roach        $relationshipsCache[$path] = $relationship;
22176fcafd02SGreg Roach
22186fcafd02SGreg Roach        return $relationship;
22196fcafd02SGreg Roach    }
22206fcafd02SGreg Roach
22216fcafd02SGreg Roach    /**
22226fcafd02SGreg Roach     * Calculate the name of a cousin.
22236fcafd02SGreg Roach     *
22246fcafd02SGreg Roach     * @param int    $n
22256fcafd02SGreg Roach     * @param string $sex
22266fcafd02SGreg Roach     *
22276fcafd02SGreg Roach     * @return string
22286fcafd02SGreg Roach     *
22296fcafd02SGreg Roach     * @deprecated
22306fcafd02SGreg Roach     */
22316fcafd02SGreg Roach    private static function legacyCousinName(int $n, string $sex): string
22326fcafd02SGreg Roach    {
22336fcafd02SGreg Roach        if ($sex === 'M') {
22346fcafd02SGreg Roach            switch ($n) {
22356fcafd02SGreg Roach                case 1:
22366fcafd02SGreg Roach                    /* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
22376fcafd02SGreg Roach                    return I18N::translateContext('MALE', 'first cousin');
22386fcafd02SGreg Roach                case 2:
22396fcafd02SGreg Roach                    /* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
22406fcafd02SGreg Roach                    return I18N::translateContext('MALE', 'second cousin');
22416fcafd02SGreg Roach                case 3:
22426fcafd02SGreg Roach                    /* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
22436fcafd02SGreg Roach                    return I18N::translateContext('MALE', 'third cousin');
22446fcafd02SGreg Roach                case 4:
22456fcafd02SGreg Roach                    /* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
22466fcafd02SGreg Roach                    return I18N::translateContext('MALE', 'fourth cousin');
22476fcafd02SGreg Roach                case 5:
22486fcafd02SGreg Roach                    /* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
22496fcafd02SGreg Roach                    return I18N::translateContext('MALE', 'fifth cousin');
22506fcafd02SGreg Roach                case 6:
22516fcafd02SGreg Roach                    /* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
22526fcafd02SGreg Roach                    return I18N::translateContext('MALE', 'sixth cousin');
22536fcafd02SGreg Roach                case 7:
22546fcafd02SGreg Roach                    /* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
22556fcafd02SGreg Roach                    return I18N::translateContext('MALE', 'seventh cousin');
22566fcafd02SGreg Roach                case 8:
22576fcafd02SGreg Roach                    /* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
22586fcafd02SGreg Roach                    return I18N::translateContext('MALE', 'eighth cousin');
22596fcafd02SGreg Roach                case 9:
22606fcafd02SGreg Roach                    /* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
22616fcafd02SGreg Roach                    return I18N::translateContext('MALE', 'ninth cousin');
22626fcafd02SGreg Roach                case 10:
22636fcafd02SGreg Roach                    /* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
22646fcafd02SGreg Roach                    return I18N::translateContext('MALE', 'tenth cousin');
22656fcafd02SGreg Roach                case 11:
22666fcafd02SGreg Roach                    /* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
22676fcafd02SGreg Roach                    return I18N::translateContext('MALE', 'eleventh cousin');
22686fcafd02SGreg Roach                case 12:
22696fcafd02SGreg Roach                    /* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
22706fcafd02SGreg Roach                    return I18N::translateContext('MALE', 'twelfth cousin');
22716fcafd02SGreg Roach                case 13:
22726fcafd02SGreg Roach                    /* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
22736fcafd02SGreg Roach                    return I18N::translateContext('MALE', 'thirteenth cousin');
22746fcafd02SGreg Roach                case 14:
22756fcafd02SGreg Roach                    /* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
22766fcafd02SGreg Roach                    return I18N::translateContext('MALE', 'fourteenth cousin');
22776fcafd02SGreg Roach                case 15:
22786fcafd02SGreg Roach                    /* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
22796fcafd02SGreg Roach                    return I18N::translateContext('MALE', 'fifteenth cousin');
22806fcafd02SGreg Roach                default:
22816fcafd02SGreg Roach                    /* I18N: Note that for Italian and Polish, “N’th cousins” are different from English “N’th cousins”, and the software has already generated the correct “N” for your language. You only need to translate - you do not need to convert. For other languages, if your cousin rules are different from English, please contact the developers. */
22826fcafd02SGreg Roach                    return I18N::translateContext('MALE', '%s × cousin', I18N::number($n));
22836fcafd02SGreg Roach            }
22846fcafd02SGreg Roach        }
22856fcafd02SGreg Roach
22866fcafd02SGreg Roach        if ($sex === 'F') {
22876fcafd02SGreg Roach            switch ($n) {
22886fcafd02SGreg Roach                case 1:
22896fcafd02SGreg Roach                    return I18N::translateContext('FEMALE', 'first cousin');
22906fcafd02SGreg Roach                case 2:
22916fcafd02SGreg Roach                    return I18N::translateContext('FEMALE', 'second cousin');
22926fcafd02SGreg Roach                case 3:
22936fcafd02SGreg Roach                    return I18N::translateContext('FEMALE', 'third cousin');
22946fcafd02SGreg Roach                case 4:
22956fcafd02SGreg Roach                    return I18N::translateContext('FEMALE', 'fourth cousin');
22966fcafd02SGreg Roach                case 5:
22976fcafd02SGreg Roach                    return I18N::translateContext('FEMALE', 'fifth cousin');
22986fcafd02SGreg Roach                case 6:
22996fcafd02SGreg Roach                    return I18N::translateContext('FEMALE', 'sixth cousin');
23006fcafd02SGreg Roach                case 7:
23016fcafd02SGreg Roach                    return I18N::translateContext('FEMALE', 'seventh cousin');
23026fcafd02SGreg Roach                case 8:
23036fcafd02SGreg Roach                    return I18N::translateContext('FEMALE', 'eighth cousin');
23046fcafd02SGreg Roach                case 9:
23056fcafd02SGreg Roach                    return I18N::translateContext('FEMALE', 'ninth cousin');
23066fcafd02SGreg Roach                case 10:
23076fcafd02SGreg Roach                    return I18N::translateContext('FEMALE', 'tenth cousin');
23086fcafd02SGreg Roach                case 11:
23096fcafd02SGreg Roach                    return I18N::translateContext('FEMALE', 'eleventh cousin');
23106fcafd02SGreg Roach                case 12:
23116fcafd02SGreg Roach                    return I18N::translateContext('FEMALE', 'twelfth cousin');
23126fcafd02SGreg Roach                case 13:
23136fcafd02SGreg Roach                    return I18N::translateContext('FEMALE', 'thirteenth cousin');
23146fcafd02SGreg Roach                case 14:
23156fcafd02SGreg Roach                    return I18N::translateContext('FEMALE', 'fourteenth cousin');
23166fcafd02SGreg Roach                case 15:
23176fcafd02SGreg Roach                    return I18N::translateContext('FEMALE', 'fifteenth cousin');
23186fcafd02SGreg Roach                default:
23196fcafd02SGreg Roach                    return I18N::translateContext('FEMALE', '%s × cousin', I18N::number($n));
23206fcafd02SGreg Roach            }
23216fcafd02SGreg Roach        }
23226fcafd02SGreg Roach
23236fcafd02SGreg Roach        switch ($n) {
23246fcafd02SGreg Roach            case 1:
23256fcafd02SGreg Roach                return I18N::translate('first cousin');
23266fcafd02SGreg Roach            case 2:
23276fcafd02SGreg Roach                return I18N::translate('second cousin');
23286fcafd02SGreg Roach            case 3:
23296fcafd02SGreg Roach                return I18N::translate('third cousin');
23306fcafd02SGreg Roach            case 4:
23316fcafd02SGreg Roach                return I18N::translate('fourth cousin');
23326fcafd02SGreg Roach            case 5:
23336fcafd02SGreg Roach                return I18N::translate('fifth cousin');
23346fcafd02SGreg Roach            case 6:
23356fcafd02SGreg Roach                return I18N::translate('sixth cousin');
23366fcafd02SGreg Roach            case 7:
23376fcafd02SGreg Roach                return I18N::translate('seventh cousin');
23386fcafd02SGreg Roach            case 8:
23396fcafd02SGreg Roach                return I18N::translate('eighth cousin');
23406fcafd02SGreg Roach            case 9:
23416fcafd02SGreg Roach                return I18N::translate('ninth cousin');
23426fcafd02SGreg Roach            case 10:
23436fcafd02SGreg Roach                return I18N::translate('tenth cousin');
23446fcafd02SGreg Roach            case 11:
23456fcafd02SGreg Roach                return I18N::translate('eleventh cousin');
23466fcafd02SGreg Roach            case 12:
23476fcafd02SGreg Roach                return I18N::translate('twelfth cousin');
23486fcafd02SGreg Roach            case 13:
23496fcafd02SGreg Roach                return I18N::translate('thirteenth cousin');
23506fcafd02SGreg Roach            case 14:
23516fcafd02SGreg Roach                return I18N::translate('fourteenth cousin');
23526fcafd02SGreg Roach            case 15:
23536fcafd02SGreg Roach                return I18N::translate('fifteenth cousin');
23546fcafd02SGreg Roach            default:
23556fcafd02SGreg Roach                return I18N::translate('%s × cousin', I18N::number($n));
23566fcafd02SGreg Roach        }
23576fcafd02SGreg Roach    }
23586fcafd02SGreg Roach
23596fcafd02SGreg Roach    /**
23606fcafd02SGreg Roach     * A variation on cousin_name(), for constructs such as “sixth great-nephew”
23616fcafd02SGreg Roach     * Currently used only by Spanish relationship names.
23626fcafd02SGreg Roach     *
23636fcafd02SGreg Roach     * @param int    $n
23646fcafd02SGreg Roach     * @param string $sex
23656fcafd02SGreg Roach     * @param string $relation
23666fcafd02SGreg Roach     *
23676fcafd02SGreg Roach     * @return string
23686fcafd02SGreg Roach     *
23696fcafd02SGreg Roach     * @deprecated
23706fcafd02SGreg Roach     */
23716fcafd02SGreg Roach    private static function legacyCousinName2(int $n, string $sex, string $relation): string
23726fcafd02SGreg Roach    {
23736fcafd02SGreg Roach        if ($sex === 'M') {
23746fcafd02SGreg Roach            switch ($n) {
23756fcafd02SGreg Roach                case 1:
23766fcafd02SGreg Roach                    /* I18N: A Spanish relationship name, such as third great-nephew */
23776fcafd02SGreg Roach                    return I18N::translateContext('MALE', 'first %s', $relation);
23786fcafd02SGreg Roach                case 2:
23796fcafd02SGreg Roach                    /* I18N: A Spanish relationship name, such as third great-nephew */
23806fcafd02SGreg Roach                    return I18N::translateContext('MALE', 'second %s', $relation);
23816fcafd02SGreg Roach                case 3:
23826fcafd02SGreg Roach                    /* I18N: A Spanish relationship name, such as third great-nephew */
23836fcafd02SGreg Roach                    return I18N::translateContext('MALE', 'third %s', $relation);
23846fcafd02SGreg Roach                case 4:
23856fcafd02SGreg Roach                    /* I18N: A Spanish relationship name, such as third great-nephew */
23866fcafd02SGreg Roach                    return I18N::translateContext('MALE', 'fourth %s', $relation);
23876fcafd02SGreg Roach                case 5:
23886fcafd02SGreg Roach                    /* I18N: A Spanish relationship name, such as third great-nephew */
23896fcafd02SGreg Roach                    return I18N::translateContext('MALE', 'fifth %s', $relation);
23906fcafd02SGreg Roach                default:
23916fcafd02SGreg Roach                    /* I18N: A Spanish relationship name, such as third great-nephew */
23926fcafd02SGreg Roach                    return I18N::translateContext('MALE', '%1$s × %2$s', I18N::number($n), $relation);
23936fcafd02SGreg Roach            }
23946fcafd02SGreg Roach        }
23956fcafd02SGreg Roach
23966fcafd02SGreg Roach        if ($sex === 'F') {
23976fcafd02SGreg Roach            switch ($n) {
23986fcafd02SGreg Roach                case 1:
23996fcafd02SGreg Roach                    /* I18N: A Spanish relationship name, such as third great-nephew */
24006fcafd02SGreg Roach                    return I18N::translateContext('FEMALE', 'first %s', $relation);
24016fcafd02SGreg Roach                case 2:
24026fcafd02SGreg Roach                    /* I18N: A Spanish relationship name, such as third great-nephew */
24036fcafd02SGreg Roach                    return I18N::translateContext('FEMALE', 'second %s', $relation);
24046fcafd02SGreg Roach                case 3:
24056fcafd02SGreg Roach                    /* I18N: A Spanish relationship name, such as third great-nephew */
24066fcafd02SGreg Roach                    return I18N::translateContext('FEMALE', 'third %s', $relation);
24076fcafd02SGreg Roach                case 4:
24086fcafd02SGreg Roach                    /* I18N: A Spanish relationship name, such as third great-nephew */
24096fcafd02SGreg Roach                    return I18N::translateContext('FEMALE', 'fourth %s', $relation);
24106fcafd02SGreg Roach                case 5:
24116fcafd02SGreg Roach                    /* I18N: A Spanish relationship name, such as third great-nephew */
24126fcafd02SGreg Roach                    return I18N::translateContext('FEMALE', 'fifth %s', $relation);
24136fcafd02SGreg Roach                default:
24146fcafd02SGreg Roach                    /* I18N: A Spanish relationship name, such as third great-nephew */
24156fcafd02SGreg Roach                    return I18N::translateContext('FEMALE', '%1$s × %2$s', I18N::number($n), $relation);
24166fcafd02SGreg Roach            }
24176fcafd02SGreg Roach        }
24186fcafd02SGreg Roach
24196fcafd02SGreg Roach        switch ($n) {
24206fcafd02SGreg Roach            case 1:
24216fcafd02SGreg Roach                /* I18N: A Spanish relationship name, such as third great-nephew */
24226fcafd02SGreg Roach                return I18N::translate('first %s', $relation);
24236fcafd02SGreg Roach            case 2:
24246fcafd02SGreg Roach                /* I18N: A Spanish relationship name, such as third great-nephew */
24256fcafd02SGreg Roach                return I18N::translate('second %s', $relation);
24266fcafd02SGreg Roach            case 3:
24276fcafd02SGreg Roach                /* I18N: A Spanish relationship name, such as third great-nephew */
24286fcafd02SGreg Roach                return I18N::translate('third %s', $relation);
24296fcafd02SGreg Roach            case 4:
24306fcafd02SGreg Roach                /* I18N: A Spanish relationship name, such as third great-nephew */
24316fcafd02SGreg Roach                return I18N::translate('fourth %s', $relation);
24326fcafd02SGreg Roach            case 5:
24336fcafd02SGreg Roach                /* I18N: A Spanish relationship name, such as third great-nephew */
24346fcafd02SGreg Roach                return I18N::translate('fifth %s', $relation);
24356fcafd02SGreg Roach            default:
24366fcafd02SGreg Roach                /* I18N: A Spanish relationship name, such as third great-nephew */
24376fcafd02SGreg Roach                return I18N::translate('%1$s × %2$s', I18N::number($n), $relation);
24386fcafd02SGreg Roach        }
24396fcafd02SGreg Roach    }
24406fcafd02SGreg Roach}
2441