made very good progress, almost usable
This commit is contained in:
parent
c68eb321ff
commit
ad68826e84
2
Gemfile
2
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'
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -1,3 +1,5 @@
|
||||
require 'ruby-debug'
|
||||
|
||||
module Extensions
|
||||
module Page
|
||||
module Render
|
||||
|
@ -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
|
||||
|
22
doc/TODO
22
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 /<default_site_locale>/....
|
||||
- inline editing
|
||||
|
||||
BACKLOG:
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -21,6 +21,10 @@ module Locomotive
|
||||
self._source.highlighted_field_value
|
||||
end
|
||||
|
||||
def _permalink
|
||||
self._source._permalink
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -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
|
||||
|
76
lib/locomotive/liquid/tags/locale_switcher.rb
Normal file
76
lib/locomotive/liquid/tags/locale_switcher.rb
Normal file
@ -0,0 +1,76 @@
|
||||
module Locomotive
|
||||
module Liquid
|
||||
module Tags
|
||||
# Display the links to change the locale of the current page
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# {% locale_switcher %} => <div id="locale-switcher"><a href="/features" class="current en">Features</a><a href="/fr/fonctionnalites" class="fr">Fonctionnalités</a></div>
|
||||
#
|
||||
# {% 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 <options>")
|
||||
end
|
||||
|
||||
super
|
||||
end
|
||||
|
||||
def render(context)
|
||||
site = context.registers[:site]
|
||||
current_page = context.registers[:page]
|
||||
|
||||
output = %(<div id="locale-switcher">)
|
||||
|
||||
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
|
||||
|
||||
%(<a href="/#{url}" class="#{locale} #{'current' if locale == context['current_locale']}">#{link_label(current_page)}</a>)
|
||||
end
|
||||
end.join(@options[:sep])
|
||||
|
||||
output += %(</div>)
|
||||
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
|
@ -76,8 +76,8 @@ module Locomotive
|
||||
icon = @options[:icon] ? '<span></span>' : ''
|
||||
label = %{#{icon if @options[:icon] != 'after' }#{page.title}#{icon if @options[:icon] == 'after' }}
|
||||
|
||||
output = %{<li id="#{page.slug.dasherize}-link" class="link#{selected} #{css}">}
|
||||
output << %{<a href="/#{page.fullpath}">#{label}</a>}
|
||||
output = %{<li id="#{page.default_slug.dasherize}-link" class="link#{selected} #{css}">}
|
||||
output << %{<a href="/#{page.fullpath_with_locale(I18n.site_locale)}">#{label}</a>}
|
||||
output << render_entry_children(page, depth.succ) if (depth.succ <= @options[:depth].to_i)
|
||||
output << %{</li>}
|
||||
|
||||
@ -90,7 +90,7 @@ module Locomotive
|
||||
|
||||
children = page.children_with_minimal_attributes.reject { |c| !include_page?(c) }
|
||||
if children.present?
|
||||
output = %{<ul id="#{@options[:id]}-#{page.slug.dasherize}">}
|
||||
output = %{<ul id="#{@options[:id]}-#{page.default_slug.dasherize}">}
|
||||
children.each do |c, page|
|
||||
css = []
|
||||
css << 'first' if children.first == c
|
||||
@ -115,8 +115,9 @@ module Locomotive
|
||||
end
|
||||
end
|
||||
|
||||
::Liquid::Template.register_tag('nav', Nav)
|
||||
end
|
||||
|
||||
::Liquid::Template.register_tag('nav', Nav)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -42,7 +42,7 @@ module Locomotive
|
||||
|
||||
page_count, current_page = pagination['total_pages'], pagination['current_page']
|
||||
|
||||
path = context.registers[:page].fullpath
|
||||
path = context.registers[:page].fullpath_with_locale(I18n.site_locale)
|
||||
|
||||
pagination['previous'] = link(I18n.t('pagination.previous'), current_page - 1, path) if pagination['previous_page']
|
||||
pagination['next'] = link(I18n.t('pagination.next'), current_page + 1, path) if pagination['next_page']
|
||||
|
@ -17,7 +17,9 @@ module Locomotive
|
||||
|
||||
render_no_page_error and return if @page.nil?
|
||||
|
||||
output = @page.render(locomotive_context)
|
||||
output = I18n.with_locale(I18n.site_locale) do
|
||||
@page.render(locomotive_context)
|
||||
end
|
||||
|
||||
self.prepare_and_set_response(output)
|
||||
end
|
||||
@ -96,7 +98,7 @@ module Locomotive
|
||||
:current_admin => current_admin
|
||||
}
|
||||
|
||||
::Liquid::Context.new({}, assigns, registers)
|
||||
::Liquid::Context.new({}, assigns, registers, true)
|
||||
end
|
||||
|
||||
def prepare_and_set_response(output)
|
||||
|
@ -29,6 +29,20 @@ namespace :locomotive do
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Prepare for i18n'
|
||||
task :prepare_for_i18n => :environment do
|
||||
Page.skip_callback(:validate, :before)
|
||||
Page.skip_callback(:save, :after)
|
||||
|
||||
I18n.with_site_locale(ENV['LOCALE'] || Locomotive.config.site_locales.first) do
|
||||
Page.all.each do |page|
|
||||
page.template_dependencies = page.template_dependencies
|
||||
page.snippet_dependencies = page.snippet_dependencies
|
||||
page.save(:validate => false)
|
||||
end
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user