nulogy-gettext_i18n_rails 0.4.6.1

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.
Files changed (33) hide show
  1. data/Gemfile +16 -0
  2. data/Gemfile.lock +126 -0
  3. data/Rakefile +24 -0
  4. data/Readme.md +226 -0
  5. data/VERSION +1 -0
  6. data/gettext_i18n_rails.gemspec +65 -0
  7. data/init.rb +14 -0
  8. data/lib/gettext_i18n_rails.rb +33 -0
  9. data/lib/gettext_i18n_rails/action_controller.rb +8 -0
  10. data/lib/gettext_i18n_rails/active_record.rb +19 -0
  11. data/lib/gettext_i18n_rails/backend.rb +67 -0
  12. data/lib/gettext_i18n_rails/base_parser.rb +41 -0
  13. data/lib/gettext_i18n_rails/haml_parser.rb +15 -0
  14. data/lib/gettext_i18n_rails/hamlet_parser.rb +16 -0
  15. data/lib/gettext_i18n_rails/html_safe_translations.rb +29 -0
  16. data/lib/gettext_i18n_rails/i18n_hacks.rb +25 -0
  17. data/lib/gettext_i18n_rails/model_attributes_finder.rb +108 -0
  18. data/lib/gettext_i18n_rails/railtie.rb +22 -0
  19. data/lib/gettext_i18n_rails/ruby_gettext_extractor.rb +144 -0
  20. data/lib/gettext_i18n_rails/slim_parser.rb +15 -0
  21. data/lib/gettext_i18n_rails/string_interpolate_fix.rb +20 -0
  22. data/lib/gettext_i18n_rails/tasks.rb +127 -0
  23. data/lib/tasks/gettext_rails_i18n.rake +1 -0
  24. data/spec/gettext_i18n_rails/action_controller_spec.rb +54 -0
  25. data/spec/gettext_i18n_rails/active_record_spec.rb +85 -0
  26. data/spec/gettext_i18n_rails/backend_spec.rb +56 -0
  27. data/spec/gettext_i18n_rails/haml_parser_spec.rb +39 -0
  28. data/spec/gettext_i18n_rails/hamlet_parser_spec.rb +33 -0
  29. data/spec/gettext_i18n_rails/slim_parser_spec.rb +40 -0
  30. data/spec/gettext_i18n_rails/string_interpolate_fix_spec.rb +32 -0
  31. data/spec/gettext_i18n_rails_spec.rb +84 -0
  32. data/spec/spec_helper.rb +39 -0
  33. metadata +110 -0
