Skip to content

Fix blog dates ignoring the page locale - #35

Merged
cverorg merged 2 commits into
mainfrom
fix/blog-date-locale
Sep 11, 2026
Merged

Fix blog dates ignoring the page locale#35
cverorg merged 2 commits into
mainfrom
fix/blog-date-locale

Conversation

@cverorg

@cverorg cverorg commented Sep 11, 2026

Copy link
Copy Markdown
Member

Summary

Fixes #34.

  • fmtDate(s, format, lang) gains a third lang argument: the page's own BCP-47 locale (the Lingo variant actually being rendered). Its default/unrecognised branch now formats with Intl.DateTimeFormat(toBcp47(lang), { year: 'numeric', month: 'long', day: 'numeric' }) instead of an unconditional en-US literal. When no locale is known, output stays byte-identical to the historic en-US string.
  • Every fmtDate caller (ArchiveView.astro, BlogIndexView.astro, PostArticle.astro, and the /search/label/[tag] archive routes) now passes the page's own meta.lang, not the site default.
  • cjk is accepted as an alias of cjk-full.
  • An unrecognised blog-date-format value still renders (the locale default, never a blank date), and now emits one build-time warning naming the allowed values — once per build per bad value, not once per post.
  • A site declaring a non-English lang with no blog-date-format set will see its dates change (e.g. lang: zh-Hant moves from July 13, 2024 to 2024年7月13日) — this is the point of the fix, but is a real, visible output change for any such site's existing pages.

Round 1 review fixes

  • P1 — invalid lang crashed the whole build. A lang: value that is not a well-formed BCP-47 tag (ja_JP, zh_TW, en US, non-ASCII text) made Intl.DateTimeFormat throw RangeError, taking the whole build down on the first date it rendered — a regression versus main, which always rendered (in English) regardless of lang. fmtDate's locale-default renderer now tries the page's tag and falls back to the historic en-US output, byte-identical to main, on any tag Intl rejects; never throws.
  • P2-1 — an explicit CJK format was applied to every locale, including English. Ruling (2026-09-11): an explicit blog-date-format is the site owner's choice for the locales it fits. cjk / cjk-full / cjk-badge / cjk-md are a script, not a punctuation style, so they now apply only when the page's own locale is Japanese, Korean, or Chinese (ja/ko/zh-*) — a non-CJK page locale renders that locale's own Intl default instead (so an en-US page stays July 13, 2024 even when the site sets blog-date-format: cjk). ymd-slash has no script and is unaffected — it always applies, on every locale, as before. When no page locale is known at all (lang absent), a named CJK format still always renders, matching the pre-existing behaviour before lang was threaded through. This rule is documented at the CJK_DATE_FORMATS/isCJKLang definitions and the fmtDate doc comment in packages/sitetile/astro/src/lib/blog.mjs.

Cheap round 1 P3s also applied

  • Fixed a timezone-dependent test suite (blog-date-format.test.mjs pins TZ=UTC for its own process) — the underlying UTC-midnight-vs-local-date gap is pre-existing elsewhere and out of scope here.
  • Added a hardcoded ICU literal assertion (ja-JP2024年7月13日) so a small-ICU/system-ICU runner missing Japanese locale data fails loudly instead of silently passing on an Intl-vs-Intl comparison.
  • Replaced the structural regex in chrome-copy.test.mjs that pinned fmtDate's exact default-branch source text with a behavioural check (it would have broken on the P1 fix's try/catch for no reason related to what it was guarding).
  • Added a structural guard requiring every fmtDate( call site to pass a lang argument, mirroring the existing dateBadgeParts guard.
  • Added a test asserting every KNOWN_DATE_FORMATS entry renders without an "unrecognised format" warning.

Test plan

  • node packages/sitetile/blog-date-format.test.mjs — 9 tests: no-format under ja-JP/zh-TW/en-US against Intl's own output plus a pinned ICU literal, no-format-no-locale byte-identical, cjk alias, the new CJK-locale-gating rule (ja-JP/zh-TW/ko-KR stay CJK, en-US falls back, ymd-slash always applies), unrecognised value warns once and still renders the locale default, every KNOWN_DATE_FORMATS value warns never, every existing explicit format unchanged, unparseable date passthrough, and the new invalid-BCP-47-tag guard (garbage tags, empty tag, non-CJK bad tag under a CJK format) never throws and matches main's byte-identical en-US output.
  • Same suite re-run under TZ=America/Los_Angeles — all 9 pass.
  • node packages/sitetile/chrome-copy.test.mjs — 15 tests, including the new behavioural (not structural) CJK-neutrality check and the new fmtDate call-site guard.
  • node packages/sitetile/blog-locale-archives.test.mjs, blog-unlisted.test.mjs, blog-defaults.test.mjs, blog-tenancy.test.mjs, blog-url-gating.test.mjs — unaffected, all green (28/18/2/14/15).

Not verified

  • No end-to-end Astro build/smoke test was run (packages/sitetile/astro/node_modules is not installed in this environment), so the actual rendered HTML on a live multi-locale build was not visually re-checked this round — only the underlying fmtDate/call-site changes were unit-tested.

fmtDate(s, format, lang) now formats its default/unrecognised branch with
the page's own BCP-47 locale via Intl.DateTimeFormat, instead of an
unconditional en-US literal. Every caller (ArchiveView, BlogIndexView,
PostArticle, and the /search/label archive routes) now passes the page's
own meta.lang (the Lingo variant actually being rendered), not the site
default. No locale known keeps the historic en-US output byte-identical.

`cjk` is accepted as an alias of `cjk-full`. Any other unrecognised
blog-date-format value still renders (the locale default, never a blank
date) but emits one build-time warning naming the allowed values, instead
of silently doing nothing.

Fixes #34
…locales

An invalid BCP-47 lang tag (e.g. ja_JP, en US) made Intl.DateTimeFormat throw
and crash the whole build; fmtDate's locale-default renderer now falls back
to the historic en-US output on any tag Intl rejects, matching main.

An explicit CJK blog-date-format (cjk/cjk-full/cjk-badge/cjk-md) was applied
to every page locale, including English. Per the 2026-09-11 ruling, these
formats now apply only to CJK page locales (ja/ko/zh-*); other locales get
their own Intl default. ymd-slash stays script-neutral and unaffected.

Also fixes a timezone-dependent test suite, pins an ICU literal so a
small-ICU runner fails loudly instead of passing silently, replaces a
source-text regex broken by the new guard with a behavioural check, and
adds call-site and KNOWN_DATE_FORMATS coverage.
@cverorg

cverorg commented Sep 11, 2026

Copy link
Copy Markdown
Member Author

Round 1 fixed: fmtDate no longer crashes on an invalid BCP-47 lang tag (falls back to main's byte-identical en-US output), and an explicit CJK blog-date-format now applies only to CJK page locales (ja/ko/zh-*) rather than every locale — ymd-slash stays unaffected; details and the cheap P3s applied are in the updated PR description.

@cverorg
cverorg merged commit 6662a72 into main Sep 11, 2026
2 checks passed
@cverorg
cverorg deleted the fix/blog-date-locale branch September 11, 2026 12:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

blog dates ignore the page locale: fmtDate falls back to en-US, and an unknown blog-date-format value silently does the same

1 participant