simple_localizer 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem 'activerecord'
4
+
5
+ group :development do
6
+ gem "rspec", "~> 2.8.0"
7
+ gem "bundler", "~> 1.0.0"
8
+ gem "jeweler", "~> 1.8.4"
9
+ gem 'database_cleaner'
10
+ gem 'sqlite3'
11
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,51 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activemodel (3.2.7)
5
+ activesupport (= 3.2.7)
6
+ builder (~> 3.0.0)
7
+ activerecord (3.2.7)
8
+ activemodel (= 3.2.7)
9
+ activesupport (= 3.2.7)
10
+ arel (~> 3.0.2)
11
+ tzinfo (~> 0.3.29)
12
+ activesupport (3.2.7)
13
+ i18n (~> 0.6)
14
+ multi_json (~> 1.0)
15
+ arel (3.0.2)
16
+ builder (3.0.0)
17
+ database_cleaner (0.8.0)
18
+ diff-lcs (1.1.3)
19
+ git (1.2.5)
20
+ i18n (0.6.0)
21
+ jeweler (1.8.4)
22
+ bundler (~> 1.0)
23
+ git (>= 1.2.5)
24
+ rake
25
+ rdoc
26
+ json (1.7.4)
27
+ multi_json (1.3.6)
28
+ rake (0.9.2.2)
29
+ rdoc (3.12)
30
+ json (~> 1.4)
31
+ rspec (2.8.0)
32
+ rspec-core (~> 2.8.0)
33
+ rspec-expectations (~> 2.8.0)
34
+ rspec-mocks (~> 2.8.0)
35
+ rspec-core (2.8.0)
36
+ rspec-expectations (2.8.0)
37
+ diff-lcs (~> 1.1.2)
38
+ rspec-mocks (2.8.0)
39
+ sqlite3 (1.3.6)
40
+ tzinfo (0.3.33)
41
+
42
+ PLATFORMS
43
+ ruby
44
+
45
+ DEPENDENCIES
46
+ activerecord
47
+ bundler (~> 1.0.0)
48
+ database_cleaner
49
+ jeweler (~> 1.8.4)
50
+ rspec (~> 2.8.0)
51
+ sqlite3
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 vad4msiu
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.
data/README.md ADDED
@@ -0,0 +1,58 @@
1
+ # Simple Localizer
2
+
3
+ Simple localization your ActiveRecord fields without magic.
4
+
5
+ ## Installation
6
+
7
+ ```ruby
8
+ source 'https://rubygems.org'
9
+
10
+ gem 'simple_localizer'
11
+ ```
12
+
13
+ ## Model translations
14
+
15
+ ```ruby
16
+ class Product < ActiveRecord::Base
17
+ translates :name
18
+ end
19
+ ```
20
+
21
+ ```ruby
22
+ product = Product.create! :name_en => 'a'
23
+ puts product.name_en # => a
24
+ product.name_en = 'b'
25
+ product.save!
26
+ puts product.name_en # => b
27
+ product.update_attributes :name_en => 'c'
28
+ puts product.name_en # => c
29
+
30
+ I18n.default_locale = :en
31
+ product = Product.create! :name => 'd'
32
+ puts product.name # => d
33
+ puts product.name_en # => d
34
+
35
+ I18n::Backend::Simple.include(I18n::Backend::Fallbacks)
36
+ I18n.fallbacks[:ru] = [:ru, :en, :fr]
37
+ product = Product.create! :name_fr => 'e', :name_ru => nil, :name_en => nil
38
+ puts product.name_ru # => e
39
+ ```
40
+
41
+ ## Supported locales
42
+
43
+ aa ab ae af al am ar as ay az
44
+ ba be bg bh bi bn bo bp br ca
45
+ cf ch co cs cy de dr dt dz ef
46
+ eg ej el en eo ep er es et eu
47
+ fa fi fj fo fr fy ga gd gl gn
48
+ gu ha he hi hm hr hu hy ia ie
49
+ ik in is it iw ja ji jv ka kk
50
+ kl km kn ko ks ku ky la ln lo
51
+ lt lv mg mi mk ml mn mo mr ms
52
+ mt my na ne nl no nt oc of og
53
+ om or pa pl pn ps pt qu re rm
54
+ rn ro ru rw sa sd sf sg sh si
55
+ sk sl sm sn so sq sr ss st su
56
+ sv sw ta te tg th ti tj tk tl
57
+ tn to tp tr ts tt tw uk ul ur
58
+ uz vi vo wo xh yo zh zu
data/Rakefile ADDED
@@ -0,0 +1,47 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ gem.name = "simple_localizer"
17
+ gem.homepage = "https://github.com/vad4msiu/simple_localizer.git"
18
+ gem.license = "MIT"
19
+ gem.summary = %Q{Simple localization your ActiveRecord fields without magic}
20
+ gem.description = %Q{Simple localization your ActiveRecord fields without magic}
21
+ gem.email = "vad4msiu@gmail.com"
22
+ gem.authors = ["vad4msiu"]
23
+ end
24
+ Jeweler::RubygemsDotOrgTasks.new
25
+
26
+ task :default => :spec
27
+
28
+ namespace :db do
29
+ require 'active_record'
30
+
31
+ config = YAML.load_file File.expand_path(File.join(File.dirname(__FILE__), 'spec', 'database.yml'))
32
+ ActiveRecord::Base.establish_connection(config.merge('schema_search_path' => 'public'))
33
+
34
+ desc 'Run migrations'
35
+ task :migrate do
36
+ ActiveRecord::Migration.create_table :products do |t|
37
+ t.timestamps
38
+ end
39
+
40
+ ActiveRecord::Migration.create_table :product_translations do |t|
41
+ t.string :locale
42
+ t.string :name
43
+ t.integer :product_id
44
+ t.timestamps
45
+ end
46
+ end
47
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,107 @@
1
+ # encoding: UTF-8
2
+
3
+ require "active_record"
4
+
5
+ module SimpleLocalizer
6
+ SUPPORTED_LOCALES = %w(
7
+ aa ab ae af al am ar as ay az
8
+ ba be bg bh bi bn bo bp br ca
9
+ cf ch co cs cy de dr dt dz ef
10
+ eg ej el en eo ep er es et eu
11
+ fa fi fj fo fr fy ga gd gl gn
12
+ gu ha he hi hm hr hu hy ia ie
13
+ ik in is it iw ja ji jv ka kk
14
+ kl km kn ko ks ku ky la ln lo
15
+ lt lv mg mi mk ml mn mo mr ms
16
+ mt my na ne nl no nt oc of og
17
+ om or pa pl pn ps pt qu re rm
18
+ rn ro ru rw sa sd sf sg sh si
19
+ sk sl sm sn so sq sr ss st su
20
+ sv sw ta te tg th ti tj tk tl
21
+ tn to tp tr ts tt tw uk ul ur
22
+ uz vi vo wo xh yo zh zu
23
+ )
24
+
25
+ module ClassMethods
26
+ def translates *columns
27
+ underscore_name = name.underscore
28
+ translation_class = const_set(:Translation, Class.new(ActiveRecord::Base))
29
+ translated_attribute_names = columns.map &:to_s
30
+
31
+ translation_class.table_name = "#{underscore_name}_translations"
32
+ translation_class.belongs_to underscore_name
33
+ translation_class.validates :locale, :presence => true
34
+ translation_class.validates :locale, :uniqueness => { :scope => ["#{underscore_name}_id"] }
35
+
36
+ has_many(:translations,
37
+ :class_name => translation_class.name,
38
+ :dependent => :destroy,
39
+ :autosave => true
40
+ )
41
+
42
+ translated_attribute_names.each do |attr|
43
+ define_method attr do
44
+ locale = SimpleLocalizer.read_locale || I18n.default_locale.to_s
45
+ send("#{attr}_#{locale}")
46
+ end
47
+
48
+ define_method "#{attr}=" do |value|
49
+ locale = SimpleLocalizer.read_locale || I18n.default_locale.to_s
50
+ send("#{attr}_#{locale}=", value)
51
+ end
52
+
53
+ SimpleLocalizer::SUPPORTED_LOCALES.each do |locale|
54
+ define_method "#{attr}_#{locale}" do
55
+ translation = translations.detect { |translation|
56
+ translation.locale == locale
57
+ }
58
+
59
+ if I18n.respond_to?(:fallbacks) && translation.try(attr).nil?
60
+ fallbacks_locales = I18n.fallbacks[locale.to_sym]
61
+ translation = translations.detect { |translation|
62
+ fallbacks_locales.include? translation.locale.to_sym
63
+ }
64
+ end
65
+
66
+ translation.try(attr)
67
+ end
68
+
69
+ define_method "#{attr}_#{locale}=" do |value|
70
+ translation = translations.detect { |translation|
71
+ translation.locale == locale
72
+ }
73
+ translation ||= translations.build :locale => locale
74
+ translation.send("#{attr}=", value)
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ module_function
82
+
83
+ def with_locale(new_locale, &block)
84
+ begin
85
+ pre_locale = read_locale
86
+ set_locale(new_locale)
87
+ yield
88
+ ensure
89
+ set_locale(pre_locale)
90
+ end
91
+ end
92
+
93
+ def read_locale
94
+ Thread.current[:simple_localizer_locale]
95
+ end
96
+
97
+ private
98
+
99
+ module_function
100
+
101
+ def set_locale(locale)
102
+ Thread.current[:simple_localizer_locale] = locale && locale.to_s
103
+ end
104
+
105
+ end
106
+
107
+ ActiveRecord::Base.extend SimpleLocalizer::ClassMethods
@@ -0,0 +1,66 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "simple_localizer"
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["vad4msiu"]
12
+ s.date = "2012-08-10"
13
+ s.description = "Simple localization your ActiveRecord fields without magic"
14
+ s.email = "vad4msiu@gmail.com"
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.md"
18
+ ]
19
+ s.files = [
20
+ "Gemfile",
21
+ "Gemfile.lock",
22
+ "LICENSE.txt",
23
+ "README.md",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "lib/simple_localizer.rb",
27
+ "simple_localizer.gemspec",
28
+ "spec/database.yml",
29
+ "spec/db/test.sqlite3",
30
+ "spec/simple_localizer_spec.rb",
31
+ "spec/spec_helper.rb"
32
+ ]
33
+ s.homepage = "https://github.com/vad4msiu/simple_localizer.git"
34
+ s.licenses = ["MIT"]
35
+ s.require_paths = ["lib"]
36
+ s.rubygems_version = "1.8.17"
37
+ s.summary = "Simple localization your ActiveRecord fields without magic"
38
+
39
+ if s.respond_to? :specification_version then
40
+ s.specification_version = 3
41
+
42
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
43
+ s.add_runtime_dependency(%q<activerecord>, [">= 0"])
44
+ s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
45
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
46
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
47
+ s.add_development_dependency(%q<database_cleaner>, [">= 0"])
48
+ s.add_development_dependency(%q<sqlite3>, [">= 0"])
49
+ else
50
+ s.add_dependency(%q<activerecord>, [">= 0"])
51
+ s.add_dependency(%q<rspec>, ["~> 2.8.0"])
52
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
53
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
54
+ s.add_dependency(%q<database_cleaner>, [">= 0"])
55
+ s.add_dependency(%q<sqlite3>, [">= 0"])
56
+ end
57
+ else
58
+ s.add_dependency(%q<activerecord>, [">= 0"])
59
+ s.add_dependency(%q<rspec>, ["~> 2.8.0"])
60
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
61
+ s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
62
+ s.add_dependency(%q<database_cleaner>, [">= 0"])
63
+ s.add_dependency(%q<sqlite3>, [">= 0"])
64
+ end
65
+ end
66
+
data/spec/database.yml ADDED
@@ -0,0 +1,4 @@
1
+ adapter: sqlite3
2
+ database: spec/db/test.sqlite3
3
+ pool: 5
4
+ timeout: 5000
Binary file
@@ -0,0 +1,92 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
4
+
5
+ class Product < ActiveRecord::Base
6
+ translates :name
7
+ end
8
+
9
+ describe SimpleLocalizer do
10
+ it "должен выполнить блок с установленным языком" do
11
+ product = Product.create! :name_fr => 'qwe', :name_en => 'asd'
12
+ SimpleLocalizer.with_locale(:fr) do
13
+ product.name.should == 'qwe'
14
+ end
15
+ end
16
+ end
17
+
18
+ describe Product::Translation do
19
+ describe "валидация" do
20
+ before(:each) do
21
+ @translation = Product::Translation.new
22
+ end
23
+
24
+ it "не должен быть валидным если поле локали пустое" do
25
+ @translation.valid?.should be_false
26
+ @translation.errors['locale'].should be_include "can't be blank"
27
+ end
28
+
29
+ it "не должен быть валидным если поле для belongs_to связи не уникальное в скопе с полем locale" do
30
+ Product::Translation.create! :locale => 'ru', :product_id => 123, :name => 'asd'
31
+ @translation.locale = 'ru'
32
+ @translation.name = 'qwe'
33
+ @translation.product_id = 123
34
+ @translation.valid?.should be_false
35
+ @translation.errors['locale'].should be_include "has already been taken"
36
+ end
37
+ end
38
+ end
39
+
40
+ describe Product do
41
+ describe "после обвноления" do
42
+ before(:each) do
43
+ @product = Product.create! :name_ru => 'asd'
44
+ end
45
+
46
+ it "должен обновлять перевод" do
47
+ @product.update_attributes :name_ru => 'qwe'
48
+ @product.translations.first.name.should == 'qwe'
49
+ end
50
+
51
+ it "должен добавить новый перевод" do
52
+ @product.translations.count.should == 1
53
+ @product.update_attributes :name_en => 'qwe'
54
+ @product.translations.count.should == 2
55
+ end
56
+ end
57
+
58
+ describe "после создания" do
59
+ before(:each) do
60
+ @product = Product.create! :name_ru => 'asd'
61
+ end
62
+
63
+ it "должен создать несколько переводов" do
64
+ product = Product.create! :name_ru => 'asd', :name_en => 'asd'
65
+ product.translations.count.should == 2
66
+ end
67
+
68
+ it "должен создать перевод с заданной локалью" do
69
+ @product.translations.count.should == 1
70
+ end
71
+
72
+ it "локаль в созданном переводе должна равняться заданной при создании" do
73
+ @product.translations.first.locale.should == 'ru'
74
+ end
75
+
76
+ it "значение в переводе должено равняться переданному при создании" do
77
+ @product.translations.first.name.should == 'asd'
78
+ end
79
+ end
80
+
81
+ it "должен отдать с fallback локалью" do
82
+ I18n::Backend::Simple.include(I18n::Backend::Fallbacks)
83
+ I18n.fallbacks[:ru] = [:ru, :en, :fr]
84
+ product = Product.create! :name_fr => 'asd', :name_ru => nil, :name_en => nil
85
+ product.name_ru.should == 'asd'
86
+ end
87
+
88
+ it "должен создать перевод с локалью I18n.default_locale" do
89
+ product = Product.create! :name => 'asd'
90
+ product.translations.first.locale == I18n.default_locale
91
+ end
92
+ end
@@ -0,0 +1,27 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+ require 'rspec'
4
+ require 'simple_localizer'
5
+ require 'database_cleaner'
6
+ require 'logger'
7
+ require 'pp'
8
+
9
+ config = YAML.load_file File.expand_path(File.join(File.dirname(__FILE__), 'database.yml'))
10
+ ActiveRecord::Base.establish_connection config
11
+
12
+ I18n.default_locale = :ru
13
+ I18n.locale = :en
14
+
15
+ RSpec.configure do |config|
16
+ config.before(:suite) do
17
+ DatabaseCleaner.strategy = :transaction
18
+ end
19
+
20
+ config.before(:each) do
21
+ DatabaseCleaner.start
22
+ end
23
+
24
+ config.after(:each) do
25
+ DatabaseCleaner.clean
26
+ end
27
+ end
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simple_localizer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - vad4msiu
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-10 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activerecord
16
+ requirement: &70306244922640 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70306244922640
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ requirement: &70306244922020 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: 2.8.0
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70306244922020
36
+ - !ruby/object:Gem::Dependency
37
+ name: bundler
38
+ requirement: &70306244921440 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ~>
42
+ - !ruby/object:Gem::Version
43
+ version: 1.0.0
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70306244921440
47
+ - !ruby/object:Gem::Dependency
48
+ name: jeweler
49
+ requirement: &70306244920740 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.8.4
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70306244920740
58
+ - !ruby/object:Gem::Dependency
59
+ name: database_cleaner
60
+ requirement: &70306244934620 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70306244934620
69
+ - !ruby/object:Gem::Dependency
70
+ name: sqlite3
71
+ requirement: &70306244933760 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70306244933760
80
+ description: Simple localization your ActiveRecord fields without magic
81
+ email: vad4msiu@gmail.com
82
+ executables: []
83
+ extensions: []
84
+ extra_rdoc_files:
85
+ - LICENSE.txt
86
+ - README.md
87
+ files:
88
+ - Gemfile
89
+ - Gemfile.lock
90
+ - LICENSE.txt
91
+ - README.md
92
+ - Rakefile
93
+ - VERSION
94
+ - lib/simple_localizer.rb
95
+ - simple_localizer.gemspec
96
+ - spec/database.yml
97
+ - spec/db/test.sqlite3
98
+ - spec/simple_localizer_spec.rb
99
+ - spec/spec_helper.rb
100
+ homepage: https://github.com/vad4msiu/simple_localizer.git
101
+ licenses:
102
+ - MIT
103
+ post_install_message:
104
+ rdoc_options: []
105
+ require_paths:
106
+ - lib
107
+ required_ruby_version: !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ! '>='
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ segments:
114
+ - 0
115
+ hash: -348099263649400343
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ none: false
118
+ requirements:
119
+ - - ! '>='
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ requirements: []
123
+ rubyforge_project:
124
+ rubygems_version: 1.8.17
125
+ signing_key:
126
+ specification_version: 3
127
+ summary: Simple localization your ActiveRecord fields without magic
128
+ test_files: []