diff --git a/frontend/locales.clj b/frontend/locales.clj deleted file mode 100644 index a64761248..000000000 --- a/frontend/locales.clj +++ /dev/null @@ -1,151 +0,0 @@ -;; This Source Code Form is subject to the terms of the Mozilla Public -;; License, v. 2.0. If a copy of the MPL was not distributed with this -;; file, You can obtain one at http://mozilla.org/MPL/2.0/. -;; -;; Copyright (c) UXBOX Labs SL - -(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 - 'com.fasterxml.jackson.databind.ObjectMapper - 'com.fasterxml.jackson.databind.SerializationFeature) - -(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 (io/as-file path))] - (reduce-kv (fn [res k v] - (let [v (into (sorted-map) v) - v (update v "translations" #(into (sorted-map) %))] - (assoc res k v))) - (sorted-map) - content)))) - -(defn- add-translation - [data {:keys [code file line] :as translation}] - (let [rpath (str file)] - (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" (sorted-map "en" nil "es" 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- write-result! - [data output-path] - (binding [*out* (io/writer (fs/path output-path))] - (let [mapper (doto (ObjectMapper.) - (.enable SerializationFeature/ORDER_MAP_ENTRIES_BY_KEYS)) - mapper (json/object-mapper {:pretty true :mapper mapper})] - (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})) - -(task *command-line-args*) diff --git a/frontend/package.json b/frontend/package.json index 3b8b95580..31728cfb9 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -12,7 +12,7 @@ "defaults" ], "scripts": { - "collect-locales": "clojure -M:dev locales.clj collect src/app/main/ resources/locales.json" + "validate-translations": "node ./scripts/validate-translations.js" }, "devDependencies": { "autoprefixer": "^10.2.4", diff --git a/frontend/scripts/validate-translations.js b/frontend/scripts/validate-translations.js new file mode 100644 index 000000000..52674054f --- /dev/null +++ b/frontend/scripts/validate-translations.js @@ -0,0 +1,31 @@ +const fs = require('fs').promises; +const gt = require("gettext-parser"); +const l = require("lodash"); +const path = require('path'); + +async function* getFiles(dir) { + const dirents = await fs.readdir(dir, { withFileTypes: true }); + for (const dirent of dirents) { + const res = path.resolve(dir, dirent.name); + if (dirent.isDirectory()) { + yield* getFiles(res); + } else { + yield res; + } + } +} + +;(async () => { + const fileRe = /.+\.po$/; + const target = path.normalize("./translations/"); + const parent = path.join(target, ".."); + for await (const f of getFiles(target)) { + if (!fileRe.test(f)) continue; + const entry = path.relative(parent, f); + console.log(`=> processing: ${entry}`); + const content = await fs.readFile(f); + const data = gt.po.parse(content, "utf-8") + const buff = gt.po.compile(data, {sort: true}); + await fs.writeFile(f, buff); + } +})() diff --git a/frontend/translations/en.po b/frontend/translations/en.po index 7067eb619..26cab1a7f 100644 --- a/frontend/translations/en.po +++ b/frontend/translations/en.po @@ -1423,6 +1423,14 @@ msgstr "Colors" msgid "workspace.assets.components" msgstr "Components" +#: src/app/main/ui/workspace/sidebar/assets.cljs +msgid "workspace.assets.create-group" +msgstr "Create a group" + +#: src/app/main/ui/workspace/sidebar/assets.cljs +msgid "workspace.assets.create-group-hint" +msgstr "Your items are going to be named automatically as \"group name / item name\"" + #: src/app/main/ui/workspace/sidebar/sitemap.cljs, src/app/main/ui/workspace/sidebar/assets.cljs, src/app/main/ui/workspace/sidebar/assets.cljs, src/app/main/ui/workspace/sidebar/assets.cljs, src/app/main/ui/workspace/sidebar/assets.cljs msgid "workspace.assets.delete" msgstr "Delete" @@ -1447,18 +1455,10 @@ msgstr "Graphics" msgid "workspace.assets.group" msgstr "Group" -#: src/app/main/ui/workspace/sidebar/assets.cljs -msgid "workspace.assets.create-group" -msgstr "Create a group" - #: src/app/main/ui/workspace/sidebar/assets.cljs msgid "workspace.assets.group-name" msgstr "Group name" -#: src/app/main/ui/workspace/sidebar/assets.cljs -msgid "workspace.assets.create-group-hint" -msgstr "Your items are going to be named automatically as \"group name / item name\"" - #: src/app/main/ui/workspace/sidebar/assets.cljs msgid "workspace.assets.libraries" msgstr "Libraries" @@ -2457,4 +2457,4 @@ msgid "workspace.updates.update" msgstr "Update" msgid "workspace.viewport.click-to-close-path" -msgstr "Click to close the path" +msgstr "Click to close the path" \ No newline at end of file diff --git a/frontend/translations/es.po b/frontend/translations/es.po index a20c36d5b..31911b1f0 100644 --- a/frontend/translations/es.po +++ b/frontend/translations/es.po @@ -1403,6 +1403,16 @@ msgstr "Colores" msgid "workspace.assets.components" msgstr "Componentes" +#: src/app/main/ui/workspace/sidebar/assets.cljs +msgid "workspace.assets.create-group" +msgstr "Crear un grupo" + +#: src/app/main/ui/workspace/sidebar/assets.cljs +msgid "workspace.assets.create-group-hint" +msgstr "" +"Tus elementos se renombrarán automáticamente a \"nombre grupo / nombre " +"elemento\"" + #: src/app/main/ui/workspace/sidebar/sitemap.cljs, src/app/main/ui/workspace/sidebar/assets.cljs, src/app/main/ui/workspace/sidebar/assets.cljs, src/app/main/ui/workspace/sidebar/assets.cljs, src/app/main/ui/workspace/sidebar/assets.cljs msgid "workspace.assets.delete" msgstr "Borrar" @@ -1427,18 +1437,10 @@ msgstr "Gráficos" msgid "workspace.assets.group" msgstr "Agrupar" -#: src/app/main/ui/workspace/sidebar/assets.cljs -msgid "workspace.assets.create-group" -msgstr "Crear un grupo" - #: src/app/main/ui/workspace/sidebar/assets.cljs msgid "workspace.assets.group-name" msgstr "Nombre del grupo" -#: src/app/main/ui/workspace/sidebar/assets.cljs -msgid "workspace.assets.create-group-hint" -msgstr "Tus elementos se renombrarán automáticamente a \"nombre grupo / nombre elemento\"" - #: src/app/main/ui/workspace/sidebar/assets.cljs msgid "workspace.assets.libraries" msgstr "Bibliotecas" @@ -2439,4 +2441,4 @@ msgid "workspace.updates.update" msgstr "Actualizar" msgid "workspace.viewport.click-to-close-path" -msgstr "Pulsar para cerrar la ruta" +msgstr "Pulsar para cerrar la ruta" \ No newline at end of file