Skip to content

Commit 0f58ae6

Browse files
committed
(@fluent/react) Refac useTranslate to return a ReactLocalization
1 parent 16013c8 commit 0f58ae6

File tree

4 files changed

+35
-98
lines changed

4 files changed

+35
-98
lines changed

fluent-react/example/src/App.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, { useState } from "react";
22
import { Localized } from "@fluent/react";
33
import { FluentDateTime } from "@fluent/bundle";
44
import { Hello } from "./Hello";
5-
import { LocalizedSignIn } from "./SignIn";
5+
import { SignIn } from "./SignIn";
66

77
export function App() {
88
let [date] = useState(() => new Date());
@@ -36,6 +36,6 @@ export function App() {
3636
</p>
3737
</Localized>
3838

39-
<LocalizedSignIn />
39+
<SignIn />
4040
</>;
4141
}

fluent-react/example/src/Hello.tsx

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,29 @@
11
import React, { useState } from "react";
2-
import { useTranslate } from "@fluent/react";
2+
import { Localized } from "@fluent/react";
33

44
export function Hello() {
55
let [userName, setUserName] = useState("");
6-
const { t, tAttributes } = useTranslate()
76

87
return (
98
<div>
109
{userName ?
11-
<h1>{t('hello', { userName })}</h1>
12-
: <h1>{t('hello-no-name')}</h1>
10+
<Localized id="hello" vars={{ userName }}>
11+
<h1>{'Hello, { $userName }!'}</h1>
12+
</Localized>
13+
:
14+
<Localized id="hello-no-name">
15+
<h1>Hello, stranger!</h1>
16+
</Localized>
1317
}
1418

15-
<input
16-
type="text"
17-
placeholder={tAttributes('type-name').placeholder}
18-
onChange={evt => setUserName(evt.target.value)}
19-
value={userName}
20-
/>
19+
<Localized id="type-name" attrs={{ placeholder: true }}>
20+
<input
21+
type="text"
22+
placeholder="Type your name"
23+
onChange={evt => setUserName(evt.target.value)}
24+
value={userName}
25+
/>
26+
</Localized>
2127
</div>
2228
);
2329
}

fluent-react/example/src/SignIn.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import React from "react";
2-
import { Localized, withLocalization, WithLocalizationProps } from "@fluent/react";
2+
import { Localized, useTranslate } from "@fluent/react";
3+
4+
export function SignIn() {
5+
const { l10n } = useTranslate()
36

4-
function SignIn(props: WithLocalizationProps) {
57
function showAlert(id: string) {
6-
const { getString } = props;
7-
alert(getString(id));
8+
alert(l10n.getString(id));
89
}
910

1011
return (
@@ -21,5 +22,3 @@ function SignIn(props: WithLocalizationProps) {
2122
</div>
2223
);
2324
}
24-
25-
export const LocalizedSignIn = withLocalization(SignIn);

fluent-react/src/useTranslate.ts

Lines changed: 12 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,28 @@
11
import { useContext } from "react";
22
import { FluentContext } from "./context";
33
import { ReactLocalization } from "./localization";
4-
import { FluentArgument, FluentBundle } from "@fluent/bundle";
54

6-
type Message = Exclude<ReturnType<FluentBundle["getMessage"]>, undefined>
7-
8-
// Using ReactLocalization and a id, return its bundle and message object
9-
// if both exists, otherwise return null for boths
10-
type getBundleAndMessage = (
11-
(l10n: ReactLocalization, id: string) =>
12-
({ bundle: FluentBundle; msg: Message } | { bundle: null; msg: null })
13-
)
14-
const getBundleAndMessage: getBundleAndMessage = (l10n, id) => {
15-
const bundle = l10n.getBundle(id);
16-
const msg = bundle?.getMessage(id);
17-
18-
if (bundle === null || msg === undefined) {
19-
return { bundle: null, msg: null };
20-
}
21-
22-
return { bundle, msg };
5+
// Implementation of null object pattern for ReactLocalization
6+
const fallbackL10n: ReactLocalization = {
7+
getString: id => id,
8+
getBundle: () => null,
9+
bundles: [],
10+
parseMarkup: null,
11+
reportError: () => undefined,
2312
};
2413

25-
type TFunction = (id: string, vars?: Record<string, FluentArgument>) => string
26-
type TAttributesFunction = (
27-
(id: string, vars?: Record<string, FluentArgument>) =>
28-
{ [key in string]: string }
29-
)
30-
31-
type useTranslate = () => { t: TFunction; tAttributes: TAttributesFunction }
32-
3314
/*
34-
* The `useTranslate` hook uses the FluentContext to return two functions
35-
* to get the translated messages from Fluent's bundle:
36-
* - t: get the root message from the given id
37-
* - tAttributes: get the attributes message from the given id
38-
*/
15+
* The `useTranslate` hook returns the FluentContext
16+
*/
17+
type useTranslate = () => { l10n: ReactLocalization }
3918
export const useTranslate: useTranslate = () => {
4019
const l10n = useContext(FluentContext);
4120

4221
if (!l10n) {
43-
// Return fallbacks functions
44-
const t: TFunction = () => "";
45-
const tAttributes: TAttributesFunction = () => ({});
46-
47-
return { t, tAttributes };
22+
return { l10n: fallbackL10n };
4823
}
4924

50-
const t: TFunction = (id, vars) => {
51-
const { bundle, msg } = getBundleAndMessage(l10n, id);
52-
53-
if (bundle === null || msg === null) {
54-
// Return as fallback an empty string.
55-
return "";
56-
}
57-
58-
// Format the message and return that
59-
const errors: Array<Error> = [];
60-
const msgValue = msg.value || "";
61-
const messageFormatted = bundle.formatPattern(msgValue, vars, errors);
62-
63-
errors.forEach(error => l10n.reportError(error));
64-
65-
return messageFormatted;
66-
};
67-
68-
const tAttributes: TAttributesFunction = (id, vars) => {
69-
const { bundle, msg } = getBundleAndMessage(l10n, id);
70-
71-
if (bundle === null || msg === null) {
72-
// Return as fallback an empty object.
73-
return {};
74-
}
75-
76-
// Format all atributes and return that
77-
const errors: Array<Error> = [];
78-
const messagesFormatted = Object
79-
.keys(msg.attributes)
80-
.reduce(
81-
(acc, key) => {
82-
acc[key] = bundle.formatPattern(msg.attributes[key], vars, errors);
83-
return acc;
84-
},
85-
{} as { [key in string]: string }
86-
);
87-
88-
errors.forEach(error => l10n.reportError(error));
89-
90-
return messagesFormatted;
91-
};
92-
93-
return { t, tAttributes };
25+
return { l10n };
9426
};
9527

9628
export default useTranslate;

0 commit comments

Comments
 (0)