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.
Files changed (77) hide show
  1. data/.gitignore +25 -0
  2. data/Gemfile +2 -18
  3. data/README.md +1 -2
  4. data/Rakefile +1 -49
  5. data/app/assets/javascripts/lolita/translation/application.js +4 -3
  6. data/app/assets/stylesheets/lolita/translation/application.css +7 -1
  7. data/app/views/components/lolita/translation/_assets.html.haml +4 -0
  8. data/app/views/components/lolita/translation/_language_wrap.html.haml +2 -0
  9. data/app/views/components/lolita/translation/_switch.html.haml +4 -0
  10. data/lib/lolita-translation.rb +40 -33
  11. data/lib/lolita-translation/builder/abstract_builder.rb +103 -0
  12. data/lib/lolita-translation/builder/active_record_builder.rb +106 -0
  13. data/lib/lolita-translation/builder/mongoid_builder.rb +0 -0
  14. data/lib/lolita-translation/configuration.rb +41 -166
  15. data/lib/lolita-translation/errors.rb +15 -0
  16. data/lib/lolita-translation/locale.rb +32 -0
  17. data/lib/lolita-translation/locales.rb +62 -0
  18. data/lib/lolita-translation/lolita/component_hooks.rb +49 -0
  19. data/lib/lolita-translation/lolita/tab_extension.rb +113 -0
  20. data/lib/lolita-translation/migrator.rb +56 -0
  21. data/lib/lolita-translation/migrators/active_record_migrator.rb +93 -0
  22. data/lib/lolita-translation/migrators/mongoid_migrator.rb +81 -0
  23. data/lib/lolita-translation/orm/mixin.rb +57 -0
  24. data/lib/lolita-translation/rails.rb +6 -31
  25. data/lib/lolita-translation/record.rb +220 -0
  26. data/lib/lolita-translation/translated_string.rb +11 -0
  27. data/lib/lolita-translation/translation_class_builder.rb +59 -0
  28. data/lib/lolita-translation/utils.rb +13 -0
  29. data/lib/lolita-translation/version.rb +32 -0
  30. data/lib/tasks/lolita_translation.rake +14 -0
  31. data/lolita-translation.gemspec +24 -71
  32. data/spec/ar_schema.rb +90 -0
  33. data/spec/header.rb +14 -0
  34. data/spec/integrations/active_record_integration_spec.rb +218 -0
  35. data/spec/lolita-translation/builder/abstract_builder_spec.rb +67 -0
  36. data/spec/lolita-translation/builder/active_record_builder_spec.rb +40 -0
  37. data/spec/lolita-translation/configuration_spec.rb +72 -0
  38. data/spec/lolita-translation/locale_spec.rb +25 -0
  39. data/spec/lolita-translation/locales_spec.rb +31 -0
  40. data/spec/lolita-translation/lolita/tab_extension_spec.rb +61 -0
  41. data/spec/lolita-translation/migrator_spec.rb +42 -0
  42. data/spec/lolita-translation/migrators/active_record_migrator_spec.rb +50 -0
  43. data/spec/lolita-translation/orm/mixin_spec.rb +52 -0
  44. data/spec/lolita-translation/record_spec.rb +112 -0
  45. data/spec/lolita-translation/translation_class_builder_spec.rb +62 -0
  46. data/spec/lolita_translation_spec.rb +16 -0
  47. data/spec/rails_helper.rb +6 -0
  48. data/spec/requests/record_language_switch_spec.rb +16 -0
  49. data/spec/requests/record_saving_spec.rb +63 -0
  50. data/spec/spec_helper.rb +38 -90
  51. data/spec/tasks/lolita_translation_spec.rb +32 -0
  52. data/spec/test_app/app/controllers/application_controller.rb +3 -0
  53. data/spec/test_app/app/models/category.rb +6 -0
  54. data/spec/test_app/app/models/post.rb +8 -0
  55. data/spec/test_app/config/application.rb +24 -0
  56. data/spec/test_app/config/boot.rb +11 -0
  57. data/spec/test_app/config/database.yml +3 -0
  58. data/spec/test_app/config/enviroment.rb +5 -0
  59. data/spec/test_app/config/enviroments/development.rb +44 -0
  60. data/spec/test_app/config/initializers/lolita_translation.rb +4 -0
  61. data/spec/test_app/config/initializers/token.rb +7 -0
  62. data/spec/test_app/config/routes.rb +4 -0
  63. data/spec/test_app/db/.gitkeep +0 -0
  64. data/spec/test_app/log/.gitkeep +0 -0
  65. metadata +193 -46
  66. data/.document +0 -5
  67. data/VERSION +0 -1
  68. data/app/views/components/lolita/translation/_assets.html.erb +0 -7
  69. data/app/views/components/lolita/translation/_language_wrap.html.erb +0 -4
  70. data/app/views/components/lolita/translation/_switch.html.erb +0 -8
  71. data/lib/generators/lolita_translation/USAGE +0 -8
  72. data/lib/generators/lolita_translation/has_translations_generator.rb +0 -8
  73. data/lib/lolita-translation/model.rb +0 -100
  74. data/lib/lolita-translation/modules.rb +0 -130
  75. data/lib/lolita-translation/string.rb +0 -19
  76. data/lib/tasks/has_translations_tasks.rake +0 -4
  77. data/spec/has_translations_spec.rb +0 -43
data/.document DELETED
@@ -1,5 +0,0 @@
1
- lib/**/*.rb
2
- bin/*
3
- -
4
- features/**/*.feature
5
- LICENSE.txt
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.3.3
@@ -1,7 +0,0 @@
1
- <% content_for :script do %>
2
- <%=javascript_include_tag "lolita/translation/application.js"%>
3
- <% end %>
4
-
5
- <% content_for :style do %>
6
- <%= stylesheet_link_tag 'lolita/translation/application.css', :media => 'screen, projection' %>
7
- <% end %>
@@ -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,8 +0,0 @@
1
- Description:
2
- Explain the generator
3
-
4
- Example:
5
- ./script/generate has_translations Thing
6
-
7
- This will create:
8
- what/will/it/create
@@ -1,8 +0,0 @@
1
- class HasTranslationsGenerator < Rails::Generator::NamedBase
2
- def manifest
3
- record do |m|
4
- # m.directory "lib"
5
- # m.template 'README', "README"
6
- end
7
- end
8
- end
@@ -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,4 +0,0 @@
1
- # desc "Explaining what the task does"
2
- # task :has_translations do
3
- # # Task goes here
4
- # 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