Site Map for plone.app.multilingual on Plone 5 Using Rapido
As of the date this was written (27-10-2016) there is an issue with plone.app.multilingual in which once installed on a Plone 5.x site, the site maps are not rendered properly (your sitemap.xml.gz file is empty).
Here is the issue that was logged on the Plone Community page that helped me with the below information: https://community.plone.org/t/capture-xml-output-from-rapido-function/2946
You can get around this by generating a sitemap that will render on the fly (once the URL is called) using Rapido.
Rapido
First you should install Rapido.
Once you have activated the Rapido add-on, go to Theming in Plone Control Panel and modify your theme.
Create a folder structure as per the Rapido tutorial. It should be structured the same as below:
++theme++yourtheme
|-rapido
|-sitemap
|-blocks
|-sitemap.yaml
|-sitemap.py
For this particular situation we do not need the .html file.
Rapido Files
Copy and paste the following into the sitemap.yaml file:
elements:
sitemap:
type: BASIC
Copy and paste the following into the sitemap.py file (please see below the code as there are some important things you will need to change):
# The URL structure of our dev server is http://server.domain.co.uk/plonesite
# Thus every sub language is on URLs such as: http://server.domain.co.uk/plonesite/fr,
# http://server.domain.co.uk/plonesite/de etc.
def sitemap(context):
language = str(context.content.language)
results = context.api.content.find(Language=language)
languages = {
'en-gb' : '.co.uk',
'fr' : '.fr',
'de' : '.de',
'it' : '.it',
'cz' : '.cz'
}
language_tlds = languages.copy()
del languages[language]
html = '''<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
xmlns:xhtml="http://www.w3.org/1999/xhtml">
'''
purl = str(context.portal.absolute_url())
url_structure = 1 # default inc .co.uk/language for TLD set to 2
for r in results:
html += '<url>'
html += '<loc>%s</loc>' %r.getObject().absolute_url()
for l in languages:
url = r.getObject().absolute_url()
if url_structure == 1:
url = url.replace(language+'/', '')
url = purl + '/' + l + str(url.replace(purl, ''))
if url.endswith('/' + language):
url = purl + '/' + l
if url_structure == 2:
for tld in language_tlds:
url = url.replace( language_tlds[tld], languages[l] )
html += '''<xhtml:link
rel="alternate"
hreflang="%s"
href="%s" />
''' % (l, url)
html += '</url>'
html += '</urlset>'
context.request.response.setHeader('content-type', 'application/xml')
return html
Modifications necessary to sitemap.py
You will need to update the languages dictionary variable to a list of the language codes that you have enabled on your site, first put in the language code, followed by the domain suffix.
If you are using URLs structured as follows: http://server.domain.co.uk/plonesite/language or http://www.domain.co.uk/language leave the url_structure variable set to 1. If you are using top level domains, such as http://www.server.co.uk/ or http://www.server.de etc then set this variable to 2.
View the site map
To view the outputted XML just go to http://server.domain.co.uk/plonesite/<language>/@@rapido/sitemap/blocks/sitemap/sitemap.
NOTE: For Plone < 5.0.5 users you'll need to go to the singular 'block' not 'blocks' (a bug that was fixed in later Rapido releases) so if you're on any version of Plone less than version 5.0.5 you'll need to go to: http://server.domain.co.uk/plonesite/<language>/@@rapido/sitemap/block/sitemap/sitemap instead.
Summary
Obviously this is a little ugly but it'll do the trick for anyone in a bind. The good news is a proper fix is being worked on by the community so make sure to keep an eye on Rapido / plone.app.multilingual for updates.
Disclaimer
The script is still to be fully tested so it may misbehave, I will be testing it fully over the next few days.