Skip to content
Open

I18n #104

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 32 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,40 @@
## Dev Workflow

1. Link the `package/walletkit` using `yarn link`
2. In `package/walletkit` run `yarn build` (This will watch the ts files for changes and will also build it)
3. In `package/example` link this walletkit instead of installing it by `npm link @gokiprotocol/walletkit`
4. `yarn run` to get the example started running!
5. DEV

---

## Demo

![walletkit-multilang](https://user-images.githubusercontent.com/22261173/137582726-9e0478dd-3168-4006-b77b-bef67843a5a4.gif)


---

## TODO

1. Get a better fallback UI for suspense
2. Anything more?

---

## To Use

Get the package from the `release` branch. [Here](https://github.com/Aadhinana/walletkit/tree/release)

---

## Source

# walletkit 🔑

[![NPM](https://img.shields.io/npm/v/@gokiprotocol/walletkit)](https://www.npmjs.com/package/@gokiprotocol/walletkit)
[![License](https://img.shields.io/npm/l/@gokiprotocol/walletkit)](/LICENSE)

![Banner](/images/banner.png)

WalletKit is a React library that allows a Solana dApp to display a modal for connecting wallets.

It is intended to be used with [use-solana](https://github.com/saber-hq/saber-common/tree/master/packages/use-solana).
Expand All @@ -14,7 +44,3 @@ It is intended to be used with [use-solana](https://github.com/saber-hq/saber-co
```bash
yarn add @gokiprotocol/walletkit
```

## Usage

Check out the [example app](/packages/example) to understand how to use this library.
46 changes: 46 additions & 0 deletions packages/example/public/locales/hn/translation.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
{
"connect_wallet": "वॉलेट कनेक्ट करें",
"modal": {
"walletStepIntro": {
"instruction": "{{appName}} का उपयोग करने के लिए, आपको एक सोलाना वॉलेट कनेक्ट करना होगा।",
"detailsOne": {
"title": "आप अपने क्रिप्टो को नियंत्रित करते हैं",
"description": "गैर-कस्टोडियल वॉलेट का उपयोग करने से आप तीसरे पक्ष पर भरोसा किए बिना अपने क्रिप्टो को नियंत्रित कर सकते हैं।"
},
"detailsTwo": {
"title": "जल्दी और सस्ते में लेन-देन करें",
"description": "सोलाना की मापनीयता सुनिश्चित करती है कि लेनदेन $0.01 से कम और बिजली की तेज गति से बने रहें।"
}
},
"walletStepSelect": {
"heading": "अपना वॉलेट चुनें",
"showUninstalledWallet": "अनइंस्टॉल किए गए वॉलेट दिखाएं",
"hideUninstalledWallet": "अनइंस्टॉल किए गए वॉलेट छिपाएं"
},
"walletStepConnecting": {
"connecting": {
"header": "कनेक्ट हो रहा है...",
"instructions": "कृपया अपना {{walletName}} वॉलेट अनलॉक करें।"
},
"footer": {
"title": "परेशानी हो रही है?"
}
},
"walletStepRedirect": {
"title": "आपको रीडायरेक्ट किया जा रहा है",
"ix1": "{{infoName}} वॉलेट उपयोग करने के लिए, पहले आपको {{infoName}} वॉलेट इंस्टॉल करना है",
"ix2": "सावधान रहे! ध्यान रखे कि आप केवल आधिकारिक वेबसाइट <strong>({{providerURL}})</strong> से इंस्टॉल करें"
}
},
"buttons": {
"continue": "आगे बड़े",
"goBack": "वापस जाओ",
"refresh": "ताज़ा करना"
},
"footer": {
"title": "पहली बार सोलाना का उपयोग कर रहे हैं?",
"button": "और अधिक जानें",
"finishedInstalling": "हो गया इंस्टॉल?"
},
"changeLanguage": "भाषा बदलें"
}
3 changes: 3 additions & 0 deletions packages/example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ const App: React.FC = () => {
app={{
name: "My App",
}}
locales={{
hn: { nativeName: "Hindi" },
}}
>
<Body />
</WalletKitProvider>
Expand Down
10 changes: 9 additions & 1 deletion packages/walletkit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
],
"repository": "[email protected]:GokiProtocol/walletkit.git",
"scripts": {
"build": "rm -fr dist/ && tsc && tsc -P tsconfig.esm.json"
"build": "rm -fr dist/ && tsc && tsc -P tsconfig.esm.json",
"build:dev": "tsc -w"
},
"bugs": {
"url": "https://github.com/GokiProtocol/walletkit/issues"
Expand All @@ -29,11 +30,18 @@
"react-dom": "^17.0.2"
},
"dependencies": {
"@emotion/react": "^11.4.1",
"@emotion/styled": "^11.3.0",
"@reach/dialog": "^0.16.2",
"@react-spring/web": "^9.3.0",
"@types/react": "^17.0.31",
"i18next": "^21.3.1",
"i18next-browser-languagedetector": "^6.1.2",
"i18next-http-backend": "^1.3.1",
"polished": "^4.1.3",
"react-device-detect": "^2.1.1",
"react-i18next": "^11.12.0",
"react-spring": "^9.2.6",
"react-use-gesture": "^9.1.3",
"tslib": "^2.3.1",
"unstated-next": "^1.1.0"
Expand Down
57 changes: 43 additions & 14 deletions packages/walletkit/src/WalletKitProvider.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
import type { UseSolanaArgs } from "@saberhq/use-solana";
import { SolanaProvider } from "@saberhq/use-solana";
import React, { useContext, useMemo, useState } from "react";
import i18next from "i18next";
import React, {
Suspense,
useContext,
useEffect,
useMemo,
useState,
} from "react";
import { I18nextProvider } from "react-i18next";

import {
ModalStep,
WalletSelectorModal,
} from "./components/WalletSelectorModal";
import type { WalletKitArgs } from "./types";
import { initI18n } from "./i18n";
import type { Locales, WalletKitArgs } from "./types";

export { useConnectedWallet, useSolana, useWallet } from "@saberhq/use-solana";

Expand All @@ -16,13 +25,19 @@ export interface WalletKit {

const WalletKitContext = React.createContext<WalletKit | null>(null);

interface Props extends WalletKitArgs, UseSolanaArgs {
interface Props extends Omit<WalletKitArgs, "locales">, UseSolanaArgs {
additionalLocales?: Locales<string>;
children: React.ReactNode;
}

export const DEFAULT_LOCALES = {
en: { nativeName: "English" },
};

export const WalletKitProvider: React.FC<Props> = ({
children,
app,
additionalLocales,
initialStep = ModalStep.Intro,
...solanaProviderArgs
}: Props) => {
Expand All @@ -32,18 +47,32 @@ export const WalletKitProvider: React.FC<Props> = ({
return { connect: () => setShowWalletSelector(true) };
}, []);

const locales = {
...DEFAULT_LOCALES,
...additionalLocales,
};

useEffect(() => {
void initI18n();
});

return (
<SolanaProvider {...solanaProviderArgs}>
<WalletKitContext.Provider value={kit}>
<WalletSelectorModal
app={app}
initialStep={initialStep}
isOpen={showWalletSelector}
onDismiss={() => setShowWalletSelector(false)}
/>
{children}
</WalletKitContext.Provider>
</SolanaProvider>
<Suspense fallback="loading..">
<I18nextProvider i18n={i18next}>
<SolanaProvider {...solanaProviderArgs}>
<WalletKitContext.Provider value={kit}>
<WalletSelectorModal
app={app}
initialStep={initialStep}
isOpen={showWalletSelector}
onDismiss={() => setShowWalletSelector(false)}
locales={locales}
/>
{children}
</WalletKitContext.Provider>
</SolanaProvider>
</I18nextProvider>
</Suspense>
);
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { css } from "@emotion/react";
import styled from "@emotion/styled";
import lighten from "polished/lib/color/lighten";
import { useTranslation } from "react-i18next";

import { useWalletKit } from "../../WalletKitProvider";

Expand Down Expand Up @@ -56,6 +57,7 @@ export const ConnectWalletButton: React.FC<Props> = ({
...buttonProps
}: Props) => {
const { connect } = useWalletKit();
const { t } = useTranslation();
return (
<Button variant={variant} {...buttonProps} onClick={connect}>
<Logomark
Expand All @@ -64,7 +66,10 @@ export const ConnectWalletButton: React.FC<Props> = ({
width: 16px;
`}
/>
<span>Connect Wallet</span>
<span>
{t("connect_wallet", "Connect Wallet")}
{/* Connect Wallet */}
</span>
</Button>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import styled from "@emotion/styled";
import type { ChangeEventHandler } from "react";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";

import type { LocaleInfo, Locales } from "../../types";

interface Props<L extends string>
extends React.DetailedHTMLProps<
React.ButtonHTMLAttributes<HTMLButtonElement>,
HTMLButtonElement
> {
locales: Locales<L>;
}

export const LanguageToggle = <L extends string>({
locales,
}: Props<L>): React.ReactElement => {
const { t, i18n } = useTranslation();

const [lang, setLang] = useState<string>(i18n.language);

const handleSelectLanguage: ChangeEventHandler<HTMLSelectElement> = (
e: React.ChangeEvent<HTMLSelectElement>
) => {
setLang(e.target.value);
i18n.changeLanguage(e.target.value).catch((e) => console.log(e));
};

return (
<BottomArea>
<label>{t("changeLanguage", "Change Language")}</label>
<select id="language" value={lang} onChange={handleSelectLanguage}>
{Object.entries<LocaleInfo>(locales).map(([locale, info]) => (
<option
key={locale}
value={locale}
style={{
border: "1px solid #dfdfdf",
boxSizing: "border-box",
borderRadius: "4px",
padding: "0 4px",
}}
>
{info.nativeName}
</option>
))}
</select>
</BottomArea>
);
};

export const BottomArea = styled.div`
font-size: 14px;
line-height: 15px;
color: #696969;
margin: 0 10px;

display: flex;
justify-content: space-around;
`;
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import styled from "@emotion/styled";
import { useSolana, WalletType } from "@saberhq/use-solana";
import { useCallback, useEffect, useState } from "react";
import { isMobile } from "react-device-detect";
import { useTranslation } from "react-i18next";

import { BottomArea, FooterText } from "../ButtonWithFooter";
import type { ProviderInfo } from "../WalletStepSelect";
Expand Down Expand Up @@ -30,6 +31,7 @@ export const WalletStepConnecting: React.FC<Props> = ({
);
const { activate, connected, wallet } = useSolana();
const [error, setError] = useState<string | null>(null);
const { t } = useTranslation();

const isManualConnect =
isMobile &&
Expand Down Expand Up @@ -70,7 +72,12 @@ export const WalletStepConnecting: React.FC<Props> = ({
<ConnectingWrapper>
{error ? (
<ConnectingHeader>
<Connecting>Error connecting wallet</Connecting>
<Connecting>
{t(
"modal.walletStepConnecting.error.header",
"Error Connecting Wallet"
)}
</Connecting>
<ConnectingInstructions>{error}</ConnectingInstructions>
<ConnectingInstructions>
<a
Expand All @@ -85,13 +92,18 @@ export const WalletStepConnecting: React.FC<Props> = ({
void doActivate();
}}
>
Retry
{t("buttons.retry", "Retry")}
</a>
</ConnectingInstructions>
</ConnectingHeader>
) : (
<ConnectingHeader>
<Connecting>Connecting...</Connecting>
<Connecting>
{t(
"modal.walletStepConnecting.connecting.header",
"Connecting..."
)}
</Connecting>
{isManualConnect ? (
<ConnectingInstructions>
Please{" "}
Expand All @@ -113,7 +125,11 @@ export const WalletStepConnecting: React.FC<Props> = ({
</ConnectingInstructions>
) : (
<ConnectingInstructions>
Please unlock your {walletProviderInfo.name} wallet.
{t(
"modal.walletStepConnecting.connecting.instructions",
"Please unlock your {{ walletName }} wallet",
{ walletName: walletProviderInfo.name }
)}
</ConnectingInstructions>
)}
</ConnectingHeader>
Expand All @@ -127,7 +143,7 @@ export const WalletStepConnecting: React.FC<Props> = ({
</AppIconsWrapper>
<BottomArea>
<FooterText>
Having trouble?{" "}
{t("modal.walletStepConnecting.footer.title", "Having trouble?")}{" "}
<a
href="#"
onClick={(e) => {
Expand All @@ -136,7 +152,7 @@ export const WalletStepConnecting: React.FC<Props> = ({
onBack?.();
}}
>
Go back
{t("buttons.goBack", "Go Back")}
</a>
</FooterText>
</BottomArea>
Expand Down
Loading