translate-rails3 0.2.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: be316db288564b0402ea25c9a893925879036248
4
+ data.tar.gz: e0a2200895b4c73b58f28c40c1e31fe097f9b325
5
+ SHA512:
6
+ metadata.gz: 77ff1b9a66bae72c2d21a926dcee31eb212019e61202ff1d1d7368c7ff3b195680a6ddd83b2d6b908621ec56467f1670dc70067b9c2f9fe30590bfcb6cd4fc6b
7
+ data.tar.gz: 8c7496dd20eab5a679bc8cb918785c0c31b0821bab38340f38aa9aba235b95fa6bbc4bf38adc39282286b6cabfb38dda8c80e9752a96c95dbe3889764f9faf99
data/README.md CHANGED
@@ -21,12 +21,13 @@ Rake Tasks
21
21
 
22
22
  In addition to the web UI this plugin adds the following rake tasks:
23
23
 
24
- translate:untranslated
25
- translate:missing
26
- translate:remove_obsolete_keys
27
- translate:merge_keys
28
- translate:google
29
- translate:changed
24
+ translate:untranslated
25
+ translate:missing
26
+ translate:remove_obsolete_keys
27
+ translate:merge_keys
28
+ translate:google
29
+ translate:changed
30
+ translate:duplicates
30
31
 
31
32
  The missing task shows you any I18n keys in your code that do not have translations in the YAML file for your default locale, i.e. config/locales/sv.yml.
32
33
 
@@ -37,6 +38,8 @@ The google task is used for auto translating from one locale to another using Go
37
38
 
38
39
  The changed rake task can show you between one YAML file to another which keys have had their texts changed.
39
40
 
41
+ The duplicates task can show you strings that are the same in both locales.
42
+
40
43
  Installation
41
44
  ------------
42
45
 
data/Rakefile CHANGED
@@ -20,12 +20,13 @@ The plugin has been tested only with the simple I18n backend that ships
20
20
  with Rails.
21
21
  I18n texts are read from and written to YAML files under config/locales.
22
22
 
23
- This gem is a fork of the original https://github.com/mynewsdesk/translate
24
- and also includes work from this fork: https://github.com/milann/translate
23
+ This gem is a fork of https://github.com/romanbsd/translate.
24
+ From the original https://github.com/mynewsdesk/translate
25
+ which also includes work from this fork: https://github.com/milann/translate
25
26
  EOF
26
- gem.email = 'romanbsd@yahoo.com'
27
- gem.homepage = 'https://github.com/romanbsd/translate'
28
- gem.authors = ['Peter Marklund', 'Milan Novota', 'Roman Shterenzon']
27
+ gem.email = 'gsmedley@kanayo.com'
28
+ gem.homepage = 'https://github.com/gsmedley/translate'
29
+ gem.authors = ['Peter Marklund', 'Milan Novota', 'Roman Shterenzon', 'Garth Smedley']
29
30
  gem.add_dependency 'ya2yaml', '~> 0.30' # For UTF-8 support in YAML
30
31
  end
31
32
  Jeweler::GemcutterTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.3
1
+ 0.4.0
@@ -12,10 +12,12 @@ class TranslateController < ActionController::Base
12
12
  initialize_keys
13
13
  filter_by_key_pattern
14
14
  filter_by_text_pattern
15
+ filter_by_translated_text_pattern
15
16
  filter_by_translated_or_changed
16
17
  sort_keys
17
18
  paginate_keys
18
19
  @total_entries = @keys.size
20
+ @page_title = page_title
19
21
  end
20
22
 
21
23
  # POST /translate
@@ -26,7 +28,7 @@ class TranslateController < ActionController::Base
26
28
  Translate::Log.new(@from_locale, @to_locale, params[:key].keys).write_to_file
27
29
  force_init_translations # Force reload from YAML file
28
30
  flash[:notice] = "Translations stored"
29
- redirect_to params.slice(:filter, :sort_by, :key_type, :key_pattern, :text_type, :text_pattern).merge({:action => :index})
31
+ redirect_to translate_path params.slice(:filter, :sort_by, :key_type, :key_pattern, :text_type, :text_pattern, :translated_text_type, :translated_text_pattern)
30
32
  end
31
33
 
32
34
  # GET /translate/reload
@@ -47,11 +49,32 @@ class TranslateController < ActionController::Base
47
49
  end
48
50
  end
49
51
 
52
+ def page_title
53
+ "Translate"
54
+ end
55
+
50
56
  def lookup(locale, key)
51
57
  I18n.backend.send(:lookup, locale, key)
52
58
  end
53
59
  helper_method :lookup
54
60
 
