i18n-active_record 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,21 @@
1
+ Copyright (c) 2010 Sven Fuchs <svenfuchs@artweb-design.de>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+
@@ -0,0 +1,70 @@
1
+ h1. I18n::Backend::ActiveRecord
2
+
3
+ This repository contains the I18n ActiveRecord backend and support code that has been extracted from the "I18n":http://github.com/svenfuchs/i18n.
4
+
5
+ h2. Installation
6
+
7
+ For Bundler put the following in your Gemfile:
8
+
9
+ <pre>
10
+ gem 'i18n-active_record',
11
+ :git => 'git://github.com/svenfuchs/i18n-active_record.git',
12
+ :require => 'i18n/active_record'
13
+ </pre>
14
+
15
+ Next create a active record model named @Translation@ with the Rails Generator.
16
+ Your migration should look like this:
17
+
18
+ <pre>
19
+ class CreateTranslations < ActiveRecord::Migration
20
+ def self.up
21
+ create_table :translations do |t|
22
+ t.string :locale
23
+ t.string :key
24
+ t.text :value
25
+ t.text :interpolations
26
+ t.boolean :is_proc, :default => false
27
+
28
+ t.timestamps
29
+ end
30
+ end
31
+
32
+ def self.down
33
+ drop_table :translations
34
+ end
35
+ end
36
+ </pre>
37
+
38
+ With this translation model you will be able to manage your translation, and add new translations or languages through
39
+ it.
40
+
41
+ To load @I18n::Backend::ActiveRecord@ into your Rails application, create a new file in *config/initializers* named *locale.rb*.
42
+
43
+ A simple configuration for your locale.rb could look like this:
44
+
45
+ <pre>
46
+ I18n.backend = I18n::Backend::Database.new
47
+ </pre>
48
+
49
+ A more adavanced example (Thanks Moritz), which uses YAML files and ActiveRecord for lookups:
50
+
51
+ <pre>
52
+ I18n.backend = I18n::Backend::ActiveRecord.new
53
+
54
+ I18n::Backend::ActiveRecord.send(:include, I18n::Backend::Memoize)
55
+ I18n::Backend::ActiveRecord.send(:include, I18n::Backend::Flatten)
56
+ I18n::Backend::Simple.send(:include, I18n::Backend::Memoize)
57
+ I18n::Backend::Simple.send(:include, I18n::Backend::Pluralization)
58
+
59
+ I18n.backend = I18n::Backend::Chain.new(I18n::Backend::Simple.new, I18n.backend)
60
+ </pre>
61
+
62
+ h2. Usage
63
+
64
+ You can now use @I18n.t('Your String')@ to lookup translations in the database.
65
+
66
+ h2. Maintainers
67
+
68
+ * Sven Fuchs
69
+
70
+
@@ -0,0 +1,10 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.libs << 'lib'
6
+ t.pattern = 'test/**/*_test.rb'
7
+ t.verbose = false
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,10 @@
1
+ source :rubygems
2
+
3
+ # gem 'i18n', '~> 0.5.0'
4
+ gem 'i18n', :path => '~/Development/projects/i18n/i18n'
5
+
6
+ gem 'activerecord', '~> 3.0.0'
7
+ gem 'activesupport', '~> 3.0.0'
8
+ gem 'sqlite3-ruby'
9
+ gem 'mocha'
10
+
@@ -0,0 +1,36 @@
1
+ PATH
2
+ remote: ~/Development/projects/i18n/i18n
3
+ specs:
4
+ i18n (0.4.2)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ activemodel (3.0.1)
10
+ activesupport (= 3.0.1)
11
+ builder (~> 2.1.2)
12
+ i18n (~> 0.4.1)
13
+ activerecord (3.0.1)
14
+ activemodel (= 3.0.1)
15
+ activesupport (= 3.0.1)
16
+ arel (~> 1.0.0)
17
+ tzinfo (~> 0.3.23)
18
+ activesupport (3.0.1)
19
+ arel (1.0.1)
20
+ activesupport (~> 3.0.0)
21
+ builder (2.1.2)
22
+ mocha (0.9.9)
23
+ rake
24
+ rake (0.8.7)
25
+ sqlite3-ruby (1.3.1)
26
+ tzinfo (0.3.23)
27
+
28
+ PLATFORMS
29
+ ruby
30
+
31
+ DEPENDENCIES
32
+ activerecord (~> 3.0.0)
33
+ activesupport (~> 3.0.0)
34
+ i18n!
35
+ mocha
36
+ sqlite3-ruby
@@ -1,6 +1,6 @@
1
1
  module I18n
