i18n-js 3.0.0.rc7 → 3.0.0.rc8

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 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