i18n-js 2.0.1 → 2.1.1
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.
- data/Gemfile.lock +27 -27
- data/README.rdoc +28 -7
- data/i18n-js.gemspec +1 -2
- data/lib/i18n-js.rb +54 -19
- data/lib/i18n-js/engine.rb +53 -1
- data/lib/i18n-js/middleware.rb +18 -11
- data/lib/i18n-js/railtie.rb +1 -1
- data/lib/i18n-js/version.rb +1 -1
- data/spec/i18n_spec.js +16 -0
- data/spec/i18n_spec.rb +24 -14
- data/spec/resources/no_config.yml +2 -0
- data/vendor/assets/javascripts/i18n.js +63 -43
- data/vendor/assets/javascripts/i18n/translations.js.erb +7 -0
- metadata +23 -31
data/Gemfile.lock
CHANGED
@@ -1,40 +1,40 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
i18n-js (2.
|
4
|
+
i18n-js (2.1.1)
|
5
5
|
i18n
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: http://rubygems.org/
|
9
9
|
specs:
|
10
|
-
activesupport (3.
|
11
|
-
|
12
|
-
|
13
|
-
diff-lcs (1.1.
|
10
|
+
activesupport (3.1.1)
|
11
|
+
multi_json (~> 1.0)
|
12
|
+
coderay (0.9.8)
|
13
|
+
diff-lcs (1.1.3)
|
14
14
|
fakeweb (1.3.0)
|
15
15
|
i18n (0.6.0)
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
16
|
+
method_source (0.6.7)
|
17
|
+
ruby_parser (>= 2.3.1)
|
18
|
+
multi_json (1.0.3)
|
19
|
+
notifier (0.1.4)
|
20
|
+
pry (0.9.7.4)
|
21
|
+
coderay (~> 0.9.8)
|
22
|
+
method_source (~> 0.6.7)
|
23
|
+
ruby_parser (>= 2.3.1)
|
24
|
+
slop (~> 2.1.0)
|
25
|
+
rake (0.9.2.2)
|
26
|
+
rspec (2.7.0)
|
27
|
+
rspec-core (~> 2.7.0)
|
28
|
+
rspec-expectations (~> 2.7.0)
|
29
|
+
rspec-mocks (~> 2.7.0)
|
30
|
+
rspec-core (2.7.1)
|
31
|
+
rspec-expectations (2.7.0)
|
26
32
|
diff-lcs (~> 1.1.2)
|
27
|
-
rspec-mocks (2.
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
ruby-debug19 (0.11.6)
|
33
|
-
columnize (>= 0.3.1)
|
34
|
-
linecache19 (>= 0.5.11)
|
35
|
-
ruby-debug-base19 (>= 0.11.19)
|
36
|
-
ruby_core_source (0.1.5)
|
37
|
-
archive-tar-minitar (>= 0.5.2)
|
33
|
+
rspec-mocks (2.7.0)
|
34
|
+
ruby_parser (2.3.1)
|
35
|
+
sexp_processor (~> 3.0)
|
36
|
+
sexp_processor (3.0.8)
|
37
|
+
slop (2.1.0)
|
38
38
|
spec-js (0.1.0.beta.3)
|
39
39
|
notifier
|
40
40
|
|
@@ -45,7 +45,7 @@ DEPENDENCIES
|
|
45
45
|
activesupport (>= 3.0.0)
|
46
46
|
fakeweb
|
47
47
|
i18n-js!
|
48
|
+
pry
|
48
49
|
rake
|
49
50
|
rspec (~> 2.6)
|
50
|
-
ruby-debug19
|
51
51
|
spec-js (~> 0.1.0.beta.0)
|
data/README.rdoc
CHANGED
@@ -18,18 +18,16 @@ Run <tt>rake i18n:js:setup</tt> to copy <tt>i18n.js</tt> to your javascript dire
|
|
18
18
|
|
19
19
|
==== Rails >= 3.1
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
Next add the following lines to your application.js to make the javascripts and translations available to your app:
|
21
|
+
Add the following lines to your application.js to make the javascripts and translations available to your app:
|
24
22
|
|
25
23
|
//= require i18n
|
26
24
|
//= require i18n/translations
|
27
25
|
|
28
|
-
If
|
26
|
+
If asset pipeline has been disabled for your Rails application, then you will need to run <tt>rake i18n:js:setup</tt> to copy <tt>i18n-js.yml</tt> to your config folder (if not already present).
|
29
27
|
|
30
28
|
==== Exporting translations
|
31
29
|
|
32
|
-
You can export the translations file by running
|
30
|
+
You can export the translations file by running <tt>rake i18n:js:export</tt>.
|
33
31
|
Translations will be automatically exported in development mode.
|
34
32
|
|
35
33
|
==== Configuration
|
@@ -52,6 +50,14 @@ If <tt>only</tt> is omitted all the translations will be saved. Also, make sure
|
|
52
50
|
- file: 'public/javascripts/pt-BR.js'
|
53
51
|
only: 'pt-BR.*'
|
54
52
|
|
53
|
+
Optionaly, you can auto generate a translation file per available locale if you specify the <tt>%{locale}</tt> placeholder.
|
54
|
+
|
55
|
+
translations:
|
56
|
+
- file: "public/javascripts/i18n/%{locale}.js"
|
57
|
+
only: '*'
|
58
|
+
- file: "public/javascripts/frontend/i18n/%{locale}.js"
|
59
|
+
only: ['frontend', 'users']
|
60
|
+
|
55
61
|
To find more examples on how to use the configuration file please refer to the tests.
|
56
62
|
|
57
63
|
=== On the Javascript
|
@@ -63,7 +69,7 @@ Set your locale is easy as
|
|
63
69
|
I18n.currentLocale();
|
64
70
|
// pt-BR
|
65
71
|
|
66
|
-
In practice, you'll have something like the following in your application.html.erb
|
72
|
+
In practice, you'll have something like the following in your <tt>application.html.erb</tt>:
|
67
73
|
|
68
74
|
<script type="text/javascript">
|
69
75
|
I18n.defaultLocale = "<%= I18n.default_locale %>";
|
@@ -73,6 +79,8 @@ In practice, you'll have something like the following in your application.html.e
|
|
73
79
|
You can use translate your messages:
|
74
80
|
|
75
81
|
I18n.t("some.scoped.translation");
|
82
|
+
// or translate with explicite setting of locale
|
83
|
+
I18n.t("some.scoped.translation", {locale: "fr"});
|
76
84
|
|
77
85
|
You can also interpolate values:
|
78
86
|
|
@@ -92,6 +100,19 @@ You can set default values for missing scopes:
|
|
92
100
|
// with interpolation
|
93
101
|
I18n.t("noun", {defaultValue: "I'm a {{noun}}", noun: "Mac"});
|
94
102
|
|
103
|
+
Translation fallback can be handled by taking from I18n.defaultLocale.
|
104
|
+
To allow this in your application.html.erb specify:
|
105
|
+
|
106
|
+
<script type="text/javascript">
|
107
|
+
I18n.fallbacks = true;
|
108
|
+
</script>
|
109
|
+
|
110
|
+
Then missing translation will be taken from your I18n.defaultLocale.
|
111
|
+
Example:
|
112
|
+
// if I18n.defaultLocale = "en" and translation doesn't exist for I18n.locale = "de"
|
113
|
+
I18n.t("some.missing.scope");
|
114
|
+
// this key will be taken from "en" locale scope
|
115
|
+
|
95
116
|
Pluralization is possible as well:
|
96
117
|
|
97
118
|
I18n.t("inbox.counting", {count: 10}); // You have 10 messages
|
@@ -258,7 +279,7 @@ First, install all dependencies.
|
|
258
279
|
|
259
280
|
bundle install
|
260
281
|
|
261
|
-
Then just run
|
282
|
+
Then just run <tt>rake spec</tt>.
|
262
283
|
|
263
284
|
== License
|
264
285
|
|
data/i18n-js.gemspec
CHANGED
@@ -21,8 +21,7 @@ Gem::Specification.new do |s|
|
|
21
21
|
s.add_development_dependency "fakeweb"
|
22
22
|
s.add_development_dependency "activesupport", ">= 3.0.0"
|
23
23
|
s.add_development_dependency "rspec", "~> 2.6"
|
24
|
-
s.add_development_dependency "ruby-debug19"
|
25
24
|
s.add_development_dependency "spec-js", "~> 0.1.0.beta.0"
|
26
25
|
s.add_development_dependency "rake"
|
27
|
-
s.add_development_dependency "
|
26
|
+
s.add_development_dependency "pry"
|
28
27
|
end
|
data/lib/i18n-js.rb
CHANGED
@@ -11,12 +11,25 @@ module SimplesIdeias
|
|
11
11
|
# deep_merge by Stefan Rusterholz, see http://www.ruby-forum.com/topic/142809
|
12
12
|
MERGER = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &MERGER) : v2 }
|
13
13
|
|
14
|
+
# Under rails 3.1.1 and higher, perform a check to ensure that the
|
15
|
+
# full environment will be available during asset compilation.
|
16
|
+
# This is required to ensure I18n is loaded.
|
17
|
+
def assert_usable_configuration!
|
18
|
+
@usable_configuration ||= Rails.version >= "3.1.1" &&
|
19
|
+
Rails.configuration.assets.initialize_on_precompile ||
|
20
|
+
raise("Cannot precompile i18n-js translations unless environment is initialized. Please set config.assets.initialize_on_precompile to true.")
|
21
|
+
end
|
22
|
+
|
23
|
+
def has_asset_pipeline?
|
24
|
+
Rails.configuration.respond_to?(:assets) && Rails.configuration.assets.enabled
|
25
|
+
end
|
26
|
+
|
14
27
|
def config_file
|
15
28
|
Rails.root.join("config/i18n-js.yml")
|
16
29
|
end
|
17
30
|
|
18
31
|
def export_dir
|
19
|
-
if
|
32
|
+
if has_asset_pipeline?
|
20
33
|
"app/assets/javascripts/i18n"
|
21
34
|
else
|
22
35
|
"public/javascripts"
|
@@ -30,25 +43,46 @@ module SimplesIdeias
|
|
30
43
|
# Export translations to JavaScript, considering settings
|
31
44
|
# from configuration file
|
32
45
|
def export!
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
46
|
+
translation_segments.each do |filename, translations|
|
47
|
+
save(translations, filename)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def segments_per_locale(pattern,scope)
|
52
|
+
::I18n.available_locales.each_with_object({}) do |locale,segments|
|
53
|
+
result = scoped_translations("#{locale}.#{scope}")
|
54
|
+
unless result.empty?
|
55
|
+
segment_name = ::I18n.interpolate(pattern,{:locale => locale})
|
56
|
+
segments[segment_name] = result
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def segment_for_scope(scope)
|
62
|
+
if scope == "*"
|
63
|
+
translations
|
64
|
+
else
|
65
|
+
scoped_translations(scope)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def configured_segments
|
70
|
+
config[:translations].each_with_object({}) do |options,segments|
|
71
|
+
options.reverse_merge!(:only => "*")
|
72
|
+
if options[:file] =~ ::I18n::INTERPOLATION_PATTERN
|
73
|
+
segments.merge!(segments_per_locale(options[:file],options[:only]))
|
74
|
+
else
|
75
|
+
result = segment_for_scope(options[:only])
|
76
|
+
segments[options[:file]] = result unless result.empty?
|
49
77
|
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def translation_segments
|
82
|
+
if config? && config[:translations]
|
83
|
+
configured_segments
|
50
84
|
else
|
51
|
-
|
85
|
+
{"#{export_dir}/translations.js" => translations}
|
52
86
|
end
|
53
87
|
end
|
54
88
|
|
@@ -77,7 +111,7 @@ module SimplesIdeias
|
|
77
111
|
# Retrieve an updated JavaScript library from Github.
|
78
112
|
def update!
|
79
113
|
require "open-uri"
|
80
|
-
contents = open("
|
114
|
+
contents = open("https://raw.github.com/fnando/i18n-js/master/vendor/assets/javascripts/i18n.js").read
|
81
115
|
File.open(javascript_file, "w+") {|f| f << contents}
|
82
116
|
end
|
83
117
|
|
@@ -140,3 +174,4 @@ module SimplesIdeias
|
|
140
174
|
end
|
141
175
|
end
|
142
176
|
end
|
177
|
+
|
data/lib/i18n-js/engine.rb
CHANGED
@@ -1,7 +1,59 @@
|
|
1
1
|
module SimplesIdeias
|
2
2
|
module I18n
|
3
3
|
class Engine < ::Rails::Engine
|
4
|
-
|
4
|
+
I18N_TRANSLATIONS_ASSET = "i18n/translations"
|
5
|
+
|
6
|
+
initializer "i18n-js.asset_dependencies", :after => "sprockets.environment" do
|
7
|
+
next unless SimplesIdeias::I18n.has_asset_pipeline?
|
8
|
+
|
9
|
+
config = Rails.root.join("config", "i18n-js.yml")
|
10
|
+
cache_file = I18n::Engine.load_path_hash_cache
|
11
|
+
|
12
|
+
Rails.application.assets.register_preprocessor "application/javascript", :"i18n-js_dependencies" do |context, data|
|
13
|
+
if context.logical_path == I18N_TRANSLATIONS_ASSET
|
14
|
+
context.depend_on(config)
|
15
|
+
# also set up dependencies on every locale file
|
16
|
+
::I18n.load_path.each {|path| context.depend_on(path)}
|
17
|
+
|
18
|
+
# Set up a dependency on the contents of the load path
|
19
|
+
# itself. In some situations it is possible to get here
|
20
|
+
# before the path hash cache file has been written; in
|
21
|
+
# this situation, write it now.
|
22
|
+
I18n::Engine.write_hash! unless File.exists?(cache_file)
|
23
|
+
context.depend_on(cache_file)
|
24
|
+
end
|
25
|
+
|
26
|
+
data
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# rewrite path cache hash at startup and before each request in development
|
31
|
+
config.to_prepare do
|
32
|
+
SimplesIdeias::I18n::Engine.write_hash_if_changed unless Rails.env.production?
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.load_path_hash_cache
|
36
|
+
@load_path_hash_cache ||= File.join(Rails.application.paths["tmp"].first, "i18n-js.i18n_path_cache.dat")
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.write_hash_if_changed
|
40
|
+
load_path_hash = ::I18n.load_path.hash
|
41
|
+
|
42
|
+
if load_path_hash != cached_load_path_hash
|
43
|
+
self.cached_load_path_hash = load_path_hash
|
44
|
+
write_hash!
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.write_hash!
|
49
|
+
File.open(load_path_hash_cache, "w") do |f|
|
50
|
+
f.write(cached_load_path_hash)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class << self
|
55
|
+
attr_accessor :cached_load_path_hash
|
56
|
+
end
|
5
57
|
end
|
6
58
|
end
|
7
59
|
end
|
data/lib/i18n-js/middleware.rb
CHANGED
@@ -26,26 +26,33 @@ module SimplesIdeias
|
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
+
# Check if translations should be regenerated.
|
30
|
+
# ONLY REGENERATE when these conditions are met:
|
31
|
+
#
|
32
|
+
# # Cache file doesn't exist
|
33
|
+
# # Translations and cache size are different (files were removed/added)
|
34
|
+
# # Translation file has been updated
|
35
|
+
#
|
29
36
|
def verify_locale_files!
|
30
37
|
valid_cache = []
|
31
|
-
|
38
|
+
new_cache = {}
|
32
39
|
|
33
40
|
valid_cache.push cache_path.exist?
|
34
|
-
valid_cache.push ::I18n.load_path.size == cache.size
|
41
|
+
valid_cache.push ::I18n.load_path.uniq.size == cache.size
|
35
42
|
|
36
43
|
::I18n.load_path.each do |path|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
changed_files << path if file_has_changed
|
41
|
-
cache[path] = change
|
44
|
+
changed_at = File.mtime(path).to_i
|
45
|
+
valid_cache.push changed_at == cache[path]
|
46
|
+
new_cache[path] = changed_at
|
42
47
|
end
|
43
48
|
|
44
|
-
|
45
|
-
|
46
|
-
|
49
|
+
unless valid_cache.all?
|
50
|
+
File.open(cache_path, "w+") do |file|
|
51
|
+
file << new_cache.to_yaml
|
52
|
+
end
|
47
53
|
|
48
|
-
|
54
|
+
SimplesIdeias::I18n.export!
|
55
|
+
end
|
49
56
|
end
|
50
57
|
end
|
51
58
|
end
|
data/lib/i18n-js/railtie.rb
CHANGED
@@ -6,7 +6,7 @@ module SimplesIdeias
|
|
6
6
|
end
|
7
7
|
|
8
8
|
initializer "i18n-js.initialize" do |app|
|
9
|
-
app.config.middleware.use(Middleware) if Rails.env.development?
|
9
|
+
app.config.middleware.use(Middleware) if Rails.env.development? && !SimplesIdeias::I18n.has_asset_pipeline?
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
data/lib/i18n-js/version.rb
CHANGED
data/spec/i18n_spec.js
CHANGED
@@ -135,6 +135,22 @@ describe("I18n.js", function(){
|
|
135
135
|
expect(I18n.t("greetings.stranger")).toBeEqualTo("Hello stranger!");
|
136
136
|
});
|
137
137
|
|
138
|
+
specify("translation with default locale option", function(){
|
139
|
+
expect(I18n.t("hello", {locale: "en"})).toBeEqualTo("Hello World!");
|
140
|
+
expect(I18n.t("hello", {locale: "pt-BR"})).toBeEqualTo("Olá Mundo!");
|
141
|
+
});
|
142
|
+
|
143
|
+
specify("translation should fall if locale is missing", function(){
|
144
|
+
I18n.locale = "pt-BR";
|
145
|
+
expect(I18n.t("greetings.stranger")).toBeEqualTo("[missing \"pt-BR.greetings.stranger\" translation]");
|
146
|
+
});
|
147
|
+
|
148
|
+
specify("translation should handle fallback if I18n.fallbacks == true", function(){
|
149
|
+
I18n.locale = "pt-BR";
|
150
|
+
I18n.fallbacks = true;
|
151
|
+
expect(I18n.t("greetings.stranger")).toBeEqualTo("Hello stranger!");
|
152
|
+
});
|
153
|
+
|
138
154
|
specify("single interpolation", function(){
|
139
155
|
actual = I18n.t("greetings.name", {name: "John Doe"});
|
140
156
|
expect(actual).toBeEqualTo("Hello John Doe!");
|
data/spec/i18n_spec.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
if File.basename(Rails.root) != "tmp"
|
4
|
-
|
4
|
+
abort <<-TXT
|
5
5
|
\e[31;5m
|
6
6
|
WARNING: That will remove your project!
|
7
7
|
Please go to #{File.expand_path(File.dirname(__FILE__) + "/..")} and run `rake spec`\e[0m
|
8
8
|
TXT
|
9
|
-
exit 1
|
10
9
|
end
|
11
10
|
|
12
11
|
describe SimplesIdeias::I18n do
|
@@ -88,10 +87,16 @@ describe SimplesIdeias::I18n do
|
|
88
87
|
File.should be_file(Rails.root.join("public/javascripts/tudo.js"))
|
89
88
|
end
|
90
89
|
|
90
|
+
it "ignores an empty config file" do
|
91
|
+
set_config "no_config.yml"
|
92
|
+
SimplesIdeias::I18n.export!
|
93
|
+
Rails.root.join(SimplesIdeias::I18n.export_dir, "translations.js").should be_file
|
94
|
+
end
|
95
|
+
|
91
96
|
it "exports to a JS file per available locale" do
|
92
97
|
set_config "js_file_per_locale.yml"
|
93
98
|
SimplesIdeias::I18n.export!
|
94
|
-
|
99
|
+
|
95
100
|
File.should be_file(Rails.root.join("public/javascripts/i18n/en.js"))
|
96
101
|
end
|
97
102
|
|
@@ -154,7 +159,7 @@ describe SimplesIdeias::I18n do
|
|
154
159
|
end
|
155
160
|
|
156
161
|
it "updates the javascript library" do
|
157
|
-
FakeWeb.register_uri(:get, "
|
162
|
+
FakeWeb.register_uri(:get, "https://raw.github.com/fnando/i18n-js/master/vendor/assets/javascripts/i18n.js", :body => "UPDATED")
|
158
163
|
|
159
164
|
SimplesIdeias::I18n.setup!
|
160
165
|
SimplesIdeias::I18n.update!
|
@@ -162,24 +167,28 @@ describe SimplesIdeias::I18n do
|
|
162
167
|
end
|
163
168
|
|
164
169
|
describe "#export_dir" do
|
165
|
-
it "detects
|
166
|
-
|
167
|
-
Rails.stub_chain(:configuration, :assets, :enabled => true)
|
170
|
+
it "detects asset pipeline support" do
|
171
|
+
SimplesIdeias::I18n.stub :has_asset_pipeline? => true
|
168
172
|
SimplesIdeias::I18n.export_dir == "vendor/assets/javascripts"
|
169
173
|
end
|
170
174
|
|
171
|
-
it "detects Rails 3.1 with asset pipeline disabled" do
|
172
|
-
Rails.version = "3.1"
|
173
|
-
Rails.stub_chain(:configuration, :assets, :enabled => false)
|
174
|
-
SimplesIdeias::I18n.export_dir == "public/javascripts"
|
175
|
-
end
|
176
|
-
|
177
175
|
it "detects older Rails" do
|
178
|
-
|
176
|
+
SimplesIdeias::I18n.stub :has_asset_pipeline? => false
|
179
177
|
SimplesIdeias::I18n.export_dir.to_s.should == "public/javascripts"
|
180
178
|
end
|
181
179
|
end
|
182
180
|
|
181
|
+
describe "#has_asset_pipeline?" do
|
182
|
+
it "detects support" do
|
183
|
+
Rails.stub_chain(:configuration, :assets, :enabled => true)
|
184
|
+
SimplesIdeias::I18n.should have_asset_pipeline
|
185
|
+
end
|
186
|
+
|
187
|
+
it "skips support" do
|
188
|
+
SimplesIdeias::I18n.should_not have_asset_pipeline
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
183
192
|
private
|
184
193
|
# Set the configuration as the current one
|
185
194
|
def set_config(path)
|
@@ -193,3 +202,4 @@ describe SimplesIdeias::I18n do
|
|
193
202
|
SimplesIdeias::I18n.translations
|
194
203
|
end
|
195
204
|
end
|
205
|
+
|
@@ -4,6 +4,9 @@ var I18n = I18n || {};
|
|
4
4
|
// Set default locale to english
|
5
5
|
I18n.defaultLocale = "en";
|
6
6
|
|
7
|
+
// Set default handling of translation fallbacks to false
|
8
|
+
I18n.fallbacks = false;
|
9
|
+
|
7
10
|
// Set default separator
|
8
11
|
I18n.defaultSeparator = ".";
|
9
12
|
|
@@ -13,18 +16,20 @@ I18n.locale = null;
|
|
13
16
|
// Set the placeholder format. Accepts `{{placeholder}}` and `%{placeholder}`.
|
14
17
|
I18n.PLACEHOLDER = /(?:\{\{|%\{)(.*?)(?:\}\}?)/gm;
|
15
18
|
|
16
|
-
I18n.isValidNode = function(obj, node) {
|
17
|
-
|
18
|
-
var undef;
|
19
|
-
return obj[node] !== null && obj[node] !== undef;
|
19
|
+
I18n.isValidNode = function(obj, node, undefined) {
|
20
|
+
return obj[node] !== null && obj[node] !== undefined;
|
20
21
|
}
|
21
22
|
|
22
23
|
I18n.lookup = function(scope, options) {
|
23
|
-
var
|
24
|
-
|
25
|
-
|
24
|
+
var options = options || {}
|
25
|
+
, lookupInitialScope = scope
|
26
|
+
, translations = this.prepareOptions(I18n.translations)
|
27
|
+
, messages = translations[options.locale || I18n.currentLocale()]
|
28
|
+
, options = this.prepareOptions(options)
|
29
|
+
, currentScope
|
30
|
+
;
|
26
31
|
|
27
|
-
if (!messages)
|
32
|
+
if (!messages){
|
28
33
|
return;
|
29
34
|
}
|
30
35
|
|
@@ -39,10 +44,13 @@ I18n.lookup = function(scope, options) {
|
|
39
44
|
scope = scope.split(this.defaultSeparator);
|
40
45
|
|
41
46
|
while (scope.length > 0) {
|
42
|
-
|
47
|
+
currentScope = scope.shift();
|
43
48
|
messages = messages[currentScope];
|
44
49
|
|
45
50
|
if (!messages) {
|
51
|
+
if (I18n.fallbacks && !options.fallback) {
|
52
|
+
messages = I18n.lookup(lookupInitialScope, this.prepareOptions({ locale: I18n.defaultLocale, fallback: true }, options));
|
53
|
+
}
|
46
54
|
break;
|
47
55
|
}
|
48
56
|
}
|
@@ -61,9 +69,10 @@ I18n.lookup = function(scope, options) {
|
|
61
69
|
// #=> {name: "John Doe", role: "user"}
|
62
70
|
//
|
63
71
|
I18n.prepareOptions = function() {
|
64
|
-
var options = {}
|
65
|
-
|
66
|
-
|
72
|
+
var options = {}
|
73
|
+
, opts
|
74
|
+
, count = arguments.length
|
75
|
+
;
|
67
76
|
|
68
77
|
for (var i = 0; i < count; i++) {
|
69
78
|
opts = arguments[i];
|
@@ -84,14 +93,16 @@ I18n.prepareOptions = function() {
|
|
84
93
|
|
85
94
|
I18n.interpolate = function(message, options) {
|
86
95
|
options = this.prepareOptions(options);
|
87
|
-
var matches = message.match(this.PLACEHOLDER)
|
96
|
+
var matches = message.match(this.PLACEHOLDER)
|
97
|
+
, placeholder
|
98
|
+
, value
|
99
|
+
, name
|
100
|
+
;
|
88
101
|
|
89
102
|
if (!matches) {
|
90
103
|
return message;
|
91
104
|
}
|
92
105
|
|
93
|
-
var placeholder, value, name;
|
94
|
-
|
95
106
|
for (var i = 0; placeholder = matches[i]; i++) {
|
96
107
|
name = placeholder.replace(this.PLACEHOLDER, "$1");
|
97
108
|
|
@@ -193,8 +204,9 @@ I18n.parseDate = function(date) {
|
|
193
204
|
};
|
194
205
|
|
195
206
|
I18n.toTime = function(scope, d) {
|
196
|
-
var date = this.parseDate(d)
|
197
|
-
|
207
|
+
var date = this.parseDate(d)
|
208
|
+
, format = this.lookup(scope)
|
209
|
+
;
|
198
210
|
|
199
211
|
if (date.toString().match(/invalid/i)) {
|
200
212
|
return date.toString();
|
@@ -213,21 +225,23 @@ I18n.strftime = function(date, format) {
|
|
213
225
|
if (!options) {
|
214
226
|
return date.toString();
|
215
227
|
}
|
228
|
+
|
216
229
|
options.meridian = options.meridian || ["AM", "PM"];
|
217
230
|
|
218
|
-
var weekDay = date.getDay()
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
+
var weekDay = date.getDay()
|
232
|
+
, day = date.getDate()
|
233
|
+
, year = date.getFullYear()
|
234
|
+
, month = date.getMonth() + 1
|
235
|
+
, hour = date.getHours()
|
236
|
+
, hour12 = hour
|
237
|
+
, meridian = hour > 11 ? 1 : 0
|
238
|
+
, secs = date.getSeconds()
|
239
|
+
, mins = date.getMinutes()
|
240
|
+
, offset = date.getTimezoneOffset()
|
241
|
+
, absOffsetHours = Math.floor(Math.abs(offset / 60))
|
242
|
+
, absOffsetMinutes = Math.abs(offset) - (absOffsetHours * 60)
|
243
|
+
, timezoneoffset = (offset > 0 ? "-" : "+") + (absOffsetHours.toString().length < 2 ? "0" + absOffsetHours : absOffsetHours) + (absOffsetMinutes.toString().length < 2 ? "0" + absOffsetMinutes : absOffsetMinutes)
|
244
|
+
;
|
231
245
|
|
232
246
|
if (hour12 > 12) {
|
233
247
|
hour12 = hour12 - 12;
|
@@ -275,21 +289,23 @@ I18n.toNumber = function(number, options) {
|
|
275
289
|
{precision: 3, separator: ".", delimiter: ",", strip_insignificant_zeros: false}
|
276
290
|
);
|
277
291
|
|
278
|
-
var negative = number < 0
|
279
|
-
|
280
|
-
|
292
|
+
var negative = number < 0
|
293
|
+
, string = Math.abs(number).toFixed(options.precision).toString()
|
294
|
+
, parts = string.split(".")
|
295
|
+
, precision
|
296
|
+
, buffer = []
|
297
|
+
, formattedNumber
|
298
|
+
;
|
281
299
|
|
282
300
|
number = parts[0];
|
283
|
-
|
284
|
-
|
285
|
-
var n = [];
|
301
|
+
precision = parts[1];
|
286
302
|
|
287
303
|
while (number.length > 0) {
|
288
|
-
|
304
|
+
buffer.unshift(number.substr(Math.max(0, number.length - 3), 3));
|
289
305
|
number = number.substr(0, number.length -3);
|
290
306
|
}
|
291
307
|
|
292
|
-
|
308
|
+
formattedNumber = buffer.join(options.delimiter);
|
293
309
|
|
294
310
|
if (options.precision > 0) {
|
295
311
|
formattedNumber += options.separator + parts[1];
|
@@ -307,7 +323,8 @@ I18n.toNumber = function(number, options) {
|
|
307
323
|
|
308
324
|
formattedNumber = formattedNumber
|
309
325
|
.replace(regex.zeros, "")
|
310
|
-
.replace(regex.separator, "")
|
326
|
+
.replace(regex.separator, "")
|
327
|
+
;
|
311
328
|
}
|
312
329
|
|
313
330
|
return formattedNumber;
|
@@ -324,7 +341,8 @@ I18n.toCurrency = function(number, options) {
|
|
324
341
|
number = this.toNumber(number, options);
|
325
342
|
number = options.format
|
326
343
|
.replace("%u", options.unit)
|
327
|
-
.replace("%n", number)
|
344
|
+
.replace("%n", number)
|
345
|
+
;
|
328
346
|
|
329
347
|
return number;
|
330
348
|
};
|
@@ -358,7 +376,8 @@ I18n.toHumanSize = function(number, options) {
|
|
358
376
|
number = this.toNumber(size, options);
|
359
377
|
number = options.format
|
360
378
|
.replace("%u", unit)
|
361
|
-
.replace("%n", number)
|
379
|
+
.replace("%n", number)
|
380
|
+
;
|
362
381
|
|
363
382
|
return number;
|
364
383
|
};
|
@@ -408,8 +427,9 @@ I18n.pluralize = function(count, scope, options) {
|
|
408
427
|
};
|
409
428
|
|
410
429
|
I18n.missingTranslation = function() {
|
411
|
-
var message = '[missing "' + this.currentLocale()
|
412
|
-
|
430
|
+
var message = '[missing "' + this.currentLocale()
|
431
|
+
, count = arguments.length
|
432
|
+
;
|
413
433
|
|
414
434
|
for (var i = 0; i < count; i++) {
|
415
435
|
message += "." + arguments[i];
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: i18n-js
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
12
|
+
date: 2011-11-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: i18n
|
16
|
-
requirement: &
|
16
|
+
requirement: &70281327448420 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70281327448420
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: fakeweb
|
27
|
-
requirement: &
|
27
|
+
requirement: &70281327447820 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70281327447820
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: activesupport
|
38
|
-
requirement: &
|
38
|
+
requirement: &70281327437540 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 3.0.0
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70281327437540
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: rspec
|
49
|
-
requirement: &
|
49
|
+
requirement: &70281327436980 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ~>
|
@@ -54,21 +54,10 @@ dependencies:
|
|
54
54
|
version: '2.6'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
58
|
-
- !ruby/object:Gem::Dependency
|
59
|
-
name: ruby-debug19
|
60
|
-
requirement: &70095310293060 !ruby/object:Gem::Requirement
|
61
|
-
none: false
|
62
|
-
requirements:
|
63
|
-
- - ! '>='
|
64
|
-
- !ruby/object:Gem::Version
|
65
|
-
version: '0'
|
66
|
-
type: :development
|
67
|
-
prerelease: false
|
68
|
-
version_requirements: *70095310293060
|
57
|
+
version_requirements: *70281327436980
|
69
58
|
- !ruby/object:Gem::Dependency
|
70
59
|
name: spec-js
|
71
|
-
requirement: &
|
60
|
+
requirement: &70281327436280 !ruby/object:Gem::Requirement
|
72
61
|
none: false
|
73
62
|
requirements:
|
74
63
|
- - ~>
|
@@ -76,10 +65,10 @@ dependencies:
|
|
76
65
|
version: 0.1.0.beta.0
|
77
66
|
type: :development
|
78
67
|
prerelease: false
|
79
|
-
version_requirements: *
|
68
|
+
version_requirements: *70281327436280
|
80
69
|
- !ruby/object:Gem::Dependency
|
81
70
|
name: rake
|
82
|
-
requirement: &
|
71
|
+
requirement: &70281327435620 !ruby/object:Gem::Requirement
|
83
72
|
none: false
|
84
73
|
requirements:
|
85
74
|
- - ! '>='
|
@@ -87,10 +76,10 @@ dependencies:
|
|
87
76
|
version: '0'
|
88
77
|
type: :development
|
89
78
|
prerelease: false
|
90
|
-
version_requirements: *
|
79
|
+
version_requirements: *70281327435620
|
91
80
|
- !ruby/object:Gem::Dependency
|
92
|
-
name:
|
93
|
-
requirement: &
|
81
|
+
name: pry
|
82
|
+
requirement: &70281327434980 !ruby/object:Gem::Requirement
|
94
83
|
none: false
|
95
84
|
requirements:
|
96
85
|
- - ! '>='
|
@@ -98,7 +87,7 @@ dependencies:
|
|
98
87
|
version: '0'
|
99
88
|
type: :development
|
100
89
|
prerelease: false
|
101
|
-
version_requirements: *
|
90
|
+
version_requirements: *70281327434980
|
102
91
|
description: It's a small library to provide the Rails I18n translations on the Javascript.
|
103
92
|
email:
|
104
93
|
- fnando.vieira@gmail.com
|
@@ -128,10 +117,12 @@ files:
|
|
128
117
|
- spec/resources/locales.yml
|
129
118
|
- spec/resources/multiple_conditions.yml
|
130
119
|
- spec/resources/multiple_files.yml
|
120
|
+
- spec/resources/no_config.yml
|
131
121
|
- spec/resources/no_scope.yml
|
132
122
|
- spec/resources/simple_scope.yml
|
133
123
|
- spec/spec_helper.rb
|
134
124
|
- vendor/assets/javascripts/i18n.js
|
125
|
+
- vendor/assets/javascripts/i18n/translations.js.erb
|
135
126
|
homepage: http://rubygems.org/gems/i18n-js
|
136
127
|
licenses: []
|
137
128
|
post_install_message:
|
@@ -146,7 +137,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
146
137
|
version: '0'
|
147
138
|
segments:
|
148
139
|
- 0
|
149
|
-
hash:
|
140
|
+
hash: -2888069354346865938
|
150
141
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
151
142
|
none: false
|
152
143
|
requirements:
|
@@ -155,10 +146,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
155
146
|
version: '0'
|
156
147
|
segments:
|
157
148
|
- 0
|
158
|
-
hash:
|
149
|
+
hash: -2888069354346865938
|
159
150
|
requirements: []
|
160
151
|
rubyforge_project:
|
161
|
-
rubygems_version: 1.8.
|
152
|
+
rubygems_version: 1.8.11
|
162
153
|
signing_key:
|
163
154
|
specification_version: 3
|
164
155
|
summary: It's a small library to provide the Rails I18n translations on the Javascript.
|
@@ -171,6 +162,7 @@ test_files:
|
|
171
162
|
- spec/resources/locales.yml
|
172
163
|
- spec/resources/multiple_conditions.yml
|
173
164
|
- spec/resources/multiple_files.yml
|
165
|
+
- spec/resources/no_config.yml
|
174
166
|
- spec/resources/no_scope.yml
|
175
167
|
- spec/resources/simple_scope.yml
|
176
168
|
- spec/spec_helper.rb
|