i18n-js-pika 3.0.0.rc6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/CHANGELOG.md +13 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +52 -0
- data/README.md +326 -0
- data/Rakefile +13 -0
- data/app/assets/javascripts/i18n/filtered.js.erb +2 -0
- data/app/assets/javascripts/i18n/shims.js +93 -0
- data/app/assets/javascripts/i18n/translations.js +3 -0
- data/app/assets/javascripts/i18n.js +690 -0
- data/i18n-js.gemspec +27 -0
- data/lib/i18n/js/engine.rb +22 -0
- data/lib/i18n/js/middleware.rb +59 -0
- data/lib/i18n/js/version.rb +12 -0
- data/lib/i18n/js.rb +162 -0
- data/lib/i18n-js.rb +1 -0
- data/lib/tasks/export.rake +8 -0
- data/package.json +11 -0
- data/spec/fixtures/custom_path.yml +4 -0
- data/spec/fixtures/default.yml +4 -0
- data/spec/fixtures/js_file_per_locale.yml +3 -0
- data/spec/fixtures/locales.yml +76 -0
- data/spec/fixtures/multiple_conditions.yml +5 -0
- data/spec/fixtures/multiple_files.yml +6 -0
- data/spec/fixtures/no_config.yml +2 -0
- data/spec/fixtures/no_scope.yml +3 -0
- data/spec/fixtures/simple_scope.yml +4 -0
- data/spec/i18n_js_spec.rb +139 -0
- data/spec/js/currency.spec.js +60 -0
- data/spec/js/current_locale.spec.js +19 -0
- data/spec/js/dates.spec.js +222 -0
- data/spec/js/defaults.spec.js +23 -0
- data/spec/js/interpolation.spec.js +28 -0
- data/spec/js/jasmine/MIT.LICENSE +20 -0
- data/spec/js/jasmine/jasmine-html.js +190 -0
- data/spec/js/jasmine/jasmine.css +166 -0
- data/spec/js/jasmine/jasmine.js +2476 -0
- data/spec/js/jasmine/jasmine_favicon.png +0 -0
- data/spec/js/localization.spec.js +41 -0
- data/spec/js/numbers.spec.js +142 -0
- data/spec/js/placeholder.spec.js +24 -0
- data/spec/js/pluralization.spec.js +105 -0
- data/spec/js/prepare_options.spec.js +41 -0
- data/spec/js/specs.html +46 -0
- data/spec/js/translate.spec.js +120 -0
- data/spec/js/translations.js +120 -0
- data/spec/spec_helper.rb +41 -0
- metadata +196 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
require "i18n/js"
|
2
|
+
|
3
|
+
module I18n
|
4
|
+
module JS
|
5
|
+
class Engine < ::Rails::Engine
|
6
|
+
initializer :after => "sprockets.environment" do
|
7
|
+
ActiveSupport.on_load(:after_initialize, :yield => true) do
|
8
|
+
next unless JS.has_asset_pipeline?
|
9
|
+
next unless Rails.configuration.assets.compile
|
10
|
+
|
11
|
+
registry = Sprockets.respond_to?("register_preprocessor") ? Sprockets : Rails.application.assets
|
12
|
+
|
13
|
+
registry.register_preprocessor "application/javascript", :"i18n-js_dependencies" do |context, source|
|
14
|
+
next source unless context.logical_path == "i18n/filtered"
|
15
|
+
::I18n.load_path.each {|path| context.depend_on(File.expand_path(path))}
|
16
|
+
source
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module I18n
|
2
|
+
module JS
|
3
|
+
class Middleware
|
4
|
+
def initialize(app)
|
5
|
+
@app = app
|
6
|
+
end
|
7
|
+
|
8
|
+
def call(env)
|
9
|
+
@cache = nil
|
10
|
+
verify_locale_files!
|
11
|
+
@app.call(env)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
def cache_path
|
16
|
+
@cache_path ||= Rails.root.join("tmp/cache/i18n-js.yml")
|
17
|
+
end
|
18
|
+
|
19
|
+
def cache
|
20
|
+
@cache ||= begin
|
21
|
+
if cache_path.exist?
|
22
|
+
YAML.load_file(cache_path) || {}
|
23
|
+
else
|
24
|
+
{}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
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
|
+
#
|
36
|
+
def verify_locale_files!
|
37
|
+
valid_cache = []
|
38
|
+
new_cache = {}
|
39
|
+
|
40
|
+
valid_cache.push cache_path.exist?
|
41
|
+
valid_cache.push ::I18n.load_path.uniq.size == cache.size
|
42
|
+
|
43
|
+
::I18n.load_path.each do |path|
|
44
|
+
changed_at = File.mtime(path).to_i
|
45
|
+
valid_cache.push changed_at == cache[path]
|
46
|
+
new_cache[path] = changed_at
|
47
|
+
end
|
48
|
+
|
49
|
+
return if valid_cache.all?
|
50
|
+
|
51
|
+
File.open(cache_path, "w+") do |file|
|
52
|
+
file << new_cache.to_yaml
|
53
|
+
end
|
54
|
+
|
55
|
+
::I18n::JS.export
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/lib/i18n/js.rb
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
require "i18n"
|
2
|
+
require "FileUtils" unless defined?(FileUtils)
|
3
|
+
|
4
|
+
module I18n
|
5
|
+
module JS
|
6
|
+
if defined?(Rails)
|
7
|
+
require "i18n/js/middleware"
|
8
|
+
require "i18n/js/engine"
|
9
|
+
end
|
10
|
+
|
11
|
+
# deep_merge by Stefan Rusterholz, see <http://www.ruby-forum.com/topic/142809>.
|
12
|
+
MERGER = proc do |key, v1, v2|
|
13
|
+
Hash === v1 && Hash === v2 ? v1.merge(v2, &MERGER) : v2
|
14
|
+
end
|
15
|
+
|
16
|
+
# Detect if Rails app has asset pipeline support.
|
17
|
+
#
|
18
|
+
def self.has_asset_pipeline?
|
19
|
+
Rails.configuration.respond_to?(:assets) && Rails.configuration.assets.enabled
|
20
|
+
end
|
21
|
+
|
22
|
+
# The configuration file. This defaults to the `config/i18n-js.yml` file.
|
23
|
+
#
|
24
|
+
def self.config_file
|
25
|
+
@config_file ||= "config/i18n-js.yml"
|
26
|
+
end
|
27
|
+
|
28
|
+
# Export translations to JavaScript, considering settings
|
29
|
+
# from configuration file
|
30
|
+
def self.export
|
31
|
+
translation_segments.each do |filename, translations|
|
32
|
+
save(translations, filename)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.segments_per_locale(pattern, scope)
|
37
|
+
I18n.available_locales.each_with_object({}) do |locale, segments|
|
38
|
+
result = scoped_translations("#{locale}.#{scope}")
|
39
|
+
next if result.empty?
|
40
|
+
|
41
|
+
segment_name = ::I18n.interpolate(pattern,{:locale => locale})
|
42
|
+
segments[segment_name] = result
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.segment_for_scope(scope)
|
47
|
+
if scope == "*"
|
48
|
+
translations
|
49
|
+
else
|
50
|
+
scoped_translations(scope)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.configured_segments
|
55
|
+
config[:translations].each_with_object({}) do |options, segments|
|
56
|
+
options.reverse_merge!(:only => "*")
|
57
|
+
if options[:file] =~ ::I18n::INTERPOLATION_PATTERN
|
58
|
+
segments.merge!(segments_per_locale(options[:file], options[:only]))
|
59
|
+
else
|
60
|
+
result = segment_for_scope(options[:only])
|
61
|
+
segments[options[:file]] = result unless result.empty?
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.export_dir
|
67
|
+
"public/javascripts"
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.filtered_translations
|
71
|
+
{}.tap do |result|
|
72
|
+
translation_segments.each do |filename, translations|
|
73
|
+
deep_merge!(result, translations)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.translation_segments
|
79
|
+
segments = if config? && config[:translations]
|
80
|
+
configured_segments
|
81
|
+
else
|
82
|
+
{"#{export_dir}/translations.js" => translations}
|
83
|
+
end
|
84
|
+
segments.inject({}) do |hash, (filename, translations)|
|
85
|
+
hash[filename] = translations.nil? ? nil : translations.select{|locale,_| I18n.available_locales.include?(locale) }
|
86
|
+
hash
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Load configuration file for partial exporting and
|
91
|
+
# custom output directory
|
92
|
+
def self.config
|
93
|
+
if config?
|
94
|
+
(YAML.load_file(config_file) || {}).with_indifferent_access
|
95
|
+
else
|
96
|
+
{}
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Check if configuration file exist
|
101
|
+
def self.config?
|
102
|
+
File.file? config_file
|
103
|
+
end
|
104
|
+
|
105
|
+
# Convert translations to JSON string and save file.
|
106
|
+
def self.save(translations, file)
|
107
|
+
FileUtils.mkdir_p File.dirname(file)
|
108
|
+
|
109
|
+
File.open(file, "w+") do |f|
|
110
|
+
f << %(I18n.translations || (I18n.translations = {});\n)
|
111
|
+
translations.each do |locale, translations_for_locale|
|
112
|
+
f << %(I18n.translations["#{locale}"] = #{translations_for_locale.to_json};\n);
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.scoped_translations(scopes) # :nodoc:
|
118
|
+
result = {}
|
119
|
+
|
120
|
+
[scopes].flatten.each do |scope|
|
121
|
+
deep_merge! result, filter(translations, scope)
|
122
|
+
end
|
123
|
+
|
124
|
+
result
|
125
|
+
end
|
126
|
+
|
127
|
+
# Filter translations according to the specified scope.
|
128
|
+
def self.filter(translations, scopes)
|
129
|
+
scopes = scopes.split(".") if scopes.is_a?(String)
|
130
|
+
scopes = scopes.clone
|
131
|
+
scope = scopes.shift
|
132
|
+
|
133
|
+
if scope == "*"
|
134
|
+
results = {}
|
135
|
+
translations.each do |scope, translations|
|
136
|
+
tmp = scopes.empty? ? translations : filter(translations, scopes)
|
137
|
+
results[scope.to_sym] = tmp unless tmp.nil?
|
138
|
+
end
|
139
|
+
return results
|
140
|
+
elsif translations.has_key?(scope.to_sym)
|
141
|
+
return {scope.to_sym => scopes.empty? ? translations[scope.to_sym] : filter(translations[scope.to_sym], scopes)}
|
142
|
+
end
|
143
|
+
nil
|
144
|
+
end
|
145
|
+
|
146
|
+
# Initialize and return translations
|
147
|
+
def self.translations
|
148
|
+
::I18n.backend.instance_eval do
|
149
|
+
init_translations unless initialized?
|
150
|
+
translations
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def self.deep_merge(target, hash) # :nodoc:
|
155
|
+
target.merge(hash, &MERGER)
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.deep_merge!(target, hash) # :nodoc:
|
159
|
+
target.merge!(hash, &MERGER)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
data/lib/i18n-js.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "i18n/js"
|
data/package.json
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
en:
|
2
|
+
number:
|
3
|
+
format:
|
4
|
+
separator: "."
|
5
|
+
delimiter: ","
|
6
|
+
precision: 3
|
7
|
+
currency:
|
8
|
+
format:
|
9
|
+
format: "%u%n"
|
10
|
+
unit: "$"
|
11
|
+
separator: "."
|
12
|
+
delimiter: ","
|
13
|
+
precision: 2
|
14
|
+
date:
|
15
|
+
formats:
|
16
|
+
default: "%Y-%m-%d"
|
17
|
+
short: "%b %d"
|
18
|
+
long: "%B %d, %Y"
|
19
|
+
day_names: [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday]
|
20
|
+
abbr_day_names: [Sun, Mon, Tue, Wed, Thu, Fri, Sat]
|
21
|
+
month_names: [~, January, February, March, April, May, June, July, August, September, October, November, December]
|
22
|
+
abbr_month_names: [~, Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec]
|
23
|
+
# order: [ :year, :month, :day ]
|
24
|
+
time:
|
25
|
+
formats:
|
26
|
+
default: "%a, %d %b %Y %H:%M:%S %z"
|
27
|
+
short: "%d %b %H:%M"
|
28
|
+
long: "%B %d, %Y %H:%M"
|
29
|
+
am: "am"
|
30
|
+
pm: "pm"
|
31
|
+
admin:
|
32
|
+
show:
|
33
|
+
title: "Show"
|
34
|
+
note: "more details"
|
35
|
+
edit:
|
36
|
+
title: "Edit"
|
37
|
+
|
38
|
+
fr:
|
39
|
+
date:
|
40
|
+
formats:
|
41
|
+
default: "%d/%m/%Y"
|
42
|
+
short: "%e %b"
|
43
|
+
long: "%e %B %Y"
|
44
|
+
long_ordinal: "%e %B %Y"
|
45
|
+
only_day: "%e"
|
46
|
+
day_names: [dimanche, lundi, mardi, mercredi, jeudi, vendredi, samedi]
|
47
|
+
abbr_day_names: [dim, lun, mar, mer, jeu, ven, sam]
|
48
|
+
month_names: [~, janvier, février, mars, avril, mai, juin, juillet, août, septembre, octobre, novembre, décembre]
|
49
|
+
abbr_month_names: [~, jan., fév., mar., avr., mai, juin, juil., août, sept., oct., nov., déc.]
|
50
|
+
# order: [ :day, :month, :year ]
|
51
|
+
time:
|
52
|
+
formats:
|
53
|
+
default: "%d %B %Y %H:%M"
|
54
|
+
time: "%H:%M"
|
55
|
+
short: "%d %b %H:%M"
|
56
|
+
long: "%A %d %B %Y %H:%M:%S %Z"
|
57
|
+
long_ordinal: "%A %d %B %Y %H:%M:%S %Z"
|
58
|
+
only_second: "%S"
|
59
|
+
am: 'am'
|
60
|
+
pm: 'pm'
|
61
|
+
number:
|
62
|
+
format:
|
63
|
+
precision: 3
|
64
|
+
separator: ','
|
65
|
+
delimiter: ' '
|
66
|
+
currency:
|
67
|
+
format:
|
68
|
+
unit: '€'
|
69
|
+
precision: 2
|
70
|
+
format: '%n %u'
|
71
|
+
admin:
|
72
|
+
show:
|
73
|
+
title: "Visualiser"
|
74
|
+
note: "plus de détails"
|
75
|
+
edit:
|
76
|
+
title: "Editer"
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe I18n::JS do
|
4
|
+
context "exporting" do
|
5
|
+
before do
|
6
|
+
I18n::JS.stub :export_dir => temp_path
|
7
|
+
end
|
8
|
+
|
9
|
+
it "exports messages to default path when configuration file doesn't exist" do
|
10
|
+
I18n::JS.export
|
11
|
+
file_should_exist "translations.js"
|
12
|
+
end
|
13
|
+
|
14
|
+
it "exports messages using custom output path" do
|
15
|
+
set_config "custom_path.yml"
|
16
|
+
I18n::JS.should_receive(:save).with(translations, "tmp/i18n-js/all.js")
|
17
|
+
I18n::JS.export
|
18
|
+
end
|
19
|
+
|
20
|
+
it "sets default scope to * when not specified" do
|
21
|
+
set_config "no_scope.yml"
|
22
|
+
I18n::JS.should_receive(:save).with(translations, "tmp/i18n-js/no_scope.js")
|
23
|
+
I18n::JS.export
|
24
|
+
end
|
25
|
+
|
26
|
+
it "exports to multiple files" do
|
27
|
+
set_config "multiple_files.yml"
|
28
|
+
I18n::JS.export
|
29
|
+
|
30
|
+
file_should_exist "all.js"
|
31
|
+
file_should_exist "tudo.js"
|
32
|
+
end
|
33
|
+
|
34
|
+
it "ignores an empty config file" do
|
35
|
+
set_config "no_config.yml"
|
36
|
+
I18n::JS.export
|
37
|
+
|
38
|
+
file_should_exist "translations.js"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "exports to a JS file per available locale" do
|
42
|
+
set_config "js_file_per_locale.yml"
|
43
|
+
I18n::JS.export
|
44
|
+
|
45
|
+
file_should_exist "en.js"
|
46
|
+
end
|
47
|
+
|
48
|
+
it "exports with multiple conditions" do
|
49
|
+
set_config "multiple_conditions.yml"
|
50
|
+
I18n::JS.export
|
51
|
+
|
52
|
+
file_should_exist "bitsnpieces.js"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "filters" do
|
57
|
+
it "filters translations using scope *.date.formats" do
|
58
|
+
result = I18n::JS.filter(translations, "*.date.formats")
|
59
|
+
result[:en][:date].keys.should eql([:formats])
|
60
|
+
result[:fr][:date].keys.should eql([:formats])
|
61
|
+
end
|
62
|
+
|
63
|
+
it "filters translations using scope [*.date.formats, *.number.currency.format]" do
|
64
|
+
result = I18n::JS.scoped_translations(["*.date.formats", "*.number.currency.format"])
|
65
|
+
result[:en].keys.collect(&:to_s).sort.should eql(%w[ date number ])
|
66
|
+
result[:fr].keys.collect(&:to_s).sort.should eql(%w[ date number ])
|
67
|
+
end
|
68
|
+
|
69
|
+
it "filters translations using multi-star scope" do
|
70
|
+
result = I18n::JS.scoped_translations("*.*.formats")
|
71
|
+
|
72
|
+
result[:en].keys.collect(&:to_s).sort.should eql(%w[ date time ])
|
73
|
+
result[:fr].keys.collect(&:to_s).sort.should eql(%w[ date time ])
|
74
|
+
|
75
|
+
result[:en][:date].keys.should eql([:formats])
|
76
|
+
result[:en][:time].keys.should eql([:formats])
|
77
|
+
|
78
|
+
result[:fr][:date].keys.should eql([:formats])
|
79
|
+
result[:fr][:time].keys.should eql([:formats])
|
80
|
+
end
|
81
|
+
|
82
|
+
it "filters translations using alternated stars" do
|
83
|
+
result = I18n::JS.scoped_translations("*.admin.*.title")
|
84
|
+
|
85
|
+
result[:en][:admin].keys.collect(&:to_s).sort.should eql(%w[ edit show ])
|
86
|
+
result[:fr][:admin].keys.collect(&:to_s).sort.should eql(%w[ edit show ])
|
87
|
+
|
88
|
+
result[:en][:admin][:show][:title].should eql("Show")
|
89
|
+
result[:fr][:admin][:show][:title].should eql("Visualiser")
|
90
|
+
|
91
|
+
result[:en][:admin][:edit][:title].should eql("Edit")
|
92
|
+
result[:fr][:admin][:edit][:title].should eql("Editer")
|
93
|
+
end
|
94
|
+
|
95
|
+
context "with available_locales set" do
|
96
|
+
before do
|
97
|
+
I18n.stub :available_locales => [:fr]
|
98
|
+
end
|
99
|
+
|
100
|
+
context 'when without config' do
|
101
|
+
let(:result){ I18n::JS.translation_segments.values.first }
|
102
|
+
it "limits the translations to the available locales" do
|
103
|
+
result[:en].should be_nil
|
104
|
+
result[:fr].should be_present
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Don't know how to test this yet
|
109
|
+
context 'when with config'
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context "general" do
|
114
|
+
it "sets export directory" do
|
115
|
+
I18n::JS.export_dir.should eql("public/javascripts")
|
116
|
+
end
|
117
|
+
|
118
|
+
it "sets empty hash as configuration when no file is found" do
|
119
|
+
I18n::JS.config?.should be_false
|
120
|
+
I18n::JS.config.should eql({})
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
context "hash merging" do
|
125
|
+
it "performs a deep merge" do
|
126
|
+
target = {:a => {:b => 1}}
|
127
|
+
result = I18n::JS.deep_merge(target, {:a => {:c => 2}})
|
128
|
+
|
129
|
+
result[:a].should eql({:b => 1, :c => 2})
|
130
|
+
end
|
131
|
+
|
132
|
+
it "performs a banged deep merge" do
|
133
|
+
target = {:a => {:b => 1}}
|
134
|
+
I18n::JS.deep_merge!(target, {:a => {:c => 2}})
|
135
|
+
|
136
|
+
target[:a].should eql({:b => 1, :c => 2})
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
var I18n = require("../../app/assets/javascripts/i18n")
|
2
|
+
, Translations = require("./translations")
|
3
|
+
;
|
4
|
+
|
5
|
+
describe("Currency", function(){
|
6
|
+
var actual, expected;
|
7
|
+
|
8
|
+
beforeEach(function() {
|
9
|
+
I18n.reset();
|
10
|
+
I18n.translations = Translations();
|
11
|
+
});
|
12
|
+
|
13
|
+
it("formats currency with default settings", function(){
|
14
|
+
expect(I18n.toCurrency(100.99)).toEqual("$100.99");
|
15
|
+
expect(I18n.toCurrency(1000.99)).toEqual("$1,000.99");
|
16
|
+
});
|
17
|
+
|
18
|
+
it("formats currency with custom settings", function(){
|
19
|
+
I18n.translations.en.number = {
|
20
|
+
currency: {
|
21
|
+
format: {
|
22
|
+
format: "%n %u",
|
23
|
+
unit: "USD",
|
24
|
+
delimiter: ".",
|
25
|
+
separator: ",",
|
26
|
+
precision: 2
|
27
|
+
}
|
28
|
+
}
|
29
|
+
};
|
30
|
+
|
31
|
+
expect(I18n.toCurrency(12)).toEqual("12,00 USD");
|
32
|
+
expect(I18n.toCurrency(123)).toEqual("123,00 USD");
|
33
|
+
expect(I18n.toCurrency(1234.56)).toEqual("1.234,56 USD");
|
34
|
+
});
|
35
|
+
|
36
|
+
it("formats currency with custom settings and partial overriding", function(){
|
37
|
+
I18n.translations.en.number = {
|
38
|
+
currency: {
|
39
|
+
format: {
|
40
|
+
format: "%n %u",
|
41
|
+
unit: "USD",
|
42
|
+
delimiter: ".",
|
43
|
+
separator: ",",
|
44
|
+
precision: 2
|
45
|
+
}
|
46
|
+
}
|
47
|
+
};
|
48
|
+
|
49
|
+
expect(I18n.toCurrency(12, {precision: 0})).toEqual("12 USD");
|
50
|
+
expect(I18n.toCurrency(123, {unit: "bucks"})).toEqual("123,00 bucks");
|
51
|
+
});
|
52
|
+
|
53
|
+
it("formats currency with some custom options that should be merged with default options", function(){
|
54
|
+
expect(I18n.toCurrency(1234, {precision: 0})).toEqual("$1,234");
|
55
|
+
expect(I18n.toCurrency(1234, {unit: "º"})).toEqual("º1,234.00");
|
56
|
+
expect(I18n.toCurrency(1234, {separator: "-"})).toEqual("$1,234-00");
|
57
|
+
expect(I18n.toCurrency(1234, {delimiter: "-"})).toEqual("$1-234.00");
|
58
|
+
expect(I18n.toCurrency(1234, {format: "%u %n"})).toEqual("$ 1,234.00");
|
59
|
+
});
|
60
|
+
});
|
@@ -0,0 +1,19 @@
|
|
1
|
+
var I18n = require("../../app/assets/javascripts/i18n");
|
2
|
+
|
3
|
+
describe("Current locale", function(){
|
4
|
+
beforeEach(function(){
|
5
|
+
I18n.reset();
|
6
|
+
});
|
7
|
+
|
8
|
+
it("returns I18n.locale", function(){
|
9
|
+
I18n.locale = "pt-BR";
|
10
|
+
expect(I18n.currentLocale()).toEqual("pt-BR");
|
11
|
+
});
|
12
|
+
|
13
|
+
it("returns I18n.defaultLocale", function(){
|
14
|
+
I18n.locale = null;
|
15
|
+
I18n.defaultLocale = "pt-BR";
|
16
|
+
|
17
|
+
expect(I18n.currentLocale()).toEqual("pt-BR");
|
18
|
+
});
|
19
|
+
});
|