grosser-fast_gettext 0.3.8 → 0.4.0

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.
@@ -105,6 +105,26 @@ is sufficient and no more `text_domain=` is needed
105
105
  ###default_locale
106
106
  If the simple rule of "first `availble_locale` or 'en'" is not suficcient for you, simply set `FastGettext.default_locale = 'de'`.
107
107
 
108
+ ###Chains
109
+ You can use any number of repositories to find a translation. Simply add them to a chain and when
110
+ the first cannot translate a given key, the next is asked and so forth.
111
+ repos = [
112
+ FastGettext::TranslationRepository.build('old', :path=>'....'),
113
+ FastGettext::TranslationRepository.build('new', :path=>'....')
114
+ ]
115
+ FastGettext.add_text_domain 'combined', :type=>:chain, :chain=>repos
116
+
117
+ #Logger
118
+ When you want to know which keys could not be translated, or where used, add a Logger to a Chain:
119
+ repos = [
120
+ FastGettext::TranslationRepository.build('app', :path=>'....')
121
+ FastGettext::TranslationRepository.build('logger', :type=>:logger, :callback=>lamda{|msgid_or_array_of_ids| ... }),
122
+ }
123
+ FastGettext.add_text_domain 'combined', :type=>:chain, :chain=>repos
124
+ If the Logger is in position #1 it will see all translations, if it is in position #2 it will only see the unfound.
125
+ Unfound may not always mean missing, if you chose not to translate a word because the msgid is a good translation, it will appear nevertheless.
126
+ A lambda or anything that responds to `call` will do as callback.
127
+
108
128
  ###Plugins
109
129
  Want a yml, xml, database version ?
110
130
  Write your own TranslationRepository!
@@ -112,7 +132,8 @@ Write your own TranslationRepository!
112
132
  module FastGettext
113
133
  module TranslationRepository
114
134
  class Wtf
115
- define initialize(name,options), available_locales, [key], plural(*msgids)
135
+ define initialize(name,options), [key], plural(*msgids) and
136
+ either inherit from Base or define available_locales and pluralisation rule
116
137
  end
117
138
  end
118
139
  end
@@ -0,0 +1,32 @@
1
+ desc "Run all specs in spec directory"
2
+ task :default do |t|
3
+ options = "--colour --format progress --loadby --reverse"
4
+ files = FileList['spec/**/*_spec.rb']
5
+ system("spec #{options} #{files}")
6
+ end
7
+
8
+ task :benchmark do
9
+ %w[baseline ideal fast_gettext original i18n_simple].each do |bench|
10
+ puts `ruby benchmark/#{bench}.rb`
11
+ puts ""
12
+ end
13
+ end
14
+
15
+ task :namespaces do
16
+ puts `ruby benchmark/namespace/original.rb`
17
+ puts `ruby benchmark/namespace/fast_gettext.rb`
18
+ end
19
+
20
+ begin
21
+ require 'jeweler'
22
+ Jeweler::Tasks.new do |gem|
23
+ gem.name = "fast_gettext"
24
+ gem.summary = "A simple, fast and threadsafe implementation of GetText"
25
+ gem.email = "grosser.michael@gmail.com"
26
+ gem.homepage = "http://github.com/grosser/fast_gettext"
27
+ gem.authors = ["Michael Grosser"]
28
+ gem.files += (FileList["{vendor,lib,spec}/**/*"] + FileList["VERSION.yml"] + FileList["README.markdown"]).to_a.sort
29
+ end
30
+ rescue LoadError
31
+ puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
32
+ end
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :major: 0
3
- :minor: 3
4
- :patch: 8
3
+ :minor: 4
4
+ :patch: 0
@@ -0,0 +1,13 @@
1
+ class MissingTranslationLogger
2
+ def call(unfound)
3
+ logger.warn "#{FastGettext.locale}: #{unfound}" unless FastGettext.locale == 'en'
4
+ end
5
+
6
+ private
7
+
8
+ def logger
9
+ return @logger if @logger
10
+ require 'logger'
11
+ @logger = Logger.new("log/unfound_translations", 2, 5*(1024**2))#max 2x 5mb logfile
12
+ end
13
+ end
@@ -10,7 +10,7 @@ module FastGettext
10
10
  end
11
11
  end
12
12
 
13
- [:available_locales, :_locale, :text_domain].each do |method_name|
13
+ [:available_locales, :_locale, :text_domain, :pluralisation_rule].each do |method_name|
14
14
  key = "fast_gettext_#{method_name}".to_sym
15
15
  define_method method_name do
