r18n-core 0.4.14 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. data/.yardopts +1 -1
  2. data/ChangeLog +21 -0
  3. data/LICENSE +2 -2
  4. data/README.md +456 -0
  5. data/Rakefile +2 -1
  6. data/base/gl.yml +31 -0
  7. data/base/it.yml +1 -1
  8. data/lib/r18n-core/filter_list.rb +157 -0
  9. data/lib/r18n-core/filters.rb +40 -36
  10. data/lib/r18n-core/i18n.rb +17 -9
  11. data/lib/r18n-core/locale.rb +5 -2
  12. data/lib/r18n-core/translated.rb +18 -15
  13. data/lib/r18n-core/translated_string.rb +14 -0
  14. data/lib/r18n-core/translation.rb +19 -20
  15. data/lib/r18n-core/untranslated.rb +8 -5
  16. data/lib/r18n-core/utils.rb +5 -1
  17. data/lib/r18n-core/version.rb +1 -1
  18. data/lib/r18n-core/yaml_loader.rb +2 -2
  19. data/lib/r18n-core.rb +60 -13
  20. data/locales/ca.rb +1 -0
  21. data/locales/cs.rb +0 -1
  22. data/locales/en-au.rb +0 -1
  23. data/locales/en-gb.rb +0 -1
  24. data/locales/en-us.rb +0 -1
  25. data/locales/en.rb +1 -1
  26. data/locales/fr.rb +1 -1
  27. data/locales/gl.rb +21 -0
  28. data/locales/hu.rb +1 -2
  29. data/locales/nb-no.rb +2 -3
  30. data/locales/nl.rb +4 -2
  31. data/locales/pt-br.rb +0 -1
  32. data/locales/pt.rb +0 -1
  33. data/locales/sv-se.rb +2 -3
  34. data/locales/th.rb +1 -1
  35. data/locales/tr.rb +2 -4
  36. data/locales/zh-cn.rb +7 -0
  37. data/locales/zh-tw.rb +7 -0
  38. data/r18n-core.gemspec +10 -10
  39. data/spec/filters_spec.rb +38 -7
  40. data/spec/i18n_spec.rb +15 -18
  41. data/spec/locale_spec.rb +19 -14
  42. data/spec/locales/cs_spec.rb +1 -1
  43. data/spec/locales/pl_spec.rb +1 -1
  44. data/spec/locales/ru_spec.rb +1 -1
  45. data/spec/locales/sk_spec.rb +1 -1
  46. data/spec/r18n_spec.rb +64 -22
  47. data/spec/spec_helper.rb +2 -3
  48. data/spec/translated_spec.rb +18 -4
  49. data/spec/translation_spec.rb +17 -6
  50. data/spec/translations/general/en.yml +1 -0
  51. data/spec/yaml_loader_spec.rb +10 -10
  52. metadata +163 -141
  53. data/Gemfile +0 -5
  54. data/Gemfile.lock +0 -35
  55. data/README.rdoc +0 -482
  56. data/spec/translations/empty/en.yml +0 -0
