From 4a5c053bf7f3da91728acfb980436a396becc359 Mon Sep 17 00:00:00 2001 From: vartija Date: Mon, 21 Aug 2023 12:56:46 +0300 Subject: [PATCH 1/2] Add i18n to multi-select component --- src/re_com/multi_select.cljs | 76 +++++++++++++++++++++++++---------- src/re_demo/multi_select.cljs | 22 +++++++++- 2 files changed, 75 insertions(+), 23 deletions(-) diff --git a/src/re_com/multi_select.cljs b/src/re_com/multi_select.cljs index 9d7e491f..4b7a9868 100644 --- a/src/re_com/multi_select.cljs +++ b/src/re_com/multi_select.cljs @@ -6,6 +6,7 @@ [clojure.set :as set] [clojure.string :as string] [goog.string :as gstring] + [cljs.pprint :as pprint] [re-com.config :refer [include-args-desc?]] [re-com.debug :refer [->attr]] [re-com.input-text :refer [input-text]] @@ -145,7 +146,7 @@ (defn list-box "Render a list box which can be a single list or a grouped list" - [& {:keys [items id-fn label-fn group-fn disabled? *current-item-id group-heading-selected? click-callback double-click-callback filter-choices-text src]}] + [& {:keys [items id-fn label-fn group-fn disabled? *current-item-id group-heading-selected? click-callback double-click-callback filter-choices-text i18n src]}] (let [[group-names group-item-lists] (items-with-group-headings items group-fn id-fn) has-group-names? (not (and (nil? (:group (first group-names))) (= 1 (count group-item-lists)))) ;; if 0 or 1 group names, no headings to display make-list-item (fn [item] @@ -185,7 +186,7 @@ (make-items (first group-item-lists))) (if (string/blank? filter-choices-text) "" - [:li.no-results (str "No results match \"" filter-choices-text "\"")]))]])) + [:li.no-results (gstring/format (get i18n :no-results-match "No results match \"%s\"") filter-choices-text)]))]])) ;;-------------------------------------------------------------------------------------------------- @@ -250,7 +251,9 @@ {:name :disabled? :required false :default false :type "boolean | r/atom" :description "if true, no user selection is allowed"} {:name :filter-box? :required false :default false :type "boolean | r/atom" :description "if true, a filter text field is placed at the bottom of the component"} {:name :regex-filter? :required false :default false :type "boolean | r/atom" :description "if true, the filter text field will support JavaScript regular expressions. If false, just plain text"} - {:name :placeholder :required false :type "string" :validate-fn string? :description "background text when no selection"} ;; TODO this is actually broken, does not display background text + {:name :placeholder :required false :type "string" :validate-fn string? :description "background text when no selection"} ;; TODO this is actually broken, does not display background text (currently shows in filter box so move that functionality to i18n if changed) + {:name :i18n :required false :type "map" :description [:span "internationalization map with optional keys e.g." [:code {:style {:white-space "pre-wrap"}} (with-out-str (pprint/pprint (sorted-map :no-results-match "No results match \"%s\"" :item-singular "%s item" :item-plural "%s items" :showing-of "showing %s of %s" :filter-result-singular "Found %s match containing %s" :filter-result-plural "Found %s matches containing %s" :include-all "include %s" :include "include %s" :exclude "exclude %s" :exclude-all "exclude %s")))] + "In case translation doesn't fit to button box use " [:code ":parts"] "e.g." [:code "{:include-all-button {:style {:width \"150px\"}}}"] " to adjust"]} {:name :width :required false :default "100%" :type "string" :validate-fn string? :description "the CSS width. e.g.: \"500px\" or \"20em\""} {:name :height :required false :type "string" :validate-fn string? :description "the specific height of the component"} {:name :max-height :required false :type "string" :validate-fn string? :description "the maximum height of the component"} @@ -295,7 +298,7 @@ :font-size 11}] (fn multi-select-render [& {:keys [choices model required? max-selected-items left-label right-label on-change disabled? filter-box? regex-filter? - placeholder width height max-height tab-index id-fn label-fn group-fn sort-fn class style attr parts src] + placeholder i18n width height max-height tab-index id-fn label-fn group-fn sort-fn class style attr parts src] :or {id-fn :id label-fn :label group-fn :group @@ -461,8 +464,10 @@ (get-in parts [:left-label-item-count :style]))} (get-in parts [:left-label-item-count :attr])) (if (string/blank? @*filter-choices-text) - (rc.util/pluralize potential-count "item") - (str "showing " (count filtered-choices) " of " potential-count))]]] + (if (= 1 potential-count) + (gstring/format (get i18n :item-singular "%s item") potential-count) + (gstring/format (get i18n :item-plural "%s items") potential-count)) + (gstring/format (get i18n :showing-of "showing %s of %s") (count filtered-choices) potential-count))]]] left-label)) [list-box :src (at) @@ -476,7 +481,8 @@ :group-heading-selected? @*choice-group-heading-selected? :click-callback choice-click :double-click-callback include-click - :filter-choices-text @*filter-choices-text] + :filter-choices-text @*filter-choices-text + :i18n i18n] (when filter-box? [:<> [box/gap @@ -497,7 +503,13 @@ :style (merge {:font-size "smaller"} (get-in parts [:left-filter-result-count :style])) :attr (get-in parts [:left-filter-result-count :attr]) - :label [:span "Found " (rc.util/pluralize (count filtered-choices) "match" "matches") " containing " [:strong @*filter-choices-text]]])])]] + :label (let [filter-result-key (if (= 1 (count filtered-choices)) + (get i18n :filter-result-singular "Found %s match containing %s") + (get i18n :filter-result-plural "Found %s matches containing %s")) + [start middle end] (clojure.string/split filter-result-key #"%s")] + [:span (gstring/format (str start "%s" middle) (count filtered-choices)) + [:strong (gstring/format "%s" @*filter-choices-text)] + end])])])]] [box/v-box :src (at) @@ -525,7 +537,10 @@ [:i {:class (str "zmdi zmdi-hc-fw-rc zmdi-fast-forward")}] [:span {:style {:position "relative" :top "-1px"}} - (str " include " (if (string/blank? @*filter-choices-text) potential-count (count filtered-choices)))]] + (gstring/format (str " " (get i18n :include-all "include %s")) + (if (string/blank? @*filter-choices-text) + potential-count + (count filtered-choices)))]] :disabled? (or disabled? (zero? (count filtered-choices))) :style (merge button-style (get-in parts [:include-all-button :style])) @@ -538,10 +553,12 @@ [:i {:class (str "zmdi zmdi-hc-fw-rc zmdi-play")}] [:span {:style {:position "relative" :top "-1px"}} - (str " include " (when @*choice-group-heading-selected? - (->> filtered-choices ;; TODO: Inefficient - (filter (fn [item] (= (first @*current-choice-id) (group-fn item)))) - count)))]] + (gstring/format (str " " (get i18n :include "include %s")) + (if @*choice-group-heading-selected? + (->> filtered-choices ;; TODO: Inefficient + (filter (fn [item] (= (first @*current-choice-id) (group-fn item)))) + count) + ""))]] :disabled? (or disabled? (not @*current-choice-id)) :style (merge button-style (get-in parts [:include-selected-button :style])) @@ -554,10 +571,12 @@ [:i {:class (str "zmdi zmdi-hc-fw-rc zmdi-play zmdi-hc-rotate-180")}] [:span {:style {:position "relative" :top "-1px"}} - (str " exclude " (when @*selection-group-heading-selected? - (->> filtered-selections ;; TODO: Inefficient - (filter (fn [item] (= (first @*current-selection-id) (group-fn item)))) - count)))]] + (gstring/format (str " " (get i18n :exclude "exclude %s")) + (if @*selection-group-heading-selected? + (->> filtered-selections ;; TODO: Inefficient + (filter (fn [item] (= (first @*current-selection-id) (group-fn item)))) + count) + ""))]] :disabled? (or disabled? (not excludable?)) :style (merge button-style (get-in parts [:exclude-selected-button :style])) @@ -570,7 +589,10 @@ [:i {:class (str "zmdi zmdi-hc-fw-rc zmdi-fast-rewind")}] [:span {:style {:position "relative" :top "-1px"}} - (str " exclude " (if (string/blank? @*filter-selections-text) chosen-count (count filtered-selections)))]] + (gstring/format (str " " (get i18n :exclude-all "exclude %s")) + (if (string/blank? @*filter-selections-text) + chosen-count + (count filtered-selections)))]] :disabled? (or disabled? (zero? (count filtered-selections)) (not (> (count @*internal-model) (if required? 1 0)))) :style (merge button-style (get-in parts [:exclude-all-button :style])) @@ -632,8 +654,11 @@ (get-in parts [:right-label-item-count :style]))} (get-in parts [:right-label-item-count :attr])) (if (string/blank? @*filter-selections-text) - (rc.util/pluralize chosen-count "item") - (str "showing " (count filtered-selections) " of " chosen-count))]]] + (if (string/blank? @*filter-choices-text) + (if (= 1 chosen-count) + (gstring/format (get i18n :item-singular "%s item") chosen-count) + (gstring/format (get i18n :item-plural "%s items") chosen-count)) + (gstring/format (get i18n :showing-of "showing %s of %s") (count filtered-selections) chosen-count)))]]] right-label)) [list-box :src (at) @@ -649,7 +674,8 @@ :group-heading-selected? @*selection-group-heading-selected? :click-callback selection-click :double-click-callback exclude-click - :filter-choices-text @*filter-selections-text] + :filter-choices-text @*filter-selections-text + :i18n i18n] (when filter-box? [:<> [box/gap @@ -666,7 +692,13 @@ :style {:font-size "smaller"}] [text/label :src (at) - :label [:span "Found " (rc.util/pluralize (count filtered-selections) "match" "matches") " containing " [:strong @*filter-selections-text]] + :label (let [filter-result-key (if (= 1 (count filtered-selections)) + (get i18n :filter-result-singular "Found %s match containing %s") + (get i18n :filter-result-plural "Found %s matches containing %s")) + [start middle end] (clojure.string/split filter-result-key #"%s")] + [:span (gstring/format (str start "%s" middle) (count filtered-selections)) + [:strong (gstring/format "%s" @*filter-selections-text)] + end]) :class (str "rc-multi-select-right-filter-result-count " (get-in parts [:right-filter-result-count :class])) :style (merge {:font-size "smaller"} (get-in parts [:right-filter-result-count :style])) :attr (get-in parts [:right-filter-result-count :attr])])])]]]]])))))) diff --git a/src/re_demo/multi_select.cljs b/src/re_demo/multi_select.cljs index 66739519..30a60182 100644 --- a/src/re_demo/multi_select.cljs +++ b/src/re_demo/multi_select.cljs @@ -14,6 +14,7 @@ (def disabled? (reagent/atom false)) (def required? (reagent/atom false)) (def filter-box? (reagent/atom false)) +(def i18n? (reagent/atom false)) (def regex-filter? (reagent/atom false)) (def choices [{:id :tesla-model-s :label "Model S" :group "Tesla"} @@ -63,6 +64,16 @@ :left-label "Car Choices" :right-label "Cars Selected" :placeholder "Select some cars." + :i18n (when @i18n? {:no-results-match "Ei sopivaa tulosta haulle \"%s\"" + :item-singular "%s osio" + :item-plural "%s osiota" + :showing-of "näytetään %s %s:sta" + :filter-result-singular "Löydetty %s tulos sisältäen %s" + :filter-result-plural "Löydetty %s tulosta sisältäen %s" + :include-all "sisällytä %s" + :include "sisällytä %s" + :exclude "sulje pois %s" + :exclude-all "sulje pois %s"}) :disabled? disabled? :required? required? :filter-box? filter-box? @@ -132,7 +143,16 @@ :align :start :child [:code ":regex-filter?"]] :model regex-filter? - :on-change #(reset! regex-filter? %)])]]]] + :on-change #(reset! regex-filter? %)])]] + [v-box :src (at) + :gap "3px" + :children [[checkbox + :src (at) + :label [box :src (at) + :align :start + :child [:code ":i18n?"]] + :model i18n? + :on-change #(reset! i18n? %)]]]]] [v-box :src (at) From e2336a1f4a7a24707a9089ddffeba9a8cf9ca3dd Mon Sep 17 00:00:00 2001 From: vartija Date: Tue, 22 Aug 2023 18:08:19 +0300 Subject: [PATCH 2/2] Refactor to util. Remove no-space chars from util. --- src/re_com/multi_select.cljs | 67 +++++++++++++++-------------------- src/re_com/util.cljs | 42 +++++++++++++++++----- src/re_demo/multi_select.cljs | 2 +- 3 files changed, 62 insertions(+), 49 deletions(-) diff --git a/src/re_com/multi_select.cljs b/src/re_com/multi_select.cljs index 4b7a9868..f62b5a0b 100644 --- a/src/re_com/multi_select.cljs +++ b/src/re_com/multi_select.cljs @@ -186,7 +186,7 @@ (make-items (first group-item-lists))) (if (string/blank? filter-choices-text) "" - [:li.no-results (gstring/format (get i18n :no-results-match "No results match \"%s\"") filter-choices-text)]))]])) + [:li.no-results (rc.util/translate i18n :no-results-match "No results match \"%s\"" filter-choices-text)]))]])) ;;-------------------------------------------------------------------------------------------------- @@ -251,7 +251,7 @@ {:name :disabled? :required false :default false :type "boolean | r/atom" :description "if true, no user selection is allowed"} {:name :filter-box? :required false :default false :type "boolean | r/atom" :description "if true, a filter text field is placed at the bottom of the component"} {:name :regex-filter? :required false :default false :type "boolean | r/atom" :description "if true, the filter text field will support JavaScript regular expressions. If false, just plain text"} - {:name :placeholder :required false :type "string" :validate-fn string? :description "background text when no selection"} ;; TODO this is actually broken, does not display background text (currently shows in filter box so move that functionality to i18n if changed) + {:name :placeholder :required false :type "string" :validate-fn string? :description "background text when no selection"} ;; TODO this is actually broken, does not display background text (currently shows in filter box so consider moving that functionality to i18n if changed) {:name :i18n :required false :type "map" :description [:span "internationalization map with optional keys e.g." [:code {:style {:white-space "pre-wrap"}} (with-out-str (pprint/pprint (sorted-map :no-results-match "No results match \"%s\"" :item-singular "%s item" :item-plural "%s items" :showing-of "showing %s of %s" :filter-result-singular "Found %s match containing %s" :filter-result-plural "Found %s matches containing %s" :include-all "include %s" :include "include %s" :exclude "exclude %s" :exclude-all "exclude %s")))] "In case translation doesn't fit to button box use " [:code ":parts"] "e.g." [:code "{:include-all-button {:style {:width \"150px\"}}}"] " to adjust"]} {:name :width :required false :default "100%" :type "string" :validate-fn string? :description "the CSS width. e.g.: \"500px\" or \"20em\""} @@ -464,10 +464,8 @@ (get-in parts [:left-label-item-count :style]))} (get-in parts [:left-label-item-count :attr])) (if (string/blank? @*filter-choices-text) - (if (= 1 potential-count) - (gstring/format (get i18n :item-singular "%s item") potential-count) - (gstring/format (get i18n :item-plural "%s items") potential-count)) - (gstring/format (get i18n :showing-of "showing %s of %s") (count filtered-choices) potential-count))]]] + (rc.util/translate-plural i18n :item "%s item" "%s items" potential-count potential-count) + (rc.util/translate i18n :showing-of "showing %s of %s" (count filtered-choices) potential-count))]]] left-label)) [list-box :src (at) @@ -503,10 +501,7 @@ :style (merge {:font-size "smaller"} (get-in parts [:left-filter-result-count :style])) :attr (get-in parts [:left-filter-result-count :attr]) - :label (let [filter-result-key (if (= 1 (count filtered-choices)) - (get i18n :filter-result-singular "Found %s match containing %s") - (get i18n :filter-result-plural "Found %s matches containing %s")) - [start middle end] (clojure.string/split filter-result-key #"%s")] + :label (let [[start middle end] (rc.util/translate-split-result i18n :filter-result "Found %s match containing %s" "Found %s matches containing %s" (count filtered-choices))] [:span (gstring/format (str start "%s" middle) (count filtered-choices)) [:strong (gstring/format "%s" @*filter-choices-text)] end])])])]] @@ -537,10 +532,10 @@ [:i {:class (str "zmdi zmdi-hc-fw-rc zmdi-fast-forward")}] [:span {:style {:position "relative" :top "-1px"}} - (gstring/format (str " " (get i18n :include-all "include %s")) - (if (string/blank? @*filter-choices-text) - potential-count - (count filtered-choices)))]] + (let [num (if (string/blank? @*filter-choices-text) + potential-count + (count filtered-choices))] + (str " " (rc.util/translate i18n :include-all "include %s" num)))]] :disabled? (or disabled? (zero? (count filtered-choices))) :style (merge button-style (get-in parts [:include-all-button :style])) @@ -553,12 +548,12 @@ [:i {:class (str "zmdi zmdi-hc-fw-rc zmdi-play")}] [:span {:style {:position "relative" :top "-1px"}} - (gstring/format (str " " (get i18n :include "include %s")) - (if @*choice-group-heading-selected? - (->> filtered-choices ;; TODO: Inefficient - (filter (fn [item] (= (first @*current-choice-id) (group-fn item)))) - count) - ""))]] + (let [num (if @*choice-group-heading-selected? + (->> filtered-choices ;; TODO: Inefficient + (filter (fn [item] (= (first @*current-choice-id) (group-fn item)))) + count) + "")] + (str " " (rc.util/translate i18n :include "include %s" num)))]] :disabled? (or disabled? (not @*current-choice-id)) :style (merge button-style (get-in parts [:include-selected-button :style])) @@ -571,12 +566,12 @@ [:i {:class (str "zmdi zmdi-hc-fw-rc zmdi-play zmdi-hc-rotate-180")}] [:span {:style {:position "relative" :top "-1px"}} - (gstring/format (str " " (get i18n :exclude "exclude %s")) - (if @*selection-group-heading-selected? - (->> filtered-selections ;; TODO: Inefficient - (filter (fn [item] (= (first @*current-selection-id) (group-fn item)))) - count) - ""))]] + (let [num (if @*selection-group-heading-selected? + (->> filtered-selections ;; TODO: Inefficient + (filter (fn [item] (= (first @*current-selection-id) (group-fn item)))) + count) + "")] + (str " " (rc.util/translate i18n :exclude "exclude %s" num)))]] :disabled? (or disabled? (not excludable?)) :style (merge button-style (get-in parts [:exclude-selected-button :style])) @@ -589,10 +584,10 @@ [:i {:class (str "zmdi zmdi-hc-fw-rc zmdi-fast-rewind")}] [:span {:style {:position "relative" :top "-1px"}} - (gstring/format (str " " (get i18n :exclude-all "exclude %s")) - (if (string/blank? @*filter-selections-text) - chosen-count - (count filtered-selections)))]] + (let [num (if (string/blank? @*filter-selections-text) + chosen-count + (count filtered-selections))] + (str " " (rc.util/translate i18n :exclude-all "exclude %s" num)))]] :disabled? (or disabled? (zero? (count filtered-selections)) (not (> (count @*internal-model) (if required? 1 0)))) :style (merge button-style (get-in parts [:exclude-all-button :style])) @@ -654,11 +649,8 @@ (get-in parts [:right-label-item-count :style]))} (get-in parts [:right-label-item-count :attr])) (if (string/blank? @*filter-selections-text) - (if (string/blank? @*filter-choices-text) - (if (= 1 chosen-count) - (gstring/format (get i18n :item-singular "%s item") chosen-count) - (gstring/format (get i18n :item-plural "%s items") chosen-count)) - (gstring/format (get i18n :showing-of "showing %s of %s") (count filtered-selections) chosen-count)))]]] + (rc.util/translate-plural i18n :item "%s item" "%s items" chosen-count chosen-count) + (rc.util/translate i18n :showing-of "showing %s of %s" (count filtered-selections) chosen-count))]]] right-label)) [list-box :src (at) @@ -692,10 +684,7 @@ :style {:font-size "smaller"}] [text/label :src (at) - :label (let [filter-result-key (if (= 1 (count filtered-selections)) - (get i18n :filter-result-singular "Found %s match containing %s") - (get i18n :filter-result-plural "Found %s matches containing %s")) - [start middle end] (clojure.string/split filter-result-key #"%s")] + :label (let [[start middle end] (rc.util/translate-split-result i18n :filter-result "Found %s match containing %s" "Found %s matches containing %s" (count filtered-selections))] [:span (gstring/format (str start "%s" middle) (count filtered-selections)) [:strong (gstring/format "%s" @*filter-selections-text)] end]) diff --git a/src/re_com/util.cljs b/src/re_com/util.cljs index 7a143aba..cf857578 100644 --- a/src/re_com/util.cljs +++ b/src/re_com/util.cljs @@ -1,6 +1,7 @@ (ns re-com.util (:require [reagent.ratom :refer [RAtom Reaction RCursor Track Wrapper]] + [goog.string :as gstring] [goog.date.DateTime] [goog.date.UtcDateTime])) @@ -106,6 +107,29 @@ [num singular & [plural]] (str num " " (if (= 1 num) singular (or plural (str singular "s"))))) +(defn translate + "Simple translation function that picks required translation from i18n map. Also format if args is provided. + Else returns unformatted translation." + [i18n i18n-key default-value & args] + (let [unformatted (get i18n i18n-key default-value)] + (if (seq args) + (apply gstring/format unformatted args) + unformatted))) + +(defn translate-plural + "Adds -singular or -plural to given key depending on num. Convenience function for translate." + [i18n i18n-key default-value-singular default-value-plural num & args] + (if (= 1 num) + (apply translate i18n (keyword (str (name i18n-key) "-singular")) default-value-singular args) + (apply translate i18n (keyword (str (name i18n-key) "-plural")) default-value-plural args))) + +(defn translate-split-result + "Return unformatted translation text split by %s. Expect caller do the formatting and add the %s between vector splits. + Used primarily when special formatting is needed." + [i18n i18n-key default-value-singular default-value-plural num] + (-> (translate-plural i18n i18n-key default-value-singular default-value-plural num) + (clojure.string/split #"%s"))) + ;; ---------------------------------------------------------------------------- ;; Handy vector functions ;; ---------------------------------------------------------------------------- @@ -194,17 +218,17 @@ ;; ;; Run at 09:22:35 in Sydney Australia... ;; -;; (now)................ goog.date.UtcDateTime {date: Thu Nov 22 2018 09:22:35 GMT+1100 (Australian Eastern Daylight Time)} -;; (now->utc)........... goog.date.UtcDateTime {date: Thu Nov 22 2018 11:00:00 GMT+1100 (Australian Eastern Daylight Time)} -;; (today).............. goog.date.Date  {date: Thu Nov 22 2018 00:00:00 GMT+1100 (Australian Eastern Daylight Time)} +;; (now)................ goog.date.UtcDateTime {date: Thu Nov 22 2018 09:22:35 GMT+1100 (Australian Eastern Daylight Time)} +;; (now->utc)........... goog.date.UtcDateTime {date: Thu Nov 22 2018 11:00:00 GMT+1100 (Australian Eastern Daylight Time)} +;; (today).............. goog.date.Date {date: Thu Nov 22 2018 00:00:00 GMT+1100 (Australian Eastern Daylight Time)} ;; -;; (time-now)........... goog.date.DateTime  {date: Thu Nov 22 2018 09:22:35 GMT+1100 (Australian Eastern Daylight Time)} -;; (today-at-midnight).. goog.date.UtcDateTime {date: Wed Nov 21 2018 11:00:00 GMT+1100 (Australian Eastern Daylight Time), firstDayOfWeek_: 6, firstWeekCutOffDay_: 5} -;; (date-midnight)...... goog.date.UtcDateTime {date: Thu Nov 22 2018 11:00:00 GMT+1100 (Australian Eastern Daylight Time)} +;; (time-now)........... goog.date.DateTime {date: Thu Nov 22 2018 09:22:35 GMT+1100 (Australian Eastern Daylight Time)} +;; (today-at-midnight).. goog.date.UtcDateTime {date: Wed Nov 21 2018 11:00:00 GMT+1100 (Australian Eastern Daylight Time), firstDayOfWeek_: 6, firstWeekCutOffDay_: 5} +;; (date-midnight)...... goog.date.UtcDateTime {date: Thu Nov 22 2018 11:00:00 GMT+1100 (Australian Eastern Daylight Time)} ;; -;; (date-time).......... goog.date.UtcDateTime {date: Thu Nov 22 2018 19:05:05 GMT+1100 (Australian Eastern Daylight Time)} -;; (local-date-time).... goog.date.DateTime  {date: Thu Nov 22 2018 08:05:05 GMT+1100 (Australian Eastern Daylight Time)} -;; (local-date)......... goog.date.Date  {date: Thu Nov 22 2018 00:00:00 GMT+1100 (Australian Eastern Daylight Time)} +;; (date-time).......... goog.date.UtcDateTime {date: Thu Nov 22 2018 19:05:05 GMT+1100 (Australian Eastern Daylight Time)} +;; (local-date-time).... goog.date.DateTime {date: Thu Nov 22 2018 08:05:05 GMT+1100 (Australian Eastern Daylight Time)} +;; (local-date)......... goog.date.Date {date: Thu Nov 22 2018 00:00:00 GMT+1100 (Australian Eastern Daylight Time)} ;; ;; ---------------------------------------------------------------------------- diff --git a/src/re_demo/multi_select.cljs b/src/re_demo/multi_select.cljs index 30a60182..5b2c79da 100644 --- a/src/re_demo/multi_select.cljs +++ b/src/re_demo/multi_select.cljs @@ -67,7 +67,7 @@ :i18n (when @i18n? {:no-results-match "Ei sopivaa tulosta haulle \"%s\"" :item-singular "%s osio" :item-plural "%s osiota" - :showing-of "näytetään %s %s:sta" + :showing-of "näytetään %s tulosta %s:sta" :filter-result-singular "Löydetty %s tulos sisältäen %s" :filter-result-plural "Löydetty %s tulosta sisältäen %s" :include-all "sisällytä %s"