bencodezen / vue-enterprise-boilerplate

An ever-evolving, very opinionated architecture and dev environment for new Vue SPA projects using Vue CLI.
7.77k stars 1.32k forks source link

Use the dynamic store module import for lang files #104

Closed ghost closed 5 years ago

ghost commented 5 years ago

Hi,

I would like to thank you first. I learned a lot with your boilerplate and your conferences.

I try unsuccessfully to edit the file state/modules/index.js to automatically import languages for Vue118

I would like to have as object structure :

{
  en: {
    homepage: {...},
    article: {...},
  },
  fr: {
    homepage: {...},
    article: {...},
  }
}

But now I have

{
  en: {
    messages: {
      homepage: {...},
      article: {...},
    }
  },
  fr: {
    messages: {
      homepage: {...},
      article: {...},
    }
  }
}

Can I be helped to remove the "messages" object?

langs folder structure

+messages
  +de
    homepage.json
    article.json
    ...
  +fr
    homepage.json
    article.json
    ...
  index.js
index.js

langs/messages/index.js

import camelCase from 'lodash/camelCase'

const requireModule = require.context('.', true, /^((?!\.unit\.).)*\.json$/)
const root = {}

requireModule.keys().forEach(fileName => {
  if (fileName === './index.js') return

  const modulePath = fileName
    .replace(/^\.\//, '')
    .replace(/\.\w+$/, '')
    .split(/\//)
    .map(camelCase)

  const { messages } = { ...getNamespace(root, modulePath) }

  messages[modulePath.pop()] = { ...requireModule(fileName) }

  function getNamespace(subtree, path) {
    if (path.length === 1) return subtree
    const namespace = path.shift()
    subtree[namespace] = { messages: {}, ...subtree[namespace] }
    return getNamespace(subtree[namespace], path)
  }
})

export default root

langs/index.js

import Vue from 'vue'
import VueI18n from 'vue-i18n'
import messages from '@langs/messages'

Vue.use(VueI18n)

export default new VueI18n({
    locale: 'de',
    fallbackLocale: 'de',
    messages: {
    fr: langs.fr.messages,
    de: langs.de.messages
  }
})

the desired result is to not need to manually import each new language and have this :

export default new VueI18n({
    locale: 'de',
    fallbackLocale: 'de',
    messages
})
chrisvfritz commented 5 years ago

If I've understood correctly, I think you'd want to update:

const { messages } = { ...getNamespace(root, modulePath) }

messages[modulePath.pop()] = { ...requireModule(fileName) }

function getNamespace(subtree, path) {
  if (path.length === 1) return subtree
  const namespace = path.shift()
  subtree[namespace] = { messages: {}, ...subtree[namespace] }
  return getNamespace(subtree[namespace], path)
}

to something like:

const messages = getNamespace(root, modulePath)

messages[modulePath.pop()] = { ...requireModule(fileName) }

function getNamespace(subtree, path) {
  if (path.length === 1) return subtree
  const namespace = path.shift()
  return getNamespace(subtree[namespace], path)
}
ghost commented 5 years ago

Thank you for taking the time to answer me.

Almost! With your proposition subtree[namespace] inside getNamespace function is undefined. I added subtree[namespace] = { ...subtree[namespace] } to make it work. Thanks for your help.

  const messages = getNamespace(root, modulePath)

  messages[modulePath.pop()] = { ...requireModule(fileName) }

  function getNamespace(subtree, path) {
    if (path.length === 1) return subtree
    const namespace = path.shift()
    subtree[namespace] = { ...subtree[namespace] }
    return getNamespace(subtree[namespace], path)
  }
ghost commented 5 years ago

other solution

const requireModule = require.context('.', true, /\.json$/)
const langs = {}

requireModule.keys().forEach(fileName => {
  const path = fileName.replace(/(\.\/|\.json)/g, '')
  const moduleName = path.split('/')

  if (!langs.hasOwnProperty(moduleName[0])) {
    langs[moduleName[0]] = { [moduleName[1]]: {} }
  }
  langs[moduleName[0]][moduleName[1]] = requireModule(fileName)
})

export default langs