diff --git a/index.ts b/index.ts index 6b2ac97..4f4a21b 100644 --- a/index.ts +++ b/index.ts @@ -1,10 +1,38 @@ import { gettextToI18next } from 'i18next-conv' +import { GettextExtractor, JsExtractors } from 'gettext-extractor'; +import { JsParser } from 'gettext-extractor/dist/js/parser'; +import { IJsExtractorOptions } from 'gettext-extractor/dist/js/extractors/common'; -export default function PoLoader() { +let extractor = new GettextExtractor(); + +interface Options { + pot: Partial<{ + out: string + callee: { calleeName: string|string[], options: IJsExtractorOptions}[] + }> +} + +export default function GettextLoader(options: Partial = {}) { + const pwd = process.cwd(); + let parser: JsParser|undefined = undefined; + if (options.pot?.out && process.env.NODE_ENV === 'development') { + let extractorFuncs = options.pot.callee?.map(c => JsExtractors.callExpression(c.calleeName, c.options)); + if (!extractorFuncs || extractorFuncs.length === 0) { + extractorFuncs = [ + JsExtractors.callExpression(['t'], { + arguments: { + text: 0, + context: 1, + } + })] + } + parser = extractor.createJsParser(extractorFuncs); + } return { - name: 'po-loader', + name: 'gettext-loader', async transform(source: string, id: string) { const poRegEx = /\.po$/; + const jsRegEx = /\.(js|jsx|ts|tsx)$/; if (poRegEx.test(id)) { const match = source.match(/Language: (\w+)/) const lang = match ? match[1] : 'en'; @@ -12,8 +40,15 @@ export default function PoLoader() { return { code: `export default ${await gettextToI18next(lang, source)}` } + } else if (jsRegEx.test(id)) { + parser?.parseFile(id.replace(pwd, '.')) } return {}; + }, + async buildEnd() { + if (parser && options.pot?.out) { + extractor.savePotFile(options.pot.out) + } } } } \ No newline at end of file diff --git a/package.json b/package.json index 9d7aa73..3ca0bb2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@arnef/vite-plugin-gettext-loader", - "version": "1.0.2", + "version": "1.1.0", "main": "dist/index.js", "types": "dist/index.d.ts", "license": "MIT", @@ -8,6 +8,7 @@ "build": "tsc" }, "dependencies": { + "gettext-extractor": "^3.5.4", "i18next-conv": "^12.1.1" }, "devDependencies": { @@ -16,10 +17,11 @@ "keywords": [ "vite", "vite-plugin", - "gettext", + "gettext", "po", "pot" ], - "publishConfig": { "@arnef:registry":" https://git.arnef.de/api/v4/projects/11/packages/npm/" } - + "publishConfig": { + "@arnef:registry": " https://git.arnef.de/api/v4/projects/11/packages/npm/" + } } diff --git a/yarn.lock b/yarn.lock index c4f7f3d..9481669 100644 --- a/yarn.lock +++ b/yarn.lock @@ -30,11 +30,34 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@types/glob@5 - 7": + version "7.2.0" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" + integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== + dependencies: + "@types/minimatch" "*" + "@types/node" "*" + "@types/istanbul-lib-coverage@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== +"@types/minimatch@*": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.5.tgz#1001cc5e6a3704b83c236027e77f2f58ea010f40" + integrity sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ== + +"@types/node@*": + version "17.0.31" + resolved "https://registry.yarnpkg.com/@types/node/-/node-17.0.31.tgz#a5bb84ecfa27eec5e1c802c6bbf8139bdb163a5d" + integrity sha512-AR0x5HbXGqkEx9CadRH3EBYx/VkiUgZIhP4wvPn/+5KIsgpNoyFaRlVe0Zlx9gRtg8fA06a9tskE2MSN7TcG4Q== + +"@types/parse5@^5": + version "5.0.3" + resolved "https://registry.yarnpkg.com/@types/parse5/-/parse5-5.0.3.tgz#e7b5aebbac150f8b5fdd4a46e7f0bd8e65e19109" + integrity sha512-kUNnecmtkunAoQ3CnjmMkzNU/gtxG8guhi+Fk2U/kOpIKjIMKnXGp4IJCgQJrXSgMsWYimYG4TGjz/UzbGEBTw== + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -140,6 +163,11 @@ cross-spawn@^7.0.0: shebang-command "^2.0.0" which "^2.0.1" +css-selector-parser@^1.3: + version "1.4.1" + resolved "https://registry.yarnpkg.com/css-selector-parser/-/css-selector-parser-1.4.1.tgz#03f9cb8a81c3e5ab2c51684557d5aaf6d2569759" + integrity sha512-HYPSb7y/Z7BNDCOrakL4raGO2zltZkbeXyAd6Tg9obzix6QhzxCotdBl6VT0Dv4vZfJGVz3WL/xaEI9Ly3ul0g== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -192,6 +220,19 @@ gettext-converter@^1.2.2: content-type "1.0.4" encoding "0.1.13" +gettext-extractor@^3.5.4: + version "3.5.4" + resolved "https://registry.yarnpkg.com/gettext-extractor/-/gettext-extractor-3.5.4.tgz#bd36c65b4d26014ffd925f9ac7b4738d6893d6b2" + integrity sha512-iK4tSnteSw+pFMts43OP8hUnsOklbkxz3ytWqru7dPf8Ec3uzTYv1aw70ojAvKItmofpj1ibfY7sZWsdSN6zIw== + dependencies: + "@types/glob" "5 - 7" + "@types/parse5" "^5" + css-selector-parser "^1.3" + glob "5 - 7" + parse5 "5 - 6" + pofile "1.0.x" + typescript "2 - 4" + gettext-parser@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/gettext-parser/-/gettext-parser-5.1.2.tgz#ebecc29a905334a48680a57b2d64da920f781cd4" @@ -202,7 +243,7 @@ gettext-parser@^5.1.2: readable-stream "^3.6.0" safe-buffer "^5.2.1" -glob@^7.1.3, glob@^7.1.4: +"glob@5 - 7", glob@^7.1.3, glob@^7.1.4: version "7.2.0" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== @@ -342,6 +383,11 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" +"parse5@5 - 6": + version "6.0.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-6.0.1.tgz#e1a1c085c569b3dc08321184f19a39cc27f7c30b" + integrity sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw== + path-exists@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" @@ -357,6 +403,11 @@ path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== +pofile@1.0.x: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pofile/-/pofile-1.0.11.tgz#35aff58c17491d127a07336d5522ebc9df57c954" + integrity sha512-Vy9eH1dRD9wHjYt/QqXcTz+RnX/zg53xK+KljFSX30PvdDMb2z+c6uDUeblUGqqJgz3QFsdlA0IJvHziPmWtQg== + readable-stream@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" @@ -454,7 +505,7 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" -typescript@^4.6.4: +"typescript@2 - 4", typescript@^4.6.4: version "4.6.4" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.4.tgz#caa78bbc3a59e6a5c510d35703f6a09877ce45e9" integrity sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==