roda-i18n 0.1.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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +18 -0
- data/README.md +309 -0
- data/Rakefile +78 -0
- data/lib/roda/plugins/i18n.rb +276 -0
- data/spec/fixtures/app/i18n/de.yml +14 -0
- data/spec/fixtures/app/i18n/en.yml +14 -0
- data/spec/fixtures/app/i18n/es.yml +8 -0
- data/spec/fixtures/i18n/de.yml +34 -0
- data/spec/fixtures/i18n/en.yml +68 -0
- data/spec/fixtures/i18n/sv-se.yml +53 -0
- data/spec/roda_i18n_coverage.rb +13 -0
- data/spec/roda_i18n_spec.rb +413 -0
- data/spec/spec_helper.rb +98 -0
- metadata +66 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5a3d6733ef6fdf42c06e7e28107e123ba746f0af
|
4
|
+
data.tar.gz: 517043eb03472e935a0ca625bd71cc07c53a8fe9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 33080f5390f7fea5ec9b4f6c85fb405cbaf70d0b8ce187eca20917ad83d61b071140deb5b03c04653a04f3fcb5f3d9816219f04a808a8ef3bec618e381e801b9
|
7
|
+
data.tar.gz: 1e96099edd2e3ecc6868b67982edb185a9ce9ed5cf5cb9dacb0d63c1f12e52fc3328653a3320b775189ceeef3d26f0341204b05ca9607d2d4c1a4c00603c93cd
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (c) 2015 Kematzy
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to
|
5
|
+
deal in the Software without restriction, including without limitation the
|
6
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
7
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
16
|
+
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
18
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,309 @@
|
|
1
|
+
# Roda-i18n
|
2
|
+
|
3
|
+
Easily add Internationalisation (i18n) and localisation support for [Roda](http://roda.jeremyevans.net/) apps, based upon the [R18n](https://github.com/ai/r18n) gem.
|
4
|
+
|
5
|
+
Extensively tested and with 100% code test coverage.
|
6
|
+
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
To use this gem, just do
|
11
|
+
|
12
|
+
$ (sudo) gem install roda-i18n
|
13
|
+
|
14
|
+
or if you use Bundler
|
15
|
+
|
16
|
+
gem "roda-i18n"
|
17
|
+
|
18
|
+
|
19
|
+
<br>
|
20
|
+
|
21
|
+
|
22
|
+
## Getting Started
|
23
|
+
|
24
|
+
To add internationalisation and localisation support to your app just add the following code snippet in your app.
|
25
|
+
|
26
|
+
plugin :i18n
|
27
|
+
|
28
|
+
By default the default locale is set to <tt>'en'</tt> and the translations directory is set to the <tt>'i18n'</tt> directory in the rooot of your app, ie: '<tt>/path/2/app/i18n</tt>'.
|
29
|
+
|
30
|
+
|
31
|
+
**IMPORTANT! Make sure you create the 'i18n' folder and add an 'en.yml' file with
|
32
|
+
at least one translation within it.**
|
33
|
+
|
34
|
+
|
35
|
+
<br>
|
36
|
+
|
37
|
+
|
38
|
+
## Configuration
|
39
|
+
|
40
|
+
### Overriding defaults during configuration
|
41
|
+
|
42
|
+
Both <tt>:locale</tt> and <tt>:translations</tt> can be configured (overridden) during plugin configuration:
|
43
|
+
|
44
|
+
plugin :i18n, :locale => ['de'], :translations => ['absolute/path/2/i18n']
|
45
|
+
|
46
|
+
|
47
|
+
**NOTE!**
|
48
|
+
|
49
|
+
1. You must set <tt>opts[:root]</tt> in your app if you do not define the <tt>:translations</tt> path during plugin configuration.
|
50
|
+
|
51
|
+
2. When overriding <tt>:translations</tt> the **any path(s) given must be absolute**.
|
52
|
+
|
53
|
+
|
54
|
+
#### Loading translations from multiple i18n directories
|
55
|
+
|
56
|
+
The <tt>:translations</tt> path supports 'wildcards', ie: <tt>path/**/i18n</tt> so you can load translations from multiple combined apps, each with their own <tt>i18n</tt> folder with translations.
|
57
|
+
|
58
|
+
**Please Note!**
|
59
|
+
|
60
|
+
When loading translations from multiple sources and the same translation key is available in multiple files of the same locale, then **the translations in the first loaded translation file takes precedence over subsequent loaded translations**.
|
61
|
+
|
62
|
+
* ie: translations in <tt>./i18n/en.yml</tt> takes precedence over translations in <tt>./apps/app1/i18n/en.yml</tt>
|
63
|
+
|
64
|
+
|
65
|
+
You can also set a list of preferred locales as an array ordered by priority.
|
66
|
+
|
67
|
+
plugin :i18n, :locale => ['es','fr','en']
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
<br>
|
72
|
+
|
73
|
+
|
74
|
+
## USAGE
|
75
|
+
|
76
|
+
The **i18n** plugin depends upon simple YAML based translations files:
|
77
|
+
|
78
|
+
# app/i18n/en.yml
|
79
|
+
|
80
|
+
user:
|
81
|
+
edit: Edit user
|
82
|
+
name: User name is %1
|
83
|
+
count: !!pl
|
84
|
+
1: There is 1 user
|
85
|
+
n: There are %1 users
|
86
|
+
|
87
|
+
|
88
|
+
...and the **<tt>:t</tt>** instance method to output the translations:
|
89
|
+
|
90
|
+
|
91
|
+
t.user.edit #=> "Edit user"
|
92
|
+
t.user.name('John') #=> "User name is John"
|
93
|
+
t.user.count(5) #=> "There are 5 users"
|
94
|
+
|
95
|
+
t.does.not.exist | 'default' #=> "default"
|
96
|
+
|
97
|
+
|
98
|
+
...and the **<tt>:l</tt>** (lowercase L) instance method provides built-in localisations support:
|
99
|
+
|
100
|
+
|
101
|
+
l Time.now #=> "03/01/2010 18:54"
|
102
|
+
l Time.now, :human #=> "now"
|
103
|
+
l Time.now, :full #=> "3rd of January, 2010 18:54"
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
Both the <tt>:t</tt> and <tt>:l</tt> methods are available within the route and template (erb) scopes. ie:
|
108
|
+
|
109
|
+
|
110
|
+
route do |r|
|
111
|
+
r.root do
|
112
|
+
t.welcome.message
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# app/views/layout.erb
|
117
|
+
<snip...>
|
118
|
+
<h1><%= t.welcome.message %></h1>
|
119
|
+
<snip...>
|
120
|
+
|
121
|
+
|
122
|
+
|
123
|
+
Please visit [R18n](https://github.com/ai/r18n/tree/master/r18n-core) for more information about the R18n gem used to create the above.
|
124
|
+
|
125
|
+
<br>
|
126
|
+
|
127
|
+
## Key Methods / Functionality
|
128
|
+
|
129
|
+
|
130
|
+
<br>
|
131
|
+
|
132
|
+
|
133
|
+
### <tt>#locale(opts={},&blk)</tt> - (request method)
|
134
|
+
|
135
|
+
This request method makes it easy to handle translations based upon the **<tt>:locale</tt> prefix on a route / URL**. ie: <tt>blog.com/**de**/posts</tt>.
|
136
|
+
|
137
|
+
|
138
|
+
To enable this, just use the following code structure:
|
139
|
+
|
140
|
+
route do |r|
|
141
|
+
|
142
|
+
# all routes are prefixed with '/:locale'
|
143
|
+
# ie: GET /de/posts => will use DE translations
|
144
|
+
# ie: GET /es/posts => will use ES translations
|
145
|
+
|
146
|
+
r.locale do # also aliased as #i18n_locale
|
147
|
+
r.is 'posts' do
|
148
|
+
t.posts.header # use translations or locales
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
|
156
|
+
|
157
|
+
**NOTE!** Any URL / request with a non-present or not supported locale will be given the **configured default locale** or the EN (English) default locale.
|
158
|
+
|
159
|
+
|
160
|
+
<br>
|
161
|
+
|
162
|
+
|
163
|
+
### <tt>#i18n_set_locale_from(type)</tt> - (request method)
|
164
|
+
|
165
|
+
Obtains the locale from either ENV, HTTP (browser), Params or Session values.
|
166
|
+
|
167
|
+
route do |r|
|
168
|
+
# A): set from session[:locale] (if present)
|
169
|
+
r.i18n_set_locale_from(:session)
|
170
|
+
|
171
|
+
# B): set from URL params ie: GET /posts?locale=de
|
172
|
+
r.i18n_set_locale_from(:params)
|
173
|
+
|
174
|
+
# C): set from the browser's HTTP request locale
|
175
|
+
r.i18n_set_locale_from(:http)
|
176
|
+
|
177
|
+
# D): set from the server ENV['LANG'] variable
|
178
|
+
r.i18n_set_locale_from(:ENV)
|
179
|
+
|
180
|
+
|
181
|
+
r.is 'posts' do
|
182
|
+
t.posts.header # use translations
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
|
187
|
+
**NOTE!** defaults to the configured default locale, or English, if the given locale type is invalid.
|
188
|
+
|
189
|
+
|
190
|
+
<br>
|
191
|
+
|
192
|
+
|
193
|
+
### <tt>#i18n_set_locale(locale, &blk)</tt> - (request method)
|
194
|
+
|
195
|
+
Enables overriding the default locale and setting a temporary :locale
|
196
|
+
within a route block.
|
197
|
+
|
198
|
+
route do |r|
|
199
|
+
# configured default locale
|
200
|
+
|
201
|
+
<snip...>
|
202
|
+
|
203
|
+
r.i18n_set_locale('de') do
|
204
|
+
# within this route block the locale is DE (German)
|
205
|
+
end
|
206
|
+
|
207
|
+
r.i18n_set_locale('es') do
|
208
|
+
# within this route block the locale is ES (Spanish)
|
209
|
+
end
|
210
|
+
|
211
|
+
end
|
212
|
+
|
213
|
+
|
214
|
+
|
215
|
+
|
216
|
+
|
217
|
+
## InstanceMethods
|
218
|
+
|
219
|
+
### `#t`
|
220
|
+
|
221
|
+
This is the main translation output method. (See examples above)
|
222
|
+
|
223
|
+
|
224
|
+
<br>
|
225
|
+
|
226
|
+
|
227
|
+
### `#l`
|
228
|
+
|
229
|
+
Key localisation method. Handles dates etc. (See examples above)
|
230
|
+
|
231
|
+
|
232
|
+
<br>
|
233
|
+
|
234
|
+
|
235
|
+
### `#i18n_available_locales`
|
236
|
+
|
237
|
+
Returns a two-dimensional array of available locales.
|
238
|
+
|
239
|
+
puts i18n_available_locales #=> [ ['en', 'English'], ...]
|
240
|
+
|
241
|
+
|
242
|
+
|
243
|
+
|
244
|
+
### `#i18n_default_places`
|
245
|
+
|
246
|
+
|
247
|
+
<br>
|
248
|
+
|
249
|
+
|
250
|
+
## Class Methods
|
251
|
+
|
252
|
+
### <tt>#i18n_opts</tt>
|
253
|
+
|
254
|
+
Return the i18n options for this class as a Hash.
|
255
|
+
|
256
|
+
|
257
|
+
<br>
|
258
|
+
|
259
|
+
|
260
|
+
## Ideas
|
261
|
+
|
262
|
+
A few ideas that may be outlandish, but possible?
|
263
|
+
|
264
|
+
|
265
|
+
### Ability to load translations from multiple locations via an array.
|
266
|
+
|
267
|
+
plugin :i18n, :translations => ['app1/i18n', 'app2/i18n', 'app3/i18n']
|
268
|
+
|
269
|
+
|
270
|
+
> [Concept Reference](https://github.com/ai/r18n/tree/master/r18n-core#loaders)
|
271
|
+
>
|
272
|
+
> You can also set several loaders to merge translations from different sources:
|
273
|
+
>
|
274
|
+
> R18n.default_places = [MyLoader.new, DBLoader.new, 'path/to/yaml']
|
275
|
+
>
|
276
|
+
|
277
|
+
|
278
|
+
### Sequel DBLoader for DB based translations support
|
279
|
+
|
280
|
+
Som form of built-in support for storing / loading translations from a Sequel based DB.
|
281
|
+
|
282
|
+
|
283
|
+
<br>
|
284
|
+
|
285
|
+
|
286
|
+
----
|
287
|
+
|
288
|
+
## TODOs
|
289
|
+
|
290
|
+
* I'm sure there's something, but right now the list is empty ;-)
|
291
|
+
|
292
|
+
|
293
|
+
## Credits
|
294
|
+
|
295
|
+
* This plugin have been inspired by the `sinatra-i18n` gem available at [github/ai/r18n](http://github.com/ai/r18n) created by [Andrey Sitnik](http://github.com/ai).
|
296
|
+
|
297
|
+
* Testing code have been partly copied from [Forme](github.com/jeremyevans/forme).
|
298
|
+
|
299
|
+
* Inspiration and assistance by [Jeremy Evans](github.com/jeremyevans). Many thanks Jeremy!!
|
300
|
+
|
301
|
+
|
302
|
+
## Licence
|
303
|
+
|
304
|
+
MIT
|
305
|
+
|
306
|
+
Copyright: 2015 Kematzy
|
307
|
+
|
308
|
+
|
309
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require "rake"
|
2
|
+
require "rake/clean"
|
3
|
+
|
4
|
+
NAME = 'roda-i18n'
|
5
|
+
CLEAN.include ["#{NAME}-*.gem", "rdoc", "coverage", '**/*.rbc']
|
6
|
+
|
7
|
+
# Gem Packaging and Release
|
8
|
+
|
9
|
+
desc "Packages #{NAME}"
|
10
|
+
task :package=>[:clean] do |p|
|
11
|
+
sh %{gem build #{NAME}.gemspec}
|
12
|
+
end
|
13
|
+
|
14
|
+
desc "Upload #{NAME} gem to rubygems"
|
15
|
+
task :release=>[:package] do
|
16
|
+
sh %{gem push ./#{NAME}-#{VERS.call}.gem}
|
17
|
+
end
|
18
|
+
|
19
|
+
# ### RDoc
|
20
|
+
#
|
21
|
+
# RDOC_DEFAULT_OPTS = ["--line-numbers", "--inline-source", '--title', 'Roda I18n']
|
22
|
+
#
|
23
|
+
# begin
|
24
|
+
# gem 'hanna-nouveau'
|
25
|
+
# RDOC_DEFAULT_OPTS.concat(['-f', 'hanna'])
|
26
|
+
# rescue Gem::LoadError
|
27
|
+
# end
|
28
|
+
#
|
29
|
+
# rdoc_task_class = begin
|
30
|
+
# require "rdoc/task"
|
31
|
+
# RDoc::Task
|
32
|
+
# rescue LoadError
|
33
|
+
# require "rake/rdoctask"
|
34
|
+
# Rake::RDocTask
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# RDOC_OPTS = RDOC_DEFAULT_OPTS + ['--main', 'README.rdoc']
|
38
|
+
#
|
39
|
+
# rdoc_task_class.new do |rdoc|
|
40
|
+
# rdoc.rdoc_dir = "rdoc"
|
41
|
+
# rdoc.options += RDOC_OPTS
|
42
|
+
# rdoc.rdoc_files.add %w"README.rdoc CHANGELOG MIT-LICENSE lib/**/*.rb"
|
43
|
+
# end
|
44
|
+
|
45
|
+
### Specs
|
46
|
+
|
47
|
+
desc "Run specs"
|
48
|
+
task :spec do
|
49
|
+
sh "#{FileUtils::RUBY} -rubygems -I lib -e 'ARGV.each{|f| require f}' ./spec/*_spec.rb"
|
50
|
+
end
|
51
|
+
task :default => :spec
|
52
|
+
|
53
|
+
desc "Run specs with coverage"
|
54
|
+
task :coverage do
|
55
|
+
ENV['COVERAGE'] = '1'
|
56
|
+
Rake::Task['spec'].invoke
|
57
|
+
end
|
58
|
+
|
59
|
+
### Other
|
60
|
+
|
61
|
+
# desc "Print #{NAME} version"
|
62
|
+
# task :version do
|
63
|
+
# puts VERS.call
|
64
|
+
# end
|
65
|
+
|
66
|
+
desc "Check syntax of all .rb files"
|
67
|
+
task :check_syntax do
|
68
|
+
Dir['**/*.rb'].each{|file| print `#{ENV['RUBY'] || :ruby} -c #{file} | fgrep -v "Syntax OK"`}
|
69
|
+
end
|
70
|
+
|
71
|
+
# desc "Start an IRB shell using the extension"
|
72
|
+
# task :irb do
|
73
|
+
# require 'rbconfig'
|
74
|
+
# ruby = ENV['RUBY'] || File.join(RbConfig::CONFIG['bindir'], RbConfig::CONFIG['ruby_install_name'])
|
75
|
+
# irb = ENV['IRB'] || File.join(RbConfig::CONFIG['bindir'], File.basename(ruby).sub('ruby', 'irb'))
|
76
|
+
# sh %{#{irb} -I lib -r forme}
|
77
|
+
# end
|
78
|
+
|
@@ -0,0 +1,276 @@
|
|
1
|
+
require 'r18n-core'
|
2
|
+
|
3
|
+
class Roda
|
4
|
+
module RodaPlugins
|
5
|
+
# The i18n plugin allows you to easily add internationalisation (i18n) and
|
6
|
+
# localisation support to your Roda app, by adding the following:
|
7
|
+
#
|
8
|
+
# plugin :i18n
|
9
|
+
#
|
10
|
+
# By default the default locale is set to <tt>'en'</tt> and the translations directory
|
11
|
+
# is set to <tt>'i18n'</tt> in the rooot of your app.
|
12
|
+
#
|
13
|
+
# Both <tt>:locale</tt> and <tt>:translations</tt> can be overridden during configuration:
|
14
|
+
#
|
15
|
+
# plugin :i18n, :locale => ['de'], :translations => ['absolute/path/2/i18n']
|
16
|
+
#
|
17
|
+
# Please note!
|
18
|
+
# 1) You must set <tt>opts[:root]</tt> in your app if you don't define the <tt>:translations</tt> path.
|
19
|
+
#
|
20
|
+
# 2) When overriding <tt>:translations</tt> the path given must be absolute.
|
21
|
+
#
|
22
|
+
# The path supports 'wildcards', ie: path/**/i18n so you can load translations from multiple
|
23
|
+
# combined apps each with their own <tt>i18n</tt> folder with translations.
|
24
|
+
#
|
25
|
+
# Note! when loading translations from multiple sources and the same translation key is used
|
26
|
+
# in both files, the first loaded file takes precedence, ie: <tt>./i18n/en.yml</tt> takes precedence over
|
27
|
+
# <tt>./apps/app1/i18n/en.yml</tt>
|
28
|
+
#
|
29
|
+
# == USAGE
|
30
|
+
#
|
31
|
+
# The i18n plugin depends upon simple YAML based translations files:
|
32
|
+
#
|
33
|
+
# # app/i18n/en.yml
|
34
|
+
#
|
35
|
+
# user:
|
36
|
+
# edit: Edit user
|
37
|
+
# name: User name is %1
|
38
|
+
# count: !!pl
|
39
|
+
# 1: There is 1 user
|
40
|
+
# n: There are %1 users
|
41
|
+
#
|
42
|
+
#
|
43
|
+
# and the <tt>:t</tt> instance method to output the translations:
|
44
|
+
#
|
45
|
+
#
|
46
|
+
# t.user.edit #=> "Edit user"
|
47
|
+
# t.user.name('John') #=> "User name is John"
|
48
|
+
# t.user.count(5) #=> "There are 5 users"
|
49
|
+
#
|
50
|
+
# t.does.not.exist | 'default' #=> "default"
|
51
|
+
#
|
52
|
+
#
|
53
|
+
# the <tt>:l</tt> instance method provides built-in localisations support:
|
54
|
+
#
|
55
|
+
# l Time.now #=> "03/01/2010 18:54"
|
56
|
+
# l Time.now, :human #=> "now"
|
57
|
+
# l Time.now, :full #=> "3rd of January, 2010 18:54"
|
58
|
+
#
|
59
|
+
# Both the <tt>:t</tt> and <tt>:l</tt> methods are available in the route and template (erb) scopes. ie:
|
60
|
+
#
|
61
|
+
# route do |r|
|
62
|
+
# r.root do
|
63
|
+
# t.welcome.message
|
64
|
+
# end
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# # app/views/layout.erb
|
68
|
+
# <snip...>
|
69
|
+
# <h1><%= t.welcome.message %></h1>
|
70
|
+
# <snip...>
|
71
|
+
#
|
72
|
+
#
|
73
|
+
#
|
74
|
+
# Visit [R18n](https://github.com/ai/r18n/tree/master/r18n-core) for more information.
|
75
|
+
#
|
76
|
+
#
|
77
|
+
# The i18n plugin also makes it easy to handle locales:
|
78
|
+
#
|
79
|
+
#
|
80
|
+
# === <tt>:locale</tt> RequestMethod
|
81
|
+
#
|
82
|
+
# This request method makes it to handle translations based upon the :locale prefix on a URL,
|
83
|
+
# ie: <tt>blog.com/de/posts</tt>, just use the following code:
|
84
|
+
#
|
85
|
+
# route do |r|
|
86
|
+
#
|
87
|
+
# r.locale do
|
88
|
+
# r.is 'posts' do
|
89
|
+
# t.posts.header
|
90
|
+
# end
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
# end
|
94
|
+
#
|
95
|
+
#
|
96
|
+
# === <tt>:i18n_set_locale_from</tt> RequestMethod
|
97
|
+
#
|
98
|
+
# Obtains the locale from either ENV, HTTP (browser), Params or Session
|
99
|
+
# values
|
100
|
+
#
|
101
|
+
#
|
102
|
+
# Naturally we can allow browsers to override the default locale within routes, like this:
|
103
|
+
#
|
104
|
+
# route do |r|
|
105
|
+
# i18n_set_locale_from(:http) #=> set to the browser's default locale (en-US)
|
106
|
+
# r.get '' do
|
107
|
+
# t.hello #=> 'Howdy, I speak American English'
|
108
|
+
# end
|
109
|
+
# end
|
110
|
+
#
|
111
|
+
# The def
|
112
|
+
#
|
113
|
+
#
|
114
|
+
# route do |r|
|
115
|
+
# i18n_set_locale('de')
|
116
|
+
# r.get 'in-german' do
|
117
|
+
# t.hello #=> 'Guten tag, ich spreche deutsch'
|
118
|
+
# end
|
119
|
+
# end
|
120
|
+
#
|
121
|
+
#
|
122
|
+
#
|
123
|
+
#
|
124
|
+
module RodaI18n
|
125
|
+
|
126
|
+
def self.load_dependencies(app, opts={})
|
127
|
+
# app.plugin :render
|
128
|
+
# app.plugin :environments
|
129
|
+
end
|
130
|
+
|
131
|
+
def self.configure(app, opts={})
|
132
|
+
opts = app.opts[:i18n][:orig_opts].merge(opts) if app.opts[:i18n]
|
133
|
+
app.opts[:i18n] = opts.dup
|
134
|
+
app.opts[:i18n][:orig_opts] = opts
|
135
|
+
opts = app.opts[:i18n]
|
136
|
+
|
137
|
+
::R18n.default_places = opts[:translations] || File.expand_path('i18n', app.opts[:root])
|
138
|
+
|
139
|
+
opts[:default_locale] = opts[:locale].is_a?(Array) ? opts[:locale].first : opts[:locale] || 'en'
|
140
|
+
::R18n::I18n.default = opts[:default_locale]
|
141
|
+
|
142
|
+
::R18n.clear_cache! if ENV['RACK_ENV'] != 'production'
|
143
|
+
i18n = R18n::I18n.new(opts[:locale], ::R18n.default_places,
|
144
|
+
off_filters: :untranslated,
|
145
|
+
on_filters: :untranslated_html)
|
146
|
+
::R18n.set(i18n)
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
module RequestMethods
|
151
|
+
|
152
|
+
# Obtains the locale from either ENV, HTTP (browser), Params or Session
|
153
|
+
# values.
|
154
|
+
#
|
155
|
+
# route do |r|
|
156
|
+
# # A): set from URL params ie: GET /posts?locale=de
|
157
|
+
# r.i18n_set_locale_from(:params)
|
158
|
+
#
|
159
|
+
# # B): set from session[:locale] (if present)
|
160
|
+
# r.i18n_set_locale_from(:session)
|
161
|
+
#
|
162
|
+
# # C): set from the browser's HTTP request locale
|
163
|
+
# r.i18n_set_locale_from(:http)
|
164
|
+
#
|
165
|
+
# # D): set from the server ENV['LANG'] variable
|
166
|
+
# r.i18n_set_locale_from(:ENV)
|
167
|
+
#
|
168
|
+
#
|
169
|
+
# r.is 'posts' do
|
170
|
+
# t.posts.header # use translations
|
171
|
+
# end
|
172
|
+
# end
|
173
|
+
#
|
174
|
+
def i18n_set_locale_from(type)
|
175
|
+
case type.to_sym
|
176
|
+
when :http
|
177
|
+
_locale = ::R18n::I18n.parse_http(scope.request.env['HTTP_ACCEPT_LANGUAGE'])
|
178
|
+
when :session
|
179
|
+
_locale = session[:locale] if session[:locale]
|
180
|
+
when :params
|
181
|
+
_locale = scope.request.params['locale'] if scope.request.params['locale']
|
182
|
+
when :ENV
|
183
|
+
_locale = ENV['LANG'].split('.').first if ENV['LANG']
|
184
|
+
else
|
185
|
+
_locale = nil
|
186
|
+
end
|
187
|
+
# sanity check: set to default locale if not set above
|
188
|
+
_locale = ::R18n::I18n.default.to_s if _locale.nil?
|
189
|
+
|
190
|
+
_i18n = ::R18n::I18n.new(_locale, ::R18n.default_places,
|
191
|
+
off_filters: :untranslated,
|
192
|
+
on_filters: :untranslated_html)
|
193
|
+
::R18n.set(_i18n)
|
194
|
+
end
|
195
|
+
|
196
|
+
# Enables setting temporary :locale.
|
197
|
+
#
|
198
|
+
# route do |r|
|
199
|
+
#
|
200
|
+
# r.i18n_set_locale('de') do
|
201
|
+
# # within this block the locale is DE (German)
|
202
|
+
# end
|
203
|
+
#
|
204
|
+
# r.i18n_set_locale('es') do
|
205
|
+
# # within this block the locale is ES (Spanish)
|
206
|
+
# end
|
207
|
+
#
|
208
|
+
# end
|
209
|
+
#
|
210
|
+
def i18n_set_locale(locale, &blk)
|
211
|
+
locale = ::R18n::I18n.default.to_s if locale.nil?
|
212
|
+
|
213
|
+
_i18n = ::R18n::I18n.new(locale, ::R18n.default_places,
|
214
|
+
off_filters: :untranslated,
|
215
|
+
on_filters: :untranslated_html)
|
216
|
+
::R18n.set(_i18n)
|
217
|
+
yield
|
218
|
+
end
|
219
|
+
|
220
|
+
# Sets the locale based upon <tt>:locale</tt> prefixed routes
|
221
|
+
#
|
222
|
+
# route do |r|
|
223
|
+
# r.locale do
|
224
|
+
# # all routes are prefixed with '/:locale'
|
225
|
+
# # ie: GET /de/posts => will use DE translations
|
226
|
+
# # ie: GET /es/posts => will use ES translations
|
227
|
+
# r.is 'posts' do
|
228
|
+
# t.posts.header # use translations or locales
|
229
|
+
# end
|
230
|
+
# end
|
231
|
+
# end
|
232
|
+
#
|
233
|
+
def locale(opts={}, &blk)
|
234
|
+
on(':locale', opts) do |l|
|
235
|
+
_locale = l || self.class.opts[:locale]
|
236
|
+
session[:locale] = _locale unless session[:locale]
|
237
|
+
::R18n.set(_locale)
|
238
|
+
yield
|
239
|
+
end
|
240
|
+
end
|
241
|
+
alias_method :i18n_locale, :locale
|
242
|
+
|
243
|
+
|
244
|
+
end #/module RequestMethods
|
245
|
+
|
246
|
+
module ClassMethods
|
247
|
+
|
248
|
+
# Return the i18n options for this class.
|
249
|
+
def i18n_opts
|
250
|
+
opts[:i18n]
|
251
|
+
end
|
252
|
+
|
253
|
+
end #/module ClassMethods
|
254
|
+
|
255
|
+
module InstanceMethods
|
256
|
+
include ::R18n::Helpers
|
257
|
+
|
258
|
+
def i18n_available_locales
|
259
|
+
@available_locales = []
|
260
|
+
::R18n.available_locales.each do |l|
|
261
|
+
@available_locales << [l.code, l.title]
|
262
|
+
end
|
263
|
+
@available_locales
|
264
|
+
end
|
265
|
+
|
266
|
+
def i18n_default_places
|
267
|
+
::R18n.default_places
|
268
|
+
end
|
269
|
+
|
270
|
+
end
|
271
|
+
|
272
|
+
end #/module RodaI18n
|
273
|
+
|
274
|
+
register_plugin(:i18n, RodaI18n)
|
275
|
+
end #/module RodaPlugins
|
276
|
+
end #/class Roda
|