Статьи

Как настроить онлайн многоязычный журнал с Sulu

Ранее мы продемонстрировали правильный способ начать работу с Sulu CMS, настроив установку Hello World на машину Vagrant. Простые вещи, но могут быть хитрыми.

Если вы не знакомы с Vagrant и изолированными средами, наша отличная книга об этой вещи доступна для покупки .

На этот раз мы рассмотрим базовую терминологию Sulu, объясним, как контент формируется, создается, хранится и кэшируется, а также рассмотрим создание простого онлайн-журнала с разными языками (языками).

Сулу логотип


Рекомендуем прочитать, прежде чем продолжить:


Страницы и шаблоны страниц

Страница — это именно то, чего вы ожидаете: блок контента, часто состоящий из небольших блоков. Шаблон страницы — это двухкомпонентный рецепт сборки страницы.

Шаблон страницы состоит из двух частей: шаблона ветки и конфигурации XML. Часть Twig отвечает за визуализацию содержимого подблоков страницы, например:

{% extends "master.html.twig" %} {% block meta %} {% autoescape false %} {{ sulu_seo(extension.seo, content, urls, shadowBaseLocale) }} {% endautoescape %} {% endblock %} {% block content %} <h1 property="title">{{ content.title }}</h1> <div property="article"> {{ content.article|raw }} </div> {% endblock %} 

Это полное содержимое шаблона ветки по умолчанию, поставляемого с sulu-minimal , которое можно найти в app/Resources/Views/Templates/default.html.twig . Он расширяет мастер-макет, определяет некоторые блоки и отображает их содержимое.

Конфигурация XML, с другой стороны, немного сложнее (как и большинство вещей с XML):

 ... <key>default</key> <view>templates/default</view> <controller>SuluWebsiteBundle:Default:index</controller> <cacheLifetime>2400</cacheLifetime> <meta> <title lang="en">Default</title> <title lang="de">Standard</title> </meta> <properties> <section name="highlight"> <properties> <property name="title" type="text_line" mandatory="true"> <meta> <title lang="en">Title</title> <title lang="de">Titel</title> </meta> <params> <param name="headline" value="true"/> </params> <tag name="sulu.rlp.part"/> </property> ... по ... <key>default</key> <view>templates/default</view> <controller>SuluWebsiteBundle:Default:index</controller> <cacheLifetime>2400</cacheLifetime> <meta> <title lang="en">Default</title> <title lang="de">Standard</title> </meta> <properties> <section name="highlight"> <properties> <property name="title" type="text_line" mandatory="true"> <meta> <title lang="en">Title</title> <title lang="de">Titel</title> </meta> <params> <param name="headline" value="true"/> </params> <tag name="sulu.rlp.part"/> </property> ... по ... <key>default</key> <view>templates/default</view> <controller>SuluWebsiteBundle:Default:index</controller> <cacheLifetime>2400</cacheLifetime> <meta> <title lang="en">Default</title> <title lang="de">Standard</title> </meta> <properties> <section name="highlight"> <properties> <property name="title" type="text_line" mandatory="true"> <meta> <title lang="en">Title</title> <title lang="de">Titel</title> </meta> <params> <param name="headline" value="true"/> </params> <tag name="sulu.rlp.part"/> </property> ... По ... <key>default</key> <view>templates/default</view> <controller>SuluWebsiteBundle:Default:index</controller> <cacheLifetime>2400</cacheLifetime> <meta> <title lang="en">Default</title> <title lang="de">Standard</title> </meta> <properties> <section name="highlight"> <properties> <property name="title" type="text_line" mandatory="true"> <meta> <title lang="en">Title</title> <title lang="de">Titel</title> </meta> <params> <param name="headline" value="true"/> </params> <tag name="sulu.rlp.part"/> </property> ... 

