Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions calendarium/api_urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,5 @@
path('feed/', cache(ReadingsFeed()), name='rss-feed'),
path('feed/<cal:cal>/', cache(ReadingsFeed()), name='rss-feed-cal'),
path('feed/<tradition:tradition>/<cal:cal>/', cache(ReadingsFeed()), name='rss-feed-cal'),
path('feed/<tradition:tradition>/<cal:cal>/<translation:translation>/', cache(ReadingsFeed()), name='rss-feed-cal'),
]
21 changes: 14 additions & 7 deletions calendarium/feeds.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from django.utils.feedgenerator import Rss201rev2Feed

from . import liturgics
from .datetools import Calendar, Tradition
from .datetools import Calendar, Tradition, TRANSLATION_LABELS


class WSRssFeed(Rss201rev2Feed):
Expand All @@ -27,22 +27,29 @@ class ReadingsFeed(Feed):
description_template = 'feed_description.html'
item_categories = categories = 'orthodox', 'christian', 'religion'

def get_object(self, request, cal=Calendar.Gregorian, tradition=Tradition.Slavic):
return {'cal': cal, 'tradition': tradition}
def get_object(self, request, cal=Calendar.Gregorian, tradition=Tradition.Slavic, translation=None):
return {'cal': cal, 'tradition': tradition, 'translation': translation}

def title(self, obj):
return f'Orthodox Daily Readings ({obj["tradition"].title()}, {obj["cal"].title()})'
title = f'Orthodox Daily Readings ({obj["tradition"].title()}, {obj["cal"].title()})'
if obj['translation']:
title += f' [{TRANSLATION_LABELS[obj["translation"]]}]'
return title

def description(self, obj):
return (f'Daily readings from scripture and the lives of the saints according to the '
f'{obj["tradition"].title()} tradition, {obj["cal"].title()} calendar.')
description = (f'Daily readings from scripture and the lives of the saints according to the '
f'{obj["tradition"].title()} tradition, {obj["cal"].title()} calendar.')
if obj['translation']:
description += f' Scripture from the {TRANSLATION_LABELS[obj["translation"]]}.'
return description

def items(self, obj):
now = timezone.localtime()
start_dt = now - timedelta(days=10)
for dt in rrule(DAILY, dtstart=start_dt, until=now):
day = liturgics.Day(dt.year, dt.month, dt.day, calendar=obj['cal'], tradition=obj['tradition'])
day = liturgics.Day(dt.year, dt.month, dt.day, calendar=obj['cal'], tradition=obj['tradition'], translation=obj['translation'])
day.initialize()
day.get_readings(fetch_content=True)
yield day

def item_pubdate(self, day):
Expand Down
11 changes: 11 additions & 0 deletions calendarium/liturgics/day.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,17 @@ async def ainitialize(self):
def __str__(self):
return str(self.date)

@cached_property
def translation_label(self):
"""Human-readable label for the Bible translation actually in effect
-- resolves the per-language default the same way VerseManager does,
since self.translation is often None (meaning "use the default")
rather than always holding a concrete value."""

from bible.models import DEFAULT_TRANSLATIONS

return datetools.TRANSLATION_LABELS[self.translation or DEFAULT_TRANSLATIONS[self.language]]

@cached_property
def summary_title(self):
"""A simplified title that summarizes the day's commemorations."""
Expand Down
4 changes: 2 additions & 2 deletions calendarium/templates/feed_description.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ <h2>Commemorations</h2>
</ul>
{% endif %}

<h2>Scripture Readings&nbsp;(KJV)</h2>
<h2>Scripture Readings&nbsp;({{ obj.translation_label }})</h2>

{% for reading in obj.get_readings %}
<section>
Expand All @@ -47,7 +47,7 @@ <h3>
</h3>

<p>
{% for verse in reading.pericope.get_passage %}
{% for verse in reading.pericope.passage %}
{% if verse.paragraph_start and not forloop.first %}</p><p>{% endif %}
<sup>{{ verse.verse }}</sup> {{ verse.content }}
{% endfor %}
Expand Down
19 changes: 19 additions & 0 deletions calendarium/tests/test_feeds.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import re

from freezegun import freeze_time

from django.test import TestCase
from django.urls import reverse

