twitter_cldr 1.8.1 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (280) hide show
  1. data/Gemfile +3 -2
  2. data/History.txt +7 -1
  3. data/README.md +55 -0
  4. data/lib/twitter_cldr/core_ext.rb +1 -1
  5. data/lib/twitter_cldr/formatters/list_formatter.rb +64 -0
  6. data/lib/twitter_cldr/formatters.rb +4 -2
  7. data/lib/twitter_cldr/localized/localized_array.rb +19 -1
  8. data/lib/twitter_cldr/localized/localized_hash.rb +20 -0
  9. data/lib/twitter_cldr/localized/localized_string.rb +46 -1
  10. data/lib/twitter_cldr/localized/localized_symbol.rb +4 -0
  11. data/lib/twitter_cldr/localized.rb +1 -0
  12. data/lib/twitter_cldr/resources/bidi_test_importer.rb +118 -0
  13. data/lib/twitter_cldr/resources/locales_resources_importer.rb +1 -1
  14. data/lib/twitter_cldr/resources.rb +1 -0
  15. data/lib/twitter_cldr/shared/bidi.rb +526 -0
  16. data/lib/twitter_cldr/shared/languages.rb +5 -0
  17. data/lib/twitter_cldr/shared.rb +1 -0
  18. data/lib/twitter_cldr/utils/code_points.rb +1 -1
  19. data/lib/twitter_cldr/utils/yaml.rb +390 -0
  20. data/lib/twitter_cldr/utils.rb +1 -0
  21. data/lib/twitter_cldr/version.rb +1 -1
  22. data/lib/twitter_cldr.rb +2 -0
  23. data/resources/custom/locales/en/units.yml +19 -18
  24. data/resources/locales/af/calendars.yml +67 -66
  25. data/resources/locales/af/languages.yml +22 -22
  26. data/resources/locales/af/layout.yml +5 -0
  27. data/resources/locales/af/lists.yml +7 -0
  28. data/resources/locales/af/numbers.yml +36 -36
  29. data/resources/locales/af/plurals.yml +2 -3
  30. data/resources/locales/af/units.yml +75 -75
  31. data/resources/locales/ar/calendars.yml +149 -148
  32. data/resources/locales/ar/languages.yml +501 -501
  33. data/resources/locales/ar/layout.yml +5 -0
  34. data/resources/locales/ar/lists.yml +7 -0
  35. data/resources/locales/ar/numbers.yml +31 -31
  36. data/resources/locales/ar/plurals.yml +2 -9
  37. data/resources/locales/ar/units.yml +220 -220
  38. data/resources/locales/ca/calendars.yml +78 -77
  39. data/resources/locales/ca/languages.yml +199 -199
  40. data/resources/locales/ca/layout.yml +5 -0
  41. data/resources/locales/ca/lists.yml +7 -0
  42. data/resources/locales/ca/numbers.yml +36 -36
  43. data/resources/locales/ca/plurals.yml +2 -3
  44. data/resources/locales/ca/units.yml +108 -108
  45. data/resources/locales/cs/calendars.yml +141 -140
  46. data/resources/locales/cs/languages.yml +399 -399
  47. data/resources/locales/cs/layout.yml +5 -0
  48. data/resources/locales/cs/lists.yml +7 -0
  49. data/resources/locales/cs/numbers.yml +41 -41
  50. data/resources/locales/cs/plurals.yml +2 -3
  51. data/resources/locales/cs/units.yml +142 -142
  52. data/resources/locales/da/calendars.yml +73 -73
  53. data/resources/locales/da/languages.yml +36 -36
  54. data/resources/locales/da/layout.yml +5 -0
  55. data/resources/locales/da/lists.yml +7 -0
  56. data/resources/locales/da/numbers.yml +37 -37
  57. data/resources/locales/da/plurals.yml +2 -3
  58. data/resources/locales/da/units.yml +97 -97
  59. data/resources/locales/de/calendars.yml +71 -71
  60. data/resources/locales/de/languages.yml +51 -51
  61. data/resources/locales/de/layout.yml +5 -0
  62. data/resources/locales/de/lists.yml +7 -0
  63. data/resources/locales/de/numbers.yml +36 -36
  64. data/resources/locales/de/plurals.yml +2 -3
  65. data/resources/locales/de/units.yml +108 -108
  66. data/resources/locales/el/calendars.yml +213 -212
  67. data/resources/locales/el/languages.yml +520 -520
  68. data/resources/locales/el/layout.yml +5 -0
  69. data/resources/locales/el/lists.yml +7 -0
  70. data/resources/locales/el/numbers.yml +39 -39
  71. data/resources/locales/el/plurals.yml +2 -3
  72. data/resources/locales/el/units.yml +143 -143
  73. data/resources/locales/en/calendars.yml +66 -65
  74. data/resources/locales/en/languages.yml +24 -24
  75. data/resources/locales/en/layout.yml +5 -0
  76. data/resources/locales/en/lists.yml +7 -0
  77. data/resources/locales/en/numbers.yml +27 -27
  78. data/resources/locales/en/plurals.yml +2 -3
  79. data/resources/locales/en/units.yml +94 -94
  80. data/resources/locales/es/calendars.yml +80 -79
  81. data/resources/locales/es/languages.yml +139 -139
  82. data/resources/locales/es/layout.yml +5 -0
  83. data/resources/locales/es/lists.yml +7 -0
  84. data/resources/locales/es/numbers.yml +36 -36
  85. data/resources/locales/es/plurals.yml +2 -3
  86. data/resources/locales/es/units.yml +96 -96
  87. data/resources/locales/eu/calendars.yml +68 -67
  88. data/resources/locales/eu/languages.yml +11 -11
  89. data/resources/locales/eu/layout.yml +5 -0
  90. data/resources/locales/eu/lists.yml +7 -0
  91. data/resources/locales/eu/numbers.yml +36 -36
  92. data/resources/locales/eu/plurals.yml +2 -3
  93. data/resources/locales/eu/units.yml +80 -80
  94. data/resources/locales/fa/calendars.yml +223 -222
  95. data/resources/locales/fa/languages.yml +489 -489
  96. data/resources/locales/fa/layout.yml +5 -0
  97. data/resources/locales/fa/lists.yml +7 -0
  98. data/resources/locales/fa/numbers.yml +26 -26
  99. data/resources/locales/fa/plurals.yml +2 -3
  100. data/resources/locales/fa/units.yml +122 -122
  101. data/resources/locales/fi/calendars.yml +87 -87
  102. data/resources/locales/fi/languages.yml +86 -86
  103. data/resources/locales/fi/layout.yml +5 -0
  104. data/resources/locales/fi/lists.yml +7 -0
  105. data/resources/locales/fi/numbers.yml +41 -41
  106. data/resources/locales/fi/plurals.yml +2 -3
  107. data/resources/locales/fi/units.yml +124 -124
  108. data/resources/locales/fil/calendars.yml +68 -67
  109. data/resources/locales/fil/languages.yml +19 -19
  110. data/resources/locales/fil/layout.yml +5 -0
  111. data/resources/locales/fil/lists.yml +7 -0
  112. data/resources/locales/fil/numbers.yml +27 -27
  113. data/resources/locales/fil/plurals.yml +2 -3
  114. data/resources/locales/fil/units.yml +80 -80
  115. data/resources/locales/fr/calendars.yml +83 -83
  116. data/resources/locales/fr/languages.yml +117 -117
  117. data/resources/locales/fr/layout.yml +5 -0
  118. data/resources/locales/fr/lists.yml +7 -0
  119. data/resources/locales/fr/numbers.yml +37 -37
  120. data/resources/locales/fr/plurals.yml +2 -3
  121. data/resources/locales/fr/units.yml +80 -80
  122. data/resources/locales/he/calendars.yml +155 -154
  123. data/resources/locales/he/languages.yml +282 -282
  124. data/resources/locales/he/layout.yml +5 -0
  125. data/resources/locales/he/lists.yml +7 -0
  126. data/resources/locales/he/numbers.yml +27 -27
  127. data/resources/locales/he/plurals.yml +2 -3
  128. data/resources/locales/he/units.yml +122 -122
  129. data/resources/locales/hi/calendars.yml +132 -131
  130. data/resources/locales/hi/languages.yml +511 -511
  131. data/resources/locales/hi/layout.yml +5 -0
  132. data/resources/locales/hi/lists.yml +7 -0
  133. data/resources/locales/hi/numbers.yml +27 -27
  134. data/resources/locales/hi/plurals.yml +2 -3
  135. data/resources/locales/hi/units.yml +122 -122
  136. data/resources/locales/hu/calendars.yml +121 -120
  137. data/resources/locales/hu/languages.yml +214 -214
  138. data/resources/locales/hu/layout.yml +5 -0
  139. data/resources/locales/hu/lists.yml +7 -0
  140. data/resources/locales/hu/numbers.yml +39 -39
  141. data/resources/locales/hu/plurals.yml +2 -3
  142. data/resources/locales/hu/units.yml +102 -102
  143. data/resources/locales/id/calendars.yml +68 -67
  144. data/resources/locales/id/languages.yml +21 -21
  145. data/resources/locales/id/layout.yml +5 -0
  146. data/resources/locales/id/lists.yml +7 -0
  147. data/resources/locales/id/numbers.yml +37 -37
  148. data/resources/locales/id/plurals.yml +2 -3
  149. data/resources/locales/id/units.yml +73 -73
  150. data/resources/locales/it/calendars.yml +81 -80
  151. data/resources/locales/it/languages.yml +20 -20
  152. data/resources/locales/it/layout.yml +5 -0
  153. data/resources/locales/it/lists.yml +7 -0
  154. data/resources/locales/it/numbers.yml +36 -36
  155. data/resources/locales/it/plurals.yml +2 -3
  156. data/resources/locales/it/units.yml +94 -94
  157. data/resources/locales/ja/calendars.yml +123 -122
  158. data/resources/locales/ja/languages.yml +516 -516
  159. data/resources/locales/ja/layout.yml +5 -0
  160. data/resources/locales/ja/lists.yml +7 -0
  161. data/resources/locales/ja/numbers.yml +38 -38
  162. data/resources/locales/ja/plurals.yml +2 -3
  163. data/resources/locales/ja/units.yml +108 -108
  164. data/resources/locales/ko/calendars.yml +141 -140
  165. data/resources/locales/ko/languages.yml +509 -509
  166. data/resources/locales/ko/layout.yml +5 -0
  167. data/resources/locales/ko/lists.yml +7 -0
  168. data/resources/locales/ko/numbers.yml +37 -37
  169. data/resources/locales/ko/plurals.yml +2 -3
  170. data/resources/locales/ko/units.yml +108 -108
  171. data/resources/locales/ms/calendars.yml +68 -67
  172. data/resources/locales/ms/languages.yml +19 -19
  173. data/resources/locales/ms/layout.yml +5 -0
  174. data/resources/locales/ms/lists.yml +7 -0
  175. data/resources/locales/ms/numbers.yml +26 -26
  176. data/resources/locales/ms/plurals.yml +2 -3
  177. data/resources/locales/ms/units.yml +73 -73
  178. data/resources/locales/nb/calendars.yml +78 -78
  179. data/resources/locales/nb/languages.yml +93 -93
  180. data/resources/locales/nb/layout.yml +5 -0
  181. data/resources/locales/nb/lists.yml +7 -0
  182. data/resources/locales/nb/numbers.yml +37 -37
  183. data/resources/locales/nb/plurals.yml +2 -3
  184. data/resources/locales/nb/units.yml +99 -99
  185. data/resources/locales/nl/calendars.yml +67 -67
  186. data/resources/locales/nl/languages.yml +30 -30
  187. data/resources/locales/nl/layout.yml +5 -0
  188. data/resources/locales/nl/lists.yml +7 -0
  189. data/resources/locales/nl/numbers.yml +36 -36
  190. data/resources/locales/nl/plurals.yml +2 -3
  191. data/resources/locales/nl/units.yml +87 -87
  192. data/resources/locales/pl/calendars.yml +102 -101
  193. data/resources/locales/pl/languages.yml +139 -139
  194. data/resources/locales/pl/layout.yml +5 -0
  195. data/resources/locales/pl/lists.yml +7 -0
  196. data/resources/locales/pl/numbers.yml +41 -41
  197. data/resources/locales/pl/plurals.yml +2 -5
  198. data/resources/locales/pl/units.yml +149 -149
  199. data/resources/locales/pt/calendars.yml +83 -83
  200. data/resources/locales/pt/languages.yml +161 -161
  201. data/resources/locales/pt/layout.yml +5 -0
  202. data/resources/locales/pt/lists.yml +7 -0
  203. data/resources/locales/pt/numbers.yml +39 -39
  204. data/resources/locales/pt/plurals.yml +2 -3
  205. data/resources/locales/pt/units.yml +110 -110
  206. data/resources/locales/ru/calendars.yml +213 -212
  207. data/resources/locales/ru/languages.yml +511 -511
  208. data/resources/locales/ru/layout.yml +5 -0
  209. data/resources/locales/ru/lists.yml +7 -0
  210. data/resources/locales/ru/numbers.yml +40 -40
  211. data/resources/locales/ru/plurals.yml +2 -5
  212. data/resources/locales/ru/units.yml +192 -192
  213. data/resources/locales/sv/calendars.yml +85 -85
  214. data/resources/locales/sv/languages.yml +108 -108
  215. data/resources/locales/sv/layout.yml +5 -0
  216. data/resources/locales/sv/lists.yml +7 -0
  217. data/resources/locales/sv/numbers.yml +39 -39
  218. data/resources/locales/sv/plurals.yml +2 -3
  219. data/resources/locales/sv/units.yml +116 -116
  220. data/resources/locales/th/calendars.yml +172 -171
  221. data/resources/locales/th/languages.yml +510 -510
  222. data/resources/locales/th/layout.yml +5 -0
  223. data/resources/locales/th/lists.yml +7 -0
  224. data/resources/locales/th/numbers.yml +38 -38
  225. data/resources/locales/th/plurals.yml +2 -3
  226. data/resources/locales/th/units.yml +107 -107
  227. data/resources/locales/tr/calendars.yml +117 -116
  228. data/resources/locales/tr/languages.yml +143 -143
  229. data/resources/locales/tr/layout.yml +5 -0
  230. data/resources/locales/tr/lists.yml +7 -0
  231. data/resources/locales/tr/numbers.yml +37 -37
  232. data/resources/locales/tr/plurals.yml +2 -3
  233. data/resources/locales/tr/units.yml +98 -98
  234. data/resources/locales/uk/calendars.yml +187 -186
  235. data/resources/locales/uk/languages.yml +520 -520
  236. data/resources/locales/uk/layout.yml +5 -0
  237. data/resources/locales/uk/lists.yml +7 -0
  238. data/resources/locales/uk/numbers.yml +44 -44
  239. data/resources/locales/uk/plurals.yml +2 -5
  240. data/resources/locales/uk/units.yml +192 -192
  241. data/resources/locales/ur/calendars.yml +112 -111
  242. data/resources/locales/ur/languages.yml +164 -164
  243. data/resources/locales/ur/layout.yml +5 -0
  244. data/resources/locales/ur/lists.yml +7 -0
  245. data/resources/locales/ur/numbers.yml +27 -27
  246. data/resources/locales/ur/plurals.yml +2 -3
  247. data/resources/locales/ur/units.yml +136 -136
  248. data/resources/locales/zh/calendars.yml +212 -211
  249. data/resources/locales/zh/languages.yml +506 -506
  250. data/resources/locales/zh/layout.yml +5 -0
  251. data/resources/locales/zh/lists.yml +7 -0
  252. data/resources/locales/zh/numbers.yml +37 -37
  253. data/resources/locales/zh/plurals.yml +2 -3
  254. data/resources/locales/zh/units.yml +108 -108
  255. data/resources/locales/zh-Hant/calendars.yml +159 -158
  256. data/resources/locales/zh-Hant/languages.yml +510 -510
  257. data/resources/locales/zh-Hant/layout.yml +5 -0
  258. data/resources/locales/zh-Hant/lists.yml +7 -0
  259. data/resources/locales/zh-Hant/numbers.yml +38 -38
  260. data/resources/locales/zh-Hant/plurals.yml +2 -3
  261. data/resources/locales/zh-Hant/units.yml +108 -108
  262. data/spec/bidi/bidi_spec.rb +72 -0
  263. data/spec/bidi/classpath_bidi_test.txt +217202 -0
  264. data/spec/collation/tailoring_tests/da.txt +1 -1
  265. data/spec/collation/tailoring_tests/fi.txt +1 -7
  266. data/spec/collation/tailoring_tests/zh-Hant.txt +1 -1
  267. data/spec/formatters/list_formatter_spec.rb +119 -0
  268. data/spec/localized/localized_array_spec.rb +28 -0
  269. data/spec/localized/localized_hash_spec.rb +22 -0
  270. data/spec/localized/localized_number_spec.rb +3 -3
  271. data/spec/localized/localized_string_spec.rb +52 -1
  272. data/spec/localized/localized_symbol_spec.rb +7 -0
  273. data/spec/normalization/base_spec.rb +2 -4
  274. data/spec/shared/languages_spec.rb +21 -0
  275. data/spec/shared/numbers_spec.rb +4 -4
  276. data/spec/spec_helper.rb +3 -1
  277. data/spec/utils/yaml/t.gif +0 -0
  278. data/spec/utils/yaml/t.yaml +5 -0
  279. data/spec/utils/yaml/yaml_spec.rb +426 -0
  280. metadata +82 -2
