i18n-js 3.0.0.rc6 → 3.0.0.rc7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 37f6e669f9c581fd9b82bf2141dc6829b1a32d21
4
- data.tar.gz: 5203d02a3ce1445054f036930c7cca0bf2103809
3
+ metadata.gz: 4377851d9bebcdaf860e76c466587f7486255752
4
+ data.tar.gz: 9b52dbf3c12aca86c6de92073323dcb5dbeb02f0
5
5
  SHA512:
6
- metadata.gz: 65ee86cbca52f2b511e9f39511308ae0640d0c1fb3099f685687eabe9d2cad4b4f28e08a389fd1b8c70bd3f71c5b475f4d1d8fa28ca07e4a4820fdfc8a496bfb
7
- data.tar.gz: a0f657c665ddc48f6c49b25321dd3ed15fa66407a9baa24ee91386604f98bd1fbf1bc40fdab23460f2c4246e12f8a63512ea6dd12b172c5f256651264a118aaf
6
+ metadata.gz: d33c4c88cdbcbeda6233f65a7455d5cfec3b958f3b4aa74f04cbe0ecd4896f7fdd9ee7a853deaae44c932ae9d127146128df24a00f6a2956c31c4f73f8474738
7
+ data.tar.gz: f8333679e32ad823e9c5946734c031f761609dc30ac8a15b143b030d2d85e6c68dbba0073192a020da39a4aaa1057ae1cad4e60f47459c86dd03b3d3d34dcce2
data/.travis.yml CHANGED
@@ -1,10 +1,19 @@
1
1
  language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
- - 2.0.0
5
- - 2.1.2
4
+ - 2.0
5
+ - 2.1
6
+ - 2.2
7
+ - ruby-head
6
8
  script: "bundle exec rake spec"
7
9
  before_install: # Need to install npm to test js
8
10
  - sudo apt-get update
9
11
  - sudo apt-get install npm
10
12
  - npm install jasmine-node@1.14.2
13
+ gemfile:
14
+ - gemfiles/i18n_0_6.gemfile
15
+ matrix:
16
+ fast_finish: true
17
+ allow_failures:
18
+ - rvm: 2.2
19
+ - rvm: ruby-head
data/Appraisals CHANGED
@@ -1,4 +1,4 @@
1
1
 
2
2
  appraise "i18n-0-6" do
3
- gem 'i18n', '0.6.9'
3
+ gem 'i18n', '0.6.11'
4
4
  end
