tolk 1.2.0 → 2.0.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.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/app/assets/javascripts/tolk/actions.js +30 -0
  3. data/app/assets/javascripts/tolk/application.js +3 -4
  4. data/app/assets/javascripts/tolk/interpolations.js +21 -0
  5. data/app/assets/javascripts/tolk/jquery-1.9.1.min.js +5 -0
  6. data/app/assets/javascripts/tolk/layout.js +17 -0
  7. data/app/assets/javascripts/tolk/libraries.js +1 -0
  8. data/app/assets/stylesheets/tolk/application.css +4 -2
  9. data/app/assets/stylesheets/tolk/screen.css +104 -38
  10. data/app/controllers/tolk/application_controller.rb +5 -4
  11. data/app/controllers/tolk/locales_controller.rb +51 -12
  12. data/app/controllers/tolk/searches_controller.rb +3 -3
  13. data/app/helpers/tolk/application_helper.rb +22 -6
  14. data/app/models/tolk/locale.rb +96 -95
  15. data/app/models/tolk/phrase.rb +4 -5
  16. data/app/models/tolk/translation.rb +53 -11
  17. data/app/views/layouts/tolk/application.html.erb +6 -10
  18. data/app/views/tolk/locales/all.html.erb +14 -9
  19. data/app/views/tolk/locales/index.html.erb +1 -4
  20. data/app/views/tolk/locales/show.html.erb +14 -9
  21. data/app/views/tolk/searches/_form.html.erb +2 -2
  22. data/app/views/tolk/searches/show.html.erb +15 -10
  23. data/config/initializers/will_paginate.rb +18 -0
  24. data/config/routes.rb +4 -0
  25. data/lib/generators/tolk/install_generator.rb +44 -0
  26. data/lib/generators/tolk/templates/initializer.erb +412 -0
  27. data/lib/generators/{tolk_migration/templates/migrate/create_tolk_tables.rb → tolk/templates/migration.rb} +0 -0
  28. data/lib/generators/tolk/utils.rb +35 -0
  29. data/lib/tasks/tolk_tasks.rake +14 -2
  30. data/lib/tolk.rb +13 -2
  31. data/lib/tolk/config.rb +87 -0
  32. data/lib/tolk/engine.rb +18 -0
  33. data/lib/tolk/export.rb +27 -0
  34. data/lib/tolk/import.rb +23 -5
  35. data/lib/tolk/pagination.rb +28 -0
  36. data/lib/tolk/sync.rb +25 -9
  37. data/lib/tolk/version.rb +2 -2
  38. data/lib/tolk/yaml.rb +29 -0
  39. metadata +113 -40
  40. data/app/assets/javascripts/tolk/controls.js +0 -963
  41. data/app/assets/javascripts/tolk/dragdrop.js +0 -972
  42. data/app/assets/javascripts/tolk/effects.js +0 -1120
  43. data/app/assets/javascripts/tolk/prototype.js +0 -4221
  44. data/init.rb +0 -8
  45. data/lib/generators/tolk_migration/tolk_migration_generator.rb +0 -19
@@ -1,15 +1,15 @@
1
1
  module Tolk
2
2
  class SearchesController < Tolk::ApplicationController
3
- before_filter :find_locale
3
+ before_action :find_locale
4
4
 
5
5
  def show
6
- @phrases = @locale.search_phrases(params[:q], params[:scope].to_sym, params[:k], params[:page])
6
+ @phrases = @locale.search_phrases(params[:q], params[:scope].to_sym, params[:k], params[pagination_param])
7
7
  end
8
8
 
9
9
  private
10
10
 
11
11
  def find_locale
12
- @locale = Tolk::Locale.find_by_name!(params[:locale])
12
+ @locale = Tolk::Locale.where('UPPER(name) = UPPER(?)', params[:tolk_locale]).first!
13
13
  end
14
14
  end
15
15
  end
@@ -1,27 +1,43 @@
1
1
  module Tolk
2
2
  module ApplicationHelper
