mirror of
https://github.com/penpot/penpot.git
synced 2025-01-08 16:00:19 -05:00
162 lines
5.1 KiB
Clojure
162 lines
5.1 KiB
Clojure
(require '[clojure.pprint :as pp :refer [pprint]])
|
|
|
|
(require '[clojure.edn :as edn]
|
|
'[clojure.set :as set]
|
|
'[clojure.java.io :as io])
|
|
|
|
(require '[datoteka.core :as fs]
|
|
'[jsonista.core :as json]
|
|
'[parcera.core :as pa])
|
|
|
|
(import 'java.nio.file.Paths
|
|
'java.nio.file.Path
|
|
'java.nio.file.Files
|
|
'java.nio.file.SimpleFileVisitor
|
|
'java.nio.file.FileVisitResult)
|
|
|
|
(defmulti task first)
|
|
|
|
(defn- find-translations-in-form
|
|
[form]
|
|
(reduce (fn [messages node]
|
|
(let [found (->> node
|
|
(filter #(and (seq? %) (= :string (first %))))
|
|
(map (fn [item]
|
|
(let [mdata (meta item)]
|
|
{:code (edn/read-string (second item))
|
|
:line (get-in mdata [::pa/start :row])}))))]
|
|
(into messages found)))
|
|
[]
|
|
(->> (tree-seq seq? seq form)
|
|
(filter #(and (seq? %)
|
|
(seq? (second %))
|
|
(= :list (first %))
|
|
(= :symbol (first (second %)))
|
|
(or (= "t" (second (second %)))
|
|
(= "tr" (second (second %)))))))))
|
|
|
|
(defn- find-translations
|
|
[path]
|
|
(let [forms (pa/ast (slurp path))
|
|
spath (str path)]
|
|
(->> forms
|
|
(filter #(and (seq? %) (= :list (first %))))
|
|
(reduce (fn [messages form]
|
|
(->> (find-translations-in-form form)
|
|
(map #(assoc % :file spath))
|
|
(into messages))) []))))
|
|
|
|
(defn- collect-translations
|
|
[path]
|
|
(let [messages (atom [])]
|
|
(->> (proxy [SimpleFileVisitor] []
|
|
(visitFile [path attrs]
|
|
(when (= (fs/ext path) "cljs")
|
|
(swap! messages into (find-translations path)))
|
|
FileVisitResult/CONTINUE)
|
|
(postVisitDirectory [dir exc]
|
|
FileVisitResult/CONTINUE))
|
|
(Files/walkFileTree (fs/path path)))
|
|
@messages))
|
|
|
|
(defn- read-json-file
|
|
[path]
|
|
(when (fs/regular-file? path)
|
|
(let [content (json/read-value (slurp (io/as-file path)))]
|
|
(into (sorted-map) content))))
|
|
|
|
(defn- read-edn-file
|
|
[path]
|
|
(when (fs/regular-file? path)
|
|
(let [content (edn/read-string (slurp (io/as-file path)))]
|
|
(into (sorted-map) content))))
|
|
|
|
|
|
(defn- add-translation
|
|
[data {:keys [code file line] :as translation}]
|
|
(let [rpath (str file ":" line)]
|
|
(if (contains? data code)
|
|
(update data code (fn [state]
|
|
(if (get state "permanent")
|
|
state
|
|
(-> state
|
|
(dissoc "unused")
|
|
(update "used-in" conj rpath)))))
|
|
(assoc data code {"translations" {"en" nil "fr" nil "es" nil "ru" nil}
|
|
"used-in" [rpath]}))))
|
|
|
|
(defn- clean-removed-translations
|
|
[data imported]
|
|
(let [existing (into #{} (keys data))
|
|
toremove (set/difference existing imported)]
|
|
(reduce (fn [data code]
|
|
(if (get-in data [code "permanent"])
|
|
data
|
|
(-> data
|
|
(update code dissoc "used-in")
|
|
(update code assoc "unused" true))))
|
|
data
|
|
toremove)))
|
|
|
|
(defn- initial-cleanup
|
|
[data]
|
|
(reduce-kv (fn [data k v]
|
|
(if (string? v)
|
|
(assoc data k {"used-in" []
|
|
"translations" {:en v}})
|
|
(update data k assoc "used-in" [])))
|
|
data
|
|
data))
|
|
|
|
(defn- synchronize-translations
|
|
[data translations]
|
|
(loop [data (initial-cleanup data)
|
|
imported #{}
|
|
c (first translations)
|
|
r (rest translations)]
|
|
(if (nil? c)
|
|
(clean-removed-translations data imported)
|
|
(recur (add-translation data c)
|
|
(conj imported (:code c))
|
|
(first r)
|
|
(rest r)))))
|
|
|
|
(defn- synchronize-legacy-translations
|
|
[data legacy-data lang]
|
|
(reduce-kv (fn [data k v]
|
|
(if (contains? data k)
|
|
(update-in data [k "translations"] assoc lang v)
|
|
data))
|
|
data
|
|
legacy-data))
|
|
|
|
(defn- write-result!
|
|
[data output-path]
|
|
(binding [*out* (io/writer (fs/path output-path))]
|
|
(let [mapper (json/object-mapper {:pretty true})]
|
|
(println (json/write-value-as-string data mapper))
|
|
(flush))))
|
|
|
|
(defn- update-translations
|
|
[{:keys [find-directory output-path] :as props}]
|
|
(let [
|
|
data (read-json-file output-path)
|
|
translations (collect-translations find-directory)
|
|
data (synchronize-translations data translations)
|
|
]
|
|
(write-result! data output-path)))
|
|
|
|
(defmethod task "collect"
|
|
[[_ in-path out-path]]
|
|
(update-translations {:find-directory in-path
|
|
:output-path out-path}))
|
|
|
|
|
|
(defmethod task "merge-with-legacy"
|
|
[[_ path lang legacy-path]]
|
|
(let [ldata (read-edn-file legacy-path)
|
|
data (read-json-file path)
|
|
data (synchronize-legacy-translations data ldata lang)]
|
|
(write-result! data path)))
|
|
|
|
(task *command-line-args*)
|