Skip to content

Commit

Permalink
Support different component name and i18n key for Trans component (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
cheton committed Jan 20, 2018
1 parent eddde76 commit b01b898
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 21 deletions.
51 changes: 47 additions & 4 deletions README.md
Expand Up @@ -108,9 +108,11 @@ module.exports = {
extensions: ['.js', '.jsx']
},
trans: {
component: 'Trans',
i18nKey: 'i18nKey',
extensions: ['.js', '.jsx'],
fallbackKey: function(ns, value) {
return value;
return sha1(value); // return a sha1 as the key
}
},
lngs: ['en','de'],
Expand Down Expand Up @@ -181,7 +183,8 @@ parser
content = fs.readFileSync('/path/to/app.jsx', 'utf-8');
parser
.parseTransFromString(content, customHandler) // pass a custom handler
.parseTransFromString(content, { fallbackKey: true }) // Use fallback key when key is missing
.parseTransFromString(content, { component: 'Trans', i18nKey: 'i18nKey' })
.parseTransFromString(content, { fallbackKey: true }) // Uses defaultValue as the fallback key when the i18nKey attribute is missing
.parseTransFromString(content); // use default options and handler

// Parse HTML Attribute
Expand Down Expand Up @@ -291,7 +294,7 @@ const html = '<div data-i18n="key"></div>';
parser.parseAttrFromString(html);

parser.get();
````
```

#### parser.parseFuncFromString
Parse translation key from JS function
Expand All @@ -315,11 +318,15 @@ Parse translation key from the [Trans component](https://github.com/i18next/reac
```js
parser.parseTransFromString(content);

parser.parseTransFromString(context, { component: 'Trans', i18nKey: 'i18nKey' });

// Uses defaultValue as the fallback key when the i18nKey attribute is missing
parser.parseTransFromString(content, { fallbackKey: true });

// Returns a hash value as the fallback key
parser.parseTransFromString(content, {
fallbackKey: function(ns, value) {
return value;
return sha1(value);
}
});

Expand Down Expand Up @@ -482,6 +489,12 @@ Below are the configuration options with their default values:
list: ['i18next.t', 'i18n.t'],
extensions: ['.js', '.jsx']
},
trans: {
component: 'Trans',
i18nKey: 'i18nKey',
extensions: ['.js', '.jsx'],
fallbackKey: false
},
lngs: ['en'],
ns: ['translation'],
defaultNs: 'translation',
Expand Down Expand Up @@ -563,6 +576,36 @@ You can set func to `false` to disable parsing translation function as below:
}
```

#### trans

Type: `Object` or `false`

If an `Object` is supplied, you can specify a list of extensions, or override the default.
```js
{ // Default
trans: {
component: 'Trans',
i18nKey: 'i18nKey',
extensions: ['.js', '.jsx'],
fallbackKey: false
}
}
```

You can set trans to `false` to disable parsing Trans component as below:
```js
{
trans: false
}
```

The fallbackKey can either be a boolean value, or a function like so:
```js
fallbackKey: function(ns, value) {
return sha1(value); // returns a hash value as the fallback key
}
```

#### lngs

Type: `Array` Default: `['en']`
Expand Down
2 changes: 1 addition & 1 deletion package.json
@@ -1,6 +1,6 @@
{
"name": "i18next-scanner",
"version": "2.3.1",
"version": "2.4.0",
"description": "Scan your code, extract translation keys/values, and merge them into i18n resource files.",
"homepage": "https://github.com/i18next/i18next-scanner",
"author": "Cheton Wu <cheton@gmail.com>",
Expand Down
27 changes: 13 additions & 14 deletions src/parser.js
Expand Up @@ -25,9 +25,9 @@ const defaults = {
},

trans: { // Trans component (https://github.com/i18next/react-i18next)
// list: ['Trans'], // TODO
component: 'Trans',
i18nKey: 'i18nKey',
extensions: ['.js', '.jsx'],
// key: 'i18nKey', // TODO
fallbackKey: false
},

Expand Down Expand Up @@ -128,19 +128,15 @@ const transformOptions = (options) => {
}

// Trans
/* TODO
if (_.isUndefined(_.get(options, 'trans.list'))) {
_.set(options, 'trans.list', defaults.trans.list);
if (_.isUndefined(_.get(options, 'trans.component'))) {
_.set(options, 'trans.component', defaults.trans.component);
}
if (_.isUndefined(_.get(options, 'trans.i18nKey'))) {
_.set(options, 'trans.i18nKey', defaults.trans.i18nKey);
}
*/
if (_.isUndefined(_.get(options, 'trans.extensions'))) {
_.set(options, 'trans.extensions', defaults.trans.extensions);
}
/* TODO
if (_.isUndefined(_.get(options, 'trans.key'))) {
_.set(options, 'trans.key', defaults.trans.key);
}
*/
if (_.isUndefined(_.get(options, 'trans.fallbackKey'))) {
_.set(options, 'trans.fallbackKey', defaults.trans.fallbackKey);
}
Expand Down Expand Up @@ -402,7 +398,10 @@ class Parser {
opts = {};
}

const reTrans = new RegExp('<Trans([^]*?)>([^]*?)</\\s*Trans\\s*>', 'gim');
const component = opts.component || this.options.trans.component;
const i18nKey = opts.i18nKey || this.options.trans.i18nKey;

const reTrans = new RegExp('<' + component + '([^]*?)>([^]*?)</\\s*' + component + '\\s*>', 'gim');
const reAttribute = /\b(\S+)\s*=\s*({.*?}|".*?"|'.*?')/gm;

let r;
Expand All @@ -415,9 +414,9 @@ class Parser {
let transKey;

try {
transKey = attributes.i18nKey ? getStringFromAttribute(attributes.i18nKey) : '';
transKey = attributes[i18nKey] ? getStringFromAttribute(attributes[i18nKey]) : '';
} catch (e) {
this.log(`i18next-scanner: i18nKey value must be a static string, saw ${chalk.yellow(attributes.i18nKey)}`);
this.log(`i18next-scanner: i18nKey value must be a static string, saw ${chalk.yellow(attributes[i18nKey])}`);
continue;
}

Expand Down
6 changes: 4 additions & 2 deletions test/fixtures/app.jsx
@@ -1,5 +1,5 @@
const mycomp = () => (
<div>
<React.Fragment>
<Trans i18nKey="key1">Key 1 default</Trans>
<Trans i18nKey="key2">
Key 2
Expand All @@ -14,5 +14,7 @@ const mycomp = () => (
<Trans count={1}>key8 default {{count}}</Trans>
<Trans>We can use Trans without i18nKey="..." as well!</Trans>
<Trans i18nKey="key9" context="male">A boyfriend</Trans>
</div>
<I18N __t="key10">A wrapper component with key</I18N>
<I18N>A wrapper component without key</I18N>
</React.Fragment>
)
26 changes: 26 additions & 0 deletions test/parser.js
Expand Up @@ -170,6 +170,32 @@ test('Parse Trans component #2', (t) => {
t.end();
});

test('Parse Trans component #3', (t) => {
const parser = new Parser({
lngs: ['en'],
trans: {
component: 'I18N',
i18nKey: '__t',
fallbackKey: true
},
nsSeparator: false,
keySeparator: false,
fallbackLng: 'en'
});

const content = fs.readFileSync(path.resolve(__dirname, 'fixtures/app.jsx'), 'utf-8');
parser.parseTransFromString(content);
t.same(parser.get(), {
en: {
translation: {
"key10": "A wrapper component with key",
"A wrapper component without key": "A wrapper component without key"
}
}
});
t.end();
});

test('Parse HTML attribute', (t) => {
const parser = new Parser({
lngs: ['en'],
Expand Down

0 comments on commit b01b898

Please sign in to comment.