gcx/frontend/genex-mobile/lib/app/i18n/locale_manager.dart

118 lines
3.1 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
/// 全局语言状态管理
///
/// userLocale = null 时跟随系统语言
/// 用户在设置页选择后,持久化到 SharedPreferences下次启动自动恢复
class LocaleManager {
static final ValueNotifier<Locale?> userLocale = ValueNotifier(null);
static const _prefKey = 'user_locale';
static const supportedLocales = [
Locale('zh', 'CN'),
Locale('zh', 'TW'),
Locale('en'),
Locale('ja'),
];
/// 启动时调用,从 SharedPreferences 恢复用户选择的语言
static Future<void> init() async {
final prefs = await SharedPreferences.getInstance();
final saved = prefs.getString(_prefKey);
if (saved != null) {
final locale = _parseLocale(saved);
if (locale != null) {
userLocale.value = locale;
}
}
}
/// 设置用户语言并持久化(传 null 表示恢复跟随系统)
static Future<void> setLocale(Locale? locale) async {
userLocale.value = locale;
final prefs = await SharedPreferences.getInstance();
if (locale == null) {
await prefs.remove(_prefKey);
} else {
await prefs.setString(_prefKey, _serializeLocale(locale));
}
}
/// 根据系统 locale 解析最佳匹配
static Locale resolve(List<Locale>? systemLocales, Iterable<Locale> supported) {
if (systemLocales == null || systemLocales.isEmpty) {
return const Locale('zh', 'CN');
}
final system = systemLocales.first;
// 精确匹配
for (final s in supported) {
if (s.languageCode == system.languageCode &&
s.countryCode == system.countryCode) {
return s;
}
}
// 语言码匹配
for (final s in supported) {
if (s.languageCode == system.languageCode) {
return s;
}
}
// 默认中文
return const Locale('zh', 'CN');
}
/// 根据语言获取默认货币
static String defaultCurrencyForLocale(Locale locale) {
switch (locale.languageCode) {
case 'zh':
return locale.countryCode == 'TW' ? 'TWD' : 'CNY';
case 'ja':
return 'JPY';
case 'en':
default:
return 'USD';
}
}
/// Locale 转显示名称
static String localeDisplayName(Locale locale) {
final key = '${locale.languageCode}_${locale.countryCode ?? ''}';
switch (key) {
case 'zh_CN':
return '简体中文';
case 'zh_TW':
return '繁體中文';
case 'en_':
case 'en_US':
return 'English';
case 'ja_':
case 'ja_JP':
return '日本語';
default:
return locale.toString();
}
}
static String _serializeLocale(Locale locale) {
if (locale.countryCode != null && locale.countryCode!.isNotEmpty) {
return '${locale.languageCode}_${locale.countryCode}';
}
return locale.languageCode;
}
static Locale? _parseLocale(String str) {
final parts = str.split('_');
if (parts.length == 2) {
return Locale(parts[0], parts[1]);
} else if (parts.length == 1 && parts[0].isNotEmpty) {
return Locale(parts[0]);
}
return null;
}
}