Skip to content

🌐 Merged fragment translation keys in Portal notifications#27175

Closed
rob-ghost wants to merge 3 commits intomainfrom
fix/portal-fragment-translation-keys
Closed

🌐 Merged fragment translation keys in Portal notifications#27175
rob-ghost wants to merge 3 commits intomainfrom
fix/portal-fragment-translation-keys

Conversation

@rob-ghost
Copy link
Copy Markdown
Contributor

Summary

  • Merged split-sentence translation keys in Portal's notification.js into complete sentences using @doist/react-interpolate
  • Removed fragment keys ("Click here to retry", "You've successfully subscribed to", "Signup error: Invalid link", "Could not sign in. Login link expired.") that prevented translators from reordering words for different languages
  • Added combined interpolated keys with inline <a> and <strong> tags so translators have full sentence context
  • Updated all 62 locale portal.json files and context.json with descriptions for the new keys

Keys changed

Old (removed) New (added)
"Could not sign in. Login link expired." + "Click here to retry" "Could not sign in. Login link expired. <a>Click here to retry</a>"
"You've successfully subscribed to" + site title "You've successfully subscribed to <strong>{siteTitle}</strong>"
"Signup error: Invalid link" + "Click here to retry" "Signup error: Invalid link. <a>Click here to retry</a>"

Why

Splitting sentences across multiple t() calls prevents translators from reordering words to match the grammar of their target language. Using @doist/react-interpolate (already a Portal dependency) allows embedding React elements within a single translatable string.

Test plan

  • Start Portal and trigger sign-in error notification (use expired magic link) — verify retry link renders and works
  • Trigger successful signup — verify site title appears in bold in the notification
  • Trigger signup error (use expired signup link) — verify retry link renders and works
  • Verify i18n lint passes: yarn workspace @tryghost/i18n lint:translations

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 6, 2026

Note

Reviews paused

It 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 reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Notification rendering in the portal was changed to use @doist/react-interpolate (imported as Interpolate) so auth-related messages now interpolate HTML/links from single translation strings rather than composing separate JSX <br />, <a> or <strong> elements. The standalone translation key "Click here to retry" was removed and sign-in/sign-up error keys were replaced with variants that inline <br /><a>Click here to retry</a>. The subscription success key was replaced with a variant that includes <br /><strong>{siteTitle}</strong>. The portal package version was bumped from 2.67.9 to 2.67.10.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: merging split translation keys in Portal notifications using the @doist/react-interpolate library.
Description check ✅ Passed The description is well-related to the changeset, providing clear context about why the changes were made, what specific keys were modified, and comprehensive testing instructions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/portal-fragment-translation-keys

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

