From 3902d6361ea0ef02d56cfff4069a3ae19a72b36e Mon Sep 17 00:00:00 2001 From: Benjamin Gamard Date: Fri, 23 Nov 2018 14:54:11 +0100 Subject: [PATCH 01/10] #256: versioning API --- .../com/sismics/docs/core/dao/FileDao.java | 8 ++-- .../com/sismics/docs/core/model/jpa/File.java | 45 +++++++++++++++++++ .../docs/core/service/InboxService.java | 4 +- .../com/sismics/docs/core/util/FileUtil.java | 45 ++++++++++++++----- .../src/main/resources/config.properties | 2 +- .../resources/db/update/dbupdate-022-0.sql | 5 +++ docs-web/src/dev/resources/config.properties | 2 +- .../docs/rest/resource/DocumentResource.java | 4 +- .../docs/rest/resource/FileResource.java | 6 ++- docs-web/src/prod/resources/config.properties | 2 +- .../src/stress/resources/config.properties | 2 +- .../sismics/docs/rest/TestFileResource.java | 34 ++++++++++++++ 12 files changed, 135 insertions(+), 24 deletions(-) create mode 100644 docs-core/src/main/resources/db/update/dbupdate-022-0.sql diff --git a/docs-core/src/main/java/com/sismics/docs/core/dao/FileDao.java b/docs-core/src/main/java/com/sismics/docs/core/dao/FileDao.java index 4610621e..a35a03e4 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/dao/FileDao.java +++ b/docs-core/src/main/java/com/sismics/docs/core/dao/FileDao.java @@ -148,7 +148,9 @@ public class FileDao { fileDb.setContent(file.getContent()); fileDb.setOrder(file.getOrder()); fileDb.setMimeType(file.getMimeType()); - + fileDb.setVersionId(file.getVersionId()); + fileDb.setLatestVersion(file.isLatestVersion()); + return file; } @@ -180,11 +182,11 @@ public class FileDao { public List getByDocumentId(String userId, String documentId) { EntityManager em = ThreadLocalContext.get().getEntityManager(); if (documentId == null) { - Query q = em.createQuery("select f from File f where f.documentId is null and f.deleteDate is null and f.userId = :userId order by f.createDate asc"); + Query q = em.createQuery("select f from File f where f.documentId is null and f.deleteDate is null and f.latestVersion = true and f.userId = :userId order by f.createDate asc"); q.setParameter("userId", userId); return q.getResultList(); } - Query q = em.createQuery("select f from File f where f.documentId = :documentId and f.deleteDate is null order by f.order asc"); + Query q = em.createQuery("select f from File f where f.documentId = :documentId and f.latestVersion = true and f.deleteDate is null order by f.order asc"); q.setParameter("documentId", documentId); return q.getResultList(); } diff --git a/docs-core/src/main/java/com/sismics/docs/core/model/jpa/File.java b/docs-core/src/main/java/com/sismics/docs/core/model/jpa/File.java index 3db2ab7b..c3e7064a 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/model/jpa/File.java +++ b/docs-core/src/main/java/com/sismics/docs/core/model/jpa/File.java @@ -71,6 +71,24 @@ public class File implements Loggable { @Column(name = "FIL_ORDER_N") private Integer order; + /** + * Version ID. + */ + @Column(name = "FIL_IDVERSION_C") + private String versionId; + + /** + * Version number (starting at 0). + */ + @Column(name = "FIL_VERSION_N", nullable = false) + private Integer version; + + /** + * True if it's the latest version of the file. + */ + @Column(name = "FIL_LATESTVERSION_B", nullable = false) + private boolean latestVersion; + /** * Private key to decrypt the file. * Not saved to database, of course. @@ -160,6 +178,33 @@ public class File implements Loggable { this.privateKey = privateKey; } + public String getVersionId() { + return versionId; + } + + public File setVersionId(String versionId) { + this.versionId = versionId; + return this; + } + + public Integer getVersion() { + return version; + } + + public File setVersion(Integer version) { + this.version = version; + return this; + } + + public boolean isLatestVersion() { + return latestVersion; + } + + public File setLatestVersion(boolean latestVersion) { + this.latestVersion = latestVersion; + return this; + } + @Override public String toString() { return MoreObjects.toStringHelper(this) diff --git a/docs-core/src/main/java/com/sismics/docs/core/service/InboxService.java b/docs-core/src/main/java/com/sismics/docs/core/service/InboxService.java index a349d329..ae0b7500 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/service/InboxService.java +++ b/docs-core/src/main/java/com/sismics/docs/core/service/InboxService.java @@ -212,7 +212,7 @@ public class InboxService extends AbstractScheduledService { } // Save the document, create the base ACLs - document = DocumentUtil.createDocument(document, "admin"); + DocumentUtil.createDocument(document, "admin"); // Add the tag String tagId = ConfigUtil.getConfigStringValue(ConfigType.INBOX_TAG); @@ -232,7 +232,7 @@ public class InboxService extends AbstractScheduledService { // Add files to the document for (EmailUtil.FileContent fileContent : mailContent.getFileContentList()) { - FileUtil.createFile(fileContent.getName(), fileContent.getFile(), fileContent.getSize(), + FileUtil.createFile(fileContent.getName(), null, fileContent.getFile(), fileContent.getSize(), document.getLanguage(), "admin", document.getId()); } } diff --git a/docs-core/src/main/java/com/sismics/docs/core/util/FileUtil.java b/docs-core/src/main/java/com/sismics/docs/core/util/FileUtil.java index a4604038..98dbeca0 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/util/FileUtil.java +++ b/docs-core/src/main/java/com/sismics/docs/core/util/FileUtil.java @@ -98,6 +98,7 @@ public class FileUtil { * Create a new file. * * @param name File name, can be null + * @param previousFileId ID of the previous version of the file, if the new file is a new version * @param unencryptedFile Path to the unencrypted file * @param fileSize File size * @param language File language, can be null if associated to no document @@ -106,7 +107,7 @@ public class FileUtil { * @return File ID * @throws Exception e */ - public static String createFile(String name, Path unencryptedFile, long fileSize, String language, String userId, String documentId) throws Exception { + public static String createFile(String name, String previousFileId, Path unencryptedFile, long fileSize, String language, String userId, String documentId) throws Exception { // Validate mime type String mimeType; try { @@ -132,22 +133,42 @@ public class FileUtil { } } - // Get files of this document - FileDao fileDao = new FileDao(); - int order = 0; - if (documentId != null) { - for (File file : fileDao.getByDocumentId(userId, documentId)) { - file.setOrder(order++); - } - } - - // Create the file + // Prepare the file File file = new File(); - file.setOrder(order); + file.setOrder(0); + file.setVersion(0); + file.setLatestVersion(true); file.setDocumentId(documentId); file.setName(StringUtils.abbreviate(name, 200)); file.setMimeType(mimeType); file.setUserId(userId); + + // Get files of this document + FileDao fileDao = new FileDao(); + if (documentId != null) { + if (previousFileId == null) { + // It's not a new version, so put it in last order + file.setOrder(fileDao.getByDocumentId(userId, documentId).size()); + } else { + // It's a new version, update the previous version + File previousFile = fileDao.getActiveById(previousFileId); + if (previousFile == null || !previousFile.getDocumentId().equals(documentId)) { + throw new IOException("Previous version mismatch"); + } + + if (previousFile.getVersionId() == null) { + previousFile.setVersionId(UUID.randomUUID().toString()); + } + + previousFile.setLatestVersion(false); + file.setVersionId(previousFile.getVersionId()); + file.setVersion(previousFile.getVersion() + 1); + + fileDao.update(previousFile); + } + } + + // Create the file String fileId = fileDao.create(file, userId); // Save the file diff --git a/docs-core/src/main/resources/config.properties b/docs-core/src/main/resources/config.properties index eb3e256a..5d8d3532 100644 --- a/docs-core/src/main/resources/config.properties +++ b/docs-core/src/main/resources/config.properties @@ -1 +1 @@ -db.version=21 \ No newline at end of file +db.version=22 \ No newline at end of file diff --git a/docs-core/src/main/resources/db/update/dbupdate-022-0.sql b/docs-core/src/main/resources/db/update/dbupdate-022-0.sql new file mode 100644 index 00000000..c8333f93 --- /dev/null +++ b/docs-core/src/main/resources/db/update/dbupdate-022-0.sql @@ -0,0 +1,5 @@ +alter table T_FILE add column FIL_VERSION_N int not null default 0; +alter table T_FILE add column FIL_LATESTVERSION_B bit not null default 1; +alter table T_FILE add column FIL_IDVERSION_C varchar(36); + +update T_CONFIG set CFG_VALUE_C = '22' where CFG_ID_C = 'DB_VERSION'; diff --git a/docs-web/src/dev/resources/config.properties b/docs-web/src/dev/resources/config.properties index e55e3dbc..7ab7347c 100644 --- a/docs-web/src/dev/resources/config.properties +++ b/docs-web/src/dev/resources/config.properties @@ -1,3 +1,3 @@ api.current_version=${project.version} api.min_version=1.0 -db.version=21 \ No newline at end of file +db.version=22 \ No newline at end of file diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java index 2c7380b7..7de9134f 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/DocumentResource.java @@ -900,7 +900,7 @@ public class DocumentResource extends BaseResource { } // Save the document, create the base ACLs - document = DocumentUtil.createDocument(document, principal.getId()); + DocumentUtil.createDocument(document, principal.getId()); // Raise a document created event DocumentCreatedAsyncEvent documentCreatedAsyncEvent = new DocumentCreatedAsyncEvent(); @@ -911,7 +911,7 @@ public class DocumentResource extends BaseResource { // Add files to the document try { for (EmailUtil.FileContent fileContent : mailContent.getFileContentList()) { - FileUtil.createFile(fileContent.getName(), fileContent.getFile(), fileContent.getSize(), + FileUtil.createFile(fileContent.getName(), null, fileContent.getFile(), fileContent.getSize(), document.getLanguage(), principal.getId(), document.getId()); } } catch (IOException e) { diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java index 4f03f156..24fd97bb 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java @@ -66,6 +66,7 @@ public class FileResource extends BaseResource { * @apiName PutFile * @apiGroup File * @apiParam {String} id Document ID + * @apiParam {String} previousFileId ID of the file to replace by this new version * @apiParam {String} file File data * @apiSuccess {String} status Status OK * @apiSuccess {String} id File ID @@ -88,6 +89,7 @@ public class FileResource extends BaseResource { @Consumes("multipart/form-data") public Response add( @FormDataParam("id") String documentId, + @FormDataParam("previousFileId") String previousFileId, @FormDataParam("file") FormDataBodyPart fileBodyPart) { if (!authenticate()) { throw new ForbiddenClientException(); @@ -122,7 +124,7 @@ public class FileResource extends BaseResource { try { String name = fileBodyPart.getContentDisposition() != null ? URLDecoder.decode(fileBodyPart.getContentDisposition().getFileName(), "UTF-8") : null; - String fileId = FileUtil.createFile(name, unencryptedFile, fileSize, documentDto == null ? + String fileId = FileUtil.createFile(name, previousFileId, unencryptedFile, fileSize, documentDto == null ? null : documentDto.getLanguage(), principal.getId(), documentId); // Always return OK @@ -392,6 +394,7 @@ public class FileResource extends BaseResource { * @apiSuccess {String} files.id ID * @apiSuccess {String} files.mimetype MIME type * @apiSuccess {String} files.name File name + * @apiSuccess {String} files.version Zero-based version number * @apiSuccess {String} files.processing True if the file is currently processing * @apiSuccess {String} files.document_id Document ID * @apiSuccess {String} files.create_date Create date (timestamp) @@ -433,6 +436,7 @@ public class FileResource extends BaseResource { .add("id", fileDb.getId()) .add("processing", FileUtil.isProcessingFile(fileDb.getId())) .add("name", JsonUtil.nullable(fileDb.getName())) + .add("version", fileDb.getVersion()) .add("mimetype", fileDb.getMimeType()) .add("document_id", JsonUtil.nullable(fileDb.getDocumentId())) .add("create_date", fileDb.getCreateDate().getTime()) diff --git a/docs-web/src/prod/resources/config.properties b/docs-web/src/prod/resources/config.properties index e55e3dbc..7ab7347c 100644 --- a/docs-web/src/prod/resources/config.properties +++ b/docs-web/src/prod/resources/config.properties @@ -1,3 +1,3 @@ api.current_version=${project.version} api.min_version=1.0 -db.version=21 \ No newline at end of file +db.version=22 \ No newline at end of file diff --git a/docs-web/src/stress/resources/config.properties b/docs-web/src/stress/resources/config.properties index e55e3dbc..7ab7347c 100644 --- a/docs-web/src/stress/resources/config.properties +++ b/docs-web/src/stress/resources/config.properties @@ -1,3 +1,3 @@ api.current_version=${project.version} api.min_version=1.0 -db.version=21 \ No newline at end of file +db.version=22 \ No newline at end of file diff --git a/docs-web/src/test/java/com/sismics/docs/rest/TestFileResource.java b/docs-web/src/test/java/com/sismics/docs/rest/TestFileResource.java index 053b72e6..278f1bb6 100644 --- a/docs-web/src/test/java/com/sismics/docs/rest/TestFileResource.java +++ b/docs-web/src/test/java/com/sismics/docs/rest/TestFileResource.java @@ -140,9 +140,11 @@ public class TestFileResource extends BaseJerseyTest { Assert.assertEquals(2, files.size()); Assert.assertEquals(file1Id, files.getJsonObject(0).getString("id")); Assert.assertEquals("PIA00452.jpg", files.getJsonObject(0).getString("name")); + Assert.assertEquals(0, files.getJsonObject(0).getInt("version")); Assert.assertEquals(163510L, files.getJsonObject(0).getJsonNumber("size").longValue()); Assert.assertEquals(file2Id, files.getJsonObject(1).getString("id")); Assert.assertEquals("PIA00452.jpg", files.getJsonObject(1).getString("name")); + Assert.assertEquals(0, files.getJsonObject(1).getInt("version")); // Rename a file target().path("file/" + file1Id) @@ -225,6 +227,38 @@ public class TestFileResource extends BaseJerseyTest { target().path("/file/" + file2Id + "/process").request() .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file1Token) .post(Entity.form(new Form()), JsonObject.class); + + // Add a new version to a file + String file3Id; + try (InputStream is0 = Resources.getResource("file/document.txt").openStream()) { + StreamDataBodyPart streamDataBodyPart = new StreamDataBodyPart("file", is0, "document.txt"); + try (FormDataMultiPart multiPart = new FormDataMultiPart()) { + json = target() + .register(MultiPartFeature.class) + .path("/file").request() + .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file1Token) + .put(Entity.entity( + multiPart + .field("id", document1Id) + .field("previousFileId", file2Id) + .bodyPart(streamDataBodyPart), + MediaType.MULTIPART_FORM_DATA_TYPE), JsonObject.class); + file3Id = json.getString("id"); + Assert.assertNotNull(file2Id); + } + } + + // Check the newly created version + json = target().path("/file/list") + .queryParam("id", document1Id) + .request() + .cookie(TokenBasedSecurityFilter.COOKIE_NAME, file1Token) + .get(JsonObject.class); + files = json.getJsonArray("files"); + Assert.assertEquals(1, files.size()); + Assert.assertEquals(file3Id, files.getJsonObject(0).getString("id")); + Assert.assertEquals("document.txt", files.getJsonObject(0).getString("name")); + Assert.assertEquals(1, files.getJsonObject(0).getInt("version")); } /** From 33aaf8afd28c73ca4f72dd57da301ac296d3e3f1 Mon Sep 17 00:00:00 2001 From: Benjamin Gamard Date: Wed, 28 Nov 2018 13:09:20 +0100 Subject: [PATCH 02/10] css fix --- .../java/com/sismics/docs/rest/resource/FileResource.java | 2 +- docs-web/src/main/webapp/src/style/main.less | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java b/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java index 24fd97bb..02195329 100644 --- a/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java +++ b/docs-web/src/main/java/com/sismics/docs/rest/resource/FileResource.java @@ -290,7 +290,7 @@ public class FileResource extends BaseResource { DocumentDao documentDao = new DocumentDao(); FileDao fileDao = new FileDao(); File file = fileDao.getFile(id); - if (file == null) { + if (file == null || file.getDocumentId() == null) { throw new NotFoundException(); } DocumentDto documentDto = documentDao.getDocument(file.getDocumentId(), PermType.WRITE, getTargetIdList(null)); diff --git a/docs-web/src/main/webapp/src/style/main.less b/docs-web/src/main/webapp/src/style/main.less index 4998f80a..a9c13ce5 100644 --- a/docs-web/src/main/webapp/src/style/main.less +++ b/docs-web/src/main/webapp/src/style/main.less @@ -653,6 +653,10 @@ input[readonly].share-link { } } +.navbar-brand { + font-weight: 500; +} + .nav > li { font-weight: 500; } From db4f5f9011c5222f665b4caecccb99474f2a5d58 Mon Sep 17 00:00:00 2001 From: Benjamin Gamard Date: Wed, 5 Dec 2018 17:23:19 +0100 Subject: [PATCH 03/10] fix workflow form --- .../settings/SettingsWorkflowEdit.js | 1 + .../partial/docs/settings.workflow.edit.html | 22 +++++++++---------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/docs-web/src/main/webapp/src/app/docs/controller/settings/SettingsWorkflowEdit.js b/docs-web/src/main/webapp/src/app/docs/controller/settings/SettingsWorkflowEdit.js index a4a4dfa1..444b1e12 100644 --- a/docs-web/src/main/webapp/src/app/docs/controller/settings/SettingsWorkflowEdit.js +++ b/docs-web/src/main/webapp/src/app/docs/controller/settings/SettingsWorkflowEdit.js @@ -1,3 +1,4 @@ + 'use strict'; /** diff --git a/docs-web/src/main/webapp/src/partial/docs/settings.workflow.edit.html b/docs-web/src/main/webapp/src/partial/docs/settings.workflow.edit.html index 1cc03eca..e3efd853 100644 --- a/docs-web/src/main/webapp/src/partial/docs/settings.workflow.edit.html +++ b/docs-web/src/main/webapp/src/partial/docs/settings.workflow.edit.html @@ -136,20 +136,10 @@ -
-
-

