mini_i18n 0.4.0 → 0.5.0

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