diff --git a/web/public/static/langs/de.json b/web/public/static/langs/de.json
index ef6b3a17..0cfc8a7f 100644
--- a/web/public/static/langs/de.json
+++ b/web/public/static/langs/de.json
@@ -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"
}
diff --git a/web/public/static/langs/en.json b/web/public/static/langs/en.json
index 08250850..78c9c00b 100644
--- a/web/public/static/langs/en.json
+++ b/web/public/static/langs/en.json
@@ -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 website or documentation.",
+ "notifications_loading": "Loading notifications ...",
+ "emoji_picker_search_placeholder": "Search emoji"
}
diff --git a/web/src/components/EmojiPicker.js b/web/src/components/EmojiPicker.js
index 965d8ac8..1392d7e8 100644
--- a/web/src/components/EmojiPicker.js
+++ b/web/src/components/EmojiPicker.js
@@ -9,6 +9,7 @@ import IconButton from "@mui/material/IconButton";
import {Close} from "@mui/icons-material";
import Popper from "@mui/material/Popper";
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)
//
@@ -36,6 +37,7 @@ rawEmojis.forEach(emoji => {
});
const EmojiPicker = (props) => {
+ const { t } = useTranslation();
const open = Boolean(props.anchorEl);
const [search, setSearch] = useState("");
const searchRef = useRef(null);
@@ -71,7 +73,7 @@ const EmojiPicker = (props) => {
inputRef={searchRef}
margin="dense"
size="small"
- placeholder="Search emoji"
+ placeholder={t("emoji_picker_search_placeholder")}
value={search}
onChange={ev => setSearch(ev.target.value)}
type="text"
diff --git a/web/src/components/Navigation.js b/web/src/components/Navigation.js
index 8e408c78..513930b7 100644
--- a/web/src/components/Navigation.js
+++ b/web/src/components/Navigation.js
@@ -97,14 +97,14 @@ const NavList = (props) => {
{!showSubscriptionsList &&
navigate(routes.root)} selected={location.pathname === config.appRoot}>
-
+
}
{showSubscriptionsList &&
<>
- Subscribed topics
+ {t("nav_topics_title")}
navigate(routes.root)} selected={location.pathname === config.appRoot}>
-
+
{
>}
navigate(routes.settings)} selected={location.pathname === routes.settings}>
-
+
openUrl("/docs")}>
-
+
props.onPublishMessageClick()}>
-
+
setSubscribeDialogOpen(true)}>
@@ -181,20 +181,19 @@ const SubscriptionItem = (props) => {
};
const NotificationGrantAlert = (props) => {
+ const { t } = useTranslation();
return (
<>
- Notifications are disabled
-
- Grant your browser permission to display desktop notifications.
-
+ {t("alert_grant_title")}
+ {t("alert_grant_description")}
@@ -203,13 +202,12 @@ const NotificationGrantAlert = (props) => {
};
const NotificationNotSupportedAlert = () => {
+ const { t } = useTranslation();
return (
<>
- Notifications not supported
-
- Notifications are not supported in your browser.
-
+ {t("alert_not_supported_title")}
+ {t("alert_not_supported_description")}
>
diff --git a/web/src/components/Notifications.js b/web/src/components/Notifications.js
index c543de39..eb338803 100644
--- a/web/src/components/Notifications.js
+++ b/web/src/components/Notifications.js
@@ -39,6 +39,7 @@ import priority4 from "../img/priority-4.svg";
import priority5 from "../img/priority-5.svg";
import logoOutline from "../img/ntfy-outline.svg";
import AttachmentIcon from "./AttachmentIcon";
+import {Trans, useTranslation} from "react-i18next";
const Notifications = (props) => {
if (props.mode === "all") {
@@ -72,6 +73,7 @@ const SingleSubscription = (props) => {
}
const NotificationList = (props) => {
+ const { t } = useTranslation();
const pageSize = 20;
const notifications = props.notifications;
const [snackOpen, setSnackOpen] = useState(false);
@@ -112,7 +114,7 @@ const NotificationList = (props) => {
open={snackOpen}
autoHideDuration={3000}
onClose={() => setSnackOpen(false)}
- message="Copied to clipboard"
+ message={t("notifications_copied_to_clipboard")}
/>
@@ -121,6 +123,7 @@ const NotificationList = (props) => {
}
const NotificationItem = (props) => {
+ const { t } = useTranslation();
const notification = props.notification;
const attachment = notification.attachment;
const date = formatShortDateTime(notification.time);
@@ -160,24 +163,24 @@ const NotificationItem = (props) => {
{notification.title && {formatTitle(notification)}}
{autolink(formatMessage(notification))}
{attachment && }
- {tags && Tags: {tags}}
+ {tags && {t("notifications_tags")}: {tags}}
{showActions &&
{showAttachmentActions && <>
-
-
+
+
-
-
+
+
>}
{showClickAction && <>
-
-
+
+
-
-
+
+
>}
}
@@ -208,6 +211,7 @@ const priorityFiles = {
};
const Attachment = (props) => {
+ const { t } = useTranslation();
const attachment = props.attachment;
const expired = 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));
}
if (expires) {
- infos.push(`link expires ${formatShortDateTime(attachment.expires)}`);
+ infos.push(t("notifications_attachment_link_expires", { date: formatShortDateTime(attachment.expires) }));
}
if (expired) {
- infos.push(`download link expired`);
+ infos.push(t("notifications_attachment_link_expired"));
}
const maybeInfoText = (infos.length > 0) ? <>
{infos.join(", ")}> : null;
@@ -326,82 +330,93 @@ const Image = (props) => {
}
const NoNotifications = (props) => {
+ const { t } = useTranslation();
const shortUrl = topicShortUrl(props.subscription.baseUrl, props.subscription.topic);
return (
-
- You haven't received any notifications for this topic yet.
+
+ {t("notifications_none_for_topic_title")}
- To send notifications to this topic, simply PUT or POST to the topic URL.
+ {t("notifications_none_for_topic_description")}
- Example:
+ {t("notifications_example")}:
$ curl -d "Hi" {shortUrl}
- For more detailed instructions, check out the website or
- {" "}documentation.
+
);
};
const NoNotificationsWithoutSubscription = (props) => {
+ const { t } = useTranslation();
const subscription = props.subscriptions[0];
const shortUrl = topicShortUrl(subscription.baseUrl, subscription.topic);
return (
-
- You haven't received any notifications.
+
+ {t("notifications_none_for_any_title")}
- To send notifications to a topic, simply PUT or POST to the topic URL. Here's
- an example using one of your topics.
+ {t("notifications_none_for_any_description")}
- Example:
+ {t("notifications_example")}:
$ curl -d "Hi" {shortUrl}
- For more detailed instructions, check out the website or
- {" "}documentation.
+
);
};
const NoSubscriptions = () => {
+ const { t } = useTranslation();
return (
-
- It looks like you don't have any subscriptions yet.
+
+ {t("notifications_no_subscriptions_title")}
- 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.
+ {t("notifications_no_subscriptions_description")}
- For more information, check out the website or
- {" "}documentation.
+
);
};
+const ForMoreDetails = () => {
+ return (
+ ,
+ docsLink:
+ }}
+ />
+ );
+};
+
const Loading = () => {
+ const { t } = useTranslation();
return (
- Loading notifications ...
+ {t("notifications_loading")}
);