fluent-react: Filter props with <Localized attrs={{…}}>#141
Merged
stasm merged 1 commit intoprojectfluent:masterfrom Feb 1, 2018
Merged
fluent-react: Filter props with <Localized attrs={{…}}>#141stasm merged 1 commit intoprojectfluent:masterfrom
stasm merged 1 commit intoprojectfluent:masterfrom
Conversation
Contributor
Author
|
@hkasemir Would you mind reviewing this? |
8d5a96c to
f176bdf
Compare
hkasemir
approved these changes
Feb 1, 2018
fluent-react/CHANGELOG.md
Outdated
| <Localized id="type-name" attrs={{placeholder: true}}> | ||
| <input | ||
| type="text" | ||
| onChange={…} |
Contributor
There was a problem hiding this comment.
might include a demo placeholder attribute here
| <div existing={true} /> | ||
| )); | ||
| }); | ||
|
|
Contributor
There was a problem hiding this comment.
nice test coverage - makes the benefits of explicitly disallowing setting attrs clear.
|
|
||
| // The default is to forbid all message attributes. If the attrs prop exists | ||
| // on the Localized instance, only set message attributes which have been | ||
| // explicitly allowed by the developer. |
The <Localized> component now requires the `attrs` prop to set any localized
attributes as props on the wrapped component. `attrs` should be an object with
attribute names as keys and booleans as values.
```jsx
<Localized id="type-name" attrs={{placeholder: true}}>
<input
type="text"
placeholder="Localizable placeholder"
value={name}
onChange={…}
/>
</Localized>
```
By default, if `attrs` is not passed, no attributes will be set. This is
a breaking change compared to the previous behavior: in `fluent-react`
0.4.1 and before `<Localized>` would set _all_ attributes found in the
translation.
f176bdf to
dd9119b
Compare
stasm
added a commit
to stasm/fluent.js
that referenced
this pull request
Feb 1, 2018
- Allow limited markup in translations. (projectfluent#101) Translations in Fluent can now include simple HTML-like markup. Elements found in translations will be matched with props passed to `<Localized>`. These props must be React elements. Their content will be replaced by the localizable content found for the corrensponding markup in the translation. This is a breaking change from `fluent-react` 0.4.1. See migration notes below. ```properties send-comment = <confirm>Send</confirm> or <cancel>go back</cancel>. ``` ```js <Localized id="send-comment" confirm={ <button onClick={sendComment}></button> } cancel={ <Link to="/"></Link> } > <p>{'<confirm>Send</confirm> or <cancel>go back</cancel>.'}</p> </Localized> ``` The rendered result will include the props interpolated into the translation: ```js <p> <button onClick={sendComment}>Send</button> or <Link to="/">go back</Link>. </p> ``` When naming markup elements it's possible to use any name which is a valid prop name. Translations containing markup will be parsed using a hidden `<template>` element. It creates a safe inert `DocumentFragment` with a hierarchy of text nodes and HTML elements. Any unknown elements (e.g. `cancel` in the example above) are parsed as `HTMLUnknownElements`. `fluent-react` then tries to match all elements found in the translation with props passed to the `<Localized>` component. If a match is found, the element passed as a prop is cloned with the translated text content taken from the `DocumentFragment` used as `children`. - Filter props with <Localized attrs={{…}}>. (projectfluent#139, projectfluent#141) The `<Localized>` component now requires the `attrs` prop to set any localized attributes as props on the wrapped component. `attrs` should be an object with attribute names as keys and booleans as values. ```jsx <Localized id="type-name" attrs={{placeholder: true}}> <input type="text" placeholder="Localizable placeholder" value={name} onChange={…} /> </Localized> ``` By default, if `attrs` is not passed, no attributes will be set. This is a breaking change compared to the previous behavior: in `fluent-react` 0.4.1 and before `<Localized>` would set _all_ attributes found in the translation. If you're setting localized attributes as props of elements wrapped in `<Localized>`, in `fluent-react` 0.6.0 you'll need to also explicitly allow the props you're interested in using the `attrs` prop. This protects your components from accidentally gaining props they aren't expecting or from translations overwriting important props which shouldn't change. ```jsx // BEFORE (fluent-react 0.4.1) <Localized id="type-name"> <input type="text" placeholder="Localizable placeholder" value={name} onChange={…} /> </Localized> ``` ```jsx // AFTER (fluent-react 0.6.0) <Localized id="type-name" attrs={{placeholder: true}}> <input type="text" placeholder="Localizable placeholder" value={name} onChange={…} /> </Localized> ``` In `fluent-react` 0.4.1 it was possible to pass React elements as _external arguments_ to localization via the `$`-prefixed props, just like you'd pass a number or a date. This was a bad localization practice because it resulted in the translation being split into multiple strings. ```properties send-comment-confirm = Send send-comment-cancel = go back send-comment = { $confirmButton } or { $cancelLink }. ``` ```jsx // Bad practice. This won't work in fluent-react 0.6.0. <Localized id="send-comment" $confirmButton={ <Localized id="send-comment-confirm"> <button onClick={sendComment}>{'Send'}</button> </Localized> } $cancelLink={ <Localized id="send-comment-cancel"> <Link to="/">{'go back'}</Link> </Localized> } > <p>{'{ $confirmButton } or { $cancelLink}.'}</p> </Localized> ``` `fluent-react` 0.6.0 removes support for this feature. It is no longer possible to pass React elements as `$`-prefixed _arguments_ to translations. Please migrate your code to use markup in translations and pass React elements as _props_ to `<Localized>`. In the example above, change `$confirmButton` to `confirm` and `$cancelLink` to `cancel`. Note that you don't need to wrap the passed element in another `<Localized>` anymore. In particular, you don't need to assign a new message id for it. The text for this element will be taken from the `send-comment` message which can now include the markup for the button and the link. ```properties send-comment = <confirm>Send</confirm> or <cancel>go back</cancel>. ``` ```jsx // BEFORE (fluent-react 0.4.1) <Localized id="send-comment" $confirmButton={ <Localized id="send-comment-button"> <button onClick={sendComment}>{'Send'}</button> </Localized> } $cancelLink={ <Localized id="send-comment-cancel"> <Link to="/">{'go back'}</Link> </Localized> } > <p>{'{ $confirmButton } or { $cancelLink}.'}</p> </Localized> ``` ```jsx // AFTER (fluent-react 0.6.0) <Localized id="send-comment" confirm={ <button onClick={sendComment}></button> } cancel={ <Link to="/"></Link> } > <p>{'<confirm>Send</confirm> or <cancel>go back</cancel>.'}</p> </Localized> ``` `fluent-react` 0.6.0 works best with `fluent` 0.6.0. It might still work with `fluent` 0.4.x but passing elements as `$`-prefixed arguments to translations will break your app. You might also run into other issues with translations with attributes and no values. Upgrading your code to [`fluent` 0.6.0][] and your localization files to [Fluent Syntax 0.5][] is the best way to avoid troubles. [`fluent` 0.6.0]: https://github.com/projectfluent/fluent.js/releases/tag/fluent%400.6.0 [Fluent Syntax 0.5]: https://github.com/projectfluent/fluent/releases/tag/v0.5.0
stasm
added a commit
to stasm/fluent.js
that referenced
this pull request
Feb 1, 2018
- Allow limited markup in translations. (projectfluent#101) Translations in Fluent can now include simple HTML-like markup. Elements found in translations will be matched with props passed to `<Localized>`. These props must be React elements. Their content will be replaced by the localizable content found for the corrensponding markup in the translation. This is a breaking change from `fluent-react` 0.4.1. See migration notes below. ```properties send-comment = <confirm>Send</confirm> or <cancel>go back</cancel>. ``` ```js <Localized id="send-comment" confirm={ <button onClick={sendComment}></button> } cancel={ <Link to="/"></Link> } > <p>{'<confirm>Send</confirm> or <cancel>go back</cancel>.'}</p> </Localized> ``` The rendered result will include the props interpolated into the translation: ```js <p> <button onClick={sendComment}>Send</button> or <Link to="/">go back</Link>. </p> ``` When naming markup elements it's possible to use any name which is a valid prop name. Translations containing markup will be parsed using a hidden `<template>` element. It creates a safe inert `DocumentFragment` with a hierarchy of text nodes and HTML elements. Any unknown elements (e.g. `cancel` in the example above) are parsed as `HTMLUnknownElements`. `fluent-react` then tries to match all elements found in the translation with props passed to the `<Localized>` component. If a match is found, the element passed as a prop is cloned with the translated text content taken from the `DocumentFragment` used as `children`. - Filter props with <Localized attrs={{…}}>. (projectfluent#139, projectfluent#141) The `<Localized>` component now requires the `attrs` prop to set any localized attributes as props on the wrapped component. `attrs` should be an object with attribute names as keys and booleans as values. ```jsx <Localized id="type-name" attrs={{placeholder: true}}> <input type="text" placeholder="Localizable placeholder" value={name} onChange={…} /> </Localized> ``` By default, if `attrs` is not passed, no attributes will be set. This is a breaking change compared to the previous behavior: in `fluent-react` 0.4.1 and before `<Localized>` would set _all_ attributes found in the translation. If you're setting localized attributes as props of elements wrapped in `<Localized>`, in `fluent-react` 0.6.0 you'll need to also explicitly allow the props you're interested in using the `attrs` prop. This protects your components from accidentally gaining props they aren't expecting or from translations overwriting important props which shouldn't change. ```jsx // BEFORE (fluent-react 0.4.1) <Localized id="type-name"> <input type="text" placeholder="Localizable placeholder" value={name} onChange={…} /> </Localized> ``` ```jsx // AFTER (fluent-react 0.6.0) <Localized id="type-name" attrs={{placeholder: true}}> <input type="text" placeholder="Localizable placeholder" value={name} onChange={…} /> </Localized> ``` In `fluent-react` 0.4.1 it was possible to pass React elements as _external arguments_ to localization via the `$`-prefixed props, just like you'd pass a number or a date. This was a bad localization practice because it resulted in the translation being split into multiple strings. ```properties send-comment-confirm = Send send-comment-cancel = go back send-comment = { $confirmButton } or { $cancelLink }. ``` ```jsx // Bad practice. This won't work in fluent-react 0.6.0. <Localized id="send-comment" $confirmButton={ <Localized id="send-comment-confirm"> <button onClick={sendComment}>{'Send'}</button> </Localized> } $cancelLink={ <Localized id="send-comment-cancel"> <Link to="/">{'go back'}</Link> </Localized> } > <p>{'{ $confirmButton } or { $cancelLink}.'}</p> </Localized> ``` `fluent-react` 0.6.0 removes support for this feature. It is no longer possible to pass React elements as `$`-prefixed _arguments_ to translations. Please migrate your code to use markup in translations and pass React elements as _props_ to `<Localized>`. In the example above, change `$confirmButton` to `confirm` and `$cancelLink` to `cancel`. Note that you don't need to wrap the passed element in another `<Localized>` anymore. In particular, you don't need to assign a new message id for it. The text for this element will be taken from the `send-comment` message which can now include the markup for the button and the link. ```properties send-comment = <confirm>Send</confirm> or <cancel>go back</cancel>. ``` ```jsx // BEFORE (fluent-react 0.4.1) <Localized id="send-comment" $confirmButton={ <Localized id="send-comment-button"> <button onClick={sendComment}>{'Send'}</button> </Localized> } $cancelLink={ <Localized id="send-comment-cancel"> <Link to="/">{'go back'}</Link> </Localized> } > <p>{'{ $confirmButton } or { $cancelLink}.'}</p> </Localized> ``` ```jsx // AFTER (fluent-react 0.6.0) <Localized id="send-comment" confirm={ <button onClick={sendComment}></button> } cancel={ <Link to="/"></Link> } > <p>{'<confirm>Send</confirm> or <cancel>go back</cancel>.'}</p> </Localized> ``` `fluent-react` 0.6.0 works best with `fluent` 0.6.0. It might still work with `fluent` 0.4.x but passing elements as `$`-prefixed arguments to translations will break your app. You might also run into other issues with translations with attributes and no values. Upgrading your code to [`fluent` 0.6.0][] and your localization files to [Fluent Syntax 0.5][] is the best way to avoid troubles. [`fluent` 0.6.0]: https://github.com/projectfluent/fluent.js/releases/tag/fluent%400.6.0 [Fluent Syntax 0.5]: https://github.com/projectfluent/fluent/releases/tag/v0.5.0
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #139.
The component now requires the
attrsprop to set any localized attributes as props on the wrapped component.attrsshould be an object with attribute names as keys and booleans as values.By default, if
attrsis not passed, no attributes will be set. This is a breaking change compared to the previous behavior: influent-react0.4.1 and before<Localized>would set all attributes found in thetranslation.