lolita-translation 0.3.3 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +25 -0
- data/Gemfile +2 -18
- data/README.md +1 -2
- data/Rakefile +1 -49
- data/app/assets/javascripts/lolita/translation/application.js +4 -3
- data/app/assets/stylesheets/lolita/translation/application.css +7 -1
- data/app/views/components/lolita/translation/_assets.html.haml +4 -0
- data/app/views/components/lolita/translation/_language_wrap.html.haml +2 -0
- data/app/views/components/lolita/translation/_switch.html.haml +4 -0
- data/lib/lolita-translation.rb +40 -33
- data/lib/lolita-translation/builder/abstract_builder.rb +103 -0
- data/lib/lolita-translation/builder/active_record_builder.rb +106 -0
- data/lib/lolita-translation/builder/mongoid_builder.rb +0 -0
- data/lib/lolita-translation/configuration.rb +41 -166
- data/lib/lolita-translation/errors.rb +15 -0
- data/lib/lolita-translation/locale.rb +32 -0
- data/lib/lolita-translation/locales.rb +62 -0
- data/lib/lolita-translation/lolita/component_hooks.rb +49 -0
- data/lib/lolita-translation/lolita/tab_extension.rb +113 -0
- data/lib/lolita-translation/migrator.rb +56 -0
- data/lib/lolita-translation/migrators/active_record_migrator.rb +93 -0
- data/lib/lolita-translation/migrators/mongoid_migrator.rb +81 -0
- data/lib/lolita-translation/orm/mixin.rb +57 -0
- data/lib/lolita-translation/rails.rb +6 -31
- data/lib/lolita-translation/record.rb +220 -0
- data/lib/lolita-translation/translated_string.rb +11 -0
- data/lib/lolita-translation/translation_class_builder.rb +59 -0
- data/lib/lolita-translation/utils.rb +13 -0
- data/lib/lolita-translation/version.rb +32 -0
- data/lib/tasks/lolita_translation.rake +14 -0
- data/lolita-translation.gemspec +24 -71
- data/spec/ar_schema.rb +90 -0
- data/spec/header.rb +14 -0
- data/spec/integrations/active_record_integration_spec.rb +218 -0
- data/spec/lolita-translation/builder/abstract_builder_spec.rb +67 -0
- data/spec/lolita-translation/builder/active_record_builder_spec.rb +40 -0
- data/spec/lolita-translation/configuration_spec.rb +72 -0
- data/spec/lolita-translation/locale_spec.rb +25 -0
- data/spec/lolita-translation/locales_spec.rb +31 -0
- data/spec/lolita-translation/lolita/tab_extension_spec.rb +61 -0
- data/spec/lolita-translation/migrator_spec.rb +42 -0
- data/spec/lolita-translation/migrators/active_record_migrator_spec.rb +50 -0
- data/spec/lolita-translation/orm/mixin_spec.rb +52 -0
- data/spec/lolita-translation/record_spec.rb +112 -0
- data/spec/lolita-translation/translation_class_builder_spec.rb +62 -0
- data/spec/lolita_translation_spec.rb +16 -0
- data/spec/rails_helper.rb +6 -0
- data/spec/requests/record_language_switch_spec.rb +16 -0
- data/spec/requests/record_saving_spec.rb +63 -0
- data/spec/spec_helper.rb +38 -90
- data/spec/tasks/lolita_translation_spec.rb +32 -0
- data/spec/test_app/app/controllers/application_controller.rb +3 -0
- data/spec/test_app/app/models/category.rb +6 -0
- data/spec/test_app/app/models/post.rb +8 -0
- data/spec/test_app/config/application.rb +24 -0
- data/spec/test_app/config/boot.rb +11 -0
- data/spec/test_app/config/database.yml +3 -0
- data/spec/test_app/config/enviroment.rb +5 -0
- data/spec/test_app/config/enviroments/development.rb +44 -0
- data/spec/test_app/config/initializers/lolita_translation.rb +4 -0
- data/spec/test_app/config/initializers/token.rb +7 -0
- data/spec/test_app/config/routes.rb +4 -0
- data/spec/test_app/db/.gitkeep +0 -0
- data/spec/test_app/log/.gitkeep +0 -0
- metadata +193 -46
- data/.document +0 -5
- data/VERSION +0 -1
- data/app/views/components/lolita/translation/_assets.html.erb +0 -7
- data/app/views/components/lolita/translation/_language_wrap.html.erb +0 -4
- data/app/views/components/lolita/translation/_switch.html.erb +0 -8
- data/lib/generators/lolita_translation/USAGE +0 -8
- data/lib/generators/lolita_translation/has_translations_generator.rb +0 -8
- data/lib/lolita-translation/model.rb +0 -100
- data/lib/lolita-translation/modules.rb +0 -130
- data/lib/lolita-translation/string.rb +0 -19
- data/lib/tasks/has_translations_tasks.rake +0 -4
- data/spec/has_translations_spec.rb +0 -43
data/.document
DELETED
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
0.3.3
|
@@ -1,4 +0,0 @@
|
|
1
|
-
<% locale = tab_form.object.respond_to?(:locale) ? tab_form.object.locale : ::I18n.default_locale %>
|
2
|
-
<div class="language-wrap" id="<%=locale%>_attributes_for_<%= tab.name %>" style="display:<%=locale == ::I18n.default_locale ? "block" : "none"%>">
|
3
|
-
<%=content %>
|
4
|
-
</div>
|
@@ -1,8 +0,0 @@
|
|
1
|
-
<ul class="tab-language-switch" id="<%=tab.name%>_language_swith">
|
2
|
-
<% I18n.available_locales.sort.each do |short_locale| %>
|
3
|
-
<% active = I18n.default_locale == short_locale %>
|
4
|
-
<li class="<%=active ? "active" : ""%>" data-locale="<%=short_locale%>" data-tab="<%=tab.name%>">
|
5
|
-
<%= short_locale.to_s.capitalize %>
|
6
|
-
</li>
|
7
|
-
<% end %>
|
8
|
-
</ul>
|
@@ -1,100 +0,0 @@
|
|
1
|
-
module Lolita
|
2
|
-
module Translation
|
3
|
-
class ClassFactory
|
4
|
-
|
5
|
-
def self.create(class_name, parent, superclass=nil, &block)
|
6
|
-
first,*other = class_name.split("::")
|
7
|
-
if other.empty?
|
8
|
-
klass = superclass ? Class.new(superclass, &block) : Class.new(&block)
|
9
|
-
parent.const_set(first, klass)
|
10
|
-
else
|
11
|
-
klass = Class.new
|
12
|
-
parent = unless parent.const_defined?(first)
|
13
|
-
parent.const_set(first, klass)
|
14
|
-
else
|
15
|
-
first.constantize
|
16
|
-
end
|
17
|
-
self.create(other.join('::'), parent, superclass, &block)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
module ModelInstanceMethods
|
23
|
-
# override validate to vaidate only translate fields from master Class
|
24
|
-
def validate
|
25
|
-
item = self.class.name.sub('Translation','').constantize.new(self.attributes.clone.delete_if{|k,_| !self.class.translate_attrs.include?(k.to_sym)})
|
26
|
-
item_adapter = Lolita::DBI::Base.create(item.class)
|
27
|
-
self_adapter = Lolita::DBI::Base.create(self.class)
|
28
|
-
was_table_name = item_adapter.collection_name
|
29
|
-
item_adapter.collection_name = self_adapter.collection_name
|
30
|
-
item.valid? rescue
|
31
|
-
self.class.translate_attrs.each do |attr|
|
32
|
-
errors_on_attr = item.errors.on(attr)
|
33
|
-
self.errors.add(attr,errors_on_attr) if errors_on_attr
|
34
|
-
end
|
35
|
-
item_adapter.collection_name = was_table_name
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
module ModelClassMethods
|
40
|
-
# sets real master_id it's aware of STI
|
41
|
-
def extract_master_id name
|
42
|
-
master_class = name.sub('Translation','').constantize
|
43
|
-
#FIXME why need to check superclass ?
|
44
|
-
class_name = master_class.name #!master_class.superclass.abstract_class? ? master_class.superclass.name : master_class.name
|
45
|
-
self.master_id = :"#{class_name.demodulize.underscore}_id"
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
class TranslationModel
|
50
|
-
|
51
|
-
attr_reader :adapter,:klass
|
52
|
-
|
53
|
-
def initialize(config)
|
54
|
-
@config = config
|
55
|
-
@adapter = Lolita::DBI::Base.create(@config.klass)
|
56
|
-
@klass = begin
|
57
|
-
@config.translation_class_name.constantize
|
58
|
-
rescue
|
59
|
-
self.create
|
60
|
-
end
|
61
|
-
fix_class_attrs
|
62
|
-
@klass.extract_master_id(@config.translation_class_name)
|
63
|
-
end
|
64
|
-
|
65
|
-
def create
|
66
|
-
translation_model = self
|
67
|
-
config = @config
|
68
|
-
new_klass = Lolita::Translation::ClassFactory.create(@config.translation_class_name, Object, get_orm_class) do
|
69
|
-
if translation_model.adapter.dbi.adapter_name == :mongoid
|
70
|
-
include Mongoid::Document
|
71
|
-
end
|
72
|
-
# set's real table name
|
73
|
-
translation_adapter = Lolita::DBI::Base.create(self)
|
74
|
-
translation_adapter.collection_name = config.options[:table_name] || translation_model.adapter.collection_name.to_s + "_translations"
|
75
|
-
|
76
|
-
cattr_accessor :translate_attrs, :master_id
|
77
|
-
|
78
|
-
include Lolita::Translation::ModelInstanceMethods
|
79
|
-
extend Lolita::Translation::ModelClassMethods
|
80
|
-
end
|
81
|
-
new_klass.translate_attrs = @config.attrs
|
82
|
-
new_klass
|
83
|
-
end
|
84
|
-
|
85
|
-
private
|
86
|
-
|
87
|
-
def get_orm_class()
|
88
|
-
@adapter.dbi.adapter_name == :active_record ? ActiveRecord::Base : nil
|
89
|
-
end
|
90
|
-
|
91
|
-
def fix_class_attrs
|
92
|
-
unless @klass.respond_to?(:translate_attrs)
|
93
|
-
@klass.send(:cattr_accessor, :translate_attrs, :master_id)
|
94
|
-
@klass.send(:extend,Lolita::Translation::ModelClassMethods)
|
95
|
-
@klass.translate_attrs = @config.attrs
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
end
|
100
|
-
end
|
@@ -1,130 +0,0 @@
|
|
1
|
-
module Lolita
|
2
|
-
module Translation
|
3
|
-
module ClassMethods
|
4
|
-
|
5
|
-
def find_with_translations(*args,&block)
|
6
|
-
unless ::I18n.locale == ::I18n.default_locale
|
7
|
-
if args && args[0].kind_of?(Hash)
|
8
|
-
args[0][:include] ||=[]
|
9
|
-
args[0][:include] << :translations
|
10
|
-
end
|
11
|
-
end
|
12
|
-
find_without_translations *args, &block
|
13
|
-
end
|
14
|
-
# creates translation table and adds missing fields
|
15
|
-
# So at first add the "translations :name, :desc" in your model
|
16
|
-
# then put YourModel.sync_translation_table! in db/seed.rb and run "rake db:seed"
|
17
|
-
# Later adding more fields in translations array, just run agin "rake db:seed"
|
18
|
-
# If you want to remove fields do it manualy, it's safer
|
19
|
-
def sync_translation_table!
|
20
|
-
out = StringIO.new
|
21
|
-
$stdout = out
|
22
|
-
self_adapter = Lolita::DBI::Base.create(self)
|
23
|
-
translations_class = self.reflect_on_association(:translations).klass
|
24
|
-
translations_adapter = Lolita::DBI::Base.create(translations_class)
|
25
|
-
|
26
|
-
if translations_adapter.dbi.adapter_name == :active_record
|
27
|
-
translations_table = translations_adapter.collection_name
|
28
|
-
|
29
|
-
unless ActiveRecord::Migration::table_exists?(translations_table)
|
30
|
-
ActiveRecord::Migration.create_table translations_table do |t|
|
31
|
-
t.integer translations_class.master_id, :null => false
|
32
|
-
t.string :locale, :null => false, :limit => 5
|
33
|
-
columns_has_translations.each do |col|
|
34
|
-
t.send(col.type,col.name)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
ActiveRecord::Migration.add_index translations_table, [translations_class.master_id, :locale], :unique => true, :name => "#{self_adapter.collection_name}_master"
|
38
|
-
translations_class.reset_column_information
|
39
|
-
else
|
40
|
-
changes = false
|
41
|
-
columns_has_translations.each do |col|
|
42
|
-
unless translations_class.columns_hash.has_key?(col.name)
|
43
|
-
ActiveRecord::Migration.add_column(translations_table, col.name, col.type)
|
44
|
-
changes = true
|
45
|
-
end
|
46
|
-
end
|
47
|
-
translations_class.reset_column_information if changes
|
48
|
-
end
|
49
|
-
elsif translations_adapter.dbi.adapter_name == :mongoid
|
50
|
-
unless translations_class.fields["locale"]
|
51
|
-
translations_class.class_eval do
|
52
|
-
field(self.master_id, :type => Integer)
|
53
|
-
field :locale, :type => String
|
54
|
-
columns_has_translations.each do |col|
|
55
|
-
field col.name, :type => col.type
|
56
|
-
end
|
57
|
-
index(
|
58
|
-
[
|
59
|
-
[ self.master_id, Mongo::ASCENDING ],
|
60
|
-
[ :locale, Mongo::ASCENDING ]
|
61
|
-
],
|
62
|
-
unique: true
|
63
|
-
)
|
64
|
-
end
|
65
|
-
else
|
66
|
-
columns_has_translations.each do |col|
|
67
|
-
unless translations_class.fields[col.name.to_s]
|
68
|
-
translations_class.field(col.name,:type => col.type)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
$stdout = STDOUT
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
module InstanceMethods
|
78
|
-
|
79
|
-
# forces given locale
|
80
|
-
# I18n.locale = :lv
|
81
|
-
# a = Article.find 18
|
82
|
-
# a.title
|
83
|
-
# => "LV title"
|
84
|
-
# a.in(:en).title
|
85
|
-
# => "EN title"
|
86
|
-
def in locale
|
87
|
-
locale.to_sym == ::I18n.default_locale ? self : find_translation(locale)
|
88
|
-
end
|
89
|
-
|
90
|
-
def find_or_build_translation(*args)
|
91
|
-
locale = args.first.to_s
|
92
|
-
build = args.second.present?
|
93
|
-
find_translation(locale) || (build ? self.translations.build(:locale => locale) : self.translations.new(:locale => locale))
|
94
|
-
end
|
95
|
-
|
96
|
-
def translation(locale)
|
97
|
-
find_translation(locale.to_s)
|
98
|
-
end
|
99
|
-
|
100
|
-
def all_translations
|
101
|
-
t = ::I18n.available_locales.map do |locale|
|
102
|
-
[locale, find_or_build_translation(locale)]
|
103
|
-
end
|
104
|
-
ActiveSupport::OrderedHash[t]
|
105
|
-
end
|
106
|
-
|
107
|
-
def has_translation?(locale)
|
108
|
-
return true if locale == ::I18n.default_locale
|
109
|
-
find_translation(locale).present?
|
110
|
-
end
|
111
|
-
|
112
|
-
# if object is new, then nested slaves ar built for all available locales
|
113
|
-
def build_nested_translations
|
114
|
-
if (::I18n.available_locales.size - 1) > self.translations.size
|
115
|
-
::I18n.available_locales.clone.delete_if{|l| l == ::I18n.default_locale}.each do |l|
|
116
|
-
options = {:locale => l.to_s}
|
117
|
-
self_adapter = Lolita::DBI::Base.create(self.class)
|
118
|
-
options[self_adapter.reflect_on_association(:translations).klass.master_id] = self.id unless self.new_record?
|
119
|
-
self.translations.build(options) unless self.translations.map(&:locale).include?(l.to_s)
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
def find_translation(locale)
|
125
|
-
locale = locale.to_s
|
126
|
-
translations.detect { |t| t.locale == locale }
|
127
|
-
end
|
128
|
-
end
|
129
|
-
end
|
130
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
class String
|
2
|
-
attr_accessor :origin_model, :origin_name
|
3
|
-
def set_origins obj, name
|
4
|
-
self.origin_model = obj
|
5
|
-
self.origin_name = name
|
6
|
-
self
|
7
|
-
end
|
8
|
-
# forces given locale
|
9
|
-
# I18n.locale = :lv
|
10
|
-
# a = Article.find 18
|
11
|
-
# a.title
|
12
|
-
# => "LV title"
|
13
|
-
# a.title.in(:en)
|
14
|
-
# => "EN title"
|
15
|
-
def in locale
|
16
|
-
return self unless self.origin_model
|
17
|
-
translation = self.origin_model.in(locale) and translation.send(self.origin_name)
|
18
|
-
end
|
19
|
-
end
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
require File.dirname(__FILE__) + '/spec_helper'
|
3
|
-
|
4
|
-
describe 'HasTranslations' do
|
5
|
-
it "should switch locales" do
|
6
|
-
g = Group.create!(:name => "Sport")
|
7
|
-
c = Category.create!(:name => "Golf", :groups => [g])
|
8
|
-
z = News.create!(:title => "Tiger Woods sucks", :body => Faker::Lorem::paragraphs(10).join, :category_id => c.id)
|
9
|
-
# translate
|
10
|
-
g.translations.create!(:locale => 'lv', :name => "Sports")
|
11
|
-
c.translations.create!(:locale => 'lv', :name => "Golfs")
|
12
|
-
z.translations.create!(:locale => 'lv', :title => "Taigers Vuds nekam neder")
|
13
|
-
|
14
|
-
g.name.should == "Sport"
|
15
|
-
c.name.should == "Golf"
|
16
|
-
z.title.should == "Tiger Woods sucks"
|
17
|
-
|
18
|
-
I18n.locale = :lv
|
19
|
-
|
20
|
-
g.name.should == "Sports"
|
21
|
-
c.name.should == "Golfs"
|
22
|
-
z.title.should == "Taigers Vuds nekam neder"
|
23
|
-
|
24
|
-
z.category.name.should == "Golfs"
|
25
|
-
z.category.groups.first.name.should == "Sports"
|
26
|
-
|
27
|
-
z.destroy
|
28
|
-
c.destroy
|
29
|
-
g.destroy
|
30
|
-
#--------------------------------
|
31
|
-
I18n.locale = I18n.default_locale
|
32
|
-
end
|
33
|
-
|
34
|
-
it "should load requested locale with 'in' method" do
|
35
|
-
g = Group.create!(:name => "Sport")
|
36
|
-
g.translations.create!(:locale => 'lv', :name => "Sports")
|
37
|
-
|
38
|
-
g = Group.find_by_name "Sport"
|
39
|
-
g.name.should == "Sport"
|
40
|
-
g.name.in(:lv).should == "Sports"
|
41
|
-
g.name.should == "Sport"
|
42
|
-
end
|
43
|
-
end
|