grosser-fast_gettext 0.4.7 → 0.4.8
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.
- data/README.markdown +32 -29
- data/VERSION.yml +1 -1
- data/lib/fast_gettext/storage.rb +8 -1
- data/lib/fast_gettext/translation.rb +3 -3
- data/spec/fast_gettext/storage_spec.rb +25 -0
- data/spec/fast_gettext/translation_spec.rb +15 -0
- data/spec/vendor/string_spec.rb +16 -4
- data/vendor/string.rb +17 -11
- metadata +2 -2
data/README.markdown
CHANGED
@@ -2,57 +2,66 @@ FastGettext
|
|
2
2
|
===========
|
3
3
|
GetText but 3.5 x faster, 560 x less memory, simple, clean namespace (7 vs 34) and threadsave!
|
4
4
|
|
5
|
-
It supports multiple backends (atm: .mo files, .po files,
|
5
|
+
It supports multiple backends (atm: .mo files, .po files, Database(ActiveRecor + any other), Chain, Loggers) and can easily be extended.
|
6
6
|
|
7
7
|
[Example Rails application](https://github.com/grosser/gettext_i18n_rails_example)
|
8
8
|
|
9
9
|
Setup
|
10
10
|
=====
|
11
|
+
### 1. Install
|
11
12
|
sudo gem install grosser-fast_gettext -s http://gems.github.com/
|
12
13
|
|
13
14
|
Or from source:
|
14
15
|
git clone git://github.com/grosser/fast_gettext.git
|
15
16
|
cd fast_gettext && rake install
|
16
17
|
|
17
|
-
|
18
|
+
### 2. Add a translation repository
|
19
|
+
|
20
|
+
#### From mo files (traditional/default)
|
21
|
+
FastGettext.add_text_domain('my_app',:path=>'locale')
|
22
|
+
|
23
|
+
#### po files (less maintenacnce than mo)
|
24
|
+
FastGettext.add_text_domain('my_app',:path=>'locale', :type=>:po)
|
25
|
+
|
26
|
+
#### Database (odern/scaleable)
|
27
|
+
include FastGettext::TranslationRepository::Db.require_models #load and include default models
|
28
|
+
FastGettext.add_text_domain('my_app', :type=>:db, :model=>TranslationKey)
|
29
|
+
|
30
|
+
### 3. Choose text domain and locale for translation
|
31
|
+
Do this once in every Thread. (e.g. Rails -> ApplicationController)
|
18
32
|
FastGettext.text_domain = 'my_app'
|
19
33
|
FastGettext.available_locales = ['de','en','fr','en_US','en_UK'] # only allow these locales to be set (optional)
|
20
34
|
FastGettext.locale = 'de'
|
21
35
|
|
22
|
-
Start translating
|
36
|
+
### 4. Start translating
|
23
37
|
include FastGettext::Translation
|
24
38
|
_('Car') == 'Auto'
|
25
39
|
_('not-found') == 'not-found'
|
26
40
|
s_('Namespace|no-found') == 'not-found'
|
27
41
|
n_('Axis','Axis',3) == 'Achsen' #German plural of Axis
|
28
42
|
|
29
|
-
|
30
|
-
FastGettext.silence_errors
|
31
|
-
|
32
|
-
Translations
|
43
|
+
Managing translations
|
33
44
|
============
|
34
|
-
###
|
45
|
+
### mo/po-files
|
35
46
|
Generate .po or .mo files using GetText parser (example tasks at [gettext_i18n_rails](http://github.com/grosser/gettext_i18n_rails))
|
36
47
|
|
37
48
|
Tell Gettext where your .mo or .po files lie:
|
38
49
|
#e.g. for locale/de/my_app.po and locale/de/LC_MESSAGES/my_app.mo
|
39
|
-
#add :type=>:po and it will read directly from po files (not recommended for production since po-parsing can crash!)
|
40
50
|
FastGettext.add_text_domain('my_app',:path=>'locale')
|
41
51
|
|
42
|
-
|
43
|
-
|
52
|
+
Use the [original GetText](http://github.com/mutoh/gettext) to create and manage po/mo-files.
|
53
|
+
(Work on a po/mo parser & reader that is easier to use has started, contributions welcome @ [pomo](http://github.com/grosser/pomo) )
|
44
54
|
|
45
55
|
###Database
|
46
56
|
!!!new/only short time in production, please report back any ideas/suggestions you have!!!
|
47
|
-
Easy to maintain especially with many translations and multiple locales.
|
48
57
|
[Example migration for ActiveRecord](http://github.com/grosser/fast_gettext/blob/master/examples/db/migration.rb)
|
49
|
-
This is usable with any model DataMapper/Sequel or any other(non-database) backend, the only thing you need to do is respond to the self.translation(key, locale) call.
|
50
58
|
The default plural seperator is `||||` but you may overwrite it (or suggest a better one..).
|
51
|
-
include FastGettext::TranslationRepository::Db.require_models #load and include default models
|
52
|
-
FastGettext.add_text_domain('my_app', :type=>:db, :model=>TranslationKey)
|
53
59
|
|
60
|
+
This is usable with any model DataMapper/Sequel or any other(non-database) backend, the only thing you need to do is respond to the self.translation(key, locale) call.
|
54
61
|
If you want to use your own models, have a look at the [default models](http://github.com/grosser/fast_gettext/tree/master/lib/fast_gettext/translation_repository/db_models) to see what you want/need to implement.
|
55
62
|
|
63
|
+
To manage translations via a Web GUI, use a [Rails application and the translation_db_engine](http://github.com/grosser/translation_db_engine)
|
64
|
+
|
56
65
|
Performance
|
57
66
|
===========
|
58
67
|
50_000 translations speed / memory
|
@@ -73,18 +82,16 @@ small translation file <-> large translation file
|
|
73
82
|
ActiveSupport I18n::Backend::Simple :
|
74
83
|
21.770000s / 10100K <->
|
75
84
|
|
76
|
-
|
85
|
+
Rails
|
77
86
|
=======================
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
###Rails
|
82
|
-
Try the [gettext_i18n_rails plugin](http://github.com/grosser/gettext_i18n_rails), it simplifies the setup.
|
87
|
+
Try the [gettext_i18n_rails plugin](http://github.com/grosser/gettext_i18n_rails), it simplifies the setup.
|
88
|
+
Try the [translation_db_engine](http://github.com/grosser/translation_db_engine), to manage your translations in a db.
|
83
89
|
|
84
|
-
Setting `available_locales`,`text_domain` or `locale` will not work inside the `evironment.rb`,
|
85
|
-
then e.g. controllers, so set them inside your application_controller.
|
90
|
+
Setting `available_locales`,`text_domain` or `locale` will not work inside the `evironment.rb`,
|
91
|
+
since it runs in a different thread then e.g. controllers, so set them inside your application_controller.
|
86
92
|
|
87
93
|
#environment.rb after initializers
|
94
|
+
Object.send(:include,FastGettext::Translation)
|
88
95
|
FastGettext.add_text_domain('accounting',:path=>'locale')
|
89
96
|
FastGettext.add_text_domain('frontend',:path=>'locale')
|
90
97
|
...
|
@@ -99,11 +106,6 @@ then e.g. controllers, so set them inside your application_controller.
|
|
99
106
|
session[:locale] = I18n.locale = FastGettext.set_locale(params[:locale] || session[:locale] || request.env['HTTP_ACCEPT_LANGUAGE'] || 'en')
|
100
107
|
end
|
101
108
|
|
102
|
-
#application_helper.rb
|
103
|
-
module ApplicationHelper
|
104
|
-
include FastGettext::Translation
|
105
|
-
...
|
106
|
-
|
107
109
|
Advanced features
|
108
110
|
=================
|
109
111
|
###Abnormal pluralisation
|
@@ -156,8 +158,9 @@ FAQ
|
|
156
158
|
|
157
159
|
TODO
|
158
160
|
====
|
161
|
+
- add caching to untranslateable calls
|
162
|
+
- break with gettext naming-tradition, convert msgid => key, msgstr => translation
|
159
163
|
- some cleanup required, repositories should not have locale
|
160
|
-
- DbModel::TranslationKey responds_to? :available_locales should be false when it is not defined, maybe testing bug
|
161
164
|
- use `default_locale=(x)` internally, atm the default is available_locales.first || 'en'
|
162
165
|
- use `default_text_domain=(x)` internally, atm default is nil...
|
163
166
|
|
data/VERSION.yml
CHANGED
data/lib/fast_gettext/storage.rb
CHANGED
@@ -6,7 +6,7 @@ module FastGettext
|
|
6
6
|
module Storage
|
7
7
|
class NoTextDomainConfigured < RuntimeError
|
8
8
|
def to_s
|
9
|
-
"Current textdomain (#{FastGettext.text_domain.inspect}) was not added, use FastGettext.add_text_domain!"
|
9
|
+
"Current textdomain (#{FastGettext.text_domain.inspect}) was not added, use FastGettext.add_text_domain !"
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
@@ -67,6 +67,13 @@ module FastGettext
|
|
67
67
|
translation_repositories[text_domain] || raise(NoTextDomainConfigured)
|
68
68
|
end
|
69
69
|
|
70
|
+
def key_exist?(key)
|
71
|
+
false
|
72
|
+
translation = current_repository[key]
|
73
|
+
current_cache[key] ||= translation
|
74
|
+
!!translation
|
75
|
+
end
|
76
|
+
|
70
77
|
def locale
|
71
78
|
_locale || ( default_locale || (available_locales||[]).first || 'en' )
|
72
79
|
end
|
@@ -38,11 +38,11 @@ module FastGettext
|
|
38
38
|
|
39
39
|
#translate, but discard namespace if nothing was found
|
40
40
|
# Car|Tire -> Tire if no translation could be found
|
41
|
-
def s_(
|
42
|
-
if translation = FastGettext.current_repository[
|
41
|
+
def s_(key,seperator=nil)
|
42
|
+
if translation = FastGettext.current_cache[key] || FastGettext.current_repository[key]
|
43
43
|
translation
|
44
44
|
else
|
45
|
-
|
45
|
+
key.split(seperator||NAMESPACE_SEPERATOR).last
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
@@ -214,6 +214,31 @@ describe 'Storage' do
|
|
214
214
|
end
|
215
215
|
end
|
216
216
|
|
217
|
+
describe :key_exist? do
|
218
|
+
it "does not find default keys" do
|
219
|
+
_('abcde')
|
220
|
+
key_exist?('abcde').should be_false
|
221
|
+
end
|
222
|
+
|
223
|
+
it "finds using the current repository" do
|
224
|
+
should_receive(:current_repository).and_return 'xxx'=>'1'
|
225
|
+
key_exist?('xxx').should == true
|
226
|
+
end
|
227
|
+
|
228
|
+
it "sets the current cache with a found result" do
|
229
|
+
should_receive(:current_repository).and_return 'xxx'=>'1'
|
230
|
+
key_exist?('xxx')
|
231
|
+
current_cache['xxx'].should == '1'
|
232
|
+
end
|
233
|
+
|
234
|
+
it "does not overwrite an existing cache value" do
|
235
|
+
current_cache['xxx']='xxx'
|
236
|
+
should_receive(:current_repository).and_return 'xxx'=>'1'
|
237
|
+
key_exist?('xxx')
|
238
|
+
current_cache['xxx'].should == 'xxx'
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
217
242
|
describe NoTextDomainConfigured do
|
218
243
|
it "shows what to do" do
|
219
244
|
NoTextDomainConfigured.new.to_s.should =~ /FastGettext\.add_text_domain/
|
@@ -96,6 +96,21 @@ describe FastGettext::Translation do
|
|
96
96
|
end
|
97
97
|
|
98
98
|
describe :caching do
|
99
|
+
describe :cache_hit do
|
100
|
+
before do
|
101
|
+
FastGettext.translation_repositories.replace({})
|
102
|
+
current_cache['xxx'] = '1'
|
103
|
+
end
|
104
|
+
|
105
|
+
it "uses the cache when translating with _" do
|
106
|
+
_('xxx').should == '1'
|
107
|
+
end
|
108
|
+
|
109
|
+
it "uses the cache when translating with s_" do
|
110
|
+
s_('xxx').should == '1'
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
99
114
|
it "caches different locales seperatly" do
|
100
115
|
FastGettext.locale = 'en'
|
101
116
|
_('car').should == 'car'
|
data/spec/vendor/string_spec.rb
CHANGED
@@ -3,8 +3,18 @@ require File.join(current_folder,'..','spec_helper')
|
|
3
3
|
|
4
4
|
#just to make sure we did not mess up while copying...
|
5
5
|
describe String do
|
6
|
-
it "
|
7
|
-
"
|
6
|
+
it "does not translate twice" do
|
7
|
+
("%{a} %{b}" % {:a=>'%{b}',:b=>'c'}).should == '%{b} c'
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "old % style replacement" do
|
11
|
+
it "substitudes using % + Hash" do
|
12
|
+
"x%{name}y" %{:name=>'a'}.should == 'xay'
|
13
|
+
end
|
14
|
+
|
15
|
+
it "does not substitute after %%" do
|
16
|
+
("%%{num} oops" % {:num => 1}).should == '%{num} oops'
|
17
|
+
end
|
8
18
|
end
|
9
19
|
|
10
20
|
describe 'old sprintf style' do
|
@@ -22,6 +32,10 @@ describe String do
|
|
22
32
|
end
|
23
33
|
|
24
34
|
describe 'ruby 1.9 style %< replacement' do
|
35
|
+
it "does not substitute after %%" do
|
36
|
+
("%%<num> oops" % {:num => 1}).should == '%<num> oops'
|
37
|
+
end
|
38
|
+
|
25
39
|
it "subsitutes %<something>d" do
|
26
40
|
("x%<hello>dy" % {:hello=>1}).should == 'x1y'
|
27
41
|
end
|
@@ -29,7 +43,5 @@ describe String do
|
|
29
43
|
it "substitutes #b" do
|
30
44
|
("%<num>#b" % {:num => 1}).should == "0b1"
|
31
45
|
end
|
32
|
-
|
33
|
-
|
34
46
|
end
|
35
47
|
end
|
data/vendor/string.rb
CHANGED
@@ -15,6 +15,12 @@ rescue ArgumentError
|
|
15
15
|
class String
|
16
16
|
alias :_fast_gettext_old_format_m :% # :nodoc:
|
17
17
|
|
18
|
+
PERCENT_MATCH_RE = Regexp.union(
|
19
|
+
/%%/,
|
20
|
+
/%\{(\w+)\}/,
|
21
|
+
/%<(\w+)>(.*?\d*\.?\d*[bBdiouxXeEfgGcps])/
|
22
|
+
)
|
23
|
+
|
18
24
|
# call-seq:
|
19
25
|
# %(hash)
|
20
26
|
#
|
@@ -28,17 +34,17 @@ rescue ArgumentError
|
|
28
34
|
def %(args)
|
29
35
|
if args.kind_of? Hash
|
30
36
|
ret = dup
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
37
|
+
ret.gsub!(PERCENT_MATCH_RE) do |match|
|
38
|
+
if match == '%%'
|
39
|
+
'%'
|
40
|
+
elsif $1
|
41
|
+
key = $1.to_sym
|
42
|
+
args.has_key?(key) ? args[key] : match
|
43
|
+
elsif $2
|
44
|
+
key = $2.to_sym
|
45
|
+
args.has_key?(key) ? sprintf("%#{$3}", args[key]) : match
|
46
|
+
end
|
47
|
+
end
|
42
48
|
else
|
43
49
|
ret = gsub(/%([{<])/, '%%\1')
|
44
50
|
ret._fast_gettext_old_format_m(args)
|
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.4.
|
4
|
+
version: 0.4.8
|
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-05-
|
12
|
+
date: 2009-05-10 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|