Repository: Automattic/wp-calypso
Pull request #103147: Remove uses of `preventWidows` from `client/blocks`
Author: login: tellthemachines
Created: 2025-05-06T06:29:44Z | Merged: 2025-05-12T01:05:05Z

<!--
Link a related issue to this PR. If the PR does not immediately resolve the issue,
for example, it requires a separate deployment to production, avoid
using the "fixes" keyword and instead attach the [Status] Fix Inbound label to
the linked issue.
-->

Related to [#100475](https://github.com/Automattic/wp-calypso/issues/100475)

## Proposed Changes

* Remove use of `preventWidows()` which is a JS workaround for what `text-wrap: pretty` now does in native CSS. Given `pretty` (and `balance`) now have good browser support, we can start removing the function.
* Scope of this PR: `client/blocks`. I'm separating out parts of the codebase so PRs are easier to review.
* Note that I'm **not** removing the instance in `client/blocks/login` as that's being done in #102811 as part of a larger changeset.

## Why are these changes being made?
<!--
It's easy to see what a PR does but much harder to find out why it was made,
particularly when researching old changes in history. Record an explanation of
the motivation behind this change and how it will help.
-->

We don't need to run JS all over the place to move words about so sentences are balanced, when CSS can now do this by itself 😊 

## Testing Instructions

<!--
Add as many details as possible to help others reproduce the issue and test the fix.
"Before / After" screenshots can also be very helpful when the change is visual.
-->

See inline comments in code view for detailed instructions. 


## Pre-merge Checklist

<!--
Complete applicable items on this checklist **before** merging into trunk. Inapplicable items can be left unchecked.

Both the PR author and reviewer are responsible for ensuring the checklist is completed.
-->

- [ ] Has the general commit checklist been followed? (PCYsg-hS-p2)
- [ ] [Have you written new tests](https://wpcalypso.wordpress.com/devdocs/docs/testing/index.md) for your changes?
- [ ] Have you tested the feature in Simple (P9HQHe-k8-p2), Atomic (P9HQHe-jW-p2), and self-hosted Jetpack sites (PCYsg-g6b-p2)?
- [ ] Have you checked for TypeScript, React or other console errors?
- [ ] Have you used memoizing on expensive computations? More info in [Memoizing with create-selector](https://github.com/Automattic/wp-calypso/blob/trunk/packages/state-utils/src/create-selector/README.md) and [Using memoizing selectors](https://react-redux.js.org/api/hooks#using-memoizing-selectors) and [Our Approach to Data](https://github.com/Automattic/wp-calypso/blob/trunk/docs/our-approach-to-data.md)
- [ ] Have we added the "[Status] String Freeze" label as soon as any new strings were ready for translation (p4TIVU-5Jq-p2)?
    - [ ] For UI changes, have we tested the change in various languages (for example, ES, PT, FR, or DE)? The length of text and words vary significantly between languages. 
- [ ] For changes affecting Jetpack: Have we added the "[Status] Needs Privacy Updates" label if this pull request changes what data or activity we track or use (p4TIVU-aUh-p2)?



Diff:
diff --git a/client/blocks/app-promo/index.tsx b/client/blocks/app-promo/index.tsx
index 248a08b5e2ee..0b5ddce42ceb 100644
--- a/client/blocks/app-promo/index.tsx
+++ b/client/blocks/app-promo/index.tsx
@@ -6,7 +6,6 @@ import wpToJpImage from 'calypso/assets/images/jetpack/wp-to-jp.svg';
 import QrCode from 'calypso/blocks/app-promo/qr-code';
 import AppsBadge from 'calypso/blocks/get-apps/apps-badge';
 import CardHeading from 'calypso/components/card-heading';
-import { preventWidows } from 'calypso/lib/formatting';
 import userAgent from 'calypso/lib/user-agent';
 import './style.scss';
 
@@ -50,17 +49,13 @@ export const AppPromo = ( {
 				alt="WordPress and Jetpack app"
 			/>
 			<div className="app-promo__title">
-				<CardHeading tagName="h2">
-					{ preventWidows( title || translate( 'Get our mobile app' ) ) }
-				</CardHeading>
-				{ ! showBadge && <h3 className="app-promo__subheader">{ preventWidows( subheader ) }</h3> }
+				<CardHeading tagName="h2">{ title || translate( 'Get our mobile app' ) }</CardHeading>
+				{ ! showBadge && <h3 className="app-promo__subheader">{ subheader }</h3> }
 			</div>
 
 			{ showBadge && (
 				<div className="app-promo__app-badges">
-					{ subheader && (
-						<p className="app-promo__app-badges-text">{ preventWidows( subheader ) }</p>
-					) }
+					{ subheader && <p className="app-promo__app-badges-text">{ subheader }</p> }
 					<AppsBadge
 						storeName={ showIosBadge ? 'ios' : 'android' }
 						utm_campaign={ campaign }
diff --git a/client/blocks/inline-help/inline-help-compact-results.jsx b/client/blocks/inline-help/inline-help-compact-results.jsx
index 70094eeb7a58..a8022f22085a 100644
--- a/client/blocks/inline-help/inline-help-compact-results.jsx
+++ b/client/blocks/inline-help/inline-help-compact-results.jsx
@@ -1,5 +1,5 @@
 import PropTypes from 'prop-types';
-import { decodeEntities, preventWidows } from 'calypso/lib/formatting';
+import { decodeEntities } from 'calypso/lib/formatting';
 
 function InlineHelpCompactResults( { helpLinks, onClick } ) {
 	return (
@@ -12,7 +12,7 @@ function InlineHelpCompactResults( { helpLinks, onClick } ) {
 						onClick={ ( event ) => onClick( event, link ) }
 						tabIndex={ -1 }
 					>
-						{ preventWidows( decodeEntities( link.title ) ) }
+						{ decodeEntities( link.title ) }
 					</a>
 				</li>
 			) ) }
diff --git a/client/blocks/inline-help/inline-help-search-results.jsx b/client/blocks/inline-help/inline-help-search-results.jsx
index 55cc7386a44a..d93c9f8283cf 100644
--- a/client/blocks/inline-help/inline-help-search-results.jsx
+++ b/client/blocks/inline-help/inline-help-search-results.jsx
@@ -12,7 +12,7 @@ import PropTypes from 'prop-types';
 import { Fragment, useEffect, useMemo } from 'react';
 import { useDispatch, useSelector } from 'react-redux';
 import QueryUserPurchases from 'calypso/components/data/query-user-purchases';
-import { decodeEntities, preventWidows } from 'calypso/lib/formatting';
+import { decodeEntities } from 'calypso/lib/formatting';
 import { recordTracksEvent } from 'calypso/state/analytics/actions';
 import getAdminHelpResults from 'calypso/state/selectors/get-admin-help-results';
 import hasCancelableUserPurchases from 'calypso/state/selectors/has-cancelable-user-purchases';
@@ -178,7 +178,7 @@ function HelpSearchResults( {
 							{ /* Old stuff - leaving this incase we need to quick revert
 							{ icon && <Gridicon icon={ icon } size={ 18 } /> } */ }
 							<LinkIcon />
-							<span>{ preventWidows( decodeEntities( title ) ) }</span>
+							<span>{ decodeEntities( title ) }</span>
 						</a>
 					</div>
 				</li>
diff --git a/client/blocks/jetpack-plugin-update-warning/index.tsx b/client/blocks/jetpack-plugin-update-warning/index.tsx
index 782013e866c0..6c81918e2ba6 100644
--- a/client/blocks/jetpack-plugin-update-warning/index.tsx
+++ b/client/blocks/jetpack-plugin-update-warning/index.tsx
@@ -2,7 +2,6 @@ import { ExternalLink } from '@automattic/components';
 import { useTranslate } from 'i18n-calypso';
 import { FC, useCallback, useMemo, useState } from 'react';
 import Notice from 'calypso/components/notice';
-import { preventWidows } from 'calypso/lib/formatting';
 import version_compare from 'calypso/lib/version-compare';
 import { useDispatch, useSelector } from 'calypso/state';
 import { recordTracksEvent } from 'calypso/state/analytics/actions/record';
@@ -59,28 +58,26 @@ export const JetpackPluginUpdateWarning: FC< ExternalProps > = ( {
 
 	return (
 		<Notice onDismissClick={ dismissClick } status="is-warning">
-			{ preventWidows(
-				translate(
-					'Your Jetpack plugin is out of date. ' +
-						'{{WarningRequirement/}}, {{JetpackUpdateLink}}update Jetpack{{/JetpackUpdateLink}}.',
-					{
-						components: {
-							JetpackUpdateLink: (
-								<ExternalLink
-									href={ pluginUpgradeUrl }
-									onClick={ updatePluginClick }
-									target="_blank"
-								/>
-							),
-							WarningRequirement: (
-								<>
-									{ warningRequirement ??
-										translate( 'To make sure it will work with our recommended plans' ) }
-								</>
-							),
-						},
-					}
-				)
+			{ translate(
+				'Your Jetpack plugin is out of date. ' +
+					'{{WarningRequirement/}}, {{JetpackUpdateLink}}update Jetpack{{/JetpackUpdateLink}}.',
+				{
+					components: {
+						JetpackUpdateLink: (
+							<ExternalLink
+								href={ pluginUpgradeUrl }
+								onClick={ updatePluginClick }
+								target="_blank"
+							/>
+						),
+						WarningRequirement: (
+							<>
+								{ warningRequirement ??
+									translate( 'To make sure it will work with our recommended plans' ) }
+							</>
+						),
+					},
+				}
 			) }
 		</Notice>
 	);
diff --git a/client/blocks/jetpack-review-prompt/index.tsx b/client/blocks/jetpack-review-prompt/index.tsx
index 37fadae36c5a..5c07cc879f0f 100644
--- a/client/blocks/jetpack-review-prompt/index.tsx
+++ b/client/blocks/jetpack-review-prompt/index.tsx
@@ -2,7 +2,6 @@ import { Button, Card, Gridicon } from '@automattic/components';
 import { useTranslate } from 'i18n-calypso';
 import { FunctionComponent, useCallback, useEffect } from 'react';
 import QueryPreferences from 'calypso/components/data/query-preferences';
-import { preventWidows } from 'calypso/lib/formatting';
 import { useSelector, useDispatch } from 'calypso/state';
 import { recordTracksEvent } from 'calypso/state/analytics/actions';
 import { dismiss } from 'calypso/state/jetpack-review-prompt/actions';
@@ -74,10 +73,8 @@ const JetpackReviewPrompt: FunctionComponent< Props > = ( { align = 'center', ty
 			case 'restore':
 				return (
 					<p>
-						{ preventWidows(
-							translate(
-								'Was it easy to restore your site? Leave us a review and help spread the word.'
-							)
+						{ translate(
+							'Was it easy to restore your site? Leave us a review and help spread the word.'
 						) }
 					</p>
 				);
@@ -85,10 +82,8 @@ const JetpackReviewPrompt: FunctionComponent< Props > = ( { align = 'center', ty
 			default:
 				return (
 					<p>
-						{ preventWidows(
-							translate(
-								'Are you happy with Jetpack Scan? Leave us a review and help spread the word.'
-							)
+						{ translate(
+							'Are you happy with Jetpack Scan? Leave us a review and help spread the word.'
 						) }
 					</p>
 				);
diff --git a/client/blocks/jitm/templates/sidebar-banner.jsx b/client/blocks/jitm/templates/sidebar-banner.jsx
index f3d13f34c2d5..6aa3824a35cd 100644
--- a/client/blocks/jitm/templates/sidebar-banner.jsx
+++ b/client/blocks/jitm/templates/sidebar-banner.jsx
@@ -1,5 +1,4 @@
 import UpsellNudge from 'calypso/blocks/upsell-nudge';
-import { preventWidows } from 'calypso/lib/formatting';
 
 import './sidebar-banner.scss';
 
@@ -32,7 +31,7 @@ export default function SidebarBannerTemplate( {
 				href={ CTA.link }
 				onClick={ onClick }
 				onDismissClick={ onDismiss }
-				title={ preventWidows( message ) }
+				title={ message }
 			/>
 			{ trackImpression && trackImpression() }
 		</>
diff --git a/client/blocks/signup-form/social.jsx b/client/blocks/signup-form/social.jsx
index 5d20b8ad37ff..572a3979d4f3 100644
--- a/client/blocks/signup-form/social.jsx
+++ b/client/blocks/signup-form/social.jsx
@@ -12,7 +12,6 @@ import {
 	GithubSocialButton,
 	UsernameOrEmailButton,
 } from 'calypso/components/social-buttons';
-import { preventWidows } from 'calypso/lib/formatting';
 import { isWpccFlow } from 'calypso/signup/is-flow';
 import { recordTracksEvent as recordTracks } from 'calypso/state/analytics/actions';
 import { errorNotice } from 'calypso/state/notices/actions';
@@ -106,9 +105,7 @@ class SocialSignupForm extends Component {
 				} ) }
 			>
 				{ ! compact && (
-					<p className="auth-form__social-text">
-						{ preventWidows( translate( 'Or create an account using:' ) ) }
-					</p>
+					<p className="auth-form__social-text">{ translate( 'Or create an account using:' ) }</p>
 				) }
 
 				<div className="auth-form__social-buttons">
diff --git a/client/blocks/time-mismatch-warning/index.tsx b/client/blocks/time-mismatch-warning/index.tsx
index f0d759d8d0fe..40a4bb923ead 100644
--- a/client/blocks/time-mismatch-warning/index.tsx
+++ b/client/blocks/time-mismatch-warning/index.tsx
@@ -1,7 +1,6 @@
 import { useTranslate } from 'i18n-calypso';
 import { FC } from 'react';
 import Notice, { NoticeStatus } from 'calypso/components/notice';
-import { preventWidows } from 'calypso/lib/formatting';
 import { useSelector, useDispatch } from 'calypso/state';
 import { savePreference } from 'calypso/state/preferences/actions';
 import { hasReceivedRemotePreferences, getPreference } from 'calypso/state/preferences/selectors';
@@ -44,17 +43,15 @@ export const TimeMismatchWarning: FC< ExternalProps > = ( {
 
 	return (
 		<Notice status={ status } onDismissClick={ dismissClick }>
-			{ preventWidows(
-				translate(
-					'This page reflects the time zone set on your site. ' +
-						'It looks like that does not match your current time zone. ' +
-						'{{SiteSettings}}You can update your site time zone here{{/SiteSettings}}.',
-					{
-						components: {
-							SiteSettings: <a href={ settingsUrl } />,
-						},
-					}
-				)
+			{ translate(
+				'This page reflects the time zone set on your site. ' +
+					'It looks like that does not match your current time zone. ' +
+					'{{SiteSettings}}You can update your site time zone here{{/SiteSettings}}.',
+				{
+					components: {
+						SiteSettings: <a href={ settingsUrl } />,
+					},
+				}
 			) }
 		</Notice>
 	);
diff --git a/client/blocks/time-mismatch-warning/test/__snapshots__/index.jsx.snap b/client/blocks/time-mismatch-warning/test/__snapshots__/index.jsx.snap
index 0ec7b3376c12..32ea15ad4f1c 100644
--- a/client/blocks/time-mismatch-warning/test/__snapshots__/index.jsx.snap
+++ b/client/blocks/time-mismatch-warning/test/__snapshots__/index.jsx.snap
@@ -31,7 +31,7 @@ exports[`TimeMismatchWarning to render if GMT offsets do not match 1`] = `
       <span
         class="calypso-notice__text"
       >
-        This page reflects the time zone set on your site. It looks like that does not match your current time zone. {{SiteSettings}}You can update your site time zone here{{/SiteSettings}}.
+        This page reflects the time zone set on your site. It looks like that does not match your current time zone. {{SiteSettings}}You can update your site time zone here{{/SiteSettings}}.
       </span>
     </span>
     <button
diff --git a/client/jetpack-connect/test/__snapshots__/signup.js.snap b/client/jetpack-connect/test/__snapshots__/signup.js.snap
index c33508a8b047..fd82eb2f15c3 100644
--- a/client/jetpack-connect/test/__snapshots__/signup.js.snap
+++ b/client/jetpack-connect/test/__snapshots__/signup.js.snap
@@ -228,7 +228,7 @@ exports[`JetpackSignup should render 1`] = `
           <p
             class="auth-form__social-text"
           >
-            Or create an account using:
+            Or create an account using:
           </p>
           <div
             class="auth-form__social-buttons"
@@ -515,7 +515,7 @@ exports[`JetpackSignup should render with locale suggestions 1`] = `
           <p
             class="auth-form__social-text"
           >
-            Or create an account using:
+            Or create an account using:
           </p>
           <div
             class="auth-form__social-buttons"
diff --git a/client/my-sites/sidebar/style.scss b/client/my-sites/sidebar/style.scss
index 5cf94094d916..237206948a10 100644
--- a/client/my-sites/sidebar/style.scss
+++ b/client/my-sites/sidebar/style.scss
@@ -586,7 +586,6 @@ $font-size: rem(14px);
 
 		.upsell-nudge.banner.card.is-compact .banner__info .banner__title {
 			color: var(--studio-black);
-			text-wrap: wrap;
 		}
 
 		.upsell-nudge.banner.card.is-compact .dismissible-card__close-button .gridicon {


Reviews:
user: login: tellthemachines
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T03:55:29Z
user: login: tellthemachines
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T03:56:48Z
user: login: tellthemachines
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T03:57:42Z
user: login: tellthemachines
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T03:58:43Z
user: login: tellthemachines
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T04:00:41Z
user: login: tellthemachines
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T04:01:56Z
user: login: tellthemachines
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T04:12:22Z
user: login: tellthemachines
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T04:12:52Z
user: login: andrewserong
body: This is looking pretty good to me, thanks for digging through these!

I just found one where a `text-wrap: wrap` rule is applying so we're left with a widow, but the others I was able to test were looking good.
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-07T05:59:00Z
user: login: tellthemachines
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-07T06:53:04Z
user: login: jasmussen
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-07T07:47:24Z
user: login: tellthemachines
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-08T00:00:13Z
user: login: andrewserong
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-05-08T03:00:56Z
user: login: andrewserong
body: This is testing well for me! 🚀 
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-08T03:01:26Z

Review comments:
diff_hunk: @@ -50,17 +49,13 @@ export const AppPromo = ( {
 				alt="WordPress and Jetpack app"
 			/>
 			<div className="app-promo__title">
-				<CardHeading tagName="h2">
-					{ preventWidows( title || translate( 'Get our mobile app' ) ) }
-				</CardHeading>
-				{ ! showBadge && <h3 className="app-promo__subheader">{ preventWidows( subheader ) }</h3> }
+				<CardHeading tagName="h2">{ title || translate( 'Get our mobile app' ) }</CardHeading>
+				{ ! showBadge && <h3 className="app-promo__subheader">{ subheader }</h3> }
 			</div>
 
 			{ showBadge && (
 				<div className="app-promo__app-badges">
-					{ subheader && (
-						<p className="app-promo__app-badges-text">{ preventWidows( subheader ) }</p>
path: client/blocks/app-promo/index.tsx
user: login: tellthemachines
body:  `AppPromo`, used in home screen and discover section of reader:

<img width="753" alt="Screenshot 2025-05-06 at 4 25 23 pm" src="https://github.com/user-attachments/assets/252432e1-76a6-499a-bb64-9398f150682c" />
created_at: 2025-05-07T03:55:29Z
author_association: CONTRIBUTOR
diff_hunk: @@ -12,7 +12,7 @@ function InlineHelpCompactResults( { helpLinks, onClick } ) {
 						onClick={ ( event ) => onClick( event, link ) }
 						tabIndex={ -1 }
 					>
-						{ preventWidows( decodeEntities( link.title ) ) }
path: client/blocks/inline-help/inline-help-compact-results.jsx
user: login: tellthemachines
body: This component doesn't seem to be in use anywhere but should be covered by generic `ul` styles.
created_at: 2025-05-07T03:56:48Z
author_association: CONTRIBUTOR
diff_hunk: @@ -178,7 +178,7 @@ function HelpSearchResults( {
 							{ /* Old stuff - leaving this incase we need to quick revert
 							{ icon && <Gridicon icon={ icon } size={ 18 } /> } */ }
 							<LinkIcon />
-							<span>{ preventWidows( decodeEntities( title ) ) }</span>
path: client/blocks/inline-help/inline-help-search-results.jsx
user: login: tellthemachines
body: Search results on dashboard:

<img width="714" alt="Screenshot 2025-05-07 at 1 23 51 pm" src="https://github.com/user-attachments/assets/38f88fc2-9d81-4ca5-94ba-9685e741471d" />

(as above, also covered by generic `ul` styles)
created_at: 2025-05-07T03:57:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -59,28 +58,26 @@ export const JetpackPluginUpdateWarning: FC< ExternalProps > = ( {
 
 	return (
 		<Notice onDismissClick={ dismissClick } status="is-warning">
-			{ preventWidows(
-				translate(
-					'Your Jetpack plugin is out of date. ' +
-						'{{WarningRequirement/}}, {{JetpackUpdateLink}}update Jetpack{{/JetpackUpdateLink}}.',
-					{
-						components: {
-							JetpackUpdateLink: (
-								<ExternalLink
-									href={ pluginUpgradeUrl }
-									onClick={ updatePluginClick }
-									target="_blank"
-								/>
-							),
-							WarningRequirement: (
-								<>
-									{ warningRequirement ??
-										translate( 'To make sure it will work with our recommended plans' ) }
-								</>
-							),
-						},
-					}
-				)
path: client/blocks/jetpack-plugin-update-warning/index.tsx
user: login: tellthemachines
body: Not sure how to test this one, but it uses `Notice` so will be covered by that component's styles.
created_at: 2025-05-07T03:58:42Z
author_association: CONTRIBUTOR
diff_hunk: @@ -74,21 +73,17 @@ const JetpackReviewPrompt: FunctionComponent< Props > = ( { align = 'center', ty
 			case 'restore':
 				return (
 					<p>
-						{ preventWidows(
-							translate(
-								'Was it easy to restore your site? Leave us a review and help spread the word.'
-							)
+						{ translate(
+							'Was it easy to restore your site? Leave us a review and help spread the word.'
 						) }
 					</p>
 				);
 			case 'scan':
 			default:
 				return (
 					<p>
-						{ preventWidows(
-							translate(
-								'Are you happy with Jetpack Scan? Leave us a review and help spread the word.'
path: client/blocks/jetpack-review-prompt/index.tsx
user: login: tellthemachines
body: In Jetpack Cloud env, go to backups, restore a previous version and see prompt pop up after restore:

<img width="729" alt="Screenshot 2025-05-07 at 1 43 13 pm" src="https://github.com/user-attachments/assets/cb8fd490-a3e2-4978-9f4a-82996412b828" />

created_at: 2025-05-07T04:00:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -32,7 +31,7 @@ export default function SidebarBannerTemplate( {
 				href={ CTA.link }
 				onClick={ onClick }
 				onDismissClick={ onDismiss }
-				title={ preventWidows( message ) }
path: client/blocks/jitm/templates/sidebar-banner.jsx
user: login: tellthemachines
body: Not sure how to test this one, but it uses `UpsellNudge` which uses `Banner` which wraps its title in a `p` tag so is covered by generic `p` styles.
created_at: 2025-05-07T04:01:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -106,9 +105,7 @@ class SocialSignupForm extends Component {
 				} ) }
 			>
 				{ ! compact && (
-					<p className="auth-form__social-text">
-						{ preventWidows( translate( 'Or create an account using:' ) ) }
-					</p>
path: client/blocks/signup-form/social.jsx
user: login: tellthemachines
body: Not sure this is still in use as I couldn't find a signup form that displayed it, but should be safe to remove as it's inside a `p`.
created_at: 2025-05-07T04:12:22Z
author_association: CONTRIBUTOR
diff_hunk: @@ -44,17 +43,15 @@ export const TimeMismatchWarning: FC< ExternalProps > = ( {
 
 	return (
 		<Notice status={ status } onDismissClick={ dismissClick }>
-			{ preventWidows(
-				translate(
-					'This page reflects the time zone set on your site. ' +
-						'It looks like that does not match your current time zone. ' +
-						'{{SiteSettings}}You can update your site time zone here{{/SiteSettings}}.',
-					{
-						components: {
-							SiteSettings: <a href={ settingsUrl } />,
-						},
-					}
-				)
path: client/blocks/time-mismatch-warning/index.tsx
user: login: tellthemachines
body: Not sure how to test this one, but it's inside a `Notice` so covered by its styles.
created_at: 2025-05-07T04:12:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -32,7 +31,7 @@ export default function SidebarBannerTemplate( {
 				href={ CTA.link }
 				onClick={ onClick }
 				onDismissClick={ onDismiss }
-				title={ preventWidows( message ) }
path: client/blocks/jitm/templates/sidebar-banner.jsx
user: login: andrewserong
body: I believe it's this sidebar upsell that you see on a Free plan from its Home screen. I notice with this PR applied that the `banner__title`'s `text-wrap: wrap` rule takes precedence over the generic `p` rule, so we wind up with a widow:

<img width="1182" alt="image" src="https://github.com/user-attachments/assets/1c9c2169-7072-45b7-b161-8c227cf48112" />

created_at: 2025-05-07T05:58:00Z
author_association: MEMBER
diff_hunk: @@ -32,7 +31,7 @@ export default function SidebarBannerTemplate( {
 				href={ CTA.link }
 				onClick={ onClick }
 				onDismissClick={ onDismiss }
-				title={ preventWidows( message ) }
path: client/blocks/jitm/templates/sidebar-banner.jsx
user: login: tellthemachines
body: Oooh good catch! That rule is so specific that I think we can safely remove it.
created_at: 2025-05-07T06:53:03Z
author_association: CONTRIBUTOR
diff_hunk: @@ -74,21 +73,17 @@ const JetpackReviewPrompt: FunctionComponent< Props > = ( { align = 'center', ty
 			case 'restore':
 				return (
 					<p>
-						{ preventWidows(
-							translate(
-								'Was it easy to restore your site? Leave us a review and help spread the word.'
-							)
+						{ translate(
+							'Was it easy to restore your site? Leave us a review and help spread the word.'
 						) }
 					</p>
 				);
 			case 'scan':
 			default:
 				return (
 					<p>
-						{ preventWidows(
-							translate(
-								'Are you happy with Jetpack Scan? Leave us a review and help spread the word.'
path: client/blocks/jetpack-review-prompt/index.tsx
user: login: jasmussen
body: Not someting for this PR, and not urgent, but it'd be nice to give this modal a DS pass. CC: @keoshi in case you would know where to file this.
created_at: 2025-05-07T07:47:23Z
author_association: MEMBER
diff_hunk: @@ -32,7 +31,7 @@ export default function SidebarBannerTemplate( {
 				href={ CTA.link }
 				onClick={ onClick }
 				onDismissClick={ onDismiss }
-				title={ preventWidows( message ) }
path: client/blocks/jitm/templates/sidebar-banner.jsx
user: login: tellthemachines
body: Ok done!
created_at: 2025-05-08T00:00:13Z
author_association: CONTRIBUTOR
diff_hunk: @@ -44,17 +43,15 @@ export const TimeMismatchWarning: FC< ExternalProps > = ( {
 
 	return (
 		<Notice status={ status } onDismissClick={ dismissClick }>
-			{ preventWidows(
-				translate(
-					'This page reflects the time zone set on your site. ' +
-						'It looks like that does not match your current time zone. ' +
-						'{{SiteSettings}}You can update your site time zone here{{/SiteSettings}}.',
-					{
-						components: {
-							SiteSettings: <a href={ settingsUrl } />,
-						},
-					}
-				)
path: client/blocks/time-mismatch-warning/index.tsx
user: login: andrewserong
body: You can get to this one by updating your site's timezone to be different to your browser's timezone and then go to Jetpack > Activity Log.

## This PR

<img width="1405" alt="image" src="https://github.com/user-attachments/assets/6e74fc7a-78e8-44fa-8cc1-7b6bdc1ceb2b" />

## Trunk

<img width="1412" alt="image" src="https://github.com/user-attachments/assets/bda425ba-9277-437d-9fb1-a6ffc7d54326" />

There's only a difference of one word between the two.
created_at: 2025-05-08T03:00:55Z
author_association: MEMBER

PR comments:
user: login: github-actions[bot]
created_at: 2025-05-06T06:29:56Z
body: <details>
<summary>Calypso Live <a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-143276">(direct link)</a></summary>
<table>
<tr>
<td>
<img src="https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl=https%3A%2F%2Fcalypso.live%3Fimage%3Dregistry.a8c.com%2Fcalypso%2Fapp%3Abuild-143276%26flags%3Doauth&choe=UTF-8" />
</td>
<td>
<a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-143276">https://calypso.live?image=registry.a8c.com/calypso/app:build-143276</a>
</td>
</tr>
</table>
</details>
<details>
<summary>Jetpack Cloud live <a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-143276&env=jetpack">(direct link)</a></summary>
<table>
<tr>
<td>
<img src="https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl=https%3A%2F%2Fcalypso.live%3Fimage%3Dregistry.a8c.com%2Fcalypso%2Fapp%3Abuild-143276%26env%3Djetpack%26flags%3Doauth&choe=UTF-8" />
</td>
<td>
<a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-143276&env=jetpack">https://calypso.live?image=registry.a8c.com/calypso/app:build-143276&env=jetpack</a>
</td>
</tr>
</table>
</details>
<details>
<summary>Automattic for Agencies live <a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-143276&env=a8c-for-agencies">(direct link)</a></summary>
<table>
<tr>
<td>
<img src="https://chart.googleapis.com/chart?chs=150x150&cht=qr&chl=https%3A%2F%2Fcalypso.live%3Fimage%3Dregistry.a8c.com%2Fcalypso%2Fapp%3Abuild-143276%26env%3Da8c-for-agencies%26flags%3Doauth&choe=UTF-8" />
</td>
<td>
<a href="https://calypso.live?image=registry.a8c.com/calypso/app:build-143276&env=a8c-for-agencies">https://calypso.live?image=registry.a8c.com/calypso/app:build-143276&env=a8c-for-agencies</a>
</td>
</tr>
</table>
</details>
<!--calypso-live-watermark:apr@v1-->
author_association: NONE
user: login: matticbot
created_at: 2025-05-06T06:34:44Z
body: **This PR modifies the release build for the following Calypso Apps:**

_For info about this notification, see here: PCYsg-OT6-p2_

* help-center
* notifications
* odyssey-stats
* wpcom-block-editor

To test WordPress.com changes, run `install-plugin.sh $pluginSlug fix/text-wrapping-technique` on your sandbox.
<!--calypso-app-artifacts-watermark:apr@v1-->
author_association: CONTRIBUTOR
user: login: matticbot
created_at: 2025-05-06T06:35:36Z
body: <!-- icfy-watermark: c52822 -->
Here is how your PR affects size of JS and CSS bundles shipped to the user's browser:

**App Entrypoints** (~54 bytes removed 📉 [gzipped])
<details>

```
name         parsed_size           gzip_size
entry-login        -69 B  (-0.0%)      -54 B  (-0.0%)
```

Common code that is always downloaded and parsed every time the app is loaded, no matter which route is used.
</details>

**Sections** (~160 bytes removed 📉 [gzipped])
<details>

```
name                    parsed_size           gzip_size
accept-invite                -849 B  (-0.1%)     -353 B  (-0.2%)
scan                         -111 B  (-0.0%)      -54 B  (-0.0%)
backup                       -111 B  (-0.0%)      -42 B  (-0.0%)
a8c-for-agencies-sites       -111 B  (-0.0%)      -42 B  (-0.0%)
home                          -78 B  (-0.0%)       -6 B  (-0.0%)
reader                        -69 B  (-0.0%)       -3 B  (-0.0%)
stepper-user-step             -51 B  (-0.0%)      -17 B  (-0.0%)
plans                         -51 B  (-0.0%)      -10 B  (-0.0%)
jetpack-connect               -51 B  (-0.0%)      -43 B  (-0.0%)
import                        -51 B  (-0.0%)      -20 B  (-0.0%)
activity                      -51 B  (-0.0%)      -10 B  (-0.0%)
```

Sections contain code specific for a given set of routes. Is downloaded and parsed only when a particular route is navigated to.
</details>

**Async-loaded Components** (~148 bytes added 📈 [gzipped])
<details>

```
name                                                     parsed_size           gzip_size
async-load-design-blocks                                      -180 B  (-0.0%)      -91 B  (-0.0%)
async-load-design                                              -60 B  (-0.0%)      -34 B  (-0.0%)
async-load-signup-steps-user                                   -51 B  (-0.0%)      -41 B  (-0.0%)
async-load-calypso-blocks-jitm-templates-sidebar-banner        -51 B  (-0.1%)      -13 B  (-0.1%)
```

React components that are loaded lazily, when a certain part of UI is displayed for the first time.
</details>

**Legend**
<details>
<summary>What is parsed and gzip size?</summary>

**Parsed Size:** Uncompressed size of the JS and CSS files. This much code needs to be parsed and stored in memory.
**Gzip Size:** Compressed size of the JS and CSS files. This much data needs to be downloaded over network.
</details>

Generated by performance advisor bot at [iscalypsofastyet.com](http://iscalypsofastyet.com).
author_association: CONTRIBUTOR
user: login: jasmussen
created_at: 2025-05-07T07:48:16Z
body: Thank you for working on this 🙏 
author_association: MEMBER