Skip to content
This repository has been archived by the owner on Apr 22, 2024. It is now read-only.

Commit

Permalink
⭐ new: add locale directory setting
Browse files Browse the repository at this point in the history
  • Loading branch information
kazupon committed Jun 26, 2018
1 parent 35f06a4 commit 3dec7a5
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 45 deletions.
28 changes: 14 additions & 14 deletions generator/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ function buildEnvContent (values) {
}

module.exports = (api, options, rootOptions) => {
const { locale, fallbackLocale, enableInSFC } = options
const { locale, fallbackLocale, localeDir, enableInSFC } = options
debug('options', options)
debug('rootOptions', rootOptions)

try {
const lang = api.hasPlugin('typescript') ? 'ts' : 'js'
const classComponent = checkInstalled('./node_modules/vue-class-component/package.json') &&
checkInstalled('./node_modules/vue-property-decorator/package.json')
const additionalOptions = { ...options, ...{ lang, classComponent } }
const additionalOptions = { ...options, ...{ lang, localeDir, classComponent } }
debug('additionalOptions', additionalOptions)

/*
Expand All @@ -48,7 +48,7 @@ module.exports = (api, options, rootOptions) => {
'vue-i18n': '^8.0.0'
},
vue: {
pluginOptions: { enableInSFC }
pluginOptions: { locale, fallbackLocale, localeDir, enableInSFC }
}
}

Expand All @@ -72,6 +72,14 @@ module.exports = (api, options, rootOptions) => {

api.extendPackage(pkg)

/*
* Modify main.(js|ts)
*/
const file = lang === 'ts' ? 'src/main.ts' : 'src/main.js'
debug('target file', file)
api.injectImports(file, `import i18n from './i18n'`)
api.injectRootOptions(file, `i18n,`)

/*
* render templates
*/
Expand All @@ -83,14 +91,6 @@ module.exports = (api, options, rootOptions) => {
if (enableInSFC) {
api.render('./templates/sfc', { ...additionalOptions })
}

/*
* Modify main.(js|ts)
*/
const file = lang === 'ts' ? 'src/main.ts' : 'src/main.js'
debug('target file', file)
api.injectImports(file, `import i18n from './i18n'`)
api.injectRootOptions(file, `i18n,`)
} catch (e) {
api.exitLog(`unexpected error in vue-cli-plugin-i18n: ${e.message}`, 'error')
return
Expand All @@ -113,17 +113,17 @@ module.exports = (api, options, rootOptions) => {
}
}

const localesDirPath = api.resolve('src/locales')
const localesDirPath = api.resolve(`src/${localeDir}`)
if (!exists(localesDirPath)) {
if (!mkdir(localesDirPath)) {
api.exitLog(`cannot make ${localesDirPath}`, 'error')
return
}
}

writeLocaleFile(api.resolve(`src/locales/${locale}.json`))
writeLocaleFile(api.resolve(`src/${localeDir}/${locale}.json`))
if (locale !== fallbackLocale) {
writeLocaleFile(api.resolve(`src/locales/${fallbackLocale}.json`))
writeLocaleFile(api.resolve(`src/${localeDir}/${fallbackLocale}.json`))
}

const envPath = api.resolve('.env')
Expand Down
2 changes: 1 addition & 1 deletion generator/templates/js/src/i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import VueI18n from 'vue-i18n'
Vue.use(VueI18n)

function loadLocaleMessages () {
const locales = require.context('./locales', true, /[a-z0-9]+\.json$/i)
const locales = require.context('./<%- localeDir %>', true, /[a-z0-9]+\.json$/i)
const messages = {}
locales.keys().forEach(key => {
const matched = key.match(/([a-z0-9]+)\./i)
Expand Down
2 changes: 1 addition & 1 deletion generator/templates/ts/src/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import VueI18n, { LocaleMessages } from 'vue-i18n'
Vue.use(VueI18n)

function loadLocaleMessages (): LocaleMessages {
const locales = require.context('./locales', true, /[a-z0-9]+\.json$/i)
const locales = require.context('./<%- localeDir %>', true, /[a-z0-9]+\.json$/i)
const messages: LocaleMessages = {}
locales.keys().forEach(key => {
const matched = key.match(/([a-z0-9]+)\./i)
Expand Down
5 changes: 5 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
const debug = require('debug')('vue-cli-plugin-i18n:service')

module.exports = (api, options) => {
const { enableInSFC } = options.pluginOptions
debug('options', options)

api.chainWebpack(webpackConfig => {
debug('chainWebpack called')

if (enableInSFC) {
webpackConfig.module
.rule('i18n')
Expand Down
6 changes: 6 additions & 0 deletions prompts.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@ module.exports = [{
message: 'The locale of project fallback localization.',
validate: input => !!input,
default: 'en'
}, {
type: 'input',
name: 'localeDir',
message: 'The directory where store localization messages of project. It\'s stored under `src` directory.',
validate: input => !!input,
default: 'locales'
}, {
type: 'confirm',
name: 'enableInSFC',
Expand Down
70 changes: 41 additions & 29 deletions ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ function assignValuesWithPath (path, value, messages) {

function getLocales (targetPath) {
debug('getLocales', targetPath)
return fs.readdirSync(`${targetPath}/src/locales`).map(locale => {
return fs.readdirSync(targetPath).map(locale => {
return path.basename(locale, '.json')
})
}

function getLocaleMessages (targetPath, locales) {
debug('getLocaleMessages', targetPath, locales)
return locales.reduce((val, locale) => {
const fullPath = `${targetPath}/src/locales/${locale}.json`
const fullPath = `${targetPath}/${locale}.json`
val[locale] = require(fullPath)
delete require.cache[require.resolve(fullPath)]
return val
Expand All @@ -65,52 +65,60 @@ function writeLocaleMessages (targetPath, locale, messages, order) {
const sortedMessages = sortObject(messages, order)
debug('writeLocaleMessages after:', sortedMessages)
return fs.writeFileSync(
`${targetPath}/src/locales/${locale}.json`,
`${targetPath}/${locale}.json`,
JSON.stringify(sortedMessages, null, 2), { encoding: 'utf8' }
)
}

module.exports = api => {
const { getSharedData, setSharedData, watchSharedData } = api.namespace('vue-i18n-')

function setupAddon (path) {
debug(`setupAddon: path -> ${path}`)
function setupAddon (path, options) {
debug(`setupAddon: path -> ${path}, options -> ${options}`)
const localeDir = options.localeDir
setSharedData('order', 'asc')
const env = readEnv(`${path}/.env`)
const current = env['VUE_APP_I18N_LOCALE'] || 'en'
const defaultLocale = env['VUE_APP_I18N_FALLBACK_LOCALE'] || 'en'
setSharedData('current', defaultLocale)
setSharedData('defaultLocale', defaultLocale)
debug(`setupAddon: current -> ${current}, defaultLocale -> ${defaultLocale}`)
const locales = getLocales(path)
const locales = getLocales(`${path}/src/${localeDir}`)
setSharedData('locales', locales)
const messages = getLocaleMessages(path, locales)
const messages = getLocaleMessages(`${path}/src/${localeDir}`, locales)
setSharedData('localeMessages', messages)
setSharedData('localePaths', getLocalePaths(messages))
}

try {
let currentProject = null
let currentConfig = null

api.onProjectOpen((project, previousProject) => {
debug('onProjectOpen', project, previousProject)
})

api.onPluginReload(project => {
debug('onPluginReload', project)
setupAddon(project.path)
const rawConfig = require(`${project.path}/vue.config`)
const config = rawConfig.pluginOptions || { localeDir: 'locales' }
if (!config.localeDir) { config.localeDir = 'locales' }
debug('onPluginReload : load vue.config', config)
setupAddon(project.path, config)
currentProject = project
currentConfig = config
})

api.onAction('add-path-action', ({ path, locale }) => {
debug('add-path-action onAction', path, locale)
if (!currentProject && !path) {
if (!currentProject || !currentConfig || !path) {
console.error('add-path-action: invalid pre-condition !!')
return
}

const locales = getLocales(currentProject.path)
const messages = getLocaleMessages(currentProject.path, locales)
const localePath = `${currentProject.path}/src/${currentConfig.localeDir}`
const locales = getLocales(localePath)
const messages = getLocaleMessages(localePath, locales)
const orderData = getSharedData('order')

const additional = {}
Expand All @@ -120,21 +128,22 @@ module.exports = api => {
debug('additional', additional)
const message = deepmerge(original, unflatten(additional))
debug('merged', message)
writeLocaleMessages(currentProject.path, locale, message, orderData.value)
writeLocaleMessages(localePath, locale, message, orderData.value)
messages[locale] = message
setSharedData('localeMessages', messages)
setSharedData('localePaths', getLocalePaths(messages))
})

api.onAction('update-path-action', ({ path, old, locale }) => {
debug('update-path-action onAction', path, old, locale)
if (!currentProject && !path && !old) {
if (!currentProject || !currentConfig || !path || !old) {
console.error('update-path-action: invalid pre-condition !!')
return
}

const locales = getLocales(currentProject.path)
const messages = getLocaleMessages(currentProject.path, locales)
const localePath = `${currentProject.path}/src/${currentConfig.localeDir}`
const locales = getLocales(localePath)
const messages = getLocaleMessages(localePath, locales)
const orderData = getSharedData('order')

const original = messages[locale]
Expand All @@ -143,28 +152,29 @@ module.exports = api => {
delete flattendOriginal[old]
const newMessage = unflatten(flattendOriginal)
assignValuesWithPath(path, oldValues, newMessage)
writeLocaleMessages(currentProject.path, locale, newMessage, orderData.value)
writeLocaleMessages(localePath, locale, newMessage, orderData.value)
messages[locale] = newMessage
setSharedData('localeMessages', messages)
setSharedData('localePaths', getLocalePaths(messages))
})

api.onAction('delete-path-action', ({ path, locale }) => {
debug('delete-path-action onAction', path, locale)
if (!currentProject && !path) {
if (!currentProject || !currentConfig || !path) {
console.log('delete-path-action: invalid pre-condition')
return
}

const locales = getLocales(currentProject.path)
const messages = getLocaleMessages(currentProject.path, locales)
const localePath = `${currentProject.path}/src/${currentConfig.localeDir}`
const locales = getLocales(localePath)
const messages = getLocaleMessages(localePath, locales)
const orderData = getSharedData('order')

const message = messages[locale]
const flattendMessage = flatten(message)
delete flattendMessage[path]
messages[locale] = unflatten(flattendMessage)
const ret = writeLocaleMessages(currentProject.path, locale, messages[locale], orderData.value)
const ret = writeLocaleMessages(localePath, locale, messages[locale], orderData.value)
debug('write data', ret)

setSharedData('localeMessages', messages)
Expand All @@ -173,46 +183,48 @@ module.exports = api => {

api.onAction('edit-message-action', ({ path, value, locale }) => {
debug('edit-message-action onAction', path, value, locale)
if (!currentProject && !path) {
if (!currentProject || !currentConfig || !path) {
console.error('edit-message-action: invalid pre-condition !!')
return
}

const locales = getLocales(currentProject.path)
const localeMessages = getLocaleMessages(currentProject.path, locales)
const localePath = `${currentProject.path}/src/${currentConfig.localeDir}`
const locales = getLocales(localePath)
const localeMessages = getLocaleMessages(localePath, locales)
const orderData = getSharedData('order')

const messages = localeMessages[locale]
const flattendMessage = flatten(messages)
flattendMessage[path] = value
localeMessages[locale] = unflatten(flattendMessage)
writeLocaleMessages(currentProject.path, locale, localeMessages[locale], orderData.value)
writeLocaleMessages(localePath, locale, localeMessages[locale], orderData.value)

setSharedData('localeMessages', localeMessages)
setSharedData('localePaths', getLocalePaths(localeMessages))
})

api.onAction('add-locale-action', ({ locale }) => {
debug('add-locale-action onAction', locale)
if (!currentProject && !locale) {
if (!currentProject || !currentConfig || !locale) {
console.error('add-locale-action: invalid pre-condition')
return
}

const localePath = `${currentProject.path}/src/${currentConfig.localeDir}`
const defaultLocaleData = getSharedData('defaultLocale')
const defaultLocale = defaultLocaleData.value
const oldMessages = getLocaleMessages(currentProject.path, getLocales(currentProject.path))
const oldMessages = getLocaleMessages(localePath, getLocales(localePath))
const orderData = getSharedData('order')

const oldFlattendMessages = flatten(oldMessages[defaultLocale])
const newLocaleMessages = Object.keys(oldFlattendMessages).reduce((val, p) => {
val[p] = oldFlattendMessages[p]
return val
}, {})
writeLocaleMessages(currentProject.path, locale, unflatten(newLocaleMessages), orderData.value)
writeLocaleMessages(localePath, locale, unflatten(newLocaleMessages), orderData.value)

const locales = getLocales(currentProject.path)
const messages = getLocaleMessages(currentProject.path, locales)
const locales = getLocales(localePath)
const messages = getLocaleMessages(localePath, locales)
setSharedData('localeMessages', messages)
setSharedData('localePaths', getLocalePaths(messages))
setSharedData('locales', locales)
Expand Down

0 comments on commit 3dec7a5

Please sign in to comment.