Fixed #29352 -- Allowed specifying a Feed language.

This commit is contained in:
Tobias Kunze 2019-04-10 23:48:58 +02:00 committed by Mariusz Felisiak
parent 86a3ad351e
commit 3166880301
6 changed files with 30 additions and 5 deletions

View File

@ -1,6 +1,5 @@
from calendar import timegm from calendar import timegm
from django.conf import settings
from django.contrib.sites.shortcuts import get_current_site from django.contrib.sites.shortcuts import get_current_site
from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
from django.http import Http404, HttpResponse from django.http import Http404, HttpResponse
@ -10,6 +9,7 @@ from django.utils.encoding import iri_to_uri
from django.utils.html import escape from django.utils.html import escape
from django.utils.http import http_date from django.utils.http import http_date
from django.utils.timezone import get_default_timezone, is_naive, make_aware from django.utils.timezone import get_default_timezone, is_naive, make_aware
from django.utils.translation import get_language
def add_domain(domain, url, secure=False): def add_domain(domain, url, secure=False):
@ -30,6 +30,7 @@ class Feed:
feed_type = feedgenerator.DefaultFeed feed_type = feedgenerator.DefaultFeed
title_template = None title_template = None
description_template = None description_template = None
language = None
def __call__(self, request, *args, **kwargs): def __call__(self, request, *args, **kwargs):
try: try:
@ -134,7 +135,7 @@ class Feed:
subtitle=self._get_dynamic_attr('subtitle', obj), subtitle=self._get_dynamic_attr('subtitle', obj),
link=link, link=link,
description=self._get_dynamic_attr('description', obj), description=self._get_dynamic_attr('description', obj),
language=settings.LANGUAGE_CODE, language=self.language or get_language(),
feed_url=add_domain( feed_url=add_domain(
current_site.domain, current_site.domain,
self._get_dynamic_attr('feed_url', obj) or request.path, self._get_dynamic_attr('feed_url', obj) or request.path,

View File

@ -307,8 +307,14 @@ Language
-------- --------
Feeds created by the syndication framework automatically include the Feeds created by the syndication framework automatically include the
appropriate ``<language>`` tag (RSS 2.0) or ``xml:lang`` attribute (Atom). This appropriate ``<language>`` tag (RSS 2.0) or ``xml:lang`` attribute (Atom). By
comes directly from your :setting:`LANGUAGE_CODE` setting. default, this is :func:`django.utils.translation.get_language()`. You can change it
by setting the ``language`` class attribute.
.. versionchanged:: 3.0
The ``language`` class attribute was added. In older versions, the behavior
is the same as ``language = settings.LANGUAGE_CODE``.
URLs URLs
---- ----
@ -406,6 +412,10 @@ This example illustrates all possible attributes and methods for a
title_template = None title_template = None
description_template = None description_template = None
# LANGUAGE -- Optional. This should be a string specifying a language
# code. Defaults to django.utils.translation.get_language().
language = 'de'
# TITLE -- One of the following three is required. The framework # TITLE -- One of the following three is required. The framework
# looks for them in this order. # looks for them in this order.

View File

@ -116,7 +116,10 @@ Minor features
:mod:`django.contrib.syndication` :mod:`django.contrib.syndication`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* ... * Added the ``language`` class attribute to the
:class:`django.contrib.syndication.views.Feed` to customize a feed language.
The default value is :func:`~django.utils.translation.get_language()` instead
of setting:`LANGUAGE_CODE`.
Cache Cache
~~~~~ ~~~~~

View File

@ -136,6 +136,10 @@ class TemplateContextFeed(TestRss2Feed):
return context return context
class TestLanguageFeed(TestRss2Feed):
language = 'de'
class NaiveDatesFeed(TestAtomFeed): class NaiveDatesFeed(TestAtomFeed):
""" """
A feed with naive (non-timezone-aware) dates. A feed with naive (non-timezone-aware) dates.

View File

@ -82,6 +82,7 @@ class SyndicationFeedTest(FeedTestCase):
self.assertEqual(len(feed_elem), 1) self.assertEqual(len(feed_elem), 1)
feed = feed_elem[0] feed = feed_elem[0]
self.assertEqual(feed.getAttribute('version'), '2.0') self.assertEqual(feed.getAttribute('version'), '2.0')
self.assertEqual(feed.getElementsByTagName('language')[0].firstChild.nodeValue, 'en')
# Making sure there's only one `channel` element w/in the # Making sure there's only one `channel` element w/in the
# `rss` element. # `rss` element.
@ -363,6 +364,11 @@ class SyndicationFeedTest(FeedTestCase):
summary = entry.getElementsByTagName('summary')[0] summary = entry.getElementsByTagName('summary')[0]
self.assertEqual(summary.getAttribute('type'), 'html') self.assertEqual(summary.getAttribute('type'), 'html')
def test_feed_generator_language_attribute(self):
response = self.client.get('/syndication/language/')
feed = minidom.parseString(response.content).firstChild
self.assertEqual(feed.firstChild.getElementsByTagName('language')[0].firstChild.nodeValue, 'de')
def test_title_escaping(self): def test_title_escaping(self):
""" """
Titles are escaped correctly in RSS feeds. Titles are escaped correctly in RSS feeds.

View File

@ -15,6 +15,7 @@ urlpatterns = [
path('syndication/atom/', feeds.TestAtomFeed()), path('syndication/atom/', feeds.TestAtomFeed()),
path('syndication/latest/', feeds.TestLatestFeed()), path('syndication/latest/', feeds.TestLatestFeed()),
path('syndication/custom/', feeds.TestCustomFeed()), path('syndication/custom/', feeds.TestCustomFeed()),
path('syndication/language/', feeds.TestLanguageFeed()),
path('syndication/naive-dates/', feeds.NaiveDatesFeed()), path('syndication/naive-dates/', feeds.NaiveDatesFeed()),
path('syndication/aware-dates/', feeds.TZAwareDatesFeed()), path('syndication/aware-dates/', feeds.TZAwareDatesFeed()),
path('syndication/feedurl/', feeds.TestFeedUrlFeed()), path('syndication/feedurl/', feeds.TestFeedUrlFeed()),