Implementing Multilingual Sitemaps
To generate sitemaps for internationalized content in this project, you use the i18n attribute on the Sitemap class. This allows you to automatically generate URLs for all active languages and include SEO-friendly hreflang tags.
Basic Multilingual Sitemap
To enable multi-language URL generation, set i18n = True in your Sitemap subclass. This causes the sitemap to generate a separate entry for every language defined in your LANGUAGES setting for each item returned by items().
from django.contrib.sitemaps import Sitemap
from .models import I18nTestModel
class SimpleI18nSitemap(Sitemap):
changefreq = "never"
priority = 0.5
i18n = True
def items(self):
# Returns a queryset of items to be translated
return I18nTestModel.objects.order_by("pk").all()
When i18n is enabled, the sitemap internally expands your items into (item, lang_code) tuples. Methods like location(), priority(), and lastmod() are then called for each tuple, with the appropriate language activated during the call to location().
Adding Alternate Links (hreflang)
For better SEO, you can include <xhtml:link rel="alternate" hreflang="..."> tags in your sitemap by setting alternates = True.
class AlternatesI18nSitemap(Sitemap):
i18n = True
alternates = True
def items(self):
return I18nTestModel.objects.all()
This will include links to all other language versions of the page within each <url> entry in the XML output.
Configuring the Default Language (x-default)
To specify a default version for users whose language isn't explicitly listed, use the x_default attribute. This requires alternates to be enabled.
class XDefaultI18nSitemap(Sitemap):
i18n = True
alternates = True
x_default = True
def items(self):
return I18nTestModel.objects.all()
The x-default URL is generated by taking the URL for the language specified in settings.LANGUAGE_CODE and removing the language prefix (e.g., /en/my-page/ becomes /my-page/).
Restricting Languages
If you only want to generate sitemap entries for a subset of your project's supported languages, use the languages attribute.
class LimitedI18nSitemap(Sitemap):
i18n = True
alternates = True
# Only generate entries for English and Spanish
languages = ["en", "es"]
def items(self):
return I18nTestModel.objects.all()
Per-Item Language Control
For more granular control, such as when certain content is only available in specific languages, override the get_languages_for_item method.
class ItemByLangSitemap(Sitemap):
i18n = True
def items(self):
return I18nTestModel.objects.all()
def get_languages_for_item(self, item):
# Only allow Portuguese for specific items
if item.name == "Only for PT":
return ["pt"]
# Fallback to all supported languages for others
return super().get_languages_for_item(item)
Requirements and Configuration
For multilingual sitemaps to function correctly, ensure the following are configured in your project:
- Settings:
USE_I18Nmust be set toTruein yoursettings.py. - URL Patterns: Your model's absolute URLs must be defined within
i18n_patternsin yoururls.pyso that they receive the correct language prefixes.
# urls.py example
from django.conf.urls.i18n import i18n_patterns
from django.urls import path
from .views import testmodelview
urlpatterns = i18n_patterns(
path("testmodel/<int:id>/", testmodelview, name="i18n_testmodel"),
)
Troubleshooting
- Entry Count: When
i18n=True, the total number of entries in your sitemap will benumber of items * number of languages. If you have a large number of items and languages, you may hit thelimit(default 50,000) much faster, triggering pagination. - Missing Prefixes: If your URLs in the sitemap do not have language prefixes (e.g.,
/en/), verify that yourget_absolute_url()implementation usesreverse()and that the corresponding paths are wrapped ini18n_patterns. - x-default Logic: The
x_defaultlogic specifically looks for thesettings.LANGUAGE_CODEprefix in the generated URL to strip it. If your default language does not use a prefix in the URL,x-defaultmay not behave as expected.