Index: packages/intl/README.md |
diff --git a/packages/intl/README.md b/packages/intl/README.md |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e1fcfc0a5121d6f1efdbffc79e8cd884c0c56efb |
--- /dev/null |
+++ b/packages/intl/README.md |
@@ -0,0 +1,322 @@ |
+Intl |
+==== |
+ |
+This package provides internationalization and localization facilities, |
+including message translation, plurals and genders, date/number formatting |
+and parsing, and bidirectional text. |
+ |
+## General |
+The most important library is [intl][intl_lib]. It defines the [Intl][Intl] |
+class, with the default locale and methods for accessing most of the |
+internationalization mechanisms. This library also defines the |
+[DateFormat][DateFormat], [NumberFormat][NumberFormat], and |
+[BidiFormatter][BidiFormatter] classes. |
+ |
+## Current locale |
+ |
+The package has a single current locale, called [defaultLocale][defaultLocale]. |
+Operations will use that locale unless told to do otherwise. |
+ |
+You can explicitly set the global locale |
+ |
+ Intl.defaultLocale = 'pt_BR'; |
+ |
+or get it from the browser |
+ |
+ import "package:intl/intl_browser.dart"; |
+ ... |
+ findSystemLocale().then(runTheRestOfMyProgram); |
+ |
+To override the current locale for a particular operation, pass the operation |
+to [withLocale][withLocale]. Note that this includes async tasks |
+spawned from that operation, and that the argument to |
+[withLocale][withLocale] |
+will supercede the [defaultLocale][defaultLocale] while the operation |
+is active. If you are using different locales within an application, |
+the [withLocale][withLocale] operation may be preferable to setting |
+[defaultLocale][defaultLocale]. |
+ |
+ Intl.withLocale('fr', () => print(myLocalizedMessage()); |
+ |
+To specify the locale for an operation you can create a format object in |
+a specific locale, pass in the locale as a parameter to methods, or |
+set the default locale. |
+ |
+```dart |
+var format = new DateFormat.yMd("ar"); |
+var dateString = format.format(new DateTime.now()); |
+``` |
+ |
+or |
+ |
+```dart |
+print(myMessage(dateString, locale: 'ar'); |
+``` |
+ |
+or |
+ |
+```dart |
+Intl.defaultLocale = "es"' |
+new DateFormat.jm().format(new DateTime.now()); |
+``` |
+ |
+## Initialization |
+ |
+All the different types of locale data require an async initialization step |
+to make |
+sure the data is available. This reduces the size of the application by only |
+loading the |
+data that is actually required. |
+ |
+Each different area of internationalization (messages, dates, numbers) requires |
+a separate initialization process. That way, if the application only needs to |
+format dates, it doesn't need to take the time or space to load up messages, |
+numbers, or other things it may not need. |
+ |
+With messages, there is also a need to import a file that won't exist until |
+the code generation step has been run. This can be awkward, but can be worked |
+around by creating a stub `messages_all.dart` file, running an empty translation |
+step, or commenting out the import until translations are available. |
+See "Extracting and Using Translated Messages" |
+ |
+## Messages |
+ |
+Messages to be localized are written as functions that return the result of |
+an [Intl.message][Intl.message] call. |
+ |
+ String continueMessage() => Intl.message( |
+ "Hit any key to continue", |
+ name: "continueMessage", |
+ args: [], |
+ desc: "Explains that we will not proceed further until " |
+ "the user presses a key"); |
+ print(continueMessage()); |
+ |
+This provides, in addition to the basic message string, a name, a |
+description for translators, the arguments used in the message, and |
+examples. The `name` and `args` parameters are required, and must |
+match the name (or ClassName_methodName) and arguments list of the |
+function respectively. In the future we |
+hope to have these provided automatically. |
+ |
+This can be run in the program before any translation has been done, |
+and will just return the message string. It can also be extracted to a |
+file and then be made to return a translated version without modifying |
+the original program. See "Extracting Messages" below for more |
+details. |
+ |
+The purpose of wrapping the message in a function is to allow it to |
+have parameters which can be used in the result. The message string is |
+allowed to use a restricted form of Dart string interpolation, where |
+only the function's parameters can be used, and only in simple |
+expressions. Local variables cannot be used, and neither can |
+expressions with curly braces. Only the message string can have |
+interpolation. The name, desc, args, and examples must be literals and |
+not contain interpolations. Only the args parameter can refer to |
+variables, and it should list exactly the function parameters. If you |
+are passing numbers or dates and you want them formatted, you must do |
+the formatting outside the function and pass the formatted string into |
+the message. |
+ |
+ greetingMessage(name) => Intl.message( |
+ "Hello $name!", |
+ name: "greetingMessage", |
+ args: [name], |
+ desc: "Greet the user as they first open the application", |
+ examples: {'name': "Emily"}); |
+ print(greetingMessage('Dan')); |
+ |
+There is one special class of complex expressions allowed in the |
+message string, for plurals and genders. |
+ |
+ remainingEmailsMessage(int howMany, String userName) => |
+ Intl.message( |
+ "${Intl.plural(howMany, |
+ zero: 'There are no emails left for $userName.', |
+ one: 'There is one email left for $userName.', |
+ other: 'There are $howMany emails left for $userName.')}", |
+ name: "remainingEmailsMessage", |
+ args: [howMany, userName], |
+ desc: "How many emails remain after archiving.", |
+ examples: {'howMany': 42, 'userName': 'Fred'}); |
+ |
+ print(remainingEmailsMessage(1, "Fred")); |
+ |
+However, since the typical usage for a plural or gender is for it to |
+be at the top-level, we can also omit the [Intl.message][Intl.message] call and |
+provide its parameters to the [Intl.plural][Intl.plural] call instead. |
+ |
+ remainingEmailsMessage(int howMany, String userName) => |
+ Intl.plural( |
+ howMany, |
+ zero: 'There are no emails left for $userName.', |
+ one: 'There is one email left for $userName.', |
+ other: 'There are $howMany emails left for $userName.'), |
+ name: "remainingEmailsMessage", |
+ args: [howMany, userName], |
+ desc: "How many emails remain after archiving.", |
+ examples: {'howMany': 42, 'userName': 'Fred'}); |
+ |
+Similarly, there is an [Intl.gender][Intl.gender] message, and plurals |
+and genders can be nested. |
+ |
+ notOnlineMessage(String userName, String userGender) => |
+ Intl.gender( |
+ userGender, |
+ male: '$userName is unavailable because he is not online.', |
+ female: '$userName is unavailable because she is not online.', |
+ other: '$userName is unavailable because they are not online'), |
+ name: "notOnlineMessage", |
+ args: [userName, userGender], |
+ desc: "The user is not available to hangout.", |
+ examples: {{'userGender': 'male', 'userName': 'Fred'}, |
+ {'userGender': 'female', 'userName' : 'Alice'}}); |
+ |
+It's recommended to use complete sentences in the sub-messages to keep |
+the structure as simple as possible for the translators. |
+ |
+## Extracting And Using Translated Messages |
+ |
+When your program contains messages that need translation, these must |
+be extracted from the program source, sent to human translators, and the |
+results need to be incorporated. |
+ |
+To extract messages, run the `extract_to_arb.dart` program. |
+ |
+ pub run intl:extract_to_arb --output-dir=target/directory |
+ my_program.dart more_of_my_program.dart |
+ |
+This will produce a file `intl_messages.arb` with the messages from |
+all of these programs. an [ARB] |
+(https://code.google.com/p/arb/wiki/ApplicationResourceBundleSpecification) |
+format file which can be used for input to translation tools like |
+[Google Translator Toolkit](https://translate.google.com/toolkit/) |
+The resulting translations can be used to generate a set of libraries |
+using the `generate_from_arb.dart` program. |
+ |
+This expects to receive a series of files, one per |
+locale. |
+ |
+ pub run intl:generate_from_arb --generated_file_prefix=<prefix> |
+ <my_dart_files> <translated_ARB_files> |
+ |
+This will generate Dart libraries, one per locale, which contain the |
+translated versions. Your Dart libraries can import the primary file, |
+named `<prefix>messages_all.dart`, and then call the initialization |
+for a specific locale. Once that's done, any |
+[Intl.message][Intl.message] calls made in the context of that locale |
+will automatically print the translated version instead of the |
+original. |
+ |
+ import "my_prefix_messages_all.dart"; |
+ ... |
+ initializeMessages("dk").then(printSomeMessages); |
+ |
+Once the future returned from the initialization call returns, the |
+message data is available. |
+ |
+## Number Formatting and Parsing |
+ |
+To format a number, create a NumberFormat instance. |
+ |
+ var f = new NumberFormat("###.0#", "en_US"); |
+ print(f.format(12.345)); |
+ ==> 12.34 |
+ |
+The locale parameter is optional. If omitted, then it will use the |
+current locale. The format string is as described in |
+[NumberFormat][NumberFormat] |
+ |
+It's also possible to access the number symbol data for the current |
+locale, which provides information as to the various separator |
+characters, patterns, and other information used for formatting, as |
+ |
+ f.symbols |
+ |
+Current known limitations are that the currency format will only print |
+the name of the currency, and does not support currency symbols, and |
+that the scientific format does not really agree with scientific |
+notation. Number parsing is not yet implemented. |
+ |
+Note that before doing any number formatting for a particular locale |
+you must load the appropriate data by calling |
+ |
+ import 'package:intl/number_symbols_data_local.dart'; |
+ ... |
+ initializeNumberFormatting(localeName, null).then(formatNumbers); |
+ |
+Once the future returned from the initialization call returns, the |
+formatting data is available. Note that right now this includes all |
+the data for a locales. We expect to make this use deferred loading to |
+reduce code size. |
+ |
+## Date Formatting and Parsing |
+ |
+To format a [DateTime][DateTime], create a [DateFormat][DateFormat] |
+instance. These can be created using a set of commonly used skeletons |
+taken from ICU/CLDR or using an explicit pattern. For details on the |
+supported skeletons and patterns see [DateFormat][DateFormat]. |
+ |
+ new DateFormat.yMMMMEEEEd().format(aDateTime); |
+ ==> 'Wednesday, January 10, 2012' |
+ new DateFormat("EEEEE", "en_US").format(aDateTime); |
+ ==> 'Wednesday' |
+ new DateFormat("EEEEE", "ln").format(aDateTime); |
+ ==> 'mokɔlɔ mwa mísáto' |
+ |
+You can also parse dates using the same skeletons or patterns. |
+ |
+ new DateFormat.yMd("en_US").parse("1/10/2012"); |
+ new DateFormat("Hms", "en_US").parse('14:23:01'); |
+ |
+Skeletons can be combined, the main use being to print a full date and |
+time, e.g. |
+ |
+ new DateFormat.yMEd().add_jms().format(new DateTime.now()); |
+ ==> 'Thu, 5/23/2013 10:21:47 AM' |
+ |
+Known limitations: Time zones are not yet supported. Dart |
+[DateTime][DateTime] objects don't have a time zone, so are either |
+local or UTC. Formatting and parsing Durations is not yet implemented. |
+ |
+Note that before doing any DateTime formatting for a particular |
+locale, you must load the appropriate data by calling. |
+ |
+ import 'package:intl/date_symbol_data_local.dart'; |
+ ... |
+ initializeDateFormatting("de_DE", null).then(formatDates); |
+ |
+Once the future returned from the initialization call returns, the |
+formatting data is available. |
+ |
+There are other mechanisms for loading the date formatting data |
+implemented, but we expect to deprecate those in favor of having the |
+data in a library as in the above, and using deferred loading to only |
+load the portions that are needed. For the time being, this will |
+include all of the data, which will increase code size. |
+ |
+## Bidirectional Text |
+ |
+The class [BidiFormatter][BidiFormatter] provides utilities for |
+working with Bidirectional text. We can wrap the string with unicode |
+directional indicator characters or with an HTML span to indicate |
+direction. The direction can be specified with the |
+[RTL][BidiFormatter.RTL] and [LTR][BidiFormatter.LTR] constructors, or |
+detected from the text. |
+ |
+ new BidiFormatter.RTL().wrapWithUnicode('xyz'); |
+ new BidiFormatter.RTL().wrapWithSpan('xyz'); |
+ |
+[intl_lib]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/intl/intl |
+[Intl]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/intl |
+[DateFormat]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/intl/intl.DateFormat |
+[NumberFormat]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/intl/intl.NumberFormat |
+[withLocale]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/intl/intl.Intl#id_withLocale |
+[defaultLocale]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/intl/intl.Intl#id_defaultLocale |
+[Intl.message]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/intl/intl.Intl#id_message |
+[Intl.plural]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/intl/intl.Intl#id_plural |
+[Intl.gender]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/intl/intl.Intl#id_gender |
+[DateTime]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/dart:core.DateTime |
+[BidiFormatter]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/intl/intl.BidiFormatter |
+[BidiFormatter.RTL]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/intl/intl.BidiFormatter#id_BidiFormatter-RTL |
+[BidiFormatter.LTR]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/intl/intl.BidiFormatter#id_BidiFormatter-LTR |