ngx-translate-extract icon indicating copy to clipboard operation
ngx-translate-extract copied to clipboard

Angular 13 compatibility

Open bartholomej opened this issue 3 years ago • 42 comments

What is in this PR?

  • Building UMD

Why?

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

Notes

  • Possible breaking changes!
  • Tested with:
    • Angular 12.0.0 (with ivy), nodejs14, nodejs16
    • Angular 13.0.0 (with ivy), nodejs14, nodejs16

More testing would be appreciated :)

bartholomej avatar Nov 11 '21 16:11 bartholomej

@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.

venraij avatar Nov 15 '21 08:11 venraij

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

tiberiuzuld avatar Nov 15 '21 10:11 tiberiuzuld

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

venraij avatar Nov 15 '21 11:11 venraij

@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 avatar Nov 15 '21 13:11 tiberiuzuld

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'
}

tiberiuzuld avatar Nov 15 '21 13:11 tiberiuzuld

@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

venraij avatar Nov 15 '21 13:11 venraij

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 avatar Nov 15 '21 13:11 tiberiuzuld

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 avatar Nov 15 '21 16:11 tiberiuzuld

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",

tiberiuzuld avatar Nov 15 '21 17:11 tiberiuzuld

@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 avatar Nov 15 '21 19:11 venraij

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

venraij avatar Nov 15 '21 20:11 venraij

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

bartholomej avatar Nov 23 '21 18:11 bartholomej

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

venraij avatar Nov 23 '21 20:11 venraij

I can also confirm that this works as expected.

tarlepp avatar Nov 26 '21 16:11 tarlepp

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

bartholomej avatar Nov 26 '21 16:11 bartholomej

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

vandres avatar Nov 29 '21 12:11 vandres

@biesbjerg could you give some feedback for this?

tarlepp avatar Dec 11 '21 23:12 tarlepp

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.

hthetiot avatar Dec 15 '21 23:12 hthetiot

@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?

enchorb avatar Dec 26 '21 17:12 enchorb

I have the same problem as @enchorb

adnanomerovic avatar Dec 30 '21 09:12 adnanomerovic

@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));
     }

enchorb avatar Jan 08 '22 16:01 enchorb

@biesbjerg could we get some feedback from you?

tarlepp avatar Jan 09 '22 17:01 tarlepp

It works on:

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

zeljkoantich avatar Jan 10 '22 09:01 zeljkoantich

It works on:

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

does not work for me

pongells avatar Jan 10 '22 10:01 pongells

@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 avatar Jan 12 '22 18:01 bartholomej

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?

bartholomej avatar Jan 12 '22 18:01 bartholomej

@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

adnanomerovic avatar Jan 13 '22 10:01 adnanomerovic

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

pongells avatar Jan 18 '22 09:01 pongells

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

zeljkoantich avatar Jan 27 '22 09:01 zeljkoantich

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

bartholomej avatar Jan 27 '22 09:01 bartholomej