16
16
  Thread.current[key]
@@ -27,6 +27,10 @@ module FastGettext
27
27
  Thread.current[:fast_gettext_text_domain] || default_text_domain
28
28
  end
29
29
 
30
+ def pluralisation_rule
31
+ Thread.current[:fast_gettext_pluralisation_rule] || current_repository.pluralisation_rule || lambda{|i| i!=1}
32
+ end
33
+
30
34
  def current_cache
31
35
  Thread.current[:fast_gettext_current_cache] || {}
32
36
  end
@@ -28,9 +28,10 @@ module FastGettext
28
28
  # n_('apple','apples',3)
29
29
  def n_(*msgids)
30
30
  count = msgids.pop
31
-
32
- translations = FastGettext.current_repository.plural(*msgids)
33
- selected = FastGettext.current_repository.pluralisation_rule.call(count)
31
+ repo = FastGettext.current_repository
32
+
33
+ translations = repo.plural(*msgids)
34
+ selected = FastGettext.pluralisation_rule.call(count)
34
35
  selected = selected ? 1 : 0 unless selected.is_a? Numeric #convert booleans to numbers
35
36
  translations[selected] || msgids[selected] || msgids.last
36
37
  end
@@ -5,7 +5,6 @@ module FastGettext
5
5
  # - fallback as empty repository, that cannot translate anything but does not crash
6
6
  class Base
7
7
  attr_accessor :locale
8
- attr_writer :pluralisation_rule
9
8
 
10
9
  def initialize(name,options={})
11
10
  @name = name
@@ -13,7 +12,7 @@ module FastGettext
13
12
  end
14
13
 
15
14
  def pluralisation_rule
16
- @pluralisation_rule || lambda{|n| n==1 ? 0 : 1}
15
+ nil
17
16
  end
18
17
 
19
18
  def available_locales
@@ -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(*msgids)
35
+ chain.each do |c|
36
+ result = c.plural(*msgids)
37
+ return result unless result.compact.empty?
38
+ end
39
+ []
40
+ end
41
+ end
42
+ end
43
+ 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(*msgids)
22
+ callback.call(msgids)
23
+ []
24
+ end
25
+ end
26
+ end
27
+ end
@@ -15,7 +15,7 @@ module FastGettext
15
15
  end
16
16
 
17
17
  def pluralisation_rule
18
- current_translations.pluralisation_rule || super
18
+ current_translations.pluralisation_rule
19
19
  end
20
20
 
21
21
  protected
@@ -6,29 +6,29 @@ include FastGettext::Storage
6
6
  describe 'Storage' do
7
7
  before do
8
8
  #reset everything to nil
9
+ self.available_locales = nil
9
10
  self.default_text_domain = nil
10
11
  self.default_locale = nil
11
- self.available_locales = nil
12
12
  send(:_locale=,nil)#nil is not allowed to be set...
13
13
  default_locale.should be_nil
14
14
  available_locales.should be_nil
15
15
  locale.should == 'en'
16
16
  end
17
17
 
18
- def thread_save(method)
19
- send("#{method}=",'de')
18
+ def thread_save(method, value)
19
+ send("#{method}=",value)
20
20
 
21
21
  # mess around with other threads
22
22
  100.times do
23
23
  Thread.new {FastGettext.send("#{method}=",'en')}
24
24
  end
25
25
 
26
- send(method) == 'de'
26
+ send(method) == value
27
27
  end
28
28
 
29
- [:locale, :available_locales, :text_domain].each do |method|
29
+ {:locale=>'de', :available_locales=>['de'], :text_domain=>'xx', :pluralisation_rule=>lambda{|x|x==4}}.each do |method, value|
30
30
  it "stores #{method} thread-save" do
31
- thread_save(method).should == true
31
+ thread_save(method, value).should == true
32
32
  end
33
33
  end
34
34
 
@@ -39,9 +39,19 @@ describe 'Storage' do
39
39
  self.translation_repositories[:x].should == 2
40
40
  end
41
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
+
42
52
  describe :default_locale do
43
53
  it "stores default_locale non-thread-safe" do
44
- thread_save(:default_locale).should == false
54
+ thread_save(:default_locale, 'de').should == false
45
55
  end
46
56
 
47
57
  it "does not overwrite locale" do
@@ -70,7 +80,7 @@ describe 'Storage' do
70
80
 
71
81
  describe :default_text_domain do
72
82
  it "stores default_text_domain non-thread-safe" do
73
- thread_save(:default_text_domain).should == false
83
+ thread_save(:default_text_domain, 'xx').should == false
74
84
  end
