i18n for quick-dapp

pull/5060/head
drafish 5 months ago committed by yann300
parent ed54f645f7
commit c489febfdd
  1. 17
      apps/quick-dapp/src/App.tsx
  2. 6
      apps/quick-dapp/src/components/ContractGUI/index.tsx
  3. 24
      apps/quick-dapp/src/components/CreateInstance/index.tsx
  4. 51
      apps/quick-dapp/src/components/DeployPanel/index.tsx
  5. 3
      apps/quick-dapp/src/components/DeployPanel/theme.tsx
  6. 6
      apps/quick-dapp/src/components/EditInstance/index.tsx
  7. 6
      apps/quick-dapp/src/components/ImageUpload/index.tsx
  8. 6
      apps/quick-dapp/src/components/MultipleContainers/index.tsx
  9. 40
      apps/remix-ide/src/app/tabs/locales/en/quickDapp.json

@ -1,4 +1,5 @@
import React, { useEffect, useReducer } from 'react'; import React, { useEffect, useReducer, useState } from 'react';
import { IntlProvider } from 'react-intl'
import CreateInstance from './components/CreateInstance'; import CreateInstance from './components/CreateInstance';
import EditInstance from './components/EditInstance'; import EditInstance from './components/EditInstance';
import DeployPanel from './components/DeployPanel'; import DeployPanel from './components/DeployPanel';
@ -15,6 +16,10 @@ import remixClient from './remix-client';
import './App.css'; import './App.css';
function App(): JSX.Element { function App(): JSX.Element {
const [locale, setLocale] = useState<{code: string; messages: any}>({
code: 'en',
messages: null,
})
const [appState, dispatch] = useReducer(appReducer, appInitialState); const [appState, dispatch] = useReducer(appReducer, appInitialState);
useEffect(() => { useEffect(() => {
updateState(appState); updateState(appState);
@ -29,6 +34,14 @@ function App(): JSX.Element {
remixClient.on('theme', 'themeChanged', (theme: any) => { remixClient.on('theme', 'themeChanged', (theme: any) => {
selectTheme(theme.name); selectTheme(theme.name);
}); });
// @ts-ignore
remixClient.call('locale', 'currentLocale').then((locale: any) => {
setLocale(locale)
})
// @ts-ignore
remixClient.on('locale', 'localeChanged', (locale: any) => {
setLocale(locale)
})
}); });
}, []); }, []);
return ( return (
@ -38,6 +51,7 @@ function App(): JSX.Element {
appState, appState,
}} }}
> >
<IntlProvider locale={locale.code} messages={locale.messages}>
{Object.keys(appState.instance.abi).length > 0 ? ( {Object.keys(appState.instance.abi).length > 0 ? (
<div className="row m-0 pt-3"> <div className="row m-0 pt-3">
<EditInstance /> <EditInstance />
@ -49,6 +63,7 @@ function App(): JSX.Element {
</div> </div>
)} )}
<LoadingScreen /> <LoadingScreen />
</IntlProvider>
</AppContext.Provider> </AppContext.Provider>
); );
} }