🟡 Minor comments (22)
ghost/i18n/locales/ur/portal.json-58-58 (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Backfill the new composite notification keys for Urdu.

Line 58, Line 174, and Line 244 are empty for newly added notification keys, which leaves these strings untranslated for this locale. Please add Urdu values while preserving <a> and <strong>{siteTitle}</strong>.

Also applies to: 174-174, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/ur/portal.json` at line 58, Add Urdu translations for the
three empty composite notification keys by filling the values for the exact JSON
keys "Could not sign in. Login link expired. <a>Click here to retry</a>",
"Invitation invalid. <a>Click here to request a new invitation</a>", and "This
content is for <strong>{siteTitle}</strong> members only. <a>Sign in</a>" in the
same locale file; ensure you preserve the embedded HTML tags (<a> and
<strong>{siteTitle}</strong>) exactly as they appear and provide fluent Urdu
text for each string.
ghost/i18n/locales/lv/portal.json-58-58 (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Backfill the new composite notification keys for Latvian.

Line 58, Line 174, and Line 244 are empty for newly added notification strings, leaving these messages untranslated in this locale. Please populate localized values while preserving <a> and <strong>{siteTitle}</strong>.

Also applies to: 174-174, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/lv/portal.json` at line 58, Populate the three empty
Latvian translations for the notification keys by replacing the empty strings
with proper Latvian text while preserving the embedded HTML tags and
placeholders exactly as in the source keys: "Could not sign in. Login link
expired. <a>Click here to retry</a>", "You need to <a>sign in</a> to access
<strong>{siteTitle}</strong>.", and "You need to <a>sign in</a> to access this
content on <strong>{siteTitle}</strong>."; ensure the <a>…</a> and
<strong>{siteTitle}</strong> remain unchanged and provide accurate, natural
Latvian phrasing for each message.
ghost/i18n/locales/nb/portal.json-58-58 (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Backfill the new composite notification keys for Norwegian.

Line 58, Line 174, and Line 244 are new user-facing notification keys but currently have empty values, so these messages are not localized in this locale yet. Please populate these strings (keeping <a>/<strong> placeholders intact) to avoid translation regressions.

Also applies to: 174-174, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/nb/portal.json` at line 58, The three empty notification
keys "Could not sign in. Login link expired. <a>Click here to retry</a>", plus
the other composite keys containing "<a>" and "<strong>" placeholders, need
Norwegian translations inserted (replace the empty string values) while
preserving the exact placeholder tags (<a> and <strong>) and punctuation; update
the values to appropriate Norwegian text for each English key string so
user-facing notifications are localized and placeholders remain intact.
ghost/i18n/locales/ko/portal.json-58-58 (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Backfill the new composite notification keys for Korean.

Line 58, Line 174, and Line 244 are currently empty, so these notification messages are not localized in this file. Please provide Korean translations and keep the inline placeholders/tags intact.

Also applies to: 174-174, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/ko/portal.json` at line 58, Provide Korean translations
for the three empty composite notification keys by replacing the empty string
values with proper Korean text while preserving the inline HTML tag placeholders
exactly as in the keys; specifically update the keys "Could not sign in. Login
link expired. <a>Click here to retry</a>", "Email address already verified.
<a>Sign in</a>", and "We couldn't find an account with that email address.
<a>Create one now</a>" with appropriate Korean translations that keep the
<a>...</a> tags intact (e.g., "로그인할 수 없습니다. 로그인 링크의 유효기간이 만료되었습니다. <a>다시 시도하려면
클릭하세요</a>"), ensuring the translations are concise and maintain the original tag
placement.
ghost/i18n/locales/es/portal.json-58-58 (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Backfill the new composite notification keys for Spanish.

Line 58, Line 174, and Line 244 are empty for the new notification keys, so these messages are currently untranslated in es. Please add Spanish values and keep the embedded <a> / <strong>{siteTitle}</strong> placeholders unchanged.

Also applies to: 174-174, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/es/portal.json` at line 58, Add Spanish translations for
the three empty composite notification keys: "Could not sign in. Login link
expired. <a>Click here to retry</a>", "Unable to send invitation to
<strong>{siteTitle}</strong>. Contact the site owner to invite them manually.",
and "Unable to send recovery email. <a>Click here to retry</a>" in
ghost/i18n/locales/es/portal.json; keep the embedded HTML tags and placeholder
<a> and <strong>{siteTitle}</strong> exactly as-is and provide natural Spanish
text for each message.
ghost/i18n/locales/ca/portal.json-58-58 (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Backfill the new composite notification keys for Catalan.

Line 58, Line 174, and Line 244 introduce user-visible keys with empty values. Please add Catalan translations for these entries (retaining the embedded placeholders) to keep notification localization complete.

Also applies to: 174-174, 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` at line 58, Add Catalan translations for
the three empty notification keys shown (preserve the embedded <a>...</a>
placeholder exactly): "Could not sign in. Login link expired. <a>Click here to
retry</a>", plus the other two composite notification keys referenced in the
comment; replace the empty string values with the proper Catalan text while
keeping the HTML anchor tags and original punctuation intact so placeholders
still work in code.
ghost/i18n/locales/kz/portal.json-58-58 (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Backfill the new composite notification keys for Kazakh.

Line 58, Line 174, and Line 244 are empty for newly introduced notification keys, leaving these messages untranslated in this locale. Please add localized values while preserving the <a> and <strong>{siteTitle}</strong> placeholders.

Also applies to: 174-174, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/kz/portal.json` at line 58, Add Kazakh translations for
the untranslated composite notification keys in portal.json: provide localized
values for the key "Could not sign in. Login link expired. <a>Click here to
retry</a>" and the other two new composite keys (the ones containing the <a>
anchor and the one with <strong>{siteTitle}</strong>) ensuring you preserve the
exact HTML placeholders "<a>" (and its closing tag) and
"<strong>{siteTitle}</strong>" unchanged; replace the empty string values with
the proper Kazakh text for each key while keeping the surrounding punctuation
and tags intact.
ghost/i18n/locales/sl/portal.json-58-58 (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Backfill the new composite notification keys for Slovenian.

Line 58, Line 174, and Line 244 are currently empty, so these new notification messages are not localized in this locale file. Please populate the values and keep the <a>/<strong> structure unchanged.

Also applies to: 174-174, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/sl/portal.json` at line 58, Populate the empty Slovenian
translations for the three new composite notification keys: "Could not sign in.
Login link expired. <a>Click here to retry</a>" and the two other composite
notification keys currently empty in this locale file, making sure to keep the
embedded HTML tags (<a> and <strong>) exactly as-is and provide proper Slovenian
text that preserves the link/text structure; update the corresponding values for
those keys with accurate Slovenian phrases while not altering the key strings or
tag placement.
ghost/i18n/locales/cs/portal.json-58-58 (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Czech locale now lacks translations for the migrated messages.

Line 58, Line 174, and Line 244 are empty, which will likely show English fallback text in these Portal notifications.

Also applies to: 174-174, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/cs/portal.json` at line 58, The Czech locale file is
missing translations for migrated Portal notification messages; add Czech
translations for the migrated keys (including the message key "Could not sign
in. Login link expired. <a>Click here to retry</a>") and the other two empty
migrated Portal notification keys so they no longer fall back to English; update
the values in the cs portal.json to the proper Czech strings preserving the
exact keys and HTML anchor markup, ensuring JSON validity and consistent
phrasing with other Portal translations.
ghost/i18n/locales/sk/portal.json-58-58 (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Localization regression in new notification keys.

Line 58, Line 174, and Line 244 are empty for newly introduced keys, so Slovak users will likely see English fallback text in these flows.

Also applies to: 174-174, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/sk/portal.json` at line 58, The Slovak locale is missing
translations for three newly introduced portal notification keys, so update the
sk translation file by supplying Slovak strings for the keys "Could not sign in.
Login link expired. <a>Click here to retry</a>", "Your subscription has been
canceled. <a>Manage your subscription</a>", and "Payment method declined.
<a>Update payment details</a>" (use the exact keys to locate them in the file,
preserving the HTML anchor tags) ensuring each empty value is replaced with the
correct Slovak translation while keeping the surrounding JSON structure and
escaping unchanged.
ghost/i18n/locales/hr/portal.json-58-58 (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Croatian locale loses translated copy for these updated notifications.

Line 58, Line 174, and Line 244 are empty after the key migration, so users will likely see English fallback text for these cases.

Also applies to: 174-174, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/hr/portal.json` at line 58, The Croatian locale is missing
translations for three migrated notification keys; add Croatian translations for
the exact message keys "Could not sign in. Login link expired. <a>Click here to
retry</a>", and the other two migrated notification keys present in the same
file (the entries at the other empty values) by replacing the empty string
values with appropriate Croatian text so the keys map to localized strings;
update the values for these specific keys in the hr/portal.json locale (ensure
you preserve the HTML anchor tag exactly as in the key) so users will see the
localized messages instead of English fallbacks.
ghost/i18n/locales/gd/portal.json-58-58 (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Gaelic translations are missing for the new combined keys.

Line 58, Line 174, and Line 244 are empty, so these messages will likely render in English fallback instead of Gaelic.

Also applies to: 174-174, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/gd/portal.json` at line 58, The Gaelic translations for
the new combined keys are missing in the locale file: add Gaelic values for the
keys "Could not sign in. Login link expired. <a>Click here to retry</a>" (and
the other two empty entries on the same file) so they no longer fall back to
English; open the gd/portal.json and provide proper Gaelic translations for
those exact message keys (preserve the HTML anchor tag "<a>...</a>" in the
translated strings) replacing the empty string values with the translated text.
ghost/i18n/locales/pt-BR/portal.json-58-58 (1)

58-58: ⚠️ Potential issue | 🟡 Minor

pt-BR translation coverage regresses for the new keys.

Line 58, Line 174, and Line 244 are empty, so these newly merged notification messages will fall back to English for pt-BR users.

Also applies to: 174-174, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/pt-BR/portal.json` at line 58, The pt-BR locale file has
empty values for new notification keys (e.g., the key "Could not sign in. Login
link expired. <a>Click here to retry</a>") causing fallback to English; update
ghost/i18n/locales/pt-BR/portal.json by supplying appropriate Brazilian
Portuguese translations for that exact string and the other two empty keys
referenced in the review, preserving the embedded HTML anchor (<a>...</a>) and
JSON quoting/escaping rules so the keys remain identical and valid JSON.
ghost/i18n/locales/nn/portal.json-58-58 (1)

58-58: ⚠️ Potential issue | 🟡 Minor

New Nynorsk keys are untranslated.

Line 58, Line 174, and Line 244 are empty after replacing existing message keys, which will likely surface English fallback strings in these notification states.

Also applies to: 174-174, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/nn/portal.json` at line 58, The three empty Nynorsk
translation values in the nn portal JSON must be populated: replace the empty
string values for the message keys "Could not sign in. Login link expired.
<a>Click here to retry</a>", and the other two untranslated keys mentioned (line
174 and 244) with appropriate Nynorsk translations, preserving the exact key
text (including HTML tags like <a>) and valid JSON quoting/escaping so the
portal falls back correctly; update nn/portal.json by inserting the translated
strings in place of "" for those keys.
ghost/i18n/locales/sr/portal.json-58-58 (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Serbian translations are missing for the migrated notification keys.

Line 58, Line 174, and Line 244 are empty, which likely causes English fallback rendering in those notification flows.

Also applies to: 174-174, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/sr/portal.json` at line 58, The Serbian locale file has
empty translations for portal notification keys causing English fallbacks; fill
in Serbian translations for the empty keys in sr/portal.json — at minimum
replace the empty value for "Could not sign in. Login link expired. <a>Click
here to retry</a>" and the two other empty notification keys in the same file
with appropriate Serbian text, preserving the exact key strings (including HTML
tags like <a>) and JSON syntax so lookup (portal notification rendering) uses
the Serbian strings instead of falling back to English.
ghost/i18n/locales/ta/portal.json-58-58 (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Please avoid empty Tamil values for these migrated notification keys.

Line 58, Line 174, and Line 244 are currently blank, so these messages will not stay localized in Tamil. Please carry over translated wording into the new combined key structure.

Also applies to: 174-174, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/ta/portal.json` at line 58, The three migrated
notification keys in ghost/i18n/locales/ta/portal.json currently have empty
Tamil values; update the JSON by providing proper Tamil translations for the
exact keys "Could not sign in. Login link expired. <a>Click here to retry</a>",
plus the other two migrated notification keys mentioned in the review (ensure
you locate the other empty entries in the same file) so the messages remain
localized; edit the value strings for those keys to contain the correct Tamil
wording while preserving the original HTML anchor markup and JSON quoting.
ghost/i18n/locales/mn/portal.json-58-58 (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Preserve Mongolian localization for migrated notification strings.

Line 58, Line 174, and Line 244 are empty after the key update. This will downgrade these notifications to fallback English. Please populate Mongolian translations for the new merged key format.

Also applies to: 174-174, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/mn/portal.json` at line 58, Fill in Mongolian translations
for the empty notification keys introduced by the merge: replace the empty value
for "Could not sign in. Login link expired. <a>Click here to retry</a>" with the
appropriate Mongolian string (preserving the <a>...</a> anchor markup), and
likewise populate the other two newly empty merged notification keys referenced
in the comment with their Mongolian translations; ensure you keep the exact key
strings unchanged and that the JSON value is properly escaped and valid.
ghost/i18n/locales/hu/portal.json-58-58 (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Please seed Hungarian values for the new composite notification keys.

Line 58, Line 174, and Line 244 are now empty, which regresses these messages to fallback English in Hungarian Portal flows. Please carry forward existing translated intent into the new <a>...</a> / <strong>{siteTitle}</strong> key format.

Also applies to: 174-174, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/hu/portal.json` at line 58, Three composite notification
keys in the Hungarian locale are empty; replace the empty values with proper
Hungarian translations that preserve the existing translated intent while
incorporating the HTML placeholders exactly as in the keys (e.g., for the key
"Could not sign in. Login link expired. <a>Click here to retry</a>" provide a
Hungarian sentence that includes the <a>...</a> anchor around the retry text).
Do the same for the other two composite keys that include <a>...</a> and the one
including <strong>{siteTitle}</strong>, ensuring you keep the HTML tags and the
{siteTitle} placeholder verbatim and translate the surrounding text into natural
Hungarian.
ghost/i18n/locales/id/portal.json-58-58 (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Avoid localization regression on the new merged notification keys.

Line 58, Line 174, and Line 244 introduce the new composite keys with empty values. That will surface fallback English for Indonesian users in these auth/signup notifications. Please prefill these entries (using prior translated fragments) so this migration doesn’t drop existing localization quality.

Also applies to: 174-174, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/id/portal.json` at line 58, The three new composite
localization keys ("Could not sign in. Login link expired. <a>Click here to
retry</a>", and the two other merged notification keys introduced around the
same changes) currently have empty strings; populate each value with the
corresponding existing Indonesian translations by reusing the prior translated
fragments for "Could not sign in", "Login link expired" and "Click here to
retry" (and analogous fragments for the other two composite keys), ensuring the
HTML anchor markup (<a>...</a>) is preserved in the translated string, keep JSON
quoting/escaping correct, and run a quick JSON lint to confirm validity so the
merge does not fall back to English.
ghost/i18n/locales/uz/portal.json-58-58 (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Backfill Uzbek translations for newly merged auth keys.

Line 58, Line 174, and Line 244 are empty after key migration. That will show English fallback text for these user-visible notifications. Please pre-populate Uzbek values for the new combined strings to preserve current localization quality.

Also applies to: 174-174, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/uz/portal.json` at line 58, Populate the Uzbek
translations for the three untranslated auth notification keys by replacing the
empty values for "Could not sign in. Login link expired. <a>Click here to
retry</a>", the other two migrated keys at the same positions (the combined auth
strings present in portal.json), with appropriate Uzbek text; update the JSON
entries so each key maps to a proper Uzbek sentence preserving the HTML anchor
tag (e.g. translate the message and keep "<a>Click here to retry</a>" translated
but with the same anchor tags), ensuring valid JSON string quoting and no
trailing commas.
ghost/i18n/locales/bs/portal.json-58-58 (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Backfill Bosnian translations for new merged auth/subscription strings.

Line 58, Line 174, and Line 244 are empty, which will surface fallback English in Bosnian UI for these notifications. Please prefill these keys to maintain current localized UX.

Also applies to: 174-174, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/bs/portal.json` at line 58, Three portal translation
entries in ghost/i18n/locales/bs/portal.json are empty and fall back to English;
fill the Bosnian translations for the affected keys (e.g. "Could not sign in.
Login link expired. <a>Click here to retry</a>" and the other two keys at the
same file for lines 174 and 244) by replacing the empty strings with proper
Bosnian text, preserving any HTML tags like <a> so the link markup remains
intact, and save the file to restore localized UX for the bs locale.
ghost/i18n/locales/fi/portal.json-58-58 (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Don’t leave the new Finnish notification keys empty.

Line 58, Line 174, and Line 244 currently resolve to empty translations, causing fallback English in Finnish flows. Please migrate existing Finnish phrasing into these new combined keys.

Also applies to: 174-174, 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/fi/portal.json` at line 58, The new Finnish notification
key "Could not sign in. Login link expired. <a>Click here to retry</a>" is empty
(and the same issue exists for the other two new keys in this file); fill each
empty string with the appropriate Finnish translation copied/migrated from the
existing Finnish phrasing used elsewhere in the project, preserving the HTML
anchor tag (<a>...</a>) exactly and any placeholders or punctuation so the UI
and links continue to work; update the three empty values so they no longer
fallback to English.
🧹 Nitpick comments (1)
apps/portal/src/components/notification.js (1)

52-72: Consider extracting duplicate success message rendering.

The signup and signup-paid success branches (lines 52-62 and 63-73) render identical JSX. The same duplication exists for the error branches (lines 86-96 and 97-107).

♻️ Optional: Extract shared rendering logic
+const SubscribeSuccessMessage = ({siteTitle}) => (
+    <p>
+        <Interpolate
+            mapping={{
+                strong: <strong />
+            }}
+            string={t('You\'ve successfully subscribed to <strong>{siteTitle}</strong>', {siteTitle})}
+        />
+    </p>
+);
+
+const SignupErrorMessage = ({portalLink}) => (
+    <p>
+        <Interpolate
+            mapping={{
+                a: <a href={portalLink} target="_parent" />
+            }}
+            string={t('Signup error: Invalid link. <a>Click here to retry</a>')}
+        />
+    </p>
+);

// Then use in NotificationText:
 } else if (type === 'signup' && status === 'success') {
-    return (
-        <p>
-            <Interpolate ... />
-        </p>
-    );
+    return <SubscribeSuccessMessage siteTitle={context.site.title} />;
 } else if (type === 'signup-paid' && status === 'success') {
-    return (
-        <p>
-            <Interpolate ... />
-        </p>
-    );
+    return <SubscribeSuccessMessage siteTitle={context.site.title} />;
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/portal/src/components/notification.js` around lines 52 - 72, Duplicate
JSX for signup and signup-paid branches (both success and error) should be
consolidated: create a small helper inside the component (e.g.,
renderSubscriptionMessage or renderSignupMessage) that takes status
('success'|'error') and returns the shared <p><Interpolate .../></p> JSX using
context.site.title and t(...), and replace the duplicated branches where type
=== 'signup' and type === 'signup-paid' to call that helper; update the error
branches similarly so both cases reuse the same function instead of repeating
identical JSX.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Minor comments:
In `@ghost/i18n/locales/bs/portal.json`:
- Line 58: Three portal translation entries in ghost/i18n/locales/bs/portal.json
are empty and fall back to English; fill the Bosnian translations for the
affected keys (e.g. "Could not sign in. Login link expired. <a>Click here to
retry</a>" and the other two keys at the same file for lines 174 and 244) by
replacing the empty strings with proper Bosnian text, preserving any HTML tags
like <a> so the link markup remains intact, and save the file to restore
localized UX for the bs locale.

In `@ghost/i18n/locales/ca/portal.json`:
- Line 58: Add Catalan translations for the three empty notification keys shown
(preserve the embedded <a>...</a> placeholder exactly): "Could not sign in.
Login link expired. <a>Click here to retry</a>", plus the other two composite
notification keys referenced in the comment; replace the empty string values
with the proper Catalan text while keeping the HTML anchor tags and original
punctuation intact so placeholders still work in code.

In `@ghost/i18n/locales/cs/portal.json`:
- Line 58: The Czech locale file is missing translations for migrated Portal
notification messages; add Czech translations for the migrated keys (including
the message key "Could not sign in. Login link expired. <a>Click here to
retry</a>") and the other two empty migrated Portal notification keys so they no
longer fall back to English; update the values in the cs portal.json to the
proper Czech strings preserving the exact keys and HTML anchor markup, ensuring
JSON validity and consistent phrasing with other Portal translations.

In `@ghost/i18n/locales/es/portal.json`:
- Line 58: Add Spanish translations for the three empty composite notification
keys: "Could not sign in. Login link expired. <a>Click here to retry</a>",
"Unable to send invitation to <strong>{siteTitle}</strong>. Contact the site
owner to invite them manually.", and "Unable to send recovery email. <a>Click
here to retry</a>" in ghost/i18n/locales/es/portal.json; keep the embedded HTML
tags and placeholder <a> and <strong>{siteTitle}</strong> exactly as-is and
provide natural Spanish text for each message.

In `@ghost/i18n/locales/fi/portal.json`:
- Line 58: The new Finnish notification key "Could not sign in. Login link
expired. <a>Click here to retry</a>" is empty (and the same issue exists for the
other two new keys in this file); fill each empty string with the appropriate
Finnish translation copied/migrated from the existing Finnish phrasing used
elsewhere in the project, preserving the HTML anchor tag (<a>...</a>) exactly
and any placeholders or punctuation so the UI and links continue to work; update
the three empty values so they no longer fallback to English.

In `@ghost/i18n/locales/gd/portal.json`:
- Line 58: The Gaelic translations for the new combined keys are missing in the
locale file: add Gaelic values for the keys "Could not sign in. Login link
expired. <a>Click here to retry</a>" (and the other two empty entries on the
same file) so they no longer fall back to English; open the gd/portal.json and
provide proper Gaelic translations for those exact message keys (preserve the
HTML anchor tag "<a>...</a>" in the translated strings) replacing the empty
string values with the translated text.

In `@ghost/i18n/locales/hr/portal.json`:
- Line 58: The Croatian locale is missing translations for three migrated
notification keys; add Croatian translations for the exact message keys "Could
not sign in. Login link expired. <a>Click here to retry</a>", and the other two
migrated notification keys present in the same file (the entries at the other
empty values) by replacing the empty string values with appropriate Croatian
text so the keys map to localized strings; update the values for these specific
keys in the hr/portal.json locale (ensure you preserve the HTML anchor tag
exactly as in the key) so users will see the localized messages instead of
English fallbacks.

In `@ghost/i18n/locales/hu/portal.json`:
- Line 58: Three composite notification keys in the Hungarian locale are empty;
replace the empty values with proper Hungarian translations that preserve the
existing translated intent while incorporating the HTML placeholders exactly as
in the keys (e.g., for the key "Could not sign in. Login link expired. <a>Click
here to retry</a>" provide a Hungarian sentence that includes the <a>...</a>
anchor around the retry text). Do the same for the other two composite keys that
include <a>...</a> and the one including <strong>{siteTitle}</strong>, ensuring
you keep the HTML tags and the {siteTitle} placeholder verbatim and translate
the surrounding text into natural Hungarian.

In `@ghost/i18n/locales/id/portal.json`:
- Line 58: The three new composite localization keys ("Could not sign in. Login
link expired. <a>Click here to retry</a>", and the two other merged notification
keys introduced around the same changes) currently have empty strings; populate
each value with the corresponding existing Indonesian translations by reusing
the prior translated fragments for "Could not sign in", "Login link expired" and
"Click here to retry" (and analogous fragments for the other two composite
keys), ensuring the HTML anchor markup (<a>...</a>) is preserved in the
translated string, keep JSON quoting/escaping correct, and run a quick JSON lint
to confirm validity so the merge does not fall back to English.

In `@ghost/i18n/locales/ko/portal.json`:
- Line 58: Provide Korean translations for the three empty composite
notification keys by replacing the empty string values with proper Korean text
while preserving the inline HTML tag placeholders exactly as in the keys;
specifically update the keys "Could not sign in. Login link expired. <a>Click
here to retry</a>", "Email address already verified. <a>Sign in</a>", and "We
couldn't find an account with that email address. <a>Create one now</a>" with
appropriate Korean translations that keep the <a>...</a> tags intact (e.g.,
"로그인할 수 없습니다. 로그인 링크의 유효기간이 만료되었습니다. <a>다시 시도하려면 클릭하세요</a>"), ensuring the
translations are concise and maintain the original tag placement.

In `@ghost/i18n/locales/kz/portal.json`:
- Line 58: Add Kazakh translations for the untranslated composite notification
keys in portal.json: provide localized values for the key "Could not sign in.
Login link expired. <a>Click here to retry</a>" and the other two new composite
keys (the ones containing the <a> anchor and the one with
<strong>{siteTitle}</strong>) ensuring you preserve the exact HTML placeholders
"<a>" (and its closing tag) and "<strong>{siteTitle}</strong>" unchanged;
replace the empty string values with the proper Kazakh text for each key while
keeping the surrounding punctuation and tags intact.

In `@ghost/i18n/locales/lv/portal.json`:
- Line 58: Populate the three empty Latvian translations for the notification
keys by replacing the empty strings with proper Latvian text while preserving
the embedded HTML tags and placeholders exactly as in the source keys: "Could
not sign in. Login link expired. <a>Click here to retry</a>", "You need to
<a>sign in</a> to access <strong>{siteTitle}</strong>.", and "You need to
<a>sign in</a> to access this content on <strong>{siteTitle}</strong>."; ensure
the <a>…</a> and <strong>{siteTitle}</strong> remain unchanged and provide
accurate, natural Latvian phrasing for each message.

In `@ghost/i18n/locales/mn/portal.json`:
- Line 58: Fill in Mongolian translations for the empty notification keys
introduced by the merge: replace the empty value for "Could not sign in. Login
link expired. <a>Click here to retry</a>" with the appropriate Mongolian string
(preserving the <a>...</a> anchor markup), and likewise populate the other two
newly empty merged notification keys referenced in the comment with their
Mongolian translations; ensure you keep the exact key strings unchanged and that
the JSON value is properly escaped and valid.

In `@ghost/i18n/locales/nb/portal.json`:
- Line 58: The three empty notification keys "Could not sign in. Login link
expired. <a>Click here to retry</a>", plus the other composite keys containing
"<a>" and "<strong>" placeholders, need Norwegian translations inserted (replace
the empty string values) while preserving the exact placeholder tags (<a> and
<strong>) and punctuation; update the values to appropriate Norwegian text for
each English key string so user-facing notifications are localized and
placeholders remain intact.

In `@ghost/i18n/locales/nn/portal.json`:
- Line 58: The three empty Nynorsk translation values in the nn portal JSON must
be populated: replace the empty string values for the message keys "Could not
sign in. Login link expired. <a>Click here to retry</a>", and the other two
untranslated keys mentioned (line 174 and 244) with appropriate Nynorsk
translations, preserving the exact key text (including HTML tags like <a>) and
valid JSON quoting/escaping so the portal falls back correctly; update
nn/portal.json by inserting the translated strings in place of "" for those
keys.

In `@ghost/i18n/locales/pt-BR/portal.json`:
- Line 58: The pt-BR locale file has empty values for new notification keys
(e.g., the key "Could not sign in. Login link expired. <a>Click here to
retry</a>") causing fallback to English; update
ghost/i18n/locales/pt-BR/portal.json by supplying appropriate Brazilian
Portuguese translations for that exact string and the other two empty keys
referenced in the review, preserving the embedded HTML anchor (<a>...</a>) and
JSON quoting/escaping rules so the keys remain identical and valid JSON.

In `@ghost/i18n/locales/sk/portal.json`:
- Line 58: The Slovak locale is missing translations for three newly introduced
portal notification keys, so update the sk translation file by supplying Slovak
strings for the keys "Could not sign in. Login link expired. <a>Click here to
retry</a>", "Your subscription has been canceled. <a>Manage your
subscription</a>", and "Payment method declined. <a>Update payment details</a>"
(use the exact keys to locate them in the file, preserving the HTML anchor tags)
ensuring each empty value is replaced with the correct Slovak translation while
keeping the surrounding JSON structure and escaping unchanged.

In `@ghost/i18n/locales/sl/portal.json`:
- Line 58: Populate the empty Slovenian translations for the three new composite
notification keys: "Could not sign in. Login link expired. <a>Click here to
retry</a>" and the two other composite notification keys currently empty in this
locale file, making sure to keep the embedded HTML tags (<a> and <strong>)
exactly as-is and provide proper Slovenian text that preserves the link/text
structure; update the corresponding values for those keys with accurate
Slovenian phrases while not altering the key strings or tag placement.

In `@ghost/i18n/locales/sr/portal.json`:
- Line 58: The Serbian locale file has empty translations for portal
notification keys causing English fallbacks; fill in Serbian translations for
the empty keys in sr/portal.json — at minimum replace the empty value for "Could
not sign in. Login link expired. <a>Click here to retry</a>" and the two other
empty notification keys in the same file with appropriate Serbian text,
preserving the exact key strings (including HTML tags like <a>) and JSON syntax
so lookup (portal notification rendering) uses the Serbian strings instead of
falling back to English.

In `@ghost/i18n/locales/ta/portal.json`:
- Line 58: The three migrated notification keys in
ghost/i18n/locales/ta/portal.json currently have empty Tamil values; update the
JSON by providing proper Tamil translations for the exact keys "Could not sign
in. Login link expired. <a>Click here to retry</a>", plus the other two migrated
notification keys mentioned in the review (ensure you locate the other empty
entries in the same file) so the messages remain localized; edit the value
strings for those keys to contain the correct Tamil wording while preserving the
original HTML anchor markup and JSON quoting.

In `@ghost/i18n/locales/ur/portal.json`:
- Line 58: Add Urdu translations for the three empty composite notification keys
by filling the values for the exact JSON keys "Could not sign in. Login link
expired. <a>Click here to retry</a>", "Invitation invalid. <a>Click here to
request a new invitation</a>", and "This content is for
<strong>{siteTitle}</strong> members only. <a>Sign in</a>" in the same locale
file; ensure you preserve the embedded HTML tags (<a> and
<strong>{siteTitle}</strong>) exactly as they appear and provide fluent Urdu
text for each string.

In `@ghost/i18n/locales/uz/portal.json`:
- Line 58: Populate the Uzbek translations for the three untranslated auth
notification keys by replacing the empty values for "Could not sign in. Login
link expired. <a>Click here to retry</a>", the other two migrated keys at the
same positions (the combined auth strings present in portal.json), with
appropriate Uzbek text; update the JSON entries so each key maps to a proper
Uzbek sentence preserving the HTML anchor tag (e.g. translate the message and
keep "<a>Click here to retry</a>" translated but with the same anchor tags),
ensuring valid JSON string quoting and no trailing commas.

---

Nitpick comments:
In `@apps/portal/src/components/notification.js`:
- Around line 52-72: Duplicate JSX for signup and signup-paid branches (both
success and error) should be consolidated: create a small helper inside the
component (e.g., renderSubscriptionMessage or renderSignupMessage) that takes
status ('success'|'error') and returns the shared <p><Interpolate .../></p> JSX
using context.site.title and t(...), and replace the duplicated branches where
type === 'signup' and type === 'signup-paid' to call that helper; update the
error branches similarly so both cases reuse the same function instead of
repeating identical JSX.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 97dad959-e172-43b5-8cd2-5f8977cdd8e8

📥 Commits

Reviewing files that changed from the base of the PR and between 17492ed and 8377936.

📒 Files selected for processing (64)
  • apps/portal/src/components/notification.js
  • ghost/i18n/locales/af/portal.json
  • ghost/i18n/locales/ar/portal.json
  • ghost/i18n/locales/bg/portal.json
  • ghost/i18n/locales/bn/portal.json
  • ghost/i18n/locales/bs/portal.json
  • ghost/i18n/locales/ca/portal.json
  • ghost/i18n/locales/context.json
  • ghost/i18n/locales/cs/portal.json
  • ghost/i18n/locales/da/portal.json
  • ghost/i18n/locales/de-CH/portal.json
  • ghost/i18n/locales/de/portal.json
  • ghost/i18n/locales/el/portal.json
  • ghost/i18n/locales/en/portal.json
  • ghost/i18n/locales/eo/portal.json
  • ghost/i18n/locales/es/portal.json
  • ghost/i18n/locales/et/portal.json
  • ghost/i18n/locales/eu/portal.json
  • ghost/i18n/locales/fa/portal.json
  • ghost/i18n/locales/fi/portal.json
  • ghost/i18n/locales/fr/portal.json
  • ghost/i18n/locales/gd/portal.json
  • ghost/i18n/locales/he/portal.json
  • ghost/i18n/locales/hi/portal.json
  • ghost/i18n/locales/hr/portal.json
  • ghost/i18n/locales/hu/portal.json
  • ghost/i18n/locales/id/portal.json
  • ghost/i18n/locales/is/portal.json
  • ghost/i18n/locales/it/portal.json
  • ghost/i18n/locales/ja/portal.json
  • ghost/i18n/locales/ko/portal.json
  • ghost/i18n/locales/kz/portal.json
  • ghost/i18n/locales/lt/portal.json
  • ghost/i18n/locales/lv/portal.json
  • ghost/i18n/locales/mk/portal.json
  • ghost/i18n/locales/mn/portal.json
  • ghost/i18n/locales/ms/portal.json
  • ghost/i18n/locales/nb/portal.json
  • ghost/i18n/locales/ne/portal.json
  • ghost/i18n/locales/nl/portal.json
  • ghost/i18n/locales/nn/portal.json
  • ghost/i18n/locales/pa/portal.json
  • ghost/i18n/locales/pl/portal.json
  • ghost/i18n/locales/pt-BR/portal.json
  • ghost/i18n/locales/pt/portal.json
  • ghost/i18n/locales/ro/portal.json
  • ghost/i18n/locales/ru/portal.json
  • ghost/i18n/locales/si/portal.json
  • ghost/i18n/locales/sk/portal.json
  • ghost/i18n/locales/sl/portal.json
  • ghost/i18n/locales/sq/portal.json
  • ghost/i18n/locales/sr-Cyrl/portal.json
  • ghost/i18n/locales/sr/portal.json
  • ghost/i18n/locales/sv/portal.json
  • ghost/i18n/locales/sw/portal.json
  • ghost/i18n/locales/ta/portal.json
  • ghost/i18n/locales/th/portal.json
  • ghost/i18n/locales/tr/portal.json
  • ghost/i18n/locales/uk/portal.json
  • ghost/i18n/locales/ur/portal.json
  • ghost/i18n/locales/uz/portal.json
  • ghost/i18n/locales/vi/portal.json
  • ghost/i18n/locales/zh-Hant/portal.json
  • ghost/i18n/locales/zh/portal.json

Copy link
Copy Markdown
Member

@cathysarisky cathysarisky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @rob-ghost - excellent thinking! There's one issue, though: These strings have translations already in many languages, and your proposal will wipe them out, causing non-English sites to see English until someone files a new PR, and it gets approved and merged.

I think the right thing to do here is to write a script that constructs translations for the new strings using our our "previous best" values. That avoids an initial regression. If you want me to do it, I can, but I think that work would be best placed right in this PR.

@rob-ghost
Copy link
Copy Markdown
Contributor Author

Thanks @cathysarisky I gave it a go to merge together the keys whose locales already had translations for the keys we're replacing.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 11

🧹 Nitpick comments (6)
ghost/i18n/locales/el/portal.json (1)

174-174: Add sentence punctuation before the retry link for consistency.

Minor copy polish: add a period before <a> to match the source key’s sentence boundary and improve readability.

Proposed tweak
-    "Signup error: Invalid link. <a>Click here to retry</a>": "Σφάλμα εγγραφής: Μη έγκυρος σύνδεσμος <a>Κάντε κλικ εδώ για επανάληψη</a>",
+    "Signup error: Invalid link. <a>Click here to retry</a>": "Σφάλμα εγγραφής: Μη έγκυρος σύνδεσμος. <a>Κάντε κλικ εδώ για επανάληψη</a>",
🤖 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 174, The translated value for the
key "Signup error: Invalid link. <a>Click here to retry</a>" is missing a period
before the <a> tag; update the translation string for that exact key so it reads
"Σφάλμα εγγραφής: Μη έγκυρος σύνδεσμος. <a>Κάντε κλικ εδώ για επανάληψη</a>"
(i.e., insert a period before the <a> tag) to match the source punctuation and
sentence boundary.
ghost/i18n/locales/zh-Hant/portal.json (1)

174-174: Add sentence punctuation before the retry link for consistency.

At Line 174, the Traditional Chinese string reads more naturally with a full stop before the CTA link.

Proposed tweak
-    "Signup error: Invalid link. <a>Click here to retry</a>": "註冊錯誤:連結無效 <a>點擊重試</a>",
+    "Signup error: Invalid link. <a>Click here to retry</a>": "註冊錯誤:連結無效。<a>點擊重試</a>",
🤖 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` at line 174, Update the Traditional
Chinese translation for the exact key "Signup error: Invalid link. <a>Click here
to retry</a>" so the value ends with a full stop before the link; change
"註冊錯誤:連結無效 <a>點擊重試</a>" to include a sentence punctuation (e.g.,
"註冊錯誤:連結無效。<a>點擊重試</a>") to match punctuation consistency.
ghost/i18n/locales/is/portal.json (1)

174-174: Minor punctuation inconsistency.

The English key has a period after "Invalid link." but the Icelandic translation omits the period after "Ógildur hlekkur". Consider adding it for consistency.

Suggested fix
-    "Signup error: Invalid link. <a>Click here to retry</a>": "Villa við nýskráningu: Ógildur hlekkur <a>Smellið hér til að reyna aftur</a>",
+    "Signup error: Invalid link. <a>Click here to retry</a>": "Villa við nýskráningu: Ógildur hlekkur. <a>Smellið hér til að reyna aftur</a>",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/is/portal.json` at line 174, The Icelandic translation for
the key "Signup error: Invalid link. <a>Click here to retry</a>" is missing the
period after "Ógildur hlekkur"; update the value for that key (the string
starting with "Villa við nýskráningu: Ógildur hlekkur <a>...") to include a
period after "Ógildur hlekkur" so it matches the English punctuation (i.e.,
"Ógildur hlekkur. <a>Smellið hér til að reyna aftur</a>").
ghost/i18n/locales/sw/portal.json (1)

174-174: Optional: add a period before the retry link for sentence consistency.

This is purely text-quality/readability; interpolation will work either way.

Suggested tweak
-    "Signup error: Invalid link. <a>Click here to retry</a>": "Kosa la usajili: Kiungo batili <a>Bofya hapa kurudia</a>",
+    "Signup error: Invalid link. <a>Click here to retry</a>": "Kosa la usajili: Kiungo batili. <a>Bofya hapa kurudia</a>",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/sw/portal.json` at line 174, Update the Swahili
translation for the key "Signup error: Invalid link. <a>Click here to retry</a>"
so the sentence ends with a period before the retry link; change the value "Kosa
la usajili: Kiungo batili <a>Bofya hapa kurudia</a>" to include a period before
the <a> tag (e.g., "Kosa la usajili: Kiungo batili. <a>Bofya hapa kurudia</a>")
to ensure sentence consistency.
ghost/i18n/locales/lv/portal.json (1)

174-174: Minor punctuation inconsistency.

The English key has a period after "Invalid link." but the Latvian translation omits it after "nederīga saite". This may be intentional for Latvian grammatical style, but if consistency with the source punctuation is desired, consider adding the period.

-    "Signup error: Invalid link. <a>Click here to retry</a>": "Reģistrācijas kļūda: nederīga saite <a>Noklikšķiniet šeit, lai mēģinātu vēlreiz</a>",
+    "Signup error: Invalid link. <a>Click here to retry</a>": "Reģistrācijas kļūda: nederīga saite. <a>Noklikšķiniet šeit, lai mēģinātu vēlreiz</a>",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/lv/portal.json` at line 174, The Latvian translation for
the key "Signup error: Invalid link. <a>Click here to retry</a>" is missing the
period after "nederīga saite"; update the value string "Reģistrācijas kļūda:
nederīga saite <a>Noklikšķiniet šeit, lai mēģinātu vēlreiz</a>" to include the
period ("nederīga saite.") so the punctuation matches the source key.
ghost/i18n/locales/pt/portal.json (1)

174-174: Minor punctuation: missing period after "ligação inválida".

The English key has "Invalid link." with a period, but the Portuguese translation omits it. Consider adding the period for consistency.

Proposed fix
-    "Signup error: Invalid link. <a>Click here to retry</a>": "Erro de inscrição: ligação inválida <a>Clique aqui para tentar novamente</a>",
+    "Signup error: Invalid link. <a>Click here to retry</a>": "Erro de inscrição: ligação inválida. <a>Clique aqui para tentar novamente</a>",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/pt/portal.json` at line 174, The Portuguese translation
for the key "Signup error: Invalid link. <a>Click here to retry</a>" is missing
the period after "ligação inválida"; update the translated value "Erro de
inscrição: ligação inválida <a>Clique aqui para tentar novamente</a>" to include
the period so it reads "Erro de inscrição: ligação inválida. <a>Clique aqui para
tentar novamente</a>" to match the English punctuation and maintain consistency.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ghost/i18n/locales/af/portal.json`:
- Line 174: The Afrikaans translation for the JSON key "Signup error: Invalid
link. <a>Click here to retry</a>" is missing a period before the <a> tag; update
the value for that key in portal.json (the entry with the key starting "Signup
error: Invalid link. <a>Click here to retry</a>") to include a period before the
<a> tag so it reads like "Aanmelding fout: Ongeldige skakel. <a>Kliek hier om
weer te probeer</a>" ensuring punctuation matches the English source.

In `@ghost/i18n/locales/bn/portal.json`:
- Line 174: The Bengali translation for the key "Signup error: Invalid link.
<a>Click here to retry</a>" in bn/portal.json is missing a sentence separator
before the retry link; update the value for that key ("সাইন আপ ত্রুটি: অবৈধ
লিঙ্ক <a>আবার চেষ্টা করতে এখানে ক্লিক করুন</a>") by inserting the Bengali danda
character "।" immediately before the opening <a> tag so it reads "সাইন আপ
ত্রুটি: অবৈধ লিঙ্ক। <a>আবার চেষ্টা করতে এখানে ক্লিক করুন</a>" for correct
sentence separation and readability.

In `@ghost/i18n/locales/es/portal.json`:
- Line 174: The Spanish translation for the key "Signup error: Invalid link.
<a>Click here to retry</a>" is missing a period before the retry link; update
the value to insert a period before the <a> tag so it reads "Error de registro:
Enlace no válido. <a>Haz click aquí para reintentar</a>" (preserving the
existing wording) to match the two-sentence structure of the source key.

In `@ghost/i18n/locales/gd/portal.json`:
- Line 174: The Gaelic translation for the key "Signup error: Invalid link.
<a>Click here to retry</a>" is missing a sentence separator before the <a> tag;
update the translated value "Mearachd: Ceangal mì-dhligheach <a>Briog an seo gus
feuchainn a-rithist</a>" to include a period (or appropriate separator) before
the <a> tag so it reads like "Mearachd: Ceangal mì-dhligheach. <a>…</a>"
ensuring the sentence and the retry link are properly separated.

In `@ghost/i18n/locales/hr/portal.json`:
- Line 58: Update the Croatian translations for the retry-link messages to use
consistent, polite wording and correct the signup vs sign-in semantics: replace
the current string value for the key "Could not sign in. Login link expired.
<a>Click here to retry</a>" with a normalized sign-in phrasing (e.g., use "Nije
bilo moguće prijaviti se. Link za prijavu je istekao. <a>Kliknite ovdje za
ponovni pokušaj</a>") and locate the analogous signup message that incorrectly
uses "prijave" and change it to use "registracije" (e.g., "Nije bilo moguće
dovršiti registraciju. Link za registraciju je istekao. <a>Kliknite ovdje za
ponovni pokušaj</a>"); ensure both messages use consistent punctuation and the
polite plural "Kliknite".

In `@ghost/i18n/locales/hu/portal.json`:
- Line 58: The Hungarian translation for the key "Could not sign in. Login link
expired. <a>Click here to retry</a>" is semantically wrong (it mentions
registration/signup); update the value to a phrasing that preserves "sign in"
(e.g., mention "bejelentkezés" and that the bejelentkezési link lejárt) and keep
the <a>...</a> anchor intact; also scan the file for the other mismatched entry
where the English key contains "subscribed" and replace any translations that
incorrectly say "regisztráció/subscribe" with a correct Hungarian equivalent for
"subscribed" or the intended verb, ensuring meanings match their English keys.

In `@ghost/i18n/locales/lt/portal.json`:
- Line 174: The Lithuanian translation for the key "Signup error: Invalid link.
<a>Click here to retry</a>" is missing the period before the <a> tag; update the
value string "Registracijos klaida: negaliojanti nuoroda <a>Spauskite čia, kad
pakartotumėte</a>" to include a period right after "negaliojanti nuoroda" (i.e.,
"negaliojanti nuoroda. <a>...") so it matches the punctuation of the English
key.

In `@ghost/i18n/locales/mk/portal.json`:
- Line 174: The Macedonian translation for the key "Signup error: Invalid link.
<a>Click here to retry</a>" is missing the period after "Невалиден линк"; update
the value string to include the period before the <a> tag so it reads "Грешка
при регистрација: Невалиден линк. <a>Кликнете тука за да се обидите
повторно</a>", preserving the existing spacing and HTML anchor tag.

In `@ghost/i18n/locales/nl/portal.json`:
- Line 174: The Dutch translation for the key "Signup error: Invalid link.
<a>Click here to retry</a>" in portal.json is missing the period before the <a>
tag; update the value for that key (the string starting "Registratiefout:
Ongeldige link ...") to include a period before the <a> tag (e.g.,
"Registratiefout: Ongeldige link. <a>Klik hier om opnieuw te proberen</a>")
preserving spacing and the surrounding HTML tag.

In `@ghost/i18n/locales/nn/portal.json`:
- Line 174: The translated value for the key "Signup error: Invalid link.
<a>Click here to retry</a>" is missing a full stop before the retry anchor;
update the translation string "Registreringsfeil: Ugyldig lenke <a>Klikk her for
å prøva på ny</a>" to insert a period before the <a> tag (i.e., end the sentence
with a full stop then the anchor) so it matches the source punctuation and
improves readability.

In `@ghost/i18n/locales/pt/portal.json`:
- Line 58: The translation for the key "Could not sign in. Login link expired.
<a>Click here to retry</a>" incorrectly uses "registar" (register); update the
Portuguese value to use "entrar" (login) instead, e.g. change "Não foi possível
registar. O link de login expirou. <a>Clique aqui para tentar novamente</a>" to
"Não foi possível entrar. O link de login expirou. <a>Clique aqui para tentar
novamente</a>" so the message correctly reflects a sign-in/login failure.

---

Nitpick comments:
In `@ghost/i18n/locales/el/portal.json`:
- Line 174: The translated value for the key "Signup error: Invalid link.
<a>Click here to retry</a>" is missing a period before the <a> tag; update the
translation string for that exact key so it reads "Σφάλμα εγγραφής: Μη έγκυρος
σύνδεσμος. <a>Κάντε κλικ εδώ για επανάληψη</a>" (i.e., insert a period before
the <a> tag) to match the source punctuation and sentence boundary.

In `@ghost/i18n/locales/is/portal.json`:
- Line 174: The Icelandic translation for the key "Signup error: Invalid link.
<a>Click here to retry</a>" is missing the period after "Ógildur hlekkur";
update the value for that key (the string starting with "Villa við nýskráningu:
Ógildur hlekkur <a>...") to include a period after "Ógildur hlekkur" so it
matches the English punctuation (i.e., "Ógildur hlekkur. <a>Smellið hér til að
reyna aftur</a>").

In `@ghost/i18n/locales/lv/portal.json`:
- Line 174: The Latvian translation for the key "Signup error: Invalid link.
<a>Click here to retry</a>" is missing the period after "nederīga saite"; update
the value string "Reģistrācijas kļūda: nederīga saite <a>Noklikšķiniet šeit, lai
mēģinātu vēlreiz</a>" to include the period ("nederīga saite.") so the
punctuation matches the source key.

In `@ghost/i18n/locales/pt/portal.json`:
- Line 174: The Portuguese translation for the key "Signup error: Invalid link.
<a>Click here to retry</a>" is missing the period after "ligação inválida";
update the translated value "Erro de inscrição: ligação inválida <a>Clique aqui
para tentar novamente</a>" to include the period so it reads "Erro de inscrição:
ligação inválida. <a>Clique aqui para tentar novamente</a>" to match the English
punctuation and maintain consistency.

In `@ghost/i18n/locales/sw/portal.json`:
- Line 174: Update the Swahili translation for the key "Signup error: Invalid
link. <a>Click here to retry</a>" so the sentence ends with a period before the
retry link; change the value "Kosa la usajili: Kiungo batili <a>Bofya hapa
kurudia</a>" to include a period before the <a> tag (e.g., "Kosa la usajili:
Kiungo batili. <a>Bofya hapa kurudia</a>") to ensure sentence consistency.

In `@ghost/i18n/locales/zh-Hant/portal.json`:
- Line 174: Update the Traditional Chinese translation for the exact key "Signup
error: Invalid link. <a>Click here to retry</a>" so the value ends with a full
stop before the link; change "註冊錯誤:連結無效 <a>點擊重試</a>" to include a sentence
punctuation (e.g., "註冊錯誤:連結無效。<a>點擊重試</a>") to match punctuation consistency.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 288b13e7-456c-4b7c-bd53-db3bdf6e42b1

📥 Commits

Reviewing files that changed from the base of the PR and between 60ebb9d and ee2f52f.

📒 Files selected for processing (58)
  • ghost/i18n/locales/af/portal.json
  • ghost/i18n/locales/ar/portal.json
  • ghost/i18n/locales/bg/portal.json
  • ghost/i18n/locales/bn/portal.json
  • ghost/i18n/locales/bs/portal.json
  • ghost/i18n/locales/ca/portal.json
  • ghost/i18n/locales/cs/portal.json
  • ghost/i18n/locales/da/portal.json
  • ghost/i18n/locales/de-CH/portal.json
  • ghost/i18n/locales/de/portal.json
  • ghost/i18n/locales/el/portal.json
  • ghost/i18n/locales/es/portal.json
  • ghost/i18n/locales/et/portal.json
  • ghost/i18n/locales/eu/portal.json
  • ghost/i18n/locales/fa/portal.json
  • ghost/i18n/locales/fi/portal.json
  • ghost/i18n/locales/fr/portal.json
  • ghost/i18n/locales/gd/portal.json
  • ghost/i18n/locales/he/portal.json
  • ghost/i18n/locales/hi/portal.json
  • ghost/i18n/locales/hr/portal.json
  • ghost/i18n/locales/hu/portal.json
  • ghost/i18n/locales/id/portal.json
  • ghost/i18n/locales/is/portal.json
  • ghost/i18n/locales/it/portal.json
  • ghost/i18n/locales/ja/portal.json
  • ghost/i18n/locales/ko/portal.json
  • ghost/i18n/locales/kz/portal.json
  • ghost/i18n/locales/lt/portal.json
  • ghost/i18n/locales/lv/portal.json
  • ghost/i18n/locales/mk/portal.json
  • ghost/i18n/locales/mn/portal.json
  • ghost/i18n/locales/ms/portal.json
  • ghost/i18n/locales/nb/portal.json
  • ghost/i18n/locales/nl/portal.json
  • ghost/i18n/locales/nn/portal.json
  • ghost/i18n/locales/pa/portal.json
  • ghost/i18n/locales/pl/portal.json
  • ghost/i18n/locales/pt-BR/portal.json
  • ghost/i18n/locales/pt/portal.json
  • ghost/i18n/locales/ro/portal.json
  • ghost/i18n/locales/ru/portal.json
  • ghost/i18n/locales/si/portal.json
  • ghost/i18n/locales/sk/portal.json
  • ghost/i18n/locales/sl/portal.json
  • ghost/i18n/locales/sq/portal.json
  • ghost/i18n/locales/sr-Cyrl/portal.json
  • ghost/i18n/locales/sr/portal.json
  • ghost/i18n/locales/sv/portal.json
  • ghost/i18n/locales/sw/portal.json
  • ghost/i18n/locales/ta/portal.json
  • ghost/i18n/locales/th/portal.json
  • ghost/i18n/locales/tr/portal.json
  • ghost/i18n/locales/uk/portal.json
  • ghost/i18n/locales/ur/portal.json
  • ghost/i18n/locales/vi/portal.json
  • ghost/i18n/locales/zh-Hant/portal.json
  • ghost/i18n/locales/zh/portal.json
✅ Files skipped from review due to trivial changes (13)
  • ghost/i18n/locales/si/portal.json
  • ghost/i18n/locales/eu/portal.json
  • ghost/i18n/locales/fr/portal.json
  • ghost/i18n/locales/ko/portal.json
  • ghost/i18n/locales/de/portal.json
  • ghost/i18n/locales/it/portal.json
  • ghost/i18n/locales/sv/portal.json
  • ghost/i18n/locales/kz/portal.json
  • ghost/i18n/locales/ru/portal.json
  • ghost/i18n/locales/pa/portal.json
  • ghost/i18n/locales/sk/portal.json
  • ghost/i18n/locales/ar/portal.json
  • ghost/i18n/locales/nb/portal.json
🚧 Files skipped from review as they are similar to previous changes (25)
  • ghost/i18n/locales/ro/portal.json
  • ghost/i18n/locales/ur/portal.json
  • ghost/i18n/locales/sq/portal.json
  • ghost/i18n/locales/ja/portal.json
  • ghost/i18n/locales/hi/portal.json
  • ghost/i18n/locales/sl/portal.json
  • ghost/i18n/locales/ms/portal.json
  • ghost/i18n/locales/tr/portal.json
  • ghost/i18n/locales/bg/portal.json
  • ghost/i18n/locales/de-CH/portal.json
  • ghost/i18n/locales/pl/portal.json
  • ghost/i18n/locales/th/portal.json
  • ghost/i18n/locales/uk/portal.json
  • ghost/i18n/locales/vi/portal.json
  • ghost/i18n/locales/et/portal.json
  • ghost/i18n/locales/sr-Cyrl/portal.json
  • ghost/i18n/locales/pt-BR/portal.json
  • ghost/i18n/locales/cs/portal.json
  • ghost/i18n/locales/da/portal.json
  • ghost/i18n/locales/ta/portal.json
  • ghost/i18n/locales/sr/portal.json
  • ghost/i18n/locales/ca/portal.json
  • ghost/i18n/locales/fi/portal.json
  • ghost/i18n/locales/bs/portal.json
  • ghost/i18n/locales/id/portal.json

"Sign out": "Clàraich a-mach",
"Sign up": "Clàraich",
"Signup error: Invalid link": "Mearachd: Ceangal mì-dhligheach",
"Signup error: Invalid link. <a>Click here to retry</a>": "Mearachd: Ceangal mì-dhligheach <a>Briog an seo gus feuchainn a-rithist</a>",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Missing period before the <a> tag.

Similar to the Dutch translation, the Gaelic translation is missing a period (or appropriate sentence separator) before the <a> tag to separate the error message from the retry action.

📝 Suggested fix
-    "Signup error: Invalid link. <a>Click here to retry</a>": "Mearachd: Ceangal mì-dhligheach <a>Briog an seo gus feuchainn a-rithist</a>",
+    "Signup error: Invalid link. <a>Click here to retry</a>": "Mearachd: Ceangal mì-dhligheach. <a>Briog an seo gus feuchainn a-rithist</a>",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"Signup error: Invalid link. <a>Click here to retry</a>": "Mearachd: Ceangal mì-dhligheach <a>Briog an seo gus feuchainn a-rithist</a>",
"Signup error: Invalid link. <a>Click here to retry</a>": "Mearachd: Ceangal mì-dhligheach. <a>Briog an seo gus feuchainn a-rithist</a>",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/gd/portal.json` at line 174, The Gaelic translation for
the key "Signup error: Invalid link. <a>Click here to retry</a>" is missing a
sentence separator before the <a> tag; update the translated value "Mearachd:
Ceangal mì-dhligheach <a>Briog an seo gus feuchainn a-rithist</a>" to include a
period (or appropriate separator) before the <a> tag so it reads like "Mearachd:
Ceangal mì-dhligheach. <a>…</a>" ensuring the sentence and the retry link are
properly separated.

"Could not create Stripe billing portal session": "",
"Could not create Stripe checkout session": "Nije moguće pokrenuti Stripe naplatu",
"Could not sign in. Login link expired.": "Neuspio pokušaj prijave. Link za prijavu je istekao.",
"Could not sign in. Login link expired. <a>Click here to retry</a>": "Neuspio pokušaj prijave. Link za prijavu je istekao. <a>Klikni ovdje za ponovni pokušaj</a>",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix Croatian wording consistency and signup semantics in retry-link messages

Line 174 currently translates signup context as "prijave" (sign-in), which is semantically off for signup. Also, the sentence punctuation/tone can be normalized in both changed retry-link strings.

Suggested wording update
-    "Could not sign in. Login link expired. <a>Click here to retry</a>": "Neuspio pokušaj prijave. Link za prijavu je istekao. <a>Klikni ovdje za ponovni pokušaj</a>",
+    "Could not sign in. Login link expired. <a>Click here to retry</a>": "Prijava nije uspjela. Poveznica za prijavu je istekla. <a>Kliknite ovdje za ponovni pokušaj</a>",

-    "Signup error: Invalid link. <a>Click here to retry</a>": "Greška prilikom prijave. Neispravan link <a>Klikni ovdje za ponovni pokušaj</a>",
+    "Signup error: Invalid link. <a>Click here to retry</a>": "Greška pri registraciji. Neispravna poveznica. <a>Kliknite ovdje za ponovni pokušaj</a>",

Also applies to: 174-174

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/hr/portal.json` at line 58, Update the Croatian
translations for the retry-link messages to use consistent, polite wording and
correct the signup vs sign-in semantics: replace the current string value for
the key "Could not sign in. Login link expired. <a>Click here to retry</a>" with
a normalized sign-in phrasing (e.g., use "Nije bilo moguće prijaviti se. Link za
prijavu je istekao. <a>Kliknite ovdje za ponovni pokušaj</a>") and locate the
analogous signup message that incorrectly uses "prijave" and change it to use
"registracije" (e.g., "Nije bilo moguće dovršiti registraciju. Link za
registraciju je istekao. <a>Kliknite ovdje za ponovni pokušaj</a>"); ensure both
messages use consistent punctuation and the polite plural "Kliknite".

"Sign out": "Одјавете се",
"Sign up": "Регистрирајте се",
"Signup error: Invalid link": "Грешка при регистрација: Невалиден линк",
"Signup error: Invalid link. <a>Click here to retry</a>": "Грешка при регистрација: Невалиден линк <a>Кликнете тука за да се обидите повторно</a>",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Minor punctuation inconsistency: missing period before the retry link.

The English key has a period after "Invalid link." but the Macedonian translation omits it: "Невалиден линк ..." instead of "Невалиден линк. ...". This may affect readability.

Proposed fix
-    "Signup error: Invalid link. <a>Click here to retry</a>": "Грешка при регистрација: Невалиден линк <a>Кликнете тука за да се обидите повторно</a>",
+    "Signup error: Invalid link. <a>Click here to retry</a>": "Грешка при регистрација: Невалиден линк. <a>Кликнете тука за да се обидите повторно</a>",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"Signup error: Invalid link. <a>Click here to retry</a>": "Грешка при регистрација: Невалиден линк <a>Кликнете тука за да се обидите повторно</a>",
"Signup error: Invalid link. <a>Click here to retry</a>": "Грешка при регистрација: Невалиден линк. <a>Кликнете тука за да се обидите повторно</a>",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/mk/portal.json` at line 174, The Macedonian translation
for the key "Signup error: Invalid link. <a>Click here to retry</a>" is missing
the period after "Невалиден линк"; update the value string to include the period
before the <a> tag so it reads "Грешка при регистрација: Невалиден линк.
<a>Кликнете тука за да се обидите повторно</a>", preserving the existing spacing
and HTML anchor tag.

"Sign out": "Uitloggen",
"Sign up": "Registreren",
"Signup error: Invalid link": "Registratiefout: Ongeldige link",
"Signup error: Invalid link. <a>Click here to retry</a>": "Registratiefout: Ongeldige link <a>Klik hier om opnieuw te proberen</a>",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Missing period before the <a> tag.

The English key has a period after "Invalid link." to separate the error description from the retry action. The Dutch translation is missing this period before the <a> tag, which may affect readability.

📝 Suggested fix
-    "Signup error: Invalid link. <a>Click here to retry</a>": "Registratiefout: Ongeldige link <a>Klik hier om opnieuw te proberen</a>",
+    "Signup error: Invalid link. <a>Click here to retry</a>": "Registratiefout: Ongeldige link. <a>Klik hier om opnieuw te proberen</a>",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"Signup error: Invalid link. <a>Click here to retry</a>": "Registratiefout: Ongeldige link <a>Klik hier om opnieuw te proberen</a>",
"Signup error: Invalid link. <a>Click here to retry</a>": "Registratiefout: Ongeldige link. <a>Klik hier om opnieuw te proberen</a>",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/nl/portal.json` at line 174, The Dutch translation for the
key "Signup error: Invalid link. <a>Click here to retry</a>" in portal.json is
missing the period before the <a> tag; update the value for that key (the string
starting "Registratiefout: Ongeldige link ...") to include a period before the
<a> tag (e.g., "Registratiefout: Ongeldige link. <a>Klik hier om opnieuw te
proberen</a>") preserving spacing and the surrounding HTML tag.

"Could not create Stripe billing portal session": "",
"Could not create Stripe checkout session": "",
"Could not sign in. Login link expired.": "Não foi possível registar. O link de login expirou.",
"Could not sign in. Login link expired. <a>Click here to retry</a>": "Não foi possível registar. O link de login expirou. <a>Clique aqui para tentar novamente</a>",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Mistranslation: "sign in" translated as "registar" (register) instead of "entrar" (login).

The Portuguese translation uses "Não foi possível registar" which means "Could not register/signup", but this message is for a login (sign in) error. This could confuse users about which action failed.

Proposed fix
-    "Could not sign in. Login link expired. <a>Click here to retry</a>": "Não foi possível registar. O link de login expirou. <a>Clique aqui para tentar novamente</a>",
+    "Could not sign in. Login link expired. <a>Click here to retry</a>": "Não foi possível entrar. O link de login expirou. <a>Clique aqui para tentar novamente</a>",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"Could not sign in. Login link expired. <a>Click here to retry</a>": "Não foi possível registar. O link de login expirou. <a>Clique aqui para tentar novamente</a>",
"Could not sign in. Login link expired. <a>Click here to retry</a>": "Não foi possível entrar. O link de login expirou. <a>Clique aqui para tentar novamente</a>",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/pt/portal.json` at line 58, The translation for the key
"Could not sign in. Login link expired. <a>Click here to retry</a>" incorrectly
uses "registar" (register); update the Portuguese value to use "entrar" (login)
instead, e.g. change "Não foi possível registar. O link de login expirou.
<a>Clique aqui para tentar novamente</a>" to "Não foi possível entrar. O link de
login expirou. <a>Clique aqui para tentar novamente</a>" so the message
correctly reflects a sign-in/login failure.

Fragmented translation keys like "Click here to retry" and
"You've successfully subscribed to" were split across JSX elements,
preventing translators from reordering words for their locale. Merged
them into single keys with inline <a> and <strong> tags using
react-interpolate so each locale gets complete sentence context.
Reconstructed translations for the 3 new combined notification keys
from the old fragment translations, preserving existing localization
rather than leaving empty strings that would fall back to English.

168 translations backfilled across 58 locales.
@rob-ghost rob-ghost force-pushed the fix/portal-fragment-translation-keys branch from ee2f52f to 3bc57d0 Compare April 7, 2026 10:32
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (4)
ghost/i18n/locales/hu/portal.json (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Fix semantic mismatches in auth/subscription translations.

Two values still change the action meaning versus their keys (“sign in” and “subscribed”).

Suggested fix
-    "Could not sign in. Login link expired. <a>Click here to retry</a>": "A bejelentkezési link lejárt, a regisztráció sikertelen. <a>Kattints ide az újrapróbálkozáshoz</a>",
+    "Could not sign in. Login link expired. <a>Click here to retry</a>": "Nem sikerült bejelentkezni. A bejelentkezési link lejárt. <a>Kattints ide az újrapróbálkozáshoz</a>",

-    "You've successfully subscribed to <strong>{siteTitle}</strong>": "Sikeresen bejelentkeztél ide:  <strong>{siteTitle}</strong>",
+    "You've successfully subscribed to <strong>{siteTitle}</strong>": "Sikeresen feliratkoztál erre: <strong>{siteTitle}</strong>",

Also applies to: 244-244

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/hu/portal.json` at line 58, The Hungarian translation for
the key "Could not sign in. Login link expired. <a>Click here to retry</a>"
incorrectly uses wording that implies registration/signup; update the value to
use "bejelentkezés" (sign in) and keep the action as retry (e.g., use phrasing
like "A bejelentkezés sikertelen, a bejelentkezési link lejárt. <a>Kattints ide
az újrapróbálkozáshoz</a>"). Also locate the key that corresponds to
"subscribed" (line ~244) and ensure the Hungarian string reflects the same
subscription state (past-tense/subscribed) rather than a different action/state;
change it to the correct Hungarian past-tense word for "subscribed" so the
meaning matches the English key.
ghost/i18n/locales/pt/portal.json (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Use a sign-in term instead of a register term in this auth error.

The value currently says “registar” (register), but this key is about failing to sign in.

Suggested fix
-    "Could not sign in. Login link expired. <a>Click here to retry</a>": "Não foi possível registar. O link de login expirou. <a>Clique aqui para tentar novamente</a>",
+    "Could not sign in. Login link expired. <a>Click here to retry</a>": "Não foi possível entrar. O link de login expirou. <a>Clique aqui para tentar novamente</a>",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/pt/portal.json` at line 58, The Portuguese translation for
the key "Could not sign in. Login link expired. <a>Click here to retry</a>" uses
the register term "registar" but should use a sign-in term; update the value to
use a sign-in phrase (e.g., replace "Não foi possível registar" with "Não foi
possível iniciar sessão" or "Não foi possível entrar") while preserving the rest
of the string and the HTML anchor (<a>...</a>) so the key and markup remain
unchanged.
ghost/i18n/locales/lt/portal.json (1)

174-174: ⚠️ Potential issue | 🟡 Minor

Add the missing period before the retry link.

Line 174 should keep the two-sentence structure before the <a> tag.

✏️ Proposed fix
-    "Signup error: Invalid link. <a>Click here to retry</a>": "Registracijos klaida: negaliojanti nuoroda <a>Spauskite čia, kad pakartotumėte</a>",
+    "Signup error: Invalid link. <a>Click here to retry</a>": "Registracijos klaida: negaliojanti nuoroda. <a>Spauskite čia, kad pakartotumėte</a>",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/lt/portal.json` at line 174, The translation for the key
"Signup error: Invalid link. <a>Click here to retry</a>" is missing the period
before the retry link; update the Lithuanian value so it preserves the
two-sentence structure by placing a period at the end of the first sentence
immediately before the <a> tag (i.e., ensure "Registracijos klaida: negaliojanti
nuoroda." is followed by a space and then the <a>... link text).
ghost/i18n/locales/es/portal.json (1)

174-174: ⚠️ Potential issue | 🟡 Minor

Re-add the missing period before the retry link.

Line 174 still reads as a run-on before <a>.

✏️ Proposed fix
-    "Signup error: Invalid link. <a>Click here to retry</a>": "Error de registro: Enlace no válido <a>Haz click aquí para reintentar</a>",
+    "Signup error: Invalid link. <a>Click here to retry</a>": "Error de registro: Enlace no válido. <a>Haz click aquí para reintentar</a>",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/es/portal.json` at line 174, The Spanish translation for
the signup error message is missing the period before the retry link; update the
value for the key "Signup error: Invalid link. <a>Click here to retry</a>" so it
reads "Error de registro: Enlace no válido. <a>Haz click aquí para
reintentar</a>" (add the period and space before the <a> tag) to match the
original punctuation and spacing.
🧹 Nitpick comments (1)
apps/portal/src/components/notification.js (1)

52-73: Consider consolidating duplicated signup and signup-paid branches.

The success/error rendering blocks are duplicated and can be merged to reduce maintenance overhead.

♻️ Suggested refactor
-    } else if (type === 'signup' && status === 'success') {
-        return (
-            <p>
-                <Interpolate
-                    mapping={{
-                        strong: <strong />
-                    }}
-                    string={t('You\'ve successfully subscribed to <strong>{siteTitle}</strong>', {siteTitle: context.site.title})}
-                />
-            </p>
-        );
-    } else if (type === 'signup-paid' && status === 'success') {
+    } else if (['signup', 'signup-paid'].includes(type) && status === 'success') {
         return (
             <p>
                 <Interpolate
@@
-    } else if (type === 'signup' && status === 'error') {
-        return (
-            <p>
-                <Interpolate
-                    mapping={{
-                        a: <a href={singupPortalLink} target="_parent" />
-                    }}
-                    string={t('Signup error: Invalid link. <a>Click here to retry</a>')}
-                />
-            </p>
-        );
-    } else if (type === 'signup-paid' && status === 'error') {
+    } else if (['signup', 'signup-paid'].includes(type) && status === 'error') {
         return (
             <p>
                 <Interpolate

Also applies to: 86-107

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/portal/src/components/notification.js` around lines 52 - 73, The
branches handling type === 'signup' and type === 'signup-paid' (and their
success/error counterparts around lines 86-107) are duplicated; consolidate them
by combining the checks into a single condition (e.g., types.includes('signup')
or /^(signup(-paid)?)$/) inside the notification rendering logic in the
Notification component (or the function rendering these branches) and reuse the
same JSX/Interpolate mapping and string call (t('You\'ve successfully subscribed
to <strong>{siteTitle}</strong>', {siteTitle: context.site.title})) so the
success and error render blocks are implemented once and handle both 'signup'
and 'signup-paid'.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ghost/i18n/locales/pt-BR/portal.json`:
- Line 174: Update the translation string key "Signup error: Invalid link.
<a>Click here to retry</a>" so the Portuguese value inserts a period before the
anchor tag; edit the value for that key (currently "Erro de inscrição: link
inválido <a>Clique aqui para tentar novamente</a>") to include a period
separating the sentence from the <a> element, preserving the same text and HTML
tag.

In `@ghost/i18n/locales/sl/portal.json`:
- Line 174: The translation string for the key "Signup error: Invalid link.
<a>Click here to retry</a>" is missing a period before the retry link; update
the Slovenian value so there is a sentence-ending period before the <a> tag
(e.g., change "Neveljavna povezava <a>..." to "Neveljavna povezava. <a>...")
ensuring spacing and the <a> tag remain intact in the value.

In `@ghost/i18n/locales/sr-Cyrl/portal.json`:
- Line 174: The translation string key "Signup error: Invalid link. <a>Click
here to retry</a>" in portal.json is missing a period before the anchor; update
the Serbian Cyrillic value for that key (the string starting with "Грешка при
регистрацији: Невалидан линк <a>...") to include a sentence-ending period before
the <a> tag so it reads "...Невалидан линк. <a>Кликните овде да покушате
поново</a>" ensuring punctuation is added immediately before the anchor tag.

---

Duplicate comments:
In `@ghost/i18n/locales/es/portal.json`:
- Line 174: The Spanish translation for the signup error message is missing the
period before the retry link; update the value for the key "Signup error:
Invalid link. <a>Click here to retry</a>" so it reads "Error de registro: Enlace
no válido. <a>Haz click aquí para reintentar</a>" (add the period and space
before the <a> tag) to match the original punctuation and spacing.

In `@ghost/i18n/locales/hu/portal.json`:
- Line 58: The Hungarian translation for the key "Could not sign in. Login link
expired. <a>Click here to retry</a>" incorrectly uses wording that implies
registration/signup; update the value to use "bejelentkezés" (sign in) and keep
the action as retry (e.g., use phrasing like "A bejelentkezés sikertelen, a
bejelentkezési link lejárt. <a>Kattints ide az újrapróbálkozáshoz</a>"). Also
locate the key that corresponds to "subscribed" (line ~244) and ensure the
Hungarian string reflects the same subscription state (past-tense/subscribed)
rather than a different action/state; change it to the correct Hungarian
past-tense word for "subscribed" so the meaning matches the English key.

In `@ghost/i18n/locales/lt/portal.json`:
- Line 174: The translation for the key "Signup error: Invalid link. <a>Click
here to retry</a>" is missing the period before the retry link; update the
Lithuanian value so it preserves the two-sentence structure by placing a period
at the end of the first sentence immediately before the <a> tag (i.e., ensure
"Registracijos klaida: negaliojanti nuoroda." is followed by a space and then
the <a>... link text).

In `@ghost/i18n/locales/pt/portal.json`:
- Line 58: The Portuguese translation for the key "Could not sign in. Login link
expired. <a>Click here to retry</a>" uses the register term "registar" but
should use a sign-in term; update the value to use a sign-in phrase (e.g.,
replace "Não foi possível registar" with "Não foi possível iniciar sessão" or
"Não foi possível entrar") while preserving the rest of the string and the HTML
anchor (<a>...</a>) so the key and markup remain unchanged.

---

Nitpick comments:
In `@apps/portal/src/components/notification.js`:
- Around line 52-73: The branches handling type === 'signup' and type ===
'signup-paid' (and their success/error counterparts around lines 86-107) are
duplicated; consolidate them by combining the checks into a single condition
(e.g., types.includes('signup') or /^(signup(-paid)?)$/) inside the notification
rendering logic in the Notification component (or the function rendering these
branches) and reuse the same JSX/Interpolate mapping and string call (t('You\'ve
successfully subscribed to <strong>{siteTitle}</strong>', {siteTitle:
context.site.title})) so the success and error render blocks are implemented
once and handle both 'signup' and 'signup-paid'.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d97d8a2b-98e3-4681-940e-5638d13c64be

📥 Commits

Reviewing files that changed from the base of the PR and between ee2f52f and 3bc57d0.

📒 Files selected for processing (65)
  • apps/portal/package.json
  • apps/portal/src/components/notification.js
  • ghost/i18n/locales/af/portal.json
  • ghost/i18n/locales/ar/portal.json
  • ghost/i18n/locales/bg/portal.json
  • ghost/i18n/locales/bn/portal.json
  • ghost/i18n/locales/bs/portal.json
  • ghost/i18n/locales/ca/portal.json
  • ghost/i18n/locales/context.json
  • ghost/i18n/locales/cs/portal.json
  • ghost/i18n/locales/da/portal.json
  • ghost/i18n/locales/de-CH/portal.json
  • ghost/i18n/locales/de/portal.json
  • ghost/i18n/locales/el/portal.json
  • ghost/i18n/locales/en/portal.json
  • ghost/i18n/locales/eo/portal.json
  • ghost/i18n/locales/es/portal.json
  • ghost/i18n/locales/et/portal.json
  • ghost/i18n/locales/eu/portal.json
  • ghost/i18n/locales/fa/portal.json
  • ghost/i18n/locales/fi/portal.json
  • ghost/i18n/locales/fr/portal.json
  • ghost/i18n/locales/gd/portal.json
  • ghost/i18n/locales/he/portal.json
  • ghost/i18n/locales/hi/portal.json
  • ghost/i18n/locales/hr/portal.json
  • ghost/i18n/locales/hu/portal.json
  • ghost/i18n/locales/id/portal.json
  • ghost/i18n/locales/is/portal.json
  • ghost/i18n/locales/it/portal.json
  • ghost/i18n/locales/ja/portal.json
  • ghost/i18n/locales/ko/portal.json
  • ghost/i18n/locales/kz/portal.json
  • ghost/i18n/locales/lt/portal.json
  • ghost/i18n/locales/lv/portal.json
  • ghost/i18n/locales/mk/portal.json
  • ghost/i18n/locales/mn/portal.json
  • ghost/i18n/locales/ms/portal.json
  • ghost/i18n/locales/nb/portal.json
  • ghost/i18n/locales/ne/portal.json
  • ghost/i18n/locales/nl/portal.json
  • ghost/i18n/locales/nn/portal.json
  • ghost/i18n/locales/pa/portal.json
  • ghost/i18n/locales/pl/portal.json
  • ghost/i18n/locales/pt-BR/portal.json
  • ghost/i18n/locales/pt/portal.json
  • ghost/i18n/locales/ro/portal.json
  • ghost/i18n/locales/ru/portal.json
  • ghost/i18n/locales/si/portal.json
  • ghost/i18n/locales/sk/portal.json
  • ghost/i18n/locales/sl/portal.json
  • ghost/i18n/locales/sq/portal.json
  • ghost/i18n/locales/sr-Cyrl/portal.json
  • ghost/i18n/locales/sr/portal.json
  • ghost/i18n/locales/sv/portal.json
  • ghost/i18n/locales/sw/portal.json
  • ghost/i18n/locales/ta/portal.json
  • ghost/i18n/locales/th/portal.json
  • ghost/i18n/locales/tr/portal.json
  • ghost/i18n/locales/uk/portal.json
  • ghost/i18n/locales/ur/portal.json
  • ghost/i18n/locales/uz/portal.json
  • ghost/i18n/locales/vi/portal.json
  • ghost/i18n/locales/zh-Hant/portal.json
  • ghost/i18n/locales/zh/portal.json
✅ Files skipped from review due to trivial changes (11)
  • apps/portal/package.json
  • ghost/i18n/locales/sv/portal.json
  • ghost/i18n/locales/bn/portal.json
  • ghost/i18n/locales/ja/portal.json
  • ghost/i18n/locales/ms/portal.json
  • ghost/i18n/locales/ko/portal.json
  • ghost/i18n/locales/si/portal.json
  • ghost/i18n/locales/uk/portal.json
  • ghost/i18n/locales/is/portal.json
  • ghost/i18n/locales/el/portal.json
  • ghost/i18n/locales/bs/portal.json
🚧 Files skipped from review as they are similar to previous changes (33)
  • ghost/i18n/locales/ro/portal.json
  • ghost/i18n/locales/zh-Hant/portal.json
  • ghost/i18n/locales/sw/portal.json
  • ghost/i18n/locales/ne/portal.json
  • ghost/i18n/locales/nn/portal.json
  • ghost/i18n/locales/it/portal.json
  • ghost/i18n/locales/eu/portal.json
  • ghost/i18n/locales/mk/portal.json
  • ghost/i18n/locales/af/portal.json
  • ghost/i18n/locales/hi/portal.json
  • ghost/i18n/locales/bg/portal.json
  • ghost/i18n/locales/ur/portal.json
  • ghost/i18n/locales/pl/portal.json
  • ghost/i18n/locales/sq/portal.json
  • ghost/i18n/locales/vi/portal.json
  • ghost/i18n/locales/de/portal.json
  • ghost/i18n/locales/tr/portal.json
  • ghost/i18n/locales/da/portal.json
  • ghost/i18n/locales/de-CH/portal.json
  • ghost/i18n/locales/hr/portal.json
  • ghost/i18n/locales/ca/portal.json
  • ghost/i18n/locales/ar/portal.json
  • ghost/i18n/locales/sk/portal.json
  • ghost/i18n/locales/nl/portal.json
  • ghost/i18n/locales/kz/portal.json
  • ghost/i18n/locales/sr/portal.json
  • ghost/i18n/locales/fr/portal.json
  • ghost/i18n/locales/ru/portal.json
  • ghost/i18n/locales/en/portal.json
  • ghost/i18n/locales/pa/portal.json
  • ghost/i18n/locales/uz/portal.json
  • ghost/i18n/locales/context.json
  • ghost/i18n/locales/fi/portal.json

"Sign out": "Sair",
"Sign up": "Cadastrar",
"Signup error: Invalid link": "Erro de inscrição: link inválido",
"Signup error: Invalid link. <a>Click here to retry</a>": "Erro de inscrição: link inválido <a>Clique aqui para tentar novamente</a>",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add a period before the retry link.

Line 174 should keep sentence separation before <a>.

✏️ Proposed fix
-    "Signup error: Invalid link. <a>Click here to retry</a>": "Erro de inscrição: link inválido <a>Clique aqui para tentar novamente</a>",
+    "Signup error: Invalid link. <a>Click here to retry</a>": "Erro de inscrição: link inválido. <a>Clique aqui para tentar novamente</a>",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"Signup error: Invalid link. <a>Click here to retry</a>": "Erro de inscrição: link inválido <a>Clique aqui para tentar novamente</a>",
"Signup error: Invalid link. <a>Click here to retry</a>": "Erro de inscrição: link inválido. <a>Clique aqui para tentar novamente</a>",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/pt-BR/portal.json` at line 174, Update the translation
string key "Signup error: Invalid link. <a>Click here to retry</a>" so the
Portuguese value inserts a period before the anchor tag; edit the value for that
key (currently "Erro de inscrição: link inválido <a>Clique aqui para tentar
novamente</a>") to include a period separating the sentence from the <a>
element, preserving the same text and HTML tag.

"Sign out": "Odjava",
"Sign up": "Registracija",
"Signup error: Invalid link": "Napaka pri registraciji: Neveljavna povezava",
"Signup error: Invalid link. <a>Click here to retry</a>": "Napaka pri registraciji: Neveljavna povezava <a>Kliknite tukaj, da poskusite znova</a>",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Insert sentence punctuation before the retry link.

Line 174 is missing a period before <a>.

✏️ Proposed fix
-    "Signup error: Invalid link. <a>Click here to retry</a>": "Napaka pri registraciji: Neveljavna povezava <a>Kliknite tukaj, da poskusite znova</a>",
+    "Signup error: Invalid link. <a>Click here to retry</a>": "Napaka pri registraciji: Neveljavna povezava. <a>Kliknite tukaj, da poskusite znova</a>",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"Signup error: Invalid link. <a>Click here to retry</a>": "Napaka pri registraciji: Neveljavna povezava <a>Kliknite tukaj, da poskusite znova</a>",
"Signup error: Invalid link. <a>Click here to retry</a>": "Napaka pri registraciji: Neveljavna povezava. <a>Kliknite tukaj, da poskusite znova</a>",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/sl/portal.json` at line 174, The translation string for
the key "Signup error: Invalid link. <a>Click here to retry</a>" is missing a
period before the retry link; update the Slovenian value so there is a
sentence-ending period before the <a> tag (e.g., change "Neveljavna povezava
<a>..." to "Neveljavna povezava. <a>...") ensuring spacing and the <a> tag
remain intact in the value.

"Sign out": "Одјавите се",
"Sign up": "Региструјте се",
"Signup error: Invalid link": "Грешка при регистрацији: Невалидан линк",
"Signup error: Invalid link. <a>Click here to retry</a>": "Грешка при регистрацији: Невалидан линк <a>Кликните овде да покушате поново</a>",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add sentence punctuation before the retry link.

Line 174 is missing a period before <a>.

✏️ Proposed fix
-    "Signup error: Invalid link. <a>Click here to retry</a>": "Грешка при регистрацији: Невалидан линк <a>Кликните овде да покушате поново</a>",
+    "Signup error: Invalid link. <a>Click here to retry</a>": "Грешка при регистрацији: Невалидан линк. <a>Кликните овде да покушате поново</a>",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"Signup error: Invalid link. <a>Click here to retry</a>": "Грешка при регистрацији: Невалидан линк <a>Кликните овде да покушате поново</a>",
"Signup error: Invalid link. <a>Click here to retry</a>": "Грешка при регистрацији: Невалидан линк. <a>Кликните овде да покушате поново</a>",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/sr-Cyrl/portal.json` at line 174, The translation string
key "Signup error: Invalid link. <a>Click here to retry</a>" in portal.json is
missing a period before the anchor; update the Serbian Cyrillic value for that
key (the string starting with "Грешка при регистрацији: Невалидан линк <a>...")
to include a sentence-ending period before the <a> tag so it reads "...Невалидан
линк. <a>Кликните овде да покушате поново</a>" ensuring punctuation is added
immediately before the anchor tag.

@rob-ghost rob-ghost force-pushed the fix/portal-fragment-translation-keys branch from 3bc57d0 to bd9b631 Compare April 7, 2026 10:47
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud bot commented Apr 7, 2026

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

♻️ Duplicate comments (3)
ghost/i18n/locales/pt/portal.json (1)

58-58: ⚠️ Potential issue | 🟡 Minor

Use the login verb here, not the signup verb.

Line 58 says registar, but the same file translates Sign in as Entrar on Line 171. That tells Portuguese users the wrong action failed.

📝 Suggested fix
-    "Could not sign in. Login link expired. <br /><a>Click here to retry</a>": "Não foi possível registar. O link de login expirou. <br /><a>Clique aqui para tentar novamente</a>",
+    "Could not sign in. Login link expired. <br /><a>Click here to retry</a>": "Não foi possível entrar. O link de login expirou. <br /><a>Clique aqui para tentar novamente</a>",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/pt/portal.json` at line 58, The translation for the key
"Could not sign in. Login link expired. <br /><a>Click here to retry</a>" uses
the signup verb "registar" but should use the sign-in verb "entrar"; update the
Portuguese value to use "Não foi possível entrar. O link de login expirou. <br
/><a>Clique aqui para tentar novamente</a>" so it matches the existing "Sign in"
-> "Entrar" terminology and semantics.
ghost/i18n/locales/gd/portal.json (1)

174-174: ⚠️ Potential issue | 🟡 Minor

Add the missing sentence separator before the retry link.

Line 174 still attaches the retry CTA directly to the error text.

📝 Suggested fix
-    "Signup error: Invalid link.<br /><a>Click here to retry</a>": "Mearachd: Ceangal mì-dhligheach <br /><a>Briog an seo gus feuchainn a-rithist</a>",
+    "Signup error: Invalid link.<br /><a>Click here to retry</a>": "Mearachd: Ceangal mì-dhligheach. <br /><a>Briog an seo gus feuchainn a-rithist</a>",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/gd/portal.json` at line 174, The Gaelic translation value
for the key "Signup error: Invalid link.<br /><a>Click here to retry</a>" is
missing a sentence separator before the retry link; update the translated string
value (currently "Mearachd: Ceangal mì-dhligheach <br /><a>Briog an seo gus
feuchainn a-rithist</a>") to include a sentence terminator (e.g., a period)
before the <br /> so it reads "Mearachd: Ceangal mì-dhligheach. <br /><a>Briog
an seo gus feuchainn a-rithist</a>".
ghost/i18n/locales/pt-BR/portal.json (1)

174-174: ⚠️ Potential issue | 🟡 Minor

Add sentence punctuation before the retry link in pt-BR.

Line 174 still reads as a run-on before <br />; a period improves readability and consistency.

✏️ Proposed fix
-    "Signup error: Invalid link.<br /><a>Click here to retry</a>": "Erro de inscrição: link inválido <br /><a>Clique aqui para tentar novamente</a>",
+    "Signup error: Invalid link.<br /><a>Click here to retry</a>": "Erro de inscrição: link inválido. <br /><a>Clique aqui para tentar novamente</a>",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/pt-BR/portal.json` at line 174, The Portuguese translation
for the key "Signup error: Invalid link.<br /><a>Click here to retry</a>" is
missing a sentence-ending period before the retry link; update the value for
that JSON key so it ends the sentence with a period immediately before the <br
/> (i.e., "Erro de inscrição: link inválido." followed by the existing <br
/><a>... tag) to improve punctuation and readability.
🧹 Nitpick comments (1)
apps/portal/src/components/notification.js (1)

52-73: Consider collapsing duplicated signup/signup-paid branches.

The success and error blocks for signup and signup-paid are identical and can be merged to reduce repetition.

♻️ Proposed refactor
-    } else if (type === 'signup' && status === 'success') {
+    } else if ((type === 'signup' || type === 'signup-paid') && status === 'success') {
         return (
             <p>
                 <Interpolate
                     mapping={{
                         strong: <strong />
                     }}
                     string={t('You\'ve successfully subscribed to <br /><strong>{siteTitle}</strong>', {siteTitle: context.site.title})}
                 />
             </p>
         );
-    } else if (type === 'signup-paid' && status === 'success') {
-        return (
-            <p>
-                <Interpolate
-                    mapping={{
-                        strong: <strong />
-                    }}
-                    string={t('You\'ve successfully subscribed to <br /><strong>{siteTitle}</strong>', {siteTitle: context.site.title})}
-                />
-            </p>
-        );
     } else if (type === 'updateEmail' && status === 'success') {
@@
-    } else if (type === 'signup' && status === 'error') {
+    } else if ((type === 'signup' || type === 'signup-paid') && status === 'error') {
         return (
             <p>
                 <Interpolate
                     mapping={{
                         a: <a href={singupPortalLink} target="_parent" />
                     }}
                     string={t('Signup error: Invalid link.<br /><a>Click here to retry</a>')}
                 />
             </p>
         );
-    } else if (type === 'signup-paid' && status === 'error') {
-        return (
-            <p>
-                <Interpolate
-                    mapping={{
-                        a: <a href={singupPortalLink} target="_parent" />
-                    }}
-                    string={t('Signup error: Invalid link.<br /><a>Click here to retry</a>')}
-                />
-            </p>
-        );
     } else if (type === 'stripe:checkout' && status === 'success') {

Also applies to: 86-107

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/portal/src/components/notification.js` around lines 52 - 73, The
branches handling notification types 'signup' and 'signup-paid' are duplicated
for both success and error cases; update the conditional logic in the
notification component (where type is checked) to combine those cases—e.g.,
replace separate checks for type === 'signup' and type === 'signup-paid' with a
single combined condition ((type === 'signup' || type === 'signup-paid') &&
status === 'success') and similarly for the error branch—then reuse the same JSX
(the Interpolate element with mapping and t(..., {siteTitle:
context.site.title})) to eliminate repetition while preserving behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ghost/i18n/locales/ca/portal.json`:
- Line 174: The translated value for the key "Signup error: Invalid link.<br
/><a>Click here to retry</a>" in portal.json lacks a sentence separator before
the retry CTA; update the Catalan translation ("Error de registre: Enllaç no
vàlid <br /><a>Fes clic aquí per tornar-ho a intentar</a>") to include a proper
sentence separator (e.g., a period) before the <br /><a> tag so it reads as a
complete sentence followed by the CTA.

In `@ghost/i18n/locales/et/portal.json`:
- Line 174: The Estonian translation value for the key "Signup error: Invalid
link.<br /><a>Click here to retry</a>" is missing a sentence separator before
the retry CTA; update the translated string (the value for that key) to insert a
period (and a space) after "Vigane link" so it reads "...Vigane link. <br
/><a>Klõpsake siia, et uuesti proovida</a>" ensuring proper punctuation and
spacing.

In `@ghost/i18n/locales/he/portal.json`:
- Line 58: The translation dropped the sentence-final period before the retry
CTA so the CTA reads attached to the preceding sentence; restore the full stop
immediately before the <br /> in the portal string key "Could not sign in. Login
link expired. <br /><a>Click here to retry</a>" and its Hebrew value (and the
other identical occurrence around line 174) so both the source key and
translated string include the period just before <br />.

In `@ghost/i18n/locales/it/portal.json`:
- Line 174: The translation value for the signup invalid-link key uses "Errore
di accesso" (sign-in) but should reflect signup; update the value for the key
"Signup error: Invalid link.<br /><a>Click here to retry</a>" to use the correct
signup wording — e.g., replace "Errore di accesso" with "Errore di
registrazione" (or "Errore di iscrizione") and keep the rest of the Italian text
and HTML intact so the key reads like "Errore di registrazione: link invalido
<br /><a>Clicca qui per riprovare</a>".

In `@ghost/i18n/locales/ms/portal.json`:
- Line 174: The Malay translation key currently concatenates the error and CTA
without a sentence separator; update the JSON value for the key "Signup error:
Invalid link.<br /><a>Click here to retry</a>" so it mirrors the source by
adding a sentence-ending period and a space before the <br /> tag (i.e., change
"Pautan tidak sah <br /><a>..." to "Pautan tidak sah. <br /><a>...") while
keeping the existing Malay CTA text "Klik di sini untuk cuba semula".

In `@ghost/i18n/locales/pl/portal.json`:
- Line 58: Update the Polish translation for the retry CTA in the entries whose
English keys start with "Could not sign in. Login link expired. <br /><a>Click
here to retry</a>" and the second identical entry so the link text uses a
correct "retry" phrasing (replace "potwierdzić" with "spróbować ponownie" or
"ponownie" in the <a> tag) — e.g., change the current "<a>Kliknij tu żeby
potwierdzić</a>" to "<a>Kliknij tu, aby spróbować ponownie</a>" (apply the same
replacement for both occurrences).

In `@ghost/i18n/locales/pt/portal.json`:
- Line 174: The translated value for the key "Signup error: Invalid link.<br
/><a>Click here to retry</a>" currently lacks a sentence separator before the
retry CTA; update the Portuguese string "Erro de inscrição: ligação inválida <br
/><a>Clique aqui para tentar novamente</a>" to include a period and a space
before the line break so it reads "Erro de inscrição: ligação inválida. <br
/><a>Clique aqui para tentar novamente</a>" ensuring proper sentence separation
and spacing.

In `@ghost/i18n/locales/ro/portal.json`:
- Line 174: The Romanian translation for the key "Signup error: Invalid link.<br
/><a>Click here to retry</a>" is missing the sentence separator before the retry
link; update the value for that key in portal.json by inserting the missing
period (sentence separator) before the <br /> so the error sentence ends
properly before the retry CTA (look for the exact string key "Signup error:
Invalid link.<br /><a>Click here to retry</a>" to locate the line).

---

Duplicate comments:
In `@ghost/i18n/locales/gd/portal.json`:
- Line 174: The Gaelic translation value for the key "Signup error: Invalid
link.<br /><a>Click here to retry</a>" is missing a sentence separator before
the retry link; update the translated string value (currently "Mearachd: Ceangal
mì-dhligheach <br /><a>Briog an seo gus feuchainn a-rithist</a>") to include a
sentence terminator (e.g., a period) before the <br /> so it reads "Mearachd:
Ceangal mì-dhligheach. <br /><a>Briog an seo gus feuchainn a-rithist</a>".

In `@ghost/i18n/locales/pt-BR/portal.json`:
- Line 174: The Portuguese translation for the key "Signup error: Invalid
link.<br /><a>Click here to retry</a>" is missing a sentence-ending period
before the retry link; update the value for that JSON key so it ends the
sentence with a period immediately before the <br /> (i.e., "Erro de inscrição:
link inválido." followed by the existing <br /><a>... tag) to improve
punctuation and readability.

In `@ghost/i18n/locales/pt/portal.json`:
- Line 58: The translation for the key "Could not sign in. Login link expired.
<br /><a>Click here to retry</a>" uses the signup verb "registar" but should use
the sign-in verb "entrar"; update the Portuguese value to use "Não foi possível
entrar. O link de login expirou. <br /><a>Clique aqui para tentar novamente</a>"
so it matches the existing "Sign in" -> "Entrar" terminology and semantics.

---

Nitpick comments:
In `@apps/portal/src/components/notification.js`:
- Around line 52-73: The branches handling notification types 'signup' and
'signup-paid' are duplicated for both success and error cases; update the
conditional logic in the notification component (where type is checked) to
combine those cases—e.g., replace separate checks for type === 'signup' and type
=== 'signup-paid' with a single combined condition ((type === 'signup' || type
=== 'signup-paid') && status === 'success') and similarly for the error
branch—then reuse the same JSX (the Interpolate element with mapping and t(...,
{siteTitle: context.site.title})) to eliminate repetition while preserving
behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8f878c5e-7545-4617-a2d3-3f2321a49bc1

📥 Commits

Reviewing files that changed from the base of the PR and between 3bc57d0 and bd9b631.

📒 Files selected for processing (65)
  • apps/portal/package.json
  • apps/portal/src/components/notification.js
  • ghost/i18n/locales/af/portal.json
  • ghost/i18n/locales/ar/portal.json
  • ghost/i18n/locales/bg/portal.json
  • ghost/i18n/locales/bn/portal.json
  • ghost/i18n/locales/bs/portal.json
  • ghost/i18n/locales/ca/portal.json
  • ghost/i18n/locales/context.json
  • ghost/i18n/locales/cs/portal.json
  • ghost/i18n/locales/da/portal.json
  • ghost/i18n/locales/de-CH/portal.json
  • ghost/i18n/locales/de/portal.json
  • ghost/i18n/locales/el/portal.json
  • ghost/i18n/locales/en/portal.json
  • ghost/i18n/locales/eo/portal.json
  • ghost/i18n/locales/es/portal.json
  • ghost/i18n/locales/et/portal.json
  • ghost/i18n/locales/eu/portal.json
  • ghost/i18n/locales/fa/portal.json
  • ghost/i18n/locales/fi/portal.json
  • ghost/i18n/locales/fr/portal.json
  • ghost/i18n/locales/gd/portal.json
  • ghost/i18n/locales/he/portal.json
  • ghost/i18n/locales/hi/portal.json
  • ghost/i18n/locales/hr/portal.json
  • ghost/i18n/locales/hu/portal.json
  • ghost/i18n/locales/id/portal.json
  • ghost/i18n/locales/is/portal.json
  • ghost/i18n/locales/it/portal.json
  • ghost/i18n/locales/ja/portal.json
  • ghost/i18n/locales/ko/portal.json
  • ghost/i18n/locales/kz/portal.json
  • ghost/i18n/locales/lt/portal.json
  • ghost/i18n/locales/lv/portal.json
  • ghost/i18n/locales/mk/portal.json
  • ghost/i18n/locales/mn/portal.json
  • ghost/i18n/locales/ms/portal.json
  • ghost/i18n/locales/nb/portal.json
  • ghost/i18n/locales/ne/portal.json
  • ghost/i18n/locales/nl/portal.json
  • ghost/i18n/locales/nn/portal.json
  • ghost/i18n/locales/pa/portal.json
  • ghost/i18n/locales/pl/portal.json
  • ghost/i18n/locales/pt-BR/portal.json
  • ghost/i18n/locales/pt/portal.json
  • ghost/i18n/locales/ro/portal.json
  • ghost/i18n/locales/ru/portal.json
  • ghost/i18n/locales/si/portal.json
  • ghost/i18n/locales/sk/portal.json
  • ghost/i18n/locales/sl/portal.json
  • ghost/i18n/locales/sq/portal.json
  • ghost/i18n/locales/sr-Cyrl/portal.json
  • ghost/i18n/locales/sr/portal.json
  • ghost/i18n/locales/sv/portal.json
  • ghost/i18n/locales/sw/portal.json
  • ghost/i18n/locales/ta/portal.json
  • ghost/i18n/locales/th/portal.json
  • ghost/i18n/locales/tr/portal.json
  • ghost/i18n/locales/uk/portal.json
  • ghost/i18n/locales/ur/portal.json
  • ghost/i18n/locales/uz/portal.json
  • ghost/i18n/locales/vi/portal.json
  • ghost/i18n/locales/zh-Hant/portal.json
  • ghost/i18n/locales/zh/portal.json
✅ Files skipped from review due to trivial changes (5)
  • ghost/i18n/locales/ja/portal.json
  • ghost/i18n/locales/uk/portal.json
  • ghost/i18n/locales/lt/portal.json
  • ghost/i18n/locales/es/portal.json
  • ghost/i18n/locales/si/portal.json
🚧 Files skipped from review as they are similar to previous changes (34)
  • apps/portal/package.json
  • ghost/i18n/locales/lv/portal.json
  • ghost/i18n/locales/fr/portal.json
  • ghost/i18n/locales/zh-Hant/portal.json
  • ghost/i18n/locales/eo/portal.json
  • ghost/i18n/locales/pa/portal.json
  • ghost/i18n/locales/tr/portal.json
  • ghost/i18n/locales/ur/portal.json
  • ghost/i18n/locales/nb/portal.json
  • ghost/i18n/locales/da/portal.json
  • ghost/i18n/locales/sr/portal.json
  • ghost/i18n/locales/sr-Cyrl/portal.json
  • ghost/i18n/locales/en/portal.json
  • ghost/i18n/locales/mk/portal.json
  • ghost/i18n/locales/ne/portal.json
  • ghost/i18n/locales/eu/portal.json
  • ghost/i18n/locales/nn/portal.json
  • ghost/i18n/locales/uz/portal.json
  • ghost/i18n/locales/hi/portal.json
  • ghost/i18n/locales/nl/portal.json
  • ghost/i18n/locales/hr/portal.json
  • ghost/i18n/locales/fa/portal.json
  • ghost/i18n/locales/sw/portal.json
  • ghost/i18n/locales/de-CH/portal.json
  • ghost/i18n/locales/ru/portal.json
  • ghost/i18n/locales/vi/portal.json
  • ghost/i18n/locales/bg/portal.json
  • ghost/i18n/locales/kz/portal.json
  • ghost/i18n/locales/af/portal.json
  • ghost/i18n/locales/el/portal.json
  • ghost/i18n/locales/ta/portal.json
  • ghost/i18n/locales/ar/portal.json
  • ghost/i18n/locales/sv/portal.json
  • ghost/i18n/locales/sk/portal.json

"Sign out": "Tanca sessió",
"Sign up": "Registra't",
"Signup error: Invalid link": "Error de registre: Enllaç no vàlid",
"Signup error: Invalid link.<br /><a>Click here to retry</a>": "Error de registre: Enllaç no vàlid <br /><a>Fes clic aquí per tornar-ho a intentar</a>",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add the missing sentence separator before the retry link.

Line 174 currently reads as one continuous phrase instead of a sentence plus CTA.

📝 Suggested fix
-    "Signup error: Invalid link.<br /><a>Click here to retry</a>": "Error de registre: Enllaç no vàlid <br /><a>Fes clic aquí per tornar-ho a intentar</a>",
+    "Signup error: Invalid link.<br /><a>Click here to retry</a>": "Error de registre: Enllaç no vàlid. <br /><a>Fes clic aquí per tornar-ho a intentar</a>",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"Signup error: Invalid link.<br /><a>Click here to retry</a>": "Error de registre: Enllaç no vàlid <br /><a>Fes clic aquí per tornar-ho a intentar</a>",
"Signup error: Invalid link.<br /><a>Click here to retry</a>": "Error de registre: Enllaç no vàlid. <br /><a>Fes clic aquí per tornar-ho a intentar</a>",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/ca/portal.json` at line 174, The translated value for the
key "Signup error: Invalid link.<br /><a>Click here to retry</a>" in portal.json
lacks a sentence separator before the retry CTA; update the Catalan translation
("Error de registre: Enllaç no vàlid <br /><a>Fes clic aquí per tornar-ho a
intentar</a>") to include a proper sentence separator (e.g., a period) before
the <br /><a> tag so it reads as a complete sentence followed by the CTA.

"Sign out": "Logi välja",
"Sign up": "Registreeru",
"Signup error: Invalid link": "Registreerimise viga: Vigane link",
"Signup error: Invalid link.<br /><a>Click here to retry</a>": "Registreerimise viga: Vigane link <br /><a>Klõpsake siia, et uuesti proovida</a>",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add the missing sentence separator before the retry link.

Line 174 currently reads as one continuous phrase instead of an error sentence followed by the retry CTA.

📝 Suggested fix
-    "Signup error: Invalid link.<br /><a>Click here to retry</a>": "Registreerimise viga: Vigane link <br /><a>Klõpsake siia, et uuesti proovida</a>",
+    "Signup error: Invalid link.<br /><a>Click here to retry</a>": "Registreerimise viga: Vigane link. <br /><a>Klõpsake siia, et uuesti proovida</a>",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"Signup error: Invalid link.<br /><a>Click here to retry</a>": "Registreerimise viga: Vigane link <br /><a>Klõpsake siia, et uuesti proovida</a>",
"Signup error: Invalid link.<br /><a>Click here to retry</a>": "Registreerimise viga: Vigane link. <br /><a>Klõpsake siia, et uuesti proovida</a>",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/et/portal.json` at line 174, The Estonian translation
value for the key "Signup error: Invalid link.<br /><a>Click here to retry</a>"
is missing a sentence separator before the retry CTA; update the translated
string (the value for that key) to insert a period (and a space) after "Vigane
link" so it reads "...Vigane link. <br /><a>Klõpsake siia, et uuesti
proovida</a>" ensuring proper punctuation and spacing.

"Could not create Stripe billing portal session": "",
"Could not create Stripe checkout session": "לא ניתן ליצור סשן של קופה של סטרייפ",
"Could not sign in. Login link expired.": "כניסה נכשלה. פג תוקפו של לינק הכניסה",
"Could not sign in. Login link expired. <br /><a>Click here to retry</a>": "כניסה נכשלה. פג תוקפו של לינק הכניסה <br /><a>לחצו כאן כדי לנסות שוב</a>",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Restore the missing sentence separators before the retry CTA.

Line 58 and Line 174 both drop the full stop before <br />, so the retry action reads attached to the preceding error message.

📝 Suggested fix
-    "Could not sign in. Login link expired. <br /><a>Click here to retry</a>": "כניסה נכשלה. פג תוקפו של לינק הכניסה <br /><a>לחצו כאן כדי לנסות שוב</a>",
+    "Could not sign in. Login link expired. <br /><a>Click here to retry</a>": "כניסה נכשלה. פג תוקפו של לינק הכניסה. <br /><a>לחצו כאן כדי לנסות שוב</a>",
...
-    "Signup error: Invalid link.<br /><a>Click here to retry</a>": "שגיאת הרשמה: לינק לא תקין <br /><a>לחצו כאן כדי לנסות שוב</a>",
+    "Signup error: Invalid link.<br /><a>Click here to retry</a>": "שגיאת הרשמה: לינק לא תקין. <br /><a>לחצו כאן כדי לנסות שוב</a>",

Also applies to: 174-174

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/he/portal.json` at line 58, The translation dropped the
sentence-final period before the retry CTA so the CTA reads attached to the
preceding sentence; restore the full stop immediately before the <br /> in the
portal string key "Could not sign in. Login link expired. <br /><a>Click here to
retry</a>" and its Hebrew value (and the other identical occurrence around line
174) so both the source key and translated string include the period just before
<br />.

"Sign out": "Esci",
"Sign up": "Iscriviti",
"Signup error: Invalid link": "Errore di accesso: link invalido",
"Signup error: Invalid link.<br /><a>Click here to retry</a>": "Errore di accesso: link invalido <br /><a>Clicca qui per riprovare</a>",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Align Italian signup error wording with the actual flow.

Line 174 says “Errore di accesso” (sign-in), but this key is for signup invalid-link errors.

✏️ Proposed fix
-    "Signup error: Invalid link.<br /><a>Click here to retry</a>": "Errore di accesso: link invalido <br /><a>Clicca qui per riprovare</a>",
+    "Signup error: Invalid link.<br /><a>Click here to retry</a>": "Errore di registrazione: link non valido. <br /><a>Clicca qui per riprovare</a>",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"Signup error: Invalid link.<br /><a>Click here to retry</a>": "Errore di accesso: link invalido <br /><a>Clicca qui per riprovare</a>",
"Signup error: Invalid link.<br /><a>Click here to retry</a>": "Errore di registrazione: link non valido. <br /><a>Clicca qui per riprovare</a>",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/it/portal.json` at line 174, The translation value for the
signup invalid-link key uses "Errore di accesso" (sign-in) but should reflect
signup; update the value for the key "Signup error: Invalid link.<br /><a>Click
here to retry</a>" to use the correct signup wording — e.g., replace "Errore di
accesso" with "Errore di registrazione" (or "Errore di iscrizione") and keep the
rest of the Italian text and HTML intact so the key reads like "Errore di
registrazione: link invalido <br /><a>Clicca qui per riprovare</a>".

"Sign out": "Log keluar",
"Sign up": "Daftar",
"Signup error: Invalid link": "Ralat daftar: Pautan tidak sah",
"Signup error: Invalid link.<br /><a>Click here to retry</a>": "Ralat daftar: Pautan tidak sah <br /><a>Klik di sini untuk cuba semula</a>",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add the missing sentence separator before the retry link.

Line 174 currently turns the error and the CTA into one run-on string. Mirror the source key's split sentence here as well.

📝 Suggested fix
-    "Signup error: Invalid link.<br /><a>Click here to retry</a>": "Ralat daftar: Pautan tidak sah <br /><a>Klik di sini untuk cuba semula</a>",
+    "Signup error: Invalid link.<br /><a>Click here to retry</a>": "Ralat daftar: Pautan tidak sah. <br /><a>Klik di sini untuk cuba semula</a>",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"Signup error: Invalid link.<br /><a>Click here to retry</a>": "Ralat daftar: Pautan tidak sah <br /><a>Klik di sini untuk cuba semula</a>",
"Signup error: Invalid link.<br /><a>Click here to retry</a>": "Ralat daftar: Pautan tidak sah. <br /><a>Klik di sini untuk cuba semula</a>",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/ms/portal.json` at line 174, The Malay translation key
currently concatenates the error and CTA without a sentence separator; update
the JSON value for the key "Signup error: Invalid link.<br /><a>Click here to
retry</a>" so it mirrors the source by adding a sentence-ending period and a
space before the <br /> tag (i.e., change "Pautan tidak sah <br /><a>..." to
"Pautan tidak sah. <br /><a>...") while keeping the existing Malay CTA text
"Klik di sini untuk cuba semula".

"Could not create Stripe billing portal session": "",
"Could not create Stripe checkout session": "Nie można utworzyć sesji rozliczeniowej Stripe",
"Could not sign in. Login link expired.": "Nie można się zalogować, ponieważ link do logowania wygasł.",
"Could not sign in. Login link expired. <br /><a>Click here to retry</a>": "Nie można się zalogować, ponieważ link do logowania wygasł. <br /><a>Kliknij tu żeby potwierdzić</a>",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix retry CTA wording in Polish translation.

Line 58 and Line 174 currently translate “retry” as “potwierdzić” (“confirm”), which changes the action meaning.

✏️ Proposed fix
-    "Could not sign in. Login link expired. <br /><a>Click here to retry</a>": "Nie można się zalogować, ponieważ link do logowania wygasł. <br /><a>Kliknij tu żeby potwierdzić</a>",
+    "Could not sign in. Login link expired. <br /><a>Click here to retry</a>": "Nie można się zalogować, ponieważ link do logowania wygasł. <br /><a>Kliknij tutaj, aby spróbować ponownie</a>",

-    "Signup error: Invalid link.<br /><a>Click here to retry</a>": "Błąd rejestracji: Nieprawidłowy link <br /><a>Kliknij tu żeby potwierdzić</a>",
+    "Signup error: Invalid link.<br /><a>Click here to retry</a>": "Błąd rejestracji: Nieprawidłowy link. <br /><a>Kliknij tutaj, aby spróbować ponownie</a>",

Also applies to: 174-174

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/pl/portal.json` at line 58, Update the Polish translation
for the retry CTA in the entries whose English keys start with "Could not sign
in. Login link expired. <br /><a>Click here to retry</a>" and the second
identical entry so the link text uses a correct "retry" phrasing (replace
"potwierdzić" with "spróbować ponownie" or "ponownie" in the <a> tag) — e.g.,
change the current "<a>Kliknij tu żeby potwierdzić</a>" to "<a>Kliknij tu, aby
spróbować ponownie</a>" (apply the same replacement for both occurrences).

"Sign out": "Sair",
"Sign up": "Registar",
"Signup error: Invalid link": "Erro de inscrição: ligação inválida",
"Signup error: Invalid link.<br /><a>Click here to retry</a>": "Erro de inscrição: ligação inválida <br /><a>Clique aqui para tentar novamente</a>",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add the missing sentence separator before the retry link.

Line 174 currently reads as one continuous phrase instead of an error sentence followed by the retry CTA.

📝 Suggested fix
-    "Signup error: Invalid link.<br /><a>Click here to retry</a>": "Erro de inscrição: ligação inválida <br /><a>Clique aqui para tentar novamente</a>",
+    "Signup error: Invalid link.<br /><a>Click here to retry</a>": "Erro de inscrição: ligação inválida. <br /><a>Clique aqui para tentar novamente</a>",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"Signup error: Invalid link.<br /><a>Click here to retry</a>": "Erro de inscrição: ligação inválida <br /><a>Clique aqui para tentar novamente</a>",
"Signup error: Invalid link.<br /><a>Click here to retry</a>": "Erro de inscrição: ligação inválida. <br /><a>Clique aqui para tentar novamente</a>",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ghost/i18n/locales/pt/portal.json` at line 174, The translated value for the
key "Signup error: Invalid link.<br /><a>Click here to retry</a>" currently
lacks a sentence separator before the retry CTA; update the Portuguese string
"Erro de inscrição: ligação inválida <br /><a>Clique aqui para tentar
novamente</a>" to include a period and a space before the line break so it reads
"Erro de inscrição: ligação inválida. <br /><a>Clique aqui para tentar
novamente</a>" ensuring proper sentence separation and spacing.

"Sign out": "Deconectare",
"Sign up": "Înregistrare",
"Signup error: Invalid link": "Eroare la înregistrare: Link invalid",
"Signup error: Invalid link.<br /><a>Click here to retry</a>": "Eroare la înregistrare: Link invalid <br /><a>Clic aici pentru a reîncerca</a>",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add the missing sentence separator before the retry link.

Line 174 drops the separator before the retry CTA, so the error and action read as a single phrase.

📝 Suggested fix
-    "Signup error: Invalid link.<br /><a>Click here to retry</a>": "Eroare la înregistrare: Link invalid <br /><a>Clic aici pentru a reîncerca</a>",
+    "Signup error: Invalid link.<br /><a>Click here to retry</a>": "Eroare la înregistrare: Link invalid. <br /><a>Clic aici pentru a reîncerca</a>",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"Signup error: Invalid link.<br /><a>Click here to retry</a>": "Eroare la înregistrare: Link invalid <br /><a>Clic aici pentru a reîncerca</a>",
"Signup error: Invalid link.<br /><a>Click here to retry</a>": "Eroare la înregistrare: Link invalid. <br /><a>Clic aici pentru a reîncerca</a>",
🤖 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 174, The Romanian translation for
the key "Signup error: Invalid link.<br /><a>Click here to retry</a>" is missing
the sentence separator before the retry link; update the value for that key in
portal.json by inserting the missing period (sentence separator) before the <br
/> so the error sentence ends properly before the retry CTA (look for the exact
string key "Signup error: Invalid link.<br /><a>Click here to retry</a>" to
locate the line).

Copy link
Copy Markdown
Member

@cathysarisky cathysarisky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

THANK YOU for preserving the existing translations! 🙏
A couple comments below.

mapping={{
strong: <strong />
}}
string={t('You\'ve successfully subscribed to <br /><strong>{siteTitle}</strong>', {siteTitle: context.site.title})}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, this breaks my heuristic that a br means a new string... 😆

Is having the br necessary here? Will it survive a variety of languages (which could be adjusted by translators) and site title lengths (which cannot? Would it be better to let the browser make the decision about when to break the line? And does the layout break if a translator removes it? I'm imagining that the zh and zh-Hant translators would probably remove it, for example.


const NotificationText = ({type, status, context}) => {
const signinPortalLink = getPortalLink({page: 'signin', siteUrl: context.site.url});
const singupPortalLink = getPortalLink({page: 'signup', siteUrl: context.site.url});
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo - you meant signup, right? :) 🎵 🎵

Comment on lines +44 to +49
<Interpolate
mapping={{
a: <a href={signinPortalLink} target="_parent" />
}}
string={t('Could not sign in. Login link expired. <br /><a>Click here to retry</a>')}
/>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To play devil's advocate, the fact that there's a br might really suggest that these are two separate ideas that can be safely translated as separate strings. And then we'd keep the enforced common phrasing for "Click here to retry", which really does seem to be a separate idea.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at this with fresh eyes and I think you're right, this would revert this PR and make it a no-op so I'll close this PR

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rob-ghost - I think it's perhaps worth keeping "You've successfully subscribed to {siteTitle}". That's an improvement :)

Copy link
Copy Markdown
Member

@cathysarisky cathysarisky left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Marking as approved so that I'm not blocking you, but see comments about error in variable name and some questions about whether this swings a little too far in the other direction. :)

@rob-ghost
Copy link
Copy Markdown
Contributor Author

Closing this because the two translation keys were actually correct to be split up which makes this a no-op PR.

@rob-ghost rob-ghost closed this Apr 7, 2026
@cathysarisky
Copy link
Copy Markdown
Member

Closing this because the two translation keys were actually correct to be split up which makes this a no-op PR.

There was also this one, which might be worth keeping? https://github.com/TryGhost/Ghost/pull/27175/changes#diff-b980c9767edc8137443b5b075a307bb3bca189e537e14f1da20e9ae0e9684904R55-R59

@rob-ghost
Copy link
Copy Markdown
Contributor Author

@cathysarisky I'm putting up a new one with just that change now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants