From 3dfdc92b2a4cdde390cdd01f1a3810a9b6627f6a Mon Sep 17 00:00:00 2001 From: Maurice Date: Sun, 20 Sep 2026 19:43:52 +0200 Subject: [PATCH] fix(collab): a shared link can be edited, and its glyph opens it A link in the Collab tab could only be deleted and added again once its title or address needed a correction; the update route has taken both all along. The add dialog edits a link handed to it now, behind a pencil on each row. The external-link glyph next to a row that was already a link read as a button doing nothing; it is a link to the address itself now. Closes #2414 --- .../components/Collab/CollabLinks.test.tsx | 39 +++++++++++++++ client/src/components/Collab/CollabLinks.tsx | 48 ++++++++++++++----- shared/src/i18n/ar/collab.ts | 2 + shared/src/i18n/br/collab.ts | 2 + shared/src/i18n/ca/collab.ts | 2 + shared/src/i18n/cs/collab.ts | 2 + shared/src/i18n/de/collab.ts | 2 + shared/src/i18n/en/collab.ts | 2 + shared/src/i18n/es/collab.ts | 2 + shared/src/i18n/fr/collab.ts | 2 + shared/src/i18n/gr/collab.ts | 2 + shared/src/i18n/hu/collab.ts | 2 + shared/src/i18n/id/collab.ts | 2 + shared/src/i18n/it/collab.ts | 2 + shared/src/i18n/ja/collab.ts | 2 + shared/src/i18n/ko/collab.ts | 2 + shared/src/i18n/nl/collab.ts | 2 + shared/src/i18n/pl/collab.ts | 2 + shared/src/i18n/ru/collab.ts | 2 + shared/src/i18n/sv/collab.ts | 2 + shared/src/i18n/tr/collab.ts | 2 + shared/src/i18n/uk/collab.ts | 2 + shared/src/i18n/vi/collab.ts | 2 + shared/src/i18n/zh-TW/collab.ts | 2 + shared/src/i18n/zh/collab.ts | 2 + 25 files changed, 120 insertions(+), 13 deletions(-) diff --git a/client/src/components/Collab/CollabLinks.test.tsx b/client/src/components/Collab/CollabLinks.test.tsx index bb7db9940..f134d6819 100644 --- a/client/src/components/Collab/CollabLinks.test.tsx +++ b/client/src/components/Collab/CollabLinks.test.tsx @@ -118,6 +118,45 @@ describe('CollabLinks', () => { expect(screen.getByRole('button', { name: /delete link|collab\.links\.delete/i })).toBeInTheDocument(); }); + it('FE-COMP-LINKS-009: a link can be edited in place, title and address alike', async () => { + // #2414: a link used to be delete-and-add once it needed a correction. + const user = userEvent.setup(); + let put: Record | null = null; + server.use( + http.get('/api/trips/1/collab/links', () => HttpResponse.json({ links: [buildLink()] })), + http.put('/api/trips/1/collab/links/1', async ({ request }) => { + put = (await request.json()) as Record; + return HttpResponse.json({ link: buildLink({ title: 'Ferry timetable 2026', url: 'https://ferries.example/2026' }) }); + }), + ); + render(); + await user.click(await screen.findByRole('button', { name: /edit link|collab\.links\.edit/i })); + const title = await screen.findByLabelText(/link title|collab\.links\.titlePlaceholder/i); + expect(title).toHaveValue('Ferry timetable'); + await user.clear(title); + await user.type(title, 'Ferry timetable 2026'); + const url = screen.getByLabelText(/https|collab\.links\.urlPlaceholder/i); + expect(url).toHaveValue('https://ferries.example/timetable'); + await user.clear(url); + await user.type(url, 'https://ferries.example/2026'); + await user.click(screen.getByRole('button', { name: /save link|collab\.links\.save/i })); + + await waitFor(() => expect(put).toEqual({ title: 'Ferry timetable 2026', url: 'https://ferries.example/2026' })); + await waitFor(() => expect(screen.queryByLabelText(/link title|collab\.links\.titlePlaceholder/i)).not.toBeInTheDocument()); + expect(await screen.findByText('Ferry timetable 2026')).toBeInTheDocument(); + expect(screen.getByText('https://ferries.example/2026')).toBeInTheDocument(); + }); + + it('FE-COMP-LINKS-010: the external-link glyph opens the address in a new tab', async () => { + server.use( + http.get('/api/trips/1/collab/links', () => HttpResponse.json({ links: [buildLink()] })), + ); + render(); + const open = await screen.findByRole('link', { name: /open link|collab\.links\.open/i }); + expect(open).toHaveAttribute('href', 'https://ferries.example/timetable'); + expect(open).toHaveAttribute('target', '_blank'); + }); + it('FE-COMP-LINKS-008: a viewer without edit rights gets no add button', async () => { // collab_edit reserved for the owner, on somebody else's trip. seedStore(usePermissionsStore, { permissions: { collab_edit: 'trip_owner' } }); diff --git a/client/src/components/Collab/CollabLinks.tsx b/client/src/components/Collab/CollabLinks.tsx index 564eacdde..43f285c67 100644 --- a/client/src/components/Collab/CollabLinks.tsx +++ b/client/src/components/Collab/CollabLinks.tsx @@ -1,6 +1,6 @@ import { CSSProperties, FormEvent, useEffect, useRef, useState } from 'react' import { createPortal } from 'react-dom' -import { ExternalLink, Link2, Pin, Plus, Trash2, X } from 'lucide-react' +import { ExternalLink, Link2, Pencil, Pin, Plus, Trash2, X } from 'lucide-react' import { collabApi } from '../../api/client' import { addListener, removeListener } from '../../api/websocket' import { useTranslation } from '../../i18n' @@ -27,14 +27,16 @@ function LinkIcon({ url, title }: { url: string; title: string }) { } /** - * The add form as a modal, like the poll and note panels next to it. Inline it - * pushed the list down and gave the panel a second header, which is what made - * this tab read as a different app from its four siblings. + * The add and edit form as a modal, like the poll and note panels next to it. + * Inline it pushed the list down and gave the panel a second header, which is + * what made this tab read as a different app from its four siblings. With a + * link handed in it edits that link (#2414): a link used to be delete-and-add + * once its title or address needed a correction. */ -function AddLinkModal({ onClose, onCreate }: { onClose: () => void; onCreate: (link: { title: string; url: string }) => Promise }) { +function LinkModal({ link, onClose, onSave }: { link?: CollabLink; onClose: () => void; onSave: (link: { title: string; url: string }) => Promise }) { const { t } = useTranslation() - const [title, setTitle] = useState('') - const [url, setUrl] = useState('') + const [title, setTitle] = useState(link?.title ?? '') + const [url, setUrl] = useState(link?.url ?? '') const [busy, setBusy] = useState(false) const valid = title.trim().length > 0 && url.trim().length > 0 @@ -43,10 +45,10 @@ function AddLinkModal({ onClose, onCreate }: { onClose: () => void; onCreate: (l if (!valid || busy) return setBusy(true) try { - await onCreate({ title: title.trim(), url: url.trim() }) + await onSave({ title: title.trim(), url: url.trim() }) onClose() } catch { - // add() already said what went wrong; the form stays open with the input in it. + // The caller already said what went wrong; the form stays open with the input in it. } finally { setBusy(false) } @@ -66,7 +68,7 @@ function AddLinkModal({ onClose, onCreate }: { onClose: () => void; onCreate: (l
{ if (e.target === e.currentTarget) onClose() }}>
-

