Skip to content

Commit ac2ee01

Browse files
authored
Merge pull request #106 from SkrzypMajster/feat/add-new-utils-for-handling-translations
feat: add new utils for handling translations
2 parents 93c20df + 12f61ed commit ac2ee01

7 files changed

Lines changed: 64 additions & 24 deletions

File tree

.changeset/polite-moons-lie.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'react-starter-boilerplate': patch
3+
---
4+
5+
feat: Add new utils for handling translations in application

src/app/home/Home.tsx

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import { Fragment } from 'react';
22

3-
import { useLocale } from 'hooks/useLocale/useLocale';
3+
import { AppRoute } from 'routing/AppRoute.enum';
44
import { AppLocale } from 'context/locale/AppLocale.enum';
5-
import { AppMessages } from 'i18n/messages';
6-
import { LocationInfo } from 'ui/locationInfo/LocationInfo';
5+
import { useLocale } from 'hooks/useLocale/useLocale';
76
import { useAuth } from 'hooks/useAuth/useAuth';
8-
import { useUsers } from '../../hooks/useUsers/useUsers';
9-
import { AppRoute } from 'routing/AppRoute.enum';
7+
import { useUsers } from 'hooks/useUsers/useUsers';
108
import { useNavigate } from 'hooks/useNavigate/useNavigate';
9+
import { Translation } from 'ui/translation/Translation';
10+
import { LocationInfo } from 'ui/locationInfo/LocationInfo';
1111

1212
export const Home = () => {
13-
const { formatMessage, locale, setLocale } = useLocale();
13+
const { locale, setLocale } = useLocale();
1414
const { user, login, logout, isAuthenticated, isAuthenticating } = useAuth();
1515

1616
const {
@@ -28,13 +28,12 @@ export const Home = () => {
2828
<>
2929
<h2>Home</h2>
3030
<p>
31-
{formatMessage({ id: AppMessages['home.helloWorld'] })}
31+
<Translation id="home.helloWorld" />
3232
<span style={{ margin: '0 1rem' }}>&#x2190;</span>
33-
This text is translated using{' '}
34-
<a href="https://github.com/formatjs/react-intl/blob/master/docs/API.md#formatmessage">
35-
<code>formatMessage</code>
36-
</a>{' '}
37-
function from <a href="https://github.com/formatjs/react-intl">react-intl</a>. Click{' '}
33+
<span>
34+
This text is translated using <strong>Translation</strong> component.
35+
</span>
36+
<span>Click </span>
3837
<button
3938
style={{ fontSize: 'inherit' }}
4039
onClick={() => setLocale(locale === AppLocale.pl ? AppLocale.en : AppLocale.pl)}

src/hooks/useLocale/useLocale.ts

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,27 @@
1-
import { useContext, useMemo } from 'react';
2-
import { IntlShape, useIntl } from 'react-intl';
1+
import { useContext, useCallback, useMemo } from 'react';
2+
import { useIntl } from 'react-intl';
33

4+
import type { TranslateFn } from 'i18n/messages';
45
import { LocaleContext } from 'context/locale/localeContext/LocaleContext';
5-
import { LocaleContextValueType } from 'context/locale/localeContext/LocaleContext.types';
66

7-
export const useLocale = (): IntlShape & LocaleContextValueType => {
7+
import { UseLocaleReturnType } from './useLocale.types';
8+
9+
export const useLocale: UseLocaleReturnType = () => {
810
const intl = useIntl();
911
const localeContext = useContext(LocaleContext);
1012

1113
if (localeContext === undefined) {
1214
throw new Error('LocaleContext is unavailable, make sure you are using LocaleContextController');
1315
}
1416

15-
const locale = useMemo(
17+
const t: TranslateFn = useCallback((id, value?) => intl.formatMessage({ id }, value), [intl]);
18+
19+
return useMemo(
1620
() => ({
1721
...intl,
1822
...localeContext,
23+
t,
1924
}),
20-
[intl, localeContext],
25+
[intl, localeContext, t],
2126
);
22-
23-
return locale;
2427
};
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import type { IntlShape } from 'react-intl';
2+
3+
import type { TranslateFn } from 'i18n/messages';
4+
import type { LocaleContextValueType } from 'context/locale/localeContext/LocaleContext.types';
5+
6+
export type WithTranslateFn = {
7+
t: TranslateFn;
8+
};
9+
10+
export type UseLocaleReturnType = () => IntlShape & LocaleContextValueType & WithTranslateFn;

src/i18n/messages.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
1+
import type { PrimitiveType } from 'intl-messageformat/src/formatters';
2+
13
import { AppLocale } from 'context/locale/AppLocale.enum';
24

35
import enMessages from './data/en.json';
46
import plMessages from './data/pl.json';
57

68
type KeyAsValue<T> = { [P in keyof T]: P };
79

8-
const keysToValues = <T extends Record<string, string | unknown>>(source: T): KeyAsValue<typeof source> => {
9-
return (Object.keys(source) as Array<keyof T>).reduce(
10+
const keysToValues = <T extends Record<string, string | unknown>>(source: T): KeyAsValue<typeof source> =>
11+
(Object.keys(source) as Array<keyof T>).reduce(
1012
(accumulated, current) => {
1113
accumulated[current] = current;
1214
return accumulated;
1315
},
1416
{} as KeyAsValue<typeof source>,
1517
);
16-
};
1718

1819
export const AppMessages = {
1920
...keysToValues(enMessages),
2021
...keysToValues(plMessages),
2122
};
2223

23-
export const translations: Record<AppLocale, Record<keyof typeof AppMessages, string>> = {
24+
export type Translation = keyof typeof AppMessages;
25+
26+
export type TranslateFn = (id: Translation, value?: Record<string, PrimitiveType>) => string;
27+
28+
export const translations: Record<AppLocale, Record<Translation, string>> = {
2429
[AppLocale.en]: enMessages,
2530
[AppLocale.pl]: plMessages,
2631
};

src/ui/translation/Translation.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { useLocale } from 'hooks/useLocale/useLocale';
2+
import { AppMessages } from 'i18n/messages';
3+
4+
import { TranslationProps } from './Translation.types';
5+
6+
export const Translation = ({ id, values }: TranslationProps) => {
7+
const { formatMessage } = useLocale();
8+
9+
return <>{formatMessage({ id: AppMessages[id] }, values)}</>;
10+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { PrimitiveType } from 'react-intl';
2+
3+
import { Translation } from 'i18n/messages';
4+
5+
export type TranslationProps = {
6+
id: Translation;
7+
values?: Record<string, PrimitiveType>;
8+
};

0 commit comments

Comments
 (0)