feat: phase1 UI prep — 设备ID系统传递 + 国家本地化展示 + 继续观看直进播放页
设备标识: Android SSAID/ iOS IDFV 原生通道 → Dart DeviceIdProvider 国家解析: 注册/登录从后端 IP → 国家/语言/时区/币种 自动落库 账号资料: 全部本地化展示 (account_display.dart) 我的页: 继续观看卡片点击直接进播放页
This commit is contained in:
1 parent
1b19513efb
commit
a3f3481f4f
15 files changed
+468
-25
No files matched your search
@@ -0,0 +1,239 @@
|
||||
// Author: fruit.com.cn
|
||||
|
||||
/// 账号资料页只读字段的展示格式化。
|
||||
///
|
||||
/// 后端存的是 ISO 国家码、BCP-47 语言标签和 IANA 时区(`ID` / `id-ID` / `Asia/Jakarta`),
|
||||
/// 直接展示对用户没有意义,这里统一转成当前界面语言的名称。
|
||||
/// 国家与城市名只维护中文与英文两套:界面语言为印尼语时回退英文名,
|
||||
/// 语言名与账号状态则三种界面语言都有。
|
||||
library;
|
||||
|
||||
const _countryNamesZh = {
|
||||
'ID': '印度尼西亚',
|
||||
'MY': '马来西亚',
|
||||
'SG': '新加坡',
|
||||
'TH': '泰国',
|
||||
'VN': '越南',
|
||||
'PH': '菲律宾',
|
||||
'KH': '柬埔寨',
|
||||
'MM': '缅甸',
|
||||
'LA': '老挝',
|
||||
'BN': '文莱',
|
||||
'CN': '中国',
|
||||
'TW': '中国台湾',
|
||||
'HK': '中国香港',
|
||||
'MO': '中国澳门',
|
||||
'JP': '日本',
|
||||
'KR': '韩国',
|
||||
'IN': '印度',
|
||||
'PK': '巴基斯坦',
|
||||
'BD': '孟加拉国',
|
||||
'LK': '斯里兰卡',
|
||||
'NP': '尼泊尔',
|
||||
'US': '美国',
|
||||
'CA': '加拿大',
|
||||
'MX': '墨西哥',
|
||||
'BR': '巴西',
|
||||
'AR': '阿根廷',
|
||||
'CL': '智利',
|
||||
'CO': '哥伦比亚',
|
||||
'PE': '秘鲁',
|
||||
'VE': '委内瑞拉',
|
||||
'EC': '厄瓜多尔',
|
||||
'GT': '危地马拉',
|
||||
'DO': '多米尼加',
|
||||
'GB': '英国',
|
||||
'DE': '德国',
|
||||
'FR': '法国',
|
||||
'ES': '西班牙',
|
||||
'IT': '意大利',
|
||||
'NL': '荷兰',
|
||||
'PL': '波兰',
|
||||
'RU': '俄罗斯',
|
||||
'UA': '乌克兰',
|
||||
'TR': '土耳其',
|
||||
'SA': '沙特阿拉伯',
|
||||
'AE': '阿联酋',
|
||||
'IL': '以色列',
|
||||
'EG': '埃及',
|
||||
'NG': '尼日利亚',
|
||||
'ZA': '南非',
|
||||
'KE': '肯尼亚',
|
||||
'MA': '摩洛哥',
|
||||
'AU': '澳大利亚',
|
||||
'NZ': '新西兰',
|
||||
};
|
||||
|
||||
const _countryNamesEn = {
|
||||
'ID': 'Indonesia',
|
||||
'MY': 'Malaysia',
|
||||
'SG': 'Singapore',
|
||||
'TH': 'Thailand',
|
||||
'VN': 'Vietnam',
|
||||
'PH': 'Philippines',
|
||||
'KH': 'Cambodia',
|
||||
'MM': 'Myanmar',
|
||||
'LA': 'Laos',
|
||||
'BN': 'Brunei',
|
||||
'CN': 'China',
|
||||
'TW': 'Taiwan',
|
||||
'HK': 'Hong Kong',
|
||||
'MO': 'Macau',
|
||||
'JP': 'Japan',
|
||||
'KR': 'South Korea',
|
||||
'IN': 'India',
|
||||
'PK': 'Pakistan',
|
||||
'BD': 'Bangladesh',
|
||||
'LK': 'Sri Lanka',
|
||||
'NP': 'Nepal',
|
||||
'US': 'United States',
|
||||
'CA': 'Canada',
|
||||
'MX': 'Mexico',
|
||||
'BR': 'Brazil',
|
||||
'AR': 'Argentina',
|
||||
'CL': 'Chile',
|
||||
'CO': 'Colombia',
|
||||
'PE': 'Peru',
|
||||
'VE': 'Venezuela',
|
||||
'EC': 'Ecuador',
|
||||
'GT': 'Guatemala',
|
||||
'DO': 'Dominican Republic',
|
||||
'GB': 'United Kingdom',
|
||||
'DE': 'Germany',
|
||||
'FR': 'France',
|
||||
'ES': 'Spain',
|
||||
'IT': 'Italy',
|
||||
'NL': 'Netherlands',
|
||||
'PL': 'Poland',
|
||||
'RU': 'Russia',
|
||||
'UA': 'Ukraine',
|
||||
'TR': 'Turkey',
|
||||
'SA': 'Saudi Arabia',
|
||||
'AE': 'United Arab Emirates',
|
||||
'IL': 'Israel',
|
||||
'EG': 'Egypt',
|
||||
'NG': 'Nigeria',
|
||||
'ZA': 'South Africa',
|
||||
'KE': 'Kenya',
|
||||
'MA': 'Morocco',
|
||||
'AU': 'Australia',
|
||||
'NZ': 'New Zealand',
|
||||
};
|
||||
|
||||
const _timezoneNamesZh = {
|
||||
'Asia/Jakarta': '雅加达',
|
||||
'Asia/Kuala_Lumpur': '吉隆坡',
|
||||
'Asia/Singapore': '新加坡',
|
||||
'Asia/Bangkok': '曼谷',
|
||||
'Asia/Ho_Chi_Minh': '胡志明市',
|
||||
'Asia/Manila': '马尼拉',
|
||||
'Asia/Phnom_Penh': '金边',
|
||||
'Asia/Yangon': '仰光',
|
||||
'Asia/Vientiane': '万象',
|
||||
'Asia/Brunei': '斯里巴加湾市',
|
||||
'Asia/Shanghai': '上海',
|
||||
'Asia/Taipei': '台北',
|
||||
'Asia/Hong_Kong': '香港',
|
||||
'Asia/Macau': '澳门',
|
||||
'Asia/Tokyo': '东京',
|
||||
'Asia/Seoul': '首尔',
|
||||
'Asia/Kolkata': '加尔各答',
|
||||
'Asia/Karachi': '卡拉奇',
|
||||
'Asia/Dhaka': '达卡',
|
||||
'Asia/Colombo': '科伦坡',
|
||||
'Asia/Kathmandu': '加德满都',
|
||||
'America/New_York': '纽约',
|
||||
'America/Toronto': '多伦多',
|
||||
'America/Mexico_City': '墨西哥城',
|
||||
'America/Sao_Paulo': '圣保罗',
|
||||
'America/Argentina/Buenos_Aires': '布宜诺斯艾利斯',
|
||||
'America/Santiago': '圣地亚哥',
|
||||
'America/Bogota': '波哥大',
|
||||
'America/Lima': '利马',
|
||||
'America/Caracas': '加拉加斯',
|
||||
'America/Guayaquil': '瓜亚基尔',
|
||||
'America/Guatemala': '危地马拉城',
|
||||
'America/Santo_Domingo': '圣多明各',
|
||||
'Europe/London': '伦敦',
|
||||
'Europe/Berlin': '柏林',
|
||||
'Europe/Paris': '巴黎',
|
||||
'Europe/Madrid': '马德里',
|
||||
'Europe/Rome': '罗马',
|
||||
'Europe/Amsterdam': '阿姆斯特丹',
|
||||
'Europe/Warsaw': '华沙',
|
||||
'Europe/Moscow': '莫斯科',
|
||||
'Europe/Kyiv': '基辅',
|
||||
'Europe/Istanbul': '伊斯坦布尔',
|
||||
'Asia/Riyadh': '利雅得',
|
||||
'Asia/Dubai': '迪拜',
|
||||
'Asia/Jerusalem': '耶路撒冷',
|
||||
'Africa/Cairo': '开罗',
|
||||
'Africa/Lagos': '拉各斯',
|
||||
'Africa/Johannesburg': '约翰内斯堡',
|
||||
'Africa/Nairobi': '内罗毕',
|
||||
'Africa/Casablanca': '卡萨布兰卡',
|
||||
'Australia/Sydney': '悉尼',
|
||||
'Pacific/Auckland': '奥克兰',
|
||||
};
|
||||
|
||||
const _languageNames = {
|
||||
'id': {'zh': '印度尼西亚语', 'en': 'Indonesian', 'id': 'Bahasa Indonesia'},
|
||||
'en': {'zh': '英语', 'en': 'English', 'id': 'Inggris'},
|
||||
'zh': {'zh': '中文', 'en': 'Chinese', 'id': 'Mandarin'},
|
||||
};
|
||||
|
||||
const _statusNames = {
|
||||
'normal': {'zh': '正常', 'en': 'Active', 'id': 'Aktif'},
|
||||
'limited': {'zh': '受限', 'en': 'Limited', 'id': 'Dibatasi'},
|
||||
'banned': {'zh': '已封禁', 'en': 'Banned', 'id': 'Diblokir'},
|
||||
'deactivated': {'zh': '已注销', 'en': 'Deactivated', 'id': 'Dinonaktifkan'},
|
||||
};
|
||||
|
||||
String _pick(Map<String, String> names, String localeName) =>
|
||||
names[localeName] ?? names['en']!;
|
||||
|
||||
/// 国家码 → 国家名;未收录的码原样返回。
|
||||
String countryName(String code, String localeName) {
|
||||
final key = code.trim().toUpperCase();
|
||||
if (key.isEmpty) return '';
|
||||
final names = localeName == 'zh' ? _countryNamesZh : _countryNamesEn;
|
||||
return names[key] ?? key;
|
||||
}
|
||||
|
||||
/// IANA 时区 → 城市名;中文界面查表,其余语言取时区里的城市段。
|
||||
String timezoneName(String timezone, String localeName) {
|
||||
final value = timezone.trim();
|
||||
if (value.isEmpty) return '';
|
||||
if (localeName == 'zh') {
|
||||
final name = _timezoneNamesZh[value];
|
||||
if (name != null) return name;
|
||||
}
|
||||
final city = value.split('/').last.replaceAll('_', ' ');
|
||||
return city.isEmpty ? value : city;
|
||||
}
|
||||
|
||||
/// BCP-47 语言标签 → 语言名,按主语言归类(`zh-TW` 也算中文)。
|
||||
String languageName(String language, String localeName) {
|
||||
final value = language.trim();
|
||||
if (value.isEmpty) return '';
|
||||
final primary = value.split(RegExp('[-_]')).first.toLowerCase();
|
||||
final names = _languageNames[primary];
|
||||
return names == null ? value : _pick(names, localeName);
|
||||
}
|
||||
|
||||
/// 账号状态 → 展示文案;未知状态原样返回。
|
||||
String accountStatusText(String status, String localeName) {
|
||||
final value = status.trim().toLowerCase();
|
||||
final names = _statusNames[value];
|
||||
return names == null ? status : _pick(names, localeName);
|
||||
}
|
||||
|
||||
/// VIP 等级:0 表示未开通,避免用户看到一个孤零零的 0。
|
||||
String vipLevelText(int level, String localeName) {
|
||||
if (level > 0) return 'VIP $level';
|
||||
return switch (localeName) {
|
||||
'zh' => '未开通',
|
||||
'id' => 'Belum aktif',
|
||||
_ => 'Not subscribed',
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user