Compare commits

...

140 Commits

Author SHA1 Message Date
Anthony Stirling
d142f0abd6 Merge pull request #1236 from Stirling-Tools/sync_version
💾 Update Version
2024-05-19 16:56:25 +01:00
Anthony Stirling
c2949d8944 Merge pull request #1234 from Stirling-Tools/sync_readme
📝 Update README: Translation Progress Table
2024-05-19 16:56:18 +01:00
GitHub Action action@github.com
4766201621 💾 Sync Versions
> Made via sync_files.yml
2024-05-19 15:56:15 +00:00
Anthony Stirling
d9043c9100 Update build.gradle 2024-05-19 16:56:02 +01:00
Anthony Stirling
d52b0d0082 Update merge-pdfs.html 2024-05-19 16:55:44 +01:00
GitHub Action action@github.com
ecfbaef933 📝 Sync README
> Made via sync_files.yml
2024-05-19 15:17:23 +00:00
Anthony Stirling
c5e6555bb5 Merge pull request #1233 from HNPorts/main
Update messages_tr_TR.properties
2024-05-19 16:17:09 +01:00
Han
81d7cc0a40 Update messages_tr_TR.properties 2024-05-19 18:02:27 +03:00
Anthony Stirling
02524c64d5 Merge pull request #1230 from Stirling-Tools/sync_version
💾 Update Version
2024-05-19 13:28:31 +01:00
GitHub Action action@github.com
7d6846920e 💾 Sync Versions
> Made via sync_files.yml
2024-05-19 12:27:16 +00:00
Anthony Stirling
2443ed2020 quick cache fix 2024-05-19 13:27:00 +01:00
Anthony Stirling
0dd91f209a Merge pull request #1229 from Stirling-Tools/sync_readme
📝 Update README: Translation Progress Table
2024-05-19 12:26:55 +01:00
GitHub Action action@github.com
869e2dc62d 📝 Sync README
> Made via sync_files.yml
2024-05-19 11:06:36 +00:00
Anthony Stirling
a28f14b70e Merge pull request #1227 from albanobattistella/patch-26
Update messages_it_IT.properties
2024-05-19 12:06:23 +01:00
Anthony Stirling
b5de6a73cc Merge pull request #1228 from Stirling-Tools/config
Config
2024-05-19 12:05:47 +01:00
Anthony Stirling
45e2623b9b change configs 2024-05-19 12:00:46 +01:00
albanobattistella
6d95bfdee0 Update messages_it_IT.properties 2024-05-19 12:57:34 +02:00
a
f9111e556c Merge remote-tracking branch 'origin/main' into config 2024-05-19 11:54:58 +01:00
Anthony Stirling
fa746a2b51 config stuff 2024-05-19 11:54:45 +01:00
Anthony Stirling
e43292f4dd Merge pull request #1226 from Ludy87/validation_username_password
bg-card will be added to the class and password/username validation
2024-05-19 11:52:52 +01:00
Anthony Stirling
c56c5f80ab Merge pull request #1225 from Ludy87/add_missing_settings
adds all available settings to settings.yml
2024-05-19 11:52:04 +01:00
Ludy87
f2eb5dd7d3 bg-card will be added to the class and password/username validation
bg-card should not be an id, ids should be unique in their use.
2024-05-19 12:44:54 +02:00
Ludy87
ffe221b93c Update README.md 2024-05-19 11:36:50 +02:00
Ludy87
3f252e29a1 adds all available settings to settings.yml 2024-05-19 11:35:46 +02:00
Anthony Stirling
7c0fd02126 Merge pull request #1224 from Ludy87/fix_system_exit
Fix: Removes username validation check
2024-05-19 10:25:41 +01:00
Ludy87
7109dd7905 Fix: Removes username validation check
- Removes username validation check
- Ignores API users in user counting
2024-05-19 10:52:11 +02:00
Anthony Stirling
e30665e7c8 Merge pull request #1223 from Stirling-Tools/sync_version
💾 Update Version
2024-05-19 00:03:17 +01:00
GitHub Action action@github.com
514606789e 💾 Sync Versions
> Made via sync_files.yml
2024-05-18 23:00:29 +00:00
Anthony Stirling
dd1a441f92 Merge pull request #1222 from Stirling-Tools/minorSizes
sizes
2024-05-19 00:00:15 +01:00
Anthony Stirling
31c48aec90 sizes 2024-05-18 23:59:40 +01:00
Anthony Stirling
6709e0c46d Merge pull request #1221 from Stirling-Tools/sync_readme
📝 Update README: Translation Progress Table
2024-05-18 23:33:54 +01:00
GitHub Action action@github.com
10dd5e4a40 📝 Sync README
> Made via sync_files.yml
2024-05-18 22:30:52 +00:00
Anthony Stirling
6fc9a2032a Merge pull request #1201 from Ludy87/add_functions_oauth2
extends the functionality of oauth in Stirling PDF
2024-05-18 23:30:37 +01:00
Ludy87
ffec5f7b54 extends the functionality of oauth in Stirling PDF 2. 2024-05-18 23:47:05 +02:00
Anthony Stirling
b904a46bca Update CustomAuthenticationSuccessHandler.java 2024-05-18 19:39:35 +01:00
Anthony Stirling
26a457f9d0 Update InitialSecuritySetup.java 2024-05-18 19:38:39 +01:00
Anthony Stirling
e9042e0b7e Update login.html 2024-05-18 19:37:11 +01:00
Anthony Stirling
521dff737f Merge branch 'main' into add_functions_oauth2 2024-05-18 19:24:02 +01:00
Anthony Stirling
2968a696cd error banner fixes 2024-05-18 18:40:13 +01:00
a
e0d3bbf13b Merge branch 'main' of git@github.com:Stirling-Tools/Stirling-PDF.git into main 2024-05-18 18:39:46 +01:00
Anthony Stirling
89e763d959 error banner fixes 2024-05-18 18:39:38 +01:00
Anthony Stirling
1f9a0ed0e3 Merge pull request #1193 from Stirling-Tools/redesign
Redesign
2024-05-18 14:14:31 +01:00
Anthony Stirling
f203e07f55 Merge remote-tracking branch 'origin/main' into redesign 2024-05-18 13:53:34 +01:00
Anthony Stirling
56d4c02445 readd searchbar 2024-05-18 13:43:00 +01:00
Ludy
c20936b485 Merge branch 'main' into add_functions_oauth2 2024-05-18 13:52:53 +02:00
Anthony Stirling
389323c190 transition only on change not load 2024-05-18 12:48:01 +01:00
Anthony Stirling
f0dd48b3b1 font load detection 2024-05-18 12:47:21 +01:00
Anthony Stirling
b860146c93 logging for #1024 and jdk bump 2024-05-17 19:18:57 +01:00
Anthony Stirling
23b662e5dc Merge pull request #1211 from Stirling-Tools/sync_readme
📝 Update README: Translation Progress Table
2024-05-15 22:27:38 +01:00
GitHub Action action@github.com
7160ba47b1 📝 Sync README
> Made via sync_files.yml
2024-05-15 08:34:47 +00:00
Anthony Stirling
bdea990b18 Merge pull request #1208 from p3lo/slovakia-translation
Slovak translation
2024-05-15 09:34:32 +01:00
p3lo
1cbc6307c3 Added Slovak language to supported languages table 2024-05-15 10:13:03 +02:00
p3lo
1e42f54ec7 Added slovak translation 2024-05-14 22:56:36 +02:00
Anthony Stirling
44e85a1d38 Merge pull request #1205 from foivospro/main
Fix rotation function
2024-05-14 18:01:15 +01:00
Anthony Stirling
54073767af Merge pull request #1207 from urjeetpatel/main
fix Remove Redundant Back to Main Page Button
2024-05-14 18:01:02 +01:00
Urjeet Patel
3fa41e058a fix: Remove Redundant Back to Main Page Button
Remove Redundant Back to Main Page Button. this fixes #489

Closes #489
2024-05-14 16:43:18 +00:00
foiv
44f9313012 Fix Rotation function 2024-05-14 12:11:30 +03:00
Ludy87
dcf13e9ade Update InitialSecuritySetup.java 2024-05-12 20:17:46 +02:00
Ludy87
811c19e00d extends the functionality of oauth in Stirling PDF 2024-05-12 19:58:34 +02:00
Anthony Stirling
f2b7aeeb1c Merge pull request #1199 from jimdouk/fixFrontEndIssue
Enhance UI Search Functionality in Navbar
2024-05-12 14:36:52 +01:00
Dimitris Doukas
840694c527 Update search functionality on navbar 2024-05-12 14:07:43 +03:00
Dimitris Doukas
21e5002d73 Merge branch 'Stirling-Tools:main' into fixFrontEndIssue 2024-05-12 13:55:51 +03:00
Rectos VX
36d6c06237 Update: fix dropdown hover + icon titles on mobile 2024-05-10 15:44:54 +04:00
Anthony Stirling
29ec42bc35 Merge branch 'main' into redesign 2024-05-09 19:49:06 +01:00
Anthony Stirling
425502b3e3 Merge pull request #1192 from Stirling-Tools/sync_readme
📝 Update README: Translation Progress Table
2024-05-09 17:50:44 +01:00
Anthony Stirling
692a526900 Merge pull request #1188 from bluestero/main
Install locally on a machine with no-root, docker, apt, yum, and apk via nix package manager.
2024-05-09 17:50:30 +01:00
Rectos VX
3a27d97811 Update: change update icon + animation 2024-05-09 17:31:12 +04:00
GitHub Action action@github.com
af91c73e7a 📝 Sync README
> Made via sync_files.yml
2024-05-08 21:22:18 +00:00
Anthony Stirling
526a30d033 Merge pull request #1191 from nimdassdev/main
Updated/improved Bulgarian language strings. Thank you.
2024-05-08 22:22:03 +01:00
IT Creativity + Art Team
bf8d6d2337 Update messages_bg_BG.properties
Updated/improved Bulgarian language strings. Thank you.
2024-05-08 23:43:51 +03:00
IT Creativity + Art Team
5628300f51 Merge branch 'Stirling-Tools:main' into main 2024-05-08 23:00:20 +03:00
Rectos VX
72ba97a00c Update: open dropdown on hover 2024-05-08 20:21:07 +04:00
Rectos VX
1634987171 Update: local font + fix home card layout 2024-05-08 18:24:55 +04:00
Rectos VX
0f43723250 Update: fix dropdown text wrap 2024-05-08 17:42:36 +04:00
Rectos VX
34e2128a39 Update: fix error page theme 2024-05-08 16:26:14 +04:00
Ahmed Khatib
0a0887aafc Fixed the bad working regarding language packs. Explained the dbus variable change before running the jar file. 2024-05-08 01:52:41 +05:30
Anthony Stirling
7c0c33ca63 Merge pull request #1180 from subarudad/fix_readme
Update README.md: minor spelling fix
2024-05-07 21:04:59 +01:00
Ahmed Khatib
8b2f24affd Added the export command before running. 2024-05-08 01:22:52 +05:30
Ahmed Khatib
cbe750c76c Small typo in apt-get update. 2024-05-08 01:15:43 +05:30
Ahmed Khatib
5f6d24f805 Added support for non-root and nix package manager for local installation. Fixed a bad small line break issue. 2024-05-08 01:14:08 +05:30
Anthony Stirling
be5d5fdf04 Merge pull request #1179 from Stirling-Tools/pixeebot/drip-2024-05-07-pixee-java/strip-http-header-newlines
Introduced protections against HTTP header injection / smuggling attacks
2024-05-07 19:14:29 +01:00
brucengumetro
a04dc605df minor spelling fix 2024-05-07 16:05:01 +07:00
pixeebot[bot]
503acc9408 Introduced protections against HTTP header injection / smuggling attacks 2024-05-07 03:44:03 +00:00
Anthony Stirling
9b166da57d Merge pull request #1177 from albanobattistella/patch-25
Update messages_it_IT.properties
2024-05-06 12:45:29 +01:00
albanobattistella
66e566555e Update messages_it_IT.properties 2024-05-06 13:32:23 +02:00
Anthony Stirling
f7aebf22c8 Merge pull request #1172 from Stirling-Tools/sync_version
💾 Update Version
2024-05-05 21:08:23 +01:00
GitHub Action action@github.com
bb0b5f0528 💾 Sync Versions
> Made via sync_files.yml
2024-05-05 19:50:36 +00:00
Anthony Stirling
9e3d5a5bc5 Update build.gradle 2024-05-05 20:50:22 +01:00
Anthony Stirling
9ba5c6d4be Merge pull request #1171 from Stirling-Tools/timeouts
Timeouts #1094
2024-05-05 20:47:17 +01:00
Anthony Stirling
00f7fe7ac3 Update application.properties 2024-05-05 20:46:22 +01:00
Anthony Stirling
f4fcede771 Update ProcessExecutor.java 2024-05-05 20:45:52 +01:00
Anthony Stirling
b69646d00b Merge branch 'main' into 0.22.8Clone 2024-05-05 20:28:25 +01:00
Anthony Stirling
9e81b161c3 Merge pull request #1170 from Rectos28/redesign
Redesign using MD3 system
2024-05-05 18:46:44 +01:00
github-actions[bot]
66ce7511ca 📝 Update README: Translation Progress Table (#1168)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-05-05 14:01:42 +01:00
Anthony Stirling
d17db24aa9 #1160 update rhefs (#1169)
Update common.html
2024-05-05 13:53:26 +01:00
Anthony Stirling
ac5273244c flatten (#1167) 2024-05-05 13:33:17 +01:00
Rectos VX
27113f99cb Remove: old icon svg file 2024-05-05 15:46:06 +04:00
Rectos VX
fa31a4e340 Update: some margins in some places 2024-05-05 15:43:03 +04:00
Rectos VX
4d53119390 Update: add new tags to all languages 2024-05-05 15:23:42 +04:00
Rectos VX
303b8e032b Update: updated all pages to new theme system 2024-05-05 15:19:53 +04:00
Anthony Stirling
d6b1fec69d Update Dockerfile 2024-05-05 12:18:52 +01:00
Rectos VX
5c572a7d89 Update: changed JS to new theme system + Darkmode system 2024-05-05 15:12:30 +04:00
Rectos VX
04d1ff3822 Update: Changed pages css to adapte new theme system 2024-05-05 15:07:44 +04:00
Rectos VX
eb8a494b5c Remove: Deleted old theme css 2024-05-05 14:53:22 +04:00
Rectos VX
4dfac2f46f Add: New theme css system 2024-05-05 14:50:36 +04:00
albanobattistella
547f231e29 Update messages_it_IT.properties (#1165) 2024-05-05 11:40:18 +01:00
Anthony Stirling
38979dd362 lets try this again (Config fix) (#1159)
* Introducing a custom settings file

* formats

* chnages

* Update README.md

* fixes

---------

Co-authored-by: a <a>
2024-05-03 22:23:21 +01:00
Anthony Stirling
890163053b introduces custom settings file (#1158)
* Introducing a custom settings file

* formats

* chnages

* Update README.md
2024-05-03 20:43:48 +01:00
t71rs
fbbc71d7e6 Drag&drop bug (#1157)
* Fixed issue that Drag and Droppped Files can not be deleted

* Deleted unnecessary Comment
2024-05-03 19:09:36 +01:00
Anthony Stirling
4372536c17 Remove ChatGPT mention to avoid confusion 2024-05-03 10:40:22 +01:00
github-actions[bot]
7f577a6052 📝 Update README: Translation Progress Table (#1155)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-05-02 22:02:33 +01:00
Sahil Phule
d7afc574a6 Change User Roles (#1153)
* Modify user service and controller

* Modify Template

* Add messages

* Fix Username output

* Add tooltip

* Change Role Modify logic

* Add Roles from database to existing users

* Add default select Fillers

* Indent JS

* Add Change Role Related Translations

* Remove unnecessary Whitespace and imports
2024-05-02 21:52:50 +01:00
github-actions[bot]
c622ee915b 📝 Update README: Translation Progress Table (#1151)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-04-30 23:04:59 +01:00
albanobattistella
d0df392eef Update messages_it_IT.properties (#1148) 2024-04-30 23:04:05 +01:00
Ludy
1c33500815 Update messages_de_DE.properties (#1149) 2024-04-30 23:03:50 +01:00
t71rs
d730c6a12f Arrow key support signing (#1143)
* Added Arrow Key functionality for the Sign page.

* Added Arrow Key functionality for the Sign page.

* Adjusted step size, so it is relative to the size of the draggable

* Enabled Arrow Key support also for Add-Image

---------

Co-authored-by: Eric <71648843+sbplat@users.noreply.github.com>
2024-04-30 13:02:12 -04:00
Sahil Phule
b71f6f93b1 Add translations for OAUTH2 Related Text (#1146) 2024-04-30 08:02:15 +01:00
github-actions[bot]
32dd328048 Update 3rd Party Licenses (#1144)
Signed-off-by: GitHub Action <action@github.com>
Co-authored-by: GitHub Action <action@github.com>
2024-04-29 22:05:54 +01:00
Sahil Phule
d9fa8f7b48 Add OAUTH2 OIDC login support (#1140)
* Somewhat working

* Change Autocreate logic

* Add OAuth Error Message if Auto create Disabled

* Display OAUTH2 username(email) in Account Settings

* Disable Change user/pass for Oauth2 user

* Hide SSO Button if SSO login Disabled

* Remove some spaces and comments

* Add OAUTH2 Login example docker-compose file

* Add Some Comments

* Hide Printing of Client secret

* Remove OAUTH2 Beans

and replace with applicationProperties

* Add conditional annotation to Bean Creation

* Update settings.yml.template

Add OAUTH2 enabling template.

* Update messages_en_GB.properties
2024-04-29 22:01:22 +01:00
Anthony Stirling
777e512e61 fonts noto fix #974 (#1139)
fix #974
2024-04-28 23:33:55 +01:00
Anthony Stirling
e7e3b34b37 fix for #1035 (#1137)
* fix for #1035

* Update ConvertImgPDFController.java
2024-04-28 22:37:40 +01:00
github-actions[bot]
6ed9e1c707 📝 Update README: Translation Progress Table (#1134)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-04-28 10:40:01 +01:00
Ludy
318076254d Handling Untranslatable Strings (#1133) 2024-04-27 23:26:12 +01:00
github-actions[bot]
4fea8d10f8 💾 Update Version (#1130)
💾 Sync Versions
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-04-27 11:04:28 +01:00
Anthony Stirling
8c9d6f7b66 Custom HTML support #355 (#1129)
* test

* settings

* version
2024-04-27 11:03:57 +01:00
Anthony Stirling
30444fc9bb commit (#1128)
* commit

* formatting
2024-04-26 23:27:40 +01:00
Han
70349d642b Update messages_tr_TR.properties (#1126)
* Update messages_tr_TR.properties

* Update messages_tr_TR.properties
2024-04-26 19:37:09 +01:00
albanobattistella
afaec64afd Update messages_it_IT.properties (#1120) 2024-04-24 21:57:56 +01:00
github-actions[bot]
2a9fdff605 📝 Update README: Translation Progress Table (#1119)
📝 Sync README
> Made via sync_files.yml

Co-authored-by: GitHub Action action@github.com <GitHub Action action@github.com>
2024-04-24 19:59:53 +01:00
Anthony Stirling
34c7ee46a0 lang adds 2024-04-24 19:59:01 +01:00
phfuh
5ee702f364 PDF to PDF/A language files (#1118)
* Update messages_en_GB.properties

* Update messages_en_US.properties

* Update messages_de_DE.properties
2024-04-24 19:56:35 +01:00
Ludy
1b5d21a22e Bugfix: Login page shows wrong selected country flag/language (#1117)
Closes #1116
2024-04-24 09:10:16 +01:00
Anthony Stirling
c3e5157dee Delete CNAME 2024-04-23 22:35:21 +01:00
Anthony Stirling
6d859e4c25 Create CNAME 2024-04-23 22:34:29 +01:00
diemade
95a9aca5b5 Update CONTRIBUTING.md (#1115)
adding a chapter on how to edit Docs
2024-04-23 22:32:12 +01:00
Dimitris Doukas
9402109663 Merge branch 'Stirling-Tools:main' into main 2024-04-15 17:05:08 +03:00
Dimitris Doukas
a05cfd52cb Merge branch 'updatereadme' 2024-04-02 21:01:07 +03:00
Dimitris Doukas
ad0967f7d0 Update screen of homepage 2024-04-02 12:50:53 +03:00
IT Creativity + Art Team
7e4d8f45f6 Merge branch 'Stirling-Tools:main' into main 2024-02-14 21:26:22 +02:00
Stirling-PDF-Bot
9dbc2712e7 Update 3rd Party Licenses 2024-01-16 20:06:35 +00:00
240 changed files with 7755 additions and 2869 deletions

View File

@@ -7,6 +7,7 @@ on:
paths: paths:
- "build.gradle" - "build.gradle"
- "src/main/resources/messages_*.properties" - "src/main/resources/messages_*.properties"
- "scripts/translation_status.toml"
permissions: permissions:
contents: write contents: write
@@ -58,6 +59,8 @@ jobs:
uses: actions/setup-python@v5.1.0 uses: actions/setup-python@v5.1.0
with: with:
python-version: "3.x" python-version: "3.x"
- name: Install dependencies
run: pip install tomlkit
- name: Sync README - name: Sync README
run: python scripts/counter_translation.py run: python scripts/counter_translation.py
- name: Set up git config - name: Set up git config

View File

@@ -27,6 +27,10 @@ Please make sure your Pull Request adheres to the following guidelines:
If you would like to add or modify a translation, please see [How to add new languages to Stirling-PDF](HowToAddNewLanguage.md). Also, please create a Pull Request so others can use it! If you would like to add or modify a translation, please see [How to add new languages to Stirling-PDF](HowToAddNewLanguage.md). Also, please create a Pull Request so others can use it!
## Docs
Documentation for Stirling-PDF is handled in a seperate repository. Please see [Docs repository](https://github.com/Stirling-Tools/Stirling-Tools.github.io) or use "edit this page"-button at the bottom of each page at [https://stirlingtools.com/docs/](https://stirlingtools.com/docs/).
## Fixing Bugs or Adding a New Feature ## Fixing Bugs or Adding a New Feature
First, make sure you've read the section [Pull Requests](#pull-requests). First, make sure you've read the section [Pull Requests](#pull-requests).

View File

@@ -4,8 +4,8 @@ FROM alpine:20240329
# Copy necessary files # Copy necessary files
COPY scripts /scripts COPY scripts /scripts
COPY pipeline /pipeline COPY pipeline /pipeline
COPY src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto COPY src/main/resources/static/fonts/*.ttf /usr/share/fonts/opentype/noto/
COPY src/main/resources/static/fonts/*.otf /usr/share/fonts/opentype/noto #COPY src/main/resources/static/fonts/*.otf /usr/share/fonts/opentype/noto/
COPY build/libs/*.jar app.jar COPY build/libs/*.jar app.jar
ARG VERSION_TAG ARG VERSION_TAG
@@ -34,7 +34,7 @@ RUN echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /et
openssl-dev \ openssl-dev \
bash \ bash \
curl \ curl \
openjdk17-jre \ openjdk21-jre \
su-exec \ su-exec \
shadow \ shadow \
# Doc conversion # Doc conversion

View File

@@ -31,7 +31,7 @@ RUN mkdir /configs /logs /customFiles && \
curl \ curl \
su-exec \ su-exec \
shadow \ shadow \
openjdk17-jre && \ openjdk21-jre && \
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \ echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/main" | tee -a /etc/apk/repositories && \
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/community" | tee -a /etc/apk/repositories && \ echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/community" | tee -a /etc/apk/repositories && \
echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing" | tee -a /etc/apk/repositories && \ echo "@testing https://dl-cdn.alpinelinux.org/alpine/edge/testing" | tee -a /etc/apk/repositories && \

View File

@@ -34,5 +34,18 @@ Then simply translate all property entries within that file and make a PR into m
If you do not have a java IDE i am happy to verify the changes worked once you raise PR (but won't be able to verify the translations themselves) If you do not have a java IDE i am happy to verify the changes worked once you raise PR (but won't be able to verify the translations themselves)
## Handling Untranslatable Strings
Sometimes, certain strings in the properties file may not require translation because they are the same in the target language or are universal (like names of protocols, certain terminologies, etc.). To ensure accurate statistics for language progress, these strings should be added to the `ignore_translation.toml` file located in the `scripts` directory. This will exclude them from the translation progress calculations.
For example, if the English string error=Error does not need translation in Polish, add it to the ignore_translation.toml under the Polish section:
```toml
[pl_PL]
ignore = [
"language.direction", # Existing entries
"error" # Add new entries here
]
```
Make sure to place the entry under the correct language section. This helps maintain the accuracy of translation progress statistics and ensures that the translation tool or scripts do not misinterpret the completion rate.

View File

@@ -14,7 +14,7 @@ You could theoretically use a Distrobox/Toolbox, if your Distribution has old or
Install the following software, if not already installed: Install the following software, if not already installed:
- Java 17 or later - Java 17 or later (21 recommended)
- Gradle 7.0 or later (included within repo so not needed on server) - Gradle 7.0 or later (included within repo so not needed on server)
@@ -42,17 +42,25 @@ For Debian-based systems, you can use the following command:
```bash ```bash
sudo apt-get update sudo apt-get update
sudo apt-get install -y git automake autoconf libtool libleptonica-dev pkg-config zlib1g-dev make g++ openjdk-17-jdk python3 python3-pip sudo apt-get install -y git automake autoconf libtool libleptonica-dev pkg-config zlib1g-dev make g++ openjdk-21-jdk python3 python3-pip
``` ```
For Fedora-based systems use this command: For Fedora-based systems use this command:
```bash ```bash
sudo dnf install -y git automake autoconf libtool leptonica-devel pkg-config zlib-devel make gcc-c++ java-17-openjdk python3 python3-pip sudo dnf install -y git automake autoconf libtool leptonica-devel pkg-config zlib-devel make gcc-c++ java-21-openjdk python3 python3-pip
```
For non-root users with Nix Package Manager, use the following command:
```bash
nix-channel --update
nix-env -iA nixpkgs.jdk21 nixpkgs.git nixpkgs.python38 nixpkgs.gnumake nixpkgs.libgcc nixpkgs.automake nixpkgs.autoconf nixpkgs.libtool nixpkgs.pkg-config nixpkgs.zlib nixpkgs.leptonica
``` ```
### Step 2: Clone and Build jbig2enc (Only required for certain OCR functionality) ### Step 2: Clone and Build jbig2enc (Only required for certain OCR functionality)
For Debian and Fedora, you can build it from source using the following commands:
```bash ```bash
mkdir ~/.git mkdir ~/.git
cd ~/.git &&\ cd ~/.git &&\
@@ -64,6 +72,11 @@ make &&\
sudo make install sudo make install
``` ```
For Nix, you will face `Leptonica not detected`. Bypass this by installing it directly using the following command:
```bash
nix-env -iA nixpkgs.jbig2enc
```
### Step 3: Install Additional Software ### Step 3: Install Additional Software
Next we need to install LibreOffice for conversions, ocrmypdf for OCR, and opencv for pattern recognition functionality. Next we need to install LibreOffice for conversions, ocrmypdf for OCR, and opencv for pattern recognition functionality.
@@ -105,6 +118,13 @@ sudo dnf install -y libreoffice-writer libreoffice-calc libreoffice-impress unpa
pip3 install uno opencv-python-headless unoconv pngquant WeasyPrint pip3 install uno opencv-python-headless unoconv pngquant WeasyPrint
``` ```
For Nix:
```bash
nix-env -iA nixpkgs.unpaper nixpkgs.libreoffice nixpkgs.ocrmypdf nixpkgs.poppler_utils
pip3 install uno opencv-python-headless unoconv pngquant WeasyPrint
```
### Step 4: Clone and Build Stirling-PDF ### Step 4: Clone and Build Stirling-PDF
```bash ```bash
@@ -115,13 +135,12 @@ chmod +x ./gradlew &&\
./gradlew build ./gradlew build
``` ```
### Step 5: Move jar to desired location ### Step 5: Move jar to desired location
After the build process, a `.jar` file will be generated in the `build/libs` directory. After the build process, a `.jar` file will be generated in the `build/libs` directory.
You can move this file to a desired location, for example, `/opt/Stirling-PDF/`. You can move this file to a desired location, for example, `/opt/Stirling-PDF/`.
You must also move the Script folder within the Stirling-PDF repo that you have downloaded to this directory. You must also move the Script folder within the Stirling-PDF repo that you have downloaded to this directory.
This folder is required for the python scripts using OpenCV This folder is required for the python scripts using OpenCV.
```bash ```bash
sudo mkdir /opt/Stirling-PDF &&\ sudo mkdir /opt/Stirling-PDF &&\
@@ -129,19 +148,25 @@ sudo mv ./build/libs/Stirling-PDF-*.jar /opt/Stirling-PDF/ &&\
sudo mv scripts /opt/Stirling-PDF/ &&\ sudo mv scripts /opt/Stirling-PDF/ &&\
echo "Scripts installed." echo "Scripts installed."
``` ```
For non-root users, you can just keep the jar in the main directory of Stirling-PDF using the following command:
```bash
mv ./build/libs/Stirling-PDF-*.jar ./Stirling-PDF-*.jar
```
### Step 6: Other files ### Step 6: Other files
#### OCR #### OCR
If you plan to use the OCR (Optical Character Recognition) functionality, you might need to install language packs for Tesseract if running non-english scanning. If you plan to use the OCR (Optical Character Recognition) functionality, you might need to install language packs for Tesseract if running non-english scanning.
##### Installing Language Packs ##### Installing Language Packs
Easiest is to use the langpacks provided by your repositories. Skip the other steps Easiest is to use the langpacks provided by your repositories. Skip the other steps.
Manual: Manual:
1. Download the desired language pack(s) by selecting the `.traineddata` file(s) for the language(s) you need. 1. Download the desired language pack(s) by selecting the `.traineddata` file(s) for the language(s) you need.
2. Place the `.traineddata` files in the Tesseract tessdata directory: `/usr/share/tessdata` 2. Place the `.traineddata` files in the Tesseract tessdata directory: `/usr/share/tessdata`
3. 3. Please view [OCRmyPDF install guide](https://ocrmypdf.readthedocs.io/en/latest/installation.html) for more info.
Please view [OCRmyPDF install guide](https://ocrmypdf.readthedocs.io/en/latest/installation.html) for more info.
**IMPORTANT:** DO NOT REMOVE EXISTING `eng.traineddata`, IT'S REQUIRED. **IMPORTANT:** DO NOT REMOVE EXISTING `eng.traineddata`, IT'S REQUIRED.
Debian based systems, install languages with this command: Debian based systems, install languages with this command:
@@ -171,14 +196,38 @@ dnf search -C tesseract-langpack-
rpm -qa | grep tesseract-langpack | sed 's/tesseract-langpack-//g' rpm -qa | grep tesseract-langpack | sed 's/tesseract-langpack-//g'
``` ```
Nix:
```bash
nix-env -iA nixpkgs.tesseract
```
**Note:** Nix Package Manager pre-installs almost all the language packs when tesseract is installed.
### Step 7: Run Stirling-PDF ### Step 7: Run Stirling-PDF
Those who have pushed to the root directory, run the following commands:
```bash ```bash
./gradlew bootRun ./gradlew bootRun
or or
java -jar /opt/Stirling-PDF/Stirling-PDF-*.jar java -jar /opt/Stirling-PDF/Stirling-PDF-*.jar
``` ```
Since libreoffice, soffice, and conversion tools have their dbus_tmp_dir set as `dbus_tmp_dir="/run/user/$(id -u)/libreoffice-dbus"`, you might get the following error when using their endpoints:
```
[Thread-7] INFO s.s.SPDF.utils.ProcessExecutor - mkdir: cannot create directory /run/user/1501: Permission denied
```
To resolve this, before starting the Stirling-PDF, you have to set the environment variable to a directory you have write access to by using the following commands:
```bash
mkdir temp
export DBUS_SESSION_BUS_ADDRESS="unix:path=./temp"
./gradlew bootRun
or
java -jar ./Stirling-PDF-*.jar
```
### Step 8: Adding a Desktop icon ### Step 8: Adding a Desktop icon
This will add a modified Appstarter to your Appmenu. This will add a modified Appstarter to your Appmenu.
@@ -202,7 +251,19 @@ EOF
Note: Currently the app will run in the background until manually closed. Note: Currently the app will run in the background until manually closed.
### Optional: Run Stirling-PDF as a service ### Optional: Changing the host and port of the application:
To override the default configuration, you can add the following to `/.git/Stirling-PDF/configs/custom_settings.yml` file:
```bash
server:
host: 0.0.0.0
port: 3000
```
**Note:** This file is created after the first application launch. To have it before that, you can create the directory and add the file yourself.
### Optional: Run Stirling-PDF as a service (requires root).
First create a .env file, where you can store environment variables: First create a .env file, where you can store environment variables:
``` ```
@@ -239,6 +300,7 @@ WantedBy=multi-user.target
``` ```
Notify systemd that it has to rebuild its internal service database (you have to run this command every time you make a change in the service file): Notify systemd that it has to rebuild its internal service database (you have to run this command every time you make a change in the service file):
``` ```
sudo systemctl daemon-reload sudo systemctl daemon-reload
``` ```

View File

@@ -10,7 +10,7 @@
[![Deploy to DO](https://www.deploytodo.com/do-btn-blue.svg)](https://cloud.digitalocean.com/apps/new?repo=https://github.com/Stirling-Tools/Stirling-PDF/tree/digitalOcean&refcode=c3210994b1af) [![Deploy to DO](https://www.deploytodo.com/do-btn-blue.svg)](https://cloud.digitalocean.com/apps/new?repo=https://github.com/Stirling-Tools/Stirling-PDF/tree/digitalOcean&refcode=c3210994b1af)
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. Originally developed entirely by ChatGPT, 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.
Stirling PDF does not initiate any outbound calls for record-keeping or tracking purposes. Stirling PDF does not initiate any outbound calls for record-keeping or tracking purposes.
@@ -165,31 +165,32 @@ Stirling PDF currently supports 27!
| ------------------------------------------- | -------------------------------------- | | ------------------------------------------- | -------------------------------------- |
| English (English) (en_GB) | ![100%](https://geps.dev/progress/100) | | English (English) (en_GB) | ![100%](https://geps.dev/progress/100) |
| English (US) (en_US) | ![100%](https://geps.dev/progress/100) | | English (US) (en_US) | ![100%](https://geps.dev/progress/100) |
| Arabic (العربية) (ar_AR) | ![58%](https://geps.dev/progress/58) | | Arabic (العربية) (ar_AR) | ![41%](https://geps.dev/progress/41) |
| German (Deutsch) (de_DE) | ![98%](https://geps.dev/progress/98) | | German (Deutsch) (de_DE) | ![97%](https://geps.dev/progress/97) |
| French (Français) (fr_FR) | ![93%](https://geps.dev/progress/93) | | French (Français) (fr_FR) | ![89%](https://geps.dev/progress/89) |
| Spanish (Español) (es_ES) | ![99%](https://geps.dev/progress/99) | | Spanish (Español) (es_ES) | ![97%](https://geps.dev/progress/97) |
| Simplified Chinese (简体中文) (zh_CN) | ![98%](https://geps.dev/progress/98) | | Simplified Chinese (简体中文) (zh_CN) | ![96%](https://geps.dev/progress/96) |
| Traditional Chinese (繁體中文) (zh_TW) | ![98%](https://geps.dev/progress/98) | | Traditional Chinese (繁體中文) (zh_TW) | ![96%](https://geps.dev/progress/96) |
| Catalan (Català) (ca_CA) | ![64%](https://geps.dev/progress/64) | | Catalan (Català) (ca_CA) | ![50%](https://geps.dev/progress/50) |
| Italian (Italiano) (it_IT) | ![98%](https://geps.dev/progress/98) | | Italian (Italiano) (it_IT) | ![99%](https://geps.dev/progress/99) |
| Swedish (Svenska) (sv_SE) | ![58%](https://geps.dev/progress/58) | | Swedish (Svenska) (sv_SE) | ![41%](https://geps.dev/progress/41) |
| Polish (Polski) (pl_PL) | ![59%](https://geps.dev/progress/59) | | Polish (Polski) (pl_PL) | ![43%](https://geps.dev/progress/43) |
| Romanian (Română) (ro_RO) | ![57%](https://geps.dev/progress/57) | | Romanian (Română) (ro_RO) | ![40%](https://geps.dev/progress/40) |
| Korean (한국어) (ko_KR) | ![93%](https://geps.dev/progress/93) | | Korean (한국어) (ko_KR) | ![89%](https://geps.dev/progress/89) |
| Portuguese Brazilian (Português) (pt_BR) | ![73%](https://geps.dev/progress/73) | | Portuguese Brazilian (Português) (pt_BR) | ![62%](https://geps.dev/progress/62) |
| Russian (Русский) (ru_RU) | ![93%](https://geps.dev/progress/93) | | Russian (Русский) (ru_RU) | ![89%](https://geps.dev/progress/89) |
| Basque (Euskara) (eu_ES) | ![75%](https://geps.dev/progress/75) | | Basque (Euskara) (eu_ES) | ![65%](https://geps.dev/progress/65) |
| Japanese (日本語) (ja_JP) | ![93%](https://geps.dev/progress/93) | | Japanese (日本語) (ja_JP) | ![89%](https://geps.dev/progress/89) |
| Dutch (Nederlands) (nl_NL) | ![91%](https://geps.dev/progress/91) | | Dutch (Nederlands) (nl_NL) | ![86%](https://geps.dev/progress/86) |
| Greek (Ελληνικά) (el_GR) | ![92%](https://geps.dev/progress/92) | | Greek (Ελληνικά) (el_GR) | ![87%](https://geps.dev/progress/87) |
| Turkish (Türkçe) (tr_TR) | ![99%](https://geps.dev/progress/99) | | Turkish (Türkçe) (tr_TR) | ![99%](https://geps.dev/progress/99) |
| Indonesia (Bahasa Indonesia) (id_ID) | ![87%](https://geps.dev/progress/87) | | Indonesia (Bahasa Indonesia) (id_ID) | ![80%](https://geps.dev/progress/80) |
| Hindi (हिंदी) (hi_IN) | ![87%](https://geps.dev/progress/87) | | Hindi (हिंदी) (hi_IN) | ![81%](https://geps.dev/progress/81) |
| Hungarian (Magyar) (hu_HU) | ![86%](https://geps.dev/progress/86) | | Hungarian (Magyar) (hu_HU) | ![79%](https://geps.dev/progress/79) |
| Bulgarian (Български) (bg_BG) | ![82%](https://geps.dev/progress/82) | | Bulgarian (Български) (bg_BG) | ![96%](https://geps.dev/progress/96) |
| Sebian Latin alphabet (Srpski) (sr_LATN_RS) | ![88%](https://geps.dev/progress/88) | | Sebian Latin alphabet (Srpski) (sr_LATN_RS) | ![82%](https://geps.dev/progress/82) |
| Ukrainian (Українська) (uk_UA) | ![93%](https://geps.dev/progress/93) | | Ukrainian (Українська) (uk_UA) | ![88%](https://geps.dev/progress/88) |
| Slovakian (Slovensky) (sk_SK) | ![96%](https://geps.dev/progress/96) |
## Contributing (creating issues, translations, fixing bugs, etc.) ## Contributing (creating issues, translations, fixing bugs, etc.)
@@ -201,7 +202,7 @@ Stirling PDF allows easy customization of the app.
Includes things like Includes things like
- Custom application name - Custom application name
- Custom slogans, icons, images, and even custom HTML (via file overrides) - Custom slogans, icons, HTML, images CSS etc (via file overrides)
There are two options for this, either using the generated settings file ``settings.yml`` There are two options for this, either using the generated settings file ``settings.yml``
This file is located in the ``/configs`` directory and follows standard YAML formatting This file is located in the ``/configs`` directory and follows standard YAML formatting
@@ -221,28 +222,45 @@ The Current list of settings is
```yaml ```yaml
security: security:
enableLogin: false # set to 'true' to enable login enableLogin: false # set to 'true' to enable login
csrfDisabled: true csrfDisabled: true # Set to 'true' to disable CSRF protection (not recommended for production)
loginAttemptCount: 5 # lock user account after 5 tries
loginResetTimeMinutes : 120 # lock account for 2 hours after x attempts
# initialLogin:
# username: "admin" # Initial username for the first login (these are defaulted)
# password: "stirling" # Initial password for the first login
# oauth2:
# enabled: false # set to 'true' to enable login (Note: enableLogin must also be 'true' for this to work)
# issuer: "" # set to any provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) end-point
# clientId: "" # Client ID from your provider
# clientSecret: "" # Client Secret from your provider
# autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users
# useAsUsername: "email" # Default is 'email'; custom fields can be used as the username
# 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)
googlevisibility: false # 'true' to allow Google visibility (via robots.txt), 'false' to disallow googlevisibility: false # 'true' to allow Google visibility (via robots.txt), 'false' to disallow
customStaticFilePath: '/customFiles/static/' # Directory path for custom static files enableAlphaFunctionality: false # Set to enable functionality which might need more testing before it fully goes live (This feature might make no changes)
showUpdate: true # see when a new update is available showUpdate: true # see when a new update is available
showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true' showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true'
customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template html files
#ui: ui:
# appName: exampleAppName # Application's visible name appName: null # Application's visible name
# homeDescription: I am a description # Short description or tagline shown on homepage. homeDescription: null # Short description or tagline shown on homepage.
# appNameNavbar: navbarName # Name displayed on the navigation bar appNameNavbar: null # 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'])
groupsToRemove: [] # List groups to disable (e.g. ['LibreOffice']) groupsToRemove: [] # List groups to disable (e.g. ['LibreOffice'])
metrics: metrics:
enabled: true # 'true' to enable Info APIs endpoints (view http://localhost:8080/swagger-ui/index.html#/API to learn more), 'false' to disable enabled: true # 'true' to enable Info APIs (`/api/*`) endpoints, 'false' to disable
``` ```
There is an additional config file ``/configs/custom_settings.yml`` were users familiar with java and spring application.properties can input their own settings on-top of Stirling-PDFs existing ones
### Extra notes ### Extra notes
- Endpoints. Currently, the endpoints ENDPOINTS_TO_REMOVE and GROUPS_TO_REMOVE can include comma separate lists of endpoints and groups to disable as example ENDPOINTS_TO_REMOVE=img-to-pdf,remove-pages would disable both image-to-pdf and remove pages, GROUPS_TO_REMOVE=LibreOffice Would disable all things that use LibreOffice. You can see a list of all endpoints and groups [here](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/Endpoint-groups.md) - Endpoints. Currently, the endpoints ENDPOINTS_TO_REMOVE and GROUPS_TO_REMOVE can include comma separate lists of endpoints and groups to disable as example ENDPOINTS_TO_REMOVE=img-to-pdf,remove-pages would disable both image-to-pdf and remove pages, GROUPS_TO_REMOVE=LibreOffice Would disable all things that use LibreOffice. You can see a list of all endpoints and groups [here](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/Endpoint-groups.md)
@@ -268,7 +286,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 uses 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.
- Then either enable login via the settings.yml file or via setting ``SECURITY_ENABLE_LOGIN`` to ``true`` - Then either enable login via the settings.yml file or via setting ``SECURITY_ENABLE_LOGIN`` to ``true``
- Now the initial user will be generated with username ``admin`` and password ``stirling``. On login you will be forced to change the password to a new one. You can also use the environment variables ``SECURITY_INITIALLOGIN_USERNAME`` and ``SECURITY_INITIALLOGIN_PASSWORD`` to set your own straight away (Recommended to remove them after user creation). - Now the initial user will be generated with username ``admin`` and password ``stirling``. On login you will be forced to change the password to a new one. You can also use the environment variables ``SECURITY_INITIALLOGIN_USERNAME`` and ``SECURITY_INITIALLOGIN_PASSWORD`` to set your own straight away (Recommended to remove them after user creation).

View File

@@ -12,7 +12,9 @@ plugins {
import com.github.jk1.license.render.* import com.github.jk1.license.render.*
group = 'stirling.software' group = 'stirling.software'
version = '0.23.0' version = '0.24.2'
//17 is lowest but we support and recommend 21
sourceCompatibility = '17' sourceCompatibility = '17'
repositories { repositories {
@@ -54,8 +56,8 @@ launch4j {
headerType="console" headerType="console"
jarTask = tasks.bootJar jarTask = tasks.bootJar
errTitle="Encountered error, Do you have Java 17?" errTitle="Encountered error, Do you have Java 21?"
downloadUrl="https://download.oracle.com/java/17/latest/jdk-17_windows-x64_bin.exe" downloadUrl="https://download.oracle.com/java/21/latest/jdk-21_windows-x64_bin.exe"
variables=["BROWSER_OPEN=true", "ENDPOINTS_GROUPS_TO_REMOVE=CLI"] variables=["BROWSER_OPEN=true", "ENDPOINTS_GROUPS_TO_REMOVE=CLI"]
jreMinVersion="17" jreMinVersion="17"
@@ -64,8 +66,8 @@ launch4j {
messagesStartupError="An error occurred while starting Stirling-PDF" messagesStartupError="An error occurred while starting Stirling-PDF"
//messagesJreNotFoundError="This application requires a Java Runtime Environment, Please download Java 17." //messagesJreNotFoundError="This application requires a Java Runtime Environment, Please download Java 17."
messagesJreVersionError="You are running the wrong version of Java, Please download Java 17." messagesJreVersionError="You are running the wrong version of Java, Please download Java 21."
messagesLauncherError="Java is corrupted. Please uninstall and then install Java 17." messagesLauncherError="Java is corrupted. Please uninstall and then install Java 21."
messagesInstanceAlreadyExists="Stirling-PDF is already running." messagesInstanceAlreadyExists="Stirling-PDF is already running."
} }
@@ -99,6 +101,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security:3.2.4' implementation 'org.springframework.boot:spring-boot-starter-security:3.2.4'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.2.RELEASE' implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5:3.1.2.RELEASE'
implementation "org.springframework.boot:spring-boot-starter-data-jpa:3.2.4" implementation "org.springframework.boot:spring-boot-starter-data-jpa:3.2.4"
implementation 'org.springframework.boot:spring-boot-starter-oauth2-client:3.2.4'
//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"

View File

@@ -1,5 +1,5 @@
apiVersion: v2 apiVersion: v2
appVersion: 0.23.0 appVersion: 0.24.2
description: locally hosted web application that allows you to perform various operations description: locally hosted web application that allows you to perform various operations
on PDF files on PDF files
home: https://github.com/Stirling-Tools/Stirling-PDF home: https://github.com/Stirling-Tools/Stirling-PDF

View File

@@ -0,0 +1,39 @@
version: '3.3'
services:
stirling-pdf:
container_name: Stirling-PDF-Security
image: frooodle/s-pdf:latest
deploy:
resources:
limits:
memory: 4G
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8080/api/v1/info/status | grep -q 'UP' && curl -fL http://localhost:8080/ | grep -q 'Please sign in'"]
interval: 5s
timeout: 10s
retries: 16
ports:
- 8080:8080
volumes:
- /stirling/latest/data:/usr/share/tessdata:rw
- /stirling/latest/config:/configs:rw
- /stirling/latest/logs:/logs:rw
environment:
DOCKER_ENABLE_SECURITY: "true"
SECURITY_ENABLELOGIN: "true"
SECURITY_OAUTH2_ENABLED: "true"
SECURITY_OAUTH2_AUTOCREATEUSER: "true" # This is set to true to allow auto-creation of non-existing users in Striling-PDF
SECURITY_OAUTH2_ISSUER: "https://accounts.google.com" # Change with any other provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) end-point
SECURITY_OAUTH2_CLIENTID: "<YOUR CLIENT ID>.apps.googleusercontent.com" # Client ID from your provider
SECURITY_OAUTH2_CLIENTSECRET: "<YOUR CLIENT SECRET>" # Client Secret from your provider
PUID: 1002
PGID: 1002
UMASK: "022"
SYSTEM_DEFAULTLOCALE: en-US
UI_APPNAME: Stirling-PDF
UI_HOMEDESCRIPTION: Demo site for Stirling-PDF Latest with Security
UI_APPNAMENAVBAR: Stirling-PDF Latest
SYSTEM_MAXFILESIZE: "100"
METRICS_ENABLED: "true"
SYSTEM_GOOGLEVISIBILITY: "true"
restart: on-failure:5

View File

@@ -10,49 +10,77 @@ Author: Ludy87
Example: Example:
To use this script, simply run it from command line: To use this script, simply run it from command line:
$ python counter_translation.py $ python counter_translation.py
""" """ # noqa: D205
import os
import glob import glob
import os
import re import re
from typing import List, Tuple
import tomlkit
import tomlkit.toml_file
def write_readme(progress_list: List[Tuple[str, int]]) -> None: def convert_to_multiline(data: tomlkit.TOMLDocument) -> tomlkit.TOMLDocument:
""" """Converts 'ignore' and 'missing' arrays to multiline arrays and sorts the first-level keys of the TOML document.
Updates the progress status in the README.md file based Enhances readability and consistency in the TOML file by ensuring arrays contain unique and sorted entries.
Parameters:
data (tomlkit.TOMLDocument): The original TOML document containing the data.
Returns:
tomlkit.TOMLDocument: A new TOML document with sorted keys and properly formatted arrays.
""" # noqa: D205
sorted_data = tomlkit.document()
for key in sorted(data.keys()):
value = data[key]
if isinstance(value, dict):
new_table = tomlkit.table()
for subkey in ("ignore", "missing"):
if subkey in value:
# Convert the list to a set to remove duplicates, sort it, and convert to multiline for readability
unique_sorted_array = sorted(set(value[subkey]))
array = tomlkit.array()
array.multiline(True)
for item in unique_sorted_array:
array.append(item)
new_table[subkey] = array
sorted_data[key] = new_table
else:
# Add other types of data unchanged
sorted_data[key] = value
return sorted_data
def write_readme(progress_list: list[tuple[str, int]]) -> None:
"""Updates the progress status in the README.md file based
on the provided progress list. on the provided progress list.
Parameters: Parameters:
progress_list (List[Tuple[str, int]]): A list of tuples containing progress_list (list[tuple[str, int]]): A list of tuples containing
language and progress percentage. language and progress percentage.
Returns: Returns:
None None
""" """ # noqa: D205
with open("README.md", "r", encoding="utf-8") as file: with open("README.md", encoding="utf-8") as file:
content = file.read() content = file.readlines()
lines = content.split("\n") for i, line in enumerate(content[2:], start=2):
for i, line in enumerate(lines[2:], start=2):
for progress in progress_list: for progress in progress_list:
language, value = progress language, value = progress
if language in line: if language in line:
match = re.search(r"\!\[(\d+(\.\d+)?)%\]\(.*\)", line) if match := re.search(r"\!\[(\d+(\.\d+)?)%\]\(.*\)", line):
if match: content[i] = line.replace(
lines[i] = line.replace(
match.group(0), match.group(0),
f"![{value}%](https://geps.dev/progress/{value})", f"![{value}%](https://geps.dev/progress/{value})",
) )
new_content = "\n".join(lines)
with open("README.md", "w", encoding="utf-8") as file: with open("README.md", "w", encoding="utf-8") as file:
file.write(new_content) file.writelines(content)
def compare_files(default_file_path, files_directory) -> List[Tuple[str, int]]: def compare_files(default_file_path, file_paths, translation_status_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.
Parameters: Parameters:
@@ -60,20 +88,22 @@ def compare_files(default_file_path, files_directory) -> List[Tuple[str, int]]:
files_directory (str): The directory containing other properties files. files_directory (str): The directory containing other properties files.
Returns: Returns:
List[Tuple[str, int]]: A list of tuples containing list[tuple[str, int]]: A list of tuples containing
language and progress percentage. language and progress percentage.
""" """ # noqa: D205
file_paths = glob.glob(os.path.join(files_directory, "messages_*.properties")) num_lines = sum(
num_lines = sum(1 for _ in open(default_file_path, encoding="utf-8")) 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
# read toml
with open(translation_status_file, encoding="utf-8") as f:
sort_translation_status = tomlkit.parse(f.read())
for file_path in file_paths: for file_path in file_paths:
language = ( language = os.path.basename(file_path).split("messages_", 1)[1].split(".properties", 1)[0]
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:
@@ -81,9 +111,21 @@ def compare_files(default_file_path, files_directory) -> List[Tuple[str, int]]:
result_list.append(("en_US", 100)) result_list.append(("en_US", 100))
continue continue
with open(default_file_path, "r", encoding="utf-8") as default_file, open( if language not in sort_translation_status:
file_path, "r", encoding="utf-8" sort_translation_status[language] = tomlkit.table()
) as file:
if (
"ignore" not in sort_translation_status[language]
or len(sort_translation_status[language].get("ignore", [])) < 1
):
sort_translation_status[language]["ignore"] = tomlkit.array(["language.direction"])
# if "missing" not in sort_translation_status[language]:
# sort_translation_status[language]["missing"] = tomlkit.array()
# elif "language.direction" in sort_translation_status[language]["missing"]:
# sort_translation_status[language]["missing"].remove("language.direction")
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:
@@ -91,24 +133,47 @@ def compare_files(default_file_path, files_directory) -> List[Tuple[str, int]]:
except StopIteration: except StopIteration:
fails = num_lines fails = num_lines
for _, (line_default, line_file) in enumerate( for line_num, (line_default, line_file) in enumerate(zip(default_file, file), start=6):
zip(default_file, file), start=6
):
try: try:
# Ignoring empty lines and lines start with #
if line_default.strip() == "" or line_default.startswith("#"):
continue
default_key, default_value = line_default.split("=", 1)
file_key, file_value = line_file.split("=", 1)
if ( if (
line_default.split("=", 1)[1].strip() default_value.strip() == file_value.strip()
== line_file.split("=", 1)[1].strip() and default_key.strip() not in sort_translation_status[language]["ignore"]
): ):
print(f"{language}: Line {line_num} is missing the translation.")
# if default_key.strip() not in sort_translation_status[language]["missing"]:
# missing_array = tomlkit.array()
# missing_array.append(default_key.strip())
# missing_array.multiline(True)
# sort_translation_status[language]["missing"].extend(missing_array)
fails += 1 fails += 1
# elif default_key.strip() in sort_translation_status[language]["ignore"]:
# if default_key.strip() in sort_translation_status[language]["missing"]:
# sort_translation_status[language]["missing"].remove(default_key.strip())
if default_value.strip() != file_value.strip():
# if default_key.strip() in sort_translation_status[language]["missing"]:
# sort_translation_status[language]["missing"].remove(default_key.strip())
if default_key.strip() in sort_translation_status[language]["ignore"]:
sort_translation_status[language]["ignore"].remove(default_key.strip())
except IndexError: except IndexError:
pass pass
print(f"{language}: {fails} out of {num_lines} lines are not translated.")
result_list.append( result_list.append(
( (
language, language,
int((num_lines - fails) * 100 / num_lines), int((num_lines - fails) * 100 / num_lines),
) )
) )
translation_status = convert_to_multiline(sort_translation_status)
with open(translation_status_file, "w", encoding="utf-8") as file:
file.write(tomlkit.dumps(translation_status))
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)
@@ -118,5 +183,10 @@ def compare_files(default_file_path, files_directory) -> List[Tuple[str, int]]:
if __name__ == "__main__": if __name__ == "__main__":
directory = os.path.join(os.getcwd(), "src", "main", "resources") directory = os.path.join(os.getcwd(), "src", "main", "resources")
messages_file_paths = glob.glob(os.path.join(directory, "messages_*.properties"))
reference_file = os.path.join(directory, "messages_en_GB.properties") reference_file = os.path.join(directory, "messages_en_GB.properties")
write_readme(compare_files(reference_file, directory))
scripts_directory = os.path.join(os.getcwd(), "scripts")
translation_state_file = os.path.join(scripts_directory, "translation_status.toml")
write_readme(compare_files(reference_file, messages_file_paths, translation_state_file))

View File

@@ -0,0 +1,159 @@
[ar_AR]
ignore = [
'language.direction',
]
[bg_BG]
ignore = [
'language.direction',
]
[ca_CA]
ignore = [
'language.direction',
]
[de_DE]
ignore = [
'AddStampRequest.alphabet',
'AddStampRequest.position',
'PDFToBook.selectText.1',
'PDFToText.tags',
'addPageNumbers.selectText.3',
'alphabet',
'certSign.name',
'language.direction',
'licenses.version',
'pipeline.title',
'pipelineOptions.pipelineHeader',
'sponsor',
'text',
'watermark.type.1',
]
[el_GR]
ignore = [
'language.direction',
]
[es_ES]
ignore = [
'adminUserSettings.roles',
'color',
'language.direction',
'no',
'showJS.tags',
]
[eu_ES]
ignore = [
'language.direction',
]
[fr_FR]
ignore = [
'language.direction',
]
[hi_IN]
ignore = [
'language.direction',
]
[hu_HU]
ignore = [
'language.direction',
]
[id_ID]
ignore = [
'language.direction',
]
[it_IT]
ignore = [
'font',
'language.direction',
'no',
'password',
'pipeline.title',
'pipelineOptions.pipelineHeader',
'removePassword.selectText.2',
'showJS.tags',
'sponsor',
]
[ja_JP]
ignore = [
'language.direction',
]
[ko_KR]
ignore = [
'language.direction',
]
[nl_NL]
ignore = [
'language.direction',
]
[pl_PL]
ignore = [
'language.direction',
]
[pt_BR]
ignore = [
'language.direction',
]
[pt_PT]
ignore = [
'language.direction',
]
[ro_RO]
ignore = [
'language.direction',
]
[ru_RU]
ignore = [
'language.direction',
]
[sk_SK]
ignore = [
'language.direction',
]
[sr_LATN_RS]
ignore = [
'language.direction',
]
[sv_SE]
ignore = [
'language.direction',
]
[tr_TR]
ignore = [
'language.direction',
]
[uk_UA]
ignore = [
'language.direction',
]
[zh_CN]
ignore = [
'language.direction',
]
[zh_TW]
ignore = [
'language.direction',
]

View File

@@ -5,6 +5,8 @@ import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -65,14 +67,36 @@ public class SPdfApplication {
SpringApplication app = new SpringApplication(SPdfApplication.class); SpringApplication app = new SpringApplication(SPdfApplication.class);
app.addInitializers(new ConfigInitializer()); app.addInitializers(new ConfigInitializer());
Map<String, String> propertyFiles = new HashMap<>();
// stirling pdf settings file
if (Files.exists(Paths.get("configs/settings.yml"))) { if (Files.exists(Paths.get("configs/settings.yml"))) {
app.setDefaultProperties( propertyFiles.put("spring.config.additional-location", "file:configs/settings.yml");
Collections.singletonMap(
"spring.config.additional-location", "file:configs/settings.yml"));
} else { } else {
logger.warn( logger.warn(
"External configuration file 'configs/settings.yml' does not exist. Using default configuration and environment configuration instead."); "External configuration file 'configs/settings.yml' does not exist. Using default configuration and environment configuration instead.");
} }
// custom javs settings file
if (Files.exists(Paths.get("configs/custom_settings.yml"))) {
String existing = propertyFiles.getOrDefault("spring.config.additional-location", "");
if (!existing.isEmpty()) {
existing += ",";
}
propertyFiles.put(
"spring.config.additional-location",
existing + "file:configs/custom_settings.yml");
} else {
logger.warn("Custom configuration file 'configs/custom_settings.yml' does not exist.");
}
if (!propertyFiles.isEmpty()) {
app.setDefaultProperties(
Collections.singletonMap(
"spring.config.additional-location",
propertyFiles.get("spring.config.additional-location")));
}
app.run(args); app.run(args);
try { try {

View File

@@ -7,18 +7,34 @@ import java.util.Properties;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.thymeleaf.spring6.SpringTemplateEngine;
import stirling.software.SPDF.model.ApplicationProperties; import stirling.software.SPDF.model.ApplicationProperties;
@Configuration @Configuration
@Lazy
public class AppConfig { public class AppConfig {
@Autowired ApplicationProperties applicationProperties; @Autowired ApplicationProperties applicationProperties;
@Bean
@ConditionalOnProperty(
name = "system.customHTMLFiles",
havingValue = "true",
matchIfMissing = false)
public SpringTemplateEngine templateEngine(ResourceLoader resourceLoader) {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.addTemplateResolver(new FileFallbackTemplateResolver(resourceLoader));
return templateEngine;
}
@Bean(name = "loginEnabled") @Bean(name = "loginEnabled")
public boolean loginEnabled() { public boolean loginEnabled() {
return applicationProperties.getSecurity().getEnableLogin(); return applicationProperties.getSecurity().getEnableLogin();

View File

@@ -15,7 +15,14 @@ public class CleanUrlInterceptor implements HandlerInterceptor {
private static final List<String> ALLOWED_PARAMS = private static final List<String> ALLOWED_PARAMS =
Arrays.asList( Arrays.asList(
"lang", "endpoint", "endpoints", "logout", "error", "file", "messageType"); "lang",
"endpoint",
"endpoints",
"logout",
"error",
"erroroauth",
"file",
"messageType");
@Override @Override
public boolean preHandle( public boolean preHandle(

View File

@@ -1,20 +1,18 @@
package stirling.software.SPDF.config; package stirling.software.SPDF.config;
import java.io.BufferedReader;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
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 java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.ConfigurableApplicationContext;
@@ -26,12 +24,12 @@ public class ConfigInitializer
public void initialize(ConfigurableApplicationContext applicationContext) { public void initialize(ConfigurableApplicationContext applicationContext) {
try { try {
ensureConfigExists(); ensureConfigExists();
} catch (IOException e) { } catch (Exception e) {
throw new RuntimeException("Failed to initialize application configuration", e); throw new RuntimeException("Failed to initialize application configuration", e);
} }
} }
public void ensureConfigExists() throws IOException { public void ensureConfigExists() throws IOException, URISyntaxException {
// Define the path to the external config directory // Define the path to the external config directory
Path destPath = Paths.get("configs", "settings.yml"); Path destPath = Paths.get("configs", "settings.yml");
@@ -51,170 +49,90 @@ public class ConfigInitializer
} }
} }
} else { } else {
// If user file exists, we need to merge it with the template from the classpath Path templatePath =
List<String> templateLines; Paths.get(
try (InputStream in = getClass()
getClass().getClassLoader().getResourceAsStream("settings.yml.template")) { .getClassLoader()
templateLines = .getResource("settings.yml.template")
new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)) .toURI());
.lines() Path userPath = Paths.get("configs", "settings.yml");
.collect(Collectors.toList());
}
mergeYamlFiles(templateLines, destPath, destPath); List<String> templateLines = Files.readAllLines(templatePath);
} List<String> userLines =
} Files.exists(userPath) ? Files.readAllLines(userPath) : new ArrayList<>();
public void mergeYamlFiles(List<String> templateLines, Path userFilePath, Path outputPath) List<String> resultLines = new ArrayList<>();
throws IOException {
List<String> userLines = Files.readAllLines(userFilePath);
List<String> mergedLines = new ArrayList<>();
boolean insideAutoGenerated = false;
boolean beforeFirstKey = true;
Function<String, Boolean> isCommented = line -> line.trim().startsWith("#"); for (String templateLine : templateLines) {
Function<String, String> extractKey = // Check if the line is a comment
line -> { if (templateLine.trim().startsWith("#")) {
String[] parts = line.split(":"); String entry = templateLine.trim().substring(1).trim();
return parts.length > 0 ? parts[0].trim().replace("#", "").trim() : ""; if (!entry.isEmpty()) {
}; // Check if this comment has been uncommented in userLines
String key = entry.split(":")[0].trim();
Function<String, Integer> getIndentationLevel = System.out.println("key=" + key + ", entry=" + entry );
line -> { addLine(resultLines, userLines, templateLine, key);
int count = 0; } else {
for (char ch : line.toCharArray()) { resultLines.add(templateLine);
if (ch == ' ') count++;
else break;
} }
return count; }
}; // Check if the line is a key-value pair
else if (templateLine.contains(":")) {
Set<String> userKeys = userLines.stream().map(extractKey).collect(Collectors.toSet()); String key = templateLine.split(":")[0].trim();
addLine(resultLines, userLines, templateLine, key);
for (String line : templateLines) { }
String key = extractKey.apply(line); // Handle empty lines
else if (templateLine.trim().length() == 0) {
if ("AutomaticallyGenerated:".equalsIgnoreCase(line.trim())) { resultLines.add("");
insideAutoGenerated = true;
mergedLines.add(line);
continue;
} else if (insideAutoGenerated && line.trim().isEmpty()) {
insideAutoGenerated = false;
mergedLines.add(line);
continue;
}
if (beforeFirstKey && (isCommented.apply(line) || line.trim().isEmpty())) {
// Handle top comments and empty lines before the first key.
mergedLines.add(line);
continue;
}
if (!key.isEmpty()) beforeFirstKey = false;
if (userKeys.contains(key)) {
// If user has any version (commented or uncommented) of this key, skip the
// template line
Optional<String> userValue =
userLines.stream()
.filter(
l ->
extractKey.apply(l).equalsIgnoreCase(key)
&& !isCommented.apply(l))
.findFirst();
if (userValue.isPresent()) mergedLines.add(userValue.get());
continue;
}
if (isCommented.apply(line) || line.trim().isEmpty() || !userKeys.contains(key)) {
mergedLines.add(
line); // If line is commented, empty or key not present in user's file,
// retain the
// template line
continue;
}
}
// Add any additional uncommented user lines that are not present in the
// template
for (String userLine : userLines) {
String userKey = extractKey.apply(userLine);
boolean isPresentInTemplate =
templateLines.stream()
.map(extractKey)
.anyMatch(templateKey -> templateKey.equalsIgnoreCase(userKey));
if (!isPresentInTemplate && !isCommented.apply(userLine)) {
if (!childOfTemplateEntry(
isCommented,
extractKey,
getIndentationLevel,
userLines,
userLine,
templateLines)) {
// check if userLine is a child of a entry within templateLines or not, if child
// of parent in templateLines then dont add to mergedLines, if anything else
// then add
mergedLines.add(userLine);
} }
} }
// Write the result to the user settings file
Files.write(userPath, resultLines);
} }
Files.write(outputPath, mergedLines, StandardCharsets.UTF_8); Path customSettingsPath = Paths.get("configs", "custom_settings.yml");
if (!Files.exists(customSettingsPath)) {
Files.createFile(customSettingsPath);
}
} }
// New method to check if a userLine is a child of an entry in templateLines
boolean childOfTemplateEntry(
Function<String, Boolean> isCommented, //TODO check parent value instead of just indent lines for duplicate keys (like enabled etc)
Function<String, String> extractKey, private static void addLine(List<String> resultLines, List<String> userLines, String templateLine, String key) {
Function<String, Integer> getIndentationLevel, boolean added = false;
List<String> userLines, int templateIndentationLevel = getIndentationLevel(templateLine);
String userLine, for (String settingsLine : userLines) {
List<String> templateLines) { if(settingsLine.contains("oauth2") || settingsLine.contains("enabled") )
String userKey = extractKey.apply(userLine).trim(); if (settingsLine.trim().startsWith(key + ":")) {
int userIndentation = getIndentationLevel.apply(userLine); int settingsIndentationLevel = getIndentationLevel(settingsLine);
// Check if it is correct settingsLine and has the same parent as templateLine
// Start by assuming the line is not a child of an entry in templateLines if (settingsIndentationLevel == templateIndentationLevel) {
boolean isChild = false; resultLines.add(settingsLine);
added = true;
// Iterate backwards through userLines from the current line to find any parent
for (int i = userLines.indexOf(userLine) - 1; i >= 0; i--) {
String potentialParentLine = userLines.get(i);
int parentIndentation = getIndentationLevel.apply(potentialParentLine);
// Check if we've reached a potential parent based on indentation
if (parentIndentation < userIndentation) {
String parentKey = extractKey.apply(potentialParentLine).trim();
// Now, check if this potential parent or any of its parents exist in templateLines
boolean parentExistsInTemplate =
templateLines.stream()
.filter(line -> !isCommented.apply(line)) // Skip commented lines
.anyMatch(
templateLine -> {
String templateKey =
extractKey.apply(templateLine).trim();
return parentKey.equalsIgnoreCase(templateKey);
});
if (!parentExistsInTemplate) {
// If the parent does not exist in template, check the next level parent
userIndentation =
parentIndentation; // Update userIndentation to the parent's indentation
// for next iteration
if (parentIndentation == 0) {
// If we've reached the top-level parent and it's not in template, the
// original line is considered not a child
isChild = false;
break;
}
} else {
// If any parent exists in template, the original line is considered a child
isChild = true;
break; break;
} }
} }
} }
if (!added) {
resultLines.add(templateLine);
}
}
return isChild; // Return true if the line is not a child of any entry in templateLines private static int getIndentationLevel(String line) {
int indentationLevel = 0;
String trimmedLine = line.trim();
if (trimmedLine.startsWith("#")) {
line = trimmedLine.substring(1);
}
for (char c : line.toCharArray()) {
if (c == ' ') {
indentationLevel++;
} else {
break;
}
}
return indentationLevel;
} }
} }

View File

@@ -0,0 +1,48 @@
package stirling.software.SPDF.config;
import java.io.IOException;
import java.util.Map;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.thymeleaf.IEngineConfiguration;
import org.thymeleaf.templateresolver.AbstractConfigurableTemplateResolver;
import org.thymeleaf.templateresource.ClassLoaderTemplateResource;
import org.thymeleaf.templateresource.FileTemplateResource;
import org.thymeleaf.templateresource.ITemplateResource;
public class FileFallbackTemplateResolver extends AbstractConfigurableTemplateResolver {
private final ResourceLoader resourceLoader;
public FileFallbackTemplateResolver(ResourceLoader resourceLoader) {
super();
this.resourceLoader = resourceLoader;
setSuffix(".html");
}
// Note this does not work in local IDE, Prod jar only.
@Override
protected ITemplateResource computeTemplateResource(
IEngineConfiguration configuration,
String ownerTemplate,
String template,
String resourceName,
String characterEncoding,
Map<String, Object> templateResolutionAttributes) {
Resource resource =
resourceLoader.getResource("file:./customFiles/templates/" + resourceName);
try {
if (resource.exists() && resource.isReadable()) {
return new FileTemplateResource(resource.getFile().getPath(), characterEncoding);
}
} catch (IOException e) {
}
return new ClassLoaderTemplateResource(
Thread.currentThread().getContextClassLoader(),
"classpath:/templates/" + resourceName,
characterEncoding);
}
}

View File

@@ -3,27 +3,31 @@ package stirling.software.SPDF.config.security;
import java.io.IOException; import java.io.IOException;
import java.util.Optional; import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired; import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.LockedException; import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler; import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import jakarta.servlet.ServletException; import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import stirling.software.SPDF.model.User; import stirling.software.SPDF.model.User;
@Component
public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
@Autowired private final LoginAttemptService loginAttemptService; private LoginAttemptService loginAttemptService;
@Autowired private final UserService userService; // Inject the UserService private UserService userService;
private static final Logger logger =
LoggerFactory.getLogger(CustomAuthenticationFailureHandler.class);
public CustomAuthenticationFailureHandler( public CustomAuthenticationFailureHandler(
LoginAttemptService loginAttemptService, UserService userService) { final LoginAttemptService loginAttemptService, UserService userService) {
this.loginAttemptService = loginAttemptService; this.loginAttemptService = loginAttemptService;
this.userService = userService; this.userService = userService;
} }
@@ -34,22 +38,33 @@ public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationF
HttpServletResponse response, HttpServletResponse response,
AuthenticationException exception) AuthenticationException exception)
throws IOException, ServletException { throws IOException, ServletException {
String ip = request.getRemoteAddr(); String ip = request.getRemoteAddr();
logger.error("Failed login attempt from IP: " + ip); logger.error("Failed login attempt from IP: {}", ip);
if (exception.getClass().isAssignableFrom(InternalAuthenticationServiceException.class)
|| "Password must not be null".equalsIgnoreCase(exception.getMessage())) {
response.sendRedirect("/login?error=oauth2AuthenticationError");
return;
}
String username = request.getParameter("username"); String username = request.getParameter("username");
if (!isDemoUser(username)) { if (username != null && !isDemoUser(username)) {
if (loginAttemptService.loginAttemptCheck(username)) { logger.info(
setDefaultFailureUrl("/login?error=locked"); "Remaining attempts for user {}: {}",
username,
} else { loginAttemptService.getRemainingAttempts(username));
if (exception.getClass().isAssignableFrom(LockedException.class)) { loginAttemptService.loginFailed(username);
setDefaultFailureUrl("/login?error=locked"); if (loginAttemptService.isBlocked(username)
} || exception.getClass().isAssignableFrom(LockedException.class)) {
response.sendRedirect("/login?error=locked");
return;
} }
} }
if (exception.getClass().isAssignableFrom(BadCredentialsException.class)) { if (exception.getClass().isAssignableFrom(BadCredentialsException.class)
setDefaultFailureUrl("/login?error=badcredentials"); || exception.getClass().isAssignableFrom(UsernameNotFoundException.class)) {
response.sendRedirect("/login?error=badcredentials");
return;
} }
super.onAuthenticationFailure(request, response, exception); super.onAuthenticationFailure(request, response, exception);

View File

@@ -2,11 +2,9 @@ package stirling.software.SPDF.config.security;
import java.io.IOException; import java.io.IOException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.savedrequest.SavedRequest; import org.springframework.security.web.savedrequest.SavedRequest;
import org.springframework.stereotype.Component;
import jakarta.servlet.ServletException; import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
@@ -14,25 +12,30 @@ import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession; import jakarta.servlet.http.HttpSession;
import stirling.software.SPDF.utils.RequestUriUtils; import stirling.software.SPDF.utils.RequestUriUtils;
@Component
public class CustomAuthenticationSuccessHandler public class CustomAuthenticationSuccessHandler
extends SavedRequestAwareAuthenticationSuccessHandler { extends SavedRequestAwareAuthenticationSuccessHandler {
@Autowired private LoginAttemptService loginAttemptService; private LoginAttemptService loginAttemptService;
public CustomAuthenticationSuccessHandler(LoginAttemptService loginAttemptService) {
this.loginAttemptService = loginAttemptService;
}
@Override @Override
public void onAuthenticationSuccess( public void onAuthenticationSuccess(
HttpServletRequest request, HttpServletResponse response, Authentication authentication) HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws ServletException, IOException { throws ServletException, IOException {
String username = request.getParameter("username");
loginAttemptService.loginSucceeded(username); String userName = request.getParameter("username");
loginAttemptService.loginSucceeded(userName);
// Get the saved request // Get the saved request
HttpSession session = request.getSession(false); HttpSession session = request.getSession(false);
SavedRequest savedRequest = SavedRequest savedRequest =
session != null (session != null)
? (SavedRequest) session.getAttribute("SPRING_SECURITY_SAVED_REQUEST") ? (SavedRequest) session.getAttribute("SPRING_SECURITY_SAVED_REQUEST")
: null; : null;
if (savedRequest != null if (savedRequest != null
&& !RequestUriUtils.isStaticResource(savedRequest.getRedirectUrl())) { && !RequestUriUtils.isStaticResource(savedRequest.getRedirectUrl())) {
// Redirect to the original destination // Redirect to the original destination

View File

@@ -0,0 +1,33 @@
package stirling.software.SPDF.config.security;
import java.io.IOException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
public class CustomLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
@Autowired SessionRegistry sessionRegistry;
@Override
public void onLogoutSuccess(
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
HttpSession session = request.getSession(false);
if (session != null) {
String sessionId = session.getId();
sessionRegistry.removeSessionInformation(sessionId);
session.invalidate();
logger.debug("Session invalidated: " + sessionId);
}
response.sendRedirect(request.getContextPath() + "/login?logout=true");
}
}

View File

@@ -39,6 +39,10 @@ public class CustomUserDetailsService implements UserDetailsService {
"Your account has been locked due to too many failed login attempts."); "Your account has been locked due to too many failed login attempts.");
} }
if (!user.hasPassword()) {
throw new IllegalArgumentException("Password must not be null");
}
return new org.springframework.security.core.userdetails.User( return new org.springframework.security.core.userdetails.User(
user.getUsername(), user.getUsername(),
user.getPassword(), user.getPassword(),

View File

@@ -7,6 +7,8 @@ import java.nio.file.Paths;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
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;
@@ -19,40 +21,67 @@ public class InitialSecuritySetup {
@Autowired private UserService userService; @Autowired private UserService userService;
@Autowired ApplicationProperties applicationProperties; @Autowired private ApplicationProperties applicationProperties;
private static final Logger logger = LoggerFactory.getLogger(InitialSecuritySetup.class);
@PostConstruct @PostConstruct
public void init() { public void init() {
if (!userService.hasUsers()) { if (!userService.hasUsers()) {
initializeAdminUser();
String initialUsername =
applicationProperties.getSecurity().getInitialLogin().getUsername();
String initialPassword =
applicationProperties.getSecurity().getInitialLogin().getPassword();
if (initialUsername != null && initialPassword != null) {
userService.saveUser(initialUsername, initialPassword, Role.ADMIN.getRoleId());
} else {
initialUsername = "admin";
initialPassword = "stirling";
userService.saveUser(
initialUsername, initialPassword, Role.ADMIN.getRoleId(), true);
}
} }
initializeInternalApiUser();
}
@PostConstruct
public void initSecretKey() throws IOException {
String secretKey = applicationProperties.getAutomaticallyGenerated().getKey();
if (!isValidUUID(secretKey)) {
secretKey = UUID.randomUUID().toString(); // Generating a random UUID as the secret key
saveKeyToConfig(secretKey);
}
}
private void initializeAdminUser() {
String initialUsername =
applicationProperties.getSecurity().getInitialLogin().getUsername();
String initialPassword =
applicationProperties.getSecurity().getInitialLogin().getPassword();
if (initialUsername != null
&& !initialUsername.isEmpty()
&& initialPassword != null
&& !initialPassword.isEmpty()
&& !userService.findByUsernameIgnoreCase(initialUsername).isPresent()) {
try {
userService.saveUser(initialUsername, initialPassword, Role.ADMIN.getRoleId());
logger.info("Admin user created: " + initialUsername);
} catch (IllegalArgumentException e) {
logger.error("Failed to initialize security setup", e);
System.exit(1);
}
} else {
createDefaultAdminUser();
}
}
private void createDefaultAdminUser() {
String defaultUsername = "admin";
String defaultPassword = "stirling";
if (!userService.findByUsernameIgnoreCase(defaultUsername).isPresent()) {
userService.saveUser(defaultUsername, defaultPassword, Role.ADMIN.getRoleId(), true);
logger.info("Default admin user created: " + defaultUsername);
}
}
private void initializeInternalApiUser() {
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());
}
@PostConstruct
public void initSecretKey() throws IOException {
String secretKey = applicationProperties.getAutomaticallyGenerated().getKey();
if (secretKey == null || secretKey.isEmpty()) {
secretKey = UUID.randomUUID().toString(); // Generating a random UUID as the secret key
saveKeyToConfig(secretKey);
} }
} }
@@ -85,4 +114,16 @@ public class InitialSecuritySetup {
// Write back to the file // Write back to the file
Files.write(path, lines); Files.write(path, lines);
} }
private boolean isValidUUID(String uuid) {
if (uuid == null) {
return false;
}
try {
UUID.fromString(uuid);
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
} }

View File

@@ -3,6 +3,8 @@ package stirling.software.SPDF.config.security;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
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.Service; import org.springframework.stereotype.Service;
@@ -15,44 +17,62 @@ public class LoginAttemptService {
@Autowired ApplicationProperties applicationProperties; @Autowired ApplicationProperties applicationProperties;
private int MAX_ATTEMPTS; private static final Logger logger = LoggerFactory.getLogger(LoginAttemptService.class);
private int MAX_ATTEMPT;
private long ATTEMPT_INCREMENT_TIME; private long ATTEMPT_INCREMENT_TIME;
private ConcurrentHashMap<String, AttemptCounter> attemptsCache;
@PostConstruct @PostConstruct
public void init() { public void init() {
MAX_ATTEMPTS = applicationProperties.getSecurity().getLoginAttemptCount(); MAX_ATTEMPT = applicationProperties.getSecurity().getLoginAttemptCount();
ATTEMPT_INCREMENT_TIME = ATTEMPT_INCREMENT_TIME =
TimeUnit.MINUTES.toMillis( TimeUnit.MINUTES.toMillis(
applicationProperties.getSecurity().getLoginResetTimeMinutes()); applicationProperties.getSecurity().getLoginResetTimeMinutes());
attemptsCache = new ConcurrentHashMap<>();
} }
private final ConcurrentHashMap<String, AttemptCounter> attemptsCache =
new ConcurrentHashMap<>();
public void loginSucceeded(String key) { public void loginSucceeded(String key) {
attemptsCache.remove(key); logger.info(key + " " + attemptsCache.mappingCount());
if (key == null || key.trim().isEmpty()) {
return;
}
attemptsCache.remove(key.toLowerCase());
} }
public boolean loginAttemptCheck(String key) { public void loginFailed(String key) {
attemptsCache.compute( if (key == null || key.trim().isEmpty()) return;
key,
(k, attemptCounter) -> { AttemptCounter attemptCounter = attemptsCache.get(key.toLowerCase());
if (attemptCounter == null if (attemptCounter == null) {
|| attemptCounter.shouldReset(ATTEMPT_INCREMENT_TIME)) { attemptCounter = new AttemptCounter();
return new AttemptCounter(); attemptsCache.put(key.toLowerCase(), attemptCounter);
} else { } else {
attemptCounter.increment(); if (attemptCounter.shouldReset(ATTEMPT_INCREMENT_TIME)) {
return attemptCounter; attemptCounter.reset();
} }
}); attemptCounter.increment();
return attemptsCache.get(key).getAttemptCount() >= MAX_ATTEMPTS; }
} }
public boolean isBlocked(String key) { public boolean isBlocked(String key) {
AttemptCounter attemptCounter = attemptsCache.get(key); if (key == null || key.trim().isEmpty()) return false;
if (attemptCounter != null) { AttemptCounter attemptCounter = attemptsCache.get(key.toLowerCase());
return attemptCounter.getAttemptCount() >= MAX_ATTEMPTS; if (attemptCounter == null) {
return false;
} }
return false;
return attemptCounter.getAttemptCount() >= MAX_ATTEMPT;
}
public int getRemainingAttempts(String key) {
if (key == null || key.trim().isEmpty()) return MAX_ATTEMPT;
AttemptCounter attemptCounter = attemptsCache.get(key.toLowerCase());
if (attemptCounter == null) {
return MAX_ATTEMPT;
}
return MAX_ATTEMPT - attemptCounter.getAttemptCount();
} }
} }

View File

@@ -1,7 +1,10 @@
package stirling.software.SPDF.config.security; package stirling.software.SPDF.config.security;
import java.util.*;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy; import org.springframework.context.annotation.Lazy;
@@ -10,18 +13,31 @@ import org.springframework.security.config.annotation.method.configuration.Enabl
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.core.session.SessionRegistry; import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.core.session.SessionRegistryImpl; import org.springframework.security.core.session.SessionRegistryImpl;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.registration.ClientRegistrations;
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository; import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import org.springframework.security.web.savedrequest.NullRequestCache; import org.springframework.security.web.savedrequest.NullRequestCache;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import jakarta.servlet.http.HttpSession; import stirling.software.SPDF.config.security.oauth2.CustomOAuth2AuthenticationFailureHandler;
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2AuthenticationSuccessHandler;
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2LogoutSuccessHandler;
import stirling.software.SPDF.config.security.oauth2.CustomOAuth2UserService;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.SPDF.model.User;
import stirling.software.SPDF.repository.JPATokenRepositoryImpl; import stirling.software.SPDF.repository.JPATokenRepositoryImpl;
@Configuration @Configuration
@@ -29,7 +45,7 @@ import stirling.software.SPDF.repository.JPATokenRepositoryImpl;
@EnableMethodSecurity @EnableMethodSecurity
public class SecurityConfiguration { public class SecurityConfiguration {
@Autowired private UserDetailsService userDetailsService; @Autowired private CustomUserDetailsService userDetailsService;
@Bean @Bean
public PasswordEncoder passwordEncoder() { public PasswordEncoder passwordEncoder() {
@@ -42,6 +58,8 @@ public class SecurityConfiguration {
@Qualifier("loginEnabled") @Qualifier("loginEnabled")
public boolean loginEnabledValue; public boolean loginEnabledValue;
@Autowired ApplicationProperties applicationProperties;
@Autowired private UserAuthenticationFilter userAuthenticationFilter; @Autowired private UserAuthenticationFilter userAuthenticationFilter;
@Autowired private LoginAttemptService loginAttemptService; @Autowired private LoginAttemptService loginAttemptService;
@@ -76,7 +94,8 @@ public class SecurityConfiguration {
formLogin formLogin
.loginPage("/login") .loginPage("/login")
.successHandler( .successHandler(
new CustomAuthenticationSuccessHandler()) new CustomAuthenticationSuccessHandler(
loginAttemptService))
.defaultSuccessUrl("/") .defaultSuccessUrl("/")
.failureHandler( .failureHandler(
new CustomAuthenticationFailureHandler( new CustomAuthenticationFailureHandler(
@@ -87,20 +106,9 @@ public class SecurityConfiguration {
logout -> logout ->
logout.logoutRequestMatcher( logout.logoutRequestMatcher(
new AntPathRequestMatcher("/logout")) new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/login?logout=true") .logoutSuccessHandler(new CustomLogoutSuccessHandler())
.invalidateHttpSession(true) // Invalidate session .invalidateHttpSession(true) // Invalidate session
.deleteCookies("JSESSIONID", "remember-me") .deleteCookies("JSESSIONID", "remember-me"))
.addLogoutHandler(
(request, response, authentication) -> {
HttpSession session =
request.getSession(false);
if (session != null) {
String sessionId = session.getId();
sessionRegistry()
.removeSessionInformation(
sessionId);
}
}))
.rememberMe( .rememberMe(
rememberMeConfigurer -> rememberMeConfigurer ->
rememberMeConfigurer // Use the configurator directly rememberMeConfigurer // Use the configurator directly
@@ -124,6 +132,7 @@ public class SecurityConfiguration {
: uri; : uri;
return trimmedUri.startsWith("/login") return trimmedUri.startsWith("/login")
|| trimmedUri.startsWith("/oauth")
|| trimmedUri.endsWith(".svg") || trimmedUri.endsWith(".svg")
|| trimmedUri.startsWith( || trimmedUri.startsWith(
"/register") "/register")
@@ -138,8 +147,44 @@ public class SecurityConfiguration {
.permitAll() .permitAll()
.anyRequest() .anyRequest()
.authenticated()) .authenticated())
.userDetailsService(userDetailsService)
.authenticationProvider(authenticationProvider()); .authenticationProvider(authenticationProvider());
// Handle OAUTH2 Logins
if (applicationProperties.getSecurity().getOAUTH2().getEnabled()) {
http.oauth2Login(
oauth2 ->
oauth2.loginPage("/oauth2")
/*
This Custom handler is used to check if the OAUTH2 user trying to log in, already exists in the database.
If user exists, login proceeds as usual. If user does not exist, then it is autocreated but only if 'OAUTH2AutoCreateUser'
is set as true, else login fails with an error message advising the same.
*/
.successHandler(
new CustomOAuth2AuthenticationSuccessHandler(
loginAttemptService,
applicationProperties,
userService))
.failureHandler(
new CustomOAuth2AuthenticationFailureHandler())
// Add existing Authorities from the database
.userInfoEndpoint(
userInfoEndpoint ->
userInfoEndpoint
.oidcUserService(
new CustomOAuth2UserService(
applicationProperties,
userService,
loginAttemptService))
.userAuthoritiesMapper(
userAuthoritiesMapper())))
.logout(
logout ->
logout.logoutSuccessHandler(
new CustomOAuth2LogoutSuccessHandler(
this.applicationProperties,
sessionRegistry())));
}
} else { } else {
http.csrf(csrf -> csrf.disable()) http.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(authz -> authz.anyRequest().permitAll()); .authorizeHttpRequests(authz -> authz.anyRequest().permitAll());
@@ -148,6 +193,70 @@ public class SecurityConfiguration {
return http.build(); return http.build();
} }
// Client Registration Repository for OAUTH2 OIDC Login
@Bean
@ConditionalOnProperty(
value = "security.oauth2.enabled",
havingValue = "true",
matchIfMissing = false)
public ClientRegistrationRepository clientRegistrationRepository() {
return new InMemoryClientRegistrationRepository(this.oidcClientRegistration());
}
private ClientRegistration oidcClientRegistration() {
OAUTH2 oauth = applicationProperties.getSecurity().getOAUTH2();
return ClientRegistrations.fromIssuerLocation(oauth.getIssuer())
.registrationId("oidc")
.clientId(oauth.getClientId())
.clientSecret(oauth.getClientSecret())
.scope(oauth.getScopes())
.userNameAttributeName(oauth.getUseAsUsername())
.clientName("OIDC")
.build();
}
/*
This following function is to grant Authorities to the OAUTH2 user from the values stored in the database.
This is required for the internal; 'hasRole()' function to give out the correct role.
*/
@Bean
@ConditionalOnProperty(
value = "security.oauth2.enabled",
havingValue = "true",
matchIfMissing = false)
GrantedAuthoritiesMapper userAuthoritiesMapper() {
return (authorities) -> {
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
authorities.forEach(
authority -> {
// Add existing OAUTH2 Authorities
mappedAuthorities.add(new SimpleGrantedAuthority(authority.getAuthority()));
// Add Authorities from database for existing user, if user is present.
if (authority instanceof OAuth2UserAuthority oauth2Auth) {
String useAsUsername =
applicationProperties
.getSecurity()
.getOAUTH2()
.getUseAsUsername();
Optional<User> userOpt =
userService.findByUsernameIgnoreCase(
(String) oauth2Auth.getAttributes().get(useAsUsername));
if (userOpt.isPresent()) {
User user = userOpt.get();
if (user != null) {
mappedAuthorities.add(
new SimpleGrantedAuthority(
userService.findRole(user).getAuthority()));
}
}
}
});
return mappedAuthorities;
};
}
@Bean @Bean
public IPRateLimitingFilter rateLimitingFilter() { public IPRateLimitingFilter rateLimitingFilter() {
int maxRequestsPerIp = 1000000; // Example limit TODO add config level int maxRequestsPerIp = 1000000; // Example limit TODO add config level

View File

@@ -20,6 +20,7 @@ import io.github.bucket4j.Bandwidth;
import io.github.bucket4j.Bucket; import io.github.bucket4j.Bucket;
import io.github.bucket4j.ConsumptionProbe; import io.github.bucket4j.ConsumptionProbe;
import io.github.bucket4j.Refill; import io.github.bucket4j.Refill;
import io.github.pixee.security.Newlines;
import jakarta.servlet.FilterChain; import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException; import jakarta.servlet.ServletException;
@@ -125,12 +126,16 @@ public class UserBasedRateLimitingFilter extends OncePerRequestFilter {
ConsumptionProbe probe = userBucket.tryConsumeAndReturnRemaining(1); ConsumptionProbe probe = userBucket.tryConsumeAndReturnRemaining(1);
if (probe.isConsumed()) { if (probe.isConsumed()) {
response.setHeader("X-Rate-Limit-Remaining", Long.toString(probe.getRemainingTokens())); response.setHeader(
"X-Rate-Limit-Remaining",
Newlines.stripAll(Long.toString(probe.getRemainingTokens())));
filterChain.doFilter(request, response); filterChain.doFilter(request, response);
} else { } else {
long waitForRefill = probe.getNanosToWaitForRefill() / 1_000_000_000; long waitForRefill = probe.getNanosToWaitForRefill() / 1_000_000_000;
response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value()); response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
response.setHeader("X-Rate-Limit-Retry-After-Seconds", String.valueOf(waitForRefill)); response.setHeader(
"X-Rate-Limit-Retry-After-Seconds",
Newlines.stripAll(String.valueOf(waitForRefill)));
response.getWriter().write("Rate limit exceeded for POST requests."); response.getWriter().write("Rate limit exceeded for POST requests.");
} }
} }

View File

@@ -8,6 +8,8 @@ import java.util.UUID;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.GrantedAuthority;
@@ -18,9 +20,11 @@ import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
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.Authority; import stirling.software.SPDF.model.Authority;
import stirling.software.SPDF.model.Role; import stirling.software.SPDF.model.Role;
import stirling.software.SPDF.model.User; import stirling.software.SPDF.model.User;
import stirling.software.SPDF.repository.AuthorityRepository;
import stirling.software.SPDF.repository.UserRepository; import stirling.software.SPDF.repository.UserRepository;
@Service @Service
@@ -28,8 +32,28 @@ public class UserService implements UserServiceInterface {
@Autowired private UserRepository userRepository; @Autowired private UserRepository userRepository;
@Autowired private AuthorityRepository authorityRepository;
@Autowired private PasswordEncoder passwordEncoder; @Autowired private PasswordEncoder passwordEncoder;
@Autowired private MessageSource messageSource;
// Handle OAUTH2 login and user auto creation.
public boolean processOAuth2PostLogin(String username, boolean autoCreateUser) {
if (!isUsernameValid(username)) {
return false;
}
Optional<User> existingUser = userRepository.findByUsernameIgnoreCase(username);
if (existingUser.isPresent()) {
return true;
}
if (autoCreateUser) {
saveUser(username, AuthenticationType.OAUTH2);
return true;
}
return false;
}
public Authentication getAuthentication(String apiKey) { public Authentication getAuthentication(String apiKey) {
User user = getUserByApiKey(apiKey); User user = getUserByApiKey(apiKey);
if (user == null) { if (user == null) {
@@ -90,9 +114,8 @@ public class UserService implements UserServiceInterface {
} }
public UserDetails loadUserByApiKey(String apiKey) { public UserDetails loadUserByApiKey(String apiKey) {
User userOptional = userRepository.findByApiKey(apiKey); User user = userRepository.findByApiKey(apiKey);
if (userOptional != null) { if (user != null) {
User user = userOptional;
// Convert your User entity to a UserDetails object with authorities // Convert your User entity to a UserDetails object with authorities
return new org.springframework.security.core.userdetails.User( return new org.springframework.security.core.userdetails.User(
user.getUsername(), user.getUsername(),
@@ -104,35 +127,53 @@ public class UserService implements UserServiceInterface {
public boolean validateApiKeyForUser(String username, String apiKey) { public boolean validateApiKeyForUser(String username, String apiKey) {
Optional<User> userOpt = userRepository.findByUsernameIgnoreCase(username); Optional<User> userOpt = userRepository.findByUsernameIgnoreCase(username);
return userOpt.isPresent() && userOpt.get().getApiKey().equals(apiKey); return userOpt.isPresent() && apiKey.equals(userOpt.get().getApiKey());
} }
public void saveUser(String username, String password) { public void saveUser(String username, AuthenticationType authenticationType)
throws IllegalArgumentException {
if (!isUsernameValid(username)) {
throw new IllegalArgumentException(getInvalidUsernameMessage());
}
User user = new User();
user.setUsername(username);
user.setEnabled(true);
user.setFirstLogin(false);
user.addAuthority(new Authority(Role.USER.getRoleId(), user));
user.setAuthenticationType(authenticationType);
userRepository.save(user);
}
public void saveUser(String username, String password) throws IllegalArgumentException {
if (!isUsernameValid(username)) {
throw new IllegalArgumentException(getInvalidUsernameMessage());
}
User user = new User(); User user = new User();
user.setUsername(username); user.setUsername(username);
user.setPassword(passwordEncoder.encode(password)); user.setPassword(passwordEncoder.encode(password));
user.setEnabled(true); user.setEnabled(true);
user.setAuthenticationType(AuthenticationType.WEB);
userRepository.save(user); userRepository.save(user);
} }
public void saveUser(String username, String password, String role, boolean firstLogin) { public void saveUser(String username, String password, String role, boolean firstLogin)
throws IllegalArgumentException {
if (!isUsernameValid(username)) {
throw new IllegalArgumentException(getInvalidUsernameMessage());
}
User user = new User(); User user = new User();
user.setUsername(username); user.setUsername(username);
user.setPassword(passwordEncoder.encode(password)); user.setPassword(passwordEncoder.encode(password));
user.addAuthority(new Authority(role, user)); user.addAuthority(new Authority(role, user));
user.setEnabled(true); user.setEnabled(true);
user.setAuthenticationType(AuthenticationType.WEB);
user.setFirstLogin(firstLogin); user.setFirstLogin(firstLogin);
userRepository.save(user); userRepository.save(user);
} }
public void saveUser(String username, String password, String role) { public void saveUser(String username, String password, String role)
User user = new User(); throws IllegalArgumentException {
user.setUsername(username); saveUser(username, password, role, false);
user.setPassword(passwordEncoder.encode(password));
user.addAuthority(new Authority(role, user));
user.setEnabled(true);
user.setFirstLogin(false);
userRepository.save(user);
} }
public void deleteUser(String username) { public void deleteUser(String username) {
@@ -156,7 +197,13 @@ public class UserService implements UserServiceInterface {
} }
public boolean hasUsers() { public boolean hasUsers() {
return userRepository.count() > 0; long userCount = userRepository.count();
if (userRepository
.findByUsernameIgnoreCase(Role.INTERNAL_API_USER.getRoleId())
.isPresent()) {
userCount -= 1;
}
return userCount > 0;
} }
public void updateUserSettings(String username, Map<String, String> updates) { public void updateUserSettings(String username, Map<String, String> updates) {
@@ -166,7 +213,7 @@ public class UserService implements UserServiceInterface {
Map<String, String> settingsMap = user.getSettings(); Map<String, String> settingsMap = user.getSettings();
if (settingsMap == null) { if (settingsMap == null) {
settingsMap = new HashMap<String, String>(); settingsMap = new HashMap<>();
} }
settingsMap.clear(); settingsMap.clear();
settingsMap.putAll(updates); settingsMap.putAll(updates);
@@ -184,7 +231,14 @@ public class UserService implements UserServiceInterface {
return userRepository.findByUsernameIgnoreCase(username); return userRepository.findByUsernameIgnoreCase(username);
} }
public void changeUsername(User user, String newUsername) { public Authority findRole(User user) {
return authorityRepository.findByUserId(user.getId());
}
public void changeUsername(User user, String newUsername) throws IllegalArgumentException {
if (!isUsernameValid(newUsername)) {
throw new IllegalArgumentException(getInvalidUsernameMessage());
}
user.setUsername(newUsername); user.setUsername(newUsername);
userRepository.save(user); userRepository.save(user);
} }
@@ -199,11 +253,41 @@ public class UserService implements UserServiceInterface {
userRepository.save(user); userRepository.save(user);
} }
public void changeRole(User user, String newRole) {
Authority userAuthority = this.findRole(user);
userAuthority.setAuthority(newRole);
authorityRepository.save(userAuthority);
}
public boolean isPasswordCorrect(User user, String currentPassword) { public boolean isPasswordCorrect(User user, String currentPassword) {
return passwordEncoder.matches(currentPassword, user.getPassword()); return passwordEncoder.matches(currentPassword, user.getPassword());
} }
public boolean isUsernameValid(String username) { public boolean isUsernameValid(String username) {
return username.matches("[a-zA-Z0-9]+"); // Checks whether the simple username is formatted correctly
boolean isValidSimpleUsername =
username.matches("^[a-zA-Z0-9][a-zA-Z0-9@._+-]*[a-zA-Z0-9]$");
// Checks whether the email address is formatted correctly
boolean isValidEmail =
username.matches(
"^(?=.{1,64}@)[A-Za-z0-9]+(\\.[A-Za-z0-9_+.-]+)*@[^-][A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(\\.[A-Za-z]{2,})$");
return isValidSimpleUsername || isValidEmail;
}
private String getInvalidUsernameMessage() {
return messageSource.getMessage(
"invalidUsernameMessage", null, LocaleContextHolder.getLocale());
}
public boolean hasPassword(String username) {
Optional<User> user = userRepository.findByUsernameIgnoreCase(username);
return user.isPresent() && user.get().hasPassword();
}
public boolean isAuthenticationTypeByUsername(
String username, AuthenticationType authenticationType) {
Optional<User> user = userRepository.findByUsernameIgnoreCase(username);
return user.isPresent()
&& authenticationType.name().equalsIgnoreCase(user.get().getAuthenticationType());
} }
} }

View File

@@ -0,0 +1,49 @@
package stirling.software.SPDF.config.security.oauth2;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
public class CustomOAuth2AuthenticationFailureHandler
extends SimpleUrlAuthenticationFailureHandler {
private static final Logger logger =
LoggerFactory.getLogger(CustomOAuth2AuthenticationFailureHandler.class);
@Override
public void onAuthenticationFailure(
HttpServletRequest request,
HttpServletResponse response,
AuthenticationException exception)
throws IOException, ServletException {
if (exception instanceof OAuth2AuthenticationException) {
OAuth2Error error = ((OAuth2AuthenticationException) exception).getError();
String errorCode = error.getErrorCode();
if (error.getErrorCode().equals("Password must not be null")) {
errorCode = "userAlreadyExistsWeb";
}
logger.error("OAuth2 Authentication error: " + errorCode);
getRedirectStrategy()
.sendRedirect(request, response, "/logout?erroroauth=" + errorCode);
return;
} else if (exception instanceof LockedException) {
logger.error("Account locked: ", exception);
getRedirectStrategy().sendRedirect(request, response, "/logout?error=locked");
} else {
logger.error("Unhandled authentication exception", exception);
super.onAuthenticationFailure(request, response, exception);
}
}
}

View File

@@ -0,0 +1,93 @@
package stirling.software.SPDF.config.security.oauth2;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.savedrequest.SavedRequest;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import stirling.software.SPDF.config.security.LoginAttemptService;
import stirling.software.SPDF.config.security.UserService;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
import stirling.software.SPDF.model.AuthenticationType;
import stirling.software.SPDF.utils.RequestUriUtils;
public class CustomOAuth2AuthenticationSuccessHandler
extends SavedRequestAwareAuthenticationSuccessHandler {
private LoginAttemptService loginAttemptService;
private static final Logger logger =
LoggerFactory.getLogger(CustomOAuth2AuthenticationSuccessHandler.class);
private ApplicationProperties applicationProperties;
private UserService userService;
public CustomOAuth2AuthenticationSuccessHandler(
final LoginAttemptService loginAttemptService,
ApplicationProperties applicationProperties,
UserService userService) {
this.applicationProperties = applicationProperties;
this.userService = userService;
this.loginAttemptService = loginAttemptService;
}
@Override
public void onAuthenticationSuccess(
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws ServletException, IOException {
// Get the saved request
HttpSession session = request.getSession(false);
SavedRequest savedRequest =
(session != null)
? (SavedRequest) session.getAttribute("SPRING_SECURITY_SAVED_REQUEST")
: null;
if (savedRequest != null
&& !RequestUriUtils.isStaticResource(savedRequest.getRedirectUrl())) {
// Redirect to the original destination
super.onAuthenticationSuccess(request, response, authentication);
} else {
OAuth2User oauthUser = (OAuth2User) authentication.getPrincipal();
OAUTH2 oAuth = applicationProperties.getSecurity().getOAUTH2();
String username = oauthUser.getName();
if (loginAttemptService.isBlocked(username)) {
if (session != null) {
session.removeAttribute("SPRING_SECURITY_SAVED_REQUEST");
}
throw new LockedException(
"Your account has been locked due to too many failed login attempts.");
}
if (userService.usernameExistsIgnoreCase(username)
&& userService.hasPassword(username)
&& !userService.isAuthenticationTypeByUsername(
username, AuthenticationType.OAUTH2)
&& oAuth.getAutoCreateUser()) {
response.sendRedirect(
request.getContextPath() + "/logout?oauth2AuthenticationErrorWeb=true");
return;
} else {
try {
userService.processOAuth2PostLogin(username, oAuth.getAutoCreateUser());
response.sendRedirect("/");
return;
} catch (IllegalArgumentException e) {
response.sendRedirect("/logout?invalidUsername=true");
return;
}
}
}
}
}

View File

@@ -0,0 +1,86 @@
package stirling.software.SPDF.config.security.oauth2;
import java.io.IOException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.session.SessionRegistry;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.ApplicationProperties.Security.OAUTH2;
public class CustomOAuth2LogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler {
private static final Logger logger =
LoggerFactory.getLogger(CustomOAuth2LogoutSuccessHandler.class);
private final SessionRegistry sessionRegistry;
private final ApplicationProperties applicationProperties;
public CustomOAuth2LogoutSuccessHandler(
ApplicationProperties applicationProperties, SessionRegistry sessionRegistry) {
this.sessionRegistry = sessionRegistry;
this.applicationProperties = applicationProperties;
}
@Override
public void onLogoutSuccess(
HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
String param = "logout=true";
OAUTH2 oauth = applicationProperties.getSecurity().getOAUTH2();
String provider = oauth.getProvider() != null ? oauth.getProvider() : "";
if (request.getParameter("oauth2AuthenticationErrorWeb") != null) {
param = "erroroauth=oauth2AuthenticationErrorWeb";
} else if (request.getParameter("error") != null) {
param = "error=" + request.getParameter("error");
} else if (request.getParameter("erroroauth") != null) {
param = "erroroauth=" + request.getParameter("erroroauth");
} else if (request.getParameter("oauth2AutoCreateDisabled") != null) {
param = "error=oauth2AutoCreateDisabled";
}
HttpSession session = request.getSession(false);
if (session != null) {
String sessionId = session.getId();
sessionRegistry.removeSessionInformation(sessionId);
session.invalidate();
logger.debug("Session invalidated: " + sessionId);
}
switch (provider) {
case "keycloak":
String logoutUrl =
oauth.getIssuer()
+ "/protocol/openid-connect/logout"
+ "?client_id="
+ oauth.getClientId()
+ "&post_logout_redirect_uri="
+ response.encodeRedirectURL(
request.getScheme()
+ "://"
+ request.getHeader("host")
+ "/login?"
+ param);
logger.debug("Redirecting to Keycloak logout URL: " + logoutUrl);
response.sendRedirect(logoutUrl);
break;
case "google":
// Add Google specific logout URL if needed
default:
String redirectUrl = request.getContextPath() + "/login?" + param;
logger.debug("Redirecting to default logout URL: " + redirectUrl);
response.sendRedirect(redirectUrl);
break;
}
}
}

View File

@@ -0,0 +1,73 @@
package stirling.software.SPDF.config.security.oauth2;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import stirling.software.SPDF.config.security.LoginAttemptService;
import stirling.software.SPDF.config.security.UserService;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.User;
public class CustomOAuth2UserService implements OAuth2UserService<OidcUserRequest, OidcUser> {
private final OidcUserService delegate = new OidcUserService();
private UserService userService;
private LoginAttemptService loginAttemptService;
private ApplicationProperties applicationProperties;
private static final Logger logger = LoggerFactory.getLogger(CustomOAuth2UserService.class);
public CustomOAuth2UserService(
ApplicationProperties applicationProperties,
UserService userService,
LoginAttemptService loginAttemptService) {
this.applicationProperties = applicationProperties;
this.userService = userService;
this.loginAttemptService = loginAttemptService;
}
@Override
public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
String usernameAttribute =
applicationProperties.getSecurity().getOAUTH2().getUseAsUsername();
try {
OidcUser user = delegate.loadUser(userRequest);
String username = user.getUserInfo().getClaimAsString(usernameAttribute);
Optional<User> duser = userService.findByUsernameIgnoreCase(username);
if (duser.isPresent()) {
if (loginAttemptService.isBlocked(username)) {
throw new LockedException(
"Your account has been locked due to too many failed login attempts.");
}
if (userService.hasPassword(username)) {
throw new IllegalArgumentException("Password must not be null");
}
}
// Return a new OidcUser with adjusted attributes
return new DefaultOidcUser(
user.getAuthorities(),
userRequest.getIdToken(),
user.getUserInfo(),
usernameAttribute);
} catch (java.lang.IllegalArgumentException e) {
logger.error("Error loading OIDC user: {}", e.getMessage());
throw new OAuth2AuthenticationException(new OAuth2Error(e.getMessage()), e);
} catch (Exception e) {
logger.error("Unexpected error loading OIDC user", e);
throw new OAuth2AuthenticationException("Unexpected error during authentication");
}
}
}

View File

@@ -0,0 +1,57 @@
package stirling.software.SPDF.config.security.oauth2;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import stirling.software.SPDF.model.ApplicationProperties;
public class CustomOAuthUserService implements OAuth2UserService<OidcUserRequest, OidcUser> {
private static final Logger logger = LoggerFactory.getLogger(CustomOAuthUserService.class);
private final OidcUserService delegate = new OidcUserService();
private ApplicationProperties applicationProperties;
public CustomOAuthUserService(ApplicationProperties applicationProperties) {
this.applicationProperties = applicationProperties;
}
@Override
public OidcUser loadUser(OidcUserRequest userRequest) throws OAuth2AuthenticationException {
String usernameAttribute =
applicationProperties.getSecurity().getOAUTH2().getUseAsUsername();
try {
OidcUser user = delegate.loadUser(userRequest);
Map<String, Object> attributes = new HashMap<>(user.getAttributes());
// Ensure the preferred username attribute is present
if (!attributes.containsKey(usernameAttribute)) {
attributes.put(usernameAttribute, attributes.getOrDefault("email", ""));
usernameAttribute = "email";
logger.info("Adjusted username attribute to use email");
}
// Return a new OidcUser with adjusted attributes
return new DefaultOidcUser(
user.getAuthorities(),
userRequest.getIdToken(),
user.getUserInfo(),
usernameAttribute);
} catch (java.lang.IllegalArgumentException e) {
throw new OAuth2AuthenticationException(
new OAuth2Error(e.getMessage()), e.getMessage(), e);
}
}
}

View File

@@ -47,8 +47,11 @@ public class UserController {
model.addAttribute("error", "Username already exists"); model.addAttribute("error", "Username already exists");
return "register"; return "register";
} }
try {
userService.saveUser(requestModel.getUsername(), requestModel.getPassword()); userService.saveUser(requestModel.getUsername(), requestModel.getPassword());
} catch (IllegalArgumentException e) {
return "redirect:/login?messageType=invalidUsername";
}
return "redirect:/login?registered=true"; return "redirect:/login?registered=true";
} }
@@ -92,7 +95,11 @@ public class UserController {
} }
if (newUsername != null && newUsername.length() > 0) { if (newUsername != null && newUsername.length() > 0) {
userService.changeUsername(user, newUsername); try {
userService.changeUsername(user, newUsername);
} catch (IllegalArgumentException e) {
return new RedirectView("/account?messageType=invalidUsername");
}
} }
// Logout using Spring's utility // Logout using Spring's utility
@@ -227,6 +234,45 @@ public class UserController {
return new RedirectView("/addUsers"); // Redirect to account page after adding the user return new RedirectView("/addUsers"); // Redirect to account page after adding the user
} }
@PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping("/admin/changeRole")
public RedirectView changeRole(
@RequestParam(name = "username") String username,
@RequestParam(name = "role") String role,
Authentication authentication) {
Optional<User> userOpt = userService.findByUsernameIgnoreCase(username);
if (!userOpt.isPresent()) {
return new RedirectView("/addUsers?messageType=userNotFound");
}
if (!userService.usernameExistsIgnoreCase(username)) {
return new RedirectView("/addUsers?messageType=userNotFound");
}
// Get the currently authenticated username
String currentUsername = authentication.getName();
// Check if the provided username matches the current session's username
if (currentUsername.equalsIgnoreCase(username)) {
return new RedirectView("/addUsers?messageType=downgradeCurrentUser");
}
try {
// Validate the role
Role roleEnum = Role.fromString(role);
if (roleEnum == Role.INTERNAL_API_USER) {
// If the role is INTERNAL_API_USER, reject the request
return new RedirectView("/addUsers?messageType=invalidRole");
}
} catch (IllegalArgumentException e) {
// If the role ID is not valid, redirect with an error message
return new RedirectView("/addUsers?messageType=invalidRole");
}
User user = userOpt.get();
userService.changeRole(user, role);
return new RedirectView("/addUsers"); // Redirect to account page after adding the user
}
@PreAuthorize("hasRole('ROLE_ADMIN')") @PreAuthorize("hasRole('ROLE_ADMIN')")
@PostMapping("/admin/deleteUser/{username}") @PostMapping("/admin/deleteUser/{username}")
public RedirectView deleteUser( public RedirectView deleteUser(

View File

@@ -6,10 +6,6 @@ import java.net.URLConnection;
import org.apache.pdfbox.rendering.ImageType; import org.apache.pdfbox.rendering.ImageType;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.ModelAttribute;
@@ -39,8 +35,8 @@ public class ConvertImgPDFController {
summary = "Convert PDF to image(s)", summary = "Convert PDF to image(s)",
description = description =
"This endpoint converts a PDF file to image(s) with the specified image format, color type, and DPI. Users can choose to get a single image or multiple images. Input:PDF Output:Image Type:SI-Conditional") "This endpoint converts a PDF file to image(s) with the specified image format, color type, and DPI. Users can choose to get a single image or multiple images. Input:PDF Output:Image Type:SI-Conditional")
public ResponseEntity<Resource> convertToImage(@ModelAttribute ConvertToImageRequest request) public ResponseEntity<byte[]> convertToImage(@ModelAttribute ConvertToImageRequest request)
throws IOException { throws NumberFormatException, Exception {
MultipartFile file = request.getFileInput(); MultipartFile file = request.getFileInput();
String imageFormat = request.getImageFormat(); String imageFormat = request.getImageFormat();
String singleOrMultiple = request.getSingleOrMultiple(); String singleOrMultiple = request.getSingleOrMultiple();
@@ -60,38 +56,28 @@ public class ConvertImgPDFController {
String filename = String filename =
Filenames.toSimpleFileName(file.getOriginalFilename()) Filenames.toSimpleFileName(file.getOriginalFilename())
.replaceFirst("[.][^.]+$", ""); .replaceFirst("[.][^.]+$", "");
try {
result = result =
PdfUtils.convertFromPdf( PdfUtils.convertFromPdf(
pdfBytes, pdfBytes,
imageFormat.toUpperCase(), imageFormat.toUpperCase(),
colorTypeResult, colorTypeResult,
singleImage, singleImage,
Integer.valueOf(dpi), Integer.valueOf(dpi),
filename); filename);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace(); if(result == null || result.length == 0) {
} catch (Exception e) { logger.error("resultant bytes for {} is null, error converting ", filename);
// TODO Auto-generated catch block
e.printStackTrace();
} }
if (singleImage) { if (singleImage) {
HttpHeaders headers = new HttpHeaders(); String docName = filename + "." + imageFormat;
headers.setContentType(MediaType.parseMediaType(getMediaType(imageFormat))); MediaType mediaType = MediaType.parseMediaType(getMediaType(imageFormat));
ResponseEntity<Resource> response = return WebResponseUtils.bytesToWebResponse(result, docName, mediaType);
new ResponseEntity<>(new ByteArrayResource(result), headers, HttpStatus.OK);
return response;
} else { } else {
ByteArrayResource resource = new ByteArrayResource(result); String zipFilename = filename + "_convertedToImages.zip";
// return the Resource in the response return WebResponseUtils.bytesToWebResponse(
return ResponseEntity.ok() result, zipFilename, MediaType.APPLICATION_OCTET_STREAM);
.header(
HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=" + filename + "_convertedToImages.zip")
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.contentLength(resource.contentLength())
.body(resource);
} }
} }

View File

@@ -1,10 +1,14 @@
package stirling.software.SPDF.controller.api.misc; package stirling.software.SPDF.controller.api.misc;
import java.awt.AlphaComposite; import java.awt.AlphaComposite;
import java.awt.BasicStroke;
import java.awt.Color; import java.awt.Color;
import java.awt.GradientPaint; import java.awt.GradientPaint;
import java.awt.Graphics2D; import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform; import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Path2D;
import java.awt.image.AffineTransformOp; import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage; import java.awt.image.BufferedImage;
import java.awt.image.BufferedImageOp; import java.awt.image.BufferedImageOp;
@@ -33,6 +37,7 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames; import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Hidden;
import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
@@ -47,12 +52,13 @@ public class FakeScanControllerWIP {
private static final Logger logger = LoggerFactory.getLogger(FakeScanControllerWIP.class); private static final Logger logger = LoggerFactory.getLogger(FakeScanControllerWIP.class);
//TODO // TODO finish
//@PostMapping(consumes = "multipart/form-data", value = "/fake-scan") @PostMapping(consumes = "multipart/form-data", value = "/fake-scan")
//@Operation( @Hidden
// summary = "Repair a PDF file", @Operation(
// description = summary = "Repair a PDF file",
// "This endpoint repairs a given PDF file by running Ghostscript command. The PDF is first saved to a temporary location, repaired, read back, and then returned as a response.") description =
"This endpoint repairs a given PDF file by running Ghostscript command. The PDF is first saved to a temporary location, repaired, read back, and then returned as a response.")
public ResponseEntity<byte[]> fakeScan(@ModelAttribute PDFFile request) throws IOException { public ResponseEntity<byte[]> fakeScan(@ModelAttribute PDFFile request) throws IOException {
MultipartFile inputFile = request.getFileInput(); MultipartFile inputFile = request.getFileInput();
@@ -91,18 +97,19 @@ public class FakeScanControllerWIP {
public BufferedImage processImage(BufferedImage image) { public BufferedImage processImage(BufferedImage image) {
// Rotation // Rotation
image = rotate(image); image = softenEdges(image, 50);
// image = softenEdges(image, 5); image = rotate(image, 1);
image = applyGaussianBlur(image, 0.5);
addGaussianNoise(image, 0.25);
image = linearStretch(image);
image = applyGaussianBlur(image, 0.5);
addGaussianNoise(image, 0.5);
image = linearStretch(image);
addDustAndHairs(image, 3);
return image; return image;
} }
private BufferedImage rotate(BufferedImage image) { private BufferedImage rotate(BufferedImage image, double rotation) {
double rotationRequired = Math.toRadians(1.0); double rotationRequired = Math.toRadians(rotation);
double locationX = image.getWidth() / 2; double locationX = image.getWidth() / 2;
double locationY = image.getHeight() / 2; double locationY = image.getHeight() / 2;
AffineTransform tx = AffineTransform tx =
@@ -144,39 +151,106 @@ public class FakeScanControllerWIP {
BufferedImage output = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); BufferedImage output = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
Graphics2D g2 = output.createGraphics(); Graphics2D g2 = output.createGraphics();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2.setRenderingHint(
RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
g2.drawImage(image, 0, 0, null); g2.drawImage(image, 0, 0, null);
g2.setComposite(AlphaComposite.DstIn); g2.setComposite(AlphaComposite.DstIn);
g2.setPaint(
new GradientPaint( // Top edge
0, 0, new Color(0, 0, 0, 1f), 0, featherRadius, new Color(0, 0, 0, 0f)));
g2.fillRect(0, 0, width, featherRadius); // top edge
g2.setPaint( g2.setPaint(
new GradientPaint( new GradientPaint(
0, 0,
height - featherRadius, 0,
new Color(0, 0, 0, 1f),
0,
featherRadius * 2,
new Color(0, 0, 0, 0f)));
g2.fillRect(0, 0, width, featherRadius);
// Bottom edge
g2.setPaint(
new GradientPaint(
0,
height - featherRadius * 2,
new Color(0, 0, 0, 0f), new Color(0, 0, 0, 0f),
0, 0,
height, height,
new Color(0, 0, 0, 1f))); new Color(0, 0, 0, 1f)));
g2.fillRect(0, height - featherRadius, width, featherRadius); // bottom edge g2.fillRect(0, height - featherRadius, width, featherRadius);
// Left edge
g2.setPaint( g2.setPaint(
new GradientPaint( new GradientPaint(
0, 0, new Color(0, 0, 0, 1f), featherRadius, 0, new Color(0, 0, 0, 0f))); 0,
g2.fillRect(0, 0, featherRadius, height); // left edge 0,
new Color(0, 0, 0, 1f),
featherRadius * 2,
0,
new Color(0, 0, 0, 0f)));
g2.fillRect(0, 0, featherRadius, height);
// Right edge
g2.setPaint( g2.setPaint(
new GradientPaint( new GradientPaint(
width - featherRadius, width - featherRadius * 2,
0, 0,
new Color(0, 0, 0, 0f), new Color(0, 0, 0, 0f),
width, width,
0, 0,
new Color(0, 0, 0, 1f))); new Color(0, 0, 0, 1f)));
g2.fillRect(width - featherRadius, 0, featherRadius, height); // right edge g2.fillRect(width - featherRadius, 0, featherRadius, height);
g2.dispose(); g2.dispose();
return output; return output;
} }
private void addDustAndHairs(BufferedImage image, float intensity) {
int width = image.getWidth();
int height = image.getHeight();
Graphics2D g2d = image.createGraphics();
Random random = new SecureRandom();
// Set rendering hints for better quality
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// Calculate the number of artifacts based on intensity
int numSpots = (int) (intensity * 10);
int numHairs = (int) (intensity * 20);
// Add spots with more variable sizes
g2d.setColor(new Color(100, 100, 100, 50)); // Semi-transparent gray
for (int i = 0; i < numSpots; i++) {
int x = random.nextInt(width);
int y = random.nextInt(height);
int ovalSize = 1 + random.nextInt(3); // Base size + variable component
if (random.nextFloat() > 0.9) {
// 10% chance to get a larger spot
ovalSize += random.nextInt(3);
}
g2d.fill(new Ellipse2D.Double(x, y, ovalSize, ovalSize));
}
// Add hairs
g2d.setStroke(new BasicStroke(0.5f)); // Thin stroke for hairs
g2d.setColor(new Color(80, 80, 80, 40)); // Slightly lighter and more transparent
for (int i = 0; i < numHairs; i++) {
int x1 = random.nextInt(width);
int y1 = random.nextInt(height);
int x2 = x1 + random.nextInt(20) - 10; // Random length and direction
int y2 = y1 + random.nextInt(20) - 10;
Path2D.Double hair = new Path2D.Double();
hair.moveTo(x1, y1);
hair.curveTo(x1, y1, (x1 + x2) / 2, (y1 + y2) / 2, x2, y2);
g2d.draw(hair);
}
g2d.dispose();
}
private void addGaussianNoise(BufferedImage image, double strength) { private void addGaussianNoise(BufferedImage image, double strength) {
Random rand = new SecureRandom(); Random rand = new SecureRandom();
int width = image.getWidth(); int width = image.getWidth();

View File

@@ -0,0 +1,84 @@
package stirling.software.SPDF.controller.api.misc;
import java.awt.image.BufferedImage;
import java.io.IOException;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.graphics.image.JPEGFactory;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.pdmodel.interactive.form.PDAcroForm;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import io.github.pixee.security.Filenames;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.PdfMetadata;
import stirling.software.SPDF.model.api.misc.FlattenRequest;
import stirling.software.SPDF.utils.PdfUtils;
import stirling.software.SPDF.utils.WebResponseUtils;
@RestController
@RequestMapping("/api/v1/misc")
@Tag(name = "Misc", description = "Miscellaneous APIs")
public class FlattenController {
@PostMapping(consumes = "multipart/form-data", value = "/flatten")
@Operation(
summary = "Flatten PDF form fields or full page",
description =
"Flattening just PDF form fields or converting each page to images to make text unselectable. Input: PDF, Output: PDF. Type: SISO")
public ResponseEntity<byte[]> flatten(@ModelAttribute FlattenRequest request) throws Exception {
MultipartFile file = request.getFileInput();
PDDocument document = Loader.loadPDF(file.getBytes());
PdfMetadata metadata = PdfUtils.extractMetadataFromPdf(document);
Boolean flattenOnlyForms = request.getFlattenOnlyForms();
if (Boolean.TRUE.equals(flattenOnlyForms)) {
PDAcroForm acroForm = document.getDocumentCatalog().getAcroForm();
if (acroForm != null) {
acroForm.flatten();
}
return WebResponseUtils.pdfDocToWebResponse(
document, Filenames.toSimpleFileName(file.getOriginalFilename()));
} else {
// flatten whole page aka convert each page to image and readd it (making text
// unselectable)
PDFRenderer pdfRenderer = new PDFRenderer(document);
PDDocument newDocument = new PDDocument();
int numPages = document.getNumberOfPages();
for (int i = 0; i < numPages; i++) {
try {
BufferedImage image = pdfRenderer.renderImageWithDPI(i, 300, ImageType.RGB);
PDPage page = new PDPage();
page.setMediaBox(document.getPage(i).getMediaBox());
newDocument.addPage(page);
try (PDPageContentStream contentStream =
new PDPageContentStream(newDocument, page)) {
PDImageXObject pdImage = JPEGFactory.createFromImage(newDocument, image);
float pageWidth = page.getMediaBox().getWidth();
float pageHeight = page.getMediaBox().getHeight();
contentStream.drawImage(pdImage, 0, 0, pageWidth, pageHeight);
}
} catch (IOException e) {
e.printStackTrace();
}
}
PdfUtils.setMetadataToPdf(newDocument, metadata);
return WebResponseUtils.pdfDocToWebResponse(
newDocument, Filenames.toSimpleFileName(file.getOriginalFilename()));
}
}
}

View File

@@ -20,12 +20,10 @@ import org.apache.pdfbox.printing.PDFPageable;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartFile;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import stirling.software.SPDF.model.api.misc.PrintFileRequest; import stirling.software.SPDF.model.api.misc.PrintFileRequest;
@@ -35,12 +33,13 @@ import stirling.software.SPDF.model.api.misc.PrintFileRequest;
@Tag(name = "Misc", description = "Miscellaneous APIs") @Tag(name = "Misc", description = "Miscellaneous APIs")
public class PrintFileController { public class PrintFileController {
//TODO // TODO
//@PostMapping(value = "/print-file", consumes = "multipart/form-data") // @PostMapping(value = "/print-file", consumes = "multipart/form-data")
//@Operation( // @Operation(
// summary = "Prints PDF/Image file to a set printer", // summary = "Prints PDF/Image file to a set printer",
// description = // description =
// "Input of PDF or Image along with a printer name/URL/IP to match against to send it to (Fire and forget) Input:Any Output:N/A Type:SISO") // "Input of PDF or Image along with a printer name/URL/IP to match against to
// send it to (Fire and forget) Input:Any Output:N/A Type:SISO")
public ResponseEntity<String> printFile(@ModelAttribute PrintFileRequest request) public ResponseEntity<String> printFile(@ModelAttribute PrintFileRequest request)
throws IOException { throws IOException {
MultipartFile file = request.getFileInput(); MultipartFile file = request.getFileInput();

View File

@@ -9,6 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.Model; import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
@@ -19,6 +20,7 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.oas.annotations.tags.Tag; import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import stirling.software.SPDF.model.ApplicationProperties;
import stirling.software.SPDF.model.Authority; import stirling.software.SPDF.model.Authority;
import stirling.software.SPDF.model.Role; import stirling.software.SPDF.model.Role;
import stirling.software.SPDF.model.User; import stirling.software.SPDF.model.User;
@@ -28,17 +30,65 @@ import stirling.software.SPDF.repository.UserRepository;
@Tag(name = "Account Security", description = "Account Security APIs") @Tag(name = "Account Security", description = "Account Security APIs")
public class AccountWebController { public class AccountWebController {
@Autowired ApplicationProperties applicationProperties;
@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:/";
} }
model.addAttribute(
"oAuth2Enabled", applicationProperties.getSecurity().getOAUTH2().getEnabled());
model.addAttribute("currentPage", "login"); model.addAttribute("currentPage", "login");
if (request.getParameter("error") != null) { String error = request.getParameter("error");
if (error != null) {
model.addAttribute("error", request.getParameter("error")); switch (error) {
case "badcredentials":
error = "login.invalid";
break;
case "locked":
error = "login.locked";
break;
case "oauth2AuthenticationError":
error = "userAlreadyExistsOAuthMessage";
break;
default:
break;
}
model.addAttribute("error", error);
}
String erroroauth = request.getParameter("erroroauth");
if (erroroauth != null) {
switch (erroroauth) {
case "oauth2AutoCreateDisabled":
erroroauth = "login.oauth2AutoCreateDisabled";
break;
case "invalidUsername":
erroroauth = "login.invalid";
break;
case "userAlreadyExistsWeb":
erroroauth = "userAlreadyExistsWebMessage";
break;
case "oauth2AuthenticationErrorWeb":
erroroauth = "login.oauth2InvalidUserType";
break;
case "invalid_token_response":
erroroauth = "login.oauth2InvalidTokenResponse";
default:
break;
}
model.addAttribute("erroroauth", erroroauth);
}
if (request.getParameter("messageType") != null) {
model.addAttribute("messageType", "changedCredsMessage");
} }
if (request.getParameter("logout") != null) { if (request.getParameter("logout") != null) {
@@ -53,7 +103,8 @@ public class AccountWebController {
@PreAuthorize("hasRole('ROLE_ADMIN')") @PreAuthorize("hasRole('ROLE_ADMIN')")
@GetMapping("/addUsers") @GetMapping("/addUsers")
public String showAddUserForm(Model model, Authentication authentication) { public String showAddUserForm(
HttpServletRequest request, Model model, Authentication authentication) {
List<User> allUsers = userRepository.findAll(); List<User> allUsers = userRepository.findAll();
Iterator<User> iterator = allUsers.iterator(); Iterator<User> iterator = allUsers.iterator();
Map<String, String> roleDetails = Role.getAllRoleDetails(); Map<String, String> roleDetails = Role.getAllRoleDetails();
@@ -71,6 +122,52 @@ public class AccountWebController {
} }
} }
String messageType = request.getParameter("messageType");
String deleteMessage = null;
if (messageType != null) {
switch (messageType) {
case "deleteCurrentUser":
deleteMessage = "deleteCurrentUserMessage";
break;
case "deleteUsernameExists":
deleteMessage = "deleteUsernameExistsMessage";
break;
default:
break;
}
model.addAttribute("deleteMessage", deleteMessage);
String addMessage = null;
switch (messageType) {
case "usernameExists":
addMessage = "usernameExistsMessage";
break;
case "invalidUsername":
addMessage = "invalidUsernameMessage";
break;
default:
break;
}
model.addAttribute("addMessage", addMessage);
}
String changeMessage = null;
if (messageType != null) {
switch (messageType) {
case "userNotFound":
changeMessage = "userNotFoundMessage";
break;
case "downgradeCurrentUser":
changeMessage = "downgradeCurrentUserMessage";
break;
default:
break;
}
model.addAttribute("changeMessage", changeMessage);
}
model.addAttribute("users", allUsers); model.addAttribute("users", allUsers);
model.addAttribute("currentUsername", authentication.getName()); model.addAttribute("currentUsername", authentication.getName());
model.addAttribute("roleDetails", roleDetails); model.addAttribute("roleDetails", roleDetails);
@@ -85,14 +182,30 @@ public class AccountWebController {
} }
if (authentication != null && authentication.isAuthenticated()) { if (authentication != null && authentication.isAuthenticated()) {
Object principal = authentication.getPrincipal(); Object principal = authentication.getPrincipal();
String username = null;
if (principal instanceof UserDetails) { if (principal instanceof UserDetails) {
// Cast the principal object to UserDetails // Cast the principal object to UserDetails
UserDetails userDetails = (UserDetails) principal; UserDetails userDetails = (UserDetails) principal;
// Retrieve username and other attributes // Retrieve username and other attributes
String username = userDetails.getUsername(); username = userDetails.getUsername();
// Add oAuth2 Login attributes to the model
model.addAttribute("oAuth2Login", false);
}
if (principal instanceof OAuth2User) {
// Cast the principal object to OAuth2User
OAuth2User userDetails = (OAuth2User) principal;
// Retrieve username and other attributes
username =
userDetails.getAttribute(
applicationProperties.getSecurity().getOAUTH2().getUseAsUsername());
// Add oAuth2 Login attributes to the model
model.addAttribute("oAuth2Login", true);
}
if (username != null) {
// Fetch user details from the database // Fetch user details from the database
Optional<User> user = Optional<User> user =
userRepository.findByUsernameIgnoreCase( userRepository.findByUsernameIgnoreCase(
@@ -113,6 +226,30 @@ public class AccountWebController {
return "redirect:/error"; // Example redirection in case of error return "redirect:/error"; // Example redirection in case of error
} }
String messageType = request.getParameter("messageType");
if (messageType != null) {
switch (messageType) {
case "notAuthenticated":
messageType = "notAuthenticatedMessage";
break;
case "userNotFound":
messageType = "userNotFoundMessage";
break;
case "incorrectPassword":
messageType = "incorrectPasswordMessage";
break;
case "usernameExists":
messageType = "usernameExistsMessage";
break;
case "invalidUsername":
messageType = "invalidUsernameMessage";
break;
default:
break;
}
model.addAttribute("messageType", messageType);
}
// Add attributes to the model // Add attributes to the model
model.addAttribute("username", username); model.addAttribute("username", username);
model.addAttribute("role", user.get().getRolesAsString()); model.addAttribute("role", user.get().getRolesAsString());
@@ -151,6 +288,28 @@ public class AccountWebController {
// Handle error appropriately // Handle error appropriately
return "redirect:/error"; // Example redirection in case of error return "redirect:/error"; // Example redirection in case of error
} }
String messageType = request.getParameter("messageType");
if (messageType != null) {
switch (messageType) {
case "notAuthenticated":
messageType = "notAuthenticatedMessage";
break;
case "userNotFound":
messageType = "userNotFoundMessage";
break;
case "incorrectPassword":
messageType = "incorrectPasswordMessage";
break;
case "usernameExists":
messageType = "usernameExistsMessage";
break;
default:
break;
}
model.addAttribute("messageType", messageType);
}
// Add attributes to the model // Add attributes to the model
model.addAttribute("username", username); model.addAttribute("username", username);
} }

View File

@@ -1,6 +1,10 @@
package stirling.software.SPDF.model; package stirling.software.SPDF.model;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@@ -118,6 +122,7 @@ public class ApplicationProperties {
private Boolean enableLogin; private Boolean enableLogin;
private Boolean csrfDisabled; private Boolean csrfDisabled;
private InitialLogin initialLogin; private InitialLogin initialLogin;
private OAUTH2 oauth2;
private int loginAttemptCount; private int loginAttemptCount;
private long loginResetTimeMinutes; private long loginResetTimeMinutes;
@@ -145,6 +150,14 @@ public class ApplicationProperties {
this.initialLogin = initialLogin; this.initialLogin = initialLogin;
} }
public OAUTH2 getOAUTH2() {
return oauth2 != null ? oauth2 : new OAUTH2();
}
public void setOAUTH2(OAUTH2 oauth2) {
this.oauth2 = oauth2;
}
public Boolean getEnableLogin() { public Boolean getEnableLogin() {
return enableLogin; return enableLogin;
} }
@@ -165,6 +178,8 @@ public class ApplicationProperties {
public String toString() { public String toString() {
return "Security [enableLogin=" return "Security [enableLogin="
+ enableLogin + enableLogin
+ ", oauth2="
+ oauth2
+ ", initialLogin=" + ", initialLogin="
+ initialLogin + initialLogin
+ ", csrfDisabled=" + ", csrfDisabled="
@@ -202,16 +217,127 @@ public class ApplicationProperties {
+ "]"; + "]";
} }
} }
public static class OAUTH2 {
private boolean enabled;
private String issuer;
private String clientId;
private String clientSecret;
private boolean autoCreateUser;
private String useAsUsername;
private String provider;
private Collection<String> scopes = new ArrayList<String>();
public boolean getEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getIssuer() {
return issuer;
}
public void setIssuer(String issuer) {
this.issuer = issuer;
}
public String getClientId() {
return clientId;
}
public void setClientId(String clientId) {
this.clientId = clientId;
}
public String getClientSecret() {
return clientSecret;
}
public void setClientSecret(String clientSecret) {
this.clientSecret = clientSecret;
}
public boolean getAutoCreateUser() {
return autoCreateUser;
}
public void setAutoCreateUser(boolean autoCreateUser) {
this.autoCreateUser = autoCreateUser;
}
public String getUseAsUsername() {
if (useAsUsername != null && useAsUsername.trim().length() > 0) {
return useAsUsername;
}
return "email";
}
public void setUseAsUsername(String useAsUsername) {
this.useAsUsername = useAsUsername;
}
public String getProvider() {
return provider;
}
public void setProvider(String provider) {
this.provider = provider;
}
public Collection<String> getScopes() {
return scopes;
}
public void setScopes(String scpoes) {
List<String> scopesList =
Arrays.stream(scpoes.split(","))
.map(String::trim)
.collect(Collectors.toList());
this.scopes.addAll(scopesList);
}
@Override
public String toString() {
return "OAUTH2 [enabled="
+ enabled
+ ", issuer="
+ issuer
+ ", clientId="
+ clientId
+ ", clientSecret="
+ (clientSecret != null && !clientSecret.isEmpty() ? "MASKED" : "NULL")
+ ", autoCreateUser="
+ autoCreateUser
+ ", useAsUsername="
+ useAsUsername
+ ", provider"
+ provider
+ ", scopes="
+ scopes
+ "]";
}
}
} }
public static class System { public static class System {
private String defaultLocale; private String defaultLocale;
private Boolean googlevisibility; private Boolean googlevisibility;
private String rootURIPath;
private String customStaticFilePath;
private Integer maxFileSize;
private boolean showUpdate; private boolean showUpdate;
private Boolean showUpdateOnlyAdmin; private Boolean showUpdateOnlyAdmin;
private boolean customHTMLFiles;
public boolean isCustomHTMLFiles() {
return customHTMLFiles;
}
public void setCustomHTMLFiles(boolean customHTMLFiles) {
this.customHTMLFiles = customHTMLFiles;
}
public boolean getShowUpdateOnlyAdmin() { public boolean getShowUpdateOnlyAdmin() {
return showUpdateOnlyAdmin; return showUpdateOnlyAdmin;
@@ -255,29 +381,8 @@ public class ApplicationProperties {
this.googlevisibility = googlevisibility; this.googlevisibility = googlevisibility;
} }
public String getRootURIPath() {
return rootURIPath;
}
public void setRootURIPath(String rootURIPath) {
this.rootURIPath = rootURIPath;
}
public String getCustomStaticFilePath() {
return customStaticFilePath;
}
public void setCustomStaticFilePath(String customStaticFilePath) {
this.customStaticFilePath = customStaticFilePath;
}
public Integer getMaxFileSize() {
return maxFileSize;
}
public void setMaxFileSize(Integer maxFileSize) {
this.maxFileSize = maxFileSize;
}
@Override @Override
public String toString() { public String toString() {
@@ -285,12 +390,6 @@ public class ApplicationProperties {
+ defaultLocale + defaultLocale
+ ", googlevisibility=" + ", googlevisibility="
+ googlevisibility + googlevisibility
+ ", rootURIPath="
+ rootURIPath
+ ", customStaticFilePath="
+ customStaticFilePath
+ ", maxFileSize="
+ maxFileSize
+ ", enableAlphaFunctionality=" + ", enableAlphaFunctionality="
+ enableAlphaFunctionality + enableAlphaFunctionality
+ ", showUpdate=" + ", showUpdate="

View File

@@ -5,7 +5,7 @@ public class AttemptCounter {
private long lastAttemptTime; private long lastAttemptTime;
public AttemptCounter() { public AttemptCounter() {
this.attemptCount = 1; this.attemptCount = 0;
this.lastAttemptTime = System.currentTimeMillis(); this.lastAttemptTime = System.currentTimeMillis();
} }
@@ -18,11 +18,16 @@ public class AttemptCounter {
return attemptCount; return attemptCount;
} }
public long getlastAttemptTime() { public long getLastAttemptTime() {
return lastAttemptTime; return lastAttemptTime;
} }
public boolean shouldReset(long ATTEMPT_INCREMENT_TIME) { public boolean shouldReset(long attemptIncrementTime) {
return System.currentTimeMillis() - lastAttemptTime > ATTEMPT_INCREMENT_TIME; return System.currentTimeMillis() - lastAttemptTime > attemptIncrementTime;
}
public void reset() {
this.attemptCount = 0;
this.lastAttemptTime = System.currentTimeMillis();
} }
} }

View File

@@ -0,0 +1,6 @@
package stirling.software.SPDF.model;
public enum AuthenticationType {
WEB,
OAUTH2
}

View File

@@ -47,6 +47,9 @@ public class User {
@Column(name = "roleName") @Column(name = "roleName")
private String roleName; private String roleName;
@Column(name = "authenticationtype")
private String authenticationType;
@OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "user") @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "user")
private Set<Authority> authorities = new HashSet<>(); private Set<Authority> authorities = new HashSet<>();
@@ -116,6 +119,14 @@ public class User {
this.enabled = enabled; this.enabled = enabled;
} }
public void setAuthenticationType(AuthenticationType authenticationType) {
this.authenticationType = authenticationType.toString().toLowerCase();
}
public String getAuthenticationType() {
return authenticationType;
}
public Set<Authority> getAuthorities() { public Set<Authority> getAuthorities() {
return authorities; return authorities;
} }
@@ -137,4 +148,8 @@ public class User {
.map(Authority::getAuthority) .map(Authority::getAuthority)
.collect(Collectors.joining(", ")); .collect(Collectors.joining(", "));
} }
public boolean hasPassword() {
return this.password != null && !this.password.isEmpty();
}
} }

View File

@@ -0,0 +1,17 @@
package stirling.software.SPDF.model.api.misc;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import stirling.software.SPDF.model.api.PDFFile;
@Data
@EqualsAndHashCode(callSuper = true)
public class FlattenRequest extends PDFFile {
@Schema(
description =
"True to flatten only the forms, false to flatten full PDF (Convert page to image)")
private Boolean flattenOnlyForms;
}

View File

@@ -9,4 +9,6 @@ import stirling.software.SPDF.model.Authority;
public interface AuthorityRepository extends JpaRepository<Authority, Long> { public interface AuthorityRepository extends JpaRepository<Authority, Long> {
// Set<Authority> findByUsername(String username); // Set<Authority> findByUsername(String username);
Set<Authority> findByUser_Username(String username); Set<Authority> findByUser_Username(String username);
Authority findByUserId(long user_id);
} }

View File

@@ -342,8 +342,6 @@ public class PdfUtils {
boolean imageIsLandscape = image.getWidth() > image.getHeight(); boolean imageIsLandscape = image.getWidth() > image.getHeight();
PDRectangle pageSize = PDRectangle.A4; PDRectangle pageSize = PDRectangle.A4;
System.out.println(fitOption);
if (autoRotate && imageIsLandscape) { if (autoRotate && imageIsLandscape) {
pageSize = new PDRectangle(pageSize.getHeight(), pageSize.getWidth()); pageSize = new PDRectangle(pageSize.getHeight(), pageSize.getWidth());
} }

View File

@@ -58,10 +58,10 @@ public class ProcessExecutor {
long timeoutMinutes = long timeoutMinutes =
switch (key) { switch (key) {
case LIBRE_OFFICE -> 30; case LIBRE_OFFICE -> 30;
case PDFTOHTML -> 5; case PDFTOHTML -> 20;
case OCR_MY_PDF -> 30; case OCR_MY_PDF -> 30;
case PYTHON_OPENCV -> 30; case PYTHON_OPENCV -> 30;
case GHOSTSCRIPT -> 5; case GHOSTSCRIPT -> 30;
case WEASYPRINT -> 30; case WEASYPRINT -> 30;
case INSTALL_APP -> 60; case INSTALL_APP -> 60;
case CALIBRE -> 30; case CALIBRE -> 30;

View File

@@ -24,8 +24,8 @@ spring.devtools.livereload.enabled=true
spring.thymeleaf.encoding=UTF-8 spring.thymeleaf.encoding=UTF-8
server.connection-timeout=${SYSTEM_CONNECTIONTIMEOUTMINUTES:5m} server.connection-timeout=${SYSTEM_CONNECTIONTIMEOUTMINUTES:20m}
spring.mvc.async.request-timeout=${SYSTEM_CONNECTIONTIMEOUTMILLISECONDS:300000} spring.mvc.async.request-timeout=${SYSTEM_CONNECTIONTIMEOUTMILLISECONDS:1200000}
spring.resources.static-locations=file:customFiles/static/ spring.resources.static-locations=file:customFiles/static/
#spring.thymeleaf.prefix=file:/customFiles/templates/,classpath:/templates/ #spring.thymeleaf.prefix=file:/customFiles/templates/,classpath:/templates/

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found. userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect. incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists. usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers. invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=لا يمكن خفض دور المستخدم الحالي
downgradeCurrentUserLongMessage=لا يمكن تخفيض دور المستخدم الحالي. وبالتالي، لن يظهر المستخدم الحالي.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=Error error=Error
oops=Oops! oops=Oops!
help=Help help=Help
@@ -67,6 +71,7 @@ visitGithub=Visit Github Repository
donate=Donate donate=Donate
color=Color color=Color
sponsor=Sponsor sponsor=Sponsor
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=Validate
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=تحويل navbar.favorite=Favorites
navbar.security=الأمان
navbar.other=أخرى
navbar.darkmode=الوضع الداكن navbar.darkmode=الوضع الداكن
navbar.pageOps=عمليات الصفحة navbar.language=Languages
navbar.settings=إعدادات navbar.settings=إعدادات
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=User adminUserSettings.user=User
adminUserSettings.addUser=Add New User adminUserSettings.addUser=Add New User
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters. adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles adminUserSettings.roles=Roles
adminUserSettings.role=Role adminUserSettings.role=Role
adminUserSettings.actions=Actions adminUserSettings.actions=Actions
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Demo User (No custom settings)
adminUserSettings.internalApiUser=Internal API User adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Force user to change password on login adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=تغيير دور المستخدم
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=Remember me
login.invalid=Invalid username or password. login.invalid=Invalid username or password.
login.locked=Your account has been locked. login.locked=Your account has been locked.
login.signinTitle=Please sign in login.signinTitle=Please sign in
login.ssoSignIn=تسجيل الدخول عبر تسجيل الدخول الأحادي
login.oauth2AutoCreateDisabled=تم تعطيل مستخدم الإنشاء التلقائي لـ OAuth2
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=الإصلاح
#flatten #flatten
flatten.title=تسطيح flatten.title=تسطيح
flatten.header=تسوية ملفات PDF flatten.header=تسوية ملفات PDF
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=تسطيح flatten.submit=تسطيح
@@ -736,6 +752,7 @@ extractImages.submit=استخراج
fileToPDF.title=ملف إلى PDF fileToPDF.title=ملف إلى PDF
fileToPDF.header=تحويل أي ملف إلى PDF fileToPDF.header=تحويل أي ملف إلى PDF
fileToPDF.credit=تستخدم هذه الخدمة ليبر أوفيس وأونوكونف لتحويل الملفات. fileToPDF.credit=تستخدم هذه الخدمة ليبر أوفيس وأونوكونف لتحويل الملفات.
fileToPDF.supportedFileTypesInfo=Supported File types
fileToPDF.supportedFileTypes=يجب أن تتضمن أنواع الملفات المدعومة ما يلي ولكن للحصول على قائمة محدثة كاملة بالتنسيقات المدعومة ، يرجى الرجوع إلى وثائق LibreOffice fileToPDF.supportedFileTypes=يجب أن تتضمن أنواع الملفات المدعومة ما يلي ولكن للحصول على قائمة محدثة كاملة بالتنسيقات المدعومة ، يرجى الرجوع إلى وثائق LibreOffice
fileToPDF.submit=تحويل إلى PDF fileToPDF.submit=تحويل إلى PDF
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool #multiTool
multiTool.title=أداة متعددة PDF multiTool.title=أداة متعددة PDF
multiTool.header=أداة متعددة PDF multiTool.header=أداة متعددة PDF
multiTool.uploadPrompts=Please Upload PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=View PDF viewPdf.title=View PDF
@@ -941,6 +958,7 @@ pdfToPDFA.header=PDF إلى PDF / A
pdfToPDFA.credit=تستخدم هذه الخدمة OCRmyPDF لتحويل PDF / A. pdfToPDFA.credit=تستخدم هذه الخدمة OCRmyPDF لتحويل PDF / A.
pdfToPDFA.submit=تحويل pdfToPDFA.submit=تحويل
pdfToPDFA.tip=Currently does not work for multiple inputs at once pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Version
licenses.license=License licenses.license=License
# error #error
error.sorry=Sorry for the issue! error.sorry=Sorry for the issue!
error.needHelp=Need help / Found an issue? error.needHelp=Need help / Found an issue?
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=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:

View File

@@ -11,17 +11,17 @@ imgPrompt=Изберете изображение(я)
genericSubmit=Подайте genericSubmit=Подайте
processTimeWarning=Предупреждение: Този процес може да отнеме до минута в зависимост от размера на файла processTimeWarning=Предупреждение: Този процес може да отнеме до минута в зависимост от размера на файла
pageOrderPrompt=Персонализиран ред на страниците (Въведете разделен със запетаи списък с номера на страници или функции като 2n+1): pageOrderPrompt=Персонализиран ред на страниците (Въведете разделен със запетаи списък с номера на страници или функции като 2n+1):
pageSelectionPrompt=Custom Page Selection (Enter a comma-separated list of page numbers 1,5,6 or Functions like 2n+1) : pageSelectionPrompt=Персонализиран избор на страница (Въведете списък с номера на страници 1,5,6, разделени със запетая, или функции като 2n+1) :
goToPage=Давай goToPage=Давай
true=Вярно true=Вярно
false=Невярно false=Невярно
unknown=Непознат unknown=Непознат
save=Съхранете save=Съхранете
saveToBrowser=Save to Browser saveToBrowser=Съхраняване в браузъра
close=Затворете close=Затворете
filesSelected=избрани файлове filesSelected=избрани файлове
noFavourites=Няма добавени любими noFavourites=Няма добавени любими
downloadComplete=Download Complete downloadComplete=Свалянето завършено
bored=Отекчени сте да чакате? bored=Отекчени сте да чакате?
alphabet=Азбука alphabet=Азбука
downloadPdf=Изтеглете PDF downloadPdf=Изтеглете PDF
@@ -45,54 +45,59 @@ red=Червено
green=Зелено green=Зелено
blue=Синьо blue=Синьо
custom=Персонализиране... custom=Персонализиране...
WorkInProgess=Work in progress, May not work or be buggy, Please report any problems! WorkInProgess=Работата е в ход, може да не работи или да има грешки, моля, докладвайте за проблеми!
poweredBy=Powered by poweredBy=Задвижван чрез
yes=Yes yes=Да
no=No no=Не
changedCredsMessage=Идентификационните данни са променени! changedCredsMessage=Идентификационните данни са променени!
notAuthenticatedMessage=Потребителят не е автентикиран. notAuthenticatedMessage=Потребителят не е автентикиран.
userNotFoundMessage=Потребителят не е намерен userNotFoundMessage=Потребителят не е намерен
incorrectPasswordMessage=Текущата парола е неправилна. incorrectPasswordMessage=Текущата парола е неправилна.
usernameExistsMessage=Новият потребител вече съществува. usernameExistsMessage=Новият потребител вече съществува.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers. invalidUsernameMessage=Невалидно потребителско име, потребителското име може да съдържа само букви, цифри и следните специални знаци @._+- или трябва да е валиден имейл адрес.
deleteCurrentUserMessage=Cannot delete currently logged in user. deleteCurrentUserMessage=Не може да се изтрие вписания в момента потребител.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=Потребителското име не съществува и не може да бъде изтрито.
error=Error downgradeCurrentUserMessage=Не може да се понижи ролята на текущия потребител
oops=Oops! downgradeCurrentUserLongMessage=Не може да се понижи ролята на текущия потребител. Следователно текущият потребител няма да бъде показан.
help=Help userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
goHomepage=Go to Homepage userAlreadyExistsWebMessage=The user already exists as an web user.
joinDiscord=Join our Discord server error=Грешка
seeDockerHub=See Docker Hub oops=Опаа!
visitGithub=Visit Github Repository help=Помощ
donate=Donate goHomepage=Отидете на началната страница
color=Color joinDiscord=Присъединете се към нашия Discord сървър
sponsor=Sponsor seeDockerHub=Погледнете Docker Hub
visitGithub=Посетете Github Repository
donate=Направете дарение
color=Цвят
sponsor=Спонсор
info=Info
############### ###############
# Pipeline # # Pipeline #
############### ###############
pipeline.header=Pipeline Menu (Beta) pipeline.header=Pipeline Меню (Бета)
pipeline.uploadButton=Upload Custom pipeline.uploadButton=Качване на персонализиран
pipeline.configureButton=Configure pipeline.configureButton=Настройка
pipeline.defaultOption=Custom pipeline.defaultOption=Персонализиран
pipeline.submitButton=Submit pipeline.submitButton=Подайте
pipeline.help=Pipeline Help pipeline.help=Pipeline Помощ
pipeline.scanHelp=Folder Scanning Help pipeline.scanHelp=Помощ за сканиране на папки
###################### ######################
# Pipeline Options # # Pipeline Options #
###################### ######################
pipelineOptions.header=Pipeline Configuration pipelineOptions.header=Pipeline Конфигурация
pipelineOptions.pipelineNameLabel=Pipeline Name pipelineOptions.pipelineNameLabel=Pipeline име
pipelineOptions.saveSettings=Save Operation Settings pipelineOptions.saveSettings=Запазете настройките за работа
pipelineOptions.pipelineNamePrompt=Enter pipeline name here pipelineOptions.pipelineNamePrompt=Въведете името на pipeline тук
pipelineOptions.selectOperation=Select Operation pipelineOptions.selectOperation=Избор на операция
pipelineOptions.addOperationButton=Add operation pipelineOptions.addOperationButton=Добавяне на операция
pipelineOptions.pipelineHeader=Pipeline: pipelineOptions.pipelineHeader=Pipeline:
pipelineOptions.saveButton=Download pipelineOptions.saveButton=Изтегли
pipelineOptions.validateButton=Validate pipelineOptions.validateButton=Валидирай
@@ -100,19 +105,25 @@ pipelineOptions.validateButton=Validate
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=Преобразуване navbar.favorite=Favorites
navbar.security=Сигурност
navbar.other=Разни
navbar.darkmode=Тъмна тема navbar.darkmode=Тъмна тема
navbar.pageOps=Операции със страници navbar.language=Languages
navbar.settings=Настройки navbar.settings=Настройки
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
############# #############
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=Отваряне в същия прозорец
@@ -121,13 +132,13 @@ 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=Актуализирайте данните за акаунта си
changeCreds.changePassword=You are using default login credentials. Please enter a new password changeCreds.changePassword=Използвате идентификационни данни за вход по подразбиране. Моля, въведете нова парола
changeCreds.newUsername=Ново потребителско име changeCreds.newUsername=Ново потребителско име
changeCreds.oldPassword=Текуща парола changeCreds.oldPassword=Текуща парола
changeCreds.newPassword=Нова парола changeCreds.newPassword=Нова парола
@@ -153,8 +164,8 @@ account.syncTitle=Синхронизиране на настройките на
account.settingsCompare=Сравняване на настройките: account.settingsCompare=Сравняване на настройките:
account.property=Свойство account.property=Свойство
account.webBrowserSettings=Уеб-браузър настройки account.webBrowserSettings=Уеб-браузър настройки
account.syncToBrowser=Синхронизиране на акаунт -> Бразър account.syncToBrowser=Синхронизиране на акаунт -> Браузър
account.syncToAccount=Синхронизиране на акаунт <- Бразър account.syncToAccount=Синхронизиране на акаунт <- Браузър
adminUserSettings.title=Настройки за потребителски контрол adminUserSettings.title=Настройки за потребителски контрол
@@ -162,28 +173,30 @@ adminUserSettings.header=Настройки за администраторск
adminUserSettings.admin=Администратор adminUserSettings.admin=Администратор
adminUserSettings.user=Потребител adminUserSettings.user=Потребител
adminUserSettings.addUser=Добавяне на нов потребител adminUserSettings.addUser=Добавяне на нов потребител
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters. adminUserSettings.usernameInfo=Потребителското име може да съдържа само букви, цифри и следните специални символи @._+- или трябва да е валиден имейл адрес.
adminUserSettings.roles=Роли adminUserSettings.roles=Роли
adminUserSettings.role=Роля adminUserSettings.role=Роля
adminUserSettings.actions=Действия adminUserSettings.actions=Действия
adminUserSettings.apiUser=Ограничен API потребител adminUserSettings.apiUser=Ограничен API потребител
adminUserSettings.extraApiUser=Additional Limited API User adminUserSettings.extraApiUser=Допълнителен ограничен API потребител
adminUserSettings.webOnlyUser=Само за уеб-потребител adminUserSettings.webOnlyUser=Само за уеб-потребител
adminUserSettings.demoUser=Demo User (No custom settings) adminUserSettings.demoUser=Демо потребител (без персонализирани настройки)
adminUserSettings.internalApiUser=Internal API User adminUserSettings.internalApiUser=Вътрешен API потребител
adminUserSettings.forceChange=Принудете потребителя да промени потребителското име/парола при влизане adminUserSettings.forceChange=Принудете потребителя да промени потребителското име/парола при влизане
adminUserSettings.submit=Съхранете потребителя adminUserSettings.submit=Съхранете потребителя
adminUserSettings.changeUserRole=Промяна на ролята на потребителя
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
############# #############
home.desc=Вашето локално хоствано обслужване на едно място за всички ваши PDF нужди. home.desc=Вашето локално хоствано обслужване на едно място за всички ваши PDF нужди.
home.searchBar=Search for features... home.searchBar=Търсене на функции...
home.viewPdf.title=View PDF home.viewPdf.title=Преглед на PDF
home.viewPdf.desc=View, annotate, add text or images home.viewPdf.desc=Преглеждайте, коментирайте, добавяйте текст или изображения
viewPdf.tags=view,read,annotate,text,image viewPdf.tags=преглед,четене,анотиране,текст,изображение
home.multiTool.title=PDF Мулти инструмент home.multiTool.title=PDF Мулти инструмент
home.multiTool.desc=Обединяване, завъртане, пренареждане и премахване на страници home.multiTool.desc=Обединяване, завъртане, пренареждане и премахване на страници
@@ -254,7 +267,7 @@ home.fileToPDF.desc=Преобразуване почти всеки файл к
fileToPDF.tags=трансформация,формат,документ,изображение,слайд,текст,преобразуване,офис,документи,word,excel,powerpoint fileToPDF.tags=трансформация,формат,документ,изображение,слайд,текст,преобразуване,офис,документи,word,excel,powerpoint
home.ocr.title=OCR / Почистващи сканирания home.ocr.title=OCR / Почистващи сканирания
home.ocr.desc=Cleanup сканира и открива текст от изображения към PDF и го добавя отново като текст. home.ocr.desc=Почистване, сканира и открива текст от изображения към PDF и го добавя отново като текст.
ocr.tags=разпознаване,текст,изображение,сканиране,четене,идентифициране,откриване,редактиране ocr.tags=разпознаване,текст,изображение,сканиране,четене,идентифициране,откриване,редактиране
@@ -307,9 +320,9 @@ home.removeBlanks.title=Премахване на празни страници
home.removeBlanks.desc=Открива и премахва празни страници от документ home.removeBlanks.desc=Открива и премахва празни страници от документ
removeBlanks.tags=почистване,рационализиране,без съдържание,организиране removeBlanks.tags=почистване,рационализиране,без съдържание,организиране
home.removeAnnotations.title=Remove Annotations home.removeAnnotations.title=Премахване на анотации
home.removeAnnotations.desc=Removes all comments/annotations from a PDF home.removeAnnotations.desc=Премахва всички коментари/анотации от PDF
removeAnnotations.tags=comments,highlight,notes,markup,remove removeAnnotations.tags=коментари, маркиране, бележки, маркиране, премахване
home.compare.title=Сравнете home.compare.title=Сравнете
home.compare.desc=Сравнява и показва разликите между 2 PDF документа home.compare.desc=Сравнява и показва разликите между 2 PDF документа
@@ -351,7 +364,7 @@ home.autoSplitPDF.title=Автоматично разделяне на стра
home.autoSplitPDF.desc=Автоматично разделяне на сканиран PDF файл с QR код за разделяне на физически сканирани страници home.autoSplitPDF.desc=Автоматично разделяне на сканиран PDF файл с QR код за разделяне на физически сканирани страници
autoSplitPDF.tags=QR-базиран,отделен,сканиране-сегмент,организиране autoSplitPDF.tags=QR-базиран,отделен,сканиране-сегмент,организиране
home.sanitizePdf.title=Дезинфекцирай home.sanitizePdf.title=Дезинфенкцирам
home.sanitizePdf.desc=Премахване на скриптове и други елементи от PDF файлове home.sanitizePdf.desc=Премахване на скриптове и други елементи от PDF файлове
sanitizePdf.tags=чисти,сигурни,безопасни,премахване-заплахи sanitizePdf.tags=чисти,сигурни,безопасни,премахване-заплахи
@@ -393,35 +406,35 @@ home.autoRedact.desc=Автоматично редактира (зачерняв
autoRedact.tags=Редактиране,Скриване,затъмняване,черен,маркер,скрит autoRedact.tags=Редактиране,Скриване,затъмняване,черен,маркер,скрит
home.tableExtraxt.title=PDF to CSV home.tableExtraxt.title=PDF to CSV
home.tableExtraxt.desc=Extracts Tables from a PDF converting it to CSV home.tableExtraxt.desc=Извлича таблици от PDF, като ги конвертира в CSV
tableExtraxt.tags=CSV,Table Extraction,extract,convert tableExtraxt.tags=CSV,извличане на таблица,извличане,конвертиране
home.autoSizeSplitPDF.title=Auto Split by Size/Count home.autoSizeSplitPDF.title=Автоматично разделяне по размер/брой
home.autoSizeSplitPDF.desc=Split a single PDF into multiple documents based on size, page count, or document count home.autoSizeSplitPDF.desc=Разделете един PDF на множество документи въз основа на размер, брой страници или брой документи
autoSizeSplitPDF.tags=pdf,split,document,organization autoSizeSplitPDF.tags=pdf,разделяне,документ,организация
home.overlay-pdfs.title=Overlay PDFs home.overlay-pdfs.title=Наслагване PDF
home.overlay-pdfs.desc=Overlays PDFs on-top of another PDF home.overlay-pdfs.desc=Наслагва PDF файлове върху друг PDF
overlay-pdfs.tags=Overlay overlay-pdfs.tags=Наслагване
home.split-by-sections.title=Split PDF by Sections home.split-by-sections.title=Разделяне на PDF по секции
home.split-by-sections.desc=Divide each page of a PDF into smaller horizontal and vertical sections home.split-by-sections.desc=Разделете всяка страница от PDF на по-малки хоризонтални и вертикални секции
split-by-sections.tags=Section Split, Divide, Customize split-by-sections.tags=Разделяне на секция,Разделяне,Персонализиране
home.AddStampRequest.title=Add Stamp to PDF home.AddStampRequest.title=Добавяне на печат към PDF
home.AddStampRequest.desc=Add text or add image stamps at set locations home.AddStampRequest.desc=Добавете текст или добавете печати с изображения на определени места
AddStampRequest.tags=Stamp, Add image, center image, Watermark, PDF, Embed, Customize AddStampRequest.tags=Печат,добавяне на изображение,централно изображение,воден знак,PDF,вграждане,персонализиране
home.PDFToBook.title=PDF to Book home.PDFToBook.title=PDF към книга
home.PDFToBook.desc=Converts PDF to Book/Comic formats using calibre home.PDFToBook.desc=Преобразува PDF във формати на книги/комикси с помощта на calibre
PDFToBook.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle PDFToBook.tags=Книга,комикс,calibre,конвертиране,манга,Amazon,Kindle
home.BookToPDF.title=Book to PDF home.BookToPDF.title=Книга към PDF
home.BookToPDF.desc=Converts Books/Comics formats to PDF using calibre home.BookToPDF.desc=Преобразува формати на книги/комикси в PDF с помощта на calibre
BookToPDF.tags=Book,Comic,Calibre,Convert,manga,amazon,kindle BookToPDF.tags=Книга,комикс,calibre,конвертиране,манга,Amazon,Kindle
########################### ###########################
@@ -437,6 +450,8 @@ login.rememberme=Запомни ме
login.invalid=Невалидно потребителско име или парола. login.invalid=Невалидно потребителско име или парола.
login.locked=Вашият акаунт е заключен. login.locked=Вашият акаунт е заключен.
login.signinTitle=Моля впишете се login.signinTitle=Моля впишете се
login.ssoSignIn=Влизане чрез еднократно влизане
login.oauth2AutoCreateDisabled=OAUTH2 Автоматично създаване на потребител е деактивирано
#auto-redact #auto-redact
@@ -466,9 +481,9 @@ pdfToSinglePage.submit=Преобразуване към единична стр
#pageExtracter #pageExtracter
pageExtracter.title=Extract Pages pageExtracter.title=Извличане на страници
pageExtracter.header=Extract Pages pageExtracter.header=Извличане на страници
pageExtracter.submit=Extract pageExtracter.submit=Извличане
pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1) pageExtracter.placeholder=(e.g. 1,2,8 or 4,7,12-16 or 2n-1)
@@ -498,40 +513,40 @@ 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 файлове и ZIP файлове, съдържащи html/css/изображения и т.н HTMLToPDF.help=Приемане на HTML файлове и ZIP файлове, съдържащи html/css/изображения и т.н.
HTMLToPDF.submit=Преобразуване HTMLToPDF.submit=Преобразуване
HTMLToPDF.credit=Използва WeasyPrint HTMLToPDF.credit=Използва WeasyPrint
HTMLToPDF.zoom=Zoom level for displaying the website. HTMLToPDF.zoom=Ниво на мащабиране за показване на уебсайта.
HTMLToPDF.pageWidth=Width of the page in centimeters. (Blank to default) HTMLToPDF.pageWidth=Ширина на страницата в сантиметри. (Празно по подразбиране)
HTMLToPDF.pageHeight=Height of the page in centimeters. (Blank to default) HTMLToPDF.pageHeight=Височина на страницата в сантиметри. (Празно по подразбиране)
HTMLToPDF.marginTop=Top margin of the page in millimeters. (Blank to default) HTMLToPDF.marginTop=Горно поле на страницата в милиметри. (Празно по подразбиране)
HTMLToPDF.marginBottom=Bottom margin of the page in millimeters. (Blank to default) HTMLToPDF.marginBottom=Долно поле на страницата в милиметри. (Празно по подразбиране)
HTMLToPDF.marginLeft=Left margin of the page in millimeters. (Blank to default) HTMLToPDF.marginLeft=Ляво поле на страницата в милиметри. (Празно по подразбиране)
HTMLToPDF.marginRight=Right margin of the page in millimeters. (Blank to default) HTMLToPDF.marginRight=Дясно поле на страницата в милиметри. (Празно по подразбиране)
HTMLToPDF.printBackground=Render the background of websites. HTMLToPDF.printBackground=Изобразете фона на уебсайтове.
HTMLToPDF.defaultHeader=Enable Default Header (Name and page number) HTMLToPDF.defaultHeader=Активиране на горния колонтитул по подразбиране (име и номер на страница)
HTMLToPDF.cssMediaType=Change the CSS media type of the page. HTMLToPDF.cssMediaType=Променете CSS медийния тип на страницата.
HTMLToPDF.none=None HTMLToPDF.none=Няма
HTMLToPDF.print=Print HTMLToPDF.print=Печат
HTMLToPDF.screen=Screen HTMLToPDF.screen=Екран
#AddStampRequest #AddStampRequest
AddStampRequest.header=Stamp PDF AddStampRequest.header=Поставяне на печат на PDF
AddStampRequest.title=Stamp PDF AddStampRequest.title=Поставяне на печат на PDF
AddStampRequest.stampType=Stamp Type AddStampRequest.stampType=Тип печат
AddStampRequest.stampText=Stamp Text AddStampRequest.stampText=Поставяне на текст
AddStampRequest.stampImage=Stamp Image AddStampRequest.stampImage=Изображение с печат
AddStampRequest.alphabet=Alphabet AddStampRequest.alphabet=Азбука
AddStampRequest.fontSize=Font/Image Size AddStampRequest.fontSize=Размер на шрифта/изображението
AddStampRequest.rotation=Rotation AddStampRequest.rotation=Ротация
AddStampRequest.opacity=Opacity AddStampRequest.opacity=Непрозрачност
AddStampRequest.position=Position AddStampRequest.position=Позиция
AddStampRequest.overrideX=Override X Coordinate AddStampRequest.overrideX=Замяна на X координата
AddStampRequest.overrideY=Override Y Coordinate AddStampRequest.overrideY=Замяна на Y координата
AddStampRequest.customMargin=Custom Margin AddStampRequest.customMargin=Персонализиран марж
AddStampRequest.customColor=Custom Text Color AddStampRequest.customColor=Персонализиран цвят на текста
AddStampRequest.submit=Submit AddStampRequest.submit=Изпращане
#sanitizePDF #sanitizePDF
@@ -620,11 +635,11 @@ scalePages.submit=Подайте
certSign.title=Подписване на сертификат certSign.title=Подписване на сертификат
certSign.header=Подпишете PDF с вашия сертификат (В процес на работа) certSign.header=Подпишете PDF с вашия сертификат (В процес на работа)
certSign.selectPDF=Изберете PDF файл за подписване: certSign.selectPDF=Изберете PDF файл за подписване:
certSign.jksNote=Note: If your certificate type is not listed below, please convert it to a Java Keystore (.jks) file using the keytool command line tool. Then, choose the .jks file option below. certSign.jksNote=Забележка: Ако вашият тип сертификат не е в списъка по-долу, моля, конвертирайте го във файл на Java Keystore (.jks) с помощта на инструмента за команден ред keytool. След това изберете опцията за .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 Keystore файл (.p12 или .pfx) (По избор, ако е предоставен, трябва да съдържа вашия личен ключ и сертификат): certSign.selectP12=Изберете вашия PKCS#12 Keystore файл (.p12 или .pfx) (По избор, ако е предоставен, трябва да съдържа вашия личен ключ и сертификат):
certSign.selectJKS=Select Your Java Keystore File (.jks or .keystore): certSign.selectJKS=Изберете Вашия Java Keystore Файл (.jks или .keystore):
certSign.certType=Тип сертификат certSign.certType=Тип сертификат
certSign.password=Въведете вашата парола за Keystore за ключове или частен ключ (ако има): certSign.password=Въведете вашата парола за Keystore за ключове или частен ключ (ако има):
certSign.showSig=Показване на подпис certSign.showSig=Показване на подпис
@@ -645,9 +660,9 @@ removeBlanks.submit=Премахване на празни места
#removeAnnotations #removeAnnotations
removeAnnotations.title=Remove Annotations removeAnnotations.title=Премахване на анотации
removeAnnotations.header=Remove Annotations removeAnnotations.header=Премахване на анотации
removeAnnotations.submit=Remove removeAnnotations.submit=Премахване
#compare #compare
@@ -658,17 +673,17 @@ compare.document.2=Документ 2
compare.submit=Сравнявай compare.submit=Сравнявай
#BookToPDF #BookToPDF
BookToPDF.title=Books and Comics to PDF BookToPDF.title=Книги и комикси в PDF
BookToPDF.header=Book to PDF BookToPDF.header=Книга в PDF
BookToPDF.credit=Uses Calibre BookToPDF.credit=Използва Calibre
BookToPDF.submit=Convert BookToPDF.submit=Конвертиране
#PDFToBook #PDFToBook
PDFToBook.title=PDF to Book PDFToBook.title=PDF към книга
PDFToBook.header=PDF to Book PDFToBook.header=PDF към книга
PDFToBook.selectText.1=Format PDFToBook.selectText.1=Формат
PDFToBook.credit=Uses Calibre PDFToBook.credit=Използва Calibre
PDFToBook.submit=Convert PDFToBook.submit=Конвертиране
#sign #sign
sign.title=Подпишете sign.title=Подпишете
@@ -689,6 +704,7 @@ repair.submit=Поправи
#flatten #flatten
flatten.title=Изравнете flatten.title=Изравнете
flatten.header=Изравнете PDF-и flatten.header=Изравнете PDF-и
flatten.flattenOnlyForms=Изравнете само форми
flatten.submit=Изравнете flatten.submit=Изравнете
@@ -736,6 +752,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.supportedFileTypes=Поддържаните типове файлове трябва да включват по-долу, но за пълен актуализиран списък на поддържаните формати, моля, вижте документацията на LibreOffice fileToPDF.supportedFileTypes=Поддържаните типове файлове трябва да включват по-долу, но за пълен актуализиран списък на поддържаните формати, моля, вижте документацията на LibreOffice
fileToPDF.submit=Преобразуване към PDF fileToPDF.submit=Преобразуване към PDF
@@ -748,7 +765,7 @@ 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 размер (напр. 25МБ, 10.8МБ, 25КБ)
compress.submit=Компресиране compress.submit=Компресиране
@@ -772,27 +789,27 @@ merge.submit=Обединяване
pdfOrganiser.title=Организатор на страници pdfOrganiser.title=Организатор на страници
pdfOrganiser.header=Организатор на PDF страници pdfOrganiser.header=Организатор на PDF страници
pdfOrganiser.submit=Пренареждане на страниците pdfOrganiser.submit=Пренареждане на страниците
pdfOrganiser.mode=Mode pdfOrganiser.mode=Режим
pdfOrganiser.mode.1=Custom Page Order pdfOrganiser.mode.1=Персонализиран ред на страниците
pdfOrganiser.mode.2=Reverse Order pdfOrganiser.mode.2=Обърнат ред
pdfOrganiser.mode.3=Duplex Sort pdfOrganiser.mode.3=Двустранно сортиране
pdfOrganiser.mode.4=Booklet Sort pdfOrganiser.mode.4=Сортиране на брошури
pdfOrganiser.mode.5=Side Stitch Booklet Sort pdfOrganiser.mode.5=Сортиране на брошури със страничен шев
pdfOrganiser.mode.6=Odd-Even Split pdfOrganiser.mode.6=Четно-нечетно разделяне
pdfOrganiser.mode.7=Remove First pdfOrganiser.mode.7=Премахни първо
pdfOrganiser.mode.8=Remove Last pdfOrganiser.mode.8=Премахване на последния
pdfOrganiser.mode.9=Remove First and Last pdfOrganiser.mode.9=Премахване на първия и последния
pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1) pdfOrganiser.placeholder=(напр. 1,3,2 или 4-8,2,10-12 или 2n-1)
#multiTool #multiTool
multiTool.title=PDF Мулти инструмент multiTool.title=PDF Мулти инструмент
multiTool.header=PDF Мулти инструмент multiTool.header=PDF Мулти инструмент
multiTool.uploadPrompts=Please Upload PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=View PDF viewPdf.title=Преглед на PDF
viewPdf.header=View PDF viewPdf.header=Преглед на PDF
#pageRemover #pageRemover
pageRemover.title=Премахване на страници pageRemover.title=Премахване на страници
@@ -940,7 +957,8 @@ 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=Currently does not work for multiple inputs at once pdfToPDFA.tip=В момента не работи за няколко входа наведнъж
pdfToPDFA.outputFormat=Изходен формат
#PDFToWord #PDFToWord
@@ -983,75 +1001,75 @@ PDFToXML.submit=Преобразуване
#PDFToCSV #PDFToCSV
PDFToCSV.title=PDF ??? CSV PDFToCSV.title=PDF ??? CSV
PDFToCSV.header=PDF ??? CSV PDFToCSV.header=PDF ??? CSV
PDFToCSV.prompt=Choose page to extract table PDFToCSV.prompt=Изберете страница за извличане на таблица
PDFToCSV.submit=???????? PDFToCSV.submit=????
#split-by-size-or-count #split-by-size-or-count
split-by-size-or-count.title=Split PDF by Size or Count split-by-size-or-count.title=Разделяне на PDF по размер или брой
split-by-size-or-count.header=Split PDF by Size or Count split-by-size-or-count.header=Разделяне на PDF по размер или брой
split-by-size-or-count.type.label=Select Split Type split-by-size-or-count.type.label=Изберете тип разделяне
split-by-size-or-count.type.size=By Size split-by-size-or-count.type.size=По размер
split-by-size-or-count.type.pageCount=By Page Count split-by-size-or-count.type.pageCount=По брой страници
split-by-size-or-count.type.docCount=By Document Count split-by-size-or-count.type.docCount=По брой документи
split-by-size-or-count.value.label=Enter Value split-by-size-or-count.value.label=Въведете стойност
split-by-size-or-count.value.placeholder=Enter size (e.g., 2MB or 3KB) or count (e.g., 5) split-by-size-or-count.value.placeholder=Въведете размер (напр. 2МБ или 3КБ) или брой (напр. 5)
split-by-size-or-count.submit=Submit split-by-size-or-count.submit=Изпращане
#overlay-pdfs #overlay-pdfs
overlay-pdfs.header=Overlay PDF Files overlay-pdfs.header=Наслагване на PDF файлове
overlay-pdfs.baseFile.label=Select Base PDF File overlay-pdfs.baseFile.label=Изберете Основен PDF файл
overlay-pdfs.overlayFiles.label=Select Overlay PDF Files overlay-pdfs.overlayFiles.label=Изберете наслагване на PDF файлове
overlay-pdfs.mode.label=Select Overlay Mode overlay-pdfs.mode.label=Изберете режим на наслагване
overlay-pdfs.mode.sequential=Sequential Overlay overlay-pdfs.mode.sequential=Последователно наслагване
overlay-pdfs.mode.interleaved=Interleaved Overlay overlay-pdfs.mode.interleaved=Преплетено наслагване
overlay-pdfs.mode.fixedRepeat=Fixed Repeat Overlay overlay-pdfs.mode.fixedRepeat=Фиксирано наслагване при повторение
overlay-pdfs.counts.label=Overlay Counts (for Fixed Repeat Mode) overlay-pdfs.counts.label=Брой наслагвания (за режим на фиксирано повторение)
overlay-pdfs.counts.placeholder=Enter comma-separated counts (e.g., 2,3,1) overlay-pdfs.counts.placeholder=Въведете броя, разделени със запетая (напр. 2,3,1)
overlay-pdfs.position.label=Select Overlay Position overlay-pdfs.position.label=Изберете позиция на наслагване
overlay-pdfs.position.foreground=Foreground overlay-pdfs.position.foreground=Преден план
overlay-pdfs.position.background=Background overlay-pdfs.position.background=Фон
overlay-pdfs.submit=Submit overlay-pdfs.submit=Изпращане
#split-by-sections #split-by-sections
split-by-sections.title=Split PDF by Sections split-by-sections.title=Разделяне на PDF по секции
split-by-sections.header=Split PDF into Sections split-by-sections.header=Разделяне на PDF на секции
split-by-sections.horizontal.label=Horizontal Divisions split-by-sections.horizontal.label=Хоризонтални разделения
split-by-sections.vertical.label=Vertical Divisions split-by-sections.vertical.label=Вертикални разделения
split-by-sections.horizontal.placeholder=Enter number of horizontal divisions split-by-sections.horizontal.placeholder=Въведете брой хоризонтални деления
split-by-sections.vertical.placeholder=Enter number of vertical divisions split-by-sections.vertical.placeholder=Въведете брой вертикални деления
split-by-sections.submit=Split PDF split-by-sections.submit=Разделяне на PDF
split-by-sections.merge=Merge Into One PDF 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
licenses.nav=Licenses licenses.nav=Лицензи
licenses.title=3rd Party Licenses licenses.title=Лицензи на трети страни
licenses.header=3rd Party Licenses licenses.header=Лицензи на трети страни
licenses.module=Module licenses.module=Модул
licenses.version=Version licenses.version=Версия
licenses.license=License licenses.license=Лиценз
# error #error
error.sorry=Sorry for the issue! error.sorry=Извинете за проблема!
error.needHelp=Need help / Found an issue? error.needHelp=Нуждаете се от помощ / Открихте проблем?
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=Ако все още имате проблеми, не се колебайте да се свържете с нас за помощ. Можете да изпратите запитване на нашата страница в GitHub или да се свържете с нас чрез Discord:
error.404.head=404 - Page Not Found | Oops, we tripped in the code! error.404.head=404 - Страницата не е намерена | Опа! Спънахме се в кода!
error.404.1=We can't seem to find the page you're looking for. error.404.1=Изглежда не можем да намерим страницата, която търсите.
error.404.2=Something went wrong error.404.2=Нещо се обърка
error.github=Submit a ticket on GitHub error.github=Изпратете запитване в GitHub
error.showStack=Show Stack Trace error.showStack=Покажи проследяване на стека
error.copyStack=Copy Stack Trace error.copyStack=Копиране на проследяване на стека
error.githubSubmit=GitHub - Submit a ticket error.githubSubmit=GitHub - Изпратете запитване
error.discordSubmit=Discord - Submit Support post error.discordSubmit=Discord - Изпратете запитване за поддръжка

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found. userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect. incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists. usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers. invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=No es pot reduir la funció de l'usuari actual
downgradeCurrentUserLongMessage=No es pot baixar la funció de l'usuari actual. Per tant, no es mostrarà l'usuari actual.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=Error error=Error
oops=Oops! oops=Oops!
help=Help help=Help
@@ -67,6 +71,7 @@ visitGithub=Visit Github Repository
donate=Donate donate=Donate
color=Color color=Color
sponsor=Sponsor sponsor=Sponsor
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=Validate
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=Converteix navbar.favorite=Favorites
navbar.security=Seguretat
navbar.other=Altres
navbar.darkmode=Mode Fosc navbar.darkmode=Mode Fosc
navbar.pageOps=Operacions de Pàgina navbar.language=Languages
navbar.settings=Opcions navbar.settings=Opcions
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=Usuari Admin Opcions Control
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=Usuari adminUserSettings.user=Usuari
adminUserSettings.addUser=Afegir Usuari adminUserSettings.addUser=Afegir Usuari
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters. adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Rols adminUserSettings.roles=Rols
adminUserSettings.role=Rol adminUserSettings.role=Rol
adminUserSettings.actions=Accions adminUserSettings.actions=Accions
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Demo User (No custom settings)
adminUserSettings.internalApiUser=Internal API User adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Force user to change password on login adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Desar Usuari adminUserSettings.submit=Desar Usuari
adminUserSettings.changeUserRole=Canvia el rol de l'usuari
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=Recordar
login.invalid=Nom usuari / password no vàlid login.invalid=Nom usuari / password no vàlid
login.locked=Compte bloquejat login.locked=Compte bloquejat
login.signinTitle=Autenticat login.signinTitle=Autenticat
login.ssoSignIn=Inicia sessió mitjançant l'inici de sessió ún
login.oauth2AutoCreateDisabled=L'usuari de creació automàtica OAUTH2 està desactivat
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=Reparar
#flatten #flatten
flatten.title=Aplanar flatten.title=Aplanar
flatten.header=Aplana els PDF flatten.header=Aplana els PDF
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Aplanar flatten.submit=Aplanar
@@ -736,6 +752,7 @@ extractImages.submit=Extreu
fileToPDF.title=Arxiu a PDF fileToPDF.title=Arxiu a PDF
fileToPDF.header=Converteix arxiu a PDF fileToPDF.header=Converteix arxiu a PDF
fileToPDF.credit=Utilitza LibreOffice i Unoconv per a la conversió. fileToPDF.credit=Utilitza LibreOffice i Unoconv per a la conversió.
fileToPDF.supportedFileTypesInfo=Supported File types
fileToPDF.supportedFileTypes=Els tipus de fitxers admesos haurien d'incloure el següent, però per obtenir una llista completa actualitzada dels formats compatibles, consulteu la documentació de LibreOffice fileToPDF.supportedFileTypes=Els tipus de fitxers admesos haurien d'incloure el següent, però per obtenir una llista completa actualitzada dels formats compatibles, consulteu la documentació de LibreOffice
fileToPDF.submit=Converteix a PDF fileToPDF.submit=Converteix a PDF
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool #multiTool
multiTool.title=PDF Multi Tool multiTool.title=PDF Multi Tool
multiTool.header=PDF Multi Tool multiTool.header=PDF Multi Tool
multiTool.uploadPrompts=Please Upload PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=View PDF viewPdf.title=View PDF
@@ -941,6 +958,7 @@ pdfToPDFA.header=PDF a PDF/A
pdfToPDFA.credit=Utilitza OCRmyPDF per la conversió a PDF/A pdfToPDFA.credit=Utilitza OCRmyPDF per la conversió a PDF/A
pdfToPDFA.submit=Converteix pdfToPDFA.submit=Converteix
pdfToPDFA.tip=Currently does not work for multiple inputs at once pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Version
licenses.license=License licenses.license=License
# error #error
error.sorry=Sorry for the issue! error.sorry=Sorry for the issue!
error.needHelp=Need help / Found an issue? error.needHelp=Need help / Found an issue?
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=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:

View File

@@ -46,7 +46,7 @@ green=Grün
blue=Blau blue=Blau
custom=benutzerdefiniert... custom=benutzerdefiniert...
WorkInProgess=In Arbeit, funktioniert möglicherweise nicht oder ist fehlerhaft. Bitte melden Sie alle Probleme! WorkInProgess=In Arbeit, funktioniert möglicherweise nicht oder ist fehlerhaft. Bitte melden Sie alle Probleme!
poweredBy=Powered by poweredBy=Unterstützt von
yes=Ja yes=Ja
no=Nein no=Nein
changedCredsMessage=Anmeldedaten geändert! changedCredsMessage=Anmeldedaten geändert!
@@ -54,9 +54,13 @@ notAuthenticatedMessage=Benutzer nicht authentifiziert.
userNotFoundMessage=Benutzer nicht gefunden. userNotFoundMessage=Benutzer nicht gefunden.
incorrectPasswordMessage=Das Passwort ist falsch. incorrectPasswordMessage=Das Passwort ist falsch.
usernameExistsMessage=Neuer Benutzername existiert bereits. usernameExistsMessage=Neuer Benutzername existiert bereits.
invalidUsernameMessage=Ungültiger Benutzername. Der Benutzername darf nur Buchstaben und Zahlen enthalten. invalidUsernameMessage=Ungültiger Benutzername. Der Benutzername darf nur Buchstaben, Zahlen und die folgenden Sonderzeichen @._+- enthalten oder muss eine gültige E-Mail-Adresse sein.
deleteCurrentUserMessage=Der aktuell angemeldete Benutzer kann nicht gelöscht werden. deleteCurrentUserMessage=Der aktuell angemeldete Benutzer kann nicht gelöscht werden.
deleteUsernameExistsMessage=Der Benutzername existiert nicht und kann nicht gelöscht werden. deleteUsernameExistsMessage=Der Benutzername existiert nicht und kann nicht gelöscht werden.
downgradeCurrentUserMessage=Die Rolle des aktuellen Benutzers kann nicht herabgestuft werden
downgradeCurrentUserLongMessage=Die Rolle des aktuellen Benutzers kann nicht herabgestuft werden. Daher wird der aktuelle Benutzer nicht angezeigt.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=Fehler error=Fehler
oops=Hoppla! oops=Hoppla!
help=Hilfe help=Hilfe
@@ -67,6 +71,7 @@ visitGithub=GitHub-Repository besuchen
donate=Spenden donate=Spenden
color=Farbe color=Farbe
sponsor=Sponsor sponsor=Sponsor
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=Validieren
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=Konvertieren navbar.favorite=Favorites
navbar.security=Sicherheit
navbar.other=Anderes
navbar.darkmode=Dunkler Modus navbar.darkmode=Dunkler Modus
navbar.pageOps=Seitenoperationen navbar.language=Languages
navbar.settings=Einstellungen navbar.settings=Einstellungen
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -121,9 +132,9 @@ settings.downloadOption.3=Datei herunterladen
settings.zipThreshold=Dateien komprimieren, wenn die Anzahl der heruntergeladenen Dateien überschritten wird settings.zipThreshold=Dateien komprimieren, wenn die Anzahl der heruntergeladenen Dateien überschritten wird
settings.signOut=Abmelden settings.signOut=Abmelden
settings.accountSettings=Kontoeinstellungen settings.accountSettings=Kontoeinstellungen
settings.bored.help=Enables easter egg game settings.bored.help=Aktiviert das Easter-Egg-Spiel
settings.cacheInputs.name=Save form inputs settings.cacheInputs.name=Formulareingaben speichern
settings.cacheInputs.help=Enable to store previously used inputs for future runs settings.cacheInputs.help=Aktivieren, um zuvor verwendete Eingaben für zukünftige Durchläufe zu speichern
changeCreds.title=Anmeldeinformationen ändern changeCreds.title=Anmeldeinformationen ändern
changeCreds.header=Aktualisieren Sie Ihre Kontodaten changeCreds.header=Aktualisieren Sie Ihre Kontodaten
@@ -162,7 +173,7 @@ adminUserSettings.header=Administrator-Benutzerkontrolle
adminUserSettings.admin=Administrator adminUserSettings.admin=Administrator
adminUserSettings.user=Benutzer adminUserSettings.user=Benutzer
adminUserSettings.addUser=Neuen Benutzer hinzufügen adminUserSettings.addUser=Neuen Benutzer hinzufügen
adminUserSettings.usernameInfo=Der Benutzername darf nur Buchstaben und Zahlen enthalten, keine Leerzeichen oder Sonderzeichen. adminUserSettings.usernameInfo=Der Benutzername darf nur Buchstaben, Zahlen und die folgenden Sonderzeichen @._+- enthalten oder muss eine gültige E-Mail-Adresse sein.
adminUserSettings.roles=Rollen adminUserSettings.roles=Rollen
adminUserSettings.role=Rolle adminUserSettings.role=Rolle
adminUserSettings.actions=Aktion adminUserSettings.actions=Aktion
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Demo-Benutzer (Keine benutzerdefinierten Einstellunge
adminUserSettings.internalApiUser=Interner API-Benutzer adminUserSettings.internalApiUser=Interner API-Benutzer
adminUserSettings.forceChange=Benutzer dazu zwingen, Benutzernamen/Passwort bei der Anmeldung zu ändern adminUserSettings.forceChange=Benutzer dazu zwingen, Benutzernamen/Passwort bei der Anmeldung zu ändern
adminUserSettings.submit=Benutzer speichern adminUserSettings.submit=Benutzer speichern
adminUserSettings.changeUserRole=Benutzerrolle ändern
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=Angemeldet bleiben
login.invalid=Benutzername oder Passwort ungültig. login.invalid=Benutzername oder Passwort ungültig.
login.locked=Ihr Konto wurde gesperrt. login.locked=Ihr Konto wurde gesperrt.
login.signinTitle=Bitte melden Sie sich an. login.signinTitle=Bitte melden Sie sich an.
login.ssoSignIn=Anmeldung per Single Sign-On
login.oauth2AutoCreateDisabled=OAUTH2 Benutzer automatisch erstellen deaktiviert
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=Reparieren
#flatten #flatten
flatten.title=Abflachen flatten.title=Abflachen
flatten.header=PDFs reduzieren flatten.header=PDFs reduzieren
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Abflachen flatten.submit=Abflachen
@@ -736,6 +752,7 @@ extractImages.submit=Extrahieren
fileToPDF.title=Datei in PDF fileToPDF.title=Datei in PDF
fileToPDF.header=Beliebige Dateien in PDF konvertieren fileToPDF.header=Beliebige Dateien in PDF konvertieren
fileToPDF.credit=Dieser Dienst verwendet LibreOffice und Unoconv für die Dateikonvertierung. fileToPDF.credit=Dieser Dienst verwendet LibreOffice und Unoconv für die Dateikonvertierung.
fileToPDF.supportedFileTypesInfo=Supported File types
fileToPDF.supportedFileTypes=Unterstützte Dateitypen sollten die folgenden enthalten, eine vollständige aktualisierte Liste der unterstützten Formate finden Sie jedoch in der LibreOffice-Dokumentation fileToPDF.supportedFileTypes=Unterstützte Dateitypen sollten die folgenden enthalten, eine vollständige aktualisierte Liste der unterstützten Formate finden Sie jedoch in der LibreOffice-Dokumentation
fileToPDF.submit=In PDF konvertieren fileToPDF.submit=In PDF konvertieren
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(z.B. 1,3,2 oder 4-8,2,10-12 oder 2n-1)
#multiTool #multiTool
multiTool.title=PDF-Multitool multiTool.title=PDF-Multitool
multiTool.header=PDF-Multitool multiTool.header=PDF-Multitool
multiTool.uploadPrompts=Bitte PDF hochladen multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=PDF anzeigen viewPdf.title=PDF anzeigen
@@ -941,6 +958,7 @@ pdfToPDFA.header=PDF zu PDF/A
pdfToPDFA.credit=Dieser Dienst verwendet OCRmyPDF für die PDF/A-Konvertierung pdfToPDFA.credit=Dieser Dienst verwendet OCRmyPDF für die PDF/A-Konvertierung
pdfToPDFA.submit=Konvertieren pdfToPDFA.submit=Konvertieren
pdfToPDFA.tip=Dieser Dienst kann nur einzelne Eingangsdateien verarbeiten. pdfToPDFA.tip=Dieser Dienst kann nur einzelne Eingangsdateien verarbeiten.
pdfToPDFA.outputFormat=Ausgabeformat
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Version
licenses.license=Lizenz licenses.license=Lizenz
# error #error
error.sorry=Entschuldigung für das Problem! error.sorry=Entschuldigung für das Problem!
error.needHelp=Brauchst du Hilfe / Ein Problem gefunden? error.needHelp=Brauchst du Hilfe / Ein Problem gefunden?
error.contactTip=Wenn du weiterhin Probleme hast, zögere nicht, uns um Hilfe zu bitten. Du kannst ein Ticket auf unserer GitHub-Seite einreichen oder uns über Discord kontaktieren: error.contactTip=Wenn du weiterhin Probleme hast, zögere nicht, uns um Hilfe zu bitten. Du kannst ein Ticket auf unserer GitHub-Seite einreichen oder uns über Discord kontaktieren:

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=Ο χρήστης δεν έχει αυθεντικοπο
userNotFoundMessage=Ο χρήστης δεν βρέθηκε. userNotFoundMessage=Ο χρήστης δεν βρέθηκε.
incorrectPasswordMessage=Ο τρέχων κωδικός πρόσβασης είναι λανθασμένος. incorrectPasswordMessage=Ο τρέχων κωδικός πρόσβασης είναι λανθασμένος.
usernameExistsMessage=Το νέο όνομα χρήστη υπάρχει ήδη. usernameExistsMessage=Το νέο όνομα χρήστη υπάρχει ήδη.
invalidUsernameMessage=Μη έγκυρο όνομα χρήστη, το όνομα χρήστη πρέπει να περιέχει μόνο αλφαβητικούς χαρακτήρες και αριθμούς. invalidUsernameMessage=Μη έγκυρο όνομα χρήστη, όνομα χρήστη μπορεί να περιέχει μόνο γράμματα, αριθμούς και τους ακόλουθους ειδικούς χαρακτήρες @._+- ή πρέπει να είναι έγκυρη διεύθυνση email.
deleteCurrentUserMessage=Δεν είναι δυνατή η διαγραφή του τρέχοντος συνδεδεμένου χρήστη. deleteCurrentUserMessage=Δεν είναι δυνατή η διαγραφή του τρέχοντος συνδεδεμένου χρήστη.
deleteUsernameExistsMessage=Το όνομα χρήστη δεν υπάρχει και δεν μπορεί να διαγραφεί. deleteUsernameExistsMessage=Το όνομα χρήστη δεν υπάρχει και δεν μπορεί να διαγραφεί.
downgradeCurrentUserMessage=Δεν είναι δυνατή η υποβάθμιση του ρόλου του τρέχοντος χρήστη
downgradeCurrentUserLongMessage=Δεν είναι δυνατή η υποβάθμιση του ρόλου του τρέχοντος χρήστη. Ως εκ τούτου, ο τρέχων χρήστης δεν θα εμφανίζεται.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=Σφάλμα error=Σφάλμα
oops=Ωχ! oops=Ωχ!
help=Βοήθεια help=Βοήθεια
@@ -67,6 +71,7 @@ visitGithub=Επισκεφθείτε το Αποθετήριο του Github
donate=Δωρισε donate=Δωρισε
color=Χρώμα color=Χρώμα
sponsor=οστηρικτής sponsor=οστηρικτής
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=Επικυρώνω
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=Μετατροπή navbar.favorite=Favorites
navbar.security=Ασφάλεια
navbar.other=Διάφορα
navbar.darkmode=Μαύρο Θέμα navbar.darkmode=Μαύρο Θέμα
navbar.pageOps=Λειτουργίες σελίδας navbar.language=Languages
navbar.settings=Ρυθμίσεις navbar.settings=Ρυθμίσεις
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=Ρυθμίσεις ελέγχου Διαχειριστ
adminUserSettings.admin=Διαχειριστής adminUserSettings.admin=Διαχειριστής
adminUserSettings.user=Χρήστης adminUserSettings.user=Χρήστης
adminUserSettings.addUser=Προσθήκη νέου Χρήστη adminUserSettings.addUser=Προσθήκη νέου Χρήστη
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters. adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Ρόλοι adminUserSettings.roles=Ρόλοι
adminUserSettings.role=Ρόλος adminUserSettings.role=Ρόλος
adminUserSettings.actions=Ενέργειες adminUserSettings.actions=Ενέργειες
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Demo χρήστης (Χωρίς προσαρμοσμ
adminUserSettings.internalApiUser=Εσωτερικός API χρήστης adminUserSettings.internalApiUser=Εσωτερικός API χρήστης
adminUserSettings.forceChange=Αναγκάστε τον χρήστη να αλλάξει το όνομα χρήστη/κωδικό πρόσβασης κατά τη σύνδεση adminUserSettings.forceChange=Αναγκάστε τον χρήστη να αλλάξει το όνομα χρήστη/κωδικό πρόσβασης κατά τη σύνδεση
adminUserSettings.submit=Αποθήκευση Χρήστη adminUserSettings.submit=Αποθήκευση Χρήστη
adminUserSettings.changeUserRole=Αλλαγή ρόλου χρήστη
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=Να Με Θυμάσαι
login.invalid=Λάθος όνομα χρήστη ή κωδικού πρόσβασης. login.invalid=Λάθος όνομα χρήστη ή κωδικού πρόσβασης.
login.locked=Ο λογαριασμός σας έχει κλειδωθεί. login.locked=Ο λογαριασμός σας έχει κλειδωθεί.
login.signinTitle=Παρακαλώ, συνδεθείτε login.signinTitle=Παρακαλώ, συνδεθείτε
login.ssoSignIn=Σύνδεση μέσω μοναδικής σύνδεσης
login.oauth2AutoCreateDisabled=Απενεργοποιήθηκε ο χρήστης αυτόματης δημιουργίας OAUTH2
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=Επιδιόρθωση
#flatten #flatten
flatten.title=Flatten flatten.title=Flatten
flatten.header=Flatten PDFs flatten.header=Flatten PDFs
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Flatten flatten.submit=Flatten
@@ -736,6 +752,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.supportedFileTypes=Οι υποστηριζόμενοι τύποι αρχείων θα πρέπει να περιλαμβάνουν τα παρακάτω, ωστόσο, για μια πλήρη ενημερωμένη λίστα με τις υποστηριζόμενες μορφές, ανατρέξτε στην τεκμηρίωση του LibreOffice fileToPDF.supportedFileTypes=Οι υποστηριζόμενοι τύποι αρχείων θα πρέπει να περιλαμβάνουν τα παρακάτω, ωστόσο, για μια πλήρη ενημερωμένη λίστα με τις υποστηριζόμενες μορφές, ανατρέξτε στην τεκμηρίωση του LibreOffice
fileToPDF.submit=Μετατροπή σε PDF fileToPDF.submit=Μετατροπή σε PDF
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(π.χ. 1,3,2 ή 4-8,2,10-12 ή 2n-1)
#multiTool #multiTool
multiTool.title=PDF Πολυεργαλείο multiTool.title=PDF Πολυεργαλείο
multiTool.header=PDF Πολυεργαλείο multiTool.header=PDF Πολυεργαλείο
multiTool.uploadPrompts=Ανεβάστε το PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=Προβολή PDF viewPdf.title=Προβολή PDF
@@ -941,6 +958,7 @@ 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
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Εκδοχή
licenses.license=Άδεια licenses.license=Άδεια
# error #error
error.sorry=Συγγνώμη για το ζήτημα! error.sorry=Συγγνώμη για το ζήτημα!
error.needHelp=Χρειάζεστε βοήθεια / Βρήκατε πρόβλημα; error.needHelp=Χρειάζεστε βοήθεια / Βρήκατε πρόβλημα;
error.contactTip=Εάν εξακολουθείτε να αντιμετωπίζετε προβλήματα, μη διστάσετε να επικοινωνήσετε μαζί μας για βοήθεια. Μπορείτε να υποβάλετε ένα ticket στη σελίδα μας στο GitHub ή να επικοινωνήσετε μαζί μας μέσω του Discord: error.contactTip=Εάν εξακολουθείτε να αντιμετωπίζετε προβλήματα, μη διστάσετε να επικοινωνήσετε μαζί μας για βοήθεια. Μπορείτε να υποβάλετε ένα ticket στη σελίδα μας στο GitHub ή να επικοινωνήσετε μαζί μας μέσω του Discord:

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found. userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect. incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists. usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers. invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Cannot downgrade current user's role
downgradeCurrentUserLongMessage=Cannot downgrade current user's role. Hence, current user will not be shown.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=Error error=Error
oops=Oops! oops=Oops!
help=Help help=Help
@@ -67,6 +71,7 @@ visitGithub=Visit Github Repository
donate=Donate donate=Donate
color=Color color=Color
sponsor=Sponsor sponsor=Sponsor
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=Validate
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=Convert navbar.favorite=Favorites
navbar.security=Security
navbar.other=Miscellaneous
navbar.darkmode=Dark Mode navbar.darkmode=Dark Mode
navbar.pageOps=Page Operations navbar.language=Languages
navbar.settings=Settings navbar.settings=Settings
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=User adminUserSettings.user=User
adminUserSettings.addUser=Add New User adminUserSettings.addUser=Add New User
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters. adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles adminUserSettings.roles=Roles
adminUserSettings.role=Role adminUserSettings.role=Role
adminUserSettings.actions=Actions adminUserSettings.actions=Actions
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Demo User (No custom settings)
adminUserSettings.internalApiUser=Internal API User adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Force user to change password on login adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=Change User's Role
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=Remember me
login.invalid=Invalid username or password. login.invalid=Invalid username or password.
login.locked=Your account has been locked. login.locked=Your account has been locked.
login.signinTitle=Please sign in login.signinTitle=Please sign in
login.ssoSignIn=Login via Single Sign-on
login.oauth2AutoCreateDisabled=OAUTH2 Auto-Create User Disabled
#auto-redact #auto-redact
@@ -688,7 +703,8 @@ repair.submit=Repair
#flatten #flatten
flatten.title=Flatten flatten.title=Flatten
flatten.header=Flatten PDFs flatten.header=Flatten PDF
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Flatten flatten.submit=Flatten
@@ -736,6 +752,7 @@ extractImages.submit=Extract
fileToPDF.title=File to PDF fileToPDF.title=File to PDF
fileToPDF.header=Convert any file to PDF fileToPDF.header=Convert any file to PDF
fileToPDF.credit=This service uses LibreOffice and Unoconv for file conversion. fileToPDF.credit=This service uses LibreOffice and Unoconv for file conversion.
fileToPDF.supportedFileTypesInfo=Supported File types
fileToPDF.supportedFileTypes=Supported file types should include the below however for a full updated list of supported formats, please refer to the LibreOffice documentation fileToPDF.supportedFileTypes=Supported file types should include the below however for a full updated list of supported formats, please refer to the LibreOffice documentation
fileToPDF.submit=Convert to PDF fileToPDF.submit=Convert to PDF
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool #multiTool
multiTool.title=PDF Multi Tool multiTool.title=PDF Multi Tool
multiTool.header=PDF Multi Tool multiTool.header=PDF Multi Tool
multiTool.uploadPrompts=Please Upload PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=View PDF viewPdf.title=View PDF
@@ -941,6 +958,7 @@ pdfToPDFA.header=PDF To PDF/A
pdfToPDFA.credit=This service uses OCRmyPDF for PDF/A conversion pdfToPDFA.credit=This service uses OCRmyPDF for PDF/A conversion
pdfToPDFA.submit=Convert pdfToPDFA.submit=Convert
pdfToPDFA.tip=Currently does not work for multiple inputs at once pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Version
licenses.license=License licenses.license=License
# error #error
error.sorry=Sorry for the issue! error.sorry=Sorry for the issue!
error.needHelp=Need help / Found an issue? error.needHelp=Need help / Found an issue?
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=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:

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found. userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect. incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists. usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers. invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Cannot downgrade current user's role
downgradeCurrentUserLongMessage=Cannot downgrade current user's role. Hence, current user will not be shown.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=Error error=Error
oops=Oops! oops=Oops!
help=Help help=Help
@@ -67,6 +71,7 @@ visitGithub=Visit Github Repository
donate=Donate donate=Donate
color=Color color=Color
sponsor=Sponsor sponsor=Sponsor
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=Validate
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=Convert navbar.favorite=Favorites
navbar.security=Security
navbar.other=Miscellaneous
navbar.darkmode=Dark Mode navbar.darkmode=Dark Mode
navbar.pageOps=Page Operations navbar.language=Languages
navbar.settings=Settings navbar.settings=Settings
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=User adminUserSettings.user=User
adminUserSettings.addUser=Add New User adminUserSettings.addUser=Add New User
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters. adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles adminUserSettings.roles=Roles
adminUserSettings.role=Role adminUserSettings.role=Role
adminUserSettings.actions=Actions adminUserSettings.actions=Actions
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Demo User (No custom settings)
adminUserSettings.internalApiUser=Internal API User adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Force user to change password on login adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=Change User's Role
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -327,7 +340,7 @@ home.scalePages.title=Adjust page size/scale
home.scalePages.desc=Change the size/scale of a page and/or its contents. home.scalePages.desc=Change the size/scale of a page and/or its contents.
scalePages.tags=resize,modify,dimension,adapt scalePages.tags=resize,modify,dimension,adapt
home.pipeline.title=Pipeline (Advanced) home.pipeline.title=Pipeline
home.pipeline.desc=Run multiple actions on PDFs by defining pipeline scripts home.pipeline.desc=Run multiple actions on PDFs by defining pipeline scripts
pipeline.tags=automate,sequence,scripted,batch-process pipeline.tags=automate,sequence,scripted,batch-process
@@ -379,7 +392,7 @@ home.extractPage.desc=Extracts select pages from PDF
extractPage.tags=extract extractPage.tags=extract
home.PdfToSinglePage.title=PDF to Single Large Page home.PdfToSinglePage.title=Single Large Page
home.PdfToSinglePage.desc=Merges all PDF pages into one large single page home.PdfToSinglePage.desc=Merges all PDF pages into one large single page
PdfToSinglePage.tags=single page PdfToSinglePage.tags=single page
@@ -437,6 +450,8 @@ login.rememberme=Remember me
login.invalid=Invalid username or password. login.invalid=Invalid username or password.
login.locked=Your account has been locked. login.locked=Your account has been locked.
login.signinTitle=Please sign in login.signinTitle=Please sign in
login.ssoSignIn=Login via Single Sign-on
login.oauth2AutoCreateDisabled=OAUTH2 Auto-Create User Disabled
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=Repair
#flatten #flatten
flatten.title=Flatten flatten.title=Flatten
flatten.header=Flatten PDFs flatten.header=Flatten PDFs
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Flatten flatten.submit=Flatten
@@ -736,6 +752,7 @@ extractImages.submit=Extract
fileToPDF.title=File to PDF fileToPDF.title=File to PDF
fileToPDF.header=Convert any file to PDF fileToPDF.header=Convert any file to PDF
fileToPDF.credit=This service uses LibreOffice and Unoconv for file conversion. fileToPDF.credit=This service uses LibreOffice and Unoconv for file conversion.
fileToPDF.supportedFileTypesInfo=Supported File types
fileToPDF.supportedFileTypes=Supported file types should include the below however for a full updated list of supported formats, please refer to the LibreOffice documentation fileToPDF.supportedFileTypes=Supported file types should include the below however for a full updated list of supported formats, please refer to the LibreOffice documentation
fileToPDF.submit=Convert to PDF fileToPDF.submit=Convert to PDF
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool #multiTool
multiTool.title=PDF Multi Tool multiTool.title=PDF Multi Tool
multiTool.header=PDF Multi Tool multiTool.header=PDF Multi Tool
multiTool.uploadPrompts=Please Upload PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=View PDF viewPdf.title=View PDF
@@ -941,6 +958,7 @@ pdfToPDFA.header=PDF To PDF/A
pdfToPDFA.credit=This service uses OCRmyPDF for PDF/A conversion pdfToPDFA.credit=This service uses OCRmyPDF for PDF/A conversion
pdfToPDFA.submit=Convert pdfToPDFA.submit=Convert
pdfToPDFA.tip=Currently does not work for multiple inputs at once pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Version
licenses.license=License licenses.license=License
# error #error
error.sorry=Sorry for the issue! error.sorry=Sorry for the issue!
error.needHelp=Need help / Found an issue? error.needHelp=Need help / Found an issue?
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=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:

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=Usuario no autentificado.
userNotFoundMessage=Usuario no encontrado. userNotFoundMessage=Usuario no encontrado.
incorrectPasswordMessage=La contraseña actual no es correcta. incorrectPasswordMessage=La contraseña actual no es correcta.
usernameExistsMessage=El nuevo nombre de usuario está en uso. usernameExistsMessage=El nuevo nombre de usuario está en uso.
invalidUsernameMessage=Nombre de usuario no válido, El nombre de ususario debe contener únicamente números y caracteres alfabéticos. invalidUsernameMessage=Nombre de usuario no válido, el nombre de usuario solo puede contener letras, números y los siguientes caracteres especiales @._+- o debe ser una dirección de correo electrónico válida.
deleteCurrentUserMessage=No puede eliminar el usuario que tiene la sesión actualmente en uso. deleteCurrentUserMessage=No puede eliminar el usuario que tiene la sesión actualmente en uso.
deleteUsernameExistsMessage=El usuario no existe y no puede eliminarse. deleteUsernameExistsMessage=El usuario no existe y no puede eliminarse.
downgradeCurrentUserMessage=No se puede degradar el rol del usuario actual
downgradeCurrentUserLongMessage=No se puede degradar el rol del usuario actual. Por lo tanto, el usuario actual no se mostrará.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=Error error=Error
oops=Ups! oops=Ups!
help=Help help=Help
@@ -67,6 +71,7 @@ visitGithub=Visitar Repositorio de Github
donate=Donar donate=Donar
color=Color color=Color
sponsor=Patrocinador sponsor=Patrocinador
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=Validar
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=Convertir navbar.favorite=Favorites
navbar.security=Seguridad
navbar.other=Otro
navbar.darkmode=Modo oscuro navbar.darkmode=Modo oscuro
navbar.pageOps=Operaciones de página navbar.language=Languages
navbar.settings=Configuración navbar.settings=Configuración
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=Configuración de control de usuario administrador
adminUserSettings.admin=Administrador adminUserSettings.admin=Administrador
adminUserSettings.user=Usuario adminUserSettings.user=Usuario
adminUserSettings.addUser=Añadir Nuevo Usuario adminUserSettings.addUser=Añadir Nuevo Usuario
adminUserSettings.usernameInfo=El nombrede usuario debe contener únicamente letras y números, no espacios ni caracteres especiales. adminUserSettings.usernameInfo=El nombre de usuario solo puede contener letras, números y los siguientes caracteres especiales @._+- o debe ser una dirección de correo electrónico válida.
adminUserSettings.roles=Roles adminUserSettings.roles=Roles
adminUserSettings.role=Rol adminUserSettings.role=Rol
adminUserSettings.actions=Acciones adminUserSettings.actions=Acciones
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Usuario Demo (Sin ajustes personalizados)
adminUserSettings.internalApiUser=Usuario interno de API adminUserSettings.internalApiUser=Usuario interno de API
adminUserSettings.forceChange=Forzar usuario a cambiar usuario/contraseña en el acceso adminUserSettings.forceChange=Forzar usuario a cambiar usuario/contraseña en el acceso
adminUserSettings.submit=Guardar Usuario adminUserSettings.submit=Guardar Usuario
adminUserSettings.changeUserRole=Cambiar rol de usuario
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=Recordarme
login.invalid=Nombre de usuario o contraseña erróneos. login.invalid=Nombre de usuario o contraseña erróneos.
login.locked=Su cuenta se ha bloqueado. login.locked=Su cuenta se ha bloqueado.
login.signinTitle=Por favor, inicie sesión login.signinTitle=Por favor, inicie sesión
login.ssoSignIn=Iniciar sesión a través del inicio de sesión único
login.oauth2AutoCreateDisabled=Usuario DE creación automática de OAUTH2 DESACTIVADO
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=Reparar
#flatten #flatten
flatten.title=Aplanar flatten.title=Aplanar
flatten.header=Acoplar archivos PDF flatten.header=Acoplar archivos PDF
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Aplanar flatten.submit=Aplanar
@@ -736,6 +752,7 @@ extractImages.submit=Extraer
fileToPDF.title=Archivo a PDF fileToPDF.title=Archivo a PDF
fileToPDF.header=Convertir cualquier archivo a PDF fileToPDF.header=Convertir cualquier archivo a PDF
fileToPDF.credit=Este servicio usa LibreOffice y Unoconv para la conversión de archivos fileToPDF.credit=Este servicio usa LibreOffice y Unoconv para la conversión de archivos
fileToPDF.supportedFileTypesInfo=Supported File types
fileToPDF.supportedFileTypes=Los tipos de archivo soportados deben incluir los indicados a continuación; sin embargo, para una completa y acutualizada lista de formatos soportados, por favor consulte la documentación de LibreOffice fileToPDF.supportedFileTypes=Los tipos de archivo soportados deben incluir los indicados a continuación; sin embargo, para una completa y acutualizada lista de formatos soportados, por favor consulte la documentación de LibreOffice
fileToPDF.submit=Convertir a PDF fileToPDF.submit=Convertir a PDF
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(por ej., 1,3,2 o 4-8,2,10-12 o 2n-1)
#multiTool #multiTool
multiTool.title=Multi-herramienta PDF multiTool.title=Multi-herramienta PDF
multiTool.header=Multi-herramienta PDF multiTool.header=Multi-herramienta PDF
multiTool.uploadPrompts=Por favor, cargue PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=Ver PDF viewPdf.title=Ver PDF
@@ -941,6 +958,7 @@ pdfToPDFA.header=PDF a PDF/A
pdfToPDFA.credit=Este servicio usa OCRmyPDF para la conversión a PDF/A pdfToPDFA.credit=Este servicio usa OCRmyPDF para la conversión a PDF/A
pdfToPDFA.submit=Convertir pdfToPDFA.submit=Convertir
pdfToPDFA.tip=Actualmente no funciona para múltiples entrada a la vez pdfToPDFA.tip=Actualmente no funciona para múltiples entrada a la vez
pdfToPDFA.outputFormat=Output format
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Versión
licenses.license=Licencia licenses.license=Licencia
# error #error
error.sorry=¡Perdón por el fallo! error.sorry=¡Perdón por el fallo!
error.needHelp=Necesita ayuda / Encontró un fallo? error.needHelp=Necesita ayuda / Encontró un fallo?
error.contactTip=Si sigue experimentando errores, no dude en contactarnos para solicitar soporte. Puede enviarnos un ticket en la página de GitHub o contactarnos mediante Discord: error.contactTip=Si sigue experimentando errores, no dude en contactarnos para solicitar soporte. Puede enviarnos un ticket en la página de GitHub o contactarnos mediante Discord:

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found. userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect. incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists. usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers. invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Ezin da uneko erabiltzailearen rola jaitsi
downgradeCurrentUserLongMessage=Ezin da uneko erabiltzailearen rola jaitsi. Beraz, oraingo erabiltzailea ez da erakutsiko.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=Error error=Error
oops=Oops! oops=Oops!
help=Help help=Help
@@ -67,6 +71,7 @@ visitGithub=Visit Github Repository
donate=Donate donate=Donate
color=Color color=Color
sponsor=Sponsor sponsor=Sponsor
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=Validate
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=Bihurtu navbar.favorite=Favorites
navbar.security=Segurtasuna
navbar.other=Beste bat
navbar.darkmode=Modu iluna navbar.darkmode=Modu iluna
navbar.pageOps=Orrialde-eragiketak navbar.language=Languages
navbar.settings=Ezarpenak navbar.settings=Ezarpenak
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=Admin Erabiltzailearen Ezarpenen Kontrolak
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=Erabiltzaile adminUserSettings.user=Erabiltzaile
adminUserSettings.addUser=Erabiltzaile berria adminUserSettings.addUser=Erabiltzaile berria
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters. adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Rolak adminUserSettings.roles=Rolak
adminUserSettings.role=Rol adminUserSettings.role=Rol
adminUserSettings.actions=Ekintzak adminUserSettings.actions=Ekintzak
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Demo User (No custom settings)
adminUserSettings.internalApiUser=Internal API User adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Force user to change password on login adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Gorde Erabiltzailea adminUserSettings.submit=Gorde Erabiltzailea
adminUserSettings.changeUserRole=Erabiltzailearen rola aldatu
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=Oroitu nazazu
login.invalid=Okerreko erabiltzaile izena edo pasahitza. login.invalid=Okerreko erabiltzaile izena edo pasahitza.
login.locked=Zure kontua blokeatu egin da. login.locked=Zure kontua blokeatu egin da.
login.signinTitle=Mesedez, hasi saioa login.signinTitle=Mesedez, hasi saioa
login.ssoSignIn=Hasi saioa Saioa hasteko modu bakarraren bidez
login.oauth2AutoCreateDisabled=OAUTH2 Sortu automatikoki erabiltzailea desgaituta dago
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=Konpondu
#flatten #flatten
flatten.title=Lautu flatten.title=Lautu
flatten.header=Akoplatu PDF fitxategiak flatten.header=Akoplatu PDF fitxategiak
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Lautu flatten.submit=Lautu
@@ -736,6 +752,7 @@ extractImages.submit=Atera
fileToPDF.title=Fitxategia PDF bihurtu fileToPDF.title=Fitxategia PDF bihurtu
fileToPDF.header=Edozein fitxategi PDF bihurtu fileToPDF.header=Edozein fitxategi PDF bihurtu
fileToPDF.credit=Zerbitzu honek LibreOffice eta Unoconv erabiltzen ditu fitxategiak bihurtzeko fileToPDF.credit=Zerbitzu honek LibreOffice eta Unoconv erabiltzen ditu fitxategiak bihurtzeko
fileToPDF.supportedFileTypesInfo=Supported File types
fileToPDF.supportedFileTypes=Jasandako fitxategi-motek behekoak barne hartu behar dituzte; hala ere, jasandako formatuen zerrenda osoa eta eguneratua izateko, kontsultatu, mesedez, LibreOffice-en dokumentazioa fileToPDF.supportedFileTypes=Jasandako fitxategi-motek behekoak barne hartu behar dituzte; hala ere, jasandako formatuen zerrenda osoa eta eguneratua izateko, kontsultatu, mesedez, LibreOffice-en dokumentazioa
fileToPDF.submit=PDF bihurtu fileToPDF.submit=PDF bihurtu
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool #multiTool
multiTool.title=PDF erabilera anitzeko tresna multiTool.title=PDF erabilera anitzeko tresna
multiTool.header=PDF erabilera anitzeko tresna multiTool.header=PDF erabilera anitzeko tresna
multiTool.uploadPrompts=Please Upload PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=View PDF viewPdf.title=View PDF
@@ -941,6 +958,7 @@ pdfToPDFA.header=PDFa PDF/A bihurtu
pdfToPDFA.credit=Zerbitzu honek OCRmyPDF erabiltzen du PDFak PDF/A bihurtzeko pdfToPDFA.credit=Zerbitzu honek OCRmyPDF erabiltzen du PDFak PDF/A bihurtzeko
pdfToPDFA.submit=Bihurtu pdfToPDFA.submit=Bihurtu
pdfToPDFA.tip=Currently does not work for multiple inputs at once pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Version
licenses.license=License licenses.license=License
# error #error
error.sorry=Sorry for the issue! error.sorry=Sorry for the issue!
error.needHelp=Need help / Found an issue? error.needHelp=Need help / Found an issue?
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=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:

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=Utilisateur non authentifié.
userNotFoundMessage=Utilisateur non trouvé. userNotFoundMessage=Utilisateur non trouvé.
incorrectPasswordMessage=Le mot de passe actuel est incorrect. incorrectPasswordMessage=Le mot de passe actuel est incorrect.
usernameExistsMessage=Le nouveau nom dutilisateur existe déjà. usernameExistsMessage=Le nouveau nom dutilisateur existe déjà.
invalidUsernameMessage=Nom dutilisateur invalide, le nom dutilisateur ne peut contenir que des chiffres et des lettres. invalidUsernameMessage=Nom dutilisateur invalide, le nom dutilisateur ne peut contenir que des lettres, des chiffres et les caractères spéciaux suivants @._+- ou doit être une adresse e-mail valide.
deleteCurrentUserMessage=Impossible de supprimer lutilisateur actuellement connecté. deleteCurrentUserMessage=Impossible de supprimer lutilisateur actuellement connecté.
deleteUsernameExistsMessage=Le nom dutilisateur nexiste pas et ne peut pas être supprimé. deleteUsernameExistsMessage=Le nom dutilisateur nexiste pas et ne peut pas être supprimé.
downgradeCurrentUserMessage=Impossible de rétrograder le rôle de l'utilisateur actuel
downgradeCurrentUserLongMessage=Impossible de rétrograder le rôle de l'utilisateur actuel. Par conséquent, l'utilisateur actuel ne sera pas affiché.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=Erreur error=Erreur
oops=Oups ! oops=Oups !
help=Aide help=Aide
@@ -67,6 +71,7 @@ visitGithub=Visiter le dépôt Github
donate=Faire un don donate=Faire un don
color=Couleur color=Couleur
sponsor=Sponsor sponsor=Sponsor
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=Valider
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=Convertir navbar.favorite=Favorites
navbar.security=Sécurité
navbar.other=Autre
navbar.darkmode=Mode sombre navbar.darkmode=Mode sombre
navbar.pageOps=Opérations sur les pages navbar.language=Languages
navbar.settings=Paramètres navbar.settings=Paramètres
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=Administration des paramètres des utilisateurs
adminUserSettings.admin=Administateur adminUserSettings.admin=Administateur
adminUserSettings.user=Utilisateur adminUserSettings.user=Utilisateur
adminUserSettings.addUser=Ajouter un utilisateur adminUserSettings.addUser=Ajouter un utilisateur
adminUserSettings.usernameInfo=Le nom dutilisateur ne doit contenir que des lettres et des chiffres, sans espaces ni caractères spéciaux. adminUserSettings.usernameInfo=Le nom d'utilisateur ne peut contenir que des lettres, des chiffres et les caractères spéciaux suivants @._+- ou doit être une adresse e-mail valide.
adminUserSettings.roles=Rôles adminUserSettings.roles=Rôles
adminUserSettings.role=Rôle adminUserSettings.role=Rôle
adminUserSettings.actions=Actions adminUserSettings.actions=Actions
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Demo User (Paramètres par défaut)
adminUserSettings.internalApiUser=Internal API User adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Forcer lutilisateur à changer son nom dutilisateur/mot de passe lors de la connexion adminUserSettings.forceChange=Forcer lutilisateur à changer son nom dutilisateur/mot de passe lors de la connexion
adminUserSettings.submit=Ajouter adminUserSettings.submit=Ajouter
adminUserSettings.changeUserRole=Changer le rôle de l'utilisateur
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=Se souvenir de moi
login.invalid=Nom dutilisateur ou mot de passe invalide. login.invalid=Nom dutilisateur ou mot de passe invalide.
login.locked=Votre compte a été verrouillé. login.locked=Votre compte a été verrouillé.
login.signinTitle=Veuillez vous connecter login.signinTitle=Veuillez vous connecter
login.ssoSignIn=Se connecter via l'authentification unique
login.oauth2AutoCreateDisabled=OAUTH2 Création automatique d'utilisateur désactivée
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=Réparer
#flatten #flatten
flatten.title=Rendre inerte flatten.title=Rendre inerte
flatten.header=Rendre inerte flatten.header=Rendre inerte
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Rendre inerte flatten.submit=Rendre inerte
@@ -736,6 +752,7 @@ extractImages.submit=Extraire
fileToPDF.title=Fichier en PDF fileToPDF.title=Fichier en PDF
fileToPDF.header=Convertir un fichier en PDF fileToPDF.header=Convertir un fichier en PDF
fileToPDF.credit=Ce service utilise LibreOffice et Unoconv pour la conversion de fichiers. fileToPDF.credit=Ce service utilise LibreOffice et Unoconv pour la conversion de fichiers.
fileToPDF.supportedFileTypesInfo=Supported File types
fileToPDF.supportedFileTypes=Les types de fichiers pris en charge doivent inclure les éléments ci-dessous, mais pour une liste complète et mise à jour des formats pris en charge, veuillez vous reporter à la documentation de LibreOffice. fileToPDF.supportedFileTypes=Les types de fichiers pris en charge doivent inclure les éléments ci-dessous, mais pour une liste complète et mise à jour des formats pris en charge, veuillez vous reporter à la documentation de LibreOffice.
fileToPDF.submit=Convertir fileToPDF.submit=Convertir
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool #multiTool
multiTool.title=Outil multifonction PDF multiTool.title=Outil multifonction PDF
multiTool.header=Outil multifonction PDF multiTool.header=Outil multifonction PDF
multiTool.uploadPrompts=Please Upload PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=Visualiser un PDF viewPdf.title=Visualiser un PDF
@@ -941,6 +958,7 @@ pdfToPDFA.header=PDF en PDF/A
pdfToPDFA.credit=Ce service utilise OCRmyPDF pour la conversion en PDF/A. pdfToPDFA.credit=Ce service utilise OCRmyPDF pour la conversion en PDF/A.
pdfToPDFA.submit=Convertir pdfToPDFA.submit=Convertir
pdfToPDFA.tip=Currently does not work for multiple inputs at once pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Version
licenses.license=Licence licenses.license=Licence
# error #error
error.sorry=Désolé pour ce problème ! error.sorry=Désolé pour ce problème !
error.needHelp=Besoin daide / Vous avez trouvé un problème ? error.needHelp=Besoin daide / Vous avez trouvé un problème ?
error.contactTip=Si vous avez encore des problèmes, nhésitez pas à nous contacter pour obtenir de laide. Vous pouvez soumettre un ticket sur notre page GitHub ou nous contacter via Discord : error.contactTip=Si vous avez encore des problèmes, nhésitez pas à nous contacter pour obtenir de laide. Vous pouvez soumettre un ticket sur notre page GitHub ou nous contacter via Discord :

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=उपयोगकर्ता प्रमाणित
userNotFoundMessage=उपयोगकर्ता नहीं मिला। userNotFoundMessage=उपयोगकर्ता नहीं मिला।
incorrectPasswordMessage=वर्तमान पासवर्ड गलत है। incorrectPasswordMessage=वर्तमान पासवर्ड गलत है।
usernameExistsMessage=नया उपयोगकर्ता नाम पहले से मौजूद है। usernameExistsMessage=नया उपयोगकर्ता नाम पहले से मौजूद है।
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers. invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=मौजूदा यूज़र की भूमिका को डाउनग्रेड नहीं किया जा सकता
downgradeCurrentUserLongMessage=मौजूदा यूज़र की भूमिका को डाउनग्रेड नहीं किया जा सकता। इसलिए, वर्तमान उपयोगकर्ता को नहीं दिखाया जाएगा।
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=Error error=Error
oops=Oops! oops=Oops!
help=Help help=Help
@@ -67,6 +71,7 @@ visitGithub=Visit Github Repository
donate=Donate donate=Donate
color=Color color=Color
sponsor=Sponsor sponsor=Sponsor
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=Validate
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=कनवर्ट navbar.favorite=Favorites
navbar.security=सुरक्षा
navbar.other=विविध
navbar.darkmode=डार्क मोड navbar.darkmode=डार्क मोड
navbar.pageOps=पेज कार्य navbar.language=Languages
navbar.settings=सेटिंग्स navbar.settings=सेटिंग्स
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=व्यवस्थापक उपयोगकर्
adminUserSettings.admin=व्यवस्थापक adminUserSettings.admin=व्यवस्थापक
adminUserSettings.user=उपयोगकर्ता adminUserSettings.user=उपयोगकर्ता
adminUserSettings.addUser=नया उपयोगकर्ता जोड़ें adminUserSettings.addUser=नया उपयोगकर्ता जोड़ें
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters. adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=रोल्स adminUserSettings.roles=रोल्स
adminUserSettings.role=रोल adminUserSettings.role=रोल
adminUserSettings.actions=क्रियाएँ adminUserSettings.actions=क्रियाएँ
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Demo User (No custom settings)
adminUserSettings.internalApiUser=Internal API User adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=उपयोगकर्ता को लॉगिन पर उपयोगकर्ता नाम/पासवर्ड बदलने के लिए मजबूर करें adminUserSettings.forceChange=उपयोगकर्ता को लॉगिन पर उपयोगकर्ता नाम/पासवर्ड बदलने के लिए मजबूर करें
adminUserSettings.submit=उपयोगकर्ता को सहेजें adminUserSettings.submit=उपयोगकर्ता को सहेजें
adminUserSettings.changeUserRole=यूज़र की भूमिका बदलें
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=मुझे याद रखें
login.invalid=अमान्य उपयोगकर्ता नाम या पासवर्ड। login.invalid=अमान्य उपयोगकर्ता नाम या पासवर्ड।
login.locked=आपका खाता लॉक कर दिया गया है। login.locked=आपका खाता लॉक कर दिया गया है।
login.signinTitle=कृपया साइन इन करें login.signinTitle=कृपया साइन इन करें
login.ssoSignIn=सिंगल साइन - ऑन के ज़रिए लॉग इन करें
login.oauth2AutoCreateDisabled=OAUTH2 ऑटो - क्रिएट यूज़र अक्षम किया गया
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=मरम्मत
#flatten #flatten
flatten.title=समतल करें flatten.title=समतल करें
flatten.header=पीडीएफ़ समतल करें flatten.header=पीडीएफ़ समतल करें
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=समतल करें flatten.submit=समतल करें
@@ -736,6 +752,7 @@ extractImages.submit=निकालें
fileToPDF.title=फ़ाइल से पीडीएफ़ fileToPDF.title=फ़ाइल से पीडीएफ़
fileToPDF.header=किसी भी फ़ाइल को पीडीएफ़ में बदलें fileToPDF.header=किसी भी फ़ाइल को पीडीएफ़ में बदलें
fileToPDF.credit=यह सेवा फ़ाइल परिवर्तन के लिए LibreOffice और Unoconv का उपयोग करती है। fileToPDF.credit=यह सेवा फ़ाइल परिवर्तन के लिए LibreOffice और Unoconv का उपयोग करती है।
fileToPDF.supportedFileTypesInfo=Supported File types
fileToPDF.supportedFileTypes=समर्थित फ़ाइल प्रकार नीचे दिए गए होने चाहिए हालांकि समर्थित प्रारूपों की पूरी अद्यतन सूची के लिए कृपया LibreOffice दस्तावेज़ीकरण से संदर्भित करें fileToPDF.supportedFileTypes=समर्थित फ़ाइल प्रकार नीचे दिए गए होने चाहिए हालांकि समर्थित प्रारूपों की पूरी अद्यतन सूची के लिए कृपया LibreOffice दस्तावेज़ीकरण से संदर्भित करें
fileToPDF.submit=पीडीएफ़ में बदलें fileToPDF.submit=पीडीएफ़ में बदलें
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool #multiTool
multiTool.title=पीडीएफ मल्टी टूल multiTool.title=पीडीएफ मल्टी टूल
multiTool.header=पीडीएफ मल्टी टूल multiTool.header=पीडीएफ मल्टी टूल
multiTool.uploadPrompts=Please Upload PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=पीडीएफ देखें viewPdf.title=पीडीएफ देखें
@@ -941,6 +958,7 @@ pdfToPDFA.header=PDF से PDF/A में
pdfToPDFA.credit=इस सेवा में PDF/A परिवर्तन के लिए OCRmyPDF का उपयोग किया जाता है। pdfToPDFA.credit=इस सेवा में PDF/A परिवर्तन के लिए OCRmyPDF का उपयोग किया जाता है।
pdfToPDFA.submit=परिवर्तित करें pdfToPDFA.submit=परिवर्तित करें
pdfToPDFA.tip=Currently does not work for multiple inputs at once pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Version
licenses.license=License licenses.license=License
# error #error
error.sorry=Sorry for the issue! error.sorry=Sorry for the issue!
error.needHelp=Need help / Found an issue? error.needHelp=Need help / Found an issue?
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=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:

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=Felhasználó nincs hitelesítve.
userNotFoundMessage=A felhasználó nem található. userNotFoundMessage=A felhasználó nem található.
incorrectPasswordMessage=A jelenlegi jelszó helytelen. incorrectPasswordMessage=A jelenlegi jelszó helytelen.
usernameExistsMessage=Az új felhasználónév már létezik. usernameExistsMessage=Az új felhasználónév már létezik.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers. invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=A jelenlegi felhasználó szerepkörét nem lehet visszaminősíteni
downgradeCurrentUserLongMessage=Az aktuális felhasználó szerepkörét nem lehet visszaminősíteni. Ezért az aktuális felhasználó nem jelenik meg.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=Error error=Error
oops=Oops! oops=Oops!
help=Help help=Help
@@ -67,6 +71,7 @@ visitGithub=Visit Github Repository
donate=Donate donate=Donate
color=Color color=Color
sponsor=Sponsor sponsor=Sponsor
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=Validate
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=Átalakítás navbar.favorite=Favorites
navbar.security=Biztonság
navbar.other=Egyéb
navbar.darkmode=Sötét mód navbar.darkmode=Sötét mód
navbar.pageOps=Lap műveletek navbar.language=Languages
navbar.settings=Beállítások navbar.settings=Beállítások
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=Adminisztrátori Felhasználói Vezérlési Beállítá
adminUserSettings.admin=Adminisztrátor adminUserSettings.admin=Adminisztrátor
adminUserSettings.user=Felhasználó adminUserSettings.user=Felhasználó
adminUserSettings.addUser=Új felhasználó hozzáadása adminUserSettings.addUser=Új felhasználó hozzáadása
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters. adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Szerepek adminUserSettings.roles=Szerepek
adminUserSettings.role=Szerep adminUserSettings.role=Szerep
adminUserSettings.actions=Műveletek adminUserSettings.actions=Műveletek
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Demo User (No custom settings)
adminUserSettings.internalApiUser=Internal API User adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Kényszerítse a felhasználót a felhasználónév/jelszó megváltoztatására bejelentkezéskor adminUserSettings.forceChange=Kényszerítse a felhasználót a felhasználónév/jelszó megváltoztatására bejelentkezéskor
adminUserSettings.submit=Felhasználó mentése adminUserSettings.submit=Felhasználó mentése
adminUserSettings.changeUserRole=Felhasználó szerepkörének módosítása
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=Emlékezz rám
login.invalid=Érvénytelen felhasználónév vagy jelszó! login.invalid=Érvénytelen felhasználónév vagy jelszó!
login.locked=A fiókja zárolva lett! login.locked=A fiókja zárolva lett!
login.signinTitle=Kérjük, jelentkezzen be! login.signinTitle=Kérjük, jelentkezzen be!
login.ssoSignIn=Bejelentkezés egyszeri bejelentkezéssel
login.oauth2AutoCreateDisabled=OAUTH2 Felhasználó automatikus létrehozása letiltva
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=Javítás
#flatten #flatten
flatten.title=Kiegyenlítés flatten.title=Kiegyenlítés
flatten.header=PDF-ek kiegyenlítése flatten.header=PDF-ek kiegyenlítése
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Kiegyenlítés flatten.submit=Kiegyenlítés
@@ -736,6 +752,7 @@ extractImages.submit=Kinyerés
fileToPDF.title=Fájl PDF dokumentummá alakítása fileToPDF.title=Fájl PDF dokumentummá alakítása
fileToPDF.header=Konvertáljon bármilyen fájlt PDF dokumentummá fileToPDF.header=Konvertáljon bármilyen fájlt PDF dokumentummá
fileToPDF.credit=Ez a szolgáltatás a LibreOffice-t és az Unoconv-ot használja a fájlkonverzióhoz. fileToPDF.credit=Ez a szolgáltatás a LibreOffice-t és az Unoconv-ot használja a fájlkonverzióhoz.
fileToPDF.supportedFileTypesInfo=Supported File types
fileToPDF.supportedFileTypes=A funkció az alábbi fájltípusokat támogatja, azonban a teljesen friss támogatott formátumok listájáért kérjük, tekintse meg a LibreOffice dokumentációját fileToPDF.supportedFileTypes=A funkció az alábbi fájltípusokat támogatja, azonban a teljesen friss támogatott formátumok listájáért kérjük, tekintse meg a LibreOffice dokumentációját
fileToPDF.submit=Konvertálás PDF dokumentummá fileToPDF.submit=Konvertálás PDF dokumentummá
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool #multiTool
multiTool.title=PDF többfunkciós eszköz multiTool.title=PDF többfunkciós eszköz
multiTool.header=PDF többfunkciós eszköz multiTool.header=PDF többfunkciós eszköz
multiTool.uploadPrompts=Please Upload PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=PDF megtekintése viewPdf.title=PDF megtekintése
@@ -941,6 +958,7 @@ pdfToPDFA.header=PDF >> PDF/A
pdfToPDFA.credit=Ez a szolgáltatás az OCRmyPDF-t használja a PDF/A konverzióhoz pdfToPDFA.credit=Ez a szolgáltatás az OCRmyPDF-t használja a PDF/A konverzióhoz
pdfToPDFA.submit=Konvertálás pdfToPDFA.submit=Konvertálás
pdfToPDFA.tip=Currently does not work for multiple inputs at once pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Version
licenses.license=License licenses.license=License
# error #error
error.sorry=Sorry for the issue! error.sorry=Sorry for the issue!
error.needHelp=Need help / Found an issue? error.needHelp=Need help / Found an issue?
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=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:

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=Pengguna tidak ter-autentikasi.
userNotFoundMessage=Pengguna tidak ditemukan. userNotFoundMessage=Pengguna tidak ditemukan.
incorrectPasswordMessage=Kata sandi saat ini salah. incorrectPasswordMessage=Kata sandi saat ini salah.
usernameExistsMessage=Nama pengguna baru sudah ada. usernameExistsMessage=Nama pengguna baru sudah ada.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers. invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Tidak dapat menurunkan peran pengguna saat ini
downgradeCurrentUserLongMessage=Tidak dapat menurunkan peran pengguna saat ini. Oleh karena itu, pengguna saat ini tidak akan ditampilkan.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=Error error=Error
oops=Oops! oops=Oops!
help=Help help=Help
@@ -67,6 +71,7 @@ visitGithub=Visit Github Repository
donate=Donate donate=Donate
color=Color color=Color
sponsor=Sponsor sponsor=Sponsor
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=Validate
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=Konversi navbar.favorite=Favorites
navbar.security=Keamanan
navbar.other=Lain-lain
navbar.darkmode=Mode Gelap navbar.darkmode=Mode Gelap
navbar.pageOps=Operasi Halaman navbar.language=Languages
navbar.settings=Pengaturan navbar.settings=Pengaturan
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=Pengaturan Kontrol Admin
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=Pengguna adminUserSettings.user=Pengguna
adminUserSettings.addUser=Tambahkan Pengguna Baru adminUserSettings.addUser=Tambahkan Pengguna Baru
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters. adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Peran adminUserSettings.roles=Peran
adminUserSettings.role=Peran adminUserSettings.role=Peran
adminUserSettings.actions=Tindakan adminUserSettings.actions=Tindakan
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Demo User (No custom settings)
adminUserSettings.internalApiUser=Internal API User adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Memaksa pengguna untuk mengubah nama pengguna/kata sandi saat masuk adminUserSettings.forceChange=Memaksa pengguna untuk mengubah nama pengguna/kata sandi saat masuk
adminUserSettings.submit=Simpan Pengguna adminUserSettings.submit=Simpan Pengguna
adminUserSettings.changeUserRole=Ubah Peran Pengguna
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=Ingat saya
login.invalid=Nama pengguna atau kata sandi tidak valid. login.invalid=Nama pengguna atau kata sandi tidak valid.
login.locked=Akun Anda telah dikunci. login.locked=Akun Anda telah dikunci.
login.signinTitle=Silakan masuk login.signinTitle=Silakan masuk
login.ssoSignIn=Masuk melalui Single Sign - on
login.oauth2AutoCreateDisabled=OAUTH2 Buat Otomatis Pengguna Dinonaktifkan
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=Perbaiki
#flatten #flatten
flatten.title=Ratakan flatten.title=Ratakan
flatten.header=Ratakan PDF flatten.header=Ratakan PDF
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Ratakan flatten.submit=Ratakan
@@ -736,6 +752,7 @@ extractImages.submit=Ekstrak
fileToPDF.title=Berkas ke PDF fileToPDF.title=Berkas ke PDF
fileToPDF.header=Mengonversi berkas apa pun ke PDF fileToPDF.header=Mengonversi berkas apa pun ke PDF
fileToPDF.credit=Layanan ini menggunakan LibreOffice dan Unoconv untuk konversi berkas. fileToPDF.credit=Layanan ini menggunakan LibreOffice dan Unoconv untuk konversi berkas.
fileToPDF.supportedFileTypesInfo=Supported File types
fileToPDF.supportedFileTypes=Jenis berkas yang didukung harus mencakup yang di bawah ini, namun untuk daftar lengkap format yang didukung, silakan lihat dokumentasi LibreOffice fileToPDF.supportedFileTypes=Jenis berkas yang didukung harus mencakup yang di bawah ini, namun untuk daftar lengkap format yang didukung, silakan lihat dokumentasi LibreOffice
fileToPDF.submit=Konversi ke PDF fileToPDF.submit=Konversi ke PDF
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool #multiTool
multiTool.title=Alat Multi PDF multiTool.title=Alat Multi PDF
multiTool.header=Alat Multi PDF multiTool.header=Alat Multi PDF
multiTool.uploadPrompts=Please Upload PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=Lihat PDF viewPdf.title=Lihat PDF
@@ -941,6 +958,7 @@ pdfToPDFA.header=PDF ke PDF/A
pdfToPDFA.credit=Layanan ini menggunakan OCRmyPDF untuk konversi PDF/A. pdfToPDFA.credit=Layanan ini menggunakan OCRmyPDF untuk konversi PDF/A.
pdfToPDFA.submit=Konversi pdfToPDFA.submit=Konversi
pdfToPDFA.tip=Currently does not work for multiple inputs at once pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Version
licenses.license=License licenses.license=License
# error #error
error.sorry=Sorry for the issue! error.sorry=Sorry for the issue!
error.needHelp=Need help / Found an issue? error.needHelp=Need help / Found an issue?
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=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:

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=Utente non autenticato.
userNotFoundMessage=Utente non trovato. userNotFoundMessage=Utente non trovato.
incorrectPasswordMessage=La password attuale non è corretta. incorrectPasswordMessage=La password attuale non è corretta.
usernameExistsMessage=Il nuovo nome utente esiste già. usernameExistsMessage=Il nuovo nome utente esiste già.
invalidUsernameMessage=Nome utente non valido, il nome utente deve contenere solo caratteri alfabetici e numeri. invalidUsernameMessage=Nome utente non valido, il nome utente può contenere solo lettere, numeri e i seguenti caratteri speciali @._+- o deve essere un indirizzo email valido.
deleteCurrentUserMessage=Impossibile eliminare l'utente attualmente connesso. deleteCurrentUserMessage=Impossibile eliminare l'utente attualmente connesso.
deleteUsernameExistsMessage=Il nome utente non esiste e non può essere eliminato. deleteUsernameExistsMessage=Il nome utente non esiste e non può essere eliminato.
downgradeCurrentUserMessage=Impossibile declassare il ruolo dell'utente corrente
downgradeCurrentUserLongMessage=Impossibile declassare il ruolo dell'utente corrente. Pertanto, l'utente corrente non verrà visualizzato.
userAlreadyExistsOAuthMessage=L'utente esiste già come utente OAuth2.
userAlreadyExistsWebMessage=L'utente esiste già come utente web.
error=Errore error=Errore
oops=Oops! oops=Oops!
help=Aiuto help=Aiuto
@@ -67,6 +71,7 @@ visitGithub=Visita il repository Github
donate=Donazione donate=Donazione
color=Colore color=Colore
sponsor=Sponsor sponsor=Sponsor
info=Info
@@ -100,19 +105,25 @@ pipelineOptions.validateButton=Convalidare
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=Converti navbar.favorite=Preferiti
navbar.security=Sicurezza
navbar.other=Altro
navbar.darkmode=Modalità Scura navbar.darkmode=Modalità Scura
navbar.pageOps=Modifica pagine navbar.language=Lingue
navbar.settings=Impostazioni navbar.settings=Impostazioni
navbar.allTools=Strumenti
navbar.multiTool=Strumenti multipli
navbar.sections.organize=Organizza
navbar.sections.convertTo=Converti in PDF
navbar.sections.convertFrom=Converti da PDF
navbar.sections.security=Firma Firma & Sicurezza
navbar.sections.advance=Avanzate
navbar.sections.edit=Visualizza & Modifica
############# #############
# SETTINGS # # SETTINGS #
############# #############
settings.title=Impostazioni settings.title=Impostazioni
settings.update=Aggiornamento disponibile settings.update=Aggiornamento disponibile
settings.updateAvailable={0} is the current installed version. A new version ({1}) is available. settings.updateAvailable={0} è la versione attualmente installata. Una nuova versione ({1}) è disponibile.
settings.appVersion=Versione App: settings.appVersion=Versione App:
settings.downloadOption.title=Scegli opzione di download (Per file singoli non compressi): settings.downloadOption.title=Scegli opzione di download (Per file singoli non compressi):
settings.downloadOption.1=Apri in questa finestra settings.downloadOption.1=Apri in questa finestra
@@ -162,7 +173,7 @@ adminUserSettings.header=Impostazioni di controllo utente amministratore
adminUserSettings.admin=Amministratore adminUserSettings.admin=Amministratore
adminUserSettings.user=Utente adminUserSettings.user=Utente
adminUserSettings.addUser=Aggiungi un nuovo Utente adminUserSettings.addUser=Aggiungi un nuovo Utente
adminUserSettings.usernameInfo=Il nome utente deve contenere solo lettere e numeri, senza spazi o caratteri speciali. adminUserSettings.usernameInfo=Il nome utente può contenere solo lettere, numeri e i seguenti caratteri speciali @._+- oppure deve essere un indirizzo email valido.
adminUserSettings.roles=Ruoli adminUserSettings.roles=Ruoli
adminUserSettings.role=Ruolo adminUserSettings.role=Ruolo
adminUserSettings.actions=Azioni adminUserSettings.actions=Azioni
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Utente demo (nessuna impostazione personalizzata)
adminUserSettings.internalApiUser=API utente interna adminUserSettings.internalApiUser=API utente interna
adminUserSettings.forceChange=Forza l'utente a cambiare nome username/password all'accesso adminUserSettings.forceChange=Forza l'utente a cambiare nome username/password all'accesso
adminUserSettings.submit=Salva utente adminUserSettings.submit=Salva utente
adminUserSettings.changeUserRole=Cambia il ruolo dell'utente
adminUserSettings.authenticated=Autenticato
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=Ricordami
login.invalid=Nome utente o password errati. login.invalid=Nome utente o password errati.
login.locked=Il tuo account è stato bloccato. login.locked=Il tuo account è stato bloccato.
login.signinTitle=Per favore accedi login.signinTitle=Per favore accedi
login.ssoSignIn=Accedi tramite Single Sign-on
login.oauth2AutoCreateDisabled=Creazione automatica utente OAUTH2 DISABILITATA
#auto-redact #auto-redact
@@ -646,7 +661,7 @@ removeBlanks.submit=Rimuovi
#removeAnnotations #removeAnnotations
removeAnnotations.title=Rimuovi Annotazioni removeAnnotations.title=Rimuovi Annotazioni
removeAnnotations.header=Remuovi Annotazioni removeAnnotations.header=Rimuovi Annotazioni
removeAnnotations.submit=Rimuovi removeAnnotations.submit=Rimuovi
@@ -687,8 +702,9 @@ repair.submit=Ripara
#flatten #flatten
flatten.title=Appiattisci flatten.title=Appiattire
flatten.header=Appiattisci PDF flatten.header=Appiattisci PDF
flatten.flattenOnlyForms=Appiattisci solo i moduli
flatten.submit=Appiattisci flatten.submit=Appiattisci
@@ -736,6 +752,7 @@ extractImages.submit=Estrai
fileToPDF.title=Converti file in PDF fileToPDF.title=Converti file in PDF
fileToPDF.header=Converti qualsiasi file in PDF fileToPDF.header=Converti qualsiasi file in PDF
fileToPDF.credit=Questo servizio utilizza LibreOffice e Unoconv per la conversione dei file. fileToPDF.credit=Questo servizio utilizza LibreOffice e Unoconv per la conversione dei file.
fileToPDF.supportedFileTypesInfo=Tipi di file supportati
fileToPDF.supportedFileTypes=I formati file supportati dovrebbero includere quelli sottostanti. Tuttavia, per una lista aggiornata controlla la documentazione di LibreOffice fileToPDF.supportedFileTypes=I formati file supportati dovrebbero includere quelli sottostanti. Tuttavia, per una lista aggiornata controlla la documentazione di LibreOffice
fileToPDF.submit=Converti in PDF fileToPDF.submit=Converti in PDF
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(ad es. 1,3,2 o 4-8,2,10-12 o 2n-1)
#multiTool #multiTool
multiTool.title=Multifunzione PDF multiTool.title=Multifunzione PDF
multiTool.header=Multifunzione PDF multiTool.header=Multifunzione PDF
multiTool.uploadPrompts=Caricare il PDF multiTool.uploadPrompts=Nome file
#view pdf #view pdf
viewPdf.title=Visualizza PDF viewPdf.title=Visualizza PDF
@@ -941,6 +958,7 @@ pdfToPDFA.header=Da PDF a PDF/A
pdfToPDFA.credit=Questo servizio utilizza OCRmyPDF per la conversione in PDF/A. pdfToPDFA.credit=Questo servizio utilizza OCRmyPDF per la conversione in PDF/A.
pdfToPDFA.submit=Converti pdfToPDFA.submit=Converti
pdfToPDFA.tip=Attualmente non funziona per più input contemporaneamente pdfToPDFA.tip=Attualmente non funziona per più input contemporaneamente
pdfToPDFA.outputFormat=Formato di output
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Versione
licenses.license=Licenza licenses.license=Licenza
# error #error
error.sorry=Ci scusiamo per il problema! error.sorry=Ci scusiamo per il problema!
error.needHelp=Hai bisogno di aiuto / trovato un problema? error.needHelp=Hai bisogno di aiuto / trovato un problema?
error.contactTip=Se i problemi persistono, non esitare a contattarci per chiedere aiuto. Puoi inviare un ticket sulla nostra pagina GitHub o contattarci tramite Discord: error.contactTip=Se i problemi persistono, non esitare a contattarci per chiedere aiuto. Puoi inviare un ticket sulla nostra pagina GitHub o contattarci tramite Discord:

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=ユーザーが認証されていません。
userNotFoundMessage=ユーザーが見つかりません。 userNotFoundMessage=ユーザーが見つかりません。
incorrectPasswordMessage=現在のパスワードが正しくありません。 incorrectPasswordMessage=現在のパスワードが正しくありません。
usernameExistsMessage=新しいユーザー名はすでに存在します。 usernameExistsMessage=新しいユーザー名はすでに存在します。
invalidUsernameMessage=ユーザー名が無効です。ユーザー名にはアルファベットと数字のみを使用してください invalidUsernameMessage=ユーザー名が無効です。ユーザー名には文字、数字、およびそれに続く特殊文字 @._+- のみを含めることができます。または、有効な電子メール アドレスである必要があります
deleteCurrentUserMessage=現在ログインしているユーザーは削除できません。 deleteCurrentUserMessage=現在ログインしているユーザーは削除できません。
deleteUsernameExistsMessage=そのユーザー名は存在しないため削除できません。 deleteUsernameExistsMessage=そのユーザー名は存在しないため削除できません。
downgradeCurrentUserMessage=現在のユーザーの役割をダウングレードできません
downgradeCurrentUserLongMessage=現在のユーザーの役割をダウングレードできません。したがって、現在のユーザーは表示されません。
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=エラー error=エラー
oops=おっと! oops=おっと!
help=ヘルプ help=ヘルプ
@@ -67,6 +71,7 @@ visitGithub=Githubリポジトリを訪問する
donate=寄付する donate=寄付する
color= color=
sponsor=スポンサー sponsor=スポンサー
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=検証
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=変換 navbar.favorite=Favorites
navbar.security=セキュリティ
navbar.other=その他
navbar.darkmode=ダークモード navbar.darkmode=ダークモード
navbar.pageOps=ページ操作 navbar.language=Languages
navbar.settings=設定 navbar.settings=設定
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=管理者ユーザー制御設定
adminUserSettings.admin=管理者 adminUserSettings.admin=管理者
adminUserSettings.user=ユーザー adminUserSettings.user=ユーザー
adminUserSettings.addUser=新しいユーザを追加 adminUserSettings.addUser=新しいユーザを追加
adminUserSettings.usernameInfo=ユーザー名には文字数字のみが使用でき、スペースや特殊文字は使用できません adminUserSettings.usernameInfo=ユーザー名には文字数字、および次の特殊文字 @._+- のみを含めることができます。または、有効な電子メール アドレスである必要があります
adminUserSettings.roles=役割 adminUserSettings.roles=役割
adminUserSettings.role=役割 adminUserSettings.role=役割
adminUserSettings.actions=アクション adminUserSettings.actions=アクション
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=デモユーザー (カスタム設定なし)
adminUserSettings.internalApiUser=内部APIユーザー adminUserSettings.internalApiUser=内部APIユーザー
adminUserSettings.forceChange=ログイン時にユーザー名/パスワードを強制的に変更する adminUserSettings.forceChange=ログイン時にユーザー名/パスワードを強制的に変更する
adminUserSettings.submit=ユーザーの保存 adminUserSettings.submit=ユーザーの保存
adminUserSettings.changeUserRole=ユーザーの役割を変更する
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=サインイン状態を記憶する
login.invalid=ユーザー名かパスワードが無効です。 login.invalid=ユーザー名かパスワードが無効です。
login.locked=あなたのアカウントはロックされています。 login.locked=あなたのアカウントはロックされています。
login.signinTitle=サインインしてください login.signinTitle=サインインしてください
login.ssoSignIn=シングルサインオンでログイン
login.oauth2AutoCreateDisabled=OAuth 2自動作成ユーザーが無効
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=修復
#flatten #flatten
flatten.title=平坦化 flatten.title=平坦化
flatten.header=PDFを平坦化する flatten.header=PDFを平坦化する
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=平坦化 flatten.submit=平坦化
@@ -736,6 +752,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.supportedFileTypes=サポートされるファイル形式には以下が含まれますが、完全な更新リストについてはLibreOfficeのドキュメントを参照してください。 fileToPDF.supportedFileTypes=サポートされるファイル形式には以下が含まれますが、完全な更新リストについてはLibreOfficeのドキュメントを参照してください。
fileToPDF.submit=PDFを変換 fileToPDF.submit=PDFを変換
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(例:1,3,2または4-8,2,10-12または2n-1)
#multiTool #multiTool
multiTool.title=PDFマルチツール multiTool.title=PDFマルチツール
multiTool.header=PDFマルチツール multiTool.header=PDFマルチツール
multiTool.uploadPrompts=Please Upload PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=PDFを表示 viewPdf.title=PDFを表示
@@ -941,6 +958,7 @@ pdfToPDFA.header=PDFをPDF/Aに変換
pdfToPDFA.credit=本サービスはPDF/Aの変換にOCRmyPDFを使用しています。 pdfToPDFA.credit=本サービスはPDF/Aの変換にOCRmyPDFを使用しています。
pdfToPDFA.submit=変換 pdfToPDFA.submit=変換
pdfToPDFA.tip=現在、一度に複数の入力に対して機能しません pdfToPDFA.tip=現在、一度に複数の入力に対して機能しません
pdfToPDFA.outputFormat=Output format
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=バージョン
licenses.license=ライセンス licenses.license=ライセンス
# error #error
error.sorry=問題が発生したことをお詫び申し上げます! error.sorry=問題が発生したことをお詫び申し上げます!
error.needHelp=助けが必要/問題が見つかりましたか? error.needHelp=助けが必要/問題が見つかりましたか?
error.contactTip=まだ問題が解決していない場合は、お手数ですが、GitHubページでチケットを提出するか、Discordで私たちに連絡してください error.contactTip=まだ問題が解決していない場合は、お手数ですが、GitHubページでチケットを提出するか、Discordで私たちに連絡してください

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=사용자가 인증되지 않았습니다.
userNotFoundMessage=사용자를 찾을 수 없습니다. userNotFoundMessage=사용자를 찾을 수 없습니다.
incorrectPasswordMessage=현재 비밀번호가 틀립니다. incorrectPasswordMessage=현재 비밀번호가 틀립니다.
usernameExistsMessage=새 사용자명이 이미 존재합니다. usernameExistsMessage=새 사용자명이 이미 존재합니다.
invalidUsernameMessage=사용자 이름이 잘못되었습니다. 사용자 이름에는 알파벳 문자 숫자만 포함되어야 합니다. invalidUsernameMessage=잘못된 사용자 이름니다. 사용자 이름에는 문자, 숫자 및 다음 특수 문자(@._+-)만 포함할 수 있거나 유효한 이메일 주소여야 합니다.
deleteCurrentUserMessage=현재 로그인한 사용자를 삭제할 수 없습니다. deleteCurrentUserMessage=현재 로그인한 사용자를 삭제할 수 없습니다.
deleteUsernameExistsMessage=사용자 이름이 존재하지 않으며 삭제할 수 없습니다. deleteUsernameExistsMessage=사용자 이름이 존재하지 않으며 삭제할 수 없습니다.
downgradeCurrentUserMessage=현재 사용자의 역할을 다운그레이드할 수 없습니다
downgradeCurrentUserLongMessage=현재 사용자의 역할을 다운그레이드할 수 없습니다. 따라서 현재 사용자는 표시되지 않습니다.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=오류 error=오류
oops=어머나! oops=어머나!
help=도움말 help=도움말
@@ -67,6 +71,7 @@ visitGithub=GitHub 저장소 방문하기
donate=기부하기 donate=기부하기
color=색상 color=색상
sponsor=스폰서 sponsor=스폰서
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=확인
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=변환 navbar.favorite=Favorites
navbar.security=보안
navbar.other=기타
navbar.darkmode=다크 모드 navbar.darkmode=다크 모드
navbar.pageOps=페이지 편집 navbar.language=Languages
navbar.settings=설정 navbar.settings=설정
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=사용자 관리
adminUserSettings.admin=관리자 adminUserSettings.admin=관리자
adminUserSettings.user=사용자 adminUserSettings.user=사용자
adminUserSettings.addUser=새 사용자 추가 adminUserSettings.addUser=새 사용자 추가
adminUserSettings.usernameInfo=사용자 이름은 문자 숫자만 포함해야 하며 공백이나 특수 문자는 포함할 수 없습니다. adminUserSettings.usernameInfo=사용자 이름은 문자, 숫자, 특수 문자 @._+-만 포함할 수 있으며 유효한 이메일 주소여야 합니다.
adminUserSettings.roles=역할 adminUserSettings.roles=역할
adminUserSettings.role=역할 adminUserSettings.role=역할
adminUserSettings.actions=동작 adminUserSettings.actions=동작
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=데모 사용자(사용자 지정 설정 없음)
adminUserSettings.internalApiUser=내부 API 사용자 adminUserSettings.internalApiUser=내부 API 사용자
adminUserSettings.forceChange=다음 로그인 때 사용자명과 비밀번호를 변경하도록 강제 adminUserSettings.forceChange=다음 로그인 때 사용자명과 비밀번호를 변경하도록 강제
adminUserSettings.submit=사용자 저장 adminUserSettings.submit=사용자 저장
adminUserSettings.changeUserRole=사용자의 역할 변경
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=로그인 유지
login.invalid=사용자 이름이나 비밀번호가 틀립니다. login.invalid=사용자 이름이나 비밀번호가 틀립니다.
login.locked=계정이 잠겼습니다. login.locked=계정이 잠겼습니다.
login.signinTitle=로그인해 주세요. login.signinTitle=로그인해 주세요.
login.ssoSignIn=싱글사인온을 통한 로그인
login.oauth2AutoCreateDisabled=OAUTH2 사용자 자동 생성 비활성화됨
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=복구
#flatten #flatten
flatten.title=평탄화 flatten.title=평탄화
flatten.header=PDF 문서의 레이어 평탄화 flatten.header=PDF 문서의 레이어 평탄화
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=평탄화 flatten.submit=평탄화
@@ -736,6 +752,7 @@ extractImages.submit=추출
fileToPDF.title=File to PDF fileToPDF.title=File to PDF
fileToPDF.header=다양한 파일을 PDF로 변환 fileToPDF.header=다양한 파일을 PDF로 변환
fileToPDF.credit=이 서비스는 파일 변환에 LibreOffice와 Unoconv를 사용합니다. fileToPDF.credit=이 서비스는 파일 변환에 LibreOffice와 Unoconv를 사용합니다.
fileToPDF.supportedFileTypesInfo=Supported File types
fileToPDF.supportedFileTypes=지원되는 파일 형식은 아래와 같습니다. 지원되는 형식의 전체 업데이트 목록은 LibreOffice 설명서를 참조합니다. fileToPDF.supportedFileTypes=지원되는 파일 형식은 아래와 같습니다. 지원되는 형식의 전체 업데이트 목록은 LibreOffice 설명서를 참조합니다.
fileToPDF.submit=PDF로 변환 fileToPDF.submit=PDF로 변환
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(예: 1,3,2 또는 4-8,2,10-12 또는 2n-1)
#multiTool #multiTool
multiTool.title=PDF 멀티툴 multiTool.title=PDF 멀티툴
multiTool.header=PDF 멀티툴 multiTool.header=PDF 멀티툴
multiTool.uploadPrompts=PDF를 업로드하십시오 multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=PDF 뷰어 viewPdf.title=PDF 뷰어
@@ -941,6 +958,7 @@ pdfToPDFA.header=PDF 문서를 PDF/A로 변환
pdfToPDFA.credit=이 서비스는 PDF/A 변환을 위해 OCRmyPDF 문서를 사용합니다. pdfToPDFA.credit=이 서비스는 PDF/A 변환을 위해 OCRmyPDF 문서를 사용합니다.
pdfToPDFA.submit=변환 pdfToPDFA.submit=변환
pdfToPDFA.tip=현재 한 번에 여러 입력에 대해 작동하지 않습니다. pdfToPDFA.tip=현재 한 번에 여러 입력에 대해 작동하지 않습니다.
pdfToPDFA.outputFormat=Output format
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=버전
licenses.license=라이센스 licenses.license=라이센스
# error #error
error.sorry=문제를 끼친 점 죄송합니다! error.sorry=문제를 끼친 점 죄송합니다!
error.needHelp=도움이 필요하신가요 / 문제가 있으신가요? error.needHelp=도움이 필요하신가요 / 문제가 있으신가요?
error.contactTip=여전히 문제가 해결되지 않는다면 망설이지 마시고 도움을 요청하십시오. GitHub 페이지에서 티켓을 제출하거나 Discord를 통해 우리에게 연락하실 수 있습니다: error.contactTip=여전히 문제가 해결되지 않는다면 망설이지 마시고 도움을 요청하십시오. GitHub 페이지에서 티켓을 제출하거나 Discord를 통해 우리에게 연락하실 수 있습니다:

View File

@@ -54,9 +54,13 @@ 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 must only contain alphabet characters and numbers. invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
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.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=Error error=Error
oops=Oops! oops=Oops!
help=Help help=Help
@@ -67,6 +71,7 @@ visitGithub=Visit Github Repository
donate=Donate donate=Donate
color=Color color=Color
sponsor=Sponsor sponsor=Sponsor
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=Valideren
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=Converteren navbar.favorite=Favorites
navbar.security=Beveiliging
navbar.other=Overige
navbar.darkmode=Donkere modus navbar.darkmode=Donkere modus
navbar.pageOps=Pagina bewerkingen navbar.language=Languages
navbar.settings=Instellingen navbar.settings=Instellingen
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ 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.usernameInfo=Username must only contain letters and numbers, no spaces or special characters. adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Rollen adminUserSettings.roles=Rollen
adminUserSettings.role=Rol adminUserSettings.role=Rol
adminUserSettings.actions=Acties adminUserSettings.actions=Acties
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Demogebruiker (geen aangepaste instellingen)
adminUserSettings.internalApiUser=Internal API User adminUserSettings.internalApiUser=Internal API User
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.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=Onthoud mij
login.invalid=Ongeldige gebruikersnaam of wachtwoord. login.invalid=Ongeldige gebruikersnaam of wachtwoord.
login.locked=Je account is geblokkeerd. 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.oauth2AutoCreateDisabled=OAUTH2 Automatisch aanmaken gebruiker uitgeschakeld
#auto-redact #auto-redact
@@ -689,6 +704,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.submit=Afvlakken flatten.submit=Afvlakken
@@ -736,6 +752,7 @@ extractImages.submit=Extraheer
fileToPDF.title=Bestand naar PDF fileToPDF.title=Bestand naar PDF
fileToPDF.header=Zet elk bestand om naar PDF fileToPDF.header=Zet elk bestand om naar PDF
fileToPDF.credit=Deze service gebruikt LibreOffice en Unoconv voor bestandsconversie. fileToPDF.credit=Deze service gebruikt LibreOffice en Unoconv voor bestandsconversie.
fileToPDF.supportedFileTypesInfo=Supported File types
fileToPDF.supportedFileTypes=Ondersteunde bestandstypen zijn hieronder opgenomen, maar raadpleeg voor een volledige lijst met ondersteunde formaten de LibreOffice-documentatie fileToPDF.supportedFileTypes=Ondersteunde bestandstypen zijn hieronder opgenomen, maar raadpleeg voor een volledige lijst met ondersteunde formaten de LibreOffice-documentatie
fileToPDF.submit=Omzetten naar PDF fileToPDF.submit=Omzetten naar PDF
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool #multiTool
multiTool.title=PDF Multitool multiTool.title=PDF Multitool
multiTool.header=PDF Multitool multiTool.header=PDF Multitool
multiTool.uploadPrompts=Please Upload PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=PDF bekijken viewPdf.title=PDF bekijken
@@ -941,6 +958,7 @@ 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=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Versie
licenses.license=Licentie licenses.license=Licentie
# error #error
error.sorry=Sorry for the issue! error.sorry=Sorry for the issue!
error.needHelp=Need help / Found an issue? error.needHelp=Need help / Found an issue?
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=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:

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found. userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect. incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists. usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers. invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Nie można obniżyć roli bieżącego użytkownika
downgradeCurrentUserLongMessage=Nie można obniżyć roli bieżącego użytkownika. W związku z tym bieżący użytkownik nie zostanie wyświetlony.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=Error error=Error
oops=Oops! oops=Oops!
help=Help help=Help
@@ -67,6 +71,7 @@ visitGithub=Visit Github Repository
donate=Donate donate=Donate
color=Color color=Color
sponsor=Sponsor sponsor=Sponsor
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=Validate
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=Konwertuj navbar.favorite=Favorites
navbar.security=Bezpieczeństwo
navbar.other=Inne
navbar.darkmode=Tryb nocny navbar.darkmode=Tryb nocny
navbar.pageOps=Strony navbar.language=Languages
navbar.settings=Ustawienia navbar.settings=Ustawienia
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=User adminUserSettings.user=User
adminUserSettings.addUser=Add New User adminUserSettings.addUser=Add New User
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters. adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles adminUserSettings.roles=Roles
adminUserSettings.role=Role adminUserSettings.role=Role
adminUserSettings.actions=Actions adminUserSettings.actions=Actions
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Demo User (No custom settings)
adminUserSettings.internalApiUser=Internal API User adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Force user to change password on login adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=Zmień rolę użytkownika
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=Remember me
login.invalid=Invalid username or password. login.invalid=Invalid username or password.
login.locked=Your account has been locked. login.locked=Your account has been locked.
login.signinTitle=Please sign in login.signinTitle=Please sign in
login.ssoSignIn=Zaloguj się za pomocą logowania jednokrotnego
login.oauth2AutoCreateDisabled=Wyłączono automatyczne tworzenie użytkownika OAUTH2
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=Napraw
#flatten #flatten
flatten.title=Spłaszcz flatten.title=Spłaszcz
flatten.header=Spłaszcz dokument(y) PDF flatten.header=Spłaszcz dokument(y) PDF
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Spłaszcz flatten.submit=Spłaszcz
@@ -736,6 +752,7 @@ extractImages.submit=Wyodrębnij
fileToPDF.title=Plik na PDF fileToPDF.title=Plik na PDF
fileToPDF.header=Konwertuj dowolny plik na dokument PDF fileToPDF.header=Konwertuj dowolny plik na dokument PDF
fileToPDF.credit=Ta usługa używa LibreOffice i Unoconv do konwersji plików. fileToPDF.credit=Ta usługa używa LibreOffice i Unoconv do konwersji plików.
fileToPDF.supportedFileTypesInfo=Supported File types
fileToPDF.supportedFileTypes=Obsługiwane typy plików powinny być zgodne z poniższymi, jednak pełną zaktualizowaną listę obsługiwanych formatów można znaleźć w dokumentacji LibreOffice fileToPDF.supportedFileTypes=Obsługiwane typy plików powinny być zgodne z poniższymi, jednak pełną zaktualizowaną listę obsługiwanych formatów można znaleźć w dokumentacji LibreOffice
fileToPDF.submit=Konwertuj na PDF fileToPDF.submit=Konwertuj na PDF
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool #multiTool
multiTool.title=Multi narzędzie PDF multiTool.title=Multi narzędzie PDF
multiTool.header=Multi narzędzie PDF multiTool.header=Multi narzędzie PDF
multiTool.uploadPrompts=Please Upload PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=View PDF viewPdf.title=View PDF
@@ -941,6 +958,7 @@ pdfToPDFA.header=PDF na PDF/A
pdfToPDFA.credit=Ta usługa używa OCRmyPDF do konwersji PDF/A pdfToPDFA.credit=Ta usługa używa OCRmyPDF do konwersji PDF/A
pdfToPDFA.submit=Konwertuj pdfToPDFA.submit=Konwertuj
pdfToPDFA.tip=Currently does not work for multiple inputs at once pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Version
licenses.license=License licenses.license=License
# error #error
error.sorry=Sorry for the issue! error.sorry=Sorry for the issue!
error.needHelp=Need help / Found an issue? error.needHelp=Need help / Found an issue?
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=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:

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found. userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect. incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists. usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers. invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Não é possível fazer downgrade da função do usuário atual
downgradeCurrentUserLongMessage=Não é possível fazer downgrade da função do usuário atual. Portanto, o usuário atual não será mostrado.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=Error error=Error
oops=Oops! oops=Oops!
help=Help help=Help
@@ -67,6 +71,7 @@ visitGithub=Visit Github Repository
donate=Donate donate=Donate
color=Color color=Color
sponsor=Sponsor sponsor=Sponsor
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=Validate
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=Converter navbar.favorite=Favorites
navbar.security=Segurança
navbar.other=Outro
navbar.darkmode=Modo Escuro navbar.darkmode=Modo Escuro
navbar.pageOps=Operações de página navbar.language=Languages
navbar.settings=Configurações navbar.settings=Configurações
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=User adminUserSettings.user=User
adminUserSettings.addUser=Add New User adminUserSettings.addUser=Add New User
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters. adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles adminUserSettings.roles=Roles
adminUserSettings.role=Role adminUserSettings.role=Role
adminUserSettings.actions=Actions adminUserSettings.actions=Actions
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Demo User (No custom settings)
adminUserSettings.internalApiUser=Internal API User adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Force user to change password on login adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=Alterar Função de Usuário
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=Remember me
login.invalid=Invalid username or password. login.invalid=Invalid username or password.
login.locked=Your account has been locked. login.locked=Your account has been locked.
login.signinTitle=Please sign in login.signinTitle=Please sign in
login.ssoSignIn=Iniciar sessão através de início de sessão único
login.oauth2AutoCreateDisabled=OAUTH2 Auto-Criar Usuário Desativado
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=Reparar
#flatten #flatten
flatten.title=Achatar flatten.title=Achatar
flatten.header=Achatar PDFs flatten.header=Achatar PDFs
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Achatar flatten.submit=Achatar
@@ -736,6 +752,7 @@ extractImages.submit=Extrair
fileToPDF.title=Arquivo para PDF fileToPDF.title=Arquivo para PDF
fileToPDF.header=Converter Qualquer Arquivo para PDF fileToPDF.header=Converter Qualquer Arquivo para PDF
fileToPDF.credit=Este serviço usa o LibreOffice e o Unoconv para conversão de arquivos. fileToPDF.credit=Este serviço usa o LibreOffice e o Unoconv para conversão de arquivos.
fileToPDF.supportedFileTypesInfo=Supported File types
fileToPDF.supportedFileTypes=Os tipos de arquivo suportados devem incluir os listados abaixo. No entanto, para obter uma lista atualizada completa dos formatos suportados, consulte a documentação do LibreOffice. fileToPDF.supportedFileTypes=Os tipos de arquivo suportados devem incluir os listados abaixo. No entanto, para obter uma lista atualizada completa dos formatos suportados, consulte a documentação do LibreOffice.
fileToPDF.submit=Converter para PDF fileToPDF.submit=Converter para PDF
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool #multiTool
multiTool.title=Multiferramenta de PDF multiTool.title=Multiferramenta de PDF
multiTool.header=Multiferramenta de PDF multiTool.header=Multiferramenta de PDF
multiTool.uploadPrompts=Please Upload PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=View PDF viewPdf.title=View PDF
@@ -941,6 +958,7 @@ pdfToPDFA.header=PDF para PDF/A
pdfToPDFA.credit=Este serviço usa OCRmyPDF para Conversão de PDF/A pdfToPDFA.credit=Este serviço usa OCRmyPDF para Conversão de PDF/A
pdfToPDFA.submit=Converter pdfToPDFA.submit=Converter
pdfToPDFA.tip=Currently does not work for multiple inputs at once pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Version
licenses.license=License licenses.license=License
# error #error
error.sorry=Sorry for the issue! error.sorry=Sorry for the issue!
error.needHelp=Need help / Found an issue? error.needHelp=Need help / Found an issue?
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=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:

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=Utilizador não autenticado.
userNotFoundMessage=Utilizador inexistente. userNotFoundMessage=Utilizador inexistente.
incorrectPasswordMessage=Senha incorreta. incorrectPasswordMessage=Senha incorreta.
usernameExistsMessage=Esse utilizador já existe. usernameExistsMessage=Esse utilizador já existe.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers. invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Não é possível fazer downgrade da função do utilizador atual
downgradeCurrentUserLongMessage=Não é possível fazer downgrade da função do utilizador atual. Portanto, o utilizador atual não será mostrado.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=Error error=Error
oops=Oops! oops=Oops!
help=Help help=Help
@@ -67,6 +71,7 @@ visitGithub=Visit Github Repository
donate=Donate donate=Donate
color=Color color=Color
sponsor=Sponsor sponsor=Sponsor
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=Validar
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=Converter navbar.favorite=Favorites
navbar.security=Segurança
navbar.other=Outro
navbar.darkmode=Modo Escuro navbar.darkmode=Modo Escuro
navbar.pageOps=Operações de página navbar.language=Languages
navbar.settings=Configurações navbar.settings=Configurações
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=User adminUserSettings.user=User
adminUserSettings.addUser=Add New User adminUserSettings.addUser=Add New User
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters. adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles adminUserSettings.roles=Roles
adminUserSettings.role=Role adminUserSettings.role=Role
adminUserSettings.actions=Actions adminUserSettings.actions=Actions
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Demo User (No custom settings)
adminUserSettings.internalApiUser=Internal API User adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Force user to change password on login adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=Alterar usuário
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=Lembrar dados
login.invalid=Utilizador ou senha inválidos. login.invalid=Utilizador ou senha inválidos.
login.locked=A sua conta foi bloqueada. login.locked=A sua conta foi bloqueada.
login.signinTitle=Introduza os seus dados de acesso login.signinTitle=Introduza os seus dados de acesso
login.ssoSignIn=Iniciar sessão através de início de sessão único
login.oauth2AutoCreateDisabled=OAUTH2 Criação Automática de Utilizador Desativada
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=Reparar
#flatten #flatten
flatten.title=Achatar flatten.title=Achatar
flatten.header=Achatar PDFs flatten.header=Achatar PDFs
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Achatar flatten.submit=Achatar
@@ -736,6 +752,7 @@ extractImages.submit=Extrair
fileToPDF.title=Ficheiro para PDF fileToPDF.title=Ficheiro para PDF
fileToPDF.header=Converter Qualquer ficheiro para PDF fileToPDF.header=Converter Qualquer ficheiro para PDF
fileToPDF.credit=Este serviço usa o LibreOffice e o Unoconv para conversão de ficheiros. fileToPDF.credit=Este serviço usa o LibreOffice e o Unoconv para conversão de ficheiros.
fileToPDF.supportedFileTypesInfo=Supported File types
fileToPDF.supportedFileTypes=Os tipos de ficheiro suportados devem incluir os listados abaixo. No entanto, para obter uma lista atualizada completa dos formatos suportados, consulte a documentação do LibreOffice. fileToPDF.supportedFileTypes=Os tipos de ficheiro suportados devem incluir os listados abaixo. No entanto, para obter uma lista atualizada completa dos formatos suportados, consulte a documentação do LibreOffice.
fileToPDF.submit=Converter para PDF fileToPDF.submit=Converter para PDF
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool #multiTool
multiTool.title=Multiferramenta de PDF multiTool.title=Multiferramenta de PDF
multiTool.header=Multiferramenta de PDF multiTool.header=Multiferramenta de PDF
multiTool.uploadPrompts=Please Upload PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=View PDF viewPdf.title=View PDF
@@ -941,6 +958,7 @@ pdfToPDFA.header=PDF para PDF/A
pdfToPDFA.credit=Este serviço usa OCRmyPDF para Conversão de PDF/A pdfToPDFA.credit=Este serviço usa OCRmyPDF para Conversão de PDF/A
pdfToPDFA.submit=Converter pdfToPDFA.submit=Converter
pdfToPDFA.tip=Currently does not work for multiple inputs at once pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Versão
licenses.license=Licença licenses.license=Licença
# error #error
error.sorry=Sorry for the issue! error.sorry=Sorry for the issue!
error.needHelp=Need help / Found an issue? error.needHelp=Need help / Found an issue?
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=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:

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found. userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect. incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists. usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers. invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Rolul utilizatorului curent nu poate fi retrogradat
downgradeCurrentUserLongMessage=Rolul utilizatorului curent nu poate fi retrogradat. Prin urmare, utilizatorul curent nu va fi afișat.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=Error error=Error
oops=Oops! oops=Oops!
help=Help help=Help
@@ -67,6 +71,7 @@ visitGithub=Visit Github Repository
donate=Donate donate=Donate
color=Color color=Color
sponsor=Sponsor sponsor=Sponsor
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=Validate
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=Converteste navbar.favorite=Favorites
navbar.security=Securitate
navbar.other=Altele
navbar.darkmode=Mod întunecat navbar.darkmode=Mod întunecat
navbar.pageOps=Operații pe pagină navbar.language=Languages
navbar.settings=Setări navbar.settings=Setări
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=User adminUserSettings.user=User
adminUserSettings.addUser=Add New User adminUserSettings.addUser=Add New User
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters. adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles adminUserSettings.roles=Roles
adminUserSettings.role=Role adminUserSettings.role=Role
adminUserSettings.actions=Actions adminUserSettings.actions=Actions
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Demo User (No custom settings)
adminUserSettings.internalApiUser=Internal API User adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Force user to change password on login adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=Schimbați rolul utilizatorului
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=Remember me
login.invalid=Invalid username or password. login.invalid=Invalid username or password.
login.locked=Your account has been locked. login.locked=Your account has been locked.
login.signinTitle=Please sign in login.signinTitle=Please sign in
login.ssoSignIn=Conectare prin conectare unică
login.oauth2AutoCreateDisabled=OAUTH2 Creare automată utilizator dezactivată
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=Repară
#flatten #flatten
flatten.title=Nivelare flatten.title=Nivelare
flatten.header=Nivelează documente PDF flatten.header=Nivelează documente PDF
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Nivelează flatten.submit=Nivelează
@@ -736,6 +752,7 @@ extractImages.submit=Extrage
fileToPDF.title=Fișier în PDF fileToPDF.title=Fișier în PDF
fileToPDF.header=Convertiți orice fișier în PDF fileToPDF.header=Convertiți orice fișier în PDF
fileToPDF.credit=Acest serviciu utilizează LibreOffice și Unoconv pentru conversia fișierelor. fileToPDF.credit=Acest serviciu utilizează LibreOffice și Unoconv pentru conversia fișierelor.
fileToPDF.supportedFileTypesInfo=Supported File types
fileToPDF.supportedFileTypes=Tipurile de fișiere suportate ar trebui să includă cele de mai jos. Pentru o listă completă și actualizată a formatelor suportate, consultați documentația LibreOffice. fileToPDF.supportedFileTypes=Tipurile de fișiere suportate ar trebui să includă cele de mai jos. Pentru o listă completă și actualizată a formatelor suportate, consultați documentația LibreOffice.
fileToPDF.submit=Convertiți în PDF fileToPDF.submit=Convertiți în PDF
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool #multiTool
multiTool.title=Instrument PDF multiplu multiTool.title=Instrument PDF multiplu
multiTool.header=Instrument PDF multiplu multiTool.header=Instrument PDF multiplu
multiTool.uploadPrompts=Please Upload PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=View PDF viewPdf.title=View PDF
@@ -941,6 +958,7 @@ pdfToPDFA.header=PDF către PDF/A
pdfToPDFA.credit=Acest serviciu utilizează OCRmyPDF pentru conversia în PDF/A pdfToPDFA.credit=Acest serviciu utilizează OCRmyPDF pentru conversia în PDF/A
pdfToPDFA.submit=Convert pdfToPDFA.submit=Convert
pdfToPDFA.tip=Currently does not work for multiple inputs at once pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Version
licenses.license=License licenses.license=License
# error #error
error.sorry=Sorry for the issue! error.sorry=Sorry for the issue!
error.needHelp=Need help / Found an issue? error.needHelp=Need help / Found an issue?
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=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:

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=Пользователь не прошел провер
userNotFoundMessage=Пользователь не найден. userNotFoundMessage=Пользователь не найден.
incorrectPasswordMessage=Текущий пароль неверен. incorrectPasswordMessage=Текущий пароль неверен.
usernameExistsMessage=Новое имя пользователя уже существует. usernameExistsMessage=Новое имя пользователя уже существует.
invalidUsernameMessage=Недопустимое имя пользователя, Имя пользователя должно содержать только буквы алфавита и цифры. invalidUsernameMessage=Неверное имя пользователя. Имя пользователя может содержать только буквы, цифры и следующие специальные символы @._+- или должно быть действительным адресом электронной почты.
deleteCurrentUserMessage=Невозможно удалить пользователя, вошедшего в систему. deleteCurrentUserMessage=Невозможно удалить пользователя, вошедшего в систему.
deleteUsernameExistsMessage=Имя пользователя не существует и не может быть удалено. deleteUsernameExistsMessage=Имя пользователя не существует и не может быть удалено.
downgradeCurrentUserMessage=Невозможно понизить роль текущего пользователя
downgradeCurrentUserLongMessage=Невозможно понизить роль текущего пользователя. Следовательно, текущий пользователь не будет отображаться.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=Ошибка error=Ошибка
oops=Ой! oops=Ой!
help=Помощь help=Помощь
@@ -67,6 +71,7 @@ visitGithub=Посетить репозиторий на GitHub
donate=Пожертвовать donate=Пожертвовать
color=Цвет color=Цвет
sponsor=Спонсор sponsor=Спонсор
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=Проверить
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=Конвертировать navbar.favorite=Favorites
navbar.security=Безопасность
navbar.other=Другое
navbar.darkmode=Темный режим navbar.darkmode=Темный режим
navbar.pageOps=Операции с страницей navbar.language=Languages
navbar.settings=Настройки navbar.settings=Настройки
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=Настройки контроля пользоват
adminUserSettings.admin=Администратор adminUserSettings.admin=Администратор
adminUserSettings.user=Пользователь adminUserSettings.user=Пользователь
adminUserSettings.addUser=Добавить нового пользователя adminUserSettings.addUser=Добавить нового пользователя
adminUserSettings.usernameInfo=Имя пользователя должно содержать только буквы и цифры, без пробелов и специальных символов. adminUserSettings.usernameInfo=Имя пользователя может содержать только буквы, цифры и следующие специальные символы @._+- или должно быть действительным адресом электронной почты.
adminUserSettings.roles=Роли adminUserSettings.roles=Роли
adminUserSettings.role=Роль adminUserSettings.role=Роль
adminUserSettings.actions=Действия adminUserSettings.actions=Действия
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Демо-пользователь (без настр
adminUserSettings.internalApiUser=Внутренний пользователь API adminUserSettings.internalApiUser=Внутренний пользователь API
adminUserSettings.forceChange=Просить пользователя изменить пароль при входе в систему adminUserSettings.forceChange=Просить пользователя изменить пароль при входе в систему
adminUserSettings.submit=Сохранить пользователя adminUserSettings.submit=Сохранить пользователя
adminUserSettings.changeUserRole=Изменить роль пользователя
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=Запомнить меня
login.invalid=Недействительное имя пользователя или пароль. login.invalid=Недействительное имя пользователя или пароль.
login.locked=Ваша учетная запись заблокирована. login.locked=Ваша учетная запись заблокирована.
login.signinTitle=Пожалуйста, войдите login.signinTitle=Пожалуйста, войдите
login.ssoSignIn=Вход через единый вход
login.oauth2AutoCreateDisabled=OAUTH2 Автоматическое создание пользователя отключено
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=Ремонт
#flatten #flatten
flatten.title=Сглаживание flatten.title=Сглаживание
flatten.header=Сглаживание PDF ов flatten.header=Сглаживание PDF ов
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Сгладить flatten.submit=Сгладить
@@ -736,6 +752,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.supportedFileTypes=Поддерживаемые типы файлов должны включать приведенные ниже, однако полный обновленный список поддерживаемых форматов см. в документации LibreOffice. fileToPDF.supportedFileTypes=Поддерживаемые типы файлов должны включать приведенные ниже, однако полный обновленный список поддерживаемых форматов см. в документации LibreOffice.
fileToPDF.submit=Преобразовать в PDF fileToPDF.submit=Преобразовать в PDF
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(например, 1,3,2 или 4-8,2,10-12 или 2n-1
#multiTool #multiTool
multiTool.title=Мультиинструмент PDF multiTool.title=Мультиинструмент PDF
multiTool.header=Мультиинструмент PDF multiTool.header=Мультиинструмент PDF
multiTool.uploadPrompts=Пожалуйста, загрузите PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=Просмотреть PDF viewPdf.title=Просмотреть PDF
@@ -941,6 +958,7 @@ pdfToPDFA.header=PDF в PDF/A
pdfToPDFA.credit=Этот сервис использует OCRmyPDF для преобразования PDF/A pdfToPDFA.credit=Этот сервис использует OCRmyPDF для преобразования PDF/A
pdfToPDFA.submit=Конвертировать pdfToPDFA.submit=Конвертировать
pdfToPDFA.tip=Currently does not work for multiple inputs at once pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Версия
licenses.license=Лицензия licenses.license=Лицензия
# error #error
error.sorry=Извините за проблему! error.sorry=Извините за проблему!
error.needHelp=Нужна помощь / Нашли проблему? error.needHelp=Нужна помощь / Нашли проблему?
error.contactTip=Если у вас все еще есть проблемы, не стесняйтесь обращаться к нам за помощью. Вы можете отправить заявку на нашей странице GitHub или связаться с нами через Discord: error.contactTip=Если у вас все еще есть проблемы, не стесняйтесь обращаться к нам за помощью. Вы можете отправить заявку на нашей странице GitHub или связаться с нами через Discord:

File diff suppressed because it is too large Load Diff

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=Korisnik nije autentifikovan.
userNotFoundMessage=Korisnik nije pronađen. userNotFoundMessage=Korisnik nije pronađen.
incorrectPasswordMessage=Trenutna šifra je netačna. incorrectPasswordMessage=Trenutna šifra je netačna.
usernameExistsMessage=Novi korisnik već postoji usernameExistsMessage=Novi korisnik već postoji
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers. invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Nije moguće degradirati ulogu trenutnog korisnika
downgradeCurrentUserLongMessage=Nije moguće unazaditi ulogu trenutnog korisnika. Dakle, trenutni korisnik neće biti prikazan.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=Error error=Error
oops=Oops! oops=Oops!
help=Help help=Help
@@ -67,6 +71,7 @@ visitGithub=Visit Github Repository
donate=Donate donate=Donate
color=Color color=Color
sponsor=Sponsor sponsor=Sponsor
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=Proveri
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=Konvertuj navbar.favorite=Favorites
navbar.security=Bezbednost
navbar.other=Razno
navbar.darkmode=Tamni režim navbar.darkmode=Tamni režim
navbar.pageOps=Operacije stranice navbar.language=Languages
navbar.settings=Podešavanja navbar.settings=Podešavanja
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=Podešavanja kontrole korisnika za administratora
adminUserSettings.admin=Administrator adminUserSettings.admin=Administrator
adminUserSettings.user=Korisnik adminUserSettings.user=Korisnik
adminUserSettings.addUser=Dodaj novog korisnika adminUserSettings.addUser=Dodaj novog korisnika
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters. adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Uloge adminUserSettings.roles=Uloge
adminUserSettings.role=Uloga adminUserSettings.role=Uloga
adminUserSettings.actions=Akcije adminUserSettings.actions=Akcije
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Demo korisnik (Bez prilagođenih podešavanja)
adminUserSettings.internalApiUser=Internal API User adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Prisili korisnika da promeni korisničko ime/lozinku pri prijavi adminUserSettings.forceChange=Prisili korisnika da promeni korisničko ime/lozinku pri prijavi
adminUserSettings.submit=Sačuvaj korisnika adminUserSettings.submit=Sačuvaj korisnika
adminUserSettings.changeUserRole=Promenite ulogu korisnika
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=Zapamti me
login.invalid=Neispravno korisničko ime ili lozinka. login.invalid=Neispravno korisničko ime ili lozinka.
login.locked=Vaš nalog je zaključan. login.locked=Vaš nalog je zaključan.
login.signinTitle=Molimo vas da se prijavite login.signinTitle=Molimo vas da se prijavite
login.ssoSignIn=Prijavite se putem jedinstvene prijave
login.oauth2AutoCreateDisabled=OAUTH2 automatsko kreiranje korisnika je onemogućeno
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=Popravi
#flatten #flatten
flatten.title=Ravnanje flatten.title=Ravnanje
flatten.header=Ravnanje PDF fajlova flatten.header=Ravnanje PDF fajlova
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Ravnanje flatten.submit=Ravnanje
@@ -736,6 +752,7 @@ extractImages.submit=Izdvajanje
fileToPDF.title=Fajl u PDF fileToPDF.title=Fajl u PDF
fileToPDF.header=Konvertuj bilo koji fajl u PDF fileToPDF.header=Konvertuj bilo koji fajl u PDF
fileToPDF.credit=Ova usluga koristi LibreOffice i Unoconv za konverziju fajla. fileToPDF.credit=Ova usluga koristi LibreOffice i Unoconv za konverziju fajla.
fileToPDF.supportedFileTypesInfo=Supported File types
fileToPDF.supportedFileTypes=Podržani tipovi fajlova bi trebali uključivati navedeno, ali za punu ažuriranu listu podržanih formata, molimo pogledajte LibreOffice dokumentaciju fileToPDF.supportedFileTypes=Podržani tipovi fajlova bi trebali uključivati navedeno, ali za punu ažuriranu listu podržanih formata, molimo pogledajte LibreOffice dokumentaciju
fileToPDF.submit=Konvertuj u PDF fileToPDF.submit=Konvertuj u PDF
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool #multiTool
multiTool.title=PDF Multi Alatka multiTool.title=PDF Multi Alatka
multiTool.header=PDF Multi Alatka multiTool.header=PDF Multi Alatka
multiTool.uploadPrompts=Please Upload PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=Prikaz viewPdf.title=Prikaz
@@ -941,6 +958,7 @@ pdfToPDFA.header=PDF u PDF/A
pdfToPDFA.credit=Ova usluga koristi OCRmyPDF za konverziju u PDF/A format pdfToPDFA.credit=Ova usluga koristi OCRmyPDF za konverziju u PDF/A format
pdfToPDFA.submit=Konvertuj pdfToPDFA.submit=Konvertuj
pdfToPDFA.tip=Currently does not work for multiple inputs at once pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Version
licenses.license=License licenses.license=License
# error #error
error.sorry=Sorry for the issue! error.sorry=Sorry for the issue!
error.needHelp=Need help / Found an issue? error.needHelp=Need help / Found an issue?
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=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:

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=User not authenticated.
userNotFoundMessage=User not found. userNotFoundMessage=User not found.
incorrectPasswordMessage=Current password is incorrect. incorrectPasswordMessage=Current password is incorrect.
usernameExistsMessage=New Username already exists. usernameExistsMessage=New Username already exists.
invalidUsernameMessage=Invalid username, Username must only contain alphabet characters and numbers. invalidUsernameMessage=Invalid username, username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
deleteCurrentUserMessage=Cannot delete currently logged in user. deleteCurrentUserMessage=Cannot delete currently logged in user.
deleteUsernameExistsMessage=The username does not exist and cannot be deleted. deleteUsernameExistsMessage=The username does not exist and cannot be deleted.
downgradeCurrentUserMessage=Kan inte nedgradera nuvarande användares roll
downgradeCurrentUserLongMessage=Kan inte nedgradera nuvarande användares roll. Därför kommer den aktuella användaren inte att visas.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=Error error=Error
oops=Oops! oops=Oops!
help=Help help=Help
@@ -67,6 +71,7 @@ visitGithub=Visit Github Repository
donate=Donate donate=Donate
color=Color color=Color
sponsor=Sponsor sponsor=Sponsor
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=Validate
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=Konvertera navbar.favorite=Favorites
navbar.security=Säkerhet
navbar.other=Annat
navbar.darkmode=Mörkt läge navbar.darkmode=Mörkt läge
navbar.pageOps=Sidoperationer navbar.language=Languages
navbar.settings=Inställningar navbar.settings=Inställningar
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=Admin User Control Settings
adminUserSettings.admin=Admin adminUserSettings.admin=Admin
adminUserSettings.user=User adminUserSettings.user=User
adminUserSettings.addUser=Add New User adminUserSettings.addUser=Add New User
adminUserSettings.usernameInfo=Username must only contain letters and numbers, no spaces or special characters. adminUserSettings.usernameInfo=Username can only contain letters, numbers and the following special characters @._+- or must be a valid email address.
adminUserSettings.roles=Roles adminUserSettings.roles=Roles
adminUserSettings.role=Role adminUserSettings.role=Role
adminUserSettings.actions=Actions adminUserSettings.actions=Actions
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Demo User (No custom settings)
adminUserSettings.internalApiUser=Internal API User adminUserSettings.internalApiUser=Internal API User
adminUserSettings.forceChange=Force user to change password on login adminUserSettings.forceChange=Force user to change password on login
adminUserSettings.submit=Save User adminUserSettings.submit=Save User
adminUserSettings.changeUserRole=Ändra användarens roll
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=Remember me
login.invalid=Invalid username or password. login.invalid=Invalid username or password.
login.locked=Your account has been locked. login.locked=Your account has been locked.
login.signinTitle=Please sign in login.signinTitle=Please sign in
login.ssoSignIn=Logga in via enkel inloggning
login.oauth2AutoCreateDisabled=OAUTH2 Auto-Create User inaktiverad
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=Reparera
#flatten #flatten
flatten.title=Platta till flatten.title=Platta till
flatten.header=Placera PDF-filer flatten.header=Placera PDF-filer
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Platta till flatten.submit=Platta till
@@ -736,6 +752,7 @@ extractImages.submit=Extrahera
fileToPDF.title=Fil till PDF fileToPDF.title=Fil till PDF
fileToPDF.header=Konvertera valfri fil till PDF fileToPDF.header=Konvertera valfri fil till PDF
fileToPDF.credit=Denna tjänst använder LibreOffice och Unoconv för filkonvertering. fileToPDF.credit=Denna tjänst använder LibreOffice och Unoconv för filkonvertering.
fileToPDF.supportedFileTypesInfo=Supported File types
fileToPDF.supportedFileTypes=Filtyper som stöds bör inkludera nedanstående men för en fullständig uppdaterad lista över format som stöds, se LibreOffice-dokumentationen fileToPDF.supportedFileTypes=Filtyper som stöds bör inkludera nedanstående men för en fullständig uppdaterad lista över format som stöds, se LibreOffice-dokumentationen
fileToPDF.submit=Konvertera till PDF fileToPDF.submit=Konvertera till PDF
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(e.g. 1,3,2 or 4-8,2,10-12 or 2n-1)
#multiTool #multiTool
multiTool.title=PDF-multiverktyg multiTool.title=PDF-multiverktyg
multiTool.header=PDF Multi-verktyg multiTool.header=PDF Multi-verktyg
multiTool.uploadPrompts=Please Upload PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=View PDF viewPdf.title=View PDF
@@ -941,6 +958,7 @@ pdfToPDFA.header=PDF till PDF/A
pdfToPDFA.credit=Denna tjänst använder OCRmyPDF för PDF/A-konvertering pdfToPDFA.credit=Denna tjänst använder OCRmyPDF för PDF/A-konvertering
pdfToPDFA.submit=Konvertera pdfToPDFA.submit=Konvertera
pdfToPDFA.tip=Currently does not work for multiple inputs at once pdfToPDFA.tip=Currently does not work for multiple inputs at once
pdfToPDFA.outputFormat=Output format
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Version
licenses.license=License licenses.license=License
# error #error
error.sorry=Sorry for the issue! error.sorry=Sorry for the issue!
error.needHelp=Need help / Found an issue? error.needHelp=Need help / Found an issue?
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=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:

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=Kullanıcı doğrulanmadı.
userNotFoundMessage=Kullanıcı bulunamadı. userNotFoundMessage=Kullanıcı bulunamadı.
incorrectPasswordMessage=Mevcut şifre yanlış. incorrectPasswordMessage=Mevcut şifre yanlış.
usernameExistsMessage=Yeni Kullanıcı Adı zaten var. usernameExistsMessage=Yeni Kullanıcı Adı zaten var.
invalidUsernameMessage=Geçersiz kullanıcı adı, Kullanıcı adı yalnızca alfabe karakterleri ve sayılar içermelidir. invalidUsernameMessage=Geçersiz kullanıcı adı, kullanıcı adı yalnızca harf, rakam ve aşağıdaki özel karakterleri @._+- içerebilir veya geçerli bir e-posta adresi olmalıdır.
deleteCurrentUserMessage=Şu anda oturum açmış olan kullanıcı silinemiyor. deleteCurrentUserMessage=Şu anda oturum açmış olan kullanıcı silinemiyor.
deleteUsernameExistsMessage=Kullanıcı adı mevcut değil ve silinemez. deleteUsernameExistsMessage=Kullanıcı adı mevcut değil ve silinemez.
downgradeCurrentUserMessage=Mevcut kullanıcının rolü düşürülemiyor
downgradeCurrentUserLongMessage=Mevcut kullanıcının rolü düşürülemiyor. Bu nedenle, mevcut kullanıcı gösterilmeyecektir.
userAlreadyExistsOAuthMessage=Kullanıcı zaten bir OAuth2 kullanıcısı olarak mevcut.
userAlreadyExistsWebMessage=Kullanıcı zaten bir web kullanıcısı olarak mevcut.
error=Hata error=Hata
oops=Tüh! oops=Tüh!
help=Yardım help=Yardım
@@ -66,7 +70,8 @@ seeDockerHub=Docker Hub'a bakın
visitGithub=Github Deposunu Ziyaret Edin visitGithub=Github Deposunu Ziyaret Edin
donate=Bağış Yapın donate=Bağış Yapın
color=Renk color=Renk
sponsor=Sponsor sponsor=Bağış
info=Bilgi
@@ -100,19 +105,25 @@ pipelineOptions.validateButton=Doğrula
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=Dönüştür navbar.favorite=Favoriler
navbar.security=Güvenlik
navbar.other=Çeşitli
navbar.darkmode=Karanlık Mod navbar.darkmode=Karanlık Mod
navbar.pageOps=Sayfa İşlemleri navbar.language=Diller
navbar.settings=Ayarlar navbar.settings=Ayarlar
navbar.allTools=Araçlar
navbar.multiTool=Çoklu Araçlar
navbar.sections.organize=Düzenle
navbar.sections.convertTo=PDF'ye dönüştür
navbar.sections.convertFrom=PDF'den dönüştür
navbar.sections.security=Oturum & Güvenlik
navbar.sections.advance=Gelişmiş
navbar.sections.edit=Görüntüle ve Düzenle
############# #############
# SETTINGS # # SETTINGS #
############# #############
settings.title=Ayarlar settings.title=Ayarlar
settings.update=Güncelleme mevcut settings.update=Güncelleme mevcut
settings.updateAvailable={0} is the current installed version. A new version ({1}) is available. settings.updateAvailable={0} mevcut kurulu sürümdür. Yeni bir sürüm ({1}) mevcuttur.
settings.appVersion=Uygulama Sürümü: settings.appVersion=Uygulama Sürümü:
settings.downloadOption.title=İndirme seçeneği seçin (Zip olmayan tek dosya indirmeler için): settings.downloadOption.title=İndirme seçeneği seçin (Zip olmayan tek dosya indirmeler için):
settings.downloadOption.1=Aynı pencerede aç settings.downloadOption.1=Aynı pencerede aç
@@ -162,7 +173,7 @@ adminUserSettings.header=Yönetici Kullanıcı Kontrol Ayarları
adminUserSettings.admin=Yönetici adminUserSettings.admin=Yönetici
adminUserSettings.user=Kullanıcı adminUserSettings.user=Kullanıcı
adminUserSettings.addUser=Yeni Kullanıcı Ekle adminUserSettings.addUser=Yeni Kullanıcı Ekle
adminUserSettings.usernameInfo=Kullanıcı adı yalnızca harf ve rakamlardan oluşmalı, boşluk veya özel karakter içermemelidir. adminUserSettings.usernameInfo=Kullanıcı adı yalnızca harf, rakam ve aşağıdaki özel karakterleri @._+- içerebilir veya geçerli bir e-posta adresi olmalıdır.
adminUserSettings.roles=Roller adminUserSettings.roles=Roller
adminUserSettings.role=Rol adminUserSettings.role=Rol
adminUserSettings.actions=Eylemler adminUserSettings.actions=Eylemler
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Demo Kullanıcısı (Özel ayar yok)
adminUserSettings.internalApiUser=Dahili API Kullanıcısı adminUserSettings.internalApiUser=Dahili API Kullanıcısı
adminUserSettings.forceChange=Kullanıcının girişte kullanıcı adı/şifre değiştirmesini zorla adminUserSettings.forceChange=Kullanıcının girişte kullanıcı adı/şifre değiştirmesini zorla
adminUserSettings.submit=Kullanıcıyı Kaydet adminUserSettings.submit=Kullanıcıyı Kaydet
adminUserSettings.changeUserRole=Kullanıcı rolünü değiştir
adminUserSettings.authenticated=Onaylandı
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=Beni hatırla
login.invalid=Geçersiz kullanıcı adı veya şifre. login.invalid=Geçersiz kullanıcı adı veya şifre.
login.locked=Hesabınız kilitlendi. login.locked=Hesabınız kilitlendi.
login.signinTitle=Lütfen giriş yapınız. login.signinTitle=Lütfen giriş yapınız.
login.ssoSignIn=Tek Oturum Açma ile Giriş Yap
login.oauth2AutoCreateDisabled=OAUTH2 Otomatik Oluşturma Kullanıcı Devre Dışı Bırakıldı
#auto-redact #auto-redact
@@ -666,7 +681,7 @@ BookToPDF.submit=Dönüştür
#PDFToBook #PDFToBook
PDFToBook.title=PDF'den Kitaba PDFToBook.title=PDF'den Kitaba
PDFToBook.header=PDF'den Kitaba PDFToBook.header=PDF'den Kitaba
PDFToBook.selectText.1=Format PDFToBook.selectText.1=Format biçimi
PDFToBook.credit=Kalibre Kullanır PDFToBook.credit=Kalibre Kullanır
PDFToBook.submit=Dönüştür PDFToBook.submit=Dönüştür
@@ -689,6 +704,7 @@ repair.submit=Onar
#flatten #flatten
flatten.title=Düzleştir flatten.title=Düzleştir
flatten.header=PDF'leri Düzleştir flatten.header=PDF'leri Düzleştir
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Düzleştir flatten.submit=Düzleştir
@@ -736,6 +752,7 @@ extractImages.submit=Çıkar
fileToPDF.title=Dosyadan PDF'e fileToPDF.title=Dosyadan PDF'e
fileToPDF.header=Herhangi bir dosyayı PDF'e dönüştür fileToPDF.header=Herhangi bir dosyayı PDF'e dönüştür
fileToPDF.credit=Bu hizmet dosya dönüşümü için LibreOffice ve Unoconv'u kullanır. fileToPDF.credit=Bu hizmet dosya dönüşümü için LibreOffice ve Unoconv'u kullanır.
fileToPDF.supportedFileTypesInfo=Desteklenen Dosya türleri
fileToPDF.supportedFileTypes=Desteklenen dosya türleri aşağıdakileri içermelidir ancak desteklenen formatların tam güncellenmiş listesi için lütfen LibreOffice dokümantasyonuna başvurun fileToPDF.supportedFileTypes=Desteklenen dosya türleri aşağıdakileri içermelidir ancak desteklenen formatların tam güncellenmiş listesi için lütfen LibreOffice dokümantasyonuna başvurun
fileToPDF.submit=PDF'e Dönüştür fileToPDF.submit=PDF'e Dönüştür
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(örn. 1,3,2 veya 4-8,2,10-12 veya 2n-1)
#multiTool #multiTool
multiTool.title=PDF Çoklu Araç multiTool.title=PDF Çoklu Araç
multiTool.header=PDF Çoklu Araç multiTool.header=PDF Çoklu Araç
multiTool.uploadPrompts=Lütfen PDF Yükleyin multiTool.uploadPrompts=Dosya Adı
#view pdf #view pdf
viewPdf.title=PDF Görüntüle viewPdf.title=PDF Görüntüle
@@ -941,6 +958,7 @@ pdfToPDFA.header=PDF'den PDF/A'ya
pdfToPDFA.credit=Bu hizmet PDF/A dönüşümü için OCRmyPDF kullanır pdfToPDFA.credit=Bu hizmet PDF/A dönüşümü için OCRmyPDF kullanır
pdfToPDFA.submit=Dönüştür pdfToPDFA.submit=Dönüştür
pdfToPDFA.tip=Şu anda aynı anda birden fazla giriş için çalışmıyor pdfToPDFA.tip=Şu anda aynı anda birden fazla giriş için çalışmıyor
pdfToPDFA.outputFormat=Çıkış formatı
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Versiyon
licenses.license=Lisans licenses.license=Lisans
# error #error
error.sorry=Sorun için özür dileriz! error.sorry=Sorun için özür dileriz!
error.needHelp=Yardıma mı ihtiyacınız var / Bir sorun mu buldunuz? error.needHelp=Yardıma mı ihtiyacınız var / Bir sorun mu buldunuz?
error.contactTip=Hala sorun yaşıyorsanız, yardım için bize ulaşmaktan çekinmeyin. GitHub sayfamızdan bir bilet gönderebilir veya Discord üzerinden bizimle iletişime geçebilirsiniz: error.contactTip=Hala sorun yaşıyorsanız, yardım için bize ulaşmaktan çekinmeyin. GitHub sayfamızdan bir bilet gönderebilir veya Discord üzerinden bizimle iletişime geçebilirsiniz:

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=Користувач не пройшов перевір
userNotFoundMessage=Користувача не знайдено. userNotFoundMessage=Користувача не знайдено.
incorrectPasswordMessage=Поточний пароль невірний. incorrectPasswordMessage=Поточний пароль невірний.
usernameExistsMessage=Нове ім'я користувача вже існує. usernameExistsMessage=Нове ім'я користувача вже існує.
invalidUsernameMessage=Недійсне ім'я користувача, Ім'я користувача повинно містити тільки літери алфавіту та цифри. invalidUsernameMessage=Недійсне імя користувача, ім’я користувача може містити лише літери, цифри та наступні спеціальні символи @._+- або має бути дійсною електронною адресою.
deleteCurrentUserMessage=Неможливо видалити користувача, який увійшов в систему. deleteCurrentUserMessage=Неможливо видалити користувача, який увійшов в систему.
deleteUsernameExistsMessage=Ім'я користувача не існує і не може бути видалено. deleteUsernameExistsMessage=Ім'я користувача не існує і не може бути видалено.
downgradeCurrentUserMessage=Неможливо понизити роль поточного користувача
downgradeCurrentUserLongMessage=Неможливо понизити роль поточного користувача. Отже, поточний користувач не відображатиметься.
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=Error error=Error
oops=Oops! oops=Oops!
help=Help help=Help
@@ -67,6 +71,7 @@ visitGithub=Visit Github Repository
donate=Donate donate=Donate
color=Color color=Color
sponsor=Sponsor sponsor=Sponsor
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=Перевірити
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=Конвертувати navbar.favorite=Favorites
navbar.security=Безпека
navbar.other=Інше
navbar.darkmode=Темний режим navbar.darkmode=Темний режим
navbar.pageOps=Операції зі сторінкою navbar.language=Languages
navbar.settings=Налаштування navbar.settings=Налаштування
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=Налаштування контролю корист
adminUserSettings.admin=Адміністратор adminUserSettings.admin=Адміністратор
adminUserSettings.user=Користувач adminUserSettings.user=Користувач
adminUserSettings.addUser=Додати нового користувача adminUserSettings.addUser=Додати нового користувача
adminUserSettings.usernameInfo=Ім'я користувача має містити тільки літери та цифри, без пробілів та спеціальних символів. adminUserSettings.usernameInfo=Імя користувача може містити лише літери, цифри та наступні спеціальні символи @._+- або має бути дійсною електронною адресою.
adminUserSettings.roles=Ролі adminUserSettings.roles=Ролі
adminUserSettings.role=Роль adminUserSettings.role=Роль
adminUserSettings.actions=Дії adminUserSettings.actions=Дії
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=Демо-користувач (без налашто
adminUserSettings.internalApiUser=Внутрішній користувач API adminUserSettings.internalApiUser=Внутрішній користувач API
adminUserSettings.forceChange=Примусити користувача змінити пароль при вході в систему adminUserSettings.forceChange=Примусити користувача змінити пароль при вході в систему
adminUserSettings.submit=Зберегти користувача adminUserSettings.submit=Зберегти користувача
adminUserSettings.changeUserRole=Змінити роль користувача
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=Запам'ятати мене
login.invalid=Недійсне ім'я користувача або пароль. login.invalid=Недійсне ім'я користувача або пароль.
login.locked=Ваш обліковий запис заблоковано. login.locked=Ваш обліковий запис заблоковано.
login.signinTitle=Будь ласка, увійдіть login.signinTitle=Будь ласка, увійдіть
login.ssoSignIn=Увійти через єдиний вхід
login.oauth2AutoCreateDisabled=Автоматичне створення користувача OAUTH2 ВИМКНЕНО
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=Ремонтувати
#flatten #flatten
flatten.title=Згладжування flatten.title=Згладжування
flatten.header=Згладжування PDF flatten.header=Згладжування PDF
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=Згладити flatten.submit=Згладити
@@ -736,6 +752,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.supportedFileTypes=Підтримувані типи файлів повинні включати нижченаведені, однак повний оновлений список підтримуваних форматів дивіться у документації LibreOffice. fileToPDF.supportedFileTypes=Підтримувані типи файлів повинні включати нижченаведені, однак повний оновлений список підтримуваних форматів дивіться у документації LibreOffice.
fileToPDF.submit=Перетворити у PDF fileToPDF.submit=Перетворити у PDF
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(наприклад, 1,3,2 або 4-8,2,10-12 або 2n
#multiTool #multiTool
multiTool.title=Мультіінструмент PDF multiTool.title=Мультіінструмент PDF
multiTool.header=Мультіінструмент PDF multiTool.header=Мультіінструмент PDF
multiTool.uploadPrompts=Будь ласка, завантажте PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=Переглянути PDF viewPdf.title=Переглянути PDF
@@ -941,6 +958,7 @@ 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
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=Версія
licenses.license=Ліцензія licenses.license=Ліцензія
# error #error
error.sorry=Вибачте за незручності! error.sorry=Вибачте за незручності!
error.needHelp=Потрібна допомога / Знайшли проблему? error.needHelp=Потрібна допомога / Знайшли проблему?
error.contactTip=Якщо у вас досі виникають проблеми, не соромтеся звертатися до нас за допомогою. Ви можете надіслати запит на нашій сторінці GitHub або зв'язатися з нами через Discord: error.contactTip=Якщо у вас досі виникають проблеми, не соромтеся звертатися до нас за допомогою. Ви можете надіслати запит на нашій сторінці GitHub або зв'язатися з нами через Discord:

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=用户未经过身份验证。
userNotFoundMessage=未找到用户。 userNotFoundMessage=未找到用户。
incorrectPasswordMessage=当前密码不正确。 incorrectPasswordMessage=当前密码不正确。
usernameExistsMessage=新用户名已存在。 usernameExistsMessage=新用户名已存在。
invalidUsernameMessage=用户名无效,用户名只能由字母字符和数字组成 invalidUsernameMessage=用户名无效,用户名只能包含字母、数字和以下特殊字符@._+- 或必须是有效的电子邮件地址
deleteCurrentUserMessage=无法删除当前登录的用户。 deleteCurrentUserMessage=无法删除当前登录的用户。
deleteUsernameExistsMessage=用户名不存在,无法删除。 deleteUsernameExistsMessage=用户名不存在,无法删除。
downgradeCurrentUserMessage=无法降级当前用户的角色
downgradeCurrentUserLongMessage=无法降级当前用户的角色。因此,当前用户将不会显示。
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=错误 error=错误
oops=哎呀! oops=哎呀!
help=帮助 help=帮助
@@ -67,6 +71,7 @@ visitGithub=访问Github仓库
donate=捐款 donate=捐款
color=颜色 color=颜色
sponsor=赞助 sponsor=赞助
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=验证
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=转换 navbar.favorite=Favorites
navbar.security=安全
navbar.other=其他
navbar.darkmode=暗模式 navbar.darkmode=暗模式
navbar.pageOps=页面操作 navbar.language=Languages
navbar.settings=设置 navbar.settings=设置
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=管理员用户控制设置
adminUserSettings.admin=管理员 adminUserSettings.admin=管理员
adminUserSettings.user=用户 adminUserSettings.user=用户
adminUserSettings.addUser=添加新用户 adminUserSettings.addUser=添加新用户
adminUserSettings.usernameInfo=用户名只能字母数字组成,不能包含空格或特殊字符 adminUserSettings.usernameInfo=用户名只能包含字母数字和以下特殊字符@._+-,或者必须是有效的电子邮件地址
adminUserSettings.roles=角色 adminUserSettings.roles=角色
adminUserSettings.role=角色 adminUserSettings.role=角色
adminUserSettings.actions=操作 adminUserSettings.actions=操作
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=演示用户(无自定义设置)
adminUserSettings.internalApiUser=内部API用户 adminUserSettings.internalApiUser=内部API用户
adminUserSettings.forceChange=强制用户在登录时更改用户名/密码 adminUserSettings.forceChange=强制用户在登录时更改用户名/密码
adminUserSettings.submit=保存用户 adminUserSettings.submit=保存用户
adminUserSettings.changeUserRole=更改用户角色
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=记住我
login.invalid=用户名或密码无效。 login.invalid=用户名或密码无效。
login.locked=您的账户已被锁定。 login.locked=您的账户已被锁定。
login.signinTitle=请登录 login.signinTitle=请登录
login.ssoSignIn=通过单点登录登录
login.oauth2AutoCreateDisabled=OAUTH2自动创建用户已禁用
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=修复
#flatten #flatten
flatten.title=展平 flatten.title=展平
flatten.header=展平 PDF flatten.header=展平 PDF
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=展平 flatten.submit=展平
@@ -736,6 +752,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.supportedFileTypes=支持的文件类型应该包括以下几种但是对于支持的格式的完整更新列表请参考LibreOffice文档。 fileToPDF.supportedFileTypes=支持的文件类型应该包括以下几种但是对于支持的格式的完整更新列表请参考LibreOffice文档。
fileToPDF.submit=转换为 PDF fileToPDF.submit=转换为 PDF
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(例如 1,3,2 或 4-8,2,10-12 或 2n-1
#multiTool #multiTool
multiTool.title=PDF多功能工具 multiTool.title=PDF多功能工具
multiTool.header=PDF多功能工具 multiTool.header=PDF多功能工具
multiTool.uploadPrompts=上传PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=浏览PDF viewPdf.title=浏览PDF
@@ -941,6 +958,7 @@ 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
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=版本
licenses.license=许可证 licenses.license=许可证
# error #error
error.sorry=对此问题感到抱歉! error.sorry=对此问题感到抱歉!
error.needHelp=需要帮助 / 发现问题? error.needHelp=需要帮助 / 发现问题?
error.contactTip=如果你仍然遇到问题不要犹豫向我们寻求帮助。你可以在我们的GitHub页面上提交工单或者通过Discord与我们联系 error.contactTip=如果你仍然遇到问题不要犹豫向我们寻求帮助。你可以在我们的GitHub页面上提交工单或者通过Discord与我们联系

View File

@@ -54,9 +54,13 @@ notAuthenticatedMessage=使用者未認證。
userNotFoundMessage=找不到使用者。 userNotFoundMessage=找不到使用者。
incorrectPasswordMessage=目前密碼不正確。 incorrectPasswordMessage=目前密碼不正確。
usernameExistsMessage=新使用者名稱已存在。 usernameExistsMessage=新使用者名稱已存在。
invalidUsernameMessage=使用者名無效,使用者名只能包含字母字元和數位 invalidUsernameMessage=使用者名無效,使用者名只能包含字母、數字和以下特殊字元@._+- 或必須是有效的電子郵件地址
deleteCurrentUserMessage=無法刪除目前登錄的使用者。 deleteCurrentUserMessage=無法刪除目前登錄的使用者。
deleteUsernameExistsMessage=使用者名不存在,無法刪除。 deleteUsernameExistsMessage=使用者名不存在,無法刪除。
downgradeCurrentUserMessage=無法降級目前使用者的角色
downgradeCurrentUserLongMessage=無法降級目前使用者的角色。因此,不會顯示目前的使用者。
userAlreadyExistsOAuthMessage=The user already exists as an OAuth2 user.
userAlreadyExistsWebMessage=The user already exists as an web user.
error=錯誤 error=錯誤
oops=哎呀! oops=哎呀!
help=幫助 help=幫助
@@ -67,6 +71,7 @@ visitGithub=訪問Github存儲庫
donate=捐贈 donate=捐贈
color=顏色 color=顏色
sponsor=贊助 sponsor=贊助
info=Info
@@ -100,12 +105,18 @@ pipelineOptions.validateButton=驗證
############# #############
# NAVBAR # # NAVBAR #
############# #############
navbar.convert=轉換 navbar.favorite=Favorites
navbar.security=安全
navbar.other=其他
navbar.darkmode=暗黑模式 navbar.darkmode=暗黑模式
navbar.pageOps=頁面操作 navbar.language=Languages
navbar.settings=設定 navbar.settings=設定
navbar.allTools=Tools
navbar.multiTool=Multi Tools
navbar.sections.organize=Organize
navbar.sections.convertTo=Convert to PDF
navbar.sections.convertFrom=Convert from PDF
navbar.sections.security=Sign & Security
navbar.sections.advance=Advanced
navbar.sections.edit=View & Edit
############# #############
# SETTINGS # # SETTINGS #
@@ -162,7 +173,7 @@ adminUserSettings.header=管理使用者控制設定
adminUserSettings.admin=管理員 adminUserSettings.admin=管理員
adminUserSettings.user=使用者 adminUserSettings.user=使用者
adminUserSettings.addUser=新增使用者 adminUserSettings.addUser=新增使用者
adminUserSettings.usernameInfo=使用者名只能包含字母和數位,不能包含空格或特殊字元 adminUserSettings.usernameInfo=使用者名只能包含字母、數字和以下特殊字元@._+-,或必須是有效的電子郵件地址
adminUserSettings.roles=角色 adminUserSettings.roles=角色
adminUserSettings.role=角色 adminUserSettings.role=角色
adminUserSettings.actions=操作 adminUserSettings.actions=操作
@@ -173,6 +184,8 @@ adminUserSettings.demoUser=示範用途的使用者(無自訂設定)
adminUserSettings.internalApiUser=內部 API 使用者 adminUserSettings.internalApiUser=內部 API 使用者
adminUserSettings.forceChange=強制使用者在登入時修改使用者名稱/密碼 adminUserSettings.forceChange=強制使用者在登入時修改使用者名稱/密碼
adminUserSettings.submit=儲存 adminUserSettings.submit=儲存
adminUserSettings.changeUserRole=更改使用者身份
adminUserSettings.authenticated=Authenticated
############# #############
# HOME-PAGE # # HOME-PAGE #
@@ -437,6 +450,8 @@ login.rememberme=記住我
login.invalid=使用者名稱或密碼無效。 login.invalid=使用者名稱或密碼無效。
login.locked=您的帳戶已被鎖定。 login.locked=您的帳戶已被鎖定。
login.signinTitle=請登入 login.signinTitle=請登入
login.ssoSignIn=透過織網單一簽入
login.oauth2AutoCreateDisabled=OAUTH2自動建立使用者已停用
#auto-redact #auto-redact
@@ -689,6 +704,7 @@ repair.submit=修復
#flatten #flatten
flatten.title=平坦化 flatten.title=平坦化
flatten.header=PDF 平坦化 flatten.header=PDF 平坦化
flatten.flattenOnlyForms=Flatten only forms
flatten.submit=平坦化 flatten.submit=平坦化
@@ -736,6 +752,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.supportedFileTypes=支援的檔案類型應包括以下內容,但要獲得完整的更新支援格式列表,請參閱 LibreOffice 的文件 fileToPDF.supportedFileTypes=支援的檔案類型應包括以下內容,但要獲得完整的更新支援格式列表,請參閱 LibreOffice 的文件
fileToPDF.submit=轉換為 PDF fileToPDF.submit=轉換為 PDF
@@ -788,7 +805,7 @@ pdfOrganiser.placeholder=(例如 1,3,2 或 4-8,2,10-12 或 2n-1
#multiTool #multiTool
multiTool.title=PDF 多工具 multiTool.title=PDF 多工具
multiTool.header=PDF 多工具 multiTool.header=PDF 多工具
multiTool.uploadPrompts=Please Upload PDF multiTool.uploadPrompts=File Name
#view pdf #view pdf
viewPdf.title=檢視 PDF viewPdf.title=檢視 PDF
@@ -941,6 +958,7 @@ 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
#PDFToWord #PDFToWord
@@ -1042,7 +1060,7 @@ licenses.version=版本
licenses.license=許可證 licenses.license=許可證
# error #error
error.sorry=對於這個問題,我們感到抱歉! error.sorry=對於這個問題,我們感到抱歉!
error.needHelp=需要幫助/發現了一個問題? error.needHelp=需要幫助/發現了一個問題?
error.contactTip=如果你仍然遇到問題請不要猶豫隨時向我們尋求幫助。你可以在我們的GitHub頁面提交工單或通過Discord與我們聯繋 error.contactTip=如果你仍然遇到問題請不要猶豫隨時向我們尋求幫助。你可以在我們的GitHub頁面提交工單或通過Discord與我們聯繋

View File

@@ -4,9 +4,21 @@
security: security:
enableLogin: false # set to 'true' to enable login enableLogin: false # set to 'true' to enable login
csrfDisabled: true 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:
# username: "admin" # Initial username for the first login
# password: "stirling" # Initial password for the first login
# oauth2:
# enabled: false # set to 'true' to enable login (Note: enableLogin must also be 'true' for this to work)
# issuer: "" # set to any provider that supports OpenID Connect Discovery (/.well-known/openid-configuration) end-point
# clientId: "" # Client ID from your provider
# clientSecret: "" # Client Secret from your provider
# autoCreateUser: false # set to 'true' to allow auto-creation of non-existing users
# useAsUsername: "email" # Default is 'email'; custom fields can be used as the username
# 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)
@@ -14,11 +26,12 @@ system:
enableAlphaFunctionality: false # Set to enable functionality which might need more testing before it fully goes live (This feature might make no changes) enableAlphaFunctionality: false # Set to enable functionality which might need more testing before it fully goes live (This feature might make no changes)
showUpdate: true # see when a new update is available showUpdate: true # see when a new update is available
showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true' showUpdateOnlyAdmin: false # Only admins can see when a new update is available, depending on showUpdate it must be set to 'true'
customHTMLFiles: false # enable to have files placed in /customFiles/templates override the existing template html files
#ui: ui:
# appName: exampleAppName # Application's visible name appName: null # Application's visible name
# homeDescription: I am a description # Short description or tagline shown on homepage. homeDescription: null # Short description or tagline shown on homepage.
# appNameNavbar: navbarName # Name displayed on the navigation bar appNameNavbar: null # 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'])
@@ -26,3 +39,7 @@ endpoints:
metrics: metrics:
enabled: true # 'true' to enable Info APIs (`/api/*`) endpoints, 'false' to disable enabled: true # 'true' to enable Info APIs (`/api/*`) endpoints, 'false' to disable
# Automatically Generated Settings (Do Not Edit Directly)
AutomaticallyGenerated:
key: example

View File

@@ -81,6 +81,13 @@
"moduleLicense": "GNU Lesser General Public License v3 (LGPL-v3)", "moduleLicense": "GNU Lesser General Public License v3 (LGPL-v3)",
"moduleLicenseUrl": "http://www.gnu.org/licenses/lgpl-3.0.html" "moduleLicenseUrl": "http://www.gnu.org/licenses/lgpl-3.0.html"
}, },
{
"moduleName": "com.github.stephenc.jcip:jcip-annotations",
"moduleUrl": "http://stephenc.github.com/jcip-annotations",
"moduleVersion": "1.0-1",
"moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
},
{ {
"moduleName": "com.github.vladimir-bukhtoyarov:bucket4j-core", "moduleName": "com.github.vladimir-bukhtoyarov:bucket4j-core",
"moduleUrl": "http://github.com/vladimir-bukhtoyarov/bucket4j/bucket4j-core", "moduleUrl": "http://github.com/vladimir-bukhtoyarov/bucket4j/bucket4j-core",
@@ -109,6 +116,34 @@
"moduleLicense": "LGPL", "moduleLicense": "LGPL",
"moduleLicenseUrl": "http://www.martiansoftware.com/jsap/license.html" "moduleLicenseUrl": "http://www.martiansoftware.com/jsap/license.html"
}, },
{
"moduleName": "com.nimbusds:content-type",
"moduleUrl": "https://connect2id.com",
"moduleVersion": "2.2",
"moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
},
{
"moduleName": "com.nimbusds:lang-tag",
"moduleUrl": "https://connect2id.com/",
"moduleVersion": "1.7",
"moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
},
{
"moduleName": "com.nimbusds:nimbus-jose-jwt",
"moduleUrl": "https://connect2id.com",
"moduleVersion": "9.24.4",
"moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.txt"
},
{
"moduleName": "com.nimbusds:oauth2-oidc-sdk",
"moduleUrl": "https://bitbucket.org/connect2id/oauth-2.0-sdk-with-openid-connect-extensions",
"moduleVersion": "9.43.3",
"moduleLicense": "Apache License, version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0.html"
},
{ {
"moduleName": "com.opencsv:opencsv", "moduleName": "com.opencsv:opencsv",
"moduleUrl": "http://opencsv.sf.net", "moduleUrl": "http://opencsv.sf.net",
@@ -335,6 +370,20 @@
"moduleLicense": "Apache License, Version 2.0", "moduleLicense": "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": "net.minidev:accessors-smart",
"moduleUrl": "https://urielch.github.io/",
"moduleVersion": "2.5.0",
"moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
},
{
"moduleName": "net.minidev:json-smart",
"moduleUrl": "https://urielch.github.io/",
"moduleVersion": "2.5.0",
"moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
},
{ {
"moduleName": "org.antlr:antlr4-runtime", "moduleName": "org.antlr:antlr4-runtime",
"moduleUrl": "https://www.antlr.org/", "moduleUrl": "https://www.antlr.org/",
@@ -547,6 +596,13 @@
"moduleLicense": "Public Domain, per Creative Commons CC0", "moduleLicense": "Public Domain, per Creative Commons CC0",
"moduleLicenseUrl": "http://creativecommons.org/publicdomain/zero/1.0/" "moduleLicenseUrl": "http://creativecommons.org/publicdomain/zero/1.0/"
}, },
{
"moduleName": "org.ow2.asm:asm",
"moduleUrl": "http://asm.ow2.org",
"moduleVersion": "9.3",
"moduleLicense": "The Apache Software License, Version 2.0",
"moduleLicenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.txt"
},
{ {
"moduleName": "org.slf4j:jul-to-slf4j", "moduleName": "org.slf4j:jul-to-slf4j",
"moduleUrl": "http://www.slf4j.org", "moduleUrl": "http://www.slf4j.org",
@@ -663,6 +719,13 @@
"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": "org.springframework.boot:spring-boot-starter-oauth2-client",
"moduleUrl": "https://spring.io/projects/spring-boot",
"moduleVersion": "3.2.4",
"moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
},
{ {
"moduleName": "org.springframework.boot:spring-boot-starter-security", "moduleName": "org.springframework.boot:spring-boot-starter-security",
"moduleUrl": "https://spring.io/projects/spring-boot", "moduleUrl": "https://spring.io/projects/spring-boot",
@@ -726,6 +789,27 @@
"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": "org.springframework.security:spring-security-oauth2-client",
"moduleUrl": "https://spring.io/projects/spring-security",
"moduleVersion": "6.2.3",
"moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
},
{
"moduleName": "org.springframework.security:spring-security-oauth2-core",
"moduleUrl": "https://spring.io/projects/spring-security",
"moduleVersion": "6.2.3",
"moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
},
{
"moduleName": "org.springframework.security:spring-security-oauth2-jose",
"moduleUrl": "https://spring.io/projects/spring-security",
"moduleVersion": "6.2.3",
"moduleLicense": "Apache License, Version 2.0",
"moduleLicenseUrl": "https://www.apache.org/licenses/LICENSE-2.0"
},
{ {
"moduleName": "org.springframework.security:spring-security-web", "moduleName": "org.springframework.security:spring-security-web",
"moduleUrl": "https://spring.io/projects/spring-security", "moduleUrl": "https://spring.io/projects/spring-security",

View File

@@ -1,141 +0,0 @@
/* Dark Mode Styles */
body,
select,
textarea {
--body-background-color: 51, 51, 51;
--base-font-color: 255, 255, 255;
background-color: rgb(var(--body-background-color)) !important;
color: rgb(var(--base-font-color)) !important;
}
.card {
background-color: rgb(var(--body-background-color)) !important;
border: 1px solid #999;
color: rgb(var(--base-font-color)) !important;
}
a {
color: #add8e6;
}
a:hover {
color: #87ceeb; /* Slightly brighter blue on hover for accessibility */
}
.dark-card {
background-color: rgb(var(--body-background-color)) !important;
color: rgb(var(--base-font-color)) !important;
}
.jumbotron {
background-color: #222; /* or any other dark color */
color: rgb(var(--base-font-color)) !important; /* or any other light color */
}
.list-group {
background-color: #222 !important;
color: rgb(var(--base-font-color)) !important;
}
.list-group-item {
background-color: #222 !important;
color: rgb(var(--base-font-color)) !important;
}
#support-section {
background-color: #444 !important;
}
#pages-container-wrapper {
--background-color: rgba(255, 255, 255, 0.046) !important;
--scroll-bar-color: #4c4c4c !important;
--scroll-bar-thumb: #d3d3d3 !important;
--scroll-bar-thumb-hover: rgb(var(--base-font-color)) !important;
}
.favorite-icon img {
filter: brightness(0) invert(1) !important;
}
table thead {
background-color: #333 !important;
border: 1px solid #444;
}
table th,
table td {
border: 1px solid #444 !important;
color: white;
}
.btn {
background-color: #444 !important;
border: none;
color: #fff !important;
}
.btn-primary {
background-color: #007bff !important;
border: none;
color: #fff !important;
}
.btn-secondary {
background-color: #6c757d !important;
border: none;
color: #fff !important;
}
.btn-info {
background-color: #17a2b8 !important;
border: none;
color: #fff !important;
}
.btn-danger {
background-color: #dc3545 !important;
border: none;
color: #fff !important;
}
.btn-warning {
background-color: #ffc107 !important;
border: none;
color: #000 !important;
}
.btn-outline-secondary {
color: #fff !important;
border-color: #fff;
}
.btn-outline-secondary:hover {
background-color: #444 !important;
color: #007bff !important;
border-color: #007bff;
}
.blackwhite-icon {
filter: brightness(0) invert(1);
}
hr {
border-color: rgba(255, 255, 255, 0.6); /* semi-transparent white */
background-color: rgba(255, 255, 255, 0.6); /* for some browsers that might use background instead of border for <hr> */
}
.modal-content {
color: #fff !important;
border-color: #fff;
}
.global-buttons-container input {
background-color: #323948;
caret-color: #ffffff;
color: #ffffff;
}
.global-buttons-container input::placeholder {
color: #ffffff;
}
.global-buttons-container input:disabled::-webkit-input-placeholder {
/* WebKit browsers */
color: #6e6865;
}
.global-buttons-container input:disabled:-moz-placeholder {
/* Mozilla Firefox 4 to 18 */
color: #6e6865;
}
.global-buttons-container input:disabled::-moz-placeholder {
/* Mozilla Firefox 19+ */
color: #6e6865;
}
.global-buttons-container input:disabled:-ms-input-placeholder {
/* Internet Explorer 10+ */
color: #6e6865;
}

View File

@@ -1,17 +1,8 @@
h1 {
text-align: center;
margin-top: 10%;
}
p { p {
text-align: center; text-align: center;
margin-top: 2em; margin-top: 2em;
} }
.button:hover {
background-color: #005b7f;
}
.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));
@@ -31,58 +22,21 @@ p {
flex: 1; flex: 1;
} }
#support-section {
background-color: #f9f9f9;
padding: 4rem;
margin-top: 1rem;
text-align: center;
}
#support-section h1 {
margin-top: 0;
}
#support-section p {
margin-top: 0;
}
#button-group { #button-group {
display: flex; display: flex;
justify-content: center; justify-content: center;
flex-wrap: wrap; flex-wrap: wrap;
} }
#home-button,
#github-button, #github-button,
#discord-button { #discord-button {
display: inline-block; display: inline-block;
padding: 1rem 2rem; padding: 1rem 2rem;
margin: 1rem; margin: 1rem;
background-color: #008cba;
color: #fff;
font-size: 1.2rem; font-size: 1.2rem;
text-align: center; text-align: center;
text-decoration: none; text-decoration: none;
border-radius: 3rem; border-radius: 3rem;
transition: all 0.3s ease-in-out; transition: all 0.3s ease-in-out;
} }
#github-button:hover,
#discord-button:hover,
.home-button:hover {
background-color: #005b7f;
}
.home-button {
display: block;
width: 200px;
height: 50px;
margin: 2em auto;
background-color: #008cba;
color: white;
text-align: center;
line-height: 50px;
text-decoration: none;
font-weight: bold;
border-radius: 25px;
transition: all 0.3s ease-in-out;
}

View File

@@ -1,5 +1,6 @@
#errorContainer { #errorContainer {
margin: 20px; /* adjust this value as needed */ margin: 1rem 0rem 2rem;
border-radius: 3rem;
} }
#helpModalDialog { #helpModalDialog {
@@ -18,7 +19,7 @@
} }
#helpModal .button:hover { #helpModal .button:hover {
background-color: #005b7f; background-color: var(--md-sys-color-primary);
} }
#helpModal .features-container { #helpModal .features-container {
@@ -40,58 +41,21 @@
flex: 1; flex: 1;
} }
#support-section {
background-color: #f9f9f9;
padding: 4rem;
margin-top: 1rem;
text-align: center;
}
#support-section h1 {
margin-top: 0;
}
#support-section p {
margin-top: 0;
}
#button-group { #button-group {
display: flex; display: flex;
justify-content: center; justify-content: center;
flex-wrap: wrap; flex-wrap: wrap;
} }
#home-button,
#github-button, #github-button,
#discord-button { #discord-button {
display: inline-block; display: inline-block;
padding: 1rem 2rem; padding: 1rem 2rem;
margin: 1rem; margin: 1rem;
background-color: #008cba;
color: #fff;
font-size: 1.2rem; font-size: 1.2rem;
text-align: center; text-align: center;
text-decoration: none; text-decoration: none;
border-radius: 3rem; border-radius: 3rem;
transition: all 0.3s ease-in-out; transition: all 0.3s ease-in-out;
} }
#github-button:hover,
#discord-button:hover,
.home-button:hover {
background-color: #005b7f;
}
.home-button {
display: block;
width: 200px;
height: 50px;
margin: 2em auto;
background-color: #008cba;
color: white;
text-align: center;
line-height: 50px;
text-decoration: none;
font-weight: bold;
border-radius: 25px;
transition: all 0.3s ease-in-out;
}

View File

@@ -10,11 +10,15 @@
display: flex; display: flex;
align-items: center; /* Center children horizontally */ align-items: center; /* Center children horizontally */
flex-grow: 1; flex-grow: 1;
flex-direction: column;
} }
.footer-powered-by { .footer-powered-by {
margin-top: auto; /* Pushes the text to the bottom */ margin-top: auto; /* Pushes the text to the bottom */
color: grey;
text-align: center; /* Centers the text inside the div */ text-align: center; /* Centers the text inside the div */
width: 100%; /* Full width to center the text properly */ width: 100%; /* Full width to center the text properly */
} }
.footer-icon {
font-size: 2rem;
}

View File

@@ -1,18 +1,19 @@
#searchBar { #searchBar {
background-image: url("../images/search.svg"); color: var(--md-sys-color-on-surface);
background-position: 16px 16px; background-color: var(--md-sys-color-surface-container-low);
background-repeat: no-repeat;
width: 100%; width: 100%;
font-size: 16px; font-size: 16px;
margin-bottom: 12px; margin-bottom: 2rem;
padding: 12px 20px 12px 40px; padding: 0.75rem 3.5rem;
border: 1px solid #ddd; border: 0.1rem solid var(--md-sys-color-outline-variant);
border-radius: 3rem;
outline-color: var(--md-sys-color-outline-variant);
} }
.dark-mode-search {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' hei… 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z'/%3E%3C/svg%3E") !important; .search-icon {
color: #f8f9fa !important; position: absolute;
background-color: #212529 !important; margin: 0.75rem 1rem;
border-color: #343a40 !important; border: 0.1rem solid transparent;
} }
.features-container { .features-container {
@@ -22,23 +23,23 @@
} }
.feature-card { .feature-card {
border: 2px solid rgba(0, 0, 0, 0.25); border: 2px solid var(--md-sys-color-surface-5);
border-radius: 0.25rem; border-radius: 2rem;
padding: 1.25rem; padding: 1.25rem;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
background: rgba(13, 110, 253, 0.05); background: var(--md-sys-color-surface-5);
transition: transition:
transform 0.3s, transform 0.3s,
border 0.3s; border 0.3s;
transform-origin: center center; transform-origin: center center;
outline: 2px solid transparent; outline: 0px solid transparent;
} }
.feature-card a { .feature-card a {
text-decoration: none; text-decoration: none;
color: inherit; color: var(--md-sys-color-on-surface);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
width: 100%; width: 100%;
@@ -50,44 +51,53 @@
} }
.feature-card:hover { .feature-card:hover {
outline: 1px solid rgba(0, 0, 0, 0.5);
cursor: pointer; cursor: pointer;
transform: scale(1.1); transform: scale(1.1);
box-shadow: var(--md-sys-elevation-3);
} }
.feature-card:hover .card-title {
text-decoration: underline;
}
.card-title.text-primary { .card-title.text-primary {
color: #000; /* Replace with your desired shade of blue */ color: #000;
} }
.home-card-icon { .home-card-icon {
width: 30px; width: 3rem;
height: 30px; height: 3rem;
transform: translateY(-5px); transform: translateY(-5px);
} }
.home-card-icon-colour {
filter: invert(0.2) sepia(2) saturate(50) hue-rotate(190deg);
}
.favorite-icon { .favorite-icon {
display: none; display: none;
position: absolute; position: absolute;
top: 10px; top: 10px;
right: 10px; right: 10px;
color: var(--md-sys-color-secondary);
}
#tool-icon {
height: 100%;
}
#tool-text {
margin: 0.5rem 0.5rem 0rem;
}
.card-title {
margin-bottom: 1rem;
} }
/* Only show the favorite icons when the parent card is being hovered over */ /* Only show the favorite icons when the parent card is being hovered over */
.feature-card:hover .favorite-icon { .feature-card:hover .favorite-icon {
display: block; display: block;
} }
.favorite-icon img { .favorite-icon img {
filter: brightness(0); filter: brightness(0) invert(var(--md-theme-filter-color));
} }
.jumbotron { .jumbotron {
padding: 3rem 3rem; /* Reduce vertical padding */ padding: 3rem 3rem;
/* Reduce vertical padding */
} }
.lookatme { .lookatme {
@@ -124,3 +134,21 @@
opacity: 0; opacity: 0;
} }
} }
.update-notice {
animation: scale 1s infinite alternate;
}
@keyframes scale {
0% {
transform: scale(0.96);
}
100% {
transform: scale(1);
}
}
.hidden {
visibility: hidden;
}

View File

@@ -1,23 +0,0 @@
/* Dark Mode Styles */
body {
--body-background-color: 255, 255, 255;
--base-font-color: 33, 37, 41;
}
.global-buttons-container input {
background-color: #ffffff;
/*caret-color: #ffffff;*/
/*color: #ffffff;*/
}
/*.global-buttons-container input:disabled::-webkit-input-placeholder { !* WebKit browsers *!*/
/* color: #98A0AB;*/
/*}*/
/*.global-buttons-container input:disabled:-moz-placeholder { !* Mozilla Firefox 4 to 18 *!*/
/* color: #98A0AB;*/
/*}*/
/*.global-buttons-container input:disabled::-moz-placeholder { !* Mozilla Firefox 19+ *!*/
/* color: #98A0AB;*/
/*}*/
/*.global-buttons-container input:disabled:-ms-input-placeholder { !* Internet Explorer 10+ *!*/
/* color: #98A0AB;*/
/*}*/

View File

@@ -8,7 +8,6 @@ body {
align-items: center; align-items: center;
padding-top: 40px; padding-top: 40px;
padding-bottom: 40px; padding-bottom: 40px;
background-color: #f5f5f5;
} }
.form-signin { .form-signin {
@@ -37,6 +36,7 @@ body {
border-top-left-radius: 0; border-top-left-radius: 0;
border-top-right-radius: 0; border-top-right-radius: 0;
} }
.container-flex { .container-flex {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -44,41 +44,22 @@ body {
width: 100%; /* Set width to 100% */ width: 100%; /* Set width to 100% */
align-items: center; /* Center its children horizontally */ align-items: center; /* Center its children horizontally */
} }
.footer-bottom { .footer-bottom {
margin-top: auto; margin-top: auto;
} }
body.light-mode input:-webkit-autofill,
body.light-mode input:-webkit-autofill:hover, .form-control {
body.light-mode input:-webkit-autofill:focus, border-radius: 1.25rem !important;
body.light-mode input:-webkit-autofill:active {
-webkit-text-fill-color: #212529; /* Dark font color */
-webkit-box-shadow: 0 0 0 1000px #f8f9fa inset; /* Light background color */
} }
/* Dark Mode */ .form-signin .form-floating {
body.dark-mode input:-webkit-autofill, margin: 1rem 0px;
body.dark-mode input:-webkit-autofill:hover,
body.dark-mode input:-webkit-autofill:focus,
body.dark-mode input:-webkit-autofill:active {
-webkit-text-fill-color: #f8f9fa; /* Light font color */
-webkit-box-shadow: 0 0 0 1000px #212529 inset; /* Dark background color */
}
/* Light Mode */
body.light-mode .form-floating > input:focus + label {
color: #212529 !important; /* Dark text for light background */
} }
/* Dark Mode */ input[type="checkbox" i] {
body.dark-mode .form-floating > input:focus + label { margin: 0px 5px;
color: #fff !important; /* Light text for dark background */ vertical-align: middle;
}
body.light-mode .form-floating > label {
color: #212529 !important; /* Dark text for light background */
}
body.dark-mode .form-floating > label {
color: #fff !important; /* Light text for dark background */
} }
/* Removing default styles for ul and li */ /* Removing default styles for ul and li */

View File

@@ -3,43 +3,80 @@
margin: 0 auto; margin: 0 auto;
} }
.global-buttons-container { label {
text-align: left;
display: block;
padding: 0rem 0.25rem;
font-size: 1.25rem;
}
.form-control {
border-radius: 16px !important;
padding: 0.75rem;
border: 1px solid var(--theme-color-outline-variant);
}
.mt-action-bar {
display: flex; display: flex;
gap: 10px; gap: 10px;
align-items: start; align-items: start;
background-color: var(--md-sys-color-surface-5);
background-color: rgba(13, 110, 253, 0.1); border: none;
border: 1px solid rgba(0, 0, 0, 0.25);
backdrop-filter: blur(2px); backdrop-filter: blur(2px);
top: 10px; top: 10px;
z-index: 10; z-index: 10;
padding: 10px; padding: 1.25rem;
border-radius: 8px; border-radius: 2rem;
} margin: 0px 25px;
.global-buttons-container > * {
padding: 0.6rem 0.75rem;
} }
.global-buttons-container svg { .mt-action-bar>* {
padding-bottom: 0.5rem;
}
.mt-action-bar svg,
.mt-action-btn svg {
width: 20px; width: 20px;
height: 20px; height: 20px;
} }
.mt-action-bar .mt-filename {
width: 100%;
}
.mt-action-btn {
display: flex;
gap: 10px;
align-items: start;
top: 10px;
z-index: 10;
padding: 12px 0px 0px;
width: 100%;
}
.mt-action-btn .btn {
width: 3rem;
height: 3rem;
border-radius: 20px;
padding: 0;
}
#export-button { #export-button {
margin-left: auto; margin-left: auto;
} }
.bg-card {
background-color: var(--md-sys-color-surface-5);
border-radius: 3rem;
padding: 25px 0 0;
}
#pages-container-wrapper { #pages-container-wrapper {
--background-color: rgba(0, 0, 0, 0.025);
--scroll-bar-color: #f1f1f1;
--scroll-bar-thumb: #888;
--scroll-bar-thumb-hover: #555;
background-color: var(--background-color);
width: 100%; width: 100%;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
padding: 10px 25px; padding: 1rem;
border-radius: 10px; border-radius: 25px;
overflow-y: hidden; overflow-y: hidden;
overflow-x: auto; overflow-x: auto;
min-height: 275px; min-height: 275px;
@@ -47,11 +84,11 @@
} }
#pages-container { #pages-container {
margin: auto;
gap: 0px; gap: 0px;
display: flex; display: flex;
align-items: center; flex-wrap: wrap;
justify-content: center; margin-left: -15px;
margin-right: -15px;
} }
/* width */ /* width */
@@ -86,6 +123,58 @@
position: relative; position: relative;
user-select: none; user-select: none;
transition: width 1s linear; transition: width 1s linear;
margin-top: 16px;
margin-bottom: 16px;
}
/* Pushes the last item to the left */
.page-container:last-child {
margin-right: auto;
}
.page-container:last-child:lang(ar),
/* Arabic */
.page-container:last-child:lang(he),
/* Hebrew */
.page-container:last-child:lang(fa),
/* Persian */
.page-container:last-child:lang(ur),
/* Urdu */
.page-container:last-child:lang(ckb),
/* Sorani Kurdish */
.page-container:last-child:lang(ks),
/* Kashmiri */
.page-container:last-child:lang(kk),
/* Kazakh */
.page-container:last-child:lang(uz),
/* Uzbek */
.page-container:last-child:lang(ky),
/* Kyrgyz */
.page-container:last-child:lang(bal),
/* Baluchi */
.page-container:last-child:lang(dv),
/* Divehi */
.page-container:last-child:lang(ps),
/* Pashto */
.page-container:last-child:lang(sdg),
/* Southern Kurdish */
.page-container:last-child:lang(syr),
/* Syriac */
.page-container:last-child:lang(mzn),
/* Mazanderani */
.page-container:last-child:lang(tgl),
/* Tagalog */
.page-container:last-child:lang(pnb),
/* Western Punjabi */
.page-container:last-child:lang(ug),
/* Uyghur */
.page-container:last-child:lang(nqo),
/* N'Ko */
.page-container:last-child:lang(bqi)
/* Bakhtiari */
{
margin-left: auto !important;
margin-right: 0 !important;
} }
.page-container img { .page-container img {
@@ -109,11 +198,15 @@
.page-number { .page-number {
position: absolute; position: absolute;
top: 5px; top: 5px;
right: 5px; right: 0px;
color: white; color: var(--md-sys-color-on-surface);
background-color: #007bff; /* Primary blue color */ background-color: var(--md-sys-color-surface-5);
padding: 3px 6px; padding: 6px 8px;
border-radius: 4px; border-radius: 8px;
font-size: 12px; font-size: 16px;
z-index: 2; z-index: 2;
} }
.tool-header {
margin: 0.5rem 1rem 2rem;
}

View File

@@ -7,28 +7,18 @@
} }
#navbarSearch.show { #navbarSearch.show {
max-height: 300px; /* Adjust this to your desired max height */ max-height: 300px;
} /* Adjust this to your desired max height */
#searchForm {
width: 200px; /* Adjust this value as needed */
}
/* Style the search results to match the navbar */
#searchResults {
max-height: 200px; /* Adjust this value as needed */
overflow-y: auto;
width: 100%;
max-width: 300px; /* Adjust to your preferred width */
transition: height 0.3s ease; /* Smooth height transition */
} }
#searchResults .dropdown-item { #searchResults .dropdown-item {
display: flex; display: flex;
align-items: center; align-items: center;
white-space: nowrap; white-space: nowrap;
height: 50px; /* Fixed height */ height: 50px;
overflow: hidden; /* Hide overflow */ /* Fixed height */
overflow: hidden;
/* Hide overflow */
} }
#searchResults .icon { #searchResults .icon {
@@ -37,40 +27,34 @@
#searchResults .icon-text { #searchResults .icon-text {
display: inline; display: inline;
overflow: hidden; /* Hide overflow */ overflow: hidden;
text-overflow: ellipsis; /* Add ellipsis for long text */ /* Hide overflow */
text-overflow: ellipsis;
/* Add ellipsis for long text */
} }
#search-icon i { #search-icon i {
font-size: 24px; /* Adjust this to your desired size */ font-size: 24px;
/* Adjust this to your desired size */
transition: color 0.3s; transition: color 0.3s;
} }
#search-icon:hover i { #search-icon:hover i {
color: #666; /* Adjust this to your hover color */ color: #666;
/* Adjust this to your hover color */
} }
.search-input { .search-input {
transition: transition: border 0.3s, box-shadow 0.3s;
border 0.3s,
box-shadow 0.3s;
} }
.search-input:focus { .search-input:focus {
border-color: #666; /* Adjust this to your focus color */ border-color: #666;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); /* Adjust this to your desired shadow */ /* Adjust this to your focus color */
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
/* Adjust this to your desired shadow */
} }
/* Set a fixed height and styling for each search result item */
.search-results a {
display: flex;
align-items: center;
gap: 10px; /* space between icon and text */
height: 40px; /* Adjust based on your design */
overflow: hidden; /* Prevent content from overflowing */
white-space: nowrap; /* Prevent text from wrapping to next line */
text-overflow: ellipsis; /* Truncate text if it's too long */
}
.main-icon { .main-icon {
width: 36px; width: 36px;
@@ -79,34 +63,59 @@
transform: translateY(-2px); transform: translateY(-2px);
} }
.icon { .nav-icon {
width: 16px;
height: 16px;
vertical-align: middle; vertical-align: middle;
transform: translateY(-2px); font-size: 2rem !important;
padding: 0.25rem;
border-radius: 1rem;
} }
.icon + .icon { .icon+.icon {
margin-left: -4px; margin-left: -4px;
} }
.icon-text { .icon-text {
margin-left: 4px; margin-left: 4px;
margin-right: 4px;
display: inline-flex;
flex-direction: column;
justify-content: space-between;
vertical-align: middle;
}
.dropdown-item .icon-text {
text-wrap: wrap;
word-break: break-word;
width: 80%;
}
span.icon-text::after {
content: attr(data-text);
content: attr(data-text) / "";
font-weight: 600;
height: 0;
visibility: hidden;
overflow: hidden;
user-select: none;
pointer-events: none;
} }
.nav-item-separator { .nav-item-separator {
position: relative; position: relative;
margin: 0 4px; /* Adjust the margin as needed */ margin: 0 4px;
/* Adjust the margin as needed */
} }
.nav-item-separator::before { .nav-item-separator::before {
content: ""; content: "";
position: absolute; position: absolute;
left: 0; left: 0;
top: 10%; /* Adjust the top and bottom margins as needed */ top: 10%;
/* Adjust the top and bottom margins as needed */
bottom: 10%; bottom: 10%;
width: 1px; width: 1px;
background-color: #ccc; /* Adjust the color as needed */ background-color: #ccc;
/* Adjust the color as needed */
} }
.navbar-icon { .navbar-icon {
@@ -114,3 +123,170 @@
height: 20px; height: 20px;
transform: translateY(-2px); transform: translateY(-2px);
} }
.navbar-toggler {
color: var(--md-sys-color-on-surface-variant);
}
.dropdown-menu.scrollable-y {
overflow-y: scroll;
height: 360px;
}
/* Dropdown Scrollbar*/
.scrollable-y {
overflow-y: scroll;
height: 360px;
}
.scrollable-y::-webkit-scrollbar {
background: transparent;
width: 0.7rem;
}
.scrollable-y::-webkit-scrollbar-track {
background: transparent;
}
.scrollable-y::-webkit-scrollbar-thumb {
border-radius: 2rem;
background-color: var(--md-sys-color-surface-5);
border: 3px solid var(--md-sys-color-surface-5);
}
/* Mega Menu */
.dropdown-mega .dropdown-menu {
width: 98%;
}
.dropdown-mega .title {
padding-bottom: 1rem;
margin: 0;
}
.dropdown-menu .list-group {
padding: 1rem;
}
.mega-content .dropdown-item:focus .nav-icon,
.mega-content .dropdown-item:hover .nav-icon,
.mega-content .dropdown-item.active .nav-icon {
background-color: transparent;
}
.dropdown-item:focus.sign,
.dropdown-item:hover.sign,
.dropdown-item.active.sign {
color: var(--md-nav-on-section-color-sign);
background-color: var(--md-nav-section-color-sign);
}
.dropdown-item:focus.organize,
.dropdown-item:hover.organize,
.dropdown-item.active.organize {
color: var(--md-nav-on-section-color-organize);
background-color: var(--md-nav-section-color-organize);
}
.dropdown-item:focus.convert,
.dropdown-item:hover.convert,
.dropdown-item.active.convert {
color: var(--md-nav-on-section-color-convert);
background-color: var(--md-nav-section-color-convert);
}
.dropdown-item:focus.image,
.dropdown-item:hover.image,
.dropdown-item.active.image {
color: var(--md-nav-on-section-color-image);
background-color: var(--md-nav-section-color-image);
}
.dropdown-item:focus.word,
.dropdown-item:hover.word,
.dropdown-item.active.word {
color: var(--md-nav-on-section-color-word);
background-color: var(--md-nav-section-color-word);
}
.dropdown-item:focus.ppt,
.dropdown-item:hover.ppt,
.dropdown-item.active.ppt {
color: var(--md-nav-on-section-color-ppt);
background-color: var(--md-nav-section-color-ppt);
}
.dropdown-item:focus.security,
.dropdown-item:hover.security,
.dropdown-item.active.security {
color: var(--md-nav-on-section-color-security);
background-color: var(--md-nav-section-color-security);
}
.dropdown-item:focus.other,
.dropdown-item:hover.other,
.dropdown-item.active.other {
color: var(--md-nav-on-section-color-other);
background-color: var(--md-nav-section-color-other);
}
.dropdown-item:focus.advance,
.dropdown-item:hover.advance,
.dropdown-item.active.advance {
color: var(--md-nav-on-section-color-advance);
background-color: var(--md-nav-section-color-advance);
}
/* Dropdown min-width */
.dropdown-mw-28 {
min-width: 280px;
}
.dropdown-mw-20 {
min-width: 200px;
}
/* Dropdown open on hover */
.dropdown-menu {
padding-top: 0.5rem;
top: auto;
left: auto;
right: 0;
}
.dropdown-menu[data-bs-popper] {
top: auto;
left: auto;
right: 0;
margin-top: 0 !important;
}
.dropdown-menu-wrapper {
padding: 1.5rem 0;
border-radius: 1rem;
color: var(--md-sys-color-on-surface);
background-color: var(--md-sys-color-surface-container);
border: 1px solid var(--md-sys-color-surface-5);
box-shadow: var(--md-sys-elevation-2);
}
.dropdown-menu-tp {
color: transparent;
background-color: transparent;
border: none;
box-shadow: none;
}
.icon-hide {
display: inline-flex;
}
@media (min-width:992px) {
.dropdown:hover .dropdown-menu {
display: block;
margin-top: 0;
}
.icon-hide {
display: none;
}
}

View File

@@ -9,19 +9,33 @@
opacity: 1; opacity: 1;
} }
.pdf-actions_button-container > * { .pdf-actions_button-container>* {
padding: 0.25rem 0.5rem; padding: 0.25rem 0.5rem;
margin: 3px;
display: block; display: block;
} }
.pdf-actions_button-container>*:focus {
box-shadow: none !important;
}
.pdf-actions_button-container .btn {
border-radius: 12px;
}
.pdf-actions_button-container> :first-child,
.pdf-actions_container:first-child>.pdf-actions_button-container> :first-child+* {
border-radius: 12px 0px 0px 12px;
}
.pdf-actions_container svg { .pdf-actions_container svg {
width: 16px; width: 16px;
height: 16px; height: 16px;
} }
.pdf-actions_container:nth-child(1) .pdf-actions_move-left-button { .pdf-actions_container:nth-child(1) .pdf-actions_move-left-button {
display: none; display: none;
} }
.pdf-actions_container:last-child .pdf-actions_move-right-button { .pdf-actions_container:last-child .pdf-actions_move-right-button {
display: none; display: none;
} }
@@ -37,6 +51,25 @@
transition: opacity 0.2s; transition: opacity 0.2s;
} }
.pdf-actions_insert-file-button-container button .material-symbols-rounded {
vertical-align: top;
}
.pdf-actions_insert-file-button-container.left button,
.pdf-actions_insert-file-button-container.right button {
padding: 0.45rem;
}
.pdf-actions_button-container button .material-symbols-rounded {
font-size: 1.25rem;
vertical-align: sub;
}
.pdf-actions_insert-file-button {
padding: 0;
vertical-align: sub;
}
.pdf-actions_insert-file-button-container.left { .pdf-actions_insert-file-button-container.left {
left: -20px; left: -20px;
} }
@@ -63,11 +96,11 @@ html[dir="rtl"] .pdf-actions_insert-file-button-container.left {
translate: 0 -50%; translate: 0 -50%;
} }
html[dir="ltr"] .pdf-actions_container:last-child > .pdf-actions_insert-file-button-container.right { html[dir="ltr"] .pdf-actions_container:last-child>.pdf-actions_insert-file-button-container.right {
display: block; display: block;
} }
html[dir="rtl"] .pdf-actions_container:last-child > .pdf-actions_insert-file-button-container.left { html[dir="rtl"] .pdf-actions_container:last-child>.pdf-actions_insert-file-button-container.left {
display: block; display: block;
} }
@@ -75,6 +108,7 @@ html[dir="rtl"] .pdf-actions_container:last-child > .pdf-actions_insert-file-but
opacity: 1; opacity: 1;
transition: opacity 0.05s; transition: opacity 0.05s;
} }
.pdf-actions_insert-file-button { .pdf-actions_insert-file-button {
position: absolute; position: absolute;
top: 50%; top: 50%;
@@ -82,4 +116,4 @@ html[dir="rtl"] .pdf-actions_container:last-child > .pdf-actions_insert-file-but
translate: 50% -50%; translate: 50% -50%;
aspect-ratio: 1; aspect-ratio: 1;
border-radius: 100px; border-radius: 100px;
} }

View File

@@ -4,18 +4,23 @@
.bordered-box { .bordered-box {
border: 1px solid #ddd; border: 1px solid #ddd;
padding: 20px; padding: 2rem;
margin: 20px; margin: 2rem;
width: 70%; width: 70%;
} }
.center-element { .center-element {
width: 80%; width: 100%;
text-align: center; text-align: center;
margin: auto; margin: auto;
margin-top: 2rem;
} }
.element-margin { .element-margin {
margin: 10px 0; margin: 1rem 0;
/* Adjust this value to increase/decrease the margin as needed */ /* Adjust this value to increase/decrease the margin as needed */
} }
#pipelineList {
margin-bottom: 2rem;
}

View File

@@ -0,0 +1,917 @@
/* Dark Mode Styles */
body,
select,
textarea {
background-color: var(--md-sys-color-surface);
color: var(--md-sys-color-on-surface);
}
.transition-theme {
transition: background 0.5s ease, color 0.5s ease, border 0.5s ease;
}
/*.global-buttons-container input:disabled::-webkit-input-placeholder { !* WebKit browsers *!*/
/* color: #98A0AB;*/
/*}*/
/*.global-buttons-container input:disabled:-moz-placeholder { !* Mozilla Firefox 4 to 18 *!*/
/* color: #98A0AB;*/
/*}*/
/*.global-buttons-container input:disabled::-moz-placeholder { !* Mozilla Firefox 19+ *!*/
/* color: #98A0AB;*/
/*}*/
/*.global-buttons-container input:disabled:-ms-input-placeholder { !* Internet Explorer 10+ *!*/
/* color: #98A0AB;*/
/*}*/
/* Scrollbar */
*::-webkit-scrollbar {
background: var(--md-sys-color-surface);
width: 1rem;
}
*::-webkit-scrollbar-track {
background: var(--md-sys-color-surface);
}
*::-webkit-scrollbar-thumb {
border-radius: 2rem;
background-color: var(--md-sys-color-surface-5);
border: 5px solid var(--md-sys-color-surface-5);
}
/* Alerts */
.alert {
border-radius: 3rem;
}
/* Table */
td {
word-break: break-word;
}
.input-group-append {
margin: 0rem 0.5rem !important;
}
.card-header {
background-color: transparent;
border-bottom: none;
}
.bg-card {
background-color: var(--md-sys-color-surface-5);
border-radius: 3rem;
padding: 2.5rem;
}
.card {
padding: 1.25rem;
border-radius: 2rem;
background-color: var(--md-sys-color-surface-5);
border: none;
}
/* Modal */
.modal-content {
background-color: var(--md-sys-color-surface);
border-radius: 2rem;
border: transparent;
}
.modal-header,
.modal-body,
.modal-footer {
background-color: var(--md-sys-color-surface-5);
padding: 1.5rem 2rem;
border: none;
}
.modal-header {
border-radius: 2rem 2rem 0rem 0rem;
}
.modal-footer {
border-radius: 0rem 0rem 2rem 2rem;
}
/* Icon fill */
.material-symbols-rounded {
vertical-align: text-top;
}
/* Navbar Icon*/
.nav-icon {
color: var(--md-sys-color-surface);
}
.sign .nav-icon,
.sign.tool-header-icon {
color: var(--md-nav-on-section-color-sign);
background-color: var(--md-nav-section-color-sign);
}
.organize .nav-icon,
.organize.tool-header-icon {
color: var(--md-nav-on-section-color-organize);
background-color: var(--md-nav-section-color-organize);
}
.convert .nav-icon,
.convert.tool-header-icon {
color: var(--md-nav-on-section-color-convert);
background-color: var(--md-nav-section-color-convert);
}
.security .nav-icon,
.security.tool-header-icon {
color: var(--md-nav-on-section-color-security);
background-color: var(--md-nav-section-color-security);
}
.other .nav-icon,
.other.tool-header-icon {
color: var(--md-nav-on-section-color-other);
background-color: var(--md-nav-section-color-other);
}
.advance .nav-icon,
.advance.tool-header-icon {
color: var(--md-nav-on-section-color-advance);
background-color: var(--md-nav-section-color-advance);
}
.image .nav-icon,
.image.tool-header-icon {
color: var(--md-nav-on-section-color-image);
background-color: var(--md-nav-section-color-image);
}
.word .nav-icon,
.word.tool-header-icon {
color: var(--md-nav-on-section-color-word);
background-color: var(--md-nav-section-color-word);
}
.ppt .nav-icon,
.ppt.tool-header-icon {
color: var(--md-nav-on-section-color-ppt);
background-color: var(--md-nav-section-color-ppt);
}
/* Tool Page Header*/
.tool-header {
margin-bottom: 2rem;
}
.tool-header .tool-header-icon {
margin: 0px 1rem;
height: 4rem;
width: 4rem;
border-radius: 25px;
font-size: 3rem;
padding: 0.5rem;
vertical-align: middle;
pointer-events: none;
user-select: none;
-webkit-user-select: none;
-webkit-tap-highlight-color: rgb(0 0 0 / 0%);
}
.tool-header .tool-header-text {
font-size: 2.5rem;
font-weight: 400;
vertical-align: middle;
}
/* Home Card Colors*/
.feature-card .nav-icon {
vertical-align: middle;
font-size: 2rem !important;
padding: 0.5rem;
border-radius: 1.25rem;
color: var(--md-sys-color-surface);
}
.feature-card .sign .nav-icon {
color: var(--md-nav-on-section-color-sign);
background-color: var(--md-nav-section-color-sign);
}
.feature-card .organize .nav-icon {
color: var(--md-nav-on-section-color-organize);
background-color: var(--md-nav-section-color-organize);
}
.feature-card .convert .nav-icon {
color: var(--md-nav-on-section-color-convert);
background-color: var(--md-nav-section-color-convert);
}
.feature-card .security .nav-icon {
color: var(--md-nav-on-section-color-security);
background-color: var(--md-nav-section-color-security);
}
.feature-card .other .nav-icon {
color: var(--md-nav-on-section-color-other);
background-color: var(--md-nav-section-color-other);
}
.feature-card .advance .nav-icon {
color: var(--md-nav-on-section-color-advance);
background-color: var(--md-nav-section-color-advance);
}
.feature-card .image .nav-icon {
color: var(--md-nav-on-section-color-image);
background-color: var(--md-nav-section-color-image);
}
.feature-card .word .nav-icon {
color: var(--md-nav-on-section-color-word);
background-color: var(--md-nav-section-color-word);
}
.feature-card .ppt .nav-icon {
color: var(--md-nav-on-section-color-ppt);
background-color: var(--md-nav-section-color-ppt);
}
/* Buttons Components */
.btn {
border-radius: 1.25rem;
}
.btn-close {
width: auto;
height: auto;
color: var(--md-sys-color-on-surface);
background: transparent;
}
.btn-close:hover {
color: var(--md-sys-color-on-surface);
}
.modal-header .btn-close {
margin: 0;
}
/* Primary btn */
.btn-primary {
color: var(--md-sys-color-on-primary);
background-color: var(--md-sys-color-primary);
border-color: var(--md-sys-color-primary);
box-shadow: none !important;
}
.btn-primary.disabled,
.btn-primary:disabled {
color: var(--md-sys-color-on-primary);
background-color: var(--md-sys-color-primary);
border-color: var(--md-sys-color-primary);
}
.btn-primary:hover {
color: var(--md-sys-color-on-primary);
background-color: var(--md-sys-color-primary);
border-color: var(--md-sys-color-primary);
box-shadow: var(--md-sys-elevation-3) !important;
}
.btn-check:active+.btn-primary,
.btn-check:checked+.btn-primary,
.btn-primary.active,
.btn-primary:active,
.show>.btn-primary.dropdown-toggle {
color: var(--md-sys-color-on-primary);
background-color: var(--md-sys-color-primary);
border-color: var(--md-sys-color-primary);
box-shadow: var(--md-sys-elevation-3) !important;
}
.btn-check:focus+.btn-primary,
.btn-primary:focus {
color: var(--md-sys-color-on-primary);
background-color: var(--md-sys-color-primary);
border-color: var(--md-sys-color-primary);
box-shadow: var(--md-sys-elevation-3) !important;
}
/* Secondary btn */
.btn-secondary {
color: var(--md-sys-color-on-secondary);
background-color: var(--md-sys-color-secondary);
border-color: var(--md-sys-color-secondary);
box-shadow: none !important;
}
.btn-secondary.disabled,
.btn-secondary:disabled {
color: var(--md-sys-color-on-secondary);
background-color: var(--md-sys-color-secondary);
border-color: var(--md-sys-color-secondary);
}
.btn-secondary:hover {
color: var(--md-sys-color-on-secondary);
background-color: var(--md-sys-color-secondary);
border-color: var(--md-sys-color-secondary);
box-shadow: var(--md-sys-elevation-3) !important;
}
.btn-check:active+.btn-secondary,
.btn-check:checked+.btn-secondary,
.btn-secondary.active,
.btn-secondary:active,
.show>.btn-secondary.dropdown-toggle {
color: var(--md-sys-color-on-secondary);
background-color: var(--md-sys-color-secondary);
border-color: var(--md-sys-color-secondary);
box-shadow: var(--md-sys-elevation-3) !important;
}
.btn-check:focus+.btn-secondary,
.btn-secondary:focus {
color: var(--md-sys-color-on-secondary);
background-color: var(--md-sys-color-secondary);
border-color: var(--md-sys-color-secondary);
box-shadow: var(--md-sys-elevation-3) !important;
}
/* Danger btn */
.btn-danger {
color: var(--md-sys-color-on-error);
background-color: var(--md-sys-color-error);
border-color: var(--md-sys-color-error);
box-shadow: none !important;
}
.btn-danger.disabled,
.btn-danger:disabled {
color: var(--md-sys-color-on-error);
background-color: var(--md-sys-color-error);
border-color: var(--md-sys-color-error);
}
.btn-danger:hover {
color: var(--md-sys-color-on-error);
background-color: var(--md-sys-color-error);
border-color: var(--md-sys-color-error);
box-shadow: var(--md-sys-elevation-3) !important;
}
.btn-check:active+.btn-danger,
.btn-check:checked+.btn-danger,
.btn-danger.active,
.btn-danger:active,
.show>.btn-danger.dropdown-toggle {
color: var(--md-sys-color-on-error);
background-color: var(--md-sys-color-error);
border-color: var(--md-sys-color-error);
box-shadow: var(--md-sys-elevation-3) !important;
}
.btn-check:focus+.btn-danger,
.btn-danger:focus {
color: var(--md-sys-color-on-error);
background-color: var(--md-sys-color-error);
border-color: var(--md-sys-color-error);
box-shadow: var(--md-sys-elevation-3) !important;
}
/* Info btn */
.btn-info {
color: var(--md-sys-color-on-tertiary);
background-color: var(--md-sys-color-tertiary);
border-color: var(--md-sys-color-tertiary);
box-shadow: none !important;
}
.btn-info .disabled,
.btn-info:disabled {
color: var(--md-sys-color-on-tertiary);
background-color: var(--md-sys-color-tertiary);
border-color: var(--md-sys-color-tertiary);
}
.btn-info:hover {
color: var(--md-sys-color-on-tertiary);
background-color: var(--md-sys-color-tertiary);
border-color: var(--md-sys-color-tertiary);
box-shadow: var(--md-sys-elevation-3) !important;
}
.btn-check:active+.btn-info,
.btn-check:checked+.btn-info,
.btn-info .active,
.btn-info:active,
.show>.btn-info.dropdown-toggle {
color: var(--md-sys-color-on-tertiary);
background-color: var(--md-sys-color-tertiary);
border-color: var(--md-sys-color-tertiary);
box-shadow: var(--md-sys-elevation-3) !important;
}
.btn-check:focus+.btn-info,
.btn-info:focus {
color: var(--md-sys-color-on-tertiary);
background-color: var(--md-sys-color-tertiary);
border-color: var(--md-sys-color-tertiary);
box-shadow: var(--md-sys-elevation-3) !important;
}
/* Info btn */
.btn-success {
box-shadow: none !important;
}
.btn-success:hover,
.btn-check:active+.btn-success,
.btn-check:checked+.btn-success,
.btn-success .active,
.btn-success:active,
.show>.btn-success.dropdown-toggle,
.btn-check:focus+.btn-success,
.btn-success:focus {
box-shadow: var(--md-sys-elevation-3) !important;
}
/* Warning btn */
.btn-warning {
box-shadow: none !important;
}
.btn-warning:hover,
.btn-check:active+.btn-warning,
.btn-check:checked+.btn-warning,
.btn-warning .active,
.btn-warning:active,
.show>.btn-warning.dropdown-toggle,
.btn-check:focus+.btn-warning,
.btn-warning:focus {
box-shadow: var(--md-sys-elevation-3) !important;
}
/* Outline Primary btn */
.btn-outline-primary {
color: var(--md-sys-color-primary);
background-color: transparent;
border-color: var(--md-sys-color-primary);
box-shadow: none !important;
}
.btn-outline-primary .disabled,
.btn-outline-primary:disabled {
color: var(--md-sys-color-primary);
background-color: transparent;
border-color: var(--md-sys-color-primary);
}
.btn-outline-primary:hover {
color: var(--md-sys-color-on-primary);
background-color: var(--md-sys-color-primary);
border-color: var(--md-sys-color-primary);
}
.btn-check:active+.btn-outline-primary,
.btn-check:checked+.btn-outline-primary,
.btn-outline-primary .active,
.btn-outline-primary:active,
.show>.btn-outline-primary.dropdown-toggle {
color: var(--md-sys-color-on-primary);
background-color: var(--md-sys-color-primary);
border-color: var(--md-sys-color-primary);
}
.btn-check:focus+.btn-outline-primary,
.btn-outline-primary:focus {
color: var(--md-sys-color-on-primary);
background-color: var(--md-sys-color-primary);
border-color: var(--md-sys-color-primary);
}
/* Outline Secondary btn */
.btn-outline-secondary {
color: var(--md-sys-color-secondary);
background-color: transparent;
border-color: var(--md-sys-color-secondary);
box-shadow: none !important;
}
.btn-outline-secondary .disabled,
.btn-outline-secondary:disabled {
color: var(--md-sys-color-secondary);
background-color: transparent;
border-color: var(--md-sys-color-secondary);
}
.btn-outline-secondary:hover {
color: var(--md-sys-color-on-secondary);
background-color: var(--md-sys-color-secondary);
border-color: var(--md-sys-color-secondary);
}
.btn-check:active+.btn-outline-secondary,
.btn-check:checked+.btn-outline-secondary,
.btn-outline-secondary .active,
.btn-outline-secondary:active,
.show>.btn-outline-secondary.dropdown-toggle {
color: var(--md-sys-color-on-secondary);
background-color: var(--md-sys-color-secondary);
border-color: var(--md-sys-color-secondary);
}
.btn-check:focus+.btn-outline-secondary,
.btn-outline-secondary:focus {
color: var(--md-sys-color-on-secondary);
background-color: var(--md-sys-color-secondary);
border-color: var(--md-sys-color-secondary);
}
/* Disabled btn */
.btn.disabled,
.btn:disabled,
fieldset:disabled .btn {
pointer-events: none;
opacity: 0.65;
}
/* Range Slider */
.form-range:focus::-webkit-slider-thumb {
box-shadow: 0 0 0 1px var(--md-sys-color-surface), 0 0 0 .25rem var(--md-sys-color-primary)
}
.form-range:focus::-moz-range-thumb {
box-shadow: 0 0 0 1px var(--md-sys-color-surface), 0 0 0 .25rem var(--md-sys-color-primary)
}
.form-range::-webkit-slider-thumb {
background-color: var(--md-sys-color-primary);
}
.form-range::-webkit-slider-thumb:active {
background-color: var(--md-sys-color-primary)
}
.form-range::-webkit-slider-runnable-track {
background-color: var(--md-sys-color-on-primary)
}
.form-range::-moz-range-thumb {
background-color: var(--md-sys-color-primary);
}
/* checkbox */
.form-check {
margin-bottom: 1rem;
}
.form-check-label {
margin-left: 0.5rem;
margin-right: 0.5rem;
}
.form-check-input {
width: 1.5rem;
height: 1.5rem;
margin: 0;
background-color: var(--md-sys-color-surface);
border: 2px solid var(--md-sys-color-outline-variant);
}
.form-check-input:checked {
background-color: var(--md-sys-color-primary);
border-color: var(--md-sys-color-outline-variant);
border: none;
}
.form-check-input:focus {
border-color: var(--md-sys-color-outline-variant);
outline: 0;
box-shadow: 0 0 0 .25rem var(--md-sys-color-outline-variant);
}
.form-check-input:checked[type=checkbox] {
background-image: none;
}
.form-check input[type="checkbox"]:checked+span.material-symbols-rounded {
display: block;
}
.form-check span.material-symbols-rounded {
display: none;
color: var(--md-sys-color-surface);
position: absolute;
margin-left: -1.5rem;
margin-right: -1.5rem;
pointer-events: none;
user-select: none;
-webkit-user-select: none;
-webkit-tap-highlight-color: rgb(0 0 0 / 0%);
}
.form-check {
min-height: 22px;
padding-left: 0;
}
.form-check > label {
padding-left: 29px !important;
min-height: 22px;
line-height: 22px;
display: inline-block;
position: relative;
vertical-align: top;
margin-bottom: 0;
font-weight: normal;
cursor: pointer;
padding-right: 29px !important;
}
.form-check > input:first-child {
position: absolute !important;
opacity: 0;
margin: 0;
background-color: var(--md-sys-state-hover-opacity);
border-radius: 50%;
appearance: none;
-moz-appearance: none;
-webkit-appearance: none;
-ms-appearance: none;
display: block;
width: 22px;
height: 22px;
outline: none;
transform: scale(1.65);
-ms-transform: scale(1.65);
transition: opacity .3s;
}
.form-check > input:first-child:hover {
opacity: 1;
transform: scale(1.65);
-ms-transform: scale(1.65);
}
.form-check > input:first-child:disabled {
cursor: default;
}
.form-check > input:first-child:disabled + label,
.form-check > input:first-child:disabled + input[type="hidden"] + label,
.form-check > input:first-child:disabled + label::before,
.form-check > input:first-child:disabled + input[type="hidden"] + label::before {
pointer-events: none;
cursor: default;
filter: alpha(opacity=65);
-webkit-box-shadow: none;
box-shadow: none;
opacity: .65;
}
.form-check > input:first-child + label::before,
.form-check > input:first-child + input[type="hidden"] + label::before {
content: "";
display: inline-block;
position: absolute;
width: 22px;
height: 22px;
border: 2px solid var(--md-sys-color-on-surface-variant);
border-radius: 3px;
margin-left: -29px;
box-sizing: border-box;
margin-right: -29px;
}
.form-check > input:first-child:checked + label::after,
.form-check > input:first-child:checked + input[type="hidden"] + label::after {
content: "";
display: inline-block;
position: absolute;
top: 0;
left: 0;
width: 7px;
height: 10px;
border: solid 2px;
border-left: none;
border-top: none;
transform: translate(7.75px, 4.5px) rotate(45deg);
-ms-transform: translate(7.75px, 4.5px) rotate(45deg);
box-sizing: border-box;
right: 0;
margin-right: 14px;
border-bottom-color: var(--md-sys-color-on-primary);
border-right-color: var(--md-sys-color-on-primary);
}
.form-check > input:first-child::-ms-check {
opacity: 0;
border-radius: 50%;
background-color: var(--md-sys-color-primary);
}
.form-check > input:first-child:active {
transform: scale(0);
-ms-transform: scale(0);
opacity: 1;
transition: opacity 0s, transform 0s;
}
.form-check > input[type="radio"]:first-child + label::before,
.form-check > input[type="radio"]:first-child + input[type="hidden"] + label::before {
border-radius: 50%;
}
.form-check > input[type="radio"]:first-child:checked + label::before,
.form-check > input[type="radio"]:first-child:checked + input[type="hidden"] + label::before {
background-color: transparent;
}
.form-check > input[type="radio"]:first-child:checked + label::after,
.form-check > input[type="radio"]:first-child:checked + input[type="hidden"] + label::after {
content: "";
position: absolute;
width: 10px;
height: 10px;
border-radius: 50%;
border: none;
top: 6px;
left: 6px;
transform: none;
-ms-transform: none;
}
.form-check > input[type="checkbox"]:first-child:checked + label::after,
.form-check > input[type="checkbox"]:first-child:checked + input[type="hidden"] + label::after {
width: 8px;
height: 14px;
transform: translate(7px, 2px) rotate(45deg);
-ms-transform: translate(7px, 2px) rotate(45deg);
}
.form-check-inline {
display: inline-block;
}
.form-check-inline + .form-check-inline {
margin-left: .75rem;
margin-top: 6px;
}
.form-check > input:first-child:checked + label::before,
.form-check > input:first-child:checked + input[type="hidden"] + label::before {
background-color: var(--md-sys-color-primary);
border-color: var(--md-sys-color-primary);
}
/* Forms */
textarea.form-control {
border-radius: 1.5rem !important;
}
.form-control,
.form-select,
.form-control:disabled,
.form-control[readonly] {
color: var(--md-sys-color-on-surface);
background-color: var(--md-sys-color-surface-container-low);
border-color: var(--md-sys-color-outline-variant);
border-radius: 3rem !important;
}
.form-control:focus,
.form-select:focus {
color: var(--md-sys-color-on-surface);
background-color: var(--md-sys-color-surface-container-lowest);
border-color: var(--md-sys-color-outline-variant);
outline: 0;
box-shadow: 0 0 0 0.25rem var(--md-sys-color-outline-variant);
}
/* Navbar Components */
.navbar-brand {
color: var(--md-sys-color-on-surface) !important;
}
.nav-link {
transition: none !important;
padding: 0.5rem 1rem !important;
border: 1px transparent;
}
.navbar-nav li {
flex: 1;
}
.navbar-nav .nav-link {
color: var(--md-sys-color-on-surface-variant);
}
.navbar-nav .nav-link:focus,
.navbar-nav .nav-link:hover {
color: var(--md-sys-color-on-secondary-container);
background-color: var(--md-sys-color-surface-3);
border-radius: 3rem;
font-weight: 500;
font-variation-settings: var(--md-sys-icon-fill-1);
}
.navbar-nav .nav-link.active,
.navbar-nav .show>.nav-link {
color: var(--md-sys-color-on-secondary-container);
background-color: var(--md-sys-color-surface-5);
border-radius: 3rem;
font-weight: 500;
font-variation-settings: var(--md-sys-icon-fill-1);
}
.menu-title {
padding: 0 1rem;
}
.dropdown-menu {
margin: 0 1%;
padding: 1.5rem 0;
border-radius: 1rem;
color: var(--md-sys-color-on-surface);
background-color: var(--md-sys-color-surface-container);
border: 1px solid var(--md-sys-color-surface-5);
box-shadow: var(--md-sys-elevation-2);
}
.dropdown-item {
color: var(--md-sys-color-on-surface);
padding: 0.25rem 1rem;
}
.dropdown-item:focus,
.dropdown-item:hover {
color: var(--md-sys-color-on-surface);
background-color: var(--md-sys-color-surface-5);
border-radius: 3rem;
font-weight: 500;
font-variation-settings: var(--md-sys-icon-fill-1);
}
.dropdown-item.active,
.dropdown-item:active {
color: var(--md-sys-color-on-surface);
background-color: var(--md-sys-color-surface-5);
border-radius: 3rem;
font-weight: 500;
font-variation-settings: var(--md-sys-icon-fill-1);
}
/* list-group-item */
.list-group-item {
color: var(--md-sys-color-on-surface);
background-color: var(--md-sys-color-surface-5);
border: 1px solid var(--md-sys-color-outline-variant);
}
.list-group-item:first-child {
border-radius: 1rem 1rem 0rem 0rem;
}
.list-group-item:last-child {
border-radius: 0rem 0rem 1rem 1rem;
}
.list-group-item:only-child {
border-radius: 1rem 1rem 1rem 1rem;
}
.list-group-item .btn {
padding: .375rem .5rem;
}
/*Alert */
.alert-container {
padding: 2rem 3rem;
border-radius: 3rem;
margin: 1rem 0rem 2rem;
}
.alert-header {
display: flex !important;
justify-content: space-between;
}
.alert-heading {
font-size: calc(1.275rem + .3vw);
}
.alert-dismissible .btn-close {
position: relative;
padding: 0;
}
.alert-danger {
color: var(--md-sys-color-on-error-container);
background-color: var(--md-sys-color-error-container);
border-color: transparent;
}

View File

@@ -0,0 +1,22 @@
@font-face {
font-family: 'Material Symbols Rounded';
font-style: normal;
font-weight: 100 700;
src: url(../../fonts/google-symbol.woff2) format('woff2');
}
.material-symbols-rounded {
font-family: 'Material Symbols Rounded';
font-weight: normal;
font-style: normal;
font-size: 24px;
line-height: 1;
letter-spacing: normal;
text-transform: none;
display: inline-block;
white-space: nowrap;
word-wrap: normal;
direction: ltr;
-webkit-font-feature-settings: 'liga';
-webkit-font-smoothing: antialiased;
}

View File

@@ -0,0 +1,34 @@
:where(html, .light-theme, .dark-theme),
.tokens,
:host {
/* Define surface colors based on primary color */
--md-sys-color-surface-1: color-mix(in srgb, var(--md-sys-color-primary) 13%, rgba(0, 0, 0, 0.05) 5%);
--md-sys-color-surface-2: color-mix(in srgb, var(--md-sys-color-primary) 13%, rgba(0, 0, 0, 0.08) 5%);
--md-sys-color-surface-3: color-mix(in srgb, var(--md-sys-color-primary) 13%, rgba(0, 0, 0, 0.11) 5%);
--md-sys-color-surface-4: color-mix(in srgb, var(--md-sys-color-primary) 13%, rgba(0, 0, 0, 0.12) 5%);
--md-sys-color-surface-5: color-mix(in srgb, var(--md-sys-color-primary) 13%, rgba(0, 0, 0, 0.14) 5%);
/* Icon fill */
--md-sys-icon-fill-0: 'FILL' 0, 'wght' 500;
--md-sys-icon-fill-1: 'FILL' 1, 'wght' 500;
/* Hover Color */
--md-sys-state-hover-opacity: color-mix(in srgb, var(--md-sys-color-primary), rgba(0, 0, 0, 0) 80%);
/* Shadow */
--md-sys-color-shadow: #000000;
--md-elevation-shadow-color-rgb: 0, 0, 0;
--md-elevation-shadow-color: var(--md-elevation-shadow-color-rgb);
/* Shadow Elevation*/
--md-sys-elevation-0: 0px 0px 0px 0px rgb(var(--md-elevation-shadow-color), 0.2), 0px 0px 0px 0px rgb(var(--md-elevation-shadow-color), 0.14), 0px 0px 0px 0px rgb(var(--md-elevation-shadow-color), 0.12);
--md-sys-elevation-1: 0px 3px 1px -2px rgb(var(--md-elevation-shadow-color), 0.2), 0px 2px 2px 0px rgb(var(--md-elevation-shadow-color), 0.14), 0px 1px 5px 0px rgb(var(--md-elevation-shadow-color), 0.12);
--md-sys-elevation-2: 0px 2px 4px -1px rgb(var(--md-elevation-shadow-color), 0.2), 0px 4px 5px 0px rgb(var(--md-elevation-shadow-color), 0.14), 0px 1px 10px 0px rgb(var(--md-elevation-shadow-color), 0.12);
--md-sys-elevation-3: 0px 5px 5px -3px rgb(var(--md-elevation-shadow-color), 0.2), 0px 8px 10px 1px rgb(var(--md-elevation-shadow-color), 0.14), 0px 3px 14px 2px rgb(var(--md-elevation-shadow-color), 0.12);
--md-sys-elevation-4: 0px 5px 5px -3px rgb(var(--md-elevation-shadow-color) / 0.2), 0px 8px 10px 1px rgb(var(--md-elevation-shadow-color), 0.14), 0px 3px 14px 2px rgb(var(--md-elevation-shadow-color), 0.12);
--md-sys-elevation-5: 0px 8px 10px -6px rgb(var(--md-elevation-shadow-color), 0.2), 0px 16px 24px 2px rgb(var(--md-elevation-shadow-color), 0.14), 0px 6px 30px 5px rgb(var(--md-elevation-shadow-color), 0.12);
}
.fill {
font-variation-settings: var(--md-sys-icon-fill-1);
}
.no-fill {
font-variation-settings: var(--md-sys-icon-fill-0);
}

View File

@@ -0,0 +1,73 @@
:root {
/* Colors */
--md-sys-color-primary: rgb(162 201 255);
--md-sys-color-surface-tint: rgb(162 201 255);
--md-sys-color-on-primary: rgb(0 49 92);
--md-sys-color-primary-container: rgb(0 118 208);
--md-sys-color-on-primary-container: rgb(255 255 255);
--md-sys-color-secondary: rgb(169 201 246);
--md-sys-color-on-secondary: rgb(12 49 87);
--md-sys-color-secondary-container: rgb(29 62 100);
--md-sys-color-on-secondary-container: rgb(180 210 255);
--md-sys-color-tertiary: rgb(193 194 248);
--md-sys-color-on-tertiary: rgb(42 44 88);
--md-sys-color-tertiary-container: rgb(110 112 161);
--md-sys-color-on-tertiary-container: rgb(255 255 255);
--md-sys-color-error: rgb(255 180 171);
--md-sys-color-on-error: rgb(105 0 5);
--md-sys-color-error-container: rgb(147 0 10);
--md-sys-color-on-error-container: rgb(255 218 214);
--md-sys-color-background: rgb(15 20 26);
--md-sys-color-on-background: rgb(223 226 235);
--md-sys-color-surface: rgb(15 20 26);
--md-sys-color-on-surface: rgb(223 226 235);
--md-sys-color-surface-variant: rgb(64 71 83);
--md-sys-color-on-surface-variant: rgb(192 199 213);
--md-sys-color-outline: rgb(138 145 158);
--md-sys-color-outline-variant: rgb(64 71 83);
--md-sys-color-shadow: rgb(0 0 0);
--md-sys-color-scrim: rgb(0 0 0);
--md-sys-color-inverse-surface: rgb(223 226 235);
--md-sys-color-inverse-on-surface: rgb(45 49 55);
--md-sys-color-inverse-primary: rgb(0 96 170);
--md-sys-color-primary-fixed: rgb(211 228 255);
--md-sys-color-on-primary-fixed: rgb(0 28 56);
--md-sys-color-primary-fixed-dim: rgb(162 201 255);
--md-sys-color-on-primary-fixed-variant: rgb(0 72 130);
--md-sys-color-secondary-fixed: rgb(211 228 255);
--md-sys-color-on-secondary-fixed: rgb(0 28 56);
--md-sys-color-secondary-fixed-dim: rgb(169 201 246);
--md-sys-color-on-secondary-fixed-variant: rgb(40 72 111);
--md-sys-color-tertiary-fixed: rgb(225 224 255);
--md-sys-color-on-tertiary-fixed: rgb(20 22 66);
--md-sys-color-tertiary-fixed-dim: rgb(193 194 248);
--md-sys-color-on-tertiary-fixed-variant: rgb(64 67 112);
--md-sys-color-surface-dim: rgb(15 20 26);
--md-sys-color-surface-bright: rgb(53 57 64);
--md-sys-color-surface-container-lowest: rgb(10 14 20);
--md-sys-color-surface-container-low: rgb(24 28 34);
--md-sys-color-surface-container: rgb(28 32 38);
--md-sys-color-surface-container-high: rgb(38 42 49);
--md-sys-color-surface-container-highest: rgb(49 53 60);
/* Tools Color */
--md-nav-section-color-opacity: 1;
--md-nav-on-section-color-opacity: 1;
--md-nav-section-color-sign: rgba(25, 101, 212, var(--md-nav-section-color-opacity));
--md-nav-on-section-color-sign: rgba(28, 27, 31, var(--md-nav-on-section-color-opacity));
--md-nav-section-color-organize: rgba(120, 130, 255, var(--md-nav-section-color-opacity));
--md-nav-on-section-color-organize: rgba(28, 27, 31, var(--md-nav-on-section-color-opacity));
--md-nav-section-color-convert: rgba(25, 177, 212, var(--md-nav-section-color-opacity));
--md-nav-on-section-color-convert: rgba(28, 27, 31, var(--md-nav-on-section-color-opacity));
--md-nav-section-color-security: rgba(255, 120, 146, var(--md-nav-section-color-opacity));
--md-nav-on-section-color-security: rgba(28, 27, 31, var(--md-nav-on-section-color-opacity));
--md-nav-section-color-other: rgba(72, 189, 84, var(--md-nav-section-color-opacity));
--md-nav-on-section-color-other: rgba(28, 27, 31, var(--md-nav-on-section-color-opacity));
--md-nav-section-color-advance: rgba(245, 84, 84, var(--md-nav-section-color-opacity));
--md-nav-on-section-color-advance: rgba(28, 27, 31, var(--md-nav-on-section-color-opacity));
--md-nav-section-color-image: rgba(212, 172, 25, var(--md-nav-section-color-opacity));
--md-nav-on-section-color-image: rgba(28, 27, 31, var(--md-nav-on-section-color-opacity));
--md-nav-section-color-word: rgba(61, 153, 245, var(--md-nav-section-color-opacity));
--md-nav-on-section-color-word: rgba(28, 27, 31, var(--md-nav-on-section-color-opacity));
--md-nav-section-color-ppt: rgba(255, 128, 0, var(--md-nav-section-color-opacity));
--md-nav-on-section-color-ppt: rgba(28, 27, 31, var(--md-nav-on-section-color-opacity));
}

View File

@@ -0,0 +1,73 @@
:root {
/* Colors */
--md-sys-color-primary: rgb(0 96 170);
--md-sys-color-surface-tint: rgb(0 96 170);
--md-sys-color-on-primary: rgb(255 255 255);
--md-sys-color-primary-container: rgb(80 163 255);
--md-sys-color-on-primary-container: rgb(0 20 43);
--md-sys-color-secondary: rgb(65 96 136);
--md-sys-color-on-secondary: rgb(255 255 255);
--md-sys-color-secondary-container: rgb(188 215 255);
--md-sys-color-on-secondary-container: rgb(32 65 103);
--md-sys-color-tertiary: rgb(88 90 138);
--md-sys-color-on-tertiary: rgb(255 255 255);
--md-sys-color-tertiary-container: rgb(151 153 205);
--md-sys-color-on-tertiary-container: rgb(7 9 55);
--md-sys-color-error: rgb(186 26 26);
--md-sys-color-on-error: rgb(255 255 255);
--md-sys-color-error-container: rgb(255 218 214);
--md-sys-color-on-error-container: rgb(65 0 2);
--md-sys-color-background: rgb(248 249 255);
--md-sys-color-on-background: rgb(24 28 34);
--md-sys-color-surface: rgb(248 249 255);
--md-sys-color-on-surface: rgb(24 28 34);
--md-sys-color-surface-variant: rgb(220 227 241);
--md-sys-color-on-surface-variant: rgb(64 71 83);
--md-sys-color-outline: rgb(112 119 132);
--md-sys-color-outline-variant: rgb(192 199 213);
--md-sys-color-shadow: rgb(0 0 0);
--md-sys-color-scrim: rgb(0 0 0);
--md-sys-color-inverse-surface: rgb(45 49 55);
--md-sys-color-inverse-on-surface: rgb(238 241 250);
--md-sys-color-inverse-primary: rgb(162 201 255);
--md-sys-color-primary-fixed: rgb(211 228 255);
--md-sys-color-on-primary-fixed: rgb(0 28 56);
--md-sys-color-primary-fixed-dim: rgb(162 201 255);
--md-sys-color-on-primary-fixed-variant: rgb(0 72 130);
--md-sys-color-secondary-fixed: rgb(211 228 255);
--md-sys-color-on-secondary-fixed: rgb(0 28 56);
--md-sys-color-secondary-fixed-dim: rgb(169 201 246);
--md-sys-color-on-secondary-fixed-variant: rgb(40 72 111);
--md-sys-color-tertiary-fixed: rgb(225 224 255);
--md-sys-color-on-tertiary-fixed: rgb(20 22 66);
--md-sys-color-tertiary-fixed-dim: rgb(193 194 248);
--md-sys-color-on-tertiary-fixed-variant: rgb(64 67 112);
--md-sys-color-surface-dim: rgb(215 218 227);
--md-sys-color-surface-bright: rgb(248 249 255);
--md-sys-color-surface-container-lowest: rgb(255 255 255);
--md-sys-color-surface-container-low: rgb(241 243 253);
--md-sys-color-surface-container: rgb(235 238 247);
--md-sys-color-surface-container-high: rgb(229 232 241);
--md-sys-color-surface-container-highest: rgb(223 226 235);
/* Tools Color */
--md-nav-section-color-opacity: 1;
--md-nav-on-section-color-opacity: 1;
--md-nav-section-color-sign: rgba(25, 101, 212, var(--md-nav-section-color-opacity));
--md-nav-on-section-color-sign: rgba(255, 251, 254, var(--md-nav-on-section-color-opacity));
--md-nav-section-color-organize: rgba(120, 130, 255, var(--md-nav-section-color-opacity));
--md-nav-on-section-color-organize: rgba(255, 251, 254, var(--md-nav-on-section-color-opacity));
--md-nav-section-color-convert: rgba(25, 177, 212, var(--md-nav-section-color-opacity));
--md-nav-on-section-color-convert: rgba(255, 251, 254, var(--md-nav-on-section-color-opacity));
--md-nav-section-color-security: rgba(255, 120, 146, var(--md-nav-section-color-opacity));
--md-nav-on-section-color-security: rgba(255, 251, 254, var(--md-nav-on-section-color-opacity));
--md-nav-section-color-other: rgba(72, 189, 84, var(--md-nav-section-color-opacity));
--md-nav-on-section-color-other: rgba(255, 251, 254, var(--md-nav-on-section-color-opacity));
--md-nav-section-color-advance: rgba(245, 84, 84, var(--md-nav-section-color-opacity));
--md-nav-on-section-color-advance: rgba(255, 251, 254, var(--md-nav-on-section-color-opacity));
--md-nav-section-color-image: rgba(212, 172, 25, var(--md-nav-section-color-opacity));
--md-nav-on-section-color-image: rgba(255, 251, 254, var(--md-nav-on-section-color-opacity));
--md-nav-section-color-word: rgba(61, 153, 245, var(--md-nav-section-color-opacity));
--md-nav-on-section-color-word: rgba(255, 251, 254, var(--md-nav-on-section-color-opacity));
--md-nav-section-color-ppt: rgba(255, 128, 0, var(--md-nav-section-color-opacity));
--md-nav-on-section-color-ppt: rgba(255, 251, 254, var(--md-nav-on-section-color-opacity));
}

Binary file not shown.

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-123" viewBox="0 0 16 16">
<path d="M2.873 11.297V4.142H1.699L0 5.379v1.137l1.64-1.18h.06v5.961h1.174Zm3.213-5.09v-.063c0-.618.44-1.169 1.196-1.169.676 0 1.174.44 1.174 1.106 0 .624-.42 1.101-.807 1.526L4.99 10.553v.744h4.78v-.99H6.643v-.069L8.41 8.252c.65-.724 1.237-1.332 1.237-2.27C9.646 4.849 8.723 4 7.308 4c-1.573 0-2.36 1.064-2.36 2.15v.057h1.138Zm6.559 1.883h.786c.823 0 1.374.481 1.379 1.179.01.707-.55 1.216-1.421 1.21-.77-.005-1.326-.419-1.379-.953h-1.095c.042 1.053.938 1.918 2.464 1.918 1.478 0 2.642-.839 2.62-2.144-.02-1.143-.922-1.651-1.551-1.714v-.063c.535-.09 1.347-.66 1.326-1.678-.026-1.053-.933-1.855-2.359-1.845-1.5.005-2.317.88-2.348 1.898h1.116c.032-.498.498-.944 1.206-.944.703 0 1.206.435 1.206 1.07.005.64-.504 1.106-1.2 1.106h-.75v.96Z"/>
</svg>

Before

Width:  |  Height:  |  Size: 870 B

View File

@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-palette" viewBox="0 0 16 16">
<path d="M8 5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zm4 3a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3zM5.5 7a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm.5 6a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3z"/>
<path d="M16 8c0 3.15-1.866 2.585-3.567 2.07C11.42 9.763 10.465 9.473 10 10c-.603.683-.475 1.819-.351 2.92C9.826 14.495 9.996 16 8 16a8 8 0 1 1 8-8zm-8 7c.611 0 .654-.171.655-.176.078-.146.124-.464.07-1.119-.014-.168-.037-.37-.061-.591-.052-.464-.112-1.005-.118-1.462-.01-.707.083-1.61.704-2.314.369-.417.845-.578 1.272-.618.404-.038.812.026 1.16.104.343.077.702.186 1.025.284l.028.008c.346.105.658.199.953.266.653.148.904.083.991.024C14.717 9.38 15 9.161 15 8a7 7 0 1 0-7 7z"/>
</svg>

Before

Width:  |  Height:  |  Size: 795 B

View File

@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-clockwise" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M8 3a5 5 0 1 0 4.546 2.914.5.5 0 0 1 .908-.417A6 6 0 1 1 8 2v1z"/>
<path d="M8 4.466V.534a.25.25 0 0 1 .41-.192l2.36 1.966c.12.1.12.284 0 .384L8.41 4.658A.25.25 0 0 1 8 4.466z"/>
</svg>

Before

Width:  |  Height:  |  Size: 352 B

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-arrow-left-right" viewBox="0 0 16 16">
<path fill-rule="evenodd" d="M1 11.5a.5.5 0 0 0 .5.5h11.793l-3.147 3.146a.5.5 0 0 0 .708.708l4-4a.5.5 0 0 0 0-.708l-4-4a.5.5 0 0 0-.708.708L13.293 11H1.5a.5.5 0 0 0-.5.5zm14-7a.5.5 0 0 1-.5.5H2.707l3.147 3.146a.5.5 0 1 1-.708.708l-4-4a.5.5 0 0 1 0-.708l4-4a.5.5 0 1 1 .708.708L2.707 4H14.5a.5.5 0 0 1 .5.5z"/>
</svg>

Before

Width:  |  Height:  |  Size: 453 B

View File

@@ -1,4 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-award" viewBox="0 0 16 16">
<path d="M9.669.864 8 0 6.331.864l-1.858.282-.842 1.68-1.337 1.32L2.6 6l-.306 1.854 1.337 1.32.842 1.68 1.858.282L8 12l1.669-.864 1.858-.282.842-1.68 1.337-1.32L13.4 6l.306-1.854-1.337-1.32-.842-1.68L9.669.864zm1.196 1.193.684 1.365 1.086 1.072L12.387 6l.248 1.506-1.086 1.072-.684 1.365-1.51.229L8 10.874l-1.355-.702-1.51-.229-.684-1.365-1.086-1.072L3.614 6l-.25-1.506 1.087-1.072.684-1.365 1.51-.229L8 1.126l1.356.702 1.509.229z"/>
<path d="M4 11.794V16l4-1 4 1v-4.206l-2.018.306L8 13.126 6.018 12.1 4 11.794z"/>
</svg>

Before

Width:  |  Height:  |  Size: 649 B

View File

@@ -1,3 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-file" viewBox="0 0 16 16">
<path d="M4 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H4zm0 1h8a1 1 0 0 1 1 1v12a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1z"/>
</svg>

Before

Width:  |  Height:  |  Size: 284 B

Some files were not shown because too many files have changed in this diff Show More