Skip to content
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

No i18n support: components should provide an object with Labels as props #409

Open
janus-reith opened this issue Apr 12, 2019 · 23 comments
Labels
good first issue For issues that a new contributor could likely submit a pull request for without needing much help help wanted For issues that have a clear solution described and are not currently prioritized core team work

Comments

@janus-reith
Copy link
Contributor

Some components render localized text, but provide no way to alter it outside of the component.
Example:

The component library should not be responsible for i18n itself.
It could accept an object with labels as props, in a similar manner compnents are passed and overrriden. The current strings could serve as fallback.

@aldeed
Copy link
Contributor

aldeed commented Apr 12, 2019

This is a known deficiency that will eventually have a solution. The workaround in the meantime is to override the entire component using the components context, providing a version of it that you've modified to use whatever i18n solution your app uses.

@janus-reith
Copy link
Contributor Author

Yes, that would work in the meantime, thank you.
Would you accept PRs that would allow passing own strings(so still i18n-library-agnostic), or does this need further internal discussion?

@aldeed
Copy link
Contributor

aldeed commented Apr 16, 2019

@nnnnat Any thoughts here? Some components already accept label overrides (e.g., otherAddressLabel prop on AddressChoice). I think it makes sense to accept PRs that do this same thing for other components that have English text built into them. It's the simplest way to support translations without buying into any particular framework.

@HarisSpahija
Copy link

Can labels be added for this issue? I think its a fairly easy starting issue.

@nnnnat nnnnat added good first issue For issues that a new contributor could likely submit a pull request for without needing much help help wanted For issues that have a clear solution described and are not currently prioritized core team work labels Oct 1, 2019
@HarisSpahija
Copy link

Hey, this issue doesn't seem to get a lot of traction. When it comes to components every single component that has text would need to get an extra prop for translation.
Is there any possibilty where we can slowly tackle this issue by doing components in batches?
Also, could I be assigned to this issue? We already did a big part when it comes to translations in our component library.

@HarisSpahija
Copy link

Did you guys ever make any progress on this issue @nnnnat @aldeed ?

@nnnnat
Copy link
Contributor

nnnnat commented Oct 16, 2019

@HarisSpahija please feel free to create PRs to this repo that add label overrides for component text. We'd prefer 1 component per PR and not in batches just to keep reviews on our side shorter.

@HarisSpahija
Copy link

@nnnnat could you check if the current PR's are viable to be implemented?

@aldeed
Copy link
Contributor

aldeed commented Nov 13, 2019

@HarisSpahija I approved PRs. One needs a small change. Someone with ability to override the snyk checks will have to merge them, or you can merge master into them after the Snyk-related PRs have been merged.

@HarisSpahijaPon
Copy link
Contributor

HarisSpahijaPon commented Nov 21, 2019

Some components have strings that are possibly gramatically different in other languages. For example:

<StockWarning />

return <Span className={className}>Only {inventoryQuantity} in stock</Span>;

In Dutch one would say "Slechts 7 op voorraad", while in Bosnian you could say: "7 Na Lageru". Grammar should be counted in when implementing i18next.

@HarisSpahijaPon
Copy link
Contributor

All components should have translation options now with a couple of exceptions. @janus-reith we could move to adding i18n to example-storefront now

@aldeed
Copy link
Contributor

aldeed commented Nov 26, 2019

@HarisSpahijaPon For those that need interpolation, you can update to take a fn prop instead.

// default props
getLowStockText: (data) => `Only ${data.inventoryQuantity} in stock`

const { getLowStockText } = this.props;

return <Span className={className}>{getLowStockText({ inventoryQuantity })}</Span>;

When using in translated app, you'd pass through to i18next in the function prop:

getLowStockText={(data) => i18next.t("lowStockText", data)}

And your translation file would have "Only {{inventoryQuantity}} in stock" as the English value, for example.

See https://www.i18next.com/translation-function/interpolation

@HarisSpahijaPon
Copy link
Contributor

okay thanks! I will update them @aldeed

@HarisSpahijaPon
Copy link
Contributor

I think pretty much all components except the interpolation items have been set now. Is it time to implement a basic example to the storefront for i18n?

@janus-reith , would you be interested in helping with this issue? I am not sure what exactly is needed to make a sufficient example for users to test. Would be cool if we can implement it before 3.0 release.

@janus-reith
Copy link
Contributor Author

@HarisSpahijaPon Great work, sure we can collaborate on this.

@CristianCucunuba
Copy link

Hey guys @HarisSpahijaPon @janus-reith , I'm also interested in collaborating on this, please let me know how i can help.

@HarisSpahija
Copy link

HarisSpahija commented Dec 9, 2019

@CristianCucunuba Id say check out this issue: reactioncommerce/example-storefront#524

You could fork the master branch and create an example using the new label props to show translations. I think its best if we start with one component and one language. Preferably English.

Also there are still some PR's open with some labels needing to be adjusted. Feel free to continue with my PR.

@HarisSpahija
Copy link

I noticed that some components are using other components from the component library. Components such as MiniCart make it so labels cannot be passed to MiniCartSummary without either overriding componentContext or passing props from the parent. For example:

 <MiniCartSummary displaySubtotal={summary.itemTotal.displayAmount} />

Can be translated with the override labels

 <MiniCartSummary displaySubtotal={summary.itemTotal.displayAmount} checkoutButtonText={"test"} footerMessageText={"test"}/>

Because the component is nested there is no way we can reach the override labels. This should be fixed in the component library or an extra props should be added to pass nested props.

What do you think would be the right approach to this @aldeed ?

@aldeed
Copy link
Contributor

aldeed commented Dec 9, 2019

@HarisSpahija I tend to prefer specific props like miniCartSummaryCheckoutButtonText, etc. which are passed down. This allows specific prop validation whereas a miniCartSummaryProps prop opens the door to hundreds of potential combinations that would need to be tested and supported.

That said, I don't know that Reaction has a specific policy on this. @mikemurray or @nnnnat may have more to say.

It's not quite correct to say there's no way to do it, though. If you use the components context to inject translations for MiniCartSummary (and all components), which would be the best and recommended way, then it will be translated wherever it is used without any need for passing down props. That's really the main reason why this package supports a component context: ability to override nested components.

@HarisSpahija
Copy link

I tried setting an override in component context, but I couldnt get the syntax to work without sideffects. Could you elaborate how to do this with an example?

@aldeed
Copy link
Contributor

aldeed commented Dec 10, 2019

@HarisSpahija I didn't test this, but it should work as long as you provide a component (e.g. a function that returns JSX).

{
  MiniCartSummary: (props) => <MiniCartSummary checkoutButtonText={i18next.t("MiniCartSummary.checkoutButtonText")} footerMessageText={i18next.t("MiniCartSummary.footerMessageText")} {...props} />
}

You'd have to make a slightly more complicated component that uses useTranslation hook to get a properly reactive version of i18next.t function, but this is the general idea.

@HarisSpahijaPon
Copy link
Contributor

Some components require some references or not every component is listed in the componentContext file, we should refactor those to make it easier for developers to override the components.

@aldeed
Copy link
Contributor

aldeed commented Jan 14, 2020

Agree that no components should directly import any other components unless there's clearly no use case for overriding it. Submitting individual GH issues for each case of that would be best.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue For issues that a new contributor could likely submit a pull request for without needing much help help wanted For issues that have a clear solution described and are not currently prioritized core team work
Projects
None yet
Development

No branches or pull requests

6 participants