i18next + strftime
i18next + strftime
by Csaba Hellinger
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/i18next/22.0.6/i18next.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dayjs/1.11.12/dayjs.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/liquidjs/10.16.0/liquid.browser.min.js"></script>
CSS
body {
background: #222;
color: #ccc;
font-family: monospace;
line-height: 1.8;
}
JavaScript
// use Liquid as an strftime formatter
const engine = new liquidjs.Liquid()
const strftime = (value, format) => engine.parseAndRenderSync(`{{value | date: '${format}'}}`, { value });
// i18next interpolation formatter for both date formats
const myFormatter = (value, format) => {
// strftime date format
const strftimeFormat = format.match(/^datetime\((.*)\)$/i)?.[1];
if (strftimeFormat) return strftime(value, strftimeFormat)
// relative date format
if (format === 'relativeDate()') {
// just calculating dates for the demo
const days = dayjs().diff(value, 'days');
const relFormat = new Intl.RelativeTimeFormat('en', { style: 'narrow' });
return relFormat.format(-days, 'day')
}
// duration format
if (format === 'duration()') {
return [
Math.floor(value / 3600) || null,
String(Math.floor((value % 3600) / 60)).padStart(2,'0'),
String(value % 60).padStart(2,'0'),
].filter(x => x !== null).join(':');
}
// fall back to the old format
return dayjs(value).format(format);
}
// configure i18next, just as it is on web today
i18next.init({
initImmediate: true,
lng: 'en',
nsSeparator: '',
returnNull: false,
compatibilityJSON: 'v3',
interpolation: {
prefix: '__',
suffix: '__',
format: myFormatter
},
resources: {
'en': {
translation: {
'date.old': "__-today, YYYY/MM/DD__",
'date.new': "__-today, datetime(%Y-%m-%d %H:%M)__",
'relative': "__-releaseDate, relativeDate()__",
'duration': "__-videoDuration, duration()__",
},
},
},
returnedObjectHandler: (key) => key,
});
// tests
const today = new Date();
const translate = (translation, context) => {
document.body.innerText += `${translation} = ${JSON.stringify(i18next.t(translation, context))}\n`;
}
translate('date.new', { today });
translate('relative', { releaseDate: new Date('2024-04-14') });
translate('duration', { videoDuration: 754 });
translate('duration', {...