diff --git a/packages/babel-plugin-lingui-macro/src/index.ts b/packages/babel-plugin-lingui-macro/src/index.ts index a6d9e7560..450814e1d 100644 --- a/packages/babel-plugin-lingui-macro/src/index.ts +++ b/packages/babel-plugin-lingui-macro/src/index.ts @@ -20,6 +20,7 @@ let config: LinguiConfigNormalized export type LinguiPluginOpts = { // explicitly set by CLI when running extraction process extract?: boolean + stripMessageField?: boolean linguiConfig?: LinguiConfigNormalized } @@ -46,6 +47,19 @@ function reportUnsupportedSyntax(path: NodePath, e: Error) { throw codeFrameError } +function shouldStripMessageProp(opts: LinguiPluginOpts) { + if (opts.extract) { + // never strip message during extraction process + return false + } + if (typeof opts.stripMessageField === "boolean") { + // if explicitly set in options, use it + return opts.stripMessageField + } + // default to strip message in production if no explicit option is set + return process.env.NODE_ENV === "production" +} + type LinguiSymbol = "Trans" | "useLingui" | "i18n" const getIdentifierPath = ((path: NodePath, node: Identifier) => { @@ -186,6 +200,9 @@ export default function ({ stripNonEssentialProps: process.env.NODE_ENV == "production" && !(state.opts as LinguiPluginOpts).extract, + stripMessageProp: shouldStripMessageProp( + state.opts as LinguiPluginOpts + ), } ) @@ -214,6 +231,9 @@ export default function ({ stripNonEssentialProps: process.env.NODE_ENV == "production" && !(state.opts as LinguiPluginOpts).extract, + stripMessageProp: shouldStripMessageProp( + state.opts as LinguiPluginOpts + ), i18nImportName: getSymbolIdentifier(state, "i18n").name, useLinguiImportName: getSymbolIdentifier(state, "useLingui") .name, diff --git a/packages/babel-plugin-lingui-macro/src/macroJs.ts b/packages/babel-plugin-lingui-macro/src/macroJs.ts index a114c277e..3d35d9842 100644 --- a/packages/babel-plugin-lingui-macro/src/macroJs.ts +++ b/packages/babel-plugin-lingui-macro/src/macroJs.ts @@ -27,6 +27,7 @@ export type MacroJsOpts = { useLinguiImportName: string stripNonEssentialProps: boolean + stripMessageProp: boolean isLinguiIdentifier: (node: Identifier, macro: JsMacroName) => boolean } @@ -46,7 +47,8 @@ export class MacroJs { this._ctx = createMacroJsContext( opts.isLinguiIdentifier, - opts.stripNonEssentialProps + opts.stripNonEssentialProps, + opts.stripMessageProp ) } @@ -59,7 +61,8 @@ export class MacroJs { createMessageDescriptorFromTokens( tokens, path.node.loc, - this._ctx.stripNonEssentialProps + this._ctx.stripNonEssentialProps, + this._ctx.stripMessageProp ), linguiInstance ) @@ -89,7 +92,8 @@ export class MacroJs { return createMessageDescriptorFromTokens( tokens, path.node.loc, - ctx.stripNonEssentialProps + ctx.stripNonEssentialProps, + ctx.stripMessageProp ) } @@ -260,7 +264,8 @@ export class MacroJs { const descriptor = createMessageDescriptorFromTokens( tokens, currentPath.node.loc, - ctx.stripNonEssentialProps + ctx.stripNonEssentialProps, + ctx.stripMessageProp ) const callExpr = t.callExpression( diff --git a/packages/babel-plugin-lingui-macro/src/macroJsAst.test.ts b/packages/babel-plugin-lingui-macro/src/macroJsAst.test.ts index 4e00d5962..3bf9464ab 100644 --- a/packages/babel-plugin-lingui-macro/src/macroJsAst.test.ts +++ b/packages/babel-plugin-lingui-macro/src/macroJsAst.test.ts @@ -35,9 +35,13 @@ const parseExpression = (expression: string) => { } function createMacroCtx() { - return createMacroJsContext((identifier, macro) => { - return identifier.name === macro - }, false) + return createMacroJsContext( + (identifier, macro) => { + return identifier.name === macro + }, + false, // stripNonEssentialProps + false // stripMessageProp + ) } describe("js macro", () => { diff --git a/packages/babel-plugin-lingui-macro/src/macroJsAst.ts b/packages/babel-plugin-lingui-macro/src/macroJsAst.ts index 51ca1bfad..8c7e942cc 100644 --- a/packages/babel-plugin-lingui-macro/src/macroJsAst.ts +++ b/packages/babel-plugin-lingui-macro/src/macroJsAst.ts @@ -18,17 +18,20 @@ export type MacroJsContext = { // Positional expressions counter (e.g. for placeholders `Hello {0}, today is {1}`) getExpressionIndex: () => number stripNonEssentialProps: boolean + stripMessageProp: boolean isLinguiIdentifier: (node: Identifier, macro: JsMacroName) => boolean } export function createMacroJsContext( isLinguiIdentifier: MacroJsContext["isLinguiIdentifier"], - stripNonEssentialProps: boolean + stripNonEssentialProps: boolean, + stripMessageProp: boolean ): MacroJsContext { return { getExpressionIndex: makeCounter(), isLinguiIdentifier, stripNonEssentialProps, + stripMessageProp, } } @@ -85,6 +88,7 @@ export function processDescriptor( tokens, descriptor.loc, ctx.stripNonEssentialProps, + ctx.stripMessageProp, { id: idProperty, context: contextProperty, diff --git a/packages/babel-plugin-lingui-macro/src/macroJsx.test.ts b/packages/babel-plugin-lingui-macro/src/macroJsx.test.ts index a7bbf58da..b16b2b560 100644 --- a/packages/babel-plugin-lingui-macro/src/macroJsx.test.ts +++ b/packages/babel-plugin-lingui-macro/src/macroJsx.test.ts @@ -33,7 +33,11 @@ const parseExpression = (expression: string) => { function createMacro() { return new MacroJSX( { types }, - { stripNonEssentialProps: false, transImportName: "Trans" } + { + stripNonEssentialProps: false, + stripMessageProp: false, + transImportName: "Trans", + } ) } diff --git a/packages/babel-plugin-lingui-macro/src/macroJsx.ts b/packages/babel-plugin-lingui-macro/src/macroJsx.ts index cc8ae2e1f..a867bac01 100644 --- a/packages/babel-plugin-lingui-macro/src/macroJsx.ts +++ b/packages/babel-plugin-lingui-macro/src/macroJsx.ts @@ -45,6 +45,7 @@ function maybeNodeValue(node: Node): { text: string; loc: SourceLocation } { export type MacroJsxOpts = { stripNonEssentialProps: boolean + stripMessageProp: boolean transImportName: string } @@ -53,11 +54,13 @@ export class MacroJSX { expressionIndex = makeCounter() elementIndex = makeCounter() stripNonEssentialProps: boolean + stripMessageProp: boolean transImportName: string constructor({ types }: { types: typeof babelTypes }, opts: MacroJsxOpts) { this.types = types this.stripNonEssentialProps = opts.stripNonEssentialProps + this.stripMessageProp = opts.stripMessageProp this.transImportName = opts.transImportName } @@ -84,6 +87,7 @@ export class MacroJSX { tokens, path.node.loc, this.stripNonEssentialProps, + this.stripMessageProp, { id, context, diff --git a/packages/babel-plugin-lingui-macro/src/messageDescriptorUtils.ts b/packages/babel-plugin-lingui-macro/src/messageDescriptorUtils.ts index c85936fb2..165c0032f 100644 --- a/packages/babel-plugin-lingui-macro/src/messageDescriptorUtils.ts +++ b/packages/babel-plugin-lingui-macro/src/messageDescriptorUtils.ts @@ -29,6 +29,7 @@ export function createMessageDescriptorFromTokens( tokens: Tokens, oldLoc: SourceLocation, stripNonEssentialProps: boolean, + stripMessageProp: boolean, defaults: { id?: TextWithLoc | ObjectProperty context?: TextWithLoc | ObjectProperty @@ -39,6 +40,7 @@ export function createMessageDescriptorFromTokens( buildICUFromTokens(tokens), oldLoc, stripNonEssentialProps, + stripMessageProp, defaults ) } @@ -47,6 +49,7 @@ export function createMessageDescriptor( result: Partial, oldLoc: SourceLocation, stripNonEssentialProps: boolean, + stripMessageProp: boolean, defaults: { id?: TextWithLoc | ObjectProperty context?: TextWithLoc | ObjectProperty @@ -76,13 +79,15 @@ export function createMessageDescriptor( ) ) - if (!stripNonEssentialProps) { + if (!stripMessageProp) { if (message) { properties.push( createStringObjectProperty(MsgDescriptorPropKey.message, message) ) } + } + if (!stripNonEssentialProps) { if (defaults.comment) { properties.push( isObjectProperty(defaults.comment) diff --git a/packages/babel-plugin-lingui-macro/test/__snapshots__/js-t.test.ts.snap b/packages/babel-plugin-lingui-macro/test/__snapshots__/js-t.test.ts.snap index ee22a3056..f1db6876c 100644 --- a/packages/babel-plugin-lingui-macro/test/__snapshots__/js-t.test.ts.snap +++ b/packages/babel-plugin-lingui-macro/test/__snapshots__/js-t.test.ts.snap @@ -156,6 +156,31 @@ const msg = _i18n._( `; +exports[`Production - message prop is kept if stripMessageField: false 1`] = ` +import { t } from "@lingui/macro"; +const msg = t({ + message: \`Hello \${name}\`, + id: "msgId", + comment: "description for translators", + context: "My Context", +}); + +↓ ↓ ↓ ↓ ↓ ↓ + +import { i18n as _i18n } from "@lingui/core"; +const msg = _i18n._( + /*i18n*/ + { + id: "msgId", + message: "Hello {name}", + values: { + name: name, + }, + } +); + +`; + exports[`Production - only essential props are kept 1`] = ` import { t } from "@lingui/core/macro"; const msg = t\`Message\`; @@ -570,6 +595,39 @@ const msg = _i18n._(); `; +exports[`stripMessageField option - Message prop is kept during extraction process if extract: true and stripMessageField: true 1`] = ` +import { t } from "@lingui/macro"; +const msg = t\`Message\`; + +↓ ↓ ↓ ↓ ↓ ↓ + +import { i18n as _i18n } from "@lingui/core"; +const msg = _i18n._( + /*i18n*/ + { + id: "xDAtGP", + message: "Message", + } +); + +`; + +exports[`stripMessageField option - message prop is removed if stripMessageField: true 1`] = ` +import { t } from "@lingui/macro"; +const msg = t\`Message\`; + +↓ ↓ ↓ ↓ ↓ ↓ + +import { i18n as _i18n } from "@lingui/core"; +const msg = _i18n._( + /*i18n*/ + { + id: "xDAtGP", + } +); + +`; + exports[`t\`\` macro could be renamed 1`] = ` import { t as t2 } from "@lingui/core/macro"; const a = t2\`Expression assignment\`; diff --git a/packages/babel-plugin-lingui-macro/test/__snapshots__/jsx-trans.test.ts.snap b/packages/babel-plugin-lingui-macro/test/__snapshots__/jsx-trans.test.ts.snap index 8edb94936..f6b6e9b4d 100644 --- a/packages/babel-plugin-lingui-macro/test/__snapshots__/jsx-trans.test.ts.snap +++ b/packages/babel-plugin-lingui-macro/test/__snapshots__/jsx-trans.test.ts.snap @@ -411,6 +411,27 @@ import { Trans as _Trans } from "@lingui/react"; `; +exports[`Production - message prop is kept if stripMessageField: false 1`] = ` +import { Trans } from "@lingui/macro"; + + Hello World +; + +↓ ↓ ↓ ↓ ↓ ↓ + +import { Trans as _Trans } from "@lingui/react"; +<_Trans + { + /*i18n*/ + ...{ + id: "msg.hello", + message: "Hello World", + } + } +/>; + +`; + exports[`Production - only essential props are kept 1`] = ` import { Trans } from "@lingui/react/macro"; @@ -791,3 +812,40 @@ import { Trans as _Trans } from "@lingui/react"; />; `; + +exports[`stripMessageField option - Message prop is kept during extraction process if extract: true and stripMessageField: true 1`] = ` +import { Trans } from "@lingui/macro"; +Hello World; + +↓ ↓ ↓ ↓ ↓ ↓ + +import { Trans as _Trans } from "@lingui/react"; +<_Trans + { + /*i18n*/ + ...{ + id: "msg.hello", + message: "Hello World", + } + } +/>; + +`; + +exports[`stripMessageField option - message prop is removed if stripMessageField: true 1`] = ` +import { Trans } from "@lingui/macro"; +Hello World; + +↓ ↓ ↓ ↓ ↓ ↓ + +import { Trans as _Trans } from "@lingui/react"; +<_Trans + { + /*i18n*/ + ...{ + id: "msg.hello", + } + } +/>; + +`; diff --git a/packages/babel-plugin-lingui-macro/test/js-t.test.ts b/packages/babel-plugin-lingui-macro/test/js-t.test.ts index b11afc7cc..ed2e0796e 100644 --- a/packages/babel-plugin-lingui-macro/test/js-t.test.ts +++ b/packages/babel-plugin-lingui-macro/test/js-t.test.ts @@ -156,6 +156,27 @@ macroTester({ const msg = t() `, }, + { + name: "stripMessageField option - message prop is removed if stripMessageField: true", + macroOpts: { + stripMessageField: true, + }, + code: ` + import { t } from '@lingui/macro' + const msg = t\`Message\` + `, + }, + { + name: "stripMessageField option - Message prop is kept during extraction process if extract: true and stripMessageField: true", + macroOpts: { + extract: true, + stripMessageField: true, + }, + code: ` + import { t } from '@lingui/macro' + const msg = t\`Message\` + `, + }, { name: "Production - only essential props are kept", production: true, @@ -204,6 +225,22 @@ macroTester({ }) `, }, + { + name: "Production - message prop is kept if stripMessageField: false", + production: true, + macroOpts: { + stripMessageField: false, + }, + code: ` + import { t } from '@lingui/macro'; + const msg = t({ + message: \`Hello $\{name\}\`, + id: 'msgId', + comment: 'description for translators', + context: 'My Context', + }) + `, + }, { name: "Production - all props kept if extract: true", production: true, diff --git a/packages/babel-plugin-lingui-macro/test/jsx-trans.test.ts b/packages/babel-plugin-lingui-macro/test/jsx-trans.test.ts index a7289481b..8fcb5d783 100644 --- a/packages/babel-plugin-lingui-macro/test/jsx-trans.test.ts +++ b/packages/babel-plugin-lingui-macro/test/jsx-trans.test.ts @@ -163,6 +163,27 @@ macroTester({ {
}
; `, }, + { + name: "stripMessageField option - message prop is removed if stripMessageField: true", + macroOpts: { + stripMessageField: true, + }, + code: ` + import { Trans } from '@lingui/macro'; + Hello World + `, + }, + { + name: "stripMessageField option - Message prop is kept during extraction process if extract: true and stripMessageField: true", + macroOpts: { + extract: true, + stripMessageField: true, + }, + code: ` + import { Trans } from '@lingui/macro'; + Hello World + `, + }, { name: "Production - only essential props are kept", production: true, @@ -171,6 +192,17 @@ macroTester({ Hello World `, }, + { + name: "Production - message prop is kept if stripMessageField: false", + production: true, + macroOpts: { + stripMessageField: false, + }, + code: ` + import { Trans } from '@lingui/macro'; + Hello World + `, + }, { name: "Production - all props kept if extract: true", production: true,