Executable
+1035
File diff suppressed because it is too large
Load Diff
Executable
+57
@@ -0,0 +1,57 @@
|
||||
// import 'package:get/get.dart';
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class GetxTranslations extends Translations {
|
||||
final Map<String, Map<String, String>> _translations = {};
|
||||
|
||||
@override
|
||||
Map<String, Map<String, String>> get keys => _translations;
|
||||
|
||||
// 初始化并加载所有翻译文件
|
||||
Future<void> loadAllTranslations() async {
|
||||
_translations['en'] = await _loadTranslations('assets/translations/strings_en.i18n.json');
|
||||
_translations['zh_CN'] = await _loadTranslations('assets/translations/strings_zh.i18n.json');
|
||||
_translations['zh_TW'] = await _loadTranslations('assets/translations/strings_zh_Hant.i18n.json');
|
||||
_translations['es'] =
|
||||
await _loadTranslations('assets/translations/strings_es.i18n.json');
|
||||
_translations['ja'] =
|
||||
await _loadTranslations('assets/translations/strings_ja.i18n.json');
|
||||
_translations['ru'] =
|
||||
await _loadTranslations('assets/translations/strings_ru.i18n.json');
|
||||
_translations['et'] =
|
||||
await _loadTranslations('assets/translations/strings_et.i18n.json');
|
||||
}
|
||||
|
||||
// 读取并解析 JSON 文件
|
||||
Future<Map<String, String>> _loadTranslations(String path) async {
|
||||
final Map<String, String> translations = {};
|
||||
final String jsonString = await rootBundle.loadString(path);
|
||||
final Map<String, dynamic> jsonMap = json.decode(jsonString);
|
||||
|
||||
_flattenTranslations(jsonMap, translations);
|
||||
|
||||
return translations;
|
||||
}
|
||||
|
||||
// 递归提取最底层的翻译文本并展平结构
|
||||
|
||||
void _flattenTranslations(
|
||||
Map<String, dynamic> jsonMap, Map<String, String> translations,
|
||||
[String prefix = '']) {
|
||||
jsonMap.forEach((key, value) {
|
||||
final newKey = prefix.isEmpty ? key : '$prefix.$key';
|
||||
if (value is Map<String, dynamic>) {
|
||||
_flattenTranslations(value, translations, newKey);
|
||||
} else if (value is String) {
|
||||
// 替换占位符 {xxx} 为 @xxx
|
||||
final modifiedValue = value.replaceAllMapped(
|
||||
RegExp(r'\{(\w+)\}'),
|
||||
(match) => '@${match.group(1)}',
|
||||
);
|
||||
translations[newKey] = modifiedValue;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Executable
+146
@@ -0,0 +1,146 @@
|
||||
import 'dart:ui';
|
||||
|
||||
import 'package:get/get.dart';
|
||||
import 'package:kaer_with_panels/app/utils/kr_secure_storage.dart';
|
||||
|
||||
enum KRLanguage {
|
||||
en('🇬🇧', 'English', 'en'),
|
||||
zh('🇨🇳', '中文', 'zh'),
|
||||
es('🇪🇸', 'Español', 'es'),
|
||||
zhHant('🇹🇼', '繁體中文', 'zhHant'),
|
||||
ja('🇯🇵', '日本語', 'ja'),
|
||||
ru('🇷🇺', 'Русский', 'ru'),
|
||||
et('🇪🇪', 'Eesti', 'et');
|
||||
|
||||
final String flagEmoji;
|
||||
final String languageName;
|
||||
final String countryCode;
|
||||
|
||||
const KRLanguage(this.flagEmoji, this.languageName, this.countryCode);
|
||||
}
|
||||
|
||||
class KRLanguageUtils {
|
||||
static const String _lastLanguageKey = 'last_language';
|
||||
static const String _initLanguageKey = 'init_language';
|
||||
static final KRSecureStorage _storage = KRSecureStorage();
|
||||
static final RxString kr_language = ''.obs;
|
||||
// 获取可选语言列表
|
||||
|
||||
static List<KRLanguage> getAvailableLanguages() {
|
||||
return KRLanguage.values;
|
||||
}
|
||||
|
||||
// 切换语言
|
||||
static Future<void> switchLanguage(KRLanguage language) async {
|
||||
final locale = _getLocaleFromLanguage(language);
|
||||
|
||||
Get.updateLocale(locale);
|
||||
await _saveLastLanguage(language);
|
||||
kr_language.value = language.languageName;
|
||||
}
|
||||
|
||||
// 获取当前语言
|
||||
static KRLanguage getCurrentLanguage() {
|
||||
final locale = Get.locale;
|
||||
return _getLanguageFromLocale(locale);
|
||||
}
|
||||
|
||||
// 获取最后保存的语言并转换为 Locale
|
||||
static Future<Locale> getLastSavedLocale() async {
|
||||
final lastLanguage = await _storage.kr_readData(key: _lastLanguageKey);
|
||||
if (lastLanguage != null) {
|
||||
final language = KRLanguage.values.firstWhere(
|
||||
(lang) => lang.countryCode == lastLanguage,
|
||||
orElse: () => KRLanguage.ru,
|
||||
);
|
||||
return _getLocaleFromLanguage(language);
|
||||
}
|
||||
return Locale('ru');
|
||||
}
|
||||
|
||||
// 检查首次打开应用时的语言设置
|
||||
static Future<bool> checkInitialLanguage() async {
|
||||
final Locale? systemLocale = Get.deviceLocale;
|
||||
|
||||
final lastLanguage = await _storage.kr_readData(key: _initLanguageKey);
|
||||
if (lastLanguage == null) {
|
||||
final bool isChineseRegion = systemLocale?.languageCode == 'zh' &&
|
||||
(systemLocale?.countryCode == 'CN' ||
|
||||
systemLocale?.scriptCode == 'Hans');
|
||||
_storage.kr_saveData(
|
||||
key: _initLanguageKey, value: isChineseRegion.toString());
|
||||
return isChineseRegion;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// 保存最后使用的语言
|
||||
static Future<void> _saveLastLanguage(KRLanguage language) async {
|
||||
await _storage.kr_saveData(
|
||||
key: _lastLanguageKey, value: language.countryCode);
|
||||
}
|
||||
|
||||
// 从语言枚举获取 Locale
|
||||
static Locale _getLocaleFromLanguage(KRLanguage language) {
|
||||
switch (language) {
|
||||
case KRLanguage.zh:
|
||||
return Locale('zh', 'CN');
|
||||
case KRLanguage.es:
|
||||
return Locale('es');
|
||||
case KRLanguage.zhHant:
|
||||
return Locale('zh', 'TW');
|
||||
case KRLanguage.ja:
|
||||
return Locale('ja');
|
||||
case KRLanguage.ru:
|
||||
return Locale('ru');
|
||||
case KRLanguage.et:
|
||||
return Locale('et');
|
||||
default:
|
||||
return Locale('en');
|
||||
}
|
||||
}
|
||||
|
||||
// 从 Locale 获取语言枚举
|
||||
static KRLanguage _getLanguageFromLocale(Locale? locale) {
|
||||
if (locale == null) return KRLanguage.en;
|
||||
switch (locale.languageCode) {
|
||||
case 'zh':
|
||||
if (locale.countryCode == 'TW' || locale.scriptCode == 'Hant') {
|
||||
return KRLanguage.zhHant;
|
||||
}
|
||||
return KRLanguage.zh;
|
||||
case 'es':
|
||||
return KRLanguage.es;
|
||||
case 'ja':
|
||||
return KRLanguage.ja;
|
||||
case 'ru':
|
||||
return KRLanguage.ru;
|
||||
case 'et':
|
||||
return KRLanguage.et;
|
||||
default:
|
||||
return KRLanguage.en;
|
||||
}
|
||||
}
|
||||
|
||||
// 获取当前语言编码字符串
|
||||
static String getCurrentLanguageCode() {
|
||||
final KRLanguage currentLanguage = getCurrentLanguage();
|
||||
switch (currentLanguage) {
|
||||
case KRLanguage.zh:
|
||||
return 'zh_CN';
|
||||
case KRLanguage.zhHant:
|
||||
return 'zh_TW';
|
||||
case KRLanguage.es:
|
||||
return 'es';
|
||||
case KRLanguage.ja:
|
||||
return 'ja';
|
||||
case KRLanguage.ru:
|
||||
return 'ru';
|
||||
case KRLanguage.et:
|
||||
return 'et';
|
||||
case KRLanguage.en:
|
||||
return 'en';
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user