61
+ def from_locales
62
+ # Attempt to get the list of locale from configuration
63
+ from_loc = Rails.application.config.from_locales if Rails.application.config.respond_to?(:from_locales)
64
+ return I18n.available_locales if from_loc.blank?
65
+ raise StandardError, "from_locale expected to be an array" if from_loc.class != Array
66
+ from_loc
67
+ end
68
+ helper_method :from_locales
69
+
70
+ def to_locales
71
+ to_loc = Rails.application.config.to_locales if Rails.application.config.respond_to?(:to_locales)
72
+ return I18n.available_locales if to_loc.blank?
73
+ raise StandardError, "to_locales expected to be an array" if to_loc.class != Array
74
+ to_loc
75
+ end
76
+ helper_method :to_locales
77
+
55
78
  def filter_by_translated_or_changed
56
79
  params[:filter] ||= 'all'
57
80
  return if params[:filter] == 'all'
@@ -62,7 +85,16 @@ class TranslateController < ActionController::Base
62
85
  when 'translated'
63
86
  lookup(@to_locale, key).blank?
64
87
  when 'changed'
65
- old_from_text(key).blank? || lookup(@from_locale, key) == old_from_text(key)
88
+ lookup(@from_locale, key).to_s == lookup(@to_locale, key).to_s
89
+ when 'list_changed'
90
+ fr = lookup(@from_locale, key).to_s.squish
91
+ to = lookup(@to_locale, key).to_s.squish
92
+ if fr.downcase != to.downcase
93
+ p '--'
94
+ p 'c:' + fr
95
+ p 'g:' + to
96
+ end
97
+ fr.downcase == to.downcase
66
98
  else
67
99
  raise "Unknown filter '#{params[:filter]}'"
68
100
  end
@@ -97,6 +129,20 @@ class TranslateController < ActionController::Base
97
129
  end
98
130
  end
99
131
 
132
+ def filter_by_translated_text_pattern
133
+ return if params[:translated_text_pattern].blank?
134
+ @keys.reject! do |key|
135
+ case params[:translated_text_type]
136
+ when 'contains' then
137
+ !lookup(@to_locale, key).present? || !lookup(@to_locale, key).to_s.downcase.index(params[:translated_text_pattern].downcase)
138
+ when 'equals' then
139
+ !lookup(@to_locale, key).present? || lookup(@to_locale, key).to_s.downcase != params[:translated_text_pattern].downcase
140
+ else
141
+ raise "Unknown translated_text_type '#{params[:translated_text_type]}'"
142
+ end
143
+ end
144
+ end
145
+
100
146
  def sort_keys
101
147
  params[:sort_by] ||= "key"
102
148
  case params[:sort_by]
@@ -143,39 +189,29 @@ class TranslateController < ActionController::Base
143
189
  I18n.default_locale
144
190
  end
145
191
 
192
+ def default_to_locale
193
+ :en
194
+ end
195
+
146
196
  def set_locale
147
197
  session[:from_locale] ||= default_locale
148
- session[:to_locale] ||= :en
198
+ session[:to_locale] ||= default_to_locale
149
199
  session[:from_locale] = params[:from_locale] if params[:from_locale].present?
150
200
  session[:to_locale] = params[:to_locale] if params[:to_locale].present?
151
201
  @from_locale = session[:from_locale].to_sym
152
202
  @to_locale = session[:to_locale].to_sym
153
203
  end
154
204
 
155
- def old_from_text(key)
156
- return @old_from_text[key] if @old_from_text && @old_from_text[key]
157
- @old_from_text = {}
158
- text = key.split(".").inject(log_hash) do |hash, k|
159
- hash ? hash[k] : nil
160
- end
161
- @old_from_text[key] = text
162
- end
163
- helper_method :old_from_text
205
+ def process_array_parameters(parameter)
206
+ reconstructed_hash = Hash.new
164
207
 
165
- def log_hash
166
- @log_hash ||= Translate::Log.new(@from_locale, @to_locale, {}).read
208
+ parameter.each do |key, value|
209
+ if value.is_a?(String)
210
+ reconstructed_hash[key] = value
211
+ elsif value.is_a?(Hash)
212
+ reconstructed_hash[key] = Translate::Keys.arraylize(value)
213
+ end
214
+ end
215
+ reconstructed_hash
167
216
  end
168
-
169
- def process_array_parameters(parameter)
170
- reconstructed_hash = Hash.new
171
-
172
- parameter.each do |key, value|
173
- if value.is_a?(String)
174
- reconstructed_hash[key] = value
175
- elsif value.is_a?(Hash)
176
- reconstructed_hash[key] = Translate::Keys.arraylize(value)
177
- end
178
- end
179
- reconstructed_hash
180
- end
181
217
  end
