Skip to content

Commit b422aff

Browse files
Merge pull request #6 from yita0101/origin-branch
Support for internationalization
2 parents 3d90fbe + f784d69 commit b422aff

21 files changed

+710
-209
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@ pacakge-lock.json
99
*.bak
1010
*.db
1111
*.original
12+
.idea
13+
pnpm-lock.yaml

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@
3939
"ethereum-cryptography": "^3.1.0",
4040
"fernet": "^0.3.2",
4141
"framer-motion": "^12.5.0",
42+
"i18next": "^24.2.3",
43+
"i18next-browser-languagedetector": "^8.0.4",
4244
"keytar": "^7.9.0",
45+
"react-i18next": "^15.4.1",
4346
"react-icons": "^5.5.0",
4447
"react-router": "^7.3.0",
4548
"sample": "^0.0.2",

src/renderer/src/app/components/CreateWalletModal.tsx

Lines changed: 29 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ import {
1313
} from '@heroui/react'
1414
import { PasswordInput } from '@renderer/components/PasswordInput'
1515
import { useToggle } from 'ahooks'
16-
import { useState } from 'react'
16+
import { useState, useEffect } from 'react'
1717
import { GoPlus } from 'react-icons/go'
1818
import { IoIosEye, IoIosEyeOff } from 'react-icons/io'
1919
import { MdOutlineContentCopy } from 'react-icons/md'
20+
import { useTranslation } from 'react-i18next'
2021
import { useWallet } from '../wallets/WalletContext'
2122

