diff --git a/AUTHORS b/AUTHORS index 4bdd5048e9..13b6bdee5e 100644 --- a/AUTHORS +++ b/AUTHORS @@ -484,6 +484,7 @@ answer newbie questions, and generally made Django that much better: Christian Oudard oggie rob oggy + Luan Pablo Tomek Paczkowski Jens Page Guillaume Pannatier diff --git a/django/contrib/sitemaps/__init__.py b/django/contrib/sitemaps/__init__.py index 1100712991..ca51fd4523 100644 --- a/django/contrib/sitemaps/__init__.py +++ b/django/contrib/sitemaps/__init__.py @@ -1,6 +1,8 @@ from django.apps import apps as django_apps +from django.conf import settings from django.core import urlresolvers, paginator from django.core.exceptions import ImproperlyConfigured +from django.utils import translation from django.utils.six.moves.urllib.parse import urlencode from django.utils.six.moves.urllib.request import urlopen @@ -89,6 +91,19 @@ class Sitemap(object): raise ImproperlyConfigured("To use sitemaps, either enable the sites framework or pass a Site/RequestSite object in your view.") domain = site.domain + if getattr(self, 'i18n', False): + urls = [] + current_lang_code = translation.get_language() + for lang_code, lang_name in settings.LANGUAGES: + translation.activate(lang_code) + urls += self._urls(page, protocol, domain) + translation.activate(current_lang_code) + else: + urls = self._urls(page, protocol, domain) + + return urls + + def _urls(self, page, protocol, domain): urls = [] latest_lastmod = None all_items_lastmod = True # track if all items have a lastmod diff --git a/django/contrib/sitemaps/tests/base.py b/django/contrib/sitemaps/tests/base.py index 2d0a7bff20..54446b3012 100644 --- a/django/contrib/sitemaps/tests/base.py +++ b/django/contrib/sitemaps/tests/base.py @@ -1,5 +1,6 @@ from django.apps import apps from django.core.cache import cache +from django.core.urlresolvers import reverse from django.db import models from django.test import TestCase, override_settings @@ -17,6 +18,16 @@ class TestModel(models.Model): return '/testmodel/%s/' % self.id +class I18nTestModel(models.Model): + name = models.CharField(max_length=100) + + class Meta: + app_label = 'sitemaps' + + def get_absolute_url(self): + return reverse('i18n_testmodel', args=[self.id]) + + @override_settings(ROOT_URLCONF='django.contrib.sitemaps.tests.urls.http') class SitemapTestsBase(TestCase): protocol = 'http' @@ -28,3 +39,4 @@ class SitemapTestsBase(TestCase): cache.clear() # Create an object for sitemap content. TestModel.objects.create(name='Test Object') + I18nTestModel.objects.create(name='Test Object') diff --git a/django/contrib/sitemaps/tests/test_http.py b/django/contrib/sitemaps/tests/test_http.py index 2f9ebd8fad..bce276d2ea 100644 --- a/django/contrib/sitemaps/tests/test_http.py +++ b/django/contrib/sitemaps/tests/test_http.py @@ -171,3 +171,14 @@ class HTTPSitemapTests(SitemapTestsBase): def test_empty_sitemap(self): response = self.client.get('/empty/sitemap.xml') self.assertEqual(response.status_code, 200) + + @override_settings(LANGUAGES=(('en', 'English'), ('pt', 'Portuguese'))) + def test_simple_i18nsitemap_index(self): + "A simple i18n sitemap index can be rendered" + response = self.client.get('/simple/i18n.xml') + expected_content = """ + +{0}/en/i18n/testmodel/1/never0.5{0}/pt/i18n/testmodel/1/never0.5 + +""".format(self.base_url) + self.assertXMLEqual(response.content.decode('utf-8'), expected_content) diff --git a/django/contrib/sitemaps/tests/urls/http.py b/django/contrib/sitemaps/tests/urls/http.py index 50418683d8..c232958074 100644 --- a/django/contrib/sitemaps/tests/urls/http.py +++ b/django/contrib/sitemaps/tests/urls/http.py @@ -1,9 +1,11 @@ from datetime import datetime from django.conf.urls import url +from django.conf.urls.i18n import i18n_patterns from django.contrib.sitemaps import Sitemap, GenericSitemap, FlatPageSitemap, views +from django.http import HttpResponse from django.views.decorators.cache import cache_page -from django.contrib.sitemaps.tests.base import TestModel +from django.contrib.sitemaps.tests.base import I18nTestModel, TestModel class SimpleSitemap(Sitemap): @@ -16,6 +18,15 @@ class SimpleSitemap(Sitemap): return [object()] +class SimpleI18nSitemap(Sitemap): + changefreq = "never" + priority = 0.5 + i18n = True + + def items(self): + return I18nTestModel.objects.all() + + class EmptySitemap(Sitemap): changefreq = "never" priority = 0.5 @@ -42,10 +53,18 @@ class FixedLastmodMixedSitemap(Sitemap): return [o1, o2] +def testmodelview(request, id): + return HttpResponse() + + simple_sitemaps = { 'simple': SimpleSitemap, } +simple_i18nsitemaps = { + 'simple': SimpleI18nSitemap, +} + empty_sitemaps = { 'empty': EmptySitemap, } @@ -74,6 +93,7 @@ urlpatterns = [ url(r'^simple/sitemap-(?P
.+)\.xml$', views.sitemap, {'sitemaps': simple_sitemaps}, name='django.contrib.sitemaps.views.sitemap'), url(r'^simple/sitemap\.xml$', views.sitemap, {'sitemaps': simple_sitemaps}), + url(r'^simple/i18n\.xml$', views.sitemap, {'sitemaps': simple_i18nsitemaps}), url(r'^simple/custom-sitemap\.xml$', views.sitemap, {'sitemaps': simple_sitemaps, 'template_name': 'custom_sitemap.xml'}), url(r'^empty/sitemap\.xml$', views.sitemap, {'sitemaps': empty_sitemaps}), @@ -86,3 +106,7 @@ urlpatterns = [ url(r'^cached/sitemap-(?P
.+)\.xml', cache_page(1)(views.sitemap), {'sitemaps': simple_sitemaps}, name='cached_sitemap') ] + +urlpatterns += i18n_patterns( + url(r'^i18n/testmodel/(?P\d+)/$', testmodelview, name='i18n_testmodel'), +) diff --git a/docs/ref/contrib/sitemaps.txt b/docs/ref/contrib/sitemaps.txt index 8c48651054..e6817dbba4 100644 --- a/docs/ref/contrib/sitemaps.txt +++ b/docs/ref/contrib/sitemaps.txt @@ -232,6 +232,15 @@ Sitemap class reference sitemap was requested is used. If the sitemap is built outside the context of a request, the default is ``'http'``. + .. attribute:: Sitemap.i18n + + .. versionadded:: 1.8 + + **Optional.** + + A boolean attribute that defines if the URLs of this sitemap should + be generated using all of your :setting:`LANGUAGES`. The default is + ``False``. Shortcuts ========= diff --git a/docs/releases/1.8.txt b/docs/releases/1.8.txt index 54bfd2b2ea..b406c661fe 100644 --- a/docs/releases/1.8.txt +++ b/docs/releases/1.8.txt @@ -83,7 +83,8 @@ Minor features :mod:`django.contrib.sitemaps` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -* ... +* The new :attr:`Sitemap.i18n ` attribute + allows you to generate a sitemap based on the :setting:`LANGUAGES` setting. :mod:`django.contrib.sites` ^^^^^^^^^^^^^^^^^^^^^^^^^^^