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

Custom locale loader #35

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 4 additions & 9 deletions lib/rules/no-html-messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
const { extname } = require('path')
const parse5 = require('parse5')
const {
UNEXPECTED_ERROR_LOCATION,
findExistLocaleMessage,
getLocaleMessages,
extractJsonInfo,
generateJsonAst
generateJsonAst,
validateSettings
} = require('../utils/index')
const debug = require('debug')('eslint-plugin-vue-i18n:no-html-messages')

Expand Down Expand Up @@ -45,16 +45,11 @@ function create (context) {
return {}
}

const { settings } = context
if (!settings['vue-i18n'] || !settings['vue-i18n'].localeDir) {
context.report({
loc: UNEXPECTED_ERROR_LOCATION,
message: `You need to 'localeDir' at 'settings. See the 'eslint-plugin-vue-i18n documentation`
})
if (!validateSettings(context)) {
return {}
}

const localeMessages = getLocaleMessages(settings['vue-i18n'].localeDir)
const localeMessages = getLocaleMessages(context)
const targetLocaleMessage = findExistLocaleMessage(filename, localeMessages)
if (!targetLocaleMessage) {
debug(`ignore ${filename} in no-html-messages`)
Expand Down
38 changes: 16 additions & 22 deletions lib/rules/no-missing-keys.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,82 +4,76 @@
'use strict'

const {
UNEXPECTED_ERROR_LOCATION,
defineTemplateBodyVisitor,
getLocaleMessages,
findMissingsFromLocaleMessages
findMissingsFromLocaleMessages,
validateSettings
} = require('../utils/index')

function create (context) {
const { settings } = context
if (!settings['vue-i18n'] || !settings['vue-i18n'].localeDir) {
context.report({
loc: UNEXPECTED_ERROR_LOCATION,
message: `You need to set 'localeDir' at 'settings. See the 'eslint-plugin-vue-i18n documentation`
})
if (!validateSettings(context)) {
return {}
}

const localeDir = settings['vue-i18n'].localeDir
const localeMessages = getLocaleMessages(localeDir)
const localeMessages = getLocaleMessages(context)

return defineTemplateBodyVisitor(context, {
"VAttribute[directive=true][key.name='t']" (node) {
checkDirective(context, localeDir, localeMessages, node)
checkDirective(context, localeMessages, node)
},

"VAttribute[directive=true][key.name.name='t']" (node) {
checkDirective(context, localeDir, localeMessages, node)
checkDirective(context, localeMessages, node)
},

"VElement[name=i18n] > VStartTag > VAttribute[key.name='path']" (node) {
checkComponent(context, localeDir, localeMessages, node)
checkComponent(context, localeMessages, node)
},

"VElement[name=i18n] > VStartTag > VAttribute[key.name.name='path']" (node) {
checkComponent(context, localeDir, localeMessages, node)
checkComponent(context, localeMessages, node)
},

CallExpression (node) {
checkCallExpression(context, localeDir, localeMessages, node)
checkCallExpression(context, localeMessages, node)
}
}, {
CallExpression (node) {
checkCallExpression(context, localeDir, localeMessages, node)
checkCallExpression(context, localeMessages, node)
}
})
}

function checkDirective (context, localeDir, localeMessages, node) {
function checkDirective (context, localeMessages, node) {
if ((node.value && node.value.type === 'VExpressionContainer') &&
(node.value.expression && node.value.expression.type === 'Literal')) {
const key = node.value.expression.value
if (!key) {
// TODO: should be error
return
}
const missings = findMissingsFromLocaleMessages(localeMessages, key, localeDir)
const missings = findMissingsFromLocaleMessages(localeMessages, key)
if (missings.length) {
missings.forEach(missing => context.report({ node, ...missing }))
}
}
}

function checkComponent (context, localeDir, localeMessages, node) {
function checkComponent (context, localeMessages, node) {
if (node.value && node.value.type === 'VLiteral') {
const key = node.value.value
if (!key) {
// TODO: should be error
return
}
const missings = findMissingsFromLocaleMessages(localeMessages, key, localeDir)
const missings = findMissingsFromLocaleMessages(localeMessages, key)
if (missings.length) {
missings.forEach(missing => context.report({ node, ...missing }))
}
}
}

function checkCallExpression (context, localeDir, localeMessages, node) {
function checkCallExpression (context, localeMessages, node) {
const funcName = (node.callee.type === 'MemberExpression' && node.callee.property.name) || node.callee.name

if (!/^(\$t|t|\$tc|tc)$/.test(funcName) || !node.arguments || !node.arguments.length) {
Expand All @@ -95,7 +89,7 @@ function checkCallExpression (context, localeDir, localeMessages, node) {
return
}

const missings = findMissingsFromLocaleMessages(localeMessages, key, localeDir)
const missings = findMissingsFromLocaleMessages(localeMessages, key)
if (missings.length) {
missings.forEach(missing => context.report({ node, ...missing }))
}
Expand Down
12 changes: 4 additions & 8 deletions lib/rules/no-unused-keys.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ const {
findExistLocaleMessage,
getLocaleMessages,
extractJsonInfo,
generateJsonAst
generateJsonAst,
validateSettings
} = require('../utils/index')
const debug = require('debug')('eslint-plugin-vue-i18n:no-unused-keys')

Expand Down Expand Up @@ -79,16 +80,11 @@ function create (context) {
return {}
}

const { settings } = context
if (!settings['vue-i18n'] || !settings['vue-i18n'].localeDir) {
context.report({
loc: UNEXPECTED_ERROR_LOCATION,
message: `You need to 'localeDir' at 'settings. See the 'eslint-plugin-vue-i18n documentation`
})
if (!validateSettings(context)) {
return {}
}

const localeMessages = getLocaleMessages(settings['vue-i18n'].localeDir)
const localeMessages = getLocaleMessages(context)
const targetLocaleMessage = findExistLocaleMessage(filename, localeMessages)
if (!targetLocaleMessage) {
debug(`ignore ${filename} in no-unused-keys`)
Expand Down
42 changes: 31 additions & 11 deletions lib/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,17 +40,20 @@ function loadLocaleMessages (pattern) {
})
}

let localeMessages = null // locale messages
let localeDir = null // locale dir

function getLocaleMessages (localeDirectory) {
if (localeDir !== localeDirectory) {
localeDir = localeDirectory
localeMessages = loadLocaleMessages(localeDir)
} else {
localeMessages = localeMessages || loadLocaleMessages(localeDir)
const localeDirCache = {} // locale messages

function getLocaleMessages (context) {
const settings = getSettings(context)

if (settings.locales) {
return settings.locales
}

if (!localeDirCache[settings.localeDir]) {
localeDirCache[settings.localeDir] = loadLocaleMessages(settings.localeDir)
}
return localeMessages

return localeDirCache[settings.localeDir]
}

function findMissingsFromLocaleMessages (localeMessages, key) {
Expand Down Expand Up @@ -106,12 +109,29 @@ function generateJsonAst (context, json, filename) {
return ast
}

function getSettings (context) {
return context.settings['vue-i18n'] || {}
}

function validateSettings (context) {
const settings = getSettings(context)
const isValid = !!(settings.localeDir || settings.locales)
if (!isValid) {
context.report({
loc: UNEXPECTED_ERROR_LOCATION,
message: 'You need to define locales in settings. See the eslint-plugin-vue-i18n documentation'
})
}
return isValid
}

module.exports = {
UNEXPECTED_ERROR_LOCATION,
defineTemplateBodyVisitor,
getLocaleMessages,
findMissingsFromLocaleMessages,
findExistLocaleMessage,
extractJsonInfo,
generateJsonAst
generateJsonAst,
validateSettings
}
19 changes: 18 additions & 1 deletion tests/lib/rules/no-missing-keys.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ const settings = {
}
}

const settingLocales = {
'vue-i18n': {
locales: [{ name: 'en', messages: { hello: 'hello world' }}]
}
}

const tester = new RuleTester({
parser: require.resolve('vue-eslint-parser'),
parserOptions: { ecmaVersion: 2015 }
Expand Down Expand Up @@ -60,6 +66,10 @@ tester.run('no-missing-keys', rule, {
code: `<template>
<p v-t="'hello'"></p>
</template>`
}, {
// using message settings
settings: settingLocales,
code: `$t('hello')`
}],

invalid: [{
Expand Down Expand Up @@ -106,7 +116,7 @@ tester.run('no-missing-keys', rule, {
// settings.vue-i18n.localeDir' error
code: `$t('missing')`,
errors: [
`You need to set 'localeDir' at 'settings. See the 'eslint-plugin-vue-i18n documentation`
'You need to define locales in settings. See the eslint-plugin-vue-i18n documentation'
]
}, {
// nested basic
Expand All @@ -118,5 +128,12 @@ tester.run('no-missing-keys', rule, {
`'missing.path' does not exist`,
`'missing.path' does not exist`
]
}, {
// using message settings
settings: settingLocales,
code: `$t('missing')`,
errors: [
`'missing' does not exist`
]
}]
})
2 changes: 1 addition & 1 deletion tests/lib/rules/no-unused-keys.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ describe('no-unused-keys', () => {
.filter(message => message.ruleId === 'vue-i18n/no-unused-keys')
}).reduce((values, current) => values.concat(current), [])
.forEach(message => {
assert.equal(message.message, `You need to 'localeDir' at 'settings. See the 'eslint-plugin-vue-i18n documentation`)
assert.equal(message.message, 'You need to define locales in settings. See the eslint-plugin-vue-i18n documentation')
})
})
})
Expand Down