tml 5.2.7 → 5.4.1
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/LICENSE +1 -1
- data/README.md +2 -2
- data/lib/tml/api/client.rb +98 -43
- data/lib/tml/application.rb +22 -20
- data/lib/tml/cache.rb +111 -30
- data/lib/tml/cache_version.rb +135 -0
- data/lib/tml/config.rb +14 -10
- data/lib/tml/language.rb +5 -3
- data/lib/tml/language_case.rb +3 -3
- data/lib/tml/languages/en.json +643 -663
- data/lib/tml/session.rb +6 -3
- data/lib/tml/source.rb +1 -1
- data/lib/tml/utils.rb +30 -0
- data/lib/tml/version.rb +1 -1
- data/lib/tml.rb +1 -1
- metadata +3 -5
- data/lib/tml/api/post_office.rb +0 -71
- data/lib/tml/generators/base.rb +0 -122
- data/lib/tml/generators/file.rb +0 -72
@@ -0,0 +1,135 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
#--
|
3
|
+
# Copyright (c) 2016 Translation Exchange, Inc
|
4
|
+
#
|
5
|
+
# _______ _ _ _ ______ _
|
6
|
+
# |__ __| | | | | (_) | ____| | |
|
7
|
+
# | |_ __ __ _ _ __ ___| | __ _| |_ _ ___ _ __ | |__ __ _____| |__ __ _ _ __ __ _ ___
|
8
|
+
# | | '__/ _` | '_ \/ __| |/ _` | __| |/ _ \| '_ \| __| \ \/ / __| '_ \ / _` | '_ \ / _` |/ _ \
|
9
|
+
# | | | | (_| | | | \__ \ | (_| | |_| | (_) | | | | |____ > < (__| | | | (_| | | | | (_| | __/
|
10
|
+
# |_|_| \__,_|_| |_|___/_|\__,_|\__|_|\___/|_| |_|______/_/\_\___|_| |_|\__,_|_| |_|\__, |\___|
|
11
|
+
# __/ |
|
12
|
+
# |___/
|
13
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
14
|
+
# a copy of this software and associated documentation files (the
|
15
|
+
# "Software"), to deal in the Software without restriction, including
|
16
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
17
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
18
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
19
|
+
# the following conditions:
|
20
|
+
#
|
21
|
+
# The above copyright notice and this permission notice shall be
|
22
|
+
# included in all copies or substantial portions of the Software.
|
23
|
+
#
|
24
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
25
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
26
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
27
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
28
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
29
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
30
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
31
|
+
#++
|
32
|
+
|
33
|
+
module Tml
|
34
|
+
|
35
|
+
CACHE_VERSION_KEY = 'current_version'
|
36
|
+
|
37
|
+
class CacheVersion
|
38
|
+
|
39
|
+
attr_accessor :version, :cache
|
40
|
+
|
41
|
+
# Init cache version with cache adapter
|
42
|
+
def initialize(cache)
|
43
|
+
self.cache = cache
|
44
|
+
end
|
45
|
+
|
46
|
+
# reset cache version
|
47
|
+
def reset
|
48
|
+
self.version = nil
|
49
|
+
end
|
50
|
+
|
51
|
+
# updates the current cache version
|
52
|
+
def set(new_version)
|
53
|
+
self.version = new_version
|
54
|
+
end
|
55
|
+
|
56
|
+
# upgrade current version
|
57
|
+
def upgrade
|
58
|
+
cache.store(CACHE_VERSION_KEY, {'version' => 'undefined', 't' => cache_timestamp})
|
59
|
+
reset
|
60
|
+
end
|
61
|
+
|
62
|
+
# validate that current cache version hasn't expired
|
63
|
+
def validate_cache_version(version)
|
64
|
+
return version unless version.is_a?(Hash)
|
65
|
+
return 'undefined' unless version['t'].is_a?(Numeric)
|
66
|
+
return version['version'] if cache.read_only?
|
67
|
+
|
68
|
+
expires_at = version['t'] + version_check_interval
|
69
|
+
if expires_at < Time.now.to_i
|
70
|
+
Tml.logger.debug('Cache version is outdated, needs refresh')
|
71
|
+
'undefined'
|
72
|
+
else
|
73
|
+
delta = expires_at - Time.now.to_i
|
74
|
+
Tml.logger.debug("Cache version is up to date, expires in #{delta}s")
|
75
|
+
version['version']
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# fetches the version from the cache
|
80
|
+
def fetch
|
81
|
+
self.version = begin
|
82
|
+
ver = cache.fetch(CACHE_VERSION_KEY) do
|
83
|
+
{'version' => Tml.config.cache[:version] || 'undefined', 't' => cache_timestamp}
|
84
|
+
end
|
85
|
+
validate_cache_version(ver)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# how often should the cache be checked for
|
90
|
+
def version_check_interval
|
91
|
+
Tml.config.cache[:version_check_interval] || 3600
|
92
|
+
end
|
93
|
+
|
94
|
+
# generates cache timestamp based on an interval
|
95
|
+
def cache_timestamp
|
96
|
+
Tml::Utils.interval_timestamp(version_check_interval)
|
97
|
+
end
|
98
|
+
|
99
|
+
# stores the current version back in cache
|
100
|
+
def store(new_version)
|
101
|
+
self.version = new_version
|
102
|
+
cache.store(CACHE_VERSION_KEY, {'version' => new_version, 't' => cache_timestamp})
|
103
|
+
end
|
104
|
+
|
105
|
+
# checks if the version is undefined
|
106
|
+
def undefined?
|
107
|
+
version.nil? or version == 'undefined'
|
108
|
+
end
|
109
|
+
|
110
|
+
# checks if version is defined
|
111
|
+
def defined?
|
112
|
+
not undefined?
|
113
|
+
end
|
114
|
+
|
115
|
+
# checks if the version is valid
|
116
|
+
def valid?
|
117
|
+
not invalid?
|
118
|
+
end
|
119
|
+
|
120
|
+
# checks if the version is invalid
|
121
|
+
def invalid?
|
122
|
+
%w(undefined 0).include?(version.to_s)
|
123
|
+
end
|
124
|
+
|
125
|
+
# returns versioned key with prefix
|
126
|
+
def versioned_key(key, namespace = '')
|
127
|
+
"tml_#{namespace}#{CACHE_VERSION_KEY == key ? '' : "_v#{version}"}_#{key}"
|
128
|
+
end
|
129
|
+
|
130
|
+
# returns string representation of the version
|
131
|
+
def to_s
|
132
|
+
self.version.to_s
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
data/lib/tml/config.rb
CHANGED
@@ -80,20 +80,25 @@ module Tml
|
|
80
80
|
|
81
81
|
# Used by Rails and Sinatra extensions
|
82
82
|
attr_accessor :current_locale_method, :current_user_method, :translator_options, :i18n_backend
|
83
|
-
attr_accessor :invalidator, :agent, :
|
83
|
+
attr_accessor :invalidator, :agent, :api_client
|
84
84
|
|
85
85
|
# Used for IRB only
|
86
86
|
attr_accessor :submit_missing_keys_realtime
|
87
87
|
|
88
88
|
def initialize
|
89
89
|
@enabled = true
|
90
|
-
@api_client_class = Tml::Api::Client
|
91
90
|
@default_level = 0
|
92
91
|
@format = :html
|
93
92
|
@subdomains = false
|
94
93
|
@auto_init = true
|
95
94
|
@source_separator = '@:@'
|
96
95
|
|
96
|
+
@api_client = {
|
97
|
+
class: Tml::Api::Client,
|
98
|
+
timeout: 5,
|
99
|
+
open_timeout: 2
|
100
|
+
}
|
101
|
+
|
97
102
|
@locale = {
|
98
103
|
default: 'en',
|
99
104
|
method: 'current_locale',
|
@@ -196,14 +201,13 @@ module Tml
|
|
196
201
|
},
|
197
202
|
}
|
198
203
|
|
199
|
-
@
|
200
|
-
:enabled => false,
|
201
|
-
:path => './log/tml.log',
|
202
|
-
:level => 'debug'
|
203
|
-
}
|
204
|
+
@cache = nil
|
204
205
|
|
205
|
-
@
|
206
|
-
:enabled
|
206
|
+
@logger = {
|
207
|
+
:enabled => false,
|
208
|
+
:path => './log/tml.log',
|
209
|
+
:level => 'debug',
|
210
|
+
:secure => true
|
207
211
|
}
|
208
212
|
|
209
213
|
@default_tokens = {
|
@@ -356,7 +360,7 @@ module Tml
|
|
356
360
|
end
|
357
361
|
|
358
362
|
def cache_enabled?
|
359
|
-
|
363
|
+
not cache.nil?
|
360
364
|
end
|
361
365
|
|
362
366
|
#########################################################
|
data/lib/tml/language.rb
CHANGED
@@ -54,6 +54,7 @@ class Tml::Language < Tml::Base
|
|
54
54
|
self
|
55
55
|
end
|
56
56
|
|
57
|
+
# update language attributes
|
57
58
|
def update_attributes(attrs)
|
58
59
|
super
|
59
60
|
|
@@ -127,7 +128,6 @@ class Tml::Language < Tml::Base
|
|
127
128
|
# or
|
128
129
|
# tr(:label => label, :description => "", :tokens => {}, :options => {})
|
129
130
|
########################################################################################################
|
130
|
-
|
131
131
|
def translate(label, description = nil, tokens = {}, options = {})
|
132
132
|
params = Tml::Utils.normalize_tr_params(label, description, tokens, options)
|
133
133
|
return params[:label] if params[:label].to_s.strip == '' or params[:label].index('tml:label')
|
@@ -164,8 +164,9 @@ class Tml::Language < Tml::Base
|
|
164
164
|
return translation_key.translate(self, params[:tokens], params[:options]).tml_translated
|
165
165
|
end
|
166
166
|
|
167
|
-
# each key translations will be loaded directly from the API
|
167
|
+
# each key translations will be loaded directly from the API, and registered against "manual" source
|
168
168
|
if Tml.session.block_option(:by_key)
|
169
|
+
application.register_missing_key(:manual, translation_key)
|
169
170
|
translation_key.fetch_translations(locale)
|
170
171
|
return translation_key.translate(self, params[:tokens], params[:options]).tml_translated
|
171
172
|
end
|
@@ -181,7 +182,7 @@ class Tml::Language < Tml::Base
|
|
181
182
|
application.verify_source_path(source_key, current_source_path)
|
182
183
|
end
|
183
184
|
|
184
|
-
# Tml.logger.debug("#{params[:label]} : #{source_key}")
|
185
|
+
# Tml.logger.debug("#{self.locale} : #{params[:label]} : #{source_key}")
|
185
186
|
|
186
187
|
source = application.source(source_key, locale)
|
187
188
|
|
@@ -204,6 +205,7 @@ class Tml::Language < Tml::Base
|
|
204
205
|
end
|
205
206
|
alias :tr :translate
|
206
207
|
|
208
|
+
# build source path to the block
|
207
209
|
def source_path
|
208
210
|
sp = []
|
209
211
|
|
data/lib/tml/language_case.rb
CHANGED
@@ -35,7 +35,7 @@ class Tml::LanguageCase < Tml::Base
|
|
35
35
|
attributes :id, :keyword, :latin_name, :native_name, :description, :application
|
36
36
|
has_many :rules
|
37
37
|
|
38
|
-
|
38
|
+
TML_HTML_TAGS_REGEX = /<\/?[^>]*>/
|
39
39
|
|
40
40
|
def initialize(attrs = {})
|
41
41
|
super
|
@@ -63,8 +63,8 @@ class Tml::LanguageCase < Tml::Base
|
|
63
63
|
|
64
64
|
options = options.merge(:skip_decorations => true) if value.index('not_translated')
|
65
65
|
|
66
|
-
html_tokens = value.scan(
|
67
|
-
sanitized_value = value.gsub(
|
66
|
+
html_tokens = value.scan(TML_HTML_TAGS_REGEX).uniq
|
67
|
+
sanitized_value = value.gsub(TML_HTML_TAGS_REGEX, '')
|
68
68
|
|
69
69
|
if application.to_s == 'phrase'
|
70
70
|
words = [sanitized_value]
|