Skip to content

Commit

Permalink
Merge pull request #204 from rajnandan1/date-fns
Browse files Browse the repository at this point in the history
feat: i18n for dates
  • Loading branch information
rajnandan1 authored Jan 18, 2025
2 parents 1b1507d + a05de82 commit d54b346
Show file tree
Hide file tree
Showing 28 changed files with 249 additions and 163 deletions.
14 changes: 14 additions & 0 deletions docs/changelogs.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,20 @@ description: Changelogs for Kener

# Changelogs

## v3.0.1

<picture>
<source srcset="https://fonts.gstatic.com/s/e/notoemoji/latest/1f680/512.webp" type="image/webp">
<img src="https://fonts.gstatic.com/s/e/notoemoji/latest/1f680/512.gif" alt="🚀" width="32" height="32">
</picture>

Here are the changes in this release

### Features

- Support for i18n in dates.
- Support of i18n in monitor embeds. Read more [here](/docs/embed#javascript-parameters)

## v3.0.0

<picture>
Expand Down
2 changes: 2 additions & 0 deletions docs/embed.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ You can pass the following parameters to the embed code
- `theme`: You can pass `light` or `dark` theme
- `monitor`: The monitor url
- `bgc`: Background color of the monitor. Only supports hex color codes. DO NOT include the `#` symbol
- `locale`: The locale of the monitor. You can pass the code of the locale you have enabled in your kener settings

Replace `[hostname]` with your kener hostname and `[tag]` with your monitor tag.

Expand Down Expand Up @@ -79,6 +80,7 @@ You can pass the following parameters to the embed code

- `theme`: You can pass `light` or `dark` theme
- `bgc`: Background color of the monitor. Only supports hex color codes. DO NOT include the `#` symbol
- `locale`: The locale of the monitor. You can pass the code of the locale you have enabled in your kener settings

### Demo

Expand Down
16 changes: 16 additions & 0 deletions docs/i18n.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,22 @@ Open `src/lib/locales/locales.json` and add the locale code and the name of the

### Step 3

Open `src/lib/i18n/client.js` and add the locale code to the `locales` array.

```js
import { ru, enUS, hi, de, zhCN, vi, ja, nl, da, fr, ko } from "date-fns/locale";
```

This should be valid for the date-fns library.

Next add a mapping in the `locales` object.

```js
const locales = { ru, en: enUS, hi, dk: de, "zh-CN": zhCN, vi, ja, nl, dk: da, fr, ko };
```

### Step 4

Restart the server and you will see a dropdown in the navbar to select the language.

<div class="note info">
Expand Down
8 changes: 7 additions & 1 deletion docs/roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,16 @@ description: Roadmap for Kener

☐ Introduce sitemap.xml

Migrate from moment to date-fns
~~Migrate from moment to date-fns for status page~~ (moment remains in dashboard. Will remove later)

~~Create Admin UI~~ Released in (3.0.0)

☐ Webhook customization

☐ Monitor Update Screen

☐ i18n for admin dashboard

---

Request a feature or start a discussion [here](https://github.com/rajnandan1/kener/discussions/119)
2 changes: 1 addition & 1 deletion embed.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
Hello world
<script
async
src="http://localhost:3000/embed/monitor-earth/js?theme=light&monitor=http://localhost:3000/embed/monitor-earth"
src="http://localhost:3000/embed/monitor-earth/js?theme=dark&bgc=111&locale=hi&monitor=http://localhost:3000/embed/monitor-earth"
></script>
</body>
</html>
36 changes: 24 additions & 12 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "kener",
"version": "3.0.0",
"version": "3.0.1",
"private": false,
"license": "MIT",
"description": "Kener: An open-source Node.js status page application for real-time service monitoring, incident management, and customizable reporting. Simplify service outage tracking, enhance incident communication, and ensure a seamless user experience.",
Expand Down Expand Up @@ -76,6 +76,7 @@
"bits-ui": "^0.9.9",
"clsx": "^2.0.0",
"croner": "^7.0.5",
"date-fns": "^4.1.0",
"dns2": "^2.1.0",
"dotenv": "^16.4.5",
"express": "^4.18.2",
Expand Down
2 changes: 1 addition & 1 deletion src/kener.css
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,7 @@ textarea::placeholder {
vertical-align: middle;
width: auto;
word-break: keep-all;
z-index: 0;
z-index: 10;
}

@media (min-width: 768px) {
Expand Down
29 changes: 17 additions & 12 deletions src/lib/components/IncidentNew.svelte
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
<script>
import moment from "moment";
import { formatDistanceToNow, formatDistance } from "date-fns";
import * as Accordion from "$lib/components/ui/accordion";
import { l } from "$lib/i18n/client";
import { l, f, fd, fdn } from "$lib/i18n/client";
import { base } from "$app/paths";
export let incident;
export let index;
export let lang;
let startTime = incident.start_date_time;
// let startTime = moment(incident.incident_start_time * 1000).format("MMMM Do YYYY, h:mm:ss a");
let endTime = parseInt(new Date() / 1000);
let nowTime = parseInt(new Date() / 1000);
export let selectedLang = "en";
let startTime = new Date(incident.start_date_time * 1000);
let endTime = new Date();
let nowTime = new Date();
if (incident.end_date_time) {
endTime = incident.end_date_time;
endTime = new Date(incident.end_date_time * 1000);
}
let lastedFor = moment.duration(endTime - startTime, "seconds").humanize();
let startedAt = moment.duration(nowTime - startTime, "seconds").humanize();
const lastedFor = fd(startTime, endTime, selectedLang);
const startedAt = fdn(startTime, selectedLang);
let isFuture = false;
//is future incident
if (nowTime < startTime) {
Expand Down Expand Up @@ -94,7 +97,7 @@
</div>
{/if}
<p class="my-3 text-xs font-semibold uppercase text-muted-foreground">
Updates
{l(lang, "Updates")}
</p>
{#if incident.comments.length > 0}
<ol class="relative mt-2 pl-14">
Expand All @@ -108,8 +111,10 @@
<time
class=" mb-1 text-sm font-medium leading-none text-muted-foreground"
>
{moment(comment.commented_at * 1000).format(
"MMMM Do YYYY, h:mm:ss a"
{f(
new Date(comment.commented_at * 1000),
"MMMM do yyyy, h:mm:ss a",
selectedLang
)}
</time>

Expand Down
32 changes: 18 additions & 14 deletions src/lib/components/monitor.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import { Badge } from "$lib/components/ui/badge";
import { Button } from "$lib/components/ui/button";
import { base } from "$app/paths";
import { sub, startOfDay, getUnixTime } from "date-fns";
import {
Share2,
Link,
Expand All @@ -19,10 +21,9 @@
import { createEventDispatcher } from "svelte";
import { afterUpdate } from "svelte";
import axios from "axios";
import { l, summaryTime, n, ampm } from "$lib/i18n/client";
import { l, summaryTime, f } from "$lib/i18n/client";
import { hoverAction, clickOutsideAction, slide } from "svelte-legos";
import LoaderBoxes from "$lib/components/loaderbox.svelte";
import moment from "moment";
import NumberFlow from "@number-flow/svelte";
import Incident from "$lib/components/IncidentNew.svelte";
Expand All @@ -33,6 +34,8 @@
export let localTz;
export let lang;
export let embed = false;
export let selectedLang = "en";
let _0Day = {};
let _90Day = monitor.pageData._90Day;
let uptime90Day = monitor.pageData.uptime90Day;
Expand Down Expand Up @@ -87,33 +90,31 @@
});
}, 1000 * 0.2);
}
let uptimesRollers = [
{
text: `${l(lang, "90 Days")}`,
startTs: moment().subtract(90, "days").startOf("day").unix(),
startTs: getUnixTime(startOfDay(sub(new Date(), { days: 90 }))),
value: uptime90Day
},
{
text: `${l(lang, "60 Days")}`,
startTs: moment().subtract(59, "days").startOf("day").unix(),
value: uptime90Day
startTs: getUnixTime(startOfDay(sub(new Date(), { days: 59 })))
},
{
text: `${l(lang, "30 Days")}`,
startTs: moment().subtract(29, "days").startOf("day").unix()
startTs: getUnixTime(startOfDay(sub(new Date(), { days: 29 })))
},
{
text: `${l(lang, "14 Days")}`,
startTs: moment().subtract(13, "days").startOf("day").unix()
startTs: getUnixTime(startOfDay(sub(new Date(), { days: 13 })))
},
{
text: `${l(lang, "7 Days")}`,
startTs: moment().subtract(6, "days").startOf("day").unix()
startTs: getUnixTime(startOfDay(sub(new Date(), { days: 6 })))
},
{
text: l(lang, "Today"),
startTs: moment().startOf("day").unix()
startTs: getUnixTime(startOfDay(new Date()))
}
];
Expand Down Expand Up @@ -171,7 +172,7 @@
}
let incidentIDs = incidentObj?.ids || [];
dayUptime = "NA";
dateFetchedFor = moment(new Date(bar.timestamp * 1000)).format("dddd, MMMM Do, YYYY");
dateFetchedFor = f(new Date(bar.timestamp * 1000), "EEEE, MMMM do, yyyy", selectedLang);
showDailyDataModal = true;
loadingDayData = true;
dayIncidentsFull = [];
Expand Down Expand Up @@ -328,9 +329,12 @@
{#if bar.showDetails}
<div class="show-hover absolute text-sm">
<div class="text-{bar.textClass} text-xs font-semibold">
{moment(new Date(bar.timestamp * 1000)).format(
"dddd, MMMM Do, YYYY"
)} -
{f(
new Date(bar.timestamp * 1000),
"EEEE, MMMM do, yyyy",
selectedLang
)}
-
{l(lang, summaryTime(bar.summaryStatus), {
status: bar.summaryStatus,
duration: bar.summaryDuration
Expand Down
3 changes: 2 additions & 1 deletion src/lib/components/shareMenu.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,13 @@
import { base } from "$app/paths";
import { onMount } from "svelte";
import { analyticsEvent } from "$lib/boringOne";
import { l, summaryTime, n, ampm } from "$lib/i18n/client";
import { l, summaryTime } from "$lib/i18n/client";
import * as RadioGroup from "$lib/components/ui/radio-group";
import { Label } from "$lib/components/ui/label";
export let monitor;
export let lang;
export let selectedLang = "en";
let theme = "light";
let copiedLink = false;
let embedType = "js";
Expand Down
55 changes: 28 additions & 27 deletions src/lib/i18n/client.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,31 @@
// @ts-nocheck

import { format, formatDistance, formatDistanceToNow, formatDuration } from "date-fns";
import { ru, enUS, hi, de, zhCN, vi, ja, nl, da, fr, ko } from "date-fns/locale";

const locales = { ru, en: enUS, hi, de, "zh-CN": zhCN, vi, ja, nl, dk: da, fr, ko };

const f = function (date, formatStr, locale) {
return format(date, formatStr, {
locale: locales[locale] || enUS
});
};

const fd = function (start, end, locale) {
return formatDistance(start, end, { addSuffix: false, locale: locales[locale] });
};
const fdn = function (start, locale) {
return formatDistanceToNow(start, { addSuffix: true, locale: locales[locale] });
};
const fdm = function (duration, locale) {
return formatDuration(duration, {
format: ["hours", "minutes"],
zero: false,
delimiter: " ",
locale: locales[locale]
});
};

const l = function (sessionLangMap, key, args = {}) {
const keys = key.split(".");
let obj = sessionLangMap;
Expand Down Expand Up @@ -31,30 +58,4 @@ const summaryTime = function (summaryStatus) {
return "%status for %duration";
};

const n = function (
/** @type {{ numbers: { [x: string]: any; }; }} */ sessionLangMap,
/** @type {string} */ inputString
) {
const translations = sessionLangMap.numbers;
console.trace("translations", translations);
// @ts-ignore
return inputString.replace(
/\d/g,
(/** @type {string | number} */ match) => translations[match] || match
);
};
const ampm = function (
/** @type {{ monitor: { [x: string]: any; }; }} */ sessionLangMap,
/** @type {string} */ inputString
) {
const translations = sessionLangMap.monitor;

// @ts-ignore
let resp = inputString.replace(/(am|pm)/g, function (/** @type {string | number} */ match) {
return translations[match] || match;
});

return resp;
};

export { l, summaryTime, n, ampm };
export { l, summaryTime, f, formatDistance, fd, fdn, fdm };
Loading

0 comments on commit d54b346

Please sign in to comment.