Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: allow extract to work with i18n._ calls not created from macro #1309

Merged
merged 1 commit into from
Dec 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 40 additions & 24 deletions packages/babel-plugin-extract-messages/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,28 @@ function extractStringContatentation(t, node, error): string {
}
}

function extractCommentString(t, path, valuePath, valueObj): string {
if (t.isStringLiteral(valueObj)) {
// Comment is a single line string
return valueObj.value;
}

// Comment is a multi-line string.
const errorIfNotAString = path
.get(valuePath)
.buildCodeFrameError("Only strings are supported as comments.")

if (t.isBinaryExpression(valueObj)) {
return extractStringContatentation(
t,
valueObj,
errorIfNotAString
)
} else {
throw errorIfNotAString
}
}

export default function ({ types: t }) {
let localTransComponentName

Expand Down Expand Up @@ -220,25 +242,32 @@ export default function ({ types: t }) {
)
}
)
if (!hasComment) return


const isNonMacroI18n = isI18nMethod(path.node.callee) && !hasComment && path.node.arguments[0] && !path.node.arguments[0].leadingComments;
if (!hasComment && !isNonMacroI18n) return;
const props = {
id: path.node.arguments[0].value,
}
id: path.node.arguments[0].value
};

if (!props.id) {
console.warn("Missing message ID, skipping.")
console.warn("Missing message ID, skipping.");
console.warn(generate(path.node).code)
return
return;
}

const copyOptions = ["message", "comment", "context"]

if (t.isObjectExpression(path.node.arguments[2])) {
path.node.arguments[2].properties.forEach((property) => {
if (!copyOptions.includes(property.key.name)) return
path.node.arguments[2].properties.forEach(({key, value}, i) => {
if (!copyOptions.includes(key.name)) return

let valueToExtract = value.value;

if (key.name === "comment") {
valueToExtract = extractCommentString(t, path, `arguments.2.properties.${i}.value`, value);
}

props[property.key.name] = property.value.value
props[key.name] = valueToExtract
})
}

Expand Down Expand Up @@ -298,21 +327,8 @@ export default function ({ types: t }) {
// By default, the value is just the string value of the object property.
let valueToExtract = value.value;

if (key.name === "comment" && !t.isStringLiteral(value)) {
// Comments can be single or multi-line strings.
const errorIfNotAString = path
.get(`properties.${i}.value`)
.buildCodeFrameError("Only strings are supported as comments.")

if (t.isBinaryExpression(value)) {
valueToExtract = extractStringContatentation(
t,
value,
errorIfNotAString
)
} else {
throw errorIfNotAString
}
if (key.name === "comment") {
valueToExtract = extractCommentString(t, path, `properties.${i}.value`, value);
} else if (key.name === "id") {
const isIdLiteral = !value.value && t.isTemplateLiteral(value)
if (isIdLiteral) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,72 @@ Object {
}
`;

exports[`@lingui/babel-plugin-extract-messages should extract all messages from JS files (without macros or i18n comments) 1`] = `
Object {
Context1: Object {
Some id: Object {
extractedComments: Array [],
origin: Array [
Array [
js-without-macros-or-comments.js,
11,
],
],
},
},
Description: Object {
extractedComments: Array [
description,
],
origin: Array [
Array [
js-without-macros-or-comments.js,
3,
],
],
},
ID: Object {
extractedComments: Array [],
message: Message with id,
origin: Array [
Array [
js-without-macros-or-comments.js,
7,
],
],
},
Message: Object {
extractedComments: Array [],
origin: Array [
Array [
js-without-macros-or-comments.js,
1,
],
],
},
Multiline: Object {
extractedComments: Array [
this is 2 lines long,
],
origin: Array [
Array [
js-without-macros-or-comments.js,
5,
],
],
},
Values {param}: Object {
extractedComments: Array [],
origin: Array [
Array [
js-without-macros-or-comments.js,
9,
],
],
},
}
`;

exports[`@lingui/babel-plugin-extract-messages should extract all messages from JS files 1`] = `
Object {
Context1: Object {
Expand Down Expand Up @@ -321,3 +387,30 @@ Object {
},
}
`;

exports[`@lingui/babel-plugin-extract-messages should handle duplicate ids 1`] = `
Object {
msg: Object {
extractedComments: Array [],
message: Hello World!,
origin: Array [
Array [
duplicate-id-valid.js,
5,
],
Array [
duplicate-id-valid.js,
8,
],
Array [
duplicate-id-valid.js,
11,
],
Array [
duplicate-id-valid.js,
14,
],
],
},
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
const msg = i18n._('Message')

const withDescription = i18n._('Description', {}, { comment: "description"});

const withMultilineComment = i18n._('Multiline', {}, { comment: "this is " + "2 lines long" });

const withId = i18n._('ID', {}, { message: 'Message with id' });

const withValues = i18n._('Values {param}', { param: param });

const withContext = i18n._('Some id', {},{ context: 'Context1'});
10 changes: 10 additions & 0 deletions packages/babel-plugin-extract-messages/test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ describe("@lingui/babel-plugin-extract-messages", function () {
).toBeFalsy()
})

testCase(
"should handle duplicate ids",
"duplicate-id-valid.js"
)

testCase(
"should extract all messages from JSX files",
"jsx-without-macros.js"
Expand All @@ -134,4 +139,9 @@ describe("@lingui/babel-plugin-extract-messages", function () {
"should extract all messages from JS files (macros)",
"js-with-macros.js"
)

testCase(
"should extract all messages from JS files (without macros or i18n comments)",
"js-without-macros-or-comments.js"
)
})