feat(socialMeta): settings.socialMeta.description override (#7599 follow-up)#7691
feat(socialMeta): settings.socialMeta.description override (#7599 follow-up)#7691JohnMcLear merged 1 commit intodevelopfrom
Conversation
…low-up) Issue #7599 follow-up from @stffen: the OG description has no obvious settings.json knob and the i18n catalog default is English, but most preview crawlers (WhatsApp, Signal, Slack, Telegram, Facebook) don't send Accept-Language and so always hit the English fallback regardless of how many locale files translate `pad.social.description`. Keep the i18n catalog as the default source — translatable strings belong in locale files, per the original Qodo review on PR #7635 — but add an explicit `socialMeta.description` setting that wins when set as a non-empty string, regardless of negotiated language. This is the lever that fixes the crawler case for non-English instances without re-introducing per-language config in settings.json (operators who want that still use customLocaleStrings). - Empty/whitespace overrides are treated as unset (would otherwise silently blank the preview). - Override is HTML-escaped via the same path as every other value. - og:locale stays language-negotiated; only the description is forced. - Documented next to publicURL in settings.json.template and settings.json.docker (env var SOCIAL_META_DESCRIPTION). The customLocaleStrings example now spells out pad.social.description so operators discover both routes. 5 new unit specs + 4 new integration specs cover override-wins, null/missing fallback, blank-treated-as-unset, and HTML-escaping. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ⓘ You've reached your Qodo monthly free-tier limit. Reviews pause until next month — upgrade your plan to continue now, or link your paid account if you already have one. |
Review Summary by QodoAdd socialMeta.description setting to override OG preview text
WalkthroughsDescription• Add settings.socialMeta.description override for Open Graph metadata • Override wins over i18n catalog regardless of negotiated language • Solves crawler issue where most preview tools ignore Accept-Language • Empty/whitespace overrides safely fall back to i18n catalog • Comprehensive unit and integration tests validate all scenarios Diagramflowchart LR
A["Operator Setting<br/>socialMeta.description"] -->|"Non-empty string"| B["Use Override<br/>Verbatim"]
A -->|"null/empty/whitespace"| C["Fall Back to<br/>i18n Catalog"]
B --> D["og:description<br/>twitter:description"]
C --> E["Accept-Language<br/>Negotiation"]
E --> D
D --> F["HTML-Escaped<br/>Meta Tags"]
File Changes1. src/node/utils/Settings.ts
|
Code Review by Qodo
Context used✅ Tickets:
🎫 Open Graph Metadata 1. Numeric env override ignored
|
|
Action follow-up to Qodo's bug-find: numeric/boolean env-var coercion fix in PR #7692. |
…7692) * fix(socialMeta): coerced numeric/boolean override silently dropped Qodo flagged on PR #7691: Settings.coerceValue() turns numeric-looking env vars into numbers and "true"/"false" into booleans, so e.g. SOCIAL_META_DESCRIPTION="2026" arrives at the resolver as the number 2026. The previous resolver gated on `typeof override === 'string'`, so it silently fell back to the i18n catalog with no warning — the operator's docker config would appear broken. Accept string|number|boolean and stringify before the empty-check; null / undefined / unsupported types still fall through to the catalog. Two new unit specs cover the numeric and boolean coercion paths. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(socialMeta): widen description type to match coerced runtime Action Qodo bug-find: SettingsType.socialMeta.description and SocialMetaSettings.description still claimed `string | null`, but Settings.coerceValue() can produce number|boolean from env-var-driven config — the previous resolver fix was correct at runtime but the type mismatch forced `as unknown as string` casts in the new tests. Widen both declared types to `string | number | boolean | null` to match runtime reality, drop the typeof string|number|boolean guards in the resolver (the union now narrows automatically) and remove the test casts. Behaviour is unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Follow-up to #7635 / issue #7599 addressing @stffen's comment:
Accept-Language, so they always hit the English fallback in the i18n catalog regardless of how many locales translatepad.social.description.Adds an explicit
socialMeta.descriptionsetting that wins over the i18n catalog when set as a non-empty string. The catalog stays the default — translatable strings still belong in locale files, per the prior Qodo review on PR #7635 — and operators who want fully localised descriptions still usecustomLocaleStrings. The new setting is the lever for the crawler-no-Accept-Language case on non-English instances.Behaviour
socialMeta.descriptionnull/ missing / empty / whitespaceog:descriptionandtwitter:description, regardless of negotiated languageog:localeis unaffected; it continues to reflect the negotiated render language.Files
src/node/utils/Settings.ts— newsocialMeta: { description: string | null }block, defaultnull, with operator-facing JSDoc.src/node/utils/socialMeta.ts—resolveDescriptionWithOverride()checkssettings.socialMeta?.descriptionand falls back to the existing i18n resolver.settings.json.template/settings.json.docker— documented next topublicURL; the docker template wires it to${SOCIAL_META_DESCRIPTION:null}.customLocaleStringsexample now spells out thepad.social.descriptionkey explicitly so operators find both routes.src/tests/backend/specs/socialMeta-unit.ts— 5 new specs (override wins / null fallback / blank-treated-as-unset / HTML escape / missing block).src/tests/backend/specs/socialMeta.ts— 4 new integration specs covering the same matrix end-to-end through Express.docs/superpowers/specs/2026-04-30-issue-7599-open-graph-metadata-design.md— addendum describing the follow-up.Test plan
pnpm --filter ep_etherpad-lite run testforsocialMeta-unit.ts— 31 passing (26 existing + 5 new)pnpm --filter ep_etherpad-lite run testforsocialMeta.tsintegration — 15 passing (11 existing + 4 new)pnpm ts-checkclean forsrc/node/utils/socialMeta.ts,src/node/utils/Settings.ts,src/tests/backend/specs/socialMeta*.ts(pre-existing failures inplugin_packages/are unrelated)socialMeta.descriptioninsettings.json, share the URL into Slack/Signal/WhatsApp, confirm the unfurl shows the override🤖 Generated with Claude Code