tr8n 3.1.6 → 3.1.7

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.
@@ -90,7 +90,7 @@ class Tr8n::Translation < ActiveRecord::Base
90
90
  return nil if super_rules == nil
91
91
  return nil unless super_rules.class.name == 'Array'
92
92
  return nil if super_rules.size == 0
93
-
93
+
94
94
  @loaded_rules ||= begin
95
95
  rulz = []
96
96
  super_rules.each do |rule|
@@ -118,43 +118,6 @@ class Tr8n::Translation < ActiveRecord::Base
118
118
  end
119
119
  end
120
120
 
121
- # generates the hash without rule ids, but with full definitions
122
- def rules_api_hash
123
- @rules_api_hash ||= (rules || []).collect{|rule_hash| rule_hash[:rule].to_api_hash.merge(:token => rule_hash[:token])}
124
- end
125
-
126
- # serilaize translation to API hash to be used for synchronization
127
- def to_api_hash
128
- {:locale => language.locale, :label => label, :rank => rank, :rules => rules_api_hash}
129
- end
130
-
131
- # create translation from API hash for a specific key
132
- def self.create_from_api_hash(tkey, translator, hash, opts = {})
133
- return if hash[:label].blank? # don't add empty translations
134
- lang = Tr8n::Language.for(hash[:locale])
135
- return unless lang # don't add translations for an unsupported language
136
-
137
- tkey.translations.each do |trn|
138
- # if an identical translation exists, don't add it
139
- return if trn.to_api_hash == hash
140
- end
141
-
142
- # generate rules for the translation
143
- rules = nil
144
-
145
- if hash[:rules].any?
146
- hash[:rules].each do |rule_hash|
147
- return unless rule_hash[:token] and rule_hash[:type] and rule_hash[:definition]
148
-
149
- rule = Tr8n::LanguageRule.for_definition(lang, translator, rule_hash[:type], rule_hash[:definition], opts)
150
- return unless rule # if the rule has not been created, we should not even add the translation
151
- rules << {:token => rule_hash[:token], :rule_id => rule.id}
152
- end
153
- end
154
-
155
- tkey.add_translation(hash[:label], rules, lang, translator)
156
- end
157
-
158
121
  # deprecated - api_hash should be used instead
159
122
  def rules_definitions
160
123
  return nil if rules.nil? or rules.empty?
@@ -257,9 +220,49 @@ class Tr8n::Translation < ActiveRecord::Base
257
220
  end
258
221
 
259
222
  ###############################################################
260
- ## Search Related Stuff
223
+ ## Synchronization Methods
224
+ ###############################################################
225
+ # generates the hash without rule ids, but with full definitions
226
+ def rules_sync_hash
227
+ @rules_sync_hash ||= (rules || []).collect{|rule| rule[:rule].to_sync_hash(rule[:token])}
228
+ end
229
+
230
+ # serilaize translation to API hash to be used for synchronization
231
+ def to_sync_hash(include_translator = true)
232
+ hash = {"locale" => language.locale, "label" => label, "rank" => rank, "rules" => rules_sync_hash}
233
+ hash["translator_id"] = translator.remote_id if include_translator and translator and translator.remote_id
234
+ hash
235
+ end
236
+
237
+ # create translation from API hash for a specific key
238
+ def self.create_from_sync_hash(tkey, translator, hash, opts = {})
239
+ # don't add empty translations
240
+ return if hash["label"].blank?
241
+
242
+ lang = Tr8n::Language.for(hash["locale"])
243
+ # don't add translations for an unsupported language
244
+ return unless lang
245
+
246
+ # generate rules for the translation
247
+ rules = []
248
+
249
+ if hash["rules"] and hash["rules"].any?
250
+ hash["rules"].each do |rule_hash|
251
+ rule = Tr8n::LanguageRule.create_from_sync_hash(lang, translator, rule_hash, opts)
252
+ pp rule
253
+
254
+ return unless rule # if the rule has not been created, we should not even add the translation
255
+ rules << {:token => rule_hash["token"], :rule_id => rule.id}
256
+ end
257
+ end
258
+
259
+ rules = nil if rules.empty?
260
+ tkey.add_translation(hash["label"], rules, lang, translator)
261
+ end
262
+
263
+ ###############################################################
264
+ ## Search Methods
261
265
  ###############################################################
