import { normalizeLocale } from './api-errors'; import dialCodesJson from './phone-dial-codes.json'; /** 平台开放注册/短信的国家(ISO 3166-1 alpha-2),顺序即下拉展示顺序 */ export const ALLOWED_PHONE_ISO = ['MY', 'SG', 'IN', 'AU', 'TH', 'VN', 'BD', 'TW']; const ALLOWED_SET = new Set(ALLOWED_PHONE_ISO); const ZH_LABELS = { MY: '马来西亚', SG: '新加坡', IN: '印度', AU: '澳洲', TH: '泰国', VN: '越南', BD: '孟加拉国', TW: '台湾', }; const allCountries = dialCodesJson; /** 开放国家列表(从 ITU 全量数据中筛选) */ export const PHONE_COUNTRIES = ALLOWED_PHONE_ISO.map((iso) => { const found = allCountries.find((c) => c.iso === iso); if (!found) { throw new Error(`Missing phone country data for ISO: ${iso}`); } return found; }); const DIAL_SET = new Set(PHONE_COUNTRIES.map((c) => c.dial)); export function isSupportedPhoneDial(dial) { return DIAL_SET.has(dial.replace(/\D/g, '')); } export function isAllowedPhoneIso(iso) { return ALLOWED_SET.has(iso.toUpperCase()); } export function defaultPhoneDialForLocale(localeInput) { return findPhoneCountryByIso(defaultPhoneIsoForLocale(localeInput))?.dial ?? '60'; } export function defaultPhoneIsoForLocale(localeInput) { const locale = normalizeLocale(localeInput); if (locale === 'zh-CN') return 'TW'; if (locale === 'ms-MY') return 'MY'; return 'SG'; } export function getPhoneDialFromIso(iso) { return findPhoneCountryByIso(iso)?.dial ?? ''; } export function getPhoneCountryLabel(country, localeInput) { const locale = normalizeLocale(localeInput); if (locale === 'zh-CN' && isAllowedPhoneIso(country.iso)) { return ZH_LABELS[country.iso]; } if (locale === 'zh-CN') { return country.nameLocal || country.nameEn; } return country.nameEn; } export function findPhoneCountryByDial(dial) { const normalized = dial.replace(/\D/g, ''); return PHONE_COUNTRIES.find((c) => c.dial === normalized); } export function findPhoneCountryByIso(iso) { const upper = iso.toUpperCase(); if (!isAllowedPhoneIso(upper)) return undefined; return PHONE_COUNTRIES.find((c) => c.iso === upper); } export function searchPhoneCountries(query, localeInput) { const q = query.trim().toLowerCase(); if (!q) return PHONE_COUNTRIES; return PHONE_COUNTRIES.filter((country) => { const label = getPhoneCountryLabel(country, localeInput).toLowerCase(); return (country.iso.toLowerCase().includes(q) || country.dial.includes(q.replace(/^\+/, '')) || country.nameEn.toLowerCase().includes(q) || label.includes(q) || `+${country.dial}`.includes(q)); }); }