Repository: lingui/js-lingui (ts)

Issue:
auto-generated message ID override id in V3 
**Describe the bug**
Auto-generated message ID overrides `id` property in the `Trans` component.  This component
` <Trans id="msg.hello">Hello World</Trans>` will transfformed to ` <Trans id="Hello World"></Trans>`.

**To Reproduce**

```
import { Trans } from "@lingui/react"

export default function App() {
   return <Trans id={"msg.hello"}>Hello World</Trans>
}
```

**Expected behavior**
The `id` should override the auto-generated message ID.

**Additional context**


- jsLingui version ``3.0.0-7``

.linguirc
```
{
  "catalogs": [
    {
      "path": "<rootDir>/translations/{locale}/messages",
      "include": [
        "<rootDir>"
      ],
      "exclude": [
        "*/node_modules/*"
      ]
    }
  ],
  "locales": [
    "de",
    "es"
  ],
  "format": "po"
}
```


Pull request:
Fixes maybeNodeValue
The JSX attributes contain expressions which contain literals. The current accessor is missing the expression dereference,

Fixes #604 

Patch:
diff --git a/docs/releases/migration-3.rst b/docs/releases/migration-3.rst
index e0f292c5..0a53645a 100644
--- a/docs/releases/migration-3.rst
+++ b/docs/releases/migration-3.rst
@@ -115,7 +115,7 @@ for a single locale or multiple catalogs at once.
      import catalogEn from './locale/en/messages.js'
 
    - i18n.load({ en: catalogEn })
-   + i18n.load('en', catalogEn)
+   + i18n.load('en', catalogEn.messages)
 
 .. note::
 
@@ -129,8 +129,8 @@ for a single locale or multiple catalogs at once.
       import catalogFr from './locale/fr/messages.js'
 
       i18n.load({
-         en: catalogEn
-         fr: catalogFr
+         en: catalogEn.messages,
+         fr: catalogFr.messages
       })
 
 @lingui/macro
diff --git a/packages/macro/src/macroJsx.ts b/packages/macro/src/macroJsx.ts
index bb24904f..59549ab5 100644
--- a/packages/macro/src/macroJsx.ts
+++ b/packages/macro/src/macroJsx.ts
@@ -15,6 +15,20 @@ const keepSpaceRe = /\s*(?:\r\n|\r|\n)+\s*/g
 // remove whitespace before/after tag or expression
 const stripAroundTagsRe = /(?:([>}])(?:\r\n|\r|\n)+\s*|(?:\r\n|\r|\n)+\s*(?=[<{]))/g
 
+function maybeNodeValue(node) {
+  if (!node)
+    return null
+  if (node.type === "StringLiteral")
+    return node.value
+  if (node.type === "JSXAttribute")
+    return maybeNodeValue(node.value)
+  if (node.type === "JSXExpressionContainer")
+    return maybeNodeValue(node.expression)
+  if (node.type === "TemplateLiteral" && node.expressions.length === 0)
+    return node.quasis[0].value.raw
+  return null
+}
+
 function normalizeWhitespace(text) {
   return (
     text
@@ -173,8 +187,6 @@ export default class MacroJSX {
       ]
     }
 
-    const maybeNodeValue = (node) => (node != null ? node.value.value : null)
-
     return {
       id: maybeNodeValue(id),
       message: maybeNodeValue(message),


Test patch:
diff --git a/packages/macro/test/jsx-trans.ts b/packages/macro/test/jsx-trans.ts
index 2791447f..ed96062c 100644
--- a/packages/macro/test/jsx-trans.ts
+++ b/packages/macro/test/jsx-trans.ts
@@ -15,14 +15,14 @@ export default [
     input: `
         import { Trans } from '@lingui/macro';
         <Trans id="Hello World">Hello World</Trans>;
-          `,
+      `,
     expected: `
         import { Trans } from "@lingui/react";
         <Trans id="Hello World" />;
       `,
   },
   {
-    name: "Macro with custom ID",
+    name: "Macro with custom ID (string literal)",
     input: `
         import { Trans } from '@lingui/macro';
         <Trans id="msg.hello">Hello World</Trans>;
@@ -32,6 +32,28 @@ export default [
         <Trans id="msg.hello" message="Hello World" />;
       `,
   },
+  {
+    name: "Macro with custom ID (literal expression)",
+    input: `
+        import { Trans } from '@lingui/macro';
+        <Trans id={"msg.hello"}>Hello World</Trans>;
+      `,
+    expected: `
+        import { Trans } from "@lingui/react";
+        <Trans id="msg.hello" message="Hello World" />;
+      `,
+  },
+  {
+    name: "Macro with custom ID (template expression)",
+    input: `
+        import { Trans } from '@lingui/macro';
+        <Trans id={\`msg.hello\`}>Hello World</Trans>;
+      `,
+    expected: `
+        import { Trans } from "@lingui/react";
+        <Trans id="msg.hello" message="Hello World" />;
+      `,
+  },
   {
     name: "Macro without children is noop",
     input: `