From 4600f94922a19c72c9482008135ebdadaba9cc8e Mon Sep 17 00:00:00 2001 From: did Date: Wed, 25 Jan 2012 22:07:10 +0100 Subject: [PATCH] extend i18n to pages (wip) --- Gemfile | 2 +- Gemfile.lock | 30 ++++---- app/models/locomotive/editable_element.rb | 10 +-- app/models/locomotive/editable_file.rb | 2 + app/models/locomotive/editable_short_text.rb | 9 ++- .../locomotive/extensions/page/parse.rb | 10 +-- .../locomotive/extensions/shared/seo.rb | 6 +- app/models/locomotive/page.rb | 71 +++++++++++++----- doc/TODO | 3 + lib/tasks/locomotive.rake | 75 +++++++++++++++---- 10 files changed, 151 insertions(+), 67 deletions(-) diff --git a/Gemfile b/Gemfile index 1245b5f3..0bcad503 100644 --- a/Gemfile +++ b/Gemfile @@ -11,7 +11,7 @@ gem 'cancan', '~> 1.6.7' gem 'mongo', '~> 1.5.2' gem 'bson_ext', '~> 1.5.2' -gem 'mongoid', '~> 2.4.0' +gem 'mongoid', '~> 2.4.2' gem 'locomotive_mongoid_acts_as_tree', '~> 0.1.5.8' gem 'custom_fields', :path => '../gems/custom_fields' # DEV # gem 'custom_fields', :git => 'git://github.com/locomotivecms/custom_fields.git', :branch => 'experimental' diff --git a/Gemfile.lock b/Gemfile.lock index 53e6e2b7..15d6b302 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,10 +1,10 @@ PATH remote: ../gems/custom_fields specs: - custom_fields (2.0.0.rc1) + custom_fields (2.0.0.rc2) activesupport (~> 3.1.3) carrierwave-mongoid (~> 0.1.3) - mongoid (~> 2.4.0) + mongoid (~> 2.4.2) GEM remote: http://rubygems.org/ @@ -91,12 +91,12 @@ GEM gherkin (~> 2.7.1) json (>= 1.4.6) term-ansicolor (>= 1.0.6) - cucumber-rails (1.2.0) - capybara (>= 1.1.1) - cucumber (>= 1.1.1) + cucumber-rails (1.2.1) + capybara (>= 1.1.2) + cucumber (>= 1.1.3) nokogiri (>= 1.5.0) - database_cleaner (0.7.0) - delayed_job (3.0.0) + database_cleaner (0.7.1) + delayed_job (3.0.1) activesupport (~> 3.0) delayed_job_mongoid (1.0.8) delayed_job (~> 3.0.0) @@ -111,7 +111,7 @@ GEM ejs (1.0.0) erubis (2.7.0) excon (0.7.12) - execjs (1.2.13) + execjs (1.3.0) multi_json (~> 1.0) factory_girl (2.2.0) activesupport @@ -135,11 +135,11 @@ GEM formtastic (2.0.2) rails (~> 3.0) fssm (0.2.8.1) - gherkin (2.7.3) + gherkin (2.7.4) json (>= 1.4.6) growl-glue (1.0.7) haml (3.1.4) - highline (1.6.9) + highline (1.6.11) hike (1.2.1) httparty (0.8.1) multi_json @@ -148,7 +148,7 @@ GEM jquery-rails (1.0.19) railties (~> 3.0) thor (~> 0.14) - json (1.6.4) + json (1.6.5) kaminari (0.13.0) actionpack (>= 3.0.0) activesupport (>= 3.0.0) @@ -171,7 +171,7 @@ GEM mocha (0.9.12) mongo (1.5.2) bson (= 1.5.2) - mongoid (2.4.0) + mongoid (2.4.2) activemodel (~> 3.1) mongo (~> 1.3) tzinfo (~> 0.3.22) @@ -218,7 +218,7 @@ GEM rake (0.9.2) rdoc (3.12) json (~> 1.4) - responders (0.6.4) + responders (0.6.5) rest-client (1.6.7) mime-types (>= 1.16) rmagick (2.12.2) @@ -248,7 +248,7 @@ GEM railties (~> 3.1.0) sass (~> 3.1.10) tilt (~> 1.3.2) - selenium-webdriver (2.16.0) + selenium-webdriver (2.17.0) childprocess (>= 0.2.5) ffi (~> 1.0.9) multi_json (~> 1.0.4) @@ -318,7 +318,7 @@ DEPENDENCIES mimetype-fu (~> 0.1.2) mocha (= 0.9.12) mongo (~> 1.5.2) - mongoid (~> 2.4.0) + mongoid (~> 2.4.2) pickle rack-cache (~> 1.1) rails (~> 3.1.3) diff --git a/app/models/locomotive/editable_element.rb b/app/models/locomotive/editable_element.rb index 04cbc337..dcd5031e 100644 --- a/app/models/locomotive/editable_element.rb +++ b/app/models/locomotive/editable_element.rb @@ -6,13 +6,13 @@ module Locomotive ## fields ## field :slug field :block - field :default_content + field :default_content, :localize => true field :default_attribute field :hint - field :priority, :type => Integer, :default => 0 - field :disabled, :type => Boolean, :default => false - field :assignable, :type => Boolean, :default => true - field :from_parent, :type => Boolean, :default => false + field :priority, :type => Integer, :default => 0 + field :disabled, :type => Boolean, :default => false + field :assignable, :type => Boolean, :default => true + field :from_parent, :type => Boolean, :default => false ## associations ## embedded_in :page, :class_name => 'Locomotive::Page', :inverse_of => :editable_elements diff --git a/app/models/locomotive/editable_file.rb b/app/models/locomotive/editable_file.rb index 7dab8f90..d4589d26 100644 --- a/app/models/locomotive/editable_file.rb +++ b/app/models/locomotive/editable_file.rb @@ -3,6 +3,8 @@ module Locomotive mount_uploader :source, EditableFileUploader, :mount_on => :source_filename + replace_field :source_filename, ::String, true + def content self.source? ? self.source.url : self.default_content end diff --git a/app/models/locomotive/editable_short_text.rb b/app/models/locomotive/editable_short_text.rb index ad026129..01031b6f 100644 --- a/app/models/locomotive/editable_short_text.rb +++ b/app/models/locomotive/editable_short_text.rb @@ -2,14 +2,17 @@ module Locomotive class EditableShortText < EditableElement ## fields ## - field :content + field :content, :localize => true ## methods ## - def content - self.read_attribute(:content).blank? ? self.default_content : self.read_attribute(:content) + def content_with_localization + value = self.content_without_localization + value.blank? ? self.default_content : value end + alias_method_chain :content, :localization + def as_json(options = {}) Locomotive::EditableShortTextPresenter.new(self).as_json end diff --git a/app/models/locomotive/extensions/page/parse.rb b/app/models/locomotive/extensions/page/parse.rb index bc22614b..5c3c255a 100644 --- a/app/models/locomotive/extensions/page/parse.rb +++ b/app/models/locomotive/extensions/page/parse.rb @@ -6,14 +6,14 @@ module Locomotive extend ActiveSupport::Concern included do - field :serialized_template, :type => Binary - field :template_dependencies, :type => Array, :default => [] - field :snippet_dependencies, :type => Array, :default => [] + field :serialized_template, :type => Binary, :localize => true + field :template_dependencies, :type => Array, :default => [], :localize => true + field :snippet_dependencies, :type => Array, :default => [], :localize => true attr_reader :template_changed before_validation :serialize_template - after_save :update_template_descendants + after_save :update_template_descendants validate :template_must_be_valid @@ -23,7 +23,7 @@ module Locomotive module InstanceMethods def template - @template ||= Marshal.load(read_attribute(:serialized_template).to_s) rescue nil + @template ||= Marshal.load(self.serialized_template.to_s) rescue nil end protected diff --git a/app/models/locomotive/extensions/shared/seo.rb b/app/models/locomotive/extensions/shared/seo.rb index 88414bc3..87380937 100644 --- a/app/models/locomotive/extensions/shared/seo.rb +++ b/app/models/locomotive/extensions/shared/seo.rb @@ -5,9 +5,9 @@ module Locomotive extend ActiveSupport::Concern included do - field :seo_title, :type => String - field :meta_keywords, :type => String - field :meta_description, :type => String + field :seo_title, :type => String, :localize => true + field :meta_keywords, :type => String, :localize => true + field :meta_description, :type => String, :localize => true end end # Seo diff --git a/app/models/locomotive/page.rb b/app/models/locomotive/page.rb index 7a71a7a1..97acd356 100644 --- a/app/models/locomotive/page.rb +++ b/app/models/locomotive/page.rb @@ -14,12 +14,13 @@ module Locomotive include Extensions::Shared::Seo ## fields ## - field :title - field :slug - field :fullpath - field :raw_template - field :published, :type => Boolean, :default => false - field :cache_strategy, :default => 'none' + field :title, :localize => true + field :slug, :localize => true + field :fullpath, :localize => true + field :raw_template, :localize => true + field :locales, :type => Array + field :published, :type => Boolean, :default => false + field :cache_strategy, :default => 'none' ## associations ## referenced_in :site, :class_name => 'Locomotive::Site' @@ -32,7 +33,8 @@ module Locomotive ## callbacks ## after_initialize :set_default_raw_template before_validation :normalize_slug - before_save { |p| p.fullpath = p.fullpath(true) } + before_save :build_fullpath + before_save :record_current_locale before_destroy :do_not_remove_index_and_404_pages ## validations ## @@ -62,19 +64,34 @@ module Locomotive self.index? || self.not_found? end - def fullpath(force = false) - if read_attribute(:fullpath).present? && !force - return read_attribute(:fullpath) - end + # def localized_fullpath(locale) + # ::Mongoid::Fields::I18n.with_locale(locale) do + # self.fullpath + # # locale != self.site.default_locale ? File.join(locale, self.fullpath) : self.fullpath + # end + # end - if self.index? || self.not_found? - self.slug - else - slugs = self.self_and_ancestors.sort_by(&:depth).map(&:slug) - slugs.shift unless slugs.size == 1 - File.join slugs.compact - end - end + # def fullpath(locale = nil) + # locale ||= ::Mongoid::Fields::I18n.locale + # + # localized_fullpath = self.attributes['fullpath'][locale] + # + # return localized_fullpath if localized_fullpath.present? && !force + # + # if self.index? || self.not_found? + # self.slug + # else + # slugs = self.self_and_ancestors.sort_by(&:depth).map(&:slug) + # slugs.shift unless slugs.size == 1 + # File.join slugs.compact + # end + # end + + # def fullpath_with_locale(locale) + # url, locale = self.fullpath(true), locale.to_s + # + # locale != self.site.default_locale ? File.join(locale, url) : url + # end def with_cache? self.cache_strategy != 'none' @@ -113,5 +130,21 @@ module Locomotive self.raw_template ||= ::I18n.t('attributes.defaults.pages.other.body') end + def build_fullpath + if self.index? || self.not_found? || self.templatized? + self.fullpath = self.slug + else + slugs = self.self_and_ancestors.sort_by(&:depth).map(&:slug) + slugs.shift unless slugs.size == 1 + self.fullpath = File.join slugs.compact + end + end + + def record_current_locale + self.locales ||= [] + self.locales << ::Mongoid::Fields::I18n.locale + self.locales.uniq! + end + end end \ No newline at end of file diff --git a/doc/TODO b/doc/TODO index decc346f..7232caf6 100644 --- a/doc/TODO +++ b/doc/TODO @@ -99,10 +99,13 @@ x deployment x CRUD pages x CRUD content types x data ? +- script to migrate existing site + - i18n - refactoring - remove the import / export scripts - remove the cross domain authentication (use auth_token instead) - upgrade to rails 3.2 (https://github.com/locomotivecms/engine/pull/281/files) +- heroku module for locomotive - bugs: x unable to toggle the "required" check_boxes for content types diff --git a/lib/tasks/locomotive.rake b/lib/tasks/locomotive.rake index 3fa85199..03e84648 100644 --- a/lib/tasks/locomotive.rake +++ b/lib/tasks/locomotive.rake @@ -29,22 +29,22 @@ namespace :locomotive do end end - desc 'Import a remote template described by its URL -- 2 options: SITE=name or id, RESET=by default false' - task :import => :environment do - url, site_name_or_id, reset = ENV['URL'], ENV['SITE'], Boolean.set(ENV['RESET']) || false - - if url.blank? || (url =~ /https?:\/\//).nil? - raise "URL is missing or it is not a valid http url." - end - - site = Locomotive::Site.find(site_name_or_id) || Locomotive::Site.where(:name => site_name_or_id).first || Locomotive::Site.first - - if site.nil? - raise "No site found. Please give a correct value (name or id) for the SITE env variable." - end - - ::Locomotive::Import::Job.run!(url, site, { :samples => true, :reset => reset }) - end + # desc 'Import a remote template described by its URL -- 2 options: SITE=name or id, RESET=by default false' + # task :import => :environment do + # url, site_name_or_id, reset = ENV['URL'], ENV['SITE'], Boolean.set(ENV['RESET']) || false + # + # if url.blank? || (url =~ /https?:\/\//).nil? + # raise "URL is missing or it is not a valid http url." + # end + # + # site = Locomotive::Site.find(site_name_or_id) || Locomotive::Site.where(:name => site_name_or_id).first || Locomotive::Site.first + # + # if site.nil? + # raise "No site found. Please give a correct value (name or id) for the SITE env variable." + # end + # + # ::Locomotive::Import::Job.run!(url, site, { :samples => true, :reset => reset }) + # end desc 'Add a new admin user (NOTE: currently only supports adding user to first site)' task :add_admin => :environment do @@ -85,6 +85,49 @@ namespace :locomotive do end end + desc "Upgrade a site to i18n. Requires SITE (name or id) and LOCALE (by default: en) as env variables" + task :i18n => :environment do + locale, site_name_or_id = ENV['LOCALE'] || 'en', ENV['SITE'] + + site = Locomotive::Site.find(site_name_or_id) || Locomotive::Site.where(:name => site_name_or_id).first + + raise 'Site not found' if site.nil? + + site.locales ||= [locale] + + # sites + %w(seo_title meta_keywords meta_description).each do |attribute| + if !site.send(:"#{attribute}_translations").respond_to?(:keys) + site.changed_attributes.store attribute, site.attributes[attribute] + site.attributes.store attribute, { locale => site.attributes[attribute] } + end + end + site.save! + + puts "=======" + + # TODO https://github.com/mongodb/mongo-ruby-driver + + Locomotive::Page.skip_callback(:validate, :before) + Locomotive::Page.skip_callback(:save, :after) + + Locomotive::Page.all.each do |page| + begin + %w(title slug fullpath raw_template seo_title meta_keywords meta_description serialized_template template_dependencies snippet_dependencies).each do |attribute| + if !page.send(:"#{attribute}_translations").respond_to?(:keys) + page.changed_attributes.store attribute, page.attributes[attribute] + page.attributes.store attribute, { locale => page.attributes[attribute] } + end + end + page.save(:validate => false) + rescue Exception => e + puts "Error: #{e.message}, page = #{page.title}" + puts e.backtrace + raise "STOP a first error" + end + end + end + end end