diff --git a/.circleci/config.yml b/.circleci/config.yml index ce440ab..fc0bff8 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -9,8 +9,11 @@ jobs: name: update-yarn command: 'curl --compressed -o- -L https://yarnpkg.com/install.sh | bash' - run: - name: install-yarn + name: install-dependencies command: yarn install + - run: + name: compile-translations + command: yarn translate - run: name: test command: yarn test diff --git a/README.md b/README.md index 8669fd8..4a23cce 100644 --- a/README.md +++ b/README.md @@ -15,14 +15,20 @@ $ cd mvfront-react $ yarn install ``` +## Translation + +We are welcoming translations of the application in any language. +To add a new language, copy a [language folder](./public/locale/i18n/en/) into a new folder with your language as a name. +Then, replace values in the JSON files. + +To compile them, launch: `$ yarn translate`. ## Starting -In dev: -`yarn start` +In development, you might want to copy `.env` into `.env.local` and set the environment variables. Then launch `$ yarn start` For production, see our [CI/CD configuration](https://github.com/MieuxVoter/continuous-integration). ## Testing -`yarn test` +Launch `$ yarn test` diff --git a/i18n.config.js b/i18n.config.js index efcbe45..c29e59a 100644 --- a/i18n.config.js +++ b/i18n.config.js @@ -30,7 +30,7 @@ module.exports = { // Check out https://github.com/acornjs/acorn/tree/master/acorn#interface for additional options } }, - lngs: ["en", "fr", "es"], + lngs: ["en", "fr", "es", "de"], ns: ["resource", "common"], defaultLng: "en", defaultNs: "resource", diff --git a/make_translation.sh b/make_translation.sh deleted file mode 100755 index 8a2c757..0000000 --- a/make_translation.sh +++ /dev/null @@ -1 +0,0 @@ -i18next-scanner --config i18n.config.js 'src/**/*.{js,jsx}' diff --git a/package.json b/package.json index a2b533a..3daaa66 100644 --- a/package.json +++ b/package.json @@ -84,7 +84,8 @@ "scripts": { "start": "node scripts/start.js", "build": "node scripts/build.js", - "test": "node scripts/test.js" + "test": "node scripts/test.js", + "translate": "i18next-scanner --config i18n.config.js 'src/**/*.{js,jsx}'" }, "eslintConfig": { "extends": "react-app" diff --git a/public/locale/i18n/en/resource.json b/public/locale/i18n/en/resource.json index 3bf653a..4860c47 100644 --- a/public/locale/i18n/en/resource.json +++ b/public/locale/i18n/en/resource.json @@ -66,5 +66,16 @@ "Voters' list": "Voters' list", "Graph": "Graph", "Preference profile": "Merit profile", - "Results of the election:": "Results of the election:" + "Results of the election:": "Results of the election:", + "Unknown error. Try again please.": "Unknown error. Try again please.", + "If you list voters' emails, only them will be able to access the election": "If you list voters' emails, only them will be able to access the election", + "Voters received a link to vote by email. Each link can be used only once!": "Voters received a link to vote by email. Each link can be used only once!", + "Oops... The election is unknown.": "Oops... The election is unknown.", + "The election is still going on. You can't access now to the results.": "The election is still going on. You can't access now to the results.", + "No votes have been recorded yet. Come back later.": "No votes have been recorded yet. Come back later.", + "The election has not started yet.": "The election has not started yet.", + "The election is over. You can't vote anymore": "The election is over. You can't vote anymore", + "You need a token to vote in this election": "You need a token to vote in this election", + "You seem to have already voted.": "You seem to have already voted.", + "The parameters of the election are incorrect.": "The parameters of the election are incorrect." } diff --git a/public/locale/i18n/es/resource.json b/public/locale/i18n/es/resource.json index da34af1..0d246ad 100644 --- a/public/locale/i18n/es/resource.json +++ b/public/locale/i18n/es/resource.json @@ -1,70 +1,81 @@ -{ - "Homepage": "Página de inicio", - "Source code": "Código fuente", - "Who are we": "Quiénes somos", - "BetterVote": "VotarMejor", - "Voting platform": "Plataforma de votación", - "Majority Judgment": "Juicio Mayoritario", - "Start an election": "Iniciar una elección", - "Candidate/proposal name...": "Nombre del(la) candidato(a)/propuesta...", - "Delete?": "Borrar?", - "Are you sure to delete": "Estás seguro de quierer borrar", - "the row": "la fila", - "Write here your question or introduce simple your election (250 characters max.)": "Escriba aquí su pregunta o introduzca simplemente su elección (250 caracteres máx.)", - "Please add at least 2 candidates.": "Por favor, añada al menos dos canidatos(as).", - "Question of the election": "Pregunta de su elección", - "Write here the question of your election": "Escriba aquí la pregunta de su elección", - "For example:": "Por ejemplo:", - "For the role of my representative, I judge this candidate...": "Para ser mi representante, yo elijo a este(a) candidato(a)....", - "Candidates/Proposals": "Candidatos(as)/Propuestas", - "Add a proposal": "Añadir una propuesta", - "Advanced options": "Opciones avanzadas", - "Starting date:": "Fecha de inicio:", - "Ending date: ": "Fecha de finalización: ", - "Grades:": "Escala", - "You can select here the number of grades for your election": "Puede seleccionar aquí el número de niveles de la escala para su elección", - "5 = Excellent, Very good, Good, Fair, Passable": "5 == Excelente, Muy bien, Bien, Regular, Pasable", - "Participants:": "Participantes", - "Add here participants' emails": "Añadir aquí los correos electrónicos de los participantes", - "List voters' emails in case the election is not opened": "Enumere los correos electrónicos de los votantes en caso de que la elección no se abra", - "Validate": "Validar", - "Confirm your vote": "Confirme su voto", - "The form contains no address.": "El formulario no contiene ningún correo electrónico", - "The election will be opened to anyone with the link": "La elección se abrirá a cualquiera que tenga el enlace", - "Start the election": "Iniciar la elección", - "Cancel": "Cancelar", - "Confirm": "Confirmar", - "Successful election creation!": "La elección ha sido creada con éxito!", - "You can now share the election link to participants:": "Ahora puede compartir el enlace de la elección con los participantes", - "Copy": "Copiar", - "Here is the link for the results in real time:": "En este enlace puedes revisar los resultados en tiempo real", - "Keep these links carefully": "Guarda cuidadosamente estos enlaces", - "Participate now!": "¡Participa ahora!", - "t": "<0>Advertencia: No tendrás otras opciones para recuperar los enlaces, y no podremos compartirlos contigo. Por ejemplo, puedes agregarlos a favoritos de tu buscador.", - "Simple and free: organize an election with Majority Judgment.": "Simple y gratuito: organizar una elección con Juicio Mayoritario", - "Start": "Comenzar", - "No advertising or ad cookies": "No contiene publicidad ni cookies publicitarias", - "Oops! This election does not exist or it is not available anymore.": "¡Uy! Esta elección no existe o ya no está disponible", - "You can start another election.": "Puedes empezar otra elección", - "Go back to homepage": "Vuelve a la página de inicio", - "You have to judge every candidate/proposal!": "¡Tienes que evaluar a todos los(as) candidatos(as)/propuestas", - "Your participation was recorded with success!": "¡Su participación fue registrada con éxito!", - "Thanks for your participation.": "Muchas gracias por participar", - "Ending date:": "Fecha de finalización:", - "Excellent": "Excelente", - "Very good": "Muy bien", - "Good": "Bien", - "Fair": "Regular", - "Passable": "Pasable", - "Insufficient": "Insuficiente", - "To reject": "Rechazar", - "Dates": "Fechas", - "The election will take place from": "La elección tendrá lugar de las", - "at": "a las", - "to": "hasta", - "Grades": "Escala", - "Voters' list": "Lista de votantes", - "Graph": "Gráfico", - "Preference profile": "Perfil de preferencia", - "Results of the election:": "Resultados de la elección" -} +{ + "Homepage": "Página de inicio", + "Source code": "Código fuente", + "Who are we": "Quiénes somos", + "BetterVote": "VotarMejor", + "Voting platform": "Plataforma de votación", + "Majority Judgment": "Juicio Mayoritario", + "Start an election": "Iniciar una elección", + "Candidate/proposal name...": "Nombre del(la) candidato(a)/propuesta...", + "Delete?": "Borrar?", + "Are you sure to delete": "Estás seguro de quierer borrar", + "the row": "la fila", + "Write here your question or introduce simple your election (250 characters max.)": "Escriba aquí su pregunta o introduzca simplemente su elección (250 caracteres máx.)", + "Please add at least 2 candidates.": "Por favor, añada al menos dos canidatos(as).", + "Question of the election": "Pregunta de su elección", + "Write here the question of your election": "Escriba aquí la pregunta de su elección", + "For example:": "Por ejemplo:", + "For the role of my representative, I judge this candidate...": "Para ser mi representante, yo elijo a este(a) candidato(a)....", + "Candidates/Proposals": "Candidatos(as)/Propuestas", + "Add a proposal": "Añadir una propuesta", + "Advanced options": "Opciones avanzadas", + "Starting date:": "Fecha de inicio:", + "Ending date: ": "Fecha de finalización: ", + "Grades:": "Escala", + "You can select here the number of grades for your election": "Puede seleccionar aquí el número de niveles de la escala para su elección", + "5 = Excellent, Very good, Good, Fair, Passable": "5 == Excelente, Muy bien, Bien, Regular, Pasable", + "Participants:": "Participantes", + "Add here participants' emails": "Añadir aquí los correos electrónicos de los participantes", + "List voters' emails in case the election is not opened": "Enumere los correos electrónicos de los votantes en caso de que la elección no se abra", + "Validate": "Validar", + "Confirm your vote": "Confirme su voto", + "The form contains no address.": "El formulario no contiene ningún correo electrónico", + "The election will be opened to anyone with the link": "La elección se abrirá a cualquiera que tenga el enlace", + "Start the election": "Iniciar la elección", + "Cancel": "Cancelar", + "Confirm": "Confirmar", + "Successful election creation!": "La elección ha sido creada con éxito!", + "You can now share the election link to participants:": "Ahora puede compartir el enlace de la elección con los participantes", + "Copy": "Copiar", + "Here is the link for the results in real time:": "En este enlace puedes revisar los resultados en tiempo real", + "Keep these links carefully": "Guarda cuidadosamente estos enlaces", + "Participate now!": "¡Participa ahora!", + "t": "<0>Advertencia: No tendrás otras opciones para recuperar los enlaces, y no podremos compartirlos contigo. Por ejemplo, puedes agregarlos a favoritos de tu buscador.", + "Simple and free: organize an election with Majority Judgment.": "Simple y gratuito: organizar una elección con Juicio Mayoritario", + "Start": "Comenzar", + "No advertising or ad cookies": "No contiene publicidad ni cookies publicitarias", + "Oops! This election does not exist or it is not available anymore.": "¡Uy! Esta elección no existe o ya no está disponible", + "You can start another election.": "Puedes empezar otra elección", + "Go back to homepage": "Vuelve a la página de inicio", + "You have to judge every candidate/proposal!": "¡Tienes que evaluar a todos los(as) candidatos(as)/propuestas", + "Your participation was recorded with success!": "¡Su participación fue registrada con éxito!", + "Thanks for your participation.": "Muchas gracias por participar", + "Ending date:": "Fecha de finalización:", + "Excellent": "Excelente", + "Very good": "Muy bien", + "Good": "Bien", + "Fair": "Regular", + "Passable": "Pasable", + "Insufficient": "Insuficiente", + "To reject": "Rechazar", + "Dates": "Fechas", + "The election will take place from": "La elección tendrá lugar de las", + "at": "a las", + "to": "hasta", + "Grades": "Escala", + "Voters' list": "Lista de votantes", + "Graph": "Gráfico", + "Preference profile": "Perfil de preferencia", + "Results of the election:": "Resultados de la elección", + "Unknown error. Try again please.": "__STRING_NOT_TRANSLATED__", + "If you list voters' emails, only them will be able to access the election": "__STRING_NOT_TRANSLATED__", + "Voters received a link to vote by email. Each link can be used only once!": "__STRING_NOT_TRANSLATED__", + "Oops... The election is unknown.": "__STRING_NOT_TRANSLATED__", + "The election is still going on. You can't access now to the results.": "__STRING_NOT_TRANSLATED__", + "No votes have been recorded yet. Come back later.": "__STRING_NOT_TRANSLATED__", + "The election has not started yet.": "__STRING_NOT_TRANSLATED__", + "The election is over. You can't vote anymore": "__STRING_NOT_TRANSLATED__", + "You need a token to vote in this election": "__STRING_NOT_TRANSLATED__", + "You seem to have already voted.": "__STRING_NOT_TRANSLATED__", + "The parameters of the election are incorrect.": "__STRING_NOT_TRANSLATED__" +} diff --git a/public/locale/i18n/fr/resource.json b/public/locale/i18n/fr/resource.json index 37d8226..2f7d8fc 100644 --- a/public/locale/i18n/fr/resource.json +++ b/public/locale/i18n/fr/resource.json @@ -66,5 +66,16 @@ "Voters' list": "Listes des électeurs", "Graph": "Graphique", "Preference profile": "Profil de mérites", - "Results of the election:": "Résultats de l'élection" + "Results of the election:": "Résultats de l'élection", + "Unknown error. Try again please.": "Erreur inconnue. Merci de ré-essayer plus tard.", + "If you list voters' emails, only them will be able to access the election": "Si vous ajoutez des emails, seulement ceux-là seront capables d'accéder à l'élection", + "Voters received a link to vote by email. Each link can be used only once!": "Les électeurs ont reçu un lien par courriel pour voter. Chaque lien ne peut être utilisé qu'une seule fois.", + "Oops... The election is unknown.": "Oups... Le serveur ne retrouve pas l'élection.", + "The election is still going on. You can't access now to the results.": "L'élection est encore en cours. Vous ne pouvez pas encore accéder aux résultats.", + "No votes have been recorded yet. Come back later.": "Aucun vote n'a été enregistré. Merci de revenir plus tard.", + "The election has not started yet.": "L'élection n'a pas encore commencé.", + "The election is over. You can't vote anymore": "L'élection est terminée. Vous ne pouvez plus voter.", + "You need a token to vote in this election": "Vous avez besoin d'un jeton pour voter dans cette élection", + "You seem to have already voted.": "Il semble que vous ayez déjà voté.", + "The parameters of the election are incorrect.": "Les paramètres de l'élection sont incorrects." } diff --git a/src/components/layouts/Footer.jsx b/src/components/layouts/Footer.jsx index 894011a..687812e 100644 --- a/src/components/layouts/Footer.jsx +++ b/src/components/layouts/Footer.jsx @@ -20,6 +20,13 @@ class Footer extends Component { const buttonStyle = {backgroundColor: "black", padding: "0px", border: "0px",}; const linkStyle = {whiteSpace: "nowrap"}; const {t} = this.props; + const countries = [ + {"l": "en", "flag": "gb"}, + {"l": "es", "flag": "es"}, + {"l": "fr", "flag": "fr"}, + {"l": "de", "flag": "de"}, + ]; + return (