Skip to content

Commit

Permalink
Merge branch 'langpavel-docs'
Browse files Browse the repository at this point in the history
  • Loading branch information
koistya committed May 3, 2016
2 parents 03fddd6 + cf6dad3 commit 629bea0
Show file tree
Hide file tree
Showing 5 changed files with 198 additions and 0 deletions.
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ forked repo, check that it meets these guidelines:
* [Squash](http://stackoverflow.com/questions/5189560/squash-my-last-x-commits-together-using-git)
your commits into one for each PR.
* Run `npm test` to make sure that your code style is OK and there are no any regression bugs.
* When contributing to an opt-in feature, apply the `[feature/...]` tag as a prefix to your PR title

#### Style Guide

Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,23 @@ visit our sponsors:<br><br>
* Follow the [getting started guide](./docs/getting-started.md) to download and run the project
* Check the [code recipes](./docs/recipes) used in this boilerplate, or share yours

### Customization

The `master` branch of React Starter Kit doesn't include a Flux implementation or any other
advanced integrations. Nevertheless, we have some integrations available to you in *feature*
branches that you can use either as a reference or merge into your project:

* [feature/redux](https://github.com/kriasoft/react-starter-kit/tree/feature/redux) — isomorphic
Redux by [Pavel Lang](https://github.com/langpavel) (see [how to integrate
Redux](./docs/recipes/how-to-integrate-redux.md))
* [feature/react-intl](https://github.com/kriasoft/react-starter-kit/tree/feature/react-intl)
isomorphic Redux and React Intl by [Pavel Lang](https://github.com/langpavel) (see [how
to integrate React Intl](./docs/recipes/how-to-integrate-react-intl.md))

If you think that any of these features should be on `master`, or vise versa, some features should
removed from the `master` branch, please [let us know](https://gitter.im/kriasoft/react-starter-kit).
We love your feedback!

### Backers

♥ React Starter Kit? Help us keep it alive by donating funds to cover project
Expand Down
2 changes: 2 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@
### Recipes

* [How to Implement Routing and Navigation](./recipes/how-to-implement-routing.md)
* [How to Integrate Redux](./recipes/how-to-integrate-redux.md)
* [How to Integrate React Intl](./recipes/how-to-integrate-react-intl.md)
* [How to Integrate Disqus](./recipes/how-to-integrate-disqus.md)
122 changes: 122 additions & 0 deletions docs/recipes/how-to-integrate-react-intl.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
## How to Integrate [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.
56 changes: 56 additions & 0 deletions docs/recipes/how-to-integrate-redux.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
## How to Integrate [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`

0 comments on commit 629bea0

Please sign in to comment.