Przeglądaj źródła

Format datetimes using i18n lang

nimbleghost 2 lat temu
rodzic
commit
311ffc3672

+ 4 - 3
web/src/app/utils.js

@@ -130,13 +130,14 @@ export const hashCode = (s) => {
   return hash;
 };
 
-export const formatShortDateTime = (timestamp) =>
-  new Intl.DateTimeFormat("default", {
+export const formatShortDateTime = (timestamp, language) =>
+  new Intl.DateTimeFormat(language, {
     dateStyle: "short",
     timeStyle: "short",
   }).format(new Date(timestamp * 1000));
 
-export const formatShortDate = (timestamp) => new Intl.DateTimeFormat("default", { dateStyle: "short" }).format(new Date(timestamp * 1000));
+export const formatShortDate = (timestamp, language) =>
+  new Intl.DateTimeFormat(language, { dateStyle: "short" }).format(new Date(timestamp * 1000));
 
 export const formatBytes = (bytes, decimals = 2) => {
   if (bytes === 0) return "0 bytes";

+ 7 - 8
web/src/components/Account.jsx

@@ -39,7 +39,6 @@ import EditIcon from "@mui/icons-material/Edit";
 import { Trans, useTranslation } from "react-i18next";
 import DeleteOutlineIcon from "@mui/icons-material/DeleteOutline";
 import InfoOutlinedIcon from "@mui/icons-material/InfoOutlined";
-import i18n from "i18next";
 import humanizeDuration from "humanize-duration";
 import CelebrationIcon from "@mui/icons-material/Celebration";
 import CloseIcon from "@mui/icons-material/Close";
@@ -224,7 +223,7 @@ const ChangePasswordDialog = (props) => {
 };
 
 const AccountType = () => {
-  const { t } = useTranslation();
+  const { t, i18n } = useTranslation();
   const { account } = useContext(AccountContext);
   const [upgradeDialogKey, setUpgradeDialogKey] = useState(0);
   const [upgradeDialogOpen, setUpgradeDialogOpen] = useState(false);
@@ -283,7 +282,7 @@ const AccountType = () => {
         {account.billing?.paid_until && !account.billing?.cancel_at && (
           <Tooltip
             title={t("account_basics_tier_paid_until", {
-              date: formatShortDate(account.billing?.paid_until),
+              date: formatShortDate(account.billing?.paid_until, i18n.language),
             })}
           >
             <span>
@@ -328,7 +327,7 @@ const AccountType = () => {
       {account.billing?.cancel_at > 0 && (
         <Alert severity="warning" sx={{ mt: 1 }}>
           {t("account_basics_tier_canceled_subscription", {
-            date: formatShortDate(account.billing.cancel_at),
+            date: formatShortDate(account.billing.cancel_at, i18n.language),
           })}
         </Alert>
       )}
@@ -556,7 +555,7 @@ const AddPhoneNumberDialog = (props) => {
 };
 
 const Stats = () => {
-  const { t } = useTranslation();
+  const { t, i18n } = useTranslation();
   const { account } = useContext(AccountContext);
 
   if (!account) {
@@ -798,7 +797,7 @@ const Tokens = () => {
 };
 
 const TokensTable = (props) => {
-  const { t } = useTranslation();
+  const { t, i18n } = useTranslation();
   const [snackOpen, setSnackOpen] = useState(false);
   const [upsertDialogKey, setUpsertDialogKey] = useState(0);
   const [upsertDialogOpen, setUpsertDialogOpen] = useState(false);
@@ -872,11 +871,11 @@ const TokensTable = (props) => {
               {token.token !== session.token() && (token.label || "-")}
             </TableCell>
             <TableCell sx={{ whiteSpace: "nowrap" }} aria-label={t("account_tokens_table_expires_header")}>
-              {token.expires ? formatShortDateTime(token.expires) : <em>{t("account_tokens_table_never_expires")}</em>}
+              {token.expires ? formatShortDateTime(token.expires, i18n.language) : <em>{t("account_tokens_table_never_expires")}</em>}
             </TableCell>
             <TableCell sx={{ whiteSpace: "nowrap" }} aria-label={t("account_tokens_table_last_access_header")}>
               <div style={{ display: "flex", alignItems: "center" }}>
-                <span>{formatShortDateTime(token.last_access)}</span>
+                <span>{formatShortDateTime(token.last_access, i18n.language)}</span>
                 <Tooltip
                   title={t("account_tokens_table_last_origin_tooltip", {
                     ip: token.last_origin,

+ 4 - 4
web/src/components/Notifications.jsx

@@ -160,10 +160,10 @@ const autolink = (s) => {
 };
 
 const NotificationItem = (props) => {
-  const { t } = useTranslation();
+  const { t, i18n } = useTranslation();
   const { notification } = props;
   const { attachment } = notification;
-  const date = formatShortDateTime(notification.time);
+  const date = formatShortDateTime(notification.time, i18n.language);
   const otherTags = unmatchedTags(notification.tags);
   const tags = otherTags.length > 0 ? otherTags.join(", ") : null;
   const handleDelete = async () => {
@@ -277,7 +277,7 @@ const NotificationItem = (props) => {
 };
 
 const Attachment = (props) => {
-  const { t } = useTranslation();
+  const { t, i18n } = useTranslation();
   const { attachment } = props;
   const expired = attachment.expires && attachment.expires < Date.now() / 1000;
   const expires = attachment.expires && attachment.expires > Date.now() / 1000;
@@ -296,7 +296,7 @@ const Attachment = (props) => {
   if (expires) {
     infos.push(
       t("notifications_attachment_link_expires", {
-        date: formatShortDateTime(attachment.expires),
+        date: formatShortDateTime(attachment.expires, i18n.language),
       })
     );
   }

+ 8 - 2
web/src/components/SubscriptionPopup.jsx

@@ -117,10 +117,16 @@ export const SubscriptionPopup = (props) => {
     ])[0];
     const nowSeconds = Math.round(Date.now() / 1000);
     const message = shuffle([
-      `Hello friend, this is a test notification from ntfy web. It's ${formatShortDateTime(nowSeconds)} right now. Is that early or late?`,
+      `Hello friend, this is a test notification from ntfy web. It's ${formatShortDateTime(
+        nowSeconds,
+        "en-US"
+      )} right now. Is that early or late?`,
       `So I heard you like ntfy? If that's true, go to GitHub and star it, or to the Play store and rate it. Thanks! Oh yeah, this is a test notification.`,
       `It's almost like you want to hear what I have to say. I'm not even a machine. I'm just a sentence that Phil typed on a random Thursday.`,
-      `Alright then, it's ${formatShortDateTime(nowSeconds)} already. Boy oh boy, where did the time go? I hope you're alright, friend.`,
+      `Alright then, it's ${formatShortDateTime(
+        nowSeconds,
+        "en-US"
+      )} already. Boy oh boy, where did the time go? I hope you're alright, friend.`,
       `There are nine million bicycles in Beijing That's a fact; It's a thing we can't deny. I wonder if that's true ...`,
       `I'm really excited that you're trying out ntfy. Did you know that there are a few public topics, such as ntfy.sh/stats and ntfy.sh/announcements.`,
       `It's interesting to hear what people use ntfy for. I've heard people talk about using it for so many cool things. What do you use it for?`,

+ 2 - 2
web/src/components/UpgradeDialog.jsx

@@ -62,7 +62,7 @@ const Banner = {
 
 const UpgradeDialog = (props) => {
   const theme = useTheme();
-  const { t } = useTranslation();
+  const { t, i18n } = useTranslation();
   const { account } = useContext(AccountContext); // May be undefined!
   const [error, setError] = useState("");
   const [tiers, setTiers] = useState(null);
@@ -233,7 +233,7 @@ const UpgradeDialog = (props) => {
             <Trans
               i18nKey="account_upgrade_dialog_cancel_warning"
               values={{
-                date: formatShortDate(account?.billing?.paid_until || 0),
+                date: formatShortDate(account?.billing?.paid_until || 0, i18n.language),
               }}
             />
           </Alert>