Repository: lingui/js-lingui
Pull request #585 (2019-11-08 01:20:51)

Fix issues with Flow type checking
Currently, `Flow` isn't actually checking any type imported from `core` due to its root-level `index.js` file missing a `@flow` header. Fixing this revealed a few more errors which I also included fixes for in this branch.

Not all tests are passing in this branch; however all failing tests also fail on `master`, so I'm just ignoring them for now.

now[bot]: 
This pull request is being automatically deployed with ZEIT Now ([learn more](https://zeit.co/docs/v2/integrations/now-for-github?utm_source=automated&utm_medium=github&utm_campaign=now_bot)).
To see the status of your deployment, click on the icon next to each commit.
	
now[bot]: 
Deployment failed with the following error:

~~~
Your `package.json` file is missing a `build` property inside the `script` property.
~~~
			

Patch:
diff --git a/README.md b/README.md
index 876fc1d8..7ff417fe 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
 
 <hr />
 
-[![CircleCI][Badge-CI]][CI] 
+[![CircleCI][Badge-CI]][CI]
 [![AppVeyor][Badge-AppVeyor]][AppVeyor]
 [![Code Coverage][Badge-Coverage]][Coverage]
 [![PRs Welcome][Badge-PRWelcome]][PRWelcome]
@@ -25,29 +25,29 @@ Lingui is an easy yet powerful internationalization framework for global project
 
 - **Clean and readable** - Keep your code clean and readable, while the library uses
   battle-tested and powerful **ICU MessageFormat** under the hood.
-  
+
 - **Universal** - Use it everywhere. `@lingui/core` provides the essential intl
   functionality which works in any JavaScript project while `@lingui/react` offers
   components to leverage React rendering.
 
 - **Full rich-text support** - Use React components inside localized messages
   without any limitation. Writing rich-text messages is as easy as writing JSX.
-  
+
 - **Powerful tooling** - Manage the whole intl workflow using Lingui [CLI][RefCLI]. It
   extracts messages from source code, validates messages coming from translators and
   checks that all messages are translated before shipping to production.
-  
+
 - **Unopinionated** - Integrate Lingui into your existing workflow. It supports
   message keys as well as auto generated messages. Translations are stored either in
   JSON or standard PO file, which is supported in almost all translation tools.
-  
+
 - **Lightweight and optimized** - Core library is only [1.9 kB gzipped][BundleCore],
   React components are additional [3.1 kBs gzipped][BundleReact]. That's less than Redux
   for a full-featured intl library.
-  
+
 - **Active community** - Join us on [Spectrum][Spectrum] to discuss the latest development.
   At the moment, Lingui is the most active intl project on GitHub.
-  
+
 - **Compatible with react-intl** - Low-level React API is very similar to react-intl
   and the message format is the same. It's easy to migrate an existing project.
 
@@ -98,8 +98,7 @@ For more example see the [React tutorial][TutorialReact].
 
 If you are having issues, please let us know.
 
-- Join us at [gitter.im][Gitter] to get almost instant
-  feedback.
+- Join us at [Gitter](https://gitter.im/lingui/js-lingui) to get almost instant feedback.
 - Ask question on [StackOverflow](https://stackoverflow.com/questions/ask?tags=jsLingui)
   and mark it with [Lingui](https://stackoverflow.com/questions/tagged/jslingui) tag.
 - If something doesn't work as documented, documentation is missing or if you just want
diff --git a/packages/cli/package.json b/packages/cli/package.json
index a1cadfd2..91946a01 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -58,14 +58,15 @@
     "ora": "^3.4.0",
     "pofile": "^1.0.11",
     "pseudolocale": "^1.1.0",
-    "ramda": "^0.26.1",
-    "typescript": "^2.9.2"
+    "ramda": "^0.26.1"
   },
   "devDependencies": {
-    "mockdate": "^2.0.2"
+    "mockdate": "^2.0.2",
+    "typescript": "^2.9.2"
   },
   "peerDependencies": {
     "babel-core": "6.x || ^7.0.0-bridge.0",
-    "babel-plugin-macros": "^2.4.2"
+    "babel-plugin-macros": "^2.4.2",
+    "typescript": "2 || 3"
   }
 }
diff --git a/packages/cli/src/lingui-compile.js b/packages/cli/src/lingui-compile.js
index 6a7a6cf5..9368ec84 100644
--- a/packages/cli/src/lingui-compile.js
+++ b/packages/cli/src/lingui-compile.js
@@ -65,7 +65,11 @@ function command(config, options) {
       }))
     )
 
