Skip to content

Commit 9a36521

Browse files
committed
feat: add language selection in app
1 parent 41a0c6e commit 9a36521

File tree

6 files changed

+143
-1
lines changed

6 files changed

+143
-1
lines changed

apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/DropdownMenuOverlay.tsx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import {
88
Links,
99
LockWallet,
1010
NetworkChoise,
11+
LanguageChoice,
12+
LanguageInfo,
1113
RenameWalletDrawer,
1214
Separator,
1315
SettingsLink,
@@ -98,6 +100,11 @@ export const DropdownMenuOverlay: VFC<Props> = ({
98100
sendAnalyticsEvent(PostHogAction.UserWalletProfileNetworkClick);
99101
};
100102

103+
const handleLanguageChoice = () => {
104+
setCurrentSection(Sections.Language);
105+
sendAnalyticsEvent(PostHogAction.UserWalletProfileLanguageClick);
106+
};
107+
101108
const goBackToMainSection = useCallback(() => setCurrentSection(Sections.Main), []);
102109

103110
useEffect(() => {
@@ -209,6 +216,7 @@ export const DropdownMenuOverlay: VFC<Props> = ({
209216
/>
210217
</div>
211218
)}
219+
<LanguageChoice onClick={handleLanguageChoice} />
212220
<NetworkChoise onClick={handleNetworkChoise} />
213221
{lockWalletButton && (
214222
<>
@@ -219,6 +227,7 @@ export const DropdownMenuOverlay: VFC<Props> = ({
219227
</div>
220228
)}
221229
{currentSection === Sections.NetworkInfo && <NetworkInfo onBack={goBackToMainSection} />}
230+
{currentSection === Sections.Language && <LanguageInfo onBack={goBackToMainSection} />}
222231
{currentSection === Sections.WalletAccounts && <WalletAccounts onBack={goBackToMainSection} isPopup={isPopup} />}
223232
{isRenamingWallet && (
224233
<RenameWalletDrawer open={isRenamingWallet} popupView={isPopup} onClose={() => setIsRenamingWallet(false)} />
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import React, { useEffect, useState } from 'react';
2+
import { useTranslation } from 'react-i18next';
3+
import cn from 'classnames';
4+
import styles from '../DropdownMenuOverlay.module.scss';
5+
import { useBackgroundServiceAPIContext } from '@providers';
6+
7+
type LanguageChoiceProps = {
8+
onClick: () => void;
9+
};
10+
11+
export const LanguageChoice = ({ onClick }: LanguageChoiceProps): React.ReactElement => {
12+
const { t } = useTranslation();
13+
const { getBackgroundStorage } = useBackgroundServiceAPIContext();
14+
const [language, setLanguage] = useState<string>();
15+
16+
useEffect(() => {
17+
const getLanguage = async () => {
18+
const { languageChoice } = await getBackgroundStorage();
19+
setLanguage(languageChoice);
20+
};
21+
getLanguage();
22+
}, [getBackgroundStorage]);
23+
24+
return (
25+
<div
26+
data-testid="header-menu-language-choice-container"
27+
className={cn(styles.menuItem, styles.cta)}
28+
onClick={() => onClick()}
29+
>
30+
<div className={styles.networkChoise}>
31+
<span data-testid="header-menu-language-choice-label">{t('browserView.topNavigationBar.links.language')}</span>
32+
<span data-testid="header-menu-language-choice-value" className={styles.value}>
33+
{language || 'en'}
34+
</span>
35+
</div>
36+
</div>
37+
);
38+
};
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import React, { useCallback, useEffect, useState } from 'react';
2+
import { useTranslation } from 'react-i18next';
3+
import { NavigationButton, PostHogAction } from '@lace/common';
4+
import styles from './NetworkInfo.module.scss';
5+
import { useBackgroundServiceAPIContext } from '@providers';
6+
import { Radio, RadioChangeEvent } from 'antd';
7+
import { usePostHogClientContext } from '@providers/PostHogClientProvider';
8+
9+
type LanguageChoiceProps = {
10+
onBack: () => void;
11+
};
12+
13+
const LANG_CHOICES = ['en', 'ja']; // hardcoding for v1 only
14+
15+
export const LanguageInfo = ({ onBack }: LanguageChoiceProps): React.ReactElement => {
16+
const { t } = useTranslation();
17+
const [language, setLanguage] = useState('en'); // default
18+
const posthog = usePostHogClientContext();
19+
20+
const { getBackgroundStorage, handleChangeLanguage } = useBackgroundServiceAPIContext();
21+
22+
useEffect(() => {
23+
const getLanguage = async () => {
24+
const { languageChoice } = await getBackgroundStorage();
25+
if (languageChoice) setLanguage(languageChoice);
26+
};
27+
getLanguage();
28+
}, [getBackgroundStorage]);
29+
30+
const handleLanguageChangeRequest = useCallback(
31+
(e: RadioChangeEvent) => {
32+
handleChangeLanguage(e.target.value);
33+
posthog.sendEvent(PostHogAction.UserWalletProfileLanguageSelectClick, { language: e.target.value });
34+
},
35+
[handleChangeLanguage, posthog]
36+
);
37+
38+
return (
39+
<div data-testid="user-dropdown-language-info-section" className={styles.container}>
40+
<div className={styles.navigation} data-testid="drawer-navigation">
41+
<NavigationButton iconClassName={styles.iconClassName} icon="arrow" onClick={onBack} />
42+
</div>
43+
<div className={styles.titleSection}>
44+
<div data-testid="user-dropdown-language-title" className={styles.title}>
45+
{t('browserView.settings.wallet.language.title')}
46+
</div>
47+
<div data-testid="user-dropdown-language-description" className={styles.subTitle}>
48+
{t('browserView.settings.wallet.language.drawerDescription')}
49+
</div>
50+
</div>
51+
<div className={styles.content} data-testid="user-dropdown-language-choice">
52+
<Radio.Group
53+
className={styles.radioGroup}
54+
onChange={handleLanguageChangeRequest}
55+
value={language}
56+
data-testid={'language-choice-radio-group'}
57+
>
58+
{LANG_CHOICES.map((choice) => (
59+
<Radio key={`language-choice-${choice}`} value={choice}>
60+
{choice}
61+
</Radio>
62+
))}
63+
</Radio.Group>
64+
</div>
65+
</div>
66+
);
67+
};

apps/browser-extension-wallet/src/components/MainMenu/DropdownMenuOverlay/components/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ export * from './NetworkInfo';
1212
export * from './AddNewWalletLink';
1313
export * from './AddNewBitcoinWalletLink';
1414
export * from './RenameWalletDrawer';
15+
export * from './LanguageInfo';
16+
export * from './LanguageChoice';
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
export enum Sections {
22
Main = 'main',
33
NetworkInfo = 'network_info',
4-
WalletAccounts = 'wallet_accounts'
4+
WalletAccounts = 'wallet_accounts',
5+
Language = 'language'
56
}

apps/browser-extension-wallet/src/hooks/useAppInit.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import { setBackgroundStorage } from '@lib/scripts/background/storage';
99
import { useCustomSubmitApi } from '@hooks/useCustomSubmitApi';
1010
import { bitcoinWalletManager } from '@lib/wallet-api-ui';
1111
import { useCurrentBlockchain } from '@src/multichain';
12+
import { useBackgroundServiceAPIContext } from '@providers';
13+
import { initI18n } from '@lace/translation';
14+
import { Message, MessageTypes } from '@lib/scripts/types';
1215

1316
export const useAppInit = (): void => {
1417
const {
@@ -26,6 +29,28 @@ export const useAppInit = (): void => {
2629
const walletState = useWalletState();
2730
const { environmentName, currentChain } = useWalletStore();
2831
const { getCustomSubmitApiForNetwork } = useCustomSubmitApi();
32+
const backgroundServices = useBackgroundServiceAPIContext();
33+
34+
useEffect(() => {
35+
const subscription = backgroundServices.requestMessage$?.subscribe(({ type, data }: Message): void => {
36+
if (type === MessageTypes.CHANGE_LANGUAGE) {
37+
initI18n(data);
38+
backgroundServices.setBackgroundStorage({ languageChoice: data });
39+
}
40+
});
41+
42+
backgroundServices
43+
.getBackgroundStorage()
44+
.then((bs) => {
45+
initI18n(bs.languageChoice ?? window.navigator.language);
46+
})
47+
.catch((error) => {
48+
// eslint-disable-next-line no-console
49+
console.log(error);
50+
});
51+
52+
return () => subscription.unsubscribe();
53+
}, [backgroundServices]);
2954

3055
useEffect(() => {
3156
setWalletState(walletState);

0 commit comments

Comments
 (0)