data/Gemfile CHANGED
@@ -8,7 +8,7 @@ end
8
8
 
9
9
  group :development do
10
10
  gem 'nokogiri'
11
- gem 'ruby-cldr', :github => 'KL-7/ruby-cldr', :branch => 'for-twitter-cldr'
11
+ gem 'ruby-cldr', :github => 'svenfuchs/ruby-cldr'
12
12
  end
13
13
 
14
14
  group :test do
@@ -19,4 +19,5 @@ group :test do
19
19
  platform :mri_18 do
20
20
  gem 'rcov'
21
21
  end
22
- end
22
+ end
23
+
data/History.txt CHANGED
@@ -1,6 +1,12 @@
1
+ === 1.9.0
2
+
3
+ * Included Unicode-safe YAML dumping support via an adaptation of the ya2yaml gem.
4
+ * Implemented the Unicode Bidirectional Algorithm to help reorder mixed right-to-left and left-to-right text.
5
+ * Added list formatting support.
6
+
1
7
  === 1.8.1
2
8
 
3
- * Improved, more accurate Japanese collation support.
9
+ * Improved, more accurate Finnish and Chinese collation support.
4
10
  * Moved JavaScript build environment to twitter-cldr-js.
5
11
 
6
12
  === 1.8.0
data/README.md CHANGED
@@ -154,6 +154,27 @@ ts.to_s # Vor 1 Tag
154
154
  ts.to_s(:unit => :hour) # Vor 24 Stunden
