grosser-fast_gettext 0.2.4 → 0.2.5

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 fast + simple + threadsave!
3
+ GetText but 4 times faster, simple, clean namespace (7 vs 34) and threadsave!
4
4
 
5
5
  Setup
6
6
  =====
@@ -16,7 +16,7 @@ Choose text domain, and locale for translation
16
16
  FastGettext.locale = 'de'
17
17
 
18
18
  Start translating
19
- include FastGettext
19
+ include FastGettext::Translation
20
20
  _('Car') == 'Auto'
21
21
  _('not-found') == 'not-found'
22
22
  s_('Namespace|no-found') == 'not-found'
@@ -24,24 +24,34 @@ Start translating
24
24
 
25
25
  Speed
26
26
  =====
27
- FastGettext
28
- small:
29
- 1.000000 0.130000 1.130000 ( 1.132578)
30
- mapped: 8620K writeable/private: 5588K shared: 28K
27
+ 50_000 translations:
28
+ Ideal: (primitive Hash lookup)
29
+ small translation file:
30
+ 1.100000 0.180000 1.280000 ( 1.287230)
31
+ mapped: 5832K writeable/private: 3016K shared: 28K
32
+
33
+ large translation file:
34
+ 1.150000 0.150000 1.300000 ( 1.296114)
35
+ mapped: 5832K writeable/private: 3016K shared: 28K
36
+
37
+ FastGettext:
38
+ small translation file:
39
+ 3.980000 0.430000 4.410000 ( 4.407260)
40
+ mapped: 5852K writeable/private: 3036K shared: 28K
31
41
 
32
- large:
33
- 1.060000 0.100000 1.160000 ( 1.163962)
34
- mapped: 8620K writeable/private: 5588K shared: 28K
42
+ large translation file:
43
+ 4.070000 0.450000 4.520000 ( 4.515585)
44
+ mapped: 5972K writeable/private: 3156K shared: 28K
35
45
 
46
+ GetText:
47
+ small translation file:
48
+ 16.280000 1.340000 17.620000 ( 17.630391)
49
+ mapped: 8976K writeable/private: 5944K shared: 28K
36
50
 
37
- GetText
38
- small:
39
- 3.220000 0.260000 3.480000 ( 3.478093)
40
- mapped: 9036K writeable/private: 6004K shared: 28K
51
+ large translation file:
52
+ 16.590000 1.430000 18.020000 ( 18.042926)
53
+ mapped: 9024K writeable/private: 5992K shared: 28K
41
54
 
42
- large:
43
- 3.280000 0.230000 3.510000 ( 3.511891)
44
- mapped: 9156K writeable/private: 6124K shared: 28K
45
55
 
46
56
 
47
57
  Thread Safety and Rails
@@ -59,7 +69,7 @@ then e.g. controllers, so set them inside your application_controller.
59
69
 
60
70
  #application_controller.rb
61
71
  class ApplicationController ...
62
- include FastGettext
72
+ include FastGettext::Translation
63
73
  before_filter :set_locale
64
74
  def set_locale
65
75
  FastGettext.available_locales = ['de','en',...]
@@ -69,7 +79,7 @@ then e.g. controllers, so set them inside your application_controller.
69
79
 
70
80
  #application_helper.rb
71
81
  module ApplicationHelper
72
- include FastGettext
82
+ include FastGettext::Translation
73
83
  ...
74
84
 
75
85
  Try the [gettext_i18n_rails plugin](http://github.com/grosser/gettext_i18n_rails), it simplifies the setup.
data/VERSION.yml CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
2
  :minor: 2
3
- :patch: 4
3
+ :patch: 5
4
4
  :major: 0
data/lib/fast_gettext.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'fast_gettext/mo_file'
2
2
  require 'fast_gettext/storage'
3
+ require 'fast_gettext/translation'
3
4
  require File.join(File.dirname(__FILE__),'..','vendor','string')
4
5
 
5
6
  module FastGettext
@@ -13,39 +14,18 @@ module FastGettext
13
14
  LOCALE_REX = /^[a-z]{2}$|^[a-z]{2}_[A-Z]{2}$/
14
15
  NAMESPACE_SEPERATOR = '|'
15
16
 
16
- def _(translate)
17
- current_mo[translate] || translate
18
- end
19
-
20
- #translate pluralized
21
- def n_(singular,plural,count)
22
- if translation = current_mo.plural(singular,plural,count)
23
- translation
24
- else
25
- count > 1 ? plural : singular
26
- end
27
- end
28
-
29
- #translate, but discard namespace if nothing was found
30
- # Car|Tire -> Tire if no translation could be found
31
- def s_(translate,seperator=nil)
32
- if translation = current_mo[translate]
33
- translation
34
- else
35
- translate.split(seperator||NAMESPACE_SEPERATOR).last
17
+ # users should not include FastGettext, since this would conterminate their namespace
18
+ # rather use
19
+ # FastGettext.locale = ..
20
+ # FastGettext.text_domain = ..
21
+ # and
22
+ # include FastGettext::Translation
23
+ FastGettext::Translation.public_instance_methods.each do |method|
24
+ define_method method do |*args|
25
+ Translation.send(method,*args)
36
26
  end
37
27
  end
38
28
 
39
- #tell gettext: this string need translation (will be found during parsing)
40
- def N_(translate)
41
- translate
42
- end
43
-
44
- #tell gettext: this string need translation (will be found during parsing)
45
- def Nn_(singular,plural)
46
- [singular,plural]
47
- end
48
-
49
29
  def add_text_domain(name,options)
50
30
  self.text_domains ||= {}
51
31
  domain = self.text_domains[name] = {:path=>options.delete(:path),:mo_files=>{}}
@@ -60,12 +40,4 @@ module FastGettext
60
40
  end
61
41
  domain
62
42
  end
63
-
64
- private
65
-
66
- #TODO geht nicht <-> {}.plural
67
- def current_mo
68
- mo = text_domains[text_domain][:mo_files][locale] rescue nil
69
- mo || {}
70
- end
71
43
  end
@@ -1,6 +1,6 @@
1
1
  module FastGettext
2
2
  module Storage
3
- [:text_domain,:available_locales].each do |method|
3
+ [:current_translations,:available_locales].each do |method|
4
4
  define_method method do
5
5
  thread_store(method)
6
6
  end
@@ -9,21 +9,39 @@ module FastGettext
9
9
  end
10
10
  end
11
11
 
12
+ #global, since re-parsing whole folders takes too much time...
12
13
  @@text_domains={}
13
14
  def text_domains
14
15
  @@text_domains
15
16
  end
16
17
 
18
+ def text_domain
19
+ thread_store(:text_domain)
20
+ end
21
+
22
+ def text_domain=(new_text_domain)
23
+ write_thread_store(:text_domain,new_text_domain)
24
+ update_current_translations
25
+ end
26
+
17
27
  def locale
18
28
  thread_store(:locale) || (available_locales||[]).first || 'en'
19
29
  end
20
30
 
21
- def locale=(value)
22
- write_thread_store(:locale,value) if not available_locales or available_locales.include?(value)
31
+ def locale=(new_locale)
32
+ new_locale = new_locale.to_s
33
+ if not available_locales or available_locales.include?(new_locale)
34
+ write_thread_store(:locale,new_locale)
35
+ update_current_translations
36
+ end
23
37
  end
24
38
 
25
39
  private
26
40
 
41
+ def update_current_translations
42
+ self.current_translations = text_domains[text_domain][:mo_files][locale] || {} if text_domains[text_domain]
43
+ end
44
+
27
45
  def thread_store(key)
28
46
  Thread.current["FastGettext.#{key}"]
29
47
  end
@@ -0,0 +1,38 @@
1
+ module FastGettext
2
+ module Translation
3
+ extend self
4
+
5
+ def _(translate)
6
+ FastGettext.current_translations[translate] || translate
7
+ end
8
+
9
+ #translate pluralized
10
+ def n_(singular,plural,count)
11
+ if translation = FastGettext.current_translations.plural(singular,plural,count)
12
+ translation
13
+ else
14
+ count > 1 ? plural : singular
15
+ end
16
+ end
17
+
18
+ #translate, but discard namespace if nothing was found
19
+ # Car|Tire -> Tire if no translation could be found
20
+ def s_(translate,seperator=nil)
21
+ if translation = FastGettext.current_translations[translate]
22
+ translation
23
+ else
24
+ translate.split(seperator||NAMESPACE_SEPERATOR).last
25
+ end
26
+ end
27
+
28
+ #tell gettext: this string need translation (will be found during parsing)
29
+ def N_(translate)
30
+ translate
31
+ end
32
+
33
+ #tell gettext: this string need translation (will be found during parsing)
34
+ def Nn_(singular,plural)
35
+ [singular,plural]
36
+ end
37
+ end
38
+ end
@@ -15,7 +15,7 @@ describe Storage do
15
15
  send(method) == 'de'
16
16
  end
17
17
 
18
- [:locale, :available_locales, :text_domain].each do |method|
18
+ [:locale, :available_locales, :text_domain, :current_translations].each do |method|
19
19
  it "stores #{method} thread-save" do
20
20
  thread_save(method).should == true
21
21
  end
@@ -0,0 +1,55 @@
1
+ current_folder = File.dirname(__FILE__)
2
+ require File.join(current_folder,'..','spec_helper')
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
+ FastGettext.locale = 'de'
8
+
9
+ include FastGettext::Translation
10
+
11
+ describe FastGettext::Translation do
12
+ describe :_ do
13
+ it "translates simple text" do
14
+ _('car').should == 'Auto'
15
+ end
16
+ it "returns msgid if not translation was found" do
17
+ _('NOT|FOUND').should == 'NOT|FOUND'
18
+ end
19
+ end
20
+
21
+ describe :n_ do
22
+ it "translates pluralized" do
23
+ n_('Axis','Axis',1).should == 'Achse'
24
+ n_('Axis','Axis',2).should == 'Achsen'
25
+ end
26
+ it "returns the appropriate msgid if no translation was found" do
27
+ n_('NOTFOUND','NOTFOUNDs',1).should == 'NOTFOUND'
28
+ n_('NOTFOUND','NOTFOUNDs',2).should == 'NOTFOUNDs'
29
+ end
30
+ end
31
+
32
+ describe :s_ do
33
+ it "translates simple text" do
34
+ _('car').should == 'Auto'
35
+ end
36
+ it "returns cleaned msgid if a translation was not found" do
37
+ s_("XXX|not found").should == "not found"
38
+ end
39
+ it "can use a custom seperator" do
40
+ s_("XXX/not found",'/').should == "not found"
41
+ end
42
+ end
43
+
44
+ describe :N_ do
45
+ it "returns the msgid" do
46
+ N_('XXXXX').should == 'XXXXX'
47
+ end
48
+ end
49
+
50
+ describe :Nn_ do
51
+ it "returns the msgids as array" do
52
+ Nn_('X','Y').should == ['X','Y']
53
+ end
54
+ end
55
+ end
@@ -1,6 +1,5 @@
1
1
  require File.expand_path("spec_helper", File.dirname(__FILE__))
2
2
 
3
- include FastGettext
4
3
  FastGettext.add_text_domain('test',:path=>File.join(File.dirname(__FILE__),'locale'))
5
4
  FastGettext.text_domain = 'test'
6
5
  FastGettext.available_locales = ['en','de']
@@ -9,47 +8,11 @@ FastGettext.locale = 'de'
9
8
  include FastGettext
10
9
 
11
10
  describe FastGettext do
12
- describe :_ do
13
- it "translates simple text" do
14
- _('car').should == 'Auto'
15
- end
16
- it "returns msgid if not translation was found" do
17
- _('NOT|FOUND').should == 'NOT|FOUND'
18
- end
19
- end
20
-
21
- describe :n_ do
22
- it "translates pluralized" do
23
- n_('Axis','Axis',1).should == 'Achse'
24
- n_('Axis','Axis',2).should == 'Achsen'
25
- end
26
- it "returns the appropriate msgid if no translation was found" do
27
- n_('NOTFOUND','NOTFOUNDs',1).should == 'NOTFOUND'
28
- n_('NOTFOUND','NOTFOUNDs',2).should == 'NOTFOUNDs'
29
- end
30
- end
31
-
32
- describe :s_ do
33
- it "translates simple text" do
34
- _('car').should == 'Auto'
35
- end
36
- it "returns cleaned msgid if a translation was not found" do
37
- s_("XXX|not found").should == "not found"
38
- end
39
- it "can use a custom seperator" do
40
- s_("XXX/not found",'/').should == "not found"
41
- end
42
- end
43
-
44
- describe :N_ do
45
- it "returns the msgid" do
46
- N_('XXXXX').should == 'XXXXX'
47
- end
48
- end
49
-
50
- describe :Nn_ do
51
- it "returns the msgids as array" do
52
- Nn_('X','Y').should == ['X','Y']
53
- end
11
+ it "provides access to FastGettext::Translations methods" do
12
+ _('car').should == 'Auto'
13
+ s_("XXX|not found").should == "not found"
14
+ n_('Axis','Axis',1).should == 'Achse'
15
+ N_('XXXXX').should == 'XXXXX'
16
+ Nn_('X','Y').should == ['X','Y']
54
17
  end
55
18
  end
@@ -0,0 +1,2 @@
1
+ #simulate file not found
2
+ raise LoadError
@@ -0,0 +1,27 @@
1
+ current_folder = File.dirname(__FILE__)
2
+ $LOAD_PATH.unshift File.expand_path("../../lib", current_folder)
3
+
4
+ describe 'Iconv' do
5
+ it "also works when Iconv was not found locally" do
6
+ #prepare load path
7
+ $LOAD_PATH.unshift File.join(current_folder,'fake_load_path')
8
+ test = 1
9
+ begin
10
+ require 'iconv'
11
+ rescue LoadError
12
+ test = 2
13
+ end
14
+ test.should == 2
15
+
16
+ #load fast_gettext
17
+ require 'fast_gettext'
18
+
19
+ FastGettext.add_text_domain('test',:path=>File.join(File.dirname(__FILE__),'..','locale'))
20
+ FastGettext.text_domain = 'test'
21
+ FastGettext.available_locales = ['en','de']
22
+ FastGettext.locale = 'de'
23
+
24
+ #translate
25
+ FastGettext._('car').should == 'Auto'
26
+ end
27
+ end
data/vendor/iconv.rb CHANGED
@@ -15,8 +15,11 @@
15
15
  $Id: iconv.rb,v 1.6 2007/11/08 14:21:22 mutoh Exp $
16
16
  =end
17
17
 
18
+ #Modifications
19
+ #wrapped inside FastGettext namespace to reduce conflic
20
+
18
21
  begin
19
- require 'iconv.so'
22
+ require 'iconv'
20
23
  rescue LoadError
21
24
  # Pseudo Iconv class
22
25
  #
@@ -27,73 +30,75 @@ rescue LoadError
27
30
  # (1) Ruby/GLib is a module which is provided from Ruby-GNOME2 Project.
28
31
  # You can get binaries for Win32(One-Click Ruby Installer).
29
32
  # <URL: http://ruby-gnome2.sourceforge.jp/>
30
- class Iconv
31
- module Failure; end
32
- class InvalidEncoding < ArgumentError; include Failure; end
33
- class IllegalSequence < ArgumentError; include Failure; end
34
- class InvalidCharacter < ArgumentError; include Failure; end
33
+ module FastGettext
34
+ class Iconv2
35
+ module Failure; end
36
+ class InvalidEncoding < ArgumentError; include Failure; end
37
+ class IllegalSequence < ArgumentError; include Failure; end
38
+ class InvalidCharacter < ArgumentError; include Failure; end
35
39
 
36
- if RUBY_PLATFORM =~ /java/
37
- def self.conv(to, from, str)
38
- raise InvalidCharacter, "the 3rd argument is nil" unless str
39
- begin
40
- str = java.lang.String.new(str.unpack("C*").to_java(:byte), from)
41
- str.getBytes(to).to_ary.pack("C*")
42
- rescue java.io.UnsupportedEncodingException
43
- raise InvalidEncoding
44
- end
45
- end
46
- else
47
- begin
48
- require 'glib2'
49
-
50
- def self.check_glib_version?(major, minor, micro) # :nodoc:
51
- (GLib::BINDING_VERSION[0] > major ||
52
- (GLib::BINDING_VERSION[0] == major &&
53
- GLib::BINDING_VERSION[1] > minor) ||
54
- (GLib::BINDING_VERSION[0] == major &&
55
- GLib::BINDING_VERSION[1] == minor &&
56
- GLib::BINDING_VERSION[2] >= micro))
40
+ if RUBY_PLATFORM =~ /java/
41
+ def self.conv(to, from, str)
42
+ raise InvalidCharacter, "the 3rd argument is nil" unless str
43
+ begin
44
+ str = java.lang.String.new(str.unpack("C*").to_java(:byte), from)
45
+ str.getBytes(to).to_ary.pack("C*")
46
+ rescue java.io.UnsupportedEncodingException
47
+ raise InvalidEncoding
48
+ end
57
49
  end
58
-
59
- if check_glib_version?(0, 11, 0)
60
- # This is a function equivalent of Iconv.iconv.
61
- # * to: encoding name for destination
62
- # * from: encoding name for source
63
- # * str: strings to be converted
64
- # * Returns: Returns an Array of converted strings.
65
- def self.conv(to, from, str)
66
- begin
67
- GLib.convert(str, to, from)
68
- rescue GLib::ConvertError => e
69
- case e.code
70
- when GLib::ConvertError::NO_CONVERSION
71
- raise InvalidEncoding.new(str)
72
- when GLib::ConvertError::ILLEGAL_SEQUENCE
50
+ else
51
+ begin
52
+ require 'glib2'
53
+
54
+ def self.check_glib_version?(major, minor, micro) # :nodoc:
55
+ (GLib::BINDING_VERSION[0] > major ||
56
+ (GLib::BINDING_VERSION[0] == major &&
57
+ GLib::BINDING_VERSION[1] > minor) ||
58
+ (GLib::BINDING_VERSION[0] == major &&
59
+ GLib::BINDING_VERSION[1] == minor &&
60
+ GLib::BINDING_VERSION[2] >= micro))
61
+ end
62
+
63
+ if check_glib_version?(0, 11, 0)
64
+ # This is a function equivalent of Iconv.iconv.
65
+ # * to: encoding name for destination
66
+ # * from: encoding name for source
67
+ # * str: strings to be converted
68
+ # * Returns: Returns an Array of converted strings.
69
+ def self.conv(to, from, str)
70
+ begin
71
+ GLib.convert(str, to, from)
72
+ rescue GLib::ConvertError => e
73
+ case e.code
74
+ when GLib::ConvertError::NO_CONVERSION
75
+ raise InvalidEncoding.new(str)
76
+ when GLib::ConvertError::ILLEGAL_SEQUENCE
77
+ raise IllegalSequence.new(str)
78
+ else
79
+ raise InvalidCharacter.new(str)
80
+ end
81
+ end
82
+ end
83
+ else
84
+ def self.conv(to, from, str) # :nodoc:
85
+ begin
86
+ GLib.convert(str, to, from)
87
+ rescue
73
88
  raise IllegalSequence.new(str)
74
- else
75
- raise InvalidCharacter.new(str)
76
89
  end
77
90
  end
78
91
  end
79
- else
92
+ rescue LoadError
80
93
  def self.conv(to, from, str) # :nodoc:
81
- begin
82
- GLib.convert(str, to, from)
83
- rescue
84
- raise IllegalSequence.new(str)
85
- end
94
+ warn "Iconv was not found." if $DEBUG
95
+ str
86
96
  end
87
97
  end
88
- rescue LoadError
89
- def self.conv(to, from, str) # :nodoc:
90
- warn "Iconv was not found." if $DEBUG
91
- str
92
- end
93
98
  end
94
- end
95
- def self.iconv(to, from, str)
96
- conv(to, from, str).split(//)
99
+ def self.iconv(to, from, str)
100
+ conv(to, from, str).split(//)
101
+ end
97
102
  end
98
103
  end
99
104
  end
data/vendor/mofile.rb CHANGED
@@ -18,6 +18,9 @@
18
18
  require 'iconv'
19
19
  require 'stringio'
20
20
 
21
+ #Modifications:
22
+ # use Iconv or FastGettext::Icvon
23
+
21
24
  module FastGettext
22
25
  module GetText
23
26
  class MOFile < Hash
@@ -148,8 +151,9 @@ module FastGettext
148
151
  else
149
152
  if @output_charset
150
153
  begin
151
- str = Iconv.conv(@output_charset, @charset, str) if @charset
152
- rescue Iconv::Failure
154
+ iconv = Iconv || FastGettext::Iconv
155
+ str = iconv.conv(@output_charset, @charset, str) if @charset
156
+ rescue iconv::Failure
153
157
  if $DEBUG
154
158
  warn "@charset = ", @charset
155
159
  warn"@output_charset = ", @output_charset
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.4
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Grosser
@@ -28,6 +28,7 @@ files:
28
28
  - vendor/README.rdoc
29
29
  - lib/fast_gettext.rb
30
30
  - lib/fast_gettext
31
+ - lib/fast_gettext/translation.rb
31
32
  - lib/fast_gettext/storage.rb
32
33
  - lib/fast_gettext/mo_file.rb
33
34
  - spec/fast_gettext_spec.rb
@@ -40,9 +41,13 @@ files:
40
41
  - spec/locale/de/LC_MESSAGES
41
42
  - spec/locale/de/LC_MESSAGES/test.mo
42
43
  - spec/fast_gettext
44
+ - spec/fast_gettext/translation_spec.rb
43
45
  - spec/fast_gettext/storage_spec.rb
44
46
  - spec/fast_gettext/mo_file_spec.rb
45
47
  - spec/vendor
48
+ - spec/vendor/iconv_spec.rb
49
+ - spec/vendor/fake_load_path
50
+ - spec/vendor/fake_load_path/iconv.rb
46
51
  - spec/vendor/string_spec.rb
47
52
  - VERSION.yml
48
53
  - README.markdown