✨(frontend) add EmojiPicker in DocumentTitle
We can now add emojis to the document title using the EmojiPicker component.
This commit is contained in:
committed by
Anthony LC
parent
b1d033edc9
commit
08f3ceaf3f
@@ -65,16 +65,36 @@ test.describe('Doc Header', () => {
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
await createDoc(page, 'doc-update', browserName, 1);
|
||||
await createDoc(page, 'doc-update-emoji', browserName, 1);
|
||||
|
||||
const emojiPicker = page.locator('.--docs--doc-title').getByRole('button');
|
||||
|
||||
// Top parent should not have emoji picker
|
||||
await expect(emojiPicker).toBeHidden();
|
||||
|
||||
const { name: docChild } = await createRootSubPage(
|
||||
page,
|
||||
browserName,
|
||||
'doc-update-emoji-child',
|
||||
);
|
||||
|
||||
await verifyDocName(page, docChild);
|
||||
|
||||
await expect(emojiPicker).toBeVisible();
|
||||
await emojiPicker.click({
|
||||
delay: 100,
|
||||
});
|
||||
await page.getByRole('button', { name: '😀' }).first().click();
|
||||
await expect(emojiPicker).toHaveText('😀');
|
||||
|
||||
const docTitle = page.getByRole('textbox', { name: 'Document title' });
|
||||
await expect(docTitle).toBeVisible();
|
||||
await docTitle.fill('👍 Hello Emoji World');
|
||||
await docTitle.fill('Hello Emoji World');
|
||||
await docTitle.blur();
|
||||
await verifyDocName(page, '👍 Hello Emoji World');
|
||||
await verifyDocName(page, 'Hello Emoji World');
|
||||
|
||||
// Check the tree
|
||||
const row = await getTreeRow(page, 'Hello Emoji World');
|
||||
await expect(row.getByText('👍')).toBeVisible();
|
||||
await expect(row.getByText('😀')).toBeVisible();
|
||||
});
|
||||
|
||||
test('it deletes the doc', async ({ page, browserName }) => {
|
||||
|
||||
@@ -340,9 +340,11 @@ test.describe('Doc Tree', () => {
|
||||
|
||||
// Verify the emoji is updated in the tree and in the document title
|
||||
await expect(row.getByText('😀')).toBeVisible();
|
||||
await expect(
|
||||
page.getByRole('textbox', { name: 'Document title' }),
|
||||
).toContainText('😀');
|
||||
|
||||
const titleEmojiPicker = page
|
||||
.locator('.--docs--doc-title')
|
||||
.getByRole('button');
|
||||
await expect(titleEmojiPicker).toHaveText('😀');
|
||||
|
||||
// Now remove the emoji using the new action
|
||||
await row.hover();
|
||||
@@ -350,9 +352,7 @@ test.describe('Doc Tree', () => {
|
||||
await page.getByRole('menuitem', { name: 'Remove emoji' }).click();
|
||||
|
||||
await expect(row.getByText('😀')).toBeHidden();
|
||||
await expect(
|
||||
page.getByRole('textbox', { name: 'Document title' }),
|
||||
).not.toContainText('😀');
|
||||
await expect(titleEmojiPicker).not.toHaveText('😀');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ export const EmojiPicker = ({
|
||||
const { i18n } = useTranslation();
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Box $position="absolute" $zIndex={1000} $margin="2rem 0 0 0">
|
||||
<Picker
|
||||
data={emojiData}
|
||||
locale={i18n.resolvedLanguage}
|
||||
|
||||
@@ -7,11 +7,15 @@ import { Box, Text } from '@/components';
|
||||
import { useCunninghamTheme } from '@/cunningham';
|
||||
import {
|
||||
Doc,
|
||||
DocIcon,
|
||||
getEmojiAndTitle,
|
||||
useDocStore,
|
||||
useDocTitleUpdate,
|
||||
useDocUtils,
|
||||
useIsCollaborativeEditable,
|
||||
useTrans,
|
||||
} from '@/docs/doc-management';
|
||||
import SimpleFileIcon from '@/features/docs/doc-management/assets/simple-document.svg';
|
||||
import { useResponsiveStore } from '@/stores';
|
||||
|
||||
interface DocTitleProps {
|
||||
@@ -46,22 +50,77 @@ export const DocTitleText = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const DocTitleEmojiPicker = ({ doc }: DocTitleProps) => {
|
||||
const { t } = useTranslation();
|
||||
const { colorsTokens } = useCunninghamTheme();
|
||||
const { emoji } = getEmojiAndTitle(doc.title ?? '');
|
||||
|
||||
return (
|
||||
<Tooltip content={t('Document emoji')} aria-hidden={true} placement="top">
|
||||
<Box
|
||||
$css={css`
|
||||
padding: 4px;
|
||||
padding-top: 3px;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background-color: ${colorsTokens['greyscale-100']};
|
||||
border-radius: 4px;
|
||||
}
|
||||
transition: background-color 0.2s ease-in-out;
|
||||
`}
|
||||
>
|
||||
<DocIcon
|
||||
withEmojiPicker={doc.abilities.partial_update}
|
||||
docId={doc.id}
|
||||
title={doc.title}
|
||||
emoji={emoji}
|
||||
$size="25px"
|
||||
defaultIcon={
|
||||
<SimpleFileIcon
|
||||
width="25px"
|
||||
height="25px"
|
||||
aria-hidden="true"
|
||||
aria-label={t('Simple document icon')}
|
||||
color={colorsTokens['primary-500']}
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</Box>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
const DocTitleInput = ({ doc }: DocTitleProps) => {
|
||||
const { isDesktop } = useResponsiveStore();
|
||||
const { t } = useTranslation();
|
||||
const { colorsTokens } = useCunninghamTheme();
|
||||
const [titleDisplay, setTitleDisplay] = useState(doc.title);
|
||||
|
||||
const { spacingsTokens } = useCunninghamTheme();
|
||||
const { isTopRoot } = useDocUtils(doc);
|
||||
const { untitledDocument } = useTrans();
|
||||
const { emoji, titleWithoutEmoji } = getEmojiAndTitle(doc.title ?? '');
|
||||
const [titleDisplay, setTitleDisplay] = useState(
|
||||
isTopRoot ? doc.title : titleWithoutEmoji,
|
||||
);
|
||||
|
||||
const { updateDocTitle } = useDocTitleUpdate();
|
||||
|
||||
const handleTitleSubmit = useCallback(
|
||||
(inputText: string) => {
|
||||
const sanitizedTitle = updateDocTitle(doc, inputText.trim());
|
||||
setTitleDisplay(sanitizedTitle);
|
||||
if (isTopRoot) {
|
||||
const sanitizedTitle = updateDocTitle(doc, inputText);
|
||||
setTitleDisplay(sanitizedTitle);
|
||||
} else {
|
||||
const sanitizedTitle = updateDocTitle(
|
||||
doc,
|
||||
emoji ? `${emoji} ${inputText}` : inputText,
|
||||
);
|
||||
const { titleWithoutEmoji: sanitizedTitleWithoutEmoji } =
|
||||
getEmojiAndTitle(sanitizedTitle);
|
||||
|
||||
setTitleDisplay(sanitizedTitleWithoutEmoji);
|
||||
}
|
||||
},
|
||||
[doc, updateDocTitle],
|
||||
[updateDocTitle, doc, emoji, isTopRoot],
|
||||
);
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
@@ -72,43 +131,62 @@ const DocTitleInput = ({ doc }: DocTitleProps) => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
setTitleDisplay(doc.title);
|
||||
}, [doc]);
|
||||
setTitleDisplay(isTopRoot ? doc.title : titleWithoutEmoji);
|
||||
}, [doc.title, isTopRoot, titleWithoutEmoji]);
|
||||
|
||||
return (
|
||||
<Tooltip content={t('Rename')} aria-hidden={true} placement="top">
|
||||
<Box
|
||||
as="span"
|
||||
role="textbox"
|
||||
className="--docs--doc-title-input"
|
||||
contentEditable
|
||||
defaultValue={titleDisplay || undefined}
|
||||
onKeyDownCapture={handleKeyDown}
|
||||
suppressContentEditableWarning={true}
|
||||
aria-label={`${t('Document title')}`}
|
||||
aria-multiline={false}
|
||||
onBlurCapture={(event) =>
|
||||
handleTitleSubmit(event.target.textContent || '')
|
||||
}
|
||||
$color={colorsTokens['greyscale-1000']}
|
||||
$minHeight="40px"
|
||||
$padding={{ right: 'big' }}
|
||||
$css={css`
|
||||
&[contenteditable='true']:empty:not(:focus):before {
|
||||
content: '${untitledDocument}';
|
||||
color: grey;
|
||||
pointer-events: none;
|
||||
font-style: italic;
|
||||
<Box
|
||||
className="--docs--doc-title"
|
||||
$direction="row"
|
||||
$align="center"
|
||||
$gap={spacingsTokens['xs']}
|
||||
$minHeight="40px"
|
||||
>
|
||||
{isTopRoot && (
|
||||
<SimpleFileIcon
|
||||
width="25px"
|
||||
height="25px"
|
||||
aria-hidden="true"
|
||||
aria-label={t('Simple document icon')}
|
||||
color={colorsTokens['primary-500']}
|
||||
style={{ flexShrink: '0' }}
|
||||
/>
|
||||
)}
|
||||
{!isTopRoot && <DocTitleEmojiPicker doc={doc} />}
|
||||
|
||||
<Tooltip content={t('Rename')} aria-hidden={true} placement="top">
|
||||
<Box
|
||||
as="span"
|
||||
role="textbox"
|
||||
className="--docs--doc-title-input"
|
||||
contentEditable
|
||||
defaultValue={titleDisplay || undefined}
|
||||
onKeyDownCapture={handleKeyDown}
|
||||
suppressContentEditableWarning={true}
|
||||
aria-label={`${t('Document title')}`}
|
||||
aria-multiline={false}
|
||||
onBlurCapture={(event) =>
|
||||
handleTitleSubmit(event.target.textContent || '')
|
||||
}
|
||||
font-size: ${isDesktop
|
||||
? css`var(--c--theme--font--sizes--h2)`
|
||||
: css`var(--c--theme--font--sizes--sm)`};
|
||||
font-weight: 700;
|
||||
outline: none;
|
||||
`}
|
||||
>
|
||||
{titleDisplay}
|
||||
</Box>
|
||||
</Tooltip>
|
||||
$color={colorsTokens['greyscale-1000']}
|
||||
$padding={{ right: 'big' }}
|
||||
$css={css`
|
||||
&[contenteditable='true']:empty:not(:focus):before {
|
||||
content: '${untitledDocument}';
|
||||
color: grey;
|
||||
pointer-events: none;
|
||||
font-style: italic;
|
||||
}
|
||||
font-size: ${isDesktop
|
||||
? css`var(--c--theme--font--sizes--h2)`
|
||||
: css`var(--c--theme--font--sizes--sm)`};
|
||||
font-weight: 700;
|
||||
outline: none;
|
||||
`}
|
||||
>
|
||||
{titleDisplay}
|
||||
</Box>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -20,9 +20,11 @@ import {
|
||||
KEY_DOC,
|
||||
KEY_LIST_DOC,
|
||||
ModalRemoveDoc,
|
||||
getEmojiAndTitle,
|
||||
useCopyDocLink,
|
||||
useCreateFavoriteDoc,
|
||||
useDeleteFavoriteDoc,
|
||||
useDocTitleUpdate,
|
||||
useDocUtils,
|
||||
useDuplicateDoc,
|
||||
} from '@/docs/doc-management';
|
||||
@@ -49,7 +51,7 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
|
||||
const treeContext = useTreeContext<Doc>();
|
||||
const queryClient = useQueryClient();
|
||||
const router = useRouter();
|
||||
const { isChild } = useDocUtils(doc);
|
||||
const { isChild, isTopRoot } = useDocUtils(doc);
|
||||
|
||||
const { spacingsTokens, colorsTokens } = useCunninghamTheme();
|
||||
|
||||
@@ -83,6 +85,10 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
|
||||
});
|
||||
}, [selectHistoryModal.isOpen, queryClient]);
|
||||
|
||||
// Emoji Management
|
||||
const { emoji } = getEmojiAndTitle(doc.title ?? '');
|
||||
const { updateDocEmoji } = useDocTitleUpdate();
|
||||
|
||||
const options: DropdownMenuOption[] = [
|
||||
...(isSmallMobile
|
||||
? [
|
||||
@@ -118,6 +124,17 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
|
||||
},
|
||||
testId: `docs-actions-${doc.is_favorite ? 'unpin' : 'pin'}-${doc.id}`,
|
||||
},
|
||||
...(emoji && doc.abilities.partial_update && !isTopRoot
|
||||
? [
|
||||
{
|
||||
label: t('Remove emoji'),
|
||||
icon: 'emoji_emotions',
|
||||
callback: () => {
|
||||
updateDocEmoji(doc.id, doc.title ?? '', '');
|
||||
},
|
||||
},
|
||||
]
|
||||
: []),
|
||||
{
|
||||
label: t('Version history'),
|
||||
icon: 'history',
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
<svg
|
||||
width="33"
|
||||
height="33"
|
||||
viewBox="0 0 33 33"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
|
||||
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 6.2 KiB |
@@ -73,6 +73,8 @@ export const SimpleDocItem = ({
|
||||
/>
|
||||
) : (
|
||||
<SimpleFileIcon
|
||||
width="32px"
|
||||
height="32px"
|
||||
aria-hidden="true"
|
||||
data-testid="doc-simple-icon"
|
||||
color={colorsTokens['primary-500']}
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
"Document access mode": "Doare moned ar restr",
|
||||
"Document accessible to any connected person": "Restr a c'hall bezañ tizhet gant ne vern piv a vefe kevreet",
|
||||
"Document duplicated successfully!": "Restr eilet gant berzh!",
|
||||
"Document emoji": "Emoju ar restr",
|
||||
"Document owner": "Perc'henn ar restr",
|
||||
"Document role text": "Testenn rol ar restr",
|
||||
"Document sections": "Kevrennoù ar restr",
|
||||
@@ -175,6 +176,7 @@
|
||||
"Reader": "Lenner",
|
||||
"Reading": "Lenn hepken",
|
||||
"Remove access": "Dilemel ar moned",
|
||||
"Remove emoji": "Dilemel ar emoju",
|
||||
"Rename": "Adenvel",
|
||||
"Rephrase": "Adformulenniñ",
|
||||
"Request access": "Goulenn mont e-barzh",
|
||||
@@ -296,6 +298,7 @@
|
||||
"Docs: Your new companion to collaborate on documents efficiently, intuitively, and securely.": "Pages: Ihr neuer Begleiter für eine effiziente, intuitive und sichere Zusammenarbeit bei Dokumenten.",
|
||||
"Document accessible to any connected person": "Dokument für jeden angemeldeten Benutzer zugänglich",
|
||||
"Document duplicated successfully!": "Dokument erfolgreich dupliziert!",
|
||||
"Document emoji": "Dokument-Emoji",
|
||||
"Document owner": "Besitzer des Dokuments",
|
||||
"Docx": "Docx",
|
||||
"Download": "Herunterladen",
|
||||
@@ -378,6 +381,7 @@
|
||||
"Reader": "Leser",
|
||||
"Reading": "Lesen",
|
||||
"Remove access": "Zugriff entziehen",
|
||||
"Remove emoji": "Emoji entfernen",
|
||||
"Rename": "Umbenennen",
|
||||
"Rephrase": "Umformulieren",
|
||||
"Request access": "Zugriff anfragen",
|
||||
@@ -496,6 +500,7 @@
|
||||
"Docs transforms your documents into knowledge bases thanks to subpages, powerful search and the ability to pin your important documents.": "Docs transforma sus documentos en bases de conocimiento gracias a las subpáginas, una potente herramienta de búsqueda y la capacidad de marcar como favorito sus documentos más importantes.",
|
||||
"Docs: Your new companion to collaborate on documents efficiently, intuitively, and securely.": "Docs: su nuevo compañero para colaborar en documentos de forma eficiente, intuitiva y segura.",
|
||||
"Document accessible to any connected person": "Documento accesible a cualquier persona conectada",
|
||||
"Document emoji": "Emoji del documento",
|
||||
"Document owner": "Propietario del documento",
|
||||
"Docx": "Docx",
|
||||
"Download": "Descargar",
|
||||
@@ -565,6 +570,7 @@
|
||||
"Quick search input": "Entrada de búsqueda rápida",
|
||||
"Reader": "Lector",
|
||||
"Reading": "Lectura",
|
||||
"Remove emoji": "Eliminar emoji",
|
||||
"Rename": "Cambiar el nombre",
|
||||
"Rephrase": "Reformular",
|
||||
"Request access": "Solicitar acceso",
|
||||
@@ -694,6 +700,7 @@
|
||||
"Document accessible to any connected person": "Document accessible à toute personne connectée",
|
||||
"Document deleted": "Document supprimé",
|
||||
"Document duplicated successfully!": "Document dupliqué avec succès !",
|
||||
"Document emoji": "Emoji du document",
|
||||
"Document owner": "Propriétaire du document",
|
||||
"Document role text": "Texte du rôle du document",
|
||||
"Document sections": "Sections du document",
|
||||
@@ -806,6 +813,7 @@
|
||||
"Reader": "Lecteur",
|
||||
"Reading": "Lecture seule",
|
||||
"Remove access": "Supprimer l'accès",
|
||||
"Remove emoji": "Supprimer l'emoji",
|
||||
"Rename": "Renommer",
|
||||
"Rephrase": "Reformuler",
|
||||
"Request access": "Demander l'accès",
|
||||
@@ -930,6 +938,7 @@
|
||||
"Docs transforms your documents into knowledge bases thanks to subpages, powerful search and the ability to pin your important documents.": "Docs trasforma i tuoi documenti in piattaforme di conoscenza grazie alle sotto-pagine, alla ricerca potente e alla capacità di fissare i tuoi documenti importanti.",
|
||||
"Docs: Your new companion to collaborate on documents efficiently, intuitively, and securely.": "Docs: Il tuo nuovo compagno di collaborare sui documenti in modo efficiente, intuitivo e sicuro.",
|
||||
"Document accessible to any connected person": "Documento accessibile a qualsiasi persona collegata",
|
||||
"Document emoji": "Emoji del documento",
|
||||
"Document owner": "Proprietario del documento",
|
||||
"Docx": "Docx",
|
||||
"Download": "Scarica",
|
||||
@@ -990,6 +999,7 @@
|
||||
"Public document": "Documento pubblico",
|
||||
"Reader": "Lettore",
|
||||
"Reading": "Leggendo",
|
||||
"Remove emoji": "Rimuovi emoji",
|
||||
"Rename": "Rinomina",
|
||||
"Rephrase": "Riformula",
|
||||
"Restore": "Ripristina",
|
||||
@@ -1103,6 +1113,7 @@
|
||||
"Docs: Your new companion to collaborate on documents efficiently, intuitively, and securely.": "Docs: Je nieuwe metgezel om efficiënt, intuïtief en veilig samen te werken aan documenten.",
|
||||
"Document access mode": "Document toegangsmodus",
|
||||
"Document accessible to any connected person": "Document is toegankelijk voor ieder verbonden persoon",
|
||||
"Document emoji": "Document emoji",
|
||||
"Document duplicated successfully!": "Document met succes gedupliceerd!",
|
||||
"Document owner": "Document eigenaar",
|
||||
"Document role text": "Document roltekst",
|
||||
@@ -1214,6 +1225,7 @@
|
||||
"Reader": "Lezer",
|
||||
"Reading": "Lezen",
|
||||
"Remove access": "Toegang verwijderen",
|
||||
"Remove emoji": "Emoji verwijderen",
|
||||
"Rename": "Hernoemen",
|
||||
"Rephrase": "Herschrijf",
|
||||
"Request access": "Toegang aanvragen",
|
||||
@@ -1287,7 +1299,11 @@
|
||||
"pdf": "PDF"
|
||||
}
|
||||
},
|
||||
"pt": { "translation": {} },
|
||||
"pt": {
|
||||
"translation": {
|
||||
"Remove emoji": "Remover emoji"
|
||||
}
|
||||
},
|
||||
"ru": {
|
||||
"translation": {
|
||||
"\"{{email}}\" is already invited to the document.": "\"{{email}}\" уже имеет приглашение для этого документа.",
|
||||
@@ -1368,6 +1384,7 @@
|
||||
"Document accessible to any connected person": "Документ доступен всем, кто присоединится",
|
||||
"Document deleted": "Документ удалён",
|
||||
"Document duplicated successfully!": "Документ успешно дублирован!",
|
||||
"Document emoji": "Эмодзи документа",
|
||||
"Document owner": "Владелец документа",
|
||||
"Document role text": "Текст роли документа",
|
||||
"Document sections": "Разделы документа",
|
||||
@@ -1480,6 +1497,7 @@
|
||||
"Reader": "Читатель",
|
||||
"Reading": "Чтение",
|
||||
"Remove access": "Отменить доступ",
|
||||
"Remove emoji": "Убрать эмодзи",
|
||||
"Rename": "Переименовать",
|
||||
"Rephrase": "Переформулировать",
|
||||
"Request access": "Запрос доступа",
|
||||
@@ -1565,6 +1583,7 @@
|
||||
"sl": {
|
||||
"translation": {
|
||||
"Load more": "Naloži več",
|
||||
"Remove emoji": "Odstrani emoji",
|
||||
"Untitled document": "Dokument brez naslova"
|
||||
}
|
||||
},
|
||||
@@ -1598,7 +1617,8 @@
|
||||
"This file is flagged as unsafe.": "Denna fil är flaggad som osäker.",
|
||||
"Too many requests. Please wait 60 seconds.": "För många förfrågningar. Vänligen vänta 60 sekunder.",
|
||||
"Use as prompt": "Använd som prompt",
|
||||
"Warning": "Varning"
|
||||
"Warning": "Varning",
|
||||
"Remove emoji": "Ta bort emoji"
|
||||
}
|
||||
},
|
||||
"tr": {
|
||||
@@ -1625,6 +1645,7 @@
|
||||
"Docs": "Docs",
|
||||
"Docs Logo": "Docs logosu",
|
||||
"Document accessible to any connected person": "Bağlanan herhangi bir kişi tarafından erişilebilen belge",
|
||||
"Document emoji": "Belge emojisi",
|
||||
"Docx": "Docx",
|
||||
"Download": "İndir",
|
||||
"Download anyway": "Yine de indir",
|
||||
@@ -1668,7 +1689,8 @@
|
||||
"Version history": "Sürüm geçmişi",
|
||||
"Warning": "Uyarı",
|
||||
"Write": "Yaz",
|
||||
"Your {{format}} was downloaded succesfully": "{{format}} indirildi"
|
||||
"Your {{format}} was downloaded succesfully": "{{format}} indirildi",
|
||||
"Remove emoji": "Emoji kaldır"
|
||||
}
|
||||
},
|
||||
"uk": {
|
||||
@@ -1751,6 +1773,7 @@
|
||||
"Document accessible to any connected person": "Документ, доступний для будь-якої особи, що приєдналася",
|
||||
"Document deleted": "Документ видалено",
|
||||
"Document duplicated successfully!": "Документ успішно продубльовано!",
|
||||
"Document emoji": "Емодзі документа",
|
||||
"Document owner": "Власник документа",
|
||||
"Document role text": "Текст ролі документа",
|
||||
"Document sections": "Розділи документу",
|
||||
@@ -1863,6 +1886,7 @@
|
||||
"Reader": "Читач",
|
||||
"Reading": "Читання",
|
||||
"Remove access": "Вилучити доступ",
|
||||
"Remove emoji": "Видалити емодзі",
|
||||
"Rename": "Перейменувати",
|
||||
"Rephrase": "Перефразувати",
|
||||
"Request access": "Запит доступу",
|
||||
@@ -2000,6 +2024,7 @@
|
||||
"Docs transforms your documents into knowledge bases thanks to subpages, powerful search and the ability to pin your important documents.": "Docs 通过子页面、强大的搜索功能以及固定重要文档的能力,将您的文档转化为知识库。",
|
||||
"Docs: Your new companion to collaborate on documents efficiently, intuitively, and securely.": "Docs 为您提供高效、直观且安全的文档协作解决方案。",
|
||||
"Document accessible to any connected person": "任何来访的人都可以访问文档",
|
||||
"Document emoji": "文档表情符号",
|
||||
"Document owner": "文档所有者",
|
||||
"Document title": "文档标题",
|
||||
"Docx": "Doc",
|
||||
@@ -2076,6 +2101,7 @@
|
||||
"Quick search input": "快速搜索",
|
||||
"Reader": "阅读者",
|
||||
"Reading": "阅读中",
|
||||
"Remove emoji": "移除表情符号",
|
||||
"Rename": "重命名",
|
||||
"Rephrase": "改写",
|
||||
"Reset": "重置",
|
||||
|
||||
Reference in New Issue
Block a user