Skip to content

feat: Android dialect - #20

Merged
odolbeau merged 1 commit into
mainfrom
feat/android-dialect
Oct 3, 2026
Merged

odolbeau merged 1 commit into
mainfrom
feat/android-dialect

Conversation

@odolbeau

@odolbeau odolbeau commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Fourth step of the vendor layer: the Android dialect, for the X-ANDROID-CUSTOM rows of the Android contacts app. Each row is a line of the Android contacts database: vnd.android.cursor.item/relation;Jane;14;;… means Jane, relation type 14 (spouse).

Reading

Row RFC JSContact
relation;Mother;8 RELATED;VALUE=text;TYPE=parent;X-ANDROID-TYPE=8:Mother relatedTo
relation;Ann;0;Colleague (custom) RELATED;TYPE=colleague;X-ANDROID-TYPE=0;X-ANDROID-LABEL=Colleague:Ann relatedTo
contact_event;2015-03-04;1 (anniversary) ANNIVERSARY:2015-03-04 anniversary of kind wedding
nickname;Pseudo;1 (default) NICKNAME:Pseudo nicknames
  • Relation types:
    • Assistant → agent.
    • Brother and sister → sibling.
    • Child → child.
    • Father, mother and parent → parent.
    • Friend → friend.
    • Relative → kin.
    • Spouse → spouse.
    • Domestic partner, manager, partner, referred by: no RFC type.
    • A custom relation whose label is a RFC type gets that type.
  • Android type and label are kept in X-ANDROID-TYPE and X-ANDROID-LABEL, in vCardParams, so that a mother does not come back as a parent.
  • Other events and nicknames have no JSContact equivalent: they stay verbatim.
  • Quoted-printable rows are read too. sabre splits them into columns, but not the other rows.

Writing

  • Relations go back to their Android type when they have one. Otherwise the type comes from the first RELATED type, or the row is a custom one named after it.
  • Wedding anniversaries become event rows.
  • Dates without a year that vCard 3.0 cannot hold are written as Android does: BDAY:--04-12, or an event row with --06-12. The JSPROP parsing that Apple already used moves to the shared helpers.

Several dialects

Reading can use every dialect at once. Writing should use those of the address book the vCard is for, because Apple and Android both write relations and dates, each in their own way. The README says so.

Tests

  • The Android exports, including the quoted-printable one, convert to typed properties.
  • Custom relations, and Cards written back.
  • Six real exports, read with every dialect and written with their own, survive a round trip.

X-PHONETIC-* stays verbatim: JSContact requires a phoneticSystem or phoneticScript for phonetics, and Android gives neither.

🤖 Generated with Claude Code

Reads and writes the X-ANDROID-CUSTOM rows of the Android contacts app:
relations, wedding anniversaries and default nicknames. The Android type
of a relation is kept in X-ANDROID-TYPE. Dates without a year are written
to vCard 3.0 as Android does, as Apple's already were: the parsing of
their JSPROP moves to the shared helpers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@odolbeau
odolbeau merged commit 47c80ba into main Oct 3, 2026
4 checks passed
@odolbeau
odolbeau deleted the feat/android-dialect branch October 3, 2026 12:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant