✨ Added ability to put a share button on posts#26866
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThis pull request introduces a new Share modal feature to the Portal application. The implementation includes a new ShareModal component that extracts metadata from the host document (canonical URL, Open Graph tags, Twitter tags, favicon, site name, and author) and generates social share links for Twitter, Facebook, LinkedIn, Threads, Bluesky, and email. The component provides copy-to-clipboard functionality with visual feedback and a collapsible menu for additional sharing options. The 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 9
🧹 Nitpick comments (4)
ghost/i18n/locales/zh-Hant/portal.json (1)
58-59: Prefer real zh-Hant strings for new share actions (instead of empty placeholders).At Line 58, Line 59, Line 88, Line 127, Line 176, Line 214, and Line 244, these are user-facing modal actions. Using empty strings can produce mixed-language/blank labels in localized UI. Consider filling these now.
Suggested translation patch
- "Copied": "", - "Copy link": "", + "Copied": "已複製", + "Copy link": "複製連結", @@ - "Facebook": "", + "Facebook": "Facebook", @@ - "LinkedIn": "", + "LinkedIn": "LinkedIn", @@ - "Share": "", + "Share": "分享", @@ - "Threads": "", + "Threads": "Threads", @@ - "X (Twitter)": "", + "X (Twitter)": "X(Twitter)",Also applies to: 88-88, 127-127, 176-176, 214-214, 244-244
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ghost/i18n/locales/zh-Hant/portal.json` around lines 58 - 59, Replace the empty strings for the user-facing share/action keys (e.g., "Copied", "Copy link" and the other modal action keys referenced in the review) with proper Traditional Chinese (zh-Hant) translations so the localized UI doesn't show blank or English labels; update the values for the keys "Copied" and "Copy link" (and the other empty action keys at the locations noted) with suitable zh-Hant strings that match the tone of the portal UI.ghost/i18n/locales/ca/portal.json (1)
58-59: Populate the new share labels in Catalan before shipping broadly.These new share-related keys are currently empty. Even with fallback behavior, this creates an inconsistent localized experience in the new modal.
Suggested translation patch
- "Copied": "", - "Copy link": "", + "Copied": "Copiat", + "Copy link": "Copia l'enllaç", @@ - "Facebook": "", + "Facebook": "Facebook", @@ - "LinkedIn": "", + "LinkedIn": "LinkedIn", @@ - "Share": "", + "Share": "Comparteix", @@ - "Threads": "", + "Threads": "Threads", @@ - "X (Twitter)": "", + "X (Twitter)": "X (Twitter)",Also applies to: 88-88, 127-127, 176-176, 214-214, 244-244
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ghost/i18n/locales/ca/portal.json` around lines 58 - 59, The new share-related keys in the Catalan locale ("Copied" and "Copy link" and the other empty share labels present in portal.json) are empty and must be populated; update the translation strings for the keys "Copied", "Copy link" (and any other blank share-related keys referenced in the file) with correct Catalan equivalents so the share modal displays localized text instead of falling back to the default language, keeping the key names unchanged.ghost/i18n/locales/he/portal.json (1)
58-59: Prefer non-empty defaults for new share-related locale keys.Lines 58, 59, 88, 127, 176, 214, and 244 add new keys with empty values. This can produce inconsistent UX for Hebrew users (fallback language mix, or blank labels if fallback doesn’t trigger on empty strings). Consider setting explicit values now.
Proposed patch
- "Copied": "", - "Copy link": "", + "Copied": "הועתק", + "Copy link": "העתק קישור", @@ - "Facebook": "", + "Facebook": "Facebook", @@ - "LinkedIn": "", + "LinkedIn": "LinkedIn", @@ - "Share": "", + "Share": "שיתוף", @@ - "Threads": "", + "Threads": "Threads", @@ - "X (Twitter)": "", + "X (Twitter)": "X (Twitter)",Also applies to: 88-88, 127-127, 176-176, 214-214, 244-244
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ghost/i18n/locales/he/portal.json` around lines 58 - 59, Several new share-related locale keys (e.g., "Copied" and "Copy link") were added with empty values; replace those empty strings with explicit non-empty Hebrew defaults (or clear English placeholders if Hebrew translations are not ready) for "Copied", "Copy link" and the other newly added share-related locale keys in this locale file so the UI never falls back to a blank label; keep the same quoting/JSON style as surrounding entries and follow existing translation conventions when providing the values.ghost/i18n/locales/context.json (1)
70-71: Add translator context text for the new share labels.These entries are currently blank, which removes guidance for translators and can cause inconsistent wording across locales.
💡 Suggested context text
- "Copied": "", - "Copy link": "", + "Copied": "Toast text shown after a share URL is copied", + "Copy link": "Button label to copy the current page URL in the share modal", ... - "Facebook": "", + "Facebook": "Share target label for Facebook", ... - "LinkedIn": "", + "LinkedIn": "Share target label for LinkedIn", ... - "Share": "", + "Share": "Title/label for the share modal and share actions", ... - "Threads": "", + "Threads": "Share target label for Threads", ... - "X (Twitter)": "", + "X (Twitter)": "Share target label for X (formerly Twitter)"Also applies to: 109-109, 164-164, 245-245, 310-310, 354-354
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ghost/i18n/locales/context.json` around lines 70 - 71, The i18n context entries for the share labels are blank; add concise translator context strings for the keys "Copied" and "Copy link" (and the other identical keys elsewhere) so translators understand intent and tone — e.g., indicate whether "Copied" is a confirmation message shown after copying a link and whether "Copy link" is a button/action label; update the context.json entries for the "Copied" and "Copy link" keys (and matching keys found in the same file) with those brief explanatory notes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/portal/README.md`:
- Line 25: The README entry describing how to open the share modal is
inconsistent: update the route fragment documented alongside data-portal="share"
to match the PR objective by replacing `#/portal/share` with `#/share` (so the
docs show Share modal can be opened with `data-portal="share"` (or `#/share`));
ensure both the inline fragment text and any other references in the same file
that mention `#/portal/share` are changed to `#/share`.
In `@apps/portal/src/app.js`:
- Around line 953-956: The share route mapping returning {page: 'share'} is
never reached because fetchLinkData's linkRegex only matches hashes like
/portal/..., so hashes like "#/share" bypass it; update fetchLinkData to
recognize the "#/share" fragment (either by expanding linkRegex to include
^#\/share(?:\/|$) or adding an explicit check for hash.startsWith('#/share')) so
that when the hash is "#/share" it returns the same path === 'share' result and
triggers the modal; refer to fetchLinkData and linkRegex as the places to change
and ensure the code path that builds {page: 'share'} is returned for "#/share".
In `@apps/portal/test/unit/components/pages/share-modal.test.js`:
- Around line 95-100: The test assertions in the ShareModal unit test check
button order incorrectly; update the expectations that read the actions array
(from container.querySelector('.gh-portal-share-actions').children) so they
assert the actual DOM order: actions[0] = 'copy', actions[1] = 'email',
actions[2] = 'twitter', actions[3] = 'facebook', actions[4] =
'gh-portal-share-more' (adjust the expect(...).toHaveClass calls accordingly in
the share-modal.test.js test that references the actions array).
In `@ghost/i18n/locales/de-CH/portal.json`:
- Around line 58-59: The de-CH locale file has empty translations for the new
share-modal keys (e.g., "Copied" and "Copy link" in portal.json and the other
empty entries noted); populate each empty string with the correct Swiss German
translations (or explicit passthrough if they are brand names) so the UI doesn’t
fallback to source strings—update the keys "Copied", "Copy link" and the other
empty keys mentioned (lines referenced in the review) with appropriate localized
text, preserving the JSON key names and punctuation.
In `@ghost/i18n/locales/en/portal.json`:
- Line 33: Add the missing translation keys "Bluesky" and "More options" to
every locale's portal.json and to the shared context.json metadata so
translations and fallback behavior remain consistent; for each locale file add
the same key names (use the English strings or empty "" placeholders as
appropriate) and in context.json add corresponding entries for "Bluesky" and
"More options" so tools that read context/metadata can detect them.
In `@ghost/i18n/locales/hu/portal.json`:
- Around line 58-59: Add Hungarian translations for the actionable UI strings in
the portal.json locale: set "Copied" to "Másolva", "Copy link" to "Link
másolása", and "Share" to "Megosztás"; ensure you update both occurrences
referenced in the file (the keys "Copied", "Copy link", and "Share") so the
user-facing copy is consistently localized across the portal.
In `@ghost/i18n/locales/nn/portal.json`:
- Around line 58-59: The nn locale file has empty values for several UI strings
causing fallback to keys; update portal.json by supplying Norwegian Nynorsk
translations for the keys "Copied", "Copy link", "Facebook", "LinkedIn",
"Share", "Threads", and "X (Twitter)" (the exact entries shown in the diff) so
they are not empty, or explicitly mark/annotate them as intentional placeholders
before merging; ensure you edit the nn/portal.json entries for those keys to
contain the correct Nynorsk strings.
In `@ghost/i18n/locales/sl/portal.json`:
- Around line 58-59: Add the missing "Bluesky" translation key to the Slovenian
portal locale so t('Bluesky') used by ShareModal resolves; update the JSON in
sl/portal.json to include the entry "Bluesky": "" alongside the existing social
platform keys (e.g., "Facebook", "LinkedIn", "Threads", "X (Twitter)") so the
ShareModal component in apps/portal/src/components/pages/share-modal.js finds
the key.
In `@ghost/i18n/locales/sr-Cyrl/portal.json`:
- Around line 58-59: Fill in Serbian Cyrillic translations for the empty generic
UI action keys in ghost/i18n/locales/sr-Cyrl/portal.json — specifically provide
proper SR-Cyrl values for "Copied" and "Copy link" and for the other empty
entries referenced (the empty generic action keys around the same modal at the
other noted locations). Update those JSON values with concise Serbian-Cyrillic
strings (keeping brand names unchanged if present) so the new Share modal does
not display mixed-language UI.
---
Nitpick comments:
In `@ghost/i18n/locales/ca/portal.json`:
- Around line 58-59: The new share-related keys in the Catalan locale ("Copied"
and "Copy link" and the other empty share labels present in portal.json) are
empty and must be populated; update the translation strings for the keys
"Copied", "Copy link" (and any other blank share-related keys referenced in the
file) with correct Catalan equivalents so the share modal displays localized
text instead of falling back to the default language, keeping the key names
unchanged.
In `@ghost/i18n/locales/context.json`:
- Around line 70-71: The i18n context entries for the share labels are blank;
add concise translator context strings for the keys "Copied" and "Copy link"
(and the other identical keys elsewhere) so translators understand intent and
tone — e.g., indicate whether "Copied" is a confirmation message shown after
copying a link and whether "Copy link" is a button/action label; update the
context.json entries for the "Copied" and "Copy link" keys (and matching keys
found in the same file) with those brief explanatory notes.
In `@ghost/i18n/locales/he/portal.json`:
- Around line 58-59: Several new share-related locale keys (e.g., "Copied" and
"Copy link") were added with empty values; replace those empty strings with
explicit non-empty Hebrew defaults (or clear English placeholders if Hebrew
translations are not ready) for "Copied", "Copy link" and the other newly added
share-related locale keys in this locale file so the UI never falls back to a
blank label; keep the same quoting/JSON style as surrounding entries and follow
existing translation conventions when providing the values.
In `@ghost/i18n/locales/zh-Hant/portal.json`:
- Around line 58-59: Replace the empty strings for the user-facing share/action
keys (e.g., "Copied", "Copy link" and the other modal action keys referenced in
the review) with proper Traditional Chinese (zh-Hant) translations so the
localized UI doesn't show blank or English labels; update the values for the
keys "Copied" and "Copy link" (and the other empty action keys at the locations
noted) with suitable zh-Hant strings that match the tone of the portal UI.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: bb5a4a8c-a7d1-4784-9b27-0f9eaa9d4db3
⛔ Files ignored due to path filters (8)
apps/portal/src/images/icons/ellipsis.svgis excluded by!**/*.svgapps/portal/src/images/icons/envelope.svgis excluded by!**/*.svgapps/portal/src/images/icons/share-bluesky.svgis excluded by!**/*.svgapps/portal/src/images/icons/share-facebook.svgis excluded by!**/*.svgapps/portal/src/images/icons/share-link.svgis excluded by!**/*.svgapps/portal/src/images/icons/share-linkedin.svgis excluded by!**/*.svgapps/portal/src/images/icons/share-threads.svgis excluded by!**/*.svgapps/portal/src/images/icons/share-x.svgis excluded by!**/*.svg
📒 Files selected for processing (73)
apps/portal/README.mdapps/portal/src/app.jsapps/portal/src/components/frame.styles.jsapps/portal/src/components/pages/share-modal.jsapps/portal/src/pages.jsapps/portal/src/utils/copy-to-clipboard.jsapps/portal/test/data-attributes.test.jsapps/portal/test/portal-links.test.jsapps/portal/test/unit/components/pages/share-modal.test.jsapps/portal/test/utils/copy-to-clipboard.test.jsghost/i18n/locales/af/portal.jsonghost/i18n/locales/ar/portal.jsonghost/i18n/locales/bg/portal.jsonghost/i18n/locales/bn/portal.jsonghost/i18n/locales/bs/portal.jsonghost/i18n/locales/ca/portal.jsonghost/i18n/locales/context.jsonghost/i18n/locales/cs/portal.jsonghost/i18n/locales/da/portal.jsonghost/i18n/locales/de-CH/portal.jsonghost/i18n/locales/de/portal.jsonghost/i18n/locales/el/portal.jsonghost/i18n/locales/en/portal.jsonghost/i18n/locales/eo/portal.jsonghost/i18n/locales/es/portal.jsonghost/i18n/locales/et/portal.jsonghost/i18n/locales/eu/portal.jsonghost/i18n/locales/fa/portal.jsonghost/i18n/locales/fi/portal.jsonghost/i18n/locales/fr/portal.jsonghost/i18n/locales/gd/portal.jsonghost/i18n/locales/he/portal.jsonghost/i18n/locales/hi/portal.jsonghost/i18n/locales/hr/portal.jsonghost/i18n/locales/hu/portal.jsonghost/i18n/locales/id/portal.jsonghost/i18n/locales/is/portal.jsonghost/i18n/locales/it/portal.jsonghost/i18n/locales/ja/portal.jsonghost/i18n/locales/ko/portal.jsonghost/i18n/locales/kz/portal.jsonghost/i18n/locales/lt/portal.jsonghost/i18n/locales/lv/portal.jsonghost/i18n/locales/mk/portal.jsonghost/i18n/locales/mn/portal.jsonghost/i18n/locales/ms/portal.jsonghost/i18n/locales/nb/portal.jsonghost/i18n/locales/ne/portal.jsonghost/i18n/locales/nl/portal.jsonghost/i18n/locales/nn/portal.jsonghost/i18n/locales/pa/portal.jsonghost/i18n/locales/pl/portal.jsonghost/i18n/locales/pt-BR/portal.jsonghost/i18n/locales/pt/portal.jsonghost/i18n/locales/ro/portal.jsonghost/i18n/locales/ru/portal.jsonghost/i18n/locales/si/portal.jsonghost/i18n/locales/sk/portal.jsonghost/i18n/locales/sl/portal.jsonghost/i18n/locales/sq/portal.jsonghost/i18n/locales/sr-Cyrl/portal.jsonghost/i18n/locales/sr/portal.jsonghost/i18n/locales/sv/portal.jsonghost/i18n/locales/sw/portal.jsonghost/i18n/locales/ta/portal.jsonghost/i18n/locales/th/portal.jsonghost/i18n/locales/tr/portal.jsonghost/i18n/locales/uk/portal.jsonghost/i18n/locales/ur/portal.jsonghost/i18n/locales/uz/portal.jsonghost/i18n/locales/vi/portal.jsonghost/i18n/locales/zh-Hant/portal.jsonghost/i18n/locales/zh/portal.json
ref #26866 Bumped @tryghost/portal version, aligned share action order with spec, and regenerated portal locale keys required by i18n checks.
There was a problem hiding this comment.
Actionable comments posted: 15
♻️ Duplicate comments (2)
ghost/i18n/locales/hu/portal.json (1)
59-60:⚠️ Potential issue | 🟡 MinorFill the Hungarian action labels for the share UI.
Line 59, Line 60, Line 137, and Line 178 are empty for user-facing actions, so users will see fallback English in a Hungarian locale.
Suggested patch
- "Copied": "", - "Copy link": "", + "Copied": "Másolva", + "Copy link": "Link másolása", ... - "More options": "", + "More options": "További lehetőségek", ... - "Share": "", + "Share": "Megosztás",Also applies to: 137-137, 178-178
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ghost/i18n/locales/hu/portal.json` around lines 59 - 60, The Hungarian locale file is missing translations for several user-facing action labels; update the portal.json entries for the keys "Copied" and "Copy link" (and the other empty action-label keys noted at the same file positions) by providing appropriate Hungarian strings (e.g., "Másolva" for "Copied", "Link másolása" for "Copy link") so users see localized UI text instead of falling back to English; edit the existing keys in portal.json and ensure the values are properly quoted JSON strings.ghost/i18n/locales/nn/portal.json (1)
59-60:⚠️ Potential issue | 🟡 MinorProvide Nynorsk values for share action labels.
Line 59, Line 60, Line 137, and Line 178 are still empty. These are user-visible actions and should not rely on fallback/source text in the
nnlocale.Also applies to: 137-137, 178-178
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ghost/i18n/locales/nn/portal.json` around lines 59 - 60, The nn locale file has empty values for the share action keys—fill in Nynorsk translations for the JSON keys "Copied" and "Copy link" (and the other two empty keys shown at lines 137 and 178) so these user-visible actions do not fall back to the source locale; update the corresponding string values in ghost/i18n/locales/nn/portal.json with accurate Nynorsk phrases while keeping the JSON keys unchanged.
🧹 Nitpick comments (4)
ghost/i18n/locales/el/portal.json (1)
33-33: Fill the new share labels in Greek to avoid English fallback UIBecause these values are empty, users in
ellocale will see source keys (English) for the Share modal labels (e.g., “Copy link”, “Share”), creating mixed-language UX.Proposed localization patch
- "Bluesky": "", + "Bluesky": "Bluesky", ... - "Copied": "", - "Copy link": "", + "Copied": "Αντιγράφηκε", + "Copy link": "Αντιγραφή συνδέσμου", ... - "Facebook": "", + "Facebook": "Facebook", ... - "LinkedIn": "", + "LinkedIn": "LinkedIn", ... - "More options": "", + "More options": "Περισσότερες επιλογές", ... - "Share": "", + "Share": "Κοινοποίηση", ... - "Threads": "", + "Threads": "Threads", ... - "X (Twitter)": "", + "X (Twitter)": "X (Twitter)",Also applies to: 59-60, 89-89, 128-128, 137-137, 178-178, 216-216, 246-246
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ghost/i18n/locales/el/portal.json` at line 33, Several share-label JSON keys (e.g., "Bluesky", and the other empty keys noted at positions 59-60, 89, 128, 137, 178, 216, 246) are empty, causing English fallback; open the portal.json locale object and provide Greek translations for each empty share-related key (for example fill "Bluesky" with the Greek equivalent), ensuring every empty string is replaced with an appropriate Greek label so the Share modal displays fully localized text for the el locale.ghost/i18n/locales/ro/portal.json (1)
33-33: Translate the new Share modal labels in Romanian.These new user-facing strings are currently empty. Adding Romanian values now will avoid mixed-language UX in the new share flow.
🌐 Suggested locale patch
- "Bluesky": "", + "Bluesky": "Bluesky", - "Copied": "", + "Copied": "Copiat", - "Copy link": "", + "Copy link": "Copiază linkul", - "Facebook": "", + "Facebook": "Facebook", - "LinkedIn": "", + "LinkedIn": "LinkedIn", - "More options": "", + "More options": "Mai multe opțiuni", - "Share": "", + "Share": "Distribuie", - "Threads": "", + "Threads": "Threads", - "X (Twitter)": "", + "X (Twitter)": "X (Twitter)",Also applies to: 59-60, 89-89, 128-128, 137-137, 178-178, 216-216, 246-246
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ghost/i18n/locales/ro/portal.json` at line 33, Fill in Romanian translations for the new Share modal keys in portal.json — notably the "Bluesky" key (and the other empty share-modal keys referenced in the review) by replacing the empty strings with proper Romanian text, keeping the JSON keys unchanged; ensure you preserve existing formatting/commas and escape any special characters, validate the JSON after editing, and run the locale lint/CI to confirm there are no missing translations or syntax errors.ghost/i18n/locales/hi/portal.json (1)
33-33: Fill new Hindi share strings to avoid untranslated UI in Share ModalThese new keys are currently empty, so Hindi users will likely see fallback English for core share actions. Please localize them before release.
Proposed patch (please validate with a native Hindi reviewer)
- "Bluesky": "", + "Bluesky": "ब्लूस्काई", ... - "Copied": "", + "Copied": "कॉपी किया गया", - "Copy link": "", + "Copy link": "लिंक कॉपी करें", ... - "Facebook": "", + "Facebook": "फ़ेसबुक", ... - "LinkedIn": "", + "LinkedIn": "लिंक्डइन", ... - "More options": "", + "More options": "और विकल्प", ... - "Share": "", + "Share": "साझा करें", ... - "Threads": "", + "Threads": "थ्रेड्स", ... - "X (Twitter)": "", + "X (Twitter)": "एक्स (ट्विटर)",Also applies to: 59-60, 89-89, 128-128, 137-137, 178-178, 216-216, 246-246
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ghost/i18n/locales/hi/portal.json` at line 33, The listed share-string keys in portal.json (e.g., "Bluesky" and the other empty keys at the mentioned locations) are empty and must be replaced with Hindi translations; open ghost/i18n/locales/hi/portal.json, locate the keys "Bluesky" (and the other empty entries referenced) and replace each "" with an appropriate Hindi translation that matches the share-modal context (short, UI-friendly labels), preserve JSON string escaping and punctuation, run a JSON/l10n validation or build to ensure no syntax errors, and optionally add a comment or note for a native reviewer if unsure about nuance.ghost/i18n/locales/context.json (1)
33-33: Add context descriptions for new share keys.In
context.json, these keys are translator metadata; leaving them blank makes future localization harder and less consistent.💡 Suggested patch
- "Bluesky": "", + "Bluesky": "Social network label in Share modal", @@ - "Copied": "", - "Copy link": "", + "Copied": "Toast text shown after copying the post URL", + "Copy link": "Button label to copy the post URL", @@ - "Facebook": "", + "Facebook": "Social network label in Share modal", @@ - "LinkedIn": "", + "LinkedIn": "Social network label in Share modal", @@ - "More options": "", + "More options": "Button label to open native share dialog", @@ - "Share": "", + "Share": "Share modal title", @@ - "Threads": "", + "Threads": "Social network label in Share modal", @@ - "X (Twitter)": "", + "X (Twitter)": "Social network label in Share modal",Also applies to: 71-72, 110-110, 165-165, 179-179, 247-247, 312-312, 356-356
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@ghost/i18n/locales/context.json` at line 33, The context.json entries for new share keys (e.g., "Bluesky" and the other newly added share keys) are currently empty; add concise translator metadata for each key in context.json describing where and how the string is used (e.g., "Label for sharing via Bluesky social network", whether it's a button/tooltip, and any placeholder/noun/gender/pluralization notes) so translators know context and constraints; update the entries for all new share keys (the same set referenced in the review) with short, clear descriptions that include intended UI location (button/label/menu), any variable placeholders, and preferred tone/register.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/portal/src/components/pages/share-modal.js`:
- Around line 383-385: getShareUrl currently falls back to window.location.href
which may include hash fragments like "#/share" and leak modal routing state;
update getShareUrl so when getCanonicalUrl() is falsy it returns the current
location without any hash fragment (i.e., strip everything from the first '#' in
window.location.href or use the URL API to construct a href that omits
location.hash) before returning the fallback; keep references to getShareUrl and
getCanonicalUrl so the change is applied in that function.
- Around line 324-326: The metadata helpers in ShareModal (e.g.,
getCanonicalUrl) are querying the iframe's empty document; change them to read
from the host page by using window.parent for DOM and location access (e.g.,
replace document.querySelector(...) with
window.parent.document.querySelector(...) and window.location.href fallback with
window.parent.location.href) and update all metadata getter functions and their
usages (the functions around getCanonicalUrl and where their results are used
around lines 446-453) to use window.parent so the canonical URL, title,
description and image come from the parent page.
In `@ghost/i18n/locales/cs/portal.json`:
- Line 33: The JSON entries for new share labels are left empty (e.g., the
"Bluesky" key in portal.json) so Czech users get fallback source strings; open
ghost/i18n/locales/cs/portal.json and fill each empty string value (including
"Bluesky" and the other empty share-label keys reported) with proper Czech
translations, preserving the exact JSON keys and punctuation, escaping any
special characters, and keeping trailing commas/format consistent; after
updating, run the project's i18n/JSON linter or formatter to ensure valid JSON
and that keys remain unchanged.
In `@ghost/i18n/locales/es/portal.json`:
- Around line 59-60: The Spanish locale file is missing translations for share
action keys causing English fallbacks: add appropriate Spanish strings for the
keys "Copied" and "Copy link" (present at the shown lines) and for the other
empty keys at lines 137 and 178 (the other share/action strings in portal.json)
by updating ghost/i18n/locales/es/portal.json so each empty value is replaced
with the correct Spanish translation, preserving the exact JSON key names and
surrounding punctuation.
In `@ghost/i18n/locales/fa/portal.json`:
- Around line 59-60: The Persian locale file is missing translations for UI
action labels; update the JSON entries for the keys "Copied" and "Copy link"
(and the other empty keys referenced at the same locations) with proper Persian
strings so they don't fall back to the default locale; edit the values for
"Copied", "Copy link" (and the empty keys at the other referenced positions) to
use correct Persian translations, preserve surrounding punctuation/quote
structure and valid JSON formatting, and run a quick lint/parse to ensure no
trailing commas or syntax errors.
In `@ghost/i18n/locales/fr/portal.json`:
- Line 33: Populate the missing French translations for the newly added Share
modal labels by replacing the empty string values for the listed keys (e.g.
"Bluesky" and the other empty entries at the same locations) with appropriate
French text; edit the fr/portal.json entries for "Bluesky" and the other empty
share-related keys referenced in the comment so they contain proper French
labels (ensure wording matches existing portal terminology and pluralization/
casing used elsewhere), then run a quick UI check to confirm there are no
fallback English strings in the Share modal.
In `@ghost/i18n/locales/gd/portal.json`:
- Around line 59-60: The Gaelic (gd) locale file has empty UI strings for the
share actions — fill the empty values for the keys "Copied" and "Copy link" (and
the other empty keys at the indicated spots around lines 137 and 178) with
proper Gaelic translations, or if translation is not available, explicitly
annotate those keys as pending (e.g., add a clear "TODO: translate" comment or
placeholder value) so the missing translations are tracked; update the values
for the keys "Copied", "Copy link" and the other empty keys referenced to either
their correct Gaelic strings or a standardized pending-locale marker.
In `@ghost/i18n/locales/is/portal.json`:
- Around line 59-60: Translate the empty user-facing action labels in the
Icelandic locale by providing Icelandic strings for the keys shown (e.g.,
"Copied" and "Copy link") and for the other empty entries referenced at lines
137 and 178; update the JSON values for those keys in portal.json (use
appropriate Icelandic phrases such as “Afritað” for "Copied" and “Afrita tengil”
for "Copy link") so the locale no longer falls back to the default language.
In `@ghost/i18n/locales/it/portal.json`:
- Around line 59-60: Fill the empty Italian translation values for the share
action labels: set "Copied" to "Copiato" and "Copy link" to "Copia link", and
also complete the other two empty entries mentioned (the keys at the empty lines
around 137 and 178) with appropriate Italian strings; ensure you preserve the
JSON key names exactly, use proper capitalization/punctuation consistent with
existing locale entries, escape any special characters, and run the repo's
i18n/json linter to validate the file.
In `@ghost/i18n/locales/ko/portal.json`:
- Line 33: Fill the empty Korean translations for the new Share modal keys
(e.g., the "Bluesky" key and the other empty share-label keys added for the
Share modal) so the UI isn’t mixed-language; locate the empty entries (the
"Bluesky" key and the other newly added share keys indicated in the review) and
replace each empty string with the proper Korean translation, keeping the JSON
key names intact and ensuring punctuation/quoting stays valid.
In `@ghost/i18n/locales/pt-BR/portal.json`:
- Line 33: Several share-modal keys in pt-BR locale (for example the "Bluesky"
key and other empty share strings in portal.json) are left as empty strings
causing fallback to source text; open ghost/i18n/locales/pt-BR/portal.json,
locate the empty share-related keys (e.g., "Bluesky" and the other empty entries
mentioned) and replace each "" value with the correct Brazilian Portuguese
translation that matches the source intent (preserve punctuation/capitalization
and any placeholders), then save and run a quick smoke check of the portal share
modal to confirm translations appear.
In `@ghost/i18n/locales/ru/portal.json`:
- Line 33: Several new RU locale keys in portal.json are left empty (e.g.,
"Bluesky" plus the other new share-related keys added at the same commits),
which causes English fallbacks; populate each newly added string value with the
correct Russian translation for the corresponding share modal labels/buttons
(find and update the empty keys such as "Bluesky" and the other newly added
empty keys in the same JSON object) so the Russian UI shows translated text
instead of English fallbacks.
In `@ghost/i18n/locales/si/portal.json`:
- Line 33: The new Sinhala locale has empty values for share-label keys (e.g.,
"Bluesky", and the generic labels "Copied", "Copy link", "More options",
"Share") so the UI falls back to English; open ghost/i18n/locales/si/portal.json
and provide Sinhala translations for those keys (and the other empty keys
mentioned at positions corresponding to lines 59-60, 89, 128, 137, 178, 216,
246), ensuring brand names like "Bluesky" remain unchanged (passthrough) while
all generic labels receive proper Sinhala text.
In `@ghost/i18n/locales/th/portal.json`:
- Line 33: Several share modal translation keys in
ghost/i18n/locales/th/portal.json (e.g., "Bluesky" plus the other empty keys at
lines mentioned) are empty; provide Thai translations for each of the new
share-related keys so the UI renders Thai text. Open portal.json and replace the
empty string values for the keys "Bluesky" and the other blank share modal keys
(the entries referenced at lines 59-60, 89, 128, 137, 178, 216, 246) with
appropriate Thai translations that match the English source text, keeping the
JSON key names unchanged and preserving punctuation and any interpolation
placeholders.
In `@ghost/i18n/locales/zh-Hant/portal.json`:
- Around line 59-60: The file has empty Traditional Chinese values for the
share-related keys "Copied" and "Copy link" (and two other empty string keys
later in the file at the noted positions); fill them with proper zh-Hant
translations (e.g., "已複製" for "Copied" and "複製連結" for "Copy link") and likewise
provide appropriate Traditional Chinese strings for the other empty keys found
at the two later positions so all portal share/action labels are fully
localized; update the values for the keys "Copied" and "Copy link" (and the
other empty keys at the indicated locations) in
ghost/i18n/locales/zh-Hant/portal.json.
---
Duplicate comments:
In `@ghost/i18n/locales/hu/portal.json`:
- Around line 59-60: The Hungarian locale file is missing translations for
several user-facing action labels; update the portal.json entries for the keys
"Copied" and "Copy link" (and the other empty action-label keys noted at the
same file positions) by providing appropriate Hungarian strings (e.g., "Másolva"
for "Copied", "Link másolása" for "Copy link") so users see localized UI text
instead of falling back to English; edit the existing keys in portal.json and
ensure the values are properly quoted JSON strings.
In `@ghost/i18n/locales/nn/portal.json`:
- Around line 59-60: The nn locale file has empty values for the share action
keys—fill in Nynorsk translations for the JSON keys "Copied" and "Copy link"
(and the other two empty keys shown at lines 137 and 178) so these user-visible
actions do not fall back to the source locale; update the corresponding string
values in ghost/i18n/locales/nn/portal.json with accurate Nynorsk phrases while
keeping the JSON keys unchanged.
---
Nitpick comments:
In `@ghost/i18n/locales/context.json`:
- Line 33: The context.json entries for new share keys (e.g., "Bluesky" and the
other newly added share keys) are currently empty; add concise translator
metadata for each key in context.json describing where and how the string is
used (e.g., "Label for sharing via Bluesky social network", whether it's a
button/tooltip, and any placeholder/noun/gender/pluralization notes) so
translators know context and constraints; update the entries for all new share
keys (the same set referenced in the review) with short, clear descriptions that
include intended UI location (button/label/menu), any variable placeholders, and
preferred tone/register.
In `@ghost/i18n/locales/el/portal.json`:
- Line 33: Several share-label JSON keys (e.g., "Bluesky", and the other empty
keys noted at positions 59-60, 89, 128, 137, 178, 216, 246) are empty, causing
English fallback; open the portal.json locale object and provide Greek
translations for each empty share-related key (for example fill "Bluesky" with
the Greek equivalent), ensuring every empty string is replaced with an
appropriate Greek label so the Share modal displays fully localized text for the
el locale.
In `@ghost/i18n/locales/hi/portal.json`:
- Line 33: The listed share-string keys in portal.json (e.g., "Bluesky" and the
other empty keys at the mentioned locations) are empty and must be replaced with
Hindi translations; open ghost/i18n/locales/hi/portal.json, locate the keys
"Bluesky" (and the other empty entries referenced) and replace each "" with an
appropriate Hindi translation that matches the share-modal context (short,
UI-friendly labels), preserve JSON string escaping and punctuation, run a
JSON/l10n validation or build to ensure no syntax errors, and optionally add a
comment or note for a native reviewer if unsure about nuance.
In `@ghost/i18n/locales/ro/portal.json`:
- Line 33: Fill in Romanian translations for the new Share modal keys in
portal.json — notably the "Bluesky" key (and the other empty share-modal keys
referenced in the review) by replacing the empty strings with proper Romanian
text, keeping the JSON keys unchanged; ensure you preserve existing
formatting/commas and escape any special characters, validate the JSON after
editing, and run the locale lint/CI to confirm there are no missing translations
or syntax errors.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 349e32cb-cf08-4616-bb37-82b9c84ef450
📒 Files selected for processing (64)
apps/portal/package.jsonapps/portal/src/components/pages/share-modal.jsghost/i18n/locales/af/portal.jsonghost/i18n/locales/ar/portal.jsonghost/i18n/locales/bg/portal.jsonghost/i18n/locales/bn/portal.jsonghost/i18n/locales/bs/portal.jsonghost/i18n/locales/ca/portal.jsonghost/i18n/locales/context.jsonghost/i18n/locales/cs/portal.jsonghost/i18n/locales/da/portal.jsonghost/i18n/locales/de-CH/portal.jsonghost/i18n/locales/de/portal.jsonghost/i18n/locales/el/portal.jsonghost/i18n/locales/eo/portal.jsonghost/i18n/locales/es/portal.jsonghost/i18n/locales/et/portal.jsonghost/i18n/locales/eu/portal.jsonghost/i18n/locales/fa/portal.jsonghost/i18n/locales/fi/portal.jsonghost/i18n/locales/fr/portal.jsonghost/i18n/locales/gd/portal.jsonghost/i18n/locales/he/portal.jsonghost/i18n/locales/hi/portal.jsonghost/i18n/locales/hr/portal.jsonghost/i18n/locales/hu/portal.jsonghost/i18n/locales/id/portal.jsonghost/i18n/locales/is/portal.jsonghost/i18n/locales/it/portal.jsonghost/i18n/locales/ja/portal.jsonghost/i18n/locales/ko/portal.jsonghost/i18n/locales/kz/portal.jsonghost/i18n/locales/lt/portal.jsonghost/i18n/locales/lv/portal.jsonghost/i18n/locales/mk/portal.jsonghost/i18n/locales/mn/portal.jsonghost/i18n/locales/ms/portal.jsonghost/i18n/locales/nb/portal.jsonghost/i18n/locales/ne/portal.jsonghost/i18n/locales/nl/portal.jsonghost/i18n/locales/nn/portal.jsonghost/i18n/locales/pa/portal.jsonghost/i18n/locales/pl/portal.jsonghost/i18n/locales/pt-BR/portal.jsonghost/i18n/locales/pt/portal.jsonghost/i18n/locales/ro/portal.jsonghost/i18n/locales/ru/portal.jsonghost/i18n/locales/si/portal.jsonghost/i18n/locales/sk/portal.jsonghost/i18n/locales/sl/portal.jsonghost/i18n/locales/sq/portal.jsonghost/i18n/locales/sr-Cyrl/portal.jsonghost/i18n/locales/sr/portal.jsonghost/i18n/locales/sv/portal.jsonghost/i18n/locales/sw/portal.jsonghost/i18n/locales/ta/portal.jsonghost/i18n/locales/th/portal.jsonghost/i18n/locales/tr/portal.jsonghost/i18n/locales/uk/portal.jsonghost/i18n/locales/ur/portal.jsonghost/i18n/locales/uz/portal.jsonghost/i18n/locales/vi/portal.jsonghost/i18n/locales/zh-Hant/portal.jsonghost/i18n/locales/zh/portal.json
✅ Files skipped from review due to trivial changes (1)
- apps/portal/package.json
🚧 Files skipped from review as they are similar to previous changes (24)
- ghost/i18n/locales/sr/portal.json
- ghost/i18n/locales/pl/portal.json
- ghost/i18n/locales/ms/portal.json
- ghost/i18n/locales/fi/portal.json
- ghost/i18n/locales/vi/portal.json
- ghost/i18n/locales/eo/portal.json
- ghost/i18n/locales/tr/portal.json
- ghost/i18n/locales/kz/portal.json
- ghost/i18n/locales/zh/portal.json
- ghost/i18n/locales/id/portal.json
- ghost/i18n/locales/mn/portal.json
- ghost/i18n/locales/ca/portal.json
- ghost/i18n/locales/nb/portal.json
- ghost/i18n/locales/mk/portal.json
- ghost/i18n/locales/ja/portal.json
- ghost/i18n/locales/ne/portal.json
- ghost/i18n/locales/sv/portal.json
- ghost/i18n/locales/uk/portal.json
- ghost/i18n/locales/bg/portal.json
- ghost/i18n/locales/pt/portal.json
- ghost/i18n/locales/sr-Cyrl/portal.json
- ghost/i18n/locales/lv/portal.json
- ghost/i18n/locales/nl/portal.json
- ghost/i18n/locales/hr/portal.json
ref #26866 Portal runs in an iframe so share metadata must be read from the host page context.
There was a problem hiding this comment.
♻️ Duplicate comments (1)
apps/portal/src/components/pages/share-modal.js (1)
401-403:⚠️ Potential issue | 🟡 MinorStrip hash from fallback share URL to avoid sharing modal route fragments.
Line 402 still falls back to
location.href, which may include#/portal/sharewhen canonical metadata is missing. That leaks UI routing state into shared links.💡 Proposed fix
const getShareUrl = () => { - return getCanonicalUrl() || getHostWindow().location.href; + const canonical = getCanonicalUrl(); + if (canonical) { + return canonical; + } + + const {origin, pathname, search} = getHostWindow().location; + return `${origin}${pathname}${search}`; };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/portal/src/components/pages/share-modal.js` around lines 401 - 403, getShareUrl currently returns getCanonicalUrl() or getHostWindow().location.href which can include hash fragments like "#/portal/share"; update getShareUrl so that when falling back to getHostWindow().location.href it strips the hash fragment (i.e. use location.href.split('#')[0] or construct from getHostWindow().location.origin + pathname + search) and return that cleaned URL; keep getCanonicalUrl() path unchanged and only modify the fallback branch in the getShareUrl function.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@apps/portal/src/components/pages/share-modal.js`:
- Around line 401-403: getShareUrl currently returns getCanonicalUrl() or
getHostWindow().location.href which can include hash fragments like
"#/portal/share"; update getShareUrl so that when falling back to
getHostWindow().location.href it strips the hash fragment (i.e. use
location.href.split('#')[0] or construct from getHostWindow().location.origin +
pathname + search) and return that cleaned URL; keep getCanonicalUrl() path
unchanged and only modify the fallback branch in the getShareUrl function.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: b325200e-91bb-4588-9b6d-e421d22f4789
📒 Files selected for processing (1)
apps/portal/src/components/pages/share-modal.js
ref #26866 LinkedIn is now a primary action and uses the shareArticle URL to improve preview unfurl reliability.
There was a problem hiding this comment.
♻️ Duplicate comments (1)
apps/portal/src/components/pages/share-modal.js (1)
401-403:⚠️ Potential issue | 🟡 MinorStrip hash fragments from fallback share URL.
When canonical metadata is absent, the fallback can include route fragments (for example
#/portal/share) in shared links. Build the fallback fromorigin + pathname + searchinstead of fullhref. This is the root cause; related unit assertions should be updated accordingly.💡 Proposed fix
const getShareUrl = () => { - return getCanonicalUrl() || getHostWindow().location.href; + const canonical = getCanonicalUrl(); + if (canonical) { + return canonical; + } + + const {origin, pathname, search} = getHostWindow().location; + return `${origin}${pathname}${search}`; };🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/portal/src/components/pages/share-modal.js` around lines 401 - 403, getShareUrl currently falls back to getHostWindow().location.href which can include hash fragments; change the fallback to build the URL from getHostWindow().location.origin + getHostWindow().location.pathname + getHostWindow().location.search to strip any hash. Update the getShareUrl implementation to use getHostWindow().location (origin/pathname/search) when getCanonicalUrl() is falsy, and adjust related unit tests that asserted the old href behavior to expect the hash-free URL instead.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@apps/portal/src/components/pages/share-modal.js`:
- Around line 401-403: getShareUrl currently falls back to
getHostWindow().location.href which can include hash fragments; change the
fallback to build the URL from getHostWindow().location.origin +
getHostWindow().location.pathname + getHostWindow().location.search to strip any
hash. Update the getShareUrl implementation to use getHostWindow().location
(origin/pathname/search) when getCanonicalUrl() is falsy, and adjust related
unit tests that asserted the old href behavior to expect the hash-free URL
instead.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 89f623d7-1e85-4028-8619-73676f18bb88
📒 Files selected for processing (2)
apps/portal/src/components/pages/share-modal.jsapps/portal/test/unit/components/pages/share-modal.test.js
ref #26866 This switches share routing to #/share and keeps the old hash path disabled for the requested breaking change.
658bbdc to
9c8ebe8
Compare
ref #26866 Bumped @tryghost/portal version, aligned share action order with spec, and regenerated portal locale keys required by i18n checks.
ref #26866 Portal runs in an iframe so share metadata must be read from the host page context.
ref #26866 LinkedIn is now a primary action and uses the shareArticle URL to improve preview unfurl reliability.
ref #26866 This switches share routing to #/share and keeps the old hash path disabled for the requested breaking change.
a7b24b9 to
24e684e
Compare
ref #26866 Bumped @tryghost/portal version, aligned share action order with spec, and regenerated portal locale keys required by i18n checks.
ref #26866 Portal runs in an iframe so share metadata must be read from the host page context.
ref #26866 LinkedIn is now a primary action and uses the shareArticle URL to improve preview unfurl reliability.
ref #26866 This switches share routing to #/share and keeps the old hash path disabled for the requested breaking change.
8803292 to
936c768
Compare
ref #26866 Bumped @tryghost/portal version, aligned share action order with spec, and regenerated portal locale keys required by i18n checks.
ref #26866 Portal runs in an iframe so share metadata must be read from the host page context.
ref #26866 LinkedIn is now a primary action and uses the shareArticle URL to improve preview unfurl reliability.
ref #26866 This switches share routing to #/share and keeps the old hash path disabled for the requested breaking change.
32f34ea to
d5ae90f
Compare
cathysarisky
left a comment
There was a problem hiding this comment.
Friendly reminder to please update context.json when you add new strings. Thanks!!
ref #26866 Bumped @tryghost/portal version, aligned share action order with spec, and regenerated portal locale keys required by i18n checks.
ref #26866 Portal runs in an iframe so share metadata must be read from the host page context.
ref #26866 LinkedIn is now a primary action and uses the shareArticle URL to improve preview unfurl reliability.
ref https://linear.app/ghost/issue/FEA-480 Simplified share metadata to DOM-only and refined modal actions/footer UX
ref https://github.com/TryGhost/Team/issues/FEA-480 Improved share UX with overflow menu, upward animation, excerpt clamp, and corrected mailto encoding.
ref #26866 Bumped @tryghost/portal version, aligned share action order with spec, and regenerated portal locale keys required by i18n checks.
ref #26866 Portal runs in an iframe so share metadata must be read from the host page context.
ref #26866 LinkedIn is now a primary action and uses the shareArticle URL to improve preview unfurl reliability.
ref #26866 This switches share routing to #/share and keeps the old hash path disabled for the requested breaking change.
This reverts commit 9c8ebe8.
This reverts commit 2a7f8fe.
Refactors a bit of the share modal setup: - moves into 3 separate files for component, styles, hook - gathers all the data in one function and simplifies the logic a bit
Changelog for v2.67.1 -> 2.68.0: - Updated i18n translations
f9d7e57 to
e5e8375
Compare
|



ref https://linear.app/ghost/issue/FEA-480/native-share-buttons-with-link-based-referral-param-for-attribution
This PR adds a new small modal component to Portal that allows a reader to more easily share a post. It fires by adding #/share on any post link. The modal lets visitors copy the link to the post and share to top social platforms.