1<?php 2 3/** 4 * webtrees: online genealogy 5 * Copyright (C) 2023 webtrees development team 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <https://www.gnu.org/licenses/>. 16 */ 17 18declare(strict_types=1); 19 20namespace Fisharebest\Webtrees; 21 22use Fisharebest\Webtrees\Contracts\ElementFactoryInterface; 23use Fisharebest\Webtrees\Contracts\ElementInterface; 24use Fisharebest\Webtrees\CustomTags\Aldfaer; 25use Fisharebest\Webtrees\CustomTags\Ancestry; 26use Fisharebest\Webtrees\CustomTags\BrothersKeeper; 27use Fisharebest\Webtrees\CustomTags\FamilySearch; 28use Fisharebest\Webtrees\CustomTags\FamilyTreeBuilder; 29use Fisharebest\Webtrees\CustomTags\FamilyTreeMaker; 30use Fisharebest\Webtrees\CustomTags\Gedcom7; 31use Fisharebest\Webtrees\CustomTags\GedcomL; 32use Fisharebest\Webtrees\CustomTags\Geneatique; 33use Fisharebest\Webtrees\CustomTags\GenPlusWin; 34use Fisharebest\Webtrees\CustomTags\Heredis; 35use Fisharebest\Webtrees\CustomTags\Legacy; 36use Fisharebest\Webtrees\CustomTags\MyHeritage; 37use Fisharebest\Webtrees\CustomTags\PersonalAncestralFile; 38use Fisharebest\Webtrees\CustomTags\PhpGedView; 39use Fisharebest\Webtrees\CustomTags\ProGen; 40use Fisharebest\Webtrees\CustomTags\Reunion; 41use Fisharebest\Webtrees\CustomTags\RootsMagic; 42use Fisharebest\Webtrees\Elements\AddressCity; 43use Fisharebest\Webtrees\Elements\AddressCountry; 44use Fisharebest\Webtrees\Elements\AddressEmail; 45use Fisharebest\Webtrees\Elements\AddressFax; 46use Fisharebest\Webtrees\Elements\AddressLine; 47use Fisharebest\Webtrees\Elements\AddressLine1; 48use Fisharebest\Webtrees\Elements\AddressLine2; 49use Fisharebest\Webtrees\Elements\AddressLine3; 50use Fisharebest\Webtrees\Elements\AddressPostalCode; 51use Fisharebest\Webtrees\Elements\AddressState; 52use Fisharebest\Webtrees\Elements\AddressWebPage; 53use Fisharebest\Webtrees\Elements\AdoptedByWhichParent; 54use Fisharebest\Webtrees\Elements\Adoption; 55use Fisharebest\Webtrees\Elements\AdultChristening; 56use Fisharebest\Webtrees\Elements\AgeAtEvent; 57use Fisharebest\Webtrees\Elements\AncestralFileNumber; 58use Fisharebest\Webtrees\Elements\Annulment; 59use Fisharebest\Webtrees\Elements\ApprovedSystemId; 60use Fisharebest\Webtrees\Elements\AutomatedRecordId; 61use Fisharebest\Webtrees\Elements\Baptism; 62use Fisharebest\Webtrees\Elements\BarMitzvah; 63use Fisharebest\Webtrees\Elements\BasMitzvah; 64use Fisharebest\Webtrees\Elements\Birth; 65use Fisharebest\Webtrees\Elements\Blessing; 66use Fisharebest\Webtrees\Elements\Burial; 67use Fisharebest\Webtrees\Elements\CasteName; 68use Fisharebest\Webtrees\Elements\CauseOfEvent; 69use Fisharebest\Webtrees\Elements\Census; 70use Fisharebest\Webtrees\Elements\CertaintyAssessment; 71use Fisharebest\Webtrees\Elements\Change; 72use Fisharebest\Webtrees\Elements\ChangeDate; 73use Fisharebest\Webtrees\Elements\CharacterSet; 74use Fisharebest\Webtrees\Elements\ChildLinkageStatus; 75use Fisharebest\Webtrees\Elements\Christening; 76use Fisharebest\Webtrees\Elements\Confirmation; 77use Fisharebest\Webtrees\Elements\ContentDescription; 78use Fisharebest\Webtrees\Elements\Coordinates; 79use Fisharebest\Webtrees\Elements\CopyrightFile; 80use Fisharebest\Webtrees\Elements\CopyrightSourceData; 81use Fisharebest\Webtrees\Elements\CountOfChildren; 82use Fisharebest\Webtrees\Elements\CountOfChildrenFam; 83use Fisharebest\Webtrees\Elements\CountOfMarriages; 84use Fisharebest\Webtrees\Elements\Cremation; 85use Fisharebest\Webtrees\Elements\CustomElement; 86use Fisharebest\Webtrees\Elements\DateLdsOrd; 87use Fisharebest\Webtrees\Elements\DateValue; 88use Fisharebest\Webtrees\Elements\DateValueExact; 89use Fisharebest\Webtrees\Elements\Death; 90use Fisharebest\Webtrees\Elements\DescriptiveTitle; 91use Fisharebest\Webtrees\Elements\Divorce; 92use Fisharebest\Webtrees\Elements\DivorceFiled; 93use Fisharebest\Webtrees\Elements\Emigration; 94use Fisharebest\Webtrees\Elements\EmptyElement; 95use Fisharebest\Webtrees\Elements\Engagement; 96use Fisharebest\Webtrees\Elements\EventOrFactClassification; 97use Fisharebest\Webtrees\Elements\EventsRecorded; 98use Fisharebest\Webtrees\Elements\EventTypeCitedFrom; 99use Fisharebest\Webtrees\Elements\FamilyCensus; 100use Fisharebest\Webtrees\Elements\FamilyEvent; 101use Fisharebest\Webtrees\Elements\FamilyRecord; 102use Fisharebest\Webtrees\Elements\FileName; 103use Fisharebest\Webtrees\Elements\FirstCommunion; 104use Fisharebest\Webtrees\Elements\Form; 105use Fisharebest\Webtrees\Elements\GedcomElement; 106use Fisharebest\Webtrees\Elements\GenerationsOfAncestors; 107use Fisharebest\Webtrees\Elements\GenerationsOfDescendants; 108use Fisharebest\Webtrees\Elements\Graduation; 109use Fisharebest\Webtrees\Elements\HeaderRecord; 110use Fisharebest\Webtrees\Elements\Immigration; 111use Fisharebest\Webtrees\Elements\IndividualEvent; 112use Fisharebest\Webtrees\Elements\IndividualFact; 113use Fisharebest\Webtrees\Elements\IndividualRecord; 114use Fisharebest\Webtrees\Elements\LanguageId; 115use Fisharebest\Webtrees\Elements\LdsBaptism; 116use Fisharebest\Webtrees\Elements\LdsBaptismDateStatus; 117use Fisharebest\Webtrees\Elements\LdsChildSealing; 118use Fisharebest\Webtrees\Elements\LdsChildSealingDateStatus; 119use Fisharebest\Webtrees\Elements\LdsConfirmation; 120use Fisharebest\Webtrees\Elements\LdsEndowment; 121use Fisharebest\Webtrees\Elements\LdsEndowmentDateStatus; 122use Fisharebest\Webtrees\Elements\LdsSpouseSealing; 123use Fisharebest\Webtrees\Elements\LdsSpouseSealingDateStatus; 124use Fisharebest\Webtrees\Elements\Marriage; 125use Fisharebest\Webtrees\Elements\MarriageBanns; 126use Fisharebest\Webtrees\Elements\MarriageContract; 127use Fisharebest\Webtrees\Elements\MarriageLicence; 128use Fisharebest\Webtrees\Elements\MarriageSettlement; 129use Fisharebest\Webtrees\Elements\MarriageType; 130use Fisharebest\Webtrees\Elements\MediaRecord; 131use Fisharebest\Webtrees\Elements\MultimediaFileReference; 132use Fisharebest\Webtrees\Elements\MultimediaFormat; 133use Fisharebest\Webtrees\Elements\NameOfBusiness; 134use Fisharebest\Webtrees\Elements\NameOfFamilyFile; 135use Fisharebest\Webtrees\Elements\NameOfProduct; 136use Fisharebest\Webtrees\Elements\NameOfRepository; 137use Fisharebest\Webtrees\Elements\NameOfSourceData; 138use Fisharebest\Webtrees\Elements\NamePersonal; 139use Fisharebest\Webtrees\Elements\NamePhoneticVariation; 140use Fisharebest\Webtrees\Elements\NamePieceGiven; 141use Fisharebest\Webtrees\Elements\NamePieceNickname; 142use Fisharebest\Webtrees\Elements\NamePiecePrefix; 143use Fisharebest\Webtrees\Elements\NamePieceSuffix; 144use Fisharebest\Webtrees\Elements\NamePieceSurname; 145use Fisharebest\Webtrees\Elements\NamePieceSurnamePrefix; 146use Fisharebest\Webtrees\Elements\NameRomanizedVariation; 147use Fisharebest\Webtrees\Elements\NameType; 148use Fisharebest\Webtrees\Elements\NationalIdNumber; 149use Fisharebest\Webtrees\Elements\NationalOrTribalOrigin; 150use Fisharebest\Webtrees\Elements\Naturalization; 151use Fisharebest\Webtrees\Elements\NobilityTypeTitle; 152use Fisharebest\Webtrees\Elements\NoteRecord; 153use Fisharebest\Webtrees\Elements\NoteStructure; 154use Fisharebest\Webtrees\Elements\Occupation; 155use Fisharebest\Webtrees\Elements\OrdinanceProcessFlag; 156use Fisharebest\Webtrees\Elements\Ordination; 157use Fisharebest\Webtrees\Elements\PedigreeLinkageType; 158use Fisharebest\Webtrees\Elements\PermanentRecordFileNumber; 159use Fisharebest\Webtrees\Elements\PhoneNumber; 160use Fisharebest\Webtrees\Elements\PhoneticType; 161use Fisharebest\Webtrees\Elements\PhysicalDescription; 162use Fisharebest\Webtrees\Elements\PlaceHierarchy; 163use Fisharebest\Webtrees\Elements\PlaceLatitude; 164use Fisharebest\Webtrees\Elements\PlaceLivingOrdinance; 165use Fisharebest\Webtrees\Elements\PlaceLongtitude; 166use Fisharebest\Webtrees\Elements\PlaceName; 167use Fisharebest\Webtrees\Elements\PlacePhoneticVariation; 168use Fisharebest\Webtrees\Elements\PlaceRomanizedVariation; 169use Fisharebest\Webtrees\Elements\Possessions; 170use Fisharebest\Webtrees\Elements\Probate; 171use Fisharebest\Webtrees\Elements\PublicationDate; 172use Fisharebest\Webtrees\Elements\ReceivingSystemName; 173use Fisharebest\Webtrees\Elements\RelationIsDescriptor; 174use Fisharebest\Webtrees\Elements\ReligiousAffiliation; 175use Fisharebest\Webtrees\Elements\RepositoryRecord; 176use Fisharebest\Webtrees\Elements\Residence; 177use Fisharebest\Webtrees\Elements\ResidenceWithValue; 178use Fisharebest\Webtrees\Elements\ResponsibleAgency; 179use Fisharebest\Webtrees\Elements\RestrictionNotice; 180use Fisharebest\Webtrees\Elements\Retirement; 181use Fisharebest\Webtrees\Elements\RoleInEvent; 182use Fisharebest\Webtrees\Elements\RomanizedType; 183use Fisharebest\Webtrees\Elements\ScholasticAchievement; 184use Fisharebest\Webtrees\Elements\SexValue; 185use Fisharebest\Webtrees\Elements\SocialSecurityNumber; 186use Fisharebest\Webtrees\Elements\SourceCallNumber; 187use Fisharebest\Webtrees\Elements\SourceData; 188use Fisharebest\Webtrees\Elements\SourceFiledByEntry; 189use Fisharebest\Webtrees\Elements\SourceJurisdictionPlace; 190use Fisharebest\Webtrees\Elements\SourceMediaType; 191use Fisharebest\Webtrees\Elements\SourceOriginator; 192use Fisharebest\Webtrees\Elements\SourcePublicationFacts; 193use Fisharebest\Webtrees\Elements\SourceRecord; 194use Fisharebest\Webtrees\Elements\SubmissionRecord; 195use Fisharebest\Webtrees\Elements\SubmitterName; 196use Fisharebest\Webtrees\Elements\SubmitterRecord; 197use Fisharebest\Webtrees\Elements\SubmitterRegisteredRfn; 198use Fisharebest\Webtrees\Elements\SubmitterText; 199use Fisharebest\Webtrees\Elements\TempleCode; 200use Fisharebest\Webtrees\Elements\TextFromSource; 201use Fisharebest\Webtrees\Elements\TimeValueNow; 202use Fisharebest\Webtrees\Elements\TransmissionDate; 203use Fisharebest\Webtrees\Elements\UserReferenceNumber; 204use Fisharebest\Webtrees\Elements\UserReferenceType; 205use Fisharebest\Webtrees\Elements\VersionNumber; 206use Fisharebest\Webtrees\Elements\WebtreesUser; 207use Fisharebest\Webtrees\Elements\WhereWithinSource; 208use Fisharebest\Webtrees\Elements\Will; 209use Fisharebest\Webtrees\Elements\XrefAssociate; 210use Fisharebest\Webtrees\Elements\XrefFamily; 211use Fisharebest\Webtrees\Elements\XrefIndividual; 212use Fisharebest\Webtrees\Elements\XrefMedia; 213use Fisharebest\Webtrees\Elements\XrefRepository; 214use Fisharebest\Webtrees\Elements\XrefSource; 215use Fisharebest\Webtrees\Elements\XrefSubmission; 216use Fisharebest\Webtrees\Elements\XrefSubmitter; 217 218/** 219 * GEDCOM 5.5.1 specification 220 */ 221class Gedcom 222{ 223 // 255 less the EOL character. 224 public const LINE_LENGTH = 253; 225 226 // Gedcom tags which indicate the start of life. 227 public const BIRTH_EVENTS = ['BIRT', 'CHR', 'BAPM']; 228 229 // Gedcom tags which indicate the end of life. 230 public const DEATH_EVENTS = ['DEAT', 'BURI', 'CREM']; 231 232 // Gedcom tags which indicate the start of a relationship. 233 public const MARRIAGE_EVENTS = ['MARR', '_NMR']; 234 235 // Gedcom tags which indicate the end of a relationship. 236 public const DIVORCE_EVENTS = ['DIV', 'ANUL', '_SEPR']; 237 238 // Regular expression to match a GEDCOM tag. 239 public const REGEX_TAG = '[_A-Z][_A-Z0-9]*'; 240 241 // Regular expression to match a GEDCOM XREF. 242 public const REGEX_XREF = '[A-Za-z0-9:_.-]{1,20}'; 243 244 // Regular expression to match a GEDCOM fact/event for editing raw GEDCOM. 245 private const REGEX_VALUE = '( .+)?'; 246 private const REGEX_LEVEL_9 = '\n9 ' . self::REGEX_TAG . self::REGEX_VALUE; 247 private const REGEX_LEVEL_8 = '\n8 ' . self::REGEX_TAG . self::REGEX_VALUE . '(' . self::REGEX_LEVEL_9 . ')*'; 248 private const REGEX_LEVEL_7 = '\n7 ' . self::REGEX_TAG . self::REGEX_VALUE . '(' . self::REGEX_LEVEL_8 . ')*'; 249 private const REGEX_LEVEL_6 = '\n6 ' . self::REGEX_TAG . self::REGEX_VALUE . '(' . self::REGEX_LEVEL_7 . ')*'; 250 private const REGEX_LEVEL_5 = '\n5 ' . self::REGEX_TAG . self::REGEX_VALUE . '(' . self::REGEX_LEVEL_6 . ')*'; 251 private const REGEX_LEVEL_4 = '\n4 ' . self::REGEX_TAG . self::REGEX_VALUE . '(' . self::REGEX_LEVEL_5 . ')*'; 252 private const REGEX_LEVEL_3 = '\n3 ' . self::REGEX_TAG . self::REGEX_VALUE . '(' . self::REGEX_LEVEL_4 . ')*'; 253 private const REGEX_LEVEL_2 = '\n2 ' . self::REGEX_TAG . self::REGEX_VALUE . '(' . self::REGEX_LEVEL_3 . ')*'; 254 public const REGEX_FACT = '1 ' . self::REGEX_TAG . self::REGEX_VALUE . '(' . self::REGEX_LEVEL_2 . ')*\n?'; 255 256 // Separates the parts of a place name. 257 public const PLACE_SEPARATOR = ', '; 258 259 // Regex to match a (badly formed) GEDCOM place separator. 260 public const PLACE_SEPARATOR_REGEX = '/ *,[, ]*/'; 261 262 // LATI and LONG tags 263 public const LATITUDE_NORTH = 'N'; 264 public const LATITUDE_SOUTH = 'S'; 265 public const LONGITUDE_EAST = 'E'; 266 public const LONGITUDE_WEST = 'W'; 267 268 // Not all record types allow a CHAN event. 269 public const RECORDS_WITH_CHAN = [ 270 Family::RECORD_TYPE, 271 Individual::RECORD_TYPE, 272 Media::RECORD_TYPE, 273 Note::RECORD_TYPE, 274 Repository::RECORD_TYPE, 275 Source::RECORD_TYPE, 276 Submitter::RECORD_TYPE, 277 ]; 278 279 // These preferences control multiple tag definitions 280 public const HIDDEN_TAGS = [ 281 // Individual names 282 'NAME_NPFX' => ['INDI:NAME:NPFX', 'INDI:NAME:FONE:NPFX', 'INDI:NAME:ROMN:NPFX'], 283 'NAME_SPFX' => ['INDI:NAME:SPFX', 'INDI:NAME:FONE:SPFX', 'INDI:NAME:ROMN:SPFX'], 284 'NAME_NSFX' => ['INDI:NAME:NSFX', 'INDI:NAME:FONE:NSFX', 'INDI:NAME:ROMN:NSFX'], 285 'NAME_NICK' => ['INDI:NAME:NICK', 'INDI:NAME:FONE:NICK', 'INDI:NAME:ROMN:NICK'], 286 'NAME_FONE' => ['INDI:NAME:FONE'], 287 'NAME_ROMN' => ['INDI:NAME:ROMN'], 288 'NAME_NOTE' => ['INDI:NAME:NOTE', 'INDI:NAME:FONE:NOTE', 'INDI:NAME:ROMN:NOTE'], 289 'NAME_SOUR' => ['INDI:NAME:SOUR', 'INDI:NAME:FONE:SOUR', 'INDI:NAME:ROMN:SOUR'], 290 // Places 291 'PLAC_MAP' => [':PLAC:MAP'], 292 'PLAC_FONE' => [':PLAC:FONE'], 293 'PLAC_ROMN' => [':PLAC:ROMN'], 294 'PLAC_FORM' => [':PLAC:FORM', 'HEAD:PLAC'], 295 'PLAC_NOTE' => [':PLAC:NOTE'], 296 // Addresses 297 'ADDR_EMAIL' => [':EMAIL'], 298 'ADDR_PHON' => [':PHON'], 299 'ADDR_WWW' => [':WWW'], 300 // Source citations 301 'SOUR_EVEN' => [':SOUR:EVEN'], 302 'SOUR_DATE' => [':SOUR:DATA:DATE'], 303 'SOUR_NOTE' => [':SOUR:NOTE'], 304 'SOUR_QUAY' => [':SOUR:QUAY'], 305 // Sources 306 'SOUR_DATA' => ['SOUR:DATA:EVEN', 'SOUR:DATA:AGNC', 'SOUR:DATA:NOTE'], 307 // Individuals 308 'BIRT_FAMC' => ['INDI:BIRT:FAMC'], 309 'RELI' => ['INDI:RELI'], 310 'BAPM' => ['INDI:BAPM'], 311 'CHR' => ['INDI:CHR', 'INDI:CHRA'], 312 'FCOM' => ['INDI:FCOM', 'INDI:CONF'], 313 'ORDN' => ['INDI:ORDN'], 314 'BARM' => ['INDI:BARM', 'INDI:BASM'], 315 'ALIA' => ['INDI:ALIA'], 316 'ASSO' => ['INDI:ASSO'], 317 // Families 318 'ENGA' => ['FAM:ENGA'], 319 'MARB' => ['FAM:MARB'], 320 'MARC' => ['FAM:MARC'], 321 'MARL' => ['FAM:MARL'], 322 'MARS' => ['FAM:MARS'], 323 'ANUL' => ['FAM:ANUL'], 324 'DIVF' => ['FAM:DIVF'], 325 'FAM_RESI' => ['FAM:RESI'], 326 'FAM_CENS' => ['FAM:CENS'], 327 // LDS church 328 'LDS' => ['INDI:BAPL', 'INDI:CONL', 'INDI:ENDL', 'INDI:SLGC', 'FAM:SLGS', 'HEAD:SUBN'], 329 // Identifiers 330 'AFN' => ['INDI:AFN'], 331 'IDNO' => ['INDI:IDNO'], 332 'SSN' => ['INDI:SSN'], 333 'RFN' => [':RFN'], 334 'REFN' => [':REFN'], 335 'RIN' => [':RIN'], 336 // Submitters 337 'SUBM' => ['INDI:SUBM', 'FAM:SUBM'], 338 'ANCI' => ['INDI:ANCI', 'INDI:DESI'], 339 ]; 340 341 // Custom GEDCOM tags that can be created in webtrees. 342 public const CUSTOM_FAMILY_TAGS = [ 343 'FACT', 344 '_COML', 345 '_MARI', 346 '_MBON', 347 '_NMR', 348 '_SEPR', 349 ]; 350 351 public const CUSTOM_INDIVIDUAL_TAGS = [ 352 '_BRTM', 353 '_CIRC', 354 '_DEG', 355 '_DNA', 356 '_EXCM', 357 '_EYEC', 358 '_FNRL', 359 '_FSFTID', 360 '_HAIR', 361 '_HEIG', 362 '_INTE', 363 '_MDCL', 364 '_MEDC', 365 '_MILI', 366 '_MILT', 367 '_NAMS', 368 '_NMAR', 369 '_PRMN', 370 '_WEIG', 371 '_YART', 372 ]; 373 374 // Some applications create GEDCOM files containing records without XREFS. 375 // We cannot process these. 376 public const CUSTOM_RECORDS_WITHOUT_XREFS = [ 377 'EMOTIONALRELATIONSHIP', // GenoPro 378 'GENOMAP', // GenoPro 379 'GLOBAL', // GenoPro 380 'LABEL', // GenoPro 381 'PEDIGREELINK', // GenoPro 382 'SOCIALRELATIONSHIP', // GenoPro 383 '_EVDEF', // RootsMagic 384 '_EVENT_DEFN', // PAF and Legacy 385 '_HASHTAG_DEFN', // Legacy 386 '_PUBLISH', // MyHeritage 387 '_TASK', // Ages 388 '_TODO', // Legacy 389 ]; 390 391 /** 392 * Definitions for GEDCOM 5.5.1. 393 * 394 * @return array<string,ElementInterface> 395 */ 396 private function gedcom551Tags(): array 397 { 398 return [ 399 'FAM' => new FamilyRecord(I18N::translate('Family')), 400 'FAM:*:ADDR' => new AddressLine(I18N::translate('Address')), 401 'FAM:*:ADDR:ADR1' => new AddressLine1(I18N::translate('Address line 1')), 402 'FAM:*:ADDR:ADR2' => new AddressLine2(I18N::translate('Address line 2')), 403 'FAM:*:ADDR:ADR3' => new AddressLine3(I18N::translate('Address line 3')), 404 'FAM:*:ADDR:CITY' => new AddressCity(I18N::translate('City')), 405 'FAM:*:ADDR:CTRY' => new AddressCountry(I18N::translate('Country')), 406 'FAM:*:ADDR:POST' => new AddressPostalCode(I18N::translate('Postal code')), 407 'FAM:*:ADDR:STAE' => new AddressState(I18N::translate('State')), 408 'FAM:*:AGNC' => new ResponsibleAgency(I18N::translate('Agency')), 409 'FAM:*:CAUS' => new CauseOfEvent(I18N::translate('Cause')), 410 'FAM:*:DATE' => new DateValue(I18N::translate('Date')), 411 'FAM:*:EMAIL' => new AddressEmail(I18N::translate('Email address')), 412 'FAM:*:FAX' => new AddressFax(I18N::translate('Fax')), 413 'FAM:*:HUSB' => new EmptyElement(I18N::translate('Husband'), ['AGE' => '0:1']), 414 'FAM:*:HUSB:AGE' => new AgeAtEvent(I18N::translate('Husband’s age')), 415 'FAM:*:NOTE' => new NoteStructure(I18N::translate('Note')), 416 'FAM:*:OBJE' => new XrefMedia(I18N::translate('Media object')), 417 'FAM:*:PHON' => new PhoneNumber(I18N::translate('Phone')), 418 'FAM:*:PLAC' => new PlaceName(I18N::translate('Place')), 419 'FAM:*:PLAC:FONE' => new PlacePhoneticVariation(I18N::translate('Phonetic place')), 420 'FAM:*:PLAC:FONE:TYPE' => new PhoneticType(I18N::translate('Type')), 421 'FAM:*:PLAC:FORM' => new PlaceHierarchy(I18N::translate('Format')), 422 'FAM:*:PLAC:MAP' => new Coordinates(I18N::translate('Coordinates')), 423 'FAM:*:PLAC:MAP:LATI' => new PlaceLatitude(I18N::translate('Latitude')), 424 'FAM:*:PLAC:MAP:LONG' => new PlaceLongtitude(I18N::translate('Longitude')), 425 'FAM:*:PLAC:NOTE' => new NoteStructure(I18N::translate('Note on place')), 426 'FAM:*:PLAC:ROMN' => new PlaceRomanizedVariation(I18N::translate('Romanized place')), 427 'FAM:*:PLAC:ROMN:TYPE' => new RomanizedType(I18N::translate('Type')), 428 'FAM:*:RELI' => new ReligiousAffiliation(I18N::translate('Religion'), []), 429 'FAM:*:RESN' => new RestrictionNotice(I18N::translate('Restriction')), 430 'FAM:*:SOUR' => new XrefSource(I18N::translate('Source citation')), 431 'FAM:*:SOUR:DATA' => new SourceData(I18N::translate('Data')), 432 'FAM:*:SOUR:DATA:DATE' => new DateValue(I18N::translate('Date of entry in original source')), 433 'FAM:*:SOUR:DATA:TEXT' => new TextFromSource(I18N::translate('Text')), 434 'FAM:*:SOUR:EVEN' => new EventTypeCitedFrom(I18N::translate('Event')), 435 'FAM:*:SOUR:EVEN:ROLE' => new RoleInEvent(I18N::translate('Role')), 436 'FAM:*:SOUR:NOTE' => new NoteStructure(I18N::translate('Note on source citation')), 437 'FAM:*:SOUR:OBJE' => new XrefMedia(I18N::translate('Media object')), 438 'FAM:*:SOUR:PAGE' => new WhereWithinSource(I18N::translate('Citation details')), 439 'FAM:*:SOUR:QUAY' => new CertaintyAssessment(I18N::translate('Quality of data')), 440 'FAM:*:TYPE' => new EventOrFactClassification(I18N::translate('Type')), 441 'FAM:*:WIFE' => new EmptyElement(I18N::translate('Wife'), ['AGE' => '0:1']), 442 'FAM:*:WIFE:AGE' => new AgeAtEvent(I18N::translate('Wife’s age')), 443 'FAM:*:WWW' => new AddressWebPage(I18N::translate('URL')), 444 'FAM:ANUL' => new Annulment(I18N::translate('Annulment')), 445 'FAM:CENS' => new FamilyCensus(I18N::translate('Family census')), 446 'FAM:CHAN' => new Change(I18N::translate('Last change')), 447 'FAM:CHAN:DATE' => new ChangeDate(I18N::translate('Date of last change')), 448 'FAM:CHAN:DATE:TIME' => new TimeValueNow(I18N::translate('Time of last change')), 449 'FAM:CHAN:NOTE' => new NoteStructure(I18N::translate('Note on last change')), 450 'FAM:CHIL' => new XrefIndividual(I18N::translate('Child')), 451 'FAM:DIV' => new Divorce(I18N::translate('Divorce')), 452 'FAM:DIV:DATE' => new DateValue(I18N::translate('Date of divorce')), 453 'FAM:DIVF' => new DivorceFiled(I18N::translate('Divorce filed')), 454 'FAM:ENGA' => new Engagement(I18N::translate('Engagement')), 455 'FAM:ENGA:DATE' => new DateValue(I18N::translate('Date of engagement')), 456 'FAM:ENGA:PLAC' => new PlaceName(I18N::translate('Place of engagement')), 457 'FAM:EVEN' => new FamilyEvent(I18N::translate('Event')), 458 'FAM:EVEN:TYPE' => new EventOrFactClassification(I18N::translate('Type of event')), 459 'FAM:HUSB' => new XrefIndividual(I18N::translate('Husband')), 460 'FAM:MARB' => new MarriageBanns(I18N::translate('Marriage banns')), 461 'FAM:MARB:DATE' => new DateValue(I18N::translate('Date of marriage banns')), 462 'FAM:MARB:PLAC' => new PlaceName(I18N::translate('Place of marriage banns')), 463 'FAM:MARC' => new MarriageContract(I18N::translate('Marriage contract')), 464 'FAM:MARL' => new MarriageLicence(I18N::translate('Marriage license')), 465 'FAM:MARR' => new Marriage(I18N::translate('Marriage')), 466 'FAM:MARR:DATE' => new DateValue(I18N::translate('Date of marriage')), 467 'FAM:MARR:PLAC' => new PlaceName(I18N::translate('Place of marriage')), 468 'FAM:MARR:TYPE' => new MarriageType(I18N::translate('Type of marriage')), 469 'FAM:MARS' => new MarriageSettlement(I18N::translate('Marriage settlement')), 470 'FAM:NCHI' => new CountOfChildrenFam(I18N::translate('Number of children')), 471 'FAM:NOTE' => new NoteStructure(I18N::translate('Note')), 472 'FAM:OBJE' => new XrefMedia(I18N::translate('Media object')), 473 'FAM:REFN' => new UserReferenceNumber(I18N::translate('Reference number')), 474 'FAM:REFN:TYPE' => new UserReferenceType(I18N::translate('Type of reference number')), 475 'FAM:RESI' => new Residence(I18N::translate('Family residence')), 476 'FAM:RESN' => new RestrictionNotice(I18N::translate('Restriction')), 477 'FAM:RIN' => new AutomatedRecordId(I18N::translate('Record ID number')), 478 'FAM:SLGS' => new LdsSpouseSealing(I18N::translate('LDS spouse sealing')), 479 'FAM:SLGS:DATE' => new DateLdsOrd(I18N::translate('Date of LDS spouse sealing')), 480 'FAM:SLGS:PLAC' => new PlaceLivingOrdinance(I18N::translate('Place of LDS spouse sealing')), 481 'FAM:SLGS:STAT' => new LdsSpouseSealingDateStatus(I18N::translate('Status')), 482 'FAM:SLGS:STAT:DATE' => new DateValueExact(I18N::translate('Status change date')), 483 'FAM:SLGS:TEMP' => new TempleCode(I18N::translate('Temple')), 484 'FAM:SOUR' => new XrefSource(I18N::translate('Source citation')), 485 'FAM:SOUR:DATA' => new SourceData(I18N::translate('Data')), 486 'FAM:SOUR:DATA:DATE' => new DateValue(I18N::translate('Date of entry in original source')), 487 'FAM:SOUR:DATA:TEXT' => new TextFromSource(I18N::translate('Text')), 488 'FAM:SOUR:EVEN' => new EventTypeCitedFrom(I18N::translate('Event')), 489 'FAM:SOUR:EVEN:ROLE' => new RoleInEvent(I18N::translate('Role')), 490 'FAM:SOUR:NOTE' => new NoteStructure(I18N::translate('Note on source citation')), 491 'FAM:SOUR:OBJE' => new XrefMedia(I18N::translate('Media object')), 492 'FAM:SOUR:PAGE' => new WhereWithinSource(I18N::translate('Citation details')), 493 'FAM:SOUR:QUAY' => new CertaintyAssessment(I18N::translate('Quality of data')), 494 'FAM:SUBM' => new XrefSubmitter(I18N::translate('Submitter')), 495 'FAM:WIFE' => new XrefIndividual(I18N::translate('Wife')), 496 'HEAD' => new HeaderRecord(I18N::translate('Header')), 497 'HEAD:CHAR' => new CharacterSet(I18N::translate('Character set')), 498 'HEAD:CHAR:VERS' => new VersionNumber(I18N::translate('Version')), 499 'HEAD:COPR' => new CopyrightFile(I18N::translate('Copyright')), 500 'HEAD:DATE' => new TransmissionDate(I18N::translate('Date')), 501 'HEAD:DATE:TIME' => new TimeValueNow(I18N::translate('Time')), 502 'HEAD:DEST' => new ReceivingSystemName(I18N::translate('Destination')), 503 'HEAD:FILE' => new FileName(I18N::translate('Filename')), 504 'HEAD:GEDC' => new GedcomElement(I18N::translate('GEDCOM')), 505 'HEAD:GEDC:FORM' => new Form(I18N::translate('Format')), 506 'HEAD:GEDC:VERS' => new VersionNumber(I18N::translate('Version')), 507 'HEAD:LANG' => new LanguageId(I18N::translate('Language')), 508 'HEAD:NOTE' => new ContentDescription(I18N::translate('Note')), 509 'HEAD:PLAC' => new EmptyElement(I18N::translate('Place hierarchy'), ['FORM' => '1:1']), 510 'HEAD:PLAC:FORM' => new PlaceHierarchy(I18N::translate('Format')), 511 'HEAD:SOUR' => new ApprovedSystemId(I18N::translate('Application ID')), 512 'HEAD:SOUR:CORP' => new NameOfBusiness(I18N::translate('Corporation')), 513 'HEAD:SOUR:CORP:ADDR' => new AddressLine(I18N::translate('Address')), 514 'HEAD:SOUR:CORP:ADDR:ADR1' => new AddressLine1(I18N::translate('Address line 1')), 515 'HEAD:SOUR:CORP:ADDR:ADR2' => new AddressLine2(I18N::translate('Address line 2')), 516 'HEAD:SOUR:CORP:ADDR:ADR3' => new AddressLine3(I18N::translate('Address line 3')), 517 'HEAD:SOUR:CORP:ADDR:CITY' => new AddressCity(I18N::translate('City')), 518 'HEAD:SOUR:CORP:ADDR:CTRY' => new AddressCountry(I18N::translate('Country')), 519 'HEAD:SOUR:CORP:ADDR:POST' => new AddressPostalCode(I18N::translate('Postal code')), 520 'HEAD:SOUR:CORP:ADDR:STAE' => new AddressState(I18N::translate('State')), 521 'HEAD:SOUR:CORP:EMAIL' => new AddressEmail(I18N::translate('Email address')), 522 'HEAD:SOUR:CORP:FAX' => new AddressFax(I18N::translate('Fax')), 523 'HEAD:SOUR:CORP:PHON' => new PhoneNumber(I18N::translate('Phone')), 524 'HEAD:SOUR:CORP:WWW' => new AddressWebPage(I18N::translate('URL')), 525 'HEAD:SOUR:DATA' => new NameOfSourceData(I18N::translate('Data')), 526 'HEAD:SOUR:DATA:COPR' => new CopyrightSourceData(I18N::translate('Copyright')), 527 'HEAD:SOUR:DATA:DATE' => new PublicationDate(I18N::translate('Date')), 528 'HEAD:SOUR:NAME' => new NameOfProduct(I18N::translate('Application name')), 529 'HEAD:SOUR:VERS' => new VersionNumber(I18N::translate('Version')), 530 'HEAD:SUBM' => new XrefSubmitter(I18N::translate('Submitter')), 531 'HEAD:SUBN' => new XrefSubmission(I18N::translate('Submission')), 532 'INDI' => new IndividualRecord(I18N::translate('Individual')), 533 'INDI:*:ADDR' => new AddressLine(I18N::translate('Address')), 534 'INDI:*:ADDR:ADR1' => new AddressLine1(I18N::translate('Address line 1')), 535 'INDI:*:ADDR:ADR2' => new AddressLine2(I18N::translate('Address line 2')), 536 'INDI:*:ADDR:ADR3' => new AddressLine3(I18N::translate('Address line 3')), 537 'INDI:*:ADDR:CITY' => new AddressCity(I18N::translate('City')), 538 'INDI:*:ADDR:CTRY' => new AddressCountry(I18N::translate('Country')), 539 'INDI:*:ADDR:POST' => new AddressPostalCode(I18N::translate('Postal code')), 540 'INDI:*:ADDR:STAE' => new AddressState(I18N::translate('State')), 541 'INDI:*:AGE' => new AgeAtEvent(I18N::translate('Age')), 542 'INDI:*:AGNC' => new ResponsibleAgency(I18N::translate('Agency')), 543 'INDI:*:CAUS' => new CauseOfEvent(I18N::translate('Cause')), 544 'INDI:*:DATE' => new DateValue(I18N::translate('Date')), 545 'INDI:*:EMAIL' => new AddressEmail(I18N::translate('Email address')), 546 'INDI:*:FAX' => new AddressFax(I18N::translate('Fax')), 547 'INDI:*:NOTE' => new NoteStructure(I18N::translate('Note')), 548 'INDI:*:OBJE' => new XrefMedia(I18N::translate('Media object')), 549 'INDI:*:PHON' => new PhoneNumber(I18N::translate('Phone')), 550 'INDI:*:PLAC' => new PlaceName(I18N::translate('Place')), 551 'INDI:*:PLAC:FONE' => new PlacePhoneticVariation(I18N::translate('Phonetic place')), 552 'INDI:*:PLAC:FONE:TYPE' => new PhoneticType(I18N::translate('Type')), 553 'INDI:*:PLAC:FORM' => new PlaceHierarchy(I18N::translate('Format')), 554 'INDI:*:PLAC:MAP' => new Coordinates(I18N::translate('Coordinates')), 555 'INDI:*:PLAC:MAP:LATI' => new PlaceLatitude(I18N::translate('Latitude')), 556 'INDI:*:PLAC:MAP:LONG' => new PlaceLongtitude(I18N::translate('Longitude')), 557 'INDI:*:PLAC:NOTE' => new NoteStructure(I18N::translate('Note on place')), 558 'INDI:*:PLAC:ROMN' => new PlaceRomanizedVariation(I18N::translate('Romanized place')), 559 'INDI:*:PLAC:ROMN:TYPE' => new RomanizedType(I18N::translate('Type')), 560 'INDI:*:RELI' => new ReligiousAffiliation(I18N::translate('Religion'), []), 561 'INDI:*:RESN' => new RestrictionNotice(I18N::translate('Restriction')), 562 'INDI:*:SOUR' => new XrefSource(I18N::translate('Source citation')), 563 'INDI:*:SOUR:DATA' => new SourceData(I18N::translate('Data')), 564 'INDI:*:SOUR:DATA:DATE' => new DateValue(I18N::translate('Date of entry in original source')), 565 'INDI:*:SOUR:DATA:TEXT' => new TextFromSource(I18N::translate('Text')), 566 'INDI:*:SOUR:EVEN' => new EventTypeCitedFrom(I18N::translate('Event')), 567 'INDI:*:SOUR:EVEN:ROLE' => new RoleInEvent(I18N::translate('Role')), 568 'INDI:*:SOUR:NOTE' => new NoteStructure(I18N::translate('Note on source citation')), 569 'INDI:*:SOUR:OBJE' => new XrefMedia(I18N::translate('Media object')), 570 'INDI:*:SOUR:PAGE' => new WhereWithinSource(I18N::translate('Citation details')), 571 'INDI:*:SOUR:QUAY' => new CertaintyAssessment(I18N::translate('Quality of data')), 572 'INDI:*:TYPE' => new EventOrFactClassification(I18N::translate('Type')), 573 'INDI:*:WWW' => new AddressWebPage(I18N::translate('URL')), 574 'INDI:ADOP' => new Adoption(I18N::translate('Adoption')), 575 'INDI:ADOP:DATE' => new DateValue(I18N::translate('Date of adoption')), 576 'INDI:ADOP:FAMC' => new XrefFamily(I18N::translate('Adoptive parents'), ['ADOP' => '0:1']), 577 'INDI:ADOP:FAMC:ADOP' => new AdoptedByWhichParent(I18N::translate('Adoption')), 578 'INDI:ADOP:PLAC' => new PlaceName(I18N::translate('Place of adoption')), 579 'INDI:AFN' => new AncestralFileNumber(I18N::translate('Ancestral file number')), 580 'INDI:ALIA' => new XrefIndividual(I18N::translate('Alias')), 581 'INDI:ANCI' => new XrefSubmitter(I18N::translate('Ancestors interest')), 582 'INDI:ASSO' => new XrefAssociate(I18N::translate('Associate')), 583 'INDI:ASSO:RELA' => new RelationIsDescriptor(I18N::translate('Relationship')), 584 'INDI:BAPL' => new LdsBaptism(I18N::translate('LDS baptism')), 585 'INDI:BAPL:DATE' => new DateLdsOrd(I18N::translate('Date of LDS baptism')), 586 'INDI:BAPL:PLAC' => new PlaceLivingOrdinance(I18N::translate('Place of LDS baptism')), 587 'INDI:BAPL:STAT' => new LdsBaptismDateStatus(I18N::translate('Status')), 588 'INDI:BAPL:STAT:DATE' => new DateValueExact(I18N::translate('Status change date')), 589 'INDI:BAPL:TEMP' => new TempleCode(I18N::translate('Temple')), 590 'INDI:BAPM' => new Baptism(I18N::translate('Baptism')), 591 'INDI:BAPM:DATE' => new DateValue(I18N::translate('Date of baptism')), 592 'INDI:BAPM:PLAC' => new PlaceName(I18N::translate('Place of baptism')), 593 'INDI:BARM' => new BarMitzvah(I18N::translate('Bar mitzvah')), 594 'INDI:BARM:DATE' => new DateValue(I18N::translate('Date of bar mitzvah')), 595 'INDI:BARM:PLAC' => new PlaceName(I18N::translate('Place of bar mitzvah')), 596 'INDI:BASM' => new BasMitzvah(I18N::translate('Bat mitzvah')), 597 'INDI:BASM:DATE' => new DateValue(I18N::translate('Date of bat mitzvah')), 598 'INDI:BASM:PLAC' => new PlaceName(I18N::translate('Place of bat mitzvah')), 599 'INDI:BIRT' => new Birth(I18N::translate('Birth')), 600 'INDI:BIRT:DATE' => new DateValue(I18N::translate('Date of birth')), 601 'INDI:BIRT:FAMC' => new XrefFamily(I18N::translate('Birth parents')), 602 'INDI:BIRT:PLAC' => new PlaceName(I18N::translate('Place of birth')), 603 'INDI:BLES' => new Blessing(I18N::translate('Blessing')), 604 'INDI:BLES:DATE' => new DateValue(I18N::translate('Date of blessing')), 605 'INDI:BLES:PLAC' => new PlaceName(I18N::translate('Place of blessing')), 606 'INDI:BURI' => new Burial(I18N::translate('Burial')), 607 'INDI:BURI:DATE' => new DateValue(I18N::translate('Date of burial')), 608 'INDI:BURI:PLAC' => new PlaceName(I18N::translate('Place of burial')), 609 'INDI:CAST' => new CasteName(I18N::translate('Caste')), 610 'INDI:CENS' => new Census(I18N::translate('Census')), 611 'INDI:CENS:DATE' => new DateValue(I18N::translate('Census date')), 612 'INDI:CENS:PLAC' => new PlaceName(I18N::translate('Census place')), 613 'INDI:CHAN' => new Change(I18N::translate('Last change')), 614 'INDI:CHAN:DATE' => new ChangeDate(I18N::translate('Date of last change')), 615 'INDI:CHAN:DATE:TIME' => new TimeValueNow(I18N::translate('Time of last change')), 616 'INDI:CHAN:NOTE' => new NoteStructure(I18N::translate('Note on last change')), 617 'INDI:CHR' => new Christening(I18N::translate('Christening')), 618 'INDI:CHR:DATE' => new DateValue(I18N::translate('Date of christening')), 619 'INDI:CHR:FAMC' => new XrefFamily(I18N::translate('Godparents')), 620 'INDI:CHR:PLAC' => new PlaceName(I18N::translate('Place of christening')), 621 'INDI:CHRA' => new AdultChristening(I18N::translate('Adult christening')), 622 'INDI:CHRA:PLAC' => new PlaceName(I18N::translate('Place of christening')), 623 'INDI:CONF' => new Confirmation(I18N::translate('Confirmation')), 624 'INDI:CONF:DATE' => new DateValue(I18N::translate('Date of confirmation')), 625 'INDI:CONF:PLAC' => new PlaceName(I18N::translate('Place of confirmation')), 626 'INDI:CONL' => new LdsConfirmation(I18N::translate('LDS confirmation')), 627 'INDI:CONL:DATE' => new DateLdsOrd(I18N::translate('Date of LDS confirmation')), 628 'INDI:CONL:PLAC' => new PlaceLivingOrdinance(I18N::translate('Place of LDS confirmation')), 629 'INDI:CONL:STAT' => new LdsBaptismDateStatus(I18N::translate('Status')), 630 'INDI:CONL:STAT:DATE' => new DateValueExact(I18N::translate('Status change date')), 631 'INDI:CONL:TEMP' => new TempleCode(I18N::translate('Temple')), 632 'INDI:CREM' => new Cremation(I18N::translate('Cremation')), 633 'INDI:CREM:DATE' => new DateValue(I18N::translate('Date of cremation')), 634 'INDI:CREM:PLAC' => new PlaceName(I18N::translate('Place of cremation')), 635 'INDI:DEAT' => new Death(I18N::translate('Death')), 636 'INDI:DEAT:CAUS' => new CauseOfEvent(I18N::translate('Cause of death')), 637 'INDI:DEAT:DATE' => new DateValue(I18N::translate('Date of death')), 638 'INDI:DEAT:PLAC' => new PlaceName(I18N::translate('Place of death')), 639 'INDI:DESI' => new XrefSubmitter(I18N::translate('Descendants interest')), 640 'INDI:DSCR' => new PhysicalDescription(I18N::translate('Description')), 641 'INDI:EDUC' => new ScholasticAchievement(I18N::translate('Education')), 642 'INDI:EDUC:AGNC' => new ResponsibleAgency(I18N::translate('School or college')), 643 'INDI:EMIG' => new Emigration(I18N::translate('Emigration')), 644 'INDI:EMIG:DATE' => new DateValue(I18N::translate('Date of emigration')), 645 'INDI:EMIG:PLAC' => new PlaceName(I18N::translate('Place of emigration')), 646 'INDI:ENDL' => new LdsEndowment(I18N::translate('LDS endowment')), 647 'INDI:ENDL:DATE' => new DateLdsOrd(I18N::translate('Date of LDS endowment')), 648 'INDI:ENDL:PLAC' => new PlaceLivingOrdinance(I18N::translate('Place of LDS endowment')), 649 'INDI:ENDL:STAT' => new LdsEndowmentDateStatus(I18N::translate('Status')), 650 'INDI:ENDL:STAT:DATE' => new DateValueExact(I18N::translate('Status change date')), 651 'INDI:ENDL:TEMP' => new TempleCode(I18N::translate('Temple')), 652 'INDI:EVEN' => new IndividualEvent(I18N::translate('Event')), 653 'INDI:EVEN:DATE' => new DateValue(I18N::translate('Date of event')), 654 'INDI:EVEN:PLAC' => new PlaceName(I18N::translate('Place of event')), 655 'INDI:EVEN:TYPE' => new EventOrFactClassification(I18N::translate('Type of event')), 656 'INDI:FACT' => new IndividualFact(I18N::translate('Fact')), 657 'INDI:FACT:TYPE' => new EventOrFactClassification(I18N::translate('Type of fact')), 658 'INDI:FAMC' => new XrefFamily(I18N::translate('Family as a child'), ['NOTE' => '0:1', 'PEDI' => '0:1', 'STAT' => '0:1']), 659 'INDI:FAMC:PEDI' => new PedigreeLinkageType(I18N::translate('Relationship to parents')), 660 'INDI:FAMC:STAT' => new ChildLinkageStatus(I18N::translate('Status')), 661 'INDI:FAMS' => new XrefFamily(I18N::translate('Family as a spouse')), 662 'INDI:FCOM' => new FirstCommunion(I18N::translate('First communion')), 663 'INDI:FCOM:DATE' => new DateValue(I18N::translate('Date of first communion')), 664 'INDI:FCOM:PLAC' => new PlaceName(I18N::translate('Place of first communion')), 665 'INDI:GRAD' => new Graduation(I18N::translate('Graduation')), 666 'INDI:GRAD:AGNC' => new ResponsibleAgency(I18N::translate('School or college')), 667 'INDI:IDNO' => new NationalIdNumber(I18N::translate('Identification number')), 668 'INDI:IDNO:TYPE' => new EventOrFactClassification(I18N::translate('Type of identification number')), 669 'INDI:IMMI' => new Immigration(I18N::translate('Immigration')), 670 'INDI:IMMI:DATE' => new DateValue(I18N::translate('Date of immigration')), 671 'INDI:IMMI:PLAC' => new PlaceName(I18N::translate('Place of immigration')), 672 'INDI:NAME' => new NamePersonal(I18N::translate('Name')), 673 'INDI:NAME:*:SOUR' => new XrefSource(I18N::translate('Source citation')), 674 'INDI:NAME:*:SOUR:DATA' => new SourceData(I18N::translate('Data')), 675 'INDI:NAME:*:SOUR:DATA:DATE' => new DateValue(I18N::translate('Date of entry in original source')), 676 'INDI:NAME:*:SOUR:DATA:TEXT' => new TextFromSource(I18N::translate('Text')), 677 'INDI:NAME:*:SOUR:EVEN' => new EventTypeCitedFrom(I18N::translate('Event')), 678 'INDI:NAME:*:SOUR:EVEN:ROLE' => new RoleInEvent(I18N::translate('Role')), 679 'INDI:NAME:*:SOUR:NOTE' => new NoteStructure(I18N::translate('Note on source citation')), 680 'INDI:NAME:*:SOUR:OBJE' => new XrefMedia(I18N::translate('Media object')), 681 'INDI:NAME:*:SOUR:PAGE' => new WhereWithinSource(I18N::translate('Citation details')), 682 'INDI:NAME:*:SOUR:QUAY' => new CertaintyAssessment(I18N::translate('Quality of data')), 683 'INDI:NAME:FONE' => new NamePhoneticVariation(I18N::translate('Phonetic name')), 684 'INDI:NAME:FONE:GIVN' => new NamePieceGiven(I18N::translate('Given names')), 685 'INDI:NAME:FONE:NICK' => new NamePieceNickname(I18N::translate('Nickname')), 686 'INDI:NAME:FONE:NOTE' => new NoteStructure(I18N::translate('Note on phonetic name')), 687 'INDI:NAME:FONE:NPFX' => new NamePiecePrefix(I18N::translate('Name prefix')), 688 'INDI:NAME:FONE:NSFX' => new NamePieceSuffix(I18N::translate('Name suffix')), 689 'INDI:NAME:FONE:SOUR' => new XrefSource(I18N::translate('Source citation')), 690 'INDI:NAME:FONE:SPFX' => new NamePieceSurnamePrefix(I18N::translate('Surname prefix')), 691 'INDI:NAME:FONE:SURN' => new NamePieceSurname(I18N::translate('Surname')), 692 'INDI:NAME:FONE:TYPE' => new PhoneticType(I18N::translate('Phonetic type')), 693 'INDI:NAME:GIVN' => new NamePieceGiven(I18N::translate('Given names')), 694 'INDI:NAME:NICK' => new NamePieceNickname(I18N::translate('Nickname')), 695 'INDI:NAME:NPFX' => new NamePiecePrefix(I18N::translate('Name prefix')), 696 'INDI:NAME:NSFX' => new NamePieceSuffix(I18N::translate('Name suffix')), 697 'INDI:NAME:ROMN' => new NameRomanizedVariation(I18N::translate('Romanized name')), 698 'INDI:NAME:ROMN:GIVN' => new NamePieceGiven(I18N::translate('Given names')), 699 'INDI:NAME:ROMN:NICK' => new NamePieceNickname(I18N::translate('Nickname')), 700 'INDI:NAME:ROMN:NOTE' => new NoteStructure(I18N::translate('Note on romanized name')), 701 'INDI:NAME:ROMN:NPFX' => new NamePiecePrefix(I18N::translate('Name prefix')), 702 'INDI:NAME:ROMN:NSFX' => new NamePieceSuffix(I18N::translate('Name suffix')), 703 'INDI:NAME:ROMN:SOUR' => new XrefSource(I18N::translate('Source citation')), 704 'INDI:NAME:ROMN:SPFX' => new NamePieceSurnamePrefix(I18N::translate('Surname prefix')), 705 'INDI:NAME:ROMN:SURN' => new NamePieceSurname(I18N::translate('Surname')), 706 'INDI:NAME:ROMN:TYPE' => new RomanizedType(I18N::translate('Romanized type')), 707 'INDI:NAME:SPFX' => new NamePieceSurnamePrefix(I18N::translate('Surname prefix')), 708 'INDI:NAME:SURN' => new NamePieceSurname(I18N::translate('Surname')), 709 'INDI:NAME:TYPE' => new NameType(I18N::translate('Type of name')), 710 'INDI:NATI' => new NationalOrTribalOrigin(I18N::translate('Nationality')), 711 'INDI:NATU' => new Naturalization(I18N::translate('Naturalization')), 712 'INDI:NATU:DATE' => new DateValue(I18N::translate('Date of naturalization')), 713 'INDI:NATU:PLAC' => new PlaceName(I18N::translate('Place of naturalization')), 714 'INDI:NCHI' => new CountOfChildren(I18N::translate('Number of children')), 715 'INDI:NMR' => new CountOfMarriages(I18N::translate('Number of marriages')), 716 'INDI:NOTE' => new NoteStructure(I18N::translate('Note')), 717 'INDI:OBJE' => new XrefMedia(I18N::translate('Media object')), 718 'INDI:OCCU' => new Occupation(I18N::translate('Occupation')), 719 'INDI:OCCU:AGNC' => new ResponsibleAgency(I18N::translate('Employer')), 720 'INDI:ORDN' => new Ordination(I18N::translate('Ordination')), 721 'INDI:ORDN:AGNC' => new ResponsibleAgency(I18N::translate('Religious institution')), 722 'INDI:ORDN:DATE' => new DateValue(I18N::translate('Date of ordination')), 723 'INDI:ORDN:PLAC' => new PlaceName(I18N::translate('Place of ordination')), 724 'INDI:PROB' => new Probate(I18N::translate('Probate')), 725 'INDI:PROP' => new Possessions(I18N::translate('Property')), 726 'INDI:REFN' => new UserReferenceNumber(I18N::translate('Reference number')), 727 'INDI:REFN:TYPE' => new UserReferenceType(I18N::translate('Type of reference number')), 728 'INDI:RELI' => new ReligiousAffiliation(I18N::translate('Religion')), 729 'INDI:RESI' => new Residence(I18N::translate('Residence')), 730 'INDI:RESI:DATE' => new DateValue(I18N::translate('Date of residence')), 731 'INDI:RESI:PLAC' => new PlaceName(I18N::translate('Place of residence')), 732 'INDI:RESN' => new RestrictionNotice(I18N::translate('Restriction')), 733 'INDI:RETI' => new Retirement(I18N::translate('Retirement')), 734 'INDI:RETI:AGNC' => new ResponsibleAgency(I18N::translate('Employer')), 735 'INDI:RFN' => new PermanentRecordFileNumber(I18N::translate('Record file number')), 736 'INDI:RIN' => new AutomatedRecordId(I18N::translate('Record ID number')), 737 'INDI:SEX' => new SexValue(I18N::translate('Gender')), 738 'INDI:SLGC' => new LdsChildSealing(I18N::translate('LDS child sealing')), 739 'INDI:SLGC:DATE' => new DateLdsOrd(I18N::translate('Date of LDS child sealing')), 740 'INDI:SLGC:FAMC' => new XrefFamily(I18N::translate('Parents')), 741 'INDI:SLGC:PLAC' => new PlaceLivingOrdinance(I18N::translate('Place of LDS child sealing')), 742 'INDI:SLGC:STAT' => new LdsChildSealingDateStatus(I18N::translate('Status')), 743 'INDI:SLGC:STAT:DATE' => new DateValueExact(I18N::translate('Status change date')), 744 'INDI:SLGC:TEMP' => new TempleCode(I18N::translate('Temple')), 745 'INDI:SOUR' => new XrefSource(I18N::translate('Source citation')), 746 'INDI:SOUR:DATA' => new SourceData(I18N::translate('Data')), 747 'INDI:SOUR:DATA:DATE' => new DateValue(I18N::translate('Date of entry in original source')), 748 'INDI:SOUR:DATA:TEXT' => new TextFromSource(I18N::translate('Text')), 749 'INDI:SOUR:EVEN' => new EventTypeCitedFrom(I18N::translate('Event')), 750 'INDI:SOUR:EVEN:ROLE' => new RoleInEvent(I18N::translate('Role')), 751 'INDI:SOUR:NOTE' => new NoteStructure(I18N::translate('Note on source citation')), 752 'INDI:SOUR:OBJE' => new XrefMedia(I18N::translate('Media object')), 753 'INDI:SOUR:PAGE' => new WhereWithinSource(I18N::translate('Citation details')), 754 'INDI:SOUR:QUAY' => new CertaintyAssessment(I18N::translate('Quality of data')), 755 'INDI:SSN' => new SocialSecurityNumber(I18N::translate('Social security number')), 756 'INDI:SUBM' => new XrefSubmitter(I18N::translate('Submitter')), 757 'INDI:TITL' => new NobilityTypeTitle(I18N::translate('Title')), 758 'INDI:WILL' => new Will(I18N::translate('Will')), 759 'NOTE' => new NoteRecord(I18N::translate('Shared note')), 760 'NOTE:CHAN' => new Change(I18N::translate('Last change')), 761 'NOTE:CHAN:DATE' => new ChangeDate(I18N::translate('Date of last change')), 762 'NOTE:CHAN:DATE:TIME' => new TimeValueNow(I18N::translate('Time of last change')), 763 'NOTE:CHAN:NOTE' => new NoteStructure(I18N::translate('Note on last change')), 764 'NOTE:CONC' => new SubmitterText(I18N::translate('Note')), 765 'NOTE:CONT' => new SubmitterText(I18N::translate('Continuation')), 766 'NOTE:REFN' => new UserReferenceNumber(I18N::translate('Reference number')), 767 'NOTE:REFN:TYPE' => new UserReferenceType(I18N::translate('Type of reference number')), 768 'NOTE:RIN' => new AutomatedRecordId(I18N::translate('Record ID number')), 769 'NOTE:SOUR' => new XrefSource(I18N::translate('Source citation')), 770 'NOTE:SOUR:DATA' => new SourceData(I18N::translate('Data')), 771 'NOTE:SOUR:DATA:DATE' => new DateValue(I18N::translate('Date of entry in original source')), 772 'NOTE:SOUR:DATA:TEXT' => new TextFromSource(I18N::translate('Text')), 773 'NOTE:SOUR:EVEN' => new EventTypeCitedFrom(I18N::translate('Event')), 774 'NOTE:SOUR:EVEN:ROLE' => new RoleInEvent(I18N::translate('Role')), 775 'NOTE:SOUR:NOTE' => new NoteStructure(I18N::translate('Note on source citation')), 776 'NOTE:SOUR:OBJE' => new XrefMedia(I18N::translate('Media object')), 777 'NOTE:SOUR:PAGE' => new WhereWithinSource(I18N::translate('Citation details')), 778 'NOTE:SOUR:QUAY' => new CertaintyAssessment(I18N::translate('Quality of data')), 779 'OBJE' => new MediaRecord(I18N::translate('Media object')), 780 'OBJE:BLOB' => new CustomElement(I18N::translate('Binary data object')), 781 'OBJE:CHAN' => new Change(I18N::translate('Last change')), 782 'OBJE:CHAN:DATE' => new ChangeDate(I18N::translate('Date of last change')), 783 'OBJE:CHAN:DATE:TIME' => new TimeValueNow(I18N::translate('Time of last change')), 784 'OBJE:CHAN:NOTE' => new NoteStructure(I18N::translate('Note on last change')), 785 'OBJE:FILE' => new MultimediaFileReference(I18N::translate('Filename')), 786 'OBJE:FILE:FORM' => new MultimediaFormat(I18N::translate('Format')), 787 'OBJE:FILE:FORM:TYPE' => new SourceMediaType(I18N::translate('Media type')), 788 'OBJE:FILE:TITL' => new DescriptiveTitle(I18N::translate('Title')), 789 'OBJE:NOTE' => new NoteStructure(I18N::translate('Note')), 790 'OBJE:REFN' => new UserReferenceNumber(I18N::translate('Reference number')), 791 'OBJE:REFN:TYPE' => new UserReferenceType(I18N::translate('Type of reference number')), 792 'OBJE:RIN' => new AutomatedRecordId(I18N::translate('Record ID number')), 793 'OBJE:SOUR' => new XrefSource(I18N::translate('Source citation')), 794 'OBJE:SOUR:DATA' => new SourceData(I18N::translate('Data')), 795 'OBJE:SOUR:DATA:DATE' => new DateValue(I18N::translate('Date of entry in original source')), 796 'OBJE:SOUR:DATA:TEXT' => new TextFromSource(I18N::translate('Text')), 797 'OBJE:SOUR:EVEN' => new EventTypeCitedFrom(I18N::translate('Event')), 798 'OBJE:SOUR:EVEN:ROLE' => new RoleInEvent(I18N::translate('Role')), 799 'OBJE:SOUR:NOTE' => new NoteStructure(I18N::translate('Note on source citation')), 800 'OBJE:SOUR:OBJE' => new XrefMedia(I18N::translate('Media object')), 801 'OBJE:SOUR:PAGE' => new WhereWithinSource(I18N::translate('Citation details')), 802 'OBJE:SOUR:QUAY' => new CertaintyAssessment(I18N::translate('Quality of data')), 803 'REPO' => new RepositoryRecord(I18N::translate('Repository')), 804 'REPO:ADDR' => new AddressLine(I18N::translate('Address')), 805 'REPO:ADDR:ADR1' => new AddressLine1(I18N::translate('Address line 1')), 806 'REPO:ADDR:ADR2' => new AddressLine2(I18N::translate('Address line 2')), 807 'REPO:ADDR:ADR3' => new AddressLine3(I18N::translate('Address line 3')), 808 'REPO:ADDR:CITY' => new AddressCity(I18N::translate('City')), 809 'REPO:ADDR:CTRY' => new AddressCountry(I18N::translate('Country')), 810 'REPO:ADDR:POST' => new AddressPostalCode(I18N::translate('Postal code')), 811 'REPO:ADDR:STAE' => new AddressState(I18N::translate('State')), 812 'REPO:CHAN' => new Change(I18N::translate('Last change')), 813 'REPO:CHAN:DATE' => new ChangeDate(I18N::translate('Date of last change')), 814 'REPO:CHAN:DATE:TIME' => new TimeValueNow(I18N::translate('Time of last change')), 815 'REPO:CHAN:NOTE' => new NoteStructure(I18N::translate('Note on last change')), 816 'REPO:EMAIL' => new AddressEmail(I18N::translate('Email address')), 817 'REPO:FAX' => new AddressFax(I18N::translate('Fax')), 818 'REPO:NAME' => new NameOfRepository(I18N::translateContext('Repository', 'Name')), 819 'REPO:NOTE' => new NoteStructure(I18N::translate('Note')), 820 'REPO:PHON' => new PhoneNumber(I18N::translate('Phone')), 821 'REPO:REFN' => new UserReferenceNumber(I18N::translate('Reference number')), 822 'REPO:REFN:TYPE' => new UserReferenceType(I18N::translate('Type of reference number')), 823 'REPO:RIN' => new AutomatedRecordId(I18N::translate('Record ID number')), 824 'REPO:WWW' => new AddressWebPage(I18N::translate('URL')), 825 'SOUR' => new SourceRecord(I18N::translate('Source')), 826 'SOUR:ABBR' => new SourceFiledByEntry(I18N::translate('Abbreviation')), 827 'SOUR:AUTH' => new SourceOriginator(I18N::translate('Author')), 828 'SOUR:CHAN' => new Change(I18N::translate('Last change')), 829 'SOUR:CHAN:DATE' => new ChangeDate(I18N::translate('Date of last change')), 830 'SOUR:CHAN:DATE:TIME' => new TimeValueNow(I18N::translate('Time of last change')), 831 'SOUR:CHAN:NOTE' => new NoteStructure(I18N::translate('Note on last change')), 832 'SOUR:DATA' => new EmptyElement(I18N::translate('Data'), ['EVEN' => '0:M', 'AGNC' => '0:1', 'NOTE' => '0:M']), 833 'SOUR:DATA:AGNC' => new ResponsibleAgency(I18N::translate('Agency')), 834 'SOUR:DATA:EVEN' => new EventsRecorded(I18N::translate('Events')), 835 'SOUR:DATA:EVEN:DATE' => new DateValue(I18N::translate('Date range')), 836 'SOUR:DATA:EVEN:PLAC' => new SourceJurisdictionPlace(I18N::translate('Place'), []), 837 'SOUR:DATA:NOTE' => new NoteStructure(I18N::translate('Note on source data')), 838 'SOUR:NOTE' => new NoteStructure(I18N::translate('Note on source')), 839 'SOUR:OBJE' => new XrefMedia(I18N::translate('Media object')), 840 'SOUR:PUBL' => new SourcePublicationFacts(I18N::translate('Publication')), 841 'SOUR:REFN' => new UserReferenceNumber(I18N::translate('Reference number')), 842 'SOUR:REFN:TYPE' => new UserReferenceType(I18N::translate('Type of reference number')), 843 'SOUR:REPO' => new XrefRepository(I18N::translate('Repository')), 844 'SOUR:REPO:CALN' => new SourceCallNumber(I18N::translate('Call number')), 845 'SOUR:REPO:CALN:MEDI' => new SourceMediaType(I18N::translate('Media type')), 846 'SOUR:REPO:NOTE' => new NoteStructure(I18N::translate('Note on repository reference')), 847 'SOUR:RIN' => new AutomatedRecordId(I18N::translate('Record ID number')), 848 'SOUR:TEXT' => new TextFromSource(I18N::translate('Text')), 849 'SOUR:TITL' => new DescriptiveTitle(I18N::translate('Title')), 850 'SUBM' => new SubmitterRecord(I18N::translate('Submitter')), 851 'SUBM:ADDR' => new AddressLine(I18N::translate('Address')), 852 'SUBM:ADDR:ADR1' => new AddressLine1(I18N::translate('Address line 1')), 853 'SUBM:ADDR:ADR2' => new AddressLine2(I18N::translate('Address line 2')), 854 'SUBM:ADDR:ADR3' => new AddressLine3(I18N::translate('Address line 3')), 855 'SUBM:ADDR:CITY' => new AddressCity(I18N::translate('City')), 856 'SUBM:ADDR:CTRY' => new AddressCountry(I18N::translate('Country')), 857 'SUBM:ADDR:POST' => new AddressPostalCode(I18N::translate('Postal code')), 858 'SUBM:ADDR:STAE' => new AddressState(I18N::translate('State')), 859 'SUBM:CHAN' => new Change(I18N::translate('Last change')), 860 'SUBM:CHAN:DATE' => new ChangeDate(I18N::translate('Date of last change')), 861 'SUBM:CHAN:DATE:TIME' => new TimeValueNow(I18N::translate('Time of last change')), 862 'SUBM:CHAN:NOTE' => new NoteStructure(I18N::translate('Note on last change')), 863 'SUBM:EMAIL' => new AddressEmail(I18N::translate('Email address')), 864 'SUBM:FAX' => new AddressFax(I18N::translate('Fax')), 865 'SUBM:LANG' => new LanguageId(I18N::translate('Language')), 866 'SUBM:NAME' => new SubmitterName(I18N::translate('Name')), 867 'SUBM:NOTE' => new NoteStructure(I18N::translate('Note')), 868 'SUBM:OBJE' => new XrefMedia(I18N::translate('Media object')), 869 'SUBM:PHON' => new PhoneNumber(I18N::translate('Phone')), 870 'SUBM:RFN' => new SubmitterRegisteredRfn(I18N::translate('Record file number')), 871 'SUBM:RIN' => new AutomatedRecordId(I18N::translate('Record ID number')), 872 'SUBM:WWW' => new AddressWebPage(I18N::translate('URL')), 873 'SUBN' => new SubmissionRecord(I18N::translate('Submission')), 874 'SUBN:ANCE' => new GenerationsOfAncestors(I18N::translate('Generations of ancestors')), 875 'SUBN:CHAN' => new Change(I18N::translate('Last change')), 876 'SUBN:CHAN:DATE' => new ChangeDate(I18N::translate('Date of last change')), 877 'SUBN:CHAN:DATE:TIME' => new TimeValueNow(I18N::translate('Time of last change')), 878 'SUBN:CHAN:NOTE' => new NoteStructure(I18N::translate('Note on last change')), 879 'SUBN:DESC' => new GenerationsOfDescendants(I18N::translate('Generations of descendants')), 880 'SUBN:FAMF' => new NameOfFamilyFile(I18N::translate('Family file')), 881 'SUBN:NOTE' => new NoteStructure(I18N::translate('Note')), 882 'SUBN:ORDI' => new OrdinanceProcessFlag(I18N::translate('Ordinance')), 883 'SUBN:RIN' => new AutomatedRecordId(I18N::translate('Record ID number')), 884 'SUBN:SUBM' => new XrefSubmitter(I18N::translate('Submitter')), 885 'SUBN:TEMP' => new TempleCode(/* I18N: https://en.wikipedia.org/wiki/Temple_(LDS_Church)*/ I18N::translate('Temple')), 886 'TRLR' => new EmptyElement(I18N::translate('Trailer')), 887 ]; 888 } 889 890 /** 891 * Custom tags for webtrees. 892 * 893 * @return array<string,ElementInterface> 894 */ 895 private function webtreesTags(): array 896 { 897 return [ 898 'FAM:CHAN:_WT_USER' => new WebtreesUser(I18N::translate('Author of last change')), 899 'FAM:*:_ASSO' => new XrefAssociate(I18N::translate('Associate')), 900 'FAM:*:_ASSO:NOTE' => new NoteStructure(I18N::translate('Note on association')), 901 'FAM:*:_ASSO:RELA' => new RelationIsDescriptor(I18N::translate('Relationship')), 902 'FAM:*:_ASSO:SOUR' => new XrefSource(I18N::translate('Source citation')), 903 'FAM:*:_ASSO:SOUR:DATA' => new SourceData(I18N::translate('Data')), 904 'FAM:*:_ASSO:SOUR:DATA:DATE' => new DateValue(I18N::translate('Date of entry in original source')), 905 'FAM:*:_ASSO:SOUR:DATA:TEXT' => new TextFromSource(I18N::translate('Text')), 906 'FAM:*:_ASSO:SOUR:EVEN' => new EventTypeCitedFrom(I18N::translate('Event')), 907 'FAM:*:_ASSO:SOUR:EVEN:ROLE' => new RoleInEvent(I18N::translate('Role')), 908 'FAM:*:_ASSO:SOUR:NOTE' => new NoteStructure(I18N::translate('Note on source citation')), 909 'FAM:*:_ASSO:SOUR:OBJE' => new XrefMedia(I18N::translate('Media object')), 910 'FAM:*:_ASSO:SOUR:PAGE' => new WhereWithinSource(I18N::translate('Citation details')), 911 'FAM:*:_ASSO:SOUR:QUAY' => new CertaintyAssessment(I18N::translate('Quality of data')), 912 'INDI:CHAN:_WT_USER' => new WebtreesUser(I18N::translate('Author of last change')), 913 'INDI:*:_ASSO' => new XrefAssociate(I18N::translate('Associate')), 914 'INDI:*:_ASSO:NOTE' => new NoteStructure(I18N::translate('Note on association')), 915 'INDI:*:_ASSO:RELA' => new RelationIsDescriptor(I18N::translate('Relationship')), 916 'INDI:*:_ASSO:SOUR' => new XrefSource(I18N::translate('Source citation')), 917 'INDI:*:_ASSO:SOUR:DATA' => new SourceData(I18N::translate('Data')), 918 'INDI:*:_ASSO:SOUR:DATA:DATE' => new DateValue(I18N::translate('Date of entry in original source')), 919 'INDI:*:_ASSO:SOUR:DATA:TEXT' => new TextFromSource(I18N::translate('Text')), 920 'INDI:*:_ASSO:SOUR:EVEN' => new EventTypeCitedFrom(I18N::translate('Event')), 921 'INDI:*:_ASSO:SOUR:EVEN:ROLE' => new RoleInEvent(I18N::translate('Role')), 922 'INDI:*:_ASSO:SOUR:NOTE' => new NoteStructure(I18N::translate('Note on source citation')), 923 'INDI:*:_ASSO:SOUR:OBJE' => new XrefMedia(I18N::translate('Media object')), 924 'INDI:*:_ASSO:SOUR:PAGE' => new WhereWithinSource(I18N::translate('Citation details')), 925 'INDI:*:_ASSO:SOUR:QUAY' => new CertaintyAssessment(I18N::translate('Quality of data')), 926 'NOTE:CHAN:_WT_USER' => new WebtreesUser(I18N::translate('Author of last change')), 927 'NOTE:RESN' => new RestrictionNotice(I18N::translate('Restriction')), 928 'OBJE:CHAN:_WT_USER' => new WebtreesUser(I18N::translate('Author of last change')), 929 'OBJE:RESN' => new RestrictionNotice(I18N::translate('Restriction')), 930 'REPO:CHAN:_WT_USER' => new WebtreesUser(I18N::translate('Author of last change')), 931 'REPO:RESN' => new RestrictionNotice(I18N::translate('Restriction')), 932 'SOUR:CHAN:_WT_USER' => new WebtreesUser(I18N::translate('Author of last change')), 933 'SOUR:RESN' => new RestrictionNotice(I18N::translate('Restriction')), 934 'SUBM:CHAN:_WT_USER' => new WebtreesUser(I18N::translate('Author of last change')), 935 'SUBM:RESN' => new RestrictionNotice(I18N::translate('Restriction')), 936 '_LOC:CHAN:_WT_USER' => new WebtreesUser(I18N::translate('Author of last change')), 937 '_LOC:RESN' => new RestrictionNotice(I18N::translate('Restriction')), 938 ]; 939 } 940 941 /** 942 * @return array<string,array<int,array<int,string>>> 943 */ 944 private function webtreesSubTags(): array 945 { 946 return [ 947 'FAM' => [['_UID', '0:M']], 948 'FAM:*:SOUR:DATA' => [['TEXT', '0:1']], 949 'FAM:ANUL' => [['_ASSO', '0:M', 'NOTE']], 950 'FAM:CENS' => [['_ASSO', '0:M', 'NOTE']], 951 'FAM:CHAN' => [['_WT_USER', '0:1']], 952 'FAM:DIV' => [['_ASSO', '0:M', 'NOTE']], 953 'FAM:DIVF' => [['_ASSO', '0:M', 'NOTE']], 954 'FAM:ENGA' => [['_ASSO', '0:M', 'NOTE']], 955 'FAM:EVEN' => [['_ASSO', '0:M', 'NOTE']], 956 'FAM:MARB' => [['_ASSO', '0:M', 'NOTE']], 957 'FAM:MARC' => [['_ASSO', '0:M', 'NOTE']], 958 'FAM:MARL' => [['_ASSO', '0:M', 'NOTE']], 959 'FAM:MARR' => [['_ASSO', '2:M', 'NOTE']], 960 'FAM:MARS' => [['_ASSO', '0:M', 'NOTE']], 961 'FAM:SLGS' => [['_ASSO', '0:M', 'NOTE']], 962 'FAM:SOUR:DATA' => [['TEXT', '0:1']], 963 'INDI' => [['_UID', '0:M']], 964 'INDI:*:SOUR:DATA' => [['TEXT', '0:1']], 965 'INDI:ADOP' => [['_ASSO', '0:M', 'NOTE']], 966 'INDI:BAPL' => [['_ASSO', '0:M', 'NOTE']], 967 'INDI:BAPM' => [['_ASSO', '2:M', 'NOTE']], 968 'INDI:BARM' => [['_ASSO', '0:M', 'NOTE']], 969 'INDI:BASM' => [['_ASSO', '0:M', 'NOTE']], 970 'INDI:BIRT' => [['_ASSO', '0:M', 'NOTE'], ['FAMC', '0:0']], 971 'INDI:BURI' => [['_ASSO', '0:M', 'NOTE']], 972 'INDI:CENS' => [['_ASSO', '0:M', 'NOTE']], 973 'INDI:CHAN' => [['_WT_USER', '0:1']], 974 'INDI:CHR' => [['_ASSO', '2:M', 'NOTE']], 975 'INDI:CHRA' => [['_ASSO', '0:M', 'NOTE']], 976 'INDI:CONF' => [['_ASSO', '0:M', 'NOTE']], 977 'INDI:CONL' => [['_ASSO', '0:M', 'NOTE']], 978 'INDI:CREM' => [['_ASSO', '0:M', 'NOTE']], 979 'INDI:DEAT' => [['_ASSO', '0:M', 'NOTE']], 980 'INDI:EDUC' => [['_ASSO', '0:M', 'NOTE']], 981 'INDI:EMIG' => [['_ASSO', '0:M', 'NOTE']], 982 'INDI:ENDL' => [['_ASSO', '0:M', 'NOTE']], 983 'INDI:EVEN' => [['_ASSO', '0:M', 'NOTE']], 984 'INDI:GRAD' => [['_ASSO', '0:M', 'NOTE']], 985 'INDI:IMMI' => [['_ASSO', '0:M', 'NOTE']], 986 'INDI:NATU' => [['_ASSO', '0:M', 'NOTE']], 987 'INDI:OCCU' => [['_ASSO', '0:M', 'NOTE']], 988 'INDI:ORDN' => [['_ASSO', '0:M', 'NOTE']], 989 'INDI:PROB' => [['_ASSO', '0:M', 'NOTE']], 990 'INDI:PROP' => [['_ASSO', '0:M', 'NOTE']], 991 'INDI:RESI' => [['_ASSO', '0:M', 'NOTE']], 992 'INDI:RETI' => [['_ASSO', '0:M', 'NOTE']], 993 'INDI:SLGC' => [['_ASSO', '0:M', 'NOTE']], 994 'INDI:SOUR:DATA' => [['TEXT', '0:1']], 995 'INDI:TITL' => [['_ASSO', '0:M', 'NOTE']], 996 'INDI:WILL' => [['_ASSO', '0:M', 'NOTE']], 997 'NOTE' => [['RESN', '0:1', 'CHAN']], 998 'NOTE:CHAN' => [['_WT_USER', '0:1']], 999 'NOTE:SOUR:DATA' => [['TEXT', '0:1']], 1000 'OBJE' => [['RESN', '0:1', 'CHAN'], ['_UID', '0:M']], 1001 'OBJE:CHAN' => [['_WT_USER', '0:1']], 1002 'OBJE:SOUR:DATA' => [['TEXT', '0:1']], 1003 'REPO' => [['RESN', '0:1', 'CHAN'], ['_UID', '0:M']], 1004 'REPO:CHAN' => [['_WT_USER', '0:1']], 1005 'SOUR' => [['RESN', '0:1', 'CHAN'], ['_UID', '0:M']], 1006 'SOUR:CHAN' => [['_WT_USER', '0:1']], 1007 'SUBM' => [['RESN', '0:1', 'CHAN']], 1008 'SUBM:CHAN' => [['_WT_USER', '0:1']], 1009 ]; 1010 } 1011 1012 /** 1013 * @return array<string,array<int,array<int,string>>> 1014 */ 1015 private function customSubTags(): array 1016 { 1017 $custom_family_tags = array_filter(explode(',', Site::getPreference('CUSTOM_FAMILY_TAGS'))); 1018 $custom_individual_tags = array_filter(explode(',', Site::getPreference('CUSTOM_INDIVIDUAL_TAGS'))); 1019 1020 $subtags = [ 1021 'FAM' => array_map(static fn (string $tag): array => [$tag, '0:M'], $custom_family_tags), 1022 'INDI' => array_map(static fn (string $tag): array => [$tag, '0:M'], $custom_individual_tags), 1023 ]; 1024 1025 // GEDCOM 7 tags 1026 if (Site::getPreference('CUSTOM_FAM_FACT') === '1') { 1027 $subtags['FAM'][] = ['FACT', '0:M']; 1028 } 1029 if (Site::getPreference('CUSTOM_FAM_NCHI') === '1') { 1030 $subtags['FAM:NCHI'] = [ 1031 ['TYPE', '0:1:?'], 1032 ['DATE', '0:1'], 1033 ['PLAC', '0:1:?'], 1034 ['ADDR', '0:1:?'], 1035 ['EMAIL', '0:1:?'], 1036 ['WWW', '0:1:?'], 1037 ['PHON', '0:1:?'], 1038 ['FAX', '0:1:?'], 1039 ['CAUS', '0:1:?'], 1040 ['AGNC', '0:1:?'], 1041 ['RELI', '0:1:?'], 1042 ['NOTE', '0:M'], 1043 ['OBJE', '0:M'], 1044 ['SOUR', '0:M'], 1045 ['RESN', '0:1'], 1046 ]; 1047 } 1048 1049 if (Site::getPreference('CUSTOM_TIME_TAGS') === '1') { 1050 $subtags['INDI:BIRT:DATE'][] = ['TIME', '0:1']; 1051 $subtags['INDI:DEAT:DATE'][] = ['TIME', '0:1']; 1052 } 1053 1054 if (Site::getPreference('CUSTOM_GEDCOM_L_TAGS') === '1') { 1055 $subtags['FAM'][] = ['_ASSO', '0:M']; 1056 $subtags['FAM'][] = ['_STAT', '0:1']; 1057 $subtags['FAM'][] = ['_UID', '0:M']; 1058 $subtags['FAM:*:ADDR'] = [['_NAME', '0:1:?', 'ADR1']]; 1059 $subtags['FAM:*:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1060 $subtags['FAM:ENGA:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1061 $subtags['FAM:MARB:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1062 $subtags['FAM:MARR'] = [['_WITN', '0:1']]; 1063 $subtags['FAM:MARR:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1064 $subtags['FAM:SLGS:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1065 $subtags['INDI'][] = ['_UID', '0:M']; 1066 $subtags['INDI:*:ADDR'] = [['_NAME', '0:1:?', 'ADR1']]; 1067 $subtags['INDI:*:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1068 $subtags['INDI:ADOP:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1069 $subtags['INDI:BAPL:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1070 $subtags['INDI:BAPM'] = [['_GODP', '0:1'], ['_WITN', '0:1']]; 1071 $subtags['INDI:BAPM:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1072 $subtags['INDI:BARM:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1073 $subtags['INDI:BASM:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1074 $subtags['INDI:BIRT:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1075 $subtags['INDI:BLES:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1076 $subtags['INDI:BURI:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1077 $subtags['INDI:CENS:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1078 $subtags['INDI:CHR'] = [['_GODP', '0:1'], ['_WITN', '0:1']]; 1079 $subtags['INDI:CHR:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1080 $subtags['INDI:CHRA:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1081 $subtags['INDI:CONF:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1082 $subtags['INDI:CONL:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1083 $subtags['INDI:CREM:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1084 $subtags['INDI:DEAT:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1085 $subtags['INDI:EMIG:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1086 $subtags['INDI:ENDL:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1087 $subtags['INDI:EVEN:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1088 $subtags['INDI:FCOM:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1089 $subtags['INDI:IMMI:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1090 $subtags['INDI:NAME'] = [['_RUFNAME', '0:1', 'SPFX']]; 1091 $subtags['INDI:NATU:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1092 $subtags['INDI:ORDN:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1093 $subtags['INDI:RESI:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1094 $subtags['INDI:SLGC:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1095 $subtags['NOTE'] = [['_UID', '0:M']]; 1096 $subtags['OBJE'] = [['_PRIM', '0:1:?'], ['_UID', '0:M']]; 1097 $subtags['REPO'] = [['_UID', '0:M']]; 1098 $subtags['REPO:ADDR'] = [['_NAME', '0:1', 'ADR1']]; 1099 $subtags['SOUR'] = [['_UID', '0:M']]; 1100 $subtags['SOUR:DATA:EVEN:PLAC'] = [['_POST', '0:1'], ['_MAIDENHEAD', '0:1:?'], ['_LOC', '0:1'], ['_GOV', '0:1']]; 1101 $subtags['SUBM'] = [['_UID', '0:M']]; 1102 $subtags['SUBM:ADDR'] = [['_NAME', '0:1', 'ADR1']]; 1103 } 1104 1105 return $subtags; 1106 } 1107 1108 /** 1109 * @param ElementFactoryInterface $element_factory 1110 * @param bool $include_custom_tags 1111 * 1112 * @return void 1113 */ 1114 public function registerTags(ElementFactoryInterface $element_factory, bool $include_custom_tags): void 1115 { 1116 // Standard GEDCOM. 1117 $element_factory->registerTags($this->gedcom551Tags()); 1118 1119 // webtrees extensions. 1120 $element_factory->registerTags($this->webtreesTags()); 1121 1122 if ($include_custom_tags) { 1123 // webtrees extensions. 1124 $element_factory->registerSubTags($this->webtreesSubTags()); 1125 1126 $custom_tags = [ 1127 new Aldfaer(), 1128 new Ancestry(), 1129 new BrothersKeeper(), 1130 new FamilySearch(), 1131 new FamilyTreeBuilder(), 1132 new FamilyTreeMaker(), 1133 new Gedcom7(), 1134 new GedcomL(), 1135 new Geneatique(), 1136 new GenPlusWin(), 1137 new Heredis(), 1138 new Legacy(), 1139 new MyHeritage(), 1140 new PersonalAncestralFile(), 1141 new PhpGedView(), 1142 new ProGen(), 1143 new Reunion(), 1144 new RootsMagic(), 1145 ]; 1146 1147 foreach ($custom_tags as $custom_tag) { 1148 $element_factory->registerTags($custom_tag->tags()); 1149 } 1150 1151 // Creating tags from all the above are grouped into one place 1152 $element_factory->registerSubTags($this->customSubTags()); 1153 } 1154 } 1155} 1156