diff --git a/README.md b/README.md index a29a011..05bcdbe 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ Where `locales/fr.json` will look like this for use by your translators: }, "There is one user": { // src/pages/AboutPage/index.js:40 - "default": {"one":"French translation", "other":"French translation"}, + "default": {"1":"French translation", "2":"French translation"}, }, "Welcome to the about page!": { // src/pages/AboutPage/index.js:38 @@ -115,7 +115,7 @@ And the optimized `src/.locales/fr.json` will look like this for use by your dev "default": "French translation", "menuitem": "French translation" }, - "There is one user": {"one":"French translation", "other":"French translation"}, + "There is one user": {"1":"French translation", "2":"French translation"}, "Welcome to the about page!": "French translation" } ``` diff --git a/src/README.md b/src/README.md index 905a4e7..d5cf17b 100644 --- a/src/README.md +++ b/src/README.md @@ -99,7 +99,7 @@ Where `locales/fr.json` will look like this for use by your translators: }, "There is one user": { // src/pages/AboutPage/index.js:40 - "default": {"one":"French translation", "other":"French translation"}, + "default": {"1":"French translation", "2":"French translation"}, }, "Welcome to the about page!": { // src/pages/AboutPage/index.js:38 @@ -115,7 +115,7 @@ And the optimized `src/.locales/fr.json` will look like this for use by your dev "default": "French translation", "menuitem": "French translation" }, - "There is one user": {"one":"French translation", "other":"French translation"}, + "There is one user": {"1":"French translation", "2":"French translation"}, "Welcome to the about page!": "French translation" } ``` diff --git a/src/index.js b/src/index.js index a5e1371..4cf9a0d 100644 --- a/src/index.js +++ b/src/index.js @@ -54,14 +54,24 @@ function __p(context, key) { * @private */ function __n(singular) { - return [toKeyWithContext(singular), {one: "", other: ""}]; + return [toKeyWithContext(singular), { + // Singular form placeholder + "1": "", + // Plural form placeholder + "2": "" + }]; } /** * @private */ function __np(context, singular) { - return [toKeyWithContext(singular, context), {one: "", other: ""}]; + return [toKeyWithContext(singular, context), { + // Singular form placeholder + "1": "", + // Plural form placeholder + "2": "" + }]; } /** diff --git a/src/test.js b/src/test.js index ebdb207..5e9ac39 100644 --- a/src/test.js +++ b/src/test.js @@ -95,7 +95,7 @@ describe('TranslationStaticAnalyzer', () => { { "action": "write", "filename": "./locales/existing.json", - "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"one\":\"\",\"other\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"one\":\"\",\"other\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // NEW\n // src/index.js:2\n \"default\": \"\"\n },\n \"Search\": {\n // NEW\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n }\n}" + "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // NEW\n // src/index.js:2\n \"default\": \"\"\n },\n \"Search\": {\n // NEW\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n }\n}" }, { "action": "read", @@ -265,7 +265,7 @@ describe('TranslationStaticAnalyzer', () => { { "action": "write", "filename": "./locales/existing.json", - "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"one\":\"\",\"other\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"one\":\"\",\"other\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" + "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" }, { "action": "read", @@ -356,7 +356,7 @@ describe('TranslationStaticAnalyzer', () => { { "action": "read", "filename": "./locales/existing.json", - "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"one\":\"\",\"other\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"one\":\"\",\"other\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" + "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" } ]); }); @@ -458,7 +458,7 @@ describe('TranslationStaticAnalyzer', () => { { "action": "read", "filename": "./locales/existing.json", - "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"one\":\"\",\"other\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"one\":\"\",\"other\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" + "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" }, { "action": "write", @@ -497,12 +497,12 @@ describe('TranslationStaticAnalyzer', () => { "%d result": { // NEW // src/pages/Search/index.js:6 - "default": {"one":"","other":""} + "default": {"1":"","2":""} }, "%d view": { // NEW // src/pages/Search/index.js:6 - "footer": {"one":"","other":""} + "footer": {"1":"","2":""} }, "About": { // NEW @@ -561,7 +561,7 @@ describe('TranslationStaticAnalyzer', () => { { "action": "read", "filename": "./locales/existing.json", - "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"one\":\"\",\"other\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"one\":\"\",\"other\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" + "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" }, { "action": "write", @@ -623,7 +623,7 @@ describe('TranslationStaticAnalyzer', () => { { "action": "read", "filename": "./locales/existing.json", - "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"one\":\"\",\"other\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"one\":\"\",\"other\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" + "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" }, { "action": "write", @@ -698,12 +698,12 @@ describe('TranslationStaticAnalyzer', () => { { "action": "read", "filename": "./locales/existing.json", - "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"one\":\"\",\"other\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"one\":\"\",\"other\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" + "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" }, { "action": "write", "filename": "./locales/existing.json", - "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"one\":\"\",\"other\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"one\":\"\",\"other\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Added\": {\n // NEW\n // src/pages/Added/index.js:0\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" + "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Added\": {\n // NEW\n // src/pages/Added/index.js:0\n \"default\": \"\"\n },\n \"Application\": {\n // src/index.js:2\n \"default\": \"アプリケーション\"\n },\n \"Search\": {\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"検索\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n },\n \"test unused key\": {\n // UNUSED\n \"default\": \"test value\"\n }\n}" }, { "action": "read", @@ -890,7 +890,7 @@ describe('TranslationStaticAnalyzer', () => { { "action": "write", "filename": "./locales/new.json", - "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"one\":\"\",\"other\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"one\":\"\",\"other\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // NEW\n // src/index.js:2\n \"default\": \"\"\n },\n \"Search\": {\n // NEW\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n }\n}" + "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // NEW\n // src/index.js:2\n \"default\": \"\"\n },\n \"Search\": {\n // NEW\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n }\n}" }, { "action": "read", @@ -957,7 +957,7 @@ describe('TranslationStaticAnalyzer', () => { { "action": "write", "filename": "./locales/new.json", - "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"one\":\"\",\"other\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"one\":\"\",\"other\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // NEW\n // src/index.js:2\n \"default\": \"\"\n },\n \"Search\": {\n // NEW\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n }\n}" + "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // NEW\n // src/index.js:2\n \"default\": \"\"\n },\n \"Search\": {\n // NEW\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n }\n}" }, { "action": "read", @@ -1044,7 +1044,7 @@ describe('TranslationStaticAnalyzer', () => { { "action": "write", "filename": "testtemplatespath/locales/existing.json", - "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"one\":\"\",\"other\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"one\":\"\",\"other\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // NEW\n // src/index.js:2\n \"default\": \"\"\n },\n \"Search\": {\n // NEW\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n }\n}" + "data": "{\n \"%d result\": {\n // NEW\n // src/pages/Search/index.js:6\n \"default\": {\"1\":\"\",\"2\":\"\"}\n },\n \"%d view\": {\n // NEW\n // src/pages/Search/index.js:6\n \"footer\": {\"1\":\"\",\"2\":\"\"}\n },\n \"About\": {\n // NEW\n // src/pages/About/index.js:2\n \"default\": \"\"\n },\n \"Application\": {\n // NEW\n // src/index.js:2\n \"default\": \"\"\n },\n \"Search\": {\n // NEW\n // src/pages/About/index.js:6\n // src/pages/Search/index.js:2\n \"default\": \"\",\n // NEW\n // src/pages/Search/index.js:6\n \"menuitem\": \"\"\n }\n}" }, { "action": "read",