Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…into langpavel-docs
  • Loading branch information
koistya committed May 3, 2016
2 parents 03fddd6 + ba597af commit cf6dad3
Show file tree
Hide file tree
Showing 5 changed files with 200 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
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,25 @@ expenses via [OpenCollective](https://opencollective.com/react-starter-kit) or
<img src="https://opencollective.com/static/images/become_backer.svg" width="64" height="64" alt="">
</a>

### Feature branches

Some features aren't provided by default, but you can optionally add them.
To do so, simply merge the corresponding feature branch.
These branches should be in sync with master and all other features branches
so there should not be any merging conflicts.
If conflicts occur, please [report to us](https://github.com/kriasoft/react-starter-kit/issues).

* [feature/redux](https://github.com/kriasoft/react-starter-kit/tree/feature/redux) – isomorphic redux support.
Use [`connect()`](https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options)
higher order component to access state in redux store and to get actions mapped on dispatch.
You can see [LanguageSwitcher](https://github.com/kriasoft/react-starter-kit/blob/86eadfd3d11d804cf858aa21f657022fcc098752/src/components/LanguageSwitcher/LanguageSwitcher.js) component how to use `connect()`
<br/>
[Read full recipe](./docs/recipes/feature-redux.md)

* [feature/react-intl](https://github.com/kriasoft/react-starter-kit/tree/feature/react-intl)[`react-intl`](https://github.com/yahoo/react-intl#react-intl) integration based on `feature/redux`
<br/>
[Read full recipe](./docs/recipes/feature-react-intl.md)

### Learn More

* [Getting Started with React.js](http://facebook.github.io/react/)
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/feature-redux.md)
* [How to Integrate React-Intl](./recipes/feature-react-intl.md)
* [How to Integrate Disqus](./recipes/how-to-integrate-disqus.md)
122 changes: 122 additions & 0 deletions docs/recipes/feature-react-intl.md
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.
56 changes: 56 additions & 0 deletions docs/recipes/feature-redux.md
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`

0 comments on commit cf6dad3

Please sign in to comment.