Skip to content
3 changes: 2 additions & 1 deletion src/CardSchemeComponent.res
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module CoBadgeCardSchemeDropDown = {
@react.component
let make = (~eligibleCardSchemes, ~setCardBrand) => {
let loggerState = Recoil.useRecoilValueFromAtom(RecoilAtoms.loggerAtom)
let {localeString} = Recoil.useRecoilValueFromAtom(RecoilAtoms.configAtom)
<select
className="w-4"
onClick={_ =>
Expand All @@ -11,7 +12,7 @@ module CoBadgeCardSchemeDropDown = {
let value = target["value"]
setCardBrand(_ => value)
}}>
<option disabled=true> {"Select a card brand"->React.string} </option>
<option disabled=true> {localeString.selectCardBrandText->React.string} </option>
{eligibleCardSchemes
->Array.mapWithIndex((item, i) => {
<option key={Int.toString(i)} value=item> {item->React.string} </option>
Expand Down
2 changes: 1 addition & 1 deletion src/Components/AccordionContainer.res
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ let make = (
<div className="m-2">
<Icon size=10 name="arrow-down" />
</div>
<div className="AccordionItemLabel"> {React.string("More")} </div>
<div className="AccordionItemLabel"> {React.string(localeString.moreText)} </div>
</div>
</button>
</RenderIf>
Expand Down
8 changes: 5 additions & 3 deletions src/Components/AddBankAccount.res
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ open Utils
module ToolTip = {
@react.component
let make = (~openTip, ~forwardRef, ~onclick) => {
let {themeObj} = Recoil.useRecoilValueFromAtom(configAtom)
let {themeObj, localeString} = Recoil.useRecoilValueFromAtom(configAtom)
<RenderIf condition={openTip}>
<button
className="h-auto max-w-30 w-auto cursor-pointer absolute m-1 px-1 py-2 top-[-3rem] right-[1em]"
Expand All @@ -21,7 +21,7 @@ module ToolTip = {
}
onClick={ev => onclick(ev)}
ref={forwardRef->ReactDOM.Ref.domRef}>
{React.string("Remove account")}
{React.string(localeString.removeAccountText)}
</button>
</RenderIf>
}
Expand Down Expand Up @@ -70,7 +70,9 @@ let make = (~modalData, ~setModalData) => {
<div>
<Icon size=22 name="bank" />
</div>
<div className="tracking-wider"> {React.string(`Bank **** ${last4digts}`)} </div>
<div className="tracking-wider">
{React.string(localeString.bankAccountDisplayText(last4digts))}
</div>
</div>
<ToolTip
openTip=openToolTip forwardRef=toolTipRef onclick={_ => {setModalData(_ => None)}}
Expand Down
36 changes: 14 additions & 22 deletions src/Components/ClickToPayDetails.res
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ let make = (
~setIsClickToPayRememberMe,
) => {
let clickToPayConfig = Recoil.useRecoilValueFromAtom(RecoilAtoms.clickToPayConfig)
let {themeObj} = Recoil.useRecoilValueFromAtom(RecoilAtoms.configAtom)
let {themeObj, localeString} = Recoil.useRecoilValueFromAtom(RecoilAtoms.configAtom)
let {iframeId} = Recoil.useRecoilValueFromAtom(RecoilAtoms.keys)
let isUnrecognizedUser = clickToPayConfig.clickToPayCards->Option.getOr([])->Array.length == 0

Expand Down Expand Up @@ -78,15 +78,13 @@ let make = (
{!isUnrecognizedUser
? <div className="text-xs font-normal">
{React.string(
`By continuing, ${clickToPayConfig.dpaName} will share your card details, billing address,
and email with ${formattedCardBrand} to allow you to securely enroll in Click to
Pay for faster checkouts.`,
localeString.ctpConsentSharingText(clickToPayConfig.dpaName, formattedCardBrand),
)}
{React.string(" ")}
<span
className="underline decoration-1 underline-offset-2 cursor-pointer"
onClick={handleLearnMore}>
{React.string("Learn more")}
{React.string(localeString.learnMoreText)}
</span>
</div>
: <>
Expand All @@ -104,18 +102,18 @@ let make = (
className={`CheckboxLabel ${isSaveDetailsCheckBoxLabelState} ml-2 w-11/12 text-xs space-y-2`}
style={color: "#a9a9a9"}>
<div>
{React.string(`Save my information with ${formattedCardBrand} `)}
{React.string(localeString.ctpSaveInfoText(formattedCardBrand))}
<span
className="underline decoration-1 underline-offset-2 cursor-pointer"
onClick={handleLearnMore}>
{React.string("Click to Pay")}
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.

Localization is missing for "Click to Pay".

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

""Click to Pay" is a registered brand name (like "Google Pay" or "Apple Pay"). All 16 existing non-English locale files already use "Click to Pay" untranslated — see ctpConsentSharingText, ctpRememberMeTooltipLine1, ctpSaveInfoText, etc. throughout every locale. Translating it would be incorrect per brand guidelines."

</span>
{React.string(" ")}
{React.string("for a faster and secure checkout")}
{React.string(localeString.ctpFasterCheckoutText)}
</div>
<div>
{React.string("Your email or mobile number will be used to verify you.")}
{React.string("Message/data rates may apply.")}
{React.string(localeString.ctpVerifyIdentityText)}
{React.string(localeString.ctpDataRatesText)}
</div>
</div>
</div>
Expand All @@ -132,7 +130,7 @@ let make = (
className={`CheckboxLabel ${isRememberMeCheckBoxLabelState} ml-2 w-11/12 text-xs space-y-2`}
style={color: "#a9a9a9"}>
<div className="flex items-center">
{React.string("Remember me on this browser")}
{React.string(localeString.ctpRememberMeText)}
<div className="relative inline-block ml-2">
<div className="group cursor-help">
<div
Expand All @@ -145,32 +143,26 @@ let make = (
className="invisible group-hover:visible absolute z-10 w-64 bg-white text-xs rounded-md p-2 left-1/2 transform -translate-x-1/2 bottom-[150%] shadow-md border border-gray-200 before:content-[''] before:absolute before:top-[100%] before:left-1/2 before:ml-[-5px] before:border-[5px] before:border-solid before:border-gray-200 before:border-b-transparent before:border-l-transparent before:border-r-transparent after:content-[''] after:absolute after:top-[100%] after:left-1/2 after:ml-[-4px] after:border-[4px] after:border-solid after:border-white after:border-b-transparent after:border-l-transparent after:border-r-transparent">
// {/* Content */}
<div className="flex flex-col space-y-2">
<span>
{React.string("When remembered, you'll skip verification and securely")}
{React.string("access your saved cards when paying with Click to Pay.")}
</span>
<span>
{React.string("Not recommended for public or shared devices because")}
{React.string("this uses cookies.")}
</span>
<span> {React.string(localeString.ctpRememberMeTooltipLine1)} </span>
<span> {React.string(localeString.ctpRememberMeTooltipLine2)} </span>
</div>
</div>
</div>
</div>
</div>
<div>
{React.string(`By continuing, you agree to ${formattedCardBrand}'s `)}
{React.string(localeString.ctpTermsConsentText(formattedCardBrand))}
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.

[MEDIUM] "Click to Pay" brand string is still hardcoded inline within a localized sentence

The surrounding text (ctpTermsConsentText, termsText, ctpPrivacyConsentText) is localized, but the brand name is inlined. For RTL locales (Arabic, Hebrew — both in this PR's locale set), mixing an LTR brand string without explicit directionality causes bidi rendering issues. It also creates word-order fragility in languages that don't follow English noun placement.

Fix (minimal): Wrap with explicit dir="ltr":

<span dir="ltr"> {React.string("Click to Pay")} </span>

Fix (proper): Add a ctpBrandName locale key and include it in all locale files.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

"Pre-existing pattern, not introduced by this PR. "Click to Pay" appears without dir=\"ltr\" in every existing CTP locale string throughout the codebase (ctpConsentSharingText, ctpRememberMeTooltipLine1, ctpSaveInfoText, ctpFasterCheckoutText, etc.). Adding RTL-safe wrapping to CTP strings would be a separate refactor across all locale files."

<span
className="underline decoration-1 underline-offset-2 cursor-pointer"
onClick={ev => handleOpenUrl(ev, getTermsUrl())}>
{React.string("Terms")}
{React.string(localeString.termsText)}
</span>
{React.string(" ")}
{React.string("and understand your data will be processed according to the ")}
{React.string(localeString.ctpPrivacyConsentText)}
<span
className="underline decoration-1 underline-offset-2 cursor-pointer"
onClick={ev => handleOpenUrl(ev, getPrivacyNoticeUrl())}>
{React.string("Privacy Notice")}
{React.string(localeString.privacyNoticeText)}
</span>
{React.string(".")}
</div>
Expand Down
25 changes: 12 additions & 13 deletions src/Components/ClickToPayNotYou.res
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ open Utils

@react.component
let make = (~setIsShowClickToPayNotYou, ~isCTPAuthenticateNotYouClicked, ~getVisaCards) => {
let {themeObj} = Recoil.useRecoilValueFromAtom(RecoilAtoms.configAtom)
let {themeObj, localeString} = Recoil.useRecoilValueFromAtom(RecoilAtoms.configAtom)
let (clickToPayConfig, setClickToPayConfig) = Recoil.useRecoilState(RecoilAtoms.clickToPayConfig)

let (identifier, setIdentifier) = React.useState(_ => "")
Expand Down Expand Up @@ -157,7 +157,7 @@ let make = (~setIsShowClickToPayNotYou, ~isCTPAuthenticateNotYouClicked, ~getVis
<div className="flex space-x-2 text-sm text-[#484848]">
<button
onClick={onNotYouClick} className="underline cursor-pointer [text-underline-offset:0.2rem]">
{React.string("Not you?")}
{React.string(localeString.notYouText)}
</button>
</div>
}
Expand All @@ -178,11 +178,7 @@ let make = (~setIsShowClickToPayNotYou, ~isCTPAuthenticateNotYouClicked, ~getVis
</div>
</div>
<div className="flex flex-col justify-center items-center space-y-4 px-4">
<p className="text-sm font-normal">
{React.string(
"Enter a new email or mobile number to access a different set of linked cards.",
)}
</p>
<p className="text-sm font-normal"> {React.string(localeString.ctpSwitchIdentifierText)} </p>
<form
onSubmit={handleSubmit}
className="w-full flex flex-col justify-center items-center space-y-4">
Expand All @@ -192,9 +188,11 @@ let make = (~setIsShowClickToPayNotYou, ~isCTPAuthenticateNotYouClicked, ~getVis
value={identifierType->getIdentityType}
onChange={handleTypeChange}
className="w-full p-3 pr-10 border border-gray-300 rounded-md appearance-none">
<option value={EMAIL_ADDRESS->getIdentityType}> {React.string("Email")} </option>
<option value={EMAIL_ADDRESS->getIdentityType}>
{React.string(localeString.emailLabel)}
</option>
<option value={MOBILE_PHONE_NUMBER->getIdentityType}>
{React.string("Phone")}
{React.string(localeString.phoneLabel)}
</option>
</select>
<div
Expand All @@ -209,7 +207,7 @@ let make = (~setIsShowClickToPayNotYou, ~isCTPAuthenticateNotYouClicked, ~getVis
type_="text"
value={identifier}
onChange={handleInputChange}
placeholder="Enter email"
placeholder=localeString.enterEmailPlaceholder
className="w-2/3 p-3 border border-gray-300 rounded-md"
required=true
/>
Expand Down Expand Up @@ -241,7 +239,7 @@ let make = (~setIsShowClickToPayNotYou, ~isCTPAuthenticateNotYouClicked, ~getVis
type_="tel"
value={identifier}
onChange={handlePhoneInputChange}
placeholder="Mobile number"
placeholder=localeString.mobileNumberPlaceholder
className="flex-grow p-3 focus:outline-none w-full"
required=true
/>
Expand All @@ -257,7 +255,7 @@ let make = (~setIsShowClickToPayNotYou, ~isCTPAuthenticateNotYouClicked, ~getVis
fontSize: themeObj.buttonTextFontSize,
}
disabled={!isValid}>
{React.string("Switch ID")}
{React.string(localeString.switchIdButtonText)}
</button>
</form>
</div>
Expand All @@ -267,14 +265,15 @@ let make = (~setIsShowClickToPayNotYou, ~isCTPAuthenticateNotYouClicked, ~getVis
module ClickToPayNotYouText = {
@react.component
let make = (~setIsShowClickToPayNotYou) => {
let {localeString} = Recoil.useRecoilValueFromAtom(RecoilAtoms.configAtom)
let onNotYouClick = _ => {
setIsShowClickToPayNotYou(_ => true)
}

<div className="flex space-x-2 text-sm text-[#484848]">
<button
onClick={onNotYouClick} className="underline cursor-pointer [text-underline-offset:0.2rem]">
{React.string("Not you?")}
{React.string(localeString.notYouText)}
</button>
</div>
}
Expand Down
3 changes: 2 additions & 1 deletion src/Components/ErrorOccured.res
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
@react.component
let make = () => {
let {localeString} = Recoil.useRecoilValueFromAtom(RecoilAtoms.configAtom)
<div className="flex justify-center font-bold text-lg text-red-600">
{React.string("Error occurred")}
{React.string(localeString.errorOccurredText)}
</div>
}
9 changes: 4 additions & 5 deletions src/Components/Loader.res
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
@react.component
let make = (~branding="auto", ~showText=true) => {
let {localeString} = Recoil.useRecoilValueFromAtom(RecoilAtoms.configAtom)
let arr = ["hyperswitch-triangle", "hyperswitch-square", "hyperswitch-circle"]

<div className="flex flex-col gap-10 justify-center items-center">
Expand All @@ -25,20 +26,18 @@ let make = (~branding="auto", ~showText=true) => {
role="status">
<span
className="!absolute !-m-px !h-px !w-px !overflow-hidden !whitespace-nowrap !border-0 !p-0 ![clip:rect(0,0,0,0)]">
{"Loading..."->React.string}
{localeString.loadingText->React.string}
</span>
</div>
</RenderIf>
</div>
<RenderIf condition={showText}>
<div className="flex flex-col gap-5">
<div className="font-semibold text-sm text-gray-200 self-center ">
{React.string("We are processing your payment...")}
{React.string(localeString.processingPaymentText)}
</div>
<div className="font-medium text-xs text-gray-400 self-center text-center w-3/4 ">
{React.string(
"You have been redirected to new tab to complete your payments. Status will be updated automatically",
)}
{React.string(localeString.redirectedToNewTabText)}
</div>
</div>
</RenderIf>
Expand Down
4 changes: 2 additions & 2 deletions src/Components/SavedMethodItemV2.res
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ let make = (
<div
className={`flex flex-row items-center justify-end gap-3 -mt-1`}
style={fontSize: "14px", opacity: "0.5"}>
<div> {React.string(`Expiry`)} </div>
<div> {React.string(localeString.validThruText)} </div>
<div className="flex">
{React.string(
`${expiryMonth} / ${expiryYear->CardUtils.formatExpiryToTwoDigit}`,
Expand All @@ -154,7 +154,7 @@ let make = (
ReactEvent.Mouse.stopPropagation(event)
handleUpdate(paymentItem)->ignore
}}>
{React.string("Save")}
{React.string(localeString.formSaveText)}
</div>
<Icon
size=18
Expand Down
Loading
Loading