75
85
 
76
86
  it "uses default_text_domain when text_domain is not set" do
@@ -0,0 +1,82 @@
1
+ current_folder = File.dirname(__FILE__)
2
+ require File.join(current_folder,'..','..','spec_helper')
3
+
4
+ class MockRepo
5
+ def [](key)#should_receive :[] does not work so well...
6
+ singular key
7
+ end
8
+ end
9
+
10
+ describe 'FastGettext::TranslationRepository::Chain' do
11
+ describe "empty chain" do
12
+ before do
13
+ @rep = FastGettext::TranslationRepository.build('chain', :chain=>[], :type=>:chain)
14
+ end
15
+
16
+ it "has no locales" do
17
+ @rep.available_locales.should == []
18
+ end
19
+
20
+ it "cannot translate" do
21
+ @rep['car'].should == nil
22
+ end
23
+
24
+ it "cannot pluralize" do
25
+ @rep.plural('Axis','Axis').should == []
26
+ end
27
+
28
+ it "has no pluralisation rule" do
29
+ @rep.pluralisation_rule.should == nil
30
+ end
31
+ end
32
+
33
+ describe "filled chain" do
34
+ before do
35
+ @one = MockRepo.new
36
+ @one.stub!(:singular).with('xx').and_return 'one'
37
+ @two = MockRepo.new
38
+ @two.stub!(:singular).with('xx').and_return 'two'
39
+ @rep = FastGettext::TranslationRepository.build('chain', :chain=>[@one, @two], :type=>:chain)
40
+ end
41
+
42
+ describe :singular do
43
+ it "uses the first repo in the chain if it responds" do
44
+ @rep['xx'].should == 'one'
45
+ end
46
+
47
+ it "uses the second repo in the chain if the first does not respond" do
48
+ @one.should_receive(:singular).and_return nil
49
+ @rep['xx'].should == 'two'
50
+ end
51
+ end
52
+
53
+ describe :plural do
54
+ it "uses the first repo in the chain if it responds" do
55
+ @one.should_receive(:plural).with('a','b').and_return ['A','B']
56
+ @rep.plural('a','b').should == ['A','B']
57
+ end
58
+
59
+ it "uses the second repo in the chain if the first does not respond" do
60
+ @one.should_receive(:plural).with('a','b').and_return [nil,nil]
61
+ @two.should_receive(:plural).with('a','b').and_return ['A','B']
62
+ @rep.plural('a','b').should == ['A','B']
63
+ end
64
+ end
65
+
66
+ describe :available_locales do
67
+ it "should be the sum of all added repositories" do
68
+ @one.should_receive(:available_locales).and_return ['de']
69
+ @two.should_receive(:available_locales).and_return ['de','en']
70
+ @rep.available_locales.should == ['de','en']
71
+ end
72
+ end
73
+
74
+ describe :pluralisation_rule do
75
+ it "chooses the first that exists" do
76
+ @one.should_receive(:pluralisation_rule).and_return nil
77
+ @two.should_receive(:pluralisation_rule).and_return 'x'
78
+ @rep.pluralisation_rule.should == 'x'
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,41 @@
1
+ current_folder = File.dirname(__FILE__)
2
+ require File.join(current_folder,'..','..','spec_helper')
3
+
4
+ describe 'FastGettext::TranslationRepository::Logger' do
5
+ before do
6
+ @callback = lambda{}
7
+ @rep = FastGettext::TranslationRepository.build('test', :type=>:logger, :callback=>@callback)
8
+ @rep.is_a?(FastGettext::TranslationRepository::Logger).should be_true
9
+ end
10
+ subject{@rep}
11
+
12
+ it{ should have(0).available_locales}
13
+
14
+ it "has no pluralisation_rule" do
15
+ @rep.pluralisation_rule.should == nil
16
+ end
17
+
18
+ describe :single do
19
+ it "logs every call" do
20
+ @callback.should_receive(:call).with('the_key')
21
+ @rep['the_key']
22
+ end
23
+
24
+ it "returns nil" do
25
+ @callback.should_receive(:call).with('the_key').and_return 'something'
26
+ @rep['the_key'].should == nil
27
+ end
28
+ end
29
+
30
+ describe :plural do
31
+ it "logs every call" do
32
+ @callback.should_receive(:call).with(['a','b'])
33
+ @rep.plural('a','b')
34
+ end
35
+
36
+ it "returns an empty array" do
37
+ @callback.should_receive(:call).with(['a','b']).and_return 'something'
38
+ @rep.plural('a','b').should == []
39
+ end
40
+ end
41
+ end
@@ -5,23 +5,23 @@ require File.join(current_folder,'..','..','spec_helper')
5
5
  describe 'FastGettext::TranslationRepository::Mo' do
6
6
  before do
7
7
  @rep = FastGettext::TranslationRepository.build('test',:path=>File.join(current_folder,'..','..','locale'))
8
- @rep.is_a? FastGettext::TranslationRepository::Mo
8
+ @rep.is_a?(FastGettext::TranslationRepository::Mo).should be_true
9
9
  end
10
+
10
11
  it "can be built" do
11
12
  @rep.available_locales.should == ['de','en']
12
13
  end
14
+
13
15
  it "can translate" do
14
16
  FastGettext.locale = 'de'
15
17
  @rep['car'].should == 'Auto'
16
18
  end
19
+
17
20
  it "can pluralize" do
18
21
  FastGettext.locale = 'de'
19
22
  @rep.plural('Axis','Axis').should == ['Achse','Achsen']
20
23
  end
21
- it "stores pluralisation rule" do
22
- @rep.pluralisation_rule = lambda{|n|n+1}
23
- @rep.pluralisation_rule.call(3).should == 4
24
- end
24
+
25
25
  it "has access to the mo repositories pluralisation rule" do
26
26
  FastGettext.locale = 'en'
27
27
  rep = FastGettext::TranslationRepository.build('plural_test',:path=>File.join(current_folder,'..','..','locale'))
@@ -5,19 +5,23 @@ require File.join(current_folder,'..','..','spec_helper')
5
5
  describe 'FastGettext::TranslationRepository::Po' do
6
6
  before do
7
7
  @rep = FastGettext::TranslationRepository.build('test',:path=>File.join(current_folder,'..','..','locale'),:type=>:po)
8
- @rep.is_a? FastGettext::TranslationRepository::Po
8
+ @rep.is_a?(FastGettext::TranslationRepository::Po).should be_true
9
9
  end
10
+
10
11
  it "can be built" do
11
12
  @rep.available_locales.should == ['de','en']
12
13
  end
14
+
13
15
  it "can translate" do
14
16
  FastGettext.locale = 'de'
15
17
  @rep['car'].should == 'Auto'
16
18
  end
19
+
17
20
  it "can pluralize" do
18
21
  FastGettext.locale = 'de'
19
22
  @rep.plural('Axis','Axis').should == ['Achse','Achsen']
20
23
  end
24
+
21
25
  it "has access to the mo repositories pluralisation rule" do
22
26
  FastGettext.locale = 'en'
23
27
  rep = FastGettext::TranslationRepository.build('plural_test',:path=>File.join(current_folder,'..','..','locale'),:type=>:po)
@@ -34,7 +34,7 @@ describe FastGettext::Translation do
34
34
 
35
35
  describe :n_ do
36
36
  before do
37
- FastGettext.current_repository.pluralisation_rule = lambda{|n|n==1?0:1}
37
+ FastGettext.pluralisation_rule = nil
38
38
  end
39
39
 
40
40
  it "translates pluralized" do
@@ -45,17 +45,17 @@ describe FastGettext::Translation do
45
45
 
46
46
  describe "pluralisations rules" do
47
47
  it "supports abstract pluralisation rules" do
48
- FastGettext.current_repository.pluralisation_rule = lambda{|n|2}
48
+ FastGettext.pluralisation_rule = lambda{|n|2}
49
49
  n_('a','b','c','d',4).should == 'c'
50
50
  end
51
51
 
52
52
  it "supports false as singular" do
53
- FastGettext.current_repository.pluralisation_rule = lambda{|n|n!=2}
53
+ FastGettext.pluralisation_rule = lambda{|n|n!=2}
54
54
  n_('singular','plural','c','d',2).should == 'singular'
55
55
  end
56
56
 
57
57
  it "supports true as plural" do
58
- FastGettext.current_repository.pluralisation_rule = lambda{|n|n==2}
58
+ FastGettext.pluralisation_rule = lambda{|n|n==2}
59
59
  n_('singular','plural','c','d',2).should == 'plural'
60
60
  end
61
61
  end
@@ -66,7 +66,7 @@ describe FastGettext::Translation do
66
66
  end
67
67
 
68
68
  it "returns the last msgid when no translation was found and msgids where to short" do
69
- FastGettext.current_repository.pluralisation_rule = lambda{|x|4}
69
+ FastGettext.pluralisation_rule = lambda{|x|4}
70
70
  n_('Apple','Apples',2).should == 'Apples'