Если вы новичок в Сулу, ничего из этого не будет иметь смысла — но мы доберемся. На данный момент мы вводим концепции. Основные выводы из приведенного выше фрагмента XML:

  • key — это уникальный фрагмент шаблона и его запись в меню выбора шаблона администратора (оно должно совпадать с именем файла XML, без расширения).
  • view — то, где его коллега twig может быть найден. Шаблон появится в меню, только если у него есть и XML, и соответствующий файл Twig!
  • контроллер — это место, где выполняется его логика. Позже мы более подробно рассмотрим контроллеры, но в целом вы можете оставить это значение по умолчанию для простого контента.
  • Метаданные — это то, как шаблон будет отображаться в меню выбора шаблона администратора, в зависимости от языка, выбранного в пользовательском интерфейсе:
    Меню выбора администратора
  • Свойства — это различные элементы страницы — в этом случае поле для ввода заголовка и нередактируемое поле URL

Вы определяете новые типы страниц (шаблоны), определяя новые комбинации свойств в этом XML-файле, а затем выводите их в соответствующий файл ветки.

В качестве эксперимента попробуйте использовать меню в интерфейсе администратора, чтобы переключить домашнюю страницу на шаблон по умолчанию, а затем в master.html.twig макета master.html.twig (одна папка выше) добавить бессмысленную информацию в HTML. Не стесняйтесь также заполнять свойство article в пользовательском интерфейсе.

Модифицированная домашняя страница

 ... <form action="{{ path('sulu_search.website_search') }}" method="GET"> <input name="q" type="text" placeholder="Search" /> <input type="submit" value="Go" /> </form> Lalala <section id="content" vocab="http://schema.org/" typeof="Content"> {% block content %}{% endblock %} </section> ... 

Если вы щелкнете Save and Publish в верхнем левом углу и обновите домашнюю страницу, вы должны увидеть изменения.

Измененная живая домашняя страница

Для любопытных: вам может быть интересно, почему они выбрали XML-маршрут вместо того, чтобы пользователи управляли всем в базе данных. Первой причиной является возможность контроля версий этих файлов. Вторая причина заключается в том, что даже если добавить свойство в GUI, оно все равно будет отсутствовать в шаблоне ветки. На этом этапе им придется либо сделать шаблоны веток редактируемыми в графическом интерфейсе через БД, либо пользователю снова придется редактировать файлы — и, если они уже редактируют их, они также могут редактировать файлы XML.

Страницы против Тем

Так какая тема во всем этом?

Тема — это коллекция типов страниц. Вопреки распространенному мнению, тема — это не основной макет, который затем расширяется ветками шаблонов страниц — это целая коллекция шаблонов страниц и мастер-макетов для использования. Тема также будет содержать все необходимые ресурсы для полноценной визуализации сайта: CSS, JS, изображения, шрифты и многое другое.

Для любопытных: мы не будем иметь дело с темами в этом уроке, но не стесняйтесь читать их здесь .

О кешировании

Если содержимое домашней страницы не изменяется при изменении и обновлении, это может быть связано с кешем. Вот важные вещи, которые нужно иметь в виду:

  • во время разработки ваш сервер должен установить переменные среды разработки Symfony. Это позволяет развертывать приложение непосредственно в рабочей среде без изменения значения среды вручную в таких файлах, как web/admin.php или web/website.php , и делает ваше приложение очень отлаживаемым в процессе разработки. Значения: SYMFONY_ENV и SYMFONY_DEBUG , и они автоматически устанавливаются, если вы используете Homestead Improved . Если нет, скопируйте их отсюда, если вы находитесь на Nginx.
  • командная строка приложений Symfony (например, при использовании в bin/adminconsole или bin/websiteconsole ) по умолчанию использует среду dev . Чтобы выполнить команды для другой среды, --env= флаг --env= с соответствующей средой, например: bin/adminconsole cache:clear --env=prod . Это может сбить вас с толку, если ваше приложение находится в режиме prod и вы пытаетесь очистить кеш, но ничего не происходит — возможно, среды не совпадают, а команда очищает неправильный кеш.

Интернет-журнал

Давайте рассмотрим желание запустить онлайн-журнал. По определению, такой журнал имеет:

  • страницы, объясняющие такие вещи, как «О нас», «Контакт», «Карьера» и т. д.
  • много статей, часто сгруппированных по месяцам (как видно по общему шаблону URL: mysite.com/05/2017/some-title-goes-here)
  • разные разрешения для разных уровней сотрудников (автор, редактор, гость, администратор…)
  • медиатека, в которой хранятся статические файлы для включения в посты и страницы (изображения, CSS, JS и т. д.)

Это все, что поддерживает Сулу, с оговоркой. При создании чего-то подобного нам нужно помнить о хранении в Сулу .

Jackawhat?

Этот раздел может показаться запутанным. Нет способа облегчить понимание. Будьте утешены тем фактом, что вам вообще ничего не нужно знать об этом, и относитесь к нему как к материалу «для тех, кто хочет знать больше».

Jackalope — это PHP-реализация PHPCR, которая является версией JCR . Кроличья нора очень глубока с этими терминами, поэтому я рекомендую избегать попыток узнать о них больше. Если вы настаиваете, это несколько покрыто этим суть .

Короче говоря, если вам не требуется версия вашего контента, вам подойдет стандартный пакет Jackalope-Doctrine-DBAL, который автоматически добавляется Sulu. Он будет хранить контент в обычной СУБД (например, MySQL), но без версий.

Если вам нужно управление версиями, вам нужно установить Jackrabbit — продукт Apache, который в основном представляет собой сервер баз данных с неочевидным поворотом , и использовать другую реализацию PHP для хранения контента: Jackalope-Jackrabbit (также включается автоматически). Обратите внимание, что СУБД все еще необходима — Jackrabbit просто дополняет ее, предоставляя другой механизм хранения для фактического контента, но разрешения, настройки и т. Д. Все еще хранятся в обычной базе данных.

Суть в том, что Jackrabbit (и PHPCR в целом) имеет ограничение в 10000 дочерних узлов на узел. Так как статьи в онлайн-журналах и блогах обычно последовательны и не имеют иерархии (то есть они плоские ), они в конечном итоге будут детьми «root», и после 10 тыс. Постов у вас будут проблемы.

Вот почему команда Sulu разработала пакет, который будет автоматически разделять контент по месяцам и эмулировать плоскую структуру. Установив каждый месяц как родитель, каждый месяц может иметь 10000 сообщений. При необходимости это может быть дополнительно фрагментировано по неделям или даже по дням. Имейте это в виду:

ArticleBundle является обязательным условием, если вы создаете новостной сайт, блог-сайт или журнал, потому что в противном случае после 10000 единиц контента у вас будут проблемы.

Примечание: ArticleBundle в настоящее время находится в стадии интенсивной разработки и, вероятно, будет иметь некоторые изменения API до версии 1.0. Используйте с осторожностью.

Хорошо, давайте установим ArticleBundle, чтобы получить поддержку для нашего сайта онлайн-журнала.

ElasticSearch

К сожалению, пакет требует ElasticSearch , который может быть более простым для установки. Если вы используете Ubuntu 16.04 (например, нашу коробку Homestead Improved ):

 sudo add-apt-repository ppa:webupd8team/java sudo apt-get update sudo apt-get install oracle-java8-installer 

После того, как это будет сделано (это займет некоторое время, как и в случае с Java), новая версия должна быть установлена ​​по умолчанию в Ubuntu. В другом месте вы можете настроить его:

 sudo update-alternatives --config java 

Наконец, установите постоянную переменную среды JAVA_HOME , отредактировав /etc/environment и добавив строку JAVA_HOME="/usr/lib/jvm/java-8-oracle" в ее верхнюю или нижнюю часть. Перезагрузите этот файл с source /etc/environment .

