瀏覽代碼

Translated most of the frontend to English.

KrisVos130 7 年之前
父節點
當前提交
aab123f639

+ 6 - 2
frontend/app/js/components/AuthRoute.jsx

@@ -2,6 +2,7 @@ import React, { Component } from "react";
 import { connect } from "react-redux";
 import PropTypes from "prop-types";
 import { Redirect, Route } from "react-router-dom";
+import { translate } from "react-i18next";
 
 import io from "io";
 
@@ -11,6 +12,7 @@ import io from "io";
 	authProcessed: state.user.get("authProcessed"),
 }))
 
+@translate(["general"], { wait: true })
 export default class AuthRoute extends Component {
 	static propTypes = {
 		loggedIn: PropTypes.bool,
@@ -23,6 +25,7 @@ export default class AuthRoute extends Component {
 			PropTypes.func,
 		]),
 		computedMatch: PropTypes.object,
+		t: PropTypes.func,
 	};
 
 	static defaultProps = {
@@ -33,6 +36,7 @@ export default class AuthRoute extends Component {
 		authProcessed: false,
 		component: () => {},
 		computedMatch: {},
+		t: () => {},
 	};
 
 	constructor(props) {
@@ -71,7 +75,7 @@ export default class AuthRoute extends Component {
 	};
 
 	render() {
-		const { auth, role, loggedIn, authProcessed } = this.props;
+		const { auth, role, loggedIn, authProcessed, t } = this.props;
 		const { stationName, waitingFor, receivedStationData, stationData } = this.state;
 
 		if (this.state.continue) {
@@ -97,6 +101,6 @@ export default class AuthRoute extends Component {
 				return <Redirect to={ "/" } />;
 			}
 		}
-		return <h1>Loading...</h1>;
+		return <h1>{ t("general:loading") }</h1>;
 	}
 }

+ 9 - 7
frontend/app/js/components/CustomInput.jsx

@@ -1,6 +1,8 @@
 import React, { Component } from "react";
 import PropTypes from "prop-types";
-import reactTriggerChange from "react-trigger-change";
+const i18next = require("i18next");
+
+const t = i18next.t;
 
 const isLength = (string, min, max) => {
 	return !(typeof string !== "string" || string.length < min || string.length > max);
@@ -23,7 +25,7 @@ const dictionary = {
 		maxLength: 32,
 		regex: regex.azAZ09_,
 		errors: {
-			format: "Invalid username format. Allowed characters: a-z, A-Z, 0-9 and _."
+			format: t("general:invalidUsernameFormat", { characters: `a-z, A-Z, 0-9${ t("general:and") } _` }),
 		},
 	},
 	email: {
@@ -32,7 +34,7 @@ const dictionary = {
 		maxLength: 254,
 		regex: regex.emailSimple,
 		errors: {
-			format: "Invalid email format. Email must contain one @ symbol.",
+			format: t("general:invalidEmailFormat"),
 		},
 	},
 	password: {
@@ -41,7 +43,7 @@ const dictionary = {
 		maxLength: 200,
 		regex: regex.password,
 		errors: {
-			format: "Invalid password format. Password must have at least 1 lowercase letter, 1 uppercase letter, 1 number and one special character ($@$!%*?&).",
+			format: t("general:invalidPasswordFormat", { characters: "$@$!%*?&" }),
 		},
 	},
 	uniqueCode: {
@@ -50,8 +52,8 @@ const dictionary = {
 		maxLength: 8,
 		regex: regex.azAZ09,
 		errors: {
-			length: "Code must be 8 characters long.",
-			format: "Invalid code format.",
+			length: t("general:invalidCodeLength", { length: 8 }),
+			format: t("general:invalidCodeFormat"),
 		},
 	},
 };
@@ -183,7 +185,7 @@ export default class CustomInput extends Component {
 		const errors = [];
 		const info = dictionary[this.props.type];
 		const value = this.state.value;
-		if (!isLength(value, info.minLength, info.maxLength)) errors.push((info.errors.length) ? info.errors.length : `Value must be between ${ info.minLength } and ${ info.maxLength } characters long.`);
+		if (!isLength(value, info.minLength, info.maxLength)) errors.push((info.errors.length) ? info.errors.length : t("general:valueMustBeBetween", { min: info.minLength, max: info.maxLength }));
 		if (!info.regex.test(value)) errors.push(info.errors.format);
 		this.setState({
 			errors,

+ 7 - 3
frontend/app/js/components/CustomMessages.jsx

@@ -1,6 +1,10 @@
 import React, { Component } from "react";
 import PropTypes from "prop-types";
 
+const i18n = require("i18n");
+
+const t = i18n.default.translator.translate;
+
 export default class CustomMessages extends Component {
 	static propTypes = {
 		onRef: PropTypes.func,
@@ -107,9 +111,9 @@ export default class CustomMessages extends Component {
 				return (<li key={ key }>{ message }</li>);
 			});
 			let text = "";
-			if (type === "error") text = "Something went wrong";
-			else if (type === "info") text = "Info";
-			else if (type === "success") text = "Success";
+			if (type === "error") text = t("customMessages:somethingWentWrong");
+			else if (type === "info") text = t("customMessages:info");
+			else if (type === "success") text = t("customMessages:success");
 
 			return (
 				<div key={ type } className={ type }>

+ 11 - 6
frontend/app/js/components/Global/Navbar.jsx

@@ -2,18 +2,21 @@ import React, { Component } from "react";
 import PropTypes from "prop-types";
 import { connect } from "react-redux";
 import { NavLink } from "react-router-dom";
+import { translate } from "react-i18next";
 
 @connect(state => ({
 	loggedIn: state.user.get("loggedIn"),
 }))
-
+@translate(["navbar"], { wait: true })
 export default class Menu extends Component {
 	static propTypes = {
 		loggedIn: PropTypes.bool,
+		t: PropTypes.func,
 	};
 
 	static defaultProps = {
 		loggedIn: false,
+		t: () => {},
 	};
 
 	getLink(to, text, canShow = true) {
@@ -21,13 +24,15 @@ export default class Menu extends Component {
 	}
 
 	render() {
+		const { t } = this.props;
+
 		return (
 			<header className="Menu">
-				{this.getLink("/", "Home")}
-				{this.getLink("/login", "Login", !this.props.loggedIn)}
-				{this.getLink("/register", "Register", !this.props.loggedIn)}
-				{this.getLink("/settings", "Settings", this.props.loggedIn)}
-				{this.getLink("/logout", "Logout", this.props.loggedIn)}
+				{this.getLink("/", t("navbar:home"))}
+				{this.getLink("/login", t("navbar:login"), !this.props.loggedIn)}
+				{this.getLink("/register", t("navbar:register"), !this.props.loggedIn)}
+				{this.getLink("/settings", t("navbar:settings"), this.props.loggedIn)}
+				{this.getLink("/logout", t("navbar:logout"), this.props.loggedIn)}
 			</header>
 		);
 	}

+ 24 - 28
frontend/app/js/views/Auth/ForgotPassword/index.jsx

@@ -1,27 +1,21 @@
 import React, { Component } from "react";
 import PropTypes from "prop-types";
 import { connect } from "react-redux";
+import { translate } from "react-i18next";
 
 import CustomInput from "components/CustomInput.jsx";
 import CustomErrors from "components/CustomMessages.jsx";
 
 import io from "io";
 
-@connect(state => ({
-	user: {
-		userId: state.user.get("userId"),
-	},
-}))
-
-export default class Settings extends Component {
+@translate(["forgotPassword"], { wait: true })
+export default class ForgotPassword extends Component {
 	static propTypes = {
-		user: PropTypes.object,
+		t: PropTypes.func,
 	};
 
 	static defaultProps = {
-		user: {
-			userId: "",
-		},
+		t: () => {},
 	};
 
 	constructor(props) {
@@ -36,23 +30,23 @@ export default class Settings extends Component {
 	}
 
 	getActions = () => {
-		const emailInput = <CustomInput key="email" type="email" name="email" label="Email" placeholder="Email" onRef={ ref => (this.input.email = ref) } />;
+		const emailInput = <CustomInput key="email" type="email" name="email" label={ this.props.t("general:emailInput") } placeholder={ this.props.t("general:emailInput") } onRef={ ref => (this.input.email = ref) } />;
 		const requestResetCodeButton = (<button key="requestResetCode" onClick={ this.requestResetCode }>
-			Request reset code
+			{ this.props.t("forgotPassword:requestResetCode") }
 		</button>);
 		const iAlreadyHaveAResetCodeButton = (<button key="skipRequestResetCode" onClick={ this.skipRequestResetCode }>
-			I already have a reset code
+			{ this.props.t("forgotPassword:requestResetCode") }
 		</button>);
 
-		const resetCodeInput = <CustomInput key="resetCode" type="uniqueCode" name="resetCode" label="Reset code" placeholder="Reset code" onRef={ ref => (this.input.resetCode = ref) } />;
+		const resetCodeInput = <CustomInput key="resetCode" type="uniqueCode" name="resetCode" label={ this.props.t("general:resetCodeInput") } placeholder={ this.props.t("general:resetCodeInput") } onRef={ ref => (this.input.resetCode = ref) } />;
 		const verifyResetCode = (<button key="verifyResetCode" onClick={ this.verifyResetCode }>
-			Verify reset code
+			{ this.props.t("forgotPassword:verifyResetCode") }
 		</button>);
 
-		const newPasswordInput = <CustomInput key="newPassword" type="password" name="newPassword" label="New password" placeholder="New password" onRef={ ref => (this.input.newPassword = ref) } />;
-		const newPasswordAgainInput = <CustomInput key="newPasswordAgain" type="password" name="newPasswordAgain" label="New password again" placeholder="New password again" onRef={ ref => (this.input.newPasswordAgain = ref) } />;
+		const newPasswordInput = <CustomInput key="newPassword" type="password" name="newPassword" label={ this.props.t("general:newPasswordInput") } placeholder={ this.props.t("general:newPasswordInput") } onRef={ ref => (this.input.newPassword = ref) } />;
+		const newPasswordAgainInput = <CustomInput key="newPasswordAgain" type="password" name="newPasswordAgain" label={ this.props.t("general:newPasswordAgainInput") } placeholder={ this.props.t("general:newPasswordAgainInput") } onRef={ ref => (this.input.newPasswordAgain = ref) } />;
 		const changePassword = (<button key="changePassword" onClick={ this.changePassword }>
-			Change password
+			{ this.props.t("forgotPassword:changePassword") }
 		</button>);
 
 		if (this.state.step === 1) {
@@ -64,14 +58,14 @@ export default class Settings extends Component {
 
 	requestResetCode = () => {
 		if (CustomInput.hasInvalidInput(this.input, ["email"])) {
-			this.messages.clearAddError("Some fields are incorrect. Please fix them before continuing.");
+			this.messages.clearAddError(this.props.t("general:someFieldsAreIncorrectError"));
 		} else {
 			this.messages.clearAll();
 			io.getSocket(socket => {
 				socket.emit("users.requestPasswordReset", this.input.email.getValue(), res => {
 					if (res.status === "success") {
-						this.messages.clearAddSuccess("Successfully requested reset code.");
-						this.messages.clearAddInfo("We have sent a unique reset code to your email address.");
+						this.messages.clearAddSuccess(this.props.t("forgotPassword:successfullyRequestedResetCode"));
+						this.messages.clearAddInfo(this.props.t("forgotPassword:weHaveSentAUniqueResetCode"));
 						this.setState({
 							step: 2,
 						});
@@ -85,13 +79,13 @@ export default class Settings extends Component {
 
 	verifyResetCode = () => {
 		if (CustomInput.hasInvalidInput(this.input, ["resetCode"])) {
-			this.messages.clearAddError("Some fields are incorrect. Please fix them before continuing.");
+			this.messages.clearAddError(this.props.t("general:someFieldsAreIncorrectError"));
 		} else {
 			this.messages.clearErrors();
 			io.getSocket(socket => {
 				socket.emit("users.verifyPasswordResetCode", this.input.resetCode.getValue(), res => {
 					if (res.status === "success") {
-						this.messages.clearAddSuccess("Successfully verified reset code.");
+						this.messages.clearAddSuccess(this.props.t("forgotPassword:successfullyVerifiedResetCode"));
 						this.setState({
 							step: 3,
 							resetCode: this.input.resetCode.getValue(),
@@ -107,14 +101,14 @@ export default class Settings extends Component {
 	changePassword = () => {
 		this.messages.clearErrorSuccess();
 		if (CustomInput.hasInvalidInput(this.input, ["newPassword", "newPasswordAgain"])) {
-			this.messages.clearAddError("Some fields are incorrect. Please fix them before continuing.");
+			this.messages.clearAddError(this.props.t("general:someFieldsAreIncorrectError"));
 		} else if (CustomInput.isTheSame(this.input, ["newPassword", "newPasswordAgain"])) {
-			this.messages.clearAddError("New password and new password again need to be the same.");
+			this.messages.clearAddError(this.props.t("general:newPasswordNewPasswordAgainSameError"));
 		} else {
 			io.getSocket(socket => {
 				socket.emit("users.changePasswordWithResetCode", this.state.resetCode, this.input.newPassword.getValue(), res => {
 					if (res.status === "success") {
-						this.messages.clearAddSuccess("Successfully changed password. Redirecting you to the login page.");
+						this.messages.clearAddSuccess(this.props.t("forgotPassword:successfullyChangedPassword"));
 						// TODO Maybe add 5s delay and replace location.href everywhere
 						location.href = "/login";
 					} else {
@@ -132,9 +126,11 @@ export default class Settings extends Component {
 	};
 
 	render() {
+		const { t } = this.props;
+
 		return (
 			<div>
-				<h1>Reset password</h1>
+				<h1>{ t("forgotPassword:title") }</h1>
 				<div className="steps">
 					<span className={ `step-circle-1 ${ this.state.step === 1 ? "step-circle-active" : "" }` }>1</span>
 					<span className="step-line-1" />

+ 21 - 7
frontend/app/js/views/Auth/Login/index.jsx

@@ -2,11 +2,22 @@ import React, { Component } from "react";
 
 import CustomInput from "components/CustomInput.jsx";
 import CustomMessages from "components/CustomMessages.jsx";
+import PropTypes from "prop-types";
+import { translate } from "react-i18next";
 
 import io from "io";
 import config from "config";
 
+@translate(["login"], { wait: true })
 export default class Login extends Component {
+	static propTypes = {
+		t: PropTypes.func,
+	};
+
+	static defaultProps = {
+		t: () => {},
+	};
+
 	constructor() {
 		super();
 
@@ -16,7 +27,7 @@ export default class Login extends Component {
 	login = () => {
 		this.messages.clearErrorSuccess();
 		if (CustomInput.hasInvalidInput(this.input)) {
-			this.messages.clearAddError("Some fields are incorrect. Please fix them before continuing.");
+			this.messages.clearAddError(this.props.t("general:someFieldsAreIncorrectError"));
 		} else {
 			io.getSocket(socket => {
 				socket.emit("users.login", this.input.email.getValue(), this.input.password.getValue(), res => {
@@ -41,17 +52,20 @@ export default class Login extends Component {
 	}
 
 	render() {
+		const { t } = this.props;
+
 		return (
 			<div>
+				<h1>{ t("login:title") }</h1>
 				<CustomMessages onRef={ ref => (this.messages = ref) } />
-				<CustomInput type="email" name="email" label="Email" placeholder="Email" onRef={ ref => (this.input.email = ref) } />
-				<CustomInput type="password" name="password" label="Password" placeholder="Password" onRef={ ref => (this.input.password = ref) } />
-				<p>By logging in/registering you agree to our <a href="/terms">Terms of Service</a> and <a href="/privacy">Privacy Policy</a>.</p>
-				<button onClick={ this.login }>Login</button>
+				<CustomInput type="email" name="email" label={ t("general:emailInput") } placeholder={ t("general:emailInput") } onRef={ ref => (this.input.email = ref) } />
+				<CustomInput type="password" name="password" label={ t("general:passwordInput") } placeholder={ t("general:passwordInput") } onRef={ ref => (this.input.password = ref) } />
+				<p>{ t("login:byLoggingIn", { termsOfService: <a href="/terms">{ t("general:termsOfService") }</a>, privacyPolicy: <a href="/privacy">{ t("general:privacyPolicy") }</a> }) }</p>
+				<button onClick={ this.login }>{ t("login:login") }</button>
 				<a href={ `${ config.serverDomain }/auth/github/authorize` } onClick={ this.githubRedirect }>
-					<img alt="GitHub Icon" src="/assets/images/social/github.svg" /> &nbsp;&nbsp;Login with GitHub
+					{ t("login:loginWithGitHub") }
 				</a>
-				<a href="/reset_password">Forgot password?</a>
+				<a href="/reset_password">{ t("login:forgotPassword") }</a>
 			</div>
 		);
 	}

+ 21 - 12
frontend/app/js/views/Auth/Register/index.jsx

@@ -2,11 +2,22 @@ import React, { Component } from "react";
 
 import CustomInput from "components/CustomInput.jsx";
 import CustomMessages from "components/CustomMessages.jsx";
+import PropTypes from "prop-types";
+import { translate } from "react-i18next";
 
 import io from "io";
 import config from "config";
 
+@translate(["register"], { wait: true })
 export default class Register extends Component {
+	static propTypes = {
+		t: PropTypes.func,
+	};
+
+	static defaultProps = {
+		t: () => {},
+	};
+
 	constructor() {
 		super();
 
@@ -26,7 +37,7 @@ export default class Register extends Component {
 	register = () => {
 		this.messages.clearErrorSuccess();
 		if (CustomInput.hasInvalidInput(this.input)) {
-			this.messages.clearAddError("Some fields are incorrect. Please fix them before continuing.");
+			this.messages.clearAddError(this.props.t("general:someFieldsAreIncorrectError"));
 		} else {
 			io.getSocket(socket => {
 				socket.emit("users.register", this.input.username.getValue(), this.input.email.getValue(), this.input.password.getValue(), grecaptcha.getResponse(this.state.recaptcha), res => {
@@ -54,21 +65,19 @@ export default class Register extends Component {
 	}
 
 	render() {
+		const { t } = this.props;
+
 		return (
 			<div>
+				<h1>{ t("register:title") }</h1>
 				<CustomMessages onRef={ ref => (this.messages = ref) } />
-				<CustomInput type="email" name="email" label="Email" placeholder="Email" onRef={ ref => (this.input.email = ref) } />
-				<CustomInput type="username" name="username" label="Username" placeholder="Username" onRef={ ref => (this.input.username = ref) } />
-				<CustomInput type="password" name="password" label="Password" placeholder="Password" onRef={ ref => (this.input.password = ref) } />
+				<CustomInput type="email" name="email" label={ t("general:emailInput") } placeholder={ t("general:emailInput") } onRef={ ref => (this.input.email = ref) } />
+				<CustomInput type="username" name="username" label={ t("general:usernameInput") } placeholder={ t("general:usernameInput") } onRef={ ref => (this.input.username = ref) } />
+				<CustomInput type="password" name="password" label={ t("general:passwordInput") } placeholder={ t("general:passwordInput") } onRef={ ref => (this.input.password = ref) } />
 				<div id="recaptcha" />
-				<p>By logging in/registering you agree to our <a href="/terms">Terms of Service</a> and <a href="/privacy">Privacy Policy</a>.</p>
-				<button onClick={ this.register }>Register</button>
-				<a href={ `${ config.serverDomain }/auth/github/authorize` } onClick={ this.githubRedirect }>
-					<div className="icon">
-						<img alt="GitHub Icon" src="/assets/images/social/github.svg" />
-					</div>
-					&nbsp;&nbsp;Login with GitHub
-				</a>
+				<p>{ t("register:byLoggingIn", { termsOfService: <a href="/terms">{ t("general:termsOfService") }</a>, privacyPolicy: <a href="/privacy">{ t("general:privacyPolicy") }</a> }) }</p>
+				<button onClick={ this.register }>{ t("register:register") }</button>
+				<a href={ `${ config.serverDomain }/auth/github/authorize` } onClick={ this.githubRedirect }>{ t("register:registerWithGitHub") }</a>
 			</div>
 		);
 	}

+ 21 - 17
frontend/app/js/views/Auth/Settings/SetPassword/index.jsx

@@ -1,6 +1,7 @@
 import React, { Component } from "react";
 import PropTypes from "prop-types";
 import { connect } from "react-redux";
+import { translate } from "react-i18next";
 
 import CustomInput from "components/CustomInput.jsx";
 import CustomMessages from "components/CustomMessages.jsx";
@@ -13,15 +14,18 @@ import io from "io";
 	},
 }))
 
-export default class Settings extends Component {
+@translate(["setPassword"], { wait: true })
+export default class SetPassword extends Component {
 	static propTypes = {
 		user: PropTypes.object,
+		t: PropTypes.func,
 	};
 
 	static defaultProps = {
 		user: {
 			userId: "",
 		},
+		t: () => {},
 	};
 
 	constructor(props) {
@@ -41,12 +45,12 @@ export default class Settings extends Component {
 						passwordLinked: res.data.password,
 					});
 				} else {
-					this.messages.addError("You are currently not logged in.");
+					this.messages.addError(this.props.t("general:notLoggedInError"));
 				}
 			});
 
 			socket.on("event:user.linkPassword", () => {
-				this.messages.clearAddInfo("A password for your account has been set. Redirecting you to the settings page.");
+				this.messages.clearAddInfo(this.props.t("setPassword:passwordHasBeenSet"));
 				location.href = "/settings";
 			});
 		});
@@ -54,18 +58,18 @@ export default class Settings extends Component {
 
 	getActions = () => {
 		const requestCodeButton = (<button key="requestCode" onClick={ this.requestCode }>
-			Request code
+			{ this.props.t("setPassword:requestCode") }
 		</button>);
 
-		const codeInput = <CustomInput key="code" type="uniqueCode" name="code" label="Code" placeholder="Code" onRef={ ref => (this.input.code = ref) } />;
+		const codeInput = <CustomInput key="code" type="uniqueCode" name="code" label={ this.props.t("general:codeInput") } placeholder={ this.props.t("general:codeInput") } onRef={ ref => (this.input.code = ref) } />;
 		const verifyCodeButton = (<button key="verifyCode" onClick={ this.verifyCode }>
-			Verify code
+			{ this.props.t("verifyCode") }
 		</button>);
 
-		const newPasswordInput = <CustomInput key="newPassword" type="password" name="newPassword" label="New password" placeholder="New password" onRef={ ref => (this.input.newPassword = ref) } />;
-		const newPasswordAgainInput = <CustomInput key="newPasswordAgain" type="password" name="newPasswordAgain" label="New password again" placeholder="New password again" onRef={ ref => (this.input.newPasswordAgain = ref) } />;
+		const newPasswordInput = <CustomInput key="newPassword" type="password" name="newPassword" label={ this.props.t("general:newPasswordInput") } placeholder={ this.props.t("general:newPasswordInput") } onRef={ ref => (this.input.newPassword = ref) } />;
+		const newPasswordAgainInput = <CustomInput key="newPasswordAgain" type="password" name="newPasswordAgain" label={ this.props.t("general:newPasswordAgainInput") } placeholder={ this.props.t("general:newPasswordAgainInput") } onRef={ ref => (this.input.newPasswordAgain = ref) } />;
 		const setPassword = (<button key="setPassword" onClick={ this.setPassword }>
-			Change password
+			{ this.props.t("setPassword:setPassword") }
 		</button>);
 
 		if (this.state.step === 1) {
@@ -78,14 +82,14 @@ export default class Settings extends Component {
 	setPassword = () => {
 		this.messages.clearErrorSuccess();
 		if (CustomInput.hasInvalidInput(this.input, ["newPassword", "newPasswordAgain"])) {
-			this.messages.clearAddError("Some fields are incorrect. Please fix them before continuing.");
+			this.messages.clearAddError(this.props.t("general:someFieldsAreIncorrectError"));
 		} else if (CustomInput.isTheSame(this.input, ["newPassword", "newPasswordAgain"])) {
-			this.messages.clearAddError("New password and new password again need to be the same.");
+			this.messages.clearAddError(this.props.t("general:newPasswordNewPasswordAgainSameError"));
 		} else {
 			io.getSocket(socket => {
 				socket.emit("users.changePasswordWithCode", this.state.code, this.input.newPassword.getValue(), res => {
 					if (res.status === "success") {
-						this.messages.clearAddSuccess("Successfully set password. Redirecting you to the settings page.");
+						this.messages.clearAddSuccess(this.props.t("setPassword:successfullySetPassword"));
 						location.href = "/settings";
 					} else {
 						this.messages.addError(res.message);
@@ -100,8 +104,8 @@ export default class Settings extends Component {
 		io.getSocket(socket => {
 			socket.emit("users.requestPassword", res => {
 				if (res.status === "success") {
-					this.messages.clearAddSuccess("Successfully requested code.");
-					this.messages.clearAddInfo("We have sent a unique code to your email address.");
+					this.messages.clearAddSuccess(this.props.t("setPassword:successfullyRequestedCode"));
+					this.messages.clearAddInfo(this.props.t("setPassword:weHaveSentAUniqueCode"));
 					this.setState({
 						step: 2,
 					});
@@ -115,12 +119,12 @@ export default class Settings extends Component {
 	verifyCode = () => {
 		this.messages.clearErrorSuccess();
 		if (CustomInput.hasInvalidInput(this.input, ["code"])) {
-			this.messages.clearAddError("Some fields are incorrect. Please fix them before continuing.");
+			this.messages.clearAddError(this.props.t("general:someFieldsAreIncorrectError"));
 		} else {
 			io.getSocket(socket => {
 				socket.emit("users.verifyPasswordCode", this.input.code.getValue(), res => {
 					if (res.status === "success") {
-						this.messages.clearAddSuccess("Successfully verified code.");
+						this.messages.clearAddSuccess(this.props.t("setPassword:successfullyVerifiedCode"));
 						this.setState({
 							step: 3,
 							code: this.input.code.getValue(),
@@ -136,7 +140,7 @@ export default class Settings extends Component {
 	render() {
 		return (
 			<div>
-				<h1>Set Password</h1>
+				<h1><h1>{ t("setPassword:title") }</h1></h1>
 				<CustomMessages onRef={ ref => (this.messages = ref) } />
 				{ this.getActions() }
 			</div>

+ 36 - 25
frontend/app/js/views/Auth/Settings/index.jsx

@@ -3,6 +3,7 @@ import async from "async";
 import PropTypes from "prop-types";
 import { connect } from "react-redux";
 import { NavLink } from "react-router-dom";
+import { translate } from "react-i18next";
 
 import config from "config";
 
@@ -17,15 +18,18 @@ import io from "io";
 	},
 }))
 
+@translate(["settings"], { wait: true })
 export default class Settings extends Component {
 	static propTypes = {
 		user: PropTypes.object,
+		t: PropTypes.func,
 	};
 
 	static defaultProps = {
 		user: {
 			userId: "",
 		},
+		t: () => {},
 	};
 
 	constructor(props) {
@@ -48,7 +52,7 @@ export default class Settings extends Component {
 						gitHubLinked: res.data.github,
 					});
 				} else {
-					this.messages.addError("You are currently not logged in.");
+					this.messages.addError(this.props.t("general:notLoggedInError"));
 				}
 			});
 
@@ -101,9 +105,9 @@ export default class Settings extends Component {
 			},
 		], () => {
 			if (CustomInput.hasInvalidInput(this.input, ["username", "email"])) {
-				this.messages.clearAddError("Some fields are incorrect. Please fix them before continuing.");
+				this.messages.clearAddError(this.props.t("general:someFieldsAreIncorrectError"));
 			} else if (this.input.username.isOriginal() && this.input.email.isOriginal()) {
-				this.messages.clearAddError("Username or email hasn't changed.");
+				this.messages.clearAddError(this.props.t("settings:usernameOrEmailHasntChanged"));
 			} else {
 				const email = this.input.email.getValue();
 				const username = this.input.username.getValue();
@@ -111,7 +115,7 @@ export default class Settings extends Component {
 					if (!this.input.email.isOriginal()) {
 						socket.emit("users.updateEmail", this.props.user.userId, email, res => {
 							if (res.status === "success") {
-								this.messages.clearAddSuccess("Successfully updated email.");
+								this.messages.clearAddSuccess(this.props.t("settings:successfullyUpdatedEmail"));
 							} else {
 								this.messages.addError(res.message);
 							}
@@ -121,7 +125,7 @@ export default class Settings extends Component {
 					if (!this.input.username.isOriginal()) {
 						socket.emit("users.updateUsername", this.props.user.userId, username, res => {
 							if (res.status === "success") {
-								this.messages.clearAddSuccess("Successfully updated username.");
+								this.messages.clearAddSuccess(this.props.t("settings:successfullyUpdatedUsername"));
 							} else {
 								this.messages.addError(res.message);
 							}
@@ -135,7 +139,7 @@ export default class Settings extends Component {
 	changePassword = () => {
 		this.messages.clearErrorSuccess();
 		if (CustomInput.hasInvalidInput(this.input, ["newPassword"])) {
-			this.messages.clearAddError("Some fields are incorrect. Please fix them before continuing.");
+			this.messages.clearAddError(this.props.t("general:someFieldsAreIncorrectError"));
 		} else if (!this.state.passwordLinked) {
 			this.messages.clearAddError("You don't have a password set.");
 		} else {
@@ -156,7 +160,7 @@ export default class Settings extends Component {
 		io.getSocket(socket => {
 			socket.emit("users.removeSessions", this.props.user.userId, res => {
 				if (res.status === "success") {
-					this.messages.clearAddSuccess("Successfully logged out everywhere.");
+					this.messages.clearAddSuccess(this.props.t("settings:successfullyLoggedOutEverywhere"));
 				} else {
 					this.messages.addError(res.message);
 				}
@@ -169,7 +173,7 @@ export default class Settings extends Component {
 		io.getSocket(socket => {
 			socket.emit("users.unlinkGitHub", res => {
 				if (res.status === "success") {
-					this.messages.clearAddSuccess("Successfully unlinked GitHub.");
+					this.messages.clearAddSuccess(this.props.t("settings:successfullyUnlinkedGitHub"));
 				} else {
 					this.messages.addError(res.message);
 				}
@@ -182,7 +186,7 @@ export default class Settings extends Component {
 		io.getSocket(socket => {
 			socket.emit("users.unlinkPassword", res => {
 				if (res.status === "success") {
-					this.messages.clearAddSuccess("Successfully unlinked password.");
+					this.messages.clearAddSuccess(this.props.t("settings:successfullyUnlinkedPassword"));
 				} else {
 					this.messages.addError(res.message);
 				}
@@ -191,16 +195,20 @@ export default class Settings extends Component {
 	};
 
 	linkButtons = () => {
-		const newPassword = <CustomInput key="newPassword" type="password" name="newPassword" label="New password" placeholder="New password" onRef={ ref => (this.input.newPassword = ref) } />;
-		const changePasswordButton = <button key="changePassword" onClick={ this.changePassword }>Change password</button>;
-		const linkPassword = <NavLink key="linkPassword" to="/settings/setpassword" >Add a password to account</NavLink>;
-		const linkGitHub = <a key="linkGitHub" href={ config.serverDomain + "/auth/github/link" }>Link GitHub to account</a>;
-		const unlinkGitHub = (<button key="unlinkGitHub" onClick={ this.unlinkGitHub }>
-				Remove logging in with GitHub
-			</button>);
-		const unlinkPassword = (<button key="unlinkPassword" onClick={ this.unlinkPassword }>
-			Remove logging in with password
-		</button>);
+		const newPassword = <CustomInput key="newPassword" type="password" name="newPassword" label={ this.props.t("general:newPasswordInput") } placeholder={ this.props.t("general:newPasswordInput") } onRef={ ref => (this.input.newPassword = ref) } />;
+		const changePasswordButton = <button key="changePassword" onClick={ this.changePassword }>{ this.props.t("settings:changePassword") }</button>;
+		const linkPassword = <NavLink key="linkPassword" to="/settings/setpassword" >{ this.props.t("settings:addAPasswordToAccount") }</NavLink>;
+		const linkGitHub = <a key="linkGitHub" href={ config.serverDomain + "/auth/github/link" }>{ this.props.t("settings:linkGitHubToAccount") }</a>;
+		const unlinkGitHub = (
+			<button key="unlinkGitHub" onClick={ this.unlinkGitHub }>
+				{ this.props.t("settings:removeLoggingInWithGitHub") }
+			</button>
+		);
+		const unlinkPassword = (
+			<button key="unlinkPassword" onClick={ this.unlinkPassword }>
+				{ this.props.t("settings:removeLoggingInWithPassword") }
+			</button>
+		);
 
 		const toReturn = [];
 		if (this.state.passwordLinked) {
@@ -217,19 +225,22 @@ export default class Settings extends Component {
 	};
 
 	render() {
+		const { t } = this.props;
+
 		return (
 			<div>
+				<h1>{ t("settings:title") }</h1>
 				<CustomMessages onRef={ ref => (this.messages = ref) } />
 				<div>
-					<h2>General</h2>
-					<CustomInput type="email" name="email" label="Email" placeholder="Email" onRef={ ref => (this.input.email = ref) } />
-					<CustomInput type="username" name="username" label="Username" placeholder="Username" onRef={ ref => (this.input.username = ref) } />
-					<button onClick={ this.saveChanges }>Save changes</button>
+					<h2>{ this.props.t("settings:general") }</h2>
+					<CustomInput type="email" name="email" label={ this.props.t("general:emailInput") } placeholder={ this.props.t("general:emailInput") } onRef={ ref => (this.input.email = ref) } />
+					<CustomInput type="username" name="username" label={ this.props.t("general:usernameInput") } placeholder={ this.props.t("general:usernameInput") } onRef={ ref => (this.input.username = ref) } />
+					<button onClick={ this.saveChanges }>{ this.props.t("settings:saveChanges") }</button>
 				</div>
 				<div>
-					<h2>Security</h2>
+					<h2>{ this.props.t("settings:security") }</h2>
 					{ this.linkButtons() }
-					<button onClick={ this.logOutEverywhere }>Log out everywhere</button>
+					<button onClick={ this.logOutEverywhere }>{ this.props.t("settings:logOutEverywhere") }</button>
 				</div>
 			</div>
 		);

+ 0 - 4
frontend/app/js/views/Home/index.jsx

@@ -18,10 +18,6 @@ export default class Home extends Component {
 		return (
 			<div>
 				<h2>{ t("home:title") }</h2>
-				<h2>{ t("home:officialStations") }</h2>
-				<h2>{ t("home:communityStations") }</h2>
-				<h2>{ t("home:users", { context: "male", count: 5 }) }</h2>
-				<h2>{ t("home:users", { context: "female", count: 1 }) }</h2>
 			</div>
 		);
 	}