tr8n_core 4.0.17 → 4.2
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 +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
|