diff --git a/Gemfile b/Gemfile index 318573ea..8fa9c0b1 100644 --- a/Gemfile +++ b/Gemfile @@ -27,7 +27,7 @@ gem 'carrierwave', '0.5.6' gem 'dragonfly', '~> 0.9.1' gem 'rack-cache', :require => 'rack/cache' -gem 'custom_fields', '1.0.0.beta.22' +gem 'custom_fields', '1.0.0.beta.23' gem 'cancan' gem 'fog', '0.8.2' gem 'mimetype-fu' diff --git a/Gemfile.lock b/Gemfile.lock index c1f1ea89..67cc9541 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -87,7 +87,7 @@ GEM capybara (>= 1.0.0) cucumber (~> 1.0.0) nokogiri (>= 1.4.6) - custom_fields (1.0.0.beta.22) + custom_fields (1.0.0.beta.23) activesupport (~> 3.0.9) mongoid (= 2.0.2) daemons (1.1.4) @@ -300,7 +300,7 @@ DEPENDENCIES carrierwave (= 0.5.6) cells cucumber-rails (= 1.0.2) - custom_fields (= 1.0.0.beta.22) + custom_fields (= 1.0.0.beta.23) database_cleaner delayed_job (= 2.1.4) delayed_job_mongoid (= 1.0.2) diff --git a/app/controllers/admin/base_controller.rb b/app/controllers/admin/base_controller.rb index 3ec129af..20401b1c 100644 --- a/app/controllers/admin/base_controller.rb +++ b/app/controllers/admin/base_controller.rb @@ -90,6 +90,10 @@ module Admin I18n.site_locale = session[:site_locale] end + def back_to_default_site_locale + session[:site_locale] = I18n.site_locale = current_site.default_locale + end + # ___ site/page urls builder ___ def current_site_url diff --git a/app/controllers/admin/contents_controller.rb b/app/controllers/admin/contents_controller.rb index 0ba3cddc..4c57caf7 100644 --- a/app/controllers/admin/contents_controller.rb +++ b/app/controllers/admin/contents_controller.rb @@ -11,6 +11,8 @@ module Admin before_filter :authorize_content + before_filter :back_to_default_site_locale, :only => %w(new create) + helper_method :breadcrumb_root, :breadcrumb_url, :back_url def index diff --git a/app/controllers/admin/pages_controller.rb b/app/controllers/admin/pages_controller.rb index a0030484..13787874 100644 --- a/app/controllers/admin/pages_controller.rb +++ b/app/controllers/admin/pages_controller.rb @@ -5,6 +5,8 @@ module Admin respond_to :json, :only => [:update, :sort, :get_path] + before_filter :back_to_default_site_locale, :only => %w(new create) + def index @pages = current_site.all_pages_in_once end diff --git a/app/models/content_instance.rb b/app/models/content_instance.rb index 4ba070c3..b9c6bfb5 100644 --- a/app/models/content_instance.rb +++ b/app/models/content_instance.rb @@ -9,6 +9,8 @@ class ContentInstance include Extensions::Shared::Seo ## fields (dynamic fields) ## + localized_fields :_position_in_list, /^custom_field_/ + field :_slug field :_position_in_list, :type => Integer, :default => 0 field :_visible, :type => Boolean, :default => true diff --git a/app/models/editable_element.rb b/app/models/editable_element.rb index 60c563c8..14e8d604 100644 --- a/app/models/editable_element.rb +++ b/app/models/editable_element.rb @@ -1,23 +1,24 @@ class EditableElement - include Mongoid::Document + include Mongoid::Document + include Mongoid::I18n - ## fields ## - field :slug - field :block - field :default_content - field :default_attribute - field :hint - field :disabled, :type => Boolean, :default => false - field :assignable, :type => Boolean, :default => true - field :from_parent, :type => Boolean, :default => false + ## fields ## + field :slug + field :block + localized_field :default_content + field :default_attribute + field :hint + field :disabled, :type => Boolean, :default => false + field :assignable, :type => Boolean, :default => true + field :from_parent, :type => Boolean, :default => false - ## associations ## - embedded_in :page, :inverse_of => :editable_elements + ## associations ## + embedded_in :page, :inverse_of => :editable_elements - ## validations ## - validates_presence_of :slug + ## validations ## + validates_presence_of :slug - ## methods ## + ## methods ## end \ No newline at end of file diff --git a/app/models/editable_file.rb b/app/models/editable_file.rb index f96fa619..0bd86d2d 100644 --- a/app/models/editable_file.rb +++ b/app/models/editable_file.rb @@ -1,7 +1,11 @@ class EditableFile < EditableElement + localized_fields :source_filename + mount_uploader :source, EditableFileUploader + # localized_field :source + def content self.source? ? self.source.url : self.default_content end diff --git a/app/models/editable_short_text.rb b/app/models/editable_short_text.rb index 5e57a193..31492f88 100644 --- a/app/models/editable_short_text.rb +++ b/app/models/editable_short_text.rb @@ -1,12 +1,19 @@ class EditableShortText < EditableElement ## fields ## - field :content + localized_field :content ## methods ## - def content - self.read_attribute(:content).blank? ? self.default_content : self.read_attribute(:content) + # def content + # self.read_attribute(:content).blank? ? self.default_content : self.read_attribute(:content) + # end + + def content_with_localization + value = self.content_without_localization + value.blank? ? self.default_content : value end + alias_method_chain :content, :localization + end \ No newline at end of file diff --git a/app/models/extensions/page/parse.rb b/app/models/extensions/page/parse.rb index 14b47b33..ed5448a3 100644 --- a/app/models/extensions/page/parse.rb +++ b/app/models/extensions/page/parse.rb @@ -5,9 +5,9 @@ module Extensions extend ActiveSupport::Concern included do - field :serialized_template, :type => Binary - field :template_dependencies, :type => Array, :default => [] - field :snippet_dependencies, :type => Array, :default => [] + localized_field :serialized_template, :type => Binary + localized_field :template_dependencies, :type => Array, :default => [] + localized_field :snippet_dependencies, :type => Array, :default => [] attr_reader :template_changed @@ -22,7 +22,7 @@ module Extensions 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/extensions/page/render.rb b/app/models/extensions/page/render.rb index 81494e46..0034ff8b 100644 --- a/app/models/extensions/page/render.rb +++ b/app/models/extensions/page/render.rb @@ -1,3 +1,5 @@ +require 'ruby-debug' + module Extensions module Page module Render diff --git a/app/models/page.rb b/app/models/page.rb index 67c72504..c958fa7c 100644 --- a/app/models/page.rb +++ b/app/models/page.rb @@ -17,7 +17,7 @@ class Page localized_field :title localized_field :slug localized_field :fullpath - field :raw_template + localized_field :raw_template field :published, :type => Boolean, :default => false field :cache_strategy, :default => 'none' @@ -62,6 +62,10 @@ class Page self.index? || self.not_found? end + def default_slug + I18n.with_site_locale(I18n.default_site_locale) { self.slug } + end + def fullpath_with_building(force = false) if self.fullpath_without_building.present? && !force self.fullpath_without_building @@ -78,6 +82,16 @@ class Page alias_method_chain :fullpath, :building + def fullpath_with_locale(locale) + url, locale = self.fullpath(true), locale.to_s + + if locale != self.site.default_locale + url = File.join(locale, url) + end + + url + end + def with_cache? self.cache_strategy != 'none' end diff --git a/doc/TODO b/doc/TODO index 8c98552b..cbfb9a71 100644 --- a/doc/TODO +++ b/doc/TODO @@ -11,24 +11,26 @@ BOARD: x rendering engine x get locale x render the right version - - contents + x contents x store the site locale value - - pages + x pages x title / slug / fullpath / seo - - template ? - - editable contents - - custom contents - - snippets + x template + x editable contents + x custom contents (models) + (- snippets) x site x seo x locale picker - liquid tags: + x locale switcher + x nav - link_to (new) - - nav - - locale switcher - - others ? - + (- others ?) - - other problems to solve: - - If you create a new page it shall always be created in the default_language, not depending on the used language in the backend. + x If you create a new page it shall always be created in the default_language, not depending on the used language in the backend. + - redirect for the default site locale if urls like //.... + - inline editing BACKLOG: diff --git a/lib/locomotive/custom_fields.rb b/lib/locomotive/custom_fields.rb index 6b40fbbd..89da81da 100644 --- a/lib/locomotive/custom_fields.rb +++ b/lib/locomotive/custom_fields.rb @@ -24,7 +24,7 @@ module CustomFields class Item def to_liquid - { 'id' => self._id, 'name' => self.name } + { 'id' => self._id.to_s, 'name' => self.name } end end diff --git a/lib/locomotive/i18n.rb b/lib/locomotive/i18n.rb index f52baa88..b560d3d5 100644 --- a/lib/locomotive/i18n.rb +++ b/lib/locomotive/i18n.rb @@ -1,3 +1,4 @@ +# require 'ruby-debug' ## patches for the i18n support (aka multi languages support) require 'i18n' @@ -33,13 +34,91 @@ module I18n end DELEGATORS end + + # Executes block with given I18n.site_locale set. + def with_site_locale(tmp_locale = nil) + if tmp_locale + current_locale = self.site_locale + self.site_locale = tmp_locale + end + yield + ensure + self.site_locale = current_locale if tmp_locale + end end end +## CARRIERWAVE ## +require 'carrierwave/orm/mongoid' + +module CarrierWave + module Mongoid + def mount_uploader_with_localization(column, uploader=nil, options={}, &block) + mount_uploader_without_localization(column, uploader, options, &block) + + define_method(:read_uploader) { |name| self.send(name.to_sym) } + define_method(:write_uploader) { |name, value| self.send(:"#{name.to_sym}=", value) } + end + + alias_method_chain :mount_uploader, :localization + end +end + +## MONGOID-I18n ## + # TODO: fork https://github.com/Papipo/mongoid_i18n module Mongoid + module Criterion + class Selector< Hash + def []=(key, value) + key = "#{key}.#{::I18n.site_locale}" if fields[key.to_s].try(:type) == Mongoid::I18n::LocalizedField + super + end + end + end + module I18n + + included do + cattr_accessor :localized_fields_list + end + module ClassMethods + + def localized_fields(*args) + self.localized_fields_list = [*args].collect + end + + def field(name, options = {}) + if localized_field?(name) + options.merge!(:type => LocalizedField, :default => LocalizedField.new) + end + super + end + + protected + + def localized_field?(name) + # puts "options[:type] = #{options[:type].inspect} / #{(options[:type] == LocalizedField).inspect}" + + # return true if options[:type] == LocalizedField + + # puts "self.localized_fields_list = #{self.localized_fields_list.inspect} / #{meth.inspect}" + + (self.localized_fields_list || []).any? do |rule| + case rule + when String, Symbol then name.to_s == rule.to_s + when Regexp then !(name.to_s =~ rule).nil? + else + false + end + end.tap do |result| + # options[:type] = LocalizedField if result + + # puts "#{name.inspect}... localized ? #{result.inspect}" + end + end + def create_accessors(name, meth, options = {}) if options[:type] == LocalizedField if options[:use_default_if_empty] != false # nil or true @@ -62,12 +141,13 @@ module Mongoid end end define_method("#{meth}=") do |value| - puts "@attributes[name].present? = #{@attributes[name].present?.inspect} / !@attributes[name].is_a?(Hash) #{(!@attributes[name].is_a?(Hash)).inspect}" + # debugger + # puts "@attributes[name].present? = #{@attributes[name].present?.inspect} / !@attributes[name].is_a?(Hash) #{(!@attributes[name].is_a?(Hash)).inspect}" if !@attributes[name].nil? && !@attributes[name].is_a?(Hash) @attributes[name] = { ::I18n.default_site_locale.to_s => @attributes[name] } end - puts "value = #{value.inspect} / #{meth}" + # puts "value = #{value.inspect} / #{meth}" value = if value.is_a?(Hash) (@attributes[name] || {}).merge(value) diff --git a/lib/locomotive/liquid/drops/content.rb b/lib/locomotive/liquid/drops/content.rb index 1aefc759..ae5c536b 100644 --- a/lib/locomotive/liquid/drops/content.rb +++ b/lib/locomotive/liquid/drops/content.rb @@ -21,6 +21,10 @@ module Locomotive self._source.highlighted_field_value end + def _permalink + self._source._permalink + end + end end end diff --git a/lib/locomotive/liquid/tags/editable/base.rb b/lib/locomotive/liquid/tags/editable/base.rb index a2a8e65b..57aaf212 100644 --- a/lib/locomotive/liquid/tags/editable/base.rb +++ b/lib/locomotive/liquid/tags/editable/base.rb @@ -30,7 +30,8 @@ module Locomotive :default_content => default_content_option, :assignable => @options[:assignable], :disabled => false, - :from_parent => false + :from_parent => false, + :_type => self.document_type.to_s }, document_type) end end diff --git a/lib/locomotive/liquid/tags/locale_switcher.rb b/lib/locomotive/liquid/tags/locale_switcher.rb new file mode 100644 index 00000000..a7a77ce6 --- /dev/null +++ b/lib/locomotive/liquid/tags/locale_switcher.rb @@ -0,0 +1,76 @@ +module Locomotive + module Liquid + module Tags + # Display the links to change the locale of the current page + # + # Usage: + # + # {% locale_switcher %} =>
FeaturesFonctionnalités
+ # + # {% locale_switcher label: locale, sep: ' - ' } + # + # options: + # - label: iso (de, fr, en, ...etc), locale (Deutsch, Français, English, ...etc), title (page title) + # - sep: piece of html code seperating 2 locales + # + # notes: + # - "iso" is the default choice for label + # - " | " is the default seperating code + # + class LocaleSwitcher < ::Liquid::Tag + + Syntax = /(#{::Liquid::Expression}+)?/ + + def initialize(tag_name, markup, tokens, context) + @options = { :label => 'iso', :sep => ' | ' } + + if markup =~ Syntax + markup.scan(::Liquid::TagAttributes) { |key, value| @options[key.to_sym] = value.gsub(/"|'/, '') } + + @options[:exclude] = Regexp.new(@options[:exclude]) if @options[:exclude] + else + raise ::Liquid::SyntaxError.new("Syntax Error in 'locale_switcher' - Valid syntax: locale_switcher ") + end + + super + end + + def render(context) + site = context.registers[:site] + current_page = context.registers[:page] + + output = %(
) + + output += site.locales.collect do |locale| + I18n.with_site_locale(locale) do + url = current_page.fullpath_with_locale(locale) + + if current_page.templatized? + url.gsub!('content_type_template', context['content_instance']._permalink) + end + + %(#{link_label(current_page)}) + end + end.join(@options[:sep]) + + output += %(
) + end + + private + + def link_label(current_page) + case @options[:label] + when :iso then I18n.site_locale + when :locale then I18n.t("admin.locales.#{I18n.site_locale}", :locale => I18n.site_locale) + when :title then current_page.title + else + I18n.site_locale + end + end + + end + + ::Liquid::Template.register_tag('locale_switcher', LocaleSwitcher) + end + end +end diff --git a/lib/locomotive/liquid/tags/nav.rb b/lib/locomotive/liquid/tags/nav.rb index f96fce15..053bb4e7 100644 --- a/lib/locomotive/liquid/tags/nav.rb +++ b/lib/locomotive/liquid/tags/nav.rb @@ -76,8 +76,8 @@ module Locomotive icon = @options[:icon] ? '' : '' label = %{#{icon if @options[:icon] != 'after' }#{page.title}#{icon if @options[:icon] == 'after' }} - output = %{} @@ -90,7 +90,7 @@ module Locomotive children = page.children_with_minimal_attributes.reject { |c| !include_page?(c) } if children.present? - output = %{