✨(frontend) improve accessibility of cdoc content with correct aria tags
added appropriate aria attributes and semantic tags to enhance accessibility Signed-off-by: Cyril <c.gromoff@gmail.com>
This commit is contained in:
@@ -38,6 +38,7 @@ and this project adheres to
|
||||
- ♿(frontend) improve accessibility for decorative images in editor #1282
|
||||
- #1338
|
||||
- #1281
|
||||
- #1271
|
||||
- ♻️(backend) fallback to email identifier when no name #1298
|
||||
- 🐛(backend) allow ASCII characters in user sub field #1295
|
||||
- ⚡️(frontend) improve fallback width calculation #1333
|
||||
|
||||
@@ -45,8 +45,8 @@ test.describe('Doc Create', () => {
|
||||
})
|
||||
.click();
|
||||
|
||||
const input = page.getByRole('textbox', { name: 'doc title input' });
|
||||
await expect(input).toHaveText('');
|
||||
const input = page.getByRole('textbox', { name: 'Document title' });
|
||||
await expect(input).toHaveText('', { timeout: 10000 });
|
||||
await expect(
|
||||
page.locator('.c__tree-view--row-content').getByText('Untitled document'),
|
||||
).toBeVisible();
|
||||
@@ -67,8 +67,8 @@ test.describe('Doc Create', () => {
|
||||
.getByText('New sub-doc')
|
||||
.click();
|
||||
|
||||
const input = page.getByRole('textbox', { name: 'doc title input' });
|
||||
await expect(input).toHaveText('');
|
||||
const input = page.getByRole('textbox', { name: 'Document title' });
|
||||
await expect(input).toHaveText('', { timeout: 10000 });
|
||||
await expect(
|
||||
page.locator('.c__tree-view--row-content').getByText('Untitled document'),
|
||||
).toBeVisible();
|
||||
|
||||
@@ -40,7 +40,7 @@ test.describe('Doc Export', () => {
|
||||
await expect(
|
||||
page.getByRole('button', { name: 'Close the modal' }),
|
||||
).toBeVisible();
|
||||
await expect(page.getByTestId('modal-download-button')).toBeVisible();
|
||||
await expect(page.getByTestId('doc-export-download-button')).toBeVisible();
|
||||
});
|
||||
|
||||
test('it exports the doc with pdf line break', async ({
|
||||
@@ -81,12 +81,7 @@ test.describe('Doc Export', () => {
|
||||
return download.suggestedFilename().includes(`${randomDoc}.pdf`);
|
||||
});
|
||||
|
||||
void page
|
||||
.getByRole('button', {
|
||||
name: 'Download',
|
||||
exact: true,
|
||||
})
|
||||
.click();
|
||||
void page.getByTestId('doc-export-download-button').click();
|
||||
|
||||
const download = await downloadPromise;
|
||||
expect(download.suggestedFilename()).toBe(`${randomDoc}.pdf`);
|
||||
@@ -131,13 +126,13 @@ test.describe('Doc Export', () => {
|
||||
await page.getByRole('combobox', { name: 'Format' }).click();
|
||||
await page.getByRole('option', { name: 'Docx' }).click();
|
||||
|
||||
await expect(page.getByTestId('modal-download-button')).toBeVisible();
|
||||
await expect(page.getByTestId('doc-export-download-button')).toBeVisible();
|
||||
|
||||
const downloadPromise = page.waitForEvent('download', (download) => {
|
||||
return download.suggestedFilename().includes(`${randomDoc}.docx`);
|
||||
});
|
||||
|
||||
void page.getByTestId('modal-download-button').click();
|
||||
void page.getByTestId('doc-export-download-button').click();
|
||||
|
||||
const download = await downloadPromise;
|
||||
expect(download.suggestedFilename()).toBe(`${randomDoc}.docx`);
|
||||
@@ -203,7 +198,7 @@ test.describe('Doc Export', () => {
|
||||
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
||||
|
||||
await expect(page.getByTestId('modal-download-button')).toBeVisible();
|
||||
await expect(page.getByTestId('doc-export-download-button')).toBeVisible();
|
||||
|
||||
const responseCorsPromise = page.waitForResponse(
|
||||
(response) =>
|
||||
@@ -214,7 +209,7 @@ test.describe('Doc Export', () => {
|
||||
return download.suggestedFilename().includes(`${randomDoc}.pdf`);
|
||||
});
|
||||
|
||||
void page.getByTestId('modal-download-button').click();
|
||||
void page.getByTestId('doc-export-download-button').click();
|
||||
|
||||
const responseCors = await responseCorsPromise;
|
||||
expect(responseCors.ok()).toBe(true);
|
||||
@@ -256,13 +251,13 @@ test.describe('Doc Export', () => {
|
||||
})
|
||||
.click();
|
||||
|
||||
await expect(page.getByTestId('modal-download-button')).toBeVisible();
|
||||
await expect(page.getByTestId('doc-export-download-button')).toBeVisible();
|
||||
|
||||
const downloadPromise = page.waitForEvent('download', (download) => {
|
||||
return download.suggestedFilename().includes(`${randomDoc}.pdf`);
|
||||
});
|
||||
|
||||
void page.getByTestId('modal-download-button').click();
|
||||
void page.getByTestId('doc-export-download-button').click();
|
||||
|
||||
const download = await downloadPromise;
|
||||
expect(download.suggestedFilename()).toBe(`${randomDoc}.pdf`);
|
||||
@@ -298,13 +293,15 @@ test.describe('Doc Export', () => {
|
||||
})
|
||||
.click();
|
||||
|
||||
await expect(page.getByTestId('modal-download-button')).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId('doc-open-modal-download-button'),
|
||||
).toBeVisible();
|
||||
|
||||
const downloadPromise = page.waitForEvent('download', (download) => {
|
||||
return download.suggestedFilename().includes(`${randomDoc}.pdf`);
|
||||
});
|
||||
|
||||
void page.getByTestId('modal-download-button').click();
|
||||
void page.getByTestId('doc-export-download-button').click();
|
||||
|
||||
const download = await downloadPromise;
|
||||
expect(download.suggestedFilename()).toBe(`${randomDoc}.pdf`);
|
||||
@@ -350,13 +347,15 @@ test.describe('Doc Export', () => {
|
||||
})
|
||||
.click();
|
||||
|
||||
await expect(page.getByTestId('modal-download-button')).toBeVisible();
|
||||
await expect(
|
||||
page.getByTestId('doc-open-modal-download-button'),
|
||||
).toBeVisible();
|
||||
|
||||
const downloadPromise = page.waitForEvent('download', (download) => {
|
||||
return download.suggestedFilename().includes(`${randomDoc}.pdf`);
|
||||
});
|
||||
|
||||
void page.getByTestId('modal-download-button').click();
|
||||
void page.getByTestId('doc-export-download-button').click();
|
||||
|
||||
const download = await downloadPromise;
|
||||
expect(download.suggestedFilename()).toBe(`${randomDoc}.pdf`);
|
||||
@@ -392,14 +391,9 @@ test.describe('Doc Export', () => {
|
||||
})
|
||||
.click();
|
||||
|
||||
await page.waitForURL('**/docs/**', {
|
||||
timeout: 10000,
|
||||
waitUntil: 'domcontentloaded',
|
||||
});
|
||||
|
||||
const input = page.getByLabel('doc title input');
|
||||
const input = page.locator('.--docs--doc-title-input[role="textbox"]');
|
||||
await expect(input).toBeVisible();
|
||||
await expect(input).toHaveText('');
|
||||
await expect(input).toHaveText('', { timeout: 10000 });
|
||||
await input.click();
|
||||
await input.fill(randomDocFrench);
|
||||
await input.blur();
|
||||
@@ -418,7 +412,7 @@ test.describe('Doc Export', () => {
|
||||
return download.suggestedFilename().includes(`${randomDocFrench}.pdf`);
|
||||
});
|
||||
|
||||
void page.getByTestId('modal-download-button').click();
|
||||
void page.getByTestId('doc-export-download-button').click();
|
||||
|
||||
const download = await downloadPromise;
|
||||
expect(download.suggestedFilename()).toBe(`${randomDocFrench}.pdf`);
|
||||
@@ -453,19 +447,23 @@ test.describe('Doc Export', () => {
|
||||
await page.locator('.bn-block-outer').last().fill('/');
|
||||
await page.getByText('Link a doc').first().click();
|
||||
|
||||
await page
|
||||
.locator(
|
||||
"span[data-inline-content-type='interlinkingSearchInline'] input",
|
||||
)
|
||||
.fill('interlink-child');
|
||||
const input = page.locator(
|
||||
"span[data-inline-content-type='interlinkingSearchInline'] input",
|
||||
);
|
||||
const searchContainer = page.locator('.quick-search-container');
|
||||
|
||||
await page
|
||||
.locator('.quick-search-container')
|
||||
.getByText('interlink-child')
|
||||
.click();
|
||||
await input.fill('export-interlink');
|
||||
|
||||
const interlink = page.getByRole('link', {
|
||||
name: 'interlink-child',
|
||||
await expect(searchContainer).toBeVisible();
|
||||
await expect(searchContainer.getByText(randomDoc)).toBeVisible();
|
||||
|
||||
// We are in docChild, we want to create a link to randomDoc (parent)
|
||||
await searchContainer.getByText(randomDoc).click();
|
||||
|
||||
// Search the interlinking link in the editor (not in the document tree)
|
||||
const editor = page.locator('.ProseMirror.bn-editor');
|
||||
const interlink = editor.getByRole('link', {
|
||||
name: randomDoc,
|
||||
});
|
||||
|
||||
await expect(interlink).toBeVisible();
|
||||
@@ -480,7 +478,7 @@ test.describe('Doc Export', () => {
|
||||
})
|
||||
.click();
|
||||
|
||||
void page.getByTestId('modal-download-button').click();
|
||||
void page.getByTestId('doc-export-download-button').click();
|
||||
|
||||
const download = await downloadPromise;
|
||||
expect(download.suggestedFilename()).toBe(`${docChild}.pdf`);
|
||||
@@ -488,6 +486,6 @@ test.describe('Doc Export', () => {
|
||||
const pdfBuffer = await cs.toBuffer(await download.createReadStream());
|
||||
const pdfData = await pdf(pdfBuffer);
|
||||
|
||||
expect(pdfData.text).toContain('interlink-child'); // This is the pdf text
|
||||
expect(pdfData.text).toContain(randomDoc);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -25,7 +25,7 @@ test.describe('Doc Header', () => {
|
||||
'It is the card information about the document.',
|
||||
);
|
||||
|
||||
const docTitle = card.getByRole('textbox', { name: 'doc title input' });
|
||||
const docTitle = card.getByRole('textbox', { name: 'Document title' });
|
||||
await expect(docTitle).toBeVisible();
|
||||
|
||||
await page.getByRole('button', { name: 'Share' }).click();
|
||||
@@ -54,7 +54,7 @@ test.describe('Doc Header', () => {
|
||||
|
||||
test('it updates the title doc', async ({ page, browserName }) => {
|
||||
await createDoc(page, 'doc-update', browserName, 1);
|
||||
const docTitle = page.getByRole('textbox', { name: 'doc title input' });
|
||||
const docTitle = page.getByRole('textbox', { name: 'Document title' });
|
||||
await expect(docTitle).toBeVisible();
|
||||
await docTitle.fill('Hello World');
|
||||
await docTitle.blur();
|
||||
@@ -66,7 +66,7 @@ test.describe('Doc Header', () => {
|
||||
browserName,
|
||||
}) => {
|
||||
await createDoc(page, 'doc-update', browserName, 1);
|
||||
const docTitle = page.getByRole('textbox', { name: 'doc title input' });
|
||||
const docTitle = page.getByRole('textbox', { name: 'Document title' });
|
||||
await expect(docTitle).toBeVisible();
|
||||
await docTitle.fill('👍 Hello Emoji World');
|
||||
await docTitle.blur();
|
||||
@@ -228,23 +228,27 @@ test.describe('Doc Header', () => {
|
||||
|
||||
await page.getByRole('button', { name: 'Share' }).click();
|
||||
|
||||
const shareModal = page.getByLabel('Share modal');
|
||||
const shareModal = page.getByRole('dialog', {
|
||||
name: 'Share modal content',
|
||||
});
|
||||
await expect(shareModal).toBeVisible();
|
||||
await expect(page.getByText('Share the document')).toBeVisible();
|
||||
|
||||
await expect(page.getByPlaceholder('Type a name or email')).toBeHidden();
|
||||
|
||||
const invitationCard = shareModal.getByLabel('List invitation card');
|
||||
await expect(invitationCard).toBeVisible();
|
||||
await expect(
|
||||
invitationCard.getByText('test@invitation.test').first(),
|
||||
).toBeVisible();
|
||||
await expect(invitationCard.getByLabel('doc-role-text')).toBeVisible();
|
||||
await expect(invitationCard.getByLabel('Document role text')).toBeVisible();
|
||||
await expect(
|
||||
invitationCard.getByRole('button', { name: 'more_horiz' }),
|
||||
).toBeHidden();
|
||||
|
||||
const memberCard = shareModal.getByLabel('List members card');
|
||||
await expect(memberCard.getByText('test@accesses.test')).toBeVisible();
|
||||
await expect(memberCard.getByLabel('doc-role-text')).toBeVisible();
|
||||
await expect(memberCard.getByLabel('Document role text')).toBeVisible();
|
||||
await expect(
|
||||
memberCard.getByRole('button', { name: 'more_horiz' }),
|
||||
).toBeHidden();
|
||||
@@ -296,17 +300,18 @@ test.describe('Doc Header', () => {
|
||||
await expect(page.getByPlaceholder('Type a name or email')).toBeHidden();
|
||||
|
||||
const invitationCard = shareModal.getByLabel('List invitation card');
|
||||
await expect(invitationCard).toBeVisible();
|
||||
await expect(
|
||||
invitationCard.getByText('test@invitation.test').first(),
|
||||
).toBeVisible();
|
||||
await expect(invitationCard.getByLabel('doc-role-text')).toBeVisible();
|
||||
await expect(invitationCard.getByLabel('Document role text')).toBeVisible();
|
||||
await expect(
|
||||
invitationCard.getByRole('button', { name: 'more_horiz' }),
|
||||
).toBeHidden();
|
||||
|
||||
const memberCard = shareModal.getByLabel('List members card');
|
||||
await expect(memberCard.getByText('test@accesses.test')).toBeVisible();
|
||||
await expect(memberCard.getByLabel('doc-role-text')).toBeVisible();
|
||||
await expect(memberCard.getByLabel('Document role text')).toBeVisible();
|
||||
await expect(
|
||||
memberCard.getByRole('button', { name: 'more_horiz' }),
|
||||
).toBeHidden();
|
||||
|
||||
@@ -60,32 +60,37 @@ test.describe('Doc Routing', () => {
|
||||
|
||||
await page.locator('.ProseMirror.bn-editor').fill('Hello World');
|
||||
|
||||
const responsePromise = page.route(
|
||||
/.*\/documents\/.*\/$|users\/me\/$/,
|
||||
async (route) => {
|
||||
const request = route.request();
|
||||
// Wait for the doc link (via its dynamic title) to be visible
|
||||
const docLink = page.getByRole('link', { name: docTitle });
|
||||
await expect(docLink).toBeVisible();
|
||||
|
||||
if (
|
||||
request.method().includes('PATCH') ||
|
||||
request.method().includes('GET')
|
||||
) {
|
||||
await route.fulfill({
|
||||
status: 401,
|
||||
json: {
|
||||
detail: 'Log in to access the document',
|
||||
},
|
||||
});
|
||||
} else {
|
||||
await route.continue();
|
||||
}
|
||||
},
|
||||
// Intercept GET/PATCH requests to return 401
|
||||
await page.route(/.*\/documents\/.*\/$|users\/me\/$/, async (route) => {
|
||||
const request = route.request();
|
||||
if (
|
||||
request.method().includes('PATCH') ||
|
||||
request.method().includes('GET')
|
||||
) {
|
||||
await route.fulfill({
|
||||
status: 401,
|
||||
json: { detail: 'Log in to access the document' },
|
||||
});
|
||||
} else {
|
||||
await route.continue();
|
||||
}
|
||||
});
|
||||
|
||||
// Explicitly wait for a 401 response after clicking
|
||||
const wait401 = page.waitForResponse(
|
||||
(resp) =>
|
||||
resp.status() === 401 &&
|
||||
/\/(documents\/[^/]+\/|users\/me\/)$/.test(resp.url()),
|
||||
);
|
||||
|
||||
await page.getByRole('link', { name: '401-doc-parent' }).click();
|
||||
await docLink.click();
|
||||
await wait401;
|
||||
|
||||
await responsePromise;
|
||||
|
||||
await expect(page.getByText('Log in to access the document')).toBeVisible({
|
||||
await expect(page.getByText('Log in to access the document.')).toBeVisible({
|
||||
timeout: 10000,
|
||||
});
|
||||
});
|
||||
|
||||
@@ -50,7 +50,7 @@ test.describe('Doc Tree', () => {
|
||||
await expect(subPageItem).toBeVisible();
|
||||
await subPageItem.click();
|
||||
await verifyDocName(page, '');
|
||||
const input = page.getByRole('textbox', { name: 'doc title input' });
|
||||
const input = page.getByRole('textbox', { name: 'Document title' });
|
||||
await input.click();
|
||||
const [randomDocName] = randomName('doc-tree-test', browserName, 1);
|
||||
await input.fill(randomDocName);
|
||||
@@ -196,7 +196,7 @@ test.describe('Doc Tree', () => {
|
||||
await page.getByText('Move to my docs').click();
|
||||
|
||||
await expect(
|
||||
page.getByRole('textbox', { name: 'doc title input' }),
|
||||
page.getByRole('textbox', { name: 'Document title' }),
|
||||
).not.toHaveText(docChild);
|
||||
|
||||
const header = page.locator('header').first();
|
||||
|
||||
@@ -101,10 +101,9 @@ export const createDoc = async (
|
||||
waitUntil: 'networkidle',
|
||||
});
|
||||
|
||||
const input = page.getByLabel('doc title input');
|
||||
const input = page.getByLabel('Document title');
|
||||
await expect(input).toBeVisible();
|
||||
await expect(input).toHaveText('');
|
||||
await input.click();
|
||||
|
||||
await input.fill(randomDocs[i]);
|
||||
await input.blur();
|
||||
@@ -120,10 +119,11 @@ export const verifyDocName = async (page: Page, docName: string) => {
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
/*replace toHaveText with toContainText to handle cases where emojis or other characters might be added*/
|
||||
try {
|
||||
await expect(
|
||||
page.getByRole('textbox', { name: 'doc title input' }),
|
||||
).toHaveText(docName);
|
||||
page.getByRole('textbox', { name: 'Document title' }),
|
||||
).toContainText(docName);
|
||||
} catch {
|
||||
await expect(page.getByRole('heading', { name: docName })).toBeVisible();
|
||||
}
|
||||
@@ -182,9 +182,9 @@ export const goToGridDoc = async (
|
||||
};
|
||||
|
||||
export const updateDocTitle = async (page: Page, title: string) => {
|
||||
const input = page.getByLabel('doc title input');
|
||||
await expect(input).toBeVisible();
|
||||
const input = page.getByRole('textbox', { name: 'Document title' });
|
||||
await expect(input).toHaveText('');
|
||||
await expect(input).toBeVisible();
|
||||
await input.click();
|
||||
await input.fill(title);
|
||||
await input.click();
|
||||
|
||||
@@ -145,12 +145,12 @@ export const ModalExport = ({ onClose, doc }: ModalExportProps) => {
|
||||
{t('Cancel')}
|
||||
</Button>
|
||||
<Button
|
||||
data-testid="doc-export-download-button"
|
||||
aria-label={t('Download')}
|
||||
color="primary"
|
||||
fullWidth
|
||||
onClick={() => void onSubmit()}
|
||||
disabled={isExporting}
|
||||
data-testid="modal-download-button"
|
||||
>
|
||||
{t('Download')}
|
||||
</Button>
|
||||
|
||||
@@ -105,7 +105,7 @@ const DocTitleInput = ({ doc }: DocTitleProps) => {
|
||||
}, [doc]);
|
||||
|
||||
return (
|
||||
<Tooltip content={t('Rename')} placement="top">
|
||||
<Tooltip content={t('Rename')} aria-hidden={true} placement="top">
|
||||
<Box
|
||||
as="span"
|
||||
role="textbox"
|
||||
@@ -114,7 +114,8 @@ const DocTitleInput = ({ doc }: DocTitleProps) => {
|
||||
defaultValue={titleDisplay || undefined}
|
||||
onKeyDownCapture={handleKeyDown}
|
||||
suppressContentEditableWarning={true}
|
||||
aria-label="doc title input"
|
||||
aria-label={`${t('Document title')}`}
|
||||
aria-multiline={false}
|
||||
onBlurCapture={(event) =>
|
||||
handleTitleSubmit(event.target.textContent || '')
|
||||
}
|
||||
|
||||
@@ -215,7 +215,7 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
|
||||
>
|
||||
<Button
|
||||
color="tertiary"
|
||||
aria-label="Share button"
|
||||
aria-label={t('Share button')}
|
||||
icon={
|
||||
<Icon iconName="group" $theme="primary" $variation="800" />
|
||||
}
|
||||
@@ -233,9 +233,15 @@ export const DocToolBox = ({ doc }: DocToolBoxProps) => {
|
||||
|
||||
{!isSmallMobile && ModalExport && (
|
||||
<Button
|
||||
data-testid="doc-open-modal-download-button"
|
||||
color="tertiary-text"
|
||||
icon={
|
||||
<Icon iconName="download" $theme="primary" $variation="800" />
|
||||
<Icon
|
||||
iconName="download"
|
||||
$theme="primary"
|
||||
$variation="800"
|
||||
aria-hidden={true}
|
||||
/>
|
||||
}
|
||||
onClick={() => {
|
||||
setIsModalExportOpen(true);
|
||||
|
||||
@@ -83,7 +83,7 @@ export const SimpleDocItem = ({
|
||||
<Box $justify="center" $overflow="auto">
|
||||
<Text
|
||||
aria-describedby="doc-title"
|
||||
aria-label={displayTitle}
|
||||
aria-label={doc.title || untitledDocument}
|
||||
$size="sm"
|
||||
$variation="1000"
|
||||
$weight="500"
|
||||
|
||||
@@ -102,7 +102,7 @@ export const DocRoleDropdown = ({
|
||||
|
||||
if (!canUpdate) {
|
||||
return (
|
||||
<Text aria-label="doc-role-text" $variation="600">
|
||||
<Text aria-label={t('Document role text')} $variation="600">
|
||||
{transRole(currentRole)}
|
||||
</Text>
|
||||
);
|
||||
|
||||
@@ -302,8 +302,11 @@
|
||||
"Document accessible to any connected person": "Dokument für jeden angemeldeten Benutzer zugänglich",
|
||||
"Document duplicated successfully!": "Dokument erfolgreich dupliziert!",
|
||||
"Document owner": "Besitzer des Dokuments",
|
||||
"Document title": "Dokumenttitel",
|
||||
"Document sections": "Dokumentabschnitte",
|
||||
"Docx": "Docx",
|
||||
"Download": "Herunterladen",
|
||||
"Download the document": "Dokument herunterladen",
|
||||
"Download anyway": "Trotzdem herunterladen",
|
||||
"Download your document in a .docx or .pdf format.": "Ihr Dokument als .docx- oder .pdf-Datei herunterladen.",
|
||||
"Duplicate": "Duplizieren",
|
||||
@@ -451,6 +454,7 @@
|
||||
"en": {
|
||||
"translation": {
|
||||
"Back to homepage": "Back to Docs homepage",
|
||||
"Document title": "Document title",
|
||||
"Search docs": "Search docs",
|
||||
"More options": "More options",
|
||||
"Pinned documents": "Pinned documents",
|
||||
@@ -527,8 +531,11 @@
|
||||
"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 owner": "Propietario del documento",
|
||||
"Document title": "Título del documento",
|
||||
"Document sections": "Secciones del documento",
|
||||
"Docx": "Docx",
|
||||
"Download": "Descargar",
|
||||
"Download the document": "Descargar el documento",
|
||||
"Download anyway": "Descargar de todos modos",
|
||||
"Download your document in a .docx or .pdf format.": "Descargue su documento en formato .docx o .pdf.",
|
||||
"Editor": "Editor",
|
||||
@@ -726,10 +733,12 @@
|
||||
"Document duplicated successfully!": "Document dupliqué avec succès !",
|
||||
"Document emoji icon": "Émoticônes du document",
|
||||
"Document owner": "Propriétaire du document",
|
||||
"Document title": "Titre du document",
|
||||
"Document sections": "Sections du document",
|
||||
"Document visibility": "Visibilité du document",
|
||||
"Docx": "Docx",
|
||||
"Download": "Télécharger",
|
||||
"Download the document": "Télécharger le document",
|
||||
"Download anyway": "Télécharger malgré tout",
|
||||
"Download your document in a .docx or .pdf format.": "Téléchargez votre document au format .docx ou .pdf.",
|
||||
"Duplicate": "Dupliquer",
|
||||
@@ -1105,8 +1114,11 @@
|
||||
"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 accessible to any connected person": "Document is toegankelijk voor ieder verbonden persoon",
|
||||
"Document owner": "Document eigenaar",
|
||||
"Document title": "Documenttitel",
|
||||
"Document sections": "Document secties",
|
||||
"Docx": "Docx",
|
||||
"Download": "Download",
|
||||
"Download the document": "Document downloaden",
|
||||
"Download anyway": "Download alsnog",
|
||||
"Download your document in a .docx or .pdf format.": "Download jouw document in .docx of .pdf formaat.",
|
||||
"Editor": "Bewerker",
|
||||
|
||||
Reference in New Issue
Block a user