background
Our project had two modules initialized in this way when internationalization was done with flutter_Intl, delegates of moduleA.S. sellgate and S.sellgate modules were added in localizationsDelegates
class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return GetMaterialApp( title: '${appConfigSvc.appName}', localizationsDelegates: [ ModuleA.S.delegate, S.delegate, GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate, GlobalWidgetsLocalizations.delegate ], supportedLocales: S.delegate.supportedLocales, localeListResolutionCallback: (locales, supportedLocales) { return; },... }}Copy the code
After the module is run, it is found that the language in moduleA. S can change with the system language, but S cannot.
Source code analysis
The language internationalization method is s.current.test, so we can look at the underlying implementation from that, trace the method calls, and see that we end up calling lookupMessage, the abstract method in intl_helps
//messageLookup is a CompositeMessageLookup object, which stores the configuration language, MessageLookup = UninitializedLocaleData('initializeMessages(<locale>)', null); abstract class MessageLookup { String? lookupMessage(String? messageText, String? locale, String? name, List<Object>? args, String? meaning, {MessageIfAbsent? ifAbsent}); void addLocale(String localeName, Function findLocale); }Copy the code
The CompositeMessageLookup class addLocale adds the MessageLookupByLibrary that specifies localeName to the availableMessages map. LookupMessage gets the corresponding language from MessageLookupByLibrary
class CompositeMessageLookup implements MessageLookup { Map<String, MessageLookupByLibrary> availableMessages = Map(); bool localeExists(localeName) => availableMessages.containsKey(localeName); String? _lastLocale; MessageLookupByLibrary? _lastLookup; // messageText is a String for the locale and name. lookupMessage(String? messageText, String? locale, String? name, List<Object>? args, String? meaning, {MessageIfAbsent? ifAbsent}) { var knownLocale = locale ?? Intl.getCurrentLocale(); var messages = (knownLocale == _lastLocale) ? _lastLookup : _lookupMessageCatalog(knownLocale); if (messages == null) { return ifAbsent == null ? messageText : ifAbsent(messageText, args); } return messages.lookupMessage(messageText, locale, name, args, meaning, ifAbsent: ifAbsent); } MessageLookupByLibrary? _lookupMessageCatalog(String locale) { var verifiedLocale = Intl.verifiedLocale(locale, localeExists, onFailure: (locale) => locale); _lastLocale = locale; _lastLookup = availableMessages[verifiedLocale]; return _lastLookup; } //findLocales is used to generate MessageLookupByLibrary void addLocale(String localeName, Function findLocale) { If (localeExists(localeName)) return; if (localeExists(localeName)) return; if (localeExists(localeName)) return; var canonical = Intl.canonicalizedLocale(localeName); var newLocale = findLocale(canonical); if (newLocale ! = null) { availableMessages[localeName] = newLocale; availableMessages[canonical] = newLocale; // If there was already a failed lookup for [newLocale], null the cache. if (_lastLocale == newLocale) { _lastLocale = null; _lastLookup = null; }}}}Copy the code
Since addLocale checks if localeName exists and returns if it does, the language of our second module will not be added. How do we solve this problem? All kv mappings for languages are stored in messages, so we can consider adding messages for Module2 to Module1 before initialization.
abstract class MessageLookupByLibrary { String? lookupMessage(String? messageText, String? locale, String? name, List<Object>? args, String? meaning, {MessageIfAbsent? ifAbsent}) { var actualName = computeMessageName(name, messageText, meaning); Object? translation; if (actualName ! = null) { translation = this[actualName]; } if (translation == null) { return ifAbsent == null ? messageText : ifAbsent(messageText, args); } else { args = args ?? const []; return evaluateMessage(translation, args); } } String? evaluateMessage(translation, List<dynamic> args) { return Function.apply(translation, args); } /// Return our message with the given name dynamic operator [](String messageName) => messages[messageName]; Map<String, dynamic> get messages; String get localeName; String toString() => localeName; static String Function() simpleMessage(translatedString) => () => translatedString; }Copy the code
The solution
Based on the above analysis, I adopted a poor solution, which was to combine the languages of the two modules when the APP was started.
import 'package:xxxx1/generated/intl/messages_en.dart' as messages_en; import 'package:xxxx1/generated/intl/messages_zh.dart' as messages_zh; import 'package:xxxx2/generated/intl/messages_th.dart' as mp_messages_en; import 'package:xxxx2/generated/intl/messages_zh.dart' as mp_messages_zh; void main() { messages_en.messages.messages.addAll(mp_messages_en.messages.messages); messages_zh.messages.messages.addAll(mp_messages_zh.messages.messages); . }Copy the code
conclusion
The main problem is that MessageLookupByLibrary is unique.