Files
flutterApp/lib/components/language_selection_dialog.dart

101 lines
3.7 KiB
Dart
Raw Normal View History

2026-10-12 14:21:09 +08:00
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:maibu_satabot_v2/core/localization/locale_cubit.dart';
/// 可选语言项:tag 对应 assets/languages/{tag}.json,nativeName 用该语言本地写法展示。
class LanguageItem {
final Locale locale;
final String nativeName;
const LanguageItem(this.locale, this.nativeName);
String get tag => locale.countryCode == null || locale.countryCode!.isEmpty
? locale.languageCode
: '${locale.languageCode}-${locale.countryCode}';
}
/// 全局唯一的“可选语言列表”来源。
/// 后续接入“接口下载语言包”时,只需在这里扩展(例如把已下载的语言追加进来),
/// 登录强制弹窗与设置页入口都会自动同步,无需改多处。
class AppLanguages {
AppLanguages._();
static final AppLanguages instance = AppLanguages._();
final List<LanguageItem> items = const [
LanguageItem(Locale('zh', 'CN'), '简体中文'),
LanguageItem(Locale('en', 'US'), 'English'),
];
String nameOf(Locale locale) {
final tag = locale.countryCode == null || locale.countryCode!.isEmpty
? locale.languageCode
: '${locale.languageCode}-${locale.countryCode}';
for (final item in items) {
if (item.tag == tag) return item.nativeName;
}
return tag;
}
}
/// 语言选择弹窗。
/// [mandatory] = true:登录时强制弹出,拦截系统返回键;可点某个语言即时切换,或点“继续”确认当前默认语言后关闭。
/// [mandatory] = false:设置页中普通选择,可取消。
2026-10-12 14:21:09 +08:00
class LanguageSelectionDialog extends StatelessWidget {
final bool mandatory;
const LanguageSelectionDialog({super.key, this.mandatory = true});
Future<void> _onSelect(BuildContext context, Locale locale) async {
await context.read<LocaleCubit>().setLocale(locale);
if (context.mounted) Navigator.of(context).pop();
}
/// “继续”:不改变当前(默认)语言,仅确认已选并关闭,后续启动不再弹。
Future<void> _onContinue(BuildContext context, Locale current) async {
await context.read<LocaleCubit>().setLocale(current);
if (context.mounted) Navigator.of(context).pop();
}
2026-10-12 14:21:09 +08:00
@override
Widget build(BuildContext context) {
final current = context.select<LocaleCubit, Locale>(
(c) => c.state,
);
return PopScope(
// 强制弹窗时拦截返回键,必须选一个才能继续使用
canPop: !mandatory,
child: AlertDialog(
title: const Text('选择语言 / Select Language'),
content: SizedBox(
width: 300,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
for (final item in AppLanguages.instance.items)
RadioListTile<String>(
value: item.tag,
// 高亮当前语言:按 languageCode 匹配,兼容国家码为空的历史值
groupValue: current.countryCode == null ||
current.countryCode!.isEmpty
? current.languageCode
: '${current.languageCode}-${current.countryCode}',
title: Text(item.nativeName),
onChanged: (_) => _onSelect(context, item.locale),
),
],
),
),
actions: [
// 强制弹窗:提供“继续”出口,保持当前默认语言并确认后关闭;非强制:取消
TextButton(
onPressed: () => mandatory
? _onContinue(context, current)
: Navigator.of(context).pop(),
child: Text(mandatory ? '继续 / Continue' : '取消'),
),
],
2026-10-12 14:21:09 +08:00
),
);
}
}