diff --git a/front_end/messages/cs.json b/front_end/messages/cs.json index 9f107199cc..6687764fe6 100644 --- a/front_end/messages/cs.json +++ b/front_end/messages/cs.json @@ -718,5 +718,9 @@ "xTwitter": "X / Twitter", "copyFromBranch": "kopie z {branch}", "parentResolvesAsYes": "Rodič vyřeší jako Ano", - "parentResolvesAsNo": "Rodič se rozhodne jako Ne" + "parentResolvesAsNo": "Rodič se rozhodne jako Ne", + "othersCount": "{count} ostatní", + "selectAll": "vybrat vše", + "deselectAll": "zrušit výběr všech", + "forecastDataIsEmpty": "Údaje o prognóze jsou prázdné" } diff --git a/front_end/messages/en.json b/front_end/messages/en.json index b6e794a8e5..55ac061304 100644 --- a/front_end/messages/en.json +++ b/front_end/messages/en.json @@ -729,5 +729,10 @@ "xTwitter": "X / Twitter", "copyFromBranch": "copy from {branch}", "parentResolvesAsYes": "Parent Resolves as Yes", - "parentResolvesAsNo": "Parent Resolves as No" + "parentResolvesAsNo": "Parent Resolves as No", + "othersCount": "{count} others", + "selectAll": "select all", + "deselectAll": "deselect all", + "forecastDataIsEmpty": "Forecast data is empty", + "createdByUserOnDate": "Created by {user} on {date}" } diff --git a/front_end/messages/zh.json b/front_end/messages/zh.json index fe889ae77b..85d710361e 100644 --- a/front_end/messages/zh.json +++ b/front_end/messages/zh.json @@ -49,8 +49,6 @@ "resolutionAnnulled": "已廢止", "resolutionPending": "待解決", "resolution": "解決", - "Yes": "如果是", - "No": "如果沒有", "pendingResolution": "待解決", "forecastTimelineHeading": "預測時間線", "totalPredictionsLabel": "總預測", @@ -711,5 +709,9 @@ "xTwitter": "X / Twitter", "copyFromBranch": "從{branch}複製", "parentResolvesAsYes": "家長決定是", - "parentResolvesAsNo": "家長決定不" + "parentResolvesAsNo": "家長決定不", + "othersCount": "{count}其他", + "selectAll": "選擇全部", + "deselectAll": "取消全選", + "forecastDataIsEmpty": "預測資料為空" } diff --git a/front_end/src/app/(main)/questions/[id]/components/choices_legend/index.tsx b/front_end/src/app/(main)/questions/[id]/components/choices_legend/index.tsx index 20aba42bc3..746a09307e 100644 --- a/front_end/src/app/(main)/questions/[id]/components/choices_legend/index.tsx +++ b/front_end/src/app/(main)/questions/[id]/components/choices_legend/index.tsx @@ -2,6 +2,7 @@ import { faChevronDown } from "@fortawesome/free-solid-svg-icons"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { Popover, PopoverButton, PopoverPanel } from "@headlessui/react"; import classNames from "classnames"; +import { useTranslations } from "next-intl"; import React, { FC, useMemo } from "react"; import Button from "@/components/ui/button"; @@ -25,6 +26,7 @@ const ChoicesLegend: FC = ({ onToggleAll, maxLegendChoices, }) => { + const t = useTranslations() const { legendChoices, dropdownChoices } = useMemo( () => ({ legendChoices: choices.slice(0, maxLegendChoices), @@ -66,7 +68,7 @@ const ChoicesLegend: FC = ({ "bg-gray-300 dark:bg-gray-300-dark": open, })} > - Others ({dropdownChoices.length}) + {t("othersCount", {count: dropdownChoices.length})} = ({ onToggleAll(areAllSelected)} - label={areAllSelected ? "Deselect All" : "Select All"} - className="p-1.5" + label={areAllSelected ? t("deselectAll") : t("selectAll")} + className="p-1.5 capitalize" /> {dropdownChoices.map(({ choice, color, active }, idx) => ( = Math.min(...timestamps) + : cursorTimestamp >= Math.min(...timestamps) && + cursorTimestamp <= Math.max(...timestamps); + if (!hasValue) { + return getForecastPctDisplayValue(null); + } + if (isUserPrediction) { + let closestTimestampIndex = 0; + timestamps.forEach((timestamp, index) => { + if (cursorTimestamp >= timestamp) { + closestTimestampIndex = index; + } + }); + return getForecastPctDisplayValue(values[closestTimestampIndex]); + } + const closestTimestamp = findPreviousTimestamp(timestamps, cursorTimestamp); + const cursorIndex = timestamps.findIndex( + (timestamp) => timestamp === closestTimestamp + ); -const generateList = ( + return getForecastPctDisplayValue(values[cursorIndex]); +} + +function generateList( questions: QuestionWithNumericForecasts[], preselectedQuestionId?: number -) => - generateChoiceItemsFromBinaryGroup(questions, { +) { + return generateChoiceItemsFromBinaryGroup(questions, { withMinMax: true, activeCount: MAX_VISIBLE_CHECKBOXES, preselectedQuestionId, }); +} + +type Props = { + questions: QuestionWithNumericForecasts[]; + timestamps: number[]; + preselectedQuestionId?: number; +}; const BinaryGroupChart: FC = ({ questions, @@ -200,34 +232,4 @@ const BinaryGroupChart: FC = ({ ); }; -function getQuestionTooltipLabel( - timestamps: number[], - values: number[], - cursorTimestamp: number, - isUserPrediction: boolean = false -) { - const hasValue = isUserPrediction - ? cursorTimestamp >= Math.min(...timestamps) - : cursorTimestamp >= Math.min(...timestamps) && - cursorTimestamp <= Math.max(...timestamps); - if (!hasValue) { - return getForecastPctDisplayValue(null); - } - if (isUserPrediction) { - let closestTimestampIndex = 0; - timestamps.forEach((timestamp, index) => { - if (cursorTimestamp >= timestamp) { - closestTimestampIndex = index; - } - }); - return getForecastPctDisplayValue(values[closestTimestampIndex]); - } - const closestTimestamp = findPreviousTimestamp(timestamps, cursorTimestamp); - const cursorIndex = timestamps.findIndex( - (timestamp) => timestamp === closestTimestamp - ); - - return getForecastPctDisplayValue(values[cursorIndex]); -} - export default BinaryGroupChart; diff --git a/front_end/src/components/comment_feed/index.tsx b/front_end/src/components/comment_feed/index.tsx index 87676ec287..7bcba20264 100644 --- a/front_end/src/components/comment_feed/index.tsx +++ b/front_end/src/components/comment_feed/index.tsx @@ -277,7 +277,7 @@ const CommentFeed: FC = ({ postData, postPermissions, profileId }) => { - {totalCount} comments + {totalCount ? `${totalCount} ` : ""}{t("commentsWithCount", { count: totalCount })} {postId && ( = ({ authorUsername, curationStatus, }) => { + const t = useTranslations(); const { user } = useAuth(); if (curationStatus === PostStatus.PENDING) { return ( -
{`Created by ${authorUsername} on ${question.created_at.slice(0, 7)}`}
+
+ {t("createdByUserOnDate", { + user: authorUsername, + date: question.created_at.slice(0, 7), + })} +
); } - const isForecastEmpty = - question.aggregations.recency_weighted.history.length === 0; - if (isForecastEmpty) { - return
Forecasts data is empty
; + if (question.aggregations.recency_weighted.history.length === 0) { + return
{t("forecastDataIsEmpty")}
; } const defaultChartZoom: TimelineChartZoomOption = user