i18n-complements 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +20 -0
- data/README +15 -0
- data/VERSION +1 -0
- data/lib/i18n-complements/localize_numbers.rb +65 -0
- data/lib/i18n-complements/numisma/currencies.yml +1002 -0
- data/lib/i18n-complements/numisma/currency.rb +78 -0
- data/lib/i18n-complements/numisma.rb +61 -0
- data/lib/i18n-complements.rb +10 -0
- data/test/helper.rb +11 -0
- data/test/locales/eng.yml +10 -0
- data/test/locales/fra.yml +10 -0
- data/test/locales/jpn.yml +13 -0
- data/test/test_currencies.rb +12 -0
- data/test/test_numbers.rb +84 -0
- metadata +86 -0
@@ -0,0 +1,78 @@
|
|
1
|
+
module I18nComplements
|
2
|
+
module Numisma
|
3
|
+
|
4
|
+
class Currency
|
5
|
+
attr_reader :code, :active, :cash, :countries, :number, :precision, :unit
|
6
|
+
|
7
|
+
def initialize(code, options = {})
|
8
|
+
@code = code.strip.upcase
|
9
|
+
@active = (options[:active] ? true : false)
|
10
|
+
@cash = options[:cash].to_a.collect{|x| x.to_f}.sort
|
11
|
+
@countries = options[:countries].to_a.collect{|x| x.to_s}.sort.collect{|x| x.to_sym}
|
12
|
+
@number = options[:number].to_i
|
13
|
+
@precision = options[:precision].to_i
|
14
|
+
@unit = (options[:unit].nil? ? nil : options[:unit].to_s)
|
15
|
+
end
|
16
|
+
|
17
|
+
def name
|
18
|
+
::I18n.translate("currencies.#{self.code}")
|
19
|
+
end
|
20
|
+
|
21
|
+
def label
|
22
|
+
::I18n.translate("labels.currency_with_code", :code=>self.code, :name=>self.name, :default=>"%{name} (%{code})")
|
23
|
+
end
|
24
|
+
|
25
|
+
def round(value, options={})
|
26
|
+
precision = self.precision
|
27
|
+
if RUBY_VERSION.match(/^1\.8/)
|
28
|
+
magnitude = 10**precision
|
29
|
+
return (value * magnitude).to_i.to_f*magnitude
|
30
|
+
else
|
31
|
+
return value.round(precision)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def ==(other_currency)
|
36
|
+
self.code == other_currency.code
|
37
|
+
end
|
38
|
+
|
39
|
+
# Produces a amount of the currency with the locale parameters
|
40
|
+
# TODO: Find a better way to specify number formats which are more complex that the default Rails use
|
41
|
+
def localize(amount, options={})
|
42
|
+
return unless amount
|
43
|
+
|
44
|
+
# options.symbolize_keys!
|
45
|
+
|
46
|
+
defaults = I18n.translate('number.format'.to_sym, :locale => options[:locale], :default => {})
|
47
|
+
defaultt = I18n.translate('number.currency.format'.to_sym, :locale => options[:locale], :default => {})
|
48
|
+
defaultt[:negative_format] ||= ("-" + defaultt[:format]) if defaultt[:format]
|
49
|
+
formatcy = I18n.translate("number.currency.formats.#{self.code}".to_sym, :locale => options[:locale], :default => {})
|
50
|
+
formatcy[:negative_format] ||= "-" + formatcy[:format] if formatcy[:format]
|
51
|
+
|
52
|
+
prec = {}
|
53
|
+
prec[:separator] = formatcy[:separator] || defaultt[:separator] || defaults[:separator] || ','
|
54
|
+
prec[:delimiter] = formatcy[:delimiter] || defaultt[:delimiter] || defaults[:delimiter] || ''
|
55
|
+
prec[:precision] = formatcy[:precision] || self.precision || defaultt[:precision] || 3
|
56
|
+
format = formatcy[:format] || defaultt[:format] || "%n-%u" # defaults[:format] ||
|
57
|
+
negative_format = formatcy[:negative_format] || defaultt[:negative_format] || defaults[:negative_format] || "-" + format
|
58
|
+
unit = formatcy[:unit] || self.unit || self.code
|
59
|
+
|
60
|
+
if amount.to_f < 0
|
61
|
+
format = negative_format # options.delete(:negative_format)
|
62
|
+
amount = amount.respond_to?("abs") ? amount.abs : amount.sub(/^-/, '')
|
63
|
+
end
|
64
|
+
|
65
|
+
value = amount.to_s
|
66
|
+
integers, decimals = value.split(/\./)
|
67
|
+
value = integers.gsub(/^0+[1-9]+/, '').gsub(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{prec[:delimiter]}")
|
68
|
+
unless decimals.to_s.match(/^\s*$/)
|
69
|
+
decimals = decimals.gsub(/0+$/, '').ljust(prec[:precision], '0').reverse.split(/(?=\d{3})/).reverse.collect{|x| x.reverse}.join(prec[:delimiter])
|
70
|
+
value += prec[:separator] + decimals
|
71
|
+
end
|
72
|
+
return format.gsub(/%n/, value).gsub(/%u/, unit).gsub(/%s/, "\u{00A0}")
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# This module aimed to structure and controls currencies through the application
|
2
|
+
# It represents the international monetary system with all its currencies like specified in ISO 4217
|
3
|
+
# Numisma comes from latin: It designs here the "science of money"
|
4
|
+
require 'net/http'
|
5
|
+
require 'i18n-complements/numisma/currency'
|
6
|
+
|
7
|
+
module I18nComplements
|
8
|
+
module Numisma
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
def currencies
|
13
|
+
@@currencies
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
# Returns the path to currencies file
|
18
|
+
def currencies_file
|
19
|
+
# Rails.root.join("config", "currencies.yml")
|
20
|
+
File.join(File.dirname(__FILE__), "numisma", "currencies.yml")
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns a hash with active currencies only
|
24
|
+
def active_currencies
|
25
|
+
x = {}
|
26
|
+
for code, currency in @@currencies
|
27
|
+
x[code] = currency if currency.active
|
28
|
+
end
|
29
|
+
return x
|
30
|
+
end
|
31
|
+
|
32
|
+
# Shorcut to get currency
|
33
|
+
def [](currency_code)
|
34
|
+
@@currencies[currency_code]
|
35
|
+
end
|
36
|
+
|
37
|
+
def currency_rate(from, to)
|
38
|
+
raise ArgumentError.new(":from currency is unknown (#{from.class}:#{from.inspect})") if Numisma[from].nil?
|
39
|
+
raise ArgumentError.new(":to currency is unknown (#{to.class}:#{to.inspect})") if Numisma[to].nil?
|
40
|
+
uri = URI("http://www.webservicex.net/CurrencyConvertor.asmx/ConversionRate")
|
41
|
+
response = Net::HTTP.post_form(uri, 'FromCurrency' => from, 'ToCurrency' => to)
|
42
|
+
doc = ::LibXML::XML::Parser.string(response.body).parse
|
43
|
+
return doc.root.content.to_f
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
# Load currencies
|
48
|
+
def load_currencies
|
49
|
+
@@currencies = {}
|
50
|
+
for code, details in YAML.load_file(self.currencies_file)
|
51
|
+
|
52
|
+
currency = Currency.new(code, details.inject({}){|h, p| h[p[0].to_sym] = p[1]; h})
|
53
|
+
@@currencies[currency.code] = currency
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Finally load all currencies
|
59
|
+
load_currencies
|
60
|
+
end
|
61
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'bundler/setup'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
5
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
6
|
+
|
7
|
+
require 'i18n-complements'
|
8
|
+
|
9
|
+
for file in Dir[File.join(File.dirname(__FILE__), "locales", "*.yml")]
|
10
|
+
I18n.backend.load_translations(file)
|
11
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'helper'
|
3
|
+
|
4
|
+
class TestNumbers < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_localization
|
7
|
+
assert_nothing_raised do
|
8
|
+
I18n.localize(14.5)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_number_formatting
|
13
|
+
# Integer
|
14
|
+
number = 3
|
15
|
+
assert_equal "3", I18n.localize(number, :locale => :eng)
|
16
|
+
assert_equal "3", I18n.localize(number, :locale => :fra)
|
17
|
+
|
18
|
+
# Integer > 1000
|
19
|
+
number = 21145
|
20
|
+
assert_equal "21,145", I18n.localize(number, :locale => :eng)
|
21
|
+
assert_equal "21\u{00A0}145", I18n.localize(number, :locale => :fra)
|
22
|
+
|
23
|
+
# Float without integers with decimals
|
24
|
+
number = 0.5
|
25
|
+
assert_equal "0.500", I18n.localize(number, :locale => :eng)
|
26
|
+
assert_equal "0,500", I18n.localize(number, :locale => :fra)
|
27
|
+
|
28
|
+
# Float without decimals
|
29
|
+
number = 3.0
|
30
|
+
assert_equal "3.000", I18n.localize(number, :locale => :eng)
|
31
|
+
assert_equal "3,000", I18n.localize(number, :locale => :fra)
|
32
|
+
|
33
|
+
# Float
|
34
|
+
number = 14.53
|
35
|
+
assert_equal "14.530", I18n.localize(number, :locale => :eng)
|
36
|
+
assert_equal "14,530", I18n.localize(number, :locale => :fra)
|
37
|
+
|
38
|
+
# Float > 1000
|
39
|
+
number = 2114.5
|
40
|
+
assert_equal "2,114.500", I18n.localize(number, :locale => :eng)
|
41
|
+
assert_equal "2\u{00A0}114,500", I18n.localize(number, :locale => :fra)
|
42
|
+
|
43
|
+
# Float without integers with decimals < 0.001
|
44
|
+
number = 0.41421356
|
45
|
+
assert_equal "0.414,213,56", I18n.localize(number, :locale => :eng)
|
46
|
+
assert_equal "0,414\u{00A0}213\u{00A0}56", I18n.localize(number, :locale => :fra)
|
47
|
+
|
48
|
+
# Float without integers with decimals < 0.001
|
49
|
+
number = 3.1415926
|
50
|
+
assert_equal "3.141,592,6", I18n.localize(number, :locale => :eng)
|
51
|
+
assert_equal "3,141\u{00A0}592\u{00A0}6", I18n.localize(number, :locale => :fra)
|
52
|
+
|
53
|
+
# Float without integers with decimals < 0.001
|
54
|
+
number = 62951413.1415926
|
55
|
+
assert_equal "62,951,413.141,592,6", I18n.localize(number, :locale => :eng)
|
56
|
+
assert_equal "62\u{00A0}951\u{00A0}413,141\u{00A0}592\u{00A0}6", I18n.localize(number, :locale => :fra)
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
def test_localization_with_currency
|
61
|
+
I18n.localize(14.5, :currency => :JPY)
|
62
|
+
assert_nothing_raised do
|
63
|
+
I18n.localize(14.5, :currency => :JPY)
|
64
|
+
end
|
65
|
+
|
66
|
+
assert_nothing_raised do
|
67
|
+
I18n.localize(14.5, :currency => "JPY")
|
68
|
+
end
|
69
|
+
|
70
|
+
assert_raise(I18nComplements::InvalidCurrency) do
|
71
|
+
I18n.localize(14.5, :currency => "jPY")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_formatting_with_currency
|
76
|
+
number = 413500
|
77
|
+
assert_equal "¥413,500", I18n.localize(number, :locale => :eng, :currency=>"JPY")
|
78
|
+
assert_equal "413\u{00A0}500\u{00A0}¥", I18n.localize(number, :locale => :fra, :currency=>"JPY")
|
79
|
+
assert_equal "413,500円", I18n.localize(number, :locale => :jpn, :currency=>"JPY")
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
|
84
|
+
end
|
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: i18n-complements
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Brice Texier
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-09 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: i18n
|
16
|
+
requirement: &15085180 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0.6'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *15085180
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rake
|
27
|
+
requirement: &15084120 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.8.7
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *15084120
|
36
|
+
description:
|
37
|
+
email: burisu@oneiros.fr
|
38
|
+
executables: []
|
39
|
+
extensions: []
|
40
|
+
extra_rdoc_files:
|
41
|
+
- LICENSE
|
42
|
+
- README
|
43
|
+
files:
|
44
|
+
- LICENSE
|
45
|
+
- README
|
46
|
+
- VERSION
|
47
|
+
- lib/i18n-complements.rb
|
48
|
+
- lib/i18n-complements/localize_numbers.rb
|
49
|
+
- lib/i18n-complements/numisma.rb
|
50
|
+
- lib/i18n-complements/numisma/currencies.yml
|
51
|
+
- lib/i18n-complements/numisma/currency.rb
|
52
|
+
- test/helper.rb
|
53
|
+
- test/locales/eng.yml
|
54
|
+
- test/locales/fra.yml
|
55
|
+
- test/locales/jpn.yml
|
56
|
+
- test/test_currencies.rb
|
57
|
+
- test/test_numbers.rb
|
58
|
+
homepage: http://github.com/burisu/i18n-complements
|
59
|
+
licenses:
|
60
|
+
- MIT
|
61
|
+
post_install_message:
|
62
|
+
rdoc_options: []
|
63
|
+
require_paths:
|
64
|
+
- lib
|
65
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '0'
|
71
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
requirements: []
|
78
|
+
rubyforge_project:
|
79
|
+
rubygems_version: 1.8.11
|
80
|
+
signing_key:
|
81
|
+
specification_version: 3
|
82
|
+
summary: I18n missing functionnalities
|
83
|
+
test_files:
|
84
|
+
- test/test_currencies.rb
|
85
|
+
- test/test_numbers.rb
|
86
|
+
has_rdoc:
|