Translate vote components

This commit is contained in:
MartinBraquet
2026-01-02 13:45:53 +02:00
parent 0ee66a264e
commit 08d98468c5
3 changed files with 36 additions and 12 deletions

View File

@@ -5,6 +5,7 @@ import toast from 'react-hot-toast'
import {api} from 'web/lib/api'
import {useState, useEffect, useRef} from 'react'
import {useUser} from "web/hooks/use-user";
import {useT} from "web/lib/locale";
export type VoteChoice = 'for' | 'abstain' | 'against'
@@ -31,10 +32,10 @@ function VoteButton(props: {
}
const priorities = [
{label: 'Urgent', value: 3},
{label: 'High', value: 2},
{label: 'Medium', value: 1},
{label: 'Low', value: 0},
{key: "vote.urgent", label: 'Urgent', value: 3},
{key: "vote.high", label: 'High', value: 2},
{key: "vote.medium", label: 'Medium', value: 1},
{key: "vote.low", label: 'Low', value: 0},
] as const
export function VoteButtons(props: {
@@ -50,6 +51,7 @@ export function VoteButtons(props: {
const [showPriority, setShowPriority] = useState(false)
const containerRef = useRef<HTMLDivElement>(null)
const disabled = disabledProp || loading !== null
const t = useT()
// Close the dropdown when clicking outside or pressing Escape
useEffect(() => {
@@ -78,15 +80,23 @@ export function VoteButtons(props: {
try {
setLoading(choice)
if (!user) {
toast.error('Please sign in to vote')
toast.error(t('vote.sign_in_required', 'Please sign in to vote'))
return
}
await api('vote', {voteId, choice, priority})
toast.success(`Voted ${choice}${choice === 'for' ? ` with priority ${priority}` : ''}`)
const choiceLabel = t(
`vote.${choice}`,
choice === 'for' ? 'For' : choice === 'abstain' ? 'Abstain' : 'Against'
)
let votedMsg = `${t('vote.voted', 'Voted')} ${choiceLabel}`
if (choice === 'for') {
votedMsg += ` ${t('vote.with_priority', 'with priority')} ${priority}`
}
toast.success(votedMsg)
await onVoted?.()
} catch (e) {
console.error(e)
toast.error('Failed to vote — please try again')
toast.error(t('vote.failed', 'Failed to vote — please try again'))
} finally {
setLoading(null)
}
@@ -108,7 +118,7 @@ export function VoteButtons(props: {
<VoteButton
color={clsx('bg-green-700 text-white hover:bg-green-500')}
count={counts.for}
title={'For'}
title={t('vote.for', 'For')}
disabled={disabled}
onClick={() => handleVote('for')}
/>
@@ -129,7 +139,7 @@ export function VoteButtons(props: {
await sendVote('for', p.value)
}}
>
{p.label} priority
{t(p.key, p.label)}
</button>
))}
</div>
@@ -138,14 +148,14 @@ export function VoteButtons(props: {
<VoteButton
color={clsx('bg-yellow-700 text-white hover:bg-yellow-500')}
count={counts.abstain}
title={'Abstain'}
title={t('vote.abstain', 'Abstain')}
disabled={disabled}
onClick={() => handleVote('abstain')}
/>
<VoteButton
color={clsx('bg-red-700 text-white hover:bg-red-500')}
count={counts.against}
title={'Against'}
title={t('vote.against', 'Against')}
disabled={disabled}
onClick={() => handleVote('against')}
/>

View File

@@ -7,6 +7,7 @@ import {VoteButtons} from 'web/components/votes/vote-buttons'
import Link from "next/link";
import {STATUS_CHOICES} from "common/votes/constants";
import {useUserInStore} from "web/hooks/use-user-supabase";
import {useT} from 'web/lib/locale'
export type Vote = rowFor<'votes'> & {
votes_for: number
@@ -32,6 +33,7 @@ export function VoteItem(props: {
onVoted?: () => void | Promise<void>
}) {
const {vote, onVoted} = props
const t = useT()
// console.debug('creator', creator, vote)
return (
<Col className={'mb-4 rounded-lg border border-canvas-200 p-4'}>
@@ -42,7 +44,7 @@ export function VoteItem(props: {
<Content className="w-full" content={vote.description as JSONContent}/>
</Col>
<Row className={'gap-2 mt-2 items-center justify-between w-full custom-link flex-wrap'}>
{!!vote.priority ? <div>Priority: {vote.priority.toFixed(0)}%</div> : <p></p>}
{!!vote.priority ? <div>{t('vote.priority', 'Priority')}: {vote.priority.toFixed(0)}%</div> : <p></p>}
{!vote.is_anonymous && <Username creatorId={vote.creator_id}/>}
</Row>
</Col>

View File

@@ -149,6 +149,18 @@
"vote.toast.create_failed": "Échec de la création de la proposition — réessayez ou contactez-nous...",
"vote.toast.created": "Proposition créée",
"vote.creator.placeholder": "Veuillez décrire votre proposition ici",
"vote.sign_in_required": "Veuillez vous connecter pour voter",
"vote.voted": "Vote enregistré",
"vote.with_priority": "avec priorité",
"vote.failed": "Échec du vote — veuillez réessayer",
"vote.for": "Pour",
"vote.abstain": "Abstention",
"vote.against": "Contre",
"vote.priority": "Priorité",
"vote.urgent": "Urgent",
"vote.high": "Haute",
"vote.medium": "Moyenne",
"vote.low": "Faible",
"signin.seo.title": "Se connecter",
"signin.seo.description": "Connectez-vous à votre compte",
"signin.title": "Se connecter",