3
+ include Tolk::Pagination::ViewHelper
4
+
3
5
  def format_i18n_value(value)
4
- h(yaml_value(value)).gsub(/\n/, '<br />')
6
+ value = h(yaml_value(value))
7
+ value = highlight_linebreaks(value)
8
+ value = highligh_interpolations(value)
9
+ end
10
+
11
+ def highlight_linebreaks(value)
12
+ value.gsub(/\n/, '<span class="carriage_return" title="Line break"><br /></span>').html_safe
13
+ end
14
+
15
+ def highligh_interpolations(value)
16
+ value.gsub(/%{\w+}/, '<span class="interpolation" title="Leave this word untranslated">\0</span>').html_safe
5
17
  end
6
18
 
7
19
  def format_i18n_text_area_value(value)
8
- yaml_value(value)
20
+ yaml_value(value).to_s.force_encoding("UTF-8")
9
21
  end
10
22
 
11
23
  def yaml_value(value)
12
24
  if value.present?
13
- unless value.is_a?(String)
14
- value = value.respond_to?(:ya2yaml) ? value.ya2yaml(:syck_compatible => true) : value.to_yaml
25
+ unless value.is_a?(String) || value.is_a?(TrueClass) || value.is_a?(FalseClass)
26
+ value = Tolk::YAML.dump(value)
15
27
  end
16
28
  end
17
-
29
+
18
30
  value
19
31
  end
20
32
 
33
+ def boolean_warning
34
+ '<span class="boolean">(Do not translate -- Enter true or false)</span>'.html_safe
35
+ end
36
+
21
37
  def tolk_locale_selection
22
38
  existing_locale_names = Tolk::Locale.all.map(&:name)
23
39
 
24
- pairs = Tolk::Locale::MAPPING.to_a.map(&:reverse).sort_by(&:first)
40
+ pairs = Tolk.config.mapping.to_a.map(&:reverse).sort_by(&:first)
25
41
  pairs.reject {|pair| existing_locale_names.include?(pair.last) }
26
42
  end
27
43
 
@@ -1,55 +1,16 @@
1
+ require 'tolk/config'
2
+ require 'tolk/pagination'
3
+
1
4
  module Tolk
2
5
  class Locale < ActiveRecord::Base
6
+ include Tolk::Pagination::Methods
7
+
3
8
  self.table_name = "tolk_locales"
4
9
 
5
- MAPPING = {
6
- 'ar' => 'Arabic',
7
- 'bs' => 'Bosnian',
8
- 'bt' => 'Bulgarian',
9
- 'ca' => 'Catalan',
10
- 'cz' => 'Czech',
11
- 'da' => 'Danish',
12
- 'de' => 'German',
13
- 'dsb' => 'Lower Sorbian',
14
- 'el' => 'Greek',
15
- 'en' => 'English',
16
- 'es' => 'Spanish',
17
- 'et' => 'Estonian',
18
- 'fa' => 'Persian',
19
- 'fi' => 'Finnish',
20
- 'fr' => 'French',
21
- 'he' => 'Hebrew',
22
- 'hr' => 'Croatian',
23
- 'hsb' => 'Upper Sorbian',
24
- 'hu' => 'Hungarian',
25
- 'id' => 'Indonesian',
26
- 'is' => 'Icelandic',
27
- 'it' => 'Italian',
28
- 'jp' => 'Japanese',
29
- 'ko' => 'Korean',
30
- 'lo' => 'Lao',
31
- 'lt' => 'Lithuanian',
32
- 'lv' => 'Latvian',
33
- 'mk' => 'Macedonian',
34
- 'nl' => 'Dutch',
35
- 'no' => 'Norwegian',
36
- 'pl' => 'Polish',
37
- 'pt-br' => 'Portuguese (Brazilian)',
38
- 'pt-PT' => 'Portuguese (Portugal)',
39
- 'ro' => 'Romanian',
40
- 'ru' => 'Russian',
41
- 'se' => 'Swedish',
42
- 'sk' => 'Slovak',
43
- 'sl' => 'Slovenian',
44
- 'sr' => 'Serbian',
45
- 'sw' => 'Swahili',
46
- 'th' => 'Thai',
47
- 'tr' => 'Turkish',
48
- 'uk' => 'Ukrainian',
49
- 'vi' => 'Vietnamese',
50
- 'zh-CN' => 'Chinese (Simplified)',
51
- 'zh-TW' => 'Chinese (Traditional)'
52
- }
10
+ def self._dump_path
11
+ # Necessary to acces rails.root at runtime !
12
+ @dump_path ||= Tolk.config.dump_path.is_a?(Proc) ? instance_eval(&Tolk.config.dump_path) : Tolk.config.dump_path
13
+ end
53
14
 
