awesome_translations 0.0.16 → 0.0.17

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/awesome_translations/groups_controller.rb +8 -3
  3. data/app/models/awesome_translations/translated_value.rb +32 -1
  4. data/app/models/awesome_translations/translation.rb +45 -6
  5. data/app/views/awesome_translations/groups/show.html.haml +6 -3
  6. data/lib/awesome_translations/handlers/rails_handler.rb +208 -0
  7. data/lib/awesome_translations/version.rb +1 -1
  8. data/spec/controllers/groups_controller_spec.rb +23 -0
  9. data/spec/dummy/config/locales/awesome_translations/date_time/da.yml +9 -0
  10. data/spec/dummy/config/locales/awesome_translations/date_time/de.yml +6 -0
  11. data/spec/dummy/config/locales/awesome_translations/date_time/en.yml +62 -0
  12. data/spec/dummy/config/locales/awesome_translations/number/da.yml +16 -0
  13. data/spec/dummy/config/locales/awesome_translations/number/de.yml +16 -0
  14. data/spec/dummy/config/locales/awesome_translations/number/en.yml +16 -0
  15. data/spec/dummy/log/development.log +1505 -0
  16. data/spec/dummy/log/test.log +881 -0
  17. data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/2p155H920Y76tD9Gj4HuvSeyKPX48gW2EeT0uJ-qDC4.cache +0 -0
  18. data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/5HoGxXKxoOX3AIQe7mpvJ8HkWoGDGVITn12A-AS39bI.cache +1 -0
  19. data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/6AKSuLQ7-rmru8z6X93bpAnu7f-pBhVaPqrLnlZEEr4.cache +0 -0
  20. data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/6ISWS0E-NUDxPhl5eE0vGMmOPleI0-CevJF8RF2OPYU.cache +0 -0
  21. data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/AdM4bSpxF-V3SVialcxcS5JaSV3t0miIFEegjuwBWlA.cache +0 -0
  22. data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/GDzC1chWWGmhgF3fUvOghjlCyrUvZCCVC_YH1oldtsM.cache +0 -0
  23. data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/LtuKwRcTWtNm0-9U116mcMNSEOapgDhyZaj926hhVPs.cache +0 -0
  24. data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/MzYsi2S393224patsQC_5aJpDwq4F97WspZCPEXC2Q0.cache +0 -0
  25. data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/WyLdqMqQlKkaN4Q-7OsT-01hYlq3cmhy19iZV5OI8rs.cache +1 -0
  26. data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/YeUs3vJiPOiW0ze9DAFqEBU8WdoE6CPE1vE4Q_rumCk.cache +0 -0
  27. data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/a8zRTXmGI4EOik4D8x6S1OJGcr3oKvUM9jNHim0xGio.cache +1 -0
  28. data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/diUCwnrnAqP09ITWwzJqFv3pdkHx0DNdSAfRVgCl-Ho.cache +1 -0
  29. data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/eNBcyVIS4PNh9lfbPupF-BdIC0evfo6BlGMHxcwCYtU.cache +0 -0
  30. data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/hw8AiVkuV0Jb1MqnlKOmPV7OzCf0ggO2-FpwNNDX7rA.cache +0 -0
  31. data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/js_-GbuvJQ4VGhFUV6QutWkBN2J467qAxjx2Yf91Eak.cache +0 -0
  32. data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/kYXemjpBFknH9kzOhifClhhOaHlRaYc04eAnYvnO3VA.cache +1 -0
  33. data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/s7x5_coI4aGfED9cLsTL7o8vGLSX2oA61zI9K50O2a4.cache +0 -0
  34. data/spec/dummy/tmp/cache/assets/development/sprockets/v3.0/x38Hslo9uhZ5JJmEG-emEJE12q4Kdd3OdHw6je6KEjw.cache +1 -0
  35. data/spec/dummy/tmp/pids/server.pid +1 -0
  36. data/spec/models/awesome_translations/translated_value_spec.rb +4 -4
  37. data/spec/models/awesome_translations/translation_spec.rb +49 -0
  38. metadata +43 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a2b2ed6fcd8e5b42d71a00434b0565986624523a
4
- data.tar.gz: 85bc149c65a980f40ec128b98b611fe508d3076f
3
+ metadata.gz: 4fea063f52c4b5c59c136414a116a24b4735db9f
4
+ data.tar.gz: 7464db6a00df91622aec0160dc371e5bd1c99f6d
5
5
  SHA512:
6
- metadata.gz: 18ffa5b938502e75a4782e700616520b5dcc91f6860c7faa2bf42c23e7a006f5b00fc0ee5f8ceb92eb563649bda52350dc3ab673d21fd097b57b1ee9fe33ebda
7
- data.tar.gz: 7e8e8191fd6222c66ef7ec2d9afcd4d42ee35d122cf2e75ffc270ab3cdf3f6d94027416cc433ac6b3030d2bcddf116bab4374a805c4ba0f2d1935827c6baf6df
6
+ metadata.gz: a438f09fd630e7ca156f4a9311df7479f53f5d9d3af84b90cd4b95b8bd2b4df4c7556c8a366b8d83d803f1959a29831e64753264e7d1b29e805010e443e49112
7
+ data.tar.gz: 3d0d0a750867502382977adaf99950ee5d5524ab9f9037604dc617e33ddc477dbcf71bd0c16ee3605f5d36e54d71e0c7316a66105b97bf8cd4ac05e6701bb625
@@ -11,9 +11,15 @@ class AwesomeTranslations::GroupsController < AwesomeTranslations::ApplicationCo
11
11
 
12
12
  def update
13
13
  @group.translations.each do |translation|
14
- next unless params[:t].key?(translation.key)
14
+ if translation.array_translation?
15
+ next unless params[:t].key?(translation.array_key)
16
+ values = params[:t][translation.array_key][translation.array_no.to_s]
17
+ next unless values
18
+ else
19
+ next unless params[:t].key?(translation.key)
20
+ values = params[:t][translation.key]
21
+ end
15
22
 
16
- values = params[:t][translation.key]
17
23
  values.each do |locale, value|
18
24
  translated_value = translation.translated_value_for_locale(locale)
19
25
  translated_value.value = value
@@ -22,7 +28,6 @@ class AwesomeTranslations::GroupsController < AwesomeTranslations::ApplicationCo
22
28
  end
23
29
 
24
30
  I18n.backend.reload!
25
-
26
31
  redirect_to handler_group_path(@handler, @group)
27
32
  end
28
33
 
@@ -11,6 +11,30 @@ class AwesomeTranslations::TranslatedValue
11
11
  "<AwesomeTranslations::TranslatedValue file=\"#{@file}\" locale=\"#{@locale}\" key=\"#{@key}\" value=\"#{@value}\">"
12
12
  end
13
13
 
14
+ def array_translation?
15
+ if @key.match(/\[(\d+)\]\Z/)
16
+ return true
17
+ else
18
+ return false
19
+ end
20
+ end
21
+
22
+ def array_key
23
+ if match = @key.match(/\A(.+)\[(\d+)\]\Z/)
24
+ return match[1]
25
+ end
26
+
27
+ return nil
28
+ end
29
+
30
+ def array_no
31
+ if match = @key.match(/\A(.+)\[(\d+)\]\Z/)
32
+ return match[2].to_i
33
+ end
34
+
35
+ return nil
36
+ end
37
+
14
38
  alias inspect to_s
15
39
 
16
40
  def save!
@@ -33,7 +57,14 @@ class AwesomeTranslations::TranslatedValue
33
57
  if @value.empty?
34
58
  current.delete(key_part)
35
59
  else
36
- current[key_part] = value
60
+ if array_translation?
61
+ match = key_part.match(/\A(.+)\[(\d+)\]\Z/)
62
+ current_array = current[match[1]] || []
63
+ current_array[array_no] = value
64
+ current[match[1]] = current_array
65
+ else
66
+ current[key_part] = value
67
+ end
37
68
  end
38
69
  else
39
70
  current[key_part] ||= {}
@@ -1,15 +1,45 @@
1
1
  class AwesomeTranslations::Translation
2
- attr_reader :dir, :key, :file_path, :line_no
2
+ attr_reader :default, :dir, :key, :file_path, :line_no
3
3
 
4
4
  def initialize(data)
5
5
  @data = data
6
- @dir, @key, @file_path, @full_path, @line_no = data[:dir], data[:key], data[:file_path], data[:full_path], data[:line_no]
6
+ @dir, @file_path, @full_path, @line_no = data[:dir], data[:file_path], data[:full_path], data[:line_no]
7
+ @key, @key_show = data[:key], data[:key_show]
8
+ @default = data[:default]
7
9
 
8
10
  raise "Dir wasn't valid: '#{@dir}'." unless @dir.present?
9
11
  end
10
12
 
11
13
  def last_key
12
- key.to_s.split(".").last
14
+ key.to_s.split('.').last
15
+ end
16
+
17
+ def key_show_with_fallback
18
+ @key_show.presence || last_key
19
+ end
20
+
21
+ def array_translation?
22
+ if @key.match(/\[(\d+)\]\Z/)
23
+ return true
24
+ else
25
+ return false
26
+ end
27
+ end
28
+
29
+ def array_key
30
+ if match = @key.match(/\A(.+)\[(\d+)\]\Z/)
31
+ return match[1]
32
+ end
33
+
34
+ return nil
35
+ end
36
+
37
+ def array_no
38
+ if match = @key.match(/\A(.+)\[(\d+)\]\Z/)
39
+ return match[2].to_i
40
+ end
41
+
42
+ return nil
13
43
  end
14
44
 
15
45
  def id
@@ -64,14 +94,23 @@ class AwesomeTranslations::Translation
64
94
  end
65
95
 
66
96
  def value_for?(locale)
67
- I18n.with_locale(locale) { return I18n.exists?(@key) }
97
+ if array_translation?
98
+ I18n.with_locale(locale) { return I18n.exists?(array_key) && I18n.t(array_key)[array_no].present? }
99
+ else
100
+ I18n.with_locale(locale) { return I18n.exists?(@key) }
101
+ end
68
102
  end
69
103
 
70
104
  def value(args = {})
71
105
  locale = (args[:locale] || I18n.locale || I18n.default_locale).to_sym
72
106
 
73
107
  return nil unless value_for?(locale)
74
- I18n.with_locale(locale) { return I18n.t(@key) }
108
+
109
+ if array_translation?
110
+ I18n.with_locale(locale) { return I18n.t(array_key)[array_no] }
111
+ else
112
+ I18n.with_locale(locale) { return I18n.t(@key) }
113
+ end
75
114
  end
76
115
 
77
116
  def file_line_content?
@@ -96,7 +135,7 @@ class AwesomeTranslations::Translation
96
135
  end
97
136
 
98
137
  def to_s
99
- "<AwesomeTranslations::Translation key=\"#{@key}\" dir=\"#{@dir}\">"
138
+ "<AwesomeTranslations::Translation key=\"#{@key}\" dir=\"#{@dir}\" array_translation?=\"#{array_translation?}\" array_key=\"#{array_key}\" array_no=\"#{array_no}\">"
100
139
  end
101
140
 
102
141
  def inspect
@@ -10,16 +10,19 @@
10
10
  - @translations.each do |translation|
11
11
  %tr
12
12
  %td.translation-key
13
- .translation-key-text= translation.last_key
13
+ .translation-key-text= translation.key_show_with_fallback
14
14
 
15
15
  - I18n.available_locales.each do |locale|
16
16
  %td.translation= text_field "t", "#{translation.key}[#{locale}]", class: "translation-input", lang: locale, value: translation.value(locale: locale)
17
17
 
18
- - if translation.file_line_content?
18
+ - if translation.file_line_content? || translation.default.present?
19
19
  %tr.line-content-row
20
20
  %td.line-content{colspan: 1 + I18n.available_locales.length}
21
21
  .container
22
- %pre= translation.file_line_content
22
+ - if translation.file_line_content?
23
+ %pre= translation.file_line_content
24
+ - elsif translation.default.present?
25
+ = "Default: #{translation.default}"
23
26
  %tr
24
27
  %td.line-spacer{colspan: 1 + I18n.available_locales.length}
25
28
  - if @translations.empty?
@@ -0,0 +1,208 @@
1
+ class AwesomeTranslations::Handlers::RailsHandler < AwesomeTranslations::Handlers::BaseHandler
2
+ def groups
3
+ ArrayEnumerator.new do |yielder|
4
+ groups = ['date_time', 'errors', 'helpers', 'numbers', 'support']
5
+
6
+ groups.each do |group|
7
+ yielder << AwesomeTranslations::Group.new(
8
+ id: group,
9
+ handler: self,
10
+ data: {
11
+ name: group.humanize
12
+ }
13
+ )
14
+ end
15
+ end
16
+ end
17
+
18
+ def translations_for_group(group)
19
+ ArrayEnumerator.new do |yielder|
20
+ dir = Rails.root.join('config', 'locales', 'awesome_translations', group.id).to_s
21
+ __send__("translations_for_#{group.id}", dir, group, yielder)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def translations_for_errors(dir, group, yielder)
28
+ add_translations_for_hash(dir, group, yielder, translations: {
29
+ errors: {
30
+ format: '%{attribute} %{message}',
31
+ messages: {
32
+ accepted: 'must be accepted',
33
+ blank: "can't be blank",
34
+ confirmation: "doesn't match %{attribute}",
35
+ empty: "can't be empty",
36
+ equal_to: 'must be equal to %{count}',
37
+ even: 'must be even',
38
+ exclusion: 'is reserved',
39
+ greater_than: 'must be greater than %{count}',
40
+ greater_than_or_equal_to: 'must be greater than or equal to %{count}',
41
+ inclusion: 'is not included in the list',
42
+ invalid: 'is invalid',
43
+ less_than: 'must be less than %{count}',
44
+ less_than_or_equal_to: 'must be less than or equal to %{count}',
45
+ not_a_number: 'is not a number',
46
+ not_an_integer: 'must be an integer',
47
+ odd: 'must be odd',
48
+ record_invalid: 'Validation failed: %{errors}',
49
+ taken: 'has already been taken',
50
+ too_long: {
51
+ one: 'is too long (maximum is 1 character)',
52
+ other: 'is too long (maximum is %{count} characters)'
53
+ },
54
+ too_short: {
55
+ one: 'is too short (minimum is 1 character)',
56
+ other: 'is too short (minimum is %{count} characters)'
57
+ },
58
+ wrong_length: {
59
+ one: 'is the wrong length (should be 1 character)',
60
+ other: 'is the wrong length (should be %{count} characters)'
61
+ }
62
+ },
63
+ template: {
64
+ body: 'There were problems with the following fields:',
65
+ header: {
66
+ one: '1 error prohibited this %{model} from being saved',
67
+ other: "%{count} errors prohibited this %{model} from being saved"
68
+ }
69
+ }
70
+ }
71
+ })
72
+ end
73
+
74
+ def translations_for_date_time(dir, group, yielder)
75
+ add_translations_for_hash(dir, group, yielder, translations: {
76
+ date: {
77
+ formats: {
78
+ default: "%Y-%m-%d",
79
+ short: "%b %d",
80
+ long: "%B %d, %Y"
81
+ },
82
+ day_names: [0, 1, 2, 3, 4, 5, 6],
83
+ abbr_day_names: [0, 1, 2, 3, 4, 5, 6],
84
+ month_names: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
85
+ abbr_month_names: [0 , 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12],
86
+ order: [0, 1, 2]
87
+ },
88
+ time: {
89
+ formats: {
90
+ default: "%a, %d %b %Y %H:%M:%S %z",
91
+ short: "%d %b %H:%M",
92
+ long: "%B %d, %Y %H:%M"
93
+ },
94
+ am: "am",
95
+ pm: "pm"
96
+ }
97
+ })
98
+ end
99
+
100
+ def translations_for_helpers(dir, group, yielder)
101
+ add_translations_for_hash(dir, group, yielder, translations: {
102
+ helpers: {
103
+ select: {
104
+ prompt: 'Please select'
105
+ },
106
+ submit: {
107
+ create: 'Create %{model}',
108
+ submit: 'Save %{model}',
109
+ update: 'Update %{model}'
110
+ }
111
+ }
112
+ })
113
+ end
114
+
115
+ def translations_for_support(dir, group, yielder)
116
+ add_translations_for_hash(dir, group, yielder, translations: {
117
+ array: {
118
+ last_word_connector: ' and ',
119
+ two_words_connector: ' and ',
120
+ word_connector: ', '
121
+ }
122
+ })
123
+ end
124
+
125
+ def translations_for_numbers(dir, group, yielder)
126
+ add_translations_for_hash(dir, group, yielder, translations: {
127
+ number: {
128
+ currency: {
129
+ format: {
130
+ delimiter: ",",
131
+ format: "%n %u",
132
+ separator: ".",
133
+ unit: "$"
134
+ }
135
+ },
136
+ format: {
137
+ delimiter: ",",
138
+ separator: "."
139
+ },
140
+ human: {
141
+ decimal_units: {
142
+ format: "%n %u",
143
+ units: {
144
+ billion: "Billion",
145
+ million: "Million",
146
+ quadrillion: "Quadrillion",
147
+ thousand: "Thousand",
148
+ trillion: "Trillion",
149
+ unit: ""
150
+ }
151
+ },
152
+ format: {
153
+ delimiter: ""
154
+ },
155
+ storage_units: {
156
+ format: "%n %u",
157
+ units: {
158
+ byte: {
159
+ one: "Byte",
160
+ other: "Bytes"
161
+ },
162
+ gb: "GB",
163
+ kb: "KB",
164
+ mb: "MB",
165
+ tb: "TB"
166
+ }
167
+ }
168
+ },
169
+ percentage: {
170
+ format: {
171
+ delimiter: ""
172
+ }
173
+ }
174
+ }
175
+ })
176
+ end
177
+
178
+ def add_translations_for_hash(dir, group, yielder, hash)
179
+ translations_for_hash_recursive(dir, hash[:translations], yielder, [])
180
+ end
181
+
182
+ def translations_for_hash_recursive(dir, hash, yielder, current_keys)
183
+ hash.each do |key, value|
184
+ current_keys << key
185
+
186
+ if value.is_a?(Hash)
187
+ translations_for_hash_recursive(dir, value, yielder, current_keys)
188
+ elsif value.is_a?(Array)
189
+ value.each_index do |index|
190
+ yielder << AwesomeTranslations::Translation.new(
191
+ dir: dir,
192
+ key: "#{current_keys.join('.')}[#{index}]",
193
+ key_show: "#{current_keys.join('.')}[#{index}]"
194
+ )
195
+ end
196
+ else
197
+ yielder << AwesomeTranslations::Translation.new(
198
+ dir: dir,
199
+ key: current_keys.join('.'),
200
+ key_show: current_keys.join('.'),
201
+ default: value
202
+ )
203
+ end
204
+
205
+ current_keys.pop
206
+ end
207
+ end
208
+ end
@@ -1,3 +1,3 @@
1
1
  module AwesomeTranslations
