mini_i18n 0.4.0 → 0.5.0

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: cba824b157c9dde80eaaaf9be9f5515d94e971e9
4
- data.tar.gz: 5fbd8419e4aafde608285e00f202c15b15756a32
3
+ metadata.gz: e1535503921791b7c7660516aab9b224eda60883
4
+ data.tar.gz: 87d9b5f991ba9dca7da8310b2fc76d43b82a9100
5
5
  SHA512:
6
- metadata.gz: 398e2a9136851a66f7436909d14977aa6983c6ea6f4fbcf554c39bffdd918cb544fdfb09a26557e97e5cf0001935618375b3f6d4a7c9d561ca8f78c77b406e17
7
- data.tar.gz: 4e1ff97230966d61692d0f5ab334cb125914664f73c391eb554f909d8a34da22d30ea3b753d1bcc04f64190157b62ef9cb5fa0abdb5221eb6596f01b7d8bea57
6
+ metadata.gz: 58ba16e72dc2d6e2211999a89948490721f4ee23d7fc9781f913395bb2a44e80a21605ad0b8f7cb0c8be92d528ecf1fe0f46318a93935bfe23d67438904f2a3f
7
+ data.tar.gz: adf6f4cedaf7fc8b7c58179eb4e57a3b98a85cdc4269111b69411fcac45a0a9844d81cc4273ffff95e0b801cc035b9a6ea98fcb1e0a5c7862290636000b5d692
@@ -0,0 +1,74 @@
1
+ require 'time'
2
+
3
+ module MiniI18n
4
+ module Localization
5
+ extend self
6
+
7
+ DELIMITER_REGEX = /\d(?=(\d{3})+(?!\d))/
8
+ DAYS_MONTHS_REGEX = /%[aAbB]/
9
+
10
+ def localize(object, options = {})
11
+ case object
12
+ when Numeric
13
+ localize_number(object, options)
14
+ when Date
15
+ localize_datetime(object, options.merge(type: :date))
16
+ when Time, DateTime
17
+ localize_datetime(object, options.merge(type: :time))
18
+ when String
19
+ localize_string(object, options)
20
+ end
21
+ end
22
+ alias l localize
23
+
24
+ private
25
+
26
+ def localize_number(number, options)
27
+ locale = options[:locale]
28
+ delimiter = MiniI18n.t("number.format.delimiter", locale: locale)
29
+ separator = MiniI18n.t("number.format.separator", locale: locale)
30
+ integer, fractional = number.to_s.split(separator)
31
+
32
+ integer.to_s.gsub!(DELIMITER_REGEX) do |match|
33
+ "#{match}#{delimiter}"
34
+ end
35
+
36
+ number = [integer, fractional].compact.join(separator)
37
+
38
+ if as = options[:as]
39
+ number = MiniI18n.t("number.as.#{as}", number: number, locale: locale)
40
+ end
41
+
42
+ number
43
+ end
44
+
45
+ def localize_datetime(object, options)
46
+ locale = options[:locale]
47
+ type = options[:type]
48
+ format = MiniI18n.t("#{type}.formats.#{options[:format] || 'default'}", locale: locale)
49
+
50
+ format.gsub!(DAYS_MONTHS_REGEX) do |match|
51
+ {
52
+ '%a' => MiniI18n.t('date.abbr_day_names', locale: locale)[object.wday],
53
+ '%A' => MiniI18n.t('date.day_names', locale: locale)[object.wday],
54
+ '%b' => MiniI18n.t('date.abbr_month_names', locale: locale)[object.month - 1],
55
+ '%B' => MiniI18n.t('date.month_names', locale: locale)[object.month - 1]
56
+ }[match]
57
+ end
58
+
59
+ object.strftime(format)
60
+ end
61
+
62
+ def localize_string(string, options)
63
+ object = if options[:type] == :number || options[:as]
64
+ string.to_f
65
+ elsif options[:type] == :date
66
+ Date.parse(string) rescue nil
67
+ else
68
+ Time.parse(string) rescue nil
69
+ end
70
+
71
+ object && localize(object, options)
72
+ end
73
+ end
74
+ end
@@ -8,10 +8,6 @@ module MiniI18n
8
8
  string
9
9
  end
10
10
 
11
- def replace_with(array, old_elem, new_elem)
12
- array.map { |elem| elem == old_elem ? new_elem : elem }
13
- end
14
-
15
11
  def deep_merge(merge_to, merge_from)
16
12
  merged = merge_to.clone
17
13
 
@@ -1,3 +1,3 @@
1
1
  module MiniI18n
2
- VERSION = "0.4.0"
2
+ VERSION = "0.5.0"
3
3
  end
data/lib/mini_i18n.rb CHANGED
@@ -1,9 +1,12 @@
1
1
  require "yaml"
2
2
  require "mini_i18n/version"
3
3
  require "mini_i18n/utils"
4
+ require "mini_i18n/localization"
4
5
 
5
6
  module MiniI18n
6
7
  class << self
8
+ include Localization
9
+
7
10
  DEFAULT_LOCALE = :en
