grosser-fast_gettext 0.3.8 → 0.4.0

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