mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-05 08:16:22 +00:00
fix: call a voice number Phone and a private entry Home on contacts
The contact-detail test now expects the new label key for private, since the wording moved to the ux_pim_contact namespace.
This commit is contained in:
@@ -68,7 +68,7 @@ describe('ContactDetail', () => {
|
||||
render(<ContactDetail contact={typed} onEdit={vi.fn()} onDelete={vi.fn()} />);
|
||||
// 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();
|
||||
});
|
||||
|
||||
@@ -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(<ContactForm contact={anna} onSave={vi.fn()} onCancel={vi.fn()} />);
|
||||
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(<ContactDetail contact={anna} onEdit={vi.fn()} onDelete={vi.fn()} />);
|
||||
expect(screen.getByText('ux_pim_contact.context_private · ux_pim_contact.phone_voice')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -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<string, string> = {
|
||||
work: "form.context_work",
|
||||
private: "form.context_private",
|
||||
private: "ux_pim_contact.context_private",
|
||||
};
|
||||
|
||||
const PHONE_FEATURE_LABEL_KEYS: Record<string, string> = {
|
||||
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<ContactCard>();
|
||||
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;
|
||||
|
||||
@@ -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<HTMLDivElement | null>(null);
|
||||
@@ -916,7 +917,7 @@ export function ContactForm({ contact, addressBooks, allKeywords, defaultAddress
|
||||
>
|
||||
<option value="">-</option>
|
||||
<option value="work">{t("context_work")}</option>
|
||||
<option value="private">{t("context_private")}</option>
|
||||
<option value="private">{tx("context_private")}</option>
|
||||
</Select>
|
||||
{emails.length > 1 && (
|
||||
<IconButton label={t("remove_entry")} onClick={() => 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")}
|
||||
>
|
||||
<option value="">{t("phone_type")}</option>
|
||||
<option value="voice">{t("phone_voice")}</option>
|
||||
<option value="voice">{tx("phone_voice")}</option>
|
||||
<option value="mobile">{t("phone_cell")}</option>
|
||||
<option value="fax">{t("phone_fax")}</option>
|
||||
<option value="pager">{t("phone_pager")}</option>
|
||||
@@ -984,7 +985,7 @@ export function ContactForm({ contact, addressBooks, allKeywords, defaultAddress
|
||||
>
|
||||
<option value="">-</option>
|
||||
<option value="work">{t("context_work")}</option>
|
||||
<option value="private">{t("context_private")}</option>
|
||||
<option value="private">{tx("context_private")}</option>
|
||||
</Select>
|
||||
<IconButton label={t("remove_entry")} onClick={() => setPhones(phones.filter((_, j) => j !== i))} className="shrink-0">
|
||||
<X />
|
||||
@@ -1046,7 +1047,7 @@ export function ContactForm({ contact, addressBooks, allKeywords, defaultAddress
|
||||
>
|
||||
<option value="">-</option>
|
||||
<option value="work">{t("context_work")}</option>
|
||||
<option value="private">{t("context_private")}</option>
|
||||
<option value="private">{tx("context_private")}</option>
|
||||
</Select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4483,6 +4483,10 @@
|
||||
"menu": "فتح قائمة جهة الاتصال"
|
||||
}
|
||||
},
|
||||
"ux_pim_contact": {
|
||||
"context_private": "المنزل",
|
||||
"phone_voice": "هاتف"
|
||||
},
|
||||
"uxs_wording": {
|
||||
"more_options": "خيارات إضافية",
|
||||
"use_in_other_apps": "الاستخدام في تطبيقات أخرى",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -4483,6 +4483,10 @@
|
||||
"menu": "باز کردن منوی مخاطب"
|
||||
}
|
||||
},
|
||||
"ux_pim_contact": {
|
||||
"context_private": "منزل",
|
||||
"phone_voice": "تلفن"
|
||||
},
|
||||
"uxs_wording": {
|
||||
"more_options": "گزینههای بیشتر",
|
||||
"use_in_other_apps": "استفاده در برنامههای دیگر",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -4376,6 +4376,10 @@
|
||||
"menu": "פתח את התפריט של איש הקשר"
|
||||
}
|
||||
},
|
||||
"ux_pim_contact": {
|
||||
"context_private": "בית",
|
||||
"phone_voice": "טלפון"
|
||||
},
|
||||
"uxs_wording": {
|
||||
"more_options": "אפשרויות נוספות",
|
||||
"use_in_other_apps": "שימוש באפליקציות אחרות",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -4483,6 +4483,10 @@
|
||||
"open_categories": "カテゴリを開く",
|
||||
"row_actions": "{name} の操作"
|
||||
},
|
||||
"ux_pim_contact": {
|
||||
"context_private": "自宅",
|
||||
"phone_voice": "電話"
|
||||
},
|
||||
"uxs_wording": {
|
||||
"more_options": "その他のオプション",
|
||||
"use_in_other_apps": "ほかのアプリで使う",
|
||||
|
||||
@@ -4483,6 +4483,10 @@
|
||||
"open_categories": "카테고리 열기",
|
||||
"row_actions": "{name} 작업"
|
||||
},
|
||||
"ux_pim_contact": {
|
||||
"context_private": "집",
|
||||
"phone_voice": "전화"
|
||||
},
|
||||
"uxs_wording": {
|
||||
"more_options": "옵션 더 보기",
|
||||
"use_in_other_apps": "다른 앱에서 사용",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -4483,6 +4483,10 @@
|
||||
"menu": "Харилцагчийн цэсийг нээх"
|
||||
}
|
||||
},
|
||||
"ux_pim_contact": {
|
||||
"context_private": "Гэр",
|
||||
"phone_voice": "Утас"
|
||||
},
|
||||
"uxs_wording": {
|
||||
"more_options": "Бусад сонголт",
|
||||
"use_in_other_apps": "Бусад апп-д ашиглах",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -4483,6 +4483,10 @@
|
||||
"open_categories": "Открыть категории",
|
||||
"row_actions": "Действия для {name}"
|
||||
},
|
||||
"ux_pim_contact": {
|
||||
"context_private": "Домашний",
|
||||
"phone_voice": "Телефон"
|
||||
},
|
||||
"uxs_wording": {
|
||||
"more_options": "Другие параметры",
|
||||
"use_in_other_apps": "Использовать в других приложениях",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -3821,6 +3821,10 @@
|
||||
"menu": "เปิดเมนูของผู้ติดต่อ"
|
||||
}
|
||||
},
|
||||
"ux_pim_contact": {
|
||||
"context_private": "บ้าน",
|
||||
"phone_voice": "โทรศัพท์"
|
||||
},
|
||||
"uxs_wording": {
|
||||
"more_options": "ตัวเลือกเพิ่มเติม",
|
||||
"use_in_other_apps": "ใช้ในแอปอื่น",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -4483,6 +4483,10 @@
|
||||
"open_categories": "Відкрити категорії",
|
||||
"row_actions": "Дії для {name}"
|
||||
},
|
||||
"ux_pim_contact": {
|
||||
"context_private": "Домашній",
|
||||
"phone_voice": "Телефон"
|
||||
},
|
||||
"uxs_wording": {
|
||||
"more_options": "Інші параметри",
|
||||
"use_in_other_apps": "Використовувати в інших застосунках",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -4483,6 +4483,10 @@
|
||||
"menu": "開啟聯絡人選單"
|
||||
}
|
||||
},
|
||||
"ux_pim_contact": {
|
||||
"context_private": "住家",
|
||||
"phone_voice": "電話"
|
||||
},
|
||||
"uxs_wording": {
|
||||
"more_options": "更多選項",
|
||||
"use_in_other_apps": "在其他應用程式中使用",
|
||||
|
||||
@@ -4483,6 +4483,10 @@
|
||||
"open_categories": "打开分类",
|
||||
"row_actions": "{name} 的操作"
|
||||
},
|
||||
"ux_pim_contact": {
|
||||
"context_private": "住宅",
|
||||
"phone_voice": "电话"
|
||||
},
|
||||
"uxs_wording": {
|
||||
"more_options": "更多选项",
|
||||
"use_in_other_apps": "在其他应用中使用",
|
||||
|
||||
Reference in New Issue
Block a user