r18n-core 0.4.14 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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