mirror of
https://github.com/lukevella/rallly.git
synced 2025-04-29 18:26:34 +02:00
Add Swedish locale (#244)
* Add Swedish locale * Stop reload when changing language * Add translation * Remove unused
This commit is contained in:
parent
0546ed44a9
commit
2bacb67beb
10 changed files with 194 additions and 14 deletions
|
@ -3,7 +3,7 @@ const path = require("path");
|
||||||
module.exports = {
|
module.exports = {
|
||||||
i18n: {
|
i18n: {
|
||||||
defaultLocale: "en",
|
defaultLocale: "en",
|
||||||
locales: ["en", "de", "fr"],
|
locales: ["en", "de", "fr", "sv"],
|
||||||
localePath: path.resolve("./public/locales"),
|
localePath: path.resolve("./public/locales"),
|
||||||
reloadOnPrerender: process.env.NODE_ENV === "development",
|
reloadOnPrerender: process.env.NODE_ENV === "development",
|
||||||
},
|
},
|
||||||
|
|
|
@ -16,5 +16,6 @@
|
||||||
"spanish": "Spanish",
|
"spanish": "Spanish",
|
||||||
"starOnGithub": "Star us on Github",
|
"starOnGithub": "Star us on Github",
|
||||||
"support": "Support",
|
"support": "Support",
|
||||||
|
"swedish": "Swedish",
|
||||||
"volunteerTranslator": "Help translate this site"
|
"volunteerTranslator": "Help translate this site"
|
||||||
}
|
}
|
||||||
|
|
128
public/locales/sv/app.json
Normal file
128
public/locales/sv/app.json
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
{
|
||||||
|
"12h": "12-timmar",
|
||||||
|
"24h": "24-timmar",
|
||||||
|
"addParticipant": "Lägg till deltagare",
|
||||||
|
"addTimeOption": "Lägg till tidsalternativ",
|
||||||
|
"alreadyVoted": "Du har redan röstat",
|
||||||
|
"applyToAllDates": "Tillämpa på alla datum",
|
||||||
|
"areYouSure": "Är du säker?",
|
||||||
|
"back": "Tillbaka",
|
||||||
|
"calendarHelp": "Du kan inte skapa en enkät utan några alternativ. Lägg till minst ett alternativ för att fortsätta.",
|
||||||
|
"calendarHelpTitle": "Glöm något?",
|
||||||
|
"cancel": "Avbryt",
|
||||||
|
"comment": "Kommentera",
|
||||||
|
"commentPlaceholder": "Lämna en kommentar på denna enkät (synlig för alla)",
|
||||||
|
"comments": "Kommentarer",
|
||||||
|
"continue": "Fortsätt",
|
||||||
|
"copied": "Kopierad",
|
||||||
|
"copyLink": "Kopiera länk",
|
||||||
|
"createdBy": "av <b>{{name}}</b>",
|
||||||
|
"createPoll": "Skapa en enkät",
|
||||||
|
"creatingDemo": "Skapar demoenkät…",
|
||||||
|
"delete": "Radera",
|
||||||
|
"deleteComment": "Radera kommentar",
|
||||||
|
"deleteDate": "Radera datum",
|
||||||
|
"deletedPoll": "Raderad enkät",
|
||||||
|
"deletedPollInfo": "Den här enkäten finns inte längre.",
|
||||||
|
"deletePoll": "Radera enkät",
|
||||||
|
"deletePollDescription": "All data relaterad till denna enkät kommer att raderas. För att bekräfta, skriv <s>”{{confirmText}}”</s> i inmatningsrutan nedan:",
|
||||||
|
"deletingOptionsWarning": "Du tar bort alternativ som deltagarna har röstat på. Deras röster kommer också att raderas.",
|
||||||
|
"demoPollNotice": "Demoenkäter raderas automatiskt efter 1 dag",
|
||||||
|
"description": "Beskrivning",
|
||||||
|
"descriptionPlaceholder": "Hej alla, välj de datum som fungerar för dig!",
|
||||||
|
"donate": "Donera",
|
||||||
|
"editDetails": "Redigera detaljer",
|
||||||
|
"editOptions": "Redigera alternativ",
|
||||||
|
"email": "E-post",
|
||||||
|
"emailPlaceholder": "olle.jonsson@email.com",
|
||||||
|
"endingGuestSessionNotice": "När en gäst session avslutas kan den inte återupptas. Du kommer inte att kunna redigera några röster eller kommentarer som du har gjort med denna session.",
|
||||||
|
"endSession": "Avsluta session",
|
||||||
|
"errorCreate": "Oj då! Det gick inte att skapa din enkät. Felet har loggats och vi försöker rätta till det.",
|
||||||
|
"exportToCsv": "Exportera till CSV",
|
||||||
|
"finish": "Slutför",
|
||||||
|
"forgetMe": "Glöm mig",
|
||||||
|
"goToAdmin": "Gå till Admin",
|
||||||
|
"guest": "Gäst",
|
||||||
|
"guestSessionNotice": "Du använder en gästsession. Detta gör att vi kan känna igen dig om du kommer tillbaka senare så att du kan redigera dina röster.",
|
||||||
|
"guestSessionReadMore": "Läs mer om gästsessioner.",
|
||||||
|
"hide": "Dölj",
|
||||||
|
"ifNeedBe": "Om det behövs",
|
||||||
|
"linkHasExpired": "Din länk har gått ut eller är inte längre giltig",
|
||||||
|
"loading": "Laddar…",
|
||||||
|
"loadingParticipants": "Laddar deltagare…",
|
||||||
|
"location": "Plats",
|
||||||
|
"locationPlaceholder": "Joe's Café",
|
||||||
|
"lockPoll": "Lås enkät",
|
||||||
|
"login": "Logga in",
|
||||||
|
"loginCheckInbox": "Vänligen kolla din inbox.",
|
||||||
|
"loginMagicLinkSent": "En magisk länk har skickats till:",
|
||||||
|
"loginSendMagicLink": "Skicka mig en magisk länk",
|
||||||
|
"loginViaMagicLink": "Logga in med magisk länk",
|
||||||
|
"loginViaMagicLinkDescription": "Vi kommer att skicka dig ett mail med en magisk länk som du kan använda för att logga in.",
|
||||||
|
"loginWithValidEmail": "Skriv in en giltig e-postadress",
|
||||||
|
"logout": "Logga ut",
|
||||||
|
"manage": "Hantera",
|
||||||
|
"menu": "Meny",
|
||||||
|
"mixedOptionsDescription": "Du kan inte ha både tids- och datumalternativ i samma omröstning. Vilka vill du behålla?",
|
||||||
|
"mixedOptionsKeepDates": "Behåll datumalternativ",
|
||||||
|
"mixedOptionsKeepTimes": "Behåll tidsalternativ",
|
||||||
|
"mixedOptionsTitle": "Vänta en sekund…🤔",
|
||||||
|
"monday": "Måndag",
|
||||||
|
"monthView": "Månadsvy",
|
||||||
|
"name": "Namn",
|
||||||
|
"namePlaceholder": "Olle Jonsson",
|
||||||
|
"newPoll": "Ny enkät",
|
||||||
|
"next": "Nästa",
|
||||||
|
"nextMonth": "Nästa månad",
|
||||||
|
"no": "Nej",
|
||||||
|
"noDatesSelected": "Inga datum valda",
|
||||||
|
"notificationsDisabled": "Aviseringar har inaktiverats",
|
||||||
|
"notificationsOff": "Aviseringar är av",
|
||||||
|
"notificationsOn": "Aviseringar är på",
|
||||||
|
"notificationsOnDescription": "Ett e-postmeddelande kommer att skickas till <b>{{email}}</b> när det finns aktivitet på denna enkät.",
|
||||||
|
"notificationsVerifyEmail": "Du måste verifiera din e-post för att aktivera aviseringar",
|
||||||
|
"ok": "Ok",
|
||||||
|
"options": "Alternativ",
|
||||||
|
"participant": "Deltagare",
|
||||||
|
"participantCount_other": "{{count}} deltagare",
|
||||||
|
"participantCount": "{{count}} deltagare",
|
||||||
|
"pollHasBeenLocked": "Denna enkät har låsts",
|
||||||
|
"pollHasBeenVerified": "Din enkät har blivit verifierad",
|
||||||
|
"pollOwnerNotice": "Hej {{name}}, ser ut som du är ägare av denna enkät.",
|
||||||
|
"pollsEmpty": "Inga enkäter skapade",
|
||||||
|
"possibleAnswers": "Möjliga svar",
|
||||||
|
"preferences": "Inställningar",
|
||||||
|
"previousMonth": "Föregående månad",
|
||||||
|
"profileLogin": "Profil - Inloggning",
|
||||||
|
"profileUser": "Profil - {{username}}",
|
||||||
|
"requiredNameError": "Namn är obligatoriskt",
|
||||||
|
"save": "Spara",
|
||||||
|
"saveInstruction": "Välj din tillgänglighet och klicka på <b>{{save}}</b>",
|
||||||
|
"share": "Dela",
|
||||||
|
"shareDescription": "Ge den här länken till dina <b>deltagare</b> så att de kan delta i din enkät.",
|
||||||
|
"shareLink": "Dela via länk",
|
||||||
|
"specifyTimes": "Ange tider",
|
||||||
|
"specifyTimesDescription": "Inkludera start- och sluttider för varje alternativ",
|
||||||
|
"stepSummary": "Steg {{current}} av {{total}}",
|
||||||
|
"sunday": "Söndag",
|
||||||
|
"timeAndDate": "Tid och datum",
|
||||||
|
"timeFormat": "Tidsformat:",
|
||||||
|
"timeZone": "Tidszon:",
|
||||||
|
"title": "Titel",
|
||||||
|
"titlePlaceholder": "Månatligt möte",
|
||||||
|
"today": "Idag",
|
||||||
|
"unlockPoll": "Lås upp enkät",
|
||||||
|
"unverifiedMessage": "Ett e-postmeddelande har skickats till <b>{{email}}</b> med en länk för att verifiera e-postadressen.",
|
||||||
|
"user": "Användare",
|
||||||
|
"vote": "Rösta",
|
||||||
|
"voteCount_other": "{{count}} röster",
|
||||||
|
"voteCount": "{{count}} röst",
|
||||||
|
"weekStartsOn": "Veckan börjar med",
|
||||||
|
"weekView": "Veckovy",
|
||||||
|
"whatsThis": "Vad är detta?",
|
||||||
|
"yes": "Ja",
|
||||||
|
"you": "Du",
|
||||||
|
"yourDetails": "Dina uppgifter",
|
||||||
|
"yourName": "Ditt namn…",
|
||||||
|
"yourPolls": "Dina enkäter"
|
||||||
|
}
|
21
public/locales/sv/common.json
Normal file
21
public/locales/sv/common.json
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
{
|
||||||
|
"blog": "Blogg",
|
||||||
|
"discussions": "Diskussioner",
|
||||||
|
"donate": "Donera",
|
||||||
|
"english": "Engelska",
|
||||||
|
"footerCredit": "Gjort av <a>@imlukevella</a>",
|
||||||
|
"footerSponsor": "Detta projekt är användarfinansierat. Överväg att stödja det genom att göra en <a>donation</a>.",
|
||||||
|
"french": "Franska",
|
||||||
|
"german": "Tyska",
|
||||||
|
"home": "Hem",
|
||||||
|
"italian": "Italienska",
|
||||||
|
"language": "Språk",
|
||||||
|
"links": "Länkar",
|
||||||
|
"poweredBy": "Byggd på",
|
||||||
|
"privacyPolicy": "Integritetspolicy",
|
||||||
|
"spanish": "Spanska",
|
||||||
|
"starOnGithub": "Stjärnmarkera på GitHub",
|
||||||
|
"support": "Support",
|
||||||
|
"swedish": "Svenska",
|
||||||
|
"volunteerTranslator": "Hjälp till att översätta denna webbplats"
|
||||||
|
}
|
36
public/locales/sv/homepage.json
Normal file
36
public/locales/sv/homepage.json
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
{
|
||||||
|
"3Ls": "Ja, med 3 <e>L</e>",
|
||||||
|
"adFree": "Reklamfritt",
|
||||||
|
"adFreeDescription": "Du kan låta din annonsblockerare vila - du behöver det inte här.",
|
||||||
|
"comments": "Kommentarer",
|
||||||
|
"commentsDescription": "Deltagarna kan kommentera din enkät och kommentarerna kommer att vara synliga för alla.",
|
||||||
|
"features": "Funktioner",
|
||||||
|
"featuresSubheading": "Schemaläggning, på det smarta sättet",
|
||||||
|
"follow": "Följ",
|
||||||
|
"getStarted": "Kom igång",
|
||||||
|
"heroSubText": "Hitta rätt datum utan allt fram och tillbaka",
|
||||||
|
"heroText": "Schemalägg<br/><s>gruppmöten</s><br />enkelt",
|
||||||
|
"links": "Länkar",
|
||||||
|
"liveDemo": "Live demo",
|
||||||
|
"metaDescription": "Skapa enkäter och rösta för att hitta den bästa dagen eller tiden. Ett gratis alternativ till Doodle.",
|
||||||
|
"metaTitle": "Rallly - Schemalägg gruppmöten",
|
||||||
|
"mobileFriendly": "Mobil vänlig",
|
||||||
|
"mobileFriendlyDescription": "Fungerar bra på mobila enheter så att deltagarna kan svara på enkäter var de än befinner sig.",
|
||||||
|
"new": "Ny",
|
||||||
|
"noLoginRequired": "Ingen inloggning krävs",
|
||||||
|
"noLoginRequiredDescription": "Du behöver inte logga in för att skapa eller delta i en enkät",
|
||||||
|
"notifications": "Aviseringar",
|
||||||
|
"notificationsDescription": "Håll koll på vem som har svarat. Få aviseringar när deltagarna röstar eller kommenterar på din enkät.",
|
||||||
|
"openSource": "Öppen källkod",
|
||||||
|
"openSourceDescription": "Kodebasen är helt öppen källkod och är <a>tillgänglig på GitHub</a>.",
|
||||||
|
"participant": "Deltagare",
|
||||||
|
"participantCount_other": "{{count}} deltagare",
|
||||||
|
"participantCount": "{{count}} deltagare",
|
||||||
|
"perfect": "Perfekt!",
|
||||||
|
"principles": "Principer",
|
||||||
|
"principlesSubheading": "Vi är inte som de andra",
|
||||||
|
"selfHostable": "Självhostbar",
|
||||||
|
"selfHostableDescription": "Kör det på din egen server för att ta full kontroll över din data",
|
||||||
|
"timeSlots": "Tidsluckor",
|
||||||
|
"timeSlotsDescription": "Ange individuella start- och sluttider för varje alternativ i din enkät. Tiderna kan justeras automatiskt till varje deltagares tidszon eller så kan de ställas in så att tidszoner ignoreras helt."
|
||||||
|
}
|
|
@ -1,5 +1,4 @@
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { useRouter } from "next/router";
|
|
||||||
import { Trans, useTranslation } from "next-i18next";
|
import { Trans, useTranslation } from "next-i18next";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
|
|
||||||
|
@ -16,7 +15,6 @@ import { LanguageSelect } from "../poll/language-selector";
|
||||||
|
|
||||||
const Footer: React.VoidFunctionComponent = () => {
|
const Footer: React.VoidFunctionComponent = () => {
|
||||||
const { t } = useTranslation("common");
|
const { t } = useTranslation("common");
|
||||||
const router = useRouter();
|
|
||||||
return (
|
return (
|
||||||
<div className="mt-16 bg-slate-50/70">
|
<div className="mt-16 bg-slate-50/70">
|
||||||
<div className="mx-auto max-w-7xl space-y-8 p-8 lg:flex lg:space-x-16 lg:space-y-0">
|
<div className="mx-auto max-w-7xl space-y-8 p-8 lg:flex lg:space-x-16 lg:space-y-0">
|
||||||
|
@ -134,12 +132,7 @@ const Footer: React.VoidFunctionComponent = () => {
|
||||||
</div>
|
</div>
|
||||||
<div className="lg:w-2/6">
|
<div className="lg:w-2/6">
|
||||||
<div className="mb-4 font-medium">{t("language")}</div>
|
<div className="mb-4 font-medium">{t("language")}</div>
|
||||||
<LanguageSelect
|
<LanguageSelect className="mb-4 w-full" />
|
||||||
className="mb-4 w-full"
|
|
||||||
onChange={(locale) => {
|
|
||||||
router.push(router.asPath, router.asPath, { locale });
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<a
|
<a
|
||||||
href="https://github.com/lukevella/rallly/wiki/Guide-for-translators"
|
href="https://github.com/lukevella/rallly/wiki/Guide-for-translators"
|
||||||
className="inline-flex items-center rounded-md border px-3 py-2 text-xs text-slate-500"
|
className="inline-flex items-center rounded-md border px-3 py-2 text-xs text-slate-500"
|
||||||
|
|
|
@ -17,12 +17,14 @@ export const LanguageSelect: React.VoidFunctionComponent<{
|
||||||
Cookies.set("NEXT_LOCALE", e.target.value, {
|
Cookies.set("NEXT_LOCALE", e.target.value, {
|
||||||
expires: 365,
|
expires: 365,
|
||||||
});
|
});
|
||||||
|
router.push(router.asPath, router.asPath, { locale: e.target.value });
|
||||||
onChange?.(e.target.value);
|
onChange?.(e.target.value);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<option value="en">{t("english")}</option>
|
<option value="en">{t("english")}</option>
|
||||||
<option value="fr">{t("french")}</option>
|
<option value="fr">{t("french")}</option>
|
||||||
<option value="de">{t("german")}</option>
|
<option value="de">{t("german")}</option>
|
||||||
|
<option value="sv">{t("swedish")}</option>
|
||||||
</select>
|
</select>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import clsx from "clsx";
|
import clsx from "clsx";
|
||||||
import { useRouter } from "next/router";
|
|
||||||
import { useTranslation } from "next-i18next";
|
import { useTranslation } from "next-i18next";
|
||||||
import { usePlausible } from "next-plausible";
|
import { usePlausible } from "next-plausible";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
@ -13,8 +12,6 @@ const Preferences: React.VoidFunctionComponent = () => {
|
||||||
const { weekStartsOn, setWeekStartsOn, timeFormat, setTimeFormat } =
|
const { weekStartsOn, setWeekStartsOn, timeFormat, setTimeFormat } =
|
||||||
usePreferences();
|
usePreferences();
|
||||||
|
|
||||||
const router = useRouter();
|
|
||||||
|
|
||||||
const plausible = usePlausible();
|
const plausible = usePlausible();
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
@ -22,7 +19,7 @@ const Preferences: React.VoidFunctionComponent = () => {
|
||||||
<div className="grow text-sm text-slate-500">
|
<div className="grow text-sm text-slate-500">
|
||||||
{t("common:language")}
|
{t("common:language")}
|
||||||
</div>
|
</div>
|
||||||
<LanguageSelect className="w-full" onChange={() => router.reload()} />
|
<LanguageSelect className="w-full" />
|
||||||
</div>
|
</div>
|
||||||
<div className="grow space-y-2">
|
<div className="grow space-y-2">
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -2,6 +2,7 @@ import dayjs from "dayjs";
|
||||||
import de from "dayjs/locale/de";
|
import de from "dayjs/locale/de";
|
||||||
import en from "dayjs/locale/en";
|
import en from "dayjs/locale/en";
|
||||||
import fr from "dayjs/locale/fr";
|
import fr from "dayjs/locale/fr";
|
||||||
|
import sv from "dayjs/locale/sv";
|
||||||
import duration from "dayjs/plugin/duration";
|
import duration from "dayjs/plugin/duration";
|
||||||
import isBetween from "dayjs/plugin/isBetween";
|
import isBetween from "dayjs/plugin/isBetween";
|
||||||
import isSameOrBefore from "dayjs/plugin/isSameOrBefore";
|
import isSameOrBefore from "dayjs/plugin/isSameOrBefore";
|
||||||
|
@ -22,6 +23,7 @@ const dayJsLocales = {
|
||||||
de,
|
de,
|
||||||
en,
|
en,
|
||||||
fr,
|
fr,
|
||||||
|
sv,
|
||||||
};
|
};
|
||||||
|
|
||||||
dayjs.extend(localizedFormat);
|
dayjs.extend(localizedFormat);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { NextRequest, NextResponse } from "next/server";
|
import { NextRequest, NextResponse } from "next/server";
|
||||||
|
|
||||||
const supportedLocales = ["en", "de", "fr"];
|
const supportedLocales = ["en", "de", "fr", "sv"];
|
||||||
|
|
||||||
export function middleware({ headers, cookies, nextUrl }: NextRequest) {
|
export function middleware({ headers, cookies, nextUrl }: NextRequest) {
|
||||||
const locale =
|
const locale =
|
||||||
|
|
Loading…
Add table
Reference in a new issue