Roll forward of cl/148686729 with a workaround for analyzer crashing
Cloned from CL 148686729 by 'g4 patch'.
Original change by alanknight@alanknight:moreerrors:1055:citc on 2017/02/27 13:27:47.
Add a way to detect Intl.messages called before locale is initialized.
That might be valid, but if the result is cached the cached version will be untranslated.
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=149009079
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 78462d1..de06b47 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,9 @@
* Remove the cacheBlocker parameter from HttpRequestDataReader
* Optimize padding numbers when printing
* Remove the out of date example directory
+ * Add a facility to check if messages are being called before locale
+ initialization, which can lead to errors if the results are being cached. See
+ UninitializedLocaleData.throwOnFallback.
## 0.14.0
* MAJOR BREAKING CHANGE! Remove message extraction and code generation into a
diff --git a/lib/src/intl_helpers.dart b/lib/src/intl_helpers.dart
index 9d9cb5f..a54609a 100644
--- a/lib/src/intl_helpers.dart
+++ b/lib/src/intl_helpers.dart
@@ -19,15 +19,45 @@
class UninitializedLocaleData<F> implements MessageLookup {
final String message;
final F fallbackData;
- const UninitializedLocaleData(this.message, this.fallbackData);
+ UninitializedLocaleData(this.message, this.fallbackData);
operator [](String key) =>
(key == 'en_US') ? fallbackData : _throwException();
- String lookupMessage(String message_str, String locale, String name,
- List args, String meaning,
- {MessageIfAbsent ifAbsent}) =>
- message_str;
+ /// If a message is looked up before any locale initialization, record it,
+ /// and throw an exception with that information once the locale is
+ /// initialized.
+ ///
+ /// Set this during development to find issues with race conditions between
+ /// message caching and locale initialization. If the results of Intl.message
+ /// calls aren't being cached, then this won't help.
+ ///
+ /// There's nothing that actually sets this, so checking this requires
+ /// patching the code here.
+ static final bool throwOnFallback = false;
+
+ /// The messages that were called before the locale was initialized.
+ List<String> _badMessages = [];
+
+ void _reportErrors() {
+ if (throwOnFallback && _badMessages.length > 0) {
+ throw new StateError(
+ "The following messages were called before locale initialization:"
+ " $_uninitializedMessages");
+ }
+ }
+
+ String get _uninitializedMessages =>
+ (_badMessages.toSet().toList()..sort()).join("\n ");
+
+ String lookupMessage(
+ String message_str, String locale, String name, List args, String meaning,
+ {MessageIfAbsent ifAbsent}) {
+ if (throwOnFallback) {
+ _badMessages.add(name ?? message_str);
+ }
+ return message_str;
+ }
/// Given an initial locale or null, returns the locale that will be used
/// for messages.
@@ -67,13 +97,15 @@
/// by the implementing package so that we're not dependent on its
/// implementation.
MessageLookup messageLookup =
- const UninitializedLocaleData('initializeMessages(<locale>)', null);
+ new UninitializedLocaleData('initializeMessages(<locale>)', null);
/// Initialize the message lookup mechanism. This is for internal use only.
/// User applications should import `message_lookup_by_library.dart` and call
/// `initializeMessages`
void initializeInternalMessageLookup(Function lookupFunction) {
if (messageLookup is UninitializedLocaleData) {
+ // This line has to be precisely this way to work around an analyzer crash.
+ (messageLookup as UninitializedLocaleData)._reportErrors();
messageLookup = lookupFunction();
}
}