Compare commits
8 Commits
Author | SHA1 | Date |
---|---|---|
did | 8658f4229a | |
did | 5dd9481ec2 | |
did | b89d6f2dbd | |
did | 0b27cd5d1b | |
did | e9c1c1d98f | |
did | e1c2687681 | |
did | ad68826e84 | |
did | c68eb321ff |
1
Gemfile
1
Gemfile
|
@ -11,6 +11,7 @@ gem 'devise', '1.3.4'
|
||||||
gem 'devise_bushido_authenticatable', '1.0.0.alpha10', :require => 'devise_cas_authenticatable'
|
gem 'devise_bushido_authenticatable', '1.0.0.alpha10', :require => 'devise_cas_authenticatable'
|
||||||
|
|
||||||
gem 'mongoid', '~> 2.0.2'
|
gem 'mongoid', '~> 2.0.2'
|
||||||
|
gem 'mongoid_i18n', :require => 'mongoid/i18n'
|
||||||
gem 'bson_ext', '~> 1.3.0'
|
gem 'bson_ext', '~> 1.3.0'
|
||||||
gem 'locomotive_mongoid_acts_as_tree', '0.1.5.7', :require => 'mongoid_acts_as_tree'
|
gem 'locomotive_mongoid_acts_as_tree', '0.1.5.7', :require => 'mongoid_acts_as_tree'
|
||||||
gem 'will_paginate', '~> 3.0.0'
|
gem 'will_paginate', '~> 3.0.0'
|
||||||
|
|
|
@ -173,6 +173,9 @@ GEM
|
||||||
activemodel (~> 3.0)
|
activemodel (~> 3.0)
|
||||||
mongo (~> 1.3)
|
mongo (~> 1.3)
|
||||||
tzinfo (~> 0.3.22)
|
tzinfo (~> 0.3.22)
|
||||||
|
mongoid_i18n (0.3.1)
|
||||||
|
bson_ext
|
||||||
|
mongoid (>= 2.0.0)
|
||||||
net-ssh (2.1.4)
|
net-ssh (2.1.4)
|
||||||
nokogiri (1.5.0)
|
nokogiri (1.5.0)
|
||||||
open4 (1.1.0)
|
open4 (1.1.0)
|
||||||
|
@ -316,6 +319,7 @@ DEPENDENCIES
|
||||||
mimetype-fu
|
mimetype-fu
|
||||||
mocha (= 0.9.12)
|
mocha (= 0.9.12)
|
||||||
mongoid (~> 2.0.2)
|
mongoid (~> 2.0.2)
|
||||||
|
mongoid_i18n
|
||||||
pickle
|
pickle
|
||||||
rack-cache
|
rack-cache
|
||||||
rails (= 3.0.10)
|
rails (= 3.0.10)
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
#site-locale-picker
|
||||||
|
%span.hand
|
||||||
|
|
||||||
|
|
||||||
|
%ul
|
||||||
|
- @locales.each_with_index do |locale, index|
|
||||||
|
%li{ :class => "#{'first' if index == 0}" }
|
||||||
|
|
||||||
|
= image_tag "admin/icons/flags/#{locale}.png", :class => 'flag'
|
||||||
|
|
||||||
|
%span.text= locale
|
|
@ -0,0 +1,15 @@
|
||||||
|
class Admin::SiteLocalePickerCell < Cell::Base
|
||||||
|
|
||||||
|
def show(args)
|
||||||
|
site = args[:site]
|
||||||
|
locale = args[:locale].to_s
|
||||||
|
|
||||||
|
if site.locales.empty? || site.locales.size < 2
|
||||||
|
''
|
||||||
|
else
|
||||||
|
@locales = [locale] + (site.locales - [locale])
|
||||||
|
render
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -15,6 +15,8 @@ module Admin
|
||||||
|
|
||||||
before_filter :set_locale
|
before_filter :set_locale
|
||||||
|
|
||||||
|
before_filter :set_site_locale
|
||||||
|
|
||||||
helper_method :sections, :current_site_url, :site_url, :page_url, :current_ability
|
helper_method :sections, :current_site_url, :site_url, :page_url, :current_ability
|
||||||
|
|
||||||
# https://rails.lighthouseapp.com/projects/8994/tickets/1905-apphelpers-within-plugin-not-being-mixed-in
|
# https://rails.lighthouseapp.com/projects/8994/tickets/1905-apphelpers-within-plugin-not-being-mixed-in
|
||||||
|
@ -71,7 +73,25 @@ module Admin
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_locale
|
def set_locale
|
||||||
I18n.locale = current_admin.locale rescue Locomotive.config.default_locale
|
I18n.locale = current_admin.locale rescue Locomotive.config.default_locale # for the back-office
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_site_locale
|
||||||
|
I18n.default_site_locale = current_site.default_locale
|
||||||
|
|
||||||
|
if params[:site_locale].present?
|
||||||
|
session[:site_locale] = params[:site_locale]
|
||||||
|
end
|
||||||
|
|
||||||
|
unless current_site.locales.include?(session[:site_locale])
|
||||||
|
session[:site_locale] = current_site.default_locale
|
||||||
|
end
|
||||||
|
|
||||||
|
I18n.site_locale = session[:site_locale]
|
||||||
|
end
|
||||||
|
|
||||||
|
def back_to_default_site_locale
|
||||||
|
session[:site_locale] = I18n.site_locale = current_site.default_locale
|
||||||
end
|
end
|
||||||
|
|
||||||
# ___ site/page urls builder ___
|
# ___ site/page urls builder ___
|
||||||
|
|
|
@ -11,6 +11,8 @@ module Admin
|
||||||
|
|
||||||
before_filter :authorize_content
|
before_filter :authorize_content
|
||||||
|
|
||||||
|
before_filter :back_to_default_site_locale, :only => %w(new create)
|
||||||
|
|
||||||
helper_method :breadcrumb_root, :breadcrumb_url, :back_url
|
helper_method :breadcrumb_root, :breadcrumb_url, :back_url
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
|
|
@ -5,6 +5,8 @@ module Admin
|
||||||
|
|
||||||
respond_to :json, :only => [:update, :sort, :get_path]
|
respond_to :json, :only => [:update, :sort, :get_path]
|
||||||
|
|
||||||
|
before_filter :back_to_default_site_locale, :only => %w(new create)
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@pages = current_site.all_pages_in_once
|
@pages = current_site.all_pages_in_once
|
||||||
end
|
end
|
||||||
|
|
|
@ -30,4 +30,7 @@ module Admin::SitesHelper
|
||||||
Locomotive.config.multi_sites?
|
Locomotive.config.multi_sites?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def ordered_site_locales(site)
|
||||||
|
site.locales + (Locomotive.config.site_locales - site.locales)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,12 +2,15 @@ class ContentInstance
|
||||||
|
|
||||||
include Mongoid::Document
|
include Mongoid::Document
|
||||||
include Mongoid::Timestamps
|
include Mongoid::Timestamps
|
||||||
|
include Mongoid::I18n
|
||||||
|
|
||||||
## extensions ##
|
## extensions ##
|
||||||
include CustomFields::ProxyClassEnabler
|
include CustomFields::ProxyClassEnabler
|
||||||
include Extensions::Shared::Seo
|
include Extensions::Shared::Seo
|
||||||
|
|
||||||
## fields (dynamic fields) ##
|
## fields (dynamic fields) ##
|
||||||
|
localized_fields :_position_in_list, /^custom_field_/
|
||||||
|
|
||||||
field :_slug
|
field :_slug
|
||||||
field :_position_in_list, :type => Integer, :default => 0
|
field :_position_in_list, :type => Integer, :default => 0
|
||||||
field :_visible, :type => Boolean, :default => true
|
field :_visible, :type => Boolean, :default => true
|
||||||
|
|
|
@ -1,27 +1,28 @@
|
||||||
class EditableElement
|
class EditableElement
|
||||||
|
|
||||||
include Mongoid::Document
|
include Mongoid::Document
|
||||||
|
include Mongoid::I18n
|
||||||
|
|
||||||
## fields ##
|
## fields ##
|
||||||
field :slug
|
field :slug
|
||||||
field :block
|
field :block
|
||||||
field :default_content
|
localized_field :default_content
|
||||||
field :default_attribute
|
field :default_attribute
|
||||||
field :hint
|
field :hint
|
||||||
field :priority, :type => Integer, :default => 0
|
field :priority, :type => Integer, :default => 0
|
||||||
field :disabled, :type => Boolean, :default => false
|
field :disabled, :type => Boolean, :default => false
|
||||||
field :assignable, :type => Boolean, :default => true
|
field :assignable, :type => Boolean, :default => true
|
||||||
field :from_parent, :type => Boolean, :default => false
|
field :from_parent, :type => Boolean, :default => false
|
||||||
|
|
||||||
## associations ##
|
## associations ##
|
||||||
embedded_in :page, :inverse_of => :editable_elements
|
embedded_in :page, :inverse_of => :editable_elements
|
||||||
|
|
||||||
## validations ##
|
## validations ##
|
||||||
validates_presence_of :slug
|
validates_presence_of :slug
|
||||||
|
|
||||||
## scopes ##
|
## scopes ##
|
||||||
scope :by_priority, :order_by => [[:priority, :desc]]
|
scope :by_priority, :order_by => [[:priority, :desc]]
|
||||||
|
|
||||||
## methods ##
|
## methods ##
|
||||||
|
|
||||||
end
|
end
|
|
@ -1,7 +1,11 @@
|
||||||
class EditableFile < EditableElement
|
class EditableFile < EditableElement
|
||||||
|
|
||||||
|
localized_fields :source_filename
|
||||||
|
|
||||||
mount_uploader :source, EditableFileUploader
|
mount_uploader :source, EditableFileUploader
|
||||||
|
|
||||||
|
# localized_field :source
|
||||||
|
|
||||||
def content
|
def content
|
||||||
self.source? ? self.source.url : self.default_content
|
self.source? ? self.source.url : self.default_content
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,12 +1,19 @@
|
||||||
class EditableShortText < EditableElement
|
class EditableShortText < EditableElement
|
||||||
|
|
||||||
## fields ##
|
## fields ##
|
||||||
field :content
|
localized_field :content
|
||||||
|
|
||||||
## methods ##
|
## methods ##
|
||||||
|
|
||||||
def content
|
# def content
|
||||||
self.read_attribute(:content).blank? ? self.default_content : self.read_attribute(: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
|
end
|
||||||
|
|
||||||
|
alias_method_chain :content, :localization
|
||||||
|
|
||||||
end
|
end
|
|
@ -5,9 +5,9 @@ module Extensions
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
included do
|
included do
|
||||||
field :serialized_template, :type => Binary
|
localized_field :serialized_template, :type => Binary
|
||||||
field :template_dependencies, :type => Array, :default => []
|
localized_field :template_dependencies, :type => Array, :default => []
|
||||||
field :snippet_dependencies, :type => Array, :default => []
|
localized_field :snippet_dependencies, :type => Array, :default => []
|
||||||
|
|
||||||
attr_reader :template_changed
|
attr_reader :template_changed
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ module Extensions
|
||||||
module InstanceMethods
|
module InstanceMethods
|
||||||
|
|
||||||
def template
|
def template
|
||||||
@template ||= Marshal.load(read_attribute(:serialized_template).to_s) rescue nil
|
@template ||= Marshal.load(self.serialized_template.to_s) rescue nil
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
|
@ -4,9 +4,9 @@ module Extensions
|
||||||
extend ActiveSupport::Concern
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
included do
|
included do
|
||||||
field :seo_title, :type => String
|
localized_field :seo_title
|
||||||
field :meta_keywords, :type => String
|
localized_field :meta_keywords
|
||||||
field :meta_description, :type => String
|
localized_field :meta_description
|
||||||
end
|
end
|
||||||
|
|
||||||
end # Seo
|
end # Seo
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
module Extensions
|
||||||
|
module Site
|
||||||
|
module I18n
|
||||||
|
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
included do
|
||||||
|
|
||||||
|
## fields ##
|
||||||
|
field :locales, :type => Array, :default => []
|
||||||
|
|
||||||
|
## callbacks ##
|
||||||
|
after_validation :add_missing_locales_for_all_pages
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
module InstanceMethods
|
||||||
|
|
||||||
|
def locales=(array)
|
||||||
|
array = [] if array.blank?; super(array)
|
||||||
|
end
|
||||||
|
|
||||||
|
def default_locale
|
||||||
|
self.locales.first || Locomotive.config.site_locales.first
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def add_missing_locales_for_all_pages
|
||||||
|
if self.locales_changed?
|
||||||
|
list = self.pages.to_a
|
||||||
|
|
||||||
|
while !list.empty? do
|
||||||
|
page = list.pop
|
||||||
|
begin
|
||||||
|
page.send(:set_slug_and_fullpath_for_all_locales, self.locales)
|
||||||
|
|
||||||
|
page.save
|
||||||
|
|
||||||
|
rescue TypeError => e
|
||||||
|
list.insert(0, page)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,6 +1,7 @@
|
||||||
class Page
|
class Page
|
||||||
|
|
||||||
include Locomotive::Mongoid::Document
|
include Locomotive::Mongoid::Document
|
||||||
|
include Mongoid::I18n
|
||||||
|
|
||||||
## Extensions ##
|
## Extensions ##
|
||||||
include Extensions::Page::Tree
|
include Extensions::Page::Tree
|
||||||
|
@ -13,10 +14,10 @@ class Page
|
||||||
include Extensions::Shared::Seo
|
include Extensions::Shared::Seo
|
||||||
|
|
||||||
## fields ##
|
## fields ##
|
||||||
field :title
|
localized_field :title
|
||||||
field :slug
|
localized_field :slug
|
||||||
field :fullpath
|
localized_field :fullpath
|
||||||
field :raw_template
|
localized_field :raw_template
|
||||||
field :published, :type => Boolean, :default => false
|
field :published, :type => Boolean, :default => false
|
||||||
field :cache_strategy, :default => 'none'
|
field :cache_strategy, :default => 'none'
|
||||||
|
|
||||||
|
@ -32,6 +33,7 @@ class Page
|
||||||
after_initialize :set_default_raw_template
|
after_initialize :set_default_raw_template
|
||||||
before_validation :normalize_slug
|
before_validation :normalize_slug
|
||||||
before_save { |p| p.fullpath = p.fullpath(true) }
|
before_save { |p| p.fullpath = p.fullpath(true) }
|
||||||
|
before_create :set_slug_and_fullpath_for_all_locales
|
||||||
before_destroy :do_not_remove_index_and_404_pages
|
before_destroy :do_not_remove_index_and_404_pages
|
||||||
|
|
||||||
## validations ##
|
## validations ##
|
||||||
|
@ -61,9 +63,13 @@ class Page
|
||||||
self.index? || self.not_found?
|
self.index? || self.not_found?
|
||||||
end
|
end
|
||||||
|
|
||||||
def fullpath(force = false)
|
def default_slug
|
||||||
if read_attribute(:fullpath).present? && !force
|
I18n.with_site_locale(I18n.default_site_locale) { self.slug }
|
||||||
return read_attribute(:fullpath)
|
end
|
||||||
|
|
||||||
|
def fullpath_with_building(force = false)
|
||||||
|
if self.fullpath_without_building.present? && !force
|
||||||
|
return self.fullpath_without_building
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.index? || self.not_found?
|
if self.index? || self.not_found?
|
||||||
|
@ -75,6 +81,18 @@ class Page
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
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?
|
def with_cache?
|
||||||
self.cache_strategy != 'none'
|
self.cache_strategy != 'none'
|
||||||
end
|
end
|
||||||
|
@ -104,4 +122,14 @@ class Page
|
||||||
self.raw_template ||= I18n.t('attributes.defaults.pages.other.body')
|
self.raw_template ||= I18n.t('attributes.defaults.pages.other.body')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_slug_and_fullpath_for_all_locales(locales = nil)
|
||||||
|
(locales || self.site.locales).each do |locale|
|
||||||
|
I18n.with_site_locale(locale) do
|
||||||
|
%w(slug fullpath).each do |meth|
|
||||||
|
self.send(:"#{meth}=", self.send(meth.to_sym))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
class Site
|
class Site
|
||||||
|
|
||||||
include Locomotive::Mongoid::Document
|
include Locomotive::Mongoid::Document
|
||||||
|
include Mongoid::I18n
|
||||||
|
|
||||||
## Extensions ##
|
## Extensions ##
|
||||||
extend Extensions::Site::SubdomainDomains
|
extend Extensions::Site::SubdomainDomains
|
||||||
extend Extensions::Site::FirstInstallation
|
extend Extensions::Site::FirstInstallation
|
||||||
|
include Extensions::Site::I18n
|
||||||
include Extensions::Shared::Seo
|
include Extensions::Shared::Seo
|
||||||
|
|
||||||
## fields ##
|
## fields ##
|
||||||
|
|
|
@ -9,6 +9,17 @@
|
||||||
= f.input :meta_keywords
|
= f.input :meta_keywords
|
||||||
= f.input :meta_description
|
= f.input :meta_description
|
||||||
|
|
||||||
|
- if can?(:manage, current_site)
|
||||||
|
= f.foldable_inputs :name => :locales, :class => 'language locales' do
|
||||||
|
= f.custom_input :locales, { :css => 'full', :with_label => false } do
|
||||||
|
#locales
|
||||||
|
- ordered_site_locales(@site).each do |locale|
|
||||||
|
%span
|
||||||
|
= check_box_tag 'site[locales][]', locale, @site.locales.include?(locale), :id => "site-locales-#{locale}"
|
||||||
|
%label{ :for => "site-locales-#{locale}" }
|
||||||
|
= image_tag "admin/icons/flags/#{locale}.png"
|
||||||
|
= t("admin.locales.#{locale}")
|
||||||
|
|
||||||
- if can?(:point, Site)
|
- if can?(:point, Site)
|
||||||
- if manage_subdomain_or_domains?
|
- if manage_subdomain_or_domains?
|
||||||
= f.foldable_inputs :name => :access_points, :class => 'editable-list off' do
|
= f.foldable_inputs :name => :access_points, :class => 'editable-list off' do
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
- content_for :submenu do
|
- content_for :submenu do
|
||||||
= render_cell 'admin/settings_menu', :show
|
= render_cell 'admin/settings_menu', :show
|
||||||
|
|
||||||
|
- content_for :actions do
|
||||||
|
= render_cell 'admin/site_locale_picker', :show, :site => current_site, :locale => I18n.site_locale
|
||||||
|
|
||||||
- content_for :buttons do
|
- content_for :buttons do
|
||||||
- if can?(:manage, @site)
|
- if can?(:manage, @site)
|
||||||
|
|
|
@ -40,8 +40,7 @@
|
||||||
= f.radio_button :locale, locale
|
= f.radio_button :locale, locale
|
||||||
%label{ :for => "my_account_locale_#{locale.downcase}" }
|
%label{ :for => "my_account_locale_#{locale.downcase}" }
|
||||||
= image_tag "admin/icons/flags/#{locale}.png"
|
= image_tag "admin/icons/flags/#{locale}.png"
|
||||||
= t(".#{locale}")
|
= t("admin.locales.#{locale}")
|
||||||
/
|
|
||||||
|
|
||||||
|
|
||||||
= render 'admin/shared/form_actions', :button_label => :update
|
= render 'admin/shared/form_actions', :button_label => :update
|
||||||
|
|
|
@ -1,2 +1,4 @@
|
||||||
- if can? :manage, ContentType
|
- if can? :manage, ContentType
|
||||||
= link_to content_tag(:em) + content_tag(:span, t('admin.content_types.index.new')), new_admin_content_type_url
|
= link_to content_tag(:em) + content_tag(:span, t('admin.content_types.index.new')), new_admin_content_type_url
|
||||||
|
|
||||||
|
= render_cell 'admin/site_locale_picker', :show, :site => current_site, :locale => I18n.site_locale
|
|
@ -93,6 +93,7 @@ stylesheets:
|
||||||
- public/stylesheets/admin/formtastic_changes.css
|
- public/stylesheets/admin/formtastic_changes.css
|
||||||
- public/stylesheets/admin/assets.css
|
- public/stylesheets/admin/assets.css
|
||||||
- public/stylesheets/admin/sites_picker.css
|
- public/stylesheets/admin/sites_picker.css
|
||||||
|
- public/stylesheets/admin/site_locale_picker.css
|
||||||
- public/stylesheets/admin/application.css
|
- public/stylesheets/admin/application.css
|
||||||
- public/stylesheets/admin/safari.css
|
- public/stylesheets/admin/safari.css
|
||||||
- public/stylesheets/admin/guiders-1.1.0.css
|
- public/stylesheets/admin/guiders-1.1.0.css
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
de:
|
de:
|
||||||
admin:
|
admin:
|
||||||
|
locales:
|
||||||
|
en: Englisch
|
||||||
|
de: Deutsch
|
||||||
|
fr: Französisch
|
||||||
|
pt-BR: "Bras. Portugisisch"
|
||||||
|
it: "Italienisch"
|
||||||
|
nl: "Holländer"
|
||||||
|
es: "Spanisch"
|
||||||
|
ru: "Russisch"
|
||||||
|
|
||||||
buttons:
|
buttons:
|
||||||
login: Einloggen
|
login: Einloggen
|
||||||
send_password: Senden
|
send_password: Senden
|
||||||
|
@ -157,14 +167,6 @@ de:
|
||||||
edit:
|
edit:
|
||||||
help: "Deinen Namen kannst du durch darauf klicken ändern."
|
help: "Deinen Namen kannst du durch darauf klicken ändern."
|
||||||
new_site: Neue Webseite
|
new_site: Neue Webseite
|
||||||
en: Englisch
|
|
||||||
de: Deutsch
|
|
||||||
fr: Französisch
|
|
||||||
pt-BR: "Bras. Portugisisch"
|
|
||||||
it: "Italienisch"
|
|
||||||
nl: "Holländer"
|
|
||||||
es: "Spanisch"
|
|
||||||
ru: "Russisch"
|
|
||||||
ask_for_name: "Bitte gib deinen neuen Namen an"
|
ask_for_name: "Bitte gib deinen neuen Namen an"
|
||||||
|
|
||||||
theme_assets:
|
theme_assets:
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
en:
|
en:
|
||||||
admin:
|
admin:
|
||||||
|
locales:
|
||||||
|
en: English
|
||||||
|
de: German
|
||||||
|
fr: French
|
||||||
|
pt-BR: "Brazilian Portuguese"
|
||||||
|
it: Italian
|
||||||
|
nl: Dutch
|
||||||
|
es: Spanish
|
||||||
|
ru: Russian
|
||||||
|
|
||||||
buttons:
|
buttons:
|
||||||
login: Log in
|
login: Log in
|
||||||
send_password: Send
|
send_password: Send
|
||||||
|
@ -168,14 +178,6 @@ en:
|
||||||
edit:
|
edit:
|
||||||
help: "Your name can be updated by clicking it. To apply your changes, click on the \"Save\" button."
|
help: "Your name can be updated by clicking it. To apply your changes, click on the \"Save\" button."
|
||||||
new_site: new site
|
new_site: new site
|
||||||
en: English
|
|
||||||
de: German
|
|
||||||
fr: French
|
|
||||||
pt-BR: "Brazilian Portuguese"
|
|
||||||
it: Italian
|
|
||||||
nl: Dutch
|
|
||||||
es: Spanish
|
|
||||||
ru: Russian
|
|
||||||
ask_for_name: "Please type your new name"
|
ask_for_name: "Please type your new name"
|
||||||
|
|
||||||
theme_assets:
|
theme_assets:
|
||||||
|
|
|
@ -1,5 +1,15 @@
|
||||||
fr:
|
fr:
|
||||||
admin:
|
admin:
|
||||||
|
locales:
|
||||||
|
en: en Anglais
|
||||||
|
de: en Allemand
|
||||||
|
fr: en Français
|
||||||
|
pt-BR: "en Portugais"
|
||||||
|
it: "en Italien"
|
||||||
|
nl: "en Hollandais"
|
||||||
|
es: en Espagnol
|
||||||
|
ru: en Russe
|
||||||
|
|
||||||
errors:
|
errors:
|
||||||
"500":
|
"500":
|
||||||
title: Erreur applicative
|
title: Erreur applicative
|
||||||
|
@ -169,15 +179,6 @@ fr:
|
||||||
edit:
|
edit:
|
||||||
help: "Votre nom est modifiable en cliquant dessus. Pour appliquer votre modification, cliquez après sur le bouton \"Modifier\""
|
help: "Votre nom est modifiable en cliquant dessus. Pour appliquer votre modification, cliquez après sur le bouton \"Modifier\""
|
||||||
new_site: nouveau site
|
new_site: nouveau site
|
||||||
en: en Anglais
|
|
||||||
de: en Allemand
|
|
||||||
fr: en Français
|
|
||||||
pt-BR: "en Portugais"
|
|
||||||
it: "en Italien"
|
|
||||||
nl: "en Hollandais"
|
|
||||||
es: en Espagnol
|
|
||||||
ru: en Russe
|
|
||||||
|
|
||||||
ask_for_name: "Veuillez entrer le nouveau nom"
|
ask_for_name: "Veuillez entrer le nouveau nom"
|
||||||
|
|
||||||
theme_assets:
|
theme_assets:
|
||||||
|
|
|
@ -10,6 +10,7 @@ en:
|
||||||
raw_template: Template
|
raw_template: Template
|
||||||
credentials: Credentials
|
credentials: Credentials
|
||||||
language: Language
|
language: Language
|
||||||
|
locales: Locales
|
||||||
sites: Sites
|
sites: Sites
|
||||||
access_points: Access points
|
access_points: Access points
|
||||||
memberships: Accounts
|
memberships: Accounts
|
||||||
|
@ -67,6 +68,7 @@ en:
|
||||||
seo_title: "Define a global value here which should be used as the value for the title tag in the head section."
|
seo_title: "Define a global value here which should be used as the value for the title tag in the head section."
|
||||||
meta_keywords: "Meta keywords used within the head tag of the page. They are separated by a comma. Required for SEO."
|
meta_keywords: "Meta keywords used within the head tag of the page. They are separated by a comma. Required for SEO."
|
||||||
meta_description: "Meta description used within the head tag of the page. Required for SEO."
|
meta_description: "Meta description used within the head tag of the page. Required for SEO."
|
||||||
|
locales: "Drag&drop a flag to the first position to make it the default one."
|
||||||
domain_name: "ex: locomotiveapp.org"
|
domain_name: "ex: locomotiveapp.org"
|
||||||
robots_txt: "Content of the <span class='code'>/robots.txt</span> file. Check the following <a href='http://www.w3.org/TR/html4/appendix/notes.html#h-B.4.1.1'>url</a> for more information."
|
robots_txt: "Content of the <span class='code'>/robots.txt</span> file. Check the following <a href='http://www.w3.org/TR/html4/appendix/notes.html#h-B.4.1.1'>url</a> for more information."
|
||||||
theme_asset:
|
theme_asset:
|
||||||
|
|
|
@ -9,11 +9,11 @@ defaults: &defaults
|
||||||
|
|
||||||
development:
|
development:
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
database: locomotive_dev
|
database: locomotive_i18n_dev
|
||||||
|
|
||||||
test:
|
test:
|
||||||
<<: *defaults
|
<<: *defaults
|
||||||
database: locomotive_test
|
database: locomotive_i18n_test
|
||||||
|
|
||||||
# set these environment variables on your prod server
|
# set these environment variables on your prod server
|
||||||
production:
|
production:
|
||||||
|
|
37
doc/TODO
37
doc/TODO
|
@ -1,5 +1,42 @@
|
||||||
BOARD:
|
BOARD:
|
||||||
|
|
||||||
|
- i18n (in progress)
|
||||||
|
x site locales
|
||||||
|
x model
|
||||||
|
x ui
|
||||||
|
x locale picker
|
||||||
|
x patches
|
||||||
|
x i18n
|
||||||
|
x mongoid-i18n
|
||||||
|
x rendering engine
|
||||||
|
x get locale
|
||||||
|
x render the right version
|
||||||
|
x contents
|
||||||
|
x store the site locale value
|
||||||
|
x pages
|
||||||
|
x title / slug / fullpath / seo
|
||||||
|
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)
|
||||||
|
- others ?) -
|
||||||
|
- theme_assets
|
||||||
|
- other problems to solve:
|
||||||
|
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.
|
||||||
|
- set the page slug for all the site locales
|
||||||
|
- default site locale even if the i18n feature is disabled (the disable procedure is missing btw)
|
||||||
|
- redirect for the default site locale if urls like /<default_site_locale>/....
|
||||||
|
- inline editing
|
||||||
|
- with_scope is broken
|
||||||
|
- refactor
|
||||||
|
|
||||||
BACKLOG:
|
BACKLOG:
|
||||||
|
|
||||||
- custom_fields:
|
- custom_fields:
|
||||||
|
|
|
@ -9,6 +9,7 @@ require 'locomotive/dragonfly'
|
||||||
require 'locomotive/liquid'
|
require 'locomotive/liquid'
|
||||||
require 'locomotive/mongoid'
|
require 'locomotive/mongoid'
|
||||||
require 'locomotive/carrierwave'
|
require 'locomotive/carrierwave'
|
||||||
|
require 'locomotive/i18n'
|
||||||
require 'locomotive/custom_fields'
|
require 'locomotive/custom_fields'
|
||||||
require 'locomotive/httparty'
|
require 'locomotive/httparty'
|
||||||
require 'locomotive/inherited_resources'
|
require 'locomotive/inherited_resources'
|
||||||
|
|
|
@ -8,6 +8,7 @@ module Locomotive
|
||||||
# :forbidden_paths => %w{layouts snippets stylesheets javascripts assets admin system api},
|
# :forbidden_paths => %w{layouts snippets stylesheets javascripts assets admin system api},
|
||||||
:reserved_slugs => %w{stylesheets javascripts assets admin images api pages edit},
|
:reserved_slugs => %w{stylesheets javascripts assets admin images api pages edit},
|
||||||
:locales => %w{en de fr pt-BR it nl es ru},
|
:locales => %w{en de fr pt-BR it nl es ru},
|
||||||
|
:site_locales => %w{en de fr pt-BR it nl es ru},
|
||||||
:cookie_key => '_locomotive_session',
|
:cookie_key => '_locomotive_session',
|
||||||
:enable_logs => false,
|
:enable_logs => false,
|
||||||
:hosting => :auto,
|
:hosting => :auto,
|
||||||
|
@ -23,7 +24,7 @@ module Locomotive
|
||||||
:entitystore => URI.encode("file:#{Rails.root}/tmp/dragonfly/cache/body")
|
:entitystore => URI.encode("file:#{Rails.root}/tmp/dragonfly/cache/body")
|
||||||
},
|
},
|
||||||
:devise_modules => [:database_authenticatable, :recoverable, :rememberable, :trackable, :validatable, :encryptable, { :encryptor => :sha1 }],
|
:devise_modules => [:database_authenticatable, :recoverable, :rememberable, :trackable, :validatable, :encryptable, { :encryptor => :sha1 }],
|
||||||
:context_assign_extensions => { }
|
:context_assign_extensions => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
cattr_accessor :settings
|
cattr_accessor :settings
|
||||||
|
|
|
@ -23,6 +23,13 @@ module CustomFields
|
||||||
module Category
|
module Category
|
||||||
class Item
|
class Item
|
||||||
|
|
||||||
|
include Mongoid::I18n
|
||||||
|
|
||||||
|
localized_fields :name, :position
|
||||||
|
|
||||||
|
field :name
|
||||||
|
field :position, :type => Integer, :default => 0
|
||||||
|
|
||||||
def to_liquid
|
def to_liquid
|
||||||
{ 'id' => self._id.to_s, 'name' => self.name }
|
{ 'id' => self._id.to_s, 'name' => self.name }
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,6 +5,7 @@ require 'json/pure'
|
||||||
require 'devise'
|
require 'devise'
|
||||||
require 'mongoid'
|
require 'mongoid'
|
||||||
require 'mongoid_acts_as_tree'
|
require 'mongoid_acts_as_tree'
|
||||||
|
require 'mongoid/i18n'
|
||||||
require 'will_paginate'
|
require 'will_paginate'
|
||||||
require 'haml'
|
require 'haml'
|
||||||
require 'liquid'
|
require 'liquid'
|
||||||
|
|
|
@ -0,0 +1,213 @@
|
||||||
|
# require 'ruby-debug'
|
||||||
|
## patches for the i18n support (aka multi languages support)
|
||||||
|
require 'i18n'
|
||||||
|
|
||||||
|
module I18n
|
||||||
|
class Config
|
||||||
|
def site_locale
|
||||||
|
@site_locale ||= default_site_locale
|
||||||
|
end
|
||||||
|
|
||||||
|
def site_locale=(site_locale)
|
||||||
|
@site_locale = site_locale.to_sym rescue nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def default_site_locale
|
||||||
|
@@default_site_locale ||= :en
|
||||||
|
end
|
||||||
|
|
||||||
|
def default_site_locale=(site_locale)
|
||||||
|
@@default_site_locale = site_locale.to_sym rescue nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class << self
|
||||||
|
# Write methods which delegates to the configuration object
|
||||||
|
%w(site_locale default_site_locale).each do |method|
|
||||||
|
module_eval <<-DELEGATORS, __FILE__, __LINE__ + 1
|
||||||
|
def #{method}
|
||||||
|
config.#{method}
|
||||||
|
end
|
||||||
|
|
||||||
|
def #{method}=(value)
|
||||||
|
config.#{method} = (value)
|
||||||
|
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 I18n
|
||||||
|
class LocalizedField < Hash
|
||||||
|
|
||||||
|
attr_accessor :type
|
||||||
|
|
||||||
|
def initialize(type = nil)
|
||||||
|
self.type = type || Object
|
||||||
|
super nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def [](key)
|
||||||
|
self.type.set(super(key))
|
||||||
|
end
|
||||||
|
|
||||||
|
def []=(key, value)
|
||||||
|
super(key, self.type.set(value))
|
||||||
|
end
|
||||||
|
|
||||||
|
def merge(other_hash, &block)
|
||||||
|
# puts "merging #{other_hash.inspect}"
|
||||||
|
converted_hash = {}
|
||||||
|
other_hash.each { |k, v| converted_hash[k] = self.type.set(v) }
|
||||||
|
# puts "converted_hash = #{converted_hash.inspect}"
|
||||||
|
super(converted_hash, &block)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# DIRTY MONKEY PATCHING BEFORE THE REFACTORING
|
||||||
|
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(options[:type]))
|
||||||
|
end
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def localized_field?(name)
|
||||||
|
(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 # either nil or true
|
||||||
|
define_method(meth) do
|
||||||
|
value = read_attribute(name)
|
||||||
|
if value.is_a?(Hash)
|
||||||
|
converted_value = options[:default].merge(value)
|
||||||
|
|
||||||
|
value = converted_value[::I18n.site_locale.to_s]
|
||||||
|
|
||||||
|
value.to_s.empty? ? converted_value[::I18n.default_site_locale.to_s] : value
|
||||||
|
else
|
||||||
|
value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
define_method(meth) do
|
||||||
|
value = read_attribute(name)
|
||||||
|
if value.is_a?(Hash)
|
||||||
|
converted_value = options[:default].merge(value)
|
||||||
|
options[:default].merge(value)[::I18n.site_locale.to_s]
|
||||||
|
else
|
||||||
|
value
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
define_method("#{meth}=") do |value|
|
||||||
|
if !@attributes[name].nil? && !@attributes[name].is_a?(Hash)
|
||||||
|
# existing value but not localized yet
|
||||||
|
old_value = @attributes[name]
|
||||||
|
@attributes[name] = options[:default].merge(::I18n.default_site_locale.to_s => old_value)
|
||||||
|
end
|
||||||
|
|
||||||
|
@attributes[name] ||= options[:default]
|
||||||
|
|
||||||
|
@attributes[name] = options[:default].merge(@attributes[name]) unless @attributes[name].is_a?(LocalizedField)
|
||||||
|
|
||||||
|
value = if value.is_a?(Hash)
|
||||||
|
@attributes[name].merge(value)
|
||||||
|
else
|
||||||
|
@attributes[name].merge(::I18n.site_locale.to_s => value)
|
||||||
|
end
|
||||||
|
|
||||||
|
value = value.delete_if { |key, value| value.to_s.empty? } if options[:clear_empty_values] != false
|
||||||
|
|
||||||
|
write_attribute(name, value)
|
||||||
|
end
|
||||||
|
|
||||||
|
define_method("#{meth}_translations") { read_attribute(name) }
|
||||||
|
|
||||||
|
if options[:clear_empty_values] != false
|
||||||
|
define_method("#{meth}_translations=") { |value| write_attribute(name, value.delete_if { |key, value| value.blank? }) }
|
||||||
|
else
|
||||||
|
define_method("#{meth}_translations=") { |value| write_attribute(name, value) }
|
||||||
|
end
|
||||||
|
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -21,6 +21,10 @@ module Locomotive
|
||||||
self._source.highlighted_field_value
|
self._source.highlighted_field_value
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def _permalink
|
||||||
|
self._source._permalink
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -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
|
|
@ -56,14 +56,15 @@ module Locomotive
|
||||||
|
|
||||||
# Determines root node for the list
|
# Determines root node for the list
|
||||||
def fetch_entries(context)
|
def fetch_entries(context)
|
||||||
|
@current_site = context.registers[:site]
|
||||||
@current_page = context.registers[:page]
|
@current_page = context.registers[:page]
|
||||||
|
|
||||||
children = (case @source
|
children = (case @source
|
||||||
when 'site' then context.registers[:site].pages.root.minimal_attributes.first # start from home page
|
when 'site' then @current_site.pages.root.minimal_attributes.first # start from home page
|
||||||
when 'parent' then @current_page.parent || @current_page
|
when 'parent' then @current_page.parent || @current_page
|
||||||
when 'page' then @current_page
|
when 'page' then @current_page
|
||||||
else
|
else
|
||||||
context.registers[:site].pages.fullpath(@source).minimal_attributes.first
|
@current_site.pages.fullpath(@source).minimal_attributes.first
|
||||||
end).children_with_minimal_attributes.to_a
|
end).children_with_minimal_attributes.to_a
|
||||||
|
|
||||||
children.delete_if { |p| !include_page?(p) }
|
children.delete_if { |p| !include_page?(p) }
|
||||||
|
@ -73,11 +74,13 @@ module Locomotive
|
||||||
def render_entry_link(page, css, depth)
|
def render_entry_link(page, css, depth)
|
||||||
selected = @current_page.fullpath =~ /^#{page.fullpath}/ ? ' on' : ''
|
selected = @current_page.fullpath =~ /^#{page.fullpath}/ ? ' on' : ''
|
||||||
|
|
||||||
|
page.site = @current_site
|
||||||
|
|
||||||
icon = @options[:icon] ? '<span></span>' : ''
|
icon = @options[:icon] ? '<span></span>' : ''
|
||||||
label = %{#{icon if @options[:icon] != 'after' }#{page.title}#{icon if @options[:icon] == 'after' }}
|
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 = %{<li id="#{page.default_slug.dasherize}-link" class="link#{selected} #{css}">}
|
||||||
output << %{<a href="/#{page.fullpath}">#{label}</a>}
|
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 << render_entry_children(page, depth.succ) if (depth.succ <= @options[:depth].to_i)
|
||||||
output << %{</li>}
|
output << %{</li>}
|
||||||
|
|
||||||
|
@ -90,7 +93,7 @@ module Locomotive
|
||||||
|
|
||||||
children = page.children_with_minimal_attributes.reject { |c| !include_page?(c) }
|
children = page.children_with_minimal_attributes.reject { |c| !include_page?(c) }
|
||||||
if children.present?
|
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|
|
children.each do |c, page|
|
||||||
css = []
|
css = []
|
||||||
css << 'first' if children.first == c
|
css << 'first' if children.first == c
|
||||||
|
@ -115,8 +118,9 @@ module Locomotive
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
::Liquid::Template.register_tag('nav', Nav)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
::Liquid::Template.register_tag('nav', Nav)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -42,7 +42,7 @@ module Locomotive
|
||||||
|
|
||||||
page_count, current_page = pagination['total_pages'], pagination['current_page']
|
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['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']
|
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?
|
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)
|
self.prepare_and_set_response(output)
|
||||||
end
|
end
|
||||||
|
@ -33,6 +35,12 @@ module Locomotive
|
||||||
path.gsub!(/\.[a-zA-Z][a-zA-Z0-9]{2,}$/, '') # remove the page extension
|
path.gsub!(/\.[a-zA-Z][a-zA-Z0-9]{2,}$/, '') # remove the page extension
|
||||||
path.gsub!(/^\//, '') # remove the leading slash
|
path.gsub!(/^\//, '') # remove the leading slash
|
||||||
|
|
||||||
|
# extract the site locale
|
||||||
|
if path =~ /^(#{current_site.locales.join('|')})+(\/|$)/
|
||||||
|
I18n.site_locale = $1
|
||||||
|
path.gsub!($1 + $2, '')
|
||||||
|
end
|
||||||
|
|
||||||
path = 'index' if path.blank?
|
path = 'index' if path.blank?
|
||||||
|
|
||||||
if path != 'index'
|
if path != 'index'
|
||||||
|
@ -67,7 +75,10 @@ module Locomotive
|
||||||
'params' => self.params,
|
'params' => self.params,
|
||||||
'url' => request.url,
|
'url' => request.url,
|
||||||
'now' => Time.now.utc,
|
'now' => Time.now.utc,
|
||||||
'today' => Date.today
|
'today' => Date.today,
|
||||||
|
'default_locale' => I18n.default_site_locale.to_s,
|
||||||
|
'current_locale' => I18n.site_locale.to_s,
|
||||||
|
'locales' => current_site.locales
|
||||||
}
|
}
|
||||||
|
|
||||||
assigns.merge!(Locomotive.config.context_assign_extensions)
|
assigns.merge!(Locomotive.config.context_assign_extensions)
|
||||||
|
@ -87,7 +98,7 @@ module Locomotive
|
||||||
:current_admin => current_admin
|
:current_admin => current_admin
|
||||||
}
|
}
|
||||||
|
|
||||||
::Liquid::Context.new({}, assigns, registers)
|
::Liquid::Context.new({}, assigns, registers, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
def prepare_and_set_response(output)
|
def prepare_and_set_response(output)
|
||||||
|
|
|
@ -29,6 +29,27 @@ namespace :locomotive do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
desc 'Prepare for i18n'
|
||||||
|
task :prepare_for_i18n => :environment do
|
||||||
|
Site.all.each do |site|
|
||||||
|
if site.locales.empty?
|
||||||
|
site.locales = [Locomotive.config.site_locales.first]
|
||||||
|
site.save
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
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'
|
desc 'Import a remote template described by its URL -- 2 options: SITE=name or id, RESET=by default false'
|
||||||
task :import => :environment do
|
task :import => :environment do
|
||||||
url, site_name_or_id, reset = ENV['URL'], ENV['SITE'], Boolean.set(ENV['RESET']) || false
|
url, site_name_or_id, reset = ENV['URL'], ENV['SITE'], Boolean.set(ENV['RESET']) || false
|
||||||
|
|
|
@ -22,6 +22,7 @@ Gem::Specification.new do |s|
|
||||||
s.add_dependency 'devise', '1.3.4'
|
s.add_dependency 'devise', '1.3.4'
|
||||||
s.add_dependency 'devise_bushido_authenticatable', '1.0.0.alpha10'
|
s.add_dependency 'devise_bushido_authenticatable', '1.0.0.alpha10'
|
||||||
s.add_dependency 'mongoid', '2.0.2'
|
s.add_dependency 'mongoid', '2.0.2'
|
||||||
|
s.add_dependency 'mongoid_i18n'
|
||||||
s.add_dependency 'bson_ext', '~> 1.3.0'
|
s.add_dependency 'bson_ext', '~> 1.3.0'
|
||||||
s.add_dependency 'locomotive_mongoid_acts_as_tree', '0.1.5.7'
|
s.add_dependency 'locomotive_mongoid_acts_as_tree', '0.1.5.7'
|
||||||
s.add_dependency 'will_paginate', '~> 3.0.0'
|
s.add_dependency 'will_paginate', '~> 3.0.0'
|
||||||
|
|
|
@ -165,4 +165,11 @@ $(document).ready(function() {
|
||||||
.trigger('refresh');
|
.trigger('refresh');
|
||||||
|
|
||||||
$('.formtastic fieldset.inputs ol li:not(.item)').last().addClass('last');
|
$('.formtastic fieldset.inputs ol li:not(.item)').last().addClass('last');
|
||||||
|
|
||||||
|
// site locale picker
|
||||||
|
$('#site-locale-picker').hover(function() { $(this).addClass('open'); }, function() { $(this).removeClass('open'); })
|
||||||
|
.find('li:gt(0)').click(function(e) {
|
||||||
|
var locale = $(this).find('.text').html();
|
||||||
|
addParameterToURL('site_locale', locale);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -70,5 +70,6 @@ $(document).ready(function() {
|
||||||
});
|
});
|
||||||
}).hide();
|
}).hide();
|
||||||
|
|
||||||
|
// locales
|
||||||
|
$('#locales').sortable({ items: 'span', handle: 'label', tolerance: 'pointer', appendTo: 'body' });
|
||||||
});
|
});
|
||||||
|
|
|
@ -13,6 +13,27 @@ function makeSlug(val, sep) { // code largely inspired by http://www.thewebsitet
|
||||||
return val.toLowerCase();
|
return val.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function addParameterToURL(key, value) { // code from http://stackoverflow.com/questions/486896/adding-a-parameter-to-the-url-with-javascript
|
||||||
|
key = encodeURIComponent(key); value = encodeURIComponent(value);
|
||||||
|
|
||||||
|
var kvp = document.location.search.substr(1).split('&');
|
||||||
|
|
||||||
|
var i = kvp.length; var x; while(i--) {
|
||||||
|
x = kvp[i].split('=');
|
||||||
|
|
||||||
|
if (x[0] == key) {
|
||||||
|
x[1] = value;
|
||||||
|
kvp[i] = x.join('=');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i < 0) { kvp[kvp.length] = [key,value].join('='); }
|
||||||
|
|
||||||
|
//this will reload the page, it's likely better to store this until finished
|
||||||
|
document.location.search = kvp.join('&');
|
||||||
|
}
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
String.prototype.trim = function() {
|
String.prototype.trim = function() {
|
||||||
return this.replace(/^\s+/g, '').replace(/\s+$/g, '');
|
return this.replace(/^\s+/g, '').replace(/\s+$/g, '');
|
||||||
|
|
|
@ -508,7 +508,7 @@ form.formtastic fieldset ol li.has-many ul li.template span.actions button span
|
||||||
font-size: 0.8em;
|
font-size: 0.8em;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ___ my account ___ */
|
/* ___ language / locales ___ */
|
||||||
|
|
||||||
form.formtastic fieldset.language li.full span {
|
form.formtastic fieldset.language li.full span {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -535,6 +535,14 @@ form.formtastic fieldset.language li.full span input {
|
||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
form.formtastic fieldset.locales li.full span:first-child label {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
form.formtastic fieldset.locales p.inline-hints {
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
/* ___ membership ___ */
|
/* ___ membership ___ */
|
||||||
|
|
||||||
form.formtastic fieldset.email li.full input {
|
form.formtastic fieldset.email li.full input {
|
||||||
|
|
|
@ -107,7 +107,8 @@
|
||||||
background: transparent url(/images/admin/menu/submenu/action-border.png) repeat-y left 0; }
|
background: transparent url(/images/admin/menu/submenu/action-border.png) repeat-y left 0; }
|
||||||
#submenu > .action a {
|
#submenu > .action a {
|
||||||
margin-top: 18px;
|
margin-top: 18px;
|
||||||
display: inline-block;
|
display: block;
|
||||||
|
float: left;
|
||||||
background: rgba(0, 0, 0, 0.4);
|
background: rgba(0, 0, 0, 0.4);
|
||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
-moz-border-radius: 16px;
|
-moz-border-radius: 16px;
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
/* ___ AUTOMATICALLY GENERATED: see admin/site_locale_picker.scss for the source file */
|
||||||
|
/* ___ rounded ___ */
|
||||||
|
/* ___ box shadow ___ */
|
||||||
|
/* ___ others ___ */
|
||||||
|
#site-locale-picker {
|
||||||
|
position: relative;
|
||||||
|
float: right;
|
||||||
|
margin: 18px 0 0 10px;
|
||||||
|
padding: 0px 25px 0 10px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
background: rgba(0, 0, 0, 0.4);
|
||||||
|
border-radius: 16px;
|
||||||
|
-moz-border-radius: 16px;
|
||||||
|
-webkit-border-radius: 16px; }
|
||||||
|
#site-locale-picker:hover {
|
||||||
|
border-color: black;
|
||||||
|
border-radius: 12px;
|
||||||
|
-moz-border-radius: 12px;
|
||||||
|
-webkit-border-radius: 12px; }
|
||||||
|
#site-locale-picker .hand {
|
||||||
|
position: absolute;
|
||||||
|
top: 7px;
|
||||||
|
right: 7px;
|
||||||
|
height: 7px;
|
||||||
|
width: 12px;
|
||||||
|
background: transparent url(/images/admin/menu/icons.png) no-repeat 0px -16px; }
|
||||||
|
#site-locale-picker ul {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px; }
|
||||||
|
#site-locale-picker ul li {
|
||||||
|
position: relative;
|
||||||
|
display: none;
|
||||||
|
margin: 5px 0;
|
||||||
|
height: 22px;
|
||||||
|
line-height: 20px;
|
||||||
|
cursor: pointer; }
|
||||||
|
#site-locale-picker ul li img.flag {
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px; }
|
||||||
|
#site-locale-picker ul li span.text {
|
||||||
|
position: relative;
|
||||||
|
position: relative;
|
||||||
|
top: -6px;
|
||||||
|
color: #fff;
|
||||||
|
font-size: 0.7em;
|
||||||
|
text-shadow: 1px 1px 1px #000;
|
||||||
|
text-transform: uppercase; }
|
||||||
|
#site-locale-picker ul li:first-child {
|
||||||
|
display: block;
|
||||||
|
margin: 0px;
|
||||||
|
cursor: default; }
|
||||||
|
#site-locale-picker ul li:last-child {
|
||||||
|
margin-bottom: 0px; }
|
||||||
|
#site-locale-picker ul li:hover span.text {
|
||||||
|
text-decoration: underline; }
|
||||||
|
#site-locale-picker.open ul li {
|
||||||
|
display: block; }
|
||||||
|
#site-locale-picker.open ul li:first-child {
|
||||||
|
margin-bottom: 5px; }
|
|
@ -112,7 +112,8 @@
|
||||||
|
|
||||||
a {
|
a {
|
||||||
margin-top: 18px;
|
margin-top: 18px;
|
||||||
display: inline-block;
|
display: block;
|
||||||
|
float: left;
|
||||||
background: rgba(0, 0, 0, 0.4);
|
background: rgba(0, 0, 0, 0.4);
|
||||||
@include full-rounded(16px);
|
@include full-rounded(16px);
|
||||||
padding: 0px 10px 0 15px;
|
padding: 0px 10px 0 15px;
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
/* ___ AUTOMATICALLY GENERATED: see admin/site_locale_picker.scss for the source file */
|
||||||
|
|
||||||
|
@import "helpers";
|
||||||
|
|
||||||
|
#site-locale-picker {
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
float: right;
|
||||||
|
|
||||||
|
margin: 18px 0 0 10px;
|
||||||
|
padding: 0px 25px 0 10px;
|
||||||
|
|
||||||
|
border: 1px solid transparent;
|
||||||
|
|
||||||
|
background: rgba(0, 0, 0, 0.4);
|
||||||
|
@include full-rounded(16px);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: rgba(0, 0, 0, 1);
|
||||||
|
@include full-rounded(12px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.hand {
|
||||||
|
position: absolute;
|
||||||
|
top: 7px;
|
||||||
|
right: 7px;
|
||||||
|
|
||||||
|
height: 7px;
|
||||||
|
width: 12px;
|
||||||
|
|
||||||
|
background: transparent url(/images/admin/menu/icons.png) no-repeat 0px -16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
|
||||||
|
li {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
display: none;
|
||||||
|
|
||||||
|
margin: 5px 0;
|
||||||
|
|
||||||
|
height: 22px;
|
||||||
|
line-height: 20px;
|
||||||
|
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
img.flag {
|
||||||
|
position: relative;
|
||||||
|
top: 1px;
|
||||||
|
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.text {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
top: -6px;
|
||||||
|
|
||||||
|
color: #fff;
|
||||||
|
font-size: 0.7em;
|
||||||
|
text-shadow: 1px 1px 1px #000;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
display: block;
|
||||||
|
margin: 0px;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
span.text {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.open {
|
||||||
|
ul {
|
||||||
|
li {
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue