{"_id":"@cepharum/js-i18n","_rev":"14-720d3f5c88025b758f3dd77253bbf350","name":"@cepharum/js-i18n","dist-tags":{"latest":"0.2.0-alpha.1","next":"0.1.0-alpha.4"},"versions":{"0.0.1":{"name":"@cepharum/js-i18n","version":"0.0.1","description":"an i18n service for Javascript","main":"index.js","private":false,"scripts":{"test":"mocha --ui=tdd test/**/*.spec.js","lint":"eslint ."},"repository":{"type":"git","url":"git+https://github.com/cepharum/js-i18n.git"},"keywords":["i18n","l10n"],"author":{"name":"cepharum GmbH"},"license":"MIT","bugs":{"url":"https://github.com/cepharum/js-i18n/issues"},"homepage":"https://github.com/cepharum/js-i18n#readme","devDependencies":{"eslint":"^5.11.1","eslint-config-cepharum":"^1.0.8","eslint-plugin-promise":"^4.0.1","mocha":"^5.2.0","should":"^13.2.3"},"gitHead":"5b4e3555fcdb2a278014772cddfc1c5e3b971c57","_id":"@cepharum/js-i18n@0.0.1","_npmVersion":"6.4.1","_nodeVersion":"10.13.0","_npmUser":{"name":"soletan","email":"thomas.urban@cepharum.de"},"dist":{"integrity":"sha512-PicQwh3H/60f+vGIT5BgJWWe6IWfP1U3YIdncNaCdPE1+LYDdtZlptIYmDFAy99B1u+gfo23OkKtmqcVvpnGfQ==","shasum":"d3a71cd704e2ceb61faae3e8f2ac743dbccfcae1","tarball":"https://registry.npmjs.org/@cepharum/js-i18n/-/js-i18n-0.0.1.tgz","fileCount":7,"unpackedSize":35797,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcK+bWCRA9TVsSAnZWagAARBoQAIYDmo5COglVQrfTCMko\nXUh+6CCg4SgMt+lq+Drb+53Q294Gh2KJ8i7zeZJQCSdF7SkerzS8YtYWP1RY\nCJYQ5jnQ2OrkRT5pRAK9OeUVbXPr+UrGLTZimFDfRCoPpheRZxNYE1OUcx0g\n32tPP9eY3UW/eHdXVdWpo/0+yMIbTaJTWMR/NBa6v7bvcoofNPHIpMQipeDA\nGGT5mcT/7tbvFSOs+HUSGD0/tZyjDp7OxOLI+5gnLLlNC4JkaDMDngVLOOmN\nTh9SQUpnQhuxdC4pwxKZbD/drIjB5Mamie8pWzqJjX/RnqpY/owzdMhQKSlL\n5pDomNTbXb7lLmo3xqf4D+NP1a3imwwEqyA5n7kM0nEJnmjxfosaP17DFOQF\nSsWJvG1LX6bmmIEPxbW4MSgQ/jn3IjgJOvueqwERhwjhZo8p4e6LzVfLk1V5\nfuYr66ZEJ8bhhA8zutLamsbQm0nPWvyoUz3oUilyju6Td/lckBdstJEOoXM+\nFAUA0VGxft5N0sNRap40eRH0UKPqDWZnPI0WBnQddRv/PkkX+z3EkmgJOMrK\npePHYRealp6Qga37Nh+aVNtBTSqB0BYOkWOPXPvDV3vIr6JFSv1RDqk93Gi/\ncORt6E9PIL5Yiz/01/Y2/O12S3lt5IvsBeqCE19H2vSaPN69qTnWloC/G0/I\n5nNN\r\n=/NoR\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIHojQKpfVhu82ZvduB0WlNwssRbK1F5/5sjy+PRV5odqAiEA+PJdQRZF5FZSN4q461joexFl+wVC0UyKmQA4EzneRto="}]},"maintainers":[{"name":"simon.friedo","email":"friedosimon@aol.com"},{"name":"soletan","email":"thomas.urban@cepharum.de"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/js-i18n_0.0.1_1546381014061_0.943240970764263"},"_hasShrinkwrap":false},"0.0.2":{"name":"@cepharum/js-i18n","version":"0.0.2","description":"an i18n service for Javascript","main":"index.js","private":false,"scripts":{"test":"mocha --ui=tdd test/**/*.spec.js","lint":"eslint ."},"repository":{"type":"git","url":"git+https://github.com/cepharum/js-i18n.git"},"keywords":["i18n","l10n"],"author":{"name":"cepharum GmbH"},"license":"MIT","bugs":{"url":"https://github.com/cepharum/js-i18n/issues"},"homepage":"https://github.com/cepharum/js-i18n#readme","devDependencies":{"eslint":"^5.11.1","eslint-config-cepharum":"^1.0.8","eslint-plugin-promise":"^4.0.1","mocha":"^5.2.0","should":"^13.2.3"},"gitHead":"e52d4e7acb24da19557800a9129b7dce327da603","_id":"@cepharum/js-i18n@0.0.2","_npmVersion":"6.4.1","_nodeVersion":"10.13.0","_npmUser":{"name":"soletan","email":"thomas.urban@cepharum.de"},"dist":{"integrity":"sha512-wys9IhCq3u+cMeRsNExfsLl5NPWwxebDy/5JWjbXpqZwOdO+OKrBbBCwgkbxVju63oKNLwWbNmYZGhsd0xflgQ==","shasum":"ab7f5a0a88d73ab2e357508fbbbaf32c00a14665","tarball":"https://registry.npmjs.org/@cepharum/js-i18n/-/js-i18n-0.0.2.tgz","fileCount":10,"unpackedSize":38680,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcLAwVCRA9TVsSAnZWagAAQbMP+gKQ0jeLVNQZO5dZuofW\nF2vrus/kSG4KZRoQTbq9uu+6rrCmeA9v8eqRYslP2yyRygnMA6CPNGmjmzh6\nFZ7N954SHkNRaMp5SdkUa32qCOBRVMmzWaNFPeFP9Z77wJg9Gv5SKpPs+Uw5\n770h80uzTZhrAqgRPTwBtwEH/uFeJimW3Q9Rm79fo7UVsxhnCrIjrQsKTVhI\ntbnH5aDddWH5tlU3t1IjLiRTsWNyGLAAI694JjIc3IBijVC2kuyOs6Kx/eSV\n7169UMugLFK0IBtp+datWdFC9JrFNajAvcr1EC7xNUyPg/RCPBsvtNFa/pVN\nPBhf8TfnmdaNZdCotXzpPmYl12JP+mGVN7q3ZUwr1eiJALg1KicNv8GQBMpC\nzZVFomWBKSYsqLyIVuToekp/wMsXYDFLPkRrwmj0rQsOaolS0IxQgnQhify3\nEyCfIxKHvSNudntH1HtGhbYZ4GcidYflGOAFbLFSlVIQ1DJEuOrOdk3OFQsi\nWAwkZ9qTYcbG3FjYQDSQIbxiHZmxDSREVXcUiuIYD51dgR3bEdvslgdf4+zx\nRq1PFtQsiPEQHBt6M6we9B4uEF6Vtc+GuUVz4pUsjjBXlCkw1PX+sENR9dxO\ntpCssF2atrF0FfXHzZY7FaXfSDPDf5vQBhOEy5ObLXJy8waOWZ5hBAptAXec\nQp8V\r\n=bLBj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIGL5zq5X10XgMG0fsBxx+inA3LrpjcB0qmoxCwVXle5KAiAnrd958kidA+8A8DK8koRkvoM6zELEgE/agANP0gzF9Q=="}]},"maintainers":[{"name":"simon.friedo","email":"friedosimon@aol.com"},{"name":"soletan","email":"thomas.urban@cepharum.de"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/js-i18n_0.0.2_1546390548929_0.8919471948755848"},"_hasShrinkwrap":false},"0.0.3":{"name":"@cepharum/js-i18n","version":"0.0.3","description":"an i18n service for Javascript","main":"index.js","private":false,"scripts":{"test":"mocha --ui=tdd test/**/*.spec.js","lint":"eslint ."},"repository":{"type":"git","url":"git+https://github.com/cepharum/js-i18n.git"},"keywords":["i18n","l10n"],"author":{"name":"cepharum GmbH"},"license":"MIT","bugs":{"url":"https://github.com/cepharum/js-i18n/issues"},"homepage":"https://github.com/cepharum/js-i18n#readme","devDependencies":{"eslint":"^5.11.1","eslint-config-cepharum":"^1.0.8","eslint-plugin-promise":"^4.0.1","mocha":"^5.2.0","should":"^13.2.3"},"gitHead":"e5448859c893aafb87417e8f3c2a0a303eadbe44","_id":"@cepharum/js-i18n@0.0.3","_npmVersion":"6.4.1","_nodeVersion":"10.13.0","_npmUser":{"name":"soletan","email":"thomas.urban@cepharum.de"},"dist":{"integrity":"sha512-K6msgP4xRp5/sBjeCcke4rPBL4vkr5jFGhupRDYlo47nPoDLXTyR/CghRE2ijxx4OmnTZr8mmty9UyQ+KcJq1w==","shasum":"9ab233820f1f33694b341151e226c0cdbca24949","tarball":"https://registry.npmjs.org/@cepharum/js-i18n/-/js-i18n-0.0.3.tgz","fileCount":10,"unpackedSize":38680,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcLBW7CRA9TVsSAnZWagAAaJYP/jLfmr0QT6/NE4wetE6D\noICMVGzs2fHNP3OBWMuPjQHIlduaTqg/q/vnTRxXrLIrhxRTc9HqB0GH2LY+\nBVNZo8c1fwFxgEDbcGJ7aizw+eZ/VWvJSsVfokxwVMcQAHC/hRFYYRohUXIl\nOG6qfr4Tq+N5ertxSYdwoiCViyw7/wp7GEGK1dJWnoNrPoicpnHh770Rx/NT\nK7v9smWmH1f9tqJZ5s+TODnpcLnHEUJRaRuRK8eXmHlfP8mTrzANvljWkr1C\n8HDhtxDGt6+XpUR0hp4U3G9AnBexDc4d3UYJu98aMoZx05gYjbgonGumWPFb\n6DaGaDt64CEr+yc6kX+tHm1XP9QXDq6iBtay2NKKPJeyZ1S+mSoPddeySSq3\nWh6AQexdMrlvUC0Wp/ziI3q8gHnLK8bPM5jCmAWBxMlwVhISJdCJVb1GAh5H\nBgTpnu2geeLvXp5uX7d59wWXSriV1RCTzLebIf2JZ4xhH9391a2xPiza50K4\nv4c26gakZNy8hOGx7TZppn22xHpmtXbUUvYI2DwvNn3Vsa81X+bbCLb46wVl\nmAq6O1+2mTERqZRL3W+1/oMsWbtLUm82Bf3RuR86fu5TUbi3u04gGCTiSrQi\nIgUKnQAdNnaGzGfedrf01ancaObD+O0r3dp45mjJTqVj7qnRmH8BaRpfdjNE\nGJdk\r\n=yt9O\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDT/ieMRjPi1iU9JKLBPNPKaw8HraJSC0kJ3rFHjQuSmQIgYngI56kvTQn87H7Fsm+68pizvO0TBdVNjIjwGTSkibk="}]},"maintainers":[{"name":"simon.friedo","email":"friedosimon@aol.com"},{"name":"soletan","email":"thomas.urban@cepharum.de"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/js-i18n_0.0.3_1546393019398_0.044773968734123315"},"_hasShrinkwrap":false},"0.0.4":{"name":"@cepharum/js-i18n","version":"0.0.4","description":"an i18n service for Javascript","main":"index.js","private":false,"scripts":{"test":"mocha --ui=tdd test/**/*.spec.js","lint":"eslint ."},"repository":{"type":"git","url":"git+https://github.com/cepharum/js-i18n.git"},"keywords":["i18n","l10n"],"author":{"name":"cepharum GmbH"},"license":"MIT","bugs":{"url":"https://github.com/cepharum/js-i18n/issues"},"homepage":"https://github.com/cepharum/js-i18n#readme","devDependencies":{"eslint":"^5.11.1","eslint-config-cepharum":"^1.0.8","eslint-plugin-promise":"^4.0.1","mocha":"^5.2.0","should":"^13.2.3"},"gitHead":"39f99612e39dd06c21b34b808aedeffda475224f","_id":"@cepharum/js-i18n@0.0.4","_npmVersion":"6.4.1","_nodeVersion":"10.13.0","_npmUser":{"name":"soletan","email":"thomas.urban@cepharum.de"},"dist":{"integrity":"sha512-OqcZWhxsyWzuPGp4z6743hrz1lh7y9kU26PvpLWmPA14S+x8jgPuATV4F7ywSmJ/NmLl0qKeg2E4R9PaXbkp6Q==","shasum":"d51d93fc56c239ca79f4b1089c1c719417573ca4","tarball":"https://registry.npmjs.org/@cepharum/js-i18n/-/js-i18n-0.0.4.tgz","fileCount":10,"unpackedSize":38676,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcLBiOCRA9TVsSAnZWagAAyZQQAIqKKWIHov7sjqsNhVOs\nd4OVEgBBhBf43EYX1rSl5igrChr0BZYzAekkABTwHbwHA3DLe7jzKMMKM3Vn\nUXSbG7Soe6B1PlVFHuRMSPve7M/Giw/MvVrzWQNMX8zls4BglXD/sKuE2XtL\nS7t9JgxeqCI3udMi2SmsOykvaJCp1/VoMoUReKMmp9dFgytQ04RZmlRVuYRK\n6ftq/4uptWPRET3jV3M+TsX5vb/YI0Xhke2tgW3BWWGjU31TuD7JYtdH/Cfa\nIZVqvf1snx0vuQy4BnHG2RYHL4snI31KavBgQMn7/mxhU8nVwHJ+txcfuMoe\nAVf7Mdzaf0xPqShRXxjzf4YVYaPrZj5kX95ZszV7oVwNETCYKqYsIhMdZfK7\nRp6l3xX8Pcge2fYFXj+OjW8PLLEeKjx/PL7/DBYRga9eyuqlIu9/qfm6PYhx\nutzrQG0fwtu/j4+/RxRES9C5EfXATzxFJIFDIXdS0Dn+Z6ab6rgd1HyXKRjC\n37YabS+qssEhUgTgSZ8k5lE4xv0bStm7SUaPzrm8WYlLYfhnljv8w7qwsjz4\nyS7oz6YfAS1R5Lw0Lz5711jCt0vXBlVsZhc8t0DDPqEuI8E8W66n1+FMM8pn\nakEQ5zl1wVigv1PIDgMuKJkxEMKdv/TxfzJmiCxpvve5nW6BPMgbs3ECVtct\nRYXT\r\n=bR9I\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCNW6VI965HkLZ8E3odu/M+IAig3kC76n1086VSNR5nKwIgJpCUj6HgHaDfP4sNErWugOY4mP4VcwNjQS6BL97q6jA="}]},"maintainers":[{"name":"simon.friedo","email":"friedosimon@aol.com"},{"name":"soletan","email":"thomas.urban@cepharum.de"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/js-i18n_0.0.4_1546393741509_0.8010965367085001"},"_hasShrinkwrap":false},"0.0.5":{"name":"@cepharum/js-i18n","version":"0.0.5","description":"an i18n service for Javascript","main":"index.js","private":false,"scripts":{"test":"mocha --ui=tdd test/**/*.spec.js","lint":"eslint ."},"repository":{"type":"git","url":"git+https://github.com/cepharum/js-i18n.git"},"keywords":["i18n","l10n"],"author":{"name":"cepharum GmbH"},"license":"MIT","bugs":{"url":"https://github.com/cepharum/js-i18n/issues"},"homepage":"https://github.com/cepharum/js-i18n#readme","devDependencies":{"eslint":"^5.11.1","eslint-config-cepharum":"^1.0.8","eslint-plugin-promise":"^4.0.1","mocha":"^5.2.0","should":"^13.2.3"},"gitHead":"bc1da8ba7bf22c1762b97f2492bb58db387059ba","_id":"@cepharum/js-i18n@0.0.5","_npmVersion":"6.4.1","_nodeVersion":"10.13.0","_npmUser":{"name":"soletan","email":"thomas.urban@cepharum.de"},"dist":{"integrity":"sha512-CYx/umJHjCrf4Vw8hqIa6bWU+oACxmiIbvpIzFdpcp1hhNP1hgB4Hfw+JQgCRMzlkH5sdFERJWXJ+AYaAjSxKg==","shasum":"f717ee60886a58cd6c1f46393fae8f202e80daec","tarball":"https://registry.npmjs.org/@cepharum/js-i18n/-/js-i18n-0.0.5.tgz","fileCount":10,"unpackedSize":38691,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcLBoQCRA9TVsSAnZWagAAY8gP/jECzngRTb1HB1YBWEzH\nhhdV88Bj09m2MVJ6HVxhQj8TNPnJpCawgDQNLNuVBx7w6ugq01p8a2ihJq3A\npOIf2MzpfUpVTeWzkupmd1Bt5RybPmm3lFy3lu4qWG/eceIvBTWKAclhG7pc\n/XOBATY16G0elGK/YvefqdCFKsdAZw2L5Tb7D2eXhJnnAfAnrgSK6gORSBrh\nU53uZDL1jRfY2fg3pRZAmpGPde7lNEE+O+wurUaVi1KNqNALhy17Yya7aDr4\nNCO35kIFlBpn4bew2upOeB3KumejdwQywrv7xGYspMwjDJpvpVdg+Igtvc84\nYl677NrH8yOIda6PRKDwBBg+1SjcvMTlnyr8q/j2NDl77QXadOmyYgDuTn4x\n30wEAu3XsU8uRmSK3CxFFLn4cJ31Opqh5GL2jPTxqmMWVVPnPQsIPxGf+wa4\nNU4d6LBzBJR+QREFjVAjXbYMlhPUmq8hlIapzccW9YCpMQ58VpPW/p4d9RnG\nSCm2czpmwQTRX6lfhEq70FPc9L2wM7gquMMGjaq77w3rUHweDC9bJLR8VCyM\nTK6iCNYLptT/yU7Nk7tkJM6GkHKVpMTdyAKQyNNi3Dr7lHHlDorUdewX0r2o\nyjbhFAieguB4Q+VElXrWpg4sIyeRs1DrnL6f/7pjp3Vagnx6paC3nercOy9M\nRffw\r\n=Nvo+\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCICyZ9DaIPIQIDCngtXqStEzMjWn7tFcUohFUkSovI/etAiEA3TY34Sig7/vPrlHePoffZWTTWAWth2DPlHB5zSYYZOc="}]},"maintainers":[{"name":"simon.friedo","email":"friedosimon@aol.com"},{"name":"soletan","email":"thomas.urban@cepharum.de"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/js-i18n_0.0.5_1546394127755_0.09498542530546317"},"_hasShrinkwrap":false},"0.0.6":{"name":"@cepharum/js-i18n","version":"0.0.6","description":"an i18n service for Javascript","main":"index.js","private":false,"scripts":{"test":"mocha --ui=tdd test/**/*.spec.js","lint":"eslint ."},"repository":{"type":"git","url":"git+https://github.com/cepharum/js-i18n.git"},"keywords":["i18n","l10n"],"author":{"name":"cepharum GmbH"},"license":"MIT","bugs":{"url":"https://github.com/cepharum/js-i18n/issues"},"homepage":"https://github.com/cepharum/js-i18n#readme","devDependencies":{"eslint":"^5.11.1","eslint-config-cepharum":"^1.0.8","eslint-plugin-promise":"^4.0.1","mocha":"^5.2.0","should":"^13.2.3"},"gitHead":"78c91c9690763c4235ff62b88068af9781fd96ce","_id":"@cepharum/js-i18n@0.0.6","_npmVersion":"6.4.1","_nodeVersion":"10.13.0","_npmUser":{"name":"soletan","email":"thomas.urban@cepharum.de"},"dist":{"integrity":"sha512-4M9hBCWSXJcmtMwdqC5g0xEPx8OH/DwuLFUeddWVcPiSEvH6rSuaeD9Zh1Yg6zoy5IA3n3FhRwYbtrmEz3nTew==","shasum":"1f91826177f85787806103d03f12140816544dc0","tarball":"https://registry.npmjs.org/@cepharum/js-i18n/-/js-i18n-0.0.6.tgz","fileCount":10,"unpackedSize":38673,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcLIEhCRA9TVsSAnZWagAAnFIP/1aS9G9yof/v1w/5ZlNS\naQ/1wEJG/HPA4D5V7LT60HqlsdKCnwcv2dNoOIaJit6SxEyNJl/C3tvLbgPH\nCHlMaQle2rBxXH4RCICZ4hlNkc3O935TIrC//1Z0ZUOs1Z9JNSmP77r8/k17\noSonutEvf8sVlVP4/quSUCN0lnwrE4J2oQK71MRsEyT2P5d7TnwNZdr6l12u\n2hTTSUDEDLMHPCxtJiMDgrcd98z3NygEvtUwRAs91EYP4lCSrRH5PJPoa1h/\n5rO6wO1XjFBc3Xv2A1120Isw6mmwNo9qLIuphxbHE1vMhNJVq1966g4xfMbi\neHLEqK2/IIlTVaCMjiXTRy/dj/qE3etnk7DKcUD/4T7F9OqdVdLijAYD1fpS\nwPOXuLI5z+boJ8NY8cVIS3L/KvOIqWUAjA5ZedFmUjQ8txp6UOfh8tvDU3/y\ncKfBvjXXVeRHgyH7qPr7ul8amGaAm4VfT418J3qjU+Zc4I3bJZBEokj6eiLK\nrXendFmxs7oD9wHT4FEuLV5I6Mzx6FsdGeIRhoKnvf7F8Fd78GRWL33KYfkD\ns9CSVHQPLn4l4+LuxPNNm+JdAC7Tz4XgUYsKbjD1RivD7JlT4hI6DiyFt8w5\nv6o32XR7WVw+2e7X24Zxew4Ujx7fOKr/K5ED0wNWoQqgXeD2wCdIPuKmBGur\ntWf1\r\n=4S1l\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQC09d9dX2UT8gUy5PSadgN1N+MtKDZnfUf7A7jTJI0zSgIgRoh5nmS8V3RJ4hbPZ06gs9O0qcHJaEoozMy6a7tXWIU="}]},"maintainers":[{"name":"simon.friedo","email":"friedosimon@aol.com"},{"name":"soletan","email":"thomas.urban@cepharum.de"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/js-i18n_0.0.6_1546420513064_0.4266236729130226"},"_hasShrinkwrap":false},"0.0.7":{"name":"@cepharum/js-i18n","version":"0.0.7","description":"an i18n service for Javascript","main":"index.js","private":false,"scripts":{"test":"mocha --ui=tdd test/**/*.spec.js","lint":"eslint ."},"repository":{"type":"git","url":"git+https://github.com/cepharum/js-i18n.git"},"keywords":["i18n","l10n"],"author":{"name":"cepharum GmbH"},"license":"MIT","bugs":{"url":"https://github.com/cepharum/js-i18n/issues"},"homepage":"https://github.com/cepharum/js-i18n#readme","devDependencies":{"eslint":"^5.11.1","eslint-config-cepharum":"^1.0.8","eslint-plugin-promise":"^4.0.1","mocha":"^5.2.0","should":"^13.2.3"},"gitHead":"9e68b8349e3ed941aee2541355061902ef464681","_id":"@cepharum/js-i18n@0.0.7","_npmVersion":"6.4.1","_nodeVersion":"10.13.0","_npmUser":{"name":"soletan","email":"thomas.urban@cepharum.de"},"dist":{"integrity":"sha512-gjiOLNJRQAcXbtpJvBiyMpBM4Kkbqpudl1BOIXVRS2hC8GsktsmOW4kEtg9ZRZ7kkps7zrZrRsJVPycnwX3vZQ==","shasum":"769b799cd86fc300f84e50d3c656957dae5a59b4","tarball":"https://registry.npmjs.org/@cepharum/js-i18n/-/js-i18n-0.0.7.tgz","fileCount":12,"unpackedSize":60554,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcLOh9CRA9TVsSAnZWagAAG3MQAKAeydcrEAy5TpIOryoa\nIqiwJua5EKv6awRBgpaJdT26Dcf4k+dfZILCww4LbP+nfsFYo06aqgBPQnUk\nMuUmCNwAp+R5H9C9v3wTCefHJ6npcGt5eJprHQcu+F6cAOJNkaacFLrXl2jR\nkprWmqGMEUwnK5YOFOrqSsETp8tmG09Uwo+LTobSC8ynvsNAA3LO0FG7euW5\n1XEjqxj03CwbR2wqYzerALMbDPSxNmxSJnFTI9ota360Ao2sg35rVNFKQaam\nAmnnATRAw4OIqckWTnobKTxi2SsF3cnbBtf1OOQOk3+P97ZFYhsSh8sq71Xy\nCzsiMwloWo2zQfwgEfmE+psBuUE5fNnwmvHeUPzyts60Q2TcIa4Gwz8o4N7G\nED+OVqGdqAAM/kJ8oddukdYHkUrAlwG5JrcXAi1YCZQYEcr8u5PWm9vxtEGM\n6138fSAzb36MlnILVSdUFtLAKz2PB3he9lh/PbeDe/aPbq9fYotty583mu1Q\npgrcdgjrdq1cY+wfQ30/g7/Jh9zrgTzfOxBVkibVNu+J0vy9E6HCgA2iTNCX\nvEXkPQ4hcWtIrWKO4OldlLA3CR9DZiDRl3B4IWtNlK99+t+XLG4j1Q/XVZxg\nAWXPvtQVKoP6X6vyVjbA1gs4YZiypJ6hREOhAcartfcAKt4ufO3LI5Dhch7V\nLTOT\r\n=On7/\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAYnfIL2GhPr1AX7UEDgDwaeB895VOEWo1NP7ZMCCvCsAiEAzIF2Bj0DLZrnfk0DtdL2wM0gU0MP/FU5OwjYFNyo+kU="}]},"maintainers":[{"name":"simon.friedo","email":"friedosimon@aol.com"},{"name":"soletan","email":"thomas.urban@cepharum.de"}],"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/js-i18n_0.0.7_1546446972366_0.05451143322168761"},"_hasShrinkwrap":false},"0.0.8":{"name":"@cepharum/js-i18n","version":"0.0.8","description":"an i18n service for Javascript","main":"index.js","private":false,"scripts":{"test":"mocha --ui=tdd test/**/*.spec.js","lint":"eslint ."},"repository":{"type":"git","url":"git+https://github.com/cepharum/js-i18n.git"},"keywords":["i18n","l10n"],"author":{"name":"cepharum GmbH"},"license":"MIT","bugs":{"url":"https://github.com/cepharum/js-i18n/issues"},"homepage":"https://github.com/cepharum/js-i18n#readme","devDependencies":{"eslint":"^5.11.1","eslint-config-cepharum":"^1.0.8","eslint-plugin-promise":"^4.0.1","mocha":"^5.2.0","should":"^13.2.3"},"gitHead":"9b52db370f7422c7a5a57c971a9ab5c5ba5a0d0d","_id":"@cepharum/js-i18n@0.0.8","_nodeVersion":"10.13.0","_npmVersion":"6.9.0","dist":{"integrity":"sha512-yW2HCjgAGZQi2vUZTEA9wWARLmsjiaZH8VJOMPcs9m16fLsAw/qsSbseOG9HNNnx+y93lg/s0nQdzR5Kxlw2XQ==","shasum":"afa75033deaca81c77424aaea3e71257ea896151","tarball":"https://registry.npmjs.org/@cepharum/js-i18n/-/js-i18n-0.0.8.tgz","fileCount":12,"unpackedSize":61502,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcrHctCRA9TVsSAnZWagAAIIUP/3Or/92S//RIm09KsY7C\n00jxZEYYsgNu5SQLKwDqAowvK1rpyXMEu2ATvOqnUlbasAr7YLfGrl45ZAmQ\nNViBpuW9vu7+LCD4/ROGlB7AgEI08AwsToy4mpQIv3VWiUcWzEfKm4Okoy4b\np5ul/pXP19kITQuxDORQV6CYZ4oKhIo0sZpqjJ+LZ6TCJPyNFjQuK2AH2zBG\n/7LQTVQDro/2wZ28XHNbO8F58I4B66Fapm27yhm5cjYAH2Y6snrrX/g/VxcU\n7aYKMcWRsVb4ckWS3P5pPJZF3YfFhV4YD3eh6e7/F3lMf9ht8AuiqsmIiluA\nzsXf8xnFY3yQjxTJUIFmcocEQZ+PwPlLKZeEin7C0PjjSWZNPRzBDeTn8d4N\nnSEgKl+4LngRESLWdcJ16VA2V2NYpgoLyrGzvUuL/+0089cqC6tTeZESH8Jp\nn6CKV2Ru7sm7qbrAGhi9F7vDYrRuW6dgRVLubXekypRHKqhQxHb3+gFfAXrw\nV8FtbmYd9/hyYptU0qzp9dvonr2N0KKmH+8GeocNQfOPtoLdFZ1oR8EhGSfI\nRIfNUaUBTFnAuGWYzBt0rUi/MtzNwTPxuDh4KxiZgkzp/wlOdTlfyshTockf\nXxwMv9UDPoYJXYzl/d9KbvslRH/Py0H4Mk8AmBqsznN0WyLIIIAkMyTOj95J\nJ1wq\r\n=uGSh\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCICADxmKfvpuL066rIutZPQM7ZhmmKK37LQ+h6tUpblmcAiAB8KmRkhRHnzbJCY9JwS8/XVkougb7+ZVk3LQQt/EtAw=="}]},"maintainers":[{"name":"simon.friedo","email":"friedosimon@aol.com"},{"name":"soletan","email":"thomas.urban@cepharum.de"}],"_npmUser":{"name":"soletan","email":"thomas.urban@cepharum.de"},"directories":{},"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/js-i18n_0.0.8_1554806573047_0.8046565290021399"},"_hasShrinkwrap":false},"0.1.0-alpha.1":{"name":"@cepharum/js-i18n","version":"0.1.0-alpha.1","description":"an i18n service for Javascript","main":"index.js","private":false,"scripts":{"test":"mocha --ui=tdd test/**/*.spec.js","lint":"eslint ."},"repository":{"type":"git","url":"git+https://github.com/cepharum/js-i18n.git"},"keywords":["i18n","l10n"],"author":{"name":"cepharum GmbH"},"license":"MIT","bugs":{"url":"https://github.com/cepharum/js-i18n/issues"},"homepage":"https://github.com/cepharum/js-i18n#readme","devDependencies":{"eslint":"^5.11.1","eslint-config-cepharum":"^1.0.8","eslint-plugin-promise":"^4.0.1","mocha":"^5.2.0","should":"^13.2.3"},"readme":"# js-i18n\n\nan i18n service for Javascript\n\n## License\n\nMIT\n\n## About\n\nThis module provides a commonly useful implementation for handling i18n and l10n in Javascript-based applications. \n\n## Installation\n\n`npm i --save @cepharum/js-i18n`\n\n## Usage\n\nThis library has been created with VueJS in mind, but it is suitable to work with any other Javascript-based framework as well.\n\n### Translations\n\nTranslations are hierarchically organized in a tree of regular Javascript objects. Thus you may use a Javascript module or some JSON file to implement either set of translations.\n\n```javascript\n// German translations in a JS module\nmodule.exports = {\n\theader: {\n\t\theadline: \"Überschrift\",\n\t},\n\tHOME: {\n\t\tWELCOME: \"Herzlich Willkommen!\",\n\t},\n};\n```\n\n```json\n{\n\t\"header\": {\n\t\t\"headline\": \"Überschrift\"\n\t},\n\t\"HOME\": {\n\t\t\"WELCOME\": \"Herzlich Willkommen!\"\n\t}\n}\n```\n\n### Required: Setting up Supported Locales\n\nTranslations must be registered with provided Localizations Manager:\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\nimport TranslationsModule from \"./de.js\";\n\nLocalization.register( \"de\", TranslationsModule );\n```\n\nThis would require to explicitly load translations of all locales to be probably used. An advanced initialization is provided by using `Localization.initialize()`:\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.initialize( locale => import( `./${locale.language}` ) )\n\t.then( currentLocale => {\n\t\t// TODO start your application here\n\t} );\n```\n\nThis will try loading translations according to discovered sequence of locales accepted by current browser/user. In addition it helps with lazy-loading any translation:\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.initialize( locale => {\n\tswitch ( locale.language ) {\n\t\tcase \"de\" :\n\t\t\treturn import( /* webpackChunkName: \"de-de\" */ `./de.js` );\n\n\t\tdefault :\n\t\t\treturn import( `./${locale.language}.js` );\n\t}\n} )\n\t.then( currentLocale => {\n\t\t// TODO start your application here\n\t} );\n```\n\n### Looking Up\n\nThe current locale's translations are available using `Localization.current`. The method `lookup()` is searching the tree for a translation matching path name into tree provided in first argument:\n\n```javascript\nLocalization.current.lookup( \"@home.welcome\" );\n```\n\nUsing the translations above this will return \"Herzlich Willkommen!\".\n\n#### Look-Up Key Syntax\n\nAs you can see in example above the path name starts with a prefixing `@` which is followed by a period-separated sequence of one or more segments with each segment selecting property of next level in a tree of translations. Every such segment is processed case-insensitively and may consist of latin letters, digits, dash and underscore.\n\n```\n@<segment>.<segment>.<segment>\n```\n\nNeither length of path name nor the number of contained segments is limited.\n\n#### Looking Up Everything\n\nThe `lookup()` method is testing whether first argument complies with the format described before.\n\n* A well-formed look-up key is used to find a matching node in current locale's tree of translations. If there is no matching node in tree some provided fallback or `null` is returned instead.\n\n* On providing some string that does not comply with the syntax of a look-up key it is returned as-is. \n\nDistinguishing between look-up keys and arbitrary strings is designed to help with passing every string to conveniently localize as much internationalized strings as possible while keeping all non-internationalized strings untouched.\n\n#### Looking Up Threads of Tree\n\nUsually looking up translations is designed to result in a leaf of tree, thus returning a string. However, on using shorter look-up keys a thread may be addressed and thus gets returned instead:\n\n```javascript\nLocalization.current.lookup( \"@home\" );\n```\n\nThis will return\n\n```json\n{\n\t\"welcome\": \"Herzlich Willkommen!\"\n}\n``` \n\n#### Fallbacks\n\nYou can explicitly provide a fallback in second argument to be used in case of look up fails:\n\n```javascript\nLocalization.current.lookup( \"@home.subtitle\", \"We are happy to see you here!\" );\n```\n\nThis wil return \"We are happy to see you here!\" when used with translations given above.\n\nOptionally, fallback can be provided implicitly as part of look-up key:\n\n```javascript\nLocalization.current.lookup( \"@home.subtitle=We are here for you!\", \"We are happy to see you here!\" );\n```\n\nThis look-up key follows this basic syntax:\n\n```\n<look-up key> = <fallback>\n```\n\nThe previously introduced look-up key is extended by an assigment operator to mark start of implicit fallback string. The implicit fallback is always preferred over the explicitly provided one, so the example above will return \"We are here for you!\" on mismatching tree of translations.\n\nImplicit fallbacks may be arbitrary strings, but they can't be threads of tree. This limitation does not apply to explicit fallbacks. Thus, explicit fallbacks may be used with supporting different numeri and genera, as well.\n\n#### Looking up by Properties\nIn third argument you may provide an options object of properties of the subjects/objects to be described by translation. These are used to select a more specific translation. \n\nThe options Object has the following parameters:\n\n| parameter | type | remarks    |\n| ----------- | --- | --- |\n| number | int | number of addressed subjects in desired translation |\n| genus | string | explicitly required genus of translation |\n\n\n\n#### Numerus\n\nThe parameter number provides the number of subjects/objects to be described by translation. A locale-specific function is used internally to map the provided number of items onto the name of a numerus. This name is then used to select another level in tree of translations.\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.register( \"en\", {\n\tsearch: { result: {\n\t\tsingular: \"There is %d product matching all filter criteria.\",\n\t\tplural: \"There are %d products matching all filter criteria.\",\n\t} }\n} );\n\nLocalization.select( \"en\" );\n\nconst translated = Localization.lookup( \"@search.result\", null, { number: numSearchResults } );\n\nconsole.log( util.format( translated, numSearchResults ) );\n```\n\nIf value in `numSearchResults` is `1`, this lookup will return the string _There is %d product matching all filter criteria._. Otherwise it is returning the plural form _There are %d products matching all filter criteria._.\n\nThis basic support for numerus-aware translations doesn't support proper translations of sentences with multiple numerus-aware elements. Here the term _all filter criteria_ is always in its plural form even though it might be possible to have a different translation in case of user was applying single filter, only.\n\n#### Genus\n\nThe parameter gender provides the name of genus to be used to find translation depending on a subject's or an object's genus. There is no fixed set of supported names. In addition, the name isn't processed using some locale-specific function like numerus before. Thus you should decide to have a reasonable set of names used throughout your whole set of translations. We'd consider using genera `male` and `female` here.\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.register( \"en\", {\n\tmail: { action: { pickRecipient: {\n\t\tmale: \"Send him a mail.\",\n\t\tfemale: \"Send her a mail.\",\n\t} } }\n} );\n\nLocalization.select( \"en\" );\n\nconsole.log( Localization.lookup( \"@mail.action.pickRecipient\", null, { genus: gender } ) );\n```\n\nIf value in `genera` is `male`, this lookup will return the string _Send him a mail._ If value is `female` the returned string is _Send her a mail._ \n\nDue to the nature of looking up translations providing any other value for selecting genus results in a mismatch returning `null` unless providing fallback or having some _catch-all translation_:\n\n```\nLocalization.register( \"en\", {\n\tmail: { action: { pickRecipient: {\n\t\tmale: \"Send him a mail.\",\n\t\tfemale: \"Send her a mail.\",\n\t\t\"*\": \"Pick as recipient.\",\n\t} } }\n} );\n``` \n\n> Catch-all translations are supported for numerus and for genus, though this feature isn't considered stable and might be revised, replaced or removed in a future release.\n\n#### Combining Numerus and Genus\n\nYou can also combine look-up by numerus and by genus. The key should address a thread of your tree of translations just like before. This should handle numerus first, genus second:\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.register( \"en\", {\n\tpresent: { action: {\n\t\tsingular: {\n\t\t\tmale: \"Give him %d item.\",\n\t\t\tfemale: \"Give her %d item.\",\n\t\t},\n\t\tplural: {\n\t\t\tmale: \"Give him %d items.\",\n\t\t\tfemale: \"Give her %d items.\",\n\t\t},\n\t} }\n} );\n\nLocalization.select( \"en\" );\n\nconsole.log( Localization.lookup( \"@present.action\", null, { number: numItems, genus: gender } ) );\n```\n\n### Filtering in VueJS\n\nAs mentioned before this i18n library has been designed for use with VueJS applications. It comes with a function suitable as a [filter](https://vuejs.org/v2/guide/filters.html#ad) for VueJS.\n\nYou should register localization as early as possible. Here we inject it in application's **main.js** initializing localization prior to actually starting VueJS framework using `Localization.initialize()`:\n\n```javascript\nimport Vue from \"vue\";\n\nimport { Localization, Translate, Format } from \"@cepharum/js-i18n\";\n\nLocalization.initialize( locale => import( `../i18n/${locale.language}.js` ) )\n\t.then( () => {\n\t\tVue.filter( \"translate\", Translate );\n\t\tVue.filter( \"format\", Format );\n\n\t\tnew Vue( {\n\t\t\t...\n\t\t} ).$mount( \"#app\" );\n\t} )\n\t.catch( error => {\n\t\tconsole.error( error );\n\t} );\n```\n\nDue to this initialization filters `translate` and `format` are available in template of either component:\n\n```vue\n<h1>{{ '@Header.Title=Welcome!' | translate }}</h1>\n<p>{{ '@present.action=Give %d item(s) | translate( { number: numItems, genus: recipientGender } ) | format( numItems ) }}</p>\n```\n\n* Filter `translate` takes input string for looking up. Optional argument might be object providing number of items in property `number` and/or genus in property `genus`. The output is found translation, some fallback or provided string if it doesn't comply with look-up key syntax or on mismatch w/o provision of a fallback.\n\n* Filter `format` has been implemented to help with filling placeholders in a resulting translation. It uses a subset of printf syntax. Its arguments are consecutively used as values of encountered placeholders. Every placeholder starts with a percent sign and ends with a type marker. Between these two options may be inserted. The syntax is similar to this pattern:\n\n      '%' <fill> <width> <precision> <ref> <type marker>\n\n  | type marker | example | remarks    |\n  | ----------- | --- | --- |\n  | % | `%%` | Replaces placeholder with literal `%`. |\n  | s | `%s` | Inserts string value of next argument. |\n  | d | `%d` | Inserts integer numeric value of next argument. |\n  | x | `%x` | Inserts hexadecimal integer value of next argument using lowercase letters for digits a-f. |\n  | X | `%X` | Inserts hexadecimal integer value of next argument using uppercase letters for digits A-F. |\n  | f | `%f` | Inserts fixed-point numeric value of next argument. |\n  | . | `%.` | Consumes next argument replacing placeholder with empty string. |\n  \n  Placeholders are processed from left to right with each regular placeholder consuming another argument provided on calling filter `format`. The placeholder `%.` can be used to skip a single argument without generating any output. \n  \n  Another approach is using argument references. A reference consists of a dollar sign `$` followed by a positive integer value selecting argument in list of arguments by position with `1` referring to the first argument. Using a reference doesn't consume next argument. \n  \n  > **Example:** The placeholder `%$1s` requests to inject value of first argument as string no matter whether other placeholders might have consumed arguments before or not.\n  \n  The placeholder components `<fill>`, `<width>` and `<precision>` are all available to control vertical alignment of injected value:\n  \n  * `<width>` is a positive integer requesting to fill any value to generate at least this number of characters. Fill is applied left to the value, thus resulting in a right-aligned value.\n  \n  * `<precision>` is a positive integer requesting number of fractional digits to be displayed on decimal values. On all other types of placeholders this will result in a according number of space appended to the injected value to align it with decimal separator of decimal numbers.\n  \n  * The `<fill>` might be period, dash, underscore, space or `0`. It is selecting what character is used to fill value on behalf of `<width>`.\n  \n  In opposition to regular printf syntax `<width>` and `<precision>` are handled separately and thus `<width>` doesn't cover `<precision>`. The resulting width of a generated output is the sum of `<width>` and `<precision>` plus 1 for the separator in case of actually using `<precision>`.\n  \n  The `<sep>` is either `.` or `,` and controls what separator is used on processing decimal values.\n  \n  > **Examples:**\n  >\n  > * `%s` with `Hello` generates `Hello`.\n  > * `%8s` with `Hello` generates `Hello` with 3 additional spaces to the left.\n  > * `%4.2d` with `132.7865` generates `132.79` with 1 additional space to the left.\n  > * `%,2d` with `132.7865` generates `132,79`.\n  > * `%06,2d` with `132.7865` generates `000132,79`.\n","readmeFilename":"README.md","gitHead":"437954bcd25558d871b3ef46492c0288b478a9c7","_id":"@cepharum/js-i18n@0.1.0-alpha.1","_nodeVersion":"14.15.4","_npmVersion":"6.14.10","dist":{"integrity":"sha512-4CclVZt5HXRrO2rzDRmR21V1NsPFstvrmjzGIpz+dZXknjov24pcYxZD/b+BS+7L0qZNbtgbxCluPW2O0YgneA==","shasum":"26a42c55939535de20ff6d182b2175937431621e","tarball":"https://registry.npmjs.org/@cepharum/js-i18n/-/js-i18n-0.1.0-alpha.1.tgz","fileCount":12,"unpackedSize":63056,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgSPQ0CRA9TVsSAnZWagAA7FMP/RHTJy612pzQyiMbmPXL\n3xHTX2oxRUYqjOVit8Kwve31YKbZaSRLT2MQ/n4sb0wikYciy+9HTTVD8x3C\nOYz4nUIr5dIVdlG2I2ptAKwweCIo+YNVTJfFX0U84evX5eqqGNLNcStLl4/f\npJA5/12iQfoJiniQ5SwM241a+QW+mahgp2ZbtgWgzvLwfv82VjNORF34/VBy\nqzY8Ph+CrO9YloZYlCuYlpKp+AK8QOszjD8GqAcEBZav/3Y2MLLlrvFAbB6Q\nIS+n3b7YFnyNVmj8uBMa3dIUFchklmvmX9+CsxINuVHTsBndKi3EK1tX1sNp\nwAT7G6bQ4Xs7IUBQpjnfaWqTx/IoivYdKPNUFUsuKAdDeFz8acjHKxZpBN2S\ndT9m9mZxDjFXUZod8oTdjTdSBWBc2k3mHs/HMVB7zH+sHryq+Bst7IkqbHB4\nBsYbfSALpBetXR235lVYusgL/MzweVH1kLVkF7JxR7u7icDSYzWQSaYkXZDF\n22HlwgDT01Gt1dfqMOpd4UDad/w5+qRZJ/v6s2SuSLRSTF56SyXdRkZ1ke8U\nq7Kx9MjkUuzdVqOg9K8L3ulpoh55iXP7VXNaqc9BX+L89Bd9wt4R4MNab8gZ\nLq0DGaoepu1IJLH+mtEdt3PdMnodAQ2MAMiaK4DABYm7CCAi3wR1AR3PdVWp\n27yC\r\n=fqJU\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFf01mjtQfIpvz9QW2+0DaBrafvUFtYNBVr0b+cC15W4AiEA+vwjLI4tqSjIzECR0laBmxsR3PQ0rB5LuODQkUPcHUc="}]},"_npmUser":{"name":"simon.friedo","email":"friedosimon@aol.com"},"directories":{},"maintainers":[{"name":"soletan","email":"thomas.urban@cepharum.de"},{"name":"simon.friedo","email":"friedosimon@aol.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/js-i18n_0.1.0-alpha.1_1615393844085_0.06648563898859261"},"_hasShrinkwrap":false},"0.1.0-alpha.2":{"name":"@cepharum/js-i18n","version3":"0.1.0-alpha.1","description":"an i18n service for Javascript","main":"index.js","private":false,"scripts":{"test":"mocha --ui=tdd test/**/*.spec.js","coverage":"nyc --reporter=html --reporter=text mocha --ui tdd test/**/*.spec.js","lint":"eslint ."},"repository":{"type":"git","url":"git+https: //github.com/cepharum/js-i18n.git"},"keywords":["i18n","l10n"],"author":{"name":"cepharum GmbH"},"license":"MIT","bugs":{"url":"https://github.com/cepharum/js-i18n/issues"},"homepage":"https://github.com/cepharum/js-i18n#readme","devDependencies":{"eslint":"^5.11.1","eslint-config-cepharum":"^1.0.8","eslint-plugin-promise":"^4.0.1","mocha":"^5.2.0","nyc":"^15.0.1","should":"^13.2.3"},"version":"0.1.0-alpha.2","readme":"# js-i18n\n\nan i18n service for Javascript\n\n## License\n\nMIT\n\n## About\n\nThis module provides a commonly useful implementation for handling i18n and l10n in Javascript-based applications. \n\n## Installation\n\n`npm i --save @cepharum/js-i18n`\n\n## Usage\n\nThis library has been created with VueJS in mind, but it is suitable to work with any other Javascript-based framework as well.\n\n### Translations\n\nTranslations are hierarchically organized in a tree of regular Javascript objects. Thus you may use a Javascript module or some JSON file to implement either set of translations.\n\n```javascript\n// German translations in a JS module\nmodule.exports = {\n\theader: {\n\t\theadline: \"Überschrift\",\n\t},\n\tHOME: {\n\t\tWELCOME: \"Herzlich Willkommen!\",\n\t},\n};\n```\n\n```json\n{\n\t\"header\": {\n\t\t\"headline\": \"Überschrift\"\n\t},\n\t\"HOME\": {\n\t\t\"WELCOME\": \"Herzlich Willkommen!\"\n\t}\n}\n```\n\n### Required: Setting up Supported Locales\n\nTranslations must be registered with provided Localizations Manager:\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\nimport TranslationsModule from \"./de.js\";\n\nLocalization.register( \"de\", TranslationsModule );\n```\n\nThis would require to explicitly load translations of all locales to be probably used. An advanced initialization is provided by using `Localization.initialize()`:\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.initialize( locale => import( `./${locale.language}` ) )\n\t.then( currentLocale => {\n\t\t// TODO start your application here\n\t} );\n```\n\nThis will try loading translations according to discovered sequence of locales accepted by current browser/user. In addition it helps with lazy-loading any translation:\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.initialize( locale => {\n\tswitch ( locale.language ) {\n\t\tcase \"de\" :\n\t\t\treturn import( /* webpackChunkName: \"de-de\" */ `./de.js` );\n\n\t\tdefault :\n\t\t\treturn import( `./${locale.language}.js` );\n\t}\n} )\n\t.then( currentLocale => {\n\t\t// TODO start your application here\n\t} );\n```\n\n### Looking Up\n\nThe current locale's translations are available using `Localization.current`. The method `lookup()` is searching the tree for a translation matching path name into tree provided in first argument:\n\n```javascript\nLocalization.current.lookup( \"@home.welcome\" );\n```\n\nUsing the translations above this will return \"Herzlich Willkommen!\".\n\n#### Look-Up Key Syntax\n\nAs you can see in example above the path name starts with a prefixing `@` which is followed by a period-separated sequence of one or more segments with each segment selecting property of next level in a tree of translations. Every such segment is processed case-insensitively and may consist of latin letters, digits, dash and underscore.\n\n```\n@<segment>.<segment>.<segment>\n```\n\nNeither length of path name nor the number of contained segments is limited.\n\n#### Looking Up Everything\n\nThe `lookup()` method is testing whether first argument complies with the format described before.\n\n* A well-formed look-up key is used to find a matching node in current locale's tree of translations. If there is no matching node in tree some provided fallback or `null` is returned instead.\n\n* On providing some string that does not comply with the syntax of a look-up key it is returned as-is. \n\nDistinguishing between look-up keys and arbitrary strings is designed to help with passing every string to conveniently localize as much internationalized strings as possible while keeping all non-internationalized strings untouched.\n\n#### Looking Up Threads of Tree\n\nUsually looking up translations is designed to result in a leaf of tree, thus returning a string. However, on using shorter look-up keys a thread may be addressed and thus gets returned instead:\n\n```javascript\nLocalization.current.lookup( \"@home\" );\n```\n\nThis will return\n\n```json\n{\n\t\"welcome\": \"Herzlich Willkommen!\"\n}\n``` \n\n#### Fallbacks\n\nYou can explicitly provide a fallback in second argument to be used in case of look up fails:\n\n```javascript\nLocalization.current.lookup( \"@home.subtitle\", \"We are happy to see you here!\" );\n```\n\nThis wil return \"We are happy to see you here!\" when used with translations given above.\n\nOptionally, fallback can be provided implicitly as part of look-up key:\n\n```javascript\nLocalization.current.lookup( \"@home.subtitle=We are here for you!\", \"We are happy to see you here!\" );\n```\n\nThis look-up key follows this basic syntax:\n\n```\n<look-up key> = <fallback>\n```\n\nThe previously introduced look-up key is extended by an assigment operator to mark start of implicit fallback string. The implicit fallback is always preferred over the explicitly provided one, so the example above will return \"We are here for you!\" on mismatching tree of translations.\n\nImplicit fallbacks may be arbitrary strings, but they can't be threads of tree. This limitation does not apply to explicit fallbacks. Thus, explicit fallbacks may be used with supporting different numeri and genera, as well.\n\n#### Looking up by Properties\nIn third argument you may provide an options object of properties of the subjects/objects to be described by translation. These are used to select a more specific translation. \n\nThe options Object has the following parameters:\n\n| parameter | type | remarks    |\n| ----------- | --- | --- |\n| number | int | number of addressed subjects in desired translation |\n| genus | string | explicitly required genus of translation |\n\n\n\n#### Numerus\n\nThe parameter number provides the number of subjects/objects to be described by translation. A locale-specific function is used internally to map the provided number of items onto the name of a numerus. This name is then used to select another level in tree of translations.\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.register( \"en\", {\n\tsearch: { result: {\n\t\tsingular: \"There is %d product matching all filter criteria.\",\n\t\tplural: \"There are %d products matching all filter criteria.\",\n\t} }\n} );\n\nLocalization.select( \"en\" );\n\nconst translated = Localization.lookup( \"@search.result\", null, { number: numSearchResults } );\n\nconsole.log( util.format( translated, numSearchResults ) );\n```\n\nIf value in `numSearchResults` is `1`, this lookup will return the string _There is %d product matching all filter criteria._. Otherwise it is returning the plural form _There are %d products matching all filter criteria._.\n\nThis basic support for numerus-aware translations doesn't support proper translations of sentences with multiple numerus-aware elements. Here the term _all filter criteria_ is always in its plural form even though it might be possible to have a different translation in case of user was applying single filter, only.\n\n#### Genus\n\nThe parameter gender provides the name of genus to be used to find translation depending on a subject's or an object's genus. There is no fixed set of supported names. In addition, the name isn't processed using some locale-specific function like numerus before. Thus you should decide to have a reasonable set of names used throughout your whole set of translations. We'd consider using genera `male` and `female` here.\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.register( \"en\", {\n\tmail: { action: { pickRecipient: {\n\t\tmale: \"Send him a mail.\",\n\t\tfemale: \"Send her a mail.\",\n\t} } }\n} );\n\nLocalization.select( \"en\" );\n\nconsole.log( Localization.lookup( \"@mail.action.pickRecipient\", null, { genus: gender } ) );\n```\n\nIf value in `genera` is `male`, this lookup will return the string _Send him a mail._ If value is `female` the returned string is _Send her a mail._ \n\nDue to the nature of looking up translations providing any other value for selecting genus results in a mismatch returning `null` unless providing fallback or having some _catch-all translation_:\n\n```\nLocalization.register( \"en\", {\n\tmail: { action: { pickRecipient: {\n\t\tmale: \"Send him a mail.\",\n\t\tfemale: \"Send her a mail.\",\n\t\t\"*\": \"Pick as recipient.\",\n\t} } }\n} );\n``` \n\n> Catch-all translations are supported for numerus and for genus, though this feature isn't considered stable and might be revised, replaced or removed in a future release.\n\n#### Combining Numerus and Genus\n\nYou can also combine look-up by numerus and by genus. The key should address a thread of your tree of translations just like before. This should handle numerus first, genus second:\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.register( \"en\", {\n\tpresent: { action: {\n\t\tsingular: {\n\t\t\tmale: \"Give him %d item.\",\n\t\t\tfemale: \"Give her %d item.\",\n\t\t},\n\t\tplural: {\n\t\t\tmale: \"Give him %d items.\",\n\t\t\tfemale: \"Give her %d items.\",\n\t\t},\n\t} }\n} );\n\nLocalization.select( \"en\" );\n\nconsole.log( Localization.lookup( \"@present.action\", null, { number: numItems, genus: gender } ) );\n```\n\n### Filtering in VueJS\n\nAs mentioned before this i18n library has been designed for use with VueJS applications. It comes with a function suitable as a [filter](https://vuejs.org/v2/guide/filters.html#ad) for VueJS.\n\nYou should register localization as early as possible. Here we inject it in application's **main.js** initializing localization prior to actually starting VueJS framework using `Localization.initialize()`:\n\n```javascript\nimport Vue from \"vue\";\n\nimport { Localization, Translate, Format } from \"@cepharum/js-i18n\";\n\nLocalization.initialize( locale => import( `../i18n/${locale.language}.js` ) )\n\t.then( () => {\n\t\tVue.filter( \"translate\", Translate );\n\t\tVue.filter( \"format\", Format );\n\n\t\tnew Vue( {\n\t\t\t...\n\t\t} ).$mount( \"#app\" );\n\t} )\n\t.catch( error => {\n\t\tconsole.error( error );\n\t} );\n```\n\nDue to this initialization filters `translate` and `format` are available in template of either component:\n\n```vue\n<h1>{{ '@Header.Title=Welcome!' | translate }}</h1>\n<p>{{ '@present.action=Give %d item(s) | translate( { number: numItems, genus: recipientGender } ) | format( numItems ) }}</p>\n```\n\n* Filter `translate` takes input string for looking up. Optional argument might be object providing number of items in property `number` and/or genus in property `genus`. The output is found translation, some fallback or provided string if it doesn't comply with look-up key syntax or on mismatch w/o provision of a fallback.\n\n* Filter `format` has been implemented to help with filling placeholders in a resulting translation. It uses a subset of printf syntax. Its arguments are consecutively used as values of encountered placeholders. Every placeholder starts with a percent sign and ends with a type marker. Between these two options may be inserted. The syntax is similar to this pattern:\n\n      '%' <fill> <width> <precision> <ref> <type marker>\n\n  | type marker | example | remarks    |\n  | ----------- | --- | --- |\n  | % | `%%` | Replaces placeholder with literal `%`. |\n  | s | `%s` | Inserts string value of next argument. |\n  | d | `%d` | Inserts integer numeric value of next argument. |\n  | x | `%x` | Inserts hexadecimal integer value of next argument using lowercase letters for digits a-f. |\n  | X | `%X` | Inserts hexadecimal integer value of next argument using uppercase letters for digits A-F. |\n  | f | `%f` | Inserts fixed-point numeric value of next argument. |\n  | . | `%.` | Consumes next argument replacing placeholder with empty string. |\n  \n  Placeholders are processed from left to right with each regular placeholder consuming another argument provided on calling filter `format`. The placeholder `%.` can be used to skip a single argument without generating any output. \n  \n  Another approach is using argument references. A reference consists of a dollar sign `$` followed by a positive integer value selecting argument in list of arguments by position with `1` referring to the first argument. Using a reference doesn't consume next argument. \n  \n  > **Example:** The placeholder `%$1s` requests to inject value of first argument as string no matter whether other placeholders might have consumed arguments before or not.\n  \n  The placeholder components `<fill>`, `<width>` and `<precision>` are all available to control vertical alignment of injected value:\n  \n  * `<width>` is a positive integer requesting to fill any value to generate at least this number of characters. Fill is applied left to the value, thus resulting in a right-aligned value.\n  \n  * `<precision>` is a positive integer requesting number of fractional digits to be displayed on decimal values. On all other types of placeholders this will result in a according number of space appended to the injected value to align it with decimal separator of decimal numbers.\n  \n  * The `<fill>` might be period, dash, underscore, space or `0`. It is selecting what character is used to fill value on behalf of `<width>`.\n  \n  In opposition to regular printf syntax `<width>` and `<precision>` are handled separately and thus `<width>` doesn't cover `<precision>`. The resulting width of a generated output is the sum of `<width>` and `<precision>` plus 1 for the separator in case of actually using `<precision>`.\n  \n  The `<sep>` is either `.` or `,` and controls what separator is used on processing decimal values.\n  \n  > **Examples:**\n  >\n  > * `%s` with `Hello` generates `Hello`.\n  > * `%8s` with `Hello` generates `Hello` with 3 additional spaces to the left.\n  > * `%4.2d` with `132.7865` generates `132.79` with 1 additional space to the left.\n  > * `%,2d` with `132.7865` generates `132,79`.\n  > * `%06,2d` with `132.7865` generates `000132,79`.\n","readmeFilename":"README.md","gitHead":"c7727293c339a6a3e4aa5d5fed849340ff55cb8f","_id":"@cepharum/js-i18n@0.1.0-alpha.2","_nodeVersion":"14.15.4","_npmVersion":"7.6.3","dist":{"integrity":"sha512-A/rP8k35YbDEen3nnNk4bBOKKnpVwcLT0S5ssFGUZn7jnloQk6V6AHt4iTafmtHyplEKWqcKl/r4pBdC36k5+Q==","shasum":"d044cf2d7a7b02c58314e4670dcf5b09a16bd04f","tarball":"https://registry.npmjs.org/@cepharum/js-i18n/-/js-i18n-0.1.0-alpha.2.tgz","fileCount":20,"unpackedSize":148018,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgbXC9CRA9TVsSAnZWagAAA6kP/05UvyvCHsjxpqgBavLc\nNM/KCkPlucON65hX81UMcuVsWGv4mysenmxx857xXi5ebvg+fQKBGe/LK8C8\n4MczfZBwfJ6LdudOwiMqdcZLIlXZUcX4tSqTnvMAfCnSnDdS8OBDPmPA1uaF\nC8sUkopezetIrcV/224B/DBzyQJqut3+cUcKMvHhAMXA0pgSzuPRuZ+a8Zhf\n50TmGizpFdtFYsZgpBnihQIajyfNs3zgFdvclwy6p+tnIXv5yllxtw4NHSKg\nnKtHgD/gmQbGedC3AAvzrsAR07oCvhU6kC5k12cnoEfXAz8iRbI2u4C8FK6R\nZwRbuzTupbK+SU7hFzxr2ezsjrJy32x564cTS+myo3uDXwQa9IzZYgQ5HyCY\nJVgqn4uvP4kkrpMENZ7wXRXVIonO1zJY+xpe9sTPbF7G4Oba9YZbr99TDI0B\nSjFJdB46Vks7jZIZ15w1FVCKppQNM+dNL7t3XGHs+44Zu/45KgC5z4LTJ+XN\nbvtbJmQQDHk4mKVFd7wi1o8oEVKyn2MTmyH6VA8qxSVB48+1bTOVCJLHxuMj\n6xkwRbE/H3Lwn0yQ8VCH/nywOJ1jUp/5/iMyJIHddLKHUfRL/3gHHnKL2NNG\nZvuo4RYoq4naHB5y/MH312KMu80mA8CXjNw8JkfSaqpKSskK/efIHTNd2GqL\nbhe6\r\n=LPWw\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDlRkaSfM3GeoYvmRVJWafonWP5bKx2Iei+8nBD5+k3jwIgHmQ6R8woe40bEscvRj/9bjHzqoUtaegqdVwXMpYlWug="}]},"_npmUser":{"name":"simon.friedo","email":"friedosimon@aol.com"},"directories":{},"maintainers":[{"name":"soletan","email":"thomas.urban@cepharum.de"},{"name":"simon.friedo","email":"friedosimon@aol.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/js-i18n_0.1.0-alpha.2_1617785021414_0.9858406754086986"},"_hasShrinkwrap":false},"0.1.0-alpha.3":{"name":"@cepharum/js-i18n","version3":"0.1.0-alpha.1","description":"an i18n service for Javascript","main":"index.js","private":false,"scripts":{"test":"mocha --ui=tdd test/**/*.spec.js","coverage":"nyc --reporter=html --reporter=text mocha --ui tdd test/**/*.spec.js","lint":"eslint ."},"repository":{"type":"git","url":"git+https: //github.com/cepharum/js-i18n.git"},"keywords":["i18n","l10n"],"author":{"name":"cepharum GmbH"},"license":"MIT","bugs":{"url":"https://github.com/cepharum/js-i18n/issues"},"homepage":"https://github.com/cepharum/js-i18n#readme","devDependencies":{"eslint":"^5.11.1","eslint-config-cepharum":"^1.0.8","eslint-plugin-promise":"^4.0.1","mocha":"^5.2.0","nyc":"^15.0.1","should":"^13.2.3"},"version":"0.1.0-alpha.3","readme":"# js-i18n\n\nan i18n service for Javascript\n\n## License\n\nMIT\n\n## About\n\nThis module provides a commonly useful implementation for handling i18n and l10n in Javascript-based applications. \n\n## Installation\n\n`npm i --save @cepharum/js-i18n`\n\n## Usage\n\nThis library has been created with VueJS in mind, but it is suitable to work with any other Javascript-based framework as well.\n\n### Translations\n\nTranslations are hierarchically organized in a tree of regular Javascript objects. Thus you may use a Javascript module or some JSON file to implement either set of translations.\n\n```javascript\n// German translations in a JS module\nmodule.exports = {\n\theader: {\n\t\theadline: \"Überschrift\",\n\t},\n\tHOME: {\n\t\tWELCOME: \"Herzlich Willkommen!\",\n\t},\n};\n```\n\n```json\n{\n\t\"header\": {\n\t\t\"headline\": \"Überschrift\"\n\t},\n\t\"HOME\": {\n\t\t\"WELCOME\": \"Herzlich Willkommen!\"\n\t}\n}\n```\n\n### Required: Setting up Supported Locales\n\nTranslations must be registered with provided Localizations Manager:\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\nimport TranslationsModule from \"./de.js\";\n\nLocalization.register( \"de\", TranslationsModule );\n```\n\nThis would require to explicitly load translations of all locales to be probably used. An advanced initialization is provided by using `Localization.initialize()`:\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.initialize( locale => import( `./${locale.language}` ) )\n\t.then( currentLocale => {\n\t\t// TODO start your application here\n\t} );\n```\n\nThis will try loading translations according to discovered sequence of locales accepted by current browser/user. In addition it helps with lazy-loading any translation:\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.initialize( locale => {\n\tswitch ( locale.language ) {\n\t\tcase \"de\" :\n\t\t\treturn import( /* webpackChunkName: \"de-de\" */ `./de.js` );\n\n\t\tdefault :\n\t\t\treturn import( `./${locale.language}.js` );\n\t}\n} )\n\t.then( currentLocale => {\n\t\t// TODO start your application here\n\t} );\n```\n\n### Looking Up\n\nThe current locale's translations are available using `Localization.current`. The method `lookup()` is searching the tree for a translation matching path name into tree provided in first argument:\n\n```javascript\nLocalization.current.lookup( \"@home.welcome\" );\n```\n\nUsing the translations above this will return \"Herzlich Willkommen!\".\n\n#### Look-Up Key Syntax\n\nAs you can see in example above the path name starts with a prefixing `@` which is followed by a period-separated sequence of one or more segments with each segment selecting property of next level in a tree of translations. Every such segment is processed case-insensitively and may consist of latin letters, digits, dash and underscore.\n\n```\n@<segment>.<segment>.<segment>\n```\n\nNeither length of path name nor the number of contained segments is limited.\n\n#### Looking Up Everything\n\nThe `lookup()` method is testing whether first argument complies with the format described before.\n\n* A well-formed look-up key is used to find a matching node in current locale's tree of translations. If there is no matching node in tree some provided fallback or `null` is returned instead.\n\n* On providing some string that does not comply with the syntax of a look-up key it is returned as-is. \n\nDistinguishing between look-up keys and arbitrary strings is designed to help with passing every string to conveniently localize as much internationalized strings as possible while keeping all non-internationalized strings untouched.\n\n#### Looking Up Threads of Tree\n\nUsually looking up translations is designed to result in a leaf of tree, thus returning a string. However, on using shorter look-up keys a thread may be addressed and thus gets returned instead:\n\n```javascript\nLocalization.current.lookup( \"@home\" );\n```\n\nThis will return\n\n```json\n{\n\t\"welcome\": \"Herzlich Willkommen!\"\n}\n``` \n\n#### Fallbacks\n\nYou can explicitly provide a fallback in second argument to be used in case of look up fails:\n\n```javascript\nLocalization.current.lookup( \"@home.subtitle\", \"We are happy to see you here!\" );\n```\n\nThis wil return \"We are happy to see you here!\" when used with translations given above.\n\nOptionally, fallback can be provided implicitly as part of look-up key:\n\n```javascript\nLocalization.current.lookup( \"@home.subtitle=We are here for you!\", \"We are happy to see you here!\" );\n```\n\nThis look-up key follows this basic syntax:\n\n```\n<look-up key> = <fallback>\n```\n\nThe previously introduced look-up key is extended by an assigment operator to mark start of implicit fallback string. The implicit fallback is always preferred over the explicitly provided one, so the example above will return \"We are here for you!\" on mismatching tree of translations.\n\nImplicit fallbacks may be arbitrary strings, but they can't be threads of tree. This limitation does not apply to explicit fallbacks. Thus, explicit fallbacks may be used with supporting different numeri and genera, as well.\n\n#### Looking up by Properties\nIn third argument you may provide an options object of properties of the subjects/objects to be described by translation. These are used to select a more specific translation. \n\nThe options Object has the following parameters:\n\n| parameter | type | remarks    |\n| ----------- | --- | --- |\n| number | int | number of addressed subjects in desired translation |\n| genus | string | explicitly required genus of translation |\n\n\n\n#### Numerus\n\nThe parameter number provides the number of subjects/objects to be described by translation. A locale-specific function is used internally to map the provided number of items onto the name of a numerus. This name is then used to select another level in tree of translations.\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.register( \"en\", {\n\tsearch: { result: {\n\t\tsingular: \"There is %d product matching all filter criteria.\",\n\t\tplural: \"There are %d products matching all filter criteria.\",\n\t} }\n} );\n\nLocalization.select( \"en\" );\n\nconst translated = Localization.lookup( \"@search.result\", null, { number: numSearchResults } );\n\nconsole.log( util.format( translated, numSearchResults ) );\n```\n\nIf value in `numSearchResults` is `1`, this lookup will return the string _There is %d product matching all filter criteria._. Otherwise it is returning the plural form _There are %d products matching all filter criteria._.\n\nThis basic support for numerus-aware translations doesn't support proper translations of sentences with multiple numerus-aware elements. Here the term _all filter criteria_ is always in its plural form even though it might be possible to have a different translation in case of user was applying single filter, only.\n\n#### Genus\n\nThe parameter gender provides the name of genus to be used to find translation depending on a subject's or an object's genus. There is no fixed set of supported names. In addition, the name isn't processed using some locale-specific function like numerus before. Thus you should decide to have a reasonable set of names used throughout your whole set of translations. We'd consider using genera `male` and `female` here.\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.register( \"en\", {\n\tmail: { action: { pickRecipient: {\n\t\tmale: \"Send him a mail.\",\n\t\tfemale: \"Send her a mail.\",\n\t} } }\n} );\n\nLocalization.select( \"en\" );\n\nconsole.log( Localization.lookup( \"@mail.action.pickRecipient\", null, { genus: gender } ) );\n```\n\nIf value in `genera` is `male`, this lookup will return the string _Send him a mail._ If value is `female` the returned string is _Send her a mail._ \n\nDue to the nature of looking up translations providing any other value for selecting genus results in a mismatch returning `null` unless providing fallback or having some _catch-all translation_:\n\n```\nLocalization.register( \"en\", {\n\tmail: { action: { pickRecipient: {\n\t\tmale: \"Send him a mail.\",\n\t\tfemale: \"Send her a mail.\",\n\t\t\"*\": \"Pick as recipient.\",\n\t} } }\n} );\n``` \n\n> Catch-all translations are supported for numerus and for genus, though this feature isn't considered stable and might be revised, replaced or removed in a future release.\n\n#### Combining Numerus and Genus\n\nYou can also combine look-up by numerus and by genus. The key should address a thread of your tree of translations just like before. This should handle numerus first, genus second:\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.register( \"en\", {\n\tpresent: { action: {\n\t\tsingular: {\n\t\t\tmale: \"Give him %d item.\",\n\t\t\tfemale: \"Give her %d item.\",\n\t\t},\n\t\tplural: {\n\t\t\tmale: \"Give him %d items.\",\n\t\t\tfemale: \"Give her %d items.\",\n\t\t},\n\t} }\n} );\n\nLocalization.select( \"en\" );\n\nconsole.log( Localization.lookup( \"@present.action\", null, { number: numItems, genus: gender } ) );\n```\n\n### Filtering in VueJS\n\nAs mentioned before this i18n library has been designed for use with VueJS applications. It comes with a function suitable as a [filter](https://vuejs.org/v2/guide/filters.html#ad) for VueJS.\n\nYou should register localization as early as possible. Here we inject it in application's **main.js** initializing localization prior to actually starting VueJS framework using `Localization.initialize()`:\n\n```javascript\nimport Vue from \"vue\";\n\nimport { Localization, Translate, Format } from \"@cepharum/js-i18n\";\n\nLocalization.initialize( locale => import( `../i18n/${locale.language}.js` ) )\n\t.then( () => {\n\t\tVue.filter( \"translate\", Translate );\n\t\tVue.filter( \"format\", Format );\n\n\t\tnew Vue( {\n\t\t\t...\n\t\t} ).$mount( \"#app\" );\n\t} )\n\t.catch( error => {\n\t\tconsole.error( error );\n\t} );\n```\n\nDue to this initialization filters `translate` and `format` are available in template of either component:\n\n```vue\n<h1>{{ '@Header.Title=Welcome!' | translate }}</h1>\n<p>{{ '@present.action=Give %d item(s) | translate( { number: numItems, genus: recipientGender } ) | format( numItems ) }}</p>\n```\n\n* Filter `translate` takes input string for looking up. Optional argument might be object providing number of items in property `number` and/or genus in property `genus`. The output is found translation, some fallback or provided string if it doesn't comply with look-up key syntax or on mismatch w/o provision of a fallback.\n\n* Filter `format` has been implemented to help with filling placeholders in a resulting translation. It uses a subset of printf syntax. Its arguments are consecutively used as values of encountered placeholders. Every placeholder starts with a percent sign and ends with a type marker. Between these two options may be inserted. The syntax is similar to this pattern:\n\n      '%' <fill> <width> <precision> <ref> <type marker>\n\n  | type marker | example | remarks    |\n  | ----------- | --- | --- |\n  | % | `%%` | Replaces placeholder with literal `%`. |\n  | s | `%s` | Inserts string value of next argument. |\n  | d | `%d` | Inserts integer numeric value of next argument. |\n  | x | `%x` | Inserts hexadecimal integer value of next argument using lowercase letters for digits a-f. |\n  | X | `%X` | Inserts hexadecimal integer value of next argument using uppercase letters for digits A-F. |\n  | f | `%f` | Inserts fixed-point numeric value of next argument. |\n  | . | `%.` | Consumes next argument replacing placeholder with empty string. |\n  \n  Placeholders are processed from left to right with each regular placeholder consuming another argument provided on calling filter `format`. The placeholder `%.` can be used to skip a single argument without generating any output. \n  \n  Another approach is using argument references. A reference consists of a dollar sign `$` followed by a positive integer value selecting argument in list of arguments by position with `1` referring to the first argument. Using a reference doesn't consume next argument. \n  \n  > **Example:** The placeholder `%$1s` requests to inject value of first argument as string no matter whether other placeholders might have consumed arguments before or not.\n  \n  The placeholder components `<fill>`, `<width>` and `<precision>` are all available to control vertical alignment of injected value:\n  \n  * `<width>` is a positive integer requesting to fill any value to generate at least this number of characters. Fill is applied left to the value, thus resulting in a right-aligned value.\n  \n  * `<precision>` is a positive integer requesting number of fractional digits to be displayed on decimal values. On all other types of placeholders this will result in a according number of space appended to the injected value to align it with decimal separator of decimal numbers.\n  \n  * The `<fill>` might be period, dash, underscore, space or `0`. It is selecting what character is used to fill value on behalf of `<width>`.\n  \n  In opposition to regular printf syntax `<width>` and `<precision>` are handled separately and thus `<width>` doesn't cover `<precision>`. The resulting width of a generated output is the sum of `<width>` and `<precision>` plus 1 for the separator in case of actually using `<precision>`.\n  \n  The `<sep>` is either `.` or `,` and controls what separator is used on processing decimal values.\n  \n  > **Examples:**\n  >\n  > * `%s` with `Hello` generates `Hello`.\n  > * `%8s` with `Hello` generates `Hello` with 3 additional spaces to the left.\n  > * `%4.2d` with `132.7865` generates `132.79` with 1 additional space to the left.\n  > * `%,2d` with `132.7865` generates `132,79`.\n  > * `%06,2d` with `132.7865` generates `000132,79`.\n","readmeFilename":"README.md","gitHead":"3664e6606e7ab7ded7f00b8ea8525eb5dd1a8d46","_id":"@cepharum/js-i18n@0.1.0-alpha.3","_nodeVersion":"14.15.4","_npmVersion":"7.13.0","dist":{"integrity":"sha512-6WK+vOvO8rSktwQdhLC9pAqC0BxCWZsyzW+xLcUY102H7dxigL8T9KEOuBG0j5uYv7WoSZQ2UpYkXxa3uRZ6FA==","shasum":"219aab9d6f93a3fa8333080f27bb8f4cb81be924","tarball":"https://registry.npmjs.org/@cepharum/js-i18n/-/js-i18n-0.1.0-alpha.3.tgz","fileCount":20,"unpackedSize":148984,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhLJ99CRA9TVsSAnZWagAAnZsP/A+rZlPHAttfpAZWw4lB\nyzyhXLYliUsNwtafBQCOgkBF4ndt2tdo23zlYpX6RyXVNjzm58uri2iZBRqd\nb3DdYZxzroAe/CMd1PDm8aS5pXm6SrENEIOyKM/GWqMMFWsbGd5x1bgRKaWF\nGFM3gcunLNobuYr7rsaVAxoe2wwdYIBTWTYDElDOoBmIBqN1Z5xmCvIJQVdj\nqQ/V2uTwlpvBA3oB+uS0uNJpo3iQiYh40HAtnSmFLyDcrIPLRfraQAPfBVsI\nPa6uzqhkBp8cr2iIXYtcgKoyb+q1RyHyZd860d9lI1We5UFeq3PtwUJX5ZGl\nFi0ZQbASd8qfzpWCqIMBS+3HT6yDSHDHQ1+uAxmhVOPFpWnDvXluFn3uFabx\niUd6qnc6+333/+7Loqq0XEzltjLTctNGMpre7bVKTUhu8Mr815zoi2rg2WdK\ndBxN0nhXzNz5yabHw/7nqiXKqTE0wY0lg+L3YFBaxhHRDi4cGG21Fb1V8byd\niYfRsK1Ai0zVJTh6d4fzW4hypdJA3HV2PhXQwsZwylhewLdjW0zEu0KZSimj\nN7NP9qC/X7lYrXmzpexsQNACB1w9lHy+13dgrFtlfb5FCiE4n/ewlpAIozOU\nPMoOVgeoNjkOLzseSkBIQ7Xd8pWx8FZp7O3c2Pu+HaGN3s4HHLj9IgSYaiLN\nC1Ie\r\n=eZPj\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIAIzWS2PcUHb+tfVrfiF8yzz+gGA/iQSyB2Ba7UTl/LdAiEAtGBO6EXe9ibkeqbCBiRVVC/xnLp2F+voIJ02z9AYxrg="}]},"_npmUser":{"name":"simon.friedo","email":"friedosimon@aol.com"},"directories":{},"maintainers":[{"name":"soletan","email":"thomas.urban@cepharum.de"},{"name":"simon.friedo","email":"friedosimon@aol.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/js-i18n_0.1.0-alpha.3_1630314365566_0.5455515290920059"},"_hasShrinkwrap":false},"0.1.0-alpha.4":{"name":"@cepharum/js-i18n","version3":"0.1.0-alpha.1","description":"an i18n service for Javascript","main":"index.js","private":false,"scripts":{"test":"mocha --ui=tdd test/**/*.spec.js","coverage":"nyc --reporter=html --reporter=text mocha --ui tdd test/**/*.spec.js","lint":"eslint ."},"repository":{"type":"git","url":"git+https: //github.com/cepharum/js-i18n.git"},"keywords":["i18n","l10n"],"author":{"name":"cepharum GmbH"},"license":"MIT","bugs":{"url":"https://github.com/cepharum/js-i18n/issues"},"homepage":"https://github.com/cepharum/js-i18n#readme","devDependencies":{"eslint":"^5.11.1","eslint-config-cepharum":"^1.0.8","eslint-plugin-promise":"^4.0.1","mocha":"^5.2.0","nyc":"^15.0.1","should":"^13.2.3"},"version":"0.1.0-alpha.4","readme":"# js-i18n\n\nan i18n service for Javascript\n\n## License\n\nMIT\n\n## About\n\nThis module provides a commonly useful implementation for handling i18n and l10n in Javascript-based applications. \n\n## Installation\n\n`npm i --save @cepharum/js-i18n`\n\n## Usage\n\nThis library has been created with VueJS in mind, but it is suitable to work with any other Javascript-based framework as well.\n\n### Translations\n\nTranslations are hierarchically organized in a tree of regular Javascript objects. Thus you may use a Javascript module or some JSON file to implement either set of translations.\n\n```javascript\n// German translations in a JS module\nmodule.exports = {\n\theader: {\n\t\theadline: \"Überschrift\",\n\t},\n\tHOME: {\n\t\tWELCOME: \"Herzlich Willkommen!\",\n\t},\n};\n```\n\n```json\n{\n\t\"header\": {\n\t\t\"headline\": \"Überschrift\"\n\t},\n\t\"HOME\": {\n\t\t\"WELCOME\": \"Herzlich Willkommen!\"\n\t}\n}\n```\n\n### Required: Setting up Supported Locales\n\nTranslations must be registered with provided Localizations Manager:\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\nimport TranslationsModule from \"./de.js\";\n\nLocalization.register( \"de\", TranslationsModule );\n```\n\nThis would require to explicitly load translations of all locales to be probably used. An advanced initialization is provided by using `Localization.initialize()`:\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.initialize( locale => import( `./${locale.language}` ) )\n\t.then( currentLocale => {\n\t\t// TODO start your application here\n\t} );\n```\n\nThis will try loading translations according to discovered sequence of locales accepted by current browser/user. In addition it helps with lazy-loading any translation:\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.initialize( locale => {\n\tswitch ( locale.language ) {\n\t\tcase \"de\" :\n\t\t\treturn import( /* webpackChunkName: \"de-de\" */ `./de.js` );\n\n\t\tdefault :\n\t\t\treturn import( `./${locale.language}.js` );\n\t}\n} )\n\t.then( currentLocale => {\n\t\t// TODO start your application here\n\t} );\n```\n\n### Looking Up\n\nThe current locale's translations are available using `Localization.current`. The method `lookup()` is searching the tree for a translation matching path name into tree provided in first argument:\n\n```javascript\nLocalization.current.lookup( \"@home.welcome\" );\n```\n\nUsing the translations above this will return \"Herzlich Willkommen!\".\n\n#### Look-Up Key Syntax\n\nAs you can see in example above the path name starts with a prefixing `@` which is followed by a period-separated sequence of one or more segments with each segment selecting property of next level in a tree of translations. Every such segment is processed case-insensitively and may consist of latin letters, digits, dash and underscore.\n\n```\n@<segment>.<segment>.<segment>\n```\n\nNeither length of path name nor the number of contained segments is limited.\n\n#### Looking Up Everything\n\nThe `lookup()` method is testing whether first argument complies with the format described before.\n\n* A well-formed look-up key is used to find a matching node in current locale's tree of translations. If there is no matching node in tree some provided fallback or `null` is returned instead.\n\n* On providing some string that does not comply with the syntax of a look-up key it is returned as-is. \n\nDistinguishing between look-up keys and arbitrary strings is designed to help with passing every string to conveniently localize as much internationalized strings as possible while keeping all non-internationalized strings untouched.\n\n#### Looking Up Threads of Tree\n\nUsually looking up translations is designed to result in a leaf of tree, thus returning a string. However, on using shorter look-up keys a thread may be addressed and thus gets returned instead:\n\n```javascript\nLocalization.current.lookup( \"@home\" );\n```\n\nThis will return\n\n```json\n{\n\t\"welcome\": \"Herzlich Willkommen!\"\n}\n``` \n\n#### Fallbacks\n\nYou can explicitly provide a fallback in second argument to be used in case of look up fails:\n\n```javascript\nLocalization.current.lookup( \"@home.subtitle\", \"We are happy to see you here!\" );\n```\n\nThis wil return \"We are happy to see you here!\" when used with translations given above.\n\nOptionally, fallback can be provided implicitly as part of look-up key:\n\n```javascript\nLocalization.current.lookup( \"@home.subtitle=We are here for you!\", \"We are happy to see you here!\" );\n```\n\nThis look-up key follows this basic syntax:\n\n```\n<look-up key> = <fallback>\n```\n\nThe previously introduced look-up key is extended by an assigment operator to mark start of implicit fallback string. The implicit fallback is always preferred over the explicitly provided one, so the example above will return \"We are here for you!\" on mismatching tree of translations.\n\nImplicit fallbacks may be arbitrary strings, but they can't be threads of tree. This limitation does not apply to explicit fallbacks. Thus, explicit fallbacks may be used with supporting different numeri and genera, as well.\n\n#### Looking up by Properties\nIn third argument you may provide an options object of properties of the subjects/objects to be described by translation. These are used to select a more specific translation. \n\nThe options Object has the following parameters:\n\n| parameter | type | remarks    |\n| ----------- | --- | --- |\n| number | int | number of addressed subjects in desired translation |\n| genus | string | explicitly required genus of translation |\n\n\n\n#### Numerus\n\nThe parameter number provides the number of subjects/objects to be described by translation. A locale-specific function is used internally to map the provided number of items onto the name of a numerus. This name is then used to select another level in tree of translations.\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.register( \"en\", {\n\tsearch: { result: {\n\t\tsingular: \"There is %d product matching all filter criteria.\",\n\t\tplural: \"There are %d products matching all filter criteria.\",\n\t} }\n} );\n\nLocalization.select( \"en\" );\n\nconst translated = Localization.lookup( \"@search.result\", null, { number: numSearchResults } );\n\nconsole.log( util.format( translated, numSearchResults ) );\n```\n\nIf value in `numSearchResults` is `1`, this lookup will return the string _There is %d product matching all filter criteria._. Otherwise it is returning the plural form _There are %d products matching all filter criteria._.\n\nThis basic support for numerus-aware translations doesn't support proper translations of sentences with multiple numerus-aware elements. Here the term _all filter criteria_ is always in its plural form even though it might be possible to have a different translation in case of user was applying single filter, only.\n\n#### Genus\n\nThe parameter gender provides the name of genus to be used to find translation depending on a subject's or an object's genus. There is no fixed set of supported names. In addition, the name isn't processed using some locale-specific function like numerus before. Thus you should decide to have a reasonable set of names used throughout your whole set of translations. We'd consider using genera `male` and `female` here.\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.register( \"en\", {\n\tmail: { action: { pickRecipient: {\n\t\tmale: \"Send him a mail.\",\n\t\tfemale: \"Send her a mail.\",\n\t} } }\n} );\n\nLocalization.select( \"en\" );\n\nconsole.log( Localization.lookup( \"@mail.action.pickRecipient\", null, { genus: gender } ) );\n```\n\nIf value in `genera` is `male`, this lookup will return the string _Send him a mail._ If value is `female` the returned string is _Send her a mail._ \n\nDue to the nature of looking up translations providing any other value for selecting genus results in a mismatch returning `null` unless providing fallback or having some _catch-all translation_:\n\n```\nLocalization.register( \"en\", {\n\tmail: { action: { pickRecipient: {\n\t\tmale: \"Send him a mail.\",\n\t\tfemale: \"Send her a mail.\",\n\t\t\"*\": \"Pick as recipient.\",\n\t} } }\n} );\n``` \n\n> Catch-all translations are supported for numerus and for genus, though this feature isn't considered stable and might be revised, replaced or removed in a future release.\n\n#### Combining Numerus and Genus\n\nYou can also combine look-up by numerus and by genus. The key should address a thread of your tree of translations just like before. This should handle numerus first, genus second:\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.register( \"en\", {\n\tpresent: { action: {\n\t\tsingular: {\n\t\t\tmale: \"Give him %d item.\",\n\t\t\tfemale: \"Give her %d item.\",\n\t\t},\n\t\tplural: {\n\t\t\tmale: \"Give him %d items.\",\n\t\t\tfemale: \"Give her %d items.\",\n\t\t},\n\t} }\n} );\n\nLocalization.select( \"en\" );\n\nconsole.log( Localization.lookup( \"@present.action\", null, { number: numItems, genus: gender } ) );\n```\n\n### Filtering in VueJS\n\nAs mentioned before this i18n library has been designed for use with VueJS applications. It comes with a function suitable as a [filter](https://vuejs.org/v2/guide/filters.html#ad) for VueJS.\n\nYou should register localization as early as possible. Here we inject it in application's **main.js** initializing localization prior to actually starting VueJS framework using `Localization.initialize()`:\n\n```javascript\nimport Vue from \"vue\";\n\nimport { Localization, Translate, Format } from \"@cepharum/js-i18n\";\n\nLocalization.initialize( locale => import( `../i18n/${locale.language}.js` ) )\n\t.then( () => {\n\t\tVue.filter( \"translate\", Translate );\n\t\tVue.filter( \"format\", Format );\n\n\t\tnew Vue( {\n\t\t\t...\n\t\t} ).$mount( \"#app\" );\n\t} )\n\t.catch( error => {\n\t\tconsole.error( error );\n\t} );\n```\n\nDue to this initialization filters `translate` and `format` are available in template of either component:\n\n```vue\n<h1>{{ '@Header.Title=Welcome!' | translate }}</h1>\n<p>{{ '@present.action=Give %d item(s) | translate( { number: numItems, genus: recipientGender } ) | format( numItems ) }}</p>\n```\n\n* Filter `translate` takes input string for looking up. Optional argument might be object providing number of items in property `number` and/or genus in property `genus`. The output is found translation, some fallback or provided string if it doesn't comply with look-up key syntax or on mismatch w/o provision of a fallback.\n\n* Filter `format` has been implemented to help with filling placeholders in a resulting translation. It uses a subset of printf syntax. Its arguments are consecutively used as values of encountered placeholders. Every placeholder starts with a percent sign and ends with a type marker. Between these two options may be inserted. The syntax is similar to this pattern:\n\n      '%' <fill> <width> <precision> <ref> <type marker>\n\n  | type marker | example | remarks    |\n  | ----------- | --- | --- |\n  | % | `%%` | Replaces placeholder with literal `%`. |\n  | s | `%s` | Inserts string value of next argument. |\n  | d | `%d` | Inserts integer numeric value of next argument. |\n  | x | `%x` | Inserts hexadecimal integer value of next argument using lowercase letters for digits a-f. |\n  | X | `%X` | Inserts hexadecimal integer value of next argument using uppercase letters for digits A-F. |\n  | f | `%f` | Inserts fixed-point numeric value of next argument. |\n  | . | `%.` | Consumes next argument replacing placeholder with empty string. |\n  \n  Placeholders are processed from left to right with each regular placeholder consuming another argument provided on calling filter `format`. The placeholder `%.` can be used to skip a single argument without generating any output. \n  \n  Another approach is using argument references. A reference consists of a dollar sign `$` followed by a positive integer value selecting argument in list of arguments by position with `1` referring to the first argument. Using a reference doesn't consume next argument. \n  \n  > **Example:** The placeholder `%$1s` requests to inject value of first argument as string no matter whether other placeholders might have consumed arguments before or not.\n  \n  The placeholder components `<fill>`, `<width>` and `<precision>` are all available to control vertical alignment of injected value:\n  \n  * `<width>` is a positive integer requesting to fill any value to generate at least this number of characters. Fill is applied left to the value, thus resulting in a right-aligned value.\n  \n  * `<precision>` is a positive integer requesting number of fractional digits to be displayed on decimal values. On all other types of placeholders this will result in a according number of space appended to the injected value to align it with decimal separator of decimal numbers.\n  \n  * The `<fill>` might be period, dash, underscore, space or `0`. It is selecting what character is used to fill value on behalf of `<width>`.\n  \n  In opposition to regular printf syntax `<width>` and `<precision>` are handled separately and thus `<width>` doesn't cover `<precision>`. The resulting width of a generated output is the sum of `<width>` and `<precision>` plus 1 for the separator in case of actually using `<precision>`.\n  \n  The `<sep>` is either `.` or `,` and controls what separator is used on processing decimal values.\n  \n  > **Examples:**\n  >\n  > * `%s` with `Hello` generates `Hello`.\n  > * `%8s` with `Hello` generates `Hello` with 3 additional spaces to the left.\n  > * `%4.2d` with `132.7865` generates `132.79` with 1 additional space to the left.\n  > * `%,2d` with `132.7865` generates `132,79`.\n  > * `%06,2d` with `132.7865` generates `000132,79`.\n","readmeFilename":"README.md","gitHead":"9c3a18fdf46ff68b6694e792a76bf9e03d3b6070","_id":"@cepharum/js-i18n@0.1.0-alpha.4","_nodeVersion":"14.15.4","_npmVersion":"7.13.0","dist":{"integrity":"sha512-pqR+0BixK+KZFIrw3T6Z+uv9e+o2NmxbhbearXU2qIVjOXyEY1uPOUr2M2wjirBXSuZS1wAfijAA+gG6uYsfkQ==","shasum":"669e4f4a7134f4c527c9e5a08373f3d71fe572c8","tarball":"https://registry.npmjs.org/@cepharum/js-i18n/-/js-i18n-0.1.0-alpha.4.tgz","fileCount":20,"unpackedSize":149182,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhLK1SCRA9TVsSAnZWagAANl4P/i8ft7byypvec9u3BT0h\n2Z7O/fPG99i4WDrLj7gke2d/2ET/3L0io3RqYMf6ZoL3C+3dHDocRWYzFq+L\npkbH6yqziiWhYui9Id27T/xaRGpV5wH73AOyhZwQ9K3ODAemg8ZlhAxjp+Ct\n+ZhjP6V2hkuJHmyG25wQWto+IbmM3WW76JXDkSMGKn6uvrh1v7s7eeZXCMUT\n1Ow3At5+M9jbqDUIDDgi1Rwec+cyLVgbsdxf1Gllh9qdKtYpxt9pVny8Wbjn\nwG8VCUvj/1+7AulSizPnbgWx8lZt5YewpDlfdCPx8nME7XvxudobaDiJqN8r\nTRBhwLzO3wQHYcF1AulMKNzADYzk8+ziQQmo4Z0SlH2Os6L3StfJcVfLOy+J\nnlTKraRwotvIJPZb/8sj9KgTSmZ0aPcD6c+YHPWHDjyqKVnvFDWXgxgYJ9K8\nxLlr20SGRmoBSwJ/5Kk0lfxBU2VSxtrLIvuNViVb8AIzVKzVbNjeyYKWC7ng\nz7t8z21N9UEMzhD2PspA5+3F1rwoXSFUdLL57By3KvKMNJphTCNwl4DQ69gy\nN/V5IEfteWETtuW80O0k0GVOgFPgAi7cpFxzB10d3B+IBhkxukoiKHZoxUOr\nn2Pk8aSDu5Y4CFHovpGgTDLL2IVAkYmmXA9fVmX4vlJl9G/ZMrJ0xKyWzLPb\nwClL\r\n=E2t4\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCYM+GvdQqI4dryUPjHSUt4+EuqKxc37Xz1+HZ5NoCTMwIgdQq5tD2S8PItyq42dOp78aFeknFfFYkCGdeToQfiq8c="}]},"_npmUser":{"name":"simon.friedo","email":"friedosimon@aol.com"},"directories":{},"maintainers":[{"name":"soletan","email":"thomas.urban@cepharum.de"},{"name":"simon.friedo","email":"friedosimon@aol.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/js-i18n_0.1.0-alpha.4_1630317906320_0.14972810541274106"},"_hasShrinkwrap":false},"0.2.0-alpha.1":{"name":"@cepharum/js-i18n","version3":"0.1.0-alpha.1","description":"an i18n service for Javascript","main":"lib/index.js","private":false,"type":"module","scripts":{"test":"mocha --ui=tdd test/**/*.spec.js","coverage":"c8 --reporter=html --reporter=text mocha --ui tdd test/**/*.spec.js","lint":"eslint ."},"repository":{"type":"git","url":"git+https: //github.com/cepharum/js-i18n.git"},"keywords":["i18n","l10n"],"author":{"name":"cepharum GmbH"},"license":"MIT","bugs":{"url":"https://github.com/cepharum/js-i18n/issues"},"homepage":"https://github.com/cepharum/js-i18n#readme","devDependencies":{"c8":"^7.9.0","eslint":"^5.11.1","eslint-config-cepharum":"^1.0.8","eslint-plugin-promise":"^4.0.1","mocha":"^9.1.1","nyc":"^15.0.1","should":"^13.2.3","vue":"^3.2.19"},"version":"0.2.0-alpha.1","gitHead":"26c8b7ccd71505932860622e12e06e06029cafb1","_id":"@cepharum/js-i18n@0.2.0-alpha.1","_nodeVersion":"14.15.4","_npmVersion":"7.13.0","dist":{"integrity":"sha512-IByFiTg7ukh2bAmmJiuq1wLwYz4T7es9TgmLAsvgta0RrxAMqRG2v0nV5vRbMU+ILT7W2X+zEV8ARaLupcg2CQ==","shasum":"282b7ef4df71d4bd478b6ec150cf05a85c257676","tarball":"https://registry.npmjs.org/@cepharum/js-i18n/-/js-i18n-0.2.0-alpha.1.tgz","fileCount":24,"unpackedSize":115274,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJhzcNDCRA9TVsSAnZWagAAJZ8P/iBcXwkHhS63oIS70iMB\nl6XGmxMKZxZU9b4KJBHw7oohSjF8JG/5wEdOC/C7wxpnIHUi6yxUjzTHU6QF\nVaIieFPAaMxjrHyM07tHSL5fq2rNPyaKP4KwcdhIpt1CviD3AaIIxWeVPgIZ\nLfU0nOXhea17DJCAzviCKMxT5n867KCe10bJU4hZPgfGiUR3gsP7LbiygcLp\nDmoDbvt0lVwMKdBgFQpzCydEvKMoDhpDNJc0rkZM+lNzAfZP7TVkuBd9KK2q\nlzudB/H+LofxCyreKaSCn/0AWbPv7tyDtSsGMFwS0dnBd1SIp6R2JkirOIl9\n32stDmN6MQeOltAfhf3j6AwnuXoNIOc8VaJ7S91rfUS165kA4W0xU04ImhAS\nqHfNqgsRjp+uUkx43MHCkP9KK/2NlZCZOQvFdKy+1si7hMLVdndxcnUev/IF\nEfkc118z/caM5oZNl+vCV3lfQg02bYyWgT6PMPgSTV8US0qODBsLuDIdRf/i\nf4COk4YFEeuJ8JL3sm11TpCW93Rcw0fg98iuiXMNHRekPiPjYEikLfB79p4i\nmuGHeJ+rx7bJc2sRpqW8MFDtMqSLOfbu0sRjrAg6Ehw8gZrBHKFjyU2d9/nB\nLsbRnW6zJ9kTFpp7ENjdPmRdUKWd8yAac0O5XTYPYjfCa49iSovekeasWcvb\nBdUD\r\n=StwL\r\n-----END PGP SIGNATURE-----\r\n","signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQDdgfB0X05puAvRv7jx9jWbrWXxutFCxDWjSxdtF6qB6wIgGM5JsuXRlyQMSJk6ZToKG726tvgTPCtgKpfjGLlyxn4="}]},"_npmUser":{"name":"simon.friedo","email":"friedosimon@aol.com"},"directories":{},"maintainers":[{"name":"soletan","email":"thomas.urban@cepharum.de"},{"name":"simon.friedo","email":"friedosimon@aol.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/js-i18n_0.2.0-alpha.1_1633618314643_0.564089948269479"},"_hasShrinkwrap":false}},"time":{"created":"2019-01-01T22:16:53.992Z","0.0.1":"2019-01-01T22:16:54.188Z","modified":"2022-04-04T22:20:24.038Z","0.0.2":"2019-01-02T00:55:49.055Z","0.0.3":"2019-01-02T01:36:59.580Z","0.0.4":"2019-01-02T01:49:01.621Z","0.0.5":"2019-01-02T01:55:27.892Z","0.0.6":"2019-01-02T09:15:13.203Z","0.0.7":"2019-01-02T16:36:12.592Z","0.0.8":"2019-04-09T10:42:53.130Z","0.1.0-alpha.1":"2021-03-10T16:30:44.287Z","0.1.0-alpha.2":"2021-04-07T08:43:41.605Z","0.1.0-alpha.3":"2021-08-30T09:06:05.704Z","0.1.0-alpha.4":"2021-08-30T10:05:06.454Z","0.2.0-alpha.1":"2021-10-07T14:51:54.795Z"},"maintainers":[{"name":"soletan","email":"thomas.urban@cepharum.de"},{"name":"simon.friedo","email":"friedosimon@aol.com"}],"description":"an i18n service for Javascript","homepage":"https://github.com/cepharum/js-i18n#readme","keywords":["i18n","l10n"],"repository":{"type":"git","url":"git+https: //github.com/cepharum/js-i18n.git"},"author":{"name":"cepharum GmbH"},"bugs":{"url":"https://github.com/cepharum/js-i18n/issues"},"license":"MIT","readme":"# js-i18n\n\nan i18n service for Javascript\n\n## License\n\nMIT\n\n## About\n\nThis module provides a commonly useful implementation for handling i18n and l10n in Javascript-based applications. \n\n## Installation\n\n`npm i --save @cepharum/js-i18n`\n\n## Usage\n\nThis library has been created with VueJS in mind, but it is suitable to work with any other Javascript-based framework as well.\n\n### Translations\n\nTranslations are hierarchically organized in a tree of regular Javascript objects. Thus you may use a Javascript module or some JSON file to implement either set of translations.\n\n```javascript\n// German translations in a JS module\nmodule.exports = {\n\theader: {\n\t\theadline: \"Überschrift\",\n\t},\n\tHOME: {\n\t\tWELCOME: \"Herzlich Willkommen!\",\n\t},\n};\n```\n\n```json\n{\n\t\"header\": {\n\t\t\"headline\": \"Überschrift\"\n\t},\n\t\"HOME\": {\n\t\t\"WELCOME\": \"Herzlich Willkommen!\"\n\t}\n}\n```\n\n### Required: Setting up Supported Locales\n\nTranslations must be registered with provided Localizations Manager:\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\nimport TranslationsModule from \"./de.js\";\n\nLocalization.register( \"de\", TranslationsModule );\n```\n\nThis would require to explicitly load translations of all locales to be probably used. An advanced initialization is provided by using `Localization.initialize()`:\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.initialize( locale => import( `./${locale.language}` ) )\n\t.then( currentLocale => {\n\t\t// TODO start your application here\n\t} );\n```\n\nThis will try loading translations according to discovered sequence of locales accepted by current browser/user. In addition it helps with lazy-loading any translation:\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.initialize( locale => {\n\tswitch ( locale.language ) {\n\t\tcase \"de\" :\n\t\t\treturn import( /* webpackChunkName: \"de-de\" */ `./de.js` );\n\n\t\tdefault :\n\t\t\treturn import( `./${locale.language}.js` );\n\t}\n} )\n\t.then( currentLocale => {\n\t\t// TODO start your application here\n\t} );\n```\n\n### Looking Up\n\nThe current locale's translations are available using `Localization.current`. The method `lookup()` is searching the tree for a translation matching path name into tree provided in first argument:\n\n```javascript\nLocalization.current.lookup( \"@home.welcome\" );\n```\n\nUsing the translations above this will return \"Herzlich Willkommen!\".\n\n#### Look-Up Key Syntax\n\nAs you can see in example above the path name starts with a prefixing `@` which is followed by a period-separated sequence of one or more segments with each segment selecting property of next level in a tree of translations. Every such segment is processed case-insensitively and may consist of latin letters, digits, dash and underscore.\n\n```\n@<segment>.<segment>.<segment>\n```\n\nNeither length of path name nor the number of contained segments is limited.\n\n#### Looking Up Everything\n\nThe `lookup()` method is testing whether first argument complies with the format described before.\n\n* A well-formed look-up key is used to find a matching node in current locale's tree of translations. If there is no matching node in tree some provided fallback or `null` is returned instead.\n\n* On providing some string that does not comply with the syntax of a look-up key it is returned as-is. \n\nDistinguishing between look-up keys and arbitrary strings is designed to help with passing every string to conveniently localize as much internationalized strings as possible while keeping all non-internationalized strings untouched.\n\n#### Looking Up Threads of Tree\n\nUsually looking up translations is designed to result in a leaf of tree, thus returning a string. However, on using shorter look-up keys a thread may be addressed and thus gets returned instead:\n\n```javascript\nLocalization.current.lookup( \"@home\" );\n```\n\nThis will return\n\n```json\n{\n\t\"welcome\": \"Herzlich Willkommen!\"\n}\n``` \n\n#### Fallbacks\n\nYou can explicitly provide a fallback in second argument to be used in case of look up fails:\n\n```javascript\nLocalization.current.lookup( \"@home.subtitle\", \"We are happy to see you here!\" );\n```\n\nThis wil return \"We are happy to see you here!\" when used with translations given above.\n\nOptionally, fallback can be provided implicitly as part of look-up key:\n\n```javascript\nLocalization.current.lookup( \"@home.subtitle=We are here for you!\", \"We are happy to see you here!\" );\n```\n\nThis look-up key follows this basic syntax:\n\n```\n<look-up key> = <fallback>\n```\n\nThe previously introduced look-up key is extended by an assigment operator to mark start of implicit fallback string. The implicit fallback is always preferred over the explicitly provided one, so the example above will return \"We are here for you!\" on mismatching tree of translations.\n\nImplicit fallbacks may be arbitrary strings, but they can't be threads of tree. This limitation does not apply to explicit fallbacks. Thus, explicit fallbacks may be used with supporting different numeri and genera, as well.\n\n#### Looking up by Properties\nIn third argument you may provide an options object of properties of the subjects/objects to be described by translation. These are used to select a more specific translation. \n\nThe options Object has the following parameters:\n\n| parameter | type | remarks    |\n| ----------- | --- | --- |\n| number | int | number of addressed subjects in desired translation |\n| genus | string | explicitly required genus of translation |\n\n\n\n#### Numerus\n\nThe parameter number provides the number of subjects/objects to be described by translation. A locale-specific function is used internally to map the provided number of items onto the name of a numerus. This name is then used to select another level in tree of translations.\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.register( \"en\", {\n\tsearch: { result: {\n\t\tsingular: \"There is %d product matching all filter criteria.\",\n\t\tplural: \"There are %d products matching all filter criteria.\",\n\t} }\n} );\n\nLocalization.select( \"en\" );\n\nconst translated = Localization.lookup( \"@search.result\", null, { number: numSearchResults } );\n\nconsole.log( util.format( translated, numSearchResults ) );\n```\n\nIf value in `numSearchResults` is `1`, this lookup will return the string _There is %d product matching all filter criteria._. Otherwise it is returning the plural form _There are %d products matching all filter criteria._.\n\nThis basic support for numerus-aware translations doesn't support proper translations of sentences with multiple numerus-aware elements. Here the term _all filter criteria_ is always in its plural form even though it might be possible to have a different translation in case of user was applying single filter, only.\n\n#### Genus\n\nThe parameter gender provides the name of genus to be used to find translation depending on a subject's or an object's genus. There is no fixed set of supported names. In addition, the name isn't processed using some locale-specific function like numerus before. Thus you should decide to have a reasonable set of names used throughout your whole set of translations. We'd consider using genera `male` and `female` here.\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.register( \"en\", {\n\tmail: { action: { pickRecipient: {\n\t\tmale: \"Send him a mail.\",\n\t\tfemale: \"Send her a mail.\",\n\t} } }\n} );\n\nLocalization.select( \"en\" );\n\nconsole.log( Localization.lookup( \"@mail.action.pickRecipient\", null, { genus: gender } ) );\n```\n\nIf value in `genera` is `male`, this lookup will return the string _Send him a mail._ If value is `female` the returned string is _Send her a mail._ \n\nDue to the nature of looking up translations providing any other value for selecting genus results in a mismatch returning `null` unless providing fallback or having some _catch-all translation_:\n\n```\nLocalization.register( \"en\", {\n\tmail: { action: { pickRecipient: {\n\t\tmale: \"Send him a mail.\",\n\t\tfemale: \"Send her a mail.\",\n\t\t\"*\": \"Pick as recipient.\",\n\t} } }\n} );\n``` \n\n> Catch-all translations are supported for numerus and for genus, though this feature isn't considered stable and might be revised, replaced or removed in a future release.\n\n#### Combining Numerus and Genus\n\nYou can also combine look-up by numerus and by genus. The key should address a thread of your tree of translations just like before. This should handle numerus first, genus second:\n\n```javascript\nimport { Localization } from \"@cepharum/js-i18n\";\n\nLocalization.register( \"en\", {\n\tpresent: { action: {\n\t\tsingular: {\n\t\t\tmale: \"Give him %d item.\",\n\t\t\tfemale: \"Give her %d item.\",\n\t\t},\n\t\tplural: {\n\t\t\tmale: \"Give him %d items.\",\n\t\t\tfemale: \"Give her %d items.\",\n\t\t},\n\t} }\n} );\n\nLocalization.select( \"en\" );\n\nconsole.log( Localization.lookup( \"@present.action\", null, { number: numItems, genus: gender } ) );\n```\n\n### Filtering in VueJS\n\nAs mentioned before this i18n library has been designed for use with VueJS applications. It comes with a function suitable as a [filter](https://vuejs.org/v2/guide/filters.html#ad) for VueJS.\n\nYou should register localization as early as possible. Here we inject it in application's **main.js** initializing localization prior to actually starting VueJS framework using `Localization.initialize()`:\n\n```javascript\nimport Vue from \"vue\";\n\nimport { Localization, Translate, Format } from \"@cepharum/js-i18n\";\n\nLocalization.initialize( locale => import( `../i18n/${locale.language}.js` ) )\n\t.then( () => {\n\t\tVue.filter( \"translate\", Translate );\n\t\tVue.filter( \"format\", Format );\n\n\t\tnew Vue( {\n\t\t\t...\n\t\t} ).$mount( \"#app\" );\n\t} )\n\t.catch( error => {\n\t\tconsole.error( error );\n\t} );\n```\n\nDue to this initialization filters `translate` and `format` are available in template of either component:\n\n```vue\n<h1>{{ '@Header.Title=Welcome!' | translate }}</h1>\n<p>{{ '@present.action=Give %d item(s) | translate( { number: numItems, genus: recipientGender } ) | format( numItems ) }}</p>\n```\n\n* Filter `translate` takes input string for looking up. Optional argument might be object providing number of items in property `number` and/or genus in property `genus`. The output is found translation, some fallback or provided string if it doesn't comply with look-up key syntax or on mismatch w/o provision of a fallback.\n\n* Filter `format` has been implemented to help with filling placeholders in a resulting translation. It uses a subset of printf syntax. Its arguments are consecutively used as values of encountered placeholders. Every placeholder starts with a percent sign and ends with a type marker. Between these two options may be inserted. The syntax is similar to this pattern:\n\n      '%' <fill> <width> <precision> <ref> <type marker>\n\n  | type marker | example | remarks    |\n  | ----------- | --- | --- |\n  | % | `%%` | Replaces placeholder with literal `%`. |\n  | s | `%s` | Inserts string value of next argument. |\n  | d | `%d` | Inserts integer numeric value of next argument. |\n  | x | `%x` | Inserts hexadecimal integer value of next argument using lowercase letters for digits a-f. |\n  | X | `%X` | Inserts hexadecimal integer value of next argument using uppercase letters for digits A-F. |\n  | f | `%f` | Inserts fixed-point numeric value of next argument. |\n  | . | `%.` | Consumes next argument replacing placeholder with empty string. |\n  \n  Placeholders are processed from left to right with each regular placeholder consuming another argument provided on calling filter `format`. The placeholder `%.` can be used to skip a single argument without generating any output. \n  \n  Another approach is using argument references. A reference consists of a dollar sign `$` followed by a positive integer value selecting argument in list of arguments by position with `1` referring to the first argument. Using a reference doesn't consume next argument. \n  \n  > **Example:** The placeholder `%$1s` requests to inject value of first argument as string no matter whether other placeholders might have consumed arguments before or not.\n  \n  The placeholder components `<fill>`, `<width>` and `<precision>` are all available to control vertical alignment of injected value:\n  \n  * `<width>` is a positive integer requesting to fill any value to generate at least this number of characters. Fill is applied left to the value, thus resulting in a right-aligned value.\n  \n  * `<precision>` is a positive integer requesting number of fractional digits to be displayed on decimal values. On all other types of placeholders this will result in a according number of space appended to the injected value to align it with decimal separator of decimal numbers.\n  \n  * The `<fill>` might be period, dash, underscore, space or `0`. It is selecting what character is used to fill value on behalf of `<width>`.\n  \n  In opposition to regular printf syntax `<width>` and `<precision>` are handled separately and thus `<width>` doesn't cover `<precision>`. The resulting width of a generated output is the sum of `<width>` and `<precision>` plus 1 for the separator in case of actually using `<precision>`.\n  \n  The `<sep>` is either `.` or `,` and controls what separator is used on processing decimal values.\n  \n  > **Examples:**\n  >\n  > * `%s` with `Hello` generates `Hello`.\n  > * `%8s` with `Hello` generates `Hello` with 3 additional spaces to the left.\n  > * `%4.2d` with `132.7865` generates `132.79` with 1 additional space to the left.\n  > * `%,2d` with `132.7865` generates `132,79`.\n  > * `%06,2d` with `132.7865` generates `000132,79`.\n","readmeFilename":"README.md"}