fast_gettext 0.4.16
Sign up to get free protection for your applications and to get access to all the features.
- 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
|