Browse Source

Fixed #29352 -- Allowed specifying a Feed language.

Tobias Kunze 6 years ago
parent
commit
3166880301

+ 3 - 2
django/contrib/syndication/views.py

@@ -1,6 +1,5 @@
 from calendar import timegm
 
-from django.conf import settings
 from django.contrib.sites.shortcuts import get_current_site
 from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
 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.http import http_date
 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):
@@ -30,6 +30,7 @@ class Feed:
     feed_type = feedgenerator.DefaultFeed
     title_template = None
     description_template = None
+    language = None
 
     def __call__(self, request, *args, **kwargs):
         try:
@@ -134,7 +135,7 @@ class Feed:
             subtitle=self._get_dynamic_attr('subtitle', obj),
             link=link,
             description=self._get_dynamic_attr('description', obj),
-            language=settings.LANGUAGE_CODE,
+            language=self.language or get_language(),
             feed_url=add_domain(
                 current_site.domain,
                 self._get_dynamic_attr('feed_url', obj) or request.path,

+ 12 - 2
docs/ref/contrib/syndication.txt

@@ -307,8 +307,14 @@ Language
 --------
 
 Feeds created by the syndication framework automatically include the
-appropriate ``<language>`` tag (RSS 2.0) or ``xml:lang`` attribute (Atom). This
-comes directly from your :setting:`LANGUAGE_CODE` setting.
+appropriate ``<language>`` tag (RSS 2.0) or ``xml:lang`` attribute (Atom). By
+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
 ----
@@ -406,6 +412,10 @@ This example illustrates all possible attributes and methods for a
         title_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
         # looks for them in this order.
 

+ 4 - 1
docs/releases/3.0.txt

@@ -116,7 +116,10 @@ Minor features
 :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
 ~~~~~

+ 4 - 0
tests/syndication_tests/feeds.py

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

+ 6 - 0
tests/syndication_tests/tests.py

@@ -82,6 +82,7 @@ class SyndicationFeedTest(FeedTestCase):
         self.assertEqual(len(feed_elem), 1)
         feed = feed_elem[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
         # `rss` element.
@@ -363,6 +364,11 @@ class SyndicationFeedTest(FeedTestCase):
             summary = entry.getElementsByTagName('summary')[0]
             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):
         """
         Titles are escaped correctly in RSS feeds.

+ 1 - 0
tests/syndication_tests/urls.py

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