Skip to content

Commit

Permalink
i18n-js runtime extension, stick interpolator on I18n
Browse files Browse the repository at this point in the history
  • Loading branch information
jenseng committed Mar 29, 2015
1 parent 68c37c0 commit fce4488
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 12 deletions.
60 changes: 53 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,22 +49,68 @@ will Just Work™.

## Installation

TODO: depends on [this feature](https://github.com/jenseng/i18nliner-js/issues/12) ... until then you need some glue code.
### 1. get i18n-js and i18nliner

Get i18n-js and i18nliner installed [per these instructions](https://github.com/jenseng/i18nliner-js#installation).

### 2. add react-i18nliner

```bash
npm install i18nliner react-i18nliner --save
npm install react-i18nliner --save
```

And make sure your `.i18nrc` file has:

```json
{
"plugins": {
"react-i18nliner": true
}
"plugins": [
"react-i18nliner"
]
}
```

TODO: figure out registering w/ runtime extension
This will ensure that when you export strings for translation, all of your
new `translate="yes"` stuff will get picked up.

### 3. preprocess your all your js files with react-i18nliner

TODO: webpack / browserify / broccoli / etc

### 4. add the react-i18nliner runtime extensions to i18n-js

Assuming you have a cjs-style app, do something like this:

```js
var I18n = require("./path/to/cjs'd/i18n");
require("i18nliner/dist/lib/extensions/i18n_js")["default"](I18n);
require("react-i18nliner/extensions/i18n_js")(I18n);
```

If you're using AMD/`<script>`/something else, see the [i18nliner-js README](https://github.com/jenseng/i18nliner-js#installation)
for hints; these extensions can be set up exactly the same way as
i18nliner-js's.

## Working with translations

Since react-i18nliner is just an i18nliner plugin, you can use the
i18nliner bin / grunt task to extract translations from your codebase;
it will pick up normal `I18n.t` usage, as well as your new
`translate="yes"` components.

TODO: instructions for browserify/webpack
Once you've gotten all your translations back from the translators,
simply stick them the giant blob 'o json on `I18n.translations`; it
expects the translations to be of the format:

```js
I18n.translations = {
"en": {
"some_key": "Hello World",
"another_key": "What's up?"
}
"es": {
"some_key": "Hola mundo",
"another_key": "¿Qué tal?"
},
...
}
```
8 changes: 4 additions & 4 deletions __tests__/preprocess.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,19 @@ describe('preprocess', function() {
});

it('transforms translatable content with markup', function() {
expect(subject('<div translate="yes">hello <b>world</b></div>')).toEqual('<div><ComponentInterpolator string={I18n.t("hello *world*")} wrappers={{ "*": <b /> }} /></div>');
expect(subject('<div translate="yes">hello <b>world</b></div>')).toEqual('<div><I18n.ComponentInterpolator string={I18n.t("hello *world*")} wrappers={{ "*": <b /> }} /></div>');
});

it('creates placeholders for expressions', function() {
expect(subject('<div translate="yes">hello {this.props.userName}</div>')).toEqual('<div><ComponentInterpolator string={I18n.t("hello %{user_name}")} user_name={this.props.userName} /></div>');
expect(subject('<div translate="yes">hello {this.props.userName}</div>')).toEqual('<div><I18n.ComponentInterpolator string={I18n.t("hello %{user_name}")} user_name={this.props.userName} /></div>');
});

it('creates placeholders for components with no textContent', function() {
expect(subject('<div translate="yes">Create <input /> new accounts</div>')).toEqual('<div><ComponentInterpolator string={I18n.t("Create %{input} new accounts")} input={<input />} /></div>');
expect(subject('<div translate="yes">Create <input /> new accounts</div>')).toEqual('<div><I18n.ComponentInterpolator string={I18n.t("Create %{input} new accounts")} input={<input />} /></div>');
});

it('ensures placeholders are unique', function() {
expect(subject('<div translate="yes"><input /> vs <input /></div>')).toEqual('<div><ComponentInterpolator string={I18n.t("%{input} vs %{input1}")} input={<input />} input1={<input />} /></div>');
expect(subject('<div translate="yes"><input /> vs <input /></div>')).toEqual('<div><I18n.ComponentInterpolator string={I18n.t("%{input} vs %{input1}")} input={<input />} input1={<input />} /></div>');
});
});

7 changes: 7 additions & 0 deletions extensions/i18n_js.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
var ComponentInterpolator = require("../ComponentInterpolator");

var extend = function(I18n) {
I18n.ComponentInterpolator = ComponentInterpolator;
};

module.exports = extend;
2 changes: 2 additions & 0 deletions extensions/i18n_js_build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
import extend from './i18n_js';
extend(I18n);
4 changes: 3 additions & 1 deletion preprocess.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
var recast = require('recast');
var b = recast.types.builders;

var interpolatorName = "I18n.ComponentInterpolator";

var findIndex = function(fn, ary) {
for (var i = 0; i < ary.length; i++) {
if (fn(ary[i]))
Expand Down Expand Up @@ -60,7 +62,7 @@ var componentInterpolatorFor = function(string, wrappers, placeholders) {

return b.jsxElement(
b.jsxOpeningElement(
b.jsxIdentifier("ComponentInterpolator"),
b.jsxIdentifier(interpolatorName),
properties,
true
)
Expand Down

0 comments on commit fce4488

Please sign in to comment.