diff --git a/src/components/i18n/__tests__/__snapshots__/i18n.test.js.snap b/src/components/i18n/__tests__/__snapshots__/i18n.test.js.snap index b1d413f35..737f2ef1f 100644 --- a/src/components/i18n/__tests__/__snapshots__/i18n.test.js.snap +++ b/src/components/i18n/__tests__/__snapshots__/i18n.test.js.snap @@ -4,6 +4,8 @@ exports[`I18n Component should attempt to perform a component translate: transla exports[`I18n Component should attempt to perform a string replace: translate 1`] = ` Object { + "emptyContext": "t(lorem.ipsum, {\\"context\\":\\" \\"})", + "emptyPartialContext": "t(lorem.ipsum, {\\"context\\":\\"hello_ \\"})", "localeKey": "t(lorem.ipsum)", "multiContext": "t(lorem.ipsum, {\\"context\\":\\"hello_world\\"})", "multiContextWithEmptyValue": "t(lorem.ipsum, {\\"context\\":\\"hello_world\\"})", diff --git a/src/components/i18n/__tests__/i18n.test.js b/src/components/i18n/__tests__/i18n.test.js index 56ef165a9..104243ded 100644 --- a/src/components/i18n/__tests__/i18n.test.js +++ b/src/components/i18n/__tests__/i18n.test.js @@ -5,7 +5,7 @@ import PropTypes from 'prop-types'; import { shallow } from 'enzyme'; import _get from 'lodash/get'; import enLocales from '../../../../public/locales/en-US.json'; -import { I18n, translate, translateComponent } from '../i18n'; +import { EMPTY_CONTEXT, I18n, translate, translateComponent } from '../i18n'; /** * Get translation keys. @@ -97,6 +97,8 @@ describe('I18n Component', () => { }); it('should attempt to perform a string replace', () => { + const emptyContext = translate('lorem.ipsum', { context: EMPTY_CONTEXT }); + const emptyPartialContext = translate('lorem.ipsum', { context: ['hello', EMPTY_CONTEXT] }); const localeKey = translate('lorem.ipsum'); const placeholder = translate('lorem.ipsum', 'hello world'); const multiContext = translate('lorem.ipsum', { context: ['hello', 'world'] }); @@ -104,6 +106,8 @@ describe('I18n Component', () => { const multiKey = translate(['lorem.ipsum', undefined, null, '', 'lorem.fallback']); expect({ + emptyContext, + emptyPartialContext, localeKey, placeholder, multiContext, diff --git a/src/components/i18n/i18n.js b/src/components/i18n/i18n.js index d7267b4fb..44dc09266 100644 --- a/src/components/i18n/i18n.js +++ b/src/components/i18n/i18n.js @@ -6,6 +6,13 @@ import { initReactI18next, Trans } from 'react-i18next'; import { useMount } from 'react-use'; import { helpers } from '../../common/helpers'; +/** + * Check to help provide an empty context. + * + * @type {string} + */ +const EMPTY_CONTEXT = 'LOCALE_EMPTY_CONTEXT'; + /** * Apply a string towards a key. Optional replacement values and component/nodes. * See, https://react.i18next.com/ @@ -13,9 +20,11 @@ import { helpers } from '../../common/helpers'; * @param {string|Array} translateKey A key reference, or an array of a primary key with fallback keys. * @param {string|object|Array} values A default string if the key can't be found. An object with i18next settings. Or an array of objects (key/value) pairs used to replace string tokes. i.e. "[{ hello: 'world' }]" * @param {Array} components An array of HTML/React nodes used to replace string tokens. i.e. "[, ]" + * @param {object} options + * @param {string} options.emptyContextValue Check to allow an empty context value. * @returns {string|React.ReactNode} */ -const translate = (translateKey, values = null, components) => { +const translate = (translateKey, values = null, components, { emptyContextValue = EMPTY_CONTEXT } = {}) => { const updatedValues = values; let updatedTranslateKey = translateKey; @@ -25,8 +34,11 @@ const translate = (translateKey, values = null, components) => { if (Array.isArray(updatedValues?.context)) { updatedValues.context = updatedValues.context + .map(value => (value === emptyContextValue && ' ') || value) .filter(value => typeof value === 'string' && value.length > 0) .join('_'); + } else if (updatedValues?.context === emptyContextValue) { + updatedValues.context = ' '; } if (helpers.TEST_MODE) { @@ -143,4 +155,4 @@ I18n.defaultProps = { locale: null }; -export { I18n as default, I18n, i18next, translate, translateComponent }; +export { I18n as default, I18n, i18next, translate, translateComponent, EMPTY_CONTEXT };