i18n-js 3.0.0.rc7 → 3.0.0.rc8

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: 4377851d9bebcdaf860e76c466587f7486255752
4
- data.tar.gz: 9b52dbf3c12aca86c6de92073323dcb5dbeb02f0
3
+ metadata.gz: f5f7d877f8e94243760d5e3c4c3bbe232badc99d
4
+ data.tar.gz: 0d2cf27dc10c17acc846c457ec48573ae9832413
5
5
  SHA512:
6
- metadata.gz: d33c4c88cdbcbeda6233f65a7455d5cfec3b958f3b4aa74f04cbe0ecd4896f7fdd9ee7a853deaae44c932ae9d127146128df24a00f6a2956c31c4f73f8474738
7
- data.tar.gz: f8333679e32ad823e9c5946734c031f761609dc30ac8a15b143b030d2d85e6c68dbba0073192a020da39a4aaa1057ae1cad4e60f47459c86dd03b3d3d34dcce2
6
+ metadata.gz: 6ebf38bdbc12665767e0c7c3806fd02221204b26e8b1f82dda78c3f07534ec5cedd18b4b6bc133c2820effc6ddb0f3c6902318a76b78563ceb232e99272213b8
7
+ data.tar.gz: c505d9671c59b80c51c28a033b03c8cac3bdc4174621789f7f9e48e5257324c37803f4e1f084cc337c3512894c193bbbf8a820e78c6495f570872dee4ff50f28
@@ -3,6 +3,33 @@
3
3
 
4
4
  ### enhancements
5
5
 
