diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 1ed7a2f216a0b33512e459221b3a7dfa8c10eec1..886993664132be60edd7d739379e5f8521e2ac1a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -24,9 +24,12 @@ metabuild:
         changes:
             - "pica-dokuwiki/*"
             - "pica-etherpad/*"
+            - "pica-tellform/*"
+            - "pica-wekan/*"
         refs:
             - master
             - dev-ci
+            - tx-services-p19-test
 
 # build the container that was modified
 build:
@@ -45,9 +48,12 @@ build:
         changes:
             - "pica-dokuwiki/*"
             - "pica-etherpad/*"
+            - "pica-tellform/*"
+            - "pica-wekan/*"
         refs:
             - master
             - dev-ci
+            - tx-services-p19-test
 
 # run CoreOS' Clair and make the CI failed if a critical vulnerability isn't in the whitelist
 clair:
@@ -75,9 +81,12 @@ clair:
         changes:
             - "pica-dokuwiki/*"
             - "pica-etherpad/*"
+            - "pica-tellform/*"
+            - "pica-wekan/*"
         refs:
             - master
             - dev-ci
+            - tx-services-p19-test
 
 # run docker-bench-security and upload the results
 docker-bench-security:
@@ -110,9 +119,12 @@ docker-bench-security:
         changes:
             - "pica-dokuwiki/*"
             - "pica-etherpad/*"
+            - "pica-tellform/*"    
+            - "pica-wekan/*"
         refs:
             - master
             - dev-ci
+            - tx-services-p19-test
 
 # automatically deploy the container on pica01-test
 deployment-test:
@@ -147,9 +159,12 @@ deployment-test:
         changes:
             - "pica-dokuwiki/*"
             - "pica-etherpad/*"
+            - "pica-tellform/*"
+            - "pica-wekan/*"
         refs:
             - master
             - dev-ci
+            - tx-services-p19-test
 
 # automatically deploy the container on the production host associated with the modified image
 # this will only happen after manually triggering the deployment
@@ -189,7 +204,10 @@ deployment-prod:
         changes:
             - "pica-dokuwiki/*"
             - "pica-etherpad/*"
+            - "pica-tellform/*"
+            - "pica-wekan/*"
         refs:
             - master
             - dev-ci
+            - tx-services-p19-test
     when: manual
diff --git a/pica-tellform/Dockerfile b/pica-tellform/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..4e591a5bd15cb206bfa13089916cad3e8e672c1a
--- /dev/null
+++ b/pica-tellform/Dockerfile
@@ -0,0 +1,56 @@
+FROM node:8.12-slim as base
+LABEL maintainer="liam.dhenin@etu.utc.fr"
+ENV NODE_ENV="development"
+
+FROM base as downloader
+RUN printf "deb http://archive.debian.org/debian/ jessie main\ndeb-src http://archive.debian.org/debian/ jessie main\ndeb http://security.debian.org jessie/updates main\ndeb-src http://security.debian.org jessie/updates main" > /etc/apt/sources.list && \
+    apt-get update && \
+    apt-get install -y \
+	bzip2 \
+    	git \
+  	curl \
+	apt-utils \
+ 	build-essential \
+ 	libkrb5-dev \
+	gzip \
+	unzip && \
+    mkdir /opt/tellform && \
+    chown -R node /opt/tellform && \
+    npm install -g bower grunt-cli
+
+USER node
+WORKDIR /opt/tellform
+
+# Trouver mieux que le git clone...
+#COPY entrypoint.sh /opt/tellform/entrypoint.sh
+RUN git clone https://github.com/tellform/tellform . && git checkout stable2.1
+COPY tellform-patch.patch /opt
+RUN cd /opt; patch -p0 < tellform-patch.patch; exit 0 && \
+    npm install && \
+    bower install && \
+    grunt build
+
+FROM base
+
+COPY entrypoint.sh /opt/tellform/entrypoint.sh
+RUN chmod +x /opt/tellform/entrypoint.sh && \
+    mkdir -p /opt/tellform && \
+    chown -R node /opt/tellform && \
+    usermod -d /opt/tellform node
+
+COPY --from=downloader --chown=node /opt/tellform /opt/tellform
+
+RUN printf "deb http://archive.debian.org/debian/ jessie main\ndeb-src http://archive.debian.org/debian/ jessie main\ndeb http://security.debian.org jessie/updates main\ndeb-src http://security.debian.org jessie/updates main" > /etc/apt/sources.list && \
+    apt update && apt install -y git && \
+    apt install -y vim && \
+    npm install -g bower grunt-cli
+
+USER node
+WORKDIR /opt/tellform
+
+# RUN node ./scripts/setup.js
+ ENTRYPOINT ["./entrypoint.sh"]
+ CMD ["node","server.js"]
+# CMD exec /bin/bash -c "trap : TERM INT; sleep infinity & wait"
+
+EXPOSE 3000
diff --git a/pica-tellform/docker-compose.yml b/pica-tellform/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..896f30d332ea27e365df74d43e9f01ae01f6a243
--- /dev/null
+++ b/pica-tellform/docker-compose.yml
@@ -0,0 +1,19 @@
+version : "2.4"
+services:
+        mongo:
+                image: mongo
+                container_name: mongo
+                environment:
+                        - MONGO_INITDB_ROOT_USERNAME=root
+                        - MONGO_INITDB_ROOT_PASSWORD=example
+        tellform:
+                image: tellform
+                container_name: tellform
+                links:
+                        - mongo:mongo-db
+                env_file: ./env.secrets
+                environment:
+                        - MONGO_DB_URI=mongodb://mongo-db/tellform
+                        - MAILER_FROM=huetremy@picasoft.net
+                        - MAILER_SMTP_HOST=mail.picasoft.net
+                        - MAILER_SMTP_PORT=465
diff --git a/pica-tellform/entrypoint.sh b/pica-tellform/entrypoint.sh
new file mode 100644
index 0000000000000000000000000000000000000000..8b1ee03afdd66dbc5fde15c998101c483f91fca9
--- /dev/null
+++ b/pica-tellform/entrypoint.sh
@@ -0,0 +1,50 @@
+#!/bin/bash
+
+set -e
+
+: ${MONGODB_URI:=localhost}
+: ${BASE_URL:=tellform.test.picasoft.net}
+: ${MAILER_EMAIL_ID:=form}
+: ${MAILER_PASSWORD:=loremipsumdolorsitamet}
+: ${MAILER_FROM:=form@picasoft.net}
+: ${MAILER_SMTP_HOST:=mail.picasoft.net}
+: ${MAILER_SMTP_PORT:=587}
+: ${MAILER_SMTP_SECURE:=TRUE}
+
+#cat << EOF > /opt/tellform/.env
+#MONGODB_URI=$MONGO_DB_URI
+#BASE_URL=$BASE_URL
+#MAILER_EMAIL_ID=$MAILER_EMAIL_ID
+#MAILER_PASSWORD=$MAILER_PASSWORD
+#MAILER_FROM=$MAILER_FROM
+#MAILER_SMTP_HOST=$MAILER_SMTP_HOST
+#MAILER_SMTP_PORT=$MAILER_SMTP_PORT
+#MAILER_SMTP_SECURE=$MAILER_SMTP_SECURE
+#EOF
+
+cat << EOF > /opt/tellform/.env
+NODE_ENV=development
+CREATE_ADMIN=TRUE
+PORT=3000
+ADMIN_EMAIL=admin@admin.com
+ADMIN_USERNAME=root
+ADMIN_PASSWORD=password
+MONGODB_URI=$MONGODB_URI
+BASE_URL=$BASE_URL
+MAILER_EMAIL_ID=$MAILER_EMAIL_ID
+MAILER_PASSWORD=$MAILER_PASSWORD
+MAILER_FROM=$MAILER_FROM
+MAILER_SMTP_HOST=$MAILER_SMTP_HOST
+MAILER_SMTP_PORT=$MAILER_SMTP_PORT
+SIGNUP_DISABLED=FALSE
+SUBDOMAINS_DISABLED=TRUE
+ENABLE_CLUSTER_MODE=FALSE
+APP_NAME=pica-form
+APP_DESC=Une alternative OpenSource à TypeForm
+
+EOF
+
+
+#cat << EOF > /opt/tellform/.env                                                                                                                                          NODE_ENV=development                                                                                                                                                     CREATE_ADMIN_ACCOUNT=FALSE                                                                                                                                               PORT=3000                                                                                                                                                                ADMIN_EMAIL=admin@admin.com                                                                                                                                              ADMIN_USERNAME=root                                                                                                                                                      ADMIN_PASSWORD=password                                                                                                                                                  MONGODB_URI=$MONGODB_URI                                                                                                                                                 BASE_URL=$BASE_URL                                                                                                                                                       MAILER_EMAIL_ID=$MAILER_EMAIL_ID                                                                                                                                         MAILER_PASSWORD=$MAILER_PASSWORD                                                                                                                                         MAILER_FROM=$MAILER_FROM                                                                                                                                                 MAILER_SMTP_HOST=$MAILER_SMTP_HOST                                                                                                                                       MAILER_SMTP_PORT=$MAILER_SMTP_PORT                                                                                                                                       MAILER_SMTP_SECURE=TRUE                                                                                                                                                  SIGNUP_DISABLED=FALSE                                                                                                                                                    SUBDOMAINS_DISABLED=TRUE
+
+exec "$@"
diff --git a/pica-tellform/tellform-patch.patch b/pica-tellform/tellform-patch.patch
new file mode 100644
index 0000000000000000000000000000000000000000..8b112493044b16c715b175fbc0fb32f0c4b630fb
--- /dev/null
+++ b/pica-tellform/tellform-patch.patch
@@ -0,0 +1,1573 @@
+diff -Naur tellform/app/controllers/errors.server.controller.js tellform-patch/app/controllers/errors.server.controller.js
+--- tellform/app/controllers/errors.server.controller.js	2019-06-03 15:54:01.650435222 +0200
++++ tellform-patch/app/controllers/errors.server.controller.js	2019-06-03 17:31:23.675642088 +0200
+@@ -8,10 +8,10 @@
+ 
+ 	try {
+ 		var fieldName = err.err.substring(err.err.lastIndexOf('.$') + 2, err.err.lastIndexOf('_1'));
+-		output = fieldName.charAt(0).toUpperCase() + fieldName.slice(1) + ' already exists';
++		output = fieldName.charAt(0).toUpperCase() + fieldName.slice(1) + ' existe déjà';
+ 
+ 	} catch (ex) {
+-		output = 'Unique field already exists';
++		output = 'Un champ unique existe déjà';
+ 	}
+ 
+ 	return output;
+@@ -34,7 +34,7 @@
+ 				message = getUniqueErrorMessage(err);
+ 				break;
+ 			default:
+-				message = 'Something went wrong';
++				message = 'Quelque chose s\'est mal passé';
+ 		}
+ 	} else {
+ 		for (var errName in err.errors) {
+diff -Naur tellform/app/controllers/forms.server.controller.js tellform-patch/app/controllers/forms.server.controller.js
+--- tellform/app/controllers/forms.server.controller.js	2019-06-03 15:54:01.650435222 +0200
++++ tellform-patch/app/controllers/forms.server.controller.js	2019-06-03 17:34:29.871899768 +0200
+@@ -36,7 +36,7 @@
+ 				});
+ 				return;
+ 			}
+-			res.status(200).send('Form submissions successfully deleted');
++			res.status(200).send('La soumission des formulaires a bien été désactivé');
+ 
+ 		});
+ 	});
+@@ -69,7 +69,7 @@
+ 				message: errorHandler.getErrorMessage(err)
+ 			});
+ 		}
+-		res.status(200).send('Form submission successfully saved');
++		res.status(200).send('Votre réponse a bien été enregistré');
+ 	});
+ };
+ 
+@@ -94,7 +94,7 @@
+  * Create a new form
+  */
+ exports.create = function(req, res) {
+-	
++
+ 	if(!req.body.form){
+ 		return res.status(400).send({
+ 			message: 'Invalid Input'
+@@ -130,7 +130,7 @@
+ 					return res.json(newForm);
+ 				}
+ 				return res.status(404).send({
+-					message: 'Form Does Not Exist'
++					message: 'Le formulaire n\'existe pas'
+ 				});
+ 			}
+ 			return res.json(newForm);
+@@ -144,7 +144,7 @@
+ 	var newForm = req.form;
+ 	if (!newForm.isLive && !req.user) {
+ 		return res.status(401).send({
+-			message: 'Form is Not Public'
++			message: 'Le formulaire n\'est pas public'
+ 		});
+ 	}
+ 
+@@ -186,7 +186,7 @@
+ 	} else {
+ 
+ 	    delete updatedForm.__v;
+-	    delete updatedForm.created; 
++	    delete updatedForm.created;
+ 		//Unless we have 'admin' privileges, updating the form's admin is disabled
+ 		if(updatedForm && req.user.roles.indexOf('admin') === -1) {
+ 			delete updatedForm.admin;
+@@ -272,7 +272,7 @@
+ exports.formByID = function(req, res, next, id) {
+ 	if (!mongoose.Types.ObjectId.isValid(id)) {
+ 		return res.status(400).send({
+-			message: 'Form is invalid'
++			message: 'Le formulaire est invalide'
+ 		});
+ 	}
+ 	Form.findById(id)
+@@ -282,7 +282,7 @@
+ 			return next(err);
+ 		} else if (!form || form === null) {
+ 			res.status(404).send({
+-				message: 'Form not found'
++				message: 'Formulaire non trouvé'
+ 			});
+ 		}
+ 		else {
+@@ -304,7 +304,7 @@
+ exports.formByIDFast = function(req, res, next, id) {
+ 	if (!mongoose.Types.ObjectId.isValid(id)) {
+ 		return res.status(400).send({
+-			message: 'Form is invalid'
++			message: 'Formulaire invalide'
+ 		});
+ 	}
+ 	Form.findById(id)
+@@ -315,7 +315,7 @@
+ 			return next(err);
+ 		} else if (!form || form === null) {
+ 			res.status(404).send({
+-				message: 'Form not found'
++				message: 'Formulaire non trouvé'
+ 			});
+ 		}
+ 		else {
+@@ -339,7 +339,7 @@
+ 	var form = req.form;
+ 	if (req.form.admin.id !== req.user.id && req.user.roles.indexOf('admin') === -1) {
+ 		res.status(403).send({
+-			message: 'User '+req.user.username+' is not authorized to edit Form: '+form.title
++			message: 'Utilisateur '+req.user.username+' n\'est pas authorisé à modifier le formulaire suivant : '+form.title
+ 		});
+ 	}
+ 	return next();
+diff -Naur tellform/app/controllers/users/users.authentication.server.controller.js tellform-patch/app/controllers/users/users.authentication.server.controller.js
+--- tellform/app/controllers/users/users.authentication.server.controller.js	2019-06-03 15:54:01.650435222 +0200
++++ tellform-patch/app/controllers/users/users.authentication.server.controller.js	2019-06-03 17:22:57.150799235 +0200
+@@ -36,7 +36,7 @@
+ 
+ 	    verificationURL: config.baseUrl+'/#!/verify/${URL}',
+ 	    transportOptions: config.mailer.options,
+-	    
++
+ 	    verifySendMailCallback: function(err, info) {
+ 	      if (err) {
+ 	        throw err;
+@@ -73,12 +73,12 @@
+ 	    if(err) {
+ 			return res.status(500).send( {message: err } );
+ 	    } else if (user){
+-	        return res.status(200).send('User successfully verified');
++	        return res.status(200).send('Utilisateur vérifié');
+ 	    }
+ 	    // redirect to resend verification email
+ 	    else {
+-	    	return res.status(400).send( {message: 'Verification token is invalid or has expired'} );
+-	    } 
++	    	return res.status(400).send( {message: 'Jeton de validation expiré ou invalide'} );
++	    }
+ 	});
+ };
+ 
+@@ -98,10 +98,10 @@
+ 	    }
+ 
+ 	    if (userFound){
+-	        res.status(200).send('Verification email successfully Re-Sent');
++	        res.status(200).send('Email de vérification renvoyé !');
+ 	    }else {
+ 	        // user hasn't been found yet
+-	        res.status(400).send( {message: 'Error: User has not been registered yet'} );
++	        res.status(400).send( {message: 'Erreur : l\'utilisateur n\'a pas encore été enregistré'} );
+ 	    }
+ 	});
+ };
+@@ -149,10 +149,10 @@
+ 						message: errorHandler.getErrorMessage(err)
+ 					});
+ 				}
+-				return res.status(200).send('An email has been sent to you. Please check it to verify your account.');
++				return res.status(200).send('Un email vous a été envoyé. Consultez votre boîte mail pour vérifier votre compte.');
+ 			});
+ 		} else {
+-			return res.status(400).send({message: 'User with username/email already exists!'});
++			return res.status(400).send({message: 'Un utilisateur avec cet identifiant ou email existe déjà!'});
+ 		}
+ 	});
+ };
+@@ -161,7 +161,7 @@
+  * Signin after passport authentication
+  */
+ exports.signin = function(req, res, next) {
+-	
++
+ 	passport.authenticate('local', function(err, user, info) {
+ 		if (err || !user) {
+ 			res.status(400).send(info);
+@@ -193,14 +193,14 @@
+ 		res.clearCookie('userLang');
+ 	}
+ 	req.logout();
+-	return res.status(200).send('You have successfully logged out.');
++	return res.status(200).send('Vous êtes déconnectés.');
+ };
+ 
+ /* Generate API Key for User */
+ exports.generateAPIKey = function(req, res) {
+ 	if (!req.isAuthenticated()){
+ 		return res.status(400).send({
+-			message: 'User is not Authorized'
++			message: 'Utilisateur non autorisé'
+ 		});
+ 	}
+ 
+@@ -212,7 +212,7 @@
+ 
+ 			if (!user) {
+ 				return res.status(400).send({
+-					message: 'User does not Exist'
++					message: 'L\'utilisateur n\'existe pas'
+ 				});
+ 			}
+ 
+diff -Naur tellform/app/controllers/users/users.authorization.server.controller.js tellform-patch/app/controllers/users/users.authorization.server.controller.js
+--- tellform/app/controllers/users/users.authorization.server.controller.js	2019-06-03 15:54:01.650435222 +0200
++++ tellform-patch/app/controllers/users/users.authorization.server.controller.js	2019-06-03 17:23:48.290918414 +0200
+@@ -13,7 +13,7 @@
+ exports.userByID = function (req, res, next, id) {
+   if (!mongoose.Types.ObjectId.isValid(id)) {
+     return res.status(400).send({
+-      message: 'User is invalid'
++      message: 'Utilisateur invalide'
+     });
+   }
+ 
+@@ -24,7 +24,7 @@
+       return next(err);
+     } else if (!user) {
+ 		return res.status(404).send({
+-			message: 'User does not exist'
++			message: 'L\'utilisateur n\'existe pas'
+ 		});
+     }
+ 
+@@ -39,7 +39,7 @@
+ exports.requiresLogin = function(req, res, next) {
+ 	if (!req.isAuthenticated()) {
+ 		return res.status(401).send({
+-			message: 'User is not logged in'
++			message: 'Utilisateur non connecté'
+ 		});
+ 	} else {
+ 		return next();
+@@ -58,7 +58,7 @@
+ 				return next();
+ 			} else {
+ 				return res.status(403).send({
+-					message: 'User is not authorized'
++					message: 'Utilisateur non autorisé'
+ 				});
+ 			}
+ 		});
+diff -Naur tellform/app/controllers/users/users.password.server.controller.js tellform-patch/app/controllers/users/users.password.server.controller.js
+--- tellform/app/controllers/users/users.password.server.controller.js	2019-06-03 15:54:01.650435222 +0200
++++ tellform-patch/app/controllers/users/users.password.server.controller.js	2019-06-03 17:30:27.007574740 +0200
+@@ -57,12 +57,12 @@
+ 							}
+ 							if(!user){
+ 								return res.status(400).send({
+-									message: 'No account with that username or email has been found'
+-								});	
++									message: 'Pas d\'utilisateur n\'a été trouvé avec cet identifiant ou email'
++								});
+ 							}
+ 
+ 							return res.status(400).send({
+-								message: 'The account associated with this email has not been activated yet'
++								message: 'Le compte associé avec cet identifiant ou email n\'a pas été vérifié'
+ 							});
+ 						});
+ 					} else {
+@@ -76,14 +76,14 @@
+ 				});
+ 			} else {
+ 				return res.status(400).send({
+-					message: 'Username field must not be blank'
++					message: 'Le champ utilisateur doit être renseigné'
+ 				});
+ 			}
+ 		},
+ 		function(token, user, done) {
+ 			const fn = pug.compileFile(__dirname + "/../../views/templates/reset-password-email.server.view.pug");
+ 			res.locals['url'] = 'http://' + req.headers.host + '/auth/reset/' + token;
+-			
++
+ 			console.log(res.locals);
+ 			var renderedHtml = fn(res.locals);
+ 			done(null, renderedHtml, user);
+@@ -93,7 +93,7 @@
+ 			var mailOptions = {
+ 				to: user.email,
+ 				from: config.mailer.from,
+-				subject: 'Password Reset',
++				subject: 'Réinitialisation de mot de passe',
+ 				html: emailHTML
+ 			};
+ 
+@@ -116,11 +116,11 @@
+ 		if (err) {
+ 			console.log(err);
+ 			return res.status(400).send({
+-				message: 'Couldn\'t send reset password email due to internal server errors. Please contact support at team@tellform.com.'
++				message: 'Erreur interne lors de l\'envoi du mail de réinitialisation : pour plus d\information, contactez form@picasoft.net.'
+ 			});
+ 		} else {
+ 			return res.send({
+-				message: 'An email has been sent to ' + obfuscatedEmail + ' with further instructions.'
++				message: 'Un email a été envoyé à ' + obfuscatedEmail + ' avec la procédure à suivre.'
+ 			});
+ 		}
+ 	});
+@@ -155,13 +155,13 @@
+ exports.reset = function(req, res, next) {
+ 	if(req.body.newPassword.length < 4){
+ 		return res.status(400).send({
+-			message: 'Password must be at least 4 characters long'
++			message: 'Le mot de passe doit être supérieur à 4 caractères'
+ 		});
+ 	}
+ 
+ 	if(req.body.newPassword !== req.body.verifyPassword){
+ 		return res.status(400).send({
+-			message: 'Passwords do not match'
++			message: 'Les mots de passent ne correspondent pas'
+ 		});
+ 	}
+ 
+@@ -187,7 +187,7 @@
+ 						done(null, savedUser);
+ 					});
+ 				} else {
+-					done('Password reset token is invalid or has expired.', null);
++					done('Jeton de réinitialisation de mot de passe expiré ou invalide.', null);
+ 				}
+ 			});
+ 		},
+@@ -201,7 +201,7 @@
+ 			var mailOptions = {
+ 				to: user.email,
+ 				from: config.mailer.from,
+-				subject: 'Your password has been changed',
++				subject: 'Votre mot de passe a été changé',
+ 				html: emailHTML
+ 			};
+ 
+@@ -217,7 +217,7 @@
+ 		}
+ 
+ 		return res.json({
+-			message: 'Successfully changed your password!'
++			message: 'Le changement de votre mot de passe a été effectué!'
+ 		});
+ 	});
+ };
+@@ -248,7 +248,7 @@
+ 											res.status(400).send(err);
+ 										} else {
+ 											res.send({
+-												message: 'Password changed successfully'
++												message: 'Votre mot de passe a été changé'
+ 											});
+ 										}
+ 									});
+@@ -256,28 +256,28 @@
+ 							});
+ 						} else {
+ 							res.status(400).send({
+-								message: 'Passwords do not match'
++								message: 'Les mots de passent ne correspondent pas'
+ 							});
+ 						}
+ 					} else {
+ 						res.status(400).send({
+-							message: 'Current password is incorrect'
++							message: 'Mot de passe courant incorrect'
+ 						});
+ 					}
+ 				} else {
+ 					res.status(400).send({
+-						message: 'User is not found'
++						message: 'Utilisateur non trouvé'
+ 					});
+ 				}
+ 			});
+ 		} else {
+ 			res.status(400).send({
+-				message: 'Please provide a new password'
++				message: 'Merci de renseigner un nouveau mot de passe'
+ 			});
+ 		}
+ 	} else {
+ 		res.status(400).send({
+-			message: 'User is not signed in'
++			message: 'L\'utilisateur doit être enregistré'
+ 		});
+ 	}
+ };
+diff -Naur tellform/app/controllers/users/users.profile.server.controller.js tellform-patch/app/controllers/users/users.profile.server.controller.js
+--- tellform/app/controllers/users/users.profile.server.controller.js	2019-06-03 15:54:01.650435222 +0200
++++ tellform-patch/app/controllers/users/users.profile.server.controller.js	2019-06-03 17:30:45.591596171 +0200
+@@ -27,7 +27,7 @@
+ 				return res.status(500).send({
+ 					message: errorHandler.getErrorMessage(err)
+ 				});
+-			} 
++			}
+ 			req.login(user, function(loginErr) {
+ 				if (err) {
+ 					res.status(500).send(loginErr);
+@@ -35,11 +35,11 @@
+ 					res.json(user);
+ 				}
+ 			});
+-			
++
+ 		});
+ 	} else {
+ 		res.status(401).send({
+-			message: 'User is not signed in'
++			message: 'L\'utilisateur doit être enregistré'
+ 		});
+ 	}
+ };
+diff -Naur tellform/app/models/form_field.server.model.js tellform-patch/app/models/form_field.server.model.js
+--- tellform/app/models/form_field.server.model.js	2019-06-03 15:54:01.650435222 +0200
++++ tellform-patch/app/models/form_field.server.model.js	2019-06-03 17:37:37.616202537 +0200
+@@ -157,7 +157,7 @@
+ 	if(this.fieldType !== 'rating'){
+ 
+ 		if(this.ratingOptions && this.ratingOptions.steps && this.ratingOptions.shape){
+-			error.errors.ratingOptions = new mongoose.Error.ValidatorError({path: 'ratingOptions', message: 'ratingOptions is only allowed for type \'rating\' fields.', type: 'notvalid', value: this.ratingOptions});
++			error.errors.ratingOptions = new mongoose.Error.ValidatorError({path: 'ratingOptions', message: 'ratingOptions sont uniquement authorisés pour les types \'rating\' ', type: 'notvalid', value: this.ratingOptions});
+ 			console.error(error);
+ 			return(next(error));
+ 		}
+@@ -181,7 +181,7 @@
+ 	//If field is multiple choice check that it has field
+ 	if(this.fieldType !== 'dropdown' && this.fieldType !== 'radio' && this.fieldType !== 'checkbox'){
+ 		if(this.fieldOptions && this.fieldOptions.length > 0){
+-			error.errors.ratingOptions = new mongoose.Error.ValidatorError({path:'fieldOptions', message: 'fieldOptions are only allowed for type dropdown, checkbox or radio fields.', type: 'notvalid', value: this.ratingOptions});
++			error.errors.ratingOptions = new mongoose.Error.ValidatorError({path:'fieldOptions', message: 'fieldOptions sont uniquement authorisés pour les types menus déroualnts et cases à cocher.', type: 'notvalid', value: this.ratingOptions});
+ 			console.error(error);
+ 			return(next(error));
+ 		}
+@@ -212,4 +212,3 @@
+ var RatingOptions = mongoose.model('RatingOptions', RatingFieldSchema);
+ 
+ module.exports = FormFieldSchema;
+-
+diff -Naur tellform/app/models/form.server.model.js tellform-patch/app/models/form.server.model.js
+--- tellform/app/models/form.server.model.js	2019-06-03 15:54:01.650435222 +0200
++++ tellform-patch/app/models/form.server.model.js	2019-06-03 20:20:28.450567139 +0200
+@@ -91,8 +91,8 @@
+ 	language: {
+ 		type: String,
+ 		enum: ['en', 'fr', 'es', 'it', 'de'],
+-		default: 'en',
+-		required: 'Form must have a language'
++		default: 'fr',
++		required: 'Le formulaire doit avoir une langue'
+ 	},
+ 	analytics:{
+ 		gaCode: {
+@@ -110,7 +110,7 @@
+ 	admin: {
+ 		type: Schema.Types.ObjectId,
+ 		ref: 'User',
+-		required: 'Form must have an Admin'
++		required: 'Le formulaire doit avoir un administrateur'
+ 	},
+ 	startPage: {
+ 		showStart:{
+@@ -119,7 +119,7 @@
+ 		},
+ 		introTitle:{
+ 			type: String,
+-			default: 'Welcome to Form'
++			default: 'Bienvenue sur PicaForm'
+ 		},
+ 		introParagraph:{
+ 			type: String
+@@ -137,14 +137,14 @@
+ 		},
+ 		title:{
+ 			type: String,
+-			default: 'Thank you for filling out the form'
++			default: 'Merci d\'avoir rempli le formulaire'
+ 		},
+ 		paragraph:{
+ 			type: String
+ 		},
+ 		buttonText:{
+ 			type: String,
+-			default: 'Go back to Form'
++			default: 'Retour au formulaire'
+ 		},
+ 		buttons:[ButtonSchema]
+ 	},
+@@ -261,12 +261,12 @@
+ 			var totalViews = dropoffViews+continueViews;
+ 			var continueRate = 0;
+ 			var dropoffRate = 0;
+-			
++
+ 			if(totalViews > 0){
+ 				continueRate = (continueViews/totalViews*100).toFixed(0);
+ 				dropoffRate = (dropoffViews/totalViews*100).toFixed(0);
+ 			}
+-			
++
+ 			fieldDropoffs[i] = {
+ 				dropoffViews: dropoffViews,
+ 				responses: continueViews,
+@@ -444,4 +444,3 @@
+ FormSchema.index({created: 1});
+ 
+ mongoose.model('Form', FormSchema);
+-
+diff -Naur tellform/app/models/plugins/languagePlugin.js tellform-patch/app/models/plugins/languagePlugin.js
+--- tellform/app/models/plugins/languagePlugin.js	2019-06-03 21:41:43.768319367 +0200
++++ tellform-patch/app/models/plugins/languagePlugin.js	2019-06-03 17:35:49.144023220 +0200
+@@ -9,18 +9,18 @@
+ 			type: String,
+ 			enum: constants.languageTypes,
+ 			default: config.defaultLanguage,
+-			required: options.required || 'Must be a valid language'
++			required: options.required || 'Doit être une langue valide'
+ 		}
+   	});
+ 
+ 	schema.pre('save', function (next) {
+ 		var currWord = this.language;
+ 
+-		//English is the default backup language
+-		this.language = 'en';
++		//French is the default backup language
++		this.language = 'fr';
+ 		if(constants.wordToLangCode.has(currWord)){
+ 			this.language = constants.wordToLangCode[currWord];
+-		} 
++		}
+ 		next();
+ 	});
+-};
+\ Pas de fin de ligne à la fin du fichier
++};
+diff -Naur tellform/app/models/user.server.model.js tellform-patch/app/models/user.server.model.js
+--- tellform/app/models/user.server.model.js	2019-06-03 15:54:01.650435222 +0200
++++ tellform-patch/app/models/user.server.model.js	2019-06-03 17:41:53.060660640 +0200
+@@ -51,16 +51,16 @@
+ 		type: String,
+ 		trim: true,
+ 		lowercase: true,
+-		unique: 'Account already exists with this email',
+-		match: [/.+\@.+\..+/, 'Please fill a valid email address'],
+-		required: [true, 'Email is required']
++		unique: 'Un compte existe déjà avec cet email',
++		match: [/.+\@.+\..+/, 'Merci de renseigner une adresse mail valide'],
++		required: [true, 'Un email est requis']
+ 	},
+ 	username: {
+ 		type: String,
+ 		unique: true,
+ 		lowercase: true,
+-		match: [/^[a-zA-Z0-9\-]+$/, 'Username can only contain alphanumeric characters and \'-\''],
+-		required: [true, 'Username is required']
++		match: [/^[a-zA-Z0-9\-]+$/, 'Les noms d\'utilisateur ne peuvent contenir que des caractères alphanumeriques et \'-\''],
++		required: [true, 'Un identifiant est requis']
+ 	},
+ 	passwordHash: {
+ 		type: String,
+@@ -85,7 +85,7 @@
+ 	language: {
+ 		type: String,
+ 		enum: ['en', 'fr', 'es', 'it', 'de'],
+-		default: 'en',
++		default: 'fr',
+ 	},
+ 	lastModified: {
+ 		type: Date
+diff -Naur tellform/app/views/form.server.view.pug tellform-patch/app/views/form.server.view.pug
+--- tellform/app/views/form.server.view.pug	2019-06-03 15:54:01.650435222 +0200
++++ tellform-patch/app/views/form.server.view.pug	2019-06-04 00:09:38.082736932 +0200
+@@ -2,24 +2,24 @@
+ html(lang='en', xmlns='http://www.w3.org/1999/xhtml')
+   head
+     title=title
+-    // General META 
++    // General META
+     meta(charset='utf-8')
+     meta(http-equiv='Content-type', content='text/html;charset=UTF-8')
+     meta(http-equiv='X-UA-Compatible', content='IE=edge,chrome=1')
+     meta(name='viewport', content='width=device-width,initial-scale=1,maximum-scale=1')
+     meta(name='apple-mobile-web-app-capable', content='yes')
+     meta(name='apple-mobile-web-app-status-bar-style', content='black')
+-    // Semantic META 
++    // Semantic META
+     meta(name='keywords', content='keywords')
+     meta(name='description', content='description')
+-    // Facebook META 
++    // Facebook META
+     meta(property='og:site_name', content=title)
+     meta(property='og:title', content=title)
+     meta(property='og:description', content='description')
+     meta(property='og:url', content='url')
+     meta(property='og:image', content='/img/brand/logo.png')
+     meta(property='og:type', content='website')
+-    // Twitter META 
++    // Twitter META
+     meta(name='twitter:title', content=title)
+     meta(name='twitter:description', content='description')
+     meta(name='twitter:url', content='url')
+@@ -35,17 +35,17 @@
+         background: url('/static/dist/page-loader.gif') 50% 35% no-repeat rgb(249,249,249);
+         background-size: 50px 50px;
+       }
+-    // Fav Icon 
++    // Fav Icon
+     link(href='/static/modules/core/img/brand/favicon.ico', rel='shortcut icon', type='image/x-icon')
+ 
+   body(ng-cloak='')
+     .loader
+     section.content
+       section(ui-view='')
+-    //Embedding The User Object signupDisabled, socketPort and socketUrl Boolean 
++    //Embedding The User Object signupDisabled, socketPort and socketUrl Boolean
+     script(type='text/javascript').
+       var signupDisabled = !{signupDisabled};
+-      var socketPort = false;     
++      var socketPort = false;
+       var socketUrl = false;
+       var subdomainsDisabled = !{subdomainsDisabled};
+ 
+@@ -92,18 +92,3 @@
+     each jsFile in formJSFiles
+       script(type='text/javascript', src=jsFile)
+     // end Application Javascript dependencies
+-
+-    if process.env.NODE_ENV === 'development'
+-      //Livereload script rendered 
+-      script(async='', type='text/javascript', src='http://#{request.hostname}:35729/livereload.js')
+-
+-    script Raven.config('https://825fefd6b4ed4a4da199c1b832ca845c@sentry.tellform.com/2').install();
+-    
+-    if google_analytics_id
+-      script window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;ga('create','{{google_analytics_id}}','auto');ga('send','pageview')
+-      
+-      script(src='https://www.google-analytics.com/analytics.js', async='')
+-
+-    script(type="text/javascript").
+-      window.heap=window.heap||[],heap.load=function(e,t){window.heap.appid=e,window.heap.config=t=t||{};var r=t.forceSSL||"https:"===document.location.protocol,a=document.createElement("script");a.type="text/javascript",a.async=!0,a.src=(r?"https:":"http:")+"//cdn.heapanalytics.com/js/heap-"+e+".js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(a,n);for(var o=function(e){return function(){heap.push([e].concat(Array.prototype.slice.call(arguments,0)))}},p=["addEventProperties","addUserProperties","clearEventProperties","identify","removeEventProperty","setEventProperties","track","unsetEventProperty"],c=0;c<p.length;c++)heap[p[c]]=o(p[c])};
+-      heap.load("2213510609");
+diff -Naur tellform/app/views/index.server.view.pug tellform-patch/app/views/index.server.view.pug
+--- tellform/app/views/index.server.view.pug	2019-06-03 15:54:01.650435222 +0200
++++ tellform-patch/app/views/index.server.view.pug	2019-06-03 18:36:12.037450225 +0200
+@@ -12,7 +12,7 @@
+ 	//Embedding The signupDisabled Boolean
+ 	script(type='text/javascript').
+ 		var signupDisabled = !{signupDisabled};
+-		var socketPort = false;     
++		var socketPort = false;
+ 		var socketUrl = false;
+ 		var subdomainsDisabled = !{subdomainsDisabled};
+ 		var locale = "en";
+@@ -47,9 +47,4 @@
+ 		script(type='text/javascript', src=jsFile)
+ 	// end Application Javascript dependencies
+ 
+-	if process.env.NODE_ENV === 'development'
+-		script(type='text/javascript', src='http://#{request.hostname}:35729/livereload.js')
+-	
+ 	script(src='https://cdn.ravenjs.com/2.3.0/angular/raven.min.js')
+-	
+-	script Raven.config('https://825fefd6b4ed4a4da199c1b832ca845c@sentry.tellform.com/2').install();
+\ Pas de fin de ligne à la fin du fichier
+diff -Naur tellform/app/views/layout.server.view.pug tellform-patch/app/views/layout.server.view.pug
+--- tellform/app/views/layout.server.view.pug	2019-06-03 21:41:43.768319367 +0200
++++ tellform-patch/app/views/layout.server.view.pug	2019-06-04 00:11:34.854903019 +0200
+@@ -2,8 +2,8 @@
+ html(lang='en', xmlns='http://www.w3.org/1999/xhtml')
+   head
+     title=title
+-    
+-    // General META 
++
++    // General META
+     meta(charset='utf-8')
+     meta(http-equiv='Content-type', content='text/html;charset=UTF-8')
+     meta(http-equiv='X-UA-Compatible', content='IE=edge,chrome=1')
+@@ -11,11 +11,11 @@
+     meta(name='apple-mobile-web-app-capable', content='yes')
+     meta(name='apple-mobile-web-app-status-bar-style', content='black')
+ 
+-    // Semantic META 
++    // Semantic META
+     meta(name='keywords', content=keywords)
+     meta(name='description', content=description)
+ 
+-    // Facebook META 
++    // Facebook META
+     meta(property='og:site_name', content=title)
+     meta(property='og:title', content=title)
+     meta(property='og:description', content=description)
+@@ -23,19 +23,19 @@
+     meta(property='og:image', content='/img/brand/logo.png')
+     meta(property='og:type', content='website')
+ 
+-    // Twitter META 
++    // Twitter META
+     meta(name='twitter:title', content=title)
+     meta(name='twitter:description', content=description)
+     meta(name='twitter:url', content=url)
+     meta(name='twitter:image', content='/img/brand/logo.png')
+ 
+-    // Fav Icon 
++    // Fav Icon
+     link(href='/static/modules/core/img/brand/favicon.ico', rel='shortcut icon', type='image/x-icon')
+     link(rel='stylesheet', href='https://maxcdn.bootstrapcdn.com/font-awesome/4.6.1/css/font-awesome.min.css')
+     link(rel='stylesheet', href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css', integrity='sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u', crossorigin='anonymous')
+     link(rel='stylesheet', href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,900')
+ 
+-    //Bower CSS dependencies  
++    //Bower CSS dependencies
+     each bowerCssFile in bowerCssFiles
+       link(rel='stylesheet', href=bowerCssFile)
+     link(rel='stylesheet', href='/static/lib/angular-input-stars/angular-input-stars.css')
+@@ -51,11 +51,3 @@
+   body
+ 
+     block content
+-
+-    script window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;ga('create','#{google_analytics_id}','auto');ga('send','pageview')
+-    
+-    script(src='https://www.google-analytics.com/analytics.js', async='', defer='')
+-
+-    script(type="text/javascript").
+-      window.heap=window.heap||[],heap.load=function(e,t){window.heap.appid=e,window.heap.config=t=t||{};var r=t.forceSSL||"https:"===document.location.protocol,a=document.createElement("script");a.type="text/javascript",a.async=!0,a.src=(r?"https:":"http:")+"//cdn.heapanalytics.com/js/heap-"+e+".js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(a,n);for(var o=function(e){return function(){heap.push([e].concat(Array.prototype.slice.call(arguments,0)))}},p=["addEventProperties","addUserProperties","clearEventProperties","identify","removeEventProperty","setEventProperties","track","unsetEventProperty"],c=0;c<p.length;c++)heap[p[c]]=o(p[c])};
+-      heap.load("2213510609");
+diff -Naur tellform/app/views/redoc.server.view.pug tellform-patch/app/views/redoc.server.view.pug
+--- tellform/app/views/redoc.server.view.pug	2019-06-03 15:54:01.650435222 +0200
++++ tellform-patch/app/views/redoc.server.view.pug	2019-06-04 00:11:42.486913943 +0200
+@@ -3,7 +3,7 @@
+   head
+     title #{title}
+ 
+-    // General META 
++    // General META
+     meta(charset='utf-8')
+     meta(http-equiv='Content-type', content='text/html;charset=UTF-8')
+     meta(http-equiv='X-UA-Compatible', content='IE=edge,chrome=1')
+@@ -11,11 +11,11 @@
+     meta(name='apple-mobile-web-app-capable', content='yes')
+     meta(name='apple-mobile-web-app-status-bar-style', content='black')
+ 
+-    // Semantic META 
++    // Semantic META
+     meta(name='keywords', content='#{keywords}')
+     meta(name='description', content='#{description}')
+ 
+-    // Facebook META 
++    // Facebook META
+     meta(property='og:site_name', content='#{title}')
+     meta(property='og:title', content='#{title}')
+     meta(property='og:description', content='#{description}')
+@@ -23,13 +23,13 @@
+     meta(property='og:image', content='/img/brand/logo.png')
+     meta(property='og:type', content='website')
+ 
+-    // Twitter META 
++    // Twitter META
+     meta(name='twitter:title', content='#{title}')
+     meta(name='twitter:description', content='#{description}')
+     meta(name='twitter:url', content='{{url}}')
+     meta(name='twitter:image', content='/img/brand/logo.png')
+ 
+-    // Fav Icon 
++    // Fav Icon
+     link(href='/static/modules/core/img/brand/favicon.ico', rel='shortcut icon', type='image/x-icon')
+     link(rel='stylesheet', href='https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,600,700,900')
+ 
+@@ -40,23 +40,10 @@
+   body
+     redoc(spec-url='/static/swagger.json')
+     script(src='https://rebilly.github.io/ReDoc/releases/latest/redoc.min.js')
+-    
++
+     //Bower JS dependencies
+     each bowerJSFile in bowerJSFiles
+       script(type='text/javascript', src='#{bowerJSFile}')
+     // end Bower JS dependencies
+-    
++
+     script(type='text/javascript', src='https://cdnjs.cloudflare.com/ajax/libs/angular-strap/2.3.8/angular-strap.min.js')
+-    
+-    if process.env.NODE_ENV === 'development'
+-      script(src='https://cdn.ravenjs.com/2.3.0/angular/raven.min.js')
+-    
+-    script Raven.config('https://825fefd6b4ed4a4da199c1b832ca845c@sentry.tellform.com/2').install();
+-   
+-    script window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;ga('create','{{google_analytics_id}}','auto');ga('send','pageview')
+-    
+-    script(src='https://www.google-analytics.com/analytics.js', async='', defer='')
+-
+-    script(type="text/javascript").
+-      window.heap=window.heap||[],heap.load=function(e,t){window.heap.appid=e,window.heap.config=t=t||{};var r=t.forceSSL||"https:"===document.location.protocol,a=document.createElement("script");a.type="text/javascript",a.async=!0,a.src=(r?"https:":"http:")+"//cdn.heapanalytics.com/js/heap-"+e+".js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(a,n);for(var o=function(e){return function(){heap.push([e].concat(Array.prototype.slice.call(arguments,0)))}},p=["addEventProperties","addUserProperties","clearEventProperties","identify","removeEventProperty","setEventProperties","track","unsetEventProperty"],c=0;c<p.length;c++)heap[p[c]]=o(p[c])};
+-      heap.load("2213510609");
+diff -Naur tellform/app/views/templates/reset-password-confirm-email.server.view.html tellform-patch/app/views/templates/reset-password-confirm-email.server.view.html
+--- tellform/app/views/templates/reset-password-confirm-email.server.view.html	2019-06-03 15:54:01.650435222 +0200
++++ tellform-patch/app/views/templates/reset-password-confirm-email.server.view.html	2019-06-03 18:36:07.453459845 +0200
+@@ -27,10 +27,10 @@
+                     <tr>
+                       <td width="36"></td>
+                       <td width="454" align="left" style="color: #444444; border-collapse: collapse; font-size: 11pt; font-family: 'Open Sans', 'Lucida Grande', 'Segoe UI', Arial, Verdana, 'Lucida Sans Unicode', Tahoma, 'Sans Serif'; max-width: 454px;" valign="top">
+-                        <p>Hello there!</p>
+-                        <p>This is a courtesy message to confirm that your password was just changed.</p>
+-                        <p>Thanks so much for using our services! If you have any questions, or suggestions, please feel free to email us here at&nbsp;<a href="mailto:team@tellform.com">team@tellform.com</a>.</p>
+-                        <p>  - The #{appName} team</p>
++                        <p>Bonjour!</p>
++                        <p>Votre mot de passe a bien été changé !</p>
++                        <p>Merci d'utiliser nos services ! Pour toute question ou recommandation, contactez&nbsp;<a href="mailto:form@picasoft.net">form@picasoft.net</a>.</p>
++                        <p>  - L'équipe #{appName}</p>
+                       </td>
+                       <td width="36"></td>
+                     </tr>
+@@ -61,4 +61,4 @@
+       </table>
+     </center>
+   </body>
+-</html>
+\ Pas de fin de ligne à la fin du fichier
++</html>
+diff -Naur tellform/app/views/templates/reset-password-confirm-email.server.view.pug tellform-patch/app/views/templates/reset-password-confirm-email.server.view.pug
+--- tellform/app/views/templates/reset-password-confirm-email.server.view.pug	2019-06-03 15:54:01.650435222 +0200
++++ tellform-patch/app/views/templates/reset-password-confirm-email.server.view.pug	2019-06-03 18:36:08.981456619 +0200
+@@ -23,7 +23,7 @@
+                               p=__('EMAIL_GREETING')
+                               p=__('RESET_PASSWORD_CONFIRMATION_EMAIL_BODY_1')
+                               p=__("VERIFICATION_EMAIL_PARAGRAPH_2")
+-                                a(href='mailto:team@tellform.com') team@tellform.com
++                                a(href='mailto:form@picasoft.net') form@picasoft.net
+                               p=__('EMAIL_SIGNATURE')
+                             td(width='36')
+                           tr
+diff -Naur tellform/app/views/templates/reset-password-email.server.view.html tellform-patch/app/views/templates/reset-password-email.server.view.html
+--- tellform/app/views/templates/reset-password-email.server.view.html	2019-06-03 15:54:01.650435222 +0200
++++ tellform-patch/app/views/templates/reset-password-email.server.view.html	2019-06-03 17:48:53.025481048 +0200
+@@ -27,12 +27,12 @@
+                     <tr>
+                       <td width="36"></td>
+                       <td width="454" align="left" style="color: #444444; border-collapse: collapse; font-size: 11pt; font-family: 'Open Sans', 'Lucida Grande', 'Segoe UI', Arial, Verdana, 'Lucida Sans Unicode', Tahoma, 'Sans Serif'; max-width: 454px;" valign="top">
+-                        <p>Hello there!</p>
+-                        <p>Here is a special link that will allow you to reset your password.  Please note it will expire in one hour for your protection:</p>
+-                        <p><a href="{{url}}">Reset Your Password</a></p>
+-                        <p>If you did not request this, please ignore this email and your password will remain unchanged.</p>
+-                        <p>Thanks so much for using our services! If you have any questions, or suggestions, please feel free to email us here at&nbsp;<a href="mailto:team@tellform.com">team@tellform.com</a>.</p>
+-                        <p>  - The {{appName}} team</p>
++                        <p>Bonjour!</p>
++                        <p>Voilà un lien pour réinitialiser votre mot de passe. Il expirera dans une heure :</p>
++                        <p><a href="{{url}}">Réinitialiser le mot de passe</a></p>
++                        <p>Si vous n'êtes pas à l'origine de cette requête, ignorez ce message, votre mot de passe restera inchangé.</p>
++                        <p>Merci d'utiliser nos services ! Pour toute question ou recommandation, contactez&nbsp;<a href="mailto:form@picasoft.net">form@picasoft.net</a>.</p>
++                        <p>  - L'équipe {{appName}}</p>
+                       </td>
+                       <td width="36"></td>
+                     </tr>
+@@ -63,4 +63,4 @@
+       </table>
+     </center>
+   </body>
+-</html>
+\ Pas de fin de ligne à la fin du fichier
++</html>
+diff -Naur tellform/app/views/templates/reset-password-email.server.view.pug tellform-patch/app/views/templates/reset-password-email.server.view.pug
+--- tellform/app/views/templates/reset-password-email.server.view.pug	2019-06-03 15:54:01.650435222 +0200
++++ tellform-patch/app/views/templates/reset-password-email.server.view.pug	2019-06-03 18:36:09.937454612 +0200
+@@ -26,7 +26,7 @@
+                                 a(href=url)=__('RESET_PASSWORD_REQUEST_EMAIL_LINK_TEXT')
+                               p=__('RESET_PASSWORD_REQUEST_EMAIL_PARAGRAPH_2')
+                               p=__('VERIFICATION_EMAIL_PARAGRAPH_2')
+-                                a(href='mailto:team@tellform.com') team@tellform.com
++                                a(href='mailto:form@picasoft.net') form@picasoft.net
+                               p=__('EMAIL_SIGNATURE')
+                             td(width='36')
+                           tr
+diff -Naur tellform/config/env/all.js tellform-patch/config/env/all.js
+--- tellform/config/env/all.js	2019-06-03 15:54:01.650435222 +0200
++++ tellform-patch/config/env/all.js	2019-06-03 18:37:49.117283065 +0200
+@@ -14,14 +14,14 @@
+ 			pass: ''
+ 		}
+ 	},
+-	
+-	
++
++
+ 	admin:{
+ 		email: process.env.ADMIN_EMAIL || 'admin@admin.com',
+ 		username: process.env.ADMIN_USERNAME || 'root',
+ 		password: process.env.ADMIN_PASSWORD || 'root',
+ 	},
+-	
++
+ 	redisUrl: process.env.REDIS_URL || 'redis://127.0.0.1:6379',
+ 
+ 	port: process.env.PORT || 3000,
+@@ -36,7 +36,7 @@
+ 	tempUserCollection: 'temporary_users',
+ 
+ 	mailer: {
+-		from: process.env.MAILER_FROM || 'testing@'+process.env.SPARKPOST_SANDBOX_DOMAIN || 'no-reply@tellform.com',
++		from: process.env.MAILER_FROM || 'testing@'+process.env.SPARKPOST_SANDBOX_DOMAIN || 'form@picasoft.net',
+ 		options: process.env.MAILER_SMTP_HOST ? { //Uses custom SMTP if MAILER_SMTP_HOST is set
+ 			host: process.env.MAILER_SMTP_HOST || '',
+ 			port: process.env.MAILER_SMTP_PORT || 465,
+diff -Naur tellform/config/env/development.js tellform-patch/config/env/development.js
+--- tellform/config/env/development.js	2019-06-03 15:54:01.650435222 +0200
++++ tellform-patch/config/env/development.js	2019-06-03 18:37:50.065281754 +0200
+@@ -17,7 +17,7 @@
+         // Uncomment to enable logging to a log on the file system
+     },
+ 	mailer: {
+-		from: process.env.MAILER_FROM || 'no-reply@tellform.com',
++		from: process.env.MAILER_FROM || 'form@picasoft.net',
+ 		options: process.env.MAILER_SMTP_HOST ? { //Uses custom SMTP if MAILER_SMTP_HOST is set
+ 			host: process.env.MAILER_SMTP_HOST || '',
+ 			port: process.env.MAILER_SMTP_PORT || 465,
+diff -Naur tellform/config/express.js tellform-patch/config/express.js
+--- tellform/config/express.js	2019-06-03 15:54:01.650435222 +0200
++++ tellform-patch/config/express.js	2019-06-03 20:56:17.832233360 +0200
+@@ -75,7 +75,7 @@
+ 
+ 	if(config.socketUrl){
+ 		app.locals.socketUrl = config.socketUrl;
+-	} 
++	}
+ 
+ 	app.locals.bowerJSFiles = config.getBowerJSAssets();
+ 	app.locals.bowerCssFiles = config.getBowerCSSAssets();
+@@ -91,7 +91,7 @@
+ 			var User = mongoose.model('User');
+ 			var subdomainPath = '/subdomain/';
+ 			var subdomains = req.subdomains;
+-			
++
+ 			if (subdomains.slice(0, 4).join('.') + '' === '1.0.0.127') {
+ 				subdomains = subdomains.slice(4);
+ 			}
+@@ -100,7 +100,7 @@
+ 			if (!subdomains.length) {
+ 				return next();
+ 			}
+-			
++
+ 			urlPath = url.parse(req.url).path.split('/');
+ 			if (urlPath.indexOf('static') > -1) {
+ 				urlPath.splice(1, 1);
+@@ -131,13 +131,13 @@
+ 					req.subdomains = null;
+ 					// Error page
+ 					return res.status(404).render('404', {
+-						error: 'Page Does Not Exist'
++						error: 'La page n\'existe pas'
+ 					});
+ 				}
+ 				if (user === null) {
+ 					// Error page
+ 					return res.status(404).render('404', {
+-						error: 'Page Does Not Exist'
++						error: 'La page n\'existe pas'
+ 					});
+ 				}
+ 
+@@ -190,7 +190,7 @@
+     i18n.configure({
+         locales: supportedLanguages,
+         directory: __dirname + '/locales',
+-        defaultLocale: 'en',
++        defaultLocale: 'fr',
+         cookie: 'userLang'
+     });
+ 
+@@ -340,10 +340,10 @@
+ 
+ 	// Assume 404 since no middleware responded
+ 	app.use(function(req, res) {
+-		client.captureError(new Error('Page Not Found'));
++		client.captureError(new Error('Pas non trouvée'));
+ 		res.status(404).render('404', {
+ 			url: req.originalUrl,
+-			error: 'Not Found',
++			error: 'Non trouvée',
+             __: i18n.__
+ 		});
+ 	});
+diff -Naur tellform/config/init.js tellform-patch/config/init.js
+--- tellform/config/init.js	2019-06-03 15:54:01.650435222 +0200
++++ tellform-patch/config/init.js	2019-06-03 19:33:23.324180800 +0200
+@@ -18,9 +18,9 @@
+ 
+ 	if (!environmentFiles.length) {
+ 		if (process.env.NODE_ENV) {
+-			console.error(chalk.red('No configuration file found for "' + process.env.NODE_ENV + '" environment using development instead'));
++			console.error(chalk.red('Pas de fichier de configuration trouvé pour l\'environnement "' + process.env.NODE_ENV + '"'));
+ 		} else {
+-			console.error(chalk.red('NODE_ENV is not defined! Using default development environment'));
++			console.error(chalk.red('NODE_ENV n\'est pas défini!'));
+ 		}
+ 
+ 		process.env.NODE_ENV = 'development';
+diff -Naur tellform/config/locales/fr.json tellform-patch/config/locales/fr.json
+--- tellform/config/locales/fr.json	2019-06-03 21:41:43.768319367 +0200
++++ tellform-patch/config/locales/fr.json	2019-06-03 16:08:40.807954389 +0200
+@@ -4,14 +4,14 @@
+ 	"404_BODY": "%s n'est pas un chemin valide.",
+ 	"500_BODY": "Une erreur inattendue semble s'être produite, pourquoi ne pas essayer d'actualiser votre page ? Ou vous pouvez nous contacter si le problème persiste.",
+ 	"EMAIL_GREETING": "Bonjour !",
+-	"VERIFICATION_EMAIL_PARAGRAPH_1": "Bienvenue sur TellForm ! Voici un lien spécial pour activer votre nouveau compte : ",
++	"VERIFICATION_EMAIL_PARAGRAPH_1": "Bienvenue sur PicaForm ! Voici un lien spécial pour activer votre nouveau compte : ",
+ 	"VERIFICATION_EMAIL_LINK_TEXT": "Activer mon compte",
+ 	"VERIFICATION_EMAIL_PARAGRAPH_2": "Merci infiniment d'utiliser nos services ! Si vous avez des questions ou des suggestions, n'hésitez pas à nous envoyer un courriel ici",
+-	"VERIFICATION_EMAIL_SUBJECT": "Activer votre nouveau compte TellForm !",
++	"VERIFICATION_EMAIL_SUBJECT": "Activer votre nouveau compte PicaForm !",
+ 	"VERIFICATION_EMAIL_TEXT": "Merci de vérifier votre compte en cliquant sur le lien suivant, ou en le copiant dans votre navigateur web : ${URL}",
+-	"EMAIL_SIGNATURE": "- L'équipe TellForm",
++	"EMAIL_SIGNATURE": "- L'équipe PicaForm",
+ 	"WELCOME_EMAIL_PARAGRAPH_1": "Nous aimerions vous accueillir en tant que nouveau membre !",
+-	"WELCOME_EMAIL_PARAGRAPH_2": "Nous espérons que vous apprécierez l'utilisation de TellForm ! Si vous avez des problèmes, n'hésitez pas à nous envoyer un e-mail ici",
++	"WELCOME_EMAIL_PARAGRAPH_2": "Nous espérons que vous apprécierez l'utilisation de PicaForm ! Si vous avez des problèmes, n'hésitez pas à nous envoyer un e-mail ici",
+ 	"WELCOME_EMAIL_SUBJECT": "Bienvenue dans %s!",
+ 	"WELCOME_EMAIL_TEXT": "Votre compte a été vérifié avec succès.",
+ 	"RESET_PASSWORD_CONFIRMATION_EMAIL_PARAGRAPH_1": "Ceci est un message de courtoisie pour confirmer que votre mot de passe a été modifié.",
+diff -Naur tellform/config/logger.js tellform-patch/config/logger.js
+--- tellform/config/logger.js	2019-06-03 15:54:01.650435222 +0200
++++ tellform-patch/config/logger.js	2019-06-03 20:19:41.678306270 +0200
+@@ -56,7 +56,7 @@
+   } catch (err) {
+     if (process.env.NODE_ENV !== 'test') {
+       console.log();
+-      console.log(chalk.red('An error has occured during the creation of the File transport logger.'));
++      console.log(chalk.red('Une erreur s\'est produite pendant la création du fichier d\'inscription.'));
+       console.log(chalk.red(err));
+       console.log();
+     }
+@@ -75,9 +75,9 @@
+ 
+   var _config = _.clone(config, true);
+   var configFileLogger = _config.log.fileLogger;
+-  
++
+   if (!_.has(_config, 'log.fileLogger.directoryPath') || !_.has(_config, 'log.fileLogger.fileName')) {
+-    console.log('unable to find logging file configuration');
++    console.log('Impossible de trouver le fichier de configuration de connexion');
+     return false;
+   }
+ 
+@@ -122,13 +122,13 @@
+ logger.getLogFormat = function getLogFormat() {
+   var format = config.log && config.log.format ? config.log.format.toString() : 'combined';
+ 
+-   if (!_.includes(validFormats, format)) { 
++   if (!_.includes(validFormats, format)) {
+     if (process.env.NODE_ENV !== 'test') {
+       console.log();
+-      console.log(chalk.yellow('Warning: An invalid format was provided. The logger will use the default format of "' + format + '"'));
++      console.log(chalk.yellow('Attetion : un format invalide a été fourni Le format par défaut sera : "' + format + '"'));
+       console.log();
+     }
+-  }    
++  }
+   return format;
+ };
+ 
+diff -Naur tellform/config/passport_helpers.js tellform-patch/config/passport_helpers.js
+--- tellform/config/passport_helpers.js	2019-06-03 15:54:01.650435222 +0200
++++ tellform-patch/config/passport_helpers.js	2019-06-03 19:35:59.088482320 +0200
+@@ -31,7 +31,7 @@
+ 
+ module.exports.hasRole = function hasRole(roleRequired) {
+ 	if (!roleRequired) {
+-		throw new Error('Required role needs to be set');
++		throw new Error('Des rôles doivent être définis');
+ 	}
+ 
+ 	return function(req, res, next) {
+@@ -47,4 +47,3 @@
+ module.exports.hasAdminRole = function hasAdminRole() {
+ 	return module.exports.hasRole('admin');
+ };
+-
+diff -Naur tellform/.git/index tellform-patch/.git/index
+--- tellform/.git/index	2019-06-03 21:41:43.772319383 +0200
++++ tellform-patch/.git/index	2019-06-03 15:58:01.042801090 +0200
+@@ -5,14 +5,14 @@
+ ����=+�h"٫
��m���.slugignore�������\�&y&�ѐ\�&y&�ѐ���}&���������������a:N�R�Ps}�������.travis.yml�������\�&y&�ږ\�&y&�ږ���}'�������������l��#�v1!��:��+��]d`��CODE_OF_CONDUCT.md��������\�'i��\�'i�����}"������������$k_�k��1��=��a
�
+ Dockerfile��������\�&y&�ږ\�&y&�ږ���})����������������W*3t���U�g��
+ �INSTALLATION_INSTRUCTIONS.md������\�&y&�ږ\�&y&�ږ���}*��������������kSp�ݴ�ü/���-���4�ISSUE_TEMPLATE.md�\�&y&�ږ\�&y&�ږ���},�������������f��x;7���|�a�`�����
+-LICENSE.md��������\�&y&�ږ\�&y&�ږ���}5������������=*N�M��ʚP�����ۨ��PULL_REQUEST_TEMPLATE.md��\�&y&�ږ\�&y&�ږ���}X�������������03`	zM�ٯ��Kp}�J��Procfile��\�'i��\�'i�����}(������������MI��5��o�@��8����$4�	README.md�\�&y&�ږ\�&y&�ږ���}Z������������+�H��s�q���_C�k�^��Vagrantfile�������\�&y&�ږ\�&y&�ږ���}[�������������6�����2Gk{3���y��app.json��\�&y&�ږ\�&y&�ږ���}\������������ԑNe.��ш��%:x���4�)app/controllers/core.server.controller.js�\�&y&�ږ\�&y&�ږ���}]�������������x܇q��u`�Z��iC�[�+app/controllers/errors.server.controller.js�������\�&y&�ږ\�&y&�ږ���}^������������/���"]��!���_I8�	�{�*app/controllers/forms.server.controller.js��������\�&y&�ږ\�&y&�ږ���}`������������n���1�x-!b��o^|��E��*app/controllers/users.server.controller.js��������\�&y&�ږ\�&y&�ږ���}a�������������[�lC*�?L��>���v ��+�?app/controllers/users/users.authentication.server.controller.js���\�&y&�ږ\�&y&�ږ���}b��������������%ϡ����v���_|sG�>app/controllers/users/users.authorization.server.controller.js����\�&y&�ږ\�&y&�ږ���}c���������������U��Ϊf-�_� `���9app/controllers/users/users.password.server.controller.js�\�&y&�ږ\�&y&�ږ���}e������������+q����ؕx�V��̗�i��8app/controllers/users/users.profile.server.controller.js��\�&y&�ږ\�&y&�ږ���}f�������������gjGz�\`�|ݞ1��܃B���app/libs/constants.js�����\�&y&�ږ\�&y&�ږ���}g�������������N,
��bwM%��S�Gl�'��#app/libs/timestamp.server.plugin.js�������\�&y&�ږ\�&y&�ږ���}h��������������+�C��y��'��+��app/libs/tokenGenerator.js��������\�&y&�ږ\�&y&�ږ���}i������������&#��&�X���l�<�{c�=�app/models/form.server.model.js���\�&y&�ږ\�&y&�ږ���}j������������1�nq5�bV�N�AF�&A�%app/models/form_field.server.model.js�����\�&y&�ږ\�&y&�ږ���}k������������	�P_:C�_T[t�X��/ܗ	�*app/models/form_submission.server.model.js��������\�&y&�ږ\�&y&�ږ���}l�������������&��s���E��#���B��%app/models/logic_jump.server.model.js�����\�w�-˟�\�w�-˟����=�����������������@H_��{�3�D��f�$app/models/plugins/languagePlugin.js������\�&y&�ږ\�&y&�ږ���}n������������9�(J�T�ǫ{�� O��]�l�app/models/user.server.model.js���\�&y&�ږ\�&y&�ږ���}o������������D�T�y�Cu�`F�U�_"+��X� app/routes/core.server.routes.js��\�&y&�ږ\�&y&�ږ���}p������������g��%x�,�*J!$?P4��!app/routes/forms.server.routes.js�\�&y&�ږ\�&y&�ږ���}q������������9�qvΐ�'p(�Q��ʙBU\��!app/routes/users.server.routes.js�\�&y&�ږ\�&y&�ږ���}r�������������:h`N<�x�'�p����_i� app/sockets/analytics_service.js��\�&y&�ږ\�&y&�ږ���}s�������������W>c��`OZw��m�#l����#app/tests/form.server.model.test.js�������\�&y&�ږ\�&y&�ږ���}t������������'N����ޓԑ�_n�SY)O��$app/tests/form.server.routes.test.js������\�&y&�ږ\�&y&�ږ���}v������������F	D,�Q��a#b�Z#�P,ZC�'app/tests/form_submission.model.test.js���\�&y&�ږ\�&y&�ږ���}w���������������@o2�)}Q� ��Y�(app/tests/form_submission.routes.test.js��\�&y&�ږ\�&y&�ږ���}x�������������)�r�V�$m������W��.app/tests/libs/timestamp.server.plugin.test.js����\�&y&�ږ\�&y&�ږ���}y������������Z|���$|I���	�d��
�D��#app/tests/user.server.model.test.js�������\�&y&�ږ\�&y&�ږ���}z������������
�����浇y�2
++LICENSE.md��������\�&y&�ږ\�&y&�ږ���}5������������=*N�M��ʚP�����ۨ��PULL_REQUEST_TEMPLATE.md��\�&y&�ږ\�&y&�ږ���}X�������������03`	zM�ٯ��Kp}�J��Procfile��\�'i��\�'i�����}(������������MI��5��o�@��8����$4�	README.md�\�&y&�ږ\�&y&�ږ���}Z������������+�H��s�q���_C�k�^��Vagrantfile�������\�&y&�ږ\�&y&�ږ���}[�������������6�����2Gk{3���y��app.json��\�&y&�ږ\�&y&�ږ���}\������������ԑNe.��ш��%:x���4�)app/controllers/core.server.controller.js�\�&y&�ږ\�&y&�ږ���}]�������������x܇q��u`�Z��iC�[�+app/controllers/errors.server.controller.js�������\�&y&�ږ\�&y&�ږ���}^������������/���"]��!���_I8�	�{�*app/controllers/forms.server.controller.js��������\�&y&�ږ\�&y&�ږ���}`������������n���1�x-!b��o^|��E��*app/controllers/users.server.controller.js��������\�&y&�ږ\�&y&�ږ���}a�������������[�lC*�?L��>���v ��+�?app/controllers/users/users.authentication.server.controller.js���\�&y&�ږ\�&y&�ږ���}b��������������%ϡ����v���_|sG�>app/controllers/users/users.authorization.server.controller.js����\�&y&�ږ\�&y&�ږ���}c���������������U��Ϊf-�_� `���9app/controllers/users/users.password.server.controller.js�\�&y&�ږ\�&y&�ږ���}e������������+q����ؕx�V��̗�i��8app/controllers/users/users.profile.server.controller.js��\�&y&�ږ\�&y&�ږ���}f�������������gjGz�\`�|ݞ1��܃B���app/libs/constants.js�����\�&y&�ږ\�&y&�ږ���}g�������������N,
��bwM%��S�Gl�'��#app/libs/timestamp.server.plugin.js�������\�&y&�ږ\�&y&�ږ���}h��������������+�C��y��'��+��app/libs/tokenGenerator.js��������\�&y&�ږ\�&y&�ږ���}i������������&#��&�X���l�<�{c�=�app/models/form.server.model.js���\�&y&�ږ\�&y&�ږ���}j������������1�nq5�bV�N�AF�&A�%app/models/form_field.server.model.js�����\�&y&�ږ\�&y&�ږ���}k������������	�P_:C�_T[t�X��/ܗ	�*app/models/form_submission.server.model.js��������\�&y&�ږ\�&y&�ږ���}l�������������&��s���E��#���B��%app/models/logic_jump.server.model.js�����\�&y&�ږ\�&y&�ږ���}m����������������@H_��{�3�D��f�$app/models/plugins/languagePlugin.js������\�&y&�ږ\�&y&�ږ���}n������������9�(J�T�ǫ{�� O��]�l�app/models/user.server.model.js���\�&y&�ږ\�&y&�ږ���}o������������D�T�y�Cu�`F�U�_"+��X� app/routes/core.server.routes.js��\�&y&�ږ\�&y&�ږ���}p������������g��%x�,�*J!$?P4��!app/routes/forms.server.routes.js�\�&y&�ږ\�&y&�ږ���}q������������9�qvΐ�'p(�Q��ʙBU\��!app/routes/users.server.routes.js�\�&y&�ږ\�&y&�ږ���}r�������������:h`N<�x�'�p����_i� app/sockets/analytics_service.js��\�&y&�ږ\�&y&�ږ���}s�������������W>c��`OZw��m�#l����#app/tests/form.server.model.test.js�������\�&y&�ږ\�&y&�ږ���}t������������'N����ޓԑ�_n�SY)O��$app/tests/form.server.routes.test.js������\�&y&�ږ\�&y&�ږ���}v������������F	D,�Q��a#b�Z#�P,ZC�'app/tests/form_submission.model.test.js���\�&y&�ږ\�&y&�ږ���}w���������������@o2�)}Q� ��Y�(app/tests/form_submission.routes.test.js��\�&y&�ږ\�&y&�ږ���}x�������������)�r�V�$m������W��.app/tests/libs/timestamp.server.plugin.test.js����\�&y&�ږ\�&y&�ږ���}y������������Z|���$|I���	�d��
�D��#app/tests/user.server.model.test.js�������\�&y&�ږ\�&y&�ږ���}z������������
�����浇y�2
+ �񛩁0�g�$app/tests/user.server.routes.test.js������\�&y&�ږ\�&y&�ږ���}{������������7�7	Hk|?�W�7�e*�Ц�
+-�app/views/404.server.view.pug�����\�&y&�ږ\�&y&�ږ���}|������������w9����:�b�'�o=/6�app/views/500.server.view.pug�����\�&y&�ږ\�&y&�ږ���}~������������a���/!�s7x��t����F���app/views/form.server.view.pug����\�&y&�ږ\�&y&�ږ���}������������-™5Ű��!��sa�4Ak�!��app/views/index.server.view.pug���\�w�-˟�\�w�-˟����=��������������D��-���Z�r٥�T��w� app/views/layout.server.view.pug��\�&y&�ږ\�&y&�ږ���}���������������Pܖ�BS2���ఀ	�Ne�app/views/redoc.server.view.pug���\�&y&�ږ\�&y&�ږ���}�������������<]��?o}UC�4H9��Y9c�Aapp/views/templates/reset-password-confirm-email.server.view.html�\�&y&�ږ\�&y&�ږ���}�������������	ڕ�\�s3(\u	�v��4���@app/views/templates/reset-password-confirm-email.server.view.pug��\�&y&�ږ\�&y&�ږ���}�������������
9�辰������vS�r���V�9app/views/templates/reset-password-email.server.view.html�\�&y&�ږ\�&y&�ږ���}�������������
++�app/views/404.server.view.pug�����\�&y&�ږ\�&y&�ږ���}|������������w9����:�b�'�o=/6�app/views/500.server.view.pug�����\�&y&�ږ\�&y&�ږ���}~������������a���/!�s7x��t����F���app/views/form.server.view.pug����\�&y&�ږ\�&y&�ږ���}������������-™5Ű��!��sa�4Ak�!��app/views/index.server.view.pug���\�&y&�ږ\�&y&�ږ���}��������������D��-���Z�r٥�T��w� app/views/layout.server.view.pug��\�&y&�ږ\�&y&�ږ���}���������������Pܖ�BS2���ఀ	�Ne�app/views/redoc.server.view.pug���\�&y&�ږ\�&y&�ږ���}�������������<]��?o}UC�4H9��Y9c�Aapp/views/templates/reset-password-confirm-email.server.view.html�\�&y&�ږ\�&y&�ږ���}�������������	ڕ�\�s3(\u	�v��4���@app/views/templates/reset-password-confirm-email.server.view.pug��\�&y&�ږ\�&y&�ږ���}�������������
9�辰������vS�r���V�9app/views/templates/reset-password-email.server.view.html�\�&y&�ږ\�&y&�ږ���}�������������
+ ��/2������DK@g�96��8app/views/templates/reset-password-email.server.view.pug��\�&y&�ږ\�&y&�ږ���}�������������
+ ��"U�,�D�V��sap���
+ �%app/views/verification.email.view.pug�����\�&y&�ږ\�&y&�ږ���}�������������
+ {�V,�Fbܻ|�}FT'�'!D� app/views/welcome.email.view.pug��\�&y&�ږ\�&y&�ږ���}�������������h���q�-L�,|� ���
+-bower.json��������\�&y&�ږ\�&y&�ږ���}�������������I8�Q� �]	Z�����h��͟�	conf.json�\�&y&�ږ\�&y&�ږ���}�������������O��)�%�#P@:��r�h]�d��config/config.js��\�&y&�ږ\�&y&�ږ���}��������������5������bS?�d,"��config/env/all.js�\�&y&�ږ\�&y&�ږ���}�������������T�&s���+T�z?60�#�config/env/development.js�\�&y&�ږ\�&y&�ږ���}���������������r�O��Q�/+��f5��f��config/env/production.js��\�&y&�ږ\�&y&�ږ���}�������������ڼ�������dO��ew�config/env/secure.js������\�&y&�ږ\�&y&�ږ���}�������������DӠ/$��0?��h��zP�v�config/env/test.js��������\�&y&�ږ\�&y&�ږ���}�������������'��Dy�y�ζ�S1���o�!��config/express.js�\�&y&�ږ\�&y&�ږ���}��������������j�S7�\ϱ�C��Z����config/init.js����\�&y&�ږ\�&y&�ږ���}�������������{�	V��a�D݈s!�p~t�config/locales/de.json����\�&y&�ږ\�&y&�ږ���}�������������f�"�[G��j���z`/��config/locales/en.json����\�&y&�ږ\�&y&�ږ���}�������������!Jn����GW�$��P�\�config/locales/es.json����\�w�-˟�\�w�-˟����=�������������{�Þ�n���i�s����U��config/locales/fr.json����\�&y&�ږ\�&y&�ږ���}���������������@���x�\�Ž�6L�config/locales/it.json����\�&y&�ږ\�&y&�ږ���}��������������c�}�7T��"�o	/���*�config/locales/sv.json����\�&y&�ږ\�&y&�ږ���}�������������
�3�/A���+��٬-�ԫ���config/logger.js��\�&y&�ږ\�&y&�ږ���}��������������Z��vn�5�ML_e(�����config/passport.js��������\�&y&�ږ\�&y&�ږ���}��������������ˆ���J^fL�ܬXQU�2~�config/passport_helpers.js��������\�&y&�ږ\�&y&�ږ���}�������������ɕ��8w0^�?��}hI�A�config/socket.io.js�������\�&y&�ږ\�&y&�ږ���}���������������r���L�/��o�cQ%��&�config/strategies/anonymous.js����\�&y&�ږ\�&y&�ږ���}����������������	�+n�Օ�"�&5�config/strategies/apikey.js�������\�&y&�ږ\�&y&�ږ���}�������������PJ��sqj�\�Us�&��9d�config/strategies/local.js��������\�&y'�\�&y'����}������������n_n���u(��
xȵ*�<�� design/screenshots/analytics.png��\�&y'�\�&y'����}������������r��ҏ�r`�j5
�����f@�?� design/screenshots/collapsed.png��\�&y'�\�&y'����}��������������$x��Λ۝Kv�+��<���&design/screenshots/tellform_rating.png����\�&y'�\�&y'����}��������������Ʒ^l��ƫ1�;�R�+design/screenshots/tellform_screenshot1.png�������\�&y'�\�&y'����}�������������j=�W����+�V�[oYԭ�design/tellform_mascot.png��������\�&y'�\�&y'����}����������������4����Oz��
��*�@a�dev_entrypoint.sh�\�&y'�\�&y'����}�������������� ��koV�'���b�g��D��dns_masq_setup_osx.md�����\�&y'�\�&y'����}�������������
�}�+
�
++bower.json��������\�&y&�ږ\�&y&�ږ���}�������������I8�Q� �]	Z�����h��͟�	conf.json�\�&y&�ږ\�&y&�ږ���}�������������O��)�%�#P@:��r�h]�d��config/config.js��\�&y&�ږ\�&y&�ږ���}��������������5������bS?�d,"��config/env/all.js�\�&y&�ږ\�&y&�ږ���}�������������T�&s���+T�z?60�#�config/env/development.js�\�&y&�ږ\�&y&�ږ���}���������������r�O��Q�/+��f5��f��config/env/production.js��\�&y&�ږ\�&y&�ږ���}�������������ڼ�������dO��ew�config/env/secure.js������\�&y&�ږ\�&y&�ږ���}�������������DӠ/$��0?��h��zP�v�config/env/test.js��������\�&y&�ږ\�&y&�ږ���}�������������'��Dy�y�ζ�S1���o�!��config/express.js�\�&y&�ږ\�&y&�ږ���}��������������j�S7�\ϱ�C��Z����config/init.js����\�&y&�ږ\�&y&�ږ���}�������������{�	V��a�D݈s!�p~t�config/locales/de.json����\�&y&�ږ\�&y&�ږ���}�������������f�"�[G��j���z`/��config/locales/en.json����\�&y&�ږ\�&y&�ږ���}�������������!Jn����GW�$��P�\�config/locales/es.json����\�&y&�ږ\�&y&�ږ���}�������������{�Þ�n���i�s����U��config/locales/fr.json����\�&y&�ږ\�&y&�ږ���}���������������@���x�\�Ž�6L�config/locales/it.json����\�&y&�ږ\�&y&�ږ���}��������������c�}�7T��"�o	/���*�config/locales/sv.json����\�&y&�ږ\�&y&�ږ���}�������������
�3�/A���+��٬-�ԫ���config/logger.js��\�&y&�ږ\�&y&�ږ���}��������������Z��vn�5�ML_e(�����config/passport.js��������\�&y&�ږ\�&y&�ږ���}��������������ˆ���J^fL�ܬXQU�2~�config/passport_helpers.js��������\�&y&�ږ\�&y&�ږ���}�������������ɕ��8w0^�?��}hI�A�config/socket.io.js�������\�&y&�ږ\�&y&�ږ���}���������������r���L�/��o�cQ%��&�config/strategies/anonymous.js����\�&y&�ږ\�&y&�ږ���}����������������	�+n�Օ�"�&5�config/strategies/apikey.js�������\�&y&�ږ\�&y&�ږ���}�������������PJ��sqj�\�Us�&��9d�config/strategies/local.js��������\�&y'�\�&y'����}������������n_n���u(��
xȵ*�<�� design/screenshots/analytics.png��\�&y'�\�&y'����}������������r��ҏ�r`�j5
�����f@�?� design/screenshots/collapsed.png��\�&y'�\�&y'����}��������������$x��Λ۝Kv�+��<���&design/screenshots/tellform_rating.png����\�&y'�\�&y'����}��������������Ʒ^l��ƫ1�;�R�+design/screenshots/tellform_screenshot1.png�������\�&y'�\�&y'����}�������������j=�W����+�V�[oYԭ�design/tellform_mascot.png��������\�&y'�\�&y'����}����������������4����Oz��
��*�@a�dev_entrypoint.sh�\�&y'�\�&y'����}�������������� ��koV�'���b�g��D��dns_masq_setup_osx.md�����\�&y'�\�&y'����}�������������
�}�+
�
+ ��M%(�K��"docs/readme_logos/digitalOcean.png��������\�&y'�\�&y'����}�������������
+ xIǼWb�l0���
O鑿ͻe�docs/readme_logos/sentryIO.png����\�&y'�\�&y'����}���������������((P-�uf�1Pz8���Hإ�docs/readme_logos/sparkPost.png���\�&y'�\�&y'����}��������������;�lL
�9$c�H@�uh�"docs/readme_logos/statusPageIO.png��������\�&y'�\�&y'����}�������������c�5N6��$I�5$f�W
+ ��/�!docs/readme_logos/stickerMule.png�\�&y'�\�&y'����}��������������n���4�L3��_�����n/�#docs/readme_logos/theRoostStand.png�������\�&y'�\�&y'����}�������������oo�/�
+@@ -135,4 +135,4 @@
+ (c�����:5���/
�q�edirectives�3 0
+ ilnr�!�O�I�f�g�1scripts�5 1
+ �B6ŷ�֬(h����g�#��build�1 0
+-He�5���C�]<������/�$����u?*��E��z0���
+\ Pas de fin de ligne à la fin du fichier
++He�5���C�]<������ͩ�����R>��kv����
+\ Pas de fin de ligne à la fin du fichier
+diff -Naur tellform/public/form_modules/forms/base/config/i18n/english.js tellform-patch/public/form_modules/forms/base/config/i18n/english.js
+--- tellform/public/form_modules/forms/base/config/i18n/english.js	2019-06-03 15:54:01.662435238 +0200
++++ tellform-patch/public/form_modules/forms/base/config/i18n/english.js	2019-06-04 09:32:16.433539612 +0200
+@@ -42,8 +42,4 @@
+   	FORM_UNAUTHORIZED_BODY2: 'If you are the owner of the form, you can set it to "Public" in the "Configuration" panel in the form admin.',
+   });
+ 
+-  $translateProvider.preferredLanguage('en')
+-  	.fallbackLanguage('en')
+-	.useSanitizeValueStrategy('escape');
+-
+ }]);
+diff -Naur tellform/public/form_modules/forms/base/config/i18n/french.js tellform-patch/public/form_modules/forms/base/config/i18n/french.js
+--- tellform/public/form_modules/forms/base/config/i18n/french.js	2019-06-03 15:54:01.662435238 +0200
++++ tellform-patch/public/form_modules/forms/base/config/i18n/french.js	2019-06-04 09:33:50.377608073 +0200
+@@ -42,4 +42,8 @@
+    FORM_UNAUTHORIZED_BODY2: 'Si vous êtes le propriétaire du formulaire, vous pouvez le définir en "Public" dans le panneau "Configuration" du formulaire admin.',
+   });
+ 
++  $translateProvider.preferredLanguage('fr')
++    .fallbackLanguage('fr')
++  .useSanitizeValueStrategy('escape');
++
+ }]);
+diff -Naur tellform/public/form_modules/forms/base/directives/on-finish-render.client.directive.js tellform-patch/public/form_modules/forms/base/directives/on-finish-render.client.directive.js
+--- tellform/public/form_modules/forms/base/directives/on-finish-render.client.directive.js	2019-06-03 15:54:01.662435238 +0200
++++ tellform-patch/public/form_modules/forms/base/directives/on-finish-render.client.directive.js	2019-06-03 19:38:25.347772458 +0200
+@@ -4,7 +4,7 @@
+     return {
+         restrict: 'A',
+         link: function (scope, element, attrs) {
+-			
++
+             //Don't do anything if we don't have a ng-repeat on the current element
+             if(!element.attr('ng-repeat') && !element.attr('data-ng-repeat')){
+                 return;
+@@ -14,11 +14,11 @@
+ 
+             if(scope.$first && !scope.$last) {
+                 scope.$evalAsync(function () {
+-                    $rootScope.$broadcast(broadcastMessage+' Started');
++                    $rootScope.$broadcast(broadcastMessage+' commencé');
+                 });
+             }else if(scope.$last) {
+             	scope.$evalAsync(function () {
+-            	    $rootScope.$broadcast(broadcastMessage+' Finished');
++            	    $rootScope.$broadcast(broadcastMessage+' terminé');
+                 });
+             }
+         }
+diff -Naur tellform/public/form_modules/forms/base/directives/submit-form.client.directive.js tellform-patch/public/form_modules/forms/base/directives/submit-form.client.directive.js
+--- tellform/public/form_modules/forms/base/directives/submit-form.client.directive.js	2019-06-03 15:54:01.662435238 +0200
++++ tellform-patch/public/form_modules/forms/base/directives/submit-form.client.directive.js	2019-06-04 00:12:41.142998121 +0200
+@@ -1,13 +1,5 @@
+ 'use strict';
+ 
+-//FIXME: Should find an appropriate place for this
+-//Setting up jsep
+-jsep.addBinaryOp('contains', 10);
+-jsep.addBinaryOp('!contains', 10);
+-jsep.addBinaryOp('begins', 10);
+-jsep.addBinaryOp('!begins', 10);
+-jsep.addBinaryOp('ends', 10);
+-jsep.addBinaryOp('!ends', 10);
+ 
+ angular.module('view-form').directive('submitFormDirective', ['$http', 'TimeCounter', '$filter', '$rootScope', 'SendVisitorData', '$translate', '$timeout',
+     function ($http, TimeCounter, $filter, $rootScope, SendVisitorData, $translate, $timeout) {
+@@ -22,7 +14,7 @@
+ 		        var NOSCROLL = false;
+ 		        var FORM_ACTION_ID = 'submit_field';
+                 $scope.forms = {};
+-                
++
+ 				//Don't start timer if we are looking at a design preview
+                 if($scope.ispreview){
+                     TimeCounter.restartClock();
+@@ -125,8 +117,8 @@
+ 
+ 				var getActiveField = function(){
+ 					if($scope.selected === null){
+-						console.error('current active field is null');
+-						throw new Error('current active field is null');
++						console.error('Le champ courant est null');
++						throw new Error('Le champ courant est null');
+ 					}
+ 
+ 					if($scope.selected._id === FORM_ACTION_ID) {
+@@ -146,7 +138,7 @@
+                     if($scope.selected === null || (!field_id && field_index === null) )  {
+                     	return;
+                     }
+-	    			
++
+ 	    			if(!field_id){
+ 	    				field_id = $scope.myform.visible_form_fields[field_index]._id;
+ 					} else if(field_index === null){
+@@ -243,12 +235,12 @@
+                             field_index = $scope.selected.index+1;
+                             $scope.setActiveField(FORM_ACTION_ID, field_index, false);
+                         }
+-                        
++
+                         //If we scrolled bellow the current field, move to next field
+                         else if(fieldBottom < elemHeight * fractionToJump && $scope.selected.index < $scope.myform.visible_form_fields.length-1 ){
+                             field_index = $scope.selected.index+1;
+                             $scope.setActiveField(null, field_index, false);
+-                        } 
++                        }
+                         //If we scrolled above the current field, move to prev field
+                         else if ( $scope.selected.index !== 0 && fieldTop > elemHeight * fractionToJump) {
+                             field_index = $scope.selected.index-1;
+@@ -264,7 +256,7 @@
+ 
+ 						if($scope.selected._id !== FORM_ACTION_ID){
+ 							var currField = $scope.myform.visible_form_fields[$scope.selected.index];
+-						
++
+ 							//Jump to logicJump's destination if it is true
+ 							if(currField.logicJump && currField.logicJump.jumpTo && evaluateLogicJump(currField)){
+ 								$scope.setActiveField(currField.logicJump.jumpTo, null, true);
+@@ -281,7 +273,7 @@
+ 						//If selected is not defined go to the first field
+ 						$rootScope.setActiveField(null, 0, true);
+ 					}
+-	
++
+                 };
+ 
+                 $rootScope.prevField = $scope.prevField = function(){
+@@ -380,7 +372,7 @@
+ 						if($scope.myform.form_fields[i].fieldType === 'dropdown' && !$scope.myform.form_fields[i].deletePreserved){
+ 							$scope.myform.form_fields[i].fieldValue = $scope.myform.form_fields[i].fieldValue.option_value;
+ 						}
+-						
++
+ 						//Get rid of unnessecary attributes for each form field
+ 						delete form.form_fields[i].submissionId;
+                         			delete form.form_fields[i].disabled;
+@@ -389,8 +381,8 @@
+                         			delete form.form_fields[i].logicJump;
+                         			delete form.form_fields[i].description;
+                         			delete form.form_fields[i].validFieldTypes;
+-                        			delete form.form_fields[i].fieldType;	
+-					 
++                        			delete form.form_fields[i].fieldType;
++
+ 					}
+ 
+ 					setTimeout(function () {
+diff -Naur tellform/public/form_modules/forms/base/services/time-counter.client.service.js tellform-patch/public/form_modules/forms/base/services/time-counter.client.service.js
+--- tellform/public/form_modules/forms/base/services/time-counter.client.service.js	2019-06-03 15:54:01.662435238 +0200
++++ tellform-patch/public/form_modules/forms/base/services/time-counter.client.service.js	2019-06-03 19:39:52.009289726 +0200
+@@ -25,7 +25,7 @@
+ 
+ 				return this.timeSpent;
+ 			}
+-			return new Error('Clock has not been started');
++			return new Error('L\'horloge n\'as pas démarrée');
+ 		};
+ 
+ 		this.clockStarted = function(){
+diff -Naur tellform/public/form_modules/forms/base/views/submit-form.client.view.html tellform-patch/public/form_modules/forms/base/views/submit-form.client.view.html
+--- tellform/public/form_modules/forms/base/views/submit-form.client.view.html	2019-06-03 15:54:01.662435238 +0200
++++ tellform-patch/public/form_modules/forms/base/views/submit-form.client.view.html	2019-06-03 20:19:26.070189906 +0200
+@@ -1,12 +1,3 @@
+ <section class="public-form">
+ 	<submit-form-directive myform="myform"></submit-form-directive>
+ </section>
+-
+-<!-- User's Google Analytics -->
+-<script ng-if="myform.analytics.gaCode">
+-	window.ga=function(){ga.q.push(arguments)};ga.q=[];ga.l=+new Date;
+-	ga('create', '{{myform.analytics.gaCode}}', 'auto'); ga('send', 'pageview');
+-</script>
+-<script ng-if="myform.analytics.gaCode" src="https://www.google-analytics.com/analytics.js" async defer></script>
+-
+-<!-- End Google Analytics -->
+diff -Naur tellform/public/modules/core/config/i18n/english.js tellform-patch/public/modules/core/config/i18n/english.js
+--- tellform/public/modules/core/config/i18n/english.js	2019-06-03 15:54:01.662435238 +0200
++++ tellform-patch/public/modules/core/config/i18n/english.js	2019-06-04 09:33:06.745577915 +0200
+@@ -13,8 +13,4 @@
+ 		TOGGLE_NAVIGATION: 'Toggle navigation'
+ 	});
+ 
+-	$translateProvider.preferredLanguage('en')
+-		.fallbackLanguage('en')
+-		.useSanitizeValueStrategy('escape');
+-
+ }]);
+diff -Naur tellform/public/modules/core/config/i18n/french.js tellform-patch/public/modules/core/config/i18n/french.js
+--- tellform/public/modules/core/config/i18n/french.js	2019-06-03 15:54:01.662435238 +0200
++++ tellform-patch/public/modules/core/config/i18n/french.js	2019-06-04 09:33:02.525574857 +0200
+@@ -12,4 +12,8 @@
+ 		CHANGE_PASSWORD: 'Changer mon mot de passe',
+ 		TOGGLE_NAVIGATION: 'Basculer la navigation',
+ 	});
++
++	$translateProvider.preferredLanguage('fr')
++		.fallbackLanguage('fr')
++		.useSanitizeValueStrategy('escape');
+ }]);
+diff -Naur tellform/public/modules/core/controllers/header.client.controller.js tellform-patch/public/modules/core/controllers/header.client.controller.js
+--- tellform/public/modules/core/controllers/header.client.controller.js	2019-06-03 15:54:01.662435238 +0200
++++ tellform-patch/public/modules/core/controllers/header.client.controller.js	2019-06-03 19:42:37.122929848 +0200
+@@ -31,7 +31,7 @@
+ 				$state.reload();
+ 			},
+ 			function(reason) {
+-			  	console.error('Logout Failed: ' + reason);
++			  	console.error('Deconnexion échouée : ' + reason);
+ 			});
+ 	    };
+ 
+diff -Naur tellform/public/modules/core/services/menus.client.service.js tellform-patch/public/modules/core/services/menus.client.service.js
+--- tellform/public/modules/core/services/menus.client.service.js	2019-06-03 15:54:01.662435238 +0200
++++ tellform-patch/public/modules/core/services/menus.client.service.js	2019-06-03 19:43:15.450441553 +0200
+@@ -15,7 +15,7 @@
+ 			if (user) {
+ 				if (~this.roles.indexOf('*')) {
+ 					return true;
+-				} 
++				}
+ 				for (var userRoleIndex in user.roles) {
+ 					for (var roleIndex in this.roles) {
+ 						if (this.roles[roleIndex] === user.roles[userRoleIndex]) {
+@@ -25,7 +25,7 @@
+ 				}
+ 				return false;
+ 
+-			} 
++			}
+ 			return this.isPublic;
+ 		};
+ 
+@@ -35,10 +35,10 @@
+ 				if (this.menus[menuId]) {
+ 					return true;
+ 				} else {
+-					throw new Error('Menu does not exists');
++					throw new Error('Menu n\'existe pas ');
+ 				}
+ 			} else {
+-				throw new Error('MenuId was not provided');
++				throw new Error('MenuId n\'est pas fourni');
+ 			}
+ 		};
+ 
+diff -Naur tellform/public/modules/forms/admin/controllers/admin-form.client.controller.js tellform-patch/public/modules/forms/admin/controllers/admin-form.client.controller.js
+--- tellform/public/modules/forms/admin/controllers/admin-form.client.controller.js	2019-06-03 15:54:01.666435244 +0200
++++ tellform-patch/public/modules/forms/admin/controllers/admin-form.client.controller.js	2019-06-03 19:44:25.647310706 +0200
+@@ -102,7 +102,7 @@
+                 $scope.deleteModal.close();
+ 
+                 var form_id = $scope.myform._id;
+-                if(!form_id) throw new Error('Error - removeCurrentForm(): $scope.myform._id does not exist');
++                if(!form_id) throw new Error('Erreur - removeCurrentForm(): $scope.myform._id n\'existe pas');
+ 
+                 $http.delete('/forms/'+form_id)
+                     .then(function(response){
+@@ -214,4 +214,4 @@
+ 
+ 
+     }
+-]);
+\ Pas de fin de ligne à la fin du fichier
++]);
+diff -Naur tellform/public/modules/forms/admin/controllers/list-forms.client.controller.js tellform-patch/public/modules/forms/admin/controllers/list-forms.client.controller.js
+--- tellform/public/modules/forms/admin/controllers/list-forms.client.controller.js	2019-06-03 15:54:01.666435244 +0200
++++ tellform-patch/public/modules/forms/admin/controllers/list-forms.client.controller.js	2019-06-03 19:44:51.522571004 +0200
+@@ -105,7 +105,7 @@
+ 
+         $scope.removeForm = function(form_index) {
+             if(form_index >= $scope.myforms.length || form_index < 0){
+-                throw new Error('Error: form_index in removeForm() must be between 0 and '+$scope.myforms.length-1);
++                throw new Error('Erreur: form_index dans removeForm() doit être entre 0 et '+$scope.myforms.length-1);
+             }
+ 
+             $http.delete('/forms/'+$scope.myforms[form_index]._id)
+diff -Naur tellform/public/modules/users/config/i18n/english.js tellform-patch/public/modules/users/config/i18n/english.js
+--- tellform/public/modules/users/config/i18n/english.js	2019-06-03 15:54:01.666435244 +0200
++++ tellform-patch/public/modules/users/config/i18n/english.js	2019-06-03 21:51:06.101488598 +0200
+@@ -68,8 +68,4 @@
+ 		ERROR: 'Error'
+ 	});
+ 
+-	$translateProvider.preferredLanguage('en')
+-		.fallbackLanguage('en')
+-		.useSanitizeValueStrategy('escape');
+-
+ }]);
+diff -Naur tellform/public/modules/users/config/i18n/french.js tellform-patch/public/modules/users/config/i18n/french.js
+--- tellform/public/modules/users/config/i18n/french.js	2019-06-03 15:54:01.666435244 +0200
++++ tellform-patch/public/modules/users/config/i18n/french.js	2019-06-03 21:47:10.149216152 +0200
+@@ -49,4 +49,8 @@
+ 		ERROR: 'Erreur'
+ 	});
+ 
++	$translateProvider.preferredLanguage('fr')
++		.fallbackLanguage('fr')
++		.useSanitizeValueStrategy('escape');
++
+ }]);
+diff -Naur tellform/public/modules/users/controllers/authentication.client.controller.js tellform-patch/public/modules/users/controllers/authentication.client.controller.js
+--- tellform/public/modules/users/controllers/authentication.client.controller.js	2019-06-03 15:54:01.666435244 +0200
++++ tellform-patch/public/modules/users/controllers/authentication.client.controller.js	2019-06-03 19:47:40.038970866 +0200
+@@ -2,7 +2,7 @@
+ 
+ angular.module('users').controller('AuthenticationController', ['$scope', '$location', '$state', '$rootScope', 'User', 'Auth', '$translate', '$window',
+ 	function($scope, $location, $state, $rootScope, User, Auth, $translate, $window) {
+-		
++
+ 		$scope = $rootScope;
+ 		$scope.credentials = {};
+ 		$scope.error = '';
+@@ -36,7 +36,7 @@
+ 
+ 	    $scope.signup = function() {
+ 	    	if($scope.credentials === 'admin'){
+-	    		$scope.error = 'Username cannot be \'admin\'. Please pick another username.';
++	    		$scope.error = 'L\'identifiant ne peut être \'admin\'. Merci d\'en choisir un autre.';
+ 	    		return;
+ 	    	}
+ 
+@@ -51,7 +51,7 @@
+ 							$scope.error = error;
+ 							console.error(error);
+ 						} else {
+-							console.error('No response received');
++							console.error('Aucune réponse reçue');
+ 						}
+ 			        }
+ 			    );
+diff -Naur tellform/public/modules/users/services/authorizer.client.service.js tellform-patch/public/modules/users/services/authorizer.client.service.js
+--- tellform/public/modules/users/services/authorizer.client.service.js	2019-06-03 15:54:01.666435244 +0200
++++ tellform-patch/public/modules/users/services/authorizer.client.service.js	2019-06-03 19:48:12.756023362 +0200
+@@ -11,7 +11,7 @@
+         for (i = 0, len = permissions.length; i < len; i++) {
+           permission = permissions[i];
+           if (APP_PERMISSIONS[permission] === null) {
+-            throw 'Bad permission value';
++            throw 'Mauvaise valeur de permission';
+           }
+           if (user && user.roles) {
+             switch (permission) {
+@@ -31,4 +31,4 @@
+       }
+     };
+   };
+-});
+\ Pas de fin de ligne à la fin du fichier
++});
+diff -Naur tellform/public/modules/users/services/user.client.service.js tellform-patch/public/modules/users/services/user.client.service.js
+--- tellform/public/modules/users/services/user.client.service.js	2019-06-03 15:54:01.666435244 +0200
++++ tellform-patch/public/modules/users/services/user.client.service.js	2019-06-03 19:48:44.180484997 +0200
+@@ -12,7 +12,7 @@
+     		    deferred.resolve(response);
+     		  })
+     		  .error(function() {
+-    		    deferred.reject('User\'s session has expired');
++    		    deferred.reject('La session utilisateur a expirée');
+     		  });
+ 
+         return deferred.promise;
+@@ -69,7 +69,7 @@
+         //DAVID: TODO: The valid length of a token should somehow be linked to server config values
+         //DAVID: TODO: SEMI-URGENT: Should we even be doing this?
+         var validTokenRe = /^([A-Za-z0-9]{48})$/g;
+-        if( !validTokenRe.test(token) ) throw new Error('Error token: '+token+' is not a valid verification token');
++        if( !validTokenRe.test(token) ) throw new Error('Erreur: '+token+' est un jeton invalide');
+ 
+         var deferred = $q.defer();
+         $http.get('/auth/verify/'+token).then(function(response) {
+diff -Naur tellform/scripts/create_admin.js tellform-patch/scripts/create_admin.js
+--- tellform/scripts/create_admin.js	2019-06-03 15:54:01.702435295 +0200
++++ tellform-patch/scripts/create_admin.js	2019-06-03 19:51:04.054570055 +0200
+@@ -6,7 +6,7 @@
+ 
+ 	var User = mongoose.model('User');
+ 	var email = 'admin@admin.com' || config.admin.email;
+-	
++
+ 	var newUser = new User({
+ 		firstName: 'Admin',
+ 		lastName: 'Account',
+@@ -27,12 +27,12 @@
+ 				if (userErr) {
+ 					return cb(userErr);
+ 				}
+-				console.log(chalk.green('Successfully created Admin Account'));
++				console.log(chalk.green('Compte administrateur créé'));
+ 
+ 				cb();
+ 			});
+ 		} else {
+-			cb('User already exists!');
++			cb('L\'utilisateur existe déjà!');
+ 		}
+ 	});
+ }
+diff -Naur tellform/scripts/git-remove-history.sh tellform-patch/scripts/git-remove-history.sh
+--- tellform/scripts/git-remove-history.sh	2019-06-03 15:54:01.702435295 +0200
++++ tellform-patch/scripts/git-remove-history.sh	2019-06-03 19:51:35.017628137 +0200
+@@ -1,24 +1,24 @@
+ #!/bin/bash
+ set -o errexit
+- 
++
+ # Author: David Underhill
+-# Script to permanently delete files/folders from your git repository.  To use 
++# Script to permanently delete files/folders from your git repository.  To use
+ # it, cd to your repository's root and then run the script with a list of paths
+ # you want to delete, e.g., git-delete-history path1 path2
+- 
++
+ if [ $# -eq 0 ]; then
+     exit 0
+ fi
+- 
++
+ # make sure we're at the root of git repo
+ if [ ! -d .git ]; then
+-    echo "Error: must run this script from the root of a git repository"
++    echo "Erreur: l\éxécution doit se faire depuis la racine du dossier git"
+     exit 1
+ fi
+- 
++
+ # remove all paths passed as arguments from the history of the repo
+ files=$@
+ git filter-branch --index-filter "git rm -rf --cached --ignore-unmatch $files" HEAD
+- 
++
+ # remove the temporary history git-filter-branch otherwise leaves behind for a long time
+ rm -rf .git/refs/original/ && git reflog expire --all &&  git gc --aggressive --prune
+diff -Naur tellform/scripts/setup.js tellform-patch/scripts/setup.js
+--- tellform/scripts/setup.js	2019-06-03 15:54:01.702435295 +0200
++++ tellform-patch/scripts/setup.js	2019-06-03 19:52:24.523909961 +0200
+@@ -15,12 +15,12 @@
+ // Bootstrap db connection
+ var db = mongoose.connect(config.db.uri, config.db.options, function(err) {
+ 	if (err) {
+-		console.error(chalk.red('Could not connect to MongoDB!'));
++		console.error(chalk.red('Impossible de se connecter à MongoDB!'));
+ 		console.log(chalk.red(err));
+ 	}
+ });
+ mongoose.connection.on('error', function(err) {
+-	console.error(chalk.red('MongoDB connection error: ' + err));
++	console.error(chalk.red('Erreur de connexion MongoDB : ' + err));
+ 	process.exit(-1);
+ });
+ 
diff --git a/pica-wekan-scripts/Dockerfile b/pica-wekan-scripts/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..9101d6adfd1e24e6e8fc69ff6ab2fc367b4edf99
--- /dev/null
+++ b/pica-wekan-scripts/Dockerfile
@@ -0,0 +1,13 @@
+from alpine
+
+ENV DRYRUN=1 \
+    url="https://wekan.test.picasoft.net" \
+    CRON_TIME="0 0 1 * *"
+
+COPY *.sh ./
+
+RUN apk add --no-cache --update curl jq
+
+ENTRYPOINT /bin/sh ./run.sh
+
+
diff --git a/pica-wekan-scripts/README.md b/pica-wekan-scripts/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..73d3a16294691bef2548932282ee209cc1cbe45b
--- /dev/null
+++ b/pica-wekan-scripts/README.md
@@ -0,0 +1,43 @@
+# Localement : script de suppression des boards Wekan trop anciens
+## Introduction
+
+Ce README est obsolète mais peut-être testé en local, en dehors du serveur de picasoft, à condition de connaître les identifiants du compte Wekan dédié.
+
+## Avant le lancement
+Le paquet jq permet de parser et manipuler du JSON en ligne de commande. Il est nécessaire pour filtrer les informations reçu de l'API.
+
+```bash
+sudo apt install jq
+```
+
+Le Wekan doit contenir un compte dédié pour ce script permettant d'accéder à l'API. Ce compte doit disposer des droits administrateurs du Wekan. Les identifiants doivent être présents dans un fichier séparer du script `policy.sh`.
+
+```bash
+touch ids.sh
+```
+
+## Contenu de `ids.sh`
+2 variables sont nécessaires : username et password du compte dédié.
+```bash
+#!/bin/sh
+
+export username="username"
+export password="password"
+```
+
+## Choix de la deadline et de l'URL de l'API
+Les boards n'ayant pas été modifiés depuis un certain temps sont définitivement supprimés. Cette durée est la somme de trois variables : `boardExpirationDurationYears`, `boardExpirationDurationMonths` et `boardExpirationDurationDays`. L'URL de l'application est également nécessaire.
+ Ces informations sont à modifier directement dans les premières lignes du script `policy.sh`.
+
+```bash
+boardExpirationDurationYears=0 # années
+boardExpirationDurationMonths=12 # mois
+boardExpirationDurationDays=0 # jours
+url=https://wekan.test.picasoft.net
+```
+
+
+## Lancement du script
+```bash
+./policy.sh
+```
diff --git a/pica-wekan-scripts/docker-compose.yml b/pica-wekan-scripts/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..1af1c3070f38624719edd72e2926ae4afd50b858
--- /dev/null
+++ b/pica-wekan-scripts/docker-compose.yml
@@ -0,0 +1,8 @@
+version: '3'
+
+services:
+  wekan-cleaner:
+    image: registry.picasoft.net/pica-wekan-cleaner
+    environment:
+       - DRYRUN=1
+    container_name: wekan_clean 
diff --git a/pica-wekan-scripts/ids_example.sh b/pica-wekan-scripts/ids_example.sh
new file mode 100644
index 0000000000000000000000000000000000000000..5fa2ccab1b3f8fe04ea8eef98014313881bff1dc
--- /dev/null
+++ b/pica-wekan-scripts/ids_example.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+username="username"
+password="password"
diff --git a/pica-wekan-scripts/policy.sh b/pica-wekan-scripts/policy.sh
new file mode 100755
index 0000000000000000000000000000000000000000..f8415fb1e521df91d2bd6998d36ba2e759e05b4a
--- /dev/null
+++ b/pica-wekan-scripts/policy.sh
@@ -0,0 +1,89 @@
+#!/bin/sh
+
+
+. ./ids.sh # contient $username et $password pour authentification
+
+# Paramètres
+boardExpirationDurationYears=${boardExpirationDurationYears-0} # années
+boardExpirationDurationMonths=${boardExpirationDurationMonths-12} # mois
+boardExpirationDurationDays=${boardExpirationDurationDays-0} # jours
+url=${url-"https://wekan.test.picasoft.net"}
+# Deadline = somme des durées du dessus
+
+boardExpirationDurationDays=$(($boardExpirationDurationDays+30*$boardExpirationDurationMonths))
+boardExpirationDurationDays=$(($boardExpirationDurationDays+365*$boardExpirationDurationYears))
+deadLineSeconds=$(($boardExpirationDurationDays*86400))
+now=$(date +%s)
+deadlineTimeStamp=$(($now-$deadLineSeconds))
+
+delete=false
+while getopts "d" option
+do
+  delete=true
+done
+boardsToDelete=""
+totalBoardsToDelete=0
+
+# Récupération du token de connexion
+queryPica=$(curl -s $url/users/login -d 'username='"$username"'&password='"$password"'')
+token=$(echo $queryPica | jq -r .token)
+
+# Récupération des utilisateurs
+users=$(curl -s -X GET $url/api/users \
+  -H 'Accept: application/json' \
+  -H 'Authorization: Bearer '"$token"'')
+usersIds=$(echo $users | jq -r '.[]._id')
+usersUsernames=$(echo $users | jq -r '.[].username')
+
+# Boucle sur les utilisateurs
+for usersId in $usersIds
+do
+  # Récupération des boards de chaque utilisateur
+  userBoards=$(curl -s -X GET $url/api/users/$usersId/boards \
+  -H 'Accept: application/json' \
+  -H 'Authorization: Bearer '"$token"'' | jq -r '.[]._id')
+
+  # Boucle sur chaque board de l'utilisateur
+  for userBoard in $userBoards
+  do
+    # Récupération de la date de dernière modification et du titre du board concerné
+    board=$(curl -s -X GET $url/api/boards/$userBoard \
+    -H 'Accept: application/json' \
+    -H 'Authorization: Bearer '"$token"'')
+    boardTitle=$(echo $board | jq -r '.title')
+    lastModificationDate=$(echo $board | jq -r '.modifiedAt' | sed 's/T.*Z//g')
+    # Si le board n'a jamais été modifié, on considère alors sa date de création
+    if [ $lastModificationDate = null ]
+    then
+      lastModificationDate=$(echo $board | jq -r '.createdAt' | sed 's/T.*Z//g')
+    fi
+
+    if [ $(($deadlineTimeStamp-$(date -d $lastModificationDate +%s))) -gt 0 ]
+    then
+      if [ $delete = true ]
+      then
+        echo "Suppression du board "$boardTitle" (_id "$userBoard", modifié le "$lastModificationDate")"
+
+        # Suppression du board si trop ancien
+        curl -X DELETE https://wekan.test.picasoft.net/api/boards/$userBoard \
+        -H 'Authorization: Bearer '"$token"''
+        totalBoardsToDelete=$(($totalBoardsToDelete+1))
+      elif [ $(echo $boardsToDelete | grep -c $userBoard) -eq 0 ]
+      then
+        echo "Board "$boardTitle" trop ancien (modifié le "$lastModificationDate")"
+        boardsToDelete=$boardsToDelete" "$userBoard
+        totalBoardsToDelete=$(($totalBoardsToDelete+1))
+      fi
+    fi
+  done
+done
+
+if [ $delete = true ]
+then
+  echo "Total de boards supprimés : "$totalBoardsToDelete
+else
+  echo "Total de boards à supprimer : "$totalBoardsToDelete
+fi
+
+
+exit 1
diff --git a/pica-wekan-scripts/run.sh b/pica-wekan-scripts/run.sh
new file mode 100755
index 0000000000000000000000000000000000000000..64c53e15d66e6f851a00bb6db1411bc3b561a786
--- /dev/null
+++ b/pica-wekan-scripts/run.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+
+if [ $DRYRUN -eq 0 ]
+then
+  ./policy.sh -d
+else
+  ./policy.sh
+fi
diff --git a/pica-wekan/Dockerfile b/pica-wekan/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..b0d69e341ddbddc1639070394237727caa53238c
--- /dev/null
+++ b/pica-wekan/Dockerfile
@@ -0,0 +1,261 @@
+FROM ubuntu:disco
+LABEL maintainer="wekan"
+
+# Set the environment variables (defaults where required)
+# DOES NOT WORK: paxctl fix for alpine linux: https://github.com/wekan/wekan/issues/1303
+# ENV BUILD_DEPS="paxctl"
+ENV BUILD_DEPS="apt-utils bsdtar gnupg gosu wget curl bzip2 build-essential python3 python3-pip git ca-certificates gcc-8" \
+    DEBUG=false \
+    NODE_VERSION=v8.16.0 \
+    METEOR_RELEASE=1.6.0.1 \
+    USE_EDGE=false \
+    METEOR_EDGE=1.5-beta.17 \
+    NPM_VERSION=latest \
+    FIBERS_VERSION=2.0.0 \
+    ARCHITECTURE=linux-x64 \
+    SRC_PATH=./ \
+    WITH_API=true \
+    ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURES_BEFORE=3 \
+    ACCOUNTS_LOCKOUT_KNOWN_USERS_PERIOD=60 \
+    ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURE_WINDOW=15 \
+    ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURES_BERORE=3 \
+    ACCOUNTS_LOCKOUT_UNKNOWN_USERS_LOCKOUT_PERIOD=60 \
+    ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURE_WINDOW=15 \
+    EMAIL_NOTIFICATION_TIMEOUT=30000 \
+    MATOMO_ADDRESS="" \
+    MATOMO_SITE_ID="" \
+    MATOMO_DO_NOT_TRACK=true \
+    MATOMO_WITH_USERNAME=false \
+    BROWSER_POLICY_ENABLED=true \
+    TRUSTED_URL="" \
+    WEBHOOKS_ATTRIBUTES="" \
+    OAUTH2_ENABLED=false \
+    OAUTH2_LOGIN_STYLE=redirect \
+    OAUTH2_CLIENT_ID="" \
+    OAUTH2_SECRET="" \
+    OAUTH2_SERVER_URL="" \
+    OAUTH2_AUTH_ENDPOINT="" \
+    OAUTH2_USERINFO_ENDPOINT="" \
+    OAUTH2_TOKEN_ENDPOINT="" \
+    OAUTH2_ID_MAP="" \
+    OAUTH2_USERNAME_MAP="" \
+    OAUTH2_FULLNAME_MAP="" \
+    OAUTH2_ID_TOKEN_WHITELIST_FIELDS=[] \
+    OAUTH2_REQUEST_PERMISSIONS=['openid','profiles','email'] \
+    OAUTH2_EMAIL_MAP="" \
+    LDAP_ENABLE=false \
+    LDAP_PORT=389 \
+    LDAP_HOST="" \
+    LDAP_BASEDN="" \
+    LDAP_LOGIN_FALLBACK=false \
+    LDAP_RECONNECT=true \
+    LDAP_TIMEOUT=10000 \
+    LDAP_IDLE_TIMEOUT=10000 \
+    LDAP_CONNECT_TIMEOUT=10000 \
+    LDAP_AUTHENTIFICATION=false \
+    LDAP_AUTHENTIFICATION_USERDN="" \
+    LDAP_AUTHENTIFICATION_PASSWORD="" \
+    LDAP_LOG_ENABLED=false \
+    LDAP_BACKGROUND_SYNC=false \
+    LDAP_BACKGROUND_SYNC_INTERVAL=100 \
+    LDAP_BACKGROUND_SYNC_KEEP_EXISTANT_USERS_UPDATED=false \
+    LDAP_BACKGROUND_SYNC_IMPORT_NEW_USERS=false \
+    LDAP_ENCRYPTION=false \
+    LDAP_CA_CERT="" \
+    LDAP_REJECT_UNAUTHORIZED=false \
+    LDAP_USER_AUTHENTICATION=false \
+    LDAP_USER_SEARCH_FILTER="" \
+    LDAP_USER_SEARCH_SCOPE="" \
+    LDAP_USER_SEARCH_FIELD="" \
+    LDAP_SEARCH_PAGE_SIZE=0 \
+    LDAP_SEARCH_SIZE_LIMIT=0 \
+    LDAP_GROUP_FILTER_ENABLE=false \
+    LDAP_GROUP_FILTER_OBJECTCLASS="" \
+    LDAP_GROUP_FILTER_GROUP_ID_ATTRIBUTE="" \
+    LDAP_GROUP_FILTER_GROUP_MEMBER_ATTRIBUTE="" \
+    LDAP_GROUP_FILTER_GROUP_MEMBER_FORMAT="" \
+    LDAP_GROUP_FILTER_GROUP_NAME="" \
+    LDAP_UNIQUE_IDENTIFIER_FIELD="" \
+    LDAP_UTF8_NAMES_SLUGIFY=true \
+    LDAP_USERNAME_FIELD="" \
+    LDAP_FULLNAME_FIELD="" \
+    LDAP_MERGE_EXISTING_USERS=false \
+    LDAP_EMAIL_FIELD="" \
+    LDAP_EMAIL_MATCH_ENABLE=false \
+    LDAP_EMAIL_MATCH_REQUIRE=false \
+    LDAP_EMAIL_MATCH_VERIFIED=false \
+    LDAP_SYNC_USER_DATA=false \
+    LDAP_SYNC_USER_DATA_FIELDMAP="" \
+    LDAP_SYNC_GROUP_ROLES="" \
+    LDAP_DEFAULT_DOMAIN="" \
+    LDAP_SYNC_ADMIN_STATUS="" \
+    LDAP_SYNC_ADMIN_GROUPS="" \
+    HEADER_LOGIN_ID="" \
+    HEADER_LOGIN_FIRSTNAME="" \
+    HEADER_LOGIN_LASTNAME="" \
+    HEADER_LOGIN_EMAIL="" \
+    LOGOUT_WITH_TIMER=false \
+    LOGOUT_IN="" \
+    LOGOUT_ON_HOURS="" \
+    LOGOUT_ON_MINUTES="" \
+    CORS="" \
+    DEFAULT_AUTHENTICATION_METHOD=""
+
+RUN set -o xtrace && \                                                                                                                                                       
+    apt-get update -y && apt-get install -y --no-install-recommends ${BUILD_DEPS} && \  
+    pip3 install -U pip setuptools wheel 
+
+RUN git clone https://github.com/wekan/wekan && cd wekan && git checkout v2.75 && cd .. && mkdir /home/wekan && cp -r ./wekan /home/wekan/app && \ 
+    useradd --user-group --system --home-dir /home/wekan wekan
+
+    # Meteor installer doesn't work with the default tar binary, so using bsdtar while installing.
+    # https://github.com/coreos/bugs/issues/1095#issuecomment-350574389
+RUN cp $(which tar) $(which tar)~ && \
+    ln -sf $(which bsdtar) $(which tar) && \
+    \
+    # Download nodejs
+    wget https://nodejs.org/dist/${NODE_VERSION}/node-${NODE_VERSION}-${ARCHITECTURE}.tar.gz && \
+    wget https://nodejs.org/dist/${NODE_VERSION}/SHASUMS256.txt.asc && \
+    #---------------------------------------------------------------------------------------------
+    # Node Fibers 100% CPU usage issue:
+    # https://github.com/wekan/wekan-mongodb/issues/2#issuecomment-381453161
+    # https://github.com/meteor/meteor/issues/9796#issuecomment-381676326
+    # https://github.com/sandstorm-io/sandstorm/blob/0f1fec013fe7208ed0fd97eb88b31b77e3c61f42/shell/server/00-startup.js#L99-L129
+    # Also see beginning of wekan/server/authentication.js
+    #   import Fiber from "fibers";
+    #   Fiber.poolSize = 1e9;
+    # OLD: Download node version 8.12.0 prerelease that has fix included, => Official 8.12.0 has been released
+    # Description at https://releases.wekan.team/node.txt
+    #wget https://releases.wekan.team/node-${NODE_VERSION}-${ARCHITECTURE}.tar.gz && \
+    #echo "1ed54adb8497ad8967075a0b5d03dd5d0a502be43d4a4d84e5af489c613d7795  node-v8.12.0-linux-x64.tar.gz" >> SHASUMS256.txt.asc && \
+    \
+    # Verify nodejs authenticity
+    grep ${NODE_VERSION}-${ARCHITECTURE}.tar.gz SHASUMS256.txt.asc | shasum -a 256 -c - && \
+    #export GNUPGHOME="$(mktemp -d)" && \
+    #\
+    # Try other key servers if ha.pool.sks-keyservers.net is unreachable
+    # Code from https://github.com/chorrell/docker-node/commit/2b673e17547c34f17f24553db02beefbac98d23c
+    # gpg keys listed at https://github.com/nodejs/node#release-team
+    # and keys listed here from previous version of this Dockerfile
+    #for key in \
+    #9554F04D7259F04124DE6B476D5A82AC7E37093B \
+    #94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
+    #FD3A5288F042B6850C66B31F09FE44734EB7990E \
+    #71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
+    #DD8F2338BAE7501E3DD5AC78C273792F7D83545D \
+    #C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
+    #B9AE9905FFD7803F25714661B63B535A4C206CA9 \
+    #; do \
+    #gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key" || \
+    #gpg --keyserver pgp.mit.edu --recv-keys "$key" || \
+    #gpg --keyserver keyserver.pgp.com --recv-keys "$key" ; \
+    #done && \
+    #gpg --verify SHASUMS256.txt.asc && \
+    # Ignore socket files then delete files then delete directories
+    #find "$GNUPGHOME" -type f | xargs rm -f && \
+    #find "$GNUPGHOME" -type d | xargs rm -fR && \
+    rm -f SHASUMS256.txt.asc && \
+    \
+    # Install Node
+    tar xvzf node-${NODE_VERSION}-${ARCHITECTURE}.tar.gz && \
+    rm node-${NODE_VERSION}-${ARCHITECTURE}.tar.gz && \
+    mv node-${NODE_VERSION}-${ARCHITECTURE} /opt/nodejs && \
+    ln -s /opt/nodejs/bin/node /usr/bin/node && \
+    ln -s /opt/nodejs/bin/npm /usr/bin/npm && \
+    \
+    #DOES NOT WORK: paxctl fix for alpine linux: https://github.com/wekan/wekan/issues/1303
+    #paxctl -mC `which node` && \
+    \
+    # Install Node dependencies
+    npm install -g npm@${NPM_VERSION} && \
+    npm install -g node-gyp && \
+    npm install -g fibers@${FIBERS_VERSION} && \
+    \
+    # Change user to wekan and install meteor
+    cd /home/wekan/ && \
+    chown wekan:wekan --recursive /home/wekan && \
+    curl "https://install.meteor.com" -o /home/wekan/install_meteor.sh && \
+    #curl "https://install.meteor.com/?release=${METEOR_RELEASE}" -o /home/wekan/install_meteor.sh && \
+    # OLD: sed -i "s|RELEASE=.*|RELEASE=${METEOR_RELEASE}\"\"|g" ./install_meteor.sh && \
+    # Install Meteor forcing its progress
+    sed -i 's/VERBOSITY="--silent"/VERBOSITY="--progress-bar"/' ./install_meteor.sh && \
+    echo "Starting meteor ${METEOR_RELEASE} installation...   \n" && \
+    chown wekan:wekan /home/wekan/install_meteor.sh && \
+    \
+    # Check if opting for a release candidate instead of major release
+    if [ "$USE_EDGE" = false ]; then \
+      gosu wekan:wekan sh /home/wekan/install_meteor.sh; \
+    else \
+      gosu wekan:wekan git clone --recursive --depth 1 -b release/METEOR@${METEOR_EDGE} git://github.com/meteor/meteor.git /home/wekan/.meteor; \
+    fi; \
+    \
+    # Get additional packages
+    #mkdir -p /home/wekan/app/packages && \
+    #chown wekan:wekan --recursive /home/wekan && \
+    # REPOS BELOW ARE INCLUDED TO WEKAN REPO
+    #cd /home/wekan/app/packages && \
+    #gosu wekan:wekan git clone --depth 1 -b master https://github.com/wekan/flow-router.git kadira-flow-router && \
+    #gosu wekan:wekan git clone --depth 1 -b master https://github.com/meteor-useraccounts/core.git meteor-useraccounts-core && \
+    #gosu wekan:wekan git clone --depth 1 -b master https://github.com/wekan/meteor-accounts-cas.git && \
+    #gosu wekan:wekan git clone --depth 1 -b master https://github.com/wekan/wekan-ldap.git && \
+    #gosu wekan:wekan git clone --depth 1 -b master https://github.com/wekan/wekan-scrollbar.git && \
+    #gosu wekan:wekan git clone --depth 1 -b master https://github.com/wekan/meteor-accounts-oidc.git && \
+    #gosu wekan:wekan git clone --depth 1 -b master --recurse-submodules https://github.com/wekan/markdown.git && \
+    #gosu wekan:wekan mv meteor-accounts-oidc/packages/switch_accounts-oidc wekan-accounts-oidc && \
+    #gosu wekan:wekan mv meteor-accounts-oidc/packages/switch_oidc wekan-oidc && \
+    #gosu wekan:wekan rm -rf meteor-accounts-oidc && \
+    sed -i 's/api\.versionsFrom/\/\/api.versionsFrom/' /home/wekan/app/packages/meteor-useraccounts-core/package.js && \
+    cd /home/wekan/.meteor && \
+    gosu wekan:wekan /home/wekan/.meteor/meteor -- help; \
+    \
+    # extract the OpenAPI specification
+    npm install -g api2html@0.3.3 && \
+    mkdir -p /home/wekan/python && \
+    chown wekan:wekan --recursive /home/wekan/python && \
+    cd /home/wekan/python && \
+    gosu wekan:wekan git clone --depth 1 -b master https://github.com/Kronuz/esprima-python && \
+    cd /home/wekan/python/esprima-python && \
+    python3 setup.py install --record files.txt && \
+    cd /home/wekan/app &&\
+    gosu wekan:wekan mkdir -p ./public/api && \
+    gosu wekan:wekan python3 ./openapi/generate_openapi.py --release $(git describe --tags --abbrev=0) > ./public/api/wekan.yml && \
+    gosu wekan:wekan /opt/nodejs/bin/api2html -c ./public/logo-header.png -o ./public/api/wekan.html ./public/api/wekan.yml; \
+    # Build app
+    cd /home/wekan/app && \
+    gosu wekan:wekan /home/wekan/.meteor/meteor add standard-minifier-js && \
+    gosu wekan:wekan /home/wekan/.meteor/meteor npm install && \
+    gosu wekan:wekan /home/wekan/.meteor/meteor build --directory /home/wekan/app_build && \
+    cp /home/wekan/app/fix-download-unicode/cfs_access-point.txt /home/wekan/app_build/bundle/programs/server/packages/cfs_access-point.js && \
+    rm /home/wekan/app_build/bundle/programs/server/npm/node_modules/meteor/rajit_bootstrap3-datepicker/lib/bootstrap-datepicker/node_modules/phantomjs-prebuilt/lib/phantom/bin/phantomjs && \
+    chown wekan:wekan /home/wekan/app_build/bundle/programs/server/packages/cfs_access-point.js && \
+    #Removed binary version of bcrypt because of security vulnerability that is not fixed yet.
+    #https://github.com/wekan/wekan/commit/4b2010213907c61b0e0482ab55abb06f6a668eac
+    #https://github.com/wekan/wekan/commit/7eeabf14be3c63fae2226e561ef8a0c1390c8d3c
+    #cd /home/wekan/app_build/bundle/programs/server/npm/node_modules/meteor/npm-bcrypt && \
+    #gosu wekan:wekan rm -rf node_modules/bcrypt && \
+    #gosu wekan:wekan npm install bcrypt && \
+    cd /home/wekan/app_build/bundle/programs/server/ && \
+    gosu wekan:wekan npm install && \
+    #gosu wekan:wekan npm install bcrypt && \
+    mv /home/wekan/app_build/bundle /build && \
+    \
+    # Put back the original tar
+    mv $(which tar)~ $(which tar) && \
+    \
+    # Cleanup
+    apt-get remove --purge -y ${BUILD_DEPS} && \
+    apt-get autoremove -y && \
+    npm uninstall -g api2html &&\
+    rm -R /var/lib/apt/lists/* && \
+    rm -R /home/wekan/.meteor && \
+    rm -R /home/wekan/app && \
+    rm -R /home/wekan/app_build && \
+    cat /home/wekan/python/esprima-python/files.txt | xargs rm -R && \
+    rm -R /home/wekan/python && \
+    rm /home/wekan/install_meteor.sh
+
+ENV PORT=8080
+EXPOSE $PORT
+USER wekan
+
+CMD ["node", "/build/main.js"]
diff --git a/pica-wekan/clair-whitelist.yml b/pica-wekan/clair-whitelist.yml
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/pica-wekan/docker-compose.yml b/pica-wekan/docker-compose.yml
new file mode 100644
index 0000000000000000000000000000000000000000..e6b4b149d7cb88a858b0fbf91976b516584e6bfc
--- /dev/null
+++ b/pica-wekan/docker-compose.yml
@@ -0,0 +1,66 @@
+version: '2.4'
+
+networks:
+  docker_default:
+    external: true
+    name: "docker_default"
+
+
+
+services:
+
+  wekan-app:
+    image: pica-wekan:2.75
+    container_name: wekan-app
+    restart: always
+    links:
+      - wekan-db:wekan-db
+    networks:
+      - docker_default
+    labels: 
+      - "traefik.frontend.rule=Host:wekan2.test.picasoft.net"
+      - "traefik.port=8080"     
+      - "traefik.enable=true"
+    environment:
+      - MONGO_URL=mongodb://wekan-db:27017/wekan
+      - ROOT_URL=http://wekan2.test.picasoft.net  #   <=== using only at same laptop/desktop where Wekan is installed
+      - WITH_API=true
+      #---------------------------------------------------------------
+      #
+      # LOGOUT_ON_MINUTES : The number of minutes
+      # example : LOGOUT_ON_MINUTES=55
+      #- LOGOUT_ON_MINUTES=
+      #-------------------------------------------------------------------
+    security_opt:
+      - no-new-privileges
+    mem_limit: "4096m"
+    cpus: "0.60"
+    pids_limit: 1024
+    depends_on:
+      - wekan-db
+
+  wekan-db:
+    image: mongo:3.2.21
+    #-------------------------------------------------------------------------------------
+    container_name: wekan-db
+    restart: always
+    command: mongod --smallfiles --oplogSize 128
+    networks:
+      - docker_default
+    expose:
+      - 27017
+        #volumes:
+        #- wekan-db:/data/db
+        #- wekan-db-dump:/dump
+        #volumes:
+        #- /DATA/docker/wekan-db:/data/db
+    security_opt:
+      - no-new-privileges
+    mem_limit: "2048m"  
+    cpus: "0.20"
+    pids_limit: 1024
+volumes:
+  wekan-db:
+    driver: local
+  wekan-db-dump:
+    driver: local