155
155
  ```
156
156
 
157
+ ### Lists
158
+
159
+ TwitterCLDR supports formatting lists of strings as you might do in English by using commas, eg: "Apples, cherries, and oranges". Use the `localize` method on an array followed by a call to `to_sentence`:
160
+
161
+ ```ruby
162
+ ["apples", "cherries", "oranges"].localize.to_sentence # "apples, cherries, and oranges"
163
+ ["apples", "cherries", "oranges"].localize(:es).to_sentence # "apples, cherries y oranges"
164
+ ```
165
+
166
+ Behind the scenes, these convenience methods are creating instances of `ListFormatter`. You can do the same thing if you're feeling adventurous:
167
+
168
+ ```ruby
169
+ f = TwitterCldr::Formatters::ListFormatter.new(:locale => :en)
170
+ f.format(["Larry", "Curly", "Moe"]) # "Larry, Curly, and Moe"
171
+
172
+ f = TwitterCldr::Formatters::ListFormatter.new(:locale => :es)
173
+ f.format(["Larry", "Curly", "Moe"]) # "Larry, Curly y Moe"
174
+ ```
175
+
176
+ The TwitterCLDR `ListFormatter` class is smart enough to handle right-to-left (RTL) text and will format the list "backwards" in these cases (note that what looks backwards to English speakers looks frontwards for RTL speakers). See the section on handling bidirectional text below for more information.
177
+
157
178
  ### Plural Rules
158
179
 
159
180
  Some languages, like English, have "countable" nouns. You probably know this concept better as "plural" and "singular", i.e. the difference between "strawberry" and "strawberries". Other languages, like Russian, have three plural forms: one (numbers ending in 1), few (numbers ending in 2, 3, or 4), and many (everything else). Still other languages like Japanese don't use countable nouns at all.
@@ -475,6 +496,40 @@ collator.get_sort_key("Älg") # [39, 61, 51, 1, 134, 157, 6, 1, 143,
475
496
 
476
497
  **Note**: The TwitterCLDR collator does not currently pass all the collation tests provided by Unicode, but for some strange reasons. See the [summary](https://gist.github.com/f4ee3bd280a2257c5641) of these discrepancies if you're curious.
477
498
 
499
+ ### Handling Bidirectional Text
500
+
501
+ When it comes to displaying text written in both right-to-left (RTL) and left-to-right (LTR) languages, most display systems run into problems. The trouble is that Arabic or Hebrew text and English text (for example) often get scrambled visually and are therefore difficult to read. It's not usually the basic ASCII characters like A-Z that get scrambled - it's most often punctuation marks and the like that are confusingly mixed up (they are considered "weak" types by Unicode).
502
+
503
+ To mitigate this problem, Unicode supports special invisible characters that force visual reordering so that mixed RTL and LTR (called "bidirectional") text renders naturally on the screen. The Unicode Consortium has developed an algorithm (The Unicode Bidirectional Algorithm, or UBA) that intelligently inserts these control characters where appropriate. You can make use of the UBA implementation in TwitterCLDR by creating a new instance of `TwitterCldr::Shared::Bidi` using the `from_string` static method, and manipulating it like so:
504
+
505
+ ```ruby
506
+ bidi = TwitterCldr::Shared::Bidi.from_string("hello نزوة world", :direction => :RTL)
507
+ bidi.reorder_visually!
508
+ bidi.to_s
509
+ ```
510
+
511
+ **Disclaimer**: Google Translate tells me the Arabic in the example above means "fancy", but my confidence is not very high, especially since all the letters are unattached. Apologies to any native speakers :)
512
+
513
+ ### Unicode YAML Support
514
+
515
+ Ruby 1.8 does not come with great Unicode support, and nowhere is this more apparent then when dumping Unicode characters in YAML. The Psych gem by @tenderlove is a good replacement and is the default in Ruby 1.9, but requires libyaml and still doesn't handle Unicode characters perfectly. To mitigate this problem (especially in Ruby 1.8), TwitterCLDR contains an adaptation of the [ya2yaml](https://github.com/afunai/ya2yaml) gem by Akira Funai. Our changes specifically add better dumping of Ruby symbols. If you can get Mr. Funai's attention, please gently remind him to merge @camertron's pull request so we can use his gem and not have to maintain a separate version :) Fortunately, YAML parsing can still be done with the usual `YAML.load` or `YAML.load_file`.
516
+
517
+ You can make use of TwitterCLDR's YAML dumper by calling `localize` and then `to_yaml` on an `Array`, `Hash`, or `String`:
518
+
519
+ ```ruby
520
+ { :hello => "world" }.localize.to_yaml
521
+ ["hello", "world"].localize.to_yaml
522
+ "hello, world".localize.to_yaml
523
+ ```
524
+
525
+ Behind the scenes, these convenience methods are using the `TwitterCldr::Shared::YAML` class. You can do the same thing if you're feeling adventurous:
526
+
527
+ ```ruby
528
+ TwitterCldr::Shared::YAML.dump({ :hello => "world" })
529
+ TwitterCldr::Shared::YAML.dump(["hello", "world"])
530
+ TwitterCldr::Shared::YAML.dump("hello, world")
531
+ ```
532
+
478
533
  ## About Twitter-specific Locales
479
534
 
480
535
  Twitter tries to always use BCP-47 language codes. Data from the CLDR doesn't always match those codes however, so TwitterCLDR provides a `convert_locale` method to convert between the two. All functionality throughout the entire gem defers to `convert_locale` before retrieving CLDR data. `convert_locale` supports Twitter-supported BCP-47 language codes as well as CLDR locale codes, so you don't have to guess which one to use. Here are a few examples:
@@ -7,6 +7,6 @@
7
7
  TwitterCldr::Localized::LocalizedNumber.localize(klass)
8
8
  end
9
9
 
10
- [Array, Date, DateTime, String, Symbol, Time].each do |klass|
10
+ [Array, Date, DateTime, String, Symbol, Time, Hash].each do |klass|
11
11
  TwitterCldr::Localized::const_get("Localized#{klass}").localize(klass)
12
12
  end
@@ -0,0 +1,64 @@
1
+ # encoding: UTF-8
2
+
3
+ # Copyright 2012 Twitter, Inc
4
+ # http://www.apache.org/licenses/LICENSE-2.0
5
+
6
+ module TwitterCldr
7
+ module Formatters
8
+ class ListFormatter < Base
9
+
10
+ attr_accessor :locale
11
+
12
+ def initialize(options = {})
13
+ @locale = TwitterCldr.convert_locale(extract_locale(options))
14
+ end
15
+
16
+ def format(list)
17
+ if resource.include?(list.size)
18
+ compose(resource[list.size], list)
19
+ else
20
+ compose_list(list)
21
+ end
22
+ end
23
+
24
+ protected
25
+
26
+ def compose_list(list)
27
+ result = compose(resource[:end] || resource[:middle] || "", [list[-2], list[-1]])
28
+
29
+ # Ruby ranges don't support subtraction for some reason (eg. -3..-5).
30
+ # Instead, we use a positive counter and negate it on array access.
31
+ (3..list.size).each do |i|
32
+ format_sym = i == list.size ? :start : :middle
33
+ format_sym = :middle unless resource.include?(format_sym)
34
+ result = compose(resource[format_sym] || "", [list[-i], result])
35
+ end
36
+
37
+ result
38
+ end
39
+
40
+ def compose(format, elements)
41
+ elements.compact!
42
+
43
+ if elements.size > 1
44
+ result = format.dup
45
+ result.gsub!(/\{(\d+)\}/) { $1 } # unfortunately "{" and "}" are weak types - must replace
46
+
47
+ if TwitterCldr::Shared::Languages.is_rtl?(@locale)
48
+ result = result.localize.to_reordered_s(:direction => :RTL)
49
+ end
50
+
51
+ result.gsub!(/(\d+)/) { elements[$1.to_i] }
52
+ result
53
+ else
54
+ elements[0] || ""
55
+ end
56
+ end
57
+
58
+ def resource
59
+ @resource ||= TwitterCldr.get_locale_resource(@locale, :lists)[@locale][:lists]
60
+ end
61
+
62
+ end
63
+ end
64
+ end
@@ -18,7 +18,9 @@ module TwitterCldr
18
18
  autoload :CurrencyFormatter, 'twitter_cldr/formatters/numbers/currency_formatter'
19
19
  autoload :PercentFormatter, 'twitter_cldr/formatters/numbers/percent_formatter'
20
20
 
21
- autoload :Plurals, 'twitter_cldr/formatters/plurals'
22
- autoload :PluralFormatter, 'twitter_cldr/formatters/plurals/plural_formatter'
21
+ autoload :Plurals, 'twitter_cldr/formatters/plurals'
22
+ autoload :PluralFormatter, 'twitter_cldr/formatters/plurals/plural_formatter'
23
+
24
+ autoload :ListFormatter, 'twitter_cldr/formatters/list_formatter'
23
25
  end
24
26
  end
@@ -7,6 +7,8 @@ module TwitterCldr
7
7
  module Localized
8
8
 
9
9
  class LocalizedArray < LocalizedObject
10
+ include Enumerable
11
+
10
12
  def code_points_to_string
11
13
  TwitterCldr::Utils::CodePoints.to_string(base_obj)
12
14
  end
@@ -27,7 +29,23 @@ module TwitterCldr
27
29
  def to_a
28
30
  @base_obj.dup
29
31
  end
32
+
33
+ def to_sentence
34
+ TwitterCldr::Formatters::ListFormatter.new(:locale => locale).format(base_obj)
35
+ end
36
+
37
+ def each
38
+ if block_given?
39
+ @base_obj.each { |val| yield val }
40
+ else
41
+ @base_obj.to_enum
42
+ end
43
+ end
44
+
45
+ def to_yaml(options = {})
46
+ TwitterCldr::Utils::YAML.dump(@base_obj, options)
47
+ end
30
48
  end
31
49
 
32
50
  end
33
- end
51
+ end
@@ -0,0 +1,20 @@
1
+ # encoding: UTF-8
2
+
3
+ # Copyright 2012 Twitter, Inc
4
+ # http://www.apache.org/licenses/LICENSE-2.0
5
+
6
+ module TwitterCldr
7
+ module Localized
8
+
9
+ class LocalizedHash < LocalizedObject
10
+ def to_yaml(options = {})
11
+ TwitterCldr::Utils::YAML.dump(@base_obj, options)
12
+ end
13
+
14
+ def formatter_const
15
+ nil
16
+ end
17
+ end
18
+
19
+ end
20
+ end
@@ -7,6 +7,7 @@ module TwitterCldr
7
7
  module Localized
8
8
 
9
9
  class LocalizedString < LocalizedObject
10
+ include Enumerable
10
11
 
11
12
  # Uses wrapped string object as a format specification and returns the result of applying it to +args+ (see
12
13
  # +TwitterCldr::Utils.interpolate+ method for interpolation syntax).
@@ -35,7 +36,51 @@ module TwitterCldr
35
36
  @base_obj.dup
36
37
  end
37
38
 
39
+ def size
40
+ code_points.size
41
+ end
42
+
43
+ alias :length :size
44
+
45
+ def bytesize
46
+ # bytesize method available in ruby 1.9 only
47
+ @base_obj.respond_to?(:bytesize) ? @base_obj.bytesize : @base_obj.size
48
+ end
49
+
50
+ def [](index)
51
+ if index.is_a?(Range)
52
+ TwitterCldr::Utils::CodePoints.to_string(code_points[index])
53
+ else
54
+ TwitterCldr::Utils::CodePoints.to_char(code_points[index])
55
+ end
56
+ end
57
+
58
+ def each_char
59
+ if block_given?
60
+ code_points.each do |code_point|
61
+ yield TwitterCldr::Utils::CodePoints.to_char(code_point)
62
+ end
63
+ @base_obj
64
+ else
65
+ code_points.map { |code_point| TwitterCldr::Utils::CodePoints.to_char(code_point) }.to_enum
66
+ end
67
+ end
68
+
69
+ alias :each :each_char
70
+
71
+ def to_yaml(options = {})
72
+ TwitterCldr::Utils::YAML.dump(@base_obj, options)
73
+ end
74
+
75
+ def to_bidi(options = {})
76
+ TwitterCldr::Shared::Bidi.from_string(@base_obj, options)
77
+ end
78
+
79
+ def to_reordered_s(options = {})
80
+ to_bidi(options).reorder_visually!.to_s
81
+ end
82
+
38
83
  end
39
84
 
40
85
  end
41
- end
86
+ end
@@ -11,6 +11,10 @@ module TwitterCldr
11
11
  TwitterCldr::Shared::Languages.from_code_for_locale(@base_obj, @locale)
12
12
  end
13
13
 
14
+ def is_rtl?
15
+ TwitterCldr::Shared::Languages.is_rtl?(@base_obj)
16
+ end
17
+
14
18
  def formatter_const
15
19
  nil
16
20
  end
@@ -6,6 +6,7 @@
6
6
  module TwitterCldr
7
7
  module Localized
8
8
  autoload :LocalizedArray, 'twitter_cldr/localized/localized_array'
9
+ autoload :LocalizedHash, 'twitter_cldr/localized/localized_hash'
9
10
  autoload :LocalizedDate, 'twitter_cldr/localized/localized_date'
10
11
  autoload :LocalizedDateTime, 'twitter_cldr/localized/localized_datetime'
11
12
  autoload :LocalizedNumber, 'twitter_cldr/localized/localized_number'
@@ -0,0 +1,118 @@
1
+ # encoding: UTF-8
2
+
3
+ # Copyright 2012 Twitter, Inc
4
+ # http://www.apache.org/licenses/LICENSE-2.0
5
+
6
+ require 'java'
7
+ java_import "java.lang.Character"
8
+ java_import "classpath.Bidi"
9
+
10
+ require 'twitter_cldr/resources/download'
11
+
12
+ module TwitterCldr
13
+ module Resources
14
+ # This class should be used with JRuby in 1.9 mode
15
+
16
+ class BidiTestImporter
17
+
18
+ BIDI_TEST_URL = 'http://unicode.org/Public/6.1.0/ucd/BidiTest.txt' # this file is about 3.4 MB
19
+ OUT_FILE = "classpath_bidi_test.txt"
20
+ DIRECTIONS = [nil, :LTR, :RTL]
21
+
22
+ def initialize(working_dir)
23
+ @working_dir = working_dir
24
+ end
25
+
26
+ def import
27
+ TwitterCldr::Resources.download_if_necessary(File.join(@working_dir, File.basename(BIDI_TEST_URL)), BIDI_TEST_URL)
28
+ generate_test
29
+ end
30
+
31
+ protected
32
+
33
+ def generate_test
34
+ run_hash = {}
35
+
36
+ File.open(File.join(@working_dir, File.basename(BIDI_TEST_URL)), "r").each_line do |ln|
37
+ cur_line = ln.strip
38
+
39
+ case cur_line[0]
40
+ when "#", "@"
41
+ next
42
+ else
43
+ input, bitset = cur_line.split("; ")
44
+
45
+ expand_bitset_str(bitset).each_with_index do |check, index|
46
+ if check
47
+ types = input.split(" ")
48
+ direction = get_java_direction(DIRECTIONS[index])
49
+ bidi = Java::Classpath::Bidi.new(types_to_string(types), direction)
50
+ levels = types.each_with_index.map { |_, idx| bidi.getLevelAt(idx) }
51
+ reorder_arr = Java::Classpath::Bidi.reorderVisually(levels.dup, 0, (0...types.size).to_a, 0, types.size)
52
+
53
+ key = "#{levels.join(" ")} | #{reorder_arr.join(" ")}"
54
+ run_hash[key] ||= {}
55
+ run_hash[key][input] ||= 0
56
+ run_hash[key][input] |= (2 ** index)
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ File.open(File.join(@working_dir, OUT_FILE), "w+") do |out|
63
+ run_hash.each_pair do |levels_and_reorders, inputs|
64
+ levels, reorders = levels_and_reorders.split(" | ")
65
+ out.write("@Levels: #{levels}\n")
66
+ out.write("@Reorder: #{reorders}\n")
67
+ inputs.each_pair do |input, bitset|
68
+ out.write("#{input}; #{bitset}\n")
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ def expand_bitset_str(bitset)
75
+ bitset.to_i.to_s(2).rjust(3, "0").chars.to_a.map { |i| i == "1" }.reverse
76
+ end
77
+
78
+ def get_java_direction(dir)
79
+ case dir
80
+ when :RTL
81
+ Java::Classpath::Bidi::DIRECTION_RIGHT_TO_LEFT
82
+ when :LTR
83
+ Java::Classpath::Bidi::DIRECTION_LEFT_TO_RIGHT
84
+ else
85
+ Java::Classpath::Bidi::DIRECTION_DEFAULT_LEFT_TO_RIGHT
86
+ end
87
+ end
88
+
89
+ def types_to_string(types)
90
+ @utf_map ||= {
91
+ "L" => "\u0041",
92
+ "LRE" => "\u202a",
93
+ "LRO" => "\u202d",
94
+ "R" => "\u05be",
95
+ "AL" => "\u0626",
96
+ "RLE" => "\u202b",
97
+ "RLO" => "\u202e",
98
+ "PDF" => "\u202c",
99
+ "EN" => "\u0030",
100
+ "ET" => "\u0023",
101
+ "AN" => "\u0667",
102
+ "CS" => "\u002c",
103
+ "NSM" => "\u0300",
104
+ "BN" => "\u0000",
105
+ "B" => "\u0085",
106
+ "S" => "\u0009",
107
+ "WS" => "\u000c",
108
+ "ON" => "\u0021"
109
+ }
110
+
111
+ # java 1.6 and 1.7 report different representative characters for the "ES" bidi class
112
+ @utf_map["ES"] = (Character.getDirectionality(0x002b) == Character::DIRECTIONALITY_EUROPEAN_NUMBER_SEPARATOR) ? "\u002b" : "\u002f"
113
+ types.inject("") { |ret, type| ret << @utf_map[type]; ret }
114
+ end
115
+
116
+ end
117
+ end
118
+ end
@@ -12,7 +12,7 @@ module TwitterCldr
12
12
 
13
13
  class LocalesResourcesImporter
14
14
 
15
- COMPONENTS = %w[calendars languages numbers units plurals]
15
+ COMPONENTS = %w[calendars languages numbers units plurals lists layout]
16
16
 
17
17
  # Arguments:
18
18
  #
@@ -16,5 +16,6 @@ module TwitterCldr
16
16
  autoload :PostalCodesImporter, 'twitter_cldr/resources/postal_codes_importer'
17
17
  autoload :TailoringImporter, 'twitter_cldr/resources/tailoring_importer'
18
18
  autoload :UnicodeDataImporter, 'twitter_cldr/resources/unicode_data_importer'
19
+ autoload :BidiTestImporter, 'twitter_cldr/resources/bidi_test_importer'
19
20
  end
20
21
  end