Skip to content

Commit

Permalink
defaultValue support async function
Browse files Browse the repository at this point in the history
  • Loading branch information
guoyunhe committed Jan 18, 2023
1 parent 432cb66 commit 2353dae
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 55 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ export default {

defaultValue: '',
// Default value to give to keys with no value
// You may also specify a function accepting the locale, namespace, key, and value as arguments
// You may also specify a sync/async function:
// (locale: string, namespace: string, key: string, value: string) => string | Promise<string>

indentation: 2,
// Indentation of the catalog files
Expand Down
2 changes: 1 addition & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export interface UserConfig {
contextSeparator?: string;
createOldCatalogs?: boolean;
defaultNamespace?: string;
defaultValue?: string | ((locale?: string, namespace?: string, key?: string) => string);
defaultValue?: string | ((locale?: string, namespace?: string, key?: string) => string | Promise<string>);
indentation?: number;
keepRemoved?: boolean;
keySeparator?: string | false;
Expand Down
4 changes: 2 additions & 2 deletions src/helpers.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { builtinModules } from 'module'
* {one: {two: "bla"}}), `"value"` if the same key already exists with a
* different value, or `false`.
*/
function dotPathToHash(entry, target = {}, options = {}) {
async function dotPathToHash(entry, target = {}, options = {}) {
let conflict = false
let duplicate = false
let path = entry.keyWithNamespace
Expand Down Expand Up @@ -45,7 +45,7 @@ function dotPathToHash(entry, target = {}, options = {}) {

let newValue =
typeof options.value === 'function'
? options.value(options.locale, entry.namespace, key, defaultValue)
? await options.value(options.locale, entry.namespace, key, defaultValue)
: options.value || defaultValue

if (path.endsWith(separator)) {
Expand Down
18 changes: 9 additions & 9 deletions src/transform.js
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ export default class i18nTransform extends Transform {
done()
}

_flush(done) {
async _flush(done) {
let maybeSortedLocales = this.options.locales
if (this.options.resetDefaultValueLocale) {
// ensure we process the reset locale first
Expand All @@ -155,15 +155,15 @@ export default class i18nTransform extends Transform {
let uniqueCount = {}
let uniquePluralsCount = {}

const transformEntry = (entry, suffix) => {
const transformEntry = async (entry, suffix) => {
if (uniqueCount[entry.namespace] === undefined) {
uniqueCount[entry.namespace] = 0
}
if (uniquePluralsCount[entry.namespace] === undefined) {
uniquePluralsCount[entry.namespace] = 0
}

const { duplicate, conflict } = dotPathToHash(entry, catalog, {
const { duplicate, conflict } = await dotPathToHash(entry, catalog, {
suffix,
locale,
separator: this.options.keySeparator,
Expand Down Expand Up @@ -192,13 +192,13 @@ export default class i18nTransform extends Transform {
// generates plurals according to i18next rules: key_zero, key_one, key_two, key_few, key_many and key_other
for (const entry of this.entries) {
if (entry.count !== undefined) {
this.i18next.services.pluralResolver
.getSuffixes(locale, { ordinal: entry.ordinal })
.forEach((suffix) => {
transformEntry(entry, suffix)
})
await Promise.all(
this.i18next.services.pluralResolver
.getSuffixes(locale, { ordinal: entry.ordinal })
.map((suffix) => transformEntry(entry, suffix))
)
} else {
transformEntry(entry)
await transformEntry(entry)
}
}

Expand Down
72 changes: 30 additions & 42 deletions test/helpers/dotPathToHash.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,142 +2,130 @@ import { assert } from 'chai'
import { dotPathToHash } from '../../src/helpers.js'

describe('dotPathToHash helper function', () => {
it('creates an object from a string path', (done) => {
const { target, duplicate } = dotPathToHash({ keyWithNamespace: 'one' })
it('creates an object from a string path', async () => {
const { target, duplicate } = await dotPathToHash({
keyWithNamespace: 'one',
})
assert.deepEqual(target, { one: '' })
assert.equal(duplicate, false)
done()
})

it('ignores trailing separator', (done) => {
const { target } = dotPathToHash(
it('ignores trailing separator', async () => {
const { target } = await dotPathToHash(
{ keyWithNamespace: 'one.two.' },
{},
{ separator: '.' }
)
assert.deepEqual(target, { one: { two: '' } })
done()
})

it('ignores duplicated separator', (done) => {
const { target } = dotPathToHash({ keyWithNamespace: 'one..two' })
it('ignores duplicated separator', async () => {
const { target } = await dotPathToHash({ keyWithNamespace: 'one..two' })
assert.deepEqual(target, { one: { two: '' } })
done()
})

it('supports custom separator', (done) => {
const { target } = dotPathToHash(
it('supports custom separator', async () => {
const { target } = await dotPathToHash(
{ keyWithNamespace: 'one-two' },
{},
{ separator: '-' }
)
assert.deepEqual(target, { one: { two: '' } })
done()
})

it('handles an empty namespace', (done) => {
const { target, duplicate } = dotPathToHash({
it('handles an empty namespace', async () => {
const { target, duplicate } = await dotPathToHash({
keyWithNamespace: 'ns.',
namespace: 'ns',
})
assert.deepEqual(target, { ns: {} })
assert.equal(duplicate, false)
done()
})

it('handles a target hash', (done) => {
const { target, duplicate } = dotPathToHash(
it('handles a target hash', async () => {
const { target, duplicate } = await dotPathToHash(
{ keyWithNamespace: 'one.two.three' },
{ one: { twenty: '' } }
)
assert.deepEqual(target, { one: { two: { three: '' }, twenty: '' } })
assert.equal(duplicate, false)
done()
})

it('handles a `defaultValue` option', (done) => {
const { target } = dotPathToHash(
it('handles a `defaultValue` option', async () => {
const { target } = await dotPathToHash(
{ keyWithNamespace: 'one' },
{},
{ value: 'myDefaultValue' }
)
assert.deepEqual(target, { one: 'myDefaultValue' })
done()
})

it('handles a `separator` option', (done) => {
const { target } = dotPathToHash(
it('handles a `separator` option', async () => {
const { target } = await dotPathToHash(
{ keyWithNamespace: 'one_two_three.' },
{},
{ separator: '_' }
)
assert.deepEqual(target, { one: { two: { 'three.': '' } } })
done()
})

it('detects duplicate keys with the same value', (done) => {
const { target, duplicate, conflict } = dotPathToHash(
it('detects duplicate keys with the same value', async () => {
const { target, duplicate, conflict } = await dotPathToHash(
{ keyWithNamespace: 'one.two.three' },
{ one: { two: { three: '' } } }
)
assert.deepEqual(target, { one: { two: { three: '' } } })
assert.equal(duplicate, true)
assert.equal(conflict, false)
done()
})

it('detects and overwrites duplicate keys with different values', (done) => {
const { target, duplicate, conflict } = dotPathToHash(
it('detects and overwrites duplicate keys with different values', async () => {
const { target, duplicate, conflict } = await dotPathToHash(
{ keyWithNamespace: 'one.two.three', defaultValue: 'new' },
{ one: { two: { three: 'old' } } }
)
assert.deepEqual(target, { one: { two: { three: 'new' } } })
assert.equal(duplicate, true)
assert.equal(conflict, 'value')
done()
})

it('overwrites keys already mapped to a string with an object value', (done) => {
const { target, duplicate, conflict } = dotPathToHash(
it('overwrites keys already mapped to a string with an object value', async () => {
const { target, duplicate, conflict } = await dotPathToHash(
{ keyWithNamespace: 'one', defaultValue: 'bla' },
{ one: { two: { three: 'bla' } } }
)
assert.deepEqual(target, { one: 'bla' })
assert.equal(duplicate, true)
assert.equal(conflict, 'key')
done()
})

it('overwrites keys already mapped to an object with a string value', (done) => {
const { target, duplicate, conflict } = dotPathToHash(
it('overwrites keys already mapped to an object with a string value', async () => {
const { target, duplicate, conflict } = await dotPathToHash(
{ keyWithNamespace: 'one.two.three', defaultValue: 'bla' },
{ one: 'bla' }
)
assert.deepEqual(target, { one: { two: { three: 'bla' } } })
assert.equal(duplicate, true)
assert.equal(conflict, 'key')
done()
})

it('uses old value when there is no new value and does not conflict', (done) => {
const { target, duplicate, conflict } = dotPathToHash(
it('uses old value when there is no new value and does not conflict', async () => {
const { target, duplicate, conflict } = await dotPathToHash(
{ keyWithNamespace: 'one.two.three' },
{ one: { two: { three: 'old' } } }
)
assert.deepEqual(target, { one: { two: { three: 'old' } } })
assert.equal(duplicate, true)
assert.equal(conflict, false)
done()
})

it('uses new value when there is no old value and does not conflict', (done) => {
const { target, duplicate, conflict } = dotPathToHash(
it('uses new value when there is no old value and does not conflict', async () => {
const { target, duplicate, conflict } = await dotPathToHash(
{ keyWithNamespace: 'one.two.three', defaultValue: 'new' },
{ one: { two: { three: '' } } }
)
assert.deepEqual(target, { one: { two: { three: 'new' } } })
assert.equal(duplicate, true)
assert.equal(conflict, false)
done()
})
})

0 comments on commit 2353dae

Please sign in to comment.