biesbjerg / ngx-translate-extract

Extract translatable (using ngx-translate) strings and save as a JSON or Gettext pot file
MIT License
524 stars 196 forks source link

Angular 13 compatibility #247

Open bartholomej opened 2 years ago

bartholomej commented 2 years ago

What is in this PR?

Why?

Because it no longer works with Angular 13. Issue: #246

Notes

More testing would be appreciated :)

venraij commented 2 years ago

@bartholomej I've tested it with Angular 13 NodeJS 16 as well but still doesn't work. Gives me the same error as before your changes.

tiberiuzuld commented 2 years ago

Can confirm that this changes do not work

node:internal/modules/cjs/loader:936
  throw err;
  ^

Error: Cannot find module '../dist/cli/cli'
Require stack:
- <path>/node_modules/@biesbjerg/ngx-translate-extract/bin/cli.js
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)

Angular 13 NodeJS 16

venraij commented 2 years ago

@bartholomej i've opened a pull request in your repo to merge my changes into your branch. The new changes fix the issues.

tiberiuzuld commented 2 years ago

@venraij Still same issue as above. Installed your version with "@biesbjerg/ngx-translate-extract": "github:bartholomej/ngx-translate-extract#ng13" Or it requires a build ... ? Will try that now.

node:internal/modules/cjs/loader:936
  throw err;
  ^

Error: Cannot find module '../dist/cli/cli.js'
Require stack:
-<path>\node_modules\@biesbjerg\ngx-translate-extract\bin\cli.js
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
    at Function.Module._load (node:internal/modules/cjs/loader:778:27)
tiberiuzuld commented 2 years ago

Ok made the build and copied the dist folder but still not working

node:internal/modules/cjs/loader:979
    throw new ERR_REQUIRE_ESM(filename, true);
    ^

Error [ERR_REQUIRE_ESM]: require() of ES Module <path>\node_modules\@angular\compile
r\fesm2015\compiler.mjs not supported.
Instead change the require of <path>\node_modules\@angular\compiler\fesm2015\compile
r.mjs to a dynamic import() which is available in all CommonJS modules.
    at Object.<anonymous> (<path>\node_modules\@biesbjerg\ngx-translate-extract\dist
\parsers\pipe.parser.js:3:20)
    at Object.<anonymous> <path>\node_modules\@biesbjerg\ngx-translate-extract\dist
\cli\cli.js:25:23)
    at Object.<anonymous> (<path>\node_modules\@biesbjerg\ngx-translate-extract\bin\
cli.js:3:1) {
  code: 'ERR_REQUIRE_ESM'
}
venraij commented 2 years ago

@tiberiuzuld give this a whirl https://www.npmjs.com/package/@misternick/ngx-translate-extract it is the packaged version. It uses the code in this branche of my repo https://github.com/venraij/ngx-translate-extract/tree/ng13

tiberiuzuld commented 2 years ago

Still the same issue


node:internal/modules/cjs/loader:979
    throw new ERR_REQUIRE_ESM(filename, true);
    ^

Error [ERR_REQUIRE_ESM]: require() of ES Module <path>\node_modules\@angular\compile
r\fesm2015\compiler.mjs not supported.
Instead change the require of <path>\node_modules\@angular\compiler\fesm2015\compile
r.mjs to a dynamic import() which is available in all CommonJS modules.
    at Object.<anonymous> (<path>\node_modules\@misternick\ngx-translate-extract\dis
t\parsers\pipe.parser.js:3:20)
    at Object.<anonymous> (<path>\node_modules\@misternick\ngx-translate-extract\dis
t\cli\cli.js:25:23)
    at Object.<anonymous> (<path>\node_modules\@misternick\ngx-translate-extract\bin
\cli.js:3:1) {
  code: 'ERR_REQUIRE_ESM'
}

Maybe the issue in my case is the fact that I use npm i --legacy-peer-deps so I still download the @angular/compiler@13 which does not like to be loaded with require commonJS style.

tiberiuzuld commented 2 years ago

So after some more trial and error arrived at this changes: https://github.com/biesbjerg/ngx-translate-extract/compare/master...tiberiuzuld:ng13?expand=1

My initial issue starts from the change in angular packages which now default to ESM so all the libraries depending on angular need to make the switch https://github.com/angular/angular/issues/43833