262
-
263
266
  def self.filter_status_options
264
267
  [["all translations", "all"],
265
268
  ["accepted translations", "accepted"],
@@ -68,6 +68,7 @@ class Tr8n::TranslationKey < ActiveRecord::Base
68
68
  :locale => locale,
69
69
  :level => level,
70
70
  :admin => Tr8n::Config.block_options[:admin])
71
+
71
72
  unless options[:source].blank?
72
73
  # at the time of creation - mark the first source of the key
73
74
  Tr8n::TranslationKeySource.find_or_create(new_tkey, Tr8n::TranslationSource.find_or_create(options[:source], options[:url]))
@@ -218,8 +219,10 @@ class Tr8n::TranslationKey < ActiveRecord::Base
218
219
 
219
220
  def add_translation(label, rules = nil, language = Tr8n::Config.current_language, translator = Tr8n::Config.current_translator)
220
221
  raise Tr8n::Exception.new("The sentence contains dirty words") unless language.clean_sentence?(label)
221
- translation = Tr8n::Translation.create(:translation_key => self, :language => language,
222
- :translator => translator, :label => label, :rules => rules)
222
+ pp rules
223
+ translation = Tr8n::Translation.create(:translation_key => self, :language => language, :translator => translator, :label => label, :rules => rules)
224
+ pp translation
225
+
223
226
  translation.vote!(translator, 1)
224
227
  translation
225
228
  end
@@ -524,35 +527,62 @@ class Tr8n::TranslationKey < ActiveRecord::Base
524
527
  Tr8n::Cache.delete("translation_key_#{key}")
525
528
  end
526
529
 
527
- def to_api_hash
530
+ ###############################################################
531
+ ## Synchronization Methods
532
+ ###############################################################
533
+ def mark_as_synced!
534
+ update_attributes(:synced_at => Time.now + 5.seconds)
535
+ end
536
+
537
+ def to_sync_hash(default_translation_hashes = nil)
528
538
  {
529
- :key => self.key,
530
- :label => self.label,
531
- :description => self.description,
532
- :locale => (locale || Tr8n::Config.default_locale),
533
- :translations => translations_for(nil, Tr8n::Config.translation_threshold).collect{|t| t.to_api_hash}
539
+ "key" => self.key,
540
+ "label" => self.label,
541
+ "description" => self.description,
542
+ "locale" => (locale || Tr8n::Config.default_locale),
543
+ "translations" => default_translation_hashes || translations_for(nil, Tr8n::Config.translation_threshold).collect{|t| t.to_sync_hash}
534
544
  }
535
545
  end
536
546
 
547
+ def transations_sync_hashes
548
+ @transations_sync_hashes ||= translations.collect{|t| t.to_sync_hash(false)}
549
+ end
550
+
537
551
  # create translation key from API hash
538
- def self.create_from_api_hash(tkey_hash, translator, opts = {})
539
- return if tkey_hash[:key].blank? or tkey_hash[:label].blank? or tkey_hash[:locale].blank?
552
+ def self.create_from_sync_hash(tkey_hash, translator, opts = {})
553
+ return if tkey_hash["key"].blank? or tkey_hash["label"].blank? or tkey_hash["locale"].blank?
540
554
 
541
- tkey = Tr8n::TranslationKey.find_or_create(tkey_hash[:label], tkey_hash[:description])
555
+ tkey = Tr8n::TranslationKey.find_or_create(tkey_hash["label"], tkey_hash["description"])
542
556
 
543
557
  # return unless tkey.key==tkey_hash[:key] # need to warn the user that the key methods don't match
544
558
 
545
- opts[:force_create] = Tr8n::Config.synchronization_create_rules? if opts[:force_create].nil?
559
+ # opts[:force_create] = Tr8n::Config.synchronization_create_rules? if opts[:force_create].nil?
560
+
561
+ remaining_translations = tkey.transations_sync_hashes.dup
562
+ # pp :before, remaining_sync_hashes
546
563
 
