forked from kriasoft/react-starter-kit
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Updated docs, documented feature branches, added recipes
closes kriasoft#612 closes kriasoft#610 closes kriasoft#595 closes kriasoft#173
- Loading branch information
Showing
5 changed files
with
199 additions
and
0 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
## Integrating [React-Intl](https://github.com/yahoo/react-intl#react-intl) | ||
|
||
1. Merge `feature/react-intl` branch with git. | ||
You will get `feature/redux` too because this is based on top of it. | ||
|
||
2. Adjust `INTL_REQUIRE_DESCRIPTIONS` constant in `tools/webpack.config.js` around line 17: | ||
```js | ||
const INTL_REQUIRE_DESCRIPTIONS = true; | ||
``` | ||
It's boolean. When enabled, build will fail if `description` is not provided. | ||
3. Adjust `locales` settings in `src/config.js`: | ||
```js | ||
// default locale is the first one | ||
export const locales = ['en-GB', 'cs-CZ']; | ||
``` | ||
Note that you should follow | ||
[BCP 47](https://tools.ietf.org/html/bcp47) | ||
([RFC 5646](https://tools.ietf.org/html/rfc5646)). | ||
4. Add locale support in `src/client.js`: | ||
```js | ||
import en from 'react-intl/locale-data/en'; | ||
import cs from 'react-intl/locale-data/cs'; | ||
... | ||
[en, cs].forEach(addLocaleData); | ||
``` | ||
5. Execute `npm run extractMessages` or `npm start` to strip out messages. | ||
Message files are created in `src/messages` directory. | ||
6. Edit `src/messages/*.json` files, change only `message` property. | ||
7. Execute `npm run build`, | ||
your translations should be copied to `build/messages/` directory. | ||
## How to write localizable components | ||
Just import appropriate [component](https://github.com/yahoo/react-intl/wiki#the-react-intl-module) from `react-intl` | ||
- For localizable text use | ||
[`<FormattedMessage>`](https://github.com/yahoo/react-intl/wiki/Components#formattedmessage). | ||
- You can also use it with | ||
[`defineMessages()`](https://github.com/yahoo/react-intl/wiki/API#definemessages) helper. | ||
- For date and time: | ||
[`<FormattedDate>`](https://github.com/yahoo/react-intl/wiki/Components#formatteddate) | ||
[`<FormattedTime>`](https://github.com/yahoo/react-intl/wiki/Components#formattedtime) | ||
[`<FormattedRelative>`](https://github.com/yahoo/react-intl/wiki/Components#formattedrelative) | ||
- For numbers and currencies: | ||
[`<FormattedNumber>`](https://github.com/yahoo/react-intl/wiki/Components#formattednumber) | ||
[`<FormattedPlural>`](https://github.com/yahoo/react-intl/wiki/Components#formattedplural) | ||
- Do not use `<FormattedHTMLMessage>` if possible, see how to use *Rich Text Formatting* with | ||
[`<FormattedMessage>`](https://github.com/yahoo/react-intl/wiki/Components#formattedmessage) | ||
- When you need imperative formatting API, use [`injectIntl`](https://github.com/yahoo/react-intl/wiki/API#injectintl) High-Order Component. | ||
### Example | ||
```jsx | ||
import { defineMessages, FormattedMessage, injectIntl, intlShape } from 'react-intl'; | ||
const messages = defineMessages({ | ||
text: { | ||
id: 'example.text', | ||
defaultMessage: 'Example text', | ||
description: 'Hi Pavel', | ||
}, | ||
textTemplate: { | ||
id: 'example.text.template', | ||
defaultMessage: 'Example text template', | ||
description: 'Hi {name}', | ||
}, | ||
}); | ||
function Example(props) { | ||
const text = props.intl.formatMessage(messages.textTemplate, { name: 'Pavel'}); | ||
return ( | ||
<div> | ||
<FormattedMessage | ||
id="example.text.inlineDefinition" | ||
defaultMessage="Hi Pavel" | ||
description="Example of usage without defineMessages" | ||
/> | ||
<FormattedMessage {...messages.text} /> | ||
<FormattedMessage | ||
{...messages.textTemplate} | ||
values={{ | ||
name: <b>Pavel</b> | ||
}} | ||
/> | ||
</div> | ||
); | ||
} | ||
Example.propTypes = { | ||
intl: intlShape, | ||
} | ||
export default injectIntl(Example); | ||
``` | ||
## Updating translations | ||
When developing, every source file is watched and parsed for messages on change. | ||
Messages files are updated on the fly. | ||
If new definition is found, this definition is added at the end of every used `src/messages/xx-XX.json` file so when commiting, new translations are at the tail of file. | ||
When untranslated message is removed and if it's `message` field is empty too, message is deleted from all translation files. This is reason why `files` array is present. | ||
|
||
When developing and you edit translation file, it should be copied to `build/messages/` directory. | ||
|
||
## Other references | ||
|
||
* [`Intl documentation on MDN`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Intl) | ||
* [express-request-language](https://github.com/tinganho/express-request-language#readme) | ||
– for more details how initial language negotiation works. |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
## Integrating [Redux](http://redux.js.org/index.html) | ||
|
||
Merge `feature/redux` branch with git. | ||
If you are interrested into `feature/react-intl`, | ||
merge that branch instead. | ||
It contains this implementation of redux | ||
|
||
**If you don't know redux well, you should [read about it first](http://redux.js.org/docs/basics/index.html).** | ||
|
||
|
||
## Creating Actions | ||
|
||
1. Go to `src/constants/index.js` and define action name there. | ||
|
||
2. Go to `src/actions/` and create file with appropriate name. | ||
You can copy `src/actions/runtime.js` as a template. | ||
|
||
3. If you need async action, [`redux-thunk`](https://github.com/gaearon/redux-thunk#readme) | ||
is there for you. | ||
For inspiration how to create async actions you can look at | ||
[`setLocale`](https://github.com/kriasoft/react-starter-kit/blob/feature/react-intl/src/actions/intl.js) | ||
action from `feature/react-intl`. | ||
See [Async Flow](http://redux.js.org/docs/advanced/AsyncFlow.html) for more on this topic | ||
|
||
|
||
## Creating Reducer (aka Store) | ||
|
||
1. Go to [`src/reducers/`](https://github.com/kriasoft/react-starter-kit/tree/feature/redux/src/reducers) and create new file there. | ||
|
||
You can copy [`src/reducers/runtime.js`](https://github.com/kriasoft/react-starter-kit/tree/feature/redux/src/reducers/runtime.js) as a template. | ||
|
||
- Do not forget to always return `state`. | ||
- Never mutate provided `state`. | ||
If you mutate state, rendering of connected component will not be triggered because of `===` equality. | ||
Always return new value if you perform state update. | ||
You can use this construct: `{ ...state, updatedKey: action.payload.value, }` | ||
- Keep in mind that store state *must* be repeatable by replaying actions on it. | ||
For example, when you store timestamp, pass it into *action payload*. | ||
If you call REST API, do it in action. Never do this things in reducer! | ||
|
||
2. Edit [`src/reducers/index.js`](https://github.com/kriasoft/react-starter-kit/tree/feature/redux/src/reducers/index.js), import your reducer and add it to root reducer created by | ||
[`combineReducers`](http://redux.js.org/docs/api/combineReducers.html) | ||
|
||
|
||
## Connecting Components | ||
|
||
You can use [`connect()`](https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options) High-Order Component from [`react-redux`](https://github.com/reactjs/react-redux#readme) package. | ||
|
||
See [Usage With React](http://redux.js.org/docs/basics/UsageWithReact.html) on redux.js.org. | ||
|
||
For example you can look at | ||
[`<LanguageSwitcher>`](https://github.com/kriasoft/react-starter-kit/blob/feature/react-intl/src/components/LanguageSwitcher/LanguageSwitcher.js) | ||
component from `feature/react-intl` branch. It demonstrates both, subscribing to store and dispathing actions. | ||
|
||
|
||
## Dispatching Actions On Server | ||
|
||
See source of `src/server.js` |