mirror of
https://github.com/Stirling-Tools/Stirling-PDF.git
synced 2025-06-06 18:30:57 +00:00
Merge branch 'main' into decrypt
This commit is contained in:
commit
c93a48b40d
20
.github/labeler-config.yml
vendored
Normal file
20
.github/labeler-config.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
translation:
|
||||||
|
- changed-files:
|
||||||
|
- any-glob-to-any-file: 'src/main/resources/messages_*_*.properties'
|
||||||
|
|
||||||
|
Front End:
|
||||||
|
- changed-files:
|
||||||
|
- any-glob-to-any-file: 'src/main/resources/templates/**'
|
||||||
|
|
||||||
|
java:
|
||||||
|
- changed-files:
|
||||||
|
- any-glob-to-any-file: 'src/main/java/**/*.java'
|
||||||
|
|
||||||
|
documentation:
|
||||||
|
- changed-files:
|
||||||
|
- any-glob-to-any-file: '**/*.md'
|
||||||
|
|
||||||
|
docker:
|
||||||
|
- changed-files:
|
||||||
|
- any-glob-to-any-file: 'Dockerfile'
|
||||||
|
- any-glob-to-any-file: 'Dockerfile-*'
|
18
.github/workflows/labeler.yml
vendored
Normal file
18
.github/workflows/labeler.yml
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
name: "Pull Request Labeler"
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types: [opened, synchronize]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
labeler:
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/labeler@v5
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
configuration-path: .github/labeler-config.yml
|
||||||
|
sync-labels: true
|
32
.github/workflows/stale.yml
vendored
Normal file
32
.github/workflows/stale.yml
vendored
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
name: Close stale issues
|
||||||
|
|
||||||
|
on:
|
||||||
|
schedule:
|
||||||
|
- cron: "30 0 * * *"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
stale:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
issues: write
|
||||||
|
pull-requests: write
|
||||||
|
steps:
|
||||||
|
- name: 30 days stale issues
|
||||||
|
uses: actions/stale@v9
|
||||||
|
with:
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
days-before-stale: 30
|
||||||
|
days-before-close: 7
|
||||||
|
stale-issue-message: >
|
||||||
|
This issue has been automatically marked as stale because it has had no recent activity.
|
||||||
|
It will be closed if no further activity occurs. Thank you for your contributions.
|
||||||
|
close-issue-message: >
|
||||||
|
This issue has been automatically closed because it has had no recent activity after being marked as stale.
|
||||||
|
Please reopen if you need further assistance.
|
||||||
|
stale-issue-label: "Stale"
|
||||||
|
remove-stale-when-updated: true
|
||||||
|
only-issue-labels: "more-info-needed"
|
||||||
|
days-before-pr-stale: -1 # Prevents PRs from being marked as stale
|
||||||
|
days-before-pr-close: -1 # Prevents PRs from being closed
|
||||||
|
start-date: '2024-07-06T00:00:00Z' # ISO 8601 Format
|
14
.github/workflows/sync_files.yml
vendored
14
.github/workflows/sync_files.yml
vendored
@ -7,7 +7,7 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- "build.gradle"
|
- "build.gradle"
|
||||||
- "src/main/resources/messages_*.properties"
|
- "src/main/resources/messages_*.properties"
|
||||||
- "scripts/translation_status.toml"
|
- "scripts/ignore_translation.toml"
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
@ -17,9 +17,9 @@ jobs:
|
|||||||
sync-versions:
|
sync-versions:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4.1.1
|
- uses: actions/checkout@v4
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5.1.0
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: "3.x"
|
python-version: "3.x"
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
@ -36,7 +36,7 @@ jobs:
|
|||||||
git diff --staged --quiet || git commit -m ":floppy_disk: Sync Versions
|
git diff --staged --quiet || git commit -m ":floppy_disk: Sync Versions
|
||||||
> Made via sync_files.yml" || echo "no changes"
|
> Made via sync_files.yml" || echo "no changes"
|
||||||
- name: Create Pull Request
|
- name: Create Pull Request
|
||||||
uses: peter-evans/create-pull-request@v6.0.1
|
uses: peter-evans/create-pull-request@v6
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
commit-message: Update files
|
commit-message: Update files
|
||||||
@ -54,9 +54,9 @@ jobs:
|
|||||||
sync-readme:
|
sync-readme:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4.1.1
|
- uses: actions/checkout@v4
|
||||||
- name: Set up Python
|
- name: Set up Python
|
||||||
uses: actions/setup-python@v5.1.0
|
uses: actions/setup-python@v5
|
||||||
with:
|
with:
|
||||||
python-version: "3.x"
|
python-version: "3.x"
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
@ -73,7 +73,7 @@ jobs:
|
|||||||
git diff --staged --quiet || git commit -m ":memo: Sync README
|
git diff --staged --quiet || git commit -m ":memo: Sync README
|
||||||
> Made via sync_files.yml" || echo "no changes"
|
> Made via sync_files.yml" || echo "no changes"
|
||||||
- name: Create Pull Request
|
- name: Create Pull Request
|
||||||
uses: peter-evans/create-pull-request@v6.0.1
|
uses: peter-evans/create-pull-request@v6
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
commit-message: Update files
|
commit-message: Update files
|
||||||
|
@ -6,9 +6,11 @@ repos:
|
|||||||
args:
|
args:
|
||||||
- --fix
|
- --fix
|
||||||
- --line-length=127
|
- --line-length=127
|
||||||
files: ^((.github/scripts)/.+)?[^/]+\.py$
|
files: ^((.github/scripts|scripts)/.+)?[^/]+\.py$
|
||||||
|
exclude: (split_photos.py)
|
||||||
- id: ruff-format
|
- id: ruff-format
|
||||||
files: ^((.github/scripts)/.+)?[^/]+\.py$
|
files: ^((.github/scripts|scripts)/.+)?[^/]+\.py$
|
||||||
|
exclude: (split_photos.py)
|
||||||
- repo: https://github.com/codespell-project/codespell
|
- repo: https://github.com/codespell-project/codespell
|
||||||
rev: v2.2.6
|
rev: v2.2.6
|
||||||
hooks:
|
hooks:
|
||||||
@ -33,5 +35,5 @@ repos:
|
|||||||
# args: ["--replace_with= "]
|
# args: ["--replace_with= "]
|
||||||
entry: python .github/scripts/check_tabulator.py
|
entry: python .github/scripts/check_tabulator.py
|
||||||
language: python
|
language: python
|
||||||
exclude: ^src/main/resources/static/pdfjs/
|
exclude: ^(src/main/resources/static/pdfjs|src/main/resources/static/pdfjs-legacy)
|
||||||
files: ^.*(\.html|\.css|\.js)$
|
files: ^.*(\.html|\.css|\.js)$
|
||||||
|
40
DATABASE.md
Normal file
40
DATABASE.md
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
# New Database Backup and Import Functionality
|
||||||
|
|
||||||
|
**Full activation will take place on approximately January 5th, 2025!**
|
||||||
|
|
||||||
|
Why is the waiting time six months?
|
||||||
|
|
||||||
|
There are users who only install updates sporadically; if they skip the preparation, it can/will lead to data loss in the database.
|
||||||
|
|
||||||
|
## Functionality Overview
|
||||||
|
|
||||||
|
The newly introduced feature enhances the application with robust database backup and import capabilities. This feature is designed to ensure data integrity and provide a straightforward way to manage database backups. Here's how it works:
|
||||||
|
|
||||||
|
1. Automatic Backup Creation
|
||||||
|
- The system automatically creates a database backup every day at midnight. This ensures that there is always a recent backup available, minimizing the risk of data loss.
|
||||||
|
2. Manual Backup Export
|
||||||
|
- Admin actions that modify the user database trigger a manual export of the database. This keeps the backup up-to-date with the latest changes and provides an extra layer of data security.
|
||||||
|
3. Importing Database Backups
|
||||||
|
- Admin users can import a database backup either via the web interface or API endpoints. This allows for easy restoration of the database to a previous state in case of data corruption or other issues.
|
||||||
|
- The import process ensures that the database structure and data are correctly restored, maintaining the integrity of the application.
|
||||||
|
4. Managing Backup Files
|
||||||
|
- Admins can view a list of all existing backup files, along with their creation dates and sizes. This helps in managing storage and identifying the most recent or relevant backups.
|
||||||
|
- Backup files can be downloaded for offline storage or transferred to other environments, providing flexibility in database management.
|
||||||
|
- Unnecessary backup files can be deleted through the interface to free up storage space and maintain an organized backup directory.
|
||||||
|
|
||||||
|
## User Interface
|
||||||
|
|
||||||
|
### Web Interface
|
||||||
|
|
||||||
|
1. Upload SQL files to import database backups.
|
||||||
|
2. View details of existing backups, such as file names, creation dates, and sizes.
|
||||||
|
3. Download backup files for offline storage.
|
||||||
|
4. Delete outdated or unnecessary backup files.
|
||||||
|
|
||||||
|
### API Endpoints
|
||||||
|
|
||||||
|
1. Import database backups by uploading SQL files.
|
||||||
|
2. Download backup files.
|
||||||
|
3. Delete backup files.
|
||||||
|
|
||||||
|
This new functionality streamlines database management, ensuring that backups are always available and easy to manage, thus improving the reliability and resilience of the application.
|
134
README.md
134
README.md
@ -9,6 +9,7 @@
|
|||||||
[](https://github.com/sponsors/Frooodle)
|
[](https://github.com/sponsors/Frooodle)
|
||||||
|
|
||||||
[](https://cloud.digitalocean.com/apps/new?repo=https://github.com/Stirling-Tools/Stirling-PDF/tree/digitalOcean&refcode=c3210994b1af)
|
[](https://cloud.digitalocean.com/apps/new?repo=https://github.com/Stirling-Tools/Stirling-PDF/tree/digitalOcean&refcode=c3210994b1af)
|
||||||
|
[<img src="https://www.ssdnodes.com/wp-content/uploads/2023/11/footer-logo.svg" alt="Name" height="40">](https://www.ssdnodes.com/manage/aff.php?aff=2216®ister=true)
|
||||||
|
|
||||||
This is a robust, locally hosted web-based PDF manipulation tool using Docker. It enables you to carry out various operations on PDF files, including splitting, merging, converting, reorganizing, adding images, rotating, compressing, and more. This locally hosted web application has evolved to encompass a comprehensive set of features, addressing all your PDF requirements.
|
This is a robust, locally hosted web-based PDF manipulation tool using Docker. It enables you to carry out various operations on PDF files, including splitting, merging, converting, reorganizing, adding images, rotating, compressing, and more. This locally hosted web application has evolved to encompass a comprehensive set of features, addressing all your PDF requirements.
|
||||||
|
|
||||||
@ -21,10 +22,11 @@ All files and PDFs exist either exclusively on the client side, reside in server
|
|||||||
## Features
|
## Features
|
||||||
|
|
||||||
- Dark mode support.
|
- Dark mode support.
|
||||||
- Custom download options (see [here](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/images/settings.png) for example)
|
- Custom download options
|
||||||
- Parallel file processing and downloads
|
- Parallel file processing and downloads
|
||||||
- API for integration with external scripts
|
- API for integration with external scripts
|
||||||
- Optional Login and Authentication support (see [here](https://github.com/Stirling-Tools/Stirling-PDF/tree/main#login-authentication) for documentation)
|
- Optional Login and Authentication support (see [here](https://github.com/Stirling-Tools/Stirling-PDF/tree/main#login-authentication) for documentation)
|
||||||
|
- Database Backup and Import (see [here](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DATABASE.md) for documentation)
|
||||||
|
|
||||||
## **PDF Features**
|
## **PDF Features**
|
||||||
|
|
||||||
@ -82,7 +84,8 @@ All files and PDFs exist either exclusively on the client side, reside in server
|
|||||||
- Get all information on a PDF to view or export as JSON.
|
- Get all information on a PDF to view or export as JSON.
|
||||||
|
|
||||||
For a overview of the tasks and the technology each uses please view [Endpoint-groups.md](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/Endpoint-groups.md)
|
For a overview of the tasks and the technology each uses please view [Endpoint-groups.md](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/Endpoint-groups.md)
|
||||||
Demo of the app is available [here](https://stirlingpdf.io). username: demo, password: demo
|
|
||||||
|
Demo of the app is available [here](https://stirlingpdf.io).
|
||||||
|
|
||||||
## Technologies used
|
## Technologies used
|
||||||
|
|
||||||
@ -168,36 +171,36 @@ Stirling PDF currently supports 32!
|
|||||||
| ------------------------------------------- | -------------------------------------- |
|
| ------------------------------------------- | -------------------------------------- |
|
||||||
| English (English) (en_GB) |  |
|
| English (English) (en_GB) |  |
|
||||||
| English (US) (en_US) |  |
|
| English (US) (en_US) |  |
|
||||||
| Arabic (العربية) (ar_AR) |  |
|
| Arabic (العربية) (ar_AR) |  |
|
||||||
| German (Deutsch) (de_DE) |  |
|
| German (Deutsch) (de_DE) |  |
|
||||||
| French (Français) (fr_FR) |  |
|
| French (Français) (fr_FR) |  |
|
||||||
| Spanish (Español) (es_ES) |  |
|
| Spanish (Español) (es_ES) |  |
|
||||||
| Simplified Chinese (简体中文) (zh_CN) |  |
|
| Simplified Chinese (简体中文) (zh_CN) |  |
|
||||||
| Traditional Chinese (繁體中文) (zh_TW) |  |
|
| Traditional Chinese (繁體中文) (zh_TW) |  |
|
||||||
| Catalan (Català) (ca_CA) |  |
|
| Catalan (Català) (ca_CA) |  |
|
||||||
| Italian (Italiano) (it_IT) |  |
|
| Italian (Italiano) (it_IT) |  |
|
||||||
| Swedish (Svenska) (sv_SE) |  |
|
| Swedish (Svenska) (sv_SE) |  |
|
||||||
| Polish (Polski) (pl_PL) |  |
|
| Polish (Polski) (pl_PL) |  |
|
||||||
| Romanian (Română) (ro_RO) |  |
|
| Romanian (Română) (ro_RO) |  |
|
||||||
| Korean (한국어) (ko_KR) |  |
|
| Korean (한국어) (ko_KR) |  |
|
||||||
| Portuguese Brazilian (Português) (pt_BR) |  |
|
| Portuguese Brazilian (Português) (pt_BR) |  |
|
||||||
| Portuguese (Português) (pt_PT) |  |
|
| Portuguese (Português) (pt_PT) |  |
|
||||||
| Russian (Русский) (ru_RU) |  |
|
| Russian (Русский) (ru_RU) |  |
|
||||||
| Basque (Euskara) (eu_ES) |  |
|
| Basque (Euskara) (eu_ES) |  |
|
||||||
| Japanese (日本語) (ja_JP) |  |
|
| Japanese (日本語) (ja_JP) |  |
|
||||||
| Dutch (Nederlands) (nl_NL) |  |
|
| Dutch (Nederlands) (nl_NL) |  |
|
||||||
| Greek (Ελληνικά) (el_GR) |  |
|
| Greek (Ελληνικά) (el_GR) |  |
|
||||||
| Turkish (Türkçe) (tr_TR) |  |
|
| Turkish (Türkçe) (tr_TR) |  |
|
||||||
| Indonesia (Bahasa Indonesia) (id_ID) |  |
|
| Indonesia (Bahasa Indonesia) (id_ID) |  |
|
||||||
| Hindi (हिंदी) (hi_IN) |  |
|
| Hindi (हिंदी) (hi_IN) |  |
|
||||||
| Hungarian (Magyar) (hu_HU) |  |
|
| Hungarian (Magyar) (hu_HU) |  |
|
||||||
| Bulgarian (Български) (bg_BG) |  |
|
| Bulgarian (Български) (bg_BG) |  |
|
||||||
| Sebian Latin alphabet (Srpski) (sr_LATN_RS) |  |
|
| Sebian Latin alphabet (Srpski) (sr_LATN_RS) |  |
|
||||||
| Ukrainian (Українська) (uk_UA) |  |
|
| Ukrainian (Українська) (uk_UA) |  |
|
||||||
| Slovakian (Slovensky) (sk_SK) |  |
|
| Slovakian (Slovensky) (sk_SK) |  |
|
||||||
| Czech (Česky) (cs_CZ) |  |
|
| Czech (Česky) (cs_CZ) |  |
|
||||||
| Croatian (Hrvatski) (hr_HR) |  |
|
| Croatian (Hrvatski) (hr_HR) |  |
|
||||||
| Norwegian (Norsk) (no_NB) |  |
|
| Norwegian (Norsk) (no_NB) |  |
|
||||||
|
|
||||||
## Contributing (creating issues, translations, fixing bugs, etc.)
|
## Contributing (creating issues, translations, fixing bugs, etc.)
|
||||||
|
|
||||||
@ -218,11 +221,11 @@ Environment variables are also supported and would override the settings file
|
|||||||
For example in the settings.yml you have
|
For example in the settings.yml you have
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
system:
|
security:
|
||||||
enableLogin: 'true'
|
enableLogin: 'true'
|
||||||
```
|
```
|
||||||
|
|
||||||
To have this via an environment variable you would have ``SYSTEM_ENABLELOGIN``
|
To have this via an environment variable you would have ``SECURITY_ENABLELOGIN``
|
||||||
|
|
||||||
The Current list of settings is
|
The Current list of settings is
|
||||||
|
|
||||||
@ -232,35 +235,36 @@ security:
|
|||||||
csrfDisabled: true # Set to 'true' to disable CSRF protection (not recommended for production)
|
csrfDisabled: true # Set to 'true' to disable CSRF protection (not recommended for production)
|
||||||
loginAttemptCount: 5 # lock user account after 5 tries
|
loginAttemptCount: 5 # lock user account after 5 tries
|
||||||
loginResetTimeMinutes: 120 # lock account for 2 hours after x attempts
|
loginResetTimeMinutes: 120 # lock account for 2 hours after x attempts
|
||||||
# initialLogin:
|
loginMethod: all # 'all' (Login Username/Password and OAuth2[must be enabled and configured]), 'normal'(only Login with Username/Password) or 'oauth2'(only Login with OAuth2)
|
||||||
# username: "admin" # Initial username for the first login
|
initialLogin:
|
||||||
# password: "stirling" # Initial password for the first login
|
username: '' # Initial username for the first login
|
||||||
# oauth2:
|
password: '' # Initial password for the first login
|
||||||
# enabled: false # set to 'true' to enable login (Note: enableLogin must also be 'true' for this to work)
|
oauth2:
|
||||||
# issuer: "" # set to any provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) end-point
|
enabled: false # set to 'true' to enable login (Note: enableLogin must also be 'true' for this to work)
|
||||||
# clientId: "" # Client ID from your provider
|
client:
|
||||||
# clientSecret: "" # Client Secret from your provider
|
keycloak:
|
||||||
# autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users
|
issuer: '' # URL of the Keycloak realm's OpenID Connect Discovery endpoint
|
||||||
# useAsUsername: "email" # Default is 'email'; custom fields can be used as the username
|
clientId: '' # Client ID for Keycloak OAuth2
|
||||||
# scopes: "openid, profile, email" # Specify the scopes for which the application will request permissions
|
clientSecret: '' # Client Secret for Keycloak OAuth2
|
||||||
# provider: "google" # Set this to your OAuth provider's name, e.g., 'google' or 'keycloak'
|
scopes: openid, profile, email # Scopes for Keycloak OAuth2
|
||||||
# client:
|
useAsUsername: preferred_username # Field to use as the username for Keycloak OAuth2
|
||||||
# google:
|
google:
|
||||||
# clientId: "" # Client ID for Google OAuth2
|
clientId: '' # Client ID for Google OAuth2
|
||||||
# clientSecret: "" # Client Secret for Google OAuth2
|
clientSecret: '' # Client Secret for Google OAuth2
|
||||||
# scopes: "https://www.googleapis.com/auth/userinfo.email, https://www.googleapis.com/auth/userinfo.profile" # Scopes for Google OAuth2
|
scopes: https://www.googleapis.com/auth/userinfo.email, https://www.googleapis.com/auth/userinfo.profile # Scopes for Google OAuth2
|
||||||
# useAsUsername: "email" # Field to use as the username for Google OAuth2
|
useAsUsername: email # Field to use as the username for Google OAuth2
|
||||||
# github:
|
github:
|
||||||
# clientId: "" # Client ID for GitHub OAuth2
|
clientId: '' # Client ID for GitHub OAuth2
|
||||||
# clientSecret: "" # Client Secret for GitHub OAuth2
|
clientSecret: '' # Client Secret for GitHub OAuth2
|
||||||
# scopes: "read:user" # Scope for GitHub OAuth2
|
scopes: read:user # Scope for GitHub OAuth2
|
||||||
# useAsUsername: "login" # Field to use as the username for GitHub OAuth2
|
useAsUsername: login # Field to use as the username for GitHub OAuth2
|
||||||
# keycloak:
|
issuer: '' # set to any provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) end-point
|
||||||
# issuer: "http://192.168.0.123:8888/realms/stirling-pdf" # URL of the Keycloak realm's OpenID Connect Discovery endpoint
|
clientId: '' # Client ID from your provider
|
||||||
# clientId: "stirling-pdf" # Client ID for Keycloak OAuth2
|
clientSecret: '' # Client Secret from your provider
|
||||||
# clientSecret: "" # Client Secret for Keycloak OAuth2
|
autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users
|
||||||
# scopes: "openid, profile, email" # Scopes for Keycloak OAuth2
|
useAsUsername: email # Default is 'email'; custom fields can be used as the username
|
||||||
# useAsUsername: "email" # Field to use as the username for Keycloak OAuth2
|
scopes: openid, profile, email # Specify the scopes for which the application will request permissions
|
||||||
|
provider: google # Set this to your OAuth provider's name, e.g., 'google' or 'keycloak'
|
||||||
|
|
||||||
system:
|
system:
|
||||||
defaultLocale: 'en-US' # Set the default language (e.g. 'de-DE', 'fr-FR', etc)
|
defaultLocale: 'en-US' # Set the default language (e.g. 'de-DE', 'fr-FR', etc)
|
||||||
@ -271,9 +275,9 @@ system:
|
|||||||
customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template html files
|
customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template html files
|
||||||
|
|
||||||
ui:
|
ui:
|
||||||
appName: null # Application's visible name
|
appName: '' # Application's visible name
|
||||||
homeDescription: null # Short description or tagline shown on homepage.
|
homeDescription: '' # Short description or tagline shown on homepage.
|
||||||
appNameNavbar: null # Name displayed on the navigation bar
|
appNameNavbar: '' # Name displayed on the navigation bar
|
||||||
|
|
||||||
endpoints:
|
endpoints:
|
||||||
toRemove: [] # List endpoints to disable (e.g. ['img-to-pdf', 'remove-pages'])
|
toRemove: [] # List endpoints to disable (e.g. ['img-to-pdf', 'remove-pages'])
|
||||||
@ -307,7 +311,7 @@ For those wanting to use Stirling-PDFs backend API to link with their own custom
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
### Prerequisites:
|
### Prerequisites
|
||||||
|
|
||||||
- User must have the folder ./configs volumed within docker so that it is retained during updates.
|
- User must have the folder ./configs volumed within docker so that it is retained during updates.
|
||||||
- Docker users must download the security jar version by setting ``DOCKER_ENABLE_SECURITY`` to ``true`` in environment variables.
|
- Docker users must download the security jar version by setting ``DOCKER_ENABLE_SECURITY`` to ``true`` in environment variables.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
|All versions in a Docker envrionment can download Calibre as a optional extra at runtime to support `book-to-pdf` and `pdf-to-book` using parameter ``INSTALL_BOOK_AND_ADVANCED_HTML_OPS``.
|
|All versions in a Docker environment can download Calibre as a optional extra at runtime to support `book-to-pdf` and `pdf-to-book` using parameter ``INSTALL_BOOK_AND_ADVANCED_HTML_OPS``.
|
||||||
The 'Fat' container contains all those found in 'Full' with security jar along with this Calibre install.
|
The 'Fat' container contains all those found in 'Full' with security jar along with this Calibre install.
|
||||||
|
|
||||||
Technology | Ultra-Lite | Full |
|
Technology | Ultra-Lite | Full |
|
||||||
|
@ -36,7 +36,9 @@ sourceSets {
|
|||||||
if (System.getenv("DOCKER_ENABLE_SECURITY") == "false") {
|
if (System.getenv("DOCKER_ENABLE_SECURITY") == "false") {
|
||||||
exclude "stirling/software/SPDF/config/security/**"
|
exclude "stirling/software/SPDF/config/security/**"
|
||||||
exclude "stirling/software/SPDF/controller/api/UserController.java"
|
exclude "stirling/software/SPDF/controller/api/UserController.java"
|
||||||
|
exclude "stirling/software/SPDF/controller/api/DatabaseController.java"
|
||||||
exclude "stirling/software/SPDF/controller/web/AccountWebController.java"
|
exclude "stirling/software/SPDF/controller/web/AccountWebController.java"
|
||||||
|
exclude "stirling/software/SPDF/controller/web/DatabaseWebController.java"
|
||||||
exclude "stirling/software/SPDF/model/ApiKeyAuthenticationToken.java"
|
exclude "stirling/software/SPDF/model/ApiKeyAuthenticationToken.java"
|
||||||
exclude "stirling/software/SPDF/model/Authority.java"
|
exclude "stirling/software/SPDF/model/Authority.java"
|
||||||
exclude "stirling/software/SPDF/model/PersistentLogin.java"
|
exclude "stirling/software/SPDF/model/PersistentLogin.java"
|
||||||
@ -97,7 +99,7 @@ dependencies {
|
|||||||
//security updates
|
//security updates
|
||||||
implementation "ch.qos.logback:logback-classic:1.5.6"
|
implementation "ch.qos.logback:logback-classic:1.5.6"
|
||||||
implementation "ch.qos.logback:logback-core:1.5.6"
|
implementation "ch.qos.logback:logback-core:1.5.6"
|
||||||
implementation "org.springframework:spring-webmvc:6.1.8"
|
implementation "org.springframework:spring-webmvc:6.1.9"
|
||||||
|
|
||||||
implementation("io.github.pixee:java-security-toolkit:1.1.3")
|
implementation("io.github.pixee:java-security-toolkit:1.1.3")
|
||||||
|
|
||||||
@ -120,6 +122,7 @@ dependencies {
|
|||||||
|
|
||||||
//2.2.x requires rebuild of DB file.. need migration path
|
//2.2.x requires rebuild of DB file.. need migration path
|
||||||
implementation "com.h2database:h2:2.1.214"
|
implementation "com.h2database:h2:2.1.214"
|
||||||
|
// implementation "com.h2database:h2:2.2.224"
|
||||||
}
|
}
|
||||||
|
|
||||||
testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
|
testImplementation "org.springframework.boot:spring-boot-starter-test:$springBootVersion"
|
||||||
@ -133,7 +136,7 @@ dependencies {
|
|||||||
// implementation "com.twelvemonkeys.imageio:imageio-hdr:3.10.1"
|
// implementation "com.twelvemonkeys.imageio:imageio-hdr:3.10.1"
|
||||||
// implementation "com.twelvemonkeys.imageio:imageio-icns:3.10.1"
|
// implementation "com.twelvemonkeys.imageio:imageio-icns:3.10.1"
|
||||||
// implementation "com.twelvemonkeys.imageio:imageio-iff:3.10.1"
|
// implementation "com.twelvemonkeys.imageio:imageio-iff:3.10.1"
|
||||||
implementation "com.twelvemonkeys.imageio:imageio-jpeg:3.10.1"
|
implementation "com.twelvemonkeys.imageio:imageio-jpeg:3.11.0"
|
||||||
// implementation "com.twelvemonkeys.imageio:imageio-pcx:3.10.1"
|
// implementation "com.twelvemonkeys.imageio:imageio-pcx:3.10.1"
|
||||||
// implementation "com.twelvemonkeys.imageio:imageio-pict:3.10.1"
|
// implementation "com.twelvemonkeys.imageio:imageio-pict:3.10.1"
|
||||||
// implementation "com.twelvemonkeys.imageio:imageio-pnm:3.10.1"
|
// implementation "com.twelvemonkeys.imageio:imageio-pnm:3.10.1"
|
||||||
|
@ -79,7 +79,9 @@ def write_readme(progress_list: list[tuple[str, int]]) -> None:
|
|||||||
file.writelines(content)
|
file.writelines(content)
|
||||||
|
|
||||||
|
|
||||||
def compare_files(default_file_path, file_paths, translation_status_file) -> list[tuple[str, int]]:
|
def compare_files(
|
||||||
|
default_file_path, file_paths, ignore_translation_file
|
||||||
|
) -> list[tuple[str, int]]:
|
||||||
"""Compares the default properties file with other
|
"""Compares the default properties file with other
|
||||||
properties files in the directory.
|
properties files in the directory.
|
||||||
|
|
||||||
@ -92,18 +94,24 @@ def compare_files(default_file_path, file_paths, translation_status_file) -> lis
|
|||||||
language and progress percentage.
|
language and progress percentage.
|
||||||
""" # noqa: D205
|
""" # noqa: D205
|
||||||
num_lines = sum(
|
num_lines = sum(
|
||||||
1 for line in open(default_file_path, encoding="utf-8") if line.strip() and not line.strip().startswith("#")
|
1
|
||||||
|
for line in open(default_file_path, encoding="utf-8")
|
||||||
|
if line.strip() and not line.strip().startswith("#")
|
||||||
)
|
)
|
||||||
|
|
||||||
result_list = []
|
result_list = []
|
||||||
sort_translation_status: tomlkit.TOMLDocument
|
sort_ignore_translation: tomlkit.TOMLDocument
|
||||||
|
|
||||||
# read toml
|
# read toml
|
||||||
with open(translation_status_file, encoding="utf-8") as f:
|
with open(ignore_translation_file, encoding="utf-8") as f:
|
||||||
sort_translation_status = tomlkit.parse(f.read())
|
sort_ignore_translation = tomlkit.parse(f.read())
|
||||||
|
|
||||||
for file_path in file_paths:
|
for file_path in file_paths:
|
||||||
language = os.path.basename(file_path).split("messages_", 1)[1].split(".properties", 1)[0]
|
language = (
|
||||||
|
os.path.basename(file_path)
|
||||||
|
.split("messages_", 1)[1]
|
||||||
|
.split(".properties", 1)[0]
|
||||||
|
)
|
||||||
|
|
||||||
fails = 0
|
fails = 0
|
||||||
if "en_GB" in language or "en_US" in language:
|
if "en_GB" in language or "en_US" in language:
|
||||||
@ -111,21 +119,25 @@ def compare_files(default_file_path, file_paths, translation_status_file) -> lis
|
|||||||
result_list.append(("en_US", 100))
|
result_list.append(("en_US", 100))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if language not in sort_translation_status:
|
if language not in sort_ignore_translation:
|
||||||
sort_translation_status[language] = tomlkit.table()
|
sort_ignore_translation[language] = tomlkit.table()
|
||||||
|
|
||||||
if (
|
if (
|
||||||
"ignore" not in sort_translation_status[language]
|
"ignore" not in sort_ignore_translation[language]
|
||||||
or len(sort_translation_status[language].get("ignore", [])) < 1
|
or len(sort_ignore_translation[language].get("ignore", [])) < 1
|
||||||
):
|
):
|
||||||
sort_translation_status[language]["ignore"] = tomlkit.array(["language.direction"])
|
sort_ignore_translation[language]["ignore"] = tomlkit.array(
|
||||||
|
["language.direction"]
|
||||||
|
)
|
||||||
|
|
||||||
# if "missing" not in sort_translation_status[language]:
|
# if "missing" not in sort_ignore_translation[language]:
|
||||||
# sort_translation_status[language]["missing"] = tomlkit.array()
|
# sort_ignore_translation[language]["missing"] = tomlkit.array()
|
||||||
# elif "language.direction" in sort_translation_status[language]["missing"]:
|
# elif "language.direction" in sort_ignore_translation[language]["missing"]:
|
||||||
# sort_translation_status[language]["missing"].remove("language.direction")
|
# sort_ignore_translation[language]["missing"].remove("language.direction")
|
||||||
|
|
||||||
with open(default_file_path, encoding="utf-8") as default_file, open(file_path, encoding="utf-8") as file:
|
with open(default_file_path, encoding="utf-8") as default_file, open(
|
||||||
|
file_path, encoding="utf-8"
|
||||||
|
) as file:
|
||||||
for _ in range(5):
|
for _ in range(5):
|
||||||
next(default_file)
|
next(default_file)
|
||||||
try:
|
try:
|
||||||
@ -133,34 +145,45 @@ def compare_files(default_file_path, file_paths, translation_status_file) -> lis
|
|||||||
except StopIteration:
|
except StopIteration:
|
||||||
fails = num_lines
|
fails = num_lines
|
||||||
|
|
||||||
for line_num, (line_default, line_file) in enumerate(zip(default_file, file), start=6):
|
for line_num, (line_default, line_file) in enumerate(
|
||||||
|
zip(default_file, file), start=6
|
||||||
|
):
|
||||||
try:
|
try:
|
||||||
# Ignoring empty lines and lines start with #
|
# Ignoring empty lines and lines start with #
|
||||||
if line_default.strip() == "" or line_default.startswith("#"):
|
if line_default.strip() == "" or line_default.startswith("#"):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
default_key, default_value = line_default.split("=", 1)
|
default_key, default_value = line_default.split("=", 1)
|
||||||
file_key, file_value = line_file.split("=", 1)
|
file_key, file_value = line_file.split("=", 1)
|
||||||
if (
|
if (
|
||||||
default_value.strip() == file_value.strip()
|
default_value.strip() == file_value.strip()
|
||||||
and default_key.strip() not in sort_translation_status[language]["ignore"]
|
and default_key.strip()
|
||||||
|
not in sort_ignore_translation[language]["ignore"]
|
||||||
):
|
):
|
||||||
print(f"{language}: Line {line_num} is missing the translation.")
|
print(
|
||||||
# if default_key.strip() not in sort_translation_status[language]["missing"]:
|
f"{language}: Line {line_num} is missing the translation."
|
||||||
|
)
|
||||||
|
# if default_key.strip() not in sort_ignore_translation[language]["missing"]:
|
||||||
# missing_array = tomlkit.array()
|
# missing_array = tomlkit.array()
|
||||||
# missing_array.append(default_key.strip())
|
# missing_array.append(default_key.strip())
|
||||||
# missing_array.multiline(True)
|
# missing_array.multiline(True)
|
||||||
# sort_translation_status[language]["missing"].extend(missing_array)
|
# sort_ignore_translation[language]["missing"].extend(missing_array)
|
||||||
fails += 1
|
fails += 1
|
||||||
# elif default_key.strip() in sort_translation_status[language]["ignore"]:
|
# elif default_key.strip() in sort_ignore_translation[language]["ignore"]:
|
||||||
# if default_key.strip() in sort_translation_status[language]["missing"]:
|
# if default_key.strip() in sort_ignore_translation[language]["missing"]:
|
||||||
# sort_translation_status[language]["missing"].remove(default_key.strip())
|
# sort_ignore_translation[language]["missing"].remove(default_key.strip())
|
||||||
if default_value.strip() != file_value.strip():
|
if default_value.strip() != file_value.strip():
|
||||||
# if default_key.strip() in sort_translation_status[language]["missing"]:
|
# if default_key.strip() in sort_ignore_translation[language]["missing"]:
|
||||||
# sort_translation_status[language]["missing"].remove(default_key.strip())
|
# sort_ignore_translation[language]["missing"].remove(default_key.strip())
|
||||||
if default_key.strip() in sort_translation_status[language]["ignore"]:
|
if (
|
||||||
sort_translation_status[language]["ignore"].remove(default_key.strip())
|
default_key.strip()
|
||||||
|
in sort_ignore_translation[language]["ignore"]
|
||||||
|
):
|
||||||
|
sort_ignore_translation[language]["ignore"].remove(
|
||||||
|
default_key.strip()
|
||||||
|
)
|
||||||
|
except ValueError:
|
||||||
|
print(f"{line_default}|{line_file}")
|
||||||
|
exit(1)
|
||||||
except IndexError:
|
except IndexError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -171,9 +194,9 @@ def compare_files(default_file_path, file_paths, translation_status_file) -> lis
|
|||||||
int((num_lines - fails) * 100 / num_lines),
|
int((num_lines - fails) * 100 / num_lines),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
translation_status = convert_to_multiline(sort_translation_status)
|
ignore_translation = convert_to_multiline(sort_ignore_translation)
|
||||||
with open(translation_status_file, "w", encoding="utf-8") as file:
|
with open(ignore_translation_file, "w", encoding="utf-8") as file:
|
||||||
file.write(tomlkit.dumps(translation_status))
|
file.write(tomlkit.dumps(ignore_translation))
|
||||||
|
|
||||||
unique_data = list(set(result_list))
|
unique_data = list(set(result_list))
|
||||||
unique_data.sort(key=lambda x: x[1], reverse=True)
|
unique_data.sort(key=lambda x: x[1], reverse=True)
|
||||||
@ -187,6 +210,8 @@ if __name__ == "__main__":
|
|||||||
reference_file = os.path.join(directory, "messages_en_GB.properties")
|
reference_file = os.path.join(directory, "messages_en_GB.properties")
|
||||||
|
|
||||||
scripts_directory = os.path.join(os.getcwd(), "scripts")
|
scripts_directory = os.path.join(os.getcwd(), "scripts")
|
||||||
translation_state_file = os.path.join(scripts_directory, "translation_status.toml")
|
translation_state_file = os.path.join(scripts_directory, "ignore_translation.toml")
|
||||||
|
|
||||||
write_readme(compare_files(reference_file, messages_file_paths, translation_state_file))
|
write_readme(
|
||||||
|
compare_files(reference_file, messages_file_paths, translation_state_file)
|
||||||
|
)
|
||||||
|
@ -10,7 +10,11 @@ ignore = [
|
|||||||
|
|
||||||
[ca_CA]
|
[ca_CA]
|
||||||
ignore = [
|
ignore = [
|
||||||
|
'PDFToText.tags',
|
||||||
|
'adminUserSettings.admin',
|
||||||
'language.direction',
|
'language.direction',
|
||||||
|
'survey.button',
|
||||||
|
'watermark.type.1',
|
||||||
]
|
]
|
||||||
|
|
||||||
[cs_CZ]
|
[cs_CZ]
|
||||||
@ -48,6 +52,7 @@ ignore = [
|
|||||||
ignore = [
|
ignore = [
|
||||||
'adminUserSettings.roles',
|
'adminUserSettings.roles',
|
||||||
'color',
|
'color',
|
||||||
|
'error',
|
||||||
'language.direction',
|
'language.direction',
|
||||||
'no',
|
'no',
|
||||||
'showJS.tags',
|
'showJS.tags',
|
||||||
@ -60,8 +65,26 @@ ignore = [
|
|||||||
|
|
||||||
[fr_FR]
|
[fr_FR]
|
||||||
ignore = [
|
ignore = [
|
||||||
|
'AddStampRequest.alphabet',
|
||||||
|
'AddStampRequest.position',
|
||||||
|
'AddStampRequest.rotation',
|
||||||
|
'PDFToBook.selectText.1',
|
||||||
|
'addPageNumbers.selectText.3',
|
||||||
|
'adminUserSettings.actions',
|
||||||
|
'alphabet',
|
||||||
|
'compare.document.1',
|
||||||
|
'compare.document.2',
|
||||||
|
'info',
|
||||||
'language.direction',
|
'language.direction',
|
||||||
|
'licenses.license',
|
||||||
|
'licenses.module',
|
||||||
|
'licenses.nav',
|
||||||
|
'licenses.version',
|
||||||
|
'pdfOrganiser.mode',
|
||||||
|
'pipeline.title',
|
||||||
|
'pipelineOptions.pipelineHeader',
|
||||||
'sponsor',
|
'sponsor',
|
||||||
|
'watermark.type.2',
|
||||||
]
|
]
|
||||||
|
|
||||||
[hi_IN]
|
[hi_IN]
|
||||||
@ -71,6 +94,7 @@ ignore = [
|
|||||||
|
|
||||||
[hr_HR]
|
[hr_HR]
|
||||||
ignore = [
|
ignore = [
|
||||||
|
'PDFToBook.selectText.1',
|
||||||
'font',
|
'font',
|
||||||
'home.pipeline.title',
|
'home.pipeline.title',
|
||||||
'info',
|
'info',
|
||||||
@ -114,16 +138,34 @@ ignore = [
|
|||||||
|
|
||||||
[nl_NL]
|
[nl_NL]
|
||||||
ignore = [
|
ignore = [
|
||||||
|
'HTMLToPDF.print',
|
||||||
|
'adjustContrast.contrast',
|
||||||
|
'compare.document.1',
|
||||||
|
'compare.document.2',
|
||||||
|
'error',
|
||||||
|
'getPdfInfo.downloadJson',
|
||||||
|
'help',
|
||||||
|
'info',
|
||||||
'language.direction',
|
'language.direction',
|
||||||
|
'navbar.allTools',
|
||||||
|
'printFile.submit',
|
||||||
|
'showJS.downloadJS',
|
||||||
|
'sponsor',
|
||||||
]
|
]
|
||||||
|
|
||||||
[no_NB]
|
[no_NB]
|
||||||
ignore = [
|
ignore = [
|
||||||
|
'PDFToBook.selectText.1',
|
||||||
|
'adminUserSettings.admin',
|
||||||
|
'info',
|
||||||
'language.direction',
|
'language.direction',
|
||||||
|
'oops',
|
||||||
|
'sponsor',
|
||||||
]
|
]
|
||||||
|
|
||||||
[pl_PL]
|
[pl_PL]
|
||||||
ignore = [
|
ignore = [
|
||||||
|
'PDFToBook.selectText.1',
|
||||||
'language.direction',
|
'language.direction',
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -149,12 +191,20 @@ ignore = [
|
|||||||
|
|
||||||
[sk_SK]
|
[sk_SK]
|
||||||
ignore = [
|
ignore = [
|
||||||
|
'adminUserSettings.admin',
|
||||||
|
'home.multiTool.title',
|
||||||
|
'info',
|
||||||
'language.direction',
|
'language.direction',
|
||||||
|
'navbar.sections.security',
|
||||||
|
'text',
|
||||||
|
'watermark.type.1',
|
||||||
]
|
]
|
||||||
|
|
||||||
[sr_LATN_RS]
|
[sr_LATN_RS]
|
||||||
ignore = [
|
ignore = [
|
||||||
'language.direction',
|
'language.direction',
|
||||||
|
'licenses.version',
|
||||||
|
'poweredBy',
|
||||||
]
|
]
|
||||||
|
|
||||||
[sv_SE]
|
[sv_SE]
|
@ -22,7 +22,8 @@ public class CleanUrlInterceptor implements HandlerInterceptor {
|
|||||||
"error",
|
"error",
|
||||||
"erroroauth",
|
"erroroauth",
|
||||||
"file",
|
"file",
|
||||||
"messageType");
|
"messageType",
|
||||||
|
"infoMessage");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean preHandle(
|
public boolean preHandle(
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
package stirling.software.SPDF.config;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import stirling.software.SPDF.utils.FileInfo;
|
||||||
|
|
||||||
|
public interface DatabaseBackupInterface {
|
||||||
|
void exportDatabase() throws IOException;
|
||||||
|
|
||||||
|
boolean importDatabase();
|
||||||
|
|
||||||
|
boolean hasBackup();
|
||||||
|
|
||||||
|
List<FileInfo> getBackupList();
|
||||||
|
}
|
@ -6,28 +6,33 @@ import java.nio.file.Paths;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.simpleyaml.configuration.file.YamlFile;
|
import org.simpleyaml.configuration.file.YamlFile;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import jakarta.annotation.PostConstruct;
|
import jakarta.annotation.PostConstruct;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import stirling.software.SPDF.config.DatabaseBackupInterface;
|
||||||
import stirling.software.SPDF.model.ApplicationProperties;
|
import stirling.software.SPDF.model.ApplicationProperties;
|
||||||
import stirling.software.SPDF.model.Role;
|
import stirling.software.SPDF.model.Role;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
|
@Slf4j
|
||||||
public class InitialSecuritySetup {
|
public class InitialSecuritySetup {
|
||||||
|
|
||||||
@Autowired private UserService userService;
|
@Autowired private UserService userService;
|
||||||
|
|
||||||
@Autowired private ApplicationProperties applicationProperties;
|
@Autowired private ApplicationProperties applicationProperties;
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(InitialSecuritySetup.class);
|
@Autowired private DatabaseBackupInterface databaseBackupHelper;
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public void init() {
|
public void init() throws IllegalArgumentException, IOException {
|
||||||
if (!userService.hasUsers()) {
|
if (databaseBackupHelper.hasBackup() && !userService.hasUsers()) {
|
||||||
|
databaseBackupHelper.importDatabase();
|
||||||
|
} else if (!userService.hasUsers()) {
|
||||||
initializeAdminUser();
|
initializeAdminUser();
|
||||||
|
} else {
|
||||||
|
databaseBackupHelper.exportDatabase();
|
||||||
}
|
}
|
||||||
initializeInternalApiUser();
|
initializeInternalApiUser();
|
||||||
}
|
}
|
||||||
@ -41,12 +46,11 @@ public class InitialSecuritySetup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeAdminUser() {
|
private void initializeAdminUser() throws IOException {
|
||||||
String initialUsername =
|
String initialUsername =
|
||||||
applicationProperties.getSecurity().getInitialLogin().getUsername();
|
applicationProperties.getSecurity().getInitialLogin().getUsername();
|
||||||
String initialPassword =
|
String initialPassword =
|
||||||
applicationProperties.getSecurity().getInitialLogin().getPassword();
|
applicationProperties.getSecurity().getInitialLogin().getPassword();
|
||||||
|
|
||||||
if (initialUsername != null
|
if (initialUsername != null
|
||||||
&& !initialUsername.isEmpty()
|
&& !initialUsername.isEmpty()
|
||||||
&& initialPassword != null
|
&& initialPassword != null
|
||||||
@ -54,9 +58,9 @@ public class InitialSecuritySetup {
|
|||||||
&& !userService.findByUsernameIgnoreCase(initialUsername).isPresent()) {
|
&& !userService.findByUsernameIgnoreCase(initialUsername).isPresent()) {
|
||||||
try {
|
try {
|
||||||
userService.saveUser(initialUsername, initialPassword, Role.ADMIN.getRoleId());
|
userService.saveUser(initialUsername, initialPassword, Role.ADMIN.getRoleId());
|
||||||
logger.info("Admin user created: " + initialUsername);
|
log.info("Admin user created: " + initialUsername);
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
logger.error("Failed to initialize security setup", e);
|
log.error("Failed to initialize security setup", e);
|
||||||
System.exit(1);
|
System.exit(1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -64,23 +68,23 @@ public class InitialSecuritySetup {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createDefaultAdminUser() {
|
private void createDefaultAdminUser() throws IllegalArgumentException, IOException {
|
||||||
String defaultUsername = "admin";
|
String defaultUsername = "admin";
|
||||||
String defaultPassword = "stirling";
|
String defaultPassword = "stirling";
|
||||||
if (!userService.findByUsernameIgnoreCase(defaultUsername).isPresent()) {
|
if (!userService.findByUsernameIgnoreCase(defaultUsername).isPresent()) {
|
||||||
userService.saveUser(defaultUsername, defaultPassword, Role.ADMIN.getRoleId(), true);
|
userService.saveUser(defaultUsername, defaultPassword, Role.ADMIN.getRoleId(), true);
|
||||||
logger.info("Default admin user created: " + defaultUsername);
|
log.info("Default admin user created: " + defaultUsername);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeInternalApiUser() {
|
private void initializeInternalApiUser() throws IllegalArgumentException, IOException {
|
||||||
if (!userService.usernameExistsIgnoreCase(Role.INTERNAL_API_USER.getRoleId())) {
|
if (!userService.usernameExistsIgnoreCase(Role.INTERNAL_API_USER.getRoleId())) {
|
||||||
userService.saveUser(
|
userService.saveUser(
|
||||||
Role.INTERNAL_API_USER.getRoleId(),
|
Role.INTERNAL_API_USER.getRoleId(),
|
||||||
UUID.randomUUID().toString(),
|
UUID.randomUUID().toString(),
|
||||||
Role.INTERNAL_API_USER.getRoleId());
|
Role.INTERNAL_API_USER.getRoleId());
|
||||||
userService.addApiKeyToUser(Role.INTERNAL_API_USER.getRoleId());
|
userService.addApiKeyToUser(Role.INTERNAL_API_USER.getRoleId());
|
||||||
logger.info("Internal API user created: " + Role.INTERNAL_API_USER.getRoleId());
|
log.info("Internal API user created: " + Role.INTERNAL_API_USER.getRoleId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package stirling.software.SPDF.config.security;
|
package stirling.software.SPDF.config.security;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -19,6 +20,7 @@ import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
|||||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import stirling.software.SPDF.config.DatabaseBackupInterface;
|
||||||
import stirling.software.SPDF.controller.api.pipeline.UserServiceInterface;
|
import stirling.software.SPDF.controller.api.pipeline.UserServiceInterface;
|
||||||
import stirling.software.SPDF.model.AuthenticationType;
|
import stirling.software.SPDF.model.AuthenticationType;
|
||||||
import stirling.software.SPDF.model.Authority;
|
import stirling.software.SPDF.model.Authority;
|
||||||
@ -38,8 +40,11 @@ public class UserService implements UserServiceInterface {
|
|||||||
|
|
||||||
@Autowired private MessageSource messageSource;
|
@Autowired private MessageSource messageSource;
|
||||||
|
|
||||||
|
@Autowired DatabaseBackupInterface databaseBackupHelper;
|
||||||
|
|
||||||
// Handle OAUTH2 login and user auto creation.
|
// Handle OAUTH2 login and user auto creation.
|
||||||
public boolean processOAuth2PostLogin(String username, boolean autoCreateUser) {
|
public boolean processOAuth2PostLogin(String username, boolean autoCreateUser)
|
||||||
|
throws IllegalArgumentException, IOException {
|
||||||
if (!isUsernameValid(username)) {
|
if (!isUsernameValid(username)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -131,7 +136,7 @@ public class UserService implements UserServiceInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void saveUser(String username, AuthenticationType authenticationType)
|
public void saveUser(String username, AuthenticationType authenticationType)
|
||||||
throws IllegalArgumentException {
|
throws IllegalArgumentException, IOException {
|
||||||
if (!isUsernameValid(username)) {
|
if (!isUsernameValid(username)) {
|
||||||
throw new IllegalArgumentException(getInvalidUsernameMessage());
|
throw new IllegalArgumentException(getInvalidUsernameMessage());
|
||||||
}
|
}
|
||||||
@ -142,9 +147,11 @@ public class UserService implements UserServiceInterface {
|
|||||||
user.addAuthority(new Authority(Role.USER.getRoleId(), user));
|
user.addAuthority(new Authority(Role.USER.getRoleId(), user));
|
||||||
user.setAuthenticationType(authenticationType);
|
user.setAuthenticationType(authenticationType);
|
||||||
userRepository.save(user);
|
userRepository.save(user);
|
||||||
|
databaseBackupHelper.exportDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveUser(String username, String password) throws IllegalArgumentException {
|
public void saveUser(String username, String password)
|
||||||
|
throws IllegalArgumentException, IOException {
|
||||||
if (!isUsernameValid(username)) {
|
if (!isUsernameValid(username)) {
|
||||||
throw new IllegalArgumentException(getInvalidUsernameMessage());
|
throw new IllegalArgumentException(getInvalidUsernameMessage());
|
||||||
}
|
}
|
||||||
@ -154,10 +161,11 @@ public class UserService implements UserServiceInterface {
|
|||||||
user.setEnabled(true);
|
user.setEnabled(true);
|
||||||
user.setAuthenticationType(AuthenticationType.WEB);
|
user.setAuthenticationType(AuthenticationType.WEB);
|
||||||
userRepository.save(user);
|
userRepository.save(user);
|
||||||
|
databaseBackupHelper.exportDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveUser(String username, String password, String role, boolean firstLogin)
|
public void saveUser(String username, String password, String role, boolean firstLogin)
|
||||||
throws IllegalArgumentException {
|
throws IllegalArgumentException, IOException {
|
||||||
if (!isUsernameValid(username)) {
|
if (!isUsernameValid(username)) {
|
||||||
throw new IllegalArgumentException(getInvalidUsernameMessage());
|
throw new IllegalArgumentException(getInvalidUsernameMessage());
|
||||||
}
|
}
|
||||||
@ -169,10 +177,11 @@ public class UserService implements UserServiceInterface {
|
|||||||
user.setAuthenticationType(AuthenticationType.WEB);
|
user.setAuthenticationType(AuthenticationType.WEB);
|
||||||
user.setFirstLogin(firstLogin);
|
user.setFirstLogin(firstLogin);
|
||||||
userRepository.save(user);
|
userRepository.save(user);
|
||||||
|
databaseBackupHelper.exportDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveUser(String username, String password, String role)
|
public void saveUser(String username, String password, String role)
|
||||||
throws IllegalArgumentException {
|
throws IllegalArgumentException, IOException {
|
||||||
saveUser(username, password, role, false);
|
saveUser(username, password, role, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,7 +215,8 @@ public class UserService implements UserServiceInterface {
|
|||||||
return userCount > 0;
|
return userCount > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateUserSettings(String username, Map<String, String> updates) {
|
public void updateUserSettings(String username, Map<String, String> updates)
|
||||||
|
throws IOException {
|
||||||
Optional<User> userOpt = userRepository.findByUsernameIgnoreCase(username);
|
Optional<User> userOpt = userRepository.findByUsernameIgnoreCase(username);
|
||||||
if (userOpt.isPresent()) {
|
if (userOpt.isPresent()) {
|
||||||
User user = userOpt.get();
|
User user = userOpt.get();
|
||||||
@ -220,6 +230,7 @@ public class UserService implements UserServiceInterface {
|
|||||||
user.setSettings(settingsMap);
|
user.setSettings(settingsMap);
|
||||||
|
|
||||||
userRepository.save(user);
|
userRepository.save(user);
|
||||||
|
databaseBackupHelper.exportDatabase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -235,22 +246,26 @@ public class UserService implements UserServiceInterface {
|
|||||||
return authorityRepository.findByUserId(user.getId());
|
return authorityRepository.findByUserId(user.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void changeUsername(User user, String newUsername) throws IllegalArgumentException {
|
public void changeUsername(User user, String newUsername)
|
||||||
|
throws IllegalArgumentException, IOException {
|
||||||
if (!isUsernameValid(newUsername)) {
|
if (!isUsernameValid(newUsername)) {
|
||||||
throw new IllegalArgumentException(getInvalidUsernameMessage());
|
throw new IllegalArgumentException(getInvalidUsernameMessage());
|
||||||
}
|
}
|
||||||
user.setUsername(newUsername);
|
user.setUsername(newUsername);
|
||||||
userRepository.save(user);
|
userRepository.save(user);
|
||||||
|
databaseBackupHelper.exportDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void changePassword(User user, String newPassword) {
|
public void changePassword(User user, String newPassword) throws IOException {
|
||||||
user.setPassword(passwordEncoder.encode(newPassword));
|
user.setPassword(passwordEncoder.encode(newPassword));
|
||||||
userRepository.save(user);
|
userRepository.save(user);
|
||||||
|
databaseBackupHelper.exportDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void changeFirstUse(User user, boolean firstUse) {
|
public void changeFirstUse(User user, boolean firstUse) throws IOException {
|
||||||
user.setFirstLogin(firstUse);
|
user.setFirstLogin(firstUse);
|
||||||
userRepository.save(user);
|
userRepository.save(user);
|
||||||
|
databaseBackupHelper.exportDatabase();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void changeRole(User user, String newRole) {
|
public void changeRole(User user, String newRole) {
|
||||||
|
@ -0,0 +1,202 @@
|
|||||||
|
package stirling.software.SPDF.config.security.database;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.DirectoryStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.DriverManager;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.ZoneId;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import stirling.software.SPDF.config.DatabaseBackupInterface;
|
||||||
|
import stirling.software.SPDF.utils.FileInfo;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Configuration
|
||||||
|
public class DatabaseBackupHelper implements DatabaseBackupInterface {
|
||||||
|
|
||||||
|
@Value("${spring.datasource.url}")
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
private Path backupPath = Paths.get("configs/db/backup/");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasBackup() {
|
||||||
|
// Check if there is at least one backup
|
||||||
|
return !getBackupList().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<FileInfo> getBackupList() {
|
||||||
|
// Check if the backup directory exists, and create it if it does not
|
||||||
|
ensureBackupDirectoryExists();
|
||||||
|
|
||||||
|
List<FileInfo> backupFiles = new ArrayList<>();
|
||||||
|
|
||||||
|
// Read the backup directory and filter for files with the prefix "backup_" and suffix
|
||||||
|
// ".sql"
|
||||||
|
try (DirectoryStream<Path> stream =
|
||||||
|
Files.newDirectoryStream(
|
||||||
|
backupPath,
|
||||||
|
path ->
|
||||||
|
path.getFileName().toString().startsWith("backup_")
|
||||||
|
&& path.getFileName().toString().endsWith(".sql"))) {
|
||||||
|
for (Path entry : stream) {
|
||||||
|
BasicFileAttributes attrs = Files.readAttributes(entry, BasicFileAttributes.class);
|
||||||
|
LocalDateTime modificationDate =
|
||||||
|
LocalDateTime.ofInstant(
|
||||||
|
attrs.lastModifiedTime().toInstant(), ZoneId.systemDefault());
|
||||||
|
LocalDateTime creationDate =
|
||||||
|
LocalDateTime.ofInstant(
|
||||||
|
attrs.creationTime().toInstant(), ZoneId.systemDefault());
|
||||||
|
long fileSize = attrs.size();
|
||||||
|
backupFiles.add(
|
||||||
|
new FileInfo(
|
||||||
|
entry.getFileName().toString(),
|
||||||
|
entry.toString(),
|
||||||
|
modificationDate,
|
||||||
|
fileSize,
|
||||||
|
creationDate));
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Error reading backup directory: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return backupFiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Imports a database backup from the specified file.
|
||||||
|
public boolean importDatabaseFromUI(String fileName) throws IOException {
|
||||||
|
return this.importDatabaseFromUI(getBackupFilePath(fileName));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Imports a database backup from the specified path.
|
||||||
|
public boolean importDatabaseFromUI(Path tempTemplatePath) throws IOException {
|
||||||
|
boolean success = executeDatabaseScript(tempTemplatePath);
|
||||||
|
if (success) {
|
||||||
|
LocalDateTime dateNow = LocalDateTime.now();
|
||||||
|
DateTimeFormatter myFormatObj = DateTimeFormatter.ofPattern("yyyyMMddHHmm");
|
||||||
|
Path insertOutputFilePath =
|
||||||
|
this.getBackupFilePath("backup_user_" + dateNow.format(myFormatObj) + ".sql");
|
||||||
|
Files.copy(tempTemplatePath, insertOutputFilePath);
|
||||||
|
Files.deleteIfExists(tempTemplatePath);
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean importDatabase() {
|
||||||
|
if (!this.hasBackup()) return false;
|
||||||
|
|
||||||
|
List<FileInfo> backupList = this.getBackupList();
|
||||||
|
backupList.sort(Comparator.comparing(FileInfo::getModificationDate).reversed());
|
||||||
|
|
||||||
|
return executeDatabaseScript(Paths.get(backupList.get(0).getFilePath()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exportDatabase() throws IOException {
|
||||||
|
// Check if the backup directory exists, and create it if it does not
|
||||||
|
ensureBackupDirectoryExists();
|
||||||
|
|
||||||
|
// Filter and delete old backups if there are more than 5
|
||||||
|
List<FileInfo> filteredBackupList =
|
||||||
|
this.getBackupList().stream()
|
||||||
|
.filter(backup -> !backup.getFileName().startsWith("backup_user_"))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (filteredBackupList.size() > 5) {
|
||||||
|
filteredBackupList.sort(
|
||||||
|
Comparator.comparing(
|
||||||
|
p -> p.getFileName().substring(7, p.getFileName().length() - 4)));
|
||||||
|
Files.deleteIfExists(Paths.get(filteredBackupList.get(0).getFilePath()));
|
||||||
|
log.info("Deleted oldest backup: {}", filteredBackupList.get(0).getFileName());
|
||||||
|
}
|
||||||
|
|
||||||
|
LocalDateTime dateNow = LocalDateTime.now();
|
||||||
|
DateTimeFormatter myFormatObj = DateTimeFormatter.ofPattern("yyyyMMddHHmm");
|
||||||
|
Path insertOutputFilePath =
|
||||||
|
this.getBackupFilePath("backup_" + dateNow.format(myFormatObj) + ".sql");
|
||||||
|
String query = "SCRIPT SIMPLE COLUMNS DROP to '" + insertOutputFilePath.toString() + "';";
|
||||||
|
|
||||||
|
try (Connection conn = DriverManager.getConnection(url, "sa", "");
|
||||||
|
Statement stmt = conn.createStatement()) {
|
||||||
|
stmt.execute(query);
|
||||||
|
log.info("Database export completed: {}", insertOutputFilePath);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error("Error during database export: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieves the H2 database version.
|
||||||
|
public String getH2Version() {
|
||||||
|
String version = "Unknown";
|
||||||
|
try (Connection conn = DriverManager.getConnection(url, "sa", "")) {
|
||||||
|
try (Statement stmt = conn.createStatement();
|
||||||
|
ResultSet rs = stmt.executeQuery("SELECT H2VERSION() AS version")) {
|
||||||
|
if (rs.next()) {
|
||||||
|
version = rs.getString("version");
|
||||||
|
log.info("H2 Database Version: {}", version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error("Error retrieving H2 version: {}", e.getMessage(), e);
|
||||||
|
}
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deletes a backup file.
|
||||||
|
public boolean deleteBackupFile(String fileName) throws IOException {
|
||||||
|
Path filePath = this.getBackupFilePath(fileName);
|
||||||
|
if (Files.deleteIfExists(filePath)) {
|
||||||
|
log.info("Deleted backup file: {}", fileName);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
log.error("File not found or could not be deleted: {}", fileName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the Path object for a given backup file name.
|
||||||
|
public Path getBackupFilePath(String fileName) {
|
||||||
|
return Paths.get(backupPath.toString(), fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean executeDatabaseScript(Path scriptPath) {
|
||||||
|
try (Connection conn = DriverManager.getConnection(url, "sa", "");
|
||||||
|
Statement stmt = conn.createStatement()) {
|
||||||
|
|
||||||
|
String query = "RUNSCRIPT from '" + scriptPath.toString() + "';";
|
||||||
|
stmt.execute(query);
|
||||||
|
log.info("Database import completed: {}", scriptPath);
|
||||||
|
return true;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
log.error("Error during database import: {}", e.getMessage(), e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ensureBackupDirectoryExists() {
|
||||||
|
if (Files.notExists(backupPath)) {
|
||||||
|
try {
|
||||||
|
Files.createDirectories(backupPath);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Error creating directories: {}", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package stirling.software.SPDF.config.security.database;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class ScheduledTasks {
|
||||||
|
|
||||||
|
@Autowired private DatabaseBackupHelper databaseBackupService;
|
||||||
|
|
||||||
|
@Scheduled(cron = "0 0 0 * * ?")
|
||||||
|
public void performBackup() throws IOException {
|
||||||
|
databaseBackupService.exportDatabase();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,144 @@
|
|||||||
|
package stirling.software.SPDF.controller.api;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.http.HttpStatus;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.core.io.InputStreamResource;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Hidden;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import stirling.software.SPDF.config.security.database.DatabaseBackupHelper;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@Controller
|
||||||
|
@RequestMapping("/api/v1/database")
|
||||||
|
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||||
|
@Tag(name = "Database", description = "Database APIs")
|
||||||
|
public class DatabaseController {
|
||||||
|
|
||||||
|
@Autowired DatabaseBackupHelper databaseBackupHelper;
|
||||||
|
|
||||||
|
@Hidden
|
||||||
|
@PostMapping(consumes = "multipart/form-data", value = "import-database")
|
||||||
|
@Operation(
|
||||||
|
summary = "Import database backup",
|
||||||
|
description = "This endpoint imports a database backup from a SQL file.")
|
||||||
|
public String importDatabase(
|
||||||
|
@RequestParam("fileInput") MultipartFile file, RedirectAttributes redirectAttributes)
|
||||||
|
throws IllegalArgumentException, IOException {
|
||||||
|
if (file == null || file.isEmpty()) {
|
||||||
|
redirectAttributes.addAttribute("error", "fileNullOrEmpty");
|
||||||
|
return "redirect:/database";
|
||||||
|
}
|
||||||
|
log.info("Received file: {}", file.getOriginalFilename());
|
||||||
|
Path tempTemplatePath = Files.createTempFile("backup_", ".sql");
|
||||||
|
try (InputStream in = file.getInputStream()) {
|
||||||
|
Files.copy(in, tempTemplatePath, StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
boolean importSuccess = databaseBackupHelper.importDatabaseFromUI(tempTemplatePath);
|
||||||
|
if (importSuccess) {
|
||||||
|
redirectAttributes.addAttribute("infoMessage", "importIntoDatabaseSuccessed");
|
||||||
|
} else {
|
||||||
|
redirectAttributes.addAttribute("error", "failedImportFile");
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("Error importing database: {}", e.getMessage());
|
||||||
|
redirectAttributes.addAttribute("error", "failedImportFile");
|
||||||
|
}
|
||||||
|
return "redirect:/database";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Hidden
|
||||||
|
@GetMapping("/import-database-file/{fileName}")
|
||||||
|
public String importDatabaseFromBackupUI(@PathVariable String fileName)
|
||||||
|
throws IllegalArgumentException, IOException {
|
||||||
|
if (fileName == null || fileName.isEmpty()) {
|
||||||
|
return "redirect:/database?error=fileNullOrEmpty";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if the file exists in the backup list
|
||||||
|
boolean fileExists =
|
||||||
|
databaseBackupHelper.getBackupList().stream()
|
||||||
|
.anyMatch(backup -> backup.getFileName().equals(fileName));
|
||||||
|
if (!fileExists) {
|
||||||
|
log.error("File {} not found in backup list", fileName);
|
||||||
|
return "redirect:/database?error=fileNotFound";
|
||||||
|
}
|
||||||
|
log.info("Received file: {}", fileName);
|
||||||
|
if (databaseBackupHelper.importDatabaseFromUI(fileName)) {
|
||||||
|
log.info("File {} imported to database", fileName);
|
||||||
|
return "redirect:/database?infoMessage=importIntoDatabaseSuccessed";
|
||||||
|
}
|
||||||
|
return "redirect:/database?error=failedImportFile";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Hidden
|
||||||
|
@GetMapping("/delete/{fileName}")
|
||||||
|
@Operation(
|
||||||
|
summary = "Delete a database backup file",
|
||||||
|
description =
|
||||||
|
"This endpoint deletes a database backup file with the specified file name.")
|
||||||
|
public String deleteFile(@PathVariable String fileName) {
|
||||||
|
if (fileName == null || fileName.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("File must not be null or empty");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (databaseBackupHelper.deleteBackupFile(fileName)) {
|
||||||
|
log.info("Deleted file: {}", fileName);
|
||||||
|
} else {
|
||||||
|
log.error("Failed to delete file: {}", fileName);
|
||||||
|
return "redirect:/database?error=failedToDeleteFile";
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Error deleting file: {}", e.getMessage());
|
||||||
|
return "redirect:/database?error=" + e.getMessage();
|
||||||
|
}
|
||||||
|
return "redirect:/database";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Hidden
|
||||||
|
@GetMapping("/download/{fileName}")
|
||||||
|
@Operation(
|
||||||
|
summary = "Download a database backup file",
|
||||||
|
description =
|
||||||
|
"This endpoint downloads a database backup file with the specified file name.")
|
||||||
|
public ResponseEntity<?> downloadFile(@PathVariable String fileName) {
|
||||||
|
if (fileName == null || fileName.isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("File must not be null or empty");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Path filePath = databaseBackupHelper.getBackupFilePath(fileName);
|
||||||
|
InputStreamResource resource = new InputStreamResource(Files.newInputStream(filePath));
|
||||||
|
return ResponseEntity.ok()
|
||||||
|
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + fileName)
|
||||||
|
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||||
|
.contentLength(Files.size(filePath))
|
||||||
|
.body(resource);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error("Error downloading file: {}", e.getMessage());
|
||||||
|
return ResponseEntity.status(HttpStatus.SEE_OTHER_303)
|
||||||
|
.location(URI.create("/database?error=downloadFailed"))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
package stirling.software.SPDF.controller.api;
|
package stirling.software.SPDF.controller.api;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -42,7 +43,8 @@ public class UserController {
|
|||||||
|
|
||||||
@PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
|
@PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
|
||||||
@PostMapping("/register")
|
@PostMapping("/register")
|
||||||
public String register(@ModelAttribute UsernameAndPass requestModel, Model model) {
|
public String register(@ModelAttribute UsernameAndPass requestModel, Model model)
|
||||||
|
throws IOException {
|
||||||
if (userService.usernameExistsIgnoreCase(requestModel.getUsername())) {
|
if (userService.usernameExistsIgnoreCase(requestModel.getUsername())) {
|
||||||
model.addAttribute("error", "Username already exists");
|
model.addAttribute("error", "Username already exists");
|
||||||
return "register";
|
return "register";
|
||||||
@ -63,7 +65,8 @@ public class UserController {
|
|||||||
@RequestParam(name = "newUsername") String newUsername,
|
@RequestParam(name = "newUsername") String newUsername,
|
||||||
HttpServletRequest request,
|
HttpServletRequest request,
|
||||||
HttpServletResponse response,
|
HttpServletResponse response,
|
||||||
RedirectAttributes redirectAttributes) {
|
RedirectAttributes redirectAttributes)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
if (!userService.isUsernameValid(newUsername)) {
|
if (!userService.isUsernameValid(newUsername)) {
|
||||||
return new RedirectView("/account?messageType=invalidUsername", true);
|
return new RedirectView("/account?messageType=invalidUsername", true);
|
||||||
@ -116,7 +119,8 @@ public class UserController {
|
|||||||
@RequestParam(name = "newPassword") String newPassword,
|
@RequestParam(name = "newPassword") String newPassword,
|
||||||
HttpServletRequest request,
|
HttpServletRequest request,
|
||||||
HttpServletResponse response,
|
HttpServletResponse response,
|
||||||
RedirectAttributes redirectAttributes) {
|
RedirectAttributes redirectAttributes)
|
||||||
|
throws IOException {
|
||||||
if (principal == null) {
|
if (principal == null) {
|
||||||
return new RedirectView("/change-creds?messageType=notAuthenticated", true);
|
return new RedirectView("/change-creds?messageType=notAuthenticated", true);
|
||||||
}
|
}
|
||||||
@ -149,7 +153,8 @@ public class UserController {
|
|||||||
@RequestParam(name = "newPassword") String newPassword,
|
@RequestParam(name = "newPassword") String newPassword,
|
||||||
HttpServletRequest request,
|
HttpServletRequest request,
|
||||||
HttpServletResponse response,
|
HttpServletResponse response,
|
||||||
RedirectAttributes redirectAttributes) {
|
RedirectAttributes redirectAttributes)
|
||||||
|
throws IOException {
|
||||||
if (principal == null) {
|
if (principal == null) {
|
||||||
return new RedirectView("/account?messageType=notAuthenticated", true);
|
return new RedirectView("/account?messageType=notAuthenticated", true);
|
||||||
}
|
}
|
||||||
@ -176,7 +181,8 @@ public class UserController {
|
|||||||
|
|
||||||
@PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
|
@PreAuthorize("!hasAuthority('ROLE_DEMO_USER')")
|
||||||
@PostMapping("/updateUserSettings")
|
@PostMapping("/updateUserSettings")
|
||||||
public String updateUserSettings(HttpServletRequest request, Principal principal) {
|
public String updateUserSettings(HttpServletRequest request, Principal principal)
|
||||||
|
throws IOException {
|
||||||
Map<String, String[]> paramMap = request.getParameterMap();
|
Map<String, String[]> paramMap = request.getParameterMap();
|
||||||
Map<String, String> updates = new HashMap<>();
|
Map<String, String> updates = new HashMap<>();
|
||||||
|
|
||||||
@ -201,7 +207,8 @@ public class UserController {
|
|||||||
@RequestParam(name = "password") String password,
|
@RequestParam(name = "password") String password,
|
||||||
@RequestParam(name = "role") String role,
|
@RequestParam(name = "role") String role,
|
||||||
@RequestParam(name = "forceChange", required = false, defaultValue = "false")
|
@RequestParam(name = "forceChange", required = false, defaultValue = "false")
|
||||||
boolean forceChange) {
|
boolean forceChange)
|
||||||
|
throws IllegalArgumentException, IOException {
|
||||||
|
|
||||||
if (!userService.isUsernameValid(username)) {
|
if (!userService.isUsernameValid(username)) {
|
||||||
return new RedirectView("/addUsers?messageType=invalidUsername", true);
|
return new RedirectView("/addUsers?messageType=invalidUsername", true);
|
||||||
|
@ -43,6 +43,7 @@ public class AccountWebController {
|
|||||||
|
|
||||||
@GetMapping("/login")
|
@GetMapping("/login")
|
||||||
public String login(HttpServletRequest request, Model model, Authentication authentication) {
|
public String login(HttpServletRequest request, Model model, Authentication authentication) {
|
||||||
|
|
||||||
if (authentication != null && authentication.isAuthenticated()) {
|
if (authentication != null && authentication.isAuthenticated()) {
|
||||||
return "redirect:/";
|
return "redirect:/";
|
||||||
}
|
}
|
||||||
@ -72,6 +73,10 @@ public class AccountWebController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Remove any null keys/values from the providerList
|
||||||
|
providerList
|
||||||
|
.entrySet()
|
||||||
|
.removeIf(entry -> entry.getKey() == null || entry.getValue() == null);
|
||||||
model.addAttribute("providerlist", providerList);
|
model.addAttribute("providerlist", providerList);
|
||||||
|
|
||||||
model.addAttribute("loginMethod", applicationProperties.getSecurity().getLoginMethod());
|
model.addAttribute("loginMethod", applicationProperties.getSecurity().getLoginMethod());
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
package stirling.software.SPDF.controller.web;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.security.access.prepost.PreAuthorize;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.Model;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import stirling.software.SPDF.config.security.database.DatabaseBackupHelper;
|
||||||
|
import stirling.software.SPDF.utils.FileInfo;
|
||||||
|
|
||||||
|
@Controller
|
||||||
|
@Tag(name = "Database Management", description = "Database management and security APIs")
|
||||||
|
public class DatabaseWebController {
|
||||||
|
|
||||||
|
@Autowired private DatabaseBackupHelper databaseBackupHelper;
|
||||||
|
|
||||||
|
@PreAuthorize("hasRole('ROLE_ADMIN')")
|
||||||
|
@GetMapping("/database")
|
||||||
|
public String database(HttpServletRequest request, Model model, Authentication authentication) {
|
||||||
|
String error = request.getParameter("error");
|
||||||
|
String confirmed = request.getParameter("infoMessage");
|
||||||
|
|
||||||
|
if (error != null) {
|
||||||
|
model.addAttribute("error", error);
|
||||||
|
} else if (confirmed != null) {
|
||||||
|
model.addAttribute("infoMessage", confirmed);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<FileInfo> backupList = databaseBackupHelper.getBackupList();
|
||||||
|
model.addAttribute("systemUpdate", backupList);
|
||||||
|
|
||||||
|
return "database";
|
||||||
|
}
|
||||||
|
}
|
@ -16,6 +16,7 @@ import jakarta.persistence.GeneratedValue;
|
|||||||
import jakarta.persistence.GenerationType;
|
import jakarta.persistence.GenerationType;
|
||||||
import jakarta.persistence.Id;
|
import jakarta.persistence.Id;
|
||||||
import jakarta.persistence.JoinColumn;
|
import jakarta.persistence.JoinColumn;
|
||||||
|
import jakarta.persistence.Lob;
|
||||||
import jakarta.persistence.MapKeyColumn;
|
import jakarta.persistence.MapKeyColumn;
|
||||||
import jakarta.persistence.OneToMany;
|
import jakarta.persistence.OneToMany;
|
||||||
import jakarta.persistence.Table;
|
import jakarta.persistence.Table;
|
||||||
@ -55,7 +56,8 @@ public class User {
|
|||||||
|
|
||||||
@ElementCollection
|
@ElementCollection
|
||||||
@MapKeyColumn(name = "setting_key")
|
@MapKeyColumn(name = "setting_key")
|
||||||
@Column(name = "setting_value")
|
@Lob
|
||||||
|
@Column(name = "setting_value", columnDefinition = "CLOB")
|
||||||
@CollectionTable(name = "user_settings", joinColumns = @JoinColumn(name = "user_id"))
|
@CollectionTable(name = "user_settings", joinColumns = @JoinColumn(name = "user_id"))
|
||||||
private Map<String, String> settings = new HashMap<>(); // Key-value pairs of settings.
|
private Map<String, String> settings = new HashMap<>(); // Key-value pairs of settings.
|
||||||
|
|
||||||
|
50
src/main/java/stirling/software/SPDF/utils/FileInfo.java
Normal file
50
src/main/java/stirling/software/SPDF/utils/FileInfo.java
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
package stirling.software.SPDF.utils;
|
||||||
|
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Data
|
||||||
|
public class FileInfo {
|
||||||
|
private String fileName;
|
||||||
|
private String filePath;
|
||||||
|
private LocalDateTime modificationDate;
|
||||||
|
private long fileSize;
|
||||||
|
private LocalDateTime creationDate;
|
||||||
|
|
||||||
|
private static final DateTimeFormatter DATE_FORMATTER =
|
||||||
|
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
|
// Converts the file path string to a Path object.
|
||||||
|
public Path getFilePathAsPath() {
|
||||||
|
return Paths.get(filePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Formats the file size into a human-readable string.
|
||||||
|
public String getFormattedFileSize() {
|
||||||
|
if (fileSize >= 1024 * 1024 * 1024) {
|
||||||
|
return String.format("%.2f GB", fileSize / (1024.0 * 1024 * 1024));
|
||||||
|
} else if (fileSize >= 1024 * 1024) {
|
||||||
|
return String.format("%.2f MB", fileSize / (1024.0 * 1024));
|
||||||
|
} else if (fileSize >= 1024) {
|
||||||
|
return String.format("%.2f KB", fileSize / 1024.0);
|
||||||
|
} else {
|
||||||
|
return String.format("%d Bytes", fileSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Formats the modification date to a string.
|
||||||
|
public String getFormattedModificationDate() {
|
||||||
|
return modificationDate.format(DATE_FORMATTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Formats the creation date to a string.
|
||||||
|
public String getFormattedCreationDate() {
|
||||||
|
return creationDate.format(DATE_FORMATTER);
|
||||||
|
}
|
||||||
|
}
|
@ -191,6 +191,23 @@ adminUserSettings.submit=Save User
|
|||||||
adminUserSettings.changeUserRole=تغيير دور المستخدم
|
adminUserSettings.changeUserRole=تغيير دور المستخدم
|
||||||
adminUserSettings.authenticated=Authenticated
|
adminUserSettings.authenticated=Authenticated
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=إزالة
|
|||||||
#compare
|
#compare
|
||||||
compare.title=يقارن
|
compare.title=يقارن
|
||||||
compare.header=قارن ملفات PDF
|
compare.header=قارن ملفات PDF
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=المستند 1
|
compare.document.1=المستند 1
|
||||||
compare.document.2=المستند 2
|
compare.document.2=المستند 2
|
||||||
compare.submit=يقارن
|
compare.submit=يقارن
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=Съхранете потребителя
|
|||||||
adminUserSettings.changeUserRole=Промяна на ролята на потребителя
|
adminUserSettings.changeUserRole=Промяна на ролята на потребителя
|
||||||
adminUserSettings.authenticated=Удостоверен
|
adminUserSettings.authenticated=Удостоверен
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Премахване
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Сравнявай
|
compare.title=Сравнявай
|
||||||
compare.header=Сравнявай PDF-и
|
compare.header=Сравнявай PDF-и
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Документ 1
|
compare.document.1=Документ 1
|
||||||
compare.document.2=Документ 2
|
compare.document.2=Документ 2
|
||||||
compare.submit=Сравнявай
|
compare.submit=Сравнявай
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=Desar Usuari
|
|||||||
adminUserSettings.changeUserRole=Canvia el rol de l'usuari
|
adminUserSettings.changeUserRole=Canvia el rol de l'usuari
|
||||||
adminUserSettings.authenticated=Authenticated
|
adminUserSettings.authenticated=Authenticated
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Remove
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Comparar
|
compare.title=Comparar
|
||||||
compare.header=Compara PDF
|
compare.header=Compara PDF
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Document 1
|
compare.document.1=Document 1
|
||||||
compare.document.2=Document 2
|
compare.document.2=Document 2
|
||||||
compare.submit=Comparar
|
compare.submit=Comparar
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=Uložit Uživatele
|
|||||||
adminUserSettings.changeUserRole=Zmenit Roli Uživatele
|
adminUserSettings.changeUserRole=Zmenit Roli Uživatele
|
||||||
adminUserSettings.authenticated=Ověřeno
|
adminUserSettings.authenticated=Ověřeno
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Odebrat
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Porovnat
|
compare.title=Porovnat
|
||||||
compare.header=Porovnat PDF
|
compare.header=Porovnat PDF
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Porovnat
|
compare.submit=Porovnat
|
||||||
|
@ -86,7 +86,7 @@ pipeline.defaultOption=Benutzerdefiniert
|
|||||||
pipeline.submitButton=Speichern
|
pipeline.submitButton=Speichern
|
||||||
pipeline.help=Hilfe für Pipeline
|
pipeline.help=Hilfe für Pipeline
|
||||||
pipeline.scanHelp=Hilfe zum Ordnerscan
|
pipeline.scanHelp=Hilfe zum Ordnerscan
|
||||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
pipeline.deletePrompt=Möchten Sie die Pipeline wirklich löschen?
|
||||||
|
|
||||||
######################
|
######################
|
||||||
# Pipeline Options #
|
# Pipeline Options #
|
||||||
@ -191,6 +191,23 @@ adminUserSettings.submit=Benutzer speichern
|
|||||||
adminUserSettings.changeUserRole=Benutzerrolle ändern
|
adminUserSettings.changeUserRole=Benutzerrolle ändern
|
||||||
adminUserSettings.authenticated=Authentifiziert
|
adminUserSettings.authenticated=Authentifiziert
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Datenbank Import/Export
|
||||||
|
database.header=Datenbank Import/Export
|
||||||
|
database.fileName=Dateiname
|
||||||
|
database.creationDate=Erstellungsdatum
|
||||||
|
database.fileSize=Dateigröße
|
||||||
|
database.deleteBackupFile=Sicherungsdatei löschen
|
||||||
|
database.importBackupFile=Sicherungsdatei importieren
|
||||||
|
database.downloadBackupFile=Sicherungsdatei herunterladen
|
||||||
|
database.info_1=Beim Importieren der Daten ist es von größter Bedeutung, die korrekte Struktur zu gewährleisten. Wenn Sie nicht sicher sind, was Sie tun, suchen Sie Rat und Unterstützung von einem Fachmann. Ein Fehler in der Struktur kann zu Fehlfunktionen der Anwendung führen, bis hin zur vollständigen Nicht-Lauffähigkeit der Anwendung.
|
||||||
|
database.info_2=Der Dateiname spielt beim Hochladen keine Rolle. Dieser wird nachträglich in das Format backup_user_yyyyMMddHHmm.sql geändert, um eine einheitliche Benennung zu gewährleisten.
|
||||||
|
database.submit=Sicherungsdatei importieren
|
||||||
|
database.importIntoDatabaseSuccessed=Import in die Datenbank erfolgreich
|
||||||
|
database.fileNotFound=Datei nicht gefunden
|
||||||
|
database.fileNullOrEmpty=Datei darf nicht null oder leer sein
|
||||||
|
database.failedImportFile=Dateiimport fehlgeschlagen
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Entfernen
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Vergleichen
|
compare.title=Vergleichen
|
||||||
compare.header=PDFs vergleichen
|
compare.header=PDFs vergleichen
|
||||||
|
compare.highlightColor.1=Highlight-Farbe 1:
|
||||||
|
compare.highlightColor.2=Highlight-Farbe 2:
|
||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Vergleichen
|
compare.submit=Vergleichen
|
||||||
@ -1084,13 +1103,13 @@ licenses.version=Version
|
|||||||
licenses.license=Lizenz
|
licenses.license=Lizenz
|
||||||
|
|
||||||
#survey
|
#survey
|
||||||
survey.nav=Survey
|
survey.nav=Umfrage
|
||||||
survey.title=Stirling-PDF Survey
|
survey.title=Stirling-PDF-Umfrage
|
||||||
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
survey.description=Stirling-PDF hat kein Tracking, daher möchten wir von unseren Benutzern hören, wie wir Stirling-PDF verbessern können!
|
||||||
survey.please=Please consider taking our survey!
|
survey.please=Bitte nehmen Sie an unserer Umfrage teil!
|
||||||
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
survey.disabled=(Das Umfrage-Popup wird in folgenden Updates deaktiviert, ist aber am Fuß der Seite verfügbar.)
|
||||||
survey.button=Take Survey
|
survey.button=Umfrage durchführen
|
||||||
survey.dontShowAgain=Don't show again
|
survey.dontShowAgain=Nicht mehr anzeigen
|
||||||
|
|
||||||
|
|
||||||
#error
|
#error
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=Αποθήκευση Χρήστη
|
|||||||
adminUserSettings.changeUserRole=Αλλαγή ρόλου χρήστη
|
adminUserSettings.changeUserRole=Αλλαγή ρόλου χρήστη
|
||||||
adminUserSettings.authenticated=Authenticated
|
adminUserSettings.authenticated=Authenticated
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Κατάργηση
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Σύγκριση
|
compare.title=Σύγκριση
|
||||||
compare.header=Σύγκριση PDFs
|
compare.header=Σύγκριση PDFs
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Έγγραφο 1
|
compare.document.1=Έγγραφο 1
|
||||||
compare.document.2=Έγγραφο 2
|
compare.document.2=Έγγραφο 2
|
||||||
compare.submit=Σύγκριση
|
compare.submit=Σύγκριση
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=Save User
|
|||||||
adminUserSettings.changeUserRole=Change User's Role
|
adminUserSettings.changeUserRole=Change User's Role
|
||||||
adminUserSettings.authenticated=Authenticated
|
adminUserSettings.authenticated=Authenticated
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed to import file
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Remove
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Compare
|
compare.title=Compare
|
||||||
compare.header=Compare PDFs
|
compare.header=Compare PDFs
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Document 1
|
compare.document.1=Document 1
|
||||||
compare.document.2=Document 2
|
compare.document.2=Document 2
|
||||||
compare.submit=Compare
|
compare.submit=Compare
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=Save User
|
|||||||
adminUserSettings.changeUserRole=Change User's Role
|
adminUserSettings.changeUserRole=Change User's Role
|
||||||
adminUserSettings.authenticated=Authenticated
|
adminUserSettings.authenticated=Authenticated
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Remove
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Compare
|
compare.title=Compare
|
||||||
compare.header=Compare PDFs
|
compare.header=Compare PDFs
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Document 1
|
compare.document.1=Document 1
|
||||||
compare.document.2=Document 2
|
compare.document.2=Document 2
|
||||||
compare.submit=Compare
|
compare.submit=Compare
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=Guardar Usuario
|
|||||||
adminUserSettings.changeUserRole=Cambiar rol de usuario
|
adminUserSettings.changeUserRole=Cambiar rol de usuario
|
||||||
adminUserSettings.authenticated=Authenticated
|
adminUserSettings.authenticated=Authenticated
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Eliminar
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Comparar
|
compare.title=Comparar
|
||||||
compare.header=Comparar archivos PDF
|
compare.header=Comparar archivos PDF
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Documento 1
|
compare.document.1=Documento 1
|
||||||
compare.document.2=Documento 2
|
compare.document.2=Documento 2
|
||||||
compare.submit=Comparar
|
compare.submit=Comparar
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=Gorde Erabiltzailea
|
|||||||
adminUserSettings.changeUserRole=Erabiltzailearen rola aldatu
|
adminUserSettings.changeUserRole=Erabiltzailearen rola aldatu
|
||||||
adminUserSettings.authenticated=Authenticated
|
adminUserSettings.authenticated=Authenticated
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Remove
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Konparatu
|
compare.title=Konparatu
|
||||||
compare.header=Konparatu PDF fitxategiak
|
compare.header=Konparatu PDF fitxategiak
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=1. dokumentua
|
compare.document.1=1. dokumentua
|
||||||
compare.document.2=2. dokumentua
|
compare.document.2=2. dokumentua
|
||||||
compare.submit=Konparatu
|
compare.submit=Konparatu
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=Ajouter
|
|||||||
adminUserSettings.changeUserRole=Changer le rôle de l'utilisateur
|
adminUserSettings.changeUserRole=Changer le rôle de l'utilisateur
|
||||||
adminUserSettings.authenticated=Authentifié
|
adminUserSettings.authenticated=Authentifié
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Supprimer
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Comparer
|
compare.title=Comparer
|
||||||
compare.header=Comparer
|
compare.header=Comparer
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Document 1
|
compare.document.1=Document 1
|
||||||
compare.document.2=Document 2
|
compare.document.2=Document 2
|
||||||
compare.submit=Comparer
|
compare.submit=Comparer
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=उपयोगकर्ता को सहेजे
|
|||||||
adminUserSettings.changeUserRole=यूज़र की भूमिका बदलें
|
adminUserSettings.changeUserRole=यूज़र की भूमिका बदलें
|
||||||
adminUserSettings.authenticated=Authenticated
|
adminUserSettings.authenticated=Authenticated
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=हटाएं
|
|||||||
#compare
|
#compare
|
||||||
compare.title=तुलना करें
|
compare.title=तुलना करें
|
||||||
compare.header=पीडीएफ़ तुलना करें
|
compare.header=पीडीएफ़ तुलना करें
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=दस्तावेज़ 1
|
compare.document.1=दस्तावेज़ 1
|
||||||
compare.document.2=दस्तावेज़ 2
|
compare.document.2=दस्तावेज़ 2
|
||||||
compare.submit=तुलना करें
|
compare.submit=तुलना करें
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=Spremi korisnika
|
|||||||
adminUserSettings.changeUserRole=Promijenite korisničku ulogu
|
adminUserSettings.changeUserRole=Promijenite korisničku ulogu
|
||||||
adminUserSettings.authenticated=Autentificirano
|
adminUserSettings.authenticated=Autentificirano
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Ukloni
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Uporedite
|
compare.title=Uporedite
|
||||||
compare.header=Usporedite PDF-ove
|
compare.header=Usporedite PDF-ove
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Uporedi
|
compare.submit=Uporedi
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=Felhasználó mentése
|
|||||||
adminUserSettings.changeUserRole=Felhasználó szerepkörének módosítása
|
adminUserSettings.changeUserRole=Felhasználó szerepkörének módosítása
|
||||||
adminUserSettings.authenticated=Authenticated
|
adminUserSettings.authenticated=Authenticated
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Remove
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Összehasonlítás
|
compare.title=Összehasonlítás
|
||||||
compare.header=PDF-ek összehasonlítása
|
compare.header=PDF-ek összehasonlítása
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Dokumentum 1
|
compare.document.1=Dokumentum 1
|
||||||
compare.document.2=Dokumentum 2
|
compare.document.2=Dokumentum 2
|
||||||
compare.submit=Összehasonlítás
|
compare.submit=Összehasonlítás
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=Simpan Pengguna
|
|||||||
adminUserSettings.changeUserRole=Ubah Peran Pengguna
|
adminUserSettings.changeUserRole=Ubah Peran Pengguna
|
||||||
adminUserSettings.authenticated=Authenticated
|
adminUserSettings.authenticated=Authenticated
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Hapus
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Bandingkan
|
compare.title=Bandingkan
|
||||||
compare.header=Bandingkan PDF
|
compare.header=Bandingkan PDF
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Dokumen 1
|
compare.document.1=Dokumen 1
|
||||||
compare.document.2=Dokumen 2
|
compare.document.2=Dokumen 2
|
||||||
compare.submit=Bandingkan
|
compare.submit=Bandingkan
|
||||||
|
@ -35,7 +35,7 @@ sizes.large=Largo
|
|||||||
sizes.x-large=Extra-Large
|
sizes.x-large=Extra-Large
|
||||||
error.pdfPassword=Il documento PDF è protetto da password e la password non è stata fornita oppure non era corretta
|
error.pdfPassword=Il documento PDF è protetto da password e la password non è stata fornita oppure non era corretta
|
||||||
delete=Elimina
|
delete=Elimina
|
||||||
username=Username
|
username=Nome utente
|
||||||
password=Password
|
password=Password
|
||||||
welcome=Benvenuto
|
welcome=Benvenuto
|
||||||
property=Proprietà
|
property=Proprietà
|
||||||
@ -116,7 +116,7 @@ navbar.multiTool=Strumenti multipli
|
|||||||
navbar.sections.organize=Organizza
|
navbar.sections.organize=Organizza
|
||||||
navbar.sections.convertTo=Converti in PDF
|
navbar.sections.convertTo=Converti in PDF
|
||||||
navbar.sections.convertFrom=Converti da PDF
|
navbar.sections.convertFrom=Converti da PDF
|
||||||
navbar.sections.security=Firma Firma & Sicurezza
|
navbar.sections.security=Firma & Sicurezza
|
||||||
navbar.sections.advance=Avanzate
|
navbar.sections.advance=Avanzate
|
||||||
navbar.sections.edit=Visualizza & Modifica
|
navbar.sections.edit=Visualizza & Modifica
|
||||||
|
|
||||||
@ -191,6 +191,23 @@ adminUserSettings.submit=Salva utente
|
|||||||
adminUserSettings.changeUserRole=Cambia il ruolo dell'utente
|
adminUserSettings.changeUserRole=Cambia il ruolo dell'utente
|
||||||
adminUserSettings.authenticated=Autenticato
|
adminUserSettings.authenticated=Autenticato
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Importazione/Esportazione database
|
||||||
|
database.header=Importazione/esportazione database
|
||||||
|
database.fileName=Nome file
|
||||||
|
database.creationDate=Data di creazione
|
||||||
|
database.fileSize=Dimensione
|
||||||
|
database.deleteBackupFile=Elimina file di backup
|
||||||
|
database.importBackupFile=Importa file di backup
|
||||||
|
database.downloadBackupFile=Scarica il file di backup
|
||||||
|
database.info_1=Quando si importano i dati, è fondamentale garantire la struttura corretta. Se non sei sicuro di quello che stai facendo, chiedi consiglio e supporto a un professionista. Un errore nella struttura può causare malfunzionamenti dell'applicazione, fino alla completa impossibilità di eseguire l'applicazione.
|
||||||
|
database.info_2=Il nome del file non ha importanza durante il caricamento. Verrà rinominato in seguito per seguire il formato backup_user__yyyyMMddHHmm.sql,garantendo una convenzione di denominazione coerente.
|
||||||
|
database.submit=Importa Backup
|
||||||
|
database.importIntoDatabaseSuccessed=L'importazione nel database è avvenuta con successo
|
||||||
|
database.fileNotFound=File non trovato
|
||||||
|
database.fileNullOrEmpty=Il file non deve essere nullo o vuoto
|
||||||
|
database.failedImportFile=Importazione file non riuscita
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -234,7 +251,7 @@ pdfOrganiser.tags=duplex,pari,dispari,ordinamento,spostamento
|
|||||||
|
|
||||||
home.addImage.title=Aggiungi Immagine
|
home.addImage.title=Aggiungi Immagine
|
||||||
home.addImage.desc=Aggiungi un'immagine in un punto specifico del PDF (Lavori in corso)
|
home.addImage.desc=Aggiungi un'immagine in un punto specifico del PDF (Lavori in corso)
|
||||||
addImage.tags=img,jpg,immagine,photo
|
addImage.tags=img,jpg,immagine,foto
|
||||||
|
|
||||||
home.watermark.title=Aggiungi Filigrana
|
home.watermark.title=Aggiungi Filigrana
|
||||||
home.watermark.desc=Aggiungi una filigrana al tuo PDF.
|
home.watermark.desc=Aggiungi una filigrana al tuo PDF.
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Rimuovi
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Compara
|
compare.title=Compara
|
||||||
compare.header=Compara PDF
|
compare.header=Compara PDF
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Documento 1
|
compare.document.1=Documento 1
|
||||||
compare.document.2=Documento 2
|
compare.document.2=Documento 2
|
||||||
compare.submit=Compara
|
compare.submit=Compara
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=ユーザーの保存
|
|||||||
adminUserSettings.changeUserRole=ユーザーの役割を変更する
|
adminUserSettings.changeUserRole=ユーザーの役割を変更する
|
||||||
adminUserSettings.authenticated=認証済
|
adminUserSettings.authenticated=認証済
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=削除
|
|||||||
#compare
|
#compare
|
||||||
compare.title=比較
|
compare.title=比較
|
||||||
compare.header=PDFの比較
|
compare.header=PDFの比較
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=ドキュメント 1
|
compare.document.1=ドキュメント 1
|
||||||
compare.document.2=ドキュメント 2
|
compare.document.2=ドキュメント 2
|
||||||
compare.submit=比較
|
compare.submit=比較
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=사용자 저장
|
|||||||
adminUserSettings.changeUserRole=사용자의 역할 변경
|
adminUserSettings.changeUserRole=사용자의 역할 변경
|
||||||
adminUserSettings.authenticated=Authenticated
|
adminUserSettings.authenticated=Authenticated
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=제거하다
|
|||||||
#compare
|
#compare
|
||||||
compare.title=비교
|
compare.title=비교
|
||||||
compare.header=PDF 문서 비교
|
compare.header=PDF 문서 비교
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=문서 1
|
compare.document.1=문서 1
|
||||||
compare.document.2=문서 2
|
compare.document.2=문서 2
|
||||||
compare.submit=비교
|
compare.submit=비교
|
||||||
|
@ -11,17 +11,17 @@ imgPrompt=Selecteer afbeelding(en)
|
|||||||
genericSubmit=Indienen
|
genericSubmit=Indienen
|
||||||
processTimeWarning=Waarschuwing: Dit proces kan tot een minuut duren afhankelijk van de bestandsgrootte
|
processTimeWarning=Waarschuwing: Dit proces kan tot een minuut duren afhankelijk van de bestandsgrootte
|
||||||
pageOrderPrompt=Aangepaste pagina volgorde (Voer een komma-gescheiden lijst van paginanummers of functies in, zoals 2n+1) :
|
pageOrderPrompt=Aangepaste pagina volgorde (Voer een komma-gescheiden lijst van paginanummers of functies in, zoals 2n+1) :
|
||||||
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) :
|
pageSelectionPrompt=Aangepaste pagina selectie (Voer een komma-gescheiden lijst van paginanummer 1,5,6 of functies zoals 2n+1 in) :
|
||||||
goToPage=Ga
|
goToPage=Ga
|
||||||
true=Waar
|
true=Waar
|
||||||
false=Onwaar
|
false=Onwaar
|
||||||
unknown=Onbekend
|
unknown=Onbekend
|
||||||
save=Opslaan
|
save=Opslaan
|
||||||
saveToBrowser=Save to Browser
|
saveToBrowser=Opslaan in browser
|
||||||
close=Sluiten
|
close=Sluiten
|
||||||
filesSelected=Bestanden geselecteerd
|
filesSelected=Bestanden geselecteerd
|
||||||
noFavourites=Geen favorieten toegevoegd
|
noFavourites=Geen favorieten toegevoegd
|
||||||
downloadComplete=Download Complete
|
downloadComplete=Download klaar
|
||||||
bored=Verveeld met wachten?
|
bored=Verveeld met wachten?
|
||||||
alphabet=Alfabet
|
alphabet=Alfabet
|
||||||
downloadPdf=Download PDF
|
downloadPdf=Download PDF
|
||||||
@ -54,23 +54,23 @@ notAuthenticatedMessage=Gebruiker niet ingelogd.
|
|||||||
userNotFoundMessage=Gebruiker niet gevonden.
|
userNotFoundMessage=Gebruiker niet gevonden.
|
||||||
incorrectPasswordMessage=Huidige wachtwoord is onjuist.
|
incorrectPasswordMessage=Huidige wachtwoord is onjuist.
|
||||||
usernameExistsMessage=Nieuwe gebruikersnaam bestaat al.
|
usernameExistsMessage=Nieuwe gebruikersnaam bestaat al.
|
||||||
invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
invalidUsernameMessage=Ongeldige gebruikersnaam, gebruikersnaam kan alleen letters, nummers en de volgende speciale tekens @._+- bevatten of moet een geldig emailadres zijn.
|
||||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
confirmPasswordErrorMessage=Nieuw wachtwoord en bevestig wachtwoord moeten overeenkomen.
|
||||||
deleteCurrentUserMessage=Cannot delete currently logged in user.
|
deleteCurrentUserMessage=Kan niet een momenteel ingelogde gebruiker verwijderen.
|
||||||
deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
|
deleteUsernameExistsMessage=De gebruikersnaam bestaat niet en kan niet verwijderd worden.
|
||||||
downgradeCurrentUserMessage=Kan de rol van de huidige gebruiker niet downgraden
|
downgradeCurrentUserMessage=Kan de rol van de huidige gebruiker niet downgraden
|
||||||
downgradeCurrentUserLongMessage=Kan de rol van de huidige gebruiker niet downgraden. Huidige gebruiker wordt dus niet weergegeven.
|
downgradeCurrentUserLongMessage=Kan de rol van de huidige gebruiker niet downgraden. Huidige gebruiker wordt dus niet weergegeven.
|
||||||
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
|
userAlreadyExistsOAuthMessage=De gebruiker bestaat al als een OAuth2 gebruiker.
|
||||||
userAlreadyExistsWebMessage=The user already exists as an web user.
|
userAlreadyExistsWebMessage=De gebruiker bestaat al als een web gebruiker.
|
||||||
error=Error
|
error=Error
|
||||||
oops=Oops!
|
oops=Oeps!
|
||||||
help=Help
|
help=Help
|
||||||
goHomepage=Go to Homepage
|
goHomepage=Ga naar de startpagina
|
||||||
joinDiscord=Join our Discord server
|
joinDiscord=Word lid van onze Discord server
|
||||||
seeDockerHub=See Docker Hub
|
seeDockerHub=Zie Docker Hub
|
||||||
visitGithub=Visit Github Repository
|
visitGithub=Ga naar de Github Repository
|
||||||
donate=Donate
|
donate=Doneer
|
||||||
color=Color
|
color=Kleur
|
||||||
sponsor=Sponsor
|
sponsor=Sponsor
|
||||||
info=Info
|
info=Info
|
||||||
|
|
||||||
@ -79,14 +79,14 @@ info=Info
|
|||||||
###############
|
###############
|
||||||
# Pipeline #
|
# Pipeline #
|
||||||
###############
|
###############
|
||||||
pipeline.header=Pijplijn menu (Alpha)
|
pipeline.header=Pijplijn menu (Beta)
|
||||||
pipeline.uploadButton=Aangepast uploaden
|
pipeline.uploadButton=Aangepast uploaden
|
||||||
pipeline.configureButton=Configureren
|
pipeline.configureButton=Configureren
|
||||||
pipeline.defaultOption=Aangepast
|
pipeline.defaultOption=Aangepast
|
||||||
pipeline.submitButton=Opslaan
|
pipeline.submitButton=Opslaan
|
||||||
pipeline.help=Pipeline Help
|
pipeline.help=Pijplijn help
|
||||||
pipeline.scanHelp=Folder Scanning Help
|
pipeline.scanHelp=Map scannen help
|
||||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
pipeline.deletePrompt=Weet je zeker dat je deze pijplijn wil verwijderen?
|
||||||
|
|
||||||
######################
|
######################
|
||||||
# Pipeline Options #
|
# Pipeline Options #
|
||||||
@ -107,25 +107,25 @@ pipelineOptions.validateButton=Valideren
|
|||||||
#############
|
#############
|
||||||
# NAVBAR #
|
# NAVBAR #
|
||||||
#############
|
#############
|
||||||
navbar.favorite=Favorites
|
navbar.favorite=Favorieten
|
||||||
navbar.darkmode=Donkere modus
|
navbar.darkmode=Donkere modus
|
||||||
navbar.language=Languages
|
navbar.language=Talen
|
||||||
navbar.settings=Instellingen
|
navbar.settings=Instellingen
|
||||||
navbar.allTools=Tools
|
navbar.allTools=Tools
|
||||||
navbar.multiTool=Multi Tools
|
navbar.multiTool=Multitools
|
||||||
navbar.sections.organize=Organize
|
navbar.sections.organize=Organizeren
|
||||||
navbar.sections.convertTo=Convert to PDF
|
navbar.sections.convertTo=Converteren naar PDF
|
||||||
navbar.sections.convertFrom=Convert from PDF
|
navbar.sections.convertFrom=Converteren van PDF
|
||||||
navbar.sections.security=Sign & Security
|
navbar.sections.security=Ondertekenen & beveiliging
|
||||||
navbar.sections.advance=Advanced
|
navbar.sections.advance=Geavanceerd
|
||||||
navbar.sections.edit=View & Edit
|
navbar.sections.edit=Bekijken & wijzigen
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# SETTINGS #
|
# SETTINGS #
|
||||||
#############
|
#############
|
||||||
settings.title=Instellingen
|
settings.title=Instellingen
|
||||||
settings.update=Update beschikbaar
|
settings.update=Update beschikbaar
|
||||||
settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
|
settings.updateAvailable={0} is de huidig geïnstalleerde versie. Een nieuwe versie ({1}) is beschikbaar.
|
||||||
settings.appVersion=App versie:
|
settings.appVersion=App versie:
|
||||||
settings.downloadOption.title=Kies download optie (Voor enkelvoudige bestanddownloads zonder zip):
|
settings.downloadOption.title=Kies download optie (Voor enkelvoudige bestanddownloads zonder zip):
|
||||||
settings.downloadOption.1=Open in hetzelfde venster
|
settings.downloadOption.1=Open in hetzelfde venster
|
||||||
@ -134,13 +134,13 @@ settings.downloadOption.3=Download bestand
|
|||||||
settings.zipThreshold=Bestanden zippen wanneer het aantal gedownloade bestanden meer is dan
|
settings.zipThreshold=Bestanden zippen wanneer het aantal gedownloade bestanden meer is dan
|
||||||
settings.signOut=Uitloggen
|
settings.signOut=Uitloggen
|
||||||
settings.accountSettings=Account instellingen
|
settings.accountSettings=Account instellingen
|
||||||
settings.bored.help=Enables easter egg game
|
settings.bored.help=Schakelt geheim spelletje in
|
||||||
settings.cacheInputs.name=Save form inputs
|
settings.cacheInputs.name=Sla invoer in formulieren op
|
||||||
settings.cacheInputs.help=Enable to store previously used inputs for future runs
|
settings.cacheInputs.help=Schakel in om eerdere invoeren op te slaan voor toekomstige uitvoeren
|
||||||
|
|
||||||
changeCreds.title=Inloggegevens wijzigen
|
changeCreds.title=Inloggegevens wijzigen
|
||||||
changeCreds.header=Werk je accountgegevens bij
|
changeCreds.header=Werk je accountgegevens bij
|
||||||
changeCreds.changePassword=You are using default login credentials. Please enter a new password
|
changeCreds.changePassword=Je gebruikt de standaard inloggegevens. Voer alstublieft een nieuw wachtwoord in
|
||||||
changeCreds.newUsername=Nieuwe gebruikersnaam
|
changeCreds.newUsername=Nieuwe gebruikersnaam
|
||||||
changeCreds.oldPassword=Huidige wachtwoord
|
changeCreds.oldPassword=Huidige wachtwoord
|
||||||
changeCreds.newPassword=Nieuw wachtwoord
|
changeCreds.newPassword=Nieuw wachtwoord
|
||||||
@ -175,27 +175,44 @@ adminUserSettings.header=Beheer gebruikers
|
|||||||
adminUserSettings.admin=Beheerder
|
adminUserSettings.admin=Beheerder
|
||||||
adminUserSettings.user=Gebruiker
|
adminUserSettings.user=Gebruiker
|
||||||
adminUserSettings.addUser=Voeg nieuwe gebruiker toe
|
adminUserSettings.addUser=Voeg nieuwe gebruiker toe
|
||||||
adminUserSettings.deleteUser=Delete User
|
adminUserSettings.deleteUser=Verwijder gebruiker
|
||||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
adminUserSettings.confirmDeleteUser=Moet deze gebruiker verwijderd worden?
|
||||||
adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
|
adminUserSettings.usernameInfo=Gebruikersnaam kan alleen letters, nummers en de volgende speciale tekens @._+- bevatten of moet een geldig emailadres zijn.
|
||||||
adminUserSettings.roles=Rollen
|
adminUserSettings.roles=Rollen
|
||||||
adminUserSettings.role=Rol
|
adminUserSettings.role=Rol
|
||||||
adminUserSettings.actions=Acties
|
adminUserSettings.actions=Acties
|
||||||
adminUserSettings.apiUser=Beperkte API gebruiker
|
adminUserSettings.apiUser=Beperkte API gebruiker
|
||||||
adminUserSettings.extraApiUser=Additional Limited API User
|
adminUserSettings.extraApiUser=Extra beperkte API gebruiker
|
||||||
adminUserSettings.webOnlyUser=Alleen web gebruiker
|
adminUserSettings.webOnlyUser=Alleen web gebruiker
|
||||||
adminUserSettings.demoUser=Demogebruiker (geen aangepaste instellingen)
|
adminUserSettings.demoUser=Demogebruiker (geen aangepaste instellingen)
|
||||||
adminUserSettings.internalApiUser=Internal API User
|
adminUserSettings.internalApiUser=Interne API gebruiker
|
||||||
adminUserSettings.forceChange=Forceer gebruiker om gebruikersnaam/wachtwoord te wijzigen bij inloggen
|
adminUserSettings.forceChange=Forceer gebruiker om gebruikersnaam/wachtwoord te wijzigen bij inloggen
|
||||||
adminUserSettings.submit=Gebruiker opslaan
|
adminUserSettings.submit=Gebruiker opslaan
|
||||||
adminUserSettings.changeUserRole=De rol van de gebruiker wijzigen
|
adminUserSettings.changeUserRole=De rol van de gebruiker wijzigen
|
||||||
adminUserSettings.authenticated=Authenticated
|
adminUserSettings.authenticated=Geauthenticeerd
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
home.desc=Jouw lokaal gehoste one-stop-shop voor al je PDF-behoeften.
|
home.desc=Jouw lokaal gehoste one-stop-shop voor al je PDF-behoeften.
|
||||||
home.searchBar=Zoeken naar functies...
|
home.searchBar=Zoek naar functies...
|
||||||
|
|
||||||
|
|
||||||
home.viewPdf.title=PDF bekijken
|
home.viewPdf.title=PDF bekijken
|
||||||
@ -204,11 +221,11 @@ viewPdf.tags=bekijken,lezen,annoteren,tekst,afbeelding
|
|||||||
|
|
||||||
home.multiTool.title=PDF multitool
|
home.multiTool.title=PDF multitool
|
||||||
home.multiTool.desc=Pagina's samenvoegen, draaien, herschikken en verwijderen
|
home.multiTool.desc=Pagina's samenvoegen, draaien, herschikken en verwijderen
|
||||||
multiTool.tags=Multitool,Multi bewerking,UI,klik sleep,voorkant,clientzijde,interactief,beweegbaar,verplaats
|
multiTool.tags=Multitool,meerdere bewerkingen,UI,klik sleep,voorkant,clientzijde,interactief,beweegbaar,verplaats
|
||||||
|
|
||||||
home.merge.title=Samenvoegen
|
home.merge.title=Samenvoegen
|
||||||
home.merge.desc=Voeg eenvoudig meerdere PDF's samen tot één.
|
home.merge.desc=Voeg eenvoudig meerdere PDF's samen tot één.
|
||||||
merge.tags=samenvoegen,Pagina bewerkingen,Serverkant
|
merge.tags=samenvoegen,pagina bewerkingen,serverzijde
|
||||||
|
|
||||||
home.split.title=Splitsen
|
home.split.title=Splitsen
|
||||||
home.split.desc=Splits PDF's in meerdere documenten
|
home.split.desc=Splits PDF's in meerdere documenten
|
||||||
@ -255,7 +272,7 @@ addPassword.tags=veilig,beveiliging
|
|||||||
|
|
||||||
home.removePassword.title=Wachtwoord verwijderen
|
home.removePassword.title=Wachtwoord verwijderen
|
||||||
home.removePassword.desc=Verwijder wachtwoordbeveiliging van je PDF-document.
|
home.removePassword.desc=Verwijder wachtwoordbeveiliging van je PDF-document.
|
||||||
removePassword.tags=veilig,Decrypteren,beveiliging,wachtwoord verwijderen
|
removePassword.tags=veilig,ontsleutelen,beveiliging,wachtwoord verwijderen
|
||||||
|
|
||||||
home.compressPdfs.title=Comprimeren
|
home.compressPdfs.title=Comprimeren
|
||||||
home.compressPdfs.desc=Comprimeer PDF's om hun bestandsgrootte te verkleinen.
|
home.compressPdfs.desc=Comprimeer PDF's om hun bestandsgrootte te verkleinen.
|
||||||
@ -336,9 +353,9 @@ home.certSign.title=Ondertekenen met certificaat
|
|||||||
home.certSign.desc=Ondertekent een PDF met een certificaat/sleutel (PEM/P12)
|
home.certSign.desc=Ondertekent een PDF met een certificaat/sleutel (PEM/P12)
|
||||||
certSign.tags=authenticeren,PEM,P12,officieel,versleutelen
|
certSign.tags=authenticeren,PEM,P12,officieel,versleutelen
|
||||||
|
|
||||||
home.removeCertSign.title=Remove Certificate Sign
|
home.removeCertSign.title=Verwijder certificaat
|
||||||
home.removeCertSign.desc=Remove certificate signature from PDF
|
home.removeCertSign.desc=Verwijder certificaat van PDF
|
||||||
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
removeCertSign.tags=authenticeren,PEM,P12,officieel,ontsleutelen
|
||||||
|
|
||||||
home.pageLayout.title=Multi-pagina indeling
|
home.pageLayout.title=Multi-pagina indeling
|
||||||
home.pageLayout.desc=Voeg meerdere pagina's van een PDF-document samen op één pagina
|
home.pageLayout.desc=Voeg meerdere pagina's van een PDF-document samen op één pagina
|
||||||
@ -436,13 +453,13 @@ home.AddStampRequest.desc=Voeg tekst of afbeeldingsstempels toe op vaste locatie
|
|||||||
AddStampRequest.tags=Stempel, Afbeelding toevoegen, afbeelding centreren, watermerk, PDF, Insluiten, Aanpassen
|
AddStampRequest.tags=Stempel, Afbeelding toevoegen, afbeelding centreren, watermerk, PDF, Insluiten, Aanpassen
|
||||||
|
|
||||||
|
|
||||||
home.PDFToBook.title=PDF to Book
|
home.PDFToBook.title=PDF naar Boek
|
||||||
home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre
|
home.PDFToBook.desc=Converteert PDF naar boek-/stripformaat met gebruik van Calibre
|
||||||
PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
PDFToBook.tags=Boek,Strip,Comic,Calibre,Converteren,manga,amazon,kindle
|
||||||
|
|
||||||
home.BookToPDF.title=Book to PDF
|
home.BookToPDF.title=Boek naar PDF
|
||||||
home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre
|
home.BookToPDF.desc=Converteert boek-/stripformaat naar PDF met gebruik van Calibre
|
||||||
BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle
|
BookToPDF.tags=Boek,Strip,Comic,Calibre,Converteren,manga,amazon,kindle
|
||||||
|
|
||||||
|
|
||||||
###########################
|
###########################
|
||||||
@ -460,12 +477,12 @@ login.locked=Je account is geblokkeerd.
|
|||||||
login.signinTitle=Gelieve in te loggen
|
login.signinTitle=Gelieve in te loggen
|
||||||
login.ssoSignIn=Inloggen via Single Sign-on
|
login.ssoSignIn=Inloggen via Single Sign-on
|
||||||
login.oauth2AutoCreateDisabled=OAUTH2 Automatisch aanmaken gebruiker uitgeschakeld
|
login.oauth2AutoCreateDisabled=OAUTH2 Automatisch aanmaken gebruiker uitgeschakeld
|
||||||
login.oauth2RequestNotFound=Authorization request not found
|
login.oauth2RequestNotFound=Autorisatieverzoek niet gevonden
|
||||||
login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
login.oauth2InvalidUserInfoResponse=Ongeldige reactie op gebruikersinfo
|
||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=Ongeldig verzoek
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=Toegang geweigerd
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=Ongeldige tokenreactie
|
||||||
login.oauth2InvalidIdToken=Invalid Id Token
|
login.oauth2InvalidIdToken=Ongeldige ID token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -512,7 +529,7 @@ getPdfInfo.downloadJson=Download JSON
|
|||||||
MarkdownToPDF.title=Markdown naar PDF
|
MarkdownToPDF.title=Markdown naar PDF
|
||||||
MarkdownToPDF.header=Markdown naar PDF
|
MarkdownToPDF.header=Markdown naar PDF
|
||||||
MarkdownToPDF.submit=Converteren
|
MarkdownToPDF.submit=Converteren
|
||||||
MarkdownToPDF.help=in ontwikkeling
|
MarkdownToPDF.help=In ontwikkeling
|
||||||
MarkdownToPDF.credit=Gebruikt WeasyPrint
|
MarkdownToPDF.credit=Gebruikt WeasyPrint
|
||||||
|
|
||||||
|
|
||||||
@ -542,7 +559,7 @@ HTMLToPDF.defaultHeader=Standaard koptekst weergeven (naam en paginanummer)
|
|||||||
HTMLToPDF.cssMediaType=Wijzig het CSS-mediatype van de pagina.
|
HTMLToPDF.cssMediaType=Wijzig het CSS-mediatype van de pagina.
|
||||||
HTMLToPDF.none=Geen
|
HTMLToPDF.none=Geen
|
||||||
HTMLToPDF.print=Print
|
HTMLToPDF.print=Print
|
||||||
HTMLToPDF.screen=Screen
|
HTMLToPDF.screen=Scherm
|
||||||
|
|
||||||
|
|
||||||
#AddStampRequest
|
#AddStampRequest
|
||||||
@ -664,10 +681,10 @@ certSign.submit=PDF ondertekenen
|
|||||||
|
|
||||||
|
|
||||||
#removeCertSign
|
#removeCertSign
|
||||||
removeCertSign.title=Remove Certificate Signature
|
removeCertSign.title=Verwijder certificaat
|
||||||
removeCertSign.header=Remove the digital certificate from the PDF
|
removeCertSign.header=Verwijder het digitale certificaat van de PDF
|
||||||
removeCertSign.selectPDF=Select a PDF file:
|
removeCertSign.selectPDF=Selecteer een PDF bestand:
|
||||||
removeCertSign.submit=Remove Signature
|
removeCertSign.submit=Verwijder certificaat
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
@ -689,22 +706,24 @@ removeAnnotations.submit=Verwijderen
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Vergelijken
|
compare.title=Vergelijken
|
||||||
compare.header=PDF's vergelijken
|
compare.header=PDF's vergelijken
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Document 1
|
compare.document.1=Document 1
|
||||||
compare.document.2=Document 2
|
compare.document.2=Document 2
|
||||||
compare.submit=Vergelijken
|
compare.submit=Vergelijken
|
||||||
|
|
||||||
#BookToPDF
|
#BookToPDF
|
||||||
BookToPDF.title=Books and Comics to PDF
|
BookToPDF.title=Boeken en strips naar PDF
|
||||||
BookToPDF.header=Book to PDF
|
BookToPDF.header=Boek naar PDF
|
||||||
BookToPDF.credit=Uses Calibre
|
BookToPDF.credit=Gebruikt Calibre
|
||||||
BookToPDF.submit=Convert
|
BookToPDF.submit=Converteer
|
||||||
|
|
||||||
#PDFToBook
|
#PDFToBook
|
||||||
PDFToBook.title=PDF to Book
|
PDFToBook.title=PDF naar boek
|
||||||
PDFToBook.header=PDF to Book
|
PDFToBook.header=PDF naar boek
|
||||||
PDFToBook.selectText.1=Format
|
PDFToBook.selectText.1=Formaat
|
||||||
PDFToBook.credit=Uses Calibre
|
PDFToBook.credit=Gebruikt Calibre
|
||||||
PDFToBook.submit=Convert
|
PDFToBook.submit=Converteer
|
||||||
|
|
||||||
#sign
|
#sign
|
||||||
sign.title=Ondertekenen
|
sign.title=Ondertekenen
|
||||||
@ -725,7 +744,7 @@ repair.submit=Repareren
|
|||||||
#flatten
|
#flatten
|
||||||
flatten.title=Afvlakken
|
flatten.title=Afvlakken
|
||||||
flatten.header=PDF's afvlakken
|
flatten.header=PDF's afvlakken
|
||||||
flatten.flattenOnlyForms=Flatten only forms
|
flatten.flattenOnlyForms=Alleen formulieren afvlakken
|
||||||
flatten.submit=Afvlakken
|
flatten.submit=Afvlakken
|
||||||
|
|
||||||
|
|
||||||
@ -756,7 +775,7 @@ ocr.selectText.8=Normaal (Zal een fout geven als de PDF tekst bevat)
|
|||||||
ocr.selectText.9=Aanvullende instellingen
|
ocr.selectText.9=Aanvullende instellingen
|
||||||
ocr.selectText.10=OCR-modus
|
ocr.selectText.10=OCR-modus
|
||||||
ocr.selectText.11=Verwijder afbeeldingen na OCR (Verwijdert ALLE afbeeldingen, alleen nuttig als onderdeel van conversiestap)
|
ocr.selectText.11=Verwijder afbeeldingen na OCR (Verwijdert ALLE afbeeldingen, alleen nuttig als onderdeel van conversiestap)
|
||||||
ocr.selectText.12=Render Type (Geavanceerd)
|
ocr.selectText.12=Weergave Type (Geavanceerd)
|
||||||
ocr.help=Lees deze documentatie over hoe dit te gebruiken voor andere talen en/of gebruik buiten docker
|
ocr.help=Lees deze documentatie over hoe dit te gebruiken voor andere talen en/of gebruik buiten docker
|
||||||
ocr.credit=Deze dienst maakt gebruik van OCRmyPDF en Tesseract voor OCR.
|
ocr.credit=Deze dienst maakt gebruik van OCRmyPDF en Tesseract voor OCR.
|
||||||
ocr.submit=Verwerk PDF met OCR
|
ocr.submit=Verwerk PDF met OCR
|
||||||
@ -803,7 +822,7 @@ merge.title=Samenvoegen
|
|||||||
merge.header=Meerdere PDF's samenvoegen (2+)
|
merge.header=Meerdere PDF's samenvoegen (2+)
|
||||||
merge.sortByName=Sorteer op naam
|
merge.sortByName=Sorteer op naam
|
||||||
merge.sortByDate=Sorteer op datum
|
merge.sortByDate=Sorteer op datum
|
||||||
merge.removeCertSign=Remove digital signature in the merged file?
|
merge.removeCertSign=Verwijder digitale handtekening in het samengevoegde bestand?
|
||||||
merge.submit=Samenvoegen
|
merge.submit=Samenvoegen
|
||||||
|
|
||||||
|
|
||||||
@ -811,24 +830,24 @@ merge.submit=Samenvoegen
|
|||||||
pdfOrganiser.title=Pagina organisator
|
pdfOrganiser.title=Pagina organisator
|
||||||
pdfOrganiser.header=PDF pagina organisator
|
pdfOrganiser.header=PDF pagina organisator
|
||||||
pdfOrganiser.submit=Pagina's herschikken
|
pdfOrganiser.submit=Pagina's herschikken
|
||||||
pdfOrganiser.mode=Mode
|
pdfOrganiser.mode=Modus
|
||||||
pdfOrganiser.mode.1=Custom Page Order
|
pdfOrganiser.mode.1=Aangepaste paginavolgorde
|
||||||
pdfOrganiser.mode.2=Reverse Order
|
pdfOrganiser.mode.2=Omgekeerde volgorde
|
||||||
pdfOrganiser.mode.3=Duplex Sort
|
pdfOrganiser.mode.3=Duplex sorteren
|
||||||
pdfOrganiser.mode.4=Booklet Sort
|
pdfOrganiser.mode.4=Boekje sorteren
|
||||||
pdfOrganiser.mode.5=Side Stitch Booklet Sort
|
pdfOrganiser.mode.5=Zijsteek boekje sorteren
|
||||||
pdfOrganiser.mode.6=Odd-Even Split
|
pdfOrganiser.mode.6=Oneven-even splitsen
|
||||||
pdfOrganiser.mode.7=Remove First
|
pdfOrganiser.mode.7=Eerste verwijderen
|
||||||
pdfOrganiser.mode.8=Remove Last
|
pdfOrganiser.mode.8=Laatste verwijderen
|
||||||
pdfOrganiser.mode.9=Remove First and Last
|
pdfOrganiser.mode.9=Eerste en laaste verwijderen
|
||||||
pdfOrganiser.mode.10=Odd-Even Merge
|
pdfOrganiser.mode.10=Oneven-even samenvoeken
|
||||||
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
|
pdfOrganiser.placeholder=(bijv. 1,3,2 of 4-8,2,10-12 of 2n-1)
|
||||||
|
|
||||||
|
|
||||||
#multiTool
|
#multiTool
|
||||||
multiTool.title=PDF Multitool
|
multiTool.title=PDF Multitool
|
||||||
multiTool.header=PDF Multitool
|
multiTool.header=PDF Multitool
|
||||||
multiTool.uploadPrompts=File Name
|
multiTool.uploadPrompts=Bestandsnaam
|
||||||
|
|
||||||
#view pdf
|
#view pdf
|
||||||
viewPdf.title=PDF bekijken
|
viewPdf.title=PDF bekijken
|
||||||
@ -839,7 +858,7 @@ pageRemover.title=Pagina verwijderaar
|
|||||||
pageRemover.header=PDF pagina verwijderaar
|
pageRemover.header=PDF pagina verwijderaar
|
||||||
pageRemover.pagesToDelete=Te verwijderen pagina's (Voer een door komma's gescheiden lijst met paginanummers in):
|
pageRemover.pagesToDelete=Te verwijderen pagina's (Voer een door komma's gescheiden lijst met paginanummers in):
|
||||||
pageRemover.submit=Pagina's verwijderen
|
pageRemover.submit=Pagina's verwijderen
|
||||||
pageRemover.placeholder=(e.g. 1,2,6 or 1-10,15-30)
|
pageRemover.placeholder=(bijv. 1,2,6 of 1-10,15-30)
|
||||||
|
|
||||||
|
|
||||||
#rotate
|
#rotate
|
||||||
@ -980,9 +999,9 @@ pdfToPDFA.title=PDF naar PDF/A
|
|||||||
pdfToPDFA.header=PDF naar PDF/A
|
pdfToPDFA.header=PDF naar PDF/A
|
||||||
pdfToPDFA.credit=Deze service gebruikt OCRmyPDF voor PDF/A-conversie
|
pdfToPDFA.credit=Deze service gebruikt OCRmyPDF voor PDF/A-conversie
|
||||||
pdfToPDFA.submit=Converteren
|
pdfToPDFA.submit=Converteren
|
||||||
pdfToPDFA.tip=Currently does not work for multiple inputs at once
|
pdfToPDFA.tip=Werkt momenteel niet voor meerdere inputs tegelijkertijd.
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=Output format
|
||||||
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
pdfToPDFA.pdfWithDigitalSignature=Dit PDF bestand bevat een digitale handtekening. Deze wordt in de volgende stap verwijderd.
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
@ -1064,14 +1083,14 @@ split-by-sections.vertical.label=Verticale secties
|
|||||||
split-by-sections.horizontal.placeholder=Voer het aantal horizontale secties in
|
split-by-sections.horizontal.placeholder=Voer het aantal horizontale secties in
|
||||||
split-by-sections.vertical.placeholder=Voer het aantal verticale secties in
|
split-by-sections.vertical.placeholder=Voer het aantal verticale secties in
|
||||||
split-by-sections.submit=PDF splitsen
|
split-by-sections.submit=PDF splitsen
|
||||||
split-by-sections.merge=Merge Into One PDF
|
split-by-sections.merge=Samenvoegen in één PDF
|
||||||
|
|
||||||
|
|
||||||
#printFile
|
#printFile
|
||||||
printFile.title=Print File
|
printFile.title=Print bestand
|
||||||
printFile.header=Print File to Printer
|
printFile.header=Print bestand naar printer
|
||||||
printFile.selectText.1=Select File to Print
|
printFile.selectText.1=Selecteer bestand om te printen
|
||||||
printFile.selectText.2=Enter Printer Name
|
printFile.selectText.2=Voer printernaam in
|
||||||
printFile.submit=Print
|
printFile.submit=Print
|
||||||
|
|
||||||
|
|
||||||
@ -1084,25 +1103,25 @@ licenses.version=Versie
|
|||||||
licenses.license=Licentie
|
licenses.license=Licentie
|
||||||
|
|
||||||
#survey
|
#survey
|
||||||
survey.nav=Survey
|
survey.nav=Enquête
|
||||||
survey.title=Stirling-PDF Survey
|
survey.title=Stirling-PDF Enquête
|
||||||
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
survey.description=Stirling-PDF heeft geen tracking, dus we willen van onze gebruikers horen om Stirling-PDF te verbeteren.
|
||||||
survey.please=Please consider taking our survey!
|
survey.please=Overweeg alstublieft om onze enquête in te vullen!
|
||||||
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
survey.disabled=(Enquête popup wordt in een toekomstige update weggehaald, maar is beschikbaar aan de onderkant van de pagina.)
|
||||||
survey.button=Take Survey
|
survey.button=Vul enquête in.
|
||||||
survey.dontShowAgain=Don't show again
|
survey.dontShowAgain=Niet weer tonen
|
||||||
|
|
||||||
|
|
||||||
#error
|
#error
|
||||||
error.sorry=Sorry for the issue!
|
error.sorry=Excuses voor het probleem!
|
||||||
error.needHelp=Need help / Found an issue?
|
error.needHelp=Hulp nodig / probleem gevonden?
|
||||||
error.contactTip=If you're still having trouble, don't hesitate to reach out to us for help. You can submit a ticket on our GitHub page or contact us through Discord:
|
error.contactTip=Als je nog steeds problemen hebt, schroom niet om contact met ons op te nemen voor hulp. Je kan een ticket op onze Github pagina indienen of ons via Discord bereiken:
|
||||||
error.404.head=404 - Page Not Found | Oops, we tripped in the code!
|
error.404.head=404 - Pagina niet gevonden | Oeps, we struikelden over de code!
|
||||||
error.404.1=We can't seem to find the page you're looking for.
|
error.404.1=We kunnen de pagina die je zoek niet vinden.
|
||||||
error.404.2=Something went wrong
|
error.404.2=Er ging iets mis.
|
||||||
error.github=Submit a ticket on GitHub
|
error.github=Dien een ticket op Github in.
|
||||||
error.showStack=Show Stack Trace
|
error.showStack=Geeft tracering weer
|
||||||
error.copyStack=Copy Stack Trace
|
error.copyStack=Kopieer tracering
|
||||||
error.githubSubmit=GitHub - Submit a ticket
|
error.githubSubmit=GitHub - Dien een ticket in
|
||||||
error.discordSubmit=Discord - Submit Support post
|
error.discordSubmit=Discord - Maak een support post
|
||||||
|
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=Lagre Bruker
|
|||||||
adminUserSettings.changeUserRole=Endre Brukerens Rolle
|
adminUserSettings.changeUserRole=Endre Brukerens Rolle
|
||||||
adminUserSettings.authenticated=Autentisert
|
adminUserSettings.authenticated=Autentisert
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Fjern
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Sammenlign
|
compare.title=Sammenlign
|
||||||
compare.header=Sammenlign PDF-er
|
compare.header=Sammenlign PDF-er
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Sammenlign
|
compare.submit=Sammenlign
|
||||||
|
831
src/main/resources/messages_pl_PL.properties
Normal file → Executable file
831
src/main/resources/messages_pl_PL.properties
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
@ -191,6 +191,23 @@ adminUserSettings.submit=Save User
|
|||||||
adminUserSettings.changeUserRole=Alterar Função de Usuário
|
adminUserSettings.changeUserRole=Alterar Função de Usuário
|
||||||
adminUserSettings.authenticated=Authenticated
|
adminUserSettings.authenticated=Authenticated
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Remove
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Comparar
|
compare.title=Comparar
|
||||||
compare.header=Comparar PDFs
|
compare.header=Comparar PDFs
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Documento 1
|
compare.document.1=Documento 1
|
||||||
compare.document.2=Documento 2
|
compare.document.2=Documento 2
|
||||||
compare.submit=Comparar
|
compare.submit=Comparar
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=Save User
|
|||||||
adminUserSettings.changeUserRole=Alterar usuário
|
adminUserSettings.changeUserRole=Alterar usuário
|
||||||
adminUserSettings.authenticated=Authenticated
|
adminUserSettings.authenticated=Authenticated
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Remover
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Comparar
|
compare.title=Comparar
|
||||||
compare.header=Comparar PDFs
|
compare.header=Comparar PDFs
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Documento 1
|
compare.document.1=Documento 1
|
||||||
compare.document.2=Documento 2
|
compare.document.2=Documento 2
|
||||||
compare.submit=Comparar
|
compare.submit=Comparar
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=Save User
|
|||||||
adminUserSettings.changeUserRole=Schimbați rolul utilizatorului
|
adminUserSettings.changeUserRole=Schimbați rolul utilizatorului
|
||||||
adminUserSettings.authenticated=Authenticated
|
adminUserSettings.authenticated=Authenticated
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Remove
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Compară
|
compare.title=Compară
|
||||||
compare.header=Compară PDF-uri
|
compare.header=Compară PDF-uri
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Document 1
|
compare.document.1=Document 1
|
||||||
compare.document.2=Document 2
|
compare.document.2=Document 2
|
||||||
compare.submit=Compară
|
compare.submit=Compară
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=Сохранить пользователя
|
|||||||
adminUserSettings.changeUserRole=Изменить роль пользователя
|
adminUserSettings.changeUserRole=Изменить роль пользователя
|
||||||
adminUserSettings.authenticated=Authenticated
|
adminUserSettings.authenticated=Authenticated
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Удалить
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Сравнение
|
compare.title=Сравнение
|
||||||
compare.header=Сравнение PDFы
|
compare.header=Сравнение PDFы
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Документ 1
|
compare.document.1=Документ 1
|
||||||
compare.document.2=Документ 2
|
compare.document.2=Документ 2
|
||||||
compare.submit=Сравнить
|
compare.submit=Сравнить
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=Uložiť používateľa
|
|||||||
adminUserSettings.changeUserRole=Zmeniť rolu používateľa
|
adminUserSettings.changeUserRole=Zmeniť rolu používateľa
|
||||||
adminUserSettings.authenticated=Authenticated
|
adminUserSettings.authenticated=Authenticated
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Odstrániť
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Porovnať
|
compare.title=Porovnať
|
||||||
compare.header=Porovnať PDF
|
compare.header=Porovnať PDF
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Porovnať
|
compare.submit=Porovnať
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=Sačuvaj korisnika
|
|||||||
adminUserSettings.changeUserRole=Promenite ulogu korisnika
|
adminUserSettings.changeUserRole=Promenite ulogu korisnika
|
||||||
adminUserSettings.authenticated=Authenticated
|
adminUserSettings.authenticated=Authenticated
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Ukloni
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Uporedi
|
compare.title=Uporedi
|
||||||
compare.header=Uporedi PDF fajlove
|
compare.header=Uporedi PDF fajlove
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Uporedi
|
compare.submit=Uporedi
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=Save User
|
|||||||
adminUserSettings.changeUserRole=Ändra användarens roll
|
adminUserSettings.changeUserRole=Ändra användarens roll
|
||||||
adminUserSettings.authenticated=Authenticated
|
adminUserSettings.authenticated=Authenticated
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Remove
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Jämför
|
compare.title=Jämför
|
||||||
compare.header=Jämför PDF-filer
|
compare.header=Jämför PDF-filer
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Dokument 1
|
compare.document.1=Dokument 1
|
||||||
compare.document.2=Dokument 2
|
compare.document.2=Dokument 2
|
||||||
compare.submit=Jämför
|
compare.submit=Jämför
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=Kullanıcıyı Kaydet
|
|||||||
adminUserSettings.changeUserRole=Kullanıcı rolünü değiştir
|
adminUserSettings.changeUserRole=Kullanıcı rolünü değiştir
|
||||||
adminUserSettings.authenticated=Onaylandı
|
adminUserSettings.authenticated=Onaylandı
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Kaldır
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Karşılaştır
|
compare.title=Karşılaştır
|
||||||
compare.header=PDF'leri Karşılaştır
|
compare.header=PDF'leri Karşılaştır
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Belge 1
|
compare.document.1=Belge 1
|
||||||
compare.document.2=Belge 2
|
compare.document.2=Belge 2
|
||||||
compare.submit=Karşılaştır
|
compare.submit=Karşılaştır
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=Зберегти користувача
|
|||||||
adminUserSettings.changeUserRole=Змінити роль користувача
|
adminUserSettings.changeUserRole=Змінити роль користувача
|
||||||
adminUserSettings.authenticated=Автентифіковано
|
adminUserSettings.authenticated=Автентифіковано
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=Видалити
|
|||||||
#compare
|
#compare
|
||||||
compare.title=Порівняння
|
compare.title=Порівняння
|
||||||
compare.header=Порівняння PDF
|
compare.header=Порівняння PDF
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=Документ 1
|
compare.document.1=Документ 1
|
||||||
compare.document.2=Документ 2
|
compare.document.2=Документ 2
|
||||||
compare.submit=Порівняти
|
compare.submit=Порівняти
|
||||||
|
@ -10,8 +10,8 @@ multiPdfDropPrompt=选择(或拖拽)所需的PDF
|
|||||||
imgPrompt=选择图像
|
imgPrompt=选择图像
|
||||||
genericSubmit=提交
|
genericSubmit=提交
|
||||||
processTimeWarning=警告:此过程可能需要多达一分钟,具体时间取决于文件大小
|
processTimeWarning=警告:此过程可能需要多达一分钟,具体时间取决于文件大小
|
||||||
pageOrderPrompt=页面顺序(输入逗号分隔的页码列表):
|
pageOrderPrompt=页面顺序(输入逗号分隔的页码列表或函数):
|
||||||
pageSelectionPrompt=自定义页面选择(输入以逗号分隔的页码列表 1,5,6 或 2n+1 等函数):
|
pageSelectionPrompt=自定义页面选择(输入以逗号分隔的页码列表或函数:1,5,6、2n+1):
|
||||||
goToPage=到
|
goToPage=到
|
||||||
true=对
|
true=对
|
||||||
false=错
|
false=错
|
||||||
@ -33,7 +33,7 @@ sizes.small=小型尺寸
|
|||||||
sizes.medium=中型尺寸
|
sizes.medium=中型尺寸
|
||||||
sizes.large=大型尺寸
|
sizes.large=大型尺寸
|
||||||
sizes.x-large=超大型尺寸
|
sizes.x-large=超大型尺寸
|
||||||
error.pdfPassword=PDF 文档有密码,未提供密码或密码不正确
|
error.pdfPassword=PDF文档有密码,未提供密码或密码不正确
|
||||||
delete=删除
|
delete=删除
|
||||||
username=用户名
|
username=用户名
|
||||||
password=密码
|
password=密码
|
||||||
@ -55,13 +55,13 @@ userNotFoundMessage=未找到用户。
|
|||||||
incorrectPasswordMessage=当前密码不正确。
|
incorrectPasswordMessage=当前密码不正确。
|
||||||
usernameExistsMessage=新用户名已存在。
|
usernameExistsMessage=新用户名已存在。
|
||||||
invalidUsernameMessage=用户名无效,用户名只能包含字母、数字和以下特殊字符@._+- 或必须是有效的电子邮件地址。
|
invalidUsernameMessage=用户名无效,用户名只能包含字母、数字和以下特殊字符@._+- 或必须是有效的电子邮件地址。
|
||||||
confirmPasswordErrorMessage=New Password and Confirm New Password must match.
|
confirmPasswordErrorMessage=两次密码不一致。
|
||||||
deleteCurrentUserMessage=无法删除当前登录的用户。
|
deleteCurrentUserMessage=无法删除当前登录的用户。
|
||||||
deleteUsernameExistsMessage=用户名不存在,无法删除。
|
deleteUsernameExistsMessage=用户名不存在,无法删除。
|
||||||
downgradeCurrentUserMessage=无法降级当前用户的角色
|
downgradeCurrentUserMessage=无法降级当前用户的角色
|
||||||
downgradeCurrentUserLongMessage=无法降级当前用户的角色。因此,当前用户将不会显示。
|
downgradeCurrentUserLongMessage=无法降级当前用户的角色。因此,当前用户将不会显示。
|
||||||
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
|
userAlreadyExistsOAuthMessage=该用户已作为OAuth2用户存在。
|
||||||
userAlreadyExistsWebMessage=The user already exists as an web user.
|
userAlreadyExistsWebMessage=该用户已作为Web用户存在。
|
||||||
error=错误
|
error=错误
|
||||||
oops=哎呀!
|
oops=哎呀!
|
||||||
help=帮助
|
help=帮助
|
||||||
@ -72,21 +72,21 @@ visitGithub=访问Github仓库
|
|||||||
donate=捐款
|
donate=捐款
|
||||||
color=颜色
|
color=颜色
|
||||||
sponsor=赞助
|
sponsor=赞助
|
||||||
info=Info
|
info=信息
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
###############
|
###############
|
||||||
# Pipeline #
|
# Pipeline #
|
||||||
###############
|
###############
|
||||||
pipeline.header=流水线菜单 (Beta)
|
pipeline.header=流水线菜单(Beta)
|
||||||
pipeline.uploadButton=上传自定义流水线
|
pipeline.uploadButton=上传自定义流水线
|
||||||
pipeline.configureButton=配置
|
pipeline.configureButton=配置
|
||||||
pipeline.defaultOption=自定义
|
pipeline.defaultOption=自定义
|
||||||
pipeline.submitButton=提交
|
pipeline.submitButton=提交
|
||||||
pipeline.help=工作流帮助
|
pipeline.help=工作流帮助
|
||||||
pipeline.scanHelp=文件夹扫描帮助
|
pipeline.scanHelp=文件夹扫描帮助
|
||||||
pipeline.deletePrompt=Are you sure you want to delete pipeline
|
pipeline.deletePrompt=确认删除该工作流?
|
||||||
|
|
||||||
######################
|
######################
|
||||||
# Pipeline Options #
|
# Pipeline Options #
|
||||||
@ -125,7 +125,7 @@ navbar.sections.edit=查看和编辑
|
|||||||
#############
|
#############
|
||||||
settings.title=设置
|
settings.title=设置
|
||||||
settings.update=可更新
|
settings.update=可更新
|
||||||
settings.updateAvailable={0} is the current installed version. A new version ({1}) is available.
|
settings.updateAvailable=当前版本为 {0},新版本 ({1}) 可用。
|
||||||
settings.appVersion=应用程序版本:
|
settings.appVersion=应用程序版本:
|
||||||
settings.downloadOption.title=选择下载选项(单个文件非压缩文件):
|
settings.downloadOption.title=选择下载选项(单个文件非压缩文件):
|
||||||
settings.downloadOption.1=在同一窗口打开
|
settings.downloadOption.1=在同一窗口打开
|
||||||
@ -133,10 +133,10 @@ settings.downloadOption.2=在新窗口中打开
|
|||||||
settings.downloadOption.3=下载文件
|
settings.downloadOption.3=下载文件
|
||||||
settings.zipThreshold=当下载的文件数量超过限制时,将文件压缩。
|
settings.zipThreshold=当下载的文件数量超过限制时,将文件压缩。
|
||||||
settings.signOut=登出
|
settings.signOut=登出
|
||||||
settings.accountSettings=帐号设定
|
settings.accountSettings=账号设定
|
||||||
settings.bored.help=Enables easter egg game
|
settings.bored.help=启用彩蛋游戏
|
||||||
settings.cacheInputs.name=Save form inputs
|
settings.cacheInputs.name=保存表单输入
|
||||||
settings.cacheInputs.help=Enable to store previously used inputs for future runs
|
settings.cacheInputs.help=保存先前输入以供日后使用
|
||||||
|
|
||||||
changeCreds.title=更改凭证
|
changeCreds.title=更改凭证
|
||||||
changeCreds.header=更新您的账户详情
|
changeCreds.header=更新您的账户详情
|
||||||
@ -149,8 +149,8 @@ changeCreds.submit=提交更改
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
account.title=帐号设定
|
account.title=账号设定
|
||||||
account.accountSettings=帐号设定
|
account.accountSettings=账号设定
|
||||||
account.adminSettings=管理员设置 - 查看和添加用户
|
account.adminSettings=管理员设置 - 查看和添加用户
|
||||||
account.userControlSettings=用户控制设置
|
account.userControlSettings=用户控制设置
|
||||||
account.changeUsername=更改用户名
|
account.changeUsername=更改用户名
|
||||||
@ -161,11 +161,11 @@ account.newPassword=新密码
|
|||||||
account.changePassword=更改密码
|
account.changePassword=更改密码
|
||||||
account.confirmNewPassword=确认新密码
|
account.confirmNewPassword=确认新密码
|
||||||
account.signOut=退出登录
|
account.signOut=退出登录
|
||||||
account.yourApiKey=您的 API 密钥
|
account.yourApiKey=您的API密钥
|
||||||
account.syncTitle=将浏览器设置与账户同步
|
account.syncTitle=将浏览器设置与账户同步
|
||||||
account.settingsCompare=设置比较:
|
account.settingsCompare=设置比较:
|
||||||
account.property=属性
|
account.property=属性
|
||||||
account.webBrowserSettings=Web 浏览器设置
|
account.webBrowserSettings=Web浏览器设置
|
||||||
account.syncToBrowser=同步账户 -> 浏览器
|
account.syncToBrowser=同步账户 -> 浏览器
|
||||||
account.syncToAccount=同步账户 <- 浏览器
|
account.syncToAccount=同步账户 <- 浏览器
|
||||||
|
|
||||||
@ -175,21 +175,38 @@ adminUserSettings.header=管理员用户控制设置
|
|||||||
adminUserSettings.admin=管理员
|
adminUserSettings.admin=管理员
|
||||||
adminUserSettings.user=用户
|
adminUserSettings.user=用户
|
||||||
adminUserSettings.addUser=添加新用户
|
adminUserSettings.addUser=添加新用户
|
||||||
adminUserSettings.deleteUser=Delete User
|
adminUserSettings.deleteUser=删除用户
|
||||||
adminUserSettings.confirmDeleteUser=Should the user be deleted?
|
adminUserSettings.confirmDeleteUser=确认删除该用户?
|
||||||
adminUserSettings.usernameInfo=用户名只能包含字母、数字和以下特殊字符@._+-,或者必须是有效的电子邮件地址。
|
adminUserSettings.usernameInfo=用户名只能包含字母、数字和以下特殊字符@._+-,或者必须是有效的电子邮件地址。
|
||||||
adminUserSettings.roles=角色
|
adminUserSettings.roles=角色
|
||||||
adminUserSettings.role=角色
|
adminUserSettings.role=角色
|
||||||
adminUserSettings.actions=操作
|
adminUserSettings.actions=操作
|
||||||
adminUserSettings.apiUser=受限制的 API 用户
|
adminUserSettings.apiUser=受限制的API用户
|
||||||
adminUserSettings.extraApiUser=额外受限制的 API 用户
|
adminUserSettings.extraApiUser=额外受限制的API用户
|
||||||
adminUserSettings.webOnlyUser=仅限 Web 用户
|
adminUserSettings.webOnlyUser=仅限Web用户
|
||||||
adminUserSettings.demoUser=演示用户(无自定义设置)
|
adminUserSettings.demoUser=演示用户(无自定义设置)
|
||||||
adminUserSettings.internalApiUser=内部API用户
|
adminUserSettings.internalApiUser=内部API用户
|
||||||
adminUserSettings.forceChange=强制用户在登录时更改用户名/密码
|
adminUserSettings.forceChange=强制用户在登录时更改用户名/密码
|
||||||
adminUserSettings.submit=保存用户
|
adminUserSettings.submit=保存用户
|
||||||
adminUserSettings.changeUserRole=更改用户角色
|
adminUserSettings.changeUserRole=更改用户角色
|
||||||
adminUserSettings.authenticated=Authenticated
|
adminUserSettings.authenticated=已验证
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
@ -332,13 +349,13 @@ home.compare.title=比较
|
|||||||
home.compare.desc=比较并显示两个PDF文档之间的差异
|
home.compare.desc=比较并显示两个PDF文档之间的差异
|
||||||
compare.tags=区分、对比、更改、分析
|
compare.tags=区分、对比、更改、分析
|
||||||
|
|
||||||
home.certSign.title=使用证书签署
|
home.certSign.title=使用证书签名
|
||||||
home.certSign.desc=使用证书/密钥(PEM/P12)对PDF进行签署
|
home.certSign.desc=使用证书/密钥(PEM/P12)对PDF进行签名
|
||||||
certSign.tags=身份验证、PEM、P12、官方、加密
|
certSign.tags=身份验证、PEM、P12、官方、加密
|
||||||
|
|
||||||
home.removeCertSign.title=Remove Certificate Sign
|
home.removeCertSign.title=移除证书签名
|
||||||
home.removeCertSign.desc=Remove certificate signature from PDF
|
home.removeCertSign.desc=移除PDF的证书签名
|
||||||
removeCertSign.tags=authenticate,PEM,P12,official,decrypt
|
removeCertSign.tags=身份验证、PEM、P12、官方、加密
|
||||||
|
|
||||||
home.pageLayout.title=多页布局
|
home.pageLayout.title=多页布局
|
||||||
home.pageLayout.desc=将PDF文档的多个页面合并成一页
|
home.pageLayout.desc=将PDF文档的多个页面合并成一页
|
||||||
@ -459,13 +476,13 @@ login.invalid=用户名或密码无效。
|
|||||||
login.locked=您的账户已被锁定。
|
login.locked=您的账户已被锁定。
|
||||||
login.signinTitle=请登录
|
login.signinTitle=请登录
|
||||||
login.ssoSignIn=通过单点登录登录
|
login.ssoSignIn=通过单点登录登录
|
||||||
login.oauth2AutoCreateDisabled=OAUTH2自动创建用户已禁用
|
login.oauth2AutoCreateDisabled=OAuth2自动创建用户已禁用
|
||||||
login.oauth2RequestNotFound=Authorization request not found
|
login.oauth2RequestNotFound=找不到验证请求
|
||||||
login.oauth2InvalidUserInfoResponse=Invalid User Info Response
|
login.oauth2InvalidUserInfoResponse=无效的用户信息响应
|
||||||
login.oauth2invalidRequest=Invalid Request
|
login.oauth2invalidRequest=无效请求
|
||||||
login.oauth2AccessDenied=Access Denied
|
login.oauth2AccessDenied=拒绝访问
|
||||||
login.oauth2InvalidTokenResponse=Invalid Token Response
|
login.oauth2InvalidTokenResponse=无效的Token响应
|
||||||
login.oauth2InvalidIdToken=Invalid Id Token
|
login.oauth2InvalidIdToken=无效的Token
|
||||||
|
|
||||||
|
|
||||||
#auto-redact
|
#auto-redact
|
||||||
@ -482,15 +499,15 @@ autoRedact.submitButton=提交
|
|||||||
|
|
||||||
|
|
||||||
#showJS
|
#showJS
|
||||||
showJS.title=显示 JavaScript
|
showJS.title=显示JavaScript
|
||||||
showJS.header=显示 JavaScript
|
showJS.header=显示JavaScript
|
||||||
showJS.downloadJS=下载 JavaScript
|
showJS.downloadJS=下载JavaScript
|
||||||
showJS.submit=显示
|
showJS.submit=显示
|
||||||
|
|
||||||
|
|
||||||
#pdfToSinglePage
|
#pdfToSinglePage
|
||||||
pdfToSinglePage.title=PDF转为单页
|
pdfToSinglePage.title=PDF转单页
|
||||||
pdfToSinglePage.header=PDF转为单页
|
pdfToSinglePage.header=将PDF转换为单页
|
||||||
pdfToSinglePage.submit=转为单页
|
pdfToSinglePage.submit=转为单页
|
||||||
|
|
||||||
|
|
||||||
@ -498,7 +515,7 @@ pdfToSinglePage.submit=转为单页
|
|||||||
pageExtracter.title=提取页面
|
pageExtracter.title=提取页面
|
||||||
pageExtracter.header=提取页面
|
pageExtracter.header=提取页面
|
||||||
pageExtracter.submit=提取
|
pageExtracter.submit=提取
|
||||||
pageExtracter.placeholder=(例如 1,2,8 或 4,7,12-16 或 2n-1)
|
pageExtracter.placeholder=(例如:1,2,8 或 4,7,12-16 或 2n-1)
|
||||||
|
|
||||||
|
|
||||||
#getPdfInfo
|
#getPdfInfo
|
||||||
@ -510,7 +527,7 @@ getPdfInfo.downloadJson=下载JSON
|
|||||||
|
|
||||||
#markdown-to-pdf
|
#markdown-to-pdf
|
||||||
MarkdownToPDF.title=Markdown转PDF
|
MarkdownToPDF.title=Markdown转PDF
|
||||||
MarkdownToPDF.header=Markdown转PDF
|
MarkdownToPDF.header=将Markdown转换为PDF
|
||||||
MarkdownToPDF.submit=转换
|
MarkdownToPDF.submit=转换
|
||||||
MarkdownToPDF.help=正在努力中
|
MarkdownToPDF.help=正在努力中
|
||||||
MarkdownToPDF.credit=此服务使用WeasyPrint进行文件转换。
|
MarkdownToPDF.credit=此服务使用WeasyPrint进行文件转换。
|
||||||
@ -519,14 +536,14 @@ MarkdownToPDF.credit=此服务使用WeasyPrint进行文件转换。
|
|||||||
|
|
||||||
#url-to-pdf
|
#url-to-pdf
|
||||||
URLToPDF.title=URL转PDF
|
URLToPDF.title=URL转PDF
|
||||||
URLToPDF.header=URL转PDF
|
URLToPDF.header=将URL转换为PDF
|
||||||
URLToPDF.submit=转换
|
URLToPDF.submit=转换
|
||||||
URLToPDF.credit=此服务使用WeasyPrint进行文件转换。
|
URLToPDF.credit=此服务使用WeasyPrint进行文件转换。
|
||||||
|
|
||||||
|
|
||||||
#html-to-pdf
|
#html-to-pdf
|
||||||
HTMLToPDF.title=HTML转PDF
|
HTMLToPDF.title=HTML转PDF
|
||||||
HTMLToPDF.header=HTML转PDF
|
HTMLToPDF.header=将HTML转换为PDF
|
||||||
HTMLToPDF.help=接受HTML文件和包含所需的html/css/images等的ZIP文件
|
HTMLToPDF.help=接受HTML文件和包含所需的html/css/images等的ZIP文件
|
||||||
HTMLToPDF.submit=转换
|
HTMLToPDF.submit=转换
|
||||||
HTMLToPDF.credit=此服务使用WeasyPrint进行文件转换。
|
HTMLToPDF.credit=此服务使用WeasyPrint进行文件转换。
|
||||||
@ -539,7 +556,7 @@ HTMLToPDF.marginLeft=页面左上边距-以毫米为单位(填空则使用默
|
|||||||
HTMLToPDF.marginRight=页面右边距-以毫米为单位(填空则使用默认值)
|
HTMLToPDF.marginRight=页面右边距-以毫米为单位(填空则使用默认值)
|
||||||
HTMLToPDF.printBackground=页面背景渲染
|
HTMLToPDF.printBackground=页面背景渲染
|
||||||
HTMLToPDF.defaultHeader=启用默认页头(文件名称和页码)
|
HTMLToPDF.defaultHeader=启用默认页头(文件名称和页码)
|
||||||
HTMLToPDF.cssMediaType=更换页面的CSS media type.
|
HTMLToPDF.cssMediaType=更换页面的CSS媒体类型。
|
||||||
HTMLToPDF.none=无
|
HTMLToPDF.none=无
|
||||||
HTMLToPDF.print=打印
|
HTMLToPDF.print=打印
|
||||||
HTMLToPDF.screen=屏幕
|
HTMLToPDF.screen=屏幕
|
||||||
@ -556,8 +573,8 @@ AddStampRequest.fontSize=字体/图片大小
|
|||||||
AddStampRequest.rotation=旋转角度
|
AddStampRequest.rotation=旋转角度
|
||||||
AddStampRequest.opacity=透明度
|
AddStampRequest.opacity=透明度
|
||||||
AddStampRequest.position=定位
|
AddStampRequest.position=定位
|
||||||
AddStampRequest.overrideX=覆盖 X 坐标
|
AddStampRequest.overrideX=覆盖X坐标
|
||||||
AddStampRequest.overrideY=覆盖 Y 坐标
|
AddStampRequest.overrideY=覆盖Y坐标
|
||||||
AddStampRequest.customMargin=自定义外边距
|
AddStampRequest.customMargin=自定义外边距
|
||||||
AddStampRequest.customColor=自定义文本颜色
|
AddStampRequest.customColor=自定义文本颜色
|
||||||
AddStampRequest.submit=提交
|
AddStampRequest.submit=提交
|
||||||
@ -647,27 +664,27 @@ scalePages.submit=提交
|
|||||||
|
|
||||||
#certSign
|
#certSign
|
||||||
certSign.title=证书签名
|
certSign.title=证书签名
|
||||||
certSign.header=使用您的证书签署 PDF(进行中)
|
certSign.header=使用您的证书签名PDF(进行中)
|
||||||
certSign.selectPDF=选择要签名的 PDF 文件:
|
certSign.selectPDF=选择要签名的PDF文件:
|
||||||
certSign.jksNote=注意:如果您的证书类型未在下面列出,请使用 keytool 命令行工具将其转换为 Java Keystore (.jks) 文件。 然后,选择下面的 .jks 文件选项。
|
certSign.jksNote=注意:如果您的证书类型未在下面列出,请使用keytool命令行工具将其转换为Java Keystore(.jks)文件。 然后,选择下面的.jks文件选项。
|
||||||
certSign.selectKey=选择您的私钥文件(PKCS#8 格式,可以是 .pem 或 .der):
|
certSign.selectKey=选择您的私钥文件(PKCS#8格式,可以是.pem或.der):
|
||||||
certSign.selectCert=选择您的证书文件(X.509 格式,可以是 .pem 或 .der):
|
certSign.selectCert=选择您的证书文件(X.509格式,可以是.pem或.der):
|
||||||
certSign.selectP12=选择您的 PKCS#12 密钥库文件(.p12 或 .pfx)(可选,如果提供,它应该包含您的私钥和证书):
|
certSign.selectP12=选择您的PKCS#12密钥库文件(.p12或.pfx)(可选,如果提供,它应该包含您的私钥和证书):
|
||||||
certSign.selectJKS=选择你的 Java Keystore 文件 (.jks 或 .keystore):
|
certSign.selectJKS=选择你的Java Keystore文件 (.jks或.keystore):
|
||||||
certSign.certType=证书类型
|
certSign.certType=证书类型
|
||||||
certSign.password=输入您的密钥库或私钥密码(如果有):
|
certSign.password=输入您的密钥库或私钥密码(如果有):
|
||||||
certSign.showSig=显示签名
|
certSign.showSig=显示签名
|
||||||
certSign.reason=原因
|
certSign.reason=原因
|
||||||
certSign.location=位置
|
certSign.location=位置
|
||||||
certSign.name=名称
|
certSign.name=名称
|
||||||
certSign.submit=签署 PDF
|
certSign.submit=给PDF签名
|
||||||
|
|
||||||
|
|
||||||
#removeCertSign
|
#removeCertSign
|
||||||
removeCertSign.title=Remove Certificate Signature
|
removeCertSign.title=移除证书签名
|
||||||
removeCertSign.header=Remove the digital certificate from the PDF
|
removeCertSign.header=移除PDF的证书签名
|
||||||
removeCertSign.selectPDF=Select a PDF file:
|
removeCertSign.selectPDF=选择PDF文件:
|
||||||
removeCertSign.submit=Remove Signature
|
removeCertSign.submit=移除签名
|
||||||
|
|
||||||
|
|
||||||
#removeBlanks
|
#removeBlanks
|
||||||
@ -688,7 +705,9 @@ removeAnnotations.submit=删除
|
|||||||
|
|
||||||
#compare
|
#compare
|
||||||
compare.title=比较
|
compare.title=比较
|
||||||
compare.header=比较 PDF
|
compare.header=比较PDF
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=文档 1
|
compare.document.1=文档 1
|
||||||
compare.document.2=文档 2
|
compare.document.2=文档 2
|
||||||
compare.submit=比较
|
compare.submit=比较
|
||||||
@ -718,14 +737,14 @@ sign.add=添加
|
|||||||
|
|
||||||
#repair
|
#repair
|
||||||
repair.title=修复
|
repair.title=修复
|
||||||
repair.header=修复 PDF
|
repair.header=修复PDF
|
||||||
repair.submit=修复
|
repair.submit=修复
|
||||||
|
|
||||||
|
|
||||||
#flatten
|
#flatten
|
||||||
flatten.title=展平
|
flatten.title=展平
|
||||||
flatten.header=展平 PDF
|
flatten.header=展平 PDF
|
||||||
flatten.flattenOnlyForms=Flatten only forms
|
flatten.flattenOnlyForms=仅展平表格
|
||||||
flatten.submit=展平
|
flatten.submit=展平
|
||||||
|
|
||||||
|
|
||||||
@ -752,7 +771,7 @@ ocr.selectText.4=清理页面,降低OCR在噪点中识别到文本的可能。
|
|||||||
ocr.selectText.5=清洁页面,降低OCR在噪点中识别到文本的可能,保持输出的清洁。
|
ocr.selectText.5=清洁页面,降低OCR在噪点中识别到文本的可能,保持输出的清洁。
|
||||||
ocr.selectText.6=忽略有交互式文本的页面,只对有图像的页面进行OCR。
|
ocr.selectText.6=忽略有交互式文本的页面,只对有图像的页面进行OCR。
|
||||||
ocr.selectText.7=强制OCR,将OCR每个页面,删除所有的原始文本元素。
|
ocr.selectText.7=强制OCR,将OCR每个页面,删除所有的原始文本元素。
|
||||||
ocr.selectText.8=Normal (如果PDF包含文本,将出现错误)
|
ocr.selectText.8=正常 (如果PDF包含文本,将出现错误)
|
||||||
ocr.selectText.9=额外设置
|
ocr.selectText.9=额外设置
|
||||||
ocr.selectText.10=OCR模式
|
ocr.selectText.10=OCR模式
|
||||||
ocr.selectText.11=OCR后移除图像(移除所有图像,只有在转换步骤中才有用)。
|
ocr.selectText.11=OCR后移除图像(移除所有图像,只有在转换步骤中才有用)。
|
||||||
@ -773,7 +792,7 @@ extractImages.submit=提取
|
|||||||
fileToPDF.title=文件转换为PDF
|
fileToPDF.title=文件转换为PDF
|
||||||
fileToPDF.header=将任何文件转换为PDF。
|
fileToPDF.header=将任何文件转换为PDF。
|
||||||
fileToPDF.credit=此服务使用LibreOffice和Unoconv进行文件转换。
|
fileToPDF.credit=此服务使用LibreOffice和Unoconv进行文件转换。
|
||||||
fileToPDF.supportedFileTypesInfo=Supported File types
|
fileToPDF.supportedFileTypesInfo=支持的文件类型
|
||||||
fileToPDF.supportedFileTypes=支持的文件类型应该包括以下几种,但是,对于支持的格式的完整更新列表,请参考LibreOffice文档。
|
fileToPDF.supportedFileTypes=支持的文件类型应该包括以下几种,但是,对于支持的格式的完整更新列表,请参考LibreOffice文档。
|
||||||
fileToPDF.submit=转换为 PDF
|
fileToPDF.submit=转换为 PDF
|
||||||
|
|
||||||
@ -781,12 +800,12 @@ fileToPDF.submit=转换为 PDF
|
|||||||
#compress
|
#compress
|
||||||
compress.title=压缩
|
compress.title=压缩
|
||||||
compress.header=压缩PDF
|
compress.header=压缩PDF
|
||||||
compress.credit=此服务使用 Ghostscript 进行 PDF 压缩/优化。
|
compress.credit=此服务使用Ghostscript进行PDF压缩/优化。
|
||||||
compress.selectText.1=手动模式 - 从 1 到 4
|
compress.selectText.1=手动模式 - 从 1 到 4
|
||||||
compress.selectText.2=优化级别:
|
compress.selectText.2=优化级别:
|
||||||
compress.selectText.3=4(文本图像很糟糕)
|
compress.selectText.3=4(文本图像很糟糕)
|
||||||
compress.selectText.4=自动模式 - 自动调整质量以获得精确大小的 PDF
|
compress.selectText.4=自动模式 - 自动调整质量以获得精确大小的PDF
|
||||||
compress.selectText.5=预期 PDF 大小(例如 25MB、10.8MB、25KB)
|
compress.selectText.5=预期PDF大小(例如:25MB、10.8MB、25KB)
|
||||||
compress.submit=压缩
|
compress.submit=压缩
|
||||||
|
|
||||||
|
|
||||||
@ -803,7 +822,7 @@ merge.title=合并
|
|||||||
merge.header=合并多个PDF(2个以上)。
|
merge.header=合并多个PDF(2个以上)。
|
||||||
merge.sortByName=按名称排序
|
merge.sortByName=按名称排序
|
||||||
merge.sortByDate=按日期排序
|
merge.sortByDate=按日期排序
|
||||||
merge.removeCertSign=Remove digital signature in the merged file?
|
merge.removeCertSign=删除合并文件的数字签名吗?
|
||||||
merge.submit=合并
|
merge.submit=合并
|
||||||
|
|
||||||
|
|
||||||
@ -821,8 +840,8 @@ pdfOrganiser.mode.6=奇偶拆分
|
|||||||
pdfOrganiser.mode.7=删除第一页
|
pdfOrganiser.mode.7=删除第一页
|
||||||
pdfOrganiser.mode.8=删除最后一页
|
pdfOrganiser.mode.8=删除最后一页
|
||||||
pdfOrganiser.mode.9=删除第一页和最后一页
|
pdfOrganiser.mode.9=删除第一页和最后一页
|
||||||
pdfOrganiser.mode.10=Odd-Even Merge
|
pdfOrganiser.mode.10=奇偶合并
|
||||||
pdfOrganiser.placeholder=(例如 1,3,2 或 4-8,2,10-12 或 2n-1)
|
pdfOrganiser.placeholder=(例如:1,3,2 或 4-8,2,10-12 或 2n-1)
|
||||||
|
|
||||||
|
|
||||||
#multiTool
|
#multiTool
|
||||||
@ -839,7 +858,7 @@ pageRemover.title=删除页面
|
|||||||
pageRemover.header=PDF页面移除器
|
pageRemover.header=PDF页面移除器
|
||||||
pageRemover.pagesToDelete=要删除的页面(输入一个用逗号分隔的页码列表):
|
pageRemover.pagesToDelete=要删除的页面(输入一个用逗号分隔的页码列表):
|
||||||
pageRemover.submit=删除页面
|
pageRemover.submit=删除页面
|
||||||
pageRemover.placeholder=(例如 1,2,6 或 1-10,15-30)
|
pageRemover.placeholder=(例如:1,2,6 或 1-10,15-30)
|
||||||
|
|
||||||
|
|
||||||
#rotate
|
#rotate
|
||||||
@ -866,7 +885,7 @@ split.submit=拆分
|
|||||||
|
|
||||||
#merge
|
#merge
|
||||||
imageToPDF.title=图片转PDF
|
imageToPDF.title=图片转PDF
|
||||||
imageToPDF.header=图像转为PDF
|
imageToPDF.header=将图片转换为PDF
|
||||||
imageToPDF.submit=转换
|
imageToPDF.submit=转换
|
||||||
imageToPDF.selectLabel=图片适应选项
|
imageToPDF.selectLabel=图片适应选项
|
||||||
imageToPDF.fillPage=填充页面
|
imageToPDF.fillPage=填充页面
|
||||||
@ -880,7 +899,7 @@ imageToPDF.selectText.5=转换为独立的PDF文件
|
|||||||
|
|
||||||
#pdfToImage
|
#pdfToImage
|
||||||
pdfToImage.title=PDF转图片
|
pdfToImage.title=PDF转图片
|
||||||
pdfToImage.header=PDF转图片
|
pdfToImage.header=将PDF转换为图片
|
||||||
pdfToImage.selectText=图像格式
|
pdfToImage.selectText=图像格式
|
||||||
pdfToImage.singleOrMultiple=图像结果类型
|
pdfToImage.singleOrMultiple=图像结果类型
|
||||||
pdfToImage.single=单张图片
|
pdfToImage.single=单张图片
|
||||||
@ -976,55 +995,55 @@ changeMetadata.submit=更改
|
|||||||
|
|
||||||
|
|
||||||
#pdfToPDFA
|
#pdfToPDFA
|
||||||
pdfToPDFA.title=将PDF转换为PDF/A
|
pdfToPDFA.title=PDF转PDF/A
|
||||||
pdfToPDFA.header=PDF转换为PDF/A
|
pdfToPDFA.header=将PDF转换为PDF/A
|
||||||
pdfToPDFA.credit=此服务使用OCRmyPDF进行PDF/A转换
|
pdfToPDFA.credit=此服务使用OCRmyPDF进行PDF/A转换
|
||||||
pdfToPDFA.submit=转换
|
pdfToPDFA.submit=转换
|
||||||
pdfToPDFA.tip=目前不支持上传多个
|
pdfToPDFA.tip=目前不支持上传多个
|
||||||
pdfToPDFA.outputFormat=Output format
|
pdfToPDFA.outputFormat=输出格式
|
||||||
pdfToPDFA.pdfWithDigitalSignature=The PDF contains a digital signature. This will be removed in the next step.
|
pdfToPDFA.pdfWithDigitalSignature=该PDF包含数字签名,下一步将移除该签名。
|
||||||
|
|
||||||
|
|
||||||
#PDFToWord
|
#PDFToWord
|
||||||
PDFToWord.title=PDF to Word
|
PDFToWord.title=PDF转Word
|
||||||
PDFToWord.header=将PDF转换成Word
|
PDFToWord.header=将PDF转换为Word
|
||||||
PDFToWord.selectText.1=输出文件格式
|
PDFToWord.selectText.1=输出文件格式
|
||||||
PDFToWord.credit=此服务使用LibreOffice进行文件转换。
|
PDFToWord.credit=此服务使用LibreOffice进行文件转换。
|
||||||
PDFToWord.submit=转换
|
PDFToWord.submit=转换
|
||||||
|
|
||||||
|
|
||||||
#PDFToPresentation
|
#PDFToPresentation
|
||||||
PDFToPresentation.title=PDF转换为演示文稿
|
PDFToPresentation.title=PDF转演示文稿
|
||||||
PDFToPresentation.header=将PDF转为演示文稿
|
PDFToPresentation.header=将PDF转换为演示文稿
|
||||||
PDFToPresentation.selectText.1=输出文件格式
|
PDFToPresentation.selectText.1=输出文件格式
|
||||||
PDFToPresentation.credit=此服务使用LibreOffice进行文件转换。
|
PDFToPresentation.credit=此服务使用LibreOffice进行文件转换。
|
||||||
PDFToPresentation.submit=转换
|
PDFToPresentation.submit=转换
|
||||||
|
|
||||||
|
|
||||||
#PDFToText
|
#PDFToText
|
||||||
PDFToText.title=PDF to RTF (Text)
|
PDFToText.title=PDF转文本/RTF
|
||||||
PDFToText.header=将PDF转换成文本/RTF
|
PDFToText.header=将PDF转换为文本/RTF
|
||||||
PDFToText.selectText.1=输出文件格式
|
PDFToText.selectText.1=输出文件格式
|
||||||
PDFToText.credit=此服务使用LibreOffice进行文件转换。
|
PDFToText.credit=此服务使用LibreOffice进行文件转换。
|
||||||
PDFToText.submit=转换
|
PDFToText.submit=转换
|
||||||
|
|
||||||
|
|
||||||
#PDFToHTML
|
#PDFToHTML
|
||||||
PDFToHTML.title=PDF To HTML
|
PDFToHTML.title=PDF转HTML
|
||||||
PDFToHTML.header=将PDF转换成HTML
|
PDFToHTML.header=将PDF转换为HTML
|
||||||
PDFToHTML.credit=此服务使用pdftohtml进行文件转换。
|
PDFToHTML.credit=此服务使用pdftohtml进行文件转换。
|
||||||
PDFToHTML.submit=转换
|
PDFToHTML.submit=转换
|
||||||
|
|
||||||
|
|
||||||
#PDFToXML
|
#PDFToXML
|
||||||
PDFToXML.title=PDF To XML
|
PDFToXML.title=PDF转XML
|
||||||
PDFToXML.header=将PDF转换为XML
|
PDFToXML.header=将PDF转换为XML
|
||||||
PDFToXML.credit=此服务使用LibreOffice进行文件转换。
|
PDFToXML.credit=此服务使用LibreOffice进行文件转换。
|
||||||
PDFToXML.submit=转换
|
PDFToXML.submit=转换
|
||||||
|
|
||||||
#PDFToCSV
|
#PDFToCSV
|
||||||
PDFToCSV.title=PDF To CSV
|
PDFToCSV.title=PDF转CSV
|
||||||
PDFToCSV.header=将 PDF 转换为 CSV
|
PDFToCSV.header=将PDF转换为CSV
|
||||||
PDFToCSV.prompt=选择需要提取表格的页面
|
PDFToCSV.prompt=选择需要提取表格的页面
|
||||||
PDFToCSV.submit=提取
|
PDFToCSV.submit=提取
|
||||||
|
|
||||||
@ -1036,7 +1055,7 @@ split-by-size-or-count.type.size=按照大小
|
|||||||
split-by-size-or-count.type.pageCount=按照页数
|
split-by-size-or-count.type.pageCount=按照页数
|
||||||
split-by-size-or-count.type.docCount=按照文档数
|
split-by-size-or-count.type.docCount=按照文档数
|
||||||
split-by-size-or-count.value.label=输入数值
|
split-by-size-or-count.value.label=输入数值
|
||||||
split-by-size-or-count.value.placeholder=输入大小(例如,2MB或3KB)或数目(例如,5)
|
split-by-size-or-count.value.placeholder=输入大小(例如:2MB或3KB)或数目(例如:5)
|
||||||
split-by-size-or-count.submit=提交
|
split-by-size-or-count.submit=提交
|
||||||
|
|
||||||
|
|
||||||
@ -1049,7 +1068,7 @@ overlay-pdfs.mode.sequential=按顺序叠加
|
|||||||
overlay-pdfs.mode.interleaved=交错叠加
|
overlay-pdfs.mode.interleaved=交错叠加
|
||||||
overlay-pdfs.mode.fixedRepeat=固定重复叠加
|
overlay-pdfs.mode.fixedRepeat=固定重复叠加
|
||||||
overlay-pdfs.counts.label=叠加次数(仅限固定重复叠加模式)
|
overlay-pdfs.counts.label=叠加次数(仅限固定重复叠加模式)
|
||||||
overlay-pdfs.counts.placeholder=输入用逗号分隔的次数(例如,2,3,1)
|
overlay-pdfs.counts.placeholder=输入用逗号分隔的次数(例如:2,3,1)
|
||||||
overlay-pdfs.position.label=选择叠加位置
|
overlay-pdfs.position.label=选择叠加位置
|
||||||
overlay-pdfs.position.foreground=前面(上面)
|
overlay-pdfs.position.foreground=前面(上面)
|
||||||
overlay-pdfs.position.background=后面(下面)
|
overlay-pdfs.position.background=后面(下面)
|
||||||
@ -1068,11 +1087,11 @@ split-by-sections.merge=是否合并为一个pdf
|
|||||||
|
|
||||||
|
|
||||||
#printFile
|
#printFile
|
||||||
printFile.title=Print File
|
printFile.title=打印文件
|
||||||
printFile.header=Print File to Printer
|
printFile.header=使用打印机打印文件
|
||||||
printFile.selectText.1=Select File to Print
|
printFile.selectText.1=选择要打印的文件
|
||||||
printFile.selectText.2=Enter Printer Name
|
printFile.selectText.2=输入打印机名称
|
||||||
printFile.submit=Print
|
printFile.submit=打印
|
||||||
|
|
||||||
|
|
||||||
#licenses
|
#licenses
|
||||||
@ -1084,13 +1103,13 @@ licenses.version=版本
|
|||||||
licenses.license=许可证
|
licenses.license=许可证
|
||||||
|
|
||||||
#survey
|
#survey
|
||||||
survey.nav=Survey
|
survey.nav=调查
|
||||||
survey.title=Stirling-PDF Survey
|
survey.title=Stirling-PDF调查
|
||||||
survey.description=Stirling-PDF has no tracking so we want to hear from our users to improve Stirling-PDF!
|
survey.description=Stirling-PDF没有跟踪器,所以我们希望听取用户的意见来改进Stirling-PDF!
|
||||||
survey.please=Please consider taking our survey!
|
survey.please=请考虑参加我们的调查!
|
||||||
survey.disabled=(Survey popup will be disabled in following updates but available at foot of page)
|
survey.disabled=(调查弹出窗口将在后续更新中被禁用,但可在页脚处查看)
|
||||||
survey.button=Take Survey
|
survey.button=参与调查
|
||||||
survey.dontShowAgain=Don't show again
|
survey.dontShowAgain=不再显示
|
||||||
|
|
||||||
|
|
||||||
#error
|
#error
|
||||||
|
@ -191,6 +191,23 @@ adminUserSettings.submit=儲存
|
|||||||
adminUserSettings.changeUserRole=更改使用者身份
|
adminUserSettings.changeUserRole=更改使用者身份
|
||||||
adminUserSettings.authenticated=已驗證
|
adminUserSettings.authenticated=已驗證
|
||||||
|
|
||||||
|
|
||||||
|
database.title=Database Import/Export
|
||||||
|
database.header=Database Import/Export
|
||||||
|
database.fileName=File Name
|
||||||
|
database.creationDate=Creation Date
|
||||||
|
database.fileSize=File Size
|
||||||
|
database.deleteBackupFile=Delete Backup File
|
||||||
|
database.importBackupFile=Import Backup File
|
||||||
|
database.downloadBackupFile=Download Backup File
|
||||||
|
database.info_1=When importing data, it is crucial to ensure the correct structure. If you are unsure of what you are doing, seek advice and support from a professional. An error in the structure can cause application malfunctions, up to and including the complete inability to run the application.
|
||||||
|
database.info_2=The file name does not matter when uploading. It will be renamed afterward to follow the format backup_user_yyyyMMddHHmm.sql, ensuring a consistent naming convention.
|
||||||
|
database.submit=Import Backup
|
||||||
|
database.importIntoDatabaseSuccessed=Import into database successed
|
||||||
|
database.fileNotFound=File not Found
|
||||||
|
database.fileNullOrEmpty=File must not be null or empty
|
||||||
|
database.failedImportFile=Failed Import File
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# HOME-PAGE #
|
# HOME-PAGE #
|
||||||
#############
|
#############
|
||||||
@ -689,6 +706,8 @@ removeAnnotations.submit=移除
|
|||||||
#compare
|
#compare
|
||||||
compare.title=比較
|
compare.title=比較
|
||||||
compare.header=比較 PDF
|
compare.header=比較 PDF
|
||||||
|
compare.highlightColor.1=Highlight Color 1:
|
||||||
|
compare.highlightColor.2=Highlight Color 2:
|
||||||
compare.document.1=文件 1
|
compare.document.1=文件 1
|
||||||
compare.document.2=文件 2
|
compare.document.2=文件 2
|
||||||
compare.submit=比較
|
compare.submit=比較
|
||||||
|
@ -176,19 +176,19 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.twelvemonkeys.common:common-image",
|
"moduleName": "com.twelvemonkeys.common:common-image",
|
||||||
"moduleVersion": "3.10.1",
|
"moduleVersion": "3.11.0",
|
||||||
"moduleLicense": "The BSD License",
|
"moduleLicense": "The BSD License",
|
||||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.twelvemonkeys.common:common-io",
|
"moduleName": "com.twelvemonkeys.common:common-io",
|
||||||
"moduleVersion": "3.10.1",
|
"moduleVersion": "3.11.0",
|
||||||
"moduleLicense": "The BSD License",
|
"moduleLicense": "The BSD License",
|
||||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.twelvemonkeys.common:common-lang",
|
"moduleName": "com.twelvemonkeys.common:common-lang",
|
||||||
"moduleVersion": "3.10.1",
|
"moduleVersion": "3.11.0",
|
||||||
"moduleLicense": "The BSD License",
|
"moduleLicense": "The BSD License",
|
||||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||||
},
|
},
|
||||||
@ -206,19 +206,19 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.twelvemonkeys.imageio:imageio-core",
|
"moduleName": "com.twelvemonkeys.imageio:imageio-core",
|
||||||
"moduleVersion": "3.10.1",
|
"moduleVersion": "3.11.0",
|
||||||
"moduleLicense": "The BSD License",
|
"moduleLicense": "The BSD License",
|
||||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.twelvemonkeys.imageio:imageio-jpeg",
|
"moduleName": "com.twelvemonkeys.imageio:imageio-jpeg",
|
||||||
"moduleVersion": "3.10.1",
|
"moduleVersion": "3.11.0",
|
||||||
"moduleLicense": "The BSD License",
|
"moduleLicense": "The BSD License",
|
||||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "com.twelvemonkeys.imageio:imageio-metadata",
|
"moduleName": "com.twelvemonkeys.imageio:imageio-metadata",
|
||||||
"moduleVersion": "3.10.1",
|
"moduleVersion": "3.11.0",
|
||||||
"moduleLicense": "The BSD License",
|
"moduleLicense": "The BSD License",
|
||||||
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
"moduleLicenseUrl": "https://github.com/haraldk/TwelveMonkeys#license"
|
||||||
},
|
},
|
||||||
@ -313,21 +313,21 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "io.swagger.core.v3:swagger-annotations-jakarta",
|
"moduleName": "io.swagger.core.v3:swagger-annotations-jakarta",
|
||||||
"moduleUrl": "https://github.com/swagger-api/swagger-core/modules/swagger-annotations",
|
"moduleUrl": "https://github.com/swagger-api/swagger-core/modules/swagger-annotations",
|
||||||
"moduleVersion": "2.2.21",
|
"moduleVersion": "2.2.15",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "io.swagger.core.v3:swagger-core-jakarta",
|
"moduleName": "io.swagger.core.v3:swagger-core-jakarta",
|
||||||
"moduleUrl": "https://github.com/swagger-api/swagger-core/modules/swagger-core",
|
"moduleUrl": "https://github.com/swagger-api/swagger-core/modules/swagger-core",
|
||||||
"moduleVersion": "2.2.21",
|
"moduleVersion": "2.2.15",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "io.swagger.core.v3:swagger-models-jakarta",
|
"moduleName": "io.swagger.core.v3:swagger-models-jakarta",
|
||||||
"moduleUrl": "https://github.com/swagger-api/swagger-core/modules/swagger-models",
|
"moduleUrl": "https://github.com/swagger-api/swagger-core/modules/swagger-models",
|
||||||
"moduleVersion": "2.2.21",
|
"moduleVersion": "2.2.15",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
@ -859,19 +859,19 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springdoc:springdoc-openapi-starter-common",
|
"moduleName": "org.springdoc:springdoc-openapi-starter-common",
|
||||||
"moduleVersion": "2.5.0",
|
"moduleVersion": "2.2.0",
|
||||||
"moduleLicense": "The Apache License, Version 2.0",
|
"moduleLicense": "The Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springdoc:springdoc-openapi-starter-webmvc-api",
|
"moduleName": "org.springdoc:springdoc-openapi-starter-webmvc-api",
|
||||||
"moduleVersion": "2.5.0",
|
"moduleVersion": "2.2.0",
|
||||||
"moduleLicense": "The Apache License, Version 2.0",
|
"moduleLicense": "The Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"moduleName": "org.springdoc:springdoc-openapi-starter-webmvc-ui",
|
"moduleName": "org.springdoc:springdoc-openapi-starter-webmvc-ui",
|
||||||
"moduleVersion": "2.5.0",
|
"moduleVersion": "2.2.0",
|
||||||
"moduleLicense": "The Apache License, Version 2.0",
|
"moduleLicense": "The Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
|
||||||
},
|
},
|
||||||
@ -1137,7 +1137,7 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "org.springframework:spring-webmvc",
|
"moduleName": "org.springframework:spring-webmvc",
|
||||||
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
"moduleUrl": "https://github.com/spring-projects/spring-framework",
|
||||||
"moduleVersion": "6.1.8",
|
"moduleVersion": "6.1.9",
|
||||||
"moduleLicense": "Apache License, Version 2.0",
|
"moduleLicense": "Apache License, Version 2.0",
|
||||||
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
|
||||||
},
|
},
|
||||||
@ -1175,7 +1175,7 @@
|
|||||||
{
|
{
|
||||||
"moduleName": "org.webjars:swagger-ui",
|
"moduleName": "org.webjars:swagger-ui",
|
||||||
"moduleUrl": "http://webjars.org",
|
"moduleUrl": "http://webjars.org",
|
||||||
"moduleVersion": "5.13.0",
|
"moduleVersion": "5.2.0",
|
||||||
"moduleLicense": "Apache 2.0",
|
"moduleLicense": "Apache 2.0",
|
||||||
"moduleLicenseUrl": "https://github.com/swagger-api/swagger-ui"
|
"moduleLicenseUrl": "https://github.com/swagger-api/swagger-ui"
|
||||||
},
|
},
|
||||||
|
@ -1,8 +1,3 @@
|
|||||||
p {
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 2em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.features-container {
|
.features-container {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fill, minmax(21rem, 3fr));
|
grid-template-columns: repeat(auto-fill, minmax(21rem, 3fr));
|
||||||
|
@ -3,12 +3,12 @@
|
|||||||
"short_name": "Stirling-PDF",
|
"short_name": "Stirling-PDF",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/android-icon-192x192.png",
|
"src": "/android-chrome-192x192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/android-icon-512x512.png",
|
"src": "/android-chrome-512x512.png",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,17 @@
|
|||||||
{
|
{
|
||||||
"name": "Stirling PDF",
|
"name": "Stirling-PDF",
|
||||||
"short_name": "Stirling PDF",
|
"short_name": "Stirling-PDF",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/android-chrome-192x192.png",
|
"src": "/android-chrome-192x192.png",
|
||||||
"sizes": "192x192",
|
"sizes": "192x192",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "/android-chrome-512x512.png",
|
"src": "/android-chrome-512x512.png",
|
||||||
"sizes": "512x512",
|
"sizes": "512x512",
|
||||||
"type": "image/png"
|
"type": "image/png"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"theme_color": "#ffffff",
|
"theme_color": "#ffffff",
|
||||||
"background_color": "#ffffff",
|
"background_color": "#ffffff",
|
||||||
|
@ -13,9 +13,12 @@
|
|||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-9 bg-card">
|
<div class="col-md-9 bg-card">
|
||||||
|
<div class="tool-header">
|
||||||
|
<span class="material-symbols-rounded tool-header-icon organize">settings_account_box</span>
|
||||||
|
<span class="tool-header-text" th:text="#{account.accountSettings}">User Settings</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- User Settings Title -->
|
<!-- User Settings Title -->
|
||||||
<h2 class="text-center" th:text="#{account.accountSettings}">User Settings</h2>
|
|
||||||
<th:block th:if="${messageType}">
|
<th:block th:if="${messageType}">
|
||||||
<div class="alert alert-danger">
|
<div class="alert alert-danger">
|
||||||
<span th:text="#{${messageType}}">Default message if not found</span>
|
<span th:text="#{${messageType}}">Default message if not found</span>
|
||||||
@ -247,9 +250,9 @@
|
|||||||
<table id="settingsTable" class="table table-bordered table-sm table-striped">
|
<table id="settingsTable" class="table table-bordered table-sm table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th th:text="#{account.property}">Property</th>
|
<th scope="col" th:text="#{account.property}">Property</th>
|
||||||
<th th:text="#{account.accountSettings}">Account Setting</th>
|
<th scope="col" th:text="#{account.accountSettings}">Account Setting</th>
|
||||||
<th th:text="#{account.webBrowserSettings}">Web Browser Setting</th>
|
<th scope="col" th:text="#{account.webBrowserSettings}">Web Browser Setting</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -12,10 +12,13 @@
|
|||||||
<br><br>
|
<br><br>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-8 bg-card">
|
<div class="col-md-9 bg-card">
|
||||||
|
<div class="tool-header">
|
||||||
|
<span class="material-symbols-rounded tool-header-icon organize">manage_accounts</span>
|
||||||
|
<span class="tool-header-text" th:text="#{adminUserSettings.header}">Admin User Control Settings</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- User Settings Title -->
|
<!-- User Settings Title -->
|
||||||
<h2 class="text-center" th:text="#{adminUserSettings.header}">Admin User Control Settings</h2>
|
|
||||||
<div style="background: var(--md-sys-color-outline-variant);padding: .8rem; margin: 10px 0; border-radius: 2rem; text-align: center;">
|
<div style="background: var(--md-sys-color-outline-variant);padding: .8rem; margin: 10px 0; border-radius: 2rem; text-align: center;">
|
||||||
<a href="#" data-bs-toggle="modal" data-bs-target="#addUserModal" class="btn btn-outline-info" th:title="#{adminUserSettings.addUser}">
|
<a href="#" data-bs-toggle="modal" data-bs-target="#addUserModal" class="btn btn-outline-info" th:title="#{adminUserSettings.addUser}">
|
||||||
<span class="material-symbols-rounded">person_add</span>
|
<span class="material-symbols-rounded">person_add</span>
|
||||||
@ -29,35 +32,39 @@
|
|||||||
<div th:if="${deleteMessage}" class="alert alert-danger">
|
<div th:if="${deleteMessage}" class="alert alert-danger">
|
||||||
<span th:text="#{${deleteMessage}}">Message</span>
|
<span th:text="#{${deleteMessage}}">Message</span>
|
||||||
</div>
|
</div>
|
||||||
<table class="table">
|
<div class="bg-card mt-3 mb-3">
|
||||||
<thead>
|
<table class="table table-striped table-hover">
|
||||||
<tr>
|
<thead>
|
||||||
<th th:text="#{username}">Username</th>
|
<tr>
|
||||||
<th th:text="#{adminUserSettings.roles}">Roles</th>
|
<th scope="col">UID</th>
|
||||||
<th th:text="#{adminUserSettings.actions}">Actions</th>
|
<th scope="col" th:text="#{username}">Username</th>
|
||||||
<th th:text="#{adminUserSettings.authenticated}">Authenticated</th>
|
<th scope="col" th:text="#{adminUserSettings.roles}">Roles</th>
|
||||||
</tr>
|
<th scope="col" th:text="#{adminUserSettings.actions}">Actions</th>
|
||||||
</thead>
|
<th scope="col" th:text="#{adminUserSettings.authenticated}">Authenticated</th>
|
||||||
<tbody>
|
</tr>
|
||||||
<tr th:each="user : ${users}">
|
</thead>
|
||||||
<td style="align-content: center;" th:text="${user.username}"></td>
|
<tbody>
|
||||||
<td style="align-content: center;" th:text="#{${user.roleName}}"></td>
|
<tr th:each="user : ${users}">
|
||||||
<td style="align-content: center;">
|
<th scope="row" style="align-content: center;" th:text="${user.id}"></th>
|
||||||
<form th:if="${user.username != currentUsername}" th:action="@{'/api/v1/user/admin/deleteUser/' + ${user.username}}" method="post" onsubmit="return confirmDelete()">
|
<td style="align-content: center;" th:text="${user.username}"></td>
|
||||||
<button type="submit" th:title="#{adminUserSettings.deleteUser}" class="btn btn-info"><span class="material-symbols-rounded">person_remove</span></button>
|
<td style="align-content: center;" th:text="#{${user.roleName}}"></td>
|
||||||
</form>
|
<td style="align-content: center;">
|
||||||
<script th:inline="javascript">
|
<form th:if="${user.username != currentUsername}" th:action="@{'/api/v1/user/admin/deleteUser/' + ${user.username}}" method="post" onsubmit="return confirmDelete()">
|
||||||
const confirm_text = /*[[#{adminUserSettings.confirmDeleteUser}]]*/ 'Should the user be deleted?';
|
<button type="submit" th:title="#{adminUserSettings.deleteUser}" class="btn btn-info"><span class="material-symbols-rounded">person_remove</span></button>
|
||||||
function confirmDelete() {
|
</form>
|
||||||
return confirm(confirm_text);
|
<a th:if="${user.username == currentUsername}" th:href="@{'/account'}" class="btn btn-outline-info"><span class="material-symbols-rounded">edit</span></a>
|
||||||
}
|
</td>
|
||||||
</script>
|
<td style="align-content: center;" th:text="${user.authenticationType}"></td>
|
||||||
<a th:if="${user.username == currentUsername}" th:href="@{'/account'}" class="btn btn-outline-info"><span class="material-symbols-rounded">edit</span></a>
|
</tr>
|
||||||
</td>
|
</tbody>
|
||||||
<td style="align-content: center;" th:text="${user.authenticationType}"></td>
|
</table>
|
||||||
</tr>
|
</div>
|
||||||
</tbody>
|
<script th:inline="javascript">
|
||||||
</table>
|
const confirm_text = /*[[#{adminUserSettings.confirmDeleteUser}]]*/ 'Should the user be deleted?';
|
||||||
|
function confirmDelete() {
|
||||||
|
return confirm(confirm_text);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
71
src/main/resources/templates/database.html
Normal file
71
src/main/resources/templates/database.html
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html th:lang="${#locale.language}" th:dir="#{language.direction}" th:data-language="${#locale.toString()}" xmlns:th="https://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<th:block th:insert="~{fragments/common :: head(title=#{database.title}, header=#{database.header})}"></th:block>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div id="page-container">
|
||||||
|
<div id="content-wrap">
|
||||||
|
<th:block th:insert="~{fragments/navbar.html :: navbar}"></th:block>
|
||||||
|
<br><br>
|
||||||
|
<div class="container">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-9 bg-card">
|
||||||
|
<div class="tool-header">
|
||||||
|
<span class="material-symbols-rounded tool-header-icon organize">database</span>
|
||||||
|
<span class="tool-header-text" text="#{database.title}">Database Im-/Export</span>
|
||||||
|
</div>
|
||||||
|
<p th:if="${error}" th:text="#{'database.' + ${error}}" class="alert alert-danger text-center"></p>
|
||||||
|
<p th:if="${infoMessage}" th:text="#{'database.' + ${infoMessage}}" class="alert alert-success text-center"></p>
|
||||||
|
<div class="bg-card mt-3 mb-3">
|
||||||
|
<table class="table table-striped table-hover mb-0">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th scope="col" th:text="#{database.fileName}">File Name</th>
|
||||||
|
<th scope="col" th:text="#{database.creationDate}">Creation Date</th>
|
||||||
|
<th scope="col" th:text="#{database.fileSize}">File Size</th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
<th scope="col"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr th:each="backup : ${systemUpdate}">
|
||||||
|
<td th:text="${backup.fileName}"></td>
|
||||||
|
<td th:text="${backup.formattedCreationDate}"></td>
|
||||||
|
<td th:text="${backup.formattedFileSize}"></td>
|
||||||
|
<td th:title="#{database.deleteBackupFile}"><a th:href="@{'/api/v1/database/delete/' + ${backup.fileName}}" style="color: red;"><span class="material-symbols-rounded">delete</span></a></td>
|
||||||
|
<td th:title="#{database.importBackupFile}"><a th:href="@{'/api/v1/database/import-database-file/' + ${backup.fileName}}" style="color: var(--md-nav-section-color-organize);"><span class="material-symbols-rounded">backup</span></a></td>
|
||||||
|
<td th:title="#{database.downloadBackupFile}"><a th:href="@{'/api/v1/database/download/' + ${backup.fileName}}"><span class="material-symbols-rounded">download</span></a></td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<hr>
|
||||||
|
<form th:action="@{'/api/v1/database/import-database'}" method="post" enctype="multipart/form-data" class="bg-card mt-3 mb-3">
|
||||||
|
<div style="background: var(--md-sys-color-error-container);padding: .8rem;border-radius: 2rem;" class="mb-3">
|
||||||
|
<p th:text="#{database.info_1}"></p>
|
||||||
|
<p th:text="#{database.info_2}"></p>
|
||||||
|
</div>
|
||||||
|
<div class="custom-file-chooser">
|
||||||
|
<div class="mb-3">
|
||||||
|
<input type="file" class="form-control" th:name="fileInput" id="fileInput-input" accept=".sql" required>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button type="submit" id="submitBtn" class="btn btn-primary" th:text="#{database.submit}">Import Backup</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script th:inline="javascript">
|
||||||
|
const pdfPasswordPrompt = /*[[#{error.pdfPassword}]]*/ '';
|
||||||
|
const multiple = /*[[${multiple}]]*/ false;
|
||||||
|
const remoteCall = /*[[${remoteCall}]]*/ true;
|
||||||
|
</script>
|
||||||
|
<script th:src="@{'/js/fileInput.js'}"></script>
|
||||||
|
<th:block th:insert="~{fragments/footer.html :: footer}"></th:block>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -13,7 +13,7 @@
|
|||||||
<link rel="apple-touch-icon" sizes="180x180" th:href="@{'/apple-touch-icon.png'}">
|
<link rel="apple-touch-icon" sizes="180x180" th:href="@{'/apple-touch-icon.png'}">
|
||||||
<link rel="icon" type="image/png" sizes="32x32" th:href="@{'/favicon-32x32.png'}">
|
<link rel="icon" type="image/png" sizes="32x32" th:href="@{'/favicon-32x32.png'}">
|
||||||
<link rel="icon" type="image/png" sizes="16x16" th:href="@{'/favicon-16x16.png'}">
|
<link rel="icon" type="image/png" sizes="16x16" th:href="@{'/favicon-16x16.png'}">
|
||||||
<link rel="manifest" th:href="@{'/site.webmanifest'}">
|
<link rel="manifest" th:href="@{'/site.webmanifest'}" crossorigin="use-credentials">
|
||||||
<link rel="mask-icon" th:href="@{'/safari-pinned-tab.svg'}" color="#ca2b2a">
|
<link rel="mask-icon" th:href="@{'/safari-pinned-tab.svg'}" color="#ca2b2a">
|
||||||
<link rel="shortcut icon" th:href="@{'/favicon.ico'}">
|
<link rel="shortcut icon" th:href="@{'/favicon.ico'}">
|
||||||
<meta name="apple-mobile-web-app-title" content="Stirling PDF">
|
<meta name="apple-mobile-web-app-title" content="Stirling PDF">
|
||||||
|
@ -274,7 +274,7 @@
|
|||||||
|
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link" href="#" th:href="@{'/split-pdfs'}"
|
<a class="nav-link" href="#" th:href="@{'/split-pdfs'}"
|
||||||
th:classappend="${currentPage}=='split-pdfs' ? 'active' : ''" th:title="#{home.split-pdfs.desc}">
|
th:classappend="${currentPage}=='split-pdfs' ? 'active' : ''" th:title="#{home.split.desc}">
|
||||||
<span class="material-symbols-rounded">
|
<span class="material-symbols-rounded">
|
||||||
cut
|
cut
|
||||||
</span>
|
</span>
|
||||||
|
@ -11,14 +11,17 @@
|
|||||||
<br><br>
|
<br><br>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-6 bg-card">
|
<div class="col-md-8 bg-card">
|
||||||
<h2 th:text="#{licenses.header}">3rd Party licenses</h2>
|
<div class="tool-header">
|
||||||
|
<span class="material-symbols-rounded tool-header-icon organize">license</span>
|
||||||
|
<span class="tool-header-text" th:text="#{licenses.header}">3rd Party licenses</span>
|
||||||
|
</div>
|
||||||
<table class="table table-striped">
|
<table class="table table-striped">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th th:text="#{licenses.module}">Module</th>
|
<th scope="col" th:text="#{licenses.module}">Module</th>
|
||||||
<th th:text="#{licenses.version}">Version</th>
|
<th scope="col" th:text="#{licenses.version}">Version</th>
|
||||||
<th th:text="#{licenses.license}">License</th>
|
<th scope="col" th:text="#{licenses.license}">License</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
@ -6,10 +6,36 @@
|
|||||||
.result-column {
|
.result-column {
|
||||||
border: 1px solid #ccc;
|
border: 1px solid #ccc;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
|
margin-bottom: 15px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
height: calc(100vh - 400px);
|
height: calc(100vh - 400px);
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
}
|
}
|
||||||
|
.flex-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
.color-selector {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
width: 50%;
|
||||||
|
max-height: 100px;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
#color-box1, #color-box2 {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
|
appearance: none;
|
||||||
|
border: none;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
.spacer1 {
|
||||||
|
padding-right: calc(var(--bs-gutter-x) * .5);
|
||||||
|
}
|
||||||
|
.spacer2 {
|
||||||
|
padding-left: calc(var(--bs-gutter-x) * .5);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
@ -27,7 +53,22 @@
|
|||||||
</div>
|
</div>
|
||||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf', remoteCall='false')}"></div>
|
<div th:replace="~{fragments/common :: fileSelector(name='fileInput', multiple=false, accept='application/pdf', remoteCall='false')}"></div>
|
||||||
<div th:replace="~{fragments/common :: fileSelector(name='fileInput2', multiple=false, accept='application/pdf', remoteCall='false')}"></div>
|
<div th:replace="~{fragments/common :: fileSelector(name='fileInput2', multiple=false, accept='application/pdf', remoteCall='false')}"></div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="flex-container">
|
||||||
|
<div class="color-selector spacer1">
|
||||||
|
<label th:text="#{compare.highlightColor.1}"></label>
|
||||||
|
<label for="color-box1"></label><input type="color" id="color-box1" value="#ff0000">
|
||||||
|
</div>
|
||||||
|
<div class="color-selector spacer2">
|
||||||
|
<label th:text="#{compare.highlightColor.2}"></label>
|
||||||
|
<label for="color-box2"></label><input type="color" id="color-box2" value="#008000">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button class="btn btn-primary" onclick="comparePDFs()" th:text="#{compare.submit}"></button>
|
<button class="btn btn-primary" onclick="comparePDFs()" th:text="#{compare.submit}"></button>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<h3 th:text="#{compare.document.1}"></h3>
|
<h3 th:text="#{compare.document.1}"></h3>
|
||||||
@ -55,6 +96,8 @@
|
|||||||
async function comparePDFs() {
|
async function comparePDFs() {
|
||||||
const file1 = document.getElementById("fileInput-input").files[0];
|
const file1 = document.getElementById("fileInput-input").files[0];
|
||||||
const file2 = document.getElementById("fileInput2-input").files[0];
|
const file2 = document.getElementById("fileInput2-input").files[0];
|
||||||
|
var color1 = document.getElementById('color-box1').value;
|
||||||
|
var color2 = document.getElementById('color-box2').value;
|
||||||
|
|
||||||
if (!file1 || !file2) {
|
if (!file1 || !file2) {
|
||||||
console.error("Please select two PDF files to compare");
|
console.error("Please select two PDF files to compare");
|
||||||
@ -115,13 +158,15 @@
|
|||||||
i--;
|
i--;
|
||||||
j--;
|
j--;
|
||||||
} else if (j > 0 && (i === 0 || matrix[i][j - 1] >= matrix[i - 1][j])) {
|
} else if (j > 0 && (i === 0 || matrix[i][j - 1] >= matrix[i - 1][j])) {
|
||||||
differences.unshift(['green', words2[j - 1]]);
|
differences.unshift([color2, words2[j - 1]]);
|
||||||
j--;
|
j--;
|
||||||
} else if (i > 0 && (j === 0 || matrix[i][j - 1] < matrix[i - 1][j])) {
|
} else if (i > 0 && (j === 0 || matrix[i][j - 1] < matrix[i - 1][j])) {
|
||||||
differences.unshift(['red', words1[i - 1]]);
|
differences.unshift([color1, words1[i - 1]]);
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
console.log(differences);
|
||||||
|
|
||||||
|
|
||||||
return differences;
|
return differences;
|
||||||
};
|
};
|
||||||
@ -138,14 +183,14 @@
|
|||||||
const span1 = document.createElement("span");
|
const span1 = document.createElement("span");
|
||||||
const span2 = document.createElement("span");
|
const span2 = document.createElement("span");
|
||||||
|
|
||||||
// If it's an addition, show it in green in the second document and transparent in the first
|
// If it's an addition, show it in color2 in the second document and transparent in the first
|
||||||
if (color === "green") {
|
if (color === color2) {
|
||||||
span1.style.color = "transparent";
|
span1.style.color = "transparent";
|
||||||
span1.style.userSelect = "none";
|
span1.style.userSelect = "none";
|
||||||
span2.style.color = color;
|
span2.style.color = color;
|
||||||
}
|
}
|
||||||
// If it's a deletion, show it in red in the first document and transparent in the second
|
// If it's a deletion, show it in color1 in the first document and transparent in the second
|
||||||
else if (color === "red") {
|
else if (color === color1) {
|
||||||
span1.style.color = color;
|
span1.style.color = color;
|
||||||
span2.style.color = "transparent";
|
span2.style.color = "transparent";
|
||||||
span2.style.userSelect = "none";
|
span2.style.userSelect = "none";
|
||||||
|
@ -5,7 +5,6 @@ import static org.junit.jupiter.api.Assertions.*;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
|
||||||
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@ -44,18 +43,6 @@ public class SPdfApplicationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMainApplicationStartup() throws IOException, InterruptedException {
|
public void testMainApplicationStartup() throws IOException, InterruptedException {
|
||||||
// Setup mock environment for the main method
|
|
||||||
Path settingsPath = Paths.get("configs/settings.yml");
|
|
||||||
Path customSettingsPath = Paths.get("configs/custom_settings.yml");
|
|
||||||
|
|
||||||
// Ensure the files do not exist for the test
|
|
||||||
if (Files.exists(settingsPath)) {
|
|
||||||
Files.delete(settingsPath);
|
|
||||||
}
|
|
||||||
if (Files.exists(customSettingsPath)) {
|
|
||||||
Files.delete(customSettingsPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run the main method
|
// Run the main method
|
||||||
SPdfApplication.main(new String[]{});
|
SPdfApplication.main(new String[]{});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user