data/README.rdoc DELETED
@@ -1,482 +0,0 @@
1
- = R18n
2
-
3
- R18n is an i18n tool to translate your Ruby application into several languages.
4
-
5
- Use <tt>r18n-rails</tt>, <tt>sinatra-r18n</tt> or teamon’s <tt>merb_i18n</tt> to
6
- localize Web applications and <tt>r18n-desktop</tt> to localize desktop
7
- application.
8
-
9
- == Features
10
-
11
- === Ruby-style Syntax
12
- R18n uses hierarchical, not English-centric, YAML format for translations by
13
- default:
14
-
15
- user:
16
- edit: Edit user
17
- name: User name is %1
18
- count: !!pl
19
- 1: There is 1 user
20
- n: There are %1 users
21
-
22
- To access translation you can call methods with the same names:
23
-
24
- t.user.edit #=> "Edit user"
25
- t.user.name('John') #=> "User name is John"
26
- t.user.count(5) #=> "There are 5 users"
27
-
28
- t.not.exists | 'default' #=> "default"
29
- t.not.exists.translated? #=> false
30
-
31
- If the translation key is the name of an Object method you can access it via
32
- hash index:
33
-
34
- t[:methods] #=> "Methods"
35
-
36
- === Filters
37
-
38
- You can add custom filters for YAML types or any translated string. Filters are
39
- cascading and can communicate with each other.
40
-
41
- R18n already has filters for HTML escaping, lambdas, Textile and Markdown:
42
-
43
- hi: !!markdown |
44
- **Hi**, people!
45
- greater: !!escape
46
- 1 < 2 is true
47
-
48
- t.hi #=> "<p><strong>Hi</strong>, people!</p>"
49
- t.greater #=> "1 &lt; 2 is true"
50
-
51
- === Flexibility
52
-
53
- Translation variables and pluralization (“1 comment”, “5 comments”) are filters
54
- too, so you can extend or replace them. For example, you can use the ‘named
55
- variables filter’ from the <tt>r18n-rails-api</tt> gem:
56
-
57
- greeting: "Hi, %{name}"
58
-
59
- R18n::Filters.on(:named_variables)
60
- t.greeting(name: 'John') #=> "Hi, John"
61
-
62
- === Flexible Locales
63
-
64
- Locales extend the Locale class. For example, English locale extends the time
65
- formatters:
66
-
67
- l Date.now, :full #=> "30th of November, 2009"
68
-
69
- Russian has built-in pluralization without any lambdas in YAML:
70
-
71
- t.user.count(1) #=> "1 пользователь"
72
- t.user.count(2) #=> "2 пользователя"
73
- t.user.count(5) #=> "5 пользователей"
74
-
75
- === Loaders
76
-
77
- R18n can load translations from anywhere, not just from YAML files. You just
78
- need to create loader object with 2 methods: +available+ and +load+:
79
-
80
- class DBLoader
81
- def available
82
- Translation.find(:all).map(&:locale)
83
- end
84
- def load(locale)
85
- Translation.find(locale).to_hash
86
- end
87
- end
88
-
89
- R18n.set(user_locales, DBLoader.new)
90
-
91
- You can also set a list of different translation locations or set extension
92
- locations which will be only used with application translation (useful for
93
- plugins).
94
-
95
- === Object Translation
96
-
97
- You can translate any class, including ORM models (ActiveRecord, DataMapper,
98
- MongoMapper, Mongoid or others):
99
-
100
- require 'r18n-core/translated'
101
-
102
- class Product < ActiveRecord::Base
103
- include R18n::Translated
104
- # Model has two normal properties: title_en and title_ru
105
- translations :title
106
- end
107
-
108
- # For English users
109
- product.title #=> "Anthrax"
110
-
111
- # For Russian users
112
- product.title #=> "Сибирская язва"
113
-
114
- === Localization
115
-
116
- R18n can localize numbers and time:
117
-
118
- l -5000 #=> "−5,000"
119
- l Time.now #=> "30/11/2009 14:36"
120
- l Time.now, :full #=> "30th of November, 2009 14:37"
121
- l Time.now - 60, :human #=> "1 minute ago"
122
-
123
- === Several User Languages
124
-
125
- If a particular locale is requested but missing, R18n will automatically take
126
- the next available language (according to the browser’s list of locales) and for
127
- cultures with two official languages (e.g., exUSSR) it takes the second language
128
- (e.g., if a translation isn’t available in Kazakh R18n will look for Russian):
129
-
130
- i18n = R18n::I18n.new(['kk', 'de'], 'dir/with/translations')
131
-
132
- i18n.locales #=> [Locale kk (Қазақша), Locale de (Deutsch),
133
- # Locale ru (Русский), Locale en (English)]
134
-
135
- i18n.kazakh #=> "Қазақша", main user language
136
- i18n.deutsch #=> "Deutsch", not in Kazakh, use next user locale
137
- i18n.russian #=> "Русский", not in kk and de, use Kazakh sublocale
138
- i18n.english #=> "English", not in any user locales, use default
139
-
140
- === Agnostic
141
-
142
- R18n has an agnostic core package and plugins with out-of-box support for
143
- Sinatra, Merb and desktop applications.
144
-
145
- == Usage
146
-
147
- To add i18n support to your app, you can use the particular plugin for your
148
- environment: <tt>r18n-rails</tt>, <tt>sinatra-r18n</tt> or
149
- <tt>r18n-desktop</tt>.
150
-
151
- If you develop you own plugin or want to use only core gem, you will need to
152
- create an I18n object and by using <tt>R18n.set</tt> or, for the current thread,
153
- by using <tt>R18n.thread_set</tt>:
154
-
155
- R18n.set('en', 'path/to/translations')
156
-
157
- You can add helpers to access the current R18n object:
158
-
159
- include R18n::Helpers
160
-
161
- t.yes #=> "Yes"
162
- l Time.now, :human #=> "now"
163
- r18n.locale.code #=> "en"
164
-
165
- === Translation
166
-
167
- Translation files are in YAML format by default and have names like en.yml
168
- (English) or en-us.yml (USA English dialect) with language/country code (RFC
169
- 3066).
170
-
171
- In your translation files you can use:
172
- * Strings
173
- robot: This is a robot
174
- percent: "Percent sign (%)"
175
- * Numbers
176
- number: 123
177
- float: 12.45
178
- * Pluralizable messages
179
- robots: !!pl
180
- 0: No robots
181
- 1: One robot
182
- n: %1 robots
183
- * Filters
184
- filtered: !!custom_type
185
- This content will be processed by a filter
186
-
187
- To get the translated string use a method with the key name or square brackets
188
- [] for keys, which is the same with Object methods (+class+, +inspect+, etc):
189
-
190
- t.robot #=> "This is a robot"
191
- t[:robot] #=> "This is a robot"
192
-
193
- Translation may be hierarchical:
194
-
195
- t.post.add #=> "Add post"
196
- t[:post][:add] #=> "Add post"
197
-
198
- If the locale isn’t found in the user’s requested locale, R18n will search for
199
- it in sublocales or in another locale, which the user also can accept:
200
-
201
- t.not.in.english #=> "В английском нет"
202
-
203
- The translated string has a +locale+ method for determining its locale (Locale
204
- instance or code string if locale is’t supported in R18n):
205
-
206
- i18n.not.in.english.locale #=> Locale ru (Русский)
207
-
208
- You can include parameters in the translated string by specifying arguments:
209
-
210
- name: "My name is %1"
211
-
212
- t.name('John') #=> "My name is John"
213
-
214
- Pluralizable messages get their item count from the first argument:
215
-
216
- t.robots(0) #=> "No robots"
217
- t.robots(1) #=> "One robot"
218
- t.robots(50) #=> "50 robots"
219
-
220
- If there isn’t a pluralization for a particular number, translation will be use
221
- +n+. If there isn’t a locale file for translation, it will use the English
222
- pluralization rule (0, 1 and +n+).
223
-
224
- You can check if the key has a translation:
225
-
226
- t.post.add.translated? #=> true
227
- t.not.exists.translated? #=> false
228
-
229
- You can set a default value for untranslated strings:
230
-
231
- t.not.exists | 'default' #=> "default"
232
-
233
- You can query the translation keys:
234
-
235
- t.counties._keys.each do |county|
236
- puts t.counties[county]
237
- end
238
-
239
- R18n already has translations for common words for most built in locales.
240
- See <tt>base/</tt> the source.
241
-
242
- t.yes #=> "Yes"
243
- t.cancel #=> "Cancel"
244
- t.delete #=> "Delete"
245
-
246
- === Filters
247
-
248
- You can also add you own filters for translations: escape HTML entities, convert
249
- from Markdown syntax, etc. Filters can be passive, only being processed when
250
- loaded.
251
-
252
- friendship: !!gender
253
- f: She adds a friend
254
- m: He adds a friend
255
-
256
- R18n::Filters.add('gender', :user_gender) do |content, config, user|
257
- if user.female?
258
- content['f']
259
- else
260
- content['m']
261
- end
262
- end
263
-
264
- t.friendship(anne) #=> "She adds a friend"
265
-
266
- To create a filter you pass the following to <tt>R18n::Filters.add</tt>:
267
-
268
- * Filter target. YAML type (<tt>!!type</tt>), <tt>String</tt> for all
269
- translations of <tt>R18n::Untranslated</tt> for missing translations.
270
- * Optional filter name, to disable, enable or delete it later by
271
- <tt>R18n::Filters.off</tt>, <tt>R18n::Filters.on</tt> and
272
- <tt>R18n::Filters.delete</tt>.
273
- * Hash with options:
274
- * <tt>:passive => true</tt> to filter translations only on load;
275
- * <tt>:position</tt> within the list of current filters of this type
276
- (by default a new filter will be inserted into last position).
277
-
278
- The filter will receive at least two arguments:
279
- * Translation (possibly already filtered by other filters for this type earlier
280
- in the list).
281
- * A Hash with translation +locale+ and +path+.
282
- * Parameters from translation request will be in the remaining arguments.
283
-
284
- ==== HTML Escape
285
-
286
- R18n contains 2 filters to escape HTML entities: by YAML type and global. If you
287
- need to escape HTML in some translations, just set <tt>!!escape</tt> YAML type:
288
-
289
- greater: !!escape
290
- 1 < 2 is true
291
-
292
- t.greater #=> "1 &lt; 2 is true"
293
-
294
- If you develop web application and want to escape HTML in all translations, just
295
- activate the global escape filter:
296
-
297
- R18n::Filters.on(:global_escape_html)
298
-
299
- If you enable global HTML escape, you may still use <tt>!!html</tt> YAML type to
300
- disable escaping on some values:
301
-
302
- warning: !!html
303
- <b>Warning</b>
304
-
305
- R18n::Filters.on(:global_escape_html)
306
- t.warning #=> "<b>Warning</b>"
307
-
308
- ==== Markdown
309
-
310
- To use Markdown in your translations you must install the Maruku gem:
311
-
312
- hi: !!markdown
313
- **Hi**, people!
314
-
315
- t.hi #=> "<p><strong>Hi</strong>, people!</p>"
316
-
317
-
318
- ==== Textile
319
-
320
- To use Textile in your translations you must install the RedCloth gem:
321
-
322
- alarm: !!textile
323
- It will delete _all_ users!
324
-
325
- t.alarm #=> "<p>It will delete <em>all</em> users!</p>"
326
-
327
- ==== Lambdas
328
-
329
- You can use lambdas in your translations.
330
-
331
- sum: !!proc |x, y| x + y
332
-
333
- t.sum(1, 2) #=> 3
334
-
335
- If this is unsafe in your application (for example, user can change
336
- translations), you can disable it:
337
-
338
- R18n::Filters.off(:procedure)
339
-
340
- === Localization
341
-
342
- You can print numbers and floats according to the rules of the user locale:
343
-
344
- l -12000.5 #=> "−12,000.5"
345
-
346
- Number and float formatters will also put real typographic minus and put
347
- non-breakable thin spaces (for locale, which use it as digit separator).
348
-
349
- You can translate months and week day names in Time, Date and DateTime by the
350
- +strftime+ method:
351
-
352
- l Time.now, '%B' #=> "September"
353
-
354
- R18n has some built-in time formats for locales: <tt>:human</tt>, <tt>:full</tt>
355
- and <tt>:standard</tt> (the default):
356
-
357
- l Time.now, :human #=> "now"
358
- l Time.now, :full #=> "August 9th, 2009 21:47"
359
- l Time.now #=> "08/09/2009 21:41"
360
- l Time.now.to_date #=> "08/09/2009"
361
-
362
- === Model
363
-
364
- You can add i18n support to any classes, including ORM models (ActiveRecord,
365
- DataMapper, MongoMapper, Mongoid or others):
366
-
367
- require 'r18n-core/translated'
368
-
369
- class Product
370
- include DataMapper::Resource
371
- property :title_ru, String
372
- property :title_en, String
373
-
374
- include R18n::Translated
375
- translations :title
376
- end
377
-
378
- # For example, user only knows Russian
379
-
380
- # Set English (default) title
381
- product.title_en = "Anthrax"
382
- product.title #=> "Anthrax"
383
-
384
- # Set value for user locale (Russian)
385
- product.title = "Сибирская язва"
386
- product.title #=> "Сибирская язва"
387
-
388
- product.title_en #=> "Anthrax"
389
- product.title_ru #=> "Сибирская язва"
390
-
391
- See R18n::Translated for documentation.
392
-
393
- === Locale
394
-
395
- All supported locales are stored in R18n gem in +locales+ directory. If you want
396
- to add your locale, please fork this project and send a pull request or email me
397
- at andrey@sitnik.ru.
398
-
399
- To get information about a locale create an R18n::Locale instance:
400
-
401
- locale = R18n::Locale.load('en')
402
-
403
- You can then get the following from the locale:
404
-
405
- * Locale title and RFC 3066 code:
406
-
407
- locale.title #=> "English"
408
- locale.code #=> "en"
409
-
410
- * Language direction (left to right, or right to left for Arabic and Hebrew):
411
-
412
- locale.ltr? #=> true
413
-
414
- * Week start day (+:monday+ or +:sunday+):
415
-
416
- locale.week_start #=> :sunday
417
-
418
- === Loaders
419
-
420
- You can load translations from anywhere, not just from YAML files. To load
421
- translation you must create loader class with 2 methods:
422
-
423
- * <tt>available</tt> – return array of locales of available translations;
424
- * <tt>load(locale)</tt> – return Hash of translation.
425
-
426
- Pass its instance to <tt>R18n::I18n.new</tt>:
427
-
428
- R18n.set('en', MyLoader.new(loader_param))
429
-
430
- You can set your default loader and pass it to <tt>R18n::I18n.new</tt> as the
431
- only constructor argument:
432
-
433
- R18n.default_loader = MyLoader
434
- R18n.set('en', loader_param)
435
-
436
- If you want to load a translation with some type for filter, use
437
- <tt>R18n::Typed</tt> struct:
438
-
439
- # Loader will return something like:
440
- { 'users' => R18n::Typed.new('pl', { 1 => '1 user', 'n' => '%1 users' }) }
441
-
442
- # To use pluralization filter (+pl+ type):
443
- t.users(5) #=> "5 users"
444
-
445
- === Extension Translations
446
-
447
- For r18n plugin you can add loaders with translations, which will be used with
448
- application translations. For example, DB plugin may place translations for
449
- error messages in extension directory. R18n contain translations for base words
450
- as extension directory too.
451
-
452
- R18n.extension_places << R18n::Loader::YAML.new('./error_messages/')
453
-
454
- == Add Locale
455
-
456
- If R18n hasn’t got locale file for your language, please add it. It’s very
457
- simple:
458
-
459
- * Create the file _code_.rb in the locales/ directory for your language and
460
- describe locale. Just copy from another locale and change the values.
461
- * If your country has alternate languages (for example, in exUSSR countries
462
- most people also know Russian), add
463
- <tt>sublocales %{_another_locale_ en}</tt>.
464
- * Create in base/ file _code_.yml for your language and translate the base
465
- messages. Just copy file from language, which you know, and rewrite values.
466
- * If your language needs some special logic (for example, different
467
- pluralization or time formatters) you can extend Locale class methods.
468
- * Send a pull request via GitHub (http://github.com/ai/r18n) or just write email
469
- with the files to me (andrey@sitnik.ru).
470
-
471
- _Code_ is RFC 3066 code for your language (for example, “en” for English and
472
- “fr-CA” for Canadian French). Email me with any questions you may have, you will
473
- find other contact addresses at http://sitnik.ru.
474
-
475
- == License
476
-
477
- R18n is licensed under the GNU Lesser General Public License version 3.
478
- See the LICENSE file or http://www.gnu.org/licenses/lgpl.html.
479
-
480
- == Author
481
-
482
- Andrey “A.I.” Sitnik <andrey@sitnik.ru>
File without changes