fast_gettext 0.4.16
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/.gitignore +2 -0
- data/CHANGELOG +6 -0
- data/README.markdown +181 -0
- data/Rakefile +42 -0
- data/VERSION +1 -0
- data/benchmark/base.rb +42 -0
- data/benchmark/baseline.rb +5 -0
- data/benchmark/fast_gettext.rb +18 -0
- data/benchmark/i18n_simple.rb +7 -0
- data/benchmark/ideal.rb +22 -0
- data/benchmark/locale/de.yml +127 -0
- data/benchmark/locale/de/LC_MESSAGES/large.mo +0 -0
- data/benchmark/misc/threadsave.rb +21 -0
- data/benchmark/namespace/fast_gettext.rb +15 -0
- data/benchmark/namespace/original.rb +14 -0
- data/benchmark/original.rb +15 -0
- data/examples/db/migration.rb +22 -0
- data/examples/missing_translation_logger.rb +13 -0
- data/fast_gettext.gemspec +114 -0
- data/lib/fast_gettext.rb +30 -0
- data/lib/fast_gettext/mo_file.rb +67 -0
- data/lib/fast_gettext/po_file.rb +14 -0
- data/lib/fast_gettext/storage.rb +188 -0
- data/lib/fast_gettext/translation.rb +53 -0
- data/lib/fast_gettext/translation_repository.rb +15 -0
- data/lib/fast_gettext/translation_repository/base.rb +49 -0
- data/lib/fast_gettext/translation_repository/chain.rb +43 -0
- data/lib/fast_gettext/translation_repository/db.rb +57 -0
- data/lib/fast_gettext/translation_repository/db_models/translation_key.rb +26 -0
- data/lib/fast_gettext/translation_repository/db_models/translation_text.rb +9 -0
- data/lib/fast_gettext/translation_repository/logger.rb +27 -0
- data/lib/fast_gettext/translation_repository/mo.rb +35 -0
- data/lib/fast_gettext/translation_repository/po.rb +18 -0
- data/spec/aa_unconfigued_spec.rb +21 -0
- data/spec/fast_gettext/mo_file_spec.rb +36 -0
- data/spec/fast_gettext/storage_spec.rb +309 -0
- data/spec/fast_gettext/translation_repository/base_spec.rb +21 -0
- data/spec/fast_gettext/translation_repository/chain_spec.rb +82 -0
- data/spec/fast_gettext/translation_repository/db_spec.rb +71 -0
- data/spec/fast_gettext/translation_repository/logger_spec.rb +41 -0
- data/spec/fast_gettext/translation_repository/mo_spec.rb +31 -0
- data/spec/fast_gettext/translation_repository/po_spec.rb +31 -0
- data/spec/fast_gettext/translation_spec.rb +152 -0
- data/spec/fast_gettext_spec.rb +44 -0
- data/spec/locale/de/LC_MESSAGES/test.mo +0 -0
- data/spec/locale/de/test.po +61 -0
- data/spec/locale/en/LC_MESSAGES/plural_test.mo +0 -0
- data/spec/locale/en/LC_MESSAGES/test.mo +0 -0
- data/spec/locale/en/plural_test.po +20 -0
- data/spec/locale/en/test.po +59 -0
- data/spec/spec_helper.rb +26 -0
- data/spec/vendor/fake_load_path/iconv.rb +2 -0
- data/spec/vendor/iconv_spec.rb +27 -0
- data/spec/vendor/string_spec.rb +67 -0
- data/vendor/README.rdoc +236 -0
- data/vendor/empty.mo +0 -0
- data/vendor/iconv.rb +107 -0
- data/vendor/mofile.rb +296 -0
- data/vendor/poparser.rb +331 -0
- data/vendor/string.rb +58 -0
- metadata +130 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
module FastGettext
|
2
|
+
# this module should be included
|
3
|
+
# Responsibility:
|
4
|
+
# - direct translation queries to the current repository
|
5
|
+
# - handle untranslated values
|
6
|
+
# - understand / enforce namespaces
|
7
|
+
# - decide which plural form is used
|
8
|
+
module Translation
|
9
|
+
extend self
|
10
|
+
|
11
|
+
#make it usable in class definition, e.g.
|
12
|
+
# class Y
|
13
|
+
# include FastGettext::Translation
|
14
|
+
# @@x = _('y')
|
15
|
+
# end
|
16
|
+
def self.included(klas) #:nodoc:
|
17
|
+
klas.extend self
|
18
|
+
end
|
19
|
+
|
20
|
+
def _(key)
|
21
|
+
FastGettext.cached_find(key) or key
|
22
|
+
end
|
23
|
+
|
24
|
+
#translate pluralized
|
25
|
+
# some languages have up to 4 plural forms...
|
26
|
+
# n_(singular, plural, plural form 2, ..., count)
|
27
|
+
# n_('apple','apples',3)
|
28
|
+
def n_(*keys)
|
29
|
+
count = keys.pop
|
30
|
+
translations = FastGettext.cached_plural_find *keys
|
31
|
+
selected = FastGettext.pluralisation_rule.call(count)
|
32
|
+
selected = selected ? 1 : 0 unless selected.is_a? Numeric #convert booleans to numbers
|
33
|
+
translations[selected] || keys[selected] || keys.last
|
34
|
+
end
|
35
|
+
|
36
|
+
#translate, but discard namespace if nothing was found
|
37
|
+
# Car|Tire -> Tire if no translation could be found
|
38
|
+
def s_(key,seperator=nil)
|
39
|
+
translation = FastGettext.cached_find(key) and return translation
|
40
|
+
key.split(seperator||NAMESPACE_SEPERATOR).last
|
41
|
+
end
|
42
|
+
|
43
|
+
#tell gettext: this string need translation (will be found during parsing)
|
44
|
+
def N_(translate)
|
45
|
+
translate
|
46
|
+
end
|
47
|
+
|
48
|
+
#tell gettext: this string need translation (will be found during parsing)
|
49
|
+
def Nn_(*keys)
|
50
|
+
keys
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module FastGettext
|
2
|
+
# Responsibility:
|
3
|
+
# - decide which repository to choose from given input
|
4
|
+
module TranslationRepository
|
5
|
+
extend self
|
6
|
+
|
7
|
+
# only single-word types supported atm (mytype works, MyType will not)
|
8
|
+
def build(name,options)
|
9
|
+
type = options[:type] || :mo
|
10
|
+
require "fast_gettext/translation_repository/#{type}"
|
11
|
+
klas = eval(type.to_s.capitalize)
|
12
|
+
klas.new(name,options)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module FastGettext
|
2
|
+
module TranslationRepository
|
3
|
+
# Responsibility:
|
4
|
+
# - base for all repositories
|
5
|
+
# - fallback as empty repository, that cannot translate anything but does not crash
|
6
|
+
class Base
|
7
|
+
def initialize(name,options={})
|
8
|
+
@name = name
|
9
|
+
@options = options
|
10
|
+
end
|
11
|
+
|
12
|
+
def pluralisation_rule
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def available_locales
|
17
|
+
[]
|
18
|
+
end
|
19
|
+
|
20
|
+
def [](key)
|
21
|
+
current_translations[key]
|
22
|
+
end
|
23
|
+
|
24
|
+
def plural(*keys)
|
25
|
+
current_translations.plural(*keys)
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def current_translations
|
31
|
+
MoFile.empty
|
32
|
+
end
|
33
|
+
|
34
|
+
def find_files_in_locale_folders(relative_file_path,path)
|
35
|
+
path ||= "locale"
|
36
|
+
raise "path #{path} cound not be found!" unless File.exist?(path)
|
37
|
+
|
38
|
+
@files = {}
|
39
|
+
Dir[File.join(path,'*')].each do |locale_folder|
|
40
|
+
next unless File.basename(locale_folder) =~ LOCALE_REX
|
41
|
+
file = File.join(locale_folder,relative_file_path)
|
42
|
+
next unless File.exist? file
|
43
|
+
locale = File.basename(locale_folder)
|
44
|
+
@files[locale] = yield(locale,file)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'fast_gettext/translation_repository/base'
|
2
|
+
|
3
|
+
module FastGettext
|
4
|
+
module TranslationRepository
|
5
|
+
# Responsibility:
|
6
|
+
# - delegate calls to members of the chain in turn
|
7
|
+
#TODO cache should be expired after a repo was added
|
8
|
+
class Chain < Base
|
9
|
+
attr_accessor :chain
|
10
|
+
|
11
|
+
def initialize(name,options={})
|
12
|
+
super
|
13
|
+
self.chain = options[:chain]
|
14
|
+
end
|
15
|
+
|
16
|
+
def available_locales
|
17
|
+
chain.map{|c|c.available_locales}.flatten.uniq
|
18
|
+
end
|
19
|
+
|
20
|
+
def pluralisation_rule
|
21
|
+
chain.each do |c|
|
22
|
+
result = c.pluralisation_rule and return result
|
23
|
+
end
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def [](key)
|
28
|
+
chain.each do |c|
|
29
|
+
result = c[key] and return result
|
30
|
+
end
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
|
34
|
+
def plural(*keys)
|
35
|
+
chain.each do |c|
|
36
|
+
result = c.plural(*keys)
|
37
|
+
return result unless result.compact.empty?
|
38
|
+
end
|
39
|
+
[]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
module FastGettext
|
3
|
+
module TranslationRepository
|
4
|
+
# Responsibility:
|
5
|
+
# - provide access to translations in database through a database abstraction
|
6
|
+
#
|
7
|
+
# Options:
|
8
|
+
# :model => Model that represents your keys
|
9
|
+
# you can either use the models supplied under db/, extend them or build your own
|
10
|
+
# only constraints:
|
11
|
+
# key: find_by_key, translations
|
12
|
+
# translation: text, locale
|
13
|
+
class Db
|
14
|
+
def initialize(name,options={})
|
15
|
+
@model = options[:model]
|
16
|
+
end
|
17
|
+
|
18
|
+
@@seperator = '||||' # string that seperates multiple plurals
|
19
|
+
def self.seperator=(sep);@@seperator = sep;end
|
20
|
+
def self.seperator;@@seperator;end
|
21
|
+
|
22
|
+
def available_locales
|
23
|
+
if @model.respond_to? :available_locales
|
24
|
+
@model.available_locales || []
|
25
|
+
else
|
26
|
+
[]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def pluralisation_rule
|
31
|
+
if @model.respond_to? :pluralsation_rule
|
32
|
+
@model.pluralsation_rule
|
33
|
+
else
|
34
|
+
nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def [](key)
|
39
|
+
@model.translation(key, FastGettext.locale)
|
40
|
+
end
|
41
|
+
|
42
|
+
def plural(*args)
|
43
|
+
if translation = @model.translation(args*self.class.seperator, FastGettext.locale)
|
44
|
+
translation.to_s.split(self.class.seperator)
|
45
|
+
else
|
46
|
+
[]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.require_models
|
51
|
+
require 'fast_gettext/translation_repository/db_models/translation_key'
|
52
|
+
require 'fast_gettext/translation_repository/db_models/translation_text'
|
53
|
+
FastGettext::TranslationRepository::DbModels
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module FastGettext::TranslationRepository
|
2
|
+
module DbModels
|
3
|
+
class TranslationKey < ActiveRecord::Base
|
4
|
+
has_many :translations, :class_name=>'TranslationText'
|
5
|
+
accepts_nested_attributes_for :translations, :allow_destroy => true
|
6
|
+
|
7
|
+
validates_uniqueness_of :key
|
8
|
+
validates_presence_of :key
|
9
|
+
|
10
|
+
def self.translation(key, locale)
|
11
|
+
return unless translation_key = find_by_key(key)
|
12
|
+
return unless translation_text = translation_key.translations.find_by_locale(locale)
|
13
|
+
translation_text.text
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.available_locales
|
17
|
+
@@available_locales ||= TranslationText.count(:group=>:locale).keys.sort
|
18
|
+
end
|
19
|
+
|
20
|
+
#this is only for ActiveSupport to get polymorphic_url FastGettext::... namespace free
|
21
|
+
def self.model_name
|
22
|
+
ActiveSupport::ModelName.new('TranslationKey')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module FastGettext::TranslationRepository
|
2
|
+
module DbModels
|
3
|
+
class TranslationText < ActiveRecord::Base
|
4
|
+
belongs_to :key, :class_name=>'TranslationKey'
|
5
|
+
validates_presence_of :locale
|
6
|
+
validates_uniqueness_of :locale, :scope=>:translation_key_id
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'fast_gettext/translation_repository/base'
|
2
|
+
|
3
|
+
module FastGettext
|
4
|
+
module TranslationRepository
|
5
|
+
# This should be used in a TranslationRepository::Chain, so tat untranslated keys can be found
|
6
|
+
# Responsibility:
|
7
|
+
# - log every translation call
|
8
|
+
class Logger < Base
|
9
|
+
attr_accessor :callback
|
10
|
+
|
11
|
+
def initialize(name,options={})
|
12
|
+
super
|
13
|
+
self.callback = options[:callback]
|
14
|
+
end
|
15
|
+
|
16
|
+
def [](key)
|
17
|
+
callback.call(key)
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def plural(*keys)
|
22
|
+
callback.call(keys)
|
23
|
+
[]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'fast_gettext/translation_repository/base'
|
2
|
+
module FastGettext
|
3
|
+
module TranslationRepository
|
4
|
+
# Responsibility:
|
5
|
+
# - find and store mo files
|
6
|
+
# - provide access to translations in mo files
|
7
|
+
class Mo < Base
|
8
|
+
def initialize(name,options={})
|
9
|
+
find_and_store_files(name,options)
|
10
|
+
super
|
11
|
+
end
|
12
|
+
|
13
|
+
def available_locales
|
14
|
+
@files.keys
|
15
|
+
end
|
16
|
+
|
17
|
+
def pluralisation_rule
|
18
|
+
current_translations.pluralisation_rule
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def find_and_store_files(name,options)
|
24
|
+
# parse all .mo files with the right name, that sit in locale/LC_MESSAGES folders
|
25
|
+
find_files_in_locale_folders(File.join('LC_MESSAGES',"#{name}.mo"),options[:path]) do |locale,file|
|
26
|
+
@files[locale] = MoFile.new(file)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def current_translations
|
31
|
+
@files[FastGettext.locale] || MoFile.empty
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'fast_gettext/translation_repository/base'
|
2
|
+
require 'fast_gettext/translation_repository/mo'
|
3
|
+
module FastGettext
|
4
|
+
module TranslationRepository
|
5
|
+
# Responsibility:
|
6
|
+
# - find and store po files
|
7
|
+
# - provide access to translations in po files
|
8
|
+
class Po < Mo
|
9
|
+
protected
|
10
|
+
def find_and_store_files(name,options)
|
11
|
+
require 'fast_gettext/po_file'
|
12
|
+
find_files_in_locale_folders("#{name}.po",options[:path]) do |locale,file|
|
13
|
+
@files[locale] = PoFile.to_mo_file(file)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__),'spec_helper')
|
2
|
+
|
3
|
+
describe 'unconfigured' do
|
4
|
+
it "gives a useful error message when trying to just translate" do
|
5
|
+
FastGettext.text_domain = nil
|
6
|
+
begin
|
7
|
+
FastGettext._('x')
|
8
|
+
"".should == "success!?"
|
9
|
+
rescue FastGettext::Storage::NoTextDomainConfigured
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
it "gives a useful error message when only locale was set" do
|
14
|
+
FastGettext.locale = 'de'
|
15
|
+
begin
|
16
|
+
FastGettext._('x')
|
17
|
+
"".should == "success!?"
|
18
|
+
rescue FastGettext::Storage::NoTextDomainConfigured
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
current_folder = File.dirname(__FILE__)
|
2
|
+
require File.join(current_folder,'..','spec_helper')
|
3
|
+
|
4
|
+
include FastGettext
|
5
|
+
de_file = File.join(current_folder,'..','locale','de','LC_MESSAGES','test.mo')
|
6
|
+
de = MoFile.new(de_file)
|
7
|
+
|
8
|
+
describe MoFile do
|
9
|
+
before :all do
|
10
|
+
File.exist?(de_file).should == true
|
11
|
+
end
|
12
|
+
|
13
|
+
it "parses a file" do
|
14
|
+
de['car'].should == 'Auto'
|
15
|
+
end
|
16
|
+
|
17
|
+
it "stores untranslated values as nil" do
|
18
|
+
de['Car|Model'].should == nil
|
19
|
+
end
|
20
|
+
|
21
|
+
it "finds pluralized values" do
|
22
|
+
de.plural('Axis','Axis').should == ['Achse','Achsen']
|
23
|
+
end
|
24
|
+
|
25
|
+
it "returns singular translations when pluralisation could not be found" do
|
26
|
+
de.plural('Axis','Axis','Axis').should == ['Achse','Achse','Achse']
|
27
|
+
end
|
28
|
+
|
29
|
+
it "returns ids when not plural and singular translations could not be found" do
|
30
|
+
de.plural('Axis','Axis','NOTFOUND').should == ['Achse','Achse','NOTFOUND']
|
31
|
+
end
|
32
|
+
|
33
|
+
it "can access plurals through []" do
|
34
|
+
de['Axis'].should == 'Achse' #singular
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,309 @@
|
|
1
|
+
current_folder = File.dirname(__FILE__)
|
2
|
+
require File.join(current_folder,'..','spec_helper')
|
3
|
+
|
4
|
+
include FastGettext::Storage
|
5
|
+
|
6
|
+
describe 'Storage' do
|
7
|
+
before do
|
8
|
+
#reset everything to nil
|
9
|
+
self.available_locales = nil
|
10
|
+
self.default_text_domain = nil
|
11
|
+
self.default_locale = nil
|
12
|
+
send(:_locale=,nil)#nil is not allowed to be set...
|
13
|
+
default_locale.should be_nil
|
14
|
+
available_locales.should be_nil
|
15
|
+
locale.should == 'en'
|
16
|
+
end
|
17
|
+
|
18
|
+
def thread_save(method, value)
|
19
|
+
send("#{method}=",value)
|
20
|
+
|
21
|
+
# mess around with other threads
|
22
|
+
100.times do
|
23
|
+
Thread.new {FastGettext.send("#{method}=",'en')}
|
24
|
+
end
|
25
|
+
|
26
|
+
send(method) == value
|
27
|
+
end
|
28
|
+
|
29
|
+
{:locale=>'de', :available_locales=>['de'], :text_domain=>'xx', :pluralisation_rule=>lambda{|x|x==4}}.each do |method, value|
|
30
|
+
it "stores #{method} thread-save" do
|
31
|
+
thread_save(method, value).should == true
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
it "stores translation_repositories non-thread-safe" do
|
36
|
+
self.translation_repositories[:x]=1
|
37
|
+
t = Thread.new{self.translation_repositories[:x]=2}
|
38
|
+
t.join
|
39
|
+
self.translation_repositories[:x].should == 2
|
40
|
+
end
|
41
|
+
|
42
|
+
describe :pluralisation_rule do
|
43
|
+
it "defaults to singular-if-1 when it is not set" do
|
44
|
+
stub!(:current_repository).and_return mock('',:pluralisation_rule=>nil)
|
45
|
+
self.pluralisation_rule = nil
|
46
|
+
pluralisation_rule.call(1).should == false
|
47
|
+
pluralisation_rule.call(0).should == true
|
48
|
+
pluralisation_rule.call(2).should == true
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe :default_locale do
|
53
|
+
it "stores default_locale non-thread-safe" do
|
54
|
+
thread_save(:default_locale, 'de').should == false
|
55
|
+
end
|
56
|
+
|
57
|
+
it "does not overwrite locale" do
|
58
|
+
self.locale = 'de'
|
59
|
+
self.default_locale = 'yy'
|
60
|
+
self.locale.should == 'de'
|
61
|
+
end
|
62
|
+
|
63
|
+
it "falls back to default if locale is missing" do
|
64
|
+
self.default_locale = 'yy'
|
65
|
+
self.locale.should == 'yy'
|
66
|
+
end
|
67
|
+
|
68
|
+
it "does not set non-available-locales as default" do
|
69
|
+
self.available_locales = ['xx']
|
70
|
+
self.default_locale = 'yy'
|
71
|
+
self.default_locale.should == nil
|
72
|
+
end
|
73
|
+
|
74
|
+
it "can set default_locale to nil" do
|
75
|
+
self.default_locale = 'xx'
|
76
|
+
self.default_locale = nil
|
77
|
+
default_locale.should be_nil
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe :default_text_domain do
|
82
|
+
it "stores default_text_domain non-thread-safe" do
|
83
|
+
thread_save(:default_text_domain, 'xx').should == false
|
84
|
+
end
|
85
|
+
|
86
|
+
it "uses default_text_domain when text_domain is not set" do
|
87
|
+
self.text_domain = nil
|
88
|
+
self.default_text_domain = 'x'
|
89
|
+
text_domain.should == 'x'
|
90
|
+
end
|
91
|
+
|
92
|
+
it "does not use default when domain is set" do
|
93
|
+
self.text_domain = 'x'
|
94
|
+
self.default_text_domain = 'y'
|
95
|
+
text_domain.should == 'x'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe :default_available_locales do
|
100
|
+
after do
|
101
|
+
self.default_available_locales = nil
|
102
|
+
end
|
103
|
+
|
104
|
+
it "stores default_available_locales non-thread-safe" do
|
105
|
+
thread_save(:default_available_locales, 'xx').should == false
|
106
|
+
end
|
107
|
+
|
108
|
+
it "uses default_available_locales when available_locales is not set" do
|
109
|
+
self.available_locales = nil
|
110
|
+
self.default_available_locales = 'x'
|
111
|
+
available_locales.should == 'x'
|
112
|
+
end
|
113
|
+
|
114
|
+
it "does not use default when available_locales is set" do
|
115
|
+
self.available_locales = 'x'
|
116
|
+
self.default_available_locales = 'y'
|
117
|
+
available_locales.should == 'x'
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe :locale do
|
122
|
+
it "stores everything as long as available_locales is not set" do
|
123
|
+
self.available_locales = nil
|
124
|
+
self.locale = 'XXX'
|
125
|
+
locale.should == 'XXX'
|
126
|
+
end
|
127
|
+
|
128
|
+
it "is en if no locale and no available_locale were set" do
|
129
|
+
FastGettext.send(:_locale=,nil)
|
130
|
+
self.available_locales = nil
|
131
|
+
locale.should == 'en'
|
132
|
+
end
|
133
|
+
|
134
|
+
it "does not change the locale if locales was called with nil" do
|
135
|
+
self.locale = nil
|
136
|
+
locale.should == 'en'
|
137
|
+
end
|
138
|
+
|
139
|
+
it "is the first available_locale if one was set" do
|
140
|
+
self.available_locales = ['de']
|
141
|
+
locale.should == 'de'
|
142
|
+
end
|
143
|
+
|
144
|
+
it "does not store a locale if it is not available" do
|
145
|
+
self.available_locales = ['de']
|
146
|
+
self.locale = 'en'
|
147
|
+
locale.should == 'de'
|
148
|
+
end
|
149
|
+
|
150
|
+
it "set_locale returns the old locale if the new could not be set" do
|
151
|
+
self.locale = 'de'
|
152
|
+
self.available_locales = ['de']
|
153
|
+
self.set_locale('en').should == 'de'
|
154
|
+
end
|
155
|
+
|
156
|
+
{
|
157
|
+
'Opera' => "de-DE,de;q=0.9,en;q=0.8",
|
158
|
+
'Firefox' => "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3",
|
159
|
+
}.each do |browser,accept_language|
|
160
|
+
it "sets the locale from #{browser} headers" do
|
161
|
+
FastGettext.available_locales = ['de_DE','de','xx']
|
162
|
+
FastGettext.locale = 'xx'
|
163
|
+
FastGettext.locale = accept_language
|
164
|
+
FastGettext.locale.should == 'de_DE'
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
it "sets a unimportant locale if it is the only available" do
|
169
|
+
FastGettext.available_locales = ['en','xx']
|
170
|
+
FastGettext.locale = "de-de,de;q=0.8,en-us;q=0.5,en;q=0.3"
|
171
|
+
FastGettext.locale.should == 'en'
|
172
|
+
end
|
173
|
+
|
174
|
+
it "sets the locale with the highest wheight" do
|
175
|
+
FastGettext.available_locales = ['en','de']
|
176
|
+
FastGettext.locale = "xx-us;q=0.5,de-de,de;q=0.8,en;q=0.9"
|
177
|
+
FastGettext.locale.should == 'en'
|
178
|
+
end
|
179
|
+
|
180
|
+
it "sets the locale from languages" do
|
181
|
+
FastGettext.available_locales = ['de']
|
182
|
+
FastGettext.locale = "xx-us;q=0.5,de-de;q=0.8,en-uk;q=0.9"
|
183
|
+
FastGettext.locale.should == 'de'
|
184
|
+
end
|
185
|
+
|
186
|
+
it "sets locale from comma seperated" do
|
187
|
+
FastGettext.available_locales = ['de_DE','en','xx']
|
188
|
+
FastGettext.locale = "de,de-de,en"
|
189
|
+
FastGettext.locale.should == 'de_DE'
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
describe :silence_errors do
|
194
|
+
before do
|
195
|
+
FastGettext.text_domain = 'xxx'
|
196
|
+
end
|
197
|
+
|
198
|
+
it "raises when a textdomain was empty" do
|
199
|
+
begin
|
200
|
+
FastGettext._('x')
|
201
|
+
"".should == "success!?"
|
202
|
+
rescue FastGettext::Storage::NoTextDomainConfigured
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
it "can silence erros" do
|
207
|
+
FastGettext.silence_errors
|
208
|
+
FastGettext._('x').should == 'x'
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
describe :current_cache do
|
213
|
+
before do
|
214
|
+
FastGettext.text_domain = 'xxx'
|
215
|
+
FastGettext.available_locales = ['de','en']
|
216
|
+
FastGettext.locale = 'de'
|
217
|
+
FastGettext.current_repository.stub!(:"[]").with('abc').and_return 'old'
|
218
|
+
FastGettext.current_repository.stub!(:"[]").with('unfound').and_return nil
|
219
|
+
FastGettext._('abc')
|
220
|
+
FastGettext._('unfound')
|
221
|
+
FastGettext.locale = 'en'
|
222
|
+
end
|
223
|
+
|
224
|
+
it "stores a translation seperate by locale" do
|
225
|
+
FastGettext.current_cache['abc'].should == nil
|
226
|
+
end
|
227
|
+
|
228
|
+
it "stores a translation seperate by domain" do
|
229
|
+
FastGettext.locale = 'de'
|
230
|
+
FastGettext.text_domain = nil
|
231
|
+
FastGettext.current_cache['abc'].should == nil
|
232
|
+
end
|
233
|
+
|
234
|
+
it "cache is restored through setting of default_text_domain" do
|
235
|
+
FastGettext.locale = 'de'
|
236
|
+
FastGettext.text_domain = nil
|
237
|
+
FastGettext.default_text_domain = 'xxx'
|
238
|
+
FastGettext.current_cache['abc'].should == 'old'
|
239
|
+
end
|
240
|
+
|
241
|
+
it "cache is restored through setting of default_locale" do
|
242
|
+
FastGettext.send(:_locale=,nil)#reset locale to nil
|
243
|
+
FastGettext.default_locale = 'de'
|
244
|
+
FastGettext.locale.should == 'de'
|
245
|
+
FastGettext.current_cache['abc'].should == 'old'
|
246
|
+
end
|
247
|
+
|
248
|
+
it "stores a translation permanently" do
|
249
|
+
FastGettext.locale = 'de'
|
250
|
+
FastGettext.current_cache['abc'].should == 'old'
|
251
|
+
end
|
252
|
+
|
253
|
+
it "stores a unfound translation permanently" do
|
254
|
+
FastGettext.locale = 'de'
|
255
|
+
FastGettext.current_cache['unfound'].should == false
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
describe :key_exist? do
|
260
|
+
it "does not find default keys" do
|
261
|
+
_('abcde')
|
262
|
+
key_exist?('abcde').should be_false
|
263
|
+
end
|
264
|
+
|
265
|
+
it "finds using the current repository" do
|
266
|
+
should_receive(:current_repository).and_return '1234'=>'1'
|
267
|
+
key_exist?('1234').should == true
|
268
|
+
end
|
269
|
+
|
270
|
+
it "sets the current cache with a found result" do
|
271
|
+
should_receive(:current_repository).and_return 'xxx'=>'1'
|
272
|
+
key_exist?('xxx')
|
273
|
+
current_cache['xxx'].should == '1'
|
274
|
+
end
|
275
|
+
|
276
|
+
it "does not overwrite an existing cache value" do
|
277
|
+
current_cache['xxx']='xxx'
|
278
|
+
stub!(:current_repository).and_return 'xxx'=>'1'
|
279
|
+
key_exist?('xxx')
|
280
|
+
current_cache['xxx'].should == 'xxx'
|
281
|
+
end
|
282
|
+
|
283
|
+
it "is false for gettext meta key" do
|
284
|
+
key_exist?("").should == false
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
describe :cached_find do
|
289
|
+
it "is nil for gettext meta key" do
|
290
|
+
cached_find("").should == false
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
describe NoTextDomainConfigured do
|
295
|
+
it "shows what to do" do
|
296
|
+
NoTextDomainConfigured.new.to_s.should =~ /FastGettext\.add_text_domain/
|
297
|
+
end
|
298
|
+
|
299
|
+
it "warns when text_domain is nil" do
|
300
|
+
FastGettext.text_domain = nil
|
301
|
+
NoTextDomainConfigured.new.to_s.should =~ /\(nil\)/
|
302
|
+
end
|
303
|
+
|
304
|
+
it "shows current text_domain" do
|
305
|
+
FastGettext.text_domain = 'xxx'
|
306
|
+
NoTextDomainConfigured.new('xxx').to_s.should =~ /xxx/
|
307
|
+
end
|
308
|
+
end
|
309
|
+
end
|