Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2013, 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 * This provides utilities for generating localized versions of | |
| 7 * messages. It does not stand alone, but expects to be given | |
| 8 * TranslatedMessage objects and generate code for a particular locale | |
| 9 * based on them. | |
| 10 * | |
| 11 * An example of usage can be found | |
| 12 * in test/message_extract/generate_from_json.dart | |
| 13 */ | |
| 14 library generate_localized; | |
| 15 | |
| 16 import 'extract_messages.dart'; | |
| 17 import 'src/intl_message.dart'; | |
| 18 import 'dart:io'; | |
| 19 import 'package:pathos/path.dart' as path; | |
| 20 | |
| 21 /** | |
| 22 * A list of all the locales for which we have translations. Code that does | |
| 23 * the reading of translations should add to this. | |
| 24 */ | |
| 25 List<String> allLocales = []; | |
| 26 | |
| 27 /** | |
| 28 * This represents a message and its translation. We assume that the translation | |
| 29 * has some identifier that allows us to figure out the original message it | |
| 30 * corresponds to, and that it may want to transform the translated text in | |
| 31 * some way, e.g. to turn whatever format the translation uses for variables | |
| 32 * into a Dart string interpolation. Specific translation | |
| 33 * mechanisms are expected to subclass this. | |
| 34 */ | |
| 35 abstract class TranslatedMessage { | |
| 36 /** The identifier for this message. In the simplest case, this is the name.*/ | |
| 37 var id; | |
| 38 | |
| 39 String translatedString; | |
| 40 IntlMessage originalMessage; | |
| 41 TranslatedMessage(this.id, this.translatedString); | |
| 42 | |
| 43 get message => translatedString; | |
|
Emily Fortuna
2013/03/13 18:54:43
please list the return type for getters/functions.
Alan Knight
2013/03/14 17:49:05
Done.
| |
| 44 } | |
| 45 | |
| 46 /** | |
| 47 * We can't use a hyphen in a Dart library name, so convert the locale | |
| 48 * separator to an underscore. | |
| 49 */ | |
| 50 asLibraryName(String x) => x.replaceAll('-', '_'); | |
| 51 | |
| 52 /** | |
| 53 * Generate a file messages_<locale>.dart for the [translations] in | |
| 54 * [locale]. | |
| 55 */ | |
| 56 generateIndividualMessageFile(String locale, | |
| 57 Iterable<TranslatedMessage> translations) { | |
| 58 var result = new StringBuffer(); | |
| 59 locale = new IntlMessage().escapeAndValidate(locale, locale); | |
| 60 result.write(prologue(locale)); | |
| 61 for (var each in translations) { | |
| 62 var message = each.originalMessage; | |
| 63 if (each.message != null) { | |
| 64 message.addTranslation(locale, each.message); | |
| 65 } | |
| 66 } | |
| 67 var sorted = translations.where((each) => each.message != null).toList(); | |
| 68 sorted.sort((a, b) => | |
| 69 a.originalMessage.name.compareTo(b.originalMessage.name)); | |
| 70 for (var each in sorted) { | |
| 71 result.write(" "); | |
| 72 result.write(each.originalMessage.toCode(locale)); | |
| 73 result.write("\n\n"); | |
| 74 } | |
| 75 result.write("\n final messages = const {\n"); | |
| 76 var entries = sorted | |
| 77 .map((translation) => translation.originalMessage.name) | |
| 78 .map((name) => " \"$name\" : $name"); | |
| 79 result.write(entries.join(",\n")); | |
| 80 result.write("\n };\n}"); | |
| 81 | |
| 82 ifNull(x, y) => (x == null) ? y : x; | |
| 83 var target = ifNull(Platform.environment["INTL_MESSAGE_OUTPUT"], '.'); | |
| 84 var output = new File(path.join(target, "messages_$locale.dart")); | |
| 85 output.writeAsStringSync(result.toString()); | |
| 86 } | |
| 87 | |
| 88 /** | |
| 89 * This returns the mostly constant string used in [generated] for the | |
| 90 * beginning of the file, parameterized by [locale]. | |
| 91 */ | |
| 92 prologue(String locale) => """ | |
| 93 /** | |
| 94 * DO NOT EDIT. This is code generated via pkg/intl/generate_localized.dart | |
| 95 * This is a library that provides messages for a $locale locale. All the | |
| 96 * messages from the main program should be duplicated here with the same | |
| 97 * function name. | |
| 98 */ | |
| 99 | |
| 100 library messages_${locale.replaceAll('-','_')}; | |
| 101 import 'package:intl/intl.dart'; | |
| 102 import 'package:intl/message_lookup_by_library.dart'; | |
| 103 | |
| 104 final messages = new MessageLookup(); | |
| 105 | |
| 106 class MessageLookup extends MessageLookupByLibrary { | |
| 107 | |
| 108 get localeName => '$locale'; | |
| 109 """; | |
| 110 | |
| 111 /** | |
| 112 * This section generates the messages_all.dart file based on the list of | |
| 113 * [allLocales]. | |
| 114 */ | |
| 115 generateMainImportFile() { | |
| 116 var output = new StringBuffer(); | |
| 117 output.write(mainPrologue); | |
| 118 for (var each in allLocales) { | |
| 119 output.write("import 'messages_$each.dart' as ${asLibraryName(each)};\n"); | |
| 120 } | |
| 121 output.write( | |
| 122 "\nMessageLookupByLibrary _findExact(localeName) {\n" | |
| 123 " switch (localeName) {\n"); | |
| 124 for (var each in allLocales) { | |
| 125 output.write( | |
| 126 " case '$each' : return ${asLibraryName(each)}.messages;\n"); | |
| 127 } | |
| 128 output.write(closing); | |
| 129 return output.toString(); | |
| 130 } | |
| 131 | |
| 132 /** | |
| 133 * Constant string used in [generateMainImportFile] for the beginning of the | |
| 134 * file. | |
| 135 */ | |
| 136 const mainPrologue = """ | |
| 137 /** | |
| 138 * DO NOT EDIT. This is code generated via pkg/intl/generate_localized.dart | |
| 139 * This is a library that looks up messages for specific locales by | |
| 140 * delegating to the appropriate library. | |
| 141 */ | |
| 142 | |
| 143 library messages_all; | |
| 144 | |
| 145 import 'dart:async'; | |
| 146 import 'package:intl/message_lookup_by_library.dart'; | |
| 147 import 'package:intl/src/intl_helpers.dart'; | |
| 148 import 'package:intl/intl.dart'; | |
| 149 | |
| 150 """; | |
| 151 | |
| 152 /** | |
| 153 * Constant string used in [generateMainImportfile] as the end of the file. | |
| 154 */ | |
| 155 const closing = """ | |
| 156 default: return null; | |
| 157 } | |
| 158 } | |
| 159 | |
| 160 /** User programs should call this before using [localeName] for messages.*/ | |
| 161 initializeMessages(localeName) { | |
| 162 initializeInternalMessageLookup(() => new CompositeMessageLookup()); | |
| 163 messageLookup.addLocale(localeName, _findGeneratedMessagesFor); | |
| 164 return new Future.immediate(null); | |
| 165 } | |
| 166 | |
| 167 MessageLookupByLibrary _findGeneratedMessagesFor(locale) { | |
| 168 var actualLocale = Intl.verifiedLocale(locale, (x) => _findExact(x) != null); | |
| 169 if (actualLocale == null) return null; | |
| 170 return _findExact(actualLocale); | |
| 171 } | |
| 172 """; | |
| OLD | NEW |