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.
@@ -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