air18n 0.4.5 → 0.4.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -2,10 +2,59 @@ module Air18n
2
2
  module Metrics
3
3
  TARGET_PRIORITY_PHRASE_TRANSLATION_PERCENT = 98
4
4
 
5
+ def self.time_to_first_translation
6
+ # First we get all phrases created in the last 28 days and one of their
7
+ # translations (leaving out verifications).
8
+ #
9
+ # Then we look at the difference between the phrase's created_at and the
10
+ # phrase translation's created_at and return the average per language
11
+
12
+ search_scope = Air18n::Phrase.still_used
13
+ search_scope = search_scope.select(
14
+ '`phrases`.`id`, `phrases`.`key`, `phrases`.`created_at`, ' +
15
+ '`phrase_translations`.`locale` AS latest_translation_locale, ' +
16
+ '`phrase_translations`.`user_id` AS latest_translation_user_id, ' +
17
+ '`phrase_translations`.`created_at` AS latest_translation_created_at'
18
+ )
19
+ search_scope = search_scope.where('`phrases`.`created_at` >= ?', 28.days.ago)
20
+ search_scope = search_scope.pull_in_all_historic_phrase_translations
21
+ search_scope = search_scope.where('`phrase_translations`.`is_verification` = ?', false)
22
+ search_scope = search_scope.group('`phrases`.`id`, `phrase_translations`.`phrase_id`, `latest_translation_locale`')
23
+
24
+ phrases_and_translations = search_scope.all
25
+
26
+ progress = {}
27
+
28
+ locale_to_translations = phrases_and_translations.group_by do |phrase_and_translation|
29
+ phrase_and_translation.latest_translation_locale
30
+ end
31
+ locale_to_translations.each do |locale, phrases_and_translations_for_locale|
32
+ if locale.present?
33
+ locale = locale.to_sym
34
+ progress[locale] ||= {}
35
+ elapsed_times = []
36
+ phrases_and_translations_for_locale.each do |phrase_and_translation|
37
+ phrase_created_at = phrase_and_translation.created_at
38
+ translated_at = phrase_and_translation.latest_translation_created_at
39
+ if translated_at.is_a?(String)
40
+ translated_at = Time.parse(translated_at)
41
+ end
42
+ seconds_passed = (translated_at - phrase_created_at).to_i
43
+
44
+ elapsed_times << seconds_passed
45
+ end
46
+
47
+ progress[locale][:average_seconds_to_first_translation] = (elapsed_times.inject(:+).to_f / elapsed_times.size).round
48
+ end
49
+ end
50
+
51
+ progress
52
+ end
53
+
5
54
  def self.translation_progress(page_ids)
6
55
  search_scope = Air18n::Phrase.still_used
7
56
  search_scope = search_scope.select(
8
- '`phrases`.`id`, `phrases`.`key`, ' +
57
+ '`phrases`.`id`, `phrases`.`key`, `phrases`.`created_at`, ' +
9
58
  '`phrase_translations`.`locale` AS latest_translation_locale, ' +
10
59
  '`phrase_translations`.`user_id` AS latest_translation_user_id, ' +
11
60
  '`phrase_translations`.`created_at` AS latest_translation_created_at, ' +
@@ -39,13 +88,19 @@ module Air18n
39
88
  priority_keys = phrases_and_translations.map { |phrase_and_translation| phrase_and_translation.key }.uniq
40
89
  number_of_priority_phrases = priority_keys.size
41
90
  number_of_priority_words = priority_keys.map { |k| word_counts[k] }.sum
42
- locale_to_translations = phrases_and_translations.group_by { |phrase_and_translation| phrase_and_translation.latest_translation_locale }
91
+ locale_to_translations = phrases_and_translations.group_by do |phrase_and_translation|
92
+ phrase_and_translation.latest_translation_locale
93
+ end
43
94
  locale_to_translations.each do |locale, phrases_and_translations_for_locale|
44
95
  if locale.present?
45
96
  locale = locale.to_sym
46
97
  progress[locale] ||= {}
47
- phrases_with_translations_for_locale = phrases_and_translations_for_locale.find_all { |phrase_and_translation| phrase_and_translation.latest_translation_user_id }
48
- phrases_with_verifications_for_locale = phrases_with_translations_for_locale.find_all { |phrase_and_translation| true_value?(phrase_and_translation.latest_translation_is_verification) }
98
+ phrases_with_translations_for_locale = phrases_and_translations_for_locale.find_all do |phrase_and_translation|
99
+ phrase_and_translation.latest_translation_user_id
100
+ end
101
+ phrases_with_verifications_for_locale = phrases_with_translations_for_locale.find_all do |phrase_and_translation|
102
+ true_value?(phrase_and_translation.latest_translation_is_verification)
103
+ end
49
104
 
50
105
  words_with_translations_for_locale = phrases_with_translations_for_locale.map { |p| word_counts[p.key] }.sum
51
106
  words_with_verifications_for_locale = phrases_with_verifications_for_locale.map { |p| word_counts[p.key] }.sum
@@ -83,12 +138,19 @@ module Air18n
83
138
  progress[locale][:phrases_remaining_to_verify] = progress[locale][:phrases] - progress[locale][:phrases_verified]
84
139
  progress[locale][:words_remaining_to_verify] = progress[locale][:words] - progress[locale][:words_verified]
85
140
 
86
- progress[locale][:translators] = phrases_with_translations_for_locale.inject(Set.new) do |carry, value|
87
- if since?(value.latest_translation_created_at, 28.days.ago)
88
- carry.add(value.latest_translation_user_id)
141
+ progress[locale][:translators] =
142
+ phrases_with_translations_for_locale.inject(Set.new) do |carry, value|
143
+ if since?(value.latest_translation_created_at, 28.days.ago)
144
+ carry.add(value.latest_translation_user_id)
145
+ end
146
+ carry
147
+ end
148
+ progress[locale][:number_of_nonautomatic_translators] =
149
+ if progress[locale][:translators].include?(0)
150
+ progress[locale][:translators].size - 1
151
+ else
152
+ progress[locale][:translators].size
89
153
  end
90
- carry
91
- end
92
154
  end
93
155
  end
94
156
 
@@ -156,7 +218,6 @@ module Air18n
156
218
  :words_translated_last_week => words_translated_last_week,
157
219
  :words_verified_last_month => words_verified_last_month,
158
220
  :words_verified_last_week => words_verified_last_week,
159
- :words_verified_last_week => words_verified_last_week,
160
221
  :daily_average => daily_average,
161
222
  :number_of_later_modified_phrases_last_month => number_of_later_modified_phrases_last_month,
162
223
  :later_modified_percent => later_modified_percent
@@ -173,6 +234,13 @@ module Air18n
173
234
  info[:translator_progress][user_id] = translator_progress(locale, user_id)
174
235
  end
175
236
  end
237
+
238
+ t = time_to_first_translation()
239
+ t.each do |locale, info|
240
+ p[locale].merge!(info)
241
+ end
242
+
243
+ p
176
244
  end
177
245
 
178
246
  # Returns scope for searching for most recent PhraseTranslations of a
@@ -125,6 +125,10 @@ module Air18n
125
125
  "LEFT OUTER JOIN phrase_translations ON phrase_translations.phrase_id = phrases.id AND phrase_translations.is_latest = #{connection.quoted_true} AND phrase_translations.is_stale = #{connection.quoted_false}"
126
126
  ) }
127
127
 
128
+ scope :pull_in_all_historic_phrase_translations, lambda { joins(
129
+ "LEFT OUTER JOIN phrase_translations ON phrase_translations.phrase_id = phrases.id"
130
+ ) }
131
+
128
132
  # The still_used scope is wrapped in a lambda expression to
129
133
  # I18n.still_used_phrase_ids is reevaluated each time.
130
134
  # This makes dynamic updating possible and testing easier.
@@ -1,3 +1,3 @@
1
1
  module Air18n
2
- VERSION = "0.4.5"
2
+ VERSION = "0.4.6"
3
3
  end
@@ -17,13 +17,17 @@ describe Air18n::Metrics do
17
17
 
