fix: update gender handling to use speakToAs structure and adjust localization keys
This commit is contained in:
@@ -226,7 +226,7 @@ describe("parseVCard", () => {
|
||||
expect(result).toHaveLength(1);
|
||||
const card = result[0];
|
||||
|
||||
expect(card.gender).toEqual({ sex: "F", identity: "Female" });
|
||||
expect(card.speakToAs).toEqual({ grammaticalGender: "feminine", pronouns: { p0: { pronouns: "Female" } } });
|
||||
expect(card.media?.m0).toEqual({
|
||||
kind: "logo",
|
||||
uri: "https://example.com/logo.png",
|
||||
@@ -331,7 +331,7 @@ describe("generateVCard", () => {
|
||||
components: [{ kind: "given", value: "Jane" }],
|
||||
isOrdered: true,
|
||||
},
|
||||
gender: { sex: "F", identity: "Female" },
|
||||
speakToAs: { grammaticalGender: "feminine", pronouns: { p0: { pronouns: "Female" } } },
|
||||
media: {
|
||||
m0: { kind: "logo", uri: "https://example.com/logo.png", mediaType: "image/png" },
|
||||
m1: { kind: "sound", uri: "https://example.com/sound.ogg", mediaType: "audio/ogg" },
|
||||
|
||||
+4
-1
@@ -183,7 +183,10 @@ export interface ContactCard {
|
||||
relatedTo?: Record<string, ContactRelation>;
|
||||
keywords?: Record<string, boolean>;
|
||||
members?: Record<string, boolean>;
|
||||
gender?: { sex?: string; identity?: string };
|
||||
speakToAs?: {
|
||||
grammaticalGender?: string;
|
||||
pronouns?: Record<string, { pronouns: string; pref?: number; contexts?: Record<string, boolean> }>;
|
||||
};
|
||||
calendarUri?: string;
|
||||
schedulingUri?: string;
|
||||
freeBusyUri?: string;
|
||||
|
||||
+44
-7
@@ -1,5 +1,29 @@
|
||||
import type { ContactCard, NameComponent, ContactMedia, ContactOnlineService } from "@/lib/jmap/types";
|
||||
|
||||
const VCARD_SEX_TO_GENDER: Record<string, string> = {
|
||||
M: "masculine",
|
||||
F: "feminine",
|
||||
O: "other",
|
||||
N: "none",
|
||||
U: "unknown",
|
||||
};
|
||||
|
||||
const GENDER_TO_VCARD_SEX: Record<string, string> = {
|
||||
masculine: "M",
|
||||
feminine: "F",
|
||||
other: "O",
|
||||
none: "N",
|
||||
unknown: "U",
|
||||
};
|
||||
|
||||
function vcardSexToGrammaticalGender(sex: string): string {
|
||||
return VCARD_SEX_TO_GENDER[sex.toUpperCase()] || sex.toLowerCase();
|
||||
}
|
||||
|
||||
function grammaticalGenderToVcardSex(gender: string): string {
|
||||
return GENDER_TO_VCARD_SEX[gender.toLowerCase()] || "";
|
||||
}
|
||||
|
||||
function unfoldLines(vcf: string): string {
|
||||
return vcf.replace(/\r\n[ \t]/g, "").replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
||||
}
|
||||
@@ -390,9 +414,17 @@ function buildContact(raw: Record<string, string[]>): ContactCard | null {
|
||||
|
||||
case "GENDER": {
|
||||
const gParts = val.split(";");
|
||||
card.gender = {};
|
||||
if (gParts[0]) card.gender.sex = gParts[0];
|
||||
if (gParts[1]) card.gender.identity = gParts[1];
|
||||
const sexCode = gParts[0]?.toUpperCase();
|
||||
const identityText = gParts[1];
|
||||
if (sexCode || identityText) {
|
||||
card.speakToAs = {};
|
||||
if (sexCode) {
|
||||
card.speakToAs.grammaticalGender = vcardSexToGrammaticalGender(sexCode);
|
||||
}
|
||||
if (identityText) {
|
||||
card.speakToAs.pronouns = { p0: { pronouns: identityText } };
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -684,10 +716,15 @@ function generateSingleVCard(contact: ContactCard): string {
|
||||
}
|
||||
}
|
||||
|
||||
if (contact.gender) {
|
||||
const sex = contact.gender.sex || "";
|
||||
const identity = contact.gender.identity || "";
|
||||
lines.push(`GENDER:${sex}${identity ? `;${identity}` : ""}`);
|
||||
if (contact.speakToAs) {
|
||||
const sex = contact.speakToAs.grammaticalGender
|
||||
? grammaticalGenderToVcardSex(contact.speakToAs.grammaticalGender)
|
||||
: "";
|
||||
const pronouns = contact.speakToAs.pronouns;
|
||||
const identity = pronouns ? Object.values(pronouns)[0]?.pronouns || "" : "";
|
||||
if (sex || identity) {
|
||||
lines.push(`GENDER:${sex}${identity ? `;${identity}` : ""}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (contact.calendarUri) {
|
||||
|
||||
Reference in New Issue
Block a user