54
15
  has_many :phrases, :through => :translations, :class_name => 'Tolk::Phrase'
55
16
  has_many :translations, :class_name => 'Tolk::Translation', :dependent => :destroy
@@ -57,12 +18,11 @@ module Tolk
57
18
  accepts_nested_attributes_for :translations, :reject_if => proc { |attributes| attributes['text'].blank? }
58
19
  before_validation :remove_invalid_translations_from_target, :on => :update
59
20
 
60
- attr_accessible :name
61
21
  cattr_accessor :locales_config_path
62
- self.locales_config_path = "#{Rails.root}/config/locales"
22
+ self.locales_config_path = self._dump_path
63
23
 
64
24
  cattr_accessor :primary_locale_name
65
- self.primary_locale_name = I18n.default_locale.to_s
25
+ self.primary_locale_name = Tolk.config.primary_locale_name || I18n.default_locale.to_s
66
26
 
67
27
  include Tolk::Sync
68
28
  include Tolk::Import
@@ -81,7 +41,7 @@ module Tolk
81
41
  @_primary_locale = nil if reload
82
42
  @_primary_locale ||= begin
83
43
  raise "Primary locale is not set. Please set Locale.primary_locale_name in your application's config file" unless self.primary_locale_name
84
- find_or_create_by_name(self.primary_locale_name)
44
+ where(name: self.primary_locale_name).first_or_create
85
45
  end
86
46
  end
87
47
 
@@ -93,28 +53,32 @@ module Tolk
93
53
  all - [primary_locale]
94
54
  end
95
55
 
96
- def dump_all(to = self.locales_config_path)
97
- secondary_locales.each do |locale|
98
- File.open("#{to}/#{locale.name}.yml", "w+") do |file|
99
- data = locale.to_hash
100
- data.respond_to?(:ya2yaml) ? file.write(data.ya2yaml(:syck_compatible => true)) : YAML.dump(locale.to_hash, file)
101
- end
102
- end
56
+ def dump_all(*args)
57
+ secondary_locales.each { |locale| locale.dump(*args) }
58
+ end
59
+
60
+ def dump_yaml(name, *args)
61
+ where(name: name).first.dump(*args)
103
62
  end
104
63
 
105
64
  def special_key_or_prefix?(prefix, key)
106
65
  self.special_prefixes.include?(prefix) || self.special_keys.include?(key)
107
66
  end
108
67
 
109
- PLURALIZATION_KEYS = ['none', 'one', 'two', 'few', 'many', 'other']
68
+ # http://cldr.unicode.org/index/cldr-spec/plural-rules - TODO: usage of 'none' isn't standard-conform
69
+ PLURALIZATION_KEYS = ['none', 'zero', 'one', 'two', 'few', 'many', 'other']
110
70
  def pluralization_data?(data)
111
71
  keys = data.keys.map(&:to_s)
112
72
  keys.all? {|k| PLURALIZATION_KEYS.include?(k) }
113
73
  end
114
74
  end
115
75
 
76
+ def dump(to = self.locales_config_path, exporter = Tolk::Export)
77
+ exporter.dump(name: name, data: to_hash, destination: to)
78
+ end
79
+
116
80
  def has_updated_translations?
117
- translations.count(:conditions => {:'tolk_translations.primary_updated' => true}) > 0
81
+ translations.where('tolk_translations.primary_updated' => true).count > 0
118
82
  end
119
83
 
120
84
  def phrases_with_translation(page = nil)
@@ -126,22 +90,31 @@ module Tolk
126
90
  end
127
91
 
128
92
  def count_phrases_without_translation
129
- existing_ids = self.translations.all(:select => 'tolk_translations.phrase_id').map(&:phrase_id).uniq
93
+ existing_ids = self.translations(:select => 'tolk_translations.phrase_id').map(&:phrase_id).uniq
130
94
  Tolk::Phrase.count - existing_ids.count
131
95
  end
132
96
 
133
- def phrases_without_translation(page = nil, options = {})
134
- phrases = Tolk::Phrase.scoped(:order => 'tolk_phrases.key ASC')
97
+ def count_phrases_with_updated_translation(page = nil)
98
+ find_phrases_with_translations(page, :'tolk_translations.primary_updated' => true).count
99
+ end
100
+
101
+ def phrases_without_translation(page = nil)
102
+ phrases = Tolk::Phrase.all.order('tolk_phrases.key ASC')
135
103
 
136
- existing_ids = self.translations.all(:select => 'tolk_translations.phrase_id').map(&:phrase_id).uniq
137
- phrases = phrases.scoped(:conditions => ['tolk_phrases.id NOT IN (?)', existing_ids]) if existing_ids.present?
104
+ existing_ids = self.translations(:select => 'tolk_translations.phrase_id').map(&:phrase_id).uniq
105
+ phrases = phrases.where('tolk_phrases.id NOT IN (?)', existing_ids) if existing_ids.present?
106
+
107
+ result = phrases.public_send(pagination_method, page)
108
+ if Rails.version =~ /^4\.0/
109
+ ActiveRecord::Associations::Preloader.new result, :translations
110
+ else
111
+ ActiveRecord::Associations::Preloader.new().preload(result, :translations)
112
+ end
138
113
 
139
- result = phrases.paginate({:page => page, :per_page => Phrase.per_page}.merge(options))
140
- ActiveRecord::Associations::Preloader.new result, :translations
141
114
  result
142
115
  end
143
116
 
144
- def search_phrases(query, scope, key_query, page = nil, options = {})
117
+ def search_phrases(query, scope, key_query, page = nil)
145
118
  return [] unless query.present? || key_query.present?
146
119
 
147
120
  translations = case scope
@@ -151,35 +124,42 @@ module Tolk
151
124
  self.translations.containing_text(query)
152
125
  end
153
126
 
154
- phrases = Tolk::Phrase.scoped(:order => 'tolk_phrases.key ASC')
127
+ phrases = Tolk::Phrase.all.order('tolk_phrases.key ASC')
155
128
  phrases = phrases.containing_text(key_query)
156
129
 
157
- phrases = phrases.scoped(:conditions => ['tolk_phrases.id IN(?)', translations.map(&:phrase_id).uniq])
158
- phrases.paginate({:page => page}.merge(options))
130
+ phrases = phrases.where('tolk_phrases.id IN(?)', translations.map(&:phrase_id).uniq)
131
+ phrases.public_send(pagination_method, page)
159
132
  end
160
133
 
161
- def search_phrases_without_translation(query, page = nil, options = {})
162
- return phrases_without_translation(page, options) unless query.present?
134
+ def search_phrases_without_translation(query, page = nil)
135
+ return phrases_without_translation(page) unless query.present?
163
136
 
164
- phrases = Tolk::Phrase.scoped(:order => 'tolk_phrases.key ASC')
137
+ phrases = Tolk::Phrase.all.order('tolk_phrases.key ASC')
165
138
 