6
+ ### bug fixes
7
+
8
+
9
+ ## 3.0.0.rc8
10
+
11
+ ### enhancements
12
+
13
+ - Add support for loading via AMD and CommonJS module loaders ([#266](https://github.com/fnando/i18n-js/pull/266))
14
+ - Add `I18n.nullPlaceholder`
15
+ Defaults to I18n.missingPlaceholder (`[missing {{name}} value]`)
16
+ Set to `function() {return "";}` to match Ruby `I18n.t("name: %{name}", name: nil)`
17
+ - For date formatting, you can now also add placeholders to the date format, see README for detail
18
+ - Add fallbacks option to `i18n-js.yml`, defaults to `true`
19
+
20
+ ### bug fixes
21
+
22
+ - Fix factory initialization so that the Node/CommonJS branch only gets executed if the environment is Node/CommonJS
23
+ (it currently will execute if module is defined in the global scope, which occurs with QUnit, for example)
24
+ - Fix pluralization rules selection for negative `count` (e.g. `-1` was lead to use `one` for pluralization) ([#268](https://github.com/fnando/i18n-js/pull/268))
25
+ - Remove check for `Rails.configuration.assets.compile` before telling Sprockets the dependency of translations JS file
26
+ This might be the reason of many "cache not expired" issues
27
+ Discovered/reported in #277
28
+
29
+ ## 3.0.0.rc7
30
+
31
+ ### enhancements
32
+
6
33
  - The Rails Engine initializer is now named as `i18n-js.register_preprocessor` (https://github.com/fnando/i18n-js/pull/261)
7
34
  - Rename `I18n::JS.config_file` to `I18n::JS.config_file_path` and make it configurable
8
35
  Expected a `String`, default is still `config/i18n-js.yml`
data/README.md CHANGED
@@ -121,6 +121,65 @@ translations:
121
121
 
122
122
  To find more examples on how to use the configuration file please refer to the tests.
123
123
 
124
+ ##### Fallbacks
125
+
126
+ If you specify the `fallbacks` option, you will be able to fill missing translations with those inside fallback locale(s).
127
+ Default value is `true`.
128
+
129
+ Examples:
130
+ ```yaml
131
+ fallbacks: true
132
+
133
+ translations:
134
+ - file: "public/javascripts/i18n/%{locale}.js"
135
+ only: '*'
136
+ ```
137
+ This will enable merging fallbacks into each file. (set to `false` to disable).
138
+ If you use `I18n` with fallbacks, the fallbacks defined there will be used.
139
+ Otherwise `I18n.default_locale` will be used.
140
+
141
+ ```yaml
142
+ fallbacks: :de
143
+
144
+ translations:
145
+ - file: "public/javascripts/i18n/%{locale}.js"
146
+ only: '*'
147
+ ```
148
+ Here, the specified locale `:de` will be used as fallback for all locales.
149
+
150
+ ```yaml
151
+ fallbacks:
152
+ fr: ["de", "en"]
153
+ de: "en"
154
+
155
+ translations:
156
+ - file: "public/javascripts/i18n/%{locale}.js"
157
+ only: '*'
158
+ ```
159
+ Fallbacks defined will be used, if not defined (e.g. `:pl`) `I18n.fallbacks` or `I18n.default_locale` will be used.
160
+
161
+ ```yaml
162
+ fallbacks: :default_locale
163
+
164
+ translations:
165
+ - file: "public/javascripts/i18n/%{locale}.js"
166
+ only: '*'
167
+ ```
168
+ Setting the option to `:default_locale` will enforce the fallback to use the `I18n.default_locale`, ignoring `I18n.fallbacks`.
169
+
170
+ Examples:
171
+ ```yaml
172
+ fallbacks: false
173
+
174
+ translations:
175
+ - file: "public/javascripts/i18n/%{locale}.js"
176
+ only: '*'
177
+ ```
178
+ You must disable this feature by setting the option to `false`.
179
+
180
+ To find more examples on how to use the configuration file please refer to the tests.
181
+
182
+
124
183
  #### Vanilla JavaScript
125
184
 
126
185
  Just add the `i18n.js` file to your page. You'll have to build the translations object
@@ -320,6 +379,17 @@ The `toHumanSize` function accepts the following options:
320
379
  I18n.l("date.formats.short", "09/18/2009"); // mm/dd/yyyy
321
380
  I18n.l("date.formats.short", (new Date())); // Date object
322
381
 
382
+ You can also add placeholders to the date format:
383
+
384
+ I18n.translations["en"] = {
385
+ date: {
386
+ formats: {
387
+ ordinal_day: "%B %{day}"
388
+ }
389
+ }
390
+ }
391
+ I18n.l("date.formats.ordinal_day", "2009-09-18", { day: '18th' }); // Sep 18th
392
+
323
393
  If you prefer, you can use the `I18n.strftime` function to format dates.
324
394
 
325
395
  var date = new Date();
data/Rakefile CHANGED
@@ -9,7 +9,8 @@ RSpec::Core::RakeTask.new(:"spec:ruby")
9
9
 
10
10
  desc "Run JavaScript specs"
11
11
  task "spec:js" do
12
- system "npm", "test"
12
+ # Need to call `exit!` manually to propogate exit status
13
+ system "npm", "test" or exit!(1)
13
14
  end
14
15
 
15
16
  desc "Run all specs"
@@ -11,9 +11,26 @@
11
11
  //
12
12
  // See tests for specific formatting like numbers and dates.
13
13
  //
14
- ;(function(I18n){
14
+
15
+ ;(function(factory) {
16
+ if (typeof module !== 'undefined' && module.exports) {
17
+ // Node/CommonJS
18
+ module.exports = factory(this);
19
+
20
+ } else if (typeof define === 'function' && define.amd) {
21
+ // AMD
22
+ define((function(global){ return function(){ factory(global); }})(this));
23
+
24
+ } else {
25
+ // Browser globals
26
+ this.I18n = factory(this);
27
+ }
28
+ }(function(global) {
15
29
  "use strict";
16
30
 
31
+ // Use previously defined object if exists in current scope
32
+ var I18n = global && global.I18n || {};
33
+
17
34
  // Just cache the Array#slice function.
18
35
  var slice = Array.prototype.slice;
19
36
 
@@ -407,6 +424,8 @@
407
424
 
408
425
  if (this.isSet(options[name])) {
409
426
  value = options[name].toString().replace(/\$/gm, "_#$#_");
427
+ } else if (name in options) {
428
+ value = this.nullPlaceholder(placeholder, message);
410
429
  } else {
411
430
  value = this.missingPlaceholder(placeholder, message);
412
431
  }
@@ -436,7 +455,7 @@
436
455
  }
437
456
 
438
457
  pluralizer = this.pluralization.get(options.locale);
439
- keys = pluralizer(Math.abs(count));
458
+ keys = pluralizer(count);
440
459
 
441
460
  while (keys.length) {
442
461
  key = keys.shift();
@@ -467,6 +486,10 @@
467
486
  return "[missing " + placeholder + " value]";
468
487
  };
469
488
 
489
+ I18n.nullPlaceholder = function() {
490
+ return I18n.missingPlaceholder.apply(I18n, arguments);
491
+ };
492
+
470
493
  // Format number using localization rules.
471
494
  // The options will be retrieved from the `number.format` scope.
472
495
  // If this isn't present, then the following options will be used:
@@ -557,7 +580,9 @@
557
580
  //
558
581
  // It will default to the value's `toString` function.
559
582
  //
560
- I18n.localize = function(scope, value) {
583
+ I18n.localize = function(scope, value, options) {
584
+ options || (options = {});
585
+
561
586
  switch (scope) {
562
587
  case "currency":
563
588
  return this.toCurrency(value);
@@ -567,11 +592,15 @@
567
592
  case "percentage":
568
593
  return this.toPercentage(value);
569
594
  default:
595
+ var localizedValue;
596
+
570
597
  if (scope.match(/^(date|time)/)) {
571
- return this.toTime(scope, value);
598
+ localizedValue = this.toTime(scope, value);
572
599
  } else {
573
- return value.toString();
600
+ localizedValue = value.toString();
574
601
  }
602
+
603
+ return this.interpolate(localizedValue, options);
575
604
  }
576
605
  };
577
606
 
@@ -797,4 +826,6 @@
797
826
  I18n.t = I18n.translate;
798
827
  I18n.l = I18n.localize;
799
828
  I18n.p = I18n.pluralize;
800
- })(typeof(exports) === "undefined" ? (this.I18n || (this.I18n = {})) : exports);
829
+
830
+ return I18n;
831
+ }));
@@ -1,2 +1,20 @@
1
1
  <%# encoding: utf-8 %>
2
- ;I18n.translations = <%= I18n::JS.filtered_translations.to_json %>;
2
+
3
+ ;(function(factory) {
4
+ if (typeof module !== 'undefined') {
5
+ // Node/CommonJS
6
+ factory(require('i18n'));
7
+
8
+ } else if (typeof define === 'function' && define.amd) {
9
+ // AMD
10
+ define(['i18n'], factory);
11
+
12
+ } else {
13
+ // Browser globals
14
+ factory(this.I18n);
15
+ }
16
+ }(function(I18n) {
17
+ "use strict";
18
+
19
+ I18n.translations = <%= I18n::JS.filtered_translations.to_json %>;
20
+ }));
@@ -6,6 +6,7 @@ require "i18n/js/utils"
6
6
  module I18n
7
7
  module JS
8
8
  require "i18n/js/dependencies"
9
+ require "i18n/js/fallback_locales"
9
10
  if JS::Dependencies.rails?
10
11
  require "i18n/js/middleware"
11
12
  require "i18n/js/engine"
@@ -37,6 +38,8 @@ module I18n
37
38
  I18n.available_locales.each_with_object({}) do |locale, segments|
38
39
  scope = [scope] unless scope.respond_to?(:each)
39
40
  result = scoped_translations(scope.collect{|s| "#{locale}.#{s}"})
41
+ merge_with_fallbacks!(result, locale, scope) if use_fallbacks?
42
+
40
43
  next if result.empty?
41
44
 
42
45
  segment_name = ::I18n.interpolate(pattern,{:locale => locale})
@@ -145,6 +148,28 @@ module I18n
145
148
  end
146
149
  end
147
150
 
151
+ def self.use_fallbacks?
152
+ fallbacks != false
153
+ end
154
+
155
+ def self.fallbacks
156
+ config.fetch(:fallbacks) do
157
+ # default value
158
+ true
159
+ end
160
+ end
161
+
162
+ # deep_merge! given result with result for fallback locale
163
+ def self.merge_with_fallbacks!(result, locale, scope)
164
+ result[locale] ||= {}
165
+ fallback_locales = FallbackLocales.new(fallbacks, locale)
166
+
167
+ fallback_locales.each do |fallback_locale|
168
+ fallback_result = scoped_translations(scope.collect{|s| "#{fallback_locale}.#{s}"}) # NOTE: Duplicated code here
169
+ result[locale] = Utils.deep_merge(fallback_result[fallback_locale], result[locale])
170
+ end
171
+ end
172
+
148
173
 
149
174
  ### Export i18n.js
150
175
  begin
@@ -6,7 +6,6 @@ module I18n
6
6
  initializer "i18n-js.register_preprocessor", :after => "sprockets.environment" do
7
7
  next unless JS::Dependencies.using_asset_pipeline?
8
8
  next unless JS::Dependencies.sprockets_supports_register_preprocessor?
9
- next unless Rails.configuration.assets.compile
10
9
 
11
10
  Rails.application.assets.register_preprocessor "application/javascript", :"i18n-js_dependencies" do |context, source|
12
11
  if context.logical_path == "i18n/filtered"
@@ -0,0 +1,81 @@
1
+ module I18n
2
+ module JS
3
+ class FallbackLocales
4
+ attr_reader :fallbacks, :locale
5
+
6
+ def initialize(fallbacks, locale)
7
+ @fallbacks = fallbacks
8
+ @locale = locale
9
+ end
10
+
11
+ def each
12
+ locales.each { |locale| yield(locale) }
13
+ end
14
+
15
+ # @return [Array<String, Symbol>]
16
+ # An Array of locales to use as fallbacks for given locale.
17
+ def locales
18
+ locales = case fallbacks
19
+ when true
20
+ default_fallbacks
21
+ when :default_locale
22
+ [::I18n.default_locale]
23
+ when Symbol, String
24
+ [fallbacks.to_sym]
25
+ when Array
26
+ ensure_valid_fallbacks_as_array!
27
+ fallbacks
28
+ when Hash
29
+ Array(fallbacks[locale] || default_fallbacks)
30
+ else
31
+ fail ArgumentError, "fallbacks must be: true, :default_locale an Array or a Hash - given: #{fallbacks}"
32
+ end
33
+
34
+ locales.map! { |locale| locale.to_sym }
35
+ ensure_valid_locales!(locales)
36
+ locales
37
+ end
38
+
39
+ private
40
+
41
+ # @return [Array<String, Symbol>] An Array of locales.
42
+ def default_fallbacks
43
+ if using_i18n_fallbacks_module?
44
+ I18n.fallbacks[locale]
45
+ else
46
+ [::I18n.default_locale]
47
+ end
48
+ end
49
+
50
+ # @return
51
+ # true if we can safely use I18n.fallbacks, false otherwise.
52
+ #
53
+ # @note
54
+ # We should implement this as `I18n.respond_to?(:fallbacks)`, but
55
+ # once I18n::Backend::Fallbacks is included, I18n will _always_
56
+ # respond to :fallbacks. Even if we switch the backend to one
57
+ # without fallbacks!
58
+ #
59
+ # Maybe this should be fixed within I18n.
60
+ def using_i18n_fallbacks_module?
61
+ I18n.backend.class.included_modules.include?(I18n::Backend::Fallbacks)
62
+ end
63
+
64
+ def ensure_valid_fallbacks_as_array!
65
+ return if fallbacks.all? { |e| e.is_a?(String) || e.is_a?(Symbol) }
66
+
67
+ fail ArgumentError, "If fallbacks is passed as Array, it must ony include Strings or Symbols. Given: #{fallbacks}"
68
+ end
69
+
70
+ # Ensures that only valid locales are returned.
71
+ #
72
+ # @note
73
+ # This ignores option `I18n.enforce_available_locales`
74
+ def ensure_valid_locales!(locales)
75
+ if locales.any? { |locale| !::I18n.available_locales.include?(locale) }
76
+ fail ArgumentError, "Valid locales: #{::I18n.available_locales} - Given Locales: #{locales}"
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
@@ -4,7 +4,7 @@ module I18n
4
4
  MAJOR = 3
5
5
  MINOR = 0
6
6
  PATCH = 0
7
- STRING = "#{MAJOR}.#{MINOR}.#{PATCH}.rc7"
7
+ STRING = "#{MAJOR}.#{MINOR}.#{PATCH}.rc8"
8
8
  end
9
9
  end
10
10
  end
@@ -4,7 +4,7 @@
4
4
  "devDependencies": {
5
5
  "jasmine-node": "*"
6
6
  },
7
-
7
+ "main": "app/assets/javascripts/i18n.js",
8
8
  "scripts": {
9
9
  "test": "./node_modules/.bin/jasmine-node spec/js"
10
10
  }
@@ -0,0 +1,4 @@
1
+ fallbacks: :default_locale
2
+
3
+ translations:
4
+ - file: "tmp/i18n-js/%{locale}.js"
@@ -0,0 +1,6 @@
1
+ fallbacks:
2
+ fr: ["de", "en"]
3
+ de: "en"
4
+
5
+ translations:
6
+ - file: "tmp/i18n-js/%{locale}.js"
@@ -0,0 +1,4 @@
1
+ fallbacks: :de
2
+
3
+ translations:
4
+ - file: "tmp/i18n-js/%{locale}.js"
@@ -0,0 +1,4 @@
1
+ fallbacks: true
2
+
3
+ translations:
4
+ - file: "tmp/i18n-js/%{locale}.js"
@@ -0,0 +1,4 @@
1
+ fallbacks: false
2
+
3
+ translations:
4
+ - file: "tmp/i18n-js/%{locale}.js"
@@ -35,6 +35,10 @@ en:
35
35
  edit:
36
36
  title: "Edit"
37
37
  foo: "Foo"
38
+ fallback_test: "Success"
39
+
40
+ de:
41
+ fallback_test: "Erfolg"
38
42
 
39
43
  fr:
40
44
  date:
@@ -0,0 +1,94 @@
1
+ require "spec_helper"
2
+
3
+ describe I18n::JS::FallbackLocales do
4
+ let(:locale) { :fr }
5
+ let(:default_locale) { :en }
6
+
7
+ describe "#locales" do
8
+ let(:fallbacks_locales) { described_class.new(fallbacks, locale) }
9
+ subject { fallbacks_locales.locales }
10
+
11
+ let(:fetching_locales) { proc do fallbacks_locales.locales end }
12
+
13
+ context "when given true as fallbacks" do
14
+ let(:fallbacks) { true }
15
+ it { should eq([default_locale]) }
16
+ end
17
+
18
+ context "when given false as fallbacks" do
19
+ let(:fallbacks) { false }
20
+ it { expect(fetching_locales).to raise_error(ArgumentError) }
21
+ end
22
+
23
+ context "when given a valid locale as fallbacks" do
24
+ let(:fallbacks) { :de }
25
+ it { should eq([:de]) }
26
+ end
27
+
28
+ context "when given a valid Array as fallbacks" do
29
+ let(:fallbacks) { [:de, :en] }
30
+ it { should eq([:de, :en]) }
31
+ end
32
+
33
+ context "when given a valid Hash with current locale as key as fallbacks" do
34
+ let(:fallbacks) do { :fr => [:de, :en] } end
35
+ it { should eq([:de, :en]) }
36
+ end
37
+
38
+ context "when given a valid Hash without current locale as key as fallbacks" do
39
+ let(:fallbacks) do { :de => [:fr, :en] } end
40
+ it { should eq([default_locale]) }
41
+ end
42
+
43
+ context "when given a invalid locale as fallbacks" do
44
+ let(:fallbacks) { :invalid_locale }
45
+ it { expect(fetching_locales).to raise_error(ArgumentError) }
46
+ end
47
+
48
+ context "when given a invalid type as fallbacks" do
49
+ let(:fallbacks) { 42 }
50
+ it { expect(fetching_locales).to raise_error(ArgumentError) }
51
+ end
52
+
53
+ context "when given an invalid Array as fallbacks" do
54
+ let(:fallbacks) { [:de, :en, :invalid_locale] }
55
+ it { expect(fetching_locales).to raise_error(ArgumentError) }
56
+ end
57
+
58
+ context "when given a invalid Hash as fallbacks" do
59
+ let(:fallbacks) do { :fr => [:de, :en, :invalid_locale] } end
60
+ it { expect(fetching_locales).to raise_error(ArgumentError) }
61
+ end
62
+
63
+ # I18n::Backend::Fallbacks
64
+ context "when I18n::Backend::Fallbacks is used" do
65
+ let(:backend_with_fallbacks) { backend_class_with_fallbacks.new }
66
+
67
+ before do
68
+ I18n.backend = backend_with_fallbacks
69
+ I18n.fallbacks[:fr] = [:de, :en]
70
+ end
71
+ after { I18n.backend = I18n::Backend::Simple.new }
72
+
73
+ context "given true as fallbacks" do
74
+ let(:fallbacks) { true }
75
+ it { should eq([:de, :en]) }
76
+ end
77
+
78
+ context "given :default_locale as fallbacks" do
79
+ let(:fallbacks) { :default_locale }
80
+ it { should eq([:en]) }
81
+ end
82
+
83
+ context "given a Hash with current locale as fallbacks" do
84
+ let(:fallbacks) do { :fr => [:en] } end
85
+ it { should eq([:en]) }
86
+ end
87
+
88
+ context "given a Hash without current locale as fallbacks" do
89
+ let(:fallbacks) do { :de => [:en] } end
90
+ it { should eq([:de, :en]) }
91
+ end
92
+ end
93
+ end
94
+ end
@@ -73,10 +73,13 @@ describe I18n::JS do
73
73
 
74
74
  set_config "multiple_conditions_per_locale.yml"
75
75
 
76
+ expected_locales = %w(en fr)
77
+
76
78
  result = I18n::JS.translation_segments
77
- result.keys.should eql(["tmp/i18n-js/bits.en.js", "tmp/i18n-js/bits.fr.js"])
79
+ expected_files = expected_locales.map { |locale| "tmp/i18n-js/bits.#{locale}.js" }
80
+ result.keys.should eql(expected_files)
78
81
 
79
- %w{en fr}.each do |lang|
82
+ expected_locales.each do |lang|
80
83
  result["tmp/i18n-js/bits.#{lang}.js"].keys.should eql([lang.to_sym])
81
84
  result["tmp/i18n-js/bits.#{lang}.js"][lang.to_sym].keys.sort.should eql([:date, :number])
82
85
  end
@@ -129,6 +132,68 @@ describe I18n::JS do
129
132
  end
130
133
  end
131
134
 
135
+ context "fallbacks" do
136
+ it "exports without fallback when disabled" do
137
+ set_config "js_file_per_locale_without_fallbacks.yml"
138
+
139
+ result = I18n::JS.translation_segments
140
+ result["tmp/i18n-js/fr.js"][:fr][:fallback_test].should eql(nil)
141
+ end
142
+
143
+ it "exports with default_locale as fallback when enabled" do
144
+ set_config "js_file_per_locale_with_fallbacks_enabled.yml"
145
+
146
+ result = I18n::JS.translation_segments
147
+ result["tmp/i18n-js/fr.js"][:fr][:fallback_test].should eql("Success")
148
+ end
149
+
150
+ it "exports with default_locale as fallback when enabled with :default_locale" do
151
+ set_config "js_file_per_locale_with_fallbacks_as_default_locale_symbol.yml"
152
+
153
+ result = I18n::JS.translation_segments
154
+ result["tmp/i18n-js/fr.js"][:fr][:fallback_test].should eql("Success")
155
+ end
156
+
157
+ it "exports with given locale as fallback" do
158
+ set_config "js_file_per_locale_with_fallbacks_as_locale.yml"
159
+
160
+ result = I18n::JS.translation_segments
161
+ result["tmp/i18n-js/fr.js"][:fr][:fallback_test].should eql("Erfolg")
162
+ end
163
+
164
+ context "with I18n::Fallbacks enabled" do
165
+ let(:backend_with_fallbacks) { backend_class_with_fallbacks.new }
166
+ let!(:old_backebad) { I18n.backend }
167
+
168
+ before do
169
+ I18n.backend = backend_with_fallbacks
170
+ I18n.fallbacks[:fr] = [:de, :en]
171
+ end
172
+ after { I18n.backend = old_backebad }
173
+
174
+ it "exports with defined locale as fallback when enabled" do
175
+ set_config "js_file_per_locale_with_fallbacks_enabled.yml"
176
+
177
+ result = I18n::JS.translation_segments
178
+ result["tmp/i18n-js/fr.js"][:fr][:fallback_test].should eql("Erfolg")
179
+ end
180
+
181
+ it "exports with defined locale as fallback when enabled with :default_locale" do
182
+ set_config "js_file_per_locale_with_fallbacks_as_default_locale_symbol.yml"
183
+
184
+ result = I18n::JS.translation_segments
185
+ result["tmp/i18n-js/fr.js"][:fr][:fallback_test].should eql("Success")
186
+ end
187
+
188
+ it "exports with Fallbacks as Hash" do
189
+ set_config "js_file_per_locale_with_fallbacks_as_hash.yml"
190
+
191
+ result = I18n::JS.translation_segments
192
+ result["tmp/i18n-js/fr.js"][:fr][:fallback_test].should eql("Erfolg")
193
+ end
194
+ end
195
+ end
196
+
132
197
  context "I18n.available_locales" do
133
198
  context "when I18n.available_locales is not set" do
134
199
  it "should allow all locales" do
@@ -29,5 +29,18 @@ describe("Interpolation", function(){
29
29
  it("outputs missing placeholder message if interpolation value is missing", function(){
30
30
  actual = I18n.t("greetings.name");
31
31
  expect(actual).toEqual("Hello [missing {{name}} value]!");
32
- })
32
+ });
33
+
34
+ it("outputs missing placeholder message if interpolation value is null", function(){
35
+ actual = I18n.t("greetings.name", {name: null});
36
+ expect(actual).toEqual("Hello [missing {{name}} value]!");
37
+ });
38
+
39
+ it("allows overriding the null placeholder message", function(){
40
+ var orig = I18n.nullPlaceholder;
41
+ I18n.nullPlaceholder = function() {return "";}
42
+ actual = I18n.t("greetings.name", {name: null});
43
+ expect(actual).toEqual("Hello !");
44
+ I18n.nullPlaceholder = orig;
45
+ });
33
46
  });
@@ -34,6 +34,13 @@ describe("Localization", function(){
34
34
  expect(I18n.l("time.formats.long", "2009-11-29 15:07:59")).toEqual("Domingo, 29 de Novembro de 2009, 15:07 h");
35
35
  });
36
36
 
37
+ it("localizes date/time strings with placeholders", function(){
38
+ I18n.locale = "pt-BR";
39
+
40
+ expect(I18n.l("date.formats.short_with_placeholders", "2009-01-07", { p1: "!", p2: "?" })).toEqual("07 de Janeiro ! ?");
41
+ expect(I18n.l("time.formats.short_with_placeholders", "2009-01-07 09:12:35", { p1: "!" })).toEqual("07/01, 09:12 h !");
42
+ });
43
+
37
44
  it("localizes percentage", function(){
38
45
  I18n.locale = "pt-BR";
39
46
  expect(I18n.l("percentage", 123.45)).toEqual("123,45%");
@@ -32,7 +32,7 @@ describe("Pluralization", function(){
32
32
  });
33
33
 
34
34
  it("pluralizes using negative values", function(){
35
- expect(I18n.p(-1, "inbox")).toEqual("You have -1 message");
35
+ expect(I18n.p(-1, "inbox")).toEqual("You have -1 messages");
36
36
  expect(I18n.p(-5, "inbox")).toEqual("You have -5 messages");
37
37
  });
38
38
 
@@ -76,6 +76,7 @@ describe("Pluralization", function(){
76
76
 
77
77
  expect(I18n.p(0, "things")).toEqual("No things");
78
78
  expect(I18n.p(4, "things")).toEqual("A few things");
79
+ expect(I18n.p(-4, "things")).toEqual("-4 things");
79
80
  expect(I18n.p(10, "things")).toEqual("10 things");
80
81
  });
81
82
 
@@ -88,6 +88,7 @@ var DEBUG = false;
88
88
  "default": "%d/%m/%Y"
89
89
  , "short": "%d de %B"
90
90
  , "long": "%d de %B de %Y"
91
+ , "short_with_placeholders": "%d de %B {{p1}} {{p2}}"
91
92
  }
92
93
  , day_names: ["Domingo", "Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado"]
93
94
  , abbr_day_names: ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"]
@@ -100,6 +101,7 @@ var DEBUG = false;
100
101
  "default": "%A, %d de %B de %Y, %H:%M h"
101
102
  , "short": "%d/%m, %H:%M h"
102
103
  , "long": "%A, %d de %B de %Y, %H:%M h"
104
+ , "short_with_placeholders": "%d/%m, %H:%M h {{p1}}"
103
105
  }
104
106
  , am: "AM"
105
107
  , pm: "PM"
@@ -24,6 +24,15 @@ module Helpers
24
24
  def temp_path(file_name = "")
25
25
  File.expand_path("../../tmp/i18n-js/#{file_name}", __FILE__)
26
26
  end
27
+
28
+
29
+ def self.included(base)
30
+ base.let(:backend_class_with_fallbacks) do
31
+ klass = Class.new(I18n::Backend::Simple)
32
+ klass.send(:include, I18n::Backend::Fallbacks)
33
+ klass
34
+ end
35
+ end
27
36
  end
28
37
 
29
38
  RSpec.configure do |config|
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i18n-js
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0.rc7
4
+ version: 3.0.0.rc8
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-10-20 00:00:00.000000000 Z
11
+ date: 2014-11-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n
@@ -132,6 +132,7 @@ files:
132
132
  - lib/i18n/js.rb
133
133
  - lib/i18n/js/dependencies.rb
134
134
  - lib/i18n/js/engine.rb
135
+ - lib/i18n/js/fallback_locales.rb
135
136
  - lib/i18n/js/middleware.rb
136
137
  - lib/i18n/js/utils.rb
137
138
  - lib/i18n/js/version.rb
@@ -143,6 +144,11 @@ files:
143
144
  - spec/fixtures/default.yml
144
145
  - spec/fixtures/erb.yml
145
146
  - spec/fixtures/js_file_per_locale.yml
147
+ - spec/fixtures/js_file_per_locale_with_fallbacks_as_default_locale_symbol.yml
148
+ - spec/fixtures/js_file_per_locale_with_fallbacks_as_hash.yml
149
+ - spec/fixtures/js_file_per_locale_with_fallbacks_as_locale.yml
150
+ - spec/fixtures/js_file_per_locale_with_fallbacks_enabled.yml
151
+ - spec/fixtures/js_file_per_locale_without_fallbacks.yml
146
152
  - spec/fixtures/locales.yml
147
153
  - spec/fixtures/multiple_conditions.yml
148
154
  - spec/fixtures/multiple_conditions_per_locale.yml
@@ -150,6 +156,7 @@ files:
150
156
  - spec/fixtures/no_config.yml
151
157
  - spec/fixtures/no_scope.yml
152
158
  - spec/fixtures/simple_scope.yml
159
+ - spec/i18n_js_fallback_locales_spec.rb
153
160
  - spec/i18n_js_spec.rb
154
161
  - spec/js/currency.spec.js
155
162
  - spec/js/current_locale.spec.js
@@ -191,7 +198,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
191
198
  version: 1.3.1
192
199
  requirements: []
193
200
  rubyforge_project:
194
- rubygems_version: 2.2.2
201
+ rubygems_version: 2.4.3
195
202
  signing_key:
196
203
  specification_version: 4
197
204
  summary: It's a small library to provide the Rails I18n translations on the Javascript.
@@ -200,6 +207,11 @@ test_files:
200
207
  - spec/fixtures/default.yml
201
208
  - spec/fixtures/erb.yml
202
209
  - spec/fixtures/js_file_per_locale.yml
210
+ - spec/fixtures/js_file_per_locale_with_fallbacks_as_default_locale_symbol.yml
211
+ - spec/fixtures/js_file_per_locale_with_fallbacks_as_hash.yml
212
+ - spec/fixtures/js_file_per_locale_with_fallbacks_as_locale.yml
213
+ - spec/fixtures/js_file_per_locale_with_fallbacks_enabled.yml
214
+ - spec/fixtures/js_file_per_locale_without_fallbacks.yml
203
215
  - spec/fixtures/locales.yml
204
216
  - spec/fixtures/multiple_conditions.yml
205
217
  - spec/fixtures/multiple_conditions_per_locale.yml
@@ -207,6 +219,7 @@ test_files:
207
219
  - spec/fixtures/no_config.yml
208
220
  - spec/fixtures/no_scope.yml
209
221
  - spec/fixtures/simple_scope.yml
222
+ - spec/i18n_js_fallback_locales_spec.rb
210
223
  - spec/i18n_js_spec.rb
211
224
  - spec/js/currency.spec.js
212
225
  - spec/js/current_locale.spec.js