rubi18n 0.3
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.
- data/LICENSE +166 -0
- data/README +177 -0
- data/Rakefile +95 -0
- data/base/en.yml +15 -0
- data/base/ru.yml +13 -0
- data/lib/rubi18n/formatters.rb +74 -0
- data/lib/rubi18n/locale.rb +124 -0
- data/lib/rubi18n/translated_string.rb +33 -0
- data/lib/rubi18n/translation.rb +269 -0
- data/lib/rubi18n.rb +29 -0
- data/locales/en.yml +13 -0
- data/locales/en_US.yml +5 -0
- data/locales/ru.yml +13 -0
- data/spec/formatters_spec.rb +19 -0
- data/spec/locale_spec.rb +71 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/translation_spec.rb +106 -0
- data/spec/translations/extention/en.yml +2 -0
- data/spec/translations/extention/no_TR.yml +1 -0
- data/spec/translations/general/en.yml +31 -0
- data/spec/translations/general/fr.yml +1 -0
- data/spec/translations/general/no_LC.yml +4 -0
- data/spec/translations/general/ru.yml +5 -0
- metadata +78 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
=begin
|
2
|
+
Translation string for i18n support.
|
3
|
+
|
4
|
+
Copyright (C) 2008 Andrey "A.I." Sitnik <andrey@sitnik.ru>
|
5
|
+
|
6
|
+
This program is free software: you can redistribute it and/or modify
|
7
|
+
it under the terms of the GNU Lesser General Public License as published by
|
8
|
+
the Free Software Foundation, either version 3 of the License, or
|
9
|
+
(at your option) any later version.
|
10
|
+
|
11
|
+
This program is distributed in the hope that it will be useful,
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
GNU Lesser General Public License for more details.
|
15
|
+
|
16
|
+
You should have received a copy of the GNU Lesser General Public License
|
17
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
=end
|
19
|
+
|
20
|
+
module Rubi18n
|
21
|
+
# String, which is translated to some locale and loading from Translation.
|
22
|
+
class TranslatedString < String
|
23
|
+
# String locale
|
24
|
+
attr_reader :locale
|
25
|
+
|
26
|
+
# Returns a new string object containing a copy of str and translated to
|
27
|
+
# +locale+
|
28
|
+
def initialize(str, locale)
|
29
|
+
super(str)
|
30
|
+
@locale = locale
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,269 @@
|
|
1
|
+
=begin
|
2
|
+
Translation to i18n support.
|
3
|
+
|
4
|
+
Copyright (C) 2008 Andrey “A.I.” Sitnik <andrey@sitnik.ru>
|
5
|
+
|
6
|
+
This program is free software: you can redistribute it and/or modify
|
7
|
+
it under the terms of the GNU Lesser General Public License as published by
|
8
|
+
the Free Software Foundation, either version 3 of the License, or
|
9
|
+
(at your option) any later version.
|
10
|
+
|
11
|
+
This program is distributed in the hope that it will be useful,
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
GNU Lesser General Public License for more details.
|
15
|
+
|
16
|
+
You should have received a copy of the GNU Lesser General Public License
|
17
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
=end
|
19
|
+
|
20
|
+
require "pathname"
|
21
|
+
require "yaml"
|
22
|
+
|
23
|
+
module Rubi18n
|
24
|
+
# Translation for interface to i18n support.
|
25
|
+
#
|
26
|
+
# Translation files use YAML format and has name CODE.yml, where CODE is a
|
27
|
+
# language/country code (RFC 3066) like en_US. For example: en.yaml is a
|
28
|
+
# English translation, en_US.yml is a translation to USA English dialect.
|
29
|
+
#
|
30
|
+
# Rubi18n contain translations for common words (such as “OK”, “Cancel”, etc)
|
31
|
+
# for most supported locales. See <tt>base/</tt> dir.
|
32
|
+
#
|
33
|
+
# You may load several locales. Also for each locale will be load it
|
34
|
+
# sublocales – languages, which user often know in this locale. For example,
|
35
|
+
# many, who speak on Frensh dialects in Canada can understand original French.
|
36
|
+
# Also many people in Belarus can understand Russian.
|
37
|
+
#
|
38
|
+
# Translated strinsg will have locale methods, which return Locale of locale
|
39
|
+
# code if locale info file isn't exists.
|
40
|
+
#
|
41
|
+
# == Examples
|
42
|
+
# translations/fr.yaml
|
43
|
+
#
|
44
|
+
# one: Un
|
45
|
+
#
|
46
|
+
# translations/ru.yaml
|
47
|
+
#
|
48
|
+
# one: Один
|
49
|
+
# two: Два
|
50
|
+
#
|
51
|
+
# translations/en.yaml
|
52
|
+
#
|
53
|
+
# one: One
|
54
|
+
# two: Two
|
55
|
+
# three: Three
|
56
|
+
#
|
57
|
+
# entry:
|
58
|
+
# between: Between %1 and %2
|
59
|
+
# methods: Is %1 method
|
60
|
+
#
|
61
|
+
# comments: !!pl
|
62
|
+
# 0: no comments
|
63
|
+
# 1: one comment
|
64
|
+
# n: %1 comments
|
65
|
+
#
|
66
|
+
# sum: !!proc |x, y| "is #{x + y}"
|
67
|
+
#
|
68
|
+
# example.rb
|
69
|
+
#
|
70
|
+
# i18n = Rubi18n::Translation.load(["fr", "ru"], "translations/")
|
71
|
+
# i18n.one #=> "Un"
|
72
|
+
# i18n.two #=> "Два"
|
73
|
+
# i18n.three #=> "Three"
|
74
|
+
#
|
75
|
+
# i18n.three.locale["code"] #=> "en"
|
76
|
+
# i18n.three.locale["direction"] #=> "ltr"
|
77
|
+
#
|
78
|
+
# i18n.entry.between(2, 3) #=> "between 2 and 3"
|
79
|
+
# i18n["methods", "object"] #=> "Is object method"
|
80
|
+
#
|
81
|
+
# i18n.comments(0) #=> "no comments"
|
82
|
+
# i18n.comments(10) #=> "10 comments"
|
83
|
+
#
|
84
|
+
# i18n.sum(2, 3) #=> "is 5"
|
85
|
+
#
|
86
|
+
# == Extention translations
|
87
|
+
# You can add dir with translations, which will be used with application
|
88
|
+
# translations. If application translations with same locale isn't exists
|
89
|
+
# extention files willn't be used.
|
90
|
+
#
|
91
|
+
# It's useful for plugins for rubi18n. For example DB plugin may place
|
92
|
+
# translations for error messages in extention dir. Rubi18n contain
|
93
|
+
# translations for base words as extention dir too.
|
94
|
+
class Translation
|
95
|
+
@@default = "en"
|
96
|
+
|
97
|
+
# Set default locale code to use when any user locales willn't be founded.
|
98
|
+
# It should has all translations and locale file.
|
99
|
+
def self.default=(locale)
|
100
|
+
@@default = locale
|
101
|
+
end
|
102
|
+
|
103
|
+
# Get default locale code
|
104
|
+
def self.default
|
105
|
+
@@default
|
106
|
+
end
|
107
|
+
|
108
|
+
@@extension_translations = [
|
109
|
+
Pathname(__FILE__).dirname.expand_path + "../../base"]
|
110
|
+
|
111
|
+
# Get dirs with extention translations. If application translations with
|
112
|
+
# same locale isn't exists extention files willn't be used.
|
113
|
+
def self.extension_translations
|
114
|
+
@@extension_translations
|
115
|
+
end
|
116
|
+
|
117
|
+
# Return available translations in +translations_dir+
|
118
|
+
def self.available(translations_dir)
|
119
|
+
Dir.glob(File.join(translations_dir, "*.yml")).map do |i|
|
120
|
+
File.basename(i, ".yml")
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Load locale and translations. +locales+ may be string for one user locale
|
125
|
+
# or array with many.
|
126
|
+
#
|
127
|
+
# It load all available translations in +translations_dir+, which exists in
|
128
|
+
# +locales+. Next it load all translations for +sublocales+ in locale info
|
129
|
+
# for all loaded translations.
|
130
|
+
#
|
131
|
+
# == Example
|
132
|
+
# +locales+ is ["fr", "uk"], translations are available for "fr", "be", "ru"
|
133
|
+
# and "en". Translation will be founding firstly in "fr" next in "be" and
|
134
|
+
# next in "ru" and "en" (because many Belarusians know Russian and "be"
|
135
|
+
# locale contain in +sublocales+ "ru" and "en").
|
136
|
+
def self.load(locales, translations_dir)
|
137
|
+
locales = locales.to_a if String == locales.class
|
138
|
+
locales << @@default
|
139
|
+
|
140
|
+
locales += Locale.find(locales)["sublocales"]
|
141
|
+
locales.each_with_index do |locale, i|
|
142
|
+
# Add language locale for dialects
|
143
|
+
if "_" == locale[2..2]
|
144
|
+
locales.insert(i + 1, locale[0..1])
|
145
|
+
end
|
146
|
+
end
|
147
|
+
locales.uniq!
|
148
|
+
|
149
|
+
locales &= self.available(translations_dir)
|
150
|
+
|
151
|
+
translations = []
|
152
|
+
locales.map! do |locale|
|
153
|
+
locale.delete!("/", "\\")
|
154
|
+
|
155
|
+
translation = {}
|
156
|
+
@@extension_translations.each do |dir|
|
157
|
+
file = File.join(dir, "#{locale}.yml")
|
158
|
+
translation.merge! YAML::load_file(file) if File.exists? file
|
159
|
+
end
|
160
|
+
file = File.join(translations_dir, "#{locale}.yml")
|
161
|
+
translation.merge! YAML::load_file(file)
|
162
|
+
translations << translation
|
163
|
+
|
164
|
+
if Locale.exists? locale
|
165
|
+
Locale.new(locale)
|
166
|
+
else
|
167
|
+
locale
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
self.new(locales, translations)
|
172
|
+
end
|
173
|
+
|
174
|
+
# Default pluralization rule to translation without locale info
|
175
|
+
def self.pluralize(n)
|
176
|
+
n == 0 ? 0 : n == 1 ? 1 : 'n'
|
177
|
+
end
|
178
|
+
|
179
|
+
# Create translation hash with messages in +translations+ for +locales+.
|
180
|
+
#
|
181
|
+
# This is internal contructor to load translation use
|
182
|
+
# Rubi18n::Translation.load(locales, translations_dir).
|
183
|
+
def initialize(locales, translations)
|
184
|
+
@locales = locales
|
185
|
+
@translations = translations
|
186
|
+
end
|
187
|
+
|
188
|
+
# Short and pretty way to get traslation by method name. If translation
|
189
|
+
# has name of object methods ("methods", "strftime") use <tt>[]</tt> method
|
190
|
+
# to access.
|
191
|
+
#
|
192
|
+
# Translation can contain variable part. Just set is as %1, %2 etc in
|
193
|
+
# translations file and set values as methods params.
|
194
|
+
def method_missing(name, *params)
|
195
|
+
self[name.to_s, *params]
|
196
|
+
end
|
197
|
+
|
198
|
+
# Return traslation with special name.
|
199
|
+
#
|
200
|
+
# Translation can contain variable part. Just set is as %1, %2 etc in
|
201
|
+
# translations file and set values in next arguments.
|
202
|
+
def [](name, *params)
|
203
|
+
@translations.each_with_index do |translation, i|
|
204
|
+
result = translation[name]
|
205
|
+
next if result.nil?
|
206
|
+
|
207
|
+
if YAML::PrivateType == result.class
|
208
|
+
case result.type_id
|
209
|
+
when "proc"
|
210
|
+
return eval("proc {#{result.value}}").call(*params)
|
211
|
+
when "pl"
|
212
|
+
pluralizator = @locales[i]
|
213
|
+
pluralizator = self.class if Locale != pluralizator.class
|
214
|
+
|
215
|
+
params.each do |param|
|
216
|
+
type = pluralizator.pluralize(param)
|
217
|
+
type = "n" if not result.value.include? type
|
218
|
+
result = result.value[type]
|
219
|
+
break if YAML::PrivateType != result.class
|
220
|
+
end
|
221
|
+
else
|
222
|
+
return result
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
if String == result.class
|
227
|
+
params.each_with_index do |param, i|
|
228
|
+
result.gsub! "%#{i+1}", param.to_s
|
229
|
+
end
|
230
|
+
return TranslatedString.new(result, @locales[i])
|
231
|
+
elsif Hash == result.class
|
232
|
+
return self.class.new(@locales, @translations.map { |i|
|
233
|
+
i[name] or {}
|
234
|
+
})
|
235
|
+
else
|
236
|
+
return result
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
return nil
|
241
|
+
end
|
242
|
+
|
243
|
+
# Format +time+ according to the directives in the given format string and
|
244
|
+
# translate month, week days and meridian indicator (AM/PM) names (%A, %a,
|
245
|
+
# %B, %b, %p directives).
|
246
|
+
#
|
247
|
+
# See <tt>Time.strftime()</tt> method docs for info about all directives.
|
248
|
+
def strftime(time, format)
|
249
|
+
translated = ""
|
250
|
+
format.scan(/%[EO]?.|./o) do |c|
|
251
|
+
case c.sub(/^%[EO]?(.)$/o, "%\\1")
|
252
|
+
when "%A"
|
253
|
+
translated << self.week.days[time.wday - 1]
|
254
|
+
when "%a"
|
255
|
+
translated << self.week.abbr_days[time.wday - 1]
|
256
|
+
when "%B"
|
257
|
+
translated << self.months.names[time.month - 1]
|
258
|
+
when "%b"
|
259
|
+
translated << self.months.abbr_names[time.month - 1]
|
260
|
+
when "%p"
|
261
|
+
translated << if time.hour < 12 then self.am else self.pm end
|
262
|
+
else
|
263
|
+
translated << c
|
264
|
+
end
|
265
|
+
end
|
266
|
+
time.strftime(translated)
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|
data/lib/rubi18n.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
=begin
|
2
|
+
Main file to load all neccessary classes for i18n support.
|
3
|
+
|
4
|
+
Copyright (C) 2008 Andrey “A.I.” Sitnik <andrey@sitnik.ru>
|
5
|
+
|
6
|
+
This program is free software: you can redistribute it and/or modify
|
7
|
+
it under the terms of the GNU Lesser General Public License as published by
|
8
|
+
the Free Software Foundation, either version 3 of the License, or
|
9
|
+
(at your option) any later version.
|
10
|
+
|
11
|
+
This program is distributed in the hope that it will be useful,
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
GNU Lesser General Public License for more details.
|
15
|
+
|
16
|
+
You should have received a copy of the GNU Lesser General Public License
|
17
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
18
|
+
=end
|
19
|
+
|
20
|
+
require "pathname"
|
21
|
+
|
22
|
+
$KCODE = "u"
|
23
|
+
|
24
|
+
dir = Pathname(__FILE__).dirname.expand_path + "rubi18n"
|
25
|
+
|
26
|
+
require dir + "locale"
|
27
|
+
require dir + "translation"
|
28
|
+
require dir + "translated_string"
|
29
|
+
require dir + "formatters"
|
data/locales/en.yml
ADDED
data/locales/en_US.yml
ADDED
data/locales/ru.yml
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
title: Русский
|
2
|
+
code: ru
|
3
|
+
sublocales: [en]
|
4
|
+
direction: ltr
|
5
|
+
|
6
|
+
pluralization: "n==0 ? 0 : n%10==1 && n%100!=11 ? 1 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 2 : 'n'"
|
7
|
+
|
8
|
+
week_start: monday
|
9
|
+
|
10
|
+
numbers:
|
11
|
+
separation: classic
|
12
|
+
decimal_separator: ","
|
13
|
+
group_delimiter: " "
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
2
|
+
|
3
|
+
describe Rubi18n::Formatters do
|
4
|
+
|
5
|
+
it "should format number in local traditions" do
|
6
|
+
Rubi18n::Locale.current = "en"
|
7
|
+
-123456789.to_ls.should == "−123,456,789"
|
8
|
+
|
9
|
+
-123456789.to_ls(Rubi18n::Locale.new("ru")).should == "−123 456 789"
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should format float in local traditions" do
|
13
|
+
Rubi18n::Locale.current = "en"
|
14
|
+
-12345.67.to_ls.should == "−12,345.67"
|
15
|
+
|
16
|
+
-12345.67.to_ls(Rubi18n::Locale.new("ru")).should == "−12 345,67"
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
data/spec/locale_spec.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
2
|
+
|
3
|
+
describe Rubi18n::Locale do
|
4
|
+
|
5
|
+
it "should check is locale exists" do
|
6
|
+
Rubi18n::Locale.exists?("ru").should be_true
|
7
|
+
Rubi18n::Locale.exists?("no_LC").should be_false
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should load locale" do
|
11
|
+
locale = Rubi18n::Locale.new "ru"
|
12
|
+
locale["code"].should == "ru"
|
13
|
+
locale["title"].should == "Русский"
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should include locale by 'include' option" do
|
17
|
+
en_US = Rubi18n::Locale.new "en_US"
|
18
|
+
en = Rubi18n::Locale.new "en"
|
19
|
+
en_US["title"].should == "English (US)"
|
20
|
+
en["title"].should == "English"
|
21
|
+
en_US["week"].should == en["week"]
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should raise error if locale isn't exists" do
|
25
|
+
lambda {
|
26
|
+
Rubi18n::Locale.new "no_LC"
|
27
|
+
}.should raise_error
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should be equal to another locale with same code" do
|
31
|
+
ru = Rubi18n::Locale.new "ru"
|
32
|
+
en = Rubi18n::Locale.new "en"
|
33
|
+
another = Rubi18n::Locale.new "en"
|
34
|
+
en.should_not == ru
|
35
|
+
en.should == another
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should print human readable representation" do
|
39
|
+
Rubi18n::Locale.new("ru").inspect.should == "Locale ru (Русский)"
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should has current locale to use in +to_ls+ methods" do
|
43
|
+
en = Rubi18n::Locale.new "en"
|
44
|
+
Rubi18n::Locale.current = en
|
45
|
+
Rubi18n::Locale.current.should == en
|
46
|
+
Rubi18n::Locale.current = "en"
|
47
|
+
Rubi18n::Locale.current.should == en
|
48
|
+
Rubi18n::Locale.current = "ru"
|
49
|
+
Rubi18n::Locale.current.should_not == en
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should return all available locales" do
|
53
|
+
Rubi18n::Locale.locales.sort.should == ["en", "en_US", "ru"]
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should load first available locale" do
|
57
|
+
Rubi18n::Locale.find(["no_LC", "en", "ru"])["code"].should == "en"
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should find a short name of locale" do
|
61
|
+
Rubi18n::Locale.find("ru_RU.UTF-8")["code"].should == "ru"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should return pluralization type by elements count" do
|
65
|
+
locale = Rubi18n::Locale.new "en"
|
66
|
+
locale.pluralize(0).should == 0
|
67
|
+
locale.pluralize(1).should == 1
|
68
|
+
locale.pluralize(:n).should == 'n'
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
2
|
+
|
3
|
+
describe Rubi18n::Translation do
|
4
|
+
DIR = File.join(File.dirname(__FILE__), "translations", "general")
|
5
|
+
EXT = File.join(File.dirname(__FILE__), "translations", "extention")
|
6
|
+
|
7
|
+
it "should return all available translations" do
|
8
|
+
Rubi18n::Translation.available(DIR).sort.should == ["en", "fr", "no_LC", "ru"]
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should has default locale to use when there aren't any user locales" do
|
12
|
+
Rubi18n::Translation.default = "en"
|
13
|
+
Rubi18n::Translation.default.should == "en"
|
14
|
+
Rubi18n::Translation.load("no_TR", DIR).one.should == "One"
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should load translations" do
|
18
|
+
translation = Rubi18n::Translation.load("en", DIR)
|
19
|
+
translation.one.should == "One"
|
20
|
+
translation["one"].should == "One"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should find in subtranslations" do
|
24
|
+
translation = Rubi18n::Translation.load(["fr", "ru"], DIR)
|
25
|
+
translation.one.should == "Un"
|
26
|
+
translation.two.should == "Два"
|
27
|
+
translation.three.should == "Three"
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should return nil if translation isn't found" do
|
31
|
+
translation = Rubi18n::Translation.load("en", DIR)
|
32
|
+
translation.without_translation.should be_nil
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should search language locale for dialect" do
|
36
|
+
translation = Rubi18n::Translation.load("fr_CA", DIR)
|
37
|
+
translation.one.should == "Un"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should can use params in translation" do
|
41
|
+
translation = Rubi18n::Translation.load("en", DIR)
|
42
|
+
translation.params(1, 2).should == "Is 1 between 1 and 2?"
|
43
|
+
translation["params", 1, 2].should == "Is 1 between 1 and 2?"
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should load use hierarchical translations" do
|
47
|
+
translation = Rubi18n::Translation.load(["ru", "en"], DIR)
|
48
|
+
translation.in.another.should == "Иерархический"
|
49
|
+
translation["in"]["another"].should == "Иерархический"
|
50
|
+
translation.only.english.should == "Only in English"
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should return string with locale info" do
|
54
|
+
translation = Rubi18n::Translation.load(["fr", "ru"], DIR)
|
55
|
+
translation.one.locale.should == "fr"
|
56
|
+
translation.two.locale.should == Rubi18n::Locale.new("ru")
|
57
|
+
translation.three.locale.should == Rubi18n::Locale.new("en")
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should use extention translations" do
|
61
|
+
Rubi18n::Translation.extension_translations << EXT
|
62
|
+
|
63
|
+
translation = Rubi18n::Translation.load("en", DIR)
|
64
|
+
translation.ext.should == "Extention"
|
65
|
+
translation.one.should == "One"
|
66
|
+
end
|
67
|
+
|
68
|
+
it "shouldn't use extention without app translations with same locale" do
|
69
|
+
Rubi18n::Translation.extension_translations << EXT
|
70
|
+
|
71
|
+
translation = Rubi18n::Translation.load(["no_TR", "en"], DIR)
|
72
|
+
translation.ext.should == "Extention"
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should translate month, week days and am/pm names in strftime" do
|
76
|
+
translation = Rubi18n::Translation.load("ru", DIR)
|
77
|
+
|
78
|
+
time = Time.at(0).utc
|
79
|
+
translation.strftime(time, "%a %A").should == 'Срд Среда'
|
80
|
+
translation.strftime(time, "%b %B").should == 'Янв Январь'
|
81
|
+
translation.strftime(time, "%H:%M%p").should == '00:00AM'
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should call proc in translation" do
|
85
|
+
translation = Rubi18n::Translation.load("en", DIR)
|
86
|
+
translation.sum(2, 3).should == 5
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should pluralize translation" do
|
90
|
+
translation = Rubi18n::Translation.load("en", DIR)
|
91
|
+
translation.comments(0, "article").should == "no comments for article"
|
92
|
+
translation.comments(1, "article").should == "one comment for article"
|
93
|
+
translation.comments(5, "article").should == "5 comments for article"
|
94
|
+
|
95
|
+
translation.files(0).should == "0 files"
|
96
|
+
|
97
|
+
translation.authors(1, 4).should == "One author with many comments"
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should pluralize translation without locale" do
|
101
|
+
translation = Rubi18n::Translation.load("no_LC", DIR)
|
102
|
+
translation.entries(1).should == "ONE"
|
103
|
+
translation.entries(5).should == "N"
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
ext: NO
|
@@ -0,0 +1,31 @@
|
|
1
|
+
one: One
|
2
|
+
two: Two
|
3
|
+
three: Three
|
4
|
+
|
5
|
+
params: Is %1 between %1 and %2?
|
6
|
+
|
7
|
+
in:
|
8
|
+
another: Hierarchical
|
9
|
+
|
10
|
+
only:
|
11
|
+
english: Only in English
|
12
|
+
|
13
|
+
sum: !!proc |x, y| x + y
|
14
|
+
|
15
|
+
comments: !!pl
|
16
|
+
0: no comments for %2
|
17
|
+
1: one comment for %2
|
18
|
+
n: %1 comments for %2
|
19
|
+
|
20
|
+
files: !!pl
|
21
|
+
1: 1 file
|
22
|
+
n: %1 files
|
23
|
+
|
24
|
+
authors: !!pl
|
25
|
+
0: No authors
|
26
|
+
1: !!pl
|
27
|
+
1: One author with one comment
|
28
|
+
n: One author with many comments
|
29
|
+
n: !!pl
|
30
|
+
1: Many authors with one comment
|
31
|
+
n: Many authors with many comments
|
@@ -0,0 +1 @@
|
|
1
|
+
one: Un
|