tr8n_core 4.0.17 → 4.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +7 -9
- data/lib/tr8n/{api_client.rb → api/client.rb} +66 -30
- data/lib/tr8n/api/post_office.rb +71 -0
- data/lib/tr8n/application.rb +115 -102
- data/lib/tr8n/base.rb +1 -1
- data/lib/tr8n/cache.rb +13 -1
- data/lib/tr8n/cache_adapters/file.rb +18 -11
- data/lib/tr8n/cache_adapters/memcache.rb +5 -5
- data/lib/tr8n/cache_adapters/memory.rb +85 -0
- data/lib/tr8n/component.rb +4 -4
- data/lib/tr8n/config.rb +5 -5
- data/lib/tr8n/decorators/base.rb +9 -1
- data/lib/tr8n/decorators/default.rb +5 -1
- data/lib/tr8n/decorators/html.rb +43 -12
- data/lib/tr8n/language.rb +23 -16
- data/lib/tr8n/language_case.rb +5 -29
- data/lib/tr8n/language_case_rule.rb +8 -26
- data/lib/tr8n/language_context.rb +5 -15
- data/lib/tr8n/language_context_rule.rb +3 -18
- data/lib/tr8n/logger.rb +16 -4
- data/lib/tr8n/session.rb +71 -13
- data/lib/tr8n/source.rb +45 -11
- data/lib/tr8n/translation.rb +1 -44
- data/lib/tr8n/translation_key.rb +10 -22
- data/lib/tr8n/translator.rb +5 -13
- data/lib/tr8n/utils.rb +6 -2
- data/lib/tr8n_core.rb +3 -2
- data/lib/tr8n_core/ext/array.rb +1 -1
- data/lib/tr8n_core/ext/date.rb +1 -2
- data/lib/tr8n_core/ext/fixnum.rb +1 -1
- data/lib/tr8n_core/ext/hash.rb +1 -1
- data/lib/tr8n_core/ext/string.rb +1 -1
- data/lib/tr8n_core/ext/time.rb +1 -1
- data/lib/tr8n_core/generators/cache/base.rb +40 -18
- data/lib/tr8n_core/generators/cache/cdb.rb +1 -1
- data/lib/tr8n_core/generators/cache/file.rb +99 -21
- data/lib/tr8n_core/languages/{en-US.json → en.json} +2 -2
- data/lib/tr8n_core/version.rb +2 -2
- metadata +6 -4
data/lib/tr8n/translation_key.rb
CHANGED
@@ -59,7 +59,7 @@ class Tr8n::TranslationKey < Tr8n::Base
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
-
def self.generate_key(label, desc =
|
62
|
+
def self.generate_key(label, desc = '')
|
63
63
|
"#{Digest::MD5.hexdigest("#{label};;;#{desc}")}~"[0..-2].to_s
|
64
64
|
end
|
65
65
|
|
@@ -67,39 +67,27 @@ class Tr8n::TranslationKey < Tr8n::Base
|
|
67
67
|
translations and translations[language.locale] and translations[language.locale].any?
|
68
68
|
end
|
69
69
|
|
70
|
-
def
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
70
|
+
def set_translations(locale, translations)
|
71
|
+
translations.each do |translation|
|
72
|
+
translation.locale ||= locale
|
73
|
+
translation.translation_key = self
|
74
|
+
translation.language = self.application.language(translation.locale)
|
75
75
|
end
|
76
|
-
|
77
|
-
tkey = application.post("translation_key/translations",
|
78
|
-
{:key => key, :label => label, :description => description, :locale => language.locale},
|
79
|
-
{:class => Tr8n::TranslationKey, :attributes => {:application => application}})
|
80
|
-
|
81
|
-
application.cache_translation_key(tkey)
|
76
|
+
self.translations[locale] = translations
|
82
77
|
end
|
83
78
|
|
84
79
|
# switches to a new application
|
85
80
|
def set_application(app)
|
86
81
|
self.application = app
|
87
82
|
translations.values.each do |locale_translations|
|
88
|
-
locale_translations.each do |
|
89
|
-
|
83
|
+
locale_translations.each do |translation|
|
84
|
+
translation.translation_key = self
|
85
|
+
translation.language = self.application.language(translation.locale)
|
90
86
|
end
|
91
87
|
end
|
92
88
|
self
|
93
89
|
end
|
94
90
|
|
95
|
-
def set_language_translations(language, translations)
|
96
|
-
translations.each do |translation|
|
97
|
-
translation.locale = language.locale
|
98
|
-
translation.set_translation_key(self)
|
99
|
-
end
|
100
|
-
self.translations[language.locale] = translations
|
101
|
-
end
|
102
|
-
|
103
91
|
###############################################################
|
104
92
|
## Translation Methods
|
105
93
|
###############################################################
|
data/lib/tr8n/translator.rb
CHANGED
@@ -30,31 +30,29 @@
|
|
30
30
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
31
31
|
#++
|
32
32
|
|
33
|
-
require 'digest/md5'
|
34
|
-
|
35
33
|
class Tr8n::Translator < Tr8n::Base
|
36
34
|
belongs_to :application
|
37
|
-
attributes :id, :name, :email, :gender, :mugshot, :link, :inline, :features
|
35
|
+
attributes :id, :name, :email, :gender, :mugshot, :link, :inline, :features, :image_url
|
38
36
|
attributes :voting_power, :rank, :level, :locale, :manager, :code, :access_token
|
39
37
|
|
40
38
|
def self.authorize(application, username, password, options = {})
|
41
|
-
data = application.get('oauth/request_token', {:grant_type => :password, :username => username, :password => password})
|
39
|
+
data = application.api_client.get('oauth/request_token', {:grant_type => :password, :username => username, :password => password})
|
42
40
|
init(application, data['access_token'])
|
43
41
|
end
|
44
42
|
|
45
43
|
def self.init(application, access_token)
|
46
|
-
application.get('translator', {:access_token => access_token}, {:class => Tr8n::Translator, :attributes => {
|
44
|
+
application.api_client.get('translator', {:access_token => access_token}, {:class => Tr8n::Translator, :attributes => {
|
47
45
|
:application => application,
|
48
46
|
:access_token => access_token
|
49
47
|
}})
|
50
48
|
end
|
51
49
|
|
52
50
|
def applications
|
53
|
-
application.get(
|
51
|
+
application.api_client.get('translator/applications', {:access_token => access_token}, {:class => Tr8n::Application})
|
54
52
|
end
|
55
53
|
|
56
54
|
def translations
|
57
|
-
application.get(
|
55
|
+
application.api_client.get('translator/translations', {:access_token => access_token}, {:class => Tr8n::Application})
|
58
56
|
end
|
59
57
|
|
60
58
|
def feature_enabled?(key)
|
@@ -62,12 +60,6 @@ class Tr8n::Translator < Tr8n::Base
|
|
62
60
|
hash_value(features, key)
|
63
61
|
end
|
64
62
|
|
65
|
-
def mugshot_url
|
66
|
-
return nil unless email
|
67
|
-
gravatar_id = Digest::MD5.hexdigest(email.downcase)
|
68
|
-
"http://gravatar.com/avatar/#{gravatar_id}.png?s=48"
|
69
|
-
end
|
70
|
-
|
71
63
|
def inline?
|
72
64
|
return Tr8n.session.block_options[:inline] unless Tr8n.session.block_options[:inline].nil?
|
73
65
|
super
|
data/lib/tr8n/utils.rb
CHANGED
@@ -105,11 +105,15 @@ module Tr8n
|
|
105
105
|
signed_request = URI::decode(signed_request)
|
106
106
|
signed_request = Base64.decode64(signed_request)
|
107
107
|
|
108
|
-
|
108
|
+
parts = signed_request.split('.')
|
109
|
+
return JSON.parse(Base64.decode64(parts.first)) if parts.size == 1
|
110
|
+
|
111
|
+
encoded_sig = parts.first
|
112
|
+
payload = parts.last
|
109
113
|
expected_sig = OpenSSL::HMAC.digest('sha256', secret, payload)
|
110
114
|
expected_sig = Base64.encode64(expected_sig)
|
111
115
|
if expected_sig != encoded_sig
|
112
|
-
raise Tr8n::Exception.new(
|
116
|
+
raise Tr8n::Exception.new('Bad signature')
|
113
117
|
end
|
114
118
|
|
115
119
|
JSON.parse(Base64.decode64(payload))
|
data/lib/tr8n_core.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
#--
|
3
|
-
# Copyright (c)
|
3
|
+
# Copyright (c) 2015 Translation Exchange Inc. http://translationexchange.com
|
4
4
|
#
|
5
5
|
# _______ _ _ _ ______ _
|
6
6
|
# |__ __| | | | | (_) | ____| | |
|
@@ -38,6 +38,7 @@ module Tr8nCore
|
|
38
38
|
end
|
39
39
|
|
40
40
|
module Tr8n
|
41
|
+
module Api end
|
41
42
|
module Tokens end
|
42
43
|
module Tokenizers end
|
43
44
|
module Rules end
|
@@ -45,7 +46,7 @@ module Tr8n
|
|
45
46
|
module CacheAdapters end
|
46
47
|
end
|
47
48
|
|
48
|
-
%w(tr8n/base.rb tr8n tr8n/rules_engine tr8n/tokens tr8n/tokenizers tr8n/decorators tr8n/cache_adapters tr8n/cache tr8n/cache/generators tr8n_core/ext tr8n_core/modules tr8n_core/generators/cache).each do |f|
|
49
|
+
%w(tr8n/base.rb tr8n tr8n/api tr8n/rules_engine tr8n/tokens tr8n/tokenizers tr8n/decorators tr8n/cache_adapters tr8n/cache tr8n/cache/generators tr8n_core/ext tr8n_core/modules tr8n_core/generators/cache).each do |f|
|
49
50
|
if f.index('.rb')
|
50
51
|
require(File.expand_path(File.join(File.dirname(__FILE__), f)))
|
51
52
|
next
|
data/lib/tr8n_core/ext/array.rb
CHANGED
data/lib/tr8n_core/ext/date.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c)
|
2
|
+
# Copyright (c) 2015 Translation Exchange Inc. http://translationexchange.com
|
3
3
|
#
|
4
4
|
# _______ _ _ _ ______ _
|
5
5
|
# |__ __| | | | | (_) | ____| | |
|
@@ -69,7 +69,6 @@ class Date
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
|
73
72
|
tokens = {}
|
74
73
|
selected_tokens.each do |token|
|
75
74
|
case token
|
data/lib/tr8n_core/ext/fixnum.rb
CHANGED
data/lib/tr8n_core/ext/hash.rb
CHANGED
data/lib/tr8n_core/ext/string.rb
CHANGED
data/lib/tr8n_core/ext/time.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c)
|
2
|
+
# Copyright (c) 2015 Translation Exchange Inc. http://translationexchange.com
|
3
3
|
#
|
4
4
|
# _______ _ _ _ ______ _
|
5
5
|
# |__ __| | | | | (_) | ____| | |
|
@@ -34,19 +34,25 @@ class Tr8nCore::Generators::Cache::Base
|
|
34
34
|
attr_accessor :started_at, :finished_at
|
35
35
|
|
36
36
|
def log(msg)
|
37
|
-
|
37
|
+
msg = "#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}: #{msg}"
|
38
|
+
puts msg
|
39
|
+
Tr8n.logger.debug(msg)
|
38
40
|
end
|
39
41
|
|
40
42
|
def cache_path
|
41
|
-
raise Tr8n::Exception.new(
|
43
|
+
raise Tr8n::Exception.new('Must be implemented by the subclass')
|
44
|
+
end
|
45
|
+
|
46
|
+
def cache_version
|
47
|
+
@started_at.strftime('%Y%m%d%H%M%S')
|
42
48
|
end
|
43
49
|
|
44
50
|
def cache(key, data)
|
45
|
-
raise Tr8n::Exception.new(
|
51
|
+
raise Tr8n::Exception.new('Must be implemented by the subclass')
|
46
52
|
end
|
47
53
|
|
48
54
|
def execute
|
49
|
-
raise Tr8n::Exception.new(
|
55
|
+
raise Tr8n::Exception.new('Must be implemented by the subclass')
|
50
56
|
end
|
51
57
|
|
52
58
|
def run
|
@@ -57,39 +63,55 @@ class Tr8nCore::Generators::Cache::Base
|
|
57
63
|
|
58
64
|
def prepare
|
59
65
|
@started_at = Time.now
|
66
|
+
Tr8n.session.init
|
67
|
+
cache_path
|
68
|
+
end
|
69
|
+
|
70
|
+
def api_client
|
71
|
+
Tr8n.session.application.api_client
|
72
|
+
end
|
73
|
+
|
74
|
+
def application
|
75
|
+
@application ||= api_client.get('applications/current', {:definition => true})
|
76
|
+
end
|
77
|
+
|
78
|
+
def languages
|
79
|
+
application['languages']
|
60
80
|
end
|
61
81
|
|
62
82
|
def finalize
|
63
83
|
@finished_at = Time.now
|
64
84
|
log("Cache has been stored in #{cache_path}")
|
65
85
|
log("Cache generation took #{@finished_at - @started_at} mls.")
|
66
|
-
log(
|
86
|
+
log('Done.')
|
67
87
|
end
|
68
88
|
|
69
89
|
def cache_application
|
70
|
-
log(
|
71
|
-
|
72
|
-
|
73
|
-
log("Application has been cached.")
|
74
|
-
app
|
90
|
+
log('Downloading application...')
|
91
|
+
cache(Tr8n::Application.cache_key, application)
|
92
|
+
log('Application has been cached.')
|
75
93
|
end
|
76
94
|
|
77
95
|
def cache_languages
|
78
|
-
log(
|
79
|
-
|
96
|
+
log('Downloading languages...')
|
97
|
+
unless application['languages']
|
98
|
+
log('No languages are available...')
|
99
|
+
return
|
100
|
+
end
|
80
101
|
languages.each do |lang|
|
81
|
-
|
102
|
+
language = api_client.get("languages/#{lang['locale']}", :definition => true)
|
103
|
+
cache(Tr8n::Language.cache_key(language['locale']), language)
|
82
104
|
end
|
83
|
-
log("#{languages.count} languages have been cached.")
|
84
|
-
languages
|
105
|
+
log("#{application['languages'].count} languages have been cached.")
|
85
106
|
end
|
86
107
|
|
87
108
|
def symlink_path
|
88
|
-
|
109
|
+
"#{Tr8n.config.cache[:path]}/current"
|
89
110
|
end
|
90
111
|
|
91
112
|
def generate_symlink
|
92
113
|
FileUtils.rm(symlink_path) if File.exist?(symlink_path)
|
93
|
-
FileUtils.ln_s(
|
114
|
+
FileUtils.ln_s(cache_version, symlink_path)
|
115
|
+
log('Symlink has been updated.')
|
94
116
|
end
|
95
117
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
#--
|
2
|
-
# Copyright (c)
|
2
|
+
# Copyright (c) 2015 Translation Exchange Inc. http://translationexchange.com
|
3
3
|
#
|
4
4
|
# _______ _ _ _ ______ _
|
5
5
|
# |__ __| | | | | (_) | ____| | |
|
@@ -33,7 +33,7 @@ class Tr8nCore::Generators::Cache::File < Tr8nCore::Generators::Cache::Base
|
|
33
33
|
|
34
34
|
def cache_path
|
35
35
|
@cache_path ||= begin
|
36
|
-
path = "#{Tr8n.config.cache[:path]}
|
36
|
+
path = "#{Tr8n.config.cache[:path]}/#{cache_version}"
|
37
37
|
log("Cache will be stored in #{path}")
|
38
38
|
FileUtils.mkdir_p(path)
|
39
39
|
FileUtils.chmod(0777, path)
|
@@ -42,40 +42,118 @@ class Tr8nCore::Generators::Cache::File < Tr8nCore::Generators::Cache::Base
|
|
42
42
|
end
|
43
43
|
|
44
44
|
def file_path(key)
|
45
|
-
|
45
|
+
path = key.split('/')
|
46
|
+
if path.count > 1
|
47
|
+
filename = path.pop
|
48
|
+
path = File.join(cache_path, path)
|
49
|
+
FileUtils.mkdir_p(path)
|
50
|
+
File.join(path, "#{filename}.json")
|
51
|
+
else
|
52
|
+
File.join(cache_path, "#{path.first}.json")
|
53
|
+
end
|
46
54
|
end
|
47
55
|
|
48
56
|
def cache(key, data)
|
49
57
|
File.open(file_path(key), 'w') { |file| file.write(JSON.pretty_generate(data)) }
|
50
58
|
end
|
51
59
|
|
52
|
-
def symlink_path
|
53
|
-
Tr8n::CacheAdapters::File.cache_path
|
54
|
-
end
|
55
|
-
|
56
60
|
def execute
|
57
|
-
Tr8n.session.init_application
|
58
61
|
cache_application
|
59
|
-
|
62
|
+
cache_languages
|
60
63
|
cache_translations
|
61
64
|
generate_symlink
|
62
65
|
end
|
63
66
|
|
64
67
|
def cache_translations
|
65
|
-
log(
|
66
|
-
|
67
|
-
|
68
|
-
log("
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
68
|
+
log('Downloading translations...')
|
69
|
+
|
70
|
+
languages.each do |language|
|
71
|
+
log("Downloading #{language['english_name']} language...")
|
72
|
+
|
73
|
+
if Tr8n.config.cache[:segmented]
|
74
|
+
api_client.paginate('applications/current/sources') do |source|
|
75
|
+
next unless source['source']
|
76
|
+
|
77
|
+
cache_path = Tr8n::Source.cache_key(language['locale'], source['source'])
|
78
|
+
log("Downloading #{source['source']} in #{language['locale']} to #{cache_path}...")
|
79
|
+
|
80
|
+
data = api_client.get("sources/#{source['key']}/translations", {:locale => language['locale'], :original => true, :per_page => 1000})
|
81
|
+
cache(cache_path, data)
|
82
|
+
end
|
83
|
+
else
|
84
|
+
cache_path = Tr8n::Application.translations_cache_key(language['locale'])
|
85
|
+
log("Downloading translations in #{language['locale']} to #{cache_path}...")
|
86
|
+
data = {}
|
87
|
+
api_client.paginate('applications/current/translations', {:locale => language['locale'], :original => true, :per_page => 1000}) do |translations|
|
88
|
+
data.merge!(translations)
|
89
|
+
end
|
90
|
+
cache(cache_path, data)
|
77
91
|
end
|
78
92
|
end
|
79
93
|
end
|
80
94
|
|
95
|
+
def rollback
|
96
|
+
folders = Dir["#{Tr8n.config.cache[:path]}/*"]
|
97
|
+
folders.delete_if{|e| e.index('current')}.sort!
|
98
|
+
|
99
|
+
if File.exist?(symlink_path)
|
100
|
+
current_dest = File.readlink("#{Tr8n.config.cache[:path]}/current")
|
101
|
+
current_dest = "#{Tr8n.config.cache[:path]}/#{current_dest}"
|
102
|
+
else
|
103
|
+
current_dest = 'undefined'
|
104
|
+
end
|
105
|
+
|
106
|
+
index = folders.index(current_dest)
|
107
|
+
|
108
|
+
if index == 0
|
109
|
+
log('There are no earlier cache versions')
|
110
|
+
return
|
111
|
+
end
|
112
|
+
|
113
|
+
if index.nil?
|
114
|
+
new_version_path = folders[folders.size-1]
|
115
|
+
else
|
116
|
+
new_version_path = folders[index-1]
|
117
|
+
end
|
118
|
+
|
119
|
+
new_version_path = new_version_path.split('/').last
|
120
|
+
|
121
|
+
FileUtils.rm(symlink_path) if File.exist?(symlink_path)
|
122
|
+
FileUtils.ln_s(new_version_path, symlink_path)
|
123
|
+
|
124
|
+
log("Cache has been rolled back to version #{new_version_path}.")
|
125
|
+
end
|
126
|
+
|
127
|
+
def rollup
|
128
|
+
folders = Dir["#{Tr8n.config.cache[:path]}/*"]
|
129
|
+
folders.delete_if{|e| e.index('current')}.sort!
|
130
|
+
|
131
|
+
if File.exist?(symlink_path)
|
132
|
+
current_dest = File.readlink("#{Tr8n.config.cache[:path]}/current")
|
133
|
+
current_dest = "#{Tr8n.config.cache[:path]}/#{current_dest}"
|
134
|
+
else
|
135
|
+
current_dest = 'undefined'
|
136
|
+
end
|
137
|
+
|
138
|
+
index = folders.index(current_dest)
|
139
|
+
|
140
|
+
if index == (folders.size - 1)
|
141
|
+
log('You are on the latest version of the cache already. No further versions are available')
|
142
|
+
return
|
143
|
+
end
|
144
|
+
|
145
|
+
if index.nil?
|
146
|
+
new_version_path = folders[0]
|
147
|
+
else
|
148
|
+
new_version_path = folders[index+1]
|
149
|
+
end
|
150
|
+
|
151
|
+
new_version_path = new_version_path.split('/').last
|
152
|
+
|
153
|
+
FileUtils.rm(symlink_path) if File.exist?(symlink_path)
|
154
|
+
FileUtils.ln_s(new_version_path, symlink_path)
|
155
|
+
|
156
|
+
log("Cache has been upgraded to version #{new_version_path}.")
|
157
|
+
end
|
158
|
+
|
81
159
|
end
|