From 531c1bb245b01eb78e142da92ca2f3d46c261579 Mon Sep 17 00:00:00 2001 From: Yamagishi Kazutoshi Date: Thu, 25 May 2017 21:09:25 +0900 Subject: [PATCH] Add localization of datetime in public page (#3296) --- app/javascript/packs/public.js | 173 ++++++++---------- .../stream_entries/_detailed_status.html.haml | 2 +- package.json | 2 +- yarn.lock | 4 - 4 files changed, 81 insertions(+), 100 deletions(-) diff --git a/app/javascript/packs/public.js b/app/javascript/packs/public.js index 38ef7203ec..9f71b6dc5a 100644 --- a/app/javascript/packs/public.js +++ b/app/javascript/packs/public.js @@ -1,111 +1,96 @@ import emojify from 'mastodon/emoji'; +import { getLocale } from 'mastodon/locales'; import { length } from 'stringz'; -import { default as dateFormat } from 'date-fns/format'; -import distanceInWordsStrict from 'date-fns/distance_in_words_strict'; +import IntlRelativeFormat from 'intl-relativeformat'; import { delegate } from 'rails-ujs'; require.context('../images/', true); -const parseFormat = (format) => format.replace(/%(\w)/g, (_, modifier) => { - switch (modifier) { - case '%': - return '%'; - case 'a': - return 'ddd'; - case 'A': - return 'ddd'; - case 'b': - return 'MMM'; - case 'B': - return 'MMMM'; - case 'd': - return 'DD'; - case 'H': - return 'HH'; - case 'I': - return 'hh'; - case 'l': - return 'H'; - case 'm': - return 'M'; - case 'M': - return 'mm'; - case 'p': - return 'A'; - case 'S': - return 'ss'; - case 'w': - return 'd'; - case 'y': - return 'YY'; - case 'Y': - return 'YYYY'; - default: - return `%${modifier}`; - } -}); +const { localeData } = getLocale(); +localeData.forEach(IntlRelativeFormat.__addLocaleData); -document.addEventListener('DOMContentLoaded', () => { - [].forEach.call(document.querySelectorAll('.emojify'), (content) => { - content.innerHTML = emojify(content.innerHTML); +function main() { + const locale = document.documentElement.lang; + const dateTimeFormat = new Intl.DateTimeFormat(locale, { + year: 'numeric', + month: 'long', + day: 'numeric', + hour: 'numeric', + minute: 'numeric', }); + const relativeFormat = new IntlRelativeFormat(locale); - [].forEach.call(document.querySelectorAll('time[data-format]'), (content) => { - const format = parseFormat(content.dataset.format); - const formattedDate = dateFormat(content.getAttribute('datetime'), format); - content.textContent = formattedDate; - }); - - [].forEach.call(document.querySelectorAll('time.time-ago'), (content) => { - const timeAgo = distanceInWordsStrict(new Date(), content.getAttribute('datetime'), { - addSuffix: true, + document.addEventListener('DOMContentLoaded', () => { + [].forEach.call(document.querySelectorAll('.emojify'), (content) => { + content.innerHTML = emojify(content.innerHTML); + }); + + [].forEach.call(document.querySelectorAll('time.formatted'), (content) => { + const datetime = new Date(content.getAttribute('datetime')); + const formattedDate = dateTimeFormat.format(datetime); + content.title = formattedDate; + content.textContent = formattedDate; + }); + + [].forEach.call(document.querySelectorAll('time.time-ago'), (content) => { + const datetime = new Date(content.getAttribute('datetime')); + content.textContent = relativeFormat.format(datetime);; }); - content.textContent = timeAgo; }); -}); -delegate(document, '.video-player video', 'click', ({ target }) => { - if (target.paused) { - target.play(); - } else { - target.pause(); - } -}); + delegate(document, '.video-player video', 'click', ({ target }) => { + if (target.paused) { + target.play(); + } else { + target.pause(); + } + }); -delegate(document, '.media-spoiler', 'click', ({ target }) => { - target.style.display = 'none'; -}); + delegate(document, '.media-spoiler', 'click', ({ target }) => { + target.style.display = 'none'; + }); -delegate(document, '.webapp-btn', 'click', ({ target, button }) => { - if (button !== 0) { - return true; - } - window.location.href = target.href; - return false; -}); + delegate(document, '.webapp-btn', 'click', ({ target, button }) => { + if (button !== 0) { + return true; + } + window.location.href = target.href; + return false; + }); -delegate(document, '.status__content__spoiler-link', 'click', ({ target }) => { - const contentEl = target.parentNode.parentNode.querySelector('.e-content'); - if (contentEl.style.display === 'block') { - contentEl.style.display = 'none'; - target.parentNode.style.marginBottom = 0; - } else { - contentEl.style.display = 'block'; - target.parentNode.style.marginBottom = null; - } - return false; -}); + delegate(document, '.status__content__spoiler-link', 'click', ({ target }) => { + const contentEl = target.parentNode.parentNode.querySelector('.e-content'); + if (contentEl.style.display === 'block') { + contentEl.style.display = 'none'; + target.parentNode.style.marginBottom = 0; + } else { + contentEl.style.display = 'block'; + target.parentNode.style.marginBottom = null; + } + return false; + }); -delegate(document, '.account_display_name', 'input', ({ target }) => { - const nameCounter = document.querySelector('.name-counter'); - if (nameCounter) { - nameCounter.textContent = 30 - length(target.value); - } -}); + delegate(document, '.account_display_name', 'input', ({ target }) => { + const nameCounter = document.querySelector('.name-counter'); + if (nameCounter) { + nameCounter.textContent = 30 - length(target.value); + } + }); -delegate(document, '.account_note', 'input', ({ target }) => { - const noteCounter = document.querySelector('.note-counter'); - if (noteCounter) { - noteCounter.textContent = 160 - length(target.value); - } -}); + delegate(document, '.account_note', 'input', ({ target }) => { + const noteCounter = document.querySelector('.note-counter'); + if (noteCounter) { + noteCounter.textContent = 160 - length(target.value); + } + }); +} + +if (!window.Intl) { + import(/* webpackChunkName: "base_polyfills" */ 'mastodon/base_polyfills').then(() => { + main(); + }).catch(error => { + console.log(error); // eslint-disable-line no-console + }); +} else { + main(); +} diff --git a/app/views/stream_entries/_detailed_status.html.haml b/app/views/stream_entries/_detailed_status.html.haml index d22afb0822..a3e2f766ee 100644 --- a/app/views/stream_entries/_detailed_status.html.haml +++ b/app/views/stream_entries/_detailed_status.html.haml @@ -31,7 +31,7 @@ .detailed-status__meta %data.dt-published{ value: status.created_at.to_time.iso8601 } = link_to TagManager.instance.url_for(status), class: 'detailed-status__datetime u-url u-uid', target: stream_link_target, rel: 'noopener' do - %time{ datetime: status.created_at.iso8601, title: l(status.created_at), data: { format: t('time.formats.default') } }= l(status.created_at) + %time.formatted{ datetime: status.created_at.iso8601, title: l(status.created_at) }= l(status.created_at) ยท - if status.application - if status.application.website.blank? diff --git a/package.json b/package.json index 51136223a3..7a2d1d38c2 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,6 @@ "coffee-script": "^1.12.5", "compression-webpack-plugin": "^0.4.0", "css-loader": "^0.28.0", - "date-fns": "^1.28.4", "dotenv": "^4.0.0", "emojione": "^2.2.7", "emojione-picker": "^2.2.1", @@ -57,6 +56,7 @@ "immutable": "^3.8.1", "intersection-observer": "^0.2.1", "intl": "^1.2.5", + "intl-relativeformat": "^1.3.0", "is-nan": "^1.2.1", "js-yaml": "^3.8.3", "lodash": "^4.17.4", diff --git a/yarn.lock b/yarn.lock index e84c045dae..a45352c538 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2016,10 +2016,6 @@ dashdash@^1.12.0: dependencies: assert-plus "^1.0.0" -date-fns@^1.28.4: - version "1.28.4" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.28.4.tgz#7938aec34ba31fc8bd134d2344bc2e0bbfd95165" - date-now@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/date-now/-/date-now-0.1.4.tgz#eaf439fd4d4848ad74e5cc7dbef200672b9e345b"