translate-rails3-plus 0.0.7 → 0.0.8
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.
- checksums.yaml +7 -0
- data/VERSION +1 -1
- data/app/helpers/translate_helper.rb +53 -53
- data/app/views/layouts/translate.html.erb +495 -495
- data/app/views/translate/_string_form.html.erb +35 -35
- data/app/views/translate/index.html.erb +96 -96
- data/lib/translate.rb +1 -1
- metadata +9 -21
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: a5dcc53ed9f5892df58152563f29dc218b406dee
|
4
|
+
data.tar.gz: 2cebfeeebcb457a68d26b2b44fb76ef67e5a2689
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: dc935d6c7812502a878dc2e2b8663a35122d8ea8d83b6ea8d03391313505d6cd90b7be472fc19d2f8df0f411380d4834bd7ebdf9ad028d113dae3109c3937283
|
7
|
+
data.tar.gz: 6a46f9196c386b9dca7fa1e1d79f8c3581782dc36311186e11bfb83a9ca080e5d6abb94fdb7e85d74c30a2c0735b759b67332e8ac38844567231787959c89932
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.8
|
@@ -1,53 +1,53 @@
|
|
1
|
-
module TranslateHelper
|
2
|
-
|
3
|
-
def simple_filter(labels, param_name = 'filter', selected_value = nil)
|
4
|
-
selected_value ||= params[param_name]
|
5
|
-
filter = []
|
6
|
-
labels.each do |item|
|
7
|
-
if item.is_a?(Array)
|
8
|
-
type, label = item
|
9
|
-
else
|
10
|
-
type = label = item
|
11
|
-
end
|
12
|
-
if type.to_s == selected_value.to_s
|
13
|
-
filter << "<i>#{label}</i>"
|
14
|
-
else
|
15
|
-
link_params = params.merge({param_name.to_s => type})
|
16
|
-
link_params.merge!({"page" => nil}) if param_name.to_s != "page"
|
17
|
-
filter << link_to(label, link_params)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
filter.join(" | ")
|
21
|
-
end
|
22
|
-
|
23
|
-
def n_lines(text, line_size)
|
24
|
-
n_lines = 1
|
25
|
-
if text.present?
|
26
|
-
n_lines = text.split("\n").size
|
27
|
-
if n_lines == 1 && text.length > line_size
|
28
|
-
n_lines = text.length / line_size + 1
|
29
|
-
end
|
30
|
-
end
|
31
|
-
n_lines
|
32
|
-
end
|
33
|
-
|
34
|
-
def translate_javascript_includes
|
35
|
-
if File.exists?(File.join(Rails.root, "public", "javascripts", "prototype.js"))
|
36
|
-
javascript_include_tag("prototype.js")
|
37
|
-
else
|
38
|
-
javascript_include_tag("http://ajax.googleapis.com/ajax/libs/prototype/1.7.0.0/prototype.js")
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
def translate_link(key, text, from, to)
|
43
|
-
method = if Translate.app_id
|
44
|
-
'getBingTranslation'
|
45
|
-
elsif Translate.api_key
|
46
|
-
'getGoogleTranslation'
|
47
|
-
else
|
48
|
-
nil
|
49
|
-
end
|
50
|
-
return nil unless method
|
51
|
-
link_to_function 'Auto Translate', "#{method}('#{key}', \"#{escape_javascript(text)}\", '#{from}', '#{to}')", :style => 'padding: 0; margin: 0;'
|
52
|
-
end
|
53
|
-
end
|
1
|
+
module TranslateHelper
|
2
|
+
|
3
|
+
def simple_filter(labels, param_name = 'filter', selected_value = nil)
|
4
|
+
selected_value ||= params[param_name]
|
5
|
+
filter = []
|
6
|
+
labels.each do |item|
|
7
|
+
if item.is_a?(Array)
|
8
|
+
type, label = item
|
9
|
+
else
|
10
|
+
type = label = item
|
11
|
+
end
|
12
|
+
if type.to_s == selected_value.to_s
|
13
|
+
filter << "<i>#{label}</i>"
|
14
|
+
else
|
15
|
+
link_params = params.merge({param_name.to_s => type})
|
16
|
+
link_params.merge!({"page" => nil}) if param_name.to_s != "page"
|
17
|
+
filter << link_to(label, link_params)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
filter.join(" | ")
|
21
|
+
end
|
22
|
+
|
23
|
+
def n_lines(text, line_size)
|
24
|
+
n_lines = 1
|
25
|
+
if text.present?
|
26
|
+
n_lines = text.split("\n").size
|
27
|
+
if n_lines == 1 && text.length > line_size
|
28
|
+
n_lines = text.length / line_size + 1
|
29
|
+
end
|
30
|
+
end
|
31
|
+
n_lines
|
32
|
+
end
|
33
|
+
|
34
|
+
def translate_javascript_includes
|
35
|
+
if File.exists?(File.join(Rails.root, "public", "javascripts", "prototype.js"))
|
36
|
+
javascript_include_tag("prototype.js")
|
37
|
+
else
|
38
|
+
javascript_include_tag("http://ajax.googleapis.com/ajax/libs/prototype/1.7.0.0/prototype.js")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def translate_link(key, text, from, to)
|
43
|
+
method = if Translate.app_id
|
44
|
+
'getBingTranslation'
|
45
|
+
elsif Translate.api_key
|
46
|
+
'getGoogleTranslation'
|
47
|
+
else
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
return nil unless method
|
51
|
+
link_to_function 'Auto Translate', "#{method}('#{key}', \"#{escape_javascript(text)}\", '#{from}', '#{to}')", :style => 'padding: 0; margin: 0;'
|
52
|
+
end
|
53
|
+
end
|
@@ -1,495 +1,495 @@
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
2
|
-
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
-
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
4
|
-
<head>
|
5
|
-
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
6
|
-
<title><%= h(@page_title) %></title>
|
7
|
-
|
8
|
-
<%= translate_javascript_includes %>
|
9
|
-
<script type="text/javascript">
|
10
|
-
|
11
|
-
// Return elements which are in A but not in arg0 through argn
|
12
|
-
Array.prototype.diff =
|
13
|
-
function() {
|
14
|
-
var a1 = this;
|
15
|
-
var a = a2 = null;
|
16
|
-
var n = 0;
|
17
|
-
while(n < arguments.length) {
|
18
|
-
a = [];
|
19
|
-
a2 = arguments[n];
|
20
|
-
var l = a1.length;
|
21
|
-
var l2 = a2.length;
|
22
|
-
var diff = true;
|
23
|
-
for(var i=0; i<l; i++) {
|
24
|
-
for(var j=0; j<l2; j++) {
|
25
|
-
if (a1[i] === a2[j]) {
|
26
|
-
diff = false;
|
27
|
-
break;
|
28
|
-
}
|
29
|
-
}
|
30
|
-
diff ? a.push(a1[i]) : diff = true;
|
31
|
-
}
|
32
|
-
a1 = a;
|
33
|
-
n++;
|
34
|
-
}
|
35
|
-
return a.unique();
|
36
|
-
};
|
37
|
-
|
38
|
-
// Return new array with duplicate values removed
|
39
|
-
Array.prototype.unique =
|
40
|
-
function() {
|
41
|
-
var a = [];
|
42
|
-
var l = this.length;
|
43
|
-
for(var i=0; i<l; i++) {
|
44
|
-
for(var j=i+1; j<l; j++) {
|
45
|
-
// If this[i] is found later in the array
|
46
|
-
if (this[i] === this[j])
|
47
|
-
j = ++i;
|
48
|
-
}
|
49
|
-
a.push(this[i]);
|
50
|
-
}
|
51
|
-
return a;
|
52
|
-
};
|
53
|
-
|
54
|
-
|
55
|
-
var source_ids = [];
|
56
|
-
|
57
|
-
function googleCallback(response) {
|
58
|
-
if (response.error) {
|
59
|
-
alert(response.error.message);
|
60
|
-
return;
|
61
|
-
}
|
62
|
-
var result_text = response.data.translations[0].translatedText.gsub(/__(.+)__/, function(match) {
|
63
|
-
return '{{' + match[1] + '}}';
|
64
|
-
});
|
65
|
-
var id = source_ids.shift();
|
66
|
-
if (id) {
|
67
|
-
Form.Element.setValue(id, result_text);
|
68
|
-
}
|
69
|
-
}
|
70
|
-
|
71
|
-
function getGoogleTranslation(id, text, from_language, to_language) {
|
72
|
-
source_ids.push(id);
|
73
|
-
text = text.replace(/\{\{/, '__').replace(/\}\}/, '__');
|
74
|
-
var s = document.createElement('script'), api_key = '<%= Translate.api_key %>';
|
75
|
-
s.type = 'text/javascript';
|
76
|
-
s.src = 'https://www.googleapis.com/language/translate/v2?key=' + api_key + '&source=' +
|
77
|
-
from_language + '&target=' + to_language + '&callback=googleCallback&q=' + text;
|
78
|
-
document.getElementsByTagName("head")[0].appendChild(s);
|
79
|
-
}
|
80
|
-
|
81
|
-
function bingCallback(text) {
|
82
|
-
var id = source_ids.shift();
|
83
|
-
if (text && id) {
|
84
|
-
var result_text = text.gsub(/__(.+)__/, function(match) {
|
85
|
-
return '{{' + match[1] + '}}';
|
86
|
-
});
|
87
|
-
Form.Element.setValue(id, result_text);
|
88
|
-
}
|
89
|
-
}
|
90
|
-
|
91
|
-
function getBingTranslation(id, text, from_language, to_language) {
|
92
|
-
source_ids.push(id);
|
93
|
-
text = text.replace(/\{\{/, '__').replace(/\}\}/, '__');
|
94
|
-
var s = document.createElement("script"), app_id = '<%= Translate.app_id %>';
|
95
|
-
s.type = 'text/javascript';
|
96
|
-
s.src = 'http://api.microsofttranslator.com/V2/Ajax.svc/Translate?oncomplete=bingCallback&appId=' +
|
97
|
-
app_id + '&from=' + from_language + '&to=' + to_language + '&text=' + text;
|
98
|
-
document.getElementsByTagName("head")[0].appendChild(s);
|
99
|
-
}
|
100
|
-
|
101
|
-
function checkErrors()
|
102
|
-
{
|
103
|
-
var errors = []
|
104
|
-
$$('.translation-error').each(function(item) {
|
105
|
-
item.removeClassName("translation-error")
|
106
|
-
item.select('.error-text')[0].innerHTML = ""
|
107
|
-
});
|
108
|
-
|
109
|
-
$$('.single-translation').each(function(item) {
|
110
|
-
var val = item.select('.edit-field')[0].value
|
111
|
-
if( !val.blank() )
|
112
|
-
{
|
113
|
-
var patt1=/%\{[^\{\}]*\}/g;
|
114
|
-
var val_subs = val.match(patt1)
|
115
|
-
var key = item.select('.translation-text')[0].innerHTML
|
116
|
-
var key_subs = key.match(patt1)
|
117
|
-
if( val_subs == null ){ val_subs = [] }
|
118
|
-
if( key_subs == null ){ key_subs = [] }
|
119
|
-
if( val_subs.sort().join('') != key_subs.sort().join('') )
|
120
|
-
{
|
121
|
-
missing_subs = key_subs.diff( val_subs )
|
122
|
-
item.addClassName("translation-error");
|
123
|
-
errors.push( item )
|
124
|
-
item.select('.error-text')[0].innerHTML = "Missing substitution strings: " + missing_subs.join(', ')
|
125
|
-
}
|
126
|
-
}
|
127
|
-
});
|
128
|
-
return errors
|
129
|
-
}
|
130
|
-
|
131
|
-
function testAndSave()
|
132
|
-
{
|
133
|
-
var errors = checkErrors()
|
134
|
-
|
135
|
-
if( errors.length == 0 )
|
136
|
-
{
|
137
|
-
document.forms["translate_form"].submit();
|
138
|
-
}
|
139
|
-
else
|
140
|
-
{
|
141
|
-
alert( "Some translations have errors. Please review and correct errors before saving.")
|
142
|
-
}
|
143
|
-
}
|
144
|
-
|
145
|
-
/*
|
146
|
-
prototypeUtils.js from http://jehiah.com/
|
147
|
-
Licensed under Creative Commons.
|
148
|
-
version 1.0 December 20 2005
|
149
|
-
|
150
|
-
Contains:
|
151
|
-
+ Form.Element.setValue()
|
152
|
-
+ unpackToForm()
|
153
|
-
|
154
|
-
*/
|
155
|
-
|
156
|
-
/* Form.Element.setValue("fieldname/id","valueToSet") */
|
157
|
-
Form.Element.setValue = function(element,newValue) {
|
158
|
-
element_id = element;
|
159
|
-
element = $(element);
|
160
|
-
if (!element){element = document.getElementsByName(element_id)[0];}
|
161
|
-
if (!element){return false;}
|
162
|
-
var method = element.tagName.toLowerCase();
|
163
|
-
var parameter = Form.Element.SetSerializers[method](element,newValue);
|
164
|
-
}
|
165
|
-
|
166
|
-
Form.Element.SetSerializers = {
|
167
|
-
input: function(element,newValue) {
|
168
|
-
switch (element.type.toLowerCase()) {
|
169
|
-
case 'submit':
|
170
|
-
case 'hidden':
|
171
|
-
case 'password':
|
172
|
-
case 'text':
|
173
|
-
return Form.Element.SetSerializers.textarea(element,newValue);
|
174
|
-
case 'checkbox':
|
175
|
-
case 'radio':
|
176
|
-
return Form.Element.SetSerializers.inputSelector(element,newValue);
|
177
|
-
}
|
178
|
-
return false;
|
179
|
-
},
|
180
|
-
|
181
|
-
inputSelector: function(element,newValue) {
|
182
|
-
fields = document.getElementsByName(element.name);
|
183
|
-
for (var i=0;i<fields.length;i++){
|
184
|
-
if (fields[i].value == newValue){
|
185
|
-
fields[i].checked = true;
|
186
|
-
}
|
187
|
-
}
|
188
|
-
},
|
189
|
-
|
190
|
-
textarea: function(element,newValue) {
|
191
|
-
element.value = newValue;
|
192
|
-
},
|
193
|
-
|
194
|
-
select: function(element,newValue) {
|
195
|
-
var value = '', opt, index = element.selectedIndex;
|
196
|
-
for (var i=0;i< element.options.length;i++){
|
197
|
-
if (element.options[i].value == newValue){
|
198
|
-
element.selectedIndex = i;
|
199
|
-
return true;
|
200
|
-
}
|
201
|
-
}
|
202
|
-
}
|
203
|
-
}
|
204
|
-
|
205
|
-
function unpackToForm(data){
|
206
|
-
for (i in data){
|
207
|
-
Form.Element.setValue(i,data[i].toString());
|
208
|
-
}
|
209
|
-
}
|
210
|
-
|
211
|
-
</script>
|
212
|
-
|
213
|
-
|
214
|
-
<style type="text/css">
|
215
|
-
/*reset.css*/
|
216
|
-
/* v1.0 | 20080212 */
|
217
|
-
html, body, div, span, applet, object, iframe,
|
218
|
-
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
219
|
-
a, abbr, acronym, address, big, cite, code,
|
220
|
-
del, dfn, em, font, img, ins, kbd, q, s, samp,
|
221
|
-
small, strike, strong, sub, sup, tt, var,
|
222
|
-
b, u, i, center,
|
223
|
-
dl, dt, dd, ol, ul, li,
|
224
|
-
fieldset, form, label, legend,
|
225
|
-
table, caption, tbody, tfoot, thead, tr, th, td {
|
226
|
-
margin: 0;
|
227
|
-
padding: 0;
|
228
|
-
border: 0;
|
229
|
-
outline: 0;
|
230
|
-
font-size: 100%;
|
231
|
-
vertical-align: baseline;
|
232
|
-
background: transparent;
|
233
|
-
}
|
234
|
-
body {
|
235
|
-
line-height: 1;
|
236
|
-
}
|
237
|
-
ol, ul {
|
238
|
-
list-style: none;
|
239
|
-
}
|
240
|
-
blockquote, q {
|
241
|
-
quotes: none;
|
242
|
-
}
|
243
|
-
blockquote:before, blockquote:after,
|
244
|
-
q:before, q:after {
|
245
|
-
content: '';
|
246
|
-
content: none;
|
247
|
-
}
|
248
|
-
|
249
|
-
/* remember to define focus styles! */
|
250
|
-
:focus {
|
251
|
-
outline: 0;
|
252
|
-
}
|
253
|
-
|
254
|
-
/* remember to highlight inserts somehow! */
|
255
|
-
ins {
|
256
|
-
text-decoration: none;
|
257
|
-
}
|
258
|
-
del {
|
259
|
-
text-decoration: line-through;
|
260
|
-
}
|
261
|
-
|
262
|
-
/* tables still need 'cellspacing="0"' in the markup */
|
263
|
-
table {
|
264
|
-
border-collapse: collapse;
|
265
|
-
border-spacing: 0;
|
266
|
-
}
|
267
|
-
/*clear fix*/
|
268
|
-
.clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden;}
|
269
|
-
.clearfix{display:inline-block;}
|
270
|
-
html[xmlns] .clearfix {
|
271
|
-
display: block;
|
272
|
-
}
|
273
|
-
* html .clearfix{height:1%;}
|
274
|
-
/*start layout*/
|
275
|
-
body{
|
276
|
-
background:#fff;
|
277
|
-
color:#333;
|
278
|
-
font-size:75%;
|
279
|
-
font-family:Arial;
|
280
|
-
margin:2em auto;
|
281
|
-
line-height:1.5em;
|
282
|
-
}
|
283
|
-
textarea,input,select{
|
284
|
-
font-family:Arial;
|
285
|
-
font-size:1em;
|
286
|
-
}
|
287
|
-
h1{
|
288
|
-
color:#d46021;
|
289
|
-
font-size:2em;
|
290
|
-
margin-bottom:0.5em;
|
291
|
-
}
|
292
|
-
h2{
|
293
|
-
text-align:left;
|
294
|
-
color:#d46021;
|
295
|
-
font-size:1.3em;
|
296
|
-
padding-left:0;
|
297
|
-
}
|
298
|
-
a{
|
299
|
-
color:#2158C7;
|
300
|
-
}
|
301
|
-
div#container{
|
302
|
-
width:960px;
|
303
|
-
margin:0 auto;
|
304
|
-
font-size:1em;
|
305
|
-
}
|
306
|
-
/*paging*/
|
307
|
-
div.paging{
|
308
|
-
margin-bottom:1em;
|
309
|
-
text-align:left;
|
310
|
-
}
|
311
|
-
div.paging div{
|
312
|
-
border:solid 1px red;
|
313
|
-
margin:1em 1em 0;
|
314
|
-
padding:0.5em;
|
315
|
-
border:solid 1px #d5d6d5;
|
316
|
-
background:#f1f1f1;
|
317
|
-
}
|
318
|
-
ul.paging{
|
319
|
-
display:inline-block;
|
320
|
-
}
|
321
|
-
ul.paging li{
|
322
|
-
display:block;
|
323
|
-
margin:0.2em 0;
|
324
|
-
float:left;
|
325
|
-
}
|
326
|
-
ul.paging li.selected a{
|
327
|
-
color:#fff;
|
328
|
-
background:#2158C7;
|
329
|
-
font-weight:bold;
|
330
|
-
padding:0.5em 0.7em;
|
331
|
-
}
|
332
|
-
ul.paging li a{
|
333
|
-
display:inline-block;
|
334
|
-
line-height:1em;
|
335
|
-
padding:0.5em 0.5em;
|
336
|
-
}
|
337
|
-
/*forms filter*/
|
338
|
-
fieldset{
|
339
|
-
padding:1em;
|
340
|
-
margin:1em;
|
341
|
-
border:solid 2px #d46021;
|
342
|
-
}
|
343
|
-
legend{
|
344
|
-
font-size:1.2em;
|
345
|
-
font-weight:bold;
|
346
|
-
padding:0 1em;
|
347
|
-
padding-bottom:0.5em;
|
348
|
-
}
|
349
|
-
label{
|
350
|
-
font-weight:bold;
|
351
|
-
}
|
352
|
-
fieldset span{padding-right:0.5em;}
|
353
|
-
div#show-sort label,
|
354
|
-
div#languages label,
|
355
|
-
div#filter-pattern label{
|
356
|
-
display:inline-block;
|
357
|
-
width:100px;
|
358
|
-
line-height:2em;
|
359
|
-
}
|
360
|
-
div#show-sort select,
|
361
|
-
div#languages select,
|
362
|
-
div#filter-pattern select{
|
363
|
-
width:120px;
|
364
|
-
margin-right:0.5em;
|
365
|
-
}
|
366
|
-
div#show-sort input.text-default,
|
367
|
-
div#languages input.text-default,
|
368
|
-
div#filter-pattern input.text-default{
|
369
|
-
width:200px;
|
370
|
-
}
|
371
|
-
p.hits{
|
372
|
-
margin-top:1em;
|
373
|
-
}
|
374
|
-
/*translation edit*/
|
375
|
-
div.translations{
|
376
|
-
margin:1em;
|
377
|
-
padding:1em;
|
378
|
-
border:solid 2px #d46021;
|
379
|
-
}
|
380
|
-
div.translations h2{
|
381
|
-
margin-bottom:1em;
|
382
|
-
}
|
383
|
-
p.translate{
|
384
|
-
background:red;
|
385
|
-
border:solid 1px #d5d6d5;
|
386
|
-
background:#f1f1f1;
|
387
|
-
margin:0.5em;
|
388
|
-
padding:0.7em 0.5em 0.5em 1.5em;
|
389
|
-
}
|
390
|
-
div.translation{
|
391
|
-
padding: 11px;
|
392
|
-
border-bottom:solid 1px #d46021;
|
393
|
-
border-left: solid 1px #D46021;
|
394
|
-
margin:14px 12px 12px 19px;
|
395
|
-
}
|
396
|
-
div.translation input, div.translation textarea{
|
397
|
-
width:98%;
|
398
|
-
margin:1em 0;
|
399
|
-
display:inline-block;
|
400
|
-
padding:0.3em;
|
401
|
-
}
|
402
|
-
div.translation textarea{
|
403
|
-
height:50px;
|
404
|
-
}
|
405
|
-
div.translation em strong{
|
406
|
-
color:#333;
|
407
|
-
padding-right:0.5em;
|
408
|
-
}
|
409
|
-
p.translation em{
|
410
|
-
display:block;
|
411
|
-
font-size:0.8333em;
|
412
|
-
}
|
413
|
-
div.translation a{
|
414
|
-
padding:1em;
|
415
|
-
}
|
416
|
-
div.translation input.btnDefault{
|
417
|
-
margin:0 0 1em;
|
418
|
-
width:auto;
|
419
|
-
}
|
420
|
-
.focus-text{
|
421
|
-
font-weight:bold;
|
422
|
-
}
|
423
|
-
div.selected{
|
424
|
-
margin:12px 10px 12px 12px;
|
425
|
-
border-left:solid 8px #d46021;
|
426
|
-
border-right:solid 2px #d46021;
|
427
|
-
border-top:solid 2px #d46021;
|
428
|
-
background:#f1f1f1;
|
429
|
-
}
|
430
|
-
.display{display:block !important;}
|
431
|
-
/*feedback*/
|
432
|
-
div#notice, div#error {
|
433
|
-
font-size:1em;
|
434
|
-
margin:1em;
|
435
|
-
padding: 1em;
|
436
|
-
border: 1px solid red;
|
437
|
-
}
|
438
|
-
div#notice span, div#error span{
|
439
|
-
font-size:1.5em;
|
440
|
-
}
|
441
|
-
|
442
|
-
div#error {
|
443
|
-
background-color: #F3C6CC;
|
444
|
-
color: red;
|
445
|
-
}
|
446
|
-
div#notice {
|
447
|
-
border-color: #72A974;
|
448
|
-
color: #597B5C;
|
449
|
-
background-color: #BCFFBD;
|
450
|
-
}
|
451
|
-
.translation-error .edit-field
|
452
|
-
{
|
453
|
-
border: 1px solid red;
|
454
|
-
}
|
455
|
-
.error-text
|
456
|
-
{
|
457
|
-
color: red;
|
458
|
-
}
|
459
|
-
.big-locale
|
460
|
-
{
|
461
|
-
font-size: 32px;
|
462
|
-
color: red;
|
463
|
-
}
|
464
|
-
</style>
|
465
|
-
<script type="text/javascript">
|
466
|
-
onload = function (){
|
467
|
-
$$("div.translation input, div.translation textarea").each(function (e){
|
468
|
-
Event.observe(e,'focus', function (elm){
|
469
|
-
this.up(".single-translation").down(".translation-text").addClassName("focus-text");
|
470
|
-
this.up(".translation").addClassName("selected");
|
471
|
-
});
|
472
|
-
Event.observe(e,'blur', function (elm,e){
|
473
|
-
this.up(".single-translation").down(".translation-text").removeClassName("focus-text");
|
474
|
-
this.up(".translation").removeClassName("selected");
|
475
|
-
});
|
476
|
-
});
|
477
|
-
|
478
|
-
checkErrors()
|
479
|
-
}
|
480
|
-
</script>
|
481
|
-
</head>
|
482
|
-
<body>
|
483
|
-
<div id="container">
|
484
|
-
<% if @page_title -%><h1><%=h @page_title %></h1><% end -%>
|
485
|
-
<% [:notice, :error].each do |message| %>
|
486
|
-
<%if flash[message] %>
|
487
|
-
<div id="<%= message %>">
|
488
|
-
<span><%= h(flash[message]) if flash[message] %></span>
|
489
|
-
</div>
|
490
|
-
<% end %>
|
491
|
-
<% end %>
|
492
|
-
<%= yield %>
|
493
|
-
</div>
|
494
|
-
</body>
|
495
|
-
</html>
|
1
|
+
<?xml version="1.0" encoding="utf-8"?>
|
2
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
3
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
4
|
+
<head>
|
5
|
+
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
6
|
+
<title><%= h(@page_title) %></title>
|
7
|
+
|
8
|
+
<%= translate_javascript_includes %>
|
9
|
+
<script type="text/javascript">
|
10
|
+
|
11
|
+
// Return elements which are in A but not in arg0 through argn
|
12
|
+
Array.prototype.diff =
|
13
|
+
function() {
|
14
|
+
var a1 = this;
|
15
|
+
var a = a2 = null;
|
16
|
+
var n = 0;
|
17
|
+
while(n < arguments.length) {
|
18
|
+
a = [];
|
19
|
+
a2 = arguments[n];
|
20
|
+
var l = a1.length;
|
21
|
+
var l2 = a2.length;
|
22
|
+
var diff = true;
|
23
|
+
for(var i=0; i<l; i++) {
|
24
|
+
for(var j=0; j<l2; j++) {
|
25
|
+
if (a1[i] === a2[j]) {
|
26
|
+
diff = false;
|
27
|
+
break;
|
28
|
+
}
|
29
|
+
}
|
30
|
+
diff ? a.push(a1[i]) : diff = true;
|
31
|
+
}
|
32
|
+
a1 = a;
|
33
|
+
n++;
|
34
|
+
}
|
35
|
+
return a.unique();
|
36
|
+
};
|
37
|
+
|
38
|
+
// Return new array with duplicate values removed
|
39
|
+
Array.prototype.unique =
|
40
|
+
function() {
|
41
|
+
var a = [];
|
42
|
+
var l = this.length;
|
43
|
+
for(var i=0; i<l; i++) {
|
44
|
+
for(var j=i+1; j<l; j++) {
|
45
|
+
// If this[i] is found later in the array
|
46
|
+
if (this[i] === this[j])
|
47
|
+
j = ++i;
|
48
|
+
}
|
49
|
+
a.push(this[i]);
|
50
|
+
}
|
51
|
+
return a;
|
52
|
+
};
|
53
|
+
|
54
|
+
|
55
|
+
var source_ids = [];
|
56
|
+
|
57
|
+
function googleCallback(response) {
|
58
|
+
if (response.error) {
|
59
|
+
alert(response.error.message);
|
60
|
+
return;
|
61
|
+
}
|
62
|
+
var result_text = response.data.translations[0].translatedText.gsub(/__(.+)__/, function(match) {
|
63
|
+
return '{{' + match[1] + '}}';
|
64
|
+
});
|
65
|
+
var id = source_ids.shift();
|
66
|
+
if (id) {
|
67
|
+
Form.Element.setValue(id, result_text);
|
68
|
+
}
|
69
|
+
}
|
70
|
+
|
71
|
+
function getGoogleTranslation(id, text, from_language, to_language) {
|
72
|
+
source_ids.push(id);
|
73
|
+
text = text.replace(/\{\{/, '__').replace(/\}\}/, '__');
|
74
|
+
var s = document.createElement('script'), api_key = '<%= Translate.api_key %>';
|
75
|
+
s.type = 'text/javascript';
|
76
|
+
s.src = 'https://www.googleapis.com/language/translate/v2?key=' + api_key + '&source=' +
|
77
|
+
from_language + '&target=' + to_language + '&callback=googleCallback&q=' + text;
|
78
|
+
document.getElementsByTagName("head")[0].appendChild(s);
|
79
|
+
}
|
80
|
+
|
81
|
+
function bingCallback(text) {
|
82
|
+
var id = source_ids.shift();
|
83
|
+
if (text && id) {
|
84
|
+
var result_text = text.gsub(/__(.+)__/, function(match) {
|
85
|
+
return '{{' + match[1] + '}}';
|
86
|
+
});
|
87
|
+
Form.Element.setValue(id, result_text);
|
88
|
+
}
|
89
|
+
}
|
90
|
+
|
91
|
+
function getBingTranslation(id, text, from_language, to_language) {
|
92
|
+
source_ids.push(id);
|
93
|
+
text = text.replace(/\{\{/, '__').replace(/\}\}/, '__');
|
94
|
+
var s = document.createElement("script"), app_id = '<%= Translate.app_id %>';
|
95
|
+
s.type = 'text/javascript';
|
96
|
+
s.src = 'http://api.microsofttranslator.com/V2/Ajax.svc/Translate?oncomplete=bingCallback&appId=' +
|
97
|
+
app_id + '&from=' + from_language + '&to=' + to_language + '&text=' + text;
|
98
|
+
document.getElementsByTagName("head")[0].appendChild(s);
|
99
|
+
}
|
100
|
+
|
101
|
+
function checkErrors()
|
102
|
+
{
|
103
|
+
var errors = []
|
104
|
+
$$('.translation-error').each(function(item) {
|
105
|
+
item.removeClassName("translation-error")
|
106
|
+
item.select('.error-text')[0].innerHTML = ""
|
107
|
+
});
|
108
|
+
|
109
|
+
$$('.single-translation').each(function(item) {
|
110
|
+
var val = item.select('.edit-field')[0].value
|
111
|
+
if( !val.blank() )
|
112
|
+
{
|
113
|
+
var patt1=/%\{[^\{\}]*\}/g;
|
114
|
+
var val_subs = val.match(patt1)
|
115
|
+
var key = item.select('.translation-text')[0].innerHTML
|
116
|
+
var key_subs = key.match(patt1)
|
117
|
+
if( val_subs == null ){ val_subs = [] }
|
118
|
+
if( key_subs == null ){ key_subs = [] }
|
119
|
+
if( val_subs.sort().join('') != key_subs.sort().join('') )
|
120
|
+
{
|
121
|
+
missing_subs = key_subs.diff( val_subs )
|
122
|
+
item.addClassName("translation-error");
|
123
|
+
errors.push( item )
|
124
|
+
item.select('.error-text')[0].innerHTML = "Missing substitution strings: " + missing_subs.join(', ')
|
125
|
+
}
|
126
|
+
}
|
127
|
+
});
|
128
|
+
return errors
|
129
|
+
}
|
130
|
+
|
131
|
+
function testAndSave()
|
132
|
+
{
|
133
|
+
var errors = checkErrors()
|
134
|
+
|
135
|
+
if( errors.length == 0 )
|
136
|
+
{
|
137
|
+
document.forms["translate_form"].submit();
|
138
|
+
}
|
139
|
+
else
|
140
|
+
{
|
141
|
+
alert( "Some translations have errors. Please review and correct errors before saving.")
|
142
|
+
}
|
143
|
+
}
|
144
|
+
|
145
|
+
/*
|
146
|
+
prototypeUtils.js from http://jehiah.com/
|
147
|
+
Licensed under Creative Commons.
|
148
|
+
version 1.0 December 20 2005
|
149
|
+
|
150
|
+
Contains:
|
151
|
+
+ Form.Element.setValue()
|
152
|
+
+ unpackToForm()
|
153
|
+
|
154
|
+
*/
|
155
|
+
|
156
|
+
/* Form.Element.setValue("fieldname/id","valueToSet") */
|
157
|
+
Form.Element.setValue = function(element,newValue) {
|
158
|
+
element_id = element;
|
159
|
+
element = $(element);
|
160
|
+
if (!element){element = document.getElementsByName(element_id)[0];}
|
161
|
+
if (!element){return false;}
|
162
|
+
var method = element.tagName.toLowerCase();
|
163
|
+
var parameter = Form.Element.SetSerializers[method](element,newValue);
|
164
|
+
}
|
165
|
+
|
166
|
+
Form.Element.SetSerializers = {
|
167
|
+
input: function(element,newValue) {
|
168
|
+
switch (element.type.toLowerCase()) {
|
169
|
+
case 'submit':
|
170
|
+
case 'hidden':
|
171
|
+
case 'password':
|
172
|
+
case 'text':
|
173
|
+
return Form.Element.SetSerializers.textarea(element,newValue);
|
174
|
+
case 'checkbox':
|
175
|
+
case 'radio':
|
176
|
+
return Form.Element.SetSerializers.inputSelector(element,newValue);
|
177
|
+
}
|
178
|
+
return false;
|
179
|
+
},
|
180
|
+
|
181
|
+
inputSelector: function(element,newValue) {
|
182
|
+
fields = document.getElementsByName(element.name);
|
183
|
+
for (var i=0;i<fields.length;i++){
|
184
|
+
if (fields[i].value == newValue){
|
185
|
+
fields[i].checked = true;
|
186
|
+
}
|
187
|
+
}
|
188
|
+
},
|
189
|
+
|
190
|
+
textarea: function(element,newValue) {
|
191
|
+
element.value = newValue;
|
192
|
+
},
|
193
|
+
|
194
|
+
select: function(element,newValue) {
|
195
|
+
var value = '', opt, index = element.selectedIndex;
|
196
|
+
for (var i=0;i< element.options.length;i++){
|
197
|
+
if (element.options[i].value == newValue){
|
198
|
+
element.selectedIndex = i;
|
199
|
+
return true;
|
200
|
+
}
|
201
|
+
}
|
202
|
+
}
|
203
|
+
}
|
204
|
+
|
205
|
+
function unpackToForm(data){
|
206
|
+
for (i in data){
|
207
|
+
Form.Element.setValue(i,data[i].toString());
|
208
|
+
}
|
209
|
+
}
|
210
|
+
|
211
|
+
</script>
|
212
|
+
|
213
|
+
|
214
|
+
<style type="text/css">
|
215
|
+
/*reset.css*/
|
216
|
+
/* v1.0 | 20080212 */
|
217
|
+
html, body, div, span, applet, object, iframe,
|
218
|
+
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
219
|
+
a, abbr, acronym, address, big, cite, code,
|
220
|
+
del, dfn, em, font, img, ins, kbd, q, s, samp,
|
221
|
+
small, strike, strong, sub, sup, tt, var,
|
222
|
+
b, u, i, center,
|
223
|
+
dl, dt, dd, ol, ul, li,
|
224
|
+
fieldset, form, label, legend,
|
225
|
+
table, caption, tbody, tfoot, thead, tr, th, td {
|
226
|
+
margin: 0;
|
227
|
+
padding: 0;
|
228
|
+
border: 0;
|
229
|
+
outline: 0;
|
230
|
+
font-size: 100%;
|
231
|
+
vertical-align: baseline;
|
232
|
+
background: transparent;
|
233
|
+
}
|
234
|
+
body {
|
235
|
+
line-height: 1;
|
236
|
+
}
|
237
|
+
ol, ul {
|
238
|
+
list-style: none;
|
239
|
+
}
|
240
|
+
blockquote, q {
|
241
|
+
quotes: none;
|
242
|
+
}
|
243
|
+
blockquote:before, blockquote:after,
|
244
|
+
q:before, q:after {
|
245
|
+
content: '';
|
246
|
+
content: none;
|
247
|
+
}
|
248
|
+
|
249
|
+
/* remember to define focus styles! */
|
250
|
+
:focus {
|
251
|
+
outline: 0;
|
252
|
+
}
|
253
|
+
|
254
|
+
/* remember to highlight inserts somehow! */
|
255
|
+
ins {
|
256
|
+
text-decoration: none;
|
257
|
+
}
|
258
|
+
del {
|
259
|
+
text-decoration: line-through;
|
260
|
+
}
|
261
|
+
|
262
|
+
/* tables still need 'cellspacing="0"' in the markup */
|
263
|
+
table {
|
264
|
+
border-collapse: collapse;
|
265
|
+
border-spacing: 0;
|
266
|
+
}
|
267
|
+
/*clear fix*/
|
268
|
+
.clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden;}
|
269
|
+
.clearfix{display:inline-block;}
|
270
|
+
html[xmlns] .clearfix {
|
271
|
+
display: block;
|
272
|
+
}
|
273
|
+
* html .clearfix{height:1%;}
|
274
|
+
/*start layout*/
|
275
|
+
body{
|
276
|
+
background:#fff;
|
277
|
+
color:#333;
|
278
|
+
font-size:75%;
|
279
|
+
font-family:Arial;
|
280
|
+
margin:2em auto;
|
281
|
+
line-height:1.5em;
|
282
|
+
}
|
283
|
+
textarea,input,select{
|
284
|
+
font-family:Arial;
|
285
|
+
font-size:1em;
|
286
|
+
}
|
287
|
+
h1{
|
288
|
+
color:#d46021;
|
289
|
+
font-size:2em;
|
290
|
+
margin-bottom:0.5em;
|
291
|
+
}
|
292
|
+
h2{
|
293
|
+
text-align:left;
|
294
|
+
color:#d46021;
|
295
|
+
font-size:1.3em;
|
296
|
+
padding-left:0;
|
297
|
+
}
|
298
|
+
a{
|
299
|
+
color:#2158C7;
|
300
|
+
}
|
301
|
+
div#container{
|
302
|
+
width:960px;
|
303
|
+
margin:0 auto;
|
304
|
+
font-size:1em;
|
305
|
+
}
|
306
|
+
/*paging*/
|
307
|
+
div.paging{
|
308
|
+
margin-bottom:1em;
|
309
|
+
text-align:left;
|
310
|
+
}
|
311
|
+
div.paging div{
|
312
|
+
border:solid 1px red;
|
313
|
+
margin:1em 1em 0;
|
314
|
+
padding:0.5em;
|
315
|
+
border:solid 1px #d5d6d5;
|
316
|
+
background:#f1f1f1;
|
317
|
+
}
|
318
|
+
ul.paging{
|
319
|
+
display:inline-block;
|
320
|
+
}
|
321
|
+
ul.paging li{
|
322
|
+
display:block;
|
323
|
+
margin:0.2em 0;
|
324
|
+
float:left;
|
325
|
+
}
|
326
|
+
ul.paging li.selected a{
|
327
|
+
color:#fff;
|
328
|
+
background:#2158C7;
|
329
|
+
font-weight:bold;
|
330
|
+
padding:0.5em 0.7em;
|
331
|
+
}
|
332
|
+
ul.paging li a{
|
333
|
+
display:inline-block;
|
334
|
+
line-height:1em;
|
335
|
+
padding:0.5em 0.5em;
|
336
|
+
}
|
337
|
+
/*forms filter*/
|
338
|
+
fieldset{
|
339
|
+
padding:1em;
|
340
|
+
margin:1em;
|
341
|
+
border:solid 2px #d46021;
|
342
|
+
}
|
343
|
+
legend{
|
344
|
+
font-size:1.2em;
|
345
|
+
font-weight:bold;
|
346
|
+
padding:0 1em;
|
347
|
+
padding-bottom:0.5em;
|
348
|
+
}
|
349
|
+
label{
|
350
|
+
font-weight:bold;
|
351
|
+
}
|
352
|
+
fieldset span{padding-right:0.5em;}
|
353
|
+
div#show-sort label,
|
354
|
+
div#languages label,
|
355
|
+
div#filter-pattern label{
|
356
|
+
display:inline-block;
|
357
|
+
width:100px;
|
358
|
+
line-height:2em;
|
359
|
+
}
|
360
|
+
div#show-sort select,
|
361
|
+
div#languages select,
|
362
|
+
div#filter-pattern select{
|
363
|
+
width:120px;
|
364
|
+
margin-right:0.5em;
|
365
|
+
}
|
366
|
+
div#show-sort input.text-default,
|
367
|
+
div#languages input.text-default,
|
368
|
+
div#filter-pattern input.text-default{
|
369
|
+
width:200px;
|
370
|
+
}
|
371
|
+
p.hits{
|
372
|
+
margin-top:1em;
|
373
|
+
}
|
374
|
+
/*translation edit*/
|
375
|
+
div.translations{
|
376
|
+
margin:1em;
|
377
|
+
padding:1em;
|
378
|
+
border:solid 2px #d46021;
|
379
|
+
}
|
380
|
+
div.translations h2{
|
381
|
+
margin-bottom:1em;
|
382
|
+
}
|
383
|
+
p.translate{
|
384
|
+
background:red;
|
385
|
+
border:solid 1px #d5d6d5;
|
386
|
+
background:#f1f1f1;
|
387
|
+
margin:0.5em;
|
388
|
+
padding:0.7em 0.5em 0.5em 1.5em;
|
389
|
+
}
|
390
|
+
div.translation{
|
391
|
+
padding: 11px;
|
392
|
+
border-bottom:solid 1px #d46021;
|
393
|
+
border-left: solid 1px #D46021;
|
394
|
+
margin:14px 12px 12px 19px;
|
395
|
+
}
|
396
|
+
div.translation input, div.translation textarea{
|
397
|
+
width:98%;
|
398
|
+
margin:1em 0;
|
399
|
+
display:inline-block;
|
400
|
+
padding:0.3em;
|
401
|
+
}
|
402
|
+
div.translation textarea{
|
403
|
+
height:50px;
|
404
|
+
}
|
405
|
+
div.translation em strong{
|
406
|
+
color:#333;
|
407
|
+
padding-right:0.5em;
|
408
|
+
}
|
409
|
+
p.translation em{
|
410
|
+
display:block;
|
411
|
+
font-size:0.8333em;
|
412
|
+
}
|
413
|
+
div.translation a{
|
414
|
+
padding:1em;
|
415
|
+
}
|
416
|
+
div.translation input.btnDefault{
|
417
|
+
margin:0 0 1em;
|
418
|
+
width:auto;
|
419
|
+
}
|
420
|
+
.focus-text{
|
421
|
+
font-weight:bold;
|
422
|
+
}
|
423
|
+
div.selected{
|
424
|
+
margin:12px 10px 12px 12px;
|
425
|
+
border-left:solid 8px #d46021;
|
426
|
+
border-right:solid 2px #d46021;
|
427
|
+
border-top:solid 2px #d46021;
|
428
|
+
background:#f1f1f1;
|
429
|
+
}
|
430
|
+
.display{display:block !important;}
|
431
|
+
/*feedback*/
|
432
|
+
div#notice, div#error {
|
433
|
+
font-size:1em;
|
434
|
+
margin:1em;
|
435
|
+
padding: 1em;
|
436
|
+
border: 1px solid red;
|
437
|
+
}
|
438
|
+
div#notice span, div#error span{
|
439
|
+
font-size:1.5em;
|
440
|
+
}
|
441
|
+
|
442
|
+
div#error {
|
443
|
+
background-color: #F3C6CC;
|
444
|
+
color: red;
|
445
|
+
}
|
446
|
+
div#notice {
|
447
|
+
border-color: #72A974;
|
448
|
+
color: #597B5C;
|
449
|
+
background-color: #BCFFBD;
|
450
|
+
}
|
451
|
+
.translation-error .edit-field
|
452
|
+
{
|
453
|
+
border: 1px solid red;
|
454
|
+
}
|
455
|
+
.error-text
|
456
|
+
{
|
457
|
+
color: red;
|
458
|
+
}
|
459
|
+
.big-locale
|
460
|
+
{
|
461
|
+
font-size: 32px;
|
462
|
+
color: red;
|
463
|
+
}
|
464
|
+
</style>
|
465
|
+
<script type="text/javascript">
|
466
|
+
onload = function (){
|
467
|
+
$$("div.translation input, div.translation textarea").each(function (e){
|
468
|
+
Event.observe(e,'focus', function (elm){
|
469
|
+
this.up(".single-translation").down(".translation-text").addClassName("focus-text");
|
470
|
+
this.up(".translation").addClassName("selected");
|
471
|
+
});
|
472
|
+
Event.observe(e,'blur', function (elm,e){
|
473
|
+
this.up(".single-translation").down(".translation-text").removeClassName("focus-text");
|
474
|
+
this.up(".translation").removeClassName("selected");
|
475
|
+
});
|
476
|
+
});
|
477
|
+
|
478
|
+
checkErrors()
|
479
|
+
}
|
480
|
+
</script>
|
481
|
+
</head>
|
482
|
+
<body>
|
483
|
+
<div id="container">
|
484
|
+
<% if @page_title -%><h1><%=h @page_title %></h1><% end -%>
|
485
|
+
<% [:notice, :error].each do |message| %>
|
486
|
+
<%if flash[message] %>
|
487
|
+
<div id="<%= message %>">
|
488
|
+
<span><%= h(flash[message]) if flash[message] %></span>
|
489
|
+
</div>
|
490
|
+
<% end %>
|
491
|
+
<% end %>
|
492
|
+
<%= yield %>
|
493
|
+
</div>
|
494
|
+
</body>
|
495
|
+
</html>
|