547
- (tkey_hash[:translations] || []).each do |trn_hash|
548
- Tr8n::Translation.create_from_api_hash(tkey, translator, trn_hash, opts)
564
+ added_trans = []
565
+ (tkey_hash["translations"] || []).each do |t_hash|
566
+ # if the translation came from a linked translator, use the translator
567
+ translation_translator = translator
568
+ if t_hash["translator_id"]
569
+ translation_translator = Tr8n::Translator.find_by_id(t_hash["translator_id"])
570
+ t_hash.delete("translator_id")
571
+ translation_translator ||= translator
572
+ end
573
+
574
+ remaining_translations.delete(t_hash)
575
+ next if tkey.transations_sync_hashes.include?(t_hash)
576
+ trans = Tr8n::Translation.create_from_sync_hash(tkey, translation_translator, t_hash, opts)
549
577
  end
550
578
 
551
- tkey
579
+ # need to send back translations that have not been added, but exist in the system
580
+ # pp :after, remaining_sync_hashes
581
+ [tkey, remaining_translations]
552
582
  end
553
583
 
554
584
  ###############################################################
555
- ## Feature Related Stuff
585
+ ## Feature Methods
556
586
  ###############################################################
557
587
 
558
588
  def self.title
@@ -580,7 +610,7 @@ class Tr8n::TranslationKey < ActiveRecord::Base
580
610
  end
581
611
 
582
612
  ###############################################################
583
- ## Search Related Stuff
613
+ ## Search Methods
584
614
  ###############################################################
585
615
 
586
616
  def self.filter_phrase_type_options
@@ -641,6 +671,6 @@ class Tr8n::TranslationKey < ActiveRecord::Base
641
671
  results = results.where("tr8n_translation_keys.id not in (select tr8n_translation_key_locks.translation_key_id from tr8n_translation_key_locks where tr8n_translation_key_locks.language_id = ? and tr8n_translation_key_locks.locked = ?)", Tr8n::Config.current_language.id, true)
642
672
  end
643
673
 
644
- results
674
+ results.order("created_at desc")
645
675
  end
646
676
  end
@@ -43,5 +43,5 @@ Tr8n::Engine.routes.draw do
43
43
  end
44
44
  end
45
45
 
46
- root :to => "home#index"
46
+ root :to => "dashboard#index"
47
47
  end
@@ -265,8 +265,8 @@ defaults:
265
265
  #############################################################################
266
266
  synchronization:
267
267
  server: "http://tr8n.net" # alternative, regional locations will be available in the future
268
- key: "iKjOrZjor68a4UeCD3Cq2r9t9ibBC4HnYoMNMrN7" # replace this with your key
269
- secret: "iKjOrZjor68a4UeCD3Cq2r9t9ibBC4HnYoMNMrN7" # replace this with your secret
268
+ key: "YOUR APP KEY" # replace this with your key
269
+ secret: "YOUR APP SECRET" # replace this with your secret
270
270
  batch_size: 50 # how many kesy to send to the server at a time
271
271
  create_rules: true # force rules creation, or skip translations for rules that don't exist
272
272
  all_languages: false # use only enabled languages, or all languages
@@ -11,6 +11,9 @@
11
11
  <div class="page_head">
12
12
  <div class="page_fixed">
13
13
  <div class="mrgn_h">
14
+ <ul class="flt_r horiz_list top_nav">
15
+ <li><%= tr8n_language_selector_tag(:lightbox=>false) %></li>
16
+ </ul>
14
17
  <h1 class="logo"><%=tr("Tr8n Translation Engine", "Application title")%></h1>
15
18
  </div>
16
19
  </div>
@@ -37,7 +40,7 @@
37
40
  <li><%=link_to(tr("Credits"), "/tr8n/help/credits", :class => "quiet")%></li>
38
41
  <li><%=link_to(tr("License"), "/tr8n/help/license", :class => "quiet")%></li>
39
42
  </ul>
40
- &copy; Copyright 2010 - 2011 tr8n.net
43
+ &copy; Copyright 2010 - 2012 tr8n.net
41
44
  </div>
42
45
 
43
46
  <div style="padding:15px;">
@@ -23,8 +23,10 @@
23
23
  <div class="page_head">
24
24
  <div class="page_fixed">
25
25
  <div class="mrgn_h">