2
- VERSION = '0.0.16'
2
+ VERSION = '0.0.17'
3
3
  end
@@ -4,9 +4,14 @@ describe AwesomeTranslations::GroupsController do
4
4
  let(:model_locales_path) { "#{Rails.root}/config/locales/awesome_translations/models" }
5
5
  let(:user_yml_path) { "#{model_locales_path}/user/da.yml" }
6
6
  let(:role_yml_path) { "#{model_locales_path}/role/da.yml" }
7
+ let(:date_time_path) { Rails.root.join('config', 'locales', 'awesome_translations', 'date_time', 'da.yml') }
7
8
 
8
9
  before do
9
10
  FileUtils.rm_f(model_locales_path) if File.exist?(model_locales_path)
11
+ FileUtils.rm_f(date_time_path) if File.exists?(date_time_path)
12
+
13
+ I18n.load_path.delete(date_time_path.to_s)
14
+ I18n.load_path.delete(model_locales_path)
10
15
  end
11
16
 
12
17
  render_views
@@ -30,5 +35,23 @@ describe AwesomeTranslations::GroupsController do
30
35
 
31
36
  I18n.load_path.should include role_yml_path
32
37
  end
38
+
39
+ it 'handles array translations' do
40
+ put :update, handler_id: 'rails_handler', id: 'date_time', use_route: 'awesome_translations', t: {
41
+ 'date.day_names' => {
42
+ '1' => {
43
+ 'da' => 'Mandag'
44
+ },
45
+ '4' => {
46
+ 'da' => 'Torsdag'
47
+ }
48
+ }
49
+ }
50
+
51
+ translations = YAML.load_file(date_time_path)
52
+
53
+ expect(translations['da']['date']['day_names'][1]).to eq 'Mandag'
54
+ expect(translations['da']['date']['day_names'][4]).to eq 'Torsdag'
55
+ end
33
56
  end
34
57
  end
@@ -0,0 +1,9 @@
1
+ ---
2
+ da:
3
+ date:
4
+ day_names:
5
+ -
6
+ - Mandag
7
+ -
8
+ -
9
+ - Torsdag