- -
-
-
+ +
+
+

+ +
+
\ No newline at end of file From 5fbbcfc888418aba6d83c06832fd085b6cfc8ce3 Mon Sep 17 00:00:00 2001 From: Mario Voigt Date: Thu, 24 Jan 2019 11:38:17 +0100 Subject: [PATCH 04/10] Open jdk11 (#287) Java 11 compat --- docs-web/pom.xml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/docs-web/pom.xml b/docs-web/pom.xml index b5eb7f28..32aa4aa7 100644 --- a/docs-web/pom.xml +++ b/docs-web/pom.xml @@ -26,6 +26,25 @@ docs-web-common + + + javax.xml.bind + jaxb-api + 2.3.0 + + + + com.sun.xml.bind + jaxb-core + 2.3.0 + + + + com.sun.xml.bind + jaxb-impl + 2.3.0 + + org.glassfish.jersey.containers From 183e86aad6602e2e85acae429b6f2d4b11562d22 Mon Sep 17 00:00:00 2001 From: Benjamin Gamard Date: Thu, 24 Jan 2019 11:48:42 +0100 Subject: [PATCH 05/10] fix travis build for PR --- .travis.yml | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 30fe4095..b94a31a1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,14 +7,17 @@ before_install: - sudo apt-get -y -q install ffmpeg mediainfo tesseract-ocr tesseract-ocr-fra tesseract-ocr-ita tesseract-ocr-kor tesseract-ocr-rus tesseract-ocr-ukr tesseract-ocr-spa tesseract-ocr-ara tesseract-ocr-hin tesseract-ocr-deu tesseract-ocr-pol tesseract-ocr-jpn tesseract-ocr-por tesseract-ocr-tha tesseract-ocr-jpn tesseract-ocr-chi-sim tesseract-ocr-chi-tra - sudo apt-get -y -q install haveged && sudo service haveged start after_success: - - mvn -Pprod -DskipTests clean install - - docker login -u $DOCKER_USER -p $DOCKER_PASS - - export REPO=sismics/docs - - export TAG=`if [ "$TRAVIS_BRANCH" == "master" ]; then echo "latest"; else echo $TRAVIS_BRANCH ; fi` - - docker build -f Dockerfile -t $REPO:$COMMIT . - - docker tag $REPO:$COMMIT $REPO:$TAG - - docker tag $REPO:$COMMIT $REPO:travis-$TRAVIS_BUILD_NUMBER - - docker push $REPO + - | + if [ "$TRAVIS_PULL_REQUEST" = "false" ]; + mvn -Pprod -DskipTests clean install + docker login -u $DOCKER_USER -p $DOCKER_PASS + export REPO=sismics/docs + export TAG=`if [ "$TRAVIS_BRANCH" == "master" ]; then echo "latest"; else echo $TRAVIS_BRANCH ; fi` + docker build -f Dockerfile -t $REPO:$COMMIT . + docker tag $REPO:$COMMIT $REPO:$TAG + docker tag $REPO:$COMMIT $REPO:travis-$TRAVIS_BUILD_NUMBER + docker push $REPO + fi env: global: - secure: LRGpjWORb0qy6VuypZjTAfA8uRHlFUMTwb77cenS9PPRBxuSnctC531asS9Xg3DqC5nsRxBBprgfCKotn5S8nBSD1ceHh84NASyzLSBft3xSMbg7f/2i7MQ+pGVwLncusBU6E/drnMFwZBleo+9M8Tf96axY5zuUp90MUTpSgt0= From c7c7badaf04fcf8663c38997657b43bacd4b88e5 Mon Sep 17 00:00:00 2001 From: Benjamin Gamard Date: Thu, 24 Jan 2019 11:49:45 +0100 Subject: [PATCH 06/10] fix travis build for PR --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b94a31a1..683ab10a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ before_install: - sudo apt-get -y -q install haveged && sudo service haveged start after_success: - | - if [ "$TRAVIS_PULL_REQUEST" = "false" ]; + if [ "$TRAVIS_PULL_REQUEST" == "false" ]; then mvn -Pprod -DskipTests clean install docker login -u $DOCKER_USER -p $DOCKER_PASS export REPO=sismics/docs From 8a5e90e56237c4a0e059aadd211ba339b3b60e10 Mon Sep 17 00:00:00 2001 From: Freekers <1370857+Freekers@users.noreply.github.com> Date: Thu, 24 Jan 2019 11:52:44 +0100 Subject: [PATCH 07/10] Added OCR support for Dutch (Nederlands) (#286) Dutch support for OCR --- .travis.yml | 2 +- Dockerfile | 2 +- .../main/java/com/sismics/docs/core/constant/Constants.java | 2 +- docs-web/src/main/webapp/src/app/docs/app.js | 5 +++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 683ab10a..6a1c0e61 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,7 +4,7 @@ language: java before_install: - sudo add-apt-repository -y ppa:mc3man/trusty-media - sudo apt-get -qq update - - sudo apt-get -y -q install ffmpeg mediainfo tesseract-ocr tesseract-ocr-fra tesseract-ocr-ita tesseract-ocr-kor tesseract-ocr-rus tesseract-ocr-ukr tesseract-ocr-spa tesseract-ocr-ara tesseract-ocr-hin tesseract-ocr-deu tesseract-ocr-pol tesseract-ocr-jpn tesseract-ocr-por tesseract-ocr-tha tesseract-ocr-jpn tesseract-ocr-chi-sim tesseract-ocr-chi-tra + - sudo apt-get -y -q install ffmpeg mediainfo tesseract-ocr tesseract-ocr-fra tesseract-ocr-ita tesseract-ocr-kor tesseract-ocr-rus tesseract-ocr-ukr tesseract-ocr-spa tesseract-ocr-ara tesseract-ocr-hin tesseract-ocr-deu tesseract-ocr-pol tesseract-ocr-jpn tesseract-ocr-por tesseract-ocr-tha tesseract-ocr-jpn tesseract-ocr-chi-sim tesseract-ocr-chi-tra tesseract-ocr-nld - sudo apt-get -y -q install haveged && sudo service haveged start after_success: - | diff --git a/Dockerfile b/Dockerfile index 74764c72..ddb5eb09 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM sismics/ubuntu-jetty:9.4.12 MAINTAINER b.gamard@sismics.com -RUN apt-get update && apt-get -y -q install ffmpeg mediainfo tesseract-ocr tesseract-ocr-fra tesseract-ocr-ita tesseract-ocr-kor tesseract-ocr-rus tesseract-ocr-ukr tesseract-ocr-spa tesseract-ocr-ara tesseract-ocr-hin tesseract-ocr-deu tesseract-ocr-pol tesseract-ocr-jpn tesseract-ocr-por tesseract-ocr-tha tesseract-ocr-jpn tesseract-ocr-chi-sim tesseract-ocr-chi-tra && \ +RUN apt-get update && apt-get -y -q install ffmpeg mediainfo tesseract-ocr tesseract-ocr-fra tesseract-ocr-ita tesseract-ocr-kor tesseract-ocr-rus tesseract-ocr-ukr tesseract-ocr-spa tesseract-ocr-ara tesseract-ocr-hin tesseract-ocr-deu tesseract-ocr-pol tesseract-ocr-jpn tesseract-ocr-por tesseract-ocr-tha tesseract-ocr-jpn tesseract-ocr-chi-sim tesseract-ocr-chi-tra tesseract-ocr-nld && \ apt-get clean && rm -rf /var/lib/apt/lists/* # Remove the embedded javax.mail jar from Jetty diff --git a/docs-core/src/main/java/com/sismics/docs/core/constant/Constants.java b/docs-core/src/main/java/com/sismics/docs/core/constant/Constants.java index 78aebf50..70037313 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/constant/Constants.java +++ b/docs-core/src/main/java/com/sismics/docs/core/constant/Constants.java @@ -38,7 +38,7 @@ public class Constants { /** * Supported document languages. */ - public static final List SUPPORTED_LANGUAGES = Lists.newArrayList("eng", "fra", "ita", "deu", "spa", "por", "pol", "rus", "ukr", "ara", "hin", "chi_sim", "chi_tra", "jpn", "tha", "kor"); + public static final List SUPPORTED_LANGUAGES = Lists.newArrayList("eng", "fra", "ita", "deu", "spa", "por", "pol", "rus", "ukr", "ara", "hin", "chi_sim", "chi_tra", "jpn", "tha", "kor", "nld"); /** * Base URL environment variable. diff --git a/docs-web/src/main/webapp/src/app/docs/app.js b/docs-web/src/main/webapp/src/app/docs/app.js index 7b9e26da..c6e1c90a 100644 --- a/docs-web/src/main/webapp/src/app/docs/app.js +++ b/docs-web/src/main/webapp/src/app/docs/app.js @@ -507,7 +507,8 @@ angular.module('docs', { key: 'chi_tra', label: '繁体中文' }, { key: 'jpn', label: '日本語' }, { key: 'tha', label: 'ภาษาไทย' }, - { key: 'kor', label: '한국어' } + { key: 'kor', label: '한국어' }, + { key: 'nld', label: 'Nederlands' } ]; }) /** @@ -530,4 +531,4 @@ angular.module('docs', if (location.search.indexOf("protractor") > -1) { window.name = 'NG_DEFER_BOOTSTRAP!'; -} \ No newline at end of file +} From 10d5c4334b059362c4bf24b271a912632dd92b41 Mon Sep 17 00:00:00 2001 From: Mario Voigt Date: Thu, 24 Jan 2019 11:53:45 +0100 Subject: [PATCH 08/10] =?UTF-8?q?Fixed=20some=20spelling=20mistakes=20+=20?= =?UTF-8?q?added=20translated=20properties=20for=20german=E2=80=A6=20(#266?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit german fixes --- .../sismics/docs/adapter/LanguageAdapter.java | 1 + .../app/src/main/res/drawable-xhdpi/deu.png | Bin 0 -> 9365 bytes .../app/src/main/res/drawable-xxhdpi/deu.png | Bin 0 -> 20921 bytes .../app/src/main/res/values-de/strings.xml | 148 ++++++++++++++++++ .../app/src/main/res/values/strings.xml | 1 + .../src/main/resources/messages.properties.de | 10 ++ .../src/main/resources/messages_de.properties | 10 ++ docs-importer/SismicsDocs.ico | Bin 0 -> 85182 bytes docs-web/src/main/webapp/src/locale/de.json | 135 +++++++++------- 9 files changed, 246 insertions(+), 59 deletions(-) create mode 100644 docs-android/app/src/main/res/drawable-xhdpi/deu.png create mode 100644 docs-android/app/src/main/res/drawable-xxhdpi/deu.png create mode 100644 docs-android/app/src/main/res/values-de/strings.xml create mode 100644 docs-core/src/main/resources/messages.properties.de create mode 100644 docs-core/src/main/resources/messages_de.properties create mode 100644 docs-importer/SismicsDocs.ico diff --git a/docs-android/app/src/main/java/com/sismics/docs/adapter/LanguageAdapter.java b/docs-android/app/src/main/java/com/sismics/docs/adapter/LanguageAdapter.java index a5f24ce3..80797651 100644 --- a/docs-android/app/src/main/java/com/sismics/docs/adapter/LanguageAdapter.java +++ b/docs-android/app/src/main/java/com/sismics/docs/adapter/LanguageAdapter.java @@ -33,6 +33,7 @@ public class LanguageAdapter extends BaseAdapter { } languageList.add(new Language("fra", R.string.language_french, R.drawable.fra)); languageList.add(new Language("eng", R.string.language_english, R.drawable.eng)); + languageList.add(new Language("deu", R.string.language_german, R.drawable.deu)); } @Override diff --git a/docs-android/app/src/main/res/drawable-xhdpi/deu.png b/docs-android/app/src/main/res/drawable-xhdpi/deu.png new file mode 100644 index 0000000000000000000000000000000000000000..f459ec25868faa327285ae7e319c063c647653de GIT binary patch literal 9365 zcmeHN&ubGw6#iy5Nllw75vout^dPh#NChc^AShLvLu(PidMFBB1P=;cyy`_f3SRUd z5DyAo`~!+!M5tIQh#-hHU>n5xqivGiS>M|<)7dp`ETP$5*nzh*vu|eS``&xAvop!P ziSaYtoxPm^x(lNt=O`ay*^!~^1zEmJS@y>0#haA5ETZGh@zX#*3L_`ZU;QM84$OQM zu1mTYCmCbx9`uAj*d9zgka(a)3&cKzQjH8C#O(}v!0Soll!odn&iNLQ`JRK8*I0JB z`1V@$1$xed?(DTBR89m`&8v&WvgBLr?ORBJFz0vwxLiO;Zz z`f!>A!UELNxN#)li;_4J@OexxWc~E^q3LduG+Z!zy+W!GHs?!VY)#++P@z>~k@U-f zHj$}PxRk~MXf%NV@&Hw;6kwG=o5)njz|~!ZX30RL3Gn*NDaw=LpRbyT=I>z zH^c7f69WHbrfqB#D-ZBzX)x)xQ2rWLtTH|e<$Z4l+eM2$-?rD3gWq^U!x{^LCXgZ6mIWn)d&RcH+;~7&)pn+4i&)J86L`HGI|4#@Ti!bU z^)CnB+tb}f6J0lsVqx6_6#ulL^iDsb2-L%*P@y@>7`34_f#L#6w(T9ML>B+jGT!lv z#sp{{Y^CmBNAJ`G#4`^NRZQ;z$+g)}gT&3uw%)y_9ADErGh3S{GSfOz% zbgbeLF$wT-MaS?UvX>^1@7ax<<3QLU5=aq&szP<{1Ae}m!7l<|CXBpew26QhMkWEa zG?U=4;&NT67;0jm^|<%)y7d{ACJ-vb76#XoxP@ng+BG2%s`+W~!~=d0OuzVg7DyfA v{{r|m?WiT*Xor?_?eB{~5%Xj_)rD-;L literal 0 HcmV?d00001 diff --git a/docs-android/app/src/main/res/drawable-xxhdpi/deu.png b/docs-android/app/src/main/res/drawable-xxhdpi/deu.png new file mode 100644 index 0000000000000000000000000000000000000000..9468588da504e3f970179e8898d2428dd4b91733 GIT binary patch literal 20921 zcmeI4J7^S96o&uFCYfw7D?SP_0Uww&iH#sAR*^_Hg~4Z$E@`w$A&6inh#(4rf?}mM zA_@{PBBG_y%1SVTvO>fMig}4dlYM&5y1TQRJLB1f1T!<|!pYpZ=gi}N^Us~V4|3r^ ze{W0k#%2I5ees?{w2iYhHPYXsQxAJ-6Fm_hI0?j_vsu?VW39ku^!0QfIsMLxAACGw z<#IWS)8s{<&dZ_Ye+eicK?w>-0SN>Iw<<^h2?PYUDo6nd1O&G#NC6211h*I zw<<^gR4@2pt-IKUW-BVi<^AbQ3du~Sb$TM_c0i)7!zmVG`Fx4!S{jguS%^ez*b%F$ zd#E<()2|P?+?k{lZVY!=mc;`o434dfY$w?!GQL5-D=tfQ;50$@lI%5Ex?maFW@-2* zMO!EFcu={Kr-iJYY@Cb-i-K$qsD2$}TxS+WV>t`XSHQ^^0J|vg4Ox)EEUw#bs_!Z? zyBa`YP|jjNtfUxObTJ^eHf3oWL%OOD5;rN#!l=6&ARp9c$#1a;rz${UhE^3IBWTH= zmyb>uX0=rHm=utMiQgRK?NLAuAlIA%a>e2l8lBZ0K$1Em3rQjH;QWkYCZOU#Ww*z20bor!0HC(ZD7tLK9I#E4$rs805ngnI*kt) zEqfrz6e>l{i)Vec!4{sp0#ZN%0l}>bQa}O$!L15XKmq~5tqQ6Y5Kk0^E%9i+S2BJ{ zuilTT`gu6Bp&K&fPmDlv4#&;4pU#KvrFT35*#T(h>tu z9j&bj8;e4nx!%RqXe9&&poKL3stj35WieTRV~E25^lBVWLdFL-@8ezpkgT9R$MF8? z7_KMNmOzxK%+4NFX4%RY3|!ARxF^K?+D9Ah=aQ3P>OzxK%+4NFX4% bRY3xv4MTT_UVPj>#$kQ?`g=z94xar3=sm?0 literal 0 HcmV?d00001 diff --git a/docs-android/app/src/main/res/values-de/strings.xml b/docs-android/app/src/main/res/values-de/strings.xml new file mode 100644 index 00000000..08250eaf --- /dev/null +++ b/docs-android/app/src/main/res/values-de/strings.xml @@ -0,0 +1,148 @@ + + + + + Ungültige E-Mail + Zu kurz (min. %d) + Zu lang (max. %d) + Erforderlich + Nur Buchstaben und Zahlen + + + Sismics Docs + Navigationsleiste öffnen + Navigationsleiste schließen + github.com/sismics/docs, sowie die Login-Daten unten eingeben]]> + Server + Username + Password + Login + OK + Abbrechen + Login gescheitert + Benutzername oder Passwort falsch + Netzwerkfehler + Netzwerkfehler, überprüfen Sie die Internetverbindung und die Server-URL + Ungültige URL + Bitte überprüfen Sie die Server-URL und versuchen Sie es erneut + Ein Absturz ist aufgetreten, ein Bericht wurde gesendet, um dieses Problem zu beheben + Erstellungsdatum + Aktuelle Datei herunterladen + Herunterladen + Dokumente durchsuchen + Alle Dokumente + Geteilte Dokumente + Alle Tags + Keine Tags + Fehler beim Laden von Tags + Keine Dokumente + Fehler beim Laden von Dokumenten + Keine Dateien + Fehler beim Laden von Dateien + Neues Dokument + Teilen + Schließen + Hinzufügen + Freigabename (optional) + Dieses Dokument wird derzeit nicht freigegeben + Diese Freigabe löschen + Send this share link + Fehler beim Laden von Freigaben + Fehler beim Hinzufügen der Freigabe + Freigabe Link + Fehler beim Löschen der Freigabe + Freigabe senden an + Datei hinzufügen + Datei hochladen von + Einstellungen + Ausloggen + Version + Build + Erweiterte Einstellungen + Über + GitHub + Fehler berichten + Cache leeren + Zwischengespeicherte Dateien löschen + Cache wurde geleert + Suchhistorie löschen + Leert die aktuellen Suchvorschläge + Suchvorschläge wurden gelöscht + Cache Größe + Français + English + Deutsch + Speichern + Bearbeiten + Netzwerkfehler, bitte versuchen Sie es erneut + Bitte warten + Daten werden gesendet + Löschen + Dokument löschen + Dieses Dokument und alle zugehörigen Dateien wirklich löschen? + Netzwerkfehler beim Löschen des Dokuments + Lösche Dokument + Datei löschen + Die aktuelle Datei wirklich löschen? + Netzwerkfehler beim Löschen der Datei + Lösche Datei + Fehler beim Lesen der Datei + Sismics Docs + Neue Datei in das Dokument hochladen + Fehler beim Hochladen der neuen Datei + Aktuelle Datei löschen + Erweiterte Suche + Suche + Tags hinzufügen + Erstellungsdatum + Beschreibung + Titel + Einfache Suche + Volltextsuche + Ersteller + Nach Datum + Vor Datum + Tags durchsuchen + Alle Sprachen + Informationen anzeigen + Wer kann darauf zugreifen? + Kommentare + Keine Kommentare + Fehler beim Laden von Kommentaren + Senden + Kommentar hinzufügen + Fehler beim Hinzufügen des Kommentars + Füge Kommentar hinzu + Kommentar löschen + Lösche Kommentar + Fehler beim Löschen des Kommentars + PDF + Download + Rand + Bild an Seite anpassen + Kommentare exportieren + Metadaten exportieren + mm + Sismics Docs Datei Export + Sismics Docs Dokumentenexport + Sismics Docs PDF Export + Letzte Aktivität + Aktivitäten + E-Mail + Speicherbegrenzung + %1$d/%2$d MB + Validierungscode + Geteilt + Sprache + Geltungsbereich + Typ + Quelle + Format + Verleger + Identifikator + Thema + Rechte + Mitwirkende + Beziehungen + + diff --git a/docs-android/app/src/main/res/values/strings.xml b/docs-android/app/src/main/res/values/strings.xml index 5d453293..e5ca3d48 100644 --- a/docs-android/app/src/main/res/values/strings.xml +++ b/docs-android/app/src/main/res/values/strings.xml @@ -71,6 +71,7 @@ Cache size Français English + Deutsch Save Edit Network error, please try again diff --git a/docs-core/src/main/resources/messages.properties.de b/docs-core/src/main/resources/messages.properties.de new file mode 100644 index 00000000..bfdd17d9 --- /dev/null +++ b/docs-core/src/main/resources/messages.properties.de @@ -0,0 +1,10 @@ +email.template.password_recovery.subject=Bitte setzen Sie ihr Passwort zur\u00FCck +email.template.password_recovery.hello=Hallo {0}. +email.template.password_recovery.instruction1=Wir haben eine Anfrage zum Zur\u00FCcksetzen Ihres Passworts erhalten.
Wenn Sie keine Hilfe angefordert haben, können Sie diese E-Mail einfach ignorieren. +email.template.password_recovery.instruction2=Um Ihr Passwort zur\u00FCckzusetzen, besuchen Sie bitte den folgenden Link: +email.template.password_recovery.click_here=Klicken Sie hier, um Ihr Passwort zur\u00FCckzusetzen +email.template.route_step_validate.subject=Ein Dokument braucht Ihre Aufmerksamkeit +email.template.route_step_validate.hello=Hallo {0}. +email.template.route_step_validate.instruction1=Ihnen wurde ein Workflow-Schritt zugewiesen, der Ihre Aufmerksamkeit erfordert. +email.template.route_step_validate.instruction2=Um das Dokument anzuzeigen und den Workflow zu \u00FCberpr\u00FCfen, besuchen Sie bitte den folgenden Link: +email.no_html.error=Ihr E-Mail-Client unterst\u00FCtzt keine HTML-Nachrichten \ No newline at end of file diff --git a/docs-core/src/main/resources/messages_de.properties b/docs-core/src/main/resources/messages_de.properties new file mode 100644 index 00000000..bfdd17d9 --- /dev/null +++ b/docs-core/src/main/resources/messages_de.properties @@ -0,0 +1,10 @@ +email.template.password_recovery.subject=Bitte setzen Sie ihr Passwort zur\u00FCck +email.template.password_recovery.hello=Hallo {0}. +email.template.password_recovery.instruction1=Wir haben eine Anfrage zum Zur\u00FCcksetzen Ihres Passworts erhalten.
Wenn Sie keine Hilfe angefordert haben, können Sie diese E-Mail einfach ignorieren. +email.template.password_recovery.instruction2=Um Ihr Passwort zur\u00FCckzusetzen, besuchen Sie bitte den folgenden Link: +email.template.password_recovery.click_here=Klicken Sie hier, um Ihr Passwort zur\u00FCckzusetzen +email.template.route_step_validate.subject=Ein Dokument braucht Ihre Aufmerksamkeit +email.template.route_step_validate.hello=Hallo {0}. +email.template.route_step_validate.instruction1=Ihnen wurde ein Workflow-Schritt zugewiesen, der Ihre Aufmerksamkeit erfordert. +email.template.route_step_validate.instruction2=Um das Dokument anzuzeigen und den Workflow zu \u00FCberpr\u00FCfen, besuchen Sie bitte den folgenden Link: +email.no_html.error=Ihr E-Mail-Client unterst\u00FCtzt keine HTML-Nachrichten \ No newline at end of file diff --git a/docs-importer/SismicsDocs.ico b/docs-importer/SismicsDocs.ico new file mode 100644 index 0000000000000000000000000000000000000000..4042f802faf9950fa2c5a9563ce316c9129071ba GIT binary patch literal 85182 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

%RP5(l!xzICVih9DKmyXVsPF$;}*pi z`mFexzU5HganSe?<2{ZckR#ud1J4&YvVbu}>VN1xR0n^oRWV>-p3Vhu-VgQbz90Xp zw*P+oDF;Cu*n{xCH{ba~c@fKCOzVRWcFM>;{mYF%>$^G~vKbr2x z#ih%AT~cJ|>+g8@6JK!XIXTljo}w{A?;al+tm`+*mxfJpOgz}E`5w8m%`TOV71HzZ zX)^eg!Sadr`z{#WS=LQ#Zu$w)f0R6z<457+%XVKf$B%3|@buq|FFE#~^8>Y0_sI|!{}j*fhipCK0oxyVa-jGx`kwOvadViTX=vi6y z$sK}r0{RP*6ze4Ap?+g~eo-ahZ;c~+x*mYPEenqQAF2JxuK!mXfc9jE&iV4ia;!Jw z%mGAQ5r68v%^3q!2maJ|Voi>Gq$BA*#m(yOzv; z|6y4^?k*jFZ7MspUm$Vz&8B@|_Z<*-o7>|@p)qB9>?o9uHkZV2|G7^&;66F?gYa+E zv_Re+k}GMuLvbIl2XQWNBpXoO_y@@X`uaeO`5~)_Wim7KbPcWyY2GSdntAxwa%?^9 zzRwO&4*b3V=V9J((D5+*VMAP^3W+I>3@`F{MN z`yKDkmqm+1ejjz^$36&u*n_IXpY4BQPJJh*9bjLt9rHu?*RD&Ku8(F(!`liK|9y`B z&sF>v=p0}de{v67t53l50k)j@juUTk^cf&c{K>=PJ{$kY`ky?{X%`sW-8g{#enuXw z_J0U>S5{oVkfi6l{xs~rvmRAL?d$3HPM)q2DlhXJ?1c`DeS2`X5aOszd*& z_q6xqjQP2~8~uK2YL2eOt9>u(_Zv1TDieQO4vZ{#Hh}$up>_hX_R9$6z{r3P|41@m z%K~xta~pr!fk?8zn2*>~|9e04zK$^$=zPySU281#eFEBkTlZ}l@XJAU>A#IX?SLKg zQ}^*4g@r|``>Pgx{#Ev(aaRchQ zEeFh_?f3I=U*Pxw$Urnd0C|86*w|Mb|B<>zb%6{Snyc#tI^QKgpJ+w#hcBp3{U`Rc z{ao7-?g3>fkOkOShMVyD#>>|NDf zic>~OL0n(S+4QtzuIVi4U$m0lOB%Q`0sCOJ9bKQ`w*|zXJY4^SW5TlVw_}26`rp1o zo~&N&y!VILnD2YR_6OO2+5}*3Q+41Eytxs3`hCXyuvO6gWuNa=JLkmwi2Hzj82)o_ zRlgsOzmbDTvY=QV+VhEAx^PlT&K!`l$1>#9!EJIZZ;5=FG1-xeU412UZ5P?SsIH0q zFV`1D>K_Qwf7$~Z|8TqSjs>d!@BPe3Z3k!T-0m#%-Y4*Ym-cVr>ehd=!SZ2rjuTa5S_IaFEv`fDx2 zr4qSx@r+zNe_YO=DV8%wQsj8SO8Ii{WGPB`M{+kkqjuvS*}e2ONnNNmN9{wh6&Ltz z0R2E|Ul3{sM0>x$`1*kMKjObp{fFzimwUbUdx$@=2M69Z=Kg))580?n{Mr7e{@c3G zxjlHd1LZ0x*st@K_UgA8)bDG1-^2eljsH{*ni>4n{zt-JZ9Xx#dHNSE4Ys!Zp)8_2 zER)0a+jJMts!SY_lGBB9?)Y9gv45i++%rK6cJ`6nEj=Z3-2<}c^A_rZ(0`~l-zCS+ zhre?c{C1<$jH<2jC5UNS;y8DbDN0&us0n45BncXrDXuV{@jTyZ@w{b_HUE}a_yDYQykg& z`YXu9Ik{MJTrQkFDCbY*$=Rc+a-wLp6sL}oto2=G&$4D}A8szQe;`_0z_$JV`2q23 zhZ_9xZWrG34Z@#tKwCiE!6_4vfvVJhd;HhYuhR26Q9eA+=U=3&?q?g_x3Om$`tRUh z+x7pj`{8mBiU~vULGG4k6}JNh@({j$32^o!9Y?-@d zKR@U8^urgp z&vFJH)XYf7knw)8v13QDx$U+K2)hk+koY<0o7suQAgB& z8-K*Fixy|;m_}YH{3!=P_{09EVjd{C>kH7Y7v>Xmf1kGB&K%vX_r4US`^1wRxcRq8 zSn|A}<3V{iKXm=CRUS8Myx1fV|44lTw*QCy_v3H31Im(t2@@t%dHWxA5QKkrcCqyB zmo3e1FDNJegSGwV_L{%rrFzJl;yu`*BYe=twKuT-S8KcWmE7BKezO~rp+9n#)fIyce8s*BNKP+U3r)K-bYM~erWF$Ihwc3=;OKL`%GUD$sJ~;XniV_B@?z`;(GcJH}V`qH8v-|d30qqa4@#ng4@c+ag9N5}&z%;Q3$2p&T z@=3MoKjXjrg2U4LEuD9JdtsUQ!v_T6A0z|x2b2Taf>58(&89t;wxqt=;oBsAc`Mns z`d-Q2*iH5)y=(da5xb+kkGO$2M#37nVzZA2{Rep^8vkW)e9G-72+bGp$APAANcA4_ z;Mf01_!DpHyni40X#Z8m`=6{2*Z|;<7+~wxxb^_g z%nkXc4(*UVOSP}ioiAwfpm>0GAQJxc0k#a-m;-n0!}ep09rX{NT-D!yMIBHdC)xIFj5A!&QJ+JhD$-2M0ukAQzPJ3xP6@b~o(`1Ri&L!t}>%@4qN=+oP? ztf{s!+G~663GHXP0+_nMiKlDFI z<9|Q?+$a79d#isSNCwP2Aodqw?ASMc9Hjr01B?jQGcjBl&<`YaIPAFaCb)QP13}6My24vM`OZQ4Snia6#AmIIs5ZluVy-RC@G0 zAh+MKUv6*Z;y<^JGiPUk#sDPMeOvzx{{EOCpnrfdfw2P>z~9z+VsGaK%^NfG1Khd8 zk>(0S#@|{0-^SnW1E3!O2f^l3?^(~R^Qy$3?SGVk_h)(h+%E^16MFRMS+xfzZ8DhQ%OZ@FVKw=Ktk2HL~jXmq#0H8nLh4_!yvrH_bUk03U!n1Pl z&_}g+&DkfYI{GJhQy@S8LOW?)?Cf}MTWabTddJmr; znm0VE?h^yNy4_05NuE;}5$J>`{-@Io2`vt5W}QuOO_6H_OCx$mtL4 zv4SrT7RuhOgB527f7k$$=LgEbKgbpkdvIWH6JtW!0^1IR;~zf1Jkb7|`K2N3Lvsa@ z=fr~4duKls1ID@fkG0-02P8=UZS09TIqMnw-xd5>HgMuj?#JI*|J}vk)qmpyTp0+% z-;x14F0`>n+V2BGauAXM;&0jnm=kRK0V@qzu>C-!SRgc4EF=f?1(X5ukSyrB!%<{<`EoIO?}L@Mjrpe3|Ako8uVq=UlNPhxf}q#h?D4x=!rDnMb`3 z5j2yt43j`T~Hp)fa5$0@(OpFNqsQ zc;EX%-!JA(qHSc?AM3fSysE_CZvU}d#M$O7JM*v){6Tn5^aY(faY(Y`hARGbz4$K` z@jr2AI;c(H+JZ><(*{5W7z>bx@JB3wK3yj!2)6~{?SDrWtau&K#G#gb~L6+jxhkF(=IJ2edeFH!+{Z?KXgo zIrN1+#TpW z<2}|9>kd39&pwWHb?86Kfbww*Dr?Yj%0S8a)AD830-b;HoMh{}nWbo><{5fgkA+j# zM(jUj=3Zg`6)1}o`=spK&|PAuKO#%Uc9r>~Ne_AHd83gIr+K3v6hosPl6f9!-YAfr zr|FRo%ChkfNW#(wBz47ulDhICNn6!b($_vBnH#z(JuaECO5iSKX?~XGfevJ?FgD+h zy~_+D~`H zOaHz*Bq45_?A^UnGBe^OKRZQ^9Lh2G50$xCp9kbTmw8To)(huP8NIjdKI@0|1s;^g ze4h7R!Jp;vmyh{;7IHj033>pZ07BZPpgjAyoyNKFr=T-u&r5dB8Tn$xaT)xc&PnUA zU)LRQ)*iz816+rw0n!%L*Y$}UDpKxHy+-&>BdEyG?RVts`;B`|8xDQ==)c2y7r1Y< z^7488xU_ z^O#RwmG~pp)hFbcXAkOkSFtulkPoozfYEj}k=g;T$$$1^_+nllhn*hv8N-k)>+c{mI=(s%o)B(Bk zF3eALi z|3v9G)PLO9zp+gIeC`Jw56Z*&LD%PXf_Tt%>^!Ey{c>>bT#4kVUs$m4xV-rCLH*{Q z#)DTIO7V*9)8`9i@@*^D&`VaHK`9E^z+53_5m~V5Y@qdzE4iG2i=AD)KDhEAZ zI4G^}bk?kKY(SxO>8jsl(f1pV9C7+#KxopnzlH32c^Ozqk565^OIrHrONO{cnbNm++ zE(e$7^qGrl^Dk)o5q(pkJ}aK@zbCKDf(ferY|?l z9CDsR83^J$$No>Gbfj}}KDJ25kkL9wTqpUppne21zYxvLcpBHp)P#*qA;x);G@|jl=&g%tnUMJ`n z@^~EFzwwxz@6Xe*!_1W{SGN4y-~I;O2ln5F?mOr^zw`q?)cdwk8Q7y`I)_I=IsN6c z^ZduS56;cbV}4Mc|GMS*KhGiO^|=qudzF>PbIBuJ%f60%u6-XnZJ!_MnwpR89O{1g z^5u6ZEQrg$jhNrY-A;SHVAZNsb@kn(k5mp*)D|7qa+RQP_H!_eZ2zI4JiDIw--_f# zI@i7y&k4$_NE!YAFYkWPbNln`a%dV`3F=tqO{M7k@Q>66*Hci?FZXTQd>eN=4H@{} zpa1;lAH4S3Yrh&dZd~o@)2H{+cIY^zS=t{lkEFX^nt3+=S2!M2M&^;*&t#{|dmQHl zo$KZ+n>9}B_yyE8>Kt`nP1u)`1GgNoLFjuzxoW6#>j3piqMwH^{z)Zl!1gY z)zG(F2j2zE%Pkx=C)U(JO%2r4KurzQ)Id!Q)YL#t4b;>?O%2r4KurzQ)Id!Q)YL#t z4b;>?O%2r4Kurx)eGQa%yt4AnTOWGJ@8hbW-Iy5Ny=3n<6ghA2|5W6-Z$H=Gzgon< zzurEsH!N$vuYLX%A~pL~h1AqXjXYT55K|)$HS$o!^03~%Upef#|NLD0|LQON{v^!b z{He4*3iDTe)M51vUC{V5&H5MG{;H+_hf-IiD`KwE-AD7aL3VcbQKe(iNY}VH79SsfZ2R`@hT`Jl%zi>b!m-4}#A8WGNrsY> zlaGN?Qc^rhO-(%pN=r*Kw0rmNV<5dZ=&1g;VEp*;)Ac$2tOdtB_GsG`S6_YgFLXZK zRGky)&Do8X#yeg3egfXrPfySA*4@OqdsuH3$M79BticDuIvyab=>Wo-oFJ^n48q#A zAbf)dgtZJoQ>RXy{DU9-0PkT%lcVqb;upX8Kf2~~PP8)f7|M>ap{!VMV!*&;rFdDl zey60R?H0w%d^?oSf%U{H`V1_;u1A@zGIfoXKbj1E@7KTn^z;F%{urwIXPwxOq`GJ9q>Cx#D@3) z7h>VZLBFGO_*cLB)nC3z`B83Qih4xdVvSanRZ$t0C!a}^Tj~^q(e14>WXQ0cvSCA< z;*qBBg=d=o;dww<+Z%*${GcB6-5GQ3plA4|=#z3=|b z`EN;%KuL4{E*{OkR+2pWo2D&V($?4l$S2BgKSSk~KeS${SAO^Vm64tS`DH%C;*ea|$4BLulPQzrzO(5Wt`M&kR`XOe}kWRc=DNaNlq>>a-=@866@bBzj=m#%JOk{%7=YlkvDpLC|x^$ zE{&S()B6`1y0u=R7^+*SzPZ2<%HO)>PPMbO!*m+uN7?ZVp!*-pm+YJal~R7h4e-6N zpDDWLvRPwQ*V#>)dxP}qK1u2}$d@_|3Z;&g8^rR1^BHQ@bIM<*ey%iEU$<;b8)I{6 zmrVI}q zJ$zSj@d26f(U7q61BcIsJ}z||>Y6Bx@}z0Abm`cBgO>GEdGD10^68Mr)CV`vaz?jJ zz+mC%yNqtsu3sQCXXSe~6!pJv-@eN(KkI(c;%w>HYh%Pl|Z9&t~8ezA0aI!F4wpz(tx z|I`DUht`|5Z4}FI;oy6Qg`@9Q-GSWadEb?T{lDDuQ|{r*XU)!$#!U;f{#Adiwe`)q z%I0}=y?w5mt^9JHVUd>qu_yAhJyGa=2N&fB?cKY#!tz78&&es4$Ghj~I$(ube)V6b z{Gsmyq%Xfij%3f5{fR>)ck{F6+w*M9HsoV?c*F-TKvJ?`YlYSt%LXh?Hjgn zDq4QlJ#5abIXTj#d4X4cXYG4k_gKq^HIMVRzv{Ntbp3)$x<00U+Zf-pJ({~z_9qY5 zHF$f-?xjssA1F_hrEp!?HoKk5eU@p*p!{|_P1}zZs(;pfQBkpUc__!Mxr8;A`n@>X z`<4^eYCpJpY^k=Uzy0}@e!IKmw63L}zd{b~`B>(ltHZXXyXZ2U>P# zZFu`T0F))#CVXdP-xay946w>?V?doo`MqzKSoRd_r0-tRQ1-38U-I<3 z#K6mm!9%*7xa2Mq_oF`v-x*|o3;d6!D_nkJ4P8EUszlapIIi)-hiY@ezt0i=9I&e) z+iLp+q)XdVwt@afQ2**@O&b_}DX4pt9p(5Y<;VYNkFw)G((;GCJz~m^b>^+_&4y&j z`F>E@&){H?xcDxw{HS~M*RT%1Y55^bsEeG0@bUu-J_Ggno0K1YT(F;r7g_eosDG3n z^^u=6F0B4b$&!B4!`20Uw;?(PPW>k>y<2j$Uk-NLE_-E^AJ>3QE#C8~`qHLKxA~}v zq^XZhThdtKW;N6pw1G?Ym4oUD;?x~V;0g2UO7g;b>cc{`Ti2LJe--NL+bBP-d*R#( zIeQ}C&>5H8`=^iPYMpgP4-xprWF*XM63jWW& zc2K$k`ukrvH|QD_$>Vciow7Oej%%Mtv3ZW$TNlWt&4s2tT9NCy<^QiT{MQxQ$Nqcu zf7unecC>Tx92YNM(pa)YKAV1AKGAPOpVhV7kss}U{$pyBvQaiIf3)$Jn4kRQCs%LX zx^=Ao|KD`q!2|sOp>-iEa?LGUwv5%XVLg|!wkv-B```b&j>WyNK5(z%cF0Fx>VA32 z|KAGlqYNku%2Zat?c@LPAOCTs{^u8e_`@H5SB>;rEyFMW_{TqD{fe5crUq(iz*hs2 zrZk!9Qh#!%QE_^%@?89%({XFKS084&8S6>w%}jT07^!wc`Ix75jZ!0}nt57U3FX@` zhXHeneyQ}UN+w(r*N!w#0&`S;)4O-?p_3*}S~+?0M>)+tp4buk31SXcI;}9uK8q0=g6#fY1ON*zB&~5&@u$YI#>4BEmG`(I0gNs`}SqY zmMtl!KLGt1=m$eTF#6)rpUZJgv^O|LZqIjl>#eu?>HUNJ=2bIi&Rp!jKVojQkI>(V z`4AH)rRq0Wa^&?lk|Z`Z!Rwb}e;oUzSss5GrcIlMb+555l7G8O=LapZ?~nW9dC+&D zbCLA>4GH=km`rajM*}U#8*e4b#*GPPd{_Ho&ADjnV(tpYdr>!b89x2=(c$gdo*d_<1%SrH<|r@S3Ta*(6;#<_56;qeL*ML^+gZU zSHrP#v|si4%YA>etM|q}AJ&&>`bB-?0~{yg{DWkSz0T432Me2+Hb3f+@}TpbF5~{} zivkbtTjp4cR|byz>irWJG&VS(zlZY%Dt`YL-2O23Ck2-wY4-o;4#zHQxf(GU#_<(YLs3=1sC-R7V;8)+_Sj6XWIXJ2y(hMj1M` z*2f)ty;jEpZ!_brEm~*kxOaxp-zih3l)L`XFSIwdm)EzpaC9f>^~7Z9+WE3@#&>H zPCZJd4%Yrl^x5mUA@6@%3(O@uU~E)*?~gWoVc{W}|Iu^a{a1b5MsB}7RUYiLLi+R^ zDH8|wkQL+a&@n-LyVI2mOE*@1+|1aD(H|BV`vsd+p8Mn3VKc{nk}DGizF_*3*-y1= z)~$+%zrWLw3BPXO{w-SPt4(s|Yrqz%4=J<$@$9*|2X($(zTUr=bAR&WGd76hZ4)O>jCz0Kj{jj?ZNebj-|4%~)IRD<7td;cd!CNhESKWs z_s#bl(P!rGvxW?8o!(T(_i{~tFUQQvx<71wUfv$>_F7#hyO(xPMx}-UH}3&CI+?^!Xz`0JiY)<@LYtfBQDQ5U zii$ozWdZVFlhY4dqW1Bqw7dh~+j9C~J9N%do4w!k)AD>iH+hujzfzBR->KpG(Kzmb z{>P8TIptWmxY*n~+JA5lmA|0)_lgfb_~5l@|BZAE=UKj)F)vK4G7himFOxLbmU%|DsjP`a#_wL<$`1K$50kPla%^9+GU8;#m z5Dy^F-)2Y5&Gve?Zrz^Ii`%y1iave%yvyt3x@aR{To-NMZcpqr?Sft}rRlp3Dds-t zBfxR^VB8aJLEc0AI^KM~5&sa`mj2Wyj|)$&N2x zmYqt8Yu_<(Hrv~;zy5mE>!W?0zPhUyuld`yUYpX)!`1fef_i5D1KYFZyZ*yoJminh z*-lBCt@AYX9&xkk%J%KMO)t|J`et{?Dt>;F_L!B1O zXG0#+_RzJmeqw!%>2hS?;B>|0Q2DQ~?aw7+?$No)%k({v-C^xM%v0y9ta{(D!;D^HD=vHg07SboU;@#81uvB&fD`j49SQR>25b?(d)8WT4+?G-N$<2)w4eym=9 z+2;i&7DX%^>G~-97t8S-xk8ye64$>`GS@v|Vz{p^m6-O=@uIbIAoW9yzn{_h0*#Ff zC(LVL;yw0-z5Mdaf#pAQ=A6!lEHKxfGx9OhzCqjKSiuT8cOpw;Ehko`o)@QnV6LCE zpn>UwV_PE9_0ONbWWIxjZz9ea)y^x8|X zO>e&WW?=bIE?{u*;5pg3=y9ukfH@wxN2py8!a?WM>-BTAJ%qL(Vo2Dsvh2^^^-p;5 zcZxTcC-@#o3mcjD>Tqq8v8?Ok8NSR~pmQll%l?#6%16oW*x@pE;5#z>jR7*OcYo#m zC1qWIDNGtJ`%}kx?TGSRpZM7v_bl39BEv=;k!CH684jMG*ZKZyfNpBArFrcf(nt?vpf6sq~eGQcw z=f+&!czw+G8~2U5;u{mL1HyGdh{JxSbdA!t9fy7Y``^F1dGqF-+qG-g9n`jM+wLt} zw(Q=jRjcl;TemiJ#~pWc2eoO_rhC(-O*`X1S~RnD?AWm#L zeQk_2Fz4)^d+uq=|3Ccj!(H%y=;^-1d9q{8hw}X6)1=2E(`4$Hagw-ktR!z9Cu!TK znCl>3dEkKuy7>POJH7jhcE&c^v4e>l5HrlX#l#Enb6s=`{{LOB|GrMPeO6oMjJQwx zaQn)dPnyWqX}8Erui)Kdo$DO%f5b<-zqm`*OlT?X+U(H2(E@$nB~R{dyHVzj=&b$G zwe%gA0!c|ZB=_Hcf2sTL%RDNpC*Gy+J>DuK-+EIPe$Y{N&bY;S9`v7Se|GOT3rxSU z|Npr6+x-h=`S|t%dwxKD1p0!UzBs2JaL07@wMowV4)@)6U)cRKGf(K;bN&Cv_vn1( zwsQ99Zg;Np*HUukfMjiWROb`dHuI_A&;0*CeE5Q~VQVJctM(rKLfS{TQ0L~Z?kELu zebf&(lO+8=#$X@|8ZUeIM;iD8zx0(I9sgnaRMf7!eJRFo%&%kmZXjd!|0zGX#_|0d z(7=HMTc|CJH15dDmWzwbZQS>Y%Om{v{{#6lH30ws literal 0 HcmV?d00001 diff --git a/docs-web/src/main/webapp/src/locale/de.json b/docs-web/src/main/webapp/src/locale/de.json index 476d0dcc..7fdf845f 100644 --- a/docs-web/src/main/webapp/src/locale/de.json +++ b/docs-web/src/main/webapp/src/locale/de.json @@ -24,8 +24,8 @@ "passwordreset": { "message": "Bitte geben Sie ein neues Passwort ein.", "submit": "Mein Passwort ändern", - "error_title": "Fehler beim ändern des Passworts.", - "error_message": "Ihre Anfrage zur Passwort-Wiederherstellung ist abgelaufen, bitte wiederholen Sie die die Anfrage." + "error_title": "Fehler beim Ändern des Passworts.", + "error_message": "Ihre Anfrage zur Passwort-Wiederherstellung ist abgelaufen, bitte wiederholen Sie die Anfrage." }, "index": { "toggle_navigation": "Navigation ein-/ausblenden", @@ -36,11 +36,13 @@ "logged_as": "Eingeloggt als {{ username }}", "nav_settings": "Einstellungen", "logout": "Logout", - "global_quota_warning": "Warnung! Der frei zur Verfügung stehende maximale Speicherplatz ist fast erreicht bei {{ current | number: 0 }}MB ({{ percent | number: 1 }}%) verwendet {{ total | number: 0 }}MB" + "global_quota_warning": "Warnung! Der frei zur Verfügung stehende, maximale Speicherplatz ist fast erreicht bei {{ current | number: 0 }}MB ({{ percent | number: 1 }}%) verwendet {{ total | number: 0 }}MB" }, "document": { "navigation_up": "Eine Stufe höher", "toggle_navigation": "Navigation ein-/ausblenden", + "display_mode_list": "Dokumente in Liste anzeigen", + "display_mode_grid": "Dokumente im Raster anzeigen", "search_simple": "Einfache Suche", "search_fulltext": "Volltext Suche", "search_creator": "Urheber", @@ -76,8 +78,8 @@ "type": "Typ", "coverage": "Geltungsbereich", "rights": "Rechte", - "relations": "Beziehung", - "page_size": "Seiten Größe", + "relations": "Beziehungen", + "page_size": "Seitengröße", "page_size_10": "10 pro Seite", "page_size_20": "20 pro Seite", "page_size_30": "30 pro Seite", @@ -94,12 +96,12 @@ "shared_document_message": "Sie können dieses Dokument mit diesem Link freigeben. Beachten Sie, dass jeder, der diesen Link hat, das Dokument sehen kann.
", "not_found": "Dokument nicht gefunden", "forbidden": "Zugriff verweigert", - "download_files": "Download Datei", + "download_files": "Datei herunterladen", "export_pdf": "in PDF exportieren", "by_creator": "von", "comments": "Kommentar", "no_comments": "Noch keine Kommentare zu diesem Dokument vorhanden", - "add_comment": "Fügen sie einen Komentar hinzu", + "add_comment": "Fügen sie einen Kommentar hinzu", "error_loading_comments": "Fehler beim Laden eines Kommentars", "workflow_current": "Aktueller Workflow-Status", "workflow_comment": "Fügen Sie einen Workflow Kommentar hinzu", @@ -111,27 +113,28 @@ "delete_file_message": "Wollen Sie diese Datei wirklich löschen?", "upload_pending": "Ausstehend...", "upload_progress": "Hochladen...", - "upload_error": "Fehler beim hochladen", + "upload_error": "Fehler beim Hochladen", "upload_error_quota": "Maximaler Speicherplatz erreicht", - "drop_zone": "Drag & Drop Dateien hier her ziehen, um diese hochzuladen", + "drop_zone": "Drag & Drop Dateien hierherziehen, um diese hochzuladen", "add_files": "Dateien hinzufügen", - "file_processing_indicator": "Diese Datei wird gerade bearbeitet. Die Suche wird nicht verfügbar sein, bevor sie abgeschlossen ist.", - "reprocess_file": "Diese Datei erneut bearbeiten" + "file_processing_indicator": "Diese Datei wird gerade bearbeitet. Die Suche wird nicht verfügbar sein, bevor der Vorgang abgeschlossen ist.", + "reprocess_file": "Diese Datei erneut verarbeiten" }, "workflow": { "workflow": "Workflow", - "message": "Verifizieren oder validieren Sie Ihre Dokumente mit Mitarbeitern Ihres Unternehmens mithilfe von Workflows.", + "message": "Verifizieren oder validieren Sie Ihre Dokumente mit Mitarbeitern Ihres Unternehmens mit Hilfe von Workflows.", "workflow_start_label": "Welcher Workflow soll gestartet werden?", "add_more_workflow": "Fügen Sie weitere Workflows hinzu", "start_workflow_submit": "Starten Sie den Workflow", "full_name": "{{ name }} gestartet am {{ create_date | date }}", "cancel_workflow": "Abbrechen des aktuellen Workflows", "cancel_workflow_title": "Abbrechen des Workflows", - "cancel_workflow_message": "Wollen Sie den laufenden Workflow wirklich abbrechen?" + "cancel_workflow_message": "Wollen Sie den laufenden Workflow wirklich abbrechen?", + "no_workflow": "Sie können keinen Workflow für dieses Dokument starten." }, "permissions": { "permissions": "Berechtigungen", - "message": "Die Berechtigungen können direkt auf dieses Dokument angewendet werden, oder sind erhältlich bei tags.", + "message": "Die Berechtigungen können direkt auf dieses Dokument angewendet werden, oder können von tags vorgegeben werden.", "title": "Berechtigungen auf diesem Dokument", "inherited_tags": "Von Tags geerbte Berechtigungen", "acl_source": "Von", @@ -150,7 +153,7 @@ "primary_metadata": "Primäre Metadaten", "title_placeholder": "Titel des Dokuments", "description_placeholder": "Zusammenfassung, Inhaltsverzeichnis oder Freitext", - "new_files": "New files", + "new_files": "neue Dateien", "orphan_files": "+ {{ count }} Datei{{ count > 1 ? 's' : '' }}", "additional_metadata": "Weitere Metadaten", "subject_placeholder": "Schlüsselwörter, abstrakte Sätze oder Klassifizierungscodes", @@ -163,16 +166,16 @@ "default": { "upload_pending": "Ausstehend...", "upload_progress": "Lädt hoch...", - "upload_error": "Fehler beim hochladen", + "upload_error": "Fehler beim Hochladen", "upload_error_quota": "Maximaler Speicherplatz erreicht", - "quick_upload": "Schnelles hochladen", - "drop_zone": "Drag & Drop Dateien hier her ziehen, um diese hochzuladen", + "quick_upload": "Schnelles Hochladen", + "drop_zone": "Drag & Drop Dateien hierherziehen, um diese hochzuladen", "add_files": "Dateien hinzufügen", "add_new_document": "Neues Dokument hinzufügen", "latest_activity": "Letzte Aktivitäten", - "footer_sismics": "Programmiert mit by Sismics", + "footer_sismics": "Programmiert mit von Sismics", "api_documentation": "API Dokumentation", - "feedback": "Geben Sie uns Feedback", + "feedback": "Geben Sie uns Ihr Feedback", "workflow_document_list": "Mir zugeordnete Dokumente", "select_all": "Alle auswählen", "select_none": "Nichts auswählen" @@ -209,7 +212,7 @@ "title": "Tags", "message_1": "Tags sind Kategorien, die den Dokumenten zugeordnet sind.", "message_2": "Ein Dokument kann mit mehreren Tags versehen werden und ein Tag kann auf mehrere Dokumente angewendet werden.", - "message_3": "Verwendung der Schaltfläche können Sie die Berechtigungen für ein Tag bearbeiten.", + "message_3": "Unter Verwendung der Schaltfläche können Sie die Berechtigungen für ein Tag bearbeiten.", "message_4": "Wenn ein Tag von einem anderen Benutzer oder einer anderen Gruppe gelesen werden kann, können die zugehörigen Dokumente auch von diesen Personen gelesen werden.", "message_5": "Kennzeichnen Sie z.B. Ihre Firmendokumente mit einem Tag MyCompany und fügen Sie die Berechtigung Can read zu einer Gruppe hinzu employees" }, @@ -219,7 +222,9 @@ "name": "Name", "color": "Farbe", "parent": "Übergeordnet", - "info": "Berechtigungen für dieses Tag werden auch auf Dokumente angewendet, die mit einem Tag versehen sind {{ name }}" + "info": "Berechtigungen für dieses Tag werden auch auf Dokumente angewendet, die mit einem Tag versehen sind {{ name }}", + "circular_reference_title": "Zirkuläre Referenz", + "circular_reference_message": "Die Hierarchie der übergeordneten Tags bildet eine Schleife. Bitte wählen Sie ein anderes übergeordnetes Tag." } }, "group": { @@ -234,7 +239,7 @@ "profile": { "groups": "Gruppen", "quota_used": "Benutzter Speicherplatz", - "percent_used": "{{ percent | number: 0 }}% Benutzt", + "percent_used": "{{ percent | number: 0 }}% genutzt", "related_links": "Weiterführende Links", "document_created": "Dokumente erstellt von {{ username }}", "edit_user": "Benutzer {{ username }} bearbeiten" @@ -250,18 +255,18 @@ } }, "settings": { - "menu_personal_settings": "Peröhnliche Einstellungen", + "menu_personal_settings": "Persönliche Einstellungen", "menu_user_account": "Benutzerkonto", "menu_two_factor_auth": "Zwei-Faktor-Authentifizierung", - "menu_opened_sessions": "Geöffnete Sitzung", + "menu_opened_sessions": "Geöffnete Sitzungen", "menu_file_importer": "Massen Datei Importer", "menu_general_settings": "Generelle Einstellungen", - "menu_workflow": "Workflow", - "menu_users": "Benutzer", - "menu_groups": "Gruppen", - "menu_vocabularies": "Vokabulare", + "menu_workflow": "Workflows", + "menu_users": "Benutzerverwaltung", + "menu_groups": "Gruppenverwaltung", + "menu_vocabularies": "Vokabulareinträge", "menu_configuration": "Einstellungen", - "menu_inbox": "Inbox scannen", + "menu_inbox": "Posteingang durchsuchen", "menu_monitoring": "Überwachung", "user": { "title": "Benutzerverwaltung", @@ -290,7 +295,7 @@ } }, "workflow": { - "title": "Workflow Konfigurator", + "title": "Workflows", "add_workflow": "Workflow hinzufügen", "name": "Name", "create_date": "Erstellungsdatum", @@ -306,22 +311,23 @@ "type_approve": "Genehmigen", "type_validate": "Bestätigen", "target": "Zugewiesen an", - "target_help": "Zulassen: Überprüfen und fortsetzen des Workflows
Genemigen: Übernehmen oder lehnen Sie die Überprüfung ab", + "target_help": "Zulassen: Überprüfen und fortsetzen des Workflows
Genehmigen: Übernehmen oder lehnen Sie die Überprüfung ab", "add_step": "Workflow Schritt hinzufügen", "actions": "Was passiert danach?", - "remove_action": "Aktion entfernen" + "remove_action": "Aktion entfernen", + "acl_info": "Nur hier definierte Benutzer und Gruppen können diesen Workflow für ein Dokument starten" } }, "security": { "enable_totp": "Zwei-Faktor-Authentifizierung aktivieren", - "enable_totp_message": "Stellen Sie sicher, dass Sie eine TOTP-kompatible Anwendung auf Ihrem Handy haben, die bereit ist, ein neues Konto hinzuzufügen.", + "enable_totp_message": "Stellen Sie sicher, dass Sie eine TOTP-kompatible Anwendung auf Ihrem Telefon haben, die bereit ist, ein neues Konto hinzuzufügen.", "title": "Zwei-Faktor-Authentifizierung", - "message_1": "Die Zwei-Faktor-Authentifizierung ermöglicht Ihnen eine weitere Abischerung Ihres {{ appName }} Benutzerkontos. Bevor Sie diese Funktion aktivieren, stellen Sie sicher, dass Sie eine TOTP-kompatible Anwendung auf Ihrem Telefon haben:", + "message_1": "Die Zwei-Faktor-Authentifizierung ermöglicht Ihnen eine weitere Absicherung Ihres {{ appName }} Benutzerkontos. Bevor Sie diese Funktion aktivieren, stellen Sie sicher, dass Sie eine TOTP-kompatible Anwendung auf Ihrem Telefon haben:", "message_google_authenticator": "Für Android, iOS, und Blackberry: Google Authenticator", "message_duo_mobile": "Für Android und iOS: Duo Mobile", "message_authenticator": "Für Windows Phone: Authenticator", - "message_2": "Diese Anwendungen generieren automatisch einen Validierungscod der sich nach einer gewissen Zeitspanne ändert. Sie müssen diesen Validierungscode jedes Mal eingeben, wenn Sie sich bei {{ appName }} anmelden. .", - "secret_key": "Ihr geheimer Schlüssel ist: {{ secret }}", + "message_2": "Diese Anwendungen generieren automatisch einen Validierungscode, der sich nach einer gewissen Zeitspanne ändert. Sie müssen diesen Validierungscode jedes Mal eingeben, wenn Sie sich bei {{ appName }} anmelden. .", + "secret_key": "Ihr geheimer Schlüssel lautet: {{ secret }}", "secret_key_warning": "Konfigurieren Sie Ihre TOTP-App jetzt mit diesem geheimen Schlüssel auf Ihrem Telefon. Sie können später nicht mehr darauf zugreifen.", "totp_enabled_message": "Die Zwei-Faktor-Authentifizierung ist in Ihrem Konto aktiviert.
Bei jeder Anmeldung auf {{ appName }}, werden Sie in Ihrer konfigurierten Telefon-App nach einem Bestätigungscode gefragt.
Wenn Sie Ihr Telefon verlieren, können Sie sich nicht in Ihrem Konto anmelden, aber aktive Sitzungen ermöglichen es Ihnen, einen geheimen Schlüssel neu zu generieren.", "disable_totp": { @@ -358,7 +364,7 @@ }, "config": { "title_guest_access": "Gastzugang", - "message_guest_access": "Der Gastzugang ist ein Modus in dem jeder Zugriff hat und {{ appName }} ohne Passwort nutzen kann.
Wie ein normaler Benutzer kann der Gastbenutzer nur auf seine Dokumente zugreifen und Berechtigungen zugreifen.
", + "message_guest_access": "Der Gastzugang ist ein Modus, in dem jeder auf {{appName}} ohne Kennwort zugreifen kann.
Wie ein normaler Benutzer kann der Gastbenutzer nur auf seine Dokumente und diejenigen zugreifen, auf die er über Berechtigungen zugreifen kann.
", "enable_guest_access": "Gastzugang aktivieren", "disable_guest_access": "Gastzugang deaktivieren", "title_theme": "Aussehen anpassen", @@ -371,18 +377,24 @@ "logo": "Logo (quadratische Größe)", "background_image": "Hintergrundbild", "uploading_image": "Bild hochladen...", - "title_smtp": "SMTP Email Einstellungen für Passwort wiederherstellungfür das Zürucksetzen des Passworts", "smtp_hostname": "SMTP Server", "smtp_port": "SMTP Port", "smtp_from": "Absender E-Mail", "smtp_username": "SMTP Benutzername", "smtp_password": "SMTP Passwort", - "smtp_updated": "SMTP Konfiguration erfolgreich aktualisiert" + "smtp_updated": "SMTP Konfiguration erfolgreich aktualisiert", + "webhooks": "Webhooks", + "webhooks_explain": "Webhooks werden aufgerufen, wenn das angegebene Ereignis eintritt. Die angegebene URL wird mit einer JSON-Payload gepostet, die den Ereignisnamen und die ID der betreffenden Ressource enthält.", + "webhook_event": "Ereignisse", + "webhook_url": "URL", + "webhook_create_date": "Erstelldatum", + "webhook_add": "Webhook hinzufügen" }, "inbox": { "title": "Posteingang durchsuchen", - "message": "Wenn Sie diese Funktion aktivieren, durchsucht das System den angegebenen Posteingang jede Minute nach ungelesenen E-Mails und importieren diese automatisch.
Nach dem Import einer E-Mail wird diese als gelesen markiert.
Folgen Sie den Links zu Konfigurationseinstellungen für Gmail, Outlook.com, Yahoo.", - "enabled": "Posteingang duchrsuchen aktivieren", + "message": "Wenn Sie diese Funktion aktivieren, durchsucht das System den angegebenen Posteingang jede Minute nach ungelesenen E-Mails und importiert diese automatisch.
Nach dem Import einer E-Mail wird diese als gelesen markiert.
Folgen Sie den Links zu Konfigurationseinstellungen für Gmail, Outlook.com, Yahoo.", + "enabled": "Durchsuchen des Posteingangs aktivieren", "hostname": "IMAP Server", "port": "IMAP Port (143 oder 993)", "username": "IMAP Benutzername", @@ -391,16 +403,21 @@ "test": "Konfiguration testen", "last_sync": "Letzte Synchronisation: {{ data.date | date: 'medium' }}, {{ data.count }} E-Mail(s){{ data.count > 1 ? 's' : '' }} importiert", "test_success": "Die Verbindung zum Posteingang war erfolgreich ({{ count }} unread message{{ count > 1 ? 's' : '' }})", - "test_fail": "Beim Verbinden mit dem Posteingang ist ein Fehler aufgetreten, bitte überprüfen Sie die Einstellungen" + "test_fail": "Beim Verbinden mit dem Posteingang ist ein Fehler aufgetreten, bitte überprüfen Sie die Einstellungen", + "saved": "IMAP Konfiguration erfolgreich gespeichert" }, "monitoring": { "background_tasks": "Hintergrundaufgaben", - "queued_tasks": "Es gibt derzeit {{ count }}} anstehende Tasks.", + "queued_tasks": "Es gibt derzeit {{ count }} anstehende Tasks.", "queued_tasks_explain": "Dateiverarbeitung, Thumbnail-Erstellung, Index-Update, optische Zeichenerkennung sind Hintergrundaufgaben. Eine große Anzahl unbearbeiteter Aufgaben führt zu unvollständigen Suchergebnissen.", - "server_logs": "Server logs", + "server_logs": "Server Logs", "log_date": "Datum", "log_tag": "Tag", - "log_message": "Nachricht" + "log_message": "Nachricht", + "indexing": "Indexierung", + "indexing_info": "Wenn Sie Unstimmigkeiten in den Suchergebnissen feststellen, können Sie versuchen, eine vollständige Neuindizierung durchzuführen. Die Suchergebnisse sind bis zum Abschluss dieser Operation unvollständig.", + "start_reindexing": "Vollständige Neuindizierung starten", + "reindexing_started": "Neuindizierung wurde gestartet, bitte warten Sie, bis es keine Hintergrundaufgaben mehr gibt." }, "session": { "title": "Geöffnete Sitzungen", @@ -413,7 +430,7 @@ "clear": "Alle anderen Sitzungen löschen" }, "vocabulary": { - "title": "Vokabulareinträge", + "title": "Vokabular", "choose_vocabulary": "Wählen Sie ein Vokabular aus, das Sie bearbeiten möchten.", "type": "Typ", "coverage": "Abdeckung", @@ -423,31 +440,31 @@ "new_entry": "Neuer Eintrag" }, "fileimporter": { - "title": "Massen Datei Importeur", + "title": "Massen Datei Importer", "advanced_users": "Für fortgeschrittene Benutzer!", "need_intro": "Wenn Sie:", "need_1": "Ganze Verzeichnisse von Dateien auf einmal importieren möchten", "need_2": "Ein Verzeichnis nach neuen Dateien durchsuchen lassen und gefunden Dateien importieren lassen möchten", "line_1": "Gehen Sie zu sismics/docs/releases und laden Sie das Datei-Importer-Tool für Ihr System herunter.", - "line_2": "Folgen Sie dem Link instructions here um das Import-Toll zu nutzen.", - "line_3": "Ihre Dateien werden in Quick upload importiert, danach können Sie die Dateien weiterbearbeiten und Dokumenten zuordnen oder Dokumente erstellen.", + "line_2": "Folgen Sie den Anweisungen, um das Import-Tool zu nutzen.", + "line_3": "Ihre Dateien werden in Modus 'Schnelles Hochladen' importiert. Danach können Sie die Dateien weiterbearbeiten und Dokumenten zuordnen oder Dokumente erstellen.", "download": "Herunterladen", "instructions": "Anweisungen" } }, "feedback": { "title": "Geben Sie uns Feedback", - "message": "Irgendwelche Vorschläge oder Fragen zu Sismics Docs? Wir hören Ihnen genre zu!", + "message": "Irgendwelche Vorschläge oder Fragen zu Sismics Docs? Wir hören Ihnen gerne zu!", "sent_title": "Feedback gesendet", "sent_message": "Vielen Dank für Ihr Feedback! Es wird uns helfen, Sismics Docs noch besser zu machen." }, "import": { "title": "Wird importiert", - "error_quota": "Speicher Limit erreicht, kontaktieren Sie Ihren Administrator, um den Ihnen zur verfügung gestellten Speicherplatz zu erhöhen.", + "error_quota": "Speicherlimit erreicht. Kontaktieren Sie Ihren Administrator, um den Ihnen zur Verfügung gestellten Speicherplatz zu erhöhen.", "error_general": "Beim Versuch, Ihre Datei zu importieren, ist ein Fehler aufgetreten. Bitte stellen Sie sicher, dass es sich um eine gültige EML-Datei handelt." }, "app_share": { - "main": "Fragen Sie nach einen Link zu einem gemeinsam genutzten Dokument, um darauf zuzugreifen.", + "main": "Fragen Sie nach einem Link zu einem gemeinsam genutzten Dokument, um darauf zuzugreifen.", "403": { "title": "Nicht erlaubt", "message": "Das Dokument, das Sie anzeigen möchten, ist nicht mehr freigegeben." @@ -458,7 +475,7 @@ "acl_target": "Für", "acl_permission": "Zugriffsberechtigung", "add_permission": "Zugriffsberechtigung hinzufügen", - "search_user_group": "Suchen einen Benutzer oder eine Gruppe" + "search_user_group": "Suchen nach einem Benutzer oder einer Gruppe" }, "auditlog": { "log_created": "erstellt", @@ -468,7 +485,7 @@ "Comment": "Kommentar", "Document": "Dokument", "File": "Datei", - "Group": "Guppe", + "Group": "Gruppe", "Tag": "Tag", "User": "Benutzer", "RouteModel": "Workflow-Muster", @@ -515,13 +532,13 @@ "too_long": "Zu lang", "email": "Muss eine gültige E-Mailadresse sein", "password_confirm": "Passwort und Passwortbestätigung müssen übereinstimmen", - "number": "Nummer erfoderlich", + "number": "Nummer erforderlich", "no_space": "Leerzeichen sind nicht erlaubt" }, "action_type": { "ADD_TAG": "Tag hinzufügen", "REMOVE_TAG": "Tag entfernen", - "PROCESS_FILES": "Dateien bearbeiten" + "PROCESS_FILES": "Dateien verarbeiten" }, "pagination": { "previous": "Vorherige", @@ -532,7 +549,7 @@ "ok": "OK", "cancel": "Abbrechen", "share": "Teilen", - "unshare": "Nicht mehr Teilen", + "unshare": "Nicht mehr teilen", "close": "Schliessen", "add": "Hinzufügen", "open": "Öffnen", @@ -543,7 +560,7 @@ "delete": "Löschen", "rename": "Umbenennen", "loading": "Lädt...", - "send": "Gesendet", + "send": "Absenden", "enabled": "Aktiviert", "disabled": "Deaktiviert" } \ No newline at end of file From 6e56a0f5689feddd02058c23ce53b83bf5589713 Mon Sep 17 00:00:00 2001 From: Benjamin Gamard Date: Thu, 24 Jan 2019 17:26:46 +0100 Subject: [PATCH 09/10] #289: better search parsing (including wildcard and fuzzy) --- .../util/indexing/LuceneIndexingHandler.java | 47 +++++++++++-------- .../docs/rest/TestDocumentResource.java | 1 + 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/docs-core/src/main/java/com/sismics/docs/core/util/indexing/LuceneIndexingHandler.java b/docs-core/src/main/java/com/sismics/docs/core/util/indexing/LuceneIndexingHandler.java index 40f17127..948e18fb 100644 --- a/docs-core/src/main/java/com/sismics/docs/core/util/indexing/LuceneIndexingHandler.java +++ b/docs-core/src/main/java/com/sismics/docs/core/util/indexing/LuceneIndexingHandler.java @@ -25,8 +25,7 @@ import org.apache.lucene.document.Field; import org.apache.lucene.document.StringField; import org.apache.lucene.document.TextField; import org.apache.lucene.index.*; -import org.apache.lucene.queryparser.flexible.standard.QueryParserUtil; -import org.apache.lucene.queryparser.flexible.standard.StandardQueryParser; +import org.apache.lucene.queryparser.simple.SimpleQueryParser; import org.apache.lucene.search.*; import org.apache.lucene.search.highlight.Highlighter; import org.apache.lucene.search.highlight.QueryScorer; @@ -371,29 +370,26 @@ public class LuceneIndexingHandler implements IndexingHandler { * @throws Exception e */ private Map search(String searchQuery, String fullSearchQuery) throws Exception { - // Escape query and add quotes so QueryParser generate a PhraseQuery - String escapedSearchQuery = "\"" + QueryParserUtil.escape(searchQuery + " " + fullSearchQuery) + "\""; - String escapedFullSearchQuery = "\"" + QueryParserUtil.escape(fullSearchQuery) + "\""; + // The fulltext query searches in all fields + searchQuery = searchQuery + " " + fullSearchQuery; // Build search query Analyzer analyzer = new StandardAnalyzer(); - StandardQueryParser qpHelper = new StandardQueryParser(analyzer); - qpHelper.setPhraseSlop(100); // PhraseQuery add terms // Search on documents and files BooleanQuery query = new BooleanQuery.Builder() - .add(qpHelper.parse(escapedSearchQuery, "title"), BooleanClause.Occur.SHOULD) - .add(qpHelper.parse(escapedSearchQuery, "description"), BooleanClause.Occur.SHOULD) - .add(qpHelper.parse(escapedSearchQuery, "subject"), BooleanClause.Occur.SHOULD) - .add(qpHelper.parse(escapedSearchQuery, "identifier"), BooleanClause.Occur.SHOULD) - .add(qpHelper.parse(escapedSearchQuery, "publisher"), BooleanClause.Occur.SHOULD) - .add(qpHelper.parse(escapedSearchQuery, "format"), BooleanClause.Occur.SHOULD) - .add(qpHelper.parse(escapedSearchQuery, "source"), BooleanClause.Occur.SHOULD) - .add(qpHelper.parse(escapedSearchQuery, "type"), BooleanClause.Occur.SHOULD) - .add(qpHelper.parse(escapedSearchQuery, "coverage"), BooleanClause.Occur.SHOULD) - .add(qpHelper.parse(escapedSearchQuery, "rights"), BooleanClause.Occur.SHOULD) - .add(qpHelper.parse(escapedSearchQuery, "filename"), BooleanClause.Occur.SHOULD) - .add(qpHelper.parse(escapedFullSearchQuery, "content"), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "title").parse(searchQuery), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "description").parse(searchQuery), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "subject").parse(searchQuery), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "identifier").parse(searchQuery), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "publisher").parse(searchQuery), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "format").parse(searchQuery), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "source").parse(searchQuery), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "type").parse(searchQuery), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "coverage").parse(searchQuery), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "rights").parse(searchQuery), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "filename").parse(searchQuery), BooleanClause.Occur.SHOULD) + .add(buildQueryParser(analyzer, "content").parse(fullSearchQuery), BooleanClause.Occur.SHOULD) .build(); // Search @@ -435,6 +431,19 @@ public class LuceneIndexingHandler implements IndexingHandler { return documentMap; } + /** + * Build a query parser for searching. + * + * @param analyzer Analyzer + * @param field Field + * @return Query parser + */ + private SimpleQueryParser buildQueryParser(Analyzer analyzer, String field) { + SimpleQueryParser simpleQueryParser = new SimpleQueryParser(analyzer, field); + simpleQueryParser.setDefaultOperator(BooleanClause.Occur.MUST); // AND all the terms + return simpleQueryParser; + } + /** * Build Lucene document from database document. * diff --git a/docs-web/src/test/java/com/sismics/docs/rest/TestDocumentResource.java b/docs-web/src/test/java/com/sismics/docs/rest/TestDocumentResource.java index 964e7e6d..9f0c78d0 100644 --- a/docs-web/src/test/java/com/sismics/docs/rest/TestDocumentResource.java +++ b/docs-web/src/test/java/com/sismics/docs/rest/TestDocumentResource.java @@ -184,6 +184,7 @@ public class TestDocumentResource extends BaseJerseyTest { // Search documents Assert.assertEquals(1, searchDocuments("full:uranium full:einstein", document1Token)); + Assert.assertEquals(2, searchDocuments("tit*", document1Token)); Assert.assertEquals(2, searchDocuments("full:title", document1Token)); Assert.assertEquals(2, searchDocuments("title", document1Token)); Assert.assertEquals(1, searchDocuments("super description", document1Token)); From 7a285d11a530ea52831d585323cd1769d5c48451 Mon Sep 17 00:00:00 2001 From: Benjamin Gamard Date: Thu, 24 Jan 2019 17:34:44 +0100 Subject: [PATCH 10/10] Closes #270: missing permission for android 28 --- docs-android/app/src/main/AndroidManifest.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/docs-android/app/src/main/AndroidManifest.xml b/docs-android/app/src/main/AndroidManifest.xml index 66708a1d..7cb9edaf 100644 --- a/docs-android/app/src/main/AndroidManifest.xml +++ b/docs-android/app/src/main/AndroidManifest.xml @@ -8,6 +8,7 @@ +