[FIX #1048] Localize timestamps in chat history
If current locale is xx-YY, looks up xx_YY first, xx then and finally falls back to us. goog.i18n.DateTimeSymbols database is used for localization. Signed-off-by: Eric Dvorsak <eric@dvorsak.fr>
This commit is contained in:
parent
2292d2e500
commit
4a08d2a818
|
@ -6,7 +6,10 @@
|
|||
unparse]]
|
||||
[status-im.i18n :refer [label label-pluralize]]
|
||||
[goog.string :as gstring]
|
||||
goog.string.format))
|
||||
goog.string.format
|
||||
goog.i18n.DateTimeFormat
|
||||
[clojure.string :as s]
|
||||
[goog.object :refer [get]]))
|
||||
|
||||
(defn now []
|
||||
(t/now))
|
||||
|
@ -21,18 +24,47 @@
|
|||
|
||||
(def time-zone-offset (hours (- (/ (.getTimezoneOffset (js/Date.)) 60))))
|
||||
|
||||
(defn to-short-str
|
||||
([ms]
|
||||
(to-short-str ms #(unparse (formatters :hour-minute) %)))
|
||||
([ms today-format-fn]
|
||||
;; xx-YY locale, xx locale or en fallback
|
||||
(defn- locale-symbols [locale-name]
|
||||
(if-let [loc (get goog.i18n (str "DateTimeSymbols_" locale-name))]
|
||||
loc
|
||||
(let [name-first (s/replace (or locale-name "") #"-.*$" "")
|
||||
loc (get goog.i18n (str "DateTimeSymbols_" name-first))]
|
||||
(or loc goog.i18n.DateTimeSymbols_en))))
|
||||
|
||||
;; Closure does not have an enum for datetime formats
|
||||
(def short-date-time-format 10)
|
||||
(def short-date-format 2)
|
||||
|
||||
(defn mk-fmt [locale format]
|
||||
(goog.i18n.DateTimeFormat. format (locale-symbols locale)))
|
||||
|
||||
(def date-time-fmt
|
||||
(mk-fmt status-im.i18n/locale short-date-time-format))
|
||||
(def date-fmt
|
||||
(mk-fmt status-im.i18n/locale short-date-format))
|
||||
|
||||
(defn- to-str [ms old-fmt-fn yesterday-fmt-fn today-fmt-fn]
|
||||
(let [date (from-long ms)
|
||||
local (plus date time-zone-offset)
|
||||
today (t/today-at-midnight)
|
||||
yesterday (plus today (days -1))]
|
||||
(cond
|
||||
(before? date yesterday) (unparse (formatter "dd MMM hh:mm") local)
|
||||
(before? date today) (label :t/datetime-yesterday)
|
||||
:else (today-format-fn local)))))
|
||||
(before? date yesterday) (old-fmt-fn local)
|
||||
(before? date today) (yesterday-fmt-fn local)
|
||||
:else (today-fmt-fn local))))
|
||||
|
||||
(defn to-short-str [ms]
|
||||
(to-str ms
|
||||
#(.format date-fmt %)
|
||||
#(label :t/datetime-yesterday)
|
||||
#(unparse (formatters :hour-minute) %)))
|
||||
|
||||
(defn day-relative [ms]
|
||||
(to-str ms
|
||||
#(.format date-time-fmt %)
|
||||
#(label :t/datetime-yesterday)
|
||||
#(label :t/datetime-today)))
|
||||
|
||||
(defn timestamp->mini-date [ms]
|
||||
(unparse (formatter "dd MMM") (-> ms
|
||||
|
@ -55,10 +87,6 @@
|
|||
from-long
|
||||
(plus time-zone-offset)))))
|
||||
|
||||
(defn day-relative [ms]
|
||||
(when (pos? ms)
|
||||
(to-short-str ms #(label :t/datetime-today))))
|
||||
|
||||
(defn format-time-ago [diff unit]
|
||||
(let [name (label-pluralize diff (:name unit))]
|
||||
(label :t/datetime-ago-format {:ago (label :t/datetime-ago)
|
||||
|
|
|
@ -21,7 +21,8 @@
|
|||
[status-im.test.utils.gfycat.core]
|
||||
[status-im.test.utils.signing-phrase.core]
|
||||
[status-im.test.utils.transducers]
|
||||
[status-im.test.utils.async]))
|
||||
[status-im.test.utils.async]
|
||||
[status-im.test.utils.datetime]))
|
||||
|
||||
(enable-console-print!)
|
||||
|
||||
|
@ -53,4 +54,5 @@
|
|||
'status-im.test.utils.random
|
||||
'status-im.test.utils.gfycat.core
|
||||
'status-im.test.utils.signing-phrase.core
|
||||
'status-im.test.utils.transducers)
|
||||
'status-im.test.utils.transducers
|
||||
'status-im.test.utils.datetime)
|
||||
|
|
|
@ -0,0 +1,51 @@
|
|||
(ns status-im.test.utils.datetime
|
||||
(:require [cljs.test :refer-macros [deftest is]]
|
||||
[status-im.utils.datetime :as d]
|
||||
[cljs-time.core :as t]))
|
||||
|
||||
(defn match [name symbols]
|
||||
(is (identical? (.-dateTimeSymbols_ (d/mk-fmt name d/short-date-format))
|
||||
symbols)))
|
||||
|
||||
(deftest date-time-formatter-test
|
||||
(match "en-US" goog.i18n.DateTimeSymbols_en_US)
|
||||
(match "en-ZZ" goog.i18n.DateTimeSymbols_en)
|
||||
(match "en" goog.i18n.DateTimeSymbols_en)
|
||||
(match "nb-NO" goog.i18n.DateTimeSymbols_nb)
|
||||
(match "nb" goog.i18n.DateTimeSymbols_nb)
|
||||
(match "whoa-WHOA" goog.i18n.DateTimeSymbols_en)
|
||||
(match "whoa" goog.i18n.DateTimeSymbols_en))
|
||||
|
||||
;; 1970-01-01 00:00:00 UTC
|
||||
(def epoch 0)
|
||||
;; 1970-01-03 00:00:00 UTC
|
||||
(def epoch-plus-3d 172800000)
|
||||
|
||||
(deftest to-short-str-today-test
|
||||
(with-redefs [t/*ms-fn* (constantly epoch-plus-3d)
|
||||
d/time-zone-offset (t/period :hours 0)]
|
||||
(is (= (d/to-short-str epoch-plus-3d) "00:00"))))
|
||||
|
||||
(deftest to-short-str-before-yesterday-us-test
|
||||
(with-redefs [t/*ms-fn* (constantly epoch-plus-3d)
|
||||
d/time-zone-offset (t/period :hours 0)
|
||||
d/date-fmt (d/mk-fmt "us" d/short-date-format)]
|
||||
(is (= (d/to-short-str epoch) "Jan 1, 1970"))))
|
||||
|
||||
(deftest to-short-str-before-yesterday-nb-test
|
||||
(with-redefs [d/time-zone-offset (t/period :hours 0)
|
||||
d/date-fmt (d/mk-fmt "nb-NO" d/short-date-format)
|
||||
t/*ms-fn* (constantly epoch-plus-3d)]
|
||||
(is (= (d/to-short-str epoch) "1. jan. 1970"))))
|
||||
|
||||
(deftest day-relative-before-yesterday-us-test
|
||||
(with-redefs [t/*ms-fn* (constantly epoch-plus-3d)
|
||||
d/time-zone-offset (t/period :hours 0)
|
||||
d/date-time-fmt (d/mk-fmt "us" d/short-date-time-format)]
|
||||
(is (= (d/day-relative epoch) "Jan 1, 1970, 12:00:00 AM"))))
|
||||
|
||||
(deftest day-relative-before-yesterday-nb-test
|
||||
(with-redefs [t/*ms-fn* (constantly epoch-plus-3d)
|
||||
d/time-zone-offset (t/period :hours 0)
|
||||
d/date-time-fmt (d/mk-fmt "nb-NO" d/short-date-time-format)]
|
||||
(is (= (d/day-relative epoch) "1. jan. 1970, 00:00:00"))))
|
Loading…
Reference in New Issue