| Index: packages/intl/lib/message_lookup_by_library.dart
|
| diff --git a/packages/intl/lib/message_lookup_by_library.dart b/packages/intl/lib/message_lookup_by_library.dart
|
| index 3b668d4cdf4f8eb58fd237072fb7bd15a3c235ed..7ef2a8d607504135b3caf7ab9f5d3c00bc0cf2e9 100644
|
| --- a/packages/intl/lib/message_lookup_by_library.dart
|
| +++ b/packages/intl/lib/message_lookup_by_library.dart
|
| @@ -2,113 +2,142 @@
|
| // for details. All rights reserved. Use of this source code is governed by a
|
| // BSD-style license that can be found in the LICENSE file.
|
|
|
| -/**
|
| - * Message/plural format library with locale support. This can have different
|
| - * implementations based on the mechanism for finding the localized versions
|
| - * of messages. This version expects them to be in a library named e.g.
|
| - * 'messages_en_US'. The prefix is set in the "initializeMessages" call, which
|
| - * must be made for a locale before any lookups can be done.
|
| - *
|
| - * See Intl class comment or `tests/message_format_test.dart` for more examples.
|
| - */
|
| +/// Message/plural format library with locale support. This can have different
|
| +/// implementations based on the mechanism for finding the localized versions of
|
| +/// messages. This version expects them to be in a library named e.g.
|
| +/// 'messages_en_US'. The prefix is set in the "initializeMessages" call, which
|
| +/// must be made for a locale before any lookups can be done.
|
| +///
|
| +/// See Intl class comment or `tests/message_format_test.dart` for more
|
| +/// examples.
|
| library message_lookup_by_library;
|
|
|
| -import 'intl.dart';
|
| +import 'package:intl/intl.dart';
|
| +import 'package:intl/src/intl_helpers.dart';
|
|
|
| -/**
|
| - * This is a message lookup mechanism that delegates to one of a collection
|
| - * of individual [MessageLookupByLibrary] instances.
|
| - */
|
| -class CompositeMessageLookup {
|
| - /** A map from locale names to the corresponding lookups. */
|
| +/// This is a message lookup mechanism that delegates to one of a collection
|
| +/// of individual [MessageLookupByLibrary] instances.
|
| +class CompositeMessageLookup implements MessageLookup {
|
| + /// A map from locale names to the corresponding lookups.
|
| Map<String, MessageLookupByLibrary> availableMessages = new Map();
|
|
|
| - /** Return true if we have a message lookup for [localeName]. */
|
| + /// Return true if we have a message lookup for [localeName].
|
| bool localeExists(localeName) => availableMessages.containsKey(localeName);
|
|
|
| - /**
|
| - * Look up the message with the given [name] and [locale] and return
|
| - * the translated version with the values in [args] interpolated.
|
| - * If nothing is found, return [message_str]. The [desc] and [examples]
|
| - * parameters are ignored
|
| - */
|
| - String lookupMessage(String message_str, [final String desc = '',
|
| - final Map examples = const {}, String locale, String name,
|
| - List<String> args, String meaning]) {
|
| - var actualLocale = (locale == null) ? Intl.getCurrentLocale() : locale;
|
| - // For this usage, if the locale doesn't exist for messages, just return
|
| - // it and we'll fall back to the original version.
|
| - var verifiedLocale = Intl.verifiedLocale(actualLocale, localeExists,
|
| + /// The last locale in which we looked up messages.
|
| + ///
|
| + /// If this locale matches the new one then we can skip looking up the
|
| + /// messages and assume they will be the same as last time.
|
| + String _lastLocale;
|
| +
|
| + /// Caches the last messages that we found
|
| + MessageLookupByLibrary _lastLookup;
|
| +
|
| + /// Look up the message with the given [name] and [locale] and return
|
| + /// the translated version with the values in [args] interpolated.
|
| + /// If nothing is found, return [message_str]. The [desc] and [examples]
|
| + /// parameters are ignored
|
| + String lookupMessage(
|
| + String message_str, String locale, String name, List args, String meaning,
|
| + {MessageIfAbsent ifAbsent: _useOriginal}) {
|
| + // If passed null, use the default.
|
| + var knownLocale = locale ?? Intl.getCurrentLocale();
|
| + var messages = (knownLocale == _lastLocale)
|
| + ? _lastLookup
|
| + : _lookupMessageCatalog(knownLocale);
|
| + // If we didn't find any messages for this locale, use the original string,
|
| + // faking interpolations if necessary.
|
| + if (messages == null) {
|
| + return ifAbsent(message_str, args);
|
| + }
|
| + return messages.lookupMessage(message_str, locale, name, args, meaning,
|
| + ifAbsent: ifAbsent);
|
| + }
|
| +
|
| + /// Find the right message lookup for [locale].
|
| + MessageLookupByLibrary _lookupMessageCatalog(String locale) {
|
| + var verifiedLocale = Intl.verifiedLocale(locale, localeExists,
|
| onFailure: (locale) => locale);
|
| - var messages = availableMessages[verifiedLocale];
|
| - if (messages == null) return message_str;
|
| - return messages.lookupMessage(
|
| - message_str, desc, examples, locale, name, args, meaning);
|
| + _lastLocale = locale;
|
| + _lastLookup = availableMessages[verifiedLocale];
|
| + return _lastLookup;
|
| }
|
|
|
| - /**
|
| - * If we do not already have a locale for [localeName] then
|
| - * [findLocale] will be called and the result stored as the lookup
|
| - * mechanism for that locale.
|
| - */
|
| - addLocale(String localeName, Function findLocale) {
|
| + /// If we do not already have a locale for [localeName] then
|
| + /// [findLocale] will be called and the result stored as the lookup
|
| + /// mechanism for that locale.
|
| + void addLocale(String localeName, Function findLocale) {
|
| 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;
|
| + }
|
| }
|
| }
|
| }
|
|
|
| -/**
|
| - * This provides an abstract class for messages looked up in generated code.
|
| - * Each locale will have a separate subclass of this class with its set of
|
| - * messages. See generate_localized.dart.
|
| - */
|
| +/// The default ifAbsent method, just returns the message string.
|
| +String _useOriginal(String message_str, List args) => message_str;
|
| +
|
| +/// This provides an abstract class for messages looked up in generated code.
|
| +/// Each locale will have a separate subclass of this class with its set of
|
| +/// messages. See generate_localized.dart.
|
| abstract class MessageLookupByLibrary {
|
| - /**
|
| - * Return the localized version of a message. We are passed the original
|
| - * version of the message, which consists of a
|
| - * [message_str] that will be translated, and which may be interpolated
|
| - * based on one or more variables, a [desc] providing a description of usage
|
| - * for the [message_str], and a map of [examples] for each data element to be
|
| - * substituted into the message.
|
| - *
|
| - * For example, if message="Hello, $name", then
|
| - * examples = {'name': 'Sparky'}. If not using the user's default locale, or
|
| - * if the locale is not easily detectable, explicitly pass [locale].
|
| - *
|
| - * The values of [desc] and [examples] are not used at run-time but are only
|
| - * made available to the translators, so they MUST be simple Strings available
|
| - * at compile time: no String interpolation or concatenation.
|
| - * The expected usage of this is inside a function that takes as parameters
|
| - * the variables used in the interpolated string.
|
| - *
|
| - * Ultimately, the information about the enclosing function and its arguments
|
| - * will be extracted automatically but for the time being it must be passed
|
| - * explicitly in the [name] and [args] arguments.
|
| - */
|
| - String lookupMessage(String message_str, [final String desc = '',
|
| - final Map examples = const {}, String locale, String name,
|
| - List<String> args, String meaning]) {
|
| - if (name == null) return message_str;
|
| - var function = this[name];
|
| - return function == null ? message_str : Function.apply(function, args);
|
| + /// Return the localized version of a message. We are passed the original
|
| + /// version of the message, which consists of a
|
| + /// [message_str] that will be translated, and which may be interpolated
|
| + /// based on one or more variables, a [desc] providing a description of usage
|
| + /// for the [message_str], and a map of [examples] for each data element to be
|
| + /// substituted into the message.
|
| + ///
|
| + /// For example, if message="Hello, $name", then
|
| + /// examples = {'name': 'Sparky'}. If not using the user's default locale, or
|
| + /// if the locale is not easily detectable, explicitly pass [locale].
|
| + ///
|
| + /// The values of [desc] and [examples] are not used at run-time but are only
|
| + /// made available to the translators, so they MUST be simple Strings
|
| + /// available at compile time: no String interpolation or concatenation. The
|
| + /// expected usage of this is inside a function that takes as parameters the
|
| + /// variables used in the interpolated string.
|
| + ///
|
| + /// Ultimately, the information about the enclosing function and its arguments
|
| + /// will be extracted automatically but for the time being it must be passed
|
| + /// explicitly in the [name] and [args] arguments.
|
| + String lookupMessage(
|
| + String message_str, String locale, String name, List args, String meaning,
|
| + {MessageIfAbsent ifAbsent}) {
|
| + var notFound = false;
|
| + var actualName = computeMessageName(name, message_str, meaning);
|
| + if (actualName == null) notFound = true;
|
| + var function = this[actualName];
|
| + notFound = notFound || (function == null);
|
| + if (notFound) {
|
| + return ifAbsent == null ? message_str : ifAbsent(message_str, args);
|
| + } else {
|
| + args = args ?? [];
|
| + return Function.apply(function, args);
|
| + }
|
| }
|
|
|
| - /** Return our message with the given name */
|
| + /// Return our message with the given name
|
| operator [](String messageName) => messages[messageName];
|
|
|
| - /**
|
| - * Subclasses should override this to return a list of their message
|
| - * functions.
|
| - */
|
| + /// Subclasses should override this to return a list of their message
|
| + /// functions.
|
| Map<String, Function> get messages;
|
|
|
| - /** Subclasses should override this to return their locale, e.g. 'en_US' */
|
| + /// Subclasses should override this to return their locale, e.g. 'en_US'
|
| String get localeName;
|
|
|
| toString() => localeName;
|
| +
|
| + /// Return a function that returns the given string.
|
| + /// An optimization for dart2js, used from the generated code.
|
| + static simpleMessage(translatedString) => () => translatedString;
|
| }
|
|
|