Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

i18next-scanner optional chaining throwing error #178

Closed
timneyens opened this issue Feb 28, 2020 · 11 comments
Closed

i18next-scanner optional chaining throwing error #178

timneyens opened this issue Feb 28, 2020 · 11 comments

Comments

@timneyens
Copy link

Hello,

We were trying optional chaining in our code but it seems the i18next-scanner does not like the syntax. Any suggestions how to work around this temporarily or is there an easy fix?

Kind regards

Version

  • i18next: 19.3.2
  • i18next-scanner: 2.10.3

Error

i18next-scanner: Unable to parse Trans component from src\app.jsx
SyntaxError: Unexpected token (28:19)

Code it crashes on:
`
const test = null;

console.log(test?.name);
`

@cheton
Copy link
Member

cheton commented Mar 5, 2020

Related to acornjs/acorn#891

So far the only way is to replace Acorn with Babel.

@krini
Copy link

krini commented Mar 6, 2020

We had a similar problem, however it seems to be a issue with trans components only. It's working fine for functions.

You don't really need optional chaining for the trans components in order to get the translations, so we did a workaround that replaces the optional chaining for trans components.

Create a customTransform where you handle trans components.

// removes optional chaining
const regex = /?.[/g;
let transContent = content.replace(regex, '[');
const regex1 = /?./g;
transContent = transContent.replace(regex1, '.');

const transOptions = { component: 'Trans', i18nKey: 'i18nKey', defaultsKey: 'defaults' };

parser.parseTransFromString(transContent, transOptions, (key, value) => {
parser.set(key, value.defaultValue);
});

@achtan
Copy link

achtan commented Mar 12, 2020

here is complete transform function based on @krini comment

  transform: function transform(file, enc, done) {
    const parser = this.parser;
    let content = fs.readFileSync(file.path, enc);


    const regex = /\?\.\[/g;
    let transContent = content.replace(regex, '[');
    const regex1 = /\?\./g;
    transContent = transContent.replace(regex1, '.');
    console.log(transContent)

    const transOptions = { component: 'Trans', i18nKey: 'i18nKey', defaultsKey: 'defaults' };

    parser.parseTransFromString(transContent, transOptions, (key, value) => {
      parser.set(key || value.defaultValue, value.defaultValue);
    });
    
    done();
  }

@shirazz
Copy link

shirazz commented Jun 20, 2020

@cheton The AcronJS optional chaining support landed few days back. Do you think this issue can be addressed now.

@shirazz
Copy link

shirazz commented Jul 24, 2020

@cheton Extremely sorry. This is by no means meant to bother you. I think you might be busy with other stuff. If you have some time to just provide some pointers on how to move ahead, i think i can work on this on my free time.

@spraylee
Copy link

here is complete transform function based on @krini comment

  transform: function transform(file, enc, done) {
    const parser = this.parser;
    let content = fs.readFileSync(file.path, enc);


    const regex = /\?\.\[/g;
    let transContent = content.replace(regex, '[');
    const regex1 = /\?\./g;
    transContent = transContent.replace(regex1, '.');
    console.log(transContent)

    const transOptions = { component: 'Trans', i18nKey: 'i18nKey', defaultsKey: 'defaults' };

    parser.parseTransFromString(transContent, transOptions, (key, value) => {
      parser.set(key || value.defaultValue, value.defaultValue);
    });
    
    done();
  }

I tried as you said, but the error is still exsit. Can you give me some help?

My "i18next-scanner-config.js" is as follows:

var fs = require('fs')
var chalk = require('chalk')

module.exports = {
  input: [
    'src/**/*.{js,jsx}',
    // Use ! to filter out files or directories
    '!src/**/*.spec.{js,jsx}',
    '!src/i18n/**',
    '!**/node_modules/**',
  ],
  output: './',
  options: {
    debug: true,
    func: {
      list: ['i18next.t', 'i18n.t'],
      extensions: ['.js', '.jsx'],
    },
    trans: {
      component: 'Trans',
      i18nKey: 'i18nKey',
      defaultsKey: 'defaults',
      extensions: ['.js', '.jsx'],
      fallbackKey: function (ns, value) {
        return value
      },
      acorn: {
        ecmaVersion: 10, // defaults to 10
        sourceType: 'module', // defaults to 'module'
        // Check out https://github.com/acornjs/acorn/tree/master/acorn#interface for additional options
      },
    },
    lngs: ['en', 'cn'],
    ns: ['translation'],
    // ns: ['locale', 'resource'],
    defaultLng: 'en',
    defaultNs: 'translation',
    // defaultNs: 'resource',
    defaultValue: '__STRING_NOT_TRANSLATED__',
    resource: {
      loadPath: 'public/locales/{{lng}}/{{ns}}.json',
      savePath: 'public/locales/{{lng}}/{{ns}}.json',
      jsonIndent: 2,
      lineEnding: '\n',
    },
    nsSeparator: false, // namespace separator
    keySeparator: false, // key separator
    interpolation: {
      prefix: '{{',
      suffix: '}}',
    },
  },
  transform: function customTransform(file, enc, done) {
    'use strict'

    const parser = this.parser
    let content = fs.readFileSync(file.path, enc)

    const regex = /\?\.\[/g
    let transContent = content.replace(regex, '[')
    const regex1 = /\?\./g
    transContent = transContent.replace(regex1, '.')

    const transOptions = { component: 'Trans', i18nKey: 'i18nKey', defaultsKey: 'defaults' }

    parser.parseTransFromString('', transOptions, (key, value) => {
      parser.set(key || value.defaultValue, value.defaultValue)
    })

    done()
  },
}

@krini
Copy link

krini commented Jul 30, 2020

3/3-21
It works with the updated version, without the below config.


I'm running the scanner with

vfs.src(['./src/**/*.js'])
  .pipe(sort()) // Sort files in stream by path
  .pipe(scanner(options, customTransform))
  .pipe(vfs.dest('./'));

In my options trans is set to false because it is transformed in customTransform

const options = {
  debug: false,
  removeUnusedKeys: true,
  sort: true,
  attr: false,
  func: false, // is transformed in customTransform
  trans: false, // is transformed in customTransform
  ...
};

@6uliver
Copy link

6uliver commented Jan 13, 2021

I had the same problem which is resolved since I've updated to 3.0.0. As you can read in the release notes: "Update Acorn to 8.0 to support new syntax features"

Could someone else confirm that the update resolves the problem? If so please close this issue.

@austinhc-ibm
Copy link

The problem is also resovled for me after updated to 3.0.0 and modify the ecmaVersion to 11 in i18next-scanner-config.js

"acorn": {
      "ecmaVersion": 11,
      "sourceType": "module"
    }

@marcuzgabriel
Copy link

@austinhc-ibm I can confirm that updating the 18next-scanner to latest 3.0.0 will ensure that the scanner can handle modern JS when parsing Trans components.

@shirazz
Copy link

shirazz commented Mar 3, 2021

I had the same problem which is resolved since I've updated to 3.0.0. As you can read in the release notes: "Update Acorn to 8.0 to support new syntax features"

Could someone else confirm that the update resolves the problem? If so please close this issue.

I can also confirm this works fine.

"acorn": {
      "ecmaVersion": 11,
      "sourceType": "module"
    }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants