tr8n 3.1.6 → 3.1.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- tr8n (3.1.6)
4
+ tr8n (3.1.7)
5
5
  coffee-script
6
6
  kaminari
7
7
  rails (>= 3.1.0)
@@ -0,0 +1,211 @@
1
+ /* General */
2
+
3
+ .flt_r {float:right}
4
+ .quiet {color:#888 !important;}
5
+ .strong {font-weight:bold}
6
+ .em {font-style:italic}
7
+ .small {font-size:11px}
8
+ .xsmall {font-size:10px}
9
+ .sub_heading {border-bottom:solid 1px #ddd;margin-bottom:3px;}
10
+ .notice_msg {color:darkorange;background:#feffef;padding:3px 5px;margin:0 0 3px 0}
11
+ .warning_msg {color:darkred;background:pink;padding:3px 5px;margin:0 0 3px 0}
12
+ .focus {background-color:#f1f5ff}
13
+ .highlight {background-color:#fefff1}
14
+ .highlight_hover:hover {background:#fefff1}
15
+ .nowrap {white-space:nowrap}
16
+ .underscore {border-bottom:solid 1px #eee}
17
+
18
+ .light_bevel_hr {height:0px;border:solid 1px #e1e5e8;border-bottom-color:#fff;}
19
+
20
+ .padding_0 {padding:0px !important;}
21
+ .padding_5 {padding:5px !important;}
22
+ .padding_10 {padding:10px !important;}
23
+ .padding_15 {padding:15px !important;}
24
+
25
+ /* Module Skins */
26
+
27
+ .basic .inner {padding:10px;}
28
+
29
+ .outset .inner {border:1px solid #D7D7D7;border-color:#e9e9e9 #cdcdcd #a4a4a4;border-width:1px 1px 2px;padding:10px;}
30
+ .outset b {background-image:url('rounded_corners_sprite.gif');}
31
+ .outset .tl {background-position: 0 -70px;}
32
+ .outset .tr {background-position: -10px -70px;}
33
+ .outset .bl {background-position: 0 -80px;}
34
+ .outset .br {background-position: -10px -80px;}
35
+
36
+ .inset .inner {border:1px solid #e1e5e8;border-color:#b1b3b7 #e1e5e8 #e1e5e8;border-width:2px 1px 1px;padding:10px;}
37
+ .inset b {background-image:url('rounded_corners_sprite.gif');}
38
+ .inset .tl {background-position: 0 -93px;}
39
+ .inset .tr {background-position: -10px -93px;}
40
+ .inset .bl {background-position: 0 -103px;}
41
+ .inset .br {background-position: -10px -103px;}
42
+
43
+ .rounded .inner {padding:10px;text-align:left;}
44
+ .rounded b {background-image:url('rounded_corners_sprite.gif');}
45
+ .rounded .tl {background-position: 0 -116px;}
46
+ .rounded .tr {background-position: -10px -116px;}
47
+ .rounded .bl {background-position: 0 -126px;}
48
+ .rounded .br {background-position: -10px -126px;}
49
+
50
+
51
+ /* Module Backgrounds */
52
+
53
+ .highlight_bevel {background:url('/images/highlight_bkgd.gif') repeat-x 0 bottom #fefff1}
54
+ .focus_bevel {background:url('/images/focus_bkgd.gif') repeat-x 0 bottom #edf2f8}
55
+ .success_bevel {background:url('/images/success_bkgd.gif') repeat-x 0 bottom #eefce7}
56
+
57
+
58
+ /* Module Headers */
59
+ .pagination_hd {border-bottom:solid 1px #ddd;padding:5px 0}
60
+
61
+ /* Module Body */
62
+
63
+
64
+ /* Module Footers */
65
+ .action_ft {background:#fbfbfb;border-top:solid 1px #eee;padding:15px 20px;}
66
+ .pagination_ft {border-top:solid 1px #ddd;padding:5px 0;margin-top:-1px;}
67
+
68
+
69
+ /* Forms */
70
+
71
+ .field {clear:both;padding:5px 0 7px 0;overflow:hidden;}
72
+ .field_hd {float:left;width:145px;text-align:right;color:#666;}
73
+ .field_bd {margin-left:165px;clear:right}
74
+ .field_section {float:left;margin-right:5px;color:#999;font-size:10px;}
75
+ .field_note {margin-top:5px;font-size:10px;color:#666;clear:both;}
76
+ .field_hint {float:right;font-size:10px;color:#666;width:170px;line-height:11px;font-weight:normal}
77
+
78
+ .xshort_input {width:50px}
79
+ .short_input {width:100px}
80
+ .medium_input {width:150px}
81
+ .long_input {width:200px}
82
+ .xlong_input {width:250px}
83
+ .full_width_input {width:98%}
84
+
85
+
86
+ /* Lists */
87
+
88
+ ol.simple_list li {list-style-type: decimal; margin-left:40px;}
89
+ ul.simple_list li {list-style-type:disc; margin-left:0px;padding:4px 0}
90
+
91
+ .nav_list,
92
+ .horiz_list,
93
+ .right_horiz_list {overflow:hidden;text-align:left}
94
+
95
+ .nav_list li {margin-top:-1px;border-top:solid 1px #ced2e4;padding:3px 5px;zoom:1}
96
+ .nav_list li:hover {background-color:#ebeef1}
97
+ .nav_list li a {text-decoration:none;}
98
+
99
+ .horiz_list li {margin-left:-11px;border-left:solid 1px #ccc;padding:0px 10px;margin-right:10px;float:left;}
100
+ .right_horiz_list li {margin-right:-11px;border-right:solid 1px #ccc;padding:0px 10px;margin-left:10px;float:left;}
101
+
102
+ .checklist li {overflow:hidden;padding:0px 0}
103
+ .checklist input {float:left;}
104
+ .checklist label {margin:0 0 5px 25px;display:block}
105
+
106
+ .segmented_list {overflow:hidden;}
107
+ .segmented_list li {padding:7px 0;border-bottom:solid 1px #eee;margin-bottom:-1px}
108
+
109
+ .block_list li {padding:3px 0}
110
+
111
+
112
+ /* Pagination */
113
+
114
+ .pagination {overflow:hidden;zoom:1}
115
+ .pagination li {padding:0 3px;margin-right:2px;float:left;font-weight:bold;}
116
+
117
+
118
+
119
+ /* Buttons */
120
+
121
+ .btn {position:relative;border:0;padding:0;margin:0 2px 0 -2px;cursor:pointer;overflow:visible;background:transparent url('/images/site_sprite.gif') no-repeat right -100px;font-size:11px;font-weight:bold;text-align:center;font-family:Arial}
122
+ .btn span {position:relative;display:block;white-space:nowrap;background:transparent url('/images/site_sprite.gif') no-repeat left top;}
123
+ button::-moz-focus-inner {border:none;}
124
+ @media screen and (-webkit-min-device-pixel-ratio:0) {
125
+ .btn span {margin-top:-1px;}
126
+ }
127
+ a.btn {display:block;display:-moz-inline-box;display:inline-block;vertical-align:middle}
128
+ a.btn span {display:block;margin-top:0px}
129
+
130
+ /* Button Skins */
131
+
132
+ .button {-webkit-border-radius:2px;-moz-border-radius:2px;border-radius:2px;-webkit-box-shadow: rgba(0, 0, 0, 0.246094) 0px 1px 3px;-moz-box-shadow: rgba(0, 0, 0, 0.246094) 0px 1px 3px;background-color: #222;border-bottom: 1px solid rgba(0, 0, 0, 0.246094);color: white !important;cursor: pointer;display: inline-block;font-size: 13px;font-weight: bold;line-height: 1;overflow: visible;padding: 5px 15px 6px;position: relative;text-decoration: none !important;width: auto;}
133
+
134
+ .super.button {background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAeCAYAAADtlXTHAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAABYSURBVHjaZM27EcAgDANQSzZZgP0XpKLh20BM7mjS6J7kwrrWEuScgZQS2HsXjjHEdaqytfZ4kLXWU81lruAK9wqWUuBVvni3n+4Pc9nRnFOUZFQAcQswAI/sUZSGPd0tAAAAAElFTkSuQmCC) repeat-x 0 bottom;background-position:0 bottom;border: 1px solid rgba(0, 0, 0, 0.246094);font-size: 12px;padding: 0px;}
135
+ .super.button span {border-top: 1px solid rgba(255, 255, 255, 0.199219);display: block;line-height: 1;padding: 4px 15px 6px;}
136
+
137
+ .green.button {background-color: #91BD09;}
138
+ .green.button:hover {background-color:#749a02}
139
+
140
+ .blue.button {background-color:#5689c0}
141
+ .blue.button:hover {background-color:#4a77a8}
142
+
143
+ .large.super.button span {padding: 7px 20px 9px;font-size:13px;}
144
+ .xlarge.super.button span {padding: 8px 20px 10px;font-size:16px;}
145
+
146
+ /* Icons */
147
+
148
+ .icn {background:url(/images/icon_sprite.gif) no-repeat 0 0;}
149
+
150
+
151
+
152
+
153
+ /* Tabs */
154
+
155
+ .tab_nav {list-style-type:none;overflow:auto;margin-bottom:0px !important;position:relative}
156
+ .tab_nav li {float:left;margin-right:2px;cursor:pointer;}
157
+ .tab_nav li a {display:block;padding:6px 10px 6px 10px;}
158
+
159
+ /* Tables */
160
+
161
+ .data_table {padding:0;width:auto;margin:0}
162
+ .data_table td, .data_table th {vertical-align:top;padding:1px 0px 2px 0px}
163
+ .data_table th {width:115px;color:#777;font-weight:normal;padding-right:6px}
164
+
165
+ .data_table.small th {width:70px}
166
+
167
+ .segmented_table {width:100%;}
168
+ .segmented_table td {border-bottom:solid 1px #eee;padding:10px 5px}
169
+ .segmented_table .last td {border:none}
170
+
171
+ .skinny_cells td {padding:5px}
172
+ .fat_cells td {padding:10px 5px}
173
+
174
+ .txt_c {text-align:center;}
175
+ .txt_l {text-align:left;}
176
+ .txt_r {text-align:right;}
177
+ .txt_t {vertical-align:top;}
178
+ .txt_b {vertical-align:bottom;}
179
+ .txt_m {vertical-align:middle;}
180
+
181
+ .min_cell_width {width:1%}
182
+ .max_cell_width {width:99%}
183
+
184
+ .mrgn_v {margin:10px 0}
185
+ .mrgn_h {margin:0 10px}
186
+
187
+ /* Media Block */
188
+
189
+ .media {overflow:hidden;_overflow:visible; zoom:1;}
190
+ .media .img {float:left;margin-right: 10px;}
191
+ .media .img img {display:block;}
192
+ .media .imgExt {float:right; margin-left: 10px;}
193
+
194
+
195
+
196
+
197
+ /* Home */
198
+
199
+ .home_banner {background:url('/images/bubbles_bkgd.jpg');-webkit-border-radius:5px 5px 0 0;-moz-border-radius:5px 5px 0 0;border-radius:5px 5px 0 0;padding:50px 25px 0px 25px;height:220px;border-bottom:solid 10px #c2d6eb}
200
+ .home_banner h1 {font:normal bold 45px Arial, Helvetica, sans-serif;color:#fff;text-shadow:0 -1px 1px #000;letter-spacing:-2px}
201
+ .home_banner h2 {font:normal normal 24px Arial, Helvetica, sans-serif;color:#ccc;text-shadow:0 -1px 1px #000;width:520px;}
202
+
203
+
204
+ .benefit_details {line-height:20px;height:70px;}
205
+ .page_form {margin:0 50px}
206
+
207
+ .tr8n {
208
+ width:auto !important;
209
+ overflow:hidden !important
210
+ }
211
+
@@ -0,0 +1,143 @@
1
+ @mixin shadow($info) {
2
+ text-shadow:$info;
3
+ -moz-text-shadow:$info;
4
+ -webkit-text-shadow:$info;
5
+ }
6
+
7
+ @mixin rounded-corners($radius) {
8
+ border-radius: $radius;
9
+ -moz-border-radius: $radius;
10
+ -webkit-border-radius: $radius;
11
+ }
12
+
13
+ body {margin:0;padding:0;font:normal normal 12px Arial, Helvetica, sans-serif;text-align:left;background:#f5f5f5;color:#444;}
14
+
15
+ h1,h2,h3,h4,h5,h6 {margin:0 0 5px 0;padding:0;line-height: 1em;}
16
+ h1,.h1 {font:normal normal 35px Georgia, serif;color:#424c56;letter-spacing:-1px;}
17
+ h2,.h2 {font: normal normal normal 24px/normal Arial, Helvetica, sans-serif;color:#666;margin:0 0 8px 0;letter-spacing:-1px;}
18
+ h3,.h3 {font: normal normal bold 18px/normal Arial, Helvetica, sans-serif;color:#555;margin:0 0 8px 0;padding-bottom:5px;}
19
+ h4,.h4 {font:normal normal 14px Arial, Helvetica, sans-serif;color:#444;padding:6px;}
20
+ h5,.h5 {font:normal bold 11px Arial, Helvetica, sans-serif;color:#999}
21
+ h6,.h6 {font:normal bold 11px Arial, Helvetica, sans-serif;color:#444}
22
+
23
+
24
+ a {color:#3B5998;text-decoration: none;outline:none}
25
+ a:focus, a:hover {text-decoration: underline }
26
+ a:visited {color:#3B5998;}
27
+
28
+ p {margin:0 0 10px 0;}
29
+ table {border-collapse:collapse;border-spacing:0}
30
+ table,ul,ol,dt,dl,dd {padding:0;margin:0;list-style-type:none}
31
+ td,th {vertical-align:top}
32
+ img {vertical-align:middle;border:none}
33
+ input, select, textarea {vertical-align:middle;border:solid 1px #eee;border-color:#bbb #eee #eee #bbb;border-width:1px;font:normal normal 11px Arial, Helvetica, sans-serif;color:#444;outline:none;padding:3px;}
34
+ select {padding:2px;}
35
+ input[type=checkbox],
36
+ input[type=radio],
37
+ input[type=file],
38
+ checkbox,
39
+ radio {border:none;padding:0;}
40
+
41
+
42
+ /* Page Template */
43
+
44
+ .page_fixed {width:1000px;margin:0 auto;}
45
+ .page_elastic {width:auto;margin:0;}
46
+ .page_fluid {max-width:1100px;min-width:925px;_width:960px;margin:0 auto;padding:0 25px;}
47
+
48
+ .page_body,
49
+ .page_body .main_col {overflow:hidden;_overflow:visible;_zoom:1;}
50
+ .page_body .left_col {float:left; width:250px;_margin-right:-3px;}
51
+ .page_body .right_col {float:right; width: 300px;_margin-left:-3px;}
52
+
53
+
54
+ /* Header */
55
+
56
+ .page_head {background:#fff;border-bottom: 1px solid #DDD;border-top: 4px solid #6699cc;margin-bottom: 15px;padding: 5px 15px 2px;}
57
+ .logo a {
58
+ font-family:Arial;
59
+ color:#424c56;
60
+ text-decoration:none;
61
+ @include shadow(2px 3px 3px 2px rgba(0,0,0,0.6));
62
+ }
63
+ .logo a:hover {color:#000}
64
+ .top_nav {padding-top:13px;}
65
+
66
+ /* Grids */
67
+
68
+ .line, .last_unit {overflow:hidden;_overflow:visible;_zoom:1; }
69
+ .unit {float:left;_zoom:1;}
70
+ .size_1of1 {float:none;}
71
+ .size_1of2 {width:50%;}
72
+ .size_1of3 {width:33.33333%;}
73
+ .size_2of3 {width:66.66666%;}
74
+ .size_1of4 {width:25%;}
75
+ .size_3of4 {width:75%;}
76
+ .size_1of5 {width:20%;}
77
+ .size_2of5 {width:40%;}
78
+ .size_3of5 {width:60%;}
79
+ .size_4of5 {width:80%;}
80
+ .last_unit {float:none;_position:relative;_left:-3px;_margin-right:-3px;width:auto;}
81
+
82
+
83
+ /* Page Content */
84
+
85
+ .content_module {margin:0 10px 10px;}
86
+ .content_inner {
87
+ border:1px solid #D7D7D7;
88
+ border-color:#e9e9e9 #cdcdcd #a4a4a4;
89
+ border-width:1px 1px 2px;
90
+ background:#fff;
91
+ @include rounded-corners(10px);
92
+ }
93
+
94
+
95
+
96
+ .content_hd,
97
+ .content_bd,
98
+ .content_ft {overflow:hidden;zoom:1;padding:25px}
99
+
100
+
101
+
102
+ /* Module */
103
+
104
+ .module {margin:10px;}
105
+ .hd,.bd,.ft {overflow:hidden;_overflow:visible;_zoom:1;}
106
+ .inner {position:relative;}
107
+
108
+
109
+ /* Rounded Corners */
110
+
111
+ .tl, .tr, .bl, .br {height:10px; width:10px;position:absolute;}
112
+ .tl {background-position: left top;left:0}
113
+ .tr {background-position: right top;}
114
+ .bl {background-position: left bottom;left:0}
115
+ .br {background-position: right bottom;}
116
+ .br,.tr {right:0}
117
+ .tr,.tl {overflow:hidden;margin-bottom:-32000px;}
118
+ .bl,.br {bottom:0}
119
+
120
+
121
+ /* Complex Module */
122
+
123
+ .complex {overflow:visible;margin: 10px 20px 20px 10px; background-position:left top;}
124
+ .complex .inner {right:-10px; bottom:-10px; background-position:right bottom;padding:0 10px 10px 0;}
125
+ .complex .tl, .complex .br {display:none;}
126
+ .complex .bl {bottom:-10px;}
127
+ .complex .tr {right:-10px;}
128
+
129
+
130
+ /* Media Block */
131
+
132
+ .media {overflow:auto;zoom:1}
133
+ .media .thumb {width:100px;float:left;}
134
+ .media .desc {margin-left:110px;}
135
+
136
+
137
+ /* Clear Floats */
138
+ .clearfix:after {visibility: hidden;display: block;font-size: 0;content: " ";clear: both;height: 0;}
139
+ .clearfix {display: inline-block; }
140
+ /* start commented backslash hack \*/
141
+ * html .clearfix {height: 1%;}
142
+ .clearfix {display:block;}
143
+ /* close commented backslash hack */
@@ -61,28 +61,6 @@ class Tr8n::LanguageRule < ActiveRecord::Base
61
61
  dependency
62
62
  end
63
63
 
64
- # {"locale"=>"ru", "label"=>"{count} сообщения", "rank"=>1, "rules"=>[
65
- # {"token"=>"count", "type"=>"number", "definition"=>
66
- # {"multipart"=>true, "part1"=>"ends_in", "value1"=>"2,3,4", "operator"=>"and", "part2"=>"does_not_end_in", "value2"=>"12,13,14"}
67
- # }
68
- # ]
69
- # }
70
-
71
- def self.for_definition(lang, translator, type, definition, opts = {})
72
- opts[:force_create] ||= false
73
-
74
- rule_class = Tr8n::Config.language_rule_dependencies[type]
75
- return if rule_class == nil # unsupported rule type, skip this completely
76
-
77
- rule_class.for(lang).each do |rule|
78
- return rule if rule.definition == definition
79
- end
80
-
81
- if opts[:force_create]
82
- rule_class.create(:language => lang, :translator => translator, :definition => definition)
83
- end
84
- end
85
-
86
64
  # TDOD: switch to using keyword
87
65
  def self.dependency
88
66
  raise Tr8n::Exception.new("This method must be implemented in the extending rule")
@@ -102,13 +80,6 @@ class Tr8n::LanguageRule < ActiveRecord::Base
102
80
  sanitize_values(values).join(", ")
103
81
  end
104
82
 
105
- def to_api_hash
106
- {
107
- :type => self.class.keyword,
108
- :definition => definition
109
- }
110
- end
111
-
112
83
  def evaluate(token_value)
113
84
  raise Tr8n::Exception.new("This method must be implemented in the extending rule")
114
85
  end
@@ -149,4 +120,35 @@ class Tr8n::LanguageRule < ActiveRecord::Base
149
120
  Tr8n::Cache.delete("language_rule_#{id}")
150
121
  end
151
122
 
123
+ ###############################################################
124
+ ## Synchronization Methods
125
+ ###############################################################
126
+ def to_sync_hash(token)
127
+ {
128
+ "token" => token,
129
+ "type" => self.class.keyword,
130
+ "definition" => definition
131
+ }
132
+ end
133
+
134
+ # {"locale"=>"ru", "label"=>"{count} сообщения", "rank"=>1, "rules"=>[
135
+ # {"token"=>"count", "type"=>"number", "definition"=>
136
+ # {"multipart"=>true, "part1"=>"ends_in", "value1"=>"2,3,4", "operator"=>"and", "part2"=>"does_not_end_in", "value2"=>"12,13,14"}
137
+ # }
138
+ # ]
139
+ # }
140
+
141
+ def self.create_from_sync_hash(lang, translator, rule_hash, opts = {})
142
+ return unless rule_hash["token"] and rule_hash["type"] and rule_hash["definition"]
143
+
144
+ rule_class = Tr8n::Config.language_rule_dependencies[rule_hash["type"]]
145
+ return unless rule_class # unsupported rule type, skip this completely
146
+
147
+ rule_class.for(lang).each do |rule|
148
+ return rule if rule.definition == rule_hash["definition"]
149
+ end
150
+
151
+ rule_class.create(:language => lang, :translator => translator, :definition => rule_hash["definition"])
152
+ end
153
+
152
154
  end
@@ -23,25 +23,73 @@
23
23
 
24
24
  class Tr8n::SyncLog < ActiveRecord::Base
25
25
 
26
- def self.sync
27
- log = Tr8n::SyncLog.create(:started_at => Time.now)
28
- key_count = 0
26
+ def self.sync(opts = {})
27
+ sync_log = Tr8n::SyncLog.create(:started_at => Time.now)
28
+
29
29
  translation_count = 0
30
30
  payload = []
31
- Tr8n::TranslationKey.find_each(:batch_size => Tr8n::Config.synchronization_batch_size) do |key|
32
- key_count += 1
33
-
34
- payload << key.to_api_hash
31
+ batch_count = 0
32
+ total_key_count = 0
33
+
34
+ log("Begin synchronization process...")
35
+ log("Registering keys...")
36
+
37
+ conditions = "synced_at is null or updated_at > synced_at"
38
+ conditions = nil if opts[:force]
39
+
40
+ # STDOUT.sync = true
41
+
42
+ Tr8n::TranslationKey.find_each(:conditions => conditions, :batch_size => Tr8n::Config.synchronization_batch_size) do |key|
43
+ total_key_count += 1
44
+ sync_hash = key.to_sync_hash
45
+ payload << sync_hash
35
46
 
36
- puts "*"
47
+ key.mark_as_synced!
37
48
 
38
- if key_count % Tr8n::Config.synchronization_batch_size == 0
49
+ # if sync_hash["label"] == "you have {count||message}"
50
+ # payload << sync_hash
51
+ # end
52
+
53
+ if payload.size == Tr8n::Config.synchronization_batch_size
54
+ # pp "Sending #{batch_count+1} batch of #{Tr8n::Config.synchronization_batch_size} keys..."
55
+ batch_count += 1
39
56
  exchange(payload)
57
+ payload = []
40
58
  end
41
59
  end
42
- log.update_attributes(:finished_at => Time.now)
60
+
61
+ if payload.size > 0
62
+ # pp "Sending final batch..."
63
+ batch_count += 1
64
+ exchange(payload, opts)
65
+ end
66
+
67
+ sync_log.keys_sent = total_key_count
68
+
69
+ log("Sent #{total_key_count} keys in #{batch_count} batches.")
70
+
71
+ batch_count = 0
72
+ total_key_count = 0
73
+
74
+ unless opts[:force]
75
+ log("Downloading translations...")
76
+
77
+ key_count = download
78
+ while key_count > 0
79
+ batch_count += 1
80
+ total_key_count += key_count
81
+ key_count = download(opts)
82
+ end
83
+ log("Downloaded #{total_key_count} keys in #{batch_count} batches.")
84
+ end
85
+
86
+ sync_log.keys_received = total_key_count
87
+ sync_log.finished_at = Time.now
88
+ sync_log.save
89
+
43
90
  rescue Exception => ex
44
91
  pp ex.message
92
+ pp ex.backtrace
45
93
  end
46
94
 
47
95
  def self.access_token
@@ -49,28 +97,75 @@ class Tr8n::SyncLog < ActiveRecord::Base
49
97
  uri = URI.parse("#{Tr8n::Config.synchronization_server}/platform/oauth/request_token?client_id=#{Tr8n::Config.synchronization_key}&client_secret=#{Tr8n::Config.synchronization_secret}&grant_type=client_credentials")
50
98
  response = Net::HTTP.get_response(uri)
51
99
  data = JSON.parse(response.body)
52
- raise Tr8n::Exception.new("Failed to get access token") unless data["access_toke"]
100
+ raise Tr8n::Exception.new("Failed to get access token") unless data["access_token"]
53
101
  data["access_token"]
54
102
  end
55
103
  end
56
104
 
57
- def self.exchange(payload)
58
- uri = URI.parse("#{Tr8n::Config.synchronization_server}/api/sync")
105
+ def self.exchange(payload, opts = {})
106
+ uri = URI.parse("#{Tr8n::Config.synchronization_server}/api/application/sync")
107
+ params = {:method => "register", :batch_size => Tr8n::Config.synchronization_batch_size, :translation_keys => payload}
59
108
 
60
109
  req = Net::HTTP::Post.new(uri.path)
61
- req.body = JSON.generate({:translation_keys => payload})
62
110
  req["Content-Type"] = "application/json"
63
111
  req["Authorization"] = "Bearer #{access_token}"
112
+ req.body = params.to_json
64
113
 
65
- http = Net::HTTP.new(uri.host, uri.port)
66
- response = http.start {|htt| htt.request(req)}
67
- raise Tr8n::Exception.new("Synchronization failed") unless response.status == 200
114
+ # pp payload
68
115
 
69
- data = JSON.parse(response.body)
116
+ response = Net::HTTP.start(uri.host, uri.port) do |http|
117
+ http.request(req)
118
+ end
119
+
120
+ if response.is_a?(Net::HTTPInternalServerError)
121
+ raise Exception.new("Failed to synchronize keys: #{response.body}")
122
+ end
123
+
124
+ raise Tr8n::Exception.new("Synchronization failed") unless response.is_a?(Net::HTTPOK)
125
+
126
+ data = HashWithIndifferentAccess.new(JSON.parse(response.body))
127
+ # pp data
128
+
129
+ data[:translation_keys].each do |tkey_hash|
130
+ # pp tkey_hash
131
+ Tr8n::TranslationKey.create_from_sync_hash(tkey_hash, Tr8n::Config.system_translator)
132
+ end
133
+ end
134
+
135
+ def self.download(opts = {})
136
+ uri = URI.parse("#{Tr8n::Config.synchronization_server}/api/application/sync")
137
+ params = {:method=>"download", :batch_size => Tr8n::Config.synchronization_batch_size}
138
+ params[:force] = true if opts[:force]
139
+
140
+ req = Net::HTTP::Post.new(uri.path)
141
+ req["Content-Type"] = "application/json"
142
+ req["Authorization"] = "Bearer #{access_token}"
143
+ req.body = params.to_json
144
+
145
+ response = Net::HTTP.start(uri.host, uri.port) do |http|
146
+ http.request(req)
147
+ end
148
+
149
+ if response.is_a?(Net::HTTPInternalServerError)
150
+ raise Exception.new("Failed to download translations: #{response.body}")
151
+ end
152
+
153
+ raise Tr8n::Exception.new("Synchronization failed") unless response.is_a?(Net::HTTPOK)
154
+
155
+ data = HashWithIndifferentAccess.new(JSON.parse(response.body))
156
+ # pp data
70
157
 
71
158
  data[:translation_keys].each do |tkey_hash|
72
- Tr8n::TranslationKey.create_from_api_hash(tkey_hash, Tr8n::Config.system_translator)
159
+ # pp tkey_hash
160
+ tkey, translations = Tr8n::TranslationKey.create_from_sync_hash(tkey_hash, Tr8n::Config.system_translator)
161
+ tkey.mark_as_synced!
73
162
  end
163
+
164
+ data[:translation_keys].size
165
+ end
166
+
167
+ def self.log(msg)
168
+ pp "#{Time.now}: #{msg}"
74
169
  end
75
170
 
76
171
  end