grosser-fast_gettext 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,61 @@
1
+ FastGettext
2
+ ===========
3
+ GetText but fast + simple + threadsave!
4
+
5
+ Setup
6
+ =====
7
+ sudo gem install grosser-fast_gettext -s http://gems.github.com/
8
+
9
+ Tell Gettext where your mo-files lie:
10
+ #e.g. for locale/de/LC_MESSAGES/my_app.mo
11
+ FastGettext.add_text_domain('my_app',:path=>'locale')
12
+
13
+ Choose text domain, and locale for translation
14
+ FastGettext.text_domain = 'my_app'
15
+ FastGettext.locale = 'de'
16
+
17
+ Start translating
18
+ include FastGettext
19
+ _('Car') == 'Auto'
20
+ _('not-found') == 'not-found'
21
+ s_('Namespace|no-found') == 'not-found'
22
+ n_('Axis','Axis',3) == 'Achsen' #German plural of Axis
23
+
24
+ Thread-safety
25
+ =============
26
+ locale/text_domain/available_locales are not shared between threads.
27
+ But text_domains is, so that found translations can be reused.
28
+
29
+ Speed
30
+ =====
31
+ FastGettext
32
+ small:
33
+ 1.000000 0.130000 1.130000 ( 1.132578)
34
+ mapped: 8620K writeable/private: 5588K shared: 28K
35
+
36
+ large:
37
+ 1.060000 0.100000 1.160000 ( 1.163962)
38
+ mapped: 8620K writeable/private: 5588K shared: 28K
39
+
40
+
41
+ GetText
42
+ small:
43
+ 3.220000 0.260000 3.480000 ( 3.478093)
44
+ mapped: 9036K writeable/private: 6004K shared: 28K
45
+
46
+ large:
47
+ 3.280000 0.230000 3.510000 ( 3.511891)
48
+ mapped: 9156K writeable/private: 6124K shared: 28K
49
+
50
+
51
+ Updating translations
52
+ =====================
53
+ ATM you have to use the [original GetText](http://github.com/mutoh/gettext) to create and manage your po/mo-files.
54
+
55
+ Author
56
+ ======
57
+ Mofile parsing from Masao Mutoh, see vender/README
58
+
59
+ Michael Grosser
60
+ grosser.michael@gmail.com
61
+ Hereby placed under public domain, do what you want, just do not hold me accountable...
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 1
3
+ :patch: 0
4
+ :major: 0
@@ -0,0 +1,59 @@
1
+ require 'fast_gettext/mo_file'
2
+ require 'fast_gettext/storage'
3
+
4
+ module FastGettext
5
+ include FastGettext::Storage
6
+
7
+ extend self
8
+ def self.included(mod) #:nodoc:
9
+ mod.extend self
10
+ end
11
+
12
+ LOCALE_REX = /^[a-z]{2}$|^[a-z]{2}_[A-Z]{2}$/
13
+ NAMESPACE_SEPERATOR = '|'
14
+
15
+ def _(translate)
16
+ current_mo[translate] || translate
17
+ end
18
+
19
+ #translate pluralized
20
+ def n_(singular,plural,count)
21
+ if translation = current_mo.plural(singular,plural,count)
22
+ translation
23
+ else
24
+ count > 1 ? plural : singular
25
+ end
26
+ end
27
+
28
+ #translate, but discard namespace if nothing was found
29
+ # Car|Tire -> Tire if no translation could be found
30
+ def s_(translate,seperator=nil)
31
+ if translation = current_mo[translate]
32
+ translation
33
+ else
34
+ translate.split(seperator||NAMESPACE_SEPERATOR).last
35
+ end
36
+ end
37
+
38
+ def add_text_domain(name,options)
39
+ self.text_domains ||= {}
40
+ domain = self.text_domains[name] = {:path=>options.delete(:path),:mo_files=>{}}
41
+
42
+ # parse all .mo files with the right name, that sit in locale/LC_MESSAGES folders
43
+ Dir[File.join(domain[:path],'*')].each do |locale_folder|
44
+ next unless File.basename(locale_folder) =~ LOCALE_REX
45
+ mo_file = File.join(locale_folder,'LC_MESSAGES',"#{name}.mo")
46
+ next unless File.exist? mo_file
47
+ locale = File.basename(locale_folder)
48
+ domain[:mo_files][locale] = MoFile.new(mo_file)
49
+ end
50
+ domain
51
+ end
52
+
53
+ private
54
+
55
+ def current_mo
56
+ mo = text_domains[text_domain][:mo_files][locale] rescue nil
57
+ mo || {}
58
+ end
59
+ end
@@ -0,0 +1,48 @@
1
+ require File.join(File.dirname(__FILE__),'..','..','vendor','mofile')
2
+ module FastGettext
3
+ class MoFile
4
+ PLURAL_SEPERATOR = "\000"
5
+
6
+ def initialize(file)
7
+ @data = GetText::MOFile.open(file, "UTF-8")
8
+ make_singular_and_plural_available
9
+ end
10
+
11
+ def [](key)
12
+ @data[key]
13
+ end
14
+
15
+ def plural(singular,plural,count)
16
+ translations = plural_translations(singular,plural)
17
+
18
+ if count > 1
19
+ translations[1] || self[plural]
20
+ else
21
+ translations[0] || self[singular]
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ #(if plural==singular, prefer singular)
28
+ def make_singular_and_plural_available
29
+ @data.each do |key,translation|
30
+ next unless key.include? PLURAL_SEPERATOR
31
+ singular, plural = split_plurals(key)
32
+ translation = split_plurals(translation)
33
+ @data[singular] ||= translation[0]
34
+ @data[plural] ||= translation[1]
35
+ end
36
+ end
37
+
38
+ def split_plurals(singular_plural)
39
+ singular_plural.split(PLURAL_SEPERATOR,2)
40
+ end
41
+
42
+ # Car, Cars => [Auto,Autos] or []
43
+ def plural_translations(singular,plural)
44
+ plurals = self[singular+PLURAL_SEPERATOR+plural]
45
+ if plurals then split_plurals(plurals) else [] end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,24 @@
1
+ module FastGettext
2
+ module Storage
3
+ [:locale,:text_domain,:available_locales].each do |method|
4
+ key = "FastGettext.#{method}"
5
+ define_method method do
6
+ Thread.current[key]
7
+ end
8
+ define_method "#{method}=" do |value|
9
+ Thread.current[key] = value
10
+ end
11
+ end
12
+
13
+ #NOT THREADSAFE, for speed/caching
14
+ @@text_domains = {}
15
+
16
+ def text_domains
17
+ @@text_domains
18
+ end
19
+
20
+ def text_domains=(value)
21
+ @@text_domains=value
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,25 @@
1
+ current_folder = File.dirname(__FILE__)
2
+ require File.join(current_folder,'..','spec_helper')
3
+
4
+ include FastGettext
5
+ de_file = File.join(current_folder,'..','locale','de','LC_MESSAGES','test.mo')
6
+ de = MoFile.new(de_file)
7
+
8
+ describe MoFile do
9
+ before :all do
10
+ File.exist?(de_file).should == true
11
+ end
12
+ it "parses a file" do
13
+ de['car'].should == 'Auto'
14
+ end
15
+ it "stores untranslated values as nil" do
16
+ de['Car|Model'].should == nil
17
+ end
18
+ it "finds pluralized values" do
19
+ de.plural('Axis','Axis',1).should == 'Achse' #singular
20
+ de.plural('Axis','Axis',2).should == 'Achsen' #plurals
21
+ end
22
+ it "can access plurals through []" do
23
+ de['Axis'].should == 'Achse' #singular
24
+ end
25
+ end
@@ -0,0 +1,29 @@
1
+ current_folder = File.dirname(__FILE__)
2
+ require File.join(current_folder,'..','spec_helper')
3
+
4
+ include FastGettext::Storage
5
+
6
+ describe Storage do
7
+ def thread_save(method)
8
+ send("#{method}=",1)
9
+
10
+ # mess around with other threads
11
+ threads = []
12
+ 100.times do |i|
13
+ threads << Thread.new {send("#{method}=",i)}
14
+ end
15
+ threads.each(&:join)
16
+
17
+ send(method) == 1
18
+ end
19
+
20
+ [:locale, :available_locales, :text_domain].each do |method|
21
+ it "stores #{method} thread-save" do
22
+ thread_save(:locale).should == true
23
+ end
24
+ end
25
+
26
+ it "does not store text_domains thread-save" do
27
+ thread_save(:text_domains).should == false
28
+ end
29
+ end
@@ -0,0 +1,43 @@
1
+ require File.expand_path("spec_helper", File.dirname(__FILE__))
2
+
3
+ include FastGettext
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
10
+
11
+ 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
+ end
@@ -0,0 +1,21 @@
1
+ # ---- requirements
2
+ $LOAD_PATH << File.expand_path("../lib", File.dirname(__FILE__))
3
+ require 'fast_gettext'
4
+
5
+ # ---- bugfix
6
+ #`exit?': undefined method `run?' for Test::Unit:Module (NoMethodError)
7
+ #can be solved with require test/unit but this will result in extra test-output
8
+ module Test
9
+ module Unit
10
+ def self.run?
11
+ true
12
+ end
13
+ end
14
+ end
15
+
16
+ # ---- Helpers
17
+ def pending_it(text,&block)
18
+ it text do
19
+ pending(&block)
20
+ end
21
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: grosser-fast_gettext
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Michael Grosser
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-02-19 00:00:00 -08:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description:
17
+ email: grosser.michael@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files: []
23
+
24
+ files:
25
+ - VERSION.yml
26
+ - README.markdown
27
+ - lib/fast_gettext.rb
28
+ - lib/fast_gettext
29
+ - lib/fast_gettext/storage.rb
30
+ - lib/fast_gettext/mo_file.rb
31
+ - spec/fast_gettext_spec.rb
32
+ - spec/spec_helper.rb
33
+ - spec/locale
34
+ - spec/locale/en
35
+ - spec/locale/en/LC_MESSAGES
36
+ - spec/locale/en/LC_MESSAGES/test.mo
37
+ - spec/locale/de
38
+ - spec/locale/de/LC_MESSAGES
39
+ - spec/locale/de/LC_MESSAGES/test.mo
40
+ - spec/fast_gettext
41
+ - spec/fast_gettext/storage_spec.rb
42
+ - spec/fast_gettext/mo_file_spec.rb
43
+ has_rdoc: true
44
+ homepage: http://github.com/grosser/fast_gettext
45
+ post_install_message:
46
+ rdoc_options:
47
+ - --inline-source
48
+ - --charset=UTF-8
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ version:
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: "0"
62
+ version:
63
+ requirements: []
64
+
65
+ rubyforge_project:
66
+ rubygems_version: 1.2.0
67
+ signing_key:
68
+ specification_version: 2
69
+ summary: A simple, fast and threadsafe implementation of GetText
70
+ test_files: []
71
+