71
71
  end
72
72
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grosser-fast_gettext
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.8
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Grosser
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-04-14 00:00:00 -07:00
12
+ date: 2009-04-19 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -19,46 +19,41 @@ executables: []
19
19
 
20
20
  extensions: []
21
21
 
22
- extra_rdoc_files: []
23
-
22
+ extra_rdoc_files:
23
+ - README.markdown
24
24
  files:
25
25
  - README.markdown
26
+ - Rakefile
26
27
  - VERSION.yml
27
- - lib/fast_gettext
28
+ - examples/missing_translation_logger.rb
28
29
  - lib/fast_gettext.rb
29
30
  - lib/fast_gettext/mo_file.rb
30
31
  - lib/fast_gettext/po_file.rb
31
32
  - lib/fast_gettext/storage.rb
32
33
  - lib/fast_gettext/translation.rb
33
- - lib/fast_gettext/translation_repository
34
34
  - lib/fast_gettext/translation_repository.rb
35
35
  - lib/fast_gettext/translation_repository/base.rb
36
+ - lib/fast_gettext/translation_repository/chain.rb
37
+ - lib/fast_gettext/translation_repository/logger.rb
36
38
  - lib/fast_gettext/translation_repository/mo.rb
37
39
  - lib/fast_gettext/translation_repository/po.rb
38
40
  - spec/aa_unconfigued_spec.rb
39
- - spec/fast_gettext
40
41
  - spec/fast_gettext/mo_file_spec.rb
41
42
  - spec/fast_gettext/storage_spec.rb
42
- - spec/fast_gettext/translation_repository
43
43
  - spec/fast_gettext/translation_repository/base_spec.rb
44
+ - spec/fast_gettext/translation_repository/chain_spec.rb
45
+ - spec/fast_gettext/translation_repository/logger_spec.rb
44
46
  - spec/fast_gettext/translation_repository/mo_spec.rb
45
47
  - spec/fast_gettext/translation_repository/po_spec.rb
46
48
  - spec/fast_gettext/translation_spec.rb
47
49
  - spec/fast_gettext_spec.rb
48
- - spec/locale
49
- - spec/locale/de
50
- - spec/locale/de/LC_MESSAGES
51
50
  - spec/locale/de/LC_MESSAGES/test.mo
52
51
  - spec/locale/de/test.po
53
- - spec/locale/en
54
- - spec/locale/en/LC_MESSAGES
55
52
  - spec/locale/en/LC_MESSAGES/plural_test.mo
56
53
  - spec/locale/en/LC_MESSAGES/test.mo
57
54
  - spec/locale/en/plural_test.po
58
55
  - spec/locale/en/test.po
59
56
  - spec/spec_helper.rb
60
- - spec/vendor
61
- - spec/vendor/fake_load_path
62
57
  - spec/vendor/fake_load_path/iconv.rb
63
58
  - spec/vendor/iconv_spec.rb
64
59
  - spec/vendor/string_spec.rb
@@ -72,7 +67,6 @@ has_rdoc: true
72
67
  homepage: http://github.com/grosser/fast_gettext
73
68
  post_install_message:
74
69
  rdoc_options:
75
- - --inline-source
76
70
  - --charset=UTF-8
77
71
  require_paths:
78
72
  - lib
@@ -95,5 +89,19 @@ rubygems_version: 1.2.0
95
89
  signing_key:
96
90
  specification_version: 2
97
91
  summary: A simple, fast and threadsafe implementation of GetText
98
- test_files: []
99
-
92
+ test_files:
93
+ - spec/fast_gettext_spec.rb
94
+ - spec/spec_helper.rb
95
+ - spec/fast_gettext/translation_spec.rb
96
+ - spec/fast_gettext/storage_spec.rb
97
+ - spec/fast_gettext/translation_repository/chain_spec.rb
98
+ - spec/fast_gettext/translation_repository/logger_spec.rb
99
+ - spec/fast_gettext/translation_repository/base_spec.rb
100
+ - spec/fast_gettext/translation_repository/po_spec.rb
101
+ - spec/fast_gettext/translation_repository/mo_spec.rb
102
+ - spec/fast_gettext/mo_file_spec.rb
103
+ - spec/aa_unconfigued_spec.rb
104
+ - spec/vendor/iconv_spec.rb
105
+ - spec/vendor/fake_load_path/iconv.rb
106
+ - spec/vendor/string_spec.rb
107
+ - examples/missing_translation_logger.rb