26
- <%= tr8n_translator_login_tag(:class => "flt_r horiz_list top_nav") %>
27
- <h1 class="logo"><%=link_to(tr("Tr8n Translation Engine", "Application title"), {:controller => "/tr8n/home"}, :style=>"text-decorations:none;")%></h1>
26
+ <ul class="flt_r horiz_list top_nav">
27
+ <li><%= tr8n_language_selector_tag(:lightbox=>false) %></li>
28
+ </ul>
29
+ <h1 class="logo"><%=link_to(tr("Tr8n Translation Engine", "Application title"), "/", :style=>"text-decorations:none;")%></h1>
28
30
  </div>
29
31
  </div>
30
32
  </div>
@@ -49,7 +51,7 @@
49
51
  <li><%=link_to(tr("Credits"), "/tr8n/help/credits", :class => "quiet")%></li>
50
52
  <li><%=link_to(tr("License"), "/tr8n/help/license", :class => "quiet")%></li>
51
53
  </ul>
52
- &copy; Copyright 2010 - 2011 tr8n.net
54
+ &copy; Copyright 2010 - 2012 tr8n.net
53
55
  </div>
54
56
 
55
57
  <div style="padding:15px;">
@@ -45,7 +45,7 @@ class Tr8nGenerator < Rails::Generators::Base
45
45
  end
46
46
 
47
47
  def copy_configuration
