xref: /webtrees/app/Factories/ElementFactory.php (revision 4dbb2a39d4ff3907e4739e53d4c0af9bf637bb4d)
1<?php
2
3/**
4 * webtrees: online genealogy
5 * Copyright (C) 2021 webtrees development team
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18declare(strict_types=1);
19
20namespace Fisharebest\Webtrees\Factories;
21
22use Fisharebest\Webtrees\Contracts\ElementFactoryInterface;
23use Fisharebest\Webtrees\Contracts\ElementInterface;
24use Fisharebest\Webtrees\Elements\AddressCity;
25use Fisharebest\Webtrees\Elements\AddressCountry;
26use Fisharebest\Webtrees\Elements\AddressEmail;
27use Fisharebest\Webtrees\Elements\AddressFax;
28use Fisharebest\Webtrees\Elements\AddressLine;
29use Fisharebest\Webtrees\Elements\AddressLine1;
30use Fisharebest\Webtrees\Elements\AddressLine2;
31use Fisharebest\Webtrees\Elements\AddressLine3;
32use Fisharebest\Webtrees\Elements\AddressPostalCode;
33use Fisharebest\Webtrees\Elements\AddressState;
34use Fisharebest\Webtrees\Elements\AddressWebPage;
35use Fisharebest\Webtrees\Elements\AdoptedByWhichParent;
36use Fisharebest\Webtrees\Elements\Adoption;
37use Fisharebest\Webtrees\Elements\AdultChristening;
38use Fisharebest\Webtrees\Elements\AgeAtEvent;
39use Fisharebest\Webtrees\Elements\AncestralFileNumber;
40use Fisharebest\Webtrees\Elements\Annulment;
41use Fisharebest\Webtrees\Elements\ApprovedSystemId;
42use Fisharebest\Webtrees\Elements\AttributeDescriptor;
43use Fisharebest\Webtrees\Elements\AutomatedRecordId;
44use Fisharebest\Webtrees\Elements\Baptism;
45use Fisharebest\Webtrees\Elements\BasMitzvah;
46use Fisharebest\Webtrees\Elements\Birth;
47use Fisharebest\Webtrees\Elements\Blessing;
48use Fisharebest\Webtrees\Elements\Burial;
49use Fisharebest\Webtrees\Elements\CasteName;
50use Fisharebest\Webtrees\Elements\CauseOfEvent;
51use Fisharebest\Webtrees\Elements\Census;
52use Fisharebest\Webtrees\Elements\CertaintyAssessment;
53use Fisharebest\Webtrees\Elements\Change;
54use Fisharebest\Webtrees\Elements\ChangeDate;
55use Fisharebest\Webtrees\Elements\CharacterSet;
56use Fisharebest\Webtrees\Elements\ChildLinkageStatus;
57use Fisharebest\Webtrees\Elements\Christening;
58use Fisharebest\Webtrees\Elements\Confirmation;
59use Fisharebest\Webtrees\Elements\ContentDescription;
60use Fisharebest\Webtrees\Elements\CopyrightFile;
61use Fisharebest\Webtrees\Elements\CopyrightSourceData;
62use Fisharebest\Webtrees\Elements\CountOfChildren;
63use Fisharebest\Webtrees\Elements\CountOfMarriages;
64use Fisharebest\Webtrees\Elements\Cremation;
65use Fisharebest\Webtrees\Elements\CustomElement;
66use Fisharebest\Webtrees\Elements\CustomEvent;
67use Fisharebest\Webtrees\Elements\CustomFact;
68use Fisharebest\Webtrees\Elements\DateLdsOrd;
69use Fisharebest\Webtrees\Elements\DateValue;
70use Fisharebest\Webtrees\Elements\Death;
71use Fisharebest\Webtrees\Elements\DescriptiveTitle;
72use Fisharebest\Webtrees\Elements\Divorce;
73use Fisharebest\Webtrees\Elements\DivorceFiled;
74use Fisharebest\Webtrees\Elements\Emigration;
75use Fisharebest\Webtrees\Elements\EmptyElement;
76use Fisharebest\Webtrees\Elements\Engagement;
77use Fisharebest\Webtrees\Elements\EntryRecordingDate;
78use Fisharebest\Webtrees\Elements\EventAttributeType;
79use Fisharebest\Webtrees\Elements\EventDescriptor;
80use Fisharebest\Webtrees\Elements\EventOrFactClassification;
81use Fisharebest\Webtrees\Elements\EventsRecorded;
82use Fisharebest\Webtrees\Elements\EventTypeCitedFrom;
83use Fisharebest\Webtrees\Elements\FamilyRecord;
84use Fisharebest\Webtrees\Elements\FamilySearchFamilyTreeId;
85use Fisharebest\Webtrees\Elements\FamilyStatusText;
86use Fisharebest\Webtrees\Elements\FileName;
87use Fisharebest\Webtrees\Elements\FirstCommunion;
88use Fisharebest\Webtrees\Elements\Form;
89use Fisharebest\Webtrees\Elements\GedcomElement;
90use Fisharebest\Webtrees\Elements\GenerationsOfAncestors;
91use Fisharebest\Webtrees\Elements\GenerationsOfDescendants;
92use Fisharebest\Webtrees\Elements\GovIdentifier;
93use Fisharebest\Webtrees\Elements\Graduation;
94use Fisharebest\Webtrees\Elements\HeaderRecord;
95use Fisharebest\Webtrees\Elements\HierarchicalRelationship;
96use Fisharebest\Webtrees\Elements\Immigration;
97use Fisharebest\Webtrees\Elements\IndividualRecord;
98use Fisharebest\Webtrees\Elements\LanguageId;
99use Fisharebest\Webtrees\Elements\LdsBaptism;
100use Fisharebest\Webtrees\Elements\LdsBaptismDateStatus;
101use Fisharebest\Webtrees\Elements\LdsChildSealing;
102use Fisharebest\Webtrees\Elements\LdsChildSealingDateStatus;
103use Fisharebest\Webtrees\Elements\LdsConfirmation;
104use Fisharebest\Webtrees\Elements\LdsEndowment;
105use Fisharebest\Webtrees\Elements\LdsEndowmentDateStatus;
106use Fisharebest\Webtrees\Elements\LdsSpouseSealing;
107use Fisharebest\Webtrees\Elements\LdsSpouseSealingDateStatus;
108use Fisharebest\Webtrees\Elements\LocationRecord;
109use Fisharebest\Webtrees\Elements\MaidenheadLocator;
110use Fisharebest\Webtrees\Elements\Marriage;
111use Fisharebest\Webtrees\Elements\MarriageBanns;
112use Fisharebest\Webtrees\Elements\MarriageContract;
113use Fisharebest\Webtrees\Elements\MarriageLicence;
114use Fisharebest\Webtrees\Elements\MarriageSettlement;
115use Fisharebest\Webtrees\Elements\MarriageType;
116use Fisharebest\Webtrees\Elements\MediaRecord;
117use Fisharebest\Webtrees\Elements\MultimediaFileReference;
118use Fisharebest\Webtrees\Elements\MultimediaFormat;
119use Fisharebest\Webtrees\Elements\NameOfBusiness;
120use Fisharebest\Webtrees\Elements\NameOfFamilyFile;
121use Fisharebest\Webtrees\Elements\NameOfProduct;
122use Fisharebest\Webtrees\Elements\NameOfRepository;
123use Fisharebest\Webtrees\Elements\NameOfSourceData;
124use Fisharebest\Webtrees\Elements\NamePersonal;
125use Fisharebest\Webtrees\Elements\NamePhoneticVariation;
126use Fisharebest\Webtrees\Elements\NamePieceGiven;
127use Fisharebest\Webtrees\Elements\NamePieceNickname;
128use Fisharebest\Webtrees\Elements\NamePiecePrefix;
129use Fisharebest\Webtrees\Elements\NamePieceSuffix;
130use Fisharebest\Webtrees\Elements\NamePieceSurname;
131use Fisharebest\Webtrees\Elements\NamePieceSurnamePrefix;
132use Fisharebest\Webtrees\Elements\NameRomanizedVariation;
133use Fisharebest\Webtrees\Elements\NameType;
134use Fisharebest\Webtrees\Elements\NationalIdNumber;
135use Fisharebest\Webtrees\Elements\NationOrTribalOrigin;
136use Fisharebest\Webtrees\Elements\Naturalization;
137use Fisharebest\Webtrees\Elements\NobilityTypeTitle;
138use Fisharebest\Webtrees\Elements\NoteRecord;
139use Fisharebest\Webtrees\Elements\NoteStructure;
140use Fisharebest\Webtrees\Elements\Occupation;
141use Fisharebest\Webtrees\Elements\OrdinanceProcessFlag;
142use Fisharebest\Webtrees\Elements\Ordination;
143use Fisharebest\Webtrees\Elements\PafUid;
144use Fisharebest\Webtrees\Elements\PedigreeLinkageType;
145use Fisharebest\Webtrees\Elements\PermanentRecordFileNumber;
146use Fisharebest\Webtrees\Elements\PhoneNumber;
147use Fisharebest\Webtrees\Elements\PhoneticType;
148use Fisharebest\Webtrees\Elements\PhysicalDescription;
149use Fisharebest\Webtrees\Elements\PlaceHierarchy;
150use Fisharebest\Webtrees\Elements\PlaceLatitude;
151use Fisharebest\Webtrees\Elements\PlaceLivingOrdinance;
152use Fisharebest\Webtrees\Elements\PlaceLongtitude;
153use Fisharebest\Webtrees\Elements\PlaceName;
154use Fisharebest\Webtrees\Elements\PlacePhoneticVariation;
155use Fisharebest\Webtrees\Elements\PlaceRomanizedVariation;
156use Fisharebest\Webtrees\Elements\Possessions;
157use Fisharebest\Webtrees\Elements\Probate;
158use Fisharebest\Webtrees\Elements\PublicationDate;
159use Fisharebest\Webtrees\Elements\ReceivingSystemName;
160use Fisharebest\Webtrees\Elements\RelationIsDescriptor;
161use Fisharebest\Webtrees\Elements\ReligiousAffiliation;
162use Fisharebest\Webtrees\Elements\RepositoryRecord;
163use Fisharebest\Webtrees\Elements\ResearchTask;
164use Fisharebest\Webtrees\Elements\ResearchTaskPriority;
165use Fisharebest\Webtrees\Elements\ResearchTaskStatus;
166use Fisharebest\Webtrees\Elements\ResearchTaskType;
167use Fisharebest\Webtrees\Elements\Residence;
168use Fisharebest\Webtrees\Elements\ResponsibleAgency;
169use Fisharebest\Webtrees\Elements\RestrictionNotice;
170use Fisharebest\Webtrees\Elements\Retirement;
171use Fisharebest\Webtrees\Elements\RoleInEvent;
172use Fisharebest\Webtrees\Elements\RomanizedType;
173use Fisharebest\Webtrees\Elements\ScholasticAchievement;
174use Fisharebest\Webtrees\Elements\SexValue;
175use Fisharebest\Webtrees\Elements\SexXValue;
176use Fisharebest\Webtrees\Elements\SocialSecurityNumber;
177use Fisharebest\Webtrees\Elements\SourceCallNumber;
178use Fisharebest\Webtrees\Elements\SourceData;
179use Fisharebest\Webtrees\Elements\SourceFiledByEntry;
180use Fisharebest\Webtrees\Elements\SourceJurisdictionPlace;
181use Fisharebest\Webtrees\Elements\SourceMediaType;
182use Fisharebest\Webtrees\Elements\SourceOriginator;
183use Fisharebest\Webtrees\Elements\SourcePublicationFacts;
184use Fisharebest\Webtrees\Elements\SourceRecord;
185use Fisharebest\Webtrees\Elements\SubmissionRecord;
186use Fisharebest\Webtrees\Elements\SubmitterName;
187use Fisharebest\Webtrees\Elements\SubmitterRecord;
188use Fisharebest\Webtrees\Elements\SubmitterRegisteredRfn;
189use Fisharebest\Webtrees\Elements\SubmitterText;
190use Fisharebest\Webtrees\Elements\TempleCode;
191use Fisharebest\Webtrees\Elements\TextFromSource;
192use Fisharebest\Webtrees\Elements\TimeValue;
193use Fisharebest\Webtrees\Elements\TransmissionDate;
194use Fisharebest\Webtrees\Elements\UnknownElement;
195use Fisharebest\Webtrees\Elements\UserReferenceNumber;
196use Fisharebest\Webtrees\Elements\UserReferenceType;
197use Fisharebest\Webtrees\Elements\VersionNumber;
198use Fisharebest\Webtrees\Elements\WebtreesUser;
199use Fisharebest\Webtrees\Elements\WhereWithinSource;
200use Fisharebest\Webtrees\Elements\Will;
201use Fisharebest\Webtrees\Elements\XrefAssociate;
202use Fisharebest\Webtrees\Elements\XrefFamily;
203use Fisharebest\Webtrees\Elements\XrefIndividual;
204use Fisharebest\Webtrees\Elements\XrefLocation;
205use Fisharebest\Webtrees\Elements\XrefMedia;
206use Fisharebest\Webtrees\Elements\XrefRepository;
207use Fisharebest\Webtrees\Elements\XrefSource;
208use Fisharebest\Webtrees\Elements\XrefSubmission;
209use Fisharebest\Webtrees\Elements\XrefSubmitter;
210use Fisharebest\Webtrees\I18N;
211
212use function preg_match;
213use function strpos;
214
215/**
216 * Make a GEDCOM element.
217 */
218class ElementFactory implements ElementFactoryInterface
219{
220    /** @var array<string,ElementInterface> */
221    private array $elements = [];
222
223    /**
224     * Create a GEDCOM element that corresponds to a GEDCOM tag.
225     * Finds the correct element for all valid tags.
226     * Finds a likely element for custom tags.
227     *
228     * @param string $tag - Colon delimited hierarchy, e.g. 'INDI:BIRT:PLAC'
229     *
230     * @return ElementInterface
231     */
232    public function make(string $tag): ElementInterface
233    {
234        return $this->elements()[$tag] ?? $this->findElementByWildcard($tag) ?? new UnknownElement($tag);
235    }
236
237    /**
238     * Association between GEDCOM tags and GEDCOM elements.
239     * We can't initialise this in the constructor, as the I18N package isn't available then.
240     *
241     * @return array<string,ElementInterface>
242     */
243    private function elements(): array
244    {
245        if ($this->elements === []) {
246            // Gedcom 5.5.1
247            $this->elements = [
248                'FAM'                      => new FamilyRecord(I18N::translate('Family')),
249                'FAM:*:ADDR'               => new AddressLine(I18N::translate('Address')),
250                'FAM:*:ADDR:ADR1'          => new AddressLine1(I18N::translate('Address line 1')),
251                'FAM:*:ADDR:ADR2'          => new AddressLine2(I18N::translate('Address line 2')),
252                'FAM:*:ADDR:ADR3'          => new AddressLine3(I18N::translate('Address line 3')),
253                'FAM:*:ADDR:CITY'          => new AddressCity(I18N::translate('City')),
254                'FAM:*:ADDR:CTRY'          => new AddressCountry(I18N::translate('Country')),
255                'FAM:*:ADDR:POST'          => new AddressPostalCode(I18N::translate('Postal code')),
256                'FAM:*:ADDR:STAE'          => new AddressState(I18N::translate('State')),
257                'FAM:*:AGNC'               => new ResponsibleAgency(I18N::translate('Agency')),
258                'FAM:*:CAUS'               => new CauseOfEvent(I18N::translate('Cause')),
259                'FAM:*:DATE'               => new DateValue(I18N::translate('Date')),
260                'FAM:*:EMAIL'              => new AddressEmail(I18N::translate('Email address')),
261                'FAM:*:FAX'                => new AddressFax(I18N::translate('Fax')),
262                'FAM:*:HUSB'               => new EmptyElement(I18N::translate('Husband'), ['AGE' => '0:1']),
263                'FAM:*:HUSB:AGE'           => new AgeAtEvent(I18N::translate('Husband’s age')),
264                'FAM:*:NOTE'               => new NoteStructure(I18N::translate('Note')),
265                'FAM:*:OBJE'               => new XrefMedia(I18N::translate('Media object')),
266                'FAM:*:PHON'               => new PhoneNumber(I18N::translate('Phone')),
267                'FAM:*:PLAC'               => new PlaceName(I18N::translate('Place')),
268                'FAM:*:PLAC:FONE'          => new PlacePhoneticVariation(I18N::translate('Phonetic place')),
269                'FAM:*:PLAC:FONE:TYPE'     => new PhoneticType(I18N::translate('Type')),
270                'FAM:*:PLAC:FORM'          => new PlaceHierarchy(I18N::translate('Format')),
271                'FAM:*:PLAC:MAP'           => new EmptyElement(I18N::translate('Coordinates')),
272                'FAM:*:PLAC:MAP:LATI'      => new PlaceLatitude(I18N::translate('Latitude')),
273                'FAM:*:PLAC:MAP:LONG'      => new PlaceLongtitude(I18N::translate('Longitude')),
274                'FAM:*:PLAC:NOTE'          => new NoteStructure(I18N::translate('Note')),
275                'FAM:*:PLAC:ROMN'          => new PlaceRomanizedVariation(I18N::translate('Romanized place')),
276                'FAM:*:PLAC:ROMN:TYPE'     => new RomanizedType(I18N::translate('Type')),
277                'FAM:*:RELI'               => new ReligiousAffiliation(I18N::translate('Religion')),
278                'FAM:*:RESN'               => new RestrictionNotice(I18N::translate('Restriction')),
279                'FAM:*:SOUR'               => new XrefSource(I18N::translate('Source')),
280                'FAM:*:SOUR:DATA'          => new SourceData(I18N::translate('Data')),
281                'FAM:*:SOUR:DATA:DATE'     => new EntryRecordingDate(I18N::translate('Date of entry in original source')),
282                'FAM:*:SOUR:DATA:TEXT'     => new TextFromSource(I18N::translate('Text')),
283                'FAM:*:SOUR:EVEN'          => new EventTypeCitedFrom(I18N::translate('Event')),
284                'FAM:*:SOUR:EVEN:ROLE'     => new RoleInEvent(I18N::translate('Role')),
285                'FAM:*:SOUR:NOTE'          => new NoteStructure(I18N::translate('Note')),
286                'FAM:*:SOUR:OBJE'          => new XrefMedia(I18N::translate('Media object')),
287                'FAM:*:SOUR:PAGE'          => new WhereWithinSource(I18N::translate('Citation details')),
288                'FAM:*:SOUR:QUAY'          => new CertaintyAssessment(I18N::translate('Quality of data')),
289                'FAM:*:TYPE'               => new EventOrFactClassification(I18N::translate('Type')),
290                'FAM:*:WIFE'               => new EmptyElement(I18N::translate('Wife'), ['AGE' => '0:1']),
291                'FAM:*:WIFE:AGE'           => new AgeAtEvent(I18N::translate('Wife’s age')),
292                'FAM:*:WWW'                => new AddressWebPage(I18N::translate('URL')),
293                'FAM:ANUL'                 => new Annulment(I18N::translate('Annulment')),
294                'FAM:CENS'                 => new Census(I18N::translate('Census')),
295                'FAM:CHAN'                 => new Change(I18N::translate('Last change')),
296                'FAM:CHAN:DATE'            => new ChangeDate(I18N::translate('Date of last change')),
297                'FAM:CHAN:DATE:TIME'       => new TimeValue(I18N::translate('Time')),
298                'FAM:CHIL'                 => new XrefIndividual(I18N::translate('Child')),
299                'FAM:DIV'                  => new Divorce(I18N::translate('Divorce')),
300                'FAM:DIVF'                 => new DivorceFiled(I18N::translate('Divorce filed')),
301                'FAM:ENGA'                 => new Engagement(I18N::translate('Engagement')),
302                'FAM:ENGA:DATE'            => new DateValue(I18N::translate('Date of engagement')),
303                'FAM:ENGA:PLACE'           => new PlaceName(I18N::translate('Place of engagement')),
304                'FAM:EVEN'                 => new EventDescriptor(I18N::translate('Event')),
305                'FAM:EVEN:TYPE'            => new EventAttributeType(I18N::translate('Type of event')),
306                'FAM:HUSB'                 => new XrefIndividual(I18N::translate('Husband')),
307                'FAM:MARB'                 => new MarriageBanns(I18N::translate('Marriage banns')),
308                'FAM:MARB:DATE'            => new DateValue(I18N::translate('Date of marriage banns')),
309                'FAM:MARB:PLAC'            => new PlaceName(I18N::translate('Place of marriage banns')),
310                'FAM:MARC'                 => new MarriageContract(I18N::translate('Marriage contract')),
311                'FAM:MARL'                 => new MarriageLicence(I18N::translate('Marriage license')),
312                'FAM:MARR'                 => new Marriage(I18N::translate('Marriage')),
313                'FAM:MARR:DATE'            => new DateValue(I18N::translate('Date of marriage')),
314                'FAM:MARR:PLAC'            => new PlaceName(I18N::translate('Place of marriage')),
315                'FAM:MARR:TYPE'            => new MarriageType(I18N::translate('Type of marriage')),
316                'FAM:MARS'                 => new MarriageSettlement(I18N::translate('Marriage settlement')),
317                'FAM:NCHI'                 => new CountOfChildren(I18N::translate('Number of children')),
318                'FAM:NOTE'                 => new NoteStructure(I18N::translate('Note')),
319                'FAM:OBJE'                 => new XrefMedia(I18N::translate('Media object')),
320                'FAM:REFN'                 => new UserReferenceNumber(I18N::translate('Reference number')),
321                'FAM:REFN:TYPE'            => new UserReferenceType(I18N::translate('Type')),
322                'FAM:RESI'                 => new Residence(I18N::translate('Residence')),
323                'FAM:RESN'                 => new RestrictionNotice(I18N::translate('Restriction')),
324                'FAM:RIN'                  => new AutomatedRecordId(I18N::translate('Record ID number')),
325                'FAM:SLGS'                 => new LdsSpouseSealing(I18N::translate('LDS spouse sealing')),
326                'FAM:SLGS:DATE'            => new DateLdsOrd(I18N::translate('Date')),
327                'FAM:SLGS:PLAC'            => new PlaceLivingOrdinance(I18N::translate('Place')),
328                'FAM:SLGS:STAT'            => new LdsSpouseSealingDateStatus(I18N::translate('Status')),
329                'FAM:SLGS:STAT:DATE'       => new ChangeDate(I18N::translate('Status change date')),
330                'FAM:SLGS:TEMP'            => new TempleCode(I18N::translate('Temple')),
331                'FAM:SOUR'                 => new XrefSource(I18N::translate('Source')),
332                'FAM:SOUR:DATA'            => new SourceData(I18N::translate('Data')),
333                'FAM:SOUR:DATA:DATE'       => new EntryRecordingDate(I18N::translate('Date of entry in original source')),
334                'FAM:SOUR:DATA:TEXT'       => new TextFromSource(I18N::translate('Text')),
335                'FAM:SOUR:EVEN'            => new EventTypeCitedFrom(I18N::translate('Event')),
336                'FAM:SOUR:EVEN:ROLE'       => new RoleInEvent(I18N::translate('Role')),
337                'FAM:SOUR:OBJE'            => new XrefMedia(I18N::translate('Media object')),
338                'FAM:SOUR:PAGE'            => new WhereWithinSource(I18N::translate('Citation details')),
339                'FAM:SOUR:QUAY'            => new CertaintyAssessment(I18N::translate('Quality of data')),
340                'FAM:SUBM'                 => new XrefSubmitter(I18N::translate('Submitter')),
341                'FAM:WIFE'                 => new XrefIndividual(I18N::translate('Wife')),
342                'HEAD'                     => new HeaderRecord(I18N::translate('Header')),
343                'HEAD:CHAR'                => new CharacterSet(I18N::translate('Character set')),
344                'HEAD:CHAR:VERS'           => new VersionNumber(I18N::translate('Version')),
345                'HEAD:COPR'                => new CopyrightFile(I18N::translate('Copyright')),
346                'HEAD:DATE'                => new TransmissionDate(I18N::translate('Date')),
347                'HEAD:DATE:TIME'           => new TimeValue(I18N::translate('Time')),
348                'HEAD:DEST'                => new ReceivingSystemName(I18N::translate('Destination')),
349                'HEAD:FILE'                => new FileName(I18N::translate('Filename')),
350                'HEAD:GEDC'                => new GedcomElement(I18N::translate('GEDCOM')),
351                'HEAD:GEDC:FORM'           => new Form(I18N::translate('Format')),
352                'HEAD:GEDC:VERS'           => new VersionNumber(I18N::translate('Version')),
353                'HEAD:LANG'                => new LanguageId(I18N::translate('Language')),
354                'HEAD:NOTE'                => new ContentDescription(I18N::translate('Note')),
355                'HEAD:PLAC'                => new EmptyElement(I18N::translate('Place hierarchy'), ['FORM' => '1:1']),
356                'HEAD:PLAC:FORM'           => new PlaceHierarchy(I18N::translate('Format')),
357                'HEAD:SOUR'                => new ApprovedSystemId('Genealogy software'),
358                'HEAD:SOUR:CORP'           => new NameOfBusiness(I18N::translate('Corporation')),
359                'HEAD:SOUR:CORP:ADDR'      => new AddressLine(I18N::translate('Address')),
360                'HEAD:SOUR:CORP:ADDR:ADR1' => new AddressLine1(I18N::translate('Address line 1')),
361                'HEAD:SOUR:CORP:ADDR:ADR2' => new AddressLine2(I18N::translate('Address line 2')),
362                'HEAD:SOUR:CORP:ADDR:ADR3' => new AddressLine3(I18N::translate('Address line 3')),
363                'HEAD:SOUR:CORP:ADDR:CITY' => new AddressCity(I18N::translate('City')),
364                'HEAD:SOUR:CORP:ADDR:CTRY' => new AddressCountry(I18N::translate('Country')),
365                'HEAD:SOUR:CORP:ADDR:POST' => new AddressPostalCode(I18N::translate('Postal code')),
366                'HEAD:SOUR:CORP:ADDR:STAE' => new AddressState(I18N::translate('State')),
367                'HEAD:SOUR:CORP:EMAIL'     => new AddressEmail(I18N::translate('Email address')),
368                'HEAD:SOUR:CORP:FAX'       => new AddressFax(I18N::translate('Fax')),
369                'HEAD:SOUR:CORP:PHON'      => new PhoneNumber(I18N::translate('Phone')),
370                'HEAD:SOUR:CORP:WWW'       => new AddressWebPage(I18N::translate('URL')),
371                'HEAD:SOUR:DATA'           => new NameOfSourceData('Data'),
372                'HEAD:SOUR:DATA:COPR'      => new CopyrightSourceData(I18N::translate('Copyright')),
373                'HEAD:SOUR:DATA:DATE'      => new PublicationDate(I18N::translate('Date')),
374                'HEAD:SOUR:NAME'           => new NameOfProduct('Software product'),
375                'HEAD:SOUR:VERS'           => new VersionNumber(I18N::translate('Version')),
376                'HEAD:SUBM'                => new XrefSubmitter(I18N::translate('Submitter')),
377                'HEAD:SUBN'                => new XrefSubmission(I18N::translate('Submission')),
378                'INDI'                     => new IndividualRecord(I18N::translate('Individual')),
379                'INDI:*:ADDR'              => new AddressLine(I18N::translate('Address')),
380                'INDI:*:ADDR:ADR1'         => new AddressLine1(I18N::translate('Address line 1')),
381                'INDI:*:ADDR:ADR2'         => new AddressLine2(I18N::translate('Address line 2')),
382                'INDI:*:ADDR:ADR3'         => new AddressLine3(I18N::translate('Address line 3')),
383                'INDI:*:ADDR:CITY'         => new AddressCity(I18N::translate('City')),
384                'INDI:*:ADDR:CTRY'         => new AddressCountry(I18N::translate('Country')),
385                'INDI:*:ADDR:POST'         => new AddressPostalCode(I18N::translate('Postal code')),
386                'INDI:*:ADDR:STAE'         => new AddressState(I18N::translate('State')),
387                'INDI:*:AGE'               => new AgeAtEvent(I18N::translate('Age')),
388                'INDI:*:AGNC'              => new ResponsibleAgency(I18N::translate('Agency')),
389                'INDI:*:CAUS'              => new CauseOfEvent(I18N::translate('Cause')),
390                'INDI:*:DATE'              => new DateValue(I18N::translate('Date')),
391                'INDI:*:EMAIL'             => new AddressEmail(I18N::translate('Email address')),
392                'INDI:*:FAX'               => new AddressFax(I18N::translate('Fax')),
393                'INDI:*:NOTE'              => new NoteStructure(I18N::translate('Note')),
394                'INDI:*:OBJE'              => new XrefMedia(I18N::translate('Media object')),
395                'INDI:*:PHON'              => new PhoneNumber(I18N::translate('Phone')),
396                'INDI:*:PLAC'              => new PlaceName(I18N::translate('Place')),
397                'INDI:*:PLAC:FONE'         => new PlacePhoneticVariation(I18N::translate('Phonetic place')),
398                'INDI:*:PLAC:FONE:TYPE'    => new PhoneticType(I18N::translate('Type')),
399                'INDI:*:PLAC:FORM'         => new PlaceHierarchy(I18N::translate('Format')),
400                'INDI:*:PLAC:MAP'          => new EmptyElement(I18N::translate('Coordinates')),
401                'INDI:*:PLAC:MAP:LATI'     => new PlaceLatitude(I18N::translate('Latitude')),
402                'INDI:*:PLAC:MAP:LONG'     => new PlaceLongtitude(I18N::translate('Longitude')),
403                'INDI:*:PLAC:NOTE'         => new NoteStructure(I18N::translate('Note')),
404                'INDI:*:PLAC:ROMN'         => new PlaceRomanizedVariation(I18N::translate('Romanized place')),
405                'INDI:*:PLAC:ROMN:TYPE'    => new RomanizedType(I18N::translate('Type')),
406                'INDI:*:RELI'              => new ReligiousAffiliation(I18N::translate('Religion')),
407                'INDI:*:RESN'              => new RestrictionNotice(I18N::translate('Restriction')),
408                'INDI:*:SOUR'              => new XrefSource(I18N::translate('Source')),
409                'INDI:*:SOUR:DATA'         => new SourceData(I18N::translate('Data')),
410                'INDI:*:SOUR:DATA:DATE'    => new EntryRecordingDate(I18N::translate('Date of entry in original source')),
411                'INDI:*:SOUR:DATA:TEXT'    => new TextFromSource(I18N::translate('Text')),
412                'INDI:*:SOUR:EVEN'         => new EventTypeCitedFrom(I18N::translate('Event')),
413                'INDI:*:SOUR:EVEN:ROLE'    => new RoleInEvent(I18N::translate('Role')),
414                'INDI:*:SOUR:NOTE'         => new NoteStructure(I18N::translate('Note')),
415                'INDI:*:SOUR:OBJE'         => new XrefMedia(I18N::translate('Media object')),
416                'INDI:*:SOUR:PAGE'         => new WhereWithinSource(I18N::translate('Citation details')),
417                'INDI:*:SOUR:QUAY'         => new CertaintyAssessment(I18N::translate('Quality of data')),
418                'INDI:*:TYPE'              => new EventOrFactClassification(I18N::translate('Type')),
419                'INDI:*:WWW'               => new AddressWebPage(I18N::translate('URL')),
420                'INDI:ADOP'                => new Adoption(I18N::translate('Adoption')),
421                'INDI:ADOP:DATE'           => new DateValue(I18N::translate('Date of adoption')),
422                'INDI:ADOP:FAMC'           => new XrefFamily(I18N::translate('Adoptive parents')),
423                'INDI:ADOP:FAMC:ADOP'      => new AdoptedByWhichParent(I18N::translate('Adoption')),
424                'INDI:ADOP:PLAC'           => new PlaceName(I18N::translate('Place of adoption')),
425                'INDI:AFN'                 => new AncestralFileNumber(I18N::translate('Ancestral file number')),
426                'INDI:ALIA'                => new XrefIndividual(I18N::translate('Alias')),
427                'INDI:ANCI'                => new XrefSubmitter(I18N::translate('Ancestors interest')),
428                'INDI:ASSO'                => new XrefAssociate(I18N::translate('Associate')),
429                'INDI:ASSO:RELA'           => new RelationIsDescriptor(I18N::translate('Relationship')),
430                'INDI:BAPL'                => new LdsBaptism(I18N::translate('LDS baptism')),
431                'INDI:BAPL:DATE'           => new DateLdsOrd(I18N::translate('Date of LDS baptism')),
432                'INDI:BAPL:PLAC'           => new PlaceLivingOrdinance(I18N::translate('Place of LDS baptism')),
433                'INDI:BAPL:STAT'           => new LdsBaptismDateStatus(I18N::translate('Status')),
434                'INDI:BAPL:STAT:DATE'      => new ChangeDate(I18N::translate('Status change date')),
435                'INDI:BAPL:TEMP'           => new TempleCode(I18N::translate('Temple')),
436                'INDI:BAPM'                => new Baptism(I18N::translate('Baptism')),
437                'INDI:BAPM:DATE'           => new DateValue(I18N::translate('Date of baptism')),
438                'INDI:BAPM:PLAC'           => new PlaceName(I18N::translate('Place of baptism')),
439                'INDI:BARM'                => new PlaceName(I18N::translate('Bar mitzvah')),
440                'INDI:BARM:DATE'           => new DateValue(I18N::translate('Date of bar mitzvah')),
441                'INDI:BARM:PLAC'           => new PlaceName(I18N::translate('Place of bar mitzvah')),
442                'INDI:BASM'                => new BasMitzvah(I18N::translate('Bat mitzvah')),
443                'INDI:BASM:DATE'           => new BasMitzvah(I18N::translate('Date of bat mitzvah')),
444                'INDI:BASM:PLAC'           => new DateValue(I18N::translate('Place of bat mitzvah')),
445                'INDI:BIRT'                => new Birth(I18N::translate('Birth')),
446                'INDI:BIRT:DATE'           => new DateValue(I18N::translate('Date of birth')),
447                'INDI:BIRT:FAMC'           => new XrefFamily(I18N::translate('Birth parents')),
448                'INDI:BIRT:PLAC'           => new PlaceName(I18N::translate('Place of birth')),
449                'INDI:BLES'                => new Blessing(I18N::translate('Blessing')),
450                'INDI:BLES:DATE'           => new DateValue(I18N::translate('Date of blessing')),
451                'INDI:BLES:PLAC'           => new PlaceName(I18N::translate('Place of blessing')),
452                'INDI:BURI'                => new Burial(I18N::translate('Burial')),
453                'INDI:BURI:DATE'           => new DateValue(I18N::translate('Date of burial')),
454                'INDI:BURI:PLAC'           => new PlaceName(I18N::translate('Place of burial')),
455                'INDI:CAST'                => new CasteName(I18N::translate('Caste')),
456                'INDI:CENS'                => new Census(I18N::translate('Census')),
457                'INDI:CENS:DATE'           => new DateValue(I18N::translate('Census date')),
458                'INDI:CENS:PLAC'           => new PlaceName(I18N::translate('Census place')),
459                'INDI:CHAN'                => new Change(I18N::translate('Last change')),
460                'INDI:CHAN:DATE'           => new ChangeDate(I18N::translate('Date of last change')),
461                'INDI:CHAN:DATE:TIME'      => new TimeValue(I18N::translate('Time')),
462                'INDI:CHR'                 => new Christening(I18N::translate('Christening')),
463                'INDI:CHR:DATE'            => new DateValue(I18N::translate('Date of christening')),
464                'INDI:CHR:FAMC'            => new XrefFamily(I18N::translate('Godparents')),
465                'INDI:CHR:PLAC'            => new PlaceName(I18N::translate('Place of christening')),
466                'INDI:CHRA'                => new AdultChristening(I18N::translate('Adult christening')),
467                'INDI:CONF'                => new Confirmation(I18N::translate('Confirmation')),
468                'INDI:CONF:DATE'           => new DateValue(I18N::translate('Date of confirmation')),
469                'INDI:CONF:PLAC'           => new PlaceName(I18N::translate('Place of confirmation')),
470                'INDI:CONL'                => new LdsConfirmation(I18N::translate('LDS confirmation')),
471                'INDI:CONL:DATE'           => new DateLdsOrd(I18N::translate('Date of LDS confirmation')),
472                'INDI:CONL:PLAC'           => new PlaceLivingOrdinance(I18N::translate('Place of LDS confirmation')),
473                'INDI:CONL:STAT'           => new LdsSpouseSealingDateStatus(I18N::translate('Status')),
474                'INDI:CONL:STAT:DATE'      => new ChangeDate(I18N::translate('Status change date')),
475                'INDI:CONL:TEMP'           => new TempleCode(I18N::translate('Temple')),
476                'INDI:CREM'                => new Cremation(I18N::translate('Cremation')),
477                'INDI:CREM:DATE'           => new Cremation(I18N::translate('Date of cremation')),
478                'INDI:CREM:PLAC'           => new Cremation(I18N::translate('Place of cremation')),
479                'INDI:DEAT'                => new Death(I18N::translate('Death')),
480                'INDI:DEAT:CAUS'           => new CauseOfEvent(I18N::translate('Cause of death')),
481                'INDI:DEAT:DATE'           => new DateValue(I18N::translate('Date of death')),
482                'INDI:DEAT:PLAC'           => new PlaceName(I18N::translate('Place of death')),
483                'INDI:DESI'                => new XrefSubmitter(I18N::translate('Descendants interest')),
484                'INDI:DSCR'                => new PhysicalDescription(I18N::translate('Description')),
485                'INDI:EDUC'                => new ScholasticAchievement(I18N::translate('Education')),
486                'INDI:EDUC:AGNC'           => new ResponsibleAgency(I18N::translate('School or college')),
487                'INDI:EMIG'                => new Emigration(I18N::translate('Emigration')),
488                'INDI:EMIG:DATE'           => new DateValue(I18N::translate('Date of emigration')),
489                'INDI:EMIG:PLAC'           => new PlaceName(I18N::translate('Place of emigration')),
490                'INDI:ENDL'                => new LdsEndowment(I18N::translate('LDS endowment')),
491                'INDI:ENDL:DATE'           => new DateLdsOrd(I18N::translate('Date of LDS endowment')),
492                'INDI:ENDL:PLAC'           => new PlaceLivingOrdinance(I18N::translate('Place of LDS endowment')),
493                'INDI:ENDL:STAT'           => new LdsEndowmentDateStatus(I18N::translate('Status')),
494                'INDI:ENDL:STAT:DATE'      => new ChangeDate(I18N::translate('Status change date')),
495                'INDI:ENDL:TEMP'           => new TempleCode(I18N::translate('Temple')),
496                'INDI:EVEN'                => new EventDescriptor(I18N::translate('Event')),
497                'INDI:EVEN:DATE'           => new DateValue(I18N::translate('Date of event')),
498                'INDI:EVEN:PLAC'           => new PlaceName(I18N::translate('Place of event')),
499                'INDI:EVEN:TYPE'           => new EventAttributeType(I18N::translate('Type of event')),
500                'INDI:FACT'                => new AttributeDescriptor(I18N::translate('Fact')),
501                'INDI:FACT:TYPE'           => new EventAttributeType(I18N::translate('Type of fact')),
502                'INDI:FAMC'                => new XrefFamily(I18N::translate('Family as a child'), ['NOTE' => '0:1', 'PEDI' => '0:1', 'STAT' => '0:1']),
503                'INDI:FAMC:PEDI'           => new PedigreeLinkageType(I18N::translate('Relationship to parents')),
504                'INDI:FAMC:STAT'           => new ChildLinkageStatus(I18N::translate('Status')),
505                'INDI:FAMS'                => new XrefFamily(I18N::translate('Family as a spouse')),
506                'INDI:FCOM'                => new FirstCommunion(I18N::translate('First communion')),
507                'INDI:FCOM:DATE'           => new DateValue(I18N::translate('Date of first communion')),
508                'INDI:FCOM:PLAC'           => new PlaceName(I18N::translate('Place of first communion')),
509                'INDI:GRAD'                => new Graduation(I18N::translate('Graduation')),
510                'INDI:GRAD:AGNC'           => new ResponsibleAgency(I18N::translate('School or college')),
511                'INDI:IDNO'                => new NationalIdNumber(I18N::translate('Identification number')),
512                'INDI:IMMI'                => new Immigration(I18N::translate('Immigration')),
513                'INDI:IMMI:DATE'           => new DateValue(I18N::translate('Date of immigration')),
514                'INDI:IMMI:PLAC'           => new PlaceName(I18N::translate('Place of immigration')),
515                'INDI:NAME'                => new NamePersonal(I18N::translate('Name')),
516                'INDI:NAME:FONE'           => new NamePhoneticVariation(I18N::translate('Phonetic name'), ['TYPE' => '0,1']),
517                'INDI:NAME:FONE:GIVN'      => new NamePieceGiven(I18N::translate('Given names')),
518                'INDI:NAME:FONE:NICK'      => new NamePieceNickname(I18N::translate('Nickname')),
519                'INDI:NAME:FONE:NPFX'      => new NamePiecePrefix(I18N::translate('Name prefix')),
520                'INDI:NAME:FONE:NSFX'      => new NamePieceSuffix(I18N::translate('Name suffix')),
521                'INDI:NAME:FONE:SPFX'      => new NamePieceSurnamePrefix(I18N::translate('Surname prefix')),
522                'INDI:NAME:FONE:SURN'      => new NamePieceSurname(I18N::translate('Surname')),
523                'INDI:NAME:FONE:TYPE'      => new PhoneticType(I18N::translate('Phonetic type')),
524                'INDI:NAME:GIVN'           => new NamePieceGiven(I18N::translate('Given names')),
525                'INDI:NAME:NICK'           => new NamePieceNickname(I18N::translate('Nickname')),
526                'INDI:NAME:NPFX'           => new NamePiecePrefix(I18N::translate('Name prefix')),
527                'INDI:NAME:NSFX'           => new NamePieceSuffix(I18N::translate('Name suffix')),
528                'INDI:NAME:ROMN'           => new NameRomanizedVariation(I18N::translate('Romanized name'), ['TYPE' => '0,1']),
529                'INDI:NAME:ROMN:GIVN'      => new NamePieceGiven(I18N::translate('Given names')),
530                'INDI:NAME:ROMN:NICK'      => new NamePieceNickname(I18N::translate('Nickname')),
531                'INDI:NAME:ROMN:NPFX'      => new NamePiecePrefix(I18N::translate('Name prefix')),
532                'INDI:NAME:ROMN:NSFX'      => new NamePieceSuffix(I18N::translate('Name suffix')),
533                'INDI:NAME:ROMN:SPFX'      => new NamePieceSurnamePrefix(I18N::translate('Surname prefix')),
534                'INDI:NAME:ROMN:SURN'      => new NamePieceSurname(I18N::translate('Surname')),
535                'INDI:NAME:ROMN:TYPE'      => new RomanizedType(I18N::translate('Romanized type')),
536                'INDI:NAME:SPFX'           => new NamePieceSurnamePrefix(I18N::translate('Surname prefix')),
537                'INDI:NAME:SURN'           => new NamePieceSurname(I18N::translate('Surname')),
538                'INDI:NAME:TYPE'           => new NameType(I18N::translate('Type of name')),
539                'INDI:NATI'                => new NationOrTribalOrigin(I18N::translate('Nationality')),
540                'INDI:NATU'                => new Naturalization(I18N::translate('Naturalization')),
541                'INDI:NATU:DATE'           => new DateValue(I18N::translate('Date of naturalization')),
542                'INDI:NATU:PLAC'           => new PlaceName(I18N::translate('Place of naturalization')),
543                'INDI:NCHI'                => new CountOfChildren(I18N::translate('Number of children')),
544                'INDI:NMR'                 => new CountOfMarriages(I18N::translate('Number of marriages')),
545                'INDI:NOTE'                => new NoteStructure(I18N::translate('Note')),
546                'INDI:OBJE'                => new XrefMedia(I18N::translate('Media object')),
547                'INDI:OCCU'                => new Occupation(I18N::translate('Occupation')),
548                'INDI:OCCU:AGNC'           => new ResponsibleAgency(I18N::translate('Employer')),
549                'INDI:ORDN'                => new Ordination(I18N::translate('Ordination')),
550                'INDI:ORDN:AGNC'           => new Ordination(I18N::translate('Religious institution')),
551                'INDI:ORDN:DATE'           => new Ordination(I18N::translate('Date of ordination')),
552                'INDI:ORDN:PLAC'           => new Ordination(I18N::translate('Place of ordination')),
553                'INDI:PROB'                => new Probate(I18N::translate('Probate')),
554                'INDI:PROP'                => new Possessions(I18N::translate('Property')),
555                'INDI:REFN'                => new UserReferenceNumber(I18N::translate('Reference number')),
556                'INDI:REFN:TYPE'           => new UserReferenceType(I18N::translate('Type')),
557                'INDI:RELI'                => new ReligiousAffiliation(I18N::translate('Religion')),
558                'INDI:RESI'                => new Residence(I18N::translate('Residence')),
559                'INDI:RESI:DATE'           => new DateValue(I18N::translate('Date of residence')),
560                'INDI:RESI:PLAC'           => new PlaceName(I18N::translate('Place of residence')),
561                'INDI:RESN'                => new RestrictionNotice(I18N::translate('Restriction')),
562                'INDI:RETI'                => new Retirement(I18N::translate('Retirement')),
563                'INDI:RETI:AGNC'           => new ResponsibleAgency(I18N::translate('Employer')),
564                'INDI:RFN'                 => new PermanentRecordFileNumber(I18N::translate('Record file number')),
565                'INDI:RIN'                 => new AutomatedRecordId(I18N::translate('Record ID number')),
566                'INDI:SEX'                 => new SexValue(I18N::translate('Gender')),
567                'INDI:SLGC'                => new LdsChildSealing(I18N::translate('LDS child sealing')),
568                'INDI:SLGC:DATE'           => new DateLdsOrd(I18N::translate('Date of LDS child sealing')),
569                'INDI:SLGC:FAMC'           => new XrefFamily(I18N::translate('Parents')),
570                'INDI:SLGC:PLAC'           => new PlaceLivingOrdinance(I18N::translate('Place of LDS child sealing')),
571                'INDI:SLGC:STAT'           => new LdsChildSealingDateStatus(I18N::translate('Status')),
572                'INDI:SLGC:STAT:DATE'      => new ChangeDate(I18N::translate('Status change date')),
573                'INDI:SLGC:TEMP'           => new TempleCode(I18N::translate('Temple')),
574                'INDI:SOUR'                => new XrefSource(I18N::translate('Source')),
575                'INDI:SOUR:DATA'           => new SourceData(I18N::translate('Data')),
576                'INDI:SOUR:DATA:DATE'      => new EntryRecordingDate(I18N::translate('Date of entry in original source')),
577                'INDI:SOUR:DATA:TEXT'      => new TextFromSource(I18N::translate('Text')),
578                'INDI:SOUR:EVEN'           => new EventTypeCitedFrom(I18N::translate('Event')),
579                'INDI:SOUR:EVEN:ROLE'      => new RoleInEvent(I18N::translate('Role')),
580                'INDI:SOUR:OBJE'           => new XrefMedia(I18N::translate('Media object')),
581                'INDI:SOUR:PAGE'           => new WhereWithinSource(I18N::translate('Citation details')),
582                'INDI:SOUR:QUAY'           => new CertaintyAssessment(I18N::translate('Quality of data')),
583                'INDI:SSN'                 => new SocialSecurityNumber(I18N::translate('Social security number')),
584                'INDI:SUBM'                => new XrefSubmitter(I18N::translate('Submitter')),
585                'INDI:TITL'                => new NobilityTypeTitle(I18N::translate('Title')),
586                'INDI:WILL'                => new Will(I18N::translate('Will')),
587                'NOTE'                     => new NoteRecord(I18N::translate('Note')),
588                'NOTE:CHAN'                => new Change(I18N::translate('Last change')),
589                'NOTE:CHAN:DATE'           => new ChangeDate(I18N::translate('Date of last change')),
590                'NOTE:CHAN:DATE:TIME'      => new TimeValue(I18N::translate('Time')),
591                'NOTE:CHAN:NOTE'           => new NoteStructure(I18N::translate('Note')),
592                'NOTE:CONC'                => new SubmitterText(I18N::translate('Note')),
593                'NOTE:CONT'                => new SubmitterText(I18N::translate('Continued')),
594                'NOTE:REFN'                => new UserReferenceNumber(I18N::translate('Reference number')),
595                'NOTE:REFN:TYPE'           => new UserReferenceType(I18N::translate('Type')),
596                'NOTE:RIN'                 => new AutomatedRecordId(I18N::translate('Record ID number')),
597                'NOTE:SOUR'                => new XrefSource(I18N::translate('Source')),
598                'NOTE:SOUR:DATA'           => new SourceData(I18N::translate('Data')),
599                'NOTE:SOUR:DATA:DATE'      => new EntryRecordingDate(I18N::translate('Date of entry in original source')),
600                'NOTE:SOUR:DATA:TEXT'      => new TextFromSource(I18N::translate('Text')),
601                'NOTE:SOUR:EVEN'           => new EventTypeCitedFrom(I18N::translate('Event')),
602                'NOTE:SOUR:EVEN:ROLE'      => new RoleInEvent(I18N::translate('Role')),
603                'NOTE:SOUR:NOTE'           => new NoteStructure(I18N::translate('Note')),
604                'NOTE:SOUR:OBJE'           => new XrefMedia(I18N::translate('Media object')),
605                'NOTE:SOUR:PAGE'           => new WhereWithinSource(I18N::translate('Citation details')),
606                'NOTE:SOUR:QUAY'           => new CertaintyAssessment(I18N::translate('Quality of data')),
607                'OBJE'                     => new MediaRecord(I18N::translate('Media object')),
608                'OBJE:CHAN'                => new Change(I18N::translate('Last change')),
609                'OBJE:CHAN:DATE'           => new ChangeDate(I18N::translate('Date of last change')),
610                'OBJE:CHAN:DATE:TIME'      => new TimeValue(I18N::translate('Time')),
611                'OBJE:CHAN:NOTE'           => new NoteStructure(I18N::translate('Note')),
612                'OBJE:FILE'                => new MultimediaFileReference(I18N::translate('Filename')),
613                'OBJE:FILE:FORM'           => new MultimediaFormat(I18N::translate('Format')),
614                'OBJE:FILE:FORM:TYPE'      => new SourceMediaType(I18N::translate('Media type')),
615                'OBJE:FILE:TITL'           => new DescriptiveTitle(I18N::translate('Title')),
616                'OBJE:NOTE'                => new NoteStructure(I18N::translate('Note')),
617                'OBJE:REFN'                => new UserReferenceNumber(I18N::translate('Reference number')),
618                'OBJE:REFN:TYPE'           => new UserReferenceType(I18N::translate('Type')),
619                'OBJE:RIN'                 => new AutomatedRecordId(I18N::translate('Record ID number')),
620                'OBJE:SOUR'                => new XrefSource(I18N::translate('Source')),
621                'OBJE:SOUR:DATA'           => new SourceData(I18N::translate('Data')),
622                'OBJE:SOUR:DATA:DATE'      => new EntryRecordingDate(I18N::translate('Date of entry in original source')),
623                'OBJE:SOUR:DATA:TEXT'      => new TextFromSource(I18N::translate('Text')),
624                'OBJE:SOUR:EVEN'           => new EventTypeCitedFrom(I18N::translate('Event')),
625                'OBJE:SOUR:EVEN:ROLE'      => new RoleInEvent(I18N::translate('Role')),
626                'OBJE:SOUR:NOTE'           => new NoteStructure(I18N::translate('Note')),
627                'OBJE:SOUR:OBJE'           => new XrefMedia(I18N::translate('Media object')),
628                'OBJE:SOUR:PAGE'           => new WhereWithinSource(I18N::translate('Citation details')),
629                'OBJE:SOUR:QUAY'           => new CertaintyAssessment(I18N::translate('Quality of data')),
630                'REPO'                     => new RepositoryRecord(I18N::translate('Repository')),
631                'REPO:ADDR'                => new AddressLine(I18N::translate('Address')),
632                'REPO:ADDR:ADR1'           => new AddressLine1(I18N::translate('Address line 1')),
633                'REPO:ADDR:ADR2'           => new AddressLine2(I18N::translate('Address line 2')),
634                'REPO:ADDR:ADR3'           => new AddressLine3(I18N::translate('Address line 3')),
635                'REPO:ADDR:CITY'           => new AddressCity(I18N::translate('City')),
636                'REPO:ADDR:CTRY'           => new AddressCountry(I18N::translate('Country')),
637                'REPO:ADDR:POST'           => new AddressPostalCode(I18N::translate('Postal code')),
638                'REPO:ADDR:STAE'           => new AddressState(I18N::translate('State')),
639                'REPO:CHAN'                => new Change(I18N::translate('Last change')),
640                'REPO:CHAN:DATE'           => new ChangeDate(I18N::translate('Date of last change')),
641                'REPO:CHAN:DATE:TIME'      => new TimeValue(I18N::translate('Time')),
642                'REPO:CHAN:NOTE'           => new NoteStructure(I18N::translate('Note')),
643                'REPO:EMAIL'               => new AddressEmail(I18N::translate('Email address')),
644                'REPO:FAX'                 => new AddressFax(I18N::translate('Fax')),
645                'REPO:NAME'                => new NameOfRepository(I18N::translateContext('Repository', 'Name')),
646                'REPO:NOTE'                => new NoteStructure(I18N::translate('Note')),
647                'REPO:PHON'                => new PhoneNumber(I18N::translate('Phone')),
648                'REPO:REFN'                => new UserReferenceNumber(I18N::translate('Reference number')),
649                'REPO:REFN:TYPE'           => new UserReferenceType(I18N::translate('Type')),
650                'REPO:RIN'                 => new AutomatedRecordId(I18N::translate('Record ID number')),
651                'REPO:WWW'                 => new AddressWebPage(I18N::translate('URL')),
652                'SOUR'                     => new SourceRecord(I18N::translate('Source')),
653                'SOUR:ABBR'                => new SourceFiledByEntry(I18N::translate('Abbreviation')),
654                'SOUR:AUTH'                => new SourceOriginator(I18N::translate('Author')),
655                'SOUR:CHAN'                => new Change(I18N::translate('Last change')),
656                'SOUR:CHAN:DATE'           => new ChangeDate(I18N::translate('Date of last change')),
657                'SOUR:CHAN:DATE:TIME'      => new TimeValue(I18N::translate('Time')),
658                'SOUR:CHAN:NOTE'           => new NoteStructure(I18N::translate('Note')),
659                'SOUR:DATA'                => new EmptyElement(I18N::translate('Data'), ['EVEN' => '0:M', 'AGNC' => '0:1', 'NOTE' => '0:M']),
660                'SOUR:DATA:AGNC'           => new ResponsibleAgency(I18N::translate('Agency')),
661                'SOUR:DATA:EVEN'           => new EventsRecorded(I18N::translate('Events')),
662                'SOUR:DATA:EVEN:DATE'      => new DateValue(I18N::translate('Date range')),
663                'SOUR:DATA:EVEN:PLAC'      => new SourceJurisdictionPlace(I18N::translate('Place')),
664                'SOUR:DATA:NOTE'           => new NoteStructure(I18N::translate('Note')),
665                'SOUR:NOTE'                => new NoteStructure(I18N::translate('Note')),
666                'SOUR:OBJE'                => new XrefMedia(I18N::translate('Media object')),
667                'SOUR:PUBL'                => new SourcePublicationFacts(I18N::translate('Publication')),
668                'SOUR:REFN'                => new UserReferenceNumber(I18N::translate('Reference number')),
669                'SOUR:REFN:TYPE'           => new UserReferenceType(I18N::translate('Type')),
670                'SOUR:REPO'                => new XrefRepository(I18N::translate('Repository')),
671                'SOUR:REPO:CALN'           => new SourceCallNumber(I18N::translate('Call number')),
672                'SOUR:REPO:CALN:MEDI'      => new SourceMediaType(I18N::translate('Media type')),
673                'SOUR:REPO:NOTE'           => new NoteStructure(I18N::translate('Note')),
674                'SOUR:RIN'                 => new AutomatedRecordId(I18N::translate('Record ID number')),
675                'SOUR:TEXT'                => new TextFromSource(I18N::translate('Text')),
676                'SOUR:TITL'                => new DescriptiveTitle(I18N::translate('Title')),
677                'SUBM'                     => new SubmitterRecord(I18N::translate('Submitter')),
678                'SUBM:ADDR'                => new AddressLine(I18N::translate('Address')),
679                'SUBM:ADDR:ADR1'           => new AddressLine1(I18N::translate('Address line 1')),
680                'SUBM:ADDR:ADR2'           => new AddressLine2(I18N::translate('Address line 2')),
681                'SUBM:ADDR:ADR3'           => new AddressLine3(I18N::translate('Address line 3')),
682                'SUBM:ADDR:CITY'           => new AddressCity(I18N::translate('City')),
683                'SUBM:ADDR:CTRY'           => new AddressCountry(I18N::translate('Country')),
684                'SUBM:ADDR:POST'           => new AddressPostalCode(I18N::translate('Postal code')),
685                'SUBM:ADDR:STAE'           => new AddressState(I18N::translate('State')),
686                'SUBM:CHAN'                => new Change(I18N::translate('Last change')),
687                'SUBM:CHAN:DATE'           => new ChangeDate(I18N::translate('Date of last change')),
688                'SUBM:CHAN:DATE:TIME'      => new TimeValue(I18N::translate('Time')),
689                'SUBM:CHAN:NOTE'           => new NoteStructure(I18N::translate('Note')),
690                'SUBM:EMAIL'               => new AddressEmail(I18N::translate('Email address')),
691                'SUBM:FAX'                 => new AddressFax(I18N::translate('Fax')),
692                'SUBM:LANG'                => new LanguageId(I18N::translate('Language')),
693                'SUBM:NAME'                => new SubmitterName(I18N::translate('Name')),
694                'SUBM:NOTE'                => new NoteStructure(I18N::translate('Note')),
695                'SUBM:OBJE'                => new XrefMedia(I18N::translate('Media object')),
696                'SUBM:PHON'                => new PhoneNumber(I18N::translate('Phone')),
697                'SUBM:RFN'                 => new SubmitterRegisteredRfn(I18N::translate('Record file number')),
698                'SUBM:RIN'                 => new AutomatedRecordId(I18N::translate('Record ID number')),
699                'SUBM:WWW'                 => new AddressWebPage(I18N::translate('URL')),
700                'SUBN'                     => new SubmissionRecord(I18N::translate('Submission')),
701                'SUBN:ANCE'                => new GenerationsOfAncestors(I18N::translate('Generations of ancestors')),
702                'SUBN:CHAN'                => new Change(I18N::translate('Last change')),
703                'SUBN:CHAN:DATE'           => new ChangeDate(I18N::translate('Date of last change')),
704                'SUBN:CHAN:DATE:TIME'      => new TimeValue(I18N::translate('Time')),
705                'SUBN:CHAN:NOTE'           => new NoteStructure(I18N::translate('Note')),
706                'SUBN:DESC'                => new GenerationsOfDescendants(I18N::translate('Generations of descendants')),
707                'SUBN:FAMF'                => new NameOfFamilyFile(I18N::translate('Family file')),
708                'SUBN:NOTE'                => new NoteStructure(I18N::translate('Note')),
709                'SUBN:ORDI'                => new OrdinanceProcessFlag(I18N::translate('Ordinance')),
710                'SUBN:RIN'                 => new AutomatedRecordId(I18N::translate('Record ID number')),
711                'SUBN:SUBM'                => new XrefSubmitter(I18N::translate('Submitter')),
712                'SUBN:TEMP'                => new TempleCode(/* I18N: https://en.wikipedia.org/wiki/Temple_(LDS_Church)*/ I18N::translate('Temple')),
713                'TRLR'                     => new EmptyElement(I18N::translate('Trailer')),
714            ];
715
716            // Aldfaer extensions
717            $this->register([
718                'FAM:MARR_CIVIL'     => new CustomEvent(I18N::translate('Civil marriage')),
719                'FAM:MARR_RELIGIOUS' => new CustomEvent(I18N::translate('Religious marriage')),
720                'FAM:MARR_PARTNERS'  => new CustomEvent(I18N::translate('Registered partnership')),
721                'FAM:MARR_UNKNOWN'   => new CustomEvent(I18N::translate('Marriage type unknown')),
722            ]);
723
724            // Ancestry extensions
725            $this->register([
726                'INDI:*:SOUR:_APID' => new CustomElement(I18N::translate('Ancestry PID')),
727                'INDI:_EMPLOY'      => new CustomEvent(I18N::translate('Occupation')),
728            ]);
729
730            // Brother’s Keeper extensions
731            $this->register([
732                'FAM:*:_EVN'       => new CustomElement('Event number'),
733                'FAM:CHIL:_FREL'   => new CustomElement('Relationship to father'),
734                'FAM:CHIL:_MREL'   => new CustomElement('Relationship to mother'),
735                'FAM:_COML'        => new CustomEvent(I18N::translate('Common law marriage')),
736                'FAM:_MARI'        => new CustomEvent(I18N::translate('Marriage intention')),
737                'FAM:_MBON'        => new CustomEvent(I18N::translate('Marriage bond')),
738                'FAM:_NMR'         => new CustomEvent(I18N::translate('Not married'), ['NOTE' => '0:M', 'SOUR' => '0:M']),
739                'FAM:_PRMN'        => new CustomElement(I18N::translate('Permanent number')),
740                'FAM:_SEPR'        => new CustomEvent(I18N::translate('Separated')),
741                'FAM:_TODO'        => new CustomElement(I18N::translate('Research task')),
742                'INDI:*:_EVN'      => new CustomElement('Event number'),
743                'INDI:NAME:_ADPN'  => new NamePersonal(I18N::translate('Adopted name')),
744                'INDI:NAME:_AKAN'  => new NamePersonal(I18N::translate('Also known as')),
745                'INDI:NAME:_BIRN'  => new NamePersonal(I18N::translate('Birth name')),
746                'INDI:NAME:_CALL'  => new NamePersonal('Called name'),
747                'INDI:NAME:_CENN'  => new NamePersonal('Census name'),
748                'INDI:NAME:_CURN'  => new NamePersonal('Current name'),
749                'INDI:NAME:_FARN'  => new NamePersonal(I18N::translate('Estate name')),
750                'INDI:NAME:_FKAN'  => new NamePersonal('Formal name'),
751                'INDI:NAME:_FRKA'  => new NamePersonal('Formerly known as'),
752                'INDI:NAME:_GERN'  => new NamePersonal('German name'),
753                'INDI:NAME:_HEBN'  => new NamePersonal(I18N::translate('Hebrew name')),
754                'INDI:NAME:_HNM'   => new NamePersonal(I18N::translate('Hebrew name')),
755                'INDI:NAME:_INDG'  => new NamePersonal('Indigenous name'),
756                'INDI:NAME:_INDN'  => new NamePersonal('Indian name'),
757                'INDI:NAME:_LNCH'  => new NamePersonal('Legal name change'),
758                'INDI:NAME:_MARN'  => new NamePersonal('Married name'),
759                'INDI:NAME:_MARNM' => new NamePersonal('Married name'),
760                'INDI:NAME:_OTHN'  => new NamePersonal('Other name'),
761                'INDI:NAME:_RELN'  => new NamePersonal('Religious name'),
762                'INDI:NAME:_SHON'  => new NamePersonal('Short name'),
763                'INDI:NAME:_SLDN'  => new NamePersonal('Soldier name'),
764                'INDI:_ADPF'       => new CustomElement(I18N::translate('Adopted by father')),
765                'INDI:_ADPM'       => new CustomElement(I18N::translate('Adopted by mother')),
766                'INDI:_BRTM'       => new CustomEvent(I18N::translate('Brit milah')),
767                'INDI:_BRTM:DATE'  => new DateValue(I18N::translate('Date of brit milah')),
768                'INDI:_BRTM:PLAC'  => new PlaceName(I18N::translate('Place of brit milah')),
769                'INDI:_EMAIL'      => new AddressEmail(I18N::translate('Email address')),
770                'INDI:_EYEC'       => new CustomFact(I18N::translate('Eye color')),
771                'INDI:_FRNL'       => new CustomElement(I18N::translate('Funeral')),
772                'INDI:_HAIR'       => new CustomFact(I18N::translate('Hair color')),
773                'INDI:_HEIG'       => new CustomFact(I18N::translate('Height')),
774                'INDI:_INTE'       => new CustomElement(I18N::translate('Interment')),
775                'INDI:_MEDC'       => new CustomFact(I18N::translate('Medical')),
776                'INDI:_MILT'       => new CustomElement(I18N::translate('Military service')),
777                'INDI:_NLIV'       => new CustomFact(I18N::translate('Not living')),
778                'INDI:_NMAR'       => new CustomEvent(I18N::translate('Never married'), ['NOTE' => '0:M', 'SOUR' => '0:M']),
779                'INDI:_PRMN'       => new CustomElement(I18N::translate('Permanent number')),
780                'INDI:_TODO'       => new CustomElement(I18N::translate('Research task')),
781                'INDI:_WEIG'       => new CustomFact(I18N::translate('Weight')),
782                'INDI:_YART'       => new CustomEvent(I18N::translate('Yahrzeit')),
783                // 1 XXXX
784                // 2 _EVN ##
785                // 1 ASSO @Xnnn@
786                // 2 RELA Witness at event _EVN ##
787            ]);
788
789            // familysearch.org extensions
790            $this->register([
791                'INDI:_FSFTID' => /* I18N: familysearch.org */ new FamilySearchFamilyTreeId(I18N::translate('FamilySearch ID')),
792            ]);
793
794            // Family Tree Builder extensions
795            $this->register([
796                '*:_UPD'              => new CustomElement(I18N::translate('Last change')), // e.g. "1 _UPD 14 APR 2012 00:14:10 GMT-5"
797                'INDI:NAME:_AKA'      => new NamePersonal(I18N::translate('Also known as')),
798                'OBJE:_ALBUM'         => new CustomElement(I18N::translate('Album')), // XREF to an album
799                'OBJE:_DATE'          => new DateValue(I18N::translate('Date')),
800                'OBJE:_FILESIZE'      => new CustomElement(I18N::translate('File size')),
801                'OBJE:_PHOTO_RIN'     => new CustomElement(I18N::translate('Photo')),
802                'OBJE:_PLACE'         => new PlaceName(I18N::translate('Place')),
803                '_ALBUM:_PHOTO'       => new CustomElement(I18N::translate('Photo')),
804                '_ALBUM:_PHOTO:_PRIN' => new CustomElement(I18N::translate('Highlighted image')),
805            ]);
806
807            // Family Tree Maker extensions
808            $this->register([
809                'FAM:CHIL:_FREL'              => new CustomElement(I18N::translate('Relationship to father')),
810                'FAM:CHIL:_MREL'              => new CustomElement(I18N::translate('Relationship to mother')),
811                'FAM:_DETS'                   => new CustomElement(I18N::translate('Death of one spouse')),
812                'FAM:_FA1'                    => new CustomElement('Fact 1'),
813                'FAM:_FA10'                   => new CustomElement('Fact 10'),
814                'FAM:_FA11'                   => new CustomElement('Fact 11'),
815                'FAM:_FA12'                   => new CustomElement('Fact 12'),
816                'FAM:_FA13'                   => new CustomElement('Fact 13'),
817                'FAM:_FA2'                    => new CustomElement('Fact 2'),
818                'FAM:_FA3'                    => new CustomElement('Fact 3'),
819                'FAM:_FA4'                    => new CustomElement('Fact 4'),
820                'FAM:_FA5'                    => new CustomElement('Fact 5'),
821                'FAM:_FA6'                    => new CustomElement('Fact 6'),
822                'FAM:_FA7'                    => new CustomElement('Fact 7'),
823                'FAM:_FA8'                    => new CustomElement('Fact 8'),
824                'FAM:_FA9'                    => new CustomElement('Fact 9'),
825                'FAM:_MEND'                   => new CustomElement(I18N::translate('Marriage ending status')),
826                'FAM:_MSTAT'                  => new CustomElement(I18N::translate('Marriage beginning status')),
827                'FAM:_SEPR'                   => new CustomElement(I18N::translate('Separation')),
828                'HEAD:_SCHEMA'                => new CustomElement('Schema'),
829                'HEAD:_SCHEMA:FAM'            => new CustomElement(I18N::translate('Family')),
830                'HEAD:_SCHEMA:FAM:_FA*:LABL'  => new CustomElement(I18N::translate('Label')),
831                'HEAD:_SCHEMA:FAM:_FA1'       => new CustomElement(I18N::translate('Fact 1')),
832                'HEAD:_SCHEMA:FAM:_FA10'      => new CustomElement(I18N::translate('Fact 10')),
833                'HEAD:_SCHEMA:FAM:_FA11'      => new CustomElement(I18N::translate('Fact 11')),
834                'HEAD:_SCHEMA:FAM:_FA12'      => new CustomElement(I18N::translate('Fact 12')),
835                'HEAD:_SCHEMA:FAM:_FA13'      => new CustomElement(I18N::translate('Fact 13')),
836                'HEAD:_SCHEMA:FAM:_FA2'       => new CustomElement(I18N::translate('Fact 2')),
837                'HEAD:_SCHEMA:FAM:_FA3'       => new CustomElement(I18N::translate('Fact 3')),
838                'HEAD:_SCHEMA:FAM:_FA4'       => new CustomElement(I18N::translate('Fact 4')),
839                'HEAD:_SCHEMA:FAM:_FA5'       => new CustomElement(I18N::translate('Fact 5')),
840                'HEAD:_SCHEMA:FAM:_FA6'       => new CustomElement(I18N::translate('Fact 6')),
841                'HEAD:_SCHEMA:FAM:_FA7'       => new CustomElement(I18N::translate('Fact 7')),
842                'HEAD:_SCHEMA:FAM:_FA8'       => new CustomElement(I18N::translate('Fact 8')),
843                'HEAD:_SCHEMA:FAM:_FA9'       => new CustomElement(I18N::translate('Fact 9')),
844                'HEAD:_SCHEMA:FAM:_M*:LABL'   => new CustomElement(I18N::translate('Label')),
845                'HEAD:_SCHEMA:FAM:_MEND'      => new CustomElement(I18N::translate('Marriage ending status')),
846                'HEAD:_SCHEMA:FAM:_MSTAT'     => new CustomElement(I18N::translate('Marriage beginning status')),
847                'HEAD:_SCHEMA:INDI'           => new CustomElement(I18N::translate('Individual')),
848                'HEAD:_SCHEMA:INDI:_FA*:LABL' => new CustomElement(I18N::translate('Label')),
849                'HEAD:_SCHEMA:INDI:_FA1'      => new CustomElement(I18N::translate('Fact 1')),
850                'HEAD:_SCHEMA:INDI:_FA10'     => new CustomElement(I18N::translate('Fact 10')),
851                'HEAD:_SCHEMA:INDI:_FA11'     => new CustomElement(I18N::translate('Fact 11')),
852                'HEAD:_SCHEMA:INDI:_FA12'     => new CustomElement(I18N::translate('Fact 12')),
853                'HEAD:_SCHEMA:INDI:_FA13'     => new CustomElement(I18N::translate('Fact 13')),
854                'HEAD:_SCHEMA:INDI:_FA2'      => new CustomElement(I18N::translate('Fact 2')),
855                'HEAD:_SCHEMA:INDI:_FA3'      => new CustomElement(I18N::translate('Fact 3')),
856                'HEAD:_SCHEMA:INDI:_FA4'      => new CustomElement(I18N::translate('Fact 4')),
857                'HEAD:_SCHEMA:INDI:_FA5'      => new CustomElement(I18N::translate('Fact 5')),
858                'HEAD:_SCHEMA:INDI:_FA6'      => new CustomElement(I18N::translate('Fact 6')),
859                'HEAD:_SCHEMA:INDI:_FA7'      => new CustomElement(I18N::translate('Fact 7')),
860                'HEAD:_SCHEMA:INDI:_FA8'      => new CustomElement(I18N::translate('Fact 8')),
861                'HEAD:_SCHEMA:INDI:_FA9'      => new CustomElement(I18N::translate('Fact 9')),
862                'HEAD:_SCHEMA:INDI:_FREL'     => new CustomElement('Relationship to father'),
863                'HEAD:_SCHEMA:INDI:_M*:LABL'  => new CustomElement(I18N::translate('Label')),
864                'HEAD:_SCHEMA:INDI:_MREL'     => new CustomElement('Relationship to mother'),
865                'INDI:*:SOUR:_APID'           => new CustomElement('Ancestry.com source identifier'),
866                'INDI:*:SOUR:_LINK'           => new CustomElement('External link'),
867                'INDI:NAME:_AKA'              => new NamePersonal(I18N::translate('Also known as')),
868                'INDI:NAME:_MARNM'            => new NamePersonal(I18N::translate('Married name')),
869                'INDI:_CIRC'                  => new CustomElement('Circumcision'),
870                'INDI:_DCAUSE'                => new CustomElement(I18N::translate('Cause of death')),
871                'INDI:_DEG'                   => new CustomElement(I18N::translate('Degree')),
872                'INDI:_DNA'                   => new CustomElement(I18N::translate('DNA markers')),
873                'INDI:_ELEC'                  => new CustomElement('Elected'),
874                'INDI:_EMPLOY'                => new CustomElement('Employment'),
875                'INDI:_EXCM'                  => new CustomElement('Excommunicated'),
876                'INDI:_FA1'                   => new CustomElement('Fact 1'),
877                'INDI:_FA10'                  => new CustomElement('Fact 10'),
878                'INDI:_FA11'                  => new CustomElement('Fact 11'),
879                'INDI:_FA12'                  => new CustomElement('Fact 12'),
880                'INDI:_FA13'                  => new CustomElement('Fact 13'),
881                'INDI:_FA2'                   => new CustomElement('Fact 2'),
882                'INDI:_FA3'                   => new CustomElement('Fact 3'),
883                'INDI:_FA4'                   => new CustomElement('Fact 4'),
884                'INDI:_FA5'                   => new CustomElement('Fact 5'),
885                'INDI:_FA6'                   => new CustomElement('Fact 6'),
886                'INDI:_FA7'                   => new CustomElement('Fact 7'),
887                'INDI:_FA8'                   => new CustomElement('Fact 8'),
888                'INDI:_FA9'                   => new CustomElement('Fact 9'),
889                'INDI:_MDCL'                  => new CustomElement('Medical'),
890                'INDI:_MILT'                  => new CustomElement(I18N::translate('Military service')),
891                'INDI:_MILTID'                => new CustomElement('Military ID number'),
892                'INDI:_MISN'                  => new CustomElement('Mission'),
893                'INDI:_NAMS'                  => new CustomElement(I18N::translate('Namesake')),
894                'INDI:_UNKN'                  => new CustomElement(I18N::translate('Unknown')), // Special individual ID code for later file comparisons
895                // The context and meaning of these tags is unknown
896                '_FOOT'                       => new CustomElement(''),
897                '_FUN'                        => new CustomElement(''),
898                '_JUST'                       => new CustomElement(''),
899                '_PHOTO'                      => new CustomElement(''),
900            ]);
901
902            // Gedcom 5.3 extensions
903            $this->register([
904                'EVEN'                       => new CustomElement('Event'),
905                'EVEN:*:*:NAME'              => new NamePersonal(I18N::translate('Name')),
906                'EVEN:*:AUDIO'               => new CustomElement(I18N::translate('Audio')),
907                'EVEN:*:BROT'                => new PlaceName('Brother'),
908                'EVEN:*:BUYR'                => new PlaceName('Buyer'),
909                'EVEN:*:CHIL'                => new PlaceName('Child'),
910                'EVEN:*:DATE'                => new DateValue('Date'),
911                'EVEN:*:FATH'                => new PlaceName('Father'),
912                'EVEN:*:GODP'                => new PlaceName('Godparent'),
913                'EVEN:*:HDOH'                => new PlaceName('Head of household'),
914                'EVEN:*:HEIR'                => new PlaceName('Heir'),
915                'EVEN:*:HFAT'                => new PlaceName('Husband’s father'),
916                'EVEN:*:HMOT'                => new PlaceName('Husband’s mother'),
917                'EVEN:*:HUSB'                => new PlaceName('Husband'),
918                'EVEN:*:IMAGE'               => new CustomElement('Image'),
919                'EVEN:*:INDI'                => new PlaceName('Individual'),
920                'EVEN:*:INFT'                => new PlaceName('Informant'),
921                'EVEN:*:LEGA'                => new PlaceName('Legatee'),
922                'EVEN:*:MBR'                 => new PlaceName('Member'),
923                'EVEN:*:MOTH'                => new PlaceName('Mother'),
924                'EVEN:*:OFFI'                => new PlaceName('Official'),
925                'EVEN:*:PARE'                => new PlaceName('Parent'),
926                'EVEN:*:PHOTO'               => new CustomElement(I18N::translate('Photo')),
927                'EVEN:*:PHUS'                => new PlaceName('Previous husband'),
928                'EVEN:*:PLAC'                => new PlaceName('Place'),
929                'EVEN:*:PWIF'                => new PlaceName('Previous wife'),
930                'EVEN:*:RECO'                => new PlaceName('Recorder'),
931                'EVEN:*:REL'                 => new PlaceName('Relative'),
932                'EVEN:*:SELR'                => new PlaceName('Seller'),
933                'EVEN:*:SIBL'                => new PlaceName('Sibling'),
934                'EVEN:*:SIST'                => new PlaceName('Sister'),
935                'EVEN:*:SPOU'                => new PlaceName('Spouse'),
936                'EVEN:*:TXPY'                => new PlaceName('Taxpayer'),
937                'EVEN:*:VIDEO'               => new CustomElement(I18N::translate('Video')),
938                'EVEN:*:WFAT'                => new PlaceName('Wife’s father'),
939                'EVEN:*:WIFE'                => new PlaceName('Wife'),
940                'EVEN:*:WITN'                => new PlaceName('Witness'),
941                'EVEN:*:WMOT'                => new PlaceName('Wife’s mother'),
942                'EVEN:TYPE'                  => new CustomElement('Type of event'),
943                'FAM:*:*:QUAY'               => new CertaintyAssessment(I18N::translate('Quality of data')),
944                'FAM:*:PLAC:SITE'            => new CustomElement('Site'),
945                'FAM:*:QUAY'                 => new CertaintyAssessment(I18N::translate('Quality of data')),
946                'FAM:AUDIO'                  => new CustomElement(I18N::translate('Audio')),
947                'FAM:IMAGE'                  => new CustomElement('Image'),
948                'FAM:PHOTO'                  => new CustomElement(I18N::translate('Photo')),
949                'FAM:VIDEO'                  => new CustomElement(I18N::translate('Video')),
950                'HEAD:SCHEMA'                => new CustomElement(I18N::translate('Unknown')),
951                'HEAD:SCHEMA:FAM'            => new CustomElement(I18N::translate('Family')),
952                'HEAD:SCHEMA:FAM:*:_*'       => new CustomElement('Custom event'),
953                'HEAD:SCHEMA:FAM:*:_*:DEFN'  => new CustomElement('Definition'),
954                'HEAD:SCHEMA:FAM:*:_*:ISA'   => new CustomElement('Type of event'),
955                'HEAD:SCHEMA:FAM:*:_*:LABL'  => new CustomElement('Label'),
956                'HEAD:SCHEMA:FAM:_*'         => new CustomElement('Custom event'),
957                'HEAD:SCHEMA:FAM:_*:DEFN'    => new CustomElement('Definition'),
958                'HEAD:SCHEMA:FAM:_*:ISA'     => new CustomElement('Type of event'),
959                'HEAD:SCHEMA:FAM:_*:LABL'    => new CustomElement('Label'),
960                'HEAD:SCHEMA:INDI'           => new CustomElement(I18N::translate('Individual')),
961                'HEAD:SCHEMA:INDI:*:_*'      => new CustomElement('Custom event'),
962                'HEAD:SCHEMA:INDI:*:_*:DEFN' => new CustomElement('Definition'),
963                'HEAD:SCHEMA:INDI:*:_*:ISA'  => new CustomElement('Type of event'),
964                'HEAD:SCHEMA:INDI:*:_*:LABL' => new CustomElement('Label'),
965                'HEAD:SCHEMA:INDI:_*'        => new CustomElement('Custom event'),
966                'HEAD:SCHEMA:INDI:_*:DEFN'   => new CustomElement('Definition'),
967                'HEAD:SCHEMA:INDI:_*:ISA'    => new CustomElement('Type of event'),
968                'HEAD:SCHEMA:INDI:_*:LABL'   => new CustomElement('Label'),
969                'INDI:*:*:QUAY'              => new CertaintyAssessment(I18N::translate('Quality of data')),
970                'INDI:*:PLAC:SITE'           => new CustomElement('Site'),
971                'INDI:*:QUAY'                => new CertaintyAssessment(I18N::translate('Quality of data')),
972                'INDI:AUDIO'                 => new CustomElement(I18N::translate('Audio')),
973                'INDI:BURI:PLAC:CEME'        => new CustomElement(I18N::translate('Cemetery')),
974                'INDI:BURI:PLAC:CEME:PLOT'   => new CustomElement('Burial plot'),
975                'INDI:IMAGE'                 => new CustomElement('Image'),
976                'INDI:NAMR'                  => new CustomElement(I18N::translate('Religious name')),
977                'INDI:NAMS'                  => new CustomElement(I18N::translate('Namesake')),
978                'INDI:PHOTO'                 => new CustomElement(I18N::translate('Photo')),
979                'INDI:SIGN'                  => new CustomElement('Signature'),
980                'INDI:VIDEO'                 => new CustomElement(I18N::translate('Video')),
981                'REPO:CALN:ITEM'             => new CustomElement('Item'),
982                'REPO:CALN:PAGE'             => new CustomElement('Page'),
983                'REPO:CALN:SHEE'             => new CustomElement('Sheet'),
984                'REPO:CNTC'                  => new CustomElement('Contact person'),
985                'REPO:MEDI'                  => new SourceMediaType(I18N::translate('Media type')),
986                'REPO:REFN'                  => new CustomElement('Reference number'),
987                'SOUR:AUDIO'                 => new CustomElement(I18N::translate('Audio')),
988                'SOUR:CENS'                  => new CustomElement('Census'),
989                'SOUR:CENS:DATE'             => new CustomElement('Census'),
990                'SOUR:CENS:DWEL'             => new CustomElement('Dwelling number'),
991                'SOUR:CENS:FAMN'             => new CustomElement('Family number'),
992                'SOUR:CENS:LINE'             => new CustomElement('Line number'),
993                'SOUR:CLAS'                  => new CustomElement('Source classification'),
994                'SOUR:CPLR'                  => new CustomElement('Compiler'),
995                'SOUR:EDTR'                  => new CustomElement('Editor'),
996                'SOUR:EVEN'                  => new CustomElement('Source events'),
997                'SOUR:FIDE'                  => new CustomElement('Fidelity'),
998                'SOUR:FILM'                  => new CustomElement(I18N::translate('Microfilm')),
999                'SOUR:IMAGE'                 => new CustomElement('Image'),
1000                'SOUR:INDX'                  => new CustomElement('Indexed'),
1001                'SOUR:INTV'                  => new CustomElement('Interviewer'),
1002                'SOUR:ORIG'                  => new CustomElement('Originator'),
1003                'SOUR:ORIG:NAME'             => new CustomElement('Name'),
1004                'SOUR:ORIG:NOTE'             => new CustomElement('Note'),
1005                'SOUR:ORIG:TYPE'             => new CustomElement('Type'),
1006                'SOUR:PERI'                  => new CustomElement('Date period'),
1007                'SOUR:PHOTO'                 => new CustomElement(I18N::translate('Photo')),
1008                'SOUR:PUBL:DATE'             => new CustomElement('Date'),
1009                'SOUR:PUBL:EDTN'             => new CustomElement('Edition'),
1010                'SOUR:PUBL:ISSU'             => new CustomElement('Issue'),
1011                'SOUR:PUBL:LCCN'             => new CustomElement('Library of Congress call number'),
1012                'SOUR:PUBL:NAME'             => new CustomElement('Name'),
1013                'SOUR:PUBL:PUBR'             => new CustomElement('Publisher'),
1014                'SOUR:PUBL:SERS'             => new CustomElement('Series'),
1015                'SOUR:PUBL:TYPE'             => new CustomElement('Type'),
1016                'SOUR:QUAY'                  => new CertaintyAssessment(I18N::translate('Quality of data')),
1017                'SOUR:RECO'                  => new CustomElement('Recording agency?'),
1018                'SOUR:REFS'                  => new XrefSource('Referenced source'),
1019                'SOUR:REPO:DPRT:ARVL'        => new CustomElement('Departure'),
1020                'SOUR:REPO:DPRT:ARVL:DATE'   => new DateValue('Date'),
1021                'SOUR:REPO:DPRT:ARVL:PLAC'   => new PlaceName('Place'),
1022                'SOUR:REPO:NAME'             => new CustomElement('Name of vessel'),
1023                'SOUR:REPO:NOTE'             => new NoteStructure(I18N::translate('Note')),
1024                'SOUR:REPO:PORT'             => new CustomElement('Port'),
1025                'SOUR:REPO:PORT:ARVL'        => new CustomElement('Arrival'),
1026                'SOUR:REPO:PORT:ARVL:DATE'   => new DateValue('Date'),
1027                'SOUR:REPO:PORT:ARVL:PLAC'   => new PlaceName('Place'),
1028                'SOUR:REPO:TEXT'             => new TextFromSource(I18N::translate('Text')),
1029                'SOUR:SEQU'                  => new CustomElement('Sequence'),
1030                'SOUR:STAT'                  => new CustomElement('Search status'),
1031                'SOUR:STAT:DATE'             => new DateValue('Date'),
1032                'SOUR:TEXT'                  => new TextFromSource(I18N::translate('Text')),
1033                'SOUR:TYPE'                  => new CustomElement('Type of source'),
1034                'SOUR:VIDEO'                 => new CustomElement(I18N::translate('Video')),
1035                'SOUR:XLTR'                  => new CustomElement('Translator'),
1036            ]);
1037
1038            // Gedcom 5.5 extensions
1039            $this->register([
1040                'OBJE:BLOB' => new UnknownElement(I18N::translate('Binary data object')),
1041            ]);
1042
1043            // Gedcom-L extensions
1044            $this->register([
1045                'FAM:*:ADDR:_NAME'               => new CustomElement('Name of addressee'),
1046                'FAM:*:PLAC:_GOV'                => new GovIdentifier(I18N::translate('GOV identifier')),
1047                'FAM:*:PLAC:_LOC'                => new XrefLocation(I18N::translate('Location')),
1048                'FAM:*:PLAC:_MAIDENHEAD'         => new MaidenheadLocator('Maidenhead locator'),
1049                'FAM:*:PLAC:_POST'               => new AddressPostalCode('Postal code'),
1050                'FAM:*:PLAC:_POST:DATE'          => new DateValue(I18N::translate('Date')),
1051                'FAM:*:_ASSO'                    => new XrefAssociate(I18N::translate('Associate')),
1052                'FAM:*:_ASSO:NOTE'               => new NoteStructure(I18N::translate('Note')),
1053                'FAM:*:_ASSO:RELA'               => new RelationIsDescriptor(I18N::translate('Relationship')),
1054                'FAM:*:_ASSO:SOUR'               => new XrefSource(I18N::translate('Source citation')),
1055                'FAM:*:_ASSO:SOUR:DATA'          => new SourceData(I18N::translate('Data')),
1056                'FAM:*:_ASSO:SOUR:DATA:DATE'     => new EntryRecordingDate(I18N::translate('Date of entry in original source')),
1057                'FAM:*:_ASSO:SOUR:DATA:TEXT'     => new TextFromSource(I18N::translate('Text')),
1058                'FAM:*:_ASSO:SOUR:EVEN'          => new EventTypeCitedFrom(I18N::translate('Event')),
1059                'FAM:*:_ASSO:SOUR:EVEN:ROLE'     => new RoleInEvent(I18N::translate('Role')),
1060                'FAM:*:_ASSO:SOUR:NOTE'          => new NoteStructure(I18N::translate('Note')),
1061                'FAM:*:_ASSO:SOUR:OBJE'          => new XrefMedia(I18N::translate('Media object')),
1062                'FAM:*:_ASSO:SOUR:PAGE'          => new WhereWithinSource(I18N::translate('Citation details')),
1063                'FAM:*:_ASSO:SOUR:QUAY'          => new CertaintyAssessment(I18N::translate('Quality of data')),
1064                'FAM:*:_WITN'                    => new CustomElement('Witness'),
1065                'FAM:_STAT'                      => new FamilyStatusText(I18N::translate('Family status'), ['DATE' => '0:1', 'PLAC' => '0:1', 'NOTE' => '0:M', 'SOUR' => '0:M']),
1066                'FAM:_TODO'                      => new ResearchTask(I18N::translate('Research task'), ['DESC' => '1:1', '_CAT' => '0:1', '_PRTY' => '0:1', 'TYPE' => '0:1', 'NOTE' => '0:M', 'DATA' => '0:1', 'STAT' => '0:1', '_CDATE' => '0:1', '_RDATE' => '0:1', 'REPO' => '0:1', '_UID' => '0:M']),
1067                'FAM:_TODO:DATA'                 => new SubmitterText(I18N::translate('The solution')),
1068                'FAM:_TODO:DATE'                 => new DateValue(I18N::translate('Creation date')),
1069                'FAM:_TODO:DESC'                 => new CustomElement(I18N::translate('Description')),
1070                'FAM:_TODO:NOTE'                 => new SubmitterText(I18N::translate('The problem')),
1071                'FAM:_TODO:REPO'                 => new XrefRepository('Repository', []),
1072                'FAM:_TODO:STAT'                 => new ResearchTaskStatus(I18N::translate('Status')),
1073                'FAM:_TODO:TYPE'                 => new ResearchTaskType(I18N::translate('Type of research task')),
1074                'FAM:_TODO:_CAT'                 => new CustomElement(I18N::translate('Category')),
1075                'FAM:_TODO:_CDATE'               => new DateValue(I18N::translate('Completion date')),
1076                'FAM:_TODO:_PRTY'                => new ResearchTaskPriority(I18N::translate('Priority')),
1077                'FAM:_TODO:_RDATE'               => new DateValue(I18N::translate('Reminder date')),
1078                'FAM:_UID'                       => new PafUid(I18N::translate('Unique identifier')),
1079                'HEAD:SOUR:CORP:ADDR:_NAME'      => new CustomElement('Name of addressee'),
1080                'HEAD:_SCHEMA'                   => new EmptyElement(I18N::translate('Schema')),
1081                'HEAD:_SCHEMA:*'                 => new EmptyElement(I18N::translate('Base GEDCOM tag')),
1082                'HEAD:_SCHEMA:*:*'               => new EmptyElement(I18N::translate('New GEDCOM tag')),
1083                'HEAD:_SCHEMA:*:*:*'             => new EmptyElement(I18N::translate('New GEDCOM tag')),
1084                'HEAD:_SCHEMA:*:*:*:*'           => new EmptyElement(I18N::translate('New GEDCOM tag')),
1085                'HEAD:_SCHEMA:*:*:*:*:*'         => new EmptyElement(I18N::translate('New GEDCOM tag')),
1086                'HEAD:_SCHEMA:*:*:*:*:*:*'       => new EmptyElement(I18N::translate('New GEDCOM tag')),
1087                'HEAD:_SCHEMA:*:*:*:*:*:*:_DEFN' => new EmptyElement(I18N::translate('Definition')),
1088                'HEAD:_SCHEMA:*:*:*:*:*:_DEFN'   => new EmptyElement(I18N::translate('Definition')),
1089                'HEAD:_SCHEMA:*:*:*:*:_DEFN'     => new EmptyElement(I18N::translate('Definition')),
1090                'HEAD:_SCHEMA:*:*:*:_DEFN'       => new EmptyElement(I18N::translate('Definition')),
1091                'HEAD:_SCHEMA:*:*:_DEFN'         => new EmptyElement(I18N::translate('Definition')),
1092                'INDI:*:ADDR:_NAME'              => new CustomElement('Name of addressee'),
1093                'INDI:*:PLAC:_GOV'               => new GovIdentifier(I18N::translate('GOV identifier')),
1094                'INDI:*:PLAC:_LOC'               => new XrefLocation(I18N::translate('Location')),
1095                'INDI:*:PLAC:_MAIDENHEAD'        => new MaidenheadLocator('Maidenhead locator'),
1096                'INDI:*:PLAC:_POST'              => new AddressPostalCode('Postal code'),
1097                'INDI:*:PLAC:_POST:DATE'         => new DateValue(I18N::translate('Date')),
1098                'INDI:*:_ASSO'                   => new XrefAssociate(I18N::translate('Associate')),
1099                'INDI:*:_ASSO:NOTE'              => new NoteStructure(I18N::translate('Note')),
1100                'INDI:*:_ASSO:RELA'              => new RelationIsDescriptor(I18N::translate('Relationship')),
1101                'INDI:*:_ASSO:SOUR'              => new XrefSource(I18N::translate('Source citation')),
1102                'INDI:*:_ASSO:SOUR:DATA'         => new SourceData(I18N::translate('Data')),
1103                'INDI:*:_ASSO:SOUR:DATA:DATE'    => new EntryRecordingDate(I18N::translate('Date of entry in original source')),
1104                'INDI:*:_ASSO:SOUR:DATA:TEXT'    => new TextFromSource(I18N::translate('Text')),
1105                'INDI:*:_ASSO:SOUR:EVEN'         => new EventTypeCitedFrom(I18N::translate('Event')),
1106                'INDI:*:_ASSO:SOUR:EVEN:ROLE'    => new RoleInEvent(I18N::translate('Role')),
1107                'INDI:*:_ASSO:SOUR:NOTE'         => new NoteStructure(I18N::translate('Note')),
1108                'INDI:*:_ASSO:SOUR:OBJE'         => new XrefMedia(I18N::translate('Media object')),
1109                'INDI:*:_ASSO:SOUR:PAGE'         => new WhereWithinSource(I18N::translate('Citation details')),
1110                'INDI:*:_ASSO:SOUR:QUAY'         => new CertaintyAssessment(I18N::translate('Quality of data')),
1111                'INDI:*:_WITN'                   => new CustomElement('Witness'),
1112                'INDI:BAPM:_GODP'                => new CustomElement('Godparent'),
1113                'INDI:CHR:_GODP'                 => new CustomElement('Godparent'),
1114                'INDI:NAME:_RUFNAME'             => new NamePieceGiven(I18N::translate('Rufname')),
1115                'INDI:OBJE:_PRIM'                => new CustomElement(I18N::translate('Highlighted image')),
1116                'INDI:SEX'                       => new SexXValue(I18N::translate('Gender')),
1117                'INDI:_TODO'                     => new ResearchTask(I18N::translate('Research task')),
1118                'INDI:_TODO:DATA'                => new SubmitterText(I18N::translate('The solution')),
1119                'INDI:_TODO:DATE'                => new DateValue(I18N::translate('Creation date')),
1120                'INDI:_TODO:DESC'                => new CustomElement(I18N::translate('Description')),
1121                'INDI:_TODO:NOTE'                => new SubmitterText(I18N::translate('The problem')),
1122                'INDI:_TODO:REPO'                => new XrefRepository('Repository', []),
1123                'INDI:_TODO:STAT'                => new ResearchTaskStatus(I18N::translate('Status')),
1124                'INDI:_TODO:TYPE'                => new ResearchTaskType(I18N::translate('Type of research task')),
1125                'INDI:_TODO:_CAT'                => new CustomElement(I18N::translate('Category')),
1126                'INDI:_TODO:_CDATE'              => new DateValue(I18N::translate('Completion date')),
1127                'INDI:_TODO:_PRTY'               => new ResearchTaskPriority(I18N::translate('Priority')),
1128                'INDI:_TODO:_RDATE'              => new DateValue(I18N::translate('Reminder date')),
1129                'INDI:_UID'                      => new PafUid(I18N::translate('Unique identifier')),
1130                'NOTE:_UID'                      => new PafUid(I18N::translate('Unique identifier')),
1131                'OBJE:FILE:_PRIM'                => new CustomElement(I18N::translate('Highlighted image')),
1132                'OBJE:_UID'                      => new PafUid(I18N::translate('Unique identifier')),
1133                'REPO:ADDR:_NAME'                => new CustomElement('Name of addressee'),
1134                'REPO:_UID'                      => new PafUid(I18N::translate('Unique identifier')),
1135                'SOUR:_UID'                      => new PafUid(I18N::translate('Unique identifier')),
1136                'SUBM:ADDR:_NAME'                => new CustomElement('Name of addressee'),
1137                'SUBM:_UID'                      => new PafUid(I18N::translate('Unique identifier')),
1138                'SUBN:_UID'                      => new PafUid(I18N::translate('Unique identifier')),
1139                '_LOC'                           => new LocationRecord(I18N::translate('Location')),
1140                '_LOC:CHAN'                      => new Change(I18N::translate('Last change')),
1141                '_LOC:CHAN:DATE'                 => new ChangeDate(I18N::translate('Date of last change')),
1142                '_LOC:CHAN:DATE:TIME'            => new TimeValue(I18N::translate('Time')),
1143                '_LOC:CHAN:NOTE'                 => new NoteStructure(I18N::translate('Note')),
1144                '_LOC:EVEN'                      => new EventDescriptor(I18N::translate('Event'), ['TYPE' => '0:1']),
1145                '_LOC:EVEN:TYPE'                 => new EventAttributeType(I18N::translate('Type of event')),
1146                '_LOC:MAP'                       => new EmptyElement(I18N::translate('Coordinates')),
1147                '_LOC:MAP:LATI'                  => new PlaceLatitude(I18N::translate('Latitude')),
1148                '_LOC:MAP:LONG'                  => new PlaceLongtitude(I18N::translate('Longitude')),
1149                '_LOC:NAME'                      => new PlaceName(I18N::translate('Place'), ['ABBR' => '0:1', 'DATE' => '0:1', 'LANG' => '0:1', 'SOUR' => '0:M']),
1150                '_LOC:NAME:ABBR'                 => new CustomElement(I18N::translate('Abbreviation')),
1151                '_LOC:NAME:ABBR:TYPE'            => new CustomElement(I18N::translate('Type of abbreviation')),
1152                '_LOC:NAME:DATE'                 => new DateValue(I18N::translate('Date')),
1153                '_LOC:NAME:LANG'                 => new LanguageId(I18N::translate('Language')),
1154                '_LOC:NAME:SOUR'                 => new XrefSource(I18N::translate('Source')),
1155                '_LOC:NOTE'                      => new NoteStructure(I18N::translate('Note')),
1156                '_LOC:OBJE'                      => new XrefMedia(I18N::translate('Media')),
1157                '_LOC:RELI'                      => new ReligiousAffiliation('Religion', []),
1158                '_LOC:SOUR'                      => new XrefSource(I18N::translate('Source')),
1159                '_LOC:SOUR:DATA'                 => new SourceData(I18N::translate('Data')),
1160                '_LOC:SOUR:DATA:DATE'            => new EntryRecordingDate(I18N::translate('Date of entry in original source')),
1161                '_LOC:SOUR:DATA:TEXT'            => new TextFromSource(I18N::translate('Text')),
1162                '_LOC:SOUR:EVEN'                 => new EventTypeCitedFrom(I18N::translate('Event')),
1163                '_LOC:SOUR:EVEN:ROLE'            => new RoleInEvent(I18N::translate('Role')),
1164                '_LOC:SOUR:NOTE'                 => new NoteStructure(I18N::translate('Note')),
1165                '_LOC:SOUR:OBJE'                 => new XrefMedia(I18N::translate('Media object')),
1166                '_LOC:SOUR:PAGE'                 => new WhereWithinSource(I18N::translate('Citation details')),
1167                '_LOC:SOUR:QUAY'                 => new CertaintyAssessment(I18N::translate('Quality of data')),
1168                '_LOC:TYPE'                      => new CustomElement(I18N::translate('Type of location')),
1169                '_LOC:TYPE:DATE'                 => new DateValue(I18N::translate('Date')),
1170                '_LOC:TYPE:SOUR'                 => new XrefSource(I18N::translate('Source')),
1171                '_LOC:TYPE:_GOVTYPE'             => new CustomElement('GOV identifier type'),
1172                '_LOC:_AIDN'                     => new CustomElement('Administrative ID'),
1173                '_LOC:_AIDN:DATE'                => new DateValue(I18N::translate('Date')),
1174                '_LOC:_AIDN:SOUR'                => new XrefSource(I18N::translate('Source')),
1175                '_LOC:_AIDN:TYPE'                => new CustomElement(I18N::translate('Type of administrative ID')),
1176                '_LOC:_DMGD'                     => new CustomElement('Demographic data'),
1177                '_LOC:_DMGD:DATE'                => new DateValue(I18N::translate('Date')),
1178                '_LOC:_DMGD:SOUR'                => new XrefSource(I18N::translate('Source')),
1179                '_LOC:_DMGD:TYPE'                => new CustomElement(I18N::translate('Type of demographic data')),
1180                '_LOC:_GOV'                      => new GovIdentifier(I18N::translate('GOV identifier')),
1181                '_LOC:_LOC'                      => new XrefLocation(I18N::translate('Parent'), ['DATE' => '0:1', 'SOUR' => '0:M', 'TYPE' => '0:1']),
1182                '_LOC:_LOC:DATE'                 => new DateValue(I18N::translate('Date')),
1183                '_LOC:_LOC:SOUR'                 => new XrefSource(I18N::translate('Source')),
1184                '_LOC:_LOC:TYPE'                 => new HierarchicalRelationship(I18N::translate('Hierarchical relationship')),
1185                '_LOC:_MAIDENHEAD'               => new MaidenheadLocator('Maidenhead locator'),
1186                '_LOC:_POST'                     => new AddressPostalCode(I18N::translate('Postal code')),
1187                '_LOC:_POST:DATE'                => new DateValue(I18N::translate('Date')),
1188                '_LOC:_POST:SOUR'                => new XrefSource(I18N::translate('Source')),
1189                '_LOC:_UID'                      => new PafUid(I18N::translate('Unique identifier')),
1190                '_LOC:*:SOUR:DATA'               => new SourceData(I18N::translate('Data')),
1191                '_LOC:*:SOUR:DATA:DATE'          => new EntryRecordingDate(I18N::translate('Date of entry in original source')),
1192                '_LOC:*:SOUR:DATA:TEXT'          => new TextFromSource(I18N::translate('Text')),
1193                '_LOC:*:SOUR:EVEN'               => new EventTypeCitedFrom(I18N::translate('Event')),
1194                '_LOC:*:SOUR:EVEN:ROLE'          => new RoleInEvent(I18N::translate('Role')),
1195                '_LOC:*:SOUR:NOTE'               => new NoteStructure(I18N::translate('Note')),
1196                '_LOC:*:SOUR:OBJE'               => new XrefMedia(I18N::translate('Media object')),
1197                '_LOC:*:SOUR:PAGE'               => new WhereWithinSource(I18N::translate('Citation details')),
1198                '_LOC:*:SOUR:QUAY'               => new CertaintyAssessment(I18N::translate('Quality of data')),
1199            ]);
1200
1201            // Legacy extensions
1202            $this->register([
1203                'FAM:*:ADDR:_PRIV'             => new CustomElement('Indicates that an address or event is marked as Private.'),
1204                'FAM:*:PLAC:_VERI'             => new CustomElement('Indicates that a source citation or place name has a checkmark in the Verified column.'),
1205                'FAM:*:SOUR:_VERI'             => new CustomElement('Indicates that a source citation or place name has a checkmark in the Verified column.'),
1206                'FAM:*:_PRIV'                  => new CustomElement('Indicates that an address or event is marked as Private.'),
1207                'FAM:CHIL:_FREL'               => new CustomElement('The Relationship of a child to the Father (under a CHIL block under a FAM record).'),
1208                'FAM:CHIL:_MREL'               => new CustomElement('The Relationship of a child to the Mother (under a CHIL block under a FAM record).'),
1209                'FAM:CHIL:_STAT'               => new CustomElement('The Status of a marriage (Married, Unmarried, etc.).  Also the Status of a child (Twin, Triplet, etc.).  (The marriage status of Divorced is exported using a DIV tag.)'),
1210                'FAM:EVEN:_OVER'               => new CustomElement('An event sentence override (under an EVEN block).'),
1211                'FAM:MARR:_STAT'               => new CustomElement('The Status of a marriage (Married, Unmarried, etc.).  Also the Status of a child (Twin, Triplet, etc.).  (The marriage status of Divorced is exported using a DIV tag.)'),
1212                'FAM:SOUR:_VERI'               => new CustomElement('Indicates that a source citation or place name has a checkmark in the Verified column.'),
1213                'FAM:_NONE'                    => new CustomElement('Indicates that a couple had no children (under a FAM record).'),
1214                'HEAD:_EVENT_DEFN'             => new CustomElement('Indicates the start of an Event Definition record that describes the attributes of an event or fact.'),
1215                'HEAD:_EVENT_DEFN:_CONF_FLAG'  => new CustomElement('Indicates that an event is Confidential or Private (under an _EVENT_DEFN record).'),
1216                'HEAD:_EVENT_DEFN:_DATE_TYPE'  => new CustomElement('Indicates whether or not a Date field is shown for a specific event (under an _EVENT_DEFN record).'),
1217                'HEAD:_EVENT_DEFN:_DESC_FLAG'  => new CustomElement('Indicates whether or not a Description field is shown for a specific event (under an _EVENT_DEFN record).'),
1218                'HEAD:_EVENT_DEFN:_PLACE_TYPE' => new CustomElement('Indicates whether or not a Place field is shown for a specific event (under an _EVENT_DEFN record).'),
1219                'HEAD:_EVENT_DEFN:_PP_EXCLUDE' => new CustomElement('Indicates that an event is to be Excluded from the Potential Problems reporting (under an _EVENT_DEFN record).'),
1220                'HEAD:_EVENT_DEFN:_SEN1'       => new CustomElement('Event sentence definitions (under an _EVENT_DEFN record).'),
1221                'HEAD:_EVENT_DEFN:_SEN2'       => new CustomElement('Event sentence definitions (under an _EVENT_DEFN record).'),
1222                'HEAD:_EVENT_DEFN:_SEN3'       => new CustomElement('Event sentence definitions (under an _EVENT_DEFN record).'),
1223                'HEAD:_EVENT_DEFN:_SEN4'       => new CustomElement('Event sentence definitions (under an _EVENT_DEFN record).'),
1224                'HEAD:_EVENT_DEFN:_SEN5'       => new CustomElement('Event sentence definitions (under an _EVENT_DEFN record).'),
1225                'HEAD:_EVENT_DEFN:_SEN6'       => new CustomElement('Event sentence definitions (under an _EVENT_DEFN record).'),
1226                'HEAD:_EVENT_DEFN:_SEN7'       => new CustomElement('Event sentence definitions (under an _EVENT_DEFN record).'),
1227                'HEAD:_EVENT_DEFN:_SEN8'       => new CustomElement('Event sentence definitions (under an _EVENT_DEFN record).'),
1228                'HEAD:_EVENT_DEFN:_SENDOF'     => new CustomElement('Event sentence for PAF5 if only the Date field is filled in for a Male individual (under an _EVENT_DEFN record).'),
1229                'HEAD:_EVENT_DEFN:_SENDOM'     => new CustomElement('Event sentence for PAF5 if only the Date field is filled in for a Male individual (under an _EVENT_DEFN record).'),
1230                'HEAD:_EVENT_DEFN:_SENDOU'     => new CustomElement('Event sentence for PAF5 if only the Date field is filled in for a Male individual (under an _EVENT_DEFN record).'),
1231                'HEAD:_EVENT_DEFN:_SENDPF'     => new CustomElement('Event sentence for PAF5 if only the Date and Place fields are filled in for a Male individual (under an _EVENT_DEFN record).'),
1232                'HEAD:_EVENT_DEFN:_SENDPM'     => new CustomElement('Event sentence for PAF5 if only the Date and Place fields are filled in for a Male individual (under an _EVENT_DEFN record).'),
1233                'HEAD:_EVENT_DEFN:_SENDPU'     => new CustomElement('Event sentence for PAF5 if only the Date and Place fields are filled in for a Male individual (under an _EVENT_DEFN record).'),
1234                'HEAD:_EVENT_DEFN:_SENF'       => new CustomElement('Event sentence for PAF5 if all fields are filled in for a Male individual (under an _EVENT_DEFN record).'),
1235                'HEAD:_EVENT_DEFN:_SENM'       => new CustomElement('Event sentence for PAF5 if all fields are filled in for a Male individual (under an _EVENT_DEFN record).'),
1236                'HEAD:_EVENT_DEFN:_SENPOF'     => new CustomElement('Event sentence for PAF5 if only the Place field is filled in for a Male individual (under an _EVENT_DEFN record).'),
1237                'HEAD:_EVENT_DEFN:_SENPOM'     => new CustomElement('Event sentence for PAF5 if only the Place field is filled in for a Male individual (under an _EVENT_DEFN record).'),
1238                'HEAD:_EVENT_DEFN:_SENPOU'     => new CustomElement('Event sentence for PAF5 if only the Place field is filled in for a Male individual (under an _EVENT_DEFN record).'),
1239                'HEAD:_EVENT_DEFN:_SENU'       => new CustomElement('Event sentence for PAF5 if all fields are filled in for a Male individual (under an _EVENT_DEFN record).'),
1240                'HEAD:_PLAC_DEFN'              => new CustomElement('Indicates the start of a Place Definition record that describes the attribute of a place.'),
1241                'HEAD:_PLAC_DEFN:_PREP'        => new CustomElement('A location Preposition (under a _PLAC_DEFN record).'),
1242                'INDI:*:ADDR:_LIST3 YES'       => new CustomElement('Indicates that a person’s address is part of the Birthday grouping (under an ADDR block).'),
1243                'INDI:*:ADDR:_LIST4 YES'       => new CustomElement('Indicates that a person’s address is part of the Research grouping (under an ADDR block).'),
1244                'INDI:*:ADDR:_LIST5 YES'       => new CustomElement('Indicates that a person’s address is part of the Christmas grouping (under an ADDR block).'),
1245                'INDI:*:ADDR:_LIST6 YES'       => new CustomElement('Indicates that a person’s address is part of the Holiday grouping (under an ADDR block).'),
1246                'INDI:*:ADDR:_NAME'            => new CustomElement('The name of an individual as part of an address (under an ADDR block).'),
1247                'INDI:*:ADDR:_PRIV'            => new CustomElement('Indicates that an address or event is marked as Private.'),
1248                'INDI:*:ADDR:_SORT'            => new CustomElement('The spelling of a name to be used when sorting addresses for a report (under an ADDR block).'),
1249                'INDI:*:ADDR:_TAG'             => new CustomElement('Indicates that an address, or place has been tagged.  Also used for Tag 1 selection for an individual.'),
1250                'INDI:*:PLAC:_TAG'             => new CustomElement('Indicates that an address, or place has been tagged.  Also used for Tag 1 selection for an individual.'),
1251                'INDI:*:PLAC:_VERI'            => new CustomElement('Indicates that a source citation or place name has a checkmark in the Verified column.'),
1252                'INDI:*:SOUR:_VERI'            => new CustomElement('Indicates that a source citation or place name has a checkmark in the Verified column.'),
1253                'INDI:*:_PRIV'                 => new CustomElement('Indicates that an address or event is marked as Private.'),
1254                'INDI:ADDR:_EMAIL'             => new CustomElement('An email address (under an ADDR block).'),
1255                'INDI:ADDR:_LIST1 YES'         => new CustomElement('Indicates that a person’s address is part of the Newsletter grouping (under an ADDR block).'),
1256                'INDI:ADDR:_LIST2 YES'         => new CustomElement('Indicates that a person’s address is part of the Family Association grouping (under an ADDR block).'),
1257                'INDI:EVEN:_OVER'              => new CustomElement('An event sentence override (under an EVEN block).'),
1258                'INDI:SOUR:_VERI'              => new CustomElement('Indicates that a source citation or place name has a checkmark in the Verified column.'),
1259                'INDI:_TAG'                    => new CustomElement('When under an INDI record, indicates that an individual has been given certain tag marks.'),
1260                'INDI:_TAG2'                   => new CustomElement('When under an INDI record, indicates that an individual has been given certain tag marks.'),
1261                'INDI:_TAG3'                   => new CustomElement('When under an INDI record, indicates that an individual has been given certain tag marks.'),
1262                'INDI:_TAG4'                   => new CustomElement('When under an INDI record, indicates that an individual has been given certain tag marks.'),
1263                'INDI:_TAG5'                   => new CustomElement('When under an INDI record, indicates that an individual has been given certain tag marks.'),
1264                'INDI:_TAG6'                   => new CustomElement('When under an INDI record, indicates that an individual has been given certain tag marks.'),
1265                'INDI:_TAG7'                   => new CustomElement('When under an INDI record, indicates that an individual has been given certain tag marks.'),
1266                'INDI:_TAG8'                   => new CustomElement('When under an INDI record, indicates that an individual has been given certain tag marks.'),
1267                'INDI:_TAG9'                   => new CustomElement('When under an INDI record, indicates that an individual has been given certain tag marks.'),
1268                'INDI:_TODO'                   => new CustomElement('Research task'),
1269                'INDI:_TODO:_CAT'              => new CustomElement('The Category of a To-Do item (under a _TODO record).'),
1270                'INDI:_TODO:_CDATE'            => new CustomElement('Closed Date of a To-Do item (under a _TODO record).'),
1271                'INDI:_TODO:_LOCL'             => new CustomElement('The Locality of a To-Do item (under a _TODO record).'),
1272                'INDI:_TODO:_RDATE'            => new CustomElement('Reminder date on to-do items. (Under a _TODO record.)'),
1273                'INDI:_UID'                    => new CustomElement('A Unique Identification Number given to each individual in a family file.'),
1274                'INDI:_URL'                    => new CustomElement('An Internet address (under an INDI record).'),
1275                'OBJE:_DATE'                   => new CustomElement('A date associated with a multimedia object, usually a picture or video (under an OBJE block).'),
1276                'OBJE:_PRIM'                   => new CustomElement('Means a multimedia object, usually a picture, is the Primary object (the one that is shown on a report) (under an OBJE block).'),
1277                'OBJE:_SCBK'                   => new CustomElement('Indicates that a Picture is tagged to be included in a scrapbook report (under an OBJE block).'),
1278                'OBJE:_SOUND'                  => new CustomElement('A sound file name that is attached to a picture (under an OBJE block).'),
1279                'OBJE:_TYPE'                   => new CustomElement('The type of a multimedia object: Photo, Sound, or Video (under an OBJE block).'),
1280                'SOUR:_ITALIC Y'               => new CustomElement('Indicates that a source title should be printed on a report in italics (under a SOUR record).'),
1281                'SOUR:_PAREN'                  => new CustomElement('Indicates that the Publication Facts of a source should be printed within parentheses on a report (under a SOUR record).'),
1282                'SOUR:_QUOTED Y'               => new CustomElement('Indicates that a source title should be printed within quotes on a report (under a SOUR record).'),
1283                'SOUR:_TAG NO'                 => new CustomElement('When used under a SOUR record, indicates to exclude the source citation detail on reports.'),
1284                'SOUR:_TAG2 NO'                => new CustomElement('When used under a SOUR record, indicates to exclude the source citation on reports.'),
1285                'SOUR:_TAG3 YES'               => new CustomElement('When used under a SOUR record, indicates to include the source citation detail text on reports.'),
1286                'SOUR:_TAG4 YES'               => new CustomElement('When used under a SOUR record, indicates to include the source citation detail notes on reports.'),
1287                '_PREF'                        => new CustomElement('Indicates a Preferred spouse, child or parents.'), // How is this used?
1288            ]);
1289
1290            // Personal Ancestral File extensions
1291            $this->register([
1292                'INDI:NAME:_ADPN' => new NamePersonal(I18N::translate('Adopted name')),
1293                'INDI:NAME:_AKA'  => new NamePersonal(I18N::translate('Also known as')),
1294                'INDI:NAME:_AKAN' => new NamePersonal(I18N::translate('Also known as')),
1295                'INDI:_EMAIL'     => new AddressEmail(I18N::translate('Email address')),
1296                'URL'             => new CustomElement(I18N::translate('URL')),
1297                '_HEB'            => new CustomElement(I18N::translate('Hebrew')),
1298                '_NAME'           => new CustomElement(I18N::translate('Mailing name')),
1299                '_SCBK'           => new CustomElement(I18N::translate('Scrapbook')),
1300                '_SSHOW'          => new CustomElement(I18N::translate('Slide show')),
1301                '_TYPE'           => new CustomElement(I18N::translate('Media type')),
1302                '_URL'            => new CustomElement(I18N::translate('URL')),
1303            ]);
1304
1305            // PhpGedView extensions
1306            $this->register([
1307                'FAM:CHAN:_PGVU'        => new WebtreesUser(I18N::translate('Author of last change')),
1308                'FAM:COMM'              => new CustomElement(I18N::translate('Comment')),
1309                'INDI:*:ASSO'           => new XrefAssociate(I18N::translate('Associate')),
1310                'INDI:*:ASSO:RELA'      => new RelationIsDescriptor(I18N::translate('Relationship')),
1311                'INDI:*:PLAC:_HEB'      => new NoteStructure(I18N::translate('Place in Hebrew')),
1312                'INDI:ADDR'             => new AddressLine(I18N::translate('Address'), []),
1313                'INDI:BIRT:DATE:TIME'   => new TimeValue(I18N::translate('Time')),
1314                'INDI:BURI:CEME'        => new CustomElement(I18N::translate('Cemetery')),
1315                'INDI:CHAN:_PGVU'       => new WebtreesUser(I18N::translate('Author of last change')),
1316                'INDI:COMM'             => new CustomElement(I18N::translate('Comment')),
1317                'INDI:DEAT:DATE:TIME'   => new TimeValue(I18N::translate('Time')),
1318                'INDI:EMAIL'            => new AddressEmail(I18N::translate('Email address')),
1319                'INDI:NAME:_HEB'        => new NamePersonal(I18N::translate('Name in Hebrew')),
1320                'INDI:_FNRL'            => new CustomEvent(I18N::translate('Funeral')),
1321                'INDI:_HOL'             => new CustomEvent(I18N::translate('Holocaust')),
1322                'INDI:_MILI'            => new CustomEvent(I18N::translate('Military')),
1323                'INDI:_PGV_OBJS'        => new XrefMedia(I18N::translate('Re-order media')),
1324                'NOTE:CHAN:_PGVU'       => new WebtreesUser(I18N::translate('Author of last change')),
1325                'OBJE:CHAN:_PGVU'       => new WebtreesUser(I18N::translate('Author of last change')),
1326                'OBJE:_PRIM'            => new CustomElement(I18N::translate('Highlighted image')),
1327                'OBJE:_THUM'            => new CustomElement(I18N::translate('Thumbnail image')),
1328                'REPO:CHAN:_PGVU'       => new WebtreesUser(I18N::translate('Author of last change')),
1329                'SOUR:CHAN:_PGVU'       => new WebtreesUser(I18N::translate('Author of last change')),
1330                'SOUR:SERV'             => new CustomElement(I18N::translate('Remote server')),
1331                'SOUR:URL'              => new AddressWebPage(I18N::translate('URL')),
1332                'SOUR:URL:TYPE'         => new CustomElement(I18N::translate('Type')), // e.g. "FamilySearch"
1333                'SOUR:URL:_BLOCK'       => new CustomElement(I18N::translate('Block')), // "e.g. "false"
1334                'SOUR:_DBID'            => new CustomElement(I18N::translate('Database name')),
1335                'SOUR:_DBID:_PASS'      => new CustomElement(I18N::translate('Database password')),
1336                'SOUR:_DBID:_PASS:RESN' => new RestrictionNotice(I18N::translate('Restriction')),
1337                'SOUR:_DBID:_USER'      => new CustomElement(I18N::translate('Database user account')),
1338            ]);
1339
1340            // Reunion extensions
1341            $this->register([
1342                'INDI:EMAL'  => new AddressEmail(I18N::translate('Email address')),
1343                'INDI:CITN'  => new CustomElement(I18N::translate('Citizenship')),
1344                'INDI:_LEGA' => new CustomElement(I18N::translate('Legatee')),
1345                'INDI:_MDCL' => new CustomElement(I18N::translate('Medical')),
1346                'INDI:_PURC' => new CustomElement('Land purchase'),
1347                'INDI:_SALE' => new CustomElement('Land sale'),
1348            ]);
1349
1350            // Roots Magic extensions
1351            $this->register([
1352                'INDI:_DNA'         => new CustomElement(I18N::translate('DNA markers')),
1353                'INDI:_WEBTAG'      => new CustomElement(I18N::translate('External link')),
1354                'INDI:_WEBTAG:NAME' => new CustomElement(I18N::translate('Text')),
1355                'INDI:_WEBTAG:URL'  => new AddressWebPage(I18N::translate('URL')),
1356                'SOUR:_BIBL'        => new CustomElement(I18N::translate('Bibliography')),
1357                'SOUR:_SUBQ'        => new CustomElement(I18N::translate('Abbreviation')),
1358            ]);
1359
1360            // webtrees extensions
1361            $this->register([
1362                'FAM:CHAN:_WT_USER'           => new WebtreesUser(I18N::translate('Author of last change')),
1363                'FAM:_ASSO'                   => new XrefAssociate(I18N::translate('Associate')),
1364                'FAM:_ASSO:RELA'              => new RelationIsDescriptor(I18N::translate('Relationship')),
1365                'FAM:*:_ASSO'                 => new XrefAssociate(I18N::translate('Associate')),
1366                'FAM:*:_ASSO:NOTE'            => new NoteStructure(I18N::translate('Note')),
1367                'FAM:*:_ASSO:RELA'            => new RelationIsDescriptor(I18N::translate('Relationship')),
1368                'FAM:*:_ASSO:SOUR'            => new XrefSource(I18N::translate('Source citation')),
1369                'FAM:*:_ASSO:SOUR:DATA'       => new SourceData(I18N::translate('Data')),
1370                'FAM:*:_ASSO:SOUR:DATA:DATE'  => new EntryRecordingDate(I18N::translate('Date of entry in original source')),
1371                'FAM:*:_ASSO:SOUR:DATA:TEXT'  => new TextFromSource(I18N::translate('Text')),
1372                'FAM:*:_ASSO:SOUR:EVEN'       => new EventTypeCitedFrom(I18N::translate('Event')),
1373                'FAM:*:_ASSO:SOUR:EVEN:ROLE'  => new RoleInEvent(I18N::translate('Role')),
1374                'FAM:*:_ASSO:SOUR:NOTE'       => new NoteStructure(I18N::translate('Note')),
1375                'FAM:*:_ASSO:SOUR:OBJE'       => new XrefMedia(I18N::translate('Media object')),
1376                'FAM:*:_ASSO:SOUR:PAGE'       => new WhereWithinSource(I18N::translate('Citation details')),
1377                'FAM:*:_ASSO:SOUR:QUAY'       => new CertaintyAssessment(I18N::translate('Quality of data')),
1378                'INDI:CHAN:_WT_USER'          => new WebtreesUser(I18N::translate('Author of last change')),
1379                'INDI:*:_ASSO'                => new XrefAssociate(I18N::translate('Associate')),
1380                'INDI:*:_ASSO:NOTE'           => new NoteStructure(I18N::translate('Note')),
1381                'INDI:*:_ASSO:RELA'           => new RelationIsDescriptor(I18N::translate('Relationship')),
1382                'INDI:*:_ASSO:SOUR'           => new XrefSource(I18N::translate('Source citation')),
1383                'INDI:*:_ASSO:SOUR:DATA'      => new SourceData(I18N::translate('Data')),
1384                'INDI:*:_ASSO:SOUR:DATA:DATE' => new EntryRecordingDate(I18N::translate('Date of entry in original source')),
1385                'INDI:*:_ASSO:SOUR:DATA:TEXT' => new TextFromSource(I18N::translate('Text')),
1386                'INDI:*:_ASSO:SOUR:EVEN'      => new EventTypeCitedFrom(I18N::translate('Event')),
1387                'INDI:*:_ASSO:SOUR:EVEN:ROLE' => new RoleInEvent(I18N::translate('Role')),
1388                'INDI:*:_ASSO:SOUR:NOTE'      => new NoteStructure(I18N::translate('Note')),
1389                'INDI:*:_ASSO:SOUR:OBJE'      => new XrefMedia(I18N::translate('Media object')),
1390                'INDI:*:_ASSO:SOUR:PAGE'      => new WhereWithinSource(I18N::translate('Citation details')),
1391                'INDI:*:_ASSO:SOUR:QUAY'      => new CertaintyAssessment(I18N::translate('Quality of data')),
1392                'NOTE:CHAN:_WT_USER'          => new WebtreesUser(I18N::translate('Author of last change')),
1393                'NOTE:RESN'                   => new RestrictionNotice(I18N::translate('Restriction')),
1394                'OBJE:CHAN:_WT_USER'          => new WebtreesUser(I18N::translate('Author of last change')),
1395                'OBJE:RESN'                   => new RestrictionNotice(I18N::translate('Restriction')),
1396                'REPO:CHAN:_WT_USER'          => new WebtreesUser(I18N::translate('Author of last change')),
1397                'REPO:RESN'                   => new RestrictionNotice(I18N::translate('Restriction')),
1398                'SOUR:CHAN:_WT_USER'          => new WebtreesUser(I18N::translate('Author of last change')),
1399                'SOUR:RESN'                   => new RestrictionNotice(I18N::translate('Restriction')),
1400                'SUBM:CHAN:_WT_USER'          => new WebtreesUser(I18N::translate('Author of last change')),
1401                'SUBM:RESN'                   => new RestrictionNotice(I18N::translate('Restriction')),
1402                '_LOC:CHAN:_WT_USER'          => new WebtreesUser(I18N::translate('Author of last change')),
1403                '_LOC:RESN'                   => new RestrictionNotice(I18N::translate('Restriction')),
1404            ]);
1405        }
1406
1407        return $this->elements;
1408    }
1409
1410    /**
1411     * Register more elements.
1412     *
1413     * @param array<string,ElementInterface> $elements
1414     */
1415    public function register(array $elements): void
1416    {
1417        $this->elements = array_merge($this->elements(), $elements);
1418    }
1419
1420    /**
1421     * @param string $tag
1422     *
1423     * @return ElementInterface|null
1424     */
1425    private function findElementByWildcard(string $tag): ?ElementInterface
1426    {
1427        foreach ($this->elements() as $tags => $element) {
1428            if (strpos($tags, '*') !== false) {
1429                $regex = '/^' . strtr($tags, ['*' => '[^:]+']) . '$/';
1430
1431                if (preg_match($regex, $tag)) {
1432                    return $element;
1433                }
1434            }
1435        }
1436
1437        return null;
1438    }
1439}
1440