I18n-module: Allow decorators (and TypeScript) in component

Created on 30 Apr 2018  路  11Comments  路  Source: nuxt-community/i18n-module

What problem does this feature solve?

Allow using decorators inside component (and TypeScript).

I'm using TypeScript in .vue files with nuxt-property-decorator.
Since nuxt-i18n 3.x is using acron to parse each component files to check i18n property, it will throw exception on decorations (e.g. @Component from nuxt-property-decorator)

As I know, acron has a plugin acron-es7 can parse.
But the better solution is to load component files via webpack processor that webpack will solve the future syntax.

What does the proposed changes look like?

While using nuxt-i18n 3.x, I can use these syntax below in component file:

<script lang="ts">
import {
  Component,
  Vue,
} from 'nuxt-property-decorator'
import AppLogo from '~/components/AppLogo.vue'

@Component({ // <- acron (or nuxt-i18n) should not blame here
  components: {
    AppLogo
  }
})
export default class extends Vue {
}
</script>

This feature request is available on Nuxt.js community (#c71)
feature-request

Most helpful comment

@Seb-L Thank you for that. I'll test it out and if it works will make a PR for it.

(BTW, extractComponentOptions shouldn't be async)

All 11 comments

Hi @david50407 !
Thanks for reporting this issue, I admit that I never thought of TypeScript while developing v3...
I'd love to have a way of loading components via Webpack to get their options but I simply don't know how to get started :disappointed: I did a quick test with acorn-es7 plugin but it's not plug & play, I'll need to give it a better try.
I'd love to have your take on the Webpack approach, I agree it would be the best solution for this.

I have exactly same issue. @paulgv could you provide an example (workaround) for TS users inside documentation?

@AndrewBogdanovTSS For now you can disable parsing by setting parsePages option to false (https://nuxt-community.github.io/nuxt-i18n/routing.html#custom-paths)
@paulgv I think it is better in the package to avoid parsing the components because in the future it may cause similar problems. Maybe it is better to add the option of defining a pages in a seperate JS file?

How will it affect overall usage of nuxt-i18n? As far as I understand the parsing is needed to properly generate routes? Does it mean that routes should be generated manually in this case?

@AndrewBogdanovTSS If you do not use nuxtI18n option in the components then everything should work ok :) I had no problems with generating routes automatically.

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Hello,
This bug is not fixed. Unfortunately, nuxt-i18n is incompatible with TypeScript.

@pamls Unfortunately it isn't. The recommended workaround is to disable pages parsing and fallback on the modules configuration to customize paths:

Any update on this?

Got the issue as well in a Nuxt + TS + Decorators project, so I tried to replace acorn by @babel/parser and @babel/traverse.
It seems to return the componentOptions as intended but I didn't have the time to test it properly yet.

./src/helpers/components.js

const { readFileSync } = require('fs')
const { COMPONENT_OPTIONS_KEY } = require('./constants')

const parser = require('@babel/parser')
const traverse = require('@babel/traverse').default

// Must not be an explicit dependency to avoid version mismatch issue.
// See https://github.com/nuxt-community/nuxt-i18n/issues/297
const compiler = require('vue-template-compiler')

exports.extractComponentOptions = async (path) => {
  let componentOptions = {}
  const Component = compiler.parseComponent(readFileSync(path).toString())
  if (!Component.script || Component.script.content.length < 1) {
    return componentOptions
  }

  const script = Component.script.content
  const parsed = parser.parse(script, {
    sourceType: 'module',
    plugins: [
      'dynamicImport',
      'exportDefaultFrom',
      'typescript',
      'classProperties',
      'decorators-legacy',
      'estree'
    ]
  })

  traverse(parsed, {
    enter (path) {
      if (path.node.type === 'Property') {
        if (path.node.key.name === COMPONENT_OPTIONS_KEY) {
          const data = script.substring(path.node.start, path.node.end)
          componentOptions = eval(`({${data}})`)[COMPONENT_OPTIONS_KEY]
        }
      }
    }
  })

  return componentOptions
}

@Seb-L Thank you for that. I'll test it out and if it works will make a PR for it.

(BTW, extractComponentOptions shouldn't be async)

Was this page helpful?
0 / 5 - 0 ratings