Swap to actual react-i18next (#431)
* Swap to actual react-i18next * Update i18n creation
This commit is contained in:
parent
fddb842085
commit
206c0b4d85
@ -13,9 +13,12 @@
|
||||
"@polkadot/react-qr": "^0.59.0-beta.0",
|
||||
"@polkadot/util": "^3.4.1",
|
||||
"@polkadot/util-crypto": "^3.4.1",
|
||||
"i18next": "^19.7.0",
|
||||
"i18next-browser-languagedetector": "^5.0.1",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-dropzone": "^11.0.3",
|
||||
"react-i18next": "^11.7.2",
|
||||
"react-is": "^16.13.1",
|
||||
"react-router": "^5.2.0",
|
||||
"react-router-dom": "^5.2.0",
|
||||
|
||||
@ -69,14 +69,14 @@ function Account ({ address, className, genesisHash, isExternal, isHidden, paren
|
||||
className='menuItem'
|
||||
onClick={_toggleEdit}
|
||||
>
|
||||
{t('Rename')}
|
||||
{t<string>('Rename')}
|
||||
</Link>
|
||||
{!isExternal && (
|
||||
<Link
|
||||
className='menuItem'
|
||||
to={`/account/derive/${address}/locked`}
|
||||
>
|
||||
{t('Derive New Account')}
|
||||
{t<string>('Derive New Account')}
|
||||
</Link>
|
||||
)}
|
||||
<MenuDivider />
|
||||
@ -86,7 +86,7 @@ function Account ({ address, className, genesisHash, isExternal, isHidden, paren
|
||||
isDanger
|
||||
to={`/account/export/${address}`}
|
||||
>
|
||||
{t('Export Account')}
|
||||
{t<string>('Export Account')}
|
||||
</Link>
|
||||
)}
|
||||
<Link
|
||||
@ -94,14 +94,14 @@ function Account ({ address, className, genesisHash, isExternal, isHidden, paren
|
||||
isDanger
|
||||
to={`/account/forget/${address}`}
|
||||
>
|
||||
{t('Forget Account')}
|
||||
{t<string>('Forget Account')}
|
||||
</Link>
|
||||
<MenuDivider />
|
||||
<div className='menuItem'>
|
||||
<Checkbox
|
||||
checked={!isHidden}
|
||||
className='inputItem'
|
||||
label={t('Visible (always inject)')}
|
||||
label={t<string>('Visible (always inject)')}
|
||||
onClick={_toggleVisibility}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -36,7 +36,7 @@ function AddAccount ({ className }: Props): React.ReactElement<Props> {
|
||||
<AddAccountImage onClick={_onClick}/>
|
||||
</div>
|
||||
<div className='no-accounts'>
|
||||
<p>{t("You currently don't have any accounts. Create your first account to get started.")}</p>
|
||||
<p>{t<string>("You currently don't have any accounts. Create your first account to get started.")}</p>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@ -24,7 +24,7 @@ export default function Accounts (): React.ReactElement {
|
||||
<Header
|
||||
showAdd
|
||||
showSettings
|
||||
text={t('Accounts')}
|
||||
text={t<string>('Accounts')}
|
||||
/>
|
||||
<AccountsArea>
|
||||
{hierarchy.map((json, index): React.ReactNode => (
|
||||
|
||||
@ -6,6 +6,7 @@ import { RequestAuthorizeTab } from '@polkadot/extension-base/background/types';
|
||||
import { ThemeProps } from '../../types';
|
||||
|
||||
import React, { useCallback, useContext } from 'react';
|
||||
import { Trans } from 'react-i18next';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { ActionBar, ActionContext, Button, Icon, Link, Warning } from '../../components';
|
||||
@ -38,7 +39,6 @@ function Request ({ authId, className, isFirst, request: { origin }, url }: Prop
|
||||
[authId, onAction]
|
||||
);
|
||||
|
||||
// FIXME i18next <Trans /> component to be used here
|
||||
return (
|
||||
<div className={className}>
|
||||
<RequestInfo>
|
||||
@ -48,20 +48,21 @@ function Request ({ authId, className, isFirst, request: { origin }, url }: Prop
|
||||
onClick={_onReject}
|
||||
/>
|
||||
<div className='tab-info'>
|
||||
An application, self-identifying as <span className='tab-name'>{origin}</span> is requesting access from{' '}
|
||||
<a
|
||||
href={url}
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
>
|
||||
<span className='tab-url'>{url}</span>
|
||||
</a>.
|
||||
<Trans key='accessRequest'>An application, self-identifying as <span className='tab-name'>{origin}</span> is requesting access from{' '}
|
||||
<a
|
||||
href={url}
|
||||
rel='noopener noreferrer'
|
||||
target='_blank'
|
||||
>
|
||||
<span className='tab-url'>{url}</span>
|
||||
</a>.
|
||||
</Trans>
|
||||
</div>
|
||||
</Info>
|
||||
{isFirst && (
|
||||
<>
|
||||
<RequestWarning>{t('Only approve this request if you trust the application. Approving gives the application access to the addresses of your accounts.')}</RequestWarning>
|
||||
<AcceptButton onClick={_onApprove}>{t('Yes, allow this application access')}</AcceptButton>
|
||||
<RequestWarning>{t<string>('Only approve this request if you trust the application. Approving gives the application access to the addresses of your accounts.')}</RequestWarning>
|
||||
<AcceptButton onClick={_onApprove}>{t<string>('Yes, allow this application access')}</AcceptButton>
|
||||
</>
|
||||
)}
|
||||
<RejectButton>
|
||||
|
||||
@ -17,7 +17,7 @@ export default function Authorize (): React.ReactElement {
|
||||
return (
|
||||
<>
|
||||
<Scroll isLastRequest={requests.length === 1}>
|
||||
<Header text={t('Authorize')} />
|
||||
<Header text={t<string>('Authorize')} />
|
||||
{requests.map(({ id, request, url }, index): React.ReactNode => (
|
||||
<Request
|
||||
authId={id}
|
||||
|
||||
@ -41,7 +41,7 @@ function AccountName ({ isBusy, onBackClick, onCreate }: Props): React.ReactElem
|
||||
isDisabled={!password || !name}
|
||||
onClick={_onCreate}
|
||||
>
|
||||
{t('Add the account with the generated seed')}
|
||||
{t<string>('Add the account with the generated seed')}
|
||||
</NextStepButton>
|
||||
</ButtonArea>
|
||||
</>
|
||||
|
||||
@ -40,11 +40,11 @@ function Mnemonic ({ onNextStep, seed }: Props): React.ReactElement<Props> {
|
||||
onCopy={_onCopy}
|
||||
seed={seed}
|
||||
/>
|
||||
<Warning>{t("Please write down your wallet's mnemonic seed and keep it in a safe place. The mnemonic can be used to restore your wallet. Keep it carefully to not lose your assets.")}</Warning>
|
||||
<Warning>{t<string>("Please write down your wallet's mnemonic seed and keep it in a safe place. The mnemonic can be used to restore your wallet. Keep it carefully to not lose your assets.")}</Warning>
|
||||
<VerticalSpace />
|
||||
<Checkbox
|
||||
checked={isMnemonicSaved}
|
||||
label={t('I have saved my mnemonic seed safely.')}
|
||||
label={t<string>('I have saved my mnemonic seed safely.')}
|
||||
onChange={setIsMnemonicSaved}
|
||||
/>
|
||||
<ButtonArea>
|
||||
@ -52,7 +52,7 @@ function Mnemonic ({ onNextStep, seed }: Props): React.ReactElement<Props> {
|
||||
isDisabled={!isMnemonicSaved}
|
||||
onClick={onNextStep}
|
||||
>
|
||||
{t('Next step')}
|
||||
{t<string>('Next step')}
|
||||
</NextStepButton>
|
||||
</ButtonArea>
|
||||
</>
|
||||
|
||||
@ -49,7 +49,7 @@ export default function CreateAccount (): React.ReactElement {
|
||||
<>
|
||||
<HeaderWithSteps
|
||||
step={step}
|
||||
text={t('Create an account')}
|
||||
text={t<string>('Create an account')}
|
||||
/>
|
||||
<Loading>
|
||||
<div>
|
||||
|
||||
@ -47,7 +47,7 @@ function DerivationPath ({ className, defaultPath, isError, onChange }: Props):
|
||||
: t('Derivation Path (unlock to edit)')
|
||||
}
|
||||
onChange={_onChange}
|
||||
placeholder={t('//hard/soft')}
|
||||
placeholder={t<string>('//hard/soft')}
|
||||
value={path}
|
||||
/>
|
||||
</PathInput>
|
||||
|
||||
@ -95,7 +95,7 @@ export function SelectParent ({ isLocked, onDerivationConfirmed, parentAddress,
|
||||
{!isLocked && (
|
||||
<CheckboxWithSmallerMargins
|
||||
checked={shouldAccountBeDerived}
|
||||
label={t('Derive new account from existing')}
|
||||
label={t<string>('Derive new account from existing')}
|
||||
onChange={setShouldAccountBeDerived}
|
||||
/>
|
||||
)}
|
||||
@ -108,7 +108,7 @@ export function SelectParent ({ isLocked, onDerivationConfirmed, parentAddress,
|
||||
/>
|
||||
)
|
||||
: (
|
||||
<Label label={t('Choose Parent Account:')}>
|
||||
<Label label={t<string>('Choose Parent Account:')}>
|
||||
<AddressDropdown
|
||||
allAddresses={allAddresses}
|
||||
onSelect={_onParentChange}
|
||||
@ -123,7 +123,7 @@ export function SelectParent ({ isLocked, onDerivationConfirmed, parentAddress,
|
||||
data-export-password
|
||||
isError={!isProperParentPassword}
|
||||
isFocused
|
||||
label={t('enter the password for the account you want to derive from')}
|
||||
label={t<string>('enter the password for the account you want to derive from')}
|
||||
onChange={_onParentPasswordEnter}
|
||||
type='password'
|
||||
value={parentPassword}
|
||||
@ -148,7 +148,7 @@ export function SelectParent ({ isLocked, onDerivationConfirmed, parentAddress,
|
||||
isDisabled={!isProperParentPassword || !suriPath}
|
||||
onClick={_onSubmit}
|
||||
>
|
||||
{t('Create a derived account')}
|
||||
{t<string>('Create a derived account')}
|
||||
</NextStepButton>
|
||||
)
|
||||
: (
|
||||
@ -156,7 +156,7 @@ export function SelectParent ({ isLocked, onDerivationConfirmed, parentAddress,
|
||||
data-button-action='create root account'
|
||||
onClick={_goCreate}
|
||||
>
|
||||
{t('Create account from new seed')}
|
||||
{t<string>('Create account from new seed')}
|
||||
</NextStepButton>
|
||||
)
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@ function Derive ({ isLocked }: Props): React.ReactElement<Props> {
|
||||
<>
|
||||
<HeaderWithSteps
|
||||
step={account ? 2 : 1}
|
||||
text={t('Add new account')}
|
||||
text={t<string>('Add new account')}
|
||||
/>
|
||||
{!account && (
|
||||
<SelectParent
|
||||
@ -103,7 +103,7 @@ function Derive ({ isLocked }: Props): React.ReactElement<Props> {
|
||||
isDisabled={!password}
|
||||
onClick={_onCreate}
|
||||
>
|
||||
{t('Create derived account')}
|
||||
{t<string>('Create derived account')}
|
||||
</NextStepButton>
|
||||
</ButtonArea>
|
||||
</>
|
||||
|
||||
@ -57,17 +57,17 @@ function Export ({ match: { params: { address } } }: Props): React.ReactElement<
|
||||
<>
|
||||
<Header
|
||||
showBackArrow
|
||||
text={t('Export account')}
|
||||
text={t<string>('Export account')}
|
||||
/>
|
||||
<div>
|
||||
<Address address={address}>
|
||||
<MovedWarning danger>{t("You are exporting your account. Keep it safe and don't share it with anyone.")}</MovedWarning>
|
||||
<MovedWarning danger>{t<string>("You are exporting your account. Keep it safe and don't share it with anyone.")}</MovedWarning>
|
||||
<ActionArea>
|
||||
<InputWithLabel
|
||||
data-export-password
|
||||
disabled={isBusy}
|
||||
isError={pass.length < MIN_LENGTH || wrongPasswordHighlight}
|
||||
label={t('password for this account')}
|
||||
label={t<string>('password for this account')}
|
||||
onChange={setPass}
|
||||
type='password'
|
||||
/>
|
||||
@ -79,12 +79,12 @@ function Export ({ match: { params: { address } } }: Props): React.ReactElement<
|
||||
isDisabled={pass.length === 0}
|
||||
onClick={_onExportButtonClick}
|
||||
>
|
||||
{t('I want to export this account')}
|
||||
{t<string>('I want to export this account')}
|
||||
</Button>
|
||||
<CancelButton>
|
||||
<ActionText
|
||||
onClick={_goHome}
|
||||
text={t('Cancel')}
|
||||
text={t<string>('Cancel')}
|
||||
/>
|
||||
</CancelButton>
|
||||
</ActionArea>
|
||||
|
||||
@ -34,22 +34,22 @@ function Forget ({ match: { params: { address } } }: Props): React.ReactElement<
|
||||
<>
|
||||
<Header
|
||||
showBackArrow
|
||||
text={t('Forget account')}
|
||||
text={t<string>('Forget account')}
|
||||
/>
|
||||
<div>
|
||||
<Address address={address}>
|
||||
<MovedWarning isDanger>{t('You are about to remove the account. This means that you will not be able to access it via this extension anymore. If you wish to recover it, you would need to use the seed.')}</MovedWarning>
|
||||
<MovedWarning isDanger>{t<string>('You are about to remove the account. This means that you will not be able to access it via this extension anymore. If you wish to recover it, you would need to use the seed.')}</MovedWarning>
|
||||
<ActionArea>
|
||||
<Button
|
||||
isDanger
|
||||
onClick={_onClick}
|
||||
>
|
||||
{t('I want to forget this account')}
|
||||
{t<string>('I want to forget this account')}
|
||||
</Button>
|
||||
<CancelButton>
|
||||
<ActionText
|
||||
onClick={_goHome}
|
||||
text={t('Cancel')}
|
||||
text={t<string>('Cancel')}
|
||||
/>
|
||||
</CancelButton>
|
||||
</ActionArea>
|
||||
|
||||
@ -29,7 +29,7 @@ export default function ImportQr (): React.ReactElement {
|
||||
<>
|
||||
<Header
|
||||
showBackArrow
|
||||
text={t('Scan Address Qr')}
|
||||
text={t<string>('Scan Address Qr')}
|
||||
/>
|
||||
{!account && (
|
||||
<div>
|
||||
@ -54,7 +54,7 @@ export default function ImportQr (): React.ReactElement {
|
||||
<NextStepButton
|
||||
onClick={_onCreate}
|
||||
>
|
||||
{t('Add the account with identified address')}
|
||||
{t<string>('Add the account with identified address')}
|
||||
</NextStepButton>
|
||||
</ButtonArea>
|
||||
)}
|
||||
|
||||
@ -73,7 +73,7 @@ export default function Import (): React.ReactElement {
|
||||
<>
|
||||
<HeaderWithSmallerMargin
|
||||
showBackArrow
|
||||
text={t('Import account')}
|
||||
text={t<string>('Import account')}
|
||||
/>
|
||||
<div>
|
||||
<Address
|
||||
@ -85,7 +85,7 @@ export default function Import (): React.ReactElement {
|
||||
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
||||
component={SeedInput}
|
||||
isFocused
|
||||
label={t('existing 12 or 24-word mnemonic seed')}
|
||||
label={t<string>('existing 12 or 24-word mnemonic seed')}
|
||||
onValidatedChange={_onChangeSeed}
|
||||
rowsCount={2}
|
||||
validator={isSeedValid}
|
||||
@ -104,7 +104,7 @@ export default function Import (): React.ReactElement {
|
||||
isBusy={isBusy}
|
||||
onClick={_onCreate}
|
||||
>
|
||||
{t('Add the account with the supplied seed')}
|
||||
{t<string>('Add the account with the supplied seed')}
|
||||
</NextStepButton>
|
||||
</ButtonArea>
|
||||
</>
|
||||
|
||||
@ -47,44 +47,44 @@ function Request ({ className, metaId, request, url }: Props): React.ReactElemen
|
||||
<div className={className}>
|
||||
<Table>
|
||||
<tr>
|
||||
<td className='label'>{t('from')}</td>
|
||||
<td className='label'>{t<string>('from')}</td>
|
||||
<td className='data'>{url}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className='label'>{t('chain')}</td>
|
||||
<td className='label'>{t<string>('chain')}</td>
|
||||
<td className='data'>{request.chain}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className='label'>{t('icon')}</td>
|
||||
<td className='label'>{t<string>('icon')}</td>
|
||||
<td className='data'>{request.icon}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className='label'>{t('decimals')}</td>
|
||||
<td className='label'>{t<string>('decimals')}</td>
|
||||
<td className='data'>{request.tokenDecimals}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className='label'>{t('symbol')}</td>
|
||||
<td className='label'>{t<string>('symbol')}</td>
|
||||
<td className='data'>{request.tokenSymbol}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className='label'>{t('upgrade')}</td>
|
||||
<td className='label'>{t<string>('upgrade')}</td>
|
||||
<td className='data'>{chain ? chain.specVersion : t('<unknown>')} -> {request.specVersion}</td>
|
||||
</tr>
|
||||
</Table>
|
||||
<div className='requestInfo'>
|
||||
<Warning className='requestWarning'>{t('This approval will add the metadata to your extension instance, allowing future requests to be decoded using this metadata.')}</Warning>
|
||||
<Warning className='requestWarning'>{t<string>('This approval will add the metadata to your extension instance, allowing future requests to be decoded using this metadata.')}</Warning>
|
||||
<Button
|
||||
className='btnAccept'
|
||||
onClick={_onApprove}
|
||||
>
|
||||
{t('Yes, do this metadata update')}
|
||||
{t<string>('Yes, do this metadata update')}
|
||||
</Button>
|
||||
<ActionBar className='btnReject'>
|
||||
<Link
|
||||
isDanger
|
||||
onClick={_onReject}
|
||||
>
|
||||
{t('Reject')}
|
||||
{t<string>('Reject')}
|
||||
</Link>
|
||||
</ActionBar>
|
||||
</div>
|
||||
|
||||
@ -15,7 +15,7 @@ export default function Metadata (): React.ReactElement {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header text={t('Metadata')} />
|
||||
<Header text={t<string>('Metadata')} />
|
||||
{requests[0]
|
||||
? (
|
||||
<Request
|
||||
|
||||
@ -96,7 +96,7 @@ export default function Upload (): React.ReactElement {
|
||||
<>
|
||||
<HeaderWithSmallerMargin
|
||||
showBackArrow
|
||||
text={t('Restore from JSON')}
|
||||
text={t<string>('Restore from JSON')}
|
||||
/>
|
||||
<div>
|
||||
<div>
|
||||
@ -109,13 +109,13 @@ export default function Upload (): React.ReactElement {
|
||||
<InputFileWithLabel
|
||||
accept={acceptedFormats}
|
||||
isError={!isFileValid}
|
||||
label={t('backup file')}
|
||||
label={t<string>('backup file')}
|
||||
onChange={_onChangeFile}
|
||||
withLabel
|
||||
/>
|
||||
<InputWithLabel
|
||||
isError={!isPassValid}
|
||||
label={t('Password for this file')}
|
||||
label={t<string>('Password for this file')}
|
||||
onChange={_onChangePass}
|
||||
type='password'
|
||||
/>
|
||||
@ -124,7 +124,7 @@ export default function Upload (): React.ReactElement {
|
||||
isDisabled={!isFileValid || !isPassValid}
|
||||
onClick={_onRestore}
|
||||
>
|
||||
{t('Restore')}
|
||||
{t<string>('Restore')}
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
|
||||
@ -20,11 +20,11 @@ function Bytes ({ bytes, className, url }: Props): React.ReactElement<Props> {
|
||||
<table className={className}>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td className='label'>{t('from')}</td>
|
||||
<td className='label'>{t<string>('from')}</td>
|
||||
<td className='data'>{url}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className='label'>{t('bytes')}</td>
|
||||
<td className='label'>{t<string>('bytes')}</td>
|
||||
<td className='data'>{bytes}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
|
||||
@ -8,6 +8,7 @@ import { AnyJson, SignerPayloadJSON } from '@polkadot/types/types';
|
||||
|
||||
import BN from 'bn.js';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { TFunction } from 'i18next';
|
||||
import { formatNumber, bnToBn } from '@polkadot/util';
|
||||
|
||||
import { Table } from '../../components';
|
||||
@ -44,11 +45,11 @@ function decodeMethod (data: string, isDecoded: boolean, chain: Chain | null, sp
|
||||
return { args, method };
|
||||
}
|
||||
|
||||
function renderMethod (data: string, { args, method }: Decoded, t: (key: string) => string): React.ReactNode {
|
||||
function renderMethod (data: string, { args, method }: Decoded, t: TFunction): React.ReactNode {
|
||||
if (!args || !method) {
|
||||
return (
|
||||
<tr>
|
||||
<td className='label'>{t('method data')}</td>
|
||||
<td className='label'>{t<string>('method data')}</td>
|
||||
<td className='data'>{data}</td>
|
||||
</tr>
|
||||
);
|
||||
@ -57,7 +58,7 @@ function renderMethod (data: string, { args, method }: Decoded, t: (key: string)
|
||||
return (
|
||||
<>
|
||||
<tr>
|
||||
<td className='label'>{t('method')}</td>
|
||||
<td className='label'>{t<string>('method')}</td>
|
||||
<td className='data'>
|
||||
<details>
|
||||
<summary>{method.sectionName}.{method.methodName}{
|
||||
@ -71,7 +72,7 @@ function renderMethod (data: string, { args, method }: Decoded, t: (key: string)
|
||||
</tr>
|
||||
{method.meta && (
|
||||
<tr>
|
||||
<td className='label'>{t('info')}</td>
|
||||
<td className='label'>{t<string>('info')}</td>
|
||||
<td className='data'>
|
||||
<details>
|
||||
<summary>{method.meta.documentation.map((d) => d.toString().trim()).join(' ')}</summary>
|
||||
@ -83,15 +84,15 @@ function renderMethod (data: string, { args, method }: Decoded, t: (key: string)
|
||||
);
|
||||
}
|
||||
|
||||
function mortalityAsString (era: ExtrinsicEra, hexBlockNumber: string, t: (key: string, options?: { replace: Record<string, string> }) => string): string {
|
||||
function mortalityAsString (era: ExtrinsicEra, hexBlockNumber: string, t: TFunction): string {
|
||||
if (era.isImmortalEra) {
|
||||
return t('immortal');
|
||||
return t<string>('immortal');
|
||||
}
|
||||
|
||||
const blockNumber = bnToBn(hexBlockNumber);
|
||||
const mortal = era.asMortalEra;
|
||||
|
||||
return t('mortal, valid from {{birth}} to {{death}}', {
|
||||
return t<string>('mortal, valid from {{birth}} to {{death}}', {
|
||||
replace: {
|
||||
birth: formatNumber(mortal.birth(blockNumber)),
|
||||
death: formatNumber(mortal.death(blockNumber))
|
||||
@ -115,24 +116,24 @@ function Extrinsic ({ className, isDecoded, payload: { era, nonce, tip }, reques
|
||||
isFull
|
||||
>
|
||||
<tr>
|
||||
<td className='label'>{t('from')}</td>
|
||||
<td className='label'>{t<string>('from')}</td>
|
||||
<td className='data'>{url}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className='label'>{chain ? t('chain') : t('genesis')}</td>
|
||||
<td className='label'>{chain ? t<string>('chain') : t<string>('genesis')}</td>
|
||||
<td className='data'>{chain ? chain.name : genesisHash}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className='label'>{t('version')}</td>
|
||||
<td className='label'>{t<string>('version')}</td>
|
||||
<td className='data'>{specVersion.toNumber()}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className='label'>{t('nonce')}</td>
|
||||
<td className='label'>{t<string>('nonce')}</td>
|
||||
<td className='data'>{formatNumber(nonce)}</td>
|
||||
</tr>
|
||||
{!tip.isEmpty && (
|
||||
<tr>
|
||||
<td className='label'>{t('tip')}</td>
|
||||
<td className='label'>{t<string>('tip')}</td>
|
||||
<td className='data'>{formatNumber(tip)}</td>
|
||||
</tr>
|
||||
)}
|
||||
|
||||
@ -51,7 +51,7 @@ function Qr ({ className, onSignature, payload, request }: Props): React.ReactEl
|
||||
className='scanButton'
|
||||
onClick={_onShowQr}
|
||||
>
|
||||
{t('Scan signature via camera')}
|
||||
{t<string>('Scan signature via camera')}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@ -125,7 +125,7 @@ export default function Request ({ account: { isExternal }, buttonText, isFirst,
|
||||
>
|
||||
<Checkbox
|
||||
checked={!!isSavedPass}
|
||||
label={t("Don't ask me again for the next 15 minutes")}
|
||||
label={t<string>("Don't ask me again for the next 15 minutes")}
|
||||
onChange={setIsSavedPass}
|
||||
/>
|
||||
</Unlock>
|
||||
@ -174,7 +174,7 @@ export default function Request ({ account: { isExternal }, buttonText, isFirst,
|
||||
isDanger
|
||||
onClick={_onCancel}
|
||||
>
|
||||
{t('Cancel')}
|
||||
{t<string>('Cancel')}
|
||||
</Link>
|
||||
</CancelButton>
|
||||
</SignArea>
|
||||
@ -200,7 +200,7 @@ export default function Request ({ account: { isExternal }, buttonText, isFirst,
|
||||
isDanger
|
||||
onClick={_onCancel}
|
||||
>
|
||||
{t('Reject')}
|
||||
{t<string>('Reject')}
|
||||
</Link>
|
||||
</CancelButton>
|
||||
</SignArea>
|
||||
|
||||
@ -44,7 +44,7 @@ function Unlock ({ buttonText, children, className, error, isBusy, onSign }: Pro
|
||||
disabled={isBusy}
|
||||
isError={!password || !!ownError}
|
||||
isFocused
|
||||
label={t('Password for this account')}
|
||||
label={t<string>('Password for this account')}
|
||||
onChange={_onChangePassword}
|
||||
onEnter={_onClick}
|
||||
type='password'
|
||||
|
||||
@ -48,7 +48,7 @@ export default function Signing (): React.ReactElement {
|
||||
return request
|
||||
? (
|
||||
<>
|
||||
<Header text={isTransaction ? t('Transaction') : t('Sign message')}>
|
||||
<Header text={isTransaction ? t<string>('Transaction') : t<string>('Sign message')}>
|
||||
{requests.length > 1 && (
|
||||
<TransactionIndex
|
||||
index={requestIndex}
|
||||
|
||||
@ -22,19 +22,19 @@ export default function Welcome (): React.ReactElement<Props> {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header text={t('Welcome')} />
|
||||
<Note>{t('Before we start, just a couple of notes regarding use:')}</Note>
|
||||
<Header text={t<string>('Welcome')} />
|
||||
<Note>{t<string>('Before we start, just a couple of notes regarding use:')}</Note>
|
||||
<TextBox>
|
||||
<List>
|
||||
<li>{t('We do not send any clicks, pageviews or events to a central server')}</li>
|
||||
<li>{t('We do not use any trackers or analytics')}</li>
|
||||
<li>{t("We don't collect keys, addresses or any information - your information never leaves this machine")}</li>
|
||||
<li>{t<string>('We do not send any clicks, pageviews or events to a central server')}</li>
|
||||
<li>{t<string>('We do not use any trackers or analytics')}</li>
|
||||
<li>{t<string>("We don't collect keys, addresses or any information - your information never leaves this machine")}</li>
|
||||
</List>
|
||||
</TextBox>
|
||||
<Note>{t('... we are not in the information collection business (even anonymized).')}</Note>
|
||||
<Note>{t<string>('... we are not in the information collection business (even anonymized).')}</Note>
|
||||
<VerticalSpace />
|
||||
<ButtonArea>
|
||||
<Button onClick={_onClick}>{t('Understood, let me continue')}</Button>
|
||||
<Button onClick={_onClick}>{t<string>('Understood, let me continue')}</Button>
|
||||
</ButtonArea>
|
||||
</>
|
||||
);
|
||||
|
||||
@ -15,7 +15,7 @@ export default function Loading ({ children }: Props): React.ReactElement<Props>
|
||||
|
||||
if (!children) {
|
||||
return (
|
||||
<div>{t('... loading ...')}</div>
|
||||
<div>{t<string>('... loading ...')}</div>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@ function MnemonicSeed ({ className, onCopy, seed }: Props): React.ReactElement<P
|
||||
<TextAreaWithLabel
|
||||
className='mnemonicDisplay'
|
||||
isReadOnly
|
||||
label={t('Generated 12-word mnemonic seed:')}
|
||||
label={t<string>('Generated 12-word mnemonic seed:')}
|
||||
value={seed}
|
||||
/>
|
||||
<div className='buttonsRow'>
|
||||
@ -35,7 +35,7 @@ function MnemonicSeed ({ className, onCopy, seed }: Props): React.ReactElement<P
|
||||
data-seed-action='copy'
|
||||
icon={copy}
|
||||
onClick={onCopy}
|
||||
text={t('Copy to clipboard')}
|
||||
text={t<string>('Copy to clipboard')}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -8,6 +8,8 @@ import { HashRouter } from 'react-router-dom';
|
||||
|
||||
import { Fonts, View } from './components';
|
||||
|
||||
import './i18n';
|
||||
|
||||
export default function createView (Entry: React.ComponentType, rootId = 'root'): void {
|
||||
const rootElement = document.getElementById(rootId);
|
||||
|
||||
|
||||
@ -2,19 +2,6 @@
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
interface TranslationOptions {
|
||||
replace: Record<string, string | number>
|
||||
}
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
interface Translation {
|
||||
t: (key: string, options?: TranslationOptions) => string;
|
||||
}
|
||||
|
||||
const defaultTranslation: Translation = {
|
||||
t: (key: string, { replace }: TranslationOptions = { replace: {} }) =>
|
||||
Object.entries(replace).reduce((result: string, [rk, rv]) => result.replace(`{{${rk}}}`, `${rv}`), key)
|
||||
};
|
||||
|
||||
export default function useTranslation (): Translation {
|
||||
return defaultTranslation;
|
||||
}
|
||||
export default useTranslation;
|
||||
|
||||
30
packages/extension-ui/src/i18n.ts
Normal file
30
packages/extension-ui/src/i18n.ts
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2019-2020 @polkadot/extension-ui authors & contributors
|
||||
// This software may be modified and distributed under the terms
|
||||
// of the Apache-2.0 license. See the LICENSE file for details.
|
||||
|
||||
import i18n from 'i18next';
|
||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
|
||||
i18n
|
||||
.use(LanguageDetector)
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
backend: {},
|
||||
debug: false,
|
||||
fallbackLng: 'en',
|
||||
interpolation: {
|
||||
escapeValue: false
|
||||
},
|
||||
keySeparator: false,
|
||||
load: 'languageOnly',
|
||||
nsSeparator: false,
|
||||
react: {
|
||||
wait: true
|
||||
},
|
||||
returnEmptyString: false,
|
||||
returnNull: false
|
||||
})
|
||||
.catch(console.error);
|
||||
|
||||
export default i18n;
|
||||
@ -23,7 +23,7 @@ function Back ({ className, to = '/' }: Props): React.ReactElement<Props> {
|
||||
<div className={className}>
|
||||
<BackLink to={to}>
|
||||
<ArrowLeft />
|
||||
{t('Back')}
|
||||
{t<string>('Back')}
|
||||
</BackLink>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -50,7 +50,7 @@ function MenuAdd ({ className, reference }: Props): React.ReactElement<Props> {
|
||||
<MenuItem className='menuItem'>
|
||||
<Link to='/account/import-seed'>
|
||||
<Svg src={seedIcon} />
|
||||
<span>{t('Import account from pre-existing seed')}</span>
|
||||
<span>{t<string>('Import account from pre-existing seed')}</span>
|
||||
</Link>
|
||||
</MenuItem>
|
||||
<MenuItem className='menuItem'>
|
||||
@ -59,7 +59,7 @@ function MenuAdd ({ className, reference }: Props): React.ReactElement<Props> {
|
||||
to={isPopup ? undefined : '/account/restore-json'}
|
||||
>
|
||||
<Svg src={fileIcon} />
|
||||
<span>{t('Restore account from backup JSON file')}</span>
|
||||
<span>{t<string>('Restore account from backup JSON file')}</span>
|
||||
</Link>
|
||||
</MenuItem>
|
||||
<MenuDivider />
|
||||
@ -69,7 +69,7 @@ function MenuAdd ({ className, reference }: Props): React.ReactElement<Props> {
|
||||
to='/account/import-qr'
|
||||
>
|
||||
<Svg src={qrIcon} />
|
||||
<span>{t('Attach external QR-signer account')}</span>
|
||||
<span>{t<string>('Attach external QR-signer account')}</span>
|
||||
</Link>
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
|
||||
@ -71,19 +71,19 @@ function MenuSettings ({ className, reference }: Props): React.ReactElement<Prop
|
||||
<MenuDivider />
|
||||
<MenuItem
|
||||
className='setting'
|
||||
title={t('External QR accounts and Access')}
|
||||
title={t<string>('External QR accounts and Access')}
|
||||
>
|
||||
<Checkbox
|
||||
checked={camera}
|
||||
className='checkbox'
|
||||
label={t('Allow Camera Access')}
|
||||
label={t<string>('Allow Camera Access')}
|
||||
onChange={setCamera}
|
||||
/>
|
||||
</MenuItem>
|
||||
<MenuDivider />
|
||||
<MenuItem
|
||||
className='setting'
|
||||
title={t('Display address format For')}
|
||||
title={t<string>('Display address format For')}
|
||||
>
|
||||
<Dropdown
|
||||
className='dropdown'
|
||||
@ -101,7 +101,7 @@ function MenuSettings ({ className, reference }: Props): React.ReactElement<Prop
|
||||
className='openWindow'
|
||||
icon={FullScreenIcon}
|
||||
onClick={windowOpen}
|
||||
text={t('Open extension in new window')}
|
||||
text={t<string>('Open extension in new window')}
|
||||
/>
|
||||
</MenuItem>
|
||||
</>
|
||||
|
||||
@ -34,7 +34,7 @@ export default function Name ({ address, className, isFocused, label, onBlur, on
|
||||
data-input-name
|
||||
defaultValue={startValue}
|
||||
isFocused={isFocused}
|
||||
label={label || t('A descriptive name for your account')}
|
||||
label={label || t<string>('A descriptive name for your account')}
|
||||
onBlur={onBlur}
|
||||
onValidatedChange={onChange}
|
||||
type='text'
|
||||
|
||||
@ -37,7 +37,7 @@ export default function Password ({ isFocussed, onChange }: Props): React.ReactE
|
||||
component={InputWithLabel}
|
||||
data-input-password
|
||||
isFocused={isFocussed}
|
||||
label={t('A new password for this account')}
|
||||
label={t<string>('A new password for this account')}
|
||||
onValidatedChange={setPass1}
|
||||
type='password'
|
||||
validator={isFirstPasswordValid}
|
||||
@ -46,7 +46,7 @@ export default function Password ({ isFocussed, onChange }: Props): React.ReactE
|
||||
<ValidatedInput
|
||||
component={InputWithLabel}
|
||||
data-input-repeat-password
|
||||
label={t('Repeat password for verification')}
|
||||
label={t<string>('Repeat password for verification')}
|
||||
onValidatedChange={setPass2}
|
||||
type='password'
|
||||
validator={isSecondPasswordValid(pass1)}
|
||||
|
||||
45
yarn.lock
45
yarn.lock
@ -1400,7 +1400,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.10.3, @babel/runtime@npm:^7.11.0, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.4":
|
||||
"@babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.10.1, @babel/runtime@npm:^7.10.3, @babel/runtime@npm:^7.11.0, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.4":
|
||||
version: 7.11.2
|
||||
resolution: "@babel/runtime@npm:7.11.2"
|
||||
dependencies:
|
||||
@ -3093,9 +3093,12 @@ __metadata:
|
||||
"@types/styled-components": ^5.1.3
|
||||
enzyme: ^3.11.0
|
||||
enzyme-adapter-react-16: ^1.15.4
|
||||
i18next: ^19.7.0
|
||||
i18next-browser-languagedetector: ^5.0.1
|
||||
react: ^16.13.1
|
||||
react-dom: ^16.13.1
|
||||
react-dropzone: ^11.0.3
|
||||
react-i18next: ^11.7.2
|
||||
react-is: ^16.13.1
|
||||
react-router: ^5.2.0
|
||||
react-router-dom: ^5.2.0
|
||||
@ -11920,6 +11923,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"html-parse-stringify2@npm:2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "html-parse-stringify2@npm:2.0.1"
|
||||
dependencies:
|
||||
void-elements: ^2.0.1
|
||||
checksum: 71159c76d54e7e8c1dad808b7ed3f3410e7846b496e3910f0c14f78ade875477b3f6b320ee1259ba5a7689a7ba61bee0b23f9f50ae1d33189de73bf436fb2a52
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"html-tags@npm:^2.0.0":
|
||||
version: 2.0.0
|
||||
resolution: "html-tags@npm:2.0.0"
|
||||
@ -12116,6 +12128,15 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"i18next-browser-languagedetector@npm:^5.0.1":
|
||||
version: 5.0.1
|
||||
resolution: "i18next-browser-languagedetector@npm:5.0.1"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.5.5
|
||||
checksum: 4e80cc054cb1d1600c421d53153b7752aaca07a3ca9f394d64962aa34f901c3e61d2a409d76436c1d76ea8bb1e6ab99a4888dcfbfc3a8de0a489abcd2bb6563d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"i18next-scanner@npm:^2.11.0":
|
||||
version: 2.11.0
|
||||
resolution: "i18next-scanner@npm:2.11.0"
|
||||
@ -12146,7 +12167,7 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"i18next@npm:*":
|
||||
"i18next@npm:*, i18next@npm:^19.7.0":
|
||||
version: 19.7.0
|
||||
resolution: "i18next@npm:19.7.0"
|
||||
dependencies:
|
||||
@ -18253,6 +18274,19 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-i18next@npm:^11.7.2":
|
||||
version: 11.7.2
|
||||
resolution: "react-i18next@npm:11.7.2"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.3.1
|
||||
html-parse-stringify2: 2.0.1
|
||||
peerDependencies:
|
||||
i18next: ">= 19.0.0"
|
||||
react: ">= 16.8.0"
|
||||
checksum: ea5c989d1b129d74b2d4b4d90cd33709f883cf89df90bcfbb78e3c97ac0c052cbf3369554e9e5beb405f1dbab5d7f7b77aa29fc0e13716d78d456f4f8408771c
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"react-is@npm:^16.12.0, react-is@npm:^16.13.1, react-is@npm:^16.6.0, react-is@npm:^16.7.0, react-is@npm:^16.8.1, react-is@npm:^16.8.6":
|
||||
version: 16.13.1
|
||||
resolution: "react-is@npm:16.13.1"
|
||||
@ -22395,6 +22429,13 @@ __metadata:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"void-elements@npm:^2.0.1":
|
||||
version: 2.0.1
|
||||
resolution: "void-elements@npm:2.0.1"
|
||||
checksum: 768d7e08534922455d0e87c66426123920f4d26d88e9c3dc430469e4ce1c11920ca8e2aea7794e52916524d55c3c7820efc20d3f5ce6b749036d989adef1cdd9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"vue-hot-reload-api@npm:^2.3.0":
|
||||
version: 2.3.4
|
||||
resolution: "vue-hot-reload-api@npm:2.3.4"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user