diff --git a/i18n/de.po b/i18n/de.po index b24d399..50071c0 100644 --- a/i18n/de.po +++ b/i18n/de.po @@ -12,6 +12,102 @@ msgstr "" "Plural-Forms: nplurals = 2; plural = (n != 1);\n" "X-Generator: Poedit 2.3\n" +#: src/components/CoordinatesBox.jsx:37 src/controls/keypress.js:59 +msgid "Copied!" +msgstr "Kopiert!" + +#: src/ui/placePixel.js:53 +msgid "Error :(" +msgstr "Fehler :(" + +#: src/ui/placePixel.js:54 +msgid "Didn't get an answer from pixelplanet. Maybe try to refresh?" +msgstr "" +"Keine Antwort von pixelplanet erhalten. Vielleicht versuche die Seite neu zu " +"laden?" + +#: src/ui/placePixel.js:56 src/ui/placePixel.js:265 +msgid "OK" +msgstr "OK" + +#: src/ui/placePixel.js:206 +msgid "Invalid Canvas" +msgstr "Ungültige Leinwand" + +#: src/ui/placePixel.js:207 +msgid "This canvas doesn't exist" +msgstr "Diese Leinwand existiert nicht" + +#: src/ui/placePixel.js:210 src/ui/placePixel.js:214 src/ui/placePixel.js:218 +msgid "Invalid Coordinates" +msgstr "Ungültige Koordinaten" + +#: src/ui/placePixel.js:211 +msgid "x out of bounds" +msgstr "x außerhalb des Spielfelds" + +#: src/ui/placePixel.js:215 +msgid "y out of bounds" +msgstr "y außerhalb des Spielfelds" + +#: src/ui/placePixel.js:219 +msgid "z out of bounds" +msgstr "z außerhalb des Spielfelds" + +#: src/ui/placePixel.js:222 +msgid "Wrong Color" +msgstr "Falsche Farbe" + +#: src/ui/placePixel.js:223 +msgid "Invalid color selected" +msgstr "Ungültige Farbe ausgewählt" + +#: src/ui/placePixel.js:226 +msgid "Just for registered Users" +msgstr "Nur ür registrierte Spieler" + +#: src/ui/placePixel.js:227 +msgid "You have to be logged in to place on this canvas" +msgstr "Melde dich an um auf dieser Leinwand zu spielen" + +#: src/ui/placePixel.js:230 +msgid "Place more :)" +msgstr "Spiel mehr :)" + +#: src/ui/placePixel.js:232 +msgid "You can not access this canvas yet. You need to place more pixels" +msgstr "Mehr Pixel sind benötigt um auf dieser Leinwand zu spielen" + +#: src/ui/placePixel.js:235 +msgid "Pixel protected!" +msgstr "Pixel beschützt!" + +#: src/ui/placePixel.js:251 +msgid "No Proxies Allowed :(" +msgstr "Kein Proxy erlaubt :(" + +#: src/ui/placePixel.js:252 +msgid "You are using a Proxy." +msgstr "Du benutzt ein Proxy." + +#: src/ui/placePixel.js:255 +msgid "Weird" +msgstr "Komisch" + +#: src/ui/placePixel.js:256 +msgid "Couldn't set Pixel" +msgstr "Konnte ein Pixel setzen" + +#: src/ui/placePixel.js:262 +#, javascript-format +msgid "Error ${ retCode }" +msgstr "Fehler ${ retCode }" + +#: src/components/Admintools.jsx:219 src/components/ChannelContextMenu.jsx:85 +#: src/components/ModalRoot.jsx:60 +msgid "Close" +msgstr "Schließen" + #: src/components/ExpandMenuButton.jsx:19 msgid "Close Menu" msgstr "Schließe Menü" @@ -28,6 +124,11 @@ msgstr "Schließe Chat" msgid "Open Chat" msgstr "Öffne Chat" +#: src/components/CanvasSelectModal.jsx:67 +#: src/components/CanvasSwitchButton.jsx:20 +msgid "Canvas Selection" +msgstr "Leinwand auswahl" + #: src/components/OnlineBox.jsx:22 msgid "User online" msgstr "Spieler anwesend" @@ -36,11 +137,7 @@ msgstr "Spieler anwesend" msgid "Pixel gesetzt" msgstr "Pixel plaziert" -#: src/components/CanvasSwitchButton.jsx:20 -msgid "Canvas Selection" -msgstr "Leinwand auswahl" - -#: src/components/CoordinatesBox.jsx:26 +#: src/components/Converter.jsx:609 src/components/CoordinatesBox.jsx:26 msgid "Copy to Clipboard" msgstr "Kopiere in die Zwischenablage" @@ -70,27 +167,104 @@ msgstr "maximieren" #: src/components/Chat.jsx:168 msgid "Start chatting here" -msgstr "Beginne hier zu chatten" +msgstr "Beginne hier zu unterhalten" #: src/components/Chat.jsx:200 msgid "Chat here" msgstr "Chatte hier" -#: src/components/Chat.jsx:219 +#: src/components/Chat.jsx:220 msgid "You must be logged in to chat" -msgstr "Melde dich an um zu chatten" +msgstr "Melde dich an um dich zu unterhalten" #: src/components/GlobeButton.jsx:31 msgid "Globe View" msgstr "Globus Ansicht" -#: src/components/PalselButton.jsx:25 -msgid "Close Palette" -msgstr "Schließe Palette" +#: src/components/SettingsModal.jsx:123 +msgid "Show Grid" +msgstr "Zeige Raster" -#: src/components/PalselButton.jsx:25 -msgid "Open Palette" -msgstr "Öffne Palette" +#: src/components/SettingsModal.jsx:124 +msgid "Turn on grid to highlight pixel borders." +msgstr "Aktiviere das Raster um Pixelgrenzen zu sehen." + +#: src/components/SettingsModal.jsx:130 +msgid "Show Pixel Activity" +msgstr "Zeige Pixelaktivität" + +#: src/components/SettingsModal.jsx:131 +msgid "Show circles where pixels are placed." +msgstr "Zeige Kreise wo Pixel von Spielern gesetzt werden." + +#: src/components/SettingsModal.jsx:137 +msgid "Disable Game Sounds" +msgstr "Deaktiviere Spiel Ton" + +#: src/components/SettingsModal.jsx:139 +msgid "All sound effects will be disabled." +msgstr "alle Toneffekte werden ausgeschaltet" + +#: src/components/SettingsModal.jsx:145 +msgid "Enable chat notifications" +msgstr "Aktiviere Chat Benachrichtigungen" + +#: src/components/SettingsModal.jsx:146 +msgid "Play a sound when new chat messages arrive" +msgstr "Spiele ein Geräusch wenn eine neue Chat Nachricht eintrifft" + +#: src/components/SettingsModal.jsx:151 +msgid "Auto Zoom In" +msgstr "Automaticher Zoom" + +#: src/components/SettingsModal.jsx:153 +msgid "" +"Zoom in instead of placing a pixel when you tap the canvas and your zoom is " +"small." +msgstr "" +"Zoome rein anstatt ein Pixel zu setzen wenn auf kleineren Zoomlevel geklickt " +"wird." + +#: src/components/SettingsModal.jsx:158 +msgid "Compact Palette" +msgstr "Kompakte Palette" + +#: src/components/SettingsModal.jsx:160 +msgid "Display Palette in a compact form that takes less screen space." +msgstr "" +"Zeige die Palette in einer kleineren Form an, welche weniger Platz benötigt" + +#: src/components/SettingsModal.jsx:165 +msgid "Potato Mode" +msgstr "Erdapfel Modus" + +#: src/components/SettingsModal.jsx:166 +msgid "For when you are playing on a potato." +msgstr "Wenn du auf einer Kartoffel spielst." + +#: src/components/Converter.jsx:423 src/components/SettingsModal.jsx:171 +msgid "Light Grid" +msgstr "Helles Raster" + +#: src/components/SettingsModal.jsx:172 +msgid "Show Grid in white instead of black." +msgstr "Zeige das Raster in weiß anstatt schwarz" + +#: src/components/SettingsModal.jsx:179 +msgid "Historical View" +msgstr "Historische Ansicht" + +#: src/components/SettingsModal.jsx:180 +msgid "Check out past versions of the canvas." +msgstr "Siehe vergangene Versionen der Leinwand" + +#: src/components/SettingsModal.jsx:188 +msgid "Themes" +msgstr "Themen" + +#: src/components/SettingsModal.jsx:189 +msgid "How pixelplanet should look like." +msgstr "Wähle aus wie pixelplanet aussehen soll" #: src/components/HelpModal.jsx:34 src/components/HelpModal.jsx:35 msgid "Privacy Policy" @@ -321,9 +495,46 @@ msgstr "" msgid "Welcome to PixelPlanet.fun" msgstr "Willkommen auf PixelPlanet.fun" +#: src/components/ChannelContextMenu.jsx:73 +msgid "Mute" +msgstr "" + +#: src/components/UserContextMenu.jsx:72 +msgid "Ping" +msgstr "" + +#: src/components/UserContextMenu.jsx:97 +msgid "DM" +msgstr "" + +#: src/components/UserContextMenu.jsx:107 +msgid "Block" +msgstr "" + +#: src/components/PalselButton.jsx:25 +msgid "Close Palette" +msgstr "Schließe Palette" + +#: src/components/PalselButton.jsx:25 +msgid "Open Palette" +msgstr "Öffne Palette" + +#: src/components/RegisterModal.jsx:18 +msgid "Register new account here" +msgstr "Registriere ein neues Konto hier" + +#: src/components/ForgotPasswordModal.jsx:20 +#: src/components/RegisterModal.jsx:21 src/components/UserAreaModal.jsx:130 +msgid "Consider joining us on Guilded:" +msgstr "Triff uns und andere Spieler auf guilded:" + +#: src/components/RegisterModal.jsx:38 +msgid "Register New Account" +msgstr "Registriere neues Konto" + #: src/components/UserAreaModal.jsx:33 msgid "Login to access more features and stats." -msgstr "Melde dich and um mehr Funktionen und Statistikan zu sehen" +msgstr "Melde dich and um mehr Funktionen und Statistikan zu sehen." #: src/components/UserAreaModal.jsx:35 msgid "Login with Mail:" @@ -333,6 +544,10 @@ msgstr "Mit Mail anmelden:" msgid "I forgot my Password." msgstr "Ich habe mein Passwort vergessen" +#: src/components/UserAreaModal.jsx:43 +msgid "or login with:" +msgstr "oder melde dich an mit:" + #: src/components/UserAreaModal.jsx:84 msgid "or register here:" msgstr "oder registriere dich hier:" @@ -341,107 +556,41 @@ msgstr "oder registriere dich hier:" msgid "Register" msgstr "Registrieren" +#: src/components/UserAreaModal.jsx:107 +msgid "Profile" +msgstr "Profil" + +#: src/components/UserAreaModal.jsx:113 +msgid "Ranking" +msgstr "Rangliste" + +#: src/components/UserAreaModal.jsx:116 +msgid "Converter" +msgstr "Konverter" + +#: src/components/UserAreaModal.jsx:122 +msgid "Admintools" +msgstr "Admin Werkzeuge" + +#: src/components/UserAreaModal.jsx:122 +msgid "Modtools" +msgstr "Mod Werkzeuge" + #: src/components/UserAreaModal.jsx:123 msgid "Loading..." msgstr "Lade..." -#: src/components/ForgotPasswordModal.jsx:20 -#: src/components/RegisterModal.jsx:21 src/components/UserAreaModal.jsx:130 -msgid "Consider joining us on Guilded:" -msgstr "Triff uns und andere Spieler auf guilded:" +#: src/components/ForgotPasswordModal.jsx:16 +msgid "Enter your mail adress and we will send you a new password:" +msgstr "Gib deine Mail Adresse an und wir senden dir ein neues Passwort." -#: src/components/RegisterModal.jsx:18 -msgid "Register new account here" -msgstr "Registriere ein neues Konto hier" +#: src/components/ForgotPasswordModal.jsx:37 +msgid "Restore my Password" +msgstr "Passwort wiederherstellen" -#: src/components/RegisterModal.jsx:38 -msgid "Register New Account" -msgstr "Registriere neues Konto" - -#: src/components/SettingsModal.jsx:123 -msgid "Show Grid" -msgstr "Zeige Raster" - -#: src/components/SettingsModal.jsx:124 -msgid "Turn on grid to highlight pixel borders." -msgstr "Aktiviere das Raster um Pixelgrenzen zu sehen." - -#: src/components/SettingsModal.jsx:130 -msgid "Show Pixel Activity" -msgstr "Zeige Pixelaktivität" - -#: src/components/SettingsModal.jsx:131 -msgid "Show circles where pixels are placed." -msgstr "Zeige Kreise wo Pixel von Spielern gesetzt werden" - -#: src/components/SettingsModal.jsx:137 -msgid "Disable Game Sounds" -msgstr "Deaktiviere Spiel Ton" - -#: src/components/SettingsModal.jsx:139 -msgid "All sound effects will be disabled." -msgstr "alle Toneffekte werden ausgeschaltet" - -#: src/components/SettingsModal.jsx:145 -msgid "Enable chat notifications" -msgstr "Aktiviere Chat Benachrichtigungen" - -#: src/components/SettingsModal.jsx:146 -msgid "Play a sound when new chat messages arrive" -msgstr "Spiele ein Geräusch wenn eine neue Chat Nachricht eintrifft" - -#: src/components/SettingsModal.jsx:151 -msgid "Auto Zoom In" -msgstr "Automaticher Zoom" - -#: src/components/SettingsModal.jsx:153 -msgid "" -"Zoom in instead of placing a pixel when you tap the canvas and your zoom is " -"small." -msgstr "" -"Zoome rein anstatt ein Pixel zu setzen wenn auf kleineren Zoomlevel geklickt " -"wird." - -#: src/components/SettingsModal.jsx:158 -msgid "Compact Palette" -msgstr "Kompakte Palette" - -#: src/components/SettingsModal.jsx:160 -msgid "Display Palette in a compact form that takes less screen space." -msgstr "" -"Zeige die Palette in einer kleineren Form an, welche weniger Platz benötigt" - -#: src/components/SettingsModal.jsx:165 -msgid "Potato Mode" -msgstr "Erdapfel Modus" - -#: src/components/SettingsModal.jsx:166 -msgid "For when you are playing on a potato." -msgstr "Wenn du auf einer Kartoffel spielst." - -#: src/components/SettingsModal.jsx:171 -msgid "Light Grid" -msgstr "Helles Raster" - -#: src/components/SettingsModal.jsx:172 -msgid "Show Grid in white instead of black." -msgstr "Zeige das Raster in weiß anstatt schwarz" - -#: src/components/SettingsModal.jsx:179 -msgid "Historical View" -msgstr "Historische Ansicht" - -#: src/components/SettingsModal.jsx:180 -msgid "Check out past versions of the canvas." -msgstr "Siehe vergangene Versionen der Leinwand" - -#: src/components/SettingsModal.jsx:188 -msgid "Themes" -msgstr "Themen" - -#: src/components/SettingsModal.jsx:189 -msgid "How pixelplanet should look like." -msgstr "Wähle aus wie pixelplanet aussehen soll" +#: src/components/ChatModal.jsx:35 +msgid "Chat" +msgstr "Unterhaltung" #: src/components/ArchiveModal.jsx:20 msgid "" @@ -485,23 +634,23 @@ msgstr "" msgid "Canvas Archive" msgstr "Leinwand Archiv" -#: src/components/ForgotPasswordModal.jsx:16 -msgid "Enter your mail adress and we will send you a new password:" -msgstr "Gib deine Mail Adresse an und wir senden dir ein neues Passwort." +#: src/components/CanvasSelectModal.jsx:29 +msgid "" +"Select the canvas you want to use. Every canvas is unique and has different " +"palettes, cooldown and requirements. Archive of closed canvases can be " +"accessed here:" +msgstr "" -#: src/components/ForgotPasswordModal.jsx:37 -msgid "Restore my Password" -msgstr "Passwort wiederherstellen" - -#: src/components/ChatModal.jsx:35 -msgid "Chat" -msgstr "Unterhaltung" +#: src/components/CanvasSelectModal.jsx:37 +msgid "Archive" +msgstr "Archiv" #: src/components/LogInForm.jsx:104 msgid "Name or Email" msgstr "Name oder Email" -#: src/components/LogInForm.jsx:111 +#: src/components/ChangeMail.jsx:109 src/components/DeleteAccount.jsx:88 +#: src/components/LogInForm.jsx:111 src/components/SignUpForm.jsx:139 msgid "Password" msgstr "Passwort" @@ -509,12 +658,363 @@ msgstr "Passwort" msgid "LogIn" msgstr "Einloggen" +#: src/components/UserArea.jsx:57 +msgid "Todays Placed Pixels" +msgstr "Heutige Pixel" + +#: src/components/UserArea.jsx:61 +msgid "Daily Rank" +msgstr "Tägliche Rangliste" + +#: src/components/UserArea.jsx:66 +msgid "Placed Pixels" +msgstr "Plazierte Pixel" + +#: src/components/UserArea.jsx:70 +msgid "Total Rank" +msgstr "Gesamt Rang" + +#: src/components/UserArea.jsx:75 +#, javascript-format +msgid "Your name is: ${ name }" +msgstr "Dein Name ist: ${ name }" + +#: src/components/UserArea.jsx:81 +msgid "Log out" +msgstr "Abmelden" + +#: src/components/UserArea.jsx:93 +msgid "Change Username" +msgstr "Ändere Namen" + +#: src/components/UserArea.jsx:108 +msgid "Change Mail" +msgstr "Ändere Mail" + +#: src/components/UserArea.jsx:122 +msgid "Change Password" +msgstr "Passwort ändern" + +#: src/components/UserArea.jsx:134 +msgid "Delete Account" +msgstr "Lösche Konto" + +#: src/components/UserArea.jsx:147 +msgid "Social Settings" +msgstr "Soziale Einstellungen" + +#: src/components/Rankings.jsx:37 +msgid "Total" +msgstr "Gesamt" + +#: src/components/Rankings.jsx:45 +msgid "Daily" +msgstr "Täglich" + #: src/components/Rankings.jsx:49 msgid "Ranking updates every 5 min. Daily rankings get reset at midnight UTC." msgstr "" "Die Rangliste wird alle 5min aktualisiert. Die tägliche Liste wird um " "Mitternacht UTC zurückgestellt." +#: src/components/CanvasItem.jsx:46 +msgid "Cooldown" +msgstr "Wartezeit" + +#: src/components/CanvasItem.jsx:52 +msgid "Stacking till" +msgstr "Gesamtzeit" + +#: src/components/CanvasItem.jsx:54 +msgid "Ranked" +msgstr "" + +#: src/components/CanvasItem.jsx:56 +msgid "Requirements" +msgstr "Vorraussetzungen" + +#: src/components/CanvasItem.jsx:58 +msgid "User Account" +msgstr "Konto" + +#: src/components/CanvasItem.jsx:60 +#, javascript-format +msgid "and ${ canvas.req } Pixels set" +msgstr "und ${ canvas.req } gesetzte Pixel" + +#: src/components/CanvasItem.jsx:64 +msgid "Dimensions" +msgstr "Dimensionen" + +#: src/components/Admintools.jsx:179 +msgid "Build image on canvas." +msgstr "" + +#: src/components/Admintools.jsx:182 +msgid "Build image and set it to protected." +msgstr "" + +#: src/components/Admintools.jsx:185 +msgid "Build image, but reset cooldown to unset-pixel cd." +msgstr "" + +#: src/components/Admintools.jsx:248 +msgid "Image Upload" +msgstr "" + +#: src/components/Admintools.jsx:249 +msgid "Upload images to canvas" +msgstr "Lade ein Bild zur Leinwand hoch" + +#: src/components/Admintools.jsx:251 +msgid "File" +msgstr "" + +#: src/components/Admintools.jsx:271 +msgid "Coordinates in X_Y format:" +msgstr "" + +#: src/components/Admintools.jsx:306 src/components/Admintools.jsx:387 +#: src/components/Admintools.jsx:461 src/components/Admintools.jsx:505 +#: src/components/Admintools.jsx:589 src/components/SignUpForm.jsx:151 +msgid "Submit" +msgstr "" + +#: src/components/Admintools.jsx:311 +msgid "Pixel Protection" +msgstr "Pixel beschützen" + +#: src/components/Admintools.jsx:313 +msgid "" +"Set protection of areas (if you need finer grained control, " +"use protect with image upload and alpha layers)" +msgstr "" + +#: src/components/Admintools.jsx:392 +msgid "Rollback to Date" +msgstr "" + +#: src/components/Admintools.jsx:394 +msgid "Rollback an area of the canvas to a set date (00:00 UTC)" +msgstr "" + +#: src/components/Admintools.jsx:468 +msgid "IP Actions" +msgstr "" + +#: src/components/Admintools.jsx:470 +msgid "Do stuff with IPs (one IP per line)" +msgstr "" + +#: src/components/Admintools.jsx:510 +msgid "Manage Moderators" +msgstr "" + +#: src/components/Admintools.jsx:512 +msgid "Remove Moderator" +msgstr "" + +#: src/components/Admintools.jsx:544 +msgid "There are no mods" +msgstr "" + +#: src/components/Admintools.jsx:549 +msgid "Assign new Mod" +msgstr "" + +#: src/components/Admintools.jsx:552 +msgid "Enter UserName of new Mod" +msgstr "" + +#: src/components/SignUpForm.jsx:125 +msgid "Name" +msgstr "" + +#: src/components/SignUpForm.jsx:132 +msgid "Email" +msgstr "" + +#: src/components/SignUpForm.jsx:148 +msgid "Confirm Password" +msgstr "Passwort bestätigen" + +#: src/components/ChangeMail.jsx:122 src/components/ChangePassword.jsx:151 +#: src/components/DeleteAccount.jsx:94 src/components/SignUpForm.jsx:157 +msgid "Cancel" +msgstr "Abbrechen" + +#: src/components/Converter.jsx:274 +msgid "Choose Canvas" +msgstr "Wähle Leinwand" + +#: src/components/Converter.jsx:300 +msgid "Palette Download" +msgstr "Palette herunterladen" + +#: src/components/Converter.jsx:302 +#, javascript-format +msgid "Palette for ${ gimpLink }" +msgstr "Palette für ${ gimpLink }" + +#: src/components/Converter.jsx:320 +#, javascript-format +msgid "Credit for the Palette of the Moon goes to ${ starhouseLink }." +msgstr "Vielen Dank an ${ starhouseLink } für die Palette der Mond Leinwand." + +#: src/components/Converter.jsx:323 +msgid "Image Converter" +msgstr "Bild Konverter" + +#: src/components/Converter.jsx:324 +msgid "Convert an image to canvas colors" +msgstr "Konvertiere ein Bild zu Leinwand Farben" + +#: src/components/Converter.jsx:335 +msgid "Choose Strategy" +msgstr "Wähle Strategie" + +#: src/components/Converter.jsx:362 +msgid "Choose Color Mode" +msgstr "Wähle Farb Modus" + +#: src/components/Converter.jsx:400 +msgid "Add Grid (uncheck if you need a 1:1 template)" +msgstr "Zeichne Raster (deaktiviere falls du eine 1:1 Vorlage benötigst)" + +#: src/components/Converter.jsx:425 src/components/Converter.jsx:441 +msgid "Offset" +msgstr "Abweichung" + +#: src/components/Converter.jsx:471 +msgid "Scale Image" +msgstr "Skaliere Bild" + +#: src/components/Converter.jsx:483 +msgid "Width" +msgstr "Breite" + +#: src/components/Converter.jsx:513 +msgid "Height" +msgstr "Höhe" + +#: src/components/Converter.jsx:551 +msgid "Keep Ratio" +msgstr "Seitenverhältniss beibehalten" + +#: src/components/Converter.jsx:564 +msgid "Anti Aliasing" +msgstr "Kantenglättung" + +#: src/components/Converter.jsx:578 +msgid "Reset" +msgstr "Zurücksetzen" + +#: src/components/Converter.jsx:597 +msgid "Download Template" +msgstr "Bild herunterladen" + +#: src/utils/validation.js:15 +msgid "Email can't be empty." +msgstr "" + +#: src/utils/validation.js:16 +msgid "Email should be at least 5 characters long." +msgstr "" + +#: src/utils/validation.js:17 +msgid "Email can't be longer than 40 characters." +msgstr "" + +#: src/utils/validation.js:18 +msgid "Email should at least contain a dot" +msgstr "" + +#: src/utils/validation.js:20 +msgid "Email should contain a @" +msgstr "" + +#: src/utils/validation.js:27 +msgid "Name can't be empty." +msgstr "" + +#: src/utils/validation.js:28 +msgid "Name must be at least 4 characters long" +msgstr "" + +#: src/utils/validation.js:29 +msgid "Name must be shorter than 26 characters" +msgstr "" + +#: src/utils/validation.js:36 +msgid "Name contains invalid character like @, /, \\ or #" +msgstr "" + +#: src/utils/validation.js:51 +msgid "Password must be at least 6 characters long." +msgstr "Passwort muss mindestens 6 Zeichen lang sein" + +#: src/utils/validation.js:54 +msgid "Password must be shorter than 60 characters." +msgstr "" + +#: src/utils/validation.js:68 +msgid "Could not connect to server, please try again later :(" +msgstr "" + +#: src/utils/validation.js:74 +msgid "I think we experienced some error :(" +msgstr "" + +#: src/components/DeleteAccount.jsx:92 +msgid "Yes, Delete My Account!" +msgstr "Ja, löche mein Konto!" + +#: src/components/ChangeMail.jsx:89 +msgid "" +"Changed Mail successfully. We sent you a verification mail, " +"please verify your new mail adress." +msgstr "" + +#: src/components/ChangeMail.jsx:116 +msgid "New Mail" +msgstr "Neue Mail" + +#: src/components/ChangeMail.jsx:120 src/components/ChangePassword.jsx:149 +msgid "Save" +msgstr "" + +#: src/components/ChangePassword.jsx:18 +msgid "Passwords do not match." +msgstr "" + +#: src/components/ChangePassword.jsx:103 +msgid "Changed Password successfully." +msgstr "Passwort erfolgreich geändert" + +#: src/components/ChangePassword.jsx:128 +msgid "Old Password" +msgstr "Altes Passwort" + +#: src/components/ChangePassword.jsx:136 +msgid "New Password" +msgstr "Neues Passwort" + +#: src/components/ChangePassword.jsx:145 +msgid "Confirm New Password" +msgstr "Neues Passwort bestätigen" + +#: src/components/SocialSettings.jsx:39 +msgid "Block all Private Messages" +msgstr "" + +#: src/components/SocialSettings.jsx:57 +msgid "Unblock Users" +msgstr "" + +#: src/components/SocialSettings.jsx:81 +msgid "You have no users blocked" +msgstr "" + #: src/components/HelpModal.jsx:15 src/components/SettingsModal.jsx:125 msgctxt "keybinds" msgid "G" @@ -525,6 +1025,11 @@ msgctxt "keybinds" msgid "X" msgstr "" +#: src/components/SettingsModal.jsx:140 +msgctxt "keybinds" +msgid "M" +msgstr "" + #: src/components/HelpModal.jsx:17 src/components/SettingsModal.jsx:182 msgctxt "keybinds" msgid "H" @@ -574,8 +1079,3 @@ msgstr "" msgctxt "keybinds" msgid "C" msgstr "" - -#: src/components/SettingsModal.jsx:140 -msgctxt "keybinds" -msgid "M" -msgstr "" diff --git a/i18n/ssr-de.po b/i18n/ssr-de.po index c8e92a6..13e8d2f 100644 --- a/i18n/ssr-de.po +++ b/i18n/ssr-de.po @@ -1,15 +1,237 @@ msgid "" msgstr "" -"Content-Type: text/plain; charset=utf-8\n" -"Plural-Forms: nplurals = 2; plural = (n != 1);\n" +"Project-Id-Version: \n" +"POT-Creation-Date: \n" +"PO-Revision-Date: \n" +"Last-Translator: \n" +"Language-Team: \n" "Language: de\n" -"mime-version: 1.0\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals = 2; plural = (n != 1);\n" +"X-Generator: Poedit 2.3\n" -#: src/ssr-components/Globe.jsx:23 +#: src/ssr-components/Globe.jsx:44 msgid "Double click on globe to go back." msgstr "Doppelklick um zurück zu gehen" -#: src/ssr-components/Globe.jsx:24 +#: src/ssr-components/Globe.jsx:45 msgid "Loading..." msgstr "Lade..." + +#: src/ssr-components/Globe.jsx:51 +msgid "PixelPlanet.Fun 3DGlobe" +msgstr "PixelPlanet.Fun 3D Globus" + +#: src/ssr-components/Globe.jsx:52 +msgid "A 3D globe of our whole map" +msgstr "Ein interaktvier 3D Globus unserer gesamten Karte" + +#: src/routes/reset_password.js:63 +msgid "You sent an empty password or invalid data :(" +msgstr "" + +#: src/routes/reset_password.js:74 +msgid "This password-reset link isn't valid anymore :(" +msgstr "" + +#: src/routes/reset_password.js:84 +msgid "Your passwords do not match :(" +msgstr "" + +#: src/routes/reset_password.js:98 +msgid "User doesn't exist in our database :(" +msgstr "" + +#: src/routes/reset_password.js:109 +msgid "Passowrd successfully changed." +msgstr "" + +#: src/routes/reset_password.js:126 +msgid "Invalid url :( Please check your mail again." +msgstr "" + +#: src/routes/reset_password.js:138 +msgid "" +"This passwort reset link is wrong or already expired, please request a new " +"one (Note: you can use those links just once)" +msgstr "" + +#: src/core/mail.js:65 +#, javascript-format +msgid "" +"We already sent you a verification mail, you can request another one in " +"${ minLeft } minutes." +msgstr "" + +#: src/core/mail.js:75 +msgid "Welcome ${ name } to PixelPlanet, plese verify your mail" +msgstr "" + +#: src/core/mail.js:77 +#, javascript-format +msgid "Hello ${ name }" +msgstr "" + +#: src/core/mail.js:78 +msgid "" +"welcome to our little community of pixelplacers, to use your account, you " +"have to verify your mail. You can do that here: " +msgstr "" + +#: src/core/mail.js:78 +msgid "Click to Verify" +msgstr "" + +#: src/core/mail.js:78 src/core/mail.js:128 +msgid "Or by copying following url:" +msgstr "" + +#: src/core/mail.js:79 +msgid "" +"Have fun and don't hesitate to contact us if you encouter any problems :)" +msgstr "" + +#: src/core/mail.js:80 src/core/mail.js:130 +msgid "Thanks" +msgstr "" + +#: src/core/mail.js:98 +msgid "" +"We already sent you a mail with instructions. Please wait before requesting " +"another mail." +msgstr "" + +#: src/core/mail.js:106 +msgid "Couldn't find this mail in our database" +msgstr "" + +#: src/core/mail.js:125 +msgid "You forgot your password for PixelPlanet? Get a new one here" +msgstr "" + +#: src/core/mail.js:127 +msgid "Hello" +msgstr "" + +#: src/core/mail.js:128 +msgid "" +"You requested to get a new password. You can change your password within the " +"next 30min here: " +msgstr "" + +#: src/core/mail.js:128 +msgid "Reset Password" +msgstr "" + +#: src/core/mail.js:129 +#, javascript-format +msgid "" +"If you did not request this mail, please just ignore it (the ip that " +"requested this mail was ${ ip })." +msgstr "" + +#: src/utils/validation.js:15 +msgid "Email can't be empty." +msgstr "" + +#: src/utils/validation.js:16 +msgid "Email should be at least 5 characters long." +msgstr "" + +#: src/utils/validation.js:17 +msgid "Email can't be longer than 40 characters." +msgstr "" + +#: src/utils/validation.js:18 +msgid "Email should at least contain a dot" +msgstr "" + +#: src/utils/validation.js:20 +msgid "Email should contain a @" +msgstr "" + +#: src/utils/validation.js:27 +msgid "Name can't be empty." +msgstr "" + +#: src/utils/validation.js:28 +msgid "Name must be at least 4 characters long" +msgstr "" + +#: src/utils/validation.js:29 +msgid "Name must be shorter than 26 characters" +msgstr "" + +#: src/utils/validation.js:36 +msgid "Name contains invalid character like @, /, \\ or #" +msgstr "" + +#: src/utils/validation.js:51 +msgid "Password must be at least 6 characters long." +msgstr "Passwort muss mindestens 6 Zeichen lang sein." + +#: src/utils/validation.js:54 +msgid "Password must be shorter than 60 characters." +msgstr "" + +#: src/utils/validation.js:68 +msgid "Could not connect to server, please try again later :(" +msgstr "" + +#: src/utils/validation.js:74 +msgid "I think we experienced some error :(" +msgstr "" + +#: src/routes/api/auth/change_mail.js:41 +#: src/routes/api/auth/change_passwd.js:37 +#: src/routes/api/auth/delete_account.js:38 +msgid "You are not authenticated." +msgstr "" + +#: src/routes/api/auth/change_mail.js:50 +#: src/routes/api/auth/change_passwd.js:46 +#: src/routes/api/auth/delete_account.js:48 +msgid "Incorrect password!" +msgstr "" + +#: src/routes/api/auth/register.js:61 +msgid "Failed to create new user :(" +msgstr "" + +#: src/routes/api/auth/register.js:77 +msgid "Failed to establish session after register :(" +msgstr "" + +#: src/canvasesDesc.js:19 +msgid "Our main canvas, a huge map of the world. Place everywhere you like" +msgstr "" +"Unsere Hauptleinwand, eine große Weltkarte. Zeichnen ist überall möglich." + +#: src/canvasesDesc.js:20 +msgid "" +"Moon canvas. Safe space for art. No flags or large text (unless part of art)" +msgstr "" +"Mond Leinwand. Kunst erwünscht. Keine Flaggen oder großer Text außer als " +"Teil von Kunst." + +#: src/canvasesDesc.js:21 +msgid "Place Voxels on a 3D canvas with others" +msgstr "Zeichne mit Voxeln in einer 3D Umgebung." + +#: src/canvasesDesc.js:22 +msgid "Special canvas to spread awareness of SARS-CoV2" +msgstr "Kleine Leinwand im SARS-CoV2 Thema" + +#: src/canvasesDesc.js:23 +msgid "Mirror of PixelZone" +msgstr "Kopie von PixelZone" + +#: src/canvasesDesc.js:24 +msgid "Mirror of PixelCanvas" +msgstr "Kopie von PixelCanvas" + +#: src/canvasesDesc.js:25 +msgid "Black and White canvas" +msgstr "Schwarz/Weiß Leinwand" diff --git a/i18n/template-ssr.pot b/i18n/template-ssr.pot index 9f35b76..e250753 100644 --- a/i18n/template-ssr.pot +++ b/i18n/template-ssr.pot @@ -3,10 +3,223 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Plural-Forms: nplurals=2; plural=(n!=1);\n" -#: src/ssr-components/Globe.jsx:46 +#: src/ssr-components/Globe.jsx:44 msgid "Double click on globe to go back." msgstr "" -#: src/ssr-components/Globe.jsx:47 +#: src/ssr-components/Globe.jsx:45 msgid "Loading..." +msgstr "" + +#: src/ssr-components/Globe.jsx:51 +msgid "PixelPlanet.Fun 3DGlobe" +msgstr "" + +#: src/ssr-components/Globe.jsx:52 +msgid "A 3D globe of our whole map" +msgstr "" + +#: src/routes/reset_password.js:63 +msgid "You sent an empty password or invalid data :(" +msgstr "" + +#: src/routes/reset_password.js:74 +msgid "This password-reset link isn't valid anymore :(" +msgstr "" + +#: src/routes/reset_password.js:84 +msgid "Your passwords do not match :(" +msgstr "" + +#: src/routes/reset_password.js:98 +msgid "User doesn't exist in our database :(" +msgstr "" + +#: src/routes/reset_password.js:109 +msgid "Passowrd successfully changed." +msgstr "" + +#: src/routes/reset_password.js:126 +msgid "Invalid url :( Please check your mail again." +msgstr "" + +#: src/routes/reset_password.js:138 +msgid "" +"This passwort reset link is wrong or already expired, please request a new " +"one (Note: you can use those links just once)" +msgstr "" + +#: src/core/mail.js:65 +#, javascript-format +msgid "" +"We already sent you a verification mail, you can request another one in ${ " +"minLeft } minutes." +msgstr "" + +#: src/core/mail.js:75 +msgid "Welcome ${ name } to PixelPlanet, plese verify your mail" +msgstr "" + +#: src/core/mail.js:77 +#, javascript-format +msgid "Hello ${ name }" +msgstr "" + +#: src/core/mail.js:78 +msgid "" +"welcome to our little community of pixelplacers, to use your account, you " +"have to verify your mail. You can do that here: " +msgstr "" + +#: src/core/mail.js:78 +msgid "Click to Verify" +msgstr "" + +#: src/core/mail.js:78 +#: src/core/mail.js:128 +msgid "Or by copying following url:" +msgstr "" + +#: src/core/mail.js:79 +msgid "Have fun and don't hesitate to contact us if you encouter any problems :)" +msgstr "" + +#: src/core/mail.js:80 +#: src/core/mail.js:130 +msgid "Thanks" +msgstr "" + +#: src/core/mail.js:98 +msgid "" +"We already sent you a mail with instructions. Please wait before requesting " +"another mail." +msgstr "" + +#: src/core/mail.js:106 +msgid "Couldn't find this mail in our database" +msgstr "" + +#: src/core/mail.js:125 +msgid "You forgot your password for PixelPlanet? Get a new one here" +msgstr "" + +#: src/core/mail.js:127 +msgid "Hello" +msgstr "" + +#: src/core/mail.js:128 +msgid "" +"You requested to get a new password. You can change your password within " +"the next 30min here: " +msgstr "" + +#: src/core/mail.js:128 +msgid "Reset Password" +msgstr "" + +#: src/core/mail.js:129 +#, javascript-format +msgid "" +"If you did not request this mail, please just ignore it (the ip that " +"requested this mail was ${ ip })." +msgstr "" + +#: src/utils/validation.js:15 +msgid "Email can't be empty." +msgstr "" + +#: src/utils/validation.js:16 +msgid "Email should be at least 5 characters long." +msgstr "" + +#: src/utils/validation.js:17 +msgid "Email can't be longer than 40 characters." +msgstr "" + +#: src/utils/validation.js:18 +msgid "Email should at least contain a dot" +msgstr "" + +#: src/utils/validation.js:20 +msgid "Email should contain a @" +msgstr "" + +#: src/utils/validation.js:27 +msgid "Name can't be empty." +msgstr "" + +#: src/utils/validation.js:28 +msgid "Name must be at least 4 characters long" +msgstr "" + +#: src/utils/validation.js:29 +msgid "Name must be shorter than 26 characters" +msgstr "" + +#: src/utils/validation.js:36 +msgid "Name contains invalid character like @, /, \\ or #" +msgstr "" + +#: src/utils/validation.js:51 +msgid "Password must be at least 6 characters long." +msgstr "" + +#: src/utils/validation.js:54 +msgid "Password must be shorter than 60 characters." +msgstr "" + +#: src/utils/validation.js:68 +msgid "Could not connect to server, please try again later :(" +msgstr "" + +#: src/utils/validation.js:74 +msgid "I think we experienced some error :(" +msgstr "" + +#: src/routes/api/auth/change_mail.js:41 +#: src/routes/api/auth/change_passwd.js:37 +#: src/routes/api/auth/delete_account.js:38 +msgid "You are not authenticated." +msgstr "" + +#: src/routes/api/auth/change_mail.js:50 +#: src/routes/api/auth/change_passwd.js:46 +#: src/routes/api/auth/delete_account.js:48 +msgid "Incorrect password!" +msgstr "" + +#: src/routes/api/auth/register.js:61 +msgid "Failed to create new user :(" +msgstr "" + +#: src/routes/api/auth/register.js:77 +msgid "Failed to establish session after register :(" +msgstr "" + +#: src/canvasesDesc.js:19 +msgid "Our main canvas, a huge map of the world. Place everywhere you like" +msgstr "" + +#: src/canvasesDesc.js:20 +msgid "Moon canvas. Safe space for art. No flags or large text (unless part of art)" +msgstr "" + +#: src/canvasesDesc.js:21 +msgid "Place Voxels on a 3D canvas with others" +msgstr "" + +#: src/canvasesDesc.js:22 +msgid "Special canvas to spread awareness of SARS-CoV2" +msgstr "" + +#: src/canvasesDesc.js:23 +msgid "Mirror of PixelZone" +msgstr "" + +#: src/canvasesDesc.js:24 +msgid "Mirror of PixelCanvas" +msgstr "" + +#: src/canvasesDesc.js:25 +msgid "Black and White canvas" msgstr "" \ No newline at end of file diff --git a/i18n/template.pot b/i18n/template.pot index 2bfc78f..68c7726 100644 --- a/i18n/template.pot +++ b/i18n/template.pot @@ -3,6 +3,105 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Plural-Forms: nplurals=2; plural=(n!=1);\n" +#: src/components/CoordinatesBox.jsx:37 +#: src/controls/keypress.js:59 +msgid "Copied!" +msgstr "" + +#: src/ui/placePixel.js:53 +msgid "Error :(" +msgstr "" + +#: src/ui/placePixel.js:54 +msgid "Didn't get an answer from pixelplanet. Maybe try to refresh?" +msgstr "" + +#: src/ui/placePixel.js:56 +#: src/ui/placePixel.js:265 +msgid "OK" +msgstr "" + +#: src/ui/placePixel.js:206 +msgid "Invalid Canvas" +msgstr "" + +#: src/ui/placePixel.js:207 +msgid "This canvas doesn't exist" +msgstr "" + +#: src/ui/placePixel.js:210 +#: src/ui/placePixel.js:214 +#: src/ui/placePixel.js:218 +msgid "Invalid Coordinates" +msgstr "" + +#: src/ui/placePixel.js:211 +msgid "x out of bounds" +msgstr "" + +#: src/ui/placePixel.js:215 +msgid "y out of bounds" +msgstr "" + +#: src/ui/placePixel.js:219 +msgid "z out of bounds" +msgstr "" + +#: src/ui/placePixel.js:222 +msgid "Wrong Color" +msgstr "" + +#: src/ui/placePixel.js:223 +msgid "Invalid color selected" +msgstr "" + +#: src/ui/placePixel.js:226 +msgid "Just for registered Users" +msgstr "" + +#: src/ui/placePixel.js:227 +msgid "You have to be logged in to place on this canvas" +msgstr "" + +#: src/ui/placePixel.js:230 +msgid "Place more :)" +msgstr "" + +#: src/ui/placePixel.js:232 +msgid "You can not access this canvas yet. You need to place more pixels" +msgstr "" + +#: src/ui/placePixel.js:235 +msgid "Pixel protected!" +msgstr "" + +#: src/ui/placePixel.js:251 +msgid "No Proxies Allowed :(" +msgstr "" + +#: src/ui/placePixel.js:252 +msgid "You are using a Proxy." +msgstr "" + +#: src/ui/placePixel.js:255 +msgid "Weird" +msgstr "" + +#: src/ui/placePixel.js:256 +msgid "Couldn't set Pixel" +msgstr "" + +#: src/ui/placePixel.js:262 +#, javascript-format +msgid "Error ${ retCode }" +msgstr "" + +#: src/components/Admintools.jsx:219 +#: src/components/ChannelContextMenu.jsx:85 +#: src/components/ModalRoot.jsx:60 +msgid "Close" +msgstr "" + #: src/components/ExpandMenuButton.jsx:19 msgid "Close Menu" msgstr "" @@ -19,6 +118,11 @@ msgstr "" msgid "Open Chat" msgstr "" +#: src/components/CanvasSelectModal.jsx:67 +#: src/components/CanvasSwitchButton.jsx:20 +msgid "Canvas Selection" +msgstr "" + #: src/components/OnlineBox.jsx:22 msgid "User online" msgstr "" @@ -27,10 +131,7 @@ msgstr "" msgid "Pixel gesetzt" msgstr "" -#: src/components/CanvasSwitchButton.jsx:20 -msgid "Canvas Selection" -msgstr "" - +#: src/components/Converter.jsx:609 #: src/components/CoordinatesBox.jsx:26 msgid "Copy to Clipboard" msgstr "" @@ -69,7 +170,7 @@ msgstr "" msgid "Chat here" msgstr "" -#: src/components/Chat.jsx:219 +#: src/components/Chat.jsx:220 msgid "You must be logged in to chat" msgstr "" @@ -77,12 +178,87 @@ msgstr "" msgid "Globe View" msgstr "" -#: src/components/PalselButton.jsx:25 -msgid "Close Palette" +#: src/components/SettingsModal.jsx:123 +msgid "Show Grid" msgstr "" -#: src/components/PalselButton.jsx:25 -msgid "Open Palette" +#: src/components/SettingsModal.jsx:124 +msgid "Turn on grid to highlight pixel borders." +msgstr "" + +#: src/components/SettingsModal.jsx:130 +msgid "Show Pixel Activity" +msgstr "" + +#: src/components/SettingsModal.jsx:131 +msgid "Show circles where pixels are placed." +msgstr "" + +#: src/components/SettingsModal.jsx:137 +msgid "Disable Game Sounds" +msgstr "" + +#: src/components/SettingsModal.jsx:139 +msgid "All sound effects will be disabled." +msgstr "" + +#: src/components/SettingsModal.jsx:145 +msgid "Enable chat notifications" +msgstr "" + +#: src/components/SettingsModal.jsx:146 +msgid "Play a sound when new chat messages arrive" +msgstr "" + +#: src/components/SettingsModal.jsx:151 +msgid "Auto Zoom In" +msgstr "" + +#: src/components/SettingsModal.jsx:153 +msgid "" +"Zoom in instead of placing a pixel when you tap the canvas and your zoom is " +"small." +msgstr "" + +#: src/components/SettingsModal.jsx:158 +msgid "Compact Palette" +msgstr "" + +#: src/components/SettingsModal.jsx:160 +msgid "Display Palette in a compact form that takes less screen space." +msgstr "" + +#: src/components/SettingsModal.jsx:165 +msgid "Potato Mode" +msgstr "" + +#: src/components/SettingsModal.jsx:166 +msgid "For when you are playing on a potato." +msgstr "" + +#: src/components/Converter.jsx:423 +#: src/components/SettingsModal.jsx:171 +msgid "Light Grid" +msgstr "" + +#: src/components/SettingsModal.jsx:172 +msgid "Show Grid in white instead of black." +msgstr "" + +#: src/components/SettingsModal.jsx:179 +msgid "Historical View" +msgstr "" + +#: src/components/SettingsModal.jsx:180 +msgid "Check out past versions of the canvas." +msgstr "" + +#: src/components/SettingsModal.jsx:188 +msgid "Themes" +msgstr "" + +#: src/components/SettingsModal.jsx:189 +msgid "How pixelplanet should look like." msgstr "" #: src/components/HelpModal.jsx:34 @@ -278,6 +454,44 @@ msgstr "" msgid "Welcome to PixelPlanet.fun" msgstr "" +#: src/components/ChannelContextMenu.jsx:73 +msgid "Mute" +msgstr "" + +#: src/components/UserContextMenu.jsx:72 +msgid "Ping" +msgstr "" + +#: src/components/UserContextMenu.jsx:97 +msgid "DM" +msgstr "" + +#: src/components/UserContextMenu.jsx:107 +msgid "Block" +msgstr "" + +#: src/components/PalselButton.jsx:25 +msgid "Close Palette" +msgstr "" + +#: src/components/PalselButton.jsx:25 +msgid "Open Palette" +msgstr "" + +#: src/components/RegisterModal.jsx:18 +msgid "Register new account here" +msgstr "" + +#: src/components/ForgotPasswordModal.jsx:20 +#: src/components/RegisterModal.jsx:21 +#: src/components/UserAreaModal.jsx:130 +msgid "Consider joining us on Guilded:" +msgstr "" + +#: src/components/RegisterModal.jsx:38 +msgid "Register New Account" +msgstr "" + #: src/components/UserAreaModal.jsx:33 msgid "Login to access more features and stats." msgstr "" @@ -290,6 +504,10 @@ msgstr "" msgid "I forgot my Password." msgstr "" +#: src/components/UserAreaModal.jsx:43 +msgid "or login with:" +msgstr "" + #: src/components/UserAreaModal.jsx:84 msgid "or register here:" msgstr "" @@ -298,104 +516,40 @@ msgstr "" msgid "Register" msgstr "" +#: src/components/UserAreaModal.jsx:107 +msgid "Profile" +msgstr "" + +#: src/components/UserAreaModal.jsx:113 +msgid "Ranking" +msgstr "" + +#: src/components/UserAreaModal.jsx:116 +msgid "Converter" +msgstr "" + +#: src/components/UserAreaModal.jsx:122 +msgid "Admintools" +msgstr "" + +#: src/components/UserAreaModal.jsx:122 +msgid "Modtools" +msgstr "" + #: src/components/UserAreaModal.jsx:123 msgid "Loading..." msgstr "" -#: src/components/ForgotPasswordModal.jsx:20 -#: src/components/RegisterModal.jsx:21 -#: src/components/UserAreaModal.jsx:130 -msgid "Consider joining us on Guilded:" +#: src/components/ForgotPasswordModal.jsx:16 +msgid "Enter your mail adress and we will send you a new password:" msgstr "" -#: src/components/RegisterModal.jsx:18 -msgid "Register new account here" +#: src/components/ForgotPasswordModal.jsx:37 +msgid "Restore my Password" msgstr "" -#: src/components/RegisterModal.jsx:38 -msgid "Register New Account" -msgstr "" - -#: src/components/SettingsModal.jsx:123 -msgid "Show Grid" -msgstr "" - -#: src/components/SettingsModal.jsx:124 -msgid "Turn on grid to highlight pixel borders." -msgstr "" - -#: src/components/SettingsModal.jsx:130 -msgid "Show Pixel Activity" -msgstr "" - -#: src/components/SettingsModal.jsx:131 -msgid "Show circles where pixels are placed." -msgstr "" - -#: src/components/SettingsModal.jsx:137 -msgid "Disable Game Sounds" -msgstr "" - -#: src/components/SettingsModal.jsx:139 -msgid "All sound effects will be disabled." -msgstr "" - -#: src/components/SettingsModal.jsx:145 -msgid "Enable chat notifications" -msgstr "" - -#: src/components/SettingsModal.jsx:146 -msgid "Play a sound when new chat messages arrive" -msgstr "" - -#: src/components/SettingsModal.jsx:151 -msgid "Auto Zoom In" -msgstr "" - -#: src/components/SettingsModal.jsx:153 -msgid "" -"Zoom in instead of placing a pixel when you tap the canvas and your zoom is " -"small." -msgstr "" - -#: src/components/SettingsModal.jsx:158 -msgid "Compact Palette" -msgstr "" - -#: src/components/SettingsModal.jsx:160 -msgid "Display Palette in a compact form that takes less screen space." -msgstr "" - -#: src/components/SettingsModal.jsx:165 -msgid "Potato Mode" -msgstr "" - -#: src/components/SettingsModal.jsx:166 -msgid "For when you are playing on a potato." -msgstr "" - -#: src/components/SettingsModal.jsx:171 -msgid "Light Grid" -msgstr "" - -#: src/components/SettingsModal.jsx:172 -msgid "Show Grid in white instead of black." -msgstr "" - -#: src/components/SettingsModal.jsx:179 -msgid "Historical View" -msgstr "" - -#: src/components/SettingsModal.jsx:180 -msgid "Check out past versions of the canvas." -msgstr "" - -#: src/components/SettingsModal.jsx:188 -msgid "Themes" -msgstr "" - -#: src/components/SettingsModal.jsx:189 -msgid "How pixelplanet should look like." +#: src/components/ChatModal.jsx:35 +msgid "Chat" msgstr "" #: src/components/ArchiveModal.jsx:20 @@ -435,23 +589,25 @@ msgstr "" msgid "Canvas Archive" msgstr "" -#: src/components/ForgotPasswordModal.jsx:16 -msgid "Enter your mail adress and we will send you a new password:" +#: src/components/CanvasSelectModal.jsx:29 +msgid "" +"Select the canvas you want to use. Every canvas is unique and has different " +"palettes, cooldown and requirements. Archive of closed canvases can be " +"accessed here:" msgstr "" -#: src/components/ForgotPasswordModal.jsx:37 -msgid "Restore my Password" -msgstr "" - -#: src/components/ChatModal.jsx:35 -msgid "Chat" +#: src/components/CanvasSelectModal.jsx:37 +msgid "Archive" msgstr "" #: src/components/LogInForm.jsx:104 msgid "Name or Email" msgstr "" +#: src/components/ChangeMail.jsx:109 +#: src/components/DeleteAccount.jsx:88 #: src/components/LogInForm.jsx:111 +#: src/components/SignUpForm.jsx:139 msgid "Password" msgstr "" @@ -459,10 +615,368 @@ msgstr "" msgid "LogIn" msgstr "" +#: src/components/UserArea.jsx:57 +msgid "Todays Placed Pixels" +msgstr "" + +#: src/components/UserArea.jsx:61 +msgid "Daily Rank" +msgstr "" + +#: src/components/UserArea.jsx:66 +msgid "Placed Pixels" +msgstr "" + +#: src/components/UserArea.jsx:70 +msgid "Total Rank" +msgstr "" + +#: src/components/UserArea.jsx:75 +#, javascript-format +msgid "Your name is: ${ name }" +msgstr "" + +#: src/components/UserArea.jsx:81 +msgid "Log out" +msgstr "" + +#: src/components/UserArea.jsx:93 +msgid "Change Username" +msgstr "" + +#: src/components/UserArea.jsx:108 +msgid "Change Mail" +msgstr "" + +#: src/components/UserArea.jsx:122 +msgid "Change Password" +msgstr "" + +#: src/components/UserArea.jsx:134 +msgid "Delete Account" +msgstr "" + +#: src/components/UserArea.jsx:147 +msgid "Social Settings" +msgstr "" + +#: src/components/Rankings.jsx:37 +msgid "Total" +msgstr "" + +#: src/components/Rankings.jsx:45 +msgid "Daily" +msgstr "" + #: src/components/Rankings.jsx:49 msgid "Ranking updates every 5 min. Daily rankings get reset at midnight UTC." msgstr "" +#: src/components/CanvasItem.jsx:46 +msgid "Cooldown" +msgstr "" + +#: src/components/CanvasItem.jsx:52 +msgid "Stacking till" +msgstr "" + +#: src/components/CanvasItem.jsx:54 +msgid "Ranked" +msgstr "" + +#: src/components/CanvasItem.jsx:56 +msgid "Requirements" +msgstr "" + +#: src/components/CanvasItem.jsx:58 +msgid "User Account" +msgstr "" + +#: src/components/CanvasItem.jsx:60 +#, javascript-format +msgid "and ${ canvas.req } Pixels set" +msgstr "" + +#: src/components/CanvasItem.jsx:64 +msgid "Dimensions" +msgstr "" + +#: src/components/Admintools.jsx:179 +msgid "Build image on canvas." +msgstr "" + +#: src/components/Admintools.jsx:182 +msgid "Build image and set it to protected." +msgstr "" + +#: src/components/Admintools.jsx:185 +msgid "Build image, but reset cooldown to unset-pixel cd." +msgstr "" + +#: src/components/Admintools.jsx:248 +msgid "Image Upload" +msgstr "" + +#: src/components/Admintools.jsx:249 +msgid "Upload images to canvas" +msgstr "" + +#: src/components/Admintools.jsx:251 +msgid "File" +msgstr "" + +#: src/components/Admintools.jsx:271 +msgid "Coordinates in X_Y format:" +msgstr "" + +#: src/components/Admintools.jsx:306 +#: src/components/Admintools.jsx:387 +#: src/components/Admintools.jsx:461 +#: src/components/Admintools.jsx:505 +#: src/components/Admintools.jsx:589 +#: src/components/SignUpForm.jsx:151 +msgid "Submit" +msgstr "" + +#: src/components/Admintools.jsx:311 +msgid "Pixel Protection" +msgstr "" + +#: src/components/Admintools.jsx:313 +msgid "" +"Set protection of areas (if you need finer grained control, " +"use protect with image upload and alpha layers)" +msgstr "" + +#: src/components/Admintools.jsx:392 +msgid "Rollback to Date" +msgstr "" + +#: src/components/Admintools.jsx:394 +msgid "Rollback an area of the canvas to a set date (00:00 UTC)" +msgstr "" + +#: src/components/Admintools.jsx:468 +msgid "IP Actions" +msgstr "" + +#: src/components/Admintools.jsx:470 +msgid "Do stuff with IPs (one IP per line)" +msgstr "" + +#: src/components/Admintools.jsx:510 +msgid "Manage Moderators" +msgstr "" + +#: src/components/Admintools.jsx:512 +msgid "Remove Moderator" +msgstr "" + +#: src/components/Admintools.jsx:544 +msgid "There are no mods" +msgstr "" + +#: src/components/Admintools.jsx:549 +msgid "Assign new Mod" +msgstr "" + +#: src/components/Admintools.jsx:552 +msgid "Enter UserName of new Mod" +msgstr "" + +#: src/components/SignUpForm.jsx:125 +msgid "Name" +msgstr "" + +#: src/components/SignUpForm.jsx:132 +msgid "Email" +msgstr "" + +#: src/components/SignUpForm.jsx:148 +msgid "Confirm Password" +msgstr "" + +#: src/components/ChangeMail.jsx:122 +#: src/components/ChangePassword.jsx:151 +#: src/components/DeleteAccount.jsx:94 +#: src/components/SignUpForm.jsx:157 +msgid "Cancel" +msgstr "" + +#: src/components/Converter.jsx:274 +msgid "Choose Canvas" +msgstr "" + +#: src/components/Converter.jsx:300 +msgid "Palette Download" +msgstr "" + +#: src/components/Converter.jsx:302 +#, javascript-format +msgid "Palette for ${ gimpLink }" +msgstr "" + +#: src/components/Converter.jsx:320 +#, javascript-format +msgid "Credit for the Palette of the Moon goes to ${ starhouseLink }." +msgstr "" + +#: src/components/Converter.jsx:323 +msgid "Image Converter" +msgstr "" + +#: src/components/Converter.jsx:324 +msgid "Convert an image to canvas colors" +msgstr "" + +#: src/components/Converter.jsx:335 +msgid "Choose Strategy" +msgstr "" + +#: src/components/Converter.jsx:362 +msgid "Choose Color Mode" +msgstr "" + +#: src/components/Converter.jsx:400 +msgid "Add Grid (uncheck if you need a 1:1 template)" +msgstr "" + +#: src/components/Converter.jsx:425 +#: src/components/Converter.jsx:441 +msgid "Offset" +msgstr "" + +#: src/components/Converter.jsx:471 +msgid "Scale Image" +msgstr "" + +#: src/components/Converter.jsx:483 +msgid "Width" +msgstr "" + +#: src/components/Converter.jsx:513 +msgid "Height" +msgstr "" + +#: src/components/Converter.jsx:551 +msgid "Keep Ratio" +msgstr "" + +#: src/components/Converter.jsx:564 +msgid "Anti Aliasing" +msgstr "" + +#: src/components/Converter.jsx:578 +msgid "Reset" +msgstr "" + +#: src/components/Converter.jsx:597 +msgid "Download Template" +msgstr "" + +#: src/utils/validation.js:15 +msgid "Email can't be empty." +msgstr "" + +#: src/utils/validation.js:16 +msgid "Email should be at least 5 characters long." +msgstr "" + +#: src/utils/validation.js:17 +msgid "Email can't be longer than 40 characters." +msgstr "" + +#: src/utils/validation.js:18 +msgid "Email should at least contain a dot" +msgstr "" + +#: src/utils/validation.js:20 +msgid "Email should contain a @" +msgstr "" + +#: src/utils/validation.js:27 +msgid "Name can't be empty." +msgstr "" + +#: src/utils/validation.js:28 +msgid "Name must be at least 4 characters long" +msgstr "" + +#: src/utils/validation.js:29 +msgid "Name must be shorter than 26 characters" +msgstr "" + +#: src/utils/validation.js:36 +msgid "Name contains invalid character like @, /, \\ or #" +msgstr "" + +#: src/utils/validation.js:51 +msgid "Password must be at least 6 characters long." +msgstr "" + +#: src/utils/validation.js:54 +msgid "Password must be shorter than 60 characters." +msgstr "" + +#: src/utils/validation.js:68 +msgid "Could not connect to server, please try again later :(" +msgstr "" + +#: src/utils/validation.js:74 +msgid "I think we experienced some error :(" +msgstr "" + +#: src/components/DeleteAccount.jsx:92 +msgid "Yes, Delete My Account!" +msgstr "" + +#: src/components/ChangeMail.jsx:89 +msgid "" +"Changed Mail successfully. We sent you a verification mail, " +"please verify your new mail adress." +msgstr "" + +#: src/components/ChangeMail.jsx:116 +msgid "New Mail" +msgstr "" + +#: src/components/ChangeMail.jsx:120 +#: src/components/ChangePassword.jsx:149 +msgid "Save" +msgstr "" + +#: src/components/ChangePassword.jsx:18 +msgid "Passwords do not match." +msgstr "" + +#: src/components/ChangePassword.jsx:103 +msgid "Changed Password successfully." +msgstr "" + +#: src/components/ChangePassword.jsx:128 +msgid "Old Password" +msgstr "" + +#: src/components/ChangePassword.jsx:136 +msgid "New Password" +msgstr "" + +#: src/components/ChangePassword.jsx:145 +msgid "Confirm New Password" +msgstr "" + +#: src/components/SocialSettings.jsx:39 +msgid "Block all Private Messages" +msgstr "" + +#: src/components/SocialSettings.jsx:57 +msgid "Unblock Users" +msgstr "" + +#: src/components/SocialSettings.jsx:81 +msgid "You have no users blocked" +msgstr "" + #: src/components/HelpModal.jsx:15 #: src/components/SettingsModal.jsx:125 msgctxt "keybinds" @@ -475,6 +989,11 @@ msgctxt "keybinds" msgid "X" msgstr "" +#: src/components/SettingsModal.jsx:140 +msgctxt "keybinds" +msgid "M" +msgstr "" + #: src/components/HelpModal.jsx:17 #: src/components/SettingsModal.jsx:182 msgctxt "keybinds" @@ -524,9 +1043,4 @@ msgstr "" #: src/components/HelpModal.jsx:32 msgctxt "keybinds" msgid "C" -msgstr "" - -#: src/components/SettingsModal.jsx:140 -msgctxt "keybinds" -msgid "M" msgstr "" \ No newline at end of file diff --git a/src/canvasesDesc.js b/src/canvasesDesc.js index 2982ceb..d91560c 100644 --- a/src/canvasesDesc.js +++ b/src/canvasesDesc.js @@ -35,6 +35,8 @@ function getCanvases(t) { const key = canvasKeys[i]; localicedCanvases[key].desc = canvasDesc[key] || `Canvas ${key}`; } + + return localicedCanvases; } diff --git a/src/components/Admintools.jsx b/src/components/Admintools.jsx index e404013..972029e 100644 --- a/src/components/Admintools.jsx +++ b/src/components/Admintools.jsx @@ -5,6 +5,7 @@ import React, { useState, useEffect } from 'react'; import { connect } from 'react-redux'; +import { t } from 'ttag'; import type { State } from '../reducers'; @@ -175,13 +176,13 @@ function Admintools({ let descAction; switch (imageAction) { case 'build': - descAction = 'Build image on canvas.'; + descAction = t`Build image on canvas.`; break; case 'protect': - descAction = 'Build image and set it to protected.'; + descAction = t`Build image and set it to protected.`; break; case 'wipe': - descAction = 'Build image, but reset cooldown to unset-pixel cd.'; + descAction = t`Build image, but reset cooldown to unset-pixel cd.`; break; default: // nothing @@ -215,7 +216,7 @@ function Admintools({ className="modallink" onClick={() => setResp(null)} > - Close + {t`Close`} )} @@ -244,10 +245,10 @@ function Admintools({


-

Image Upload

-

Upload images to canvas

+

{t`Image Upload`}

+

{t`Upload images to canvas`}

- File:  + {t`File`}: 

- {(submitting) ? '...' : 'Submit'} + {(submitting) ? '...' : t`Submit`}
-

Pixel Protection

+

{t`Pixel Protection`}

- Set protection of areas  - (if you need finer grained control,  - use protect with image upload and alpha layers) + {t`Set protection of areas \ + (if you need finer grained control, \ + use protect with image upload and alpha layers)`}

- {(submitting) ? '...' : 'Submit'} + {(submitting) ? '...' : t`Submit`} {(userlvl === 1) && (

-

IP Actions

-

Do stuff with IPs (one IP per line)

+

{t`IP Actions`}

+

+ {t`Do stuff with IPs (one IP per line)`} +

- {(submitting) ? '...' : 'Submit'} + {(submitting) ? '...' : t`Submit`}
diff --git a/src/components/ChangeMail.jsx b/src/components/ChangeMail.jsx index 2d04d9c..845f9aa 100644 --- a/src/components/ChangeMail.jsx +++ b/src/components/ChangeMail.jsx @@ -4,6 +4,7 @@ */ import React from 'react'; +import { t } from 'ttag'; import { validateEMail, validatePassword, parseAPIresponse, } from '../utils/validation'; @@ -85,8 +86,8 @@ class ChangeMail extends React.Component {

- Changed Mail successfully. - We sent you a verification mail, please verify your new mail adress. + {t`Changed Mail successfully. We sent you a verification mail, \ + please verify your new mail adress.`}

@@ -105,20 +106,20 @@ class ChangeMail extends React.Component { value={password} onChange={(evt) => this.setState({ password: evt.target.value })} type="password" - placeholder="Password" + placeholder={t`Password`} />
this.setState({ email: evt.target.value })} type="text" - placeholder="New Mail" + placeholder={t`New Mail`} />
- +
); diff --git a/src/components/ChangePassword.jsx b/src/components/ChangePassword.jsx index b73dc1f..892067c 100644 --- a/src/components/ChangePassword.jsx +++ b/src/components/ChangePassword.jsx @@ -4,6 +4,7 @@ */ import React from 'react'; +import { t } from 'ttag'; import { validatePassword, parseAPIresponse } from '../utils/validation'; function validate(mailreg, password, newPassword, confirmPassword) { @@ -14,7 +15,7 @@ function validate(mailreg, password, newPassword, confirmPassword) { if (oldpasserror) errors.push(oldpasserror); } if (newPassword !== confirmPassword) { - errors.push('Passwords do not match.'); + errors.push(t`Passwords do not match.`); return errors; } const passerror = validatePassword(newPassword); @@ -99,7 +100,7 @@ class ChangePassword extends React.Component { const { done } = this.props; return (
-

Changed Password successfully.

+

{t`Changed Password successfully.`}

); @@ -124,7 +125,7 @@ class ChangePassword extends React.Component { value={password} onChange={(evt) => this.setState({ password: evt.target.value })} type="password" - placeholder="Old Password" + placeholder={t`Old Password`} /> )}
@@ -132,7 +133,7 @@ class ChangePassword extends React.Component { value={newPassword} onChange={(evt) => this.setState({ newPassword: evt.target.value })} type="password" - placeholder="New Password" + placeholder={t`New Password`} />

- +
); diff --git a/src/components/ChannelContextMenu.jsx b/src/components/ChannelContextMenu.jsx index 4934e93..730b5ec 100644 --- a/src/components/ChannelContextMenu.jsx +++ b/src/components/ChannelContextMenu.jsx @@ -7,6 +7,7 @@ import React, { useRef, useEffect, } from 'react'; import { connect } from 'react-redux'; +import { t } from 'ttag'; import { hideContextMenu, @@ -69,7 +70,7 @@ const UserContextMenu = ({ tabIndex={0} style={{ borderTop: 'none' }} > - {`${(isMuted) ? '✔' : '✘'} Mute`} + {`${(isMuted) ? '✔' : '✘'} ${t`Mute`}`}
{(channels[cid][1] !== 0) && ( @@ -81,7 +82,7 @@ const UserContextMenu = ({ }} tabIndex={0} > - Close + {t`Close`}
)} diff --git a/src/components/DeleteAccount.jsx b/src/components/DeleteAccount.jsx index 263e5d8..490c3c0 100644 --- a/src/components/DeleteAccount.jsx +++ b/src/components/DeleteAccount.jsx @@ -5,8 +5,9 @@ import React from 'react'; import { connect } from 'react-redux'; -import { validatePassword, parseAPIresponse } from '../utils/validation'; +import { t } from 'ttag'; +import { validatePassword, parseAPIresponse } from '../utils/validation'; import { logoutUser } from '../actions'; function validate(password) { @@ -84,13 +85,13 @@ class DeleteAccount extends React.Component { value={password} onChange={(evt) => this.setState({ password: evt.target.value })} type="password" - placeholder="Password" + placeholder={t`Password`} />
- + ); diff --git a/src/components/LogInForm.jsx b/src/components/LogInForm.jsx index 6fa8047..7da23f4 100644 --- a/src/components/LogInForm.jsx +++ b/src/components/LogInForm.jsx @@ -18,8 +18,10 @@ function validate(nameoremail, password) { ? validateEMail(nameoremail) : validateName(nameoremail); if (mailerror) errors.push(mailerror); + /* const passworderror = validatePassword(password); if (passworderror) errors.push(passworderror); + */ return errors; } diff --git a/src/components/SignUpForm.jsx b/src/components/SignUpForm.jsx index d95c6d2..746c58d 100644 --- a/src/components/SignUpForm.jsx +++ b/src/components/SignUpForm.jsx @@ -5,6 +5,7 @@ import React from 'react'; import { connect } from 'react-redux'; +import { t } from 'ttag'; import { validateEMail, validateName, validatePassword, parseAPIresponse, } from '../utils/validation'; @@ -121,21 +122,21 @@ class SignUpForm extends React.Component { value={name} onChange={(evt) => this.setState({ name: evt.target.value })} type="text" - placeholder="Name" + placeholder={t`Name`} />
this.setState({ email: evt.target.value })} type="text" - placeholder="Email" + placeholder={t`Email`} />
this.setState({ password: evt.target.value })} type="password" - placeholder="Password" + placeholder={t`Password`} />

); diff --git a/src/components/SocialSettings.jsx b/src/components/SocialSettings.jsx index f068d31..e959c62 100644 --- a/src/components/SocialSettings.jsx +++ b/src/components/SocialSettings.jsx @@ -5,6 +5,7 @@ import React from 'react'; import { connect } from 'react-redux'; +import { t } from 'ttag'; import { setBlockingDm, @@ -35,7 +36,7 @@ const SocialSettings = ({ }} className="modaltitle" > - Block all Private Messages + {t`Block all Private Messages`} Unblock Users

+ >{t`Unblock Users`}

{ (blocked.length) ? ( ) : ( -

You have no users blocked

+

{t`You have no users blocked`}

) }
diff --git a/src/components/UserContextMenu.jsx b/src/components/UserContextMenu.jsx index 5875be7..9df7817 100644 --- a/src/components/UserContextMenu.jsx +++ b/src/components/UserContextMenu.jsx @@ -7,6 +7,7 @@ import React, { useRef, useEffect, } from 'react'; import { connect } from 'react-redux'; +import { t } from 'ttag'; import { hideContextMenu, @@ -68,7 +69,7 @@ const UserContextMenu = ({ }} style={{ borderTop: 'none' }} > - Ping + {t`Ping`}
- DM + {t`DM`}
{ @@ -103,7 +104,7 @@ const UserContextMenu = ({ role="button" tabIndex={-1} > - Block + {t`Block`}
); diff --git a/src/core/mail.js b/src/core/mail.js index da55742..bfb0a40 100644 --- a/src/core/mail.js +++ b/src/core/mail.js @@ -3,12 +3,14 @@ * @flow */ -// import Sequelize from 'sequelize'; +/* eslint-disable max-len */ + import nodemailer from 'nodemailer'; import logger from './logger'; import { HOUR, MINUTE } from './constants'; import { DailyCron, HourlyCron } from '../utils/cron'; +import { getTTag } from './ttag'; import { GMAIL_USER, GMAIL_PW } from './config'; import RegUser from '../data/models/RegUser'; @@ -48,7 +50,9 @@ class MailProvider { DailyCron.hook(MailProvider.cleanUsers); } - sendVerifyMail(to, name, host) { + sendVerifyMail(to, name, host, lang) { + const { t } = getTTag(lang); + const pastMail = this.verifyCodes[to]; if (pastMail) { const minLeft = Math.floor( @@ -58,8 +62,7 @@ class MailProvider { logger.info( `Verify mail for ${to} - already sent, ${minLeft} minutes left`, ); - // eslint-disable-next-line max-len - return `We already sent you a verification mail, you can request another one in ${minLeft} minutes.`; + return t`We already sent you a verification mail, you can request another one in ${minLeft} minutes.`; } } logger.info(`Sending verification mail to ${to} / ${name}`); @@ -69,12 +72,13 @@ class MailProvider { from, to, replyTo: 'donotreply@pixelplanet.fun', - // eslint-disable-next-line max-len - subject: `Welcome ${name} to PixelPlanet, plese verify your mail`, - // eslint-disable-next-line max-len + subject: t`Welcome ${name} to PixelPlanet, plese verify your mail`, // text: `Hello,\nwelcome to our little community of pixelplacers, to use your account, you have to verify your mail. You can do that here:\n ${verifyUrl} \nHave fun and don't hesitate to contact us if you encouter any problems :)\nThanks`, - // eslint-disable-next-line max-len - html: `Hello ${name},
\nwelcome to our little community of pixelplacers, to use your account, you have to verify your mail. You can do that here. Or by copying following url:
${verifyUrl}\n
\nHave fun and don't hesitate to contact us if you encouter any problems :)
\nThanks

\n`, + html: `${t`Hello ${name}`},
+ ${t`welcome to our little community of pixelplacers, to use your account, you have to verify your mail. You can do that here: `} ${t`Click to Verify`}. ${t`Or by copying following url:`}
${verifyUrl}\n
+ ${t`Have fun and don't hesitate to contact us if you encouter any problems :)`}
+ ${t`Thanks`}

+ `, }, (err) => { if (err) { logger.error(err); @@ -83,15 +87,15 @@ class MailProvider { return null; } - async sendPasswdResetMail(to, ip, host) { + async sendPasswdResetMail(to, ip, host, lang) { + const { t } = getTTag(lang); const pastMail = this.verifyCodes[to]; if (pastMail) { if (Date.now() < pastMail.timestamp + 15 * MINUTE) { logger.info( `Password reset mail for ${to} requested by ${ip} - already sent`, ); - // eslint-disable-next-line max-len - return 'We already sent you a mail with instructions. Please wait before requesting another mail.'; + return t`We already sent you a mail with instructions. Please wait before requesting another mail.`; } } const reguser = await RegUser.findOne({ where: { email: to } }); @@ -99,7 +103,7 @@ class MailProvider { logger.info( `Password reset mail for ${to} requested by ${ip} - mail not found`, ); - return "Couldn't find this mail in our database"; + return t`Couldn't find this mail in our database`; } /* * not sure if this is needed yet @@ -118,11 +122,12 @@ class MailProvider { from, to, replyTo: 'donotreply@pixelplanet.fun', - subject: 'You forgot your password for PixelPlanet? Get a new one here', - // eslint-disable-next-line max-len + subject: t`You forgot your password for PixelPlanet? Get a new one here`, // text: `Hello,\nYou requested to get a new password. You can change your password within the next 30min here:\n ${restoreUrl} \nHave fun and don't hesitate to contact us if you encouter any problems :)\nIf you did not request this mail, please just ignore it (the ip that requested this mail was ${ip}).\nThanks`, - // eslint-disable-next-line max-len - html: `Hello,
\nYou requested to get a new password. You can change your password within the next 30min here. Or by copying following url:
${restoreUrl}\n
\nIf you did not request this mail, please just ignore it (the ip that requested this mail was ${ip}).
\nThanks

\n`, + html: `${t`Hello`},
+ ${t`You requested to get a new password. You can change your password within the next 30min here: `} ${t`Reset Password`}. ${t`Or by copying following url:`}
${restoreUrl}\n
+ ${t`If you did not request this mail, please just ignore it (the ip that requested this mail was ${ip}).`}
+ ${t`Thanks`}

\n`, }, (err) => { if (err) { logger.error(err & err.stack); diff --git a/src/core/ttag.js b/src/core/ttag.js index 2d2ec8a..10f986c 100644 --- a/src/core/ttag.js +++ b/src/core/ttag.js @@ -4,6 +4,7 @@ */ import { TTag } from 'ttag'; import deLocale from '../../i18n/ssr-de.po'; +import { languageFromLocalisation } from '../utils/location'; const LOCALES = { de: deLocale, @@ -27,4 +28,11 @@ export function getTTag(lang) { return ttags[lang] || ttags.default; } +export function expressTTag(req, res, next) { + const language = req.headers['accept-language']; + req.lang = (language) ? languageFromLocalisation(language) : 'en'; + req.ttag = getTTag(req.lang); + next(); +} + export default ttags; diff --git a/src/routes/api/auth/change_mail.js b/src/routes/api/auth/change_mail.js index ab7b30e..e574c2d 100644 --- a/src/routes/api/auth/change_mail.js +++ b/src/routes/api/auth/change_mail.js @@ -11,10 +11,10 @@ import { validatePassword, validateEMail } from '../../../utils/validation'; import { getHostFromRequest } from '../../../utils/ip'; import { compareToHash } from '../../../utils/hash'; -function validate(email, password) { +function validate(email, password, gettext) { const errors = []; - const passerror = validatePassword(password); + const passerror = gettext(validatePassword(password)); if (passerror) errors.push(passerror); const mailerror = validateEMail(email); if (mailerror) errors.push(mailerror); @@ -24,7 +24,8 @@ function validate(email, password) { export default async (req: Request, res: Response) => { const { email, password } = req.body; - const errors = validate(email, password); + const { t, gettext } = req.ttag; + const errors = validate(email, password, gettext); if (errors.length > 0) { res.status(400); res.json({ @@ -33,11 +34,11 @@ export default async (req: Request, res: Response) => { return; } - const { user } = req; + const { user, lang } = req; if (!user) { res.status(401); res.json({ - errors: ['You are not authenticated.'], + errors: [t`You are not authenticated.`], }); return; } @@ -46,7 +47,7 @@ export default async (req: Request, res: Response) => { if (!compareToHash(password, currentPassword)) { res.status(400); res.json({ - errors: ['Incorrect password!'], + errors: [t`Incorrect password!`], }); return; } @@ -57,7 +58,7 @@ export default async (req: Request, res: Response) => { }); const host = getHostFromRequest(req); - mailProvider.sendVerifyMail(email, user.regUser.name, host); + mailProvider.sendVerifyMail(email, user.regUser.name, host, lang); res.json({ success: true, diff --git a/src/routes/api/auth/change_passwd.js b/src/routes/api/auth/change_passwd.js index 364641b..32b9bee 100644 --- a/src/routes/api/auth/change_passwd.js +++ b/src/routes/api/auth/change_passwd.js @@ -9,10 +9,10 @@ import type { Request, Response } from 'express'; import { validatePassword } from '../../../utils/validation'; import { compareToHash } from '../../../utils/hash'; -function validate(newPassword) { +function validate(newPassword, gettext) { const errors = []; - const newpassworderror = validatePassword(newPassword); + const newpassworderror = gettext(validatePassword(newPassword)); if (newpassworderror) errors.push(newpassworderror); return errors; @@ -20,7 +20,8 @@ function validate(newPassword) { export default async (req: Request, res: Response) => { const { newPassword, password } = req.body; - const errors = validate(newPassword); + const { t, gettext } = req.ttag; + const errors = validate(newPassword, gettext); if (errors.length > 0) { res.status(400); res.json({ @@ -33,7 +34,7 @@ export default async (req: Request, res: Response) => { if (!user) { res.status(401); res.json({ - errors: ['You are not authenticated.'], + errors: [t`You are not authenticated.`], }); return; } @@ -42,7 +43,7 @@ export default async (req: Request, res: Response) => { if (currentPassword && !compareToHash(password, currentPassword)) { res.status(400); res.json({ - errors: ['Incorrect password!'], + errors: [t`Incorrect password!`], }); return; } diff --git a/src/routes/api/auth/delete_account.js b/src/routes/api/auth/delete_account.js index 47d4673..433837e 100644 --- a/src/routes/api/auth/delete_account.js +++ b/src/routes/api/auth/delete_account.js @@ -10,10 +10,10 @@ import { RegUser } from '../../../data/models'; import { validatePassword } from '../../../utils/validation'; import { compareToHash } from '../../../utils/hash'; -function validate(password) { +function validate(password, gettext) { const errors = []; - const passworderror = validatePassword(password); + const passworderror = gettext(validatePassword(password)); if (passworderror) errors.push(passworderror); return errors; @@ -21,7 +21,8 @@ function validate(password) { export default async (req: Request, res: Response) => { const { password } = req.body; - const errors = await validate(password); + const { t, gettext } = req.ttag; + const errors = await validate(password, gettext); if (errors.length > 0) { res.status(400); res.json({ @@ -34,7 +35,7 @@ export default async (req: Request, res: Response) => { if (!user) { res.status(401); res.json({ - errors: ['You are not authenticated.'], + errors: [t`You are not authenticated.`], }); return; } @@ -44,7 +45,7 @@ export default async (req: Request, res: Response) => { if (!currentPassword || !compareToHash(password, currentPassword)) { res.status(400); res.json({ - errors: ['Incorrect password!'], + errors: [t`Incorrect password!`], }); return; } diff --git a/src/routes/api/auth/index.js b/src/routes/api/auth/index.js index 8e83127..3d240ad 100644 --- a/src/routes/api/auth/index.js +++ b/src/routes/api/auth/index.js @@ -156,7 +156,7 @@ export default (passport) => { } user.ip = req.user.ip; - const me = await getMe(user); + const me = await getMe(user, req.lang); res.json({ success: true, me, diff --git a/src/routes/api/auth/register.js b/src/routes/api/auth/register.js index fcced3e..b184568 100644 --- a/src/routes/api/auth/register.js +++ b/src/routes/api/auth/register.js @@ -18,13 +18,13 @@ import { validatePassword, } from '../../../utils/validation'; -async function validate(email, name, password) { +async function validate(email, name, password, gettext) { const errors = []; const emailerror = validateEMail(email); if (emailerror) errors.push(emailerror); const nameerror = validateName(name); if (nameerror) errors.push(nameerror); - const passworderror = validatePassword(password); + const passworderror = gettext(validatePassword(password)); if (passworderror) errors.push(passworderror); let reguser = await RegUser.findOne({ where: { email } }); @@ -37,7 +37,8 @@ async function validate(email, name, password) { export default async (req: Request, res: Response) => { const { email, name, password } = req.body; - const errors = await validate(email, name, password); + const { t, gettext } = req.ttag; + const errors = await validate(email, name, password, gettext); if (errors.length > 0) { res.status(400); res.json({ @@ -57,7 +58,7 @@ export default async (req: Request, res: Response) => { if (!newuser) { res.status(500); res.json({ - errors: ['Failed to create new user :('], + errors: [t`Failed to create new user :(`], }); return; } @@ -65,20 +66,20 @@ export default async (req: Request, res: Response) => { const ip = getIPFromRequest(req); logger.info(`Created new user ${name} ${email} ${ip}`); - const { user } = req; + const { user, lang } = req; user.setRegUser(newuser); - const me = await getMe(user); + const me = await getMe(user, lang); await req.logIn(user, (err) => { if (err) { res.status(500); res.json({ - errors: ['Failed to establish session after register :('], + errors: [t`Failed to establish session after register :(`], }); return; } const host = getHostFromRequest(req); - mailProvider.sendVerifyMail(email, name, host); + mailProvider.sendVerifyMail(email, name, host, lang); res.status(200); res.json({ success: true, diff --git a/src/routes/api/auth/resend_verify.js b/src/routes/api/auth/resend_verify.js index daec475..71f0517 100644 --- a/src/routes/api/auth/resend_verify.js +++ b/src/routes/api/auth/resend_verify.js @@ -10,7 +10,7 @@ import mailProvider from '../../../core/mail'; import { getHostFromRequest } from '../../../utils/ip'; export default async (req: Request, res: Response) => { - const { user } = req; + const { user, lang } = req; if (!user) { res.status(401); res.json({ @@ -30,7 +30,7 @@ export default async (req: Request, res: Response) => { const host = getHostFromRequest(req); - const error = mailProvider.sendVerifyMail(email, name, host); + const error = mailProvider.sendVerifyMail(email, name, host, lang); if (error) { res.status(400); res.json({ diff --git a/src/routes/api/auth/restore_password.js b/src/routes/api/auth/restore_password.js index 35475a0..1cd3f46 100644 --- a/src/routes/api/auth/restore_password.js +++ b/src/routes/api/auth/restore_password.js @@ -31,7 +31,8 @@ export default async (req: Request, res: Response) => { return; } const host = getHostFromRequest(req); - const error = await mailProvider.sendPasswdResetMail(email, ip, host); + const { lang } = req; + const error = await mailProvider.sendPasswdResetMail(email, ip, host, lang); if (error) { res.status(400); res.json({ diff --git a/src/routes/api/index.js b/src/routes/api/index.js index 91ab4d6..966925e 100644 --- a/src/routes/api/index.js +++ b/src/routes/api/index.js @@ -7,6 +7,7 @@ import bodyParser from 'body-parser'; import session from '../../core/session'; import passport from '../../core/passport'; +import { expressTTag } from '../../core/ttag'; import logger from '../../core/logger'; import User from '../../data/models/User'; import { getIPFromRequest } from '../../utils/ip'; @@ -78,8 +79,6 @@ router.use((req, res, next) => { next(); }); -router.get('/me', me); - router.post('/mctp', mctp); router.get('/chathistory', chatHistory); @@ -92,6 +91,10 @@ router.post('/block', block); router.post('/blockdm', blockdm); +router.use(expressTTag); + +router.get('/me', me); + router.use('/auth', auth(passport)); export default router; diff --git a/src/routes/api/me.js b/src/routes/api/me.js index 2d23643..fa3a2fc 100644 --- a/src/routes/api/me.js +++ b/src/routes/api/me.js @@ -14,8 +14,8 @@ import { cheapDetector } from '../../core/isProxy'; export default async (req: Request, res: Response) => { - const { user } = req; - const userdata = await getMe(user); + const { user, lang } = req; + const userdata = await getMe(user, lang); user.updateLogInTimestamp(); const { trueIp: ip } = req; diff --git a/src/routes/reset_password.js b/src/routes/reset_password.js index 4f0b43e..bac273f 100644 --- a/src/routes/reset_password.js +++ b/src/routes/reset_password.js @@ -13,6 +13,7 @@ import type { Request, Response } from 'express'; import redis from '../data/redis'; import logger from '../core/logger'; import getPasswordResetHtml from '../ssr-components/PasswordReset'; +import { expressTTag } from '../core/ttag'; import { MINUTE } from '../core/constants'; import mailProvider from '../core/mail'; @@ -41,17 +42,25 @@ router.use('/', router.use(bodyParser.urlencoded({ extended: true })); +/* + * use translation + */ +router.use(expressTTag); + + /* * Check for POST parameters, * if invalid password is given, ignore it and go to next */ router.post('/', async (req: Request, res: Response) => { const { pass, passconf, code } = req.body; + const { t } = req.ttag; + if (!pass || !passconf || !code) { const html = getPasswordResetHtml( null, null, - 'You sent an empty password or invalid data :(', + t`You sent an empty password or invalid data :(`, ); res.status(400).send(html); return; @@ -62,7 +71,7 @@ router.post('/', async (req: Request, res: Response) => { const html = getPasswordResetHtml( null, null, - "This password-reset link isn't valid anymore :(", + t`This password-reset link isn't valid anymore :(`, ); res.status(401).send(html); return; @@ -72,7 +81,7 @@ router.post('/', async (req: Request, res: Response) => { const html = getPasswordResetHtml( null, null, - 'Your passwords do not match :(', + t`Your passwords do not match :(`, ); res.status(400).send(html); return; @@ -86,7 +95,7 @@ router.post('/', async (req: Request, res: Response) => { const html = getPasswordResetHtml( null, null, - "User doesn't exist in our database :(", + t`User doesn't exist in our database :(`, ); res.status(400).send(html); return; @@ -97,7 +106,7 @@ router.post('/', async (req: Request, res: Response) => { const html = getPasswordResetHtml( null, null, - 'Passowrd successfully changed.', + t`Passowrd successfully changed.`, ); res.status(200).send(html); }); @@ -108,11 +117,13 @@ router.post('/', async (req: Request, res: Response) => { */ router.get('/', async (req: Request, res: Response) => { const { token } = req.query; + const { t } = req.ttag; + if (!token) { const html = getPasswordResetHtml( null, null, - 'Invalid url :( Please check your mail again.', + t`Invalid url :( Please check your mail again.`, ); res.status(400).send(html); return; @@ -124,7 +135,7 @@ router.get('/', async (req: Request, res: Response) => { null, null, // eslint-disable-next-line max-len - 'This passwort reset link is wrong or already expired, please request a new one (Note: you can use those links just once)', + t`This passwort reset link is wrong or already expired, please request a new one (Note: you can use those links just once)`, ); res.status(401).send(html); return; diff --git a/src/utils/validation.js b/src/utils/validation.js index fd778f8..e471b67 100644 --- a/src/utils/validation.js +++ b/src/utils/validation.js @@ -1,34 +1,42 @@ /* - * functionf for validation of user input + * Functions for validation of user input + * This gets used on server and on the client. + * + * On the server the return values will be again translated with gettext + * which could be a bit questionable, but it is preferable to write this file + * two times imho. + * * @flow */ +import { t } from 'ttag/dist/mock'; + // eslint-disable-next-line no-useless-escape, max-len const mailTester = /^[-!#$%&'*+\/0-9=?A-Z^_a-z{|}~](\.?[-!#$%&'*+\/0-9=?A-Z^_a-z`{|}~])*@[a-zA-Z0-9](-*\.?[a-zA-Z0-9])*\.[a-zA-Z](-?[a-zA-Z0-9])+$/; export function validateEMail(email) { - if (!email) return "Email can't be empty."; - if (email.length < 5) return 'Email should be at least 5 characters long.'; - if (email.length > 40) return "Email can't be longer than 40 characters."; - if (email.indexOf('.') === -1) return 'Email should at least contain a dot'; + if (!email) return t`Email can't be empty.`; + if (email.length < 5) return t`Email should be at least 5 characters long.`; + if (email.length > 40) return t`Email can't be longer than 40 characters.`; + if (email.indexOf('.') === -1) return t`Email should at least contain a dot`; if (email.split('').filter((x) => x === '@').length !== 1) { - return 'Email should contain a @'; + return t`Email should contain a @`; } if (!mailTester.test(email)) return 'Your Email looks shady'; return false; } export function validateName(name) { - if (!name) return "Name can't be empty."; - if (name.length < 4) return 'Name must be at least 4 characters long'; - if (name.length > 26) return 'Name must be shorter than 26 characters'; + if (!name) return t`Name can't be empty.`; + if (name.length < 4) return t`Name must be at least 4 characters long`; + if (name.length > 26) return t`Name must be shorter than 26 characters`; if (name.indexOf('@') !== -1 || name.indexOf('/') !== -1 || name.indexOf('\\') !== -1 || name.indexOf('>') !== -1 || name.indexOf('<') !== -1 || name.indexOf('#') !== -1) { - return 'Name contains invalid character like @, /, \\ or #'; + return t`Name contains invalid character like @, /, \\ or #`; } return false; } @@ -42,11 +50,14 @@ export function sanitizeName(name) { } export function validatePassword(password) { + if (!password) { + return t`No password given.`; + } if (password.length < 6) { - return 'Password must be at least 6 characters long.'; + return t`Password must be at least 6 characters long.`; } if (password.length > 60) { - return 'Password must be shorter than 60 characters.'; + return t`Password must be shorter than 60 characters.`; } return false; } @@ -60,13 +71,13 @@ export async function parseAPIresponse(response) { const resp = await response.json(); if (!response.ok && !resp.errors) { return { - errors: ['Could not connect to server, please try again later :('], + errors: [t`Could not connect to server, please try again later :(`], }; } return resp; } catch (e) { return { - errors: ['I think we experienced some error :('], + errors: [t`I think we experienced some error :(`], }; } } diff --git a/webpack.config.web.babel.js b/webpack.config.web.babel.js index 31a8629..24b9a88 100644 --- a/webpack.config.web.babel.js +++ b/webpack.config.web.babel.js @@ -55,7 +55,7 @@ const babelPlugins = [ extract: { output: path.resolve(__dirname, 'i18n', 'template-ssr.pot'), }, - discover: ['t', 'jt', 'gettext'], + discover: ['t', 'jt'], }], ];