mirror of
https://github.com/gotson/komga.git
synced 2025-12-06 08:32:25 +01:00
Compare commits
79 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
361d20df2c | ||
|
|
ced89c5c54 | ||
|
|
a5548a5429 | ||
|
|
8f8d20a324 | ||
|
|
0f69a3a4cb | ||
|
|
9d10ed31a7 | ||
|
|
dde0169f2a | ||
|
|
a2ed7d319d | ||
|
|
475f026749 | ||
|
|
a03f1bdf7b | ||
|
|
b43046fbeb | ||
|
|
3739951b36 | ||
|
|
0f25453949 | ||
|
|
cd47fc777a | ||
|
|
f138fe31e7 | ||
|
|
454c6c7202 | ||
|
|
ce3ad4c1c7 | ||
|
|
b925f3e19d | ||
|
|
9a56b30b6c | ||
|
|
6b07fda273 | ||
|
|
727fe39e6d | ||
|
|
f8ca936ee7 | ||
|
|
fe40ede34a | ||
|
|
c23f2d3810 | ||
|
|
af66144060 | ||
|
|
ba7b82631f | ||
|
|
a166f96bdf | ||
|
|
2259e4bf1c | ||
|
|
f75ad77e85 | ||
|
|
f2913d1e83 | ||
|
|
0b3307cd70 | ||
|
|
1213309f35 | ||
|
|
5a5f8d701e | ||
|
|
bdca990e82 | ||
|
|
8081439009 | ||
|
|
80c604e089 | ||
|
|
f19d7aac1e | ||
|
|
43c1018e3e | ||
|
|
eb8bdfc94c | ||
|
|
e842a5287f | ||
|
|
e0b583ff1d | ||
|
|
5e3ca4d571 | ||
|
|
730b093a5f | ||
|
|
2f9b4e75d2 | ||
|
|
d9657587c4 | ||
|
|
69ba569b04 | ||
|
|
e850cdcd2f | ||
|
|
51bfb353e7 | ||
|
|
3f64435afa | ||
|
|
166b1ee371 | ||
|
|
0e63e7454b | ||
|
|
058af49807 | ||
|
|
7888a53dbf | ||
|
|
2ec0e295fa | ||
|
|
1776174d3f | ||
|
|
b837963f0e | ||
|
|
6b4d81e0ba | ||
|
|
caf658a7bf | ||
|
|
4a598e3908 | ||
|
|
9a6f66444d | ||
|
|
ed271fc485 | ||
|
|
9ce6258914 | ||
|
|
c6a424ee92 | ||
|
|
45a105a26f | ||
|
|
0bcf1e4743 | ||
|
|
e7b56b2bee | ||
|
|
138c0ed464 | ||
|
|
777acbbd68 | ||
|
|
3ab21ff6aa | ||
|
|
4e7c49d5d8 | ||
|
|
8b629888ff | ||
|
|
30f6d3a862 | ||
|
|
ea5a4701f2 | ||
|
|
85a33d4661 | ||
|
|
d1475864af | ||
|
|
eb8a2df3ea | ||
|
|
a333b75724 | ||
|
|
54c818e857 | ||
|
|
18ec31f28b |
93 changed files with 4454 additions and 557 deletions
2
.github/workflows/browserlist-update.yml
vendored
2
.github/workflows/browserlist-update.yml
vendored
|
|
@ -14,7 +14,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Configure git
|
||||
|
|
|
|||
2
.github/workflows/dispatch.yml
vendored
2
.github/workflows/dispatch.yml
vendored
|
|
@ -11,7 +11,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Repository Dispatch
|
||||
uses: peter-evans/repository-dispatch@v3
|
||||
uses: peter-evans/repository-dispatch@v4
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
repository: gotson/komga-website
|
||||
|
|
|
|||
2
.github/workflows/dockerhub_description.yml
vendored
2
.github/workflows/dockerhub_description.yml
vendored
|
|
@ -15,7 +15,7 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- name: DockerHub Description
|
||||
uses: peter-evans/dockerhub-description@v4.0.2
|
||||
uses: peter-evans/dockerhub-description@v5.0.0
|
||||
env:
|
||||
DOCKERHUB_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||
DOCKERHUB_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
|
|
|||
28
.github/workflows/release.yml
vendored
28
.github/workflows/release.yml
vendored
|
|
@ -43,14 +43,14 @@ jobs:
|
|||
version_next: ${{ steps.versions.outputs.version_next }}
|
||||
should_release: ${{ steps.versions.outputs.should_release }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up Homebrew
|
||||
id: set-up-homebrew
|
||||
uses: Homebrew/actions/setup-homebrew@master
|
||||
- name: Install svu
|
||||
run: brew install caarlos0/tap/svu
|
||||
run: brew install --cask caarlos0/tap/svu
|
||||
- name: Compute next version for release
|
||||
run: |
|
||||
echo "VERSION_NEXT=`svu ${{ inputs.bump }}`" | tee -a $GITHUB_ENV
|
||||
|
|
@ -72,7 +72,7 @@ jobs:
|
|||
sudo rm -rf /usr/share/dotnet
|
||||
sudo rm -rf "$AGENT_TOOLSDIRECTORY"
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
|
|
@ -84,14 +84,14 @@ jobs:
|
|||
if: needs.version.outputs.should_release #only redo if the version changed
|
||||
run: sed -i -e "s/version=.*/version=${{ needs.version.outputs.version_next }}/" gradle.properties
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: komga-webui/package-lock.json
|
||||
|
||||
- name: Setup Java 21
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
java-version: 21
|
||||
java-package: 'jdk'
|
||||
|
|
@ -117,7 +117,7 @@ jobs:
|
|||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
uses: gradle/actions/setup-gradle@v5
|
||||
|
||||
- name: Build
|
||||
run: ./gradlew :komga:prepareThymeLeaf :komga:bootJar :komga-tray:jar
|
||||
|
|
@ -143,7 +143,7 @@ jobs:
|
|||
JRELEASER_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: JReleaser Changelog output
|
||||
if: always() && needs.version.outputs.should_release
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: jreleaser-changelog
|
||||
path: |
|
||||
|
|
@ -167,7 +167,7 @@ jobs:
|
|||
echo $APPLE_PRIVATE_KEY | base64 --decode > ./secret/apple_private_key.p8
|
||||
|
||||
- name: Conveyor make copied-site
|
||||
uses: hydraulic-software/conveyor/actions/build@v18.1
|
||||
uses: hydraulic-software/conveyor/actions/build@v20.0
|
||||
if: inputs.conveyor-copied-site
|
||||
with:
|
||||
command: --cache-limit=2.0 -f conveyor.ci.conf make copied-site -o ./output/site
|
||||
|
|
@ -182,7 +182,7 @@ jobs:
|
|||
AWS_SECRET_ACCESS_KEY: ${{ secrets.B2_SECRET_ACCESS_KEY }}
|
||||
- name: Upload Conveyor log
|
||||
if: always() && inputs.conveyor-copied-site
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: conveyor-make-copied-site
|
||||
path: ~/.cache/hydraulic/conveyor/logs/log.latest.txt
|
||||
|
|
@ -194,7 +194,7 @@ jobs:
|
|||
JRELEASER_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: JReleaser Release output
|
||||
if: always() && inputs.github_release
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: jreleaser-release
|
||||
path: |
|
||||
|
|
@ -212,7 +212,7 @@ jobs:
|
|||
JRELEASER_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: JReleaser Publish output
|
||||
if: always() && inputs.docker_release
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: jreleaser-publish
|
||||
path: |
|
||||
|
|
@ -220,7 +220,7 @@ jobs:
|
|||
build/jreleaser/output.properties
|
||||
|
||||
- name: Conveyor - publish to Microsoft Store
|
||||
uses: hydraulic-software/conveyor/actions/build@v18.1
|
||||
uses: hydraulic-software/conveyor/actions/build@v20.0
|
||||
if: inputs.msstore_release
|
||||
with:
|
||||
command: --cache-limit=2.0 -f conveyor.msstore.ci.conf make ms-store-release -o ./output/msstore
|
||||
|
|
@ -236,7 +236,7 @@ jobs:
|
|||
AWS_SECRET_ACCESS_KEY: ${{ secrets.B2_SECRET_ACCESS_KEY }}
|
||||
- name: Upload Conveyor log
|
||||
if: always() && inputs.msstore_release
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: conveyor-ms-store-release
|
||||
path: ~/.cache/hydraulic/conveyor/logs/log.latest.txt
|
||||
|
|
@ -246,7 +246,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Repository Dispatch
|
||||
uses: peter-evans/repository-dispatch@v3
|
||||
uses: peter-evans/repository-dispatch@v4
|
||||
with:
|
||||
token: ${{ secrets.REPO_ACCESS_TOKEN }}
|
||||
repository: gotson/komga-website
|
||||
|
|
|
|||
20
.github/workflows/tests.yml
vendored
20
.github/workflows/tests.yml
vendored
|
|
@ -19,36 +19,36 @@ jobs:
|
|||
fail-fast: false
|
||||
name: Test server - ${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v6
|
||||
- name: Setup Java 21
|
||||
uses: actions/setup-java@v4
|
||||
uses: actions/setup-java@v5
|
||||
with:
|
||||
java-version: 21
|
||||
java-package: 'jdk'
|
||||
distribution: 'temurin'
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
uses: gradle/actions/setup-gradle@v5
|
||||
|
||||
- name: Build
|
||||
run: ./gradlew build :komga-tray:jar
|
||||
|
||||
- name: Upload Unit Test Results
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: test-results-${{ matrix.os }}
|
||||
path: komga/build/test-results/
|
||||
|
||||
- name: Upload Unit Test Reports
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: test-reports-${{ matrix.os }}
|
||||
path: komga/build/reports/tests/
|
||||
|
||||
- name: Publish Test Report
|
||||
uses: mikepenz/action-junit-report@v5
|
||||
uses: mikepenz/action-junit-report@v6
|
||||
if: always()
|
||||
with:
|
||||
report_paths: '**/build/test-results/test/TEST-*.xml'
|
||||
|
|
@ -56,7 +56,7 @@ jobs:
|
|||
|
||||
- name: Conveyor - compute JDK module list
|
||||
if: github.event_name == 'push' && github.repository_owner == 'gotson' && contains(matrix.os, 'ubuntu')
|
||||
uses: hydraulic-software/conveyor/actions/build@v18.1
|
||||
uses: hydraulic-software/conveyor/actions/build@v20.0
|
||||
with:
|
||||
command: -f conveyor.detect.conf -Kapp.machines=mac.aarch64 make processed-jars
|
||||
signing_key: ${{ secrets.CONVEYOR_SIGNING_KEY }}
|
||||
|
|
@ -69,7 +69,7 @@ jobs:
|
|||
|
||||
- name: Upload JDK required modules
|
||||
if: steps.conveyor_compare.outcome == 'failure'
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v5
|
||||
with:
|
||||
name: conveyor-required-jdk-modules
|
||||
path: ./output/required-jdk-modules.txt
|
||||
|
|
@ -78,8 +78,8 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
name: Test webui builds
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/setup-node@v4
|
||||
- uses: actions/checkout@v6
|
||||
- uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version-file: '.nvmrc'
|
||||
cache: 'npm'
|
||||
|
|
|
|||
186
CHANGELOG.md
186
CHANGELOG.md
|
|
@ -1,3 +1,189 @@
|
|||
# [1.23.6](https://github.com/gotson/komga/compare/1.23.5...1.23.6) (2025-11-28)
|
||||
## 🐛 Fixes
|
||||
**kobo**
|
||||
- proxy 401 errors on initialization ([3739951](https://github.com/gotson/komga/commits/3739951))
|
||||
- prevent double URL encoding when proxying ([ce3ad4c](https://github.com/gotson/komga/commits/ce3ad4c)), closes [#2130](https://github.com/gotson/komga/issues/2130)
|
||||
- proxy Content-Type headers for kobo ([b925f3e](https://github.com/gotson/komga/commits/b925f3e)), closes [#2074](https://github.com/gotson/komga/issues/2074)
|
||||
|
||||
**unscoped**
|
||||
- properly decode cover href when generating epub cover ([f8ca936](https://github.com/gotson/komga/commits/f8ca936)), closes [#2118](https://github.com/gotson/komga/issues/2118)
|
||||
|
||||
## 🔄️ Changes
|
||||
**kobo**
|
||||
- log error responses ([454c6c7](https://github.com/gotson/komga/commits/454c6c7))
|
||||
|
||||
## 🛠 Build
|
||||
**docker**
|
||||
- use old-releases apt repo ([ba7b826](https://github.com/gotson/komga/commits/ba7b826))
|
||||
|
||||
**webui**
|
||||
- update Browserslist db ([727fe39](https://github.com/gotson/komga/commits/727fe39))
|
||||
|
||||
**unscoped**
|
||||
- fix svu install ([9a56b30](https://github.com/gotson/komga/commits/9a56b30))
|
||||
|
||||
## 📝 Documentation
|
||||
**api**
|
||||
- fix mediatype ([af66144](https://github.com/gotson/komga/commits/af66144))
|
||||
|
||||
## 🌐 Translation
|
||||
**komga-tray**
|
||||
- translated using Weblate (Arabic) ([a5548a5](https://github.com/gotson/komga/commits/a5548a5))
|
||||
- translated using Weblate (Russian) ([8f8d20a](https://github.com/gotson/komga/commits/8f8d20a))
|
||||
- translated using Weblate (Galician) ([0f69a3a](https://github.com/gotson/komga/commits/0f69a3a))
|
||||
|
||||
**webui**
|
||||
- translated using Weblate (Croatian) ([dde0169](https://github.com/gotson/komga/commits/dde0169))
|
||||
- translated using Weblate (Russian) ([a2ed7d3](https://github.com/gotson/komga/commits/a2ed7d3))
|
||||
- translated using Weblate (Portuguese (Brazil)) ([475f026](https://github.com/gotson/komga/commits/475f026))
|
||||
- translated using Weblate (Thai) ([a03f1bd](https://github.com/gotson/komga/commits/a03f1bd))
|
||||
|
||||
## ⚙️ Dependencies
|
||||
**ci**
|
||||
- bump actions/checkout from 5 to 6 ([f138fe3](https://github.com/gotson/komga/commits/f138fe3))
|
||||
- bump mikepenz/action-junit-report from 5 to 6 ([6b07fda](https://github.com/gotson/komga/commits/6b07fda))
|
||||
- bump actions/upload-artifact from 4 to 5 ([fe40ede](https://github.com/gotson/komga/commits/fe40ede))
|
||||
- bump actions/setup-node from 5 to 6 ([c23f2d3](https://github.com/gotson/komga/commits/c23f2d3))
|
||||
|
||||
**webui**
|
||||
- bump node-forge from 1.3.1 to 1.3.2 in /komga-webui ([0f25453](https://github.com/gotson/komga/commits/0f25453))
|
||||
- bump js-yaml from 3.14.1 to 3.14.2 in /komga-webui ([cd47fc7](https://github.com/gotson/komga/commits/cd47fc7))
|
||||
|
||||
# [1.23.5](https://github.com/gotson/komga/compare/1.23.4...1.23.5) (2025-10-08)
|
||||
## 🚀 Features
|
||||
|
||||
- support local artwork in gif format ([f19d7aa](https://github.com/gotson/komga/commits/f19d7aa)), closes [#1853](https://github.com/gotson/komga/issues/1853)
|
||||
|
||||
## 🐛 Fixes
|
||||
**api**
|
||||
- empty content when x-api-key is sent alongside session ([5a5f8d7](https://github.com/gotson/komga/commits/5a5f8d7)), closes [#2099](https://github.com/gotson/komga/issues/2099)
|
||||
- relax JSON deserializer ([eb8bdfc](https://github.com/gotson/komga/commits/eb8bdfc))
|
||||
- add id field in HistoricalEventDto ([5e3ca4d](https://github.com/gotson/komga/commits/5e3ca4d))
|
||||
|
||||
## 🏎 Perf
|
||||
**api**
|
||||
- remove no-transform cache-control from response header ([43c1018](https://github.com/gotson/komga/commits/43c1018)), closes [#2091](https://github.com/gotson/komga/issues/2091)
|
||||
|
||||
## 🔄️ Changes
|
||||
|
||||
- add more logs when epub extension is missing ([730b093](https://github.com/gotson/komga/commits/730b093))
|
||||
- add more logs to koreader sync controller ([2f9b4e7](https://github.com/gotson/komga/commits/2f9b4e7))
|
||||
- make dslRO transaction aware ([69ba569](https://github.com/gotson/komga/commits/69ba569))
|
||||
|
||||
## 🛠 Build
|
||||
**webui**
|
||||
- update Browserslist db ([e842a52](https://github.com/gotson/komga/commits/e842a52))
|
||||
|
||||
## 🌐 Translation
|
||||
**komga-tray**
|
||||
- translated using Weblate (Portuguese (Brazil)) ([2259e4b](https://github.com/gotson/komga/commits/2259e4b))
|
||||
|
||||
**webui**
|
||||
- translated using Weblate (Slovak) ([f75ad77](https://github.com/gotson/komga/commits/f75ad77))
|
||||
- translated using Weblate (Croatian) ([f2913d1](https://github.com/gotson/komga/commits/f2913d1))
|
||||
- translated using Weblate (Czech) ([0b3307c](https://github.com/gotson/komga/commits/0b3307c))
|
||||
- translated using Weblate (Portuguese (Brazil)) ([1213309](https://github.com/gotson/komga/commits/1213309))
|
||||
|
||||
## ⚙️ Dependencies
|
||||
**ci**
|
||||
- bump peter-evans/dockerhub-description from 4.0.2 to 5.0.0 ([bdca990](https://github.com/gotson/komga/commits/bdca990))
|
||||
- bump gradle/actions from 4 to 5 ([8081439](https://github.com/gotson/komga/commits/8081439))
|
||||
- bump peter-evans/repository-dispatch from 3 to 4 ([80c604e](https://github.com/gotson/komga/commits/80c604e))
|
||||
- bump hydraulic-software/conveyor from 19.0 to 20.0 ([e0b583f](https://github.com/gotson/komga/commits/e0b583f))
|
||||
|
||||
**webui**
|
||||
- bump axios from 1.8.2 to 1.12.0 in /komga-webui ([d965758](https://github.com/gotson/komga/commits/d965758))
|
||||
|
||||
# [1.23.4](https://github.com/gotson/komga/compare/1.23.3...1.23.4) (2025-09-09)
|
||||
## 🐛 Fixes
|
||||
**kobo**
|
||||
- update default kobo resources ([166b1ee](https://github.com/gotson/komga/commits/166b1ee)), closes [#2066](https://github.com/gotson/komga/issues/2066)
|
||||
- fail to create proxy url ([058af49](https://github.com/gotson/komga/commits/058af49)), closes [#2063](https://github.com/gotson/komga/issues/2063)
|
||||
|
||||
## 🏎 Perf
|
||||
|
||||
- send events outside of db transaction ([51bfb35](https://github.com/gotson/komga/commits/51bfb35))
|
||||
|
||||
## 🧪 Tests
|
||||
|
||||
- run tests with a WAL database instead of memorydb ([7888a53](https://github.com/gotson/komga/commits/7888a53))
|
||||
|
||||
## 🛠 Build
|
||||
**webui**
|
||||
- update Browserslist db ([0e63e74](https://github.com/gotson/komga/commits/0e63e74))
|
||||
|
||||
## ⚙️ Dependencies
|
||||
**ci**
|
||||
- bump actions/setup-node from 4 to 5 ([3f64435](https://github.com/gotson/komga/commits/3f64435))
|
||||
|
||||
# [1.23.3](https://github.com/gotson/komga/compare/1.23.2...1.23.3) (2025-08-28)
|
||||
## 🐛 Fixes
|
||||
**api**
|
||||
- cannot create readlist or collection with database in WAL mode ([1776174](https://github.com/gotson/komga/commits/1776174))
|
||||
|
||||
## 🛠 Build
|
||||
**release**
|
||||
- fail jreleaser on publish errors ([6b4d81e](https://github.com/gotson/komga/commits/6b4d81e))
|
||||
|
||||
## ⚙️ Dependencies
|
||||
**ci**
|
||||
- bump actions/setup-java from 4 to 5 ([b837963](https://github.com/gotson/komga/commits/b837963))
|
||||
|
||||
# [1.23.2](https://github.com/gotson/komga/compare/1.23.1...1.23.2) (2025-08-25)
|
||||
## 🐛 Fixes
|
||||
**kobo**
|
||||
- NullPointer exception ([138c0ed](https://github.com/gotson/komga/commits/138c0ed)), closes [#2045](https://github.com/gotson/komga/issues/2045)
|
||||
|
||||
**webui**
|
||||
- ignore content negotiation when downloading page ([85a33d4](https://github.com/gotson/komga/commits/85a33d4)), closes [#2042](https://github.com/gotson/komga/issues/2042)
|
||||
|
||||
**unscoped**
|
||||
- ignore xml namespace in EPUB opf file ([3ab21ff](https://github.com/gotson/komga/commits/3ab21ff)), closes [#2043](https://github.com/gotson/komga/issues/2043)
|
||||
|
||||
## 🏎 Perf
|
||||
|
||||
- enable SQLite WAL mode by default ([e7b56b2](https://github.com/gotson/komga/commits/e7b56b2))
|
||||
|
||||
## 🔄️ Changes
|
||||
**api**
|
||||
- mark kepubifyPath as deprecated ([d147586](https://github.com/gotson/komga/commits/d147586))
|
||||
|
||||
**unscoped**
|
||||
- use Jsoup XmlParser instead of HTML parser where needed ([4e7c49d](https://github.com/gotson/komga/commits/4e7c49d))
|
||||
|
||||
## 🛠 Build
|
||||
**deps**
|
||||
- move redundant versions to gradle version catalog ([18ec31f](https://github.com/gotson/komga/commits/18ec31f))
|
||||
|
||||
## 📝 Documentation
|
||||
|
||||
- update sponsors ([0bcf1e4](https://github.com/gotson/komga/commits/0bcf1e4))
|
||||
|
||||
## 🌐 Translation
|
||||
**komga-tray**
|
||||
- translated using Weblate (Slovak) ([4a598e3](https://github.com/gotson/komga/commits/4a598e3))
|
||||
- translated using Weblate (Assamese) ([9ce6258](https://github.com/gotson/komga/commits/9ce6258))
|
||||
- added translation using Weblate (Slovak) ([c6a424e](https://github.com/gotson/komga/commits/c6a424e))
|
||||
- translated using Weblate (Ukrainian) ([45a105a](https://github.com/gotson/komga/commits/45a105a))
|
||||
|
||||
**webui**
|
||||
- translated using Weblate (Slovak) ([9a6f664](https://github.com/gotson/komga/commits/9a6f664))
|
||||
- translated using Weblate (Ukrainian) ([ed271fc](https://github.com/gotson/komga/commits/ed271fc))
|
||||
|
||||
## ⚙️ Dependencies
|
||||
**ci**
|
||||
- bump actions/checkout from 4 to 5 ([ea5a470](https://github.com/gotson/komga/commits/ea5a470))
|
||||
- bump hydraulic-software/conveyor from 18.1 to 19.0 ([a333b75](https://github.com/gotson/komga/commits/a333b75))
|
||||
|
||||
**webui**
|
||||
- bump brace-expansion from 1.1.11 to 1.1.12 in /komga-webui ([777acbb](https://github.com/gotson/komga/commits/777acbb))
|
||||
- bump ws in /komga-webui ([30f6d3a](https://github.com/gotson/komga/commits/30f6d3a))
|
||||
|
||||
**unscoped**
|
||||
- bump jsoup to 1.21.1 ([8b62988](https://github.com/gotson/komga/commits/8b62988))
|
||||
- bump nightcompress from 1.1.0 to 1.1.1 ([eb8a2df](https://github.com/gotson/komga/commits/eb8a2df))
|
||||
- bump ktlint from 1.6.0 to 1.7.1 ([54c818e](https://github.com/gotson/komga/commits/54c818e))
|
||||
|
||||
# [1.23.1](https://github.com/gotson/komga/compare/1.23.0...1.23.1) (2025-08-01)
|
||||
## 🐛 Fixes
|
||||
**api**
|
||||
|
|
|
|||
|
|
@ -51,6 +51,12 @@ Check the [development guidelines](./DEVELOPING.md).
|
|||
|
||||
[](https://www.jetbrains.com/?from=Komga)
|
||||
|
||||
Thanks to [JetBrains](https://www.jetbrains.com/?from=Komga) for providing the development environment that helps us develop Komga.
|
||||
|
||||
[](https://www.chromatic.com)
|
||||
|
||||
Thanks to [Chromatic](https://www.chromatic.com/) for providing the visual testing platform that helps us review UI changes and catch visual regressions.
|
||||
|
||||
## Credits
|
||||
|
||||
The Komga icon is based on an icon made by [Freepik](https://www.freepik.com/home) from www.flaticon.com
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ allprojects {
|
|||
}
|
||||
|
||||
configure<org.jlleitschuh.gradle.ktlint.KtlintExtension> {
|
||||
version = "1.6.0"
|
||||
version = "1.7.1"
|
||||
filter {
|
||||
exclude("**/generated-src/**")
|
||||
exclude("**/generated/**")
|
||||
|
|
@ -164,7 +164,7 @@ jreleaser {
|
|||
packagers {
|
||||
docker {
|
||||
active = Active.RELEASE
|
||||
continueOnError = true
|
||||
continueOnError = false
|
||||
templateDirectory = rootDir.resolve("komga/docker")
|
||||
repository.active = Active.NEVER
|
||||
buildArgs = listOf("--cache-from", "gotson/komga:latest")
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
version=1.23.1
|
||||
version=1.23.6
|
||||
org.gradle.jvmargs=-Xmx2G
|
||||
|
|
|
|||
10
gradle/libs.versions.toml
Normal file
10
gradle/libs.versions.toml
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
[versions]
|
||||
sqliteJdbc = "3.50.2.0"
|
||||
nightmonkeys = "1.0.0"
|
||||
twelvemonkeys = "3.12.0"
|
||||
springboot = "3.5.4"
|
||||
lucene = "9.9.1" # v10 requires JDK 21
|
||||
jooq = "3.19.24" # should be aligned with the version provided by Spring Boot
|
||||
|
||||
[plugins]
|
||||
gradleGitProperties = {id = "com.gorylenko.gradle-git-properties", version = "2.5.2"}
|
||||
|
|
@ -5,7 +5,7 @@ plugins {
|
|||
kotlin("jvm")
|
||||
kotlin("plugin.spring")
|
||||
}
|
||||
id("com.gorylenko.gradle-git-properties") version "2.5.2"
|
||||
alias(libs.plugins.gradleGitProperties)
|
||||
id("org.jetbrains.compose") version "1.8.2"
|
||||
id("org.jetbrains.kotlin.plugin.compose") version "2.2.0"
|
||||
id("dev.hydraulic.conveyor") version "1.12"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
dialog_error.close=إغلاق
|
||||
dialog_error.copy_clipboard=النسخ إلى الحافظة
|
||||
dialog_error.title=Komga لم يقدر على البدء
|
||||
error_message.port_in_use=الباب {} على قيد الاستعمال.\nربما Komga جارٍ بالفعل.\nتحقق أيقونة علبة النظام أو القائمة لأيقونة Komga.
|
||||
error_message.unexpected=حصل خطأ غير متوقع.
|
||||
menu.open_komga=فتح Komga
|
||||
menu.quit=إغلاق Komga
|
||||
menu.show_conf_dir=فتح موقع الإعدادات
|
||||
menu.show_log=إظهار ملف السجل
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
dialog_error.close=বন্ধ কৰক
|
||||
dialog_error.copy_clipboard=ক্লিপবোর্ডলৈ কপি কৰক
|
||||
dialog_error.title=Komga আৰম্ভ কৰাত ব্যৰ্থ হ’ল
|
||||
error_message.port_in_use={} পৰ্ট ইতিমধ্যে ব্যৱহাৰ কৰা হৈছে।\nKomga চাগে ইতিমধ্যে চলি আছে।\nKomga আইকনৰ বাবে ট্ৰে আইকন বা মেনু বাৰ পৰীক্ষা কৰক।
|
||||
error_message.unexpected=এটা অপ্ৰত্যাশিত ভুল ঘটিল।
|
||||
menu.open_komga=Komga খুলিব
|
||||
menu.quit=Komga এৰি দিয়ক
|
||||
menu.show_conf_dir=বিন্যাস পঞ্জিকা খোলক
|
||||
dialog_error.copy_clipboard=ক্লিপব’ৰ্ডলৈ কপি কৰক
|
||||
dialog_error.title=কমগা আৰম্ভ কৰাত বিফল
|
||||
error_message.port_in_use={} প’ৰ্ট ইতিমধ্যে ব্যৱহৃত।\nকমগা সম্ভৱতঃ ইতিমধ্যে চলি আছে।\nকমগা আইকনৰ বাবে ট্ৰে আইকন বা মেনু বাৰ পৰীক্ষা কৰক।
|
||||
error_message.unexpected=এক অপ্ৰত্যাশিত ত্ৰুটি ঘটিল।
|
||||
menu.open_komga=কমগা খোলক
|
||||
menu.quit=কমগা বন্ধ কৰক
|
||||
menu.show_conf_dir=বিন্যাস ডাইৰেক্টৰি খোলক
|
||||
menu.show_log=লগ ফাইল দেখুৱাওক
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
dialog_error.close=Pechar
|
||||
dialog_error.copy_clipboard=Copiar ao portapapeis
|
||||
dialog_error.title=Komga fallou ao iniciar
|
||||
error_message.port_in_use=O porto {} está en uso.\nÉ probable que Komga xa esté a executarse.\nBusca a icona de Komga na bandexa de sistema ou a barra de menú.
|
||||
error_message.unexpected=Aconteceu un erro imprevisto.
|
||||
menu.open_komga=Abrir Komga
|
||||
menu.quit=Saír de Komga
|
||||
menu.show_conf_dir=Abrir o cartafol de configuración
|
||||
menu.show_log=Amosar o ficheiro de rexistro
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
dialog_error.close=Fechar
|
||||
dialog_error.copy_clipboard=Copiar para área de transferência
|
||||
dialog_error.title=Komga falhou ao inicializar
|
||||
error_message.port_in_use=A porta {} já está em uso.\nProvavelmente o Komga já está rodando.\nVerifique o ícone na barra de tarefas ou a barra de menu.
|
||||
error_message.unexpected=Ocorreu um erro inesperado.
|
||||
menu.open_komga=Abrir Komga
|
||||
menu.quit=Sair do Komga
|
||||
menu.show_conf_dir=Abrir configuração de diretório
|
||||
menu.show_log=Mostrar arquivo de logs
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
dialog_error.close=Закрыть
|
||||
dialog_error.copy_clipboard=Скопировать в буфер обмена
|
||||
dialog_error.title=Komga не смог запуститься
|
||||
error_message.port_in_use=Порт {] уже используется.\nKomga возможно уже работает.\nПроверьте панель задач или меню на наличие иконки Komga.
|
||||
dialog_error.title=Komga не удалось запустить
|
||||
error_message.port_in_use=Порт {} уже используется.\nВероятно, Komga уже запущен.\nПроверьте область уведомлений или панель меню на наличие иконки Komga.
|
||||
error_message.unexpected=Произошла непредвиденная ошибка.
|
||||
menu.open_komga=Открыть Komga
|
||||
menu.quit=Закрыть Komga
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
dialog_error.close=Zavrieť
|
||||
dialog_error.copy_clipboard=Skopírovať do schránky
|
||||
dialog_error.title=Aplikáciu Komga sa nepodarilo spustiť
|
||||
error_message.port_in_use=Port {} sa aktuálne používa.\nAplikácia Komga je pravdepodobne už spustená.\nSkontrolujte, či ikona Komga už nie je v systémovej lište alebo medzi schovanými ikonami.
|
||||
error_message.unexpected=Nastala neočakávaná chyba.
|
||||
menu.open_komga=Otvoriť aplikáciu Komga
|
||||
menu.quit=Zavrieť aplikáciu Komga
|
||||
menu.show_conf_dir=Otvoriť konfiguračný priečinok
|
||||
menu.show_log=Zobraziť logy
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
dialog_error.close=Закрити
|
||||
dialog_error.copy_clipboard=Копіювати в буфер обміну
|
||||
dialog_error.title=Помилка при запуску Komga
|
||||
error_message.port_in_use=Порт {} вже використовується.\nKomga напевно вже запущена.\nПеревірте панель запущених програм на наявність іконки Komga.
|
||||
error_message.unexpected=Сталася невідома помилка.
|
||||
|
|
|
|||
375
komga-webui/package-lock.json
generated
375
komga-webui/package-lock.json
generated
|
|
@ -10,7 +10,7 @@
|
|||
"dependencies": {
|
||||
"@d-i-t-a/reader": "github:gotson/R2D2BC#fork",
|
||||
"@saekitominaga/isbn-verify": "^2.0.1",
|
||||
"axios": "^1.8.2",
|
||||
"axios": "^1.12.0",
|
||||
"chart.js": "^2.9.4",
|
||||
"core-js": "^3.8.3",
|
||||
"date-fns": "^2.30.0",
|
||||
|
|
@ -5102,13 +5102,12 @@
|
|||
"integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg=="
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.8.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.8.2.tgz",
|
||||
"integrity": "sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==",
|
||||
"license": "MIT",
|
||||
"version": "1.12.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.12.0.tgz",
|
||||
"integrity": "sha512-oXTDccv8PcfjZmPGlWsPSwtOJCZ/b6W5jAMCNcfwJbCzDckwG0jrYJFaWH1yvivfCXjVzV/SPDEhMB3Q+DSurg==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.0",
|
||||
"form-data": "^4.0.4",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
|
|
@ -5512,9 +5511,9 @@
|
|||
"integrity": "sha512-rJKn5ooC9u8q13IMCrW0RSp31pxBCHE3y9V/tp3TdWSLf8Em3p6Di4NBpfzbJge9YjjFEsD0RtFEjtvHL5VyEA=="
|
||||
},
|
||||
"node_modules/brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
|
@ -5715,6 +5714,18 @@
|
|||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/call-bind-apply-helpers": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/callsite": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
|
||||
|
|
@ -5768,9 +5779,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/caniuse-lite": {
|
||||
"version": "1.0.30001731",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001731.tgz",
|
||||
"integrity": "sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg==",
|
||||
"version": "1.0.30001757",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001757.tgz",
|
||||
"integrity": "sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
|
|
@ -7288,6 +7299,19 @@
|
|||
"integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"gopd": "^1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/duplexer": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
|
||||
|
|
@ -7371,9 +7395,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/editorconfig/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
|
|
@ -7614,12 +7638,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/es-define-property": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
|
||||
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
|
||||
"dependencies": {
|
||||
"get-intrinsic": "^1.2.4"
|
||||
},
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
|
|
@ -7638,15 +7659,26 @@
|
|||
"integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/es-set-tostringtag": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
|
||||
"integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==",
|
||||
"dev": true,
|
||||
"node_modules/es-object-atoms": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||
"dependencies": {
|
||||
"get-intrinsic": "^1.1.3",
|
||||
"has": "^1.0.3",
|
||||
"has-tostringtag": "^1.0.0"
|
||||
"es-errors": "^1.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/es-set-tostringtag": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"get-intrinsic": "^1.2.6",
|
||||
"has-tostringtag": "^1.0.2",
|
||||
"hasown": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
|
|
@ -8906,9 +8938,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/filehound/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
|
|
@ -9240,12 +9272,14 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
|
||||
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
|
||||
"dependencies": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"es-set-tostringtag": "^2.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"mime-types": "^2.1.12"
|
||||
},
|
||||
"engines": {
|
||||
|
|
@ -9406,15 +9440,20 @@
|
|||
}
|
||||
},
|
||||
"node_modules/get-intrinsic": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
|
||||
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||
"dependencies": {
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
"es-define-property": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"es-object-atoms": "^1.1.1",
|
||||
"function-bind": "^1.1.2",
|
||||
"has-proto": "^1.0.1",
|
||||
"has-symbols": "^1.0.3",
|
||||
"hasown": "^2.0.0"
|
||||
"get-proto": "^1.0.1",
|
||||
"gopd": "^1.2.0",
|
||||
"has-symbols": "^1.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"math-intrinsics": "^1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
|
|
@ -9432,6 +9471,18 @@
|
|||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/get-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||
"dependencies": {
|
||||
"dunder-proto": "^1.0.1",
|
||||
"es-object-atoms": "^1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/get-stream": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
|
||||
|
|
@ -9549,11 +9600,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/gopd": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
|
||||
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
|
||||
"dependencies": {
|
||||
"get-intrinsic": "^1.1.3"
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
|
|
@ -9657,6 +9708,7 @@
|
|||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
|
|
@ -9665,9 +9717,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/has-symbols": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
||||
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
|
|
@ -9676,11 +9728,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/has-tostringtag": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
|
||||
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||
"dependencies": {
|
||||
"has-symbols": "^1.0.2"
|
||||
"has-symbols": "^1.0.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
|
|
@ -12915,9 +12967,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/js-beautify/node_modules/brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"balanced-match": "^1.0.0"
|
||||
|
|
@ -12974,9 +13026,9 @@
|
|||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
|
||||
},
|
||||
"node_modules/js-yaml": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
||||
"version": "3.14.2",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
|
||||
"integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"argparse": "^1.0.7",
|
||||
|
|
@ -13683,6 +13735,14 @@
|
|||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/math-intrinsics": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
},
|
||||
"node_modules/mdn-data": {
|
||||
"version": "2.0.30",
|
||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
|
||||
|
|
@ -14101,9 +14161,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/node-forge": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
|
||||
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.2.tgz",
|
||||
"integrity": "sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">= 6.13.0"
|
||||
|
|
@ -19404,9 +19464,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/webpack-dev-server/node_modules/ws": {
|
||||
"version": "8.14.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.14.1.tgz",
|
||||
"integrity": "sha512-4OOseMUq8AzRBI/7SLMUwO+FEDnguetSk7KMb1sHwvF2w2Wv5Hoj0nlifx8vtGsftE/jWHojPy8sMMzYLJ2G/A==",
|
||||
"version": "8.18.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
|
||||
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
|
|
@ -19657,9 +19717,9 @@
|
|||
}
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "7.5.9",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
||||
"version": "7.5.10",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
|
||||
"integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
|
||||
"dev": true,
|
||||
"engines": {
|
||||
"node": ">=8.3.0"
|
||||
|
|
@ -23587,12 +23647,12 @@
|
|||
"integrity": "sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg=="
|
||||
},
|
||||
"axios": {
|
||||
"version": "1.8.2",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.8.2.tgz",
|
||||
"integrity": "sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==",
|
||||
"version": "1.12.0",
|
||||
"resolved": "https://registry.npmjs.org/axios/-/axios-1.12.0.tgz",
|
||||
"integrity": "sha512-oXTDccv8PcfjZmPGlWsPSwtOJCZ/b6W5jAMCNcfwJbCzDckwG0jrYJFaWH1yvivfCXjVzV/SPDEhMB3Q+DSurg==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.0",
|
||||
"form-data": "^4.0.4",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
}
|
||||
},
|
||||
|
|
@ -23911,9 +23971,9 @@
|
|||
"integrity": "sha512-rJKn5ooC9u8q13IMCrW0RSp31pxBCHE3y9V/tp3TdWSLf8Em3p6Di4NBpfzbJge9YjjFEsD0RtFEjtvHL5VyEA=="
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"version": "1.1.12",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
|
@ -24043,6 +24103,15 @@
|
|||
"set-function-length": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"call-bind-apply-helpers": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
|
||||
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
|
||||
"requires": {
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"callsite": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz",
|
||||
|
|
@ -24084,9 +24153,9 @@
|
|||
}
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001731",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001731.tgz",
|
||||
"integrity": "sha512-lDdp2/wrOmTRWuoB5DpfNkC0rJDU8DqRa6nYL6HK6sytw70QMopt/NIc/9SM7ylItlBWfACXk0tEn37UWM/+mg=="
|
||||
"version": "1.0.30001757",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001757.tgz",
|
||||
"integrity": "sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ=="
|
||||
},
|
||||
"case-sensitive-paths-webpack-plugin": {
|
||||
"version": "2.4.0",
|
||||
|
|
@ -25214,6 +25283,16 @@
|
|||
"integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==",
|
||||
"dev": true
|
||||
},
|
||||
"dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
|
||||
"requires": {
|
||||
"call-bind-apply-helpers": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"gopd": "^1.2.0"
|
||||
}
|
||||
},
|
||||
"duplexer": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
|
||||
|
|
@ -25290,9 +25369,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0"
|
||||
|
|
@ -25489,12 +25568,9 @@
|
|||
}
|
||||
},
|
||||
"es-define-property": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
|
||||
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
|
||||
"requires": {
|
||||
"get-intrinsic": "^1.2.4"
|
||||
}
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
|
||||
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="
|
||||
},
|
||||
"es-errors": {
|
||||
"version": "1.3.0",
|
||||
|
|
@ -25507,15 +25583,23 @@
|
|||
"integrity": "sha512-JUFAyicQV9mXc3YRxPnDlrfBKpqt6hUYzz9/boprUJHs4e4KVr3XwOF70doO6gwXUor6EWZJAyWAfKki84t20Q==",
|
||||
"dev": true
|
||||
},
|
||||
"es-set-tostringtag": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz",
|
||||
"integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==",
|
||||
"dev": true,
|
||||
"es-object-atoms": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
|
||||
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
|
||||
"requires": {
|
||||
"get-intrinsic": "^1.1.3",
|
||||
"has": "^1.0.3",
|
||||
"has-tostringtag": "^1.0.0"
|
||||
"es-errors": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"es-set-tostringtag": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
|
||||
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
|
||||
"requires": {
|
||||
"es-errors": "^1.3.0",
|
||||
"get-intrinsic": "^1.2.6",
|
||||
"has-tostringtag": "^1.0.2",
|
||||
"hasown": "^2.0.2"
|
||||
}
|
||||
},
|
||||
"es-shim-unscopables": {
|
||||
|
|
@ -26462,9 +26546,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0"
|
||||
}
|
||||
|
|
@ -26700,12 +26784,14 @@
|
|||
}
|
||||
},
|
||||
"form-data": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
|
||||
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
|
||||
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
|
||||
"requires": {
|
||||
"asynckit": "^0.4.0",
|
||||
"combined-stream": "^1.0.8",
|
||||
"es-set-tostringtag": "^2.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"mime-types": "^2.1.12"
|
||||
}
|
||||
},
|
||||
|
|
@ -26818,15 +26904,20 @@
|
|||
"dev": true
|
||||
},
|
||||
"get-intrinsic": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
|
||||
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
|
||||
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
|
||||
"requires": {
|
||||
"call-bind-apply-helpers": "^1.0.2",
|
||||
"es-define-property": "^1.0.1",
|
||||
"es-errors": "^1.3.0",
|
||||
"es-object-atoms": "^1.1.1",
|
||||
"function-bind": "^1.1.2",
|
||||
"has-proto": "^1.0.1",
|
||||
"has-symbols": "^1.0.3",
|
||||
"hasown": "^2.0.0"
|
||||
"get-proto": "^1.0.1",
|
||||
"gopd": "^1.2.0",
|
||||
"has-symbols": "^1.1.0",
|
||||
"hasown": "^2.0.2",
|
||||
"math-intrinsics": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"get-package-type": {
|
||||
|
|
@ -26835,6 +26926,15 @@
|
|||
"integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
|
||||
"dev": true
|
||||
},
|
||||
"get-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
|
||||
"requires": {
|
||||
"dunder-proto": "^1.0.1",
|
||||
"es-object-atoms": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
|
||||
|
|
@ -26919,12 +27019,9 @@
|
|||
}
|
||||
},
|
||||
"gopd": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
|
||||
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
|
||||
"requires": {
|
||||
"get-intrinsic": "^1.1.3"
|
||||
}
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
|
||||
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="
|
||||
},
|
||||
"graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
|
|
@ -26998,19 +27095,20 @@
|
|||
"has-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz",
|
||||
"integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg=="
|
||||
"integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==",
|
||||
"dev": true
|
||||
},
|
||||
"has-symbols": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
||||
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
|
||||
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="
|
||||
},
|
||||
"has-tostringtag": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
|
||||
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
|
||||
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
|
||||
"requires": {
|
||||
"has-symbols": "^1.0.2"
|
||||
"has-symbols": "^1.0.3"
|
||||
}
|
||||
},
|
||||
"hash-sum": {
|
||||
|
|
@ -29358,9 +29456,9 @@
|
|||
},
|
||||
"dependencies": {
|
||||
"brace-expansion": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
|
||||
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
|
||||
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0"
|
||||
|
|
@ -29407,9 +29505,9 @@
|
|||
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
|
||||
},
|
||||
"js-yaml": {
|
||||
"version": "3.14.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
|
||||
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
|
||||
"version": "3.14.2",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
|
||||
"integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
|
|
@ -29975,6 +30073,11 @@
|
|||
"resolved": "https://registry.npmjs.org/marked/-/marked-15.0.4.tgz",
|
||||
"integrity": "sha512-TCHvDqmb3ZJ4PWG7VEGVgtefA5/euFmsIhxtD0XsBxI39gUSKL81mIRFdt0AiNQozUahd4ke98ZdirExd/vSEw=="
|
||||
},
|
||||
"math-intrinsics": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
|
||||
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="
|
||||
},
|
||||
"mdn-data": {
|
||||
"version": "2.0.30",
|
||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz",
|
||||
|
|
@ -30295,9 +30398,9 @@
|
|||
}
|
||||
},
|
||||
"node-forge": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz",
|
||||
"integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==",
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.2.tgz",
|
||||
"integrity": "sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw==",
|
||||
"dev": true
|
||||
},
|
||||
"node-int64": {
|
||||
|
|
@ -34187,9 +34290,9 @@
|
|||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "8.14.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.14.1.tgz",
|
||||
"integrity": "sha512-4OOseMUq8AzRBI/7SLMUwO+FEDnguetSk7KMb1sHwvF2w2Wv5Hoj0nlifx8vtGsftE/jWHojPy8sMMzYLJ2G/A==",
|
||||
"version": "8.18.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
|
||||
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
}
|
||||
|
|
@ -34354,9 +34457,9 @@
|
|||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "7.5.9",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz",
|
||||
"integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==",
|
||||
"version": "7.5.10",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
|
||||
"integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
|
||||
"dev": true,
|
||||
"requires": {}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
"dependencies": {
|
||||
"@d-i-t-a/reader": "github:gotson/R2D2BC#fork",
|
||||
"@saekitominaga/isbn-verify": "^2.0.1",
|
||||
"axios": "^1.8.2",
|
||||
"axios": "^1.12.0",
|
||||
"chart.js": "^2.9.4",
|
||||
"core-js": "^3.8.3",
|
||||
"date-fns": "^2.30.0",
|
||||
|
|
|
|||
|
|
@ -19,7 +19,15 @@
|
|||
},
|
||||
"account_settings": {
|
||||
"account_settings": "إعدادات الحساب",
|
||||
"change_password": "تغيير كلمة السر"
|
||||
"api_key": {
|
||||
"created_date": "تاريخ الصنع: {date}",
|
||||
"force_kobo_sync": "إجبار مزامنة Kobo",
|
||||
"generate_api_key": "توليد مفتاح API",
|
||||
"no_keys": "لم يخلق مفتاح API بعد"
|
||||
},
|
||||
"change_password": "تغيير كلمة السر",
|
||||
"details": "تفاصيل",
|
||||
"my_account": "حسابي"
|
||||
},
|
||||
"announcements": {
|
||||
"mark_all_read": "اشر عليها بانها قرأت",
|
||||
|
|
@ -27,6 +35,7 @@
|
|||
"tab_title": "إعلانات"
|
||||
},
|
||||
"authentication_activity": {
|
||||
"api_key": "مفتاح API",
|
||||
"datetime": "التاريخ والوقت",
|
||||
"email": "البريد الإلكتروني",
|
||||
"error": "خطأ",
|
||||
|
|
@ -85,7 +94,8 @@
|
|||
"bookreader": {
|
||||
"beginning_of_book": "أنت في بداية الكتاب.",
|
||||
"changing_reading_direction": "تغيير اتجاه القراءة إلى",
|
||||
"cycling_page_layout": "تخطيط دوري للصفحة",
|
||||
"cycling_page_layout": "تغيير تخطيط الصفحة",
|
||||
"cycling_page_margin": "تغيير هامش الصفحة",
|
||||
"cycling_scale": "تغيير حجم التحرير",
|
||||
"cycling_side_padding": "تغيير الحدود الجانبية",
|
||||
"download_current_page": "تنزيل الصفحة الحالية",
|
||||
|
|
@ -128,6 +138,7 @@
|
|||
"general": "إعدادات عامة",
|
||||
"gestures": "الإيماءات",
|
||||
"page_layout": "تخطيط الصفحة",
|
||||
"page_margin": "هامش الصفحة",
|
||||
"paged": "خيارات القارئ المرقم",
|
||||
"reading_mode": "وضع القراءة",
|
||||
"scale_type": "نوع القياس",
|
||||
|
|
@ -137,8 +148,9 @@
|
|||
},
|
||||
"shortcuts": {
|
||||
"close": "إغلاق",
|
||||
"cycle_page_layout": "دورة تخطيط الصفحة",
|
||||
"cycle_scale": "مقياس الدورة",
|
||||
"cycle_page_layout": "تغيير تخطيط الصفحة",
|
||||
"cycle_page_margin": "تغيير هامش الصفحة",
|
||||
"cycle_scale": "تغيير الحجم",
|
||||
"cycle_side_padding": "تغيير الحدود الجانبية",
|
||||
"first_page": "الصفحة الأولى",
|
||||
"fullscreen": "إدخال/إنهاء ملء الشاشة",
|
||||
|
|
@ -161,6 +173,8 @@
|
|||
},
|
||||
"browse_book": {
|
||||
"comment": "تعليق",
|
||||
"date_created": "صُنِع",
|
||||
"date_modified": "آخر تعديل",
|
||||
"download_file": "تحميل الملف",
|
||||
"file": "ملف",
|
||||
"format": "صيغة",
|
||||
|
|
@ -170,6 +184,8 @@
|
|||
"outdated_tooltip": "تم تغيير ملف هذا الكتاب ، يجب إعادة تحليل هذا الكتاب",
|
||||
"read_book": "قراءة كتاب",
|
||||
"read_incognito": "قراءة التصفح المتخفي",
|
||||
"remove_from_collection": "إزالة الكتاب من المجموعة",
|
||||
"remove_from_readlist": "إزالة الكتاب من قائمة القراءة",
|
||||
"size": "حجم"
|
||||
},
|
||||
"browse_collection": {
|
||||
|
|
@ -184,6 +200,7 @@
|
|||
},
|
||||
"browse_series": {
|
||||
"earliest_year_from_release_dates": "هذه هي السنة الأولى من تواريخ الإصدار لجميع الكتب في السلسلة",
|
||||
"remove_from_collection": "إزالة السلسلة من المجموعة",
|
||||
"series_no_summary": "هذه السلسلة لا تحتوي على ملخص ، لذلك اخترنا واحدًا لك!",
|
||||
"summary_from_book": "ملخص من الكتاب {number}:"
|
||||
},
|
||||
|
|
@ -194,6 +211,8 @@
|
|||
"common": {
|
||||
"age": "العمر",
|
||||
"all_libraries": "كل المكتبات",
|
||||
"all_of": "كل من",
|
||||
"any_of": "أي من",
|
||||
"book": "كتاب",
|
||||
"books": "كتب",
|
||||
"books_n": "لا يوجد كتاب | 1 كتاب | {count} كتب",
|
||||
|
|
@ -203,15 +222,19 @@
|
|||
"choose_image": "اختر صورة",
|
||||
"close": "إغلاق",
|
||||
"collections": "المجموعات",
|
||||
"copied": "تم النسخ!",
|
||||
"create": "صنع",
|
||||
"delete": "حذف",
|
||||
"discard": "تجاهل",
|
||||
"dimension": "ع:{width}, ط:{height}",
|
||||
"discard": "تخلص",
|
||||
"disk_space": "مساحة القرص",
|
||||
"dismiss": "رفض",
|
||||
"download": "تحميل",
|
||||
"drag_drop": "أمسك واسحب",
|
||||
"duplicate": "مكرر",
|
||||
"email": "البريد الإلكتروني",
|
||||
"epub": "Epub",
|
||||
"epub": "EPUB",
|
||||
"error": "خطأ",
|
||||
"filename": "اسم الملف",
|
||||
"filter_no_matches": "الفلتر النشط ليس له تطابق",
|
||||
"genre": "نوع",
|
||||
|
|
@ -219,13 +242,17 @@
|
|||
"go_to_library": "اذهب إلى المكتبة",
|
||||
"go_to_readlist": "انتقل إلى قائمة القراءة",
|
||||
"go_to_series": "الانتقال إلى السلسلة",
|
||||
"i_understand": "فهمت",
|
||||
"library": "مكتبة",
|
||||
"locale_name": "العربية",
|
||||
"locale_rtl": "true",
|
||||
"lock_all": "قفل الكل",
|
||||
"media": "الوسائط",
|
||||
"more": "المزيد",
|
||||
"n_selected": "{count} مختار",
|
||||
"nothing_to_show": "لا شيء للعرض",
|
||||
"oneshot": "طلقة واحدة",
|
||||
"ok": "حسنا",
|
||||
"oneshot": "قصة منفردة",
|
||||
"outdated": "متقادمة",
|
||||
"page": "صفحة",
|
||||
"page_number": "رقم الصفحة",
|
||||
|
|
@ -235,19 +262,23 @@
|
|||
"password": "كلمة السر",
|
||||
"pdf": "PDF",
|
||||
"pending_tasks": "لا توجد مهام معلقة | مهمة واحدة معلقة | {count} مهام معلقة",
|
||||
"pinned_libraries": "المكتبات المثبتة",
|
||||
"publisher": "الناشر",
|
||||
"read": "اقرأ",
|
||||
"read_on": "قرأ في {date}",
|
||||
"readlist": "قائمة القراءة",
|
||||
"readlists": "قوائم القراءة",
|
||||
"remember-me": "تذكرني",
|
||||
"reorder": "تغيير الترتيب",
|
||||
"required": "مطلوب",
|
||||
"reset_filters": "إعادة تعيين فلتر",
|
||||
"roles": "أدوار",
|
||||
"save_changes": "حفظ التغييرات",
|
||||
"series": "سلسلة",
|
||||
"settings": "الإعدادات",
|
||||
"sidecars": "Sidecars",
|
||||
"tags": "التصنيف",
|
||||
"ui": "واجهة المستخدم",
|
||||
"unavailable": "غير متوفر",
|
||||
"unlock_all": "فتح الكل",
|
||||
"url": "عنوان URL",
|
||||
|
|
@ -271,10 +302,11 @@
|
|||
"comicrack_preambule_html": "يمكنك استيراد قوائم قراءة ComicRack الحالية بتنسيق <code>cbl</code>.<br>سيحاول Komga مطابقة السلسلة ورقم الكتاب المقدمين مع السلسلة والكتب في مكتباتك.",
|
||||
"dialog_confirmation": {
|
||||
"body": "{unmatched} / {total} الكتب غير متطابقة",
|
||||
"body2": "{duplicates} / {total} كتاب مكرر",
|
||||
"create": "الخلق على أي حال",
|
||||
"title": "بعض الكتب لا تتطابق"
|
||||
},
|
||||
"field_file_label": "ComicRack Reading List (.cbl)",
|
||||
"field_file_label": "قائمة قراءة ComicRack (من نوع cbl.)",
|
||||
"field_files_label": "قوائم القراءة ComicRack (.cbl)",
|
||||
"import_read_lists": "استيراد قوائم القراءة",
|
||||
"imported_as": "مستورد كـ {name}",
|
||||
|
|
@ -286,6 +318,14 @@
|
|||
"tab_title": "استيراد البيانات"
|
||||
},
|
||||
"dialog": {
|
||||
"add_api_key": {
|
||||
"button_confirm": "توليد",
|
||||
"context": "يمكن استعمال مفاتيح الAPI للتوثيق عبر بروتوكول Kobo Sync.",
|
||||
"dialog_title": "توليد مفتاح API جديد",
|
||||
"field_comment": "تعليق",
|
||||
"field_comment_hint": "ما الغرض من مفتاح الAPI هذا؟",
|
||||
"info_copy": "يرجى التأكد من نسخ مفتاح الAPI الآن. لا يستطاع النظر عليه مجددا!"
|
||||
},
|
||||
"add_to_collection": {
|
||||
"button_create": "خلق",
|
||||
"card_collection_subtitle": "لا توجد سلسلة | 1 سلسلة | {count} سلسلة",
|
||||
|
|
@ -319,6 +359,12 @@
|
|||
"filter": "مصنف حسب رقم الكتاب أو العنوان أو تاريخ الإصدار",
|
||||
"title": "حدد كتاب"
|
||||
},
|
||||
"delete_apikey": {
|
||||
"button_confirm": "حذف",
|
||||
"confirm_delete": "فهمت, حذف مفتاح الAPI المسمى {name}",
|
||||
"dialog_title": "حذف مفتاح الAPI",
|
||||
"warning_html": "كل التطبيقات التي تستعمل مفتاح الAPI هذا ستصبح غير قادرة على الوصول إلى الAPI التابع لKomga. لا يمكن التراجع عن هذا الإجراء."
|
||||
},
|
||||
"delete_book": {
|
||||
"button_confirm": "حذف",
|
||||
"confirm_delete": "نعم، حذف كتاب \"{name}\" وملفاته",
|
||||
|
|
@ -389,6 +435,8 @@
|
|||
"field_summary": "ملخص",
|
||||
"field_tags": "التصنيف",
|
||||
"field_title": "العنوان",
|
||||
"number_sort_decrement": "تقليل الجميع ب1",
|
||||
"number_sort_increment": "زيادة الجميع ب1",
|
||||
"tab_authors": "المؤلفون",
|
||||
"tab_general": "إعدادات عامة",
|
||||
"tab_links": "الروابط",
|
||||
|
|
@ -415,6 +463,7 @@
|
|||
"dialot_title_edit": "تحرير المكتبة",
|
||||
"field_analysis_analyze_dimensions": "تحليل أبعاد الصفحات",
|
||||
"field_analysis_hash_files": "حساب تجزئة للملفات",
|
||||
"field_analysis_hash_koreader": "حسابة التلبيد لملفات KOReader",
|
||||
"field_analysis_hash_pages": "حساب تجزئة الصفحات",
|
||||
"field_convert_to_cbz": "تحويل تلقائيا إلى CBZ",
|
||||
"field_import_barcode_isbn": "الباركود ردمك",
|
||||
|
|
@ -422,15 +471,19 @@
|
|||
"field_import_comicinfo_collections": "المجموعات",
|
||||
"field_import_comicinfo_readlists": "قوائم القراءة",
|
||||
"field_import_comicinfo_series": "سلسلة البيانات الوصفية",
|
||||
"field_import_comicinfo_series_append_volume": "إضافة المجلد إلى عنوان المسلسل",
|
||||
"field_import_epub_book": "البيانات الوصفية للكتاب",
|
||||
"field_import_epub_series": "سلسلة البيانات الوصفية",
|
||||
"field_import_local_artwork": "الأعمال الفنية المحلية",
|
||||
"field_import_mylar_series": "سلسلة البيانات الوصفية",
|
||||
"field_name": "الاسم",
|
||||
"field_oneshotsdirectory": "موقع القصص المنفردة",
|
||||
"field_repair_extensions": "إصلاح ملحقات الملفات غير الصحيحة تلقائيًا",
|
||||
"field_root_folder": "المجلد الرئيسي",
|
||||
"field_scan_interval": "تكرار البحث عن الملفات",
|
||||
"field_scanner_empty_trash_after_scan": "تفريغ المهملات تلقائيا بعد كل فحص",
|
||||
"field_scanner_force_directory_modified_time": "فرض وقت تعديل الدليل",
|
||||
"field_scanner_scan_startup": "البحث عن الملفات عند بدء البرنامج",
|
||||
"field_series_cover": "غلاف السلسلة",
|
||||
"file_browser_dialog_button_confirm": "إختيار",
|
||||
"file_browser_dialog_title": "المجلد الجذر للمكتبة",
|
||||
|
|
@ -441,11 +494,14 @@
|
|||
"label_import_epub": "استيراد البيانات الوصفية من ملفات EPUB",
|
||||
"label_import_local": "استيراد أصول الوسائط المحلية",
|
||||
"label_import_mylar": "استيراد البيانات الوصفية التي تم إنشاؤها بواسطة Mylar",
|
||||
"label_scan_directory_exclusions": "استبعاد المواقع",
|
||||
"label_scan_types": "البحث عن أنواع الملفات هذه",
|
||||
"label_scanner": "الماسح الضوئي",
|
||||
"label_series_cover": "غلاف السلسلة",
|
||||
"tab_general": "إعدادات عامة",
|
||||
"tab_metadata": "البيانات الوصفية",
|
||||
"tab_options": "الخيارات",
|
||||
"tooltip_oneshotsdirectory": "يترك فارغا للتعطيل",
|
||||
"tooltip_scanner_force_modified_time": "تمكين إذا كانت المكتبة على Google Drive",
|
||||
"tooltip_use_resources": "يمكن أن تستهلك الكثير من الموارد في مكتبات كبيرة أو أجهزة بطيئة"
|
||||
},
|
||||
|
|
@ -453,11 +509,16 @@
|
|||
"button_cancel": "إلغاء",
|
||||
"button_confirm": "حفظ التغييرات",
|
||||
"dialog_title": "تحرير قائمة القراءة",
|
||||
"field_manual_ordering": "ترتيب يدوي",
|
||||
"field_name": "الاسم",
|
||||
"field_summary": "ملخص",
|
||||
"tab_general": "عام",
|
||||
"tab_poster": "ملصق"
|
||||
},
|
||||
"edit_recommended": {
|
||||
"button_confirm": "حفظ التعديلات",
|
||||
"button_reset": "الإعادة إلى التعديلات الأصلية"
|
||||
},
|
||||
"edit_series": {
|
||||
"button_cancel": "إلغاء",
|
||||
"button_confirm": "حفظ التغييرات",
|
||||
|
|
@ -483,6 +544,7 @@
|
|||
"tab_poster": "ملصق",
|
||||
"tab_sharing": "مشاركة",
|
||||
"tab_tags": "التصنيف",
|
||||
"tab_titles": "العناوين البديلة",
|
||||
"tags_notice_multiple_edit": "أنت تقوم بتحرير العلامات لسلسلة متعددة. سيؤدي هذا إلى تجاوز العلامات الموجودة في كل سلسلة."
|
||||
},
|
||||
"edit_user": {
|
||||
|
|
@ -525,6 +587,9 @@
|
|||
},
|
||||
"title": "اسم الوجهة"
|
||||
},
|
||||
"force_kobo_sync": {
|
||||
"dialog_title": "إجبار مزامنة Kobo"
|
||||
},
|
||||
"password_change": {
|
||||
"button_cancel": "إلغاء",
|
||||
"button_confirm": "تغيير كلمة السر",
|
||||
|
|
@ -541,6 +606,7 @@
|
|||
},
|
||||
"series_picker": {
|
||||
"label_search_series": "سلسلة البحث",
|
||||
"no_results": "لم يتم العثور على أي سلسلة",
|
||||
"title": "اختيار سلسلة"
|
||||
},
|
||||
"server_stop": {
|
||||
|
|
@ -579,21 +645,31 @@
|
|||
}
|
||||
},
|
||||
"duplicate_pages": {
|
||||
"action_auto_delete_remaining": "باق إلغاء {count} أوتوماتيكيا",
|
||||
"action_delete_auto": "حذف تلقائي",
|
||||
"action_delete_manual": "حذف يدوي",
|
||||
"action_delete_matches": "حذف المطابقات",
|
||||
"action_ignore": "تجاهل",
|
||||
"action_ignore_remaining": "تجاهل الباقي ({count})",
|
||||
"action_manual_delete_remaining": "إلغاء الباقي يدويا ({count})",
|
||||
"delete_to_save": "حذف لحفظ {size}",
|
||||
"deleted_count": "تم حذف {count} مرة",
|
||||
"empty_title": "لم يتم العثور على صفحات مكررة",
|
||||
"empty_title_known": "لا توجد نسخ مكررة معروف عنها",
|
||||
"filter": {
|
||||
"count": "عدد",
|
||||
"date_added": "تاريخ الإضافة",
|
||||
"date_modified": "تاريخ التعديل",
|
||||
"delete_count": "عدد الحذف",
|
||||
"delete_size": "المساحة المحفوظة",
|
||||
"match_count": "عدد النتائج المتطابقة",
|
||||
"size": "حجم",
|
||||
"total_size": "الحجم الإجمالي"
|
||||
},
|
||||
"info": "حذف الصفحات المكررة سيغيّر ملفاتك. احتفظ بنسخة احتياطية من ملفاتك واستخدم الحذف اليدوي قبل استخدام الحذف التلقائي.",
|
||||
"known": "المعروفة",
|
||||
"matches_n": "لا يوجد تطابق | 1 تطابق | {count} التطابق",
|
||||
"new": "الجديدة",
|
||||
"saved_size": "حُفظ {size}",
|
||||
"title": "صفحات مكررة",
|
||||
"unknown_size": "حجم مجهول"
|
||||
|
|
@ -609,6 +685,23 @@
|
|||
"HARDLINK": "ملفات الروابط الثابتة/النسخ",
|
||||
"MOVE": "نقل الملفات"
|
||||
},
|
||||
"epubreader": {
|
||||
"appearances": {
|
||||
"day": "النهار",
|
||||
"night": "الليل",
|
||||
"sepia": "سيبيا"
|
||||
},
|
||||
"column_count": {
|
||||
"auto": "أوتوماتيكي",
|
||||
"one": "واحد",
|
||||
"two": "اثنان"
|
||||
},
|
||||
"reading_direction": {
|
||||
"auto": "أوتوماتيكي",
|
||||
"ltr": "من اليسار إلى اليمين",
|
||||
"rtl": "من اليمين إلى اليسار"
|
||||
}
|
||||
},
|
||||
"historical_event_type": {
|
||||
"BookConverted": "تمّ تحويل الكتاب",
|
||||
"BookFileDeleted": "تمّ مسح ملف الكتاب",
|
||||
|
|
@ -616,6 +709,11 @@
|
|||
"DuplicatePageDeleted": "تمّ حذف الصفحة المكررة",
|
||||
"SeriesFolderDeleted": "تمّ حذف مجلد السلسلة"
|
||||
},
|
||||
"media_profile": {
|
||||
"DIVINA": "DIVINA",
|
||||
"EPUB": "EPUB",
|
||||
"PDF": "PDF"
|
||||
},
|
||||
"media_status": {
|
||||
"ERROR": "خطأ",
|
||||
"OUTDATED": "قديمه",
|
||||
|
|
@ -634,6 +732,14 @@
|
|||
"VERTICAL": "عمودي",
|
||||
"WEBTOON": "ويبتون"
|
||||
},
|
||||
"scan_interval": {
|
||||
"DAILY": "يوميا",
|
||||
"DISABLED": "معطل",
|
||||
"EVERY_12H": "كل 12 ساعة",
|
||||
"EVERY_6H": "كل 6 ساعات",
|
||||
"HOURLY": "كل ساعة",
|
||||
"WEEKLY": "كل أسبوع"
|
||||
},
|
||||
"series_cover": {
|
||||
"FIRST": "أول",
|
||||
"LAST": "أخير"
|
||||
|
|
@ -645,6 +751,34 @@
|
|||
"ONGOING": "مستمر"
|
||||
}
|
||||
},
|
||||
"epubreader": {
|
||||
"current_chapter": "الفصل الحالي",
|
||||
"page_of": "الصفحة {page} من {count}",
|
||||
"publisher_font": "الناشر",
|
||||
"settings": {
|
||||
"column_count": "عدد أعمدة",
|
||||
"font_family": "الخط",
|
||||
"layout": "تخطيط",
|
||||
"layout_scroll": "تمرير",
|
||||
"navigation_mode": "وضع التنقل",
|
||||
"navigation_options": {
|
||||
"both": "كلاهما",
|
||||
"buttons": "أزرار",
|
||||
"click": "نقر/ضغط"
|
||||
},
|
||||
"page_margins": "هوامش الصفحة"
|
||||
},
|
||||
"shortcuts": {
|
||||
"cycle_pagination": "تغيير عدد الأعمدة",
|
||||
"font_size_decrease": "تصغير الخط",
|
||||
"font_size_increase": "تكبير الخط",
|
||||
"menus": "القائمات",
|
||||
"next": "أمام",
|
||||
"previous": "خلف",
|
||||
"settings": "الإعدادات",
|
||||
"show_hide_toc": "إظهار/إخفاء الفهرس"
|
||||
}
|
||||
},
|
||||
"error_codes": {
|
||||
"ERR_1000": "تعذر الوصول إلى الملف أثناء التحليل",
|
||||
"ERR_1001": "نوع الوسائط غير مدعوم",
|
||||
|
|
@ -667,11 +801,13 @@
|
|||
"filter": {
|
||||
"age_rating": "التصنيف العمري",
|
||||
"age_rating_none": "لا شيء",
|
||||
"any": "أي",
|
||||
"complete": "اكتمل",
|
||||
"genre": "نوع",
|
||||
"in_progress": "قيد التقدم",
|
||||
"language": "اللغة",
|
||||
"library": "المكتبة",
|
||||
"oneshot": "قصة منفردة",
|
||||
"publisher": "الناشر",
|
||||
"read": "اقرأ",
|
||||
"release_date": "تاريخ الاصدار",
|
||||
|
|
@ -699,6 +835,8 @@
|
|||
},
|
||||
"library_navigation": {
|
||||
"browse": "تصفّح",
|
||||
"browse_books": "كتب",
|
||||
"browse_series": "سلسلات",
|
||||
"collections": "المجموعات",
|
||||
"readlists": "قوائم القراءة",
|
||||
"recommended": "موصى به"
|
||||
|
|
@ -730,6 +868,7 @@
|
|||
"empty_trash": "إفراغ سلة المهملات",
|
||||
"mark_read": "تحديد كمقروء",
|
||||
"mark_unread": "تحديد كغير مقروء",
|
||||
"pin": "تثبيت",
|
||||
"refresh_metadata": "تحديث البيانات الوصفية",
|
||||
"scan_library_files": "فحص ملفات المكتبة",
|
||||
"select_all": "تحديد الكل"
|
||||
|
|
@ -745,6 +884,9 @@
|
|||
"libraries": "المكتبات",
|
||||
"logout": "تسجيل الخروج"
|
||||
},
|
||||
"no_libraries_pinned": {
|
||||
"title": "لا مكتبات مثبتة"
|
||||
},
|
||||
"page_not_found": {
|
||||
"go_back_to_home_page": "العودة إلى الصفحة الرئيسية",
|
||||
"page_does_not_exist": "الصفحة التي تبحث عنها غير موجودة.",
|
||||
|
|
@ -754,6 +896,12 @@
|
|||
"less": "أقرأ أقل",
|
||||
"more": "اقرأ أكثر"
|
||||
},
|
||||
"readlist_import": {
|
||||
"row": {
|
||||
"duplicate_book": "كتاب مكرر",
|
||||
"error_choose_book": "اختيار كتاب"
|
||||
}
|
||||
},
|
||||
"readlists_expansion_panel": {
|
||||
"manage_readlist": "إدارة قائمة القراءة",
|
||||
"title": "{name} قائمة القراءة"
|
||||
|
|
@ -775,12 +923,21 @@
|
|||
"button_empty_trash": "إفراغ سلة المهملات لكل المكتبات",
|
||||
"button_scan_libraries": "مسح جميع المكتبات",
|
||||
"button_shutdown": "إيقاف التشغيل",
|
||||
"download_log": "تحميل ملف السجل",
|
||||
"notification_tasks_cancelled": "لا يوجد مهام لإلغائها | تمّ إلغاء 1 مهمة | تمّ إلغاء {count} مهمة",
|
||||
"section_title": "إدارة الخادم"
|
||||
},
|
||||
"tab_title": "خادم"
|
||||
"tab_title": "خادم",
|
||||
"updates": "تحديثات"
|
||||
},
|
||||
"server_settings": {
|
||||
"dialog_regenerate_thumbnails": {
|
||||
"btn_alternate": "نعم، جميع الكتب",
|
||||
"btn_cancel": "لا",
|
||||
"btn_confirm": "نعم، لكن فقط إن كانت اكبر"
|
||||
},
|
||||
"label_kobo_port": "باب مزامنة Kobo الخارجي",
|
||||
"label_server_port": "باب الخادم",
|
||||
"server_settings": "إعدادات الخادم"
|
||||
},
|
||||
"settings_user": {
|
||||
|
|
@ -795,12 +952,15 @@
|
|||
"sort": {
|
||||
"books_count": "عدد الكتب",
|
||||
"date_added": "تاريخ الإضافة",
|
||||
"date_read": "تاريخ القراءة",
|
||||
"date_updated": "تاريخ التحديث",
|
||||
"file_name": "اسم الملف",
|
||||
"file_size": "حجم الملف",
|
||||
"folder_name": "اسم المجلد",
|
||||
"name": "الاسم",
|
||||
"number": "رقم",
|
||||
"page_count": "عدد الصفحات",
|
||||
"random": "عشوائي",
|
||||
"release_date": "تاريخ الإصدار"
|
||||
},
|
||||
"theme": {
|
||||
|
|
@ -818,16 +978,36 @@
|
|||
"tooltip_too_big": "الملف كبير جدًا!",
|
||||
"tooltip_user_uploaded": "تمّ الرفع بواسطة المستخدم"
|
||||
},
|
||||
"titles_more": {
|
||||
"less": "عناوين أقل",
|
||||
"more": "عناوين أكثر"
|
||||
},
|
||||
"ui_settings": {
|
||||
"general": "عام",
|
||||
"section_oauth2": "OAuth2",
|
||||
"series_groups": {
|
||||
"alpha": "ابجدي",
|
||||
"japanese": "غوجون (ياباني)"
|
||||
}
|
||||
},
|
||||
"updates": {
|
||||
"available": "توجد تحديثات"
|
||||
},
|
||||
"user_roles": {
|
||||
"ADMIN": "مدير",
|
||||
"FILE_DOWNLOAD": "تحميل الملف",
|
||||
"PAGE_STREAMING": "صفحات البث",
|
||||
"KOBO_SYNC": "مزامنة Kobo",
|
||||
"KOREADER_SYNC": "مزامنة KOReader",
|
||||
"PAGE_STREAMING": "بث الصفحات",
|
||||
"USER": "مستخدم"
|
||||
},
|
||||
"users": {
|
||||
"api_keys": "مفاتيح الAPI",
|
||||
"users": "المستخدمين"
|
||||
},
|
||||
"validation": {
|
||||
"one_or_more": "يجب أن يكون 1 أو أكثر",
|
||||
"tcp_port": "يجب أن يكون بين 1 و 65535",
|
||||
"zero_or_more": "يجب أن يكون 0 أو أكثر"
|
||||
},
|
||||
"welcome": {
|
||||
|
|
|
|||
|
|
@ -827,7 +827,12 @@
|
|||
"ERR_1031": "V ComicRack CBL Book chybí série nebo číslo",
|
||||
"ERR_1032": "Soubor EPUB má chybný typ média",
|
||||
"ERR_1033": "Některé položky chybí",
|
||||
"ERR_1034": "API key s touto poznámkou již existuje"
|
||||
"ERR_1034": "API key s touto poznámkou již existuje",
|
||||
"ERR_1035": "Chyba při získávání obsahu EPUB",
|
||||
"ERR_1036": "Chyba při získávání záložek EPUB",
|
||||
"ERR_1037": "CHyba při získávání seznamu stran EPUB",
|
||||
"ERR_1038": "Chyba při získávání stran EPUB Divina",
|
||||
"ERR_1039": "Chyba při získávání pozic EPUB"
|
||||
},
|
||||
"filter": {
|
||||
"age_rating": "Věkové hodnocení",
|
||||
|
|
|
|||
|
|
@ -19,7 +19,15 @@
|
|||
},
|
||||
"account_settings": {
|
||||
"account_settings": "Configuración da conta",
|
||||
"change_password": "Cambiar o contrasinal"
|
||||
"api_key": {
|
||||
"created_date": "Data de creación: {date}",
|
||||
"force_kobo_sync": "Forzar a sincronización con Kobo",
|
||||
"generate_api_key": "Xerar clave API",
|
||||
"no_keys": "Aínda non se xerou clave API ningunha"
|
||||
},
|
||||
"change_password": "Cambiar o contrasinal",
|
||||
"details": "Detalles",
|
||||
"my_account": "A miña conta"
|
||||
},
|
||||
"announcements": {
|
||||
"mark_all_read": "Marcar todo como lido",
|
||||
|
|
@ -27,6 +35,7 @@
|
|||
"tab_title": "Avisos"
|
||||
},
|
||||
"authentication_activity": {
|
||||
"api_key": "Clave API",
|
||||
"datetime": "Data e Hora",
|
||||
"email": "Correo electrónico",
|
||||
"error": "Erro",
|
||||
|
|
@ -58,9 +67,159 @@
|
|||
"button_scan": "Escanear",
|
||||
"button_select_series": "Escolle a serie",
|
||||
"field_import_path": "Importar dende un cartafol",
|
||||
"info_part1": "Esta pantalla permitiralle importar arquivos que están fóra das súas bibliotecas existentes. Só pódese importar arquivos a series que xa existan, nese caso Komga moverá ou copiará os arquivos cara o directorio da serie escollida."
|
||||
"info_part1": "Esta pantalla permitiralle importar arquivos que están fóra das súas bibliotecas existentes. Só pódese importar arquivos a series que xa existan, nese caso Komga moverá ou copiará os arquivos cara o directorio da serie escollida.",
|
||||
"info_part2": "Se escolles un número para un libro e existe xa algún outro libro con ese número, poderás comparalos. Se decides importar o libro, Komga actualizará o existente co novo, substituindo o ficheiro existente co novo.",
|
||||
"no_files_found": "Non se atoparon ficheiros",
|
||||
"notification": {
|
||||
"go_to_book": "Ir ao libro",
|
||||
"import_failure": "Fallou a importación do libro: {file}",
|
||||
"import_successful": "Libro importado con éxito: {book}",
|
||||
"source_file": "Ficheiro orixe: {file}"
|
||||
},
|
||||
"row": {
|
||||
"error_analyze_first": "É necesario analizar antes o libro",
|
||||
"error_choose_series": "Escoller serie",
|
||||
"error_only_import_no_errors": "Só se poden importar libros sen erros",
|
||||
"warning_upgrade": "Actualizarase o libro existente"
|
||||
},
|
||||
"table": {
|
||||
"destination_name": "Nome de destino",
|
||||
"file_name": "Nome do ficheiro",
|
||||
"number": "Número",
|
||||
"series": "Serie"
|
||||
},
|
||||
"title": "Importar",
|
||||
"try_another_directory": "Tenta atopar outro directorio"
|
||||
},
|
||||
"bookreader": {
|
||||
"beginning_of_book": "Atópaste ao principio do libro.",
|
||||
"changing_reading_direction": "Trocar o sentido de lectura a",
|
||||
"download_current_page": "Baixar a páxina actual",
|
||||
"end_of_book": "Chegaches ao final do libro.",
|
||||
"from_series_metadata": "dende os metadatos da serie",
|
||||
"move_next": "Volve pulsar \"Seguinte\" para pasar ao seguinte libro.",
|
||||
"move_next_exit": "Volve pulser \"Seguinte\" para saír do lector.",
|
||||
"move_previous": "Volve pulsar \"Anterior\" para pasar ao libro anterior.",
|
||||
"notification_poster_set_book": "A portada do libro estableceuse á páxina actual.",
|
||||
"notification_poster_set_readlist": "A portada da lista de lectura estableceuse á páxina actual.",
|
||||
"notification_poster_set_series": "A portada de serie estableceuse á páxina actual.",
|
||||
"paged_reader_layout": {
|
||||
"double": "Dobre páxina",
|
||||
"double_no_cover": "Dobre páxina (sen portada)",
|
||||
"single": "Páxina simple"
|
||||
},
|
||||
"reader_settings": "Configuración do lector",
|
||||
"scale_type": {
|
||||
"continuous_original": "Orixinal",
|
||||
"continuous_width": "Axuste á anchura",
|
||||
"height": "Axuste á altura",
|
||||
"original": "Orixinal",
|
||||
"screen": "Pantalla"
|
||||
},
|
||||
"settings": {
|
||||
"always_fullscreen": "Sempre a pantalla completa",
|
||||
"animate_page_transitions": "Transicións de páxina animadas",
|
||||
"background_color": "Cor de fondo",
|
||||
"background_colors": {
|
||||
"black": "Negro",
|
||||
"gray": "Gris",
|
||||
"white": "Branco"
|
||||
},
|
||||
"general": "Xeral",
|
||||
"gestures": "Xestos",
|
||||
"page_layout": "Disposición de páxina",
|
||||
"page_margin": "Marxe de páxina",
|
||||
"reading_mode": "Modo de lectura",
|
||||
"side_padding_none": "Ningún"
|
||||
},
|
||||
"shortcuts": {
|
||||
"close": "Pechar",
|
||||
"first_page": "Primeira páxina",
|
||||
"last_page": "Derradeira páxina",
|
||||
"left_to_right": "De esquerda a dereita",
|
||||
"menus": "Menús",
|
||||
"next_page": "Seguinte páxina",
|
||||
"previous_page": "Páxina anterior",
|
||||
"right_to_left": "De dereita a esquerda"
|
||||
},
|
||||
"tooltip_incognito": "Non se gardará o progreso de lectura"
|
||||
},
|
||||
"browse_book": {
|
||||
"comment": "COMENTARIO",
|
||||
"date_created": "CREACIÓN",
|
||||
"date_modified": "ÚLTIMA MODIFICACIÓN",
|
||||
"download_file": "Baixar ficheiro",
|
||||
"file": "FICHEIRO",
|
||||
"format": "FORMATO",
|
||||
"isbn": "ISBN",
|
||||
"links": "LIGAZÓNS",
|
||||
"outdated_tooltip": "Cambiouse o ficheiro deste libro; é necesario volver analizalo",
|
||||
"read_book": "Ler libro",
|
||||
"read_incognito": "Ler de incógnito",
|
||||
"remove_from_collection": "Quitar libro da colección",
|
||||
"remove_from_readlist": "Quitar libro da lista de lectura",
|
||||
"size": "TAMAÑO"
|
||||
},
|
||||
"browse_collection": {
|
||||
"edit_collection": "Editar colección",
|
||||
"edit_elements": "Editar elementos",
|
||||
"manual_ordering": "Ordenación manual"
|
||||
},
|
||||
"browse_readlist": {
|
||||
"edit_elements": "Editar elementos",
|
||||
"edit_readlist": "Editar lista de lectura",
|
||||
"manual_ordering": "Ordenación manual"
|
||||
},
|
||||
"browse_series": {
|
||||
"earliest_year_from_release_dates": "Este é o ano máis temperán entre as datas de lanzamento de tódolos libros da serie",
|
||||
"remove_from_collection": "Quitar serie da colección",
|
||||
"series_no_summary": "Esta serie non ten sumario, así que escollemos un por ti!",
|
||||
"summary_from_book": "Sumario do libro {number}:"
|
||||
},
|
||||
"collections_expansion_panel": {
|
||||
"manage_collection": "Xestionar colección",
|
||||
"title": "{name} colección"
|
||||
},
|
||||
"common": {
|
||||
"locale_name": "Galego"
|
||||
"age": "Idade",
|
||||
"all_libraries": "Tódalas bibliotecas",
|
||||
"all_of": "Todo",
|
||||
"any_of": "Calquera",
|
||||
"book": "Libro",
|
||||
"books": "Libros",
|
||||
"books_n": "Ningún libro | 1 libro | {count} libros",
|
||||
"books_total": "{count} / {total} libros",
|
||||
"cancel": "Cancelar",
|
||||
"choose_image": "Escoller unha imaxe",
|
||||
"close": "Pechar",
|
||||
"collections": "Coleccións",
|
||||
"copied": "Copiado!",
|
||||
"create": "Crear",
|
||||
"delete": "Borrar",
|
||||
"discard": "Descartar",
|
||||
"disk_space": "Espazo en disco",
|
||||
"download": "Baixar",
|
||||
"duplicate": "Duplicar",
|
||||
"epub": "EPUB",
|
||||
"error": "Erro",
|
||||
"filename": "Nome de ficheiro",
|
||||
"genre": "Xénero",
|
||||
"go_to_collection": "Ir á colección",
|
||||
"go_to_library": "Ir á biblioteca",
|
||||
"go_to_readlist": "Ir á lista de lectura",
|
||||
"go_to_series": "Ir á serie",
|
||||
"i_understand": "Entendido",
|
||||
"library": "Biblioteca",
|
||||
"locale_name": "Galego",
|
||||
"more": "Máis",
|
||||
"nothing_to_show": "Nada que amosar",
|
||||
"page": "Páxina",
|
||||
"page_number": "Número de páxina",
|
||||
"pages": "páxinas",
|
||||
"pages_left": "Non quedan páxinas | Queda 1 páxina | Quedan {count} páxinas",
|
||||
"pages_n": "Ningunha páxina | 1 páxina | {count} páxinas",
|
||||
"password": "Contrasinal",
|
||||
"pdf": "PDF",
|
||||
"pending_tasks": "Sen tarefas pendentes | 1 tarefa pendente | {count} tarefas pendentes"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@
|
|||
},
|
||||
"author_roles": {
|
||||
"colorist": "koloristi",
|
||||
"cover": "omot",
|
||||
"cover": "naslovnica",
|
||||
"editor": "urednici",
|
||||
"inker": "bojitelj",
|
||||
"letterer": "tipografi",
|
||||
|
|
@ -109,7 +109,7 @@
|
|||
"notification_poster_set_series": "Trenutačna stranica je sada postavljena kao poster serije.",
|
||||
"paged_reader_layout": {
|
||||
"double": "Dvije stranice",
|
||||
"double_no_cover": "Dvije stranice (bez omota)",
|
||||
"double_no_cover": "Dvije stranice (bez naslovnice)",
|
||||
"single": "Jedna stranica"
|
||||
},
|
||||
"reader_settings": "Postavke čitača",
|
||||
|
|
@ -138,7 +138,7 @@
|
|||
"general": "Općenito",
|
||||
"gestures": "Geste",
|
||||
"page_layout": "Raspored stranica",
|
||||
"page_margin": "Margine stranica",
|
||||
"page_margin": "Margina stranice",
|
||||
"paged": "Postavke prikaza stranica",
|
||||
"reading_mode": "Modus čitanja",
|
||||
"scale_type": "Vrsta skaliranja",
|
||||
|
|
@ -484,7 +484,7 @@
|
|||
"field_scanner_empty_trash_after_scan": "Automatski isprazni smeće nakon svakog pretraživanja",
|
||||
"field_scanner_force_directory_modified_time": "Pretraži mape na osnovi vremena promjene",
|
||||
"field_scanner_scan_startup": "Pretraži tijekom pokretanja",
|
||||
"field_series_cover": "Omot serije",
|
||||
"field_series_cover": "Naslovnica serije",
|
||||
"file_browser_dialog_button_confirm": "Odaberi",
|
||||
"file_browser_dialog_title": "Osnovna mapa biblioteke",
|
||||
"label_analysis": "Analiza",
|
||||
|
|
@ -497,7 +497,7 @@
|
|||
"label_scan_directory_exclusions": "Isključivanja mapa",
|
||||
"label_scan_types": "Traži ove vrste datoteka",
|
||||
"label_scanner": "Tražilica",
|
||||
"label_series_cover": "Omot serije",
|
||||
"label_series_cover": "Naslovnica serije",
|
||||
"tab_general": "Općenito",
|
||||
"tab_metadata": "Metapodaci",
|
||||
"tab_options": "Opcije",
|
||||
|
|
@ -780,7 +780,7 @@
|
|||
"buttons": "Gumbovi",
|
||||
"click": "Pritisni / Dodirni"
|
||||
},
|
||||
"page_margins": "Margine stranica",
|
||||
"page_margins": "Margine stranice",
|
||||
"viewing_theme": "Tema prikaza"
|
||||
},
|
||||
"shortcuts": {
|
||||
|
|
@ -827,7 +827,12 @@
|
|||
"ERR_1031": "ComicRack CBL knjizi nedostaje serija ili broj",
|
||||
"ERR_1032": "EPUB datoteka sadrži neispravnu vrstu medija",
|
||||
"ERR_1033": "Neki unosi nedostaju",
|
||||
"ERR_1034": "API ključ s tim komentarom već postoji"
|
||||
"ERR_1034": "API ključ s tim komentarom već postoji",
|
||||
"ERR_1035": "Greška prilikom dohvaćanja tablice sadržaja EPUB-a",
|
||||
"ERR_1036": "Greška prilikom dohvaćanja straničnika EPUB-a",
|
||||
"ERR_1037": "Greška prilikom dohvaćanja popisa stranica EPUB-a",
|
||||
"ERR_1038": "Greška prilikom dohvaćanja divina stranica EPUB-a",
|
||||
"ERR_1039": "Greška prilikom dohvaćanja pozicija EPUB-a"
|
||||
},
|
||||
"filter": {
|
||||
"age_rating": "dobna kategorija",
|
||||
|
|
@ -984,7 +989,7 @@
|
|||
"btn_confirm": "Da, ali samo ako su veće",
|
||||
"title": "Nanovo generiraj minijature"
|
||||
},
|
||||
"hint_kobo_port": "Postavi samo u slučaju problema sa sinkronizacijom omota i preuzimanja",
|
||||
"hint_kobo_port": "Postavi samo u slučaju problema sa sinkronizacijom naslovnica i preuzimanja",
|
||||
"label_delete_empty_collections": "Izbriši prazne zbirke nakon pretraživanja",
|
||||
"label_delete_empty_readlists": "Izbriši prazne liste čitanja nakon pretraživanja",
|
||||
"label_kepubify_path": "Staza do kepubify",
|
||||
|
|
|
|||
|
|
@ -19,7 +19,15 @@
|
|||
},
|
||||
"account_settings": {
|
||||
"account_settings": "Configurações de conta",
|
||||
"change_password": "alterar senha"
|
||||
"api_key": {
|
||||
"created_date": "Data de criação: {date}",
|
||||
"force_kobo_sync": "Forçar sincronização com Kobo",
|
||||
"generate_api_key": "Gerar chave de API",
|
||||
"no_keys": "Nenhuma Chave de API foi criada"
|
||||
},
|
||||
"change_password": "alterar senha",
|
||||
"details": "Detalhes",
|
||||
"my_account": "Minha conta"
|
||||
},
|
||||
"announcements": {
|
||||
"mark_all_read": "Marque todos como lido",
|
||||
|
|
@ -27,6 +35,7 @@
|
|||
"tab_title": "Anúncios"
|
||||
},
|
||||
"authentication_activity": {
|
||||
"api_key": "Chave de API",
|
||||
"datetime": "Data e Hora",
|
||||
"email": "E-mail",
|
||||
"error": "Erro",
|
||||
|
|
@ -86,6 +95,7 @@
|
|||
"beginning_of_book": "Você está no inicio do livro.",
|
||||
"changing_reading_direction": "Mudar Direção de Leitura para",
|
||||
"cycling_page_layout": "Alterando Layout de Página",
|
||||
"cycling_page_margin": "Alterando Margem de Página",
|
||||
"cycling_scale": "Alterando Escala",
|
||||
"cycling_side_padding": "Alterando Preenchimento Lateral",
|
||||
"download_current_page": "Baixar a pagina atual",
|
||||
|
|
@ -128,6 +138,7 @@
|
|||
"general": "Geral",
|
||||
"gestures": "Gestos",
|
||||
"page_layout": "Layout de página",
|
||||
"page_margin": "Margem de página",
|
||||
"paged": "Opções do Reader paginado",
|
||||
"reading_mode": "Modo de leitura",
|
||||
"scale_type": "Tipo de escala",
|
||||
|
|
@ -138,6 +149,7 @@
|
|||
"shortcuts": {
|
||||
"close": "Fechar",
|
||||
"cycle_page_layout": "Alterar layout de página",
|
||||
"cycle_page_margin": "Alterar margem de página",
|
||||
"cycle_scale": "Alterar escala",
|
||||
"cycle_side_padding": "Alterar preenchimento lateral",
|
||||
"first_page": "Primeira página",
|
||||
|
|
@ -161,6 +173,8 @@
|
|||
},
|
||||
"browse_book": {
|
||||
"comment": "COMENTÁRIO",
|
||||
"date_created": "CRIADO",
|
||||
"date_modified": "MODIFICADO POR ÚLTIMO",
|
||||
"download_file": "Baixar arquivo",
|
||||
"file": "ARQUIVO",
|
||||
"format": "FORMATO",
|
||||
|
|
@ -170,6 +184,8 @@
|
|||
"outdated_tooltip": "O arquivo para este livro foi alterado, este livro deve ser reanalisado",
|
||||
"read_book": "Ler livro",
|
||||
"read_incognito": "Ler incógnito",
|
||||
"remove_from_collection": "Remover livro da coleção",
|
||||
"remove_from_readlist": "Remover livro da lista de leitura",
|
||||
"size": "TAMANHO"
|
||||
},
|
||||
"browse_collection": {
|
||||
|
|
@ -184,6 +200,7 @@
|
|||
},
|
||||
"browse_series": {
|
||||
"earliest_year_from_release_dates": "Este é o ano mais antigo dentre as datas de lançamento de todos os livros na série",
|
||||
"remove_from_collection": "Remover série da coleção",
|
||||
"series_no_summary": "Esta série não contém um resumo, então escolhemos um para você!",
|
||||
"summary_from_book": "Resumo do livro {number}:"
|
||||
},
|
||||
|
|
@ -194,6 +211,8 @@
|
|||
"common": {
|
||||
"age": "Idade",
|
||||
"all_libraries": "Todas as bibliotecas",
|
||||
"all_of": "Todos",
|
||||
"any_of": "Qualquer",
|
||||
"book": "Livro",
|
||||
"books": "Livros",
|
||||
"books_n": "Nenhum livro | 1 livro | {count} livros",
|
||||
|
|
@ -203,6 +222,7 @@
|
|||
"choose_image": "Escolher uma imagem",
|
||||
"close": "Fechar",
|
||||
"collections": "Coleções",
|
||||
"copied": "Copiado!",
|
||||
"create": "Criar",
|
||||
"delete": "Excluir",
|
||||
"dimension": "l: {width}, a:{height}",
|
||||
|
|
@ -211,8 +231,10 @@
|
|||
"dismiss": "Ignorar",
|
||||
"download": "Baixar",
|
||||
"drag_drop": "Arrastar e soltar",
|
||||
"duplicate": "Duplicado",
|
||||
"email": "Email",
|
||||
"epub": "Epub",
|
||||
"error": "Erro",
|
||||
"filename": "Nome do arquivo",
|
||||
"filter_no_matches": "O filtro ativo não contém correspondências",
|
||||
"genre": "Gênero",
|
||||
|
|
@ -220,12 +242,17 @@
|
|||
"go_to_library": "Ir para biblioteca",
|
||||
"go_to_readlist": "Ir para lista de lidos",
|
||||
"go_to_series": "Ir para séries",
|
||||
"i_understand": "Eu compreendo",
|
||||
"library": "Biblioteca",
|
||||
"locale_name": "Português (Brasil)",
|
||||
"locale_rtl": "false",
|
||||
"lock_all": "Bloquear todos",
|
||||
"media": "Mídia",
|
||||
"more": "Mais",
|
||||
"n_selected": "{count} selecionados",
|
||||
"nothing_to_show": "Nada para exibir",
|
||||
"ok": "OK",
|
||||
"oneshot": "One-shot",
|
||||
"outdated": "Desatualizado",
|
||||
"page": "Página",
|
||||
"page_number": "Número da página",
|
||||
|
|
@ -235,19 +262,23 @@
|
|||
"password": "Senha",
|
||||
"pdf": "PDF",
|
||||
"pending_tasks": "Nenhuma tarefa pendente | 1 tarefa pendente | {count} tarefas pendentes",
|
||||
"pinned_libraries": "Bibliotecas Fixadas",
|
||||
"publisher": "Editora",
|
||||
"read": "Ler",
|
||||
"read_on": "Lido em {date}",
|
||||
"readlist": "Lista de Leitura",
|
||||
"readlists": "Listas de Leitura",
|
||||
"remember-me": "Me lembre",
|
||||
"reorder": "Reordernar",
|
||||
"required": "Obrigatório",
|
||||
"reset_filters": "Redefinir filtros",
|
||||
"roles": "Funções",
|
||||
"save_changes": "Salvar mudanças",
|
||||
"series": "Séries | Séries",
|
||||
"settings": "Configurações",
|
||||
"sidecars": "Carrinho",
|
||||
"tags": "Tags",
|
||||
"ui": "Interface de Usuário",
|
||||
"unavailable": "Indisponível",
|
||||
"unlock_all": "Desbloquear tudo",
|
||||
"url": "URL",
|
||||
|
|
@ -271,6 +302,7 @@
|
|||
"comicrack_preambule_html": "Você pode importar Listas de Leitura do ComicRack existentes no formato <code>.cbl</code><br>Komga tentará combinar a série fornecida e o número do livro com as séries e livros em suas bibliotecas.",
|
||||
"dialog_confirmation": {
|
||||
"body": "{unmatched} / {total} livro(s) não foram marcados",
|
||||
"body2": "{duplicates} / {total} livros são duplicados",
|
||||
"create": "Criar de todo modo",
|
||||
"title": "Alguns livros não estão combinados"
|
||||
},
|
||||
|
|
@ -286,6 +318,14 @@
|
|||
"tab_title": "Importação de Dados"
|
||||
},
|
||||
"dialog": {
|
||||
"add_api_key": {
|
||||
"button_confirm": "Gerar",
|
||||
"context": "Chaves API podem ser usadas para autenticar no protocolo Kobo Sync.",
|
||||
"dialog_title": "Gerar chave de API",
|
||||
"field_comment": "Comentar",
|
||||
"field_comment_hint": "Como a chave API será usada?",
|
||||
"info_copy": "Tenha a certeza de que a chave API foi salva. Você não poderá vê-la novamente!"
|
||||
},
|
||||
"add_to_collection": {
|
||||
"button_create": "Criar",
|
||||
"card_collection_subtitle": "Nenhuma série | 1 série | {count} série",
|
||||
|
|
@ -319,6 +359,12 @@
|
|||
"filter": "Filtrar por número, título ou data de lançamento",
|
||||
"title": "Selecionar livro"
|
||||
},
|
||||
"delete_apikey": {
|
||||
"button_confirm": "Excluir",
|
||||
"confirm_delete": "Eu entendo, exclua a chave API \"{name}\"",
|
||||
"dialog_title": "Deletar chave API",
|
||||
"warning_html": "Quaisquer aplicativos ou scripts que utilizem esta chave API não poderão mais acessar a API Komga. Você não poderá desfazer esta ação."
|
||||
},
|
||||
"delete_book": {
|
||||
"button_confirm": "Excluir",
|
||||
"confirm_delete": "Sim, exclua o livro \"{name}\" e seus arquivos",
|
||||
|
|
@ -468,6 +514,9 @@
|
|||
"tab_general": "Geral",
|
||||
"tab_poster": "Pôster"
|
||||
},
|
||||
"edit_recommended": {
|
||||
"button_confirm": "Salvar mudanças"
|
||||
},
|
||||
"edit_series": {
|
||||
"button_cancel": "Cancelar",
|
||||
"button_confirm": "Salvar mudanças",
|
||||
|
|
@ -536,6 +585,9 @@
|
|||
},
|
||||
"title": "Nome do Arquivo de Destino"
|
||||
},
|
||||
"force_kobo_sync": {
|
||||
"dialog_title": "Forçar sincronização com Kobo"
|
||||
},
|
||||
"password_change": {
|
||||
"button_cancel": "Cancelar",
|
||||
"button_confirm": "Mudar senha",
|
||||
|
|
@ -603,6 +655,9 @@
|
|||
"HARDLINK": "Hardlink/Copiar arquivos",
|
||||
"MOVE": "Mover Arquivos"
|
||||
},
|
||||
"media_profile": {
|
||||
"PDF": "PDF"
|
||||
},
|
||||
"media_status": {
|
||||
"ERROR": "Erro",
|
||||
"OUTDATED": "Desatualizado",
|
||||
|
|
@ -629,6 +684,14 @@
|
|||
"ONGOING": "Em andamento"
|
||||
}
|
||||
},
|
||||
"epubreader": {
|
||||
"settings": {
|
||||
"page_margins": "Margem de Páginas"
|
||||
},
|
||||
"shortcuts": {
|
||||
"settings": "Configurações"
|
||||
}
|
||||
},
|
||||
"error_codes": {
|
||||
"ERR_1000": "O arquivo não pôde ser acessado durante a análise",
|
||||
"ERR_1001": "O tipo de mídia não é compatível",
|
||||
|
|
@ -660,6 +723,7 @@
|
|||
"in_progress": "Em progresso",
|
||||
"language": "idioma",
|
||||
"library": "biblioteca",
|
||||
"oneshot": "One-shot",
|
||||
"publisher": "editora",
|
||||
"read": "Lidos",
|
||||
"release_date": "data de lançamento",
|
||||
|
|
@ -673,7 +737,8 @@
|
|||
},
|
||||
"history": {
|
||||
"header": {
|
||||
"book": "Livro"
|
||||
"book": "Livro",
|
||||
"details": "Detalhes"
|
||||
}
|
||||
},
|
||||
"home": {
|
||||
|
|
@ -795,6 +860,9 @@
|
|||
"tooltip_too_big": "Arquivo muito grande!",
|
||||
"tooltip_user_uploaded": "Enviado pelo usuário"
|
||||
},
|
||||
"ui_settings": {
|
||||
"general": "Geral"
|
||||
},
|
||||
"user_roles": {
|
||||
"ADMIN": "Administrador",
|
||||
"FILE_DOWNLOAD": "Baixar arquivos",
|
||||
|
|
@ -802,6 +870,7 @@
|
|||
"USER": "Usuário"
|
||||
},
|
||||
"users": {
|
||||
"api_keys": "Chaves API",
|
||||
"authentication_activity": "Atividade de Autenticação",
|
||||
"users": "Usuários"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@
|
|||
"pageText": "{0}-{1} из {2}"
|
||||
},
|
||||
"dataIterator": {
|
||||
"loadingText": "Загрузка объектов...",
|
||||
"noResultsText": "Подходящих записей не найдено"
|
||||
"loadingText": "Загрузка элементов...",
|
||||
"noResultsText": "Совпадений не найдено"
|
||||
},
|
||||
"dataTable": {
|
||||
"itemsPerPageText": "Строк на странице:",
|
||||
|
|
@ -15,30 +15,33 @@
|
|||
"counter": "Файлов: {0}",
|
||||
"counterSize": "Файлов: {0} (всего {1})"
|
||||
},
|
||||
"noDataText": "Отсутствуют данные"
|
||||
"noDataText": "Данные отсутствуют"
|
||||
},
|
||||
"account_settings": {
|
||||
"account_settings": "Настройки Аккаунта",
|
||||
"account_settings": "Настройки аккаунта",
|
||||
"api_key": {
|
||||
"created_date": "Дата создания: {date}",
|
||||
"generate_api_key": "Сгенерировать API ключ",
|
||||
"force_kobo_sync": "Принудительная синхронизация с Kobo",
|
||||
"generate_api_key": "Сгенерировать ключ API",
|
||||
"no_keys": "Ни одного ключа API еще не создано"
|
||||
},
|
||||
"change_password": "изменить пароль"
|
||||
"change_password": "изменить пароль",
|
||||
"details": "Подробности",
|
||||
"my_account": "Мой аккаунт"
|
||||
},
|
||||
"announcements": {
|
||||
"mark_all_read": "Пометить всё как прочитанное",
|
||||
"mark_read": "Пометить как прочитанное",
|
||||
"mark_all_read": "Отметить всё как прочитанное",
|
||||
"mark_read": "Отметить как прочитанное",
|
||||
"tab_title": "Объявления"
|
||||
},
|
||||
"authentication_activity": {
|
||||
"api_key": "API Ключ",
|
||||
"datetime": "Дата / Время",
|
||||
"api_key": "API-ключ",
|
||||
"datetime": "Дата/Время",
|
||||
"email": "Эл. почта",
|
||||
"error": "Ошибка",
|
||||
"ip": "IP-адрес",
|
||||
"source": "Источник",
|
||||
"success": "Статус",
|
||||
"success": "Успех",
|
||||
"user_agent": "User Agent"
|
||||
},
|
||||
"author_roles": {
|
||||
|
|
@ -54,18 +57,18 @@
|
|||
"book_card": {
|
||||
"error": "Ошибка",
|
||||
"no_release_date": "Дата релиза отсутствует",
|
||||
"unknown": "Необходимо проанализировать",
|
||||
"unknown": "Подлежит анализу",
|
||||
"unread": "Не прочитано",
|
||||
"unsupported": "Неподдерживаемый"
|
||||
"unsupported": "Не поддерживается"
|
||||
},
|
||||
"book_import": {
|
||||
"button_browse": "Обзор",
|
||||
"button_import": "Импортировать",
|
||||
"button_import": "Импорт",
|
||||
"button_scan": "Сканировать",
|
||||
"button_select_series": "Выберите Серию",
|
||||
"button_select_series": "Выберите серию",
|
||||
"field_import_path": "Импортировать из каталога",
|
||||
"info_part1": "Этот раздел позволяет вам импортировать файлы, которые находятся за пределами ваших существующих библиотек. Вы можете импортировать файлы только в существующие Серии, в этом случае Komga переместит или скопирует файлы в каталог выбранной Серии.",
|
||||
"info_part2": "Если вы выберете номер для книги и книга с таким номером уже существует, то вы сможете сравнить 2 книги. Если вы решите импортировать книгу, Komga обновит существующую книгу, эффективно заменив старый файл новым.",
|
||||
"info_part1": "Этот раздел позволяет вам импортировать файлы, которые находятся за пределами ваших существующих библиотек. Вы можете импортировать файлы только в существующие серии; в этом случае Komga переместит или скопирует файлы в каталог выбранной серии.",
|
||||
"info_part2": "Если вы укажете номер для книги, и книга с таким номером уже существует, вы сможете сравнить оба варианта. Если вы решите импортировать книгу, Komga обновит существующий вариант, заменив старый файл новым.",
|
||||
"no_files_found": "Файлы не найдены",
|
||||
"notification": {
|
||||
"go_to_book": "Перейти к книге",
|
||||
|
|
@ -74,9 +77,9 @@
|
|||
"source_file": "Исходный файл: {file}"
|
||||
},
|
||||
"row": {
|
||||
"error_analyze_first": "Книгу нужно сначала проанализировать",
|
||||
"error_analyze_first": "Книга нуждается в предварительном анализе",
|
||||
"error_choose_series": "Выберите серию",
|
||||
"error_only_import_no_errors": "Можно импортировать только книги без ошибок",
|
||||
"error_only_import_no_errors": "Можно импортировать только книги без наличия ошибок",
|
||||
"warning_upgrade": "Существующая книга будет обновлена"
|
||||
},
|
||||
"table": {
|
||||
|
|
@ -90,10 +93,11 @@
|
|||
},
|
||||
"bookreader": {
|
||||
"beginning_of_book": "Вы находитесь в начале книги.",
|
||||
"changing_reading_direction": "Изменение Направления Чтения на",
|
||||
"cycling_page_layout": "Переключить Формат Страниц",
|
||||
"cycling_scale": "Переключить Масштабирование",
|
||||
"cycling_side_padding": "Переключить Боковой Отступ",
|
||||
"changing_reading_direction": "Изменение направления чтения на",
|
||||
"cycling_page_layout": "Переключение макета страницы",
|
||||
"cycling_page_margin": "Переключение полей страницы",
|
||||
"cycling_scale": "Масштабирование",
|
||||
"cycling_side_padding": "Переключение боковых отступов",
|
||||
"download_current_page": "Скачать текущую страницу",
|
||||
"end_of_book": "Вы достигли конца книги.",
|
||||
"from_series_metadata": "из метаданных серии",
|
||||
|
|
@ -104,8 +108,8 @@
|
|||
"notification_poster_set_readlist": "Текущая страница теперь используется в качестве постера списка чтения.",
|
||||
"notification_poster_set_series": "Текущая страница теперь используется в качестве постера серии.",
|
||||
"paged_reader_layout": {
|
||||
"double": "Двойные страницы",
|
||||
"double_no_cover": "Двойные страницы (без обложки)",
|
||||
"double": "Две страницы",
|
||||
"double_no_cover": "Две страницы (без обложки)",
|
||||
"single": "Одна страница"
|
||||
},
|
||||
"reader_settings": "Настройки Ридера",
|
||||
|
|
@ -114,16 +118,16 @@
|
|||
"continuous_width": "По ширине",
|
||||
"height": "По высоте",
|
||||
"original": "Исходное",
|
||||
"screen": "По экрану",
|
||||
"screen": "По размеру экрана",
|
||||
"width": "По ширине",
|
||||
"width_shrink_only": "По ширине (с отступами)"
|
||||
},
|
||||
"set_current_page_as_book_poster": "Установить страницу в качестве постера для книги",
|
||||
"set_current_page_as_readlist_poster": "Установить страницу в качестве постера для списка чтения",
|
||||
"set_current_page_as_series_poster": "Установить страницу в качестве постера для серии",
|
||||
"set_current_page_as_book_poster": "Установить страницу в качестве обложки для книги",
|
||||
"set_current_page_as_readlist_poster": "Установить страницу в качестве обложки для списка чтения",
|
||||
"set_current_page_as_series_poster": "Установить страницу в качестве обложки для серии",
|
||||
"settings": {
|
||||
"always_fullscreen": "Всегда в полный экран",
|
||||
"animate_page_transitions": "Анимировать переходы страниц",
|
||||
"always_fullscreen": "Всегда полноэкранный режим",
|
||||
"animate_page_transitions": "Анимировать переходы между страницами",
|
||||
"background_color": "Цвет фона",
|
||||
"background_colors": {
|
||||
"black": "Чёрный",
|
||||
|
|
@ -134,54 +138,60 @@
|
|||
"general": "Общее",
|
||||
"gestures": "Жесты",
|
||||
"page_layout": "Формат страницы",
|
||||
"paged": "Настройки Отображения Страниц",
|
||||
"page_margin": "Поля страницы",
|
||||
"paged": "Настройки отображения страниц",
|
||||
"reading_mode": "Режим чтения",
|
||||
"scale_type": "Масштабирование",
|
||||
"side_padding": "Боковой отступ",
|
||||
"side_padding": "Боковые отступы",
|
||||
"side_padding_none": "Нет",
|
||||
"webtoon": "Параметры Режима Webtoon"
|
||||
"webtoon": "Настройки режима цифрового комикса"
|
||||
},
|
||||
"shortcuts": {
|
||||
"close": "Закрыть",
|
||||
"cycle_page_layout": "Переключить формат страниц",
|
||||
"cycle_page_layout": "Переключить макет страницы",
|
||||
"cycle_page_margin": "Переключить поля страницы",
|
||||
"cycle_scale": "Переключить масштаб",
|
||||
"cycle_side_padding": "Переключить боковой отступ",
|
||||
"cycle_side_padding": "Переключить боковые отступы",
|
||||
"first_page": "Первая страница",
|
||||
"fullscreen": "Войти/выйти из полноэкранного режима",
|
||||
"last_page": "Последняя страница",
|
||||
"left_to_right": "Слева Направо",
|
||||
"left_to_right": "Слева направо",
|
||||
"menus": "Меню",
|
||||
"next_page": "Следующая страница",
|
||||
"previous_page": "Предыдущая страница",
|
||||
"reader_navigation": "Навигация",
|
||||
"right_to_left": "Справа Налево",
|
||||
"right_to_left": "Справа налево",
|
||||
"settings": "Настройки",
|
||||
"show_hide_help": "Показать/скрыть помощь",
|
||||
"show_hide_settings": "Показать/скрыть меню настроек",
|
||||
"show_hide_thumbnails": "Показать/скрыть просмотр эскизов",
|
||||
"show_hide_thumbnails": "Показать/скрыть обозреватель миниатюр",
|
||||
"show_hide_toolbars": "Показать/скрыть панели инструментов",
|
||||
"vertical": "Вертикально",
|
||||
"webtoon": "Webtoon"
|
||||
"webtoon": "Цифровой комикс"
|
||||
},
|
||||
"tooltip_incognito": "Прогресс чтения не будет сохранен"
|
||||
},
|
||||
"browse_book": {
|
||||
"comment": "КОММЕНТАРИЙ",
|
||||
"date_created": "СОЗДАНО",
|
||||
"date_modified": "ПОСЛЕДНЕЕ ИЗМЕНЕНИЕ",
|
||||
"download_file": "Скачать файл",
|
||||
"file": "ФАЙЛ",
|
||||
"format": "ФОРМАТ",
|
||||
"isbn": "ISBN",
|
||||
"links": "ССЫЛКИ",
|
||||
"navigation_within_readlist": "Навигация в пределах списка чтения: {name}",
|
||||
"outdated_tooltip": "Файл этой книги изменен, книгу необходимо повторно проанализировать",
|
||||
"navigation_within_readlist": "Навигация внутри списка чтения: {name}",
|
||||
"outdated_tooltip": "Файл этой книги изменился, книгу необходимо повторно проанализировать",
|
||||
"read_book": "Читать книгу",
|
||||
"read_incognito": "Читать инкогнито",
|
||||
"remove_from_collection": "Удалить книгу из коллекции",
|
||||
"remove_from_readlist": "Удалить книгу из списка чтения",
|
||||
"size": "РАЗМЕР"
|
||||
},
|
||||
"browse_collection": {
|
||||
"edit_collection": "Редактировать коллекцию",
|
||||
"edit_elements": "Редактировать элементы",
|
||||
"manual_ordering": "ручной порядок"
|
||||
"manual_ordering": "ручная сортировка"
|
||||
},
|
||||
"browse_readlist": {
|
||||
"edit_elements": "Редактировать элементы",
|
||||
|
|
@ -189,17 +199,19 @@
|
|||
"manual_ordering": "ручная сортировка"
|
||||
},
|
||||
"browse_series": {
|
||||
"earliest_year_from_release_dates": "Это самая ранняя дата выпуска из всех книг в этой серии",
|
||||
"series_no_summary": "У серии нет описания, поэтому мы подобрали его для вас!",
|
||||
"earliest_year_from_release_dates": "Это самый ранний год из дат выхода всех книг серии",
|
||||
"remove_from_collection": "Удалить серию из коллекции",
|
||||
"series_no_summary": "У этой серии нет описания, поэтому мы подобрали его для вас!",
|
||||
"summary_from_book": "Краткое описание из книги {number}:"
|
||||
},
|
||||
"collections_expansion_panel": {
|
||||
"manage_collection": "Управлять коллекцией",
|
||||
"manage_collection": "Управление коллекцией",
|
||||
"title": "Коллекция {name}"
|
||||
},
|
||||
"common": {
|
||||
"age": "Возраст",
|
||||
"all_libraries": "Все Библиотеки",
|
||||
"all_libraries": "Все библиотеки",
|
||||
"any_of": "Любой из",
|
||||
"book": "Книга",
|
||||
"books": "Книги",
|
||||
"books_n": "Книг нет | 1 книга | {count} книг",
|
||||
|
|
@ -212,14 +224,16 @@
|
|||
"copied": "Скопировано!",
|
||||
"create": "Создать",
|
||||
"delete": "Удалить",
|
||||
"dimension": "шир.: {width} выс.: {height}",
|
||||
"dimension": "шир.: {width}, выс.: {height}",
|
||||
"discard": "Отмена",
|
||||
"disk_space": "Дисковое пространство",
|
||||
"dismiss": "Отклонить",
|
||||
"download": "Скачать",
|
||||
"drag_drop": "перетащить",
|
||||
"duplicate": "Дублировать",
|
||||
"email": "Эл. почта",
|
||||
"epub": "Epub",
|
||||
"error": "Ошибка",
|
||||
"filename": "Имя файла",
|
||||
"filter_no_matches": "Нет совпадений по заданному фильтру",
|
||||
"genre": "Жанр",
|
||||
|
|
@ -227,12 +241,16 @@
|
|||
"go_to_library": "Вернуться к библиотеке",
|
||||
"go_to_readlist": "Перейти к списку чтения",
|
||||
"go_to_series": "Перейти к серии",
|
||||
"i_understand": "Я понимаю",
|
||||
"library": "Библиотека",
|
||||
"locale_name": "Русский",
|
||||
"locale_rtl": "false",
|
||||
"lock_all": "Заблокировать все",
|
||||
"media": "Медиа",
|
||||
"more": "Ещё",
|
||||
"n_selected": "{count} выбрано",
|
||||
"nothing_to_show": "Нет данных для отображения",
|
||||
"ok": "OK",
|
||||
"outdated": "Устарело",
|
||||
"page": "Страница",
|
||||
"page_number": "Номер страницы",
|
||||
|
|
@ -242,17 +260,20 @@
|
|||
"password": "Пароль",
|
||||
"pdf": "PDF",
|
||||
"pending_tasks": "Нет незавершенных задач | 1 незавершенная задача | {count} незавершенных задач",
|
||||
"pinned_libraries": "Закреплённые библиотеки",
|
||||
"publisher": "Издатель",
|
||||
"read": "Читать",
|
||||
"read_on": "Читать {date}",
|
||||
"read_on": "Прочитано {date}",
|
||||
"readlist": "Список чтения",
|
||||
"readlists": "Списки чтения",
|
||||
"remember-me": "Запомнить",
|
||||
"required": "Необходимо",
|
||||
"remember-me": "Запомнить меня",
|
||||
"reorder": "Изменить порядок",
|
||||
"required": "Обязательно",
|
||||
"reset_filters": "Сбросить фильтры",
|
||||
"roles": "Роли",
|
||||
"save_changes": "Сохранить изменения",
|
||||
"series": "Серии",
|
||||
"settings": "Настройки",
|
||||
"tags": "Теги",
|
||||
"unavailable": "Недоступно",
|
||||
"unlock_all": "Разблокировать все",
|
||||
|
|
|
|||
1092
komga-webui/src/locales/sk.json
Normal file
1092
komga-webui/src/locales/sk.json
Normal file
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -97,7 +97,7 @@
|
|||
"cycling_page_layout": "Шаблон сторінки",
|
||||
"cycling_page_margin": "Відступи",
|
||||
"cycling_scale": "Масштабування",
|
||||
"cycling_side_padding": "Cycling Side Padding",
|
||||
"cycling_side_padding": "Бічні накладки для велосипедистів",
|
||||
"download_current_page": "Завантажити поточку сторінку",
|
||||
"end_of_book": "Ви дійшли до кінця книги.",
|
||||
"from_series_metadata": "з метаданих серії",
|
||||
|
|
@ -139,6 +139,7 @@
|
|||
"gestures": "Жести",
|
||||
"page_layout": "Шаблон сторінки",
|
||||
"page_margin": "Відступ сторінки",
|
||||
"paged": "Параметри зчитування з розбивкою на сторінки",
|
||||
"reading_mode": "Режим читання",
|
||||
"scale_type": "Тип масштабування",
|
||||
"side_padding": "Бокові відступи",
|
||||
|
|
@ -147,6 +148,10 @@
|
|||
},
|
||||
"shortcuts": {
|
||||
"close": "Закрити",
|
||||
"cycle_page_layout": "Перемикання макета сторінки",
|
||||
"cycle_page_margin": "Перемикання полів сторінки",
|
||||
"cycle_scale": "Шкала циклу",
|
||||
"cycle_side_padding": "Бічна підкладка для велосипеда",
|
||||
"first_page": "Перша сторінка",
|
||||
"fullscreen": "Увімкнути/вимкнути повноекранний режим",
|
||||
"last_page": "Остання сторінка",
|
||||
|
|
@ -174,9 +179,914 @@
|
|||
"file": "ФАЙЛ",
|
||||
"format": "ФОРМАТ",
|
||||
"isbn": "ISBN",
|
||||
"links": "ПОСИЛАННЯ"
|
||||
"links": "ПОСИЛАННЯ",
|
||||
"navigation_within_readlist": "Навігація у списку для читання: {name}",
|
||||
"outdated_tooltip": "Файл цієї книги змінився, цю книгу потрібно проаналізувати повторно",
|
||||
"read_book": "Читати книгу",
|
||||
"read_incognito": "Читати інкогніто",
|
||||
"remove_from_collection": "Вилучити книгу з колекції",
|
||||
"remove_from_readlist": "Вилучити книгу зі списку прочитаних",
|
||||
"size": "РОЗМІР"
|
||||
},
|
||||
"browse_collection": {
|
||||
"edit_collection": "Редагувати колекцію",
|
||||
"edit_elements": "Редагувати елементи",
|
||||
"manual_ordering": "ручне замовлення"
|
||||
},
|
||||
"browse_readlist": {
|
||||
"edit_elements": "Редагувати елементи",
|
||||
"edit_readlist": "Редагувати список прочитаних",
|
||||
"manual_ordering": "ручне замовлення"
|
||||
},
|
||||
"browse_series": {
|
||||
"earliest_year_from_release_dates": "Це найдавніший рік з дат виходу всіх книг серії",
|
||||
"remove_from_collection": "Вилучити серію з колекції",
|
||||
"series_no_summary": "У цієї серії немає короткого опису, тому ми вибрали його для вас!",
|
||||
"summary_from_book": "Короткий зміст з книги {number}:"
|
||||
},
|
||||
"collections_expansion_panel": {
|
||||
"manage_collection": "Керування колекцією",
|
||||
"title": "колекція {name}"
|
||||
},
|
||||
"common": {
|
||||
"locale_name": "Українська"
|
||||
"age": "Вік",
|
||||
"all_libraries": "Усі бібліотеки",
|
||||
"all_of": "Усі з",
|
||||
"any_of": "Будь-який з",
|
||||
"book": "Книга",
|
||||
"books": "Книги",
|
||||
"books_n": "Немає книги | 1 книга | {count} книг",
|
||||
"books_total": "{count} / {total} книг",
|
||||
"cancel": "Скасувати",
|
||||
"cbx": "Архів коміксів",
|
||||
"choose_image": "Виберіть зображення",
|
||||
"close": "Закрити",
|
||||
"collections": "Колекції",
|
||||
"copied": "Скопійовано!",
|
||||
"create": "Створити",
|
||||
"delete": "Видалити",
|
||||
"dimension": "У: {width}, г: {height}",
|
||||
"discard": "Відкинути",
|
||||
"disk_space": "Місце на диску",
|
||||
"dismiss": "Відхилити",
|
||||
"download": "Завантажити",
|
||||
"drag_drop": "перетягування",
|
||||
"duplicate": "Дублікат",
|
||||
"email": "Електронна пошта",
|
||||
"epub": "Електронна книга",
|
||||
"error": "Помилка",
|
||||
"filename": "Ім'я файлу",
|
||||
"filter_no_matches": "Активний фільтр не має збігів",
|
||||
"genre": "Жанр",
|
||||
"go_to_collection": "Перейти до колекції",
|
||||
"go_to_library": "Іди до бібліотеки",
|
||||
"go_to_readlist": "Перейти до списку прочитання",
|
||||
"go_to_series": "Перейти до серії",
|
||||
"i_understand": "Я розумію",
|
||||
"library": "Бібліотека",
|
||||
"locale_name": "Українська",
|
||||
"locale_rtl": "false",
|
||||
"lock_all": "Заблокувати все",
|
||||
"media": "Медіа",
|
||||
"more": "Більше",
|
||||
"n_selected": "Вибрано {count}",
|
||||
"nothing_to_show": "Нічого показати",
|
||||
"ok": "Гаразд",
|
||||
"oneshot": "Одноразовий",
|
||||
"outdated": "Застарілий",
|
||||
"page": "Сторінка",
|
||||
"page_number": "Номер сторінки",
|
||||
"pages": "сторінки",
|
||||
"pages_left": "Не залишилося сторінок | Залишилася 1 сторінка | Залишилося {count} сторінок",
|
||||
"pages_n": "Немає сторінок | 1 сторінка | {count} сторінок",
|
||||
"password": "Пароль",
|
||||
"pdf": "PDF",
|
||||
"pending_tasks": "Немає завдань, що очікують на розгляд | 1 завдання, що очікує на розгляд | {count} завдань, що очікують на розгляд",
|
||||
"pinned_libraries": "Закріплені бібліотеки",
|
||||
"publisher": "Видавець",
|
||||
"read": "Читати",
|
||||
"read_on": "Читайте далі {date}",
|
||||
"readlist": "Список прочитаних",
|
||||
"readlists": "Списки для читання",
|
||||
"remember-me": "Запам'ятай мене",
|
||||
"reorder": "Знову замовити",
|
||||
"required": "Обов'язково",
|
||||
"reset_filters": "Скинути фільтри",
|
||||
"roles": "Ролі",
|
||||
"save_changes": "Зберегти зміни",
|
||||
"series": "Серія | Серія",
|
||||
"settings": "Налаштування",
|
||||
"sidecars": "Коляски",
|
||||
"tags": "Теги",
|
||||
"ui": "Інтерфейс користувача",
|
||||
"unavailable": "Недоступно",
|
||||
"unlock_all": "Розблокувати все",
|
||||
"url": "URL",
|
||||
"use_filter_panel_to_change_filter": "Використовуйте панель фільтрів, щоб змінити активний фільтр",
|
||||
"year": "рік"
|
||||
},
|
||||
"dashboard": {
|
||||
"keep_reading": "Продовжуйте читати",
|
||||
"on_deck": "На палубі",
|
||||
"recently_added_books": "Нещодавно додані книги",
|
||||
"recently_added_series": "Нещодавно додані серії",
|
||||
"recently_read_books": "Нещодавно прочитані книги",
|
||||
"recently_released_books": "Нещодавно випущені книги",
|
||||
"recently_updated_series": "Нещодавно оновлені серії"
|
||||
},
|
||||
"data_import": {
|
||||
"book_number": "Номер книги: {name}",
|
||||
"book_series": "Серія: {name}",
|
||||
"button_import": "Імпорт",
|
||||
"button_match": "Матч",
|
||||
"comicrack_preambule_html": "Ви можете імпортувати існуючі списки читання ComicRack у форматі <code>.cbl</code>.<br>Komga спробує зіставити надану серію та номер книги із серіями та книгами у ваших бібліотеках.",
|
||||
"dialog_confirmation": {
|
||||
"body": "{unmatched} / {total} книг не мають збігів",
|
||||
"body2": "{duplicates} / {total} книг дублюються",
|
||||
"create": "Створити все одно",
|
||||
"title": "Деякі книги не збігаються"
|
||||
},
|
||||
"field_file_label": "Список для читання ComicRack (.cbl)",
|
||||
"field_files_label": "Списки для читання ComicRack (.cbl)",
|
||||
"import_read_lists": "Імпорт списків прочитаного",
|
||||
"imported_as": "Імпортовано як {name}",
|
||||
"readlist_created": "Список для читання створено: {name}",
|
||||
"requested_number": "Запитаний номер",
|
||||
"requested_series": "Запитана серія",
|
||||
"results_preambule": "Результат імпорту показано нижче. Ви також можете перевірити незбігані книги для кожного наданого файлу.",
|
||||
"size_limit": "Розмір має бути меншим за {size} МБ",
|
||||
"tab_title": "Імпорт даних"
|
||||
},
|
||||
"dialog": {
|
||||
"add_api_key": {
|
||||
"button_confirm": "Згенерувати",
|
||||
"context": "Ключі API можна використовувати для автентифікації через протокол Kobo Sync.",
|
||||
"dialog_title": "Згенерувати новий ключ API",
|
||||
"field_comment": "Коментар",
|
||||
"field_comment_hint": "Для чого цей ключ API?",
|
||||
"info_copy": "Обов’язково скопіюйте свій ключ API зараз. Ви більше його не побачите!"
|
||||
},
|
||||
"add_to_collection": {
|
||||
"button_create": "Створити",
|
||||
"card_collection_subtitle": "Без серій | 1 серія | {count} серій",
|
||||
"dialog_title": "Додати до колекції",
|
||||
"field_search_create": "Пошук або створення колекції",
|
||||
"field_search_create_error": "Колекція з такою назвою вже існує",
|
||||
"label_no_matching_collection": "Немає відповідної колекції"
|
||||
},
|
||||
"add_to_readlist": {
|
||||
"button_create": "Створити",
|
||||
"card_readlist_subtitle": "Немає книги | 1 книга | {count} книг",
|
||||
"dialog_title": "Додати до списку прочитання",
|
||||
"field_search_create": "Пошук або створення списку для читання",
|
||||
"field_search_create_error": "Список для читання з такою назвою вже існує",
|
||||
"label_no_matching_readlist": "Немає відповідного списку для читання"
|
||||
},
|
||||
"add_user": {
|
||||
"button_cancel": "Скасувати",
|
||||
"button_confirm": "Додати",
|
||||
"dialog_title": "Додати користувача",
|
||||
"field_email": "Електронна пошта",
|
||||
"field_email_error": "Має бути дійсна адреса електронної пошти",
|
||||
"field_password": "Пароль"
|
||||
},
|
||||
"analyze_library": {
|
||||
"body": "Аналізує всі медіафайли в бібліотеці. Аналіз збирає інформацію про медіафайли. Залежно від розміру вашої бібліотеки, це може тривати довго.",
|
||||
"button_confirm": "Аналіз",
|
||||
"title": "Аналіз бібліотеки"
|
||||
},
|
||||
"book_picker": {
|
||||
"filter": "Фільтрувати за номером книги, назвою або датою виходу",
|
||||
"title": "Виберіть книгу"
|
||||
},
|
||||
"delete_apikey": {
|
||||
"button_confirm": "Видалити",
|
||||
"confirm_delete": "Я розумію, видаліть ключ API \"{name}\"",
|
||||
"dialog_title": "Видалити ключ API",
|
||||
"warning_html": "Будь-які програми чи скрипти, що використовують цей ключ API, більше не матимуть доступу до API Komga. Ви не можете скасувати цю дію."
|
||||
},
|
||||
"delete_book": {
|
||||
"button_confirm": "Видалити",
|
||||
"confirm_delete": "Так, видалити книгу «{name}» та її файли",
|
||||
"confirm_delete_multiple": "Так, видалити {count} книг та їхні файли",
|
||||
"dialog_title": "Видалити книгу",
|
||||
"dialog_title_multiple": "Видалити книги",
|
||||
"warning_html": "Книгу <b>{name}</b> буде видалено з цього сервера разом зі збереженими медіафайлами. Цю дію <b>неможливо</b> скасувати. Продовжити?",
|
||||
"warning_multiple_html": "{count} Книги будуть вилучені з цього сервера разом зі збереженими медіафайлами. Цю дію <b>неможливо</b> скасувати. Продовжити?"
|
||||
},
|
||||
"delete_collection": {
|
||||
"button_confirm": "Видалити",
|
||||
"confirm_delete": "Так, видалити колекцію \"{name}\"",
|
||||
"confirm_delete_multiple": "Так, видалити {count} колекцій",
|
||||
"dialog_title": "Видалити колекцію",
|
||||
"dialog_title_multiple": "Видалити колекції",
|
||||
"warning_html": "Колекцію <b>{name}</b> буде видалено з цього сервера. Ваші медіафайли залишаться в силі. Цю дію <b>неможливо</b> скасувати. Продовжити?",
|
||||
"warning_multiple_html": "{count} Колекції будуть видалені з цього сервера. Ваші медіафайли залишаться в силі. Цю дію <b>неможливо</b> скасувати. Продовжити?"
|
||||
},
|
||||
"delete_library": {
|
||||
"button_confirm": "Видалити",
|
||||
"confirm_delete": "Так, видалити бібліотеку \"{name}\"",
|
||||
"title": "Видалити бібліотеку",
|
||||
"warning_html": "Бібліотеку <b>{name}</b> буде видалено з цього сервера. Ваші медіафайли залишаться в силі. Цю дію <b>неможливо</b> скасувати. Продовжити?"
|
||||
},
|
||||
"delete_readlist": {
|
||||
"button_confirm": "Видалити",
|
||||
"confirm_delete": "Так, видалити список прочитаного \"{name}\"",
|
||||
"confirm_delete_multiple": "Так, видалити {count} списків прочитання",
|
||||
"dialog_title": "Видалити список прочитаних",
|
||||
"dialog_title_multiple": "Видалити списки прочитаного",
|
||||
"warning_html": "Список для читання <b>{name}</b> буде видалено з цього сервера. Ваші медіафайли залишаться в силі. Цю дію <b>неможливо</b> скасувати. Продовжити?",
|
||||
"warning_multiple_html": "{count} Списки прочитання будуть видалені з цього сервера. Ваші медіафайли залишаться в силі. Цю дію <b>неможливо</b> скасувати. Продовжити?"
|
||||
},
|
||||
"delete_series": {
|
||||
"button_confirm": "Видалити",
|
||||
"confirm_delete": "Так, видалити серію \"{name}\" та її файли",
|
||||
"confirm_delete_multiple": "Так, видалити {count} серій та їхні файли",
|
||||
"dialog_title": "Видалити серію",
|
||||
"warning_html": "Серіал <b>{name}</b> буде видалено з цього сервера разом зі збереженими медіафайлами. Цю дію <b>неможливо</b> скасувати. Продовжити?",
|
||||
"warning_multiple_html": "Серії ({count}) будуть видалені з цього сервера разом зі збереженими медіафайлами. Цю дію <b>неможливо</b> скасувати. Продовжити?"
|
||||
},
|
||||
"delete_user": {
|
||||
"button_confirm": "Видалити",
|
||||
"confirm_delete": "Так, видалити користувача \"{name}\"",
|
||||
"dialog_title": "Видалити користувача",
|
||||
"warning_html": "Користувача <b>{name}</b> буде видалено з цього сервера. Цю дію <b>неможливо</b> скасувати. Продовжити?"
|
||||
},
|
||||
"edit_books": {
|
||||
"add_author_role_error_duplicate": "Вже існує",
|
||||
"authors_notice_multiple_edit": "Ви редагуєте авторів кількох книг. Це замінить існуючих авторів кожної книги.",
|
||||
"button_cancel": "Скасувати",
|
||||
"button_confirm": "Зберегти зміни",
|
||||
"copy_from": "Копіювати з {field}",
|
||||
"dialog_title_multiple": "Редагувати книгу {count} | Редагувати книги {count}",
|
||||
"dialog_title_single": "Редагувати {book}",
|
||||
"field_alternate_title": "Альтернативна назва",
|
||||
"field_isbn": "ISBN",
|
||||
"field_isbn_error": "Повинен бути дійсний ISBN 13",
|
||||
"field_link_label": "Мітка",
|
||||
"field_link_url": "URL",
|
||||
"field_link_url_error_protocol": "Має бути http або https",
|
||||
"field_link_url_error_url": "Має бути дійсна URL-адреса",
|
||||
"field_number": "Номер",
|
||||
"field_number_sort": "Номер сортування",
|
||||
"field_number_sort_hint": "Ви можете використовувати десяткові числа",
|
||||
"field_release_date": "Дата випуску",
|
||||
"field_release_date_error": "Має бути дійсна дата у форматі РРРР-ММ-ДД",
|
||||
"field_summary": "Короткий зміст",
|
||||
"field_tags": "Теги",
|
||||
"field_title": "Назва",
|
||||
"number_sort_decrement": "Зменшити все на 1",
|
||||
"number_sort_increment": "Збільшити все на 1",
|
||||
"tab_authors": "Автори",
|
||||
"tab_general": "Загальне",
|
||||
"tab_links": "Посилання",
|
||||
"tab_poster": "Плакат",
|
||||
"tab_tags": "Теги",
|
||||
"tags_notice_multiple_edit": "Ви редагуєте теги для кількох книг. Це замінить існуючі теги кожної книги."
|
||||
},
|
||||
"edit_collection": {
|
||||
"button_cancel": "Скасувати",
|
||||
"button_confirm": "Зберегти зміни",
|
||||
"dialog_title": "Редагувати колекцію",
|
||||
"field_manual_ordering": "Ручне замовлення",
|
||||
"label_ordering": "За замовчуванням серії в колекції будуть упорядковані за назвою. Ви можете ввімкнути ручне впорядкування, щоб визначити свій власний порядок.",
|
||||
"tab_general": "Загальне",
|
||||
"tab_poster": "Плакат"
|
||||
},
|
||||
"edit_library": {
|
||||
"button_browse": "Переглянути",
|
||||
"button_cancel": "Скасувати",
|
||||
"button_confirm_add": "Додати",
|
||||
"button_confirm_edit": "Редагувати",
|
||||
"button_next": "Далі",
|
||||
"dialog_title_add": "Додати бібліотеку",
|
||||
"dialot_title_edit": "Редагувати бібліотеку",
|
||||
"field_analysis_analyze_dimensions": "Аналіз розмірів сторінок",
|
||||
"field_analysis_hash_files": "Обчислити хеш для файлів",
|
||||
"field_analysis_hash_koreader": "Обчислити хеш файлів для KOReader",
|
||||
"field_analysis_hash_pages": "Обчислити хеш для сторінок",
|
||||
"field_convert_to_cbz": "Автоматично конвертувати в CBZ",
|
||||
"field_import_barcode_isbn": "Штрих-код ISBN",
|
||||
"field_import_comicinfo_book": "Метадані книги",
|
||||
"field_import_comicinfo_collections": "Колекції",
|
||||
"field_import_comicinfo_readlists": "Списки читання",
|
||||
"field_import_comicinfo_series": "Метадані серіалу",
|
||||
"field_import_comicinfo_series_append_volume": "Додати том до назви серії",
|
||||
"field_import_epub_book": "Метадані книги",
|
||||
"field_import_epub_series": "Метадані серіалу",
|
||||
"field_import_local_artwork": "Місцеві витвори мистецтва",
|
||||
"field_import_mylar_series": "Метадані серіалу",
|
||||
"field_name": "Ім'я",
|
||||
"field_oneshotsdirectory": "Довідник One-Shots",
|
||||
"field_repair_extensions": "Автоматичне виправлення неправильних розширень файлів",
|
||||
"field_root_folder": "Коренева папка",
|
||||
"field_scan_interval": "Інтервал сканування",
|
||||
"field_scanner_empty_trash_after_scan": "Автоматично очищувати кошик після кожного сканування",
|
||||
"field_scanner_force_directory_modified_time": "Примусово змінений час каталогу",
|
||||
"field_scanner_scan_startup": "Сканування під час запуску",
|
||||
"field_series_cover": "Обкладинка серії",
|
||||
"file_browser_dialog_button_confirm": "Виберіть",
|
||||
"file_browser_dialog_title": "Коренева папка бібліотеки",
|
||||
"label_analysis": "Аналізи",
|
||||
"label_file_management": "Керування файлами",
|
||||
"label_import_barcode_isbn": "Імпорт ISBN у штрих-код",
|
||||
"label_import_comicinfo": "Імпорт метаданих для CBR/CBZ, що містять файл ComicInfo.xml",
|
||||
"label_import_epub": "Імпорт метаданих з файлів EPUB",
|
||||
"label_import_local": "Імпорт локальних медіаресурсів",
|
||||
"label_import_mylar": "Імпорт метаданих, згенерованих Mylar",
|
||||
"label_scan_directory_exclusions": "Виключення з каталогу",
|
||||
"label_scan_types": "Сканувати ці типи файлів",
|
||||
"label_scanner": "Сканер",
|
||||
"label_series_cover": "Обкладинка серії",
|
||||
"tab_general": "Загальне",
|
||||
"tab_metadata": "Метадані",
|
||||
"tab_options": "Опції",
|
||||
"tooltip_oneshotsdirectory": "Залиште порожнім, щоб вимкнути",
|
||||
"tooltip_scanner_force_modified_time": "Увімкнути, якщо бібліотека знаходиться на Google Диску",
|
||||
"tooltip_use_resources": "Може споживати багато ресурсів на великих бібліотеках або повільному обладнанні"
|
||||
},
|
||||
"edit_readlist": {
|
||||
"button_cancel": "Скасувати",
|
||||
"button_confirm": "Зберегти зміни",
|
||||
"dialog_title": "Редагувати список прочитаних",
|
||||
"field_manual_ordering": "Ручне замовлення",
|
||||
"field_name": "Ім'я",
|
||||
"field_summary": "Короткий зміст",
|
||||
"label_ordering": "За замовчуванням книги у списку прочитання впорядковуються вручну. Ви можете вимкнути ручне впорядкування, щоб сортувати книги за датою випуску.",
|
||||
"tab_general": "Загальне",
|
||||
"tab_poster": "Плакат"
|
||||
},
|
||||
"edit_recommended": {
|
||||
"button_confirm": "Зберегти зміни",
|
||||
"button_reset": "Скинути налаштування за замовчуванням",
|
||||
"dialog_title": "Редагувати рекомендований перегляд"
|
||||
},
|
||||
"edit_series": {
|
||||
"button_cancel": "Скасувати",
|
||||
"button_confirm": "Зберегти зміни",
|
||||
"dialog_title_multiple": "Редагувати {count} серій | Редагувати {count} серій",
|
||||
"dialog_title_single": "Редагувати {series}",
|
||||
"field_age_rating": "Віковий рейтинг",
|
||||
"field_age_rating_error": "Віковий рейтинг має бути 0 або більше",
|
||||
"field_genres": "Жанри",
|
||||
"field_labels": "Мітки",
|
||||
"field_language": "Мова",
|
||||
"field_language_hint": "Тег мови IETF BCP 47",
|
||||
"field_publisher": "Видавець",
|
||||
"field_reading_direction": "Напрямок читання",
|
||||
"field_sort_title": "Сортувати заголовок",
|
||||
"field_status": "Статус",
|
||||
"field_summary": "Короткий зміст",
|
||||
"field_tags": "Теги",
|
||||
"field_title": "Назва",
|
||||
"field_total_book_count": "Загальна кількість книг",
|
||||
"field_total_book_count_error": "Загальна кількість книг має бути 1 або більше",
|
||||
"mixed": "ЗМІШАНИЙ",
|
||||
"tab_general": "Загальне",
|
||||
"tab_poster": "Плакат",
|
||||
"tab_sharing": "Спільне використання",
|
||||
"tab_tags": "Теги",
|
||||
"tab_titles": "Альтернативні назви",
|
||||
"tags_notice_multiple_edit": "Ви редагуєте теги для кількох серій. Це замінить існуючі теги кожної серії."
|
||||
},
|
||||
"edit_user": {
|
||||
"button_cancel": "Скасувати",
|
||||
"button_confirm": "Зберегти зміни",
|
||||
"dialog_title": "Редагувати користувача",
|
||||
"label_roles_for": "Ролі для {name}"
|
||||
},
|
||||
"edit_user_restrictions": {
|
||||
"age_restriction": {
|
||||
"allow_under": "Дозволити лише під",
|
||||
"exclude_over": "Виключити понад",
|
||||
"none": "Без обмежень"
|
||||
},
|
||||
"edit_restrictions_for": "Редагувати обмеження для {name}",
|
||||
"label_age_restriction": "Вікове обмеження",
|
||||
"label_allow_only_labels": "Дозволити лише мітки",
|
||||
"label_exclude_labels": "Виключити мітки",
|
||||
"tab_content_restrictions": "Обмеження контенту",
|
||||
"tab_shared_libraries": "Спільні бібліотеки"
|
||||
},
|
||||
"empty_trash": {
|
||||
"body": "За замовчуванням медіасервер не видаляє інформацію про медіафайли одразу. Це допомагає, якщо диск тимчасово відключено. Під час очищення кошика бібліотеки вся інформація про відсутні медіафайли видаляється.",
|
||||
"button_confirm": "Порожній",
|
||||
"title": "Очистити кошик для бібліотеки"
|
||||
},
|
||||
"file_browser": {
|
||||
"button_cancel": "Скасувати",
|
||||
"button_confirm_default": "Виберіть",
|
||||
"dialog_title_default": "Браузер файлів",
|
||||
"parent_directory": "Батьківський"
|
||||
},
|
||||
"filename_chooser": {
|
||||
"button_choose": "Виберіть",
|
||||
"field_destination_filename": "Ім'я файлу призначення",
|
||||
"label_source_filename": "Ім'я вихідного файлу",
|
||||
"table": {
|
||||
"existing_file": "Існуючий файл",
|
||||
"order": "Замовлення"
|
||||
},
|
||||
"title": "Ім'я файлу призначення'"
|
||||
},
|
||||
"force_kobo_sync": {
|
||||
"dialog_title": "Примусова синхронізація Kobo",
|
||||
"warning_html": "Це видалить всю історію синхронізації для цього ключа API. Ваш Kobo синхронізує все під час наступної синхронізації."
|
||||
},
|
||||
"password_change": {
|
||||
"button_cancel": "Скасувати",
|
||||
"button_confirm": "Змінити пароль",
|
||||
"dialog_title": "Змінити пароль",
|
||||
"field_new_password": "Новий пароль",
|
||||
"field_new_password_error": "Потрібен новий пароль.",
|
||||
"field_repeat_password": "Повторіть новий пароль",
|
||||
"field_repeat_password_error": "Паролі мають бути однаковими."
|
||||
},
|
||||
"refresh_library_metadata": {
|
||||
"body": "Оновлює метадані для всіх медіафайлів у бібліотеці. Залежно від розміру вашої бібліотеки, це може тривати довго.",
|
||||
"button_confirm": "Оновити",
|
||||
"title": "Оновити метадані для бібліотеки"
|
||||
},
|
||||
"series_picker": {
|
||||
"label_search_series": "Пошук серій",
|
||||
"no_results": "Серії не знайдено",
|
||||
"title": "Виберіть серію"
|
||||
},
|
||||
"server_stop": {
|
||||
"button_confirm": "Стій",
|
||||
"confirmation_message": "Ви впевнені, що хочете зупинити Komga?",
|
||||
"dialog_title": "Вимкнути сервер"
|
||||
},
|
||||
"shortcut_help": {
|
||||
"label_description": "Опис",
|
||||
"label_key": "Ключ"
|
||||
},
|
||||
"transient_book_details": {
|
||||
"label_candidate": "Кандидат",
|
||||
"label_existing": "Існуючі",
|
||||
"label_format": "Формат",
|
||||
"label_name": "Ім'я",
|
||||
"label_pages": "Сторінки",
|
||||
"label_size": "Розмір",
|
||||
"pages_table": {
|
||||
"filename": "Ім'я Файлу",
|
||||
"height": "Висота",
|
||||
"index": "Індекс",
|
||||
"media_type": "Тип медіа",
|
||||
"size": "Розмір",
|
||||
"width": "Ширина"
|
||||
},
|
||||
"title": "Деталі книги",
|
||||
"title_comparison": "Порівняння книг"
|
||||
},
|
||||
"transient_book_viewer": {
|
||||
"label_candidate": "Кандидат",
|
||||
"label_existing": "Існуючі",
|
||||
"page_of_pages": "{page} / {pages}",
|
||||
"title": "Перевірити книгу",
|
||||
"title_comparison": "Порівняння книг"
|
||||
}
|
||||
},
|
||||
"duplicate_pages": {
|
||||
"action_auto_delete_remaining": "Залишок автоматичного видалення ({count})",
|
||||
"action_delete_auto": "Автоматичне видалення",
|
||||
"action_delete_manual": "Ручне видалення",
|
||||
"action_delete_matches": "Видалити збіги",
|
||||
"action_ignore": "Ігнорувати",
|
||||
"action_ignore_remaining": "Ігнорувати решту ({count})",
|
||||
"action_manual_delete_remaining": "Залишилося ручного видалення ({count})",
|
||||
"confirm_auto_delete_remaining": "Усі хеші сторінок, що залишилися на цій сторінці ({count}), будуть позначені для автоматичного видалення.",
|
||||
"confirm_manual_delete_remaining": "Усі хеші сторінок, що залишилися на цій сторінці ({count}), будуть позначені для ручного видалення.",
|
||||
"delete_to_save": "Видалити, щоб зберегти {size}",
|
||||
"deleted_count": "Видалено {count} разів",
|
||||
"empty_title": "Дублікатів сторінок не знайдено",
|
||||
"empty_title_known": "Немає відомих дублікатів",
|
||||
"filter": {
|
||||
"count": "Кількість",
|
||||
"date_added": "Дата додавання",
|
||||
"date_modified": "Дата зміни",
|
||||
"delete_count": "Кількість видалень",
|
||||
"delete_size": "Зекономлено місце",
|
||||
"match_count": "Кількість матчів",
|
||||
"size": "Розмір",
|
||||
"total_size": "Загальний розмір"
|
||||
},
|
||||
"info": "Видалення дублікатів сторінок призведе до змінення ваших файлів. Створіть резервну копію файлів та видаліть їх вручну, перш ніж використовувати автоматичне видалення.",
|
||||
"known": "Відомий",
|
||||
"matches_n": "Немає збігів | 1 збіг | {count} збігів",
|
||||
"new": "Новий",
|
||||
"saved_size": "Збережено {size}",
|
||||
"title": "Дублікати сторінок",
|
||||
"unknown_size": "Невідомий розмір"
|
||||
},
|
||||
"duplicates": {
|
||||
"file_hash": "Хеш файлу",
|
||||
"size": "Розмір",
|
||||
"title": "Дублікати файлів",
|
||||
"url": "URL"
|
||||
},
|
||||
"enums": {
|
||||
"copy_mode": {
|
||||
"HARDLINK": "Жорстке посилання/копіювання файлів",
|
||||
"MOVE": "Переміщення файлів"
|
||||
},
|
||||
"epubreader": {
|
||||
"appearances": {
|
||||
"day": "День",
|
||||
"night": "Ніч",
|
||||
"sepia": "Сепія"
|
||||
},
|
||||
"column_count": {
|
||||
"auto": "Авто",
|
||||
"one": "Один",
|
||||
"two": "Два"
|
||||
},
|
||||
"reading_direction": {
|
||||
"auto": "Автоматичний",
|
||||
"ltr": "Зліва направо",
|
||||
"rtl": "Справа наліво"
|
||||
}
|
||||
},
|
||||
"historical_event_type": {
|
||||
"BookConverted": "Книга перетворена",
|
||||
"BookFileDeleted": "Файл книги видалено",
|
||||
"BookImported": "Імпортовано книгу",
|
||||
"DuplicatePageDeleted": "Дублікат сторінки видалено",
|
||||
"SeriesFolderDeleted": "Папку серіалу видалено"
|
||||
},
|
||||
"media_profile": {
|
||||
"DIVINA": "DIVINA",
|
||||
"EPUB": "EPUB",
|
||||
"PDF": "PDF"
|
||||
},
|
||||
"media_status": {
|
||||
"ERROR": "Помилка",
|
||||
"OUTDATED": "Застарілий",
|
||||
"READY": "Готовий",
|
||||
"UNKNOWN": "Невідомо",
|
||||
"UNSUPPORTED": "Не підтримується"
|
||||
},
|
||||
"page_hash_action": {
|
||||
"DELETE_AUTO": "Автоматичне видалення",
|
||||
"DELETE_MANUAL": "Ручне видалення",
|
||||
"IGNORE": "Ігнорувати"
|
||||
},
|
||||
"reading_direction": {
|
||||
"LEFT_TO_RIGHT": "Зліва направо",
|
||||
"RIGHT_TO_LEFT": "Справа наліво",
|
||||
"VERTICAL": "Вертикальний",
|
||||
"WEBTOON": "Вебмультфільм"
|
||||
},
|
||||
"scan_interval": {
|
||||
"DAILY": "Щоденно",
|
||||
"DISABLED": "Вимкнено",
|
||||
"EVERY_12H": "Кожні 12 годин",
|
||||
"EVERY_6H": "Кожні 6 годин",
|
||||
"HOURLY": "Щогодини",
|
||||
"WEEKLY": "Щотижнево"
|
||||
},
|
||||
"series_cover": {
|
||||
"FIRST": "Перший",
|
||||
"FIRST_UNREAD_OR_FIRST": "Спочатку непрочитані, інакше спочатку",
|
||||
"FIRST_UNREAD_OR_LAST": "Спочатку непрочитані, інакше останні",
|
||||
"LAST": "Останній"
|
||||
},
|
||||
"series_status": {
|
||||
"ABANDONED": "Покинутий",
|
||||
"ENDED": "Закінчилося",
|
||||
"HIATUS": "Перерва",
|
||||
"ONGOING": "Поточний"
|
||||
},
|
||||
"thumbnail_size": {
|
||||
"DEFAULT": "За замовчуванням (300 пікселів)",
|
||||
"LARGE": "Великий (900 пікселів)",
|
||||
"MEDIUM": "Середній (600 пікселів)",
|
||||
"XLARGE": "Дуже великий (1200 пікселів)"
|
||||
}
|
||||
},
|
||||
"epubreader": {
|
||||
"current_chapter": "Поточний розділ",
|
||||
"page_of": "Сторінка {page} з {count}",
|
||||
"publisher_font": "Видавець",
|
||||
"settings": {
|
||||
"column_count": "Кількість стовпців",
|
||||
"font_family": "Шрифт",
|
||||
"layout": "Макет",
|
||||
"layout_paginated": "Пагінована",
|
||||
"layout_scroll": "Прокрутити",
|
||||
"navigation_mode": "Режим навігації",
|
||||
"navigation_options": {
|
||||
"both": "Обидва",
|
||||
"buttons": "Ґудзики",
|
||||
"click": "Клацніть / Торкніться"
|
||||
},
|
||||
"page_margins": "Поля сторінки",
|
||||
"viewing_theme": "Перегляд теми"
|
||||
},
|
||||
"shortcuts": {
|
||||
"cycle_pagination": "Циклічна кількість стовпців",
|
||||
"cycle_viewing_theme": "Тема перегляду велосипедів",
|
||||
"font_size_decrease": "Зменшити розмір шрифту",
|
||||
"font_size_increase": "Збільшити розмір шрифту",
|
||||
"menus": "Меню",
|
||||
"next": "Вперед",
|
||||
"previous": "Назад",
|
||||
"reader_navigation": "Навігація читача",
|
||||
"scroll": "Змінити макет на прокручування",
|
||||
"settings": "Налаштування",
|
||||
"show_hide_toc": "Показати/приховати зміст"
|
||||
}
|
||||
},
|
||||
"error_codes": {
|
||||
"ERR_1000": "Не вдалося отримати доступ до файлу під час аналізу",
|
||||
"ERR_1001": "Тип медіа не підтримується",
|
||||
"ERR_1002": "Зашифровані RAR-архіви не підтримуються",
|
||||
"ERR_1003": "Архів Solid RAR не підтримується",
|
||||
"ERR_1004": "Багатотомні RAR-архіви не підтримуються",
|
||||
"ERR_1005": "Невідома помилка під час аналізу книги",
|
||||
"ERR_1006": "Книга не містить жодної сторінки",
|
||||
"ERR_1007": "Деякі записи не вдалося проаналізувати",
|
||||
"ERR_1008": "Невідома помилка під час отримання записів книги",
|
||||
"ERR_1009": "Список для читання з такою назвою вже існує'",
|
||||
"ERR_1015": "Помилка під час десеріалізації ComicRack CBL",
|
||||
"ERR_1016": "Каталог недоступний або не є каталогом",
|
||||
"ERR_1017": "Не вдається сканувати папку, яка є частиною існуючої бібліотеки",
|
||||
"ERR_1018": "Файл не знайдено",
|
||||
"ERR_1019": "Неможливо імпортувати файл, який є частиною існуючої бібліотеки",
|
||||
"ERR_1020": "Книга для оновлення не належить до наданої серії",
|
||||
"ERR_1021": "Цільовий файл вже існує",
|
||||
"ERR_1022": "Не вдалося відсканувати нещодавно імпортовану книгу",
|
||||
"ERR_1023": "Книга вже є у списку для читання",
|
||||
"ERR_1024": "Помилка входу OAuth2: немає атрибута електронної пошти",
|
||||
"ERR_1025": "Помилка входу OAuth2: локального користувача з такою електронною адресою не існує",
|
||||
"ERR_1026": "Помилка входу в OpenID Connect: електронна адреса не підтверджена",
|
||||
"ERR_1027": "Помилка входу в OpenID Connect: немає атрибута email_verified",
|
||||
"ERR_1028": "Помилка входу в OpenID Connect: немає атрибута електронної пошти",
|
||||
"ERR_1029": "ComicRack CBL не містить жодного елемента Book",
|
||||
"ERR_1030": "ComicRack CBL не має елемента Name",
|
||||
"ERR_1031": "У книзі ComicRack CBL відсутня серія або номер",
|
||||
"ERR_1032": "Файл EPUB має неправильний тип медіафайлу",
|
||||
"ERR_1033": "Деякі записи відсутні",
|
||||
"ERR_1034": "Ключ API з цим коментарем вже існує",
|
||||
"ERR_1035": "Помилка під час отримання змісту EPUB",
|
||||
"ERR_1036": "Помилка під час отримання орієнтирів EPUB",
|
||||
"ERR_1037": "Помилка під час отримання списку сторінок EPUB",
|
||||
"ERR_1038": "Помилка під час отримання сторінок EPUB divina",
|
||||
"ERR_1039": "Помилка під час отримання позицій EPUB"
|
||||
},
|
||||
"filter": {
|
||||
"age_rating": "віковий рейтинг",
|
||||
"age_rating_none": "Жоден",
|
||||
"any": "Будь-який",
|
||||
"complete": "Завершено",
|
||||
"genre": "жанр",
|
||||
"in_progress": "У процесі",
|
||||
"language": "мова",
|
||||
"library": "бібліотека",
|
||||
"media_profile": "Медіа-профіль",
|
||||
"media_status": "Стан медіа",
|
||||
"oneshot": "Одноразовий",
|
||||
"publisher": "видавець",
|
||||
"read": "Читати",
|
||||
"release_date": "дата випуску",
|
||||
"sharing_label": "Мітка спільного доступу",
|
||||
"status": "статус",
|
||||
"tag": "тег",
|
||||
"unread": "Непрочитане"
|
||||
},
|
||||
"filter_drawer": {
|
||||
"filter": "фільтр",
|
||||
"sort": "сортувати"
|
||||
},
|
||||
"history": {
|
||||
"header": {
|
||||
"book": "Книга",
|
||||
"date": "Дата",
|
||||
"details": "Деталі",
|
||||
"series": "Серія",
|
||||
"type": "Тип"
|
||||
},
|
||||
"title": "Історія"
|
||||
},
|
||||
"home": {
|
||||
"theme": "Тема",
|
||||
"translation": "Переклад"
|
||||
},
|
||||
"library_navigation": {
|
||||
"browse": "Переглянути",
|
||||
"browse_books": "Книги",
|
||||
"browse_series": "Серія",
|
||||
"collections": "Колекції",
|
||||
"readlists": "Списки для читання",
|
||||
"recommended": "Рекомендовано"
|
||||
},
|
||||
"login": {
|
||||
"create_user_account": "Створити обліковий запис користувача",
|
||||
"login": "Увійти",
|
||||
"unclaimed_html": "Цей сервер Komga ще не активний, вам потрібно створити обліковий запис користувача, щоб мати до нього доступ.<br><br>Виберіть <strong>електронну пошту</strong> та <strong>пароль</strong> і натисніть <strong>Створити обліковий запис користувача</strong>."
|
||||
},
|
||||
"media_analysis": {
|
||||
"comment": "Коментар",
|
||||
"media_analysis": "Медіа-аналіз",
|
||||
"media_type": "Тип носія",
|
||||
"name": "Ім'я",
|
||||
"size": "Розмір",
|
||||
"status": "Статус",
|
||||
"url": "URL"
|
||||
},
|
||||
"menu": {
|
||||
"add_to_collection": "Додати до колекції",
|
||||
"add_to_readlist": "Додати до списку прочитання",
|
||||
"analyze": "Аналіз",
|
||||
"bulk_edit_metadata": "Масове редагування метаданих",
|
||||
"delete": "Видалити",
|
||||
"deselect_all": "Зняти вибір усіх",
|
||||
"download_readlist": "Завантажити список для читання",
|
||||
"download_series": "Завантажити серію",
|
||||
"edit": "Редагувати",
|
||||
"edit_metadata": "Редагувати метадані",
|
||||
"empty_trash": "Очистити кошик",
|
||||
"mark_read": "Позначити як прочитане",
|
||||
"mark_unread": "Позначити як непрочитане",
|
||||
"pin": "Закріпити",
|
||||
"refresh_metadata": "Оновити метадані",
|
||||
"scan_library_files": "Сканування файлів бібліотеки",
|
||||
"scan_library_files_deep": "Сканувати файли бібліотеки (глибоко)",
|
||||
"select_all": "Вибрати все",
|
||||
"unpin": "Відкріпити"
|
||||
},
|
||||
"metrics": {
|
||||
"library_books": "Книги на бібліотеку",
|
||||
"library_disk_space": "Місце на диску бібліотеки",
|
||||
"library_series": "Серії на бібліотеку",
|
||||
"library_sidecars": "Коляски на бібліотеку",
|
||||
"tasks_executed": "Виконані завдання",
|
||||
"tasks_total_time": "Загальний час виконання завдань",
|
||||
"title": "Метрики"
|
||||
},
|
||||
"missing_posters": {
|
||||
"title": "Відсутні плакати"
|
||||
},
|
||||
"navigation": {
|
||||
"home": "Дім",
|
||||
"libraries": "Бібліотеки",
|
||||
"logout": "Вийти"
|
||||
},
|
||||
"no_libraries_pinned": {
|
||||
"subtitle": "Ви можете закріпити бібліотеку з меню з трьома крапками",
|
||||
"title": "Немає закріплених бібліотек"
|
||||
},
|
||||
"page_not_found": {
|
||||
"go_back_to_home_page": "Повернутися на головну сторінку",
|
||||
"page_does_not_exist": "Сторінка, яку ви шукаєте, не існує.",
|
||||
"page_not_found": "Сторінку не знайдено"
|
||||
},
|
||||
"read_more": {
|
||||
"less": "Читати менше",
|
||||
"more": "Читати більше"
|
||||
},
|
||||
"readlist_import": {
|
||||
"row": {
|
||||
"duplicate_book": "Дублікат книги",
|
||||
"error_choose_book": "Виберіть у книгу"
|
||||
}
|
||||
},
|
||||
"readlists_expansion_panel": {
|
||||
"manage_readlist": "Керування списком прочитаних",
|
||||
"title": "Список прочитаного {name}"
|
||||
},
|
||||
"search": {
|
||||
"no_results": "Пошук не дав результатів",
|
||||
"search": "Пошук",
|
||||
"search_for_something_else": "Спробуйте пошукати щось інше",
|
||||
"search_results_for": "Результати пошуку для \"{name}\""
|
||||
},
|
||||
"searchbox": {
|
||||
"in_library": "З {library}",
|
||||
"no_results": "Немає результатів",
|
||||
"search_all": "Шукати все…"
|
||||
},
|
||||
"server": {
|
||||
"server_management": {
|
||||
"button_cancel_all_tasks": "Скасувати всі завдання",
|
||||
"button_empty_trash": "Очистити кошик для всіх бібліотек",
|
||||
"button_scan_libraries": "Сканувати всі бібліотеки",
|
||||
"button_scan_libraries_deep": "Сканувати всі бібліотеки (глибоко)",
|
||||
"button_shutdown": "Вимкнути",
|
||||
"download_log": "Завантажити файл журналу",
|
||||
"notification_tasks_cancelled": "Немає завдань для скасування | Одне завдання скасовано | {count} завдань скасовано",
|
||||
"section_title": "Керування сервером"
|
||||
},
|
||||
"tab_title": "Сервер",
|
||||
"updates": "Оновлення"
|
||||
},
|
||||
"server_settings": {
|
||||
"config_precedence": "Має пріоритет над файлом конфігурації",
|
||||
"dialog_regenerate_thumbnails": {
|
||||
"body": "Розмір мініатюр змінився. Бажаєте створити мініатюри книг заново?",
|
||||
"btn_alternate": "Так, усі книги",
|
||||
"btn_cancel": "Ні",
|
||||
"btn_confirm": "Так, але тільки якщо більший",
|
||||
"title": "Згенерувати мініатюри знову"
|
||||
},
|
||||
"hint_kobo_port": "Встановлювати лише у разі проблем із синхронізацією обкладинок та завантажень",
|
||||
"label_delete_empty_collections": "Видалити порожні колекції після сканування",
|
||||
"label_delete_empty_readlists": "Видалити порожні списки прочитання після сканування",
|
||||
"label_kepubify_path": "Шлях до kepubify",
|
||||
"label_kobo_port": "Зовнішній порт Kobo Sync",
|
||||
"label_kobo_proxy": "Запити синхронізації проксі-сервера Kobo до магазину Kobo",
|
||||
"label_rememberme_duration": "Тривалість дії функції «Запам’ятати мене» (у днях)",
|
||||
"label_server_context_path": "Базова URL-адреса",
|
||||
"label_server_port": "Порт сервера",
|
||||
"label_task_pool_size": "Гілки завдань",
|
||||
"label_thumbnail_size": "Розмір мініатюр",
|
||||
"requires_restart": "Потрібен перезапуск, щоб набути чинності",
|
||||
"server_settings": "Налаштування сервера"
|
||||
},
|
||||
"settings_user": {
|
||||
"change_password": "Змінити пароль",
|
||||
"edit_restrictions": "Редагувати обмеження",
|
||||
"edit_user": "Редагувати користувача",
|
||||
"latest_activity": "Остання активність: {date}",
|
||||
"no_recent_activity": "Немає нещодавньої активності",
|
||||
"role_administrator": "Адміністратор",
|
||||
"role_user": "Користувач"
|
||||
},
|
||||
"sort": {
|
||||
"books_count": "Кількість книг",
|
||||
"date_added": "Дата додавання",
|
||||
"date_read": "Дата прочитання",
|
||||
"date_updated": "Дата оновлення",
|
||||
"file_name": "Ім'я файлу",
|
||||
"file_size": "Розмір файлу",
|
||||
"folder_name": "Назва папки",
|
||||
"name": "Ім'я",
|
||||
"number": "Номер",
|
||||
"page_count": "Кількість сторінок",
|
||||
"random": "Випадкове",
|
||||
"release_date": "Дата випуску'",
|
||||
"series": "Серія"
|
||||
},
|
||||
"theme": {
|
||||
"dark": "Темний",
|
||||
"light": "Світло",
|
||||
"system": "Система"
|
||||
},
|
||||
"thumbnail_card": {
|
||||
"tooltip_delete": "Видалити",
|
||||
"tooltip_generated": "Згенеровані ілюстрації",
|
||||
"tooltip_mark_as_selected": "Позначити як вибране",
|
||||
"tooltip_selected": "Вибрано",
|
||||
"tooltip_sidecar": "Місцеві витвори мистецтва",
|
||||
"tooltip_to_be_deleted": "Буде видалено",
|
||||
"tooltip_to_be_uploaded": "Для завантаження",
|
||||
"tooltip_too_big": "Файл занадто великий!",
|
||||
"tooltip_user_uploaded": "Завантажено користувачем"
|
||||
},
|
||||
"titles_more": {
|
||||
"less": "Менше назв",
|
||||
"more": "Більше назв"
|
||||
},
|
||||
"ui_settings": {
|
||||
"general": "Загальне",
|
||||
"label_oauth2_auto_login": "Автоматичний вхід OAuth2",
|
||||
"label_oauth2_hide_login": "Приховати поля входу, якщо ввімкнено OAuth2",
|
||||
"label_poster_blur_unread": "Розмиття плаката для непрочитаних книг та серій",
|
||||
"label_poster_stretch": "Розтягніть плакат, щоб він підходив до листівки",
|
||||
"label_series_groups": "Групування серій",
|
||||
"section_oauth2": "OAuth2",
|
||||
"series_groups": {
|
||||
"alpha": "Алфавітний",
|
||||
"japanese": "Годзюон (японська)"
|
||||
},
|
||||
"tooltip_oauth2_auto_login": "Потрібен один постачальник OAuth2 та ввімкнена функція «приховувати поля входу»"
|
||||
},
|
||||
"updates": {
|
||||
"available": "Доступні оновлення",
|
||||
"latest_installed": "Остання версія Komga вже встановлена"
|
||||
},
|
||||
"user_roles": {
|
||||
"ADMIN": "Адміністратор",
|
||||
"FILE_DOWNLOAD": "Завантаження файлу",
|
||||
"KOBO_SYNC": "Синхронізація Kobo",
|
||||
"KOREADER_SYNC": "Синхронізація KOReader",
|
||||
"PAGE_STREAMING": "Потокове передавання сторінок",
|
||||
"USER": "Користувач"
|
||||
},
|
||||
"users": {
|
||||
"api_keys": "Ключі API",
|
||||
"authentication_activity": "Активність автентифікації",
|
||||
"users": "Користувачі"
|
||||
},
|
||||
"validation": {
|
||||
"context_path": "Повинно починатися з '/', не закінчуватися на '/-_' та містити лише '/-_a-z0-9'",
|
||||
"one_or_more": "Має бути 1 або більше",
|
||||
"tcp_port": "Має бути від 1 до 65535",
|
||||
"zero_or_more": "Має бути 0 або більше"
|
||||
},
|
||||
"welcome": {
|
||||
"add_library": "Додати бібліотеку'",
|
||||
"no_libraries_yet": "Ще не додано жодної бібліотеки!",
|
||||
"welcome_message": "Ласкаво просимо до Komga"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -906,14 +906,14 @@ export default Vue.extend({
|
|||
}, 50),
|
||||
downloadCurrentPage() {
|
||||
new jsFileDownloader({
|
||||
url: this.currentPage.url,
|
||||
url: `${this.currentPage.url}?contentNegotiation=false`,
|
||||
filename: `${this.book.name}-${this.currentPage.number}.${this.currentPage.fileName.split('.').pop()}`,
|
||||
withCredentials: true,
|
||||
forceDesktopMode: true,
|
||||
})
|
||||
},
|
||||
async setCurrentPageAsPoster(type: ItemTypes) {
|
||||
const imageFile = await getFileFromUrl(this.currentPage.url, 'poster', 'image/jpeg', {credentials: 'include'})
|
||||
const imageFile = await getFileFromUrl(`${this.currentPage.url}?contentNegotiation=false`, 'poster', 'image/jpeg', {credentials: 'include'})
|
||||
const newImageFile = await resizeImageFile(imageFile)
|
||||
switch (type) {
|
||||
case ItemTypes.BOOK:
|
||||
|
|
|
|||
|
|
@ -3,13 +3,14 @@ import org.apache.tools.ant.taskdefs.condition.Os
|
|||
import org.flywaydb.gradle.task.FlywayMigrateTask
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
import org.jetbrains.kotlin.util.prefixIfNot
|
||||
import org.springframework.boot.gradle.plugin.SpringBootPlugin
|
||||
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
kotlin("plugin.spring")
|
||||
kotlin("kapt")
|
||||
id("org.springframework.boot") version "3.5.4"
|
||||
id("com.gorylenko.gradle-git-properties") version "2.5.2"
|
||||
id("org.springframework.boot") version libs.versions.springboot.get()
|
||||
alias(libs.plugins.gradleGitProperties)
|
||||
id("nu.studer.jooq") version "10.1"
|
||||
id("org.flywaydb.flyway") version "11.7.2"
|
||||
id("com.github.johnrengelman.processes") version "0.5.0"
|
||||
|
|
@ -37,7 +38,7 @@ dependencies {
|
|||
implementation(kotlin("stdlib"))
|
||||
implementation(kotlin("reflect"))
|
||||
|
||||
api(platform("org.springframework.boot:spring-boot-dependencies:3.5.4"))
|
||||
api(platform(SpringBootPlugin.BOM_COORDINATES))
|
||||
|
||||
api("org.springframework.boot:spring-boot-starter-web")
|
||||
implementation("org.springframework.boot:spring-boot-starter-webflux")
|
||||
|
|
@ -51,7 +52,7 @@ dependencies {
|
|||
implementation("com.github.gotson:spring-session-caffeine:2.1.0")
|
||||
implementation("org.springframework.data:spring-data-commons")
|
||||
|
||||
kapt("org.springframework.boot:spring-boot-configuration-processor:3.5.4")
|
||||
kapt("org.springframework.boot:spring-boot-configuration-processor:${libs.versions.springboot.get()}")
|
||||
|
||||
implementation("org.flywaydb:flyway-core")
|
||||
|
||||
|
|
@ -66,14 +67,10 @@ dependencies {
|
|||
implementation("org.apache.commons:commons-lang3:3.18.0")
|
||||
implementation("commons-validator:commons-validator:1.10.0")
|
||||
|
||||
run {
|
||||
// v10 requires JDK 21
|
||||
val luceneVersion = "9.9.1"
|
||||
implementation("org.apache.lucene:lucene-core:$luceneVersion")
|
||||
implementation("org.apache.lucene:lucene-analysis-common:$luceneVersion")
|
||||
implementation("org.apache.lucene:lucene-queryparser:$luceneVersion")
|
||||
implementation("org.apache.lucene:lucene-backward-codecs:$luceneVersion")
|
||||
}
|
||||
implementation("org.apache.lucene:lucene-core:${libs.versions.lucene.get()}")
|
||||
implementation("org.apache.lucene:lucene-analysis-common:${libs.versions.lucene.get()}")
|
||||
implementation("org.apache.lucene:lucene-queryparser:${libs.versions.lucene.get()}")
|
||||
implementation("org.apache.lucene:lucene-backward-codecs:${libs.versions.lucene.get()}")
|
||||
|
||||
implementation("com.ibm.icu:icu4j:77.1")
|
||||
|
||||
|
|
@ -82,18 +79,18 @@ dependencies {
|
|||
implementation("org.apache.tika:tika-core:2.9.1")
|
||||
implementation("org.apache.commons:commons-compress:1.27.1")
|
||||
implementation("com.github.junrar:junrar:7.5.5")
|
||||
implementation("com.github.gotson.nightcompress:nightcompress:1.1.0")
|
||||
implementation("com.github.gotson.nightcompress:nightcompress:1.1.1")
|
||||
implementation("org.apache.pdfbox:pdfbox:3.0.5")
|
||||
implementation("net.grey-panther:natural-comparator:1.1")
|
||||
implementation("org.jsoup:jsoup:1.18.3")
|
||||
implementation("org.jsoup:jsoup:1.21.1")
|
||||
|
||||
implementation("net.coobird:thumbnailator:0.4.20")
|
||||
runtimeOnly("com.twelvemonkeys.imageio:imageio-jpeg:3.12.0")
|
||||
runtimeOnly("com.twelvemonkeys.imageio:imageio-tiff:3.12.0")
|
||||
runtimeOnly("com.twelvemonkeys.imageio:imageio-webp:3.12.0")
|
||||
runtimeOnly("com.github.gotson.nightmonkeys:imageio-jxl:1.0.0")
|
||||
runtimeOnly("com.github.gotson.nightmonkeys:imageio-heif:1.0.0")
|
||||
runtimeOnly("com.github.gotson.nightmonkeys:imageio-webp:1.0.0")
|
||||
runtimeOnly("com.twelvemonkeys.imageio:imageio-jpeg:${libs.versions.twelvemonkeys.get()}")
|
||||
runtimeOnly("com.twelvemonkeys.imageio:imageio-tiff:${libs.versions.twelvemonkeys.get()}")
|
||||
runtimeOnly("com.twelvemonkeys.imageio:imageio-webp:${libs.versions.twelvemonkeys.get()}")
|
||||
runtimeOnly("com.github.gotson.nightmonkeys:imageio-jxl:${libs.versions.nightmonkeys.get()}")
|
||||
runtimeOnly("com.github.gotson.nightmonkeys:imageio-heif:${libs.versions.nightmonkeys.get()}")
|
||||
runtimeOnly("com.github.gotson.nightmonkeys:imageio-webp:${libs.versions.nightmonkeys.get()}")
|
||||
// support for jpeg2000
|
||||
runtimeOnly("com.github.jai-imageio:jai-imageio-jpeg2000:1.4.0")
|
||||
runtimeOnly("org.apache.pdfbox:jbig2-imageio:3.0.4")
|
||||
|
|
@ -107,8 +104,8 @@ dependencies {
|
|||
|
||||
implementation("com.github.ben-manes.caffeine:caffeine")
|
||||
|
||||
implementation("org.xerial:sqlite-jdbc:3.50.2.0")
|
||||
jooqGenerator("org.xerial:sqlite-jdbc:3.50.2.0")
|
||||
implementation("org.xerial:sqlite-jdbc:${libs.versions.sqliteJdbc.get()}")
|
||||
jooqGenerator("org.xerial:sqlite-jdbc:${libs.versions.sqliteJdbc.get()}")
|
||||
|
||||
if (version.toString().endsWith(".0.0")) {
|
||||
ksp("com.github.gotson.bestbefore:bestbefore-processor-kotlin:0.2.0")
|
||||
|
|
@ -127,9 +124,9 @@ dependencies {
|
|||
benchmarkImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2")
|
||||
benchmarkImplementation("org.openjdk.jmh:jmh-core:1.37")
|
||||
kaptBenchmark("org.openjdk.jmh:jmh-generator-annprocess:1.37")
|
||||
kaptBenchmark("org.springframework.boot:spring-boot-configuration-processor:3.5.4")
|
||||
kaptBenchmark("org.springframework.boot:spring-boot-configuration-processor:${libs.versions.springboot.get()}")
|
||||
|
||||
developmentOnly("org.springframework.boot:spring-boot-devtools:3.5.4")
|
||||
developmentOnly("org.springframework.boot:spring-boot-devtools:${libs.versions.springboot.get()}")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
|
|
@ -306,13 +303,13 @@ tasks.register("flywayMigrateTasks", FlywayMigrateTask::class) {
|
|||
buildscript {
|
||||
configurations["classpath"].resolutionStrategy.eachDependency {
|
||||
if (requested.group.startsWith("org.jooq") && requested.name.startsWith("jooq")) {
|
||||
useVersion("3.19.24")
|
||||
useVersion(libs.versions.jooq.get())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jooq {
|
||||
version = "3.19.24"
|
||||
version = libs.versions.jooq.get()
|
||||
configurations {
|
||||
create("main") {
|
||||
jooqConfiguration.apply {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ FROM ubuntu:24.10 as build-amd64
|
|||
ENV JAVA_HOME=/opt/java/openjdk
|
||||
COPY --from=eclipse-temurin:23-jre $JAVA_HOME $JAVA_HOME
|
||||
ENV PATH="${JAVA_HOME}/bin:${PATH}"
|
||||
RUN apt -y update && \
|
||||
RUN sed -i -re 's/([a-z]{2}\.)?archive.ubuntu.com|security.ubuntu.com/old-releases.ubuntu.com/g' /etc/apt/sources.list.d/ubuntu.sources && \
|
||||
apt -y update && \
|
||||
apt -y install ca-certificates locales libjxl-dev libheif-dev libwebp-dev libarchive-dev wget curl && \
|
||||
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen && \
|
||||
locale-gen en_US.UTF-8 && \
|
||||
|
|
@ -23,7 +24,8 @@ FROM ubuntu:24.10 as build-arm64
|
|||
ENV JAVA_HOME=/opt/java/openjdk
|
||||
COPY --from=eclipse-temurin:23-jre $JAVA_HOME $JAVA_HOME
|
||||
ENV PATH="${JAVA_HOME}/bin:${PATH}"
|
||||
RUN apt -y update && \
|
||||
RUN sed -i -re 's/([a-z]{2}\.)?ports.ubuntu.com\/ubuntu-ports/old-releases.ubuntu.com\/ubuntu/g' /etc/apt/sources.list.d/ubuntu.sources && \
|
||||
apt -y update && \
|
||||
apt -y install ca-certificates locales libjxl-dev libheif-dev libwebp-dev libarchive-dev wget curl && \
|
||||
echo "en_US.UTF-8 UTF-8" >> /etc/locale.gen && \
|
||||
locale-gen en_US.UTF-8 && \
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
"url": "https://github.com/gotson/komga/blob/master/LICENSE"
|
||||
},
|
||||
"title": "Komga API",
|
||||
"version": "1.23.1"
|
||||
"version": "1.23.6"
|
||||
},
|
||||
"externalDocs": {
|
||||
"description": "Komga documentation",
|
||||
|
|
@ -4919,7 +4919,7 @@
|
|||
"operationId": "matchComicRackList",
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"multipart/form-data": {
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
|
@ -10313,6 +10313,9 @@
|
|||
"bookId": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"properties": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
|
|
@ -10331,6 +10334,7 @@
|
|||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"properties",
|
||||
"timestamp",
|
||||
"type"
|
||||
|
|
@ -13082,7 +13086,9 @@
|
|||
"type": "boolean"
|
||||
},
|
||||
"kepubifyPath": {
|
||||
"type": "string"
|
||||
"type": "string",
|
||||
"deprecated": true,
|
||||
"description": "Will be removed in a future version"
|
||||
},
|
||||
"koboPort": {
|
||||
"type": "integer",
|
||||
|
|
|
|||
|
|
@ -418,6 +418,7 @@ class BookLifecycle(
|
|||
val extension =
|
||||
mediaRepository.findExtensionByIdOrNull(book.id) as? MediaExtensionEpub
|
||||
?: throw IllegalArgumentException("Epub extension not found")
|
||||
.also { logger.error { "Epub extension not found for book ${book.id}. Book should be re-analyzed." } }
|
||||
extension.positions[page - 1]
|
||||
} else {
|
||||
null
|
||||
|
|
@ -496,6 +497,7 @@ class BookLifecycle(
|
|||
val extension =
|
||||
mediaRepository.findExtensionByIdOrNull(book.id) as? MediaExtensionEpub
|
||||
?: throw IllegalArgumentException("Epub extension not found")
|
||||
.also { logger.error { "Epub extension not found for book ${book.id}. Book should be re-analyzed." } }
|
||||
// match progression with positions
|
||||
val matchingPositions = extension.positions.filter { it.href == href }
|
||||
val matchedPosition =
|
||||
|
|
|
|||
|
|
@ -113,14 +113,14 @@ class ReadListLifecycle(
|
|||
|
||||
fun deleteEmptyReadLists() {
|
||||
logger.info { "Deleting empty read lists" }
|
||||
transactionTemplate.executeWithoutResult {
|
||||
val toDelete = readListRepository.findAllEmpty()
|
||||
transactionTemplate.executeWithoutResult {
|
||||
thumbnailReadListRepository.deleteByReadListIds(toDelete.map { it.id })
|
||||
readListRepository.delete(toDelete.map { it.id })
|
||||
}
|
||||
|
||||
toDelete.forEach { eventPublisher.publishEvent(DomainEvent.ReadListDeleted(it)) }
|
||||
}
|
||||
}
|
||||
|
||||
fun addThumbnail(thumbnail: ThumbnailReadList): ThumbnailReadList {
|
||||
when (thumbnail.type) {
|
||||
|
|
|
|||
|
|
@ -99,14 +99,14 @@ class SeriesCollectionLifecycle(
|
|||
|
||||
fun deleteEmptyCollections() {
|
||||
logger.info { "Deleting empty collections" }
|
||||
transactionTemplate.executeWithoutResult {
|
||||
val toDelete = collectionRepository.findAllEmpty()
|
||||
transactionTemplate.executeWithoutResult {
|
||||
thumbnailSeriesCollectionRepository.deleteByCollectionIds(toDelete.map { it.id })
|
||||
collectionRepository.delete(toDelete.map { it.id })
|
||||
}
|
||||
|
||||
toDelete.forEach { eventPublisher.publishEvent(DomainEvent.CollectionDeleted(it)) }
|
||||
}
|
||||
}
|
||||
|
||||
fun addThumbnail(thumbnail: ThumbnailSeriesCollection): ThumbnailSeriesCollection {
|
||||
when (thumbnail.type) {
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ class KomgaProperties {
|
|||
@get:Positive
|
||||
var maxPoolSize: Int = 1
|
||||
|
||||
var journalMode: JournalMode? = null
|
||||
var journalMode: JournalMode? = JournalMode.WAL
|
||||
|
||||
@DurationUnit(ChronoUnit.SECONDS)
|
||||
var busyTimeout: Duration? = null
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@ class Hasher {
|
|||
return computeHash(path.inputStream())
|
||||
}
|
||||
|
||||
fun computeHash(string: String): String = computeHash(string.byteInputStream())
|
||||
|
||||
fun computeHash(stream: InputStream): String {
|
||||
val hash = Algorithm.XXH3_128.Seeded(SEED.toLong()).createDigest()
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
package org.gotson.komga.infrastructure.jooq
|
||||
|
||||
import org.jooq.DSLContext
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager
|
||||
|
||||
abstract class SplitDslDaoBase {
|
||||
val dslRW: DSLContext
|
||||
private val _dslRO: DSLContext
|
||||
|
||||
constructor(dslRW: DSLContext, dslRO: DSLContext) {
|
||||
this.dslRW = dslRW
|
||||
this._dslRO = dslRO
|
||||
}
|
||||
|
||||
val dslRO: DSLContext
|
||||
get() =
|
||||
if (TransactionSynchronizationManager.isActualTransactionActive() && !TransactionSynchronizationManager.isCurrentTransactionReadOnly())
|
||||
dslRW
|
||||
else
|
||||
_dslRO
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@ package org.gotson.komga.infrastructure.jooq.main
|
|||
import org.gotson.komga.domain.model.AuthenticationActivity
|
||||
import org.gotson.komga.domain.model.KomgaUser
|
||||
import org.gotson.komga.domain.persistence.AuthenticationActivityRepository
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.infrastructure.jooq.toOrderBy
|
||||
import org.gotson.komga.jooq.main.Tables
|
||||
import org.gotson.komga.jooq.main.tables.records.AuthenticationActivityRecord
|
||||
|
|
@ -21,9 +22,10 @@ import java.time.LocalDateTime
|
|||
|
||||
@Component
|
||||
class AuthenticationActivityDao(
|
||||
private val dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
) : AuthenticationActivityRepository {
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
AuthenticationActivityRepository {
|
||||
private val aa = Tables.AUTHENTICATION_ACTIVITY
|
||||
|
||||
private val sorts =
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package org.gotson.komga.infrastructure.jooq.main
|
||||
|
||||
import org.gotson.komga.domain.model.ContentRestrictions
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.infrastructure.jooq.toCondition
|
||||
import org.gotson.komga.jooq.main.Tables
|
||||
import org.jooq.DSLContext
|
||||
|
|
@ -19,8 +20,9 @@ import java.time.LocalDateTime
|
|||
|
||||
@Component
|
||||
class BookCommonDao(
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
) {
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
) : SplitDslDaoBase(dslRW, dslRO) {
|
||||
private val b = Tables.BOOK
|
||||
private val m = Tables.MEDIA
|
||||
private val d = Tables.BOOK_METADATA
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import org.gotson.komga.domain.model.SearchContext
|
|||
import org.gotson.komga.domain.persistence.BookRepository
|
||||
import org.gotson.komga.infrastructure.jooq.BookSearchHelper
|
||||
import org.gotson.komga.infrastructure.jooq.RequiredJoin
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.infrastructure.jooq.TempTable.Companion.withTempTable
|
||||
import org.gotson.komga.infrastructure.jooq.rlbAlias
|
||||
import org.gotson.komga.infrastructure.jooq.toOrderBy
|
||||
|
|
@ -30,10 +31,11 @@ import java.time.ZoneId
|
|||
|
||||
@Component
|
||||
class BookDao(
|
||||
private val dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
@param:Value("#{@komgaProperties.database.batchChunkSize}") private val batchSize: Int,
|
||||
) : BookRepository {
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
BookRepository {
|
||||
private val b = Tables.BOOK
|
||||
private val m = Tables.MEDIA
|
||||
private val d = Tables.BOOK_METADATA
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import org.gotson.komga.domain.model.SearchContext
|
|||
import org.gotson.komga.infrastructure.datasource.SqliteUdfDataSource
|
||||
import org.gotson.komga.infrastructure.jooq.BookSearchHelper
|
||||
import org.gotson.komga.infrastructure.jooq.RequiredJoin
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.infrastructure.jooq.TempTable
|
||||
import org.gotson.komga.infrastructure.jooq.TempTable.Companion.withTempTable
|
||||
import org.gotson.komga.infrastructure.jooq.noCase
|
||||
|
|
@ -51,11 +52,13 @@ import java.net.URL
|
|||
|
||||
@Component
|
||||
class BookDtoDao(
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
private val luceneHelper: LuceneHelper,
|
||||
@param:Value("#{@komgaProperties.database.batchChunkSize}") private val batchSize: Int,
|
||||
private val bookCommonDao: BookCommonDao,
|
||||
) : BookDtoRepository {
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
BookDtoRepository {
|
||||
private val b = Tables.BOOK
|
||||
private val m = Tables.MEDIA
|
||||
private val d = Tables.BOOK_METADATA
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package org.gotson.komga.infrastructure.jooq.main
|
|||
import org.gotson.komga.domain.model.Author
|
||||
import org.gotson.komga.domain.model.BookMetadataAggregation
|
||||
import org.gotson.komga.domain.persistence.BookMetadataAggregationRepository
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.infrastructure.jooq.TempTable.Companion.withTempTable
|
||||
import org.gotson.komga.jooq.main.Tables
|
||||
import org.gotson.komga.jooq.main.tables.records.BookMetadataAggregationAuthorRecord
|
||||
|
|
@ -18,10 +19,11 @@ import java.time.ZoneId
|
|||
|
||||
@Component
|
||||
class BookMetadataAggregationDao(
|
||||
private val dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
@param:Value("#{@komgaProperties.database.batchChunkSize}") private val batchSize: Int,
|
||||
) : BookMetadataAggregationRepository {
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
BookMetadataAggregationRepository {
|
||||
private val d = Tables.BOOK_METADATA_AGGREGATION
|
||||
private val a = Tables.BOOK_METADATA_AGGREGATION_AUTHOR
|
||||
private val t = Tables.BOOK_METADATA_AGGREGATION_TAG
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import org.gotson.komga.domain.model.Author
|
|||
import org.gotson.komga.domain.model.BookMetadata
|
||||
import org.gotson.komga.domain.model.WebLink
|
||||
import org.gotson.komga.domain.persistence.BookMetadataRepository
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.infrastructure.jooq.TempTable.Companion.withTempTable
|
||||
import org.gotson.komga.jooq.main.Tables
|
||||
import org.gotson.komga.jooq.main.tables.records.BookMetadataAuthorRecord
|
||||
|
|
@ -20,10 +21,11 @@ import java.time.ZoneId
|
|||
|
||||
@Component
|
||||
class BookMetadataDao(
|
||||
private val dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
@param:Value("#{@komgaProperties.database.batchChunkSize}") private val batchSize: Int,
|
||||
) : BookMetadataRepository {
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
BookMetadataRepository {
|
||||
private val d = Tables.BOOK_METADATA
|
||||
private val a = Tables.BOOK_METADATA_AUTHOR
|
||||
private val bt = Tables.BOOK_METADATA_TAG
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package org.gotson.komga.infrastructure.jooq.main
|
||||
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.interfaces.api.rest.dto.ClientSettingDto
|
||||
import org.gotson.komga.jooq.main.Tables
|
||||
import org.jooq.DSLContext
|
||||
|
|
@ -8,9 +9,9 @@ import org.springframework.stereotype.Component
|
|||
|
||||
@Component
|
||||
class ClientSettingsDtoDao(
|
||||
private val dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
) {
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
) : SplitDslDaoBase(dslRW, dslRO) {
|
||||
private val g = Tables.CLIENT_SETTINGS_GLOBAL
|
||||
private val u = Tables.CLIENT_SETTINGS_USER
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package org.gotson.komga.infrastructure.jooq.main
|
||||
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.infrastructure.jooq.toOrderBy
|
||||
import org.gotson.komga.interfaces.api.persistence.HistoricalEventDtoRepository
|
||||
import org.gotson.komga.interfaces.api.rest.dto.HistoricalEventDto
|
||||
|
|
@ -15,8 +16,10 @@ import org.springframework.stereotype.Component
|
|||
|
||||
@Component
|
||||
class HistoricalEventDtoDao(
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
) : HistoricalEventDtoRepository {
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
HistoricalEventDtoRepository {
|
||||
private val e = Tables.HISTORICAL_EVENT
|
||||
private val ep = Tables.HISTORICAL_EVENT_PROPERTIES
|
||||
|
||||
|
|
@ -41,6 +44,7 @@ class HistoricalEventDtoDao(
|
|||
.map { er ->
|
||||
val epr = dslRO.selectFrom(ep).where(ep.ID.eq(er.id)).fetch()
|
||||
HistoricalEventDto(
|
||||
id = er.id,
|
||||
type = er.type,
|
||||
timestamp = er.timestamp,
|
||||
bookId = er.bookId,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package org.gotson.komga.infrastructure.jooq.main
|
|||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import org.gotson.komga.domain.model.MediaExtensionEpub
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.infrastructure.jooq.deserializeMediaExtension
|
||||
import org.gotson.komga.interfaces.api.kobo.dto.ContributorDto
|
||||
import org.gotson.komga.interfaces.api.kobo.dto.KoboBookMetadataDto
|
||||
|
|
@ -16,9 +17,11 @@ import java.time.ZoneId
|
|||
|
||||
@Component
|
||||
class KoboDtoDao(
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
private val mapper: ObjectMapper,
|
||||
) : KoboDtoRepository {
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
KoboDtoRepository {
|
||||
private val b = Tables.BOOK
|
||||
private val m = Tables.MEDIA
|
||||
private val d = Tables.BOOK_METADATA
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import org.gotson.komga.domain.model.ContentRestrictions
|
|||
import org.gotson.komga.domain.model.KomgaUser
|
||||
import org.gotson.komga.domain.model.UserRoles
|
||||
import org.gotson.komga.domain.persistence.KomgaUserRepository
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.jooq.main.Tables
|
||||
import org.gotson.komga.jooq.main.tables.records.UserApiKeyRecord
|
||||
import org.gotson.komga.language.toCurrentTimeZone
|
||||
|
|
@ -21,9 +22,10 @@ import java.time.ZoneId
|
|||
|
||||
@Component
|
||||
class KomgaUserDao(
|
||||
private val dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
) : KomgaUserRepository {
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
KomgaUserRepository {
|
||||
private val u = Tables.USER
|
||||
private val ur = Tables.USER_ROLE
|
||||
private val ul = Tables.USER_LIBRARY_SHARING
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ package org.gotson.komga.infrastructure.jooq.main
|
|||
|
||||
import org.gotson.komga.domain.model.Library
|
||||
import org.gotson.komga.domain.persistence.LibraryRepository
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.jooq.main.Tables
|
||||
import org.gotson.komga.jooq.main.tables.records.LibraryRecord
|
||||
import org.gotson.komga.language.toCurrentTimeZone
|
||||
|
|
@ -17,9 +18,10 @@ import java.time.ZoneId
|
|||
|
||||
@Component
|
||||
class LibraryDao(
|
||||
private val dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
) : LibraryRepository {
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
LibraryRepository {
|
||||
private val l = Tables.LIBRARY
|
||||
private val ul = Tables.USER_LIBRARY_SHARING
|
||||
private val le = Tables.LIBRARY_EXCLUSIONS
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import org.gotson.komga.domain.model.MediaExtension
|
|||
import org.gotson.komga.domain.model.MediaFile
|
||||
import org.gotson.komga.domain.model.ProxyExtension
|
||||
import org.gotson.komga.domain.persistence.MediaRepository
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.infrastructure.jooq.TempTable.Companion.withTempTable
|
||||
import org.gotson.komga.infrastructure.jooq.deserializeMediaExtension
|
||||
import org.gotson.komga.infrastructure.jooq.serializeJsonGz
|
||||
|
|
@ -27,11 +28,12 @@ import java.time.ZoneId
|
|||
|
||||
@Component
|
||||
class MediaDao(
|
||||
private val dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
@param:Value("#{@komgaProperties.database.batchChunkSize}") private val batchSize: Int,
|
||||
private val mapper: ObjectMapper,
|
||||
) : MediaRepository {
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
MediaRepository {
|
||||
private val m = Tables.MEDIA
|
||||
private val p = Tables.MEDIA_PAGE
|
||||
private val f = Tables.MEDIA_FILE
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import org.gotson.komga.domain.model.PageHashKnown
|
|||
import org.gotson.komga.domain.model.PageHashMatch
|
||||
import org.gotson.komga.domain.model.PageHashUnknown
|
||||
import org.gotson.komga.domain.persistence.PageHashRepository
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.infrastructure.jooq.toOrderBy
|
||||
import org.gotson.komga.jooq.main.Tables
|
||||
import org.gotson.komga.jooq.main.tables.records.PageHashRecord
|
||||
|
|
@ -25,9 +26,10 @@ import java.time.ZoneId
|
|||
|
||||
@Component
|
||||
class PageHashDao(
|
||||
private val dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
) : PageHashRepository {
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
PageHashRepository {
|
||||
private val p = Tables.MEDIA_PAGE
|
||||
private val b = Tables.BOOK
|
||||
private val ph = Tables.PAGE_HASH
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import org.gotson.komga.domain.model.ContentRestrictions
|
|||
import org.gotson.komga.domain.model.ReadList
|
||||
import org.gotson.komga.domain.persistence.ReadListRepository
|
||||
import org.gotson.komga.infrastructure.datasource.SqliteUdfDataSource
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.infrastructure.jooq.TempTable.Companion.withTempTable
|
||||
import org.gotson.komga.infrastructure.jooq.inOrNoCondition
|
||||
import org.gotson.komga.infrastructure.jooq.sortByValues
|
||||
|
|
@ -32,11 +33,12 @@ import java.util.SortedMap
|
|||
|
||||
@Component
|
||||
class ReadListDao(
|
||||
private val dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
private val luceneHelper: LuceneHelper,
|
||||
@param:Value("#{@komgaProperties.database.batchChunkSize}") private val batchSize: Int,
|
||||
) : ReadListRepository {
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
ReadListRepository {
|
||||
private val rl = Tables.READLIST
|
||||
private val rlb = Tables.READLIST_BOOK
|
||||
private val b = Tables.BOOK
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import org.gotson.komga.domain.model.ReadListRequestBookMatchBook
|
|||
import org.gotson.komga.domain.model.ReadListRequestBookMatchSeries
|
||||
import org.gotson.komga.domain.model.ReadListRequestBookMatches
|
||||
import org.gotson.komga.domain.persistence.ReadListRequestRepository
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.infrastructure.jooq.noCase
|
||||
import org.gotson.komga.jooq.main.Tables
|
||||
import org.jooq.DSLContext
|
||||
|
|
@ -18,8 +19,10 @@ import java.time.LocalDate
|
|||
|
||||
@Component
|
||||
class ReadListRequestDao(
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
) : ReadListRequestRepository {
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
ReadListRequestRepository {
|
||||
private val sd = Tables.SERIES_METADATA
|
||||
private val b = Tables.BOOK
|
||||
private val bd = Tables.BOOK_METADATA
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper
|
|||
import org.gotson.komga.domain.model.R2Locator
|
||||
import org.gotson.komga.domain.model.ReadProgress
|
||||
import org.gotson.komga.domain.persistence.ReadProgressRepository
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.infrastructure.jooq.TempTable
|
||||
import org.gotson.komga.infrastructure.jooq.TempTable.Companion.withTempTable
|
||||
import org.gotson.komga.infrastructure.jooq.deserializeJsonGz
|
||||
|
|
@ -24,11 +25,12 @@ import java.time.ZoneId
|
|||
|
||||
@Component
|
||||
class ReadProgressDao(
|
||||
private val dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
@param:Value("#{@komgaProperties.database.batchChunkSize}") private val batchSize: Int,
|
||||
private val mapper: ObjectMapper,
|
||||
) : ReadProgressRepository {
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
ReadProgressRepository {
|
||||
private val r = Tables.READ_PROGRESS
|
||||
private val rs = Tables.READ_PROGRESS_SERIES
|
||||
private val b = Tables.BOOK
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package org.gotson.komga.infrastructure.jooq.main
|
||||
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.interfaces.api.persistence.ReadProgressDtoRepository
|
||||
import org.gotson.komga.interfaces.api.rest.dto.TachiyomiReadProgressDto
|
||||
import org.gotson.komga.interfaces.api.rest.dto.TachiyomiReadProgressV2Dto
|
||||
|
|
@ -16,8 +17,10 @@ import java.math.BigDecimal
|
|||
|
||||
@Component
|
||||
class ReadProgressDtoDao(
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
) : ReadProgressDtoRepository {
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
ReadProgressDtoRepository {
|
||||
private val rlb = Tables.READLIST_BOOK
|
||||
private val b = Tables.BOOK
|
||||
private val d = Tables.BOOK_METADATA
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package org.gotson.komga.infrastructure.jooq.main
|
|||
import org.gotson.komga.domain.model.Author
|
||||
import org.gotson.komga.domain.persistence.ReferentialRepository
|
||||
import org.gotson.komga.infrastructure.datasource.SqliteUdfDataSource
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.infrastructure.jooq.udfStripAccents
|
||||
import org.gotson.komga.jooq.main.Tables
|
||||
import org.gotson.komga.jooq.main.tables.records.BookMetadataAggregationAuthorRecord
|
||||
|
|
@ -22,8 +23,10 @@ import java.time.LocalDate
|
|||
|
||||
@Component
|
||||
class ReferentialDao(
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
) : ReferentialRepository {
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
ReferentialRepository {
|
||||
private val a = Tables.BOOK_METADATA_AUTHOR
|
||||
private val sd = Tables.SERIES_METADATA
|
||||
private val bma = Tables.BOOK_METADATA_AGGREGATION
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import org.gotson.komga.domain.model.ContentRestrictions
|
|||
import org.gotson.komga.domain.model.SeriesCollection
|
||||
import org.gotson.komga.domain.persistence.SeriesCollectionRepository
|
||||
import org.gotson.komga.infrastructure.datasource.SqliteUdfDataSource
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.infrastructure.jooq.TempTable.Companion.withTempTable
|
||||
import org.gotson.komga.infrastructure.jooq.inOrNoCondition
|
||||
import org.gotson.komga.infrastructure.jooq.sortByValues
|
||||
|
|
@ -31,11 +32,12 @@ import java.time.ZoneId
|
|||
|
||||
@Component
|
||||
class SeriesCollectionDao(
|
||||
private val dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
private val luceneHelper: LuceneHelper,
|
||||
@param:Value("#{@komgaProperties.database.batchChunkSize}") private val batchSize: Int,
|
||||
) : SeriesCollectionRepository {
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
SeriesCollectionRepository {
|
||||
private val c = Tables.COLLECTION
|
||||
private val cs = Tables.COLLECTION_SERIES
|
||||
private val s = Tables.SERIES
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import org.gotson.komga.domain.model.Series
|
|||
import org.gotson.komga.domain.persistence.SeriesRepository
|
||||
import org.gotson.komga.infrastructure.jooq.RequiredJoin
|
||||
import org.gotson.komga.infrastructure.jooq.SeriesSearchHelper
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.infrastructure.jooq.TempTable.Companion.withTempTable
|
||||
import org.gotson.komga.infrastructure.jooq.csAlias
|
||||
import org.gotson.komga.jooq.main.Tables
|
||||
|
|
@ -28,10 +29,11 @@ import java.time.ZoneId
|
|||
|
||||
@Component
|
||||
class SeriesDao(
|
||||
private val dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
@param:Value("#{@komgaProperties.database.batchChunkSize}") private val batchSize: Int,
|
||||
) : SeriesRepository {
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
SeriesRepository {
|
||||
private val s = Tables.SERIES
|
||||
private val d = Tables.SERIES_METADATA
|
||||
private val rs = Tables.READ_PROGRESS_SERIES
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import org.gotson.komga.domain.model.SeriesSearch
|
|||
import org.gotson.komga.infrastructure.datasource.SqliteUdfDataSource
|
||||
import org.gotson.komga.infrastructure.jooq.RequiredJoin
|
||||
import org.gotson.komga.infrastructure.jooq.SeriesSearchHelper
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.infrastructure.jooq.TempTable.Companion.withTempTable
|
||||
import org.gotson.komga.infrastructure.jooq.csAlias
|
||||
import org.gotson.komga.infrastructure.jooq.inOrNoCondition
|
||||
|
|
@ -52,10 +53,12 @@ const val BOOKS_READ_COUNT = "booksReadCount"
|
|||
|
||||
@Component
|
||||
class SeriesDtoDao(
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
private val luceneHelper: LuceneHelper,
|
||||
@param:Value("#{@komgaProperties.database.batchChunkSize}") private val batchSize: Int,
|
||||
) : SeriesDtoRepository {
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
SeriesDtoRepository {
|
||||
private val s = Tables.SERIES
|
||||
private val d = Tables.SERIES_METADATA
|
||||
private val rs = Tables.READ_PROGRESS_SERIES
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import org.gotson.komga.domain.model.AlternateTitle
|
|||
import org.gotson.komga.domain.model.SeriesMetadata
|
||||
import org.gotson.komga.domain.model.WebLink
|
||||
import org.gotson.komga.domain.persistence.SeriesMetadataRepository
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.infrastructure.jooq.TempTable.Companion.withTempTable
|
||||
import org.gotson.komga.jooq.main.Tables
|
||||
import org.gotson.komga.jooq.main.tables.records.SeriesMetadataRecord
|
||||
|
|
@ -19,10 +20,11 @@ import java.time.ZoneId
|
|||
|
||||
@Component
|
||||
class SeriesMetadataDao(
|
||||
private val dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
@param:Value("#{@komgaProperties.database.batchChunkSize}") private val batchSize: Int,
|
||||
) : SeriesMetadataRepository {
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
SeriesMetadataRepository {
|
||||
private val d = Tables.SERIES_METADATA
|
||||
private val g = Tables.SERIES_METADATA_GENRE
|
||||
private val st = Tables.SERIES_METADATA_TAG
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package org.gotson.komga.infrastructure.jooq.main
|
||||
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.jooq.main.Tables
|
||||
import org.jooq.DSLContext
|
||||
import org.springframework.beans.factory.annotation.Qualifier
|
||||
|
|
@ -7,9 +8,9 @@ import org.springframework.stereotype.Component
|
|||
|
||||
@Component
|
||||
class ServerSettingsDao(
|
||||
private val dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
) {
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
) : SplitDslDaoBase(dslRW, dslRO) {
|
||||
private val s = Tables.SERVER_SETTINGS
|
||||
|
||||
fun <T> getSettingByKey(
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package org.gotson.komga.infrastructure.jooq.main
|
|||
import org.gotson.komga.domain.model.Sidecar
|
||||
import org.gotson.komga.domain.model.SidecarStored
|
||||
import org.gotson.komga.domain.persistence.SidecarRepository
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.infrastructure.jooq.TempTable.Companion.withTempTable
|
||||
import org.gotson.komga.jooq.main.Tables
|
||||
import org.gotson.komga.jooq.main.tables.records.SidecarRecord
|
||||
|
|
@ -16,10 +17,11 @@ import java.net.URL
|
|||
|
||||
@Component
|
||||
class SidecarDao(
|
||||
private val dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
@param:Value("#{@komgaProperties.database.batchChunkSize}") private val batchSize: Int,
|
||||
) : SidecarRepository {
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
SidecarRepository {
|
||||
private val sc = Tables.SIDECAR
|
||||
|
||||
override fun findAll(): Collection<SidecarStored> = dslRO.selectFrom(sc).fetch().map { it.toDomain() }
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ import org.gotson.komga.domain.model.SyncPoint.ReadList.Companion.ON_DECK_ID
|
|||
import org.gotson.komga.domain.persistence.SyncPointRepository
|
||||
import org.gotson.komga.infrastructure.jooq.BookSearchHelper
|
||||
import org.gotson.komga.infrastructure.jooq.RequiredJoin
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.jooq.main.Tables
|
||||
import org.gotson.komga.language.toZonedDateTime
|
||||
import org.jooq.DSLContext
|
||||
|
|
@ -28,10 +29,11 @@ import java.time.ZoneId
|
|||
|
||||
@Component
|
||||
class SyncPointDao(
|
||||
private val dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
private val bookCommonDao: BookCommonDao,
|
||||
) : SyncPointRepository {
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
SyncPointRepository {
|
||||
private val b = Tables.BOOK
|
||||
private val m = Tables.MEDIA
|
||||
private val d = Tables.BOOK_METADATA
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package org.gotson.komga.infrastructure.jooq.main
|
|||
import org.gotson.komga.domain.model.Dimension
|
||||
import org.gotson.komga.domain.model.ThumbnailBook
|
||||
import org.gotson.komga.domain.persistence.ThumbnailBookRepository
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.infrastructure.jooq.TempTable.Companion.withTempTable
|
||||
import org.gotson.komga.jooq.main.Tables
|
||||
import org.gotson.komga.jooq.main.tables.records.ThumbnailBookRecord
|
||||
|
|
@ -15,10 +16,11 @@ import java.net.URL
|
|||
|
||||
@Component
|
||||
class ThumbnailBookDao(
|
||||
private val dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
@param:Value("#{@komgaProperties.database.batchChunkSize}") private val batchSize: Int,
|
||||
) : ThumbnailBookRepository {
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
ThumbnailBookRepository {
|
||||
private val tb = Tables.THUMBNAIL_BOOK
|
||||
|
||||
override fun findAllByBookId(bookId: String): Collection<ThumbnailBook> =
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package org.gotson.komga.infrastructure.jooq.main
|
|||
import org.gotson.komga.domain.model.Dimension
|
||||
import org.gotson.komga.domain.model.ThumbnailReadList
|
||||
import org.gotson.komga.domain.persistence.ThumbnailReadListRepository
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.jooq.main.Tables
|
||||
import org.gotson.komga.jooq.main.tables.records.ThumbnailReadlistRecord
|
||||
import org.jooq.DSLContext
|
||||
|
|
@ -12,9 +13,10 @@ import org.springframework.transaction.annotation.Transactional
|
|||
|
||||
@Component
|
||||
class ThumbnailReadListDao(
|
||||
private val dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
) : ThumbnailReadListRepository {
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
ThumbnailReadListRepository {
|
||||
private val tr = Tables.THUMBNAIL_READLIST
|
||||
|
||||
override fun findAllByReadListId(readListId: String): Collection<ThumbnailReadList> =
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package org.gotson.komga.infrastructure.jooq.main
|
|||
import org.gotson.komga.domain.model.Dimension
|
||||
import org.gotson.komga.domain.model.ThumbnailSeriesCollection
|
||||
import org.gotson.komga.domain.persistence.ThumbnailSeriesCollectionRepository
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.jooq.main.Tables
|
||||
import org.gotson.komga.jooq.main.tables.records.ThumbnailCollectionRecord
|
||||
import org.jooq.DSLContext
|
||||
|
|
@ -12,9 +13,10 @@ import org.springframework.transaction.annotation.Transactional
|
|||
|
||||
@Component
|
||||
class ThumbnailSeriesCollectionDao(
|
||||
private val dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
) : ThumbnailSeriesCollectionRepository {
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
ThumbnailSeriesCollectionRepository {
|
||||
private val tc = Tables.THUMBNAIL_COLLECTION
|
||||
|
||||
override fun findByIdOrNull(thumbnailId: String): ThumbnailSeriesCollection? =
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package org.gotson.komga.infrastructure.jooq.main
|
|||
import org.gotson.komga.domain.model.Dimension
|
||||
import org.gotson.komga.domain.model.ThumbnailSeries
|
||||
import org.gotson.komga.domain.persistence.ThumbnailSeriesRepository
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.infrastructure.jooq.TempTable.Companion.withTempTable
|
||||
import org.gotson.komga.jooq.main.Tables
|
||||
import org.gotson.komga.jooq.main.tables.records.ThumbnailSeriesRecord
|
||||
|
|
@ -15,10 +16,11 @@ import java.net.URL
|
|||
|
||||
@Component
|
||||
class ThumbnailSeriesDao(
|
||||
private val dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") private val dslRO: DSLContext,
|
||||
dslRW: DSLContext,
|
||||
@Qualifier("dslContextRO") dslRO: DSLContext,
|
||||
@param:Value("#{@komgaProperties.database.batchChunkSize}") private val batchSize: Int,
|
||||
) : ThumbnailSeriesRepository {
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
ThumbnailSeriesRepository {
|
||||
private val ts = Tables.THUMBNAIL_SERIES
|
||||
|
||||
override fun findByIdOrNull(thumbnailId: String): ThumbnailSeries? =
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper
|
|||
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||
import org.gotson.komga.application.tasks.Task
|
||||
import org.gotson.komga.application.tasks.TasksRepository
|
||||
import org.gotson.komga.infrastructure.jooq.SplitDslDaoBase
|
||||
import org.gotson.komga.jooq.tasks.Tables
|
||||
import org.jooq.DSLContext
|
||||
import org.jooq.Query
|
||||
|
|
@ -22,11 +23,12 @@ private val logger = KotlinLogging.logger {}
|
|||
@Component
|
||||
@DependsOn("flywaySecondaryMigrationInitializer")
|
||||
class TasksDao(
|
||||
@Qualifier("tasksDslContextRW") private val dslRW: DSLContext,
|
||||
@Qualifier("tasksDslContextRO") private val dslRO: DSLContext,
|
||||
@Qualifier("tasksDslContextRW") dslRW: DSLContext,
|
||||
@Qualifier("tasksDslContextRO") dslRO: DSLContext,
|
||||
@param:Value("#{@komgaProperties.tasksDb.batchChunkSize}") private val batchSize: Int,
|
||||
private val objectMapper: ObjectMapper,
|
||||
) : TasksRepository {
|
||||
) : SplitDslDaoBase(dslRW, dslRO),
|
||||
TasksRepository {
|
||||
private val t = Tables.TASK
|
||||
|
||||
private val tasksAvailableCondition =
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import org.springframework.util.LinkedMultiValueMap
|
|||
import org.springframework.web.client.RestClient
|
||||
import org.springframework.web.client.toEntity
|
||||
import org.springframework.web.server.ResponseStatusException
|
||||
import org.springframework.web.util.DefaultUriBuilderFactory
|
||||
import kotlin.time.Duration.Companion.minutes
|
||||
import kotlin.time.toJavaDuration
|
||||
|
||||
|
|
@ -29,11 +30,15 @@ class KoboProxy(
|
|||
private val komgaSyncTokenGenerator: KomgaSyncTokenGenerator,
|
||||
private val komgaSettingsProvider: KomgaSettingsProvider,
|
||||
) {
|
||||
private val koboApiClient =
|
||||
private val koboApiClient: RestClient =
|
||||
RestClient
|
||||
.builder()
|
||||
.baseUrl("https://storeapi.kobo.com")
|
||||
.requestFactory(
|
||||
.uriBuilderFactory(
|
||||
DefaultUriBuilderFactory("https://storeapi.kobo.com")
|
||||
.apply {
|
||||
this.encodingMode = DefaultUriBuilderFactory.EncodingMode.NONE
|
||||
},
|
||||
).requestFactory(
|
||||
ClientHttpRequestFactoryBuilder.reactor().build(
|
||||
ClientHttpRequestFactorySettings
|
||||
.defaults()
|
||||
|
|
@ -42,7 +47,7 @@ class KoboProxy(
|
|||
),
|
||||
).build()
|
||||
|
||||
private val pathRegex = """\/kobo\/[-\w]*(.*)""".toRegex()
|
||||
private val pathRegex = """/kobo/[-\w]*(.*)""".toRegex()
|
||||
|
||||
private val headersOutInclude =
|
||||
setOf(
|
||||
|
|
@ -50,6 +55,7 @@ class KoboProxy(
|
|||
HttpHeaders.USER_AGENT,
|
||||
HttpHeaders.ACCEPT,
|
||||
HttpHeaders.ACCEPT_LANGUAGE,
|
||||
HttpHeaders.CONTENT_TYPE,
|
||||
)
|
||||
|
||||
private val headersOutExclude =
|
||||
|
|
@ -88,7 +94,7 @@ class KoboProxy(
|
|||
.uri { uriBuilder ->
|
||||
uriBuilder
|
||||
.path(path)
|
||||
.queryParams(LinkedMultiValueMap(request.parameterMap.mapValues { it.value.toList() }))
|
||||
.query(request.queryString)
|
||||
.build()
|
||||
.also { logger.debug { "Proxy URL: $it" } }
|
||||
}.headers { headersOut ->
|
||||
|
|
@ -110,6 +116,7 @@ class KoboProxy(
|
|||
}.apply { if (body != null) body(body) }
|
||||
.retrieve()
|
||||
.onStatus(HttpStatusCode::isError) { _, response ->
|
||||
logger.debug { "Kobo response: ${response.statusCode}: ${response.body.bufferedReader().use { it.readText() }}" }
|
||||
throw ResponseStatusException(response.statusCode, response.statusText)
|
||||
}.toEntity<JsonNode>()
|
||||
|
||||
|
|
@ -161,6 +168,7 @@ class KoboProxy(
|
|||
"audiobook_subscription_tiers": "https://www.kobo.com/{region}/{language}/checkoutoption/21C6D938-934B-4A91-B979-E14D70B2F280",
|
||||
"authorproduct_recommendations": "https://storeapi.kobo.com/v1/products/books/authors/recommendations",
|
||||
"autocomplete": "https://storeapi.kobo.com/v1/products/autocomplete",
|
||||
"bam": "https://storeapi.kobo.com/v2/activity/bam/success",
|
||||
"blackstone_header": {
|
||||
"key": "x-amz-request-payer",
|
||||
"value": "requester"
|
||||
|
|
@ -173,6 +181,7 @@ class KoboProxy(
|
|||
"browse_history": "https://storeapi.kobo.com/v1/user/browsehistory",
|
||||
"categories": "https://storeapi.kobo.com/v1/categories",
|
||||
"categories_page": "https://www.kobo.com/ebooks/categories",
|
||||
"categoriesv2": "https://storeapi.kobo.com/api/v2/Categories/Top",
|
||||
"category": "https://storeapi.kobo.com/v1/categories/{CategoryId}",
|
||||
"category_featured_lists": "https://storeapi.kobo.com/v1/categories/{CategoryId}/featured",
|
||||
"category_products": "https://storeapi.kobo.com/v1/categories/{CategoryId}/products",
|
||||
|
|
@ -180,6 +189,7 @@ class KoboProxy(
|
|||
"client_authd_referral": "https://authorize.kobo.com/api/AuthenticatedReferral/client/v1/getLink",
|
||||
"configuration_data": "https://storeapi.kobo.com/v1/configuration",
|
||||
"content_access_book": "https://storeapi.kobo.com/v1/products/books/{ProductId}/access",
|
||||
"contributorsv2": "https://storeapi.kobo.com/v2/contributors/author",
|
||||
"customer_care_live_chat": "https://v2.zopim.com/widget/livechat.html?key=Y6gwUmnu4OATxN3Tli4Av9bYN319BTdO",
|
||||
"daily_deal": "https://storeapi.kobo.com/v1/products/dailydeal",
|
||||
"deals": "https://storeapi.kobo.com/v1/deals",
|
||||
|
|
@ -190,14 +200,19 @@ class KoboProxy(
|
|||
"device_refresh": "https://storeapi.kobo.com/v1/auth/refresh",
|
||||
"dictionary_host": "https://ereaderfiles.kobo.com",
|
||||
"discovery_host": "https://discovery.kobobooks.com",
|
||||
"display_accessibility_enabled": "False",
|
||||
"display_parental_controls_enabled": "True",
|
||||
"dropbox_link_account_poll": "https://authorize.kobo.com/{region}/{language}/LinkDropbox",
|
||||
"dropbox_link_account_start": "https://authorize.kobo.com/LinkDropbox/start",
|
||||
"ereaderdevices": "https://storeapi.kobo.com/v2/products/EReaderDeviceFeeds",
|
||||
"eula_page": "https://www.kobo.com/termsofuse?style=onestore",
|
||||
"exchange_auth": "https://storeapi.kobo.com/v1/auth/exchange",
|
||||
"external_book": "https://storeapi.kobo.com/v1/products/books/external/{Ids}",
|
||||
"facebook_sso_page": "https://authorize.kobo.com/signin/provider/Facebook/login?returnUrl=http://kobo.com/",
|
||||
"facebook_sso_page": "https://authorize.kobo.com/signin/provider/Facebook/login?returnUrl=https://kobo.com/",
|
||||
"featured_list": "https://storeapi.kobo.com/v1/products/featured/{FeaturedListId}",
|
||||
"featured_lists": "https://storeapi.kobo.com/v1/products/featured",
|
||||
"featuredlist2": "https://storeapi.kobo.com/v2/products/list/featured",
|
||||
"fixed_layout_page_cache_enabled": "True",
|
||||
"free_books_page": {
|
||||
"EN": "https://www.kobo.com/{region}/{language}/p/free-ebooks",
|
||||
"FR": "https://www.kobo.com/{region}/{language}/p/livres-gratuits",
|
||||
|
|
@ -207,6 +222,7 @@ class KoboProxy(
|
|||
},
|
||||
"fte_feedback": "https://storeapi.kobo.com/v1/products/ftefeedback",
|
||||
"funnel_metrics": "https://storeapi.kobo.com/v1/funnelmetrics",
|
||||
"geography_data": "https://storeapi.kobo.com/v2/configuration/geography/country",
|
||||
"get_download_keys": "https://storeapi.kobo.com/v1/library/downloadkeys",
|
||||
"get_download_link": "https://storeapi.kobo.com/v1/library/downloadlink",
|
||||
"get_tests_request": "https://storeapi.kobo.com/v1/analytics/gettests",
|
||||
|
|
@ -214,10 +230,13 @@ class KoboProxy(
|
|||
"giftcard_redeem_url": "https://www.kobo.com/{storefront}/{language}/redeem",
|
||||
"googledrive_link_account_start": "https://authorize.kobo.com/{region}/{language}/linkcloudstorage/provider/google_drive",
|
||||
"gpb_flow_enabled": "False",
|
||||
"help_page": "http://www.kobo.com/help",
|
||||
"help_page": "https://www.kobo.com/help",
|
||||
"image_host": "//cdn.kobo.com/book-images/",
|
||||
"image_url_quality_template": "https://cdn.kobo.com/book-images/{ImageId}/{Width}/{Height}/{Quality}/{IsGreyscale}/image.jpg",
|
||||
"image_url_template": "https://cdn.kobo.com/book-images/{ImageId}/{Width}/{Height}/false/image.jpg",
|
||||
"instapaper_enabled": "True",
|
||||
"instapaper_env_url": "https://www.instapaper.com/api/kobo",
|
||||
"instapaper_link_account_start": "https://authorize.kobo.com/{region}/{language}/linkinstapaper",
|
||||
"kobo_audiobooks_credit_redemption": "True",
|
||||
"kobo_audiobooks_enabled": "True",
|
||||
"kobo_audiobooks_orange_deal_enabled": "True",
|
||||
|
|
@ -244,7 +263,8 @@ class KoboProxy(
|
|||
"love_dashboard_page": "https://www.kobo.com/{region}/{language}/kobosuperpoints",
|
||||
"love_points_redemption_page": "https://www.kobo.com/{region}/{language}/KoboSuperPointsRedemption?productId={ProductId}",
|
||||
"magazine_landing_page": "https://www.kobo.com/emagazines",
|
||||
"more_sign_in_options": "https://authorize.kobo.com/signin?returnUrl=http://kobo.com/#allProviders",
|
||||
"more_sign_in_options": "https://authorize.kobo.com/signin?returnUrl=https://kobo.com/#allProviders",
|
||||
"morebyauthor": "https://storeapi.kobo.com/v2/products/recommendations/morebyauthor",
|
||||
"notebooks": "https://storeapi.kobo.com/api/internal/notebooks",
|
||||
"notifications_registration_issue": "https://storeapi.kobo.com/v1/notifications/registration",
|
||||
"oauth_host": "https://oauth.kobo.com",
|
||||
|
|
@ -258,9 +278,13 @@ class KoboProxy(
|
|||
"product_prices": "https://storeapi.kobo.com/v1/products/{ProductIds}/prices",
|
||||
"product_recommendations": "https://storeapi.kobo.com/v1/products/{ProductId}/recommendations",
|
||||
"product_reviews": "https://storeapi.kobo.com/v1/products/{ProductIds}/reviews",
|
||||
"productbyid": "https://storeapi.kobo.com/v2/products/itemDetailById/{ProductType}/{Id}",
|
||||
"productbyslug": "https://storeapi.kobo.com/v2/products/itemDetail/{ProductType}/{Slug}",
|
||||
"products": "https://storeapi.kobo.com/v1/products",
|
||||
"productstatebyid": "https://storeapi.kobo.com/v2/products/itemStateById/{ProductType}/{Id}",
|
||||
"productstatebyslug": "https://storeapi.kobo.com/v2/products/itemState/{ProductType}/{Slug}",
|
||||
"productsv2": "https://storeapi.kobo.com/v2/products",
|
||||
"provider_external_sign_in_page": "https://authorize.kobo.com/ExternalSignIn/{providerName}?returnUrl=http://kobo.com/",
|
||||
"provider_external_sign_in_page": "https://authorize.kobo.com/ExternalSignIn/{providerName}?returnUrl=https://kobo.com/",
|
||||
"purchase_buy": "https://www.kobo.com/checkoutoption/",
|
||||
"purchase_buy_templated": "https://www.kobo.com/{region}/{language}/checkoutoption/{ProductId}",
|
||||
"quickbuy_checkout": "https://storeapi.kobo.com/v1/store/quickbuy/{PurchaseId}/checkout",
|
||||
|
|
@ -270,7 +294,9 @@ class KoboProxy(
|
|||
"reading_services_host": "https://readingservices.kobo.com",
|
||||
"reading_state": "https://storeapi.kobo.com/v1/library/{Ids}/state",
|
||||
"redeem_interstitial_page": "https://www.kobo.com",
|
||||
"registration_page": "https://authorize.kobo.com/signup?returnUrl=http://kobo.com/",
|
||||
"reflowable_page_cache_enabled": "True",
|
||||
"registration_page": "https://authorize.kobo.com/signup?returnUrl=https://kobo.com/",
|
||||
"related": "https://storeapi.kobo.com/v2/products/recommendations/related",
|
||||
"related_items": "https://storeapi.kobo.com/v1/products/{Id}/related",
|
||||
"remaining_book_series": "https://storeapi.kobo.com/v1/products/books/series/{SeriesId}",
|
||||
"rename_tag": "https://storeapi.kobo.com/v1/library/tags/{TagId}",
|
||||
|
|
@ -293,14 +319,19 @@ class KoboProxy(
|
|||
"tags": "https://storeapi.kobo.com/v1/library/tags",
|
||||
"taste_profile": "https://storeapi.kobo.com/v1/products/tasteprofile",
|
||||
"terms_of_sale_page": "https://authorize.kobo.com/{region}/{language}/terms/termsofsale",
|
||||
"topproducts": "https://storeapi.kobo.com/v2/products/list/topproducts",
|
||||
"tracking": "https://storeapi.kobo.com/v2/tracking/searchperformed",
|
||||
"update_accessibility_to_preview": "https://storeapi.kobo.com/v1/library/{EntitlementIds}/preview",
|
||||
"use_one_store": "True",
|
||||
"user_currencyconversion": "https://storeapi.kobo.com/v1/user/currency/convert",
|
||||
"user_loyalty_benefits": "https://storeapi.kobo.com/v1/user/loyalty/benefits",
|
||||
"user_platform": "https://storeapi.kobo.com/v1/user/platform",
|
||||
"user_profile": "https://storeapi.kobo.com/v1/user/profile",
|
||||
"user_ratings": "https://storeapi.kobo.com/v1/user/ratings",
|
||||
"user_recommendations": "https://storeapi.kobo.com/v1/user/recommendations",
|
||||
"user_reviews": "https://storeapi.kobo.com/v1/user/reviews",
|
||||
"user_tasteprofile_complete": "https://storeapi.kobo.com/v2/user/tasteprofile/complete",
|
||||
"user_tasteprofile_genre": "https://storeapi.kobo.com/v2/user/tasteprofile/genre",
|
||||
"user_wishlist": "https://storeapi.kobo.com/v1/user/wishlist",
|
||||
"userguide_host": "https://ereaderfiles.kobo.com",
|
||||
"wishlist_page": "https://www.kobo.com/{region}/{language}/account/wishlist"
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ inline fun <R> Path.epub(block: (EpubPackage) -> R): R =
|
|||
*/
|
||||
fun ZipFile.getPackagePath(): String =
|
||||
getEntryInputStream("META-INF/container.xml")
|
||||
?.use { Jsoup.parse(it, null, "") }
|
||||
?.use { Jsoup.parse(it, null, "", Parser.xmlParser()) }
|
||||
?.getElementsByTag("rootfile")
|
||||
?.first()
|
||||
?.attr("full-path") ?: throw MediaUnsupportedException("META-INF/container.xml does not contain rootfile tag")
|
||||
|
|
|
|||
|
|
@ -60,14 +60,14 @@ class EpubExtractor(
|
|||
manifest.values.firstOrNull { it.properties.contains("cover-image") }
|
||||
?: // EPUB 2 - get cover from meta element with name="cover"
|
||||
opfDoc
|
||||
.selectFirst("metadata > meta[name=cover]")
|
||||
.selectFirst("*|metadata > *|meta[name=cover]")
|
||||
?.attr("content")
|
||||
?.ifBlank { null }
|
||||
?.let { manifest[it] }
|
||||
?: // try id="cover-image"
|
||||
manifest.values.firstOrNull { it.id == "cover-image" }
|
||||
if (coverManifestItem != null) {
|
||||
val href = coverManifestItem.href
|
||||
val href = URLDecoder.decode(coverManifestItem.href, Charsets.UTF_8)
|
||||
val mediaType = coverManifestItem.mediaType
|
||||
val coverPath = normalizeHref(opfDir, href)
|
||||
zip.getEntryBytes(coverPath)?.let { coverBytes ->
|
||||
|
|
@ -84,7 +84,7 @@ class EpubExtractor(
|
|||
fun getResources(epub: EpubPackage): List<MediaFile> {
|
||||
val spine =
|
||||
epub.opfDoc
|
||||
.select("spine > itemref")
|
||||
.select("*|spine > *|itemref")
|
||||
.map { it.attr("idref") }
|
||||
.mapNotNull { epub.manifest[it] }
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ class EpubExtractor(
|
|||
run {
|
||||
val spine =
|
||||
epub.opfDoc
|
||||
.select("spine > itemref")
|
||||
.select("*|spine > *|itemref")
|
||||
.map { it.attr("idref") }
|
||||
.mapNotNull { idref -> epub.manifest[idref]?.href?.let { normalizeHref(epub.opfDir, it) } }
|
||||
|
||||
|
|
@ -137,7 +137,7 @@ class EpubExtractor(
|
|||
|
||||
val pagesWithImages =
|
||||
epub.opfDoc
|
||||
.select("spine > itemref")
|
||||
.select("*|spine > *|itemref")
|
||||
.map { it.attr("idref") }
|
||||
.mapNotNull { idref -> epub.manifest[idref]?.href?.let { normalizeHref(epub.opfDir, it) } }
|
||||
.map { pagePath ->
|
||||
|
|
@ -219,7 +219,7 @@ class EpubExtractor(
|
|||
fun computePageCount(epub: EpubPackage): Int {
|
||||
val spine =
|
||||
epub.opfDoc
|
||||
.select("spine > itemref")
|
||||
.select("*|spine > *|itemref")
|
||||
.map { it.attr("idref") }
|
||||
.mapNotNull { idref -> epub.manifest[idref]?.href?.let { normalizeHref(epub.opfDir, it) } }
|
||||
|
||||
|
|
@ -230,8 +230,8 @@ class EpubExtractor(
|
|||
}
|
||||
|
||||
fun isFixedLayout(epub: EpubPackage) =
|
||||
epub.opfDoc.selectFirst("metadata > *|meta[property=rendition:layout]")?.text() == "pre-paginated" ||
|
||||
epub.opfDoc.selectFirst("metadata > *|meta[name=fixed-layout]")?.attr("content") == "true"
|
||||
epub.opfDoc.selectFirst("*|metadata > *|meta[property=rendition:layout]")?.text() == "pre-paginated" ||
|
||||
epub.opfDoc.selectFirst("*|metadata > *|meta[name=fixed-layout]")?.attr("content") == "true"
|
||||
|
||||
fun computePositions(
|
||||
epub: EpubPackage,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import org.gotson.komga.domain.model.EpubTocEntry
|
|||
import org.gotson.komga.infrastructure.util.getEntryBytes
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Element
|
||||
import org.jsoup.parser.Parser
|
||||
import java.net.URLDecoder
|
||||
import java.nio.file.Path
|
||||
import kotlin.io.path.Path
|
||||
|
|
@ -23,7 +24,7 @@ fun processNcx(
|
|||
navType: Epub2Nav,
|
||||
): List<EpubTocEntry> =
|
||||
Jsoup
|
||||
.parse(document.content)
|
||||
.parse(document.content, "", Parser.xmlParser())
|
||||
.select("${navType.level1} > ${navType.level2}")
|
||||
.toList()
|
||||
.mapNotNull { ncxElementToTocEntry(navType, it, document.path.parent) }
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import java.nio.file.Paths
|
|||
import kotlin.io.path.invariantSeparatorsPathString
|
||||
|
||||
fun Document.getManifest() =
|
||||
select("manifest > item").associate {
|
||||
select("*|manifest > *|item").associate {
|
||||
it.attr("id") to
|
||||
ManifestItem(
|
||||
it.attr("id"),
|
||||
|
|
@ -36,8 +36,8 @@ fun processOpfGuide(
|
|||
opf: Document,
|
||||
opfDir: Path?,
|
||||
): List<EpubTocEntry> {
|
||||
val guide = opf.selectFirst("guide") ?: return emptyList()
|
||||
return guide.select("reference").map { ref ->
|
||||
val guide = opf.selectFirst("*|guide") ?: return emptyList()
|
||||
return guide.select("*|reference").map { ref ->
|
||||
EpubTocEntry(
|
||||
ref.attr("title"),
|
||||
ref.attr("href").ifBlank { null }?.let { normalizeHref(opfDir, URLDecoder.decode(it, Charsets.UTF_8)) },
|
||||
|
|
|
|||
|
|
@ -51,22 +51,22 @@ class EpubMetadataProvider(
|
|||
getPackageFileContent(book.book.path)?.let { packageFile ->
|
||||
val opf = Jsoup.parse(packageFile, "", Parser.xmlParser())
|
||||
|
||||
val title = opf.selectFirst("metadata > dc|title")?.text()?.ifBlank { null }
|
||||
val title = opf.selectFirst("*|metadata > *|title")?.text()?.ifBlank { null }
|
||||
val description =
|
||||
opf
|
||||
.selectFirst("metadata > dc|description")
|
||||
.selectFirst("*|metadata > *|description")
|
||||
?.text()
|
||||
?.let { Jsoup.clean(it, Safelist.none()) }
|
||||
?.ifBlank { null }
|
||||
val date = opf.selectFirst("metadata > dc|date")?.text()?.let { parseDate(it) }
|
||||
val date = opf.selectFirst("*|metadata > *|date")?.text()?.let { parseDate(it) }
|
||||
|
||||
val authorRoles =
|
||||
opf
|
||||
.select("metadata > *|meta[property=role][scheme=marc:relators]")
|
||||
.select("*|metadata > *|meta[property=role][scheme=marc:relators]")
|
||||
.associate { it.attr("refines").removePrefix("#") to it.text() }
|
||||
val authors =
|
||||
opf
|
||||
.select("metadata > dc|creator")
|
||||
.select("*|metadata > *|creator")
|
||||
.mapNotNull { el ->
|
||||
val name = el.text().trim()
|
||||
if (name.isBlank()) {
|
||||
|
|
@ -81,16 +81,16 @@ class EpubMetadataProvider(
|
|||
|
||||
val isbn =
|
||||
opf
|
||||
.select("metadata > dc|identifier")
|
||||
.select("*|metadata > *|identifier")
|
||||
.map { it.text().lowercase().removePrefix("isbn:") }
|
||||
.firstNotNullOfOrNull { isbnValidator.validate(it) }
|
||||
|
||||
val seriesIndex =
|
||||
opf
|
||||
.selectFirst("metadata > *|meta[property=belongs-to-collection]")
|
||||
.selectFirst("*|metadata > *|meta[property=belongs-to-collection]")
|
||||
?.attr("id")
|
||||
?.let { id ->
|
||||
opf.selectFirst("metadata > *|meta[refines=#$id][property=group-position]")
|
||||
opf.selectFirst("*|metadata > *|meta[refines=#$id][property=group-position]")
|
||||
}?.text()
|
||||
|
||||
return BookMetadataPatch(
|
||||
|
|
@ -116,18 +116,18 @@ class EpubMetadataProvider(
|
|||
getPackageFileContent(book.book.path)?.let { packageFile ->
|
||||
val opf = Jsoup.parse(packageFile, "", Parser.xmlParser())
|
||||
|
||||
val series = opf.selectFirst("metadata > *|meta[property=belongs-to-collection]")?.text()?.ifBlank { null }
|
||||
val publisher = opf.selectFirst("metadata > dc|publisher")?.text()?.ifBlank { null }
|
||||
val language = opf.selectFirst("metadata > dc|language")?.text()?.ifBlank { null }
|
||||
val series = opf.selectFirst("*|metadata > *|meta[property=belongs-to-collection]")?.text()?.ifBlank { null }
|
||||
val publisher = opf.selectFirst("*|metadata > *|publisher")?.text()?.ifBlank { null }
|
||||
val language = opf.selectFirst("*|metadata > *|language")?.text()?.ifBlank { null }
|
||||
val genres =
|
||||
opf
|
||||
.select("metadata > dc|subject")
|
||||
.select("*|metadata > *|subject")
|
||||
.mapNotNull { it.text().trim().ifBlank { null } }
|
||||
.toSet()
|
||||
.ifEmpty { null }
|
||||
|
||||
val direction =
|
||||
opf.getElementsByTag("spine").first()?.attr("page-progression-direction")?.let {
|
||||
opf.selectFirst("*|spine")?.attr("page-progression-direction")?.let {
|
||||
when (it) {
|
||||
"rtl" -> SeriesMetadata.ReadingDirection.RIGHT_TO_LEFT
|
||||
"ltr" -> SeriesMetadata.ReadingDirection.LEFT_TO_RIGHT
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class LocalArtworkProvider(
|
|||
private val imageAnalyzer: ImageAnalyzer,
|
||||
) : SidecarSeriesConsumer,
|
||||
SidecarBookConsumer {
|
||||
val supportedExtensions = listOf("png", "jpeg", "jpg", "tbn", "webp")
|
||||
val supportedExtensions = listOf("png", "jpeg", "jpg", "tbn", "webp", "gif")
|
||||
val supportedSeriesFiles = listOf("cover", "default", "folder", "poster", "series")
|
||||
|
||||
fun getBookThumbnails(book: Book): List<ThumbnailBook> {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package org.gotson.komga.infrastructure.security
|
|||
import jakarta.servlet.Filter
|
||||
import org.gotson.komga.domain.model.UserRoles
|
||||
import org.gotson.komga.infrastructure.configuration.KomgaSettingsProvider
|
||||
import org.gotson.komga.infrastructure.hash.Hasher
|
||||
import org.gotson.komga.infrastructure.security.apikey.ApiKeyAuthenticationFilter
|
||||
import org.gotson.komga.infrastructure.security.apikey.ApiKeyAuthenticationProvider
|
||||
import org.gotson.komga.infrastructure.security.apikey.HeaderApiKeyAuthenticationConverter
|
||||
|
|
@ -34,6 +35,7 @@ import org.springframework.security.web.authentication.AnonymousAuthenticationFi
|
|||
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource
|
||||
import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter
|
||||
import org.springframework.security.web.servlet.util.matcher.PathPatternRequestMatcher
|
||||
|
||||
@Configuration
|
||||
|
|
@ -51,6 +53,7 @@ class SecurityConfiguration(
|
|||
private val opdsAuthenticationEntryPoint: OpdsAuthenticationEntryPoint,
|
||||
private val authenticationEventPublisher: AuthenticationEventPublisher,
|
||||
private val tokenEncoder: TokenEncoder,
|
||||
private val hasher: Hasher,
|
||||
clientRegistrationRepository: InMemoryClientRegistrationRepository?,
|
||||
) {
|
||||
private val oauth2Enabled = clientRegistrationRepository != null
|
||||
|
|
@ -158,7 +161,7 @@ class SecurityConfiguration(
|
|||
)
|
||||
}
|
||||
|
||||
http.addFilterBefore(restAuthenticationFilter(), AnonymousAuthenticationFilter::class.java)
|
||||
http.addFilterAfter(restAuthenticationFilter(), BasicAuthenticationFilter::class.java)
|
||||
|
||||
return http.build()
|
||||
}
|
||||
|
|
@ -239,19 +242,19 @@ class SecurityConfiguration(
|
|||
fun koboAuthenticationFilter(): Filter =
|
||||
ApiKeyAuthenticationFilter(
|
||||
apiKeyAuthenticationProvider(),
|
||||
UriRegexApiKeyAuthenticationConverter(Regex("""/kobo/([\w-]+)"""), tokenEncoder, userAgentWebAuthenticationDetailsSource),
|
||||
UriRegexApiKeyAuthenticationConverter(Regex("""/kobo/([\w-]+)"""), hasher, tokenEncoder, userAgentWebAuthenticationDetailsSource),
|
||||
)
|
||||
|
||||
fun kosyncAuthenticationFilter(): Filter =
|
||||
ApiKeyAuthenticationFilter(
|
||||
apiKeyAuthenticationProvider(),
|
||||
HeaderApiKeyAuthenticationConverter("X-Auth-User", tokenEncoder, userAgentWebAuthenticationDetailsSource),
|
||||
HeaderApiKeyAuthenticationConverter("X-Auth-User", hasher, tokenEncoder, userAgentWebAuthenticationDetailsSource),
|
||||
)
|
||||
|
||||
fun restAuthenticationFilter(): Filter =
|
||||
ApiKeyAuthenticationFilter(
|
||||
apiKeyAuthenticationProvider(),
|
||||
HeaderApiKeyAuthenticationConverter("X-API-Key", tokenEncoder, userAgentWebAuthenticationDetailsSource),
|
||||
HeaderApiKeyAuthenticationConverter("X-API-Key", hasher, tokenEncoder, userAgentWebAuthenticationDetailsSource),
|
||||
)
|
||||
|
||||
fun apiKeyAuthenticationProvider(): AuthenticationManager =
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@ class ApiKeyAuthenticationFilter(
|
|||
} catch (ex: AuthenticationException) {
|
||||
unsuccessfulAuthentication(request, response, ex)
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response)
|
||||
}
|
||||
|
||||
private fun unsuccessfulAuthentication(
|
||||
|
|
@ -78,7 +80,6 @@ class ApiKeyAuthenticationFilter(
|
|||
}
|
||||
securityContextHolderStrategy.context = context
|
||||
securityContextRepository.saveContext(context, request, response)
|
||||
filterChain.doFilter(request, response)
|
||||
}
|
||||
|
||||
private fun authenticationIsRequired(username: String): Boolean {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package org.gotson.komga.infrastructure.security.apikey
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import org.gotson.komga.infrastructure.hash.Hasher
|
||||
import org.gotson.komga.infrastructure.security.TokenEncoder
|
||||
import org.springframework.security.authentication.AuthenticationDetailsSource
|
||||
import org.springframework.security.core.Authentication
|
||||
|
|
@ -11,11 +12,13 @@ import org.springframework.security.web.authentication.AuthenticationConverter
|
|||
* and convert it to an [ApiKeyAuthenticationToken]
|
||||
*
|
||||
* @property headerName the header name from which to retrieve the API key
|
||||
* @property hasher the hasher to use to encode the API key as username in the [Authentication] object
|
||||
* @property tokenEncoder the encoder to use to encode the API key in the [Authentication] object
|
||||
* @property authenticationDetailsSource the [AuthenticationDetailsSource] to enrich the [Authentication] details
|
||||
*/
|
||||
class HeaderApiKeyAuthenticationConverter(
|
||||
private val headerName: String,
|
||||
private val hasher: Hasher,
|
||||
private val tokenEncoder: TokenEncoder,
|
||||
private val authenticationDetailsSource: AuthenticationDetailsSource<HttpServletRequest, *>,
|
||||
) : AuthenticationConverter {
|
||||
|
|
@ -23,7 +26,8 @@ class HeaderApiKeyAuthenticationConverter(
|
|||
request
|
||||
.getHeader(headerName)
|
||||
?.let {
|
||||
val (maskedToken, hashedToken) = it.take(6) + "*".repeat(6) to tokenEncoder.encode(it)
|
||||
val maskedToken = hasher.computeHash(it)
|
||||
val hashedToken = tokenEncoder.encode(it)
|
||||
ApiKeyAuthenticationToken
|
||||
.unauthenticated(maskedToken, hashedToken)
|
||||
.apply { details = authenticationDetailsSource.buildDetails(request) }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package org.gotson.komga.infrastructure.security.apikey
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest
|
||||
import org.gotson.komga.infrastructure.hash.Hasher
|
||||
import org.gotson.komga.infrastructure.security.TokenEncoder
|
||||
import org.springframework.security.authentication.AuthenticationDetailsSource
|
||||
import org.springframework.security.core.Authentication
|
||||
|
|
@ -11,11 +12,13 @@ import org.springframework.security.web.authentication.AuthenticationConverter
|
|||
* request URI, and convert it to an [ApiKeyAuthenticationToken]
|
||||
*
|
||||
* @property tokenRegex the regex used to extract the API key
|
||||
* @property tokenEncoder the encoder to use to encode the API key in the [Authentication] object
|
||||
* @property hasher the hasher to use to encode the API key as username in the [Authentication] object
|
||||
* @property tokenEncoder the encoder to use to encode the API key as credentials in the [Authentication] object
|
||||
* @property authenticationDetailsSource the [AuthenticationDetailsSource] to enrich the [Authentication] details
|
||||
*/
|
||||
class UriRegexApiKeyAuthenticationConverter(
|
||||
private val tokenRegex: Regex,
|
||||
private val hasher: Hasher,
|
||||
private val tokenEncoder: TokenEncoder,
|
||||
private val authenticationDetailsSource: AuthenticationDetailsSource<HttpServletRequest, *>,
|
||||
) : AuthenticationConverter {
|
||||
|
|
@ -24,7 +27,8 @@ class UriRegexApiKeyAuthenticationConverter(
|
|||
?.let {
|
||||
tokenRegex.find(it)?.groupValues?.lastOrNull()
|
||||
}?.let {
|
||||
val (maskedToken, hashedToken) = it.take(6) + "*".repeat(6) to tokenEncoder.encode(it)
|
||||
val maskedToken = hasher.computeHash(it)
|
||||
val hashedToken = tokenEncoder.encode(it)
|
||||
ApiKeyAuthenticationToken
|
||||
.unauthenticated(maskedToken, hashedToken)
|
||||
.apply { details = authenticationDetailsSource.buildDetails(request) }
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ fun ResponseEntity.BodyBuilder.setCachePrivate() = this.cacheControl(cachePrivat
|
|||
val cachePrivate =
|
||||
CacheControl
|
||||
.maxAge(0, TimeUnit.SECONDS)
|
||||
.noTransform()
|
||||
.cachePrivate()
|
||||
.mustRevalidate()
|
||||
|
||||
|
|
|
|||
|
|
@ -194,6 +194,7 @@ class KoboController(
|
|||
try {
|
||||
koboProxy.proxyCurrentRequest().body?.get("Resources")
|
||||
} catch (e: Exception) {
|
||||
if (e is ResponseStatusException && e.statusCode == HttpStatus.UNAUTHORIZED) throw e
|
||||
logger.warn { "Failed to get response from Kobo /v1/initialization, fallback to noproxy" }
|
||||
null
|
||||
} ?: koboProxy.nativeKoboResources
|
||||
|
|
@ -233,7 +234,7 @@ class KoboController(
|
|||
): Any {
|
||||
try {
|
||||
return koboProxy.proxyCurrentRequest(body)
|
||||
} catch (e: Exception) {
|
||||
} catch (_: Exception) {
|
||||
logger.warn { "Failed to get response from Kobo /v1/auth/device, fallback to noproxy" }
|
||||
}
|
||||
|
||||
|
|
@ -395,7 +396,7 @@ class KoboController(
|
|||
addAll(
|
||||
// changed books are also passed as changed reading state because Kobo does not process ChangedEntitlement even if it contains a ReadingState
|
||||
(booksChanged.content + changedReadingState.content).mapNotNull { book ->
|
||||
readProgress[book.bookId]?.let { it ->
|
||||
readProgress[book.bookId]?.let {
|
||||
ChangedReadingStateDto(
|
||||
WrappedReadingStateDto(
|
||||
it.toDto(),
|
||||
|
|
@ -570,7 +571,10 @@ class KoboController(
|
|||
locator =
|
||||
if (koboUpdate.statusInfo.status == StatusDto.FINISHED) {
|
||||
// If the book is finished, Kobo sends the first resource instead of the last, so we can't trust what Kobo sent
|
||||
val epubExtension = mediaRepository.findExtensionByIdOrNull(book.id) as? MediaExtensionEpub ?: throw IllegalArgumentException("Epub extension not found")
|
||||
val epubExtension =
|
||||
mediaRepository.findExtensionByIdOrNull(book.id) as? MediaExtensionEpub
|
||||
?: throw IllegalArgumentException("Epub extension not found")
|
||||
.also { logger.error { "Epub extension not found for book ${book.id}. Book should be re-analyzed." } }
|
||||
epubExtension.positions.last()
|
||||
} else {
|
||||
R2Locator(
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
package org.gotson.komga.interfaces.api.kosync
|
||||
|
||||
import io.github.oshai.kotlinlogging.KotlinLogging
|
||||
import org.gotson.komga.domain.model.MediaExtensionEpub
|
||||
import org.gotson.komga.domain.model.MediaProfile
|
||||
import org.gotson.komga.domain.model.R2Device
|
||||
|
|
@ -25,6 +26,8 @@ import org.springframework.web.bind.annotation.RestController
|
|||
import org.springframework.web.server.ResponseStatusException
|
||||
import java.time.ZonedDateTime
|
||||
|
||||
private val logger = KotlinLogging.logger {}
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/koreader", produces = ["application/vnd.koreader.v1+json"])
|
||||
class KoreaderSyncController(
|
||||
|
|
@ -48,8 +51,14 @@ class KoreaderSyncController(
|
|||
@PathVariable bookHash: String,
|
||||
): DocumentProgressDto {
|
||||
val books = bookRepository.findAllByHashKoreader(bookHash)
|
||||
if (books.isEmpty()) throw ResponseStatusException(HttpStatus.NOT_FOUND, "Book not found")
|
||||
if (books.size > 1) throw ResponseStatusException(HttpStatus.CONFLICT, "More than 1 book found with the same hash")
|
||||
if (books.isEmpty()) {
|
||||
logger.debug { "No book found with KOReader hash: $bookHash" }
|
||||
throw ResponseStatusException(HttpStatus.NOT_FOUND, "Book not found")
|
||||
}
|
||||
if (books.size > 1) {
|
||||
logger.debug { "No unique book found with KOReader hash: $bookHash. Found ${books.size} books with the same hash." }
|
||||
throw ResponseStatusException(HttpStatus.CONFLICT, "More than 1 book found with the same hash")
|
||||
}
|
||||
|
||||
val book = books.first()
|
||||
val media = mediaRepository.findById(book.id)
|
||||
|
|
@ -69,7 +78,10 @@ class KoreaderSyncController(
|
|||
when (media.profile) {
|
||||
MediaProfile.DIVINA, MediaProfile.PDF -> readProgress.page.toString()
|
||||
MediaProfile.EPUB -> {
|
||||
val extension = mediaRepository.findExtensionByIdOrNull(book.id) as? MediaExtensionEpub ?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Epub extension not found")
|
||||
val extension =
|
||||
mediaRepository.findExtensionByIdOrNull(book.id) as? MediaExtensionEpub
|
||||
?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Epub extension not found")
|
||||
.also { logger.error { "Epub extension not found for book ${book.id}. Book should be re-analyzed." } }
|
||||
|
||||
// convert the href to its index for KOReader
|
||||
val resourceIndex =
|
||||
|
|
@ -81,6 +93,7 @@ class KoreaderSyncController(
|
|||
// return a progress string that points to the beginning of the resource
|
||||
"/body/DocFragment[${resourceIndex + 1}].0"
|
||||
}
|
||||
|
||||
null -> throw ResponseStatusException(HttpStatus.NOT_FOUND, "Book has no media profile")
|
||||
}
|
||||
|
||||
|
|
@ -99,8 +112,14 @@ class KoreaderSyncController(
|
|||
@RequestBody koreaderProgress: DocumentProgressDto,
|
||||
) {
|
||||
val books = bookRepository.findAllByHashKoreader(koreaderProgress.document)
|
||||
if (books.isEmpty()) throw ResponseStatusException(HttpStatus.NOT_FOUND, "Book not found")
|
||||
if (books.size > 1) throw ResponseStatusException(HttpStatus.CONFLICT, "More than 1 book found with the same hash")
|
||||
if (books.isEmpty()) {
|
||||
logger.debug { "No book found with KOReader hash: ${koreaderProgress.document}" }
|
||||
throw ResponseStatusException(HttpStatus.NOT_FOUND, "Book not found")
|
||||
}
|
||||
if (books.size > 1) {
|
||||
logger.debug { "No unique book found with KOReader hash: ${koreaderProgress.document}. Found ${books.size} books with the same hash." }
|
||||
throw ResponseStatusException(HttpStatus.CONFLICT, "More than 1 book found with the same hash")
|
||||
}
|
||||
|
||||
val book = books.first()
|
||||
val media = mediaRepository.findById(book.id)
|
||||
|
|
@ -139,8 +158,12 @@ class KoreaderSyncController(
|
|||
?.value
|
||||
?.toIntOrNull()
|
||||
?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Could not get Epub resource index from progress: ${koreaderProgress.progress}")
|
||||
.also { logger.error { "Could not get Epub resource index from progress: ${koreaderProgress.progress}" } }
|
||||
|
||||
val extension = mediaRepository.findExtensionByIdOrNull(book.id) as? MediaExtensionEpub ?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Epub extension not found")
|
||||
val extension =
|
||||
mediaRepository.findExtensionByIdOrNull(book.id) as? MediaExtensionEpub
|
||||
?: throw ResponseStatusException(HttpStatus.BAD_REQUEST, "Epub extension not found")
|
||||
.also { logger.error { "Epub extension not found for book ${book.id}. Book should be re-analyzed." } }
|
||||
|
||||
// get the href from the index provided by KOReader
|
||||
val href =
|
||||
|
|
|
|||
|
|
@ -268,7 +268,7 @@ class ReadListController(
|
|||
}
|
||||
|
||||
@Operation(summary = "Match ComicRack list", tags = [OpenApiConfiguration.TagNames.COMICRACK])
|
||||
@PostMapping("match/comicrack")
|
||||
@PostMapping("match/comicrack", consumes = [MediaType.MULTIPART_FORM_DATA_VALUE])
|
||||
@PreAuthorize("hasRole('ADMIN')")
|
||||
fun matchComicRackList(
|
||||
@RequestParam("file") file: MultipartFile,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package org.gotson.komga.interfaces.api.rest.dto
|
|||
import java.time.LocalDateTime
|
||||
|
||||
data class HistoricalEventDto(
|
||||
val id: String,
|
||||
val type: String,
|
||||
val timestamp: LocalDateTime,
|
||||
val bookId: String?,
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ class SettingsUpdateDto {
|
|||
isSet[prop.name] = true
|
||||
}
|
||||
|
||||
@Deprecated("Will be removed in a future version")
|
||||
var kepubifyPath: String?
|
||||
by Delegates.observable(null) { prop, _, _ ->
|
||||
isSet[prop.name] = true
|
||||
|
|
|
|||
|
|
@ -46,6 +46,9 @@ spring:
|
|||
jackson:
|
||||
deserialization:
|
||||
FAIL_ON_NULL_FOR_PRIMITIVES: true
|
||||
mapper:
|
||||
accept-case-insensitive-properties: true
|
||||
accept-case-insensitive-values: true
|
||||
config:
|
||||
import:
|
||||
- "optional:file:\${komga.config-dir}/application.yml"
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import javax.sql.DataSource
|
|||
|
||||
class DataSourcesConfigurationTest {
|
||||
@SpringBootTest
|
||||
@ActiveProfiles("test", "waltest")
|
||||
@Nested
|
||||
inner class WalMode(
|
||||
@Autowired private val dataSourceRW: DataSource,
|
||||
|
|
@ -27,6 +26,7 @@ class DataSourcesConfigurationTest {
|
|||
}
|
||||
|
||||
@SpringBootTest
|
||||
@ActiveProfiles("test", "memorydb")
|
||||
@Nested
|
||||
inner class MemoryMode(
|
||||
@Autowired private val dataSourceRW: DataSource,
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ import org.gotson.komga.infrastructure.mediacontainer.epub.getPackageFileContent
|
|||
import org.junit.jupiter.api.AfterEach
|
||||
import org.junit.jupiter.api.Nested
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.params.ParameterizedTest
|
||||
import org.junit.jupiter.params.provider.ValueSource
|
||||
import org.springframework.core.io.ClassPathResource
|
||||
import java.time.LocalDate
|
||||
|
||||
|
|
@ -37,9 +39,15 @@ class EpubMetadataProviderTest {
|
|||
|
||||
@Nested
|
||||
inner class Book {
|
||||
@Test
|
||||
fun `given epub 3 opf when getting book metadata then metadata patch is valid`() {
|
||||
val opf = ClassPathResource("epub/Panik im Paradies.opf")
|
||||
@ParameterizedTest
|
||||
@ValueSource(
|
||||
strings = [
|
||||
"epub/Panik im Paradies.opf",
|
||||
"epub/Panik im Paradies - namespace.opf",
|
||||
],
|
||||
)
|
||||
fun `given epub 3 opf when getting book metadata then metadata patch is valid`(opfFile: String) {
|
||||
val opf = ClassPathResource(opfFile)
|
||||
mockkStatic(::getPackageFileContent)
|
||||
every { getPackageFileContent(any()) } returns opf.file.readText()
|
||||
|
||||
|
|
@ -128,9 +136,15 @@ class EpubMetadataProviderTest {
|
|||
|
||||
@Nested
|
||||
inner class Series {
|
||||
@Test
|
||||
fun `given epub 3 opf when getting series metadata then metadata patch is valid`() {
|
||||
val opf = ClassPathResource("epub/Panik im Paradies.opf")
|
||||
@ParameterizedTest
|
||||
@ValueSource(
|
||||
strings = [
|
||||
"epub/Panik im Paradies.opf",
|
||||
"epub/Panik im Paradies - namespace.opf",
|
||||
],
|
||||
)
|
||||
fun `given epub 3 opf when getting series metadata then metadata patch is valid`(opfFile: String) {
|
||||
val opf = ClassPathResource(opfFile)
|
||||
mockkStatic(::getPackageFileContent)
|
||||
every { getPackageFileContent(any()) } returns opf.file.readText()
|
||||
|
||||
|
|
|
|||
5
komga/src/test/resources/application-memorydb.yml
Normal file
5
komga/src/test/resources/application-memorydb.yml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
komga:
|
||||
database:
|
||||
file: "file:database?mode=memory"
|
||||
tasks-db:
|
||||
file: "file:tasks?mode=memory"
|
||||
|
|
@ -2,9 +2,11 @@ application.version: TESTING
|
|||
|
||||
komga:
|
||||
database:
|
||||
file: "file:database?mode=memory"
|
||||
file: "\${java.io.tmpdir}/database\${random.uuid}.sqlite"
|
||||
journal-mode: WAL
|
||||
tasks-db:
|
||||
file: "file:tasks?mode=memory"
|
||||
file: "\${java.io.tmpdir}/tasks\${random.uuid}.sqlite"
|
||||
journal-mode: WAL
|
||||
|
||||
spring:
|
||||
flyway:
|
||||
|
|
|
|||
|
|
@ -1,7 +0,0 @@
|
|||
komga:
|
||||
database:
|
||||
file: "\${java.io.tmpdir}/database.sqlite"
|
||||
journal-mode: WAL
|
||||
tasks-db:
|
||||
file: "\${java.io.tmpdir}/tasks.sqlite"
|
||||
journal-mode: WAL
|
||||
128
komga/src/test/resources/epub/Panik im Paradies - namespace.opf
Normal file
128
komga/src/test/resources/epub/Panik im Paradies - namespace.opf
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
<myopf:package xmlns:myopf="http://www.idpf.org/2007/opf" version="3.0" unique-identifier="uuid_id" prefix="calibre: https://calibre-ebook.com">
|
||||
<myopf:metadata xmlns:mydc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:dcterms="http://purl.org/dc/terms/"
|
||||
xmlns:calibre="http://calibre.kovidgoyal.net/2009/metadata">
|
||||
<mydc:title id="id">Panik im Paradies</mydc:title>
|
||||
<mydc:creator id="id-1">Ulf Blanck</mydc:creator>
|
||||
<mydc:creator id="id-3">The Editor</mydc:creator>
|
||||
<mydc:identifier>goodreads:222735</mydc:identifier>
|
||||
<mydc:identifier>isbn:9783440077894</mydc:identifier>
|
||||
<mydc:identifier>calibre:255</mydc:identifier>
|
||||
<mydc:identifier>uuid:499def46-39dc-4e79-b474-d0ec12ea5dc5</mydc:identifier>
|
||||
<mydc:identifier id="uuid_id">uuid:499def46-39dc-4e79-b474-d0ec12ea5dc5</mydc:identifier>
|
||||
<mydc:language>de</mydc:language>
|
||||
<mydc:date>1999-07-31T16:00:00+00:00</mydc:date>
|
||||
<mydc:description><div>
|
||||
<p>Bereits im ersten Band "Panik im Paradies" machen die drei berühmten Detektive ihrem Namen alle Ehre. Eigentlich haben sie ja gerade Ferien. Doch dann treffen sie auf diesen schrulligen Kapitän Larsson, der sich einen kleinen Privatzoo mit exotischen Tieren hält. Als plötzlich alle Tiere an rätselhaften Infektionen erkranken und die Besucher ausbleiben, werden Justus, Peter und Bob neugierig. Schon bald merken sie, daß da jemand ein düsteres Geheimnis hütet...</p></div></mydc:description>
|
||||
<mydc:publisher>Kosmos</mydc:publisher>
|
||||
<mydc:subject>Kinder- und Jugendbücher</mydc:subject>
|
||||
<myopf:meta refines="#id" property="title-type">main</myopf:meta>
|
||||
<myopf:meta refines="#id" property="file-as">Panik im Paradies</myopf:meta>
|
||||
<myopf:meta name="cover" content="cover"/>
|
||||
<myopf:meta property="calibre:timestamp" scheme="dcterms:W3CDTF">2020-08-09T08:40:58Z</myopf:meta>
|
||||
<myopf:meta property="dcterms:modified" scheme="dcterms:W3CDTF">2021-06-19T08:20:33Z</myopf:meta>
|
||||
<myopf:meta refines="#id-1" property="role" scheme="marc:relators">aut</myopf:meta>
|
||||
<myopf:meta refines="#id-1" property="file-as">Blanck, Ulf</myopf:meta>
|
||||
<myopf:meta refines="#id-3" property="role" scheme="marc:relators">edt</myopf:meta>
|
||||
<myopf:meta refines="#id-3" property="file-as">Editor, The</myopf:meta>
|
||||
<myopf:meta property="calibre:rating">6</myopf:meta>
|
||||
<myopf:meta property="belongs-to-collection" id="id-2">Die drei ??? Kids</myopf:meta>
|
||||
<myopf:meta refines="#id-2" property="collection-type">series</myopf:meta>
|
||||
<myopf:meta refines="#id-2" property="group-position">1.5</myopf:meta>
|
||||
<myopf:meta property="calibre:author_link_map">{"Ulf Blanck": ""}</myopf:meta>
|
||||
</myopf:metadata>
|
||||
<myopf:manifest>
|
||||
<myopf:item id="titlepage" href="titlepage.xhtml" media-type="application/xhtml+xml" properties="svg calibre:title-page"/>
|
||||
<myopf:item id="TableOfContents_html" href="OPS/TableOfContents.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0001_html" href="OPS/section-0001.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0002_html" href="OPS/section-0002.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0003_html" href="OPS/section-0003.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0004_html" href="OPS/section-0004.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0005_html" href="OPS/section-0005.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0006_html" href="OPS/section-0006.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0007_html" href="OPS/section-0007.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0008_html" href="OPS/section-0008.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0009_html" href="OPS/section-0009.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0010_html" href="OPS/section-0010.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0011_html" href="OPS/section-0011.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0012_html" href="OPS/section-0012.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0013_html" href="OPS/section-0013.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0014_html" href="OPS/section-0014.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0015_html" href="OPS/section-0015.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0016_html" href="OPS/section-0016.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0017_html" href="OPS/section-0017.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0018_html" href="OPS/section-0018.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0019_html" href="OPS/section-0019.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0020_html" href="OPS/section-0020.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0021_html" href="OPS/section-0021.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0022_html" href="OPS/section-0022.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="section-0023_html" href="OPS/section-0023.html" media-type="application/xhtml+xml"/>
|
||||
<myopf:item id="nav" href="nav.xhtml" media-type="application/xhtml+xml" properties="nav"/>
|
||||
<myopf:item id="page_css" href="page_styles.css" media-type="text/css"/>
|
||||
<myopf:item id="css" href="stylesheet.css" media-type="text/css"/>
|
||||
<myopf:item id="cover" href="cover.jpeg" media-type="image/jpeg" properties="cover-image"/>
|
||||
<myopf:item id="image0_jpg" href="OPS/image0.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image1_jpg" href="OPS/image1.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image10_jpg" href="OPS/image10.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image11_jpg" href="OPS/image11.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image12_jpg" href="OPS/image12.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image13_jpg" href="OPS/image13.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image14_jpg" href="OPS/image14.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image15_jpg" href="OPS/image15.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image16_jpg" href="OPS/image16.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image17_jpg" href="OPS/image17.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image18_jpg" href="OPS/image18.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image19_jpg" href="OPS/image19.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image2_jpg" href="OPS/image2.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image20_jpg" href="OPS/image20.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image21_jpg" href="OPS/image21.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image22_jpg" href="OPS/image22.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image23_jpg" href="OPS/image23.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image24_jpg" href="OPS/image24.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image25_jpg" href="OPS/image25.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image26_jpg" href="OPS/image26.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image27_jpg" href="OPS/image27.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image28_jpg" href="OPS/image28.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image29_jpg" href="OPS/image29.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image3_jpg" href="OPS/image3.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image30_jpg" href="OPS/image30.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image31_jpg" href="OPS/image31.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image32_jpg" href="OPS/image32.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image33_jpg" href="OPS/image33.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image34_jpg" href="OPS/image34.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image35_jpg" href="OPS/image35.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image4_jpg" href="OPS/image4.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image5_jpg" href="OPS/image5.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image6_jpg" href="OPS/image6.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image7_jpg" href="OPS/image7.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image8_jpg" href="OPS/image8.jpg" media-type="image/jpeg"/>
|
||||
<myopf:item id="image9_jpg" href="OPS/image9.jpg" media-type="image/jpeg"/>
|
||||
</myopf:manifest>
|
||||
<myopf:spine page-progression-direction="rtl">
|
||||
<myopf:itemref idref="titlepage"/>
|
||||
<myopf:itemref idref="TableOfContents_html"/>
|
||||
<myopf:itemref idref="section-0001_html"/>
|
||||
<myopf:itemref idref="section-0002_html"/>
|
||||
<myopf:itemref idref="section-0003_html"/>
|
||||
<myopf:itemref idref="section-0004_html"/>
|
||||
<myopf:itemref idref="section-0005_html"/>
|
||||
<myopf:itemref idref="section-0006_html"/>
|
||||
<myopf:itemref idref="section-0007_html"/>
|
||||
<myopf:itemref idref="section-0008_html"/>
|
||||
<myopf:itemref idref="section-0009_html"/>
|
||||
<myopf:itemref idref="section-0010_html"/>
|
||||
<myopf:itemref idref="section-0011_html"/>
|
||||
<myopf:itemref idref="section-0012_html"/>
|
||||
<myopf:itemref idref="section-0013_html"/>
|
||||
<myopf:itemref idref="section-0014_html"/>
|
||||
<myopf:itemref idref="section-0015_html"/>
|
||||
<myopf:itemref idref="section-0016_html"/>
|
||||
<myopf:itemref idref="section-0017_html"/>
|
||||
<myopf:itemref idref="section-0018_html"/>
|
||||
<myopf:itemref idref="section-0019_html"/>
|
||||
<myopf:itemref idref="section-0020_html"/>
|
||||
<myopf:itemref idref="section-0021_html"/>
|
||||
<myopf:itemref idref="section-0022_html"/>
|
||||
<myopf:itemref idref="section-0023_html"/>
|
||||
</myopf:spine>
|
||||
</myopf:package>
|
||||
Loading…
Reference in a new issue