tr8n_core 4.0.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 +7 -0
- data/LICENSE +22 -0
- data/README.md +69 -0
- data/Rakefile +9 -0
- data/config/config.yml +34 -0
- data/config/tokens/data.yml +45 -0
- data/config/tokens/decorations.yml +37 -0
- data/lib/tr8n/application.rb +320 -0
- data/lib/tr8n/base.rb +123 -0
- data/lib/tr8n/cache.rb +144 -0
- data/lib/tr8n/cache_adapters/cdb.rb +74 -0
- data/lib/tr8n/cache_adapters/file.rb +70 -0
- data/lib/tr8n/cache_adapters/memcache.rb +91 -0
- data/lib/tr8n/cache_adapters/redis.rb +94 -0
- data/lib/tr8n/component.rb +68 -0
- data/lib/tr8n/config.rb +291 -0
- data/lib/tr8n/decorators/base.rb +35 -0
- data/lib/tr8n/decorators/default.rb +30 -0
- data/lib/tr8n/decorators/html.rb +63 -0
- data/lib/tr8n/exception.rb +26 -0
- data/lib/tr8n/language.rb +250 -0
- data/lib/tr8n/language_case.rb +116 -0
- data/lib/tr8n/language_case_rule.rb +85 -0
- data/lib/tr8n/language_context.rb +115 -0
- data/lib/tr8n/language_context_rule.rb +62 -0
- data/lib/tr8n/logger.rb +83 -0
- data/lib/tr8n/rules_engine/evaluator.rb +156 -0
- data/lib/tr8n/rules_engine/parser.rb +83 -0
- data/lib/tr8n/source.rb +95 -0
- data/lib/tr8n/tokens/data.rb +410 -0
- data/lib/tr8n/tokens/data_tokenizer.rb +82 -0
- data/lib/tr8n/tokens/decoration_tokenizer.rb +200 -0
- data/lib/tr8n/tokens/hidden.rb +48 -0
- data/lib/tr8n/tokens/method.rb +52 -0
- data/lib/tr8n/tokens/transform.rb +191 -0
- data/lib/tr8n/translation.rb +104 -0
- data/lib/tr8n/translation_key.rb +205 -0
- data/lib/tr8n/translator.rb +62 -0
- data/lib/tr8n/utils.rb +124 -0
- data/lib/tr8n_core/ext/array.rb +74 -0
- data/lib/tr8n_core/ext/date.rb +63 -0
- data/lib/tr8n_core/ext/fixnum.rb +39 -0
- data/lib/tr8n_core/ext/hash.rb +126 -0
- data/lib/tr8n_core/ext/string.rb +44 -0
- data/lib/tr8n_core/ext/time.rb +71 -0
- data/lib/tr8n_core/generators/cache/base.rb +85 -0
- data/lib/tr8n_core/generators/cache/cdb.rb +27 -0
- data/lib/tr8n_core/generators/cache/file.rb +69 -0
- data/lib/tr8n_core/modules/logger.rb +43 -0
- data/lib/tr8n_core/version.rb +27 -0
- data/lib/tr8n_core.rb +68 -0
- data/spec/application_spec.rb +228 -0
- data/spec/base_spec.rb +19 -0
- data/spec/config_spec.rb +16 -0
- data/spec/decorator_spec.rb +10 -0
- data/spec/decorators/base_spec.rb +14 -0
- data/spec/decorators/default_spec.rb +12 -0
- data/spec/decorators/html_spec.rb +50 -0
- data/spec/fixtures/application.json +112 -0
- data/spec/fixtures/languages/en-US.json +1424 -0
- data/spec/fixtures/languages/es.json +291 -0
- data/spec/fixtures/languages/ru.json +550 -0
- data/spec/fixtures/translations/ru/basic.json +56 -0
- data/spec/fixtures/translations/ru/counters.json +43 -0
- data/spec/fixtures/translations/ru/genders.json +171 -0
- data/spec/fixtures/translations/ru/last_names.txt +200 -0
- data/spec/fixtures/translations/ru/names.json +1 -0
- data/spec/fixtures/translations/ru/names.txt +458 -0
- data/spec/helper.rb +84 -0
- data/spec/language_case_rule_spec.rb +57 -0
- data/spec/language_case_spec.rb +58 -0
- data/spec/language_context_rule_spec.rb +73 -0
- data/spec/language_context_spec.rb +331 -0
- data/spec/language_spec.rb +16 -0
- data/spec/rules_engine/evaluator_spec.rb +148 -0
- data/spec/rules_engine/parser_spec.rb +29 -0
- data/spec/tokens/data_spec.rb +160 -0
- data/spec/tokens/data_tokenizer_spec.rb +29 -0
- data/spec/tokens/decoration_tokenizer_spec.rb +81 -0
- data/spec/tokens/hidden_spec.rb +24 -0
- data/spec/tokens/method_spec.rb +84 -0
- data/spec/tokens/transform_spec.rb +50 -0
- data/spec/translation_key_spec.rb +96 -0
- data/spec/translation_spec.rb +24 -0
- data/spec/utils_spec.rb +64 -0
- metadata +176 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2013 Michael Berkovich, tr8nhub.com
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
class String
|
25
|
+
|
26
|
+
def translate(desc = "", tokens = {}, options = {}, language = Tr8n.config.current_language)
|
27
|
+
language.translate(self, desc, tokens, options)
|
28
|
+
end
|
29
|
+
|
30
|
+
def trl(desc = "", tokens = {}, options = {}, language = Tr8n.config.current_language)
|
31
|
+
translate(desc, tokens, options.merge(:skip_decorations => true), language)
|
32
|
+
end
|
33
|
+
|
34
|
+
def tr8n_translated
|
35
|
+
return self if frozen?
|
36
|
+
@tr8n_translated = true
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
def tr8n_translated?
|
41
|
+
@tr8n_translated
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2013 Michael Berkovich, tr8nhub.com
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
class Time
|
25
|
+
|
26
|
+
def translate(format = :default, language = Tr8n.config.current_language, options = {})
|
27
|
+
label = (format.is_a?(String) ? format.clone : Tr8n.config.default_date_formats[format].clone)
|
28
|
+
symbols = label.scan(/(%\w)/).flatten.uniq
|
29
|
+
|
30
|
+
selected_tokens = []
|
31
|
+
symbols.each do |symbol|
|
32
|
+
token = Tr8n.config.strftime_symbol_to_token(symbol)
|
33
|
+
next unless token
|
34
|
+
selected_tokens << token
|
35
|
+
label.gsub!(symbol, token)
|
36
|
+
end
|
37
|
+
|
38
|
+
tokens = {}
|
39
|
+
selected_tokens.each do |token|
|
40
|
+
case token
|
41
|
+
when "{days}" then tokens[:days] = options[:with_leading_zero] ? day.with_leading_zero : day.to_s
|
42
|
+
when "{year_days}" then tokens[:year_days] = options[:with_leading_zero] ? yday.with_leading_zero : yday.to_s
|
43
|
+
when "{months}" then tokens[:months] = options[:with_leading_zero] ? month.with_leading_zero : month.to_s
|
44
|
+
when "{week_num}" then tokens[:week_num] = wday
|
45
|
+
when "{week_days}" then tokens[:week_days] = strftime("%w")
|
46
|
+
when "{short_years}" then tokens[:short_years] = strftime("%y")
|
47
|
+
when "{years}" then tokens[:years] = year
|
48
|
+
when "{short_week_day_name}" then tokens[:short_week_day_name] = language.tr(Tr8n.config.default_abbr_day_names[wday], "Short name for a day of a week", {}, options)
|
49
|
+
when "{week_day_name}" then tokens[:week_day_name] = language.tr(Tr8n.config.default_day_names[wday], "Day of a week", {}, options)
|
50
|
+
when "{short_month_name}" then tokens[:short_month_name] = language.tr(Tr8n.config.default_abbr_month_names[month - 1], "Short month name", {}, options)
|
51
|
+
when "{month_name}" then tokens[:month_name] = language.tr(Tr8n.config.default_month_names[month - 1], "Month name", {}, options)
|
52
|
+
when "{am_pm}" then tokens[:am_pm] = language.tr(strftime("%p"), "Meridian indicator", {}, options)
|
53
|
+
when "{full_hours}" then tokens[:full_hours] = hour
|
54
|
+
when "{short_hours}" then tokens[:short_hours] = strftime("%I")
|
55
|
+
when "{trimed_hour}" then tokens[:trimed_hour] = strftime("%l")
|
56
|
+
when "{minutes}" then tokens[:minutes] = strftime("%M")
|
57
|
+
when "{seconds}" then tokens[:seconds] = strftime("%S")
|
58
|
+
when "{since_epoch}" then tokens[:since_epoch] = strftime("%s")
|
59
|
+
when "{day_of_month}" then tokens[:day_of_month] = strftime("%e")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
language.tr(label, nil, tokens, options)
|
64
|
+
end
|
65
|
+
alias :tr :translate
|
66
|
+
|
67
|
+
def trl(format = :default, language = Tr8n.config.current_language, options = {})
|
68
|
+
tr(format, language, options.merge!(:skip_decorations => true))
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2013 Michael Berkovich, tr8nhub.com
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
class Tr8nCore::Generators::Cache::Base
|
25
|
+
|
26
|
+
def log(msg)
|
27
|
+
puts("#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}: #{msg}\n")
|
28
|
+
end
|
29
|
+
|
30
|
+
def cache_path
|
31
|
+
raise Tr8n::Exception.new("Must be implemented by the subclass")
|
32
|
+
end
|
33
|
+
|
34
|
+
def cache(key, data)
|
35
|
+
raise Tr8n::Exception.new("Must be implemented by the subclass")
|
36
|
+
end
|
37
|
+
|
38
|
+
def execute
|
39
|
+
raise Tr8n::Exception.new("Must be implemented by the subclass")
|
40
|
+
end
|
41
|
+
|
42
|
+
def run
|
43
|
+
prepare
|
44
|
+
execute
|
45
|
+
finalize
|
46
|
+
end
|
47
|
+
|
48
|
+
def prepare
|
49
|
+
@started_at = Time.now
|
50
|
+
end
|
51
|
+
|
52
|
+
def finalize
|
53
|
+
@finished_at = Time.now
|
54
|
+
log("Cache has been stored in #{cache_path}")
|
55
|
+
log("Cache generation took #{@finished_at - @started_at} mls.")
|
56
|
+
log("Done.")
|
57
|
+
end
|
58
|
+
|
59
|
+
def cache_application
|
60
|
+
log("Downloading application...")
|
61
|
+
app = Tr8n.config.application.get("application", :definition => true)
|
62
|
+
cache(Tr8n::Application.cache_key(app["key"]), app)
|
63
|
+
log("Application has been cached.")
|
64
|
+
app
|
65
|
+
end
|
66
|
+
|
67
|
+
def cache_languages
|
68
|
+
log("Downloading languages...")
|
69
|
+
languages = Tr8n.config.application.get("application/languages", :definition => true)
|
70
|
+
languages.each do |lang|
|
71
|
+
cache(Tr8n::Language.cache_key(lang["locale"]), lang)
|
72
|
+
end
|
73
|
+
log("#{languages.count} languages have been cached.")
|
74
|
+
languages
|
75
|
+
end
|
76
|
+
|
77
|
+
def symlink_path
|
78
|
+
raise Tr8n::Exception.new("Must be implemented by the subclass")
|
79
|
+
end
|
80
|
+
|
81
|
+
def generate_symlink
|
82
|
+
FileUtils.rm(symlink_path) if File.exist?(symlink_path)
|
83
|
+
FileUtils.ln_s(cache_path, symlink_path)
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2013 Michael Berkovich, tr8nhub.com
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
class Tr8nCore::Generators::Cache::Cdb < Tr8nCore::Generators::Cache::Base
|
25
|
+
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2013 Michael Berkovich, tr8nhub.com
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
class Tr8nCore::Generators::Cache::File < Tr8nCore::Generators::Cache::Base
|
25
|
+
|
26
|
+
def cache_path
|
27
|
+
@cache_path ||= begin
|
28
|
+
path = "#{Tr8n.config.cache_path}/files/tr8n_#{Tr8n.config.application.key}_#{@started_at.strftime('%Y_%m_%d_%H_%M_%S')}"
|
29
|
+
pp "Cache will be stored in #{path}"
|
30
|
+
FileUtils.mkdir_p(path)
|
31
|
+
FileUtils.chmod(0777, path)
|
32
|
+
path
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def cache(key, data)
|
37
|
+
file_path = "#{cache_path}/#{Tr8n::CacheAdapters::File.file_name(key)}"
|
38
|
+
File.open(file_path, 'w') { |file| file.write(JSON.pretty_generate(data)) }
|
39
|
+
end
|
40
|
+
|
41
|
+
def symlink_path
|
42
|
+
Tr8n::CacheAdapters::File.cache_path
|
43
|
+
end
|
44
|
+
|
45
|
+
def execute
|
46
|
+
cache_application
|
47
|
+
@languages = cache_languages
|
48
|
+
cache_translations
|
49
|
+
generate_symlink
|
50
|
+
end
|
51
|
+
|
52
|
+
def cache_translations
|
53
|
+
log("Downloading translations...")
|
54
|
+
sources = Tr8n.config.application.get("application/sources")
|
55
|
+
@languages.each do |language|
|
56
|
+
log("--------------------------------------------------------------")
|
57
|
+
log("Downloading #{language["locale"]} language...")
|
58
|
+
log("--------------------------------------------------------------")
|
59
|
+
|
60
|
+
sources.each do |source|
|
61
|
+
log("Downloading #{source["source"]} in #{language["locale"]}...")
|
62
|
+
translation_keys = Tr8n.config.application.get("source/translations", {:source => source["source"], :locale => language["locale"]})
|
63
|
+
data = {:source => source["source"], :translation_keys => translation_keys}
|
64
|
+
cache(Tr8n::Source.cache_key(source["source"], language["locale"]), data)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2013 Michael Berkovich, tr8nhub.com
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
module Tr8nCore
|
25
|
+
module Modules
|
26
|
+
module Logger
|
27
|
+
|
28
|
+
def debug(msg)
|
29
|
+
Tr8n::Logger.debug(msg)
|
30
|
+
end
|
31
|
+
|
32
|
+
def info(msg)
|
33
|
+
Tr8n::Logger.info(msg)
|
34
|
+
end
|
35
|
+
|
36
|
+
def error(msg)
|
37
|
+
Tr8n::Logger.error(msg)
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2013 Michael Berkovich, tr8nhub.com
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
|
25
|
+
module Tr8nCore
|
26
|
+
VERSION = "4.0.1"
|
27
|
+
end
|
data/lib/tr8n_core.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2010-2013 Michael Berkovich, tr8nhub.com
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
module Tr8nCore
|
25
|
+
module Generators
|
26
|
+
module Cache
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
module Tr8n
|
32
|
+
module Tokens
|
33
|
+
end
|
34
|
+
|
35
|
+
module Rules
|
36
|
+
end
|
37
|
+
|
38
|
+
module Decorators
|
39
|
+
end
|
40
|
+
|
41
|
+
module CacheAdapters
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
[
|
46
|
+
"tr8n/base.rb",
|
47
|
+
"tr8n",
|
48
|
+
"tr8n/rules_engine",
|
49
|
+
"tr8n/tokens",
|
50
|
+
"tr8n/decorators",
|
51
|
+
"tr8n/cache_adapters",
|
52
|
+
"tr8n/cache",
|
53
|
+
"tr8n/cache/generators",
|
54
|
+
"tr8n_core/ext",
|
55
|
+
"tr8n_core/modules",
|
56
|
+
"tr8n_core/generators/cache",
|
57
|
+
].each do |f|
|
58
|
+
if f.index('.rb')
|
59
|
+
file = File.expand_path(File.join(File.dirname(__FILE__), f))
|
60
|
+
require(file)
|
61
|
+
next
|
62
|
+
end
|
63
|
+
|
64
|
+
Dir[File.expand_path("#{File.dirname(__FILE__)}/#{f}/*.rb")].sort.each do |file|
|
65
|
+
require(file)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
@@ -0,0 +1,228 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require 'helper'
|
4
|
+
|
5
|
+
describe Tr8n::Application do
|
6
|
+
describe "#configuration" do
|
7
|
+
it "sets class attributes" do
|
8
|
+
expect(Tr8n::Application.attributes).to eq([:host, :key, :secret, :access_token, :name, :description, :threshold, :default_locale, :default_level, :features, :languages, :sources, :components, :tokens])
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "#initialize" do
|
13
|
+
before do
|
14
|
+
@app = init_application
|
15
|
+
end
|
16
|
+
|
17
|
+
it "loads application attributes" do
|
18
|
+
expect(@app.key).to eq("default")
|
19
|
+
expect(@app.name).to eq("Tr8n Translation Service")
|
20
|
+
|
21
|
+
expect(@app.default_data_token('nbsp')).to eq(" ")
|
22
|
+
expect(@app.default_decoration_token('strong')).to eq("<strong>{$0}</strong>")
|
23
|
+
|
24
|
+
expect(@app.feature_enabled?(:language_cases)).to be_true
|
25
|
+
expect(@app.feature_enabled?(:language_flags)).to be_true
|
26
|
+
end
|
27
|
+
|
28
|
+
it "loads application language" do
|
29
|
+
expect(@app.languages.size).to eq(14)
|
30
|
+
|
31
|
+
russian = @app.language('ru')
|
32
|
+
expect(russian.locale).to eq('ru')
|
33
|
+
expect(russian.contexts.keys.size).to eq(6)
|
34
|
+
expect(russian.contexts.keys).to eq(["date", "gender", "genders", "list", "number", "value"])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#translation" do
|
39
|
+
before do
|
40
|
+
@app = init_application
|
41
|
+
@english = @app.language('en-US')
|
42
|
+
@russian = @app.language('ru')
|
43
|
+
end
|
44
|
+
|
45
|
+
it "translates with fallback to English" do
|
46
|
+
Tr8n.config.with_block_options(:dry => true) do
|
47
|
+
#expect(@russian.translate("{count||message}", {:count => 1})).to eq("1 message")
|
48
|
+
#expect(@russian.translate("{count||message}", {:count => 5})).to eq("5 messages")
|
49
|
+
#expect(@russian.translate("{count||message}", {:count => 0})).to eq("0 messages")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# it "translates basic phrases to Russian" do
|
54
|
+
# load_translation_keys_from_file(@app, 'translations/ru/basic.json')
|
55
|
+
# Tr8n.config.with_block_options(:dry => true) do
|
56
|
+
# expect(@russian.translate("Hello World")).to eq("Привет Мир")
|
57
|
+
# expect(@russian.translate("Hello World", "Wrong context")).to eq("Hello World")
|
58
|
+
# expect(@russian.translate("Hello World", "Greeting context")).to eq("Привет Мир")
|
59
|
+
# expect(@russian.translate("Hello world")).to eq("Hello world")
|
60
|
+
# expect(@russian.translate("Hello {user}", nil, :user => "Михаил")).to eq("Привет Михаил")
|
61
|
+
# end
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# it "translates basic phrases with data tokens to Russian" do
|
65
|
+
# load_translation_keys_from_file(@app, 'translations/ru/basic.json')
|
66
|
+
# Tr8n.config.with_block_options(:dry => true) do
|
67
|
+
# expect(@russian.translate("Hello {user}", nil, :user => "Михаил")).to eq("Привет Михаил")
|
68
|
+
# end
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# it "uses default data tokens" do
|
72
|
+
# Tr8n.config.with_block_options(:dry => true) do
|
73
|
+
# expect(@english.translate("He said: {quot}Hello{quot}", nil)).to eq("He said: "Hello"")
|
74
|
+
# expect(@english.translate("Code sample: {lbrace}a:'b'{rbrace}", nil)).to eq("Code sample: {a:'b'}")
|
75
|
+
# end
|
76
|
+
# end
|
77
|
+
#
|
78
|
+
# it "uses basic decoration tokens" do
|
79
|
+
# Tr8n.config.with_block_options(:dry => true) do
|
80
|
+
# expect(@english.translate("Hello [decor: World]", nil, :decor => lambda{|text| "''#{text}''"})).to eq("Hello ''World''")
|
81
|
+
# end
|
82
|
+
# end
|
83
|
+
#
|
84
|
+
# it "uses default decoration tokens" do
|
85
|
+
# load_translation_keys_from_file(@app, 'translations/ru/basic.json')
|
86
|
+
# Tr8n.config.with_block_options(:dry => true) do
|
87
|
+
# expect(@english.translate("Hello [i: World]")).to eq("Hello <i>World</i>")
|
88
|
+
# expect(@russian.translate("Hello [i: World]")).to eq("Привет <i>Мир</i>")
|
89
|
+
# end
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
# it "uses mixed tokens" do
|
93
|
+
# load_translation_keys_from_file(@app, 'translations/ru/basic.json')
|
94
|
+
# Tr8n.config.with_block_options(:dry => true) do
|
95
|
+
# expect(@english.translate("Hello [i: {user}]", nil, :user => "Michael")).to eq("Hello <i>Michael</i>")
|
96
|
+
# expect(@russian.translate("Hello [i: {user}]", nil, :user => "Michael")).to eq("Привет <i>Michael</i>")
|
97
|
+
# end
|
98
|
+
# end
|
99
|
+
#
|
100
|
+
# it "uses method tokens" do
|
101
|
+
# load_translation_keys_from_file(@app, 'translations/ru/basic.json')
|
102
|
+
# Tr8n.config.with_block_options(:dry => true) do
|
103
|
+
# expect(@russian.translate("Hello {user.first_name} [i: {user.last_name}]", nil,
|
104
|
+
# :user => stub_object({:first_name => "Tom", :last_name => "Anderson"}))).to eq("Привет Tom <i>Anderson</i>")
|
105
|
+
# end
|
106
|
+
# end
|
107
|
+
#
|
108
|
+
# it "translates phrases with numeric rules to Russian" do
|
109
|
+
# load_translation_keys_from_file(@app, 'translations/ru/counters.json')
|
110
|
+
# trn = @russian.translate("{count||message}", nil, {:count => 1})
|
111
|
+
# expect(trn).to eq("1 сообщение")
|
112
|
+
# trn = @russian.translate("{count||message}", nil, {:count => 2})
|
113
|
+
# expect(trn).to eq("2 сообщения")
|
114
|
+
# trn = @russian.translate("{count||message}", nil, {:count => 5})
|
115
|
+
# expect(trn).to eq("5 сообщений")
|
116
|
+
# trn = @russian.translate("{count||message}", nil, {:count => 15})
|
117
|
+
# expect(trn).to eq("15 сообщений")
|
118
|
+
# end
|
119
|
+
#
|
120
|
+
# it "translates phrases with gender rules to Russian" do
|
121
|
+
# #load_translation_key_from_hash(@app, {
|
122
|
+
# # "label" => "{actor} sent {target} a gift.",
|
123
|
+
# # "translations" => {
|
124
|
+
# # "ru" => [
|
125
|
+
# # {
|
126
|
+
# # "label"=> "{actor} послал подарок {target::dat}.",
|
127
|
+
# # "locale"=> "ru",
|
128
|
+
# # "context"=> {
|
129
|
+
# # "actor"=> [{ "type"=> "gender", "key"=> "male"}]
|
130
|
+
# # }
|
131
|
+
# # },
|
132
|
+
# # {
|
133
|
+
# # "label"=> "{actor} послала подарок {target::dat}.",
|
134
|
+
# # "locale"=> "ru",
|
135
|
+
# # "context"=> {
|
136
|
+
# # "actor"=> [{ "type"=> "gender", "key"=> "female"}]
|
137
|
+
# # },
|
138
|
+
# # },
|
139
|
+
# # {
|
140
|
+
# # "label"=> "{actor} послал/а подарок {target::dat}.",
|
141
|
+
# # "locale"=> "ru",
|
142
|
+
# # "context"=> {
|
143
|
+
# # "actor"=> [{ "type"=> "gender", "key"=> "unknown"}]
|
144
|
+
# # },
|
145
|
+
# # }
|
146
|
+
# # ]
|
147
|
+
# # }
|
148
|
+
# #});
|
149
|
+
#
|
150
|
+
# load_translation_keys_from_file(@app, "translations/ru/genders.json")
|
151
|
+
#
|
152
|
+
# actor = {'gender' => 'female', 'name' => 'Таня'}
|
153
|
+
# target = {'gender' => 'male', 'name' => 'Михаил'}
|
154
|
+
#
|
155
|
+
# Tr8n.config.with_block_options(:dry => true) do
|
156
|
+
# expect(@russian.translate(
|
157
|
+
# '{actor} sent {target} a gift.', nil,
|
158
|
+
# :actor => {:object => actor, :attribute => 'name'},
|
159
|
+
# :target => {:object => target, :attribute => 'name'})
|
160
|
+
# ).to eq("Таня послала подарок Михаилу.")
|
161
|
+
#
|
162
|
+
# expect(@russian.translate(
|
163
|
+
# '{actor} sent {target} a gift.', nil,
|
164
|
+
# :actor => {:object => target, :attribute => 'name'},
|
165
|
+
# :target => {:object => actor, :attribute => 'name'})
|
166
|
+
# ).to eq("Михаил послал подарок Тане.")
|
167
|
+
#
|
168
|
+
# expect(@russian.translate(
|
169
|
+
# '{actor} loves {target}.', nil,
|
170
|
+
# :actor => {:object => actor, :attribute => 'name'},
|
171
|
+
# :target => {:object => target, :attribute => 'name'})
|
172
|
+
# ).to eq("Таня любит Михаила.")
|
173
|
+
#
|
174
|
+
# expect(@russian.translate(
|
175
|
+
# '{actor} saw {target} {count||day} ago.', nil,
|
176
|
+
# :actor => {:object => actor, :attribute => 'name'},
|
177
|
+
# :target => {:object => target, :attribute => 'name'},
|
178
|
+
# :count => 2)
|
179
|
+
# ).to eq("Таня видела Михаила 2 дня назад.")
|
180
|
+
#
|
181
|
+
# expect(@russian.translate(
|
182
|
+
# '{actor} saw {target} {count||day} ago.', nil,
|
183
|
+
# :actor => {:object => target, :attribute => 'name'},
|
184
|
+
# :target => {:object => actor, :attribute => 'name'},
|
185
|
+
# :count => 2)
|
186
|
+
# ).to eq("Михаил видел Таню 2 дня назад.")
|
187
|
+
#
|
188
|
+
# end
|
189
|
+
#
|
190
|
+
# # trn = @russian.translate("{count||message}", nil, {:count => 1})
|
191
|
+
# # expect(trn).to eq("1 сообщение")
|
192
|
+
# end
|
193
|
+
#
|
194
|
+
end
|
195
|
+
|
196
|
+
#describe "#integration" do
|
197
|
+
# # before do
|
198
|
+
# # # @app = Tr8n::Application.init("http://geni.berkovich.net", "29adc3257b6960703", "abcdefg")
|
199
|
+
# # end
|
200
|
+
#
|
201
|
+
# # it "returns cached language by locale" do
|
202
|
+
# # # russian = @app.language("ru")
|
203
|
+
# # # pp russian.translate("{count||message,messages}", nil, :count => 3)
|
204
|
+
# # end
|
205
|
+
#
|
206
|
+
# # it "returns new language by locale" do
|
207
|
+
# # # french = @app.language("fr")
|
208
|
+
# # # pp french
|
209
|
+
# # end
|
210
|
+
#
|
211
|
+
# # it "returns translators" do
|
212
|
+
# # # translators = @app.translators
|
213
|
+
# # # pp french
|
214
|
+
# # end
|
215
|
+
#
|
216
|
+
# # it "returns featured languages" do
|
217
|
+
# # # featured_languages = @app.featured_languages
|
218
|
+
# # # pp french
|
219
|
+
# # end
|
220
|
+
#
|
221
|
+
# # it "returns source by key" do
|
222
|
+
# # # source = @app.source_by_key("/")
|
223
|
+
# # # pp source.to_api_hash
|
224
|
+
# # end
|
225
|
+
#
|
226
|
+
#end
|
227
|
+
|
228
|
+
end
|