Skip to content

Commit

Permalink
Merge pull request #486 from incleaf/support-prefix
Browse files Browse the repository at this point in the history
Support `keyPrefix` of `useTranslation` hook
  • Loading branch information
karellm committed Apr 4, 2022
2 parents 9ad195e + 774b6ec commit 35d5bc4
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 1 deletion.
28 changes: 28 additions & 0 deletions src/lexers/javascript-lexer.js
Expand Up @@ -53,6 +53,17 @@ export default class JavascriptLexer extends BaseLexer {
return keys
}

setKeyPrefixes(keys) {
if (this.keyPrefix) {
return keys.map((key) => ({
...key,
keyPrefix: this.keyPrefix,
}))
}

return keys
}

extract(content, filename = '__default.js') {
const keys = []

Expand Down Expand Up @@ -120,8 +131,25 @@ export default class JavascriptLexer extends BaseLexer {
node.arguments.length
) {
const { text, elements } = node.arguments[0]

// useTranslation
if (text) {
this.defaultNamespace = text
const optionsArgument = node.arguments[1]

if (
optionsArgument &&
optionsArgument.kind === ts.SyntaxKind.ObjectLiteralExpression
) {
const node = optionsArgument.properties.find(
(p) => p.name.escapedText === 'keyPrefix'
)
if (node != null) {
const keyPrefixValue = node.initializer.text
this.keyPrefix = keyPrefixValue
}
}
// withTranslation
} else if (elements && elements.length) {
this.defaultNamespace = elements[0].text
}
Expand Down
5 changes: 4 additions & 1 deletion src/lexers/jsx-lexer.js
Expand Up @@ -55,7 +55,10 @@ export default class JsxLexer extends JavascriptLexer {
)
parseTree(sourceFile)

return this.setNamespaces(keys)
const keysWithNamespace = this.setNamespaces(keys)
const keysWithPrefixes = this.setKeyPrefixes(keysWithNamespace)

return keysWithPrefixes
}

jsxExtractor(node, sourceText) {
Expand Down
5 changes: 5 additions & 0 deletions src/transform.js
Expand Up @@ -109,6 +109,11 @@ export default class i18nTransform extends Transform {

for (const entry of entries) {
let key = entry.key

if (entry.keyPrefix) {
key = entry.keyPrefix + this.options.keySeparator + key
}

const parts = key.split(this.options.namespaceSeparator)

// make sure we're not pulling a 'namespace' out of a default value
Expand Down
18 changes: 18 additions & 0 deletions test/gulp/gulp.test.js
Expand Up @@ -51,6 +51,18 @@ describe('gulp plugin', function () {
assert.strictEqual(error.code, 'ENOENT')
}

const enKeyPrefix = await fs.readJson(
path.resolve(__dirname, './locales/en/key-prefix.json')
)

try {
await fs.readJson(
path.resolve(__dirname, './locales/en/key-prefix_old.json')
)
} catch (error) {
assert.strictEqual(error.code, 'ENOENT')
}

const enTranslation = await fs.readJson(
path.resolve(__dirname, './locales/en/translation.json')
)
Expand Down Expand Up @@ -116,6 +128,12 @@ describe('gulp plugin', function () {
'test-1': '',
'test-2': '',
})
assert.deepEqual(enKeyPrefix, {
'test-prefix': {
foo: '',
bar: '',
},
})
assert.deepEqual(enTranslation, {
fifth: 'bar',
fifth_male: '',
Expand Down
29 changes: 29 additions & 0 deletions test/parser.test.js
Expand Up @@ -382,6 +382,35 @@ describe('parser', () => {
i18nextParser.end(fakeFile)
})

it('applies useTranslation keyPrefix globally', (done) => {
let result
const i18nextParser = new i18nTransform()
const fakeFile = new Vinyl({
contents: fs.readFileSync(
path.resolve(__dirname, 'templating/keyPrefix-hook.jsx')
),
path: 'file.jsx',
})
const expected = {
'test-prefix': {
foo: '',
bar: '',
},
}

i18nextParser.on('data', (file) => {
if (file.relative.endsWith(path.normalize('en/key-prefix.json'))) {
result = JSON.parse(file.contents)
}
})
i18nextParser.on('end', () => {
assert.deepEqual(result, expected)
done()
})

i18nextParser.end(fakeFile)
})

it('handles escaped single and double quotes', (done) => {
let result
const i18nextParser = new i18nTransform()
Expand Down
19 changes: 19 additions & 0 deletions test/templating/keyPrefix-hook.jsx
@@ -0,0 +1,19 @@
import React from 'react'
import { useTranslation, Trans } from 'react-i18next'

// This will have test-namespace even though it comes before useTranslation during parsing
const Component = () => {
return <Trans i18nKey="foo"></Trans>
}

function TestComponent() {
const { t } = useTranslation('key-prefix', { keyPrefix: 'test-prefix' })
return (
<>
<Component />
<h1>{t('bar')}</h1>
</>
)
}

export default TestComponent

0 comments on commit 35d5bc4

Please sign in to comment.