Skip to content

feat: i18nify SDK integrated for Amount component #2003

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Feb 12, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions .changeset/purple-flies-end.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
"@razorpay/blade": minor
Copy link
Contributor

Choose a reason for hiding this comment

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

Ideally, this should be treated as a breaking change since users need manual intervention (installing peerDep) to upgrade.

We can make an exception for this PR, to avoid a major release. I'll discuss this with the team.

cc @anurag-rzp @saurabhdaware @kamleshchandnani @chaitanyadeorukhkar

Copy link
Collaborator

Choose a reason for hiding this comment

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

We can do it as minor, should be fine

Copy link
Member

Choose a reason for hiding this comment

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

minor should be fine I believe since its just additional installation step and shouldn't require consumers to change anything in code as such. And even if it breaks, it breaks on development itself

---

feat: Added internationalization in Amount component via i18nify.
References
- **i18nify-js:** https://www.npmjs.com/package/@razorpay/i18nify-js
- **i18nify-react:** https://www.npmjs.com/package/@razorpay/i18nify-react

How to update ?
1. Install i18nify peer dependency `yarn add @razorpay/i18nify-js`
2. _[Optional]_: Install i18nify-react peer dependency to manage state effectively `yarn add @razorpay/i18nify-react`
Copy link
Member

Choose a reason for hiding this comment

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

We were discussing about breaking change internally. We decided to have this as minor release and add its changelog into v11 https://github.com/razorpay/blade/blob/master/packages/blade/upgrade-v11.md#amount because we very recently had a breaking release which people are yet to migrate to.

I think we'll have @razorpay/i18nify-react as mandatory dependency and ask consumers to add a I18nProvider on their end with expected locale.

A bit risky to rely on browser locale for existing Amount components since our default so far has been en-IN behaviour so things might break for product if something like this changes - https://github.com/razorpay/blade/pull/2003/files#r1482641498

Copy link
Contributor Author

@tarun-khanna tarun-khanna Feb 8, 2024

Choose a reason for hiding this comment

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

Makes sense.
What are the next steps here ? @saurabhdaware
I think @razorpay/i18nify-react should be just added as mandatory step in migration guide to v11 but shouldn't be added as a mandatory peer dependecy for new users.

Copy link
Member

Choose a reason for hiding this comment

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

I think @razorpay/i18nify-react should be just added as mandatory step in migration guide to v11 but shouldn't be added as a mandatory peer dependecy for new users.

Yes makes sense

Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't be added as a mandatory peer dependecy for new users.

regarding this, should we explicitly mark @razorpay/i18nify-react as optional via peerDependenciesMeta?

3. Install latest Blade `yarn add @razorpay/blade@latest`
11 changes: 8 additions & 3 deletions packages/blade/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,9 @@
"typescript": "4.9",
"typescript-transform-paths": "3.4.6",
"@types/body-scroll-lock": "3.1.0",
"ramda": "0.29.1"
"ramda": "0.29.1",
"@razorpay/i18nify-js": "^1.4.0",
Copy link
Collaborator

Choose a reason for hiding this comment

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

we use pinned dependency, can you pin it?

Copy link
Collaborator

Choose a reason for hiding this comment

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

why do we need to install both? ideally i18nify-react shall have i18nify-js as dependency otherwise as end consumer if the dependency versions go out of sync it will be difficult to communicate this to devs. so if someone is installing i18nify-react it shall install i18nify-js by default right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, it not should not install i18nify-js automatically if someone install i18nify-react.
As we want to maintain a single copy of i18nify-js in consumer apps for state management, i18nify-js is added as a peer dependency even for i18nify-react. So you will always have to install i18nify-js separately if you want i18nify-react.

Here for Blade, we needed I18nProvider and associated context state, so I had to install i18nify-react as a separate dev dependency but not peer dependency.
Additionally, the end consumers won't lead to a out of sync issue, as these packages are released always in sync in our mono-repo setup. If a consumer installs a latest copy of i18nify-react, they will have to update latest version of i18nify-js as well.

A similar discussion happened with Blade team on this thread too.

Copy link
Collaborator

Choose a reason for hiding this comment

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

If a consumer installs a latest copy of i18nify-react, they will have to update latest version of i18nify-js as well.

this is the issue i see. how will we prevent consumers from updating the one and not the other?

"@razorpay/i18nify-react": "^4.0.0"
},
"peerDependencies": {
"react": ">=18",
Expand All @@ -283,7 +285,8 @@
"react-native-svg": "^12.3.0",
"react-native-gesture-handler": "^2.9.0",
"@gorhom/bottom-sheet": "^4.4.6",
"@gorhom/portal": "^1.0.14"
"@gorhom/portal": "^1.0.14",
"@razorpay/i18nify-js": "^1.4.0"
},
"peerDependenciesMeta": {
"react-native": {
Expand All @@ -298,7 +301,9 @@
"@storybook/**/react": "18.2.0",
"react-dom": "18.2.0",
"react": "18.2.0",
"styled-components": "^5"
"styled-components": "^5",
"@types/react": "17.0.38",
Copy link
Collaborator

Choose a reason for hiding this comment

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

why do we have types react as 17 here while our actual react version is 18?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Had added this while testing i18nify-react in Blade/examples/basic app.
As Blade uses @types/react: 17.0.38 and i18nify-react uses "@types/react": "^18.0.0",. It was leading to some conflicts in the types.
Let me recheck this, will remove this if not required.

"@types/react-native": "0.72.2"
},
"bundlemon": {
"files": [
Expand Down
105 changes: 103 additions & 2 deletions packages/blade/src/components/Amount/Amount.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
import type { StoryFn, Meta } from '@storybook/react';
import { Title } from '@storybook/addon-docs';
import { getCurrencyList } from '@razorpay/i18nify-js/currency';
import { I18nProvider, useI18nContext } from '@razorpay/i18nify-react';
import { useState } from 'react';
import type { AmountProps } from './Amount';
import { Amount as AmountComponent } from './Amount';
import type { AmountHeadingProps, AmountDisplayProps, AmountBodyProps } from './amountTokens';
import { currencyIndicatorMapping } from './amountTokens';
import { getStyledPropsArgTypes } from '~components/Box/BaseBox/storybookArgTypes';
import BaseBox from '~components/Box/BaseBox';
import { Sandbox } from '~utils/storybook/Sandbox';
import { Display, Text } from '~components/Typography';
import StoryPageWrapper from '~utils/storybook/StoryPageWrapper';
import { Box } from '~components/Box';
import { objectKeysWithType } from '~utils/objectKeysWithType';
import { ActionList, ActionListItem } from '~components/ActionList';
import { SelectInput } from '~components/Input/DropdownInputTriggers';
import { Dropdown, DropdownOverlay } from '~components/Dropdown';
import { Divider } from '~components/Divider';

const Page = (): React.ReactElement => {
return (
Expand Down Expand Up @@ -176,7 +182,7 @@ HumanizeSuffix.args = {
HumanizeSuffix.storyName = 'Humanize Suffix';

const AmountCurrencyTemplate: StoryFn<typeof AmountComponent> = (args) => {
const values = Object.keys(currencyIndicatorMapping);
const values = Object.keys(getCurrencyList());

return (
<BaseBox justifyContent="flex-start" maxHeight="300px" overflowY="auto">
Expand Down Expand Up @@ -217,3 +223,98 @@ StrikeThrough.args = {
isStrikethrough: true,
};
StrikeThrough.storyName = 'Strike Through';

// TODO: Replace below with i18nify getDefaultLocales
const localeList = [
{
country: 'India',
locale: 'en-IN',
},
{
country: 'USA',
locale: 'en-US',
},
{
country: 'Malaysia',
locale: 'ms-MY',
},
{
country: 'France',
locale: 'fr-FR',
},
{
country: 'Germany',
locale: 'de-DE',
},
];

const I18nAmountWrapper = (args: AmountProps) => {
const { setI18nState } = useI18nContext();
const [currency, setCurrency] = useState('INR');

return (
<>
<AmountComponent {...args} currency={currency as AmountProps['currency']} />
<Divider marginY="spacing.4" marginTop="spacing.8" />
<Dropdown selectionType="single">
<SelectInput label="Select locale" />
<DropdownOverlay>
<ActionList>
{localeList.map((item) => (
<ActionListItem
key={item.locale}
title={`${item.country}(${item.locale})`}
value={item.locale}
onClick={({ name }) => {
setI18nState({ locale: name });
}}
/>
))}
</ActionList>
</DropdownOverlay>
</Dropdown>
<Divider marginY="spacing.4" />
<Dropdown selectionType="single">
<SelectInput label="Select currency" />
<DropdownOverlay>
<ActionList>
{Object.keys(getCurrencyList()).map((value) => (
<ActionListItem
key={value}
title={value}
value={value}
onClick={({ name }) => {
setCurrency(name);
}}
/>
))}
</ActionList>
</DropdownOverlay>
</Dropdown>
</>
);
};

const I18nAmountTemplate: StoryFn<typeof AmountComponent> = (args) => {
return (
<I18nProvider>
<BaseBox justifyContent="flex-start" maxHeight="300px" overflowY="auto">
<BaseBox
display="flex"
alignItems="baseline"
paddingRight="spacing.3"
paddingTop="spacing.3"
flexDirection="column"
>
<I18nAmountWrapper {...args} />
</BaseBox>
</BaseBox>
</I18nProvider>
);
};

export const I18nAmount = I18nAmountTemplate.bind({});
I18nAmount.args = {
...defaultArgs,
};
I18nAmount.storyName = 'Amount in diff locales';
Loading