My changes still don't work completely at least for my project. It starts extracting and some point I get the error:

An error occurred: TypeError: Cannot read properties of null (reading 'name')

Issues that I encountered along the way that required changes in the code changes linked above:

  1. ESM imports in NodeJS need to specify .js extension to make them work. Typescript will emit .js extension only in 4.5 but currently we are stuck to 4.4 so we need to set the extension.

  2. Yargs 16 was not working, upgraded to 17, removed @types/yargs and yargs().option imported yargs is a constructor now, needs to be instantiated.

  3. Commonjs packages not working with named exports:

    // before
    import * as glob from 'glob';
    glob.sync(..)
    // after
    import pkg from 'glob';
    const { sync } = pkg;
    sync(..)
    
    //before
    import { flatten } from 'flat';
    // after
    import pkg from 'flat';
    const { flatten } = pkg;
    
    //before
    import pkg from 'gettext-parser';
    // after
    const { po } = pkg;
    
    // after
    import pkg from 'typescript';
    const { SyntaxKind, isStringLiteralLike, isArrayLiteralExpression, isBinaryExpression, isConditionalExpression } = pkg;
    
  4. angular/compiler MethodCall not present anymore, changed to Call

  5. __dirname not available anymore in ESM changes:

    // before
    .version(require(__dirname + '/../../package.json').version)
    // after
    .version(process.env.npm_package_version)

The changes are complex to upgrade to ng13 and the last error I hit when running the changes in my project doesn't offer any clues where to take it from there. In case someone wants to pick up the work

tiberiuzuld commented 2 years ago

Update: Was able to fix all issues and to be able to run the tests under ESM except for node 12

The issues: An error occurred: TypeError: Cannot read properties of null (reading 'exp') and An error occurred: TypeError: Cannot read properties of null (reading 'name')

Where from:

    protected expressionIsOrHasBindingPipe(exp: any): exp is BindingPipe {
        if (exp && exp.name && exp.name === TRANSLATE_PIPE_NAME) {
            return true;
        }
        if (exp && exp.exp && exp.exp instanceof BindingPipe) {
            return this.expressionIsOrHasBindingPipe(exp?.exp);
        }
        return false;
    }

Seems exp can be null now.

Made a new PR with my changes which work with ng13: https://github.com/biesbjerg/ngx-translate-extract/pull/248

Also made a branch on my fork with the dist folder for who wants to use it directly in package.json : https://github.com/tiberiuzuld/ngx-translate-extract/tree/ng13-dist

"@biesbjerg/ngx-translate-extract": "github:tiberiuzuld/ngx-translate-extract#ng13-dist",

venraij commented 2 years ago

@tiberiuzuld I've made some further changes which fixed the issue even via npm for me. Tried it in 2 different projects of ng13. https://github.com/venraij/ngx-translate-extract/tree/angular-13

Unfortunately it breaks compatibility with lower angular versions because of the removal of MethodCall

venraij commented 2 years ago

I've also opened a pr for it #249 . It generally accomplishes the fixes without having to use a lot of in-depth changes.

bartholomej commented 2 years ago

Great job, guys! Actually, I still have two issues in this build.

Issues

No such file or directory

node\r: No such file or directory

This is probably due to the build being executed on Windows and having different line endings. Node.js on mac can't run the script as expected (tested with yarn, nodejs16, 14).

Cannot read property 'name'

An error occurred: TypeError: Cannot read property 'name' of null

This is probably an issue caused by the update to the ng13 compiler. It can be simulated by using the following example in your project template: <div [class.active]="+variable === -variable.item2">Active</div>

Solution

Both issues are fixed in my pull request. Jeez! so many pull requests! 😁

Important

Since we know this build contains huge breaking changes and will not be backwards compatible with older angular, it definitely deserves a major release upgrade. That's why I took the liberty of updating all dependencies as well :) I also described compatibility in readme.

Tests

My tests pass and everything works as it should with Angular 13 🎉 Tested on three production projects. In various combinations with nodejs 14, 16, npm, yarn

Can be use as version 8 @bartholomej/ngx-translate-extract

npm i @bartholomej/ngx-translate-extract --save-dev

or just change library in your package.json

"devDependencies": {
  "@bartholomej/ngx-translate-extract": "^8.0.1",
}

Let me know how it works ;)

cc @tiberiuzuld @venraij

venraij commented 2 years ago

Hello there, the build runs like a charm in my projects.

tarlepp commented 2 years ago

I can also confirm that this works as expected.

bartholomej commented 2 years ago

So, what do you think, @biesbjerg? Three of us worked on it and we made 25 commits :)

This solution seems to be working. The readme mentioned how the new version drops support for Angular 12 and older. Everything looks ready :)

Angular 13 is stable and we would like to use it in production. 🙏


In the meantime, you can see this exact version here and install it like this:

npm i @bartholomej/ngx-translate-extract --save-dev
vandres commented 2 years ago

Tested it with Node 14 and Angular 13, works as before. Thanks!

tarlepp commented 2 years ago

@biesbjerg could you give some feedback for this?

hthetiot commented 2 years ago

Fail for me on Angular 13.1 on Node 12.20.0, same work on Node 14.

> ngx-translate-extract --input ./src --output ./src/assets/i18n/{en,de,es,fr,ar,he,hi,it,ja,ko,pa,pt,ru,tr,zh}.po --clean --format pot

(node:40207) UnhandledPromiseRejectionWarning: SyntaxError: Unexpected token '.'
    at Loader.moduleStrategy (internal/modules/esm/translators.js:140:18)
(node:40207) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:40207) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
enchorb commented 2 years ago

@bartholomej I get the error mkdirp.sync is not a function, when running the following command: ngx-translate-extract --input ./src --output ./i18n/en.json --clean --sort --format namespaced-json --marker TRANSLATE

Even added mkdirp as a dev dependency but same issue, any idea what could be causing this?

adnanomerovic commented 2 years ago

I have the same problem as @enchorb

enchorb commented 2 years ago

@adnanomerovic Temporary solution using patch-package and this fix:

diff --git a/node_modules/@bartholomej/ngx-translate-extract/dist/cli/tasks/extract.task.js b/node_modules/@bartholomej/ngx-translate-extract/dist/cli/tasks/extract.task.js
index 23f06c6..d408e97 100644
--- a/node_modules/@bartholomej/ngx-translate-extract/dist/cli/tasks/extract.task.js
+++ b/node_modules/@bartholomej/ngx-translate-extract/dist/cli/tasks/extract.task.js
@@ -103,7 +103,7 @@ export class ExtractTask {
     save(output, collection) {
         const dir = path.dirname(output);
         if (!fs.existsSync(dir)) {
-            mkdirp.sync(dir);
+            fs.mkdirSync(dir, { recursive: true });
         }
         fs.writeFileSync(output, this.compiler.compile(collection));
     }
tarlepp commented 2 years ago

@biesbjerg could we get some feedback from you?

zeljkoantich commented 2 years ago

It works on:

Angular v13.0.2
node v16.13.1
npm v8.1.2
pongells commented 2 years ago

It works on:

Angular v13.0.2
node v16.13.1
npm v8.1.2

does not work for me

bartholomej commented 2 years ago

@enchorb @adnanomerovic @orestisioakeimidis You're right. I was able to replicate this and it was a case where the output folder did not exist before the extraction began.

This should be fixed in version v8.0.2

npm i @bartholomej/ngx-translate-extract --save-dev

Let me know how it works.

bartholomej commented 2 years ago

It works on:

Angular v13.0.2
node v16.13.1
npm v8.1.2

does not work for me

@pongells Can you be a little more specific, please? What doesn't work? Any error messages? Are you using latest version of ngx-translate-extract v8.0.2?

adnanomerovic commented 2 years ago

@enchorb @adnanomerovic @orestisioakeimidis You're right. I was able to replicate this and it was a case where the output folder did not exist before the extraction began.

This should be fixed in version v8.0.2

npm i @bartholomej/ngx-translate-extract --save-dev

Let me know how it works.

It's works! :D

pongells commented 2 years ago

It works on:

Angular v13.0.2
node v16.13.1
npm v8.1.2

does not work for me

@pongells Can you be a little more specific, please? What doesn't work? Any error messages? Are you using latest version of ngx-translate-extract v8.0.2?

8.0.2 was not out at the time :) works with latest version, thank you

zeljkoantich commented 2 years ago

If there are no problems any more, maybe this PR can me merged?

bartholomej commented 2 years ago

@zeljkoantich Yes, that's what we all need 😺 What do you think @biesbjerg? 🙏

sebastien-p commented 2 years ago

Good job @bartholomej!

Come on @biesbjerg can we please have some feedback from you?

masha-mariya4 commented 2 years ago

thanks @bartholomej! also for me downgrade biesbjerg/ngx-translate-extract to version 5.0.0 helped with this error

zeljkoantich commented 2 years ago

@bartholomej Maybe you should you release your fork officially, then we would switch to that fork?

Another alternative would be to have you here as a contributor with all rights. But I'm not sure if any contributor can provide you with those rights, or it has to be the owner.

The lib is used, and there are no official commits in over a year. https://github.com/biesbjerg/ngx-translate-extract/issues/257

Jace67 commented 2 years ago

@bartholomej your extractor is working on angular 13 but I am encountering a problem with output path using curly braces. I am not sure where to write this issue so I am writing it here.

My out file path has this path in the end: "/{en,jp}.json". Running the extractor will create a file "{en,jp}.json" at my output folder. Checking the file, the extraction was a success. So the only problem is that its saving the output in an incorrect filename.

oxydeon commented 2 years ago

@bartholomej your extractor is working on angular 13 but I am encountering a problem with output path using curly braces. I am not sure where to write this issue so I am writing it here.

My out file path has this path in the end: "/{en,jp}.json". Running the extractor will create a file "{en,jp}.json" at my output folder. Checking the file, the extraction was a success. So the only problem is that its saving the output in an incorrect filename.

Are you on Windows?

On Windows I must specify each output destination individually: ngx-translate-extract --output ./src/assets/i18n/fr.json ./src/assets/i18n/en.json

vadimwe commented 2 years ago

@enchorb @adnanomerovic @orestisioakeimidis You're right. I was able to replicate this and it was a case where the output folder did not exist before the extraction began.

This should be fixed in version v8.0.2

npm i @bartholomej/ngx-translate-extract --save-dev

Let me know how it works.

Works good! Thank you!

Jace67 commented 2 years ago

@bartholomej your extractor is working on angular 13 but I am encountering a problem with output path using curly braces. I am not sure where to write this issue so I am writing it here. My out file path has this path in the end: "/{en,jp}.json". Running the extractor will create a file "{en,jp}.json" at my output folder. Checking the file, the extraction was a success. So the only problem is that its saving the output in an incorrect filename.

Are you on Windows?

On Windows I must specify each output destination individually: ngx-translate-extract --output ./src/assets/i18n/fr.json ./src/assets/i18n/en.json

Is this a new limitation? Yes I am on Windows and your suggestion solves my issue but I didn't encounter this issue while I was using version 7.0.4 on Windows.

FrEaKmAn commented 2 years ago

For me @bartholomej/ngx-translate-extract works nicely, but is anyone using also @biesbjerg/ngx-translate-extract-marker. Is there an alternative compatible with @bartholomej/ngx-translate-extract? Current it fails with

Error: Cannot find module '@biesbjerg/ngx-translate-extract/dist/cli/tasks/extract.task'
stevengunneweg commented 2 years ago

I currently use both @bartholomej/ngx-translate-extract@8.0.2 and @biesbjerg/ngx-translate-extract-marker@1.0.0 without any issue, however I'm a little behind on some dependencies.

bartholomej commented 2 years ago

@FrEaKmAn Yes, I am using both @bartholomej/ngx-translate-extract@8.0.2 and @biesbjerg/ngx-translate-extract-marker@1.0.0 together with angular 13/14 and it works well.

Although marker is still legacy View Engine library (and probably will forever remain, since no one does updates either) 😿 And there's even pull request for marker IVY compatibility.

timeimp commented 1 year ago

Is there any reason for this to be held up any more? Everyone in the comments seems to be agreeing that things work?

Or is this repo considered deprecated and we should move to another offering?

michaelbromley commented 1 year ago

@timeimp This repo is unmaintained. After consultation with the interested parties, we took on maintainership of a fork. You can read the discussion here: https://github.com/biesbjerg/ngx-translate-extract/issues/246#issuecomment-1211682548