Flutter无BuildContext的独立类中调用MovMapLocalizations多语言的方案
解决方案
步骤1:修正es.yaml的格式错误
你当前的es.yaml中signup、muro、time_ago节点缩进异常,比顶层的login多了4个前置空格,会导致yaml解析失败,先调整为和login同级的缩进,同时补充所有时间相关的翻译key:
login: email: Correo electrónico password: Contraseña login: Entrar signup: Registrar or: O newHere: ¿Nuevo aquí? signup: email2: Correo electrónico password2: Contraseña login2: Entrar signup2: Registrar or2: O alreadyAccount: ¿Ya tienes cuenta de usuario? muro: expand: leer más collapse: cerrar delete: Borrar denunciar: Denunciar already: Ya ha sido denunciado has_denunciado: Has denunciado este post time_ago: yearsago: años atrás yearago: 1 año atrás last_year: El año pasado monthsago: meses atrás monthago: 1 mes atrás last_month: El mes pasado weeksago: semanas atrás weekago: 1 semana atrás last_week: La semana pasada daysago: días atrás dayago: 1 día atrás yesterday: Ayer hoursago: horas atrás hourago: 1 hora atrás an_hour_ago: Hace una hora minutesago: minutos atrás minuteago: 1 minuto atrás a_minute_ago: Hace un minuto secondsago: segundos atrás just_now: Ahora mismo
对应的en.yaml也补充完整time_ago相关key:
time_ago: yearsago: years ago yearago: 1 year ago last_year: Last year monthsago: months ago monthago: 1 month ago last_month: Last month weeksago: weeks ago weekago: 1 week ago last_week: Last week daysago: days ago dayago: 1 day ago yesterday: Yesterday hoursago: hours ago hourago: 1 hour ago an_hour_ago: An hour ago minutesago: minutes ago minuteago: 1 minute ago a_minute_ago: A minute ago secondsago: seconds ago just_now: Just now
步骤2:给MovMapLocalizations增加全局静态实例
修改MovMapLocalizations类,增加静态实例存储,本地化加载完成后自动赋值,后续不需要Context即可直接访问:
import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; import 'package:yaml/yaml.dart'; class MovMapLocalizations { final String localeName; MovMapLocalizations(this.localeName); // 新增全局静态实例 static MovMapLocalizations? _instance; static MovMapLocalizations get instance { assert(_instance != null, "MovMapLocalizations not initialized yet"); return _instance!; } static const LocalizationsDelegate<MovMapLocalizations> delegate = _MovMapLocalizationsDelegate(); YamlMap? translations; Future load() async { String yamlString = await rootBundle.loadString('lang/${localeName}.yml'); translations = loadYaml(yamlString); } String t(String key) { try { var keys = key.split("."); dynamic translated = translations; for (var k in keys) { translated = translated?[k]; } if (translated == null) { return "Key not found: $key"; } return translated.toString(); } catch (e) { return "Key not found: $key"; } } } class _MovMapLocalizationsDelegate extends LocalizationsDelegate<MovMapLocalizations> { const _MovMapLocalizationsDelegate(); @override bool isSupported(Locale locale) { print("@@@@@@@@@@@@@@@@@@@@@@@@@LOCALE ACTUAL:"+locale.languageCode); return ['es', 'en'].contains(locale.languageCode); } @override Future<MovMapLocalizations> load(Locale locale) async { var t = MovMapLocalizations(locale.languageCode); await t.load(); // 加载完成后赋值给静态实例 MovMapLocalizations._instance = t; return t; } @override bool shouldReload(covariant LocalizationsDelegate<MovMapLocalizations> old) { return false; } }
步骤3:修改TimeAgo类调用全局翻译实例
直接通过MovMapLocalizations.instance.t()获取翻译文本即可,同时修复原代码中月份计算的逻辑错误:
class TimeAgo{ String formatearFecha(Timestamp timestamp){ var dateFromTimeStamp = DateTime.fromMillisecondsSinceEpoch(timestamp.seconds * 1000); return DateFormat('dd-MM-yyyy HH:mm').format(dateFromTimeStamp); } String timeAgoSinceDate(String dateString, {bool numericDates = true}) { DateTime date = DateTime.parse(dateString); final date2 = DateTime.now(); final difference = date2.difference(date); final loc = MovMapLocalizations.instance; if ((difference.inDays / 365).floor() >= 2) { return '${(difference.inDays / 365).floor()} ${loc.t("time_ago.yearsago")}'; } else if ((difference.inDays / 365).floor() >= 1) { return (numericDates) ? loc.t("time_ago.yearago") : loc.t("time_ago.last_year"); } else if ((difference.inDays / 30).floor() >= 2) { return '${(difference.inDays / 30).floor()} ${loc.t("time_ago.monthsago")}'; } else if ((difference.inDays / 30).floor() >= 1) { return (numericDates) ? loc.t("time_ago.monthago") : loc.t("time_ago.last_month"); } else if ((difference.inDays / 7).floor() >= 2) { return '${(difference.inDays / 7).floor()} ${loc.t("time_ago.weeksago")}'; } else if ((difference.inDays / 7).floor() >= 1) { return (numericDates) ? loc.t("time_ago.weekago") : loc.t("time_ago.last_week"); } else if (difference.inDays >= 2) { return '${difference.inDays} ${loc.t("time_ago.daysago")}'; } else if (difference.inDays >= 1) { return (numericDates) ? loc.t("time_ago.dayago") : loc.t("time_ago.yesterday"); } else if (difference.inHours >= 2) { return '${difference.inHours} ${loc.t("time_ago.hoursago")}'; } else if (difference.inHours >= 1) { return (numericDates) ? loc.t("time_ago.hourago") : loc.t("time_ago.an_hour_ago"); } else if (difference.inMinutes >= 2) { return '${difference.inMinutes} ${loc.t("time_ago.minutesago")}'; } else if (difference.inMinutes >= 1) { return (numericDates) ? loc.t("time_ago.minuteago") : loc.t("time_ago.a_minute_ago"); } else if (difference.inSeconds >= 3) { return '${difference.inSeconds} ${loc.t("time_ago.secondsago")}'; } else { return loc.t("time_ago.just_now"); } } }
注意事项
确保调用TimeAgo的方法时,APP已经完成本地化初始化(即runApp执行后,本地化Delegate的load方法已经执行完成),正常业务场景下用户能触发时间计算逻辑时,本地化都已经加载完毕。如果需要在APP启动极早期就调用TimeAgo,可以提前判断MovMapLocalizations._instance是否为空,为空的话先手动初始化默认语言的实例即可。
内容的提问来源于stack exchange,提问作者mvasco
相关产品推荐
相关产品推荐

