mirror of
https://github.com/suitenumerique/docs.git
synced 2026-05-12 01:47:01 +02:00
Compare commits
99 Commits
pr/dakshes
...
v3.9.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3ab01c98c8 | ||
|
|
6445c05e29 | ||
|
|
b9b25eb1f6 | ||
|
|
de157b4f52 | ||
|
|
e5581e52f7 | ||
|
|
b91840c819 | ||
|
|
a9b77fb9a7 | ||
|
|
66f83db0e5 | ||
|
|
f9ff578c6b | ||
|
|
1372438f8e | ||
|
|
c5d5d3dec4 | ||
|
|
ad16c0843c | ||
|
|
78a6307656 | ||
|
|
d7d468f51f | ||
|
|
eb71028f6b | ||
|
|
39c22b074d | ||
|
|
d5c3f248a5 | ||
|
|
91217b3c4f | ||
|
|
ab271bc90d | ||
|
|
82e1783317 | ||
|
|
aa2b9ed5f2 | ||
|
|
1c96d645ba | ||
|
|
2f010cf36d | ||
|
|
9d3c1eb9d5 | ||
|
|
08f3ceaf3f | ||
|
|
b1d033edc9 | ||
|
|
192fa76b54 | ||
|
|
b667200ebd | ||
|
|
294922f966 | ||
|
|
8b73aa3644 | ||
|
|
dd56a8abeb | ||
|
|
145c688830 | ||
|
|
950d215632 | ||
|
|
7d5cc4e84b | ||
|
|
3e5bcf96ea | ||
|
|
fe24c00178 | ||
|
|
aca334f81f | ||
|
|
2003e41c22 | ||
|
|
5ebdf4b4d4 | ||
|
|
35e771a1ce | ||
|
|
2b5a9e1af8 | ||
|
|
a833fdc7a1 | ||
|
|
b3cc2bf833 | ||
|
|
18feab10cb | ||
|
|
2777488d24 | ||
|
|
a11258f778 | ||
|
|
33647f124f | ||
|
|
e339cda5c6 | ||
|
|
4ce65c654f | ||
|
|
c048b2ae95 | ||
|
|
5908afb098 | ||
|
|
e2298a3658 | ||
|
|
278eb233e9 | ||
|
|
b056dbfad4 | ||
|
|
771ef2417f | ||
|
|
8d5262c2f2 | ||
|
|
1125f441dc | ||
|
|
16f2de4c75 | ||
|
|
f19fa93600 | ||
|
|
af3d90db3b | ||
|
|
127c90ca5f | ||
|
|
fa7cf7a594 | ||
|
|
6523165ea0 | ||
|
|
de4d11732f | ||
|
|
37138c1a23 | ||
|
|
2c1a9ff74f | ||
|
|
31389bcae2 | ||
|
|
f772801fd0 | ||
|
|
390a615f48 | ||
|
|
5bdf5d2210 | ||
|
|
ed336558ac | ||
|
|
4fbd588198 | ||
|
|
546f97c956 | ||
|
|
af01c6e466 | ||
|
|
8023720da3 | ||
|
|
91eba31735 | ||
|
|
45d6c1beef | ||
|
|
dc25f3f39c | ||
|
|
529e7f1737 | ||
|
|
51c5c4ee63 | ||
|
|
72f098c667 | ||
|
|
3b08ba4de1 | ||
|
|
590b67fd71 | ||
|
|
b3980e7bf1 | ||
|
|
e3b2fdbdf5 | ||
|
|
314a7fa7b0 | ||
|
|
93227466d2 | ||
|
|
db7ae350ec | ||
|
|
236c8df5ae | ||
|
|
ae1b05189e | ||
|
|
431c331154 | ||
|
|
5184723862 | ||
|
|
ca10fb9a12 | ||
|
|
59e875764c | ||
|
|
7ed46ab225 | ||
|
|
18f4ab880f | ||
|
|
e71c45077d | ||
|
|
14c84f000e | ||
|
|
6cc42636e5 |
14
.github/workflows/docker-hub.yml
vendored
14
.github/workflows/docker-hub.yml
vendored
@@ -31,7 +31,7 @@ jobs:
|
||||
images: lasuite/impress-backend
|
||||
-
|
||||
name: Login to DockerHub
|
||||
if: github.event_name != 'pull_request'
|
||||
if: github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'preview')
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USER }}
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
context: .
|
||||
target: backend-production
|
||||
build-args: DOCKER_USER=${{ env.DOCKER_USER }}:-1000
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
push: ${{ github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'preview') }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
@@ -67,7 +67,7 @@ jobs:
|
||||
images: lasuite/impress-frontend
|
||||
-
|
||||
name: Login to DockerHub
|
||||
if: github.event_name != 'pull_request'
|
||||
if: github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'preview')
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_HUB_USER }}
|
||||
@@ -88,7 +88,7 @@ jobs:
|
||||
build-args: |
|
||||
DOCKER_USER=${{ env.DOCKER_USER }}:-1000
|
||||
PUBLISH_AS_MIT=false
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
push: ${{ github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'preview') }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
@@ -106,7 +106,7 @@ jobs:
|
||||
images: lasuite/impress-y-provider
|
||||
-
|
||||
name: Login to DockerHub
|
||||
if: github.event_name != 'pull_request'
|
||||
if: github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'preview')
|
||||
run: echo "${{ secrets.DOCKER_HUB_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_HUB_USER }}" --password-stdin
|
||||
-
|
||||
name: Run trivy scan
|
||||
@@ -122,7 +122,7 @@ jobs:
|
||||
file: ./src/frontend/servers/y-provider/Dockerfile
|
||||
target: y-provider
|
||||
build-args: DOCKER_USER=${{ env.DOCKER_USER }}:-1000
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
push: ${{ github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'preview') }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
|
||||
@@ -131,7 +131,7 @@ jobs:
|
||||
- build-and-push-frontend
|
||||
- build-and-push-backend
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name != 'pull_request'
|
||||
if: github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'preview')
|
||||
steps:
|
||||
- uses: numerique-gouv/action-argocd-webhook-notification@main
|
||||
id: notify
|
||||
|
||||
27
.github/workflows/label_preview.yml
vendored
Normal file
27
.github/workflows/label_preview.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
name: Label Preview
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [labeled, opened]
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
comment:
|
||||
runs-on: ubuntu-latest
|
||||
if: contains(github.event.pull_request.labels.*.name, 'preview')
|
||||
steps:
|
||||
- uses: thollander/actions-comment-pull-request@v3
|
||||
with:
|
||||
message: |
|
||||
:rocket: Preview will be available at [https://${{ github.event.pull_request.number }}-docs.ppr-docs.beta.numerique.gouv.fr/](https://${{ github.event.pull_request.number }}-docs.ppr-docs.beta.numerique.gouv.fr/)
|
||||
|
||||
You can use the existing account with these credentials:
|
||||
- username: `docs`
|
||||
- password: `docs`
|
||||
|
||||
You can also create a new account if you want to.
|
||||
|
||||
Once this Pull Request is merged, the preview will be destroyed.
|
||||
comment-tag: preview-url
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -75,3 +75,6 @@ db.sqlite3
|
||||
.vscode/
|
||||
*.iml
|
||||
.devcontainer
|
||||
|
||||
# Cursor rules
|
||||
.cursorrules
|
||||
|
||||
95
CHANGELOG.md
95
CHANGELOG.md
@@ -1,4 +1,3 @@
|
||||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0),
|
||||
@@ -7,44 +6,113 @@ and this project adheres to
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [3.9.0] - 2025-11-10
|
||||
|
||||
### Added
|
||||
|
||||
- ✨(frontend) add pdf block to the editor #1293
|
||||
- ✨(frontend) create skeleton component for DocEditor #1491
|
||||
- ✨(frontend) add an EmojiPicker in the document tree and title #1381
|
||||
- ✨(frontend) ajustable left panel #1456
|
||||
|
||||
### Changed
|
||||
|
||||
- ♻️(frontend) adapt custom blocks to new implementation #1375
|
||||
- ♻️(backend) increase user short_name field length #1510
|
||||
- 🚸(frontend) separate viewers from editors #1509
|
||||
|
||||
### Fixed
|
||||
|
||||
- 🐛(frontend) fix duplicate document entries in grid #1479
|
||||
- 🐛(backend) fix trashbin list #1520
|
||||
- ♿(frontend) improve accessibility:
|
||||
- ♿(frontend) remove empty alt on logo due to Axe a11y error #1516
|
||||
- 🐛(backend) fix s3 version_id validation #1543
|
||||
- 🐛(frontend) retry check media status after page reload #1555
|
||||
- 🐛(frontend) fix Interlinking memory leak #1560
|
||||
- 🐛(frontend) button new doc UI fix #1557
|
||||
- 🐛(frontend) interlinking UI fix #1557
|
||||
|
||||
## [3.8.2] - 2025-10-17
|
||||
|
||||
### Fixed
|
||||
|
||||
- 🐛(service-worker) fix sw registration and page reload logic #1500
|
||||
|
||||
## [3.8.1] - 2025-10-17
|
||||
|
||||
### Fixed
|
||||
|
||||
- ⚡️(backend) improve trashbin endpoint performance #1495
|
||||
- 🐛(backend) manage invitation partial update without email #1494
|
||||
- ♿(frontend) improve accessibility:
|
||||
- ♿ add missing aria-label to add sub-doc button for accessibility #1480
|
||||
- ♿ add missing aria-label to more options button on sub-docs #1481
|
||||
|
||||
### Removed
|
||||
|
||||
- 🔥(backend) remove treebeard form for the document admin #1470
|
||||
|
||||
## [3.8.0] - 2025-10-14
|
||||
|
||||
### Added
|
||||
|
||||
- ✨(frontend) add pdf block to the editor #1293
|
||||
- ✨List and restore deleted docs #1450
|
||||
|
||||
### Changed
|
||||
|
||||
- ♻️(frontend) Refactor Auth component for improved redirection logic #1461
|
||||
- ♻️(frontend) replace Arial font-family with token font #1411
|
||||
- ♿(frontend) improve accessibility:
|
||||
- #1354
|
||||
- #1349
|
||||
- ♿(frontend) enable enter key to open documentss #1354
|
||||
- ♿(frontend) improve modal a11y: structure, labels, title #1349
|
||||
- ♿improve NVDA navigation in DocShareModal #1396
|
||||
- ♿ improve accessibility by adding landmark roles to layout #1394
|
||||
- ♿ add document visible in list and openable via enter key #1365
|
||||
- ♿ add pdf outline property to enable bookmarks display #1368
|
||||
- ♿ hide decorative icons from assistive tech with aria-hidden #1404
|
||||
- ♿ fix rgaa 1.9.1: convert to figure/figcaption structure #1426
|
||||
- ♿ remove redundant aria-label to avoid over-accessibility #1420
|
||||
- ♿ remove redundant aria-label on hidden icons and update tests #1432
|
||||
- ♿ improve semantic structure and aria roles of leftpanel #1431
|
||||
- ♿ add default background to left panel for better accessibility #1423
|
||||
- ♿ restyle checked checkboxes: removing strikethrough #1439
|
||||
- ♿ add h1 for SR on 40X pages and remove alt texts #1438
|
||||
- ♿ update labels and shared document icon accessibility #1442
|
||||
- 🍱(frontend) Fonts GDPR compliants #1453
|
||||
- ♻️(service-worker) improve SW registration and update handling #1473
|
||||
|
||||
### Fixed
|
||||
|
||||
- 🐛(backend) duplicate sub docs as root for reader users
|
||||
- 🐛(backend) duplicate sub docs as root for reader users #1385
|
||||
- ⚗️(service-worker) remove index from cache first strategy #1395
|
||||
- 🐛(frontend) fix 404 page when reload 403 page #1402
|
||||
- 🐛(frontend) fix legacy role computation #1376
|
||||
- 🛂(frontend) block editing title when not allowed #1412
|
||||
- 🐛(frontend) scroll back to top when navigate to a document #1406
|
||||
- 🐛(frontend) fix export pdf emoji problem #1453
|
||||
- 🐛(frontend) fix attachment download filename #1447
|
||||
- 🐛(frontend) exclude h4-h6 headings from table of contents #1441
|
||||
- 🔒(frontend) prevent readers from changing callout emoji #1449
|
||||
- 🐛(frontend) fix overlapping placeholders in multi-column layout #1455
|
||||
- 🐛(backend) filter invitation with case insensitive email #1457
|
||||
- 🐛(frontend) reduce no access image size from 450 to 300 #1463
|
||||
- 🐛(frontend) preserve interlink style on drag-and-drop in editor #1460
|
||||
- ✨(frontend) load docs logo from public folder via url #1462
|
||||
- 🔧(keycloak) Fix https required issue in dev mode #1286
|
||||
|
||||
### Changed
|
||||
|
||||
- ♿(frontend) improve accessibility:
|
||||
- ♿improve NVDA navigation in DocShareModal #1396
|
||||
## Removed
|
||||
|
||||
- 🔥(frontend) remove custom DividerBlock ##1375
|
||||
|
||||
## [3.7.0] - 2025-09-12
|
||||
|
||||
### Added
|
||||
|
||||
- ✨(api) add API route to fetch document content #1206
|
||||
- ✨(frontend) doc emojis improvements #1381
|
||||
- add an EmojiPicker in the document tree and document title
|
||||
- remove emoji buttons in menus
|
||||
|
||||
### Changed
|
||||
|
||||
@@ -58,6 +126,8 @@ and this project adheres to
|
||||
- ✨unify tab focus style for better visual consistency #1341
|
||||
- ♿hide decorative icons, label menus, avoid accessible name… #1362
|
||||
- ♻️(tilt) use helm dev-backend chart
|
||||
- 🩹(frontend) on main pages do not display leading emoji as page icon #1381
|
||||
- 🩹(frontend) handle properly emojis in interlinking #1381
|
||||
|
||||
### Removed
|
||||
|
||||
@@ -102,7 +172,6 @@ and this project adheres to
|
||||
- 🐛(frontend) fix dnd conflict with tree and Blocknote #1328
|
||||
- 🐛(frontend) fix display bug on homepage #1332
|
||||
- 🐛link role update #1287
|
||||
- 🔧(keycloak) Fix https required issue in dev mode #1286
|
||||
|
||||
## [3.5.0] - 2025-07-31
|
||||
|
||||
@@ -774,7 +843,11 @@ and this project adheres to
|
||||
- ✨(frontend) Coming Soon page (#67)
|
||||
- 🚀 Impress, project to manage your documents easily and collaboratively.
|
||||
|
||||
[unreleased]: https://github.com/suitenumerique/docs/compare/v3.7.0...main
|
||||
[unreleased]: https://github.com/suitenumerique/docs/compare/v3.9.0...main
|
||||
[v3.9.0]: https://github.com/suitenumerique/docs/releases/v3.9.0
|
||||
[v3.8.2]: https://github.com/suitenumerique/docs/releases/v3.8.2
|
||||
[v3.8.1]: https://github.com/suitenumerique/docs/releases/v3.8.1
|
||||
[v3.8.0]: https://github.com/suitenumerique/docs/releases/v3.8.0
|
||||
[v3.7.0]: https://github.com/suitenumerique/docs/releases/v3.7.0
|
||||
[v3.6.0]: https://github.com/suitenumerique/docs/releases/v3.6.0
|
||||
[v3.5.0]: https://github.com/suitenumerique/docs/releases/v3.5.0
|
||||
|
||||
@@ -94,6 +94,14 @@ RUN chmod g=u /etc/passwd
|
||||
# Copy installed python dependencies
|
||||
COPY --from=back-builder /install /usr/local
|
||||
|
||||
# Link certifi certificate from a static path /cert/cacert.pem to avoid issues
|
||||
# when python is upgraded and the path to the certificate changes.
|
||||
# The space between print and the ( is intended otherwise the git lint is failing
|
||||
RUN mkdir /cert && \
|
||||
path=`python -c 'import certifi;print (certifi.where())'` && \
|
||||
mv $path /cert/ && \
|
||||
ln -s /cert/cacert.pem $path
|
||||
|
||||
# Copy impress application (see .dockerignore)
|
||||
COPY ./src/backend /app/
|
||||
|
||||
|
||||
@@ -82,7 +82,7 @@ backend:
|
||||
# Extra volume to manage our local custom CA and avoid to set ssl_verify: false
|
||||
extraVolumeMounts:
|
||||
- name: certs
|
||||
mountPath: /usr/local/lib/python3.13/site-packages/certifi/cacert.pem
|
||||
mountPath: /cert/cacert.pem
|
||||
subPath: cacert.pem
|
||||
|
||||
# Extra volume to manage our local custom CA and avoid to set ssl_verify: false
|
||||
|
||||
@@ -32,6 +32,24 @@ Then, set the `FRONTEND_CSS_URL` environment variable to the URL of your custom
|
||||
|
||||
----
|
||||
|
||||
# **Your logo** 📝
|
||||
|
||||
You can add your own logo in the header from the theme customization file.
|
||||
|
||||
### Settings 🔧
|
||||
|
||||
```shellscript
|
||||
THEME_CUSTOMIZATION_FILE_PATH=<path>
|
||||
```
|
||||
|
||||
### Example of JSON
|
||||
|
||||
You can activate it with the `header.logo` configuration: https://github.com/suitenumerique/docs/blob/main/src/helm/env.d/dev/configuration/theme/demo.json
|
||||
|
||||
This configuration is optional. If not set, the default logo will be used.
|
||||
|
||||
----
|
||||
|
||||
# **Footer Configuration** 📝
|
||||
|
||||
The footer is configurable from the theme customization file.
|
||||
|
||||
@@ -66,3 +66,6 @@ COLLABORATION_WS_URL=ws://localhost:4444/collaboration/ws/
|
||||
DJANGO_SERVER_TO_SERVER_API_TOKENS=server-api-token
|
||||
Y_PROVIDER_API_BASE_URL=http://y-provider-development:4444/api/
|
||||
Y_PROVIDER_API_KEY=yprovider-api-key
|
||||
|
||||
# Theme customization
|
||||
THEME_CUSTOMIZATION_CACHE_TIMEOUT=15
|
||||
@@ -19,13 +19,17 @@
|
||||
"matchPackageNames": ["redis"],
|
||||
"allowedVersions": "<6.0.0"
|
||||
},
|
||||
{
|
||||
"groupName": "allowed pylint versions",
|
||||
"matchManagers": ["pep621"],
|
||||
"matchPackageNames": ["pylint"],
|
||||
"allowedVersions": "<4.0.0"
|
||||
},
|
||||
{
|
||||
"enabled": false,
|
||||
"groupName": "ignored js dependencies",
|
||||
"matchManagers": ["npm"],
|
||||
"matchPackageNames": [
|
||||
"@hocuspocus/provider",
|
||||
"@hocuspocus/server",
|
||||
"docx",
|
||||
"fetch-mock",
|
||||
"node",
|
||||
|
||||
@@ -5,7 +5,6 @@ from django.contrib.auth import admin as auth_admin
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from treebeard.admin import TreeAdmin
|
||||
from treebeard.forms import movenodeform_factory
|
||||
|
||||
from . import models
|
||||
|
||||
@@ -157,7 +156,6 @@ class DocumentAdmin(TreeAdmin):
|
||||
},
|
||||
),
|
||||
)
|
||||
form = movenodeform_factory(models.Document)
|
||||
inlines = (DocumentAccessInline,)
|
||||
list_display = (
|
||||
"id",
|
||||
|
||||
@@ -90,6 +90,7 @@ class ListDocumentSerializer(serializers.ModelSerializer):
|
||||
nb_accesses_direct = serializers.IntegerField(read_only=True)
|
||||
user_role = serializers.SerializerMethodField(read_only=True)
|
||||
abilities = serializers.SerializerMethodField(read_only=True)
|
||||
deleted_at = serializers.SerializerMethodField(read_only=True)
|
||||
|
||||
class Meta:
|
||||
model = models.Document
|
||||
@@ -102,6 +103,7 @@ class ListDocumentSerializer(serializers.ModelSerializer):
|
||||
"computed_link_role",
|
||||
"created_at",
|
||||
"creator",
|
||||
"deleted_at",
|
||||
"depth",
|
||||
"excerpt",
|
||||
"is_favorite",
|
||||
@@ -124,6 +126,7 @@ class ListDocumentSerializer(serializers.ModelSerializer):
|
||||
"computed_link_role",
|
||||
"created_at",
|
||||
"creator",
|
||||
"deleted_at",
|
||||
"depth",
|
||||
"excerpt",
|
||||
"is_favorite",
|
||||
@@ -165,6 +168,10 @@ class ListDocumentSerializer(serializers.ModelSerializer):
|
||||
request = self.context.get("request")
|
||||
return instance.get_role(request.user) if request else None
|
||||
|
||||
def get_deleted_at(self, instance):
|
||||
"""Return the deleted_at of the current document."""
|
||||
return instance.ancestors_deleted_at
|
||||
|
||||
|
||||
class DocumentLightSerializer(serializers.ModelSerializer):
|
||||
"""Minial document serializer for nesting in document accesses."""
|
||||
@@ -193,6 +200,7 @@ class DocumentSerializer(ListDocumentSerializer):
|
||||
"content",
|
||||
"created_at",
|
||||
"creator",
|
||||
"deleted_at",
|
||||
"depth",
|
||||
"excerpt",
|
||||
"is_favorite",
|
||||
@@ -216,6 +224,7 @@ class DocumentSerializer(ListDocumentSerializer):
|
||||
"computed_link_role",
|
||||
"created_at",
|
||||
"creator",
|
||||
"deleted_at",
|
||||
"depth",
|
||||
"is_favorite",
|
||||
"link_role",
|
||||
@@ -740,6 +749,9 @@ class InvitationSerializer(serializers.ModelSerializer):
|
||||
if self.instance is None:
|
||||
attrs["issuer"] = user
|
||||
|
||||
if attrs.get("email"):
|
||||
attrs["email"] = attrs["email"].lower()
|
||||
|
||||
return attrs
|
||||
|
||||
def validate_role(self, role):
|
||||
|
||||
@@ -623,12 +623,32 @@ class DocumentViewSet(
|
||||
The selected documents are those deleted within the cutoff period defined in the
|
||||
settings (see TRASHBIN_CUTOFF_DAYS), before they are considered permanently deleted.
|
||||
"""
|
||||
|
||||
if not request.user.is_authenticated:
|
||||
return self.get_response_for_queryset(self.queryset.none())
|
||||
|
||||
access_documents_paths = (
|
||||
models.DocumentAccess.objects.select_related("document")
|
||||
.filter(
|
||||
db.Q(user=self.request.user) | db.Q(team__in=self.request.user.teams),
|
||||
role=models.RoleChoices.OWNER,
|
||||
)
|
||||
.values_list("document__path", flat=True)
|
||||
)
|
||||
|
||||
if not access_documents_paths:
|
||||
return self.get_response_for_queryset(self.queryset.none())
|
||||
|
||||
children_clause = db.Q()
|
||||
for path in access_documents_paths:
|
||||
children_clause |= db.Q(path__startswith=path)
|
||||
|
||||
queryset = self.queryset.filter(
|
||||
children_clause,
|
||||
deleted_at__isnull=False,
|
||||
deleted_at__gte=models.get_trashbin_cutoff(),
|
||||
)
|
||||
queryset = queryset.annotate_user_roles(self.request.user)
|
||||
queryset = queryset.filter(user_roles__contains=[models.RoleChoices.OWNER])
|
||||
|
||||
return self.get_response_for_queryset(queryset)
|
||||
|
||||
@@ -851,33 +871,47 @@ class DocumentViewSet(
|
||||
|
||||
try:
|
||||
current_document = (
|
||||
self.queryset.select_related(None).only("depth", "path").get(pk=pk)
|
||||
self.queryset.select_related(None)
|
||||
.only("depth", "path", "ancestors_deleted_at")
|
||||
.get(pk=pk)
|
||||
)
|
||||
except models.Document.DoesNotExist as excpt:
|
||||
raise drf.exceptions.NotFound() from excpt
|
||||
|
||||
ancestors = (
|
||||
(
|
||||
current_document.get_ancestors()
|
||||
| self.queryset.select_related(None).filter(pk=pk)
|
||||
)
|
||||
.filter(ancestors_deleted_at__isnull=True)
|
||||
.order_by("path")
|
||||
)
|
||||
is_deleted = current_document.ancestors_deleted_at is not None
|
||||
|
||||
# Get the highest readable ancestor
|
||||
highest_readable = (
|
||||
ancestors.select_related(None)
|
||||
.readable_per_se(request.user)
|
||||
.only("depth", "path")
|
||||
.first()
|
||||
)
|
||||
if highest_readable is None:
|
||||
raise (
|
||||
drf.exceptions.PermissionDenied()
|
||||
if request.user.is_authenticated
|
||||
else drf.exceptions.NotAuthenticated()
|
||||
if is_deleted:
|
||||
if current_document.get_role(user) != models.RoleChoices.OWNER:
|
||||
raise (
|
||||
drf.exceptions.PermissionDenied()
|
||||
if request.user.is_authenticated
|
||||
else drf.exceptions.NotAuthenticated()
|
||||
)
|
||||
highest_readable = current_document
|
||||
ancestors = self.queryset.select_related(None).filter(pk=pk)
|
||||
else:
|
||||
ancestors = (
|
||||
(
|
||||
current_document.get_ancestors()
|
||||
| self.queryset.select_related(None).filter(pk=pk)
|
||||
)
|
||||
.filter(ancestors_deleted_at__isnull=True)
|
||||
.order_by("path")
|
||||
)
|
||||
# Get the highest readable ancestor
|
||||
highest_readable = (
|
||||
ancestors.select_related(None)
|
||||
.readable_per_se(request.user)
|
||||
.only("depth", "path")
|
||||
.first()
|
||||
)
|
||||
|
||||
if highest_readable is None:
|
||||
raise (
|
||||
drf.exceptions.PermissionDenied()
|
||||
if request.user.is_authenticated
|
||||
else drf.exceptions.NotAuthenticated()
|
||||
)
|
||||
paths_links_mapping = {}
|
||||
ancestors_links = []
|
||||
children_clause = db.Q()
|
||||
@@ -1071,7 +1105,7 @@ class DocumentViewSet(
|
||||
@drf.decorators.action(
|
||||
detail=True,
|
||||
methods=["get", "delete"],
|
||||
url_path="versions/(?P<version_id>[0-9a-z-]+)",
|
||||
url_path=r"versions/(?P<version_id>[A-Za-z0-9._+\-=~]{1,1024})",
|
||||
)
|
||||
# pylint: disable=unused-argument
|
||||
def versions_detail(self, request, pk, version_id, *args, **kwargs):
|
||||
@@ -2157,6 +2191,7 @@ class ConfigView(drf.views.APIView):
|
||||
"LANGUAGES",
|
||||
"LANGUAGE_CODE",
|
||||
"SENTRY_DSN",
|
||||
"TRASHBIN_CUTOFF_DAYS",
|
||||
]
|
||||
dict_settings = {}
|
||||
for setting in array_settings:
|
||||
|
||||
19
src/backend/core/migrations/0025_alter_user_short_name.py
Normal file
19
src/backend/core/migrations/0025_alter_user_short_name.py
Normal file
@@ -0,0 +1,19 @@
|
||||
# Generated by Django 5.2.7 on 2025-10-22 06:12
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("core", "0024_add_is_masked_field_to_link_trace"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="user",
|
||||
name="short_name",
|
||||
field=models.CharField(
|
||||
blank=True, max_length=100, null=True, verbose_name="short name"
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -148,7 +148,9 @@ class User(AbstractBaseUser, BaseModel, auth_models.PermissionsMixin):
|
||||
)
|
||||
|
||||
full_name = models.CharField(_("full name"), max_length=100, null=True, blank=True)
|
||||
short_name = models.CharField(_("short name"), max_length=20, null=True, blank=True)
|
||||
short_name = models.CharField(
|
||||
_("short name"), max_length=100, null=True, blank=True
|
||||
)
|
||||
|
||||
email = models.EmailField(_("identity email address"), blank=True, null=True)
|
||||
|
||||
@@ -221,7 +223,7 @@ class User(AbstractBaseUser, BaseModel, auth_models.PermissionsMixin):
|
||||
Expired invitations are ignored.
|
||||
"""
|
||||
valid_invitations = Invitation.objects.filter(
|
||||
email=self.email,
|
||||
email__iexact=self.email,
|
||||
created_at__gte=(
|
||||
timezone.now()
|
||||
- timedelta(seconds=settings.INVITATION_VALIDITY_DURATION)
|
||||
@@ -721,7 +723,7 @@ class Document(MP_Node, BaseModel):
|
||||
|
||||
# Characteristics that are based only on specific access
|
||||
is_owner = role == RoleChoices.OWNER
|
||||
is_deleted = self.ancestors_deleted_at and not is_owner
|
||||
is_deleted = self.ancestors_deleted_at
|
||||
is_owner_or_admin = (is_owner or role == RoleChoices.ADMIN) and not is_deleted
|
||||
|
||||
# Compute access roles before adding link roles because we don't
|
||||
@@ -750,6 +752,7 @@ class Document(MP_Node, BaseModel):
|
||||
role = RoleChoices.max(role, link_definition["link_role"])
|
||||
|
||||
can_get = bool(role) and not is_deleted
|
||||
retrieve = can_get or is_owner
|
||||
can_update = (
|
||||
is_owner_or_admin or role == RoleChoices.EDITOR
|
||||
) and not is_deleted
|
||||
@@ -758,7 +761,7 @@ class Document(MP_Node, BaseModel):
|
||||
is_owner
|
||||
if self.is_root()
|
||||
else (is_owner_or_admin or (user.is_authenticated and self.creator == user))
|
||||
)
|
||||
) and not is_deleted
|
||||
|
||||
ai_allow_reach_from = settings.AI_ALLOW_REACH_FROM
|
||||
ai_access = any(
|
||||
@@ -790,15 +793,15 @@ class Document(MP_Node, BaseModel):
|
||||
"duplicate": can_get and user.is_authenticated,
|
||||
"favorite": can_get and user.is_authenticated,
|
||||
"link_configuration": is_owner_or_admin,
|
||||
"invite_owner": is_owner,
|
||||
"invite_owner": is_owner and not is_deleted,
|
||||
"mask": can_get and user.is_authenticated,
|
||||
"move": is_owner_or_admin and not self.ancestors_deleted_at,
|
||||
"move": is_owner_or_admin and not is_deleted,
|
||||
"partial_update": can_update,
|
||||
"restore": is_owner,
|
||||
"retrieve": can_get,
|
||||
"retrieve": retrieve,
|
||||
"media_auth": can_get,
|
||||
"link_select_options": link_select_options,
|
||||
"tree": can_get,
|
||||
"tree": retrieve,
|
||||
"update": can_update,
|
||||
"versions_destroy": is_owner_or_admin,
|
||||
"versions_list": has_access_role,
|
||||
|
||||
@@ -57,7 +57,7 @@ def test_authentication_getter_existing_user_via_email(
|
||||
|
||||
monkeypatch.setattr(OIDCAuthenticationBackend, "get_userinfo", get_userinfo_mocked)
|
||||
|
||||
with django_assert_num_queries(3): # user by sub, user by mail, update sub
|
||||
with django_assert_num_queries(4): # user by sub, user by mail, update sub
|
||||
user = klass.get_or_create_user(
|
||||
access_token="test-token", id_token=None, payload=None
|
||||
)
|
||||
@@ -214,7 +214,7 @@ def test_authentication_getter_existing_user_change_fields_sub(
|
||||
monkeypatch.setattr(OIDCAuthenticationBackend, "get_userinfo", get_userinfo_mocked)
|
||||
|
||||
# One and only one additional update query when a field has changed
|
||||
with django_assert_num_queries(2):
|
||||
with django_assert_num_queries(3):
|
||||
authenticated_user = klass.get_or_create_user(
|
||||
access_token="test-token", id_token=None, payload=None
|
||||
)
|
||||
@@ -256,7 +256,7 @@ def test_authentication_getter_existing_user_change_fields_email(
|
||||
monkeypatch.setattr(OIDCAuthenticationBackend, "get_userinfo", get_userinfo_mocked)
|
||||
|
||||
# One and only one additional update query when a field has changed
|
||||
with django_assert_num_queries(3):
|
||||
with django_assert_num_queries(4):
|
||||
authenticated_user = klass.get_or_create_user(
|
||||
access_token="test-token", id_token=None, payload=None
|
||||
)
|
||||
|
||||
@@ -596,6 +596,32 @@ def test_api_document_invitations_create_cannot_invite_existing_users():
|
||||
}
|
||||
|
||||
|
||||
def test_api_document_invitations_create_lower_email():
|
||||
"""
|
||||
No matter the case, the email should be converted to lowercase.
|
||||
"""
|
||||
user = factories.UserFactory()
|
||||
document = factories.DocumentFactory(users=[(user, "owner")])
|
||||
|
||||
# Build an invitation to the email of an existing identity in the db
|
||||
invitation_values = {
|
||||
"email": "GuEst@example.com",
|
||||
"role": random.choice(models.RoleChoices.values),
|
||||
}
|
||||
|
||||
client = APIClient()
|
||||
client.force_login(user)
|
||||
|
||||
response = client.post(
|
||||
f"/api/v1.0/documents/{document.id!s}/invitations/",
|
||||
invitation_values,
|
||||
format="json",
|
||||
)
|
||||
|
||||
assert response.status_code == 201
|
||||
assert response.json()["email"] == "guest@example.com"
|
||||
|
||||
|
||||
# Update
|
||||
|
||||
|
||||
@@ -743,6 +769,37 @@ def test_api_document_invitations_update_authenticated_unprivileged(
|
||||
assert value == old_invitation_values[key]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("via", VIA)
|
||||
@pytest.mark.parametrize("role", ["administrator", "owner"])
|
||||
def test_api_document_invitations_patch(via, role, mock_user_teams):
|
||||
"""Partially updating an invitation should be allowed."""
|
||||
|
||||
user = factories.UserFactory()
|
||||
invitation = factories.InvitationFactory(role="editor")
|
||||
|
||||
if via == USER:
|
||||
factories.UserDocumentAccessFactory(
|
||||
document=invitation.document, user=user, role=role
|
||||
)
|
||||
elif via == TEAM:
|
||||
mock_user_teams.return_value = ["lasuite", "unknown"]
|
||||
factories.TeamDocumentAccessFactory(
|
||||
document=invitation.document, team="lasuite", role=role
|
||||
)
|
||||
|
||||
client = APIClient()
|
||||
client.force_login(user)
|
||||
|
||||
response = client.patch(
|
||||
f"/api/v1.0/documents/{invitation.document.id!s}/invitations/{invitation.id!s}/",
|
||||
{"role": "reader"},
|
||||
format="json",
|
||||
)
|
||||
assert response.status_code == 200
|
||||
invitation.refresh_from_db()
|
||||
assert invitation.role == "reader"
|
||||
|
||||
|
||||
# Delete
|
||||
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ def test_api_documents_children_list_anonymous_public_standalone(
|
||||
"computed_link_role": child1.computed_link_role,
|
||||
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child1.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 2,
|
||||
"excerpt": child1.excerpt,
|
||||
"id": str(child1.id),
|
||||
@@ -63,6 +64,7 @@ def test_api_documents_children_list_anonymous_public_standalone(
|
||||
"computed_link_role": child2.computed_link_role,
|
||||
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child2.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 2,
|
||||
"excerpt": child2.excerpt,
|
||||
"id": str(child2.id),
|
||||
@@ -115,6 +117,7 @@ def test_api_documents_children_list_anonymous_public_parent(django_assert_num_q
|
||||
"computed_link_role": child1.computed_link_role,
|
||||
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child1.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 4,
|
||||
"excerpt": child1.excerpt,
|
||||
"id": str(child1.id),
|
||||
@@ -137,6 +140,7 @@ def test_api_documents_children_list_anonymous_public_parent(django_assert_num_q
|
||||
"computed_link_role": child2.computed_link_role,
|
||||
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child2.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 4,
|
||||
"excerpt": child2.excerpt,
|
||||
"id": str(child2.id),
|
||||
@@ -208,6 +212,7 @@ def test_api_documents_children_list_authenticated_unrelated_public_or_authentic
|
||||
"computed_link_role": child1.computed_link_role,
|
||||
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child1.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 2,
|
||||
"excerpt": child1.excerpt,
|
||||
"id": str(child1.id),
|
||||
@@ -230,6 +235,7 @@ def test_api_documents_children_list_authenticated_unrelated_public_or_authentic
|
||||
"computed_link_role": child2.computed_link_role,
|
||||
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child2.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 2,
|
||||
"excerpt": child2.excerpt,
|
||||
"id": str(child2.id),
|
||||
@@ -287,6 +293,7 @@ def test_api_documents_children_list_authenticated_public_or_authenticated_paren
|
||||
"computed_link_role": child1.computed_link_role,
|
||||
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child1.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 4,
|
||||
"excerpt": child1.excerpt,
|
||||
"id": str(child1.id),
|
||||
@@ -309,6 +316,7 @@ def test_api_documents_children_list_authenticated_public_or_authenticated_paren
|
||||
"computed_link_role": child2.computed_link_role,
|
||||
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child2.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 4,
|
||||
"excerpt": child2.excerpt,
|
||||
"id": str(child2.id),
|
||||
@@ -393,6 +401,7 @@ def test_api_documents_children_list_authenticated_related_direct(
|
||||
"computed_link_role": child1.computed_link_role,
|
||||
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child1.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 2,
|
||||
"excerpt": child1.excerpt,
|
||||
"id": str(child1.id),
|
||||
@@ -415,6 +424,7 @@ def test_api_documents_children_list_authenticated_related_direct(
|
||||
"computed_link_role": child2.computed_link_role,
|
||||
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child2.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 2,
|
||||
"excerpt": child2.excerpt,
|
||||
"id": str(child2.id),
|
||||
@@ -475,6 +485,7 @@ def test_api_documents_children_list_authenticated_related_parent(
|
||||
"computed_link_role": child1.computed_link_role,
|
||||
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child1.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 4,
|
||||
"excerpt": child1.excerpt,
|
||||
"id": str(child1.id),
|
||||
@@ -497,6 +508,7 @@ def test_api_documents_children_list_authenticated_related_parent(
|
||||
"computed_link_role": child2.computed_link_role,
|
||||
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child2.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 4,
|
||||
"excerpt": child2.excerpt,
|
||||
"id": str(child2.id),
|
||||
@@ -609,6 +621,7 @@ def test_api_documents_children_list_authenticated_related_team_members(
|
||||
"computed_link_role": child1.computed_link_role,
|
||||
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child1.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 2,
|
||||
"excerpt": child1.excerpt,
|
||||
"id": str(child1.id),
|
||||
@@ -631,6 +644,7 @@ def test_api_documents_children_list_authenticated_related_team_members(
|
||||
"computed_link_role": child2.computed_link_role,
|
||||
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child2.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 2,
|
||||
"excerpt": child2.excerpt,
|
||||
"id": str(child2.id),
|
||||
|
||||
@@ -38,6 +38,7 @@ def test_api_documents_descendants_list_anonymous_public_standalone():
|
||||
"computed_link_role": child1.computed_link_role,
|
||||
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child1.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 2,
|
||||
"excerpt": child1.excerpt,
|
||||
"id": str(child1.id),
|
||||
@@ -62,6 +63,7 @@ def test_api_documents_descendants_list_anonymous_public_standalone():
|
||||
"computed_link_role": grand_child.computed_link_role,
|
||||
"created_at": grand_child.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(grand_child.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 3,
|
||||
"excerpt": grand_child.excerpt,
|
||||
"id": str(grand_child.id),
|
||||
@@ -84,6 +86,7 @@ def test_api_documents_descendants_list_anonymous_public_standalone():
|
||||
"computed_link_role": child2.computed_link_role,
|
||||
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child2.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 2,
|
||||
"excerpt": child2.excerpt,
|
||||
"id": str(child2.id),
|
||||
@@ -135,6 +138,7 @@ def test_api_documents_descendants_list_anonymous_public_parent():
|
||||
"computed_link_role": child1.computed_link_role,
|
||||
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child1.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 4,
|
||||
"excerpt": child1.excerpt,
|
||||
"id": str(child1.id),
|
||||
@@ -157,6 +161,7 @@ def test_api_documents_descendants_list_anonymous_public_parent():
|
||||
"computed_link_role": grand_child.computed_link_role,
|
||||
"created_at": grand_child.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(grand_child.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 5,
|
||||
"excerpt": grand_child.excerpt,
|
||||
"id": str(grand_child.id),
|
||||
@@ -179,6 +184,7 @@ def test_api_documents_descendants_list_anonymous_public_parent():
|
||||
"computed_link_role": child2.computed_link_role,
|
||||
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child2.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 4,
|
||||
"excerpt": child2.excerpt,
|
||||
"id": str(child2.id),
|
||||
@@ -251,6 +257,7 @@ def test_api_documents_descendants_list_authenticated_unrelated_public_or_authen
|
||||
"computed_link_role": child1.computed_link_role,
|
||||
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child1.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 2,
|
||||
"excerpt": child1.excerpt,
|
||||
"id": str(child1.id),
|
||||
@@ -273,6 +280,7 @@ def test_api_documents_descendants_list_authenticated_unrelated_public_or_authen
|
||||
"computed_link_role": grand_child.computed_link_role,
|
||||
"created_at": grand_child.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(grand_child.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 3,
|
||||
"excerpt": grand_child.excerpt,
|
||||
"id": str(grand_child.id),
|
||||
@@ -295,6 +303,7 @@ def test_api_documents_descendants_list_authenticated_unrelated_public_or_authen
|
||||
"computed_link_role": child2.computed_link_role,
|
||||
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child2.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 2,
|
||||
"excerpt": child2.excerpt,
|
||||
"id": str(child2.id),
|
||||
@@ -352,6 +361,7 @@ def test_api_documents_descendants_list_authenticated_public_or_authenticated_pa
|
||||
"computed_link_role": child1.computed_link_role,
|
||||
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child1.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 4,
|
||||
"excerpt": child1.excerpt,
|
||||
"id": str(child1.id),
|
||||
@@ -374,6 +384,7 @@ def test_api_documents_descendants_list_authenticated_public_or_authenticated_pa
|
||||
"computed_link_role": grand_child.computed_link_role,
|
||||
"created_at": grand_child.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(grand_child.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 5,
|
||||
"excerpt": grand_child.excerpt,
|
||||
"id": str(grand_child.id),
|
||||
@@ -396,6 +407,7 @@ def test_api_documents_descendants_list_authenticated_public_or_authenticated_pa
|
||||
"computed_link_role": child2.computed_link_role,
|
||||
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child2.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 4,
|
||||
"excerpt": child2.excerpt,
|
||||
"id": str(child2.id),
|
||||
@@ -474,6 +486,7 @@ def test_api_documents_descendants_list_authenticated_related_direct():
|
||||
"computed_link_role": child1.computed_link_role,
|
||||
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child1.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 2,
|
||||
"excerpt": child1.excerpt,
|
||||
"id": str(child1.id),
|
||||
@@ -496,6 +509,7 @@ def test_api_documents_descendants_list_authenticated_related_direct():
|
||||
"computed_link_role": grand_child.computed_link_role,
|
||||
"created_at": grand_child.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(grand_child.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 3,
|
||||
"excerpt": grand_child.excerpt,
|
||||
"id": str(grand_child.id),
|
||||
@@ -518,6 +532,7 @@ def test_api_documents_descendants_list_authenticated_related_direct():
|
||||
"computed_link_role": child2.computed_link_role,
|
||||
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child2.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 2,
|
||||
"excerpt": child2.excerpt,
|
||||
"id": str(child2.id),
|
||||
@@ -576,6 +591,7 @@ def test_api_documents_descendants_list_authenticated_related_parent():
|
||||
"computed_link_role": child1.computed_link_role,
|
||||
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child1.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 4,
|
||||
"excerpt": child1.excerpt,
|
||||
"id": str(child1.id),
|
||||
@@ -598,6 +614,7 @@ def test_api_documents_descendants_list_authenticated_related_parent():
|
||||
"computed_link_role": grand_child.computed_link_role,
|
||||
"created_at": grand_child.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(grand_child.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 5,
|
||||
"excerpt": grand_child.excerpt,
|
||||
"id": str(grand_child.id),
|
||||
@@ -620,6 +637,7 @@ def test_api_documents_descendants_list_authenticated_related_parent():
|
||||
"computed_link_role": child2.computed_link_role,
|
||||
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child2.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 4,
|
||||
"excerpt": child2.excerpt,
|
||||
"id": str(child2.id),
|
||||
@@ -724,6 +742,7 @@ def test_api_documents_descendants_list_authenticated_related_team_members(
|
||||
"computed_link_role": child1.computed_link_role,
|
||||
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child1.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 2,
|
||||
"excerpt": child1.excerpt,
|
||||
"id": str(child1.id),
|
||||
@@ -746,6 +765,7 @@ def test_api_documents_descendants_list_authenticated_related_team_members(
|
||||
"computed_link_role": grand_child.computed_link_role,
|
||||
"created_at": grand_child.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(grand_child.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 3,
|
||||
"excerpt": grand_child.excerpt,
|
||||
"id": str(grand_child.id),
|
||||
@@ -768,6 +788,7 @@ def test_api_documents_descendants_list_authenticated_related_team_members(
|
||||
"computed_link_role": child2.computed_link_role,
|
||||
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(child2.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 2,
|
||||
"excerpt": child2.excerpt,
|
||||
"id": str(child2.id),
|
||||
|
||||
@@ -65,6 +65,7 @@ def test_api_document_favorite_list_authenticated_with_favorite():
|
||||
"computed_link_role": document.computed_link_role,
|
||||
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(document.creator.id),
|
||||
"deleted_at": None,
|
||||
"content": document.content,
|
||||
"depth": document.depth,
|
||||
"excerpt": document.excerpt,
|
||||
|
||||
@@ -69,6 +69,7 @@ def test_api_documents_list_format():
|
||||
"computed_link_role": document.computed_link_role,
|
||||
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(document.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 1,
|
||||
"excerpt": document.excerpt,
|
||||
"is_favorite": True,
|
||||
|
||||
@@ -70,6 +70,7 @@ def test_api_documents_retrieve_anonymous_public_standalone():
|
||||
"content": document.content,
|
||||
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(document.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 1,
|
||||
"excerpt": document.excerpt,
|
||||
"is_favorite": False,
|
||||
@@ -144,6 +145,7 @@ def test_api_documents_retrieve_anonymous_public_parent():
|
||||
"content": document.content,
|
||||
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(document.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 3,
|
||||
"excerpt": document.excerpt,
|
||||
"is_favorite": False,
|
||||
@@ -252,6 +254,7 @@ def test_api_documents_retrieve_authenticated_unrelated_public_or_authenticated(
|
||||
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(document.creator.id),
|
||||
"depth": 1,
|
||||
"deleted_at": None,
|
||||
"excerpt": document.excerpt,
|
||||
"is_favorite": False,
|
||||
"link_reach": reach,
|
||||
@@ -333,6 +336,7 @@ def test_api_documents_retrieve_authenticated_public_or_authenticated_parent(rea
|
||||
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(document.creator.id),
|
||||
"depth": 3,
|
||||
"deleted_at": None,
|
||||
"excerpt": document.excerpt,
|
||||
"is_favorite": False,
|
||||
"link_reach": document.link_reach,
|
||||
@@ -446,6 +450,7 @@ def test_api_documents_retrieve_authenticated_related_direct():
|
||||
"content": document.content,
|
||||
"creator": str(document.creator.id),
|
||||
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"deleted_at": None,
|
||||
"depth": 1,
|
||||
"excerpt": document.excerpt,
|
||||
"is_favorite": False,
|
||||
@@ -528,6 +533,7 @@ def test_api_documents_retrieve_authenticated_related_parent():
|
||||
"creator": str(document.creator.id),
|
||||
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"depth": 3,
|
||||
"deleted_at": None,
|
||||
"excerpt": document.excerpt,
|
||||
"is_favorite": False,
|
||||
"link_reach": "restricted",
|
||||
@@ -683,6 +689,7 @@ def test_api_documents_retrieve_authenticated_related_team_members(
|
||||
"content": document.content,
|
||||
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(document.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 1,
|
||||
"excerpt": document.excerpt,
|
||||
"is_favorite": False,
|
||||
@@ -749,6 +756,7 @@ def test_api_documents_retrieve_authenticated_related_team_administrators(
|
||||
"content": document.content,
|
||||
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(document.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 1,
|
||||
"excerpt": document.excerpt,
|
||||
"is_favorite": False,
|
||||
@@ -815,6 +823,7 @@ def test_api_documents_retrieve_authenticated_related_team_owners(
|
||||
"content": document.content,
|
||||
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(document.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 1,
|
||||
"excerpt": document.excerpt,
|
||||
"is_favorite": False,
|
||||
|
||||
@@ -48,11 +48,11 @@ def test_api_documents_trashbin_format():
|
||||
|
||||
other_users = factories.UserFactory.create_batch(3)
|
||||
document = factories.DocumentFactory(
|
||||
deleted_at=timezone.now(),
|
||||
users=factories.UserFactory.create_batch(2),
|
||||
favorited_by=[user, *other_users],
|
||||
link_traces=other_users,
|
||||
)
|
||||
document.soft_delete()
|
||||
factories.UserDocumentAccessFactory(document=document, user=user, role="owner")
|
||||
|
||||
response = client.get("/api/v1.0/documents/trashbin/")
|
||||
@@ -70,40 +70,40 @@ def test_api_documents_trashbin_format():
|
||||
assert results[0] == {
|
||||
"id": str(document.id),
|
||||
"abilities": {
|
||||
"accesses_manage": True,
|
||||
"accesses_view": True,
|
||||
"ai_transform": True,
|
||||
"ai_translate": True,
|
||||
"attachment_upload": True,
|
||||
"can_edit": True,
|
||||
"children_create": True,
|
||||
"children_list": True,
|
||||
"collaboration_auth": True,
|
||||
"descendants": True,
|
||||
"cors_proxy": True,
|
||||
"content": True,
|
||||
"destroy": True,
|
||||
"duplicate": True,
|
||||
"favorite": True,
|
||||
"invite_owner": True,
|
||||
"link_configuration": True,
|
||||
"accesses_manage": False,
|
||||
"accesses_view": False,
|
||||
"ai_transform": False,
|
||||
"ai_translate": False,
|
||||
"attachment_upload": False,
|
||||
"can_edit": False,
|
||||
"children_create": False,
|
||||
"children_list": False,
|
||||
"collaboration_auth": False,
|
||||
"descendants": False,
|
||||
"cors_proxy": False,
|
||||
"content": False,
|
||||
"destroy": False,
|
||||
"duplicate": False,
|
||||
"favorite": False,
|
||||
"invite_owner": False,
|
||||
"link_configuration": False,
|
||||
"link_select_options": {
|
||||
"authenticated": ["reader", "editor"],
|
||||
"public": ["reader", "editor"],
|
||||
"restricted": None,
|
||||
},
|
||||
"mask": True,
|
||||
"media_auth": True,
|
||||
"media_check": True,
|
||||
"mask": False,
|
||||
"media_auth": False,
|
||||
"media_check": False,
|
||||
"move": False, # Can't move a deleted document
|
||||
"partial_update": True,
|
||||
"partial_update": False,
|
||||
"restore": True,
|
||||
"retrieve": True,
|
||||
"tree": True,
|
||||
"update": True,
|
||||
"versions_destroy": True,
|
||||
"versions_list": True,
|
||||
"versions_retrieve": True,
|
||||
"update": False,
|
||||
"versions_destroy": False,
|
||||
"versions_list": False,
|
||||
"versions_retrieve": False,
|
||||
},
|
||||
"ancestors_link_reach": None,
|
||||
"ancestors_link_role": None,
|
||||
@@ -113,6 +113,7 @@ def test_api_documents_trashbin_format():
|
||||
"creator": str(document.creator.id),
|
||||
"depth": 1,
|
||||
"excerpt": document.excerpt,
|
||||
"deleted_at": document.ancestors_deleted_at.isoformat().replace("+00:00", "Z"),
|
||||
"link_reach": document.link_reach,
|
||||
"link_role": document.link_role,
|
||||
"nb_accesses_ancestors": 0,
|
||||
@@ -165,10 +166,10 @@ def test_api_documents_trashbin_authenticated_direct(django_assert_num_queries):
|
||||
|
||||
expected_ids = {str(document1.id), str(document2.id), str(document3.id)}
|
||||
|
||||
with django_assert_num_queries(10):
|
||||
with django_assert_num_queries(11):
|
||||
response = client.get("/api/v1.0/documents/trashbin/")
|
||||
|
||||
with django_assert_num_queries(4):
|
||||
with django_assert_num_queries(5):
|
||||
response = client.get("/api/v1.0/documents/trashbin/")
|
||||
|
||||
assert response.status_code == 200
|
||||
@@ -207,10 +208,10 @@ def test_api_documents_trashbin_authenticated_via_team(
|
||||
|
||||
expected_ids = {str(deleted_document_team1.id), str(deleted_document_team2.id)}
|
||||
|
||||
with django_assert_num_queries(7):
|
||||
with django_assert_num_queries(8):
|
||||
response = client.get("/api/v1.0/documents/trashbin/")
|
||||
|
||||
with django_assert_num_queries(3):
|
||||
with django_assert_num_queries(4):
|
||||
response = client.get("/api/v1.0/documents/trashbin/")
|
||||
|
||||
assert response.status_code == 200
|
||||
@@ -292,3 +293,29 @@ def test_api_documents_trashbin_distinct():
|
||||
content = response.json()
|
||||
assert len(content["results"]) == 1
|
||||
assert content["results"][0]["id"] == str(document.id)
|
||||
|
||||
|
||||
def test_api_documents_trashbin_empty_queryset_bug():
|
||||
"""
|
||||
Test that users with no owner role don't see documents.
|
||||
"""
|
||||
# Create a new user with no owner access to any document
|
||||
new_user = factories.UserFactory()
|
||||
client = APIClient()
|
||||
client.force_login(new_user)
|
||||
|
||||
# Create some deleted documents owned by other users
|
||||
other_user = factories.UserFactory()
|
||||
item1 = factories.DocumentFactory(users=[(other_user, "owner")])
|
||||
item1.soft_delete()
|
||||
item2 = factories.DocumentFactory(users=[(other_user, "owner")])
|
||||
item2.soft_delete()
|
||||
item3 = factories.DocumentFactory(users=[(other_user, "owner")])
|
||||
item3.soft_delete()
|
||||
|
||||
response = client.get("/api/v1.0/documents/trashbin/")
|
||||
|
||||
assert response.status_code == 200
|
||||
content = response.json()
|
||||
assert content["count"] == 0
|
||||
assert len(content["results"]) == 0
|
||||
|
||||
@@ -50,6 +50,7 @@ def test_api_documents_tree_list_anonymous_public_standalone(django_assert_num_q
|
||||
),
|
||||
"creator": str(child.creator.id),
|
||||
"depth": 3,
|
||||
"deleted_at": None,
|
||||
"excerpt": child.excerpt,
|
||||
"id": str(child.id),
|
||||
"is_favorite": False,
|
||||
@@ -73,6 +74,7 @@ def test_api_documents_tree_list_anonymous_public_standalone(django_assert_num_q
|
||||
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(document.creator.id),
|
||||
"depth": 2,
|
||||
"deleted_at": None,
|
||||
"excerpt": document.excerpt,
|
||||
"id": str(document.id),
|
||||
"is_favorite": False,
|
||||
@@ -96,6 +98,7 @@ def test_api_documents_tree_list_anonymous_public_standalone(django_assert_num_q
|
||||
"created_at": sibling1.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(sibling1.creator.id),
|
||||
"depth": 2,
|
||||
"deleted_at": None,
|
||||
"excerpt": sibling1.excerpt,
|
||||
"id": str(sibling1.id),
|
||||
"is_favorite": False,
|
||||
@@ -119,6 +122,7 @@ def test_api_documents_tree_list_anonymous_public_standalone(django_assert_num_q
|
||||
"created_at": sibling2.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(sibling2.creator.id),
|
||||
"depth": 2,
|
||||
"deleted_at": None,
|
||||
"excerpt": sibling2.excerpt,
|
||||
"id": str(sibling2.id),
|
||||
"is_favorite": False,
|
||||
@@ -138,6 +142,7 @@ def test_api_documents_tree_list_anonymous_public_standalone(django_assert_num_q
|
||||
"created_at": parent.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(parent.creator.id),
|
||||
"depth": 1,
|
||||
"deleted_at": None,
|
||||
"excerpt": parent.excerpt,
|
||||
"id": str(parent.id),
|
||||
"is_favorite": False,
|
||||
@@ -210,6 +215,7 @@ def test_api_documents_tree_list_anonymous_public_parent():
|
||||
),
|
||||
"creator": str(child.creator.id),
|
||||
"depth": 5,
|
||||
"deleted_at": None,
|
||||
"excerpt": child.excerpt,
|
||||
"id": str(child.id),
|
||||
"is_favorite": False,
|
||||
@@ -233,6 +239,7 @@ def test_api_documents_tree_list_anonymous_public_parent():
|
||||
),
|
||||
"creator": str(document.creator.id),
|
||||
"depth": 4,
|
||||
"deleted_at": None,
|
||||
"excerpt": document.excerpt,
|
||||
"id": str(document.id),
|
||||
"is_favorite": False,
|
||||
@@ -260,6 +267,7 @@ def test_api_documents_tree_list_anonymous_public_parent():
|
||||
),
|
||||
"creator": str(document_sibling.creator.id),
|
||||
"depth": 4,
|
||||
"deleted_at": None,
|
||||
"excerpt": document_sibling.excerpt,
|
||||
"id": str(document_sibling.id),
|
||||
"is_favorite": False,
|
||||
@@ -281,6 +289,7 @@ def test_api_documents_tree_list_anonymous_public_parent():
|
||||
"created_at": parent.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(parent.creator.id),
|
||||
"depth": 3,
|
||||
"deleted_at": None,
|
||||
"excerpt": parent.excerpt,
|
||||
"id": str(parent.id),
|
||||
"is_favorite": False,
|
||||
@@ -306,6 +315,7 @@ def test_api_documents_tree_list_anonymous_public_parent():
|
||||
),
|
||||
"creator": str(parent_sibling.creator.id),
|
||||
"depth": 3,
|
||||
"deleted_at": None,
|
||||
"excerpt": parent_sibling.excerpt,
|
||||
"id": str(parent_sibling.id),
|
||||
"is_favorite": False,
|
||||
@@ -327,6 +337,7 @@ def test_api_documents_tree_list_anonymous_public_parent():
|
||||
"created_at": grand_parent.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(grand_parent.creator.id),
|
||||
"depth": 2,
|
||||
"deleted_at": None,
|
||||
"excerpt": grand_parent.excerpt,
|
||||
"id": str(grand_parent.id),
|
||||
"is_favorite": False,
|
||||
@@ -406,6 +417,7 @@ def test_api_documents_tree_list_authenticated_unrelated_public_or_authenticated
|
||||
),
|
||||
"creator": str(child.creator.id),
|
||||
"depth": 3,
|
||||
"deleted_at": None,
|
||||
"excerpt": child.excerpt,
|
||||
"id": str(child.id),
|
||||
"is_favorite": False,
|
||||
@@ -427,6 +439,7 @@ def test_api_documents_tree_list_authenticated_unrelated_public_or_authenticated
|
||||
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(document.creator.id),
|
||||
"depth": 2,
|
||||
"deleted_at": None,
|
||||
"excerpt": document.excerpt,
|
||||
"id": str(document.id),
|
||||
"is_favorite": False,
|
||||
@@ -450,6 +463,7 @@ def test_api_documents_tree_list_authenticated_unrelated_public_or_authenticated
|
||||
"created_at": sibling.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(sibling.creator.id),
|
||||
"depth": 2,
|
||||
"deleted_at": None,
|
||||
"excerpt": sibling.excerpt,
|
||||
"id": str(sibling.id),
|
||||
"is_favorite": False,
|
||||
@@ -469,6 +483,7 @@ def test_api_documents_tree_list_authenticated_unrelated_public_or_authenticated
|
||||
"created_at": parent.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(parent.creator.id),
|
||||
"depth": 1,
|
||||
"deleted_at": None,
|
||||
"excerpt": parent.excerpt,
|
||||
"id": str(parent.id),
|
||||
"is_favorite": False,
|
||||
@@ -546,6 +561,7 @@ def test_api_documents_tree_list_authenticated_public_or_authenticated_parent(
|
||||
),
|
||||
"creator": str(child.creator.id),
|
||||
"depth": 5,
|
||||
"deleted_at": None,
|
||||
"excerpt": child.excerpt,
|
||||
"id": str(child.id),
|
||||
"is_favorite": False,
|
||||
@@ -569,6 +585,7 @@ def test_api_documents_tree_list_authenticated_public_or_authenticated_parent(
|
||||
),
|
||||
"creator": str(document.creator.id),
|
||||
"depth": 4,
|
||||
"deleted_at": None,
|
||||
"excerpt": document.excerpt,
|
||||
"id": str(document.id),
|
||||
"is_favorite": False,
|
||||
@@ -596,6 +613,7 @@ def test_api_documents_tree_list_authenticated_public_or_authenticated_parent(
|
||||
),
|
||||
"creator": str(document_sibling.creator.id),
|
||||
"depth": 4,
|
||||
"deleted_at": None,
|
||||
"excerpt": document_sibling.excerpt,
|
||||
"id": str(document_sibling.id),
|
||||
"is_favorite": False,
|
||||
@@ -617,6 +635,7 @@ def test_api_documents_tree_list_authenticated_public_or_authenticated_parent(
|
||||
"created_at": parent.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(parent.creator.id),
|
||||
"depth": 3,
|
||||
"deleted_at": None,
|
||||
"excerpt": parent.excerpt,
|
||||
"id": str(parent.id),
|
||||
"is_favorite": False,
|
||||
@@ -642,6 +661,7 @@ def test_api_documents_tree_list_authenticated_public_or_authenticated_parent(
|
||||
),
|
||||
"creator": str(parent_sibling.creator.id),
|
||||
"depth": 3,
|
||||
"deleted_at": None,
|
||||
"excerpt": parent_sibling.excerpt,
|
||||
"id": str(parent_sibling.id),
|
||||
"is_favorite": False,
|
||||
@@ -663,6 +683,7 @@ def test_api_documents_tree_list_authenticated_public_or_authenticated_parent(
|
||||
"created_at": grand_parent.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(grand_parent.creator.id),
|
||||
"depth": 2,
|
||||
"deleted_at": None,
|
||||
"excerpt": grand_parent.excerpt,
|
||||
"id": str(grand_parent.id),
|
||||
"is_favorite": False,
|
||||
@@ -744,6 +765,7 @@ def test_api_documents_tree_list_authenticated_related_direct():
|
||||
),
|
||||
"creator": str(child.creator.id),
|
||||
"depth": 3,
|
||||
"deleted_at": None,
|
||||
"excerpt": child.excerpt,
|
||||
"id": str(child.id),
|
||||
"is_favorite": False,
|
||||
@@ -765,6 +787,7 @@ def test_api_documents_tree_list_authenticated_related_direct():
|
||||
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(document.creator.id),
|
||||
"depth": 2,
|
||||
"deleted_at": None,
|
||||
"excerpt": document.excerpt,
|
||||
"id": str(document.id),
|
||||
"is_favorite": False,
|
||||
@@ -788,6 +811,7 @@ def test_api_documents_tree_list_authenticated_related_direct():
|
||||
"created_at": sibling.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(sibling.creator.id),
|
||||
"depth": 2,
|
||||
"deleted_at": None,
|
||||
"excerpt": sibling.excerpt,
|
||||
"id": str(sibling.id),
|
||||
"is_favorite": False,
|
||||
@@ -807,6 +831,7 @@ def test_api_documents_tree_list_authenticated_related_direct():
|
||||
"created_at": parent.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(parent.creator.id),
|
||||
"depth": 1,
|
||||
"deleted_at": None,
|
||||
"excerpt": parent.excerpt,
|
||||
"id": str(parent.id),
|
||||
"is_favorite": False,
|
||||
@@ -888,6 +913,7 @@ def test_api_documents_tree_list_authenticated_related_parent():
|
||||
),
|
||||
"creator": str(child.creator.id),
|
||||
"depth": 5,
|
||||
"deleted_at": None,
|
||||
"excerpt": child.excerpt,
|
||||
"id": str(child.id),
|
||||
"is_favorite": False,
|
||||
@@ -911,6 +937,7 @@ def test_api_documents_tree_list_authenticated_related_parent():
|
||||
),
|
||||
"creator": str(document.creator.id),
|
||||
"depth": 4,
|
||||
"deleted_at": None,
|
||||
"excerpt": document.excerpt,
|
||||
"id": str(document.id),
|
||||
"is_favorite": False,
|
||||
@@ -938,6 +965,7 @@ def test_api_documents_tree_list_authenticated_related_parent():
|
||||
),
|
||||
"creator": str(document_sibling.creator.id),
|
||||
"depth": 4,
|
||||
"deleted_at": None,
|
||||
"excerpt": document_sibling.excerpt,
|
||||
"id": str(document_sibling.id),
|
||||
"is_favorite": False,
|
||||
@@ -959,6 +987,7 @@ def test_api_documents_tree_list_authenticated_related_parent():
|
||||
"created_at": parent.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(parent.creator.id),
|
||||
"depth": 3,
|
||||
"deleted_at": None,
|
||||
"excerpt": parent.excerpt,
|
||||
"id": str(parent.id),
|
||||
"is_favorite": False,
|
||||
@@ -984,6 +1013,7 @@ def test_api_documents_tree_list_authenticated_related_parent():
|
||||
),
|
||||
"creator": str(parent_sibling.creator.id),
|
||||
"depth": 3,
|
||||
"deleted_at": None,
|
||||
"excerpt": parent_sibling.excerpt,
|
||||
"id": str(parent_sibling.id),
|
||||
"is_favorite": False,
|
||||
@@ -1005,6 +1035,7 @@ def test_api_documents_tree_list_authenticated_related_parent():
|
||||
"created_at": grand_parent.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(grand_parent.creator.id),
|
||||
"depth": 2,
|
||||
"deleted_at": None,
|
||||
"excerpt": grand_parent.excerpt,
|
||||
"id": str(grand_parent.id),
|
||||
"is_favorite": False,
|
||||
@@ -1094,6 +1125,7 @@ def test_api_documents_tree_list_authenticated_related_team_members(
|
||||
),
|
||||
"creator": str(child.creator.id),
|
||||
"depth": 3,
|
||||
"deleted_at": None,
|
||||
"excerpt": child.excerpt,
|
||||
"id": str(child.id),
|
||||
"is_favorite": False,
|
||||
@@ -1115,6 +1147,7 @@ def test_api_documents_tree_list_authenticated_related_team_members(
|
||||
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(document.creator.id),
|
||||
"depth": 2,
|
||||
"deleted_at": None,
|
||||
"excerpt": document.excerpt,
|
||||
"id": str(document.id),
|
||||
"is_favorite": False,
|
||||
@@ -1138,6 +1171,7 @@ def test_api_documents_tree_list_authenticated_related_team_members(
|
||||
"created_at": sibling.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(sibling.creator.id),
|
||||
"depth": 2,
|
||||
"deleted_at": None,
|
||||
"excerpt": sibling.excerpt,
|
||||
"id": str(sibling.id),
|
||||
"is_favorite": False,
|
||||
@@ -1157,6 +1191,7 @@ def test_api_documents_tree_list_authenticated_related_team_members(
|
||||
"created_at": parent.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(parent.creator.id),
|
||||
"depth": 1,
|
||||
"deleted_at": None,
|
||||
"excerpt": parent.excerpt,
|
||||
"id": str(parent.id),
|
||||
"is_favorite": False,
|
||||
@@ -1170,3 +1205,56 @@ def test_api_documents_tree_list_authenticated_related_team_members(
|
||||
"updated_at": parent.updated_at.isoformat().replace("+00:00", "Z"),
|
||||
"user_role": access.role,
|
||||
}
|
||||
|
||||
|
||||
def test_api_documents_tree_list_deleted_document():
|
||||
"""
|
||||
Tree of a deleted document should only be accessible to the owner.
|
||||
"""
|
||||
user = factories.UserFactory()
|
||||
client = APIClient()
|
||||
client.force_login(user)
|
||||
|
||||
parent = factories.DocumentFactory(link_reach="public")
|
||||
document, _ = factories.DocumentFactory.create_batch(2, parent=parent)
|
||||
factories.DocumentFactory(link_reach="public", parent=document)
|
||||
|
||||
document.soft_delete()
|
||||
|
||||
response = client.get(f"/api/v1.0/documents/{document.id!s}/tree/")
|
||||
assert response.status_code == 403
|
||||
|
||||
|
||||
def test_api_documents_tree_list_deleted_document_owner(django_assert_num_queries):
|
||||
"""
|
||||
Tree of a deleted document should only be accessible to the owner.
|
||||
"""
|
||||
user = factories.UserFactory()
|
||||
client = APIClient()
|
||||
client.force_login(user)
|
||||
|
||||
parent = factories.DocumentFactory(link_reach="public", users=[(user, "owner")])
|
||||
document, _ = factories.DocumentFactory.create_batch(2, parent=parent)
|
||||
child = factories.DocumentFactory(parent=document)
|
||||
|
||||
document.soft_delete()
|
||||
document.refresh_from_db()
|
||||
child.refresh_from_db()
|
||||
|
||||
with django_assert_num_queries(9):
|
||||
client.get(f"/api/v1.0/documents/{document.id!s}/tree/")
|
||||
|
||||
with django_assert_num_queries(5):
|
||||
response = client.get(f"/api/v1.0/documents/{document.id!s}/tree/")
|
||||
|
||||
assert response.status_code == 200
|
||||
content = response.json()
|
||||
assert content["id"] == str(document.id)
|
||||
assert content["deleted_at"] == document.deleted_at.isoformat().replace(
|
||||
"+00:00", "Z"
|
||||
)
|
||||
assert len(content["children"]) == 1
|
||||
assert content["children"][0]["id"] == str(child.id)
|
||||
assert content["children"][0][
|
||||
"deleted_at"
|
||||
] == child.ancestors_deleted_at.isoformat().replace("+00:00", "Z")
|
||||
|
||||
@@ -42,6 +42,7 @@ def test_api_config(is_authenticated):
|
||||
response = client.get("/api/v1.0/config/")
|
||||
assert response.status_code == HTTP_200_OK
|
||||
assert response.json() == {
|
||||
"AI_FEATURE_ENABLED": False,
|
||||
"COLLABORATION_WS_URL": "http://testcollab/",
|
||||
"COLLABORATION_WS_NOT_CONNECTED_READY_ONLY": True,
|
||||
"CRISP_WEBSITE_ID": "123",
|
||||
@@ -60,7 +61,7 @@ def test_api_config(is_authenticated):
|
||||
"MEDIA_BASE_URL": "http://testserver/",
|
||||
"POSTHOG_KEY": {"id": "132456", "host": "https://eu.i.posthog-test.com"},
|
||||
"SENTRY_DSN": "https://sentry.test/123",
|
||||
"AI_FEATURE_ENABLED": False,
|
||||
"TRASHBIN_CUTOFF_DAYS": 30,
|
||||
"theme_customization": {},
|
||||
}
|
||||
policy_list = sorted(response.headers["Content-Security-Policy"].split("; "))
|
||||
|
||||
@@ -375,8 +375,42 @@ def test_models_documents_get_abilities_owner(django_assert_num_queries):
|
||||
|
||||
document.soft_delete()
|
||||
document.refresh_from_db()
|
||||
expected_abilities["move"] = False
|
||||
assert document.get_abilities(user) == expected_abilities
|
||||
assert document.get_abilities(user) == {
|
||||
"accesses_manage": False,
|
||||
"accesses_view": False,
|
||||
"ai_transform": False,
|
||||
"ai_translate": False,
|
||||
"attachment_upload": False,
|
||||
"can_edit": False,
|
||||
"children_create": False,
|
||||
"children_list": False,
|
||||
"collaboration_auth": False,
|
||||
"descendants": False,
|
||||
"cors_proxy": False,
|
||||
"content": False,
|
||||
"destroy": False,
|
||||
"duplicate": False,
|
||||
"favorite": False,
|
||||
"invite_owner": False,
|
||||
"link_configuration": False,
|
||||
"link_select_options": {
|
||||
"authenticated": ["reader", "editor"],
|
||||
"public": ["reader", "editor"],
|
||||
"restricted": None,
|
||||
},
|
||||
"mask": False,
|
||||
"media_auth": False,
|
||||
"media_check": False,
|
||||
"move": False,
|
||||
"partial_update": False,
|
||||
"restore": True,
|
||||
"retrieve": True,
|
||||
"tree": True,
|
||||
"update": False,
|
||||
"versions_destroy": False,
|
||||
"versions_list": False,
|
||||
"versions_retrieve": False,
|
||||
}
|
||||
|
||||
|
||||
@override_settings(
|
||||
|
||||
@@ -8,7 +8,7 @@ from django.core.exceptions import ValidationError
|
||||
|
||||
import pytest
|
||||
|
||||
from core import factories
|
||||
from core import factories, models
|
||||
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
@@ -66,3 +66,33 @@ def test_models_users_sub_validator(sub, is_valid):
|
||||
match=("Enter a valid sub. This value should be ASCII only."),
|
||||
):
|
||||
user.full_clean()
|
||||
|
||||
|
||||
def test_modes_users_convert_valid_invitations():
|
||||
"""
|
||||
The "convert_valid_invitations" method should convert valid invitations to document accesses.
|
||||
"""
|
||||
email = "test@example.com"
|
||||
document = factories.DocumentFactory()
|
||||
other_document = factories.DocumentFactory()
|
||||
invitation_document = factories.InvitationFactory(email=email, document=document)
|
||||
invitation_other_document = factories.InvitationFactory(
|
||||
email="Test@example.coM", document=other_document
|
||||
)
|
||||
other_email_invitation = factories.InvitationFactory(
|
||||
email="pre_test@example.com", document=document
|
||||
)
|
||||
|
||||
assert document.accesses.count() == 0
|
||||
assert other_document.accesses.count() == 0
|
||||
|
||||
user = factories.UserFactory(email=email)
|
||||
|
||||
assert document.accesses.filter(user=user).count() == 1
|
||||
assert other_document.accesses.filter(user=user).count() == 1
|
||||
|
||||
assert not models.Invitation.objects.filter(id=invitation_document.id).exists()
|
||||
assert not models.Invitation.objects.filter(
|
||||
id=invitation_other_document.id
|
||||
).exists()
|
||||
assert models.Invitation.objects.filter(id=other_email_invitation.id).exists()
|
||||
|
||||
@@ -490,7 +490,7 @@ class Base(Configuration):
|
||||
environ_prefix=None,
|
||||
)
|
||||
|
||||
THEME_CUSTOMIZATION_CACHE_TIMEOUT = values.Value(
|
||||
THEME_CUSTOMIZATION_CACHE_TIMEOUT = values.IntegerValue(
|
||||
60 * 60 * 24,
|
||||
environ_name="THEME_CUSTOMIZATION_CACHE_TIMEOUT",
|
||||
environ_prefix=None,
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: lasuite-docs\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-09-10 14:29+0000\n"
|
||||
"PO-Revision-Date: 2025-09-12 09:50\n"
|
||||
"POT-Creation-Date: 2025-10-23 11:01+0000\n"
|
||||
"PO-Revision-Date: 2025-11-10 09:54\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Breton\n"
|
||||
"Language: br_FR\n"
|
||||
@@ -17,20 +17,20 @@ msgstr ""
|
||||
"X-Crowdin-File: backend-impress.pot\n"
|
||||
"X-Crowdin-File-ID: 18\n"
|
||||
|
||||
#: build/lib/core/admin.py:37 core/admin.py:37
|
||||
#: build/lib/core/admin.py:36 core/admin.py:36
|
||||
msgid "Personal info"
|
||||
msgstr "Titouroù personel"
|
||||
|
||||
#: build/lib/core/admin.py:50 build/lib/core/admin.py:138 core/admin.py:50
|
||||
#: core/admin.py:138
|
||||
#: build/lib/core/admin.py:49 build/lib/core/admin.py:137 core/admin.py:49
|
||||
#: core/admin.py:137
|
||||
msgid "Permissions"
|
||||
msgstr "Aotreoù"
|
||||
|
||||
#: build/lib/core/admin.py:62 core/admin.py:62
|
||||
#: build/lib/core/admin.py:61 core/admin.py:61
|
||||
msgid "Important dates"
|
||||
msgstr "Deiziadoù a-bouez"
|
||||
|
||||
#: build/lib/core/admin.py:148 core/admin.py:148
|
||||
#: build/lib/core/admin.py:147 core/admin.py:147
|
||||
msgid "Tree structure"
|
||||
msgstr "Gwezennadur"
|
||||
|
||||
@@ -50,27 +50,36 @@ msgstr "Kuzhet"
|
||||
msgid "Favorite"
|
||||
msgstr "Sinedoù"
|
||||
|
||||
#: build/lib/core/api/serializers.py:487 core/api/serializers.py:487
|
||||
#: build/lib/core/api/serializers.py:496 core/api/serializers.py:496
|
||||
msgid "A new document was created on your behalf!"
|
||||
msgstr "Ur restr nevez a zo bet krouet ganeoc'h!"
|
||||
|
||||
#: build/lib/core/api/serializers.py:491 core/api/serializers.py:491
|
||||
#: build/lib/core/api/serializers.py:500 core/api/serializers.py:500
|
||||
msgid "You have been granted ownership of a new document:"
|
||||
msgstr "C'hwi zo bet disklaeriet perc'henn ur restr nevez:"
|
||||
|
||||
#: build/lib/core/api/serializers.py:628 core/api/serializers.py:628
|
||||
#: build/lib/core/api/serializers.py:536 core/api/serializers.py:536
|
||||
msgid "This field is required."
|
||||
msgstr "Ar vaezienn-mañ a zo rekis."
|
||||
|
||||
#: build/lib/core/api/serializers.py:547 core/api/serializers.py:547
|
||||
#, python-format
|
||||
msgid "Link reach '%(link_reach)s' is not allowed based on parent document configuration."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:693 core/api/serializers.py:693
|
||||
msgid "Body"
|
||||
msgstr "Korf"
|
||||
|
||||
#: build/lib/core/api/serializers.py:631 core/api/serializers.py:631
|
||||
#: build/lib/core/api/serializers.py:696 core/api/serializers.py:696
|
||||
msgid "Body type"
|
||||
msgstr "Doare korf"
|
||||
|
||||
#: build/lib/core/api/serializers.py:637 core/api/serializers.py:637
|
||||
#: build/lib/core/api/serializers.py:702 core/api/serializers.py:702
|
||||
msgid "Format"
|
||||
msgstr "Stumm"
|
||||
|
||||
#: build/lib/core/api/viewsets.py:965 core/api/viewsets.py:965
|
||||
#: build/lib/core/api/viewsets.py:1003 core/api/viewsets.py:1003
|
||||
#, python-brace-format
|
||||
msgid "copy of {title}"
|
||||
msgstr "eilenn {title}"
|
||||
@@ -169,247 +178,247 @@ msgstr ""
|
||||
msgid "full name"
|
||||
msgstr "anv klok"
|
||||
|
||||
#: build/lib/core/models.py:151 core/models.py:151
|
||||
#: build/lib/core/models.py:152 core/models.py:152
|
||||
msgid "short name"
|
||||
msgstr "anv berr"
|
||||
|
||||
#: build/lib/core/models.py:153 core/models.py:153
|
||||
#: build/lib/core/models.py:155 core/models.py:155
|
||||
msgid "identity email address"
|
||||
msgstr "postel identelezh"
|
||||
|
||||
#: build/lib/core/models.py:158 core/models.py:158
|
||||
#: build/lib/core/models.py:160 core/models.py:160
|
||||
msgid "admin email address"
|
||||
msgstr "postel ar merour"
|
||||
|
||||
#: build/lib/core/models.py:165 core/models.py:165
|
||||
#: build/lib/core/models.py:167 core/models.py:167
|
||||
msgid "language"
|
||||
msgstr "yezh"
|
||||
|
||||
#: build/lib/core/models.py:166 core/models.py:166
|
||||
#: build/lib/core/models.py:168 core/models.py:168
|
||||
msgid "The language in which the user wants to see the interface."
|
||||
msgstr "Ar yezh a vo implijet evit etrefas an implijer."
|
||||
|
||||
#: build/lib/core/models.py:174 core/models.py:174
|
||||
#: build/lib/core/models.py:176 core/models.py:176
|
||||
msgid "The timezone in which the user wants to see times."
|
||||
msgstr "Ar gwerzhid-eur a vo implijet evit etrefas an implijer."
|
||||
|
||||
#: build/lib/core/models.py:177 core/models.py:177
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
msgid "device"
|
||||
msgstr "trevnad"
|
||||
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
#: build/lib/core/models.py:181 core/models.py:181
|
||||
msgid "Whether the user is a device or a real user."
|
||||
msgstr "Pe vefe an implijer un aparailh pe un implijer gwirion."
|
||||
|
||||
#: build/lib/core/models.py:182 core/models.py:182
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
msgid "staff status"
|
||||
msgstr "statud ar skipailh"
|
||||
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
#: build/lib/core/models.py:186 core/models.py:186
|
||||
msgid "Whether the user can log into this admin site."
|
||||
msgstr "Ma c'hall an implijer kevreañ ouzh al lec'hienn verañ-mañ."
|
||||
|
||||
#: build/lib/core/models.py:187 core/models.py:187
|
||||
#: build/lib/core/models.py:189 core/models.py:189
|
||||
msgid "active"
|
||||
msgstr "oberiant"
|
||||
|
||||
#: build/lib/core/models.py:190 core/models.py:190
|
||||
#: build/lib/core/models.py:192 core/models.py:192
|
||||
msgid "Whether this user should be treated as active. Unselect this instead of deleting accounts."
|
||||
msgstr "Ma rank bezañ tretet an implijer-mañ evel oberiant. Diziuzit an dra-mañ e-plas dilemel kontoù."
|
||||
|
||||
#: build/lib/core/models.py:202 core/models.py:202
|
||||
#: build/lib/core/models.py:204 core/models.py:204
|
||||
msgid "user"
|
||||
msgstr "implijer"
|
||||
|
||||
#: build/lib/core/models.py:203 core/models.py:203
|
||||
#: build/lib/core/models.py:205 core/models.py:205
|
||||
msgid "users"
|
||||
msgstr "implijerien"
|
||||
|
||||
#: build/lib/core/models.py:359 build/lib/core/models.py:1281
|
||||
#: core/models.py:359 core/models.py:1281
|
||||
#: build/lib/core/models.py:361 build/lib/core/models.py:1284
|
||||
#: core/models.py:361 core/models.py:1284
|
||||
msgid "title"
|
||||
msgstr "titl"
|
||||
|
||||
#: build/lib/core/models.py:360 core/models.py:360
|
||||
#: build/lib/core/models.py:362 core/models.py:362
|
||||
msgid "excerpt"
|
||||
msgstr "bomm"
|
||||
|
||||
#: build/lib/core/models.py:409 core/models.py:409
|
||||
#: build/lib/core/models.py:411 core/models.py:411
|
||||
msgid "Document"
|
||||
msgstr "Restr"
|
||||
|
||||
#: build/lib/core/models.py:410 core/models.py:410
|
||||
#: build/lib/core/models.py:412 core/models.py:412
|
||||
msgid "Documents"
|
||||
msgstr "Restroù"
|
||||
|
||||
#: build/lib/core/models.py:422 build/lib/core/models.py:819 core/models.py:422
|
||||
#: core/models.py:819
|
||||
#: build/lib/core/models.py:424 build/lib/core/models.py:822 core/models.py:424
|
||||
#: core/models.py:822
|
||||
msgid "Untitled Document"
|
||||
msgstr "Restr hep titl"
|
||||
|
||||
#: build/lib/core/models.py:854 core/models.py:854
|
||||
#: build/lib/core/models.py:857 core/models.py:857
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you!"
|
||||
msgstr "{name} en deus rannet ur restr ganeoc'h!"
|
||||
|
||||
#: build/lib/core/models.py:858 core/models.py:858
|
||||
#: build/lib/core/models.py:861 core/models.py:861
|
||||
#, python-brace-format
|
||||
msgid "{name} invited you with the role \"{role}\" on the following document:"
|
||||
msgstr "{name} en deus pedet ac'hanoc'h gant ar rol \"{role}\" war ar restr da-heul:"
|
||||
|
||||
#: build/lib/core/models.py:864 core/models.py:864
|
||||
#: build/lib/core/models.py:867 core/models.py:867
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you: {title}"
|
||||
msgstr "{name} en deus rannet ur restr ganeoc'h: {title}"
|
||||
|
||||
#: build/lib/core/models.py:964 core/models.py:964
|
||||
#: build/lib/core/models.py:967 core/models.py:967
|
||||
msgid "Document/user link trace"
|
||||
msgstr "Roud liamm ar restr/an implijer"
|
||||
|
||||
#: build/lib/core/models.py:965 core/models.py:965
|
||||
#: build/lib/core/models.py:968 core/models.py:968
|
||||
msgid "Document/user link traces"
|
||||
msgstr "Roudoù liamm ar restr/an implijer"
|
||||
|
||||
#: build/lib/core/models.py:971 core/models.py:971
|
||||
#: build/lib/core/models.py:974 core/models.py:974
|
||||
msgid "A link trace already exists for this document/user."
|
||||
msgstr "Ur roud liamm a zo dija evit an restr/an implijer."
|
||||
|
||||
#: build/lib/core/models.py:994 core/models.py:994
|
||||
#: build/lib/core/models.py:997 core/models.py:997
|
||||
msgid "Document favorite"
|
||||
msgstr "Restr muiañ-karet"
|
||||
|
||||
#: build/lib/core/models.py:995 core/models.py:995
|
||||
#: build/lib/core/models.py:998 core/models.py:998
|
||||
msgid "Document favorites"
|
||||
msgstr "Restroù muiañ-karet"
|
||||
|
||||
#: build/lib/core/models.py:1001 core/models.py:1001
|
||||
#: build/lib/core/models.py:1004 core/models.py:1004
|
||||
msgid "This document is already targeted by a favorite relation instance for the same user."
|
||||
msgstr "Ar restr-mañ a zo ur restr muiañ karet gant an implijer-mañ."
|
||||
|
||||
#: build/lib/core/models.py:1023 core/models.py:1023
|
||||
#: build/lib/core/models.py:1026 core/models.py:1026
|
||||
msgid "Document/user relation"
|
||||
msgstr "Liamm restr/implijer"
|
||||
|
||||
#: build/lib/core/models.py:1024 core/models.py:1024
|
||||
#: build/lib/core/models.py:1027 core/models.py:1027
|
||||
msgid "Document/user relations"
|
||||
msgstr "Liammoù restr/implijer"
|
||||
|
||||
#: build/lib/core/models.py:1030 core/models.py:1030
|
||||
#: build/lib/core/models.py:1033 core/models.py:1033
|
||||
msgid "This user is already in this document."
|
||||
msgstr "An implijer-mañ a zo dija er restr-mañ."
|
||||
|
||||
#: build/lib/core/models.py:1036 core/models.py:1036
|
||||
#: build/lib/core/models.py:1039 core/models.py:1039
|
||||
msgid "This team is already in this document."
|
||||
msgstr "Ar skipailh-mañ a zo dija en restr-mañ."
|
||||
|
||||
#: build/lib/core/models.py:1042 build/lib/core/models.py:1367
|
||||
#: core/models.py:1042 core/models.py:1367
|
||||
#: build/lib/core/models.py:1045 build/lib/core/models.py:1370
|
||||
#: core/models.py:1045 core/models.py:1370
|
||||
msgid "Either user or team must be set, not both."
|
||||
msgstr "An implijer pe ar skipailh a rank bezañ termenet, ket an daou avat."
|
||||
|
||||
#: build/lib/core/models.py:1188 core/models.py:1188
|
||||
#: build/lib/core/models.py:1191 core/models.py:1191
|
||||
msgid "Document ask for access"
|
||||
msgstr "Goulenn tizhout ar restr"
|
||||
|
||||
#: build/lib/core/models.py:1189 core/models.py:1189
|
||||
#: build/lib/core/models.py:1192 core/models.py:1192
|
||||
msgid "Document ask for accesses"
|
||||
msgstr "Goulennoù tizhout ar restr"
|
||||
|
||||
#: build/lib/core/models.py:1195 core/models.py:1195
|
||||
#: build/lib/core/models.py:1198 core/models.py:1198
|
||||
msgid "This user has already asked for access to this document."
|
||||
msgstr "An implijer en deus goulennet tizhout ar restr-mañ."
|
||||
|
||||
#: build/lib/core/models.py:1260 core/models.py:1260
|
||||
#: build/lib/core/models.py:1263 core/models.py:1263
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to a document!"
|
||||
msgstr "{name} en defe c'hoant da dizhout ar restr-mañ!"
|
||||
|
||||
#: build/lib/core/models.py:1264 core/models.py:1264
|
||||
#: build/lib/core/models.py:1267 core/models.py:1267
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to the following document:"
|
||||
msgstr "{name} en defe c'hoant da dizhout ar restr da-heul:"
|
||||
|
||||
#: build/lib/core/models.py:1270 core/models.py:1270
|
||||
#: build/lib/core/models.py:1273 core/models.py:1273
|
||||
#, python-brace-format
|
||||
msgid "{name} is asking for access to the document: {title}"
|
||||
msgstr "{name} en defe c'hoant da dizhout ar restr: {title}"
|
||||
|
||||
#: build/lib/core/models.py:1282 core/models.py:1282
|
||||
#: build/lib/core/models.py:1285 core/models.py:1285
|
||||
msgid "description"
|
||||
msgstr "deskrivadur"
|
||||
|
||||
#: build/lib/core/models.py:1283 core/models.py:1283
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
msgid "code"
|
||||
msgstr "kod"
|
||||
|
||||
#: build/lib/core/models.py:1284 core/models.py:1284
|
||||
#: build/lib/core/models.py:1287 core/models.py:1287
|
||||
msgid "css"
|
||||
msgstr "css"
|
||||
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
#: build/lib/core/models.py:1289 core/models.py:1289
|
||||
msgid "public"
|
||||
msgstr "publik"
|
||||
|
||||
#: build/lib/core/models.py:1288 core/models.py:1288
|
||||
#: build/lib/core/models.py:1291 core/models.py:1291
|
||||
msgid "Whether this template is public for anyone to use."
|
||||
msgstr "M'eo foran ar patrom-mañ hag implijus gant n'eus forzh piv."
|
||||
|
||||
#: build/lib/core/models.py:1294 core/models.py:1294
|
||||
#: build/lib/core/models.py:1297 core/models.py:1297
|
||||
msgid "Template"
|
||||
msgstr "Patrom"
|
||||
|
||||
#: build/lib/core/models.py:1295 core/models.py:1295
|
||||
#: build/lib/core/models.py:1298 core/models.py:1298
|
||||
msgid "Templates"
|
||||
msgstr "Patromoù"
|
||||
|
||||
#: build/lib/core/models.py:1348 core/models.py:1348
|
||||
#: build/lib/core/models.py:1351 core/models.py:1351
|
||||
msgid "Template/user relation"
|
||||
msgstr "Liamm patrom/implijer"
|
||||
|
||||
#: build/lib/core/models.py:1349 core/models.py:1349
|
||||
#: build/lib/core/models.py:1352 core/models.py:1352
|
||||
msgid "Template/user relations"
|
||||
msgstr "Liammoù patrom/implijer"
|
||||
|
||||
#: build/lib/core/models.py:1355 core/models.py:1355
|
||||
#: build/lib/core/models.py:1358 core/models.py:1358
|
||||
msgid "This user is already in this template."
|
||||
msgstr "An implijer-mañ a zo dija er patrom-mañ."
|
||||
|
||||
#: build/lib/core/models.py:1361 core/models.py:1361
|
||||
#: build/lib/core/models.py:1364 core/models.py:1364
|
||||
msgid "This team is already in this template."
|
||||
msgstr "Ar skipailh-mañ a zo dija er patrom-mañ."
|
||||
|
||||
#: build/lib/core/models.py:1438 core/models.py:1438
|
||||
#: build/lib/core/models.py:1441 core/models.py:1441
|
||||
msgid "email address"
|
||||
msgstr "postel"
|
||||
|
||||
#: build/lib/core/models.py:1457 core/models.py:1457
|
||||
#: build/lib/core/models.py:1460 core/models.py:1460
|
||||
msgid "Document invitation"
|
||||
msgstr "Pedadenn d'ur restr"
|
||||
|
||||
#: build/lib/core/models.py:1458 core/models.py:1458
|
||||
#: build/lib/core/models.py:1461 core/models.py:1461
|
||||
msgid "Document invitations"
|
||||
msgstr "Pedadennoù d'ur restr"
|
||||
|
||||
#: build/lib/core/models.py:1478 core/models.py:1478
|
||||
#: build/lib/core/models.py:1481 core/models.py:1481
|
||||
msgid "This email is already associated to a registered user."
|
||||
msgstr "Ar postel-mañ a zo liammet ouzh un implijer enskrivet."
|
||||
|
||||
#: core/templates/mail/html/template.html:162
|
||||
#: core/templates/mail/html/template.html:153
|
||||
#: core/templates/mail/text/template.txt:3
|
||||
msgid "Logo email"
|
||||
msgstr "Logo ar postel"
|
||||
|
||||
#: core/templates/mail/html/template.html:209
|
||||
#: core/templates/mail/html/template.html:200
|
||||
#: core/templates/mail/text/template.txt:10
|
||||
msgid "Open"
|
||||
msgstr "Digeriñ"
|
||||
|
||||
#: core/templates/mail/html/template.html:226
|
||||
#: core/templates/mail/html/template.html:217
|
||||
#: core/templates/mail/text/template.txt:14
|
||||
msgid " Docs, your new essential tool for organizing, sharing and collaborating on your documents as a team. "
|
||||
msgstr " Docs, hoc'h ostilh nevez ret-holl evit aozañ, rannañ ha kenlabourat war ar restr e skipailh. "
|
||||
|
||||
#: core/templates/mail/html/template.html:233
|
||||
#: core/templates/mail/html/template.html:224
|
||||
#: core/templates/mail/text/template.txt:16
|
||||
#, python-format
|
||||
msgid " Brought to you by %(brandname)s "
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: lasuite-docs\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-09-10 14:29+0000\n"
|
||||
"PO-Revision-Date: 2025-09-12 09:50\n"
|
||||
"POT-Creation-Date: 2025-10-23 11:01+0000\n"
|
||||
"PO-Revision-Date: 2025-11-10 09:54\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: German\n"
|
||||
"Language: de_DE\n"
|
||||
@@ -17,20 +17,20 @@ msgstr ""
|
||||
"X-Crowdin-File: backend-impress.pot\n"
|
||||
"X-Crowdin-File-ID: 18\n"
|
||||
|
||||
#: build/lib/core/admin.py:37 core/admin.py:37
|
||||
#: build/lib/core/admin.py:36 core/admin.py:36
|
||||
msgid "Personal info"
|
||||
msgstr "Persönliche Daten"
|
||||
|
||||
#: build/lib/core/admin.py:50 build/lib/core/admin.py:138 core/admin.py:50
|
||||
#: core/admin.py:138
|
||||
#: build/lib/core/admin.py:49 build/lib/core/admin.py:137 core/admin.py:49
|
||||
#: core/admin.py:137
|
||||
msgid "Permissions"
|
||||
msgstr "Berechtigungen"
|
||||
|
||||
#: build/lib/core/admin.py:62 core/admin.py:62
|
||||
#: build/lib/core/admin.py:61 core/admin.py:61
|
||||
msgid "Important dates"
|
||||
msgstr "Wichtige Daten"
|
||||
|
||||
#: build/lib/core/admin.py:148 core/admin.py:148
|
||||
#: build/lib/core/admin.py:147 core/admin.py:147
|
||||
msgid "Tree structure"
|
||||
msgstr "Baumstruktur"
|
||||
|
||||
@@ -50,27 +50,36 @@ msgstr ""
|
||||
msgid "Favorite"
|
||||
msgstr "Favorit"
|
||||
|
||||
#: build/lib/core/api/serializers.py:487 core/api/serializers.py:487
|
||||
#: build/lib/core/api/serializers.py:496 core/api/serializers.py:496
|
||||
msgid "A new document was created on your behalf!"
|
||||
msgstr "Ein neues Dokument wurde in Ihrem Namen erstellt!"
|
||||
|
||||
#: build/lib/core/api/serializers.py:491 core/api/serializers.py:491
|
||||
#: build/lib/core/api/serializers.py:500 core/api/serializers.py:500
|
||||
msgid "You have been granted ownership of a new document:"
|
||||
msgstr "Sie sind Besitzer eines neuen Dokuments:"
|
||||
|
||||
#: build/lib/core/api/serializers.py:628 core/api/serializers.py:628
|
||||
#: build/lib/core/api/serializers.py:536 core/api/serializers.py:536
|
||||
msgid "This field is required."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:547 core/api/serializers.py:547
|
||||
#, python-format
|
||||
msgid "Link reach '%(link_reach)s' is not allowed based on parent document configuration."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:693 core/api/serializers.py:693
|
||||
msgid "Body"
|
||||
msgstr "Inhalt"
|
||||
|
||||
#: build/lib/core/api/serializers.py:631 core/api/serializers.py:631
|
||||
#: build/lib/core/api/serializers.py:696 core/api/serializers.py:696
|
||||
msgid "Body type"
|
||||
msgstr "Typ"
|
||||
|
||||
#: build/lib/core/api/serializers.py:637 core/api/serializers.py:637
|
||||
#: build/lib/core/api/serializers.py:702 core/api/serializers.py:702
|
||||
msgid "Format"
|
||||
msgstr "Format"
|
||||
|
||||
#: build/lib/core/api/viewsets.py:965 core/api/viewsets.py:965
|
||||
#: build/lib/core/api/viewsets.py:1003 core/api/viewsets.py:1003
|
||||
#, python-brace-format
|
||||
msgid "copy of {title}"
|
||||
msgstr "Kopie von {title}"
|
||||
@@ -169,247 +178,247 @@ msgstr ""
|
||||
msgid "full name"
|
||||
msgstr "Name"
|
||||
|
||||
#: build/lib/core/models.py:151 core/models.py:151
|
||||
#: build/lib/core/models.py:152 core/models.py:152
|
||||
msgid "short name"
|
||||
msgstr "Kurzbezeichnung"
|
||||
|
||||
#: build/lib/core/models.py:153 core/models.py:153
|
||||
#: build/lib/core/models.py:155 core/models.py:155
|
||||
msgid "identity email address"
|
||||
msgstr "Identitäts-E-Mail-Adresse"
|
||||
|
||||
#: build/lib/core/models.py:158 core/models.py:158
|
||||
#: build/lib/core/models.py:160 core/models.py:160
|
||||
msgid "admin email address"
|
||||
msgstr "Admin E-Mail-Adresse"
|
||||
|
||||
#: build/lib/core/models.py:165 core/models.py:165
|
||||
#: build/lib/core/models.py:167 core/models.py:167
|
||||
msgid "language"
|
||||
msgstr "Sprache"
|
||||
|
||||
#: build/lib/core/models.py:166 core/models.py:166
|
||||
#: build/lib/core/models.py:168 core/models.py:168
|
||||
msgid "The language in which the user wants to see the interface."
|
||||
msgstr "Die Sprache, in der der Benutzer die Benutzeroberfläche sehen möchte."
|
||||
|
||||
#: build/lib/core/models.py:174 core/models.py:174
|
||||
#: build/lib/core/models.py:176 core/models.py:176
|
||||
msgid "The timezone in which the user wants to see times."
|
||||
msgstr "Die Zeitzone, in der der Nutzer Zeiten sehen möchte."
|
||||
|
||||
#: build/lib/core/models.py:177 core/models.py:177
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
msgid "device"
|
||||
msgstr "Gerät"
|
||||
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
#: build/lib/core/models.py:181 core/models.py:181
|
||||
msgid "Whether the user is a device or a real user."
|
||||
msgstr "Ob der Benutzer ein Gerät oder ein echter Benutzer ist."
|
||||
|
||||
#: build/lib/core/models.py:182 core/models.py:182
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
msgid "staff status"
|
||||
msgstr "Status des Teammitgliedes"
|
||||
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
#: build/lib/core/models.py:186 core/models.py:186
|
||||
msgid "Whether the user can log into this admin site."
|
||||
msgstr "Gibt an, ob der Benutzer sich in diese Admin-Seite einloggen kann."
|
||||
|
||||
#: build/lib/core/models.py:187 core/models.py:187
|
||||
#: build/lib/core/models.py:189 core/models.py:189
|
||||
msgid "active"
|
||||
msgstr "aktiviert"
|
||||
|
||||
#: build/lib/core/models.py:190 core/models.py:190
|
||||
#: build/lib/core/models.py:192 core/models.py:192
|
||||
msgid "Whether this user should be treated as active. Unselect this instead of deleting accounts."
|
||||
msgstr "Ob dieser Benutzer als aktiviert behandelt werden soll. Deaktivieren Sie diese Option, anstatt Konten zu löschen."
|
||||
|
||||
#: build/lib/core/models.py:202 core/models.py:202
|
||||
#: build/lib/core/models.py:204 core/models.py:204
|
||||
msgid "user"
|
||||
msgstr "Benutzer"
|
||||
|
||||
#: build/lib/core/models.py:203 core/models.py:203
|
||||
#: build/lib/core/models.py:205 core/models.py:205
|
||||
msgid "users"
|
||||
msgstr "Benutzer"
|
||||
|
||||
#: build/lib/core/models.py:359 build/lib/core/models.py:1281
|
||||
#: core/models.py:359 core/models.py:1281
|
||||
#: build/lib/core/models.py:361 build/lib/core/models.py:1284
|
||||
#: core/models.py:361 core/models.py:1284
|
||||
msgid "title"
|
||||
msgstr "Titel"
|
||||
|
||||
#: build/lib/core/models.py:360 core/models.py:360
|
||||
#: build/lib/core/models.py:362 core/models.py:362
|
||||
msgid "excerpt"
|
||||
msgstr "Auszug"
|
||||
|
||||
#: build/lib/core/models.py:409 core/models.py:409
|
||||
#: build/lib/core/models.py:411 core/models.py:411
|
||||
msgid "Document"
|
||||
msgstr "Dokument"
|
||||
|
||||
#: build/lib/core/models.py:410 core/models.py:410
|
||||
#: build/lib/core/models.py:412 core/models.py:412
|
||||
msgid "Documents"
|
||||
msgstr "Dokumente"
|
||||
|
||||
#: build/lib/core/models.py:422 build/lib/core/models.py:819 core/models.py:422
|
||||
#: core/models.py:819
|
||||
#: build/lib/core/models.py:424 build/lib/core/models.py:822 core/models.py:424
|
||||
#: core/models.py:822
|
||||
msgid "Untitled Document"
|
||||
msgstr "Unbenanntes Dokument"
|
||||
|
||||
#: build/lib/core/models.py:854 core/models.py:854
|
||||
#: build/lib/core/models.py:857 core/models.py:857
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you!"
|
||||
msgstr "{name} hat ein Dokument mit Ihnen geteilt!"
|
||||
|
||||
#: build/lib/core/models.py:858 core/models.py:858
|
||||
#: build/lib/core/models.py:861 core/models.py:861
|
||||
#, python-brace-format
|
||||
msgid "{name} invited you with the role \"{role}\" on the following document:"
|
||||
msgstr "{name} hat Sie mit der Rolle \"{role}\" zu folgendem Dokument eingeladen:"
|
||||
|
||||
#: build/lib/core/models.py:864 core/models.py:864
|
||||
#: build/lib/core/models.py:867 core/models.py:867
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you: {title}"
|
||||
msgstr "{name} hat ein Dokument mit Ihnen geteilt: {title}"
|
||||
|
||||
#: build/lib/core/models.py:964 core/models.py:964
|
||||
#: build/lib/core/models.py:967 core/models.py:967
|
||||
msgid "Document/user link trace"
|
||||
msgstr "Dokument/Benutzer Linkverfolgung"
|
||||
|
||||
#: build/lib/core/models.py:965 core/models.py:965
|
||||
#: build/lib/core/models.py:968 core/models.py:968
|
||||
msgid "Document/user link traces"
|
||||
msgstr "Dokument/Benutzer Linkverfolgung"
|
||||
|
||||
#: build/lib/core/models.py:971 core/models.py:971
|
||||
#: build/lib/core/models.py:974 core/models.py:974
|
||||
msgid "A link trace already exists for this document/user."
|
||||
msgstr "Für dieses Dokument/ diesen Benutzer ist bereits eine Linkverfolgung vorhanden."
|
||||
|
||||
#: build/lib/core/models.py:994 core/models.py:994
|
||||
#: build/lib/core/models.py:997 core/models.py:997
|
||||
msgid "Document favorite"
|
||||
msgstr "Dokumentenfavorit"
|
||||
|
||||
#: build/lib/core/models.py:995 core/models.py:995
|
||||
#: build/lib/core/models.py:998 core/models.py:998
|
||||
msgid "Document favorites"
|
||||
msgstr "Dokumentfavoriten"
|
||||
|
||||
#: build/lib/core/models.py:1001 core/models.py:1001
|
||||
#: build/lib/core/models.py:1004 core/models.py:1004
|
||||
msgid "This document is already targeted by a favorite relation instance for the same user."
|
||||
msgstr "Dieses Dokument ist bereits durch den gleichen Benutzer favorisiert worden."
|
||||
|
||||
#: build/lib/core/models.py:1023 core/models.py:1023
|
||||
#: build/lib/core/models.py:1026 core/models.py:1026
|
||||
msgid "Document/user relation"
|
||||
msgstr "Dokument/Benutzerbeziehung"
|
||||
|
||||
#: build/lib/core/models.py:1024 core/models.py:1024
|
||||
#: build/lib/core/models.py:1027 core/models.py:1027
|
||||
msgid "Document/user relations"
|
||||
msgstr "Dokument/Benutzerbeziehungen"
|
||||
|
||||
#: build/lib/core/models.py:1030 core/models.py:1030
|
||||
#: build/lib/core/models.py:1033 core/models.py:1033
|
||||
msgid "This user is already in this document."
|
||||
msgstr "Dieser Benutzer befindet sich bereits in diesem Dokument."
|
||||
|
||||
#: build/lib/core/models.py:1036 core/models.py:1036
|
||||
#: build/lib/core/models.py:1039 core/models.py:1039
|
||||
msgid "This team is already in this document."
|
||||
msgstr "Dieses Team befindet sich bereits in diesem Dokument."
|
||||
|
||||
#: build/lib/core/models.py:1042 build/lib/core/models.py:1367
|
||||
#: core/models.py:1042 core/models.py:1367
|
||||
#: build/lib/core/models.py:1045 build/lib/core/models.py:1370
|
||||
#: core/models.py:1045 core/models.py:1370
|
||||
msgid "Either user or team must be set, not both."
|
||||
msgstr "Benutzer oder Team müssen gesetzt werden, nicht beides."
|
||||
|
||||
#: build/lib/core/models.py:1188 core/models.py:1188
|
||||
#: build/lib/core/models.py:1191 core/models.py:1191
|
||||
msgid "Document ask for access"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1189 core/models.py:1189
|
||||
#: build/lib/core/models.py:1192 core/models.py:1192
|
||||
msgid "Document ask for accesses"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1195 core/models.py:1195
|
||||
#: build/lib/core/models.py:1198 core/models.py:1198
|
||||
msgid "This user has already asked for access to this document."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1260 core/models.py:1260
|
||||
#: build/lib/core/models.py:1263 core/models.py:1263
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to a document!"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1264 core/models.py:1264
|
||||
#: build/lib/core/models.py:1267 core/models.py:1267
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to the following document:"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1270 core/models.py:1270
|
||||
#: build/lib/core/models.py:1273 core/models.py:1273
|
||||
#, python-brace-format
|
||||
msgid "{name} is asking for access to the document: {title}"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1282 core/models.py:1282
|
||||
#: build/lib/core/models.py:1285 core/models.py:1285
|
||||
msgid "description"
|
||||
msgstr "Beschreibung"
|
||||
|
||||
#: build/lib/core/models.py:1283 core/models.py:1283
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
msgid "code"
|
||||
msgstr "Code"
|
||||
|
||||
#: build/lib/core/models.py:1284 core/models.py:1284
|
||||
#: build/lib/core/models.py:1287 core/models.py:1287
|
||||
msgid "css"
|
||||
msgstr "CSS"
|
||||
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
#: build/lib/core/models.py:1289 core/models.py:1289
|
||||
msgid "public"
|
||||
msgstr "öffentlich"
|
||||
|
||||
#: build/lib/core/models.py:1288 core/models.py:1288
|
||||
#: build/lib/core/models.py:1291 core/models.py:1291
|
||||
msgid "Whether this template is public for anyone to use."
|
||||
msgstr "Ob diese Vorlage für jedermann öffentlich ist."
|
||||
|
||||
#: build/lib/core/models.py:1294 core/models.py:1294
|
||||
#: build/lib/core/models.py:1297 core/models.py:1297
|
||||
msgid "Template"
|
||||
msgstr "Vorlage"
|
||||
|
||||
#: build/lib/core/models.py:1295 core/models.py:1295
|
||||
#: build/lib/core/models.py:1298 core/models.py:1298
|
||||
msgid "Templates"
|
||||
msgstr "Vorlagen"
|
||||
|
||||
#: build/lib/core/models.py:1348 core/models.py:1348
|
||||
#: build/lib/core/models.py:1351 core/models.py:1351
|
||||
msgid "Template/user relation"
|
||||
msgstr "Vorlage/Benutzer-Beziehung"
|
||||
|
||||
#: build/lib/core/models.py:1349 core/models.py:1349
|
||||
#: build/lib/core/models.py:1352 core/models.py:1352
|
||||
msgid "Template/user relations"
|
||||
msgstr "Vorlage/Benutzerbeziehungen"
|
||||
|
||||
#: build/lib/core/models.py:1355 core/models.py:1355
|
||||
#: build/lib/core/models.py:1358 core/models.py:1358
|
||||
msgid "This user is already in this template."
|
||||
msgstr "Dieser Benutzer ist bereits in dieser Vorlage."
|
||||
|
||||
#: build/lib/core/models.py:1361 core/models.py:1361
|
||||
#: build/lib/core/models.py:1364 core/models.py:1364
|
||||
msgid "This team is already in this template."
|
||||
msgstr "Dieses Team ist bereits in diesem Template."
|
||||
|
||||
#: build/lib/core/models.py:1438 core/models.py:1438
|
||||
#: build/lib/core/models.py:1441 core/models.py:1441
|
||||
msgid "email address"
|
||||
msgstr "E-Mail-Adresse"
|
||||
|
||||
#: build/lib/core/models.py:1457 core/models.py:1457
|
||||
#: build/lib/core/models.py:1460 core/models.py:1460
|
||||
msgid "Document invitation"
|
||||
msgstr "Einladung zum Dokument"
|
||||
|
||||
#: build/lib/core/models.py:1458 core/models.py:1458
|
||||
#: build/lib/core/models.py:1461 core/models.py:1461
|
||||
msgid "Document invitations"
|
||||
msgstr "Dokumenteinladungen"
|
||||
|
||||
#: build/lib/core/models.py:1478 core/models.py:1478
|
||||
#: build/lib/core/models.py:1481 core/models.py:1481
|
||||
msgid "This email is already associated to a registered user."
|
||||
msgstr "Diese E-Mail ist bereits einem registrierten Benutzer zugeordnet."
|
||||
|
||||
#: core/templates/mail/html/template.html:162
|
||||
#: core/templates/mail/html/template.html:153
|
||||
#: core/templates/mail/text/template.txt:3
|
||||
msgid "Logo email"
|
||||
msgstr "Logo-E-Mail"
|
||||
|
||||
#: core/templates/mail/html/template.html:209
|
||||
#: core/templates/mail/html/template.html:200
|
||||
#: core/templates/mail/text/template.txt:10
|
||||
msgid "Open"
|
||||
msgstr "Öffnen"
|
||||
|
||||
#: core/templates/mail/html/template.html:226
|
||||
#: core/templates/mail/html/template.html:217
|
||||
#: core/templates/mail/text/template.txt:14
|
||||
msgid " Docs, your new essential tool for organizing, sharing and collaborating on your documents as a team. "
|
||||
msgstr " Docs, Ihr neues unentbehrliches Werkzeug für die Organisation, den Austausch und die Zusammenarbeit in Ihren Dokumenten als Team. "
|
||||
|
||||
#: core/templates/mail/html/template.html:233
|
||||
#: core/templates/mail/html/template.html:224
|
||||
#: core/templates/mail/text/template.txt:16
|
||||
#, python-format
|
||||
msgid " Brought to you by %(brandname)s "
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: lasuite-docs\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-09-10 14:29+0000\n"
|
||||
"PO-Revision-Date: 2025-09-12 09:50\n"
|
||||
"POT-Creation-Date: 2025-10-23 11:01+0000\n"
|
||||
"PO-Revision-Date: 2025-11-10 09:54\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: English\n"
|
||||
"Language: en_US\n"
|
||||
@@ -17,20 +17,20 @@ msgstr ""
|
||||
"X-Crowdin-File: backend-impress.pot\n"
|
||||
"X-Crowdin-File-ID: 18\n"
|
||||
|
||||
#: build/lib/core/admin.py:37 core/admin.py:37
|
||||
#: build/lib/core/admin.py:36 core/admin.py:36
|
||||
msgid "Personal info"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/admin.py:50 build/lib/core/admin.py:138 core/admin.py:50
|
||||
#: core/admin.py:138
|
||||
#: build/lib/core/admin.py:49 build/lib/core/admin.py:137 core/admin.py:49
|
||||
#: core/admin.py:137
|
||||
msgid "Permissions"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/admin.py:62 core/admin.py:62
|
||||
#: build/lib/core/admin.py:61 core/admin.py:61
|
||||
msgid "Important dates"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/admin.py:148 core/admin.py:148
|
||||
#: build/lib/core/admin.py:147 core/admin.py:147
|
||||
msgid "Tree structure"
|
||||
msgstr ""
|
||||
|
||||
@@ -50,27 +50,36 @@ msgstr ""
|
||||
msgid "Favorite"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:487 core/api/serializers.py:487
|
||||
#: build/lib/core/api/serializers.py:496 core/api/serializers.py:496
|
||||
msgid "A new document was created on your behalf!"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:491 core/api/serializers.py:491
|
||||
#: build/lib/core/api/serializers.py:500 core/api/serializers.py:500
|
||||
msgid "You have been granted ownership of a new document:"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:628 core/api/serializers.py:628
|
||||
#: build/lib/core/api/serializers.py:536 core/api/serializers.py:536
|
||||
msgid "This field is required."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:547 core/api/serializers.py:547
|
||||
#, python-format
|
||||
msgid "Link reach '%(link_reach)s' is not allowed based on parent document configuration."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:693 core/api/serializers.py:693
|
||||
msgid "Body"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:631 core/api/serializers.py:631
|
||||
#: build/lib/core/api/serializers.py:696 core/api/serializers.py:696
|
||||
msgid "Body type"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:637 core/api/serializers.py:637
|
||||
#: build/lib/core/api/serializers.py:702 core/api/serializers.py:702
|
||||
msgid "Format"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/viewsets.py:965 core/api/viewsets.py:965
|
||||
#: build/lib/core/api/viewsets.py:1003 core/api/viewsets.py:1003
|
||||
#, python-brace-format
|
||||
msgid "copy of {title}"
|
||||
msgstr ""
|
||||
@@ -169,247 +178,247 @@ msgstr ""
|
||||
msgid "full name"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:151 core/models.py:151
|
||||
#: build/lib/core/models.py:152 core/models.py:152
|
||||
msgid "short name"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:153 core/models.py:153
|
||||
#: build/lib/core/models.py:155 core/models.py:155
|
||||
msgid "identity email address"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:158 core/models.py:158
|
||||
#: build/lib/core/models.py:160 core/models.py:160
|
||||
msgid "admin email address"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:165 core/models.py:165
|
||||
#: build/lib/core/models.py:167 core/models.py:167
|
||||
msgid "language"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:166 core/models.py:166
|
||||
#: build/lib/core/models.py:168 core/models.py:168
|
||||
msgid "The language in which the user wants to see the interface."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:174 core/models.py:174
|
||||
#: build/lib/core/models.py:176 core/models.py:176
|
||||
msgid "The timezone in which the user wants to see times."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:177 core/models.py:177
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
msgid "device"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
#: build/lib/core/models.py:181 core/models.py:181
|
||||
msgid "Whether the user is a device or a real user."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:182 core/models.py:182
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
msgid "staff status"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
#: build/lib/core/models.py:186 core/models.py:186
|
||||
msgid "Whether the user can log into this admin site."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:187 core/models.py:187
|
||||
#: build/lib/core/models.py:189 core/models.py:189
|
||||
msgid "active"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:190 core/models.py:190
|
||||
#: build/lib/core/models.py:192 core/models.py:192
|
||||
msgid "Whether this user should be treated as active. Unselect this instead of deleting accounts."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:202 core/models.py:202
|
||||
#: build/lib/core/models.py:204 core/models.py:204
|
||||
msgid "user"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:203 core/models.py:203
|
||||
#: build/lib/core/models.py:205 core/models.py:205
|
||||
msgid "users"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:359 build/lib/core/models.py:1281
|
||||
#: core/models.py:359 core/models.py:1281
|
||||
#: build/lib/core/models.py:361 build/lib/core/models.py:1284
|
||||
#: core/models.py:361 core/models.py:1284
|
||||
msgid "title"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:360 core/models.py:360
|
||||
#: build/lib/core/models.py:362 core/models.py:362
|
||||
msgid "excerpt"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:409 core/models.py:409
|
||||
#: build/lib/core/models.py:411 core/models.py:411
|
||||
msgid "Document"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:410 core/models.py:410
|
||||
#: build/lib/core/models.py:412 core/models.py:412
|
||||
msgid "Documents"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:422 build/lib/core/models.py:819 core/models.py:422
|
||||
#: core/models.py:819
|
||||
#: build/lib/core/models.py:424 build/lib/core/models.py:822 core/models.py:424
|
||||
#: core/models.py:822
|
||||
msgid "Untitled Document"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:854 core/models.py:854
|
||||
#: build/lib/core/models.py:857 core/models.py:857
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you!"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:858 core/models.py:858
|
||||
#: build/lib/core/models.py:861 core/models.py:861
|
||||
#, python-brace-format
|
||||
msgid "{name} invited you with the role \"{role}\" on the following document:"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:864 core/models.py:864
|
||||
#: build/lib/core/models.py:867 core/models.py:867
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you: {title}"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:964 core/models.py:964
|
||||
#: build/lib/core/models.py:967 core/models.py:967
|
||||
msgid "Document/user link trace"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:965 core/models.py:965
|
||||
#: build/lib/core/models.py:968 core/models.py:968
|
||||
msgid "Document/user link traces"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:971 core/models.py:971
|
||||
#: build/lib/core/models.py:974 core/models.py:974
|
||||
msgid "A link trace already exists for this document/user."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:994 core/models.py:994
|
||||
#: build/lib/core/models.py:997 core/models.py:997
|
||||
msgid "Document favorite"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:995 core/models.py:995
|
||||
#: build/lib/core/models.py:998 core/models.py:998
|
||||
msgid "Document favorites"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1001 core/models.py:1001
|
||||
#: build/lib/core/models.py:1004 core/models.py:1004
|
||||
msgid "This document is already targeted by a favorite relation instance for the same user."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1023 core/models.py:1023
|
||||
#: build/lib/core/models.py:1026 core/models.py:1026
|
||||
msgid "Document/user relation"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1024 core/models.py:1024
|
||||
#: build/lib/core/models.py:1027 core/models.py:1027
|
||||
msgid "Document/user relations"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1030 core/models.py:1030
|
||||
#: build/lib/core/models.py:1033 core/models.py:1033
|
||||
msgid "This user is already in this document."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1036 core/models.py:1036
|
||||
#: build/lib/core/models.py:1039 core/models.py:1039
|
||||
msgid "This team is already in this document."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1042 build/lib/core/models.py:1367
|
||||
#: core/models.py:1042 core/models.py:1367
|
||||
#: build/lib/core/models.py:1045 build/lib/core/models.py:1370
|
||||
#: core/models.py:1045 core/models.py:1370
|
||||
msgid "Either user or team must be set, not both."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1188 core/models.py:1188
|
||||
#: build/lib/core/models.py:1191 core/models.py:1191
|
||||
msgid "Document ask for access"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1189 core/models.py:1189
|
||||
#: build/lib/core/models.py:1192 core/models.py:1192
|
||||
msgid "Document ask for accesses"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1195 core/models.py:1195
|
||||
#: build/lib/core/models.py:1198 core/models.py:1198
|
||||
msgid "This user has already asked for access to this document."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1260 core/models.py:1260
|
||||
#: build/lib/core/models.py:1263 core/models.py:1263
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to a document!"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1264 core/models.py:1264
|
||||
#: build/lib/core/models.py:1267 core/models.py:1267
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to the following document:"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1270 core/models.py:1270
|
||||
#: build/lib/core/models.py:1273 core/models.py:1273
|
||||
#, python-brace-format
|
||||
msgid "{name} is asking for access to the document: {title}"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1282 core/models.py:1282
|
||||
#: build/lib/core/models.py:1285 core/models.py:1285
|
||||
msgid "description"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1283 core/models.py:1283
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
msgid "code"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1284 core/models.py:1284
|
||||
#: build/lib/core/models.py:1287 core/models.py:1287
|
||||
msgid "css"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
#: build/lib/core/models.py:1289 core/models.py:1289
|
||||
msgid "public"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1288 core/models.py:1288
|
||||
#: build/lib/core/models.py:1291 core/models.py:1291
|
||||
msgid "Whether this template is public for anyone to use."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1294 core/models.py:1294
|
||||
#: build/lib/core/models.py:1297 core/models.py:1297
|
||||
msgid "Template"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1295 core/models.py:1295
|
||||
#: build/lib/core/models.py:1298 core/models.py:1298
|
||||
msgid "Templates"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1348 core/models.py:1348
|
||||
#: build/lib/core/models.py:1351 core/models.py:1351
|
||||
msgid "Template/user relation"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1349 core/models.py:1349
|
||||
#: build/lib/core/models.py:1352 core/models.py:1352
|
||||
msgid "Template/user relations"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1355 core/models.py:1355
|
||||
#: build/lib/core/models.py:1358 core/models.py:1358
|
||||
msgid "This user is already in this template."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1361 core/models.py:1361
|
||||
#: build/lib/core/models.py:1364 core/models.py:1364
|
||||
msgid "This team is already in this template."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1438 core/models.py:1438
|
||||
#: build/lib/core/models.py:1441 core/models.py:1441
|
||||
msgid "email address"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1457 core/models.py:1457
|
||||
#: build/lib/core/models.py:1460 core/models.py:1460
|
||||
msgid "Document invitation"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1458 core/models.py:1458
|
||||
#: build/lib/core/models.py:1461 core/models.py:1461
|
||||
msgid "Document invitations"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1478 core/models.py:1478
|
||||
#: build/lib/core/models.py:1481 core/models.py:1481
|
||||
msgid "This email is already associated to a registered user."
|
||||
msgstr ""
|
||||
|
||||
#: core/templates/mail/html/template.html:162
|
||||
#: core/templates/mail/html/template.html:153
|
||||
#: core/templates/mail/text/template.txt:3
|
||||
msgid "Logo email"
|
||||
msgstr ""
|
||||
|
||||
#: core/templates/mail/html/template.html:209
|
||||
#: core/templates/mail/html/template.html:200
|
||||
#: core/templates/mail/text/template.txt:10
|
||||
msgid "Open"
|
||||
msgstr ""
|
||||
|
||||
#: core/templates/mail/html/template.html:226
|
||||
#: core/templates/mail/html/template.html:217
|
||||
#: core/templates/mail/text/template.txt:14
|
||||
msgid " Docs, your new essential tool for organizing, sharing and collaborating on your documents as a team. "
|
||||
msgstr ""
|
||||
|
||||
#: core/templates/mail/html/template.html:233
|
||||
#: core/templates/mail/html/template.html:224
|
||||
#: core/templates/mail/text/template.txt:16
|
||||
#, python-format
|
||||
msgid " Brought to you by %(brandname)s "
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: lasuite-docs\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-09-10 14:29+0000\n"
|
||||
"PO-Revision-Date: 2025-09-12 09:50\n"
|
||||
"POT-Creation-Date: 2025-10-23 11:01+0000\n"
|
||||
"PO-Revision-Date: 2025-11-10 09:54\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Spanish\n"
|
||||
"Language: es_ES\n"
|
||||
@@ -17,20 +17,20 @@ msgstr ""
|
||||
"X-Crowdin-File: backend-impress.pot\n"
|
||||
"X-Crowdin-File-ID: 18\n"
|
||||
|
||||
#: build/lib/core/admin.py:37 core/admin.py:37
|
||||
#: build/lib/core/admin.py:36 core/admin.py:36
|
||||
msgid "Personal info"
|
||||
msgstr "Información Personal"
|
||||
|
||||
#: build/lib/core/admin.py:50 build/lib/core/admin.py:138 core/admin.py:50
|
||||
#: core/admin.py:138
|
||||
#: build/lib/core/admin.py:49 build/lib/core/admin.py:137 core/admin.py:49
|
||||
#: core/admin.py:137
|
||||
msgid "Permissions"
|
||||
msgstr "Permisos"
|
||||
|
||||
#: build/lib/core/admin.py:62 core/admin.py:62
|
||||
#: build/lib/core/admin.py:61 core/admin.py:61
|
||||
msgid "Important dates"
|
||||
msgstr "Fechas importantes"
|
||||
|
||||
#: build/lib/core/admin.py:148 core/admin.py:148
|
||||
#: build/lib/core/admin.py:147 core/admin.py:147
|
||||
msgid "Tree structure"
|
||||
msgstr "Estructura en árbol"
|
||||
|
||||
@@ -50,27 +50,36 @@ msgstr ""
|
||||
msgid "Favorite"
|
||||
msgstr "Favorito"
|
||||
|
||||
#: build/lib/core/api/serializers.py:487 core/api/serializers.py:487
|
||||
#: build/lib/core/api/serializers.py:496 core/api/serializers.py:496
|
||||
msgid "A new document was created on your behalf!"
|
||||
msgstr "¡Un nuevo documento se ha creado por ti!"
|
||||
|
||||
#: build/lib/core/api/serializers.py:491 core/api/serializers.py:491
|
||||
#: build/lib/core/api/serializers.py:500 core/api/serializers.py:500
|
||||
msgid "You have been granted ownership of a new document:"
|
||||
msgstr "Se le ha concedido la propiedad de un nuevo documento :"
|
||||
|
||||
#: build/lib/core/api/serializers.py:628 core/api/serializers.py:628
|
||||
#: build/lib/core/api/serializers.py:536 core/api/serializers.py:536
|
||||
msgid "This field is required."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:547 core/api/serializers.py:547
|
||||
#, python-format
|
||||
msgid "Link reach '%(link_reach)s' is not allowed based on parent document configuration."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:693 core/api/serializers.py:693
|
||||
msgid "Body"
|
||||
msgstr "Cuerpo"
|
||||
|
||||
#: build/lib/core/api/serializers.py:631 core/api/serializers.py:631
|
||||
#: build/lib/core/api/serializers.py:696 core/api/serializers.py:696
|
||||
msgid "Body type"
|
||||
msgstr "Tipo de Cuerpo"
|
||||
|
||||
#: build/lib/core/api/serializers.py:637 core/api/serializers.py:637
|
||||
#: build/lib/core/api/serializers.py:702 core/api/serializers.py:702
|
||||
msgid "Format"
|
||||
msgstr "Formato"
|
||||
|
||||
#: build/lib/core/api/viewsets.py:965 core/api/viewsets.py:965
|
||||
#: build/lib/core/api/viewsets.py:1003 core/api/viewsets.py:1003
|
||||
#, python-brace-format
|
||||
msgid "copy of {title}"
|
||||
msgstr "copia de {title}"
|
||||
@@ -169,247 +178,247 @@ msgstr "Obligatorio. 255 caracteres o menos. Solo caracteres ASCII."
|
||||
msgid "full name"
|
||||
msgstr "nombre completo"
|
||||
|
||||
#: build/lib/core/models.py:151 core/models.py:151
|
||||
#: build/lib/core/models.py:152 core/models.py:152
|
||||
msgid "short name"
|
||||
msgstr "nombre abreviado"
|
||||
|
||||
#: build/lib/core/models.py:153 core/models.py:153
|
||||
#: build/lib/core/models.py:155 core/models.py:155
|
||||
msgid "identity email address"
|
||||
msgstr "correo electrónico de identidad"
|
||||
|
||||
#: build/lib/core/models.py:158 core/models.py:158
|
||||
#: build/lib/core/models.py:160 core/models.py:160
|
||||
msgid "admin email address"
|
||||
msgstr "correo electrónico del administrador"
|
||||
|
||||
#: build/lib/core/models.py:165 core/models.py:165
|
||||
#: build/lib/core/models.py:167 core/models.py:167
|
||||
msgid "language"
|
||||
msgstr "idioma"
|
||||
|
||||
#: build/lib/core/models.py:166 core/models.py:166
|
||||
#: build/lib/core/models.py:168 core/models.py:168
|
||||
msgid "The language in which the user wants to see the interface."
|
||||
msgstr "El idioma en el que el usuario desea ver la interfaz."
|
||||
|
||||
#: build/lib/core/models.py:174 core/models.py:174
|
||||
#: build/lib/core/models.py:176 core/models.py:176
|
||||
msgid "The timezone in which the user wants to see times."
|
||||
msgstr "La zona horaria en la que el usuario quiere ver los tiempos."
|
||||
|
||||
#: build/lib/core/models.py:177 core/models.py:177
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
msgid "device"
|
||||
msgstr "dispositivo"
|
||||
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
#: build/lib/core/models.py:181 core/models.py:181
|
||||
msgid "Whether the user is a device or a real user."
|
||||
msgstr "Si el usuario es un dispositivo o un usuario real."
|
||||
|
||||
#: build/lib/core/models.py:182 core/models.py:182
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
msgid "staff status"
|
||||
msgstr "rol en el equipo"
|
||||
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
#: build/lib/core/models.py:186 core/models.py:186
|
||||
msgid "Whether the user can log into this admin site."
|
||||
msgstr "Si el usuario puede iniciar sesión en esta página web de administración."
|
||||
|
||||
#: build/lib/core/models.py:187 core/models.py:187
|
||||
#: build/lib/core/models.py:189 core/models.py:189
|
||||
msgid "active"
|
||||
msgstr "activo"
|
||||
|
||||
#: build/lib/core/models.py:190 core/models.py:190
|
||||
#: build/lib/core/models.py:192 core/models.py:192
|
||||
msgid "Whether this user should be treated as active. Unselect this instead of deleting accounts."
|
||||
msgstr "Si este usuario debe ser considerado como activo. Deseleccionar en lugar de eliminar cuentas."
|
||||
|
||||
#: build/lib/core/models.py:202 core/models.py:202
|
||||
#: build/lib/core/models.py:204 core/models.py:204
|
||||
msgid "user"
|
||||
msgstr "usuario"
|
||||
|
||||
#: build/lib/core/models.py:203 core/models.py:203
|
||||
#: build/lib/core/models.py:205 core/models.py:205
|
||||
msgid "users"
|
||||
msgstr "usuarios"
|
||||
|
||||
#: build/lib/core/models.py:359 build/lib/core/models.py:1281
|
||||
#: core/models.py:359 core/models.py:1281
|
||||
#: build/lib/core/models.py:361 build/lib/core/models.py:1284
|
||||
#: core/models.py:361 core/models.py:1284
|
||||
msgid "title"
|
||||
msgstr "título"
|
||||
|
||||
#: build/lib/core/models.py:360 core/models.py:360
|
||||
#: build/lib/core/models.py:362 core/models.py:362
|
||||
msgid "excerpt"
|
||||
msgstr "resumen"
|
||||
|
||||
#: build/lib/core/models.py:409 core/models.py:409
|
||||
#: build/lib/core/models.py:411 core/models.py:411
|
||||
msgid "Document"
|
||||
msgstr "Documento"
|
||||
|
||||
#: build/lib/core/models.py:410 core/models.py:410
|
||||
#: build/lib/core/models.py:412 core/models.py:412
|
||||
msgid "Documents"
|
||||
msgstr "Documentos"
|
||||
|
||||
#: build/lib/core/models.py:422 build/lib/core/models.py:819 core/models.py:422
|
||||
#: core/models.py:819
|
||||
#: build/lib/core/models.py:424 build/lib/core/models.py:822 core/models.py:424
|
||||
#: core/models.py:822
|
||||
msgid "Untitled Document"
|
||||
msgstr "Documento sin título"
|
||||
|
||||
#: build/lib/core/models.py:854 core/models.py:854
|
||||
#: build/lib/core/models.py:857 core/models.py:857
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you!"
|
||||
msgstr "¡{name} ha compartido un documento contigo!"
|
||||
|
||||
#: build/lib/core/models.py:858 core/models.py:858
|
||||
#: build/lib/core/models.py:861 core/models.py:861
|
||||
#, python-brace-format
|
||||
msgid "{name} invited you with the role \"{role}\" on the following document:"
|
||||
msgstr "Te ha invitado {name} al siguiente documento con el rol \"{role}\" :"
|
||||
|
||||
#: build/lib/core/models.py:864 core/models.py:864
|
||||
#: build/lib/core/models.py:867 core/models.py:867
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you: {title}"
|
||||
msgstr "{name} ha compartido un documento contigo: {title}"
|
||||
|
||||
#: build/lib/core/models.py:964 core/models.py:964
|
||||
#: build/lib/core/models.py:967 core/models.py:967
|
||||
msgid "Document/user link trace"
|
||||
msgstr "Traza del enlace de documento/usuario"
|
||||
|
||||
#: build/lib/core/models.py:965 core/models.py:965
|
||||
#: build/lib/core/models.py:968 core/models.py:968
|
||||
msgid "Document/user link traces"
|
||||
msgstr "Trazas del enlace de documento/usuario"
|
||||
|
||||
#: build/lib/core/models.py:971 core/models.py:971
|
||||
#: build/lib/core/models.py:974 core/models.py:974
|
||||
msgid "A link trace already exists for this document/user."
|
||||
msgstr "Ya existe una traza de enlace para este documento/usuario."
|
||||
|
||||
#: build/lib/core/models.py:994 core/models.py:994
|
||||
#: build/lib/core/models.py:997 core/models.py:997
|
||||
msgid "Document favorite"
|
||||
msgstr "Documento favorito"
|
||||
|
||||
#: build/lib/core/models.py:995 core/models.py:995
|
||||
#: build/lib/core/models.py:998 core/models.py:998
|
||||
msgid "Document favorites"
|
||||
msgstr "Documentos favoritos"
|
||||
|
||||
#: build/lib/core/models.py:1001 core/models.py:1001
|
||||
#: build/lib/core/models.py:1004 core/models.py:1004
|
||||
msgid "This document is already targeted by a favorite relation instance for the same user."
|
||||
msgstr "Este documento ya ha sido marcado como favorito por el usuario."
|
||||
|
||||
#: build/lib/core/models.py:1023 core/models.py:1023
|
||||
#: build/lib/core/models.py:1026 core/models.py:1026
|
||||
msgid "Document/user relation"
|
||||
msgstr "Relación documento/usuario"
|
||||
|
||||
#: build/lib/core/models.py:1024 core/models.py:1024
|
||||
#: build/lib/core/models.py:1027 core/models.py:1027
|
||||
msgid "Document/user relations"
|
||||
msgstr "Relaciones documento/usuario"
|
||||
|
||||
#: build/lib/core/models.py:1030 core/models.py:1030
|
||||
#: build/lib/core/models.py:1033 core/models.py:1033
|
||||
msgid "This user is already in this document."
|
||||
msgstr "Este usuario ya forma parte del documento."
|
||||
|
||||
#: build/lib/core/models.py:1036 core/models.py:1036
|
||||
#: build/lib/core/models.py:1039 core/models.py:1039
|
||||
msgid "This team is already in this document."
|
||||
msgstr "Este equipo ya forma parte del documento."
|
||||
|
||||
#: build/lib/core/models.py:1042 build/lib/core/models.py:1367
|
||||
#: core/models.py:1042 core/models.py:1367
|
||||
#: build/lib/core/models.py:1045 build/lib/core/models.py:1370
|
||||
#: core/models.py:1045 core/models.py:1370
|
||||
msgid "Either user or team must be set, not both."
|
||||
msgstr "Debe establecerse un usuario o un equipo, no ambos."
|
||||
|
||||
#: build/lib/core/models.py:1188 core/models.py:1188
|
||||
#: build/lib/core/models.py:1191 core/models.py:1191
|
||||
msgid "Document ask for access"
|
||||
msgstr "Solicitud de acceso"
|
||||
|
||||
#: build/lib/core/models.py:1189 core/models.py:1189
|
||||
#: build/lib/core/models.py:1192 core/models.py:1192
|
||||
msgid "Document ask for accesses"
|
||||
msgstr "Solicitud de accesos"
|
||||
|
||||
#: build/lib/core/models.py:1195 core/models.py:1195
|
||||
#: build/lib/core/models.py:1198 core/models.py:1198
|
||||
msgid "This user has already asked for access to this document."
|
||||
msgstr "Este usuario ya ha solicitado acceso a este documento."
|
||||
|
||||
#: build/lib/core/models.py:1260 core/models.py:1260
|
||||
#: build/lib/core/models.py:1263 core/models.py:1263
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to a document!"
|
||||
msgstr "¡{name} desea acceder a un documento!"
|
||||
|
||||
#: build/lib/core/models.py:1264 core/models.py:1264
|
||||
#: build/lib/core/models.py:1267 core/models.py:1267
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to the following document:"
|
||||
msgstr "{name} desea acceso al siguiente documento:"
|
||||
|
||||
#: build/lib/core/models.py:1270 core/models.py:1270
|
||||
#: build/lib/core/models.py:1273 core/models.py:1273
|
||||
#, python-brace-format
|
||||
msgid "{name} is asking for access to the document: {title}"
|
||||
msgstr "{name} está pidiendo acceso al documento: {title}"
|
||||
|
||||
#: build/lib/core/models.py:1282 core/models.py:1282
|
||||
#: build/lib/core/models.py:1285 core/models.py:1285
|
||||
msgid "description"
|
||||
msgstr "descripción"
|
||||
|
||||
#: build/lib/core/models.py:1283 core/models.py:1283
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
msgid "code"
|
||||
msgstr "código"
|
||||
|
||||
#: build/lib/core/models.py:1284 core/models.py:1284
|
||||
#: build/lib/core/models.py:1287 core/models.py:1287
|
||||
msgid "css"
|
||||
msgstr "css"
|
||||
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
#: build/lib/core/models.py:1289 core/models.py:1289
|
||||
msgid "public"
|
||||
msgstr "público"
|
||||
|
||||
#: build/lib/core/models.py:1288 core/models.py:1288
|
||||
#: build/lib/core/models.py:1291 core/models.py:1291
|
||||
msgid "Whether this template is public for anyone to use."
|
||||
msgstr "Si esta plantilla es pública para que cualquiera la utilice."
|
||||
|
||||
#: build/lib/core/models.py:1294 core/models.py:1294
|
||||
#: build/lib/core/models.py:1297 core/models.py:1297
|
||||
msgid "Template"
|
||||
msgstr "Plantilla"
|
||||
|
||||
#: build/lib/core/models.py:1295 core/models.py:1295
|
||||
#: build/lib/core/models.py:1298 core/models.py:1298
|
||||
msgid "Templates"
|
||||
msgstr "Plantillas"
|
||||
|
||||
#: build/lib/core/models.py:1348 core/models.py:1348
|
||||
#: build/lib/core/models.py:1351 core/models.py:1351
|
||||
msgid "Template/user relation"
|
||||
msgstr "Relación plantilla/usuario"
|
||||
|
||||
#: build/lib/core/models.py:1349 core/models.py:1349
|
||||
#: build/lib/core/models.py:1352 core/models.py:1352
|
||||
msgid "Template/user relations"
|
||||
msgstr "Relaciones plantilla/usuario"
|
||||
|
||||
#: build/lib/core/models.py:1355 core/models.py:1355
|
||||
#: build/lib/core/models.py:1358 core/models.py:1358
|
||||
msgid "This user is already in this template."
|
||||
msgstr "Este usuario ya forma parte de la plantilla."
|
||||
|
||||
#: build/lib/core/models.py:1361 core/models.py:1361
|
||||
#: build/lib/core/models.py:1364 core/models.py:1364
|
||||
msgid "This team is already in this template."
|
||||
msgstr "Este equipo ya se encuentra en esta plantilla."
|
||||
|
||||
#: build/lib/core/models.py:1438 core/models.py:1438
|
||||
#: build/lib/core/models.py:1441 core/models.py:1441
|
||||
msgid "email address"
|
||||
msgstr "dirección de correo electrónico"
|
||||
|
||||
#: build/lib/core/models.py:1457 core/models.py:1457
|
||||
#: build/lib/core/models.py:1460 core/models.py:1460
|
||||
msgid "Document invitation"
|
||||
msgstr "Invitación al documento"
|
||||
|
||||
#: build/lib/core/models.py:1458 core/models.py:1458
|
||||
#: build/lib/core/models.py:1461 core/models.py:1461
|
||||
msgid "Document invitations"
|
||||
msgstr "Invitaciones a documentos"
|
||||
|
||||
#: build/lib/core/models.py:1478 core/models.py:1478
|
||||
#: build/lib/core/models.py:1481 core/models.py:1481
|
||||
msgid "This email is already associated to a registered user."
|
||||
msgstr "Este correo electrónico está asociado a un usuario registrado."
|
||||
|
||||
#: core/templates/mail/html/template.html:162
|
||||
#: core/templates/mail/html/template.html:153
|
||||
#: core/templates/mail/text/template.txt:3
|
||||
msgid "Logo email"
|
||||
msgstr "Logo de correo electrónico"
|
||||
|
||||
#: core/templates/mail/html/template.html:209
|
||||
#: core/templates/mail/html/template.html:200
|
||||
#: core/templates/mail/text/template.txt:10
|
||||
msgid "Open"
|
||||
msgstr "Abrir"
|
||||
|
||||
#: core/templates/mail/html/template.html:226
|
||||
#: core/templates/mail/html/template.html:217
|
||||
#: core/templates/mail/text/template.txt:14
|
||||
msgid " Docs, your new essential tool for organizing, sharing and collaborating on your documents as a team. "
|
||||
msgstr "Docs, su nueva herramienta esencial para organizar, compartir y colaborar en sus documentos como equipo."
|
||||
|
||||
#: core/templates/mail/html/template.html:233
|
||||
#: core/templates/mail/html/template.html:224
|
||||
#: core/templates/mail/text/template.txt:16
|
||||
#, python-format
|
||||
msgid " Brought to you by %(brandname)s "
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: lasuite-docs\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-09-10 14:29+0000\n"
|
||||
"PO-Revision-Date: 2025-09-12 09:50\n"
|
||||
"POT-Creation-Date: 2025-10-23 11:01+0000\n"
|
||||
"PO-Revision-Date: 2025-11-10 09:54\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: French\n"
|
||||
"Language: fr_FR\n"
|
||||
@@ -17,20 +17,20 @@ msgstr ""
|
||||
"X-Crowdin-File: backend-impress.pot\n"
|
||||
"X-Crowdin-File-ID: 18\n"
|
||||
|
||||
#: build/lib/core/admin.py:37 core/admin.py:37
|
||||
#: build/lib/core/admin.py:36 core/admin.py:36
|
||||
msgid "Personal info"
|
||||
msgstr "Infos Personnelles"
|
||||
|
||||
#: build/lib/core/admin.py:50 build/lib/core/admin.py:138 core/admin.py:50
|
||||
#: core/admin.py:138
|
||||
#: build/lib/core/admin.py:49 build/lib/core/admin.py:137 core/admin.py:49
|
||||
#: core/admin.py:137
|
||||
msgid "Permissions"
|
||||
msgstr "Permissions"
|
||||
|
||||
#: build/lib/core/admin.py:62 core/admin.py:62
|
||||
#: build/lib/core/admin.py:61 core/admin.py:61
|
||||
msgid "Important dates"
|
||||
msgstr "Dates importantes"
|
||||
|
||||
#: build/lib/core/admin.py:148 core/admin.py:148
|
||||
#: build/lib/core/admin.py:147 core/admin.py:147
|
||||
msgid "Tree structure"
|
||||
msgstr "Arborescence"
|
||||
|
||||
@@ -50,27 +50,36 @@ msgstr "Masqué"
|
||||
msgid "Favorite"
|
||||
msgstr "Favoris"
|
||||
|
||||
#: build/lib/core/api/serializers.py:487 core/api/serializers.py:487
|
||||
#: build/lib/core/api/serializers.py:496 core/api/serializers.py:496
|
||||
msgid "A new document was created on your behalf!"
|
||||
msgstr "Un nouveau document a été créé pour vous !"
|
||||
|
||||
#: build/lib/core/api/serializers.py:491 core/api/serializers.py:491
|
||||
#: build/lib/core/api/serializers.py:500 core/api/serializers.py:500
|
||||
msgid "You have been granted ownership of a new document:"
|
||||
msgstr "Vous avez été déclaré propriétaire d'un nouveau document :"
|
||||
|
||||
#: build/lib/core/api/serializers.py:628 core/api/serializers.py:628
|
||||
#: build/lib/core/api/serializers.py:536 core/api/serializers.py:536
|
||||
msgid "This field is required."
|
||||
msgstr "Ce champ est obligatoire."
|
||||
|
||||
#: build/lib/core/api/serializers.py:547 core/api/serializers.py:547
|
||||
#, python-format
|
||||
msgid "Link reach '%(link_reach)s' is not allowed based on parent document configuration."
|
||||
msgstr "La portée du lien '%(link_reach)s' n'est pas autorisée en fonction de la configuration du document parent."
|
||||
|
||||
#: build/lib/core/api/serializers.py:693 core/api/serializers.py:693
|
||||
msgid "Body"
|
||||
msgstr "Corps"
|
||||
|
||||
#: build/lib/core/api/serializers.py:631 core/api/serializers.py:631
|
||||
#: build/lib/core/api/serializers.py:696 core/api/serializers.py:696
|
||||
msgid "Body type"
|
||||
msgstr "Type de corps"
|
||||
|
||||
#: build/lib/core/api/serializers.py:637 core/api/serializers.py:637
|
||||
#: build/lib/core/api/serializers.py:702 core/api/serializers.py:702
|
||||
msgid "Format"
|
||||
msgstr "Format"
|
||||
|
||||
#: build/lib/core/api/viewsets.py:965 core/api/viewsets.py:965
|
||||
#: build/lib/core/api/viewsets.py:1003 core/api/viewsets.py:1003
|
||||
#, python-brace-format
|
||||
msgid "copy of {title}"
|
||||
msgstr "copie de {title}"
|
||||
@@ -169,247 +178,247 @@ msgstr "Obligatoire. 255 caractères ou moins. Caractères ASCII uniquement."
|
||||
msgid "full name"
|
||||
msgstr "nom complet"
|
||||
|
||||
#: build/lib/core/models.py:151 core/models.py:151
|
||||
#: build/lib/core/models.py:152 core/models.py:152
|
||||
msgid "short name"
|
||||
msgstr "nom court"
|
||||
|
||||
#: build/lib/core/models.py:153 core/models.py:153
|
||||
#: build/lib/core/models.py:155 core/models.py:155
|
||||
msgid "identity email address"
|
||||
msgstr "adresse e-mail d'identité"
|
||||
|
||||
#: build/lib/core/models.py:158 core/models.py:158
|
||||
#: build/lib/core/models.py:160 core/models.py:160
|
||||
msgid "admin email address"
|
||||
msgstr "adresse e-mail de l'administrateur"
|
||||
|
||||
#: build/lib/core/models.py:165 core/models.py:165
|
||||
#: build/lib/core/models.py:167 core/models.py:167
|
||||
msgid "language"
|
||||
msgstr "langue"
|
||||
|
||||
#: build/lib/core/models.py:166 core/models.py:166
|
||||
#: build/lib/core/models.py:168 core/models.py:168
|
||||
msgid "The language in which the user wants to see the interface."
|
||||
msgstr "La langue dans laquelle l'utilisateur veut voir l'interface."
|
||||
|
||||
#: build/lib/core/models.py:174 core/models.py:174
|
||||
#: build/lib/core/models.py:176 core/models.py:176
|
||||
msgid "The timezone in which the user wants to see times."
|
||||
msgstr "Le fuseau horaire dans lequel l'utilisateur souhaite voir les heures."
|
||||
|
||||
#: build/lib/core/models.py:177 core/models.py:177
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
msgid "device"
|
||||
msgstr "appareil"
|
||||
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
#: build/lib/core/models.py:181 core/models.py:181
|
||||
msgid "Whether the user is a device or a real user."
|
||||
msgstr "Si l'utilisateur est un appareil ou un utilisateur réel."
|
||||
|
||||
#: build/lib/core/models.py:182 core/models.py:182
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
msgid "staff status"
|
||||
msgstr "statut d'équipe"
|
||||
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
#: build/lib/core/models.py:186 core/models.py:186
|
||||
msgid "Whether the user can log into this admin site."
|
||||
msgstr "Si l'utilisateur peut se connecter à ce site d'administration."
|
||||
|
||||
#: build/lib/core/models.py:187 core/models.py:187
|
||||
#: build/lib/core/models.py:189 core/models.py:189
|
||||
msgid "active"
|
||||
msgstr "actif"
|
||||
|
||||
#: build/lib/core/models.py:190 core/models.py:190
|
||||
#: build/lib/core/models.py:192 core/models.py:192
|
||||
msgid "Whether this user should be treated as active. Unselect this instead of deleting accounts."
|
||||
msgstr "Si cet utilisateur doit être traité comme actif. Désélectionnez ceci au lieu de supprimer des comptes."
|
||||
|
||||
#: build/lib/core/models.py:202 core/models.py:202
|
||||
#: build/lib/core/models.py:204 core/models.py:204
|
||||
msgid "user"
|
||||
msgstr "utilisateur"
|
||||
|
||||
#: build/lib/core/models.py:203 core/models.py:203
|
||||
#: build/lib/core/models.py:205 core/models.py:205
|
||||
msgid "users"
|
||||
msgstr "utilisateurs"
|
||||
|
||||
#: build/lib/core/models.py:359 build/lib/core/models.py:1281
|
||||
#: core/models.py:359 core/models.py:1281
|
||||
#: build/lib/core/models.py:361 build/lib/core/models.py:1284
|
||||
#: core/models.py:361 core/models.py:1284
|
||||
msgid "title"
|
||||
msgstr "titre"
|
||||
|
||||
#: build/lib/core/models.py:360 core/models.py:360
|
||||
#: build/lib/core/models.py:362 core/models.py:362
|
||||
msgid "excerpt"
|
||||
msgstr "extrait"
|
||||
|
||||
#: build/lib/core/models.py:409 core/models.py:409
|
||||
#: build/lib/core/models.py:411 core/models.py:411
|
||||
msgid "Document"
|
||||
msgstr "Document"
|
||||
|
||||
#: build/lib/core/models.py:410 core/models.py:410
|
||||
#: build/lib/core/models.py:412 core/models.py:412
|
||||
msgid "Documents"
|
||||
msgstr "Documents"
|
||||
|
||||
#: build/lib/core/models.py:422 build/lib/core/models.py:819 core/models.py:422
|
||||
#: core/models.py:819
|
||||
#: build/lib/core/models.py:424 build/lib/core/models.py:822 core/models.py:424
|
||||
#: core/models.py:822
|
||||
msgid "Untitled Document"
|
||||
msgstr "Document sans titre"
|
||||
|
||||
#: build/lib/core/models.py:854 core/models.py:854
|
||||
#: build/lib/core/models.py:857 core/models.py:857
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you!"
|
||||
msgstr "{name} a partagé un document avec vous!"
|
||||
|
||||
#: build/lib/core/models.py:858 core/models.py:858
|
||||
#: build/lib/core/models.py:861 core/models.py:861
|
||||
#, python-brace-format
|
||||
msgid "{name} invited you with the role \"{role}\" on the following document:"
|
||||
msgstr "{name} vous a invité avec le rôle \"{role}\" sur le document suivant :"
|
||||
|
||||
#: build/lib/core/models.py:864 core/models.py:864
|
||||
#: build/lib/core/models.py:867 core/models.py:867
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you: {title}"
|
||||
msgstr "{name} a partagé un document avec vous : {title}"
|
||||
|
||||
#: build/lib/core/models.py:964 core/models.py:964
|
||||
#: build/lib/core/models.py:967 core/models.py:967
|
||||
msgid "Document/user link trace"
|
||||
msgstr "Trace du lien document/utilisateur"
|
||||
|
||||
#: build/lib/core/models.py:965 core/models.py:965
|
||||
#: build/lib/core/models.py:968 core/models.py:968
|
||||
msgid "Document/user link traces"
|
||||
msgstr "Traces du lien document/utilisateur"
|
||||
|
||||
#: build/lib/core/models.py:971 core/models.py:971
|
||||
#: build/lib/core/models.py:974 core/models.py:974
|
||||
msgid "A link trace already exists for this document/user."
|
||||
msgstr "Une trace de lien existe déjà pour ce document/utilisateur."
|
||||
|
||||
#: build/lib/core/models.py:994 core/models.py:994
|
||||
#: build/lib/core/models.py:997 core/models.py:997
|
||||
msgid "Document favorite"
|
||||
msgstr "Document favori"
|
||||
|
||||
#: build/lib/core/models.py:995 core/models.py:995
|
||||
#: build/lib/core/models.py:998 core/models.py:998
|
||||
msgid "Document favorites"
|
||||
msgstr "Documents favoris"
|
||||
|
||||
#: build/lib/core/models.py:1001 core/models.py:1001
|
||||
#: build/lib/core/models.py:1004 core/models.py:1004
|
||||
msgid "This document is already targeted by a favorite relation instance for the same user."
|
||||
msgstr "Ce document est déjà un favori de cet utilisateur."
|
||||
|
||||
#: build/lib/core/models.py:1023 core/models.py:1023
|
||||
#: build/lib/core/models.py:1026 core/models.py:1026
|
||||
msgid "Document/user relation"
|
||||
msgstr "Relation document/utilisateur"
|
||||
|
||||
#: build/lib/core/models.py:1024 core/models.py:1024
|
||||
#: build/lib/core/models.py:1027 core/models.py:1027
|
||||
msgid "Document/user relations"
|
||||
msgstr "Relations document/utilisateur"
|
||||
|
||||
#: build/lib/core/models.py:1030 core/models.py:1030
|
||||
#: build/lib/core/models.py:1033 core/models.py:1033
|
||||
msgid "This user is already in this document."
|
||||
msgstr "Cet utilisateur est déjà dans ce document."
|
||||
|
||||
#: build/lib/core/models.py:1036 core/models.py:1036
|
||||
#: build/lib/core/models.py:1039 core/models.py:1039
|
||||
msgid "This team is already in this document."
|
||||
msgstr "Cette équipe est déjà dans ce document."
|
||||
|
||||
#: build/lib/core/models.py:1042 build/lib/core/models.py:1367
|
||||
#: core/models.py:1042 core/models.py:1367
|
||||
#: build/lib/core/models.py:1045 build/lib/core/models.py:1370
|
||||
#: core/models.py:1045 core/models.py:1370
|
||||
msgid "Either user or team must be set, not both."
|
||||
msgstr "L'utilisateur ou l'équipe doivent être définis, pas les deux."
|
||||
|
||||
#: build/lib/core/models.py:1188 core/models.py:1188
|
||||
#: build/lib/core/models.py:1191 core/models.py:1191
|
||||
msgid "Document ask for access"
|
||||
msgstr "Demande d'accès au document"
|
||||
|
||||
#: build/lib/core/models.py:1189 core/models.py:1189
|
||||
#: build/lib/core/models.py:1192 core/models.py:1192
|
||||
msgid "Document ask for accesses"
|
||||
msgstr "Demande d'accès au document"
|
||||
|
||||
#: build/lib/core/models.py:1195 core/models.py:1195
|
||||
#: build/lib/core/models.py:1198 core/models.py:1198
|
||||
msgid "This user has already asked for access to this document."
|
||||
msgstr "Cet utilisateur a déjà demandé l'accès à ce document."
|
||||
|
||||
#: build/lib/core/models.py:1260 core/models.py:1260
|
||||
#: build/lib/core/models.py:1263 core/models.py:1263
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to a document!"
|
||||
msgstr "{name} souhaiterait accéder au document suivant !"
|
||||
|
||||
#: build/lib/core/models.py:1264 core/models.py:1264
|
||||
#: build/lib/core/models.py:1267 core/models.py:1267
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to the following document:"
|
||||
msgstr "{name} souhaiterait accéder au document suivant :"
|
||||
|
||||
#: build/lib/core/models.py:1270 core/models.py:1270
|
||||
#: build/lib/core/models.py:1273 core/models.py:1273
|
||||
#, python-brace-format
|
||||
msgid "{name} is asking for access to the document: {title}"
|
||||
msgstr "{name} demande l'accès au document : {title}"
|
||||
|
||||
#: build/lib/core/models.py:1282 core/models.py:1282
|
||||
#: build/lib/core/models.py:1285 core/models.py:1285
|
||||
msgid "description"
|
||||
msgstr "description"
|
||||
|
||||
#: build/lib/core/models.py:1283 core/models.py:1283
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
msgid "code"
|
||||
msgstr "code"
|
||||
|
||||
#: build/lib/core/models.py:1284 core/models.py:1284
|
||||
#: build/lib/core/models.py:1287 core/models.py:1287
|
||||
msgid "css"
|
||||
msgstr "CSS"
|
||||
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
#: build/lib/core/models.py:1289 core/models.py:1289
|
||||
msgid "public"
|
||||
msgstr "public"
|
||||
|
||||
#: build/lib/core/models.py:1288 core/models.py:1288
|
||||
#: build/lib/core/models.py:1291 core/models.py:1291
|
||||
msgid "Whether this template is public for anyone to use."
|
||||
msgstr "Si ce modèle est public, utilisable par n'importe qui."
|
||||
|
||||
#: build/lib/core/models.py:1294 core/models.py:1294
|
||||
#: build/lib/core/models.py:1297 core/models.py:1297
|
||||
msgid "Template"
|
||||
msgstr "Modèle"
|
||||
|
||||
#: build/lib/core/models.py:1295 core/models.py:1295
|
||||
#: build/lib/core/models.py:1298 core/models.py:1298
|
||||
msgid "Templates"
|
||||
msgstr "Modèles"
|
||||
|
||||
#: build/lib/core/models.py:1348 core/models.py:1348
|
||||
#: build/lib/core/models.py:1351 core/models.py:1351
|
||||
msgid "Template/user relation"
|
||||
msgstr "Relation modèle/utilisateur"
|
||||
|
||||
#: build/lib/core/models.py:1349 core/models.py:1349
|
||||
#: build/lib/core/models.py:1352 core/models.py:1352
|
||||
msgid "Template/user relations"
|
||||
msgstr "Relations modèle/utilisateur"
|
||||
|
||||
#: build/lib/core/models.py:1355 core/models.py:1355
|
||||
#: build/lib/core/models.py:1358 core/models.py:1358
|
||||
msgid "This user is already in this template."
|
||||
msgstr "Cet utilisateur est déjà dans ce modèle."
|
||||
|
||||
#: build/lib/core/models.py:1361 core/models.py:1361
|
||||
#: build/lib/core/models.py:1364 core/models.py:1364
|
||||
msgid "This team is already in this template."
|
||||
msgstr "Cette équipe est déjà modèle."
|
||||
|
||||
#: build/lib/core/models.py:1438 core/models.py:1438
|
||||
#: build/lib/core/models.py:1441 core/models.py:1441
|
||||
msgid "email address"
|
||||
msgstr "adresse e-mail"
|
||||
|
||||
#: build/lib/core/models.py:1457 core/models.py:1457
|
||||
#: build/lib/core/models.py:1460 core/models.py:1460
|
||||
msgid "Document invitation"
|
||||
msgstr "Invitation à un document"
|
||||
|
||||
#: build/lib/core/models.py:1458 core/models.py:1458
|
||||
#: build/lib/core/models.py:1461 core/models.py:1461
|
||||
msgid "Document invitations"
|
||||
msgstr "Invitations à un document"
|
||||
|
||||
#: build/lib/core/models.py:1478 core/models.py:1478
|
||||
#: build/lib/core/models.py:1481 core/models.py:1481
|
||||
msgid "This email is already associated to a registered user."
|
||||
msgstr "Cette adresse email est déjà associée à un utilisateur inscrit."
|
||||
|
||||
#: core/templates/mail/html/template.html:162
|
||||
#: core/templates/mail/html/template.html:153
|
||||
#: core/templates/mail/text/template.txt:3
|
||||
msgid "Logo email"
|
||||
msgstr "Logo de l'e-mail"
|
||||
|
||||
#: core/templates/mail/html/template.html:209
|
||||
#: core/templates/mail/html/template.html:200
|
||||
#: core/templates/mail/text/template.txt:10
|
||||
msgid "Open"
|
||||
msgstr "Ouvrir"
|
||||
|
||||
#: core/templates/mail/html/template.html:226
|
||||
#: core/templates/mail/html/template.html:217
|
||||
#: core/templates/mail/text/template.txt:14
|
||||
msgid " Docs, your new essential tool for organizing, sharing and collaborating on your documents as a team. "
|
||||
msgstr " Docs, votre nouvel outil incontournable pour organiser, partager et collaborer sur vos documents en équipe. "
|
||||
|
||||
#: core/templates/mail/html/template.html:233
|
||||
#: core/templates/mail/html/template.html:224
|
||||
#: core/templates/mail/text/template.txt:16
|
||||
#, python-format
|
||||
msgid " Brought to you by %(brandname)s "
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: lasuite-docs\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-09-10 14:29+0000\n"
|
||||
"PO-Revision-Date: 2025-09-12 09:50\n"
|
||||
"POT-Creation-Date: 2025-10-23 11:01+0000\n"
|
||||
"PO-Revision-Date: 2025-11-10 09:54\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Italian\n"
|
||||
"Language: it_IT\n"
|
||||
@@ -17,20 +17,20 @@ msgstr ""
|
||||
"X-Crowdin-File: backend-impress.pot\n"
|
||||
"X-Crowdin-File-ID: 18\n"
|
||||
|
||||
#: build/lib/core/admin.py:37 core/admin.py:37
|
||||
#: build/lib/core/admin.py:36 core/admin.py:36
|
||||
msgid "Personal info"
|
||||
msgstr "Informazioni personali"
|
||||
|
||||
#: build/lib/core/admin.py:50 build/lib/core/admin.py:138 core/admin.py:50
|
||||
#: core/admin.py:138
|
||||
#: build/lib/core/admin.py:49 build/lib/core/admin.py:137 core/admin.py:49
|
||||
#: core/admin.py:137
|
||||
msgid "Permissions"
|
||||
msgstr "Permessi"
|
||||
|
||||
#: build/lib/core/admin.py:62 core/admin.py:62
|
||||
#: build/lib/core/admin.py:61 core/admin.py:61
|
||||
msgid "Important dates"
|
||||
msgstr "Date importanti"
|
||||
|
||||
#: build/lib/core/admin.py:148 core/admin.py:148
|
||||
#: build/lib/core/admin.py:147 core/admin.py:147
|
||||
msgid "Tree structure"
|
||||
msgstr "Struttura ad albero"
|
||||
|
||||
@@ -50,27 +50,36 @@ msgstr ""
|
||||
msgid "Favorite"
|
||||
msgstr "Preferiti"
|
||||
|
||||
#: build/lib/core/api/serializers.py:487 core/api/serializers.py:487
|
||||
#: build/lib/core/api/serializers.py:496 core/api/serializers.py:496
|
||||
msgid "A new document was created on your behalf!"
|
||||
msgstr "Un nuovo documento è stato creato a tuo nome!"
|
||||
|
||||
#: build/lib/core/api/serializers.py:491 core/api/serializers.py:491
|
||||
#: build/lib/core/api/serializers.py:500 core/api/serializers.py:500
|
||||
msgid "You have been granted ownership of a new document:"
|
||||
msgstr "Sei ora proprietario di un nuovo documento:"
|
||||
|
||||
#: build/lib/core/api/serializers.py:628 core/api/serializers.py:628
|
||||
#: build/lib/core/api/serializers.py:536 core/api/serializers.py:536
|
||||
msgid "This field is required."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:547 core/api/serializers.py:547
|
||||
#, python-format
|
||||
msgid "Link reach '%(link_reach)s' is not allowed based on parent document configuration."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:693 core/api/serializers.py:693
|
||||
msgid "Body"
|
||||
msgstr "Corpo"
|
||||
|
||||
#: build/lib/core/api/serializers.py:631 core/api/serializers.py:631
|
||||
#: build/lib/core/api/serializers.py:696 core/api/serializers.py:696
|
||||
msgid "Body type"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:637 core/api/serializers.py:637
|
||||
#: build/lib/core/api/serializers.py:702 core/api/serializers.py:702
|
||||
msgid "Format"
|
||||
msgstr "Formato"
|
||||
|
||||
#: build/lib/core/api/viewsets.py:965 core/api/viewsets.py:965
|
||||
#: build/lib/core/api/viewsets.py:1003 core/api/viewsets.py:1003
|
||||
#, python-brace-format
|
||||
msgid "copy of {title}"
|
||||
msgstr "copia di {title}"
|
||||
@@ -169,247 +178,247 @@ msgstr ""
|
||||
msgid "full name"
|
||||
msgstr "nome completo"
|
||||
|
||||
#: build/lib/core/models.py:151 core/models.py:151
|
||||
#: build/lib/core/models.py:152 core/models.py:152
|
||||
msgid "short name"
|
||||
msgstr "nome"
|
||||
|
||||
#: build/lib/core/models.py:153 core/models.py:153
|
||||
#: build/lib/core/models.py:155 core/models.py:155
|
||||
msgid "identity email address"
|
||||
msgstr "indirizzo email di identità"
|
||||
|
||||
#: build/lib/core/models.py:158 core/models.py:158
|
||||
#: build/lib/core/models.py:160 core/models.py:160
|
||||
msgid "admin email address"
|
||||
msgstr "Indirizzo email dell'amministratore"
|
||||
|
||||
#: build/lib/core/models.py:165 core/models.py:165
|
||||
#: build/lib/core/models.py:167 core/models.py:167
|
||||
msgid "language"
|
||||
msgstr "lingua"
|
||||
|
||||
#: build/lib/core/models.py:166 core/models.py:166
|
||||
#: build/lib/core/models.py:168 core/models.py:168
|
||||
msgid "The language in which the user wants to see the interface."
|
||||
msgstr "La lingua in cui l'utente vuole vedere l'interfaccia."
|
||||
|
||||
#: build/lib/core/models.py:174 core/models.py:174
|
||||
#: build/lib/core/models.py:176 core/models.py:176
|
||||
msgid "The timezone in which the user wants to see times."
|
||||
msgstr "Il fuso orario in cui l'utente vuole vedere gli orari."
|
||||
|
||||
#: build/lib/core/models.py:177 core/models.py:177
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
msgid "device"
|
||||
msgstr "dispositivo"
|
||||
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
#: build/lib/core/models.py:181 core/models.py:181
|
||||
msgid "Whether the user is a device or a real user."
|
||||
msgstr "Se l'utente è un dispositivo o un utente reale."
|
||||
|
||||
#: build/lib/core/models.py:182 core/models.py:182
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
msgid "staff status"
|
||||
msgstr "stato del personale"
|
||||
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
#: build/lib/core/models.py:186 core/models.py:186
|
||||
msgid "Whether the user can log into this admin site."
|
||||
msgstr "Indica se l'utente può accedere a questo sito amministratore."
|
||||
|
||||
#: build/lib/core/models.py:187 core/models.py:187
|
||||
#: build/lib/core/models.py:189 core/models.py:189
|
||||
msgid "active"
|
||||
msgstr "attivo"
|
||||
|
||||
#: build/lib/core/models.py:190 core/models.py:190
|
||||
#: build/lib/core/models.py:192 core/models.py:192
|
||||
msgid "Whether this user should be treated as active. Unselect this instead of deleting accounts."
|
||||
msgstr "Indica se questo utente deve essere trattato come attivo. Deseleziona invece di eliminare gli account."
|
||||
|
||||
#: build/lib/core/models.py:202 core/models.py:202
|
||||
#: build/lib/core/models.py:204 core/models.py:204
|
||||
msgid "user"
|
||||
msgstr "utente"
|
||||
|
||||
#: build/lib/core/models.py:203 core/models.py:203
|
||||
#: build/lib/core/models.py:205 core/models.py:205
|
||||
msgid "users"
|
||||
msgstr "utenti"
|
||||
|
||||
#: build/lib/core/models.py:359 build/lib/core/models.py:1281
|
||||
#: core/models.py:359 core/models.py:1281
|
||||
#: build/lib/core/models.py:361 build/lib/core/models.py:1284
|
||||
#: core/models.py:361 core/models.py:1284
|
||||
msgid "title"
|
||||
msgstr "titolo"
|
||||
|
||||
#: build/lib/core/models.py:360 core/models.py:360
|
||||
#: build/lib/core/models.py:362 core/models.py:362
|
||||
msgid "excerpt"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:409 core/models.py:409
|
||||
#: build/lib/core/models.py:411 core/models.py:411
|
||||
msgid "Document"
|
||||
msgstr "Documento"
|
||||
|
||||
#: build/lib/core/models.py:410 core/models.py:410
|
||||
#: build/lib/core/models.py:412 core/models.py:412
|
||||
msgid "Documents"
|
||||
msgstr "Documenti"
|
||||
|
||||
#: build/lib/core/models.py:422 build/lib/core/models.py:819 core/models.py:422
|
||||
#: core/models.py:819
|
||||
#: build/lib/core/models.py:424 build/lib/core/models.py:822 core/models.py:424
|
||||
#: core/models.py:822
|
||||
msgid "Untitled Document"
|
||||
msgstr "Documento senza titolo"
|
||||
|
||||
#: build/lib/core/models.py:854 core/models.py:854
|
||||
#: build/lib/core/models.py:857 core/models.py:857
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you!"
|
||||
msgstr "{name} ha condiviso un documento con te!"
|
||||
|
||||
#: build/lib/core/models.py:858 core/models.py:858
|
||||
#: build/lib/core/models.py:861 core/models.py:861
|
||||
#, python-brace-format
|
||||
msgid "{name} invited you with the role \"{role}\" on the following document:"
|
||||
msgstr "{name} ti ha invitato con il ruolo \"{role}\" nel seguente documento:"
|
||||
|
||||
#: build/lib/core/models.py:864 core/models.py:864
|
||||
#: build/lib/core/models.py:867 core/models.py:867
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you: {title}"
|
||||
msgstr "{name} ha condiviso un documento con te: {title}"
|
||||
|
||||
#: build/lib/core/models.py:964 core/models.py:964
|
||||
#: build/lib/core/models.py:967 core/models.py:967
|
||||
msgid "Document/user link trace"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:965 core/models.py:965
|
||||
#: build/lib/core/models.py:968 core/models.py:968
|
||||
msgid "Document/user link traces"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:971 core/models.py:971
|
||||
#: build/lib/core/models.py:974 core/models.py:974
|
||||
msgid "A link trace already exists for this document/user."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:994 core/models.py:994
|
||||
#: build/lib/core/models.py:997 core/models.py:997
|
||||
msgid "Document favorite"
|
||||
msgstr "Documento preferito"
|
||||
|
||||
#: build/lib/core/models.py:995 core/models.py:995
|
||||
#: build/lib/core/models.py:998 core/models.py:998
|
||||
msgid "Document favorites"
|
||||
msgstr "Documenti preferiti"
|
||||
|
||||
#: build/lib/core/models.py:1001 core/models.py:1001
|
||||
#: build/lib/core/models.py:1004 core/models.py:1004
|
||||
msgid "This document is already targeted by a favorite relation instance for the same user."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1023 core/models.py:1023
|
||||
#: build/lib/core/models.py:1026 core/models.py:1026
|
||||
msgid "Document/user relation"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1024 core/models.py:1024
|
||||
#: build/lib/core/models.py:1027 core/models.py:1027
|
||||
msgid "Document/user relations"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1030 core/models.py:1030
|
||||
#: build/lib/core/models.py:1033 core/models.py:1033
|
||||
msgid "This user is already in this document."
|
||||
msgstr "Questo utente è già presente in questo documento."
|
||||
|
||||
#: build/lib/core/models.py:1036 core/models.py:1036
|
||||
#: build/lib/core/models.py:1039 core/models.py:1039
|
||||
msgid "This team is already in this document."
|
||||
msgstr "Questo team è già presente in questo documento."
|
||||
|
||||
#: build/lib/core/models.py:1042 build/lib/core/models.py:1367
|
||||
#: core/models.py:1042 core/models.py:1367
|
||||
#: build/lib/core/models.py:1045 build/lib/core/models.py:1370
|
||||
#: core/models.py:1045 core/models.py:1370
|
||||
msgid "Either user or team must be set, not both."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1188 core/models.py:1188
|
||||
#: build/lib/core/models.py:1191 core/models.py:1191
|
||||
msgid "Document ask for access"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1189 core/models.py:1189
|
||||
#: build/lib/core/models.py:1192 core/models.py:1192
|
||||
msgid "Document ask for accesses"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1195 core/models.py:1195
|
||||
#: build/lib/core/models.py:1198 core/models.py:1198
|
||||
msgid "This user has already asked for access to this document."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1260 core/models.py:1260
|
||||
#: build/lib/core/models.py:1263 core/models.py:1263
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to a document!"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1264 core/models.py:1264
|
||||
#: build/lib/core/models.py:1267 core/models.py:1267
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to the following document:"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1270 core/models.py:1270
|
||||
#: build/lib/core/models.py:1273 core/models.py:1273
|
||||
#, python-brace-format
|
||||
msgid "{name} is asking for access to the document: {title}"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1282 core/models.py:1282
|
||||
#: build/lib/core/models.py:1285 core/models.py:1285
|
||||
msgid "description"
|
||||
msgstr "descrizione"
|
||||
|
||||
#: build/lib/core/models.py:1283 core/models.py:1283
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
msgid "code"
|
||||
msgstr "code"
|
||||
|
||||
#: build/lib/core/models.py:1284 core/models.py:1284
|
||||
#: build/lib/core/models.py:1287 core/models.py:1287
|
||||
msgid "css"
|
||||
msgstr "css"
|
||||
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
#: build/lib/core/models.py:1289 core/models.py:1289
|
||||
msgid "public"
|
||||
msgstr "pubblico"
|
||||
|
||||
#: build/lib/core/models.py:1288 core/models.py:1288
|
||||
#: build/lib/core/models.py:1291 core/models.py:1291
|
||||
msgid "Whether this template is public for anyone to use."
|
||||
msgstr "Indica se questo modello è pubblico per chiunque."
|
||||
|
||||
#: build/lib/core/models.py:1294 core/models.py:1294
|
||||
#: build/lib/core/models.py:1297 core/models.py:1297
|
||||
msgid "Template"
|
||||
msgstr "Modello"
|
||||
|
||||
#: build/lib/core/models.py:1295 core/models.py:1295
|
||||
#: build/lib/core/models.py:1298 core/models.py:1298
|
||||
msgid "Templates"
|
||||
msgstr "Modelli"
|
||||
|
||||
#: build/lib/core/models.py:1348 core/models.py:1348
|
||||
#: build/lib/core/models.py:1351 core/models.py:1351
|
||||
msgid "Template/user relation"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1349 core/models.py:1349
|
||||
#: build/lib/core/models.py:1352 core/models.py:1352
|
||||
msgid "Template/user relations"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1355 core/models.py:1355
|
||||
#: build/lib/core/models.py:1358 core/models.py:1358
|
||||
msgid "This user is already in this template."
|
||||
msgstr "Questo utente è già in questo modello."
|
||||
|
||||
#: build/lib/core/models.py:1361 core/models.py:1361
|
||||
#: build/lib/core/models.py:1364 core/models.py:1364
|
||||
msgid "This team is already in this template."
|
||||
msgstr "Questo team è già in questo modello."
|
||||
|
||||
#: build/lib/core/models.py:1438 core/models.py:1438
|
||||
#: build/lib/core/models.py:1441 core/models.py:1441
|
||||
msgid "email address"
|
||||
msgstr "indirizzo e-mail"
|
||||
|
||||
#: build/lib/core/models.py:1457 core/models.py:1457
|
||||
#: build/lib/core/models.py:1460 core/models.py:1460
|
||||
msgid "Document invitation"
|
||||
msgstr "Invito al documento"
|
||||
|
||||
#: build/lib/core/models.py:1458 core/models.py:1458
|
||||
#: build/lib/core/models.py:1461 core/models.py:1461
|
||||
msgid "Document invitations"
|
||||
msgstr "Inviti al documento"
|
||||
|
||||
#: build/lib/core/models.py:1478 core/models.py:1478
|
||||
#: build/lib/core/models.py:1481 core/models.py:1481
|
||||
msgid "This email is already associated to a registered user."
|
||||
msgstr "Questa email è già associata a un utente registrato."
|
||||
|
||||
#: core/templates/mail/html/template.html:162
|
||||
#: core/templates/mail/html/template.html:153
|
||||
#: core/templates/mail/text/template.txt:3
|
||||
msgid "Logo email"
|
||||
msgstr "Logo e-mail"
|
||||
|
||||
#: core/templates/mail/html/template.html:209
|
||||
#: core/templates/mail/html/template.html:200
|
||||
#: core/templates/mail/text/template.txt:10
|
||||
msgid "Open"
|
||||
msgstr "Apri"
|
||||
|
||||
#: core/templates/mail/html/template.html:226
|
||||
#: core/templates/mail/html/template.html:217
|
||||
#: core/templates/mail/text/template.txt:14
|
||||
msgid " Docs, your new essential tool for organizing, sharing and collaborating on your documents as a team. "
|
||||
msgstr ""
|
||||
|
||||
#: core/templates/mail/html/template.html:233
|
||||
#: core/templates/mail/html/template.html:224
|
||||
#: core/templates/mail/text/template.txt:16
|
||||
#, python-format
|
||||
msgid " Brought to you by %(brandname)s "
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: lasuite-docs\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-09-10 14:29+0000\n"
|
||||
"PO-Revision-Date: 2025-09-12 09:50\n"
|
||||
"POT-Creation-Date: 2025-10-23 11:01+0000\n"
|
||||
"PO-Revision-Date: 2025-11-10 09:54\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Dutch\n"
|
||||
"Language: nl_NL\n"
|
||||
@@ -17,22 +17,22 @@ msgstr ""
|
||||
"X-Crowdin-File: backend-impress.pot\n"
|
||||
"X-Crowdin-File-ID: 18\n"
|
||||
|
||||
#: build/lib/core/admin.py:37 core/admin.py:37
|
||||
#: build/lib/core/admin.py:36 core/admin.py:36
|
||||
msgid "Personal info"
|
||||
msgstr "Persoonlijke informatie"
|
||||
|
||||
#: build/lib/core/admin.py:50 build/lib/core/admin.py:138 core/admin.py:50
|
||||
#: core/admin.py:138
|
||||
#: build/lib/core/admin.py:49 build/lib/core/admin.py:137 core/admin.py:49
|
||||
#: core/admin.py:137
|
||||
msgid "Permissions"
|
||||
msgstr "Toestemmingen"
|
||||
msgstr "Machtigingen"
|
||||
|
||||
#: build/lib/core/admin.py:62 core/admin.py:62
|
||||
#: build/lib/core/admin.py:61 core/admin.py:61
|
||||
msgid "Important dates"
|
||||
msgstr "Belangrijke datums"
|
||||
msgstr "Belangrijke data"
|
||||
|
||||
#: build/lib/core/admin.py:148 core/admin.py:148
|
||||
#: build/lib/core/admin.py:147 core/admin.py:147
|
||||
msgid "Tree structure"
|
||||
msgstr "Document structuur"
|
||||
msgstr "Boomstructuur"
|
||||
|
||||
#: build/lib/core/api/filters.py:47 core/api/filters.py:47
|
||||
msgid "Title"
|
||||
@@ -40,37 +40,46 @@ msgstr "Titel"
|
||||
|
||||
#: build/lib/core/api/filters.py:61 core/api/filters.py:61
|
||||
msgid "Creator is me"
|
||||
msgstr "Ik ben Eigenaar"
|
||||
msgstr "Ik ben eigenaar"
|
||||
|
||||
#: build/lib/core/api/filters.py:64 core/api/filters.py:64
|
||||
msgid "Masked"
|
||||
msgstr ""
|
||||
msgstr "Gemaskeerd"
|
||||
|
||||
#: build/lib/core/api/filters.py:67 core/api/filters.py:67
|
||||
msgid "Favorite"
|
||||
msgstr "Favoriete"
|
||||
msgstr "Favoriet"
|
||||
|
||||
#: build/lib/core/api/serializers.py:487 core/api/serializers.py:487
|
||||
#: build/lib/core/api/serializers.py:496 core/api/serializers.py:496
|
||||
msgid "A new document was created on your behalf!"
|
||||
msgstr "Een nieuw document was gecreëerd voor u!"
|
||||
msgstr "Een nieuw document is namens u gemaakt!"
|
||||
|
||||
#: build/lib/core/api/serializers.py:491 core/api/serializers.py:491
|
||||
#: build/lib/core/api/serializers.py:500 core/api/serializers.py:500
|
||||
msgid "You have been granted ownership of a new document:"
|
||||
msgstr "U heeft eigenaarschap van een nieuw document:"
|
||||
msgstr "U heeft eigenaarschap van een nieuw document gekregen:"
|
||||
|
||||
#: build/lib/core/api/serializers.py:628 core/api/serializers.py:628
|
||||
#: build/lib/core/api/serializers.py:536 core/api/serializers.py:536
|
||||
msgid "This field is required."
|
||||
msgstr "Dit veld is verplicht."
|
||||
|
||||
#: build/lib/core/api/serializers.py:547 core/api/serializers.py:547
|
||||
#, python-format
|
||||
msgid "Link reach '%(link_reach)s' is not allowed based on parent document configuration."
|
||||
msgstr "Link bereik '%(link_reach)s' is niet toegestaan op basis van bovenliggende documentconfiguratie."
|
||||
|
||||
#: build/lib/core/api/serializers.py:693 core/api/serializers.py:693
|
||||
msgid "Body"
|
||||
msgstr "Text"
|
||||
|
||||
#: build/lib/core/api/serializers.py:631 core/api/serializers.py:631
|
||||
#: build/lib/core/api/serializers.py:696 core/api/serializers.py:696
|
||||
msgid "Body type"
|
||||
msgstr "Text type"
|
||||
|
||||
#: build/lib/core/api/serializers.py:637 core/api/serializers.py:637
|
||||
#: build/lib/core/api/serializers.py:702 core/api/serializers.py:702
|
||||
msgid "Format"
|
||||
msgstr "Formaat"
|
||||
|
||||
#: build/lib/core/api/viewsets.py:965 core/api/viewsets.py:965
|
||||
#: build/lib/core/api/viewsets.py:1003 core/api/viewsets.py:1003
|
||||
#, python-brace-format
|
||||
msgid "copy of {title}"
|
||||
msgstr "kopie van {title}"
|
||||
@@ -83,11 +92,11 @@ msgstr "Lezer"
|
||||
#: build/lib/core/choices.py:36 build/lib/core/choices.py:43 core/choices.py:36
|
||||
#: core/choices.py:43
|
||||
msgid "Editor"
|
||||
msgstr "Bewerker"
|
||||
msgstr "Redacteur"
|
||||
|
||||
#: build/lib/core/choices.py:44 core/choices.py:44
|
||||
msgid "Administrator"
|
||||
msgstr "Administrator"
|
||||
msgstr "Beheerder"
|
||||
|
||||
#: build/lib/core/choices.py:45 core/choices.py:45
|
||||
msgid "Owner"
|
||||
@@ -95,7 +104,7 @@ msgstr "Eigenaar"
|
||||
|
||||
#: build/lib/core/choices.py:56 core/choices.py:56
|
||||
msgid "Restricted"
|
||||
msgstr "Niet toegestaan"
|
||||
msgstr "Beperkt"
|
||||
|
||||
#: build/lib/core/choices.py:60 core/choices.py:60
|
||||
msgid "Authenticated"
|
||||
@@ -139,11 +148,11 @@ msgstr "primaire sleutel voor dossier als UUID"
|
||||
|
||||
#: build/lib/core/models.py:87 core/models.py:87
|
||||
msgid "created on"
|
||||
msgstr "gemaakt op"
|
||||
msgstr "gecreëerd op"
|
||||
|
||||
#: build/lib/core/models.py:88 core/models.py:88
|
||||
msgid "date and time at which a record was created"
|
||||
msgstr "datum en tijd wanneer dossier was gecreëerd"
|
||||
msgstr "datum en tijd waarop dossier is gecreeërd"
|
||||
|
||||
#: build/lib/core/models.py:93 core/models.py:93
|
||||
msgid "updated on"
|
||||
@@ -155,7 +164,7 @@ msgstr "datum en tijd waarop dossier laatst was gewijzigd"
|
||||
|
||||
#: build/lib/core/models.py:130 core/models.py:130
|
||||
msgid "We couldn't find a user with this sub but the email is already associated with a registered user."
|
||||
msgstr "Wij konden geen gebruiker vinden met deze id, maar de email is al geassocieerd met een geregistreerde gebruiker."
|
||||
msgstr "Wij konden geen gebruiker vinden met dit id, maar de email is al geassocieerd met een geregistreerde gebruiker."
|
||||
|
||||
#: build/lib/core/models.py:141 core/models.py:141
|
||||
msgid "sub"
|
||||
@@ -163,253 +172,253 @@ msgstr "id"
|
||||
|
||||
#: build/lib/core/models.py:142 core/models.py:142
|
||||
msgid "Required. 255 characters or fewer. ASCII characters only."
|
||||
msgstr ""
|
||||
msgstr "Vereist. 255 tekens of minder. Alleen ASCII tekens."
|
||||
|
||||
#: build/lib/core/models.py:150 core/models.py:150
|
||||
msgid "full name"
|
||||
msgstr "volledige naam"
|
||||
|
||||
#: build/lib/core/models.py:151 core/models.py:151
|
||||
#: build/lib/core/models.py:152 core/models.py:152
|
||||
msgid "short name"
|
||||
msgstr "gebruikersnaam"
|
||||
|
||||
#: build/lib/core/models.py:153 core/models.py:153
|
||||
#: build/lib/core/models.py:155 core/models.py:155
|
||||
msgid "identity email address"
|
||||
msgstr "identiteit email adres"
|
||||
msgstr "identiteit emailadres"
|
||||
|
||||
#: build/lib/core/models.py:158 core/models.py:158
|
||||
#: build/lib/core/models.py:160 core/models.py:160
|
||||
msgid "admin email address"
|
||||
msgstr "admin email adres"
|
||||
msgstr "admin emailadres"
|
||||
|
||||
#: build/lib/core/models.py:165 core/models.py:165
|
||||
#: build/lib/core/models.py:167 core/models.py:167
|
||||
msgid "language"
|
||||
msgstr "taal"
|
||||
|
||||
#: build/lib/core/models.py:166 core/models.py:166
|
||||
#: build/lib/core/models.py:168 core/models.py:168
|
||||
msgid "The language in which the user wants to see the interface."
|
||||
msgstr "De taal waarin de gebruiker de interface wilt zien."
|
||||
msgstr "De taal waarin de gebruiker de interface wil zien."
|
||||
|
||||
#: build/lib/core/models.py:174 core/models.py:174
|
||||
#: build/lib/core/models.py:176 core/models.py:176
|
||||
msgid "The timezone in which the user wants to see times."
|
||||
msgstr "De tijdzone waarin de gebruiker de tijden wilt zien."
|
||||
msgstr "De tijdzone waarin de gebruiker de tijden wil zien."
|
||||
|
||||
#: build/lib/core/models.py:177 core/models.py:177
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
msgid "device"
|
||||
msgstr "apparaat"
|
||||
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
#: build/lib/core/models.py:181 core/models.py:181
|
||||
msgid "Whether the user is a device or a real user."
|
||||
msgstr "Of de gebruiker een apparaat is of een echte gebruiker."
|
||||
|
||||
#: build/lib/core/models.py:182 core/models.py:182
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
msgid "staff status"
|
||||
msgstr "beheerder status"
|
||||
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
#: build/lib/core/models.py:186 core/models.py:186
|
||||
msgid "Whether the user can log into this admin site."
|
||||
msgstr "Of de gebruiker kan inloggen in het admin gedeelte."
|
||||
msgstr "Of de gebruiker kan inloggen in het beheer gedeelte."
|
||||
|
||||
#: build/lib/core/models.py:187 core/models.py:187
|
||||
#: build/lib/core/models.py:189 core/models.py:189
|
||||
msgid "active"
|
||||
msgstr "actief"
|
||||
|
||||
#: build/lib/core/models.py:190 core/models.py:190
|
||||
#: build/lib/core/models.py:192 core/models.py:192
|
||||
msgid "Whether this user should be treated as active. Unselect this instead of deleting accounts."
|
||||
msgstr "Of een gebruiker als actief moet worden beschouwd. Deselecteer dit in plaats van het account te deleten."
|
||||
|
||||
#: build/lib/core/models.py:202 core/models.py:202
|
||||
#: build/lib/core/models.py:204 core/models.py:204
|
||||
msgid "user"
|
||||
msgstr "gebruiker"
|
||||
|
||||
#: build/lib/core/models.py:203 core/models.py:203
|
||||
#: build/lib/core/models.py:205 core/models.py:205
|
||||
msgid "users"
|
||||
msgstr "gebruikers"
|
||||
|
||||
#: build/lib/core/models.py:359 build/lib/core/models.py:1281
|
||||
#: core/models.py:359 core/models.py:1281
|
||||
#: build/lib/core/models.py:361 build/lib/core/models.py:1284
|
||||
#: core/models.py:361 core/models.py:1284
|
||||
msgid "title"
|
||||
msgstr "titel"
|
||||
|
||||
#: build/lib/core/models.py:360 core/models.py:360
|
||||
#: build/lib/core/models.py:362 core/models.py:362
|
||||
msgid "excerpt"
|
||||
msgstr "uittreksel"
|
||||
|
||||
#: build/lib/core/models.py:409 core/models.py:409
|
||||
#: build/lib/core/models.py:411 core/models.py:411
|
||||
msgid "Document"
|
||||
msgstr "Document"
|
||||
|
||||
#: build/lib/core/models.py:410 core/models.py:410
|
||||
#: build/lib/core/models.py:412 core/models.py:412
|
||||
msgid "Documents"
|
||||
msgstr "Documenten"
|
||||
|
||||
#: build/lib/core/models.py:422 build/lib/core/models.py:819 core/models.py:422
|
||||
#: core/models.py:819
|
||||
#: build/lib/core/models.py:424 build/lib/core/models.py:822 core/models.py:424
|
||||
#: core/models.py:822
|
||||
msgid "Untitled Document"
|
||||
msgstr "Naamloos Document"
|
||||
|
||||
#: build/lib/core/models.py:854 core/models.py:854
|
||||
#: build/lib/core/models.py:857 core/models.py:857
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you!"
|
||||
msgstr "{name} heeft een document met gedeeld!"
|
||||
msgstr "{name} heeft een document met u gedeeld!"
|
||||
|
||||
#: build/lib/core/models.py:858 core/models.py:858
|
||||
#: build/lib/core/models.py:861 core/models.py:861
|
||||
#, python-brace-format
|
||||
msgid "{name} invited you with the role \"{role}\" on the following document:"
|
||||
msgstr "{name} heeft u uitgenodigd met de rol \"{role}\" op het volgende document:"
|
||||
|
||||
#: build/lib/core/models.py:864 core/models.py:864
|
||||
#: build/lib/core/models.py:867 core/models.py:867
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you: {title}"
|
||||
msgstr "{name} heeft een document met u gedeeld: {title}"
|
||||
|
||||
#: build/lib/core/models.py:964 core/models.py:964
|
||||
#: build/lib/core/models.py:967 core/models.py:967
|
||||
msgid "Document/user link trace"
|
||||
msgstr "Document/gebruiker url"
|
||||
msgstr "Document/gebruiker link"
|
||||
|
||||
#: build/lib/core/models.py:965 core/models.py:965
|
||||
#: build/lib/core/models.py:968 core/models.py:968
|
||||
msgid "Document/user link traces"
|
||||
msgstr "Document/gebruiker url"
|
||||
msgstr "Document/gebruiker link"
|
||||
|
||||
#: build/lib/core/models.py:971 core/models.py:971
|
||||
#: build/lib/core/models.py:974 core/models.py:974
|
||||
msgid "A link trace already exists for this document/user."
|
||||
msgstr "Een url bestaat al voor dit document/deze gebruiker."
|
||||
msgstr "Een link bestaat al voor dit document/deze gebruiker."
|
||||
|
||||
#: build/lib/core/models.py:994 core/models.py:994
|
||||
#: build/lib/core/models.py:997 core/models.py:997
|
||||
msgid "Document favorite"
|
||||
msgstr "Document favoriet"
|
||||
|
||||
#: build/lib/core/models.py:995 core/models.py:995
|
||||
#: build/lib/core/models.py:998 core/models.py:998
|
||||
msgid "Document favorites"
|
||||
msgstr "Document favorieten"
|
||||
|
||||
#: build/lib/core/models.py:1001 core/models.py:1001
|
||||
#: build/lib/core/models.py:1004 core/models.py:1004
|
||||
msgid "This document is already targeted by a favorite relation instance for the same user."
|
||||
msgstr "Dit document is al in gebruik als favoriete door dezelfde gebruiker."
|
||||
msgstr "Dit document is al in gebruik als favoriet door dezelfde gebruiker."
|
||||
|
||||
#: build/lib/core/models.py:1023 core/models.py:1023
|
||||
#: build/lib/core/models.py:1026 core/models.py:1026
|
||||
msgid "Document/user relation"
|
||||
msgstr "Document/gebruiker relatie"
|
||||
|
||||
#: build/lib/core/models.py:1024 core/models.py:1024
|
||||
#: build/lib/core/models.py:1027 core/models.py:1027
|
||||
msgid "Document/user relations"
|
||||
msgstr "Document/gebruiker relaties"
|
||||
|
||||
#: build/lib/core/models.py:1030 core/models.py:1030
|
||||
#: build/lib/core/models.py:1033 core/models.py:1033
|
||||
msgid "This user is already in this document."
|
||||
msgstr "De gebruiker is al in dit document."
|
||||
msgstr "De gebruiker bestaat al in dit document."
|
||||
|
||||
#: build/lib/core/models.py:1036 core/models.py:1036
|
||||
#: build/lib/core/models.py:1039 core/models.py:1039
|
||||
msgid "This team is already in this document."
|
||||
msgstr "Het team is al in dit document."
|
||||
msgstr "Dit team bestaat al in dit document."
|
||||
|
||||
#: build/lib/core/models.py:1042 build/lib/core/models.py:1367
|
||||
#: core/models.py:1042 core/models.py:1367
|
||||
#: build/lib/core/models.py:1045 build/lib/core/models.py:1370
|
||||
#: core/models.py:1045 core/models.py:1370
|
||||
msgid "Either user or team must be set, not both."
|
||||
msgstr "Een gebruiker of team moet gekozen worden, maar niet beide."
|
||||
|
||||
#: build/lib/core/models.py:1188 core/models.py:1188
|
||||
#: build/lib/core/models.py:1191 core/models.py:1191
|
||||
msgid "Document ask for access"
|
||||
msgstr ""
|
||||
msgstr "Document verzoekt om toegang"
|
||||
|
||||
#: build/lib/core/models.py:1189 core/models.py:1189
|
||||
#: build/lib/core/models.py:1192 core/models.py:1192
|
||||
msgid "Document ask for accesses"
|
||||
msgstr ""
|
||||
msgstr "Document verzoekt om toegangen"
|
||||
|
||||
#: build/lib/core/models.py:1195 core/models.py:1195
|
||||
#: build/lib/core/models.py:1198 core/models.py:1198
|
||||
msgid "This user has already asked for access to this document."
|
||||
msgstr ""
|
||||
msgstr "Deze gebruiker heeft al om toegang tot dit document gevraagd."
|
||||
|
||||
#: build/lib/core/models.py:1260 core/models.py:1260
|
||||
#: build/lib/core/models.py:1263 core/models.py:1263
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to a document!"
|
||||
msgstr ""
|
||||
msgstr "{name} verzoekt toegang tot een document!"
|
||||
|
||||
#: build/lib/core/models.py:1264 core/models.py:1264
|
||||
#: build/lib/core/models.py:1267 core/models.py:1267
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to the following document:"
|
||||
msgstr ""
|
||||
msgstr "{name} verzoekt toegang tot het volgende document:"
|
||||
|
||||
#: build/lib/core/models.py:1270 core/models.py:1270
|
||||
#: build/lib/core/models.py:1273 core/models.py:1273
|
||||
#, python-brace-format
|
||||
msgid "{name} is asking for access to the document: {title}"
|
||||
msgstr ""
|
||||
msgstr "{name} verzoekt toegang tot het document: {title}"
|
||||
|
||||
#: build/lib/core/models.py:1282 core/models.py:1282
|
||||
#: build/lib/core/models.py:1285 core/models.py:1285
|
||||
msgid "description"
|
||||
msgstr "omschrijving"
|
||||
|
||||
#: build/lib/core/models.py:1283 core/models.py:1283
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
msgid "code"
|
||||
msgstr "code"
|
||||
|
||||
#: build/lib/core/models.py:1284 core/models.py:1284
|
||||
#: build/lib/core/models.py:1287 core/models.py:1287
|
||||
msgid "css"
|
||||
msgstr "css"
|
||||
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
#: build/lib/core/models.py:1289 core/models.py:1289
|
||||
msgid "public"
|
||||
msgstr "publiek"
|
||||
|
||||
#: build/lib/core/models.py:1288 core/models.py:1288
|
||||
#: build/lib/core/models.py:1291 core/models.py:1291
|
||||
msgid "Whether this template is public for anyone to use."
|
||||
msgstr "Of dit template als publiek is en door iedereen te gebruiken is."
|
||||
msgstr "Of dit sjabloon door iedereen publiekelijk te gebruiken is."
|
||||
|
||||
#: build/lib/core/models.py:1294 core/models.py:1294
|
||||
#: build/lib/core/models.py:1297 core/models.py:1297
|
||||
msgid "Template"
|
||||
msgstr "Template"
|
||||
msgstr "Sjabloon"
|
||||
|
||||
#: build/lib/core/models.py:1295 core/models.py:1295
|
||||
#: build/lib/core/models.py:1298 core/models.py:1298
|
||||
msgid "Templates"
|
||||
msgstr "Templates"
|
||||
msgstr "Sjabloon"
|
||||
|
||||
#: build/lib/core/models.py:1348 core/models.py:1348
|
||||
#: build/lib/core/models.py:1351 core/models.py:1351
|
||||
msgid "Template/user relation"
|
||||
msgstr "Template/gebruiker relatie"
|
||||
msgstr "Sjabloon/gebruiker relatie"
|
||||
|
||||
#: build/lib/core/models.py:1349 core/models.py:1349
|
||||
#: build/lib/core/models.py:1352 core/models.py:1352
|
||||
msgid "Template/user relations"
|
||||
msgstr "Template/gebruiker relaties"
|
||||
msgstr "Sjabloon/gebruiker relaties"
|
||||
|
||||
#: build/lib/core/models.py:1355 core/models.py:1355
|
||||
#: build/lib/core/models.py:1358 core/models.py:1358
|
||||
msgid "This user is already in this template."
|
||||
msgstr "De gebruiker bestaat al in dit template."
|
||||
msgstr "De gebruiker bestaat al in dit sjabloon."
|
||||
|
||||
#: build/lib/core/models.py:1361 core/models.py:1361
|
||||
#: build/lib/core/models.py:1364 core/models.py:1364
|
||||
msgid "This team is already in this template."
|
||||
msgstr "Het team bestaat al in dit template."
|
||||
msgstr "Het team bestaat al in dit sjabloon."
|
||||
|
||||
#: build/lib/core/models.py:1438 core/models.py:1438
|
||||
#: build/lib/core/models.py:1441 core/models.py:1441
|
||||
msgid "email address"
|
||||
msgstr "email adres"
|
||||
msgstr "e-mailadres"
|
||||
|
||||
#: build/lib/core/models.py:1457 core/models.py:1457
|
||||
#: build/lib/core/models.py:1460 core/models.py:1460
|
||||
msgid "Document invitation"
|
||||
msgstr "Document uitnodiging"
|
||||
|
||||
#: build/lib/core/models.py:1458 core/models.py:1458
|
||||
#: build/lib/core/models.py:1461 core/models.py:1461
|
||||
msgid "Document invitations"
|
||||
msgstr "Document uitnodigingen"
|
||||
|
||||
#: build/lib/core/models.py:1478 core/models.py:1478
|
||||
#: build/lib/core/models.py:1481 core/models.py:1481
|
||||
msgid "This email is already associated to a registered user."
|
||||
msgstr "Deze email is al geassocieerd met een geregistreerde gebruiker."
|
||||
|
||||
#: core/templates/mail/html/template.html:162
|
||||
#: core/templates/mail/html/template.html:153
|
||||
#: core/templates/mail/text/template.txt:3
|
||||
msgid "Logo email"
|
||||
msgstr "Logo email"
|
||||
|
||||
#: core/templates/mail/html/template.html:209
|
||||
#: core/templates/mail/html/template.html:200
|
||||
#: core/templates/mail/text/template.txt:10
|
||||
msgid "Open"
|
||||
msgstr "Open"
|
||||
|
||||
#: core/templates/mail/html/template.html:226
|
||||
#: core/templates/mail/html/template.html:217
|
||||
#: core/templates/mail/text/template.txt:14
|
||||
msgid " Docs, your new essential tool for organizing, sharing and collaborating on your documents as a team. "
|
||||
msgstr " Docs, jouw nieuwe essentiële tool voor het organiseren, delen en collaboreren van documenten als team. "
|
||||
|
||||
#: core/templates/mail/html/template.html:233
|
||||
#: core/templates/mail/html/template.html:224
|
||||
#: core/templates/mail/text/template.txt:16
|
||||
#, python-format
|
||||
msgid " Brought to you by %(brandname)s "
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: lasuite-docs\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-09-10 14:29+0000\n"
|
||||
"PO-Revision-Date: 2025-09-12 09:50\n"
|
||||
"POT-Creation-Date: 2025-10-23 11:01+0000\n"
|
||||
"PO-Revision-Date: 2025-11-10 09:54\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Portuguese\n"
|
||||
"Language: pt_PT\n"
|
||||
@@ -17,20 +17,20 @@ msgstr ""
|
||||
"X-Crowdin-File: backend-impress.pot\n"
|
||||
"X-Crowdin-File-ID: 18\n"
|
||||
|
||||
#: build/lib/core/admin.py:37 core/admin.py:37
|
||||
#: build/lib/core/admin.py:36 core/admin.py:36
|
||||
msgid "Personal info"
|
||||
msgstr "Informações Pessoais"
|
||||
|
||||
#: build/lib/core/admin.py:50 build/lib/core/admin.py:138 core/admin.py:50
|
||||
#: core/admin.py:138
|
||||
#: build/lib/core/admin.py:49 build/lib/core/admin.py:137 core/admin.py:49
|
||||
#: core/admin.py:137
|
||||
msgid "Permissions"
|
||||
msgstr "Permissões"
|
||||
|
||||
#: build/lib/core/admin.py:62 core/admin.py:62
|
||||
#: build/lib/core/admin.py:61 core/admin.py:61
|
||||
msgid "Important dates"
|
||||
msgstr "Datas importantes"
|
||||
|
||||
#: build/lib/core/admin.py:148 core/admin.py:148
|
||||
#: build/lib/core/admin.py:147 core/admin.py:147
|
||||
msgid "Tree structure"
|
||||
msgstr "Estrutura de árvore"
|
||||
|
||||
@@ -50,27 +50,36 @@ msgstr ""
|
||||
msgid "Favorite"
|
||||
msgstr "Favorito"
|
||||
|
||||
#: build/lib/core/api/serializers.py:487 core/api/serializers.py:487
|
||||
#: build/lib/core/api/serializers.py:496 core/api/serializers.py:496
|
||||
msgid "A new document was created on your behalf!"
|
||||
msgstr "Um novo documento foi criado em seu nome!"
|
||||
|
||||
#: build/lib/core/api/serializers.py:491 core/api/serializers.py:491
|
||||
#: build/lib/core/api/serializers.py:500 core/api/serializers.py:500
|
||||
msgid "You have been granted ownership of a new document:"
|
||||
msgstr "A propriedade de um novo documento foi concedida a você:"
|
||||
|
||||
#: build/lib/core/api/serializers.py:628 core/api/serializers.py:628
|
||||
#: build/lib/core/api/serializers.py:536 core/api/serializers.py:536
|
||||
msgid "This field is required."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:547 core/api/serializers.py:547
|
||||
#, python-format
|
||||
msgid "Link reach '%(link_reach)s' is not allowed based on parent document configuration."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:693 core/api/serializers.py:693
|
||||
msgid "Body"
|
||||
msgstr "Corpo"
|
||||
|
||||
#: build/lib/core/api/serializers.py:631 core/api/serializers.py:631
|
||||
#: build/lib/core/api/serializers.py:696 core/api/serializers.py:696
|
||||
msgid "Body type"
|
||||
msgstr "Tipo de corpo"
|
||||
|
||||
#: build/lib/core/api/serializers.py:637 core/api/serializers.py:637
|
||||
#: build/lib/core/api/serializers.py:702 core/api/serializers.py:702
|
||||
msgid "Format"
|
||||
msgstr "Formato"
|
||||
|
||||
#: build/lib/core/api/viewsets.py:965 core/api/viewsets.py:965
|
||||
#: build/lib/core/api/viewsets.py:1003 core/api/viewsets.py:1003
|
||||
#, python-brace-format
|
||||
msgid "copy of {title}"
|
||||
msgstr "cópia de {title}"
|
||||
@@ -169,247 +178,247 @@ msgstr ""
|
||||
msgid "full name"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:151 core/models.py:151
|
||||
#: build/lib/core/models.py:152 core/models.py:152
|
||||
msgid "short name"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:153 core/models.py:153
|
||||
#: build/lib/core/models.py:155 core/models.py:155
|
||||
msgid "identity email address"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:158 core/models.py:158
|
||||
#: build/lib/core/models.py:160 core/models.py:160
|
||||
msgid "admin email address"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:165 core/models.py:165
|
||||
#: build/lib/core/models.py:167 core/models.py:167
|
||||
msgid "language"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:166 core/models.py:166
|
||||
#: build/lib/core/models.py:168 core/models.py:168
|
||||
msgid "The language in which the user wants to see the interface."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:174 core/models.py:174
|
||||
#: build/lib/core/models.py:176 core/models.py:176
|
||||
msgid "The timezone in which the user wants to see times."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:177 core/models.py:177
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
msgid "device"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
#: build/lib/core/models.py:181 core/models.py:181
|
||||
msgid "Whether the user is a device or a real user."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:182 core/models.py:182
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
msgid "staff status"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
#: build/lib/core/models.py:186 core/models.py:186
|
||||
msgid "Whether the user can log into this admin site."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:187 core/models.py:187
|
||||
#: build/lib/core/models.py:189 core/models.py:189
|
||||
msgid "active"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:190 core/models.py:190
|
||||
#: build/lib/core/models.py:192 core/models.py:192
|
||||
msgid "Whether this user should be treated as active. Unselect this instead of deleting accounts."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:202 core/models.py:202
|
||||
#: build/lib/core/models.py:204 core/models.py:204
|
||||
msgid "user"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:203 core/models.py:203
|
||||
#: build/lib/core/models.py:205 core/models.py:205
|
||||
msgid "users"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:359 build/lib/core/models.py:1281
|
||||
#: core/models.py:359 core/models.py:1281
|
||||
#: build/lib/core/models.py:361 build/lib/core/models.py:1284
|
||||
#: core/models.py:361 core/models.py:1284
|
||||
msgid "title"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:360 core/models.py:360
|
||||
#: build/lib/core/models.py:362 core/models.py:362
|
||||
msgid "excerpt"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:409 core/models.py:409
|
||||
#: build/lib/core/models.py:411 core/models.py:411
|
||||
msgid "Document"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:410 core/models.py:410
|
||||
#: build/lib/core/models.py:412 core/models.py:412
|
||||
msgid "Documents"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:422 build/lib/core/models.py:819 core/models.py:422
|
||||
#: core/models.py:819
|
||||
#: build/lib/core/models.py:424 build/lib/core/models.py:822 core/models.py:424
|
||||
#: core/models.py:822
|
||||
msgid "Untitled Document"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:854 core/models.py:854
|
||||
#: build/lib/core/models.py:857 core/models.py:857
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you!"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:858 core/models.py:858
|
||||
#: build/lib/core/models.py:861 core/models.py:861
|
||||
#, python-brace-format
|
||||
msgid "{name} invited you with the role \"{role}\" on the following document:"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:864 core/models.py:864
|
||||
#: build/lib/core/models.py:867 core/models.py:867
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you: {title}"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:964 core/models.py:964
|
||||
#: build/lib/core/models.py:967 core/models.py:967
|
||||
msgid "Document/user link trace"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:965 core/models.py:965
|
||||
#: build/lib/core/models.py:968 core/models.py:968
|
||||
msgid "Document/user link traces"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:971 core/models.py:971
|
||||
#: build/lib/core/models.py:974 core/models.py:974
|
||||
msgid "A link trace already exists for this document/user."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:994 core/models.py:994
|
||||
#: build/lib/core/models.py:997 core/models.py:997
|
||||
msgid "Document favorite"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:995 core/models.py:995
|
||||
#: build/lib/core/models.py:998 core/models.py:998
|
||||
msgid "Document favorites"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1001 core/models.py:1001
|
||||
#: build/lib/core/models.py:1004 core/models.py:1004
|
||||
msgid "This document is already targeted by a favorite relation instance for the same user."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1023 core/models.py:1023
|
||||
#: build/lib/core/models.py:1026 core/models.py:1026
|
||||
msgid "Document/user relation"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1024 core/models.py:1024
|
||||
#: build/lib/core/models.py:1027 core/models.py:1027
|
||||
msgid "Document/user relations"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1030 core/models.py:1030
|
||||
#: build/lib/core/models.py:1033 core/models.py:1033
|
||||
msgid "This user is already in this document."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1036 core/models.py:1036
|
||||
#: build/lib/core/models.py:1039 core/models.py:1039
|
||||
msgid "This team is already in this document."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1042 build/lib/core/models.py:1367
|
||||
#: core/models.py:1042 core/models.py:1367
|
||||
#: build/lib/core/models.py:1045 build/lib/core/models.py:1370
|
||||
#: core/models.py:1045 core/models.py:1370
|
||||
msgid "Either user or team must be set, not both."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1188 core/models.py:1188
|
||||
#: build/lib/core/models.py:1191 core/models.py:1191
|
||||
msgid "Document ask for access"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1189 core/models.py:1189
|
||||
#: build/lib/core/models.py:1192 core/models.py:1192
|
||||
msgid "Document ask for accesses"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1195 core/models.py:1195
|
||||
#: build/lib/core/models.py:1198 core/models.py:1198
|
||||
msgid "This user has already asked for access to this document."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1260 core/models.py:1260
|
||||
#: build/lib/core/models.py:1263 core/models.py:1263
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to a document!"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1264 core/models.py:1264
|
||||
#: build/lib/core/models.py:1267 core/models.py:1267
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to the following document:"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1270 core/models.py:1270
|
||||
#: build/lib/core/models.py:1273 core/models.py:1273
|
||||
#, python-brace-format
|
||||
msgid "{name} is asking for access to the document: {title}"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1282 core/models.py:1282
|
||||
#: build/lib/core/models.py:1285 core/models.py:1285
|
||||
msgid "description"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1283 core/models.py:1283
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
msgid "code"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1284 core/models.py:1284
|
||||
#: build/lib/core/models.py:1287 core/models.py:1287
|
||||
msgid "css"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
#: build/lib/core/models.py:1289 core/models.py:1289
|
||||
msgid "public"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1288 core/models.py:1288
|
||||
#: build/lib/core/models.py:1291 core/models.py:1291
|
||||
msgid "Whether this template is public for anyone to use."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1294 core/models.py:1294
|
||||
#: build/lib/core/models.py:1297 core/models.py:1297
|
||||
msgid "Template"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1295 core/models.py:1295
|
||||
#: build/lib/core/models.py:1298 core/models.py:1298
|
||||
msgid "Templates"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1348 core/models.py:1348
|
||||
#: build/lib/core/models.py:1351 core/models.py:1351
|
||||
msgid "Template/user relation"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1349 core/models.py:1349
|
||||
#: build/lib/core/models.py:1352 core/models.py:1352
|
||||
msgid "Template/user relations"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1355 core/models.py:1355
|
||||
#: build/lib/core/models.py:1358 core/models.py:1358
|
||||
msgid "This user is already in this template."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1361 core/models.py:1361
|
||||
#: build/lib/core/models.py:1364 core/models.py:1364
|
||||
msgid "This team is already in this template."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1438 core/models.py:1438
|
||||
#: build/lib/core/models.py:1441 core/models.py:1441
|
||||
msgid "email address"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1457 core/models.py:1457
|
||||
#: build/lib/core/models.py:1460 core/models.py:1460
|
||||
msgid "Document invitation"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1458 core/models.py:1458
|
||||
#: build/lib/core/models.py:1461 core/models.py:1461
|
||||
msgid "Document invitations"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1478 core/models.py:1478
|
||||
#: build/lib/core/models.py:1481 core/models.py:1481
|
||||
msgid "This email is already associated to a registered user."
|
||||
msgstr ""
|
||||
|
||||
#: core/templates/mail/html/template.html:162
|
||||
#: core/templates/mail/html/template.html:153
|
||||
#: core/templates/mail/text/template.txt:3
|
||||
msgid "Logo email"
|
||||
msgstr ""
|
||||
|
||||
#: core/templates/mail/html/template.html:209
|
||||
#: core/templates/mail/html/template.html:200
|
||||
#: core/templates/mail/text/template.txt:10
|
||||
msgid "Open"
|
||||
msgstr ""
|
||||
|
||||
#: core/templates/mail/html/template.html:226
|
||||
#: core/templates/mail/html/template.html:217
|
||||
#: core/templates/mail/text/template.txt:14
|
||||
msgid " Docs, your new essential tool for organizing, sharing and collaborating on your documents as a team. "
|
||||
msgstr ""
|
||||
|
||||
#: core/templates/mail/html/template.html:233
|
||||
#: core/templates/mail/html/template.html:224
|
||||
#: core/templates/mail/text/template.txt:16
|
||||
#, python-format
|
||||
msgid " Brought to you by %(brandname)s "
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: lasuite-docs\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-09-10 14:29+0000\n"
|
||||
"PO-Revision-Date: 2025-09-12 09:50\n"
|
||||
"POT-Creation-Date: 2025-10-23 11:01+0000\n"
|
||||
"PO-Revision-Date: 2025-11-10 09:54\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Russian\n"
|
||||
"Language: ru_RU\n"
|
||||
@@ -17,20 +17,20 @@ msgstr ""
|
||||
"X-Crowdin-File: backend-impress.pot\n"
|
||||
"X-Crowdin-File-ID: 18\n"
|
||||
|
||||
#: build/lib/core/admin.py:37 core/admin.py:37
|
||||
#: build/lib/core/admin.py:36 core/admin.py:36
|
||||
msgid "Personal info"
|
||||
msgstr "Личная информация"
|
||||
|
||||
#: build/lib/core/admin.py:50 build/lib/core/admin.py:138 core/admin.py:50
|
||||
#: core/admin.py:138
|
||||
#: build/lib/core/admin.py:49 build/lib/core/admin.py:137 core/admin.py:49
|
||||
#: core/admin.py:137
|
||||
msgid "Permissions"
|
||||
msgstr "Разрешения"
|
||||
|
||||
#: build/lib/core/admin.py:62 core/admin.py:62
|
||||
#: build/lib/core/admin.py:61 core/admin.py:61
|
||||
msgid "Important dates"
|
||||
msgstr "Важные даты"
|
||||
|
||||
#: build/lib/core/admin.py:148 core/admin.py:148
|
||||
#: build/lib/core/admin.py:147 core/admin.py:147
|
||||
msgid "Tree structure"
|
||||
msgstr "Древовидная структура"
|
||||
|
||||
@@ -50,27 +50,36 @@ msgstr "Скрытый"
|
||||
msgid "Favorite"
|
||||
msgstr "Избранное"
|
||||
|
||||
#: build/lib/core/api/serializers.py:487 core/api/serializers.py:487
|
||||
#: build/lib/core/api/serializers.py:496 core/api/serializers.py:496
|
||||
msgid "A new document was created on your behalf!"
|
||||
msgstr "Новый документ был создан от вашего имени!"
|
||||
|
||||
#: build/lib/core/api/serializers.py:491 core/api/serializers.py:491
|
||||
#: build/lib/core/api/serializers.py:500 core/api/serializers.py:500
|
||||
msgid "You have been granted ownership of a new document:"
|
||||
msgstr "Вы назначены владельцем для нового документа:"
|
||||
|
||||
#: build/lib/core/api/serializers.py:628 core/api/serializers.py:628
|
||||
#: build/lib/core/api/serializers.py:536 core/api/serializers.py:536
|
||||
msgid "This field is required."
|
||||
msgstr "Это поле обязательное."
|
||||
|
||||
#: build/lib/core/api/serializers.py:547 core/api/serializers.py:547
|
||||
#, python-format
|
||||
msgid "Link reach '%(link_reach)s' is not allowed based on parent document configuration."
|
||||
msgstr "Доступ по ссылке '%(link_reach)s' запрещён в соответствии с настройками родительского документа."
|
||||
|
||||
#: build/lib/core/api/serializers.py:693 core/api/serializers.py:693
|
||||
msgid "Body"
|
||||
msgstr "Текст сообщения"
|
||||
|
||||
#: build/lib/core/api/serializers.py:631 core/api/serializers.py:631
|
||||
#: build/lib/core/api/serializers.py:696 core/api/serializers.py:696
|
||||
msgid "Body type"
|
||||
msgstr "Тип сообщения"
|
||||
|
||||
#: build/lib/core/api/serializers.py:637 core/api/serializers.py:637
|
||||
#: build/lib/core/api/serializers.py:702 core/api/serializers.py:702
|
||||
msgid "Format"
|
||||
msgstr "Формат"
|
||||
|
||||
#: build/lib/core/api/viewsets.py:965 core/api/viewsets.py:965
|
||||
#: build/lib/core/api/viewsets.py:1003 core/api/viewsets.py:1003
|
||||
#, python-brace-format
|
||||
msgid "copy of {title}"
|
||||
msgstr "копия {title}"
|
||||
@@ -169,247 +178,247 @@ msgstr "Обязательно. 255 символов или меньше. Тол
|
||||
msgid "full name"
|
||||
msgstr "полное имя"
|
||||
|
||||
#: build/lib/core/models.py:151 core/models.py:151
|
||||
#: build/lib/core/models.py:152 core/models.py:152
|
||||
msgid "short name"
|
||||
msgstr "короткое имя"
|
||||
|
||||
#: build/lib/core/models.py:153 core/models.py:153
|
||||
#: build/lib/core/models.py:155 core/models.py:155
|
||||
msgid "identity email address"
|
||||
msgstr "личный адрес электронной почты"
|
||||
|
||||
#: build/lib/core/models.py:158 core/models.py:158
|
||||
#: build/lib/core/models.py:160 core/models.py:160
|
||||
msgid "admin email address"
|
||||
msgstr "e-mail администратора"
|
||||
|
||||
#: build/lib/core/models.py:165 core/models.py:165
|
||||
#: build/lib/core/models.py:167 core/models.py:167
|
||||
msgid "language"
|
||||
msgstr "язык"
|
||||
|
||||
#: build/lib/core/models.py:166 core/models.py:166
|
||||
#: build/lib/core/models.py:168 core/models.py:168
|
||||
msgid "The language in which the user wants to see the interface."
|
||||
msgstr "Язык, на котором пользователь хочет видеть интерфейс."
|
||||
|
||||
#: build/lib/core/models.py:174 core/models.py:174
|
||||
#: build/lib/core/models.py:176 core/models.py:176
|
||||
msgid "The timezone in which the user wants to see times."
|
||||
msgstr "Часовой пояс, в котором пользователь хочет видеть время."
|
||||
|
||||
#: build/lib/core/models.py:177 core/models.py:177
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
msgid "device"
|
||||
msgstr "устройство"
|
||||
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
#: build/lib/core/models.py:181 core/models.py:181
|
||||
msgid "Whether the user is a device or a real user."
|
||||
msgstr "Пользователь является устройством или человеком."
|
||||
|
||||
#: build/lib/core/models.py:182 core/models.py:182
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
msgid "staff status"
|
||||
msgstr "статус сотрудника"
|
||||
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
#: build/lib/core/models.py:186 core/models.py:186
|
||||
msgid "Whether the user can log into this admin site."
|
||||
msgstr "Может ли пользователь войти на этот административный сайт."
|
||||
|
||||
#: build/lib/core/models.py:187 core/models.py:187
|
||||
#: build/lib/core/models.py:189 core/models.py:189
|
||||
msgid "active"
|
||||
msgstr "активный"
|
||||
|
||||
#: build/lib/core/models.py:190 core/models.py:190
|
||||
#: build/lib/core/models.py:192 core/models.py:192
|
||||
msgid "Whether this user should be treated as active. Unselect this instead of deleting accounts."
|
||||
msgstr "Должен ли пользователь рассматриваться как активный. Альтернатива удалению учётных записей."
|
||||
|
||||
#: build/lib/core/models.py:202 core/models.py:202
|
||||
#: build/lib/core/models.py:204 core/models.py:204
|
||||
msgid "user"
|
||||
msgstr "пользователь"
|
||||
|
||||
#: build/lib/core/models.py:203 core/models.py:203
|
||||
#: build/lib/core/models.py:205 core/models.py:205
|
||||
msgid "users"
|
||||
msgstr "пользователи"
|
||||
|
||||
#: build/lib/core/models.py:359 build/lib/core/models.py:1281
|
||||
#: core/models.py:359 core/models.py:1281
|
||||
#: build/lib/core/models.py:361 build/lib/core/models.py:1284
|
||||
#: core/models.py:361 core/models.py:1284
|
||||
msgid "title"
|
||||
msgstr "заголовок"
|
||||
|
||||
#: build/lib/core/models.py:360 core/models.py:360
|
||||
#: build/lib/core/models.py:362 core/models.py:362
|
||||
msgid "excerpt"
|
||||
msgstr "отрывок"
|
||||
|
||||
#: build/lib/core/models.py:409 core/models.py:409
|
||||
#: build/lib/core/models.py:411 core/models.py:411
|
||||
msgid "Document"
|
||||
msgstr "Документ"
|
||||
|
||||
#: build/lib/core/models.py:410 core/models.py:410
|
||||
#: build/lib/core/models.py:412 core/models.py:412
|
||||
msgid "Documents"
|
||||
msgstr "Документы"
|
||||
|
||||
#: build/lib/core/models.py:422 build/lib/core/models.py:819 core/models.py:422
|
||||
#: core/models.py:819
|
||||
#: build/lib/core/models.py:424 build/lib/core/models.py:822 core/models.py:424
|
||||
#: core/models.py:822
|
||||
msgid "Untitled Document"
|
||||
msgstr "Безымянный документ"
|
||||
|
||||
#: build/lib/core/models.py:854 core/models.py:854
|
||||
#: build/lib/core/models.py:857 core/models.py:857
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you!"
|
||||
msgstr "{name} делится с вами документом!"
|
||||
|
||||
#: build/lib/core/models.py:858 core/models.py:858
|
||||
#: build/lib/core/models.py:861 core/models.py:861
|
||||
#, python-brace-format
|
||||
msgid "{name} invited you with the role \"{role}\" on the following document:"
|
||||
msgstr "{name} приглашает вас присоединиться к следующему документу с ролью \"{role}\":"
|
||||
|
||||
#: build/lib/core/models.py:864 core/models.py:864
|
||||
#: build/lib/core/models.py:867 core/models.py:867
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you: {title}"
|
||||
msgstr "{name} делится с вами документом: {title}"
|
||||
|
||||
#: build/lib/core/models.py:964 core/models.py:964
|
||||
#: build/lib/core/models.py:967 core/models.py:967
|
||||
msgid "Document/user link trace"
|
||||
msgstr "Трассировка связи документ/пользователь"
|
||||
|
||||
#: build/lib/core/models.py:965 core/models.py:965
|
||||
#: build/lib/core/models.py:968 core/models.py:968
|
||||
msgid "Document/user link traces"
|
||||
msgstr "Трассировка связей документ/пользователь"
|
||||
|
||||
#: build/lib/core/models.py:971 core/models.py:971
|
||||
#: build/lib/core/models.py:974 core/models.py:974
|
||||
msgid "A link trace already exists for this document/user."
|
||||
msgstr "Для этого документа/пользователя уже существует трассировка ссылки."
|
||||
|
||||
#: build/lib/core/models.py:994 core/models.py:994
|
||||
#: build/lib/core/models.py:997 core/models.py:997
|
||||
msgid "Document favorite"
|
||||
msgstr "Избранный документ"
|
||||
|
||||
#: build/lib/core/models.py:995 core/models.py:995
|
||||
#: build/lib/core/models.py:998 core/models.py:998
|
||||
msgid "Document favorites"
|
||||
msgstr "Избранные документы"
|
||||
|
||||
#: build/lib/core/models.py:1001 core/models.py:1001
|
||||
#: build/lib/core/models.py:1004 core/models.py:1004
|
||||
msgid "This document is already targeted by a favorite relation instance for the same user."
|
||||
msgstr "Этот документ уже помечен как избранный для этого пользователя."
|
||||
|
||||
#: build/lib/core/models.py:1023 core/models.py:1023
|
||||
#: build/lib/core/models.py:1026 core/models.py:1026
|
||||
msgid "Document/user relation"
|
||||
msgstr "Отношение документ/пользователь"
|
||||
|
||||
#: build/lib/core/models.py:1024 core/models.py:1024
|
||||
#: build/lib/core/models.py:1027 core/models.py:1027
|
||||
msgid "Document/user relations"
|
||||
msgstr "Отношения документ/пользователь"
|
||||
|
||||
#: build/lib/core/models.py:1030 core/models.py:1030
|
||||
#: build/lib/core/models.py:1033 core/models.py:1033
|
||||
msgid "This user is already in this document."
|
||||
msgstr "Этот пользователь уже имеет доступ к этому документу."
|
||||
|
||||
#: build/lib/core/models.py:1036 core/models.py:1036
|
||||
#: build/lib/core/models.py:1039 core/models.py:1039
|
||||
msgid "This team is already in this document."
|
||||
msgstr "Эта команда уже имеет доступ к этому документу."
|
||||
|
||||
#: build/lib/core/models.py:1042 build/lib/core/models.py:1367
|
||||
#: core/models.py:1042 core/models.py:1367
|
||||
#: build/lib/core/models.py:1045 build/lib/core/models.py:1370
|
||||
#: core/models.py:1045 core/models.py:1370
|
||||
msgid "Either user or team must be set, not both."
|
||||
msgstr "Может быть выбран либо пользователь, либо команда, но не оба варианта сразу."
|
||||
|
||||
#: build/lib/core/models.py:1188 core/models.py:1188
|
||||
#: build/lib/core/models.py:1191 core/models.py:1191
|
||||
msgid "Document ask for access"
|
||||
msgstr "Документ запрашивает доступ"
|
||||
|
||||
#: build/lib/core/models.py:1189 core/models.py:1189
|
||||
#: build/lib/core/models.py:1192 core/models.py:1192
|
||||
msgid "Document ask for accesses"
|
||||
msgstr "Документ запрашивает доступы"
|
||||
|
||||
#: build/lib/core/models.py:1195 core/models.py:1195
|
||||
#: build/lib/core/models.py:1198 core/models.py:1198
|
||||
msgid "This user has already asked for access to this document."
|
||||
msgstr "Этот пользователь уже запросил доступ к этому документу."
|
||||
|
||||
#: build/lib/core/models.py:1260 core/models.py:1260
|
||||
#: build/lib/core/models.py:1263 core/models.py:1263
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to a document!"
|
||||
msgstr "{name} хочет получить доступ к документу!"
|
||||
|
||||
#: build/lib/core/models.py:1264 core/models.py:1264
|
||||
#: build/lib/core/models.py:1267 core/models.py:1267
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to the following document:"
|
||||
msgstr "{name} хочет получить доступ к следующему документу:"
|
||||
|
||||
#: build/lib/core/models.py:1270 core/models.py:1270
|
||||
#: build/lib/core/models.py:1273 core/models.py:1273
|
||||
#, python-brace-format
|
||||
msgid "{name} is asking for access to the document: {title}"
|
||||
msgstr "{name} запрашивает доступ к документу: {title}"
|
||||
|
||||
#: build/lib/core/models.py:1282 core/models.py:1282
|
||||
#: build/lib/core/models.py:1285 core/models.py:1285
|
||||
msgid "description"
|
||||
msgstr "описание"
|
||||
|
||||
#: build/lib/core/models.py:1283 core/models.py:1283
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
msgid "code"
|
||||
msgstr "код"
|
||||
|
||||
#: build/lib/core/models.py:1284 core/models.py:1284
|
||||
#: build/lib/core/models.py:1287 core/models.py:1287
|
||||
msgid "css"
|
||||
msgstr "css"
|
||||
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
#: build/lib/core/models.py:1289 core/models.py:1289
|
||||
msgid "public"
|
||||
msgstr "доступно всем"
|
||||
|
||||
#: build/lib/core/models.py:1288 core/models.py:1288
|
||||
#: build/lib/core/models.py:1291 core/models.py:1291
|
||||
msgid "Whether this template is public for anyone to use."
|
||||
msgstr "Этот шаблон доступен всем пользователям."
|
||||
|
||||
#: build/lib/core/models.py:1294 core/models.py:1294
|
||||
#: build/lib/core/models.py:1297 core/models.py:1297
|
||||
msgid "Template"
|
||||
msgstr "Шаблон"
|
||||
|
||||
#: build/lib/core/models.py:1295 core/models.py:1295
|
||||
#: build/lib/core/models.py:1298 core/models.py:1298
|
||||
msgid "Templates"
|
||||
msgstr "Шаблоны"
|
||||
|
||||
#: build/lib/core/models.py:1348 core/models.py:1348
|
||||
#: build/lib/core/models.py:1351 core/models.py:1351
|
||||
msgid "Template/user relation"
|
||||
msgstr "Отношение шаблон/пользователь"
|
||||
|
||||
#: build/lib/core/models.py:1349 core/models.py:1349
|
||||
#: build/lib/core/models.py:1352 core/models.py:1352
|
||||
msgid "Template/user relations"
|
||||
msgstr "Отношения шаблон/пользователь"
|
||||
|
||||
#: build/lib/core/models.py:1355 core/models.py:1355
|
||||
#: build/lib/core/models.py:1358 core/models.py:1358
|
||||
msgid "This user is already in this template."
|
||||
msgstr "Этот пользователь уже указан в этом шаблоне."
|
||||
|
||||
#: build/lib/core/models.py:1361 core/models.py:1361
|
||||
#: build/lib/core/models.py:1364 core/models.py:1364
|
||||
msgid "This team is already in this template."
|
||||
msgstr "Эта команда уже указана в этом шаблоне."
|
||||
|
||||
#: build/lib/core/models.py:1438 core/models.py:1438
|
||||
#: build/lib/core/models.py:1441 core/models.py:1441
|
||||
msgid "email address"
|
||||
msgstr "адрес электронной почты"
|
||||
|
||||
#: build/lib/core/models.py:1457 core/models.py:1457
|
||||
#: build/lib/core/models.py:1460 core/models.py:1460
|
||||
msgid "Document invitation"
|
||||
msgstr "Приглашение для документа"
|
||||
|
||||
#: build/lib/core/models.py:1458 core/models.py:1458
|
||||
#: build/lib/core/models.py:1461 core/models.py:1461
|
||||
msgid "Document invitations"
|
||||
msgstr "Приглашения для документов"
|
||||
|
||||
#: build/lib/core/models.py:1478 core/models.py:1478
|
||||
#: build/lib/core/models.py:1481 core/models.py:1481
|
||||
msgid "This email is already associated to a registered user."
|
||||
msgstr "Этот адрес уже связан с зарегистрированным пользователем."
|
||||
|
||||
#: core/templates/mail/html/template.html:162
|
||||
#: core/templates/mail/html/template.html:153
|
||||
#: core/templates/mail/text/template.txt:3
|
||||
msgid "Logo email"
|
||||
msgstr "Логотип email"
|
||||
|
||||
#: core/templates/mail/html/template.html:209
|
||||
#: core/templates/mail/html/template.html:200
|
||||
#: core/templates/mail/text/template.txt:10
|
||||
msgid "Open"
|
||||
msgstr "Открыть"
|
||||
|
||||
#: core/templates/mail/html/template.html:226
|
||||
#: core/templates/mail/html/template.html:217
|
||||
#: core/templates/mail/text/template.txt:14
|
||||
msgid " Docs, your new essential tool for organizing, sharing and collaborating on your documents as a team. "
|
||||
msgstr " Docs, ваш новый инструмент для организации и совместного использования документов в вашей команде. "
|
||||
|
||||
#: core/templates/mail/html/template.html:233
|
||||
#: core/templates/mail/html/template.html:224
|
||||
#: core/templates/mail/text/template.txt:16
|
||||
#, python-format
|
||||
msgid " Brought to you by %(brandname)s "
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: lasuite-docs\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-09-10 14:29+0000\n"
|
||||
"PO-Revision-Date: 2025-09-12 09:50\n"
|
||||
"POT-Creation-Date: 2025-10-23 11:01+0000\n"
|
||||
"PO-Revision-Date: 2025-11-10 09:54\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Slovenian\n"
|
||||
"Language: sl_SI\n"
|
||||
@@ -17,20 +17,20 @@ msgstr ""
|
||||
"X-Crowdin-File: backend-impress.pot\n"
|
||||
"X-Crowdin-File-ID: 18\n"
|
||||
|
||||
#: build/lib/core/admin.py:37 core/admin.py:37
|
||||
#: build/lib/core/admin.py:36 core/admin.py:36
|
||||
msgid "Personal info"
|
||||
msgstr "Osebni podatki"
|
||||
|
||||
#: build/lib/core/admin.py:50 build/lib/core/admin.py:138 core/admin.py:50
|
||||
#: core/admin.py:138
|
||||
#: build/lib/core/admin.py:49 build/lib/core/admin.py:137 core/admin.py:49
|
||||
#: core/admin.py:137
|
||||
msgid "Permissions"
|
||||
msgstr "Dovoljenja"
|
||||
|
||||
#: build/lib/core/admin.py:62 core/admin.py:62
|
||||
#: build/lib/core/admin.py:61 core/admin.py:61
|
||||
msgid "Important dates"
|
||||
msgstr "Pomembni datumi"
|
||||
|
||||
#: build/lib/core/admin.py:148 core/admin.py:148
|
||||
#: build/lib/core/admin.py:147 core/admin.py:147
|
||||
msgid "Tree structure"
|
||||
msgstr "Drevesna struktura"
|
||||
|
||||
@@ -50,27 +50,36 @@ msgstr ""
|
||||
msgid "Favorite"
|
||||
msgstr "Priljubljena"
|
||||
|
||||
#: build/lib/core/api/serializers.py:487 core/api/serializers.py:487
|
||||
#: build/lib/core/api/serializers.py:496 core/api/serializers.py:496
|
||||
msgid "A new document was created on your behalf!"
|
||||
msgstr "Nov dokument je bil ustvarjen v vašem imenu!"
|
||||
|
||||
#: build/lib/core/api/serializers.py:491 core/api/serializers.py:491
|
||||
#: build/lib/core/api/serializers.py:500 core/api/serializers.py:500
|
||||
msgid "You have been granted ownership of a new document:"
|
||||
msgstr "Dodeljeno vam je bilo lastništvo nad novim dokumentom:"
|
||||
|
||||
#: build/lib/core/api/serializers.py:628 core/api/serializers.py:628
|
||||
#: build/lib/core/api/serializers.py:536 core/api/serializers.py:536
|
||||
msgid "This field is required."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:547 core/api/serializers.py:547
|
||||
#, python-format
|
||||
msgid "Link reach '%(link_reach)s' is not allowed based on parent document configuration."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:693 core/api/serializers.py:693
|
||||
msgid "Body"
|
||||
msgstr "Telo"
|
||||
|
||||
#: build/lib/core/api/serializers.py:631 core/api/serializers.py:631
|
||||
#: build/lib/core/api/serializers.py:696 core/api/serializers.py:696
|
||||
msgid "Body type"
|
||||
msgstr "Vrsta telesa"
|
||||
|
||||
#: build/lib/core/api/serializers.py:637 core/api/serializers.py:637
|
||||
#: build/lib/core/api/serializers.py:702 core/api/serializers.py:702
|
||||
msgid "Format"
|
||||
msgstr "Oblika"
|
||||
|
||||
#: build/lib/core/api/viewsets.py:965 core/api/viewsets.py:965
|
||||
#: build/lib/core/api/viewsets.py:1003 core/api/viewsets.py:1003
|
||||
#, python-brace-format
|
||||
msgid "copy of {title}"
|
||||
msgstr ""
|
||||
@@ -169,247 +178,247 @@ msgstr ""
|
||||
msgid "full name"
|
||||
msgstr "polno ime"
|
||||
|
||||
#: build/lib/core/models.py:151 core/models.py:151
|
||||
#: build/lib/core/models.py:152 core/models.py:152
|
||||
msgid "short name"
|
||||
msgstr "kratko ime"
|
||||
|
||||
#: build/lib/core/models.py:153 core/models.py:153
|
||||
#: build/lib/core/models.py:155 core/models.py:155
|
||||
msgid "identity email address"
|
||||
msgstr "elektronski naslov identitete"
|
||||
|
||||
#: build/lib/core/models.py:158 core/models.py:158
|
||||
#: build/lib/core/models.py:160 core/models.py:160
|
||||
msgid "admin email address"
|
||||
msgstr "elektronski naslov skrbnika"
|
||||
|
||||
#: build/lib/core/models.py:165 core/models.py:165
|
||||
#: build/lib/core/models.py:167 core/models.py:167
|
||||
msgid "language"
|
||||
msgstr "jezik"
|
||||
|
||||
#: build/lib/core/models.py:166 core/models.py:166
|
||||
#: build/lib/core/models.py:168 core/models.py:168
|
||||
msgid "The language in which the user wants to see the interface."
|
||||
msgstr "Jezik, v katerem uporabnik želi videti vmesnik."
|
||||
|
||||
#: build/lib/core/models.py:174 core/models.py:174
|
||||
#: build/lib/core/models.py:176 core/models.py:176
|
||||
msgid "The timezone in which the user wants to see times."
|
||||
msgstr "Časovni pas, v katerem želi uporabnik videti uro."
|
||||
|
||||
#: build/lib/core/models.py:177 core/models.py:177
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
msgid "device"
|
||||
msgstr "naprava"
|
||||
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
#: build/lib/core/models.py:181 core/models.py:181
|
||||
msgid "Whether the user is a device or a real user."
|
||||
msgstr "Ali je uporabnik naprava ali pravi uporabnik."
|
||||
|
||||
#: build/lib/core/models.py:182 core/models.py:182
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
msgid "staff status"
|
||||
msgstr "kadrovski status"
|
||||
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
#: build/lib/core/models.py:186 core/models.py:186
|
||||
msgid "Whether the user can log into this admin site."
|
||||
msgstr "Ali se uporabnik lahko prijavi na to skrbniško mesto."
|
||||
|
||||
#: build/lib/core/models.py:187 core/models.py:187
|
||||
#: build/lib/core/models.py:189 core/models.py:189
|
||||
msgid "active"
|
||||
msgstr "aktivni"
|
||||
|
||||
#: build/lib/core/models.py:190 core/models.py:190
|
||||
#: build/lib/core/models.py:192 core/models.py:192
|
||||
msgid "Whether this user should be treated as active. Unselect this instead of deleting accounts."
|
||||
msgstr "Ali je treba tega uporabnika obravnavati kot aktivnega. Namesto brisanja računov počistite to izbiro."
|
||||
|
||||
#: build/lib/core/models.py:202 core/models.py:202
|
||||
#: build/lib/core/models.py:204 core/models.py:204
|
||||
msgid "user"
|
||||
msgstr "uporabnik"
|
||||
|
||||
#: build/lib/core/models.py:203 core/models.py:203
|
||||
#: build/lib/core/models.py:205 core/models.py:205
|
||||
msgid "users"
|
||||
msgstr "uporabniki"
|
||||
|
||||
#: build/lib/core/models.py:359 build/lib/core/models.py:1281
|
||||
#: core/models.py:359 core/models.py:1281
|
||||
#: build/lib/core/models.py:361 build/lib/core/models.py:1284
|
||||
#: core/models.py:361 core/models.py:1284
|
||||
msgid "title"
|
||||
msgstr "naslov"
|
||||
|
||||
#: build/lib/core/models.py:360 core/models.py:360
|
||||
#: build/lib/core/models.py:362 core/models.py:362
|
||||
msgid "excerpt"
|
||||
msgstr "odlomek"
|
||||
|
||||
#: build/lib/core/models.py:409 core/models.py:409
|
||||
#: build/lib/core/models.py:411 core/models.py:411
|
||||
msgid "Document"
|
||||
msgstr "Dokument"
|
||||
|
||||
#: build/lib/core/models.py:410 core/models.py:410
|
||||
#: build/lib/core/models.py:412 core/models.py:412
|
||||
msgid "Documents"
|
||||
msgstr "Dokumenti"
|
||||
|
||||
#: build/lib/core/models.py:422 build/lib/core/models.py:819 core/models.py:422
|
||||
#: core/models.py:819
|
||||
#: build/lib/core/models.py:424 build/lib/core/models.py:822 core/models.py:424
|
||||
#: core/models.py:822
|
||||
msgid "Untitled Document"
|
||||
msgstr "Dokument brez naslova"
|
||||
|
||||
#: build/lib/core/models.py:854 core/models.py:854
|
||||
#: build/lib/core/models.py:857 core/models.py:857
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you!"
|
||||
msgstr "{name} je delil dokument z vami!"
|
||||
|
||||
#: build/lib/core/models.py:858 core/models.py:858
|
||||
#: build/lib/core/models.py:861 core/models.py:861
|
||||
#, python-brace-format
|
||||
msgid "{name} invited you with the role \"{role}\" on the following document:"
|
||||
msgstr "{name} vas je povabil z vlogo \"{role}\" na naslednjem dokumentu:"
|
||||
|
||||
#: build/lib/core/models.py:864 core/models.py:864
|
||||
#: build/lib/core/models.py:867 core/models.py:867
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you: {title}"
|
||||
msgstr "{name} je delil dokument z vami: {title}"
|
||||
|
||||
#: build/lib/core/models.py:964 core/models.py:964
|
||||
#: build/lib/core/models.py:967 core/models.py:967
|
||||
msgid "Document/user link trace"
|
||||
msgstr "Dokument/sled povezave uporabnika"
|
||||
|
||||
#: build/lib/core/models.py:965 core/models.py:965
|
||||
#: build/lib/core/models.py:968 core/models.py:968
|
||||
msgid "Document/user link traces"
|
||||
msgstr "Sledi povezav dokumenta/uporabnika"
|
||||
|
||||
#: build/lib/core/models.py:971 core/models.py:971
|
||||
#: build/lib/core/models.py:974 core/models.py:974
|
||||
msgid "A link trace already exists for this document/user."
|
||||
msgstr "Za ta dokument/uporabnika že obstaja sled povezave."
|
||||
|
||||
#: build/lib/core/models.py:994 core/models.py:994
|
||||
#: build/lib/core/models.py:997 core/models.py:997
|
||||
msgid "Document favorite"
|
||||
msgstr "Priljubljeni dokument"
|
||||
|
||||
#: build/lib/core/models.py:995 core/models.py:995
|
||||
#: build/lib/core/models.py:998 core/models.py:998
|
||||
msgid "Document favorites"
|
||||
msgstr "Priljubljeni dokumenti"
|
||||
|
||||
#: build/lib/core/models.py:1001 core/models.py:1001
|
||||
#: build/lib/core/models.py:1004 core/models.py:1004
|
||||
msgid "This document is already targeted by a favorite relation instance for the same user."
|
||||
msgstr "Ta dokument je že ciljno usmerjen s priljubljenim primerkom relacije za istega uporabnika."
|
||||
|
||||
#: build/lib/core/models.py:1023 core/models.py:1023
|
||||
#: build/lib/core/models.py:1026 core/models.py:1026
|
||||
msgid "Document/user relation"
|
||||
msgstr "Odnos dokument/uporabnik"
|
||||
|
||||
#: build/lib/core/models.py:1024 core/models.py:1024
|
||||
#: build/lib/core/models.py:1027 core/models.py:1027
|
||||
msgid "Document/user relations"
|
||||
msgstr "Odnosi dokument/uporabnik"
|
||||
|
||||
#: build/lib/core/models.py:1030 core/models.py:1030
|
||||
#: build/lib/core/models.py:1033 core/models.py:1033
|
||||
msgid "This user is already in this document."
|
||||
msgstr "Ta uporabnik je že v tem dokumentu."
|
||||
|
||||
#: build/lib/core/models.py:1036 core/models.py:1036
|
||||
#: build/lib/core/models.py:1039 core/models.py:1039
|
||||
msgid "This team is already in this document."
|
||||
msgstr "Ta ekipa je že v tem dokumentu."
|
||||
|
||||
#: build/lib/core/models.py:1042 build/lib/core/models.py:1367
|
||||
#: core/models.py:1042 core/models.py:1367
|
||||
#: build/lib/core/models.py:1045 build/lib/core/models.py:1370
|
||||
#: core/models.py:1045 core/models.py:1370
|
||||
msgid "Either user or team must be set, not both."
|
||||
msgstr "Nastaviti je treba bodisi uporabnika ali ekipo, a ne obojega."
|
||||
|
||||
#: build/lib/core/models.py:1188 core/models.py:1188
|
||||
#: build/lib/core/models.py:1191 core/models.py:1191
|
||||
msgid "Document ask for access"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1189 core/models.py:1189
|
||||
#: build/lib/core/models.py:1192 core/models.py:1192
|
||||
msgid "Document ask for accesses"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1195 core/models.py:1195
|
||||
#: build/lib/core/models.py:1198 core/models.py:1198
|
||||
msgid "This user has already asked for access to this document."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1260 core/models.py:1260
|
||||
#: build/lib/core/models.py:1263 core/models.py:1263
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to a document!"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1264 core/models.py:1264
|
||||
#: build/lib/core/models.py:1267 core/models.py:1267
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to the following document:"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1270 core/models.py:1270
|
||||
#: build/lib/core/models.py:1273 core/models.py:1273
|
||||
#, python-brace-format
|
||||
msgid "{name} is asking for access to the document: {title}"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1282 core/models.py:1282
|
||||
#: build/lib/core/models.py:1285 core/models.py:1285
|
||||
msgid "description"
|
||||
msgstr "opis"
|
||||
|
||||
#: build/lib/core/models.py:1283 core/models.py:1283
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
msgid "code"
|
||||
msgstr "koda"
|
||||
|
||||
#: build/lib/core/models.py:1284 core/models.py:1284
|
||||
#: build/lib/core/models.py:1287 core/models.py:1287
|
||||
msgid "css"
|
||||
msgstr "css"
|
||||
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
#: build/lib/core/models.py:1289 core/models.py:1289
|
||||
msgid "public"
|
||||
msgstr "javno"
|
||||
|
||||
#: build/lib/core/models.py:1288 core/models.py:1288
|
||||
#: build/lib/core/models.py:1291 core/models.py:1291
|
||||
msgid "Whether this template is public for anyone to use."
|
||||
msgstr "Ali je ta predloga javna za uporabo."
|
||||
|
||||
#: build/lib/core/models.py:1294 core/models.py:1294
|
||||
#: build/lib/core/models.py:1297 core/models.py:1297
|
||||
msgid "Template"
|
||||
msgstr "Predloga"
|
||||
|
||||
#: build/lib/core/models.py:1295 core/models.py:1295
|
||||
#: build/lib/core/models.py:1298 core/models.py:1298
|
||||
msgid "Templates"
|
||||
msgstr "Predloge"
|
||||
|
||||
#: build/lib/core/models.py:1348 core/models.py:1348
|
||||
#: build/lib/core/models.py:1351 core/models.py:1351
|
||||
msgid "Template/user relation"
|
||||
msgstr "Odnos predloga/uporabnik"
|
||||
|
||||
#: build/lib/core/models.py:1349 core/models.py:1349
|
||||
#: build/lib/core/models.py:1352 core/models.py:1352
|
||||
msgid "Template/user relations"
|
||||
msgstr "Odnosi med predlogo in uporabnikom"
|
||||
|
||||
#: build/lib/core/models.py:1355 core/models.py:1355
|
||||
#: build/lib/core/models.py:1358 core/models.py:1358
|
||||
msgid "This user is already in this template."
|
||||
msgstr "Ta uporabnik je že v tej predlogi."
|
||||
|
||||
#: build/lib/core/models.py:1361 core/models.py:1361
|
||||
#: build/lib/core/models.py:1364 core/models.py:1364
|
||||
msgid "This team is already in this template."
|
||||
msgstr "Ta ekipa je že v tej predlogi."
|
||||
|
||||
#: build/lib/core/models.py:1438 core/models.py:1438
|
||||
#: build/lib/core/models.py:1441 core/models.py:1441
|
||||
msgid "email address"
|
||||
msgstr "elektronski naslov"
|
||||
|
||||
#: build/lib/core/models.py:1457 core/models.py:1457
|
||||
#: build/lib/core/models.py:1460 core/models.py:1460
|
||||
msgid "Document invitation"
|
||||
msgstr "Vabilo na dokument"
|
||||
|
||||
#: build/lib/core/models.py:1458 core/models.py:1458
|
||||
#: build/lib/core/models.py:1461 core/models.py:1461
|
||||
msgid "Document invitations"
|
||||
msgstr "Vabila na dokument"
|
||||
|
||||
#: build/lib/core/models.py:1478 core/models.py:1478
|
||||
#: build/lib/core/models.py:1481 core/models.py:1481
|
||||
msgid "This email is already associated to a registered user."
|
||||
msgstr "Ta e-poštni naslov je že povezan z registriranim uporabnikom."
|
||||
|
||||
#: core/templates/mail/html/template.html:162
|
||||
#: core/templates/mail/html/template.html:153
|
||||
#: core/templates/mail/text/template.txt:3
|
||||
msgid "Logo email"
|
||||
msgstr "E-pošta z logotipom"
|
||||
|
||||
#: core/templates/mail/html/template.html:209
|
||||
#: core/templates/mail/html/template.html:200
|
||||
#: core/templates/mail/text/template.txt:10
|
||||
msgid "Open"
|
||||
msgstr "Odpri"
|
||||
|
||||
#: core/templates/mail/html/template.html:226
|
||||
#: core/templates/mail/html/template.html:217
|
||||
#: core/templates/mail/text/template.txt:14
|
||||
msgid " Docs, your new essential tool for organizing, sharing and collaborating on your documents as a team. "
|
||||
msgstr " Dokumenti, vaše novo bistveno orodje za organiziranje, skupno rabo in skupinsko sodelovanje pri dokumentih. "
|
||||
|
||||
#: core/templates/mail/html/template.html:233
|
||||
#: core/templates/mail/html/template.html:224
|
||||
#: core/templates/mail/text/template.txt:16
|
||||
#, python-format
|
||||
msgid " Brought to you by %(brandname)s "
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: lasuite-docs\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-09-10 14:29+0000\n"
|
||||
"PO-Revision-Date: 2025-09-12 09:50\n"
|
||||
"POT-Creation-Date: 2025-10-23 11:01+0000\n"
|
||||
"PO-Revision-Date: 2025-11-10 09:54\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Swedish\n"
|
||||
"Language: sv_SE\n"
|
||||
@@ -17,20 +17,20 @@ msgstr ""
|
||||
"X-Crowdin-File: backend-impress.pot\n"
|
||||
"X-Crowdin-File-ID: 18\n"
|
||||
|
||||
#: build/lib/core/admin.py:37 core/admin.py:37
|
||||
#: build/lib/core/admin.py:36 core/admin.py:36
|
||||
msgid "Personal info"
|
||||
msgstr "Personuppgifter"
|
||||
|
||||
#: build/lib/core/admin.py:50 build/lib/core/admin.py:138 core/admin.py:50
|
||||
#: core/admin.py:138
|
||||
#: build/lib/core/admin.py:49 build/lib/core/admin.py:137 core/admin.py:49
|
||||
#: core/admin.py:137
|
||||
msgid "Permissions"
|
||||
msgstr "Behörigheter"
|
||||
|
||||
#: build/lib/core/admin.py:62 core/admin.py:62
|
||||
#: build/lib/core/admin.py:61 core/admin.py:61
|
||||
msgid "Important dates"
|
||||
msgstr "Viktiga datum"
|
||||
|
||||
#: build/lib/core/admin.py:148 core/admin.py:148
|
||||
#: build/lib/core/admin.py:147 core/admin.py:147
|
||||
msgid "Tree structure"
|
||||
msgstr ""
|
||||
|
||||
@@ -50,27 +50,36 @@ msgstr ""
|
||||
msgid "Favorite"
|
||||
msgstr "Favoriter"
|
||||
|
||||
#: build/lib/core/api/serializers.py:487 core/api/serializers.py:487
|
||||
#: build/lib/core/api/serializers.py:496 core/api/serializers.py:496
|
||||
msgid "A new document was created on your behalf!"
|
||||
msgstr "Ett nytt dokument skapades åt dig!"
|
||||
|
||||
#: build/lib/core/api/serializers.py:491 core/api/serializers.py:491
|
||||
#: build/lib/core/api/serializers.py:500 core/api/serializers.py:500
|
||||
msgid "You have been granted ownership of a new document:"
|
||||
msgstr "Du har beviljats äganderätt till ett nytt dokument:"
|
||||
|
||||
#: build/lib/core/api/serializers.py:628 core/api/serializers.py:628
|
||||
#: build/lib/core/api/serializers.py:536 core/api/serializers.py:536
|
||||
msgid "This field is required."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:547 core/api/serializers.py:547
|
||||
#, python-format
|
||||
msgid "Link reach '%(link_reach)s' is not allowed based on parent document configuration."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:693 core/api/serializers.py:693
|
||||
msgid "Body"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:631 core/api/serializers.py:631
|
||||
#: build/lib/core/api/serializers.py:696 core/api/serializers.py:696
|
||||
msgid "Body type"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:637 core/api/serializers.py:637
|
||||
#: build/lib/core/api/serializers.py:702 core/api/serializers.py:702
|
||||
msgid "Format"
|
||||
msgstr "Format"
|
||||
|
||||
#: build/lib/core/api/viewsets.py:965 core/api/viewsets.py:965
|
||||
#: build/lib/core/api/viewsets.py:1003 core/api/viewsets.py:1003
|
||||
#, python-brace-format
|
||||
msgid "copy of {title}"
|
||||
msgstr ""
|
||||
@@ -169,247 +178,247 @@ msgstr ""
|
||||
msgid "full name"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:151 core/models.py:151
|
||||
#: build/lib/core/models.py:152 core/models.py:152
|
||||
msgid "short name"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:153 core/models.py:153
|
||||
#: build/lib/core/models.py:155 core/models.py:155
|
||||
msgid "identity email address"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:158 core/models.py:158
|
||||
#: build/lib/core/models.py:160 core/models.py:160
|
||||
msgid "admin email address"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:165 core/models.py:165
|
||||
#: build/lib/core/models.py:167 core/models.py:167
|
||||
msgid "language"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:166 core/models.py:166
|
||||
#: build/lib/core/models.py:168 core/models.py:168
|
||||
msgid "The language in which the user wants to see the interface."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:174 core/models.py:174
|
||||
#: build/lib/core/models.py:176 core/models.py:176
|
||||
msgid "The timezone in which the user wants to see times."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:177 core/models.py:177
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
msgid "device"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
#: build/lib/core/models.py:181 core/models.py:181
|
||||
msgid "Whether the user is a device or a real user."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:182 core/models.py:182
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
msgid "staff status"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
#: build/lib/core/models.py:186 core/models.py:186
|
||||
msgid "Whether the user can log into this admin site."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:187 core/models.py:187
|
||||
#: build/lib/core/models.py:189 core/models.py:189
|
||||
msgid "active"
|
||||
msgstr "aktiv"
|
||||
|
||||
#: build/lib/core/models.py:190 core/models.py:190
|
||||
#: build/lib/core/models.py:192 core/models.py:192
|
||||
msgid "Whether this user should be treated as active. Unselect this instead of deleting accounts."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:202 core/models.py:202
|
||||
#: build/lib/core/models.py:204 core/models.py:204
|
||||
msgid "user"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:203 core/models.py:203
|
||||
#: build/lib/core/models.py:205 core/models.py:205
|
||||
msgid "users"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:359 build/lib/core/models.py:1281
|
||||
#: core/models.py:359 core/models.py:1281
|
||||
#: build/lib/core/models.py:361 build/lib/core/models.py:1284
|
||||
#: core/models.py:361 core/models.py:1284
|
||||
msgid "title"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:360 core/models.py:360
|
||||
#: build/lib/core/models.py:362 core/models.py:362
|
||||
msgid "excerpt"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:409 core/models.py:409
|
||||
#: build/lib/core/models.py:411 core/models.py:411
|
||||
msgid "Document"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:410 core/models.py:410
|
||||
#: build/lib/core/models.py:412 core/models.py:412
|
||||
msgid "Documents"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:422 build/lib/core/models.py:819 core/models.py:422
|
||||
#: core/models.py:819
|
||||
#: build/lib/core/models.py:424 build/lib/core/models.py:822 core/models.py:424
|
||||
#: core/models.py:822
|
||||
msgid "Untitled Document"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:854 core/models.py:854
|
||||
#: build/lib/core/models.py:857 core/models.py:857
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you!"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:858 core/models.py:858
|
||||
#: build/lib/core/models.py:861 core/models.py:861
|
||||
#, python-brace-format
|
||||
msgid "{name} invited you with the role \"{role}\" on the following document:"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:864 core/models.py:864
|
||||
#: build/lib/core/models.py:867 core/models.py:867
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you: {title}"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:964 core/models.py:964
|
||||
#: build/lib/core/models.py:967 core/models.py:967
|
||||
msgid "Document/user link trace"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:965 core/models.py:965
|
||||
#: build/lib/core/models.py:968 core/models.py:968
|
||||
msgid "Document/user link traces"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:971 core/models.py:971
|
||||
#: build/lib/core/models.py:974 core/models.py:974
|
||||
msgid "A link trace already exists for this document/user."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:994 core/models.py:994
|
||||
#: build/lib/core/models.py:997 core/models.py:997
|
||||
msgid "Document favorite"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:995 core/models.py:995
|
||||
#: build/lib/core/models.py:998 core/models.py:998
|
||||
msgid "Document favorites"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1001 core/models.py:1001
|
||||
#: build/lib/core/models.py:1004 core/models.py:1004
|
||||
msgid "This document is already targeted by a favorite relation instance for the same user."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1023 core/models.py:1023
|
||||
#: build/lib/core/models.py:1026 core/models.py:1026
|
||||
msgid "Document/user relation"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1024 core/models.py:1024
|
||||
#: build/lib/core/models.py:1027 core/models.py:1027
|
||||
msgid "Document/user relations"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1030 core/models.py:1030
|
||||
#: build/lib/core/models.py:1033 core/models.py:1033
|
||||
msgid "This user is already in this document."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1036 core/models.py:1036
|
||||
#: build/lib/core/models.py:1039 core/models.py:1039
|
||||
msgid "This team is already in this document."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1042 build/lib/core/models.py:1367
|
||||
#: core/models.py:1042 core/models.py:1367
|
||||
#: build/lib/core/models.py:1045 build/lib/core/models.py:1370
|
||||
#: core/models.py:1045 core/models.py:1370
|
||||
msgid "Either user or team must be set, not both."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1188 core/models.py:1188
|
||||
#: build/lib/core/models.py:1191 core/models.py:1191
|
||||
msgid "Document ask for access"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1189 core/models.py:1189
|
||||
#: build/lib/core/models.py:1192 core/models.py:1192
|
||||
msgid "Document ask for accesses"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1195 core/models.py:1195
|
||||
#: build/lib/core/models.py:1198 core/models.py:1198
|
||||
msgid "This user has already asked for access to this document."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1260 core/models.py:1260
|
||||
#: build/lib/core/models.py:1263 core/models.py:1263
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to a document!"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1264 core/models.py:1264
|
||||
#: build/lib/core/models.py:1267 core/models.py:1267
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to the following document:"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1270 core/models.py:1270
|
||||
#: build/lib/core/models.py:1273 core/models.py:1273
|
||||
#, python-brace-format
|
||||
msgid "{name} is asking for access to the document: {title}"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1282 core/models.py:1282
|
||||
#: build/lib/core/models.py:1285 core/models.py:1285
|
||||
msgid "description"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1283 core/models.py:1283
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
msgid "code"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1284 core/models.py:1284
|
||||
#: build/lib/core/models.py:1287 core/models.py:1287
|
||||
msgid "css"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
#: build/lib/core/models.py:1289 core/models.py:1289
|
||||
msgid "public"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1288 core/models.py:1288
|
||||
#: build/lib/core/models.py:1291 core/models.py:1291
|
||||
msgid "Whether this template is public for anyone to use."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1294 core/models.py:1294
|
||||
#: build/lib/core/models.py:1297 core/models.py:1297
|
||||
msgid "Template"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1295 core/models.py:1295
|
||||
#: build/lib/core/models.py:1298 core/models.py:1298
|
||||
msgid "Templates"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1348 core/models.py:1348
|
||||
#: build/lib/core/models.py:1351 core/models.py:1351
|
||||
msgid "Template/user relation"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1349 core/models.py:1349
|
||||
#: build/lib/core/models.py:1352 core/models.py:1352
|
||||
msgid "Template/user relations"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1355 core/models.py:1355
|
||||
#: build/lib/core/models.py:1358 core/models.py:1358
|
||||
msgid "This user is already in this template."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1361 core/models.py:1361
|
||||
#: build/lib/core/models.py:1364 core/models.py:1364
|
||||
msgid "This team is already in this template."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1438 core/models.py:1438
|
||||
#: build/lib/core/models.py:1441 core/models.py:1441
|
||||
msgid "email address"
|
||||
msgstr "e-postadress"
|
||||
|
||||
#: build/lib/core/models.py:1457 core/models.py:1457
|
||||
#: build/lib/core/models.py:1460 core/models.py:1460
|
||||
msgid "Document invitation"
|
||||
msgstr "Bjud in dokument"
|
||||
|
||||
#: build/lib/core/models.py:1458 core/models.py:1458
|
||||
#: build/lib/core/models.py:1461 core/models.py:1461
|
||||
msgid "Document invitations"
|
||||
msgstr "Inbjudningar dokument"
|
||||
|
||||
#: build/lib/core/models.py:1478 core/models.py:1478
|
||||
#: build/lib/core/models.py:1481 core/models.py:1481
|
||||
msgid "This email is already associated to a registered user."
|
||||
msgstr "Denna e-postadress är redan associerad med en registrerad användare."
|
||||
|
||||
#: core/templates/mail/html/template.html:162
|
||||
#: core/templates/mail/html/template.html:153
|
||||
#: core/templates/mail/text/template.txt:3
|
||||
msgid "Logo email"
|
||||
msgstr "Logotyp e-post"
|
||||
|
||||
#: core/templates/mail/html/template.html:209
|
||||
#: core/templates/mail/html/template.html:200
|
||||
#: core/templates/mail/text/template.txt:10
|
||||
msgid "Open"
|
||||
msgstr "Öppna"
|
||||
|
||||
#: core/templates/mail/html/template.html:226
|
||||
#: core/templates/mail/html/template.html:217
|
||||
#: core/templates/mail/text/template.txt:14
|
||||
msgid " Docs, your new essential tool for organizing, sharing and collaborating on your documents as a team. "
|
||||
msgstr ""
|
||||
|
||||
#: core/templates/mail/html/template.html:233
|
||||
#: core/templates/mail/html/template.html:224
|
||||
#: core/templates/mail/text/template.txt:16
|
||||
#, python-format
|
||||
msgid " Brought to you by %(brandname)s "
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: lasuite-docs\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-09-10 14:29+0000\n"
|
||||
"PO-Revision-Date: 2025-09-12 09:50\n"
|
||||
"POT-Creation-Date: 2025-10-23 11:01+0000\n"
|
||||
"PO-Revision-Date: 2025-11-10 09:54\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Turkish\n"
|
||||
"Language: tr_TR\n"
|
||||
@@ -17,20 +17,20 @@ msgstr ""
|
||||
"X-Crowdin-File: backend-impress.pot\n"
|
||||
"X-Crowdin-File-ID: 18\n"
|
||||
|
||||
#: build/lib/core/admin.py:37 core/admin.py:37
|
||||
#: build/lib/core/admin.py:36 core/admin.py:36
|
||||
msgid "Personal info"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/admin.py:50 build/lib/core/admin.py:138 core/admin.py:50
|
||||
#: core/admin.py:138
|
||||
#: build/lib/core/admin.py:49 build/lib/core/admin.py:137 core/admin.py:49
|
||||
#: core/admin.py:137
|
||||
msgid "Permissions"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/admin.py:62 core/admin.py:62
|
||||
#: build/lib/core/admin.py:61 core/admin.py:61
|
||||
msgid "Important dates"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/admin.py:148 core/admin.py:148
|
||||
#: build/lib/core/admin.py:147 core/admin.py:147
|
||||
msgid "Tree structure"
|
||||
msgstr ""
|
||||
|
||||
@@ -50,27 +50,36 @@ msgstr ""
|
||||
msgid "Favorite"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:487 core/api/serializers.py:487
|
||||
#: build/lib/core/api/serializers.py:496 core/api/serializers.py:496
|
||||
msgid "A new document was created on your behalf!"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:491 core/api/serializers.py:491
|
||||
#: build/lib/core/api/serializers.py:500 core/api/serializers.py:500
|
||||
msgid "You have been granted ownership of a new document:"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:628 core/api/serializers.py:628
|
||||
#: build/lib/core/api/serializers.py:536 core/api/serializers.py:536
|
||||
msgid "This field is required."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:547 core/api/serializers.py:547
|
||||
#, python-format
|
||||
msgid "Link reach '%(link_reach)s' is not allowed based on parent document configuration."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:693 core/api/serializers.py:693
|
||||
msgid "Body"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:631 core/api/serializers.py:631
|
||||
#: build/lib/core/api/serializers.py:696 core/api/serializers.py:696
|
||||
msgid "Body type"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:637 core/api/serializers.py:637
|
||||
#: build/lib/core/api/serializers.py:702 core/api/serializers.py:702
|
||||
msgid "Format"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/viewsets.py:965 core/api/viewsets.py:965
|
||||
#: build/lib/core/api/viewsets.py:1003 core/api/viewsets.py:1003
|
||||
#, python-brace-format
|
||||
msgid "copy of {title}"
|
||||
msgstr ""
|
||||
@@ -169,247 +178,247 @@ msgstr ""
|
||||
msgid "full name"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:151 core/models.py:151
|
||||
#: build/lib/core/models.py:152 core/models.py:152
|
||||
msgid "short name"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:153 core/models.py:153
|
||||
#: build/lib/core/models.py:155 core/models.py:155
|
||||
msgid "identity email address"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:158 core/models.py:158
|
||||
#: build/lib/core/models.py:160 core/models.py:160
|
||||
msgid "admin email address"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:165 core/models.py:165
|
||||
#: build/lib/core/models.py:167 core/models.py:167
|
||||
msgid "language"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:166 core/models.py:166
|
||||
#: build/lib/core/models.py:168 core/models.py:168
|
||||
msgid "The language in which the user wants to see the interface."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:174 core/models.py:174
|
||||
#: build/lib/core/models.py:176 core/models.py:176
|
||||
msgid "The timezone in which the user wants to see times."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:177 core/models.py:177
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
msgid "device"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
#: build/lib/core/models.py:181 core/models.py:181
|
||||
msgid "Whether the user is a device or a real user."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:182 core/models.py:182
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
msgid "staff status"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
#: build/lib/core/models.py:186 core/models.py:186
|
||||
msgid "Whether the user can log into this admin site."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:187 core/models.py:187
|
||||
#: build/lib/core/models.py:189 core/models.py:189
|
||||
msgid "active"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:190 core/models.py:190
|
||||
#: build/lib/core/models.py:192 core/models.py:192
|
||||
msgid "Whether this user should be treated as active. Unselect this instead of deleting accounts."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:202 core/models.py:202
|
||||
#: build/lib/core/models.py:204 core/models.py:204
|
||||
msgid "user"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:203 core/models.py:203
|
||||
#: build/lib/core/models.py:205 core/models.py:205
|
||||
msgid "users"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:359 build/lib/core/models.py:1281
|
||||
#: core/models.py:359 core/models.py:1281
|
||||
#: build/lib/core/models.py:361 build/lib/core/models.py:1284
|
||||
#: core/models.py:361 core/models.py:1284
|
||||
msgid "title"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:360 core/models.py:360
|
||||
#: build/lib/core/models.py:362 core/models.py:362
|
||||
msgid "excerpt"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:409 core/models.py:409
|
||||
#: build/lib/core/models.py:411 core/models.py:411
|
||||
msgid "Document"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:410 core/models.py:410
|
||||
#: build/lib/core/models.py:412 core/models.py:412
|
||||
msgid "Documents"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:422 build/lib/core/models.py:819 core/models.py:422
|
||||
#: core/models.py:819
|
||||
#: build/lib/core/models.py:424 build/lib/core/models.py:822 core/models.py:424
|
||||
#: core/models.py:822
|
||||
msgid "Untitled Document"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:854 core/models.py:854
|
||||
#: build/lib/core/models.py:857 core/models.py:857
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you!"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:858 core/models.py:858
|
||||
#: build/lib/core/models.py:861 core/models.py:861
|
||||
#, python-brace-format
|
||||
msgid "{name} invited you with the role \"{role}\" on the following document:"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:864 core/models.py:864
|
||||
#: build/lib/core/models.py:867 core/models.py:867
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you: {title}"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:964 core/models.py:964
|
||||
#: build/lib/core/models.py:967 core/models.py:967
|
||||
msgid "Document/user link trace"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:965 core/models.py:965
|
||||
#: build/lib/core/models.py:968 core/models.py:968
|
||||
msgid "Document/user link traces"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:971 core/models.py:971
|
||||
#: build/lib/core/models.py:974 core/models.py:974
|
||||
msgid "A link trace already exists for this document/user."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:994 core/models.py:994
|
||||
#: build/lib/core/models.py:997 core/models.py:997
|
||||
msgid "Document favorite"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:995 core/models.py:995
|
||||
#: build/lib/core/models.py:998 core/models.py:998
|
||||
msgid "Document favorites"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1001 core/models.py:1001
|
||||
#: build/lib/core/models.py:1004 core/models.py:1004
|
||||
msgid "This document is already targeted by a favorite relation instance for the same user."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1023 core/models.py:1023
|
||||
#: build/lib/core/models.py:1026 core/models.py:1026
|
||||
msgid "Document/user relation"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1024 core/models.py:1024
|
||||
#: build/lib/core/models.py:1027 core/models.py:1027
|
||||
msgid "Document/user relations"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1030 core/models.py:1030
|
||||
#: build/lib/core/models.py:1033 core/models.py:1033
|
||||
msgid "This user is already in this document."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1036 core/models.py:1036
|
||||
#: build/lib/core/models.py:1039 core/models.py:1039
|
||||
msgid "This team is already in this document."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1042 build/lib/core/models.py:1367
|
||||
#: core/models.py:1042 core/models.py:1367
|
||||
#: build/lib/core/models.py:1045 build/lib/core/models.py:1370
|
||||
#: core/models.py:1045 core/models.py:1370
|
||||
msgid "Either user or team must be set, not both."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1188 core/models.py:1188
|
||||
#: build/lib/core/models.py:1191 core/models.py:1191
|
||||
msgid "Document ask for access"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1189 core/models.py:1189
|
||||
#: build/lib/core/models.py:1192 core/models.py:1192
|
||||
msgid "Document ask for accesses"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1195 core/models.py:1195
|
||||
#: build/lib/core/models.py:1198 core/models.py:1198
|
||||
msgid "This user has already asked for access to this document."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1260 core/models.py:1260
|
||||
#: build/lib/core/models.py:1263 core/models.py:1263
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to a document!"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1264 core/models.py:1264
|
||||
#: build/lib/core/models.py:1267 core/models.py:1267
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to the following document:"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1270 core/models.py:1270
|
||||
#: build/lib/core/models.py:1273 core/models.py:1273
|
||||
#, python-brace-format
|
||||
msgid "{name} is asking for access to the document: {title}"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1282 core/models.py:1282
|
||||
#: build/lib/core/models.py:1285 core/models.py:1285
|
||||
msgid "description"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1283 core/models.py:1283
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
msgid "code"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1284 core/models.py:1284
|
||||
#: build/lib/core/models.py:1287 core/models.py:1287
|
||||
msgid "css"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
#: build/lib/core/models.py:1289 core/models.py:1289
|
||||
msgid "public"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1288 core/models.py:1288
|
||||
#: build/lib/core/models.py:1291 core/models.py:1291
|
||||
msgid "Whether this template is public for anyone to use."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1294 core/models.py:1294
|
||||
#: build/lib/core/models.py:1297 core/models.py:1297
|
||||
msgid "Template"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1295 core/models.py:1295
|
||||
#: build/lib/core/models.py:1298 core/models.py:1298
|
||||
msgid "Templates"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1348 core/models.py:1348
|
||||
#: build/lib/core/models.py:1351 core/models.py:1351
|
||||
msgid "Template/user relation"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1349 core/models.py:1349
|
||||
#: build/lib/core/models.py:1352 core/models.py:1352
|
||||
msgid "Template/user relations"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1355 core/models.py:1355
|
||||
#: build/lib/core/models.py:1358 core/models.py:1358
|
||||
msgid "This user is already in this template."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1361 core/models.py:1361
|
||||
#: build/lib/core/models.py:1364 core/models.py:1364
|
||||
msgid "This team is already in this template."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1438 core/models.py:1438
|
||||
#: build/lib/core/models.py:1441 core/models.py:1441
|
||||
msgid "email address"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1457 core/models.py:1457
|
||||
#: build/lib/core/models.py:1460 core/models.py:1460
|
||||
msgid "Document invitation"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1458 core/models.py:1458
|
||||
#: build/lib/core/models.py:1461 core/models.py:1461
|
||||
msgid "Document invitations"
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/models.py:1478 core/models.py:1478
|
||||
#: build/lib/core/models.py:1481 core/models.py:1481
|
||||
msgid "This email is already associated to a registered user."
|
||||
msgstr ""
|
||||
|
||||
#: core/templates/mail/html/template.html:162
|
||||
#: core/templates/mail/html/template.html:153
|
||||
#: core/templates/mail/text/template.txt:3
|
||||
msgid "Logo email"
|
||||
msgstr ""
|
||||
|
||||
#: core/templates/mail/html/template.html:209
|
||||
#: core/templates/mail/html/template.html:200
|
||||
#: core/templates/mail/text/template.txt:10
|
||||
msgid "Open"
|
||||
msgstr ""
|
||||
|
||||
#: core/templates/mail/html/template.html:226
|
||||
#: core/templates/mail/html/template.html:217
|
||||
#: core/templates/mail/text/template.txt:14
|
||||
msgid " Docs, your new essential tool for organizing, sharing and collaborating on your documents as a team. "
|
||||
msgstr ""
|
||||
|
||||
#: core/templates/mail/html/template.html:233
|
||||
#: core/templates/mail/html/template.html:224
|
||||
#: core/templates/mail/text/template.txt:16
|
||||
#, python-format
|
||||
msgid " Brought to you by %(brandname)s "
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: lasuite-docs\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-09-10 14:29+0000\n"
|
||||
"PO-Revision-Date: 2025-09-12 09:50\n"
|
||||
"POT-Creation-Date: 2025-10-23 11:01+0000\n"
|
||||
"PO-Revision-Date: 2025-11-10 09:54\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Ukrainian\n"
|
||||
"Language: uk_UA\n"
|
||||
@@ -17,20 +17,20 @@ msgstr ""
|
||||
"X-Crowdin-File: backend-impress.pot\n"
|
||||
"X-Crowdin-File-ID: 18\n"
|
||||
|
||||
#: build/lib/core/admin.py:37 core/admin.py:37
|
||||
#: build/lib/core/admin.py:36 core/admin.py:36
|
||||
msgid "Personal info"
|
||||
msgstr "Особисті дані"
|
||||
|
||||
#: build/lib/core/admin.py:50 build/lib/core/admin.py:138 core/admin.py:50
|
||||
#: core/admin.py:138
|
||||
#: build/lib/core/admin.py:49 build/lib/core/admin.py:137 core/admin.py:49
|
||||
#: core/admin.py:137
|
||||
msgid "Permissions"
|
||||
msgstr "Дозволи"
|
||||
|
||||
#: build/lib/core/admin.py:62 core/admin.py:62
|
||||
#: build/lib/core/admin.py:61 core/admin.py:61
|
||||
msgid "Important dates"
|
||||
msgstr "Важливі дати"
|
||||
|
||||
#: build/lib/core/admin.py:148 core/admin.py:148
|
||||
#: build/lib/core/admin.py:147 core/admin.py:147
|
||||
msgid "Tree structure"
|
||||
msgstr "Ієрархічна структура"
|
||||
|
||||
@@ -50,27 +50,36 @@ msgstr "Приховано"
|
||||
msgid "Favorite"
|
||||
msgstr "Обране"
|
||||
|
||||
#: build/lib/core/api/serializers.py:487 core/api/serializers.py:487
|
||||
#: build/lib/core/api/serializers.py:496 core/api/serializers.py:496
|
||||
msgid "A new document was created on your behalf!"
|
||||
msgstr "Новий документ був створений від вашого імені!"
|
||||
|
||||
#: build/lib/core/api/serializers.py:491 core/api/serializers.py:491
|
||||
#: build/lib/core/api/serializers.py:500 core/api/serializers.py:500
|
||||
msgid "You have been granted ownership of a new document:"
|
||||
msgstr "Ви тепер є власником нового документа:"
|
||||
|
||||
#: build/lib/core/api/serializers.py:628 core/api/serializers.py:628
|
||||
#: build/lib/core/api/serializers.py:536 core/api/serializers.py:536
|
||||
msgid "This field is required."
|
||||
msgstr "Це поле є обов’язковим."
|
||||
|
||||
#: build/lib/core/api/serializers.py:547 core/api/serializers.py:547
|
||||
#, python-format
|
||||
msgid "Link reach '%(link_reach)s' is not allowed based on parent document configuration."
|
||||
msgstr "Доступ до посилання '%(link_reach)s' заборонено на основі конфігурації батьківського документа."
|
||||
|
||||
#: build/lib/core/api/serializers.py:693 core/api/serializers.py:693
|
||||
msgid "Body"
|
||||
msgstr "Вміст"
|
||||
|
||||
#: build/lib/core/api/serializers.py:631 core/api/serializers.py:631
|
||||
#: build/lib/core/api/serializers.py:696 core/api/serializers.py:696
|
||||
msgid "Body type"
|
||||
msgstr "Тип вмісту"
|
||||
|
||||
#: build/lib/core/api/serializers.py:637 core/api/serializers.py:637
|
||||
#: build/lib/core/api/serializers.py:702 core/api/serializers.py:702
|
||||
msgid "Format"
|
||||
msgstr "Формат"
|
||||
|
||||
#: build/lib/core/api/viewsets.py:965 core/api/viewsets.py:965
|
||||
#: build/lib/core/api/viewsets.py:1003 core/api/viewsets.py:1003
|
||||
#, python-brace-format
|
||||
msgid "copy of {title}"
|
||||
msgstr "копія {title}"
|
||||
@@ -169,247 +178,247 @@ msgstr "Обов'язкове. 255 символів або менше. Тіль
|
||||
msgid "full name"
|
||||
msgstr "повне ім'я"
|
||||
|
||||
#: build/lib/core/models.py:151 core/models.py:151
|
||||
#: build/lib/core/models.py:152 core/models.py:152
|
||||
msgid "short name"
|
||||
msgstr "коротке ім'я"
|
||||
|
||||
#: build/lib/core/models.py:153 core/models.py:153
|
||||
#: build/lib/core/models.py:155 core/models.py:155
|
||||
msgid "identity email address"
|
||||
msgstr "адреса електронної пошти особи"
|
||||
|
||||
#: build/lib/core/models.py:158 core/models.py:158
|
||||
#: build/lib/core/models.py:160 core/models.py:160
|
||||
msgid "admin email address"
|
||||
msgstr "електронна адреса адміністратора"
|
||||
|
||||
#: build/lib/core/models.py:165 core/models.py:165
|
||||
#: build/lib/core/models.py:167 core/models.py:167
|
||||
msgid "language"
|
||||
msgstr "мова"
|
||||
|
||||
#: build/lib/core/models.py:166 core/models.py:166
|
||||
#: build/lib/core/models.py:168 core/models.py:168
|
||||
msgid "The language in which the user wants to see the interface."
|
||||
msgstr "Мова, якою користувач хоче бачити інтерфейс."
|
||||
|
||||
#: build/lib/core/models.py:174 core/models.py:174
|
||||
#: build/lib/core/models.py:176 core/models.py:176
|
||||
msgid "The timezone in which the user wants to see times."
|
||||
msgstr "Часовий пояс, в якому користувач хоче бачити час."
|
||||
|
||||
#: build/lib/core/models.py:177 core/models.py:177
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
msgid "device"
|
||||
msgstr "пристрій"
|
||||
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
#: build/lib/core/models.py:181 core/models.py:181
|
||||
msgid "Whether the user is a device or a real user."
|
||||
msgstr "Чи є користувач пристроєм чи реальним користувачем."
|
||||
|
||||
#: build/lib/core/models.py:182 core/models.py:182
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
msgid "staff status"
|
||||
msgstr "статус співробітника"
|
||||
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
#: build/lib/core/models.py:186 core/models.py:186
|
||||
msgid "Whether the user can log into this admin site."
|
||||
msgstr "Чи може користувач увійти на цей сайт адміністратора."
|
||||
|
||||
#: build/lib/core/models.py:187 core/models.py:187
|
||||
#: build/lib/core/models.py:189 core/models.py:189
|
||||
msgid "active"
|
||||
msgstr "активний"
|
||||
|
||||
#: build/lib/core/models.py:190 core/models.py:190
|
||||
#: build/lib/core/models.py:192 core/models.py:192
|
||||
msgid "Whether this user should be treated as active. Unselect this instead of deleting accounts."
|
||||
msgstr "Чи слід ставитися до цього користувача як до активного. Зніміть вибір замість видалення облікового запису."
|
||||
|
||||
#: build/lib/core/models.py:202 core/models.py:202
|
||||
#: build/lib/core/models.py:204 core/models.py:204
|
||||
msgid "user"
|
||||
msgstr "користувач"
|
||||
|
||||
#: build/lib/core/models.py:203 core/models.py:203
|
||||
#: build/lib/core/models.py:205 core/models.py:205
|
||||
msgid "users"
|
||||
msgstr "користувачі"
|
||||
|
||||
#: build/lib/core/models.py:359 build/lib/core/models.py:1281
|
||||
#: core/models.py:359 core/models.py:1281
|
||||
#: build/lib/core/models.py:361 build/lib/core/models.py:1284
|
||||
#: core/models.py:361 core/models.py:1284
|
||||
msgid "title"
|
||||
msgstr "заголовок"
|
||||
|
||||
#: build/lib/core/models.py:360 core/models.py:360
|
||||
#: build/lib/core/models.py:362 core/models.py:362
|
||||
msgid "excerpt"
|
||||
msgstr "уривок"
|
||||
|
||||
#: build/lib/core/models.py:409 core/models.py:409
|
||||
#: build/lib/core/models.py:411 core/models.py:411
|
||||
msgid "Document"
|
||||
msgstr "Документ"
|
||||
|
||||
#: build/lib/core/models.py:410 core/models.py:410
|
||||
#: build/lib/core/models.py:412 core/models.py:412
|
||||
msgid "Documents"
|
||||
msgstr "Документи"
|
||||
|
||||
#: build/lib/core/models.py:422 build/lib/core/models.py:819 core/models.py:422
|
||||
#: core/models.py:819
|
||||
#: build/lib/core/models.py:424 build/lib/core/models.py:822 core/models.py:424
|
||||
#: core/models.py:822
|
||||
msgid "Untitled Document"
|
||||
msgstr "Документ без назви"
|
||||
|
||||
#: build/lib/core/models.py:854 core/models.py:854
|
||||
#: build/lib/core/models.py:857 core/models.py:857
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you!"
|
||||
msgstr "{name} ділиться з вами документом!"
|
||||
|
||||
#: build/lib/core/models.py:858 core/models.py:858
|
||||
#: build/lib/core/models.py:861 core/models.py:861
|
||||
#, python-brace-format
|
||||
msgid "{name} invited you with the role \"{role}\" on the following document:"
|
||||
msgstr "{name} запрошує вас для роботи з документом із роллю \"{role}\":"
|
||||
|
||||
#: build/lib/core/models.py:864 core/models.py:864
|
||||
#: build/lib/core/models.py:867 core/models.py:867
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you: {title}"
|
||||
msgstr "{name} ділиться з вами документом: {title}"
|
||||
|
||||
#: build/lib/core/models.py:964 core/models.py:964
|
||||
#: build/lib/core/models.py:967 core/models.py:967
|
||||
msgid "Document/user link trace"
|
||||
msgstr "Трасування посилання Документ/користувач"
|
||||
|
||||
#: build/lib/core/models.py:965 core/models.py:965
|
||||
#: build/lib/core/models.py:968 core/models.py:968
|
||||
msgid "Document/user link traces"
|
||||
msgstr "Трасування посилань Документ/користувач"
|
||||
|
||||
#: build/lib/core/models.py:971 core/models.py:971
|
||||
#: build/lib/core/models.py:974 core/models.py:974
|
||||
msgid "A link trace already exists for this document/user."
|
||||
msgstr "Відстеження вже існуючих посилань для цього документа/користувача."
|
||||
|
||||
#: build/lib/core/models.py:994 core/models.py:994
|
||||
#: build/lib/core/models.py:997 core/models.py:997
|
||||
msgid "Document favorite"
|
||||
msgstr "Обраний документ"
|
||||
|
||||
#: build/lib/core/models.py:995 core/models.py:995
|
||||
#: build/lib/core/models.py:998 core/models.py:998
|
||||
msgid "Document favorites"
|
||||
msgstr "Обрані документи"
|
||||
|
||||
#: build/lib/core/models.py:1001 core/models.py:1001
|
||||
#: build/lib/core/models.py:1004 core/models.py:1004
|
||||
msgid "This document is already targeted by a favorite relation instance for the same user."
|
||||
msgstr "Цей документ вже вказаний як обраний для одного користувача."
|
||||
|
||||
#: build/lib/core/models.py:1023 core/models.py:1023
|
||||
#: build/lib/core/models.py:1026 core/models.py:1026
|
||||
msgid "Document/user relation"
|
||||
msgstr "Відносини документ/користувач"
|
||||
|
||||
#: build/lib/core/models.py:1024 core/models.py:1024
|
||||
#: build/lib/core/models.py:1027 core/models.py:1027
|
||||
msgid "Document/user relations"
|
||||
msgstr "Відносини документ/користувач"
|
||||
|
||||
#: build/lib/core/models.py:1030 core/models.py:1030
|
||||
#: build/lib/core/models.py:1033 core/models.py:1033
|
||||
msgid "This user is already in this document."
|
||||
msgstr "Цей користувач вже має доступ до цього документу."
|
||||
|
||||
#: build/lib/core/models.py:1036 core/models.py:1036
|
||||
#: build/lib/core/models.py:1039 core/models.py:1039
|
||||
msgid "This team is already in this document."
|
||||
msgstr "Ця команда вже має доступ до цього документа."
|
||||
|
||||
#: build/lib/core/models.py:1042 build/lib/core/models.py:1367
|
||||
#: core/models.py:1042 core/models.py:1367
|
||||
#: build/lib/core/models.py:1045 build/lib/core/models.py:1370
|
||||
#: core/models.py:1045 core/models.py:1370
|
||||
msgid "Either user or team must be set, not both."
|
||||
msgstr "Вкажіть користувача або команду, а не обох."
|
||||
|
||||
#: build/lib/core/models.py:1188 core/models.py:1188
|
||||
#: build/lib/core/models.py:1191 core/models.py:1191
|
||||
msgid "Document ask for access"
|
||||
msgstr "Запит доступу до документа"
|
||||
|
||||
#: build/lib/core/models.py:1189 core/models.py:1189
|
||||
#: build/lib/core/models.py:1192 core/models.py:1192
|
||||
msgid "Document ask for accesses"
|
||||
msgstr "Запит доступу для документа"
|
||||
|
||||
#: build/lib/core/models.py:1195 core/models.py:1195
|
||||
#: build/lib/core/models.py:1198 core/models.py:1198
|
||||
msgid "This user has already asked for access to this document."
|
||||
msgstr "Цей користувач вже попросив доступ до цього документа."
|
||||
|
||||
#: build/lib/core/models.py:1260 core/models.py:1260
|
||||
#: build/lib/core/models.py:1263 core/models.py:1263
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to a document!"
|
||||
msgstr "{name} хоче отримати доступ до документа!"
|
||||
|
||||
#: build/lib/core/models.py:1264 core/models.py:1264
|
||||
#: build/lib/core/models.py:1267 core/models.py:1267
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to the following document:"
|
||||
msgstr "{name} бажає отримати доступ до наступного документа:"
|
||||
|
||||
#: build/lib/core/models.py:1270 core/models.py:1270
|
||||
#: build/lib/core/models.py:1273 core/models.py:1273
|
||||
#, python-brace-format
|
||||
msgid "{name} is asking for access to the document: {title}"
|
||||
msgstr "{name} запитує доступ до документа: {title}"
|
||||
|
||||
#: build/lib/core/models.py:1282 core/models.py:1282
|
||||
#: build/lib/core/models.py:1285 core/models.py:1285
|
||||
msgid "description"
|
||||
msgstr "опис"
|
||||
|
||||
#: build/lib/core/models.py:1283 core/models.py:1283
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
msgid "code"
|
||||
msgstr "код"
|
||||
|
||||
#: build/lib/core/models.py:1284 core/models.py:1284
|
||||
#: build/lib/core/models.py:1287 core/models.py:1287
|
||||
msgid "css"
|
||||
msgstr "css"
|
||||
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
#: build/lib/core/models.py:1289 core/models.py:1289
|
||||
msgid "public"
|
||||
msgstr "публічне"
|
||||
|
||||
#: build/lib/core/models.py:1288 core/models.py:1288
|
||||
#: build/lib/core/models.py:1291 core/models.py:1291
|
||||
msgid "Whether this template is public for anyone to use."
|
||||
msgstr "Чи є цей шаблон публічним для будь-кого користувача."
|
||||
|
||||
#: build/lib/core/models.py:1294 core/models.py:1294
|
||||
#: build/lib/core/models.py:1297 core/models.py:1297
|
||||
msgid "Template"
|
||||
msgstr "Шаблон"
|
||||
|
||||
#: build/lib/core/models.py:1295 core/models.py:1295
|
||||
#: build/lib/core/models.py:1298 core/models.py:1298
|
||||
msgid "Templates"
|
||||
msgstr "Шаблони"
|
||||
|
||||
#: build/lib/core/models.py:1348 core/models.py:1348
|
||||
#: build/lib/core/models.py:1351 core/models.py:1351
|
||||
msgid "Template/user relation"
|
||||
msgstr "Відношення шаблон/користувач"
|
||||
|
||||
#: build/lib/core/models.py:1349 core/models.py:1349
|
||||
#: build/lib/core/models.py:1352 core/models.py:1352
|
||||
msgid "Template/user relations"
|
||||
msgstr "Відношення шаблон/користувач"
|
||||
|
||||
#: build/lib/core/models.py:1355 core/models.py:1355
|
||||
#: build/lib/core/models.py:1358 core/models.py:1358
|
||||
msgid "This user is already in this template."
|
||||
msgstr "Цей користувач вже має доступ до цього шаблону."
|
||||
|
||||
#: build/lib/core/models.py:1361 core/models.py:1361
|
||||
#: build/lib/core/models.py:1364 core/models.py:1364
|
||||
msgid "This team is already in this template."
|
||||
msgstr "Ця команда вже має доступ до цього шаблону."
|
||||
|
||||
#: build/lib/core/models.py:1438 core/models.py:1438
|
||||
#: build/lib/core/models.py:1441 core/models.py:1441
|
||||
msgid "email address"
|
||||
msgstr "електронна адреса"
|
||||
|
||||
#: build/lib/core/models.py:1457 core/models.py:1457
|
||||
#: build/lib/core/models.py:1460 core/models.py:1460
|
||||
msgid "Document invitation"
|
||||
msgstr "Запрошення до редагування документа"
|
||||
|
||||
#: build/lib/core/models.py:1458 core/models.py:1458
|
||||
#: build/lib/core/models.py:1461 core/models.py:1461
|
||||
msgid "Document invitations"
|
||||
msgstr "Запрошення до редагування документів"
|
||||
|
||||
#: build/lib/core/models.py:1478 core/models.py:1478
|
||||
#: build/lib/core/models.py:1481 core/models.py:1481
|
||||
msgid "This email is already associated to a registered user."
|
||||
msgstr "Ця електронна пошта вже пов'язана з зареєстрованим користувачем."
|
||||
|
||||
#: core/templates/mail/html/template.html:162
|
||||
#: core/templates/mail/html/template.html:153
|
||||
#: core/templates/mail/text/template.txt:3
|
||||
msgid "Logo email"
|
||||
msgstr "Логотип пошти"
|
||||
|
||||
#: core/templates/mail/html/template.html:209
|
||||
#: core/templates/mail/html/template.html:200
|
||||
#: core/templates/mail/text/template.txt:10
|
||||
msgid "Open"
|
||||
msgstr "Відкрити"
|
||||
|
||||
#: core/templates/mail/html/template.html:226
|
||||
#: core/templates/mail/html/template.html:217
|
||||
#: core/templates/mail/text/template.txt:14
|
||||
msgid " Docs, your new essential tool for organizing, sharing and collaborating on your documents as a team. "
|
||||
msgstr " Docs, ваш новий важливий інструмент для організації, обміну та командної співпраці над вашими документами. "
|
||||
|
||||
#: core/templates/mail/html/template.html:233
|
||||
#: core/templates/mail/html/template.html:224
|
||||
#: core/templates/mail/text/template.txt:16
|
||||
#, python-format
|
||||
msgid " Brought to you by %(brandname)s "
|
||||
|
||||
@@ -2,8 +2,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: lasuite-docs\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-09-10 14:29+0000\n"
|
||||
"PO-Revision-Date: 2025-09-12 09:50\n"
|
||||
"POT-Creation-Date: 2025-10-23 11:01+0000\n"
|
||||
"PO-Revision-Date: 2025-11-10 09:54\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Chinese Simplified\n"
|
||||
"Language: zh_CN\n"
|
||||
@@ -17,20 +17,20 @@ msgstr ""
|
||||
"X-Crowdin-File: backend-impress.pot\n"
|
||||
"X-Crowdin-File-ID: 18\n"
|
||||
|
||||
#: build/lib/core/admin.py:37 core/admin.py:37
|
||||
#: build/lib/core/admin.py:36 core/admin.py:36
|
||||
msgid "Personal info"
|
||||
msgstr "个人信息"
|
||||
|
||||
#: build/lib/core/admin.py:50 build/lib/core/admin.py:138 core/admin.py:50
|
||||
#: core/admin.py:138
|
||||
#: build/lib/core/admin.py:49 build/lib/core/admin.py:137 core/admin.py:49
|
||||
#: core/admin.py:137
|
||||
msgid "Permissions"
|
||||
msgstr "权限"
|
||||
|
||||
#: build/lib/core/admin.py:62 core/admin.py:62
|
||||
#: build/lib/core/admin.py:61 core/admin.py:61
|
||||
msgid "Important dates"
|
||||
msgstr "重要日期"
|
||||
|
||||
#: build/lib/core/admin.py:148 core/admin.py:148
|
||||
#: build/lib/core/admin.py:147 core/admin.py:147
|
||||
msgid "Tree structure"
|
||||
msgstr "树状结构"
|
||||
|
||||
@@ -44,33 +44,42 @@ msgstr "创建者是我"
|
||||
|
||||
#: build/lib/core/api/filters.py:64 core/api/filters.py:64
|
||||
msgid "Masked"
|
||||
msgstr ""
|
||||
msgstr "已屏蔽"
|
||||
|
||||
#: build/lib/core/api/filters.py:67 core/api/filters.py:67
|
||||
msgid "Favorite"
|
||||
msgstr "收藏"
|
||||
|
||||
#: build/lib/core/api/serializers.py:487 core/api/serializers.py:487
|
||||
#: build/lib/core/api/serializers.py:496 core/api/serializers.py:496
|
||||
msgid "A new document was created on your behalf!"
|
||||
msgstr "已为您创建了一份新文档!"
|
||||
|
||||
#: build/lib/core/api/serializers.py:491 core/api/serializers.py:491
|
||||
#: build/lib/core/api/serializers.py:500 core/api/serializers.py:500
|
||||
msgid "You have been granted ownership of a new document:"
|
||||
msgstr "您已被授予新文档的所有权:"
|
||||
|
||||
#: build/lib/core/api/serializers.py:628 core/api/serializers.py:628
|
||||
#: build/lib/core/api/serializers.py:536 core/api/serializers.py:536
|
||||
msgid "This field is required."
|
||||
msgstr "必填字段。"
|
||||
|
||||
#: build/lib/core/api/serializers.py:547 core/api/serializers.py:547
|
||||
#, python-format
|
||||
msgid "Link reach '%(link_reach)s' is not allowed based on parent document configuration."
|
||||
msgstr ""
|
||||
|
||||
#: build/lib/core/api/serializers.py:693 core/api/serializers.py:693
|
||||
msgid "Body"
|
||||
msgstr "正文"
|
||||
|
||||
#: build/lib/core/api/serializers.py:631 core/api/serializers.py:631
|
||||
#: build/lib/core/api/serializers.py:696 core/api/serializers.py:696
|
||||
msgid "Body type"
|
||||
msgstr "正文类型"
|
||||
|
||||
#: build/lib/core/api/serializers.py:637 core/api/serializers.py:637
|
||||
#: build/lib/core/api/serializers.py:702 core/api/serializers.py:702
|
||||
msgid "Format"
|
||||
msgstr "格式"
|
||||
|
||||
#: build/lib/core/api/viewsets.py:965 core/api/viewsets.py:965
|
||||
#: build/lib/core/api/viewsets.py:1003 core/api/viewsets.py:1003
|
||||
#, python-brace-format
|
||||
msgid "copy of {title}"
|
||||
msgstr "{title} 的副本"
|
||||
@@ -163,253 +172,253 @@ msgstr "sub"
|
||||
|
||||
#: build/lib/core/models.py:142 core/models.py:142
|
||||
msgid "Required. 255 characters or fewer. ASCII characters only."
|
||||
msgstr ""
|
||||
msgstr "必填项。限255个字符以内。仅支持ASCII字符。"
|
||||
|
||||
#: build/lib/core/models.py:150 core/models.py:150
|
||||
msgid "full name"
|
||||
msgstr "全名"
|
||||
|
||||
#: build/lib/core/models.py:151 core/models.py:151
|
||||
#: build/lib/core/models.py:152 core/models.py:152
|
||||
msgid "short name"
|
||||
msgstr "简称"
|
||||
|
||||
#: build/lib/core/models.py:153 core/models.py:153
|
||||
#: build/lib/core/models.py:155 core/models.py:155
|
||||
msgid "identity email address"
|
||||
msgstr "身份电子邮件地址"
|
||||
|
||||
#: build/lib/core/models.py:158 core/models.py:158
|
||||
#: build/lib/core/models.py:160 core/models.py:160
|
||||
msgid "admin email address"
|
||||
msgstr "管理员电子邮件地址"
|
||||
|
||||
#: build/lib/core/models.py:165 core/models.py:165
|
||||
#: build/lib/core/models.py:167 core/models.py:167
|
||||
msgid "language"
|
||||
msgstr "语言"
|
||||
|
||||
#: build/lib/core/models.py:166 core/models.py:166
|
||||
#: build/lib/core/models.py:168 core/models.py:168
|
||||
msgid "The language in which the user wants to see the interface."
|
||||
msgstr "用户希望看到的界面语言。"
|
||||
|
||||
#: build/lib/core/models.py:174 core/models.py:174
|
||||
#: build/lib/core/models.py:176 core/models.py:176
|
||||
msgid "The timezone in which the user wants to see times."
|
||||
msgstr "用户查看时间希望的时区。"
|
||||
|
||||
#: build/lib/core/models.py:177 core/models.py:177
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
msgid "device"
|
||||
msgstr "设备"
|
||||
|
||||
#: build/lib/core/models.py:179 core/models.py:179
|
||||
#: build/lib/core/models.py:181 core/models.py:181
|
||||
msgid "Whether the user is a device or a real user."
|
||||
msgstr "用户是设备还是真实用户。"
|
||||
|
||||
#: build/lib/core/models.py:182 core/models.py:182
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
msgid "staff status"
|
||||
msgstr "员工状态"
|
||||
|
||||
#: build/lib/core/models.py:184 core/models.py:184
|
||||
#: build/lib/core/models.py:186 core/models.py:186
|
||||
msgid "Whether the user can log into this admin site."
|
||||
msgstr "用户是否可以登录该管理员站点。"
|
||||
|
||||
#: build/lib/core/models.py:187 core/models.py:187
|
||||
#: build/lib/core/models.py:189 core/models.py:189
|
||||
msgid "active"
|
||||
msgstr "激活"
|
||||
|
||||
#: build/lib/core/models.py:190 core/models.py:190
|
||||
#: build/lib/core/models.py:192 core/models.py:192
|
||||
msgid "Whether this user should be treated as active. Unselect this instead of deleting accounts."
|
||||
msgstr "是否应将此用户视为活跃用户。取消选择此选项而不是删除账户。"
|
||||
|
||||
#: build/lib/core/models.py:202 core/models.py:202
|
||||
#: build/lib/core/models.py:204 core/models.py:204
|
||||
msgid "user"
|
||||
msgstr "用户"
|
||||
|
||||
#: build/lib/core/models.py:203 core/models.py:203
|
||||
#: build/lib/core/models.py:205 core/models.py:205
|
||||
msgid "users"
|
||||
msgstr "个用户"
|
||||
|
||||
#: build/lib/core/models.py:359 build/lib/core/models.py:1281
|
||||
#: core/models.py:359 core/models.py:1281
|
||||
#: build/lib/core/models.py:361 build/lib/core/models.py:1284
|
||||
#: core/models.py:361 core/models.py:1284
|
||||
msgid "title"
|
||||
msgstr "标题"
|
||||
|
||||
#: build/lib/core/models.py:360 core/models.py:360
|
||||
#: build/lib/core/models.py:362 core/models.py:362
|
||||
msgid "excerpt"
|
||||
msgstr "摘要"
|
||||
|
||||
#: build/lib/core/models.py:409 core/models.py:409
|
||||
#: build/lib/core/models.py:411 core/models.py:411
|
||||
msgid "Document"
|
||||
msgstr "文档"
|
||||
|
||||
#: build/lib/core/models.py:410 core/models.py:410
|
||||
#: build/lib/core/models.py:412 core/models.py:412
|
||||
msgid "Documents"
|
||||
msgstr "个文档"
|
||||
|
||||
#: build/lib/core/models.py:422 build/lib/core/models.py:819 core/models.py:422
|
||||
#: core/models.py:819
|
||||
#: build/lib/core/models.py:424 build/lib/core/models.py:822 core/models.py:424
|
||||
#: core/models.py:822
|
||||
msgid "Untitled Document"
|
||||
msgstr "未命名文档"
|
||||
|
||||
#: build/lib/core/models.py:854 core/models.py:854
|
||||
#: build/lib/core/models.py:857 core/models.py:857
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you!"
|
||||
msgstr "{name} 与您共享了一个文档!"
|
||||
|
||||
#: build/lib/core/models.py:858 core/models.py:858
|
||||
#: build/lib/core/models.py:861 core/models.py:861
|
||||
#, python-brace-format
|
||||
msgid "{name} invited you with the role \"{role}\" on the following document:"
|
||||
msgstr "{name} 邀请您以“{role}”角色访问以下文档:"
|
||||
|
||||
#: build/lib/core/models.py:864 core/models.py:864
|
||||
#: build/lib/core/models.py:867 core/models.py:867
|
||||
#, python-brace-format
|
||||
msgid "{name} shared a document with you: {title}"
|
||||
msgstr "{name} 与您共享了一个文档:{title}"
|
||||
|
||||
#: build/lib/core/models.py:964 core/models.py:964
|
||||
#: build/lib/core/models.py:967 core/models.py:967
|
||||
msgid "Document/user link trace"
|
||||
msgstr "文档/用户链接跟踪"
|
||||
|
||||
#: build/lib/core/models.py:965 core/models.py:965
|
||||
#: build/lib/core/models.py:968 core/models.py:968
|
||||
msgid "Document/user link traces"
|
||||
msgstr "个文档/用户链接跟踪"
|
||||
|
||||
#: build/lib/core/models.py:971 core/models.py:971
|
||||
#: build/lib/core/models.py:974 core/models.py:974
|
||||
msgid "A link trace already exists for this document/user."
|
||||
msgstr "此文档/用户的链接跟踪已存在。"
|
||||
|
||||
#: build/lib/core/models.py:994 core/models.py:994
|
||||
#: build/lib/core/models.py:997 core/models.py:997
|
||||
msgid "Document favorite"
|
||||
msgstr "文档收藏"
|
||||
|
||||
#: build/lib/core/models.py:995 core/models.py:995
|
||||
#: build/lib/core/models.py:998 core/models.py:998
|
||||
msgid "Document favorites"
|
||||
msgstr "文档收藏夹"
|
||||
|
||||
#: build/lib/core/models.py:1001 core/models.py:1001
|
||||
#: build/lib/core/models.py:1004 core/models.py:1004
|
||||
msgid "This document is already targeted by a favorite relation instance for the same user."
|
||||
msgstr "该文档已被同一用户的收藏关系实例关联。"
|
||||
|
||||
#: build/lib/core/models.py:1023 core/models.py:1023
|
||||
#: build/lib/core/models.py:1026 core/models.py:1026
|
||||
msgid "Document/user relation"
|
||||
msgstr "文档/用户关系"
|
||||
|
||||
#: build/lib/core/models.py:1024 core/models.py:1024
|
||||
#: build/lib/core/models.py:1027 core/models.py:1027
|
||||
msgid "Document/user relations"
|
||||
msgstr "文档/用户关系集"
|
||||
|
||||
#: build/lib/core/models.py:1030 core/models.py:1030
|
||||
#: build/lib/core/models.py:1033 core/models.py:1033
|
||||
msgid "This user is already in this document."
|
||||
msgstr "该用户已在此文档中。"
|
||||
|
||||
#: build/lib/core/models.py:1036 core/models.py:1036
|
||||
#: build/lib/core/models.py:1039 core/models.py:1039
|
||||
msgid "This team is already in this document."
|
||||
msgstr "该团队已在此文档中。"
|
||||
|
||||
#: build/lib/core/models.py:1042 build/lib/core/models.py:1367
|
||||
#: core/models.py:1042 core/models.py:1367
|
||||
#: build/lib/core/models.py:1045 build/lib/core/models.py:1370
|
||||
#: core/models.py:1045 core/models.py:1370
|
||||
msgid "Either user or team must be set, not both."
|
||||
msgstr "必须设置用户或团队之一,不能同时设置两者。"
|
||||
|
||||
#: build/lib/core/models.py:1188 core/models.py:1188
|
||||
#: build/lib/core/models.py:1191 core/models.py:1191
|
||||
msgid "Document ask for access"
|
||||
msgstr ""
|
||||
msgstr "文档需要访问权限"
|
||||
|
||||
#: build/lib/core/models.py:1189 core/models.py:1189
|
||||
#: build/lib/core/models.py:1192 core/models.py:1192
|
||||
msgid "Document ask for accesses"
|
||||
msgstr ""
|
||||
msgstr "文档需要访问权限"
|
||||
|
||||
#: build/lib/core/models.py:1195 core/models.py:1195
|
||||
#: build/lib/core/models.py:1198 core/models.py:1198
|
||||
msgid "This user has already asked for access to this document."
|
||||
msgstr ""
|
||||
msgstr "用户已申请该文档的访问权限。"
|
||||
|
||||
#: build/lib/core/models.py:1260 core/models.py:1260
|
||||
#: build/lib/core/models.py:1263 core/models.py:1263
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to a document!"
|
||||
msgstr ""
|
||||
msgstr "{name} 申请访问文档!"
|
||||
|
||||
#: build/lib/core/models.py:1264 core/models.py:1264
|
||||
#: build/lib/core/models.py:1267 core/models.py:1267
|
||||
#, python-brace-format
|
||||
msgid "{name} would like access to the following document:"
|
||||
msgstr ""
|
||||
msgstr "{name} 申请访问以下文档:"
|
||||
|
||||
#: build/lib/core/models.py:1270 core/models.py:1270
|
||||
#: build/lib/core/models.py:1273 core/models.py:1273
|
||||
#, python-brace-format
|
||||
msgid "{name} is asking for access to the document: {title}"
|
||||
msgstr ""
|
||||
msgstr "{name}申请文档:{title}的访问权限"
|
||||
|
||||
#: build/lib/core/models.py:1282 core/models.py:1282
|
||||
#: build/lib/core/models.py:1285 core/models.py:1285
|
||||
msgid "description"
|
||||
msgstr "说明"
|
||||
|
||||
#: build/lib/core/models.py:1283 core/models.py:1283
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
msgid "code"
|
||||
msgstr "代码"
|
||||
|
||||
#: build/lib/core/models.py:1284 core/models.py:1284
|
||||
#: build/lib/core/models.py:1287 core/models.py:1287
|
||||
msgid "css"
|
||||
msgstr "css"
|
||||
|
||||
#: build/lib/core/models.py:1286 core/models.py:1286
|
||||
#: build/lib/core/models.py:1289 core/models.py:1289
|
||||
msgid "public"
|
||||
msgstr "公开"
|
||||
|
||||
#: build/lib/core/models.py:1288 core/models.py:1288
|
||||
#: build/lib/core/models.py:1291 core/models.py:1291
|
||||
msgid "Whether this template is public for anyone to use."
|
||||
msgstr "该模板是否公开供任何人使用。"
|
||||
|
||||
#: build/lib/core/models.py:1294 core/models.py:1294
|
||||
#: build/lib/core/models.py:1297 core/models.py:1297
|
||||
msgid "Template"
|
||||
msgstr "模板"
|
||||
|
||||
#: build/lib/core/models.py:1295 core/models.py:1295
|
||||
#: build/lib/core/models.py:1298 core/models.py:1298
|
||||
msgid "Templates"
|
||||
msgstr "模板"
|
||||
|
||||
#: build/lib/core/models.py:1348 core/models.py:1348
|
||||
#: build/lib/core/models.py:1351 core/models.py:1351
|
||||
msgid "Template/user relation"
|
||||
msgstr "模板/用户关系"
|
||||
|
||||
#: build/lib/core/models.py:1349 core/models.py:1349
|
||||
#: build/lib/core/models.py:1352 core/models.py:1352
|
||||
msgid "Template/user relations"
|
||||
msgstr "模板/用户关系集"
|
||||
|
||||
#: build/lib/core/models.py:1355 core/models.py:1355
|
||||
#: build/lib/core/models.py:1358 core/models.py:1358
|
||||
msgid "This user is already in this template."
|
||||
msgstr "该用户已在此模板中。"
|
||||
|
||||
#: build/lib/core/models.py:1361 core/models.py:1361
|
||||
#: build/lib/core/models.py:1364 core/models.py:1364
|
||||
msgid "This team is already in this template."
|
||||
msgstr "该团队已在此模板中。"
|
||||
|
||||
#: build/lib/core/models.py:1438 core/models.py:1438
|
||||
#: build/lib/core/models.py:1441 core/models.py:1441
|
||||
msgid "email address"
|
||||
msgstr "电子邮件地址"
|
||||
|
||||
#: build/lib/core/models.py:1457 core/models.py:1457
|
||||
#: build/lib/core/models.py:1460 core/models.py:1460
|
||||
msgid "Document invitation"
|
||||
msgstr "文档邀请"
|
||||
|
||||
#: build/lib/core/models.py:1458 core/models.py:1458
|
||||
#: build/lib/core/models.py:1461 core/models.py:1461
|
||||
msgid "Document invitations"
|
||||
msgstr "文档邀请"
|
||||
|
||||
#: build/lib/core/models.py:1478 core/models.py:1478
|
||||
#: build/lib/core/models.py:1481 core/models.py:1481
|
||||
msgid "This email is already associated to a registered user."
|
||||
msgstr "此电子邮件已经与现有注册用户关联。"
|
||||
|
||||
#: core/templates/mail/html/template.html:162
|
||||
#: core/templates/mail/html/template.html:153
|
||||
#: core/templates/mail/text/template.txt:3
|
||||
msgid "Logo email"
|
||||
msgstr "徽标邮件"
|
||||
|
||||
#: core/templates/mail/html/template.html:209
|
||||
#: core/templates/mail/html/template.html:200
|
||||
#: core/templates/mail/text/template.txt:10
|
||||
msgid "Open"
|
||||
msgstr "打开"
|
||||
|
||||
#: core/templates/mail/html/template.html:226
|
||||
#: core/templates/mail/html/template.html:217
|
||||
#: core/templates/mail/text/template.txt:14
|
||||
msgid " Docs, your new essential tool for organizing, sharing and collaborating on your documents as a team. "
|
||||
msgstr " Docs——您的全新必备工具,帮助团队组织、共享和协作处理文档。 "
|
||||
|
||||
#: core/templates/mail/html/template.html:233
|
||||
#: core/templates/mail/html/template.html:224
|
||||
#: core/templates/mail/text/template.txt:16
|
||||
#, python-format
|
||||
msgid " Brought to you by %(brandname)s "
|
||||
|
||||
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "impress"
|
||||
version = "3.7.0"
|
||||
version = "3.9.0"
|
||||
authors = [{ "name" = "DINUM", "email" = "dev@mail.numerique.gouv.fr" }]
|
||||
classifiers = [
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
@@ -25,42 +25,42 @@ license = { file = "LICENSE" }
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.12"
|
||||
dependencies = [
|
||||
"beautifulsoup4==4.13.4",
|
||||
"boto3==1.39.4",
|
||||
"Brotli==1.1.0",
|
||||
"beautifulsoup4==4.14.2",
|
||||
"boto3==1.40.59",
|
||||
"Brotli==1.2.0",
|
||||
"celery[redis]==5.5.3",
|
||||
"django-configurations==2.5.1",
|
||||
"django-cors-headers==4.7.0",
|
||||
"django-cors-headers==4.9.0",
|
||||
"django-countries==7.6.1",
|
||||
"django-csp==4.0",
|
||||
"django-filter==25.1",
|
||||
"django-lasuite[all]==0.0.14",
|
||||
"django-filter==25.2",
|
||||
"django-lasuite[all]==0.0.16",
|
||||
"django-parler==2.3",
|
||||
"django-redis==6.0.0",
|
||||
"django-storages[s3]==1.14.6",
|
||||
"django-timezone-field>=5.1",
|
||||
"django==5.2.6",
|
||||
"django==5.2.8",
|
||||
"django-treebeard==4.7.1",
|
||||
"djangorestframework==3.16.0",
|
||||
"djangorestframework==3.16.1",
|
||||
"drf_spectacular==0.28.0",
|
||||
"dockerflow==2024.4.2",
|
||||
"easy_thumbnails==2.10",
|
||||
"easy_thumbnails==2.10.1",
|
||||
"factory_boy==3.3.3",
|
||||
"gunicorn==23.0.0",
|
||||
"jsonschema==4.24.0",
|
||||
"lxml==6.0.0",
|
||||
"markdown==3.8.2",
|
||||
"jsonschema==4.25.1",
|
||||
"lxml==6.0.2",
|
||||
"markdown==3.9",
|
||||
"mozilla-django-oidc==4.0.1",
|
||||
"nested-multipart-parser==1.5.0",
|
||||
"openai==1.95.0",
|
||||
"psycopg[binary]==3.2.9",
|
||||
"pycrdt==0.12.25",
|
||||
"nested-multipart-parser==1.6.0",
|
||||
"openai==2.6.1",
|
||||
"psycopg[binary]==3.2.12",
|
||||
"pycrdt==0.12.42",
|
||||
"PyJWT==2.10.1",
|
||||
"python-magic==0.4.27",
|
||||
"redis<6.0.0",
|
||||
"requests==2.32.4",
|
||||
"sentry-sdk==2.32.0",
|
||||
"whitenoise==6.9.0",
|
||||
"requests==2.32.5",
|
||||
"sentry-sdk==2.42.1",
|
||||
"whitenoise==6.11.0",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
@@ -73,21 +73,21 @@ dependencies = [
|
||||
dev = [
|
||||
"django-extensions==4.1",
|
||||
"django-test-migrations==1.5.0",
|
||||
"drf-spectacular-sidecar==2025.7.1",
|
||||
"freezegun==1.5.2",
|
||||
"drf-spectacular-sidecar==2025.10.1",
|
||||
"freezegun==1.5.5",
|
||||
"ipdb==0.13.13",
|
||||
"ipython==9.4.0",
|
||||
"pyfakefs==5.9.1",
|
||||
"ipython==9.6.0",
|
||||
"pyfakefs==5.10.0",
|
||||
"pylint-django==2.6.1",
|
||||
"pylint==3.3.7",
|
||||
"pytest-cov==6.2.1",
|
||||
"pylint<4.0.0",
|
||||
"pytest-cov==7.0.0",
|
||||
"pytest-django==4.11.1",
|
||||
"pytest==8.4.1",
|
||||
"pytest==8.4.2",
|
||||
"pytest-icdiff==0.9",
|
||||
"pytest-xdist==3.8.0",
|
||||
"responses==0.25.7",
|
||||
"ruff==0.12.2",
|
||||
"types-requests==2.32.4.20250611",
|
||||
"responses==0.25.8",
|
||||
"ruff==0.14.2",
|
||||
"types-requests==2.32.4.20250913",
|
||||
]
|
||||
|
||||
[tool.setuptools]
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* eslint-disable playwright/no-conditional-expect */
|
||||
import path from 'path';
|
||||
|
||||
import { chromium, expect, test } from '@playwright/test';
|
||||
import { expect, test } from '@playwright/test';
|
||||
import cs from 'convert-stream';
|
||||
|
||||
import {
|
||||
@@ -12,7 +12,12 @@ import {
|
||||
verifyDocName,
|
||||
} from './utils-common';
|
||||
import { getEditor, openSuggestionMenu, writeInEditor } from './utils-editor';
|
||||
import { createRootSubPage, navigateToPageFromTree } from './utils-sub-pages';
|
||||
import { connectOtherUserToDoc, updateShareLink } from './utils-share';
|
||||
import {
|
||||
createRootSubPage,
|
||||
getTreeRow,
|
||||
navigateToPageFromTree,
|
||||
} from './utils-sub-pages';
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/');
|
||||
@@ -489,7 +494,7 @@ test.describe('Doc Editor', () => {
|
||||
if (request.method().includes('GET')) {
|
||||
await route.fulfill({
|
||||
json: {
|
||||
status: requestCount ? 'ready' : 'processing',
|
||||
status: requestCount > 1 ? 'ready' : 'processing',
|
||||
file: '/anything.html',
|
||||
},
|
||||
});
|
||||
@@ -513,6 +518,12 @@ test.describe('Doc Editor', () => {
|
||||
await fileChooser.setFiles(path.join(__dirname, 'assets/test.html'));
|
||||
|
||||
await expect(editor.getByText('Analyzing file...')).toBeVisible();
|
||||
|
||||
// To be sure the retry happens even after a page reload
|
||||
await page.reload();
|
||||
|
||||
await expect(editor.getByText('Analyzing file...')).toBeVisible();
|
||||
|
||||
// The retry takes a few seconds
|
||||
await expect(editor.getByText('test.html')).toBeVisible({
|
||||
timeout: 7000,
|
||||
@@ -560,20 +571,7 @@ test.describe('Doc Editor', () => {
|
||||
|
||||
await page.getByRole('button', { name: 'Share' }).click();
|
||||
|
||||
await page.getByTestId('doc-visibility').click();
|
||||
|
||||
await page
|
||||
.getByRole('menuitem', {
|
||||
name: 'Public',
|
||||
})
|
||||
.click();
|
||||
|
||||
await expect(
|
||||
page.getByText('The document visibility has been updated.'),
|
||||
).toBeVisible();
|
||||
|
||||
await page.getByTestId('doc-access-mode').click();
|
||||
await page.getByRole('menuitem', { name: 'Editing' }).click();
|
||||
await updateShareLink(page, 'Public', 'Editing');
|
||||
|
||||
// Close the modal
|
||||
await page.getByRole('button', { name: 'close' }).first().click();
|
||||
@@ -597,17 +595,12 @@ test.describe('Doc Editor', () => {
|
||||
* We open another browser that will connect to the collaborative server
|
||||
* and will block the current browser to edit the doc.
|
||||
*/
|
||||
const otherBrowser = await chromium.launch({ headless: true });
|
||||
const otherContext = await otherBrowser.newContext({
|
||||
locale: 'en-US',
|
||||
timezoneId: 'Europe/Paris',
|
||||
permissions: [],
|
||||
storageState: {
|
||||
cookies: [],
|
||||
origins: [],
|
||||
},
|
||||
const { otherPage } = await connectOtherUserToDoc({
|
||||
browserName,
|
||||
docUrl: urlChildDoc,
|
||||
docTitle: childTitle,
|
||||
withoutSignIn: true,
|
||||
});
|
||||
const otherPage = await otherContext.newPage();
|
||||
|
||||
const webSocketPromise = otherPage.waitForEvent(
|
||||
'websocket',
|
||||
@@ -648,6 +641,11 @@ test.describe('Doc Editor', () => {
|
||||
|
||||
await expect(editor).toHaveAttribute('contenteditable', 'false');
|
||||
|
||||
await expect(
|
||||
page.getByRole('textbox', { name: 'Document title' }),
|
||||
).toBeHidden();
|
||||
await expect(page.getByRole('heading', { name: childTitle })).toBeVisible();
|
||||
|
||||
await page.goto(urlParentDoc);
|
||||
|
||||
await verifyDocName(page, parentTitle);
|
||||
@@ -664,6 +662,11 @@ test.describe('Doc Editor', () => {
|
||||
|
||||
await expect(editor).toHaveAttribute('contenteditable', 'true');
|
||||
|
||||
await expect(
|
||||
page.getByRole('textbox', { name: 'Document title' }),
|
||||
).toContainText(childTitle);
|
||||
await expect(page.getByRole('heading', { name: childTitle })).toBeHidden();
|
||||
|
||||
await expect(
|
||||
card.getByText('Others are editing. Your network prevent changes.'),
|
||||
).toBeHidden();
|
||||
@@ -683,10 +686,9 @@ test.describe('Doc Editor', () => {
|
||||
|
||||
await calloutBlock.locator('.inline-content').fill('example text');
|
||||
|
||||
await expect(page.locator('.bn-block').first()).toHaveAttribute(
|
||||
'data-background-color',
|
||||
'yellow',
|
||||
);
|
||||
await expect(
|
||||
page.locator('.bn-block-content[data-content-type="callout"]').first(),
|
||||
).toHaveAttribute('data-background-color', 'yellow');
|
||||
|
||||
const emojiButton = calloutBlock.getByRole('button');
|
||||
await expect(emojiButton).toHaveText('💡');
|
||||
@@ -710,10 +712,9 @@ test.describe('Doc Editor', () => {
|
||||
await page.locator('.mantine-Menu-dropdown > button').last().click();
|
||||
await page.locator('.bn-color-picker-dropdown > button').last().click();
|
||||
|
||||
await expect(page.locator('.bn-block').first()).toHaveAttribute(
|
||||
'data-background-color',
|
||||
'pink',
|
||||
);
|
||||
await expect(
|
||||
page.locator('.bn-block-content[data-content-type="callout"]').first(),
|
||||
).toHaveAttribute('data-background-color', 'pink');
|
||||
});
|
||||
|
||||
test('it checks interlink feature', async ({ page, browserName }) => {
|
||||
@@ -737,7 +738,13 @@ test.describe('Doc Editor', () => {
|
||||
|
||||
await verifyDocName(page, docChild2);
|
||||
|
||||
await page.locator('.bn-block-outer').last().fill('/');
|
||||
const treeRow = await getTreeRow(page, docChild2);
|
||||
await treeRow.locator('.--docs--doc-icon').click();
|
||||
await page.getByRole('button', { name: '😀' }).first().click();
|
||||
|
||||
await navigateToPageFromTree({ page, title: docChild1 });
|
||||
|
||||
await openSuggestionMenu({ page });
|
||||
await page.getByText('Link a doc').first().click();
|
||||
|
||||
const input = page.locator(
|
||||
@@ -751,6 +758,16 @@ test.describe('Doc Editor', () => {
|
||||
await expect(searchContainer.getByText(docChild1)).toBeVisible();
|
||||
await expect(searchContainer.getByText(docChild2)).toBeVisible();
|
||||
|
||||
const searchContainerRow = searchContainer
|
||||
.getByRole('option')
|
||||
.filter({
|
||||
hasText: docChild2,
|
||||
})
|
||||
.first();
|
||||
|
||||
await expect(searchContainerRow).toContainText('😀');
|
||||
await expect(searchContainerRow.locator('svg').first()).toBeHidden();
|
||||
|
||||
await input.pressSequentially('-child');
|
||||
|
||||
await expect(searchContainer.getByText(docChild1)).toBeVisible();
|
||||
@@ -765,32 +782,30 @@ test.describe('Doc Editor', () => {
|
||||
await expect(searchContainer).toBeHidden();
|
||||
|
||||
// Wait for the interlink to be created and rendered
|
||||
const editor = page.locator('.ProseMirror.bn-editor');
|
||||
const editor = await getEditor({ page });
|
||||
|
||||
const interlink = editor.getByRole('link', {
|
||||
const interlinkChild2 = editor.getByRole('button', {
|
||||
name: docChild2,
|
||||
});
|
||||
|
||||
await expect(interlink).toBeVisible({ timeout: 10000 });
|
||||
await interlink.click();
|
||||
await expect(interlinkChild2).toBeVisible({ timeout: 10000 });
|
||||
await expect(interlinkChild2).toContainText('😀');
|
||||
await expect(interlinkChild2.locator('svg').first()).toBeHidden();
|
||||
await interlinkChild2.click();
|
||||
|
||||
await verifyDocName(page, docChild2);
|
||||
});
|
||||
|
||||
test('it checks interlink shortcut @', async ({ page, browserName }) => {
|
||||
const [randomDoc] = await createDoc(page, 'doc-interlink', browserName, 1);
|
||||
|
||||
await verifyDocName(page, randomDoc);
|
||||
|
||||
const editor = page.locator('.bn-block-outer').last();
|
||||
await editor.click();
|
||||
await page.keyboard.press('@');
|
||||
|
||||
await expect(
|
||||
page.locator(
|
||||
"span[data-inline-content-type='interlinkingSearchInline'] input",
|
||||
),
|
||||
).toBeVisible();
|
||||
await page.keyboard.press('@');
|
||||
await input.fill(docChild1);
|
||||
await searchContainer.getByText(docChild1).click();
|
||||
|
||||
const interlinkChild1 = editor.getByRole('button', {
|
||||
name: docChild1,
|
||||
});
|
||||
await expect(interlinkChild1).toBeVisible({ timeout: 10000 });
|
||||
await expect(interlinkChild1.locator('svg').first()).toBeVisible();
|
||||
});
|
||||
|
||||
test('it checks multiple big doc scroll to the top', async ({
|
||||
@@ -851,12 +866,12 @@ test.describe('Doc Editor', () => {
|
||||
|
||||
await expect(pdfBlock).toBeVisible();
|
||||
|
||||
await page.getByText('Add PDF').click();
|
||||
await page.getByText(/Add (PDF|file)/).click();
|
||||
const fileChooserPromise = page.waitForEvent('filechooser');
|
||||
await page.getByText('Upload file').click();
|
||||
const downloadPromise = page.waitForEvent('download');
|
||||
await page.getByText(/Upload (PDF|file)/).click();
|
||||
const fileChooser = await fileChooserPromise;
|
||||
|
||||
console.log(path.join(__dirname, 'assets/test-pdf.pdf'));
|
||||
await fileChooser.setFiles(path.join(__dirname, 'assets/test-pdf.pdf'));
|
||||
|
||||
// Wait for the media-check to be processed
|
||||
@@ -873,5 +888,12 @@ test.describe('Doc Editor', () => {
|
||||
|
||||
await expect(pdfEmbed).toHaveAttribute('type', 'application/pdf');
|
||||
await expect(pdfEmbed).toHaveAttribute('role', 'presentation');
|
||||
|
||||
// Check download with original filename
|
||||
await page.locator('.bn-block-content[data-content-type="pdf"]').click();
|
||||
await page.locator('[data-test="downloadfile"]').click();
|
||||
|
||||
const download = await downloadPromise;
|
||||
expect(download.suggestedFilename()).toBe('test-pdf.pdf');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -2,15 +2,15 @@ import path from 'path';
|
||||
|
||||
import { expect, test } from '@playwright/test';
|
||||
import cs from 'convert-stream';
|
||||
import pdf from 'pdf-parse';
|
||||
import { PDFParse } from 'pdf-parse';
|
||||
|
||||
import {
|
||||
TestLanguage,
|
||||
createDoc,
|
||||
randomName,
|
||||
verifyDocName,
|
||||
waitForLanguageSwitch,
|
||||
} from './utils-common';
|
||||
import { openSuggestionMenu, writeInEditor } from './utils-editor';
|
||||
import { createRootSubPage } from './utils-sub-pages';
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
@@ -58,20 +58,16 @@ test.describe('Doc Export', () => {
|
||||
|
||||
await verifyDocName(page, randomDoc);
|
||||
|
||||
const editor = page.locator('.ProseMirror.bn-editor');
|
||||
|
||||
await editor.click();
|
||||
await editor.locator('.bn-block-outer').last().fill('Hello');
|
||||
|
||||
const editor = await writeInEditor({ page, text: 'Hello' });
|
||||
await page.keyboard.press('Enter');
|
||||
await editor.locator('.bn-block-outer').last().fill('/');
|
||||
await openSuggestionMenu({ page });
|
||||
await page.getByText('Page Break').click();
|
||||
|
||||
await expect(editor.locator('.bn-page-break')).toBeVisible();
|
||||
await expect(
|
||||
editor.locator('div[data-content-type="pageBreak"]'),
|
||||
).toBeVisible();
|
||||
|
||||
await page.keyboard.press('Enter');
|
||||
|
||||
await editor.locator('.bn-block-outer').last().fill('World');
|
||||
await writeInEditor({ page, text: 'World' });
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
@@ -89,11 +85,16 @@ test.describe('Doc Export', () => {
|
||||
expect(download.suggestedFilename()).toBe(`${randomDoc}.pdf`);
|
||||
|
||||
const pdfBuffer = await cs.toBuffer(await download.createReadStream());
|
||||
const pdfData = await pdf(pdfBuffer);
|
||||
const pdfParse = new PDFParse({ data: pdfBuffer });
|
||||
const pdfInfo = await pdfParse.getInfo();
|
||||
const pdfText = await pdfParse.getText();
|
||||
|
||||
expect(pdfData.numpages).toBe(2);
|
||||
expect(pdfData.text).toContain('\n\nHello\n\nWorld'); // This is the doc text
|
||||
expect(pdfData.info.Title).toBe(randomDoc);
|
||||
expect(pdfInfo.total).toBe(2);
|
||||
expect(pdfText.pages).toStrictEqual([
|
||||
{ text: 'Hello', num: 1 },
|
||||
{ text: 'World', num: 2 },
|
||||
]);
|
||||
expect(pdfInfo?.info.Title).toBe(randomDoc);
|
||||
});
|
||||
|
||||
test('it exports the doc to docx', async ({ page, browserName }) => {
|
||||
@@ -153,11 +154,13 @@ test.describe('Doc Export', () => {
|
||||
|
||||
await verifyDocName(page, randomDoc);
|
||||
|
||||
await page.locator('.ProseMirror.bn-editor').click();
|
||||
await page.locator('.ProseMirror.bn-editor').fill('Hello World');
|
||||
await writeInEditor({
|
||||
page,
|
||||
text: 'Hello World 😃🎉🚀🙋♀️🧑🏿❤️💋🧑🏾',
|
||||
});
|
||||
|
||||
await page.keyboard.press('Enter');
|
||||
await page.locator('.bn-block-outer').last().fill('/');
|
||||
await openSuggestionMenu({ page });
|
||||
await page.getByText('Resizable image with caption').click();
|
||||
|
||||
const fileChooserPromise = page.waitForEvent('filechooser');
|
||||
@@ -220,10 +223,10 @@ test.describe('Doc Export', () => {
|
||||
expect(download.suggestedFilename()).toBe(`${randomDoc}.pdf`);
|
||||
|
||||
const pdfBuffer = await cs.toBuffer(await download.createReadStream());
|
||||
const pdfExport = await pdf(pdfBuffer);
|
||||
const pdfText = pdfExport.text;
|
||||
|
||||
expect(pdfText).toContain('Hello World');
|
||||
const pdfParse = new PDFParse({ data: pdfBuffer });
|
||||
const pdfText = await pdfParse.getText();
|
||||
expect(pdfText.text).toContain('Hello World');
|
||||
});
|
||||
|
||||
test('it exports the doc with quotes', async ({ page, browserName }) => {
|
||||
@@ -266,52 +269,9 @@ test.describe('Doc Export', () => {
|
||||
expect(download.suggestedFilename()).toBe(`${randomDoc}.pdf`);
|
||||
|
||||
const pdfBuffer = await cs.toBuffer(await download.createReadStream());
|
||||
const pdfData = await pdf(pdfBuffer);
|
||||
|
||||
expect(pdfData.text).toContain('Hello World'); // This is the pdf text
|
||||
});
|
||||
|
||||
/**
|
||||
* We cannot assert the line break is visible in the pdf, but we can assert the
|
||||
* line break is visible in the editor and that the pdf is generated.
|
||||
*/
|
||||
test('it exports the doc with divider', async ({ page, browserName }) => {
|
||||
const [randomDoc] = await createDoc(page, 'export-divider', browserName, 1);
|
||||
|
||||
const editor = page.locator('.ProseMirror');
|
||||
await editor.click();
|
||||
await editor.fill('Hello World');
|
||||
|
||||
// Trigger slash menu to show menu
|
||||
await editor.locator('.bn-block-outer').last().fill('/');
|
||||
await page.getByText('Add a horizontal line').click();
|
||||
|
||||
await expect(
|
||||
editor.locator('.bn-block-content[data-content-type="divider"]'),
|
||||
).toBeVisible();
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
name: 'Export the document',
|
||||
})
|
||||
.click();
|
||||
|
||||
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('doc-export-download-button').click();
|
||||
|
||||
const download = await downloadPromise;
|
||||
expect(download.suggestedFilename()).toBe(`${randomDoc}.pdf`);
|
||||
|
||||
const pdfBuffer = await cs.toBuffer(await download.createReadStream());
|
||||
const pdfData = await pdf(pdfBuffer);
|
||||
expect(pdfData.text).toContain('Hello World');
|
||||
const pdfParse = new PDFParse({ data: pdfBuffer });
|
||||
const pdfText = await pdfParse.getText();
|
||||
expect(pdfText.text).toContain('Hello World');
|
||||
});
|
||||
|
||||
test('it exports the doc with multi columns', async ({
|
||||
@@ -364,46 +324,33 @@ test.describe('Doc Export', () => {
|
||||
expect(download.suggestedFilename()).toBe(`${randomDoc}.pdf`);
|
||||
|
||||
const pdfBuffer = await cs.toBuffer(await download.createReadStream());
|
||||
const pdfData = await pdf(pdfBuffer);
|
||||
expect(pdfData.text).toContain('Column 1');
|
||||
expect(pdfData.text).toContain('Column 2');
|
||||
expect(pdfData.text).toContain('Column 3');
|
||||
const pdfParse = new PDFParse({ data: pdfBuffer });
|
||||
const pdfText = await pdfParse.getText();
|
||||
expect(pdfText.text).toContain('Column 1');
|
||||
expect(pdfText.text).toContain('Column 2');
|
||||
expect(pdfText.text).toContain('Column 3');
|
||||
});
|
||||
|
||||
test('it injects the correct language attribute into PDF export', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
const [randomDocFrench] = await createDoc(
|
||||
page,
|
||||
'doc-language-export-french',
|
||||
browserName,
|
||||
1,
|
||||
);
|
||||
|
||||
await waitForLanguageSwitch(page, TestLanguage.French);
|
||||
|
||||
// Wait for the page to be ready after language switch
|
||||
await page.waitForLoadState('domcontentloaded');
|
||||
|
||||
const header = page.locator('header').first();
|
||||
await header.locator('h1').getByText('Docs').click();
|
||||
|
||||
const randomDocFrench = randomName(
|
||||
'doc-language-export-french',
|
||||
browserName,
|
||||
1,
|
||||
)[0];
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
name: 'Nouveau doc',
|
||||
})
|
||||
.click();
|
||||
|
||||
const input = page.getByRole('textbox', { name: 'Titre du document' });
|
||||
await expect(input).toBeVisible();
|
||||
await expect(input).toHaveText('', { timeout: 10000 });
|
||||
await input.click();
|
||||
await input.fill(randomDocFrench);
|
||||
await input.blur();
|
||||
|
||||
const editor = page.locator('.ProseMirror.bn-editor');
|
||||
await editor.click();
|
||||
await editor.fill('Contenu de test pour export en français');
|
||||
await writeInEditor({
|
||||
page,
|
||||
text: 'Contenu de test pour export en français',
|
||||
});
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
@@ -469,7 +416,7 @@ test.describe('Doc Export', () => {
|
||||
|
||||
// Search the interlinking link in the editor (not in the document tree)
|
||||
const editor = page.locator('.ProseMirror.bn-editor');
|
||||
const interlink = editor.getByRole('link', {
|
||||
const interlink = editor.getByRole('button', {
|
||||
name: randomDoc,
|
||||
});
|
||||
|
||||
@@ -491,8 +438,8 @@ test.describe('Doc Export', () => {
|
||||
expect(download.suggestedFilename()).toBe(`${docChild}.pdf`);
|
||||
|
||||
const pdfBuffer = await cs.toBuffer(await download.createReadStream());
|
||||
const pdfData = await pdf(pdfBuffer);
|
||||
|
||||
expect(pdfData.text).toContain(randomDoc);
|
||||
const pdfParse = new PDFParse({ data: pdfBuffer });
|
||||
const pdfText = await pdfParse.getText();
|
||||
expect(pdfText.text).toContain(randomDoc);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -106,7 +106,7 @@ test.describe('Doc grid dnd', () => {
|
||||
|
||||
await expect(dragOverlay).toBeVisible();
|
||||
await expect(dragOverlay).toHaveText(
|
||||
'You must be at least the editor of the target document',
|
||||
'You must be at least the administrator of the target document',
|
||||
);
|
||||
|
||||
await page.mouse.up();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
import { createDoc, getGridRow } from './utils-common';
|
||||
import { createDoc, getGridRow, verifyDocName } from './utils-common';
|
||||
import { addNewMember, connectOtherUserToDoc } from './utils-share';
|
||||
|
||||
type SmallDoc = {
|
||||
id: string;
|
||||
@@ -11,7 +12,7 @@ test.describe('Documents Grid mobile', () => {
|
||||
test.use({ viewport: { width: 500, height: 1200 } });
|
||||
|
||||
test('it checks the grid when mobile', async ({ page }) => {
|
||||
await page.route('**/documents/**', async (route) => {
|
||||
await page.route(/.*\/documents\/.*/, async (route) => {
|
||||
const request = route.request();
|
||||
if (request.method().includes('GET') && request.url().includes('page=')) {
|
||||
await route.fulfill({
|
||||
@@ -133,13 +134,15 @@ test.describe('Document grid item options', () => {
|
||||
test('it deletes the document', async ({ page, browserName }) => {
|
||||
const [docTitle] = await createDoc(page, `delete doc`, browserName);
|
||||
|
||||
await verifyDocName(page, docTitle);
|
||||
|
||||
await page.goto('/');
|
||||
|
||||
await expect(page.getByText(docTitle)).toBeVisible();
|
||||
const row = await getGridRow(page, docTitle);
|
||||
await row.getByText(`more_horiz`).click();
|
||||
|
||||
await page.getByRole('menuitem', { name: 'Remove' }).click();
|
||||
await page.getByRole('menuitem', { name: 'Delete' }).click();
|
||||
|
||||
await expect(
|
||||
page.getByRole('heading', { name: 'Delete a doc' }),
|
||||
@@ -161,7 +164,7 @@ test.describe('Document grid item options', () => {
|
||||
test("it checks if the delete option is disabled if we don't have the destroy capability", async ({
|
||||
page,
|
||||
}) => {
|
||||
await page.route('*/**/api/v1.0/documents/?page=1', async (route) => {
|
||||
await page.route(/.*\/api\/v1.0\/documents\/\?page=1/, async (route) => {
|
||||
await route.fulfill({
|
||||
json: {
|
||||
results: [
|
||||
@@ -192,90 +195,68 @@ test.describe('Document grid item options', () => {
|
||||
});
|
||||
await page.goto('/');
|
||||
|
||||
const button = page.getByTestId(
|
||||
`docs-grid-actions-button-mocked-document-id`,
|
||||
);
|
||||
const button = page
|
||||
.getByTestId(`docs-grid-actions-button-mocked-document-id`)
|
||||
.first();
|
||||
await expect(button).toBeVisible();
|
||||
await button.click();
|
||||
const removeButton = page.getByTestId(
|
||||
`docs-grid-actions-remove-mocked-document-id`,
|
||||
);
|
||||
const removeButton = page
|
||||
.getByTestId(`docs-grid-actions-remove-mocked-document-id`)
|
||||
.first();
|
||||
await expect(removeButton).toBeVisible();
|
||||
await removeButton.isDisabled();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Documents filters', () => {
|
||||
test('it checks the prebuild left panel filters', async ({ page }) => {
|
||||
test('it checks the left panel filters', async ({ page, browserName }) => {
|
||||
void page.goto('/');
|
||||
|
||||
// Create my doc
|
||||
const [docName] = await createDoc(page, 'my-doc', browserName, 1);
|
||||
await verifyDocName(page, docName);
|
||||
|
||||
// Another user create a doc and share it with me
|
||||
const { cleanup, otherPage, otherBrowserName } =
|
||||
await connectOtherUserToDoc({
|
||||
browserName,
|
||||
docUrl: '/',
|
||||
});
|
||||
|
||||
const [docShareName] = await createDoc(
|
||||
otherPage,
|
||||
'my-share-doc',
|
||||
otherBrowserName,
|
||||
1,
|
||||
);
|
||||
|
||||
await verifyDocName(otherPage, docShareName);
|
||||
|
||||
await otherPage.getByRole('button', { name: 'Share' }).click();
|
||||
|
||||
await addNewMember(otherPage, 0, 'Editor', browserName);
|
||||
|
||||
// Let's check the filters
|
||||
await page.getByRole('button', { name: 'Back to homepage' }).click();
|
||||
|
||||
const row = await getGridRow(page, docName);
|
||||
const rowShare = await getGridRow(page, docShareName);
|
||||
|
||||
// All Docs
|
||||
const response = await page.waitForResponse(
|
||||
(response) =>
|
||||
response.url().endsWith('documents/?page=1') &&
|
||||
response.status() === 200,
|
||||
);
|
||||
const result = await response.json();
|
||||
const allCount = result.count as number;
|
||||
await expect(page.getByTestId('grid-loader')).toBeHidden();
|
||||
await expect(row).toBeVisible();
|
||||
await expect(rowShare).toBeVisible();
|
||||
|
||||
const allDocs = page.getByLabel('All docs');
|
||||
const myDocs = page.getByLabel('My docs');
|
||||
const sharedWithMe = page.getByLabel('Shared with me');
|
||||
|
||||
// Initial state
|
||||
await expect(allDocs).toBeVisible();
|
||||
await expect(allDocs).toHaveAttribute('aria-current', 'page');
|
||||
|
||||
await expect(myDocs).toBeVisible();
|
||||
await expect(myDocs).toHaveCSS('background-color', 'rgba(0, 0, 0, 0)');
|
||||
await expect(myDocs).not.toHaveAttribute('aria-current');
|
||||
|
||||
await expect(sharedWithMe).toBeVisible();
|
||||
await expect(sharedWithMe).toHaveCSS(
|
||||
'background-color',
|
||||
'rgba(0, 0, 0, 0)',
|
||||
);
|
||||
await expect(sharedWithMe).not.toHaveAttribute('aria-current');
|
||||
|
||||
await allDocs.click();
|
||||
|
||||
await page.waitForURL('**/?target=all_docs');
|
||||
|
||||
let url = new URL(page.url());
|
||||
let target = url.searchParams.get('target');
|
||||
expect(target).toBe('all_docs');
|
||||
|
||||
// My docs
|
||||
await myDocs.click();
|
||||
url = new URL(page.url());
|
||||
target = url.searchParams.get('target');
|
||||
expect(target).toBe('my_docs');
|
||||
const responseMyDocs = await page.waitForResponse(
|
||||
(response) =>
|
||||
response.url().endsWith('documents/?page=1&is_creator_me=true') &&
|
||||
response.status() === 200,
|
||||
);
|
||||
const resultMyDocs = await responseMyDocs.json();
|
||||
const countMyDocs = resultMyDocs.count as number;
|
||||
await expect(page.getByTestId('grid-loader')).toBeHidden();
|
||||
expect(countMyDocs).toBeLessThanOrEqual(allCount);
|
||||
// My Docs
|
||||
await page.getByRole('link', { name: 'My docs' }).click();
|
||||
await expect(row).toBeVisible();
|
||||
await expect(rowShare).toBeHidden();
|
||||
|
||||
// Shared with me
|
||||
await sharedWithMe.click();
|
||||
url = new URL(page.url());
|
||||
target = url.searchParams.get('target');
|
||||
expect(target).toBe('shared_with_me');
|
||||
const responseSharedWithMe = await page.waitForResponse(
|
||||
(response) =>
|
||||
response.url().includes('documents/?page=1&is_creator_me=false') &&
|
||||
response.status() === 200,
|
||||
);
|
||||
const resultSharedWithMe = await responseSharedWithMe.json();
|
||||
const countSharedWithMe = resultSharedWithMe.count as number;
|
||||
await expect(page.getByTestId('grid-loader')).toBeHidden();
|
||||
expect(countSharedWithMe).toBeLessThanOrEqual(allCount);
|
||||
expect(countSharedWithMe + countMyDocs).toEqual(allCount);
|
||||
await page.getByRole('link', { name: 'Shared with me' }).click();
|
||||
await expect(row).toBeHidden();
|
||||
await expect(rowShare).toBeVisible();
|
||||
|
||||
await cleanup();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
verifyDocName,
|
||||
} from './utils-common';
|
||||
import { mockedAccesses, mockedInvitations } from './utils-share';
|
||||
import { createRootSubPage } from './utils-sub-pages';
|
||||
import { createRootSubPage, getTreeRow } from './utils-sub-pages';
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/');
|
||||
@@ -65,25 +65,61 @@ 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');
|
||||
const optionMenu = page.getByLabel('Open the document options');
|
||||
const addEmojiMenuItem = page.getByRole('menuitem', { name: 'Add emoji' });
|
||||
const removeEmojiMenuItem = page.getByRole('menuitem', {
|
||||
name: 'Remove emoji',
|
||||
});
|
||||
|
||||
// Top parent should not have emoji picker
|
||||
await expect(emojiPicker).toBeHidden();
|
||||
await optionMenu.click();
|
||||
await expect(addEmojiMenuItem).toBeHidden();
|
||||
await expect(removeEmojiMenuItem).toBeHidden();
|
||||
await page.keyboard.press('Escape');
|
||||
|
||||
const { name: docChild } = await createRootSubPage(
|
||||
page,
|
||||
browserName,
|
||||
'doc-update-emoji-child',
|
||||
);
|
||||
|
||||
await verifyDocName(page, docChild);
|
||||
|
||||
// Emoji picker should be hidden initially
|
||||
await expect(emojiPicker).toBeHidden();
|
||||
|
||||
// Add emoji
|
||||
await optionMenu.click();
|
||||
await expect(removeEmojiMenuItem).toBeHidden();
|
||||
await addEmojiMenuItem.click();
|
||||
await expect(emojiPicker).toHaveText('📄');
|
||||
|
||||
// Change emoji
|
||||
await emojiPicker.click({
|
||||
delay: 100,
|
||||
});
|
||||
await page.getByRole('button', { name: '😀' }).first().click();
|
||||
await expect(emojiPicker).toHaveText('😀');
|
||||
|
||||
// Update title
|
||||
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 docTree = page.getByTestId('doc-tree');
|
||||
await expect(docTree.getByText('Hello Emoji World')).toBeVisible();
|
||||
await expect(docTree.getByTestId('doc-emoji-icon')).toBeVisible();
|
||||
await expect(docTree.getByTestId('doc-simple-icon')).toBeHidden();
|
||||
const row = await getTreeRow(page, 'Hello Emoji World');
|
||||
await expect(row.getByText('😀')).toBeVisible();
|
||||
|
||||
await page.getByTestId('home-button').click();
|
||||
|
||||
// Check the documents grid
|
||||
const gridRow = await getGridRow(page, 'Hello Emoji World');
|
||||
await expect(gridRow.getByTestId('doc-emoji-icon')).toBeVisible();
|
||||
await expect(gridRow.getByTestId('doc-simple-icon')).toBeHidden();
|
||||
// Remove emoji
|
||||
await optionMenu.click();
|
||||
await expect(addEmojiMenuItem).toBeHidden();
|
||||
await removeEmojiMenuItem.click();
|
||||
await expect(emojiPicker).toBeHidden();
|
||||
});
|
||||
|
||||
test('it deletes the doc', async ({ page, browserName }) => {
|
||||
@@ -96,7 +132,7 @@ test.describe('Doc Header', () => {
|
||||
page.getByRole('heading', { name: 'Delete a doc' }),
|
||||
).toBeVisible();
|
||||
|
||||
await expect(page.getByText(`This document and any sub-`)).toBeVisible();
|
||||
await expect(page.getByText(`This document will be`)).toBeVisible();
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
@@ -142,6 +178,10 @@ test.describe('Doc Header', () => {
|
||||
|
||||
await goToGridDoc(page);
|
||||
|
||||
await expect(
|
||||
page.getByRole('textbox', { name: 'Document title' }),
|
||||
).toContainText('Mocked document');
|
||||
|
||||
await expect(
|
||||
page.getByRole('button', { name: 'Export the document' }),
|
||||
).toBeVisible();
|
||||
@@ -218,6 +258,10 @@ test.describe('Doc Header', () => {
|
||||
|
||||
await goToGridDoc(page);
|
||||
|
||||
await expect(
|
||||
page.getByRole('textbox', { name: 'Document title' }),
|
||||
).toContainText('Mocked document');
|
||||
|
||||
await expect(
|
||||
page.getByRole('button', { name: 'Export the document' }),
|
||||
).toBeVisible();
|
||||
@@ -286,6 +330,10 @@ test.describe('Doc Header', () => {
|
||||
|
||||
await goToGridDoc(page);
|
||||
|
||||
await expect(
|
||||
page.getByRole('heading', { name: 'Mocked document' }),
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
page.getByRole('button', { name: 'Export the document' }),
|
||||
).toBeVisible();
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
randomName,
|
||||
verifyDocName,
|
||||
} from './utils-common';
|
||||
import { writeInEditor } from './utils-editor';
|
||||
import { connectOtherUserToDoc, updateRoleUser } from './utils-share';
|
||||
import { createRootSubPage } from './utils-sub-pages';
|
||||
|
||||
@@ -169,8 +170,15 @@ test.describe('Document create member', () => {
|
||||
|
||||
const inputSearch = page.getByTestId('quick-search-input');
|
||||
|
||||
const email = randomName('test@test.fr', browserName, 1)[0];
|
||||
let email = 'user.test21@example.COM';
|
||||
await inputSearch.fill(email);
|
||||
|
||||
// Check email is found in search (case insensitive)
|
||||
await expect(page.getByRole('option').getByText(email)).toHaveCount(1);
|
||||
|
||||
email = email + 'M';
|
||||
await inputSearch.fill(email);
|
||||
|
||||
await page.getByTestId(`search-user-row-${email}`).click();
|
||||
|
||||
// Choose a role
|
||||
@@ -191,13 +199,23 @@ test.describe('Document create member', () => {
|
||||
|
||||
const listInvitation = page.getByTestId('doc-share-quick-search');
|
||||
const userInvitation = listInvitation.getByTestId(
|
||||
`doc-share-invitation-row-${email}`,
|
||||
`doc-share-invitation-row-${email.toLowerCase()}`,
|
||||
);
|
||||
await expect(userInvitation).toBeVisible();
|
||||
|
||||
const responsePromisePatchInvitation = page.waitForResponse(
|
||||
(response) =>
|
||||
response.url().includes('/invitations/') &&
|
||||
response.status() === 200 &&
|
||||
response.request().method() === 'PATCH',
|
||||
);
|
||||
|
||||
await userInvitation.getByLabel('doc-role-dropdown').click();
|
||||
await page.getByRole('menuitem', { name: 'Reader' }).click();
|
||||
|
||||
const responsePatchInvitation = await responsePromisePatchInvitation;
|
||||
expect(responsePatchInvitation.ok()).toBeTruthy();
|
||||
|
||||
const moreActions = userInvitation.getByRole('button', {
|
||||
name: 'Open invitation actions menu',
|
||||
});
|
||||
@@ -223,17 +241,13 @@ test.describe('Document create member', () => {
|
||||
|
||||
await verifyDocName(page, docTitle);
|
||||
|
||||
await page
|
||||
.locator('.ProseMirror')
|
||||
.locator('.bn-block-outer')
|
||||
.last()
|
||||
.fill('Hello World');
|
||||
await writeInEditor({ page, text: 'Hello World' });
|
||||
|
||||
const urlDoc = page.url();
|
||||
const docUrl = page.url();
|
||||
|
||||
// Other user will request access
|
||||
const { otherPage, otherBrowserName, cleanup } =
|
||||
await connectOtherUserToDoc(browserName, urlDoc);
|
||||
await connectOtherUserToDoc({ browserName, docUrl });
|
||||
|
||||
await expect(
|
||||
otherPage.getByText('Insufficient access rights to view the document.'),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
import { createDoc, goToGridDoc, verifyDocName } from './utils-common';
|
||||
import { createDoc, verifyDocName } from './utils-common';
|
||||
import { addNewMember } from './utils-share';
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
@@ -8,8 +8,14 @@ test.beforeEach(async ({ page }) => {
|
||||
});
|
||||
|
||||
test.describe('Document list members', () => {
|
||||
test('it checks a big list of members', async ({ page }) => {
|
||||
const docTitle = await goToGridDoc(page);
|
||||
test('it checks a big list of members', async ({ page, browserName }) => {
|
||||
const [docTitle] = await createDoc(
|
||||
page,
|
||||
'members-big-members-list',
|
||||
browserName,
|
||||
1,
|
||||
);
|
||||
|
||||
await verifyDocName(page, docTitle);
|
||||
|
||||
// Get the current URL and extract the last part
|
||||
@@ -25,7 +31,7 @@ test.describe('Document list members', () => {
|
||||
return cleanUrl.split('/').pop() || '';
|
||||
})();
|
||||
|
||||
await page.route('**/documents/**/accesses/', async (route) => {
|
||||
await page.route(/.*\/documents\/.*\/accesses\//, async (route) => {
|
||||
const request = route.request();
|
||||
const url = new URL(request.url());
|
||||
const pageId = url.searchParams.get('page') ?? '1';
|
||||
@@ -73,7 +79,7 @@ test.describe('Document list members', () => {
|
||||
await expect(loadMore).toBeHidden();
|
||||
});
|
||||
|
||||
test('it checks a big list of invitations', async ({ page }) => {
|
||||
test('it checks a big list of invitations', async ({ page, browserName }) => {
|
||||
await page.route(
|
||||
/.*\/documents\/.*\/invitations\/\?page=.*/,
|
||||
async (route) => {
|
||||
@@ -108,7 +114,12 @@ test.describe('Document list members', () => {
|
||||
},
|
||||
);
|
||||
|
||||
const docTitle = await goToGridDoc(page);
|
||||
const [docTitle] = await createDoc(
|
||||
page,
|
||||
'members-big-invitation-list',
|
||||
browserName,
|
||||
1,
|
||||
);
|
||||
await verifyDocName(page, docTitle);
|
||||
await page.getByRole('button', { name: 'Share' }).click();
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import {
|
||||
mockedDocument,
|
||||
verifyDocName,
|
||||
} from './utils-common';
|
||||
import { writeInEditor } from './utils-editor';
|
||||
import { createRootSubPage } from './utils-sub-pages';
|
||||
|
||||
test.describe('Doc Routing', () => {
|
||||
@@ -58,37 +59,39 @@ test.describe('Doc Routing', () => {
|
||||
|
||||
await createRootSubPage(page, browserName, '401-doc-child');
|
||||
|
||||
await page.locator('.ProseMirror.bn-editor').fill('Hello World');
|
||||
await writeInEditor({ page, text: 'Hello World' });
|
||||
|
||||
// Wait for the doc link (via its dynamic title) to be visible
|
||||
const docLink = page.getByRole('link', { name: docTitle });
|
||||
await expect(docLink).toBeVisible();
|
||||
const responsePromise = page.route(
|
||||
/.*\/documents\/.*\/$|users\/me\/$/,
|
||||
async (route) => {
|
||||
const request = route.request();
|
||||
|
||||
// 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()),
|
||||
// When we quit a document, a PATCH request is sent to save the document.
|
||||
// We intercept this request to simulate a 401 error from the backend.
|
||||
// The GET request to users/me is also intercepted to simulate the user
|
||||
// being logged out when trying to fetch user info.
|
||||
// This way we can test the 401 error handling when saving the document
|
||||
if (
|
||||
(request.url().includes('/documents/') &&
|
||||
request.method().includes('PATCH')) ||
|
||||
(request.url().includes('/users/me/') &&
|
||||
request.method().includes('GET'))
|
||||
) {
|
||||
await route.fulfill({
|
||||
status: 401,
|
||||
json: {
|
||||
detail: 'Log in to access the document',
|
||||
},
|
||||
});
|
||||
} else {
|
||||
await route.continue();
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
await docLink.click();
|
||||
await wait401;
|
||||
await page.getByRole('link', { name: '401-doc-parent' }).click();
|
||||
|
||||
await responsePromise;
|
||||
|
||||
await expect(page.getByText('Log in to access the document.')).toBeVisible({
|
||||
timeout: 10000,
|
||||
|
||||
155
src/frontend/apps/e2e/__tests__/app-impress/doc-trashbin.spec.ts
Normal file
155
src/frontend/apps/e2e/__tests__/app-impress/doc-trashbin.spec.ts
Normal file
@@ -0,0 +1,155 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
import {
|
||||
clickInEditorMenu,
|
||||
clickInGridMenu,
|
||||
createDoc,
|
||||
getGridRow,
|
||||
verifyDocName,
|
||||
} from './utils-common';
|
||||
import { addNewMember } from './utils-share';
|
||||
import {
|
||||
addChild,
|
||||
createRootSubPage,
|
||||
navigateToPageFromTree,
|
||||
} from './utils-sub-pages';
|
||||
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/');
|
||||
});
|
||||
|
||||
test.describe('Doc Trashbin', () => {
|
||||
test('it controls UI and interaction from the grid page', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
const [title1] = await createDoc(page, 'my-trash-doc-1', browserName, 1);
|
||||
const [title2] = await createDoc(page, 'my-trash-doc-2', browserName, 1);
|
||||
await verifyDocName(page, title2);
|
||||
await page.getByRole('button', { name: 'Share' }).click();
|
||||
await addNewMember(page, 0, 'Editor');
|
||||
await page.getByRole('button', { name: 'close' }).click();
|
||||
|
||||
await page.getByRole('button', { name: 'Back to homepage' }).click();
|
||||
|
||||
const row1 = await getGridRow(page, title1);
|
||||
await clickInGridMenu(page, row1, 'Delete');
|
||||
await page.getByRole('button', { name: 'Delete document' }).click();
|
||||
await expect(row1.getByText(title1)).toBeHidden();
|
||||
|
||||
const row2 = await getGridRow(page, title2);
|
||||
await clickInGridMenu(page, row2, 'Delete');
|
||||
await page.getByRole('button', { name: 'Delete document' }).click();
|
||||
await expect(row2.getByText(title2)).toBeHidden();
|
||||
|
||||
await page.getByRole('link', { name: 'Trashbin' }).click();
|
||||
|
||||
const docsGrid = page.getByTestId('docs-grid');
|
||||
await expect(docsGrid.getByText('Days remaining')).toBeVisible();
|
||||
await expect(row1.getByText(title1)).toBeVisible();
|
||||
await expect(row1.getByText('30 days')).toBeVisible();
|
||||
await expect(row2.getByText(title2)).toBeVisible();
|
||||
await expect(
|
||||
row2.getByRole('button', {
|
||||
name: 'Open the sharing settings for the document',
|
||||
}),
|
||||
).toBeVisible();
|
||||
await expect(
|
||||
row2.getByRole('button', {
|
||||
name: 'Open the sharing settings for the document',
|
||||
}),
|
||||
).toBeDisabled();
|
||||
|
||||
await clickInGridMenu(page, row2, 'Restore');
|
||||
|
||||
await expect(row2.getByText(title2)).toBeHidden();
|
||||
await page.getByRole('link', { name: 'All docs' }).click();
|
||||
const row2Restored = await getGridRow(page, title2);
|
||||
await expect(row2Restored.getByText(title2)).toBeVisible();
|
||||
await row2Restored.getByRole('link', { name: /Open document/ }).click();
|
||||
|
||||
await verifyDocName(page, title2);
|
||||
await page.getByRole('button', { name: 'Back to homepage' }).click();
|
||||
await expect(row2.getByText(title2)).toBeVisible();
|
||||
await expect(
|
||||
row2.getByRole('button', {
|
||||
name: 'Open the sharing settings for the document',
|
||||
}),
|
||||
).toBeEnabled();
|
||||
|
||||
await page.getByRole('link', { name: 'Trashbin' }).click();
|
||||
await expect(row2.getByText(title2)).toBeHidden();
|
||||
});
|
||||
|
||||
test('it controls UI and interaction from the doc page', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
const [topParent] = await createDoc(
|
||||
page,
|
||||
'my-trash-editor-doc',
|
||||
browserName,
|
||||
1,
|
||||
);
|
||||
await verifyDocName(page, topParent);
|
||||
const { name: subDocName } = await createRootSubPage(
|
||||
page,
|
||||
browserName,
|
||||
'my-trash-editor-subdoc',
|
||||
);
|
||||
|
||||
const subsubDocName = await addChild({
|
||||
page,
|
||||
browserName,
|
||||
docParent: subDocName,
|
||||
docName: 'my-trash-editor-subsubdoc',
|
||||
});
|
||||
await verifyDocName(page, subsubDocName);
|
||||
|
||||
await navigateToPageFromTree({ page, title: subDocName });
|
||||
await verifyDocName(page, subDocName);
|
||||
|
||||
await clickInEditorMenu(page, 'Delete sub-document');
|
||||
await page.getByRole('button', { name: 'Delete document' }).click();
|
||||
await verifyDocName(page, topParent);
|
||||
|
||||
await page.getByRole('button', { name: 'Back to homepage' }).click();
|
||||
await page.getByRole('link', { name: 'Trashbin' }).click();
|
||||
const row = await getGridRow(page, subDocName);
|
||||
await row.getByText(subDocName).click();
|
||||
await verifyDocName(page, subDocName);
|
||||
|
||||
await expect(
|
||||
page.locator('.--docs--editor-container.--docs--doc-deleted'),
|
||||
).toBeVisible();
|
||||
|
||||
await expect(page.getByLabel('Alert deleted document')).toBeVisible();
|
||||
await expect(page.getByRole('button', { name: 'Share' })).toBeDisabled();
|
||||
await expect(page.locator('.bn-editor')).toHaveAttribute(
|
||||
'contenteditable',
|
||||
'false',
|
||||
);
|
||||
const docTree = page.getByTestId('doc-tree');
|
||||
await expect(docTree.getByText(topParent)).toBeHidden();
|
||||
await expect(
|
||||
docTree.getByText(subDocName, {
|
||||
exact: true,
|
||||
}),
|
||||
).toBeVisible();
|
||||
await expect(docTree.getByText(subsubDocName)).toBeVisible();
|
||||
await expect(
|
||||
docTree
|
||||
.locator(".--docs-sub-page-item[aria-disabled='true']")
|
||||
.getByText(subsubDocName),
|
||||
).toBeVisible();
|
||||
|
||||
await page.getByRole('button', { name: 'Restore' }).click();
|
||||
await expect(page.getByLabel('Alert deleted document')).toBeHidden();
|
||||
await expect(page.locator('.bn-editor')).toHaveAttribute(
|
||||
'contenteditable',
|
||||
'true',
|
||||
);
|
||||
await expect(page.getByRole('button', { name: 'Share' })).toBeEnabled();
|
||||
await expect(docTree.getByText(topParent)).toBeVisible();
|
||||
});
|
||||
});
|
||||
@@ -9,7 +9,11 @@ import {
|
||||
verifyDocName,
|
||||
} from './utils-common';
|
||||
import { addNewMember } from './utils-share';
|
||||
import { clickOnAddRootSubPage, createRootSubPage } from './utils-sub-pages';
|
||||
import {
|
||||
clickOnAddRootSubPage,
|
||||
createRootSubPage,
|
||||
getTreeRow,
|
||||
} from './utils-sub-pages';
|
||||
|
||||
test.describe('Doc Tree', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
@@ -298,6 +302,58 @@ test.describe('Doc Tree', () => {
|
||||
// Now test keyboard navigation on sub-document
|
||||
await expect(docTree.getByText(docChild)).toBeVisible();
|
||||
});
|
||||
|
||||
test('it updates the child icon from the tree', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
const [docParent] = await createDoc(
|
||||
page,
|
||||
'doc-child-emoji',
|
||||
browserName,
|
||||
1,
|
||||
);
|
||||
await verifyDocName(page, docParent);
|
||||
|
||||
const { name: docChild } = await createRootSubPage(
|
||||
page,
|
||||
browserName,
|
||||
'doc-child-emoji-child',
|
||||
);
|
||||
|
||||
const row = await getTreeRow(page, docChild);
|
||||
|
||||
// Check Remove emoji is not present initially
|
||||
await row.hover();
|
||||
const menu = row.getByText(`more_horiz`);
|
||||
await menu.click();
|
||||
await expect(
|
||||
page.getByRole('menuitem', { name: 'Remove emoji' }),
|
||||
).toBeHidden();
|
||||
|
||||
// Close the menu
|
||||
await page.keyboard.press('Escape');
|
||||
|
||||
// Update the emoji from the tree
|
||||
await row.locator('.--docs--doc-icon').click();
|
||||
await page.getByRole('button', { name: '😀' }).first().click();
|
||||
|
||||
// Verify the emoji is updated in the tree and in the document title
|
||||
await expect(row.getByText('😀')).toBeVisible();
|
||||
|
||||
const titleEmojiPicker = page
|
||||
.locator('.--docs--doc-title')
|
||||
.getByRole('button');
|
||||
await expect(titleEmojiPicker).toHaveText('😀');
|
||||
|
||||
// Now remove the emoji using the new action
|
||||
await row.hover();
|
||||
await menu.click();
|
||||
await page.getByRole('menuitem', { name: 'Remove emoji' }).click();
|
||||
|
||||
await expect(row.getByText('😀')).toBeHidden();
|
||||
await expect(titleEmojiPicker).toBeHidden();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Doc Tree: Inheritance', () => {
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
keyCloakSignIn,
|
||||
verifyDocName,
|
||||
} from './utils-common';
|
||||
import { getEditor, writeInEditor } from './utils-editor';
|
||||
import { addNewMember, connectOtherUserToDoc } from './utils-share';
|
||||
import { createRootSubPage } from './utils-sub-pages';
|
||||
|
||||
@@ -151,18 +152,15 @@ test.describe('Doc Visibility: Restricted', () => {
|
||||
|
||||
await verifyDocName(page, docTitle);
|
||||
|
||||
await page
|
||||
.locator('.ProseMirror')
|
||||
.locator('.bn-block-outer')
|
||||
.last()
|
||||
.fill('Hello World');
|
||||
await writeInEditor({ page, text: 'Hello World' });
|
||||
|
||||
const urlDoc = page.url();
|
||||
const docUrl = page.url();
|
||||
|
||||
const { otherBrowserName, otherPage } = await connectOtherUserToDoc(
|
||||
browserName,
|
||||
urlDoc,
|
||||
);
|
||||
const { otherBrowserName, otherPage, cleanup } =
|
||||
await connectOtherUserToDoc({
|
||||
browserName,
|
||||
docUrl,
|
||||
});
|
||||
|
||||
await expect(
|
||||
otherPage.getByText('Insufficient access rights to view the document.'),
|
||||
@@ -175,20 +173,23 @@ test.describe('Doc Visibility: Restricted', () => {
|
||||
await addNewMember(page, 0, 'Reader', otherBrowserName);
|
||||
|
||||
await otherPage.reload();
|
||||
await expect(otherPage.getByText('Hello World')).toBeVisible();
|
||||
await expect(otherPage.getByText('Hello World')).toBeVisible({
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
await cleanup();
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Doc Visibility: Public', () => {
|
||||
test.use({ storageState: { cookies: [], origins: [] } });
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/');
|
||||
});
|
||||
|
||||
test('It checks a public doc in read only mode', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
await page.goto('/');
|
||||
await keyCloakSignIn(page, browserName);
|
||||
|
||||
const [docTitle] = await createDoc(
|
||||
page,
|
||||
'Public read only',
|
||||
@@ -198,6 +199,8 @@ test.describe('Doc Visibility: Public', () => {
|
||||
|
||||
await verifyDocName(page, docTitle);
|
||||
|
||||
await writeInEditor({ page, text: 'Hello Public Viewonly' });
|
||||
|
||||
await page.getByRole('button', { name: 'Share' }).click();
|
||||
const selectVisibility = page.getByTestId('doc-visibility');
|
||||
await selectVisibility.click();
|
||||
@@ -239,49 +242,67 @@ test.describe('Doc Visibility: Public', () => {
|
||||
await expect(page.getByTestId('search-docs-button')).toBeVisible();
|
||||
await expect(page.getByTestId('new-doc-button')).toBeVisible();
|
||||
|
||||
const urlDoc = page.url();
|
||||
const docUrl = page.url();
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
name: 'Logout',
|
||||
})
|
||||
.click();
|
||||
const { otherPage, cleanup } = await connectOtherUserToDoc({
|
||||
browserName,
|
||||
docUrl,
|
||||
withoutSignIn: true,
|
||||
});
|
||||
|
||||
await expectLoginPage(page);
|
||||
|
||||
await page.goto(urlDoc);
|
||||
|
||||
await expect(page.locator('h2').getByText(docTitle)).toBeVisible();
|
||||
await expect(page.getByTestId('search-docs-button')).toBeHidden();
|
||||
await expect(page.getByTestId('new-doc-button')).toBeHidden();
|
||||
await expect(page.getByRole('button', { name: 'Share' })).toBeVisible();
|
||||
const card = page.getByLabel('It is the card information');
|
||||
await expect(otherPage.locator('h2').getByText(docTitle)).toBeVisible();
|
||||
await expect(otherPage.getByTestId('search-docs-button')).toBeHidden();
|
||||
await expect(otherPage.getByTestId('new-doc-button')).toBeHidden();
|
||||
await expect(
|
||||
otherPage.getByRole('button', { name: 'Share' }),
|
||||
).toBeVisible();
|
||||
const card = otherPage.getByLabel('It is the card information');
|
||||
await expect(card).toBeVisible();
|
||||
await expect(card.getByText('Reader')).toBeVisible();
|
||||
|
||||
await page.getByRole('button', { name: 'Share' }).click();
|
||||
await expect(
|
||||
page.getByText(
|
||||
otherPage.locator('.--docs--editor-container.--docs--doc-readonly'),
|
||||
).toBeVisible();
|
||||
|
||||
const otherEditor = await getEditor({ page: otherPage });
|
||||
await expect(otherEditor).toHaveAttribute('contenteditable', 'false');
|
||||
await expect(otherEditor.getByText('Hello Public Viewonly')).toBeVisible();
|
||||
|
||||
// Cursor and selection of the anonymous user are not visible
|
||||
await otherEditor.getByText('Hello Public').selectText();
|
||||
await expect(
|
||||
page.locator('.collaboration-cursor-custom__base'),
|
||||
).toBeHidden();
|
||||
await expect(page.locator('.ProseMirror-yjs-selection')).toBeHidden();
|
||||
|
||||
// Can still see changes made by others
|
||||
await writeInEditor({ page, text: 'Can you see it ?' });
|
||||
await expect(otherEditor.getByText('Can you see it ?')).toBeVisible();
|
||||
|
||||
await otherPage.getByRole('button', { name: 'Share' }).click();
|
||||
await expect(
|
||||
otherPage.getByText(
|
||||
'You can view this document but need additional access to see its members or modify settings.',
|
||||
),
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
page.getByRole('button', { name: 'Request access' }),
|
||||
otherPage.getByRole('button', { name: 'Request access' }),
|
||||
).toBeHidden();
|
||||
|
||||
await cleanup();
|
||||
});
|
||||
|
||||
test('It checks a public doc in editable mode', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
await page.goto('/');
|
||||
await keyCloakSignIn(page, browserName);
|
||||
|
||||
const [docTitle] = await createDoc(page, 'Public editable', browserName, 1);
|
||||
|
||||
await verifyDocName(page, docTitle);
|
||||
|
||||
await writeInEditor({ page, text: 'Hello Public Editable' });
|
||||
|
||||
await page.getByRole('button', { name: 'Share' }).click();
|
||||
const selectVisibility = page.getByTestId('doc-visibility');
|
||||
await selectVisibility.click();
|
||||
@@ -315,20 +336,47 @@ test.describe('Doc Visibility: Public', () => {
|
||||
cardContainer.getByText('Public document', { exact: true }),
|
||||
).toBeVisible();
|
||||
|
||||
const urlDoc = page.url();
|
||||
const docUrl = page.url();
|
||||
|
||||
await page
|
||||
.getByRole('button', {
|
||||
name: 'Logout',
|
||||
})
|
||||
.click();
|
||||
const { otherPage, cleanup } = await connectOtherUserToDoc({
|
||||
browserName,
|
||||
docUrl,
|
||||
withoutSignIn: true,
|
||||
docTitle,
|
||||
});
|
||||
|
||||
await expectLoginPage(page);
|
||||
await expect(otherPage.getByTestId('search-docs-button')).toBeHidden();
|
||||
await expect(otherPage.getByTestId('new-doc-button')).toBeHidden();
|
||||
|
||||
await page.goto(urlDoc);
|
||||
const otherEditor = await getEditor({ page: otherPage });
|
||||
await expect(otherEditor).toHaveAttribute('contenteditable', 'true');
|
||||
await expect(otherEditor.getByText('Hello Public Editable')).toBeVisible();
|
||||
|
||||
await verifyDocName(page, docTitle);
|
||||
await expect(page.getByRole('button', { name: 'Share' })).toBeVisible();
|
||||
// We can see the collaboration cursor of the anonymous user
|
||||
await otherEditor.getByText('Hello Public').selectText();
|
||||
await expect(
|
||||
page.locator('.collaboration-cursor-custom__base').getByText('Anonymous'),
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
otherPage.getByRole('button', { name: 'Share' }),
|
||||
).toBeVisible();
|
||||
const card = otherPage.getByLabel('It is the card information');
|
||||
await expect(card).toBeVisible();
|
||||
await expect(card.getByText('Editor')).toBeVisible();
|
||||
|
||||
await otherPage.getByRole('button', { name: 'Share' }).click();
|
||||
await expect(
|
||||
otherPage.getByText(
|
||||
'You can view this document but need additional access to see its members or modify settings.',
|
||||
),
|
||||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
otherPage.getByRole('button', { name: 'Request access' }),
|
||||
).toBeHidden();
|
||||
|
||||
await cleanup();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -32,6 +32,15 @@ test.describe('Header', () => {
|
||||
}) => {
|
||||
await overrideConfig(page, {
|
||||
FRONTEND_THEME: 'dsfr',
|
||||
theme_customization: {
|
||||
header: {
|
||||
logo: {
|
||||
src: '/assets/logo-gouv.svg',
|
||||
width: '220px',
|
||||
alt: 'Gouvernement Logo',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
await page.goto('/');
|
||||
|
||||
@@ -98,6 +107,15 @@ test.describe('Header mobile', () => {
|
||||
test('it checks the header when mobile with DSFR theme', async ({ page }) => {
|
||||
await overrideConfig(page, {
|
||||
FRONTEND_THEME: 'dsfr',
|
||||
theme_customization: {
|
||||
header: {
|
||||
logo: {
|
||||
src: '/assets/logo-gouv.svg',
|
||||
width: '220px',
|
||||
alt: 'Gouvernement Logo',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await page.goto('/');
|
||||
@@ -131,3 +149,30 @@ test.describe('Header: Log out', () => {
|
||||
await expectLoginPage(page);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Header: Override configuration', () => {
|
||||
test('checks the header is correctly overrided', async ({ page }) => {
|
||||
await overrideConfig(page, {
|
||||
FRONTEND_THEME: 'dsfr',
|
||||
theme_customization: {
|
||||
header: {
|
||||
logo: {
|
||||
src: '/assets/logo-gouv.svg',
|
||||
width: '220px',
|
||||
alt: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
await page.goto('/');
|
||||
const header = page.locator('header').first();
|
||||
|
||||
const logoImage = header.getByTestId('header-icon-docs');
|
||||
await expect(logoImage).toBeVisible();
|
||||
|
||||
await expect(logoImage).not.toHaveAttribute('src', '/assets/icon-docs.svg');
|
||||
await expect(logoImage).toHaveAttribute('src', '/assets/logo-gouv.svg');
|
||||
await expect(logoImage).toHaveAttribute('alt', '');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
import { TestLanguage, createDoc, waitForLanguageSwitch } from './utils-common';
|
||||
import { openSuggestionMenu } from './utils-editor';
|
||||
|
||||
test.describe('Language', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
@@ -51,6 +52,7 @@ test.describe('Language', () => {
|
||||
await expect(page.locator('html')).toHaveAttribute('lang', 'en');
|
||||
await expect(languagePicker).toContainText('English');
|
||||
});
|
||||
|
||||
test('can switch language using only keyboard', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
await waitForLanguageSwitch(page, TestLanguage.English);
|
||||
@@ -106,18 +108,18 @@ test.describe('Language', () => {
|
||||
}) => {
|
||||
await createDoc(page, 'doc-toolbar', browserName, 1);
|
||||
|
||||
const editor = page.locator('.ProseMirror');
|
||||
|
||||
// Trigger slash menu to show english menu
|
||||
await editor.click();
|
||||
await editor.fill('/');
|
||||
const editor = await openSuggestionMenu({ page });
|
||||
await expect(page.getByText('Headings', { exact: true })).toBeVisible();
|
||||
|
||||
await editor.click(); // close the menu
|
||||
|
||||
await expect(page.getByText('Headings', { exact: true })).toBeHidden();
|
||||
|
||||
// Change language to French
|
||||
await waitForLanguageSwitch(page, TestLanguage.French);
|
||||
|
||||
// Trigger slash menu to show french menu
|
||||
await editor.locator('.bn-block-outer').last().fill('/');
|
||||
await openSuggestionMenu({ page });
|
||||
await expect(page.getByText('Titres', { exact: true })).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import { expect, test } from '@playwright/test';
|
||||
|
||||
import { createDoc } from './utils-common';
|
||||
|
||||
test.describe('Left panel desktop', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
await page.goto('/');
|
||||
@@ -11,6 +13,53 @@ test.describe('Left panel desktop', () => {
|
||||
await expect(page.getByTestId('home-button')).toBeVisible();
|
||||
await expect(page.getByTestId('new-doc-button')).toBeVisible();
|
||||
});
|
||||
|
||||
test('checks resize handle is present and functional on document page', async ({
|
||||
page,
|
||||
browserName,
|
||||
}) => {
|
||||
// On home page, resize handle should NOT be present
|
||||
let resizeHandle = page.locator('[data-panel-resize-handle-id]');
|
||||
await expect(resizeHandle).toBeHidden();
|
||||
|
||||
// Create and navigate to a document
|
||||
await createDoc(page, 'doc-resize-test', browserName, 1);
|
||||
|
||||
// Now resize handle should be visible on document page
|
||||
resizeHandle = page.locator('[data-panel-resize-handle-id]').first();
|
||||
await expect(resizeHandle).toBeVisible();
|
||||
|
||||
const leftPanel = page.getByTestId('left-panel-desktop');
|
||||
await expect(leftPanel).toBeVisible();
|
||||
|
||||
// Get initial panel width
|
||||
const initialBox = await leftPanel.boundingBox();
|
||||
expect(initialBox).not.toBeNull();
|
||||
|
||||
// Get handle position
|
||||
const handleBox = await resizeHandle.boundingBox();
|
||||
expect(handleBox).not.toBeNull();
|
||||
|
||||
// Test resize by dragging the handle
|
||||
await page.mouse.move(
|
||||
handleBox!.x + handleBox!.width / 2,
|
||||
handleBox!.y + handleBox!.height / 2,
|
||||
);
|
||||
await page.mouse.down();
|
||||
await page.mouse.move(
|
||||
handleBox!.x + 100,
|
||||
handleBox!.y + handleBox!.height / 2,
|
||||
);
|
||||
await page.mouse.up();
|
||||
|
||||
// Wait for resize to complete
|
||||
await page.waitForTimeout(200);
|
||||
|
||||
// Verify the panel has been resized
|
||||
const newBox = await leftPanel.boundingBox();
|
||||
expect(newBox).not.toBeNull();
|
||||
expect(newBox!.width).toBeGreaterThan(initialBox!.width);
|
||||
});
|
||||
});
|
||||
|
||||
test.describe('Left panel mobile', () => {
|
||||
@@ -47,4 +96,12 @@ test.describe('Left panel mobile', () => {
|
||||
await expect(languageButton).toBeInViewport();
|
||||
await expect(logoutButton).toBeInViewport();
|
||||
});
|
||||
|
||||
test('checks resize handle is not present on mobile', async ({ page }) => {
|
||||
await page.goto('/');
|
||||
|
||||
// Verify the resize handle is NOT present on mobile
|
||||
const resizeHandle = page.locator('[data-panel-resize-handle-id]');
|
||||
await expect(resizeHandle).toBeHidden();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Page, expect } from '@playwright/test';
|
||||
import { Locator, Page, expect } from '@playwright/test';
|
||||
|
||||
export type BrowserName = 'chromium' | 'firefox' | 'webkit';
|
||||
export const BROWSERS: BrowserName[] = ['chromium', 'webkit', 'firefox'];
|
||||
@@ -23,6 +23,7 @@ export const CONFIG = {
|
||||
LANGUAGE_CODE: 'en-us',
|
||||
POSTHOG_KEY: {},
|
||||
SENTRY_DSN: null,
|
||||
TRASHBIN_CUTOFF_DAYS: 30,
|
||||
theme_customization: {},
|
||||
} as const;
|
||||
|
||||
@@ -30,7 +31,7 @@ export const overrideConfig = async (
|
||||
page: Page,
|
||||
newConfig: { [_K in keyof typeof CONFIG]?: unknown },
|
||||
) =>
|
||||
await page.route('**/api/v1.0/config/', async (route) => {
|
||||
await page.route(/.*\/api\/v1.0\/config\/.*/, async (route) => {
|
||||
const request = route.request();
|
||||
if (request.method().includes('GET')) {
|
||||
await route.fulfill({
|
||||
@@ -47,7 +48,7 @@ export const overrideConfig = async (
|
||||
export const keyCloakSignIn = async (
|
||||
page: Page,
|
||||
browserName: string,
|
||||
fromHome: boolean = true,
|
||||
fromHome = true,
|
||||
) => {
|
||||
if (fromHome) {
|
||||
await page.getByRole('button', { name: 'Start Writing' }).first().click();
|
||||
@@ -78,8 +79,8 @@ export const createDoc = async (
|
||||
page: Page,
|
||||
docName: string,
|
||||
browserName: string,
|
||||
length: number = 1,
|
||||
isMobile: boolean = false,
|
||||
length = 1,
|
||||
isMobile = false,
|
||||
) => {
|
||||
const randomDocs = randomName(docName, browserName, length);
|
||||
|
||||
@@ -203,7 +204,7 @@ export const waitForResponseCreateDoc = (page: Page) => {
|
||||
};
|
||||
|
||||
export const mockedDocument = async (page: Page, data: object) => {
|
||||
await page.route('**/documents/**/', async (route) => {
|
||||
await page.route(/\**\/documents\/\**/, async (route) => {
|
||||
const request = route.request();
|
||||
if (
|
||||
request.method().includes('GET') &&
|
||||
@@ -255,7 +256,7 @@ export const mockedDocument = async (page: Page, data: object) => {
|
||||
};
|
||||
|
||||
export const mockedListDocs = async (page: Page, data: object[] = []) => {
|
||||
await page.route('**/documents/**/', async (route) => {
|
||||
await page.route(/\**\/documents\/\**/, async (route) => {
|
||||
const request = route.request();
|
||||
if (request.method().includes('GET') && request.url().includes('page=')) {
|
||||
await route.fulfill({
|
||||
@@ -276,6 +277,7 @@ export const expectLoginPage = async (page: Page) =>
|
||||
).toBeVisible({
|
||||
timeout: 10000,
|
||||
});
|
||||
|
||||
// language helper
|
||||
export const TestLanguage = {
|
||||
English: {
|
||||
@@ -299,7 +301,7 @@ export async function waitForLanguageSwitch(
|
||||
page: Page,
|
||||
lang: TestLanguageValue,
|
||||
) {
|
||||
await page.route('**/api/v1.0/users/**', async (route, request) => {
|
||||
await page.route(/\**\/api\/v1.0\/users\/\**/, async (route, request) => {
|
||||
if (request.method().includes('PATCH')) {
|
||||
await route.fulfill({
|
||||
json: {
|
||||
@@ -325,3 +327,19 @@ export async function waitForLanguageSwitch(
|
||||
|
||||
await page.getByRole('menuitem', { name: lang.label }).click();
|
||||
}
|
||||
|
||||
export const clickInEditorMenu = async (page: Page, textButton: string) => {
|
||||
await page.getByRole('button', { name: 'Open the document options' }).click();
|
||||
await page.getByRole('menuitem', { name: textButton }).click();
|
||||
};
|
||||
|
||||
export const clickInGridMenu = async (
|
||||
page: Page,
|
||||
row: Locator,
|
||||
textButton: string,
|
||||
) => {
|
||||
await row
|
||||
.getByRole('button', { name: /Open the menu of actions for the document/ })
|
||||
.click();
|
||||
await page.getByRole('menuitem', { name: textButton }).click();
|
||||
};
|
||||
|
||||
@@ -9,7 +9,7 @@ export const getEditor = async ({ page }: { page: Page }) => {
|
||||
export const openSuggestionMenu = async ({ page }: { page: Page }) => {
|
||||
const editor = await getEditor({ page });
|
||||
await editor.click();
|
||||
await page.locator('.bn-block-outer').last().fill('/');
|
||||
await writeInEditor({ page, text: '/' });
|
||||
|
||||
return editor;
|
||||
};
|
||||
@@ -22,6 +22,6 @@ export const writeInEditor = async ({
|
||||
text: string;
|
||||
}) => {
|
||||
const editor = await getEditor({ page });
|
||||
editor.locator('.bn-block-outer').last().fill(text);
|
||||
await editor.locator('.bn-block-outer .bn-inline-content').last().fill(text);
|
||||
return editor;
|
||||
};
|
||||
|
||||
@@ -9,13 +9,13 @@ import {
|
||||
|
||||
export type Role = 'Administrator' | 'Owner' | 'Member' | 'Editor' | 'Reader';
|
||||
export type LinkReach = 'Private' | 'Connected' | 'Public';
|
||||
export type LinkRole = 'Reading' | 'Edition';
|
||||
export type LinkRole = 'Reading' | 'Editing';
|
||||
|
||||
export const addNewMember = async (
|
||||
page: Page,
|
||||
index: number,
|
||||
role: 'Administrator' | 'Owner' | 'Editor' | 'Reader',
|
||||
fillText: string = 'user.test',
|
||||
fillText = 'user.test',
|
||||
) => {
|
||||
const responsePromiseSearchUser = page.waitForResponse(
|
||||
(response) =>
|
||||
@@ -88,11 +88,17 @@ export const updateRoleUser = async (
|
||||
* @param docTitle The title of the document (optional).
|
||||
* @returns An object containing the other browser, context, and page.
|
||||
*/
|
||||
export const connectOtherUserToDoc = async (
|
||||
browserName: BrowserName,
|
||||
docUrl: string,
|
||||
docTitle?: string,
|
||||
) => {
|
||||
export const connectOtherUserToDoc = async ({
|
||||
browserName,
|
||||
docUrl,
|
||||
docTitle,
|
||||
withoutSignIn,
|
||||
}: {
|
||||
browserName: BrowserName;
|
||||
docUrl: string;
|
||||
docTitle?: string;
|
||||
withoutSignIn?: boolean;
|
||||
}) => {
|
||||
const otherBrowserName = BROWSERS.find((b) => b !== browserName);
|
||||
if (!otherBrowserName) {
|
||||
throw new Error('No alternative browser found');
|
||||
@@ -111,15 +117,20 @@ export const connectOtherUserToDoc = async (
|
||||
const otherPage = await otherContext.newPage();
|
||||
await otherPage.goto(docUrl);
|
||||
|
||||
await otherPage
|
||||
.getByRole('main', { name: 'Main content' })
|
||||
.getByLabel('Login')
|
||||
.click({
|
||||
if (!withoutSignIn) {
|
||||
const loginFromApp = otherPage
|
||||
.getByRole('main', { name: 'Main content' })
|
||||
.getByLabel('Login');
|
||||
const loginFromHome = otherPage.getByRole('button', {
|
||||
name: 'Start Writing',
|
||||
});
|
||||
|
||||
await loginFromApp.or(loginFromHome).first().click({
|
||||
timeout: 15000,
|
||||
});
|
||||
|
||||
await keyCloakSignIn(otherPage, otherBrowserName, false);
|
||||
|
||||
await keyCloakSignIn(otherPage, otherBrowserName, false);
|
||||
}
|
||||
if (docTitle) {
|
||||
await verifyDocName(otherPage, docTitle);
|
||||
}
|
||||
@@ -152,7 +163,7 @@ export const mockedInvitations = async (page: Page, json?: object) => {
|
||||
...json,
|
||||
},
|
||||
];
|
||||
await page.route('**/invitations/**/', async (route) => {
|
||||
await page.route(/.*\/invitations\/.*/, async (route) => {
|
||||
const request = route.request();
|
||||
if (
|
||||
request.method().includes('GET') &&
|
||||
@@ -173,7 +184,7 @@ export const mockedInvitations = async (page: Page, json?: object) => {
|
||||
});
|
||||
|
||||
await page.route(
|
||||
'**/invitations/120ec765-43af-4602-83eb-7f4e1224548a/**/',
|
||||
/.*\/invitations\/120ec765-43af-4602-83eb-7f4e1224548a\/.*/,
|
||||
async (route) => {
|
||||
const request = route.request();
|
||||
if (request.method().includes('DELETE')) {
|
||||
@@ -188,7 +199,7 @@ export const mockedInvitations = async (page: Page, json?: object) => {
|
||||
};
|
||||
|
||||
export const mockedAccesses = async (page: Page, json?: object) => {
|
||||
await page.route('**/accesses/**/', async (route) => {
|
||||
await page.route(/.*\/accesses\/.*/, async (route) => {
|
||||
const request = route.request();
|
||||
|
||||
if (
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Page, expect } from '@playwright/test';
|
||||
|
||||
import {
|
||||
BrowserName,
|
||||
randomName,
|
||||
updateDocTitle,
|
||||
verifyDocName,
|
||||
@@ -9,9 +10,9 @@ import {
|
||||
|
||||
export const createRootSubPage = async (
|
||||
page: Page,
|
||||
browserName: string,
|
||||
browserName: BrowserName,
|
||||
docName: string,
|
||||
isMobile: boolean = false,
|
||||
isMobile = false,
|
||||
) => {
|
||||
if (isMobile) {
|
||||
await page
|
||||
@@ -67,6 +68,63 @@ export const clickOnAddRootSubPage = async (page: Page) => {
|
||||
await rootItem.getByTestId('doc-tree-item-actions-add-child').click();
|
||||
};
|
||||
|
||||
export const addChild = async ({
|
||||
page,
|
||||
browserName,
|
||||
docParent,
|
||||
docName,
|
||||
}: {
|
||||
page: Page;
|
||||
browserName: BrowserName;
|
||||
docParent: string;
|
||||
docName: string;
|
||||
}) => {
|
||||
let item = page.getByTestId('doc-tree-root-item');
|
||||
|
||||
const isParent = await item
|
||||
.filter({
|
||||
hasText: docParent,
|
||||
})
|
||||
.first()
|
||||
.count();
|
||||
|
||||
if (!isParent) {
|
||||
const items = page.getByRole('treeitem');
|
||||
|
||||
item = items
|
||||
.filter({
|
||||
hasText: docParent,
|
||||
})
|
||||
.first();
|
||||
}
|
||||
|
||||
await item.hover();
|
||||
await item.getByTestId('doc-tree-item-actions-add-child').click();
|
||||
|
||||
const [name] = randomName(docName, browserName, 1);
|
||||
await updateDocTitle(page, name);
|
||||
|
||||
return name;
|
||||
};
|
||||
|
||||
export const getTreeRow = async (page: Page, title: string) => {
|
||||
const docTree = page.getByTestId('doc-tree');
|
||||
const row = docTree
|
||||
.getByRole('treeitem')
|
||||
.filter({
|
||||
hasText: title,
|
||||
})
|
||||
.first();
|
||||
|
||||
await expect(row).toBeVisible();
|
||||
|
||||
return row;
|
||||
};
|
||||
|
||||
export const navigateToTopParentFromTree = async ({ page }: { page: Page }) => {
|
||||
await page.getByRole('link', { name: /Open root document/ }).click();
|
||||
};
|
||||
|
||||
export const navigateToPageFromTree = async ({
|
||||
page,
|
||||
title,
|
||||
@@ -75,6 +133,10 @@ export const navigateToPageFromTree = async ({
|
||||
title: string;
|
||||
}) => {
|
||||
const docTree = page.getByTestId('doc-tree');
|
||||
await docTree.getByText(title).click();
|
||||
await docTree
|
||||
.getByText(title, {
|
||||
exact: true,
|
||||
})
|
||||
.click();
|
||||
await verifyDocName(page, title);
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "app-e2e",
|
||||
"version": "3.7.0",
|
||||
"version": "3.9.0",
|
||||
"repository": "https://github.com/suitenumerique/docs",
|
||||
"author": "DINUM",
|
||||
"license": "MIT",
|
||||
@@ -15,7 +15,7 @@
|
||||
"test:ui::chromium": "yarn test:ui --project=chromium"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "1.55.0",
|
||||
"@playwright/test": "1.56.1",
|
||||
"@types/node": "*",
|
||||
"@types/pdf-parse": "1.1.5",
|
||||
"eslint-plugin-docs": "*",
|
||||
@@ -23,7 +23,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"convert-stream": "1.0.2",
|
||||
"pdf-parse": "1.1.1"
|
||||
"pdf-parse": "2.4.5"
|
||||
},
|
||||
"packageManager": "yarn@1.22.22"
|
||||
}
|
||||
|
||||
5
src/frontend/apps/impress/.gitignore
vendored
5
src/frontend/apps/impress/.gitignore
vendored
@@ -35,3 +35,8 @@ yarn-error.log*
|
||||
*.tsbuildinfo
|
||||
|
||||
service-worker.js
|
||||
|
||||
# Font embedding
|
||||
public/assets/fonts/emoji/*
|
||||
!public/assets/fonts/emoji/fallback.png
|
||||
public/assets/fonts/Marianne/*
|
||||
@@ -1,2 +1,3 @@
|
||||
next-env.d.ts
|
||||
service-worker.js
|
||||
public/assets/fonts/*
|
||||
|
||||
3
src/frontend/apps/impress/.stylelintignore
Normal file
3
src/frontend/apps/impress/.stylelintignore
Normal file
@@ -0,0 +1,3 @@
|
||||
out/**/*
|
||||
public/assets/fonts/**/*
|
||||
node_modules/**/*
|
||||
@@ -1,5 +1,7 @@
|
||||
const crypto = require('crypto');
|
||||
const path = require('path');
|
||||
|
||||
const CopyPlugin = require('copy-webpack-plugin');
|
||||
const { InjectManifest } = require('workbox-webpack-plugin');
|
||||
|
||||
const buildId = crypto.randomBytes(256).toString('hex').slice(0, 8);
|
||||
@@ -41,6 +43,30 @@ const nextConfig = {
|
||||
},
|
||||
);
|
||||
|
||||
// Copy necessary fonts from node_modules to public directory during build or dev
|
||||
config.plugins.push(
|
||||
new CopyPlugin({
|
||||
patterns: [
|
||||
{
|
||||
from: path.resolve(
|
||||
__dirname,
|
||||
'../../node_modules/emoji-datasource-apple/img/apple/64',
|
||||
),
|
||||
to: path.resolve(__dirname, 'public/assets/fonts/emoji'),
|
||||
force: true,
|
||||
},
|
||||
{
|
||||
from: path.resolve(
|
||||
__dirname,
|
||||
'../../node_modules/@gouvfr-lasuite/ui-kit/dist/assets/fonts/Marianne',
|
||||
),
|
||||
to: path.resolve(__dirname, 'public/assets/fonts/Marianne'),
|
||||
force: true,
|
||||
},
|
||||
],
|
||||
}),
|
||||
);
|
||||
|
||||
if (!isServer && process.env.NEXT_PUBLIC_SW_DEACTIVATED !== 'true') {
|
||||
config.plugins.push(
|
||||
new InjectManifest({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "app-impress",
|
||||
"version": "3.7.0",
|
||||
"version": "3.9.0",
|
||||
"repository": "https://github.com/suitenumerique/docs",
|
||||
"author": "DINUM",
|
||||
"license": "MIT",
|
||||
@@ -19,44 +19,51 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@ag-media/react-pdf-table": "2.0.3",
|
||||
"@blocknote/code-block": "0.37.0",
|
||||
"@blocknote/core": "0.37.0",
|
||||
"@blocknote/mantine": "0.37.0",
|
||||
"@blocknote/react": "0.37.0",
|
||||
"@blocknote/xl-docx-exporter": "0.37.0",
|
||||
"@blocknote/xl-multi-column": "0.37.0",
|
||||
"@blocknote/xl-pdf-exporter": "0.37.0",
|
||||
"@blocknote/code-block": "0.41.1",
|
||||
"@blocknote/core": "0.41.1",
|
||||
"@blocknote/mantine": "0.41.1",
|
||||
"@blocknote/react": "0.41.1",
|
||||
"@blocknote/xl-docx-exporter": "0.41.1",
|
||||
"@blocknote/xl-multi-column": "0.41.1",
|
||||
"@blocknote/xl-pdf-exporter": "0.41.1",
|
||||
"@dnd-kit/core": "6.3.1",
|
||||
"@dnd-kit/modifiers": "9.0.0",
|
||||
"@emoji-mart/data": "1.2.1",
|
||||
"@emoji-mart/react": "1.1.1",
|
||||
"@fontsource/material-icons": "5.2.5",
|
||||
"@fontsource-variable/inter": "5.2.8",
|
||||
"@fontsource-variable/material-symbols-outlined": "5.2.28",
|
||||
"@fontsource/material-icons": "5.2.7",
|
||||
"@gouvfr-lasuite/integration": "1.0.3",
|
||||
"@gouvfr-lasuite/ui-kit": "0.16.1",
|
||||
"@hocuspocus/provider": "2.15.2",
|
||||
"@gouvfr-lasuite/ui-kit": "0.16.2",
|
||||
"@hocuspocus/provider": "3.4.0",
|
||||
"@mantine/core": "8.3.6",
|
||||
"@mantine/hooks": "8.3.6",
|
||||
"@openfun/cunningham-react": "3.2.3",
|
||||
"@react-pdf/renderer": "4.3.0",
|
||||
"@sentry/nextjs": "10.11.0",
|
||||
"@tanstack/react-query": "5.87.4",
|
||||
"@react-pdf/renderer": "4.3.1",
|
||||
"@sentry/nextjs": "10.22.0",
|
||||
"@tanstack/react-query": "5.90.6",
|
||||
"@tiptap/extensions": "3.10.1",
|
||||
"canvg": "4.0.3",
|
||||
"clsx": "2.1.1",
|
||||
"cmdk": "1.1.1",
|
||||
"crisp-sdk-web": "1.0.25",
|
||||
"docx": "9.5.0",
|
||||
"crisp-sdk-web": "1.0.26",
|
||||
"docx": "*",
|
||||
"emoji-datasource-apple": "16.0.0",
|
||||
"emoji-mart": "5.6.0",
|
||||
"emoji-regex": "10.5.0",
|
||||
"i18next": "25.5.2",
|
||||
"emoji-regex": "10.6.0",
|
||||
"i18next": "25.6.0",
|
||||
"i18next-browser-languagedetector": "8.2.0",
|
||||
"idb": "8.0.3",
|
||||
"lodash": "4.17.21",
|
||||
"luxon": "3.7.2",
|
||||
"next": "15.5.3",
|
||||
"posthog-js": "1.264.2",
|
||||
"next": "15.5.4",
|
||||
"posthog-js": "1.284.0",
|
||||
"react": "*",
|
||||
"react-aria-components": "1.12.1",
|
||||
"react-aria-components": "1.13.0",
|
||||
"react-dom": "*",
|
||||
"react-i18next": "15.7.3",
|
||||
"react-intersection-observer": "9.16.0",
|
||||
"react-i18next": "16.2.3",
|
||||
"react-intersection-observer": "10.0.0",
|
||||
"react-resizable-panels": "3.0.6",
|
||||
"react-select": "5.10.2",
|
||||
"styled-components": "6.1.19",
|
||||
"use-debounce": "10.0.6",
|
||||
@@ -66,9 +73,9 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@svgr/webpack": "8.1.0",
|
||||
"@tanstack/react-query-devtools": "5.87.4",
|
||||
"@tanstack/react-query-devtools": "5.90.2",
|
||||
"@testing-library/dom": "10.4.1",
|
||||
"@testing-library/jest-dom": "6.8.0",
|
||||
"@testing-library/jest-dom": "6.9.1",
|
||||
"@testing-library/react": "16.3.0",
|
||||
"@testing-library/user-event": "14.6.1",
|
||||
"@types/lodash": "4.17.20",
|
||||
@@ -76,21 +83,22 @@
|
||||
"@types/node": "*",
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"@vitejs/plugin-react": "5.0.2",
|
||||
"cross-env": "10.0.0",
|
||||
"dotenv": "17.2.2",
|
||||
"@vitejs/plugin-react": "5.1.0",
|
||||
"copy-webpack-plugin": "13.0.1",
|
||||
"cross-env": "10.1.0",
|
||||
"dotenv": "17.2.3",
|
||||
"eslint-plugin-docs": "*",
|
||||
"fetch-mock": "9.11.0",
|
||||
"jsdom": "26.1.0",
|
||||
"jsdom": "27.1.0",
|
||||
"node-fetch": "2.7.0",
|
||||
"prettier": "3.6.2",
|
||||
"stylelint": "16.24.0",
|
||||
"stylelint-config-standard": "39.0.0",
|
||||
"stylelint": "16.25.0",
|
||||
"stylelint-config-standard": "39.0.1",
|
||||
"stylelint-prettier": "5.0.3",
|
||||
"typescript": "*",
|
||||
"vite-tsconfig-paths": "5.1.4",
|
||||
"vitest": "3.2.4",
|
||||
"webpack": "5.101.3",
|
||||
"vitest": "4.0.6",
|
||||
"webpack": "5.102.1",
|
||||
"workbox-webpack-plugin": "7.1.0"
|
||||
},
|
||||
"packageManager": "yarn@1.22.22"
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,101 +0,0 @@
|
||||
@font-face {
|
||||
font-family: Marianne;
|
||||
src:
|
||||
url('Marianne-Thin.woff2') format('woff2'),
|
||||
url('Marianne-Thin.woff') format('woff');
|
||||
font-weight: 100;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Marianne;
|
||||
src:
|
||||
url('Marianne-Thin_Italic.woff2') format('woff2'),
|
||||
url('Marianne-Thin_Italic.woff') format('woff');
|
||||
font-weight: 100;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Marianne;
|
||||
src:
|
||||
url('Marianne-Light.woff2') format('woff2'),
|
||||
url('Marianne-Light.woff') format('woff');
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Marianne;
|
||||
src:
|
||||
url('Marianne-Light_Italic.woff2') format('woff2'),
|
||||
url('Marianne-Light_Italic.woff') format('woff');
|
||||
font-weight: 300;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Marianne;
|
||||
src:
|
||||
url('Marianne-Regular.woff2') format('woff2'),
|
||||
url('Marianne-Regular.woff') format('woff');
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Marianne;
|
||||
src:
|
||||
url('Marianne-Regular_Italic.woff2') format('woff2'),
|
||||
url('Marianne-Regular_Italic.woff') format('woff');
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Marianne;
|
||||
src:
|
||||
url('Marianne-Medium.woff2') format('woff2'),
|
||||
url('Marianne-Medium.woff') format('woff');
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Marianne;
|
||||
src:
|
||||
url('Marianne-Medium_Italic.woff2') format('woff2'),
|
||||
url('Marianne-Medium_Italic.woff') format('woff');
|
||||
font-weight: 500;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Marianne;
|
||||
src:
|
||||
url('Marianne-Bold.woff2') format('woff2'),
|
||||
url('Marianne-Bold.woff') format('woff');
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Marianne;
|
||||
src:
|
||||
url('Marianne-Bold_Italic.woff2') format('woff2'),
|
||||
url('Marianne-Bold_Italic.woff') format('woff');
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Marianne;
|
||||
src:
|
||||
url('Marianne-ExtraBold.woff2') format('woff2'),
|
||||
url('Marianne-ExtraBold.woff') format('woff');
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Marianne;
|
||||
src:
|
||||
url('Marianne-ExtraBold_Italic.woff2') format('woff2'),
|
||||
url('Marianne-ExtraBold_Italic.woff') format('woff');
|
||||
font-weight: 800;
|
||||
font-style: italic;
|
||||
}
|
||||
BIN
src/frontend/apps/impress/public/assets/fonts/emoji/fallback.png
Normal file
BIN
src/frontend/apps/impress/public/assets/fonts/emoji/fallback.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.0 KiB |
@@ -18,5 +18,5 @@ export const backendUrl = () =>
|
||||
* @param apiVersion - The version of the API (defaults to '1.0').
|
||||
* @returns The full versioned API base URL as a string.
|
||||
*/
|
||||
export const baseApiUrl = (apiVersion: string = '1.0') =>
|
||||
export const baseApiUrl = (apiVersion = '1.0') =>
|
||||
`${backendUrl()}/api/v${apiVersion}/`;
|
||||
|
||||
@@ -36,7 +36,30 @@ export interface BoxProps {
|
||||
$position?: CSSProperties['position'];
|
||||
$radius?: CSSProperties['borderRadius'];
|
||||
$shrink?: CSSProperties['flexShrink'];
|
||||
$theme?:
|
||||
| 'primary'
|
||||
| 'primary-text'
|
||||
| 'secondary'
|
||||
| 'secondary-text'
|
||||
| 'info'
|
||||
| 'success'
|
||||
| 'warning'
|
||||
| 'danger'
|
||||
| 'greyscale';
|
||||
$transition?: CSSProperties['transition'];
|
||||
$variation?:
|
||||
| 'text'
|
||||
| '000'
|
||||
| '100'
|
||||
| '200'
|
||||
| '300'
|
||||
| '400'
|
||||
| '500'
|
||||
| '600'
|
||||
| '700'
|
||||
| '800'
|
||||
| '900'
|
||||
| '1000';
|
||||
$width?: CSSProperties['width'];
|
||||
$wrap?: CSSProperties['flexWrap'];
|
||||
$zIndex?: CSSProperties['zIndex'];
|
||||
@@ -73,6 +96,12 @@ export const Box = styled('div')<BoxProps>`
|
||||
${({ $position }) => $position && `position: ${$position};`}
|
||||
${({ $radius }) => $radius && `border-radius: ${$radius};`}
|
||||
${({ $shrink }) => $shrink && `flex-shrink: ${$shrink};`}
|
||||
${({ $theme, $variation }) => {
|
||||
if (!$theme || !$variation) {
|
||||
return '';
|
||||
}
|
||||
return `color: var(--c--theme--colors--${$theme}-${$variation});`;
|
||||
}}
|
||||
${({ $transition }) => $transition && `transition: ${$transition};`}
|
||||
${({ $width }) => $width && `width: ${$width};`}
|
||||
${({ $wrap }) => $wrap && `flex-wrap: ${$wrap};`}
|
||||
|
||||
@@ -24,6 +24,9 @@ export type BoxButtonType = BoxType & {
|
||||
*/
|
||||
const BoxButton = forwardRef<HTMLDivElement, BoxButtonType>(
|
||||
({ $css, ...props }, ref) => {
|
||||
const theme = props.$theme || 'greyscale';
|
||||
const variation = props.$variation || '400';
|
||||
|
||||
return (
|
||||
<Box
|
||||
ref={ref}
|
||||
@@ -37,10 +40,16 @@ const BoxButton = forwardRef<HTMLDivElement, BoxButtonType>(
|
||||
border: none;
|
||||
outline: none;
|
||||
font-family: inherit;
|
||||
|
||||
color: ${props.disabled
|
||||
? 'var(--c--theme--colors--greyscale-400) !important'
|
||||
: 'inherit'};
|
||||
? `var(--c--theme--colors--${theme}-400) !important`
|
||||
: `inherit`};
|
||||
|
||||
&:focus-visible {
|
||||
transition: none;
|
||||
outline: 2px solid var(--c--theme--colors--${theme}-${variation});
|
||||
border-radius: 1px;
|
||||
outline-offset: 4px;
|
||||
}
|
||||
${$css || ''}
|
||||
`}
|
||||
{...props}
|
||||
|
||||
@@ -7,6 +7,7 @@ import { Box, BoxType } from '.';
|
||||
|
||||
export const Card = ({
|
||||
children,
|
||||
className,
|
||||
$css,
|
||||
...props
|
||||
}: PropsWithChildren<BoxType>) => {
|
||||
@@ -14,7 +15,7 @@ export const Card = ({
|
||||
|
||||
return (
|
||||
<Box
|
||||
className={`--docs--card ${props.className || ''}`}
|
||||
className={`--docs--card ${className || ''}`}
|
||||
$background="white"
|
||||
$radius="4px"
|
||||
$css={css`
|
||||
|
||||
@@ -31,7 +31,7 @@ const StyledButton = styled(Button)<StyledButtonProps>`
|
||||
font-weight: 500;
|
||||
font-size: 0.938rem;
|
||||
padding: 0;
|
||||
${({ $css }) => $css};
|
||||
border-radius: 4px;
|
||||
&:hover {
|
||||
background-color: var(
|
||||
--c--components--button--primary-text--background--color-hover
|
||||
@@ -41,6 +41,7 @@ const StyledButton = styled(Button)<StyledButtonProps>`
|
||||
box-shadow: 0 0 0 2px var(--c--theme--colors--primary-400);
|
||||
border-radius: 4px;
|
||||
}
|
||||
${({ $css }) => $css};
|
||||
`;
|
||||
|
||||
export interface DropButtonProps {
|
||||
|
||||
@@ -4,12 +4,16 @@ import { css } from 'styled-components';
|
||||
import { Text, TextType } from '@/components';
|
||||
|
||||
type IconProps = TextType & {
|
||||
disabled?: boolean;
|
||||
iconName: string;
|
||||
variant?: 'filled' | 'outlined';
|
||||
variant?: 'filled' | 'outlined' | 'symbols-outlined';
|
||||
};
|
||||
export const Icon = ({
|
||||
className,
|
||||
iconName,
|
||||
disabled,
|
||||
variant = 'outlined',
|
||||
$variation = 'text',
|
||||
...textProps
|
||||
}: IconProps) => {
|
||||
const hasLabel = 'aria-label' in textProps || 'aria-labelledby' in textProps;
|
||||
@@ -18,12 +22,15 @@ export const Icon = ({
|
||||
|
||||
return (
|
||||
<Text
|
||||
{...textProps}
|
||||
aria-hidden={ariaHidden}
|
||||
className={clsx('--docs--icon-bg', textProps.className, {
|
||||
className={clsx('--docs--icon-bg', className, {
|
||||
'material-icons-filled': variant === 'filled',
|
||||
'material-icons': variant === 'outlined',
|
||||
'material-symbols-outlined': variant === 'symbols-outlined',
|
||||
})}
|
||||
$variation={disabled ? '300' : $variation}
|
||||
aria-disabled={disabled}
|
||||
{...textProps}
|
||||
>
|
||||
{iconName}
|
||||
</Text>
|
||||
@@ -34,15 +41,19 @@ type IconOptionsProps = TextType & {
|
||||
isHorizontal?: boolean;
|
||||
};
|
||||
|
||||
export const IconOptions = ({ isHorizontal, ...props }: IconOptionsProps) => {
|
||||
export const IconOptions = ({
|
||||
isHorizontal,
|
||||
$css,
|
||||
...props
|
||||
}: IconOptionsProps) => {
|
||||
return (
|
||||
<Icon
|
||||
{...props}
|
||||
iconName={isHorizontal ? 'more_horiz' : 'more_vert'}
|
||||
$css={css`
|
||||
user-select: none;
|
||||
${props.$css}
|
||||
${$css}
|
||||
`}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
36
src/frontend/apps/impress/src/components/Overlayer.tsx
Normal file
36
src/frontend/apps/impress/src/components/Overlayer.tsx
Normal file
@@ -0,0 +1,36 @@
|
||||
import { PropsWithChildren } from 'react';
|
||||
import { css } from 'styled-components';
|
||||
|
||||
import { Box, BoxType } from '.';
|
||||
|
||||
type OverlayerProps = PropsWithChildren<{
|
||||
isOverlay: boolean;
|
||||
}> &
|
||||
Partial<BoxType>;
|
||||
|
||||
export const Overlayer = ({
|
||||
children,
|
||||
className,
|
||||
$css,
|
||||
isOverlay,
|
||||
...props
|
||||
}: OverlayerProps) => {
|
||||
if (!isOverlay) {
|
||||
return children;
|
||||
}
|
||||
|
||||
return (
|
||||
<Box
|
||||
className={`--docs--overlayer ${className || ''}`}
|
||||
$opacity="0.4"
|
||||
$zIndex="10"
|
||||
$css={css`
|
||||
${$css}
|
||||
pointer-events: none;
|
||||
`}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
@@ -15,29 +15,6 @@ export interface TextProps extends BoxProps {
|
||||
$textAlign?: CSSProperties['textAlign'];
|
||||
$textTransform?: CSSProperties['textTransform'];
|
||||
$size?: TextSizes | (string & {});
|
||||
$theme?:
|
||||
| 'primary'
|
||||
| 'primary-text'
|
||||
| 'secondary'
|
||||
| 'secondary-text'
|
||||
| 'info'
|
||||
| 'success'
|
||||
| 'warning'
|
||||
| 'danger'
|
||||
| 'greyscale';
|
||||
$variation?:
|
||||
| 'text'
|
||||
| '000'
|
||||
| '100'
|
||||
| '200'
|
||||
| '300'
|
||||
| '400'
|
||||
| '500'
|
||||
| '600'
|
||||
| '700'
|
||||
| '800'
|
||||
| '900'
|
||||
| '1000';
|
||||
}
|
||||
|
||||
export type TextType = ComponentPropsWithRef<typeof Text>;
|
||||
@@ -50,8 +27,6 @@ export const TextStyled = styled(Box)<TextProps>`
|
||||
${({ $size }) =>
|
||||
$size &&
|
||||
`font-size: ${$size in sizes ? sizes[$size as TextSizes] : $size};`}
|
||||
${({ $theme, $variation }) =>
|
||||
`color: var(--c--theme--colors--${$theme}-${$variation});`}
|
||||
${({ $color }) => $color && `color: ${$color};`}
|
||||
${({ $ellipsis }) =>
|
||||
$ellipsis &&
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user