data/CHANGELOG.md CHANGED
@@ -1,3 +1,25 @@
1
+
2
+ ## Unreleased
3
+
4
+ ### enhancements
5
+
6
+ - The Rails Engine initializer is now named as `i18n-js.register_preprocessor` (https://github.com/fnando/i18n-js/pull/261)
7
+ - Rename `I18n::JS.config_file` to `I18n::JS.config_file_path` and make it configurable
8
+ Expected a `String`, default is still `config/i18n-js.yml`
9
+ - When running `rake i18n:js:export`, the `i18n.js` will also be exported to `I18n::JS.export_i18n_js_dir_path` by default
10
+ - Add `I18n::JS.export_i18n_js_dir_path`
11
+ Expected a `String`, default is `public/javascripts`
12
+ Set to `nil` will disable exporting `i18n.js`
13
+
14
+ ### bug fixes
15
+
16
+ - Prevent toString() call on `undefined` when there is a missing interpolation value
17
+ - Added support for Rails instances without Sprockets object (https://github.com/fnando/i18n-js/pull/241)
18
+ - Fix `DEFAULT_OPTIONS` in `i18n.js` which contained an excessive comma
19
+ - Fix `nil` values are exported into JS files which causes strange translation error
20
+ - Fix pattern to replace all escaped $ in I18n.translate
21
+ - Fix JS `I18n.lookup` modifies existing locales accidentally
22
+
1
23
  ## 3.0.0.rc6
2
24
 
3
25
  ### enhancements
data/README.md CHANGED
@@ -32,37 +32,42 @@ If you're using the [asset pipeline](http://guides.rubyonrails.org/asset_pipelin
32
32
  then you must add the following line to your `app/assets/javascripts/application.js`.
33
33
 
34
34
  ```javascript
35
+ //
36
+ // This is optional (in case you have `I18n is not defined` error)
37
+ // If you want to put this line, you must put it BEFORE `i18n/translations`
38
+ //= require i18n
39
+ //
40
+ // This is a must
35
41
  //= require i18n/translations
36
42
  ```
37
43
 
38
44
  #### Rails app without [Asset Pipeline](http://guides.rubyonrails.org/asset_pipeline.html)
39
45
 
40
- If you're not using the asset pipeline, download the JavaScript file at
41
- <https://github.com/fnando/i18n-js/tree/master/lib/i18n.js> and load it on your page.
42
- Also load the `translations.js` file.
43
46
 
47
+ First, put this in your `application.html` (layout file).
48
+ Then get the JS files following the instructions below.
44
49
  ```erb
45
- <%= javascript_include_tag "i18n", "translations" %>
50
+ <%# This is just an example, you can put `i18n.js` and `translations.js` anywhere you like %>
51
+ <%# Unlike the Asset Pipeline example, you need to require both **in order** %>
52
+ <%= javascript_include_tag "i18n" %>
53
+ <%= javascript_include_tag "translations" %>
46
54
  ```
47
55
 
48
- This `translations.js` file can be automatically generated by the `I18n::JS::Middleware`.
49
- Just add it to your `config/application.rb` file.
50
- Don't add this middleware if you are using [asset pipeline](http://guides.rubyonrails.org/asset_pipeline.html)!
56
+ **There are two ways to get `translations.js`.**
51
57
 
52
- config.middleware.use I18n::JS::Middleware
58
+ 1. This `translations.js` file can be automatically generated by the `I18n::JS::Middleware`.
59
+ Just add `config.middleware.use I18n::JS::Middleware` to your `config/application.rb` file.
60
+ Notice: Don't add this middleware if you are using [asset pipeline](http://guides.rubyonrails.org/asset_pipeline.html)!
61
+ 2. If you can't or prefer not to generate this file,
62
+ you can move the middleware line to your `config/environments/development.rb` file
63
+ and run `rake i18n:js:export` before deploying.
64
+ This will export all translation files, including the custom scopes
65
+ you may have defined on `config/i18n-js.yml`.
66
+ If `I18n.available_locales` is set (e.g. in your Rails `config/application.rb` file)
67
+ then only the specified locales will be exported.
68
+ Current version of `i18n.js` will also be exported to avoid version mismatching by downloading.
53
69
 
54
- If you can't generate this file in production (Heroku anyone?), you can "precompile"
55
- it by running the following command. Move the middleware line to your
56
- `config/environments/development.rb` file and run the following command before
57
- deploying.
58
-
59
- $ rake i18n:js:export
60
-
61
- This will export all translation files, including the custom scopes you may have
62
- defined on `config/i18n-js.yml`. If `I18n.available_locales` is set (e.g. in your
63
- Rails `config/application.rb` file) then only the specified locales will be exported.
64
-
65
- #### Export Configuration
70
+ #### Export Configuration (For translations)
66
71
 
67
72
  Exported translation files generated by `I18n::JS::Middleware` or `rake i18n:js:export` can be customized with config file `config/i18n-js.yml` (use `rails generate i18n:js:config` to create it). You can even get more files generated to different folders and with different translations to best suit your needs. But this does not affect anything if you use Asset Pipeline.
68
73
 
@@ -102,6 +107,18 @@ translations:
102
107
  <% end %>
103
108
  ```
104
109
 
110
+ #### Export Configuration (For other things)
111
+ - `I18n::JS.config_file_path`
112
+ Expected Type: `String`
113
+ Default: `config/i18n-js.yml`
114
+ Behaviour: Try to read the config file from that location
115
+ - `I18n::JS.export_i18n_js_dir_path`
116
+ Expected Type: `String`
117
+ Default: `public/javascripts`
118
+ Behaviour:
119
+ - Any `String`: considered as a relative path for a folder to `Rails.root` and export `i18n.js` to that folder for `rake i18n:js:export`
120
+ - `nil`: Disable `i18n.js` exporting
121
+
105
122
  To find more examples on how to use the configuration file please refer to the tests.
106
123
 
107
124
  #### Vanilla JavaScript
@@ -213,7 +230,8 @@ The sample above expects the following translation:
213
230
  If you need special rules just define them for your language, for example Russian, just add a new pluralizer:
214
231
 
215
232
  I18n.pluralization["ru"] = function (count) {
216
- return count % 10 == 1 && count % 100 != 11 ? "one" : [2, 3, 4].indexOf(count % 10) >= 0 && [12, 13, 14].indexOf(count % 100) < 0 ? "few" : count % 10 == 0 || [5, 6, 7, 8, 9].indexOf(count % 10) >= 0 || [11, 12, 13, 14].indexOf(count % 100) >= 0 ? "many" : "other";
233
+ var key = count % 10 == 1 && count % 100 != 11 ? "one" : [2, 3, 4].indexOf(count % 10) >= 0 && [12, 13, 14].indexOf(count % 100) < 0 ? "few" : count % 10 == 0 || [5, 6, 7, 8, 9].indexOf(count % 10) >= 0 || [11, 12, 13, 14].indexOf(count % 100) >= 0 ? "many" : "other";
234
+ return [key];
217
235
  };
218
236
 
219
237
  You can find all rules on <http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html>.
@@ -349,6 +367,32 @@ The only requirement is that you need to set the `translations` attribute like f
349
367
  message: "Uma mensagem especial para você"
350
368
  }
351
369
 
370
+ ## Known Issues
371
+
372
+ ### Missing translations in precompiled file(s) after adding any new locale file
373
+
374
+ Due to the design of `sprockets`:
375
+ - `depend_on` only takes file paths, not directory paths
376
+ - registered `preprocessors` are only run when fingerprint of any asset file, including `.erb` files, is changed
377
+
378
+ New locale files won't be picked up unless any existing locale file content is changed.
379
+ You can workaround it manually by running
380
+ ```bash
381
+ $ rake assets:clobber
382
+ ```
383
+ to clear the asset cache.
384
+ **Or**
385
+ Change something in existing locale file.
386
+ **Or**
387
+ Change `config.assets.version`
388
+
389
+ **Note:** `rake assets:clobber` will also remove all fingerprinted assets.
390
+ If you are precompiling assets on target machine(s),
391
+ old assets might be removed and cannot be served in cached pages.
392
+
393
+ Please see issue #213 for detail & related discussion.
394
+
395
+
352
396
  ## Maintainer
353
397
 
354
398
  - Nando Vieira - <http://nandovieira.com.br>
@@ -65,7 +65,7 @@
65
65
  defaultSeparator: ".",
66
66
  placeholder: /(?:\{\{|%\{)(.*?)(?:\}\}?)/gm,
67
67
  fallbacks: false,
68
- translations: {},
68
+ translations: {}
69
69
  };
70
70
 
71
71
  I18n.reset = function() {
@@ -228,7 +228,7 @@
228
228
  I18n.lookup = function(scope, options) {
229
229
  options = this.prepareOptions(options);
230
230
 
231
- var locales = this.locales.get(options.locale)
231
+ var locales = this.locales.get(options.locale).slice()
232
232
  , requestedLocale = locales[0]
233
233
  , locale
234
234
  , scopes
@@ -399,12 +399,15 @@
399
399
  return message;
400
400
  }
401
401
 
402
+ var value;
403
+
402
404
  while (matches.length) {
403
405
  placeholder = matches.shift();
404
406
  name = placeholder.replace(this.placeholder, "$1");
405
- value = options[name].toString().replace(/\$/gm, "_#$#_");
406
407
 
407
- if (!this.isSet(options[name])) {
408
+ if (this.isSet(options[name])) {
409
+ value = options[name].toString().replace(/\$/gm, "_#$#_");
410
+ } else {
408
411
  value = this.missingPlaceholder(placeholder, message);
409
412
  }
410
413
 
@@ -412,7 +415,7 @@
412
415
  message = message.replace(regex, value);
413
416
  }
414
417
 
415
- return message.replace("_#$#_", "$");
418
+ return message.replace(/_#\$#_/g, "$");
416
419
  };
417
420
 
418
421
  // Pluralize the given scope using the `count` value.
@@ -2,6 +2,6 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "i18n", "0.6.9"
5
+ gem "i18n", "0.6.11"
6
6
 
7
7
  gemspec :path => "../"
data/i18n-js.gemspec CHANGED
@@ -11,6 +11,7 @@ Gem::Specification.new do |s|
11
11
  s.homepage = "http://rubygems.org/gems/i18n-js"
12
12
  s.summary = "It's a small library to provide the Rails I18n translations on the Javascript."
13
13
  s.description = s.summary
14
+ s.license = "MIT"
14
15
 
15
16
  s.files = `git ls-files`.split("\n")
16
17
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -24,4 +25,6 @@ Gem::Specification.new do |s|
24
25
  s.add_development_dependency "rake"
25
26
  s.add_development_dependency "pry-meta"
26
27
  s.add_development_dependency "gem-release", ">= 0.7"
28
+
29
+ s.required_ruby_version = ">= 1.9.3"
27
30
  end
data/lib/i18n/js.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  require "i18n"
2
2
  require "fileutils"
3
3
 
4
+ require "i18n/js/utils"
5
+
4
6
  module I18n
5
7
  module JS
6
8
  require "i18n/js/dependencies"
@@ -9,20 +11,23 @@ module I18n
9
11
  require "i18n/js/engine"
10
12
  end
11
13
 
12
- # deep_merge by Stefan Rusterholz, see <http://www.ruby-forum.com/topic/142809>.
13
- MERGER = proc do |key, v1, v2|
14
- Hash === v1 && Hash === v2 ? v1.merge(v2, &MERGER) : v2
15
- end
14
+ DEFAULT_CONFIG_PATH = "config/i18n-js.yml"
15
+ DEFAULT_EXPORT_DIR_PATH = "public/javascripts"
16
16
 
17
17
  # The configuration file. This defaults to the `config/i18n-js.yml` file.
18
18
  #
19
- def self.config_file
20
- @config_file ||= "config/i18n-js.yml"
19
+ def self.config_file_path
20
+ @config_file_path ||= DEFAULT_CONFIG_PATH
21
+ end
22
+ def self.config_file_path=(new_path)
23
+ @config_file_path = new_path
21
24
  end
22
25
 
23
26
  # Export translations to JavaScript, considering settings
24
27
  # from configuration file
25
28
  def self.export
29
+ export_i18n_js
30
+
26
31
  translation_segments.each do |filename, translations|
27
32
  save(translations, filename)
28
33
  end
@@ -59,14 +64,10 @@ module I18n
59
64
  end
60
65
  end
61
66
 
62
- def self.export_dir
63
- "public/javascripts"
64
- end
65
-
66
67
  def self.filtered_translations
67
68
  {}.tap do |result|
68
69
  translation_segments.each do |filename, translations|
69
- deep_merge!(result, translations)
70
+ Utils.deep_merge!(result, translations)
70
71
  end
71
72
  end
72
73
  end
@@ -75,7 +76,7 @@ module I18n
75
76
  if config? && config[:translations]
76
77
  configured_segments
77
78
  else
78
- {"#{export_dir}/translations.js" => translations}
79
+ {"#{DEFAULT_EXPORT_DIR_PATH}/translations.js" => translations}
79
80
  end
80
81
  end
81
82
 
@@ -83,7 +84,7 @@ module I18n
83
84
  # custom output directory
84
85
  def self.config
85
86
  if config?
86
- erb = ERB.new(File.read(config_file)).result
87
+ erb = ERB.new(File.read(config_file_path)).result
87
88
  (YAML.load(erb) || {}).with_indifferent_access
88
89
  else
89
90
  {}
@@ -92,7 +93,7 @@ module I18n
92
93
 
93
94
  # Check if configuration file exist
94
95
  def self.config?
95
- File.file? config_file
96
+ File.file? config_file_path
96
97
  end
97
98
 
98
99
  # Convert translations to JSON string and save file.
@@ -101,7 +102,7 @@ module I18n
101
102
 
102
103
  File.open(file, "w+") do |f|
103
104
  f << %(I18n.translations || (I18n.translations = {});\n)
104
- translations.each do |locale, translations_for_locale|
105
+ Utils.strip_keys_with_nil_values(translations).each do |locale, translations_for_locale|
105
106
  f << %(I18n.translations["#{locale}"] = #{translations_for_locale.to_json};\n);
106
107
  end
107
108
  end
@@ -111,7 +112,7 @@ module I18n
111
112
  result = {}
112
113
 
113
114
  [scopes].flatten.each do |scope|
114
- deep_merge! result, filter(translations, scope)
115
+ Utils.deep_merge! result, filter(translations, scope)
115
116
  end
116
117
 
117
118
  result
@@ -144,12 +145,27 @@ module I18n
144
145
  end
145
146
  end
146
147
 
147
- def self.deep_merge(target, hash) # :nodoc:
148
- target.merge(hash, &MERGER)
149
- end
150
148
 
151
- def self.deep_merge!(target, hash) # :nodoc:
152
- target.merge!(hash, &MERGER)
149
+ ### Export i18n.js
150
+ begin
151
+ # Copy i18n.js
152
+ def self.export_i18n_js
153
+ return if export_i18n_js_dir_path.nil?
154
+
155
+ FileUtils.mkdir_p(export_i18n_js_dir_path)
156
+
157
+ i18n_js_path = File.expand_path('../../../app/assets/javascripts/i18n.js', __FILE__)
158
+ FileUtils.cp(i18n_js_path, export_i18n_js_dir_path)
159
+ end
160
+ def self.export_i18n_js_dir_path
161
+ return @export_i18n_js_dir_path if defined?(@export_i18n_js_dir_path)
162
+
163
+ @export_i18n_js_dir_path = DEFAULT_EXPORT_DIR_PATH
164
+ end
165
+ # Setting this to nil would disable i18n.js exporting
166
+ def self.export_i18n_js_dir_path=(new_path)
167
+ @export_i18n_js_dir_path = new_path
168
+ end
153
169
  end
154
170
  end
155
171
  end
@@ -10,6 +10,10 @@ module I18n
10
10
  safe_gem_check("rails", "~> 4") && running_rails4?
11
11
  end
12
12
 
13
+ def sprockets_supports_register_preprocessor?
14
+ defined?(Sprockets) && Sprockets.respond_to?(:register_preprocessor)
15
+ end
16
+
13
17
  def rails?
14
18
  rails_available? && running_rails?
15
19
  end
@@ -3,8 +3,9 @@ require "i18n/js"
3
3
  module I18n
4
4
  module JS
5
5
  class Engine < ::Rails::Engine
6
- initializer :after => "sprockets.environment" do
6
+ initializer "i18n-js.register_preprocessor", :after => "sprockets.environment" do
7
7
  next unless JS::Dependencies.using_asset_pipeline?
8
+ next unless JS::Dependencies.sprockets_supports_register_preprocessor?
8
9
  next unless Rails.configuration.assets.compile
9
10
 
10
11
  Rails.application.assets.register_preprocessor "application/javascript", :"i18n-js_dependencies" do |context, source|
@@ -0,0 +1,26 @@
1
+ module I18n
2
+ module JS
3
+ module Utils
4
+ # deep_merge by Stefan Rusterholz, see <http://www.ruby-forum.com/topic/142809>.
5
+ MERGER = proc do |key, v1, v2|
6
+ Hash === v1 && Hash === v2 ? v1.merge(v2, &MERGER) : v2
7
+ end
8
+ HASH_NIL_VALUE_CLEANER_PROC = proc do |k, v|
9
+ v.kind_of?(Hash) ? (v.delete_if(&HASH_NIL_VALUE_CLEANER_PROC); false) : v.nil?
10
+ end
11
+
12
+
13
+ def self.strip_keys_with_nil_values(hash)
14
+ hash.dup.delete_if(&HASH_NIL_VALUE_CLEANER_PROC)
15
+ end
16
+
17
+ def self.deep_merge(target_hash, hash) # :nodoc:
18
+ target_hash.merge(hash, &MERGER)
19
+ end
20
+
21
+ def self.deep_merge!(target_hash, hash) # :nodoc:
22
+ target_hash.merge!(hash, &MERGER)
23
+ end
24
+ end
25
+ end
26
+ end
@@ -4,7 +4,7 @@ module I18n
4
4
  MAJOR = 3
5
5
  MINOR = 0
6
6
  PATCH = 0
7
- STRING = "#{MAJOR}.#{MINOR}.#{PATCH}.rc6"
7
+ STRING = "#{MAJOR}.#{MINOR}.#{PATCH}.rc7"
8
8
  end
9
9
  end
10
10
  end
data/spec/i18n_js_spec.rb CHANGED
@@ -1,9 +1,25 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe I18n::JS do
4
+ describe '.config_file_path' do
5
+ let(:default_path) { I18n::JS::DEFAULT_CONFIG_PATH }
6
+ let(:new_path) { File.join("tmp", default_path) }
7
+
8
+ subject { described_class.config_file_path }
9
+
10
+ context "when it is not set" do
11
+ it { should eq default_path }
12
+ end
13
+ context "when it is set already" do
14
+ before { described_class.config_file_path = new_path }
15
+
16
+ it { should eq new_path }
17
+ end
18
+ end
19
+
4
20
  context "exporting" do
5
21
  before do
6
- I18n::JS.stub :export_dir => temp_path
22
+ stub_const('I18n::JS::DEFAULT_EXPORT_DIR_PATH', temp_path)
7
23
  end
8
24
 
9
25
  it "exports messages to default path when configuration file doesn't exist" do
@@ -65,6 +81,12 @@ describe I18n::JS do
65
81
  result["tmp/i18n-js/bits.#{lang}.js"][lang.to_sym].keys.sort.should eql([:date, :number])
66
82
  end
67
83
  end
84
+
85
+ it "calls .export_i18n_js" do
86
+ allow(described_class).to receive(:export_i18n_js)
87
+ I18n::JS.export
88
+ expect(described_class).to have_received(:export_i18n_js).once
89
+ end
68
90
  end
69
91
 
70
92
  context "filters" do
@@ -133,7 +155,7 @@ describe I18n::JS do
133
155
 
134
156
  context "general" do
135
157
  it "sets export directory" do
136
- I18n::JS.export_dir.should eql("public/javascripts")
158
+ I18n::JS::DEFAULT_EXPORT_DIR_PATH.should eql("public/javascripts")
137
159
  end
138
160
 
139
161
  it "sets empty hash as configuration when no file is found" do
@@ -149,19 +171,148 @@ describe I18n::JS do
149
171
  end
150
172
  end
151
173
 
174
+
175
+ describe "i18n.js exporting" do
176
+ describe ".export_i18n_js" do
177
+ before do
178
+ allow(FileUtils).to receive(:mkdir_p).and_call_original
179
+ allow(FileUtils).to receive(:cp).and_call_original
180
+
181
+ described_class.stub(:export_i18n_js_dir_path).and_return(export_i18n_js_dir_path)
182
+ I18n::JS.export_i18n_js
183
+ end
184
+
185
+ context 'when .export_i18n_js_dir_path returns something' do
186
+ let(:export_i18n_js_dir_path) { temp_path }
187
+
188
+ it "does create the folder before copying" do
189
+ expect(FileUtils).to have_received(:mkdir_p).with(export_i18n_js_dir_path).once
190
+ end
191
+ it "does copy the file with FileUtils.cp" do
192
+ expect(FileUtils).to have_received(:cp).once
193
+ end
194
+ it "exports the file" do
195
+ File.should be_file(File.join(I18n::JS.export_i18n_js_dir_path, "i18n.js"))
196
+ end
197
+ end
198
+
199
+ context 'when .export_i18n_js_dir_path is set to nil' do
200
+ let(:export_i18n_js_dir_path) { nil }
201
+
202
+ it "does NOT create the folder before copying" do
203
+ expect(FileUtils).to_not have_received(:mkdir_p)
204
+ end
205
+ it "does NOT copy the file with FileUtils.cp" do
206
+ expect(FileUtils).to_not have_received(:cp)
207
+ end
208
+ end
209
+ end
210
+
211
+
212
+ describe '.export_i18n_js_dir_path' do
213
+ let(:default_path) { I18n::JS::DEFAULT_EXPORT_DIR_PATH }
214
+ let(:new_path) { File.join("tmp", default_path) }
215
+ before { described_class.send(:remove_instance_variable, :@export_i18n_js_dir_path) }
216
+
217
+ subject { described_class.export_i18n_js_dir_path }
218
+
219
+ context "when it is not set" do
220
+ it { should eq default_path }
221
+ end
222
+ context "when it is set to another path already" do
223
+ before { described_class.export_i18n_js_dir_path = new_path }
224
+
225
+ it { should eq new_path }
226
+ end
227
+ context "when it is set to nil already" do
228
+ before { described_class.export_i18n_js_dir_path = nil }
229
+
230
+ it { should be_nil }
231
+ end
232
+ end
233
+ end
234
+ end
235
+
236
+ describe I18n::JS::Dependencies, ".sprockets_supports_register_preprocessor?" do
237
+
238
+ subject { described_class.sprockets_supports_register_preprocessor? }
239
+
240
+ context 'when Sprockets is available to register preprocessors' do
241
+ let!(:sprockets_double) do
242
+ class_double('Sprockets').as_stubbed_const(register_processor: true).tap do |double|
243
+ allow(double).to receive(:respond_to?).with(:register_preprocessor).and_return(true)
244
+ end
245
+ end
246
+
247
+ it { is_expected.to be_truthy }
248
+ it 'calls respond_to? with register_preprocessor on Sprockets' do
249
+ expect(sprockets_double).to receive(:respond_to?).with(:register_preprocessor).and_return(true)
250
+ subject
251
+ end
252
+ end
253
+
254
+ context 'when Sprockets is NOT available to register preprocessors' do
255
+ let!(:sprockets_double) do
256
+ class_double('Sprockets').as_stubbed_const(register_processor: true).tap do |double|
257
+ allow(double).to receive(:respond_to?).with(:register_preprocessor).and_return(false)
258
+ end
259
+ end
260
+
261
+ it { is_expected.to be_falsy }
262
+ it 'calls respond_to? with register_preprocessor on Sprockets' do
263
+ expect(sprockets_double).to receive(:respond_to?).with(:register_preprocessor).and_return(false)
264
+ subject
265
+ end
266
+ end
267
+
268
+ context 'when Sprockets is missing' do
269
+ before do
270
+ hide_const('Sprockets')
271
+ expect { Sprockets }.to raise_error(NameError)
272
+ end
273
+
274
+ it { is_expected.to be_falsy }
275
+ end
276
+
277
+ end
278
+
279
+ describe I18n::JS::Utils do
280
+
281
+ describe ".strip_keys_with_nil_values" do
282
+ subject { described_class.strip_keys_with_nil_values(input_hash) }
283
+
284
+ context 'when input_hash does NOT contain nil value' do
285
+ let(:input_hash) { {a: 1, b: { c: 2 }} }
286
+ let(:expected_hash) { input_hash }
287
+
288
+ it 'returns the original input' do
289
+ is_expected.to eq expected_hash
290
+ end
291
+ end
292
+ context 'when input_hash does contain nil value' do
293
+ let(:input_hash) { {a: 1, b: { c: 2, d: nil }, e: { f: nil }} }
294
+ let(:expected_hash) { {a: 1, b: { c: 2 }, e: {}} }
295
+
296
+ it 'returns the original input with nil values removed' do
297
+ is_expected.to eq expected_hash
298
+ end
299
+ end
300
+ end
301
+
152
302
  context "hash merging" do
153
303
  it "performs a deep merge" do
154
304
  target = {:a => {:b => 1}}
155
- result = I18n::JS.deep_merge(target, {:a => {:c => 2}})
305
+ result = described_class.deep_merge(target, {:a => {:c => 2}})
156
306
 
157
307
  result[:a].should eql({:b => 1, :c => 2})
158
308
  end
159
309
 
160
310
  it "performs a banged deep merge" do
161
311
  target = {:a => {:b => 1}}
162
- I18n::JS.deep_merge!(target, {:a => {:c => 2}})
312
+ described_class.deep_merge!(target, {:a => {:c => 2}})
163
313
 
164
314
  target[:a].should eql({:b => 1, :c => 2})
165
315
  end
166
316
  end
317
+
167
318
  end
@@ -25,4 +25,9 @@ describe("Interpolation", function(){
25
25
  expect(I18n.t("inbox", {count: 1})).toEqual("You have 1 message");
26
26
  expect(I18n.t("inbox", {count: 5})).toEqual("You have 5 messages");
27
27
  });
28
+
29
+ it("outputs missing placeholder message if interpolation value is missing", function(){
30
+ actual = I18n.t("greetings.name");
31
+ expect(actual).toEqual("Hello [missing {{name}} value]!");
32
+ })
28
33
  });
data/spec/js/specs.html CHANGED
@@ -36,6 +36,7 @@
36
36
  <script type="text/javascript" src="pluralization.spec.js"></script>
37
37
  <script type="text/javascript" src="prepare_options.spec.js"></script>
38
38
  <script type="text/javascript" src="translate.spec.js"></script>
39
+ <script type="text/javascript" src="utility_functions.spec.js"></script>
39
40
 
40
41
  <!-- run specs -->
41
42
  <script type="text/javascript">
@@ -163,6 +163,15 @@ describe("Translate", function(){
163
163
  expect(I18n.t("paid", {price: "$1.35"})).toEqual("You were paid $1.35");
164
164
  });
165
165
 
166
+ it("replaces all occurrences of escaped $", function(){
167
+ I18n.locale = "en";
168
+
169
+ expect(I18n.t("paid_with_vat", {
170
+ price: "$0.12",
171
+ vat: "$0.02"}
172
+ )).toEqual("You were paid $0.12 (incl. VAT $0.02)");
173
+ });
174
+
166
175
  it("sets default scope", function(){
167
176
  var options = {scope: "greetings"};
168
177
  expect(I18n.t("stranger", options)).toEqual("Hello stranger!");
@@ -8,6 +8,8 @@ var DEBUG = false;
8
8
  hello: "Hello World!"
9
9
  , paid: "You were paid %{price}"
10
10
 
11
+ , paid_with_vat: "You were paid %{price} (incl. VAT %{vat})"
12
+
11
13
  , booleans: {
12
14
  yes: true,
13
15
  no: false
@@ -0,0 +1,20 @@
1
+ var I18n = require("../../app/assets/javascripts/i18n");
2
+
3
+ describe("Utility Functions", function(){
4
+ beforeEach(function(){
5
+ I18n.reset();
6
+ });
7
+
8
+ describe("I18n.lookup", function() {
9
+ it("does not change locale on failed lookup", function(){
10
+ var fallback_locales = ['fallback1', 'fallback2'];
11
+
12
+ I18n.locales['lang'] = fallback_locales.slice();
13
+ expect(I18n.locales.lang).toEqual(fallback_locales);
14
+
15
+ I18n.lookup('anything', {locale: 'lang'})
16
+ expect(I18n.locales.lang).toEqual(fallback_locales);
17
+ });
18
+
19
+ })
20
+ });
data/spec/spec_helper.rb CHANGED
@@ -7,8 +7,8 @@ require "i18n/js"
7
7
  module Helpers
8
8
  # Set the configuration as the current one
9
9
  def set_config(path)
10
- config_file = File.dirname(__FILE__) + "/fixtures/#{path}"
11
- I18n::JS.stub(:config? => true, :config_file => config_file)
10
+ config_file_path = File.dirname(__FILE__) + "/fixtures/#{path}"
11
+ I18n::JS.stub(:config? => true, :config_file_path => config_file_path)
12
12
  end
13
13
 
14
14
  # Shortcut to I18n::JS.translations
@@ -17,7 +17,7 @@ module Helpers
17
17
  end
18
18
 
19
19
  def file_should_exist(name)
20
- file_path = File.join(I18n::JS.export_dir, name)
20
+ file_path = File.join(I18n::JS::DEFAULT_EXPORT_DIR_PATH, name)
21
21
  File.should be_file(file_path)
22
22
  end
23
23
 
metadata CHANGED
@@ -1,111 +1,111 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i18n-js
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0.rc6
4
+ version: 3.0.0.rc7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nando Vieira
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-09 00:00:00.000000000 Z
11
+ date: 2014-10-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0.6'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0.6'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: appraisal
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: '1.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '1.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: activesupport
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
47
  version: '3'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: '3.0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '3.0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rake
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: pry-meta
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '>='
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '>='
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: gem-release
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - '>='
101
+ - - ">="
102
102
  - !ruby/object:Gem::Version
103
103
  version: '0.7'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - '>='
108
+ - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0.7'
111
111
  description: It's a small library to provide the Rails I18n translations on the Javascript.
@@ -115,8 +115,8 @@ executables: []
115
115
  extensions: []
116
116
  extra_rdoc_files: []
117
117
  files:
118
- - .gitignore
119
- - .travis.yml
118
+ - ".gitignore"
119
+ - ".travis.yml"
120
120
  - Appraisals
121
121
  - CHANGELOG.md
122
122
  - Gemfile
@@ -133,6 +133,7 @@ files:
133
133
  - lib/i18n/js/dependencies.rb
134
134
  - lib/i18n/js/engine.rb
135
135
  - lib/i18n/js/middleware.rb
136
+ - lib/i18n/js/utils.rb
136
137
  - lib/i18n/js/version.rb
137
138
  - lib/rails/generators/i18n/js/config/config_generator.rb
138
139
  - lib/rails/generators/i18n/js/config/templates/i18n-js.yml
@@ -168,9 +169,11 @@ files:
168
169
  - spec/js/specs.html
169
170
  - spec/js/translate.spec.js
170
171
  - spec/js/translations.js
172
+ - spec/js/utility_functions.spec.js
171
173
  - spec/spec_helper.rb
172
174
  homepage: http://rubygems.org/gems/i18n-js
173
- licenses: []
175
+ licenses:
176
+ - MIT
174
177
  metadata: {}
175
178
  post_install_message:
176
179
  rdoc_options: []
@@ -178,12 +181,12 @@ require_paths:
178
181
  - lib
179
182
  required_ruby_version: !ruby/object:Gem::Requirement
180
183
  requirements:
181
- - - '>='
184
+ - - ">="
182
185
  - !ruby/object:Gem::Version
183
- version: '0'
186
+ version: 1.9.3
184
187
  required_rubygems_version: !ruby/object:Gem::Requirement
185
188
  requirements:
186
- - - '>'
189
+ - - ">"
187
190
  - !ruby/object:Gem::Version
188
191
  version: 1.3.1
189
192
  requirements: []
@@ -223,5 +226,6 @@ test_files:
223
226
  - spec/js/specs.html
224
227
  - spec/js/translate.spec.js
225
228
  - spec/js/translations.js
229
+ - spec/js/utility_functions.spec.js
226
230
  - spec/spec_helper.rb
227
231
  has_rdoc: