arena-i18n-active_record 0.0.4

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,72 @@
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
+ require 'i18n/backend/active_record'
47
+ I18n.backend = I18n::Backend::ActiveRecord.new
48
+ </pre>
49
+
50
+ A more adavanced example (Thanks Moritz), which uses YAML files and ActiveRecord for lookups:
51
+
52
+ <pre>
53
+ require 'i18n/backend/active_record'
54
+ I18n.backend = I18n::Backend::ActiveRecord.new
55
+
56
+ I18n::Backend::ActiveRecord.send(:include, I18n::Backend::Memoize)
57
+ I18n::Backend::ActiveRecord.send(:include, I18n::Backend::Flatten)
58
+ I18n::Backend::Simple.send(:include, I18n::Backend::Memoize)
59
+ I18n::Backend::Simple.send(:include, I18n::Backend::Pluralization)
60
+
61
+ I18n.backend = I18n::Backend::Chain.new(I18n::Backend::Simple.new, I18n.backend)
62
+ </pre>
63
+
64
+ h2. Usage
65
+
66
+ You can now use @I18n.t('Your String')@ to lookup translations in the database.
67
+
68
+ h2. Maintainers
69
+
70
+ * Sven Fuchs
71
+
72
+
@@ -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
@@ -0,0 +1 @@
1
+ require 'i18n'
@@ -0,0 +1,6 @@
1
+ module I18n
2
+ module ActiveRecord
3
+ VERSION = "0.0.4"
4
+ end
5
+ end
6
+
@@ -0,0 +1,62 @@
1
+ require 'i18n/backend/base'
2
+ require 'i18n/backend/active_record/translation'
3
+
4
+ module I18n
5
+ module Backend
6
+ class ActiveRecord
7
+ autoload :Missing, 'i18n/backend/active_record/missing'
8
+ autoload :StoreProcs, 'i18n/backend/active_record/store_procs'
9
+ autoload :Translation, 'i18n/backend/active_record/translation'
10
+
11
+ module Implementation
12
+ include Base, Flatten
13
+
14
+ def available_locales
15
+ begin
16
+ Translation.available_locales
17
+ rescue ::ActiveRecord::StatementInvalid
18
+ []
19
+ end
20
+ end
21
+
22
+ def store_translations(locale, data, options = {})
23
+ escape = options.fetch(:escape, true)
24
+ flatten_translations(locale, data, escape, false).each do |key, value|
25
+ Translation.locale(locale).lookup(expand_keys(key)).delete_all
26
+ Translation.create(:locale => locale.to_s, :key => key.to_s, :value => value)
27
+ end
28
+ end
29
+
30
+ protected
31
+
32
+ def lookup(locale, key, scope = [], options = {})
33
+ key = normalize_flat_keys(locale, key, scope, options[:separator])
34
+ result = Translation.locale(locale).lookup(key).all
35
+
36
+ if result.empty?
37
+ nil
38
+ elsif result.first.key == key
39
+ result.first.value
40
+ else
41
+ chop_range = (key.size + FLATTEN_SEPARATOR.size)..-1
42
+ result = result.inject({}) do |hash, r|
43
+ hash[r.key.slice(chop_range)] = r.value
44
+ hash
45
+ end
46
+ result.deep_symbolize_keys
47
+ end
48
+ end
49
+
50
+ # For a key :'foo.bar.baz' return ['foo', 'foo.bar', 'foo.bar.baz']
51
+ def expand_keys(key)
52
+ key.to_s.split(FLATTEN_SEPARATOR).inject([]) do |keys, key|
53
+ keys << [keys.last, key].compact.join(FLATTEN_SEPARATOR)
54
+ end
55
+ end
56
+ end
57
+
58
+ include Implementation
59
+ end
60
+ end
61
+ end
62
+
@@ -0,0 +1,66 @@
1
+ # This extension stores translation stub records for missing translations to
2
+ # the database.
3
+ #
4
+ # This is useful if you have a web based translation tool. It will populate
5
+ # the database with untranslated keys as the application is being used. A
6
+ # translator can then go through these and add missing translations.
7
+ #
8
+ # Example usage:
9
+ #
10
+ # I18n::Backend::Chain.send(:include, I18n::Backend::ActiveRecord::Missing)
11
+ # I18n.backend = I18n::Backend::Chain.new(I18n::Backend::ActiveRecord.new, I18n::Backend::Simple.new)
12
+ #
13
+ # Stub records for pluralizations will also be created for each key defined
14
+ # in i18n.plural.keys.
15
+ #
16
+ # For example:
17
+ #
18
+ # # en.yml
19
+ # en:
20
+ # i18n:
21
+ # plural:
22
+ # keys: [:zero, :one, :other]
23
+ #
24
+ # # pl.yml
25
+ # pl:
26
+ # i18n:
27
+ # plural:
28
+ # keys: [:zero, :one, :few, :other]
29
+ #
30
+ # It will also persist interpolation keys in Translation#interpolations so
31
+ # translators will be able to review and use them.
32
+ module I18n
33
+ module Backend
34
+ class ActiveRecord
35
+ module Missing
36
+ include Flatten
37
+
38
+ def store_default_translations(locale, key, options = {})
39
+ count, scope, default, separator = options.values_at(:count, :scope, :default, :separator)
40
+ separator ||= I18n.default_separator
41
+ key = normalize_flat_keys(locale, key, scope, separator)
42
+
43
+ unless ActiveRecord::Translation.locale(locale).lookup(key).exists?
44
+ interpolations = options.keys - I18n::RESERVED_KEYS
45
+ keys = count ? I18n.t('i18n.plural.keys', :locale => locale).map { |k| [key, k].join(FLATTEN_SEPARATOR) } : [key]
46
+ keys.each { |key| store_default_translation(locale, key, interpolations) }
47
+ end
48
+ end
49
+
50
+ def store_default_translation(locale, key, interpolations)
51
+ translation = ActiveRecord::Translation.new :locale => locale.to_s, :key => key
52
+ translation.interpolations = interpolations
53
+ translation.save
54
+ end
55
+
56
+ def translate(locale, key, options = {})
57
+ super
58
+ rescue I18n::MissingTranslationData => e
59
+ self.store_default_translations(locale, key, options)
60
+ raise e
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+
@@ -0,0 +1,39 @@
1
+ # This module is intended to be mixed into the ActiveRecord backend to allow
2
+ # storing Ruby Procs as translation values in the database.
3
+ #
4
+ # I18n.backend = I18n::Backend::ActiveRecord.new
5
+ # I18n::Backend::ActiveRecord::Translation.send(:include, I18n::Backend::ActiveRecord::StoreProcs)
6
+ #
7
+ # The StoreProcs module requires the ParseTree and ruby2ruby gems and therefor
8
+ # was extracted from the original backend.
9
+ #
10
+ # ParseTree is not compatible with Ruby 1.9.
11
+
12
+ begin
13
+ require 'ruby2ruby'
14
+ require 'parse_tree'
15
+ require 'parse_tree_extensions'
16
+ rescue LoadError => e
17
+ puts "can't use StoreProcs because: #{e.message}"
18
+ end
19
+
20
+ module I18n
21
+ module Backend
22
+ class ActiveRecord
23
+ module StoreProcs
24
+ def value=(v)
25
+ case v
26
+ when Proc
27
+ write_attribute(:value, v.to_ruby)
28
+ write_attribute(:is_proc, true)
29
+ else
30
+ write_attribute(:value, v)
31
+ end
32
+ end
33
+
34
+ Translation.send(:include, self) if method(:to_s).respond_to?(:to_ruby)
35
+ end
36
+ end
37
+ end
38
+ end
39
+
@@ -0,0 +1,111 @@
1
+ require 'active_record'
2
+
3
+ module I18n
4
+ module Backend
5
+ # ActiveRecord model used to store actual translations to the database.
6
+ #
7
+ # This model expects a table like the following to be already set up in
8
+ # your the database:
9
+ #
10
+ # create_table :translations do |t|
11
+ # t.string :locale
12
+ # t.string :key
13
+ # t.text :value
14
+ # t.text :interpolations
15
+ # t.boolean :is_proc, :default => false
16
+ # end
17
+ #
18
+ # This model supports to named scopes :locale and :lookup. The :locale
19
+ # scope simply adds a condition for a given locale:
20
+ #
21
+ # I18n::Backend::ActiveRecord::Translation.locale(:en).all
22
+ # # => all translation records that belong to the :en locale
23
+ #
24
+ # The :lookup scope adds a condition for looking up all translations
25
+ # that either start with the given keys (joined by an optionally given
26
+ # separator or I18n.default_separator) or that exactly have this key.
27
+ #
28
+ # # with translations present for :"foo.bar" and :"foo.baz"
29
+ # I18n::Backend::ActiveRecord::Translation.lookup(:foo)
30
+ # # => an array with both translation records :"foo.bar" and :"foo.baz"
31
+ #
32
+ # I18n::Backend::ActiveRecord::Translation.lookup([:foo, :bar])
33
+ # I18n::Backend::ActiveRecord::Translation.lookup(:"foo.bar")
34
+ # # => an array with the translation record :"foo.bar"
35
+ #
36
+ # When the StoreProcs module was mixed into this model then Procs will
37
+ # be stored to the database as Ruby code and evaluated when :value is
38
+ # called.
39
+ #
40
+ # Translation = I18n::Backend::ActiveRecord::Translation
41
+ # Translation.create \
42
+ # :locale => 'en'
43
+ # :key => 'foo'
44
+ # :value => lambda { |key, options| 'FOO' }
45
+ # Translation.find_by_locale_and_key('en', 'foo').value
46
+ # # => 'FOO'
47
+ class ActiveRecord
48
+ class Translation < ::ActiveRecord::Base
49
+ TRUTHY_CHAR = "\001"
50
+ FALSY_CHAR = "\002"
51
+
52
+ self.table_name = 'translations'
53
+ attr_protected :is_proc, :interpolations
54
+
55
+ serialize :value
56
+ serialize :interpolations, Array
57
+
58
+ class << self
59
+ def locale(locale)
60
+ scoped(:conditions => { :locale => locale.to_s })
61
+ end
62
+
63
+ def lookup(keys, *separator)
64
+ column_name = connection.quote_column_name('key')
65
+ keys = Array(keys).map! { |key| key.to_s }
66
+
67
+ unless separator.empty?
68
+ warn "[DEPRECATION] Giving a separator to Translation.lookup is deprecated. " <<
69
+ "You can change the internal separator by overwriting FLATTEN_SEPARATOR."
70
+ end
71
+
72
+ namespace = "#{keys.last}#{I18n::Backend::Flatten::FLATTEN_SEPARATOR}%"
73
+ scoped(:conditions => ["#{column_name} IN (?) OR #{column_name} LIKE ?", keys, namespace])
74
+ end
75
+
76
+ def available_locales
77
+ Translation.find(:all, :select => 'DISTINCT locale').map { |t| t.locale.to_sym }
78
+ end
79
+ end
80
+
81
+ def interpolates?(key)
82
+ self.interpolations.include?(key) if self.interpolations
83
+ end
84
+
85
+ def value
86
+ value = read_attribute(:value)
87
+ if is_proc
88
+ Kernel.eval(value)
89
+ elsif value == FALSY_CHAR
90
+ false
91
+ elsif value == TRUTHY_CHAR
92
+ true
93
+ else
94
+ value
95
+ end
96
+ end
97
+
98
+ def value=(value)
99
+ if value === false
100
+ value = FALSY_CHAR
101
+ elsif value === true
102
+ value = TRUTHY_CHAR
103
+ end
104
+
105
+ write_attribute(:value, value)
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+
@@ -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 ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: arena-i18n-active_record
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.4
6
+ platform: ruby
7
+ authors:
8
+ - Sven Fuchs
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2012-07-11 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: i18n
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.5.0
24
+ type: :runtime
25
+ version_requirements: *id001
26
+ description: I18n ActiveRecord backend. Allows to store translations in a database using ActiveRecord, e.g. for providing a web-interface for managing translations.
27
+ email: svenfuchs@artweb-design.de
28
+ executables: []
29
+
30
+ extensions: []
31
+
32
+ extra_rdoc_files: []
33
+
34
+ files:
35
+ - ci/Gemfile.rails-3.x
36
+ - ci/Gemfile.rails-3.x.lock
37
+ - lib/i18n/active_record/version.rb
38
+ - lib/i18n/active_record.rb
39
+ - lib/i18n/backend/active_record/missing.rb
40
+ - lib/i18n/backend/active_record/store_procs.rb
41
+ - lib/i18n/backend/active_record/translation.rb
42
+ - lib/i18n/backend/active_record.rb
43
+ - test/active_record_test.rb
44
+ - test/all.rb
45
+ - test/api_test.rb
46
+ - test/missing_test.rb
47
+ - test/test_helper.rb
48
+ - test/test_setup.rb
49
+ - MIT-LICENSE
50
+ - README.textile
51
+ - Rakefile
52
+ homepage: http://github.com/arenaflowers/i18n-active_record
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options: []
57
+
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ requirements: []
73
+
74
+ rubyforge_project: "[none]"
75
+ rubygems_version: 1.8.24
76
+ signing_key:
77
+ specification_version: 3
78
+ summary: I18n ActiveRecord backend
79
+ test_files: []
80
+
81
+ has_rdoc: