While looking at the Importer built-ins and add-ons, I wondered how Gramps selected which importer to use for a particular file? Is it by File extension?
The vCard built-in plug-in only supports v3.0 but every .vcf I have exported from a modern smart phone has been 2.1 version.
Tweaking the version inside the .vcf (from 2.1 to 3.0) imports part of the data as a workaround. But what if someone writes a real 2.1 importer add-on? Would the built-in importer keep it from working? And since there is now a 4.0 vCard, how could that importer be added?
GEDCOM is the same issue. The 5.5 and 5.5.1 and 7.0 all use the .ged extension.
The importer is selected by file extension. The version is read by the importer which will be in a format specified by the file format.
For example, in VCard format:
VERSION:3.0
and in Gedcom format:
0 HEAD
1 GEDC
2 VERS 7.0.1
I suggest enhancing the existing code rather than writing a new importer.
The existing Gedcom importer will try to import any version together with custom tags the best it can. For Gedcom 7.0 we may decide to use a new parser, but some common code will be needed to detect the version.
Perhaps another Importer Wizard shell could be a add-on Tool? Where users could select alternative Importer plug-ins and/or option?
For example, it is sometime more convenient to import just the .gramps file’s Tree data from a .gpkg archive without the media objects. Or somtimes just the Sources & Repositories… or just the Places.
If that’s posdible, the standard basic Import GUI could remain streamlined and intuitive. But an advanced option could be installed without waiting for a major revision.
This is a nice expansion. (Although it doesn’t solve the lack of Headers for Citation record creation and the Objects having SourceID instead of CitationID.)
Do you think that this Source field parsing code could be rolled into the built-in importer fairly easily?
After setting the delimiter configuration from comma to tab (in the CSVdialect option that Serge added to the parser), it becomes seamless to use the OS clipboard to copy from a spreadsheet and pipe the data into the Import Text gramplet.
To import a series of Sources would no longer require the tedious saving and then File Choosing of external files. You would just copy the cells (with Headers) in the spreadsheet, past into the Import Text gramplet and press the Import button.
Bulk entry is fairly familiar to spreadsheet users. Gramps would just need to distribute a spreadsheet workbook with the basic keywords headers laid out. And maybe have some example data.
Could someone volunteer to roll the updated vCard import/export plug-ins into the appropriate Gramps branch?
The built-in vcard import/export gramplets were forked and enhanced to support version 1, 2, 3, and 4 – because most smart phones import/export version 2.1 and the built-in importer only recognized v3 .vcf files.
This enhancement did not add support for any new chunks. It just expanded the version coverage for more compatibility. The updates were published in March as addons to facilitate testing with the new Sniffer functionality. But I never noticed how to run those tests. (I think that testing opportunity just slipped away.)
I agree that it out to be rolled into the core… but I am very uncomfortable touching core. I can experiment with validating the plugin registration in the addon system. But not the core.
Replaces the built-in Gramps vCard importer and exporter with dialect-aware versions that handle vCard versions 1.0, 2.1, 3.0, and 4.0. Unhandled vCard properties are preserved (not silently dropped) as Person attributes of type vCard <version> source. A Variant Call Format (VCF) DNA file is detected on the first line and rejected with a clear alert rather than a confusing parse error. ORG vCards without Names are imported as Surnames.
The exporter adds a version selector to the export wizard (default: 3.0).
See vCard on wikipedia
Installation
Copy the four files into a single addon directory inside your Gramps user data folder, e.g.: ~/.gramps/gramps60/plugins/vcardenhanced/
Files:
vcardenhanced.gpr.py
importvcard_enh.py
exportvcard_enh.py
README.md
Restart Gramps.
The addon once attempted to automatically hide the built-in vCard plugins on startup so that the addon could supersede. (see Hurdle 4 below). The automatic hide did not work so you have to do this manually:
Open Help → Plugin Manager Enhanced
Search vCard (the built-in import) and vCard (the built-in export) and set them to Hidden
The addon versions are named vCard (Enhanced — v1/2.1/3.0/4.0)
Fork/Hide Workaround — Hurdles Encountered
This addon is a structured experiment in the GEPS 048 “Workaround A:Fork-and-Hide” approach. The following problems were discovered during development and are documented here as input to the full GEPS 048 implementation.
Hurdle 1 — Duplicate plugin IDs cause silent failures
Problem: The built-in vCard plugins use the IDs im_vcard and ex_vcard. Reusing these IDs in an addon causes Gramps to raise a duplicate-plugin registration error. This error is not clearly reported to the user — depending on the Gramps version, the startup log either silently drops one of the registrations or produces a traceback that doesn’t identify which plugin caused it.
Workaround: This addon uses distinct IDs: im_vcard_f (‘f’ for “fork”) and ex_vcard_f. This means both the built-in and the enhanced versions are registered simultaneously, creating a duplicate-entry problem in the import/export dialog (see Hurdle 4).
GEPS 048 implication: The framework needs a first-class “supersedes” or “replaces” registration field so addon authors can explicitly declare that their plugin replaces a built-in, and the framework can handle deduplication automatically.
Hurdle 2 — Built-in .gpr.py is amalgamated; no standalone file to copy
Problem: The built-in importer and exporter plugins are registered in a shared gramps/plugins/lib/...gpr.py file (or similar amalgamated file) alongside many other plugins. There is no standalone vcard.gpr.py to simply copy and modify. An addon author who doesn’t know where to look has no obvious path to find the registration parameters needed to construct a fork.
Additional problem: If fname= in a .gpr.py points to a file that doesn’t exist, Gramps silently skips the plugin at startup with no user-visible error and no log message at the default log level. This makes typos in fname= very hard to diagnose.
Workaround: The addon’s .gpr.py was written from scratch, using the built-in plugin’s parameters as reference. The fname= values were verified by confirming that both .py files exist in the addon directory before testing.
GEPS 048 implication: The framework should emit a warning (at least
at DEBUG level) when a registered fname= cannot be found. Ideally,
the Plugin Manager UI would show “file missing” next to the plugin name.
Hurdle 3 — Import paths differ between core plugins and addons
Problem: Core Gramps plugins import from relative paths or from gramps.plugins.lib directly. Addon plugins live in the user data directory, outside the Gramps package tree, and must use fully qualified gramps.* import paths. Copying a core plugin file and adjusting only the registration is not sufficient — imports also need updating.
Additionally, the built-in importvcard.py uses OpenFileOrStdin without specifying encoding=, which works for core because it falls back to the system default. In the enhanced version, explicit encoding="utf-8", errors="replace" is necessary to handle multi-version input gracefully.
Workaround: This addon is self-contained — no shared modules from core are monkey-patched or subclassed. All imports use fully qualified Gramps package paths.
GEPS 048 implication: The fork-and-hide workaround guide (in GEPS 048’s Workaround A section) should include a checklist of import path differences as a known friction point.
Hurdle 4 — Hiding the built-in has no stable API
Problem: To eliminate the duplicate-entry problem in the import/export dialog (both built-in and enhanced showing up for .vcf files), the built-in plugins must be hidden. The .gpr.py includes a best-effort automatic hide using PluginRegister. However:
The API for reading and writing the hidden-plugin set (get_hidden_plugin_ids / save_hidden_plugin_ids) is not part of the documented Gramps plugin API and may not exist in all versions.
The hidden-plugin list is managed by Plugin Manager Enhanced, which stores it in a user config file. The attribute names on PluginRegister differ between Gramps versions.
If the automatic hide fails, it fails silently — there is no feedback to the user that manual hiding is required.
Workaround: The _auto_hide_upstream() function in .gpr.py tries two known attribute names (get_hidden_plugin_ids and _hidden) and swallows all exceptions. The README instructs users to hide manually if the automatic hide does not work.
GEPS 048 implication: A stable, version-independent API for hiding a plugin by ID is essential for any fork-and-hide approach to be reliable. This should be part of the core plugin registration system, not a side-effect dependency on Plugin Manager Enhanced.
Hurdle 5 — No “toggle active fork” UI in core
Problem: Once both the built-in and the enhanced plugin are registered, and one is hidden, there is no built-in Gramps UI for the user to toggle which one is active. This requires either Plugin Manager Enhanced (a separate addon) or manual config-file editing.
Workaround: The README documents the manual procedure. A future version of the exporter option box could include a “Restore built-in” button that calls the toggle pattern described in GEPS 048.
A vCard (.vcf) file stores contact information like a digital business card. It uses standardized text tags (or fields) to define personal and professional details.
The standard fields used in a .vcf file include:
Required / Core Fields
BEGIN:VCARD / END:VCARD: Every file must start and end with these markers. VERSION: Specifies the vCard version (e.g., 2.1, 3.0, or 4.0). N: Structured name (separated by semicolons: Last; First; Middle; Prefix; Suffix). FN: Formatted Name (the display name, complete with prefixes/suffixes).
ORG: Organization or Company name. TITLE: Job title or role within the company. ROLE: The specific function or role of the person. LOGO: URL or embedded image of the company logo.
Personal & Additional Data
BDAY: Birthday (formatted as YYYY-MM-DD). URL: Websites or social media links. PHOTO: Profile photo (can be a URL or a base64-encoded image). NOTE: Free-form text for any extra details. NICKNAME: Alternative names or aliases. IMPP: Instant messaging and presence protocol addresses (e.g., SIP, XMPP). RELATED: Other people related to this contact (e.g., TYPE=CO-WORKER or TYPE=SPOUSE). KEY: Public encryption keys.
Additional fields
Geographical & Time Fields
GEO: Latitude and longitude coordinates (e.g., GEO:geo:37.386013,-122.082932). TZ: The contact’s time zone (expressed as a text string or a UTC offset).
Metadata & System Fields
UID: A globally Unique Identifier for the specific contact. REV: Revision date and time indicating when the contact card was last updated. PRODID: The identifier of the software application that generated the vCard file. KIND: Defines the type of entity the vCard represents (individual, group, org, or location). CLIENTPIDMAP: Used in vCard 4.0 synchronization to map local IDs to global IDs.
BIRTHPLACE: The geographical place or city where the individual was born. DEATHPLACE: The location where the individual passed away. DEATHDATE: The exact date of death. ANNIVERSARY: The wedding or significant anniversary date. GENDER: Gender identity (M for male, F for female, O for other, N for none, U for unknown). X-GENDER: Gender identity (M for male, F for female, N/A, None, Unspecified). GRAMGENDER: Grammatical gender settings for formatting text about the user. PRONOUNS: Designated personal pronouns (e.g., he/him, they/them). LANGUAGE: The contact’s preferred spoken/written language.
Media & Security Extensions
AUDIO: An embedded audio file or URI pointing to the correct pronunciation of the contact’s name. FBURL: Free/Busy URL, pointing to a web page showing the contact’s calendar availability. CALADRURI: Calendar address URI used to send meeting invitations to the contact. CALURI: A direct link to the contact’s primary calendar. SOCIALPROFILE: Officially introduced to formalize web and social media handle URIs.
Custom Fields (X- Prefix)
Applications and phone systems create non-standard, custom fields by prefixing them with X-. These are widely parsed across modern systems: X-PHONETIC-FIRST-NAME / X-PHONETIC-LAST-NAME: Phonetic spellings for proper text-to-speech rendering. X-SOCIALPROFILE: The legacy/vendor format for mapping Twitter, Facebook, or LinkedIn links. X-ABRELATEDNAMES: Used heavily by Apple and Android to list custom relationships.
RELATED (a future enhancement)
In a .vcf (vCard) file, the RELATED property is used to specify a relationship between the contact and another entity.
The formatting rules and valid entries depend on whether you are defining the property value itself or the relationship TYPE parameter.
1. Valid Property Values
The value of the RELATED property is text by default, but it can also be a URI pointing directly to another digital identity or vCard.
Text (Default): The actual name of the related person or entity.
Example:RELATED:Jane Doe
URI: A direct link, such as a uuid:, a mailto: email address, or a web link. You must declare VALUE=uri.
2. Valid TYPE Parameters (Relationship Categories)
To specify how the contact is related to the person or entity, the official vCard 4.0 specification (RFC 6350) and IANA registry allow a standardized list of lowercase values for the TYPE= parameter:
Family & Personal Relationships
child – Offspring
parent – Mother, father, or legal guardian
sibling – Brother or sister
spouse – Husband, wife, or legal partner
kin – General relative or family member
sweetheart / crush / date – Romantic interests
Professional & Organizational Relationships
colleague – Someone in the same field or profession
coworker – Someone working at the same company
agent – Someone who can act on behalf of the contact
manager – A supervisor or boss
Social & Living Arrangements
friend – A personal friend
acquaintance – A casual social contact
neighbor – A person living nearby
coresident – A roommate or housemate
Other Specialized Standard Types
contact – A general related connection
emergency – A primary contact for health or safety emergencies
me – Points to another vCard or online profile belonging to the exact same person
Code Examples in Action
Example 1: Plain text spouse relationship
RELATED;TYPE=spouse:John Doe
Example 2: Multiple comma-separated relationship types linking to an email
Rarely encountered; tab-folding; QUOTED-PRINTABLE common
2.1
Versit 1996
Widely supported; used by Outlook, older phones; QP encoding
3.0
RFC 2426 (1998)
Gramps default; space-folding; UTF-8
4.0
RFC 6350 (2011)
Modern standard; GENDER, ANNIVERSARY, CLIENTPIDMAP
Properties not handled by the importer are stored as a vCard <n> source Person attribute (where <n> is the detected version), so data is preserved for manual review or future processing.
Variant Call Format (DNA) Detection
.vcf is shared between vCard (contact data) and Variant Call Format (genomic/DNA data). VCF DNA files begin with ##fileformat=VCFv. This addon reads the first 32 bytes of any .vcf file before attempting to parse it as a vCard. If the DNA magic bytes are detected, import is aborted and an alert is shown.
Credits
Original vCard import/export: Martin Hawlisch, Donald N. Allingham, Brian G. Matherly, Jakim Friant, Michiel D. Nauta (Gramps project)
Export option box pattern: Kari Kujansuu (isotammiexportxml)
Enhanced multi-version fork: Claude (Anthropic, claude-sonnet-4-6), GEPS 048 experiment, 2026-03-21
Human author / tester: Brian McCullough (emyoulation), Gramps project