@@ -1,20 +1,5 @@
1
1
  module TranslateHelper
2
2
 
3
- def from_locales
4
- # Attempt to get the list of locale from configuration
5
- from_loc = Rails.application.config.from_locales if Rails.application.config.respond_to?(:from_locales)
6
- return I18n.available_locales if from_loc.blank?
7
- raise StandardError, "from_locale expected to be an array" if from_loc.class != Array
8
- from_loc
9
- end
10
-
11
- def to_locales
12
- to_loc = Rails.application.config.to_locales if Rails.application.config.respond_to?(:to_locales)
13
- return I18n.available_locales if to_loc.blank?
14
- raise StandardError, "to_locales expected to be an array" if to_loc.class != Array
15
- to_loc
16
- end
17
-
18
3
  def simple_filter(labels, param_name = 'filter', selected_value = nil)
19
4
  selected_value ||= params[param_name]
20
5
  filter = []
@@ -47,15 +32,11 @@ module TranslateHelper
47
32
  end
48
33
 
49
34
  def translate_javascript_includes
50
- sources = []
51
35
  if File.exists?(File.join(Rails.root, "public", "javascripts", "prototype.js"))
52
- sources << "/javascripts/prototype.js"
36
+ javascript_include_tag("prototype.js")
53
37
  else
54
- sources << "http://ajax.googleapis.com/ajax/libs/prototype/1.7.0.0/prototype.js"
38
+ javascript_include_tag("http://ajax.googleapis.com/ajax/libs/prototype/1.7.0.0/prototype.js")
55
39
  end
56
- sources.map do |src|
57
- %Q{<script src="#{src}" type="text/javascript"></script>}
58
- end.join("\n").html_safe
59
40
  end
60
41
 
61
42
  def translate_link(key, text, from, to)
@@ -69,4 +50,28 @@ module TranslateHelper
69
50
  return nil unless method
70
51
  link_to_function 'Auto Translate', "#{method}('#{key}', \"#{escape_javascript(text)}\", '#{from}', '#{to}')", :style => 'padding: 0; margin: 0;'
71
52
  end
53
+
54
+ # copy/paste of missing function, because it was deprecated in Rails 4.1
55
+ def button_to_function(name, function=nil, html_options={})
56
+ message = "button_to_function is deprecated and will be removed from Rails 4.1. We recommend using Unobtrusive JavaScript instead. " +
57
+ "See http://guides.rubyonrails.org/working_with_javascript_in_rails.html#unobtrusive-javascript"
58
+ ActiveSupport::Deprecation.warn message
59
+
60
+ onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function};"
61
+
62
+ tag(:input, html_options.merge(:type => 'button', :value => name, :onclick => onclick))
63
+ end
64
+
65
+ # copy/paste of missing function, because it was deprecated in Rails 4.1
66
+ def link_to_function(name, function, html_options={})
67
+ message = "link_to_function is deprecated and will be removed from Rails 4.1. We recommend using Unobtrusive JavaScript instead. " +
68
+ "See http://guides.rubyonrails.org/working_with_javascript_in_rails.html#unobtrusive-javascript"
69
+ ActiveSupport::Deprecation.warn message
70
+
71
+ onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function}; return false;"
72
+ href = html_options[:href] || '#'
73
+
74
+ content_tag(:a, name, html_options.merge(:href => href, :onclick => onclick))
75
+ end
76
+
72
77
  end
@@ -7,6 +7,51 @@
7
7
 
8
8
  <%= translate_javascript_includes %>
9
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
+
10
55
  var source_ids = [];
11
56
 
12
57
  function googleCallback(response) {
@@ -53,6 +98,50 @@
53
98
  document.getElementsByTagName("head")[0].appendChild(s);
54
99
  }
55
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
+
56
145
  /*
57
146
  prototypeUtils.js from http://jehiah.com/
58
147
  Licensed under Creative Commons.
@@ -123,232 +212,232 @@
123
212
 
124
213
 
125
214
  <style type="text/css">
126
- /*reset.css*/
127
- /* v1.0 | 20080212 */
128
- html, body, div, span, applet, object, iframe,
129
- h1, h2, h3, h4, h5, h6, p, blockquote, pre,
130
- a, abbr, acronym, address, big, cite, code,
131
- del, dfn, em, font, img, ins, kbd, q, s, samp,
132
- small, strike, strong, sub, sup, tt, var,
133
- b, u, i, center,
134
- dl, dt, dd, ol, ul, li,
135
- fieldset, form, label, legend,
136
- table, caption, tbody, tfoot, thead, tr, th, td {
137
- margin: 0;
138
- padding: 0;
139
- border: 0;
140
- outline: 0;
141
- font-size: 100%;
142
- vertical-align: baseline;
143
- background: transparent;
144
- }
145
- body {
146
- line-height: 1;
147
- }
148
- ol, ul {
149
- list-style: none;
150
- }
151
- blockquote, q {
152
- quotes: none;
153
- }
154
- blockquote:before, blockquote:after,
155
- q:before, q:after {
156
- content: '';
157
- content: none;
158
- }
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
+ }
159
248
 
