grosser-fast_gettext 0.2.10 → 0.2.11

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -1,6 +1,6 @@
1
1
  FastGettext
2
2
  ===========
3
- GetText but 8 times faster, simple, clean namespace (7 vs 34) and threadsave!
3
+ GetText but 9.17 times faster, simple, clean namespace (7 vs 34) and threadsave!
4
4
 
5
5
  [Example Rails application](https://github.com/grosser/gettext_i18n_rails_example)
6
6
 
@@ -12,11 +12,14 @@ Or from source:
12
12
  git clone git://github.com/grosser/fast_gettext.git
13
13
  cd fast_gettext && rake install
14
14
 
15
- Tell Gettext where your mo-files lie:
16
- #e.g. for locale/de/LC_MESSAGES/my_app.mo
15
+ Generate .po or .mo files using GetText parser (example tasks at [gettext_i18n_rails](http://github.com/grosser/gettext_i18n_rails))
16
+
17
+ Tell Gettext where your .mo or .po files lie:
18
+ #e.g. for locale/de/my_app.po and locale/de/LC_MESSAGES/my_app.mo
19
+ #add :type=>:po and it will read directly from po files (not recommended for production since po-parsing can crash!)
17
20
  FastGettext.add_text_domain('my_app',:path=>'locale')
18
21
 
19
- Choose text domain, and locale for translation
22
+ Choose text domain and locale for translation
20
23
  FastGettext.text_domain = 'my_app'
21
24
  FastGettext.available_locales = ['de','en','fr','en_US','en_UK'] # only allow these locales to be set (optional)
22
25
  FastGettext.locale = 'de'
@@ -28,32 +31,32 @@ Start translating
28
31
  s_('Namespace|no-found') == 'not-found'
29
32
  n_('Axis','Axis',3) == 'Achsen' #German plural of Axis
30
33
 
31
- Disable translation errors(like no text domain setup) while doing e.g. console session
34
+ Disable translation errors(like no text domain setup) while doing e.g. console session / testing
32
35
  FastGettext.silence_errors
33
36
 
34
37
  Speed
35
38
  =====
36
- 50_000 translations
39
+ 50_000 translations speed / memory
37
40
  small translation file <-> large translation file
38
41
  Baseline: (doing nothing in a loop)
39
- 0.390000s / 2904K
42
+ 0.410000s / 2904K <->
40
43
 
41
44
  Ideal: (primitive Hash lookup)
42
- 1.010000s / 3016K <-> 1.040000s / 3016K
45
+ 1.150000s / 3016K <-> 1.130000s / 3016K
43
46
 
44
47
  FastGettext:
45
- 1.860000s / 3040K <-> 1.830000s / 3040K
48
+ 1.800000s / 3040K <-> 1.750000s / 3040K
46
49
 
47
50
  GetText:
48
- 14.880000s / 5816K <-> 14.810000s / 6008K
51
+ 16.510000s / 5900K <-> 16.400000s / 6072K
49
52
 
50
- Rails I18n Simple:
51
- 31.200000s / 10044K
53
+ ActiveSupport I18n::Backend::Simple :
54
+ 31.880000s / 10028K <->
52
55
 
53
56
 
54
57
  Thread Safety and Rails
55
58
  =======================
56
- `text_domains` is not stored thread-save, so that they can be added inside the `environment.rb`,
59
+ `text_domains` repository are not stored thread-save, so that they can be added inside the `environment.rb`,
57
60
  and do not need to be readded for every thread (parsing takes time...).
58
61
 
59
62
  ###Rails
@@ -86,9 +89,23 @@ Updating translations
86
89
  =====================
87
90
  ATM you have to use the [original GetText](http://github.com/mutoh/gettext) to create and manage your po/mo-files.
88
91
 
92
+ Plugins
93
+ =======
94
+ Want a yml, xml, database version ?
95
+ Write your own TranslationRepository!
96
+ #fast_gettext/translation_repository/xxx.rb
97
+ module FastGettext
98
+ module TranslationRepository
99
+ class Wtf
100
+ define initialize(name,options), available_locales, [key], plural(singular,plural,count)
101
+ end
102
+ end
103
+ end
104
+
105
+
89
106
  Author
90
107
  ======
91
- Mofile parsing from Masao Mutoh, see vendor/README
108
+ Mo/Po-file parsing from Masao Mutoh, see vendor/README
92
109
 
93
110
  Michael Grosser
94
111
  grosser.michael@gmail.com
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
+ :patch: 11
2
3
  :major: 0
3
4
  :minor: 2
4
- :patch: 10
@@ -1,10 +1,17 @@
1
1
  require File.join(File.dirname(__FILE__),'..','..','vendor','mofile')
2
2
  module FastGettext
3
+ # Responsibility:
4
+ # - abstract mo files for Mo Repository
3
5
  class MoFile
4
6
  PLURAL_SEPERATOR = "\000"
5
7
 
8
+ # file => path or FastGettext::GetText::MOFile
6
9
  def initialize(file)
7
- @data = FastGettext::GetText::MOFile.open(file, "UTF-8")
10
+ if file.is_a? FastGettext::GetText::MOFile
11
+ @data = file
12
+ else
13
+ @data = FastGettext::GetText::MOFile.open(file, "UTF-8")
14
+ end
8
15
  make_singular_and_plural_available
9
16
  end
10
17
 
@@ -15,10 +22,10 @@ module FastGettext
15
22
  def plural(singular,plural,count)
16
23
  translations = plural_translations(singular,plural)
17
24
 
18
- if count > 1
19
- translations[1] || self[plural]
20
- else
25
+ if count == 1
21
26
  translations[0] || self[singular]
27
+ else
28
+ translations[1] || self[plural]
22
29
  end
23
30
  end
24
31
 
@@ -1,46 +1,56 @@
1
1
  module FastGettext
2
+ # Responsibility:
3
+ # - store data threadsave
4
+ # - provide error messages when repositories are unconfigured
5
+ # - accept/reject locales that are set by the user
2
6
  module Storage
3
7
  class NoTextDomainConfigured < Exception;end
4
8
 
5
- [:available_locales,:text_domain].each do |method|
6
- define_method method do
7
- thread_store(method)
9
+ [:available_locales,:text_domain,:_locale,:current_cache].each do |method|
10
+ eval <<EOF
11
+ def #{method}
12
+ Thread.current[:fast_gettext_#{method}]
8
13
  end
9
- define_method "#{method}=" do |value|
10
- write_thread_store(method,value)
14
+ def #{method}=(value)
15
+ Thread.current[:fast_gettext_#{method}]=value
11
16
  end
17
+ EOF
12
18
  end
19
+ private :_locale, :_locale=
20
+ #so initial translations does not crash
21
+ Thread.current[:fast_gettext_current_cache]={}
13
22
 
14
- # speed hack, twice as fast as
15
- # Thread.current['FastGettext.'<<'current_translations']
16
- Thread.current[:fast_gettext_current_translations] = NoTextDomainConfigured
17
- def current_translations
18
- Thread.current[:fast_gettext_current_translations]
19
- end
20
- def current_translations=x
21
- Thread.current[:fast_gettext_current_translations]=x
23
+ def text_domain=(new_domain)
24
+ Thread.current[:fast_gettext_text_domain]=new_domain
25
+ update_current_cache
22
26
  end
23
27
 
24
28
  #global, since re-parsing whole folders takes too much time...
25
- @@text_domains={}
26
- def text_domains
27
- @@text_domains
29
+ @@translation_repositories={}
30
+ def translation_repositories
31
+ @@translation_repositories
32
+ end
33
+
34
+ # used to speedup simple translations, does not work for pluralisation
35
+ # caches[text_domain][locale][key]=translation
36
+ @@caches={}
37
+ def caches
38
+ @@caches
28
39
  end
29
40
 
30
- def text_domain=(new_text_domain)
31
- write_thread_store(:text_domain,new_text_domain)
32
- update_current_translations
41
+ def current_repository
42
+ translation_repositories[text_domain] || NoTextDomainConfigured
33
43
  end
34
44
 
35
45
  def locale
36
- thread_store(:locale) || (available_locales||[]).first || 'en'
46
+ _locale || (available_locales||[]).first || 'en'
37
47
  end
38
48
 
39
49
  def locale=(new_locale)
40
50
  new_locale = best_locale_in(new_locale)
41
51
  if new_locale
42
- write_thread_store(:locale,new_locale)
43
- update_current_translations
52
+ self._locale = new_locale
53
+ update_current_cache
44
54
  end
45
55
  end
46
56
 
@@ -78,27 +88,18 @@ module FastGettext
78
88
 
79
89
  #turn off translation if none was defined to disable all resulting errors
80
90
  def silence_errors
81
- if not self.current_translations or self.current_translations == NoTextDomainConfigured
82
- self.current_translations = MoFile.empty
91
+ if not self.current_repository or self.current_repository == NoTextDomainConfigured
92
+ require 'fast_gettext/translation_repository/base'
93
+ translation_repositories[text_domain] = TranslationRepository::Base.new('x')
83
94
  end
84
95
  end
85
96
 
86
97
  private
87
98
 
88
- def update_current_translations
89
- if text_domains[text_domain]
90
- self.current_translations = text_domains[text_domain][:mo_files][locale] || MoFile.empty
91
- else
92
- self.current_translations = NoTextDomainConfigured
93
- end
94
- end
95
-
96
- def thread_store(key)
97
- Thread.current["FastGettext.#{key}"]
98
- end
99
-
100
- def write_thread_store(key,value)
101
- Thread.current["FastGettext.#{key}"]=value
99
+ def update_current_cache
100
+ caches[text_domain]||={}
101
+ caches[text_domain][locale]||={}
102
+ self.current_cache = caches[text_domain][locale]
102
103
  end
103
104
  end
104
105
  end
@@ -1,4 +1,9 @@
1
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
2
7
  module Translation
3
8
  extend self
4
9
 
@@ -12,14 +17,16 @@ module FastGettext
12
17
  end
13
18
 
14
19
  def _(translate)
15
- FastGettext.current_translations[translate] || translate
20
+ found = FastGettext.current_cache[translate] and return found
21
+ FastGettext.current_cache[translate] = FastGettext.current_repository[translate] || translate
16
22
  end
17
23
 
18
24
  #translate pluralized
19
25
  def n_(singular,plural,count)
20
- if translation = FastGettext.current_translations.plural(singular,plural,count)
26
+ if translation = FastGettext.current_repository.plural(singular,plural,count)
21
27
  translation
22
28
  else
29
+ #TODO remove this repeated logic, e.g. return :plural / :singular or raise an exception ?
23
30
  count == 1 ? singular : plural
24
31
  end
25
32
  end
@@ -27,7 +34,7 @@ module FastGettext
27
34
  #translate, but discard namespace if nothing was found
28
35
  # Car|Tire -> Tire if no translation could be found
29
36
  def s_(translate,seperator=nil)
30
- if translation = FastGettext.current_translations[translate]
37
+ if translation = FastGettext.current_repository[translate]
31
38
  translation
32
39
  else
33
40
  translate.split(seperator||NAMESPACE_SEPERATOR).last
@@ -0,0 +1,46 @@
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
+ attr_accessor :locale
8
+ def initialize(name,options={})
9
+ @name = name
10
+ @options = options
11
+ end
12
+
13
+ def available_locales
14
+ []
15
+ end
16
+
17
+ def [](key)
18
+ current_translations[key]
19
+ end
20
+
21
+ def plural(singular,plural,count)
22
+ current_translations.plural(singular,plural,count)
23
+ end
24
+
25
+ protected
26
+
27
+ def current_translations
28
+ MoFile.empty
29
+ end
30
+
31
+ def find_files_in_locale_folders(relative_file_path,path)
32
+ path ||= "locale"
33
+ raise "path #{path} cound not be found!" unless File.exist?(path)
34
+
35
+ @files = {}
36
+ Dir[File.join(path,'*')].each do |locale_folder|
37
+ next unless File.basename(locale_folder) =~ LOCALE_REX
38
+ file = File.join(locale_folder,relative_file_path)
39
+ next unless File.exist? file
40
+ locale = File.basename(locale_folder)
41
+ @files[locale] = yield(locale,file)
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,26 @@
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
+ # parse all .mo files with the right name, that sit in locale/LC_MESSAGES folders
10
+ find_files_in_locale_folders(File.join('LC_MESSAGES',"#{name}.mo"),options[:path]) do |locale,file|
11
+ @files[locale] = MoFile.new(file)
12
+ end
13
+ end
14
+
15
+ def available_locales
16
+ @files.keys
17
+ end
18
+
19
+ protected
20
+
21
+ def current_translations
22
+ @files[FastGettext.locale] || MoFile.empty
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,20 @@
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
+ def initialize(name,options={})
10
+ require File.join(File.dirname(__FILE__),'..','..','..','vendor','poparser')
11
+ require 'fast_gettext/mo_file'
12
+ find_files_in_locale_folders("#{name}.po",options[:path]) do |locale,file|
13
+ mo_file = FastGettext::GetText::MOFile.new
14
+ FastGettext::GetText::PoParser.new.parse(File.read(file),mo_file)
15
+ @files[locale] = MoFile.new(mo_file)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ 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
data/lib/fast_gettext.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'fast_gettext/mo_file'
2
2
  require 'fast_gettext/storage'
3
3
  require 'fast_gettext/translation'
4
+ require 'fast_gettext/translation_repository'
4
5
  require File.join(File.dirname(__FILE__),'..','vendor','string')
5
6
 
6
7
  module FastGettext
@@ -23,17 +24,6 @@ module FastGettext
23
24
  end
24
25
 
25
26
  def add_text_domain(name,options)
26
- self.text_domains ||= {}
27
- domain = self.text_domains[name] = {:path=>options.delete(:path),:mo_files=>{}}
28
-
29
- # parse all .mo files with the right name, that sit in locale/LC_MESSAGES folders
30
- Dir[File.join(domain[:path],'*')].each do |locale_folder|
31
- next unless File.basename(locale_folder) =~ LOCALE_REX
32
- mo_file = File.join(locale_folder,'LC_MESSAGES',"#{name}.mo")
33
- next unless File.exist? mo_file
34
- locale = File.basename(locale_folder)
35
- domain[:mo_files][locale] = MoFile.new(mo_file)
36
- end
37
- domain
27
+ translation_repositories[name] = TranslationRepository.build(name,options)
38
28
  end
39
29
  end
@@ -3,7 +3,7 @@ require File.join(current_folder,'..','spec_helper')
3
3
 
4
4
  include FastGettext::Storage
5
5
 
6
- describe Storage do
6
+ describe 'Storage' do
7
7
  def thread_save(method)
8
8
  send("#{method}=",'de')
9
9
 
@@ -15,17 +15,17 @@ describe Storage do
15
15
  send(method) == 'de'
16
16
  end
17
17
 
18
- [:locale, :available_locales, :text_domain, :current_translations].each do |method|
18
+ [:locale, :available_locales, :text_domain].each do |method|
19
19
  it "stores #{method} thread-save" do
20
20
  thread_save(method).should == true
21
21
  end
22
22
  end
23
23
 
24
- it "stores text_domains non-thread-safe" do
25
- self.text_domains[:x]=1
26
- t = Thread.new{self.text_domains[:x]=2}
24
+ it "stores translation_repositories non-thread-safe" do
25
+ self.translation_repositories[:x]=1
26
+ t = Thread.new{self.translation_repositories[:x]=2}
27
27
  t.join
28
- self.text_domains[:x].should == 2
28
+ self.translation_repositories[:x].should == 2
29
29
  end
30
30
 
31
31
  describe :locale do
@@ -35,7 +35,7 @@ describe Storage do
35
35
  locale.should == 'XXX'
36
36
  end
37
37
  it "is en if no locale and no available_locale were set" do
38
- Thread.current['FastGettext.locale']=nil
38
+ FastGettext.send(:_locale=,nil)
39
39
  self.available_locales = nil
40
40
  locale.should == 'en'
41
41
  end
@@ -99,4 +99,22 @@ describe Storage do
99
99
  FastGettext._('x').should == 'x'
100
100
  end
101
101
  end
102
+
103
+ describe :current_cache do
104
+ before do
105
+ FastGettext.available_locales = ['de','en']
106
+ FastGettext.locale = 'de'
107
+ FastGettext._('abc')
108
+ FastGettext.locale = 'en'
109
+ end
110
+
111
+ it "stores a translation seperatly" do
112
+ FastGettext.current_cache['abc'].should == nil
113
+ end
114
+
115
+ it "stores a translation permanently" do
116
+ FastGettext.locale = 'de'
117
+ FastGettext.current_cache['abc'].should == 'abc'
118
+ end
119
+ end
102
120
  end
@@ -0,0 +1,20 @@
1
+ current_folder = File.dirname(__FILE__)
2
+ require File.join(current_folder,'..','..','spec_helper')
3
+ require 'fast_gettext/translation_repository/base'
4
+
5
+ describe 'FastGettext::TranslationRepository::Base' do
6
+ before do
7
+ @rep = FastGettext::TranslationRepository::Base.new('x')
8
+ end
9
+ it "can be built" do
10
+ @rep.available_locales.should == []
11
+ end
12
+ it "cannot translate" do
13
+ @rep.locale = 'de'
14
+ @rep['car'].should == nil
15
+ end
16
+ it "cannot pluralize" do
17
+ @rep.locale = 'de'
18
+ @rep.plural('Axis','Axis',2).should == nil
19
+ end
20
+ end
@@ -0,0 +1,21 @@
1
+ current_folder = File.dirname(__FILE__)
2
+ require File.join(current_folder,'..','..','spec_helper')
3
+
4
+
5
+ describe 'FastGettext::TranslationRepository::Mo' do
6
+ before do
7
+ @rep = FastGettext::TranslationRepository.build('test',:path=>File.join(current_folder,'..','..','locale'))
8
+ @rep.is_a? FastGettext::TranslationRepository::Mo
9
+ end
10
+ it "can be built" do
11
+ @rep.available_locales.should == ['de','en']
12
+ end
13
+ it "can translate" do
14
+ FastGettext.locale = 'de'
15
+ @rep['car'].should == 'Auto'
16
+ end
17
+ it "can pluralize" do
18
+ FastGettext.locale = 'de'
19
+ @rep.plural('Axis','Axis',2).should == 'Achsen'
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ current_folder = File.dirname(__FILE__)
2
+ require File.join(current_folder,'..','..','spec_helper')
3
+
4
+
5
+ describe 'FastGettext::TranslationRepository::Po' do
6
+ before do
7
+ @rep = FastGettext::TranslationRepository.build('test',:path=>File.join(current_folder,'..','..','locale'),:type=>:po)
8
+ @rep.is_a? FastGettext::TranslationRepository::Po
9
+ end
10
+ it "can be built" do
11
+ @rep.available_locales.should == ['de','en']
12
+ end
13
+ it "can translate" do
14
+ FastGettext.locale = 'de'
15
+ @rep['car'].should == 'Auto'
16
+ end
17
+ it "can pluralize" do
18
+ FastGettext.locale = 'de'
19
+ @rep.plural('Axis','Axis',2).should == 'Achsen'
20
+ end
21
+ end
@@ -1,16 +1,11 @@
1
1
  current_folder = File.dirname(__FILE__)
2
2
  require File.join(current_folder,'..','spec_helper')
3
3
 
4
- FastGettext.add_text_domain('test',:path=>File.join(File.dirname(__FILE__),'..','locale'))
5
- FastGettext.text_domain = 'test'
6
- FastGettext.available_locales = ['en','de']
7
-
8
4
  include FastGettext::Translation
9
5
 
10
6
  describe FastGettext::Translation do
11
7
  before do
12
- FastGettext.available_locales = ['en','de']
13
- FastGettext.locale = 'de'
8
+ default_setup
14
9
  end
15
10
 
16
11
  describe "unknown locale" do
@@ -41,7 +36,7 @@ describe FastGettext::Translation do
41
36
  it "translates pluralized" do
42
37
  n_('Axis','Axis',1).should == 'Achse'
43
38
  n_('Axis','Axis',2).should == 'Achsen'
44
- n_('Axis','Axis',0).should == 'Achse'
39
+ n_('Axis','Axis',0).should == 'Achsen'
45
40
  end
46
41
  it "returns the appropriate msgid if no translation was found" do
47
42
  n_('NOTFOUND','NOTFOUNDs',1).should == 'NOTFOUND'
@@ -72,4 +67,24 @@ describe FastGettext::Translation do
72
67
  Nn_('X','Y').should == ['X','Y']
73
68
  end
74
69
  end
70
+
71
+ describe :caching do
72
+ it "caches different locales seperatly" do
73
+ FastGettext.locale = 'en'
74
+ _('car').should == 'car'
75
+ FastGettext.locale = 'de'
76
+ _('car').should == 'Auto'
77
+ end
78
+
79
+ it "caches different textdomains seperatly" do
80
+ _('car').should == 'Auto'
81
+
82
+ FastGettext.translation_repositories['fake'] = {}
83
+ FastGettext.text_domain = 'fake'
84
+ _('car').should == 'car'
85
+
86
+ FastGettext.text_domain = 'test'
87
+ _('car').should == 'Auto'
88
+ end
89
+ end
75
90
  end
@@ -1,10 +1,6 @@
1
1
  require File.expand_path("spec_helper", File.dirname(__FILE__))
2
2
 
3
- FastGettext.add_text_domain('test',:path=>File.join(File.dirname(__FILE__),'locale'))
4
- FastGettext.text_domain = 'test'
5
- FastGettext.available_locales = ['en','de']
6
- FastGettext.locale = 'de'
7
-
3
+ default_setup
8
4
  class IncludeTest
9
5
  include FastGettext::Translation
10
6
  @@xx = _('car')
@@ -22,6 +18,10 @@ end
22
18
  include FastGettext
23
19
 
24
20
  describe FastGettext do
21
+ before :all do
22
+ default_setup
23
+ end
24
+
25
25
  it "provides access to FastGettext::Translations methods" do
26
26
  FastGettext._('car').should == 'Auto'
27
27
  _('car').should == 'Auto'
@@ -30,6 +30,7 @@ describe FastGettext do
30
30
  N_('XXXXX').should == 'XXXXX'
31
31
  Nn_('X','Y').should == ['X','Y']
32
32
  end
33
+
33
34
  it "is extended to a class and included into a class" do
34
35
  IncludeTest.ext.should == 'Auto'
35
36
  IncludeTest.ext.should == 'Auto'
@@ -0,0 +1,61 @@
1
+ # SOME DESCRIPTIVE TITLE.
2
+ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3
+ # This file is distributed under the same license as the PACKAGE package.
4
+ # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
5
+ #
6
+ #, fuzzy
7
+ msgid ""
8
+ msgstr ""
9
+ "Project-Id-Version: version 0.0.1\n"
10
+ "POT-Creation-Date: 2009-02-26 19:50+0100\n"
11
+ "PO-Revision-Date: 2009-02-18 14:53+0100\n"
12
+ "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
+ "Language-Team: LANGUAGE <LL@li.org>\n"
14
+ "MIME-Version: 1.0\n"
15
+ "Content-Type: text/plain; charset=UTF-8\n"
16
+ "Content-Transfer-Encoding: 8bit\n"
17
+ "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
18
+
19
+ #: app/helpers/translation_helper.rb:3
20
+ msgid "%{relative_time} ago"
21
+ msgstr "vor %{relative_time}"
22
+
23
+ #: app/views/cars/show.html.erb:5
24
+ msgid "Axis"
25
+ msgid_plural "Axis"
26
+ msgstr[0] "Achse"
27
+ msgstr[1] "Achsen"
28
+
29
+ #: app/controllers/cars_controller.rb:47
30
+ msgid "Car was successfully created."
31
+ msgstr "Auto wurde erfolgreich gespeichert"
32
+
33
+ #: app/controllers/cars_controller.rb:64
34
+ msgid "Car was successfully updated."
35
+ msgstr "Auto wurde erfolgreich aktualisiert"
36
+
37
+ #: app/views/cars/show.html.erb:1 locale/model_attributes.rb:3
38
+ msgid "Car|Model"
39
+ msgstr "Modell"
40
+
41
+ #: app/views/cars/show.html.erb:3 locale/model_attributes.rb:4
42
+ msgid "Car|Wheels count"
43
+ msgstr "Räderzahl"
44
+
45
+ #: app/views/cars/show.html.erb:7
46
+ msgid "Created"
47
+ msgstr "Erstellt"
48
+
49
+ #: app/views/cars/show.html.erb:9
50
+ msgid "Month"
51
+ msgstr "Monat"
52
+
53
+ #: locale/model_attributes.rb:2
54
+ msgid "car"
55
+ msgstr "Auto"
56
+
57
+ #: locale/testlog_phrases.rb:2
58
+ msgid "this is a dynamic translation which was found thorugh gettext_test_log!"
59
+ msgstr ""
60
+ "Dies ist eine dynamische Übersetzung, die durch gettext_test_log "
61
+ "gefunden wurde!"
@@ -0,0 +1,59 @@
1
+ # SOME DESCRIPTIVE TITLE.
2
+ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
3
+ # This file is distributed under the same license as the PACKAGE package.
4
+ # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
5
+ #
6
+ #, fuzzy
7
+ msgid ""
8
+ msgstr ""
9
+ "Project-Id-Version: version 0.0.1\n"
10
+ "POT-Creation-Date: 2009-02-26 19:50+0100\n"
11
+ "PO-Revision-Date: 2009-02-18 15:42+0100\n"
12
+ "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
+ "Language-Team: LANGUAGE <LL@li.org>\n"
14
+ "MIME-Version: 1.0\n"
15
+ "Content-Type: text/plain; charset=UTF-8\n"
16
+ "Content-Transfer-Encoding: 8bit\n"
17
+ "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
18
+
19
+ #: app/helpers/translation_helper.rb:3
20
+ msgid "%{relative_time} ago"
21
+ msgstr ""
22
+
23
+ #: app/views/cars/show.html.erb:5
24
+ msgid "Axis"
25
+ msgid_plural "Axis"
26
+ msgstr[0] ""
27
+ msgstr[1] ""
28
+
29
+ #: app/controllers/cars_controller.rb:47
30
+ msgid "Car was successfully created."
31
+ msgstr ""
32
+
33
+ #: app/controllers/cars_controller.rb:64
34
+ msgid "Car was successfully updated."
35
+ msgstr ""
36
+
37
+ #: app/views/cars/show.html.erb:1 locale/model_attributes.rb:3
38
+ msgid "Car|Model"
39
+ msgstr ""
40
+
41
+ #: app/views/cars/show.html.erb:3 locale/model_attributes.rb:4
42
+ msgid "Car|Wheels count"
43
+ msgstr ""
44
+
45
+ #: app/views/cars/show.html.erb:7
46
+ msgid "Created"
47
+ msgstr ""
48
+
49
+ #: app/views/cars/show.html.erb:9
50
+ msgid "Month"
51
+ msgstr ""
52
+
53
+ #: locale/model_attributes.rb:2
54
+ msgid "car"
55
+ msgstr ""
56
+
57
+ #: locale/testlog_phrases.rb:2
58
+ msgid "this is a dynamic translation which was found thorugh gettext_test_log!"
59
+ msgstr ""
data/spec/spec_helper.rb CHANGED
@@ -13,9 +13,24 @@ module Test
13
13
  end
14
14
  end
15
15
 
16
+ # ---- revert to defaults
17
+ Spec::Runner.configure do |config|
18
+ config.before :all do
19
+ FastGettext.locale = 'de'
20
+ FastGettext.available_locales = nil
21
+ end
22
+ end
23
+
16
24
  # ---- Helpers
17
25
  def pending_it(text,&block)
18
26
  it text do
19
27
  pending(&block)
20
28
  end
29
+ end
30
+
31
+ def default_setup
32
+ FastGettext.add_text_domain('test',:path=>File.join(File.dirname(__FILE__),'locale'))
33
+ FastGettext.text_domain = 'test'
34
+ FastGettext.available_locales = ['en','de']
35
+ FastGettext.locale = 'de'
21
36
  end
@@ -0,0 +1,331 @@
1
+ =begin
2
+ poparser.rb - Generate a .mo
3
+
4
+ Copyright (C) 2003-2009 Masao Mutoh <mutoh at highway.ne.jp>
5
+
6
+ You may redistribute it and/or modify it under the same
7
+ license terms as Ruby.
8
+ =end
9
+
10
+ #MODIFIED
11
+ # removed include GetText etc
12
+ # added stub translation method _(x)
13
+ require 'racc/parser'
14
+
15
+ module FastGettext
16
+ module GetText
17
+
18
+ class PoParser < Racc::Parser
19
+
20
+ def _(x)
21
+ x
22
+ end
23
+
24
+ module_eval <<'..end src/poparser.ry modeval..id7a99570e05', 'src/poparser.ry', 108
25
+ def unescape(orig)
26
+ ret = orig.gsub(/\\n/, "\n")
27
+ ret.gsub!(/\\t/, "\t")
28
+ ret.gsub!(/\\r/, "\r")
29
+ ret.gsub!(/\\"/, "\"")
30
+ ret
31
+ end
32
+
33
+ def parse(str, data, ignore_fuzzy = true)
34
+ @comments = []
35
+ @data = data
36
+ @fuzzy = false
37
+ @msgctxt = ""
38
+ $ignore_fuzzy = ignore_fuzzy
39
+
40
+ str.strip!
41
+ @q = []
42
+ until str.empty? do
43
+ case str
44
+ when /\A\s+/
45
+ str = $'
46
+ when /\Amsgctxt/
47
+ @q.push [:MSGCTXT, $&]
48
+ str = $'
49
+ when /\Amsgid_plural/
50
+ @q.push [:MSGID_PLURAL, $&]
51
+ str = $'
52
+ when /\Amsgid/
53
+ @q.push [:MSGID, $&]
54
+ str = $'
55
+ when /\Amsgstr/
56
+ @q.push [:MSGSTR, $&]
57
+ str = $'
58
+ when /\A\[(\d+)\]/
59
+ @q.push [:PLURAL_NUM, $1]
60
+ str = $'
61
+ when /\A\#~(.*)/
62
+ $stderr.print _("Warning: obsolete msgid exists.\n")
63
+ $stderr.print " #{$&}\n"
64
+ @q.push [:COMMENT, $&]
65
+ str = $'
66
+ when /\A\#(.*)/
67
+ @q.push [:COMMENT, $&]
68
+ str = $'
69
+ when /\A\"(.*)\"/
70
+ @q.push [:STRING, $1]
71
+ str = $'
72
+ else
73
+ #c = str[0,1]
74
+ #@q.push [:STRING, c]
75
+ str = str[1..-1]
76
+ end
77
+ end
78
+ @q.push [false, '$end']
79
+ if $DEBUG
80
+ @q.each do |a,b|
81
+ puts "[#{a}, #{b}]"
82
+ end
83
+ end
84
+ @yydebug = true if $DEBUG
85
+ do_parse
86
+
87
+ if @comments.size > 0
88
+ @data.set_comment(:last, @comments.join("\n"))
89
+ end
90
+ @data
91
+ end
92
+
93
+ def next_token
94
+ @q.shift
95
+ end
96
+
97
+ def on_message(msgid, msgstr)
98
+ if msgstr.size > 0
99
+ @data[msgid] = msgstr
100
+ @data.set_comment(msgid, @comments.join("\n"))
101
+ end
102
+ @comments.clear
103
+ @msgctxt = ""
104
+ end
105
+
106
+ def on_comment(comment)
107
+ @fuzzy = true if (/fuzzy/ =~ comment)
108
+ @comments << comment
109
+ end
110
+
111
+
112
+ ..end src/poparser.ry modeval..id7a99570e05
113
+
114
+ ##### racc 1.4.5 generates ###
115
+
116
+ racc_reduce_table = [
117
+ 0, 0, :racc_error,
118
+ 0, 10, :_reduce_none,
119
+ 2, 10, :_reduce_none,
120
+ 2, 10, :_reduce_none,
121
+ 2, 10, :_reduce_none,
122
+ 2, 12, :_reduce_5,
123
+ 1, 13, :_reduce_none,
124
+ 1, 13, :_reduce_none,
125
+ 4, 15, :_reduce_8,
126
+ 5, 16, :_reduce_9,
127
+ 2, 17, :_reduce_10,
128
+ 1, 17, :_reduce_none,
129
+ 3, 18, :_reduce_12,
130
+ 1, 11, :_reduce_13,
131
+ 2, 14, :_reduce_14,
132
+ 1, 14, :_reduce_15 ]
133
+
134
+ racc_reduce_n = 16
135
+
136
+ racc_shift_n = 26
137
+
138
+ racc_action_table = [
139
+ 3, 13, 5, 7, 9, 15, 16, 17, 20, 17,
140
+ 13, 17, 13, 13, 11, 17, 23, 20, 13, 17 ]
141
+
142
+ racc_action_check = [
143
+ 1, 16, 1, 1, 1, 12, 12, 12, 18, 18,
144
+ 7, 14, 15, 9, 3, 19, 20, 21, 23, 25 ]
145
+
146
+ racc_action_pointer = [
147
+ nil, 0, nil, 14, nil, nil, nil, 3, nil, 6,
148
+ nil, nil, 0, nil, 4, 5, -6, nil, 2, 8,
149
+ 8, 11, nil, 11, nil, 12 ]
150
+
151
+ racc_action_default = [
152
+ -1, -16, -2, -16, -3, -13, -4, -16, -6, -16,
153
+ -7, 26, -16, -15, -5, -16, -16, -14, -16, -8,
154
+ -16, -9, -11, -16, -10, -12 ]
155
+
156
+ racc_goto_table = [
157
+ 12, 22, 14, 4, 24, 6, 2, 8, 18, 19,
158
+ 10, 21, 1, nil, nil, nil, 25 ]
159
+
160
+ racc_goto_check = [
161
+ 5, 9, 5, 3, 9, 4, 2, 6, 5, 5,
162
+ 7, 8, 1, nil, nil, nil, 5 ]
163
+
164
+ racc_goto_pointer = [
165
+ nil, 12, 5, 2, 4, -7, 6, 9, -7, -17 ]
166
+
167
+ racc_goto_default = [
168
+ nil, nil, nil, nil, nil, nil, nil, nil, nil, nil ]
169
+
170
+ racc_token_table = {
171
+ false => 0,
172
+ Object.new => 1,
173
+ :COMMENT => 2,
174
+ :MSGID => 3,
175
+ :MSGCTXT => 4,
176
+ :MSGID_PLURAL => 5,
177
+ :MSGSTR => 6,
178
+ :STRING => 7,
179
+ :PLURAL_NUM => 8 }
180
+
181
+ racc_use_result_var = true
182
+
183
+ racc_nt_base = 9
184
+
185
+ Racc_arg = [
186
+ racc_action_table,
187
+ racc_action_check,
188
+ racc_action_default,
189
+ racc_action_pointer,
190
+ racc_goto_table,
191
+ racc_goto_check,
192
+ racc_goto_default,
193
+ racc_goto_pointer,
194
+ racc_nt_base,
195
+ racc_reduce_table,
196
+ racc_token_table,
197
+ racc_shift_n,
198
+ racc_reduce_n,
199
+ racc_use_result_var ]
200
+
201
+ Racc_token_to_s_table = [
202
+ '$end',
203
+ 'error',
204
+ 'COMMENT',
205
+ 'MSGID',
206
+ 'MSGCTXT',
207
+ 'MSGID_PLURAL',
208
+ 'MSGSTR',
209
+ 'STRING',
210
+ 'PLURAL_NUM',
211
+ '$start',
212
+ 'msgfmt',
213
+ 'comment',
214
+ 'msgctxt',
215
+ 'message',
216
+ 'string_list',
217
+ 'single_message',
218
+ 'plural_message',
219
+ 'msgstr_plural',
220
+ 'msgstr_plural_line']
221
+
222
+ Racc_debug_parser = true
223
+
224
+ ##### racc system variables end #####
225
+
226
+ # reduce 0 omitted
227
+
228
+ # reduce 1 omitted
229
+
230
+ # reduce 2 omitted
231
+
232
+ # reduce 3 omitted
233
+
234
+ # reduce 4 omitted
235
+
236
+ module_eval <<'.,.,', 'src/poparser.ry', 25
237
+ def _reduce_5( val, _values, result )
238
+ @msgctxt = unescape(val[1]) + "\004"
239
+ result
240
+ end
241
+ .,.,
242
+
243
+ # reduce 6 omitted
244
+
245
+ # reduce 7 omitted
246
+
247
+ module_eval <<'.,.,', 'src/poparser.ry', 48
248
+ def _reduce_8( val, _values, result )
249
+ if @fuzzy and $ignore_fuzzy
250
+ if val[1] != ""
251
+ $stderr.print _("Warning: fuzzy message was ignored.\n")
252
+ $stderr.print " msgid '#{val[1]}'\n"
253
+ else
254
+ on_message('', unescape(val[3]))
255
+ end
256
+ @fuzzy = false
257
+ else
258
+ on_message(@msgctxt + unescape(val[1]), unescape(val[3]))
259
+ end
260
+ result = ""
261
+ result
262
+ end
263
+ .,.,
264
+
265
+ module_eval <<'.,.,', 'src/poparser.ry', 65
266
+ def _reduce_9( val, _values, result )
267
+ if @fuzzy and $ignore_fuzzy
268
+ if val[1] != ""
269
+ $stderr.print _("Warning: fuzzy message was ignored.\n")
270
+ $stderr.print "msgid = '#{val[1]}\n"
271
+ else
272
+ on_message('', unescape(val[3]))
273
+ end
274
+ @fuzzy = false
275
+ else
276
+ on_message(@msgctxt + unescape(val[1]) + "\000" + unescape(val[3]), unescape(val[4]))
277
+ end
278
+ result = ""
279
+ result
280
+ end
281
+ .,.,
282
+
283
+ module_eval <<'.,.,', 'src/poparser.ry', 76
284
+ def _reduce_10( val, _values, result )
285
+ if val[0].size > 0
286
+ result = val[0] + "\000" + val[1]
287
+ else
288
+ result = ""
289
+ end
290
+ result
291
+ end
292
+ .,.,
293
+
294
+ # reduce 11 omitted
295
+
296
+ module_eval <<'.,.,', 'src/poparser.ry', 84
297
+ def _reduce_12( val, _values, result )
298
+ result = val[2]
299
+ result
300
+ end
301
+ .,.,
302
+
303
+ module_eval <<'.,.,', 'src/poparser.ry', 91
304
+ def _reduce_13( val, _values, result )
305
+ on_comment(val[0])
306
+ result
307
+ end
308
+ .,.,
309
+
310
+ module_eval <<'.,.,', 'src/poparser.ry', 99
311
+ def _reduce_14( val, _values, result )
312
+ result = val.delete_if{|item| item == ""}.join
313
+ result
314
+ end
315
+ .,.,
316
+
317
+ module_eval <<'.,.,', 'src/poparser.ry', 103
318
+ def _reduce_15( val, _values, result )
319
+ result = val[0]
320
+ result
321
+ end
322
+ .,.,
323
+
324
+ def _reduce_none( val, _values, result )
325
+ result
326
+ end
327
+
328
+ end # class PoParser
329
+
330
+ end # module GetText
331
+ 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.2.10
4
+ version: 0.2.11
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-02-26 00:00:00 -08:00
12
+ date: 2009-02-28 00:00:00 -08:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -29,19 +29,30 @@ files:
29
29
  - lib/fast_gettext/mo_file.rb
30
30
  - lib/fast_gettext/storage.rb
31
31
  - lib/fast_gettext/translation.rb
32
+ - lib/fast_gettext/translation_repository
33
+ - lib/fast_gettext/translation_repository.rb
34
+ - lib/fast_gettext/translation_repository/base.rb
35
+ - lib/fast_gettext/translation_repository/mo.rb
36
+ - lib/fast_gettext/translation_repository/po.rb
32
37
  - spec/aa_unconfigued_spec.rb
33
38
  - spec/fast_gettext
34
39
  - spec/fast_gettext/mo_file_spec.rb
35
40
  - spec/fast_gettext/storage_spec.rb
41
+ - spec/fast_gettext/translation_repository
42
+ - spec/fast_gettext/translation_repository/base_spec.rb
43
+ - spec/fast_gettext/translation_repository/mo_spec.rb
44
+ - spec/fast_gettext/translation_repository/po_spec.rb
36
45
  - spec/fast_gettext/translation_spec.rb
37
46
  - spec/fast_gettext_spec.rb
38
47
  - spec/locale
39
48
  - spec/locale/de
40
49
  - spec/locale/de/LC_MESSAGES
41
50
  - spec/locale/de/LC_MESSAGES/test.mo
51
+ - spec/locale/de/test.po
42
52
  - spec/locale/en
43
53
  - spec/locale/en/LC_MESSAGES
44
54
  - spec/locale/en/LC_MESSAGES/test.mo
55
+ - spec/locale/en/test.po
45
56
  - spec/spec_helper.rb
46
57
  - spec/vendor
47
58
  - spec/vendor/fake_load_path
@@ -52,6 +63,7 @@ files:
52
63
  - vendor/empty.mo
53
64
  - vendor/iconv.rb
54
65
  - vendor/mofile.rb
66
+ - vendor/poparser.rb
55
67
  - vendor/string.rb
56
68
  has_rdoc: true
57
69
  homepage: http://github.com/grosser/fast_gettext