Skip to content

Commit

Permalink
feat(@formatjs/ts-transformer): allow setting `additionalFunctionName…
Browse files Browse the repository at this point in the history
…s` to extract from custom function calls
  • Loading branch information
longlho committed Jan 4, 2021
1 parent 162c1f4 commit 96fc3b1
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 4 deletions.
17 changes: 13 additions & 4 deletions packages/ts-transformer/src/transform.ts
Expand Up @@ -97,6 +97,12 @@ export interface Opts {
* e.g: `['FormattedFooBarMessage']`.
*/
additionalComponentNames?: string[];
/**
* Additional function names to extract messages from,
* e.g: `['formatMessage', '$t']`
* Default to `['formatMessage']`
*/
additionalFunctionNames?: string[];
/**
* Opt-in to extract from `intl.formatMessage` call with the same restrictions,
* e.g: has to be called with object literal such as
Expand Down Expand Up @@ -352,8 +358,10 @@ function extractMessageDescriptor(
*/
function isIntlFormatMessageCall(
ts: TypeScript,
node: typescript.CallExpression
node: typescript.CallExpression,
additionalFunctionNames: string[]
) {
const fnNames = new Set(['formatMessage', ...additionalFunctionNames]);
const method = node.expression;

// Handle intl.formatMessage()
Expand All @@ -368,7 +376,7 @@ function isIntlFormatMessageCall(
}

// Handle formatMessage()
return ts.isIdentifier(method) && method.text === 'formatMessage';
return ts.isIdentifier(method) && fnNames.has(method.text);
}

function extractMessageFromJsxComponent(
Expand Down Expand Up @@ -506,7 +514,7 @@ function extractMessagesFromCallExpression(
opts: Opts,
sf: typescript.SourceFile
): typeof node {
const {onMsgExtracted} = opts;
const {onMsgExtracted, additionalFunctionNames} = opts;
if (isMultipleMessageDecl(ts, node)) {
const [arg, ...restArgs] = node.arguments;
let descriptorsObj: typescript.ObjectLiteralExpression | undefined;
Expand Down Expand Up @@ -576,7 +584,8 @@ function extractMessagesFromCallExpression(
}
} else if (
isSingularMessageDecl(ts, node, opts.additionalComponentNames || []) ||
(opts.extractFromFormatMessageCall && isIntlFormatMessageCall(ts, node))
(opts.extractFromFormatMessageCall &&
isIntlFormatMessageCall(ts, node, additionalFunctionNames || []))
) {
const [descriptorsObj, ...restArgs] = node.arguments;
if (ts.isObjectLiteralExpression(descriptorsObj)) {
Expand Down
27 changes: 27 additions & 0 deletions packages/ts-transformer/tests/__snapshots__/index.test.ts.snap
Expand Up @@ -78,6 +78,33 @@ export default class Foo extends Component {
}
`;
exports[`emit asserts for additionalFunctionNames 1`] = `
Object {
"code": "// @react-intl project:foo
import React, { Component } from 'react';
function CustomMessage() { }
export default class Foo extends Component {
render() {
return (<CustomMessage id={formatMessage({ id: \\"rL0Y20zC+F\\", defaultMessage: \\"foo\\" })} description={$formatMessage({ id: \\"rL0Y20zC+F\\", defaultMessage: \\"foo\\" })} defaultMessage=\\"Hello World!\\"/>);
}
}
",
"meta": Object {
"project": "foo",
},
"msgs": Array [
Object {
"defaultMessage": "foo",
"id": "rL0Y20zC+F",
},
Object {
"defaultMessage": "foo",
"id": "rL0Y20zC+F",
},
],
}
`;
exports[`emit asserts for ast 1`] = `
Object {
"code": "import React, { Component } from 'react';
Expand Down
20 changes: 20 additions & 0 deletions packages/ts-transformer/tests/fixtures/additionalFunctionNames.tsx
@@ -0,0 +1,20 @@
// @react-intl project:foo
import React, {Component} from 'react';

function CustomMessage() {}

export default class Foo extends Component {
render() {
return (
<CustomMessage
id={formatMessage({
defaultMessage: 'foo',
})}
description={$formatMessage({
defaultMessage: 'foo',
})}
defaultMessage="Hello World!"
/>
);
}
}
5 changes: 5 additions & 0 deletions packages/ts-transformer/tests/index.test.ts
Expand Up @@ -11,6 +11,11 @@ const FILES_TO_TESTS: Record<string, Partial<Opts>> = {
additionalComponentNames: ['CustomMessage'],
pragma: 'react-intl',
},
additionalFunctionNames: {
additionalFunctionNames: ['$formatMessage'],
pragma: 'react-intl',
extractFromFormatMessageCall: true,
},
defineMessages: {
pragma: 'react-intl',
},
Expand Down
4 changes: 4 additions & 0 deletions website/docs/tooling/ts-transformer.md
Expand Up @@ -176,6 +176,10 @@ Opt-in to extract from `intl.formatMessage` call with the same restrictions, e.g

Additional component names to extract messages from, e.g: `['FormattedFooBarMessage']`. **NOTE**: By default we check for the fact that `FormattedMessage` are imported from `moduleSourceName` to make sure variable alias works. This option does not do that so it's less safe.

### **`additionalFunctionNames`**

Additional function names to extract messages from, e.g: `['$formatMessage']`. Use this if you prefer to alias `formatMessage` to something shorter like `$t`.

### **`pragma`**

parse specific additional custom pragma. This allows you to tag certain file with metadata such as `project`. For example with this file:
Expand Down

0 comments on commit 96fc3b1

Please sign in to comment.