160
- /* remember to define focus styles! */
161
- :focus {
162
- outline: 0;
163
- }
249
+ /* remember to define focus styles! */
250
+ :focus {
251
+ outline: 0;
252
+ }
164
253
 
165
- /* remember to highlight inserts somehow! */
166
- ins {
167
- text-decoration: none;
168
- }
169
- del {
170
- text-decoration: line-through;
171
- }
254
+ /* remember to highlight inserts somehow! */
255
+ ins {
256
+ text-decoration: none;
257
+ }
258
+ del {
259
+ text-decoration: line-through;
260
+ }
172
261
 
173
- /* tables still need 'cellspacing="0"' in the markup */
174
- table {
175
- border-collapse: collapse;
176
- border-spacing: 0;
177
- }
178
- /*clear fix*/
179
- .clearfix:after{content:".";display:block;height:0;clear:both;visibility:hidden;}
180
- .clearfix{display:inline-block;}
181
- html[xmlns] .clearfix {
182
- display: block;
183
- }
184
- * html .clearfix{height:1%;}
185
- /*start layout*/
186
- body{
187
- background:#fff;
188
- color:#333;
189
- font-size:75%;
190
- font-family:Arial;
191
- margin:2em auto;
192
- line-height:1.5em;
193
- }
194
- textarea,input,select{
195
- font-family:Arial;
196
- font-size:1em;
197
- }
198
- h1{
199
- color:#d46021;
200
- font-size:2em;
201
- margin-bottom:0.5em;
202
- }
203
- h2{
204
- text-align:left;
205
- color:#d46021;
206
- font-size:1.3em;
207
- padding-left:0;
208
- }
209
- a{
210
- color:#2158C7;
211
- }
212
- div#container{
213
- width:960px;
214
- margin:0 auto;
215
- font-size:1em;
216
- }
217
- /*paging*/
218
- div.paging{
219
- margin-bottom:1em;
220
- text-align:left;
221
- }
222
- div.paging div{
223
- border:solid 1px red;
224
- margin:1em 1em 0;
225
- padding:0.5em;
226
- border:solid 1px #d5d6d5;
227
- background:#f1f1f1;
228
- }
229
- ul.paging{
230
- display:inline-block;
231
- }
232
- ul.paging li{
233
- display:block;
234
- margin:0.2em 0;
235
- float:left;
236
- }
237
- ul.paging li.selected a{
238
- color:#fff;
239
- background:#2158C7;
240
- font-weight:bold;
241
- padding:0.5em 0.7em;
242
- }
243
- ul.paging li a{
244
- display:inline-block;
245
- line-height:1em;
246
- padding:0.5em 0.5em;
247
- }
248
- /*forms filter*/
249
- fieldset{
250
- padding:1em;
251
- margin:1em;
252
- border:solid 2px #d46021;
253
- }
254
- legend{
255
- font-size:1.2em;
256
- font-weight:bold;
257
- padding:0 1em;
258
- padding-bottom:0.5em;
259
- }
260
- label{
261
- font-weight:bold;
262
- }
263
- fieldset span{padding-right:0.5em;}
264
- div#show-sort label,
265
- div#languages label,
266
- div#filter-pattern label{
267
- display:inline-block;
268
- width:100px;
269
- line-height:2em;
270
- }
271
- div#show-sort select,
272
- div#languages select,
273
- div#filter-pattern select{
274
- width:120px;
275
- margin-right:0.5em;
276
- }
277
- div#show-sort input.text-default,
278
- div#languages input.text-default,
279
- div#filter-pattern input.text-default{
280
- width:200px;
281
- }
282
- p.hits{
283
- margin-top:1em;
284
- }
285
- /*translation edit*/
286
- div.translations{
287
- margin:1em;
288
- padding:1em;
289
- border:solid 2px #d46021;
290
- }
291
- div.translations h2{
292
- margin-bottom:1em;
293
- }
294
- p.translate{
295
- background:red;
296
- border:solid 1px #d5d6d5;
297
- background:#f1f1f1;
298
- margin:0.5em;
299
- padding:0.7em 0.5em 0.5em 1.5em;
300
- }
301
- div.translation{
302
- padding:1em;
303
- border-bottom:solid 0.2em #d46021;
304
- border-left: solid 0.1em #D46021;
305
- margin:0 1em 1em 1.6em;
306
- }
307
- div.translation input, div.translation textarea{
308
- width:98%;
309
- margin:1em 0;
310
- display:inline-block;
311
- padding:0.3em;
312
- }
313
- div.translation textarea{
314
- height:50px;
315
- }
316
- div.translation em strong{
317
- color:#333;
318
- padding-right:0.5em;
319
- }
320
- p.translation em{
321
- display:block;
322
- font-size:0.8333em;
323
- }
324
- div.translation a{
325
- padding:1em;
326
- }
327
- div.translation input.btnDefault{
328
- margin:0 0 1em;
329
- width:auto;
330
- }
331
- .focus-text{
332
- font-weight:bold;
333
- }
334
- div.selected{
335
- margin:0 1em 1em 1em;
336
- border-left:solid 0.6em #d46021;
337
- border-right:solid 0.2em #d46021;
338
- border-top:solid 0.2em #d46021;
339
- background:#f1f1f1;
340
- }
341
- .display{display:block !important;}
342
- /*feedback*/
343
- div#notice, div#error {
344
- font-size:1em;
345
- margin:1em;
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;
346
435
  padding: 1em;
