Add nameLa mechanism for bilingual header, proof set of 11 feasts + St. Lawrence
Deploy / deploy (push) Successful in 1m32s

Threads an optional nameLa field through SanctoralIdentity/SaintRecord/
TemporalFeastRecord/ActiveOctave so day-label.ts can render real Latin
proper names instead of always falling back to English. Authors the
proof set: all 11 named temporal feasts plus St. Lawrence (chosen to
exercise the octave-headline and octave-commemoration code paths too).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EwsZQMjALCvy7u9tFDWmuQ
This commit is contained in:
2026-08-31 06:30:48 -04:00
parent 76cc363a75
commit a6261f044a
27 changed files with 190 additions and 50 deletions
+2 -1
View File
@@ -71,6 +71,7 @@ describe('August sanctoral pull (first pass)', () => {
kind: 'sanctoral',
id: 'st-lawrence',
name: 'St. Lawrence, Martyr',
nameLa: 'Sanctus Laurentius, Martyr',
rank: 'duplex-2-classis',
});
expect(getDayCollect(day).status.en).toBe('verified');
@@ -86,7 +87,7 @@ describe('August sanctoral pull (first pass)', () => {
expect(clareDay.winner.kind).toBe('temporal');
expect(clareDay.commemorations).toEqual([
{ kind: 'sanctoral', id: 'st-clare', name: 'St. Clare, Virgin', rank: 'simplex' },
{ kind: 'octave', id: 'st-lawrence', name: 'St. Lawrence, Martyr' },
{ kind: 'octave', id: 'st-lawrence', name: 'St. Lawrence, Martyr', nameLa: 'Sanctus Laurentius, Martyr' },
]);
// Aug 22 is the Assumption's own octave day (In Octava Assumptionis),
// Duplex, blocking Ss. Timothy/Hippolytus/Symphorian the same way --
+3 -3
View File
@@ -84,7 +84,7 @@ describe('December sanctoral pull (first pass, 12/12)', () => {
// dedicated stacking test below for the full week's build-up.
expect(stephen.commemorations).toEqual([
{ kind: 'temporal', id: expect.any(String) },
{ kind: 'octave', id: 'christmas-day', name: 'Christmas' },
{ kind: 'octave', id: 'christmas-day', name: 'Christmas', nameLa: 'Nativitas Domini' },
]);
});
@@ -101,7 +101,7 @@ describe('December sanctoral pull (first pass, 12/12)', () => {
// all stacked up and commemorate alongside him.
expect(day.commemorations).toEqual([
{ kind: 'temporal', id: expect.any(String) },
{ kind: 'octave', id: 'christmas-day', name: 'Christmas' },
{ kind: 'octave', id: 'christmas-day', name: 'Christmas', nameLa: 'Nativitas Domini' },
{ kind: 'octave', id: 'st-stephen-protomartyr', name: 'St. Stephen, Protomartyr' },
{ kind: 'octave', id: 'st-john-apostle', name: 'St. John, Apostle and Evangelist' },
{ kind: 'octave', id: 'holy-innocents', name: 'The Holy Innocents, Martyrs' },
@@ -155,7 +155,7 @@ describe('December sanctoral pull (first pass, 12/12)', () => {
const dec30 = resolveDay('2033-12-30'); // no saint of its own -- a plain Octave-of-the-Nativity day
expect(dec30.winner.kind).toBe('temporal');
expect(dec30.commemorations).toEqual([
{ kind: 'octave', id: 'christmas-day', name: 'Christmas' },
{ kind: 'octave', id: 'christmas-day', name: 'Christmas', nameLa: 'Nativitas Domini' },
{ kind: 'octave', id: 'st-stephen-protomartyr', name: 'St. Stephen, Protomartyr' },
{ kind: 'octave', id: 'st-john-apostle', name: 'St. John, Apostle and Evangelist' },
{ kind: 'octave', id: 'holy-innocents', name: 'The Holy Innocents, Martyrs' },
+24 -3
View File
@@ -10,7 +10,14 @@ describe('activeOctavesFor', () => {
it("finds a saint's own octave on its own day (day 1) and through day 8, not on day 9", () => {
const day1 = activeOctavesFor('2026-08-10'); // St. Lawrence's own day
expect(day1).toEqual([
{ id: 'st-lawrence', name: 'St. Lawrence, Martyr', wins: 'semiduplex', dayNumber: 1, isClosingDay: false },
{
id: 'st-lawrence',
name: 'St. Lawrence, Martyr',
nameLa: 'Sanctus Laurentius, Martyr',
wins: 'semiduplex',
dayNumber: 1,
isClosingDay: false,
},
]);
// Aug 17 is also day 3 of the Assumption's own octave (started Aug 15) --
@@ -19,7 +26,14 @@ describe('activeOctavesFor', () => {
// pattern, not a per-saint quirk (see calendar/types.ts's OctaveConfig).
const day8 = activeOctavesFor('2026-08-17');
expect(day8).toEqual([
{ id: 'st-lawrence', name: 'St. Lawrence, Martyr', wins: 'duplex', dayNumber: 8, isClosingDay: true },
{
id: 'st-lawrence',
name: 'St. Lawrence, Martyr',
nameLa: 'Sanctus Laurentius, Martyr',
wins: 'duplex',
dayNumber: 8,
isClosingDay: true,
},
{
id: 'assumption',
name: 'The Assumption of the Blessed Virgin Mary',
@@ -37,7 +51,14 @@ describe('activeOctavesFor', () => {
it("Pentecost's octave uses its own configured threshold (duplex), not the default (semiduplex)", () => {
const octaves = activeOctavesFor('2026-05-29'); // within Pentecost's octave, 2026
expect(octaves).toEqual([
{ id: 'pentecost-sunday', name: 'Pentecost', wins: 'duplex', dayNumber: 6, isClosingDay: false },
{
id: 'pentecost-sunday',
name: 'Pentecost',
nameLa: 'Dominica Pentecostes',
wins: 'duplex',
dayNumber: 6,
isClosingDay: false,
},
]);
expect(strictestThreshold(octaves)).toBe('duplex');
});
+3 -2
View File
@@ -46,6 +46,7 @@ describe('transfer mechanism (resolveDay integration)', () => {
kind: 'sanctoral',
id: 'st-lawrence',
name: 'St. Lawrence, Martyr',
nameLa: 'Sanctus Laurentius, Martyr',
rank: 'duplex-2-classis',
});
});
@@ -74,7 +75,7 @@ describe('transfer mechanism (resolveDay integration)', () => {
expect(saturday.winner).toEqual({ kind: 'temporal', id: 'pentecost-sunday' });
expect(saturday.commemorations).toEqual([
{ kind: 'sanctoral', id: 'st-felix-i', name: 'St. Felix I, Pope and Martyr', rank: 'simplex' },
{ kind: 'octave', id: 'pentecost-sunday', name: 'Pentecost' },
{ kind: 'octave', id: 'pentecost-sunday', name: 'Pentecost', nameLa: 'Dominica Pentecostes' },
]);
// Felix doesn't reach Trinity Sunday at all now. Trinity Sunday 2026
@@ -93,7 +94,7 @@ describe('transfer mechanism (resolveDay integration)', () => {
});
expect(sunday.commemorations).toEqual([
{ kind: 'temporal', id: 'post-pentecost-01' },
{ kind: 'octave', id: 'pentecost-sunday', name: 'Pentecost' },
{ kind: 'octave', id: 'pentecost-sunday', name: 'Pentecost', nameLa: 'Dominica Pentecostes' },
]);
});
});