Skip to content

Commit

Permalink
feat: add locale time ago formatting and the local name for the langu…
Browse files Browse the repository at this point in the history
…age in language dropdown
  • Loading branch information
tonyaellie committed Oct 23, 2024
1 parent a961691 commit 1d5b62f
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 4 deletions.
61 changes: 59 additions & 2 deletions frontend/composables/use-formatters.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import { useI18n } from "vue-i18n";
import { type UseTimeAgoMessages, type UseTimeAgoUnitNamesDefault } from "@vueuse/core";

const cache = {
currency: "",
};
Expand Down Expand Up @@ -37,7 +40,61 @@ function ordinalIndicator(num: number) {
}
}

export function fmtDate(value: string | Date, fmt: DateTimeFormat = "human"): string {
export function useLocaleTimeAgo(date: Date) {
const { t } = useI18n();

const I18N_MESSAGES: UseTimeAgoMessages<UseTimeAgoUnitNamesDefault> = {
justNow: t("components.global.date_time.just-now"),
past: (n) => (n.match(/\d/) ? t("components.global.date_time.ago", [n]) : n),
future: (n) => (n.match(/\d/) ? t("components.global.date_time.in", [n]) : n),
month: (n, past) =>
n === 1
? past
? t("components.global.date_time.last-month")
: t("components.global.date_time.next-month")
: `${n} ${t(`components.global.date_time.months`)}`,
year: (n, past) =>
n === 1
? past
? t("components.global.date_time.last-year")
: t("components.global.date_time.next-year")
: `${n} ${t(`components.global.date_time.years`)}`,
day: (n, past) =>
n === 1
? past
? t("components.global.date_time.yesterday")
: t("components.global.date_time.tomorrow")
: `${n} ${t(`components.global.date_time.days`)}`,
week: (n, past) =>
n === 1
? past
? t("components.global.date_time.last-week")
: t("components.global.date_time.next-week")
: `${n} ${t(`components.global.date_time.weeks`)}`,
hour: (n) => `${n} ${
n === 1 ? t("components.global.date_time.hour") : t("components.global.date_time.hours")
}`,
minute: (n) => `${n} ${
n === 1 ? t("components.global.date_time.minute") : t("components.global.date_time.minutes")
}`,
second: (n) => `${n} ${
n === 1
? t("components.global.date_time.second")
: t("components.global.date_time.seconds")
}`,
invalid: "",
};

return useTimeAgo(date, {
fullDateFormatter: (date: Date) => date.toLocaleDateString(),
messages: I18N_MESSAGES,
});
}

export function fmtDate(
value: string | Date,
fmt: DateTimeFormat = "human"
): string {
const months = [
"January",
"February",
Expand All @@ -64,7 +121,7 @@ export function fmtDate(value: string | Date, fmt: DateTimeFormat = "human"): st

switch (fmt) {
case "relative":
return useTimeAgo(dt).value + useDateFormat(dt, " (YYYY-MM-DD)").value;
return useLocaleTimeAgo(dt).value + useDateFormat(dt, " (YYYY-MM-DD)").value;
case "long":
return useDateFormat(dt, "YYYY-MM-DD (dddd)").value;
case "short":
Expand Down
27 changes: 26 additions & 1 deletion frontend/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,30 @@
},
"password_score": {
"password_strength": "Password Strength"
},
"date_time": {
"just-now": "just now",
"ago": "{0} ago",
"in": "in {0}",
"last-month": "last month",
"next-month": "next month",
"months": "months",
"last-year": "last year",
"next-year": "next year",
"years": "years",
"yesterday": "yesterday",
"tomorrow": "tomorrow",
"days": "days",
"last-week": "last week",
"next-week": "next week",
"week": "week",
"weeks": "weeks",
"hour": "hour",
"hours": "hours",
"minute": "minute",
"minutes": "minutes",
"second": "second",
"seconds": "seconds"
}
},
"item": {
Expand Down Expand Up @@ -171,7 +195,8 @@
"manual": "Manual",
"photo": "Photo",
"receipt": "Receipt",
"attachment": "Attachment"
"attachment": "Attachment",
"description": "Description"
},
"labels": {
"no_results": "No Labels Found",
Expand Down
2 changes: 1 addition & 1 deletion frontend/pages/profile.vue
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ import { useI18n } from "vue-i18n";
<select v-model="$i18n.locale" @change="(event) => {setLanguage((event.target as HTMLSelectElement).value )}"
class="select select-bordered">
<option v-for="lang in $i18n.availableLocales" :key="lang" :value="lang">
{{ $t(`languages.${lang}`) }}
{{ $t(`languages.${lang}`) }} ({{ $t(`languages.${lang}`, 1, { locale: lang }) }})
</option>
</select>
</div>
Expand Down

0 comments on commit 1d5b62f

Please sign in to comment.