347
- border: 1px solid red;
436
+ border: 1px solid red;
437
+ }
438
+ div#notice span, div#error span{
439
+ font-size:1.5em;
348
440
  }
349
- div#notice span, div#error span{
350
- font-size:1.5em;
351
- }
352
441
 
353
442
  div#error {
354
443
  background-color: #F3C6CC;
@@ -358,34 +447,49 @@
358
447
  border-color: #72A974;
359
448
  color: #597B5C;
360
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;
361
463
  }
362
464
  </style>
363
- <script type="text/javascript">
364
- onload = function (){
365
- $$("div.translation input, div.translation textarea").each(function (e){
366
- Event.observe(e,'focus', function (elm){
367
- this.up(1).down(".translation-text").addClassName("focus-text");
368
- this.up(1).addClassName("selected");
369
- });
370
- Event.observe(e,'blur', function (elm,e){
371
- this.up(1).down(".translation-text").removeClassName("focus-text");
372
- this.up(1).removeClassName("selected");
373
- });
374
- });
375
- }
376
- </script>
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>
377
481
  </head>
378
482
  <body>
379
- <div id="container">
380
- <% if @page_title -%><h1><%=h @page_title %></h1><% end -%>
381
- <% [:notice, :error].each do |message| %>
382
- <%if flash[message] %>
383
- <div id="<%= message %>">
384
- <span><%= h(flash[message]) if flash[message] %></span>
385
- </div>
386
- <% end %>
387
- <% end %>
388
- <%= yield %>
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 %>
389
493
  </div>
390
494
  </body>
391
495
  </html>
@@ -6,7 +6,7 @@
6
6
 
7
7
  <div class="translation">
8
8
  <% if from_text.present? %>
9
- <p class="translation-text">
9
+
10
10
  <ol>
11
11
  <% from_text.each_with_index do |from_text_section, index| %>
12
12
  <%
@@ -17,18 +17,21 @@
17
17
  # for this element yet...
18
18
  to_text = Array.new if to_text.blank?
19
19
  %>
20
- <li><%= from_text_section %></li>
21
- <p class="edit-form">
22
- <% if n_lines > 1 %>
23
- <%= text_area_tag("#{field_name}[#{index}]", to_text[index], :size => "#{line_size}x#{n_lines}", :id => "#{key}[#{index}]") %>
24
- <% else %>
25
- <%= text_field_tag("#{field_name}[#{index}]", to_text[index], :size => line_size, :id => "#{key}[#{index}]") %>
26
- <% end %>
27
- <%= translate_link("#{key}[#{index}]", from_text_section, @from_locale, @to_locale) %>
20
+ <li class="single-translation">
21
+ <p class="translation-text"><%= from_text_section %></p>
22
+ <p class="edit-form" >
23
+ <% if n_lines > 1 %>
24
+ <%= text_area_tag("#{field_name}[#{index}]", to_text[index], :size => "#{line_size}x#{n_lines}", :id => "#{key}[#{index}]", :class=>'edit-field') %>
25
+ <% else %>
26
+ <%= text_field_tag("#{field_name}[#{index}]", to_text[index], :size => line_size, :id => "#{key}[#{index}]", :class=>'edit-field') %>
27
+ <% end %>
28
+ <%= translate_link("#{key}[#{index}]", from_text_section, @from_locale, @to_locale) %>
28
29
  </p>
30
+ <div class="error-text"></div>
31
+ </li>
29
32
  <% end %>
30
33
  </ol>
31
- </p>
34
+
32
35
  <% end %>
33
36
  <p>
34
37
  <em>
@@ -6,19 +6,22 @@
6
6
  field_name = "key[#{key}]"
7
7
  %>
8
8
 
9
- <div class="translation">
9
+ <div class="translation single-translation" >
10
10
  <% if from_text.present? %>
11
- <p class="translation-text">
12
- <%= simple_format(h(from_text)) %>
13
- </p>
11
+ <% if from_text.starts_with?(" ") || from_text.ends_with?(" ")%>
12
+ <%= simple_format("&rarr;" + h(from_text) + "&larr;", :class => "translation-text" ) %>
13
+ <% else %>
14
+ <%= simple_format(h(from_text), :class => "translation-text") %>
15
+ <% end %>
14
16
  <% end %>
15
17
  <p class="edit-form">
16
18
  <% if n_lines > 1 %>
17
- <%= text_area_tag(field_name, to_text, :size => "#{line_size}x#{n_lines}", :id => key) %>
19
+ <%= text_area_tag(field_name, to_text, :size => "#{line_size}x#{n_lines}", :id => key, :class=>'edit-field') %>
18
20
  <% else %>
19
- <%= text_field_tag(field_name, to_text, :size => line_size, :id => key) %>
21
+ <%= text_field_tag(field_name, to_text, :size => line_size, :id => key, :class=>'edit-field') %>
20
22
  <% end %>
21
23
  </p>
24
+ <div class="error-text"></div>
22
25
  <p>
23
26
  <em>
24
27
  <%= translate_link(key, from_text, @from_locale, @to_locale) %>
@@ -1,5 +1,4 @@
1
1
  <%
2
- @page_title = "Translate"
3
2
  show_filters = ["all", "untranslated", "translated"]
4
3
  show_filters << "changed" if @from_locale != @to_locale
5
4
  %>
@@ -36,9 +35,14 @@ show_filters << "changed" if @from_locale != @to_locale
36
35
  <%= select_tag(:text_type, options_for_select(['contains', 'equals'], params[:text_type])) %>
37
36
  <%= text_field_tag(:text_pattern, params[:text_pattern], :size => 50, :id => "text_pattern_value", :class => "text-default") %>
38
37
  </p>
38
+ <p>
39
+ <label for="translated_text_pattern_value">Translated Text</label>
40
+ <%= select_tag(:translated_text_type, options_for_select(['contains', 'equals'], params[:translated_text_type])) %>
41
+ <%= text_field_tag(:translated_text_pattern, params[:translated_text_pattern], :size => 50, :id => "translated_text_pattern_value", :class => "text-default") %>
42
+ </p>
39
43
  <p>
40
44
  <%= submit_tag "Search" %>
41
- <%= link_to "clear", params.merge({:text_pattern => nil, :key_pattern => nil}) %>
45
+ <%= link_to "clear", params.merge({:text_pattern => nil, :translated_text_pattern => nil, :key_pattern => nil}) %>
42
46
  </p>
43
47
  </div>
44
48
  <% end %>
@@ -56,7 +60,7 @@ show_filters << "changed" if @from_locale != @to_locale
56
60
  </div>
57
61
 
58
62
  <% if @total_entries > 0 %>
59
- <%= form_tag(translate_path) do %>
63
+ <%= form_tag(translate_path, :name => 'translate_form') do %>
60
64
  <div>
61
65
  <%= hidden_field_tag(:filter, params[:filter], :id => "hid_filter") %>
62
66
  <%= hidden_field_tag(:sort_by, params[:sort_by], :id => "hid_sort_by") %>
@@ -66,9 +70,9 @@ show_filters << "changed" if @from_locale != @to_locale
66
70
  <%= hidden_field_tag(:text_pattern, params[:text_pattern], :id => "hid_text_pattern") %>
67
71
  </div>
68
72
  <div class="translations">
69
- <h2>Translations from <%= @from_locale %> to <%= @to_locale %></h2>
73
+ <h2>Translations from <span class='big-locale'><%= @from_locale %></span> to <span class='big-locale'><%= @to_locale %></span></h2>
70
74
  <p class="translate">
71
- <%= submit_tag "Save Translations" %>
75
+ <%= button_to_function 'Save Translations', 'testAndSave()' %>
72
76
  </p>
