Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(200)

Side by Side Diff: pkg/intl/lib/message_lookup_local.dart

Issue 12733003: Adds facilities for extracting Intl.message calls and generating code from translations (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fixes from review comments, also made tests more robust, removed scheduled_test dependency Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 /**
6 * Message/plural format library with locale support. This can have different
7 * implementations based on the mechanism for finding the localized versions
8 * of messages. This version expects them to be in a library named e.g.
9 * 'messages_en_US'. The prefix is set in the [initializeMessages] call, which
10 * must be made for a locale before any lookups can be done.
11 *
12 * See Intl class comment or `tests/message_format_test.dart` for more examples.
13 */
14 //TODO(efortuna): documentation example involving the offset parameter?
15
16 library message_lookup_local;
17
18 import 'dart:async';
19 import 'intl.dart';
20 import 'src/intl_helpers.dart';
21 import 'dart:mirrors';
22
23 /**
24 * Initialize the user messages for [localeName]. Note that this is an ASYNC
25 * operation. This must be called before attempting to use messages in
26 * [localeName].
27 */
28 Future initializeMessages(localeName, [String source = 'messages_']) {
29 initializeInternalMessageLookup(
30 () => new MessageLookupLocal(localeName, source));
31 _initializeMessagesForLocale(localeName);
32 return new Future.immediate(null);
33 }
34
35 void _initializeMessagesForLocale(String localeName) {}
36
37 class MessageLookupLocal {
38 /** Prevent infinite recursion when looking up the message. */
39 bool _lookupInProgress = false;
40
41 /** The libraries we can look in for internationalization messages. */
42 Map<String, LibraryMirror> _libraries;
43
44 /** The prefix used to find libraries that contain localized messages.
45 * So, if this is 'messages_' we would look for messages for the locale
46 * 'pt_BR' in a library named 'messages_pt_BR'.
47 */
48 String _sourcePrefix;
49
50 /**
51 * Constructor. The [localeName] is of the form 'en' or 'en_US'.
52 *The [source] parameter defines the prefix that is used to find
53 * libraries that contain localized messages. So with the default value of
54 * 'messages_', we would look for messages for the locale 'pt_BR' in a library
55 * named 'messages_pt_BR'.
56 */
57 MessageLookupLocal(String localeName, this._sourcePrefix) {
58 _libraries = currentMirrorSystem().libraries;
59 }
60
61 /**
62 * Return true if the locale exists, or if it is null. The null case
63 * is interpreted to mean that we use the default locale.
64 */
65 bool localeExists(localeName) {
66 if (localeName == null) return false;
67 return _libraries['$_sourcePrefix$localeName'] != null;
68 }
69
70 /**
71 * Return the localized version of a message. We are passed the original
72 * version of the message, which consists of a
73 * [message_str] that will be translated, and which may be interpolated
74 * based on one or more variables, a [desc] providing a description of usage
75 * for the [message_str], and a map of [examples] for each data element to be
76 * substituted into the message.
77 *
78 * For example, if message="Hello, $name", then
79 * examples = {'name': 'Sparky'}. If not using the user's default locale, or
80 * if the locale is not easily detectable, explicitly pass [locale].
81 *
82 * The values of [desc] and [examples] are not used at run-time but are only
83 * made available to the translators, so they MUST be simple Strings available
84 * at compile time: no String interpolation or concatenation.
85 * The expected usage of this is inside a function that takes as parameters
86 * the variables used in the interpolated string.
87 *
88 * Ultimately, the information about the enclosing function and its arguments
89 * will be extracted automatically but for the time being it must be passed
90 * explicitly in the [name] and [args] arguments.
91 */
92 Future<String> lookupMessage(String message_str, [final String desc='',
93 final Map examples=const {}, String locale,
94 String name, List<String> args]) {
95 if (name == null) return new Future.immediate(message_str);
96 // The translations also make use of Intl.message, so we need to not
97 // recurse and just stop when we find the first substitution.
98 if (_lookupInProgress) return new Future.immediate(message_str);
99 _lookupInProgress = true;
100 var result;
101 try {
102 var actualLocale = (locale == null) ? Intl.getCurrentLocale() : locale;
103 // For this usage, if the locale doesn't exist for messages, just return
104 // it and we'll fall back to the original version.
105 var verifiedLocale =
106 Intl.verifiedLocale(
107 actualLocale,
108 localeExists,
109 onFailure: (locale)=>locale);
110 LibraryMirror messagesForThisLocale =
111 _libraries['$_sourcePrefix$verifiedLocale'];
112 if (messagesForThisLocale == null) {
113 return new Future.immediate(message_str);
114 }
115 MethodMirror localized = messagesForThisLocale.functions[name];
116 if (localized == null) return new Future.immediate(message_str);
117 result = messagesForThisLocale.invoke(localized.simpleName, args);
118 } finally {
119 _lookupInProgress = false;
120 }
121 return result.then((value) => value.reflectee);
122 }
123 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698