ecm_cms 0.0.1.pre
Sign up to get free protection for your applications and to get access to all the features.
- data/MIT-LICENSE +20 -0
- data/README.rdoc +55 -0
- data/Rakefile +27 -0
- data/app/assets/stylesheets/ecm_cms.css.less +3 -0
- data/app/controllers/ecm/cms/page_controller.rb +11 -0
- data/app/helpers/ecm/cms_helper.rb +42 -0
- data/app/models/ecm/cms.rb +5 -0
- data/app/models/ecm/cms/folder.rb +31 -0
- data/app/models/ecm/cms/navigation.rb +24 -0
- data/app/models/ecm/cms/navigation_item.rb +93 -0
- data/app/models/ecm/cms/page.rb +42 -0
- data/app/models/ecm/cms/partial.rb +31 -0
- data/app/models/ecm/cms/template.rb +31 -0
- data/config/locales/ecm.cms.de.yml +17 -0
- data/config/locales/ecm.cms.en.yml +17 -0
- data/config/locales/ecm.cms.navigation.de.yml +16 -0
- data/config/locales/ecm.cms.navigation.en.yml +16 -0
- data/config/locales/ecm.cms.navigation_item.de.yml +23 -0
- data/config/locales/ecm.cms.navigation_item.en.yml +23 -0
- data/config/locales/ecm.cms.page.de.yml +26 -0
- data/config/locales/ecm.cms.page.en.yml +26 -0
- data/config/locales/ecm.cms.partial.de.yml +22 -0
- data/config/locales/ecm.cms.partial.en.yml +22 -0
- data/config/locales/ecm.cms.template.de.yml +22 -0
- data/config/locales/ecm.cms.template.en.yml +22 -0
- data/db/migrate/001_create_ecm_cms_folders.rb +21 -0
- data/db/migrate/002_create_ecm_cms_pages.rb +19 -0
- data/db/migrate/003_create_ecm_cms_templates.rb +18 -0
- data/db/migrate/004_create_ecm_cms_partials.rb +19 -0
- data/db/migrate/005_create_ecm_cms_navigations.rb +13 -0
- data/db/migrate/006_create_ecm_cms_navigation_items.rb +28 -0
- data/lib/ecm/cms/action_view/template/handlers/textile.rb +18 -0
- data/lib/ecm/cms/action_view/template_patch.rb +19 -0
- data/lib/ecm/cms/action_view/template_renderer_patch.rb +30 -0
- data/lib/ecm/cms/active_admin/ecm_cms_navigation_items.rb +45 -0
- data/lib/ecm/cms/active_admin/ecm_cms_navigations.rb +61 -0
- data/lib/ecm/cms/active_admin/ecm_cms_pages.rb +70 -0
- data/lib/ecm/cms/active_admin/ecm_cms_partials.rb +47 -0
- data/lib/ecm/cms/active_admin/ecm_cms_templates.rb +46 -0
- data/lib/ecm/cms/configuration.rb +22 -0
- data/lib/ecm/cms/database_resolver.rb +101 -0
- data/lib/ecm/cms/database_template.rb +67 -0
- data/lib/ecm/cms/engine.rb +22 -0
- data/lib/ecm/cms/resolvers/ecm/cms/page_resolver.rb +37 -0
- data/lib/ecm/cms/resolvers/ecm/cms/partial_resolver.rb +30 -0
- data/lib/ecm/cms/resolvers/ecm/cms/template_resolver.rb +30 -0
- data/lib/ecm/cms/routing.rb +13 -0
- data/lib/ecm/cms/version.rb +5 -0
- data/lib/ecm_cms.rb +30 -0
- data/lib/generators/ecm/cms/install/install_generator.rb +15 -0
- data/lib/generators/ecm/cms/install/templates/ecm_cms.rb +7 -0
- data/lib/generators/ecm/cms/locales/locales_generator.rb +32 -0
- data/lib/rails_tools/i18n_controller.rb +24 -0
- data/lib/tasks/ecm_cms_tasks.rake +171 -0
- metadata +463 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2012 Roberto Vasquez Angel
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
= ECM Module Template
|
2
|
+
|
3
|
+
= Prerequisites
|
4
|
+
|
5
|
+
* rails ~> 3.2.8
|
6
|
+
* active admin ~> 0.5.0
|
7
|
+
|
8
|
+
= Installation
|
9
|
+
|
10
|
+
Add it to your bundle:
|
11
|
+
|
12
|
+
# Gemfile:
|
13
|
+
gem 'ecm_cms'
|
14
|
+
|
15
|
+
Install your bundle:
|
16
|
+
|
17
|
+
> bundle install
|
18
|
+
|
19
|
+
Install the intializer:
|
20
|
+
|
21
|
+
> rails g ecm:cms:install
|
22
|
+
|
23
|
+
Install the locales
|
24
|
+
|
25
|
+
> rails g ecm:cms:locales
|
26
|
+
|
27
|
+
Generate migrations and migrate:
|
28
|
+
|
29
|
+
> rake ecm_cms_engine:install:migrations
|
30
|
+
> rake db:migrate
|
31
|
+
|
32
|
+
= Configuring localized routing
|
33
|
+
|
34
|
+
Add the routes to your routing file:
|
35
|
+
|
36
|
+
# config/routes.rb:
|
37
|
+
localized(I18n.available_locales) do
|
38
|
+
scope "/:i18n_locale", :constraints => {:i18n_locale => /#{I18n.available_locales.join('|')}/} do
|
39
|
+
# ECM CMS
|
40
|
+
Ecm::Cms::Routing.routes(self)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
match "/", :to => redirect("/#{I18n.locale}")
|
44
|
+
|
45
|
+
= Optional: Generating example/default data
|
46
|
+
|
47
|
+
There is a task to prepopulate your database tables with example data.
|
48
|
+
|
49
|
+
Warning: *RUNNING THIS WILL DELETE ALL OF YOUR CMS DATA AND REPLACE IT WITH EXAMPLE DATA!*
|
50
|
+
|
51
|
+
> rake ecm:cms:db:populate!
|
52
|
+
|
53
|
+
= License
|
54
|
+
|
55
|
+
This project rocks and uses MIT-LICENSE.
|
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'EcmCms'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
Bundler::GemHelper.install_tasks
|
27
|
+
|
@@ -0,0 +1,3 @@
|
|
1
|
+
body.active_admin textarea#ecm_cms_page_body, body.active_admin textarea#ecm_cms_template_body, body.active_admin textarea#ecm_cms_partial_body {
|
2
|
+
font-family: Consolas, Monaco,Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace;
|
3
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class Ecm::Cms::PageController < ApplicationController
|
2
|
+
# inject locale to params and vice versa
|
3
|
+
include RailsTools::I18nController
|
4
|
+
|
5
|
+
# add the page resolver
|
6
|
+
append_view_path Ecm::Cms::PageResolver.instance unless view_paths.include?(Ecm::Cms::PageResolver.instance)
|
7
|
+
|
8
|
+
def respond
|
9
|
+
render :template => params[:page]
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Ecm::CmsHelper
|
2
|
+
def cms_render_navigation(name, options = {})
|
3
|
+
options.reverse_merge! :renderer => :bootstrap, :expand_all => true
|
4
|
+
navigation = Ecm::Cms::Navigation.where(:name => name.to_s, :locale => I18n.locale.to_s).first
|
5
|
+
|
6
|
+
return I18n.t('ecm.cms.navigation.messages.not_found', {:lang => I18n.locale.to_s, :name => name.to_s}) unless navigation
|
7
|
+
|
8
|
+
options[:items] = []
|
9
|
+
navigation.ecm_cms_navigation_items.roots.all.each do |ni|
|
10
|
+
options[:items] << build_navigation(ni)
|
11
|
+
end
|
12
|
+
|
13
|
+
return I18n.t('ecm.cms.navigation.messages.empty', :lang => I18n.locale.to_s, :name => name) if options[:items].empty?
|
14
|
+
options[:items].first[:options] = {} if options[:items].first[:options].nil?
|
15
|
+
options[:items].first[:options].reverse_merge! :container_class => 'nav'
|
16
|
+
render_navigation(options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def build_navigation(navigation_item)
|
20
|
+
if navigation_item.children.count > 0
|
21
|
+
items = []
|
22
|
+
navigation_item.children.each do |child|
|
23
|
+
items << build_navigation(child)
|
24
|
+
end
|
25
|
+
#output = { :key => navigation_item.key, :name => navigation_item.name, :url => eval(navigation_item.url), :items => items }
|
26
|
+
output = { :key => navigation_item.key, :name => navigation_item.name, :url => navigation_item.url, :items => items }
|
27
|
+
else
|
28
|
+
#output = { :key => navigation_item.key, :name => navigation_item.name, :url => eval(navigation_item.url) }
|
29
|
+
output = { :key => navigation_item.key, :name => navigation_item.name, :url => navigation_item.url }
|
30
|
+
end
|
31
|
+
|
32
|
+
begin
|
33
|
+
options = eval(navigation_item.options)
|
34
|
+
output[:options] = options if options.is_a?(Hash)
|
35
|
+
rescue
|
36
|
+
logger.debug "Invalid navigation item options: #{navigation_item.options}"
|
37
|
+
end
|
38
|
+
|
39
|
+
return output
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class Ecm::Cms::Folder < ActiveRecord::Base
|
2
|
+
self.table_name = 'ecm_cms_folders'
|
3
|
+
|
4
|
+
# associations
|
5
|
+
has_many :ecm_cms_pages,
|
6
|
+
:class_name => 'Ecm::Cms::Page',
|
7
|
+
:dependent => :destroy,
|
8
|
+
:foreign_key => 'ecm_cms_folder_id'
|
9
|
+
has_many :ecm_cms_partials,
|
10
|
+
:class_name => 'Ecm::Cms::Partial',
|
11
|
+
:dependent => :destroy,
|
12
|
+
:foreign_key => 'ecm_cms_folder_id'
|
13
|
+
has_many :ecm_cms_templates,
|
14
|
+
:class_name => 'Ecm::Cms::Template',
|
15
|
+
:dependent => :destroy,
|
16
|
+
:foreign_key => 'ecm_cms_folder_id'
|
17
|
+
|
18
|
+
# attributes
|
19
|
+
attr_accessible :basename,
|
20
|
+
:children_count,
|
21
|
+
:depth,
|
22
|
+
:ecm_cms_templates_count,
|
23
|
+
:lft,
|
24
|
+
:pathname,
|
25
|
+
:rgt
|
26
|
+
|
27
|
+
# validations
|
28
|
+
validates :basename, :presence => true
|
29
|
+
validates :pathname, :presence => true
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class Ecm::Cms::Navigation < ActiveRecord::Base
|
2
|
+
self.table_name = 'ecm_cms_navigations'
|
3
|
+
|
4
|
+
# associations
|
5
|
+
has_many :ecm_cms_navigation_items,
|
6
|
+
:class_name => 'Ecm::Cms::NavigationItem',
|
7
|
+
:dependent => :destroy,
|
8
|
+
:foreign_key => 'ecm_cms_navigation_id'
|
9
|
+
|
10
|
+
# attributes
|
11
|
+
attr_accessible :locale,
|
12
|
+
:name,
|
13
|
+
:slug
|
14
|
+
|
15
|
+
# validations
|
16
|
+
validates :locale, :inclusion => I18n.available_locales.map(&:to_s),
|
17
|
+
:allow_nil => true
|
18
|
+
validates :name, :presence => true,
|
19
|
+
:uniqueness => { :scope => [ :locale ] }
|
20
|
+
|
21
|
+
def to_s
|
22
|
+
"#{self.name} (#{self.locale})"
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
class Ecm::Cms::NavigationItem < ActiveRecord::Base
|
2
|
+
self.table_name = 'ecm_cms_navigation_items'
|
3
|
+
|
4
|
+
# associations
|
5
|
+
belongs_to :ecm_cms_navigation,
|
6
|
+
:class_name => 'Ecm::Cms::Navigation',
|
7
|
+
:foreign_key => 'ecm_cms_navigation_id'
|
8
|
+
belongs_to :ecm_cms_page,
|
9
|
+
:class_name => 'Ecm::Cms::Page',
|
10
|
+
:foreign_key => 'ecm_cms_page_id'
|
11
|
+
|
12
|
+
# attributes
|
13
|
+
attr_accessible :depth,
|
14
|
+
:key,
|
15
|
+
:name,
|
16
|
+
:options,
|
17
|
+
:string,
|
18
|
+
:url
|
19
|
+
attr_protected :lgt,
|
20
|
+
:rgt
|
21
|
+
|
22
|
+
# awesome nested set
|
23
|
+
acts_as_nested_set :dependent => :destroy, :counter_cache => :children_count, :scope => :ecm_cms_navigation_id
|
24
|
+
|
25
|
+
# callbacks
|
26
|
+
before_validation :update_navigation_from_parent, :if => Proc.new { |ni| ni.child? }
|
27
|
+
before_validation :update_url_form_page, :if => Proc.new { |ni| ni.ecm_cms_page.present? && ni.url.blank? }
|
28
|
+
after_save :update_children_navigations!
|
29
|
+
|
30
|
+
# default_scope
|
31
|
+
default_scope :order => [:ecm_cms_navigation_id, :lft]
|
32
|
+
|
33
|
+
# validations
|
34
|
+
validates :key, :presence => true
|
35
|
+
validates :name, :presence => true
|
36
|
+
validates :url, :presence => true
|
37
|
+
validates :ecm_cms_navigation, :presence => true, :if => :root?
|
38
|
+
|
39
|
+
def params_for_new_page
|
40
|
+
return {} if self.new_record?
|
41
|
+
match = self.url.scan(/(#{I18n.available_locales.join('|')})$/)
|
42
|
+
return { :locale => match[0][0], :pathname => '/', :basename => 'home', :title => self.name, :ecm_cms_navigation_item_ids => [ self.to_param ] } if match.size > 0
|
43
|
+
match = self.url.scan(/(#{I18n.available_locales.join('|')})(.*)\/(.*)/)
|
44
|
+
return {} unless match.first.respond_to?(:size) # && match.first.size != 3
|
45
|
+
params = match.first
|
46
|
+
return {} if params.size != 3
|
47
|
+
params[1] << '/' unless params[1].end_with?('/')
|
48
|
+
return { :locale => params[0], :pathname => params[1], :basename => params[2], :title => self.name, :ecm_cms_navigation_item_ids => [ self.to_param ] }
|
49
|
+
end
|
50
|
+
|
51
|
+
# @TODO: test
|
52
|
+
def to_label
|
53
|
+
if depth > 0
|
54
|
+
"#{' ' * depth} ▶ #{name}".html_safe
|
55
|
+
else
|
56
|
+
name
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def update_navigation_from_parent!
|
61
|
+
self.update_navigation_from_parent
|
62
|
+
self.save!
|
63
|
+
end
|
64
|
+
|
65
|
+
def update_children_navigations!
|
66
|
+
self.descendants.map(&:"update_navigation_from_parent!")
|
67
|
+
end
|
68
|
+
|
69
|
+
def update_url_form_page!
|
70
|
+
# self.url = build_url_from_page(ecm_cms_page.locale, ecm_cms_page.pathname, ecm_cms_page.basename, ecm_cms_page.home_page?)
|
71
|
+
update_url_form_page
|
72
|
+
save!
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def build_url_from_page(locale, pathname, basename, is_home_page)
|
78
|
+
if is_home_page
|
79
|
+
"/#{locale}"
|
80
|
+
else
|
81
|
+
"/#{locale}#{pathname}#{basename}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def update_navigation_from_parent
|
86
|
+
self.ecm_cms_navigation = self.parent.ecm_cms_navigation
|
87
|
+
end
|
88
|
+
|
89
|
+
def update_url_form_page
|
90
|
+
self.url = build_url_from_page(ecm_cms_page.locale, ecm_cms_page.pathname, ecm_cms_page.basename, ecm_cms_page.home_page?)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class Ecm::Cms::Page < ActiveRecord::Base
|
2
|
+
self.table_name = 'ecm_cms_pages'
|
3
|
+
|
4
|
+
# add shared behaviour for database backed templates
|
5
|
+
include Ecm::Cms::DatabaseTemplate
|
6
|
+
|
7
|
+
# associations
|
8
|
+
has_many :ecm_cms_navigation_items,
|
9
|
+
:class_name => 'Ecm::Cms::NavigationItem',
|
10
|
+
:dependent => :nullify,
|
11
|
+
:foreign_key => 'ecm_cms_page_id'
|
12
|
+
|
13
|
+
# attributes
|
14
|
+
attr_accessible :basename,
|
15
|
+
:body,
|
16
|
+
:ecm_cms_folder_id,
|
17
|
+
:ecm_cms_navigation_item_ids,
|
18
|
+
:format,
|
19
|
+
:handler,
|
20
|
+
:layout,
|
21
|
+
:locale,
|
22
|
+
:meta_description,
|
23
|
+
:pathname,
|
24
|
+
:title
|
25
|
+
|
26
|
+
# callbacks
|
27
|
+
after_save :touch_navigation_items # , :if => Proc.new { |page| page.locale_changed? || page.pathname_changed? || page.basename_changed? }
|
28
|
+
|
29
|
+
# validations
|
30
|
+
validates :title, :presence => true
|
31
|
+
|
32
|
+
def home_page?
|
33
|
+
p self.pathname
|
34
|
+
p self.basename
|
35
|
+
return self.pathname == '/' && self.basename == 'home'
|
36
|
+
end
|
37
|
+
|
38
|
+
def touch_navigation_items
|
39
|
+
self.ecm_cms_navigation_items.map(&:update_url_form_page!)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class Ecm::Cms::Partial < ActiveRecord::Base
|
2
|
+
self.table_name = 'ecm_cms_partials'
|
3
|
+
|
4
|
+
# add shared behaviour for database backed templates
|
5
|
+
include Ecm::Cms::DatabaseTemplate
|
6
|
+
|
7
|
+
# associations
|
8
|
+
# belongs_to :ecm_cms_folder,
|
9
|
+
# :class_name => 'Ecm::Cms::Folder',
|
10
|
+
# :foreign_key => 'ecm_cms_folder_id'
|
11
|
+
|
12
|
+
# attributes
|
13
|
+
attr_accessible :basename,
|
14
|
+
:body,
|
15
|
+
:ecm_cms_folder_id,
|
16
|
+
:format,
|
17
|
+
:handler,
|
18
|
+
:layout,
|
19
|
+
:locale,
|
20
|
+
:pathname
|
21
|
+
|
22
|
+
# callbacks
|
23
|
+
before_validation :ensure_basename_starts_with_underscore, :if => Proc.new { |t| t.basename.present? }
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def ensure_basename_starts_with_underscore
|
28
|
+
self.basename.insert(0, '_') unless self.basename.start_with?('_')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class Ecm::Cms::Template < ActiveRecord::Base
|
2
|
+
self.table_name = 'ecm_cms_templates'
|
3
|
+
|
4
|
+
# add shared behaviour for database backed templates
|
5
|
+
include Ecm::Cms::DatabaseTemplate
|
6
|
+
|
7
|
+
# associations
|
8
|
+
belongs_to :ecm_cms_folder,
|
9
|
+
:class_name => 'Ecm::Cms::Folder',
|
10
|
+
:foreign_key => 'ecm_cms_folder_id'
|
11
|
+
|
12
|
+
# attributes
|
13
|
+
attr_accessible :basename,
|
14
|
+
:body,
|
15
|
+
:ecm_cms_folder_id,
|
16
|
+
:format,
|
17
|
+
:handler,
|
18
|
+
:layout,
|
19
|
+
:locale,
|
20
|
+
:pathname
|
21
|
+
|
22
|
+
# callbacks
|
23
|
+
before_validation :ensure_basename_starts_without_underscore, :if => Proc.new { |t| t.basename.present? }
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def ensure_basename_starts_without_underscore
|
28
|
+
self.basename.slice!(0) if self.basename.start_with?('_')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
de:
|
2
|
+
ecm:
|
3
|
+
cms:
|
4
|
+
active_admin:
|
5
|
+
menu: CMS
|
6
|
+
navigation:
|
7
|
+
messages:
|
8
|
+
empty: Navigation %{name} (%{lang}) ist leer
|
9
|
+
not_found: Navigation %{name} (%{lang}) nicht gefunden
|
10
|
+
resources:
|
11
|
+
ecm_cms_folders: ordner
|
12
|
+
ecm_cms_navigations: navigationen
|
13
|
+
ecm_cms_navigation_items: navigationenseintraege
|
14
|
+
ecm_cms_pages: seiten
|
15
|
+
ecm_cms_partials: fragmente
|
16
|
+
ecm_cms_templates: vorlagen
|
17
|
+
|