Ejemplo n.º 1
0
 /**
  * Generate the likely value of this census column, based on available information.
  *
  * @param Individual      $individual
  * @param Individual|null $head
  *
  * @return string
  */
 public function generate(Individual $individual, Individual $head = null)
 {
     if ($individual->getSex() === 'F') {
         return '';
     } else {
         return (string) Date::getAge($individual->getEstimatedBirthDate(), $this->date(), 0);
     }
 }
Ejemplo n.º 2
0
 /**
  * Generate the likely value of this census column, based on available information.
  *
  * @param Individual      $individual
  * @param Individual|null $head
  *
  * @return string
  */
 public function generate(Individual $individual, Individual $head = null)
 {
     $sex = $individual->getSex();
     if ($sex === 'M' || $sex === 'F') {
         return $sex;
     } else {
         return '';
     }
 }
Ejemplo n.º 3
0
 /**
  * Generate the likely value of this census column, based on available information.
  *
  * @param Individual      $individual
  * @param Individual|null $head
  *
  * @return string
  */
 public function generate(Individual $individual, Individual $head = null)
 {
     switch ($individual->getSex()) {
         case 'M':
             return $this->male;
         case 'F':
             return $this->female;
         default:
             return '';
     }
 }
 /**
  * Generate the likely value of this census column, based on available information.
  *
  * @param Individual      $individual
  * @param Individual|null $head
  *
  * @return string
  */
 public function generate(Individual $individual, Individual $head = null)
 {
     if ($individual->getSex() === 'M') {
         return '';
     } else {
         $years = Date::getAge($individual->getEstimatedBirthDate(), $this->date(), 0);
         if ($years > 15) {
             $years -= $years % 5;
         }
         return (string) $years;
     }
 }
 /**
  * Generate the likely value of this census column, based on available information.
  *
  * @param Individual      $individual
  * @param Individual|null $head
  *
  * @return string
  */
 public function generate(Individual $individual, Individual $head = null)
 {
     if ($individual->getSex() !== 'F') {
         return '';
     }
     $count = 0;
     foreach ($individual->getSpouseFamilies() as $family) {
         foreach ($family->getChildren() as $child) {
             if ($child->getBirthDate()->isOK() && Date::compare($child->getBirthDate(), $this->date()) < 0 && $child->getBirthDate() != $child->getDeathDate() && (!$child->getDeathDate()->isOK() || Date::compare($child->getDeathDate(), $this->date()) > 0)) {
                 $count++;
             }
         }
     }
     return (string) $count;
 }
Ejemplo n.º 6
0
 /**
  * get the person box stylesheet class for the given person
  *
  * @param Individual $person
  *
  * @return string returns 'person_box', 'person_boxF', or 'person_boxNN'
  */
 public function getPersonStyle($person)
 {
     switch ($person->getSex()) {
         case 'M':
             $class = 'person_box';
             break;
         case 'F':
             $class = 'person_boxF';
             break;
         default:
             $class = 'person_boxNN';
             break;
     }
     if ($person->isPendingDeletion()) {
         $class .= ' old';
     } elseif ($person->isPendingAddtion()) {
         $class .= ' new';
     }
     return $class;
 }
Ejemplo n.º 7
0
/**
 * Print a form to add an individual or edit an individual’s name
 *
 * @param string     $nextaction
 * @param Individual $person
 * @param Family     $family
 * @param Fact       $name_fact
 * @param string     $famtag
 * @param string     $gender
 */
function print_indi_form($nextaction, Individual $person = null, Family $family = null, Fact $name_fact = null, $famtag = 'CHIL', $gender = 'U')
{
    global $WT_TREE, $bdm, $controller;
    if ($person) {
        $xref = $person->getXref();
    } elseif ($family) {
        $xref = $family->getXref();
    } else {
        $xref = 'new';
    }
    // Different cultures do surnames differently
    $surname_tradition = SurnameTradition::create($WT_TREE->getPreference('SURNAME_TRADITION'));
    $name_fields = array();
    if ($name_fact) {
        // Editing an existing name
        $name_fact_id = $name_fact->getFactId();
        $name_type = $name_fact->getAttribute('TYPE');
        $namerec = $name_fact->getGedcom();
        foreach (Config::standardNameFacts() as $tag) {
            if ($tag === 'NAME') {
                $name_fields[$tag] = $name_fact->getValue();
            } else {
                $name_fields[$tag] = $name_fact->getAttribute($tag);
            }
        }
        // Populate any missing 2 XXXX fields from the 1 NAME field
        $npfx_accept = implode('|', Config::namePrefixes());
        if (preg_match('/(((' . $npfx_accept . ')\\.? +)*)([^\\n\\/"]*)("(.*)")? *\\/(([a-z]{2,3} +)*)(.*)\\/ *(.*)/i', $name_fields['NAME'], $name_bits)) {
            if (empty($name_fields['NPFX'])) {
                $name_fields['NPFX'] = $name_bits[1];
            }
            if (empty($name_fields['SPFX']) && empty($name_fields['SURN'])) {
                $name_fields['SPFX'] = trim($name_bits[7]);
                // For names with two surnames, there will be four slashes.
                // Turn them into a list
                $name_fields['SURN'] = preg_replace('~/[^/]*/~', ',', $name_bits[9]);
            }
            if (empty($name_fields['GIVN'])) {
                $name_fields['GIVN'] = $name_bits[4];
            }
            if (empty($name_fields['NICK']) && !empty($name_bits[6]) && !preg_match('/^2 NICK/m', $namerec)) {
                $name_fields['NICK'] = $name_bits[6];
            }
        }
    } else {
        // Creating a new name
        $name_fact_id = null;
        $name_type = null;
        $namerec = null;
        // Populate the standard NAME field and subfields
        foreach (Config::standardNameFacts() as $tag) {
            $name_fields[$tag] = '';
        }
        // Inherit surname from parents, spouse or child
        if ($family) {
            $father = $family->getHusband();
            if ($father && $father->getFirstFact('NAME')) {
                $father_name = $father->getFirstFact('NAME')->getValue();
            } else {
                $father_name = '';
            }
            $mother = $family->getWife();
            if ($mother && $mother->getFirstFact('NAME')) {
                $mother_name = $mother->getFirstFact('NAME')->getValue();
            } else {
                $mother_name = '';
            }
        } else {
            $father = null;
            $mother = null;
            $father_name = '';
            $mother_name = '';
        }
        if ($person && $person->getFirstFact('NAME')) {
            $indi_name = $person->getFirstFact('NAME')->getValue();
        } else {
            $indi_name = '';
        }
        switch ($nextaction) {
            case 'add_child_to_family_action':
                $name_fields = $surname_tradition->newChildNames($father_name, $mother_name, $gender) + $name_fields;
                break;
            case 'add_child_to_individual_action':
                if ($person->getSex() === 'F') {
                    $name_fields = $surname_tradition->newChildNames('', $indi_name, $gender) + $name_fields;
                } else {
                    $name_fields = $surname_tradition->newChildNames($indi_name, '', $gender) + $name_fields;
                }
                break;
            case 'add_parent_to_individual_action':
                $name_fields = $surname_tradition->newParentNames($indi_name, $gender) + $name_fields;
                break;
            case 'add_spouse_to_family_action':
                if ($father) {
                    $name_fields = $surname_tradition->newSpouseNames($father_name, $gender) + $name_fields;
                } else {
                    $name_fields = $surname_tradition->newSpouseNames($mother_name, $gender) + $name_fields;
                }
                break;
            case 'add_spouse_to_individual_action':
                $name_fields = $surname_tradition->newSpouseNames($indi_name, $gender) + $name_fields;
                break;
            case 'add_unlinked_indi_action':
            case 'update':
                if ($surname_tradition->hasSurnames()) {
                    $name_fields['NAME'] = '//';
                }
                break;
        }
    }
    $bdm = '';
    // used to copy '1 SOUR' to '2 SOUR' for BIRT DEAT MARR
    echo '<div id="edit_interface-page">';
    echo '<h4>', $controller->getPageTitle(), '</h4>';
    FunctionsPrint::initializeCalendarPopup();
    echo '<form method="post" name="addchildform" onsubmit="return checkform();">';
    echo '<input type="hidden" name="ged" value="', $WT_TREE->getNameHtml(), '">';
    echo '<input type="hidden" name="action" value="', $nextaction, '">';
    echo '<input type="hidden" name="fact_id" value="', $name_fact_id, '">';
    echo '<input type="hidden" name="xref" value="', $xref, '">';
    echo '<input type="hidden" name="famtag" value="', $famtag, '">';
    echo '<input type="hidden" name="gender" value="', $gender, '">';
    echo '<input type="hidden" name="goto" value="">';
    // set by javascript
    echo Filter::getCsrf();
    echo '<table class="facts_table">';
    switch ($nextaction) {
        case 'add_child_to_family_action':
        case 'add_child_to_individual_action':
            // When adding a new child, specify the pedigree
            FunctionsEdit::addSimpleTag('0 PEDI');
            break;
        case 'update':
            // When adding/editing a name, specify the type
            FunctionsEdit::addSimpleTag('0 TYPE ' . $name_type, '', '', null, $person);
            break;
    }
    // First - new/existing standard name fields
    foreach ($name_fields as $tag => $value) {
        if (substr_compare($tag, '_', 0, 1) !== 0) {
            FunctionsEdit::addSimpleTag('0 ' . $tag . ' ' . $value);
        }
    }
    // Second - new/existing advanced name fields
    if ($surname_tradition->hasMarriedNames() || preg_match('/\\n2 _MARNM /', $namerec)) {
        $adv_name_fields = array('_MARNM' => '');
    } else {
        $adv_name_fields = array();
    }
    if (preg_match_all('/(' . WT_REGEX_TAG . ')/', $WT_TREE->getPreference('ADVANCED_NAME_FACTS'), $match)) {
        foreach ($match[1] as $tag) {
            $adv_name_fields[$tag] = '';
        }
    }
    foreach (array_keys($adv_name_fields) as $tag) {
        // Edit existing tags, grouped together
        if (preg_match_all('/2 ' . $tag . ' (.+)/', $namerec, $match)) {
            foreach ($match[1] as $value) {
                FunctionsEdit::addSimpleTag('2 ' . $tag . ' ' . $value, '', GedcomTag::getLabel('NAME:' . $tag, $person));
                if ($tag === '_MARNM') {
                    preg_match_all('/\\/([^\\/]*)\\//', $value, $matches);
                    FunctionsEdit::addSimpleTag('2 _MARNM_SURN ' . implode(',', $matches[1]));
                }
            }
        }
        // Allow a new tag to be entered
        if (!array_key_exists($tag, $name_fields)) {
            FunctionsEdit::addSimpleTag('0 ' . $tag, '', GedcomTag::getLabel('NAME:' . $tag, $person));
            if ($tag === '_MARNM') {
                FunctionsEdit::addSimpleTag('0 _MARNM_SURN');
            }
        }
    }
    // Third - new/existing custom name fields
    foreach ($name_fields as $tag => $value) {
        if (substr_compare($tag, '_', 0, 1) === 0) {
            FunctionsEdit::addSimpleTag('0 ' . $tag . ' ' . $value);
            if ($tag === '_MARNM') {
                preg_match_all('/\\/([^\\/]*)\\//', $value, $matches);
                FunctionsEdit::addSimpleTag('2 _MARNM_SURN ' . implode(',', $matches[1]));
            }
        }
    }
    // Fourth - SOUR, NOTE, _CUSTOM, etc.
    if ($namerec) {
        $gedlines = explode("\n", $namerec);
        // -- find the number of lines in the record
        $fields = explode(' ', $gedlines[0]);
        $glevel = $fields[0];
        $level = $glevel;
        $type = trim($fields[1]);
        $tags = array();
        $i = 0;
        do {
            if ($type !== 'TYPE' && !array_key_exists($type, $name_fields) && !array_key_exists($type, $adv_name_fields)) {
                $text = '';
                for ($j = 2; $j < count($fields); $j++) {
                    if ($j > 2) {
                        $text .= ' ';
                    }
                    $text .= $fields[$j];
                }
                while ($i + 1 < count($gedlines) && preg_match('/' . ($level + 1) . ' CONT ?(.*)/', $gedlines[$i + 1], $cmatch) > 0) {
                    $text .= "\n" . $cmatch[2];
                    $i++;
                }
                FunctionsEdit::addSimpleTag($level . ' ' . $type . ' ' . $text);
            }
            $tags[] = $type;
            $i++;
            if (isset($gedlines[$i])) {
                $fields = explode(' ', $gedlines[$i]);
                $level = $fields[0];
                if (isset($fields[1])) {
                    $type = $fields[1];
                }
            }
        } while ($level > $glevel && $i < count($gedlines));
    }
    // If we are adding a new individual, add the basic details
    if ($nextaction !== 'update') {
        echo '</table><br><table class="facts_table">';
        // 1 SEX
        if ($famtag === 'HUSB' || $gender === 'M') {
            FunctionsEdit::addSimpleTag("0 SEX M");
        } elseif ($famtag === 'WIFE' || $gender === 'F') {
            FunctionsEdit::addSimpleTag('0 SEX F');
        } else {
            FunctionsEdit::addSimpleTag('0 SEX');
        }
        $bdm = 'BD';
        if (preg_match_all('/(' . WT_REGEX_TAG . ')/', $WT_TREE->getPreference('QUICK_REQUIRED_FACTS'), $matches)) {
            foreach ($matches[1] as $match) {
                if (!in_array($match, explode('|', WT_EVENTS_DEAT))) {
                    FunctionsEdit::addSimpleTags($match);
                }
            }
        }
        //-- if adding a spouse add the option to add a marriage fact to the new family
        if ($nextaction === 'add_spouse_to_individual_action' || $nextaction === 'add_spouse_to_family_action') {
            $bdm .= 'M';
            if (preg_match_all('/(' . WT_REGEX_TAG . ')/', $WT_TREE->getPreference('QUICK_REQUIRED_FAMFACTS'), $matches)) {
                foreach ($matches[1] as $match) {
                    FunctionsEdit::addSimpleTags($match);
                }
            }
        }
        if (preg_match_all('/(' . WT_REGEX_TAG . ')/', $WT_TREE->getPreference('QUICK_REQUIRED_FACTS'), $matches)) {
            foreach ($matches[1] as $match) {
                if (in_array($match, explode('|', WT_EVENTS_DEAT))) {
                    FunctionsEdit::addSimpleTags($match);
                }
            }
        }
    }
    echo keep_chan($person);
    echo '</table>';
    if ($nextaction === 'update') {
        // GEDCOM 5.5.1 spec says NAME doesn’t get a OBJE
        FunctionsEdit::printAddLayer('SOUR');
        FunctionsEdit::printAddLayer('NOTE');
        FunctionsEdit::printAddLayer('SHARED_NOTE');
        FunctionsEdit::printAddLayer('RESN');
    } else {
        FunctionsEdit::printAddLayer('SOUR', 1);
        FunctionsEdit::printAddLayer('NOTE', 1);
        FunctionsEdit::printAddLayer('SHARED_NOTE', 1);
        FunctionsEdit::printAddLayer('RESN', 1);
    }
    // If we are editing an existing name, allow raw GEDCOM editing
    if ($name_fact && (Auth::isAdmin() || $WT_TREE->getPreference('SHOW_GEDCOM_RECORD'))) {
        echo '<br><br><a href="edit_interface.php?action=editrawfact&amp;xref=', $xref, '&amp;fact_id=', $name_fact->getFactId(), '&amp;ged=', $WT_TREE->getNameUrl(), '">', I18N::translate('Edit raw GEDCOM'), '</a>';
    }
    echo '<p id="save-cancel">';
    echo '<input type="submit" class="save" value="', I18N::translate('save'), '">';
    if (preg_match('/^add_(child|spouse|parent|unlinked_indi)/', $nextaction)) {
        echo '<input type="submit" class="save" value="', I18N::translate('go to new individual'), '" onclick="document.addchildform.goto.value=\'new\';">';
    }
    echo '<input type="button" class="cancel" value="', I18N::translate('close'), '" onclick="window.close();">';
    echo '</p>';
    echo '</form>';
    $controller->addInlineJavascript('
	SURNAME_TRADITION="' . $WT_TREE->getPreference('SURNAME_TRADITION') . '";
	gender="' . $gender . '";
	famtag="' . $famtag . '";
	function trim(str) {
		str=str.replace(/\\s\\s+/g, " ");
		return str.replace(/(^\\s+)|(\\s+$)/g, "");
	}

	function lang_class(str) {
		if (str.match(/[\\u0370-\\u03FF]/)) return "greek";
		if (str.match(/[\\u0400-\\u04FF]/)) return "cyrillic";
		if (str.match(/[\\u0590-\\u05FF]/)) return "hebrew";
		if (str.match(/[\\u0600-\\u06FF]/)) return "arabic";
		return "latin"; // No matched text implies latin :-)
	}

	// Generate a full name from the name components
	function generate_name() {
		var npfx = jQuery("#NPFX").val();
		var givn = jQuery("#GIVN").val();
		var spfx = jQuery("#SPFX").val();
		var surn = jQuery("#SURN").val();
		var nsfx = jQuery("#NSFX").val();
		if (SURNAME_TRADITION === "polish" && (gender === "F" || famtag === "WIFE")) {
			surn = surn.replace(/ski$/, "ska");
			surn = surn.replace(/cki$/, "cka");
			surn = surn.replace(/dzki$/, "dzka");
			surn = surn.replace(/żki$/, "żka");
		}
		// Commas are used in the GIVN and SURN field to separate lists of surnames.
		// For example, to differentiate the two Spanish surnames from an English
		// double-barred name.
		// Commas *may* be used in other fields, and will form part of the NAME.
		if (WT_LOCALE=="vi" || WT_LOCALE=="hu") {
			// Default format: /SURN/ GIVN
			return trim(npfx+" /"+trim(spfx+" "+surn).replace(/ *, */g, " ")+"/ "+givn.replace(/ *, */g, " ")+" "+nsfx);
		} else if (WT_LOCALE=="zh") {
			// Default format: /SURN/GIVN
			return trim(npfx+" /"+trim(spfx+" "+surn).replace(/ *, */g, " ")+"/"+givn.replace(/ *, */g, " ")+" "+nsfx);
		} else {
			// Default format: GIVN /SURN/
			return trim(npfx+" "+givn.replace(/ *, */g, " ")+" /"+trim(spfx+" "+surn).replace(/ *, */g, " ")+"/ "+nsfx);
		}
	}

	// Update the NAME and _MARNM fields from the name components
	// and also display the value in read-only "gedcom" format.
	function updatewholename() {
		// Don’t update the name if the user manually changed it
		if (manualChange) {
			return;
		}
		var npfx = jQuery("#NPFX").val();
		var givn = jQuery("#GIVN").val();
		var spfx = jQuery("#SPFX").val();
		var surn = jQuery("#SURN").val();
		var nsfx = jQuery("#NSFX").val();
		var name = generate_name();
		jQuery("#NAME").val(name);
		jQuery("#NAME_display").text(name);
		// Married names inherit some NSFX values, but not these
		nsfx = nsfx.replace(/^(I|II|III|IV|V|VI|Junior|Jr\\.?|Senior|Sr\\.?)$/i, "");
		// Update _MARNM field from _MARNM_SURN field and display it
		// Be careful of mixing latin/hebrew/etc. character sets.
		var ip = document.getElementsByTagName("input");
		var marnm_id = "";
		var romn = "";
		var heb = "";
		for (var i = 0; i < ip.length; i++) {
			var val = trim(ip[i].value);
			if (ip[i].id.indexOf("_HEB") === 0)
				heb = val;
			if (ip[i].id.indexOf("ROMN") === 0)
				romn = val;
			if (ip[i].id.indexOf("_MARNM") === 0) {
				if (ip[i].id.indexOf("_MARNM_SURN") === 0) {
					var msurn = "";
					if (val !== "") {
						var lc = lang_class(document.getElementById(ip[i].id).value);
						if (lang_class(name) === lc)
							msurn = trim(npfx + " " + givn + " /" + val + "/ " + nsfx);
						else if (lc === "hebrew")
							msurn = heb.replace(/\\/.*\\//, "/" + val + "/");
						else if (lang_class(romn) === lc)
							msurn = romn.replace(/\\/.*\\//, "/" + val + "/");
					}
					document.getElementById(marnm_id).value = msurn;
					document.getElementById(marnm_id+"_display").innerHTML = msurn;
				} else {
					marnm_id = ip[i].id;
				}
			}
		}
	}

	// Toggle the name editor fields between
	// <input type="hidden"> <span style="display:inline">
	// <input type="text">   <span style="display:hidden">
	var oldName = "";

	// Calls to generate_name() trigger an update - hence need to
	// set the manual change to true first.  We are probably
	// listening to the wrong events on the input fields...
	var manualChange = true;
	manualChange = generate_name() !== jQuery("#NAME").val();

	function convertHidden(eid) {
		var input1 = jQuery("#" + eid);
		var input2 = jQuery("#" + eid + "_display");
		// Note that IE does not allow us to change the type of an input, so we must create a new one.
		if (input1.attr("type")=="hidden") {
			input1.replaceWith(input1.clone().attr("type", "text"));
			input2.hide();
		} else {
			input1.replaceWith(input1.clone().attr("type", "hidden"));
			input2.show();
		}
	}

	/**
	 * if the user manually changed the NAME field, then update the textual
	 * HTML representation of it
	 * If the value changed set manualChange to true so that changing
	 * the other fields doesn’t change the NAME line
	 */
	function updateTextName(eid) {
		var element = document.getElementById(eid);
		if (element) {
			if (element.value!=oldName) manualChange = true;
			var delement = document.getElementById(eid+"_display");
			if (delement) {
				delement.innerHTML = element.value;
			}
		}
	}

	function checkform() {
		var ip=document.getElementsByTagName("input");
		for (var i=0; i<ip.length; i++) {
			// ADD slashes to _HEB and _AKA names
			if (ip[i].id.indexOf("_AKA")==0 || ip[i].id.indexOf("_HEB")==0 || ip[i].id.indexOf("ROMN")==0)
				if (ip[i].value.indexOf("/")<0 && ip[i].value!="")
					ip[i].value=ip[i].value.replace(/([^\\s]+)\\s*$/, "/$1/");
			// Blank out temporary _MARNM_SURN
			if (ip[i].id.indexOf("_MARNM_SURN")==0)
					ip[i].value="";
			// Convert "xxx yyy" and "xxx y yyy" surnames to "xxx,yyy"
			if ((SURNAME_TRADITION=="spanish" || "SURNAME_TRADITION"=="portuguese") && ip[i].id.indexOf("SURN")==0) {
				ip[i].value=document.forms[0].SURN.value.replace(/^\\s*([^\\s,]{2,})\\s+([iIyY] +)?([^\\s,]{2,})\\s*$/, "$1,$3");
			}
		}
		return true;
	}

	// If the name isn’t initially formed from the components in a standard way,
	// then don’t automatically update it.
	if (document.getElementById("NAME").value!=generate_name() && document.getElementById("NAME").value!="//") {
		convertHidden("NAME");
	}
	');
    echo '</div>';
}
Ejemplo n.º 8
0
 /**
  * Convert a relationship path into a relationship name.
  *
  * @param string $path
  * @param Individual $person1
  * @param Individual $person2
  *
  * @return string
  */
 public static function getRelationshipNameFromPath($path, Individual $person1 = null, Individual $person2 = null)
 {
     if (!preg_match('/^(mot|fat|par|hus|wif|spo|son|dau|chi|bro|sis|sib)*$/', $path)) {
         // TODO: Update all the “3 RELA ” values in class_person
         return '<span class="error">' . $path . '</span>';
     }
     // The path does not include the starting person.  In some languages, the
     // translation for a man’s (relative) is different from a woman’s (relative),
     // due to inflection.
     $sex1 = $person1 ? $person1->getSex() : 'U';
     // The sex of the last person in the relationship determines the name in
     // many cases.  e.g. great-aunt / great-uncle
     if (preg_match('/(fat|hus|son|bro)$/', $path)) {
         $sex2 = 'M';
     } elseif (preg_match('/(mot|wif|dau|sis)$/', $path)) {
         $sex2 = 'F';
     } else {
         $sex2 = 'U';
     }
     switch ($path) {
         case '':
             return I18N::translate('self');
             //  Level One relationships
         //  Level One relationships
         case 'mot':
             return I18N::translate('mother');
         case 'fat':
             return I18N::translate('father');
         case 'par':
             return I18N::translate('parent');
         case 'hus':
             if ($person1 && $person2) {
                 foreach ($person1->getSpouseFamilies() as $family) {
                     if ($person2 === $family->getSpouse($person1)) {
                         if ($family->getFacts('_NMR')) {
                             if ($family->getFacts(WT_EVENTS_DIV)) {
                                 return I18N::translateContext('MALE', 'ex-partner');
                             } else {
                                 return I18N::translateContext('MALE', 'partner');
                             }
                         } elseif ($family->getFacts(WT_EVENTS_DIV)) {
                             return I18N::translate('ex-husband');
                         }
                     }
                 }
             }
             return I18N::translate('husband');
         case 'wif':
             if ($person1 && $person1) {
                 foreach ($person1->getSpouseFamilies() as $family) {
                     if ($person2 === $family->getSpouse($person1)) {
                         if ($family->getFacts('_NMR')) {
                             if ($family->getFacts(WT_EVENTS_DIV)) {
                                 return I18N::translateContext('FEMALE', 'ex-partner');
                             } else {
                                 return I18N::translateContext('FEMALE', 'partner');
                             }
                         } elseif ($family->getFacts(WT_EVENTS_DIV)) {
                             return I18N::translate('ex-wife');
                         }
                     }
                 }
             }
             return I18N::translate('wife');
         case 'spo':
             if ($person1 && $person2) {
                 foreach ($person1->getSpouseFamilies() as $family) {
                     if ($person2 === $family->getSpouse($person1)) {
                         if ($family->getFacts('_NMR')) {
                             if ($family->getFacts(WT_EVENTS_DIV)) {
                                 return I18N::translateContext('MALE/FEMALE', 'ex-partner');
                             } else {
                                 return I18N::translateContext('MALE/FEMALE', 'partner');
                             }
                         } elseif ($family->getFacts(WT_EVENTS_DIV)) {
                             return I18N::translate('ex-spouse');
                         }
                     }
                 }
             }
             return I18N::translate('spouse');
         case 'son':
             return I18N::translate('son');
         case 'dau':
             return I18N::translate('daughter');
         case 'chi':
             return I18N::translate('child');
         case 'bro':
             if ($person1 && $person2) {
                 $dob1 = $person1->getBirthDate();
                 $dob2 = $person2->getBirthDate();
                 if ($dob1->isOK() && $dob2->isOK()) {
                     if (abs($dob1->julianDay() - $dob2->julianDay()) < 2 && !$dob1->minimumDate()->d !== 0 && !$dob2->minimumDate()->d !== 0) {
                         // Exclude BEF, AFT, etc.
                         return I18N::translate('twin brother');
                     } elseif ($dob1->maximumJulianDay() < $dob2->minimumJulianDay()) {
                         return I18N::translate('younger brother');
                     } elseif ($dob1->minimumJulianDay() > $dob2->maximumJulianDay()) {
                         return I18N::translate('elder brother');
                     }
                 }
             }
             return I18N::translate('brother');
         case 'sis':
             if ($person1 && $person2) {
                 $dob1 = $person1->getBirthDate();
                 $dob2 = $person2->getBirthDate();
                 if ($dob1->isOK() && $dob2->isOK()) {
                     if (abs($dob1->julianDay() - $dob2->julianDay()) < 2 && !$dob1->minimumDate()->d !== 0 && !$dob2->minimumDate()->d !== 0) {
                         // Exclude BEF, AFT, etc.
                         return I18N::translate('twin sister');
                     } elseif ($dob1->maximumJulianDay() < $dob2->minimumJulianDay()) {
                         return I18N::translate('younger sister');
                     } elseif ($dob1->minimumJulianDay() > $dob2->maximumJulianDay()) {
                         return I18N::translate('elder sister');
                     }
                 }
             }
             return I18N::translate('sister');
         case 'sib':
             if ($person1 && $person2) {
                 $dob1 = $person1->getBirthDate();
                 $dob2 = $person2->getBirthDate();
                 if ($dob1->isOK() && $dob2->isOK()) {
                     if (abs($dob1->julianDay() - $dob2->julianDay()) < 2 && !$dob1->minimumDate()->d !== 0 && !$dob2->minimumDate()->d !== 0) {
                         // Exclude BEF, AFT, etc.
                         return I18N::translate('twin sibling');
                     } elseif ($dob1->maximumJulianDay() < $dob2->minimumJulianDay()) {
                         return I18N::translate('younger sibling');
                     } elseif ($dob1->minimumJulianDay() > $dob2->maximumJulianDay()) {
                         return I18N::translate('elder sibling');
                     }
                 }
             }
             return I18N::translate('sibling');
             // Level Two relationships
         // Level Two relationships
         case 'brochi':
             return I18N::translateContext('brother’s child', 'nephew/niece');
         case 'brodau':
             return I18N::translateContext('brother’s daughter', 'niece');
         case 'broson':
             return I18N::translateContext('brother’s son', 'nephew');
         case 'browif':
             return I18N::translateContext('brother’s wife', 'sister-in-law');
         case 'chichi':
             return I18N::translateContext('child’s child', 'grandchild');
         case 'chidau':
             return I18N::translateContext('child’s daughter', 'granddaughter');
         case 'chihus':
             return I18N::translateContext('child’s husband', 'son-in-law');
         case 'chison':
             return I18N::translateContext('child’s son', 'grandson');
         case 'chispo':
             return I18N::translateContext('child’s spouse', 'son/daughter-in-law');
         case 'chiwif':
             return I18N::translateContext('child’s wife', 'daughter-in-law');
         case 'dauchi':
             return I18N::translateContext('daughter’s child', 'grandchild');
         case 'daudau':
             return I18N::translateContext('daughter’s daughter', 'granddaughter');
         case 'dauhus':
             return I18N::translateContext('daughter’s husband', 'son-in-law');
         case 'dauson':
             return I18N::translateContext('daughter’s son', 'grandson');
         case 'fatbro':
             return I18N::translateContext('father’s brother', 'uncle');
         case 'fatchi':
             return I18N::translateContext('father’s child', 'half-sibling');
         case 'fatdau':
             return I18N::translateContext('father’s daughter', 'half-sister');
         case 'fatfat':
             return I18N::translateContext('father’s father', 'paternal grandfather');
         case 'fatmot':
             return I18N::translateContext('father’s mother', 'paternal grandmother');
         case 'fatpar':
             return I18N::translateContext('father’s parent', 'paternal grandparent');
         case 'fatsib':
             return I18N::translateContext('father’s sibling', 'aunt/uncle');
         case 'fatsis':
             return I18N::translateContext('father’s sister', 'aunt');
         case 'fatson':
             return I18N::translateContext('father’s son', 'half-brother');
         case 'fatwif':
             return I18N::translateContext('father’s wife', 'step-mother');
         case 'husbro':
             return I18N::translateContext('husband’s brother', 'brother-in-law');
         case 'huschi':
             return I18N::translateContext('husband’s child', 'step-child');
         case 'husdau':
             return I18N::translateContext('husband’s daughter', 'step-daughter');
         case 'husfat':
             return I18N::translateContext('husband’s father', 'father-in-law');
         case 'husmot':
             return I18N::translateContext('husband’s mother', 'mother-in-law');
         case 'hussib':
             return I18N::translateContext('husband’s sibling', 'brother/sister-in-law');
         case 'hussis':
             return I18N::translateContext('husband’s sister', 'sister-in-law');
         case 'husson':
             return I18N::translateContext('husband’s son', 'step-son');
         case 'motbro':
             return I18N::translateContext('mother’s brother', 'uncle');
         case 'motchi':
             return I18N::translateContext('mother’s child', 'half-sibling');
         case 'motdau':
             return I18N::translateContext('mother’s daughter', 'half-sister');
         case 'motfat':
             return I18N::translateContext('mother’s father', 'maternal grandfather');
         case 'mothus':
             return I18N::translateContext('mother’s husband', 'step-father');
         case 'motmot':
             return I18N::translateContext('mother’s mother', 'maternal grandmother');
         case 'motpar':
             return I18N::translateContext('mother’s parent', 'maternal grandparent');
         case 'motsib':
             return I18N::translateContext('mother’s sibling', 'aunt/uncle');
         case 'motsis':
             return I18N::translateContext('mother’s sister', 'aunt');
         case 'motson':
             return I18N::translateContext('mother’s son', 'half-brother');
         case 'parbro':
             return I18N::translateContext('parent’s brother', 'uncle');
         case 'parchi':
             return I18N::translateContext('parent’s child', 'half-sibling');
         case 'pardau':
             return I18N::translateContext('parent’s daughter', 'half-sister');
         case 'parfat':
             return I18N::translateContext('parent’s father', 'grandfather');
         case 'parmot':
             return I18N::translateContext('parent’s mother', 'grandmother');
         case 'parpar':
             return I18N::translateContext('parent’s parent', 'grandparent');
         case 'parsib':
             return I18N::translateContext('parent’s sibling', 'aunt/uncle');
         case 'parsis':
             return I18N::translateContext('parent’s sister', 'aunt');
         case 'parson':
             return I18N::translateContext('parent’s son', 'half-brother');
         case 'parspo':
             return I18N::translateContext('parent’s spouse', 'step-parent');
         case 'sibchi':
             return I18N::translateContext('sibling’s child', 'nephew/niece');
         case 'sibdau':
             return I18N::translateContext('sibling’s daughter', 'niece');
         case 'sibson':
             return I18N::translateContext('sibling’s son', 'nephew');
         case 'sibspo':
             return I18N::translateContext('sibling’s spouse', 'brother/sister-in-law');
         case 'sischi':
             return I18N::translateContext('sister’s child', 'nephew/niece');
         case 'sisdau':
             return I18N::translateContext('sister’s daughter', 'niece');
         case 'sishus':
             return I18N::translateContext('sister’s husband', 'brother-in-law');
         case 'sisson':
             return I18N::translateContext('sister’s son', 'nephew');
         case 'sonchi':
             return I18N::translateContext('son’s child', 'grandchild');
         case 'sondau':
             return I18N::translateContext('son’s daughter', 'granddaughter');
         case 'sonson':
             return I18N::translateContext('son’s son', 'grandson');
         case 'sonwif':
             return I18N::translateContext('son’s wife', 'daughter-in-law');
         case 'spobro':
             return I18N::translateContext('spouse’s brother', 'brother-in-law');
         case 'spochi':
             return I18N::translateContext('spouse’s child', 'step-child');
         case 'spodau':
             return I18N::translateContext('spouse’s daughter', 'step-daughter');
         case 'spofat':
             return I18N::translateContext('spouse’s father', 'father-in-law');
         case 'spomot':
             return I18N::translateContext('spouse’s mother', 'mother-in-law');
         case 'sposis':
             return I18N::translateContext('spouse’s sister', 'sister-in-law');
         case 'sposon':
             return I18N::translateContext('spouse’s son', 'step-son');
         case 'spopar':
             return I18N::translateContext('spouse’s parent', 'mother/father-in-law');
         case 'sposib':
             return I18N::translateContext('spouse’s sibling', 'brother/sister-in-law');
         case 'wifbro':
             return I18N::translateContext('wife’s brother', 'brother-in-law');
         case 'wifchi':
             return I18N::translateContext('wife’s child', 'step-child');
         case 'wifdau':
             return I18N::translateContext('wife’s daughter', 'step-daughter');
         case 'wiffat':
             return I18N::translateContext('wife’s father', 'father-in-law');
         case 'wifmot':
             return I18N::translateContext('wife’s mother', 'mother-in-law');
         case 'wifsib':
             return I18N::translateContext('wife’s sibling', 'brother/sister-in-law');
         case 'wifsis':
             return I18N::translateContext('wife’s sister', 'sister-in-law');
         case 'wifson':
             return I18N::translateContext('wife’s son', 'step-son');
             // Level Three relationships
             // I have commented out some of the unknown-sex relationships that are unlikely to to occur.
             // Feel free to add them in, if you think they might be needed
         // Level Three relationships
         // I have commented out some of the unknown-sex relationships that are unlikely to to occur.
         // Feel free to add them in, if you think they might be needed
         case 'brochichi':
             if ($sex1 === 'M') {
                 return I18N::translateContext('(a man’s) brother’s child’s child', 'great-nephew/niece');
             } else {
                 return I18N::translateContext('(a woman’s) brother’s child’s child', 'great-nephew/niece');
             }
         case 'brochidau':
             if ($sex1 === 'M') {
                 return I18N::translateContext('(a man’s) brother’s child’s daughter', 'great-niece');
             } else {
                 return I18N::translateContext('(a woman’s) brother’s child’s daughter', 'great-niece');
             }
         case 'brochison':
             if ($sex1 === 'M') {
                 return I18N::translateContext('(a man’s) brother’s child’s son', 'great-nephew');
             } else {
                 return I18N::translateContext('(a woman’s) brother’s child’s son', 'great-nephew');
             }
         case 'brodauchi':
             if ($sex1 === 'M') {
                 return I18N::translateContext('(a man’s) brother’s daughter’s child', 'great-nephew/niece');
             } else {
                 return I18N::translateContext('(a woman’s) brother’s daughter’s child', 'great-nephew/niece');
             }
         case 'brodaudau':
             if ($sex1 === 'M') {
                 return I18N::translateContext('(a man’s) brother’s daughter’s daughter', 'great-niece');
             } else {
                 return I18N::translateContext('(a woman’s) brother’s daughter’s daughter', 'great-niece');
             }
         case 'brodauhus':
             return I18N::translateContext('brother’s daughter’s husband', 'nephew-in-law');
         case 'brodauson':
             if ($sex1 === 'M') {
                 return I18N::translateContext('(a man’s) brother’s daughter’s son', 'great-nephew');
             } else {
                 return I18N::translateContext('(a woman’s) brother’s daughter’s son', 'great-nephew');
             }
         case 'brosonchi':
             if ($sex1 === 'M') {
                 return I18N::translateContext('(a man’s) brother’s son’s child', 'great-nephew/niece');
             } else {
                 return I18N::translateContext('(a woman’s) brother’s son’s child', 'great-nephew/niece');
             }
         case 'brosondau':
             if ($sex1 === 'M') {
                 return I18N::translateContext('(a man’s) brother’s son’s daughter', 'great-niece');
             } else {
                 return I18N::translateContext('(a woman’s) brother’s son’s daughter', 'great-niece');
             }
         case 'brosonson':
             if ($sex1 === 'M') {
                 return I18N::translateContext('(a man’s) brother’s son’s son', 'great-nephew');
             } else {
                 return I18N::translateContext('(a woman’s) brother’s son’s son', 'great-nephew');
             }
         case 'brosonwif':
             return I18N::translateContext('brother’s son’s wife', 'niece-in-law');
         case 'browifbro':
             return I18N::translateContext('brother’s wife’s brother', 'brother-in-law');
         case 'browifsib':
             return I18N::translateContext('brother’s wife’s sibling', 'brother/sister-in-law');
         case 'browifsis':
             return I18N::translateContext('brother’s wife’s sister', 'sister-in-law');
         case 'chichichi':
             return I18N::translateContext('child’s child’s child', 'great-grandchild');
         case 'chichidau':
             return I18N::translateContext('child’s child’s daughter', 'great-granddaughter');
         case 'chichison':
             return I18N::translateContext('child’s child’s son', 'great-grandson');
         case 'chidauchi':
             return I18N::translateContext('child’s daughter’s child', 'great-grandchild');
         case 'chidaudau':
             return I18N::translateContext('child’s daughter’s daughter', 'great-granddaughter');
         case 'chidauhus':
             return I18N::translateContext('child’s daughter’s husband', 'granddaughter’s husband');
         case 'chidauson':
             return I18N::translateContext('child’s daughter’s son', 'great-grandson');
         case 'chisonchi':
             return I18N::translateContext('child’s son’s child', 'great-grandchild');
         case 'chisondau':
             return I18N::translateContext('child’s son’s daughter', 'great-granddaughter');
         case 'chisonson':
             return I18N::translateContext('child’s son’s son', 'great-grandson');
         case 'chisonwif':
             return I18N::translateContext('child’s son’s wife', 'grandson’s wife');
         case 'dauchichi':
             return I18N::translateContext('daughter’s child’s child', 'great-grandchild');
         case 'dauchidau':
             return I18N::translateContext('daughter’s child’s daughter', 'great-granddaughter');
         case 'dauchison':
             return I18N::translateContext('daughter’s child’s son', 'great-grandson');
         case 'daudauchi':
             return I18N::translateContext('daughter’s daughter’s child', 'great-grandchild');
         case 'daudaudau':
             return I18N::translateContext('daughter’s daughter’s daughter', 'great-granddaughter');
         case 'daudauhus':
             return I18N::translateContext('daughter’s daughter’s husband', 'granddaughter’s husband');
         case 'daudauson':
             return I18N::translateContext('daughter’s daughter’s son', 'great-grandson');
         case 'dauhusfat':
             return I18N::translateContext('daughter’s husband’s father', 'son-in-law’s father');
         case 'dauhusmot':
             return I18N::translateContext('daughter’s husband’s mother', 'son-in-law’s mother');
         case 'dauhuspar':
             return I18N::translateContext('daughter’s husband’s parent', 'son-in-law’s parent');
         case 'dausonchi':
             return I18N::translateContext('daughter’s son’s child', 'great-grandchild');
         case 'dausondau':
             return I18N::translateContext('daughter’s son’s daughter', 'great-granddaughter');
         case 'dausonson':
             return I18N::translateContext('daughter’s son’s son', 'great-grandson');
         case 'dausonwif':
             return I18N::translateContext('daughter’s son’s wife', 'grandson’s wife');
         case 'fatbrochi':
             return I18N::translateContext('father’s brother’s child', 'first cousin');
         case 'fatbrodau':
             return I18N::translateContext('father’s brother’s daughter', 'first cousin');
         case 'fatbroson':
             return I18N::translateContext('father’s brother’s son', 'first cousin');
         case 'fatbrowif':
             return I18N::translateContext('father’s brother’s wife', 'aunt');
         case 'fatfatbro':
             return I18N::translateContext('father’s father’s brother', 'great-uncle');
         case 'fatfatfat':
             return I18N::translateContext('father’s father’s father', 'great-grandfather');
         case 'fatfatmot':
             return I18N::translateContext('father’s father’s mother', 'great-grandmother');
         case 'fatfatpar':
             return I18N::translateContext('father’s father’s parent', 'great-grandparent');
         case 'fatfatsib':
             return I18N::translateContext('father’s father’s sibling', 'great-aunt/uncle');
         case 'fatfatsis':
             return I18N::translateContext('father’s father’s sister', 'great-aunt');
         case 'fatmotbro':
             return I18N::translateContext('father’s mother’s brother', 'great-uncle');
         case 'fatmotfat':
             return I18N::translateContext('father’s mother’s father', 'great-grandfather');
         case 'fatmotmot':
             return I18N::translateContext('father’s mother’s mother', 'great-grandmother');
         case 'fatmotpar':
             return I18N::translateContext('father’s mother’s parent', 'great-grandparent');
         case 'fatmotsib':
             return I18N::translateContext('father’s mother’s sibling', 'great-aunt/uncle');
         case 'fatmotsis':
             return I18N::translateContext('father’s mother’s sister', 'great-aunt');
         case 'fatparbro':
             return I18N::translateContext('father’s parent’s brother', 'great-uncle');
         case 'fatparfat':
             return I18N::translateContext('father’s parent’s father', 'great-grandfather');
         case 'fatparmot':
             return I18N::translateContext('father’s parent’s mother', 'great-grandmother');
         case 'fatparpar':
             return I18N::translateContext('father’s parent’s parent', 'great-grandparent');
         case 'fatparsib':
             return I18N::translateContext('father’s parent’s sibling', 'great-aunt/uncle');
         case 'fatparsis':
             return I18N::translateContext('father’s parent’s sister', 'great-aunt');
         case 'fatsischi':
             return I18N::translateContext('father’s sister’s child', 'first cousin');
         case 'fatsisdau':
             return I18N::translateContext('father’s sister’s daughter', 'first cousin');
         case 'fatsishus':
             return I18N::translateContext('father’s sister’s husband', 'uncle');
         case 'fatsisson':
             return I18N::translateContext('father’s sister’s son', 'first cousin');
         case 'fatwifchi':
             return I18N::translateContext('father’s wife’s child', 'step-sibling');
         case 'fatwifdau':
             return I18N::translateContext('father’s wife’s daughter', 'step-sister');
         case 'fatwifson':
             return I18N::translateContext('father’s wife’s son', 'step-brother');
         case 'husbrowif':
             return I18N::translateContext('husband’s brother’s wife', 'sister-in-law');
         case 'hussishus':
             return I18N::translateContext('husband’s sister’s husband', 'brother-in-law');
         case 'motbrochi':
             return I18N::translateContext('mother’s brother’s child', 'first cousin');
         case 'motbrodau':
             return I18N::translateContext('mother’s brother’s daughter', 'first cousin');
         case 'motbroson':
             return I18N::translateContext('mother’s brother’s son', 'first cousin');
         case 'motbrowif':
             return I18N::translateContext('mother’s brother’s wife', 'aunt');
         case 'motfatbro':
             return I18N::translateContext('mother’s father’s brother', 'great-uncle');
         case 'motfatfat':
             return I18N::translateContext('mother’s father’s father', 'great-grandfather');
         case 'motfatmot':
             return I18N::translateContext('mother’s father’s mother', 'great-grandmother');
         case 'motfatpar':
             return I18N::translateContext('mother’s father’s parent', 'great-grandparent');
         case 'motfatsib':
             return I18N::translateContext('mother’s father’s sibling', 'great-aunt/uncle');
         case 'motfatsis':
             return I18N::translateContext('mother’s father’s sister', 'great-aunt');
         case 'mothuschi':
             return I18N::translateContext('mother’s husband’s child', 'step-sibling');
         case 'mothusdau':
             return I18N::translateContext('mother’s husband’s daughter', 'step-sister');
         case 'mothusson':
             return I18N::translateContext('mother’s husband’s son', 'step-brother');
         case 'motmotbro':
             return I18N::translateContext('mother’s mother’s brother', 'great-uncle');
         case 'motmotfat':
             return I18N::translateContext('mother’s mother’s father', 'great-grandfather');
         case 'motmotmot':
             return I18N::translateContext('mother’s mother’s mother', 'great-grandmother');
         case 'motmotpar':
             return I18N::translateContext('mother’s mother’s parent', 'great-grandparent');
         case 'motmotsib':
             return I18N::translateContext('mother’s mother’s sibling', 'great-aunt/uncle');
         case 'motmotsis':
             return I18N::translateContext('mother’s mother’s sister', 'great-aunt');
         case 'motparbro':
             return I18N::translateContext('mother’s parent’s brother', 'great-uncle');
         case 'motparfat':
             return I18N::translateContext('mother’s parent’s father', 'great-grandfather');
         case 'motparmot':
             return I18N::translateContext('mother’s parent’s mother', 'great-grandmother');
         case 'motparpar':
             return I18N::translateContext('mother’s parent’s parent', 'great-grandparent');
         case 'motparsib':
             return I18N::translateContext('mother’s parent’s sibling', 'great-aunt/uncle');
         case 'motparsis':
             return I18N::translateContext('mother’s parent’s sister', 'great-aunt');
         case 'motsischi':
             return I18N::translateContext('mother’s sister’s child', 'first cousin');
         case 'motsisdau':
             return I18N::translateContext('mother’s sister’s daughter', 'first cousin');
         case 'motsishus':
             return I18N::translateContext('mother’s sister’s husband', 'uncle');
         case 'motsisson':
             return I18N::translateContext('mother’s sister’s son', 'first cousin');
         case 'parbrowif':
             return I18N::translateContext('parent’s brother’s wife', 'aunt');
         case 'parfatbro':
             return I18N::translateContext('parent’s father’s brother', 'great-uncle');
         case 'parfatfat':
             return I18N::translateContext('parent’s father’s father', 'great-grandfather');
         case 'parfatmot':
             return I18N::translateContext('parent’s father’s mother', 'great-grandmother');
         case 'parfatpar':
             return I18N::translateContext('parent’s father’s parent', 'great-grandparent');
         case 'parfatsib':
             return I18N::translateContext('parent’s father’s sibling', 'great-aunt/uncle');
         case 'parfatsis':
             return I18N::translateContext('parent’s father’s sister', 'great-aunt');
         case 'parmotbro':
             return I18N::translateContext('parent’s mother’s brother', 'great-uncle');
         case 'parmotfat':
             return I18N::translateContext('parent’s mother’s father', 'great-grandfather');
         case 'parmotmot':
             return I18N::translateContext('parent’s mother’s mother', 'great-grandmother');
         case 'parmotpar':
             return I18N::translateContext('parent’s mother’s parent', 'great-grandparent');
         case 'parmotsib':
             return I18N::translateContext('parent’s mother’s sibling', 'great-aunt/uncle');
         case 'parmotsis':
             return I18N::translateContext('parent’s mother’s sister', 'great-aunt');
         case 'parparbro':
             return I18N::translateContext('parent’s parent’s brother', 'great-uncle');
         case 'parparfat':
             return I18N::translateContext('parent’s parent’s father', 'great-grandfather');
         case 'parparmot':
             return I18N::translateContext('parent’s parent’s mother', 'great-grandmother');
         case 'parparpar':
             return I18N::translateContext('parent’s parent’s parent', 'great-grandparent');
         case 'parparsib':
             return I18N::translateContext('parent’s parent’s sibling', 'great-aunt/uncle');
         case 'parparsis':
             return I18N::translateContext('parent’s parent’s sister', 'great-aunt');
         case 'parsishus':
             return I18N::translateContext('parent’s sister’s husband', 'uncle');
         case 'parspochi':
             return I18N::translateContext('parent’s spouse’s child', 'step-sibling');
         case 'parspodau':
             return I18N::translateContext('parent’s spouse’s daughter', 'step-sister');
         case 'parsposon':
             return I18N::translateContext('parent’s spouse’s son', 'step-brother');
         case 'sibchichi':
             return I18N::translateContext('sibling’s child’s child', 'great-nephew/niece');
         case 'sibchidau':
             return I18N::translateContext('sibling’s child’s daughter', 'great-niece');
         case 'sibchison':
             return I18N::translateContext('sibling’s child’s son', 'great-nephew');
         case 'sibdauchi':
             return I18N::translateContext('sibling’s daughter’s child', 'great-nephew/niece');
         case 'sibdaudau':
             return I18N::translateContext('sibling’s daughter’s daughter', 'great-niece');
         case 'sibdauhus':
             return I18N::translateContext('sibling’s daughter’s husband', 'nephew-in-law');
         case 'sibdauson':
             return I18N::translateContext('sibling’s daughter’s son', 'great-nephew');
         case 'sibsonchi':
             return I18N::translateContext('sibling’s son’s child', 'great-nephew/niece');
         case 'sibsondau':
             return I18N::translateContext('sibling’s son’s daughter', 'great-niece');
         case 'sibsonson':
             return I18N::translateContext('sibling’s son’s son', 'great-nephew');
         case 'sibsonwif':
             return I18N::translateContext('sibling’s son’s wife', 'niece-in-law');
         case 'sischichi':
             if ($sex1 === 'M') {
                 return I18N::translateContext('(a man’s) sister’s child’s child', 'great-nephew/niece');
             } else {
                 return I18N::translateContext('(a woman’s) sister’s child’s child', 'great-nephew/niece');
             }
         case 'sischidau':
             if ($sex1 === 'M') {
                 return I18N::translateContext('(a man’s) sister’s child’s daughter', 'great-niece');
             } else {
                 return I18N::translateContext('(a woman’s) sister’s child’s daughter', 'great-niece');
             }
         case 'sischison':
             if ($sex1 === 'M') {
                 return I18N::translateContext('(a man’s) sister’s child’s son', 'great-nephew');
             } else {
                 return I18N::translateContext('(a woman’s) sister’s child’s son', 'great-nephew');
             }
         case 'sisdauchi':
             if ($sex1 === 'M') {
                 return I18N::translateContext('(a man’s) sister’s daughter’s child', 'great-nephew/niece');
             } else {
                 return I18N::translateContext('(a woman’s) sister’s daughter’s child', 'great-nephew/niece');
             }
         case 'sisdaudau':
             if ($sex1 === 'M') {
                 return I18N::translateContext('(a man’s) sister’s daughter’s daughter', 'great-niece');
             } else {
                 return I18N::translateContext('(a woman’s) sister’s daughter’s daughter', 'great-niece');
             }
         case 'sisdauhus':
             return I18N::translateContext('sisters’s daughter’s husband', 'nephew-in-law');
         case 'sisdauson':
             if ($sex1 === 'M') {
                 return I18N::translateContext('(a man’s) sister’s daughter’s son', 'great-nephew');
             } else {
                 return I18N::translateContext('(a woman’s) sister’s daughter’s son', 'great-nephew');
             }
         case 'sishusbro':
             return I18N::translateContext('sister’s husband’s brother', 'brother-in-law');
         case 'sishussib':
             return I18N::translateContext('sister’s husband’s sibling', 'brother/sister-in-law');
         case 'sishussis':
             return I18N::translateContext('sister’s husband’s sister', 'sister-in-law');
         case 'sissonchi':
             if ($sex1 === 'M') {
                 return I18N::translateContext('(a man’s) sister’s son’s child', 'great-nephew/niece');
             } else {
                 return I18N::translateContext('(a woman’s) sister’s son’s child', 'great-nephew/niece');
             }
         case 'sissondau':
             if ($sex1 === 'M') {
                 return I18N::translateContext('(a man’s) sister’s son’s daughter', 'great-niece');
             } else {
                 return I18N::translateContext('(a woman’s) sister’s son’s daughter', 'great-niece');
             }
         case 'sissonson':
             if ($sex1 === 'M') {
                 return I18N::translateContext('(a man’s) sister’s son’s son', 'great-nephew');
             } else {
                 return I18N::translateContext('(a woman’s) sister’s son’s son', 'great-nephew');
             }
         case 'sissonwif':
             return I18N::translateContext('sisters’s son’s wife', 'niece-in-law');
         case 'sonchichi':
             return I18N::translateContext('son’s child’s child', 'great-grandchild');
         case 'sonchidau':
             return I18N::translateContext('son’s child’s daughter', 'great-granddaughter');
         case 'sonchison':
             return I18N::translateContext('son’s child’s son', 'great-grandson');
         case 'sondauchi':
             return I18N::translateContext('son’s daughter’s child', 'great-grandchild');
         case 'sondaudau':
             return I18N::translateContext('son’s daughter’s daughter', 'great-granddaughter');
         case 'sondauhus':
             return I18N::translateContext('son’s daughter’s husband', 'granddaughter’s husband');
         case 'sondauson':
             return I18N::translateContext('son’s daughter’s son', 'great-grandson');
         case 'sonsonchi':
             return I18N::translateContext('son’s son’s child', 'great-grandchild');
         case 'sonsondau':
             return I18N::translateContext('son’s son’s daughter', 'great-granddaughter');
         case 'sonsonson':
             return I18N::translateContext('son’s son’s son', 'great-grandson');
         case 'sonsonwif':
             return I18N::translateContext('son’s son’s wife', 'grandson’s wife');
         case 'sonwiffat':
             return I18N::translateContext('son’s wife’s father', 'daughter-in-law’s father');
         case 'sonwifmot':
             return I18N::translateContext('son’s wife’s mother', 'daughter-in-law’s mother');
         case 'sonwifpar':
             return I18N::translateContext('son’s wife’s parent', 'daughter-in-law’s parent');
         case 'wifbrowif':
             return I18N::translateContext('wife’s brother’s wife', 'sister-in-law');
         case 'wifsishus':
             return I18N::translateContext('wife’s sister’s husband', 'brother-in-law');
             // Some “special case” level four relationships that have specific names in certain languages
         // Some “special case” level four relationships that have specific names in certain languages
         case 'fatfatbrowif':
             return I18N::translateContext('father’s father’s brother’s wife', 'great-aunt');
         case 'fatfatsibspo':
             return I18N::translateContext('father’s father’s sibling’s spouse', 'great-aunt/uncle');
         case 'fatfatsishus':
             return I18N::translateContext('father’s father’s sister’s husband', 'great-uncle');
         case 'fatmotbrowif':
             return I18N::translateContext('father’s mother’s brother’s wife', 'great-aunt');
         case 'fatmotsibspo':
             return I18N::translateContext('father’s mother’s sibling’s spouse', 'great-aunt/uncle');
         case 'fatmotsishus':
             return I18N::translateContext('father’s mother’s sister’s husband', 'great-uncle');
         case 'fatparbrowif':
             return I18N::translateContext('father’s parent’s brother’s wife', 'great-aunt');
         case 'fatparsibspo':
             return I18N::translateContext('father’s parent’s sibling’s spouse', 'great-aunt/uncle');
         case 'fatparsishus':
             return I18N::translateContext('father’s parent’s sister’s husband', 'great-uncle');
         case 'motfatbrowif':
             return I18N::translateContext('mother’s father’s brother’s wife', 'great-aunt');
         case 'motfatsibspo':
             return I18N::translateContext('mother’s father’s sibling’s spouse', 'great-aunt/uncle');
         case 'motfatsishus':
             return I18N::translateContext('mother’s father’s sister’s husband', 'great-uncle');
         case 'motmotbrowif':
             return I18N::translateContext('mother’s mother’s brother’s wife', 'great-aunt');
         case 'motmotsibspo':
             return I18N::translateContext('mother’s mother’s sibling’s spouse', 'great-aunt/uncle');
         case 'motmotsishus':
             return I18N::translateContext('mother’s mother’s sister’s husband', 'great-uncle');
         case 'motparbrowif':
             return I18N::translateContext('mother’s parent’s brother’s wife', 'great-aunt');
         case 'motparsibspo':
             return I18N::translateContext('mother’s parent’s sibling’s spouse', 'great-aunt/uncle');
         case 'motparsishus':
             return I18N::translateContext('mother’s parent’s sister’s husband', 'great-uncle');
         case 'parfatbrowif':
             return I18N::translateContext('parent’s father’s brother’s wife', 'great-aunt');
         case 'parfatsibspo':
             return I18N::translateContext('parent’s father’s sibling’s spouse', 'great-aunt/uncle');
         case 'parfatsishus':
             return I18N::translateContext('parent’s father’s sister’s husband', 'great-uncle');
         case 'parmotbrowif':
             return I18N::translateContext('parent’s mother’s brother’s wife', 'great-aunt');
         case 'parmotsibspo':
             return I18N::translateContext('parent’s mother’s sibling’s spouse', 'great-aunt/uncle');
         case 'parmotsishus':
             return I18N::translateContext('parent’s mother’s sister’s husband', 'great-uncle');
         case 'parparbrowif':
             return I18N::translateContext('parent’s parent’s brother’s wife', 'great-aunt');
         case 'parparsibspo':
             return I18N::translateContext('parent’s parent’s sibling’s spouse', 'great-aunt/uncle');
         case 'parparsishus':
             return I18N::translateContext('parent’s parent’s sister’s husband', 'great-uncle');
         case 'fatfatbrodau':
             return I18N::translateContext('father’s father’s brother’s daughter', 'first cousin once removed ascending');
         case 'fatfatbroson':
             return I18N::translateContext('father’s father’s brother’s son', 'first cousin once removed ascending');
         case 'fatfatbrochi':
             return I18N::translateContext('father’s father’s brother’s child', 'first cousin once removed ascending');
         case 'fatfatsisdau':
             return I18N::translateContext('father’s father’s sister’s daughter', 'first cousin once removed ascending');
         case 'fatfatsisson':
             return I18N::translateContext('father’s father’s sister’s son', 'first cousin once removed ascending');
         case 'fatfatsischi':
             return I18N::translateContext('father’s father’s sister’s child', 'first cousin once removed ascending');
         case 'fatmotbrodau':
             return I18N::translateContext('father’s mother’s brother’s daughter', 'first cousin once removed ascending');
         case 'fatmotbroson':
             return I18N::translateContext('father’s mother’s brother’s son', 'first cousin once removed ascending');
         case 'fatmotbrochi':
             return I18N::translateContext('father’s mother’s brother’s child', 'first cousin once removed ascending');
         case 'fatmotsisdau':
             return I18N::translateContext('father’s mother’s sister’s daughter', 'first cousin once removed ascending');
         case 'fatmotsisson':
             return I18N::translateContext('father’s mother’s sister’s son', 'first cousin once removed ascending');
         case 'fatmotsischi':
             return I18N::translateContext('father’s mother’s sister’s child', 'first cousin once removed ascending');
         case 'motfatbrodau':
             return I18N::translateContext('mother’s father’s brother’s daughter', 'first cousin once removed ascending');
         case 'motfatbroson':
             return I18N::translateContext('mother’s father’s brother’s son', 'first cousin once removed ascending');
         case 'motfatbrochi':
             return I18N::translateContext('mother’s father’s brother’s child', 'first cousin once removed ascending');
         case 'motfatsisdau':
             return I18N::translateContext('mother’s father’s sister’s daughter', 'first cousin once removed ascending');
         case 'motfatsisson':
             return I18N::translateContext('mother’s father’s sister’s son', 'first cousin once removed ascending');
         case 'motfatsischi':
             return I18N::translateContext('mother’s father’s sister’s child', 'first cousin once removed ascending');
         case 'motmotbrodau':
             return I18N::translateContext('mother’s mother’s brother’s daughter', 'first cousin once removed ascending');
         case 'motmotbroson':
             return I18N::translateContext('mother’s mother’s brother’s son', 'first cousin once removed ascending');
         case 'motmotbrochi':
             return I18N::translateContext('mother’s mother’s brother’s child', 'first cousin once removed ascending');
         case 'motmotsisdau':
             return I18N::translateContext('mother’s mother’s sister’s daughter', 'first cousin once removed ascending');
         case 'motmotsisson':
             return I18N::translateContext('mother’s mother’s sister’s son', 'first cousin once removed ascending');
         case 'motmotsischi':
             return I18N::translateContext('mother’s mother’s sister’s child', 'first cousin once removed ascending');
     }
     // Some “special case” level five relationships that have specific names in certain languages
     if (preg_match('/^(mot|fat|par)fatbro(son|dau|chi)dau$/', $path)) {
         return I18N::translateContext('grandfather’s brother’s granddaughter', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)fatbro(son|dau|chi)son$/', $path)) {
         return I18N::translateContext('grandfather’s brother’s grandson', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)fatbro(son|dau|chi)chi$/', $path)) {
         return I18N::translateContext('grandfather’s brother’s grandchild', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)fatsis(son|dau|chi)dau$/', $path)) {
         return I18N::translateContext('grandfather’s sister’s granddaughter', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)fatsis(son|dau|chi)son$/', $path)) {
         return I18N::translateContext('grandfather’s sister’s grandson', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)fatsis(son|dau|chi)chi$/', $path)) {
         return I18N::translateContext('grandfather’s sister’s grandchild', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)fatsib(son|dau|chi)dau$/', $path)) {
         return I18N::translateContext('grandfather’s sibling’s granddaughter', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)fatsib(son|dau|chi)son$/', $path)) {
         return I18N::translateContext('grandfather’s sibling’s grandson', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)fatsib(son|dau|chi)chi$/', $path)) {
         return I18N::translateContext('grandfather’s sibling’s grandchild', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)motbro(son|dau|chi)dau$/', $path)) {
         return I18N::translateContext('grandmother’s brother’s granddaughter', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)motbro(son|dau|chi)son$/', $path)) {
         return I18N::translateContext('grandmother’s brother’s grandson', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)motbro(son|dau|chi)chi$/', $path)) {
         return I18N::translateContext('grandmother’s brother’s grandchild', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)motsis(son|dau|chi)dau$/', $path)) {
         return I18N::translateContext('grandmother’s sister’s granddaughter', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)motsis(son|dau|chi)son$/', $path)) {
         return I18N::translateContext('grandmother’s sister’s grandson', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)motsis(son|dau|chi)chi$/', $path)) {
         return I18N::translateContext('grandmother’s sister’s grandchild', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)motsib(son|dau|chi)dau$/', $path)) {
         return I18N::translateContext('grandmother’s sibling’s granddaughter', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)motsib(son|dau|chi)son$/', $path)) {
         return I18N::translateContext('grandmother’s sibling’s grandson', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)motsib(son|dau|chi)chi$/', $path)) {
         return I18N::translateContext('grandmother’s sibling’s grandchild', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)parbro(son|dau|chi)dau$/', $path)) {
         return I18N::translateContext('grandparent’s brother’s granddaughter', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)parbro(son|dau|chi)son$/', $path)) {
         return I18N::translateContext('grandparent’s brother’s grandson', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)parbro(son|dau|chi)chi$/', $path)) {
         return I18N::translateContext('grandparent’s brother’s grandchild', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)parsis(son|dau|chi)dau$/', $path)) {
         return I18N::translateContext('grandparent’s sister’s granddaughter', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)parsis(son|dau|chi)son$/', $path)) {
         return I18N::translateContext('grandparent’s sister’s grandson', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)parsis(son|dau|chi)chi$/', $path)) {
         return I18N::translateContext('grandparent’s sister’s grandchild', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)parsib(son|dau|chi)dau$/', $path)) {
         return I18N::translateContext('grandparent’s sibling’s granddaughter', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)parsib(son|dau|chi)son$/', $path)) {
         return I18N::translateContext('grandparent’s sibling’s grandson', 'second cousin');
     } elseif (preg_match('/^(mot|fat|par)parsib(son|dau|chi)chi$/', $path)) {
         return I18N::translateContext('grandparent’s sibling’s grandchild', 'second cousin');
     }
     // Look for generic/pattern relationships.
     if (preg_match('/^((?:mot|fat|par)+)(bro|sis|sib)$/', $path, $match)) {
         // siblings of direct ancestors
         $up = strlen($match[1]) / 3;
         $bef_last = substr($path, -6, 3);
         switch ($up) {
             case 3:
                 switch ($sex2) {
                     case 'M':
                         if ($bef_last === 'fat') {
                             return I18N::translateContext('great-grandfather’s brother', 'great-great-uncle');
                         } elseif ($bef_last === 'mot') {
                             return I18N::translateContext('great-grandmother’s brother', 'great-great-uncle');
                         } else {
                             return I18N::translateContext('great-grandparent’s brother', 'great-great-uncle');
                         }
                     case 'F':
                         return I18N::translate('great-great-aunt');
                     default:
                         return I18N::translate('great-great-aunt/uncle');
                 }
             case 4:
                 switch ($sex2) {
                     case 'M':
                         if ($bef_last === 'fat') {
                             return I18N::translateContext('great-great-grandfather’s brother', 'great-great-great-uncle');
                         } elseif ($bef_last === 'mot') {
                             return I18N::translateContext('great-great-grandmother’s brother', 'great-great-great-uncle');
                         } else {
                             return I18N::translateContext('great-great-grandparent’s brother', 'great-great-great-uncle');
                         }
                     case 'F':
                         return I18N::translate('great-great-great-aunt');
                     default:
                         return I18N::translate('great-great-great-aunt/uncle');
                 }
             case 5:
                 switch ($sex2) {
                     case 'M':
                         if ($bef_last === 'fat') {
                             return I18N::translateContext('great-great-great-grandfather’s brother', 'great ×4 uncle');
                         } elseif ($bef_last === 'mot') {
                             return I18N::translateContext('great-great-great-grandmother’s brother', 'great ×4 uncle');
                         } else {
                             return I18N::translateContext('great-great-great-grandparent’s brother', 'great ×4 uncle');
                         }
                     case 'F':
                         return I18N::translate('great ×4 aunt');
                     default:
                         return I18N::translate('great ×4 aunt/uncle');
                 }
             case 6:
                 switch ($sex2) {
                     case 'M':
                         if ($bef_last === 'fat') {
                             return I18N::translateContext('great ×4 grandfather’s brother', 'great ×5 uncle');
                         } elseif ($bef_last === 'mot') {
                             return I18N::translateContext('great ×4 grandmother’s brother', 'great ×5 uncle');
                         } else {
                             return I18N::translateContext('great ×4 grandparent’s brother', 'great ×5 uncle');
                         }
                     case 'F':
                         return I18N::translate('great ×5 aunt');
                     default:
                         return I18N::translate('great ×5 aunt/uncle');
                 }
             case 7:
                 switch ($sex2) {
                     case 'M':
                         if ($bef_last === 'fat') {
                             return I18N::translateContext('great ×5 grandfather’s brother', 'great ×6 uncle');
                         } elseif ($bef_last === 'mot') {
                             return I18N::translateContext('great ×5 grandmother’s brother', 'great ×6 uncle');
                         } else {
                             return I18N::translateContext('great ×5 grandparent’s brother', 'great ×6 uncle');
                         }
                     case 'F':
                         return I18N::translate('great ×6 aunt');
                     default:
                         return I18N::translate('great ×6 aunt/uncle');
                 }
             case 8:
                 switch ($sex2) {
                     case 'M':
                         if ($bef_last === 'fat') {
                             return I18N::translateContext('great ×6 grandfather’s brother', 'great ×7 uncle');
                         } elseif ($bef_last === 'mot') {
                             return I18N::translateContext('great ×6 grandmother’s brother', 'great ×7 uncle');
                         } else {
                             return I18N::translateContext('great ×6 grandparent’s brother', 'great ×7 uncle');
                         }
                     case 'F':
                         return I18N::translate('great ×7 aunt');
                     default:
                         return I18N::translate('great ×7 aunt/uncle');
                 }
             default:
                 // Different languages have different rules for naming generations.
                 // An English great ×12 uncle is a Danish great ×10 uncle.
                 //
                 // Need to find out which languages use which rules.
                 switch (WT_LOCALE) {
                     case 'da':
                         switch ($sex2) {
                             case 'M':
                                 return I18N::translate('great ×%s uncle', I18N::number($up - 4));
                             case 'F':
                                 return I18N::translate('great ×%s aunt', I18N::number($up - 4));
                             default:
                                 return I18N::translate('great ×%s aunt/uncle', I18N::number($up - 4));
                         }
                     case 'pl':
                         switch ($sex2) {
                             case 'M':
                                 if ($bef_last === 'fat') {
                                     return I18N::translateContext('great ×(%s-1) grandfather’s brother', 'great ×%s uncle', I18N::number($up - 2));
                                 } elseif ($bef_last === 'mot') {
                                     return I18N::translateContext('great ×(%s-1) grandmother’s brother', 'great ×%s uncle', I18N::number($up - 2));
                                 } else {
                                     return I18N::translateContext('great ×(%s-1) grandparent’s brother', 'great ×%s uncle', I18N::number($up - 2));
                                 }
                             case 'F':
                                 return I18N::translate('great ×%s aunt', I18N::number($up - 2));
                             default:
                                 return I18N::translate('great ×%s aunt/uncle', I18N::number($up - 2));
                         }
                     case 'it':
                         // Source: Michele Locati
                     // Source: Michele Locati
                     case 'en_AU':
                     case 'en_GB':
                     case 'en_US':
                     default:
                         switch ($sex2) {
                             case 'M':
                                 // I18N: if you need a different number for %s, contact the developers, as a code-change is required
                                 return I18N::translate('great ×%s uncle', I18N::number($up - 1));
                             case 'F':
                                 return I18N::translate('great ×%s aunt', I18N::number($up - 1));
                             default:
                                 return I18N::translate('great ×%s aunt/uncle', I18N::number($up - 1));
                         }
                 }
         }
     }
     if (preg_match('/^(?:bro|sis|sib)((?:son|dau|chi)+)$/', $path, $match)) {
         // direct descendants of siblings
         $down = strlen($match[1]) / 3 + 1;
         // Add one, as we count generations from the common ancestor
         $first = substr($path, 0, 3);
         switch ($down) {
             case 4:
                 switch ($sex2) {
                     case 'M':
                         if ($first === 'bro' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) brother’s great-grandson', 'great-great-nephew');
                         } elseif ($first === 'sis' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) sister’s great-grandson', 'great-great-nephew');
                         } else {
                             return I18N::translateContext('(a woman’s) great-great-nephew', 'great-great-nephew');
                         }
                     case 'F':
                         if ($first === 'bro' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) brother’s great-granddaughter', 'great-great-niece');
                         } elseif ($first === 'sis' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) sister’s great-granddaughter', 'great-great-niece');
                         } else {
                             return I18N::translateContext('(a woman’s) great-great-niece', 'great-great-niece');
                         }
                     default:
                         if ($first === 'bro' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) brother’s great-grandchild', 'great-great-nephew/niece');
                         } elseif ($first === 'sis' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) sister’s great-grandchild', 'great-great-nephew/niece');
                         } else {
                             return I18N::translateContext('(a woman’s) great-great-nephew/niece', 'great-great-nephew/niece');
                         }
                 }
             case 5:
                 switch ($sex2) {
                     case 'M':
                         if ($first === 'bro' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) brother’s great-great-grandson', 'great-great-great-nephew');
                         } elseif ($first === 'sis' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) sister’s great-great-grandson', 'great-great-great-nephew');
                         } else {
                             return I18N::translateContext('(a woman’s) great-great-great-nephew', 'great-great-great-nephew');
                         }
                     case 'F':
                         if ($first === 'bro' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) brother’s great-great-granddaughter', 'great-great-great-niece');
                         } elseif ($first === 'sis' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) sister’s great-great-granddaughter', 'great-great-great-niece');
                         } else {
                             return I18N::translateContext('(a woman’s) great-great-great-niece', 'great-great-great-niece');
                         }
                     default:
                         if ($first === 'bro' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) brother’s great-great-grandchild', 'great-great-great-nephew/niece');
                         } elseif ($first === 'sis' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) sister’s great-great-grandchild', 'great-great-great-nephew/niece');
                         } else {
                             return I18N::translateContext('(a woman’s) great-great-great-nephew/niece', 'great-great-great-nephew/niece');
                         }
                 }
             case 6:
                 switch ($sex2) {
                     case 'M':
                         if ($first === 'bro' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) brother’s great-great-great-grandson', 'great ×4 nephew');
                         } elseif ($first === 'sis' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) sister’s great-great-great-grandson', 'great ×4 nephew');
                         } else {
                             return I18N::translateContext('(a woman’s) great ×4 nephew', 'great ×4 nephew');
                         }
                     case 'F':
                         if ($first === 'bro' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) brother’s great-great-great-granddaughter', 'great ×4 niece');
                         } elseif ($first === 'sis' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) sister’s great-great-great-granddaughter', 'great ×4 niece');
                         } else {
                             return I18N::translateContext('(a woman’s) great ×4 niece', 'great ×4 niece');
                         }
                     default:
                         if ($first === 'bro' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) brother’s great-great-great-grandchild', 'great ×4 nephew/niece');
                         } elseif ($first === 'sis' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) sister’s great-great-great-grandchild', 'great ×4 nephew/niece');
                         } else {
                             return I18N::translateContext('(a woman’s) great ×4 nephew/niece', 'great ×4 nephew/niece');
                         }
                 }
             case 7:
                 switch ($sex2) {
                     case 'M':
                         if ($first === 'bro' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) brother’s great ×4 grandson', 'great ×5 nephew');
                         } elseif ($first === 'sis' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) sister’s great ×4 grandson', 'great ×5 nephew');
                         } else {
                             return I18N::translateContext('(a woman’s) great ×5 nephew', 'great ×5 nephew');
                         }
                     case 'F':
                         if ($first === 'bro' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) brother’s great ×4 granddaughter', 'great ×5 niece');
                         } elseif ($first === 'sis' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) sister’s great ×4 granddaughter', 'great ×5 niece');
                         } else {
                             return I18N::translateContext('(a woman’s) great ×5 niece', 'great ×5 niece');
                         }
                     default:
                         if ($first === 'bro' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) brother’s great ×4 grandchild', 'great ×5 nephew/niece');
                         } elseif ($first === 'sis' && $sex1 === 'M') {
                             return I18N::translateContext('(a man’s) sister’s great ×4 grandchild', 'great ×5 nephew/niece');
                         } else {
                             return I18N::translateContext('(a woman’s) great ×5 nephew/niece', 'great ×5 nephew/niece');
                         }
                 }
             default:
                 // Different languages have different rules for naming generations.
                 // An English great ×12 nephew is a Polish great ×11 nephew.
                 //
                 // Need to find out which languages use which rules.
                 switch (WT_LOCALE) {
                     case 'pl':
                         // Source: Lukasz Wilenski
                         switch ($sex2) {
                             case 'M':
                                 if ($first === 'bro' && $sex1 === 'M') {
                                     return I18N::translateContext('(a man’s) brother’s great ×(%s-1) grandson', 'great ×%s nephew', I18N::number($down - 3));
                                 } elseif ($first === 'sis' && $sex1 === 'M') {
                                     return I18N::translateContext('(a man’s) sister’s great ×(%s-1) grandson', 'great ×%s nephew', I18N::number($down - 3));
                                 } else {
                                     return I18N::translateContext('(a woman’s) great ×%s nephew', 'great ×%s nephew', I18N::number($down - 3));
                                 }
                             case 'F':
                                 if ($first === 'bro' && $sex1 === 'M') {
                                     return I18N::translateContext('(a man’s) brother’s great ×(%s-1) granddaughter', 'great ×%s niece', I18N::number($down - 3));
                                 } elseif ($first === 'sis' && $sex1 === 'M') {
                                     return I18N::translateContext('(a man’s) sister’s great ×(%s-1) granddaughter', 'great ×%s niece', I18N::number($down - 3));
                                 } else {
                                     return I18N::translateContext('(a woman’s) great ×%s niece', 'great ×%s niece', I18N::number($down - 3));
                                 }
                             default:
                                 if ($first === 'bro' && $sex1 === 'M') {
                                     return I18N::translateContext('(a man’s) brother’s great ×(%s-1) grandchild', 'great ×%s nephew/niece', I18N::number($down - 3));
                                 } elseif ($first === 'sis' && $sex1 === 'M') {
                                     return I18N::translateContext('(a man’s) sister’s great ×(%s-1) grandchild', 'great ×%s nephew/niece', I18N::number($down - 3));
                                 } else {
                                     return I18N::translateContext('(a woman’s) great ×%s nephew/niece', 'great ×%s nephew/niece', I18N::number($down - 3));
                                 }
                         }
                     case 'he':
                         // Source: Meliza Amity
                         switch ($sex2) {
                             case 'M':
                                 return I18N::translate('great ×%s nephew', I18N::number($down - 1));
                             case 'F':
                                 return I18N::translate('great ×%s niece', I18N::number($down - 1));
                             default:
                                 return I18N::translate('great ×%s nephew/niece', I18N::number($down - 1));
                         }
                     case 'it':
                         // Source: Michele Locati.
                     // Source: Michele Locati.
                     case 'en_AU':
                     case 'en_GB':
                     case 'en_US':
                     default:
                         switch ($sex2) {
                             case 'M':
                                 // I18N: if you need a different number for %s, contact the developers, as a code-change is required
                                 return I18N::translate('great ×%s nephew', I18N::number($down - 2));
                             case 'F':
                                 return I18N::translate('great ×%s niece', I18N::number($down - 2));
                             default:
                                 return I18N::translate('great ×%s nephew/niece', I18N::number($down - 2));
                         }
                 }
         }
     }
     if (preg_match('/^((?:mot|fat|par)*)$/', $path, $match)) {
         // direct ancestors
         $up = strlen($match[1]) / 3;
         switch ($up) {
             case 4:
                 switch ($sex2) {
                     case 'M':
                         return I18N::translate('great-great-grandfather');
                     case 'F':
                         return I18N::translate('great-great-grandmother');
                     default:
                         return I18N::translate('great-great-grandparent');
                 }
             case 5:
                 switch ($sex2) {
                     case 'M':
                         return I18N::translate('great-great-great-grandfather');
                     case 'F':
                         return I18N::translate('great-great-great-grandmother');
                     default:
                         return I18N::translate('great-great-great-grandparent');
                 }
             case 6:
                 switch ($sex2) {
                     case 'M':
                         return I18N::translate('great ×4 grandfather');
                     case 'F':
                         return I18N::translate('great ×4 grandmother');
                     default:
                         return I18N::translate('great ×4 grandparent');
                 }
             case 7:
                 switch ($sex2) {
                     case 'M':
                         return I18N::translate('great ×5 grandfather');
                     case 'F':
                         return I18N::translate('great ×5 grandmother');
                     default:
                         return I18N::translate('great ×5 grandparent');
                 }
             case 8:
                 switch ($sex2) {
                     case 'M':
                         return I18N::translate('great ×6 grandfather');
                     case 'F':
                         return I18N::translate('great ×6 grandmother');
                     default:
                         return I18N::translate('great ×6 grandparent');
                 }
             case 9:
                 switch ($sex2) {
                     case 'M':
                         return I18N::translate('great ×7 grandfather');
                     case 'F':
                         return I18N::translate('great ×7 grandmother');
                     default:
                         return I18N::translate('great ×7 grandparent');
                 }
             default:
                 // Different languages have different rules for naming generations.
                 // An English great ×12 grandfather is a Danish great ×11 grandfather.
                 //
                 // Need to find out which languages use which rules.
                 switch (WT_LOCALE) {
                     case 'da':
                         // Source: Patrick Sorensen
                         switch ($sex2) {
                             case 'M':
                                 return I18N::translate('great ×%s grandfather', I18N::number($up - 3));
                             case 'F':
                                 return I18N::translate('great ×%s grandmother', I18N::number($up - 3));
                             default:
                                 return I18N::translate('great ×%s grandparent', I18N::number($up - 3));
                         }
                     case 'it':
                         // Source: Michele Locati
                     // Source: Michele Locati
                     case 'es':
                         // Source: Wes Groleau
                         switch ($sex2) {
                             case 'M':
                                 return I18N::translate('great ×%s grandfather', I18N::number($up));
                             case 'F':
                                 return I18N::translate('great ×%s grandmother', I18N::number($up));
                             default:
                                 return I18N::translate('great ×%s grandparent', I18N::number($up));
                         }
                     case 'fr':
                         // Source: Jacqueline Tetreault
                     // Source: Jacqueline Tetreault
                     case 'fr_CA':
                         switch ($sex2) {
                             case 'M':
                                 return I18N::translate('great ×%s grandfather', I18N::number($up - 1));
                             case 'F':
                                 return I18N::translate('great ×%s grandmother', I18N::number($up - 1));
                             default:
                                 return I18N::translate('great ×%s grandparent', I18N::number($up - 1));
                         }
                     case 'nn':
                         // Source: Hogne Røed Nilsen (https://bugs.launchpad.net/webtrees/+bug/1168553)
                     // Source: Hogne Røed Nilsen (https://bugs.launchpad.net/webtrees/+bug/1168553)
                     case 'nb':
                         switch ($sex2) {
                             case 'M':
                                 // I18N: if you need a different number for %s, contact the developers, as a code-change is required
                                 return I18N::translate('great ×%s grandfather', I18N::number($up - 3));
                             case 'F':
                                 return I18N::translate('great ×%s grandmother', I18N::number($up - 3));
                             default:
                                 return I18N::translate('great ×%s grandparent', I18N::number($up - 3));
                         }
                     case 'en_AU':
                     case 'en_GB':
                     case 'en_US':
                     default:
                         switch ($sex2) {
                             case 'M':
                                 // I18N: if you need a different number for %s, contact the developers, as a code-change is required
                                 return I18N::translate('great ×%s grandfather', I18N::number($up - 2));
                             case 'F':
                                 return I18N::translate('great ×%s grandmother', I18N::number($up - 2));
                             default:
                                 return I18N::translate('great ×%s grandparent', I18N::number($up - 2));
                         }
                 }
         }
     }
     if (preg_match('/^((?:son|dau|chi)*)$/', $path, $match)) {
         // direct descendants
         $up = strlen($match[1]) / 3;
         switch ($up) {
             case 4:
                 switch ($sex2) {
                     case 'M':
                         return I18N::translate('great-great-grandson');
                     case 'F':
                         return I18N::translate('great-great-granddaughter');
                     default:
                         return I18N::translate('great-great-grandchild');
                 }
             case 5:
                 switch ($sex2) {
                     case 'M':
                         return I18N::translate('great-great-great-grandson');
                     case 'F':
                         return I18N::translate('great-great-great-granddaughter');
                     default:
                         return I18N::translate('great-great-great-grandchild');
                 }
             case 6:
                 switch ($sex2) {
                     case 'M':
                         return I18N::translate('great ×4 grandson');
                     case 'F':
                         return I18N::translate('great ×4 granddaughter');
                     default:
                         return I18N::translate('great ×4 grandchild');
                 }
             case 7:
                 switch ($sex2) {
                     case 'M':
                         return I18N::translate('great ×5 grandson');
                     case 'F':
                         return I18N::translate('great ×5 granddaughter');
                     default:
                         return I18N::translate('great ×5 grandchild');
                 }
             case 8:
                 switch ($sex2) {
                     case 'M':
                         return I18N::translate('great ×6 grandson');
                     case 'F':
                         return I18N::translate('great ×6 granddaughter');
                     default:
                         return I18N::translate('great ×6 grandchild');
                 }
             case 9:
                 switch ($sex2) {
                     case 'M':
                         return I18N::translate('great ×7 grandson');
                     case 'F':
                         return I18N::translate('great ×7 granddaughter');
                     default:
                         return I18N::translate('great ×7 grandchild');
                 }
             default:
                 // Different languages have different rules for naming generations.
                 // An English great ×12 grandson is a Danish great ×11 grandson.
                 //
                 // Need to find out which languages use which rules.
                 switch (WT_LOCALE) {
                     case 'nn':
                         // Source: Hogne Røed Nilsen
                     // Source: Hogne Røed Nilsen
                     case 'nb':
                     case 'da':
                         // Source: Patrick Sorensen
                         switch ($sex2) {
                             case 'M':
                                 return I18N::translate('great ×%s grandson', I18N::number($up - 3));
                             case 'F':
                                 return I18N::translate('great ×%s granddaughter', I18N::number($up - 3));
                             default:
                                 return I18N::translate('great ×%s grandchild', I18N::number($up - 3));
                         }
                     case 'it':
                         // Source: Michele Locati
                     // Source: Michele Locati
                     case 'es':
                         // Source: Wes Groleau (adding doesn’t change behavior, but needs to be better researched)
                     // Source: Wes Groleau (adding doesn’t change behavior, but needs to be better researched)
                     case 'en_AU':
                     case 'en_GB':
                     case 'en_US':
                     default:
                         switch ($sex2) {
                             case 'M':
                                 // I18N: if you need a different number for %s, contact the developers, as a code-change is required
                                 return I18N::translate('great ×%s grandson', I18N::number($up - 2));
                             case 'F':
                                 return I18N::translate('great ×%s granddaughter', I18N::number($up - 2));
                             default:
                                 return I18N::translate('great ×%s grandchild', I18N::number($up - 2));
                         }
                 }
         }
     }
     if (preg_match('/^((?:mot|fat|par)+)(?:bro|sis|sib)((?:son|dau|chi)+)$/', $path, $match)) {
         // cousins in English
         $ascent = $match[1];
         $descent = $match[2];
         $up = strlen($ascent) / 3;
         $down = strlen($descent) / 3;
         $cousin = min($up, $down);
         // Moved out of switch (en/default case) so that
         $removed = abs($down - $up);
         // Spanish (and other languages) can use it, too.
         // Different languages have different rules for naming cousins.  For example,
         // an English “second cousin once removed” is a Polish “cousin of 7th degree”.
         //
         // Need to find out which languages use which rules.
         switch (WT_LOCALE) {
             case 'pl':
                 // Source: Lukasz Wilenski
                 return self::cousinName($up + $down + 2, $sex2);
             case 'it':
                 // Source: Michele Locati.  See italian_cousins_names.zip
                 // http://webtrees.net/forums/8-translation/1200-great-xn-grandparent?limit=6&start=6
                 return self::cousinName($up + $down - 3, $sex2);
             case 'es':
                 // Source: Wes Groleau.  See http://UniGen.us/Parentesco.html & http://UniGen.us/Parentesco-D.html
                 if ($down == $up) {
                     return self::cousinName($cousin, $sex2);
                 } elseif ($down < $up) {
                     return self::cousinName2($cousin + 1, $sex2, self::getRelationshipNameFromPath('sib' . $descent, null, null));
                 } else {
                     switch ($sex2) {
                         case 'M':
                             return self::cousinName2($cousin + 1, $sex2, self::getRelationshipNameFromPath('bro' . $descent, null, null));
                         case 'F':
                             return self::cousinName2($cousin + 1, $sex2, self::getRelationshipNameFromPath('sis' . $descent, null, null));
                         default:
                             return self::cousinName2($cousin + 1, $sex2, self::getRelationshipNameFromPath('sib' . $descent, null, null));
                     }
                 }
             case 'en_AU':
                 // See: http://en.wikipedia.org/wiki/File:CousinTree.svg
             // See: http://en.wikipedia.org/wiki/File:CousinTree.svg
             case 'en_GB':
             case 'en_US':
             default:
                 switch ($removed) {
                     case 0:
                         return self::cousinName($cousin, $sex2);
                     case 1:
                         if ($up > $down) {
                             /* I18N: %s=“fifth cousin”, etc. http://www.ancestry.com/learn/library/article.aspx?article=2856 */
                             return I18N::translate('%s once removed ascending', self::cousinName($cousin, $sex2));
                         } else {
                             /* I18N: %s=“fifth cousin”, etc. http://www.ancestry.com/learn/library/article.aspx?article=2856 */
                             return I18N::translate('%s once removed descending', self::cousinName($cousin, $sex2));
                         }
                     case 2:
                         if ($up > $down) {
                             /* I18N: %s=“fifth cousin”, etc. */
                             return I18N::translate('%s twice removed ascending', self::cousinName($cousin, $sex2));
                         } else {
                             /* I18N: %s=“fifth cousin”, etc. */
                             return I18N::translate('%s twice removed descending', self::cousinName($cousin, $sex2));
                         }
                     case 3:
                         if ($up > $down) {
                             /* I18N: %s=“fifth cousin”, etc. */
                             return I18N::translate('%s three times removed ascending', self::cousinName($cousin, $sex2));
                         } else {
                             /* I18N: %s=“fifth cousin”, etc. */
                             return I18N::translate('%s three times removed descending', self::cousinName($cousin, $sex2));
                         }
                     default:
                         if ($up > $down) {
                             /* I18N: %1$s=“fifth cousin”, etc., %2$s>=4 */
                             return I18N::translate('%1$s %2$s times removed ascending', self::cousinName($cousin, $sex2), I18N::number($removed));
                         } else {
                             /* I18N: %1$s=“fifth cousin”, etc., %2$s>=4 */
                             return I18N::translate('%1$s %2$s times removed descending', self::cousinName($cousin, $sex2), I18N::number($removed));
                         }
                 }
         }
     }
     // Split the relationship into sub-relationships, e.g., third-cousin’s great-uncle.
     // Try splitting at every point, and choose the path with the shorted translated name.
     $relationship = null;
     $path1 = substr($path, 0, 3);
     $path2 = substr($path, 3);
     while ($path2) {
         $tmp = I18N::translate('%1$s’s %2$s', self::getRelationshipNameFromPath($path1, null, null), self::getRelationshipNameFromPath($path2, null, null));
         if (!$relationship || strlen($tmp) < strlen($relationship)) {
             $relationship = $tmp;
         }
         $path1 .= substr($path2, 0, 3);
         $path2 = substr($path2, 3);
     }
     return $relationship;
 }
