Skip to content

Commit

Permalink
Add: Introduce a useTranslation hook
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bjoernricks committed Apr 5, 2024
1 parent 045f299 commit 9553940
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 0 deletions.
50 changes: 50 additions & 0 deletions src/web/hooks/__tests__/useTranslation.js
Original file line number Diff line number Diff line change
@@ -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 (
<div>
<div data-testid="t1">{_('First Translation')}</div>
<div data-testid="t2">{t('Second Translation')}</div>
<div data-testid="r1">{ready_1 ? 'is ready' : 'not ready'}</div>
<div data-testid="r2">{ready ? 'is ready' : 'not ready'}</div>
<button
data-testid="changeLocale1"
onClick={() => i18n.changeLanguage('en')}
/>
<button
data-testid="changeLocale2"
onClick={() => i18n_1.changeLanguage('en')}
/>
</div>
);
};

describe('useTranslation tests', () => {
test('should render the translations', async () => {
const {render} = rendererWith();

render(<TestComponent />);

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);
});
});
36 changes: 36 additions & 0 deletions src/web/hooks/useTranslation.js
Original file line number Diff line number Diff line change
@@ -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;

0 comments on commit 9553940

Please sign in to comment.