2223
const WALLET_PASSWORD_REGEX = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}/
@@ -34,6 +35,12 @@ export const CreateWalletModal = () => {
3435
const [walletName, setWalletName] = useState('')
3536
const [mnemonic, setMnemonic] = useState('')
3637
const [showMnemonic, { toggle: toggleShowMnemonic }] = useToggle(false)
38+
const { t, i18n } = useTranslation()
39+
const [continueText, setContinueText] = useState(t('common.continue'))
40+
41+
useEffect(() => {
42+
setContinueText(t('common.continue'))
43+
}, [i18n.language, t])
3744

3845
const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
3946
e.preventDefault()
@@ -42,8 +49,8 @@ export const CreateWalletModal = () => {
4249

4350
if (password !== passwordConfirm) {
4451
addToast({
45-
title: 'Mismatched Passwords',
46-
description: 'Passwords do not match',
52+
title: t('toasts.passwordMismatch.title'),
53+
description: t('toasts.passwordMismatch.description'),
4754
color: 'danger',
4855
})
4956
return
@@ -56,8 +63,8 @@ export const CreateWalletModal = () => {
5663
setPassword(password)
5764
} catch (error) {
5865
addToast({
59-
title: 'Error',
60-
description: 'Failed to generate mnemonic',
66+
title: t('toasts.generateError.title'),
67+
description: t('toasts.generateError.description'),
6168
color: 'danger',
6269
})
6370
}
@@ -66,8 +73,8 @@ export const CreateWalletModal = () => {
6673
const handleCopy = async () => {
6774
await navigator.clipboard.writeText(mnemonic)
6875
addToast({
69-
title: 'Copied',
70-
description: 'Mnemonic copied to clipboard',
76+
title: t('toasts.copied.title'),
77+
description: t('toasts.copied.description'),
7178
color: 'success',
7279
})
7380
}
@@ -83,8 +90,8 @@ export const CreateWalletModal = () => {
8390
await window.dbAPI.insertWallet(walletName, address, encrypted, salt)
8491

8592
addToast({
86-
title: 'Wallet Created',
87-
description: 'Your wallet has been created successfully',
93+
title: t('toasts.walletCreated.title'),
94+
description: t('toasts.walletCreated.description'),
8895
color: 'success',
8996
})
9097
setMnemonic('')
@@ -95,8 +102,8 @@ export const CreateWalletModal = () => {
95102
onClose()
96103
} catch (error) {
97104
addToast({
98-
title: 'Error',
99-
description: 'Failed to create wallet',
105+
title: t('toasts.creationFailed.title'),
106+
description: t('toasts.creationFailed.description'),
100107
color: 'danger',
101108
})
102109
}
@@ -113,7 +120,7 @@ export const CreateWalletModal = () => {
113120
'linear-gradient(176.63deg, #725DFD -33.88%, #3E3384 111.03%)',
114121
}}
115122
>
116-
Create Wallet
123+
{t('common.createWallet')}
117124
</Button>
118125

119126
<Modal
@@ -126,9 +133,9 @@ export const CreateWalletModal = () => {
126133
<ModalContent>
127134
<div className="space-y-12 px-12 py-12">
128135
<ModalHeader className="block space-y-6 text-center">
129-
<h3 className="text-[28px]">Create Wallet</h3>
136+
<h3 className="text-[28px]">{t('createWallet.title')}</h3>
130137
<p className="text-lg font-normal text-default-400">
131-
Create a new wallet to manage your WART tokens
138+
{t('createWallet.description')}
132139
</p>
133140
</ModalHeader>
134141

@@ -141,7 +148,7 @@ export const CreateWalletModal = () => {
141148
>
142149
<Input
143150
name="name"
144-
label="Wallet Name"
151+
label={t('common.walletName')}
145152
labelPlacement="outside"
146153
isRequired
147154
size="lg"
@@ -151,21 +158,21 @@ export const CreateWalletModal = () => {
151158
/>
152159
<PasswordInput
153160
name="password"
154-
label="Password"
161+
label={t('common.password')}
155162
labelPlacement="outside"
156163
isRequired
157164
size="lg"
158165
validate={(value) =>
159166
!WALLET_PASSWORD_REGEX.test(value)
160-
? 'Invalid password format'
167+
? t('createWallet.invalidPassword')
161168
: undefined
162169
}
163170
variant="faded"
164171
classNames={{ inputWrapper: 'bg-default-200' }}
165172
/>
166173
<PasswordInput
167174
name="passwordConfirm"
168-
label="Confirm Password"
175+
label={t('common.confirmPassword')}
169176
labelPlacement="outside"
170177
isRequired
171178
size="lg"
@@ -177,7 +184,7 @@ export const CreateWalletModal = () => {
177184
) : (
178185
<ModalBody>
179186
<p className="text-center font-bold">
180-
Store your mnemonic safely:
187+
{t('createWallet.storeMnemonic')}
181188
</p>
182189
<div className="flex items-center gap-3">
183190
<Code className="w-[500px] text-wrap break-words text-base">
@@ -209,8 +216,7 @@ export const CreateWalletModal = () => {
209216
</div>
210217
</div>
211218
<p className="text-sm font-bold text-warning">
212-
Warning: Lose these words, lose your wallet. Store them
213-
safely!
219+
{t('common.warning')}
214220
</p>
215221
</ModalBody>
216222
)}
@@ -224,15 +230,15 @@ export const CreateWalletModal = () => {
224230
fullWidth
225231
radius="sm"
226232
>
227-
Create Wallet
233+
{t('common.createWallet')}
228234
</Button>
229235
) : (
230236
<Button
231237
color="default"
232238
fullWidth
233239
onPress={finalizeWalletCreation}
234240
>
235-
Continue
241+
{continueText}
236242
</Button>
237243
)}
238244
</ModalFooter>

src/renderer/src/app/components/RecoverWalletModal.tsx

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
} from '@heroui/react'
1313
import { PasswordInput } from '@renderer/components/PasswordInput'
1414
import { useState } from 'react'
15+
import { useTranslation } from 'react-i18next'
1516
import { useWallet } from '../wallets/WalletContext'
1617

1718
const WALLET_PASSWORD_REGEX = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}/
@@ -20,6 +21,7 @@ export const RecoverWalletModal = () => {
2021
const { refreshAsync } = useWallet()
2122
const { isOpen, onClose, onOpen } = useDisclosure()
2223
const [password, setPassword] = useState('')
24+
const { t } = useTranslation()
2325

2426
const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
2527
e.preventDefault()
@@ -34,18 +36,17 @@ export const RecoverWalletModal = () => {
3436

3537
if (!WALLET_PASSWORD_REGEX.test(password)) {
3638
addToast({
37-
title: 'Invalid Password',
38-
description:
39-
'Password must be at least 8 characters long and contain at least one letter and one number',
39+
title: t('toasts.invalidPassword.title'),
40+
description: t('toasts.invalidPassword.description'),
4041
color: 'danger',
4142
})
4243
return
4344
}
4445

4546
if (password !== confirmPassword) {
4647
addToast({
47-
title: 'Mismatched Passwords',
48-
description: 'Passwords do not match',
48+
title: t('toasts.passwordMismatch.title'),
49+
description: t('toasts.passwordMismatch.description'),
4950
color: 'danger',
5051
})
5152
return
@@ -61,8 +62,8 @@ export const RecoverWalletModal = () => {
6162
await window.dbAPI.insertWallet(wallet, address, encrypted, salt)
6263

6364
addToast({
64-
title: 'Success',
65-
description: 'Wallet successfully recovered',
65+
title: t('toasts.walletRecovered.title'),
66+
description: t('toasts.walletRecovered.description'),
6667
color: 'success',
6768
})
6869

@@ -71,14 +72,14 @@ export const RecoverWalletModal = () => {
7172
} catch (error: any) {
7273
if (error?.message?.includes('UNIQUE constraint failed')) {
7374
addToast({
74-
title: 'Duplicate Wallet',
75-
description: 'This wallet is already added',
75+
title: t('toasts.duplicateWallet.title'),
76+
description: t('toasts.duplicateWallet.description'),
7677
color: 'warning',
7778
})
7879
} else {
7980
addToast({
80-
title: 'Error',
81-
description: 'An error occurred while recovering wallet',
81+
title: t('toasts.recoveryError.title'),
82+
description: t('toasts.recoveryError.description'),
8283
color: 'danger',
8384
})
8485
}
@@ -87,18 +88,18 @@ export const RecoverWalletModal = () => {
8788

8889
const validatePassword = (value: string) => {
8990
return !WALLET_PASSWORD_REGEX.test(value)
90-
? 'Password must be at least 8 characters long and contain at least one letter and one number'
91+
? t('recoverWallet.errorPassword')
9192
: undefined
9293
}
9394

9495
const validateConfirmPassword = (value: string) => {
95-
return value !== password ? 'Passwords do not match' : undefined
96+
return value !== password ? t('toasts.passwordMismatch.description') : undefined
9697
}
9798

9899
return (
99100
<>
100101
<Button onPress={onOpen} className="bg-[#27292B] px-9">
101-
Recover Wallet
102+
{t('common.recoverWallet')}
102103
</Button>
103104

104105
<Modal
@@ -113,9 +114,9 @@ export const RecoverWalletModal = () => {
113114
<ModalContent>
114115
<div className="space-y-12 px-12 py-12">
115116
<ModalHeader className="block space-y-6 text-center">
116-
<h3 className="text-[28px]">Recover Wallet</h3>
117+
<h3 className="text-[28px]">{t('recoverWallet.title')}</h3>
117118
<p className="text-lg font-normal text-default-400">
118-
Recover a wallet to manage your WART tokens
119+
{t('recoverWallet.description')}
119120
</p>
120121
</ModalHeader>
121122

@@ -128,9 +129,9 @@ export const RecoverWalletModal = () => {
128129
<Input
129130
name="wallet"
130131
type="text"
131-
errorMessage="Please enter a valid wallet name"
132+
errorMessage={t('recoverWallet.errorWalletName')}
132133
labelPlacement="outside"
133-
label="Wallet Name"
134+
label={t('common.walletName')}
134135
isRequired
135136
size="lg"
136137
autoFocus
@@ -140,19 +141,19 @@ export const RecoverWalletModal = () => {
140141
<Input
141142
name="mnemonic"
142143
type="text"
143-
errorMessage="Please enter a valid mnemonic"
144+
errorMessage={t('recoverWallet.errorMnemonic')}
144145
labelPlacement="outside"
145-
label="Mnemonic"
146+
label={t('common.mnemonic')}
146147
isRequired
147148
size="lg"
148149
variant="faded"
149150
classNames={{ inputWrapper: 'bg-default-200' }}
150151
/>
151152
<PasswordInput
152153
name="password"
153-
errorMessage="Please enter a valid password"
154+
errorMessage={t('recoverWallet.errorPassword')}
154155
labelPlacement="outside"
155-
label="Password"
156+
label={t('common.password')}
156157
isRequired
157158
size="lg"
158159
variant="faded"
@@ -163,7 +164,7 @@ export const RecoverWalletModal = () => {
163164
<PasswordInput
164165
name="confirmPassword"
165166
labelPlacement="outside"
166-
label="Confirm Password"
167+
label={t('common.confirmPassword')}
167168
isRequired
168169
size="lg"
169170
validate={validateConfirmPassword}
@@ -181,7 +182,7 @@ export const RecoverWalletModal = () => {
181182
fullWidth
182183
radius="sm"
183184
>
184-
Recover Wallet
185+
{t('common.recoverWallet')}
185186
</Button>
186187
</ModalFooter>
187188
</div>

0 commit comments

Comments
 (0)