mirror of
https://github.com/Qortal/Qortal-Hub.git
synced 2025-06-06 16:36:58 +00:00
Translate app
This commit is contained in:
parent
45e5e9b660
commit
daa8a9145b
@ -357,7 +357,7 @@ export const Wallets = ({ setExtState, setRawWallet, rawWallet }) => {
|
||||
}}
|
||||
>
|
||||
<Label>
|
||||
{t('auth:name', {
|
||||
{t('core:name', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
</Label>
|
||||
@ -549,7 +549,7 @@ const WalletItem = ({ wallet, updateWalletItem, idx, setSelectedWallet }) => {
|
||||
}}
|
||||
>
|
||||
<Label>
|
||||
{t('auth:name', {
|
||||
{t('core:name', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
</Label>
|
||||
|
@ -54,13 +54,23 @@ export const AppsDesktop = ({
|
||||
|
||||
const myApp = useMemo(() => {
|
||||
return availableQapps.find(
|
||||
(app) => app.name === myName && app.service === 'APP'
|
||||
(app) =>
|
||||
app.name === myName &&
|
||||
app.service ===
|
||||
t('core:app', {
|
||||
postProcess: 'capitalizeAll',
|
||||
})
|
||||
);
|
||||
}, [myName, availableQapps]);
|
||||
|
||||
const myWebsite = useMemo(() => {
|
||||
return availableQapps.find(
|
||||
(app) => app.name === myName && app.service === 'WEBSITE'
|
||||
(app) =>
|
||||
app.name === myName &&
|
||||
app.service ===
|
||||
t('core:website', {
|
||||
postProcess: 'capitalizeAll',
|
||||
})
|
||||
);
|
||||
}, [myName, availableQapps]);
|
||||
|
||||
@ -247,7 +257,6 @@ export const AppsDesktop = ({
|
||||
setTabs((prev) => [...prev, newTab]);
|
||||
setSelectedTab(newTab);
|
||||
setMode('viewer');
|
||||
|
||||
setIsNewTabWindow(false);
|
||||
};
|
||||
|
||||
@ -258,6 +267,7 @@ export const AppsDesktop = ({
|
||||
unsubscribeFromEvent('addTab', addTabFunc);
|
||||
};
|
||||
}, [tabs]);
|
||||
|
||||
const setSelectedTabFunc = (e) => {
|
||||
const data = e.detail?.data;
|
||||
if (e.detail?.isDevMode) return;
|
||||
@ -327,9 +337,9 @@ export const AppsDesktop = ({
|
||||
return (
|
||||
<AppsParent
|
||||
sx={{
|
||||
position: !show && 'fixed',
|
||||
left: !show && '-200vw',
|
||||
flexDirection: 'row',
|
||||
left: !show && '-200vw',
|
||||
position: !show && 'fixed',
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
@ -450,6 +460,7 @@ export const AppsDesktop = ({
|
||||
}}
|
||||
>
|
||||
<Spacer height="30px" />
|
||||
|
||||
<AppsHomeDesktop
|
||||
myName={myName}
|
||||
availableQapps={availableQapps}
|
||||
@ -476,15 +487,18 @@ export const AppsDesktop = ({
|
||||
{mode === 'appInfo-from-category' && !selectedTab && (
|
||||
<AppInfo app={selectedAppInfo} myName={myName} />
|
||||
)}
|
||||
|
||||
<AppsCategoryDesktop
|
||||
availableQapps={availableQapps}
|
||||
isShow={mode === 'category' && !selectedTab}
|
||||
category={selectedCategory}
|
||||
myName={myName}
|
||||
/>
|
||||
|
||||
{mode === 'publish' && !selectedTab && (
|
||||
<AppPublish names={myName ? [myName] : []} categories={categories} />
|
||||
)}
|
||||
|
||||
{tabs.map((tab) => {
|
||||
if (!iframeRefs.current[tab.tabId]) {
|
||||
iframeRefs.current[tab.tabId] = React.createRef();
|
||||
|
@ -1,7 +1,6 @@
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { AppsDevModeHome } from './AppsDevModeHome';
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
|
||||
import {
|
||||
executeEvent,
|
||||
subscribeToEvent,
|
||||
@ -10,7 +9,6 @@ import {
|
||||
import { AppsParent } from './Apps-styles';
|
||||
import AppViewerContainer from './AppViewerContainer';
|
||||
import ShortUniqueId from 'short-unique-id';
|
||||
|
||||
import { Box, ButtonBase, useTheme } from '@mui/material';
|
||||
import { HomeIcon } from '../../assets/Icons/HomeIcon';
|
||||
import { Save } from '../Save/Save';
|
||||
@ -137,7 +135,6 @@ export const AppsDevMode = ({
|
||||
setTabs(copyTabs);
|
||||
setSelectedTab(newTab);
|
||||
setMode('viewer');
|
||||
|
||||
setIsNewTabWindow(false);
|
||||
};
|
||||
|
||||
@ -260,6 +257,7 @@ export const AppsDevMode = ({
|
||||
}
|
||||
/>
|
||||
</ButtonBase>
|
||||
|
||||
<ButtonBase
|
||||
onClick={() => {
|
||||
setDesktopViewMode('apps');
|
||||
@ -282,6 +280,7 @@ export const AppsDevMode = ({
|
||||
/>
|
||||
</IconWrapper>
|
||||
</ButtonBase>
|
||||
|
||||
<ButtonBase
|
||||
onClick={() => {
|
||||
setDesktopViewMode('chat');
|
||||
@ -351,6 +350,7 @@ export const AppsDevMode = ({
|
||||
}}
|
||||
>
|
||||
<Spacer height="30px" />
|
||||
|
||||
<AppsDevModeHome
|
||||
myName={myName}
|
||||
availableQapps={availableQapps}
|
||||
|
@ -1,14 +1,12 @@
|
||||
import React, { useContext, useMemo, useState } from 'react';
|
||||
import { useContext, useState } from 'react';
|
||||
import {
|
||||
AppCircle,
|
||||
AppCircleContainer,
|
||||
AppCircleLabel,
|
||||
AppLibrarySubTitle,
|
||||
AppsContainer,
|
||||
AppsParent,
|
||||
} from './Apps-styles';
|
||||
import { Buffer } from 'buffer';
|
||||
|
||||
import {
|
||||
Avatar,
|
||||
Box,
|
||||
@ -17,13 +15,11 @@ import {
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogContentText,
|
||||
DialogTitle,
|
||||
Input,
|
||||
} from '@mui/material';
|
||||
import { Add } from '@mui/icons-material';
|
||||
import { MyContext, getBaseApiReact } from '../../App';
|
||||
import LogoSelected from '../../assets/svgs/LogoSelected.svg';
|
||||
import { executeEvent } from '../../utils/events';
|
||||
import { Spacer } from '../../common/Spacer';
|
||||
import { useModal } from '../../common/useModal';
|
||||
@ -31,6 +27,8 @@ import { createEndpoint, isUsingLocal } from '../../background';
|
||||
import { Label } from '../Group/AddGroup';
|
||||
import ShortUniqueId from 'short-unique-id';
|
||||
import swaggerSVG from '../../assets/svgs/swagger.svg';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const uid = new ShortUniqueId({ length: 8 });
|
||||
|
||||
export const AppsDevModeHome = ({
|
||||
@ -43,7 +41,7 @@ export const AppsDevModeHome = ({
|
||||
const [domain, setDomain] = useState('127.0.0.1');
|
||||
const [port, setPort] = useState('');
|
||||
const [selectedPreviewFile, setSelectedPreviewFile] = useState(null);
|
||||
|
||||
const { t } = useTranslation(['core', 'group']);
|
||||
const { isShow, onCancel, onOk, show, message } = useModal();
|
||||
const {
|
||||
openSnackGlobal,
|
||||
@ -61,6 +59,7 @@ export const AppsDevModeHome = ({
|
||||
console.log('No file selected.');
|
||||
}
|
||||
};
|
||||
|
||||
const handleSelectDirectry = async (existingDirectoryPath) => {
|
||||
const { buffer, directoryPath } =
|
||||
await window.electron.selectAndZipDirectory(existingDirectoryPath);
|
||||
@ -79,8 +78,7 @@ export const AppsDevModeHome = ({
|
||||
|
||||
setInfoSnackCustom({
|
||||
type: 'error',
|
||||
message:
|
||||
'Please use your local node for dev mode! Logout and use Local node.',
|
||||
message: '',
|
||||
});
|
||||
return;
|
||||
}
|
||||
@ -115,20 +113,21 @@ export const AppsDevModeHome = ({
|
||||
const usingLocal = await isUsingLocal();
|
||||
if (!usingLocal) {
|
||||
setOpenSnackGlobal(true);
|
||||
|
||||
setInfoSnackCustom({
|
||||
type: 'error',
|
||||
message:
|
||||
'Please use your local node for dev mode! Logout and use Local node.',
|
||||
message: t('core:message.generic.devmode_local_node', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
}),
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!myName) {
|
||||
setOpenSnackGlobal(true);
|
||||
|
||||
setInfoSnackCustom({
|
||||
type: 'error',
|
||||
message: 'You need a name to use preview',
|
||||
message: t('core:message.generic.name_preview', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
}),
|
||||
});
|
||||
return;
|
||||
}
|
||||
@ -137,15 +136,16 @@ export const AppsDevModeHome = ({
|
||||
|
||||
if (!buffer) {
|
||||
setOpenSnackGlobal(true);
|
||||
|
||||
setInfoSnackCustom({
|
||||
type: 'error',
|
||||
message: 'Please select a file',
|
||||
message: t('core:message.generic.select_file', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
}),
|
||||
});
|
||||
return;
|
||||
}
|
||||
const postBody = Buffer.from(buffer).toString('base64');
|
||||
|
||||
const postBody = Buffer.from(buffer).toString('base64');
|
||||
const endpoint = await createEndpoint(
|
||||
`/arbitrary/APP/${myName}/zip?preview=true`
|
||||
);
|
||||
@ -156,6 +156,7 @@ export const AppsDevModeHome = ({
|
||||
},
|
||||
body: postBody,
|
||||
});
|
||||
|
||||
if (!response?.ok) throw new Error('Invalid zip');
|
||||
const previewPath = await response.text();
|
||||
if (tabId) {
|
||||
@ -192,20 +193,21 @@ export const AppsDevModeHome = ({
|
||||
const usingLocal = await isUsingLocal();
|
||||
if (!usingLocal) {
|
||||
setOpenSnackGlobal(true);
|
||||
|
||||
setInfoSnackCustom({
|
||||
type: 'error',
|
||||
message:
|
||||
'Please use your local node for dev mode! Logout and use Local node.',
|
||||
message: t('core:message.generic.devmode_local_node', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
}),
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (!myName) {
|
||||
setOpenSnackGlobal(true);
|
||||
|
||||
setInfoSnackCustom({
|
||||
type: 'error',
|
||||
message: 'You need a name to use preview',
|
||||
message: t('core:message.generic.name_preview', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
}),
|
||||
});
|
||||
return;
|
||||
}
|
||||
@ -214,15 +216,16 @@ export const AppsDevModeHome = ({
|
||||
|
||||
if (!buffer) {
|
||||
setOpenSnackGlobal(true);
|
||||
|
||||
setInfoSnackCustom({
|
||||
type: 'error',
|
||||
message: 'Please select a file',
|
||||
message: t('core:message.generic.select_file', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
}),
|
||||
});
|
||||
return;
|
||||
}
|
||||
const postBody = Buffer.from(buffer).toString('base64');
|
||||
|
||||
const postBody = Buffer.from(buffer).toString('base64');
|
||||
const endpoint = await createEndpoint(
|
||||
`/arbitrary/APP/${myName}/zip?preview=true`
|
||||
);
|
||||
@ -233,8 +236,15 @@ export const AppsDevModeHome = ({
|
||||
},
|
||||
body: postBody,
|
||||
});
|
||||
if (!response?.ok) throw new Error('Invalid zip');
|
||||
|
||||
if (!response?.ok)
|
||||
throw new Error(
|
||||
t('core:message.error.invalid_zip', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})
|
||||
);
|
||||
const previewPath = await response.text();
|
||||
|
||||
if (tabId) {
|
||||
executeEvent('appsDevModeUpdateTab', {
|
||||
data: {
|
||||
@ -276,7 +286,7 @@ export const AppsDevModeHome = ({
|
||||
fontSize: '30px',
|
||||
}}
|
||||
>
|
||||
Dev Mode Apps
|
||||
{t('core:devmode_apps', { postProcess: 'capitalizeFirst' })}
|
||||
</AppLibrarySubTitle>
|
||||
</AppsContainer>
|
||||
|
||||
@ -301,7 +311,9 @@ export const AppsDevModeHome = ({
|
||||
<AppCircle>
|
||||
<Add>+</Add>
|
||||
</AppCircle>
|
||||
<AppCircleLabel>Server</AppCircleLabel>
|
||||
<AppCircleLabel>
|
||||
{t('core:server', { postProcess: 'capitalizeFirst' })}
|
||||
</AppCircleLabel>
|
||||
</AppCircleContainer>
|
||||
</ButtonBase>
|
||||
|
||||
@ -319,7 +331,9 @@ export const AppsDevModeHome = ({
|
||||
<Add>+</Add>
|
||||
</AppCircle>
|
||||
|
||||
<AppCircleLabel>Zip</AppCircleLabel>
|
||||
<AppCircleLabel>
|
||||
{t('core:zip', { postProcess: 'capitalizeFirst' })}
|
||||
</AppCircleLabel>
|
||||
</AppCircleContainer>
|
||||
</ButtonBase>
|
||||
|
||||
@ -336,7 +350,9 @@ export const AppsDevModeHome = ({
|
||||
<AppCircle>
|
||||
<Add>+</Add>
|
||||
</AppCircle>
|
||||
<AppCircleLabel>Directory</AppCircleLabel>
|
||||
<AppCircleLabel>
|
||||
{t('core:directory', { postProcess: 'capitalizeFirst' })}
|
||||
</AppCircleLabel>
|
||||
</AppCircleContainer>
|
||||
</ButtonBase>
|
||||
|
||||
@ -365,7 +381,9 @@ export const AppsDevModeHome = ({
|
||||
objectFit: 'fill',
|
||||
},
|
||||
}}
|
||||
alt="Q-Sandbox"
|
||||
alt={t('core:q_apps.q_sandbox', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
src={`${getBaseApiReact()}/arbitrary/THUMBNAIL/Q-Sandbox/qortal_avatar?async=true`}
|
||||
>
|
||||
<img
|
||||
@ -378,7 +396,11 @@ export const AppsDevModeHome = ({
|
||||
</Avatar>
|
||||
</AppCircle>
|
||||
|
||||
<AppCircleLabel>Q-Sandbox</AppCircleLabel>
|
||||
<AppCircleLabel>
|
||||
{t('core:q_apps.q_sandbox', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
</AppCircleLabel>
|
||||
</AppCircleContainer>
|
||||
</ButtonBase>
|
||||
|
||||
@ -407,7 +429,9 @@ export const AppsDevModeHome = ({
|
||||
objectFit: 'fill',
|
||||
},
|
||||
}}
|
||||
alt="API"
|
||||
alt={t('core:api', {
|
||||
postProcess: 'capitalizeAll',
|
||||
})}
|
||||
src={swaggerSVG}
|
||||
>
|
||||
<img
|
||||
@ -420,7 +444,11 @@ export const AppsDevModeHome = ({
|
||||
</Avatar>
|
||||
</AppCircle>
|
||||
|
||||
<AppCircleLabel>API</AppCircleLabel>
|
||||
<AppCircleLabel>
|
||||
{t('core:api', {
|
||||
postProcess: 'capitalizeAll',
|
||||
})}
|
||||
</AppCircleLabel>
|
||||
</AppCircleContainer>
|
||||
</ButtonBase>
|
||||
</AppsContainer>
|
||||
@ -437,7 +465,9 @@ export const AppsDevModeHome = ({
|
||||
}}
|
||||
>
|
||||
<DialogTitle id="alert-dialog-title">
|
||||
{'Add custom framework'}
|
||||
{t('core:action.add_custom_framework', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
</DialogTitle>
|
||||
|
||||
<DialogContent>
|
||||
@ -446,15 +476,22 @@ export const AppsDevModeHome = ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: '5px',
|
||||
}} // TODO translate
|
||||
}}
|
||||
>
|
||||
<Label>Domain</Label>
|
||||
<Label>
|
||||
{t('core:domain', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
</Label>
|
||||
<Input
|
||||
placeholder="Domain"
|
||||
placeholder={t('core:domain', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
value={domain}
|
||||
onChange={(e) => setDomain(e.target.value)}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
@ -463,9 +500,15 @@ export const AppsDevModeHome = ({
|
||||
marginTop: '15px',
|
||||
}}
|
||||
>
|
||||
<Label>Port</Label>
|
||||
<Label>
|
||||
{t('core:port', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
</Label>
|
||||
<Input
|
||||
placeholder="Port"
|
||||
placeholder={t('core:port', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
value={port}
|
||||
onChange={(e) => setPort(e.target.value)}
|
||||
/>
|
||||
@ -474,15 +517,20 @@ export const AppsDevModeHome = ({
|
||||
|
||||
<DialogActions>
|
||||
<Button variant="contained" onClick={onCancel}>
|
||||
Close
|
||||
{t('core:action.close', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
disabled={!domain || !port}
|
||||
variant="contained"
|
||||
onClick={() => onOk({ portVal: port, domainVal: domain })}
|
||||
autoFocus
|
||||
>
|
||||
Add
|
||||
{t('core:action.add', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
|
@ -23,7 +23,6 @@ export const AppsDevModeNavBar = () => {
|
||||
const [navigationController, setNavigationController] = useAtom(
|
||||
navigationControllerAtom
|
||||
);
|
||||
|
||||
const theme = useTheme();
|
||||
const [isNewTabWindow, setIsNewTabWindow] = useState(false);
|
||||
const tabsRef = useRef(null);
|
||||
|
@ -16,6 +16,7 @@ import ArrowOutwardIcon from '@mui/icons-material/ArrowOutward';
|
||||
import { AppsPrivate } from './AppsPrivate';
|
||||
import ThemeSelector from '../Theme/ThemeSelector';
|
||||
import LanguageSelector from '../Language/LanguageSelector';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export const AppsHomeDesktop = ({
|
||||
setMode,
|
||||
@ -26,6 +27,7 @@ export const AppsHomeDesktop = ({
|
||||
}) => {
|
||||
const [qortalUrl, setQortalUrl] = useState('');
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['core', 'group']);
|
||||
|
||||
const openQortalUrl = () => {
|
||||
try {
|
||||
@ -41,6 +43,7 @@ export const AppsHomeDesktop = ({
|
||||
console.log(error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<AppsContainer
|
||||
@ -51,9 +54,9 @@ export const AppsHomeDesktop = ({
|
||||
<AppLibrarySubTitle
|
||||
sx={{
|
||||
fontSize: '30px',
|
||||
}} // TODO translate
|
||||
}}
|
||||
>
|
||||
Apps Dashboard
|
||||
{t('core:apps_dashboard', { postProcess: 'capitalizeFirst' })}
|
||||
</AppLibrarySubTitle>
|
||||
</AppsContainer>
|
||||
|
||||
@ -66,14 +69,14 @@ export const AppsHomeDesktop = ({
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
gap: '20px',
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
padding: '7px',
|
||||
borderRadius: '20px',
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
gap: '20px',
|
||||
maxWidth: '500px',
|
||||
padding: '7px',
|
||||
width: '100%',
|
||||
}}
|
||||
>
|
||||
<Input
|
||||
@ -143,7 +146,9 @@ export const AppsHomeDesktop = ({
|
||||
<AddIcon />
|
||||
</AppCircle>
|
||||
|
||||
<AppCircleLabel>Library</AppCircleLabel>
|
||||
<AppCircleLabel>
|
||||
{t('core:library', { postProcess: 'capitalizeFirst' })}
|
||||
</AppCircleLabel>
|
||||
</AppCircleContainer>
|
||||
</ButtonBase>
|
||||
|
||||
|
@ -41,6 +41,7 @@ import { Virtuoso } from 'react-virtuoso';
|
||||
import { executeEvent } from '../../utils/events';
|
||||
import { ComposeP, ShowMessageReturnButton } from '../Group/Forum/Mail-styles';
|
||||
import { ReturnIcon } from '../../assets/Icons/ReturnIcon.tsx';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const officialAppList = [
|
||||
'q-tube',
|
||||
@ -104,6 +105,7 @@ export const AppsLibraryDesktop = ({
|
||||
const [searchValue, setSearchValue] = useState('');
|
||||
const virtuosoRef = useRef(null);
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['core', 'group']);
|
||||
|
||||
const officialApps = useMemo(() => {
|
||||
return availableQapps.filter(
|
||||
@ -210,9 +212,13 @@ export const AppsLibraryDesktop = ({
|
||||
ml: 1,
|
||||
paddingLeft: '12px',
|
||||
}}
|
||||
placeholder="Search for apps"
|
||||
placeholder={t('core:action.search_apps', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
inputProps={{
|
||||
'aria-label': 'Search for apps',
|
||||
'aria-label': t('core:action.search_apps', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
}),
|
||||
fontSize: '16px',
|
||||
fontWeight: 400,
|
||||
}}
|
||||
@ -273,10 +279,14 @@ export const AppsLibraryDesktop = ({
|
||||
}}
|
||||
onClick={() => {
|
||||
executeEvent('navigateBack', {});
|
||||
}} // TODO translate
|
||||
}}
|
||||
>
|
||||
<ReturnIcon />
|
||||
<ComposeP>Return to Apps Dashboard</ComposeP>
|
||||
<ComposeP>
|
||||
{t('core:action.return_apps_dashboard', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
</ComposeP>
|
||||
</ShowMessageReturnButton>
|
||||
|
||||
<Spacer height="20px" />
|
||||
@ -302,7 +312,11 @@ export const AppsLibraryDesktop = ({
|
||||
</AppsWidthLimiter>
|
||||
) : searchedList?.length === 0 && debouncedValue ? (
|
||||
<AppsWidthLimiter>
|
||||
<Typography>No results</Typography>
|
||||
<Typography>
|
||||
{t('core:message.generic.no_results', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
</Typography>
|
||||
</AppsWidthLimiter>
|
||||
) : (
|
||||
<>
|
||||
@ -311,7 +325,7 @@ export const AppsLibraryDesktop = ({
|
||||
fontSize: '30px',
|
||||
}}
|
||||
>
|
||||
Official Apps
|
||||
{t('core:apps_official', { postProcess: 'capitalizeFirst' })}
|
||||
</AppLibrarySubTitle>
|
||||
|
||||
<Spacer height="45px" />
|
||||
@ -396,7 +410,13 @@ export const AppsLibraryDesktop = ({
|
||||
textAlign: 'start',
|
||||
}}
|
||||
>
|
||||
{hasPublishApp ? 'Update your app' : 'Publish your app'}
|
||||
{hasPublishApp
|
||||
? t('core:action.update_app', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})
|
||||
: t('core:action.publish_app', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
</AppLibrarySubTitle>
|
||||
|
||||
<Spacer height="18px" />
|
||||
@ -422,7 +442,13 @@ export const AppsLibraryDesktop = ({
|
||||
}}
|
||||
>
|
||||
<PublishQAppCTAButton>
|
||||
{hasPublishApp ? 'Update' : 'Publish'}
|
||||
{hasPublishApp
|
||||
? t('core:action.update', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})
|
||||
: t('core:action.publish', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
</PublishQAppCTAButton>
|
||||
|
||||
<Spacer width="20px" />
|
||||
@ -441,7 +467,9 @@ export const AppsLibraryDesktop = ({
|
||||
fontSize: '30px',
|
||||
}}
|
||||
>
|
||||
Categories
|
||||
{t('core:category_other', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
</AppLibrarySubTitle>
|
||||
|
||||
<Spacer height="18px" />
|
||||
@ -480,7 +508,7 @@ export const AppsLibraryDesktop = ({
|
||||
},
|
||||
}}
|
||||
>
|
||||
All
|
||||
{t('core:all', { postProcess: 'capitalizeFirst' })}
|
||||
</Box>
|
||||
</ButtonBase>
|
||||
|
||||
|
@ -32,6 +32,7 @@ import {
|
||||
sortablePinnedAppsAtom,
|
||||
} from '../../atoms/global';
|
||||
import { useAtom, useSetAtom } from 'jotai';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
export function saveToLocalStorage(key, subKey, newValue) {
|
||||
try {
|
||||
@ -75,7 +76,7 @@ export const AppsNavBarDesktop = ({ disableBack }) => {
|
||||
);
|
||||
|
||||
const theme = useTheme();
|
||||
|
||||
const { t } = useTranslation(['core', 'group']);
|
||||
const [isNewTabWindow, setIsNewTabWindow] = useState(false);
|
||||
const tabsRef = useRef(null);
|
||||
const [anchorEl, setAnchorEl] = useState(null);
|
||||
@ -238,6 +239,7 @@ export const AppsNavBarDesktop = ({ disableBack }) => {
|
||||
}}
|
||||
/>
|
||||
</ButtonBase>
|
||||
|
||||
<ButtonBase
|
||||
onClick={(e) => {
|
||||
if (!selectedTab) return;
|
||||
@ -274,9 +276,9 @@ export const AppsNavBarDesktop = ({ disableBack }) => {
|
||||
paper: {
|
||||
sx: {
|
||||
backgroundColor: theme.palette.background.default,
|
||||
borderRadius: '5px',
|
||||
color: theme.palette.text.primary,
|
||||
width: '148px',
|
||||
borderRadius: '5px',
|
||||
},
|
||||
},
|
||||
}}
|
||||
@ -375,9 +377,18 @@ export const AppsNavBarDesktop = ({ disableBack }) => {
|
||||
: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
primary={`${isSelectedAppPinned ? 'Unpin app' : 'Pin app'}`}
|
||||
primary={`${
|
||||
isSelectedAppPinned
|
||||
? t('core:action.unpin_app', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})
|
||||
: t('core:action.pin_app', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})
|
||||
}}`}
|
||||
/>
|
||||
</MenuItem>
|
||||
|
||||
<MenuItem
|
||||
onClick={() => {
|
||||
if (selectedTab?.refreshFunc) {
|
||||
@ -404,6 +415,7 @@ export const AppsNavBarDesktop = ({ disableBack }) => {
|
||||
}}
|
||||
/>
|
||||
</ListItemIcon>
|
||||
|
||||
<ListItemText
|
||||
sx={{
|
||||
'& .MuiTypography-root': {
|
||||
@ -447,7 +459,9 @@ export const AppsNavBarDesktop = ({ disableBack }) => {
|
||||
color: theme.palette.text.primary,
|
||||
},
|
||||
}}
|
||||
primary="Copy link"
|
||||
primary={t('core:action.copy_link', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
/>
|
||||
</MenuItem>
|
||||
)}
|
||||
|
@ -36,6 +36,7 @@ import { fileToBase64 } from '../../utils/fileReading';
|
||||
import { objectToBase64 } from '../../qdn/encryption/group-encryption';
|
||||
import { getFee } from '../../background';
|
||||
import { useAtom } from 'jotai';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
const maxFileSize = 50 * 1024 * 1024; // 50MB
|
||||
|
||||
@ -62,6 +63,7 @@ export const AppsPrivate = ({ myName }) => {
|
||||
const [memberGroups] = useAtom(memberGroupsAtom);
|
||||
|
||||
const theme = useTheme();
|
||||
const { t } = useTranslation(['core', 'group']);
|
||||
|
||||
const myGroupsPrivate = useMemo(() => {
|
||||
return memberGroups?.filter(
|
||||
@ -98,9 +100,11 @@ export const AppsPrivate = ({ myName }) => {
|
||||
errors.forEach((error) => {
|
||||
if (error.code === 'file-too-large') {
|
||||
console.error(
|
||||
`File ${file.name} is too large. Max size allowed is ${
|
||||
maxFileSize / (1024 * 1024)
|
||||
} MB.`
|
||||
t('core:message.error.file_too_large', {
|
||||
filename: file.name,
|
||||
size: maxFileSize / (1024 * 1024),
|
||||
postProcess: 'capitalizeFirst',
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
@ -111,7 +115,6 @@ export const AppsPrivate = ({ myName }) => {
|
||||
const addPrivateApp = async () => {
|
||||
try {
|
||||
if (privateAppValues?.groupId === 0) return;
|
||||
|
||||
await openApp(privateAppValues, true);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
@ -139,9 +142,28 @@ export const AppsPrivate = ({ myName }) => {
|
||||
const publishPrivateApp = async () => {
|
||||
try {
|
||||
if (selectedGroup === 0) return;
|
||||
if (!logo) throw new Error('Please select an image for a logo');
|
||||
if (!myName) throw new Error('You need a Qortal name to publish');
|
||||
if (!newPrivateAppValues?.name) throw new Error('Your app needs a name');
|
||||
|
||||
if (!logo)
|
||||
throw new Error(
|
||||
t('core:message.generic.select_image', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})
|
||||
);
|
||||
|
||||
if (!myName)
|
||||
throw new Error(
|
||||
t('core:message.generic.name_publish', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})
|
||||
);
|
||||
|
||||
if (!newPrivateAppValues?.name)
|
||||
throw new Error(
|
||||
t('core:message.error.app_need_name', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})
|
||||
);
|
||||
|
||||
const base64Logo = await fileToBase64(logo);
|
||||
const base64App = await fileToBase64(file);
|
||||
const objectToSave = {
|
||||
@ -160,16 +182,22 @@ export const AppsPrivate = ({ myName }) => {
|
||||
|
||||
if (decryptedData?.error) {
|
||||
throw new Error(
|
||||
decryptedData?.error || 'Unable to encrypt app. App not published'
|
||||
decryptedData?.error ||
|
||||
t('core:message.error.unable_encrypt_app', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
const fee = await getFee('ARBITRARY');
|
||||
|
||||
await show({
|
||||
message: 'Would you like to publish this app?',
|
||||
message: t('core:save_options.publish_app', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
}),
|
||||
publishFee: fee.fee + ' QORT',
|
||||
});
|
||||
|
||||
await new Promise((res, rej) => {
|
||||
window
|
||||
.sendMessage('publishOnQDN', {
|
||||
@ -185,7 +213,12 @@ export const AppsPrivate = ({ myName }) => {
|
||||
rej(response.error);
|
||||
})
|
||||
.catch((error) => {
|
||||
rej(error.message || 'An error occurred');
|
||||
rej(
|
||||
error.message ||
|
||||
t('core:message.error.generic', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -203,7 +236,11 @@ export const AppsPrivate = ({ myName }) => {
|
||||
setOpenSnackGlobal(true);
|
||||
setInfoSnackCustom({
|
||||
type: 'error',
|
||||
message: error?.message || 'Unable to publish app',
|
||||
message:
|
||||
error?.message ||
|
||||
t('core:message.error.unable_publish_app', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
}),
|
||||
});
|
||||
}
|
||||
};
|
||||
@ -241,6 +278,7 @@ export const AppsPrivate = ({ myName }) => {
|
||||
<AppCircleLabel>Private</AppCircleLabel>
|
||||
</AppCircleContainer>
|
||||
</ButtonBase>
|
||||
|
||||
{isOpenPrivateModal && (
|
||||
<Dialog
|
||||
open={isOpenPrivateModal}
|
||||
@ -312,10 +350,19 @@ export const AppsPrivate = ({ myName }) => {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
gap: '5px',
|
||||
}} // TODO translate
|
||||
}}
|
||||
>
|
||||
<Label>Select a group</Label>
|
||||
<Label>Only private groups will be shown</Label>
|
||||
<Label>
|
||||
{t('group:action.select_group', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
</Label>
|
||||
<Label>
|
||||
{t('group:message.generic.only_private_groups', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
</Label>
|
||||
|
||||
<Select
|
||||
labelId="demo-simple-select-label"
|
||||
id="demo-simple-select"
|
||||
@ -330,7 +377,11 @@ export const AppsPrivate = ({ myName }) => {
|
||||
});
|
||||
}}
|
||||
>
|
||||
<MenuItem value={0}>No group selected</MenuItem>
|
||||
<MenuItem value={0}>
|
||||
{t('group:message.generic.no_selection', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
</MenuItem>
|
||||
|
||||
{myGroupsPrivate
|
||||
?.filter((item) => !item?.isOpen)
|
||||
@ -343,7 +394,9 @@ export const AppsPrivate = ({ myName }) => {
|
||||
})}
|
||||
</Select>
|
||||
</Box>
|
||||
|
||||
<Spacer height="10px" />
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
@ -352,7 +405,9 @@ export const AppsPrivate = ({ myName }) => {
|
||||
marginTop: '15px',
|
||||
}}
|
||||
>
|
||||
<Label>name</Label>
|
||||
<Label>
|
||||
{t('core:name', { postProcess: 'capitalizeFirst' })}
|
||||
</Label>
|
||||
<Input
|
||||
placeholder="name"
|
||||
value={privateAppValues?.name}
|
||||
@ -366,6 +421,7 @@ export const AppsPrivate = ({ myName }) => {
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
@ -374,9 +430,14 @@ export const AppsPrivate = ({ myName }) => {
|
||||
marginTop: '15px',
|
||||
}}
|
||||
>
|
||||
<Label>identifier</Label>
|
||||
<Label>
|
||||
{t('core:identifier', { postProcess: 'capitalizeFirst' })}
|
||||
</Label>
|
||||
|
||||
<Input
|
||||
placeholder="identifier"
|
||||
placeholder={t('core:identifier', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
value={privateAppValues?.identifier}
|
||||
onChange={(e) =>
|
||||
setPrivateAppValues((prev) => {
|
||||
@ -397,7 +458,7 @@ export const AppsPrivate = ({ myName }) => {
|
||||
setIsOpenPrivateModal(false);
|
||||
}}
|
||||
>
|
||||
Close
|
||||
{t('core:action.close', { postProcess: 'capitalizeFirst' })}
|
||||
</Button>
|
||||
<Button
|
||||
disabled={
|
||||
@ -410,7 +471,7 @@ export const AppsPrivate = ({ myName }) => {
|
||||
onClick={() => addPrivateApp()}
|
||||
autoFocus
|
||||
>
|
||||
Access
|
||||
{t('core:action.access', { postProcess: 'capitalizeFirst' })}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</>
|
||||
@ -424,7 +485,9 @@ export const AppsPrivate = ({ myName }) => {
|
||||
fontSize: '14px',
|
||||
}}
|
||||
>
|
||||
Select .zip file containing static content:{' '}
|
||||
{t('core:message.generic.select_zip', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
</PublishQAppInfo>
|
||||
|
||||
<Spacer height="10px" />
|
||||
@ -435,10 +498,11 @@ export const AppsPrivate = ({ myName }) => {
|
||||
fontSize: '14px',
|
||||
}}
|
||||
>{`
|
||||
50mb MB maximum`}</PublishQAppInfo>
|
||||
50mb MB max`}</PublishQAppInfo>
|
||||
{file && (
|
||||
<>
|
||||
<Spacer height="5px" />
|
||||
|
||||
<PublishQAppInfo>{`Selected: (${file?.name})`}</PublishQAppInfo>
|
||||
</>
|
||||
)}
|
||||
@ -454,7 +518,13 @@ export const AppsPrivate = ({ myName }) => {
|
||||
>
|
||||
{' '}
|
||||
<input {...getInputProps()} />
|
||||
{file ? 'Change' : 'Choose'} File
|
||||
{file
|
||||
? t('core:action.change_file', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})
|
||||
: t('core:action.choose_file', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
</PublishQAppChoseFile>
|
||||
|
||||
<Spacer height="20px" />
|
||||
@ -466,10 +536,18 @@ export const AppsPrivate = ({ myName }) => {
|
||||
gap: '5px',
|
||||
}}
|
||||
>
|
||||
<Label>Select a group</Label>
|
||||
<Label>
|
||||
Only groups where you are an admin will be shown
|
||||
{t('group:action.select_group', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
</Label>
|
||||
|
||||
<Label>
|
||||
{t('group:amessage.generic.admin_only', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
</Label>
|
||||
|
||||
<Select
|
||||
labelId="demo-simple-select-label"
|
||||
id="demo-simple-select"
|
||||
@ -477,7 +555,11 @@ export const AppsPrivate = ({ myName }) => {
|
||||
label="Groups where you are an admin"
|
||||
onChange={(e) => setSelectedGroup(e.target.value)}
|
||||
>
|
||||
<MenuItem value={0}>No group selected</MenuItem>
|
||||
<MenuItem value={0}>
|
||||
{t('group:message.generic.no_selection', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
</MenuItem>
|
||||
{myGroupsWhereIAmAdmin
|
||||
?.filter((item) => !item?.isOpen)
|
||||
.map((group) => {
|
||||
@ -500,9 +582,13 @@ export const AppsPrivate = ({ myName }) => {
|
||||
marginTop: '15px',
|
||||
}}
|
||||
>
|
||||
<Label>identifier</Label>
|
||||
<Label>
|
||||
{t('core:identifier', { postProcess: 'capitalizeFirst' })}
|
||||
</Label>
|
||||
<Input
|
||||
placeholder="identifier"
|
||||
placeholder={t('core:identifier', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
value={newPrivateAppValues?.identifier}
|
||||
onChange={(e) =>
|
||||
setNewPrivateAppValues((prev) => {
|
||||
@ -525,9 +611,14 @@ export const AppsPrivate = ({ myName }) => {
|
||||
marginTop: '15px',
|
||||
}}
|
||||
>
|
||||
<Label>App name</Label>
|
||||
<Label>
|
||||
{t('core:app_name', { postProcess: 'capitalizeFirst' })}
|
||||
</Label>
|
||||
|
||||
<Input
|
||||
placeholder="App name"
|
||||
placeholder={t('core:app_name', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
value={newPrivateAppValues?.name}
|
||||
onChange={(e) =>
|
||||
setNewPrivateAppValues((prev) => {
|
||||
@ -543,10 +634,15 @@ export const AppsPrivate = ({ myName }) => {
|
||||
<Spacer height="10px" />
|
||||
|
||||
<ImageUploader onPick={(file) => setLogo(file)}>
|
||||
<Button variant="contained">Choose logo</Button>
|
||||
<Button variant="contained">
|
||||
{t('core:action.choose_logo', {
|
||||
postProcess: 'capitalizeFirst',
|
||||
})}
|
||||
</Button>
|
||||
</ImageUploader>
|
||||
|
||||
{logo?.name}
|
||||
|
||||
<Spacer height="25px" />
|
||||
</DialogContent>
|
||||
|
||||
@ -558,7 +654,7 @@ export const AppsPrivate = ({ myName }) => {
|
||||
clearFields();
|
||||
}}
|
||||
>
|
||||
Close
|
||||
{t('core:action.close', { postProcess: 'capitalizeFirst' })}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
@ -572,7 +668,7 @@ export const AppsPrivate = ({ myName }) => {
|
||||
onClick={() => publishPrivateApp()}
|
||||
autoFocus
|
||||
>
|
||||
Publish
|
||||
{t('core:action.publish', { postProcess: 'capitalizeFirst' })}
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</>
|
||||
|
@ -37,7 +37,6 @@
|
||||
"your_accounts": "your saved accounts"
|
||||
}
|
||||
},
|
||||
"name": "name",
|
||||
"node": {
|
||||
"choose": "choose custom node",
|
||||
"custom_many": "custom nodes",
|
||||
|
@ -1,20 +1,26 @@
|
||||
{
|
||||
"action": {
|
||||
"add": "add",
|
||||
"add_custom_framework": "add custom framework",
|
||||
"accept": "accept",
|
||||
"access": "access",
|
||||
"backup_account": "backup account",
|
||||
"backup_wallet": "backup wallet",
|
||||
"cancel": "cancel",
|
||||
"cancel_invitation": "cancel invitation",
|
||||
"change": "change",
|
||||
"change_file": "change file",
|
||||
"change_language": "change language",
|
||||
"choose": "choose",
|
||||
"choose_file": "choose file",
|
||||
"close": "close",
|
||||
"continue": "continue",
|
||||
"continue_logout": "continue to logout",
|
||||
"copy_link": "copy link",
|
||||
"create_apps": "create apps",
|
||||
"create_file": "create file",
|
||||
"create_thread": "create thread",
|
||||
"choose_logo": "choose a logo",
|
||||
"choose_name": "choose a name",
|
||||
"decline": "decline",
|
||||
"decrypt": "decrypt",
|
||||
@ -34,30 +40,44 @@
|
||||
"notify": "notify",
|
||||
"open": "open",
|
||||
"pin": "pin",
|
||||
"pin_app": "pin app",
|
||||
"pin_from_dashboard": "pin from dashboard",
|
||||
"post": "post",
|
||||
"post_message": "post message",
|
||||
"publish": "publish",
|
||||
"publish_app": "publish your app",
|
||||
"register_name": "register name",
|
||||
"remove": "remove",
|
||||
"return_apps_dashboard": "return to Apps Dashboard",
|
||||
"save": "save",
|
||||
"search_apps": "search for apps",
|
||||
"select_app_type": "select App Type",
|
||||
"select_category": "select Category",
|
||||
"select_name_app": "select Name/App",
|
||||
"start_minting": "start minting",
|
||||
"unpin": "unpin",
|
||||
"unpin_from_dashboard": "unpin from dashboard"
|
||||
"unpin_app": "unpin app",
|
||||
"unpin_from_dashboard": "unpin from dashboard",
|
||||
"update": "update",
|
||||
"update_app": "update your app"
|
||||
},
|
||||
"admin": "admin",
|
||||
"all": "all",
|
||||
"api": "API",
|
||||
"app": "app",
|
||||
"app_name": "app name",
|
||||
"app_service_type": "app service type",
|
||||
"apps_dashboard": "apps Dashboard",
|
||||
"apps_official": "official Apps",
|
||||
"category": "category",
|
||||
"category_other": "categories",
|
||||
"core": {
|
||||
"block_height": "block height",
|
||||
"information": "core information",
|
||||
"peers": "connected peers",
|
||||
"version": "core version"
|
||||
},
|
||||
"domain": "domain",
|
||||
"ui": {
|
||||
"version": "UI version"
|
||||
},
|
||||
@ -66,14 +86,18 @@
|
||||
"one": "one"
|
||||
},
|
||||
"description": "description",
|
||||
"devmode_apps": "dev Mode Apps",
|
||||
"directory": "directory",
|
||||
"downloading_qdn": "downloading from QDN",
|
||||
"fee": {
|
||||
"payment": "payment fee",
|
||||
"publish": "publish fee"
|
||||
},
|
||||
"general_settings": "general settings",
|
||||
"identifier": "identifier",
|
||||
"last_height": "last height",
|
||||
"level": "level",
|
||||
"library": "library",
|
||||
"list": {
|
||||
"invite": "invite list",
|
||||
"join_request": "join request list",
|
||||
@ -85,31 +109,41 @@
|
||||
"message": {
|
||||
"error": {
|
||||
"address_not_found": "your address was not found",
|
||||
"app_need_name": "your app needs a name",
|
||||
"file_too_large": "file {{ filename }} is too large. Max size allowed is {{ size }} MB.",
|
||||
"generic": "an error occurred",
|
||||
"incorrect_password": "incorrect password",
|
||||
"invalid_zip": "invalid zip",
|
||||
"minting_account_add": "unable to add minting account",
|
||||
"minting_account_remove": "unable to remove minting account",
|
||||
"missing_fields": "missing: {{ fields }}",
|
||||
"publish_app": "unable to publish app",
|
||||
"rating_option": "cannot find rating option",
|
||||
"save_qdn": "unable to save to QDN",
|
||||
"unable_encrypt_app": "unable to encrypt app. App not published'",
|
||||
"unable_publish_app": "unable to publish app",
|
||||
"unable_rate": "unable to rate"
|
||||
},
|
||||
"generic": {
|
||||
"devmode_local_node": "please use your local node for dev mode! Logout and use Local node.",
|
||||
"name_available": "{{ name }} is available",
|
||||
"name_benefits": "benefits of a name",
|
||||
"name_checking": "checking if name already exists",
|
||||
"name_preview": "you need a name to use preview",
|
||||
"name_publish": "you need a Qortal name to publish",
|
||||
"name_rate": "you need a name to rate.",
|
||||
"name_registration": "your balance is {{ balance }} QORT. A name registration requires a {{ fee }} QORT fee",
|
||||
"name_unavailable": "{{ name }} is unavailable",
|
||||
"no_description": "no description",
|
||||
"no_notifications": "no new notifications",
|
||||
"no_results": "no results",
|
||||
"one_app_per_name": "note: Currently, only one App and Website is allowed per Name.",
|
||||
"publish_data": "publish data to Qortal: anything from apps to videos. Fully decentralized!",
|
||||
"publishing": "publishing... Please wait.",
|
||||
"rating": "rating for {{ service }} {{ name }}",
|
||||
"secure_ownership": "secure ownership of data published by your name. You can even sell your name, along with your data to a third party.",
|
||||
"select_file": "please select a file",
|
||||
"select_image": "please select an image for a logo",
|
||||
"select_zip": "select .zip file containing static content:"
|
||||
},
|
||||
"question": {
|
||||
@ -131,6 +165,7 @@
|
||||
}
|
||||
},
|
||||
"minting_status": "minting status",
|
||||
"name": "name",
|
||||
"name_app": "name/App",
|
||||
"none": "none",
|
||||
"page": {
|
||||
@ -140,10 +175,12 @@
|
||||
"previous": "previous"
|
||||
},
|
||||
"payment_notification": "payment notification",
|
||||
"port": "port",
|
||||
"price": "price",
|
||||
"q_apps": {
|
||||
"about": "about this Q-App",
|
||||
"q_mail": "q-mail"
|
||||
"q_mail": "q-mail",
|
||||
"q_sandbox": "q-Sandbox"
|
||||
},
|
||||
"save_options": {
|
||||
"no_pinned_changes": "you currently do not have any changes to your pinned apps",
|
||||
@ -162,6 +199,7 @@
|
||||
"settings": "you are using the export/import way of saving settings.",
|
||||
"unsaved_changes": " you have unsaved changes to your pinned apps. Save them to QDN."
|
||||
},
|
||||
"server": "server",
|
||||
"settings": "settings",
|
||||
"supply": "supply",
|
||||
"tags": "tags",
|
||||
@ -180,6 +218,7 @@
|
||||
"title": "title",
|
||||
"tutorial": "tutorial",
|
||||
"user_lookup": "user lookup",
|
||||
"zip": "zip",
|
||||
"wallet": {
|
||||
"wallet": "wallet",
|
||||
"wallet_other": "wallets"
|
||||
|
@ -78,6 +78,7 @@
|
||||
"no_selection": "no group selected",
|
||||
"not_part_group": "you are not part of the encrypted group of members. Wait until an admin re-encrypts the keys.",
|
||||
"only_encrypted": "only unencrypted messages will be displayed.",
|
||||
"only_private_groups": "only private groups will be shown",
|
||||
"private_key_copied": "private key copied",
|
||||
"provide_message": "please provide a first message to the thread",
|
||||
"secure_place": "keep your private key in a secure place. Do not share!",
|
||||
|
Loading…
x
Reference in New Issue
Block a user