18
18
  @translator1_ko_id = 15
19
19
 
20
- @phrase1 = FactoryGirl.create(:phrase, :value => 'one two three four five six seven eight nine')
21
- @phrase2 = FactoryGirl.create(:phrase)
22
- @phrase3 = FactoryGirl.create(:phrase)
23
- @phrase4 = FactoryGirl.create(:phrase)
24
- @phrase5 = FactoryGirl.create(:phrase)
25
- @phrase6 = FactoryGirl.create(:phrase)
26
- @phrase7 = FactoryGirl.create(:phrase)
20
+ without_timestamping_of Air18n::Phrase do
21
+ @phrase1 = FactoryGirl.create(:phrase,
22
+ :value => 'one two three four five six seven eight nine',
23
+ :created_at => 3.days.ago)
24
+ @phrase2 = FactoryGirl.create(:phrase, :created_at => 1.year.ago)
25
+ @phrase3 = FactoryGirl.create(:phrase, :created_at => 1.year.ago)
26
+ @phrase4 = FactoryGirl.create(:phrase, :created_at => 1.year.ago)
27
+ @phrase5 = FactoryGirl.create(:phrase, :created_at => 1.year.ago)
28
+ @phrase6 = FactoryGirl.create(:phrase, :created_at => 1.year.ago)
29
+ @phrase7 = FactoryGirl.create(:phrase, :created_at => 1.year.ago)
30
+ end
27
31
 
28
32
  # info#press is a manually-prioritized page.
29
33
  @phrase3_screenshot1 = FactoryGirl.create(
@@ -197,7 +201,9 @@ describe Air18n::Metrics do
197
201
  :words_remaining_to_verify => 12,
198
202
 
199
203
  # translator2_fr doesn't appear because he hasn't last touched any phrase.
200
- :translators => Set.new([@translator1_fr_id, @translator4_fr_id]) })
204
+ :translators => Set.new([@translator1_fr_id, @translator4_fr_id]),
205
+ :number_of_nonautomatic_translators => 2,
206
+ })
201
207
 
202
208
  ppp[:it].should include({
203
209
  :phrases => 5,
@@ -210,7 +216,8 @@ describe Air18n::Metrics do
210
216
  :words_translated_percent => 43,
211
217
  :phrases_progress => :bad,
212
218
  :phrases_remaining_to_translate => 4,
213
- :words_remaining_to_translate => 12 })
219
+ :words_remaining_to_translate => 12,
220
+ })
214
221
  ppp[:ko].should include({
215
222
  :phrases => 5,
216
223
  :words => 21,
@@ -223,7 +230,8 @@ describe Air18n::Metrics do
223
230
  :phrases_progress => :bad,
224
231
  :phrases_remaining_to_translate => 4,
225
232
  :words_remaining_to_translate => 18,
226
- :translators => Set.new([@translator1_ko_id]) })
233
+ :translators => Set.new([@translator1_ko_id]),
234
+ })
227
235
  end
228
236
  end
229
237
 
@@ -259,11 +267,21 @@ describe Air18n::Metrics do
259
267
  end
260
268
  end
261
269
 
270
+ context "#time_to_first_translation" do
271
+ it "should measure time to first translation" do
272
+ s = Air18n::Metrics.time_to_first_translation
273
+ s.size.should == 2
274
+ s[:it][:average_seconds_to_first_translation].should == 280800
275
+ s[:fr][:average_seconds_to_first_translation].should == 277200
276
+ end
277
+ end
278
+
262
279
  context "#metrics_suite" do
263
280
  it "should work" do
264
281
  s = Air18n::Metrics.metrics_suite
265
282
  s[:fr][:words_translated].should == 18
266
283
  s[:fr][:translator_progress].size.should == 2
284
+ s[:fr][:average_seconds_to_first_translation].should > 0
267
285
  end
268
286
  end
269
287
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: air18n
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.5
4
+ version: 0.4.6
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ authors:
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
- date: 2013-03-27 00:00:00.000000000 Z
16
+ date: 2013-03-28 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: i18n