-    if (!options.allowEmpty && config.sourceLocale !== locale) {
+    if (
+      !options.allowEmpty &&
+      config.sourceLocale !== locale &&
+      config.pseudoLocale !== locale
+    ) {
       const missing = R.keys(messages).filter(
         key => messages[key] === undefined
       )
diff --git a/packages/core/index.js b/packages/core/index.js
index 46e72b16..b1633e9f 100644
--- a/packages/core/index.js
+++ b/packages/core/index.js
@@ -1,1 +1,2 @@
+// @flow
 export * from "./src"
diff --git a/packages/react/src/I18nProvider.js b/packages/react/src/I18nProvider.js
index 4e85d224..ecec00b6 100644
--- a/packages/react/src/I18nProvider.js
+++ b/packages/react/src/I18nProvider.js
@@ -27,7 +27,7 @@ type LinguiPublisher = {|
 
   unsubscribe(callback: Function): void,
 
-  update(?{ catalogs?: Catalogs, language?: string, locales?: string }): void
+  update(?{ catalogs?: Catalogs, language?: string, locales?: Locales }): void
 |}
 
 /*
@@ -54,7 +54,11 @@ export function makeLinguiPublisher(i18n: I18n): LinguiPublisher {
     },
 
     update(
-      params: ?{ catalogs?: Catalogs, language?: string, locales?: string } = {}
+      params: ?{
+        catalogs?: Catalogs,
+        language?: string,
+        locales?: Locales
+      } = {}
     ) {
       if (!params) return
       const { catalogs, language, locales } = params
diff --git a/packages/react/src/Select.js b/packages/react/src/Select.js
index 733327eb..cb40b446 100644
--- a/packages/react/src/Select.js
+++ b/packages/react/src/Select.js
@@ -48,7 +48,6 @@ const Select = withI18n()(
 
 const PluralFactory = (ordinal = false) => {
   const displayName = !ordinal ? "Plural" : "SelectOrdinal"
-  const pluralType = !ordinal ? "plural" : "selectOrdinal"
 
   return class extends React.Component<*, PluralProps> {
     displayName = displayName
@@ -61,6 +60,7 @@ const PluralFactory = (ordinal = false) => {
 
     render() {
       const { className, render, i18n, value, offset, ...props } = this.props
+      const getPluralValue = !ordinal ? i18n.plural : i18n.selectOrdinal
 
       // i18n.selectOrdinal/plural uses numbers for exact matches (1, 2),
       // while SelectOrdinal/Plural has to use strings (_1, _2).
@@ -80,7 +80,7 @@ const PluralFactory = (ordinal = false) => {
         <Render
           className={className}
           render={render}
-          value={i18n[pluralType](pluralProps)}
+          value={getPluralValue(pluralProps)}
         />
       )
     }
diff --git a/packages/react/src/format.js b/packages/react/src/format.js
index 95f72101..1a2d9e77 100644
--- a/packages/react/src/format.js
+++ b/packages/react/src/format.js
@@ -2,7 +2,7 @@
 import { cloneElement } from "react"
 
 // match <0>paired</0> and <1/> unpaired tags
-const tagRe = /<(\d+)>(.*)<\/\1>|<(\d+)\/>/
+const tagRe = /<(\d+)>(.*?)<\/\1>|<(\d+)\/>/
 const nlRe = /(?:\r\n|\r|\n)/g
 
 /**


Test patch:
diff --git a/packages/react/src/I18nProvider.test.js b/packages/react/src/I18nProvider.test.js
index 1099cb7c..e9114190 100644
--- a/packages/react/src/I18nProvider.test.js
+++ b/packages/react/src/I18nProvider.test.js
@@ -165,14 +165,14 @@ describe("I18nPublisher", function() {
     })
     expect(linguiPublisher.i18n.language).toEqual("fr")
     expect(linguiPublisher.i18n.messages).toEqual({ msg: "salut!" })
-    expect(linguiPublisher.i18n.languageData.plurals()).toEqual("Function")
+    expect(typeof linguiPublisher.i18n.languageData.plurals).toEqual("function")
   })
 
   it("should subscribe/unsubscribe listeners for context changes", function() {
     const linguiPublisher = makeLinguiPublisher(
       setupI18n({
         language: "en",
-        catalogs: { en: {} }
+        catalogs: { en: { messages: {} } }
       })
     )
     const listener = jest.fn()
@@ -191,7 +191,7 @@ describe("I18nPublisher", function() {
     const linguiPublisher = makeLinguiPublisher(
       setupI18n({
         language: "en",
-        catalogs: { en: {}, fr: {} }
+        catalogs: { en: { messages: {} }, fr: { messages: {} } }
       })
     )
     linguiPublisher.subscribe(listener)
diff --git a/packages/react/src/Select.test.js b/packages/react/src/Select.test.js
index 1f90045d..dbae8c87 100644
--- a/packages/react/src/Select.test.js
+++ b/packages/react/src/Select.test.js
@@ -9,7 +9,7 @@ describe("Categories", function() {
     setupI18n({
       language: language,
       locales: locales,
-      catalogs: { [language]: {} }
+      catalogs: { [language]: { messages: {} } }
     })
   const languageContext = (language, locales) => ({
     context: { linguiPublisher: { i18n: i18n(language, locales) } }
diff --git a/packages/react/src/format.test.js b/packages/react/src/format.test.js
index 5d81a483..6b1d75f8 100644
--- a/packages/react/src/format.test.js
+++ b/packages/react/src/format.test.js
@@ -53,4 +53,16 @@ describe("formatElements", function() {
       )
     )
   })
+
+  it("should format multiple usages of same element in the same scope", function() {
+    expect(
+      html(
+        formatElements("<0>First</0> second <0>third</0> <0>fourth</0>", [
+          <sup />
+        ])
+      )
+    ).toEqual(
+      wrap("<sup>First</sup> second <sup>third</sup> <sup>fourth</sup>")
+    )
+  })
 })