Java теперь готова, но нам все еще нужно установить ES.

 wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add - sudo apt-get install apt-transport-https echo "deb https://artifacts.elastic.co/packages/5.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-5.x.list sudo apt-get update && sudo apt-get install elasticsearch sudo service elasticsearch start 

Уф.

Примечание. Из-за требований к оперативной памяти ES запускается некоторое время, даже если команда выполняется немедленно, поэтому подождите некоторое время, прежде чем пытаться curl http://localhost:9200 чтобы проверить его. Если это не работает через минуту или около того, перейдите в /etc/elasticsearch/elasticsearch.yml , раскомментируйте network.host и установите его на 0.0.0.0 . Затем перезапустите ES, подождите минуту и ​​попробуйте снова керлинг.

ArticleBundle

Теперь мы можем наконец установить пакет.

Примечание. На момент написания статьи ArticleBundle находился в экспериментальном состоянии, а сам Sulu проходит процесс RC. Для работы с последними версиями этих двух основных пакетов я рекомендую следующую настройку composer.json :

 ... "sulu/sulu": "dev-develop as 1.6.0-RC1", "sulu/article-bundle": "dev-develop" ... ... "repositories": [ { "type": "vcs", "url": "https://github.com/sulu/SuluArticleBundle" }, { "type": "vcs", "url": "https://github.com/sulu/sulu" } ], ... ... "minimum-stability": "dev", "prefer-stable": true ... 

Затем установите вещи с помощью composer install или обновите с помощью composer update если вы уже работаете над запущенной установкой. Как только оба пакета будут стабильны, пакет будет установлен через:

 composer require sulu/article-bundle 

Теперь, когда пакет загружен, нам нужно добавить его в файл AbstractKernel.php :

 new Sulu\Bundle\ArticleBundle\SuluArticleBundle(), new ONGR\ElasticsearchBundle\ONGRElasticsearchBundle(), 

В app/config/config.yml мы добавляем следующее (раздел sulu_core должен быть объединен с существующим):

 sulu_route: mappings: Sulu\Bundle\ArticleBundle\Document\ArticleDocument: generator: schema options: route_schema: /articles/{object.getTitle()} sulu_core: content: structure: default_type: article: "article_default" article_page: "article_default" paths: article: path: "%kernel.root_dir%/Resources/templates/articles" type: "article" article_page: path: "%kernel.root_dir%/Resources/templates/articles" type: "article_page" ongr_elasticsearch: managers: default: index: index_name: su_articles mappings: - SuluArticleBundle live: index: index_name: su_articles_live mappings: - SuluArticleBundle sulu_article: documents: article: view: Sulu\Bundle\ArticleBundle\Document\ArticleViewDocument types: # Prototype name: translation_key: ~ # Display tab 'all' in list view display_tab_all: true 

Затем в app/config/admin/routing.yml мы добавляем маршруты:

 sulu_arictle_api: resource: "@SuluArticleBundle/Resources/config/routing_api.xml" type: rest prefix: /admin/api sulu_article: resource: "@SuluArticleBundle/Resources/config/routing.xml" prefix: /admin/articles 

Добавьте примеры шаблонов. Для templates/articles/article_default.xml :

 <?xml version="1.0" ?> <template xmlns="http://schemas.sulu.io/template/template" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xi="http://www.w3.org/2001/XInclude" xsi:schemaLocation="http://schemas.sulu.io/template/template http://schemas.sulu.io/template/template-1.0.xsd"> <key>article_default</key> <view>articles/article_default</view> <controller>SuluArticleBundle:WebsiteArticle:index</controller> <cacheLifetime>144000</cacheLifetime> <meta> <title lang="en">Default</title> <title lang="de">Standard</title> </meta> <tag name="sulu_article.type" type="article"/> <properties> <section name="highlight"> <properties> <property name="title" type="text_line" mandatory="true"> <meta> <title lang="en">Title</title> <title lang="de">Titel</title> </meta> <params> <param name="headline" value="true"/> </params> </property> <property name="routePath" type="route"> <meta> <title lang="en">Resourcelocator</title> <title lang="de">Adresse</title> </meta> </property> </properties> </section> <property name="article" type="text_editor"> <meta> <title lang="en">Article</title> <title lang="de">Artikel</title> </meta> </property> </properties> </template> 

Для views/articles/article_default.html.twig :

 {% extends "master.html.twig" %} {% block content %} <h1 property="title">{{ content.title }}</h1> <div property="article"> {{ content.article|raw }} </div> {% endblock %} 

Завершить инициализацию:

 php bin/console assets:install # this installs JS, CSS, etc for the UI. Defaults to hard copy, if you want symlinks use `--symlinks` php bin/console sulu:translate:export # creates translations php bin/console sulu:document:init # initializes some PHPCR nodes php bin/console ongr:es:index:create # initializaes the elasticsearch index 

Добавить разрешения: в интерфейсе администратора перейдите в «Настройки» -> «Роли пользователя». Выберите роль пользователя и прокрутите вниз до «Статьи». Выберите все, сохраните и обновите интерфейс, чтобы увидеть изменения. Опция «Статьи» должна появиться в левом меню.

Опция Article теперь присутствует

Примечание. Если вы видите, что загрузчик вращается бесконечно на этом экране, возможно, ваш сервер ElasticSearch выключен из-за нехватки ОЗУ на ВМ (отсутствие уведомления об этом было сообщено как ошибка ). ES очень ресурсоемкий, и простоя его простоя потребует около 1,5 ГБ ОЗУ . Решение состоит в том, чтобы либо включить машину с большим объемом оперативной памяти, либо перезапустить экземпляр ES с sudo service elasticsearch start . Вы всегда можете проверить, работает ли он с sudo service elasticsearch status .

Попробуйте написать пример поста Hello World и опубликовать его. Он должен появиться в url /articles/hello-world если вы назвали его Hello World .

Новая статья

Схемы URL

Маршрут по умолчанию, как было показано ранее в config.yml , это articles/{object.getTitle()} для статей. И, конечно же, при создании наша статья имеет такую ​​схему URL. Но что, если мы хотим что-то вроде /blog/06/2017/my-title ? Это достаточно легко изменить. Измените config.yml так, чтобы route_schema была изменена с:

 /articles/{object.getTitle()} 

в

 /blog/{object.getCreated().format('m')}/{object.getCreated().format('Y')}/{object.getTitle()} 

Фрагменты маршрута между фигурными скобками eval’d , а точки останова интерпретируются как методы доступа метода, поэтому, например, object.getCreated().format('Y') превращается в object->getCreated()->format('Y') .

Если мы попытаемся сохранить новое сообщение сейчас и оставить поле resource locator пустым (чтобы оно автоматически генерировалось), мы получим новый формат маршрута:

Новый формат маршрута в интерфейсе администратора

Новый формат маршрута в действии

Локализации

Давайте настроим другой язык нашего сайта сейчас — мы хотим охватить широкий рынок, поэтому мы будем строить наш пользовательский интерфейс и наш контент на двух языках, когда это применимо. Чтобы добавить новый язык, мы редактируем файл веб-пространства в app/Resources/webspaces . При localizations все, что нам нужно сделать, это добавить новую локаль:

  <localizations> <localization language="en" default="true"/> <localization language="hr"/> </localizations> 

HR для Hrvatski, который является местным названием для хорватского языка.

Обновление пользовательского интерфейса администратора теперь показывает новую опцию в переключателе языка:

Выбор языка в интерфейсе администратора

