Skip to content

Commit

Permalink
Add locale support (lukevella#228)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukevella authored Jul 21, 2022
1 parent 800af20 commit 416a17c
Show file tree
Hide file tree
Showing 47 changed files with 978 additions and 478 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,10 @@ yarn start

If you would like to contribute to the development of the project please reach out first before spending significant time on it.

### Translators 🇫🇷 🇩🇪 🇮🇹 🇪🇸

If you'd like to volunteer to translate Rallly to another language, check out our [guide for translators](https://github.com/lukevella/rallly/wiki/Guide-for-translators).

## 👮‍♂️ License

Rallly is open-source under the GNU Affero General Public License Version 3 (AGPLv3) or any later version. See [LICENSE](LICENSE) for more detail.
Expand Down
2 changes: 2 additions & 0 deletions declarations/i18next.d.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import "react-i18next";

import app from "~/public/locales/en/app.json";
import common from "~/public/locales/en/common.json";
import homepage from "~/public/locales/en/homepage.json";

declare module "next-i18next" {
interface Resources {
homepage: typeof homepage;
app: typeof app;
common: typeof common;
}
}
2 changes: 1 addition & 1 deletion next-i18next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const path = require("path");
module.exports = {
i18n: {
defaultLocale: "en",
locales: ["en"],
locales: ["en", "de"],
localePath: path.resolve("./public/locales"),
reloadOnPrerender: process.env.NODE_ENV === "development",
},
Expand Down
5 changes: 2 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,14 @@
"js-cookie": "^3.0.1",
"lodash": "^4.17.21",
"nanoid": "^3.1.30",
"next": "^12.1.4",
"next": "^12.2.2",
"next-i18next": "^10.5.0",
"next-plausible": "^3.1.9",
"nodemailer": "^6.7.2",
"prisma": "^3.15.2",
"react": "17.0.2",
"react-big-calendar": "^0.38.9",
"react-dom": "17.0.2",
"react-github-btn": "^1.2.2",
"react-hook-form": "^7.31.3",
"react-hot-toast": "^2.2.0",
"react-i18next": "^11.16.9",
Expand All @@ -70,7 +69,7 @@
"@typescript-eslint/parser": "^5.21.0",
"autoprefixer": "^10.4.2",
"eslint": "^7.26.0",
"eslint-config-next": "12.1.0",
"eslint-config-next": "^12.2.2",
"eslint-import-resolver-typescript": "^2.7.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-react": "^7.23.2",
Expand Down
129 changes: 129 additions & 0 deletions public/locales/de/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
{
"12h": "12 Stunden",
"24h": "24 Stunden",
"addTimeOption": "Uhrzeit hinzufügen",
"applyToAllDates": "Auf alle Termine anwenden",
"areYouSure": "Bist du sicher?",
"back": "Zurück",
"blog": "Blog",
"calendarHelp": "Du kannst keine Umfrage ohne Optionen erstellen. Füge mindestens eine Option hinzu, um fortzufahren.",
"calendarHelpTitle": "Irgendwas vergessen?",
"cancel": "Abbrechen",
"comment": "Kommentieren",
"commentPlaceholder": "Kommentar zu dieser Umfrage hinterlassen (für jeden sichtbar)",
"comments": "Kommentare",
"continue": "Weiter",
"copied": "Kopiert",
"copyLink": "Link kopieren",
"createdBy": "von <b>{{name}}</b>",
"createPoll": "Umfrage erstellen",
"creatingDemo": "Demo-Umfrage wird erstellt…",
"delete": "Löschen",
"deleteComment": "Kommentar löschen",
"deleteDate": "Tag löschen",
"deletedPoll": "Umfrage gelöscht",
"deletedPollInfo": "Diese Umfrage existiert nicht mehr.",
"deletePoll": "Umfrage löschen",
"deletePollDescription": "Alle Daten zu dieser Umfrage werden gelöscht. Zur Bestätigung geben Sie bitte <s>“{{confirmText}}”</s> in das folgende Feld ein:",
"deletingOptionsWarning": "Du löschst Optionen, für die bereits Teilnehmer gestimmt haben. Ihre Stimmen werden ebenfalls gelöscht.",
"demoPollNotice": "Demo-Umfragen werden automatisch nach einem Tag gelöscht",
"description": "Beschreibung",
"descriptionPlaceholder": "Hallo ihr, bitte wählt alle Termine aus, die für euch passen!",
"discussions": "Diskussion",
"donate": "Spenden",
"editDetails": "Details bearbeiten",
"editOptions": "Optionen bearbeiten",
"email": "E-Mail",
"emailPlaceholder": "[email protected]",
"endingGuestSessionNotice": "Sobald eine Gastsitzung beendet ist, kann sie nicht fortgesetzt werden. Du kannst weder Auswahl noch Kommentare bearbeiten, die Du mit dieser Sitzung gemacht hast.",
"endSession": "Sitzung beenden",
"errorCreate": "Oh oh! Es gab ein Problem beim Erstellen deiner Umfrage. Der Fehler wurde protokolliert und wir werden versuchen, ihn zu beheben.",
"exportToCsv": "CSV exportieren",
"finish": "Fertigstellen",
"forgetMe": "Vergiss mich",
"goToAdmin": "Zur Admin Oberfläche",
"guest": "Gast",
"guestSessionNotice": "Du benutzt eine Gastsitzung, so können wir dich erkennen, wenn du später wiederkommst, damit du deine Angaben bearbeiten kannst.",
"guestSessionReadMore": "Mehr über Gastsitzungen.",
"hide": "Ausblenden",
"ifNeedBe": "Falls erforderlich",
"linkHasExpired": "Der Link ist abgelaufen oder ungültig",
"loading": "Wird geladen…",
"loadingParticipants": "Teilnehmerliste wird geladen…",
"location": "Ort",
"locationPlaceholder": "Joe's Café",
"lockPoll": "Umfragen sperren",
"login": "Login",
"loginCheckInbox": "Bitte überprüfe deinen Posteingang.",
"loginMagicLinkSent": "Ein magischer Link wurde geschickt an:",
"loginSendMagicLink": "Schicke mir einen magischen Link",
"loginViaMagicLink": "Anmeldung über magischen Link",
"loginViaMagicLinkDescription": "Wir senden dir eine E-Mail mit einem magischen Link, mit dem du dich anmelden kannst.",
"loginWithValidEmail": "Bitte gib eine gültige E-Mail-Adresse ein",
"logout": "Logout",
"manage": "Verwalten",
"menu": "Menü",
"mixedOptionsDescription": "Du kannst keine Zeit- und Datumsoptionen in der gleichen Umfrage haben. Welche möchtest Du beibehalten?",
"mixedOptionsKeepDates": "Datumsoptionen beibehalten",
"mixedOptionsKeepTimes": "Zeitoptionen beibehalten",
"mixedOptionsTitle": "Warte einen Moment…🤔",
"monday": "Montag",
"monthView": "Monatsansicht",
"name": "Name",
"namePlaceholder": "Max Mustermann",
"newPoll": "Neue Umfrage",
"next": "Weiter",
"nextMonth": "Nächster Monat",
"no": "Nein",
"noDatesSelected": "Kein Datum ausgewählt",
"notificationsDisabled": "Benachrichtigungen wurden deaktiviert",
"notificationsOff": "Benachrichtigungen sind deaktiviert",
"notificationsOn": "Benachrichtigungen sind aktiv",
"notificationsOnDescription": "Wenn diese Umfrage bearbeitet wird, wird eine E-Mail an <b>{{email}}</b> gesendet.",
"notificationsVerifyEmail": "Du musst deine E-Mail-Adresse bestätigen, um Benachrichtigungen zu aktivieren",
"ok": "Ok",
"options": "Optionen",
"participant": "Teilnehmer",
"addParticipant": "Add participant",
"alreadyVoted": "You have already voted",
"participantCount_other": "{{count}} Teilnehmer",
"participantCount": "{{count}} Teilnehmer",
"pollHasBeenLocked": "Diese Umfrage wurde gesperrt",
"pollHasBeenVerified": "Deine Umfrage wurde verifiziert",
"pollOwnerNotice": "Hallo {{name}}, sieht so aus, als ob du der Besitzer dieser Umfrage bist.",
"pollsEmpty": "Keine Umfragen erstellt",
"possibleAnswers": "Mögliche Antworten",
"preferences": "Einstellungen",
"previousMonth": "Vorheriger Monat",
"profileLogin": "Profil - Login",
"profileUser": "Profil - {{username}}",
"requiredNameError": "Bitte gib einen Namen an",
"save": "Speichern",
"saveInstruction": "Select your availability and click <b>{{save}}</b>",
"share": "Teilen",
"shareDescription": "Gib diesen Link deinen <b>Teilnehmern</b> damit sie an deiner Umfrage teilnehmen können.",
"shareLink": "Über Link teilen",
"specifyTimes": "Uhrzeiten angeben",
"specifyTimesDescription": "Start- und Endzeit für jede Option angeben",
"stepSummary": "Schritt {{current}} von {{total}}",
"sunday": "Sonntag",
"support": "Hilfe",
"timeAndDate": "Datum & Uhrzeit",
"timeFormat": "Uhrzeitformat:",
"timeZone": "Zeitzone:",
"title": "Titel",
"titlePlaceholder": "Monatliches Meeting",
"unlockPoll": "Umfrage entsperren",
"unverifiedMessage": "Ein Link zur Bestätigung der E-Mail-Adresse wurde an <b>{{email}}</b> versendet.",
"user": "Benutzer",
"vote": "Abstimmen",
"voteCount_other": "{{count}} Stimmen",
"voteCount": "{{count}} Stimme",
"weekStartsOn": "Woche beginnt am",
"weekView": "Wochenansicht",
"whatsThis": "Was ist das?",
"yes": "Ja",
"yourDetails": "Persönliche Angaben",
"yourName": "Your name…",
"yourPolls": "Deine Umfragen"
}
13 changes: 13 additions & 0 deletions public/locales/de/common.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"language": "Sprache",
"english": "Englisch",
"german": "Deutsch",
"home": "Home",
"blog": "Blog",
"support": "Support",
"donate": "Donate",
"volunteerTranslator": "Help translate this site",
"starOnGithub": "Star us on Github",
"footerCredit": "Made by <a>@imlukevella</a>",
"footerSponsor": "This project is user-funded. Please consider supporting it by <a>donating</a>."
}
44 changes: 44 additions & 0 deletions public/locales/de/homepage.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{
"3Ls": "Ja – mit 3 <e>L</e>s",
"adFree": "Ohne Werbung",
"adFreeDescription": "Gönn deinem Adblocker eine Pause - du brauchst ihn hier nicht.",
"blog": "Blog",
"comments": "Kommentare",
"commentsDescription": "Teilnehmer können deine Umfrage kommentieren, die Kommentare sind für alle sichtbar.",
"discussions": "Diskussion",
"features": "Funktionen",
"featuresSubheading": "Terminfindung leicht gemacht",
"follow": "Folgen",
"getStarted": "Los geht's",
"heroSubText": "Finde ohne Hin-und Her den richtigen Termin",
"heroText": "Plane<br/><s>Besprechungen</s><br />ganz einfach",
"links": "Links",
"liveDemo": "Live Demo",
"metaDescription": "Erstelle Umfragen und stimme ab, um den besten Tag oder die beste Zeit zu finden. Eine kostenlose Alternative zu Doodle.",
"metaTitle": "Rallly - Gruppenmeetings planen",
"mobileFriendly": "Für Mobilgeräte optimiert",
"mobileFriendlyDescription": "Funktioniert hervorragend auf mobilen Geräten, so dass Teilnehmer auf Umfragen antworten können, wo immer sie sich befinden.",
"new": "Neu",
"noLoginRequired": "Keine Anmeldung benötigt",
"noLoginRequiredDescription": "Du musst dich nicht einloggen, um eine Umfrage zu erstellen oder an ihr teilzunehmen",
"notifications": "Benachrichtigungen",
"notificationsDescription": "Behalte den Überblick darüber, wer geantwortet hat. Werde benachrichtigt, wenn Teilnehmer abstimmen oder deine Umfrage kommentieren.",
"openSource": "Open Source",
"openSourceDescription": "Die Codebase ist vollständig Open-Source und <a>auf GitHub</a> verfügbar.",
"participant": "Teilnehmer",
"participantCount_other": "{{count}} Teilnehmer",
"social": "Social",
"participantCount": "{{count}} Teilnehmer",
"perfect": "Perfekt!",
"poweredBy": "Unterstützt von",
"principles": "Grundsätze",
"principlesSubheading": "Wir sind nicht wie die anderen",
"privacyPolicy": "Datenschutzrichtlinie",
"selfHostable": "Selfhosting möglich",
"selfHostableDescription": "Betreibe es auf deinem eigenen Server, um die volle Kontrolle über deine Daten zu haben",
"sponsorThisProject": "Dieses Projekt unterstützen",
"star": "Star",
"support": "Hilfe",
"timeSlots": "Zeitfenster",
"timeSlotsDescription": "Wähle individuelle Start- und Endzeiten für jede Option in deiner Umfrage. Die Zeiten können automatisch an die Zeitzone jedes Teilnehmers angepasst werden oder so eingestellt werden, dass Zeitzonen komplett ignoriert werden."
}
8 changes: 5 additions & 3 deletions public/locales/en/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
"12h": "12-hour",
"24h": "24-hour",
"addTimeOption": "Add time option",
"admin": "Admin",
"applyToAllDates": "Apply to all dates",
"areYouSure": "Are you sure?",
"back": "Back",
Expand All @@ -23,7 +22,7 @@
"deleteComment": "Delete comment",
"deleteDate": "Delete date",
"deletedPoll": "Deleted poll",
"deletedPollInfo": "this poll doesn't exist anymore.",
"deletedPollInfo": "This poll doesn't exist anymore.",
"deletePoll": "Delete poll",
"deletePollDescription": "All data related to this poll will be deleted. To confirm, please type <s>“{{confirmText}}”</s> in to the input below:",
"deletingOptionsWarning": "You are deleting options that participants have voted for. Their votes will be also be deleted.",
Expand Down Expand Up @@ -85,6 +84,8 @@
"ok": "Ok",
"options": "Options",
"participant": "Participant",
"addParticipant": "Add participant",
"alreadyVoted": "You have already voted",
"participantCount_other": "{{count}} participants",
"participantCount": "{{count}} participant",
"pollHasBeenLocked": "This poll has been locked",
Expand All @@ -96,9 +97,9 @@
"previousMonth": "Previous month",
"profileLogin": "Profile - Login",
"profileUser": "Profile - {{username}}",
"remove": "Remove",
"requiredNameError": "Name is required",
"save": "Save",
"saveInstruction": "Select your availability and click <b>{{save}}</b>",
"share": "Share",
"shareDescription": "Give this link to your <b>participants</b> to allow them to vote on your poll.",
"shareLink": "Share via link",
Expand All @@ -123,5 +124,6 @@
"whatsThis": "What's this?",
"yes": "Yes",
"yourDetails": "Your details",
"yourName": "Your name…",
"yourPolls": "Your polls"
}
12 changes: 11 additions & 1 deletion public/locales/en/common.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
{
"appName": "Rallly"
"language": "Language",
"english": "English",
"german": "German",
"home": "Home",
"blog": "Blog",
"support": "Support",
"donate": "Donate",
"volunteerTranslator": "Help translate this site",
"starOnGithub": "Star us on Github",
"footerCredit": "Made by <a>@imlukevella</a>",
"footerSponsor": "This project is user-funded. Please consider supporting it by <a>donating</a>."
}
4 changes: 2 additions & 2 deletions public/locales/en/homepage.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
"features": "Features",
"featuresSubheading": "Scheduling, the smart way",
"follow": "Follow",
"footerCredit": "Self-funded and built by <a>@imlukevella</a>",
"getStarted": "Get started",
"heroSubText": "Find the right date without the back and forth",
"heroText": "Schedule<br/><s>group meetings</s><br />with ease",
Expand All @@ -28,6 +27,7 @@
"openSourceDescription": "The codebase is fully open-source and <a>available on GitHub</a>.",
"participant": "Participant",
"participantCount_other": "{{count}} participants",
"social": "Social",
"participantCount": "{{count}} participant",
"perfect": "Perfect!",
"poweredBy": "Powered by",
Expand All @@ -38,7 +38,7 @@
"selfHostableDescription": "Run it on your own server to take full control of your data",
"sponsorThisProject": "Sponsor this project",
"star": "Star",
"support": "support",
"support": "Support",
"timeSlots": "Time slots",
"timeSlotsDescription": "Set individual start and end times for each option in your poll. Times can be automatically adjusted to each participant's timezone or they can be set to ignore timezones completely."
}
2 changes: 1 addition & 1 deletion src/components/create-poll.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ const Page: NextPage<CreatePollPageProps> = ({
<div className="max-w-full py-4 md:px-3 lg:px-6">
<div className="mx-auto w-fit max-w-full lg:mx-0">
<div className="mb-4 flex items-center justify-center space-x-4 px-4 lg:justify-start">
<h1 className="m-0">New Poll</h1>
<h1 className="m-0">{t("newPoll")}</h1>
<Steps current={currentStepIndex} total={steps.length} />
</div>
<div className="overflow-hidden border-t border-b bg-white shadow-sm md:rounded-lg md:border">
Expand Down
8 changes: 4 additions & 4 deletions src/components/forms/poll-options-form/week-calendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const WeekCalendar: React.VoidFunctionComponent<DateTimePickerProps> = ({
);
}}
components={{
toolbar: (props) => {
toolbar: function Toolbar(props) {
return (
<DateNavigationToolbar
year={props.date.getFullYear()}
Expand All @@ -83,7 +83,7 @@ const WeekCalendar: React.VoidFunctionComponent<DateTimePickerProps> = ({
/>
);
},
eventWrapper: (props) => {
eventWrapper: function EventWraper(props) {
const start = dayjs(props.event.start);
const end = dayjs(props.event.end);
return (
Expand All @@ -105,7 +105,7 @@ const WeekCalendar: React.VoidFunctionComponent<DateTimePickerProps> = ({
},
week: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
header: ({ date }: any) => {
header: function Header({ date }: any) {
const dateString = formatDateWithoutTime(date);
const selectedOption = options.find((option) => {
return option.type === "date" && option.date === dateString;
Expand Down Expand Up @@ -143,7 +143,7 @@ const WeekCalendar: React.VoidFunctionComponent<DateTimePickerProps> = ({
);
},
},
timeSlotWrapper: ({ children }) => {
timeSlotWrapper: function TimeSlotWrapper({ children }) {
return <div className="h-8 text-xs text-gray-500">{children}</div>;
},
}}
Expand Down
2 changes: 1 addition & 1 deletion src/components/home/bonus.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Ban from "./ban-ads.svg";
const Bonus: React.VoidFunctionComponent = () => {
const { t } = useTranslation("homepage");
return (
<div className="mx-auto max-w-7xl px-8 pt-8 pb-24">
<div className="mx-auto max-w-7xl px-8 py-8">
<h2 className="heading">{t("principles")}</h2>
<p className="subheading">{t("principlesSubheading")}</p>
<div className="grid grid-cols-4 gap-16">
Expand Down
Loading

0 comments on commit 416a17c

Please sign in to comment.