diff --git a/docs/02-Frontend-Guide.md b/docs/02-Frontend-Guide.md
index 143e0e5cb..8124474a8 100644
--- a/docs/02-Frontend-Guide.md
+++ b/docs/02-Frontend-Guide.md
@@ -2,3 +2,117 @@
This guide intends to explain the essential details of the frontend
application.
+
+**TODO**
+
+
+## Translations (I18N) ##
+
+### How it Works ###
+
+All the translation strings of this application are stored in
+`resources/locales.json` file. It has a self explanatory format that
+looks like this:
+
+```json
+{
+ "auth.email-or-username" : {
+ "used-in" : [ "src/uxbox/main/ui/auth/login.cljs:61" ],
+ "translations" : {
+ "en" : "Email or Username",
+ "fr" : "adresse email ou nom d'utilisateur"
+ }
+ },
+ "ds.num-projects" : {
+ "translations": {
+ "en": ["1 project", "%s projects"]
+ }
+ },
+}
+```
+
+For development convenience, you can forget about the specific format
+of that file, and just add a simple key-value entry pairs like this:
+
+```
+{
+ [...],
+ "foo1": "bar1",
+ "foo2": "bar2"
+}
+```
+
+The file is automatically bundled into the `index.html` file on
+compile time (in development and production). The bundled content is a
+simplified version of this data structure for avoid load unnecesary
+data.
+
+The development environment has a watch process that detect changes on
+that file and recompiles the `index.html`. **There are no hot reload
+for translations strings**, you just need to refresh the browser tab
+for refresh the translations in the running the application.
+
+If you have used the short (key-value) format, the watch process will
+automatically convert it to the apropriate format before generate the
+`index.html`.
+
+Finally, when you have finished to adding texts, execute the following
+command for reformat the file, and track the usage locations (the
+"used-in" list) before commiting the file into the repository:
+
+```bash
+clojure -Adev translations.clj collectmessages src/uxbox/main/ resources/locales.json
+```
+
+NOTE: Later, we will need to think and implement the way to export and
+import to other formats (mainly for transifex and similar services
+compatibility).
+
+
+### How to use it ###
+
+You have two aproaches for translate strings: one for general purpose
+and other specific for React components (that leverages reactivity for
+language changes).
+
+The `uxbox.util.i18n/tr` is the general purpose function. This is a
+simple use case example:
+
+```clojure
+(require '[uxbox.util.i18n :as i18n])
+
+(i18n/tr "auth.email-or-username")
+;; => "Email or Username"
+```
+
+If you have defined plurals for some translation resource, then you
+need to pass an additional parameter marked as counter in order to
+allow the system know when to show the plural:
+
+```clojure
+(require '[uxbox.util.i18n :as i18n])
+
+(i18n/tr "ds.num-projects" (i18n/c 10))
+;; => "10 projects"
+
+(i18n/tr "ds.num-projects" (i18n/c 1))
+;; => "1 project"
+```
+
+For React components, you have `uxbox.util.i18n/use-translations` hook:
+
+```clojure
+(mf/defc my-component
+ [props]
+ (let [tr (i18n/use-translations)]
+ [:div
+ [:span (tr "auth.email-or-username")]]))
+```
+
+You can use the general purpose function in React component but when
+language is changed the component will not be rerendered
+automatically.
+
+
+
+
diff --git a/frontend/deps.edn b/frontend/deps.edn
index 2e8a92d1f..21f5ab9cf 100644
--- a/frontend/deps.edn
+++ b/frontend/deps.edn
@@ -15,7 +15,7 @@
funcool/cuerdas {:mvn/version "2.2.0"}
funcool/lentes {:mvn/version "1.4.0-SNAPSHOT"}
funcool/potok {:mvn/version "2.8.0-SNAPSHOT"}
- funcool/promesa {:mvn/version "4.0.2"}
+ funcool/promesa {:mvn/version "5.0.0"}
funcool/rumext {:mvn/version "2.0.0-SNAPSHOT"}
}
:paths ["src" "vendor" "resources" "../common"]
@@ -25,7 +25,9 @@
{com.bhauman/rebel-readline-cljs {:mvn/version "0.1.4"}
com.bhauman/rebel-readline {:mvn/version "0.1.4"}
com.bhauman/figwheel-main {:mvn/version "0.2.3"}
- org.clojure/tools.namespace {:mvn/version "0.3.1"}}
+ org.clojure/tools.namespace {:mvn/version "0.3.1"}
+ metosin/jsonista {:mvn/version "0.2.5"}
+ funcool/datoteka {:mvn/version "1.2.0"}}
:extra-paths ["test"]}
:repl
diff --git a/frontend/gulpfile.js b/frontend/gulpfile.js
index 69bc0d117..80e18eb6c 100644
--- a/frontend/gulpfile.js
+++ b/frontend/gulpfile.js
@@ -7,6 +7,8 @@ const rename = require("gulp-rename");
const gulpif = require("gulp-if");
const gzip = require("gulp-gzip");
const cleancss = require("gulp-clean-css");
+const fs = require("fs");
+const l = require("lodash");
const paths = {};
paths.app = "./resources/";
@@ -79,6 +81,23 @@ gulp.task("scss:view", scssPipeline({
gulp.task("scss", gulp.parallel("scss:main", "scss:view"));
+function readLocales() {
+ const path = __dirname + "/resources/locales.json";
+ const content = JSON.parse(fs.readFileSync(path, {encoding: "utf8"}));
+
+ let result = {};
+ for (let key of Object.keys(content)) {
+ const item = content[key];
+ if (l.isString(item)) {
+ result[key] = {"en": item};
+ } else if (l.isPlainObject(item) && l.isPlainObject(item.translations)) {
+ result[key] = item.translations;
+ }
+ }
+
+ return JSON.stringify(result);
+}
+
// Templates
function templatePipeline(options) {
@@ -86,8 +105,12 @@ function templatePipeline(options) {
const input = options.input;
const output = options.output;
const ts = Math.floor(new Date());
+
+ const locales = readLocales();
+
const tmpl = mustache({
- ts: ts
+ ts: ts,
+ tr: JSON.stringify(locales),
});
return gulp.src(input)
@@ -98,27 +121,28 @@ function templatePipeline(options) {
}
gulp.task("template:main", templatePipeline({
- input: paths.app + "index.mustache",
- output: paths.output,
+ input: paths.app + "templates/index.mustache",
+ output: paths.output
}));
gulp.task("template:view", templatePipeline({
- input: paths.app + "view.mustache",
- output: paths.output + "view/",
- jspath: "/js/view.js",
- csspath: "/css/view.css"
+ input: paths.app + "templates/view.mustache",
+ output: paths.output + "view/"
}));
-gulp.task("template", gulp.parallel("template:view", "template:main"));
+gulp.task("templates", gulp.parallel("template:view", "template:main"));
// Entry Point
gulp.task("watch:main", function() {
gulp.watch(paths.scss, gulp.task("scss"));
+ gulp.watch([paths.app + "templates/*.mustache",
+ paths.app + "locales.json"],
+ gulp.task("templates"));
});
gulp.task("watch", gulp.series(
- gulp.parallel("scss", "template"),
+ gulp.parallel("scss", "templates"),
gulp.task("watch:main")
));
@@ -142,7 +166,7 @@ gulp.task("dist:template:view", templatePipeline({
output: paths.dist + "view/",
}));
-gulp.task("dist:template", gulp.parallel("dist:template:view", "dist:template:main"));
+gulp.task("dist:templates", gulp.parallel("dist:template:view", "dist:template:main"));
// Styles
@@ -184,7 +208,7 @@ gulp.task("dist:gzip", function() {
// Entry Point
gulp.task("dist", gulp.parallel(
- gulp.task("dist:template"),
+ gulp.task("dist:templates"),
gulp.task("dist:scss"),
gulp.task("dist:copy")
));
diff --git a/frontend/legacy.edn b/frontend/legacy.edn
new file mode 100644
index 000000000..51459f2a2
--- /dev/null
+++ b/frontend/legacy.edn
@@ -0,0 +1,223 @@
+{"ds.projects" "PROJECTS"
+ "ds.new-file" "+ New File"
+ "ds.project-title" "Your projects"
+ "ds.project-new" "+ New project"
+ "ds.project-thumbnail.alt" "Project title"
+
+ "ds.ordering" "Sort by"
+ "ds.ordering.by-name" "name"
+ "ds.ordering.by-last-update" "last update"
+ "ds.ordering.by-creation-date" "creation date"
+ "ds.search.placeholder" "Search..."
+ "ds.uploaded-at" "Uploaded at %s"
+ "ds.updated-at" "Updated %s"
+
+ "ds.confirm-title" "Are you sure?"
+ "ds.confirm-ok" "Ok"
+ "ds.confirm-cancel" "Cancel"
+
+ "ds.multiselect-bar.copy" "Copy"
+ "ds.multiselect-bar.copy-to-library" "Copy to library"
+ "ds.multiselect-bar.move" "Move"
+ "ds.multiselect-bar.move-to-library" "Move to library"
+ "ds.multiselect-bar.rename" "Rename"
+ "ds.multiselect-bar.delete" "Delete"
+
+ "ds.elements" "ELEMENTS"
+ "ds.icons" "ICONS"
+ "ds.your-icons-title" "YOUR ICONS"
+ "ds.store-icons-title" "ICONS STORE"
+ "ds.icons-collection.new" "+ New collection"
+ "ds.icon-new" "+ New icon"
+
+ "ds.images" "IMAGES"
+ "ds.your-images-title" "YOUR IMAGES"
+ "ds.store-images-title" "IMAGES STORE"
+ "ds.images-collection.new" "+ New library"
+ "ds.image-new" "+ New image"
+
+ "ds.colors" "COLORS"
+ "ds.your-colors-title" "YOUR COLORS"
+ "ds.store-colors-title" "COLORS STORE"
+ "ds.colors-collection.new" "+ New library"
+ "ds.color-new" "+ New color"
+ "ds.color-lightbox.title" "New color"
+ "ds.color-lightbox.add" "+ Add color"
+
+ "ds.library-title" "Library: "
+ "ds.standard-title" "STANDARD"
+ "ds.your-libraries-title" "YOUR LIBRARIES"
+ "ds.default-library-title" "Unnamed Collection (%s)"
+
+ "ds.project.placeholder" "New project name"
+ "ds.project.new" "New project"
+
+ "common.accept" "Accept"
+ "common.cancel" "Cancel"
+
+ "workspace.sidebar.icons" "Icons"
+ "workspace.sidebar.element-options" "Element options"
+ "workspace.sidebar.draw-tools" "Draw tools"
+ "workspace.sidebar.sitemap" "Sitemap"
+ "workspace.sidebar.layers" "Layers"
+ "workspace.sidebar.document-history" "Document history"
+
+ "ds.page.placeholder" "Page name"
+ "ds.page.new" "New page"
+ "ds.page.edit" "Edit page"
+
+ "ds.history.versions" "History"
+ "ds.history.pinned" "Pinned"
+
+ "workspace.header.rect" "Box (Ctrl + B)"
+ "workspace.header.circle" "Circle (Ctrl + E)"
+ "workspace.header.line" "Line (Ctrl + L)"
+ "workspace.header.text" "Text"
+ "workspace.header.path" "Path"
+ "workspace.header.curve" "Curve"
+ "workspace.header.ruler" "Ruler"
+ "workspace.header.canvas" "Canvas"
+
+ "ds.user.profile" "Profile"
+ "ds.user.password" "Password"
+ "ds.user.notifications" "Notifications"
+ "ds.user.exit" "Exit"
+
+ "workspace.header.sitemap" "Sitemap (Ctrl + Shift + M)"
+ "workspace.header.draw-tools" "Draw tools (Ctrl + Shift + S)"
+ "workspace.header.color-palette" "Color Palette (---)"
+ "workspace.header.icons" "Icons (Ctrl + Shift + I)"
+ "workspace.header.layers" "Layers (Ctrl + Shift + L)"
+ "workspace.header.element-options" "Element options (Ctrl + Shift + O)"
+ "workspace.header.document-history" "History (Ctrl + Shift + H)"
+ "workspace.header.undo" "Undo (Ctrl + Z)"
+ "workspace.header.redo" "Redo (Ctrl + Shift + Z)"
+ "workspace.header.download" "Download (Ctrl + E)"
+ "workspace.header.image" "Image (Ctrl + I)"
+ "workspace.header.rules" "Rules"
+ "workspace.header.grid" "Grid (Ctrl + G)"
+ "workspace.header.grid-snap" "Snap to grid"
+ "workspace.header.align" "Align (Ctrl + A)"
+ "workspace.header.view-mode" "View mode (Ctrl + P)"
+
+ "workspace.options.radius" "Radius"
+ "workspace.options.size" "Size"
+ "workspace.options.width" "Width"
+ "workspace.options.height" "Height"
+ "workspace.options.stroke.style" "Style"
+ "workspace.options.stroke.none" "None"
+ "workspace.options.stroke.solid" "Solid"
+ "workspace.options.stroke.dotted" "Dotted"
+ "workspace.options.stroke.dashed" "Dashed"
+ "workspace.options.stroke.mixed" "Mixed"
+ "workspace.options.position" "Position"
+ "workspace.options.rotation" "Rotation"
+ "workspace.options.opacity" "Opacity"
+ "workspace.options.color" "Color"
+ "workspace.options.background-color" "Background color"
+ "workspace.options.font-family" "Font Family"
+ "workspace.options.font-weight" "Font Size & Weight"
+ "workspace.options.font-size" "Font Size"
+ "workspace.options.line-height-letter-spacing" "Line height and Letter spacing"
+ "workspace.options.line-height" "Line Height"
+ "workspace.options.letter-spacing" "Letter Spacing"
+ "workspace.options.text-align" "Text Alignment"
+ "workspace.options.name" "Name"
+ "workspace.options.go" "Go go go!"
+ "workspace.options.measures" "Size, position & rotation"
+ "workspace.options.font-options" "Fonts & Font Size"
+ "workspace.options.rotation-radius" "Rotation & Radius"
+ "workspace.options.stroke" "Stroke"
+ "workspace.options.grid-options" "Grid settings"
+
+ "element.fill" "Fill"
+ "element.text" "Text"
+ "element.interactions" "Interactions"
+
+ "image.new" "New image"
+ "image.select" "Select from library"
+ "image.upload" "Upload file"
+ "image.import-library" "Import image from library"
+
+ "auth.email-or-username" "Email or Username"
+ "auth.password" "Password"
+ "auth.signin" "Sign in"
+ "auth.forgot-password" "Forgot your password?"
+ "auth.no-account" "Don't have an account?"
+ "auth.message.recovery-token-sent" "Password recovery link sent to your inbox."
+ "auth.message.password-recovered" "Password successfully recovered."
+
+ "register.fullname.placeholder" "Full Name"
+ "register.username.placeholder" "Username"
+ "register.email.placeholder" "Email"
+ "register.password.placeholder" "Password"
+ "register.get-started" "Get started"
+ "register.already-have-account" "Already have an account?"
+
+ "recovery-request.username-or-email.placeholder" "username or email address"
+ "recovery-request.recover-password" "Recover password"
+ "recovery-request.go-back" "Go back!"
+
+ "recover.password.placeholder" "Password"
+ "recover.recover-password" "Recover password"
+ "recover.go-back" "Go back!"
+
+ "settings.profile" "PROFILE"
+ "settings.password" "PASSWORD"
+ "settings.notifications" "NOTIFICATIONS"
+ "settings.exit" "EXIT"
+
+ "settings.profile.profile-saved" "Profile saved successfully!"
+ "settings.profile.section-basic-data" "Name, username and email"
+ "settings.profile.section-i18n-data" "Default language"
+ "settings.profile.your-name" "Your name"
+ "settings.profile.your-username" "Your username"
+ "settings.profile.your-email" "Your email"
+
+ "settings.choose-color-theme" "Choose a theme"
+ "settings.profile.light-theme" "Light theme"
+ "settings.profile.dark-theme" "Dark theme"
+ "settings.profile.high-contrast-theme" "High-contrast theme"
+ "settings.profile.your-avatar" "Your avatar"
+
+ "settings.password.password-saved" "Password saved successfully!"
+ "settings.password.wrong-old-password" "Wrong old password"
+ "settings.password.change-password" "Change password"
+ "settings.password.old-password" "Old password"
+ "settings.password.new-password" "New password"
+ "settings.password.confirm-password" "Confirm password"
+
+ "settings.notifications.notifications-saved" "Notifications preferences saved successfully!"
+ "settings.notifications.prototype-notifications" "Prototype notifications"
+ "settings.notifications.description" "Get a roll up of prototype changes in your inbox."
+ "settings.notifications.none" "None"
+ "settings.notifications.every-hour" "Every hour"
+ "settings.notifications.every-day" "Every day"
+
+ "settings.update-settings" "Update settings"
+
+ "history.alert-message" "You are seeing version %s"
+
+ "errors.api.form.unexpected-error" "An unexpected error occurred."
+ "errors.api.form.old-password-not-match" "Incorrect old password"
+ "errors.api.form.registration-disabled" "The registration is currently disabled."
+ "errors.api.form.email-already-exists" "The email is already in use by another user."
+ "errors.api.form.username-already-exists" "The username is already in use by another user."
+ "errors.api.form.user-not-exists" "Username or email does not matches any existing user."
+ "errors.form.required" "This field is mandatory"
+ "errors.form.string" "Should be string"
+ "errors.form.number" "Invalid number"
+ "errors.form.integer" "Invalid integer"
+ "errors.form.bool" "Should be boolean"
+ "errors.form.min-len" "Should be greater than %s"
+ "errors.form.max-len" "Should be lesser than %s"
+ "errors.form.color" "Should be a valid color string"
+ "errors.form.password-not-match" "Password does not match"
+ "errors.auth.unauthorized" "Username or password seems to be wrong."
+ "errors.auth.invalid-recovery-token" "The recovery token is invalid."
+ "errors.profile.update-password" "Error updating password, probably your old password is wrong."
+
+ "errors.network" "Unable to connect to backend server."
+ "errors.generic" "Something wrong has happened."
+ "errors.conflict" "Conflict on saving data, please refresh and try again."
+ }
diff --git a/frontend/legacy.fr.edn b/frontend/legacy.fr.edn
new file mode 100644
index 000000000..e0455850f
--- /dev/null
+++ b/frontend/legacy.fr.edn
@@ -0,0 +1,223 @@
+{"ds.projects" "PROJETS"
+ "ds.project-title" "Vos projets"
+ "ds.project-new" "+ Nouveau projet"
+ "ds.project-thumbnail.alt" "Titre du projet"
+
+ "ds.ordering" "Trier par"
+ "ds.ordering.by-name" "nom"
+ "ds.ordering.by-last-update" "dernière mise à jour"
+ "ds.ordering.by-creation-date" "date de création"
+ "ds.search.placeholder" "Rechercher..."
+ "ds.uploaded-at" "Mise en ligne : %s"
+ "ds.updated-at" "Mis à jour %s"
+
+ "ds.confirm-title" "Êtes-vous sûr ?"
+ "ds.confirm-ok" "Ok"
+ "ds.confirm-cancel" "Annuler"
+
+ "ds.multiselect-bar.copy" "Copier"
+ "ds.multiselect-bar.copy-to-library" "Copier vers la librairie"
+ "ds.multiselect-bar.move" "Déplacer"
+ "ds.multiselect-bar.move-to-library" "Déplacer vers la librairie"
+ "ds.multiselect-bar.rename" "Renommer"
+ "ds.multiselect-bar.delete" "Supprimer"
+
+ "ds.elements" "ÉLÉMENTS"
+ "ds.icons" "ICÔNES"
+ "ds.your-icons-title" "VOS ICÔNES"
+ "ds.store-icons-title" "BOUTIQUE"
+ "ds.icons-collection.new" "+ Nouvelle collection"
+ "ds.icon-new" "+ Nouvel icône"
+
+ "ds.images" "IMAGES"
+ "ds.your-images-title" "VOS IMAGES"
+ "ds.store-images-title" "BOUTIQUE"
+ "ds.images-collection.new" "+ Nouvelle librairie"
+ "ds.image-new" "+ Nouvelle image"
+
+ "ds.colors" "COULEURS"
+ "ds.your-colors-title" "VOS COULEURS"
+ "ds.store-colors-title" "BOUTIQUE"
+ "ds.colors-collection.new" "+ Nouvelle librairie"
+ "ds.color-new" "+ Nouvelle couleur"
+ "ds.color-lightbox.title" "Nouvelle couleur"
+ "ds.color-lightbox.add" "+ Ajouter couleur"
+
+ "ds.library-title" "Librairie : "
+ "ds.standard-title" "STANDARD"
+ "ds.your-libraries-title" "VOS LIBRAIRIES"
+ "ds.default-library-title" "Collection sans nom (%s)"
+
+ "ds.project.placeholder" "Nom du nouveau projet"
+ "ds.project.new" "Nouveau projet"
+
+
+ "ds.accept" "Accepter"
+ "ds.cancel" "Annuler"
+
+ "workspace.sidebar.icons" "Icônes"
+ "workspace.sidebar.element-options" "Options d'élément"
+ "workspace.sidebar.draw-tools" "Outils de dessin"
+ "workspace.sidebar.sitemap" "Plan du site"
+ "workspace.sidebar.layers" "Couches"
+ "workspace.sidebar.document-history" "Historique du document"
+
+ "ds.page.placeholder" "Nom de la page"
+ "ds.page.new" "Nouvelle page"
+ "ds.page.edit" "Éditer la page"
+
+ "ds.history.versions" "Historique"
+ "ds.history.pinned" "Épinglés"
+
+ "workspace.header.rect" "Boîte (Ctrl + B)"
+ "workspace.header.circle" "Cercle (Ctrl + E)"
+ "workspace.header.line" "Ligne (Ctrl + L)"
+ "workspace.header.text" "Texte"
+ "workspace.header.path" "Chemin"
+ "workspace.header.curve" "Courbe"
+ "workspace.header.ruler" "Règle"
+ "workspace.header.canvas" "Calque"
+
+ "ds.user.profile" "Profil"
+ "ds.user.password" "Mot de passe"
+ "ds.user.notifications" "Notifications"
+ "ds.user.exit" "Quitter"
+
+ "workspace.header.sitemap" "Plan du site (Ctrl + Maj + M)"
+ "workspace.header.draw-tools" "Outils de dessin (Ctrl + Maj + S)"
+ "workspace.header.color-palette" "Palette de couleurs (---)"
+ "workspace.header.icons" "Icônes (Ctrl + Maj + I)"
+ "workspace.header.layers" "Couches (Ctrl + Maj + L)"
+ "workspace.header.element-options" "Options d'élément (Ctrl + Maj + O)"
+ "workspace.header.document-history" "Historique du document (Ctrl + Maj + H)"
+ "workspace.header.undo" "Annuler (Ctrl + Z)"
+ "workspace.header.redo" "Rétablir (Ctrl + Maj + Z)"
+ "workspace.header.download" "Télécharger (Ctrl + E)"
+ "workspace.header.image" "Image (Ctrl + I)"
+ "workspace.header.rules" "Règles"
+ "workspace.header.grid" "Grille (Ctrl + G)"
+ "workspace.header.grid-snap" "Coller à la grille"
+ "workspace.header.align" "Aligner (Ctrl + A)"
+ "workspace.header.view-mode" "Mode visualisation (Ctrl + P)"
+
+ "workspace.options.radius" "Rayon"
+ "workspace.options.size" "Taille"
+ "workspace.options.width" "Largeur"
+ "workspace.options.height" "Hauteur"
+ "workspace.options.stroke.style" "Style"
+ "workspace.options.stroke.none" "Aucun"
+ "workspace.options.stroke.solid" "Solide"
+ "workspace.options.stroke.dotted" "Pointillé"
+ "workspace.options.stroke.dashed" "Tiré"
+ "workspace.options.stroke.mixed" "Mixte"
+ "workspace.options.position" "Position"
+ "workspace.options.rotation" "Rotation"
+ "workspace.options.opacity" "Opacité"
+ "workspace.options.color" "Couleur"
+ "workspace.options.background-color" "Couleur d'arrière-plan"
+ "workspace.options.font-family" "Police de caractères"
+ "workspace.options.font-weight" "Taille et graisse"
+ "workspace.options.font-size" "Taille de police"
+ "workspace.options.line-height-letter-spacing" "Hauteur de ligne et Espacement de caractères"
+ "workspace.options.line-height" "Hauteur de ligne"
+ "workspace.options.letter-spacing" "Espacement de caractères"
+ "workspace.options.text-align" "Alignement de texte"
+ "workspace.options.name" "Nom"
+ "workspace.options.go" "C'est parti !"
+ "workspace.options.measures" "Taille, position et rotation"
+ "workspace.options.font-options" "TODO"
+ "workspace.options.rotation-radius" "TODO"
+ "workspace.options.strokestroke" "Contour"
+ "workspace.options.grid-options" "Paramètres de la grille"
+
+ "element.fill" "Fond"
+ "element.text" "Texte"
+ "element.interactions" "Interactions"
+
+ "image.new" "Nouvelle image"
+ "image.select" "Choisir depuis une librairie"
+ "image.upload" "Envoyer un fichier"
+ "image.import-library" "Importer une image depuis une librairie"
+
+ "auth.email-or-username" "adresse email ou nom d'utilisateur"
+ "auth.password" "Mot de passe"
+ "auth.signin" "Se connecter"
+ "auth.forgot-password" "Mot de passe oublié ?"
+ "auth.no-account" "Vous n'avez pas de compte ?"
+ "auth.message.recovery-token-sent" "Lien de récupération de mot de passe envoyé."
+ "auth.message.password-recovered" "Mot de passe récupéré avec succès."
+
+ "register.fullname.placeholder" "Nom complet"
+ "register.username.placeholder" "Nom d'utilisateur"
+ "register.email.placeholder" "Adresse email"
+ "register.password.placeholder" "Mot de passe"
+ "register.get-started" "Commencer"
+ "register.already-have-account" "Vous avez déjà un compte ?"
+
+ "recovery-request.username-or-email.placeholder" "nom d'utilisateur ou adresse email"
+ "recovery-request.recover-password" "Récupérer le mot de passe"
+ "recovery-request.go-back" "Retour!"
+
+ "recover.password.placeholder" "Mot de passe"
+ "recover.recover-password" "Récupérer le mot de passe"
+ "recover.go-back" "Retour!"
+
+ "settings.profile" "PROFIL"
+ "settings.password" "MOT DE PASSE"
+ "settings.notifications" "NOTIFICATIONS"
+ "settings.exit" "QUITTER"
+
+ "settings.profile.profile-saved" "Profil enregistré avec succès !"
+ "settings.profile.section-basic-data" "Nom, nom d'utilisateur et adresse email"
+ "settings.profile.section-i18n-data" "Langue par défaut"
+ "settings.profile.your-name" "Votre nom complet"
+ "settings.profile.your-username" "Votre nom d'utilisateur"
+ "settings.profile.your-email" "Votre adresse email"
+
+ "settings.choose-color-theme" "Choisissez un thème"
+ "settings.profile.light-theme" "Thème Jour"
+ "settings.profile.dark-theme" "Thème Nuit"
+ "settings.profile.high-contrast-theme" "Thème Contraste élevé"
+ "settings.profile.your-avatar" "Votre avatar"
+
+ "settings.password.password-saved" "Mot de passe enregistré avec succès !"
+ "settings.password.wrong-old-password" "Ancien mot de passe incorrect"
+ "settings.password.change-password" "Changement de mot de passe"
+ "settings.password.old-password" "Ancien mot de passe"
+ "settings.password.new-password" "Nouveau mot de passe"
+ "settings.password.confirm-password" "Confirmez mot de passe"
+
+ "settings.notifications.notifications-saved" "Préférences de notifications enregistrées avec succès !"
+ "settings.notifications.prototype-notifications" "Notifications de prototypage"
+ "settings.notifications.description" "Obtenez un résumé des modifications apportées aux prototypes à votre adresse email."
+ "settings.notifications.none" "Aucune"
+ "settings.notifications.every-hour" "Chaque heure"
+ "settings.notifications.every-day" "Chaque jour"
+
+ "settings.update-settings" "Mettre à jour les paramètres"
+
+ "history.alert-message" "Vous voyez la version %s"
+
+ "errors.api.form.unexpected-error" "Une erreur inattendue c'est produite"
+ "errors.api.form.old-password-not-match" "Ancien mot de passe incorrect"
+ "errors.api.form.registration-disabled" "L'enregistrement est actuellement désactivé."
+ "errors.api.form.email-already-exists" "L'email est déjà utilisé par un autre utilisateur."
+ "errors.api.form.username-already-exists" "Le nom d'utilisateur est déjà utilisé par un autre utilisateur."
+ "errors.api.form.user-not-exists" "Le nom d'utilisateur ou l'e-mail ne correspond à aucun utilisateur existant."
+ "errors.form.required" "Ce champ est obligatoire"
+ "errors.form.string" "Devrait être une chaîne de caractères"
+ "errors.form.number" "Nombre invalide"
+ "errors.form.integer" "Entier invalide"
+ "errors.form.bool" "Devrait être un booléen"
+ "errors.form.min-len" "Devrait être supérieur à %s"
+ "errors.form.max-len" "Devrait être inférieur à %s"
+ "errors.form.color" "Devrait être une couleur valide"
+ "errors.form.password-not-match" "Le mot de passe ne correspond pas"
+ "errors.auth.unauthorized" "Le nom d'utilisateur ou le mot de passe semble être faux."
+ "errors.auth.invalid-recovery-token" "Le jeton de récupération n'est pas valide."
+ "errors.profile.update-password" "Erreur lors de la mise à jour du mot de passe, votre ancien mot de passe est probablement incorrect."
+
+ "errors.network" "Impossible de se connecter au serveur principal."
+ "errors.generic" "Quelque chose c'est mal passé."
+ "errors.conflict" "Conflit sur la sauvegarde des données, actualisez et réessayez."
+ }
diff --git a/frontend/resources/locales.json b/frontend/resources/locales.json
new file mode 100644
index 000000000..447ec5f68
--- /dev/null
+++ b/frontend/resources/locales.json
@@ -0,0 +1,891 @@
+{
+ "auth.email-or-username" : {
+ "used-in" : [ "src/uxbox/main/ui/auth/login.cljs:61" ],
+ "translations" : {
+ "en" : "Email or Username",
+ "fr" : "adresse email ou nom d'utilisateur"
+ }
+ },
+ "auth.forgot-password" : {
+ "used-in" : [ "src/uxbox/main/ui/auth/login.cljs:83" ],
+ "translations" : {
+ "en" : "Forgot your password?",
+ "fr" : "Mot de passe oublié ?"
+ }
+ },
+ "auth.message.password-recovered" : {
+ "used-in" : [ "src/uxbox/main/data/auth.cljs:178" ],
+ "translations" : {
+ "en" : "Password successfully recovered.",
+ "fr" : "Mot de passe récupéré avec succès."
+ }
+ },
+ "auth.message.recovery-token-sent" : {
+ "used-in" : [ "src/uxbox/main/data/auth.cljs:141" ],
+ "translations" : {
+ "en" : "Password recovery link sent to your inbox.",
+ "fr" : "Lien de récupération de mot de passe envoyé."
+ }
+ },
+ "auth.no-account" : {
+ "used-in" : [ "src/uxbox/main/ui/auth/login.cljs:86" ],
+ "translations" : {
+ "en" : "Don't have an account?",
+ "fr" : "Vous n'avez pas de compte ?"
+ }
+ },
+ "auth.password" : {
+ "used-in" : [ "src/uxbox/main/ui/auth/login.cljs:70" ],
+ "translations" : {
+ "en" : "Password",
+ "fr" : "Mot de passe"
+ }
+ },
+ "auth.signin" : {
+ "used-in" : [ "src/uxbox/main/ui/auth/login.cljs:77" ],
+ "translations" : {
+ "en" : "Sign in",
+ "fr" : "Se connecter"
+ }
+ },
+ "ds.accept" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/history.cljs:113" ],
+ "translations" : {
+ "en" : null,
+ "fr" : "Accepter"
+ }
+ },
+ "ds.cancel" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/history.cljs:114" ],
+ "translations" : {
+ "en" : null,
+ "fr" : "Annuler"
+ }
+ },
+ "ds.color-lightbox.add" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/colors.cljs:52" ],
+ "translations" : {
+ "en" : "+ Add color",
+ "fr" : "+ Ajouter couleur"
+ }
+ },
+ "ds.color-new" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/colors.cljs:149" ],
+ "translations" : {
+ "en" : "+ New color",
+ "fr" : "+ Nouvelle couleur"
+ }
+ },
+ "ds.colors" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/header.cljs:48" ],
+ "translations" : {
+ "en" : "COLORS",
+ "fr" : "COULEURS"
+ }
+ },
+ "ds.colors-collection.new" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/colors.cljs:134" ],
+ "translations" : {
+ "en" : "+ New library",
+ "fr" : "+ Nouvelle librairie"
+ }
+ },
+ "ds.confirm-cancel" : {
+ "used-in" : [ "src/uxbox/main/ui/confirm.cljs:38" ],
+ "translations" : {
+ "en" : "Cancel",
+ "fr" : "Annuler"
+ }
+ },
+ "ds.confirm-ok" : {
+ "used-in" : [ "src/uxbox/main/ui/confirm.cljs:34" ],
+ "translations" : {
+ "en" : "Ok",
+ "fr" : "Ok"
+ }
+ },
+ "ds.confirm-title" : {
+ "used-in" : [ "src/uxbox/main/ui/confirm.cljs:28" ],
+ "translations" : {
+ "en" : "Are you sure?",
+ "fr" : "Êtes-vous sûr ?"
+ }
+ },
+ "ds.default-library-title" : {
+ "used-in" : [ "src/uxbox/main/data/images.cljs:99", "src/uxbox/main/data/icons.cljs:87", "src/uxbox/main/data/colors.cljs:68" ],
+ "translations" : {
+ "en" : "Unnamed Collection (%s)",
+ "fr" : "Collection sans nom (%s)"
+ }
+ },
+ "ds.foobar" : {
+ "translations" : {
+ "en" : null,
+ "fr" : null
+ },
+ "permanent" : true
+ },
+ "ds.height" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/icon_measures.cljs:46" ],
+ "translations" : {
+ "en" : null,
+ "fr" : null
+ }
+ },
+ "ds.history.pinned" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/history.cljs:95" ],
+ "translations" : {
+ "en" : "Pinned",
+ "fr" : "Épinglés"
+ }
+ },
+ "ds.history.versions" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/history.cljs:92" ],
+ "translations" : {
+ "en" : "History",
+ "fr" : "Historique"
+ }
+ },
+ "ds.icon-new" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/icons.cljs:158" ],
+ "translations" : {
+ "en" : "+ New icon",
+ "fr" : "+ Nouvel icône"
+ }
+ },
+ "ds.icons" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/header.cljs:42" ],
+ "translations" : {
+ "en" : "ICONS",
+ "fr" : "ICÔNES"
+ }
+ },
+ "ds.icons-collection.new" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/icons.cljs:137" ],
+ "translations" : {
+ "en" : "+ New collection",
+ "fr" : "+ Nouvelle collection"
+ }
+ },
+ "ds.image-new" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/images.cljs:252" ],
+ "translations" : {
+ "en" : "+ New image",
+ "fr" : "+ Nouvelle image"
+ }
+ },
+ "ds.images" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/header.cljs:45" ],
+ "translations" : {
+ "en" : "IMAGES",
+ "fr" : "IMAGES"
+ }
+ },
+ "ds.images-collection.new" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/images.cljs:108" ],
+ "translations" : {
+ "en" : "+ New library",
+ "fr" : "+ Nouvelle librairie"
+ }
+ },
+ "ds.multiselect-bar.copy" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/images.cljs:196", "src/uxbox/main/ui/dashboard/images.cljs:171", "src/uxbox/main/ui/dashboard/colors.cljs:224", "src/uxbox/main/ui/dashboard/colors.cljs:201" ],
+ "translations" : {
+ "en" : "Copy",
+ "fr" : "Copier"
+ }
+ },
+ "ds.multiselect-bar.copy-to-library" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/images.cljs:200", "src/uxbox/main/ui/dashboard/images.cljs:175", "src/uxbox/main/ui/dashboard/colors.cljs:228", "src/uxbox/main/ui/dashboard/colors.cljs:205" ],
+ "translations" : {
+ "en" : "Copy to library",
+ "fr" : "Copier vers la librairie"
+ }
+ },
+ "ds.multiselect-bar.delete" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/images.cljs:190", "src/uxbox/main/ui/dashboard/colors.cljs:217" ],
+ "translations" : {
+ "en" : "Delete",
+ "fr" : "Supprimer"
+ }
+ },
+ "ds.multiselect-bar.move" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/images.cljs:179", "src/uxbox/main/ui/dashboard/colors.cljs:209" ],
+ "translations" : {
+ "en" : "Move",
+ "fr" : "Déplacer"
+ }
+ },
+ "ds.multiselect-bar.move-to-library" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/images.cljs:183", "src/uxbox/main/ui/dashboard/colors.cljs:213" ],
+ "translations" : {
+ "en" : "Move to library",
+ "fr" : "Déplacer vers la librairie"
+ }
+ },
+ "ds.multiselect-bar.rename" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/images.cljs:187" ],
+ "translations" : {
+ "en" : "Rename",
+ "fr" : "Renommer"
+ }
+ },
+ "ds.new-file" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/projects.cljs:143" ],
+ "translations" : {
+ "en" : "+ New File",
+ "fr" : null
+ }
+ },
+ "ds.position" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/icon_measures.cljs:52" ],
+ "translations" : {
+ "en" : null,
+ "fr" : null
+ }
+ },
+ "ds.projects" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/header.cljs:39" ],
+ "translations" : {
+ "en" : "PROJECTS",
+ "fr" : "PROJETS"
+ }
+ },
+ "ds.rotation" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/icon_measures.cljs:67" ],
+ "translations" : {
+ "en" : null,
+ "fr" : null
+ }
+ },
+ "ds.search.placeholder" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/projects.cljs:192" ],
+ "translations" : {
+ "en" : "Search...",
+ "fr" : "Rechercher..."
+ }
+ },
+ "ds.settings.document-history" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/history.cljs:86" ],
+ "translations" : {
+ "en" : null,
+ "fr" : null
+ }
+ },
+ "ds.settings.layers" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/layers.cljs:260" ],
+ "translations" : {
+ "en" : null,
+ "fr" : null
+ }
+ },
+ "ds.size" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/icon_measures.cljs:33" ],
+ "translations" : {
+ "en" : null,
+ "fr" : null
+ }
+ },
+ "ds.store-colors-title" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/colors.cljs:129" ],
+ "translations" : {
+ "en" : "COLORS STORE",
+ "fr" : "BOUTIQUE"
+ }
+ },
+ "ds.store-icons-title" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/icons.cljs:131" ],
+ "translations" : {
+ "en" : "ICONS STORE",
+ "fr" : "BOUTIQUE"
+ }
+ },
+ "ds.store-images-title" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/images.cljs:146", "src/uxbox/main/ui/dashboard/images.cljs:102" ],
+ "translations" : {
+ "en" : "IMAGES STORE",
+ "fr" : "BOUTIQUE"
+ }
+ },
+ "ds.updated-at" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/projects.cljs:110" ],
+ "translations" : {
+ "en" : "Updated %s",
+ "fr" : "Mis à jour %s"
+ }
+ },
+ "ds.uploaded-at" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/images.cljs:237", "src/uxbox/main/ui/dashboard/icons.cljs:303" ],
+ "translations" : {
+ "en" : "Uploaded at %s",
+ "fr" : "Mise en ligne : %s"
+ }
+ },
+ "ds.user.exit" : {
+ "used-in" : [ "src/uxbox/main/ui/users.cljs:43" ],
+ "translations" : {
+ "en" : "Exit",
+ "fr" : "Quitter"
+ }
+ },
+ "ds.user.notifications" : {
+ "used-in" : [ "src/uxbox/main/ui/users.cljs:40" ],
+ "translations" : {
+ "en" : "Notifications",
+ "fr" : "Notifications"
+ }
+ },
+ "ds.user.password" : {
+ "used-in" : [ "src/uxbox/main/ui/users.cljs:37" ],
+ "translations" : {
+ "en" : "Password",
+ "fr" : "Mot de passe"
+ }
+ },
+ "ds.user.profile" : {
+ "used-in" : [ "src/uxbox/main/ui/users.cljs:34" ],
+ "translations" : {
+ "en" : "Profile",
+ "fr" : "Profil"
+ }
+ },
+ "ds.width" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/icon_measures.cljs:36" ],
+ "translations" : {
+ "en" : null,
+ "fr" : null
+ }
+ },
+ "ds.your-colors-title" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/colors.cljs:126" ],
+ "translations" : {
+ "en" : "YOUR COLORS",
+ "fr" : "VOS COULEURS"
+ }
+ },
+ "ds.your-icons-title" : {
+ "used-in" : [ "src/uxbox/main/ui/dashboard/icons.cljs:128" ],
+ "translations" : {
+ "en" : "YOUR ICONS",
+ "fr" : "VOS ICÔNES"
+ }
+ },
+ "ds.your-images-title" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/images.cljs:143", "src/uxbox/main/ui/dashboard/images.cljs:99" ],
+ "translations" : {
+ "en" : "YOUR IMAGES",
+ "fr" : "VOS IMAGES"
+ }
+ },
+ "element.fill" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:44" ],
+ "translations" : {
+ "en" : "Fill",
+ "fr" : "Fond"
+ }
+ },
+ "errors.api.form.registration-disabled" : {
+ "used-in" : [ "src/uxbox/main/ui/auth/register.cljs:39" ],
+ "translations" : {
+ "en" : "The registration is currently disabled.",
+ "fr" : "L'enregistrement est actuellement désactivé."
+ }
+ },
+ "errors.api.form.unexpected-error" : {
+ "used-in" : [ "src/uxbox/main/ui/auth/register.cljs:51" ],
+ "translations" : {
+ "en" : "An unexpected error occurred.",
+ "fr" : "Une erreur inattendue c'est produite"
+ }
+ },
+ "errors.auth.invalid-recovery-token" : {
+ "used-in" : [ "src/uxbox/main/data/auth.cljs:174", "src/uxbox/main/data/auth.cljs:151" ],
+ "translations" : {
+ "en" : "The recovery token is invalid.",
+ "fr" : "Le jeton de récupération n'est pas valide."
+ }
+ },
+ "errors.auth.unauthorized" : {
+ "used-in" : [ "src/uxbox/main/data/auth.cljs:59" ],
+ "translations" : {
+ "en" : "Username or password seems to be wrong.",
+ "fr" : "Le nom d'utilisateur ou le mot de passe semble être faux."
+ }
+ },
+ "errors.generic" : {
+ "used-in" : [ "src/uxbox/main/ui.cljs:86" ],
+ "translations" : {
+ "en" : "Something wrong has happened.",
+ "fr" : "Quelque chose c'est mal passé."
+ }
+ },
+ "errors.network" : {
+ "used-in" : [ "src/uxbox/main/ui.cljs:80" ],
+ "translations" : {
+ "en" : "Unable to connect to backend server.",
+ "fr" : "Impossible de se connecter au serveur principal."
+ }
+ },
+ "header.sitemap" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:83" ],
+ "translations" : {
+ "en" : null,
+ "fr" : null
+ }
+ },
+ "history.alert-message" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/history.cljs:111" ],
+ "translations" : {
+ "en" : "You are seeing version %s",
+ "fr" : "Vous voyez la version %s"
+ }
+ },
+ "image.import-library" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/images.cljs:137" ],
+ "translations" : {
+ "en" : "Import image from library",
+ "fr" : "Importer une image depuis une librairie"
+ }
+ },
+ "image.new" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/images.cljs:71" ],
+ "translations" : {
+ "en" : "New image",
+ "fr" : "Nouvelle image"
+ }
+ },
+ "image.select" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/images.cljs:75" ],
+ "translations" : {
+ "en" : "Select from library",
+ "fr" : "Choisir depuis une librairie"
+ }
+ },
+ "image.upload" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/images.cljs:80" ],
+ "translations" : {
+ "en" : "Upload file",
+ "fr" : "Envoyer un fichier"
+ }
+ },
+ "register.already-have-account" : {
+ "used-in" : [ "src/uxbox/main/ui/auth/register.cljs:131" ],
+ "translations" : {
+ "en" : "Already have an account?",
+ "fr" : "Vous avez déjà un compte ?"
+ }
+ },
+ "register.fullname.placeholder" : {
+ "used-in" : [ "src/uxbox/main/ui/auth/register.cljs:72" ],
+ "translations" : {
+ "en" : "Full Name",
+ "fr" : "Nom complet"
+ }
+ },
+ "register.get-started" : {
+ "used-in" : [ "src/uxbox/main/ui/auth/register.cljs:127" ],
+ "translations" : {
+ "en" : "Get started",
+ "fr" : "Commencer"
+ }
+ },
+ "register.password.placeholder" : {
+ "used-in" : [ "src/uxbox/main/ui/auth/register.cljs:115" ],
+ "translations" : {
+ "en" : "Password",
+ "fr" : "Mot de passe"
+ }
+ },
+ "settings.notifications" : {
+ "used-in" : [ "src/uxbox/main/ui/settings/header.cljs:43" ],
+ "translations" : {
+ "en" : "NOTIFICATIONS",
+ "fr" : "NOTIFICATIONS"
+ }
+ },
+ "settings.notifications.description" : {
+ "used-in" : [ "src/uxbox/main/ui/settings/notifications.cljs:19" ],
+ "translations" : {
+ "en" : "Get a roll up of prototype changes in your inbox.",
+ "fr" : "Obtenez un résumé des modifications apportées aux prototypes à votre adresse email."
+ }
+ },
+ "settings.notifications.every-day" : {
+ "used-in" : [ "src/uxbox/main/ui/settings/notifications.cljs:38" ],
+ "translations" : {
+ "en" : "Every day",
+ "fr" : "Chaque jour"
+ }
+ },
+ "settings.notifications.every-hour" : {
+ "used-in" : [ "src/uxbox/main/ui/settings/notifications.cljs:32" ],
+ "translations" : {
+ "en" : "Every hour",
+ "fr" : "Chaque heure"
+ }
+ },
+ "settings.notifications.none" : {
+ "used-in" : [ "src/uxbox/main/ui/settings/notifications.cljs:26" ],
+ "translations" : {
+ "en" : "None",
+ "fr" : "Aucune"
+ }
+ },
+ "settings.notifications.notifications-saved" : {
+ "used-in" : [ "src/uxbox/main/ui/settings/notifications.cljs:18" ],
+ "translations" : {
+ "en" : "Notifications preferences saved successfully!",
+ "fr" : "Préférences de notifications enregistrées avec succès !"
+ }
+ },
+ "settings.password" : {
+ "used-in" : [ "src/uxbox/main/ui/settings/header.cljs:40" ],
+ "translations" : {
+ "en" : "PASSWORD",
+ "fr" : "MOT DE PASSE"
+ }
+ },
+ "settings.password.change-password" : {
+ "used-in" : [ "src/uxbox/main/ui/settings/password.cljs:50" ],
+ "translations" : {
+ "en" : "Change password",
+ "fr" : "Changement de mot de passe"
+ }
+ },
+ "settings.password.confirm-password" : {
+ "used-in" : [ "src/uxbox/main/ui/settings/password.cljs:79" ],
+ "translations" : {
+ "en" : "Confirm password",
+ "fr" : "Confirmez mot de passe"
+ }
+ },
+ "settings.password.new-password" : {
+ "used-in" : [ "src/uxbox/main/ui/settings/password.cljs:69" ],
+ "translations" : {
+ "en" : "New password",
+ "fr" : "Nouveau mot de passe"
+ }
+ },
+ "settings.password.old-password" : {
+ "used-in" : [ "src/uxbox/main/ui/settings/password.cljs:58" ],
+ "translations" : {
+ "en" : "Old password",
+ "fr" : "Ancien mot de passe"
+ }
+ },
+ "settings.password.password-saved" : {
+ "used-in" : [ "src/uxbox/main/ui/settings/password.cljs:33" ],
+ "translations" : {
+ "en" : "Password saved successfully!",
+ "fr" : "Mot de passe enregistré avec succès !"
+ }
+ },
+ "settings.profile" : {
+ "used-in" : [ "src/uxbox/main/ui/settings/header.cljs:37" ],
+ "translations" : {
+ "en" : "PROFILE",
+ "fr" : "PROFIL"
+ }
+ },
+ "settings.profile.profile-saved" : {
+ "used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:68" ],
+ "translations" : {
+ "en" : "Profile saved successfully!",
+ "fr" : "Profil enregistré avec succès !"
+ }
+ },
+ "settings.profile.section-basic-data" : {
+ "used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:78" ],
+ "translations" : {
+ "en" : "Name, username and email",
+ "fr" : "Nom, nom d'utilisateur et adresse email"
+ }
+ },
+ "settings.profile.section-i18n-data" : {
+ "used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:117" ],
+ "translations" : {
+ "en" : "Default language",
+ "fr" : "Langue par défaut"
+ }
+ },
+ "settings.profile.your-avatar" : {
+ "used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:159" ],
+ "translations" : {
+ "en" : "Your avatar",
+ "fr" : "Votre avatar"
+ }
+ },
+ "settings.profile.your-email" : {
+ "used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:111", "src/uxbox/main/ui/auth/register.cljs:101" ],
+ "translations" : {
+ "en" : "Your email",
+ "fr" : "Votre adresse email"
+ }
+ },
+ "settings.profile.your-name" : {
+ "used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:86" ],
+ "translations" : {
+ "en" : "Your name",
+ "fr" : "Votre nom complet"
+ }
+ },
+ "settings.profile.your-username" : {
+ "used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:98", "src/uxbox/main/ui/auth/register.cljs:87" ],
+ "translations" : {
+ "en" : "Your username",
+ "fr" : "Votre nom d'utilisateur"
+ }
+ },
+ "settings.update-settings" : {
+ "used-in" : [ "src/uxbox/main/ui/settings/profile.cljs:130", "src/uxbox/main/ui/settings/password.cljs:86", "src/uxbox/main/ui/settings/notifications.cljs:42" ],
+ "translations" : {
+ "en" : "Update settings",
+ "fr" : "Mettre à jour les paramètres"
+ }
+ },
+ "workspace.header.canvas" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:93" ],
+ "translations" : {
+ "en" : "Canvas",
+ "fr" : "Calque"
+ }
+ },
+ "workspace.header.circle" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:103" ],
+ "translations" : {
+ "en" : "Circle (Ctrl + E)",
+ "fr" : "Cercle (Ctrl + E)"
+ }
+ },
+ "workspace.header.color-palette" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:123" ],
+ "translations" : {
+ "en" : "Color Palette (---)",
+ "fr" : "Palette de couleurs (---)"
+ }
+ },
+ "workspace.header.curve" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:118" ],
+ "translations" : {
+ "en" : "Curve",
+ "fr" : "Courbe"
+ }
+ },
+ "workspace.header.document-history" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:143" ],
+ "translations" : {
+ "en" : "History (Ctrl + Shift + H)",
+ "fr" : "Historique du document (Ctrl + Maj + H)"
+ }
+ },
+ "workspace.header.download" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:156" ],
+ "translations" : {
+ "en" : "Download (Ctrl + E)",
+ "fr" : "Télécharger (Ctrl + E)"
+ }
+ },
+ "workspace.header.grid" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:170" ],
+ "translations" : {
+ "en" : "Grid (Ctrl + G)",
+ "fr" : "Grille (Ctrl + G)"
+ }
+ },
+ "workspace.header.grid-snap" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:175" ],
+ "translations" : {
+ "en" : "Snap to grid",
+ "fr" : "Coller à la grille"
+ }
+ },
+ "workspace.header.icons" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:128" ],
+ "translations" : {
+ "en" : "Icons (Ctrl + Shift + I)",
+ "fr" : "Icônes (Ctrl + Maj + I)"
+ }
+ },
+ "workspace.header.image" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:161" ],
+ "translations" : {
+ "en" : "Image (Ctrl + I)",
+ "fr" : "Image (Ctrl + I)"
+ }
+ },
+ "workspace.header.path" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:113" ],
+ "translations" : {
+ "en" : "Path",
+ "fr" : "Chemin"
+ }
+ },
+ "workspace.header.rect" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:98" ],
+ "translations" : {
+ "en" : "Box (Ctrl + B)",
+ "fr" : "Boîte (Ctrl + B)"
+ }
+ },
+ "workspace.header.rules" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:165" ],
+ "translations" : {
+ "en" : "Rules",
+ "fr" : "Règles"
+ }
+ },
+ "workspace.header.text" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:108" ],
+ "translations" : {
+ "en" : "Text",
+ "fr" : "Texte"
+ }
+ },
+ "workspace.header.view-mode" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:186" ],
+ "translations" : {
+ "en" : "View mode (Ctrl + P)",
+ "fr" : "Mode visualisation (Ctrl + P)"
+ }
+ },
+ "workspace.options.color" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:81", "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:125", "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:47" ],
+ "translations" : {
+ "en" : "Color",
+ "fr" : "Couleur"
+ }
+ },
+ "workspace.options.font-family" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:204" ],
+ "translations" : {
+ "en" : "Font Family",
+ "fr" : "Police de caractères"
+ }
+ },
+ "workspace.options.font-options" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:202" ],
+ "translations" : {
+ "en" : "Fonts & Font Size",
+ "fr" : "TODO"
+ }
+ },
+ "workspace.options.font-weight" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:213" ],
+ "translations" : {
+ "en" : "Font Size & Weight",
+ "fr" : "Taille et graisse"
+ }
+ },
+ "workspace.options.grid-options" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:113" ],
+ "translations" : {
+ "en" : "Grid settings",
+ "fr" : "Paramètres de la grille"
+ }
+ },
+ "workspace.options.line-height-letter-spacing" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:245" ],
+ "translations" : {
+ "en" : "Line height and Letter spacing",
+ "fr" : "Hauteur de ligne et Espacement de caractères"
+ }
+ },
+ "workspace.options.measures" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:70", "src/uxbox/main/ui/workspace/sidebar/options/rect.cljs:64", "src/uxbox/main/ui/workspace/sidebar/options/circle.cljs:65", "src/uxbox/main/ui/workspace/sidebar/options/image.cljs:62", "src/uxbox/main/ui/workspace/sidebar/options/measures.cljs:115" ],
+ "translations" : {
+ "en" : "Size, position & rotation",
+ "fr" : "Taille, position et rotation"
+ }
+ },
+ "workspace.options.opacity" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:89", "src/uxbox/main/ui/workspace/sidebar/options/fill.cljs:58" ],
+ "translations" : {
+ "en" : "Opacity",
+ "fr" : "Opacité"
+ }
+ },
+ "workspace.options.position" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:99", "src/uxbox/main/ui/workspace/sidebar/options/rect.cljs:93", "src/uxbox/main/ui/workspace/sidebar/options/circle.cljs:93", "src/uxbox/main/ui/workspace/sidebar/options/image.cljs:91", "src/uxbox/main/ui/workspace/sidebar/options/measures.cljs:74" ],
+ "translations" : {
+ "en" : "Position",
+ "fr" : "Position"
+ }
+ },
+ "workspace.options.rotation-radius" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:116", "src/uxbox/main/ui/workspace/sidebar/options/rect.cljs:110", "src/uxbox/main/ui/workspace/sidebar/options/circle.cljs:108", "src/uxbox/main/ui/workspace/sidebar/options/image.cljs:108", "src/uxbox/main/ui/workspace/sidebar/options/measures.cljs:92" ],
+ "translations" : {
+ "en" : "Rotation & Radius",
+ "fr" : "TODO"
+ }
+ },
+ "workspace.options.size" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:72", "src/uxbox/main/ui/workspace/sidebar/options/rect.cljs:66", "src/uxbox/main/ui/workspace/sidebar/options/page.cljs:115", "src/uxbox/main/ui/workspace/sidebar/options/circle.cljs:69", "src/uxbox/main/ui/workspace/sidebar/options/image.cljs:64", "src/uxbox/main/ui/workspace/sidebar/options/measures.cljs:38" ],
+ "translations" : {
+ "en" : "Size",
+ "fr" : "Taille"
+ }
+ },
+ "workspace.options.stroke" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:58" ],
+ "translations" : {
+ "en" : "Stroke",
+ "fr" : null
+ }
+ },
+ "workspace.options.stroke.dashed" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:69" ],
+ "translations" : {
+ "en" : "Dashed",
+ "fr" : "Tiré"
+ }
+ },
+ "workspace.options.stroke.dotted" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:68" ],
+ "translations" : {
+ "en" : "Dotted",
+ "fr" : "Pointillé"
+ }
+ },
+ "workspace.options.stroke.mixed" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:70" ],
+ "translations" : {
+ "en" : "Mixed",
+ "fr" : "Mixte"
+ }
+ },
+ "workspace.options.stroke.none" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:66" ],
+ "translations" : {
+ "en" : "None",
+ "fr" : "Aucun"
+ }
+ },
+ "workspace.options.stroke.solid" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:67" ],
+ "translations" : {
+ "en" : "Solid",
+ "fr" : "Solide"
+ }
+ },
+ "workspace.options.stroke.style" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/stroke.cljs:62" ],
+ "translations" : {
+ "en" : "Style",
+ "fr" : "Style"
+ }
+ },
+ "workspace.options.text-align" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/options/text.cljs:264" ],
+ "translations" : {
+ "en" : "Text Alignment",
+ "fr" : "Alignement de texte"
+ }
+ },
+ "workspace.sidebar.sitemap" : {
+ "used-in" : [ "src/uxbox/main/ui/workspace/sidebar/sitemap.cljs:134" ],
+ "translations" : {
+ "en" : "Sitemap",
+ "fr" : "Plan du site"
+ }
+ }
+}
diff --git a/frontend/resources/index.mustache b/frontend/resources/templates/index.mustache
similarity index 92%
rename from frontend/resources/index.mustache
rename to frontend/resources/templates/index.mustache
index 3a83f8351..df84b69cf 100644
--- a/frontend/resources/index.mustache
+++ b/frontend/resources/templates/index.mustache
@@ -15,6 +15,6 @@
-
+