This commit is contained in:
wchino
2026-06-13 17:38:25 +08:00
parent e7e938f261
commit 7b33d9f9fa
190 changed files with 23222 additions and 4336 deletions

View File

@@ -0,0 +1,78 @@
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));
});
}