73
77
  <% @paginated_keys.each do |key| %>
74
78
  <%=
@@ -81,7 +85,7 @@ show_filters << "changed" if @from_locale != @to_locale
81
85
  %>
82
86
  <% end %>
83
87
  <p class="translate">
84
- <%= submit_tag "Save Translations" %>
88
+ <%= button_to_function 'Save Translations', 'testAndSave()' %>
85
89
  </p>
86
90
  </div>
87
91
  <% end %>
@@ -33,6 +33,27 @@ class Hash
33
33
  end
34
34
 
35
35
  namespace :translate do
36
+ desc "Show duplicate keys for locale LOCALE"
37
+ task :duplicates => :environment do
38
+ from_locale = I18n.default_locale
39
+ duplicates = Translate::Keys.new.duplicate_keys
40
+
41
+ messages = []
42
+ duplicates.each do |locale, keys|
43
+ keys.each do |key|
44
+ from_text = I18n.backend.send(:lookup, from_locale, key)
45
+ next if from_text.blank?
46
+ messages << "#{locale}.#{key} (#{from_locale}.#{key}='#{from_text}')"
47
+ end
48
+ end
49
+
50
+ if messages.present?
51
+ messages.each { |m| puts m }
52
+ else
53
+ puts "No duplicate keys"
54
+ end
55
+ end
56
+
36
57
  desc "Show untranslated keys for locale LOCALE"
37
58
  task :untranslated => :environment do
38
59
  from_locale = I18n.default_locale
@@ -42,6 +63,7 @@ namespace :translate do
42
63
  untranslated.each do |locale, keys|
43
64
  keys.each do |key|
44
65
  from_text = I18n.backend.send(:lookup, from_locale, key)
66
+ next if from_text.blank?
45
67
  messages << "#{locale}.#{key} (#{from_locale}.#{key}='#{from_text}')"
46
68
  end
47
69
  end
@@ -2,7 +2,7 @@ require 'ya2yaml'
2
2
 
3
3
  module Translate
4
4
  class Engine < Rails::Engine
5
- end if defined?(Rails) && Rails::VERSION::MAJOR == 3
5
+ end if defined?(Rails) && Rails::VERSION::MAJOR >= 3
6
6
 
7
7
  class << self
8
8
  # For configuring Google Translate API key
@@ -26,6 +26,15 @@ class Translate::Keys
26
26
  Translate::Keys.to_shallow_hash(I18n.backend.send(:translations)[locale.to_sym]).keys.sort
27
27
  end
28
28
 
29
+ def duplicate_keys
30
+ Translate::Keys.translated_locales.inject({}) do |missing, locale|
31
+ missing[locale] = i18n_keys(I18n.default_locale).map do |key|
32
+ I18n.backend.send(:lookup, locale, key) == I18n.backend.send(:lookup, I18n.default_locale, key) ? key : nil
33
+ end.compact
34
+ missing
35
+ end
36
+ end
37
+
29
38
  def untranslated_keys
30
39
  Translate::Keys.translated_locales.inject({}) do |missing, locale|
31
40
  missing[locale] = i18n_keys(I18n.default_locale).map do |key|
@@ -2,16 +2,18 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
+ # stub: translate-rails3 0.4.0 ruby lib
5
6
 
6
7
  Gem::Specification.new do |s|
7
8
  s.name = "translate-rails3"
8
- s.version = "0.2.3"
9
+ s.version = "0.4.0"
9
10
 
10
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Peter Marklund", "Milan Novota", "Roman Shterenzon"]
12
- s.date = "2012-01-22"
13
- s.description = "This plugin provides a web interface for translating Rails I18n texts\n(requires Rails 3.0 or higher) from one locale to another.\nThe plugin has been tested only with the simple I18n backend that ships\nwith Rails.\nI18n texts are read from and written to YAML files under config/locales.\n\nThis gem is a fork of the original https://github.com/mynewsdesk/translate\nand also includes work from this fork: https://github.com/milann/translate\n"
14
- s.email = "romanbsd@yahoo.com"
12
+ s.require_paths = ["lib"]
13
+ s.authors = ["Peter Marklund", "Milan Novota", "Roman Shterenzon", "Garth Smedley"]
14
+ s.date = "2015-01-15"
15
+ s.description = "This plugin provides a web interface for translating Rails I18n texts\n(requires Rails 3.0 or higher) from one locale to another.\nThe plugin has been tested only with the simple I18n backend that ships\nwith Rails.\nI18n texts are read from and written to YAML files under config/locales.\n\nThis gem is a fork of https://github.com/romanbsd/translate.\nFrom the original https://github.com/mynewsdesk/translate\nwhich also includes work from this fork: https://github.com/milann/translate\n"
16
+ s.email = "gsmedley@kanayo.com"
15
17
  s.extra_rdoc_files = [
16
18
  "README.md"
17
19
  ]
