From 9553940d48dfef510bcfbec161642eebc78fff93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Ricks?= Date: Thu, 4 Apr 2024 11:34:42 +0200 Subject: [PATCH] Add: Introduce a useTranslation hook Provide a possibility to migrate our translation mechanism to react-i18n by introducing a similar useTranslation hook. When we started developing GSA hooks didn't exist and react-i18n including its translation mechanisms were not easy to use. Therefore I've implemented our own abstraction on top of i18next directly. With react hooks react-i18n become much easier to use and we should migrate to it at the end. To allow for an easy migration introduce a similar useTranslation hook as react-i18n that wraps our current translation code. --- src/web/hooks/__tests__/useTranslation.js | 50 +++++++++++++++++++++++ src/web/hooks/useTranslation.js | 36 ++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 src/web/hooks/__tests__/useTranslation.js create mode 100644 src/web/hooks/useTranslation.js diff --git a/src/web/hooks/__tests__/useTranslation.js b/src/web/hooks/__tests__/useTranslation.js new file mode 100644 index 0000000000..170bd2c68e --- /dev/null +++ b/src/web/hooks/__tests__/useTranslation.js @@ -0,0 +1,50 @@ +/* SPDX-FileCopyrightText: 2024 Greenbone AG + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import {fireEvent, rendererWith, screen} from 'web/utils/testing'; + +import useTranslation from '../useTranslation'; + +const TestComponent = () => { + const [_, i18n_1, ready_1] = useTranslation(); + const {t, i18n, ready} = useTranslation(); + return ( +
+
{_('First Translation')}
+
{t('Second Translation')}
+
{ready_1 ? 'is ready' : 'not ready'}
+
{ready ? 'is ready' : 'not ready'}
+
+ ); +}; + +describe('useTranslation tests', () => { + test('should render the translations', async () => { + const {render} = rendererWith(); + + render(); + + const t1 = await screen.getByTestId('t1'); + expect(t1).toHaveTextContent('First Translation'); + const t2 = await screen.getByTestId('t2'); + expect(t2).toHaveTextContent('Second Translation'); + const r1 = await screen.getByTestId('r1'); + expect(r1).toHaveTextContent('is ready'); + const r2 = await screen.getByTestId('r2'); + expect(r2).toHaveTextContent('is ready'); + const b1 = await screen.getByTestId('changeLocale1'); + await fireEvent.click(b1); + const b2 = await screen.getByTestId('changeLocale2'); + await fireEvent.click(b2); + }); +}); diff --git a/src/web/hooks/useTranslation.js b/src/web/hooks/useTranslation.js new file mode 100644 index 0000000000..6a7dc3147e --- /dev/null +++ b/src/web/hooks/useTranslation.js @@ -0,0 +1,36 @@ +/* SPDX-FileCopyrightText: 2024 Greenbone AG + * + * SPDX-License-Identifier: AGPL-3.0-or-later + */ + +import _ from 'gmp/locale'; +import i18next from 'i18next'; + +/** + * Hook to get the translation function, an i18next instance and a boolean + * indicating if the translations are ready. Currently, the ready status is + * always true. + * + * The return value can be used as in array or object. + * + * @example + * + * const [_, i18n, ready] = useTranslation(); + * + * or + * + * const {t, i18n, ready} = useTranslation(); + * + * @returns Array|Object with the translation function, i18next instance and ready status + */ +const useTranslation = () => { + // provide same interface as useTranslation from i18next + // this will allow to use react-i18next in future if required + const ret = [_, i18next, true]; + ret.t = _; + ret.i18n = i18next; + ret.ready = true; + return ret; +}; + +export default useTranslation;