Translation for chat pages

This commit is contained in:
Nicola Benaglia 2025-05-17 11:20:42 +02:00
parent 628786165a
commit bec943149f
7 changed files with 178 additions and 47 deletions

View File

@ -234,7 +234,12 @@ export const GroupAnnouncements = ({
rej(response.error); rej(response.error);
}) })
.catch((error) => { .catch((error) => {
rej(error.message || 'An error occurred'); rej(
error.message ||
t('core:message.error.generic', {
postProcess: 'capitalizeFirst',
})
);
}); });
}); });
} catch (error) { } catch (error) {
@ -257,7 +262,12 @@ export const GroupAnnouncements = ({
rej(response.error); rej(response.error);
}) })
.catch((error) => { .catch((error) => {
rej(error.message || 'An error occurred'); rej(
error.message ||
t('core:message.error.generic', {
postProcess: 'capitalizeFirst',
})
);
}); });
}); });
}; };
@ -337,7 +347,7 @@ export const GroupAnnouncements = ({
setTempData(selectedGroup); setTempData(selectedGroup);
clearEditorContent(); clearEditorContent();
} }
// TODO send chat message // send chat message
} catch (error) { } catch (error) {
if (!error) return; if (!error) return;
setInfoSnack({ setInfoSnack({
@ -586,7 +596,9 @@ export const GroupAnnouncements = ({
fontSize: '30px', fontSize: '30px',
}} }}
/> />
Group Announcements {t('group:message.generic.group_announcement', {
postProcess: 'capitalizeFirst',
})}
</Box> </Box>
<Spacer height={'25px'} /> <Spacer height={'25px'} />
@ -605,10 +617,13 @@ export const GroupAnnouncements = ({
fontSize: '16px', fontSize: '16px',
}} }}
> >
No announcements {t('group:message.generic.no_announcement', {
postProcess: 'capitalizeFirst',
})}
</Typography> </Typography>
</Box> </Box>
)} )}
<AnnouncementList <AnnouncementList
announcementData={announcementData} announcementData={announcementData}
initialMessages={combinedListTempAndReal} initialMessages={combinedListTempAndReal}
@ -689,7 +704,7 @@ export const GroupAnnouncements = ({
padding: '5px', padding: '5px',
}} }}
> >
{` Close`} {t('core:action.close', { postProcess: 'capitalizeFirst' })}
</CustomButton> </CustomButton>
)} )}
@ -723,7 +738,9 @@ export const GroupAnnouncements = ({
}} }}
/> />
)} )}
{` Publish Announcement`} {t('group:action.publish_announcement', {
postProcess: 'capitalizeFirst',
})}
</CustomButton> </CustomButton>
</Box> </Box>
</div> </div>
@ -739,7 +756,9 @@ export const GroupAnnouncements = ({
<LoadingSnackbar <LoadingSnackbar
open={isLoading} open={isLoading}
info={{ info={{
message: 'Loading announcements... please wait.', message: t('core:loading.announcements', {
postProcess: 'capitalizeFirst',
}),
}} }}
/> />
</div> </div>

View File

@ -20,6 +20,7 @@ import { getFee } from '../../background';
import { fileToBase64 } from '../../utils/fileReading'; import { fileToBase64 } from '../../utils/fileReading';
import { LoadingButton } from '@mui/lab'; import { LoadingButton } from '@mui/lab';
import ErrorIcon from '@mui/icons-material/Error'; import ErrorIcon from '@mui/icons-material/Error';
import { useTranslation } from 'react-i18next';
export const GroupAvatar = ({ export const GroupAvatar = ({
myName, myName,
@ -32,7 +33,7 @@ export const GroupAvatar = ({
const [avatarFile, setAvatarFile] = useState(null); const [avatarFile, setAvatarFile] = useState(null);
const [tempAvatar, setTempAvatar] = useState(null); const [tempAvatar, setTempAvatar] = useState(null);
const { show } = useContext(MyContext); const { show } = useContext(MyContext);
const { t } = useTranslation(['auth', 'core', 'group']);
const [anchorEl, setAnchorEl] = useState(null); const [anchorEl, setAnchorEl] = useState(null);
const [isLoading, setIsLoading] = useState(false); const [isLoading, setIsLoading] = useState(false);
// Handle child element click to open Popover // Handle child element click to open Popover
@ -68,6 +69,7 @@ export const GroupAvatar = ({
console.log(error); console.log(error);
} }
}, []); }, []);
useEffect(() => { useEffect(() => {
if (!myName || !groupId) return; if (!myName || !groupId) return;
checkIfAvatarExists(myName, groupId); checkIfAvatarExists(myName, groupId);
@ -79,14 +81,22 @@ export const GroupAvatar = ({
const fee = await getFee('ARBITRARY'); const fee = await getFee('ARBITRARY');
if (+balance < +fee.fee) if (+balance < +fee.fee)
throw new Error(`Publishing an Avatar requires ${fee.fee}`); throw new Error(
t('core:message.generic.avatar_publish_fee', {
fee: fee.fee,
postProcess: 'capitalizeFirst',
})
);
await show({ await show({
message: 'Would you like to publish an avatar?', message: t('core:question.publish_avatar', {
postProcess: 'capitalizeFirst',
}),
publishFee: fee.fee + ' QORT', publishFee: fee.fee + ' QORT',
}); });
setIsLoading(true); setIsLoading(true);
const avatarBase64 = await fileToBase64(avatarFile); const avatarBase64 = await fileToBase64(avatarFile);
await new Promise((res, rej) => { await new Promise((res, rej) => {
window window
.sendMessage('publishOnQDN', { .sendMessage('publishOnQDN', {
@ -102,7 +112,12 @@ export const GroupAvatar = ({
rej(response.error); rej(response.error);
}) })
.catch((error) => { .catch((error) => {
rej(error.message || 'An error occurred'); rej(
error.message ||
t('core:message.error.generic', {
postProcess: 'capitalizeFirst',
})
);
}); });
}); });
setAvatarFile(null); setAvatarFile(null);
@ -142,7 +157,7 @@ export const GroupAvatar = ({
opacity: 0.5, opacity: 0.5,
}} }}
> >
change avatar {t('core:action.change_avatar', { postProcess: 'capitalizeFirst' })}
</Typography> </Typography>
</ButtonBase> </ButtonBase>
@ -182,7 +197,7 @@ export const GroupAvatar = ({
opacity: 0.5, opacity: 0.5,
}} }}
> >
change avatar {t('core:action.change_avatar', { postProcess: 'capitalizeFirst' })}
</Typography> </Typography>
</ButtonBase> </ButtonBase>
@ -211,7 +226,7 @@ export const GroupAvatar = ({
opacity: 0.5, opacity: 0.5,
}} }}
> >
set avatar {t('core:action.set_avatar', { postProcess: 'capitalizeFirst' })}
</Typography> </Typography>
</ButtonBase> </ButtonBase>
@ -242,6 +257,8 @@ const PopoverComp = ({
myName, myName,
}) => { }) => {
const theme = useTheme(); const theme = useTheme();
const { t } = useTranslation(['auth', 'core', 'group']);
return ( return (
<Popover <Popover
id={id} id={id}
@ -263,11 +280,16 @@ const PopoverComp = ({
fontSize: '12px', fontSize: '12px',
}} }}
> >
(500 KB max. for GIFS){' '} {t('core:message.generic.avatar_size', {
size: 500, // TODO magic number
postProcess: 'capitalizeFirst',
})}
</Typography> </Typography>
<ImageUploader onPick={(file) => setAvatarFile(file)}> <ImageUploader onPick={(file) => setAvatarFile(file)}>
<Button variant="contained">Choose Image</Button> <Button variant="contained">
{t('core:action.choose_image', { postProcess: 'capitalizeFirst' })}
</Button>
</ImageUploader> </ImageUploader>
{avatarFile?.name} {avatarFile?.name}
@ -277,9 +299,9 @@ const PopoverComp = ({
{!myName && ( {!myName && (
<Box <Box
sx={{ sx={{
alignItems: 'center',
display: 'flex', display: 'flex',
gap: '5px', gap: '5px',
alignItems: 'center',
}} }}
> >
<ErrorIcon <ErrorIcon
@ -288,7 +310,9 @@ const PopoverComp = ({
}} }}
/> />
<Typography> <Typography>
A registered name is required to set an avatar {t('core:message.generic.avatar_registered_name', {
postProcess: 'capitalizeFirst',
})}
</Typography> </Typography>
</Box> </Box>
)} )}
@ -301,7 +325,7 @@ const PopoverComp = ({
onClick={publishAvatar} onClick={publishAvatar}
variant="contained" variant="contained"
> >
Publish avatar {t('group:action.publish_avatar', { postProcess: 'capitalizeFirst' })}
</LoadingButton> </LoadingButton>
</Box> </Box>
</Popover> </Popover>

View File

@ -1,6 +1,9 @@
import { forwardRef, useEffect, useImperativeHandle, useState } from 'react'; import { forwardRef, useEffect, useImperativeHandle, useState } from 'react';
import { useTranslation } from 'react-i18next';
export default forwardRef((props, ref) => { export default forwardRef((props, ref) => {
const { t } = useTranslation(['auth', 'core', 'group']);
const [selectedIndex, setSelectedIndex] = useState(0); const [selectedIndex, setSelectedIndex] = useState(0);
const selectItem = (index) => { const selectItem = (index) => {
@ -61,7 +64,11 @@ export default forwardRef((props, ref) => {
</button> </button>
)) ))
) : ( ) : (
<div className="item">No result</div> <div className="item">
{t('core:message.generic.no_results', {
postProcess: 'capitalizeFirst',
})}
</div>
)} )}
</div> </div>
); );

View File

@ -48,6 +48,7 @@ import level9Img from '../../assets/badges/level-9.png';
import level10Img from '../../assets/badges/level-10.png'; import level10Img from '../../assets/badges/level-10.png';
import { Embed } from '../Embeds/Embed'; import { Embed } from '../Embeds/Embed';
import { buildImageEmbedLink, messageHasImage } from '../../utils/chat'; import { buildImageEmbedLink, messageHasImage } from '../../utils/chat';
import { useTranslation } from 'react-i18next';
const getBadgeImg = (level) => { const getBadgeImg = (level) => {
switch (level?.toString()) { switch (level?.toString()) {
@ -169,12 +170,15 @@ export const MessageItem = memo(
}, [message?.id]); }, [message?.id]);
const theme = useTheme(); const theme = useTheme();
const { t } = useTranslation(['auth', 'core', 'group']);
return ( return (
<> <>
{message?.divide && ( {message?.divide && (
<div className="unread-divider" id="unread-divider-id"> <div className="unread-divider" id="unread-divider-id">
Unread messages below {t('core:message.generic.unread_messages', {
postProcess: 'capitalizeFirst',
})}
</div> </div>
)} )}
@ -262,6 +266,7 @@ export const MessageItem = memo(
{message?.senderName || message?.sender} {message?.senderName || message?.sender}
</Typography> </Typography>
</WrapperUserAction> </WrapperUserAction>
<Box <Box
sx={{ sx={{
display: 'flex', display: 'flex',
@ -279,6 +284,7 @@ export const MessageItem = memo(
<EditIcon /> <EditIcon />
</ButtonBase> </ButtonBase>
)} )}
{!isShowingAsReply && ( {!isShowingAsReply && (
<ButtonBase <ButtonBase
onClick={() => { onClick={() => {
@ -288,6 +294,7 @@ export const MessageItem = memo(
<ReplyIcon /> <ReplyIcon />
</ButtonBase> </ButtonBase>
)} )}
{!isShowingAsReply && handleReaction && ( {!isShowingAsReply && handleReaction && (
<ReactionPicker <ReactionPicker
onReaction={(val) => { onReaction={(val) => {
@ -307,6 +314,7 @@ export const MessageItem = memo(
)} )}
</Box> </Box>
</Box> </Box>
{reply && ( {reply && (
<> <>
<Spacer height="20px" /> <Spacer height="20px" />
@ -333,6 +341,7 @@ export const MessageItem = memo(
flexShrink: 0, flexShrink: 0,
}} }}
/> />
<Box <Box
sx={{ sx={{
padding: '5px', padding: '5px',
@ -344,11 +353,16 @@ export const MessageItem = memo(
fontWeight: 600, fontWeight: 600,
}} }}
> >
Replied to {reply?.senderName || reply?.senderAddress} {t('core:message.generic.replied_to', {
person: reply?.senderName || reply?.senderAddress,
postProcess: 'capitalizeFirst',
})}
</Typography> </Typography>
{reply?.messageText && ( {reply?.messageText && (
<MessageDisplay htmlContent={htmlReply} /> <MessageDisplay htmlContent={htmlReply} />
)} )}
{reply?.decryptedData?.type === 'notification' ? ( {reply?.decryptedData?.type === 'notification' ? (
<MessageDisplay <MessageDisplay
htmlContent={reply.decryptedData?.data?.message} htmlContent={reply.decryptedData?.data?.message}
@ -360,6 +374,7 @@ export const MessageItem = memo(
</Box> </Box>
</> </>
)} )}
{htmlText && <MessageDisplay htmlContent={htmlText} />} {htmlText && <MessageDisplay htmlContent={htmlText} />}
{message?.decryptedData?.type === 'notification' ? ( {message?.decryptedData?.type === 'notification' ? (
@ -454,14 +469,17 @@ export const MessageItem = memo(
> >
<Box sx={{ p: 2 }}> <Box sx={{ p: 2 }}>
<Typography variant="subtitle1" sx={{ marginBottom: 1 }}> <Typography variant="subtitle1" sx={{ marginBottom: 1 }}>
People who reacted with {selectedReaction} {t('core:message.generic.people_reaction', {
reaction: selectedReaction,
postProcess: 'capitalizeFirst',
})}
</Typography> </Typography>
<List <List
sx={{ sx={{
overflow: 'auto',
maxWidth: '300px',
maxHeight: '300px', maxHeight: '300px',
maxWidth: '300px',
overflow: 'auto',
}} }}
> >
{reactions[selectedReaction]?.map((reactionItem) => ( {reactions[selectedReaction]?.map((reactionItem) => (
@ -474,6 +492,7 @@ export const MessageItem = memo(
</ListItem> </ListItem>
))} ))}
</List> </List>
<Button <Button
variant="contained" variant="contained"
color="primary" color="primary"
@ -495,12 +514,17 @@ export const MessageItem = memo(
{reactions[selectedReaction]?.find( {reactions[selectedReaction]?.find(
(item) => item?.sender === myAddress (item) => item?.sender === myAddress
) )
? 'Remove Reaction' ? t('core:action.remove_reaction', {
: 'Add Reaction'} postProcess: 'capitalizeFirst',
})
: t('core:action.add_reaction', {
postProcess: 'capitalizeFirst',
})}
</Button> </Button>
</Box> </Box>
</Popover> </Popover>
)} )}
<Box <Box
sx={{ sx={{
alignItems: 'center', alignItems: 'center',
@ -526,8 +550,12 @@ export const MessageItem = memo(
}} }}
> >
{message?.status === 'failed-permanent' {message?.status === 'failed-permanent'
? 'Failed to update' ? t('core:message.error.update_failed', {
: 'Updating...'} postProcess: 'capitalizeFirst',
})
: t('core:message.generic.updating', {
postProcess: 'capitalizeFirst',
})}
</Typography> </Typography>
) : isTemp ? ( ) : isTemp ? (
<Typography <Typography
@ -538,8 +566,12 @@ export const MessageItem = memo(
}} }}
> >
{message?.status === 'failed-permanent' {message?.status === 'failed-permanent'
? 'Failed to send' ? t('core:message.error.send_failed', {
: 'Sending...'} postProcess: 'capitalizeFirst',
})
: t('core:message.generic.sending', {
postProcess: 'capitalizeFirst',
})}
</Typography> </Typography>
) : ( ) : (
<> <>
@ -552,7 +584,9 @@ export const MessageItem = memo(
fontStyle: 'italic', fontStyle: 'italic',
}} }}
> >
Edited {t('core:message.generic.edited', {
postProcess: 'capitalizeFirst',
})}
</Typography> </Typography>
)} )}
<Typography <Typography
@ -578,6 +612,7 @@ export const MessageItem = memo(
export const ReplyPreview = ({ message, isEdit = false }) => { export const ReplyPreview = ({ message, isEdit = false }) => {
const theme = useTheme(); const theme = useTheme();
const { t } = useTranslation(['auth', 'core', 'group']);
return ( return (
<Box <Box
@ -613,7 +648,9 @@ export const ReplyPreview = ({ message, isEdit = false }) => {
fontWeight: 600, fontWeight: 600,
}} }}
> >
Editing Message {t('core:message.generic.editing_message', {
postProcess: 'capitalizeFirst',
})}
</Typography> </Typography>
) : ( ) : (
<Typography <Typography
@ -622,7 +659,10 @@ export const ReplyPreview = ({ message, isEdit = false }) => {
fontWeight: 600, fontWeight: 600,
}} }}
> >
Replied to {message?.senderName || message?.senderAddress} {t('core:message.generic.replied_to', {
person: message?.senderName || message?.senderAddress,
postProcess: 'capitalizeFirst',
})}
</Typography> </Typography>
)} )}

View File

@ -31,6 +31,8 @@ import { isDisabledEditorEnterAtom } from '../../atoms/global.js';
import { Box, Checkbox, Typography, useTheme } from '@mui/material'; import { Box, Checkbox, Typography, useTheme } from '@mui/material';
import { useAtom } from 'jotai'; import { useAtom } from 'jotai';
import { fileToBase64 } from '../../utils/fileReading/index.js'; import { fileToBase64 } from '../../utils/fileReading/index.js';
import { useTranslation } from 'react-i18next';
import { t } from 'i18next';
function textMatcher(doc, from) { function textMatcher(doc, from) {
const textBeforeCursor = doc.textBetween(0, from, ' ', ' '); const textBeforeCursor = doc.textBetween(0, from, ' ', ' ');
@ -52,6 +54,7 @@ const MenuBar = memo(
const { editor } = useCurrentEditor(); const { editor } = useCurrentEditor();
const fileInputRef = useRef(null); const fileInputRef = useRef(null);
const theme = useTheme(); const theme = useTheme();
const { t } = useTranslation(['auth', 'core', 'group']);
useEffect(() => { useEffect(() => {
if (editor && setEditorRef) { if (editor && setEditorRef) {
@ -143,6 +146,7 @@ const MenuBar = memo(
> >
<FormatBoldIcon /> <FormatBoldIcon />
</IconButton> </IconButton>
<IconButton <IconButton
onClick={() => editor.chain().focus().toggleItalic().run()} onClick={() => editor.chain().focus().toggleItalic().run()}
disabled={!editor.can().chain().focus().toggleItalic().run()} disabled={!editor.can().chain().focus().toggleItalic().run()}
@ -155,6 +159,7 @@ const MenuBar = memo(
> >
<FormatItalicIcon /> <FormatItalicIcon />
</IconButton> </IconButton>
<IconButton <IconButton
onClick={() => editor.chain().focus().toggleStrike().run()} onClick={() => editor.chain().focus().toggleStrike().run()}
disabled={!editor.can().chain().focus().toggleStrike().run()} disabled={!editor.can().chain().focus().toggleStrike().run()}
@ -167,6 +172,7 @@ const MenuBar = memo(
> >
<StrikethroughSIcon /> <StrikethroughSIcon />
</IconButton> </IconButton>
<IconButton <IconButton
onClick={() => editor.chain().focus().toggleCode().run()} onClick={() => editor.chain().focus().toggleCode().run()}
disabled={!editor.can().chain().focus().toggleCode().run()} disabled={!editor.can().chain().focus().toggleCode().run()}
@ -179,6 +185,7 @@ const MenuBar = memo(
> >
<CodeIcon /> <CodeIcon />
</IconButton> </IconButton>
<IconButton <IconButton
onClick={() => editor.chain().focus().unsetAllMarks().run()} onClick={() => editor.chain().focus().unsetAllMarks().run()}
sx={{ sx={{
@ -194,6 +201,7 @@ const MenuBar = memo(
> >
<FormatClearIcon /> <FormatClearIcon />
</IconButton> </IconButton>
<IconButton <IconButton
onClick={() => editor.chain().focus().toggleBulletList().run()} onClick={() => editor.chain().focus().toggleBulletList().run()}
sx={{ sx={{
@ -205,6 +213,7 @@ const MenuBar = memo(
> >
<FormatListBulletedIcon /> <FormatListBulletedIcon />
</IconButton> </IconButton>
<IconButton <IconButton
onClick={() => editor.chain().focus().toggleOrderedList().run()} onClick={() => editor.chain().focus().toggleOrderedList().run()}
sx={{ sx={{
@ -216,6 +225,7 @@ const MenuBar = memo(
> >
<FormatListNumberedIcon /> <FormatListNumberedIcon />
</IconButton> </IconButton>
<IconButton <IconButton
onClick={() => editor.chain().focus().toggleCodeBlock().run()} onClick={() => editor.chain().focus().toggleCodeBlock().run()}
sx={{ sx={{
@ -227,6 +237,7 @@ const MenuBar = memo(
> >
<DeveloperModeIcon /> <DeveloperModeIcon />
</IconButton> </IconButton>
<IconButton <IconButton
onClick={() => editor.chain().focus().toggleBlockquote().run()} onClick={() => editor.chain().focus().toggleBlockquote().run()}
sx={{ sx={{
@ -238,6 +249,7 @@ const MenuBar = memo(
> >
<FormatQuoteIcon /> <FormatQuoteIcon />
</IconButton> </IconButton>
<IconButton <IconButton
onClick={() => editor.chain().focus().setHorizontalRule().run()} onClick={() => editor.chain().focus().setHorizontalRule().run()}
disabled={!editor.can().chain().focus().setHorizontalRule().run()} disabled={!editor.can().chain().focus().setHorizontalRule().run()}
@ -245,6 +257,7 @@ const MenuBar = memo(
> >
<HorizontalRuleIcon /> <HorizontalRuleIcon />
</IconButton> </IconButton>
<IconButton <IconButton
onClick={() => onClick={() =>
editor.chain().focus().toggleHeading({ level: 1 }).run() editor.chain().focus().toggleHeading({ level: 1 }).run()
@ -258,6 +271,7 @@ const MenuBar = memo(
> >
<FormatHeadingIcon fontSize="small" /> <FormatHeadingIcon fontSize="small" />
</IconButton> </IconButton>
<IconButton <IconButton
onClick={() => editor.chain().focus().undo().run()} onClick={() => editor.chain().focus().undo().run()}
disabled={!editor.can().chain().focus().undo().run()} disabled={!editor.can().chain().focus().undo().run()}
@ -265,6 +279,7 @@ const MenuBar = memo(
> >
<UndoIcon /> <UndoIcon />
</IconButton> </IconButton>
<IconButton <IconButton
onClick={() => editor.chain().focus().redo().run()} onClick={() => editor.chain().focus().redo().run()}
disabled={!editor.can().chain().focus().redo().run()} disabled={!editor.can().chain().focus().redo().run()}
@ -272,13 +287,14 @@ const MenuBar = memo(
> >
<RedoIcon /> <RedoIcon />
</IconButton> </IconButton>
{isChat && ( {isChat && (
<Box <Box
sx={{ sx={{
display: 'flex',
alignItems: 'center', alignItems: 'center',
marginLeft: '5px',
cursor: 'pointer', cursor: 'pointer',
display: 'flex',
marginLeft: '5px',
}} }}
onClick={() => { onClick={() => {
setIsDisabledEditorEnter(!isDisabledEditorEnter); setIsDisabledEditorEnter(!isDisabledEditorEnter);
@ -304,10 +320,13 @@ const MenuBar = memo(
color: theme.palette.text.primary, color: theme.palette.text.primary,
}} }}
> >
disable enter {t('core:action.disable_enter', {
postProcess: 'capitalizeFirst',
})}
</Typography> </Typography>
</Box> </Box>
)} )}
{!isChat && ( {!isChat && (
<> <>
<IconButton <IconButton
@ -319,6 +338,7 @@ const MenuBar = memo(
> >
<ImageIcon /> <ImageIcon />
</IconButton> </IconButton>
<input <input
type="file" type="file"
ref={fileInputRef} ref={fileInputRef}
@ -348,7 +368,9 @@ const extensions = [
}, },
}), }),
Placeholder.configure({ Placeholder.configure({
placeholder: 'Start typing here...', placeholder: t('core:action.start_typing', {
postProcess: 'capitalizeFirst',
}),
}), }),
ImageResize, ImageResize,
]; ];
@ -416,12 +438,6 @@ export default ({
setEditorRef(editorInstance); setEditorRef(editorInstance);
}, []); }, []);
// const users = [
// { id: 1, label: 'Alice' },
// { id: 2, label: 'Bob' },
// { id: 3, label: 'Charlie' },
// ];
const users = useMemo(() => { const users = useMemo(() => {
return (membersWithNames || [])?.map((item) => { return (membersWithNames || [])?.map((item) => {
return { return {

View File

@ -2,6 +2,7 @@
"action": { "action": {
"add": "add", "add": "add",
"add_custom_framework": "add custom framework", "add_custom_framework": "add custom framework",
"add_reaction": "add reaction",
"accept": "accept", "accept": "accept",
"access": "access", "access": "access",
"backup_account": "backup account", "backup_account": "backup account",
@ -9,10 +10,12 @@
"cancel": "cancel", "cancel": "cancel",
"cancel_invitation": "cancel invitation", "cancel_invitation": "cancel invitation",
"change": "change", "change": "change",
"change_avatar": "change avatar",
"change_file": "change file", "change_file": "change file",
"change_language": "change language", "change_language": "change language",
"choose": "choose", "choose": "choose",
"choose_file": "choose file", "choose_file": "choose file",
"choose_image": "choose image",
"close": "close", "close": "close",
"close_chat": "close Direct Chat", "close_chat": "close Direct Chat",
"continue": "continue", "continue": "continue",
@ -25,6 +28,7 @@
"choose_name": "choose a name", "choose_name": "choose a name",
"decline": "decline", "decline": "decline",
"decrypt": "decrypt", "decrypt": "decrypt",
"disable_enter": "disable enter",
"download": "download", "download": "download",
"edit": "edit", "edit": "edit",
"enter_name": "enter a name", "enter_name": "enter a name",
@ -54,6 +58,7 @@
"publish_comment": "publish comment", "publish_comment": "publish comment",
"register_name": "register name", "register_name": "register name",
"remove": "remove", "remove": "remove",
"remove_reaction": "remove reaction",
"return_apps_dashboard": "return to Apps Dashboard", "return_apps_dashboard": "return to Apps Dashboard",
"save": "save", "save": "save",
"search": "search", "search": "search",
@ -61,7 +66,9 @@
"select_app_type": "select App Type", "select_app_type": "select App Type",
"select_category": "select Category", "select_category": "select Category",
"select_name_app": "select Name/App", "select_name_app": "select Name/App",
"set_avatar": "set avatar",
"start_minting": "start minting", "start_minting": "start minting",
"start_typing": "start typing here...",
"transfer_qort": "Transfer QORT", "transfer_qort": "Transfer QORT",
"unpin": "unpin", "unpin": "unpin",
"unpin_app": "unpin app", "unpin_app": "unpin app",
@ -113,6 +120,7 @@
"member": "member list" "member": "member list"
}, },
"loading": { "loading": {
"announcements": "announcements",
"generic": "loading...", "generic": "loading...",
"chat": "loading chat... please wait.", "chat": "loading chat... please wait.",
"comments": "loading comments... please wait.", "comments": "loading comments... please wait.",
@ -139,15 +147,20 @@
"publish_app": "unable to publish app", "publish_app": "unable to publish app",
"rating_option": "cannot find rating option", "rating_option": "cannot find rating option",
"save_qdn": "unable to save to QDN", "save_qdn": "unable to save to QDN",
"send_failed": "failed to send",
"unable_encrypt_app": "unable to encrypt app. App not published'", "unable_encrypt_app": "unable to encrypt app. App not published'",
"unable_publish_app": "unable to publish app", "unable_publish_app": "unable to publish app",
"unable_publish_image": "unable to publish image", "unable_publish_image": "unable to publish image",
"unable_rate": "unable to rate" "unable_rate": "unable to rate",
"update_failed": "failed to update"
}, },
"generic": { "generic": {
"avatar_size": "{{ size }} KB max. for GIFS",
"buy_order_request": "the Application <br/><italic>{{hostname}}</italic> <br/><span>is requesting {{count}} buy order</span>", "buy_order_request": "the Application <br/><italic>{{hostname}}</italic> <br/><span>is requesting {{count}} buy order</span>",
"buy_order_request_other": "the Application <br/><italic>{{hostname}}</italic> <br/><span>is requesting {{count}} buy orders</span>", "buy_order_request_other": "the Application <br/><italic>{{hostname}}</italic> <br/><span>is requesting {{count}} buy orders</span>",
"devmode_local_node": "please use your local node for dev mode! Logout and use Local node.", "devmode_local_node": "please use your local node for dev mode! Logout and use Local node.",
"edited": "edited",
"editing_message": "editing message",
"fee_qort": "fee: {{ message }} QORT", "fee_qort": "fee: {{ message }} QORT",
"foreign_fee": "foreign fee: {{ message }}", "foreign_fee": "foreign fee: {{ message }}",
"mentioned": "mentioned", "mentioned": "mentioned",
@ -170,11 +183,13 @@
"password_confirm": "please confirm a password", "password_confirm": "please confirm a password",
"password_enter": "please enter a password", "password_enter": "please enter a password",
"payment_request": "the Application <br/><italic>{{hostname}}</italic> <br/><span>is requesting a payment</span>", "payment_request": "the Application <br/><italic>{{hostname}}</italic> <br/><span>is requesting a payment</span>",
"people_reaction": "people who reacted with {{ reaction }}",
"publish_data": "publish data to Qortal: anything from apps to videos. Fully decentralized!", "publish_data": "publish data to Qortal: anything from apps to videos. Fully decentralized!",
"publishing": "publishing... Please wait.", "publishing": "publishing... Please wait.",
"qdn": "use QDN saving", "qdn": "use QDN saving",
"rating": "rating for {{ service }} {{ name }}", "rating": "rating for {{ service }} {{ name }}",
"register_name": "you need a registered Qortal name to save your pinned apps to QDN.", "register_name": "you need a registered Qortal name to save your pinned apps to QDN.",
"replied_to": "replied to {{ person }}",
"revert_default": "revert to default", "revert_default": "revert to default",
"revert_qdn": "revert to QDN", "revert_qdn": "revert to QDN",
"save_qdn": "save to QDN", "save_qdn": "save to QDN",
@ -182,9 +197,12 @@
"select_file": "please select a file", "select_file": "please select a file",
"select_image": "please select an image for a logo", "select_image": "please select an image for a logo",
"select_zip": "select .zip file containing static content:", "select_zip": "select .zip file containing static content:",
"sending": "sending...",
"settings": "you are using the export/import way of saving settings.", "settings": "you are using the export/import way of saving settings.",
"space_for_admins": "sorry, this space is only for Admins.", "space_for_admins": "sorry, this space is only for Admins.",
"unsaved_changes": "you have unsaved changes to your pinned apps. Save them to QDN." "unread_messages": "unread messages below",
"unsaved_changes": "you have unsaved changes to your pinned apps. Save them to QDN.",
"updating": "updating"
}, },
"question": { "question": {
"logout": "are you sure you would like to logout?", "logout": "are you sure you would like to logout?",
@ -229,6 +247,7 @@
"perform_transaction": "would you like to perform a {{action}} transaction?", "perform_transaction": "would you like to perform a {{action}} transaction?",
"provide_thread": "please provide a thread title", "provide_thread": "please provide a thread title",
"publish_app": "would you like to publish this app?", "publish_app": "would you like to publish this app?",
"publish_avatar": "would you like to publish an avatar?",
"publish_qdn": "would you like to publish your settings to QDN (encrypted)?", "publish_qdn": "would you like to publish your settings to QDN (encrypted)?",
"overwrite_changes": "the app was unable to download your existing QDN-saved pinned apps. Would you like to overwrite those changes?", "overwrite_changes": "the app was unable to download your existing QDN-saved pinned apps. Would you like to overwrite those changes?",
"rate_app": "would you like to rate this app a rating of {{ rate }}?. It will create a POLL tx.", "rate_app": "would you like to rate this app a rating of {{ rate }}?. It will create a POLL tx.",

View File

@ -18,6 +18,8 @@
"make_admin": "make an admin", "make_admin": "make an admin",
"manage_members": "manage members", "manage_members": "manage members",
"promote_group": "promote your group to non-members", "promote_group": "promote your group to non-members",
"publish_announcement": "publish announcement",
"publish_avatar": "publish avatar",
"refetch_page": "refetch page", "refetch_page": "refetch page",
"remove_admin": "remove as admin", "remove_admin": "remove as admin",
"remove_minting_account": "remove minting account", "remove_minting_account": "remove minting account",
@ -57,11 +59,14 @@
"latest_mails": "latest Q-Mails", "latest_mails": "latest Q-Mails",
"message": { "message": {
"generic": { "generic": {
"avatar_publish_fee": "publishing an Avatar requires {{ fee }}",
"avatar_registered_name": "a registered name is required to set an avatar",
"admin_only": "only groups where you are an admin will be shown", "admin_only": "only groups where you are an admin will be shown",
"already_in_group": "you are already in this group!", "already_in_group": "you are already in this group!",
"closed_group": "this is a closed/private group, so you will need to wait until an admin accepts your request", "closed_group": "this is a closed/private group, so you will need to wait until an admin accepts your request",
"descrypt_wallet": "decrypting wallet...", "descrypt_wallet": "decrypting wallet...",
"encryption_key": "the group's first common encryption key is in the process of creation. Please wait a few minutes for it to be retrieved by the network. Checking every 2 minutes...", "encryption_key": "the group's first common encryption key is in the process of creation. Please wait a few minutes for it to be retrieved by the network. Checking every 2 minutes...",
"group_announcement": "group Announcements",
"group_invited_you": "{{group}} has invited you", "group_invited_you": "{{group}} has invited you",
"group_key_created": "first group key created.", "group_key_created": "first group key created.",
"group_member_list_changed": "the group member list has changed. Please re-encrypt the secret key.", "group_member_list_changed": "the group member list has changed. Please re-encrypt the secret key.",
@ -82,6 +87,7 @@
"node_minting": "This node is minting:", "node_minting": "This node is minting:",
"node_minting_account": "node's minting accounts", "node_minting_account": "node's minting accounts",
"node_minting_key": "you currently have a minting key for this account attached to this node", "node_minting_key": "you currently have a minting key for this account attached to this node",
"no_announcement": "no announcements",
"no_display": "nothing to display", "no_display": "nothing to display",
"no_selection": "no group selected", "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.", "not_part_group": "you are not part of the encrypted group of members. Wait until an admin re-encrypts the keys.",