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.
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