Open codelovercc opened 9 months ago
Random observation, may or may not be relevant: Search for @dart
, only one of the generated libraries has it.
I use intl and intl_translation in dart only package, use intl and intlutil in Flutter project, every generated `messages*.dartfiles have
@dart=2.12by intl_translation. In other word, intl_translation generate libraries with
@dart=2.12`, and intl_util does not.
intl_translation generated files samples:
messages_all.dart ↓
// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
// This is a library that looks up messages for specific locales by
// delegating to the appropriate library.
// @dart=2.12
export 'messages_all_locales.dart' show initializeMessages;
messages_all_locales.dart ↓
// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
// This is a library that looks up messages for specific locales by
// delegating to the appropriate library.
// @dart=2.12
// Ignore issues from commonly used lints in this file.
// ignore_for_file:implementation_imports, file_names
// ignore_for_file:unnecessary_brace_in_string_interps, directives_ordering
// ignore_for_file:argument_type_not_assignable, invalid_assignment
// ignore_for_file:prefer_single_quotes, prefer_generic_function_type_aliases
// ignore_for_file:comment_references
import 'package:intl/intl.dart';
import 'package:intl/message_lookup_by_library.dart';
import 'package:intl/src/intl_helpers.dart';
import 'messages_en.dart' deferred as messages_en;
import 'messages_zh.dart' deferred as messages_zh;
typedef Future<dynamic> LibraryLoader();
Map<String, LibraryLoader> _deferredLibraries = {
'en': messages_en.loadLibrary,
'zh': messages_zh.loadLibrary,
};
MessageLookupByLibrary? _findExact(String localeName) {
switch (localeName) {
case 'en':
return messages_en.messages;
case 'zh':
return messages_zh.messages;
default:
return null;
}
}
/// User programs should call this before using [localeName] for messages.
Future<bool> initializeMessages(String? localeName) async {
var availableLocale =
Intl.verifiedLocale(localeName, (locale) => _deferredLibraries[locale] != null, onFailure: (_) => null);
if (availableLocale == null) {
return Future.value(false);
}
var lib = _deferredLibraries[availableLocale];
await (lib == null ? Future.value(false) : lib());
initializeInternalMessageLookup(() => CompositeMessageLookup());
messageLookup.addLocale(availableLocale, _findGeneratedMessagesFor);
return Future.value(true);
}
bool _messagesExistFor(String locale) {
try {
return _findExact(locale) != null;
} catch (e) {
return false;
}
}
MessageLookupByLibrary? _findGeneratedMessagesFor(String locale) {
var actualLocale = Intl.verifiedLocale(locale, _messagesExistFor, onFailure: (_) => null);
if (actualLocale == null) return null;
return _findExact(actualLocale);
}
messages_en.dart ↓
// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
// This is a library that provides messages for a en locale. All the
// messages from the main program should be duplicated here with the same
// function name.
// @dart=2.12
// Ignore issues from commonly used lints in this file.
// ignore_for_file:unnecessary_brace_in_string_interps
// ignore_for_file:prefer_single_quotes,comment_references, directives_ordering
// ignore_for_file:annotate_overrides,prefer_generic_function_type_aliases
// ignore_for_file:unused_import, file_names
import 'package:intl/intl.dart';
import 'package:intl/message_lookup_by_library.dart';
final messages = MessageLookup();
typedef String? MessageIfAbsent(String? messageStr, List<Object>? args);
class MessageLookup extends MessageLookupByLibrary {
@override
String get localeName => 'en';
static m0(name) => "Hello ${name} from test";
@override
final Map<String, dynamic> messages = _notInlinedMessages(_notInlinedMessages);
static Map<String, dynamic> _notInlinedMessages(_) => {
'testArgsMessage': m0,
'testMessage': MessageLookupByLibrary.simpleMessage('This is a test message for localization.')
};
}
I solved this error by this:
class MultiCompositeMessageLookup extends CompositeMessageLookup {
@override
void addLocale(String localeName, Function findLocale) {
final canonical = Intl.canonicalizedLocale(localeName);
final newLocale = findLocale(canonical);
if (newLocale != null) {
final oldLocale = availableMessages[localeName];
if (oldLocale != null && newLocale != oldLocale) {
if (newLocale is! MessageLookupByLibrary) {
throw Exception('Merge locale messages failed, type ${newLocale.runtimeType} is not supported.');
}
if (oldLocale.messages is Map<String, Function> && newLocale.messages is! Map<String, Function>) {
final newMessages = newLocale.messages.map((key, value) => MapEntry(key, value as Function));
oldLocale.messages.addAll(newMessages);
} else {
oldLocale.messages.addAll(newLocale.messages);
}
return;
}
super.addLocale(localeName, findLocale);
}
}
}
With this code it solved the type error issue, I'm not sure there is an other way to solve this error.
if (oldLocale.messages is Map<String, Function> && newLocale.messages is! Map<String, Function>) {
final newMessages = newLocale.messages.map((key, value) => MapEntry(key, value as Function));
oldLocale.messages.addAll(newMessages);
} else {
oldLocale.messages.addAll(newLocale.messages);
}
What is the "Flutter intl plugin"? Is this an issue on their side?
I don't think so, intl_translation for dart only packages, intl_util for flutter application and packages. You can see the difference of generated codes between them:
intl_translation: ^0.19.0 ↓
...
@override
final Map<String, dynamic> messages = _notInlinedMessages(_notInlinedMessages);
static Map<String, dynamic> _notInlinedMessages(_) => {
...
Flutter intl plugin (version 1.18.4-2022.2) IntelliJ/Android Studio ↓
...
final messages = _notInlinedMessages(_notInlinedMessages);
static Map<String, Function> _notInlinedMessages(_) => <String, Function>{
...
Map<String, dynamic>
and Map<String, Function>
, that why MessageLookupByLibrary.messages.addAll()
throws the exception.
About intl_translation: ^0.19.0 and Flutter intl plugin (version 1.18.4-2022.2) on Android Studio.
intl_translation: ^0.19.0 generate messages_en.dart below:
and Flutter intl plugin generate messages_en.dart below:
The difference between them is method
_notInlinedMessages
and fieldmessages
, intl_translation: ^0.19.0 definedmessages
type asMap<String, dynamic>
and method_notInlinedMessages
returns type asMap<String, dynamic>
, but Flutter intl plugin defined method_notInlinedMessages
returns type asMap<String, Function>
, they should be in the same type, this cause the runtime exception when I callMessageLookupByLibrary.message.addAll
to merge these two messages map to one map.