tr8n 3.0.2 → 3.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -27
- data/Gemfile.lock +4 -4
- data/README.rdoc +24 -8
- data/VERSION +1 -1
- data/app/controllers/tr8n/home_controller.rb +0 -12
- data/app/helpers/application_helper.rb +0 -1
- data/app/models/tr8n/language.rb +4 -0
- data/app/models/tr8n/translation.rb +1 -1
- data/app/models/tr8n/translation_key.rb +7 -7
- data/app/views/tr8n/admin/clientsdk/index.html.erb +13 -13
- data/app/views/tr8n/admin/clientsdk/lb_samples.html.erb +1 -0
- data/app/views/tr8n/common/_scripts.html.erb +0 -8
- data/app/views/tr8n/language/select.html.erb +1 -1
- data/app/views/tr8n/phrases/_new_comment.html.erb +1 -1
- data/config/tr8n/config.yml +29 -29
- data/config/tr8n/tokens/data.yml +1 -1
- data/config/tr8n/tokens/decorations.yml +4 -4
- data/lib/application_helper.rb +53 -1
- data/lib/tr8n/controller_methods.rb +45 -7
- data/lib/tr8n/tokens/decoration_token.rb +23 -17
- data/public/tr8n/javascripts/tr8n_client_sdk.js +203 -69
- metadata +18 -10
- data/app/views/tr8n/home/docs.html.erb +0 -3
- data/app/views/tr8n/home/integration.html.erb +0 -564
- data/app/views/tr8n/home/rules.html.erb +0 -668
- data/app/views/tr8n/home/tokens.html.erb +0 -324
- data/lib/tr8n/common_methods.rb +0 -61
- data/lib/tr8n/helper_methods.rb +0 -304
@@ -1,324 +0,0 @@
|
|
1
|
-
<%= tr8n_with_options_tag(:default_locale => 'en-US', :admin => true) do %>
|
2
|
-
|
3
|
-
<style>
|
4
|
-
h2 {
|
5
|
-
font-weight: bold;
|
6
|
-
}
|
7
|
-
h3 {
|
8
|
-
padding-top: 10px;
|
9
|
-
}
|
10
|
-
.snippet {
|
11
|
-
border: 1px solid #ccc;
|
12
|
-
margin-top:10px;
|
13
|
-
margin-bottom:10px;
|
14
|
-
padding:10px;
|
15
|
-
background-color: #f8f8ff;
|
16
|
-
}
|
17
|
-
.snippet2 {
|
18
|
-
border: 1px solid #ccc;
|
19
|
-
margin-top:10px;
|
20
|
-
margin-bottom:10px;
|
21
|
-
padding:10px;
|
22
|
-
background-color: #fff8f8;
|
23
|
-
}
|
24
|
-
.try_it {
|
25
|
-
font-style:italic;
|
26
|
-
}
|
27
|
-
.toc {
|
28
|
-
margin-left:20px;
|
29
|
-
margin-bottom:20px;
|
30
|
-
list-style-type:upper-roman;
|
31
|
-
}
|
32
|
-
.toc li div {
|
33
|
-
border-bottom:1px dotted #ccc;
|
34
|
-
font-size:16px;
|
35
|
-
}
|
36
|
-
.toc1 {
|
37
|
-
margin-left:20px;
|
38
|
-
list-style-type:lower-roman;
|
39
|
-
}
|
40
|
-
</style>
|
41
|
-
<div style="text-align:center; margin:15px;">
|
42
|
-
<%=image_tag("/tr8n/images/tr8n_logo.png", :style => "height:120px;")%>
|
43
|
-
</div>
|
44
|
-
|
45
|
-
<h2 class="underscore content_hd">
|
46
|
-
<%=tr("Tr8n Label Internationalization")%>
|
47
|
-
</h2>
|
48
|
-
|
49
|
-
<div class="content_bd">
|
50
|
-
<h2><%=tr("Table of Content") %></h2>
|
51
|
-
<p>
|
52
|
-
<ul class='toc'>
|
53
|
-
<li><div><a href="#methods_introduction"><%=tr("Introduction") %></a></li>
|
54
|
-
<li><div><a href="#token_defintion"><%=tr("Definition of Tr8n Tokens") %></a></li>
|
55
|
-
<li><div><a href="#data_tokens"><%=tr("Data Tokens") %></a></li>
|
56
|
-
<li><div><a href="#method_tokens"><%=tr("Method Tokens") %></a></li>
|
57
|
-
<li><div><a href="#hidden_tokens"><%=tr("Hidden Tokens") %></a></li>
|
58
|
-
<li><div><a href="#transform_tokens"><%=tr("Transform Tokens") %></a></li>
|
59
|
-
<li><div><a href="#decoration_tokens"><%=tr("Decoration Tokens") %></a></li>
|
60
|
-
<li><div><a href="#next"><%=tr("What's next?") %></a></div></li>
|
61
|
-
</ul>
|
62
|
-
</p>
|
63
|
-
|
64
|
-
<a name="methods_introduction"> </a>
|
65
|
-
<h3>Introduction</h3>
|
66
|
-
|
67
|
-
<p>
|
68
|
-
The function for internationalizing labels has the following signature:
|
69
|
-
|
70
|
-
<div class="snippet">
|
71
|
-
<%= tr(LABEL, DESCRIPTION = "", TOKENS = {}, OPTIONS = {}) %><br><br>
|
72
|
-
* LABEL is a required string<br>
|
73
|
-
* DESCRIPTION is an optional, but highly recommended string<br>
|
74
|
-
* TOKENS is an optional hash of token values - it is required if tokens are used in the label<br>
|
75
|
-
* OPTIONS is an optional hash of options<br>
|
76
|
-
</div>
|
77
|
-
</p>
|
78
|
-
|
79
|
-
<p>
|
80
|
-
The following is the first simplest example of an internationalized phrase:
|
81
|
-
|
82
|
-
<div class="snippet">
|
83
|
-
<%= tr("Hello World") %>
|
84
|
-
</div>
|
85
|
-
|
86
|
-
or alternatively:
|
87
|
-
|
88
|
-
<div class="snippet">
|
89
|
-
<%= "Hello World".translate %>
|
90
|
-
</div>
|
91
|
-
</p>
|
92
|
-
|
93
|
-
<p class="try_it">Try it yourself:</p>
|
94
|
-
<div class="snippet2">
|
95
|
-
<%= tr("Hello World") %>
|
96
|
-
</div>
|
97
|
-
|
98
|
-
<p>As you might have noticed, the DESCRIPTION is not mandatory, but it should be used in cases when the label alone is not sufficient enough to determine the meaning of the sentence being translated. For example, when the translators use the bulk translation mode and look at the list of strings, they won’t be able to tell what the "Invite" by itself means. In that case DESCRIPTION will be very helpful.
|
99
|
-
</p>
|
100
|
-
|
101
|
-
<p>Tr8n translation engine uses label and description to create a unique key for each phrase. So the description serves two purposes: it creates a unique key for each label and it also gives a hint to the translators for the context in which the label is used. For example, the following two phrases will be registered as two independent entries in a database even though the have the same label, but a different description. The user will have to translate each one of them separately as they will have different translated labels in other languages.
|
102
|
-
</p>
|
103
|
-
|
104
|
-
<div class="snippet">
|
105
|
-
<%= tr("Invite", "Link to invite your friends to join the site") %><br>
|
106
|
-
<%= tr("Invite", "An invitation you recieved from your friend") %>
|
107
|
-
</div>
|
108
|
-
|
109
|
-
<p>It is important to provide the best possible description for each phrase from the start. Keep in mind that changing a description in the future, after it has already been translated, will register a new phrase in the database and invalidate all of its translations. On the other hand, labels that are complete sentences may not need a description as they are fully self-contained.
|
110
|
-
</p>
|
111
|
-
|
112
|
-
<p class="try_it">Try it yourself:</p>
|
113
|
-
<div class="snippet2">
|
114
|
-
<%= tr("Invite", "Link to invite your friends to join the site") %><br>
|
115
|
-
<%= tr("Invite", "An invitation you recieved from your friend") %>
|
116
|
-
</div>
|
117
|
-
|
118
|
-
<p>There are a number of other flavors of the "tr" function like trl, trfe, trfn that set default options for various reasons. You can read more about them in the Tr8n Integration Guide.
|
119
|
-
</p>
|
120
|
-
|
121
|
-
<p>The following is a short summary of the tr8n’s internationalization notations.</p>
|
122
|
-
|
123
|
-
<a name="token_defintion"> </a>
|
124
|
-
<h3>Definition of Tr8n Tokens</h3>
|
125
|
-
|
126
|
-
<p>It would have been boring if all of the labels in a site were just simple sentences without any dynamic data or decorations. Tr8n tokens are there to support the dynamic information in a label.
|
127
|
-
</p>
|
128
|
-
|
129
|
-
<p>Currently there are two major types of tokens defined in the extensible Tr8n syntax: data tokens and decoration tokens. Data tokens are defined as any strings surrounded by curly brackets inside of a label. So anything of this form {TOKEN_NAME} is considered a data token.
|
130
|
-
</p>
|
131
|
-
|
132
|
-
<p>Decoration tokens are defined as any string surrounded by squared brackets inside of a label. So anything of this form [TOKEN_NAME: decorated value\ is considered a decoration token.
|
133
|
-
</p>
|
134
|
-
|
135
|
-
<p>There are a number of different flavors of data tokens. Below are some of the flavors with some examples.
|
136
|
-
</p>
|
137
|
-
|
138
|
-
<a name="data_tokens"> </a>
|
139
|
-
<h3>Data Tokens</h3>
|
140
|
-
|
141
|
-
<p>There is a number of ways to substitute a data token with a value. Below are some of the main examples.
|
142
|
-
</p>
|
143
|
-
|
144
|
-
<strong>Simple string substitution:</strong>
|
145
|
-
|
146
|
-
<div class="snippet">
|
147
|
-
<%= tr("Dear {user}", "Fragment sample", :user => current_user) %>
|
148
|
-
</div>
|
149
|
-
|
150
|
-
<p>The to_s function will be applied on the value of the current_user variable and substituted into the {user} token.
|
151
|
-
</p>
|
152
|
-
|
153
|
-
<strong>Value substitution:</strong>
|
154
|
-
|
155
|
-
<div class="snippet">
|
156
|
-
<%= tr("Dear {user}", "Fragment sample", :user => [current_user, display_user(current_user)]) %>
|
157
|
-
</div>
|
158
|
-
|
159
|
-
<p>Notice one important thing that current_user is passed as a first element in the array. This is done for gender rules evaluation - i will describe this in the later sections. The second value is the actual value we want to subsitute into the {user} token.
|
160
|
-
</p>
|
161
|
-
|
162
|
-
<strong>Value substitution using symbol method call:</strong>
|
163
|
-
<div class="snippet">
|
164
|
-
<%= tr("Dear {user}", "Fragment sample", :user => [current_user, :first_name]) %>
|
165
|
-
</div>
|
166
|
-
|
167
|
-
<p>As in the previous example, first object for rules engine, second is a symbol that represents a method that will be called on the object and the result will be placed into the {user} token.
|
168
|
-
</p>
|
169
|
-
|
170
|
-
<strong>Value substitution using symbol method call with parameters:</strong>
|
171
|
-
<div class="snippet">
|
172
|
-
<%= tr("Dear {user}", "Fragment sample", :user => [current_user, :some_method, "value"]) %>
|
173
|
-
</div>
|
174
|
-
|
175
|
-
<p>Same as the above example, but the method can be called with some parameters.</p>
|
176
|
-
|
177
|
-
<strong>Value substitution using lambda method call:</strong>
|
178
|
-
|
179
|
-
<div class="snippet">
|
180
|
-
<%= tr("Dear {user}", "Fragment sample", :user => [current_user, lambda{|val| html_for(val)}]) %>
|
181
|
-
</div>
|
182
|
-
<p>The second parameter can also be a lambda. In that case current_user will be passed as a val into the lambda and the result of the lambda evaluation will be placed into the {user} token.
|
183
|
-
</p>
|
184
|
-
|
185
|
-
<strong>Value substitution using lambda method call with parameters:</strong>
|
186
|
-
<div class="snippet">
|
187
|
-
<%= tr("Dear {user}", "Fragment sample", :user => [current_user, lambda{|val, test| html_for(val, test)}], "test"]) %>
|
188
|
-
</div>
|
189
|
-
|
190
|
-
<p>Same as the above, but lambda has some additional parameters.</p>
|
191
|
-
|
192
|
-
<p>You may be wondering why we need so many variations. Well, they are all useful, as you will see later.
|
193
|
-
</p>
|
194
|
-
|
195
|
-
<p class="try_it">Try it yourself:</p>
|
196
|
-
<div class="snippet2">
|
197
|
-
<%= tr("Dear {user}", "Fragment sample", :user => [Tr8n::Config.current_user, :name]) %>
|
198
|
-
</div>
|
199
|
-
|
200
|
-
<a name="method_tokens"> </a>
|
201
|
-
<h3>Method Tokens</h3>
|
202
|
-
|
203
|
-
<p>Method token allows you to call a method on a token itself. It is useful if you have multiple method calls on the same token in one sentence. Consider the following example:
|
204
|
-
</p>
|
205
|
-
|
206
|
-
<div class="snippet">
|
207
|
-
<%= tr("Dear {user.first_name} {user.last_name}", "Fragment sample", :user => current_user) %>
|
208
|
-
</div>
|
209
|
-
|
210
|
-
<p>Since the substitution is implied in the token definition itself, you don’t have to use any of the basic data token substitution forms.
|
211
|
-
</p>
|
212
|
-
|
213
|
-
<a name="hidden_tokens"> </a>
|
214
|
-
<h3>Hidden Tokens</h3>
|
215
|
-
|
216
|
-
<p>Hidden tokens are used primarely for the default language dynamic data substitution that would not make sense in the translated label. Hidden tokens will not appear as tokens when translator opens the translation dialog. Consider the following examples:
|
217
|
-
</p>
|
218
|
-
|
219
|
-
<div class="snippet">
|
220
|
-
<%= tr("{user} changed {_his_her} name", "Fragment sample", :user => current_user, :_his_her => current_user.his_her) %><br>
|
221
|
-
<%= tr("you have {count} {_messages}", "Fragment sample", :count => NUM, :_messages => "message".pluralize_for(NUM)) %>
|
222
|
-
</div>
|
223
|
-
|
224
|
-
<p>In the first cases _his_her will be subsituted in English to the appropriate phrase based on the current_user gender. And in the second case the correct form of message will be used based on whether the number is 1 or other.
|
225
|
-
</p>
|
226
|
-
|
227
|
-
<p>There is a better approach for the above examples, using the Transform tokens. But there may still be situations when hidden token can be useful.
|
228
|
-
</p>
|
229
|
-
|
230
|
-
<a name="transform_tokens"> </a>
|
231
|
-
<h3>Transform tokens</h3>
|
232
|
-
|
233
|
-
<p>Transform tokens are used together with rules defined in the rules engine. Their primary job is to provide shortcuts for rule based tokens in the site native language. Consider the following example:
|
234
|
-
</p>
|
235
|
-
|
236
|
-
<div class="snippet">
|
237
|
-
<%= tr("{user} changed {user| his, her} name", "Fragment sample", :user => current_user) %>
|
238
|
-
</div>
|
239
|
-
|
240
|
-
<p>Notice that the hidden token has been replaced by the transform token. Keep in mind that {user} token must be registered as a gender based token. Consider another example:
|
241
|
-
</p>
|
242
|
-
|
243
|
-
<div class="snippet">
|
244
|
-
<%= tr("You have {count|| message, messages}", "Fragment sample", :count => messages.size) %>
|
245
|
-
</div>
|
246
|
-
|
247
|
-
<p>Notice that, in this case, {count} must be registered as a number based token. When the native language rule is evaluated it will use the singular or plural form of the word "message" based on the value of count. A single pipe indicates that the comma delimited word(s) that follow it are dependent on the token value, but the token itself should not be displayed. A double pipe indicates that the value of the token should be displayd as well. You don’t have to provide the plural form of the word if it can be derived from a singular form. So {count|| message} will be good enough and it will be pluralized by the engine automatically. Every rule has support for a transform token. For example:
|
248
|
-
</p>
|
249
|
-
|
250
|
-
<div class="snippet">
|
251
|
-
<%= tr("Michael {date| turned, turns, will turn} 33 on {date}", "Fragment sample", :date => some_date) %>
|
252
|
-
</div>
|
253
|
-
|
254
|
-
<p>This is the case when piped token is used for a date token object. And one more example for a list:
|
255
|
-
</p>
|
256
|
-
|
257
|
-
<div class="snippet">
|
258
|
-
<%= tr("{users|| likes, like} this link", "Fragment sample", :users => [users_list, lambda{|user| user.first_name}]) %>
|
259
|
-
</div>
|
260
|
-
|
261
|
-
<p>In this case if the users array contains a single element it will use the first form, otherwise it will use the plural form.
|
262
|
-
</p>
|
263
|
-
|
264
|
-
<a name="decoration_tokens"> </a>
|
265
|
-
<h3>Decoration tokens</h3>
|
266
|
-
|
267
|
-
<p>Decoration tokens are used to decorate some text in a label. Consider the following example:
|
268
|
-
</p>
|
269
|
-
|
270
|
-
<div class="snippet">
|
271
|
-
<%= tr("[link: Click here] to visit our site", "Fragment sample", :link => lambda{|text| link_to(text, 'http://www.google.com')}) %>
|
272
|
-
</div>
|
273
|
-
<p>When this label is rendered "Click here" will be turned into a link. </p>
|
274
|
-
|
275
|
-
<p class="try_it">Try it yourself:</p>
|
276
|
-
<div class="snippet2">
|
277
|
-
<%= tr("[link: Click here] to visit our site", "Fragment sample", :link => lambda{|text| link_to(text, 'http://www.google.com')}) %>
|
278
|
-
</div>
|
279
|
-
|
280
|
-
<p>Similarly you can do any kind of HTML decorations inside of the label. Alternative ways for using decorations are:</p>
|
281
|
-
<div class="snippet">
|
282
|
-
<%= tr("[link: Click here] to visit Google", "Fragment sample", :link => "<a href='http://www.google.com'>{$0}</a>") %>
|
283
|
-
</div>
|
284
|
-
|
285
|
-
<p>{$0} is the translated value of the link. And another way, using a default decoration:
|
286
|
-
</p>
|
287
|
-
|
288
|
-
<div class="snippet">
|
289
|
-
<%= tr("[link: Click here] to visit Google", "Fragment sample", :link => ['http://www.google.com']) %>
|
290
|
-
</div>
|
291
|
-
|
292
|
-
<p class="try_it">Try it yourself:</p>
|
293
|
-
<div class="snippet2">
|
294
|
-
<%= tr("[link: Click here] to visit Google", "Fragment sample", :link => ['http://www.google.com']) %>
|
295
|
-
</div>
|
296
|
-
|
297
|
-
<p>The default decorations are defined in the config/tr8n/tokens/decorations.yml file. The are presented in the following form:
|
298
|
-
</p>
|
299
|
-
|
300
|
-
<div class="snippet">
|
301
|
-
bold: "<strong>{$0}</strong>"<br>
|
302
|
-
italic: "<i>{$0}</i>"<br>
|
303
|
-
link: "<a href='{$1}' style='{$2}'>{$0}</a>"<br>
|
304
|
-
</div>
|
305
|
-
|
306
|
-
<p>You can edit the file and add as many of the default decorations as you need. Notice that you do not need to provide token parameters for decorations that only use {$0} token. So this would work just fine:
|
307
|
-
</p>
|
308
|
-
|
309
|
-
<div class="snippet">
|
310
|
-
<%= tr("This is some [bold: very cool] stuff!") %>
|
311
|
-
</div>
|
312
|
-
|
313
|
-
<p class="try_it">Try it yourself:</p>
|
314
|
-
<div class="snippet2">
|
315
|
-
<%= tr("This is some [bold: very cool] stuff!") %>
|
316
|
-
</div>
|
317
|
-
|
318
|
-
<a name="next"> </a>
|
319
|
-
<h2>What's next?</h2>
|
320
|
-
|
321
|
-
Cnogratulations! You have completed the second part of the integration guide. Now read on about <%=link_to("Tr8n Rules Engine Configuration", "/tr8n/home/rules")%>.
|
322
|
-
|
323
|
-
</div>
|
324
|
-
<% end %>
|
data/lib/tr8n/common_methods.rb
DELETED
@@ -1,61 +0,0 @@
|
|
1
|
-
#--
|
2
|
-
# Copyright (c) 2010-2011 Michael Berkovich
|
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 Tr8n::CommonMethods
|
25
|
-
|
26
|
-
# translation functions
|
27
|
-
def tr(label, desc = "", tokens = {}, options = {})
|
28
|
-
unless desc.nil? or desc.is_a?(String)
|
29
|
-
raise Tr8n::Exception.new("The second parameter of the tr function must be a description")
|
30
|
-
end
|
31
|
-
|
32
|
-
begin
|
33
|
-
url = request.url
|
34
|
-
host = request.env['HTTP_HOST']
|
35
|
-
source = "#{controller.class.name.underscore.gsub("_controller", "")}/#{controller.action_name}"
|
36
|
-
rescue Exception => ex
|
37
|
-
source = self.class.name
|
38
|
-
url = nil
|
39
|
-
host = 'localhost'
|
40
|
-
end
|
41
|
-
|
42
|
-
options.merge!(:source => source) unless options[:source]
|
43
|
-
options.merge!(:caller => caller)
|
44
|
-
options.merge!(:url => url)
|
45
|
-
options.merge!(:host => host)
|
46
|
-
|
47
|
-
# pp [source, options[:source], url]
|
48
|
-
|
49
|
-
unless Tr8n::Config.enabled?
|
50
|
-
return Tr8n::TranslationKey.substitute_tokens(label, tokens, options)
|
51
|
-
end
|
52
|
-
|
53
|
-
Tr8n::Config.current_language.translate(label, desc, tokens, options)
|
54
|
-
end
|
55
|
-
|
56
|
-
# for translating labels
|
57
|
-
def trl(label, desc = "", tokens = {}, options = {})
|
58
|
-
tr(label, desc, tokens, options.merge(:skip_decorations => true))
|
59
|
-
end
|
60
|
-
|
61
|
-
end
|
data/lib/tr8n/helper_methods.rb
DELETED
@@ -1,304 +0,0 @@
|
|
1
|
-
#--
|
2
|
-
# Copyright (c) 2010-2011 Michael Berkovich
|
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 Tr8n::HelperMethods
|
25
|
-
include Tr8n::CommonMethods
|
26
|
-
|
27
|
-
def tr8n_options_for_select(options, selected = nil, description = nil, lang = Tr8n::Config.current_language)
|
28
|
-
options_for_select(options.tro(description), selected)
|
29
|
-
end
|
30
|
-
|
31
|
-
def tr8n_phrases_link_tag(search = "", phrase_type = :without, phrase_status = :any)
|
32
|
-
return unless Tr8n::Config.enabled?
|
33
|
-
return if Tr8n::Config.current_language.default?
|
34
|
-
return unless Tr8n::Config.open_registration_mode? or Tr8n::Config.current_user_is_translator?
|
35
|
-
return unless Tr8n::Config.current_translator.enable_inline_translations?
|
36
|
-
|
37
|
-
link_to(image_tag("/tr8n/images/translate_icn.gif", :style => "vertical-align:middle; border: 0px;", :title => search),
|
38
|
-
:controller => "/tr8n/phrases", :action => :index,
|
39
|
-
:search => search, :phrase_type => phrase_type, :phrase_status => phrase_status).html_safe
|
40
|
-
end
|
41
|
-
|
42
|
-
def tr8n_dir_attribute_tag
|
43
|
-
"dir='<%=Tr8n::Config.current_language.dir%>'".html_safe
|
44
|
-
end
|
45
|
-
|
46
|
-
def tr8n_splash_screen_tag
|
47
|
-
html = "<div id='tr8n_splash_screen' style='display:none'>"
|
48
|
-
html << (render :partial => Tr8n::Config.splash_screen)
|
49
|
-
html << "</div>"
|
50
|
-
html.html_safe
|
51
|
-
end
|
52
|
-
|
53
|
-
def tr8n_language_flag_tag(lang = Tr8n::Config.current_language, opts = {})
|
54
|
-
return "" unless Tr8n::Config.enable_language_flags?
|
55
|
-
html = image_tag("/tr8n/images/flags/#{lang.flag}.png", :style => "vertical-align:middle;", :title => lang.native_name)
|
56
|
-
html << " ".html_safe
|
57
|
-
html.html_safe
|
58
|
-
end
|
59
|
-
|
60
|
-
def tr8n_language_name_tag(lang = Tr8n::Config.current_language, opts = {})
|
61
|
-
show_flag = opts[:flag].nil? ? true : opts[:flag]
|
62
|
-
name_type = opts[:name].nil? ? :full : opts[:name] # :full, :native, :english, :locale
|
63
|
-
linked = opts[:linked].nil? ? true : opts[:linked]
|
64
|
-
|
65
|
-
html = "<span style='white-space: nowrap'>"
|
66
|
-
html << tr8n_language_flag_tag(lang, opts) if show_flag
|
67
|
-
|
68
|
-
name = case name_type
|
69
|
-
when :native then lang.native_name
|
70
|
-
when :english then lang.english_name
|
71
|
-
when :locale then lang.locale
|
72
|
-
else lang.full_name
|
73
|
-
end
|
74
|
-
|
75
|
-
if linked
|
76
|
-
html << link_to(name.html_safe, :controller => "/tr8n/language",
|
77
|
-
:action => :switch, :language_action => :switch_language,
|
78
|
-
:locale => lang.locale,
|
79
|
-
:source_url => opts[:source_url])
|
80
|
-
else
|
81
|
-
html << name
|
82
|
-
end
|
83
|
-
|
84
|
-
html << "</span>"
|
85
|
-
html.html_safe
|
86
|
-
end
|
87
|
-
|
88
|
-
def tr8n_language_selector_tag(opts = {})
|
89
|
-
opts[:style] ||= "color:#1166bb;"
|
90
|
-
opts[:show_arrow] ||= true
|
91
|
-
opts[:arrow_style] ||= "font-size:8px;"
|
92
|
-
render(:partial => '/tr8n/common/language_selector', :locals => {:opts => opts})
|
93
|
-
end
|
94
|
-
|
95
|
-
def tr8n_language_strip_tag(opts = {})
|
96
|
-
opts[:flag] = opts[:flag].nil? ? false : opts[:flag]
|
97
|
-
opts[:name] = opts[:name].nil? ? :native : opts[:name]
|
98
|
-
opts[:linked] = opts[:linked].nil? ? true : opts[:linked]
|
99
|
-
opts[:javascript] = opts[:javascript].nil? ? false : opts[:javascript]
|
100
|
-
|
101
|
-
render(:partial => '/tr8n/common/language_strip', :locals => {:opts => opts})
|
102
|
-
end
|
103
|
-
|
104
|
-
def tr8n_language_table_tag(opts = {})
|
105
|
-
opts[:cols] = opts[:cols].nil? ? 4 : opts[:cols]
|
106
|
-
opts[:col_size] = opts[:col_size].nil? ? "300px" : opts[:col_size]
|
107
|
-
render(:partial => '/tr8n/common/language_table', :locals => {:opts => opts.merge(:name => :english)})
|
108
|
-
end
|
109
|
-
|
110
|
-
def tr8n_translator_login_tag(opts = {})
|
111
|
-
opts[:class] ||= 'tr8n_right_horiz_list'
|
112
|
-
render(:partial => '/tr8n/common/translator_login', :locals => {:opts => opts})
|
113
|
-
end
|
114
|
-
|
115
|
-
def tr8n_flashes_tag(opts = {})
|
116
|
-
render(:partial => '/tr8n/common/flashes', :locals => {:opts => opts})
|
117
|
-
end
|
118
|
-
|
119
|
-
def tr8n_scripts_tag(opts = {})
|
120
|
-
render(:partial => '/tr8n/common/scripts', :locals => {:opts => opts})
|
121
|
-
end
|
122
|
-
|
123
|
-
def tr8n_client_sdk_scripts_tag(opts = {})
|
124
|
-
javascript_include_tag("/tr8n/javascripts/tr8n_client_sdk.js", :locals => {:opts => opts})
|
125
|
-
end
|
126
|
-
|
127
|
-
def tr8n_translator_rank_tag(translator, rank = nil)
|
128
|
-
return "" unless translator
|
129
|
-
|
130
|
-
rank ||= translator.rank || 0
|
131
|
-
|
132
|
-
html = "<span dir='ltr'>"
|
133
|
-
1.upto(5) do |i|
|
134
|
-
if rank > i * 20 - 10 and rank < i * 20
|
135
|
-
html << image_tag("/tr8n/images/rating_star05.png")
|
136
|
-
elsif rank < i * 20 - 10
|
137
|
-
html << image_tag("/tr8n/images/rating_star0.png")
|
138
|
-
else
|
139
|
-
html << image_tag("/tr8n/images/rating_star1.png")
|
140
|
-
end
|
141
|
-
end
|
142
|
-
html << "</span>"
|
143
|
-
html.html_safe
|
144
|
-
end
|
145
|
-
|
146
|
-
def tr8n_help_icon_tag(filename = "index")
|
147
|
-
link_to(image_tag("/tr8n/images/help.png", :style => "border:0px; vertical-align:middle;", :title => trl("Help")), {:controller => "/tr8n/help", :action => filename}, :target => "_new").html_safe
|
148
|
-
end
|
149
|
-
|
150
|
-
def tr8n_help_link(text, opts = {})
|
151
|
-
filename = opts[:filename].nil? ? text.downcase.gsub(' ', '_') : opts[:filename]
|
152
|
-
classname = "tr8n_selected" if filename == controller.action_name
|
153
|
-
link_to(text, { :controller => "/tr8n/help", :action => filename }, :class => classname).html_safe
|
154
|
-
end
|
155
|
-
|
156
|
-
def tr8n_spinner_tag(id = "spinner", label = nil, cls='spinner')
|
157
|
-
html = "<div id='#{id}' class='#{cls}' style='display:none'>"
|
158
|
-
html << image_tag("/tr8n/images/spinner.gif", :style => "vertical-align:middle;")
|
159
|
-
html << " #{trl(label)}" if label
|
160
|
-
html << "</div>"
|
161
|
-
html.html_safe
|
162
|
-
end
|
163
|
-
|
164
|
-
def tr8n_toggler_tag(content_id, label = "", open = true)
|
165
|
-
html = "<span id='#{content_id}_open' "
|
166
|
-
html << "style='display:none'" unless open
|
167
|
-
html << ">"
|
168
|
-
html << link_to_function("#{image_tag("/tr8n/images/arrow_down.gif", :style=>'text-align:center; vertical-align:middle')} #{label}".html_safe, "Tr8n.Effects.hide('#{content_id}_open'); Tr8n.Effects.show('#{content_id}_closed'); Tr8n.Effects.blindUp('#{content_id}');", :style=> "text-decoration:none")
|
169
|
-
html << "</span>"
|
170
|
-
html << "<span id='#{content_id}_closed' "
|
171
|
-
html << "style='display:none'" if open
|
172
|
-
html << ">"
|
173
|
-
html << link_to_function("#{image_tag("/tr8n/images/arrow_right.gif", :style=>'text-align:center; vertical-align:middle')} #{label}".html_safe, "Tr8n.Effects.show('#{content_id}_open'); Tr8n.Effects.hide('#{content_id}_closed'); Tr8n.Effects.blindDown('#{content_id}');", :style=> "text-decoration:none")
|
174
|
-
html << "</span>"
|
175
|
-
html.html_safe
|
176
|
-
end
|
177
|
-
|
178
|
-
def tr8n_sitemap(sections, splitters, options = {})
|
179
|
-
html = ""
|
180
|
-
html << "<table style='width:100%'>"
|
181
|
-
html << "<tr>"
|
182
|
-
splitters.each do |splitter|
|
183
|
-
html << "<td style='vertical-align:top; width:" << (100 / splitters.size).to_s << "%;'>"
|
184
|
-
html << generate_sitemap(sections[splitter.first..splitter.last], options)
|
185
|
-
html << "</td>"
|
186
|
-
end
|
187
|
-
html << "</tr>"
|
188
|
-
html << "</table>"
|
189
|
-
html.html_safe
|
190
|
-
end
|
191
|
-
|
192
|
-
def tr8n_breadcrumb_tag(source = nil, opts = {})
|
193
|
-
source ||= "#{controller.class.name.underscore.gsub("_controller", "")}/#{controller.action_name}"
|
194
|
-
section = Tr8n::SiteMap.section_for_source(source)
|
195
|
-
return "" unless section
|
196
|
-
opts[:separator] ||= " >> "
|
197
|
-
opts[:min_elements] ||= 1
|
198
|
-
opts[:skip_root] ||= opts[:skip_root].nil? ? false : opts[:skip_root]
|
199
|
-
|
200
|
-
links = section.parents.collect{|node| link_to(node.title(params), node.link(params))}
|
201
|
-
return "" if links.size <= opts[:min_elements]
|
202
|
-
|
203
|
-
links.delete(links.first) if opts[:skip_root]
|
204
|
-
links.unshift(link_to(opts[:root].first, opts[:root].last)) if opts[:root]
|
205
|
-
|
206
|
-
html = "<div id='tr8n_breadcrumb' class='tr8n_breadcrumb'>"
|
207
|
-
html << links.join(opts[:separator])
|
208
|
-
html << '</div>'
|
209
|
-
html.html_safe
|
210
|
-
end
|
211
|
-
|
212
|
-
def tr8n_user_tag(translator, options = {})
|
213
|
-
return "Deleted Translator" unless translator
|
214
|
-
|
215
|
-
if options[:linked]
|
216
|
-
link_to(translator.name, translator.link).html_safe
|
217
|
-
else
|
218
|
-
translator.name
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
def tr8n_user_mugshot_tag(translator, options = {})
|
223
|
-
if translator and !translator.mugshot.blank?
|
224
|
-
img_url = translator.mugshot
|
225
|
-
else
|
226
|
-
img_url = Tr8n::Config.silhouette_image
|
227
|
-
end
|
228
|
-
|
229
|
-
img_tag = "<img src='#{img_url}' style='width:48px'>".html_safe
|
230
|
-
|
231
|
-
if translator and options[:linked]
|
232
|
-
link_to(img_tag, translator.link).html_safe
|
233
|
-
else
|
234
|
-
img_tag.html_safe
|
235
|
-
end
|
236
|
-
end
|
237
|
-
|
238
|
-
def tr8n_will_paginate(collection = nil, options = {})
|
239
|
-
will_paginate(collection, options.merge(:previous_label => tr("« Previous", "Previous entries in a list", {}, options),
|
240
|
-
:next_label => tr("Next »", "Next entries in a list", {}, options))).html_safe
|
241
|
-
end
|
242
|
-
|
243
|
-
def tr8n_page_entries_info(collection, options = {})
|
244
|
-
entry_name = options[:entry_name] || (collection.empty? ? 'entry' : collection.first.class.name.underscore.sub('_', ' '))
|
245
|
-
|
246
|
-
if collection.total_pages < 2
|
247
|
-
case collection.size
|
248
|
-
when 0
|
249
|
-
tr("None found", "Paginator no entries message", {}, options)
|
250
|
-
when 1
|
251
|
-
tr("Displaying [bold: 1] #{entry_name}", "Paginator one page message", {}, options)
|
252
|
-
else
|
253
|
-
tr("Displaying [bold: all {count}] #{entry_name.pluralize}", "Paginator all entries message", {:count => collection.size}, options)
|
254
|
-
end
|
255
|
-
else
|
256
|
-
tr("Displaying #{entry_name.pluralize} [bold: {start_num} - {end_num}] of [bold: {total_count}] in total",
|
257
|
-
"Paginator custom message", {
|
258
|
-
:start_num => collection.offset + 1,
|
259
|
-
:end_num => collection.offset + collection.length,
|
260
|
-
:total_count => collection.total_entries
|
261
|
-
}, options
|
262
|
-
)
|
263
|
-
end
|
264
|
-
end
|
265
|
-
|
266
|
-
def tr8n_select_month(date, options = {}, html_options = {})
|
267
|
-
month_names = options[:use_short_month] ? Tr8n::Config.default_abbr_month_names : Tr8n::Config.default_month_names
|
268
|
-
select_month(date, options.merge(
|
269
|
-
:use_month_names => month_names.collect{|month_name| Tr8n::Language.translate(month_name, options[:description] || "Month name")}
|
270
|
-
), html_options)
|
271
|
-
end
|
272
|
-
|
273
|
-
def tr8n_with_options_tag(opts, &block)
|
274
|
-
Thread.current[:tr8n_block_options] = opts
|
275
|
-
if block_given?
|
276
|
-
ret = capture(&block)
|
277
|
-
end
|
278
|
-
Thread.current[:tr8n_block_options] = {}
|
279
|
-
ret
|
280
|
-
end
|
281
|
-
|
282
|
-
def tr8n_button_tag(label, function, opts = {})
|
283
|
-
link_to_function("<span>#{label}</span>".html_safe, function, :class => "tr8n_grey_button tr8n_pcb")
|
284
|
-
end
|
285
|
-
|
286
|
-
private
|
287
|
-
|
288
|
-
def generate_sitemap(sections, options = {})
|
289
|
-
html = "<ul class='section_list'>"
|
290
|
-
sections.each do |section|
|
291
|
-
html << "<li class='section_list_item'>"
|
292
|
-
html << "<a href='/tr8n/phrases/index?section_key=#{section.key}'>" << tr(section.label, section.description) << "</a>"
|
293
|
-
html << "<a href='" << section.data[:link] << "' target='_new'><img src='/tr8n/images/bullet_go.png' style='border:0px; vertical-align:middle'></a>" if section.data[:link]
|
294
|
-
|
295
|
-
if section.children.size > 0
|
296
|
-
html << generate_sitemap(section.children, options)
|
297
|
-
end
|
298
|
-
html << "</li>"
|
299
|
-
end
|
300
|
-
html << "</ul>"
|
301
|
-
html.html_safe
|
302
|
-
end
|
303
|
-
|
304
|
-
end
|