-
Notifications
You must be signed in to change notification settings - Fork 0
/
txt_resources.clj
99 lines (86 loc) · 3.52 KB
/
txt_resources.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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
(ns lupapiste-commons.i18n.txt-resources
(:require [clojure.edn :as edn]
[clojure.java.io :as io]
[clojure.string :as s]
[flatland.ordered.map :refer [ordered-map]])
(:import [java.io File PushbackReader StringReader]
[java.net URL]))
(set! *warn-on-reflection* true)
(defn source-changed? [sym]
(:source-changed (meta sym)))
(defn write-key [sym]
(cond-> (str sym)
(source-changed? sym) (str "!")))
(defn nil->empty-str [x]
(if (nil? x) "" x))
(defn read-key [^String string]
(if (.endsWith string "!")
(-> (s/replace string #"!$" "")
symbol
(with-meta {:source-changed true}))
(symbol string)))
(defn- read-entry [line]
(let [in (-> line StringReader. PushbackReader.)
key (read-key (edn/read in))
lang (edn/read in)
text (edn/read in)]
{:key key :lang lang :text text}))
(def ^:private empty-line? s/blank?)
(defn- filename [input]
(cond (string? input) input
(instance? File input) (.getName ^File input)
(instance? URL input) (-> (.getFile ^URL input)
(s/split #"/")
last)
:else nil))
(defn- merge-entry [acc {:keys [key lang text]} source-name]
(let [[key current-translations] (or (find acc key)
[key (ordered-map)])]
(assoc acc
(with-meta key
(merge (meta key)
{:source-name source-name}))
(assoc current-translations
(keyword lang)
text))))
(defn txt->map [input]
(with-open [reader (io/reader input)]
(let [source-name (filename input)
translations
(loop [acc (ordered-map)
lines (line-seq reader)]
(if-let [line (first lines)]
(if (empty-line? line)
(recur acc
(rest lines))
(recur (merge-entry acc
(read-entry line)
source-name)
(rest lines)))
acc))]
{:languages (-> translations first val keys vec)
:translations translations})))
(defn- txt-line [key lang text]
(str (pr-str (write-key key)) " " (pr-str (name lang)) " " (pr-str (nil->empty-str text)) "\n"))
(defn write-txt [{:keys [translations]} txt-file]
(spit txt-file "") ;; truncate txt-file
(doseq [[key strings] translations]
(doseq [[lang text] strings]
(spit txt-file (txt-line key lang text) :append true))))
(defn missing-translations
"Returns missing translations. If selected-lang is given, only that and :fi is regarded."
[{:keys [translations languages]} & [selected-lang]]
{:languages (if selected-lang
[:fi (keyword selected-lang)]
languages)
:translations
(reduce (fn [acc [key {:keys [fi] :as strings}]]
(cond-> acc
(empty? (dissoc strings :fi)) (assoc key {:fi fi})
(empty? fi) (assoc key {:fi ""})
(source-changed? key) (assoc key {:fi fi})
(if selected-lang
(s/blank? (get strings (keyword selected-lang)))
(some empty? (vals strings))) (assoc key {:fi fi})))
(ordered-map)
translations)})