diff --git a/rollup.config.dev.js b/rollup.config.dev.js
index da55098..45816b0 100644
--- a/rollup.config.dev.js
+++ b/rollup.config.dev.js
@@ -7,7 +7,7 @@ import resolve from '@rollup/plugin-node-resolve';
import typescript from '@rollup/plugin-typescript';
import peerDepsExternal from 'rollup-plugin-peer-deps-external';
-import pkg from './package.json' assert { type: 'json' };
+import pkg from './package.json' with { type: 'json' };
export default {
input: 'src/index.ts',
@@ -30,8 +30,8 @@ export default {
{
find: 'global',
replacement: 'globalThis',
- }
- ]
+ },
+ ],
}),
json(),
peerDepsExternal(),
@@ -53,9 +53,7 @@ export default {
exclude: ['node_modules', 'motion'],
}),
],
- external: [
- ...Object.keys(pkg.peerDependencies || {}),
- ],
+ external: [...Object.keys(pkg.peerDependencies || {})],
watch: {
clearScreen: false,
include: 'src/**',
diff --git a/rollup.config.prod.js b/rollup.config.prod.js
index 034c63c..bc274c9 100644
--- a/rollup.config.prod.js
+++ b/rollup.config.prod.js
@@ -9,7 +9,7 @@ import peerDepsExternal from 'rollup-plugin-peer-deps-external';
import tailwindcss from '@tailwindcss/postcss';
-import pkg from './package.json' assert { type: 'json' };
+import pkg from './package.json' with { type: 'json' };
export default {
input: 'src/index.ts',
@@ -33,8 +33,8 @@ export default {
{
find: 'global',
replacement: 'globalThis',
- }
- ]
+ },
+ ],
}),
json(),
peerDepsExternal(),
@@ -54,7 +54,13 @@ export default {
commonjs(),
postcss({
extract: false,
- inject: true,
+ extensions: ['.css'],
+ inject: {
+ insertAt: 'top',
+ },
+ config: {
+ path: './postcss.config.mjs',
+ },
minimize: true,
plugins: [tailwindcss],
}),
@@ -63,7 +69,5 @@ export default {
exclude: ['node_modules', 'motion'],
}),
],
- external: [
- ...Object.keys(pkg.peerDependencies || {}),
- ],
+ external: [...Object.keys(pkg.peerDependencies || {})],
};
diff --git a/src/components/Button/index.tsx b/src/components/Button/index.tsx
index 7f68da4..697cdca 100644
--- a/src/components/Button/index.tsx
+++ b/src/components/Button/index.tsx
@@ -20,7 +20,7 @@ interface ButtonProps {
}
const buttonBase =
- 'bluxcc:flex bluxcc:justify-center bluxcc:items-center bluxcc:px-[10px] bluxcc:transition-all bluxcc:w-full';
+ 'bluxcc:flex bluxcc:justify-center bluxcc:items-center bluxcc:px-[10px] bluxcc:transition-all bluxcc:duration-300 bluxcc:w-full';
const sizeClasses: Record = {
small: 'bluxcc:h-8 bluxcc:!text-sm bluxcc:gap-1',
diff --git a/src/components/CardItem/index.tsx b/src/components/CardItem/index.tsx
index 9000cb8..84f2a97 100644
--- a/src/components/CardItem/index.tsx
+++ b/src/components/CardItem/index.tsx
@@ -2,6 +2,7 @@ import React, { useState, MouseEvent } from 'react';
import { useProvider } from '../../context/provider';
import { ArrowRight } from '../../assets/Icons';
import hexToRgba from '../../utils/hexToRgba';
+import { useLang } from '../../hooks/useLang';
type CardItemProps = {
variant?: 'social' | 'default' | 'input';
@@ -30,6 +31,7 @@ const CardItem = ({
}: CardItemProps) => {
const context = useProvider();
const { appearance } = context.value.config;
+ const t = useLang();
const [inputValue, setInputValue] = useState(label || '');
const [isValid, setIsValid] = useState(false);
@@ -70,7 +72,7 @@ const CardItem = ({
return (
setIsFocused(true)}
@@ -133,7 +135,7 @@ const CardItem = ({
: '1px',
}}
>
- Submit
+ {t('submit')}
>
@@ -150,7 +152,7 @@ const CardItem = ({
backgroundColor: `${hexToRgba(appearance.accent, 0.1)}`,
}}
>
- Recent
+ {t('recent')}
)}
diff --git a/src/components/Input/index.tsx b/src/components/Input/index.tsx
index f15597a..e1e69a4 100644
--- a/src/components/Input/index.tsx
+++ b/src/components/Input/index.tsx
@@ -99,7 +99,7 @@ const InputField = ({
)}
setIsFocused(true)}
onBlur={() => setIsFocused(false)}
onMouseEnter={onMouseEnter}
diff --git a/src/components/Modal/index.tsx b/src/components/Modal/index.tsx
index a7d35d3..8cfb832 100644
--- a/src/components/Modal/index.tsx
+++ b/src/components/Modal/index.tsx
@@ -87,7 +87,7 @@ const Modal = ({
onClick={(e) => e.target === e.currentTarget && handleClose(onClose)}
>
= {
+export const getModalContent = (
+ lang: LanguageKey,
+): Record
=> ({
[Routes.ONBOARDING]: {
- title: 'Log in or Signup',
+ title: translate('logInOrSignUp', lang),
Component: ,
},
[Routes.PROFILE]: {
- title: 'Profile',
+ title: translate('profile', lang),
Component: ,
},
[Routes.WAITING]: {
@@ -35,24 +38,24 @@ export const modalContent: Record = {
Component: ,
},
[Routes.SIGN_TRANSACTION]: {
- title: 'Confirmation',
+ title: translate('confirmation', lang),
Component: ,
},
[Routes.SEND]: {
- title: 'Send',
+ title: translate('send', lang),
Component: ,
},
[Routes.ACTIVITY]: {
- title: 'Activity',
+ title: translate('activity', lang),
Component: ,
},
[Routes.OTP]: {
- title: '',
+ title: translate('enterConfirmationCodeTitle', lang),
Component: ,
},
[Routes.WRONG_NETWORK]: {
isSticky: true,
- title: 'Wrong Network',
+ title: translate('wrongNetwork', lang),
Component: ,
},
-};
+});
diff --git a/src/containers/BluxModal/index.tsx b/src/containers/BluxModal/index.tsx
index 57d2ef4..e0b0d73 100644
--- a/src/containers/BluxModal/index.tsx
+++ b/src/containers/BluxModal/index.tsx
@@ -4,7 +4,8 @@ import Modal from '../../components/Modal';
import { useProvider } from '../../context/provider';
import { Routes } from '../../types';
-import { modalContent } from './content';
+import { getModalContent } from './content';
+import { LanguageKey } from '../../constants/locales';
interface BluxModalProps {
isOpen: boolean;
@@ -59,6 +60,7 @@ export default function BluxModal({ isOpen, closeModal }: BluxModalProps) {
}
}
};
+ const modalContent = getModalContent(value.config.lang as LanguageKey);
const { title, Component, isSticky } = modalContent[route];
diff --git a/src/containers/Pages/Activity/index.tsx b/src/containers/Pages/Activity/index.tsx
index 84f1b87..dd62a03 100644
--- a/src/containers/Pages/Activity/index.tsx
+++ b/src/containers/Pages/Activity/index.tsx
@@ -2,6 +2,7 @@ import { Horizon } from '@stellar/stellar-sdk';
import React, { useEffect, useState } from 'react';
import Button from '../../../components/Button';
+import { useLang } from '../../../hooks/useLang';
import { useTransactions } from '../../../useStellar';
import { useProvider } from '../../../context/provider';
import toTitleFormat from '../../../utils/toTitleFormat';
@@ -27,7 +28,7 @@ const Activity: React.FC = () => {
});
const { value } = useProvider();
-
+ const t = useLang();
const userAddress = value.user.wallet?.address as string;
const explorerUrl = getExplorerUrl(
value.activeNetwork,
@@ -60,12 +61,12 @@ const Activity: React.FC = () => {
};
if (tx.operations.length > 1) {
- details.title = 'Multi Operation';
+ details.title = t('multiOperation');
} else if (op.type === 'payment') {
- let title = 'Send';
+ let title = t('send');
if (op.to.toLowerCase() === userAddress.toLowerCase()) {
- title = 'Receive';
+ title = t('receive');
}
details.title = title;
@@ -75,8 +76,11 @@ const Activity: React.FC = () => {
Horizon.HorizonApi.OperationResponseType.pathPaymentStrictSend ||
op.type === Horizon.HorizonApi.OperationResponseType.pathPayment
) {
- details.title = 'Swap';
- details.description = `Path payment of ${op.amount} ${handleAssetText(op)}`;
+ details.title = t('swap');
+ details.description = t('pathPaymentDescription', {
+ amount: op.amount,
+ asset: handleAssetText(op),
+ });
}
result.push(details);
@@ -91,11 +95,11 @@ const Activity: React.FC = () => {
{loading ? (
- Loading activity...
+ {t('loadingActivity')}
) : isEmpty ? (
- No activity found
+ {t('noActivityFound')}
) : (
transactionsDetails.map((tx, index) => (
@@ -126,7 +130,7 @@ const Activity: React.FC = () => {
size="medium"
onClick={handleGoToExplorer}
>
- See all in explorer
+ {t('seeAllInExplorer')}
)}
diff --git a/src/containers/Pages/ConfirmCode/index.tsx b/src/containers/Pages/ConfirmCode/index.tsx
index fa2ffc9..25e9307 100644
--- a/src/containers/Pages/ConfirmCode/index.tsx
+++ b/src/containers/Pages/ConfirmCode/index.tsx
@@ -1,12 +1,14 @@
import React, { useState, useEffect } from 'react';
-import { EmailIcon } from '../../../assets/Icons';
+import { useLang } from '../../../hooks/useLang';
import Button from '../../../components/Button';
+import { EmailIcon } from '../../../assets/Icons';
import { useProvider } from '../../../context/provider';
import OTPInput from '../../../components/Input/OTPInput';
const ConfirmCode: React.FC = () => {
const { value } = useProvider();
const appearance = value.config.appearance;
+ const t = useLang();
const email = value.user.email;
const [otp, setOtp] = useState(Array(6).fill(''));
@@ -36,7 +38,7 @@ const ConfirmCode: React.FC = () => {
}, [otp, email]);
return (
-
+
{
- Enter confirmation code
+ {t('enterConfirmationCodeTitle')}
{error ? (
- Invalid code, please try again.
+ {t('invalidCodeError')}
) : (
- Please check your email and enter confirmation code below
+ {t('enterConfirmationCodeHelp')}
)}
@@ -71,7 +73,7 @@ const ConfirmCode: React.FC = () => {
{/* divider */}
{
color: appearance.accent,
}}
>
- Resend code
+ {t('resendCode')}
);
diff --git a/src/containers/Pages/OnBoarding/index.tsx b/src/containers/Pages/OnBoarding/index.tsx
index 1392c8f..8632908 100644
--- a/src/containers/Pages/OnBoarding/index.tsx
+++ b/src/containers/Pages/OnBoarding/index.tsx
@@ -2,6 +2,7 @@ import React, { useState, useMemo } from 'react';
import CardItem from '../../../components/CardItem';
import handleLogos from '../../../utils/handleLogos';
+import { useLang } from '../../../hooks/useLang';
import { useProvider } from '../../../context/provider';
import { Routes, WalletInterface } from '../../../types';
import getContrastColor from '../../../utils/getContrastColor';
@@ -12,6 +13,7 @@ import isBackgroundDark from '../../../utils/isBackgroundDark';
const OnBoarding = () => {
const { value, setValue, setRoute } = useProvider();
+ const t = useLang();
const [inputValue, setInputValue] = useState('');
const wallets = value.availableWallets;
@@ -88,7 +90,7 @@ const OnBoarding = () => {
color: appearance.borderColor,
}}
>
- or
+ {t('or')}
);
@@ -143,7 +145,7 @@ const OnBoarding = () => {
{hiddenWallets.length > 0 && !value.showAllWallets && (
{
className="bluxcc:mt-6! bluxcc:flex bluxcc:h-4 bluxcc:cursor-pointer bluxcc:items-center bluxcc:justify-center bluxcc:text-sm bluxcc:leading-[28px] bluxcc:font-medium"
style={{ color: appearance.accent }}
>
- Log in with Passkey
+ {t('logInWithPasskey')}{' '}
);
}
@@ -200,17 +202,17 @@ const OnBoarding = () => {
diff --git a/src/containers/Pages/Profile/index.tsx b/src/containers/Pages/Profile/index.tsx
index a273621..ed61ebf 100644
--- a/src/containers/Pages/Profile/index.tsx
+++ b/src/containers/Pages/Profile/index.tsx
@@ -2,6 +2,7 @@ import React, { useState } from 'react';
import { Routes } from '../../../types';
import copyText from '../../../utils/copyText';
+import { useLang } from '../../../hooks/useLang';
import { useBlux } from '../../../hooks/useBlux';
import CardItem from '../../../components/CardItem';
import { useProvider } from '../../../context/provider';
@@ -11,6 +12,7 @@ import { Copy, History, LogOut, Send } from '../../../assets/Icons';
const Profile = () => {
const { logout } = useBlux();
+ const t = useLang();
const context = useProvider();
const [copied, setCopied] = useState(false);
@@ -30,13 +32,13 @@ const Profile = () => {
setCopied(false);
}, 1000);
})
- .catch(() => { });
+ .catch(() => {});
};
const balance = context.value.account.account
? context.value.account.account.balances.find(
- (b) => b.asset_type === 'native',
- )?.balance
+ (b) => b.asset_type === 'native',
+ )?.balance
: '0';
return (
@@ -51,7 +53,7 @@ const Profile = () => {
style={{ color: appearance.textColor }}
>
{copied ? (
- 'Copied!'
+ t('copied')
) : (
{address ? shortenAddress(address, 5) : ''}
@@ -63,13 +65,13 @@ const Profile = () => {
className="bluxcc:text-center bluxcc:text-base"
style={{ color: appearance.accent }}
>
- {balance ? `${humanizeAmount(balance)} XLM` : 'Loading...'}
+ {balance ? `${humanizeAmount(balance)} XLM` : t('loading')}
}
onClick={() => {
context.setRoute(Routes.SEND);
@@ -78,7 +80,7 @@ const Profile = () => {
}
onClick={() => {
context.setRoute(Routes.ACTIVITY);
@@ -104,7 +106,7 @@ const Profile = () => {
className="bluxcc:flex bluxcc:h-12 bluxcc:w-full bluxcc:cursor-pointer bluxcc:items-center bluxcc:justify-center bluxcc:gap-2"
>
- Logout
+ {t('logout')}
);
diff --git a/src/containers/Pages/SelectAsset/index.tsx b/src/containers/Pages/SelectAsset/index.tsx
index 2f2de03..1232014 100644
--- a/src/containers/Pages/SelectAsset/index.tsx
+++ b/src/containers/Pages/SelectAsset/index.tsx
@@ -2,6 +2,7 @@ import React, { useState, MouseEvent, ChangeEvent } from 'react';
import { IAsset } from '../../../types';
import { Search } from '../../../assets/Icons';
+import { useLang } from '../../../hooks/useLang';
import { useProvider } from '../../../context/provider';
import humanizeAmount from '../../../utils/humanizeAmount';
@@ -17,6 +18,7 @@ const SelectAssets = ({
setShowSelectAssetPage,
}: SelectAssetsProps) => {
const context = useProvider();
+ const t = useLang();
const appearance = context.value.config.appearance;
const [isFocused, setIsFocused] = useState(false);
const [searchQuery, setSearchQuery] = useState('');
@@ -46,7 +48,7 @@ const SelectAssets = ({
};
if (context.value.account.loading) {
- return Loading
;
+ return {t('loading')}
;
}
return (
@@ -76,7 +78,7 @@ const SelectAssets = ({
) =>
setSearchQuery(e.target.value)
@@ -135,7 +137,7 @@ const SelectAssets = ({
style={{ color: appearance.textColor }}
className="bluxcc:mt-2 bluxcc:text-center"
>
- No assets found
+ {t('noAssetsFound')}
)}
diff --git a/src/containers/Pages/Send/SendForm.tsx b/src/containers/Pages/Send/SendForm.tsx
index ab5198f..b782767 100644
--- a/src/containers/Pages/Send/SendForm.tsx
+++ b/src/containers/Pages/Send/SendForm.tsx
@@ -11,6 +11,7 @@ import { StellarSmallLogo } from '../../../assets/logos';
import getContrastColor from '../../../utils/getContrastColor';
import paymentTransaction from '../../../utils/stellar/paymentTransaction';
import { StrKey } from '@stellar/stellar-sdk';
+import { useLang } from '../../../hooks/useLang';
type SendFormValues = {
memo: string;
@@ -19,6 +20,7 @@ type SendFormValues = {
};
const SendForm = () => {
+ const t = useLang();
const { value, setValue } = useProvider();
const { sendTransaction } = useBlux();
const [errors, setErrors] = useState>({});
@@ -85,15 +87,15 @@ const SendForm = () => {
const errorMessages: typeof errors = {};
if (!form.amount) {
- errorMessages.amount = 'Amount is required';
+ errorMessages.amount = t('amountRequired');
} else if (Number(form.amount) > Number(selectedAsset.balance)) {
- errorMessages.amount = 'Amount is greater than max balance';
+ errorMessages.amount = t('amountExceedsBalance');
}
if (!form.address) {
- errorMessages.address = 'Address is required';
+ errorMessages.address = t('addressRequired');
} else if (!StrKey.isValidEd25519PublicKey(form.address)) {
- errorMessages.address = 'Address is invalid';
+ errorMessages.address = t('addressInvalid');
}
setErrors(errorMessages);
@@ -143,7 +145,7 @@ const SendForm = () => {
{
style={{ color: appearance.accent }}
className="bluxcc:mr-2 bluxcc:inline-flex bluxcc:cursor-pointer"
>
- Max
+ {t('max')}
}
onButtonClick={handleOpenAssets}
@@ -173,20 +175,20 @@ const SendForm = () => {
@@ -211,7 +213,7 @@ const SendForm = () => {
state="enabled"
onClick={handleSubmit}
>
- Send
+ {t('sendButton')}
>
diff --git a/src/containers/Pages/Send/index.tsx b/src/containers/Pages/Send/index.tsx
index 949c38b..9657f4a 100644
--- a/src/containers/Pages/Send/index.tsx
+++ b/src/containers/Pages/Send/index.tsx
@@ -1,19 +1,20 @@
import React from 'react';
import { useProvider } from '../../../context/provider';
+import { useLang } from '../../../hooks/useLang';
import SendForm from './SendForm';
const Send = () => {
const { value } = useProvider();
-
+ const t = useLang();
const { account, loading } = value.account;
if (loading) {
- return Loading
;
+ return {t('loading')}
;
}
if (!account) {
- return Account is inactive
;
+ return {t('inactiveAccount')}
;
}
return ;
diff --git a/src/containers/Pages/SignTransaction/index.tsx b/src/containers/Pages/SignTransaction/index.tsx
index 64698c9..8dc56f7 100644
--- a/src/containers/Pages/SignTransaction/index.tsx
+++ b/src/containers/Pages/SignTransaction/index.tsx
@@ -10,8 +10,10 @@ import shortenAddress from '../../../utils/shortenAddress';
import Summary from '../../../components/Transaction/Summary';
import getActiveNetworkTitle from '../../../utils/network/getNetworkTitle';
import getTransactionDetails from '../../../utils/stellar/getTransactionDetails';
+import { useLang } from '../../../hooks/useLang';
const SignTransaction = () => {
+ const t = useLang();
const context = useProvider();
const { balance } = useBalance({ asset: 'native' });
@@ -33,7 +35,7 @@ const SignTransaction = () => {
if (!txDetails) {
return (
-
Invalid XDR
+
{t('invalidXdr')}
);
}
@@ -47,7 +49,7 @@ const SignTransaction = () => {
{context.value.config.appName}{' '}
- wants your permission to approve the following transaction.
+ {t('signTransactionPrompt')}
{
{isLobstr && (
- Ensure that your LOBSTR wallet is set to the {networkTitle} network.
- Otherwise, the transaction will definitely fail.
+ {t('lobstrWarning', { network: networkTitle })}
)}
@@ -76,7 +77,7 @@ const SignTransaction = () => {
>
- Your wallet
+ {t('yourWallet')}
{
>
{context.value.user.wallet?.address
? shortenAddress(context.value.user.wallet.address as string, 5)
- : 'No address found'}
+ : t('noAddressFound')}
{
variant="fill"
onClick={handleSignTx}
>
- Approve
+ {t('approve')}
);
diff --git a/src/containers/Pages/Successful/index.tsx b/src/containers/Pages/Successful/index.tsx
index 24a3fca..07dcf53 100644
--- a/src/containers/Pages/Successful/index.tsx
+++ b/src/containers/Pages/Successful/index.tsx
@@ -6,9 +6,11 @@ import { useProvider } from '../../../context/provider';
import getExplorerUrl from '../../../utils/stellar/getExplorerUrl';
import capitalizeFirstLetter from '../../../utils/capitalizeFirstLetter';
import { Horizon, rpc } from '@stellar/stellar-sdk';
+import { useLang } from '../../../hooks/useLang';
const Successful = () => {
const context = useProvider();
+ const t = useLang();
const waitingStatus = context.value.waitingStatus;
const appearance = context.value.config.appearance;
const { result, options } = context.value.signTransaction;
@@ -71,20 +73,23 @@ const Successful = () => {
};
return (
-
+
- {waitingStatus === 'connecting' ? 'Connection' : 'Transaction'}{' '}
- Successful
+ {waitingStatus === 'connecting'
+ ? t('connectionSuccessfulTitle')
+ : t('transactionSuccessfulTitle')}
{waitingStatus === 'connecting'
- ? `Your account has been successfully connected to ${capitalizeFirstLetter(context.value.config.appName)}`
- : 'Your transaction was successfully completed'}
+ ? t('connectionSuccessfulMessage', {
+ appName: capitalizeFirstLetter(context.value.config.appName),
+ })
+ : t('transactionSuccessfulMessage')}
{waitingStatus === 'signing' &&
@@ -97,14 +102,14 @@ const Successful = () => {
className="mt-4"
onClick={handleGoToExplorer}
>
- See in explorer
+ {t('seeInExplorer')}
)}
{/* divider */}
{
variant="outline"
className="bluxcc:cursor-default!"
>
- Logging In
+ {t('loggingIn')}
) : (
{
size="large"
onClick={handleDone}
>
- Done
+ {t('done')}
)}
diff --git a/src/containers/Pages/Waiting/index.tsx b/src/containers/Pages/Waiting/index.tsx
index 4bb8545..6e65dce 100644
--- a/src/containers/Pages/Waiting/index.tsx
+++ b/src/containers/Pages/Waiting/index.tsx
@@ -9,9 +9,11 @@ import isBackgroundDark from '../../../utils/isBackgroundDark';
import { Loading, RedExclamation } from '../../../assets/Icons';
import { setRecentConnectionMethod } from '../../../utils/setRecentConnectionMethod';
import handleTransactionSigning from '../../../utils/stellar/handleTransactionSigning';
+import { useLang } from '../../../hooks/useLang';
const Waiting = () => {
const context = useProvider();
+ const t = useLang();
const hasConnected = useRef(false);
const [error, setError] = useState(false);
const [matchedWallet, setMatchedWallet] = useState
(
@@ -107,7 +109,7 @@ const Waiting = () => {
};
return (
-
+
{error ? (
{
{error
- ? `${waitingStatus === 'connecting'
- ? 'Login failed'
- : `Signing with ${user?.wallet?.name} failed`
- }`
- : `${waitingStatus === 'connecting' ? 'Waiting for' : `Signing with`
- } ${user?.wallet?.name}`}
+ ? waitingStatus === 'connecting'
+ ? t('loginFailed')
+ : t('signingFailed', {
+ walletName: user?.wallet?.name ?? 'wallet',
+ })
+ : waitingStatus === 'connecting'
+ ? t('waitingFor', { walletName: user?.wallet?.name ?? 'wallet' })
+ : t('signingWith', {
+ walletName: user?.wallet?.name ?? 'wallet',
+ })}
{error
- ? `Please try ${waitingStatus === 'connecting' ? 'logging in' : 'signing'} again.`
- : `${waitingStatus === 'connecting'
- ? 'Accept connection'
- : 'Sign the'
- } request in your wallet`}
+ ? waitingStatus === 'connecting'
+ ? t('loginRetryMessage')
+ : t('signingRetryMessage')
+ : waitingStatus === 'connecting'
+ ? t('acceptConnection')
+ : t('signRequestInWallet')}
{/* divider */}
{
{error ? (
- Try again
+ {t('tryAgain')}
) : (
{
className="bluxcc:cursor-default!"
startIcon={ }
>
- {waitingStatus === 'connecting' ? 'Connecting' : 'Signing'}
+ {waitingStatus === 'connecting' ? t('connecting') : t('signing')}
)}
diff --git a/src/containers/Pages/WrongNetwork/index.tsx b/src/containers/Pages/WrongNetwork/index.tsx
index c47fbda..69e8047 100644
--- a/src/containers/Pages/WrongNetwork/index.tsx
+++ b/src/containers/Pages/WrongNetwork/index.tsx
@@ -1,13 +1,13 @@
import React from 'react';
+import { useLang } from '../../../hooks/useLang';
const WrongNetwork = () => {
+ const t = useLang();
return (
-
You are on a wrong network.
+
{t('wrongNetworkMessage')}
- )
-
+ );
};
export default WrongNetwork;
-
diff --git a/src/context/provider.tsx b/src/context/provider.tsx
index f219124..45386db 100644
--- a/src/context/provider.tsx
+++ b/src/context/provider.tsx
@@ -76,6 +76,7 @@ export const BluxProvider = ({
config: {
...config,
explorer: config.explorer || 'stellarchain',
+ lang: config.lang,
appearance: {
...defaultLightTheme,
...config.appearance,
diff --git a/src/hooks/useLang.ts b/src/hooks/useLang.ts
new file mode 100644
index 0000000..4c77d2e
--- /dev/null
+++ b/src/hooks/useLang.ts
@@ -0,0 +1,11 @@
+import { translate } from '../utils/translate';
+import { useProvider } from '../context/provider';
+import { LanguageKey, TranslationKey } from '../constants/locales';
+
+export const useLang = () => {
+ const { value } = useProvider();
+ const lang = value.config.lang as LanguageKey;
+
+ return (key: TranslationKey, vars?: Record
) =>
+ translate(key, lang, vars || {});
+};
diff --git a/src/tailwind.css b/src/tailwind.css
index f4d3ba2..72800c6 100644
--- a/src/tailwind.css
+++ b/src/tailwind.css
@@ -1,4 +1,82 @@
-@import 'tailwindcss' prefix(bluxcc);
+@layer theme, base, components, utilities;
+
+@import 'tailwindcss/theme.css' layer(theme) prefix(bluxcc);
+@import 'tailwindcss/utilities.css' layer(utilities) prefix(bluxcc) important;
+
+@source "../node_modules/@bluxcc/react/dist/**/*.{js,jsx,ts,tsx}";
+
+[class^='bluxcc'],
+[class*=' bluxcc'] {
+ /* Target all prefixed Tailwind elements */
+}
+
+[class^='bluxcc'],
+[class^='bluxcc']::before,
+[class^='bluxcc']::after,
+[class^='bluxcc']::backdrop,
+[class^='bluxcc']::file-selector-button,
+[class*=' bluxcc']::before,
+[class*=' bluxcc']::after,
+[class*=' bluxcc']::backdrop,
+[class*=' bluxcc']::file-selector-button {
+ margin: 0;
+ padding: 0;
+ box-sizing: border-box;
+ border: 0 solid;
+}
+
+[class^='bluxcc'] h1,
+[class^='bluxcc'] h2,
+[class^='bluxcc'] h3,
+[class^='bluxcc'] h4,
+[class^='bluxcc'] h5,
+[class^='bluxcc'] h6,
+[class*=' bluxcc'] h1,
+[class*=' bluxcc'] h2,
+[class*=' bluxcc'] h3,
+[class*=' bluxcc'] h4,
+[class*=' bluxcc'] h5,
+[class*=' bluxcc'] h6 {
+ font-size: inherit;
+ font-weight: inherit;
+}
+
+[class^='bluxcc'] ol,
+[class^='bluxcc'] ul,
+[class^='bluxcc'] menu,
+[class*=' bluxcc'] ol,
+[class*=' bluxcc'] ul,
+[class*=' bluxcc'] menu {
+ list-style: none;
+}
+
+[class^='bluxcc'] img,
+[class^='bluxcc'] svg,
+[class^='bluxcc'] video,
+[class^='bluxcc'] canvas,
+[class^='bluxcc'] audio,
+[class^='bluxcc'] iframe,
+[class^='bluxcc'] embed,
+[class^='bluxcc'] object,
+[class*=' bluxcc'] img,
+[class*=' bluxcc'] svg,
+[class*=' bluxcc'] video,
+[class*=' bluxcc'] canvas,
+[class*=' bluxcc'] audio,
+[class*=' bluxcc'] iframe,
+[class*=' bluxcc'] embed,
+[class*=' bluxcc'] object {
+ display: block;
+ vertical-align: middle;
+}
+
+[class^='bluxcc'] img,
+[class^='bluxcc'] video,
+[class*=' bluxcc'] img,
+[class*=' bluxcc'] video {
+ max-width: 100%;
+ height: auto;
+}
@theme {
--color-primary-50: #e8e8fd;
diff --git a/src/types/index.ts b/src/types/index.ts
index abb363e..743215c 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -3,6 +3,7 @@ import { HorizonApi } from '@stellar/stellar-sdk/lib/horizon';
import { Url } from '../utils/network/url';
import { UseAccountResult } from '../useStellar/useAccount';
+import { LanguageKey } from '../constants/locales';
/**
* Enum representing the supported wallets in the system.
@@ -69,6 +70,7 @@ export interface IProviderConfig {
appearance?: Partial;
transports?: ITransports;
explorer?: IExplorers;
+ lang?: LanguageKey;
showWalletUIs?: boolean;
loginMethods?: Array<
| 'wallet'
diff --git a/src/utils/translate.ts b/src/utils/translate.ts
new file mode 100644
index 0000000..dc9e1ba
--- /dev/null
+++ b/src/utils/translate.ts
@@ -0,0 +1,14 @@
+import translations, { LanguageKey } from '../constants/locales';
+
+const interpolate = (template: string, vars: Record = {}) => {
+ return template.replace(/\$\{(\w+)\}/g, (_, key) => vars[key] || '');
+};
+
+export const translate = (
+ key: keyof typeof translations,
+ lang: LanguageKey,
+ vars: Record = {},
+): string => {
+ const template = translations[key]?.[lang] || translations[key]?.en || '';
+ return interpolate(template, vars);
+};