feat: translate dates and elapsed time

This commit is contained in:
Adrien Marquès 2022-10-12 11:12:29 +02:00
parent 965574d112
commit 8257b30109
Signed by: xdrm-brackets
GPG Key ID: D75243CA236D825E
3 changed files with 77 additions and 49 deletions

View File

@ -21,7 +21,7 @@
<img src='../assets/timeline/project.svg' /> <img src='../assets/timeline/project.svg' />
</div> </div>
<div :key="'name-'+proj.name" class='name'> <div :key="'name-'+proj.name" class='name'>
Created <b>{{ proj.name }}</b> <span>{{ proj.started_at | date_diff }} ago</span> Created <b>{{ proj.name }}</b> <span>{{ elapsed(proj.started_at) }}</span>
</div> </div>
<div :key="'joint-start-'+proj.name" class='joint-start' /> <div :key="'joint-start-'+proj.name" class='joint-start' />
@ -61,7 +61,7 @@
</div> </div>
<div :key="'end-'+proj.name" class='end'> <div :key="'end-'+proj.name" class='end'>
<template v-if='proj.stopped_at != null'> <template v-if='proj.stopped_at != null'>
Project stopped in {{ proj.stopped_at | short_date }} <span>{{ proj.stopped_at | date_diff }} ago</span> Project stopped in {{ proj.stopped_at | short_date }} <span>{{ elapsed(proj.stopped_at) }}</span>
</template> </template>
<template v-else> <template v-else>
Project still active Project still active
@ -84,23 +84,44 @@ import { tID } from '../model/skills';
import * as projects from '../service/projects'; import * as projects from '../service/projects';
import * as scroller from '../service/scroller'; import * as scroller from '../service/scroller';
function pluralize(n: number, s: string): string { interface TimeDiff {
n = Math.floor(Math.abs(n)); diff: number;
const plural = (n > 1); one: string; // singular translation label
plural: string; // plural translation label
}
switch (s) { // returns a TimeDiff from a date. Holds the time elapsed until now in the most
case 'second': // broad unit that is greater than 0.
return plural ? `${n} seconds` : `1 second`; function getTimeDiff(date: Date): TimeDiff {
case 'minute': const minute = 60 * 1000;
return plural ? `${n} minutes` : `1 minute`; const hour = 60 * minute;
case 'day': const day = 24 * hour;
return plural ? `${n} days` : `1 day`; const month = 30 * day;
case 'month': const year = 365 * day;
return plural ? `${n} months` : `1 month`;
case 'year': const now = new Date();
return plural ? `${n} years` : `1 year`; const diff = now.getTime() - date.getTime();
if ( diff < 0 ) {
return {diff: 0, one: 'time.some', plural: 'time.some'};
} }
return '';
if ( diff < minute ) {
return {diff: diff, one: 'time.second', plural: 'time.seconds'};
}
if ( diff < hour ) {
return {diff: diff / minute, one: 'time.minute', plural: 'time.minutes'};
}
if ( diff < day ) {
return {diff: diff / hour, one: 'time.hour', plural: 'time.hours'};
}
if ( diff < month ) {
return {diff: diff / day, one: 'time.day', plural: 'time.days'};
}
if ( diff < year ) {
return {diff: diff / month, one: 'time.month', plural: 'time.months'};
}
return {diff: diff / year, one: 'time.year', plural: 'time.years'};
} }
@Component({ @Component({
@ -109,38 +130,7 @@ function pluralize(n: number, s: string): string {
}, },
filters: { filters: {
short_date(date: Date): string { short_date(date: Date): string {
return date.toLocaleDateString('en-US', { month: 'short', year: 'numeric' }); return date.toLocaleDateString(navigator.language, { month: 'short', year: 'numeric' });
},
date_diff(date: Date): string {
const minute = 60 * 1000;
const hour = 60 * minute;
const day = 24 * hour;
const month = 30 * day;
const year = 365 * day;
const now = new Date();
const diff = now.getTime() - date.getTime();
if ( diff < 0 ) {
return 'sometime';
}
if ( diff < minute ) {
return pluralize(diff, 'second');
}
if ( diff < hour ) {
return pluralize(diff / minute, 'minute');
}
if ( diff < day ) {
return pluralize(diff / hour, 'hour');
}
if ( diff < month ) {
return pluralize(diff / day, 'day');
}
if ( diff < year ) {
return pluralize(diff / month, 'month');
}
return pluralize(diff / year, 'year');
}, },
}, },
}) })
@ -161,6 +151,23 @@ export default class Timeline extends Vue {
document.body.addEventListener('scroll', this.onScroll, { passive: true }); document.body.addEventListener('scroll', this.onScroll, { passive: true });
} }
protected elapsed(date: Date): string {
const fmt = 'time.diff-format';
const td = getTimeDiff(date);
const diff = Math.floor(td.diff);
if( diff == 0 ){
return this.$t(fmt, { elapsed: this.$t(td.one) }).toString();
}
if( diff > 1 ){ // plural
return this.$t(fmt, { elapsed: this.$t(td.plural, { n: diff }) }).toString();
}
// singular
return this.$t(fmt, { elapsed: this.$t(td.one, { n: diff }) }).toString();
}
private onScroll(e: Event) { private onScroll(e: Event) {
const target = e.target as HTMLElement; const target = e.target as HTMLElement;
const header = this.$refs.header as HTMLElement; const header = this.$refs.header as HTMLElement;

View File

@ -72,5 +72,15 @@
"skill.inkscape": "Inkscape", "skill.inkscape": "Inkscape",
"skill.rnd": "R&D", "skill.rnd": "R&D",
"time.diff-format": "{elapsed} ago",
"time.some": "sometime",
"time.second": "{n} second", "time.seconds": "{n} seconds",
"time.minute": "{n} minute", "time.minutes": "{n} minutes",
"time.hour": "{n} hour", "time.hours": "{n} hours",
"time.day": "{n} day", "time.days": "{n} days",
"time.month": "{n} month", "time.months": "{n} months",
"time.year": "{n} year", "time.years": "{n} years",
"end": "" "end": ""
} }

View File

@ -33,5 +33,16 @@
"skill.opti": "Optimization", "skill.opti": "Optimization",
"skill.concurrency": "Programmation Concurrente", "skill.concurrency": "Programmation Concurrente",
"time.diff-format": "il y a {elapsed}",
"time.some": "un moment",
"time.second": "{n} seconde", "time.seconds": "{n} secondes",
"time.minute": "{n} minute", "time.minutes": "{n} minutes",
"time.hour": "{n} heure", "time.hours": "{n} heures",
"time.day": "{n} jour", "time.days": "{n} jours",
"time.month": "{n} mois", "time.months": "{n} mois",
"time.year": "{n} an", "time.years": "{n} ans",
"end": "" "end": ""
} }