tml 4.3.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +22 -0
  3. data/README.md +243 -0
  4. data/Rakefile +9 -0
  5. data/lib/tml.rb +56 -0
  6. data/lib/tml/api/client.rb +206 -0
  7. data/lib/tml/api/post_office.rb +71 -0
  8. data/lib/tml/application.rb +254 -0
  9. data/lib/tml/base.rb +116 -0
  10. data/lib/tml/cache.rb +143 -0
  11. data/lib/tml/cache_adapters/file.rb +89 -0
  12. data/lib/tml/cache_adapters/memcache.rb +104 -0
  13. data/lib/tml/cache_adapters/memory.rb +85 -0
  14. data/lib/tml/cache_adapters/redis.rb +108 -0
  15. data/lib/tml/config.rb +410 -0
  16. data/lib/tml/decorators/base.rb +52 -0
  17. data/lib/tml/decorators/default.rb +43 -0
  18. data/lib/tml/decorators/html.rb +102 -0
  19. data/lib/tml/exception.rb +35 -0
  20. data/lib/tml/ext/array.rb +86 -0
  21. data/lib/tml/ext/date.rb +99 -0
  22. data/lib/tml/ext/fixnum.rb +47 -0
  23. data/lib/tml/ext/hash.rb +99 -0
  24. data/lib/tml/ext/string.rb +56 -0
  25. data/lib/tml/ext/time.rb +89 -0
  26. data/lib/tml/generators/cache/base.rb +117 -0
  27. data/lib/tml/generators/cache/file.rb +159 -0
  28. data/lib/tml/language.rb +175 -0
  29. data/lib/tml/language_case.rb +105 -0
  30. data/lib/tml/language_case_rule.rb +76 -0
  31. data/lib/tml/language_context.rb +117 -0
  32. data/lib/tml/language_context_rule.rb +56 -0
  33. data/lib/tml/languages/en.json +1363 -0
  34. data/lib/tml/logger.rb +109 -0
  35. data/lib/tml/rules_engine/evaluator.rb +162 -0
  36. data/lib/tml/rules_engine/parser.rb +65 -0
  37. data/lib/tml/session.rb +199 -0
  38. data/lib/tml/source.rb +106 -0
  39. data/lib/tml/tokenizers/data.rb +96 -0
  40. data/lib/tml/tokenizers/decoration.rb +204 -0
  41. data/lib/tml/tokenizers/dom.rb +346 -0
  42. data/lib/tml/tokens/data.rb +403 -0
  43. data/lib/tml/tokens/method.rb +61 -0
  44. data/lib/tml/tokens/transform.rb +223 -0
  45. data/lib/tml/translation.rb +67 -0
  46. data/lib/tml/translation_key.rb +178 -0
  47. data/lib/tml/translator.rb +47 -0
  48. data/lib/tml/utils.rb +130 -0
  49. data/lib/tml/version.rb +34 -0
  50. metadata +121 -0
data/lib/tml/logger.rb ADDED
@@ -0,0 +1,109 @@
1
+ # encoding: UTF-8
2
+ #--
3
+ # Copyright (c) 2015 Translation Exchange, Inc
4
+ #
5
+ # _______ _ _ _ ______ _
6
+ # |__ __| | | | | (_) | ____| | |
7
+ # | |_ __ __ _ _ __ ___| | __ _| |_ _ ___ _ __ | |__ __ _____| |__ __ _ _ __ __ _ ___
8
+ # | | '__/ _` | '_ \/ __| |/ _` | __| |/ _ \| '_ \| __| \ \/ / __| '_ \ / _` | '_ \ / _` |/ _ \
9
+ # | | | | (_| | | | \__ \ | (_| | |_| | (_) | | | | |____ > < (__| | | | (_| | | | | (_| | __/
10
+ # |_|_| \__,_|_| |_|___/_|\__,_|\__|_|\___/|_| |_|______/_/\_\___|_| |_|\__,_|_| |_|\__, |\___|
11
+ # __/ |
12
+ # |___/
13
+ # Permission is hereby granted, free of charge, to any person obtaining
14
+ # a copy of this software and associated documentation files (the
15
+ # "Software"), to deal in the Software without restriction, including
16
+ # without limitation the rights to use, copy, modify, merge, publish,
17
+ # distribute, sublicense, and/or sell copies of the Software, and to
18
+ # permit persons to whom the Software is furnished to do so, subject to
19
+ # the following conditions:
20
+ #
21
+ # The above copyright notice and this permission notice shall be
22
+ # included in all copies or substantial portions of the Software.
23
+ #
24
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
+ #++
32
+
33
+ require 'logger'
34
+
35
+ module Tml
36
+
37
+ def self.logger
38
+ @logger ||= begin
39
+ logfile_path = File.expand_path(Tml.config.logger[:path])
40
+ logfile_dir = logfile_path.split("/")[0..-2].join("/")
41
+ FileUtils.mkdir_p(logfile_dir) unless File.exist?(logfile_dir)
42
+ logfile = File.open(logfile_path, 'a')
43
+ logfile.sync = true
44
+ Tml::Logger.new(logfile)
45
+ end
46
+ end
47
+
48
+ class Logger < ::Logger
49
+
50
+ def format_message(severity, timestamp, progname, msg)
51
+ return "" unless Tml.config.logger[:enabled]
52
+ # TODO: check for severity/level
53
+ "[#{timestamp.strftime("%D %T")}]: #{" " * stack.size}#{msg}\n"
54
+ end
55
+
56
+ def add(severity, message = nil, progname = nil, &block)
57
+ return unless Tml.config.logger[:enabled]
58
+ super
59
+ end
60
+
61
+ def stack
62
+ @stack ||= []
63
+ end
64
+
65
+ def trace_api_call(path, params, opts = {})
66
+ #[:client_secret, :access_token].each do |param|
67
+ # params = params.merge(param => "##filtered##") if params[param]
68
+ #end
69
+ if opts[:method] == :post
70
+ debug("post: [#{path}] #{params.inspect}")
71
+ else
72
+ debug("get: #{path}?#{to_query(params)}")
73
+ end
74
+ stack.push(caller)
75
+ t0 = Time.now
76
+ if block_given?
77
+ ret = yield
78
+ end
79
+ t1 = Time.now
80
+ stack.pop
81
+ debug("call took #{t1 - t0} seconds")
82
+ ret
83
+ end
84
+
85
+ def to_query(hash)
86
+ query = []
87
+ hash.each do |key, value|
88
+ query << "#{key}=#{value}"
89
+ end
90
+ query.join('&')
91
+ end
92
+
93
+ def trace(message)
94
+ debug(message)
95
+ stack.push(caller)
96
+ t0 = Time.now
97
+ if block_given?
98
+ ret = yield
99
+ end
100
+ t1 = Time.now
101
+ stack.pop
102
+ debug("execution took #{t1 - t0} seconds")
103
+ ret
104
+ end
105
+
106
+ end
107
+
108
+ end
109
+
@@ -0,0 +1,162 @@
1
+ # encoding: UTF-8
2
+ #--
3
+ # Copyright (c) 2015 Translation Exchange, Inc
4
+ #
5
+ # _______ _ _ _ ______ _
6
+ # |__ __| | | | | (_) | ____| | |
7
+ # | |_ __ __ _ _ __ ___| | __ _| |_ _ ___ _ __ | |__ __ _____| |__ __ _ _ __ __ _ ___
8
+ # | | '__/ _` | '_ \/ __| |/ _` | __| |/ _ \| '_ \| __| \ \/ / __| '_ \ / _` | '_ \ / _` |/ _ \
9
+ # | | | | (_| | | | \__ \ | (_| | |_| | (_) | | | | |____ > < (__| | | | (_| | | | | (_| | __/
10
+ # |_|_| \__,_|_| |_|___/_|\__,_|\__|_|\___/|_| |_|______/_/\_\___|_| |_|\__,_|_| |_|\__, |\___|
11
+ # __/ |
12
+ # |___/
13
+ # Permission is hereby granted, free of charge, to any person obtaining
14
+ # a copy of this software and associated documentation files (the
15
+ # "Software"), to deal in the Software without restriction, including
16
+ # without limitation the rights to use, copy, modify, merge, publish,
17
+ # distribute, sublicense, and/or sell copies of the Software, and to
18
+ # permit persons to whom the Software is furnished to do so, subject to
19
+ # the following conditions:
20
+ #
21
+ # The above copyright notice and this permission notice shall be
22
+ # included in all copies or substantial portions of the Software.
23
+ #
24
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
+ #++
32
+
33
+ module Tml
34
+ module RulesEngine
35
+
36
+ class Evaluator
37
+ attr_reader :env, :vars
38
+
39
+ def initialize
40
+ @vars = {}
41
+ @env = {
42
+ # McCarthy's Elementary S-functions and Predicates
43
+ 'label' => lambda { |l, r| @vars[l] = r },
44
+ 'quote' => lambda { |expr| expr },
45
+ 'car' => lambda { |list| list[1] },
46
+ 'cdr' => lambda { |list| list.drop(1) },
47
+ 'cons' => lambda { |e, cell| [e] + cell },
48
+ 'eq' => lambda { |l, r| l == r },
49
+ 'atom' => lambda { |expr| [Symbol, String, Fixnum, Float].include?(expr.class) },
50
+ 'cond' => lambda { |c, t, f| evaluate(c) ? evaluate(t) : evaluate(f) },
51
+
52
+ # Tml Extensions
53
+ '=' => lambda { |l, r| l == r }, # ['=', 1, 2]
54
+ '!=' => lambda { |l, r| l != r }, # ['!=', 1, 2]
55
+ '<' => lambda { |l, r| l < r }, # ['<', 1, 2]
56
+ '>' => lambda { |l, r| l > r }, # ['>', 1, 2]
57
+ '+' => lambda { |l, r| l + r }, # ['+', 1, 2]
58
+ '-' => lambda { |l, r| l - r }, # ['-', 1, 2]
59
+ '*' => lambda { |l, r| l * r }, # ['*', 1, 2]
60
+ '%' => lambda { |l, r| l % r }, # ['%', 14, 10]
61
+ 'mod' => lambda { |l, r| l % r }, # ['mod', '@n', 10]
62
+ '/' => lambda { |l, r| (l * 1.0) / r }, # ['/', 1, 2]
63
+ '!' => lambda { |expr| not expr }, # ['!', ['true']]
64
+ 'not' => lambda { |val| not val }, # ['not', ['true']]
65
+ '&&' => lambda { |*expr| expr.all?{|e| evaluate(e)} }, # ['&&', [], [], ...]
66
+ 'and' => lambda { |*expr| expr.all?{|e| evaluate(e)} }, # ['and', [], [], ...]
67
+ '||' => lambda { |*expr| expr.any?{|e| evaluate(e)} }, # ['||', [], [], ...]
68
+ 'or' => lambda { |*expr| expr.any?{|e| evaluate(e)} }, # ['or', [], [], ...]
69
+ 'if' => lambda { |c, t, f| evaluate(c) ? evaluate(t) : evaluate(f) }, # ['if', 'cond', 'true', 'false']
70
+ 'let' => lambda { |l, r| @vars[l] = r }, # ['let', 'n', 5]
71
+ 'true' => lambda { true }, # ['true']
72
+ 'false' => lambda { false }, # ['false']
73
+
74
+ 'date' => lambda { |date| Date.strptime(date, '%Y-%m-%d') }, # ['date', '2010-01-01']
75
+ 'today' => lambda { Time.now.to_date }, # ['today']
76
+ 'time' => lambda { |expr| Time.strptime(expr, '%Y-%m-%d %H:%M:%S') }, # ['time', '2010-01-01 10:10:05']
77
+ 'now' => lambda { Time.now }, # ['now']
78
+
79
+ 'append' => lambda { |l, r| r.to_s + l.to_s }, # ['append', 'world', 'hello ']
80
+ 'prepend' => lambda { |l, r| l.to_s + r.to_s }, # ['prepend', 'hello ', 'world']
81
+ 'match' => lambda { |search, subject| # ['match', /a/, 'abc']
82
+ search = regexp_from_string(search)
83
+ not search.match(subject).nil?
84
+ },
85
+ 'in' => lambda { |values, search| # ['in', '1,2,3,5..10,20..24', '@n']
86
+ search = search.to_s.strip
87
+ values.split(',').each do |e|
88
+ if e.index('..')
89
+ bounds = e.strip.split('..')
90
+ return true if (bounds.first.strip..bounds.last.strip).include?(search)
91
+ end
92
+ return true if e.strip == search
93
+ end
94
+ false
95
+ },
96
+ 'within' => lambda { |values, search| # ['within', '0..3', '@n']
97
+ bounds = values.split('..').map{|d| Integer(d)}
98
+ (bounds.first..bounds.last).include?(search)
99
+ },
100
+ 'replace' => lambda { |search, replace, subject| # ['replace', '/^a/', 'v', 'abc']
101
+ # handle regular expression
102
+ if /\/i$/.match(search)
103
+ replace = replace.gsub(/\$(\d+)/, '\\\\\1') # for compatibility with Perl notation
104
+ end
105
+ search = regexp_from_string(search)
106
+ subject.gsub(search, replace)
107
+ },
108
+ 'count' => lambda { |list| # ['count', '@genders']
109
+ (list.is_a?(String) ? vars[list] : list).count
110
+ },
111
+ 'all' => lambda { |list, value| # ['all', '@genders', 'male']
112
+ list = (list.is_a?(String) ? vars[list] : list)
113
+ list.is_a?(Array) ? list.all?{|e| e == value} : false
114
+ },
115
+ 'any' => lambda { |list, value| # ['any', '@genders', 'female']
116
+ list = (list.is_a?(String) ? vars[list] : list)
117
+ list.is_a?(Array) ? list.any?{|e| e == value} : false
118
+ },
119
+ }
120
+ end
121
+
122
+ def regexp_from_string(str)
123
+ return Regexp.new(/#{str}/) unless /^\//.match(str)
124
+
125
+ str = str.gsub(/^\//, '')
126
+
127
+ if /\/i$/.match(str)
128
+ str = str.gsub(/\/i$/, '')
129
+ return Regexp.new(/#{str}/i)
130
+ end
131
+
132
+ str = str.gsub(/\/$/, '')
133
+ Regexp.new(/#{str}/)
134
+ end
135
+
136
+ def reset!
137
+ @vars = {}
138
+ end
139
+
140
+ def apply(fn, args)
141
+ raise "undefined symbols #{fn}" unless @env.keys.include?(fn)
142
+ @env[fn].call(*args)
143
+ end
144
+
145
+ def evaluate(expr)
146
+ if @env['atom'].call(expr)
147
+ return @vars[expr] if expr.is_a?(String) and @vars[expr]
148
+ return expr
149
+ end
150
+
151
+ fn = expr[0]
152
+ args = expr.drop(1)
153
+
154
+ unless %w(quote car cdr cond if && || and or true false let count all any).member?(fn)
155
+ args = args.map { |a| self.evaluate(a) }
156
+ end
157
+ apply(fn, args)
158
+ end
159
+ end
160
+
161
+ end
162
+ end
@@ -0,0 +1,65 @@
1
+ # encoding: UTF-8
2
+ #--
3
+ # Copyright (c) 2015 Translation Exchange, Inc
4
+ #
5
+ # _______ _ _ _ ______ _
6
+ # |__ __| | | | | (_) | ____| | |
7
+ # | |_ __ __ _ _ __ ___| | __ _| |_ _ ___ _ __ | |__ __ _____| |__ __ _ _ __ __ _ ___
8
+ # | | '__/ _` | '_ \/ __| |/ _` | __| |/ _ \| '_ \| __| \ \/ / __| '_ \ / _` | '_ \ / _` |/ _ \
9
+ # | | | | (_| | | | \__ \ | (_| | |_| | (_) | | | | |____ > < (__| | | | (_| | | | | (_| | __/
10
+ # |_|_| \__,_|_| |_|___/_|\__,_|\__|_|\___/|_| |_|______/_/\_\___|_| |_|\__,_|_| |_|\__, |\___|
11
+ # __/ |
12
+ # |___/
13
+ # Permission is hereby granted, free of charge, to any person obtaining
14
+ # a copy of this software and associated documentation files (the
15
+ # "Software"), to deal in the Software without restriction, including
16
+ # without limitation the rights to use, copy, modify, merge, publish,
17
+ # distribute, sublicense, and/or sell copies of the Software, and to
18
+ # permit persons to whom the Software is furnished to do so, subject to
19
+ # the following conditions:
20
+ #
21
+ # The above copyright notice and this permission notice shall be
22
+ # included in all copies or substantial portions of the Software.
23
+ #
24
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
+ #++
32
+
33
+ module Tml
34
+ module RulesEngine
35
+
36
+ class Parser
37
+ attr_reader :tokens, :expression
38
+
39
+ def initialize(expression)
40
+ @expression = expression
41
+ if expression =~ /^\(/
42
+ @tokens = expression.scan(/[()]|\w+|@\w+|[\+\-\!\|\=>&<\*\/%]+|".*?"|'.*?'/)
43
+ end
44
+ end
45
+
46
+ def parse
47
+ return @expression unless tokens
48
+ token = tokens.shift
49
+ return nil if token.nil?
50
+ return parse_list if (token) == '('
51
+ return token[1..-2].to_s if token =~ /^['"].*/
52
+ return token.to_i if token =~ /\d+/
53
+ token.to_s
54
+ end
55
+
56
+ def parse_list
57
+ list = []
58
+ list << parse until tokens.empty? or tokens.first == ')'
59
+ tokens.shift
60
+ list
61
+ end
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,199 @@
1
+ # encoding: UTF-8
2
+ #--
3
+ # Copyright (c) 2015 Translation Exchange, Inc
4
+ #
5
+ # _______ _ _ _ ______ _
6
+ # |__ __| | | | | (_) | ____| | |
7
+ # | |_ __ __ _ _ __ ___| | __ _| |_ _ ___ _ __ | |__ __ _____| |__ __ _ _ __ __ _ ___
8
+ # | | '__/ _` | '_ \/ __| |/ _` | __| |/ _ \| '_ \| __| \ \/ / __| '_ \ / _` | '_ \ / _` |/ _ \
9
+ # | | | | (_| | | | \__ \ | (_| | |_| | (_) | | | | |____ > < (__| | | | (_| | | | | (_| | __/
10
+ # |_|_| \__,_|_| |_|___/_|\__,_|\__|_|\___/|_| |_|______/_/\_\___|_| |_|\__,_|_| |_|\__, |\___|
11
+ # __/ |
12
+ # |___/
13
+ # Permission is hereby granted, free of charge, to any person obtaining
14
+ # a copy of this software and associated documentation files (the
15
+ # "Software"), to deal in the Software without restriction, including
16
+ # without limitation the rights to use, copy, modify, merge, publish,
17
+ # distribute, sublicense, and/or sell copies of the Software, and to
18
+ # permit persons to whom the Software is furnished to do so, subject to
19
+ # the following conditions:
20
+ #
21
+ # The above copyright notice and this permission notice shall be
22
+ # included in all copies or substantial portions of the Software.
23
+ #
24
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
+ #++
32
+
33
+ module Tml
34
+
35
+ def self.session
36
+ Thread.current[:session] ||= Tml::Session.new
37
+ end
38
+
39
+ class Session
40
+ # Session Attributes - Move to Session
41
+ attr_accessor :application, :current_user, :current_locale, :current_language, :current_translator,
42
+ :current_source, :current_component, :block_options, :cookie_params, :access_token, :tools_enabled
43
+
44
+ def self.access_token
45
+ @access_token
46
+ end
47
+
48
+ def self.access_token=(token)
49
+ @access_token = token
50
+ end
51
+
52
+ def init(opts = {})
53
+ return unless Tml.config.enabled? and Tml.config.application
54
+
55
+ key = opts[:key] || Tml.config.application[:key]
56
+ secret = opts[:secret] || Tml.config.application[:secret]
57
+ host = opts[:host] || Tml.config.application[:host]
58
+
59
+ Tml::Session.access_token ||= begin
60
+ self.access_token = opts[:token] || Tml.config.application[:token]
61
+ self.access_token ||= opts[:access_token] || Tml.config.application[:access_token]
62
+ end
63
+
64
+ Tml.cache.reset_version
65
+
66
+ self.application = Tml.memory.fetch(Tml::Application.cache_key) do
67
+ Tml::Application.new(:host => host, :key => key, :secret => secret, :access_token => Tml::Session.access_token).fetch
68
+ end
69
+
70
+ if Tml.cache.read_only?
71
+ self.class.access_token = self.application.access_token
72
+ end
73
+
74
+ # Tml.logger.info(self.cookie_params.inspect)
75
+
76
+ self.cookie_params = begin
77
+ cookie_name = "trex_#{self.application.key}"
78
+ if opts[:cookies] and opts[:cookies][cookie_name]
79
+ begin
80
+ HashWithIndifferentAccess.new(Tml::Utils.decode_and_verify_params(opts[:cookies][cookie_name], secret))
81
+ rescue Exception => ex
82
+ Tml.logger.error("Failed to parse tml cookie: #{ex.message}")
83
+ {}
84
+ end
85
+ else
86
+ {}
87
+ end
88
+ end
89
+
90
+ self.tools_enabled = opts[:tools_enabled]
91
+ self.current_user = opts[:user]
92
+ self.current_source = opts[:source] || '/tml/core'
93
+ self.current_component = opts[:component]
94
+ self.current_locale = opts[:locale] || self.cookie_params[:locale] || Tml.config.default_locale
95
+
96
+ if self.cookie_params['translator']
97
+ self.current_translator = Tml::Translator.new(self.cookie_params['translator'])
98
+ end
99
+
100
+ # if inline mode don't use any app cache
101
+ if inline_mode?
102
+ self.application = self.application.dup
103
+ self.application.reset_translation_cache
104
+ end
105
+
106
+ if self.current_translator
107
+ self.current_translator.application = self.application
108
+ end
109
+
110
+ self.current_language = self.application.language(self.current_locale)
111
+ end
112
+
113
+ def tools_enabled?
114
+ self.tools_enabled
115
+ end
116
+
117
+ def reset
118
+ self.application= nil
119
+ self.current_user= nil
120
+ self.current_language= nil
121
+ self.current_translator= nil
122
+ self.current_source= nil
123
+ self.current_component= nil
124
+ self.tools_enabled= nil
125
+ self.block_options= nil
126
+ end
127
+
128
+ def current_language
129
+ @current_language ||= Tml.config.default_language
130
+ end
131
+
132
+ def application
133
+ @application ||= Tml::Application.new(:host => Tml::Api::Client::API_HOST)
134
+ end
135
+
136
+ def source_language
137
+ arr = @block_options || []
138
+ arr.reverse.each do |opts|
139
+ return application.language(opts[:locale]) unless opts[:locale].blank?
140
+ end
141
+ application.language
142
+ end
143
+
144
+ def target_language
145
+ arr = @block_options || []
146
+ arr.reverse.each do |opts|
147
+ return application.language(opts[:target_locale]) unless opts[:target_locale].nil?
148
+ end
149
+ current_language
150
+ end
151
+
152
+ def inline_mode?
153
+ current_translator and current_translator.inline?
154
+ end
155
+
156
+ #########################################################
157
+ ## Block Options
158
+ #########################################################
159
+
160
+ def push_block_options(opts)
161
+ (@block_options ||= []).push(opts)
162
+ end
163
+
164
+ def pop_block_options
165
+ return unless @block_options
166
+ @block_options.pop
167
+ end
168
+
169
+ def block_options
170
+ (@block_options ||= []).last || {}
171
+ end
172
+
173
+ def with_block_options(opts)
174
+ push_block_options(opts)
175
+ if block_given?
176
+ ret = yield
177
+ end
178
+ pop_block_options
179
+ ret
180
+ end
181
+
182
+ def current_source_from_block_options
183
+ arr = @block_options || []
184
+ arr.reverse.each do |opts|
185
+ return application.source_by_key(opts[:source]) unless opts[:source].blank?
186
+ end
187
+ nil
188
+ end
189
+
190
+ def current_component_from_block_options
191
+ arr = @block_options || []
192
+ arr.reverse.each do |opts|
193
+ return application.component_by_key(opts[:component]) unless opts[:component].blank?
194
+ end
195
+ Tml.config.current_component
196
+ end
197
+
198
+ end
199
+ end