OLD | NEW |
1 Intl | 1 Intl |
2 ==== | 2 ==== |
3 | 3 |
4 This package provides internationalization and localization facilities, | 4 This package provides internationalization and localization facilities, |
5 including message translation, plurals and genders, date/number formatting | 5 including message translation, plurals and genders, date/number formatting |
6 and parsing, and bidirectional text. | 6 and parsing, and bidirectional text. |
7 | 7 |
8 ## General | 8 ## General |
9 The most important library is [intl][intl_lib]. It defines the [Intl][Intl] | 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 | 10 class, with the default locale and methods for accessing most of the |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 ```dart | 45 ```dart |
46 var format = new DateFormat.yMd("ar"); | 46 var format = new DateFormat.yMd("ar"); |
47 var dateString = format.format(new DateTime.now()); | 47 var dateString = format.format(new DateTime.now()); |
48 ``` | 48 ``` |
49 | 49 |
50 or | 50 or |
51 | 51 |
52 ```dart | 52 ```dart |
53 print(myMessage(dateString, locale: 'ar'); | 53 print(myMessage(dateString, locale: 'ar'); |
54 ``` | 54 ``` |
55 » | 55 |
56 or | 56 or |
57 | 57 |
58 ```dart | 58 ```dart |
59 Intl.defaultLocale = "es"' | 59 Intl.defaultLocale = "es"; |
60 new DateFormat.jm().format(new DateTime.now()); | 60 new DateFormat.jm().format(new DateTime.now()); |
61 ``` | 61 ``` |
62 | 62 |
63 ## Initialization | 63 ## Initialization |
64 | 64 |
65 All the different types of locale data require an async initialization step | 65 All the different types of locale data require an async initialization step |
66 to make | 66 to make |
67 sure the data is available. This reduces the size of the application by only | 67 sure the data is available. This reduces the size of the application by only |
68 loading the | 68 loading the |
69 data that is actually required. | 69 data that is actually required. |
(...skipping 19 matching lines...) Expand all Loading... |
89 name: "continueMessage", | 89 name: "continueMessage", |
90 args: [], | 90 args: [], |
91 desc: "Explains that we will not proceed further until " | 91 desc: "Explains that we will not proceed further until " |
92 "the user presses a key"); | 92 "the user presses a key"); |
93 print(continueMessage()); | 93 print(continueMessage()); |
94 | 94 |
95 This provides, in addition to the basic message string, a name, a | 95 This provides, in addition to the basic message string, a name, a |
96 description for translators, the arguments used in the message, and | 96 description for translators, the arguments used in the message, and |
97 examples. The `name` and `args` parameters are required, and must | 97 examples. The `name` and `args` parameters are required, and must |
98 match the name (or ClassName_methodName) and arguments list of the | 98 match the name (or ClassName_methodName) and arguments list of the |
99 function respectively. In the future we | 99 function respectively. However, there is a transformer provided that |
100 hope to have these provided automatically. | 100 will automatically insert those parameters for you. In pubspec.yaml, |
| 101 add a section like |
101 | 102 |
102 This can be run in the program before any translation has been done, | 103 transformers: |
103 and will just return the message string. It can also be extracted to a | 104 - intl: |
104 file and then be made to return a translated version without modifying | 105 $include: some_file.dart |
105 the original program. See "Extracting Messages" below for more | 106 |
| 107 and then you can omit the name and args. |
| 108 |
| 109 A function with an Intl.message call can be run in the program before any |
| 110 translation has been done, and will just return the message string. It can also |
| 111 be extracted to a file and then be made to return a translated version without |
| 112 modifying the original program. See "Extracting Messages" below for more |
106 details. | 113 details. |
107 | 114 |
108 The purpose of wrapping the message in a function is to allow it to | 115 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 | 116 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 | 117 allowed to use a restricted form of Dart string interpolation, where |
111 only the function's parameters can be used, and only in simple | 118 only the function's parameters can be used, and only in simple |
112 expressions. Local variables cannot be used, and neither can | 119 expressions. Local variables cannot be used, and neither can |
113 expressions with curly braces. Only the message string can have | 120 expressions with curly braces. Only the message string can have |
114 interpolation. The name, desc, args, and examples must be literals and | 121 interpolation. The name, desc, args, and examples must be literals and |
115 not contain interpolations. Only the args parameter can refer to | 122 not contain interpolations. Only the args parameter can refer to |
116 variables, and it should list exactly the function parameters. If you | 123 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 | 124 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 | 125 the formatting outside the function and pass the formatted string into |
119 the message. | 126 the message. |
120 | 127 |
121 greetingMessage(name) => Intl.message( | 128 greetingMessage(name) => Intl.message( |
122 "Hello $name!", | 129 "Hello $name!", |
123 name: "greetingMessage", | 130 name: "greetingMessage", |
124 args: [name], | 131 args: [name], |
125 desc: "Greet the user as they first open the application", | 132 desc: "Greet the user as they first open the application", |
126 examples: {'name': "Emily"}); | 133 examples: const {'name': "Emily"}); |
127 print(greetingMessage('Dan')); | 134 print(greetingMessage('Dan')); |
128 | 135 |
129 There is one special class of complex expressions allowed in the | 136 There is one special class of complex expressions allowed in the |
130 message string, for plurals and genders. | 137 message string, for plurals and genders. |
131 | 138 |
132 remainingEmailsMessage(int howMany, String userName) => | 139 remainingEmailsMessage(int howMany, String userName) => |
133 Intl.message( | 140 Intl.message( |
134 "${Intl.plural(howMany, | 141 "${Intl.plural(howMany, |
135 zero: 'There are no emails left for $userName.', | 142 zero: 'There are no emails left for $userName.', |
136 one: 'There is one email left for $userName.', | 143 one: 'There is one email left for $userName.', |
137 other: 'There are $howMany emails left for $userName.')}", | 144 other: 'There are $howMany emails left for $userName.')}", |
138 name: "remainingEmailsMessage", | 145 name: "remainingEmailsMessage", |
139 args: [howMany, userName], | 146 args: [howMany, userName], |
140 desc: "How many emails remain after archiving.", | 147 desc: "How many emails remain after archiving.", |
141 examples: {'howMany': 42, 'userName': 'Fred'}); | 148 examples: const {'howMany': 42, 'userName': 'Fred'}); |
142 | 149 |
143 print(remainingEmailsMessage(1, "Fred")); | 150 print(remainingEmailsMessage(1, "Fred")); |
144 | 151 |
145 However, since the typical usage for a plural or gender is for it to | 152 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 | 153 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. | 154 provide its parameters to the [Intl.plural][Intl.plural] call instead. |
148 | 155 |
149 remainingEmailsMessage(int howMany, String userName) => | 156 remainingEmailsMessage(int howMany, String userName) => |
150 Intl.plural( | 157 Intl.plural( |
151 howMany, | 158 howMany, |
152 zero: 'There are no emails left for $userName.', | 159 zero: 'There are no emails left for $userName.', |
153 one: 'There is one email left for $userName.', | 160 one: 'There is one email left for $userName.', |
154 other: 'There are $howMany emails left for $userName.'), | 161 other: 'There are $howMany emails left for $userName.', |
155 name: "remainingEmailsMessage", | 162 name: "remainingEmailsMessage", |
156 args: [howMany, userName], | 163 args: [howMany, userName], |
157 desc: "How many emails remain after archiving.", | 164 desc: "How many emails remain after archiving.", |
158 examples: {'howMany': 42, 'userName': 'Fred'}); | 165 examples: const {'howMany': 42, 'userName': 'Fred'}); |
159 | 166 |
160 Similarly, there is an [Intl.gender][Intl.gender] message, and plurals | 167 Similarly, there is an [Intl.gender][Intl.gender] message, and plurals |
161 and genders can be nested. | 168 and genders can be nested. |
162 | 169 |
163 notOnlineMessage(String userName, String userGender) => | 170 notOnlineMessage(String userName, String userGender) => |
164 Intl.gender( | 171 Intl.gender( |
165 userGender, | 172 userGender, |
166 male: '$userName is unavailable because he is not online.', | 173 male: '$userName is unavailable because he is not online.', |
167 female: '$userName is unavailable because she is not online.', | 174 female: '$userName is unavailable because she is not online.', |
168 other: '$userName is unavailable because they are not online'), | 175 other: '$userName is unavailable because they are not online', |
169 name: "notOnlineMessage", | 176 name: "notOnlineMessage", |
170 args: [userName, userGender], | 177 args: [userName, userGender], |
171 desc: "The user is not available to hangout.", | 178 desc: "The user is not available to hangout.", |
172 examples: {{'userGender': 'male', 'userName': 'Fred'}, | 179 examples: const {{'userGender': 'male', 'userName': 'Fred'}, |
173 {'userGender': 'female', 'userName' : 'Alice'}}); | 180 {'userGender': 'female', 'userName' : 'Alice'}}); |
174 | 181 |
175 It's recommended to use complete sentences in the sub-messages to keep | 182 It's recommended to use complete sentences in the sub-messages to keep |
176 the structure as simple as possible for the translators. | 183 the structure as simple as possible for the translators. |
177 | 184 |
178 ## Extracting And Using Translated Messages | 185 ## Extracting And Using Translated Messages |
179 | 186 |
180 When your program contains messages that need translation, these must | 187 When your program contains messages that need translation, these must |
181 be extracted from the program source, sent to human translators, and the | 188 be extracted from the program source, sent to human translators, and the |
182 results need to be incorporated. | 189 results need to be incorporated. The code for this is in the |
| 190 [Intl_translation][Intl_translation] package. |
183 | 191 |
184 To extract messages, run the `extract_to_arb.dart` program. | 192 To extract messages, run the `extract_to_arb.dart` program. |
185 | 193 |
186 pub run intl:extract_to_arb --output-dir=target/directory | 194 pub run intl_translation:extract_to_arb --output-dir=target/directory |
187 my_program.dart more_of_my_program.dart | 195 my_program.dart more_of_my_program.dart |
188 | 196 |
189 This will produce a file `intl_messages.arb` with the messages from | 197 This will produce a file `intl_messages.arb` with the messages from |
190 all of these programs. an [ARB] | 198 all of these programs. an [ARB] |
191 (https://code.google.com/p/arb/wiki/ApplicationResourceBundleSpecification) | 199 (https://code.google.com/p/arb/wiki/ApplicationResourceBundleSpecification) |
192 format file which can be used for input to translation tools like | 200 format file which can be used for input to translation tools like |
193 [Google Translator Toolkit](https://translate.google.com/toolkit/) | 201 [Google Translator Toolkit](https://translate.google.com/toolkit/) |
194 The resulting translations can be used to generate a set of libraries | 202 The resulting translations can be used to generate a set of libraries |
195 using the `generate_from_arb.dart` program. | 203 using the `generate_from_arb.dart` program. |
196 | 204 |
197 This expects to receive a series of files, one per | 205 This expects to receive a series of files, one per |
198 locale. | 206 locale. |
199 | 207 |
200 pub run intl:generate_from_arb --generated_file_prefix=<prefix> | 208 ``` |
201 <my_dart_files> <translated_ARB_files> | 209 pub run intl_translation:generate_from_arb --generated_file_prefix=<prefix> |
| 210 <my_dart_files> <translated_ARB_files> |
| 211 ``` |
202 | 212 |
203 This will generate Dart libraries, one per locale, which contain the | 213 This will generate Dart libraries, one per locale, which contain the |
204 translated versions. Your Dart libraries can import the primary file, | 214 translated versions. Your Dart libraries can import the primary file, |
205 named `<prefix>messages_all.dart`, and then call the initialization | 215 named `<prefix>messages_all.dart`, and then call the initialization |
206 for a specific locale. Once that's done, any | 216 for a specific locale. Once that's done, any |
207 [Intl.message][Intl.message] calls made in the context of that locale | 217 [Intl.message][Intl.message] calls made in the context of that locale |
208 will automatically print the translated version instead of the | 218 will automatically print the translated version instead of the |
209 original. | 219 original. |
210 | 220 |
211 import "my_prefix_messages_all.dart"; | 221 import "my_prefix_messages_all.dart"; |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 The class [BidiFormatter][BidiFormatter] provides utilities for | 310 The class [BidiFormatter][BidiFormatter] provides utilities for |
301 working with Bidirectional text. We can wrap the string with unicode | 311 working with Bidirectional text. We can wrap the string with unicode |
302 directional indicator characters or with an HTML span to indicate | 312 directional indicator characters or with an HTML span to indicate |
303 direction. The direction can be specified with the | 313 direction. The direction can be specified with the |
304 [RTL][BidiFormatter.RTL] and [LTR][BidiFormatter.LTR] constructors, or | 314 [RTL][BidiFormatter.RTL] and [LTR][BidiFormatter.LTR] constructors, or |
305 detected from the text. | 315 detected from the text. |
306 | 316 |
307 new BidiFormatter.RTL().wrapWithUnicode('xyz'); | 317 new BidiFormatter.RTL().wrapWithUnicode('xyz'); |
308 new BidiFormatter.RTL().wrapWithSpan('xyz'); | 318 new BidiFormatter.RTL().wrapWithSpan('xyz'); |
309 | 319 |
310 [intl_lib]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/intl
/intl | 320 [intl_lib]: https://www.dartdocs.org/documentation/intl/latest/intl/intl-library
.html |
311 [Intl]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/intl | 321 [Intl]: https://www.dartdocs.org/documentation/intl/latest |
312 [DateFormat]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/in
tl/intl.DateFormat | 322 [DateFormat]: https://www.dartdocs.org/documentation/intl/latest/intl/DateFormat
-class.html |
313 [NumberFormat]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/
intl/intl.NumberFormat | 323 [NumberFormat]: https://www.dartdocs.org/documentation/intl/latest/intl/NumberFo
rmat-class.html |
314 [withLocale]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/in
tl/intl.Intl#id_withLocale | 324 [withLocale]: https://www.dartdocs.org/documentation/intl/latest/intl/Intl/withL
ocale.html |
315 [defaultLocale]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer
/intl/intl.Intl#id_defaultLocale | 325 [defaultLocale]: https://www.dartdocs.org/documentation/intl/latest/intl/Intl/de
faultLocale.html |
316 [Intl.message]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/
intl/intl.Intl#id_message | 326 [Intl.message]: https://www.dartdocs.org/documentation/intl/latest/intl/Intl/mes
sage.html |
317 [Intl.plural]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/i
ntl/intl.Intl#id_plural | 327 [Intl.plural]: https://www.dartdocs.org/documentation/intl/latest/intl/Intl/plur
al.html |
318 [Intl.gender]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/i
ntl/intl.Intl#id_gender | 328 [Intl.gender]: https://www.dartdocs.org/documentation/intl/latest/intl/Intl/gend
er.html |
319 [DateTime]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer/dart
:core.DateTime | 329 [DateTime]: https://api.dartlang.org/stable/dart-core/DateTime-class.html |
320 [BidiFormatter]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-viewer
/intl/intl.BidiFormatter | 330 [BidiFormatter]: https://www.dartdocs.org/documentation/intl/latest/intl/BidiFor
matter-class.html |
321 [BidiFormatter.RTL]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-vi
ewer/intl/intl.BidiFormatter#id_BidiFormatter-RTL | 331 [BidiFormatter.RTL]: https://www.dartdocs.org/documentation/intl/latest/intl/Bid
iFormatter/BidiFormatter.RTL.html |
322 [BidiFormatter.LTR]: https://api.dartlang.org/apidocs/channels/stable/dartdoc-vi
ewer/intl/intl.BidiFormatter#id_BidiFormatter-LTR | 332 [BidiFormatter.LTR]: https://www.dartdocs.org/documentation/intl/latest/intl/Bid
iFormatter/BidiFormatter.LTR.html |
OLD | NEW |