{t('collab.links.add')}

+

{t(link ? 'collab.links.edit' : 'collab.links.add')}

@@ -99,6 +101,7 @@ export default function CollabLinks({ tripId }: { tripId: number }) { const toast = useToast() const [links, setLinks] = useState([]) const [showForm, setShowForm] = useState(false) + const [editing, setEditing] = useState(null) // Both are new objects on every render, so depending on them would reload the // list after each keystroke and drop a link that was just added back out of it. @@ -168,6 +171,17 @@ export default function CollabLinks({ tripId }: { tripId: number }) { } } + const edit = async (link: CollabLink, data: { title: string; url: string }) => { + try { + const d = await collabApi.updateLink(tripId, link.id, data) + setLinks(v => v.map(x => x.id === link.id ? d.link : x)) + } catch (err) { + console.error('Failed to edit collab link:', err) + toast.error(t('common.error')) + throw err + } + } + const remove = async (id: number) => { try { await collabApi.deleteLink(tripId, id) @@ -210,8 +224,15 @@ export default function CollabLinks({ tripId }: { tripId: number }) {
{link.title}
{link.url}
-
- {/* Create Modal */} - {showForm && setShowForm(false)} onCreate={add} />} + {/* Create and edit modals */} + {showForm && setShowForm(false)} onSave={add} />} + {editing && setEditing(null)} onSave={data => edit(editing, data)} />}
) } diff --git a/shared/src/i18n/ar/collab.ts b/shared/src/i18n/ar/collab.ts index 1cb6e4ae3..4c41584a1 100644 --- a/shared/src/i18n/ar/collab.ts +++ b/shared/src/i18n/ar/collab.ts @@ -23,6 +23,8 @@ const collab: TranslationStrings = { 'collab.links.pin': 'تثبيت الرابط', 'collab.links.unpin': 'إلغاء تثبيت الرابط', 'collab.links.delete': 'حذف الرابط', + 'collab.links.edit': 'تعديل الرابط', + 'collab.links.open': 'فتح الرابط', 'collab.whatsNext.title': 'ما التالي', 'collab.whatsNext.today': 'اليوم', 'collab.whatsNext.tomorrow': 'غدًا', diff --git a/shared/src/i18n/br/collab.ts b/shared/src/i18n/br/collab.ts index 1c3163f5b..630e72674 100644 --- a/shared/src/i18n/br/collab.ts +++ b/shared/src/i18n/br/collab.ts @@ -23,6 +23,8 @@ const collab: TranslationStrings = { 'collab.links.pin': 'Fixar link', 'collab.links.unpin': 'Desafixar link', 'collab.links.delete': 'Excluir link', + 'collab.links.edit': 'Editar link', + 'collab.links.open': 'Abrir link', 'collab.whatsNext.title': 'Próximos passos', 'collab.whatsNext.today': 'Hoje', 'collab.whatsNext.tomorrow': 'Amanhã', diff --git a/shared/src/i18n/ca/collab.ts b/shared/src/i18n/ca/collab.ts index 8a4a117cc..acddf0dd3 100644 --- a/shared/src/i18n/ca/collab.ts +++ b/shared/src/i18n/ca/collab.ts @@ -15,6 +15,8 @@ const collab: TranslationStrings = { 'collab.links.pin': 'Fixa l\'enllaç', 'collab.links.unpin': 'Desfixa l\'enllaç', 'collab.links.delete': 'Suprimeix l\'enllaç', + 'collab.links.edit': 'Edita l\'enllaç', + 'collab.links.open': 'Obre l\'enllaç', 'collab.whatsNext.title': 'Què ve ara', 'collab.whatsNext.today': 'Avui', 'collab.whatsNext.tomorrow': 'Demà', diff --git a/shared/src/i18n/cs/collab.ts b/shared/src/i18n/cs/collab.ts index a77dd7ecc..55f71fa69 100644 --- a/shared/src/i18n/cs/collab.ts +++ b/shared/src/i18n/cs/collab.ts @@ -23,6 +23,8 @@ const collab: TranslationStrings = { 'collab.links.pin': 'Připnout odkaz', 'collab.links.unpin': 'Odepnout odkaz', 'collab.links.delete': 'Smazat odkaz', + 'collab.links.edit': 'Upravit odkaz', + 'collab.links.open': 'Otevřít odkaz', 'collab.whatsNext.title': 'Co následuje', 'collab.whatsNext.today': 'Dnes', 'collab.whatsNext.tomorrow': 'Zítra', diff --git a/shared/src/i18n/de/collab.ts b/shared/src/i18n/de/collab.ts index c86fb542d..453b2396c 100644 --- a/shared/src/i18n/de/collab.ts +++ b/shared/src/i18n/de/collab.ts @@ -23,6 +23,8 @@ const collab: TranslationStrings = { 'collab.links.pin': 'Link anheften', 'collab.links.unpin': 'Link lösen', 'collab.links.delete': 'Link löschen', + 'collab.links.edit': 'Link bearbeiten', + 'collab.links.open': 'Link öffnen', 'collab.whatsNext.title': 'Nächste', 'collab.whatsNext.today': 'Heute', 'collab.whatsNext.tomorrow': 'Morgen', diff --git a/shared/src/i18n/en/collab.ts b/shared/src/i18n/en/collab.ts index 7e52cd538..b7a9fc9f9 100644 --- a/shared/src/i18n/en/collab.ts +++ b/shared/src/i18n/en/collab.ts @@ -23,6 +23,8 @@ const collab: TranslationStrings = { 'collab.links.pin': 'Pin link', 'collab.links.unpin': 'Unpin link', 'collab.links.delete': 'Delete link', + 'collab.links.edit': 'Edit link', + 'collab.links.open': 'Open link', 'collab.whatsNext.title': "What's Next", 'collab.whatsNext.today': 'Today', 'collab.whatsNext.tomorrow': 'Tomorrow', diff --git a/shared/src/i18n/es/collab.ts b/shared/src/i18n/es/collab.ts index 13d0343ab..c2d2ce1b5 100644 --- a/shared/src/i18n/es/collab.ts +++ b/shared/src/i18n/es/collab.ts @@ -23,6 +23,8 @@ const collab: TranslationStrings = { 'collab.links.pin': 'Fijar enlace', 'collab.links.unpin': 'Desfijar enlace', 'collab.links.delete': 'Eliminar enlace', + 'collab.links.edit': 'Editar enlace', + 'collab.links.open': 'Abrir enlace', 'collab.whatsNext.title': 'Qué viene ahora', 'collab.whatsNext.today': 'Hoy', 'collab.whatsNext.tomorrow': 'Mañana', diff --git a/shared/src/i18n/fr/collab.ts b/shared/src/i18n/fr/collab.ts index 04312f926..c37f1063e 100644 --- a/shared/src/i18n/fr/collab.ts +++ b/shared/src/i18n/fr/collab.ts @@ -23,6 +23,8 @@ const collab: TranslationStrings = { 'collab.links.pin': 'Épingler le lien', 'collab.links.unpin': 'Désépingler le lien', 'collab.links.delete': 'Supprimer le lien', + 'collab.links.edit': 'Modifier le lien', + 'collab.links.open': 'Ouvrir le lien', 'collab.whatsNext.title': 'À venir', 'collab.whatsNext.today': "Aujourd'hui", 'collab.whatsNext.tomorrow': 'Demain', diff --git a/shared/src/i18n/gr/collab.ts b/shared/src/i18n/gr/collab.ts index 2fb4ba5a1..7d5688fd8 100644 --- a/shared/src/i18n/gr/collab.ts +++ b/shared/src/i18n/gr/collab.ts @@ -23,6 +23,8 @@ const collab: TranslationStrings = { 'collab.links.pin': 'Καρφίτσωμα συνδέσμου', 'collab.links.unpin': 'Ξεκαρφίτσωμα συνδέσμου', 'collab.links.delete': 'Διαγραφή συνδέσμου', + 'collab.links.edit': 'Επεξεργασία συνδέσμου', + 'collab.links.open': 'Άνοιγμα συνδέσμου', 'collab.whatsNext.title': 'Τι Επόμενο', 'collab.whatsNext.today': 'Σήμερα', 'collab.whatsNext.tomorrow': 'Αύριο', diff --git a/shared/src/i18n/hu/collab.ts b/shared/src/i18n/hu/collab.ts index 07cb30a96..13b86ea13 100644 --- a/shared/src/i18n/hu/collab.ts +++ b/shared/src/i18n/hu/collab.ts @@ -23,6 +23,8 @@ const collab: TranslationStrings = { 'collab.links.pin': 'Link rögzítése', 'collab.links.unpin': 'Link feloldása', 'collab.links.delete': 'Link törlése', + 'collab.links.edit': 'Link szerkesztése', + 'collab.links.open': 'Link megnyitása', 'collab.whatsNext.title': 'Mi következik', 'collab.whatsNext.today': 'Ma', 'collab.whatsNext.tomorrow': 'Holnap', diff --git a/shared/src/i18n/id/collab.ts b/shared/src/i18n/id/collab.ts index 1f15afc33..4c2b426ef 100644 --- a/shared/src/i18n/id/collab.ts +++ b/shared/src/i18n/id/collab.ts @@ -23,6 +23,8 @@ const collab: TranslationStrings = { 'collab.links.pin': 'Sematkan tautan', 'collab.links.unpin': 'Lepas sematan tautan', 'collab.links.delete': 'Hapus tautan', + 'collab.links.edit': 'Edit tautan', + 'collab.links.open': 'Buka tautan', 'collab.whatsNext.title': 'Berikutnya', 'collab.whatsNext.today': 'Hari ini', 'collab.whatsNext.tomorrow': 'Besok', diff --git a/shared/src/i18n/it/collab.ts b/shared/src/i18n/it/collab.ts index 0bf2c0d92..a3f588b82 100644 --- a/shared/src/i18n/it/collab.ts +++ b/shared/src/i18n/it/collab.ts @@ -23,6 +23,8 @@ const collab: TranslationStrings = { 'collab.links.pin': 'Fissa link', 'collab.links.unpin': 'Sblocca link', 'collab.links.delete': 'Elimina link', + 'collab.links.edit': 'Modifica link', + 'collab.links.open': 'Apri link', 'collab.whatsNext.title': "Cosa c'è dopo", 'collab.whatsNext.today': 'Oggi', 'collab.whatsNext.tomorrow': 'Domani', diff --git a/shared/src/i18n/ja/collab.ts b/shared/src/i18n/ja/collab.ts index fadbec1f9..bc54cb6f4 100644 --- a/shared/src/i18n/ja/collab.ts +++ b/shared/src/i18n/ja/collab.ts @@ -23,6 +23,8 @@ const collab: TranslationStrings = { 'collab.links.pin': 'リンクを固定', 'collab.links.unpin': 'リンクの固定を解除', 'collab.links.delete': 'リンクを削除', + 'collab.links.edit': 'リンクを編集', + 'collab.links.open': 'リンクを開く', 'collab.whatsNext.title': '次にすること', 'collab.whatsNext.today': '今日', 'collab.whatsNext.tomorrow': '明日', diff --git a/shared/src/i18n/ko/collab.ts b/shared/src/i18n/ko/collab.ts index 96839286d..bdc367907 100644 --- a/shared/src/i18n/ko/collab.ts +++ b/shared/src/i18n/ko/collab.ts @@ -23,6 +23,8 @@ const collab: TranslationStrings = { 'collab.links.pin': '링크 고정', 'collab.links.unpin': '링크 고정 해제', 'collab.links.delete': '링크 삭제', + 'collab.links.edit': '링크 편집', + 'collab.links.open': '링크 열기', 'collab.whatsNext.title': '다음 할 일', 'collab.whatsNext.today': '오늘', 'collab.whatsNext.tomorrow': '내일', diff --git a/shared/src/i18n/nl/collab.ts b/shared/src/i18n/nl/collab.ts index 3567ced61..1abb00e60 100644 --- a/shared/src/i18n/nl/collab.ts +++ b/shared/src/i18n/nl/collab.ts @@ -23,6 +23,8 @@ const collab: TranslationStrings = { 'collab.links.pin': 'Link vastmaken', 'collab.links.unpin': 'Link losmaken', 'collab.links.delete': 'Link verwijderen', + 'collab.links.edit': 'Link bewerken', + 'collab.links.open': 'Link openen', 'collab.whatsNext.title': 'Wat komt er', 'collab.whatsNext.today': 'Vandaag', 'collab.whatsNext.tomorrow': 'Morgen', diff --git a/shared/src/i18n/pl/collab.ts b/shared/src/i18n/pl/collab.ts index f605554bd..de4fb3598 100644 --- a/shared/src/i18n/pl/collab.ts +++ b/shared/src/i18n/pl/collab.ts @@ -23,6 +23,8 @@ const collab: TranslationStrings = { 'collab.links.pin': 'Przypnij link', 'collab.links.unpin': 'Odepnij link', 'collab.links.delete': 'Usuń link', + 'collab.links.edit': 'Edytuj link', + 'collab.links.open': 'Otwórz link', 'collab.whatsNext.title': 'Co dalej', 'collab.whatsNext.today': 'Dzisiaj', 'collab.whatsNext.tomorrow': 'Jutro', diff --git a/shared/src/i18n/ru/collab.ts b/shared/src/i18n/ru/collab.ts index 41611e33d..f7c7c2881 100644 --- a/shared/src/i18n/ru/collab.ts +++ b/shared/src/i18n/ru/collab.ts @@ -23,6 +23,8 @@ const collab: TranslationStrings = { 'collab.links.pin': 'Закрепить ссылку', 'collab.links.unpin': 'Открепить ссылку', 'collab.links.delete': 'Удалить ссылку', + 'collab.links.edit': 'Изменить ссылку', + 'collab.links.open': 'Открыть ссылку', 'collab.whatsNext.title': 'Что дальше', 'collab.whatsNext.today': 'Сегодня', 'collab.whatsNext.tomorrow': 'Завтра', diff --git a/shared/src/i18n/sv/collab.ts b/shared/src/i18n/sv/collab.ts index 676ca815a..bf5badd2c 100644 --- a/shared/src/i18n/sv/collab.ts +++ b/shared/src/i18n/sv/collab.ts @@ -23,6 +23,8 @@ const collab: TranslationStrings = { 'collab.links.pin': 'Fäst länk', 'collab.links.unpin': 'Lossa länk', 'collab.links.delete': 'Ta bort länk', + 'collab.links.edit': 'Redigera länk', + 'collab.links.open': 'Öppna länk', 'collab.whatsNext.title': 'Vad händer härnäst?', 'collab.whatsNext.today': 'Idag', 'collab.whatsNext.tomorrow': 'I morgon', diff --git a/shared/src/i18n/tr/collab.ts b/shared/src/i18n/tr/collab.ts index 569047ec9..95ad138a2 100644 --- a/shared/src/i18n/tr/collab.ts +++ b/shared/src/i18n/tr/collab.ts @@ -23,6 +23,8 @@ const collab: TranslationStrings = { 'collab.links.pin': 'Bağlantıyı sabitle', 'collab.links.unpin': 'Sabitlemeyi kaldır', 'collab.links.delete': 'Bağlantıyı sil', + 'collab.links.edit': 'Bağlantıyı düzenle', + 'collab.links.open': 'Bağlantıyı aç', 'collab.whatsNext.title': "What's Next", 'collab.whatsNext.today': 'Bugün', 'collab.whatsNext.tomorrow': 'Yarın', diff --git a/shared/src/i18n/uk/collab.ts b/shared/src/i18n/uk/collab.ts index f343ad14b..df9ed1bb0 100644 --- a/shared/src/i18n/uk/collab.ts +++ b/shared/src/i18n/uk/collab.ts @@ -23,6 +23,8 @@ const collab: TranslationStrings = { 'collab.links.pin': 'Закріпити посилання', 'collab.links.unpin': 'Відкріпити посилання', 'collab.links.delete': 'Видалити посилання', + 'collab.links.edit': 'Редагувати посилання', + 'collab.links.open': 'Відкрити посилання', 'collab.whatsNext.title': 'Що далі', 'collab.whatsNext.today': 'Сьогодні', 'collab.whatsNext.tomorrow': 'Завтра', diff --git a/shared/src/i18n/vi/collab.ts b/shared/src/i18n/vi/collab.ts index 603da8a4c..c1a26a10e 100644 --- a/shared/src/i18n/vi/collab.ts +++ b/shared/src/i18n/vi/collab.ts @@ -23,6 +23,8 @@ const collab: TranslationStrings = { 'collab.links.pin': 'Ghim liên kết', 'collab.links.unpin': 'Bỏ ghim liên kết', 'collab.links.delete': 'Xóa liên kết', + 'collab.links.edit': 'Chỉnh sửa liên kết', + 'collab.links.open': 'Mở liên kết', 'collab.whatsNext.title': 'Tiếp theo là gì', 'collab.whatsNext.today': 'Hôm nay', 'collab.whatsNext.tomorrow': 'Ngày mai', diff --git a/shared/src/i18n/zh-TW/collab.ts b/shared/src/i18n/zh-TW/collab.ts index c26f74bff..e146932ff 100644 --- a/shared/src/i18n/zh-TW/collab.ts +++ b/shared/src/i18n/zh-TW/collab.ts @@ -23,6 +23,8 @@ const collab: TranslationStrings = { 'collab.links.pin': '釘選連結', 'collab.links.unpin': '取消釘選連結', 'collab.links.delete': '刪除連結', + 'collab.links.edit': '編輯連結', + 'collab.links.open': '開啟連結', 'collab.whatsNext.title': '接下來', 'collab.whatsNext.today': '今天', 'collab.whatsNext.tomorrow': '明天', diff --git a/shared/src/i18n/zh/collab.ts b/shared/src/i18n/zh/collab.ts index f9ad4a001..adbf3de50 100644 --- a/shared/src/i18n/zh/collab.ts +++ b/shared/src/i18n/zh/collab.ts @@ -23,6 +23,8 @@ const collab: TranslationStrings = { 'collab.links.pin': '固定链接', 'collab.links.unpin': '取消固定链接', 'collab.links.delete': '删除链接', + 'collab.links.edit': '编辑链接', + 'collab.links.open': '打开链接', 'collab.whatsNext.title': '接下来', 'collab.whatsNext.today': '今天', 'collab.whatsNext.tomorrow': '明天',