diff --git a/src/components/AddressForm.tsx b/src/components/AddressForm.tsx index 9ad4643e834a..bd3ad7ea0888 100644 --- a/src/components/AddressForm.tsx +++ b/src/components/AddressForm.tsx @@ -96,7 +96,7 @@ function AddressForm({ // Check "State" dropdown is a valid state if selected Country is USA if (values.country === CONST.COUNTRY.US && !values.state) { - errors.state = 'common.error.fieldRequired'; + errors.state = translate('common.error.fieldRequired'); } // Add "Field required" errors if any required field is empty @@ -106,7 +106,7 @@ function AddressForm({ return; } - errors[fieldKey] = 'common.error.fieldRequired'; + errors[fieldKey] = translate('common.error.fieldRequired'); }); // If no country is selected, default value is an empty string and there's no related regex data so we default to an empty object @@ -131,7 +131,7 @@ function AddressForm({ } return errors; - }, []); + }, [translate]); return ( string); /** Form Error description */ - errorText?: MaybePhraseKey; + errorText?: string; /** Callback to call when the input changes */ onInputChange?: (value: string | undefined) => void; diff --git a/src/components/CheckboxWithLabel.tsx b/src/components/CheckboxWithLabel.tsx index dd169576186e..db62aa9e1441 100644 --- a/src/components/CheckboxWithLabel.tsx +++ b/src/components/CheckboxWithLabel.tsx @@ -3,7 +3,6 @@ import React, {useState} from 'react'; import type {StyleProp, ViewStyle} from 'react-native'; import {View} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; -import type {MaybePhraseKey} from '@libs/Localize'; import variables from '@styles/variables'; import Checkbox from './Checkbox'; import FormHelpMessage from './FormHelpMessage'; @@ -41,7 +40,7 @@ type CheckboxWithLabelProps = RequiredLabelProps & { style?: StyleProp; /** Error text to display */ - errorText?: MaybePhraseKey; + errorText?: string; /** Value for checkbox. This prop is intended to be set by FormProvider only */ value?: boolean; diff --git a/src/components/CountrySelector.tsx b/src/components/CountrySelector.tsx index 002c0c6d4b0a..62fdc85687e1 100644 --- a/src/components/CountrySelector.tsx +++ b/src/components/CountrySelector.tsx @@ -4,7 +4,6 @@ import type {ForwardedRef} from 'react'; import type {View} from 'react-native'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import type {MaybePhraseKey} from '@libs/Localize'; import Navigation from '@libs/Navigation/Navigation'; import CONST from '@src/CONST'; import type {Country} from '@src/CONST'; @@ -13,7 +12,7 @@ import MenuItemWithTopDescription from './MenuItemWithTopDescription'; type CountrySelectorProps = { /** Form error text. e.g when no country is selected */ - errorText?: MaybePhraseKey; + errorText?: string; /** Callback called when the country changes. */ onInputChange?: (value?: string) => void; diff --git a/src/components/DotIndicatorMessage.tsx b/src/components/DotIndicatorMessage.tsx index 3f72bbf429aa..f1aa8243b327 100644 --- a/src/components/DotIndicatorMessage.tsx +++ b/src/components/DotIndicatorMessage.tsx @@ -23,7 +23,7 @@ type DotIndicatorMessageProps = { * timestamp: 'message', * } */ - messages: Record; + messages: Record; /** The type of message, 'error' shows a red dot, 'success' shows a green dot */ type: 'error' | 'success'; diff --git a/src/components/FormAlertWithSubmitButton.tsx b/src/components/FormAlertWithSubmitButton.tsx index 137012478549..cd177a1d77a3 100644 --- a/src/components/FormAlertWithSubmitButton.tsx +++ b/src/components/FormAlertWithSubmitButton.tsx @@ -2,13 +2,12 @@ import React from 'react'; import type {StyleProp, ViewStyle} from 'react-native'; import {View} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; -import type {MaybePhraseKey} from '@libs/Localize'; import Button from './Button'; import FormAlertWrapper from './FormAlertWrapper'; type FormAlertWithSubmitButtonProps = { /** Error message to display above button */ - message?: MaybePhraseKey; + message?: string; /** Whether the button is disabled */ isDisabled?: boolean; diff --git a/src/components/FormAlertWrapper.tsx b/src/components/FormAlertWrapper.tsx index d8b379208a29..525182070095 100644 --- a/src/components/FormAlertWrapper.tsx +++ b/src/components/FormAlertWrapper.tsx @@ -4,7 +4,6 @@ import type {StyleProp, ViewStyle} from 'react-native'; import {View} from 'react-native'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import type {MaybePhraseKey} from '@libs/Localize'; import type Network from '@src/types/onyx/Network'; import FormHelpMessage from './FormHelpMessage'; import {withNetwork} from './OnyxProvider'; @@ -29,7 +28,7 @@ type FormAlertWrapperProps = { isMessageHtml?: boolean; /** Error message to display above button */ - message?: MaybePhraseKey; + message?: string; /** Props to detect online status */ network: Network; diff --git a/src/components/FormHelpMessage.tsx b/src/components/FormHelpMessage.tsx index 4f1d784788bf..01a5a1eaf3a8 100644 --- a/src/components/FormHelpMessage.tsx +++ b/src/components/FormHelpMessage.tsx @@ -4,14 +4,13 @@ import type {StyleProp, ViewStyle} from 'react-native'; import {View} from 'react-native'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import * as Localize from '@libs/Localize'; import Icon from './Icon'; import * as Expensicons from './Icon/Expensicons'; import Text from './Text'; type FormHelpMessageProps = { /** Error or hint text. Ignored when children is not empty */ - message?: Localize.MaybePhraseKey; + message?: string; /** Children to render next to dot indicator */ children?: React.ReactNode; @@ -33,8 +32,6 @@ function FormHelpMessage({message = '', children, isError = true, style, shouldS return null; } - const translatedMessage = Localize.translateIfPhraseKey(message); - return ( {isError && shouldShowRedDotIndicator && ( @@ -44,7 +41,7 @@ function FormHelpMessage({message = '', children, isError = true, style, shouldS /> )} - {children ?? {translatedMessage}} + {children ?? {message}} ); diff --git a/src/components/MagicCodeInput.tsx b/src/components/MagicCodeInput.tsx index deff56a534ee..6239243cb5ab 100644 --- a/src/components/MagicCodeInput.tsx +++ b/src/components/MagicCodeInput.tsx @@ -7,7 +7,6 @@ import useNetwork from '@hooks/useNetwork'; import useStyleUtils from '@hooks/useStyleUtils'; import useThemeStyles from '@hooks/useThemeStyles'; import * as Browser from '@libs/Browser'; -import type {MaybePhraseKey} from '@libs/Localize'; import * as ValidationUtils from '@libs/ValidationUtils'; import CONST from '@src/CONST'; import FormHelpMessage from './FormHelpMessage'; @@ -33,7 +32,7 @@ type MagicCodeInputProps = { shouldDelayFocus?: boolean; /** Error text to display */ - errorText?: MaybePhraseKey; + errorText?: string; /** Specifies autocomplete hints for the system, so it can provide autofill */ autoComplete: AutoCompleteVariant; diff --git a/src/components/MenuItem.tsx b/src/components/MenuItem.tsx index b6f378763659..dd3cf462f89e 100644 --- a/src/components/MenuItem.tsx +++ b/src/components/MenuItem.tsx @@ -14,7 +14,6 @@ import ControlSelection from '@libs/ControlSelection'; import convertToLTR from '@libs/convertToLTR'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; import getButtonState from '@libs/getButtonState'; -import type {MaybePhraseKey} from '@libs/Localize'; import type {AvatarSource} from '@libs/UserUtils'; import variables from '@styles/variables'; import * as Session from '@userActions/Session'; @@ -151,13 +150,13 @@ type MenuItemBaseProps = { shouldShowDescriptionOnTop?: boolean; /** Error to display at the bottom of the component */ - errorText?: MaybePhraseKey; + errorText?: string; /** Any additional styles to pass to error text. */ errorTextStyle?: StyleProp; /** Hint to display at the bottom of the component */ - hintText?: MaybePhraseKey; + hintText?: string; /** Should the error text red dot indicator be shown */ shouldShowRedDotIndicator?: boolean; diff --git a/src/components/MessagesRow.tsx b/src/components/MessagesRow.tsx index 7c764ec94fcd..2aead5da334c 100644 --- a/src/components/MessagesRow.tsx +++ b/src/components/MessagesRow.tsx @@ -4,9 +4,7 @@ import {View} from 'react-native'; import useLocalize from '@hooks/useLocalize'; import useTheme from '@hooks/useTheme'; import useThemeStyles from '@hooks/useThemeStyles'; -import type * as Localize from '@libs/Localize'; import CONST from '@src/CONST'; -import type {ReceiptError} from '@src/types/onyx/Transaction'; import {isEmptyObject} from '@src/types/utils/EmptyObject'; import DotIndicatorMessage from './DotIndicatorMessage'; import Icon from './Icon'; @@ -16,7 +14,7 @@ import Tooltip from './Tooltip'; type MessagesRowProps = { /** The messages to display */ - messages: Record; + messages: Record; /** The type of message, 'error' shows a red dot, 'success' shows a green dot */ type: 'error' | 'success'; diff --git a/src/components/MoneyRequestConfirmationList.tsx b/src/components/MoneyRequestConfirmationList.tsx index b18a98b13304..31fcdaa4843e 100755 --- a/src/components/MoneyRequestConfirmationList.tsx +++ b/src/components/MoneyRequestConfirmationList.tsx @@ -347,11 +347,11 @@ function MoneyRequestConfirmationList({ useEffect(() => { if (shouldDisplayFieldError && hasSmartScanFailed) { - setFormError('iou.receiptScanningFailed'); + setFormError(translate('iou.receiptScanningFailed')); return; } if (shouldDisplayFieldError && didConfirmSplit) { - setFormError('iou.error.genericSmartscanFailureMessage'); + setFormError(translate('iou.error.genericSmartscanFailureMessage')); return; } // reset the form error whenever the screen gains or loses focus @@ -431,7 +431,7 @@ function MoneyRequestConfirmationList({ const shares: number[] = Object.values(splitSharesMap).map((splitShare) => splitShare?.amount ?? 0); const sumOfShares = shares?.reduce((prev, current): number => prev + current, 0); if (sumOfShares !== iouAmount) { - setFormError('iou.error.invalidSplit'); + setFormError(translate('iou.error.invalidSplit')); return; } @@ -441,7 +441,7 @@ function MoneyRequestConfirmationList({ // A split must have at least two participants with amounts bigger than 0 if (participantsWithAmount.length === 1) { - setFormError('iou.error.invalidSplitParticipants'); + setFormError(translate('iou.error.invalidSplitParticipants')); return; } @@ -698,11 +698,11 @@ function MoneyRequestConfirmationList({ return; } if (!isEditingSplitBill && isMerchantRequired && (isMerchantEmpty || (shouldDisplayFieldError && TransactionUtils.isMerchantMissing(transaction ?? null)))) { - setFormError('iou.error.invalidMerchant'); + setFormError(translate('iou.error.invalidMerchant')); return; } if (iouCategory.length > CONST.API_TRANSACTION_CATEGORY_MAX_LENGTH) { - setFormError('iou.error.invalidCategoryLength'); + setFormError(translate('iou.error.invalidCategoryLength')); return; } @@ -738,24 +738,7 @@ function MoneyRequestConfirmationList({ onConfirm?.(selectedParticipants); } }, - [ - selectedParticipants, - isMerchantRequired, - isMerchantEmpty, - shouldDisplayFieldError, - transaction, - iouType, - onSendMoney, - iouCurrencyCode, - isDistanceRequest, - iouCategory, - isDistanceRequestWithPendingRoute, - iouAmount, - isEditingSplitBill, - formError, - setFormError, - onConfirm, - ], + [selectedParticipants, isEditingSplitBill, isMerchantRequired, isMerchantEmpty, shouldDisplayFieldError, transaction, iouCategory.length, formError, iouType, setFormError, translate, onSendMoney, iouCurrencyCode, isDistanceRequest, isDistanceRequestWithPendingRoute, iouAmount, onConfirm], ); const footerContent = useMemo(() => { diff --git a/src/components/PDFView/PDFPasswordForm.tsx b/src/components/PDFView/PDFPasswordForm.tsx index e1ef83c9b60d..e571c2830b3c 100644 --- a/src/components/PDFView/PDFPasswordForm.tsx +++ b/src/components/PDFView/PDFPasswordForm.tsx @@ -47,7 +47,7 @@ function PDFPasswordForm({isFocused, isPasswordInvalid = false, shouldShowLoadin const errorText = useMemo(() => { if (isPasswordInvalid) { - return 'attachmentView.passwordIncorrect'; + return translate('attachmentView.passwordIncorrect'); } if (validationErrorText) { return validationErrorText; diff --git a/src/components/Picker/types.ts b/src/components/Picker/types.ts index d935ebe8fdc5..a6a942f41f26 100644 --- a/src/components/Picker/types.ts +++ b/src/components/Picker/types.ts @@ -1,6 +1,5 @@ import type {ChangeEvent, Component, ReactElement} from 'react'; import type {MeasureLayoutOnSuccessCallback, NativeMethods, StyleProp, ViewStyle} from 'react-native'; -import type {MaybePhraseKey} from '@libs/Localize'; type MeasureLayoutOnFailCallback = () => void; @@ -59,7 +58,7 @@ type BasePickerProps = { placeholder?: PickerPlaceholder; /** Error text to display */ - errorText?: MaybePhraseKey; + errorText?: string; /** Customize the BasePicker container */ containerStyles?: StyleProp; diff --git a/src/components/RadioButtonWithLabel.tsx b/src/components/RadioButtonWithLabel.tsx index 9b93d7900772..94265c19645d 100644 --- a/src/components/RadioButtonWithLabel.tsx +++ b/src/components/RadioButtonWithLabel.tsx @@ -3,7 +3,6 @@ import React from 'react'; import type {StyleProp, ViewStyle} from 'react-native'; import {View} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; -import type {MaybePhraseKey} from '@libs/Localize'; import FormHelpMessage from './FormHelpMessage'; import * as Pressables from './Pressable'; import RadioButton from './RadioButton'; @@ -29,7 +28,7 @@ type RadioButtonWithLabelProps = { hasError?: boolean; /** Error text to display */ - errorText?: MaybePhraseKey; + errorText?: string; }; const PressableWithFeedback = Pressables.PressableWithFeedback; diff --git a/src/components/RadioButtons.tsx b/src/components/RadioButtons.tsx index 2030ce8f0bfd..07e8fe38f772 100644 --- a/src/components/RadioButtons.tsx +++ b/src/components/RadioButtons.tsx @@ -3,7 +3,6 @@ import type {ForwardedRef} from 'react'; import {View} from 'react-native'; import type {StyleProp, ViewStyle} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; -import type {MaybePhraseKey} from '@libs/Localize'; import FormHelpMessage from './FormHelpMessage'; import RadioButtonWithLabel from './RadioButtonWithLabel'; @@ -24,7 +23,7 @@ type RadioButtonsProps = { onPress: (value: string) => void; /** Potential error text provided by a form InputWrapper */ - errorText?: MaybePhraseKey; + errorText?: string; /** Style for radio button */ radioButtonStyle?: StyleProp; diff --git a/src/components/SingleChoiceQuestion.tsx b/src/components/SingleChoiceQuestion.tsx index 3ff844dd80e9..c2dc72438e43 100644 --- a/src/components/SingleChoiceQuestion.tsx +++ b/src/components/SingleChoiceQuestion.tsx @@ -3,14 +3,13 @@ import React, {forwardRef} from 'react'; // eslint-disable-next-line no-restricted-imports import type {Text as RNText} from 'react-native'; import useThemeStyles from '@hooks/useThemeStyles'; -import type {MaybePhraseKey} from '@libs/Localize'; import type {Choice} from './RadioButtons'; import RadioButtons from './RadioButtons'; import Text from './Text'; type SingleChoiceQuestionProps = { prompt: string; - errorText?: MaybePhraseKey; + errorText?: string; possibleAnswers: Choice[]; currentQuestionIndex: number; onInputChange: (value: string) => void; diff --git a/src/components/StateSelector.tsx b/src/components/StateSelector.tsx index 8cae007679ff..0733cb519f2c 100644 --- a/src/components/StateSelector.tsx +++ b/src/components/StateSelector.tsx @@ -6,7 +6,6 @@ import type {View} from 'react-native'; import useGeographicalStateFromRoute from '@hooks/useGeographicalStateFromRoute'; import useLocalize from '@hooks/useLocalize'; import useThemeStyles from '@hooks/useThemeStyles'; -import type {MaybePhraseKey} from '@libs/Localize'; import Navigation from '@libs/Navigation/Navigation'; import CONST from '@src/CONST'; import ROUTES from '@src/ROUTES'; @@ -17,7 +16,7 @@ type State = keyof typeof COMMON_CONST.STATES; type StateSelectorProps = { /** Form error text. e.g when no state is selected */ - errorText?: MaybePhraseKey; + errorText?: string; /** Current selected state */ value?: State | ''; diff --git a/src/components/TextInput/BaseTextInput/types.ts b/src/components/TextInput/BaseTextInput/types.ts index e8e2d5ab352d..7a46cca693e3 100644 --- a/src/components/TextInput/BaseTextInput/types.ts +++ b/src/components/TextInput/BaseTextInput/types.ts @@ -1,6 +1,5 @@ import type {GestureResponderEvent, StyleProp, TextInputProps, TextStyle, ViewStyle} from 'react-native'; import type {AnimatedTextInputRef} from '@components/RNTextInput'; -import type {MaybePhraseKey} from '@libs/Localize'; import type IconAsset from '@src/types/utils/IconAsset'; type CustomBaseTextInputProps = { @@ -20,7 +19,7 @@ type CustomBaseTextInputProps = { placeholder?: string; /** Error text to display */ - errorText?: MaybePhraseKey; + errorText?: string; /** Icon to display in right side of text input */ icon?: IconAsset | null; @@ -68,7 +67,7 @@ type CustomBaseTextInputProps = { hideFocusedState?: boolean; /** Hint text to display below the TextInput */ - hint?: MaybePhraseKey; + hint?: string; /** Prefix character */ prefixCharacter?: string; diff --git a/src/components/TextPicker/types.ts b/src/components/TextPicker/types.ts index 179d16a07262..cbdc1ed21efe 100644 --- a/src/components/TextPicker/types.ts +++ b/src/components/TextPicker/types.ts @@ -1,6 +1,5 @@ import type {MenuItemBaseProps} from '@components/MenuItem'; import type {BaseTextInputProps} from '@components/TextInput/BaseTextInput/types'; -import type {MaybePhraseKey} from '@libs/Localize'; type TextProps = Exclude; @@ -30,7 +29,7 @@ type TextPickerProps = { placeholder?: string; /** Form Error description */ - errorText?: MaybePhraseKey; + errorText?: string; /** Callback to call when the input changes */ onInputChange?: (value: string | undefined) => void; diff --git a/src/components/TimePicker/TimePicker.tsx b/src/components/TimePicker/TimePicker.tsx index aecaf74dc4a3..8905abd370fe 100644 --- a/src/components/TimePicker/TimePicker.tsx +++ b/src/components/TimePicker/TimePicker.tsx @@ -135,15 +135,15 @@ function TimePicker({defaultValue = '', onSubmit, onInputChange = () => {}}: Tim const hour = parseInt(hourStr, 10); if (hour === 0) { setError(true); - setErrorMessage('common.error.invalidTimeRange'); + setErrorMessage(translate('common.error.invalidTimeRange')); return false; } const isValid = DateUtils.isTimeAtLeastOneMinuteInFuture({timeString, dateTimeString: defaultValue}); setError(!isValid); - setErrorMessage('common.error.invalidTimeShouldBeFuture'); + setErrorMessage(translate('common.error.invalidTimeShouldBeFuture')); return isValid; }, - [hours, minutes, amPmValue, defaultValue], + [hours, minutes, amPmValue, defaultValue, translate], ); const resetHours = () => { diff --git a/src/components/ValuePicker/types.ts b/src/components/ValuePicker/types.ts index b9c2c89948d9..b57c9d32061a 100644 --- a/src/components/ValuePicker/types.ts +++ b/src/components/ValuePicker/types.ts @@ -1,5 +1,4 @@ import type {ListItem} from '@components/SelectionList/types'; -import type {MaybePhraseKey} from '@libs/Localize'; type ValuePickerListItem = ListItem & { value?: string; @@ -51,7 +50,7 @@ type ValuePickerProps = { placeholder?: string; /** Form Error description */ - errorText?: MaybePhraseKey; + errorText?: string; /** Callback to call when the input changes */ onInputChange?: (value: string | undefined) => void; diff --git a/src/libs/DateUtils.ts b/src/libs/DateUtils.ts index 8bd37ddd698d..75ae7ae3f043 100644 --- a/src/libs/DateUtils.ts +++ b/src/libs/DateUtils.ts @@ -648,7 +648,7 @@ const getDayValidationErrorKey = (inputDate: Date): string => { } if (isAfter(startOfDay(new Date()), startOfDay(inputDate))) { - return 'common.error.invalidDateShouldBeFuture'; + return Localize.translateLocal('common.error.invalidDateShouldBeFuture'); } return ''; }; @@ -662,7 +662,7 @@ const getDayValidationErrorKey = (inputDate: Date): string => { const getTimeValidationErrorKey = (inputTime: Date): string => { const timeNowPlusOneMinute = addMinutes(new Date(), 1); if (isBefore(inputTime, timeNowPlusOneMinute)) { - return 'common.error.invalidTimeShouldBeFuture'; + return Localize.translateLocal('common.error.invalidTimeShouldBeFuture'); } return ''; }; diff --git a/src/libs/ErrorUtils.ts b/src/libs/ErrorUtils.ts index 3487f05b9c05..af27dd5801f3 100644 --- a/src/libs/ErrorUtils.ts +++ b/src/libs/ErrorUtils.ts @@ -1,11 +1,11 @@ import mapValues from 'lodash/mapValues'; import CONST from '@src/CONST'; -import type {TranslationFlatObject, TranslationPaths} from '@src/languages/types'; +import type {TranslationFlatObject} from '@src/languages/types'; import type {ErrorFields, Errors} from '@src/types/onyx/OnyxCommon'; import type Response from '@src/types/onyx/Response'; import type {ReceiptError} from '@src/types/onyx/Transaction'; import DateUtils from './DateUtils'; -import * as Localize from './Localize'; +import type * as Localize from './Localize'; function getAuthenticateErrorMessage(response: Response): keyof TranslationFlatObject { switch (response.jsonCode) { @@ -53,15 +53,15 @@ function getMicroSecondOnyxErrorObject(error: Errors, errorKey?: number): ErrorF } // We can assume that if error is a string, it has already been translated because it is server error -function getErrorMessageWithTranslationData(error: Localize.MaybePhraseKey): Localize.MaybePhraseKey { - return typeof error === 'string' ? [error, {isTranslated: true}] : error; +function getErrorMessageWithTranslationData(error: string): string { + return error; } type OnyxDataWithErrors = { errors?: Errors | null; }; -function getLatestErrorMessage(onyxData: TOnyxData | null): Localize.MaybePhraseKey { +function getLatestErrorMessage(onyxData: TOnyxData | null): string { const errors = onyxData?.errors ?? {}; if (Object.keys(errors).length === 0) { @@ -69,7 +69,7 @@ function getLatestErrorMessage(onyxData: T } const key = Object.keys(errors).sort().reverse()[0]; - return getErrorMessageWithTranslationData(errors[key]); + return getErrorMessageWithTranslationData(errors[key] ?? ''); } function getLatestErrorMessageField(onyxData: TOnyxData): Errors { @@ -148,21 +148,20 @@ function getErrorsWithTranslationData(errors: Localize.MaybePhraseKey | Errors): * @param errors - An object containing current errors in the form * @param message - Message to assign to the inputID errors */ -function addErrorMessage(errors: Errors, inputID?: string | null, message?: TKey | Localize.MaybePhraseKey) { +function addErrorMessage(errors: Errors, inputID?: string | null, message?: string) { if (!message || !inputID) { return; } const errorList = errors; const error = errorList[inputID]; - const translatedMessage = Localize.translateIfPhraseKey(message); if (!error) { - errorList[inputID] = [translatedMessage, {isTranslated: true}]; + errorList[inputID] = [message]; } else if (typeof error === 'string') { - errorList[inputID] = [`${error}\n${translatedMessage}`, {isTranslated: true}]; + errorList[inputID] = [`${error}\n${message}`]; } else if (Array.isArray(error)) { - error[0] = `${error[0]}\n${translatedMessage}`; + error[0] = `${error[0]}\n${message}`; } } diff --git a/src/libs/ValidationUtils.ts b/src/libs/ValidationUtils.ts index 13fe326c2c1c..7fe73526a1a5 100644 --- a/src/libs/ValidationUtils.ts +++ b/src/libs/ValidationUtils.ts @@ -11,7 +11,7 @@ import type {OnyxFormKey} from '@src/ONYXKEYS'; import type {Report, TaxRates} from '@src/types/onyx'; import * as CardUtils from './CardUtils'; import DateUtils from './DateUtils'; -import type {MaybePhraseKey} from './Localize'; +import * as Localize from './Localize'; import * as LoginUtils from './LoginUtils'; import {parsePhoneNumber} from './PhoneNumber'; import StringUtils from './StringUtils'; @@ -112,7 +112,7 @@ function getFieldRequiredErrors(values: FormOnyxVal return; } - errors[fieldKey] = 'common.error.fieldRequired'; + errors[fieldKey] = Localize.translateLocal('common.error.fieldRequired'); }); return errors; @@ -191,7 +191,7 @@ function meetsMaximumAgeRequirement(date: string): boolean { /** * Validate that given date is in a specified range of years before now. */ -function getAgeRequirementError(date: string, minimumAge: number, maximumAge: number): MaybePhraseKey { +function getAgeRequirementError(date: string, minimumAge: number, maximumAge: number): Localize.MaybePhraseKey { const currentDate = startOfDay(new Date()); const testDate = parse(date, CONST.DATE.FNS_FORMAT_STRING, currentDate); @@ -222,14 +222,14 @@ function getDatePassedError(inputDate: string): string { // If input date is not valid, return an error if (!isValid(parsedDate)) { - return 'common.error.dateInvalid'; + return Localize.translateLocal('common.error.dateInvalid'); } // Clear time for currentDate so comparison is based solely on the date currentDate.setHours(0, 0, 0, 0); if (parsedDate < currentDate) { - return 'common.error.dateInvalid'; + return Localize.translateLocal('common.error.dateInvalid'); } return ''; diff --git a/src/libs/actions/TaxRate.ts b/src/libs/actions/TaxRate.ts index f8425cd0c40c..fd7fbe4e7d86 100644 --- a/src/libs/actions/TaxRate.ts +++ b/src/libs/actions/TaxRate.ts @@ -12,6 +12,7 @@ import INPUT_IDS from '@src/types/form/WorkspaceNewTaxForm'; import type {Policy, TaxRate, TaxRates} from '@src/types/onyx'; import type * as OnyxCommon from '@src/types/onyx/OnyxCommon'; import type {OnyxData} from '@src/types/onyx/Request'; +import { translateLocal } from '@libs/Localize'; let allPolicies: OnyxCollection; Onyx.connect({ @@ -39,7 +40,7 @@ const validateTaxName = (policy: Policy, values: FormOnyxValues) => { const errors: FormInputErrors = {}; if (isRequired && value[fieldKey].trim() === '') { - errors[fieldKey] = 'common.error.fieldRequired'; + errors[fieldKey] = translate('common.error.fieldRequired'); } return errors; }, - [fieldKey, isRequired], + [fieldKey, isRequired, translate], ); return ( diff --git a/src/pages/EnablePayments/AdditionalDetailsStep.tsx b/src/pages/EnablePayments/AdditionalDetailsStep.tsx index 4756db4d43ec..cc41738fa581 100644 --- a/src/pages/EnablePayments/AdditionalDetailsStep.tsx +++ b/src/pages/EnablePayments/AdditionalDetailsStep.tsx @@ -76,32 +76,32 @@ function AdditionalDetailsStep({walletAdditionalDetails = DEFAULT_WALLET_ADDITIO if (values.dob) { if (!ValidationUtils.isValidPastDate(values.dob) || !ValidationUtils.meetsMaximumAgeRequirement(values.dob)) { - errors.dob = 'bankAccount.error.dob'; + errors.dob = translate('bankAccount.error.dob'); } else if (!ValidationUtils.meetsMinimumAgeRequirement(values.dob)) { - errors.dob = 'bankAccount.error.age'; + errors.dob = translate('bankAccount.error.age'); } } if (values.addressStreet && !ValidationUtils.isValidAddress(values.addressStreet)) { - errors.addressStreet = 'bankAccount.error.addressStreet'; + errors.addressStreet = translate('bankAccount.error.addressStreet'); } if (values.addressZipCode && !ValidationUtils.isValidZipCode(values.addressZipCode)) { - errors.addressZipCode = 'bankAccount.error.zipCode'; + errors.addressZipCode = translate('bankAccount.error.zipCode'); } if (values.phoneNumber && !ValidationUtils.isValidUSPhone(values.phoneNumber, true)) { - errors.phoneNumber = 'bankAccount.error.phoneNumber'; + errors.phoneNumber = translate('bankAccount.error.phoneNumber'); } // walletAdditionalDetails stores errors returned by the server. If the server returns an SSN error // then the user needs to provide the full 9 digit SSN. if (walletAdditionalDetails?.errorCode === CONST.WALLET.ERROR.SSN) { if (values.ssn && !ValidationUtils.isValidSSNFullNine(values.ssn)) { - errors.ssn = 'additionalDetailsStep.ssnFull9Error'; + errors.ssn = translate('additionalDetailsStep.ssnFull9Error'); } } else if (values.ssn && !ValidationUtils.isValidSSNLastFour(values.ssn)) { - errors.ssn = 'bankAccount.error.ssnLast4'; + errors.ssn = translate('bankAccount.error.ssnLast4'); } return errors; diff --git a/src/pages/EnablePayments/FeesAndTerms/substeps/TermsStep.tsx b/src/pages/EnablePayments/FeesAndTerms/substeps/TermsStep.tsx index fe17ea7e1afb..261613ba9318 100644 --- a/src/pages/EnablePayments/FeesAndTerms/substeps/TermsStep.tsx +++ b/src/pages/EnablePayments/FeesAndTerms/substeps/TermsStep.tsx @@ -48,7 +48,7 @@ function TermsStep() { const [walletTerms] = useOnyx(ONYXKEYS.WALLET_TERMS); - const errorMessage = error ? 'common.error.acceptTerms' : ErrorUtils.getLatestErrorMessage(walletTerms ?? {}) ?? ''; + const errorMessage = error ? translate('common.error.acceptTerms') : ErrorUtils.getLatestErrorMessage(walletTerms ?? {}) ?? ''; const toggleDisclosure = () => { setHasAcceptedDisclosure(!hasAcceptedDisclosure); diff --git a/src/pages/EnablePayments/PersonalInfo/substeps/DateOfBirthStep.tsx b/src/pages/EnablePayments/PersonalInfo/substeps/DateOfBirthStep.tsx index cfd0f4c5e3f7..6d3a1ebe9d89 100644 --- a/src/pages/EnablePayments/PersonalInfo/substeps/DateOfBirthStep.tsx +++ b/src/pages/EnablePayments/PersonalInfo/substeps/DateOfBirthStep.tsx @@ -19,20 +19,6 @@ import INPUT_IDS from '@src/types/form/WalletAdditionalDetailsForm'; const PERSONAL_INFO_DOB_KEY = INPUT_IDS.PERSONAL_INFO_STEP.DOB; const STEP_FIELDS = [PERSONAL_INFO_DOB_KEY]; -const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - - if (values.dob) { - if (!ValidationUtils.isValidPastDate(values.dob) || !ValidationUtils.meetsMaximumAgeRequirement(values.dob)) { - errors.dob = 'bankAccount.error.dob'; - } else if (!ValidationUtils.meetsMinimumAgeRequirement(values.dob)) { - errors.dob = 'bankAccount.error.age'; - } - } - - return errors; -}; - const minDate = subYears(new Date(), CONST.DATE_BIRTH.MAX_AGE); const maxDate = subYears(new Date(), CONST.DATE_BIRTH.MIN_AGE_FOR_PAYMENT); @@ -40,6 +26,20 @@ function DateOfBirthStep({onNext, isEditing}: SubStepProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); + const validate = (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + + if (values.dob) { + if (!ValidationUtils.isValidPastDate(values.dob) || !ValidationUtils.meetsMaximumAgeRequirement(values.dob)) { + errors.dob = translate('bankAccount.error.dob'); + } else if (!ValidationUtils.meetsMinimumAgeRequirement(values.dob)) { + errors.dob = translate('bankAccount.error.age'); + } + } + + return errors; + }; + const [walletAdditionalDetails] = useOnyx(ONYXKEYS.WALLET_ADDITIONAL_DETAILS); const dobDefaultValue = walletAdditionalDetails?.[PERSONAL_INFO_DOB_KEY] ?? walletAdditionalDetails?.[PERSONAL_INFO_DOB_KEY] ?? ''; diff --git a/src/pages/EnablePayments/TermsStep.tsx b/src/pages/EnablePayments/TermsStep.tsx index 916a5200a2e0..b2afb8b49fd9 100644 --- a/src/pages/EnablePayments/TermsStep.tsx +++ b/src/pages/EnablePayments/TermsStep.tsx @@ -58,7 +58,7 @@ function TermsStep(props: TermsStepProps) { const [error, setError] = useState(false); const {translate} = useLocalize(); - const errorMessage = error ? 'common.error.acceptTerms' : ErrorUtils.getLatestErrorMessage(props.walletTerms ?? {}) ?? ''; + const errorMessage = error ? translate('common.error.acceptTerms') : ErrorUtils.getLatestErrorMessage(props.walletTerms ?? {}) ?? ''; const toggleDisclosure = () => { setHasAcceptedDisclosure(!hasAcceptedDisclosure); diff --git a/src/pages/OnboardingPurpose/BaseOnboardingPurpose.tsx b/src/pages/OnboardingPurpose/BaseOnboardingPurpose.tsx index 31ff883834cc..04281eef0d2e 100644 --- a/src/pages/OnboardingPurpose/BaseOnboardingPurpose.tsx +++ b/src/pages/OnboardingPurpose/BaseOnboardingPurpose.tsx @@ -83,7 +83,7 @@ function BaseOnboardingPurpose({shouldUseNativeStyles, shouldEnableMaxHeight, on Navigation.navigate(ROUTES.ONBOARDING_PERSONAL_DETAILS); }, [selectedPurpose]); - const [errorMessage, setErrorMessage] = useState<'onboarding.purpose.errorSelection' | 'onboarding.purpose.errorContinue' | ''>(''); + const [errorMessage, setErrorMessage] = useState(''); const menuItems: MenuItemProps[] = Object.values(CONST.ONBOARDING_CHOICES).map((choice) => { const translationKey = `onboarding.purpose.${choice}` as const; @@ -110,11 +110,11 @@ function BaseOnboardingPurpose({shouldUseNativeStyles, shouldEnableMaxHeight, on const handleOuterClick = useCallback(() => { if (!selectedPurpose) { - setErrorMessage('onboarding.purpose.errorSelection'); + setErrorMessage(translate('onboarding.purpose.errorSelection')); } else { - setErrorMessage('onboarding.purpose.errorContinue'); + setErrorMessage(translate('onboarding.purpose.errorContinue')); } - }, [selectedPurpose]); + }, [selectedPurpose, setErrorMessage, translate]); const onboardingLocalRef = useRef(null); useImperativeHandle(isFocused ? OnboardingRefManager.ref : onboardingLocalRef, () => ({handleOuterClick}), [handleOuterClick]); @@ -147,7 +147,7 @@ function BaseOnboardingPurpose({shouldUseNativeStyles, shouldEnableMaxHeight, on buttonText={translate('common.continue')} onSubmit={() => { if (!selectedPurpose) { - setErrorMessage('onboarding.purpose.errorSelection'); + setErrorMessage(translate('onboarding.purpose.errorSelection')); return; } setErrorMessage(''); diff --git a/src/pages/ReimbursementAccount/AddressFormFields.tsx b/src/pages/ReimbursementAccount/AddressFormFields.tsx index 48af00cd4925..2133c4c5bf2e 100644 --- a/src/pages/ReimbursementAccount/AddressFormFields.tsx +++ b/src/pages/ReimbursementAccount/AddressFormFields.tsx @@ -52,7 +52,7 @@ function AddressFormFields({shouldSaveDraft = false, defaultValues, values, erro value={values?.street} defaultValue={defaultValues?.street} onInputChange={onFieldChange} - errorText={errors?.street ? 'bankAccount.error.addressStreet' : ''} + errorText={errors?.street ? translate('bankAccount.error.addressStreet') : ''} renamedInputKeys={inputKeys} maxInputLength={CONST.FORM_CHARACTER_LIMIT} isLimitedToUSA @@ -68,7 +68,7 @@ function AddressFormFields({shouldSaveDraft = false, defaultValues, values, erro value={values?.city} defaultValue={defaultValues?.city} onChangeText={(value) => onFieldChange?.({city: value})} - errorText={errors?.city ? 'bankAccount.error.addressCity' : ''} + errorText={errors?.city ? translate('bankAccount.error.addressCity') : ''} containerStyles={styles.mt6} /> @@ -94,7 +94,7 @@ function AddressFormFields({shouldSaveDraft = false, defaultValues, values, erro value={values?.zipCode} defaultValue={defaultValues?.zipCode} onChangeText={(value) => onFieldChange?.({zipCode: value})} - errorText={errors?.zipCode ? 'bankAccount.error.zipCode' : ''} + errorText={errors?.zipCode ? translate('bankAccount.error.zipCode') : ''} maxLength={CONST.BANK_ACCOUNT.MAX_LENGTH.ZIP_CODE} hint={['common.zipCodeExampleFormat', {zipSampleFormat: CONST.COUNTRY_ZIP_REGEX_DATA.US.samples}]} containerStyles={styles.mt3} diff --git a/src/pages/ReimbursementAccount/BeneficialOwnerInfo/substeps/BeneficialOwnerDetailsFormSubsteps/DateOfBirthUBO.tsx b/src/pages/ReimbursementAccount/BeneficialOwnerInfo/substeps/BeneficialOwnerDetailsFormSubsteps/DateOfBirthUBO.tsx index f563692f0ae9..2173d19887ad 100644 --- a/src/pages/ReimbursementAccount/BeneficialOwnerInfo/substeps/BeneficialOwnerDetailsFormSubsteps/DateOfBirthUBO.tsx +++ b/src/pages/ReimbursementAccount/BeneficialOwnerInfo/substeps/BeneficialOwnerDetailsFormSubsteps/DateOfBirthUBO.tsx @@ -40,9 +40,9 @@ function DateOfBirthUBO({reimbursementAccountDraft, onNext, isEditing, beneficia if (values[dobInputID]) { if (!ValidationUtils.isValidPastDate(values[dobInputID]) || !ValidationUtils.meetsMaximumAgeRequirement(values[dobInputID])) { - errors[dobInputID] = 'bankAccount.error.dob'; + errors[dobInputID] = translate('bankAccount.error.dob'); } else if (!ValidationUtils.meetsMinimumAgeRequirement(values[dobInputID])) { - errors[dobInputID] = 'bankAccount.error.age'; + errors[dobInputID] = translate('bankAccount.error.age'); } } diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx index 6311a63a4059..5e0cd2f700c7 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/ConfirmationBusiness.tsx @@ -37,16 +37,6 @@ type States = keyof typeof COMMON_CONST.STATES; const BUSINESS_INFO_STEP_KEYS = INPUT_IDS.BUSINESS_INFO_STEP; const BUSINESS_INFO_STEP_INDEXES = CONST.REIMBURSEMENT_ACCOUNT.SUBSTEP_INDEX.BUSINESS_INFO; -const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, [BUSINESS_INFO_STEP_KEYS.HAS_NO_CONNECTION_TO_CANNABIS]); - - if (!values.hasNoConnectionToCannabis) { - errors.hasNoConnectionToCannabis = 'bankAccount.error.restrictedBusiness'; - } - - return errors; -}; - function ConfirmCompanyLabel() { const {translate} = useLocalize(); @@ -62,6 +52,16 @@ function ConfirmationBusiness({reimbursementAccount, reimbursementAccountDraft, const {translate} = useLocalize(); const styles = useThemeStyles(); + const validate = (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, [BUSINESS_INFO_STEP_KEYS.HAS_NO_CONNECTION_TO_CANNABIS]); + + if (!values.hasNoConnectionToCannabis) { + errors.hasNoConnectionToCannabis = translate('bankAccount.error.restrictedBusiness'); + } + + return errors; + }; + const values = useMemo(() => getSubstepValues(BUSINESS_INFO_STEP_KEYS, reimbursementAccountDraft, reimbursementAccount), [reimbursementAccount, reimbursementAccountDraft]); const defaultCheckboxState = reimbursementAccountDraft?.[BUSINESS_INFO_STEP_KEYS.HAS_NO_CONNECTION_TO_CANNABIS] ?? false; diff --git a/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx b/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx index 8fecbe46164f..14a6d03e0670 100644 --- a/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx +++ b/src/pages/ReimbursementAccount/BusinessInfo/substeps/IncorporationDateBusiness.tsx @@ -29,22 +29,22 @@ type IncorporationDateBusinessProps = IncorporationDateBusinessOnyxProps & SubSt const COMPANY_INCORPORATION_DATE_KEY = INPUT_IDS.BUSINESS_INFO_STEP.INCORPORATION_DATE; const STEP_FIELDS = [COMPANY_INCORPORATION_DATE_KEY]; -const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - - if (values.incorporationDate && !ValidationUtils.isValidDate(values.incorporationDate)) { - errors.incorporationDate = 'common.error.dateInvalid'; - } else if (values.incorporationDate && !ValidationUtils.isValidPastDate(values.incorporationDate)) { - errors.incorporationDate = 'bankAccount.error.incorporationDateFuture'; - } - - return errors; -}; - function IncorporationDateBusiness({reimbursementAccount, reimbursementAccountDraft, onNext, isEditing}: IncorporationDateBusinessProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); + const validate = (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + + if (values.incorporationDate && !ValidationUtils.isValidDate(values.incorporationDate)) { + errors.incorporationDate = translate('common.error.dateInvalid'); + } else if (values.incorporationDate && !ValidationUtils.isValidPastDate(values.incorporationDate)) { + errors.incorporationDate = translate('bankAccount.error.incorporationDateFuture'); + } + + return errors; + }; + const defaultCompanyIncorporationDate = reimbursementAccount?.achData?.incorporationDate ?? reimbursementAccountDraft?.incorporationDate ?? ''; const handleSubmit = useReimbursementAccountStepFormSubmit({ diff --git a/src/pages/ReimbursementAccount/CompleteVerification/substeps/ConfirmAgreements.tsx b/src/pages/ReimbursementAccount/CompleteVerification/substeps/ConfirmAgreements.tsx index 03a178f186ee..94d006d72f26 100644 --- a/src/pages/ReimbursementAccount/CompleteVerification/substeps/ConfirmAgreements.tsx +++ b/src/pages/ReimbursementAccount/CompleteVerification/substeps/ConfirmAgreements.tsx @@ -30,24 +30,6 @@ const STEP_FIELDS = [ INPUT_IDS.COMPLETE_VERIFICATION.CERTIFY_TRUE_INFORMATION, ]; -const validate = (values: FormOnyxValues): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - - if (!ValidationUtils.isRequiredFulfilled(values.acceptTermsAndConditions)) { - errors.acceptTermsAndConditions = 'common.error.acceptTerms'; - } - - if (!ValidationUtils.isRequiredFulfilled(values.certifyTrueInformation)) { - errors.certifyTrueInformation = 'completeVerificationStep.certifyTrueAndAccurateError'; - } - - if (!ValidationUtils.isRequiredFulfilled(values.isAuthorizedToUseBankAccount)) { - errors.isAuthorizedToUseBankAccount = 'completeVerificationStep.isAuthorizedToUseBankAccountError'; - } - - return errors; -}; - function IsAuthorizedToUseBankAccountLabel() { const {translate} = useLocalize(); return {translate('completeVerificationStep.isAuthorizedToUseBankAccount')}; @@ -76,6 +58,23 @@ function ConfirmAgreements({onNext, reimbursementAccount}: ConfirmAgreementsProp certifyTrueInformation: reimbursementAccount?.achData?.certifyTrueInformation ?? false, acceptTermsAndConditions: reimbursementAccount?.achData?.acceptTermsAndConditions ?? false, }; + const validate = (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + + if (!ValidationUtils.isRequiredFulfilled(values.acceptTermsAndConditions)) { + errors.acceptTermsAndConditions = translate('common.error.acceptTerms'); + } + + if (!ValidationUtils.isRequiredFulfilled(values.certifyTrueInformation)) { + errors.certifyTrueInformation = translate('completeVerificationStep.certifyTrueAndAccurateError'); + } + + if (!ValidationUtils.isRequiredFulfilled(values.isAuthorizedToUseBankAccount)) { + errors.isAuthorizedToUseBankAccount = translate('completeVerificationStep.isAuthorizedToUseBankAccountError'); + } + + return errors; + }; return ( ): FormInputErrors => { - const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); - - if (values.dob) { - if (!ValidationUtils.isValidPastDate(values.dob) || !ValidationUtils.meetsMaximumAgeRequirement(values.dob)) { - errors.dob = 'bankAccount.error.dob'; - } else if (!ValidationUtils.meetsMinimumAgeRequirement(values.dob)) { - errors.dob = 'bankAccount.error.age'; - } - } - - return errors; -}; - function DateOfBirth({reimbursementAccount, reimbursementAccountDraft, onNext, isEditing}: DateOfBirthProps) { const {translate} = useLocalize(); const styles = useThemeStyles(); + const validate = (values: FormOnyxValues): FormInputErrors => { + const errors = ValidationUtils.getFieldRequiredErrors(values, STEP_FIELDS); + + if (values.dob) { + if (!ValidationUtils.isValidPastDate(values.dob) || !ValidationUtils.meetsMaximumAgeRequirement(values.dob)) { + errors.dob = translate('bankAccount.error.dob'); + } else if (!ValidationUtils.meetsMinimumAgeRequirement(values.dob)) { + errors.dob = translate('bankAccount.error.age'); + } + } + + return errors; + }; + const dobDefaultValue = reimbursementAccount?.achData?.[PERSONAL_INFO_DOB_KEY] ?? reimbursementAccountDraft?.[PERSONAL_INFO_DOB_KEY] ?? ''; const minDate = subYears(new Date(), CONST.DATE_BIRTH.MAX_AGE); diff --git a/src/pages/Travel/TravelTerms.tsx b/src/pages/Travel/TravelTerms.tsx index 468ca9b8082a..9f26284848a4 100644 --- a/src/pages/Travel/TravelTerms.tsx +++ b/src/pages/Travel/TravelTerms.tsx @@ -23,7 +23,7 @@ function TravelTerms() { const [hasAcceptedTravelTerms, setHasAcceptedTravelTerms] = useState(false); const [error, setError] = useState(false); - const errorMessage = error ? 'travel.termsAndConditions.error' : ''; + const errorMessage = error ? translate('travel.termsAndConditions.error') : ''; const toggleTravelTerms = () => { setHasAcceptedTravelTerms(!hasAcceptedTravelTerms); diff --git a/src/pages/iou/MoneyRequestAmountForm.tsx b/src/pages/iou/MoneyRequestAmountForm.tsx index 46bd34006550..07037a09df11 100644 --- a/src/pages/iou/MoneyRequestAmountForm.tsx +++ b/src/pages/iou/MoneyRequestAmountForm.tsx @@ -16,7 +16,6 @@ import useThemeStyles from '@hooks/useThemeStyles'; import useWindowDimensions from '@hooks/useWindowDimensions'; import * as CurrencyUtils from '@libs/CurrencyUtils'; import * as DeviceCapabilities from '@libs/DeviceCapabilities'; -import type {MaybePhraseKey} from '@libs/Localize'; import * as MoneyRequestUtils from '@libs/MoneyRequestUtils'; import Navigation from '@libs/Navigation/Navigation'; import type {BaseTextInputRef} from '@src/components/TextInput/BaseTextInput/types'; @@ -98,7 +97,7 @@ function MoneyRequestAmountForm( const textInput = useRef(null); const moneyRequestAmountInput = useRef(null); - const [formError, setFormError] = useState(''); + const [formError, setFormError] = useState(''); const [shouldUpdateSelection, setShouldUpdateSelection] = useState(true); const isFocused = useIsFocused(); @@ -209,12 +208,12 @@ function MoneyRequestAmountForm( // Skip the check for tax amount form as 0 is a valid input const currentAmount = moneyRequestAmountInput.current?.getAmount() ?? ''; if (!currentAmount.length || (!isTaxAmountForm && isAmountInvalid(currentAmount))) { - setFormError('iou.error.invalidAmount'); + setFormError(translate('iou.error.invalidAmount')); return; } if (isTaxAmountInvalid(currentAmount, taxAmount, isTaxAmountForm)) { - setFormError(['iou.error.invalidTaxAmount', {amount: formattedTaxAmount}]); + setFormError([translate('iou.error.invalidTaxAmount'), {amount: formattedTaxAmount}]); return; } @@ -225,7 +224,7 @@ function MoneyRequestAmountForm( onSubmitButtonPress({amount: currentAmount, currency, paymentMethod: iouPaymentType}); }, - [taxAmount, onSubmitButtonPress, currency, formattedTaxAmount, initializeAmount], + [taxAmount, initializeAmount, onSubmitButtonPress, currency, translate, formattedTaxAmount], ); const buttonText: string = useMemo(() => { diff --git a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx index 1d9aec1ea60d..3e8cffd3869a 100644 --- a/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx +++ b/src/pages/iou/request/MoneyRequestParticipantsSelector.tsx @@ -309,7 +309,7 @@ function MoneyRequestParticipantsSelector({participants = [], onFinish, onPartic )} diff --git a/src/pages/settings/Security/TwoFactorAuth/Steps/CodesStep.tsx b/src/pages/settings/Security/TwoFactorAuth/Steps/CodesStep.tsx index 13d03fd557e9..b44f5d9e0610 100644 --- a/src/pages/settings/Security/TwoFactorAuth/Steps/CodesStep.tsx +++ b/src/pages/settings/Security/TwoFactorAuth/Steps/CodesStep.tsx @@ -135,7 +135,7 @@ function CodesStep({account, backTo}: CodesStepProps) { text={translate('common.next')} onPress={() => { if (!account?.codesAreCopied) { - setError('twoFactorAuth.errorStepCodes'); + setError(translate('twoFactorAuth.errorStepCodes')); return; } setStep(CONST.TWO_FACTOR_AUTH_STEPS.VERIFY); diff --git a/src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx b/src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx index 2710cadf94e4..bd6fa17bff34 100644 --- a/src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx +++ b/src/pages/settings/Wallet/ActivatePhysicalCardPage.tsx @@ -105,7 +105,7 @@ function ActivatePhysicalCardPage({ activateCardCodeInputRef.current?.blur(); if (lastFourDigits.replace(CONST.MAGIC_CODE_EMPTY_CHAR, '').length !== LAST_FOUR_DIGITS_LENGTH) { - setFormError('activateCardPage.error.thatDidntMatch'); + setFormError(translate('activateCardPage.error.thatDidntMatch')); return; } if (inactiveCard?.cardID === undefined) { diff --git a/src/pages/settings/Wallet/AddDebitCardPage.tsx b/src/pages/settings/Wallet/AddDebitCardPage.tsx index 0beb3c16018d..b3bc1d839727 100644 --- a/src/pages/settings/Wallet/AddDebitCardPage.tsx +++ b/src/pages/settings/Wallet/AddDebitCardPage.tsx @@ -89,31 +89,31 @@ function DebitCardPage({formData}: DebitCardPageProps) { const errors = ValidationUtils.getFieldRequiredErrors(values, REQUIRED_FIELDS); if (values.nameOnCard && !ValidationUtils.isValidLegalName(values.nameOnCard)) { - errors.nameOnCard = 'addDebitCardPage.error.invalidName'; + errors.nameOnCard = translate('addDebitCardPage.error.invalidName'); } if (values.cardNumber && !ValidationUtils.isValidDebitCard(values.cardNumber.replace(/ /g, ''))) { - errors.cardNumber = 'addDebitCardPage.error.debitCardNumber'; + errors.cardNumber = translate('addDebitCardPage.error.debitCardNumber'); } if (values.expirationDate && !ValidationUtils.isValidExpirationDate(values.expirationDate)) { - errors.expirationDate = 'addDebitCardPage.error.expirationDate'; + errors.expirationDate = translate('addDebitCardPage.error.expirationDate'); } if (values.securityCode && !ValidationUtils.isValidSecurityCode(values.securityCode)) { - errors.securityCode = 'addDebitCardPage.error.securityCode'; + errors.securityCode = translate('addDebitCardPage.error.securityCode'); } if (values.addressStreet && !ValidationUtils.isValidAddress(values.addressStreet)) { - errors.addressStreet = 'addDebitCardPage.error.addressStreet'; + errors.addressStreet = translate('addDebitCardPage.error.addressStreet'); } if (values.addressZipCode && !ValidationUtils.isValidZipCode(values.addressZipCode)) { - errors.addressZipCode = 'addDebitCardPage.error.addressZipCode'; + errors.addressZipCode = translate('addDebitCardPage.error.addressZipCode'); } if (!values.acceptTerms) { - errors.acceptTerms = 'common.error.acceptTerms'; + errors.acceptTerms = translate('common.error.acceptTerms'); } return errors; diff --git a/src/pages/settings/Wallet/ReportCardLostPage.tsx b/src/pages/settings/Wallet/ReportCardLostPage.tsx index 11790bd44cb6..813f09af74d5 100644 --- a/src/pages/settings/Wallet/ReportCardLostPage.tsx +++ b/src/pages/settings/Wallet/ReportCardLostPage.tsx @@ -183,7 +183,7 @@ function ReportCardLostPage({ @@ -201,7 +201,7 @@ function ReportCardLostPage({ diff --git a/src/pages/signin/LoginForm/BaseLoginForm.tsx b/src/pages/signin/LoginForm/BaseLoginForm.tsx index 4286a2603341..9e4b3e487718 100644 --- a/src/pages/signin/LoginForm/BaseLoginForm.tsx +++ b/src/pages/signin/LoginForm/BaseLoginForm.tsx @@ -31,7 +31,6 @@ import * as CloseAccount from '@userActions/CloseAccount'; import * as Session from '@userActions/Session'; import CONFIG from '@src/CONFIG'; import CONST from '@src/CONST'; -import type {TranslationPaths} from '@src/languages/types'; import ONYXKEYS from '@src/ONYXKEYS'; import type {CloseAccountForm} from '@src/types/form'; import type {Account, Credentials} from '@src/types/onyx'; @@ -59,7 +58,7 @@ function BaseLoginForm({account, credentials, closeAccount, blurOnSubmit = false const {translate} = useLocalize(); const input = useRef(null); const [login, setLogin] = useState(() => Str.removeSMSDomain(credentials?.login ?? '')); - const [formError, setFormError] = useState(); + const [formError, setFormError] = useState(); const prevIsVisible = usePrevious(isVisible); const firstBlurred = useRef(false); const isFocused = useIsFocused(); @@ -73,7 +72,7 @@ function BaseLoginForm({account, credentials, closeAccount, blurOnSubmit = false (value: string) => { const loginTrim = value.trim(); if (!loginTrim) { - setFormError('common.pleaseEnterEmailOrPhoneNumber'); + setFormError(translate('common.pleaseEnterEmailOrPhoneNumber')); return false; } @@ -82,9 +81,9 @@ function BaseLoginForm({account, credentials, closeAccount, blurOnSubmit = false if (!Str.isValidEmail(loginTrim) && !parsedPhoneNumber.possible) { if (ValidationUtils.isNumericWithSpecialChars(loginTrim)) { - setFormError('common.error.phoneNumber'); + setFormError(translate('common.error.phoneNumber')); } else { - setFormError('loginForm.error.invalidFormatEmailLogin'); + setFormError(translate('loginForm.error.invalidFormatEmailLogin')); } return false; } @@ -92,7 +91,7 @@ function BaseLoginForm({account, credentials, closeAccount, blurOnSubmit = false setFormError(undefined); return true; }, - [setFormError], + [setFormError, translate], ); /** diff --git a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx index 488d3d48eae9..7aaa5a03576b 100755 --- a/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx +++ b/src/pages/signin/ValidateCodeForm/BaseValidateCodeForm.tsx @@ -323,7 +323,7 @@ function BaseValidateCodeForm({account, credentials, session, autoComplete, isUs onChangeText={(text) => onTextInput(text, 'twoFactorAuthCode')} onFulfill={validateAndSubmitForm} maxLength={CONST.TFA_CODE_LENGTH} - errorText={formError?.twoFactorAuthCode ?? ''} + errorText={formError?.twoFactorAuthCode ? translate(formError?.twoFactorAuthCode) : ''} hasError={hasError} autoFocus key="twoFactorAuthCode" @@ -356,7 +356,7 @@ function BaseValidateCodeForm({account, credentials, session, autoComplete, isUs value={validateCode} onChangeText={(text) => onTextInput(text, 'validateCode')} onFulfill={validateAndSubmitForm} - errorText={formError?.validateCode ?? ''} + errorText={formError?.validateCode ? translate(formError?.validateCode) : ''} hasError={hasError} autoFocus key="validateCode" diff --git a/src/pages/tasks/NewTaskPage.tsx b/src/pages/tasks/NewTaskPage.tsx index d038e8260418..9fdb0ae67a65 100644 --- a/src/pages/tasks/NewTaskPage.tsx +++ b/src/pages/tasks/NewTaskPage.tsx @@ -99,17 +99,17 @@ function NewTaskPage({task, reports, personalDetails}: NewTaskPageProps) { // the response const onSubmit = () => { if (!task?.title && !task?.shareDestination) { - setErrorMessage('newTaskPage.confirmError'); + setErrorMessage(translate('newTaskPage.confirmError')); return; } if (!task.title) { - setErrorMessage('newTaskPage.pleaseEnterTaskName'); + setErrorMessage(translate('newTaskPage.pleaseEnterTaskName')); return; } if (!task.shareDestination) { - setErrorMessage('newTaskPage.pleaseEnterTaskDestination'); + setErrorMessage(translate('newTaskPage.pleaseEnterTaskDestination')); return; } diff --git a/src/pages/workspace/WorkspaceInvitePage.tsx b/src/pages/workspace/WorkspaceInvitePage.tsx index 9142361a531e..f1dbbf1047f4 100644 --- a/src/pages/workspace/WorkspaceInvitePage.tsx +++ b/src/pages/workspace/WorkspaceInvitePage.tsx @@ -277,7 +277,7 @@ function WorkspaceInvitePage({route, betas, invitedEmailsToAccountIDsDraft, poli isAlertVisible={shouldShowAlertPrompt} buttonText={translate('common.next')} onSubmit={inviteUser} - message={[policy?.alertMessage ?? '', {isTranslated: true}]} + message={policy?.alertMessage ?? ''} containerStyles={[styles.flexReset, styles.flexGrow0, styles.flexShrink0, styles.flexBasisAuto]} enabledWhenOffline disablePressOnEnter diff --git a/src/pages/workspace/WorkspaceMembersPage.tsx b/src/pages/workspace/WorkspaceMembersPage.tsx index c537ee50d19b..26c87bd0ed4f 100644 --- a/src/pages/workspace/WorkspaceMembersPage.tsx +++ b/src/pages/workspace/WorkspaceMembersPage.tsx @@ -411,7 +411,7 @@ function WorkspaceMembersPage({personalDetails, invitedEmailsToAccountIDsDraft, Policy.dismissAddedWithPrimaryLoginMessages(policyID)} /> diff --git a/src/pages/workspace/WorkspaceNewRoomPage.tsx b/src/pages/workspace/WorkspaceNewRoomPage.tsx index 382c1dde6d47..cf5d3c1fb3aa 100644 --- a/src/pages/workspace/WorkspaceNewRoomPage.tsx +++ b/src/pages/workspace/WorkspaceNewRoomPage.tsx @@ -169,18 +169,18 @@ function WorkspaceNewRoomPage({policies, reports, formState, session, activePoli if (!values.roomName || values.roomName === CONST.POLICY.ROOM_PREFIX) { // We error if the user doesn't enter a room name or left blank - ErrorUtils.addErrorMessage(errors, 'roomName', 'newRoomPage.pleaseEnterRoomName'); + ErrorUtils.addErrorMessage(errors, 'roomName', translate('newRoomPage.pleaseEnterRoomName')); } else if (values.roomName !== CONST.POLICY.ROOM_PREFIX && !ValidationUtils.isValidRoomName(values.roomName)) { // We error if the room name has invalid characters - ErrorUtils.addErrorMessage(errors, 'roomName', 'newRoomPage.roomNameInvalidError'); + ErrorUtils.addErrorMessage(errors, 'roomName', translate('newRoomPage.roomNameInvalidError')); } else if (ValidationUtils.isReservedRoomName(values.roomName)) { // Certain names are reserved for default rooms and should not be used for policy rooms. - ErrorUtils.addErrorMessage(errors, 'roomName', ['newRoomPage.roomNameReservedError', {reservedName: values.roomName}]); + ErrorUtils.addErrorMessage(errors, 'roomName', [translate('newRoomPage.roomNameReservedError'), {reservedName: values.roomName}]); } else if (ValidationUtils.isExistingRoomName(values.roomName, reports, values.policyID ?? '')) { // Certain names are reserved for default rooms and should not be used for policy rooms. - ErrorUtils.addErrorMessage(errors, 'roomName', 'newRoomPage.roomAlreadyExistsError'); + ErrorUtils.addErrorMessage(errors, 'roomName', translate('newRoomPage.roomAlreadyExistsError')); } else if (values.roomName.length > CONST.TITLE_CHARACTER_LIMIT) { - ErrorUtils.addErrorMessage(errors, 'roomName', ['common.error.characterLimitExceedCounter', {length: values.roomName.length, limit: CONST.TITLE_CHARACTER_LIMIT}]); + ErrorUtils.addErrorMessage(errors, 'roomName', [translate('common.error.characterLimitExceedCounter'), {length: values.roomName.length, limit: CONST.TITLE_CHARACTER_LIMIT}]); } const descriptionLength = ReportUtils.getCommentLength(values.reportDescription); diff --git a/src/stories/Form.stories.tsx b/src/stories/Form.stories.tsx index f4e89f6766f0..ab29612b0556 100644 --- a/src/stories/Form.stories.tsx +++ b/src/stories/Form.stories.tsx @@ -12,7 +12,6 @@ import Picker from '@components/Picker'; import StateSelector from '@components/StateSelector'; import Text from '@components/Text'; import TextInput from '@components/TextInput'; -import type {MaybePhraseKey} from '@libs/Localize'; import NetworkConnection from '@libs/NetworkConnection'; import * as ValidationUtils from '@libs/ValidationUtils'; import * as FormActions from '@userActions/FormActions'; @@ -58,7 +57,7 @@ function Template(props: FormProviderProps) { FormActions.setDraftValues(props.formID, props.draftValues); if (props.formState?.error) { - FormActions.setErrors(props.formID, {error: props.formState.error as MaybePhraseKey}); + FormActions.setErrors(props.formID, {error: props.formState.error as string}); } else { FormActions.clearErrors(props.formID); } @@ -172,7 +171,7 @@ function WithNativeEventHandler(props: FormProviderProps) { FormActions.setDraftValues(props.formID, props.draftValues); if (props.formState?.error) { - FormActions.setErrors(props.formID, {error: props.formState.error as MaybePhraseKey}); + FormActions.setErrors(props.formID, {error: props.formState.error as string}); } else { FormActions.clearErrors(props.formID); } diff --git a/src/types/onyx/OnyxCommon.ts b/src/types/onyx/OnyxCommon.ts index 8b96a89a2a1b..37a06f20ca63 100644 --- a/src/types/onyx/OnyxCommon.ts +++ b/src/types/onyx/OnyxCommon.ts @@ -1,7 +1,7 @@ import type {ValueOf} from 'type-fest'; -import type {MaybePhraseKey} from '@libs/Localize'; import type {AvatarSource} from '@libs/UserUtils'; import type CONST from '@src/CONST'; +import type { MaybePhraseKey } from '@libs/Localize'; type PendingAction = ValueOf | null; @@ -19,7 +19,7 @@ type OnyxValueWithOfflineFeedback = keyof TO type ErrorFields = Record; -type Errors = Record; +type Errors = Record; type AvatarType = typeof CONST.ICON_TYPE_AVATAR | typeof CONST.ICON_TYPE_WORKSPACE;