@ -1,4 +1,5 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { useIntl } from 'react-intl';
import { execution } from '@remix-project/remix-lib'; import { execution } from '@remix-project/remix-lib';
import { saveDetails, saveTitle } from '../../actions'; import { saveDetails, saveTitle } from '../../actions';
@ -12,6 +13,7 @@ const getFuncABIInputs = (funABI: any) => {
}; };
export function ContractGUI(props: { funcABI: any }) { export function ContractGUI(props: { funcABI: any }) {
const intl = useIntl()
const isConstant = const isConstant =
props.funcABI.constant !== undefined ? props.funcABI.constant : false; props.funcABI.constant !== undefined ? props.funcABI.constant : false;
const lookupOnly = const lookupOnly =
@ -68,7 +70,7 @@ export function ContractGUI(props: { funcABI: any }) {
<div className="p-2"> <div className="p-2">
<input <input
className="form-control" className="form-control"
placeholder="Title of function" placeholder={intl.formatMessage({ id: 'quickDapp.functionTitle' })}
value={props.funcABI.title} value={props.funcABI.title}
onChange={({ target: { value } }) => { onChange={({ target: { value } }) => {
saveTitle({ id: props.funcABI.id, title: value }); saveTitle({ id: props.funcABI.id, title: value });
@ -116,7 +118,7 @@ export function ContractGUI(props: { funcABI: any }) {
<div className="p-2"> <div className="p-2">
<textarea <textarea
className="form-control" className="form-control"
placeholder="Instructions for function" placeholder={intl.formatMessage({ id: 'quickDapp.functionInstructions' })}
value={props.funcABI.details} value={props.funcABI.details}
onChange={({ target: { value } }) => { onChange={({ target: { value } }) => {
saveDetails({ id: props.funcABI.id, details: value }); saveDetails({ id: props.funcABI.id, details: value });

@ -1,8 +1,10 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Alert, Button, Form } from 'react-bootstrap'; import { Alert, Button, Form } from 'react-bootstrap';
import { FormattedMessage, useIntl } from 'react-intl';
import { initInstance } from '../../actions'; import { initInstance } from '../../actions';
const CreateInstance: React.FC = () => { const CreateInstance: React.FC = () => {
const intl = useIntl()
const [formVal, setFormVal] = useState({ const [formVal, setFormVal] = useState({
address: '', address: '',
abi: [], abi: [],
@ -18,10 +20,10 @@ const CreateInstance: React.FC = () => {
}} }}
> >
<Form.Group className="mb-2" controlId="formAddress"> <Form.Group className="mb-2" controlId="formAddress">
<Form.Label className="text-uppercase mb-0">address</Form.Label> <Form.Label className="text-uppercase mb-0"><FormattedMessage id="quickDapp.address" /></Form.Label>
<Form.Control <Form.Control
type="address" type="address"
placeholder="Enter address" placeholder={intl.formatMessage({ id: 'quickDapp.enterAddress' })}
value={formVal.address} value={formVal.address}
onChange={(e) => { onChange={(e) => {
setFormVal({ ...formVal, address: e.target.value }); setFormVal({ ...formVal, address: e.target.value });
@ -35,7 +37,7 @@ const CreateInstance: React.FC = () => {
as="textarea" as="textarea"
rows={3} rows={3}
type="abi" type="abi"
placeholder="Enter abi" placeholder={intl.formatMessage({ id: 'quickDapp.enterAbi' })}
value={formVal.abi.length > 0 ? JSON.stringify(formVal.abi) : ''} value={formVal.abi.length > 0 ? JSON.stringify(formVal.abi) : ''}
onChange={(e) => { onChange={(e) => {
let abi = []; let abi = [];
@ -50,10 +52,10 @@ const CreateInstance: React.FC = () => {
</Form.Group> </Form.Group>
<Form.Group className="mb-2" controlId="formName"> <Form.Group className="mb-2" controlId="formName">
<Form.Label className="text-uppercase mb-0">name</Form.Label> <Form.Label className="text-uppercase mb-0"><FormattedMessage id="quickDapp.name" /></Form.Label>
<Form.Control <Form.Control
type="name" type="name"
placeholder="Enter name" placeholder={intl.formatMessage({ id: 'quickDapp.enterName' })}
value={formVal.name} value={formVal.name}
onChange={(e) => { onChange={(e) => {
setFormVal({ ...formVal, name: e.target.value }); setFormVal({ ...formVal, name: e.target.value });
@ -62,10 +64,10 @@ const CreateInstance: React.FC = () => {
</Form.Group> </Form.Group>
<Form.Group className="mb-2" controlId="formNetwork"> <Form.Group className="mb-2" controlId="formNetwork">
<Form.Label className="text-uppercase mb-0">network</Form.Label> <Form.Label className="text-uppercase mb-0"><FormattedMessage id="quickDapp.network" /></Form.Label>
<Form.Control <Form.Control
type="network" type="network"
placeholder="Enter network" placeholder={intl.formatMessage({ id: 'quickDapp.enterNetwork' })}
value={formVal.network} value={formVal.network}
onChange={(e) => { onChange={(e) => {
setFormVal({ ...formVal, network: e.target.value }); setFormVal({ ...formVal, network: e.target.value });
@ -83,14 +85,12 @@ const CreateInstance: React.FC = () => {
!formVal.abi.length !formVal.abi.length
} }
> >
Submit <FormattedMessage id="quickDapp.submit" />
</Button> </Button>
<Alert className="mt-4" variant="info"> <Alert className="mt-4" variant="info">
Dapp Draft only work for Injected Provider currently. More providers <FormattedMessage id="quickDapp.text1" />
will be adapted in further iterations.
<br /> <br />
Click the edit icon in a deployed contract will input the parameters <FormattedMessage id="quickDapp.text2" />
automatically.
</Alert> </Alert>
<img src='./assets/edit-dapp.png' /> <img src='./assets/edit-dapp.png' />
</Form> </Form>

@ -1,5 +1,6 @@
import React, { useContext, useState } from 'react'; import React, { useContext, useState } from 'react';
import { Form, Button, Alert, InputGroup } from 'react-bootstrap'; import { Form, Button, Alert, InputGroup } from 'react-bootstrap';
import { FormattedMessage, useIntl } from 'react-intl';
import { import {
deploy, deploy,
emptyInstance, emptyInstance,
@ -11,6 +12,7 @@ import { CustomTooltip } from '@remix-ui/helper';
import { AppContext } from '../../contexts'; import { AppContext } from '../../contexts';
function DeployPanel(): JSX.Element { function DeployPanel(): JSX.Element {
const intl = useIntl()
const { appState, dispatch } = useContext(AppContext); const { appState, dispatch } = useContext(AppContext);
const { verified, natSpec, noTerminal } = appState.instance; const { verified, natSpec, noTerminal } = appState.instance;
const [formVal, setFormVal] = useState<any>({ const [formVal, setFormVal] = useState<any>({
@ -36,13 +38,13 @@ function DeployPanel(): JSX.Element {
}); });
return ( return (
<div className="col-3 d-inline-block"> <div className="col-3 d-inline-block">
<h3 className="mb-3">QuickDapp Admin</h3> <h3 className="mb-3">QuickDapp <FormattedMessage id="quickDapp.admin" /></h3>
<Button <Button
onClick={() => { onClick={() => {
resetInstance(); resetInstance();
}} }}
> >
Reset Functions <FormattedMessage id="quickDapp.resetFunctions" />
</Button> </Button>
<Button <Button
className="ml-3" className="ml-3"
@ -50,16 +52,19 @@ function DeployPanel(): JSX.Element {
emptyInstance(); emptyInstance();
}} }}
> >
Delete Dapp <FormattedMessage id="quickDapp.deleteDapp" />
</Button> </Button>
<Alert variant="info" className="my-2"> <Alert variant="info" className="my-2">
QuickDapp deploys to Surge.sh. Surge accounts are free until you reach a <FormattedMessage
level of use. The email & password you input below will register you id="quickDapp.text3"
with a Surge account. The subdomain is your choice but it must be values={{
unique. More about{' '} a: (chunks) => (
<a target="_blank" href="https://surge.sh/help/"> <a target="_blank" href="https://surge.sh/help/">
surge.sh {chunks}
</a> </a>
),
}}
/>
</Alert> </Alert>
<Form <Form
onSubmit={(e) => { onSubmit={(e) => {
@ -71,10 +76,10 @@ function DeployPanel(): JSX.Element {
}} }}
> >
<Form.Group className="mb-2" controlId="formEmail"> <Form.Group className="mb-2" controlId="formEmail">
<Form.Label className="text-uppercase mb-0">Email</Form.Label> <Form.Label className="text-uppercase mb-0"><FormattedMessage id="quickDapp.email" /></Form.Label>
<Form.Control <Form.Control
type="email" type="email"
placeholder="Surge email" placeholder={intl.formatMessage({ id: 'quickDapp.surgeEmail' })}
required required
value={formVal.email} value={formVal.email}
onChange={(e) => { onChange={(e) => {
@ -83,10 +88,10 @@ function DeployPanel(): JSX.Element {
/> />
</Form.Group> </Form.Group>
<Form.Group className="mb-2" controlId="formPassword"> <Form.Group className="mb-2" controlId="formPassword">
<Form.Label className="text-uppercase mb-0">Password</Form.Label> <Form.Label className="text-uppercase mb-0"><FormattedMessage id="quickDapp.password" /></Form.Label>
<Form.Control <Form.Control
type="password" type="password"
placeholder="Surge password" placeholder={intl.formatMessage({ id: 'quickDapp.surgePassword' })}
required required
value={formVal.password} value={formVal.password}
onChange={(e) => { onChange={(e) => {
@ -95,12 +100,12 @@ function DeployPanel(): JSX.Element {
/> />
</Form.Group> </Form.Group>
<Form.Group className="mb-2" controlId="formPassword"> <Form.Group className="mb-2" controlId="formPassword">
<Form.Label className="text-uppercase mb-0">Subdomain</Form.Label> <Form.Label className="text-uppercase mb-0"><FormattedMessage id="quickDapp.subdomain" /></Form.Label>
<InputGroup> <InputGroup>
<InputGroup.Text>https://</InputGroup.Text> <InputGroup.Text>https://</InputGroup.Text>
<Form.Control <Form.Control
type="subdomain" type="subdomain"
placeholder="Unique subdomain name" placeholder={intl.formatMessage({ id: 'quickDapp.uniqueSubdomain' })}
required required
value={formVal.subdomain} value={formVal.subdomain}
onChange={(e) => { onChange={(e) => {
@ -123,7 +128,7 @@ function DeployPanel(): JSX.Element {
</Form.Group> */} </Form.Group> */}
<Form.Group className="mb-2" controlId="formShareTo"> <Form.Group className="mb-2" controlId="formShareTo">
<Form.Label className="text-uppercase mb-0"> <Form.Label className="text-uppercase mb-0">
Share To (Optional) <FormattedMessage id="quickDapp.shareTo" />
</Form.Label> </Form.Label>
<br /> <br />
<div className="d-inline-flex align-items-center custom-control custom-checkbox"> <div className="d-inline-flex align-items-center custom-control custom-checkbox">
@ -171,7 +176,7 @@ function DeployPanel(): JSX.Element {
</Form.Group> </Form.Group>
<Form.Group className="mb-2" controlId="formShareTo"> <Form.Group className="mb-2" controlId="formShareTo">
<Form.Label className="text-uppercase mb-0"> <Form.Label className="text-uppercase mb-0">
Use NatSpec (Optional) <FormattedMessage id="quickDapp.useNatSpec" />
</Form.Label> </Form.Label>
<br /> <br />
<span <span
@ -184,7 +189,7 @@ function DeployPanel(): JSX.Element {
> >
<CustomTooltip <CustomTooltip
placement="top" placement="top"
tooltipText="Retrieve info from the contract's NatSpec" tooltipText={intl.formatMessage({ id: 'quickDapp.useNatSpecTooltip' })}
> >
<i <i
className={ className={
@ -198,7 +203,7 @@ function DeployPanel(): JSX.Element {
</Form.Group> </Form.Group>
<Form.Group className="mb-2" controlId="formVerified"> <Form.Group className="mb-2" controlId="formVerified">
<Form.Label className="text-uppercase mb-0"> <Form.Label className="text-uppercase mb-0">
Verified by Etherscan (Optional) <FormattedMessage id="quickDapp.verifiedByEtherscan" />
</Form.Label> </Form.Label>
<div className="d-flex py-1 align-items-center custom-control custom-checkbox"> <div className="d-flex py-1 align-items-center custom-control custom-checkbox">
<input <input
@ -219,13 +224,13 @@ function DeployPanel(): JSX.Element {
className="m-0 form-check-label custom-control-label" className="m-0 form-check-label custom-control-label"
style={{ paddingTop: 1 }} style={{ paddingTop: 1 }}
> >
Verified <FormattedMessage id="quickDapp.verified" />
</label> </label>
</div> </div>
</Form.Group> </Form.Group>
<Form.Group className="mb-2" controlId="formNoTerminal"> <Form.Group className="mb-2" controlId="formNoTerminal">
<Form.Label className="text-uppercase mb-0"> <Form.Label className="text-uppercase mb-0">
No Terminal (Optional) <FormattedMessage id="quickDapp.noTerminal" />
</Form.Label> </Form.Label>
<div className="d-flex py-1 align-items-center custom-control custom-checkbox"> <div className="d-flex py-1 align-items-center custom-control custom-checkbox">
<input <input
@ -246,7 +251,7 @@ function DeployPanel(): JSX.Element {
className="m-0 form-check-label custom-control-label" className="m-0 form-check-label custom-control-label"
style={{ paddingTop: 1 }} style={{ paddingTop: 1 }}
> >
No Terminal <FormattedMessage id="quickDapp.no" />
</label> </label>
</div> </div>
</Form.Group> </Form.Group>
@ -260,11 +265,11 @@ function DeployPanel(): JSX.Element {
{deployState.loading && ( {deployState.loading && (
<i className="fas fa-spinner fa-spin mr-1"></i> <i className="fas fa-spinner fa-spin mr-1"></i>
)} )}
Deploy <FormattedMessage id="quickDapp.deploy" />
</Button> </Button>
{deployState.code === 'SUCCESS' && ( {deployState.code === 'SUCCESS' && (
<Alert variant="success" className="mt-4"> <Alert variant="success" className="mt-4">
Deployed successfully! <br /> Click the link below to view your dapp <FormattedMessage id="quickDapp.text4" /> <br /> <FormattedMessage id="quickDapp.text5" />
<br /> <br />
<a <a
target="_blank" target="_blank"

@ -1,4 +1,5 @@
import { Ref, useContext, useEffect } from 'react'; import { Ref, useContext, useEffect } from 'react';
import { FormattedMessage } from 'react-intl';
import { AppContext } from '../../contexts'; import { AppContext } from '../../contexts';
import { selectTheme } from '../../actions'; import { selectTheme } from '../../actions';
import { Dropdown } from 'react-bootstrap'; import { Dropdown } from 'react-bootstrap';
@ -121,7 +122,7 @@ export function ThemeUI() {
return ( return (
<div className="d-block"> <div className="d-block">
<label className="text-uppercase mb-0">Themes</label> <label className="text-uppercase mb-0"><FormattedMessage id="quickDapp.themes" /></label>
<Dropdown className="w-100"> <Dropdown className="w-100">
<Dropdown.Toggle <Dropdown.Toggle
as={CustomToggle} as={CustomToggle}

@ -1,10 +1,12 @@
import { useContext } from 'react'; import { useContext } from 'react';
import { omitBy } from 'lodash'; import { omitBy } from 'lodash';
import { useIntl } from 'react-intl';
import { MultipleContainers } from '../MultipleContainers'; import { MultipleContainers } from '../MultipleContainers';
import { AppContext } from '../../contexts'; import { AppContext } from '../../contexts';
import ImageUpload from '../ImageUpload' import ImageUpload from '../ImageUpload'
function EditInstance(): JSX.Element { function EditInstance(): JSX.Element {
const intl = useIntl()
const { appState, dispatch } = useContext(AppContext); const { appState, dispatch } = useContext(AppContext);
const { abi, items, containers, title, details, userInput, natSpec } = const { abi, items, containers, title, details, userInput, natSpec } =
appState.instance; appState.instance;
@ -16,7 +18,7 @@ function EditInstance(): JSX.Element {
<div className="my-2 p-3 bg-light"> <div className="my-2 p-3 bg-light">
<input <input
className="form-control" className="form-control"
placeholder="Dapp title" placeholder={intl.formatMessage({ id: 'quickDapp.dappTitle' })}
value={title} value={title}
onChange={({ target: { value } }) => { onChange={({ target: { value } }) => {
dispatch({ dispatch({
@ -35,7 +37,7 @@ function EditInstance(): JSX.Element {
<div className="my-2 p-3 bg-light"> <div className="my-2 p-3 bg-light">
<textarea <textarea
className="form-control" className="form-control"
placeholder="Dapp instructions" placeholder={intl.formatMessage({ id: 'quickDapp.dappInstructions' })}
value={details} value={details}
onChange={({ target: { value } }) => { onChange={({ target: { value } }) => {
dispatch({ dispatch({

@ -1,8 +1,10 @@
import React, { useContext, useEffect, useState } from 'react' import React, { useContext, useEffect, useState } from 'react'
import { useIntl } from 'react-intl';
import { CustomTooltip } from '@remix-ui/helper'; import { CustomTooltip } from '@remix-ui/helper';
import { AppContext } from '../../contexts' import { AppContext } from '../../contexts'
const ImageUpload = () => { const ImageUpload = () => {
const intl = useIntl()
const { appState, dispatch } = useContext(AppContext) const { appState, dispatch } = useContext(AppContext)
const { logo } = appState.instance const { logo } = appState.instance
const [preview, setPreview] = useState(null) const [preview, setPreview] = useState(null)
@ -31,9 +33,9 @@ const ImageUpload = () => {
<input className="d-none" type="file" accept="image/*" onChange={handleImageChange} id="upload-button" /> <input className="d-none" type="file" accept="image/*" onChange={handleImageChange} id="upload-button" />
<CustomTooltip <CustomTooltip
placement="right" placement="right"
tooltipText="Click here to change logo" tooltipText={intl.formatMessage({ id: 'quickDapp.uploadLogoTooltip' })}
> >
<label htmlFor="upload-button" className="cursor_pointer d-flex justify-content-center align-items-center position-relative" style={{height: 170}}> <label htmlFor="upload-button" className="cursor_pointer d-flex justify-content-center align-items-center position-relative" style={{ height: 170 }}>
{logo ? ( {logo ? (
<img src={preview} alt="preview" style={{ width: 120, height: 120 }} /> <img src={preview} alt="preview" style={{ width: 120, height: 120 }} />
) : ( ) : (

@ -1,5 +1,6 @@
import React, { useCallback, useEffect, useRef, useState } from 'react'; import React, { useCallback, useEffect, useRef, useState } from 'react';
import { createPortal, unstable_batchedUpdates } from 'react-dom'; import { createPortal, unstable_batchedUpdates } from 'react-dom';
import { FormattedMessage, useIntl } from 'react-intl';
import { import {
CancelDrop, CancelDrop,
closestCenter, closestCenter,
@ -173,6 +174,7 @@ export function MultipleContainers({
vertical = false, vertical = false,
scrollable, scrollable,
}: Props) { }: Props) {
const intl = useIntl()
const [activeId, setActiveId] = useState<UniqueIdentifier | null>(null); const [activeId, setActiveId] = useState<UniqueIdentifier | null>(null);
const lastOverId = useRef<UniqueIdentifier | null>(null); const lastOverId = useRef<UniqueIdentifier | null>(null);
const recentlyMovedToNewContainer = useRef(false); const recentlyMovedToNewContainer = useRef(false);
@ -442,7 +444,7 @@ export function MultipleContainers({
<DroppableContainer <DroppableContainer
key={containerId} key={containerId}
id={containerId} id={containerId}
label={`Column ${containerId}`} label={`${intl.formatMessage({ id: 'quickDapp.column' })} ${containerId}`}
columns={columns} columns={columns}
items={items[containerId]} items={items[containerId]}
style={containerStyle} style={containerStyle}
@ -485,7 +487,7 @@ export function MultipleContainers({
onClick={handleAddColumn} onClick={handleAddColumn}
placeholder placeholder
> >
+ Add column + <FormattedMessage id='quickDapp.addColumn' />
</DroppableContainer> </DroppableContainer>
)} )}
</SortableContext> </SortableContext>

@ -0,0 +1,40 @@
{
"quickDapp.address": "address",
"quickDapp.enterAddress": "Enter address",
"quickDapp.enterAbi": "Enter abi",
"quickDapp.name": "name",
"quickDapp.enterName": "Enter name",
"quickDapp.network": "network",
"quickDapp.enterNetwork": "Enter network",
"quickDapp.submit": "Submit",
"quickDapp.text1": "QuickDapp only work for Injected Provider currently. More providers will be adapted in further iterations.",
"quickDapp.text2": "Click the edit icon in a deployed contract will input the parameters automatically.",
"quickDapp.admin": "Admin",
"quickDapp.resetFunctions": "Reset Functions",
"quickDapp.deleteDapp": "Delete Dapp",
"quickDapp.text3": "QuickDapp deploys to Surge.sh. Surge accounts are free until you reach a level of use. The email & password you input below will register you with a Surge account. The subdomain is your choice but it must be unique. More about <a>surge.sh</a>",
"quickDapp.email": "Email",
"quickDapp.surgeEmail": "Surge email",
"quickDapp.password": "Password",
"quickDapp.surgePassword": "Surge password",
"quickDapp.subdomain": "Subdomain",
"quickDapp.uniqueSubdomain": "Unique subdomain name",
"quickDapp.shareTo": "Share To (Optional)",
"quickDapp.useNatSpec": "Use NatSpec (Optional)",
"quickDapp.useNatSpecTooltip": "Retrieve info from the contract's NatSpec",
"quickDapp.verifiedByEtherscan": "Verified by Etherscan (Optional)",
"quickDapp.verified": "Verified",
"quickDapp.noTerminal": "No Terminal (Optional)",
"quickDapp.no": "No",
"quickDapp.themes": "Themes",
"quickDapp.deploy": "Deploy",
"quickDapp.text4": "Deployed successfully!",
"quickDapp.text5": "Click the link below to view your dapp",
"quickDapp.uploadLogoTooltip": "Click here to change logo",
"quickDapp.dappTitle": "Dapp Title",
"quickDapp.dappInstructions": "Dapp Instructions",
"quickDapp.functionTitle": "Title of function",
"quickDapp.functionInstructions": "Instructions for function",
"quickDapp.addColumn": "Add column",
"quickDapp.column": "Column"
}
Loading…
Cancel
Save