From fc5f1fbee5caa4f2304cdb0312bdc73131761856 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Mon, 8 Feb 2021 18:25:57 +0100 Subject: [PATCH] Focused Launch: fix i18n by extracting text outside of ternary operator (#49812) * Focused Launch: extract title/subtitle text outside of ternary operator * Focused Launch: extract popular label text outside of ternary operator * Focused Launch: extract free plan label text outside of ternary operator * Focused Launch: refactor translator comment for string wrapped in sprintf * Domain picker: extract suggestion item text outside of ternary operators * Domain picker: extract select button text outside of ternary operator * Localize /help URL * Step by Step flow: extract translated text outside of ternary operator * Plans Grid: extract translated text outside of ternary operators * Composite checkout: extract payment method text outside of ternary operator * Plans feature list: extract text outside of ternary operator * Domain picker: extract categories label outside of nullish coalesce operator * Plans grid details: extract text outside of ternary operator * Plans grid accordion: extract text outside of ternary operator * Plans grid accordion: extract badge label outside of ternary operator * Focused launch success: extract subtitle text outside of ternary operator * Focused launch success: extract copy button label outside of ternary operator * Undo localized /help URL, as the contents are already localized --- .../src/launch-steps/final-step/index.tsx | 7 ++- .../components/checkout-payment-methods.tsx | 6 +- .../src/domain-categories/index.tsx | 4 +- .../src/domain-picker/suggestion-item.tsx | 39 ++++++++----- .../src/focused-launch/success/index.tsx | 20 ++++--- .../src/focused-launch/summary/index.tsx | 58 +++++++++++-------- .../src/plans-accordion-item/index.tsx | 7 ++- .../plans-grid/src/plans-accordion/index.tsx | 14 ++--- .../plans-grid/src/plans-details/index.tsx | 7 ++- .../src/plans-feature-list/index.tsx | 25 ++++---- .../plans-grid/src/plans-table/plan-item.tsx | 18 ++++-- 11 files changed, 124 insertions(+), 81 deletions(-) diff --git a/apps/editing-toolkit/editing-toolkit-plugin/editor-site-launch/src/launch-steps/final-step/index.tsx b/apps/editing-toolkit/editing-toolkit-plugin/editor-site-launch/src/launch-steps/final-step/index.tsx index c40b5624bd7c1..21b49a1a40f43 100644 --- a/apps/editing-toolkit/editing-toolkit-plugin/editor-site-launch/src/launch-steps/final-step/index.tsx +++ b/apps/editing-toolkit/editing-toolkit-plugin/editor-site-launch/src/launch-steps/final-step/index.tsx @@ -127,6 +127,9 @@ const FinalStep: React.FunctionComponent< LaunchStepProps > = ( { onNextStep, on ); + const planSummaryCostLabelAnnually = __( 'billed annually', 'full-site-editing' ); + const planSummaryCostLabelMonthly = __( 'per month, billed monthly', 'full-site-editing' ); + const planSummary = (
{ plan && planProduct && ! plan.isFree ? ( @@ -134,8 +137,8 @@ const FinalStep: React.FunctionComponent< LaunchStepProps > = ( { onNextStep, on

WordPress.com { plan.title }

{ __( 'Plan subscription', 'full-site-editing' ) }: { planProduct.price }{ ' ' } { planProduct.billingPeriod === 'ANNUALLY' - ? __( 'billed annually', 'full-site-editing' ) - : __( 'per month, billed monthly', 'full-site-editing' ) } + ? planSummaryCostLabelAnnually + : planSummaryCostLabelMonthly } ) : ( <> diff --git a/packages/composite-checkout/src/components/checkout-payment-methods.tsx b/packages/composite-checkout/src/components/checkout-payment-methods.tsx index 96c911024a082..378f8261d883a 100644 --- a/packages/composite-checkout/src/components/checkout-payment-methods.tsx +++ b/packages/composite-checkout/src/components/checkout-payment-methods.tsx @@ -128,7 +128,11 @@ export function CheckoutPaymentMethodsTitle(): JSX.Element { const { __ } = useI18n(); const isActive = useIsStepActive(); const isComplete = useIsStepComplete(); - return <>{ ! isActive && isComplete ? __( 'Payment method' ) : __( 'Pick a payment method' ) }; + + const paymentMethodLabelActive = __( 'Pick a payment method' ); + const paymentMethodLabelInactive = __( 'Payment method' ); + + return <>{ ! isActive && isComplete ? paymentMethodLabelInactive : paymentMethodLabelActive }; } function PaymentMethod( { diff --git a/packages/domain-picker/src/domain-categories/index.tsx b/packages/domain-picker/src/domain-categories/index.tsx index fa074b3b6038e..eeaef1e0c6f5b 100644 --- a/packages/domain-picker/src/domain-categories/index.tsx +++ b/packages/domain-picker/src/domain-categories/index.tsx @@ -37,13 +37,15 @@ const DomainPickerCategories: React.FunctionComponent< Props > = ( { onSelect, s select( DOMAIN_SUGGESTIONS_STORE ).getCategories() ); + const allCategoriesLabel = __( 'All Categories', __i18n_text_domain__ ); + return (
    diff --git a/packages/domain-picker/src/domain-picker/suggestion-item.tsx b/packages/domain-picker/src/domain-picker/suggestion-item.tsx index d428ac8c4da7b..5fb7609042b57 100644 --- a/packages/domain-picker/src/domain-picker/suggestion-item.tsx +++ b/packages/domain-picker/src/domain-picker/suggestion-item.tsx @@ -76,34 +76,40 @@ const DomainPickerSuggestionItem: React.FC< Props > = ( { const [ previousDomain, setPreviousDomain ] = React.useState< string | undefined >(); const [ previousRailcarId, setPreviousRailcarId ] = React.useState< string | undefined >(); + const freeDomainLabelDefault = __( 'Default', __i18n_text_domain__ ); + const freeDomainLabelFree = __( 'Free', __i18n_text_domain__ ); + + const firstYearLabel = __( 'Included in paid plans', __i18n_text_domain__ ); + const firstYearLabelAlt = __( 'Included with annual plans', __i18n_text_domain__ ); + // translators: text in between the marks is styled as bold text + const firstYearLabelFormatted = __( + 'First year included in paid plans', + __i18n_text_domain__ + ); + const freeDomainLabel = - type === ITEM_TYPE_INDIVIDUAL_ITEM - ? __( 'Default', __i18n_text_domain__ ) - : __( 'Free', __i18n_text_domain__ ); + type === ITEM_TYPE_INDIVIDUAL_ITEM ? freeDomainLabelDefault : freeDomainLabelFree; const firstYearIncludedInPaidLabel = isMobile - ? __( 'Included in paid plans', __i18n_text_domain__ ) - : createInterpolateElement( - __( 'First year included in paid plans', __i18n_text_domain__ ), - { - strong: , - } - ); + ? firstYearLabel + : createInterpolateElement( firstYearLabelFormatted, { + strong: , + } ); /** * IIFE executes immediately after creation, hence it returns the translated values immediately. * The great advantage is that: * 1. We don't have to execute it during rendering. * 2. We don't have to use nested ternaries (which is not allowed by the linter). - * 3. It improves the readibility of our code + * 3. It improves the readability of our code */ const paidIncludedDomainLabel = ( () => { if ( type === ITEM_TYPE_INDIVIDUAL_ITEM ) { return firstYearIncludedInPaidLabel; } else if ( isMobile ) { - return __( 'Free', __i18n_text_domain__ ); + return freeDomainLabelFree; } - return __( 'Included with annual plans', __i18n_text_domain__ ); + return firstYearLabelAlt; } )(); React.useEffect( () => { @@ -127,6 +133,9 @@ const DomainPickerSuggestionItem: React.FC< Props > = ( { onSelect( domain ); }; + const selectButtonLabelSelected = __( 'Selected', __i18n_text_domain__ ); + const selectButtonLabelUnselected = __( 'Select', __i18n_text_domain__ ); + return ( = ( { onClick={ onDomainSelect } > { selected && ! isUnavailable - ? __( 'Selected', __i18n_text_domain__ ) - : __( 'Select', __i18n_text_domain__ ) } + ? selectButtonLabelSelected + : selectButtonLabelUnselected }
) ) } diff --git a/packages/launch/src/focused-launch/success/index.tsx b/packages/launch/src/focused-launch/success/index.tsx index abcd6e6170f77..0b82082f692f3 100644 --- a/packages/launch/src/focused-launch/success/index.tsx +++ b/packages/launch/src/focused-launch/success/index.tsx @@ -60,17 +60,21 @@ const Success: React.FunctionComponent = () => { redirectTo( `/home/${ siteSubdomain?.domain }` ); }; + const subtitleTextLaunching = __( 'Your site will be live shortly.', __i18n_text_domain__ ); + const subtitleTextLaunched = __( + "Congratulations, your website is now live. We're excited to watch you grow with WordPress.", + __i18n_text_domain__ + ); + + const copyButtonLabelIdle = __( 'Copy Link', __i18n_text_domain__ ); + const copyButtonLabelActivated = __( 'Copied!', __i18n_text_domain__ ); + return (
{ __( 'Hooray!', __i18n_text_domain__ ) } - { isSiteLaunching - ? __( 'Your site will be live shortly.', '__i18n_text_domain__' ) - : __( - "Congratulations, your website is now live. We're excited to watch you grow with WordPress.", - __i18n_text_domain__ - ) } + { isSiteLaunching ? subtitleTextLaunching : subtitleTextLaunched } { ! isSiteLaunching && ( <> @@ -92,9 +96,7 @@ const Success: React.FunctionComponent = () => { onFinishCopy={ () => setHasCopied( false ) } className="focused-launch-success__url-copy-button" > - { hasCopied - ? __( 'Copied!', __i18n_text_domain__ ) - : __( 'Copy Link', __i18n_text_domain__ ) } + { hasCopied ? copyButtonLabelActivated : copyButtonLabelIdle }
diff --git a/packages/launch/src/focused-launch/summary/index.tsx b/packages/launch/src/focused-launch/summary/index.tsx index bc4b327e2e1cd..813f099d132aa 100644 --- a/packages/launch/src/focused-launch/summary/index.tsx +++ b/packages/launch/src/focused-launch/summary/index.tsx @@ -335,6 +335,14 @@ const PlanStep: React.FunctionComponent< PlanStepProps > = ( { [ allAvailablePlans, billingPeriod ] ); + const popularLabel = __( 'Popular', __i18n_text_domain__ ); + + const freePlanLabel = __( 'Free', __i18n_text_domain__ ); + const freePlanLabelNotAvailable = __( + 'Not available with your domain selection', + __i18n_text_domain__ + ); + return ( = ( {
{ __( 'Purchased', __i18n_text_domain__ ) } @@ -417,19 +426,20 @@ const PlanStep: React.FunctionComponent< PlanStepProps > = ( { readOnly={ plan.isFree && ( hasPaidDomain || selectedPaidDomain ) } > { plan.isFree ? ( { hasPaidDomain || selectedPaidDomain - ? __( 'Not available with your domain selection', __i18n_text_domain__ ) - : __( 'Free', __i18n_text_domain__ ) } + ? freePlanLabelNotAvailable + : freePlanLabel } ) : ( @@ -620,7 +630,7 @@ const Summary: React.FunctionComponent = () => { // Disabled steps are not interactive (e.g. user has already selected domain/plan) // Active steps require user interaction // Using this arrays allows to easily sort the steps correctly in both - // groups, and allows the actve steps to always show the correct step index. + // groups, and allows the active steps to always show the correct step index. const disabledSteps: StepIndexRenderFunction[] = []; const activeSteps: StepIndexRenderFunction[] = []; isSiteTitleStepVisible && activeSteps.push( renderSiteTitleStep ); @@ -636,24 +646,24 @@ const Summary: React.FunctionComponent = () => { const isReadyToLaunch = title && ( hasPaidDomain || hasSelectedDomain ) && ( hasPaidPlan || selectedPlanProductId ); + const titleReady = __( "You're ready to launch", __i18n_text_domain__ ); + const titleInProgress = __( "You're almost there", __i18n_text_domain__ ); + + const subtitleReady = __( + "You're good to go! Launch your site and share your site address.", + __i18n_text_domain__ + ); + const subtitleInProgress = __( + 'Prepare for launch! Confirm a few final things before you take it live.', + __i18n_text_domain__ + ); + return (
- - { hasPaidDomain && hasPaidPlan - ? __( "You're ready to launch", __i18n_text_domain__ ) - : __( "You're almost there", __i18n_text_domain__ ) } - + { hasPaidDomain && hasPaidPlan ? titleReady : titleInProgress } - { hasPaidDomain && hasPaidPlan - ? __( - "You're good to go! Launch your site and share your site address.", - __i18n_text_domain__ - ) - : __( - 'Prepare for launch! Confirm a few final things before you take it live.', - __i18n_text_domain__ - ) } + { hasPaidDomain && hasPaidPlan ? subtitleReady : subtitleInProgress }
{ disabledSteps.map( ( disabledStepRenderer, disabledStepIndex ) => diff --git a/packages/plans-grid/src/plans-accordion-item/index.tsx b/packages/plans-grid/src/plans-accordion-item/index.tsx index 0fdec71d896e9..e3c31097d4d07 100644 --- a/packages/plans-grid/src/plans-accordion-item/index.tsx +++ b/packages/plans-grid/src/plans-accordion-item/index.tsx @@ -75,6 +75,9 @@ const PlanAccordionItem: React.FunctionComponent< Props > = ( { ! disabledLabel && onToggle?.( slug, ! isOpen ); }; + const planItemPriceLabelAnnually = __( 'billed annually', __i18n_text_domain__ ); + const planItemPriceLabelMonthly = __( 'per month, billed monthly', __i18n_text_domain__ ); + return (
= ( { { ! isFree && ( billingPeriod === 'ANNUALLY' - ? __( 'billed annually', __i18n_text_domain__ ) - : __( 'per month, billed monthly', __i18n_text_domain__ ) ) } + ? planItemPriceLabelAnnually + : planItemPriceLabelMonthly ) }
{ ! isFree && (
= ( { const primaryPlan = recommendedPlan || popularPlan; - const badge = recommendedPlan - ? __( 'Recommended for you', __i18n_text_domain__ ) - : __( 'Popular', __i18n_text_domain__ ); + const badgeTextRecommended = __( 'Recommended for you', __i18n_text_domain__ ); + const badgeTextPopular = __( 'Popular', __i18n_text_domain__ ); // Other plans const otherPlans = supportedPlans.filter( @@ -102,6 +101,9 @@ const PlansAccordion: React.FunctionComponent< Props > = ( { ); }; + const plansToggleExpanded = __( 'Collapse all plans', __i18n_text_domain__ ); + const plansToggleCollapsed = __( 'Show all plans', __i18n_text_domain__ ); + return (
@@ -129,7 +131,7 @@ const PlansAccordion: React.FunctionComponent< Props > = ( { features={ primaryPlan.features ?? [] } billingPeriod={ billingPeriod } domain={ currentDomain } - badge={ badge } + badge={ recommendedPlan ? badgeTextRecommended : badgeTextPopular } isFree={ primaryPlan.isFree } isOpen isPrimary @@ -148,9 +150,7 @@ const PlansAccordion: React.FunctionComponent< Props > = ( {
diff --git a/packages/plans-grid/src/plans-details/index.tsx b/packages/plans-grid/src/plans-details/index.tsx index 0b629930a01ab..60f15a277380e 100644 --- a/packages/plans-grid/src/plans-details/index.tsx +++ b/packages/plans-grid/src/plans-details/index.tsx @@ -64,6 +64,9 @@ const PlansDetails: React.FunctionComponent< Props > = ( { onSelect, locale, bil const monthlyBillingLabel = __( 'Monthly subscription', __i18n_text_domain__ ); + const annualNudgeTextAnnually = __( 'Included with annual plans', __i18n_text_domain__ ); + const annualNudgeTextMonthly = __( 'Only included with annual plans', __i18n_text_domain__ ); + return (
@@ -123,8 +126,8 @@ const PlansDetails: React.FunctionComponent< Props > = ( { onSelect, locale, bil className="plans-details__feature-annual-nudge" aria-label={ billingPeriod === 'ANNUALLY' - ? __( 'Included with annual plans', __i18n_text_domain__ ) - : __( 'Only included with annual plans', __i18n_text_domain__ ) + ? annualNudgeTextAnnually + : annualNudgeTextMonthly } > { __( 'Included with annual plans', __i18n_text_domain__ ) } diff --git a/packages/plans-grid/src/plans-feature-list/index.tsx b/packages/plans-grid/src/plans-feature-list/index.tsx index ce6e03b3a1315..b5e9ed127a183 100644 --- a/packages/plans-grid/src/plans-feature-list/index.tsx +++ b/packages/plans-grid/src/plans-feature-list/index.tsx @@ -42,18 +42,19 @@ const DefaultFeatureListItemContentWrapper: React.FunctionComponent< FeatureList const FeatureAnnualDiscountNudge: React.FunctionComponent< { billingPeriod: Plans.PlanBillingPeriod; __: typeof import('@wordpress/i18n').__; -} > = ( { billingPeriod, __ } ) => ( - - { __( 'Included with annual plans', __i18n_text_domain__ ) } - -); +} > = ( { billingPeriod, __ } ) => { + const annualNudgeTextAnnually = __( 'Included with annual plans', __i18n_text_domain__ ); + const annualNudgeTextMonthly = __( 'Only included with annual plans', __i18n_text_domain__ ); + + return ( + + { annualNudgeTextAnnually } + + ); +}; function computeDomainFeatureItem( isFreePlan: boolean, diff --git a/packages/plans-grid/src/plans-table/plan-item.tsx b/packages/plans-grid/src/plans-table/plan-item.tsx index 966f18fa461d7..b4aadf8ac9e20 100644 --- a/packages/plans-grid/src/plans-table/plan-item.tsx +++ b/packages/plans-grid/src/plans-table/plan-item.tsx @@ -104,11 +104,19 @@ const PlanItem: React.FunctionComponent< Props > = ( { const isOpen = allPlansExpanded || isDesktop || isPopular || isOpenInternalState; + const normalCtaLabelFallback = __( 'Choose', __i18n_text_domain__ ); + const fullWidthCtaLabelSelected = __( 'Current Selection', __i18n_text_domain__ ); // translators: %s is a WordPress.com plan name (eg: Free, Personal) const fullWidthCtaLabelUnselected = __( 'Select %s', __i18n_text_domain__ ); + const planItemPriceLabelAnnually = __( 'billed annually', __i18n_text_domain__ ); + const planItemPriceLabelMonthly = __( 'per month, billed monthly', __i18n_text_domain__ ); + + const expandToggleLabelExpanded = __( 'Collapse all plans', __i18n_text_domain__ ); + const expandToggleLabelCollapsed = __( 'Expand all plans', __i18n_text_domain__ ); + return (
= ( { { isFree && __( 'free forever', __i18n_text_domain__ ) } { ! isFree && ( billingPeriod === 'ANNUALLY' - ? __( 'billed annually', __i18n_text_domain__ ) - : __( 'per month, billed monthly', __i18n_text_domain__ ) ) } + ? planItemPriceLabelAnnually + : planItemPriceLabelMonthly ) }
{ /* @@ -193,7 +201,7 @@ const PlanItem: React.FunctionComponent< Props > = ( { isPrimary disabled={ !! disabledLabel } > - { disabledLabel ?? __( 'Choose', __i18n_text_domain__ ) } + { disabledLabel ?? normalCtaLabelFallback } ) : ( ) }