mirror of
				https://github.com/binwiederhier/ntfy.git
				synced 2025-10-31 13:02:24 +01:00 
			
		
		
		
	Extracting translation strings
This commit is contained in:
		
							parent
							
								
									0ec9a4c89b
								
							
						
					
					
						commit
						893701c07b
					
				
					 5 changed files with 101 additions and 49 deletions
				
			
		web
|  | @ -1,3 +1,8 @@ | ||||||
| { | { | ||||||
|  |   "nav_topics_title": "Abonnierte Themen", | ||||||
|  |   "nav_button_all_notifications": "Alle Benachrichtigungen", | ||||||
|  |   "nav_button_settings": "Einstellungen", | ||||||
|  |   "nav_button_documentation": "Dokumentation", | ||||||
|  |   "nav_button_publish_message": "Nachricht senden", | ||||||
|   "nav_button_subscribe": "Thema abonnieren" |   "nav_button_subscribe": "Thema abonnieren" | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,3 +1,35 @@ | ||||||
| { | { | ||||||
|   "nav_button_subscribe": "Subscribe to topic" |   "nav_topics_title": "Subscribed topics", | ||||||
|  |   "nav_button_all_notifications": "All notifications", | ||||||
|  |   "nav_button_settings": "Settings", | ||||||
|  |   "nav_button_documentation": "Documentation", | ||||||
|  |   "nav_button_publish_message": "Publish message", | ||||||
|  |   "nav_button_subscribe": "Subscribe to topic", | ||||||
|  |   "alert_grant_title": "Notifications are disabled", | ||||||
|  |   "alert_grant_description": "Grant your browser permission to display desktop notifications.", | ||||||
|  |   "alert_grant_button": "Grant now", | ||||||
|  |   "alert_not_supported_title": "Notifications not supported", | ||||||
|  |   "alert_not_supported_description": "Notifications are not supported in your browser.", | ||||||
|  |   "notifications_copied_to_clipboard": "Copied to clipboard", | ||||||
|  |   "notifications_tags": "Tags", | ||||||
|  |   "notifications_attachment_copy_url_title": "Copy attachment URL to clipboard", | ||||||
|  |   "notifications_attachment_copy_url_button": "Copy URL", | ||||||
|  |   "notifications_attachment_open_title": "Go to {{url}}", | ||||||
|  |   "notifications_attachment_open_button": "Open attachment", | ||||||
|  |   "notifications_attachment_link_expires": "link expires {{date}}", | ||||||
|  |   "notifications_attachment_link_expired": "download link expired", | ||||||
|  |   "notifications_click_copy_url_title": "Copy link URL to clipboard", | ||||||
|  |   "notifications_click_copy_url_button": "Copy link", | ||||||
|  |   "notifications_click_open_title": "Go to {{url}}", | ||||||
|  |   "notifications_click_open_button": "Open link", | ||||||
|  |   "notifications_none_for_topic_title": "You haven't received any notifications for this topic yet.", | ||||||
|  |   "notifications_none_for_topic_description": "To send notifications to this topic, simply PUT or POST to the topic URL.", | ||||||
|  |   "notifications_none_for_any_title": "You haven't received any notifications.", | ||||||
|  |   "notifications_none_for_any_description": "To send notifications to a topic, simply PUT or POST to the topic URL. Here's an example using one of your topics.", | ||||||
|  |   "notifications_no_subscriptions_title": "It looks like you don't have any subscriptions yet.", | ||||||
|  |   "notifications_no_subscriptions_description": "Click the \"Add subscription\" link to create or subscribe to a topic. After that, you can send messages via PUT or POST and you'll receive notifications here.", | ||||||
|  |   "notifications_example": "Example", | ||||||
|  |   "notifications_more_details": "For more information, check out the <websiteLink>website</websiteLink> or <docsLink>documentation</docsLink>.", | ||||||
|  |   "notifications_loading": "Loading notifications ...", | ||||||
|  |   "emoji_picker_search_placeholder": "Search emoji" | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ import IconButton from "@mui/material/IconButton"; | ||||||
| import {Close} from "@mui/icons-material"; | import {Close} from "@mui/icons-material"; | ||||||
| import Popper from "@mui/material/Popper"; | import Popper from "@mui/material/Popper"; | ||||||
| import {splitNoEmpty} from "../app/utils"; | import {splitNoEmpty} from "../app/utils"; | ||||||
|  | import {useTranslation} from "react-i18next"; | ||||||
| 
 | 
 | ||||||
| // Create emoji list by category and create a search base (string with all search words)
 | // Create emoji list by category and create a search base (string with all search words)
 | ||||||
| //
 | //
 | ||||||
|  | @ -36,6 +37,7 @@ rawEmojis.forEach(emoji => { | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| const EmojiPicker = (props) => { | const EmojiPicker = (props) => { | ||||||
|  |     const { t } = useTranslation(); | ||||||
|     const open = Boolean(props.anchorEl); |     const open = Boolean(props.anchorEl); | ||||||
|     const [search, setSearch] = useState(""); |     const [search, setSearch] = useState(""); | ||||||
|     const searchRef = useRef(null); |     const searchRef = useRef(null); | ||||||
|  | @ -71,7 +73,7 @@ const EmojiPicker = (props) => { | ||||||
|                                 inputRef={searchRef} |                                 inputRef={searchRef} | ||||||
|                                 margin="dense" |                                 margin="dense" | ||||||
|                                 size="small" |                                 size="small" | ||||||
|                                 placeholder="Search emoji" |                                 placeholder={t("emoji_picker_search_placeholder")} | ||||||
|                                 value={search} |                                 value={search} | ||||||
|                                 onChange={ev => setSearch(ev.target.value)} |                                 onChange={ev => setSearch(ev.target.value)} | ||||||
|                                 type="text" |                                 type="text" | ||||||
|  |  | ||||||
|  | @ -97,14 +97,14 @@ const NavList = (props) => { | ||||||
|                 {!showSubscriptionsList && |                 {!showSubscriptionsList && | ||||||
|                     <ListItemButton onClick={() => navigate(routes.root)} selected={location.pathname === config.appRoot}> |                     <ListItemButton onClick={() => navigate(routes.root)} selected={location.pathname === config.appRoot}> | ||||||
|                         <ListItemIcon><ChatBubble/></ListItemIcon> |                         <ListItemIcon><ChatBubble/></ListItemIcon> | ||||||
|                         <ListItemText primary="All notifications"/> |                         <ListItemText primary={t("nav_button_all_notifications")}/> | ||||||
|                     </ListItemButton>} |                     </ListItemButton>} | ||||||
|                 {showSubscriptionsList && |                 {showSubscriptionsList && | ||||||
|                     <> |                     <> | ||||||
|                         <ListSubheader>Subscribed topics</ListSubheader> |                         <ListSubheader>{t("nav_topics_title")}</ListSubheader> | ||||||
|                         <ListItemButton onClick={() => navigate(routes.root)} selected={location.pathname === config.appRoot}> |                         <ListItemButton onClick={() => navigate(routes.root)} selected={location.pathname === config.appRoot}> | ||||||
|                             <ListItemIcon><ChatBubble/></ListItemIcon> |                             <ListItemIcon><ChatBubble/></ListItemIcon> | ||||||
|                             <ListItemText primary="All notifications"/> |                             <ListItemText primary={t("nav_button_all_notifications")}/> | ||||||
|                         </ListItemButton> |                         </ListItemButton> | ||||||
|                         <SubscriptionList |                         <SubscriptionList | ||||||
|                             subscriptions={props.subscriptions} |                             subscriptions={props.subscriptions} | ||||||
|  | @ -114,15 +114,15 @@ const NavList = (props) => { | ||||||
|                     </>} |                     </>} | ||||||
|                 <ListItemButton onClick={() => navigate(routes.settings)} selected={location.pathname === routes.settings}> |                 <ListItemButton onClick={() => navigate(routes.settings)} selected={location.pathname === routes.settings}> | ||||||
|                     <ListItemIcon><SettingsIcon/></ListItemIcon> |                     <ListItemIcon><SettingsIcon/></ListItemIcon> | ||||||
|                     <ListItemText primary="Settings"/> |                     <ListItemText primary={t("nav_button_settings")}/> | ||||||
|                 </ListItemButton> |                 </ListItemButton> | ||||||
|                 <ListItemButton onClick={() => openUrl("/docs")}> |                 <ListItemButton onClick={() => openUrl("/docs")}> | ||||||
|                     <ListItemIcon><ArticleIcon/></ListItemIcon> |                     <ListItemIcon><ArticleIcon/></ListItemIcon> | ||||||
|                     <ListItemText primary="Documentation"/> |                     <ListItemText primary={t("nav_button_documentation")}/> | ||||||
|                 </ListItemButton> |                 </ListItemButton> | ||||||
|                 <ListItemButton onClick={() => props.onPublishMessageClick()}> |                 <ListItemButton onClick={() => props.onPublishMessageClick()}> | ||||||
|                     <ListItemIcon><Send/></ListItemIcon> |                     <ListItemIcon><Send/></ListItemIcon> | ||||||
|                     <ListItemText primary="Publish message"/> |                     <ListItemText primary={t("nav_button_publish_message")}/> | ||||||
|                 </ListItemButton> |                 </ListItemButton> | ||||||
|                 <ListItemButton onClick={() => setSubscribeDialogOpen(true)}> |                 <ListItemButton onClick={() => setSubscribeDialogOpen(true)}> | ||||||
|                     <ListItemIcon><AddIcon/></ListItemIcon> |                     <ListItemIcon><AddIcon/></ListItemIcon> | ||||||
|  | @ -181,20 +181,19 @@ const SubscriptionItem = (props) => { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const NotificationGrantAlert = (props) => { | const NotificationGrantAlert = (props) => { | ||||||
|  |     const { t } = useTranslation(); | ||||||
|     return ( |     return ( | ||||||
|         <> |         <> | ||||||
|             <Alert severity="warning" sx={{paddingTop: 2}}> |             <Alert severity="warning" sx={{paddingTop: 2}}> | ||||||
|                 <AlertTitle>Notifications are disabled</AlertTitle> |                 <AlertTitle>{t("alert_grant_title")}</AlertTitle> | ||||||
|                 <Typography gutterBottom> |                 <Typography gutterBottom>{t("alert_grant_description")}</Typography> | ||||||
|                     Grant your browser permission to display desktop notifications. |  | ||||||
|                 </Typography> |  | ||||||
|                 <Button |                 <Button | ||||||
|                     sx={{float: 'right'}} |                     sx={{float: 'right'}} | ||||||
|                     color="inherit" |                     color="inherit" | ||||||
|                     size="small" |                     size="small" | ||||||
|                     onClick={props.onRequestPermissionClick} |                     onClick={props.onRequestPermissionClick} | ||||||
|                 > |                 > | ||||||
|                     Grant now |                     {t("alert_grant_button")} | ||||||
|                 </Button> |                 </Button> | ||||||
|             </Alert> |             </Alert> | ||||||
|             <Divider/> |             <Divider/> | ||||||
|  | @ -203,13 +202,12 @@ const NotificationGrantAlert = (props) => { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const NotificationNotSupportedAlert = () => { | const NotificationNotSupportedAlert = () => { | ||||||
|  |     const { t } = useTranslation(); | ||||||
|     return ( |     return ( | ||||||
|         <> |         <> | ||||||
|             <Alert severity="warning" sx={{paddingTop: 2}}> |             <Alert severity="warning" sx={{paddingTop: 2}}> | ||||||
|                 <AlertTitle>Notifications not supported</AlertTitle> |                 <AlertTitle>{t("alert_not_supported_title")}</AlertTitle> | ||||||
|                 <Typography gutterBottom> |                 <Typography gutterBottom>{t("alert_not_supported_description")}</Typography> | ||||||
|                     Notifications are not supported in your browser. |  | ||||||
|                 </Typography> |  | ||||||
|             </Alert> |             </Alert> | ||||||
|             <Divider/> |             <Divider/> | ||||||
|         </> |         </> | ||||||
|  |  | ||||||
|  | @ -39,6 +39,7 @@ import priority4 from "../img/priority-4.svg"; | ||||||
| import priority5 from "../img/priority-5.svg"; | import priority5 from "../img/priority-5.svg"; | ||||||
| import logoOutline from "../img/ntfy-outline.svg"; | import logoOutline from "../img/ntfy-outline.svg"; | ||||||
| import AttachmentIcon from "./AttachmentIcon"; | import AttachmentIcon from "./AttachmentIcon"; | ||||||
|  | import {Trans, useTranslation} from "react-i18next"; | ||||||
| 
 | 
 | ||||||
| const Notifications = (props) => { | const Notifications = (props) => { | ||||||
|     if (props.mode === "all") { |     if (props.mode === "all") { | ||||||
|  | @ -72,6 +73,7 @@ const SingleSubscription = (props) => { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const NotificationList = (props) => { | const NotificationList = (props) => { | ||||||
|  |     const { t } = useTranslation(); | ||||||
|     const pageSize = 20; |     const pageSize = 20; | ||||||
|     const notifications = props.notifications; |     const notifications = props.notifications; | ||||||
|     const [snackOpen, setSnackOpen] = useState(false); |     const [snackOpen, setSnackOpen] = useState(false); | ||||||
|  | @ -112,7 +114,7 @@ const NotificationList = (props) => { | ||||||
|                         open={snackOpen} |                         open={snackOpen} | ||||||
|                         autoHideDuration={3000} |                         autoHideDuration={3000} | ||||||
|                         onClose={() => setSnackOpen(false)} |                         onClose={() => setSnackOpen(false)} | ||||||
|                         message="Copied to clipboard" |                         message={t("notifications_copied_to_clipboard")} | ||||||
|                     /> |                     /> | ||||||
|                 </Stack> |                 </Stack> | ||||||
|             </Container> |             </Container> | ||||||
|  | @ -121,6 +123,7 @@ const NotificationList = (props) => { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const NotificationItem = (props) => { | const NotificationItem = (props) => { | ||||||
|  |     const { t } = useTranslation(); | ||||||
|     const notification = props.notification; |     const notification = props.notification; | ||||||
|     const attachment = notification.attachment; |     const attachment = notification.attachment; | ||||||
|     const date = formatShortDateTime(notification.time); |     const date = formatShortDateTime(notification.time); | ||||||
|  | @ -160,24 +163,24 @@ const NotificationItem = (props) => { | ||||||
|                 {notification.title && <Typography variant="h5" component="div">{formatTitle(notification)}</Typography>} |                 {notification.title && <Typography variant="h5" component="div">{formatTitle(notification)}</Typography>} | ||||||
|                 <Typography variant="body1" sx={{ whiteSpace: 'pre-line' }}>{autolink(formatMessage(notification))}</Typography> |                 <Typography variant="body1" sx={{ whiteSpace: 'pre-line' }}>{autolink(formatMessage(notification))}</Typography> | ||||||
|                 {attachment && <Attachment attachment={attachment}/>} |                 {attachment && <Attachment attachment={attachment}/>} | ||||||
|                 {tags && <Typography sx={{ fontSize: 14 }} color="text.secondary">Tags: {tags}</Typography>} |                 {tags && <Typography sx={{ fontSize: 14 }} color="text.secondary">{t("notifications_tags")}: {tags}</Typography>} | ||||||
|             </CardContent> |             </CardContent> | ||||||
|             {showActions && |             {showActions && | ||||||
|                 <CardActions sx={{paddingTop: 0}}> |                 <CardActions sx={{paddingTop: 0}}> | ||||||
|                     {showAttachmentActions && <> |                     {showAttachmentActions && <> | ||||||
|                         <Tooltip title="Copy attachment URL to clipboard"> |                         <Tooltip title={t("notifications_attachment_copy_url_title")}> | ||||||
|                             <Button onClick={() => handleCopy(attachment.url)}>Copy URL</Button> |                             <Button onClick={() => handleCopy(attachment.url)}>{t("notifications_attachment_copy_url_button")}</Button> | ||||||
|                         </Tooltip> |                         </Tooltip> | ||||||
|                         <Tooltip title={`Go to ${attachment.url}`}> |                         <Tooltip title={t("notifications_attachment_open_title", { url: attachment.url })}> | ||||||
|                             <Button onClick={() => openUrl(attachment.url)}>Open attachment</Button> |                             <Button onClick={() => openUrl(attachment.url)}>{t("notifications_attachment_open_button")}</Button> | ||||||
|                         </Tooltip> |                         </Tooltip> | ||||||
|                     </>} |                     </>} | ||||||
|                     {showClickAction && <> |                     {showClickAction && <> | ||||||
|                         <Tooltip title="Copy link URL to clipboard"> |                         <Tooltip title={t("notifications_click_copy_url_title")}> | ||||||
|                             <Button onClick={() => handleCopy(notification.click)}>Copy link</Button> |                             <Button onClick={() => handleCopy(notification.click)}>{t("notifications_click_copy_url_button")}</Button> | ||||||
|                         </Tooltip> |                         </Tooltip> | ||||||
|                         <Tooltip title={`Go to ${notification.click}`}> |                         <Tooltip title={t("notifications_click_open_title", { url: notification.click })}> | ||||||
|                             <Button onClick={() => openUrl(notification.click)}>Open link</Button> |                             <Button onClick={() => openUrl(notification.click)}>{t("notifications_click_open_button")}</Button> | ||||||
|                         </Tooltip> |                         </Tooltip> | ||||||
|                     </>} |                     </>} | ||||||
|                 </CardActions>} |                 </CardActions>} | ||||||
|  | @ -208,6 +211,7 @@ const priorityFiles = { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const Attachment = (props) => { | const Attachment = (props) => { | ||||||
|  |     const { t } = useTranslation(); | ||||||
|     const attachment = props.attachment; |     const attachment = props.attachment; | ||||||
|     const expired = attachment.expires && attachment.expires < Date.now()/1000; |     const expired = attachment.expires && attachment.expires < Date.now()/1000; | ||||||
|     const expires = attachment.expires && attachment.expires > Date.now()/1000; |     const expires = attachment.expires && attachment.expires > Date.now()/1000; | ||||||
|  | @ -224,10 +228,10 @@ const Attachment = (props) => { | ||||||
|         infos.push(formatBytes(attachment.size)); |         infos.push(formatBytes(attachment.size)); | ||||||
|     } |     } | ||||||
|     if (expires) { |     if (expires) { | ||||||
|         infos.push(`link expires ${formatShortDateTime(attachment.expires)}`); |         infos.push(t("notifications_attachment_link_expires", { date: formatShortDateTime(attachment.expires) })); | ||||||
|     } |     } | ||||||
|     if (expired) { |     if (expired) { | ||||||
|         infos.push(`download link expired`); |         infos.push(t("notifications_attachment_link_expired")); | ||||||
|     } |     } | ||||||
|     const maybeInfoText = (infos.length > 0) ? <><br/>{infos.join(", ")}</> : null; |     const maybeInfoText = (infos.length > 0) ? <><br/>{infos.join(", ")}</> : null; | ||||||
| 
 | 
 | ||||||
|  | @ -326,82 +330,93 @@ const Image = (props) => { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| const NoNotifications = (props) => { | const NoNotifications = (props) => { | ||||||
|  |     const { t } = useTranslation(); | ||||||
|     const shortUrl = topicShortUrl(props.subscription.baseUrl, props.subscription.topic); |     const shortUrl = topicShortUrl(props.subscription.baseUrl, props.subscription.topic); | ||||||
|     return ( |     return ( | ||||||
|         <VerticallyCenteredContainer maxWidth="xs"> |         <VerticallyCenteredContainer maxWidth="xs"> | ||||||
|             <Typography variant="h5" align="center" sx={{ paddingBottom: 1 }}> |             <Typography variant="h5" align="center" sx={{ paddingBottom: 1 }}> | ||||||
|                 <img src={logoOutline} height="64" width="64" alt="No notifications"/><br /> |                 <img src={logoOutline} height="64" width="64"/><br /> | ||||||
|                 You haven't received any notifications for this topic yet. |                 {t("notifications_none_for_topic_title")} | ||||||
|             </Typography> |             </Typography> | ||||||
|             <Paragraph> |             <Paragraph> | ||||||
|                 To send notifications to this topic, simply PUT or POST to the topic URL. |                 {t("notifications_none_for_topic_description")} | ||||||
|             </Paragraph> |             </Paragraph> | ||||||
|             <Paragraph> |             <Paragraph> | ||||||
|                 Example:<br/> |                 {t("notifications_example")}:<br/> | ||||||
|                 <tt> |                 <tt> | ||||||
|                     $ curl -d "Hi" {shortUrl} |                     $ curl -d "Hi" {shortUrl} | ||||||
|                 </tt> |                 </tt> | ||||||
|             </Paragraph> |             </Paragraph> | ||||||
|             <Paragraph> |             <Paragraph> | ||||||
|                 For more detailed instructions, check out the <Link href="https://ntfy.sh" target="_blank" rel="noopener">website</Link> or |                 <ForMoreDetails/> | ||||||
|                 {" "}<Link href="https://ntfy.sh/docs" target="_blank" rel="noopener">documentation</Link>. |  | ||||||
|             </Paragraph> |             </Paragraph> | ||||||
|         </VerticallyCenteredContainer> |         </VerticallyCenteredContainer> | ||||||
|     ); |     ); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const NoNotificationsWithoutSubscription = (props) => { | const NoNotificationsWithoutSubscription = (props) => { | ||||||
|  |     const { t } = useTranslation(); | ||||||
|     const subscription = props.subscriptions[0]; |     const subscription = props.subscriptions[0]; | ||||||
|     const shortUrl = topicShortUrl(subscription.baseUrl, subscription.topic); |     const shortUrl = topicShortUrl(subscription.baseUrl, subscription.topic); | ||||||
|     return ( |     return ( | ||||||
|         <VerticallyCenteredContainer maxWidth="xs"> |         <VerticallyCenteredContainer maxWidth="xs"> | ||||||
|             <Typography variant="h5" align="center" sx={{ paddingBottom: 1 }}> |             <Typography variant="h5" align="center" sx={{ paddingBottom: 1 }}> | ||||||
|                 <img src={logoOutline} height="64" width="64" alt="No notifications"/><br /> |                 <img src={logoOutline} height="64" width="64"/><br /> | ||||||
|                 You haven't received any notifications. |                 {t("notifications_none_for_any_title")} | ||||||
|             </Typography> |             </Typography> | ||||||
|             <Paragraph> |             <Paragraph> | ||||||
|                 To send notifications to a topic, simply PUT or POST to the topic URL. Here's |                 {t("notifications_none_for_any_description")} | ||||||
|                 an example using one of your topics. |  | ||||||
|             </Paragraph> |             </Paragraph> | ||||||
|             <Paragraph> |             <Paragraph> | ||||||
|                 Example:<br/> |                 {t("notifications_example")}:<br/> | ||||||
|                 <tt> |                 <tt> | ||||||
|                     $ curl -d "Hi" {shortUrl} |                     $ curl -d "Hi" {shortUrl} | ||||||
|                 </tt> |                 </tt> | ||||||
|             </Paragraph> |             </Paragraph> | ||||||
|             <Paragraph> |             <Paragraph> | ||||||
|                 For more detailed instructions, check out the <Link href="https://ntfy.sh" target="_blank" rel="noopener">website</Link> or |                 <ForMoreDetails/> | ||||||
|                 {" "}<Link href="https://ntfy.sh/docs" target="_blank" rel="noopener">documentation</Link>. |  | ||||||
|             </Paragraph> |             </Paragraph> | ||||||
|         </VerticallyCenteredContainer> |         </VerticallyCenteredContainer> | ||||||
|     ); |     ); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const NoSubscriptions = () => { | const NoSubscriptions = () => { | ||||||
|  |     const { t } = useTranslation(); | ||||||
|     return ( |     return ( | ||||||
|         <VerticallyCenteredContainer maxWidth="xs"> |         <VerticallyCenteredContainer maxWidth="xs"> | ||||||
|             <Typography variant="h5" align="center" sx={{ paddingBottom: 1 }}> |             <Typography variant="h5" align="center" sx={{ paddingBottom: 1 }}> | ||||||
|                 <img src={logoOutline} height="64" width="64" alt="No topics"/><br /> |                 <img src={logoOutline} height="64" width="64"/><br /> | ||||||
|                 It looks like you don't have any subscriptions yet. |                 {t("notifications_no_subscriptions_title")} | ||||||
|             </Typography> |             </Typography> | ||||||
|             <Paragraph> |             <Paragraph> | ||||||
|                 Click the "Add subscription" link to create or subscribe to a topic. After that, you can send messages |                 {t("notifications_no_subscriptions_description")} | ||||||
|                 via PUT or POST and you'll receive notifications here. |  | ||||||
|             </Paragraph> |             </Paragraph> | ||||||
|             <Paragraph> |             <Paragraph> | ||||||
|                 For more information, check out the <Link href="https://ntfy.sh" target="_blank" rel="noopener">website</Link> or |                 <ForMoreDetails/> | ||||||
|                 {" "}<Link href="https://ntfy.sh/docs" target="_blank" rel="noopener">documentation</Link>. |  | ||||||
|             </Paragraph> |             </Paragraph> | ||||||
|         </VerticallyCenteredContainer> |         </VerticallyCenteredContainer> | ||||||
|     ); |     ); | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | const ForMoreDetails = () => { | ||||||
|  |     return ( | ||||||
|  |         <Trans | ||||||
|  |             i18nKey="notifications_more_details" | ||||||
|  |             components={{ | ||||||
|  |                 websiteLink: <Link href="https://ntfy.sh" target="_blank" rel="noopener"/>, | ||||||
|  |                 docsLink: <Link href="https://ntfy.sh/docs" target="_blank" rel="noopener"/> | ||||||
|  |             }} | ||||||
|  |         /> | ||||||
|  |     ); | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| const Loading = () => { | const Loading = () => { | ||||||
|  |     const { t } = useTranslation(); | ||||||
|     return ( |     return ( | ||||||
|         <VerticallyCenteredContainer> |         <VerticallyCenteredContainer> | ||||||
|             <Typography variant="h5" color="text.secondary" align="center" sx={{ paddingBottom: 1 }}> |             <Typography variant="h5" color="text.secondary" align="center" sx={{ paddingBottom: 1 }}> | ||||||
|                 <CircularProgress disableShrink sx={{marginBottom: 1}}/><br /> |                 <CircularProgress disableShrink sx={{marginBottom: 1}}/><br /> | ||||||
|                 Loading notifications ... |                 {t("notifications_loading")} | ||||||
|             </Typography> |             </Typography> | ||||||
|         </VerticallyCenteredContainer> |         </VerticallyCenteredContainer> | ||||||
|     ); |     ); | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Philipp Heckel
						Philipp Heckel