OLD | NEW |
(Empty) | |
| 1 Intl |
| 2 ==== |
| 3 |
| 4 This package provides internationalization and localization facilities, |
| 5 including message translation, plurals and genders, date/number formatting |
| 6 and parsing, and bidirectional text. |
| 7 |
| 8 ## General |
| 9 The most important library is [intl][intl_lib]. It defines the [Intl][Intl] |
| 10 class, with the default locale and methods for accessing most of the |
| 11 internationalization mechanisms. This library also defines the |
| 12 [DateFormat][DateFormat], [NumberFormat][NumberFormat], and |
| 13 [BidiFormatter][BidiFormatter] classes. |
| 14 |
| 15 ## Current locale |
| 16 |
| 17 The package has a single current locale, called [defaultLocale][defaultLocale]. |
| 18 Operations will use that locale unless told to do otherwise. |
| 19 |
| 20 You can explicitly set the global locale |
| 21 |
| 22 Intl.defaultLocale = 'pt_BR'; |
| 23 |
| 24 or get it from the browser |
| 25 |
| 26 import "package:intl/intl_browser.dart"; |
| 27 ... |
| 28 findSystemLocale().then(runTheRestOfMyProgram); |
| 29 |
| 30 To override the current locale for a particular operation, pass the operation |
| 31 to [withLocale][withLocale]. Note that this includes async tasks |
| 32 spawned from that operation, and that the argument to |
| 33 [withLocale][withLocale] |
| 34 will supercede the [defaultLocale][defaultLocale] while the operation |
| 35 is active. If you are using different locales within an application, |
| 36 the [withLocale][withLocale] operation may be preferable to setting |
| 37 [defaultLocale][defaultLocale]. |
| 38 |
| 39 Intl.withLocale('fr', () => print(myLocalizedMessage()); |
| 40 |
| 41 To specify the locale for an operation you can create a format object in |
| 42 a specific locale, pass in the locale as a parameter to methods, or |
| 43 set the default locale. |
| 44 |
| 45 ```dart |
| 46 var format = new DateFormat.yMd("ar"); |
| 47 var dateString = format.format(new DateTime.now()); |
| 48 ``` |
| 49 |
| 50 or |
| 51 |
| 52 ```dart |
| 53 print(myMessage(dateString, locale: 'ar'); |
| 54 ``` |
| 55 |
| 56 or |
| 57 |
| 58 ```dart |
| 59 Intl.defaultLocale = "es"' |
| 60 new DateFormat.jm().format(new DateTime.now()); |
| 61 ``` |
| 62 |
| 63 ## Initialization |
| 64 |
| 65 All the different types of locale data require an async initialization step |
| 66 to make |
| 67 sure the data is available. This reduces the size of the application by only |
| 68 loading the |
| 69 data that is actually required. |
| 70 |
| 71 Each different area of internationalization (messages, dates, numbers) requires |
| 72 a separate initialization process. That way, if the application only needs to |
| 73 format dates, it doesn't need to take the time or space to load up messages, |
| 74 numbers, or other things it may not need. |
| 75 |
| 76 With messages, there is also a need to import a file that won't exist until |
| 77 the code generation step has been run. This can be awkward, but can be worked |
| 78 around by creating a stub `messages_all.dart` file, running an empty translation |
| 79 step, or commenting out the import until translations are available. |
| 80 See "Extracting and Using Translated Messages" |
| 81 |
| 82 ## Messages |
| 83 |
| 84 Messages to be localized are written as functions that return the result of |
| 85 an [Intl.message][Intl.message] call. |
| 86 |
| 87 String continueMessage() => Intl.message( |
| 88 "Hit any key to continue", |
| 89 name: "continueMessage", |
| 90 args: [], |
| 91 desc: "Explains that we will not proceed further until " |
| 92 "the user presses a key"); |
| 93 print(continueMessage()); |
| 94 |
| 95 This provides, in addition to the basic message string, a name, a |
| 96 description for translators, the arguments used in the message, and |
| 97 examples. The `name` and `args` parameters are required, and must |
| 98 match the name (or ClassName_methodName) and arguments list of the |
| 99 function respectively. In the future we |
| 100 hope to have these provided automatically. |
| 101 |
| 102 This can be run in the program before any translation has been done, |
| 103 and will just return the message string. It can also be extracted to a |
| 104 file and then be made to return a translated version without modifying |
| 105 the original program. See "Extracting Messages" below for more |
| 106 details. |
| 107 |
| 108 The purpose of wrapping the message in a function is to allow it to |
| 109 have parameters which can be used in the result. The message string is |
| 110 allowed to use a restricted form of Dart string interpolation, where |
| 111 only the function's parameters can be used, and only in simple |
| 112 expressions. Local variables cannot be used, and neither can |
| 113 expressions with curly braces. Only the message string can have |
| 114 interpolation. The name, desc, args, and examples must be literals and |
| 115 not contain interpolations. Only the args parameter can refer to |
| 116 variables, and it should list exactly the function parameters. If you |
| 117 are passing numbers or dates and you want them formatted, you must do |
| 118 the formatting outside the function and pass the formatted string into |
| 119 the message. |
| 120 |
| 121 greetingMessage(name) => Intl.message( |
| 122 "Hello $name!", |
| 123 name: "greetingMessage", |
| 124 args: [name], |
| 125 desc: "Greet the user as they first open the application", |
| 126 examples: {'name': "Emily"}); |
| 127 print(greetingMessage('Dan')); |
| 128 |
| 129 There is one special class of complex expressions allowed in the |
| 130 message string, for plurals and genders. |
| 131 |
| 132 remainingEmailsMessage(int howMany, String userName) => |
| 133 Intl.message( |
| 134 "${Intl.plural(howMany, |
| 135 zero: 'There are no emails left for $userName.', |
| 136 one: 'There is one email left for $userName.', |
| 137 other: 'There are $howMany emails left for $userName.')}", |
| 138 name: "remainingEmailsMessage", |
| 139 args: [howMany, userName], |
| 140 desc: "How many emails remain after archiving.", |
| 141 examples: {'howMany': 42, 'userName': 'Fred'}); |
| 142 |
| 143 print(remainingEmailsMessage(1, "Fred")); |
| 144 |
| 145 However, since the typical usage for a plural or gender is for it to |
| 146 be at the top-level, we can also omit the [Intl.message][Intl.message] call and |
| 147 provide its parameters to the [Intl.plural][Intl.plural] call instead. |
| 148 |
| 149 remainingEmailsMessage(int howMany, String userName) => |
| 150 Intl.plural( |
| 151 howMany, |
| 152 zero: 'There are no emails left for $userName.', |
| 153 one: 'There is one email left for $userName.', |
| 154 other: 'There are $howMany emails left for $userName.'), |
| 155 name: "remainingEmailsMessage", |
| 156 args: [howMany, userName], |
| 157 desc: "How many emails remain after archiving.", |
| 158 examples: {'howMany': 42, 'userName': 'Fred'}); |
| 159 |
| 160 Similarly, there is an [Intl.gender][Intl.gender] message, and plurals |
| 161 and genders can be nested. |
| 162 |
| 163 notOnlineMessage(String userName, String userGender) => |
| 164 Intl.gender( |
| 165 userGender, |
| 166 male: '$userName is unavailable because he is not online.', |
| 167 female: '$userName is unavailable because she is not online.', |
| 168 other: '$userName is unavailable because they are not online'), |
| 169 name: "notOnlineMessage", |
| 170 args: [userName, userGender], |
| 171 desc: "The user is not available to hangout.", |
| 172 examples: {{'userGender': 'male', 'userName': 'Fred'}, |
| 173 {'userGender': 'female', 'userName' : 'Alice'}}); |
| 174 |
| 175 It's recommended to use complete sentences in the sub-messages to keep |
| 176 the structure as simple as possible for the translators. |
| 177 |
| 178 ## Extracting And Using Translated Messages |
| 179 |
| 180 When your program contains messages that need translation, these must |
| 181 be extracted from the program source, sent to human translators, and the |
| 182 results need to be incorporated. |
| 183 |
| 184 To extract messages, run the `extract_to_arb.dart` program. |
| 185 |
| 186 pub run intl:extract_to_arb --output-dir=target/directory |
| 187 my_program.dart more_of_my_program.dart |
| 188 |
| 189 This will produce a file `intl_messages.arb` with the messages from |
| 190 all of these programs. an [ARB] |
| 191 (https://code.google.com/p/arb/wiki/ApplicationResourceBundleSpecification) |
| 192 format file which can be used for input to translation tools like |
| 193 [Google Translator Toolkit](https://translate.google.com/toolkit/) |
| 194 The resulting translations can be used to generate a set of libraries |
| 195 using the `generate_from_arb.dart` program. |
| 196 |
| 197 This expects to receive a series of files, one per |
| 198 locale. |
| 199 |
| 200 pub run intl:generate_from_arb --generated_file_prefix=<prefix> |
| 201 <my_dart_files> <translated_ARB_files> |
| 202 |
| 203 This will generate Dart libraries, one per locale, which contain the |
| 204 translated versions. Your Dart libraries can import the primary file, |
| 205 named `<prefix>messages_all.dart`, and then call the initialization |
| 206 for a specific locale. Once that's done, any |
| 207 [Intl.message][Intl.message] calls made in the context of that locale |
| 208 will automatically print the translated version instead of the |
| 209 original. |
| 210 |
| 211 import "my_prefix_messages_all.dart"; |
| 212 ... |
| 213 initializeMessages("dk").then(printSomeMessages); |
| 214 |
| 215 Once the future returned from the initialization call returns, the |
| 216 message data is available. |
| 217 |
| 218 ## Number Formatting and Parsing |
| 219 |
| 220 To format a number, create a NumberFormat instance. |
| 221 |
| 222 var f = new NumberFormat("###.0#", "en_US"); |
| 223 print(f.format(12.345)); |
| 224 ==> 12.34 |
| 225 |
| 226 The locale parameter is optional. If omitted, then it will use the |
| 227 current locale. The format string is as described in |
| 228 [NumberFormat][NumberFormat] |
| 229 |
| 230 It's also possible to access the number symbol data for the current |
| 231 locale, which provides information as to the various separator |
| 232 characters, patterns, and other information used for formatting, as |
| 233 |
| 234 f.symbols |
| 235 |
| 236 Current known limitations are that the currency format will only print |
| 237 the name of the currency, and does not support currency symbols, and |
| 238 that the scientific format does not really agree with scientific |
| 239 notation. Number parsing is not yet implemented. |
| 240 |
| 241 Note that before doing any number formatting for a particular locale |
| 242 you must load the appropriate data by calling |
| 243 |
| 244 import 'package:intl/number_symbols_data_local.dart'; |
| 245 ... |
| 246 initializeNumberFormatting(localeName, null).then(formatNumbers); |
| 247 |
| 248 Once the future returned from the initialization call returns, the |
| 249 formatting data is available. Note that right now this includes all |
| 250 the data for a locales. We expect to make this use deferred loading to |
| 251 reduce code size. |
| 252 |
| 253 ## Date Formatting and Parsing |
| 254 |
| 255 To format a [DateTime][DateTime], create a [DateFormat][DateFormat] |
| 256 instance. These can be created using a set of commonly used skeletons |
| 257 taken from ICU/CLDR or using an explicit pattern. For details on the |
| 258 supported skeletons and patterns see [DateFormat][DateFormat]. |
| 259 |
| 260 new DateFormat.yMMMMEEEEd().format(aDateTime); |
| 261 ==> 'Wednesday, January 10, 2012' |
| 262 new DateFormat("EEEEE", "en_US").format(aDateTime); |
| 263 ==> 'Wednesday' |
| 264 new DateFormat("EEEEE", "ln").format(aDateTime); |
| 265 ==> 'mokɔlɔ mwa mísáto' |
| 266 |
| 267 You can also parse dates using the same skeletons or patterns. |
| 268 |
| 269 new DateFormat.yMd("en_US").parse("1/10/2012"); |
| 270 new DateFormat("Hms", "en_US").parse('14:23:01'); |
| 271 |
| 272 Skeletons can be combined, the main use being to print a full date and |
| 273 time, e.g. |
| 274 |
| 275 new DateFormat.yMEd().add_jms().format(new DateTime.now()); |
| 276 ==> 'Thu, 5/23/2013 10:21:47 AM' |
| 277 |
| 278 Known limitations: Time zones are not yet supported. Dart |
| 279 [DateTime][DateTime] objects don't have a time zone, so are either |
| 280 local or UTC. Formatting and parsing Durations is not yet implemented. |
| 281 |
| 282 Note that before doing any DateTime formatting for a particular |
| 283 locale, you must load the appropriate data by calling. |
| 284 |
| 285 import 'package:intl/date_symbol_data_local.dart'; |
| 286 ... |
| 287 initializeDateFormatting("de_DE", null).then(formatDates); |
| 288 |
| 289 Once the future returned from the initialization call returns, the |
| 290 formatting data is available. |
| 291 |
| 292 There are other mechanisms for loading the date formatting data |
| 293 implemented, but we expect to deprecate those in favor of having the |
| 294 data in a library as in the above, and using deferred loading to only |
| 295 load the portions that are needed. For the time being, this will |
| 296 include all of the data, which will increase code size. |
| 297 |
| 298 ## Bidirectional Text |
| 299 |
| 300 The class [BidiFormatter][BidiFormatter] provides utilities for |
| 301 working with Bidirectional text. We can wrap the string with unicode |
| 302 directional indicator characters or with an HTML span to indicate |
| 303 direction. The direction can be specified with the |
| 304 [RTL][BidiFormatter.RTL] and [LTR][BidiFormatter.LTR] constructors, or |
| 305 detected from the text. |
| 306 |
| 307 new BidiFormatter.RTL().wrapWithUnicode('xyz'); |
| 308 new BidiFormatter.RTL().wrapWithSpan('xyz'); |
| 309 |
| 310 [intl_lib]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/intl
/intl |
| 311 [Intl]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/intl |
| 312 [DateFormat]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/in
tl/intl.DateFormat |
| 313 [NumberFormat]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/
intl/intl.NumberFormat |
| 314 [withLocale]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/in
tl/intl.Intl#id_withLocale |
| 315 [defaultLocale]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer
/intl/intl.Intl#id_defaultLocale |
| 316 [Intl.message]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/
intl/intl.Intl#id_message |
| 317 [Intl.plural]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/i
ntl/intl.Intl#id_plural |
| 318 [Intl.gender]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/i
ntl/intl.Intl#id_gender |
| 319 [DateTime]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/dart
:core.DateTime |
| 320 [BidiFormatter]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer
/intl/intl.BidiFormatter |
| 321 [BidiFormatter.RTL]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-vi
ewer/intl/intl.BidiFormatter#id_BidiFormatter-RTL |
| 322 [BidiFormatter.LTR]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-vi
ewer/intl/intl.BidiFormatter#id_BidiFormatter-LTR |
OLD | NEW |