8
11
  SEPARATOR = '.'
9
12
 
@@ -48,14 +51,7 @@ module MiniI18n
48
51
  def load_translations(path)
49
52
  Dir[path.to_s].each do |file|
50
53
  YAML.load_file(file).each do |locale, new_translations|
51
- locale = locale.to_s
52
- @@available_locales << locale unless available_locale?(locale)
53
-
54
- if translations[locale]
55
- translations[locale] = Utils.deep_merge(translations[locale], new_translations)
56
- else
57
- translations[locale] = new_translations
58
- end
54
+ add_translations(locale.to_s, new_translations)
59
55
  end
60
56
  end
61
57
  end
@@ -65,7 +61,6 @@ module MiniI18n
65
61
 
66
62
  _locale = available_locale?(options[:locale]) || locale
67
63
  scope = options[:scope]
68
- count = options[:count]
69
64
 
70
65
  keys = [_locale.to_s]
71
66
  keys << scope.to_s.split(SEPARATOR) if scope
@@ -74,25 +69,9 @@ module MiniI18n
74
69
 
75
70
  result = lookup(*keys)
76
71
 
77
- if fallbacks && result.empty?
78
- keys = Utils.replace_with(keys, _locale, default_locale.to_s)
79
- result = lookup(*keys)
80
- end
81
-
82
- if count && result.is_a?(Hash)
83
- case count
84
- when 0
85
- result = result["zero"]
86
- when 1
87
- result = result["one"]
88
- else
89
- result = result["many"]
90
- end
91
- end
92
-
93
- if result.respond_to?(:match) && result.match(/%{\w+}/)
94
- result = Utils.interpolate(result, options)
95
- end
72
+ result = with_fallbacks(result, keys)
73
+ result = with_pluralization(result, options)
74
+ result = with_interpolation(result, options)
96
75
 
97
76
  result || options[:default]
98
77
  end
@@ -116,5 +95,49 @@ module MiniI18n
116
95
  def lookup(*keys)
117
96
  translations.dig(*keys)
118
97
  end
98
+
99
+ def add_translations(locale, new_translations)
100
+ @@available_locales << locale unless available_locale?(locale)
101
+
102
+ if translations[locale]
103
+ translations[locale] = Utils.deep_merge(translations[locale], new_translations)
104
+ else
105
+ translations[locale] = new_translations
106
+ end
107
+ end
108
+
109
+ def with_fallbacks(result, keys)
110
+ if fallbacks && result.empty?
111
+ keys[0] = default_locale.to_s
112
+ result = lookup(*keys)
113
+ end
114
+
115
+ result
116
+ end
117
+
118
+ def with_pluralization(result, options)
119
+ count = options[:count]
120
+
121
+ if count && result.is_a?(Hash)
122
+ case count
123
+ when 0
124
+ result = result["zero"]
125
+ when 1
126
+ result = result["one"]
127
+ else
128
+ result = result["many"]
129
+ end
130
+ end
131
+
132
+ result
133
+ end
134
+
135
+ def with_interpolation(result, options)
136
+ if result.respond_to?(:match) && result.match(/%{\w+}/)
137
+ result = Utils.interpolate(result, options)
138
+ end
139
+
140
+ result
141
+ end
119
142
  end
120
143
  end
@@ -0,0 +1,20 @@
1
+ en:
2
+ date:
3
+ formats:
4
+ default: "%A %d, %B, %Y"
5
+ short: "%d %b %y"
6
+ day_names: [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday]
7
+ abbr_day_names: [Sun, Mon, Tue, Wed, Thu, Fri, Sat]
8
+ month_names: [January, February, March, April, May, June, July, August, September, October, November, December]
9
+ abbr_month_names: [Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec]
10
+ time:
11
+ formats:
12
+ default: "%a %d, %B, %Y - %H:%M"
13
+ short: "%d %b %y - %H:%M"
14
+ number:
15
+ format:
16
+ delimiter: ','
17
+ separator: '.'
18
+ as:
19
+ currency: '%{number} $'
20
+ distance: 'Distance: %{number} miles'
@@ -10,6 +10,9 @@ es:
10
10
  bye: "adiós"
11
11
  second_level:
12
12
  hello: "hola 2"
13
+ number:
14
+ as:
15
+ currency: '%{number} €'
13
16
 
14
17
  fr:
15
18
  hello: "bonjour"
