mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-10-01 07:37:55 -05:00
Add translations
This commit is contained in:
2
TODO.md
2
TODO.md
@@ -19,7 +19,7 @@ Calendar
|
||||
- [x] Winners on the event info page
|
||||
- [x] There should be a banner on the list page if you have past tournaments to report
|
||||
- [x] On the user page tab showing past results
|
||||
- [ ] Translations
|
||||
- [x] Translations
|
||||
|
||||
## Other
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { useActionData } from "@remix-run/react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
export function FormErrors() {
|
||||
export function FormErrors({ namespace }: { namespace: "calendar" }) {
|
||||
const { t } = useTranslation(["common", namespace]);
|
||||
const actionData = useActionData<{ errors?: string[] }>();
|
||||
|
||||
if (!actionData?.errors || actionData.errors.length === 0) {
|
||||
@@ -9,10 +11,10 @@ export function FormErrors() {
|
||||
|
||||
return (
|
||||
<div className="form-errors">
|
||||
<h4>Following errors need to be fixed:</h4>
|
||||
<h4>{t("common:forms.errors.title")}:</h4>
|
||||
<ol>
|
||||
{actionData.errors.map((error) => (
|
||||
<li key={error}>{error}</li>
|
||||
<li key={error}>{t(`${namespace}:${error}` as any)}</li>
|
||||
))}
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
@@ -73,7 +73,7 @@ export const loader = async ({ params, request }: LoaderArgs) => {
|
||||
export default function CalendarEventPage() {
|
||||
const user = useUser();
|
||||
const data = useLoaderData<typeof loader>();
|
||||
const { i18n } = useTranslation();
|
||||
const { i18n, t } = useTranslation(["common", "calendar"]);
|
||||
const isMounted = useIsMounted();
|
||||
|
||||
return (
|
||||
@@ -87,7 +87,9 @@ export default function CalendarEventPage() {
|
||||
hidden: data.event.startTimes.length === 1,
|
||||
})}
|
||||
>
|
||||
Day {i + 1}
|
||||
{t("calendar:day", {
|
||||
number: i + 1,
|
||||
})}
|
||||
</span>
|
||||
<time dateTime={databaseTimestampToDate(startTime).toISOString()}>
|
||||
{isMounted
|
||||
@@ -136,7 +138,7 @@ export default function CalendarEventPage() {
|
||||
to={calendarEditPage(data.event.eventId)}
|
||||
data-cy="edit-button"
|
||||
>
|
||||
Edit
|
||||
{t("common:actions.edit")}
|
||||
</LinkButton>
|
||||
)}
|
||||
{canReportCalendarEventWinners({
|
||||
@@ -149,7 +151,7 @@ export default function CalendarEventPage() {
|
||||
to={calendarReportWinnersPage(data.event.eventId)}
|
||||
data-cy="edit-button"
|
||||
>
|
||||
Report winners
|
||||
{t("calendar:actions.reportWinners")}
|
||||
</LinkButton>
|
||||
)}
|
||||
</div>
|
||||
@@ -162,29 +164,32 @@ export default function CalendarEventPage() {
|
||||
}
|
||||
|
||||
function Results() {
|
||||
const { t } = useTranslation(["common", "calendar"]);
|
||||
const data = useLoaderData<typeof loader>();
|
||||
|
||||
if (!data.results.length) return null;
|
||||
|
||||
return (
|
||||
<Section title="Results" className="event__results-section">
|
||||
<div className="event__results-participant-count">
|
||||
{data.event.participantCount} teams participated
|
||||
</div>
|
||||
<Section title={t("calendar:results")} className="event__results-section">
|
||||
{data.event.participantCount && (
|
||||
<div className="event__results-participant-count">
|
||||
{t("calendar:participatedCount", {
|
||||
count: data.event.participantCount,
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Placing</th>
|
||||
<th>Name</th>
|
||||
<th>Members</th>
|
||||
<th>{t("calendar:forms.team.placing")}</th>
|
||||
<th>{t("common:forms.name")}</th>
|
||||
<th>{t("calendar:members")}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{data.results.map((result, i) => (
|
||||
<tr key={i}>
|
||||
<td className="text-center">
|
||||
{placementString(result.placement)}
|
||||
</td>
|
||||
<td className="pl-4">{placementString(result.placement)}</td>
|
||||
<td>{result.teamName}</td>
|
||||
<td>
|
||||
<ul className="event__results-players">
|
||||
@@ -221,10 +226,11 @@ function Results() {
|
||||
}
|
||||
|
||||
function Description() {
|
||||
const { t } = useTranslation();
|
||||
const data = useLoaderData<typeof loader>();
|
||||
|
||||
return (
|
||||
<Section title="Description">
|
||||
<Section title={t("forms.description")}>
|
||||
<div className="stack sm">
|
||||
<div className="event__author">
|
||||
<Avatar
|
||||
|
||||
@@ -28,6 +28,7 @@ import { FormErrors } from "~/components/FormErrors";
|
||||
import type { UseDataFunctionReturn } from "@remix-run/react/dist/components";
|
||||
import type { Unpacked } from "~/utils/types";
|
||||
import { calendarEventPage } from "~/utils/urls";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
const playersSchema = z
|
||||
.array(
|
||||
@@ -36,7 +37,7 @@ const playersSchema = z
|
||||
z.object({ id }),
|
||||
])
|
||||
)
|
||||
.nonempty({ message: "Each team must have at least one player." })
|
||||
.nonempty({ message: "forms.errors.emptyTeam" })
|
||||
.max(CALENDAR_EVENT_RESULT.MAX_PLAYERS_LENGTH)
|
||||
.refine(
|
||||
(val) => {
|
||||
@@ -47,7 +48,7 @@ const playersSchema = z
|
||||
return userIds.length === new Set(userIds).size;
|
||||
},
|
||||
{
|
||||
message: "Can't have the same player twice in the same team.",
|
||||
message: "forms.errors.duplicatePlayer",
|
||||
}
|
||||
);
|
||||
|
||||
@@ -85,7 +86,7 @@ const reportWinnersActionSchema = z.object({
|
||||
)
|
||||
.refine(
|
||||
(val) => val.length === new Set(val.map((team) => team.teamName)).size,
|
||||
{ message: "Each team needs a unique name." }
|
||||
{ message: "forms.errors.uniqueTeamName" }
|
||||
)
|
||||
),
|
||||
});
|
||||
@@ -149,34 +150,37 @@ export const loader = async ({ request, params }: LoaderArgs) => {
|
||||
};
|
||||
|
||||
export default function ReportWinnersPage() {
|
||||
const { t } = useTranslation(["common", "calendar"]);
|
||||
const data = useLoaderData<typeof loader>();
|
||||
|
||||
return (
|
||||
<Main halfWidth>
|
||||
<Form method="post" className="stack smedium items-start">
|
||||
<h1 className="text-lg">Reporting results of {data.name}</h1>
|
||||
<h1 className="text-lg">
|
||||
{t("calendar:forms.reportResultsHeader", { eventName: data.name })}
|
||||
</h1>
|
||||
<ParticipantsCountInput />
|
||||
<FormMessage type="info">
|
||||
You choose how many results to report. It can be just the winning
|
||||
team, top 3 or whatever you decide.
|
||||
{t("calendar:forms.reportResultsInfo")}
|
||||
</FormMessage>
|
||||
<TeamInputs />
|
||||
<Button type="submit" className="mt-4">
|
||||
Submit
|
||||
{t("common:actions.submit")}
|
||||
</Button>
|
||||
<FormErrors />
|
||||
<FormErrors namespace="calendar" />
|
||||
</Form>
|
||||
</Main>
|
||||
);
|
||||
}
|
||||
|
||||
function ParticipantsCountInput() {
|
||||
const { t } = useTranslation("calendar");
|
||||
const data = useLoaderData<typeof loader>();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Label htmlFor="name" required>
|
||||
Participant count
|
||||
{t("forms.participantCount")}
|
||||
</Label>
|
||||
<input
|
||||
name="participantCount"
|
||||
@@ -193,6 +197,7 @@ function ParticipantsCountInput() {
|
||||
}
|
||||
|
||||
function TeamInputs() {
|
||||
const { t } = useTranslation("calendar");
|
||||
const data = useLoaderData<typeof loader>();
|
||||
const [amountOfTeams, setAmountOfTeams] = React.useState(
|
||||
Math.max(data.winners.length, 1)
|
||||
@@ -229,7 +234,7 @@ function TeamInputs() {
|
||||
onClick={() => setAmountOfTeams((amountOfTeams) => amountOfTeams + 1)}
|
||||
tiny
|
||||
>
|
||||
Add team
|
||||
{t("forms.team.add")}
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
@@ -259,6 +264,7 @@ function Team({
|
||||
initialPlacement: string;
|
||||
initialValues?: Unpacked<UseDataFunctionReturn<typeof loader>["winners"]>;
|
||||
}) {
|
||||
const { t } = useTranslation("calendar");
|
||||
const teamNameId = React.useId();
|
||||
const placementId = React.useId();
|
||||
|
||||
@@ -296,7 +302,7 @@ function Team({
|
||||
/>
|
||||
<div className="stack horizontal md flex-wrap">
|
||||
<div>
|
||||
<Label htmlFor={teamNameId}>Team name</Label>
|
||||
<Label htmlFor={teamNameId}>{t("forms.team.name")}</Label>
|
||||
<input
|
||||
id={teamNameId}
|
||||
value={results.teamName}
|
||||
@@ -306,7 +312,7 @@ function Team({
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Label htmlFor={placementId}>Placement</Label>
|
||||
<Label htmlFor={placementId}>{t("forms.team.placing")}</Label>
|
||||
<input
|
||||
id={placementId}
|
||||
value={results.placement}
|
||||
@@ -329,7 +335,7 @@ function Team({
|
||||
variant="minimal-destructive"
|
||||
className="mt-4"
|
||||
>
|
||||
Remove team
|
||||
{t("forms.team.remove")}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
@@ -343,6 +349,7 @@ function Players({
|
||||
players: TeamResults["players"];
|
||||
setPlayers: (newPlayers: TeamResults["players"]) => void;
|
||||
}) {
|
||||
const { t } = useTranslation("calendar");
|
||||
const handleAddPlayer = () => {
|
||||
setPlayers([...players, NEW_PLAYER]);
|
||||
};
|
||||
@@ -374,14 +381,16 @@ function Players({
|
||||
<div key={i}>
|
||||
<div className="stack horizontal md items-center mb-1">
|
||||
<label htmlFor={formId} className="mb-0">
|
||||
Player {i + 1}
|
||||
{t("forms.team.player.header", { number: i + 1 })}
|
||||
</label>
|
||||
<Button
|
||||
tiny
|
||||
variant="minimal"
|
||||
onClick={() => handlePlayerInputTypeChange(i)}
|
||||
>
|
||||
{asPlainInput ? "Add as user (recommended)" : "Add as text"}
|
||||
{asPlainInput
|
||||
? t("forms.team.player.addAsUser")
|
||||
: t("forms.team.player.addAsText")}
|
||||
</Button>
|
||||
</div>
|
||||
{asPlainInput ? (
|
||||
@@ -414,7 +423,7 @@ function Players({
|
||||
disabled={players.length === CALENDAR_EVENT_RESULT.MAX_PLAYERS_LENGTH}
|
||||
variant="outlined"
|
||||
>
|
||||
Add player
|
||||
{t("forms.team.player.add")}
|
||||
</Button>{" "}
|
||||
<Button
|
||||
tiny
|
||||
@@ -422,7 +431,7 @@ function Players({
|
||||
onClick={handleRemovePlayer}
|
||||
disabled={players.length === 1}
|
||||
>
|
||||
Remove player
|
||||
{t("forms.team.player.remove")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -129,6 +129,7 @@ function fetchEventsOfWeek(args: { week: number; year: number }) {
|
||||
}
|
||||
|
||||
export default function CalendarPage() {
|
||||
const { t } = useTranslation("calendar");
|
||||
const data = useLoaderData<typeof loader>();
|
||||
const user = useUser();
|
||||
const isMounted = useIsMounted();
|
||||
@@ -150,7 +151,7 @@ export default function CalendarPage() {
|
||||
<div className="stack md">
|
||||
{user && (
|
||||
<LinkButton to="new" className="calendar__add-new-button" tiny>
|
||||
Add new
|
||||
{t("addNew")}
|
||||
</LinkButton>
|
||||
)}
|
||||
{isMounted ? (
|
||||
@@ -159,13 +160,13 @@ export default function CalendarPage() {
|
||||
<>
|
||||
<EventsList events={thisWeeksEvents} />
|
||||
<div className="calendar__time-zone-info">
|
||||
All times in your local time zone:{" "}
|
||||
{t("inYourTimeZone")}{" "}
|
||||
{Intl.DateTimeFormat().resolvedOptions().timeZone}
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<h2 className="calendar__no-events" data-cy="no-events">
|
||||
No events this week
|
||||
{t("noEvents")}
|
||||
</h2>
|
||||
)}
|
||||
</>
|
||||
@@ -230,23 +231,24 @@ function WeekLinkTitle({
|
||||
}: {
|
||||
week: Unpacked<UseDataFunctionReturn<typeof loader>["weeks"]>;
|
||||
}) {
|
||||
const { t } = useTranslation("calendar");
|
||||
const data = useLoaderData<typeof loader>();
|
||||
const { i18n } = useTranslation();
|
||||
|
||||
const relativeWeekIdentifier =
|
||||
week.number === data.currentWeek
|
||||
? "This"
|
||||
? t("week.this")
|
||||
: week.number - data.currentWeek === 1
|
||||
? "Next"
|
||||
? t("week.next")
|
||||
: week.number - data.currentWeek === -1
|
||||
? "Last"
|
||||
? t("week.last")
|
||||
: null;
|
||||
|
||||
if (relativeWeekIdentifier) {
|
||||
return (
|
||||
<div className="stack xxs">
|
||||
<div>{relativeWeekIdentifier}</div>
|
||||
<div>Week</div>
|
||||
<div>{t("week.week")}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -292,21 +294,18 @@ function getEventsCountPerWeek(
|
||||
}
|
||||
|
||||
function EventsToReport() {
|
||||
const { t } = useTranslation("calendar");
|
||||
const data = useLoaderData<typeof loader>();
|
||||
|
||||
if (data.eventsToReport.length === 0) return null;
|
||||
|
||||
return (
|
||||
<Alert textClassName="calendar__events-to-report">
|
||||
You can report results for{" "}
|
||||
{t("reportResults")}{" "}
|
||||
{data.eventsToReport.map((event, i) => (
|
||||
<React.Fragment key={event.id}>
|
||||
<Link to={calendarReportWinnersPage(event.id)}>{event.name}</Link>
|
||||
{i === data.eventsToReport.length - 1
|
||||
? ""
|
||||
: i === data.eventsToReport.length - 2
|
||||
? " and "
|
||||
: ", "}
|
||||
{i === data.eventsToReport.length - 1 ? "" : ", "}
|
||||
</React.Fragment>
|
||||
))}
|
||||
</Alert>
|
||||
@@ -318,7 +317,7 @@ function EventsList({
|
||||
}: {
|
||||
events: UseDataFunctionReturn<typeof loader>["events"];
|
||||
}) {
|
||||
const { i18n } = useTranslation();
|
||||
const { t, i18n } = useTranslation("calendar");
|
||||
|
||||
return (
|
||||
<div className="calendar__events-container">
|
||||
@@ -374,7 +373,9 @@ function EventsList({
|
||||
{calendarEvent.name}{" "}
|
||||
{calendarEvent.nthAppearance > 1 ? (
|
||||
<span className="calendar__event__day">
|
||||
Day {calendarEvent.nthAppearance}
|
||||
{t("day", {
|
||||
number: calendarEvent.nthAppearance,
|
||||
})}
|
||||
</span>
|
||||
) : null}
|
||||
</h2>
|
||||
|
||||
@@ -215,12 +215,13 @@ export default function CalendarNewEventPage() {
|
||||
}
|
||||
|
||||
function NameInput() {
|
||||
const { t } = useTranslation();
|
||||
const { eventToEdit } = useLoaderData<typeof loader>();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Label htmlFor="name" required>
|
||||
Name
|
||||
{t("forms.name")}
|
||||
</Label>
|
||||
<input
|
||||
name="name"
|
||||
@@ -235,6 +236,7 @@ function NameInput() {
|
||||
}
|
||||
|
||||
function DescriptionTextarea() {
|
||||
const { t } = useTranslation();
|
||||
const { eventToEdit } = useLoaderData<typeof loader>();
|
||||
const [value, setValue] = React.useState(eventToEdit?.description ?? "");
|
||||
|
||||
@@ -247,7 +249,7 @@ function DescriptionTextarea() {
|
||||
max: CALENDAR_EVENT.DESCRIPTION_MAX_LENGTH,
|
||||
}}
|
||||
>
|
||||
Description
|
||||
{t("forms.description")}
|
||||
</Label>
|
||||
<textarea
|
||||
id="description"
|
||||
@@ -262,6 +264,7 @@ function DescriptionTextarea() {
|
||||
}
|
||||
|
||||
function DatesInput() {
|
||||
const { t } = useTranslation(["common", "calendar"]);
|
||||
const { eventToEdit } = useLoaderData<typeof loader>();
|
||||
const [datesCount, setDatesCount] = React.useState(
|
||||
eventToEdit?.startTimes.length ?? 1
|
||||
@@ -276,7 +279,7 @@ function DatesInput() {
|
||||
<div className="stack md items-start">
|
||||
<div>
|
||||
<Label htmlFor="date" required>
|
||||
Dates
|
||||
{t("calendar:forms.dates")}
|
||||
</Label>
|
||||
<div className="stack sm">
|
||||
{new Array(datesCount).fill(null).map((_, i) => {
|
||||
@@ -307,7 +310,7 @@ function DatesInput() {
|
||||
onClick={() => setDatesCount((count) => count + 1)}
|
||||
data-cy="add-date-button"
|
||||
>
|
||||
Add
|
||||
{t("common:actions.add")}
|
||||
</Button>
|
||||
{datesCount > 1 && (
|
||||
<Button
|
||||
@@ -316,7 +319,7 @@ function DatesInput() {
|
||||
data-cy="remove-date-button"
|
||||
variant="destructive"
|
||||
>
|
||||
Remove
|
||||
{t("common:actions.remove")}
|
||||
</Button>
|
||||
)}
|
||||
</>
|
||||
@@ -326,7 +329,7 @@ function DatesInput() {
|
||||
})}
|
||||
</div>
|
||||
<FormMessage type="info" className={clsx({ invisible: !isMounted })}>
|
||||
Times in your local time zone: {usersTimeZone}
|
||||
{t("calendar:inYourTimeZone")} {usersTimeZone}
|
||||
</FormMessage>
|
||||
</div>
|
||||
</div>
|
||||
@@ -334,12 +337,13 @@ function DatesInput() {
|
||||
}
|
||||
|
||||
function BracketUrlInput() {
|
||||
const { t } = useTranslation("calendar");
|
||||
const { eventToEdit } = useLoaderData<typeof loader>();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Label htmlFor="bracketUrl" required>
|
||||
Bracket URL
|
||||
{t("forms.bracketUrl")}
|
||||
</Label>
|
||||
<input
|
||||
name="bracketUrl"
|
||||
@@ -354,11 +358,12 @@ function BracketUrlInput() {
|
||||
}
|
||||
|
||||
function DiscordLinkInput() {
|
||||
const { t } = useTranslation("calendar");
|
||||
const { eventToEdit } = useLoaderData<typeof loader>();
|
||||
|
||||
return (
|
||||
<div className="stack items-start">
|
||||
<Label htmlFor="discordInviteCode">Discord server invite URL</Label>
|
||||
<Label htmlFor="discordInviteCode">{t("forms.discordInvite")}</Label>
|
||||
<Input
|
||||
name="discordInviteCode"
|
||||
leftAddon="https://discord.gg/"
|
||||
@@ -371,8 +376,8 @@ function DiscordLinkInput() {
|
||||
}
|
||||
|
||||
function TagsAdder() {
|
||||
const { eventToEdit } = useLoaderData<typeof loader>();
|
||||
const { t } = useTranslation("calendar");
|
||||
const { eventToEdit } = useLoaderData<typeof loader>();
|
||||
const [tags, setTags] = React.useState(
|
||||
(eventToEdit?.tags ?? []) as Array<CalendarEventTag>
|
||||
);
|
||||
@@ -390,7 +395,7 @@ function TagsAdder() {
|
||||
value={JSON.stringify(tags.length > 0 ? tags : null)}
|
||||
/>
|
||||
<div>
|
||||
<label htmlFor={id}>Tags</label>
|
||||
<label htmlFor={id}>{t("forms.tags")}</label>
|
||||
<select
|
||||
id={id}
|
||||
className="calendar-new__select"
|
||||
@@ -399,16 +404,14 @@ function TagsAdder() {
|
||||
}
|
||||
data-cy="tags-select"
|
||||
>
|
||||
<option value="">Choose a tag</option>
|
||||
<option value="">{t("forms.tags.placeholder")}</option>
|
||||
{tagsForSelect.map((tag) => (
|
||||
<option key={tag} value={tag}>
|
||||
{t(`tag.name.${tag}`)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<FormMessage type="info">
|
||||
"Badge prizes" tag is added automatically if applicable
|
||||
</FormMessage>
|
||||
<FormMessage type="info">{t("forms.tags.info")}</FormMessage>
|
||||
</div>
|
||||
<Tags
|
||||
tags={tags}
|
||||
@@ -421,6 +424,7 @@ function TagsAdder() {
|
||||
}
|
||||
|
||||
function BadgesAdder() {
|
||||
const { t } = useTranslation("calendar");
|
||||
const { eventToEdit } = useLoaderData<typeof loader>();
|
||||
const { managedBadges } = useLoaderData<typeof loader>();
|
||||
const [badges, setBadges] = React.useState(eventToEdit?.badges ?? []);
|
||||
@@ -448,7 +452,7 @@ function BadgesAdder() {
|
||||
<div className="stack md">
|
||||
{input}
|
||||
<div>
|
||||
<label htmlFor={id}>Badge prizes</label>
|
||||
<label htmlFor={id}>{t("forms.badges")}</label>
|
||||
<select
|
||||
id={id}
|
||||
className="calendar-new__select"
|
||||
@@ -462,7 +466,7 @@ function BadgesAdder() {
|
||||
}}
|
||||
data-cy="badges-select"
|
||||
>
|
||||
<option value="">Choose a badge prize</option>
|
||||
<option value="">{t("forms.badges.placeholder")}</option>
|
||||
{badgesForSelect.map((badge) => (
|
||||
<option key={badge.id} value={badge.id}>
|
||||
{badge.displayName}
|
||||
|
||||
@@ -29,9 +29,7 @@ export default function UserResultsPage() {
|
||||
<tbody>
|
||||
{data.results.map((result) => (
|
||||
<tr key={result.eventId}>
|
||||
<td className="text-center">
|
||||
{placementString(result.placement)}
|
||||
</td>
|
||||
<td className="pl-4">{placementString(result.placement)}</td>
|
||||
<td>{result.teamName}</td>
|
||||
<td>
|
||||
<Link to={calendarEventPage(result.eventId)}>
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
width: var(--s-24);
|
||||
}
|
||||
|
||||
.pl-4 {
|
||||
padding-inline-start: var(--s-4);
|
||||
}
|
||||
|
||||
.mt-2 {
|
||||
margin-block-start: var(--s-2);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,46 @@
|
||||
{
|
||||
"inYourTimeZone": "Times in your local time zone:",
|
||||
"addNew": "Add new",
|
||||
"noEvents": "No events this week",
|
||||
"reportResults": "You can report results:",
|
||||
"day": "Day {{number}}",
|
||||
"actions.reportWinners": "Report winners",
|
||||
"participatedCount": "{{count}} teams participated",
|
||||
"members": "Members",
|
||||
"results": "Results",
|
||||
|
||||
"forms.dates": "Dates",
|
||||
"forms.bracketUrl": "Bracket URL",
|
||||
"forms.discordInvite": "Discord server invite URL",
|
||||
"forms.tags": "Tags",
|
||||
"forms.tags.placeholder": "Choose a tag",
|
||||
"forms.tags.info": "\"Badge prizes\" tag is added automatically if applicable",
|
||||
"forms.badges": "Badge prizes",
|
||||
"forms.badges.placeholder": "Choose a badge prize",
|
||||
|
||||
"forms.participantCount": "Participant count",
|
||||
"forms.reportResultsHeader": "Reporting results for {{eventName}}",
|
||||
"forms.reportResultsInfo": "You choose how many results to report. It can be just the winning team, top 3 or whatever you decide.",
|
||||
"forms.team.add": "Add team",
|
||||
"forms.team.remove": "Remove team",
|
||||
"forms.team.name": "Team name",
|
||||
"forms.team.placing": "Placing",
|
||||
|
||||
"forms.team.player.header": "Player {{number}}",
|
||||
"forms.team.player.add": "Add player",
|
||||
"forms.team.player.remove": "Remove player",
|
||||
"forms.team.player.addAsUser": "Add as user (recommended)",
|
||||
"forms.team.player.addAsText": "Add as text",
|
||||
|
||||
"forms.errors.uniqueTeamName": "Each team needs a unique name.",
|
||||
"forms.errors.duplicatePlayer": "Can't have the same player twice in the same team.",
|
||||
"forms.errors.emptyTeam": "Each team must have at least one player.",
|
||||
|
||||
"week.this": "This",
|
||||
"week.next": "Next",
|
||||
"week.last": "Last",
|
||||
"week.week": "Week",
|
||||
|
||||
"tag.name.BADGE": "Badge prizes",
|
||||
"tag.name.SPECIAL": "Special rules",
|
||||
"tag.name.ART": "Art prizes",
|
||||
|
||||
@@ -18,7 +18,14 @@
|
||||
|
||||
"actions.save": "Save",
|
||||
"actions.saving": "Saving...",
|
||||
"actions.submit": "Submit",
|
||||
"actions.edit": "Edit",
|
||||
"actions.add": "Add",
|
||||
"actions.remove": "Remove",
|
||||
|
||||
"results": "Results"
|
||||
"results": "Results",
|
||||
|
||||
"forms.name": "Name",
|
||||
"forms.description": "Description",
|
||||
"forms.errors.title": "Following errors need to be fixed"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user