mirror of
https://github.com/CompassConnections/Compass.git
synced 2026-05-09 15:44:55 -04:00
Translate messages
This commit is contained in:
@@ -12,6 +12,7 @@ import {useClickOutside} from "web/hooks/use-click-outside"
|
||||
import {PrivateChatMessage} from "common/chat-message";
|
||||
import {updateReactionUI} from "web/lib/supabase/chat-messages";
|
||||
import {useIsMobile} from "web/hooks/use-is-mobile";
|
||||
import {useT} from 'web/lib/locale'
|
||||
|
||||
const REACTIONS = ['👍', '❤️', '😂', '😮', '😢', '👎']
|
||||
|
||||
@@ -37,6 +38,7 @@ export function MessageActions(props: {
|
||||
const user = useUser()
|
||||
const isOwner = user?.id === message.userId
|
||||
const isMobile = useIsMobile()
|
||||
const t = useT()
|
||||
|
||||
useClickOutside(emojiPickerRef, () => {
|
||||
setShowEmojiPicker(false)
|
||||
@@ -50,17 +52,17 @@ export function MessageActions(props: {
|
||||
}, [openEmojiPickerKey])
|
||||
|
||||
const handleDelete = async () => {
|
||||
if (!confirm('Are you sure you want to delete this message?')) return
|
||||
if (!confirm(t('messages.delete_confirm', 'Are you sure you want to delete this message?'))) return
|
||||
const messageId = message.id
|
||||
try {
|
||||
await api('delete-message', {messageId})
|
||||
toast.success('Message deleted')
|
||||
toast.success(t('messages.deleted', 'Message deleted'))
|
||||
setMessages?.((prevMessages) => {
|
||||
if (!prevMessages) return prevMessages
|
||||
return prevMessages.filter((m) => m.id !== messageId)
|
||||
})
|
||||
} catch (error) {
|
||||
toast.error('Failed to delete message')
|
||||
toast.error(t('messages.delete_failed', 'Failed to delete message'))
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
@@ -97,17 +99,17 @@ export function MessageActions(props: {
|
||||
<DropdownMenu
|
||||
items={[
|
||||
isOwner && {
|
||||
name: 'Edit',
|
||||
name: t('messages.action.edit', 'Edit'),
|
||||
icon: <PencilIcon className="h-4 w-4"/>,
|
||||
onClick: onRequestEdit,
|
||||
},
|
||||
isOwner && {
|
||||
name: 'Delete',
|
||||
name: t('messages.action.delete', 'Delete'),
|
||||
icon: <TrashIcon className="h-4 w-4"/>,
|
||||
onClick: handleDelete,
|
||||
},
|
||||
{
|
||||
name: 'Add Reaction',
|
||||
name: t('messages.action.add_reaction', 'Add Reaction'),
|
||||
icon: <EmojiHappyIcon className="h-4 w-4"/>,
|
||||
onClick: () => {
|
||||
setShowEmojiPicker(!showEmojiPicker)
|
||||
@@ -121,7 +123,7 @@ export function MessageActions(props: {
|
||||
/>
|
||||
)}
|
||||
{/*{message.isEdited && (*/}
|
||||
{/* <span className="text-xs text-gray-400">edited</span>*/}
|
||||
{/* <span className="text-xs text-gray-400">{t('messages.edited', 'edited')}</span>*/}
|
||||
{/*)}*/}
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -11,14 +11,16 @@ import { SelectUsers } from 'web/components/select-users'
|
||||
import { DisplayUser } from 'common/api/user-types'
|
||||
import { usePrivateUser } from 'web/hooks/use-user'
|
||||
import { buildArray } from 'common/util/array'
|
||||
import { useT } from 'web/lib/locale'
|
||||
|
||||
export default function NewMessageButton() {
|
||||
const [open, setOpen] = useState(false)
|
||||
const t = useT()
|
||||
return (
|
||||
<>
|
||||
<Button className="h-fit gap-1" onClick={() => setOpen(true)}>
|
||||
<PlusIcon className="h-5 w-5" aria-hidden="true" />
|
||||
New Message
|
||||
{t('messages.new_message', 'New Message')}
|
||||
</Button>
|
||||
<MessageModal open={open} setOpen={setOpen} />
|
||||
</>
|
||||
@@ -32,6 +34,7 @@ function MessageModal(props: {
|
||||
const { open, setOpen } = props
|
||||
const privateUser = usePrivateUser()
|
||||
const router = useRouter()
|
||||
const t = useT()
|
||||
|
||||
const [users, setUsers] = useState<DisplayUser[]>([])
|
||||
const createChannel = async () => {
|
||||
@@ -62,7 +65,7 @@ function MessageModal(props: {
|
||||
</Col>
|
||||
<Row className={'bg-canvas-0 justify-end rounded-b-md p-2'}>
|
||||
<Button disabled={users.length === 0} onClick={createChannel}>
|
||||
Create
|
||||
{t('messages.create', 'Create')}
|
||||
</Button>
|
||||
</Row>
|
||||
</Modal>
|
||||
|
||||
@@ -408,7 +408,31 @@
|
||||
"help.actions.faq_button": "Consulter la FAQ",
|
||||
"messages.title": "Messages",
|
||||
"messages.seo.description": "Vos messages",
|
||||
"messages.input_placeholder": "Envoyer un message",
|
||||
"messages.menu.see_members": "Voir les membres",
|
||||
"messages.menu.mute_1_day": "Couper le son pendant 1 jour",
|
||||
"messages.menu.mute_forever": "Couper le son définitivement",
|
||||
"messages.menu.leave_chat": "Quitter la conversation",
|
||||
"messages.action.edit": "Modifier",
|
||||
"messages.action.delete": "Supprimer",
|
||||
"messages.action.add_reaction": "Ajouter une réaction",
|
||||
"messages.toast.muting_1_day.loading": "Couper le son pour 1 jour...",
|
||||
"messages.toast.muting_1_day.success": "Son coupé pour 1 jour",
|
||||
"messages.toast.muting_1_day.error": "Échec de la coupure du son",
|
||||
"messages.toast.muting_forever.loading": "Couper le son définitivement...",
|
||||
"messages.toast.muting_forever.success": "Son coupé définitivement",
|
||||
"messages.toast.muting_forever.error": "Échec de la coupure du son",
|
||||
"messages.empty": "Vous n'avez pas encore de messages.",
|
||||
"messages.delete_confirm": "Êtes-vous sûr de vouloir supprimer ce message ?",
|
||||
"messages.deleted": "Message supprimé",
|
||||
"messages.delete_failed": "Échec de la suppression du message",
|
||||
"messages.more": " de plus",
|
||||
"messages.you_prefix": "Vous : "
|
||||
"messages.new_message": "Nouveau message",
|
||||
"messages.create": "Créer",
|
||||
"messages.you_prefix": "Vous : ",
|
||||
"messages.edited": "modifié",
|
||||
"messages.toast.edit_failed": "Échec de la modification du message.",
|
||||
"messages.toast.send_failed": "Échec de l'envoi du message. Veuillez réessayer plus tard ou contacter le support si le problème persiste.",
|
||||
"aboutsettings.copied": "Copié !",
|
||||
"aboutsettings.copy_info": "Copier les infos"
|
||||
}
|
||||
@@ -34,9 +34,11 @@ import {ChatMessage} from 'common/chat-message'
|
||||
import {BackButton} from 'web/components/back-button'
|
||||
import {SEO} from "web/components/SEO"
|
||||
import {cleanDoc} from "common/util/parse";
|
||||
import {useT} from 'web/lib/locale'
|
||||
|
||||
export default function PrivateMessagesPage() {
|
||||
const router = useRouter()
|
||||
const t = useT()
|
||||
const {channelId: channelIdString} = router.query as { channelId: string }
|
||||
const channelId = router.isReady ? parseInt(channelIdString) : undefined
|
||||
const user = useUser()
|
||||
@@ -47,8 +49,8 @@ export default function PrivateMessagesPage() {
|
||||
return (
|
||||
<PageBase trackPageView={'private messages page'}>
|
||||
<SEO
|
||||
title={'Messages'}
|
||||
description={'Messages'}
|
||||
title={t('messages.title', 'Messages')}
|
||||
description={t('messages.seo.description', 'Messages')}
|
||||
url={`/messages/${channelIdString}`}
|
||||
/>
|
||||
{router.isReady && channelId && user ? (
|
||||
@@ -96,6 +98,7 @@ export const PrivateChat = (props: {
|
||||
memberIds: string[]
|
||||
}) => {
|
||||
const {user, channel, memberIds} = props
|
||||
const t = useT()
|
||||
const channelId = channel.channel_id
|
||||
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent)
|
||||
const isMobile = useIsMobile()
|
||||
@@ -147,7 +150,7 @@ export const PrivateChat = (props: {
|
||||
const editor = useTextEditor({
|
||||
key: `private-message-${channelId}-${user.id}`,
|
||||
size: 'sm',
|
||||
placeholder: 'Send a message',
|
||||
placeholder: t('messages.input_placeholder', 'Send a message'),
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
@@ -211,8 +214,8 @@ export const PrivateChat = (props: {
|
||||
} catch (e) {
|
||||
toast.error(
|
||||
editingMessage
|
||||
? "Couldn't edit message."
|
||||
: "Couldn't send message. Please try again later or contact support if the problem persists."
|
||||
? t('messages.toast.edit_failed', "Couldn't edit message.")
|
||||
: t('messages.toast.send_failed', "Couldn't send message. Please try again later or contact support if the problem persists.")
|
||||
)
|
||||
console.error(e)
|
||||
} finally {
|
||||
@@ -277,14 +280,14 @@ export const PrivateChat = (props: {
|
||||
items={buildArray(
|
||||
{
|
||||
icon: <FaUserFriends className={'h-5 w-5'}/>,
|
||||
name: 'See members',
|
||||
name: t('messages.menu.see_members', 'See members'),
|
||||
onClick: () => {
|
||||
setShowUsers(true)
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: <GiSpeakerOff className="h-5 w-5"/>,
|
||||
name: 'Mute 1 day',
|
||||
name: t('messages.menu.mute_1_day', 'Mute 1 day'),
|
||||
onClick: async () => {
|
||||
await toast.promise(
|
||||
api('update-private-user-message-channel', {
|
||||
@@ -292,16 +295,16 @@ export const PrivateChat = (props: {
|
||||
notifyAfterTime: Date.now() + DAY_MS,
|
||||
}),
|
||||
{
|
||||
loading: 'Muting for 1 day...',
|
||||
success: 'Muted for 1 day',
|
||||
error: 'Failed to mute',
|
||||
loading: t('messages.toast.muting_1_day.loading', 'Muting for 1 day...'),
|
||||
success: t('messages.toast.muting_1_day.success', 'Muted for 1 day'),
|
||||
error: t('messages.toast.muting_1_day.error', 'Failed to mute'),
|
||||
}
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: <GiSpeakerOff className="h-5 w-5"/>,
|
||||
name: 'Mute forever',
|
||||
name: t('messages.menu.mute_forever', 'Mute forever'),
|
||||
onClick: async () => {
|
||||
await toast.promise(
|
||||
api('update-private-user-message-channel', {
|
||||
@@ -309,16 +312,16 @@ export const PrivateChat = (props: {
|
||||
notifyAfterTime: Date.now() + 100 * YEAR_MS,
|
||||
}),
|
||||
{
|
||||
loading: 'Muting forever...',
|
||||
success: 'Muted forever',
|
||||
error: 'Failed to mute',
|
||||
loading: t('messages.toast.muting_forever.loading', 'Muting forever...'),
|
||||
success: t('messages.toast.muting_forever.success', 'Muted forever'),
|
||||
error: t('messages.toast.muting_forever.error', 'Failed to mute'),
|
||||
}
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: <FaUserMinus className="h-5 w-5"/>,
|
||||
name: 'Leave chat',
|
||||
name: t('messages.menu.leave_chat', 'Leave chat'),
|
||||
onClick: async () => {
|
||||
await api('leave-private-user-message-channel', {
|
||||
channelId: channelId,
|
||||
@@ -410,7 +413,7 @@ export const PrivateChat = (props: {
|
||||
)}
|
||||
{realtimeMessages && messages.length === 0 && (
|
||||
<div className="text-ink-500 dark:text-ink-600 p-2">
|
||||
No messages yet.
|
||||
{t('messages.empty', 'No messages yet.')}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user