diff --git a/components/contacts/__tests__/contact-detail.test.tsx b/components/contacts/__tests__/contact-detail.test.tsx index a06d4e1c3..d41b1ac3f 100644 --- a/components/contacts/__tests__/contact-detail.test.tsx +++ b/components/contacts/__tests__/contact-detail.test.tsx @@ -68,7 +68,7 @@ describe('ContactDetail', () => { render(); // The test translator returns the key, so a translated label shows up as its key. expect(screen.getByText('form.context_work')).toBeInTheDocument(); - expect(screen.getByText('form.context_private · form.phone_cell, x-sat')).toBeInTheDocument(); + expect(screen.getByText('ux_pim_contact.context_private · form.phone_cell, x-sat')).toBeInTheDocument(); // Custom vCard types are shown as stored. expect(screen.getByText('form.context_work, x-hq')).toBeInTheDocument(); }); diff --git a/components/contacts/__tests__/contacts-ux-pim.test.tsx b/components/contacts/__tests__/contacts-ux-pim.test.tsx new file mode 100644 index 000000000..9ff7af07b --- /dev/null +++ b/components/contacts/__tests__/contacts-ux-pim.test.tsx @@ -0,0 +1,45 @@ +import { render, screen } from '@testing-library/react'; +import { describe, expect, it, vi } from 'vitest'; +import type { ContactCard } from '@/lib/jmap/types'; + +// Keys with their namespace, so a label read from ux_pim_contact can be told +// from the old one in contacts.form. +vi.mock('next-intl', () => ({ + useTranslations: (ns?: string) => (key: string) => (ns ? `${ns}.${key}` : key), + useLocale: () => 'en', + useFormatter: () => ({ dateTime: String, relativeTime: String, number: String }), +})); +vi.mock('@/stores/account-store', () => { + const state = { accounts: [], activeAccountId: null }; + const hook = (sel?: (s: typeof state) => unknown) => (typeof sel === 'function' ? sel(state) : state); + hook.getState = () => state; + return { useAccountStore: hook }; +}); +vi.mock('@/components/contacts/contact-activity', () => ({ ContactActivity: () => null })); + +import { ContactForm } from '../contact-form'; +import { ContactDetail } from '../contact-detail'; + +const anna: ContactCard = { + id: 'c1', + addressBookIds: {}, + name: { components: [{ kind: 'given', value: 'Anna' }, { kind: 'surname', value: 'Example' }], isOrdered: true }, + emails: { e0: { address: 'anna@example.net', contexts: { private: true } } }, + phones: { p0: { number: '+49 30 1', features: { voice: true }, contexts: { private: true } } }, +}; + +describe('pim-19: standard words read as people say them', () => { + it('offers "Phone" and "Home" in the editor, storing voice and private as before', () => { + render(); + const phoneType = screen.getByDisplayValue('ux_pim_contact.phone_voice') as HTMLSelectElement; + expect(phoneType.value).toBe('voice'); + expect(screen.getAllByDisplayValue('ux_pim_contact.context_private').map(s => (s as HTMLSelectElement).value)).toEqual(['private', 'private']); + expect(screen.queryByText('contacts.form.phone_voice')).toBeNull(); + expect(screen.queryByText('contacts.form.context_private')).toBeNull(); + }); + + it('labels a voice phone "Phone" and a private one "Home" on the contact page', () => { + render(); + expect(screen.getByText('ux_pim_contact.context_private · ux_pim_contact.phone_voice')).toBeInTheDocument(); + }); +}); diff --git a/components/contacts/contact-detail.tsx b/components/contacts/contact-detail.tsx index 66a3969e2..addc2d069 100644 --- a/components/contacts/contact-detail.tsx +++ b/components/contacts/contact-detail.tsx @@ -40,14 +40,15 @@ interface ContactDetailProps { } // Contexts and phone features the contact form offers, shown with the same -// labels here. Anything else (custom vCard types) is shown as stored. +// labels here. Anything else (custom vCard types) is shown as stored. The +// standard's "private" reads "Home" and "voice" reads "Phone" (#pim-19). const CONTEXT_LABEL_KEYS: Record = { work: "form.context_work", - private: "form.context_private", + private: "ux_pim_contact.context_private", }; const PHONE_FEATURE_LABEL_KEYS: Record = { - voice: "form.phone_voice", + voice: "ux_pim_contact.phone_voice", cell: "form.phone_cell", mobile: "form.phone_cell", fax: "form.phone_fax", @@ -78,12 +79,14 @@ function getCompletedYears(dateInput: AnniversaryDate): number | null { export function ContactDetail({ contact, onEdit, onDelete, onAddToGroup, onDuplicate, onMoveTo, onCompose, onPrint, isMobile, className, readOnly = false }: ContactDetailProps) { const t = useTranslations("contacts"); + const tRoot = useTranslations(); const tCommon = useTranslations("common"); const locale = useLocale(); // The ⋮ shows the contact's menu, the one right-click shows in the list (R6). const moreMenu = useContextMenu(); - const contextLabel = (key: string) => (CONTEXT_LABEL_KEYS[key] ? t(CONTEXT_LABEL_KEYS[key]) : key); - const featureLabel = (key: string) => (PHONE_FEATURE_LABEL_KEYS[key] ? t(PHONE_FEATURE_LABEL_KEYS[key]) : key); + const label = (labelKey: string) => (labelKey.startsWith("ux_pim_contact.") ? tRoot(labelKey) : t(labelKey)); + const contextLabel = (key: string) => (CONTEXT_LABEL_KEYS[key] ? label(CONTEXT_LABEL_KEYS[key]) : key); + const featureLabel = (key: string) => (PHONE_FEATURE_LABEL_KEYS[key] ? label(PHONE_FEATURE_LABEL_KEYS[key]) : key); const cryptoKeys = contact?.cryptoKeys ? Object.values(contact.cryptoKeys) : []; const hasCryptoKeysSlotOffers = usePluginSlotOffers('contact-cryptokeys').length > 0; diff --git a/components/contacts/contact-form.tsx b/components/contacts/contact-form.tsx index fac3205b0..4e43f313c 100644 --- a/components/contacts/contact-form.tsx +++ b/components/contacts/contact-form.tsx @@ -220,6 +220,7 @@ function Select({ value, onChange, children, className, id, "aria-label": ariaLa export function ContactForm({ contact, addressBooks, allKeywords, defaultAddressBookId, prefill, onSave, onCancel, loadCurrentMedia, onDirtyChange }: ContactFormProps) { const t = useTranslations("contacts.form"); + const tx = useTranslations("ux_pim_contact"); const isEditing = !!contact; // The header's close goes to its start when the window's own close is at its end. const [header, setHeader] = useState(null); @@ -916,7 +917,7 @@ export function ContactForm({ contact, addressBooks, allKeywords, defaultAddress > - + {emails.length > 1 && ( setEmails(emails.filter((_, j) => j !== i))} className="shrink-0"> @@ -966,7 +967,7 @@ export function ContactForm({ contact, addressBooks, allKeywords, defaultAddress aria-label={t("phone_type")} > - + @@ -984,7 +985,7 @@ export function ContactForm({ contact, addressBooks, allKeywords, defaultAddress > - + setPhones(phones.filter((_, j) => j !== i))} className="shrink-0"> @@ -1046,7 +1047,7 @@ export function ContactForm({ contact, addressBooks, allKeywords, defaultAddress > - + diff --git a/locales/ar/common.json b/locales/ar/common.json index f8800991e..adca5d49f 100644 --- a/locales/ar/common.json +++ b/locales/ar/common.json @@ -4483,6 +4483,10 @@ "menu": "فتح قائمة جهة الاتصال" } }, + "ux_pim_contact": { + "context_private": "المنزل", + "phone_voice": "هاتف" + }, "uxs_wording": { "more_options": "خيارات إضافية", "use_in_other_apps": "الاستخدام في تطبيقات أخرى", diff --git a/locales/ca/common.json b/locales/ca/common.json index 62c75d062..7968722c2 100644 --- a/locales/ca/common.json +++ b/locales/ca/common.json @@ -4483,6 +4483,10 @@ "menu": "Obre el menú del contacte" } }, + "ux_pim_contact": { + "context_private": "Casa", + "phone_voice": "Telèfon" + }, "uxs_wording": { "more_options": "Més opcions", "use_in_other_apps": "Fes-ho servir en altres aplicacions", diff --git a/locales/cs/common.json b/locales/cs/common.json index cd765731a..bfb5e43f7 100644 --- a/locales/cs/common.json +++ b/locales/cs/common.json @@ -4483,6 +4483,10 @@ "open_categories": "Otevřít kategorie", "row_actions": "Akce pro {name}" }, + "ux_pim_contact": { + "context_private": "Domácí", + "phone_voice": "Telefon" + }, "uxs_wording": { "more_options": "Další možnosti", "use_in_other_apps": "Použít v jiných aplikacích", diff --git a/locales/da/common.json b/locales/da/common.json index 68c3ace47..bbc9d59c5 100644 --- a/locales/da/common.json +++ b/locales/da/common.json @@ -4483,6 +4483,10 @@ "open_categories": "Åbn kategorier", "row_actions": "Handlinger for {name}" }, + "ux_pim_contact": { + "context_private": "Hjem", + "phone_voice": "Telefon" + }, "uxs_wording": { "more_options": "Flere indstillinger", "use_in_other_apps": "Brug i andre apps", diff --git a/locales/de/common.json b/locales/de/common.json index 6acbe0328..7f16b73bd 100644 --- a/locales/de/common.json +++ b/locales/de/common.json @@ -4483,6 +4483,10 @@ "open_categories": "Kategorien öffnen", "row_actions": "Aktionen für {name}" }, + "ux_pim_contact": { + "context_private": "Privat", + "phone_voice": "Telefon" + }, "uxs_wording": { "more_options": "Weitere Optionen", "use_in_other_apps": "In anderen Apps nutzen", diff --git a/locales/en/common.json b/locales/en/common.json index 9fe28226c..d7a1ec5c8 100644 --- a/locales/en/common.json +++ b/locales/en/common.json @@ -4483,6 +4483,10 @@ "menu": "Open the contact's menu" } }, + "ux_pim_contact": { + "context_private": "Home", + "phone_voice": "Phone" + }, "uxs_wording": { "more_options": "More options", "use_in_other_apps": "Use in other apps", diff --git a/locales/es/common.json b/locales/es/common.json index e1f5a5ebe..7df639718 100644 --- a/locales/es/common.json +++ b/locales/es/common.json @@ -4483,6 +4483,10 @@ "open_categories": "Abrir categorías", "row_actions": "Acciones para {name}" }, + "ux_pim_contact": { + "context_private": "Casa", + "phone_voice": "Teléfono" + }, "uxs_wording": { "more_options": "Más opciones", "use_in_other_apps": "Usar en otras aplicaciones", diff --git a/locales/et/common.json b/locales/et/common.json index f77713d19..74e57c678 100644 --- a/locales/et/common.json +++ b/locales/et/common.json @@ -4483,6 +4483,10 @@ "menu": "Ava kontakti menüü" } }, + "ux_pim_contact": { + "context_private": "Kodu", + "phone_voice": "Telefon" + }, "uxs_wording": { "more_options": "Rohkem valikuid", "use_in_other_apps": "Kasuta teistes rakendustes", diff --git a/locales/fa/common.json b/locales/fa/common.json index 36f5febbd..7a7ad3f15 100644 --- a/locales/fa/common.json +++ b/locales/fa/common.json @@ -4483,6 +4483,10 @@ "menu": "باز کردن منوی مخاطب" } }, + "ux_pim_contact": { + "context_private": "منزل", + "phone_voice": "تلفن" + }, "uxs_wording": { "more_options": "گزینه‌های بیشتر", "use_in_other_apps": "استفاده در برنامه‌های دیگر", diff --git a/locales/fr/common.json b/locales/fr/common.json index 96ad6b352..78bb7548f 100644 --- a/locales/fr/common.json +++ b/locales/fr/common.json @@ -4483,6 +4483,10 @@ "open_categories": "Ouvrir les catégories", "row_actions": "Actions pour {name}" }, + "ux_pim_contact": { + "context_private": "Domicile", + "phone_voice": "Téléphone" + }, "uxs_wording": { "more_options": "Plus d'options", "use_in_other_apps": "Utiliser dans d'autres applications", diff --git a/locales/he/common.json b/locales/he/common.json index 8190e738d..9a35bf159 100644 --- a/locales/he/common.json +++ b/locales/he/common.json @@ -4376,6 +4376,10 @@ "menu": "פתח את התפריט של איש הקשר" } }, + "ux_pim_contact": { + "context_private": "בית", + "phone_voice": "טלפון" + }, "uxs_wording": { "more_options": "אפשרויות נוספות", "use_in_other_apps": "שימוש באפליקציות אחרות", diff --git a/locales/hu/common.json b/locales/hu/common.json index 9d7abd079..8fcd45664 100644 --- a/locales/hu/common.json +++ b/locales/hu/common.json @@ -4483,6 +4483,10 @@ "menu": "Névjegy menüjének megnyitása" } }, + "ux_pim_contact": { + "context_private": "Otthoni", + "phone_voice": "Telefon" + }, "uxs_wording": { "more_options": "További beállítások", "use_in_other_apps": "Használat más alkalmazásokban", diff --git a/locales/it/common.json b/locales/it/common.json index c230dd475..ba65e86bc 100644 --- a/locales/it/common.json +++ b/locales/it/common.json @@ -4483,6 +4483,10 @@ "open_categories": "Apri categorie", "row_actions": "Azioni per {name}" }, + "ux_pim_contact": { + "context_private": "Casa", + "phone_voice": "Telefono" + }, "uxs_wording": { "more_options": "Altre opzioni", "use_in_other_apps": "Usa in altre app", diff --git a/locales/ja/common.json b/locales/ja/common.json index 859b086d6..7413e6e99 100644 --- a/locales/ja/common.json +++ b/locales/ja/common.json @@ -4483,6 +4483,10 @@ "open_categories": "カテゴリを開く", "row_actions": "{name} の操作" }, + "ux_pim_contact": { + "context_private": "自宅", + "phone_voice": "電話" + }, "uxs_wording": { "more_options": "その他のオプション", "use_in_other_apps": "ほかのアプリで使う", diff --git a/locales/ko/common.json b/locales/ko/common.json index b26122750..038a04a55 100644 --- a/locales/ko/common.json +++ b/locales/ko/common.json @@ -4483,6 +4483,10 @@ "open_categories": "카테고리 열기", "row_actions": "{name} 작업" }, + "ux_pim_contact": { + "context_private": "집", + "phone_voice": "전화" + }, "uxs_wording": { "more_options": "옵션 더 보기", "use_in_other_apps": "다른 앱에서 사용", diff --git a/locales/lv/common.json b/locales/lv/common.json index 6474a45eb..df153778d 100644 --- a/locales/lv/common.json +++ b/locales/lv/common.json @@ -4483,6 +4483,10 @@ "open_categories": "Atvērt kategorijas", "row_actions": "Darbības: {name}" }, + "ux_pim_contact": { + "context_private": "Mājas", + "phone_voice": "Tālrunis" + }, "uxs_wording": { "more_options": "Vairāk iespēju", "use_in_other_apps": "Lietot citās lietotnēs", diff --git a/locales/mn/common.json b/locales/mn/common.json index 49f47d310..bec3f4929 100644 --- a/locales/mn/common.json +++ b/locales/mn/common.json @@ -4483,6 +4483,10 @@ "menu": "Харилцагчийн цэсийг нээх" } }, + "ux_pim_contact": { + "context_private": "Гэр", + "phone_voice": "Утас" + }, "uxs_wording": { "more_options": "Бусад сонголт", "use_in_other_apps": "Бусад апп-д ашиглах", diff --git a/locales/nb/common.json b/locales/nb/common.json index 6c54c14c6..07ec4cd7b 100644 --- a/locales/nb/common.json +++ b/locales/nb/common.json @@ -4483,6 +4483,10 @@ "menu": "Åpne kontaktens meny" } }, + "ux_pim_contact": { + "context_private": "Hjem", + "phone_voice": "Telefon" + }, "uxs_wording": { "more_options": "Flere valg", "use_in_other_apps": "Bruk i andre apper", diff --git a/locales/nl/common.json b/locales/nl/common.json index caa6592d6..91dcf6f5c 100644 --- a/locales/nl/common.json +++ b/locales/nl/common.json @@ -4483,6 +4483,10 @@ "open_categories": "Categorieën openen", "row_actions": "Acties voor {name}" }, + "ux_pim_contact": { + "context_private": "Thuis", + "phone_voice": "Telefoon" + }, "uxs_wording": { "more_options": "Meer opties", "use_in_other_apps": "Gebruiken in andere apps", diff --git a/locales/pl/common.json b/locales/pl/common.json index a42440af6..2d685206b 100644 --- a/locales/pl/common.json +++ b/locales/pl/common.json @@ -4483,6 +4483,10 @@ "open_categories": "Otwórz kategorie", "row_actions": "Działania dla {name}" }, + "ux_pim_contact": { + "context_private": "Dom", + "phone_voice": "Telefon" + }, "uxs_wording": { "more_options": "Więcej opcji", "use_in_other_apps": "Użyj w innych aplikacjach", diff --git a/locales/pt/common.json b/locales/pt/common.json index bd73fa852..ed616d8a5 100644 --- a/locales/pt/common.json +++ b/locales/pt/common.json @@ -4483,6 +4483,10 @@ "open_categories": "Abrir categorias", "row_actions": "Ações para {name}" }, + "ux_pim_contact": { + "context_private": "Casa", + "phone_voice": "Telefone" + }, "uxs_wording": { "more_options": "Mais opções", "use_in_other_apps": "Usar noutras aplicações", diff --git a/locales/ro/common.json b/locales/ro/common.json index ad9938c1a..0ba1f75c8 100644 --- a/locales/ro/common.json +++ b/locales/ro/common.json @@ -4483,6 +4483,10 @@ "menu": "Deschideți meniul contactului" } }, + "ux_pim_contact": { + "context_private": "Acasă", + "phone_voice": "Telefon" + }, "uxs_wording": { "more_options": "Mai multe opțiuni", "use_in_other_apps": "Folosește în alte aplicații", diff --git a/locales/ru/common.json b/locales/ru/common.json index e32676136..3b53ae9ec 100644 --- a/locales/ru/common.json +++ b/locales/ru/common.json @@ -4483,6 +4483,10 @@ "open_categories": "Открыть категории", "row_actions": "Действия для {name}" }, + "ux_pim_contact": { + "context_private": "Домашний", + "phone_voice": "Телефон" + }, "uxs_wording": { "more_options": "Другие параметры", "use_in_other_apps": "Использовать в других приложениях", diff --git a/locales/sk/common.json b/locales/sk/common.json index 3da1ed6c4..9d90a7e39 100644 --- a/locales/sk/common.json +++ b/locales/sk/common.json @@ -4483,6 +4483,10 @@ "menu": "Otvoriť ponuku kontaktu" } }, + "ux_pim_contact": { + "context_private": "Domov", + "phone_voice": "Telefón" + }, "uxs_wording": { "more_options": "Ďalšie možnosti", "use_in_other_apps": "Použiť v iných aplikáciách", diff --git a/locales/th/common.json b/locales/th/common.json index d8fbce3f9..61e884b59 100644 --- a/locales/th/common.json +++ b/locales/th/common.json @@ -3821,6 +3821,10 @@ "menu": "เปิดเมนูของผู้ติดต่อ" } }, + "ux_pim_contact": { + "context_private": "บ้าน", + "phone_voice": "โทรศัพท์" + }, "uxs_wording": { "more_options": "ตัวเลือกเพิ่มเติม", "use_in_other_apps": "ใช้ในแอปอื่น", diff --git a/locales/tr/common.json b/locales/tr/common.json index 59e4b73db..ee0535a1f 100644 --- a/locales/tr/common.json +++ b/locales/tr/common.json @@ -4483,6 +4483,10 @@ "open_categories": "Kategorileri aç", "row_actions": "{name} için işlemler" }, + "ux_pim_contact": { + "context_private": "Ev", + "phone_voice": "Telefon" + }, "uxs_wording": { "more_options": "Diğer seçenekler", "use_in_other_apps": "Başka uygulamalarda kullan", diff --git a/locales/uk/common.json b/locales/uk/common.json index be354b49c..be055e0bf 100644 --- a/locales/uk/common.json +++ b/locales/uk/common.json @@ -4483,6 +4483,10 @@ "open_categories": "Відкрити категорії", "row_actions": "Дії для {name}" }, + "ux_pim_contact": { + "context_private": "Домашній", + "phone_voice": "Телефон" + }, "uxs_wording": { "more_options": "Інші параметри", "use_in_other_apps": "Використовувати в інших застосунках", diff --git a/locales/vi/common.json b/locales/vi/common.json index fe1be93e4..767c5b683 100644 --- a/locales/vi/common.json +++ b/locales/vi/common.json @@ -4495,6 +4495,10 @@ "menu": "Mở menu của liên hệ" } }, + "ux_pim_contact": { + "context_private": "Nhà riêng", + "phone_voice": "Điện thoại" + }, "uxs_wording": { "more_options": "Tùy chọn khác", "use_in_other_apps": "Dùng trong ứng dụng khác", diff --git a/locales/zh-TW/common.json b/locales/zh-TW/common.json index 205e145f6..617249424 100644 --- a/locales/zh-TW/common.json +++ b/locales/zh-TW/common.json @@ -4483,6 +4483,10 @@ "menu": "開啟聯絡人選單" } }, + "ux_pim_contact": { + "context_private": "住家", + "phone_voice": "電話" + }, "uxs_wording": { "more_options": "更多選項", "use_in_other_apps": "在其他應用程式中使用", diff --git a/locales/zh/common.json b/locales/zh/common.json index 0e601ed20..109399036 100644 --- a/locales/zh/common.json +++ b/locales/zh/common.json @@ -4483,6 +4483,10 @@ "open_categories": "打开分类", "row_actions": "{name} 的操作" }, + "ux_pim_contact": { + "context_private": "住宅", + "phone_voice": "电话" + }, "uxs_wording": { "more_options": "更多选项", "use_in_other_apps": "在其他应用中使用",