@@ -0,0 +1,15 @@
1
+ require 'gettext_i18n_rails/base_parser'
2
+
3
+ module GettextI18nRails
4
+ class SlimParser < BaseParser
5
+ def self.extension
6
+ "slim"
7
+ end
8
+
9
+ def self.convert_to_code(text)
10
+ Slim::Engine.new.call(text)
11
+ end
12
+ end
13
+ end
14
+
15
+ GetText::RGetText.add_parser(GettextI18nRails::SlimParser)
@@ -0,0 +1,20 @@
1
+ needed = "".respond_to?(:html_safe) and
2
+ (
3
+ "".html_safe % {:x => '<br/>'} == '<br/>' or
4
+ not ("".html_safe % {:x=>'a'}).html_safe?
5
+ )
6
+
7
+ if needed
8
+ class String
9
+ alias :interpolate_without_html_safe :%
10
+
11
+ def %(*args)
12
+ if args.first.is_a?(Hash) and html_safe?
13
+ safe_replacement = Hash[args.first.map{|k,v| [k,ERB::Util.h(v)] }]
14
+ interpolate_without_html_safe(safe_replacement).html_safe
15
+ else
16
+ interpolate_without_html_safe(*args).dup # make sure its not html_safe
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,127 @@
1
+ namespace :gettext do
2
+ def load_gettext
3
+ require 'gettext'
4
+ require 'gettext/utils'
5
+ end
6
+
7
+ desc "Create mo-files for L10n"
8
+ task :pack => :environment do
9
+ load_gettext
10
+ GetText.create_mofiles(true, locale_path, locale_path)
11
+ end
12
+
13
+ desc "Update pot/po files."
14
+ task :find => :environment do
15
+ load_gettext
16
+ $LOAD_PATH << File.join(File.dirname(__FILE__),'..','..','lib')
17
+ require 'gettext_i18n_rails/haml_parser'
18
+ require 'gettext_i18n_rails/slim_parser'
19
+ require 'gettext_i18n_rails/hamlet_parser'
20
+
21
+
22
+ if GetText.respond_to? :update_pofiles_org
23
+ if defined?(Rails.application)
24
+ msgmerge = Rails.application.config.gettext_i18n_rails.msgmerge
25
+ end
26
+ msgmerge ||= %w[--sort-output --no-location --no-wrap]
27
+
28
+ GetText.update_pofiles_org(
29
+ text_domain,
30
+ files_to_translate,
31
+ "version 0.0.1",
32
+ :po_root => locale_path,
33
+ :msgmerge => msgmerge
34
+ )
35
+ else #we are on a version < 2.0
36
+ puts "install new GetText with gettext:install to gain more features..."
37
+ #kill ar parser...
38
+ require 'gettext/parser/active_record'
39
+ module GetText
40
+ module ActiveRecordParser
41
+ module_function
42
+ def init(x);end
43
+ end
44
+ end
45
+
46
+ #parse files.. (models are simply parsed as ruby files)
47
+ GetText.update_pofiles(
48
+ text_domain,
49
+ files_to_translate,
50
+ "version 0.0.1",
51
+ locale_path
52
+ )
53
+ end
54
+ end
55
+
56
+ # This is more of an example, ignoring
57
+ # the columns/tables that mostly do not need translation.
58
+ # This can also be done with GetText::ActiveRecord
59
+ # but this crashed too often for me, and
60
+ # IMO which column should/should-not be translated does not
61
+ # belong into the model
62
+ #
63
+ # You can get your translations from GetText::ActiveRecord
64
+ # by adding this to you gettext:find task
65
+ #
66
+ # require 'active_record'
67
+ # gem "gettext_activerecord", '>=0.1.0' #download and install from github
68
+ # require 'gettext_activerecord/parser'
69
+ desc "write the model attributes to <locale_path>/model_attributes.rb"
70
+ task :store_model_attributes => :environment do
71
+ FastGettext.silence_errors
72
+
73
+ require 'gettext_i18n_rails/model_attributes_finder'
74
+ require 'gettext_i18n_rails/active_record'
75
+
76
+ storage_file = "#{locale_path}/model_attributes.rb"
77
+ puts "writing model translations to: #{storage_file}"
78
+
79
+ ignore_tables = [/^sitemap_/, /_versions$/, 'schema_migrations', 'sessions', 'delayed_jobs']
80
+ GettextI18nRails.store_model_attributes(
81
+ :to => storage_file,
82
+ :ignore_columns => ['id', 'type', 'created_at', 'updated_at'],
83
+ :ignore_tables => ignore_tables
84
+ )
85
+ end
86
+
87
+ desc "add a new language"
88
+ task :add_language, [:language] => :environment do |_, args|
89
+ language = args.language || ENV["LANGUAGE"]
90
+
91
+ # Let's do some pre-verification of the environment.
92
+ if language.nil?
93
+ puts "You need to specify the language to add. Either 'LANGUAGE=eo rake gettext:add_languange' or 'rake gettext:add_languange[eo]'"
94
+ next
95
+ end
96
+ pot = File.join(locale_path, "#{text_domain}.pot")
97
+ if !File.exists? pot
98
+ puts "You don't have a pot file yet, you probably should run 'rake gettext:find' at least once. Tried '#{pot}'."
99
+ next
100
+ end
101
+
102
+ # Create the directory for the new language.
103
+ dir = File.join(locale_path, language)
104
+ puts "Creating directory #{dir}"
105
+ Dir.mkdir dir
106
+
107
+ # Create the po file for the new language.
108
+ new_po = File.join(locale_path, language, "#{text_domain}.po")
109
+ puts "Initializing #{new_po} from #{pot}."
110
+ system "msginit --locale=#{language} --input=#{pot} --output=#{new_po}"
111
+ end
112
+
113
+ def locale_path
114
+ FastGettext.translation_repositories[text_domain].instance_variable_get(:@options)[:path]
115
+ rescue
116
+ File.join(Rails.root, "locale")
117
+ end
118
+
119
+ def text_domain
120
+ # if your textdomain is not 'app': require the environment before calling e.g. gettext:find OR add TEXTDOMAIN=my_domain
121
+ ENV['TEXTDOMAIN'] || (FastGettext.text_domain rescue nil) || "app"
122
+ end
123
+
124
+ def files_to_translate
125
+ Dir.glob("{app,lib,config,#{locale_path}}/**/*.{rb,erb,haml,slim}")
126
+ end
127
+ end
@@ -0,0 +1 @@
1
+ require File.join(File.dirname(__FILE__), "/../gettext_i18n_rails/tasks")
@@ -0,0 +1,54 @@
1
+ require "spec_helper"
2
+
3
+ FastGettext.silence_errors
4
+
5
+ describe ActionController::Base do
6
+ def reset!
7
+ fake_session = {}
8
+ @c.stub!(:session).and_return fake_session
9
+ fake_cookies = {}
10
+ @c.stub!(:cookies).and_return fake_cookies
11
+ @c.params = {}
12
+ @c.request = stub(:env => {})
13
+ end
14
+
15
+ before do
16
+ #controller
17
+ @c = ActionController::Base.new
18
+ reset!
19
+
20
+ #locale
21
+ FastGettext.available_locales = nil
22
+ FastGettext.locale = I18n.default_locale = 'fr'
23
+ FastGettext.available_locales = ['fr','en']
24
+ end
25
+
26
+ it "changes the locale" do
27
+ @c.params = {:locale=>'en'}
28
+ @c.set_gettext_locale
29
+ @c.session[:locale].should == 'en'
30
+ FastGettext.locale.should == 'en'
31
+ end
32
+
33
+ it "stays with default locale when none was found" do
34
+ @c.set_gettext_locale
35
+ @c.session[:locale].should == 'fr'
36
+ FastGettext.locale.should == 'fr'
37
+ end
38
+
39
+ it "locale isn't cached over request" do
40
+ @c.params = {:locale=>'en'}
41
+ @c.set_gettext_locale
42
+ @c.session[:locale].should == 'en'
43
+
44
+ reset!
45
+ @c.set_gettext_locale
46
+ @c.session[:locale].should == 'fr'
47
+ end
48
+
49
+ it "reads the locale from the HTTP_ACCEPT_LANGUAGE" do
50
+ @c.request.stub!(:env).and_return 'HTTP_ACCEPT_LANGUAGE'=>'de-de,de;q=0.8,en-us;q=0.5,en;q=0.3'
51
+ @c.set_gettext_locale
52
+ FastGettext.locale.should == 'en'
53
+ end
54
+ end
@@ -0,0 +1,85 @@
1
+ # coding: utf-8
2
+ require "spec_helper"
3
+
4
+ FastGettext.silence_errors
5
+
6
+ ActiveRecord::Base.establish_connection({
7
+ :adapter => "sqlite3",
8
+ :database => ":memory:",
9
+ })
10
+
11
+ ActiveRecord::Schema.define(:version => 1) do
12
+ create_table :car_seats, :force=>true do |t|
13
+ t.string :seat_color
14
+ end
15
+
16
+ create_table :parts, :force=>true do |t|
17
+ t.string :name
18
+ t.references :car_seat
19
+ end
20
+ end
21
+
22
+ ActiveRecord::Base.extend GettextI18nRails::ActiveRecord
23
+
24
+ class CarSeat < ActiveRecord::Base
25
+ validates_presence_of :seat_color, :message=>"translate me"
26
+ has_many :parts
27
+ accepts_nested_attributes_for :parts
28
+ end
29
+
30
+ class Part < ActiveRecord::Base
31
+ belongs_to :car_seat
32
+ end
33
+
34
+ describe ActiveRecord::Base do
35
+ before do
36
+ FastGettext.current_cache = {}
37
+ end
38
+
39
+ describe :human_name do
40
+ it "is translated through FastGettext" do
41
+ CarSeat.should_receive(:_).with('car seat').and_return('Autositz')
42
+ CarSeat.human_name.should == 'Autositz'
43
+ end
44
+ end
45
+
46
+ describe :human_attribute_name do
47
+ it "translates attributes through FastGettext" do
48
+ CarSeat.should_receive(:s_).with('CarSeat|Seat color').and_return('Sitz farbe')
49
+ CarSeat.human_attribute_name(:seat_color).should == 'Sitz farbe'
50
+ end
51
+
52
+ it "translates nested attributes through FastGettext" do
53
+ CarSeat.should_receive(:s_).with('CarSeat|Parts|Name').and_return('Handle')
54
+ CarSeat.human_attribute_name(:"parts.name").should == 'Handle'
55
+ end
56
+ end
57
+
58
+ describe 'error messages' do
59
+ let(:model){
60
+ c = CarSeat.new
61
+ c.valid?
62
+ c
63
+ }
64
+
65
+ it "translates error messages" do
66
+ FastGettext.stub!(:current_repository).and_return('translate me'=>"Übersetz mich!")
67
+ FastGettext._('translate me').should == "Übersetz mich!"
68
+ model.errors[:seat_color].should == ["Übersetz mich!"]
69
+ end
70
+
71
+ it "translates scoped error messages" do
72
+ pending 'scope is no longer added in 3.x' if ActiveRecord::VERSION::MAJOR >= 3
73
+ FastGettext.stub!(:current_repository).and_return('activerecord.errors.translate me'=>"Übersetz mich!")
74
+ FastGettext._('activerecord.errors.translate me').should == "Übersetz mich!"
75
+ model.errors[:seat_color].should == ["Übersetz mich!"]
76
+ end
77
+
78
+ it "translates error messages with %{fn}" do
79
+ pending
80
+ FastGettext.stub!(:current_repository).and_return('translate me'=>"Übersetz %{fn} mich!")
81
+ FastGettext._('translate me').should == "Übersetz %{fn} mich!"
82
+ model.errors[:seat_color].should == ["Übersetz car_seat mich!"]
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,56 @@
1
+ require "spec_helper"
2
+
3
+ FastGettext.silence_errors
4
+
5
+ describe GettextI18nRails::Backend do
6
+ it "redirects calls to another I18n backend" do
7
+ subject.backend.should_receive(:xxx).with(1,2)
8
+ subject.xxx(1,2)
9
+ end
10
+
11
+ describe :available_locales do
12
+ it "maps them to FastGettext" do
13
+ FastGettext.should_receive(:available_locales).and_return [:xxx]
14
+ subject.available_locales.should == [:xxx]
15
+ end
16
+
17
+ it "and returns an empty array when FastGettext.available_locales is nil" do
18
+ FastGettext.should_receive(:available_locales).and_return nil
19
+ subject.available_locales.should == []
20
+ end
21
+ end
22
+
23
+ describe :translate do
24
+ it "uses gettext when the key is translatable" do
25
+ FastGettext.stub(:current_repository).and_return 'xy.z.u'=>'a'
26
+ subject.translate('xx','u',:scope=>['xy','z']).should == 'a'
27
+ end
28
+
29
+ it "interpolates options" do
30
+ FastGettext.stub(:current_repository).and_return 'ab.c'=>'a%{a}b'
31
+ subject.translate('xx','c',:scope=>['ab'], :a => 'X').should == 'aXb'
32
+ end
33
+
34
+ it "can translate with gettext using symbols" do
35
+ FastGettext.stub(:current_repository).and_return 'xy.z.v'=>'a'
36
+ subject.translate('xx',:v ,:scope=>['xy','z']).should == 'a'
37
+ end
38
+
39
+ it "can translate with gettext using a flat scope" do
40
+ FastGettext.stub(:current_repository).and_return 'xy.z.x'=>'a'
41
+ subject.translate('xx',:x ,:scope=>'xy.z').should == 'a'
42
+ end
43
+
44
+ # TODO NameError is raised <-> wtf ?
45
+ xit "uses the super when the key is not translatable" do
46
+ lambda{subject.translate('xx','y',:scope=>['xy','z'])}.should raise_error(I18n::MissingTranslationData)
47
+ end
48
+ end
49
+
50
+ describe :interpolate do
51
+ it "act as an identity function for an array" do
52
+ translation = [:month, :day, :year]
53
+ subject.send(:interpolate, translation, {}).should == translation
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,39 @@
1
+ require "spec_helper"
2
+ require "gettext_i18n_rails/haml_parser"
3
+
4
+ describe GettextI18nRails::HamlParser do
5
+ let(:parser){ GettextI18nRails::HamlParser }
6
+
7
+ describe "#target?" do
8
+ it "targets .haml" do
9
+ parser.target?('foo/bar/xxx.haml').should == true
10
+ end
11
+
12
+ it "does not target anything else" do
13
+ parser.target?('foo/bar/xxx.erb').should == false
14
+ end
15
+ end
16
+
17
+ describe "#parse" do
18
+ it "finds messages in haml" do
19
+ with_file '= _("xxxx")' do |path|
20
+ parser.parse(path, []).should == [
21
+ ["xxxx", "#{path}:1"]
22
+ ]
23
+ end
24
+ end
25
+
26
+ it "ignores 1.9 errors" do
27
+ with_file '= _("xxxx", x: 1)' do |path|
28
+ $stderr.should_receive(:puts).with{|x| x =~ /file ignored/ }
29
+ parser.parse(path, [1]).should == [1]
30
+ end
31
+ end
32
+
33
+ it "does not find messages in text" do
34
+ with_file '_("xxxx")' do |path|
35
+ parser.parse(path, []).should == []
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,33 @@
1
+ require "spec_helper"
2
+ require "gettext_i18n_rails/hamlet_parser"
3
+
4
+ describe GettextI18nRails::HamletParser do
5
+ let(:parser){ GettextI18nRails::HamletParser }
6
+
7
+ describe "#target?" do
8
+ it "targets .hamlet" do
9
+ parser.target?('foo/bar/xxx.hamlet').should == true
10
+ end
11
+
12
+ it "does not target anything else" do
13
+ parser.target?('foo/bar/xxx.erb').should == false
14
+ end
15
+ end
16
+
17
+ describe "#parse" do
18
+ it "finds messages in slim" do
19
+ with_file '<div>= _("xxxx")' do |path|
20
+ parser.parse(path, []).should == [
21
+ ["xxxx", "#{path}:1"]
22
+ ]
23
+ end
24
+ end
25
+
26
+ it "does not find messages in text" do
27
+ with_file '<div> _("xxxx")' do |path|
28
+ parser.parse(path, []).should == []
29
+ end
30
+ end
31
+ end
32
+ end
33
+
@@ -0,0 +1,40 @@
1
+ require "spec_helper"
2
+ require "gettext_i18n_rails/slim_parser"
3
+
4
+ describe GettextI18nRails::SlimParser do
5
+ let(:parser){ GettextI18nRails::SlimParser }
6
+
7
+ describe "#target?" do
8
+ it "targets .slim" do
9
+ parser.target?('foo/bar/xxx.slim').should == true
10
+ end
11
+
12
+ it "does not target anything else" do
13
+ parser.target?('foo/bar/xxx.erb').should == false
14
+ end
15
+ end
16
+
17
+ describe "#parse" do
18
+ it "finds messages in slim" do
19
+ with_file 'div = _("xxxx")' do |path|
20
+ parser.parse(path, []).should == [
21
+ ["xxxx", "#{path}:1"]
22
+ ]
23
+ end
24
+ end
25
+
26
+ xit "can parse 1.9 syntax" do
27
+ with_file 'div = _("xxxx", foo: :bar)' do |path|
28
+ parser.parse(path, []).should == [
29
+ ["xxxx", "#{path}:1"]
30
+ ]
31
+ end
32
+ end
33
+
34
+ it "does not find messages in text" do
35
+ with_file 'div _("xxxx")' do |path|
36
+ parser.parse(path, []).should == []
37
+ end
38
+ end
39
+ end
40
+ end