0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-01-10 08:50:57 -05:00
penpot/frontend/translations.clj

179 lines
5.6 KiB
Clojure
Raw Normal View History

2020-01-11 10:28:54 -05:00
(require '[clojure.pprint :as pp :refer [pprint]])
(require '[clojure.java.shell :as shell])
(require '[environ.core :refer [env]])
(require '[clojure.walk :as walk]
'[clojure.edn :as edn]
'[clojure.set :as set])
(require '[datoteka.core :as fs]
'[jsonista.core :as json])
(require '[clojure.java.io :as io]
'[clojure.tools.reader :as r]
'[clojure.tools.reader.reader-types :as rt])
(import 'java.nio.file.Paths
'java.nio.file.Path
'java.nio.file.Files
'java.nio.file.SimpleFileVisitor
'java.nio.file.FileVisitResult)
(extend-protocol io/Coercions
Path
(as-file [it] (.toFile it))
(as-url [it] (io/as-url (.toFile it))))
(defmulti task first)
(defn- find-translations-in-form
[env form]
(->> form
(walk/postwalk
(fn [fm]
(when (and (list? fm)
(= (first fm) 'tr)
(string? (second fm)))
(let [m (meta (first fm))]
(swap! env conj {:code (second fm)
:file (:file m)
:line (:line m)})))
fm))))
(defn- find-translations-in-file
[env file]
(let [rdr (-> (io/as-file file)
(io/reader)
(rt/source-logging-push-back-reader 1 file))]
(try
(binding [r/*default-data-reader-fn* (constantly nil)
r/*alias-map* {'dw (create-ns 'user)
'fm (create-ns 'user)
'us (create-ns 'user)
'dp (create-ns 'user)
'cp (create-ns 'user)}]
(loop []
(let [form (r/read {:eof ::end} rdr)]
(when (not= ::end form)
(find-translations-in-form env form)
(recur)))))
(catch Exception e
;; (.printStackTrace e)
(println (str "ERROR: on procesing " file "; ignoring..."))))))
(defn- find-translations-in-directory
[env file]
(->> (proxy [SimpleFileVisitor] []
(visitFile [path attrs]
(when (= (fs/ext path) "cljs")
(find-translations-in-file env path))
FileVisitResult/CONTINUE)
(postVisitDirectory [dir exc]
FileVisitResult/CONTINUE))
(Files/walkFileTree (fs/path file))))
(defn- collect-translations
[path]
(let [env (atom [])]
(find-translations-in-directory env path)
@env))
(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")
(assoc "used-in" (->> (get state "used-in" [])
(remove #(= rpath %))
(into [rpath])))))))
(assoc data code {"translations" {"en" nil "fr" 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- ensure-translations-format
[data]
(reduce-kv (fn [data k v]
(if (string? v)
(assoc data k {:translations {:en v}})
data))
data
data))
(defn- synchronize-translations
[data translations]
(loop [data (ensure-translations-format 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 "collectmessages"
[[_ 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*)