From ae9051a2d6cd73531de6e7bc01aa1e509df161c2 Mon Sep 17 00:00:00 2001 From: Florent Lepretre Date: Tue, 15 Jun 2021 07:19:40 +0200 Subject: [PATCH 1/6] feat(react-i18n): change translate function to use oject param --- packages/react-i18n/src/components/i18n.provider.js | 2 +- packages/react-i18n/src/components/i18nElement.component.js | 2 +- packages/react-i18n/src/components/i18nString.component.js | 2 +- packages/react-i18n/src/hooks/useTranslate.js | 6 +----- packages/react-i18n/src/utils/i18n.utils.js | 6 ++++-- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/packages/react-i18n/src/components/i18n.provider.js b/packages/react-i18n/src/components/i18n.provider.js index 7a041e2..f28c89a 100644 --- a/packages/react-i18n/src/components/i18n.provider.js +++ b/packages/react-i18n/src/components/i18n.provider.js @@ -4,7 +4,7 @@ import { translate } from '../utils/i18n.utils'; import { Context } from '../context/i18n.context'; export const I18nProvider = ({ lang, i18nNames, children, errorCallback, parseHTML }) => ( - {children} + {children} ); I18nProvider.propTypes = { diff --git a/packages/react-i18n/src/components/i18nElement.component.js b/packages/react-i18n/src/components/i18nElement.component.js index bfba717..3d69cc6 100644 --- a/packages/react-i18n/src/components/i18nElement.component.js +++ b/packages/react-i18n/src/components/i18nElement.component.js @@ -4,7 +4,7 @@ import { Context } from '../context/i18n.context'; export const HtmlTrans = ({ i18nKey, data, number, general, element: Element, renderers, ...props }) => ( - {t => } + {t => } ); diff --git a/packages/react-i18n/src/components/i18nString.component.js b/packages/react-i18n/src/components/i18nString.component.js index 4563510..0971758 100644 --- a/packages/react-i18n/src/components/i18nString.component.js +++ b/packages/react-i18n/src/components/i18nString.component.js @@ -3,7 +3,7 @@ import PropTypes from 'prop-types'; import { Context } from './../context/i18n.context'; export const Trans = ({ i18nKey, data, number, general, renderers }) => ( - {t => t(i18nKey, data, number, general, renderers)} + {t => t(i18nKey, { data, number, general, renderers })} ); Trans.defaultProps = { diff --git a/packages/react-i18n/src/hooks/useTranslate.js b/packages/react-i18n/src/hooks/useTranslate.js index af54f32..dd7a01d 100644 --- a/packages/react-i18n/src/hooks/useTranslate.js +++ b/packages/react-i18n/src/hooks/useTranslate.js @@ -1,8 +1,4 @@ import { useContext } from 'react'; import { Context } from '../context/i18n.context'; -export const useTranslate = () => { - const t = useContext(Context); - - return (key, { data, number, general, renderers } = {}) => t(key, data, number, general, renderers); -}; +export const useTranslate = () => useContext(Context); diff --git a/packages/react-i18n/src/utils/i18n.utils.js b/packages/react-i18n/src/utils/i18n.utils.js index f8c634d..a53174e 100644 --- a/packages/react-i18n/src/utils/i18n.utils.js +++ b/packages/react-i18n/src/utils/i18n.utils.js @@ -36,10 +36,12 @@ const pluralizeFunctions = { }, }; -export const translate = (lang, i18nNames = {}, errorCallback = _.noop, parseHTML = false) => { +const defaultConfig = { i18nNames: {}, errorCallback: _.noop, parseHTML: false }; +export const translate = (lang, config) => { + const { i18nNames, errorCallback, parseHTML } = { ...defaultConfig, ...config }; const pluralize = pluralizeFunctions[_.get(lang, '_i18n.lang')] || pluralizeFunctions.fr; - return (key, data = {}, number, general, renderers) => { + return (key, { data = {}, number, general, renderers }) => { let combineKey = key; // Pluralize if (typeof number !== 'undefined') { From 16649b9aa17999984845256e43d8798b390c64ee Mon Sep 17 00:00:00 2001 From: Florent Lepretre Date: Thu, 15 Jul 2021 07:46:08 +0200 Subject: [PATCH 2/6] fixup! feat(react-i18n): change translate function to use oject param --- packages/react-i18n/CHANGELOG.md | 10 ------ packages/react-i18n/README.md | 36 ++++++++++++++------- packages/react-i18n/src/utils/i18n.utils.js | 4 +-- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/packages/react-i18n/CHANGELOG.md b/packages/react-i18n/CHANGELOG.md index 24122e7..0b33cff 100644 --- a/packages/react-i18n/CHANGELOG.md +++ b/packages/react-i18n/CHANGELOG.md @@ -7,21 +7,12 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline **Note:** Version bump only for package @m6web/react-i18n - - - - ## [1.9.1](https://github.com/M6Web/i18n-tools/compare/@m6web/react-i18n@1.9.0...@m6web/react-i18n@1.9.1) (2021-03-09) **Note:** Version bump only for package @m6web/react-i18n - - - - # [1.9.0](https://github.com/M6Web/i18n-tools/compare/@m6web/react-i18n@1.9.0...@m6web/react-i18n@1.9.0) (2021-03-08) - ### Bug Fixes * **build:** fix build to make the lib importable ([97e59c5](https://github.com/M6Web/i18n-tools/commit/97e59c5232444c1ed46d07e676e8032a280e3209)) @@ -30,7 +21,6 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline * **react-i18n:** exports hook in index.js ([#18](https://github.com/M6Web/i18n-tools/issues/18)) ([c7c3fb8](https://github.com/M6Web/i18n-tools/commit/c7c3fb8434da037a43e39c4cbc0b061cd1fd1e15)) * **react-i18n:** remove unused contextType in component ([41d99e1](https://github.com/M6Web/i18n-tools/commit/41d99e17aa7d9692c795af2d373a258a54388178)) - ### Features * **react-i18n:** add errorCallback for missing translations ([#54](https://github.com/M6Web/i18n-tools/issues/54)) ([56fac7d](https://github.com/M6Web/i18n-tools/commit/56fac7da38845b8aa4df4d20242b3db411607c9a)) diff --git a/packages/react-i18n/README.md b/packages/react-i18n/README.md index 9cdbd81..1f335de 100644 --- a/packages/react-i18n/README.md +++ b/packages/react-i18n/README.md @@ -7,7 +7,6 @@ ![GitHub last commit](https://img.shields.io/github/last-commit/M6Web/i18n-tools) ![NPM](https://img.shields.io/npm/l/@m6web/react-i18n) - This library brings internationalisation through a set of react components. The translation function is in **[i18n.utils.js](./src/utils/i18n.utils.js)** file. @@ -57,6 +56,7 @@ const Root = () => ( ## Use translation components ### i18n Provider + This component will provide the translation function to following components via the React.Context api. * **lang**: translation dictionary @@ -226,12 +226,15 @@ The variable used in translation template string has to be `%(number)d`, and is To use general form, you need to set 4th parameter of the translate function to `true` ### HTML Interpolation + Basic html tags are automatically interpolated in translation if the syntax is correct (opening tag should be close within the translation). Attributes are supported too. Basic textual interpolations are proceeded first, and the HTML comes in a second time. -- translation + +* translation + ```json { "foo": { @@ -239,7 +242,9 @@ Basic textual interpolations are proceeded first, and the HTML comes in a second } } ``` -- code + +* code + ```jsx import React from 'react'; import { useTranslate } from './useTranslate'; @@ -252,9 +257,11 @@ export const MyComponent = () => {

{t('foo.bar', { number: 2 })}

); -} +}; ``` -- result + +* result + ```jsx harmony

@@ -264,26 +271,31 @@ export const MyComponent = () => { ``` #### excluded elements -For now `script` and `iframe` elements are ignored with all their children in the HTML tree. + +For now `script` and `iframe` elements are ignored with all their children in the HTML tree. #### keys + In case of arrays of component, keys will be automatically generated to please React. -- translation + +* translation + ```js { foo: { - bar: - '

Test

' + + bar: '

Test

' + '

This is not what we wanna do with this lib but we need to ensure it works anyway

' + '
    ' + '
  • simple link to the package.
  • ' + '
  • a disabled
  • ' + '
  • and an auto closing br
  • ' + - '
' + ''; } -}; +} ``` -- result + +* result + ```jsx harmony

{ +export const translate = (lang, config = {}) => { const { i18nNames, errorCallback, parseHTML } = { ...defaultConfig, ...config }; const pluralize = pluralizeFunctions[_.get(lang, '_i18n.lang')] || pluralizeFunctions.fr; - return (key, { data = {}, number, general, renderers }) => { + return (key, { data = {}, number, general, renderers } = {}) => { let combineKey = key; // Pluralize if (typeof number !== 'undefined') { From 9abaabb152d72d7acc98e7b190d7ab7e147dd144 Mon Sep 17 00:00:00 2001 From: Florent Lepretre Date: Thu, 15 Jul 2021 08:06:17 +0200 Subject: [PATCH 3/6] test --- .../react-i18n/src/hooks/__tests__/useTranslate.spec.js | 6 +++--- packages/react-i18n/src/utils/__tests__/i18n.utils.spec.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/react-i18n/src/hooks/__tests__/useTranslate.spec.js b/packages/react-i18n/src/hooks/__tests__/useTranslate.spec.js index 35eb9b8..176346b 100644 --- a/packages/react-i18n/src/hooks/__tests__/useTranslate.spec.js +++ b/packages/react-i18n/src/hooks/__tests__/useTranslate.spec.js @@ -14,10 +14,10 @@ describe('useTranslate', () => { it('should wrap the translation function', () => { const wrapTranslate = useTranslate(); - wrapTranslate('key', { data: {}, number: 'number', general: 'general', renderers: 'renderers' }); + wrapTranslate('key', { data: {}, number: 2, general: true, renderers: [] }); expect(useContext).toHaveBeenCalledWith(Context); - expect(t).toHaveBeenCalledWith('key', {}, 'number', 'general', 'renderers'); + expect(t).toHaveBeenCalledWith('key', { data: {}, number: 2, general: true, renderers: [] }); }); it('should wrap the translation function 2', () => { @@ -25,6 +25,6 @@ describe('useTranslate', () => { wrapTranslate('key'); expect(useContext).toHaveBeenCalledWith(Context); - expect(t).toHaveBeenCalledWith('key', undefined, undefined, undefined, undefined); + expect(t).toHaveBeenCalledWith('key'); }); }); diff --git a/packages/react-i18n/src/utils/__tests__/i18n.utils.spec.js b/packages/react-i18n/src/utils/__tests__/i18n.utils.spec.js index a81d1b4..f5ebfa9 100644 --- a/packages/react-i18n/src/utils/__tests__/i18n.utils.spec.js +++ b/packages/react-i18n/src/utils/__tests__/i18n.utils.spec.js @@ -311,8 +311,8 @@ describe('i18n translate function', () => { }, }; - const t = translate(lang, undefined, undefined, true); - const wrapper = mount(
{t('foo.bar', undefined, undefined, undefined, {})}
); + const t = translate(lang, { parseHTML: true }, undefined, true); + const wrapper = mount(
{t('foo.bar', {})}
); expect(wrapper).toMatchSnapshot(); }); From 602aa9a7637715a914cc029404b9757254173892 Mon Sep 17 00:00:00 2001 From: Florent Lepretre Date: Thu, 15 Jul 2021 08:12:41 +0200 Subject: [PATCH 4/6] fixup! test --- .../src/utils/__tests__/i18n.utils.spec.js | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/packages/react-i18n/src/utils/__tests__/i18n.utils.spec.js b/packages/react-i18n/src/utils/__tests__/i18n.utils.spec.js index f5ebfa9..7594f87 100644 --- a/packages/react-i18n/src/utils/__tests__/i18n.utils.spec.js +++ b/packages/react-i18n/src/utils/__tests__/i18n.utils.spec.js @@ -184,9 +184,9 @@ describe('i18n translate function', () => { }, }; const renderers = { Bold }; - const t = translate(lang, undefined, undefined, true); + const t = translate(lang, { parseHTML: true }); - const result = t('foo.bar', undefined, undefined, false, renderers); + const result = t('foo.bar', { renderers }); const wrapper = mount(
{result}
); expect(wrapper).toMatchSnapshot(); @@ -199,9 +199,9 @@ describe('i18n translate function', () => { }, }; const renderers = { Bold, Italic }; - const t = translate(lang, undefined, undefined, true); + const t = translate(lang, { parseHTML: true }); - const result = t('foo.bar', undefined, undefined, false, renderers); + const result = t('foo.bar', { renderers }); const wrapper = mount(
{result}
); expect(wrapper).toMatchSnapshot(); @@ -214,9 +214,9 @@ describe('i18n translate function', () => { }, }; const renderers = { Bold, Italic }; - const t = translate(lang, undefined, undefined, true); + const t = translate(lang, { parseHTML: true }); - const result = t('foo.bar', undefined, undefined, false, renderers); + const result = t('foo.bar', { renderers }); const wrapper = mount(
{result}
); expect(wrapper).toMatchSnapshot(); @@ -229,9 +229,9 @@ describe('i18n translate function', () => { }, }; const renderers = { LineBreak }; - const t = translate(lang, undefined, undefined, true); + const t = translate(lang, { parseHTML: true }); - const result = t('foo.bar', undefined, undefined, false, renderers); + const result = t('foo.bar', { renderers }); const wrapper = mount(
{result}
); expect(wrapper).toMatchSnapshot(); @@ -244,9 +244,9 @@ describe('i18n translate function', () => { }, }; const renderers = { LineBreak, Bold, Italic }; - const t = translate(lang, undefined, undefined, true); + const t = translate(lang, { parseHTML: true }); - const result = t('foo.bar', undefined, undefined, false, renderers); + const result = t('foo.bar', { renderers }); const wrapper = mount(
{result}
); expect(wrapper).toMatchSnapshot(); @@ -258,7 +258,7 @@ describe('i18n translate function', () => { bar: 'Hello Moto !', }, }; - const t = translate(lang, undefined, undefined, true); + const t = translate(lang, { parseHTML: true }); expect(t('foo.bar', undefined, undefined, false, { Bold })).toMatchSnapshot(); expect(t('foo.bar', undefined, undefined, false, { Italic })).toMatchSnapshot(); @@ -271,9 +271,9 @@ describe('i18n translate function', () => { }, }; const renderers = {}; - const t = translate(lang, undefined, undefined, true); + const t = translate(lang, { parseHTML: true }); - const result = t('foo.bar', undefined, undefined, false, renderers); + const result = t('foo.bar', { renderers }); const wrapper = mount(
{result}
); expect(wrapper).toMatchSnapshot(); @@ -287,9 +287,9 @@ describe('i18n translate function', () => { }; const renderers = { Bold, Italic }; - const t = translate(lang, undefined, undefined, true); + const t = translate(lang, { parseHTML: true }); - const result = t('foo.bar', undefined, undefined, undefined, renderers); + const result = t('foo.bar', { renderers }); const wrapper = mount(
{result}
); expect(wrapper).toMatchSnapshot(); @@ -311,7 +311,7 @@ describe('i18n translate function', () => { }, }; - const t = translate(lang, { parseHTML: true }, undefined, true); + const t = translate(lang, { parseHTML: true }); const wrapper = mount(
{t('foo.bar', {})}
); expect(wrapper).toMatchSnapshot(); From 8920de7981ba30ca4ed9bbf37e1a10a32307451b Mon Sep 17 00:00:00 2001 From: Florent Lepretre Date: Tue, 31 Aug 2021 09:38:10 +0200 Subject: [PATCH 5/6] wip --- .../react-i18n/src/components/i18n.provider.js | 15 +++++++++++---- packages/react-i18n/src/hooks/useTranslate.js | 7 ++++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/packages/react-i18n/src/components/i18n.provider.js b/packages/react-i18n/src/components/i18n.provider.js index f28c89a..6576e94 100644 --- a/packages/react-i18n/src/components/i18n.provider.js +++ b/packages/react-i18n/src/components/i18n.provider.js @@ -1,11 +1,18 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import PropTypes from 'prop-types'; import { translate } from '../utils/i18n.utils'; import { Context } from '../context/i18n.context'; -export const I18nProvider = ({ lang, i18nNames, children, errorCallback, parseHTML }) => ( - {children} -); +export const I18nProvider = ({ lang, i18nNames, children, errorCallback, parseHTML }) => { + const t = useMemo(() => translate(lang, { i18nNames, errorCallback, parseHTML }), [ + lang, + i18nNames, + errorCallback, + parseHTML, + ]); + + return {children}; +}; I18nProvider.propTypes = { children: PropTypes.element.isRequired, diff --git a/packages/react-i18n/src/hooks/useTranslate.js b/packages/react-i18n/src/hooks/useTranslate.js index dd7a01d..a8c019f 100644 --- a/packages/react-i18n/src/hooks/useTranslate.js +++ b/packages/react-i18n/src/hooks/useTranslate.js @@ -1,4 +1,9 @@ import { useContext } from 'react'; import { Context } from '../context/i18n.context'; -export const useTranslate = () => useContext(Context); +const emptyObject = {}; +export const useTranslate = () => { + const t = useContext(Context); + + return (key, data = emptyObject) => t(key, data); +}; From 6d24e387000e7b5f15142f9f3bd4a587707d380d Mon Sep 17 00:00:00 2001 From: Florent Lepretre Date: Tue, 31 Aug 2021 09:39:08 +0200 Subject: [PATCH 6/6] Publish - @m6web/react-i18n@2.0.0-alpha.1 --- packages/react-i18n/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-i18n/package.json b/packages/react-i18n/package.json index 14b00b8..79a12a1 100644 --- a/packages/react-i18n/package.json +++ b/packages/react-i18n/package.json @@ -1,6 +1,6 @@ { "name": "@m6web/react-i18n", - "version": "2.0.0-alpha.0", + "version": "2.0.0-alpha.1", "description": "Provider and utils for translation in a react app", "main": "lib/index.js", "module": "es/index.js",