Expand Down Expand Up @@ -42,3 +44,20 @@ def test_title_distinguishes_tradition(self):
slavic_title = re.search(r'<title>(.*?)</title>', self.client.get(slavic_url).content.decode('utf-8')).group(1)
greek_title = re.search(r'<title>(.*?)</title>', self.client.get(greek_url).content.decode('utf-8')).group(1)
self.assertNotEqual(slavic_title, greek_title)

@freeze_time('2026-07-25 12:00:00') # noon UTC stays July 25 in America/Los_Angeles too
def test_translation_changes_passage_content(self):
"""A regression test: the feed's items() didn't pass fetch_content=True
to get_readings(), and feed_description.html called the get_passage()
method (fresh query, its own kjv-defaulting args) instead of the
passage attribute -- so an explicit translation was silently ignored
and every feed rendered KJV regardless of what was requested."""
kjv_url = reverse('rss-feed-cal', kwargs={'tradition': Tradition.Slavic, 'cal': Calendar.Gregorian})
lxx_url = reverse('rss-feed-cal', kwargs={'tradition': Tradition.Slavic, 'cal': Calendar.Gregorian, 'translation': 'lxx2012-web'})

kjv_body = self.client.get(kjv_url).content.decode('utf-8')
lxx_body = self.client.get(lxx_url).content.decode('utf-8')

self.assertIn('subject unto the higher powers', kjv_body)
self.assertIn('in subjection to the higher authorities', lxx_body)
self.assertNotIn('subject unto the higher powers', lxx_body)
12 changes: 7 additions & 5 deletions calendarium/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@
from django.urls import reverse
from django.utils import timezone

from bible.models import DEFAULT_TRANSLATIONS

from . import liturgics, models
from .datetools import Calendar, Tradition, Translation, TRANSLATION_LABELS, cal_session_key, translation_session_key

Expand Down Expand Up @@ -50,7 +48,7 @@ async def readings_view(request, cal=None, tradition=None, translation=None, yea
'cal': cal,
'tradition': tradition,
'translation': translation,
'translation_label': TRANSLATION_LABELS[translation or DEFAULT_TRANSLATIONS[request.LANGUAGE_CODE]],
'translation_label': day.translation_label,
# Only the selectable (English) translations, not every code that can
# appear in Verse rows -- ro/sr each have one fixed translation with
# no dropdown, so rccv/srp1865 aren't offered as choices here.
Expand Down Expand Up @@ -166,14 +164,18 @@ def remember_translation(request, translation, language):
session_key = translation_session_key(language)

if translation:
if translation != request.session.get(session_key, Translation.KJV):
if translation != request.session.get(session_key, Translation.LXX2012WEB):
request.session[session_key] = translation

# Don't send vary on cookie header when we have an explicit translation.
# In this case, the session does not actually impact the content.
request.session.accessed = False
else:
translation = request.session.get(session_key, Translation.KJV)
# Only the readings page defaults to the modern translation -- the
# API and RSS feeds are unaffected, since neither calls this function;
# they resolve translation=None straight through to
# bible.models.DEFAULT_TRANSLATIONS['en'] (kjv), unchanged.
translation = request.session.get(session_key, Translation.LXX2012WEB)

return translation

Expand Down
5 changes: 5 additions & 0 deletions orthocal/templates/feeds.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ <h3>RSS</h3>
<blockquote><a href="{% url "rss-feed-cal" tradition="greek" cal="gregorian" %}">{% fullurl "rss-feed-cal" tradition="greek" cal="gregorian" %}</a></blockquote>
<blockquote><a href="{% url "rss-feed-cal" tradition="greek" cal="julian" %}">{% fullurl "rss-feed-cal" tradition="greek" cal="julian" %}</a></blockquote>

<p>Every RSS feed above reads from the King James Version by default. For the more modern LXX2012+WEB
pairing instead, add the translation to the URL:</p>

<blockquote><a href="{% url "rss-feed-cal" tradition="slavic" cal="gregorian" translation="lxx2012-web" %}">{% fullurl "rss-feed-cal" tradition="slavic" cal="gregorian" translation="lxx2012-web" %}</a></blockquote>

<h3>iCal</h3>

<p>An ical feed for the Slavic tradition, new calendar is available at:</p>
Expand Down