Ejemplo n.º 9
0
 /**
  * Display an individual in a box - for charts, etc.
  *
  * @param Individual $individual
  *
  * @return string
  */
 public function individualBoxSmall(Individual $individual)
 {
     $personBoxClass = array_search($individual->getSex(), array('person_box' => 'M', 'person_boxF' => 'F', 'person_boxNN' => 'U'));
     if ($individual->getTree()->getPreference('SHOW_HIGHLIGHT_IMAGES')) {
         $thumbnail = $individual->displayImage();
     } else {
         $thumbnail = '';
     }
     return '<div data-pid="' . $individual->getXref() . '" class="person_box_template ' . $personBoxClass . ' iconz box-style0" style="width: ' . $this->parameter('compact-chart-box-x') . 'px; min-height: ' . $this->parameter('compact-chart-box-y') . 'px">' . '<div class="compact_view">' . $thumbnail . '<a href="' . $individual->getHtmlUrl() . '">' . '<span class="namedef name0">' . $individual->getFullName() . '</span>' . '</a>' . '<div class="inout2 details0">' . $individual->getLifeSpan() . '</div>' . '</div>' . '<div class="inout"></div>' . '</div>';
 }
Ejemplo n.º 10
0
 /**
  * Draw a person name preceded by sex icon, with parents as tooltip
  *
  * @param Individual $individual an individual
  * @param string        $dashed     if = 'dashed' print dashed top border to separate multiple spuses
  *
  * @return string
  */
 private function drawPersonName(Individual $individual, $dashed = '')
 {
     if ($this->all_partners === 'true') {
         $family = $individual->getPrimaryChildFamily();
         if ($family) {
             $family_name = strip_tags($family->getFullName());
         } else {
             $family_name = I18N::translateContext('unknown family', 'unknown');
         }
         switch ($individual->getSex()) {
             case 'M':
                 $title = ' title="' . I18N::translate('Son of %s', $family_name) . '"';
                 break;
             case 'F':
                 $title = ' title="' . I18N::translate('Daughter of %s', $family_name) . '"';
                 break;
             default:
                 $title = ' title="' . I18N::translate('Child of %s', $family_name) . '"';
                 break;
         }
     } else {
         $title = '';
     }
     $sex = $individual->getSex();
     return '<div class="tv' . $sex . ' ' . $dashed . '"' . $title . '><a href="' . $individual->getHtmlUrl() . '"></a>' . $individual->getFullName() . ' <span class="dates">' . $individual->getLifeSpan() . '</span></div>';
 }
Ejemplo n.º 11
0
 /**
  * import record into database
  *
  * this function will parse the given gedcom record and add it to the database
  *
  * @param string $gedrec the raw gedcom record to parse
  * @param Tree   $tree   import the record into this tree
  * @param bool   $update whether or not this is an updated record that has been accepted
  */
 public static function importRecord($gedrec, Tree $tree, $update)
 {
     $tree_id = $tree->getTreeId();
     // Escaped @ signs (only if importing from file)
     if (!$update) {
         $gedrec = str_replace('@@', '@', $gedrec);
     }
     // Standardise gedcom format
     $gedrec = self::reformatRecord($gedrec, $tree);
     // import different types of records
     if (preg_match('/^0 @(' . WT_REGEX_XREF . ')@ (' . WT_REGEX_TAG . ')/', $gedrec, $match)) {
         list(, $xref, $type) = $match;
         // check for a _UID, if the record doesn't have one, add one
         if ($tree->getPreference('GENERATE_UIDS') && !strpos($gedrec, "\n1 _UID ")) {
             $gedrec .= "\n1 _UID " . GedcomTag::createUid();
         }
     } elseif (preg_match('/0 (HEAD|TRLR)/', $gedrec, $match)) {
         $type = $match[1];
         $xref = $type;
         // For HEAD/TRLR, use type as pseudo XREF.
     } else {
         echo I18N::translate('Invalid GEDCOM format'), '<br><pre>', $gedrec, '</pre>';
         return;
     }
     // If the user has downloaded their GEDCOM data (containing media objects) and edited it
     // using an application which does not support (and deletes) media objects, then add them
     // back in.
     if ($tree->getPreference('keep_media') && $xref) {
         $old_linked_media = Database::prepare("SELECT l_to FROM `##link` WHERE l_from=? AND l_file=? AND l_type='OBJE'")->execute(array($xref, $tree_id))->fetchOneColumn();
         foreach ($old_linked_media as $media_id) {
             $gedrec .= "\n1 OBJE @" . $media_id . "@";
         }
     }
     switch ($type) {
         case 'INDI':
             // Convert inline media into media objects
             $gedrec = self::convertInlineMedia($tree, $gedrec);
             $record = new Individual($xref, $gedrec, null, $tree);
             if (preg_match('/\\n1 RIN (.+)/', $gedrec, $match)) {
                 $rin = $match[1];
             } else {
                 $rin = $xref;
             }
             Database::prepare("INSERT INTO `##individuals` (i_id, i_file, i_rin, i_sex, i_gedcom) VALUES (?, ?, ?, ?, ?)")->execute(array($xref, $tree_id, $rin, $record->getSex(), $gedrec));
             // Update the cross-reference/index tables.
             self::updatePlaces($xref, $tree_id, $gedrec);
             self::updateDates($xref, $tree_id, $gedrec);
             self::updateLinks($xref, $tree_id, $gedrec);
             self::updateNames($xref, $tree_id, $record);
             break;
         case 'FAM':
             // Convert inline media into media objects
             $gedrec = self::convertInlineMedia($tree, $gedrec);
             if (preg_match('/\\n1 HUSB @(' . WT_REGEX_XREF . ')@/', $gedrec, $match)) {
                 $husb = $match[1];
             } else {
                 $husb = '';
             }
             if (preg_match('/\\n1 WIFE @(' . WT_REGEX_XREF . ')@/', $gedrec, $match)) {
                 $wife = $match[1];
             } else {
                 $wife = '';
             }
             $nchi = preg_match_all('/\\n1 CHIL @(' . WT_REGEX_XREF . ')@/', $gedrec, $match);
             if (preg_match('/\\n1 NCHI (\\d+)/', $gedrec, $match)) {
                 $nchi = max($nchi, $match[1]);
             }
             Database::prepare("INSERT INTO `##families` (f_id, f_file, f_husb, f_wife, f_gedcom, f_numchil) VALUES (?, ?, ?, ?, ?, ?)")->execute(array($xref, $tree_id, $husb, $wife, $gedrec, $nchi));
             // Update the cross-reference/index tables.
             self::updatePlaces($xref, $tree_id, $gedrec);
             self::updateDates($xref, $tree_id, $gedrec);
             self::updateLinks($xref, $tree_id, $gedrec);
             break;
         case 'SOUR':
             // Convert inline media into media objects
             $gedrec = self::convertInlineMedia($tree, $gedrec);
             $record = new Source($xref, $gedrec, null, $tree);
             if (preg_match('/\\n1 TITL (.+)/', $gedrec, $match)) {
                 $name = $match[1];
             } elseif (preg_match('/\\n1 ABBR (.+)/', $gedrec, $match)) {
                 $name = $match[1];
             } else {
                 $name = $xref;
             }
             Database::prepare("INSERT INTO `##sources` (s_id, s_file, s_name, s_gedcom) VALUES (?, ?, LEFT(?, 255), ?)")->execute(array($xref, $tree_id, $name, $gedrec));
             // Update the cross-reference/index tables.
             self::updateLinks($xref, $tree_id, $gedrec);
             self::updateNames($xref, $tree_id, $record);
             break;
         case 'REPO':
             // Convert inline media into media objects
             $gedrec = self::convertInlineMedia($tree, $gedrec);
             $record = new Repository($xref, $gedrec, null, $tree);
             Database::prepare("INSERT INTO `##other` (o_id, o_file, o_type, o_gedcom) VALUES (?, ?, 'REPO', ?)")->execute(array($xref, $tree_id, $gedrec));
             // Update the cross-reference/index tables.
             self::updateLinks($xref, $tree_id, $gedrec);
             self::updateNames($xref, $tree_id, $record);
             break;
         case 'NOTE':
             $record = new Note($xref, $gedrec, null, $tree);
             Database::prepare("INSERT INTO `##other` (o_id, o_file, o_type, o_gedcom) VALUES (?, ?, 'NOTE', ?)")->execute(array($xref, $tree_id, $gedrec));
             // Update the cross-reference/index tables.
             self::updateLinks($xref, $tree_id, $gedrec);
             self::updateNames($xref, $tree_id, $record);
             break;
         case 'OBJE':
             $record = new Media($xref, $gedrec, null, $tree);
             Database::prepare("INSERT INTO `##media` (m_id, m_ext, m_type, m_titl, m_filename, m_file, m_gedcom) VALUES (?, LEFT(?, 6), LEFT(?, 60), LEFT(?, 255), left(?, 512), ?, ?)")->execute(array($xref, $record->extension(), $record->getMediaType(), $record->getTitle(), $record->getFilename(), $tree_id, $gedrec));
             // Update the cross-reference/index tables.
             self::updateLinks($xref, $tree_id, $gedrec);
             self::updateNames($xref, $tree_id, $record);
             break;
         default:
             // HEAD, TRLR, SUBM, SUBN, and custom record types.
             // Force HEAD records to have a creation date.
             if ($type === 'HEAD' && strpos($gedrec, "\n1 DATE ") === false) {
                 $gedrec .= "\n1 DATE " . date('j M Y');
             }
             Database::prepare("INSERT INTO `##other` (o_id, o_file, o_type, o_gedcom) VALUES (?, ?, LEFT(?, 15), ?)")->execute(array($xref, $tree_id, $type, $gedrec));
             // Update the cross-reference/index tables.
             self::updateLinks($xref, $tree_id, $gedrec);
             break;
     }
 }