tr8n 3.1.6 → 3.1.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ }