ymdp 0.0.3
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.
- data/.document +5 -0
- data/.gitignore +21 -0
- data/LICENSE +20 -0
- data/README.rdoc +17 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/lib/application_view/application_view.rb +210 -0
- data/lib/application_view/asset_tag_helper.rb +106 -0
- data/lib/application_view/commands/generate.rb +3 -0
- data/lib/application_view/compiler/template_compiler.rb +417 -0
- data/lib/application_view/config.rb +39 -0
- data/lib/application_view/environment.rb +29 -0
- data/lib/application_view/generator/base.rb +15 -0
- data/lib/application_view/generator/templates/javascript.js +51 -0
- data/lib/application_view/generator/templates/stylesheet.css +5 -0
- data/lib/application_view/generator/templates/translation.pres +8 -0
- data/lib/application_view/generator/templates/view.html.haml +8 -0
- data/lib/application_view/generator/view.rb +170 -0
- data/lib/application_view/helpers.rb +4 -0
- data/lib/application_view/processor/compressor.rb +81 -0
- data/lib/application_view/processor/processor.rb +132 -0
- data/lib/application_view/processor/validator.rb +125 -0
- data/lib/application_view/support/file.rb +54 -0
- data/lib/application_view/support/form_post.rb +58 -0
- data/lib/application_view/support/g.rb +11 -0
- data/lib/application_view/support/growl.rb +36 -0
- data/lib/application_view/support/timer.rb +40 -0
- data/lib/application_view/support/w3c.rb +22 -0
- data/lib/application_view/tag_helper.rb +147 -0
- data/lib/application_view/translator/base.rb +387 -0
- data/lib/application_view/translator/blank.rb +58 -0
- data/lib/application_view/translator/ymdp_translate.rb +92 -0
- data/lib/ymdp.rb +1 -0
- data/test/helper.rb +10 -0
- data/test/test_ymdp.rb +4 -0
- data/ymdp.gemspec +77 -0
- metadata +92 -0
@@ -0,0 +1,387 @@
|
|
1
|
+
require 'rtranslate'
|
2
|
+
require 'support/timer'
|
3
|
+
require 'compiler/template_compiler'
|
4
|
+
require 'translator/ymdp_translate'
|
5
|
+
|
6
|
+
module ApplicationView
|
7
|
+
module Yaml
|
8
|
+
module Support
|
9
|
+
FILENAME_REGEXP = /(.*)_(..-..)\.yml$/
|
10
|
+
|
11
|
+
def language_path(lang)
|
12
|
+
"#{BASE_PATH}/app/assets/yrb/#{lang}"
|
13
|
+
end
|
14
|
+
|
15
|
+
def base_filename(path)
|
16
|
+
filename = path.split("/").last
|
17
|
+
filename =~ FILENAME_REGEXP
|
18
|
+
$1
|
19
|
+
end
|
20
|
+
|
21
|
+
def language(path)
|
22
|
+
filename = path.split("/").last
|
23
|
+
filename =~ FILENAME_REGEXP
|
24
|
+
$2
|
25
|
+
end
|
26
|
+
|
27
|
+
def destination_path(filename, lang)
|
28
|
+
filename ||= base_filename(filename)
|
29
|
+
"#{language_path(lang)}/#{filename}_#{lang}.yml"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
module YRB
|
35
|
+
module Support
|
36
|
+
FILENAME_REGEXP = /(.*)_(..-..)\.pres$/
|
37
|
+
|
38
|
+
def language_path(lang)
|
39
|
+
"#{BASE_PATH}/app/assets/yrb/#{lang}"
|
40
|
+
end
|
41
|
+
|
42
|
+
def base_filename(path)
|
43
|
+
filename = path.split("/").last
|
44
|
+
filename =~ FILENAME_REGEXP
|
45
|
+
$1
|
46
|
+
end
|
47
|
+
|
48
|
+
def language(path)
|
49
|
+
filename = path.split("/").last
|
50
|
+
filename =~ FILENAME_REGEXP
|
51
|
+
$2
|
52
|
+
end
|
53
|
+
|
54
|
+
def destination_path(filename, lang)
|
55
|
+
filename ||= base_filename(filename)
|
56
|
+
"#{language_path(lang)}/#{filename}_#{lang}.pres"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
module Translator
|
62
|
+
module Support
|
63
|
+
# Mapping of the way Yahoo! Mail represents country codes with the way Google Translate does.
|
64
|
+
#
|
65
|
+
# The key is the Yahoo! Mail representation, and the value is the code Google Translate would expect.
|
66
|
+
#
|
67
|
+
LOCALES = {
|
68
|
+
"de-DE" => "de",
|
69
|
+
"en-MY" => "en",
|
70
|
+
"en-SG" => "en",
|
71
|
+
"es-MX" => "es",
|
72
|
+
"it-IT" => "it",
|
73
|
+
"vi-VN" => "vi",
|
74
|
+
"zh-Hant-TW" => "zh-TW",
|
75
|
+
"en-AA" => "en",
|
76
|
+
"en-NZ" => "en",
|
77
|
+
"en-US" => "en",
|
78
|
+
"fr-FR" => "fr",
|
79
|
+
"ko-KR" => "ko",
|
80
|
+
"zh-Hans-CN" => "zh-CN",
|
81
|
+
"en-AU" => "en",
|
82
|
+
"en-PH" => "en",
|
83
|
+
"es-ES" => "es",
|
84
|
+
"id-ID" => "id",
|
85
|
+
"pt-BR" => "PORTUGUESE",
|
86
|
+
"zh-Hant-HK" => "zh-CN",
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
90
|
+
#
|
91
|
+
# Finds English language translation keys which have not been translated
|
92
|
+
# and translates them through Google Translate.
|
93
|
+
#
|
94
|
+
# Usage:
|
95
|
+
# ApplicationView::Translator::Base.new().translate
|
96
|
+
#
|
97
|
+
class Base
|
98
|
+
include ApplicationView::FileSupport
|
99
|
+
extend ApplicationView::FileSupport
|
100
|
+
include ApplicationView::Support::Timer
|
101
|
+
include ApplicationView::Translator::Support
|
102
|
+
|
103
|
+
def self.original_translations
|
104
|
+
Dir["#{language_path('en-US')}/#{all_source_files}"]
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.all_source_files
|
108
|
+
raise "Define in child"
|
109
|
+
end
|
110
|
+
|
111
|
+
def self.template
|
112
|
+
raise "Define in child"
|
113
|
+
end
|
114
|
+
|
115
|
+
def self.translate
|
116
|
+
time do
|
117
|
+
original_translations.each do |path|
|
118
|
+
puts "Processing #{display_path(path)}"
|
119
|
+
template.new(path).copy
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# instance methods
|
125
|
+
|
126
|
+
attr_accessor :path, :lang, :filename
|
127
|
+
|
128
|
+
def initialize(path)
|
129
|
+
@path = path
|
130
|
+
@lang = language(path)
|
131
|
+
@filename = base_filename(path)
|
132
|
+
end
|
133
|
+
|
134
|
+
def copy
|
135
|
+
copy_lines_to_all_locales
|
136
|
+
end
|
137
|
+
|
138
|
+
def non_english_locales
|
139
|
+
@non_english_locales ||= LOCALES.select do |lang, code|
|
140
|
+
lang !~ /^en/
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def non_us_locales
|
145
|
+
@non_us_locales ||= LOCALES.select do |lang, code|
|
146
|
+
lang != "en-US"
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def copy_lines_to_all_locales
|
151
|
+
non_us_locales.each do |lang, code|
|
152
|
+
destination = destination_path(filename, lang)
|
153
|
+
new_content = each_line do |line|
|
154
|
+
copy_and_translate_line(line, lang)
|
155
|
+
end
|
156
|
+
write_content(destination, new_content)
|
157
|
+
clear_all_keys
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def write_content(destination, content)
|
162
|
+
unless content.blank?
|
163
|
+
puts "Writing to #{display_path(destination)}"
|
164
|
+
puts content
|
165
|
+
puts
|
166
|
+
File.open(destination, "a") do |f|
|
167
|
+
f.puts
|
168
|
+
f.puts new_translation_message
|
169
|
+
f.puts content
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
def new_translation_message
|
175
|
+
now = Time.now
|
176
|
+
|
177
|
+
date = now.day
|
178
|
+
month = now.month
|
179
|
+
year = now.year
|
180
|
+
|
181
|
+
timestamp = "#{date}/#{month}/#{year}"
|
182
|
+
output = []
|
183
|
+
output << "# "
|
184
|
+
output << "# Keys translated automatically on #{timestamp}."
|
185
|
+
output << "# "
|
186
|
+
|
187
|
+
output.join("\n")
|
188
|
+
end
|
189
|
+
|
190
|
+
def each_line
|
191
|
+
output = []
|
192
|
+
File.open(path, "r") do |f|
|
193
|
+
f.readlines.each do |line|
|
194
|
+
new_line = yield line
|
195
|
+
output << new_line
|
196
|
+
end
|
197
|
+
end
|
198
|
+
output.flatten.join("\n")
|
199
|
+
end
|
200
|
+
|
201
|
+
def all_keys(lang)
|
202
|
+
unless @all_keys
|
203
|
+
@all_keys = {}
|
204
|
+
Dir["#{language_path(lang)}/#{all_source_files}"].each do |p|
|
205
|
+
@all_keys = @all_keys.merge(parse_template(p))
|
206
|
+
end
|
207
|
+
end
|
208
|
+
@all_keys
|
209
|
+
end
|
210
|
+
|
211
|
+
def self.all_source_files
|
212
|
+
raise "Define in child"
|
213
|
+
end
|
214
|
+
|
215
|
+
def parse_template(p)
|
216
|
+
raise "Define in child"
|
217
|
+
end
|
218
|
+
|
219
|
+
def clear_all_keys
|
220
|
+
@all_keys = nil
|
221
|
+
end
|
222
|
+
|
223
|
+
def copy_and_translate_line(line, lang)
|
224
|
+
line = line.split("\n").first
|
225
|
+
if comment?(line) || line.blank?
|
226
|
+
nil
|
227
|
+
else
|
228
|
+
translate_new_key(line, lang)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def translate_new_key(line, lang)
|
233
|
+
k, v = key_and_value_from_line(line)
|
234
|
+
if k && !all_keys(lang).has_key?(k)
|
235
|
+
format(k, translate(v, lang))
|
236
|
+
else
|
237
|
+
nil
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
def translate(value, lang)
|
242
|
+
code = LOCALES[lang]
|
243
|
+
value = pre_process(value, lang)
|
244
|
+
translation = Translate.t(value, "ENGLISH", code)
|
245
|
+
post_process(translation, lang)
|
246
|
+
end
|
247
|
+
|
248
|
+
def pre_process(value, lang)
|
249
|
+
while value =~ /(\{\{[^\{]*\}\})/
|
250
|
+
vars << $1
|
251
|
+
value.sub!(/(\{\{[^\{]*\}\})/, "[#{index}]")
|
252
|
+
index += 1
|
253
|
+
end
|
254
|
+
value
|
255
|
+
end
|
256
|
+
|
257
|
+
def post_process(value, lang)
|
258
|
+
if lang =~ /zh/
|
259
|
+
value.gsub!("<strong>", "")
|
260
|
+
value.gsub!("</strong>", "")
|
261
|
+
end
|
262
|
+
|
263
|
+
value.gsub!(/^#{194.chr}#{160.chr}/, "")
|
264
|
+
|
265
|
+
value.gsub!(" ]", "]")
|
266
|
+
value.gsub!("«", "\"")
|
267
|
+
value.gsub!("»", "\"")
|
268
|
+
value.gsub!(/\"\.$/, ".\"")
|
269
|
+
value.gsub!(/\\ \"/, "\\\"")
|
270
|
+
value.gsub!(/<\/ /, "<\/")
|
271
|
+
value.gsub!(/(“|”)/, "\"")
|
272
|
+
value.gsub!("<strong> ", "<strong>")
|
273
|
+
value.gsub!(" </strong>", "</strong>")
|
274
|
+
value.gsub!(""", "\"")
|
275
|
+
value.gsub!("'", "\"")
|
276
|
+
value.gsub!("> ", ">")
|
277
|
+
|
278
|
+
value.gsub!("\"", "'")
|
279
|
+
value.gsub!(" \"O", " \\\"O")
|
280
|
+
|
281
|
+
while value =~ /\[(\d)\]/
|
282
|
+
index = $1.to_i
|
283
|
+
value.sub!(/\[#{index}\]/, vars[index])
|
284
|
+
end
|
285
|
+
|
286
|
+
value.gsub!(/\((0)\)/, "{0}")
|
287
|
+
value.gsub!(/\((1)\)/, "{1}")
|
288
|
+
value.gsub!(/\((2)\)/, "{2}")
|
289
|
+
value.gsub!("(0)", "{0}")
|
290
|
+
|
291
|
+
value.strip
|
292
|
+
end
|
293
|
+
|
294
|
+
def format(key, value)
|
295
|
+
raise "Define in child"
|
296
|
+
end
|
297
|
+
|
298
|
+
def key_and_value_from_line(line)
|
299
|
+
raise "Define in child"
|
300
|
+
end
|
301
|
+
|
302
|
+
def comment?(line)
|
303
|
+
raise "Define in child"
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
class Yaml < Base
|
308
|
+
include ApplicationView::Yaml::Support
|
309
|
+
extend ApplicationView::Yaml::Support
|
310
|
+
|
311
|
+
def self.template
|
312
|
+
Yaml
|
313
|
+
end
|
314
|
+
|
315
|
+
def self.all_source_files
|
316
|
+
"*.yml"
|
317
|
+
end
|
318
|
+
|
319
|
+
def all_source_files
|
320
|
+
"*.yml"
|
321
|
+
end
|
322
|
+
|
323
|
+
def parse_template(path)
|
324
|
+
YAML.load_file(path)
|
325
|
+
end
|
326
|
+
|
327
|
+
def format(key, value)
|
328
|
+
"#{key}: #{value}"
|
329
|
+
end
|
330
|
+
|
331
|
+
def key_and_value_from_line(line)
|
332
|
+
if line =~ /^([^\:]+):(.*)/
|
333
|
+
return $1, $2.strip
|
334
|
+
else
|
335
|
+
return nil, nil
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
def comment?(line)
|
340
|
+
line =~ /^[\s]*#/
|
341
|
+
end
|
342
|
+
end
|
343
|
+
|
344
|
+
class YRB < Base
|
345
|
+
include ApplicationView::YRB::Support
|
346
|
+
extend ApplicationView::YRB::Support
|
347
|
+
|
348
|
+
def self.template
|
349
|
+
YRB
|
350
|
+
end
|
351
|
+
|
352
|
+
def self.all_source_files
|
353
|
+
"*.pres"
|
354
|
+
end
|
355
|
+
|
356
|
+
def all_source_files
|
357
|
+
"*.pres"
|
358
|
+
end
|
359
|
+
|
360
|
+
def parse_template(p)
|
361
|
+
YRBTemplate.new(p).to_hash
|
362
|
+
end
|
363
|
+
|
364
|
+
def format(key, value)
|
365
|
+
"#{key}=#{value}"
|
366
|
+
end
|
367
|
+
|
368
|
+
def translate(value, lang)
|
369
|
+
unless value.blank?
|
370
|
+
super(value, lang)
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
374
|
+
def key_and_value_from_line(line)
|
375
|
+
if line =~ /^([^\=]+)=(.+)/
|
376
|
+
return $1, $2
|
377
|
+
else
|
378
|
+
return nil, nil
|
379
|
+
end
|
380
|
+
end
|
381
|
+
|
382
|
+
def comment?(line)
|
383
|
+
line =~ /^[\s]*#/
|
384
|
+
end
|
385
|
+
end
|
386
|
+
end
|
387
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
class Object
|
2
|
+
# An object is blank if it's false, empty, or a whitespace string.
|
3
|
+
# For example, "", " ", +nil+, [], and {} are blank.
|
4
|
+
#
|
5
|
+
# This simplifies
|
6
|
+
#
|
7
|
+
# if !address.nil? && !address.empty?
|
8
|
+
#
|
9
|
+
# to
|
10
|
+
#
|
11
|
+
# if !address.blank?
|
12
|
+
def blank?
|
13
|
+
respond_to?(:empty?) ? empty? : !self
|
14
|
+
end
|
15
|
+
|
16
|
+
# An object is present if it's not blank.
|
17
|
+
def present?
|
18
|
+
!blank?
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class NilClass #:nodoc:
|
23
|
+
def blank?
|
24
|
+
true
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class FalseClass #:nodoc:
|
29
|
+
def blank?
|
30
|
+
true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class TrueClass #:nodoc:
|
35
|
+
def blank?
|
36
|
+
false
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class Array #:nodoc:
|
41
|
+
alias_method :blank?, :empty?
|
42
|
+
end
|
43
|
+
|
44
|
+
class Hash #:nodoc:
|
45
|
+
alias_method :blank?, :empty?
|
46
|
+
end
|
47
|
+
|
48
|
+
class String #:nodoc:
|
49
|
+
def blank?
|
50
|
+
self !~ /\S/
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class Numeric #:nodoc:
|
55
|
+
def blank?
|
56
|
+
false
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
class YmdpTranslate
|
2
|
+
LOCALES = {
|
3
|
+
"de-DE" => "de",
|
4
|
+
"en-MY" => "en",
|
5
|
+
"en-SG" => "en",
|
6
|
+
"es-MX" => "es",
|
7
|
+
"it-IT" => "it",
|
8
|
+
"vi-VN" => "vi",
|
9
|
+
"zh-Hant-TW" => "zh-TW",
|
10
|
+
"en-AA" => "en",
|
11
|
+
"en-NZ" => "en",
|
12
|
+
"en-US" => "en",
|
13
|
+
"fr-FR" => "fr",
|
14
|
+
"ko-KR" => "ko",
|
15
|
+
"zh-Hans-CN" => "zh-CN",
|
16
|
+
"en-AU" => "en",
|
17
|
+
"en-PH" => "en",
|
18
|
+
"es-ES" => "es",
|
19
|
+
"id-ID" => "id",
|
20
|
+
"pt-BR" => "PORTUGUESE",
|
21
|
+
"zh-Hant-HK" => "zh-CN",
|
22
|
+
}
|
23
|
+
|
24
|
+
|
25
|
+
def self.translate(value, ymdp_lang)
|
26
|
+
error_results = []
|
27
|
+
|
28
|
+
lang = YmdpTranslate::LOCALES[ymdp_lang] || "en"
|
29
|
+
return value if lang =~ /en-/
|
30
|
+
|
31
|
+
index = 0
|
32
|
+
vars = []
|
33
|
+
value ||= ""
|
34
|
+
while value =~ /(\{\{[^\{]*\}\})/
|
35
|
+
vars << $1
|
36
|
+
value.sub!(/(\{\{[^\{]*\}\})/, "[#{index}]")
|
37
|
+
index += 1
|
38
|
+
end
|
39
|
+
result = Translate.t(value, "ENGLISH", lang)
|
40
|
+
|
41
|
+
if lang =~ /zh/
|
42
|
+
result.gsub!("<strong>", "")
|
43
|
+
result.gsub!("</strong>", "")
|
44
|
+
end
|
45
|
+
|
46
|
+
result.gsub!(" ]", "]")
|
47
|
+
result.gsub!("«", "\"")
|
48
|
+
result.gsub!("»", "\"")
|
49
|
+
result.gsub!(/\"\.$/, ".\"")
|
50
|
+
result.gsub!(/\\ \"/, "\\\"")
|
51
|
+
result.gsub!(/<\/ /, "<\/")
|
52
|
+
result.gsub!(/(“|”)/, "\"")
|
53
|
+
result.gsub!("<strong> ", "<strong>")
|
54
|
+
result.gsub!(" </strong>", "</strong>")
|
55
|
+
result.gsub!(""", "\"")
|
56
|
+
result.gsub!("'", "\"")
|
57
|
+
result.gsub!("> ", ">")
|
58
|
+
|
59
|
+
result.gsub!("l\"a", "l'a")
|
60
|
+
result.gsub!("l\"o", "l'o")
|
61
|
+
result.gsub!("l\"e", "l'e")
|
62
|
+
result.gsub!("L\"e", "L'e")
|
63
|
+
result.gsub!("l\"i", "l'i")
|
64
|
+
result.gsub!("l\"h", "l'h")
|
65
|
+
result.gsub!("c\"e", "c'e")
|
66
|
+
result.gsub!("d\"u", "d'u")
|
67
|
+
result.gsub!("d\"a", "d'a")
|
68
|
+
result.gsub!("d\"e", "d'e")
|
69
|
+
result.gsub!("u\"e", "u'e")
|
70
|
+
result.gsub!("d\"o", "d'o")
|
71
|
+
result.gsub!("D\"o", "D'o")
|
72
|
+
result.gsub!("n\"a", "n'a")
|
73
|
+
result.gsub!("n\"é", "n'é")
|
74
|
+
result.gsub!("j\"a", "j'a")
|
75
|
+
result.gsub!("S\"i", "S'i")
|
76
|
+
result.gsub!(" \"O", " \\\"O")
|
77
|
+
|
78
|
+
while result =~ /\[(\d)\]/
|
79
|
+
index = $1.to_i
|
80
|
+
result.sub!(/\[#{index}\]/, vars[index])
|
81
|
+
end
|
82
|
+
|
83
|
+
result.gsub!("(0)", "{0}")
|
84
|
+
result.gsub!("(0)", "{0}")
|
85
|
+
|
86
|
+
if result =~ /#{160.chr}/
|
87
|
+
result.gsub!(/^#{194.chr}#{160.chr}/, "")
|
88
|
+
end
|
89
|
+
|
90
|
+
result.strip
|
91
|
+
end
|
92
|
+
end
|