Repository: lingui/js-lingui
Pull request #1165 (2021-11-11 21:57:08)

fix: Allow pseudoLocalize to work in @lingui/loader
@lingui/loader uses strict mode when it's not running in production.  This is turn means that `compileSingleKey` always gets passed an empty string as `translation` for the pseudo locale to translate.  This seems to defeat the purpose of using pseudo localization.

With this change, you can use @lingui/loader and also get dynamically generated pseudo locale string.

vercel[bot]: This pull request is being automatically deployed with Vercel ([learn more](https://vercel.link/github-learn-more)).  
To see the status of your deployment, click below or on the icon next to each commit.

🔍 Inspect: [https://vercel.com/lingui-js/js-lingui/EGPTtzbm62HZLUyUmDYyXiwHupYG](https://vercel.com/lingui-js/js-lingui/EGPTtzbm62HZLUyUmDYyXiwHupYG)  
✅ Preview: *In Progress*



Patch:
diff --git a/docs/misc/react-intl.rst b/docs/misc/react-intl.rst
index 153a9cfd..35f7fd84 100644
--- a/docs/misc/react-intl.rst
+++ b/docs/misc/react-intl.rst
@@ -126,7 +126,7 @@ Let's compare it with `react-intl`_ solution to see the difference:
          <Trans>Read the <a href="/docs">documentation</a>.</Trans>
       </p>
 
-   The message ID is ``Read the <0>documentation</0>.`` instead of ``msg.id``. Both
+   The message ID is ``Read the <0>documentation</0>.`` instead of ``msg.docs``. Both
    solutions have pros and cons and the library lets you choose the one which works best for you.
 
 Plurals
diff --git a/packages/babel-plugin-extract-messages/src/index.ts b/packages/babel-plugin-extract-messages/src/index.ts
index 4ebfb2fb..91d9f6a1 100644
--- a/packages/babel-plugin-extract-messages/src/index.ts
+++ b/packages/babel-plugin-extract-messages/src/index.ts
@@ -96,6 +96,19 @@ function mapReplacer(key, value) {
   return value;
 }
 
+function extractStringContatentation(t, node, error): string {
+  if (t.isStringLiteral(node)) {
+    return node.value
+  } else if (t.isBinaryExpression(node)) {
+    return (
+      extractStringContatentation(t, node.left, error) +
+      extractStringContatentation(t, node.right, error)
+    )
+  } else {
+    throw error
+  }
+}
+
 export default function ({ types: t }) {
   let localTransComponentName
 
@@ -282,13 +295,31 @@ export default function ({ types: t }) {
         path.node.properties
           .filter(({ key }) => copyProps.indexOf(key.name) !== -1)
           .forEach(({ key, value }, i) => {
+            // By default, the value is just the string value of the object property.
+            let valueToExtract = value.value;
+
             if (key.name === "comment" && !t.isStringLiteral(value)) {
-              throw path
+              // 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
+              }
+            } else if (key.name === "id") {
+                const isIdLiteral = !value.value && t.isTemplateLiteral(value)
+                if (isIdLiteral) {
+                    valueToExtract = value?.quasis[0]?.value?.cooked;
+                }
             }
-            const isIdLiteral = !value.value && key.name === "id" && t.isTemplateLiteral(value)
-            props[key.name] = isIdLiteral ? value?.quasis[0]?.value?.cooked : value.value
+            props[key.name] = valueToExtract;
           })
 
         collectMessage(path, file, props)
diff --git a/packages/cli/src/api/compile.ts b/packages/cli/src/api/compile.ts
index 297a6434..0ebd8add 100644
--- a/packages/cli/src/api/compile.ts
+++ b/packages/cli/src/api/compile.ts
@@ -27,7 +27,7 @@ export type CreateCompileCatalogOptions = {
  */
 function compileSingleKey(key: string, translation: string, shouldPseudolocalize: boolean): t.ObjectProperty {
   if (shouldPseudolocalize) {
-    translation = pseudoLocalize(translation)
+    translation = pseudoLocalize(key)
   }
 
   return t.objectProperty(t.stringLiteral(key), compile(translation))
diff --git a/packages/cli/src/services/translationIO.ts b/packages/cli/src/services/translationIO.ts
index 07c391c3..3fca19c2 100644
--- a/packages/cli/src/services/translationIO.ts
+++ b/packages/cli/src/services/translationIO.ts
@@ -43,7 +43,8 @@ export default function syncProcess(config, options) {
 // Cf. https://translation.io/docs/create-library#initialization
 function init(config, options, successCallback, failCallback) {
   const sourceLocale  = config.sourceLocale || 'en'
-  const targetLocales = config.locales.filter((value) => value != sourceLocale)
+  const pseudoLocale  = config.pseudoLocale || 'pseudo'
+  const targetLocales = config.locales.filter((value) => value != sourceLocale && value != pseudoLocale)
   const paths         = poPathsPerLocale(config)
 
   let segments = {}


Test patch:
diff --git a/packages/babel-plugin-extract-messages/test/__snapshots__/index.ts.snap b/packages/babel-plugin-extract-messages/test/__snapshots__/index.ts.snap
index b77949ae..bbb46d84 100644
--- a/packages/babel-plugin-extract-messages/test/__snapshots__/index.ts.snap
+++ b/packages/babel-plugin-extract-messages/test/__snapshots__/index.ts.snap
@@ -131,7 +131,7 @@ Object {
       origin: Array [
         Array [
           js-without-macros.js,
-          11,
+          13,
         ],
       ],
     },
@@ -153,7 +153,7 @@ Object {
     origin: Array [
       Array [
         js-without-macros.js,
-        7,
+        9,
       ],
     ],
   },
@@ -166,12 +166,23 @@ Object {
       ],
     ],
   },
+  Multiline: Object {
+    extractedComments: Array [
+      this is 2 lines long,
+    ],
+    origin: Array [
+      Array [
+        js-without-macros.js,
+        7,
+      ],
+    ],
+  },
   Values {param}: Object {
     extractedComments: Array [],
     origin: Array [
       Array [
         js-without-macros.js,
-        9,
+        11,
       ],
     ],
   },
diff --git a/packages/babel-plugin-extract-messages/test/fixtures/js-without-macros.js b/packages/babel-plugin-extract-messages/test/fixtures/js-without-macros.js
index 832361b9..c98941ba 100644
--- a/packages/babel-plugin-extract-messages/test/fixtures/js-without-macros.js
+++ b/packages/babel-plugin-extract-messages/test/fixtures/js-without-macros.js
@@ -4,6 +4,8 @@ const msg = /*i18n*/{id: 'Message'}
 
 const withDescription = /*i18n*/{id: 'Description', comment: "description"}
 
+const withMultilineComment = /*i18n*/{id: 'Multiline', comment: "this is " + "2 lines long"}
+
 const withId = /*i18n*/{id: 'ID', message: 'Message with id'}
 
 const withValues = /*i18n*/{id: 'Values {param}', values: { param: param }}