48
- config_source = File.expand_path("#{self.class.source_root}/config', __FILE__)
48
+ config_source = File.expand_path("#{self.class.source_root}/config/tr8n", __FILE__)
49
49
  system "rsync -ruv #{config_source} #{Rails.root}/config"
50
50
  end
51
51
 
@@ -85,8 +85,10 @@ namespace :tr8n do
85
85
  Tr8n::IpLocation.import_from_file('config/tr8n/data/ip_locations.csv', :verbose => true)
86
86
  end
87
87
 
88
- desc "Downloads translations from tr8n.net"
88
+ desc "Synchronize translations with tr8n.net"
89
89
  task :sync => :environment do
90
- Tr8n::SyncLog.sync
90
+ opts = {}
91
+ opts[:force] = true if ENV["force"] == "true"
92
+ Tr8n::SyncLog.sync(opts)
91
93
  end
92
94
  end
@@ -532,7 +532,7 @@ module Tr8n
532
532
 
533
533
  def self.language_rule_dependencies
534
534
  @language_rule_dependencies ||= begin
535
- depts = {}
535
+ depts = HashWithIndifferentAccess.new
536
536
  language_rule_classes.each do |cls|
537
537
  if depts[cls.dependency]
538
538
  raise Tr8n::Exception.new("The same dependency key #{cls.dependency} has been registered for multiple rules. This is not allowed.")
@@ -1,3 +1,3 @@
1
1
  module Tr8n
2
- VERSION = "3.1.6"
2
+ VERSION = "3.1.7"
3
3
  end
@@ -0,0 +1,200 @@
1
+ /****************************************/
2
+ /*** Classes for the admin user page
3
+ /****************************************/
4
+ @mixin rounded-corners($radius) {
5
+ border-radius: $radius;
6
+ -moz-border-radius: $radius;
7
+ -webkit-border-radius: $radius;
8
+ }
9
+
10
+ @mixin shadow($info) {
11
+ box-shadow:$info;
12
+ -moz-box-shadow:$info;
13
+ -webkit-box-shadow:$info;
14
+ }
15
+
16
+ @import "layout.css.scss";
17
+ @import "components.css.scss";
18
+
19
+ .pagination {
20
+ text-align:left !important;
21
+ }
22
+
23
+ .admin_table {
24
+ width: 100%;
25
+ font-size: 12px;
26
+ border: 1px #e5e5e5 solid;
27
+ border-collapse: collapse;
28
+ background-color: white;
29
+ margin-bottom: 10px;
30
+ }
31
+
32
+ .admin_table th {
33
+ background-color: #efefef;
34
+ border: none;
35
+ border: 1px #e5e5e5 solid;
36
+ font-weight:bold;
37
+ }
38
+
39
+ .admin_table tr:hover {
40
+ background-color: #eee;
41
+ }
42
+
43
+ .admin_table td {
44
+ padding: 5px;
45
+ border: 1px solid #e5e5e5;
46
+ }
47
+
48
+ .admin_table td.numeric,
49
+ .admin_table th.numeric {
50
+ text-align: right;
51
+ }
52
+
53
+ .admin_table span.description {
54
+ color: #aaaaaa;
55
+ font-weight: normal;
56
+ font-size: 11px;
57
+ }
58
+
59
+ .admin_table td.key {
60
+ vertical-align:top;
61
+ width: 33%;
62
+ color: #666666;
63
+ font-weight: bold;
64
+ text-align: right;
65
+ padding-left: 10px;
66
+ }
67
+
68
+ .admin_table td.value {
69
+ vertical-align:top;
70
+ }
71
+
72
+ .admin_table td.value ul {
73
+ margin-top:0px;
74
+ margin-left:1.5em;
75
+ }
76
+
77
+ .admin_table td.value li {
78
+ line-height:1em;
79
+ margin-top:8px;
80
+ margin-left:0;
81
+ text-indent:-0.25em;
82
+ }
83
+
84
+ .admin_table td.value .detail {
85
+ font-size:11px;
86
+ color:#666;
87
+ }
88
+
89
+ .admin_table td .action_link {
90
+ float:right;
91
+ font-size:11px;
92
+ }
93
+
94
+ .admin_table p.status {
95
+ font-weight:bold;
96
+ }
97
+
98
+ .admin_table p.closed {
99
+ color:Red;
100
+ }
101
+
102
+ .admin_table p.claimed {
103
+ color:Green;
104
+ }
105
+
106
+ .admin_table .obscured {
107
+ background-color:Black;
108
+ padding:2px 6px;
109
+ }
110
+
111
+ .admin_table .obscured:hover {
112
+ background-color:#eee;
113
+ }
114
+
115
+ .admin_actions {
116
+ width: 100%;
117
+ background-color: #fffeee;
118
+ border: 1px #e5e5e5 solid;
119
+ margin-bottom: 10px;
120
+ }
121
+
122
+ .admin_actions th {
123
+ border: 1px #e5e5e5 solid;
124
+ font-weight:bold;
125
+ }
126
+
127
+ .admin_actions td {
128
+ padding: 5px;
129
+ }
130
+
131
+ .admin_actions td a {
132
+ text-decoration: none;
133
+ display:block;
134
+ display:inline-block;
135
+ width: 100%;
136
+ }
137
+
138
+ .admin_actions td a:hover {
139
+ text-decoration: underline;
140
+ }
141
+
142
+ .admin_table .expand_link {
143
+ float:right;
144
+ }
145
+
146
+ .admin_footer_edit {font-size:11px;margin-left:10px;margin-bottom:10px;font-weight:normal;height:20px;padding:5px;background-color:#feffef;border:solid 1px #e4e3c9;}
147
+
148
+ #subtabs {
149
+ margin-bottom: 1em;
150
+ }
151
+
152
+ #date_container {
153
+ margin-bottom: 1em;
154
+ font-weight: bold;
155
+ }
156
+
157
+ #totals {
158
+ border: 2px solid #ccc;
159
+ font-size: 24px;
160
+ font-weight: bold;
161
+ }
162
+
163
+ #totals td, th {
164
+ padding: 5px;
165
+ border: 1px solid #999;
166
+ }
167
+
168
+ .hourly.breakdown th {
169
+ text-align: center;
170
+ }
171
+
172
+ a {
173
+ text-decoration: none;
174
+ }
175
+
176
+ a:hover {
177
+ text-decoration: underline;
178
+ }
179
+
180
+ .admin_menu_item {
181
+ padding-left:15px;
182
+ padding-bottom:3px;
183
+ text-align:left;
184
+ width:90%;
185
+ border-right:1px solid #ccc;
186
+ }
187
+
188
+ .admin_menu_item_selected {
189
+ padding-left:15px;
190
+ text-align:left;
191
+ width:90%;
192
+ border-top:1px solid #ccc;
193
+ border-bottom:1px solid #ccc;
194
+ border-left:1px solid #ccc;
195
+ border-right:0px;
196
+ }
197
+
198
+ .admin_menu_item_selected a {
199
+ color:black;
200
+ }