@@ -0,0 +1,49 @@
1
+ RSpec.describe MiniI18n::Localization do
2
+ let(:time) { Time.new(2018, 8, 7, 22, 30) }
3
+
4
+ describe 'date' do
5
+ it 'accepts different formats' do
6
+ date = time.to_date
7
+ expect(MiniI18n.l(date)).to eq 'Tuesday 07, August, 2018'
8
+ expect(MiniI18n.l(date, format: :short)).to eq '07 Aug 18'
9
+ end
10
+ end
11
+
12
+ describe 'time' do
13
+ it 'accepts different formats' do
14
+ expect(MiniI18n.l(time)).to eq 'Tue 07, August, 2018 - 22:30'
15
+ expect(MiniI18n.l(time, format: :short)).to eq '07 Aug 18 - 22:30'
16
+ end
17
+ end
18
+
19
+ describe 'string' do
20
+ it 'accepts and defaults to time' do
21
+ time_string = time.to_s
22
+ expect(MiniI18n.l(time_string)).to eq 'Tue 07, August, 2018 - 22:30'
23
+ expect(MiniI18n.l(time_string, type: :time)).to eq 'Tue 07, August, 2018 - 22:30'
24
+ end
25
+
26
+ it 'to date' do
27
+ date_string = time.to_date.to_s
28
+ expect(MiniI18n.l(date_string, type: :date, format: :short)).to eq '07 Aug 18'
29
+ end
30
+
31
+ it 'to number' do
32
+ expect(MiniI18n.l("1000000", type: :number)).to eq '1,000,000.0'
33
+ expect(MiniI18n.l("1000000", as: :currency)).to eq '1,000,000.0 $'
34
+ end
35
+ end
36
+
37
+ describe 'number' do
38
+ it 'uses defined format' do
39
+ expect(MiniI18n.l(9000)).to eq '9,000'
40
+ expect(MiniI18n.l(9000.50)).to eq '9,000.5'
41
+ end
42
+
43
+ it 'as' do
44
+ expect(MiniI18n.l(9000, as: :currency)).to eq '9,000 $'
45
+ expect(MiniI18n.l(9000, as: :currency, locale: :es)).to eq '9000 €'
46
+ expect(MiniI18n.l(125.5, as: :distance)).to eq 'Distance: 125.5 miles'
47
+ end
48
+ end
49
+ end
@@ -1,14 +1,4 @@
1
1
  RSpec.describe MiniI18n do
2
- before(:all) do
3
- MiniI18n.load_translations File.expand_path(__dir__ + '/fixtures/locales/*')
4
- end
5
-
6
- before(:each) do
7
- MiniI18n.locale = :en
8
- MiniI18n.fallbacks = false
9
- MiniI18n.available_locales = [:en, :es, :fr]
10
- end
11
-
12
2
  describe 'load_translations' do
13
3
  it "allows to load multiple locales and translations from different files" do
14
4
  expect(MiniI18n.available_locales).to eq ["en", "es", "fr"]
@@ -89,7 +79,7 @@ RSpec.describe MiniI18n do
89
79
  it "pluralization" do
90
80
  expect(MiniI18n.t('notifications', count: 0)).to eq 'no unread notifications'
91
81
  expect(MiniI18n.t('notifications', count: 1)).to eq '1 unread notification'
92
- expect(MiniI18n.t('notifications', count: 2)).to eq '2 unread notifications'
82
+ expect(MiniI18n.t('notifications', count: 5)).to eq '5 unread notifications'
93
83
  end
94
84
  end
95
85
  end
data/spec/spec_helper.rb CHANGED
@@ -3,4 +3,14 @@ require "mini_i18n"
3
3
  RSpec.configure do |config|
4
4
  config.order = :rand
5
5
  config.disable_monkey_patching!
6
+
7
+ config.before(:suite) do
8
+ MiniI18n.load_translations File.expand_path(__dir__ + '/fixtures/locales/*')
9
+ end
10
+
11
+ config.before(:each) do
12
+ MiniI18n.locale = :en
13
+ MiniI18n.fallbacks = false
14
+ MiniI18n.available_locales = [:en, :es, :fr]
15
+ end
6
16
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mini_i18n
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - markets
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-07-30 00:00:00.000000000 Z
11
+ date: 2018-08-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -66,7 +66,8 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
- description:
69
+ description: Minimalistic I18n library for Ruby. It supports localization, pluralization,
70
+ interpolations, fallbacks, nested keys and more.
70
71
  email:
71
72
  - srmarc.ai@gmail.com
72
73
  executables: []
@@ -74,10 +75,13 @@ extensions: []
74
75
  extra_rdoc_files: []
75
76
  files:
76
77
  - lib/mini_i18n.rb
78
+ - lib/mini_i18n/localization.rb
77
79
  - lib/mini_i18n/utils.rb
78
80
  - lib/mini_i18n/version.rb
79
81
  - spec/fixtures/locales/en.yml
82
+ - spec/fixtures/locales/localization.yml
80
83
  - spec/fixtures/locales/multiple.yml
84
+ - spec/localization_spec.rb
81
85
  - spec/mini_i18n_spec.rb
82
86
  - spec/spec_helper.rb
83
87
  homepage: https://github.com/markets/mini_i18n
@@ -106,6 +110,8 @@ specification_version: 4
106
110
  summary: Minimalistic I18n library for Ruby
107
111
  test_files:
108
112
  - spec/fixtures/locales/en.yml
113
+ - spec/fixtures/locales/localization.yml
109
114
  - spec/fixtures/locales/multiple.yml
115
+ - spec/localization_spec.rb
110
116
  - spec/mini_i18n_spec.rb
111
117
  - spec/spec_helper.rb