Skip to content

Commit

Permalink
fix(suite, suite-desktop-ui, suite-common): add type check to message…
Browse files Browse the repository at this point in the history
…s.ts and fix translations
  • Loading branch information
komret committed Nov 12, 2024
1 parent b33ad25 commit 2032142
Show file tree
Hide file tree
Showing 11 changed files with 52 additions and 31 deletions.
1 change: 1 addition & 0 deletions docs/features/localization.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ _Do not manually edit language json files in `suite-data/files/translations/` di
- `id`: We don't have strict conventions for generating these IDs, although using a prefix `TR_`, or expanded variant `TR_<SCOPE>`, where scope is, for example, "ONBOARDING" is really handy. ID must be the same as the object's key.
- `defaultMessage`: Used as a source string for translator. It's also a text that is shown in the app as a fallback till someone changes/improves it in Crowdin.
- `description`: Optional. Useful for describing the context in which the message occurs, especially if it is not clear from a `defaultMessage` field.
- `dynamic`: Optional. Must be set to true for programmatically constructed keys. Otherwise, the keys will be deleted by the list-duplicates script.

Example:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export const Available = ({ onCancel, latest }: AvailableProps) => {
<div>
<Paragraph typographyStyle="highlight" variant="primary">
<Translation
id="TR_VERSION_HAS_RELEASED"
id="TR_VERSION_HAS_BEEN_RELEASED"
values={{ version: suiteNewVersion }}
/>
</Paragraph>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const JustUpdated = ({ onCancel }: AvailableProps) => {
heading={
<Paragraph typographyStyle="titleSmall" variant="primary">
<Translation
id="TR_VERSION_HAS_RELEASED"
id="TR_VERSION_HAS_BEEN_RELEASED"
values={{ version: suiteCurrentVersion }}
/>
</Paragraph>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ const Wrapper = styled.div`
const getTranslationId = (instantStakeType: StakeType) => {
switch (instantStakeType) {
case 'stake':
return 'TR_STAKING_INSTANT_STAKING';
return 'TR_INSTANT_STAKING';
case 'unstake':
return 'TR_STAKING_INSTANT_UNSTAKING';
return 'TR_INSTANT_UNSTAKING';
default:
return null; // there is no badge for claiming
}
Expand Down
54 changes: 37 additions & 17 deletions packages/suite/src/support/messages.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
import { defineMessages } from 'react-intl';

export default defineMessages({
type MessageDescriptor<K extends string> = {
// Must correspond to the property name.
id: K;
// Default text in English. This value is only used directly if the corresponding key is missing from the JSON translation files.
defaultMessage: string;
// Not integrated into Crowdin so not really used.
description?: string;
// Must be set to true for programmatically constructed keys. Otherwise, the keys will be deleted by the list-duplicates script.
dynamic?: boolean;
};

/**
Checks whether id corresponds to the property name. Otherwise, text is not translated. Returns the same value that was passed in.
*/
const defineMessagesWithTypeCheck = <Key extends string>(messages: {
[K in Key]: MessageDescriptor<K>;
}) => messages;

const messages = defineMessagesWithTypeCheck({
TR_404_DESCRIPTION: {
defaultMessage: 'Looks like a wrong URL or broken link.',
id: 'TR_404_DESCRIPTION',
Expand Down Expand Up @@ -170,7 +188,7 @@ export default defineMessages({
id: 'TR_XPUB',
},
TR_ADDRESS: {
id: 'TR_ADDRESSES',
id: 'TR_ADDRESS',
defaultMessage: 'Address',
},
TR_ADDRESSES_FRESH: {
Expand Down Expand Up @@ -971,11 +989,11 @@ export default defineMessages({
id: 'TR_BUY_MODAL_TERMS_6',
dynamic: true,
},
TR_VALIDATION_ERROR_MINIMUM_CRYPTO: {
TR_BUY_VALIDATION_ERROR_MINIMUM_CRYPTO: {
defaultMessage: 'Minimum is {minimum}',
id: 'TR_BUY_VALIDATION_ERROR_MINIMUM_CRYPTO',
},
TR_VALIDATION_ERROR_MAXIMUM_CRYPTO: {
TR_BUY_VALIDATION_ERROR_MAXIMUM_CRYPTO: {
defaultMessage: 'Maximum is {maximum}',
id: 'TR_BUY_VALIDATION_ERROR_MAXIMUM_CRYPTO',
},
Expand Down Expand Up @@ -3557,12 +3575,12 @@ export default defineMessages({
defaultMessage:
'The current and most widely accepted method of generating and managing Solana addresses ensures interoperability, security, and support for SOL and SPL tokens.',
},
TR_ACCOUNT_TYPE_NORMAL_CARDANO_DESC: {
TR_ACCOUNT_TYPE_CARDANO_DESC: {
id: 'TR_ACCOUNT_TYPE_CARDANO_DESC',
defaultMessage:
'The current and most widely accepted method of generating and managing Cardano addresses ensures interoperability, security, and support for all types of tokens.',
},
TR_ACCOUNT_TYPE_NORMAL_XRP_DESC: {
TR_ACCOUNT_TYPE_XRP_DESC: {
id: 'TR_ACCOUNT_TYPE_XRP_DESC',
defaultMessage:
'XRP is a digital currency that enables fast, low-cost cross-border payments without relying on traditional mining, using a consensus ledger for quick transaction confirmations.',
Expand Down Expand Up @@ -3667,7 +3685,7 @@ export default defineMessages({
},
TOAST_COIN_SCHEME_PROTOCOL: {
id: 'TOAST_COIN_SCHEME_PROTOCOL',
describe: 'Required for current notifications. Do not change.',
description: 'Required for current notifications. Do not change.',
defaultMessage: '{header}{body}',
},
TOAST_COIN_SCHEME_PROTOCOL_ACTION: {
Expand Down Expand Up @@ -4148,7 +4166,7 @@ export default defineMessages({
dynamic: true,
},
TR_CHECK_RECOVERY_SEED_DESC_T3B1: {
id: 'TR_CHECK_RECOVERY_SEED_DESC_T2B1',
id: 'TR_CHECK_RECOVERY_SEED_DESC_T3B1',
defaultMessage:
"Use the two-button pad to enter your wallet backup. By doing this, you're keeping all your sensitive info safe and sound, away from any shady or insecure computer or web browser.",
dynamic: true,
Expand Down Expand Up @@ -4664,7 +4682,7 @@ export default defineMessages({
TR_DISABLE_WEBUSB_TRY_BRIDGE: {
id: 'TR_DISABLE_WEBUSB_TRY_BRIDGE',
defaultMessage: 'Disable WebUSB and use Bridge',
describe:
description:
'Bridge is a communication deamon that some users will need to download and install. So word bridge should not be translated.',
},
TR_YOUR_DEVICE_IS_SEEDLESS: {
Expand Down Expand Up @@ -5173,7 +5191,7 @@ export default defineMessages({
id: 'IMAGE_VALIDATION_ERROR_INVALID_DIMENSIONS',
defaultMessage: 'Invalid dimensions (Image must be {width} x {height} px)',
},
IMAGE_VALIDATION_ERROR_INVALID_SIZE: {
IMAGE_VALIDATION_ERROR_INVALID_SIZE_JPG: {
id: 'IMAGE_VALIDATION_ERROR_INVALID_SIZE_JPG',
defaultMessage: 'Invalid size (Image must be less than 16KB)',
},
Expand Down Expand Up @@ -6199,7 +6217,7 @@ export default defineMessages({
id: 'TR_MANAGE',
defaultMessage: 'manage',
},
TR_VERSION_HAS_RELEASED: {
TR_VERSION_HAS_BEEN_RELEASED: {
id: 'TR_VERSION_HAS_BEEN_RELEASED',
defaultMessage: 'v{version} has released!',
},
Expand Down Expand Up @@ -6823,7 +6841,7 @@ export default defineMessages({
defaultMessage:
"Contact Trezor Support to figure out what's going on with your device and what to do next.",
},
TR_DEVICE_COMPROMISED_HEADING_SOFT: {
TR_PLAY_IT_SAFE: {
id: 'TR_PLAY_IT_SAFE',
defaultMessage: "Let's play it safe",
},
Expand Down Expand Up @@ -7050,7 +7068,7 @@ export default defineMessages({
TR_ONBOARDING_TROUBLESHOOTING_FAILED: {
id: 'TR_ONBOARDING_TROUBLESHOOTING_FAILED',
defaultMessage: 'Still not working?',
decription:
description:
"If troubleshooting steps for connecting a device in Onboarding didn't do the trick there is at the end link to contact a support",
},
TR_STILL_DONT_SEE_YOUR_TREZOR: {
Expand Down Expand Up @@ -7379,7 +7397,7 @@ export default defineMessages({
id: 'TR_STAKING_IS_NOT_SUPPORTED',
defaultMessage: 'Staking is not supported on this network.',
},
TR_STAKING_INSTANT_STAKING: {
TR_INSTANT_STAKING: {
id: 'TR_INSTANT_STAKING',
defaultMessage: 'Staked instantly',
},
Expand All @@ -7391,7 +7409,7 @@ export default defineMessages({
id: 'TR_STAKING_AMOUNT_UNSTAKED_INSTANTLY',
defaultMessage: '{amount} {symbol} unstaked instantly!',
},
TR_STAKING_INSTANT_UNSTAKING: {
TR_INSTANT_UNSTAKING: {
id: 'TR_INSTANT_UNSTAKING',
defaultMessage: 'Unstaked instantly',
},
Expand All @@ -7400,7 +7418,7 @@ export default defineMessages({
defaultMessage:
"You've instantly staked {amount} {symbol}. {days, plural, =0 {} one {The remaining {symbol} will be staked within # day.} other { The remaining {symbol} will be staked within # days}}",
},
TR_STAKING_INSTANTLY_UNSTAKED: {
TR_STAKE_INSTANTLY_UNSTAKED_WITH_DAYS: {
id: 'TR_STAKE_INSTANTLY_UNSTAKED_WITH_DAYS',
defaultMessage:
'You received {amount} {symbol} "Instantly". {days, plural, =0 {} one {The rest will be payed out within # day.} other { The rest will be payed out within # days}}',
Expand Down Expand Up @@ -8361,7 +8379,7 @@ export default defineMessages({
id: 'TR_DESKTOP_APP_PROMO_GET',
defaultMessage: 'Get for desktop',
},
TR_DESKTOP_APP_PROMO_TEXT_FOOTER: {
TR_MOBILE_APP_PROMO_TEXT: {
id: 'TR_MOBILE_APP_PROMO_TEXT',
defaultMessage: 'With more security features',
},
Expand Down Expand Up @@ -9234,3 +9252,5 @@ export default defineMessages({
defaultMessage: 'Trezor Connect',
},
});

export default defineMessages(messages);
2 changes: 1 addition & 1 deletion packages/suite/src/utils/suite/homescreen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const enum ImageValidationError {
InvalidFormatOnlyPngJpg = 'IMAGE_VALIDATION_ERROR_INVALID_FORMAT_ONLY_PNG_JPG',
InvalidFormatOnlyJpg = 'IMAGE_VALIDATION_ERROR_INVALID_FORMAT_ONLY_JPG',
InvalidDimensions = 'IMAGE_VALIDATION_ERROR_INVALID_DIMENSIONS',
InvalidSize = 'IMAGE_VALIDATION_ERROR_INVALID_SIZE',
InvalidSize = 'IMAGE_VALIDATION_ERROR_INVALID_SIZE_JPG',
ProgressiveJpgFormat = 'IMAGE_VALIDATION_ERROR_PROGRESSIVE_JPG',
UnexpectedAlpha = 'IMAGE_VALIDATION_ERROR_UNEXPECTED_ALPHA',
InvalidColorCombination = 'IMAGE_VALIDATION_ERROR_INVALID_COLOR_COMBINATION',
Expand Down
8 changes: 4 additions & 4 deletions packages/suite/src/utils/suite/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export const validateLimits =
: amountLimits.minCrypto;
}
if (amountLimits.minCrypto && Number(value) < minCrypto) {
return translationString('TR_VALIDATION_ERROR_MINIMUM_CRYPTO', {
return translationString('TR_BUY_VALIDATION_ERROR_MINIMUM_CRYPTO', {
minimum: formatter.format(amountLimits.minCrypto.toString(), {
isBalance: true,
symbol,
Expand All @@ -79,7 +79,7 @@ export const validateLimits =
: amountLimits.maxCrypto;
}
if (amountLimits.maxCrypto && Number(value) > maxCrypto) {
return translationString('TR_VALIDATION_ERROR_MAXIMUM_CRYPTO', {
return translationString('TR_BUY_VALIDATION_ERROR_MAXIMUM_CRYPTO', {
maximum: formatter.format(amountLimits.maxCrypto.toString(), {
isBalance: true,
symbol,
Expand Down Expand Up @@ -112,7 +112,7 @@ export const validateLimitsBigNum =
: new BigNumber(amountLimits.minCrypto);
}
if (amountLimits.minCrypto && new BigNumber(value).lt(minCrypto)) {
return translationString('TR_VALIDATION_ERROR_MINIMUM_CRYPTO', {
return translationString('TR_BUY_VALIDATION_ERROR_MINIMUM_CRYPTO', {
minimum: formatter.format(amountLimits.minCrypto.toString(), {
isBalance: true,
symbol,
Expand All @@ -129,7 +129,7 @@ export const validateLimitsBigNum =
: new BigNumber(amountLimits.maxCrypto);
}
if (amountLimits.maxCrypto && new BigNumber(value).gt(maxCrypto)) {
return translationString('TR_VALIDATION_ERROR_MAXIMUM_CRYPTO', {
return translationString('TR_BUY_VALIDATION_ERROR_MAXIMUM_CRYPTO', {
maximum: formatter.format(amountLimits.maxCrypto.toString(), {
isBalance: true,
symbol,
Expand Down
2 changes: 1 addition & 1 deletion packages/suite/src/views/dashboard/PromoBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ export const PromoBanner = () => {
<Image image="HOLLOW_APP_LOGO" width={44} height={44} />

<div>
<Translation id="TR_DESKTOP_APP_PROMO_TEXT_FOOTER" />
<Translation id="TR_MOBILE_APP_PROMO_TEXT" />

<OSIcons>
<Icon name="osMac" size={14} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ const SecurityCheckContent = ({
return isFailed ? (
<SecurityCheckFail
goBack={toggleView}
heading="TR_DEVICE_COMPROMISED_HEADING_SOFT"
heading="TR_PLAY_IT_SAFE"
text="TR_DEVICE_COMPROMISED_TEXT_SOFT"
supportUrl={supportUrl}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const IconWrapper = styled.div`
const getSubheadingTranslationId = (stakeType: StakeType) => {
if (stakeType === 'stake') return 'TR_STAKING_INSTANTLY_STAKED';

return 'TR_STAKING_INSTANTLY_UNSTAKED';
return 'TR_STAKE_INSTANTLY_UNSTAKED_WITH_DAYS';
};

const getHeadingTranslationId = (stakeType: StakeType) => {
Expand Down
4 changes: 2 additions & 2 deletions suite-common/wallet-utils/src/accountUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -304,9 +304,9 @@ export const getAccountTypeDesc = ({ path, accountType, networkType }: getAccoun
case 'solana':
return 'TR_ACCOUNT_TYPE_NORMAL_SOLANA_DESC';
case 'cardano':
return 'TR_ACCOUNT_TYPE_NORMAL_CARDANO_DESC';
return 'TR_ACCOUNT_TYPE_CARDANO_DESC';
case 'ripple':
return 'TR_ACCOUNT_TYPE_NORMAL_XRP_DESC';
return 'TR_ACCOUNT_TYPE_XRP_DESC';
}

const accountTypePrefix = getAccountTypePrefix(path);
Expand Down

0 comments on commit 2032142

Please sign in to comment.