Skip to content

Commit

Permalink
refactor(i18nTagSchema): restructured code and improved test coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
skolmer committed Nov 1, 2016
1 parent 05eaf6d commit a21658c
Show file tree
Hide file tree
Showing 9 changed files with 597 additions and 456 deletions.
95 changes: 78 additions & 17 deletions __tests__/exportTranslationKeys.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,64 @@ import path from 'path'
import { exportTranslationKeys } from '../lib'

describe('exportTranslationKeys', () => {
it('should export templates as array', (done) => {
it('should fail if rootPath param is missing', (done) => {
const filePath = './samples/grouped.js'
exportTranslationKeys({
filePath,
logger: { toConsole: true },
callback: (status, templates) => {
expect(status).toEqual(1)
expect(templates).toEqual('rootPath is not defined.')
done()
}
})
})

it('should export all templates from a directory', (done) => {
const rootPath = path.resolve(__dirname, './samples')
exportTranslationKeys({
rootPath,
logger: { toConsole: true },
callback: (status, templates) => {
expect(status).toEqual(0)
expect(templates).toEqual([
'\n <user name="${0}">${1}</user>\n ',
'\n <users>\n ${0}\n </users>\n',
{
'group': 'custom group',
'items': [
'Hello ${0}, you have ${1} in your bank account.'
]
},
{
'group': 'custom group 2',
'items': [
'Hello ${0}, you have ${1} in your bank account.'
]
},
{
'group': 'custom inline group',
'items': [
'Hello!',
'Welcome!'
]
},
{
'group': 'grouped.js',
'items': [
'Hello ${0}, you have ${1} in your bank account.',
'Hello!'
]
}
])
done()
}
})
})

it('should export grouped templates as array', (done) => {
const rootPath = path.resolve(__dirname, './samples')
const filePath = path.resolve(__dirname, './samples/grouped.js')
const filePath2 = path.resolve(__dirname, './samples/multiline.js')
exportTranslationKeys({
rootPath,
filePath,
Expand Down Expand Up @@ -42,23 +96,30 @@ describe('exportTranslationKeys', () => {
]
}
])
exportTranslationKeys({
rootPath,
filePath: filePath2,
callback: (status, templates) => {
expect(status).toEqual(0)
expect(templates).toEqual([
'\n <user name="${0}">${1}</user>\n ',
'\n <users>\n ${0}\n </users>\n',
{
'group': 'custom inline group',
'items': ['Hello!']
}
])
done()
done()
}
})
})

it('should export multiline templates as array', (done) => {
const rootPath = path.resolve(__dirname, './samples')
const filePath = path.resolve(__dirname, './samples/multiline.js')
exportTranslationKeys({
rootPath,
filePath,
callback: (status, templates) => {
expect(status).toEqual(0)
expect(templates).toEqual([
'\n <user name="${0}">${1}</user>\n ',
'\n <users>\n ${0}\n </users>\n',
{
'group': 'custom inline group',
'items': ['Hello!']
}
})
])
done()
}
})
})

})
2 changes: 2 additions & 0 deletions __tests__/samples/translation.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
{
"$schema": "./schema.json",
"\n <user name=\"${0}\">${1}</user>\n ": "<user name=\"${01}\">${1}</user>",
"\n <users>\n ${0}\n </users>\n": "",
"unknown": "unknown",
"custom group": {
"Hello ${0}, you have ${1} in your bank account.": "hello${0}, you have ${1} §{0}"
},
Expand Down
67 changes: 54 additions & 13 deletions __tests__/validateTranslations.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,59 @@ import path from 'path'
import { validateTranslations } from '../lib'

describe('validateTranslations', () => {
it('should validate translations', (done) => {
const schemaPath = path.resolve(__dirname, './samples/schema.json')
const translationPath = path.resolve(__dirname, './samples/translation.json')
validateTranslations({
rootPath: translationPath,
schemaPath,
logger: { toConsole: true },
callback: (status, result) => {
expect(status).toEqual(1)
expect(result).toEqual('translation.json has 3 missing translations; 63% translated.')
done()
}
})
it('should fail if rootPath param is missing', (done) => {
const schemaPath = path.resolve(__dirname, './samples/schema.json')
validateTranslations({
schemaPath,
logger: { toConsole: true },
callback: (status, result) => {
expect(status).toEqual(1)
expect(result).toEqual('rootPath is not defined.')
done()
}
})
})

it('should fail if schemaPath param is missing', (done) => {
const rootPath = path.resolve(__dirname, './samples')
validateTranslations({
rootPath,
logger: { toConsole: true },
callback: (status, result) => {
expect(status).toEqual(1)
expect(result).toEqual('schemaPath is not defined.')
done()
}
})
})

it('should validate translations', (done) => {
const schemaPath = path.resolve(__dirname, './samples/schema.json')
const rootPath = path.resolve(__dirname, './samples')
validateTranslations({
rootPath,
schemaPath,
logger: { toConsole: true },
callback: (status, result) => {
expect(status).toEqual(1)
expect(result).toEqual('translation.json has 3 missing translations and 1 invalid key; 63% translated.')
done()
}
})
})

it('should validate single translation file', (done) => {
const schemaPath = path.resolve(__dirname, './samples/schema.json')
const translationPath = path.resolve(__dirname, './samples/translation.json')
validateTranslations({
rootPath: translationPath,
schemaPath,
logger: { toConsole: true },
callback: (status, result) => {
expect(status).toEqual(1)
expect(result).toEqual('translation.json has 3 missing translations and 1 invalid key; 63% translated.')
done()
}
})
})
})
82 changes: 82 additions & 0 deletions lib/export.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
import * as path from 'path'
import * as fs from 'fs'
import {logError, logInfo, logTrace, logWarn} from './logging'
import {parseFile} from './parser'

function pushIfNotExist(array, item) {
if (array.indexOf(item) === -1) {
array.push(item)
}
}

export const readFileTemplates = (rootPath, filePath, templates, templatePatterns, contents, logger) => {
try {
const parsedTemplates = parseFile(contents)
const newTemplates = parsedTemplates.templates
const newTemplatePatterns = Object.assign(templatePatterns, parsedTemplates.templatePatterns)
const { length } = newTemplates

if (length) {
const fileGroup = path.relative(rootPath, filePath).replace(/\\/g, '/')
const groupedItems = { [fileGroup]: [] }
const getOrCreateGroup = (name) => groupedItems[name] || (groupedItems[name] = [])
const ungroupedTemplate = []
newTemplates.forEach((t) => {
if (t.group) {
pushIfNotExist(getOrCreateGroup((t.group === '__translationGroup') ? fileGroup : t.group), t.value)
} else {
pushIfNotExist(ungroupedTemplate, t)
}
})
ungroupedTemplate.forEach((item) => {
pushIfNotExist(templates, item)
})
Object.keys(groupedItems).sort().forEach((g) => {
const groupItems = groupedItems[g]
if (groupItems && groupItems.length) {
const grp = templates.find((item) => item.group === g)
if (grp) {
groupItems.forEach((item) => {
pushIfNotExist(grp.items, item)
})
grp.items.sort()
} else {
templates.push({ group: g, items: groupItems.sort() })
}
}
})
templates.sort()
logInfo(logger, `${path.relative(rootPath, filePath)} (${length} template${(length === 1) ? '' : 's'})`)
} else {
logInfo(logger, `${path.relative(rootPath, filePath)} (0 templates)`)
}
return { templates, templatePatterns: newTemplatePatterns }
} catch (err) {
logWarn(logger, `${filePath}: ${err.message}`)
logTrace(logger, err)
}
return {}
}

/**
* exportTranslationKeysFromFile exports all i18n tagged template literals in `srcPath`
*
* @param {Object} options - The export options.
* @param {string} options.rootPath - The root directory of your source files.
* @param {string} options.filePath - The full path of the source file.
* @param {requestCallback} options.callback - A callback function that will be called when the function completes.
* @param {logger} [options.logger] - A custom logger.
*/
export const exportTranslationKeysFromFile = ({rootPath, filePath, callback, logger}) => {
const templates = []
const templatePatterns = {}
fs.readFile(filePath, 'utf-8', (err, contents) => {
if (err) {
logError(logger, `${filePath}: ${err.messag}`)
logTrace(logger, err)
if(callback) callback(1, [])
}
const tmpls = readFileTemplates(rootPath, filePath, templates, templatePatterns, contents, logger)
if(callback) callback(0, tmpls.templates || [])
})
}
Loading

0 comments on commit a21658c

Please sign in to comment.