-
Notifications
You must be signed in to change notification settings - Fork 1
/
translate.clj
79 lines (67 loc) · 2.34 KB
/
translate.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
(ns mudguard.translate
(:require [mudguard.core :as core]))
(defn coerce-to-vec [x]
(if (coll? x)
x
[x]))
(defn matches-translation? [error-path translation-id]
(if (empty? error-path)
false
(or (= (remove int? error-path) translation-id)
(matches-translation? (rest error-path) translation-id))))
(defn map-over-keys [f m]
(->> (for [[k v] m]
[(f k) v])
(into {})))
(defn map-over-vals [f m]
(->> (for [[k v] m]
[k (f v)])
(into {})))
(defn create-translation [error translation-or-f]
(if (fn? translation-or-f)
(translation-or-f error)
translation-or-f))
(defn find-translation [error-path error translations]
(->> translations
(map-over-keys coerce-to-vec)
(sort-by (comp count first))
reverse ;; TODO optimise, do this upfront
(filter (comp (partial matches-translation? error-path) first))
(map second)
first
(create-translation error)))
(defn- error-paths [errors]
(->> errors
::core/errors
(map (juxt ::core/id identity))))
(defn translate-errors [translations errors]
(let [paths-and-errors (error-paths errors)]
(->> (for [[path error] paths-and-errors]
[(drop-last path) (find-translation path error translations)])
(group-by first)
(map-over-vals (partial map second))
(map-over-keys vec))))
(defn- add-error-msg [m [[path-f & path-r] messages]]
(cond (and (empty? m) (nil? path-f))
messages
(nil? m)
{path-f (add-error-msg {} [path-r messages])}
(sequential? m)
{::errors m
path-f (add-error-msg {} [path-r messages])}
:else
(update m path-f add-error-msg [path-r messages])
))
(defn restructure-messages [error-messages]
(->> error-messages
(reduce add-error-msg {})))
(defn untranslatable-errors [translations errors]
(let [error-list (::core/errors errors)
missing-translations (->> error-list
(remove (fn [e] (find-translation (::core/id e) e translations))))]
(when-not (empty? missing-translations)
{::core/errors missing-translations})))
(defn missing-translations [translations validator]
(some->> validator
(core/possible-errors)
(untranslatable-errors translations)))