Прежде чем мы сможем использовать это, мы должны позволить текущему пользователю управлять этим языком. Каждая локаль по умолчанию запрещена для каждого существующего пользователя. Чтобы позволить текущему пользователю редактировать этот языковой стандарт, перейдите в Контакты -> Контакты -> [ВАШ ПОЛЬЗОВАТЕЛЬ ЗДЕСЬ] -> Разрешения, и в разделе языкового стандарта мы выбираем новый языковой стандарт, затем сохраняем и перезагружаем интерфейс администратора.


Слово предупреждения

После этого мы ДОЛЖНЫ запустить следующую консольную команду:

 php bin/adminconsole sulu:document:initialize 

Это инициализирует документы PHPCR для новой локали. ЭТО НЕ МОЖЕТ быть сделано после того, как вы уже создадите контент для новых локалей, иначе все сломается.

Не забудьте запускать команду sulu:document:initialize после каждого изменения веб-пространства, связанного с локалью!

Если вы когда-нибудь забудете и в конечном итоге создадите контент после добавления языкового стандарта, но до запуска команды инициализации, следующие команды удалят весь контент, связанный с этим языковым стандартом (поэтому используйте его с осторожностью!), И разрешите перезапустить языковой стандарт (замените hr в командах с вашим собственным идентификатором (ами) локали.

 php bin/adminconsole doctrine:phpcr:nodes:update --query "SELECT * FROM [nt:base]" --apply-closure="foreach(\$node->getProperties('i18n:hr-*') as \$hrNode) {\$hrNode->remove();};" php bin/websiteconsole doctrine:phpcr:nodes:update --query "SELECT * FROM [nt:base]" --apply-closure="foreach(\$node->getProperties('i18n:hr-*') as \$hrNode) {\$hrNode->remove();};" php bin/adminconsole sulu:document:initialize 

Идет обсуждение того, как лучше всего предупредить людей об этом в пользовательском интерфейсе.


Вернуться к статьям сейчас. Когда в существующей статье переключение локали вызовет всплывающее окно, которое позволит вам либо создать новую пустую статью на этом языке, либо создать новую статью с контентом, существующим на другом языке (в нашем случае en ). Давайте выберем последнее.

Получившаяся статья будет черновой копией той, что была у нас раньше.

Черновик поста на другом языке

Вы заметите, что URL-адрес для этого поста такой же, как и для его английского аналога. Это означает, что мы не сможем посетить его в браузере, пока не переключим язык, но у нас нет переключателя языков.

Веб-пространства и локали

Если вы снова посмотрите на файл веб-пространства, вы увидите, что внизу есть portals . Порталы похожи на подсайты веб-пространств. В большинстве случаев порталы и веб-пространства будут иметь отношение 1: 1, но мы используем порталы для определения URL-маршрутов для различных сред. По умолчанию устанавливает определенный язык с помощью атрибута и определяет корень всех наших URL-адресов как просто {host} . Поэтому на скриншотах выше мы видим homestead.app , к которому добавляются такие вещи, как /articles/something или /hello-world .

Чтобы отобразить наши языки, нам нужно изменить этот раздел. Замените каждый <url language="en">{host}</url> на <url>{host}/{localization}</url> . Это приведет к созданию URL-адресов в форме homestead.app/en/hello-world .

Хорватский маршрут к статье

Конечно же, теперь мы можем вручную переключать локаль, добавляя префикс всех URL-адресов к идентификатору локали. Было бы проще, если бы мы могли просто щелкнуть буквальный переключатель на странице, не так ли?

Тематика для локалей

Давайте изменим наш макет так, чтобы у нас был фактический выбор языка на экране, который мы можем использовать для изменения языка сайта.

В app/Resources/views/master.html.twig мы сделаем следующую модификацию. Прямо над формой мы поместим это:

  <div> {% for locale, url in urls %} {% set extra="/"~request.locale %} <a href="{{ sulu_content_path((url|replace({(extra): ""})?:'/'),request.webspaceKey,locale) }}">{{ locale }}</a> {% if not loop.last %}&nbsp;|&nbsp;{% endif %} {% endfor %} </div> 

Если мы посмотрим на документы , то заметим, что есть переменная urls . Переменная urls — это ассоциативный массив из конфигурации веб-пространства, содержащий URL-адреса всех локалей с локалями в качестве ключей и URL-адреса для значений, поэтому мы перебираем их. Поскольку для каждой среды определен только один, Sulu автоматически генерирует столько языков, сколько существует локалей, смешивая их со схемой URL, определенной в ключе url .

URL-адреса содержат языковой префикс (в настоящее время ошибка), поэтому нам нужно удалить его. Мы определяем эту часть как extra в Twig ( "/"~request.locale означает» слияние / и request.locale «).

Затем мы используем вспомогательную функцию sulu_content_path из vendor/sulu/sulu/src/Sulu/Bundle/WebsiteBundle/Twig/Content/ContentPathTwigExtension.php чтобы vendor/sulu/sulu/src/Sulu/Bundle/WebsiteBundle/Twig/Content/ContentPathTwigExtension.php ему текущий URL, лишенный extra контента, который мы определили одной строкой выше. Дополнительные аргументы включают ключ веб-пространства, чтобы он знал, где искать значения маршрута для генерации, и локаль, которая должна предшествовать пути к контенту при возврате нового. Не смущайтесь частью ?:'/' — это просто троичный IF, который отправляет по корневому маршруту в качестве параметра ( / ), если url не url .

Наконец, мы проверяем, является ли это последним элементом в цикле for, и если это так, мы не отображаем символ канала, тем самым создавая разделитель вплоть до последнего элемента.

Теперь в нашем основном макете есть переключатель языка, и мы можем легко переключаться между английским и хорватским языками.

Переключатель языка

Используя этот же подход, язык можно превратить в выпадающий или любой другой желаемый формат.

Что мы делаем в тени

Наконец, нам нужно что-то сделать с отсутствующими переводами страниц. Если мы посетим домашнюю страницу, находясь в локали hr , Sulu выдаст ошибку 404, потому что эта страница не существует на хорватском языке. Поскольку некоторые страницы могут не иметь переводов, мы хотим загружать альтернативу со второго языка, когда к ним обращаются — аудитория может быть двуязычной, и было бы стыдно дискриминировать их только потому, что у нас пока нет соответствующего контента ,

Мы делаем это с теневыми страницами в Сулу. Чтобы превратить нашу хорватскую версию домашней страницы в теневую, мы делаем следующее:

  • перейдите на экран редактирования домашней страницы в пользовательском интерфейсе администратора, когда языковой стандарт установлен на английский
  • переключите локаль и выберите «пустую страницу» во всплывающем окне
  • перейдите в «Настройки» этой новой страницы, выберите «Включить тень» и выберите «en» в качестве локали, из которой можно получить контент.

Настройка теневой страницы

Если мы сейчас посетим домашнюю страницу в локали hr , она должна создать домашнюю страницу en , тогда как наши посты в блоге будут переключаться между версией hr и en . Попробуйте!

Вывод

В этом руководстве мы объяснили некоторую базовую терминологию Sulu, установили пользовательский пакет в нашу установку Sulu и поиграли с контентом. Наконец, мы создали основной многоязычный новостной сайт с выбором языка.

На данный момент следует отметить, что Sulu — очень дорогая CMS для запуска — просто требование ElasticSearch для ArticleBundle увеличило потребности ОЗУ нашего сервера до 2-3 ГБ, что отнюдь не является маленькой машиной, и папку vendor само по себе уже в сотнях мегабайт. Но Сулу собирается продемонстрировать свою ценность в будущих постах — я призываю терпение до тех пор.

В этот момент Сулу должен начать чувствовать себя все более и более знакомым, и вы должны быть готовы к более сложному контенту. Это именно то, на чем мы сосредоточимся в следующей части.