166
- found_translations_ids = Tolk::Locale.primary_locale.translations.all(:conditions => ["tolk_translations.text LIKE ?", "%#{query}%"], :select => 'tolk_translations.phrase_id').map(&:phrase_id).uniq
167
- existing_ids = self.translations.all(:select => 'tolk_translations.phrase_id').map(&:phrase_id).uniq
168
- phrases = phrases.scoped(:conditions => ['tolk_phrases.id NOT IN (?) AND tolk_phrases.id IN(?)', existing_ids, found_translations_ids]) if existing_ids.present?
139
+ found_translations_ids = Tolk::Locale.primary_locale.translations.where(["tolk_translations.text LIKE ?", "%#{query}%"]).to_a.map(&:phrase_id).uniq
140
+ existing_ids = self.translations.select('tolk_translations.phrase_id').to_a.map(&:phrase_id).uniq
141
+ # phrases = phrases.scoped(:conditions => ['tolk_phrases.id NOT IN (?) AND tolk_phrases.id IN(?)', existing_ids, found_translations_ids]) if existing_ids.present?
142
+ phrases = phrases.where(['tolk_phrases.id NOT IN (?) AND tolk_phrases.id IN(?)', existing_ids, found_translations_ids]) if existing_ids.present?
143
+ result = phrases.public_send(pagination_method, page)
144
+ if Rails.version =~ /^4\.0/
145
+ ActiveRecord::Associations::Preloader.new result, :translations
146
+ else
147
+ ActiveRecord::Associations::Preloader.new().preload(result, :translations)
148
+ end
169
149
 
170
- result = phrases.paginate({:page => page}.merge(options))
171
- ActiveRecord::Associations::Preloader.new result, :translations
172
150
  result
173
151
  end
174
152
 
175
153
  def to_hash
176
- { name => translations.each_with_object({}) do |translation, locale|
177
- if translation.phrase.key.include?(".")
178
- locale.deep_merge!(unsquish(translation.phrase.key, translation.value))
179
- else
180
- locale[translation.phrase.key] = translation.value
154
+ data = translations.includes(:phrase).references(:phrases).order(phrases.arel_table[:key]).
155
+ each_with_object({}) do |translation, locale|
156
+ if translation.phrase.key.include?(".")
157
+ locale.deep_merge!(unsquish(translation.phrase.key, translation.value))
158
+ else
159
+ locale[translation.phrase.key] = translation.value
160
+ end
181
161
  end
182
- end }
162
+ { name => data }
183
163
  end
184
164
 
185
165
  def to_param
@@ -191,11 +171,11 @@ module Tolk
191
171
  end
192
172
 
193
173
  def language_name
194
- MAPPING[self.name] || self.name
174
+ Tolk.config.mapping[self.name] || self.name
195
175
  end
196
176
 
197
177
  def get(key)
198
- if phrase = Tolk::Phrase.find_by_key(key)
178
+ if phrase = Tolk::Phrase.where(key: key).first
199
179
  t = self.translations.where(:phrase_id => phrase.id).first
200
180
  t.text if t
201
181
  end
@@ -204,18 +184,37 @@ module Tolk
204
184
  def translations_with_html
205
185
  translations = self.translations.all(:conditions => "tolk_translations.text LIKE '%>%' AND
206
186
  tolk_translations.text LIKE '%<%' AND tolk_phrases.key NOT LIKE '%_html'", :joins => :phrase)
207
- ActiveRecord::Associations::Preloader.new translations, :phrase
187
+ if Rails.version =~ /^4\.0/
188
+ ActiveRecord::Associations::Preloader.new translations, :phrase
189
+ else
190
+ ActiveRecord::Associations::Preloader.new().preload(translations, :phrase)
191
+ end
208
192
  translations
209
193
  end
210
194
 
195
+ def self.rename(old_name, new_name)
196
+ if old_name.blank? || new_name.blank?
197
+ "You need to provide both names, aborting."
198
+ else
199
+ if locale = where(name: old_name).first
200
+ locale.name = new_name
201
+ locale.save
202
+ "Locale ' #{old_name}' was renamed '#{new_name}'"
203
+ else
204
+ "Locale with name '#{old_name}' not found."
205
+ end
206
+ end
207
+ end
208
+
211
209
  private
212
210
 
211
+
213
212
  def remove_invalid_translations_from_target
214
213
  self.translations.target.dup.each do |t|
215
- unless t.valid?
214
+ unless t.valid?
216
215
  self.translations.target.delete(t)
217
216
  else
218
- t.updated_at = Time.current # Silly hax to fool autosave into saving the record
217
+ t.updated_at_will_change!
219
218
  end
220
219
  end
221
220
 
@@ -223,15 +222,17 @@ module Tolk
223
222
  end
224
223
 
225
224
  def find_phrases_with_translations(page, conditions = {})
226
- result = Tolk::Phrase.paginate(:page => page,
227
- :conditions => { :'tolk_translations.locale_id' => self.id }.merge(conditions),
228
- :joins => :translations, :order => 'tolk_phrases.key ASC')
225
+ result = Tolk::Phrase.where({ :'tolk_translations.locale_id' => self.id }.merge(conditions)).joins(:translations).order('tolk_phrases.key ASC').public_send(pagination_method, page)
229
226
 
230
227
  result.each do |phrase|
231
228
  phrase.translation = phrase.translations.for(self)
232
229
  end
233
230
 
234
- ActiveRecord::Associations::Preloader.new result, :translations
231
+ if Rails.version =~ /^4\.0/
232
+ ActiveRecord::Associations::Preloader.new result, :translations
233
+ else
234
+ ActiveRecord::Associations::Preloader.new().preload(result, :translations)
235
+ end
235
236
 
236
237
  result
237
238
  end
@@ -2,12 +2,9 @@ module Tolk
2
2
  class Phrase < ActiveRecord::Base
3
3
  self.table_name = "tolk_phrases"
4
4
 
5
- attr_accessible :key
6
-
7
5
  validates_uniqueness_of :key
8
6
 
9
- cattr_accessor :per_page
10
- self.per_page = 30
7
+ paginates_per 30
11
8
 
12
9
  has_many :translations, :class_name => 'Tolk::Translation', :dependent => :destroy do
13
10
  def primary
@@ -21,8 +18,10 @@ module Tolk
21
18
 
22
19
  attr_accessor :translation
23
20
 
21
+ #scope :red, -> { where(color: 'red') } rather than scope :red, -> { { conditions: { color: 'red' } } }
22
+
24
23
  scope :containing_text, lambda { |query|
25
- { :conditions => ["tolk_phrases.key LIKE ?", "%#{query}%"] }
24
+ where("tolk_phrases.key LIKE ?", "%#{query}%")
26
25
  }
27
26
  end
28
27
  end
@@ -5,7 +5,8 @@ module Tolk
5
5
  scope :containing_text, lambda {|query| where("tolk_translations.text LIKE ?", "%#{query}%") }
6
6
 
7
7
  serialize :text
8
- validates_presence_of :text, :if => proc {|r| r.primary.blank? && !r.explicit_nil }
8
+ serialize :previous_text
9
+ validate :validate_text_not_nil, :if => proc {|r| r.primary.blank? && !r.explicit_nil && !r.boolean?}
9
10
  validate :check_matching_variables, :if => proc { |tr| tr.primary_translation.present? }
10
11
 
11
12
  validates_uniqueness_of :phrase_id, :scope => :locale_id
@@ -14,9 +15,6 @@ module Tolk
14
15
  belongs_to :locale, :class_name => 'Tolk::Locale'
15
16
  validates_presence_of :locale_id
16
17
 
17
- attr_accessible :phrase_id, :locale_id, :text, :primary_updated, :previous_text, :locale, :phrase
18
-
19
- attr_accessor :force_set_primary_update
20
18
  before_save :set_primary_updated
21
19
 
22
20
  before_save :set_previous_text
@@ -27,6 +25,10 @@ module Tolk
27
25
  attr_accessor :explicit_nil
28
26
  before_validation :set_explicit_nil
29
27
 
28
+ def boolean?
29
+ text.is_a?(TrueClass) || text.is_a?(FalseClass) || text == 't' || text == 'f'
30
+ end
31
+
30
32
  def up_to_date?
31
33
  not out_of_date?
32
34
  end
@@ -45,24 +47,48 @@ module Tolk
45
47
 
46
48
  def text=(value)
47
49
  value = value.to_s if value.kind_of?(Fixnum)
48
- super unless value.to_s == text
50
+ if primary_translation && primary_translation.boolean?
51
+ value = case value.to_s.downcase.strip
52
+ when 'true', 't'
53
+ true
54
+ when 'false', 'f'
55
+ false
56
+ else
57
+ self.explicit_nil = true
58
+ nil
59
+ end
60
+ super unless value == text
61
+ else
62
+ value = value.strip if value.is_a?(String) && Tolk.config.strip_texts
63
+ super unless value.to_s == text
64
+ end
49
65
  end
50
66
 
51
67
  def value
52
68
  if text.is_a?(String) && /^\d+$/.match(text)
53
69
  text.to_i
70
+ elsif (primary_translation || self).boolean?
71
+ %w[true t].member?(text.to_s.downcase.strip)
54
72
  else
55
73
  text
56
74
  end
57
75
  end
58
76
 
59
77
  def self.detect_variables(search_in)
60
- case search_in
78
+ variables = case search_in
61
79
  when String then Set.new(search_in.scan(/\{\{(\w+)\}\}/).flatten + search_in.scan(/\%\{(\w+)\}/).flatten)
62
80
  when Array then search_in.inject(Set[]) { |carry, item| carry + detect_variables(item) }
63
81
  when Hash then search_in.values.inject(Set[]) { |carry, item| carry + detect_variables(item) }
64
82
  else Set[]
65
83
  end
84
+
85
+ # delete special i18n variable used for pluralization itself (might not be used in all values of
86
+ # the pluralization keys, but is essential to use pluralization at all)
87
+ if search_in.is_a?(Hash) && Tolk::Locale.pluralization_data?(search_in)
88
+ variables.delete_if {|v| v == 'count' }
89
+ else
90
+ variables
91
+ end
66
92
  end
67
93
 
68
94
  def variables
@@ -92,14 +118,25 @@ module Tolk
92
118
  end
93
119
  end
94
120
 
95
- self.text = nil if primary_translation.text.class != self.text.class
121
+ if primary_translation.boolean?
122
+ self.text = case self.text.to_s.strip
123
+ when 'true'
124
+ true
125
+ when 'false'
126
+ false
127
+ else
128
+ nil
129
+ end
130
+ elsif primary_translation.text.class != self.text.class
131
+ self.text = nil
132
+ end
96
133
  end
97
134
 
98
135
  true
99
136
  end
100
137
 
101
138
  def set_primary_updated
102
- self.primary_updated = self.force_set_primary_update ? true : false
139
+ self.primary_updated = false
103
140
  true
104
141
  end
105
142
 
@@ -110,12 +147,17 @@ module Tolk
110
147
 
111
148
  def check_matching_variables
112
149
  unless variables_match?
113
- if primary_translation.variables.empty? || primary_translation.variables.class == Set
114
- self.errors.add(:text, "The original does not contain variables, so they should not be included.")
150
+ if primary_translation.variables.empty?
151
+ self.errors.add(:variables, "The primary translation does not contain substitutions, so this should neither.")
115
152
  else
116
- self.errors.add(:text, "The translation should contain the variables #{primary_translation.to_a.to_sentence}.")
153
+ self.errors.add(:variables, "The translation should contain the substitutions of the primary translation: (#{primary_translation.variables.to_a.join(', ')}), found (#{self.variables.to_a.join(', ')}).")
117
154
  end
118
155
  end
119
156
  end
157
+
158
+ def validate_text_not_nil
159
+ return unless text.nil?
160
+ errors.add :text, :blank
161
+ end
120
162
  end
121
163
  end