diff --git a/packages/core/src/i18n.test.ts b/packages/core/src/i18n.test.ts index 5deccfe63..21beca361 100644 --- a/packages/core/src/i18n.test.ts +++ b/packages/core/src/i18n.test.ts @@ -189,7 +189,6 @@ describe("I18n", () => { it("._ should format message from catalog", () => { const messages = { Hello: "Salut", - "My name is {name}": "Je m'appelle {name}", } const i18n = setupI18n({ @@ -198,15 +197,24 @@ describe("I18n", () => { }) expect(i18n._("Hello")).toEqual("Salut") - expect(i18n._("My name is {name}", { name: "Fred" })).toEqual( - "Je m'appelle Fred" - ) + expect( + i18n._({ + id: "My name is {name}", + message: "Je m'appelle {name}", + values: { name: "Fred" }, + }) + ).toEqual("Je m'appelle Fred") // alias expect(i18n.t("Hello")).toEqual("Salut") // missing { name } - expect(i18n._("My name is {name}")).toEqual("Je m'appelle") + expect( + i18n._({ + id: "My name is {name}", + message: "Je m'appelle {name}", + }) + ).toEqual("Je m'appelle") // Untranslated message expect(i18n._("Missing message")).toEqual("Missing message") @@ -239,16 +247,19 @@ describe("I18n", () => { }) it("._ allow escaping syntax characters", () => { - const messages = { - "My ''name'' is '{name}'": "Mi ''nombre'' es '{name}'", - } + const messages = {} const i18n = setupI18n({ locale: "es", messages: { es: messages }, }) - expect(i18n._("My ''name'' is '{name}'")).toEqual("Mi 'nombre' es {name}") + expect( + i18n._({ + id: "My ''name'' is '{name}'", + message: "Mi ''nombre'' es '{name}'", + }) + ).toEqual("Mi 'nombre' es {name}") }) it("._ shouldn't compile messages in production", () => { @@ -270,6 +281,23 @@ describe("I18n", () => { }) }) + it("._ shouldn't compiled message from catalogs in development", () => { + const messages = { + Hello: "Salut", + "My name is {name}": "Je m'appelle {name}", + } + + mockEnv("development", () => { + const { setupI18n } = require("@lingui/core") + const i18n = setupI18n({ + locale: "fr", + messages: { fr: messages }, + }) + + expect(i18n._("My name is {name}")).toEqual("Je m'appelle {name}") + }) + }) + it("._ should emit missing event for missing translation", () => { const i18n = setupI18n({ locale: "en", diff --git a/packages/core/src/i18n.ts b/packages/core/src/i18n.ts index 55250958f..38b0acf42 100644 --- a/packages/core/src/i18n.ts +++ b/packages/core/src/i18n.ts @@ -232,13 +232,16 @@ export class I18n extends EventEmitter { this.emit("missing", { id, locale: this._locale }) } - let translation = messageForId || message || id - - if (process.env.NODE_ENV !== "production") { - translation = isString(translation) - ? compileMessage(translation) - : translation - } + // To avoid double compilation, skip compilation for `messageForId`, because message from catalog should be already compiled + // ref: https://github.com/lingui/js-lingui/issues/1901 + const translation = + messageForId || + (() => { + const trans: CompiledMessage | string = message || id + return process.env.NODE_ENV !== "production" + ? compileMessage(trans) + : trans + })() // hack for parsing unicode values inside a string to get parsed in react native environments if (isString(translation) && UNICODE_REGEX.test(translation)) diff --git a/packages/react/src/Trans.test.tsx b/packages/react/src/Trans.test.tsx index a7830a737..0157e844c 100644 --- a/packages/react/src/Trans.test.tsx +++ b/packages/react/src/Trans.test.tsx @@ -24,7 +24,6 @@ describe("Trans component", () => { "My name is {name}": "Jmenuji se {name}", Original: "Původní", Updated: "Aktualizovaný", - "msg.currency": "{value, number, currency}", ID: "Translation", }, }, @@ -290,6 +289,7 @@ describe("Trans component", () => { const translation = text(