Генерация файла sitemap.xml для мультиязычного сайта
Многие из нас делают мультиязычные сайты на контекстах. Контексты в MODx — вообще очень крутая штука, наверное, одна из самых крутых. На текущем большом мультиязычном проекте, SEO оптимизатор скинул мне статью в гугле и сказал, что нужно оптимизировать сайт под неё. Вопрос по теме задавали аж два года назад и ответов не последовало. Но народ вроде дал мотивацию тратить время на статью…
Поползли!
Что имеем?
1. Использовать будем Babel (для связи ресурсов и это ключевой момент) и pdoSitemap. Большой плюс в том, что в данной статье никакого программирования не будет. Так что, радуемся и пляшем. Все очень просто!
2. Сайт с контекстами, в моем случае два базовых контекста ru (web по-умолчанию) и кастомный en.
Шаг 1
В базовом контексте (ru), создаем ресурс sitemap.xml, с типом содержимого — XML. Именно в базовом контексте! Далее, в шаблоне ресурса (а если вы гуру MODx, то сразу в ресурсе) пишем обычный вызов сниппета pdoSitemap:
Убираем ресурсы которые не должны попасть в XML карту сайта ну и прописывайте нужные вам параметры. НО! Не указывайте в параметре contexts — ничего! Это важно! Обязательно создайте два кастомных чанка, будем редактировать их содержимое!
Шаг 2
Открываем чанк wrapper.tpl и пишем в нем:
Что это? Это XML разметка, внутри которой мы будем помещать урлы. Google говорит использовать пространство имен xhtml в карте сайта. Так мы и сделали!
Шаг 3
Открываем чанк row.tpl и пишем в нем:
Очень важно указать в параметре как идентификатор ресурса, так и значение 1/true, в параметре showCurrent. Этим самым — мы выводим тег <xhtml:link> для страницы активного контекста и для связанных страниц из других контекстов.
Шаг 4
Создаем чанк xhtml.tpl и пишем в нем:
Шаг 5
Чистим кэш, открываем файл sitemap.xml и ужасаемся, куда делась разметка? Не волнуйтесь, вся разметка на месте (xhtml мать его), просто откройте исходный код. Именно его и прочитают боты, можете проверить sitemap в валидаторах — все валидно и вуаля:
Итого, мы имеем валидный sitemap.xml файл для мультиязычных сайтов, который сгенерирован по рекомендациям Google. Ну а если у ресурса нет какой-либо версии языка, то там выведется та версия — которая есть.
Ни грамма кода, правки исходников и изобретения своего велосипеда!
Ну и я тестировал данную карту на сайте с 1.200 + ресурсами. Все ровно и быстро. Возможно, будут некие проблемки, если у вас ну ОООЧЕНЬ много ресурсов, т.к. мы используем сниппет в сниппете. И умные дядьки могут сказать нам, что мы говнокодеры. Возможно так оно и есть. Но лично меня данный вариант вполне устроит. Кстати! Если у вас реально очень много ресурсов, то sitemap нужно разбивать на несколько штук. Но это не отменяет того, что PHP код в сниппетах будет дергаться при построении урлов в сайтмапе.
В ином случае, все таки придется писать свой, уже оптимизированный сниппет, а это уже надо звать Артура Плагина…
Бонус
Ну и если вы почитали рекомендации гугла, то там требуется еще в теге head указать все возможные языковые варианты страницы. Для этого используется атрибут hreflang. Забацаем и его!
Шаг 1
Внутри тега head вызываем сниппет:
Шаг 2
Создаем чанк hreflang.tpl и пишем в нём:
Бонус внутри бонуса
Так свершилось судьбой, что у меня контексты на фронте переключаются через выпадающее меню. И его я тоже генерю сниппетом babelLinks, но если вдруг у вас нет перевода для определённого языка, babelLinks падла такая, выдаст страницу из настройки site_start…
Что я сделал? В каждом контексте я создал ресурс — «Нет перевода» и перевёл на нужные языки. В контекстах создал новую настройку no_translate и в ней указал идентификаторы этих ресурсов. Скопировал сниппет babelLinks и назвал его contextLinks, в нем, нашел строчку под порядковым номером 139 и заменил её на:
Теперь, если у определённого контекста нету перевода, там выводится страница «Нет перевода», дак еще и на нужном языке.
Ну не чудо ли, этот умирающий MODx?
Вот и всё! Кому хочется поблагодарить чеканной монетой — кнопка есть внизу или пишите мне в телегу — t.me/iWatchYouFromAfar. Ну или на моем сайте можете бахнуть червонца.
Готовое решение без вызова сниппета babelLinks.
@Николай — 500р
PaRaDoX2012 — 222р
Поползли!
Что имеем?
1. Использовать будем Babel (для связи ресурсов и это ключевой момент) и pdoSitemap. Большой плюс в том, что в данной статье никакого программирования не будет. Так что, радуемся и пляшем. Все очень просто!
2. Сайт с контекстами, в моем случае два базовых контекста ru (web по-умолчанию) и кастомный en.
Шаг 1
В базовом контексте (ru), создаем ресурс sitemap.xml, с типом содержимого — XML. Именно в базовом контексте! Далее, в шаблоне ресурса (а если вы гуру MODx, то сразу в ресурсе) пишем обычный вызов сниппета pdoSitemap:
{'pdoSitemap' | snippet : [
'showHidden' => 1,
'resources' => -3,
'tplWrapper' => '@FILE chunks/sitemap/wrapper.tpl',
'tpl' => '@FILE chunks/sitemap/row.tpl'
]}
Убираем ресурсы которые не должны попасть в XML карту сайта ну и прописывайте нужные вам параметры. НО! Не указывайте в параметре contexts — ничего! Это важно! Обязательно создайте два кастомных чанка, будем редактировать их содержимое!
Шаг 2
Открываем чанк wrapper.tpl и пишем в нем:
<?xml version="1.0" encoding="{$_modx->config.modx_charset}"?>
<urlset xmlns="{$schema}"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
{$output}
</urlset>
Что это? Это XML разметка, внутри которой мы будем помещать урлы. Google говорит использовать пространство имен xhtml в карте сайта. Так мы и сделали!
Шаг 3
Открываем чанк row.tpl и пишем в нем:
<url>
<loc>{$url}</loc>
<lastmod>{$date}</lastmod>
<changefreq>{$update}</changefreq>
<priority>{$priority}</priority>
{'babelLinks' | snippet : [
'resourceId' => $id,
'showCurrent' => 1,
'tpl' => '@FILE chunks/sitemap/xhtml.tpl'
]}
</url>
В атрибуте loc — мы указываем урл страницы текущего контекста (главного). Который мы генерим сниппетом pdoSitemap. lastmod, changefreq, priority — ноу комментс, гуглите если хотите узнать про эти атрибуты. А далее, с помощью прекрасного сниппета babelLinks (который идет в коробке компонента Babel), мы генерим те самые, заветные атрибуты <xhtml:link>!Очень важно указать в параметре как идентификатор ресурса, так и значение 1/true, в параметре showCurrent. Этим самым — мы выводим тег <xhtml:link> для страницы активного контекста и для связанных страниц из других контекстов.
Шаг 4
Создаем чанк xhtml.tpl и пишем в нем:
<xhtml:link rel="alternate" hreflang="{$cultureKey}" href="{$url}"/>
Шаг 5
Чистим кэш, открываем файл sitemap.xml и ужасаемся, куда делась разметка? Не волнуйтесь, вся разметка на месте (xhtml мать его), просто откройте исходный код. Именно его и прочитают боты, можете проверить sitemap в валидаторах — все валидно и вуаля:
Итого, мы имеем валидный sitemap.xml файл для мультиязычных сайтов, который сгенерирован по рекомендациям Google. Ну а если у ресурса нет какой-либо версии языка, то там выведется та версия — которая есть.
Ни грамма кода, правки исходников и изобретения своего велосипеда!
Ну и я тестировал данную карту на сайте с 1.200 + ресурсами. Все ровно и быстро. Возможно, будут некие проблемки, если у вас ну ОООЧЕНЬ много ресурсов, т.к. мы используем сниппет в сниппете. И умные дядьки могут сказать нам, что мы говнокодеры. Возможно так оно и есть. Но лично меня данный вариант вполне устроит. Кстати! Если у вас реально очень много ресурсов, то sitemap нужно разбивать на несколько штук. Но это не отменяет того, что PHP код в сниппетах будет дергаться при построении урлов в сайтмапе.
В ином случае, все таки придется писать свой, уже оптимизированный сниппет, а это уже надо звать Артура Плагина…
Бонус
Ну и если вы почитали рекомендации гугла, то там требуется еще в теге head указать все возможные языковые варианты страницы. Для этого используется атрибут hreflang. Забацаем и его!
Шаг 1
Внутри тега head вызываем сниппет:
{'babelLinks' | snippet : [
'showCurrent' => 1,
'tpl' => '@FILE chunks/language/hreflang.tpl'
]}
Шаг 2
Создаем чанк hreflang.tpl и пишем в нём:
<link hreflang="{$cultureKey}" href="{$url}" rel="alternate"/>
Бонус внутри бонуса
Так свершилось судьбой, что у меня контексты на фронте переключаются через выпадающее меню. И его я тоже генерю сниппетом babelLinks, но если вдруг у вас нет перевода для определённого языка, babelLinks падла такая, выдаст страницу из настройки site_start…
Что я сделал? В каждом контексте я создал ресурс — «Нет перевода» и перевёл на нужные языки. В контекстах создал новую настройку no_translate и в ней указал идентификаторы этих ресурсов. Скопировал сниппет babelLinks и назвал его contextLinks, в нем, нашел строчку под порядковым номером 139 и заменил её на:
$url = $context->makeUrl($context->getOption('no_translate'), $getRequest, 'full');
Теперь, если у определённого контекста нету перевода, там выводится страница «Нет перевода», дак еще и на нужном языке.
Ну не чудо ли, этот умирающий MODx?
Вот и всё! Кому хочется поблагодарить чеканной монетой — кнопка есть внизу или пишите мне в телегу — t.me/iWatchYouFromAfar. Ну или на моем сайте можете бахнуть червонца.
Готовое решение без вызова сниппета babelLinks.
Компонент SEO Tab умеет генерить аналогичный sitemap.xml без необходимости вызывать в нем сниппет babelLinks. Нужно лишь в контекстах задать настройки, включая cultureKey и включить системную настройку компонента с ключом stercseo.xmlsitemap.babel.add_alternate_links.Люди которые мотивируют писать полезные статьи:
За инфо большое спасибо @Yurij Finiv
@Николай — 500р
PaRaDoX2012 — 222р
Поблагодарить автора
Отправить деньги
Комментарии: 7
А такой вариант не подходит?
Для hreflang хорошее решение. Ранее я использовал свой сниппет, который включал и x-default
Кстати, в чанке есть незначительные ошибки — нет кавычек.
{'!StercSeoSiteMap' | snippet: [
'contexts' => 'web,en'
]}
Так свершилось судьбой, что у меня контексты на фронте переключаются через выпадающее менюBabel же не выводит язык, если нет перевода. Если конечно языки сгенерированны сниппетом BabelLinks
Для hreflang хорошее решение. Ранее я использовал свой сниппет, который включал и x-default
Кстати, в чанке есть незначительные ошибки — нет кавычек.
<link hreflang="{$cultureKey}" href="{$url}" rel="alternate"/>
По поводу StercSeoSiteMap — без понятия, не работал с этим сниппетом. Если он генерит нужный сайтмап — отлично.
Babel не выводит язык, если нет перевода. Посему я скопировал сниппет babelLinks, сделал страницу — «Нет перевода» и вывожу её.
Babel не выводит язык, если нет перевода. Посему я скопировал сниппет babelLinks, сделал страницу — «Нет перевода» и вывожу её.
Пользуюсь этим отличный компонент
Он генерит структуру XML для мультиязычного сайта?
Да, компонент SEO Tab генерит мультиязычный sitemap без необходимости вызова в нем стороннего сниппета Babel. Дополню в статье.
Мне нравится что Паша пишет статьи «выжимки».
Step-by-step гайд который и новичкам полезен, и людям поопытнее экономит время.
Два лайка бы поставил
Step-by-step гайд который и новичкам полезен, и людям поопытнее экономит время.
Два лайка бы поставил
Ему б еще подобреть к новичкам немного))))
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.