-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Passing <FormattedMessage> to a component inside a nested <IntlProvider> #419
Comments
You shouldn't be using the |
Yup, I know I should not, nor the former The aim or use case is to introduce namespaces. In short, to allow inserting additional messages and formats scoped to a component (or some other entity), and to let translation components declare which namespace they belong to (thus which message dictionary should be used). More specifically, the idea is to provide a custom provider that switches message and format dictionaries dynamically, depending on the namespace a given message belongs to. I believe the first example at react-intl-ns may clarify the general design. The only code piece that uses those functions is the one I've linked above. |
Have you tried nesting |
Nesting providers is nice to have, but that's another thing. For instance take a generic container component. Such a container may have its own strings (and own translations for them), but also display some content passed from the parent (as children, props). Some strings under the container's element subtree should use the app's message dictionary and some should use the component-provided translations; the two (or more) sets can be arbitrarily mixed. A nested Arguably, it still may be possible to get around by selectively putting some elements inside the nested providers and leaving some outside of them, but that gets convoluted too quickly. You can also use some prefixing scheme -- that's what I did before coming up with the little module -- however, I'd say that an explicit namespacing solution is less error-prone. [1] Making this happen is another thing, it would require something like including unrecognized props on |
@wrwrwr if this namespacing feature you described existed, then would you still want unbound |
Well, it kind of exists ;-) In the form of an additional module -- but that still works (currently by importing the I think this is the only significant case I have for exposing the functions, so some other solution would be just as good (as long as it can properly handle formats). I'm not sure namespaces are as substantial as to cater to them in the base package, but maybe that's also worth considering (I guess most users should be fine with a single message dictionary). |
Could you open a PR against the Nested IntlProvider Example app to demonstrate the use case you have with passing elements to props from outside the nested |
Nesting providers is a powerful technique that can be used to switch to any message or format dictionary for any element subtree. It may be a bit unwieldy at times, though.
Nesting providers is a powerful technique that can be used to switch to any message or format dictionary for any element subtree. It may be a bit unwieldy at times, though.
I thought about this some more. One thing that stands out to me is when you said generic container. I don't think components that are considered generic should have their own strings because there isn't enough context to provide a translator to get the correct phasing since the component is generic. Instead, I recommend using slots that map to props which accept Using the props-for-slots should address this problem for generic components. But there are still other cases where a component is specialized, but still receives other elements to render. One example is React Native's I think these two patterns: props-for-slots and function-props will cover many cases. In fact, using a function as a prop will always work, but starts making less sense when the component isn't something like a I could create something like Another approach you can take is to force the i18n formatting to occur before you pass things into the other i18n context. To do this, you'd need to use the imperative API; this will work because renders everything to a string, but therefore you'd loose support for rich-text message formatting. |
The const App = injectIntl(({intl}) => (
<IntlProvider messages={fooMessages}>
<Foo
title={
<IntlProvider {...intl}>
<FormattedMessage id='some_message'/>
</IntlProvider>
}
/>
</IntlProvider>
));
React.render(
<IntlProvider
locale='en'
messages={messages}
>
<App/>
</IntlProvider>
); |
Thanks a lot for the thorough look. This seems to have turned into a discussion on using multiple message spaces -- it was definitely not my intent to press on changes related to this most-likely off-stream approach. The original idea of noting some possible direction of extending the module seemed fairly innocuous :-) It is certainly possible to wrap the passed down messages in providers and to eliminate strings defined in containers completely (one more trick is to pass down "string promises" that hold the proper context, but are evaluated only when used as strings). Here are some (completely subjective) circumstances in which you could still want something more than nested providers:
[1] That's a different perspective from having a hoard of translators at your whim -- which is probably the typical situation ;-) |
@wrwrwr are you using babel-plugin-react-intl? If you're authoring a component or package, you can always namespace your strings |
Yes, I used to do that, but I don't think I want to any longer :-) Currently, I keep all of the message definitions, their translations, and component-specific formats in a file side-by-side with the code of each component. Messages and formats of components live in separate namespaces by default (with 3 lines of boilerplate per component). You could view my whole namespacing solution as an automated ids prefixer. There are really just some small bits of convenience to it: how easy it is to change the namespace, the ability to use unprefixed names of namespaced formats in translations of messages from the same namespace, and hardly any way to run into a name clash while using single-word ids. Babel extraction -- no, not at the moment, although I have a todo entry about customizing it for the specific setup. |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
Issue was closed because of inactivity. If you think this is still a valid issue, please file a new issue with additional information. |
With 2-beta I used to import
formatMessage()
and its siblings fromreact-intl/lib
. Obviously that was undocumented, unsupported, etc. Nevertheless, it may have been the best approach to toy with theconfig
parameter that theformat*
functions get bound to duringIntlProvider
child context construction (I've actually tried a couple of different options with less pleasing outcomes).Now the only way to reuse these functions seems to be to check out the sources, import from
react-intl/src
and make some adjustments to ones transpiling configuration. Not really an issue, except that it results in increased size of the dependent module -- as it likely means bundling a significant part of react-intl.That's a pretty obscure case, but how about exporting the
format*
functions, or even better making the unbound versions available from theconfig
object (or somewhere else)? Otherwise, just count this as an example for #416.The text was updated successfully, but these errors were encountered: