more translations

This commit is contained in:
HF 2021-01-30 13:32:46 +01:00
parent 8475ad0c9f
commit e7eafbf450
28 changed files with 1880 additions and 374 deletions

View File

@ -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 ""

View File

@ -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"

View File

@ -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 ""

View File

@ -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 ""

View File

@ -35,6 +35,8 @@ function getCanvases(t) {
const key = canvasKeys[i];
localicedCanvases[key].desc = canvasDesc[key] || `Canvas ${key}`;
}
return localicedCanvases;
}

View File

@ -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`}
</span>
</div>
)}
@ -244,10 +245,10 @@ function Admintools({
</p>
<br />
<div className="modaldivider" />
<h3 className="modaltitle">Image Upload</h3>
<p className="modalcotext">Upload images to canvas</p>
<h3 className="modaltitle">{t`Image Upload`}</h3>
<p className="modalcotext">{t`Upload images to canvas`}</p>
<p className="modalcotext">
File:&nbsp;
{t`File`}:&nbsp;
<input type="file" name="image" id="imgfile" />
</p>
<select
@ -267,7 +268,7 @@ function Admintools({
</select>
<p className="modalcotext">{descAction}</p>
<p className="modalcotext">
Coordinates in X_Y format:&nbsp;
{t`Coordinates in X_Y format:`}&nbsp;
<input
value={coords}
style={{
@ -302,16 +303,16 @@ function Admintools({
);
}}
>
{(submitting) ? '...' : 'Submit'}
{(submitting) ? '...' : t`Submit`}
</button>
<br />
<div className="modaldivider" />
<h3 className="modaltitle">Pixel Protection</h3>
<h3 className="modaltitle">{t`Pixel Protection`}</h3>
<p className="modalcotext">
Set protection of areas&nbsp;
(if you need finer grained control,&nbsp;
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)`}
</p>
<select
onChange={(e) => {
@ -383,14 +384,14 @@ function Admintools({
);
}}
>
{(submitting) ? '...' : 'Submit'}
{(submitting) ? '...' : t`Submit`}
</button>
<br />
<div className="modaldivider" />
<h3 className="modaltitle">Rollback to Date</h3>
<h3 className="modaltitle">{t`Rollback to Date`}</h3>
<p className="modalcotext">
Rollback an area of the canvas to a set date (00:00 UTC)
{t`Rollback an area of the canvas to a set date (00:00 UTC)`}
</p>
<input
type="date"
@ -457,15 +458,17 @@ function Admintools({
);
}}
>
{(submitting) ? '...' : 'Submit'}
{(submitting) ? '...' : t`Submit`}
</button>
{(userlvl === 1) && (
<div>
<br />
<div className="modaldivider" />
<h3 className="modaltitle">IP Actions</h3>
<p className="modalcotext">Do stuff with IPs (one IP per line)</p>
<h3 className="modaltitle">{t`IP Actions`}</h3>
<p className="modalcotext">
{t`Do stuff with IPs (one IP per line)`}
</p>
<select
onChange={(e) => {
const sel = e.target;
@ -499,14 +502,14 @@ function Admintools({
);
}}
>
{(submitting) ? '...' : 'Submit'}
{(submitting) ? '...' : t`Submit`}
</button>
<br />
<div className="modaldivider" />
<h3 className="modaltitle">Manage Moderators</h3>
<h3 className="modaltitle">{t`Manage Moderators`}</h3>
<p className="modalcotext">
Remove Moderator
{t`Remove Moderator`}
</p>
{(modlist.length) ? (
<span
@ -538,15 +541,15 @@ function Admintools({
</span>
)
: (
<p className="modaltext">There are no mods</p>
<p className="modaltext">{t`There are no mods`}</p>
)}
<br />
<p className="modalcotext">
Assign new Mod
{t`Assign new Mod`}
</p>
<p className="modalcotext">
Enter UserName of new Mod:&nbsp;
{t`Enter UserName of new Mod`}:&nbsp;
<input
value={modName}
style={{
@ -583,7 +586,7 @@ function Admintools({
);
}}
>
{(submitting) ? '...' : 'Submit'}
{(submitting) ? '...' : t`Submit`}
</button>
<br />
<div className="modaldivider" />

View File

@ -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 {
<p
className="modalmessage"
>
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.`}
</p>
<button type="button" onClick={done}>Close</button>
</div>
@ -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`}
/>
<br />
<input
value={email}
onChange={(evt) => this.setState({ email: evt.target.value })}
type="text"
placeholder="New Mail"
placeholder={t`New Mail`}
/>
<br />
<button type="submit">
{(submitting) ? '...' : 'Save'}
{(submitting) ? '...' : t`Save`}
</button>
<button type="button" onClick={done}>Cancel</button>
<button type="button" onClick={done}>{t`Cancel`}</button>
</form>
</div>
);

View File

@ -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 (
<div className="inarea">
<p className="modalmessage">Changed Password successfully.</p>
<p className="modalmessage">{t`Changed Password successfully.`}</p>
<button type="button" onClick={done}>Close</button>
</div>
);
@ -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`}
/>
)}
<br />
@ -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`}
/>
<br />
<input
@ -141,13 +142,13 @@ class ChangePassword extends React.Component {
confirmPassword: evt.target.value,
})}
type="password"
placeholder="Confirm New Password"
placeholder={t`Confirm New Password`}
/>
<br />
<button type="submit">
{(submitting) ? '...' : 'Save'}
{(submitting) ? '...' : t`Save`}
</button>
<button type="button" onClick={cancel}>Cancel</button>
<button type="button" onClick={cancel}>{t`Cancel`}</button>
</form>
</div>
);

View File

@ -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`}`}
</div>
{(channels[cid][1] !== 0)
&& (
@ -81,7 +82,7 @@ const UserContextMenu = ({
}}
tabIndex={0}
>
Close
{t`Close`}
</div>
)}
</div>

View File

@ -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`}
/>
<br />
<button type="submit">
{(submitting) ? '...' : 'Yes, Delete My Account!'}
{(submitting) ? '...' : t`Yes, Delete My Account!`}
</button>
<button type="button" onClick={done}>Cancel</button>
<button type="button" onClick={done}>{t`Cancel`}</button>
</form>
</div>
);

View File

@ -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;
}

View File

@ -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`}
/><br />
<input
style={inputStyles}
value={email}
onChange={(evt) => this.setState({ email: evt.target.value })}
type="text"
placeholder="Email"
placeholder={t`Email`}
/><br />
<input
style={inputStyles}
value={password}
onChange={(evt) => this.setState({ password: evt.target.value })}
type="password"
placeholder="Password"
placeholder={t`Password`}
/><br />
<input
style={inputStyles}
@ -144,16 +145,16 @@ class SignUpForm extends React.Component {
confirmPassword: evt.target.value,
})}
type="password"
placeholder="Confirm Password"
placeholder={t`Confirm Password`}
/><br />
<button type="submit">
{(submitting) ? '...' : 'Submit'}
{(submitting) ? '...' : t`Submit`}
</button>
<button
type="button"
onClick={back}
>
Cancel
{t`Cancel`}
</button>
</form>
);

View File

@ -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`}
</span>
<MdToggleButtonHover
value={blockDm}
@ -53,7 +54,7 @@ const SocialSettings = ({
marginLeft: 10,
}}
className="modaltitle"
>Unblock Users</p>
>{t`Unblock Users`}</p>
{
(blocked.length) ? (
<span
@ -77,7 +78,7 @@ const SocialSettings = ({
</span>
)
: (
<p className="modaltext">You have no users blocked</p>
<p className="modaltext">{t`You have no users blocked`}</p>
)
}
<div className="modaldivider" />

View File

@ -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`}
</div>
<div
role="button"
@ -93,7 +94,7 @@ const UserContextMenu = ({
close();
}}
>
DM
{t`DM`}
</div>
<div
onClick={() => {
@ -103,7 +104,7 @@ const UserContextMenu = ({
role="button"
tabIndex={-1}
>
Block
{t`Block`}
</div>
</div>
);

View File

@ -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: `<em>Hello ${name}</em>,<br />\nwelcome to our little community of pixelplacers, to use your account, you have to verify your mail. You can do that <a href="${verifyUrl}">here</a>. Or by copying following url:<br />${verifyUrl}\n<br />\nHave fun and don&#39;t hesitate to contact us if you encouter any problems :)<br />\nThanks<br /><br />\n<img alt="" src="https://assets.pixelplanet.fun/tile.png" style="height:64px; width:64px" />`,
html: `<em>${t`Hello ${name}`}</em>,<br />
${t`welcome to our little community of pixelplacers, to use your account, you have to verify your mail. You can do that here: `} <a href="${verifyUrl}">${t`Click to Verify`}</a>. ${t`Or by copying following url:`}<br />${verifyUrl}\n<br />
${t`Have fun and don't hesitate to contact us if you encouter any problems :)`}<br />
${t`Thanks`}<br /><br />
<img alt="" src="https://assets.pixelplanet.fun/tile.png" style="height:64px; width:64px" />`,
}, (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: `<em>Hello</em>,<br />\nYou requested to get a new password. You can change your password within the next 30min <a href="${restoreUrl}">here</a>. Or by copying following url:<br />${restoreUrl}\n<br />\nIf you did not request this mail, please just ignore it (the ip that requested this mail was ${ip}).<br />\nThanks<br /><br />\n<img alt="" src="https://assets.pixelplanet.fun/tile.png" style="height:64px; width:64px" />`,
html: `<em>${t`Hello`}</em>,<br />
${t`You requested to get a new password. You can change your password within the next 30min here: `} <a href="${restoreUrl}">${t`Reset Password`}</a>. ${t`Or by copying following url:`}<br />${restoreUrl}\n<br />
${t`If you did not request this mail, please just ignore it (the ip that requested this mail was ${ip}).`}<br />
${t`Thanks`}<br /><br />\n<img alt="" src="https://assets.pixelplanet.fun/tile.png" style="height:64px; width:64px" />`,
}, (err) => {
if (err) {
logger.error(err & err.stack);

View File

@ -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;

View File

@ -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,

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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,

View File

@ -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,

View File

@ -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({

View File

@ -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({

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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 :(`],
};
}
}

View File

@ -55,7 +55,7 @@ const babelPlugins = [
extract: {
output: path.resolve(__dirname, 'i18n', 'template-ssr.pot'),
},
discover: ['t', 'jt', 'gettext'],
discover: ['t', 'jt'],
}],
];