Repository: ember-intl/ember-intl
Pull request #1291 (2020-05-07 01:19:40)

Fix "occurred" typo in error message
`occured` -> `occurred`


Patch:
diff --git a/lib/broccoli/translation-reducer/linter/extract-icu-arguments.js b/lib/broccoli/translation-reducer/linter/extract-icu-arguments.js
index afa70c56..90972fb3 100644
--- a/lib/broccoli/translation-reducer/linter/extract-icu-arguments.js
+++ b/lib/broccoli/translation-reducer/linter/extract-icu-arguments.js
@@ -1,22 +1,24 @@
 const parser = require('intl-messageformat-parser');
+const traverse = require('../../../message-validator/ast-traverse');
 
 function extractICUArguments(string) {
   try {
+    const args = new Set();
+    const recordVisitedNodeValue = (node) => args.add(node.value);
+
     // Errors thrown by the parser won't include any details about the string. By rethrowing the
     // error with the string quoted it's much easier to identify which ICU argument was invalid.
-    return parser
-      .parse(string)
-      .filter(
-        (element) =>
-          parser.isTimeElement(element) ||
-          parser.isDateElement(element) ||
-          parser.isArgumentElement(element) ||
-          parser.isSelectElement(element) ||
-          parser.isPluralElement(element)
-      )
-      .map((argumentElement) => argumentElement.value);
+    traverse(parser.parse(string), {
+      [parser.TYPE.time]: recordVisitedNodeValue,
+      [parser.TYPE.date]: recordVisitedNodeValue,
+      [parser.TYPE.plural]: recordVisitedNodeValue,
+      [parser.TYPE.select]: recordVisitedNodeValue,
+      [parser.TYPE.argument]: recordVisitedNodeValue,
+    });
+
+    return [...args];
   } catch (err) {
-    throw new Error(`An error occured (${err.message}) when extracting ICU arguments for '${string}'`);
+    throw new Error(`An error occurred (${err.message}) when extracting ICU arguments for '${string}'`);
   }
 }
 
diff --git a/package.json b/package.json
index b7c198a7..1c435727 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "ember-intl",
-  "version": "5.0.7",
+  "version": "5.0.8",
   "description": "A internationalization toolbox for ambitious applications.",
   "keywords": [
     "ember-addon",


Test patch:
diff --git a/tests-node/unit/broccoli/translation-reducer/lint-test.js b/tests-node/unit/broccoli/translation-reducer/lint-test.js
index b253bcd5..696a12a5 100644
--- a/tests-node/unit/broccoli/translation-reducer/lint-test.js
+++ b/tests-node/unit/broccoli/translation-reducer/lint-test.js
@@ -126,7 +126,7 @@ describe('linting', function () {
     const brokenString = this.brokenIcuFixture.en.brokenSyntax;
 
     expect(() => this.linter.lint(this.brokenIcuFixture)).throws(
-      `An error occured (${expectedParserError}) when extracting ICU arguments for '${brokenString}'`
+      `An error occurred (${expectedParserError}) when extracting ICU arguments for '${brokenString}'`
     );
   });
 
@@ -148,4 +148,86 @@ describe('linting', function () {
       ['missing', ['en']],
     ]);
   });
+
+  it('detects mismatched arguments', function () {
+    const results = this.linter.lint({
+      de: {
+        key: `{count}`,
+      },
+      en: {
+        key: ``,
+      },
+    });
+
+    expect(results.icuMismatch).to.deep.equal([['key', [['en', ['count']]]]]);
+  });
+
+  it('detects date arguments', function () {
+    const results = this.linter.lint({
+      de: {
+        key: `{timestamp, date, long}`,
+      },
+      en: {
+        key: ``,
+      },
+    });
+
+    expect(results.icuMismatch).to.deep.equal([['key', [['en', ['timestamp']]]]]);
+  });
+
+  it('detects time arguments', function () {
+    const results = this.linter.lint({
+      de: {
+        key: `{timestamp, time, short}`,
+      },
+      en: {
+        key: ``,
+      },
+    });
+
+    expect(results.icuMismatch).to.deep.equal([['key', [['en', ['timestamp']]]]]);
+  });
+
+  it('detects select arguments', function () {
+    const results = this.linter.lint({
+      de: {
+        key: `{gender, select, male {He avoids bugs} female {She avoids bugs} other {They avoid bugs}}`,
+      },
+      en: {
+        key: ``,
+      },
+    });
+
+    expect(results.icuMismatch).to.deep.equal([['key', [['en', ['gender']]]]]);
+  });
+
+  it('detects plural arguments', function () {
+    const results = this.linter.lint({
+      de: {
+        key: `{numPhotos, plural, =0 {no photos.} =1 {one photo.} other {# photos.}}`,
+      },
+      en: {
+        key: ``,
+      },
+    });
+
+    expect(results.icuMismatch).to.deep.equal([['key', [['en', ['numPhotos']]]]]);
+  });
+
+  it('detects arguments within plural arguments', function () {
+    const results = this.linter.lint({
+      de: {
+        key: `{count, plural,
+        one {Ein Fehler hat die Speicherung von {model} verhindert}
+        other {# Fehler hat verhindert, dass {model} gespeichert wurden}
+      }`,
+      },
+      en: {
+        key: ``,
+      },
+    });
+
+    expect(results.icuMismatch).to.deep.equal([['key', [['en', ['count', 'model']]]]]);
+    expect(results.missingTranslations).to.deep.equal([]);
+  });
 });