-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'docs' of https://github.com/langpavel/react-starter-kit …
…into langpavel-docs
- Loading branch information
Showing
5 changed files
with
200 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,122 @@ | ||
## Integrating [React-Intl](https://github.com/yahoo/react-intl#react-intl) | ||
|
||
1. Merge `feature/react-intl` branch with git. | ||
Because react-intl integration is built on top of `feature/redux`, you'll also get all the features. | ||
|
||
2. Adjust `INTL_REQUIRE_DESCRIPTIONS` constant in `tools/webpack.config.js` around line 17: | ||
```js | ||
const INTL_REQUIRE_DESCRIPTIONS = true; | ||
``` | ||
When this boolean is set to true, the build will only succeed if a `description` is set for every message descriptor. | ||
|
||
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 the 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 | ||
the [`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) | ||
|
||
- If possible, do not use `<FormattedHTMLMessage>`, see how to use *Rich Text Formatting* with | ||
[`<FormattedMessage>`](https://github.com/yahoo/react-intl/wiki/Components#formattedmessage) | ||
|
||
- When you need an imperative formatting API, use the [`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 running the development server, every source file is watched and parsed for changed messages. | ||
|
||
Messages files are updated on the fly. | ||
If a new definition is found, this definition is added to the end of every used `src/messages/xx-XX.json` file so when commiting, new translations will be at the tail of file. | ||
|
||
When an untranslated message is removed and its `message` field is empty as well, the message will be deleted from all translation files. This is why the `files` array is present. | ||
|
||
When editiong a 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,56 @@ | ||
## Integrating [Redux](http://redux.js.org/index.html) | ||
|
||
Merge `feature/redux` branch with git. | ||
If you are interested in `feature/react-intl`, | ||
merge that branch instead as it also includes 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 actions, use [`redux-thunk`](https://github.com/gaearon/redux-thunk#readme). | ||
For inspiration on 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 information 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 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 an 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 dispatching actions. | ||
|
||
|
||
## Dispatching Actions On Server | ||
|
||
See source of `src/server.js` |