-
Notifications
You must be signed in to change notification settings - Fork 80
fluent-react: Introduce the Placeholder component #49
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
Conversation
Placeholders can be used as return values from custom functions passed into MessageContext. Localized.render will try to match them in order with original children of the wrapped component. Given the following HTML/JSX: <Localized id="warning-upgrade"> <p> <a href="https://www.mozilla.org/firefox/">Upgrade Firefox</a> to get started. </p> </Localized> The translation may look like this: warning-upgrade = { LINK("Upgrade Firefox", title: "New version of Firefox is available!") } to get started. The LINK function is defined in the MessageContext constructor: import { MessageContext } from 'fluent'; import negotiateLanguages from 'fluent-langneg'; import { Placeholder } from 'fluent-react'; export function* generateMessages(userLocales) { // Choose locales that are best for the user. const currentLocales = negotiateLanguages( userLocales, ['en-US', 'pl'], { defaultLocale: 'en-US' } ); for (const locale of currentLocales) { const cx = new MessageContext(locale, { functions: { // Text is the only positional argument we care about. // Title is the only named argument we care about. // This gives us filtering unsafe props (like href) for free! LINK: function([text], {title}) { return <Placeholder title={title}>{text}</Placeholder>; } } }); cx.addMessages(MESSAGES_ALL[locale]); yield cx; } }
This approach solves the immediate issue of strings being split into two as seen in https://github.com/mozilla/testpilot/pull/2611/files#diff-fa0fe0311fc532fa1c84a7f9414af2eaL241. Using Test Pilot as real-life data it seems like this approach is good enough for a huge number of cases for which we don't have a good solution right now. It has some limitations, though:
|
@zbraniecki, @Pike, @fzzzy, @mathjazz, @flodolo: I'm looking for feedback on this approach. Thanks! |
I don't think we should invest too much into context functions, and keep DOM fragments in sight as the long term solution. Which makes me wonder ..., what's the actual blocker to DOM fragments? You've figured out the src-to-l10n matching, do we really need the context methods to set markers, or could we go back and use a template element and proper parsing? Maybe with the same constraints like here, that we don't allow nested elements etc? Asking, mostly because I really don't know, and I'm afraid I'd need to learn and understand React to investigate myself. |
Any string-to-DOM parsing doesn't work well with |
Which leads me to think that the full DOM fragments solution might not even be achievable if we keep |
Or that doing both DOM fragments and React.Element in the same string is not supported? |
Yup. |
So, I don't think I understand React enough to judge, but coming form vanilla Fluent, the fact that the syntax for functions is abused here looks awkward. My gut reaction is to try to push for DOM Overlays instead, but from @stasm I understand that it may not be ready anytime soon.
That doesn't sound that bad, does it? |
I'm glad that we didn't move forward with this PR. In #101 I landed a simple implementation of DOM overlays for Read more about the new approach on the wiki: Overlays. |
Placeholders can be used as return values from custom functions passed into
MessageContext
.Localized.render
will try to match them in order with original children of the wrapped component.Given the following HTML/JSX:
The translation may look like this:
The LINK function is defined in the MessageContext constructor: