Chromium Code Reviews| Index: pkg/intl/message_lookup_local.dart |
| =================================================================== |
| --- pkg/intl/message_lookup_local.dart (revision 12066) |
| +++ pkg/intl/message_lookup_local.dart (working copy) |
| @@ -3,7 +3,11 @@ |
| // BSD-style license that can be found in the LICENSE file. |
| /** |
| - * Message/plural format library with locale support. |
| + * Message/plural format library with locale support. This can have different |
|
Emily Fortuna
2012/09/12 01:23:48
can we have a skeleton at least for the nonlocal v
Alan Knight
2012/09/12 20:58:20
I'm thinking that the skeleton should be the same
|
| + * 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. |
| * |
| * |
| * _message example: |
| @@ -34,43 +38,88 @@ |
| */ |
| //TODO(efortuna): documentation example involving the offset parameter? |
| -class IntlMessage { |
| +#library('message_lookup_local'); |
| - /** String describing the use case for this message. */ |
| - String _messageDescription; |
| +#import('intl.dart'); |
|
Emily Fortuna
2012/09/12 01:23:48
documentation nit: this was sourced by intl.dart s
Alan Knight
2012/09/12 20:58:20
We can't source it if we have multiple incompatibl
|
| +#import('dart:mirrors'); |
| - /** |
| - * String that contains the message to be displayed. It may contain |
| - * placeholders in the form of string interpolated items (ie 'hello$foo') that |
| - * will be substituted in to complete the message. |
| - * See tests/message_format_test.dart for more examples. |
| +/** |
| + * Initialize the user messages for [localeName]. Note that this is an ASYNC |
| + * operation. This must be called before attempting to use messages in |
| + * [localeName]. |
| + */ |
| +Future initializeMessages(localeName, [String source = 'messages_']) { |
| + initializeInternalMessageLookup( |
| + () => new MessageLookupLocal(localeName, source)); |
| + initializeIndividualLocaleMessageFormatting(localeName); |
| + return new Future.immediate(null); |
| +} |
| + |
| +void initializeIndividualLocaleMessageFormatting(String localeName) {} |
| + |
| +class MessageLookupLocal { |
| + /** Prevent infinite recursion when looking up the message. */ |
| + bool _lookupInProgress = false; |
| + |
| + /** The libraries we can look in for internationalization messages. */ |
| + Map<String, LibraryMirror> libraries; |
| + |
| + /** The prefix used to find libraries that contain localized messages. |
| + * So, if this is 'messages_' we would look for messages for the locale |
| + * 'pt_BR' in a library named 'messages_pt_BR'. |
| */ |
| - String _message; |
| + String source; |
|
Emily Fortuna
2012/09/12 01:23:48
call it sourcePrefix then.
Alan Knight
2012/09/12 20:58:20
Done.
|
| /** |
| - * String indicating the locale code with which the message is to be |
| - * formatted (such as en-CA). |
| + * Constructor. The [localeName] is of the form 'en' or 'en_US'. |
| + *The [source] parameter defines the prefix that is used to find |
| + * libraries that contain localized messages. So with the default value of |
| + * 'messages_', we would look for messages for the locale 'pt_BR' in a library |
| + * named 'messages_pt_BR'. |
| */ |
| - String _languageCode; |
| + MessageLookupLocal(String localeName, this.source) { |
| + libraries = currentMirrorSystem().libraries; |
| + } |
| - /** Examples of the placeholders used in the message string. */ |
| - Map _messageExamples; |
| - |
| /** |
| - * Accepts a String [_message] that contains the message (that |
| - * will be internationalized). A String [_messageDescription] describes the |
| - * use case for this string in the program, and [examples] provides a map of |
| - * examples for the items (if any) to be subsituted into [_message]. |
| - * It also optionally accepts a [_languageCode] to specify the particular |
| - * language to return content in (necessary if the Dart code is not running in |
| - * a browser). The values of [desc] and [examples] *must* be |
| - * simple Strings available at compile time: no String interpolation or |
| - * concatenation. |
| + * 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 |
|
Emily Fortuna
2012/09/12 01:23:48
make your "for example" section a new paragraph, s
Alan Knight
2012/09/12 20:58:20
Done.
|
| + * 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. |
| */ |
| - IntlMessage(this._message, [final String desc='', final Map examples=const {}, |
| - final String locale='']) { |
| - this._messageDescription = desc; |
| - this._messageExamples = examples; |
| - this._languageCode = locale; |
| + String lookupMessage(String message_str, [final String desc='', |
| + final Map examples=const {}, String locale, |
| + String name, List<String> args]) { |
| + if (name == null) return message_str; |
| + // The translations also make use of Intl.message, so we need to not |
| + // recurse and just stop when we find the first substitution. |
| + if (_lookupInProgress) return message_str; |
| + _lookupInProgress = true; |
| + var result; |
| + try { |
| + // TODO(alanknight): Look up alternate forms, e.g. en for en_US |
| + var actualLocale = (locale == null) ? Intl.getCurrentLocale() : locale; |
| + LibraryMirror messagesForThisLocale = libraries['$source$actualLocale']; |
| + if (messagesForThisLocale == null) return message_str; |
| + MethodMirror localized = messagesForThisLocale.functions[name]; |
| + if (localized == null) return message_str; |
| + result = messagesForThisLocale.invoke(localized.simpleName, args); |
| + } |
| + finally { |
| + _lookupInProgress = false; |
| + } |
| + return result.value.reflectee; |
| } |
| -} |
| +} |