@@ -50,13 +52,12 @@ Gem::Specification.new do |s|
50
52
  "spec/storage_spec.rb",
51
53
  "translate-rails3.gemspec"
52
54
  ]
53
- s.homepage = "https://github.com/romanbsd/translate"
54
- s.require_paths = ["lib"]
55
- s.rubygems_version = "1.8.15"
55
+ s.homepage = "https://github.com/gsmedley/translate"
56
+ s.rubygems_version = "2.4.3"
56
57
  s.summary = "Newsdesk translate plugin for Rails 3"
57
58
 
58
59
  if s.respond_to? :specification_version then
59
- s.specification_version = 3
60
+ s.specification_version = 4
60
61
 
61
62
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
62
63
  s.add_runtime_dependency(%q<ya2yaml>, ["~> 0.30"])
metadata CHANGED
@@ -1,48 +1,48 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: translate-rails3
3
- version: !ruby/object:Gem::Version
4
- prerelease:
5
- version: 0.2.3
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
6
5
  platform: ruby
7
- authors:
6
+ authors:
8
7
  - Peter Marklund
9
8
  - Milan Novota
10
9
  - Roman Shterenzon
10
+ - Garth Smedley
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
-
15
- date: 2012-01-22 00:00:00 Z
16
- dependencies:
17
- - !ruby/object:Gem::Dependency
14
+ date: 2015-01-15 00:00:00.000000000 Z
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
18
17
  name: ya2yaml
19
- prerelease: false
20
- requirement: &id001 !ruby/object:Gem::Requirement
21
- none: false
22
- requirements:
23
- - - ~>
24
- - !ruby/object:Gem::Version
25
- version: "0.30"
18
+ requirement: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - "~>"
21
+ - !ruby/object:Gem::Version
22
+ version: '0.30'
26
23
  type: :runtime
27
- version_requirements: *id001
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - "~>"
28
+ - !ruby/object:Gem::Version
29
+ version: '0.30'
28
30
  description: |
29
31
  This plugin provides a web interface for translating Rails I18n texts
30
32
  (requires Rails 3.0 or higher) from one locale to another.
31
33
  The plugin has been tested only with the simple I18n backend that ships
32
34
  with Rails.
33
35
  I18n texts are read from and written to YAML files under config/locales.
34
-
35
- This gem is a fork of the original https://github.com/mynewsdesk/translate
36
- and also includes work from this fork: https://github.com/milann/translate
37
36
 
38
- email: romanbsd@yahoo.com
37
+ This gem is a fork of https://github.com/romanbsd/translate.
38
+ From the original https://github.com/mynewsdesk/translate
39
+ which also includes work from this fork: https://github.com/milann/translate
40
+ email: gsmedley@kanayo.com
39
41
  executables: []
40
-
41
42
  extensions: []
42
-
43
- extra_rdoc_files:
43
+ extra_rdoc_files:
44
44
  - README.md
45
- files:
45
+ files:
46
46
  - MIT-LICENSE
47
47
  - README.md
48
48
  - Rakefile
@@ -76,32 +76,27 @@ files:
76
76
  - spec/spec_helper.rb
77
77
  - spec/storage_spec.rb
78
78
  - translate-rails3.gemspec
79
- homepage: https://github.com/romanbsd/translate
79
+ homepage: https://github.com/gsmedley/translate
80
80
  licenses: []
81
-
81
+ metadata: {}
82
82
  post_install_message:
83
83
  rdoc_options: []
84
-
85
- require_paths:
84
+ require_paths:
86
85
  - lib
87
- required_ruby_version: !ruby/object:Gem::Requirement
88
- none: false
89
- requirements:
86
+ required_ruby_version: !ruby/object:Gem::Requirement
87
+ requirements:
90
88
  - - ">="
91
- - !ruby/object:Gem::Version
92
- version: "0"
93
- required_rubygems_version: !ruby/object:Gem::Requirement
94
- none: false
95
- requirements:
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ requirements:
96
93
  - - ">="
97
- - !ruby/object:Gem::Version
98
- version: "0"
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
99
96
  requirements: []
100
-
101
97
  rubyforge_project:
102
- rubygems_version: 1.8.15
98
+ rubygems_version: 2.4.3
103
99
  signing_key:
104
- specification_version: 3
100
+ specification_version: 4
105
101
  summary: Newsdesk translate plugin for Rails 3
106
102
  test_files: []
107
-