tr8n_core 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +22 -0
  3. data/README.md +69 -0
  4. data/Rakefile +9 -0
  5. data/config/config.yml +34 -0
  6. data/config/tokens/data.yml +45 -0
  7. data/config/tokens/decorations.yml +37 -0
  8. data/lib/tr8n/application.rb +320 -0
  9. data/lib/tr8n/base.rb +123 -0
  10. data/lib/tr8n/cache.rb +144 -0
  11. data/lib/tr8n/cache_adapters/cdb.rb +74 -0
  12. data/lib/tr8n/cache_adapters/file.rb +70 -0
  13. data/lib/tr8n/cache_adapters/memcache.rb +91 -0
  14. data/lib/tr8n/cache_adapters/redis.rb +94 -0
  15. data/lib/tr8n/component.rb +68 -0
  16. data/lib/tr8n/config.rb +291 -0
  17. data/lib/tr8n/decorators/base.rb +35 -0
  18. data/lib/tr8n/decorators/default.rb +30 -0
  19. data/lib/tr8n/decorators/html.rb +63 -0
  20. data/lib/tr8n/exception.rb +26 -0
  21. data/lib/tr8n/language.rb +250 -0
  22. data/lib/tr8n/language_case.rb +116 -0
  23. data/lib/tr8n/language_case_rule.rb +85 -0
  24. data/lib/tr8n/language_context.rb +115 -0
  25. data/lib/tr8n/language_context_rule.rb +62 -0
  26. data/lib/tr8n/logger.rb +83 -0
  27. data/lib/tr8n/rules_engine/evaluator.rb +156 -0
  28. data/lib/tr8n/rules_engine/parser.rb +83 -0
  29. data/lib/tr8n/source.rb +95 -0
  30. data/lib/tr8n/tokens/data.rb +410 -0
  31. data/lib/tr8n/tokens/data_tokenizer.rb +82 -0
  32. data/lib/tr8n/tokens/decoration_tokenizer.rb +200 -0
  33. data/lib/tr8n/tokens/hidden.rb +48 -0
  34. data/lib/tr8n/tokens/method.rb +52 -0
  35. data/lib/tr8n/tokens/transform.rb +191 -0
  36. data/lib/tr8n/translation.rb +104 -0
  37. data/lib/tr8n/translation_key.rb +205 -0
  38. data/lib/tr8n/translator.rb +62 -0
  39. data/lib/tr8n/utils.rb +124 -0
  40. data/lib/tr8n_core/ext/array.rb +74 -0
  41. data/lib/tr8n_core/ext/date.rb +63 -0
  42. data/lib/tr8n_core/ext/fixnum.rb +39 -0
  43. data/lib/tr8n_core/ext/hash.rb +126 -0
  44. data/lib/tr8n_core/ext/string.rb +44 -0
  45. data/lib/tr8n_core/ext/time.rb +71 -0
  46. data/lib/tr8n_core/generators/cache/base.rb +85 -0
  47. data/lib/tr8n_core/generators/cache/cdb.rb +27 -0
  48. data/lib/tr8n_core/generators/cache/file.rb +69 -0
  49. data/lib/tr8n_core/modules/logger.rb +43 -0
  50. data/lib/tr8n_core/version.rb +27 -0
  51. data/lib/tr8n_core.rb +68 -0
  52. data/spec/application_spec.rb +228 -0
  53. data/spec/base_spec.rb +19 -0
  54. data/spec/config_spec.rb +16 -0
  55. data/spec/decorator_spec.rb +10 -0
  56. data/spec/decorators/base_spec.rb +14 -0
  57. data/spec/decorators/default_spec.rb +12 -0
  58. data/spec/decorators/html_spec.rb +50 -0
  59. data/spec/fixtures/application.json +112 -0
  60. data/spec/fixtures/languages/en-US.json +1424 -0
  61. data/spec/fixtures/languages/es.json +291 -0
  62. data/spec/fixtures/languages/ru.json +550 -0
  63. data/spec/fixtures/translations/ru/basic.json +56 -0
  64. data/spec/fixtures/translations/ru/counters.json +43 -0
  65. data/spec/fixtures/translations/ru/genders.json +171 -0
  66. data/spec/fixtures/translations/ru/last_names.txt +200 -0
  67. data/spec/fixtures/translations/ru/names.json +1 -0
  68. data/spec/fixtures/translations/ru/names.txt +458 -0
  69. data/spec/helper.rb +84 -0
  70. data/spec/language_case_rule_spec.rb +57 -0
  71. data/spec/language_case_spec.rb +58 -0
  72. data/spec/language_context_rule_spec.rb +73 -0
  73. data/spec/language_context_spec.rb +331 -0
  74. data/spec/language_spec.rb +16 -0
  75. data/spec/rules_engine/evaluator_spec.rb +148 -0
  76. data/spec/rules_engine/parser_spec.rb +29 -0
  77. data/spec/tokens/data_spec.rb +160 -0
  78. data/spec/tokens/data_tokenizer_spec.rb +29 -0
  79. data/spec/tokens/decoration_tokenizer_spec.rb +81 -0
  80. data/spec/tokens/hidden_spec.rb +24 -0
  81. data/spec/tokens/method_spec.rb +84 -0
  82. data/spec/tokens/transform_spec.rb +50 -0
  83. data/spec/translation_key_spec.rb +96 -0
  84. data/spec/translation_spec.rb +24 -0
  85. data/spec/utils_spec.rb +64 -0
  86. 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("&nbsp;")
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: &quot;Hello&quot;")
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