diff --git a/docs/roadmap-resenha.md b/docs/roadmap-resenha.md index 2aaf80b5..fb1e0b14 100644 --- a/docs/roadmap-resenha.md +++ b/docs/roadmap-resenha.md @@ -73,6 +73,8 @@ fixas por `t('chave')`. O que faltar cai para o inglês sozinho. - Configurações → Conexões (nasceu bilíngue) - Seletor de GIF - Chat: composer e mensagens (placeholder, anexos, responder, reações) +- Barra lateral: servidores, canais e menus de contexto +- Lista de membros (grupos por cargo, carregamento) - Registro de auditoria e Estatísticas (nasceram bilíngues) ### Fila sugerida de tradução diff --git a/packages/web/src/components/layout/ChannelSidebar.tsx b/packages/web/src/components/layout/ChannelSidebar.tsx index ba0809b2..3f9f13eb 100644 --- a/packages/web/src/components/layout/ChannelSidebar.tsx +++ b/packages/web/src/components/layout/ChannelSidebar.tsx @@ -1,4 +1,5 @@ import React, { useState, useRef, useEffect, useCallback, useMemo } from 'react'; +import { useT } from '../../i18n'; import { useNavigate, useLocation } from 'react-router-dom'; import type { Channel } from '@backspace/shared'; import { useSpaceStore, getChannelOrigin, getMyUserIdForOrigin } from '../../stores/spaceStore'; @@ -26,6 +27,7 @@ import { useAudioDevices } from '../../hooks/useAudioDevices'; import { DropdownItem } from '../modals/settingsPanels/_shared/SettingsPickerPrimitives'; export function ChannelSidebar() { + const tr = useT(); const spaces = useSpaceStore((s) => s.spaces); const currentSpaceId = useSpaceStore((s) => s.currentSpaceId); const loadingSpaceId = useSpaceStore((s) => s.loadingSpaceId); @@ -318,7 +320,7 @@ export function ChannelSidebar() { items.push({ key: 'create-channel', type: 'action', - label: 'Create Channel', + label: tr('sidebar.createChannel'), icon: ( @@ -330,7 +332,7 @@ export function ChannelSidebar() { items.push({ key: 'create-category', type: 'action', - label: 'Create Category', + label: tr('sidebar.createCategory'), icon: ( @@ -343,7 +345,7 @@ export function ChannelSidebar() { items.push({ key: 'invite', type: 'action', - label: 'Invite People', + label: tr('sidebar.invitePeople'), icon: ( @@ -355,7 +357,7 @@ export function ChannelSidebar() { items.push({ key: 'settings', type: 'action', - label: 'Space Settings', + label: tr('sidebar.spaceSettings'), icon: ( @@ -373,7 +375,7 @@ export function ChannelSidebar() { { key: 'leave-group', type: 'action', - label: 'Leave Group', + label: tr('sidebar.leaveGroup'), danger: true, icon: ( @@ -453,7 +455,7 @@ export function ChannelSidebar() { - Friends + {tr('sidebar.friends')} {/* Placeholder nav items */} @@ -463,7 +465,7 @@ export function ChannelSidebar() { - Coming Soon + {tr('sidebar.comingSoon')}
- Coming Soon + {tr('sidebar.comingSoon')}
- Direct Messages + {tr('sidebar.directMessages')} )}
)} @@ -845,6 +847,7 @@ function UserAreaPanel({ onDeafenToggle: () => void; onSettingsClick: (tab?: string) => void; }) { + const tr = useT(); const [accountMenuOpen, setAccountMenuOpen] = useState(false); const [openPanel, setOpenPanel] = useState<'input' | 'output' | null>(null); const inputDeviceId = useVoiceStore((s) => s.inputDeviceId); @@ -959,7 +962,7 @@ function UserAreaPanel({ className="w-full px-4 py-3 flex items-center justify-between hover:bg-interactive-hover transition-colors" >
-
Input Device
+
{tr('sidebar.inputDevice')}
{selectedInputLabel}
@@ -1004,7 +1007,7 @@ function UserAreaPanel({ {/* Input Volume */}
-
Input Volume
+
{tr('sidebar.inputVolume')}
onSettingsClick('voice')} className="w-full px-4 py-3 flex items-center justify-between hover:bg-interactive-hover transition-colors" > - Voice Settings + {tr('sidebar.voiceSettings')} @@ -1057,7 +1060,7 @@ function UserAreaPanel({ className="w-full px-4 py-3 flex items-center justify-between hover:bg-interactive-hover transition-colors" >
-
Output Device
+
{tr('sidebar.outputDevice')}
{selectedOutputLabel}
@@ -1102,7 +1105,7 @@ function UserAreaPanel({ {/* Output Volume */}
-
Output Volume
+
{tr('sidebar.outputVolume')}
onSettingsClick('voice')} className="w-full px-4 py-3 flex items-center justify-between hover:bg-interactive-hover transition-colors" > - Voice Settings + {tr('sidebar.voiceSettings')} diff --git a/packages/web/src/components/layout/MemberSidebar.tsx b/packages/web/src/components/layout/MemberSidebar.tsx index 4c84db43..026cd891 100644 --- a/packages/web/src/components/layout/MemberSidebar.tsx +++ b/packages/web/src/components/layout/MemberSidebar.tsx @@ -1,4 +1,5 @@ import React, { useMemo } from 'react'; +import { useT } from '../../i18n'; import type { MemberWithUser, Activity } from '@backspace/shared'; import { useSpaceStore } from '../../stores/spaceStore'; import { useUIStore } from '../../stores/uiStore'; @@ -21,7 +22,7 @@ function getMemberGroup(member: MemberWithUser, ownerId: string | undefined) { const ownerRole = member.roles?.find(r => r.position > 0); return { key: '__owner__', - label: 'OWNER', + label: '__OWNER__', color: ownerRole?.color ?? 'rgb(var(--accent-rose))', position: Infinity, }; @@ -40,7 +41,10 @@ function getMemberGroup(member: MemberWithUser, ownerId: string | undefined) { // No explicit roles — just @everyone return { key: '__online__', - label: 'ONLINE', + // Marcado em vez de traduzido aqui: esta funcao nao e um componente e nao + // pode usar o hook. Nomes de cargo passam adiante sem traducao — sao dados + // do usuario, nao interface. + label: '__ONLINE__', color: undefined, position: -1, }; @@ -111,6 +115,7 @@ export function MemberSidebar() { const currentSpaceId = useSpaceStore((s) => s.currentSpaceId); const loadingSpaceId = useSpaceStore((s) => s.loadingSpaceId); const memberListOpen = useUIStore((s) => s.memberListOpen); + const tr = useT(); const openUserProfile = useUIStore((s) => s.openUserProfile); const userActivities = useActivityStore((s) => s.userActivities); @@ -183,7 +188,7 @@ export function MemberSidebar() { return (
{showMemberSkeleton ? ( -
+
{/* Role group 1 */}
{Array.from({ length: 2 }, (_, i) => ( @@ -207,7 +212,11 @@ export function MemberSidebar() { {roleGroups.map(([key, group]) => (

- {group.label} — {group.members.length} + {group.label === '__ONLINE__' + ? tr('sidebar.groupOnline') + : group.label === '__OWNER__' + ? tr('sidebar.groupOwner') + : group.label} — {group.members.length}

{group.members.map((m) => renderMember(m))}
diff --git a/packages/web/src/i18n/locales/en.ts b/packages/web/src/i18n/locales/en.ts index 7234ce78..d5944cd8 100644 --- a/packages/web/src/i18n/locales/en.ts +++ b/packages/web/src/i18n/locales/en.ts @@ -56,6 +56,28 @@ export const en = { 'accountMenu.copyId': 'Copy User ID', 'accountMenu.copied': 'Copied', + // Sidebar — spaces, channels and members + 'sidebar.friends': 'Friends', + 'sidebar.directMessages': 'Direct Messages', + 'sidebar.noChannels': 'No channels', + 'sidebar.comingSoon': 'Coming Soon', + 'sidebar.loadingChannels': 'Loading channels', + 'sidebar.loadingMembers': 'Loading members', + 'sidebar.groupOnline': 'ONLINE', + 'sidebar.groupOwner': 'OWNER', + 'sidebar.createChannel': 'Create Channel', + 'sidebar.createCategory': 'Create Category', + 'sidebar.categorySettings': 'Category Settings', + 'sidebar.deleteCategory': 'Delete Category', + 'sidebar.invitePeople': 'Invite People', + 'sidebar.spaceSettings': 'Space Settings', + 'sidebar.leaveGroup': 'Leave Group', + 'sidebar.voiceSettings': 'Voice Settings', + 'sidebar.inputDevice': 'Input Device', + 'sidebar.inputVolume': 'Input Volume', + 'sidebar.outputDevice': 'Output Device', + 'sidebar.outputVolume': 'Output Volume', + // Chat — composer and messages 'chat.composer.placeholder': 'Message {channel}', 'chat.composer.attach': 'Attach file', diff --git a/packages/web/src/i18n/locales/pt-BR.ts b/packages/web/src/i18n/locales/pt-BR.ts index 23307bb5..625230eb 100644 --- a/packages/web/src/i18n/locales/pt-BR.ts +++ b/packages/web/src/i18n/locales/pt-BR.ts @@ -55,6 +55,28 @@ export const ptBR: Partial = { 'accountMenu.copyId': 'Copiar ID do usuário', 'accountMenu.copied': 'Copiado', + // Barra lateral — servidores, canais e membros + 'sidebar.friends': 'Amigos', + 'sidebar.directMessages': 'Mensagens diretas', + 'sidebar.noChannels': 'Nenhum canal', + 'sidebar.comingSoon': 'Em breve', + 'sidebar.loadingChannels': 'Carregando canais', + 'sidebar.loadingMembers': 'Carregando membros', + 'sidebar.groupOnline': 'DISPONÍVEIS', + 'sidebar.groupOwner': 'DONO', + 'sidebar.createChannel': 'Criar canal', + 'sidebar.createCategory': 'Criar categoria', + 'sidebar.categorySettings': 'Configurações da categoria', + 'sidebar.deleteCategory': 'Excluir categoria', + 'sidebar.invitePeople': 'Convidar pessoas', + 'sidebar.spaceSettings': 'Configurações do servidor', + 'sidebar.leaveGroup': 'Sair do grupo', + 'sidebar.voiceSettings': 'Configurações de voz', + 'sidebar.inputDevice': 'Dispositivo de entrada', + 'sidebar.inputVolume': 'Volume de entrada', + 'sidebar.outputDevice': 'Dispositivo de saída', + 'sidebar.outputVolume': 'Volume de saída', + // Chat — composer e mensagens 'chat.composer.placeholder': 'Conversar em {channel}', 'chat.composer.attach': 'Anexar arquivo',