2
2
  module ActiveRecord
3
- VERSION = "0.0.1"
3
+ VERSION = "0.0.2"
4
4
  end
5
5
  end
6
6
 
@@ -0,0 +1,54 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ class I18nBackendActiveRecordTest < Test::Unit::TestCase
4
+ def setup
5
+ I18n.backend = I18n::Backend::ActiveRecord.new
6
+ store_translations(:en, :foo => { :bar => 'bar', :baz => 'baz' })
7
+ end
8
+
9
+ def teardown
10
+ I18n::Backend::ActiveRecord::Translation.destroy_all
11
+ super
12
+ end
13
+
14
+ test "store_translations does not allow ambiguous keys (1)" do
15
+ I18n::Backend::ActiveRecord::Translation.delete_all
16
+ I18n.backend.store_translations(:en, :foo => 'foo')
17
+ I18n.backend.store_translations(:en, :foo => { :bar => 'bar' })
18
+ I18n.backend.store_translations(:en, :foo => { :baz => 'baz' })
19
+
20
+ translations = I18n::Backend::ActiveRecord::Translation.locale(:en).lookup('foo').all
21
+ assert_equal %w(bar baz), translations.map(&:value)
22
+
23
+ assert_equal({ :bar => 'bar', :baz => 'baz' }, I18n.t(:foo))
24
+ end
25
+
26
+ test "store_translations does not allow ambiguous keys (2)" do
27
+ I18n::Backend::ActiveRecord::Translation.delete_all
28
+ I18n.backend.store_translations(:en, :foo => { :bar => 'bar' })
29
+ I18n.backend.store_translations(:en, :foo => { :baz => 'baz' })
30
+ I18n.backend.store_translations(:en, :foo => 'foo')
31
+
32
+ translations = I18n::Backend::ActiveRecord::Translation.locale(:en).lookup('foo').all
33
+ assert_equal %w(foo), translations.map(&:value)
34
+
35
+ assert_equal 'foo', I18n.t(:foo)
36
+ end
37
+
38
+ test "can store translations with keys that are translations containing special chars" do
39
+ I18n.backend.store_translations(:es, :"Pagina's" => "Pagina's" )
40
+ assert_equal "Pagina's", I18n.t(:"Pagina's", :locale => :es)
41
+ end
42
+
43
+ with_mocha do
44
+ test "missing translations table does not cause an error in #available_locales" do
45
+ I18n::Backend::ActiveRecord::Translation.expects(:available_locales).raises(::ActiveRecord::StatementInvalid)
46
+ assert_equal [], I18n.backend.available_locales
47
+ end
48
+ end
49
+
50
+ def test_expand_keys
51
+ assert_equal %w(foo foo.bar foo.bar.baz), I18n.backend.send(:expand_keys, :'foo.bar.baz')
52
+ end
53
+ end if defined?(ActiveRecord)
54
+
@@ -0,0 +1,7 @@
1
+ dir = File.dirname(__FILE__)
2
+ $:.unshift(dir)
3
+
4
+ Dir["#{dir}/**/*_test.rb"].sort.each do |file|
5
+ require file.sub(/^#{dir}\/(.*)\.rb$/, '\1')
6
+ end
7
+
@@ -0,0 +1,30 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ class I18nActiveRecordApiTest < Test::Unit::TestCase
4
+ def setup
5
+ I18n.backend = I18n::Backend::ActiveRecord.new
6
+ super
7
+ end
8
+
9
+ def self.can_store_procs?
10
+ I18n::Backend::ActiveRecord.included_modules.include?(I18n::Backend::ActiveRecord::StoreProcs)
11
+ end
12
+
13
+ include I18n::Tests::Basics
14
+ include I18n::Tests::Defaults
15
+ include I18n::Tests::Interpolation
16
+ include I18n::Tests::Link
17
+ include I18n::Tests::Lookup
18
+ include I18n::Tests::Pluralization
19
+ include I18n::Tests::Procs if can_store_procs?
20
+
21
+ include I18n::Tests::Localization::Date
22
+ include I18n::Tests::Localization::DateTime
23
+ include I18n::Tests::Localization::Time
24
+ include I18n::Tests::Localization::Procs if can_store_procs?
25
+
26
+ test "make sure we use an ActiveRecord backend" do
27
+ assert_equal I18n::Backend::ActiveRecord, I18n.backend.class
28
+ end
29
+ end if defined?(ActiveRecord)
30
+
@@ -0,0 +1,71 @@
1
+ require File.expand_path('../test_helper', __FILE__)
2
+
3
+ class I18nActiveRecordMissingTest < Test::Unit::TestCase
4
+ class Backend < I18n::Backend::ActiveRecord
5
+ include I18n::Backend::ActiveRecord::Missing
6
+ end
7
+
8
+ def setup
9
+ I18n.backend.store_translations(:en, :bar => 'Bar', :i18n => { :plural => { :keys => [:zero, :one, :other] } })
10
+ I18n.backend = I18n::Backend::Chain.new(Backend.new, I18n.backend)
11
+ I18n::Backend::ActiveRecord::Translation.delete_all
12
+ end
13
+
14
+ test "can persist interpolations" do
15
+ translation = I18n::Backend::ActiveRecord::Translation.new(:key => 'foo', :value => 'bar', :locale => :en)
16
+ translation.interpolations = %w(count name)
17
+ translation.save
18
+ assert translation.valid?
19
+ end
20
+
21
+ test "lookup persists the key" do
22
+ I18n.t('foo.bar.baz')
23
+ assert_equal 1, I18n::Backend::ActiveRecord::Translation.count
24
+ assert I18n::Backend::ActiveRecord::Translation.locale(:en).find_by_key('foo.bar.baz')
25
+ end
26
+
27
+ test "lookup does not persist the key twice" do
28
+ 2.times { I18n.t('foo.bar.baz') }
29
+ assert_equal 1, I18n::Backend::ActiveRecord::Translation.count
30
+ assert I18n::Backend::ActiveRecord::Translation.locale(:en).find_by_key('foo.bar.baz')
31
+ end
32
+
33
+ test "lookup persists interpolation keys when looked up directly" do
34
+ I18n.t('foo.bar.baz', :cow => "lucy" ) # creates stub translation.
35
+ translation_stub = I18n::Backend::ActiveRecord::Translation.locale(:en).lookup('foo.bar.baz').first
36
+ assert translation_stub.interpolates?(:cow)
37
+ end
38
+
39
+ test "creates one stub per pluralization" do
40
+ I18n.t('foo', :count => 999)
41
+ translations = I18n::Backend::ActiveRecord::Translation.locale(:en).find_all_by_key %w{ foo.zero foo.one foo.other }
42
+ assert_equal 3, translations.length
43
+ end
44
+
45
+ test "creates no stub for base key in pluralization" do
46
+ I18n.t('foo', :count => 999)
47
+ assert_equal 3, I18n::Backend::ActiveRecord::Translation.locale(:en).lookup("foo").count
48
+ assert !I18n::Backend::ActiveRecord::Translation.locale(:en).find_by_key("foo")
49
+ end
50
+
51
+ test "creates a stub when a custom separator is used" do
52
+ I18n.t('foo|baz', :separator => '|')
53
+ I18n::Backend::ActiveRecord::Translation.locale(:en).lookup("foo.baz").first.update_attributes!(:value => 'baz!')
54
+ assert_equal 'baz!', I18n.t('foo|baz', :separator => '|')
55
+ end
56
+
57
+ test "creates a stub per pluralization when a custom separator is used" do
58
+ I18n.t('foo|bar', :count => 999, :separator => '|')
59
+ translations = I18n::Backend::ActiveRecord::Translation.locale(:en).find_all_by_key %w{ foo.bar.zero foo.bar.one foo.bar.other }
60
+ assert_equal 3, translations.length
61
+ end
62
+
63
+ test "creates a stub when a custom separator is used and the key contains the flatten separator (a dot character)" do
64
+ key = 'foo|baz.zab'
65
+ I18n.t(key, :separator => '|')
66
+ I18n::Backend::ActiveRecord::Translation.locale(:en).lookup("foo.baz\001zab").first.update_attributes!(:value => 'baz!')
67
+ assert_equal 'baz!', I18n.t(key, :separator => '|')
68
+ end
69
+
70
+ end if defined?(ActiveRecord)
71
+
@@ -0,0 +1,56 @@
1
+ require 'test_setup'
2
+
3
+ I18n::Tests.parse_options!
4
+ require 'bundler/setup'
5
+ $:.unshift File.expand_path("../lib", File.dirname(__FILE__))
6
+ require 'i18n/active_record'
7
+ require 'i18n/tests'
8
+ require 'mocha'
9
+ I18n::Tests.setup_active_record
10
+
11
+ class Test::Unit::TestCase
12
+ def self.test(name, &block)
13
+ test_name = "test_#{name.gsub(/\s+/,'_')}".to_sym
14
+ defined = instance_method(test_name) rescue false
15
+ raise "#{test_name} is already defined in #{self}" if defined
16
+ if block_given?
17
+ define_method(test_name, &block)
18
+ else
19
+ define_method(test_name) do
20
+ flunk "No implementation provided for #{name}"
21
+ end
22
+ end
23
+ end
24
+
25
+ def self.with_mocha
26
+ yield if Object.respond_to?(:expects)
27
+ end
28
+
29
+ def teardown
30
+ I18n.locale = nil
31
+ I18n.default_locale = :en
32
+ I18n.load_path = []
33
+ I18n.available_locales = nil
34
+ I18n.backend = nil
35
+ end
36
+
37
+ def translations
38
+ I18n.backend.instance_variable_get(:@translations)
39
+ end
40
+
41
+ def store_translations(*args)
42
+ data = args.pop
43
+ locale = args.pop || :en
44
+ I18n.backend.store_translations(locale, data)
45
+ end
46
+
47
+ def locales_dir
48
+ File.dirname(__FILE__) + '/test_data/locales'
49
+ end
50
+ end
51
+
52
+ Object.class_eval do
53
+ def meta_class
54
+ class << self; self; end
55
+ end
56
+ end unless Object.method_defined?(:meta_class)
@@ -0,0 +1,92 @@
1
+ $KCODE = 'u' if RUBY_VERSION <= '1.9'
2
+
3
+ require 'rubygems'
4
+ require 'test/unit'
5
+ require 'optparse'
6
+
7
+ # Do not load the i18n gem from libraries like active_support.
8
+ #
9
+ # This is required for testing against Rails 2.3 because active_support/vendor.rb#24 tries
10
+ # to load I18n using the gem method. Instead, we want to test the local library of course.
11
+ alias :gem_for_ruby_19 :gem # for 1.9. gives a super ugly seg fault otherwise
12
+ def gem(gem_name, *version_requirements)
13
+ puts("skipping loading the i18n gem ...") && return if gem_name =='i18n'
14
+ super(gem_name, *version_requirements)
15
+ end
16
+
17
+ module I18n
18
+ module Tests
19
+ class << self
20
+ def options
21
+ @options ||= { :with => [], :adapter => 'sqlite3' }
22
+ end
23
+
24
+ def parse_options!
25
+ OptionParser.new do |o|
26
+ o.on('-w', '--with DEPENDENCIES', 'Define dependencies') do |dep|
27
+ options[:with] = dep.split(',').map { |group| group.to_sym }
28
+ end
29
+ end.parse!
30
+
31
+ options[:with].each do |dep|
32
+ case dep
33
+ when :sqlite3, :mysql, :postgres
34
+ @options[:adapter] = dep
35
+ when :r23, :'rails-2.3.x'
36
+ ENV['BUNDLE_GEMFILE'] = 'ci/Gemfile.rails-2.3.x'
37
+ when :r3, :'rails-3.0.x'
38
+ ENV['BUNDLE_GEMFILE'] = 'ci/Gemfile.rails-3.x'
39
+ when :'no-rails'
40
+ ENV['BUNDLE_GEMFILE'] = 'ci/Gemfile.no-rails'
41
+ end
42
+ end
43
+
44
+ ENV['BUNDLE_GEMFILE'] ||= 'ci/Gemfile.all'
45
+ end
46
+
47
+ def setup_active_record
48
+ begin
49
+ require 'active_record'
50
+ ActiveRecord::Base.connection
51
+ true
52
+ rescue LoadError => e
53
+ puts "can't use ActiveRecord backend because: #{e.message}"
54
+ rescue ActiveRecord::ConnectionNotEstablished
55
+ require 'i18n/backend/active_record'
56
+ require 'i18n/backend/active_record/store_procs'
57
+ connect_active_record
58
+ true
59
+ end
60
+ end
61
+
62
+ def connect_active_record
63
+ connect_adapter
64
+ ActiveRecord::Migration.verbose = false
65
+ ActiveRecord::Schema.define(:version => 1) do
66
+ create_table :translations, :force => true do |t|
67
+ t.string :locale
68
+ t.string :key
69
+ t.text :value
70
+ t.text :interpolations
71
+ t.boolean :is_proc, :default => false
72
+ end
73
+ add_index :translations, [:locale, :key], :unique => true
74
+ end
75
+ end
76
+
77
+ def connect_adapter
78
+ case options[:adapter].to_sym
79
+ when :sqlite3
80
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
81
+ when :mysql
82
+ # CREATE DATABASE i18n_unittest;
83
+ # CREATE USER 'i18n'@'localhost' IDENTIFIED BY '';
84
+ # GRANT ALL PRIVILEGES ON i18n_unittest.* to 'i18n'@'localhost';
85
+ ActiveRecord::Base.establish_connection(:adapter => "mysql", :database => "i18n_unittest", :username => "i18n", :password => "", :host => "localhost")
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+
92
+
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i18n-active_record
3
3
  version: !ruby/object:Gem::Version
4
- hash: 29
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
10
- version: 0.0.1
9
+ - 2
10
+ version: 0.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Sven Fuchs
@@ -15,10 +15,25 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-12-07 00:00:00 +08:00
18
+ date: 2010-12-27 00:00:00 +01:00
19
19
  default_executable:
20
- dependencies: []
21
-
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: i18n
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 11
30
+ segments:
31
+ - 0
32
+ - 5
33
+ - 0
34
+ version: 0.5.0
35
+ type: :runtime
36
+ version_requirements: *id001
22
37
  description: "[description]"
23
38
  email: svenfuchs@artweb-design.de
24
39
  executables: []
@@ -28,12 +43,23 @@ extensions: []
28
43
  extra_rdoc_files: []
29
44
 
30
45
  files:
31
- - lib/i18n/active_record.rb
46
+ - ci/Gemfile.rails-3.x
47
+ - ci/Gemfile.rails-3.x.lock
32
48
  - lib/i18n/active_record/version.rb
33
- - lib/i18n/backend/active_record.rb
49
+ - lib/i18n/active_record.rb
34
50
  - lib/i18n/backend/active_record/missing.rb
35
51
  - lib/i18n/backend/active_record/store_procs.rb
36
52
  - lib/i18n/backend/active_record/translation.rb
53
+ - lib/i18n/backend/active_record.rb
54
+ - test/active_record_test.rb
55
+ - test/all.rb
56
+ - test/api_test.rb
57
+ - test/missing_test.rb
58
+ - test/test_helper.rb
59
+ - test/test_setup.rb
60
+ - MIT-LICENSE
61
+ - README.textile
62
+ - Rakefile
37
63
  has_rdoc: true
38
64
  homepage: http://github.com/svenfuchs/i18n-active_record
39
65
  licenses: []