mirror of
https://github.com/alam00000/bentopdf.git
synced 2026-11-05 03:50:29 +01:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9aae81e73c | ||
|
|
2f868d4d0e | ||
|
|
2be3d6858c | ||
|
|
edd959f345 | ||
|
|
b0a186839a | ||
|
|
70dc47d25c | ||
|
|
231c012e99 | ||
|
|
6a75673cbe | ||
|
|
66f3628811 | ||
|
|
4c314b8a13 | ||
|
|
0584def180 | ||
|
|
ccdb4dd8e5 | ||
|
|
733c4f0bf9 | ||
|
|
dde07a28bd | ||
|
|
6ce0d69ba5 | ||
|
|
167b7e8f90 | ||
|
|
b5a69f9191 | ||
|
|
2651471a84 | ||
|
|
872a32929e | ||
|
|
46bf0fbb57 | ||
|
|
3a5f146d1b | ||
|
|
1a41545fff | ||
|
|
c10511203e | ||
|
|
4d1dc2a838 | ||
|
|
4874f1e8a7 | ||
|
|
2560a31cdd | ||
|
|
daae736907 | ||
|
|
044b2eae99 | ||
|
|
ea3f42db84 | ||
|
|
72d20bba09 | ||
|
|
5a7927572f | ||
|
|
866d40edc8 | ||
|
|
9ae5c93886 | ||
|
|
a44ad4d7d3 | ||
|
|
4c4701ef37 | ||
|
|
fe65e9e999 | ||
|
|
ff6a09ae72 | ||
|
|
81929c7f5e | ||
|
|
2d37ac9f77 | ||
|
|
3aefd7bb06 | ||
|
|
c5ec840d10 | ||
|
|
597e36904e | ||
|
|
e01f80867b | ||
|
|
d69566ebef | ||
|
|
d931a71589 | ||
|
|
2117d70837 | ||
|
|
9e980cdea2 | ||
|
|
31f6f977f9 | ||
|
|
83ff47db9b | ||
|
|
bfc32874ce | ||
|
|
f404ff021a | ||
|
|
4e2d269dc3 | ||
|
|
e95a631909 | ||
|
|
47af6863bd | ||
|
|
9c90d08a14 | ||
|
|
f96cd4e516 | ||
|
|
a453313ff3 | ||
|
|
9132dd42b5 | ||
|
|
f35224f16f | ||
|
|
62041f4677 | ||
|
|
4f57cb076f | ||
|
|
627288ca13 | ||
|
|
480acfdf44 | ||
|
|
7888fca6fa | ||
|
|
921a5b4249 | ||
|
|
4bb43fda08 | ||
|
|
acdca59f18 | ||
|
|
829b13f8ff | ||
|
|
4339d21d41 | ||
|
|
1d78b8ec72 | ||
|
|
bf513bbcb9 | ||
|
|
7831571696 | ||
|
|
c449a85745 | ||
|
|
8e606b652c | ||
|
|
3fa731aa6e | ||
|
|
121c3d891a | ||
|
|
32db7cb173 | ||
|
|
1713fb0991 | ||
|
|
47d6871bc5 | ||
|
|
be36588468 | ||
|
|
532ba68f4f | ||
|
|
5bcdd8deeb | ||
|
|
7f6bebf21f | ||
|
|
0f65fdb2f4 | ||
|
|
09d1860396 | ||
|
|
5b4b40fe81 | ||
|
|
6ac503efae | ||
|
|
c72185ed0b | ||
|
|
aee3e0a65a | ||
|
|
5392c1be76 | ||
|
|
356128c60d | ||
|
|
8dc7509ceb | ||
|
|
cba16fe750 | ||
|
|
a55614d5ab | ||
|
|
6b4e9f2a94 | ||
|
|
75e76c9619 | ||
|
|
6529b0e9b7 | ||
|
|
78cb827ec7 | ||
|
|
dbcb9cc153 | ||
|
|
1d2cd3f805 | ||
|
|
053f22a87b | ||
|
|
e8f26c4a70 | ||
|
|
9635c398d6 | ||
|
|
5bf54f1dad | ||
|
|
ee17fa8760 | ||
|
|
61fde80a90 | ||
|
|
ca95925de9 | ||
|
|
706e74f084 | ||
|
|
e1a4a31458 | ||
|
|
866ecfed2d | ||
|
|
10b63b5f89 | ||
|
|
af5b95e93c | ||
|
|
b8f3d4e582 | ||
|
|
3672ecf91d | ||
|
|
7c8c7600ae | ||
|
|
42b2615882 | ||
|
|
02548b80b1 | ||
|
|
2ed0575ca3 | ||
|
|
54778a7e43 | ||
|
|
59de529311 | ||
|
|
5a4be8e7f2 | ||
|
|
d9183028d5 | ||
|
|
fae0aa4c04 | ||
|
|
55915a2901 | ||
|
|
f2a8b77733 | ||
|
|
c8d04e51b9 | ||
|
|
b003355a0c | ||
|
|
79ae42d73a | ||
|
|
2835e7e5f9 | ||
|
|
a59a1f41cd | ||
|
|
0447cfc032 | ||
|
|
7070bae927 | ||
|
|
a3e64f6340 | ||
|
|
45496fcd2e | ||
|
|
115bc70ad1 | ||
|
|
e59ce4feac | ||
|
|
ea0a8755bf | ||
|
|
21c924a3e6 | ||
|
|
58cd1a8893 | ||
|
|
57a6422e61 | ||
|
|
0ef279e0da | ||
|
|
8dcd936873 | ||
|
|
5ef0b40dea | ||
|
|
6f02f2d2b7 | ||
|
|
b21f602cca | ||
|
|
b09fc21e66 | ||
|
|
fa6355b98a | ||
|
|
53bcf09566 | ||
|
|
d2dc459ba9 | ||
|
|
71ced499e7 | ||
|
|
994fd81626 | ||
|
|
4487f2c1c6 | ||
|
|
39024e1a63 | ||
|
|
01c6148904 | ||
|
|
fc264f796a | ||
|
|
94c60f01c8 | ||
|
|
ad5811efb0 | ||
|
|
1ada0cee13 | ||
|
|
d7c14f821a | ||
|
|
98371733a6 | ||
|
|
6c53646e94 | ||
|
|
4812d5b389 | ||
|
|
e55c2ed405 | ||
|
|
4b875a638c | ||
|
|
b71d6c9b96 | ||
|
|
d63d1683c7 | ||
|
|
0347013df1 | ||
|
|
412f2f1acb | ||
|
|
a471bbcf4d | ||
|
|
e1843e17b3 | ||
|
|
ac3ad68b56 | ||
|
|
745698a5ba | ||
|
|
dc1dbb036c | ||
|
|
175c52bb1f | ||
|
|
1d9b7c2a07 | ||
|
|
1534ce4d85 | ||
|
|
3cab1d37c7 |
@@ -29,6 +29,9 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Run tests
|
||||
run: npm run test:run
|
||||
|
||||
- name: Build distribution
|
||||
run: npm run build
|
||||
|
||||
@@ -42,7 +45,7 @@ jobs:
|
||||
run: npm run package
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2.6.2
|
||||
with:
|
||||
files: |
|
||||
dist-${{ steps.version.outputs.version }}.zip
|
||||
@@ -74,10 +77,10 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
@@ -100,7 +103,7 @@ jobs:
|
||||
|
||||
- name: Build and push amd64 ${{ matrix.mode.name }} (release)
|
||||
if: steps.version.outputs.is_release == 'true'
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
|
||||
with:
|
||||
push: true
|
||||
build-args: |
|
||||
@@ -108,12 +111,11 @@ jobs:
|
||||
tags: |
|
||||
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-amd64
|
||||
platforms: linux/amd64
|
||||
cache-from: type=gha,scope=amd64-${{ matrix.mode.name }}
|
||||
cache-to: type=gha,mode=max,scope=amd64-${{ matrix.mode.name }}
|
||||
no-cache: true
|
||||
|
||||
- name: Build and push amd64 ${{ matrix.mode.name }} (edge)
|
||||
if: steps.version.outputs.is_release == 'false'
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
|
||||
with:
|
||||
push: true
|
||||
build-args: |
|
||||
@@ -143,10 +145,10 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
@@ -169,7 +171,7 @@ jobs:
|
||||
|
||||
- name: Build and push arm64 ${{ matrix.mode.name }} (release)
|
||||
if: steps.version.outputs.is_release == 'true'
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
|
||||
with:
|
||||
push: true
|
||||
build-args: |
|
||||
@@ -177,12 +179,11 @@ jobs:
|
||||
tags: |
|
||||
ghcr.io/${{ github.repository_owner }}/bentopdf${{ matrix.mode.suffix }}:${{ steps.version.outputs.version }}-arm64
|
||||
platforms: linux/arm64
|
||||
cache-from: type=gha,scope=arm64-${{ matrix.mode.name }}
|
||||
cache-to: type=gha,mode=max,scope=arm64-${{ matrix.mode.name }}
|
||||
no-cache: true
|
||||
|
||||
- name: Build and push arm64 ${{ matrix.mode.name }} (edge)
|
||||
if: steps.version.outputs.is_release == 'false'
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
|
||||
with:
|
||||
push: true
|
||||
build-args: |
|
||||
@@ -208,7 +209,7 @@ jobs:
|
||||
suffix: "-simple"
|
||||
steps:
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
@@ -272,14 +273,14 @@ jobs:
|
||||
suffix: "-simple"
|
||||
steps:
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to DockerHub
|
||||
uses: docker/login-action@v3
|
||||
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_TOKEN }}
|
||||
|
||||
@@ -11,7 +11,6 @@ permissions:
|
||||
actions: write
|
||||
contents: write
|
||||
pull-requests: write
|
||||
statuses: write
|
||||
|
||||
jobs:
|
||||
cla-check:
|
||||
@@ -28,16 +27,15 @@ jobs:
|
||||
)
|
||||
steps:
|
||||
- name: "CLA Assistant"
|
||||
uses: contributor-assistant/[email protected]
|
||||
uses: contributor-assistant/github-action@ca4a40a7d1004f18d9960b404b97e5f30a505a08 # v2.6.1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
PERSONAL_ACCESS_TOKEN: ${{ secrets.CLA_ASSISTANT_TOKEN }}
|
||||
with:
|
||||
path-to-signatures: 'signatures/cla.json'
|
||||
path-to-document: 'https://github.com/${{ github.repository }}/blob/main/ICLA.md'
|
||||
|
||||
# Branch to store signatures
|
||||
branch: 'main'
|
||||
branch: 'cla-signatures'
|
||||
|
||||
# Allowlist for bot accounts (won't need to sign CLA)
|
||||
allowlist: 'bot*,*[bot],dependabot*,renovate*,github-actions*'
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
name: Update Docker Downloads Badge
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '17 4 * * 1'
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
concurrency:
|
||||
group: docker-downloads-badge
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
update:
|
||||
if: github.repository == 'alam00000/bentopdf'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Sum GHCR download counts
|
||||
id: counts
|
||||
run: |
|
||||
set -euo pipefail
|
||||
total=0
|
||||
for pkg in bentopdf bentopdf-simple; do
|
||||
raw=$(curl -sf --retry 3 --retry-delay 5 --max-time 30 \
|
||||
"https://ghcr-badge.elias.eu.org/api/alam00000/bentopdf/$pkg" \
|
||||
| jq -e -r '.downloadCountRaw')
|
||||
case "$raw" in ''|*[!0-9]*) echo "::error::invalid count for $pkg: $raw"; exit 1 ;; esac
|
||||
echo "$pkg: $raw"
|
||||
total=$((total + raw))
|
||||
done
|
||||
if [ "$total" -le 0 ]; then echo "::error::total is zero"; exit 1; fi
|
||||
message=$(awk -v n="$total" 'BEGIN{
|
||||
if (n >= 1000000) printf "%.1fM", n/1000000;
|
||||
else if (n >= 1000) printf "%.1fk", n/1000;
|
||||
else printf "%d", n
|
||||
}')
|
||||
echo "total=$total" >> "$GITHUB_OUTPUT"
|
||||
echo "message=$message" >> "$GITHUB_OUTPUT"
|
||||
echo "combined: $total -> $message"
|
||||
|
||||
- name: Publish badge JSON to badges branch
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
MESSAGE: ${{ steps.counts.outputs.message }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
mkdir badges && cd badges
|
||||
jq -n --arg message "$MESSAGE" \
|
||||
'{schemaVersion: 1, label: "Docker Downloads", message: $message, color: "blue", namedLogo: "docker"}' \
|
||||
> docker-downloads.json
|
||||
cat docker-downloads.json
|
||||
git init -q -b badges
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
git add docker-downloads.json
|
||||
git commit -qm "chore: update docker downloads badge ($MESSAGE)"
|
||||
git push -qf "https://x-access-token:${GH_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" badges
|
||||
@@ -6,7 +6,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: JamesIves/github-sponsors-readme-action@v1
|
||||
- uses: JamesIves/github-sponsors-readme-action@02650b8cd445fc16dfef73195f9c406dce041623 # v1.6.1
|
||||
with:
|
||||
token: ${{ secrets.SPONSORS_TOKEN }}
|
||||
file: 'README.md'
|
||||
@@ -0,0 +1,36 @@
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- 'main'
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: tests-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
HUSKY: 0
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
|
||||
- name: Typecheck
|
||||
run: npx tsc --noEmit
|
||||
|
||||
- name: Run tests
|
||||
run: npm run test:run
|
||||
@@ -28,10 +28,10 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
|
||||
|
||||
- name: Build image for scanning
|
||||
uses: docker/build-push-action@v6
|
||||
uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2
|
||||
with:
|
||||
context: .
|
||||
file: ${{ matrix.image.file }}
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
no-cache: true
|
||||
|
||||
- name: Run Trivy vulnerability scanner
|
||||
uses: aquasecurity/trivy-action@master
|
||||
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
|
||||
with:
|
||||
image-ref: ${{ matrix.image.name }}:scan
|
||||
format: sarif
|
||||
@@ -51,7 +51,7 @@ jobs:
|
||||
|
||||
- name: Upload Trivy results to GitHub Security
|
||||
uses: github/codeql-action/upload-sarif@v4
|
||||
if: always()
|
||||
if: always() && hashFiles('trivy-*.sarif') != ''
|
||||
with:
|
||||
sarif_file: trivy-${{ matrix.image.name }}.sarif
|
||||
category: trivy-${{ matrix.image.name }}
|
||||
@@ -63,7 +63,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Scan npm dependencies with Trivy
|
||||
uses: aquasecurity/trivy-action@master
|
||||
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
|
||||
with:
|
||||
scan-type: fs
|
||||
scan-ref: .
|
||||
@@ -74,7 +74,7 @@ jobs:
|
||||
|
||||
- name: Upload dependency scan results
|
||||
uses: github/codeql-action/upload-sarif@v4
|
||||
if: always()
|
||||
if: always() && hashFiles('trivy-deps.sarif') != ''
|
||||
with:
|
||||
sarif_file: trivy-deps.sarif
|
||||
category: trivy-dependencies
|
||||
@@ -86,7 +86,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Scan Dockerfiles for misconfigurations
|
||||
uses: aquasecurity/trivy-action@master
|
||||
uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 # v0.36.0
|
||||
with:
|
||||
scan-type: config
|
||||
scan-ref: .
|
||||
@@ -96,7 +96,7 @@ jobs:
|
||||
|
||||
- name: Upload config scan results
|
||||
uses: github/codeql-action/upload-sarif@v4
|
||||
if: always()
|
||||
if: always() && hashFiles('trivy-config.sarif') != ''
|
||||
with:
|
||||
sarif_file: trivy-config.sarif
|
||||
category: trivy-config
|
||||
|
||||
@@ -0,0 +1,270 @@
|
||||
name: Update PDF Engine and Viewer
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '17 4 * * *'
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency:
|
||||
group: update-engine
|
||||
cancel-in-progress: false
|
||||
|
||||
env:
|
||||
FORK_URL: https://github.com/alam00000/bentopdf-pdfium-viewer
|
||||
HUSKY: 0
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'alam00000/bentopdf'
|
||||
permissions:
|
||||
contents: read
|
||||
outputs:
|
||||
run: ${{ steps.gate.outputs.run }}
|
||||
version: ${{ steps.gate.outputs.version }}
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: Read current upstream marker
|
||||
id: current
|
||||
run: |
|
||||
if [ -f vendor/bentopdf-viewer/.upstream-version ]; then
|
||||
echo "version=$(cat vendor/bentopdf-viewer/.upstream-version)" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "version=" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
- name: Read fork HEAD
|
||||
id: upstream
|
||||
run: echo "version=$(git ls-remote "$FORK_URL" refs/heads/main | cut -c1-12)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Should update?
|
||||
id: gate
|
||||
env:
|
||||
CURRENT: ${{ steps.current.outputs.version }}
|
||||
UPSTREAM: ${{ steps.upstream.outputs.version }}
|
||||
run: |
|
||||
if ! [[ "$UPSTREAM" =~ ^[0-9a-f]{12}$ ]]; then
|
||||
echo "::error::Unexpected fork HEAD: $UPSTREAM"
|
||||
exit 1
|
||||
fi
|
||||
echo "version=$UPSTREAM" >> "$GITHUB_OUTPUT"
|
||||
if [ "$UPSTREAM" = "$CURRENT" ]; then
|
||||
echo "run=false" >> "$GITHUB_OUTPUT"
|
||||
echo "Already on $CURRENT."
|
||||
else
|
||||
echo "run=true" >> "$GITHUB_OUTPUT"
|
||||
echo "Updating $CURRENT -> $UPSTREAM"
|
||||
fi
|
||||
|
||||
- name: Setup Node
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
|
||||
- name: Enable corepack (pnpm)
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
run: corepack enable
|
||||
|
||||
- name: Clone the viewer fork
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
run: git clone --depth 1 --branch main "$FORK_URL" ./_fork
|
||||
|
||||
- name: Require a published engine
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
run: |
|
||||
test -s ./_fork/packages/pdfium/src/vendor/pdfium.wasm
|
||||
test -s ./_fork/packages/pdfium/src/vendor/pdfium.js
|
||||
|
||||
- name: Pack the engine
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
id: engine
|
||||
env:
|
||||
SHA: ${{ steps.gate.outputs.version }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
VENDOR=./_fork/packages/pdfium/src/vendor
|
||||
STAGE=$(mktemp -d)/package
|
||||
mkdir -p "$STAGE"
|
||||
cp "$VENDOR/pdfium.js" "$STAGE/editcore.js"
|
||||
cp "$VENDOR/pdfium.wasm" "$STAGE/editcore.wasm"
|
||||
cat > "$STAGE/package.json" <<JSON
|
||||
{
|
||||
"name": "bentopdf-pdfium",
|
||||
"version": "0.0.0-$SHA",
|
||||
"type": "module",
|
||||
"main": "editcore.js",
|
||||
"exports": { ".": "./editcore.js", "./editcore.wasm": "./editcore.wasm" },
|
||||
"license": "AGPL-3.0"
|
||||
}
|
||||
JSON
|
||||
mkdir -p vendor/bentopdf-pdfium
|
||||
OUT="vendor/bentopdf-pdfium/bentopdf-pdfium-$SHA.tgz"
|
||||
tar -czf "$OUT" -C "$(dirname "$STAGE")" package
|
||||
find vendor/bentopdf-pdfium -maxdepth 1 -name 'bentopdf-pdfium*.tgz' ! -name "$(basename "$OUT")" -delete
|
||||
echo "tarball=$OUT" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Build the viewer
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
working-directory: ./_fork
|
||||
run: |
|
||||
pnpm install --no-frozen-lockfile
|
||||
pnpm run build:snippet
|
||||
|
||||
- name: Pack the viewer without a second engine
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
id: viewer
|
||||
env:
|
||||
SHA: ${{ steps.gate.outputs.version }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
WORK=$(mktemp -d)
|
||||
(cd ./_fork && npm pack ./viewers/snippet --pack-destination "$WORK" >/dev/null)
|
||||
TMP=$(mktemp -d)
|
||||
tar -xzf "$WORK"/*.tgz -C "$TMP"
|
||||
rm -f "$TMP/package/dist/pdfium.wasm"
|
||||
PKG="$TMP/package/package.json" node - <<'NODE'
|
||||
const fs = require('fs');
|
||||
const p = process.env.PKG;
|
||||
const pkg = JSON.parse(fs.readFileSync(p, 'utf8'));
|
||||
pkg.name = 'bentopdf-viewer';
|
||||
pkg.dependencies = pkg.dependencies || {};
|
||||
// The rollup bundle inlines every @embedpdf/* package, so these
|
||||
// declared deps would only pull unused copies from upstream npm.
|
||||
for (const k of Object.keys(pkg.dependencies)) {
|
||||
if (k.startsWith('@embedpdf/')) delete pkg.dependencies[k];
|
||||
if (k === 'preact') pkg.dependencies[k] = '^10.17.0';
|
||||
}
|
||||
fs.writeFileSync(p, JSON.stringify(pkg, null, 2) + '\n');
|
||||
NODE
|
||||
mkdir -p vendor/bentopdf-viewer
|
||||
OUT="vendor/bentopdf-viewer/bentopdf-viewer-$SHA.tgz"
|
||||
tar -czf "$OUT" -C "$TMP" package
|
||||
find vendor/bentopdf-viewer -maxdepth 1 -name 'bentopdf-viewer-*.tgz' ! -name "$(basename "$OUT")" -delete
|
||||
echo "tarball=$OUT" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Point dependencies at the new tarballs
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
env:
|
||||
ENGINE_TARBALL: ${{ steps.engine.outputs.tarball }}
|
||||
VIEWER_TARBALL: ${{ steps.viewer.outputs.tarball }}
|
||||
run: |
|
||||
node -e "
|
||||
const fs = require('fs');
|
||||
const pkg = JSON.parse(fs.readFileSync('package.json', 'utf8'));
|
||||
pkg.dependencies['bentopdf-pdfium'] = 'file:' + process.env.ENGINE_TARBALL;
|
||||
pkg.dependencies['bentopdf-viewer'] = 'file:' + process.env.VIEWER_TARBALL;
|
||||
fs.writeFileSync('package.json', JSON.stringify(pkg, null, 2) + '\n');
|
||||
"
|
||||
|
||||
- name: Cleanup upstream clone
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
run: rm -rf ./_fork
|
||||
|
||||
- name: Install and verify one shared engine
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
run: |
|
||||
set -euo pipefail
|
||||
npm install
|
||||
test -s node_modules/bentopdf-pdfium/editcore.wasm
|
||||
if find node_modules/bentopdf-viewer -name '*.wasm' | grep -q .; then
|
||||
echo "::error::viewer package still ships a wasm; the engine would be duplicated"
|
||||
exit 1
|
||||
fi
|
||||
if ! grep -q "bentopdf-pdfium/editcore.wasm" src/js/logic/edit-pdf-page.ts; then
|
||||
echo "::error::the PDF editor no longer points at the shared engine"
|
||||
exit 1
|
||||
fi
|
||||
echo "engine sha256: $(sha256sum node_modules/bentopdf-pdfium/editcore.wasm | cut -c1-16)"
|
||||
|
||||
- name: Typecheck and test
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
run: |
|
||||
npx tsc --noEmit
|
||||
npm run test:run
|
||||
|
||||
- name: Write upstream marker
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
env:
|
||||
SHA: ${{ steps.gate.outputs.version }}
|
||||
run: |
|
||||
echo "$SHA" > vendor/bentopdf-viewer/.upstream-version
|
||||
echo "$SHA" > vendor/bentopdf-pdfium/.upstream-version
|
||||
|
||||
- name: Upload update
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: engine-update
|
||||
include-hidden-files: true
|
||||
retention-days: 1
|
||||
path: |
|
||||
package.json
|
||||
package-lock.json
|
||||
vendor/bentopdf-pdfium/
|
||||
vendor/bentopdf-viewer/
|
||||
|
||||
pull-request:
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
if: needs.build.outputs.run == 'true'
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download update
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: engine-update
|
||||
path: ${{ runner.temp }}/engine-update
|
||||
|
||||
- name: Apply update
|
||||
id: apply
|
||||
env:
|
||||
UPDATE: ${{ runner.temp }}/engine-update
|
||||
run: |
|
||||
set -euo pipefail
|
||||
rm -rf vendor/bentopdf-pdfium vendor/bentopdf-viewer
|
||||
mkdir -p vendor
|
||||
cp -R "$UPDATE/vendor/bentopdf-pdfium" "$UPDATE/vendor/bentopdf-viewer" vendor/
|
||||
cp "$UPDATE/package.json" "$UPDATE/package-lock.json" .
|
||||
{
|
||||
echo 'checksums<<EOF'
|
||||
sha256sum vendor/bentopdf-pdfium/*.tgz vendor/bentopdf-viewer/*.tgz
|
||||
echo 'EOF'
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c # v6.1.0
|
||||
with:
|
||||
commit-message: 'build(deps): bump PDF engine and viewer to ${{ needs.build.outputs.version }}'
|
||||
title: 'build(deps): bump PDF engine and viewer to ${{ needs.build.outputs.version }}'
|
||||
body: |
|
||||
Both vendored packages built from one clone of the viewer fork at
|
||||
`${{ needs.build.outputs.version }}`, so the text editor and the
|
||||
PDF editor run the same engine.
|
||||
|
||||
- `bentopdf-pdfium` — the engine wasm, packed from the fork's published `src/vendor`
|
||||
- `bentopdf-viewer` — the snippet bundle, packed **without** `dist/pdfium.wasm`
|
||||
|
||||
The viewer loads the shared engine through `EmbedPDF.init({ wasmUrl })`.
|
||||
CI verified a single wasm on disk, typecheck, and the test suite.
|
||||
|
||||
Built in a read-only job. Tarball checksums:
|
||||
|
||||
```
|
||||
${{ steps.apply.outputs.checksums }}
|
||||
```
|
||||
branch: chore/update-pdf-engine
|
||||
delete-branch: true
|
||||
@@ -1,141 +0,0 @@
|
||||
name: Update EmbedPDF Snippet
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
update-snippet:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Read current upstream version marker
|
||||
id: current-version
|
||||
run: |
|
||||
if [ -f vendor/embedpdf/.upstream-version ]; then
|
||||
CUR=$(cat vendor/embedpdf/.upstream-version)
|
||||
else
|
||||
CUR=""
|
||||
fi
|
||||
echo "version=$CUR" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Read latest upstream version (@embedpdf/core)
|
||||
id: upstream-version
|
||||
run: |
|
||||
LATEST=$(npm view @embedpdf/core version)
|
||||
echo "version=$LATEST" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Should update?
|
||||
id: gate
|
||||
run: |
|
||||
if [ "${{ steps.upstream-version.outputs.version }}" = "${{ steps.current-version.outputs.version }}" ]; then
|
||||
echo "run=false" >> "$GITHUB_OUTPUT"
|
||||
echo "No upstream version change detected."
|
||||
else
|
||||
echo "run=true" >> "$GITHUB_OUTPUT"
|
||||
echo "Updating from '${{ steps.current-version.outputs.version }}' to '${{ steps.upstream-version.outputs.version }}'"
|
||||
fi
|
||||
|
||||
- name: Enable corepack (pnpm)
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
run: corepack enable
|
||||
|
||||
- name: Prepare workspace
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
run: |
|
||||
mkdir -p vendor/embedpdf
|
||||
npm config set cache ./\.npm-cache
|
||||
|
||||
- name: Clone upstream embed-pdf-viewer
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
run: git clone --depth 1 --branch main https://github.com/embedpdf/embed-pdf-viewer ./_upstream/embed-pdf-viewer
|
||||
|
||||
- name: Setup Node
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
cache: npm
|
||||
|
||||
- name: Install upstream deps
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
working-directory: ./_upstream/embed-pdf-viewer
|
||||
run: pnpm install --no-frozen-lockfile
|
||||
|
||||
- name: Build snippet
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
working-directory: ./_upstream/embed-pdf-viewer
|
||||
run: pnpm run build:snippet
|
||||
|
||||
- name: Pack snippet tarball
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
working-directory: ./_upstream/embed-pdf-viewer
|
||||
run: |
|
||||
npm pack ./viewers/snippet --pack-destination ../../vendor/embedpdf
|
||||
ls -l ../../vendor/embedpdf
|
||||
|
||||
- name: Sanitize tarball (rename pkg and pin deps)
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
env:
|
||||
UPSTREAM_VERSION: ${{ steps.upstream-version.outputs.version }}
|
||||
run: |
|
||||
TARBALL=$(ls vendor/embedpdf/*.tgz | sort | tail -n1)
|
||||
TMP=$(mktemp -d)
|
||||
tar -xzf "$TARBALL" -C "$TMP"
|
||||
PKG="$TMP/package/package.json"
|
||||
PKG="$PKG" node - <<'NODE'
|
||||
const fs = require("fs");
|
||||
const path = process.env.PKG;
|
||||
const ver = process.env.UPSTREAM_VERSION || "1.4.1";
|
||||
const pkg = JSON.parse(fs.readFileSync(path, "utf8"));
|
||||
pkg.name = "embedpdf-snippet";
|
||||
pkg.dependencies = pkg.dependencies || {};
|
||||
for (const k of Object.keys(pkg.dependencies)) {
|
||||
if (k.startsWith("@embedpdf/")) pkg.dependencies[k] = `^${ver}`;
|
||||
if (k === "preact") pkg.dependencies[k] = "^10.17.0";
|
||||
}
|
||||
fs.writeFileSync(path, JSON.stringify(pkg, null, 2) + "\n");
|
||||
NODE
|
||||
NEW=vendor/embedpdf/embedpdf-snippet-${UPSTREAM_VERSION}.tgz
|
||||
tar -czf "$NEW" -C "$TMP" package
|
||||
# Remove any older snippet tarballs, keep only the new one
|
||||
find vendor/embedpdf -maxdepth 1 -name 'embedpdf-snippet-*.tgz' ! -name "$(basename "$NEW")" -delete
|
||||
rm -rf "$TMP"
|
||||
ls -l vendor/embedpdf
|
||||
|
||||
- name: Update package.json dependency path
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
run: |
|
||||
TARBALL=$(ls vendor/embedpdf/embedpdf-snippet-*.tgz | sort | tail -n1)
|
||||
node -e "const fs=require('fs');const pkg=require('./package.json');const tar=process.argv[1];pkg.dependencies['embedpdf-snippet']='file:'+tar;fs.writeFileSync('package.json',JSON.stringify(pkg,null,2)+'\n');" "$TARBALL"
|
||||
|
||||
- name: Refresh lockfile
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
run: npm install --package-lock-only --ignore-scripts
|
||||
|
||||
- name: Write upstream version marker
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
run: |
|
||||
echo "${{ steps.upstream-version.outputs.version }}" > vendor/embedpdf/.upstream-version
|
||||
|
||||
- name: Cleanup upstream clone
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
run: rm -rf ./_upstream
|
||||
|
||||
- name: Create Pull Request
|
||||
if: steps.gate.outputs.run == 'true'
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
with:
|
||||
commit-message: "build(deps): bump embedpdf-snippet from ${{ steps.current-version.outputs.version }} to ${{ steps.upstream-version.outputs.version }}"
|
||||
title: "build(deps): bump embedpdf-snippet from ${{ steps.current-version.outputs.version }} to ${{ steps.upstream-version.outputs.version }}"
|
||||
body: |
|
||||
- Build snippet from upstream embed-pdf-viewer via `npm run build:snippet`
|
||||
- Pack tarball into `vendor/embedpdf/` and point dependency to it
|
||||
- Refresh package-lock.json
|
||||
branch: chore/update-embedpdf-snippet
|
||||
delete-branch: true
|
||||
+5
-2
@@ -46,8 +46,11 @@ codeql-results.csv
|
||||
libreoffice-wasm-package
|
||||
|
||||
# helm chart
|
||||
bentopdf-*.tgz
|
||||
/bentopdf-*.tgz
|
||||
|
||||
# test
|
||||
dist-test
|
||||
test
|
||||
test
|
||||
# Sibling checkouts of the engine/viewer forks
|
||||
bentopdf-pdfium-viewer/
|
||||
bentopdf-pymupdf-wasm/
|
||||
|
||||
@@ -12,8 +12,14 @@ Header always set Referrer-Policy "strict-origin-when-cross-origin"
|
||||
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
|
||||
Header always set Cross-Origin-Opener-Policy "same-origin"
|
||||
Header always set Cross-Origin-Embedder-Policy "require-corp"
|
||||
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'wasm-unsafe-eval' 'unsafe-eval' blob: https://cdn.jsdelivr.net/npm/@bentopdf/[email protected]/ https://cdn.jsdelivr.net/npm/@bentopdf/[email protected]/assets/ https://cdn.jsdelivr.net/npm/[email protected]/dist/ https://cdn.jsdelivr.net/npm/[email protected]/dist/ https://cdn.jsdelivr.net/npm/[email protected]/; worker-src 'self' blob:; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: blob: https:; font-src 'self' data: https://fonts.gstatic.com https://rawcdn.githack.com; connect-src 'self' blob: https://api.github.com https://fonts.gstatic.com https://cdn.jsdelivr.net https://bentopdf-cors-proxy.bentopdf.workers.dev https://rawcdn.githack.com; object-src 'none'; base-uri 'self'; frame-src 'self' blob:; frame-ancestors 'self'; form-action 'self'"
|
||||
</IfModule>
|
||||
|
||||
# Block source maps from being served
|
||||
<FilesMatch "\.map$">
|
||||
Require all denied
|
||||
</FilesMatch>
|
||||
|
||||
# ============================================
|
||||
# 2. BROWSER CACHING
|
||||
# ============================================
|
||||
@@ -93,7 +99,7 @@ RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
|
||||
|
||||
# Remove trailing slash (except for language root directories)
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteCond %{REQUEST_URI} !^/(de|es|zh|zh-TW|vi|it|id|tr|fr|pt)/$
|
||||
RewriteCond %{REQUEST_URI} !^/(ar|be|da|de|es|fr|id|it|ja|ko|nl|pl|pt|ru|sk|sv|tr|uk|vi|zh|zh-TW)/$
|
||||
RewriteCond %{REQUEST_URI} (.+)/$
|
||||
RewriteRule ^ %1 [R=301,L]
|
||||
|
||||
@@ -111,11 +117,11 @@ RewriteRule ^en/(.+)$ /$1 [R=301,L]
|
||||
|
||||
# Language prefix root (e.g., /de/ -> /de/index.html)
|
||||
RewriteCond %{DOCUMENT_ROOT}/$1/index.html -f
|
||||
RewriteRule ^(de|es|zh|zh-TW|vi|it|id|tr|fr|pt)/?$ /$1/index.html [L]
|
||||
RewriteRule ^(ar|be|da|de|es|fr|id|it|ja|ko|nl|pl|pt|ru|sk|sv|tr|uk|vi|zh|zh-TW)/?$ /$1/index.html [L]
|
||||
|
||||
# Language prefix with path (e.g., /de/merge-pdf -> /de/merge-pdf.html)
|
||||
RewriteCond %{DOCUMENT_ROOT}/$1/$2.html -f
|
||||
RewriteRule ^(de|es|zh|zh-TW|vi|it|id|tr|fr|pt)/([^/]+)/?$ /$1/$2.html [L]
|
||||
RewriteRule ^(ar|be|da|de|es|fr|id|it|ja|ko|nl|pl|pt|ru|sk|sv|tr|uk|vi|zh|zh-TW)/([^/]+)/?$ /$1/$2.html [L]
|
||||
|
||||
# ============================================
|
||||
# 5.5. DOCS ROUTING (VitePress)
|
||||
|
||||
@@ -1,2 +1,7 @@
|
||||
# Handlebars partials with template syntax inside HTML attributes
|
||||
src/partials/footer.html
|
||||
|
||||
blog/posts/
|
||||
|
||||
public/pdfjs-viewer/
|
||||
public/pdfjs-annotation-viewer/
|
||||
|
||||
+4
-2
@@ -1,3 +1,5 @@
|
||||
# Dockerfile.nonroot intentionally starts as root to support PUID/PGID (LSIO pattern).
|
||||
# The entrypoint.sh creates the user at runtime and drops privileges via su-exec.
|
||||
DS-0002
|
||||
|
||||
KSV-0125
|
||||
|
||||
DS-0013
|
||||
|
||||
+1
-1
@@ -81,7 +81,7 @@ When submitting code contributions, please use our [pull request template](.gith
|
||||
|
||||
```bash
|
||||
git clone https://github.com/alam00000/bentopdf.git
|
||||
cd bento-pdf
|
||||
cd bentopdf
|
||||
npm install
|
||||
```
|
||||
|
||||
|
||||
+3
-1
@@ -3,7 +3,7 @@
|
||||
ARG BASE_URL=
|
||||
|
||||
# Build stage
|
||||
FROM public.ecr.aws/docker/library/node:20-alpine AS builder
|
||||
FROM mirror.gcr.io/library/node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
@@ -19,6 +19,8 @@ COPY . .
|
||||
# Pass SIMPLE_MODE environment variable if provided
|
||||
ARG SIMPLE_MODE=false
|
||||
ENV SIMPLE_MODE=$SIMPLE_MODE
|
||||
ARG DISABLE_GITHUB_STARS=false
|
||||
ENV DISABLE_GITHUB_STARS=$DISABLE_GITHUB_STARS
|
||||
ARG COMPRESSION_MODE=all
|
||||
ENV COMPRESSION_MODE=$COMPRESSION_MODE
|
||||
|
||||
|
||||
+3
-1
@@ -5,7 +5,7 @@
|
||||
ARG BASE_URL=
|
||||
|
||||
# Build stage (identical to main Dockerfile)
|
||||
FROM public.ecr.aws/docker/library/node:20-alpine AS builder
|
||||
FROM mirror.gcr.io/library/node:20-alpine AS builder
|
||||
WORKDIR /app
|
||||
COPY package*.json ./
|
||||
COPY vendor ./vendor
|
||||
@@ -19,6 +19,8 @@ COPY . .
|
||||
|
||||
ARG SIMPLE_MODE=false
|
||||
ENV SIMPLE_MODE=$SIMPLE_MODE
|
||||
ARG DISABLE_GITHUB_STARS=false
|
||||
ENV DISABLE_GITHUB_STARS=$DISABLE_GITHUB_STARS
|
||||
ARG COMPRESSION_MODE=all
|
||||
ENV COMPRESSION_MODE=$COMPRESSION_MODE
|
||||
|
||||
|
||||
@@ -1,22 +1,23 @@
|
||||
<p align="center"><img src="public/images/favicon-no-bg.svg" width="80"></p>
|
||||
<h1 align="center">BentoPDF</h1>
|
||||
<p align="center"><sub>Supported by</sub></p>
|
||||
<p align="center">
|
||||
<a href="https://vercel.com/open-source-program">
|
||||
<img alt="Vercel OSS Program" src="https://vercel.com/oss/program-badge-2026.svg" height="30" />
|
||||
</a>
|
||||
|
||||
<a href="https://www.digitalocean.com/?refcode=d93c189ef6d0&utm_campaign=Referral_Invite&utm_medium=Referral_Program&utm_source=badge">
|
||||
<img src="https://web-platforms.sfo2.cdn.digitaloceanspaces.com/WWW/Badge%203.svg" alt="DigitalOcean Referral Badge">
|
||||
<img src="https://web-platforms.sfo2.cdn.digitaloceanspaces.com/WWW/Badge%203.svg" alt="DigitalOcean Referral Badge" height="44">
|
||||
</a>
|
||||
</p>
|
||||
|
||||
**BentoPDF** is a powerful, privacy-first, client-side PDF toolkit that is self hostable and allows you to manipulate, edit, merge, and process PDF files directly in your browser. No server-side processing is required, ensuring your files remain secure and private.
|
||||
**BentoPDF** is a powerful, privacy-first, client-side PDF toolkit that is self-hostable and allows you to manipulate, edit, merge, and process PDF files directly in your browser. No server-side processing is required, ensuring your files remain secure and private.
|
||||
|
||||
[](https://github.com/alam00000/bentopdf/pkgs/container/bentopdf) [](https://ko-fi.com/alio01) 
|
||||
[](https://github.com/alam00000/bentopdf/pkgs/container/bentopdf-simple) [](https://ko-fi.com/alio01) 
|
||||
[](https://github.com/sponsors/alam00000)
|
||||
|
||||

|
||||
|
||||
### FOSS Hack 2026
|
||||
|
||||
[](https://drive.google.com/file/d/14Vf62PvHiuf1RKFKtMlAzpbf4QQPLpRF/view?usp=sharing)
|
||||
|
||||
---
|
||||
|
||||
## Table of Contents
|
||||
@@ -33,6 +34,7 @@
|
||||
- [Convert to PDF](#convert-to-pdf)
|
||||
- [Convert from PDF](#convert-from-pdf)
|
||||
- [Secure & Optimize PDFs](#secure--optimize-pdfs)
|
||||
- [Other Products](#-other-products)
|
||||
- [Translations](#-translations)
|
||||
- [Getting Started](#-getting-started)
|
||||
- [Prerequisites](#prerequisites)
|
||||
@@ -45,6 +47,7 @@
|
||||
- [Commercial Build](#-commercial-build)
|
||||
- [Custom Branding](#-custom-branding)
|
||||
- [Disabling Specific Tools](#-disabling-specific-tools)
|
||||
- [Disabling the GitHub Star Counter](#-disabling-the-github-star-counter)
|
||||
- [WASM Configuration](#wasm-configuration)
|
||||
- [Air-Gapped / Offline Deployment](#air-gapped--offline-deployment)
|
||||
- [Security Features](#-security-features)
|
||||
@@ -116,7 +119,7 @@ BentoPDF does **not** bundle AGPL-licensed processing libraries in its source co
|
||||
|
||||
## ⭐ Stargazers over time
|
||||
|
||||
[](https://star-history.com/#alam00000/bentopdf&Date)
|
||||
[](https://github.com/alam00000/bentopdf/stargazers)
|
||||
|
||||
---
|
||||
|
||||
@@ -135,7 +138,7 @@ We're incredibly grateful to all our sponsors and supporters who help keep Bento
|
||||
## ✨ Why BentoPDF?
|
||||
|
||||
- **Privacy First**: All processing happens in your browser. Your files are never uploaded to a server, guaranteeing 100% privacy.
|
||||
- **No Limits**: Manipulate as many files as you want, as often you want. There are no restrictions or upload limits.
|
||||
- **No Limits**: Manipulate as many files as you want, as often as you want. There are no restrictions or upload limits.
|
||||
- **High Performance**: Built with modern web technologies, BentoPDF is fast and efficient, handling even large PDF files with ease.
|
||||
- **Completely Free**: BentoPDF is a free and open-source tool for everyone.
|
||||
|
||||
@@ -147,37 +150,38 @@ BentoPDF offers a comprehensive suite of tools to handle all your PDF needs.
|
||||
|
||||
### Organize & Manage PDFs
|
||||
|
||||
| Tool Name | Description |
|
||||
| :--------------------------- | :------------------------------------------------------------------------------------------------------ |
|
||||
| **Merge PDFs** | Combine multiple PDF files into one. Preserves Bookmarks. |
|
||||
| **Split PDFs** | Extract specific pages or divide a document into smaller files. |
|
||||
| **Organize Pages** | Reorder, duplicate, or delete pages with a simple drag-and-drop interface. |
|
||||
| **Extract Pages** | Save a specific range of pages as a new PDF. |
|
||||
| **Delete Pages** | Remove unwanted pages from your document. |
|
||||
| **Rotate PDF** | Rotate individual or all pages in a document. |
|
||||
| **Rotate by Custom Degrees** | Rotate pages by any custom angle. |
|
||||
| **N-Up PDF** | Combine multiple pages onto a single page. |
|
||||
| **View PDF** | A powerful, integrated PDF viewer. |
|
||||
| **Alternate & Mix Pages** | Merge pages by alternating pages from each PDF. Preserves Bookmarks. |
|
||||
| **Posterize PDF** | Split a PDF into multiple smaller pages for print. |
|
||||
| **PDF Multi Tool** | Merge, Split, Organize, Delete, Rotate, Add Blank Pages, Extract and Duplicate in an unified interface. |
|
||||
| **PDF Booklet** | Rearrange pages for double-sided booklet printing. Fold and staple to create a booklet. |
|
||||
| **Add Attachments** | Embed one or more files into your PDF. |
|
||||
| **Extract Attachments** | Extract all embedded files from PDF(s) as a ZIP. |
|
||||
| **Edit Attachments** | View or remove attachments in your PDF. |
|
||||
| **Divide Pages** | Divide pages horizontally or vertically. |
|
||||
| **Combine to Single Page** | Stitch all pages into one continuous scroll. |
|
||||
| **Add Blank Page** | Insert an empty page anywhere in your PDF. |
|
||||
| **Reverse Pages** | Flip the order of all pages in your document. |
|
||||
| **View Metadata** | Inspect the hidden properties of your PDF. |
|
||||
| **PDFs to ZIP** | Package multiple PDF files into a ZIP archive. |
|
||||
| **Compare PDFs** | Compare two PDFs side by side. |
|
||||
| Tool Name | Description |
|
||||
| :--------------------------- | :----------------------------------------------------------------------------------------------------- |
|
||||
| **Merge PDFs** | Combine multiple PDF files into one. Preserves Bookmarks. |
|
||||
| **Split PDFs** | Extract specific pages or divide a document into smaller files. |
|
||||
| **Organize Pages** | Reorder, duplicate, or delete pages with a simple drag-and-drop interface. |
|
||||
| **Extract Pages** | Save a specific range of pages as a new PDF. |
|
||||
| **Delete Pages** | Remove unwanted pages from your document. |
|
||||
| **Rotate PDF** | Rotate individual or all pages in a document. |
|
||||
| **Rotate by Custom Degrees** | Rotate pages by any custom angle. |
|
||||
| **N-Up PDF** | Combine multiple pages onto a single page. |
|
||||
| **View PDF** | A powerful, integrated PDF viewer. |
|
||||
| **Alternate & Mix Pages** | Merge pages by alternating pages from each PDF. Preserves Bookmarks. |
|
||||
| **Posterize PDF** | Split a PDF into multiple smaller pages for print. |
|
||||
| **PDF Multi Tool** | Merge, Split, Organize, Delete, Rotate, Add Blank Pages, Extract and Duplicate in a unified interface. |
|
||||
| **PDF Booklet** | Rearrange pages for double-sided booklet printing. Fold and staple to create a booklet. |
|
||||
| **Add Attachments** | Embed one or more files into your PDF. |
|
||||
| **Extract Attachments** | Extract all embedded files from PDF(s) as a ZIP. |
|
||||
| **Edit Attachments** | View or remove attachments in your PDF. |
|
||||
| **Divide Pages** | Divide pages horizontally or vertically. |
|
||||
| **Combine to Single Page** | Stitch all pages into one continuous scroll. |
|
||||
| **Add Blank Page** | Insert an empty page anywhere in your PDF. |
|
||||
| **Reverse Pages** | Flip the order of all pages in your document. |
|
||||
| **View Metadata** | Inspect the hidden properties of your PDF. |
|
||||
| **PDFs to ZIP** | Package multiple PDF files into a ZIP archive. |
|
||||
| **Compare PDFs** | Compare two PDFs side by side. |
|
||||
|
||||
### Edit & Modify PDFs
|
||||
|
||||
| Tool Name | Description |
|
||||
| :------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **PDF Editor** | Annotate, highlight, redact, comment, add shapes/images, search, and view PDFs. |
|
||||
| **Edit PDF Text** | Edit existing text directly in your PDF. Reuses the document's embedded fonts and keeps the rest of the page untouched. |
|
||||
| **Create Fillable Forms** | Create professional fillable PDF forms with text fields, checkboxes, dropdowns, radio buttons, signatures, and more. Fully compliant with PDF standards for compatibility with all PDF viewers. |
|
||||
| **PDF Form Filler** | Fill in forms directly in the browser. Also supports XFA forms. |
|
||||
| **Add Page Numbers** | Easily add page numbers with customizable formatting. |
|
||||
@@ -336,7 +340,7 @@ Open your browser at: http://localhost:3000
|
||||
> - **Self-Hosted build** — `ghcr.io/alam00000/bentopdf-simple:latest`. Every PDF tool the public site has, **without** the BentoPDF marketing (no hero, FAQ, testimonials, footer). Use this for internal/team/organization deployments. It is **not** a feature-reduced lite version.
|
||||
> - **Commercial build** — `ghcr.io/alam00000/bentopdf:latest`. The full marketing site, used by bentopdf.com itself and by commercial license holders running public-facing deployments. Includes hero, FAQ, testimonials, and footer.
|
||||
>
|
||||
> If in doubt: pull the Self Hosted build.
|
||||
> If in doubt: pull the Self-Hosted build.
|
||||
|
||||
<details>
|
||||
<summary><b>Alternative: Using Docker Hub or Podman</b></summary>
|
||||
@@ -688,7 +692,7 @@ BentoPDF can also be hosted from a subdirectory (e.g., `example.com/tools/bentop
|
||||
```bash
|
||||
|
||||
# Example:
|
||||
# 1. Build the app with the specific BASE_URL. BASE_URL must have a trailing and leading slash. The BASE_URL can be any url of your choice. Here we are using /tools/bentopdf/ as an example.
|
||||
# 1. Build the app with the specific BASE_URL. BASE_URL must have a trailing and leading slash. The BASE_URL can be any URL of your choice. Here we are using /tools/bentopdf/ as an example.
|
||||
|
||||
BASE_URL=/tools/bentopdf/ npm run build
|
||||
|
||||
@@ -810,7 +814,7 @@ For detailed Quadlet configuration, see [Self-Hosting Docker Guide](https://bent
|
||||
|
||||
### 🏢 Self-Hosted build (Simple Mode)
|
||||
|
||||
The Self-Hosted build (the `bentopdf-simple` image, also called Simple Mode) is **functionally identical** to the Commercial build. Every PDF tool is present and behaves the same. It just hides the marketing that only makes sense on bentopdf.com itself or on a commercial public-facing deployment. **It is not a feature reduced or "lite" version.**
|
||||
The Self-Hosted build (the `bentopdf-simple` image, also called Simple Mode) is **functionally identical** to the Commercial build. Every PDF tool is present and behaves the same. It just hides the marketing that only makes sense on bentopdf.com itself or on a commercial public-facing deployment. **It is not a feature-reduced or "lite" version.**
|
||||
|
||||
**What the Self-Hosted build hides** (cosmetic only, no PDF features are removed):
|
||||
|
||||
@@ -822,7 +826,7 @@ The Self-Hosted build (the `bentopdf-simple` image, also called Simple Mode) is
|
||||
- All PDF tools (merge, split, edit, sign, OCR, Office conversion, every other tool)
|
||||
- Custom branding support, all build-time and runtime config
|
||||
|
||||
The Commercial build (`ghcr.io/alam00000/bentopdf:latest`) is what powers bentopdf.com itself and is used by commercial license holders running public facing deployments. It adds the hero, FAQ, testimonials, and footer that wouldn't make sense on an internal tool.
|
||||
The Commercial build (`ghcr.io/alam00000/bentopdf:latest`) is what powers bentopdf.com itself and is used by commercial license holders running public-facing deployments. It adds the hero, FAQ, testimonials, and footer that wouldn't make sense on an internal tool.
|
||||
|
||||
If you're self-hosting BentoPDF for your team, organization, or as an internal tool, pull `ghcr.io/alam00000/bentopdf-simple:latest`. For more details, see [SIMPLE_MODE.md](SIMPLE_MODE.md).
|
||||
|
||||
@@ -938,6 +942,24 @@ You can also disable specific features inside the PDF Editor (e.g., redaction, f
|
||||
|
||||
For the full list of editor categories, see the [self-hosting docs](https://bentopdf.com/docs/self-hosting/docker#disabling-editor-features).
|
||||
|
||||
### 🔕 Disabling the GitHub Star Counter
|
||||
|
||||
The navbar shows a live GitHub star count, fetched from `api.github.com` on page load. The only external request that isn't serving a PDF feature. Self-hosters who want zero non-essential network calls can disable it at build time. This removes the fetch code from the bundle entirely and drops `api.github.com` from the Content-Security-Policy.
|
||||
|
||||
Simple Mode builds (`bentopdf-simple`) always skip the star counter — this flag is only needed on the Commercial build or custom full builds.
|
||||
|
||||
**Docker:**
|
||||
|
||||
```bash
|
||||
docker build --build-arg DISABLE_GITHUB_STARS=true -t bentopdf .
|
||||
```
|
||||
|
||||
**Building from source:**
|
||||
|
||||
```bash
|
||||
DISABLE_GITHUB_STARS=true npm run build
|
||||
```
|
||||
|
||||
### 🔒 Security Features
|
||||
|
||||
BentoPDF runs as a non-root user using nginx-unprivileged for enhanced security:
|
||||
@@ -1203,16 +1225,20 @@ BentoPDF was originally built using **HTML**, **CSS**, and **vanilla JavaScript*
|
||||
|
||||
---
|
||||
|
||||
## 📦 Other Products
|
||||
|
||||
| Product | Description | Links |
|
||||
| :----------------- | :------------------------------------------------------------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------- |
|
||||
| **Kura** | PDF standards and preflight engine. Converts to every PDF/A level, PDF/UA, PDF/X, PDF/E and PDF/VT, and can perform preflight checks. | [Website](https://kura.bentopdf.com) · [GitHub](https://github.com/alam00000/bentopdf-kura) |
|
||||
| **Hyper Compress** | The best open source PDF compression engine. | [Website](https://hyper.bentopdf.com) · [GitHub](https://github.com/alam00000/bentopdf-hyper-compress) |
|
||||
|
||||
---
|
||||
|
||||
## 🗺️ Roadmap
|
||||
|
||||
### Planned Features:
|
||||
|
||||
- **HTML to PDF**: Convert HTML files or web pages into PDF documents.
|
||||
- **Markdown to PDF**: Enhanced support for converting `.md` files to PDF.
|
||||
- **Convert to PDF/A**: Convert PDFs to the PDF/A archival format.
|
||||
- **Edit PDF Content**: Directly edit text and other content within your PDF.
|
||||
- **PDF to Office**: Converts PDF files into editable Word, Excel, and PowerPoint formats.
|
||||
- **Office to PDF**: Converts Word, Excel, and PowerPoint documents into optimized PDFs.
|
||||
|
||||
Contributions and discussions on the roadmap are welcome! Join the conversation via [Discord](https://discord.gg/Bgq3Ay3f2w).
|
||||
|
||||
|
||||
+19
-8
@@ -1,18 +1,18 @@
|
||||
# Hosting BentoPDF as a static website
|
||||
|
||||
As an alternative to runnning BenotPDF locally or in a Docker container, you can very easily host it as a set of static web pages. Here are a few examples:
|
||||
As an alternative to running BentoPDF locally or in a Docker container, you can easily host it as a set of static web pages. Here are a few examples:
|
||||
|
||||
## Netlify
|
||||
|
||||
### Netlify - static deployment
|
||||
|
||||
One of simplest ways to host BentoPDF is to create a project at [Netlify](https://www.netlify.com/) and create a static deployment. You can accomplish this by first downloading the pre-built distribution file from our [GitHub releases](https://github.com/alam00000/bentopdf/releases). Each release includes a `dist-{version}.zip` file that contains all necessary files for self-hosting.
|
||||
One of the simplest ways to host BentoPDF is to create a project at [Netlify](https://www.netlify.com/) and create a static deployment. You can accomplish this by first downloading the pre-built distribution file from our [GitHub releases](https://github.com/alam00000/bentopdf/releases). Each release includes a `dist-{version}.zip` file that contains all necessary files for self-hosting.
|
||||
|
||||
1. Go to [BentoPDF Releases](https://github.com/alam00000/bentopdf/releases)
|
||||
2. Download the latest `dist-{version}.zip` file
|
||||
3. Next, if you have not already done so, create a Netlify account and log in.
|
||||
4. From your Netlify projects page, add a new project and select "Deploy manually".
|
||||
5. Drag and drop to upload the Bentopdf zip file you downloaded in step 3.
|
||||
5. Drag and drop to upload the BentoPDF zip file you downloaded in step 2.
|
||||
6. Your BentoPDF deployment should now be working! Optionally, you can go into Project Configuration and change the project name.
|
||||
|
||||
When a new BentoPDF release becomes available, you will need to repeat steps 1-3, then go into "Deploys" and upload the new release.
|
||||
@@ -21,7 +21,7 @@ When a new BentoPDF release becomes available, you will need to repeat steps 1-3
|
||||
|
||||
Alternatively, you can configure a Netlify project to automatically deploy whenever your BentoPDF is updated.
|
||||
|
||||
1. If you have not done so already, create a fork of BentoPDF into your own Github account.
|
||||
1. If you have not done so already, create a fork of BentoPDF into your own GitHub account.
|
||||
2. If you have not already done so, create a Netlify account and log in.
|
||||
3. From your Netlify projects page, add a new project and select 'Import an existing project'.
|
||||
4. Select the GitHub button, authorize Netlify, then choose where to install the integration. You can choose 'All repositories' or 'Only select repositories' and choose your BentoPDF fork.
|
||||
@@ -36,7 +36,7 @@ If you want to use BentoPDF's simple mode, go into Deploy Settings, then Environ
|
||||
|
||||
Vercel provides similar services to Netlify dynamic hosting.
|
||||
|
||||
1. If you have not done so already, create a fork of BentoPDF into your own Github account.
|
||||
1. If you have not done so already, create a fork of BentoPDF into your own GitHub account.
|
||||
2. If you have not already done so, create a Vercel account and log in.
|
||||
3. From your Vercel Overview page, select 'Add new project'
|
||||
4. Under 'Import Git Repository' and then choose 'Add GitHub Account'. Follow the prompts to authorize Vercel integration. You can choose 'All repositories' or 'Only select repositories' and choose your BentoPDF fork.
|
||||
@@ -44,15 +44,15 @@ Vercel provides similar services to Netlify dynamic hosting.
|
||||
6. Under 'Framework Preset', select 'Vite' and save the settings.
|
||||
7. The Vercel build & deploy process will kick off. Once it finishes, you can click on the provided link to view your deployment of BentoPDF.
|
||||
|
||||
Whenever the BentoPDF source code is updated, you can sync the changes into your repo. This will kick off a new build and deploy within BentoPDF.
|
||||
Whenever the BentoPDF source code is updated, you can sync the changes into your repo. This will kick off a new build and deploy within Vercel.
|
||||
|
||||
If you want to use BentoPDF's simple mode, go into Project Settings, then Environment Variables, and Create a new variable. Add `SIMPLE_MODE` and set it to `true`. You will need to redeploy to get this to take effect.
|
||||
|
||||
## GitHub Pages
|
||||
|
||||
You can also host your own instance of BentoPDF using GitHub pages. An advantage of this over the other options is you are able to do everything in GitHub without any third party service.
|
||||
You can also host your own instance of BentoPDF using GitHub Pages. An advantage of this over the other options is you are able to do everything in GitHub without any third-party service.
|
||||
|
||||
1. If you have not done so already, create a fork of BentoPDF into your own Github account.
|
||||
1. If you have not done so already, create a fork of BentoPDF into your own GitHub account.
|
||||
2. From your fork, go to `Settings->Pages`, and change the 'Source' to 'GitHub Actions'
|
||||
3. Go to `Settings->Secrets and Variables > Actions`, then select 'Variables', and add the repository variable `BASE_URL`. Set the value to `/bentopdf`. _If you've renamed the repo to something other than bentopdf, put that here_.
|
||||
4. Go to `Actions` in the top menu, and select 'I understand' to enable Actions
|
||||
@@ -62,6 +62,17 @@ When the build completes, you can find the website at `https://[your-github-user
|
||||
|
||||
If/when you merge changes from the source BentoPDF repository, the build and deploy action will automatically be kicked off and the new version will be automatically deployed to GitHub Pages.
|
||||
|
||||
> **Note:** GitHub Pages cannot set custom response headers, so a GitHub Pages deployment is served without BentoPDF's Content-Security-Policy and other security headers. If you need them, use one of the other hosts below or put a proxy or CDN that can add headers in front of your Pages site.
|
||||
|
||||
## Security headers
|
||||
|
||||
BentoPDF ships a Content-Security-Policy and other security headers for each static host:
|
||||
|
||||
- **Netlify and Cloudflare Pages** read `_headers` from the deployed folder. The build copies `public/_headers` into `dist/_headers`, and `scripts/generate-security-headers.mjs` regenerates both during `npm run build`, so any `VITE_WASM_*`, `VITE_TESSERACT_*`, `VITE_CORS_PROXY_URL` or `VITE_OCR_FONT_BASE_URL` values you set at build time are allowed by the policy. The release `dist-{version}.zip` already contains it.
|
||||
- **Vercel** uses the `headers` block in `vercel.json`. It holds the default policy, so if you point the `VITE_*` URLs at your own servers, update the Content-Security-Policy there to match `public/_headers`.
|
||||
- **`npx serve`** reads `serve.json` from the folder it serves. To use the repository's `serve.json` with the build output, run `npx serve dist -c ../serve.json`.
|
||||
- **GitHub Pages** cannot set headers (see the note above).
|
||||
|
||||
## SEO and search engine indexing
|
||||
|
||||
By default, every self-hosted BentoPDF build emits canonical URLs and an
|
||||
|
||||
+17
-3
@@ -33,6 +33,13 @@ BentoPDF uses **i18next** for internationalization (i18n). Currently supported l
|
||||
- **Traditional Chinese (Taiwan)** (`zh-TW`)
|
||||
- **Korean** (`ko`)
|
||||
- **Russian** (`ru`)
|
||||
- **Ukrainian** (`uk`)
|
||||
- **Slovak** (`sk`)
|
||||
- **Arabic** (`ar`)
|
||||
- **Dutch** (`nl`)
|
||||
- **Danish** (`da`)
|
||||
- **Swedish** (`sv`)
|
||||
- **Japanese** (`ja`)
|
||||
|
||||
The app automatically detects the language from the URL path:
|
||||
|
||||
@@ -393,7 +400,7 @@ Some strings contain HTML or special characters:
|
||||
|
||||
```json
|
||||
{
|
||||
"faq.analytics.answer": "We care about your privacy. BentoPDF does not track personal information. We use <a href=\"https://simpleanalytics.com\" class=\"text-indigo-400 hover:underline\" target=\"_blank\" rel=\"noopener noreferrer\">Simple Analytics</a> solely to see anonymous visit counts."
|
||||
"faq.analytics.answer": "No. BentoPDF does not track you at all. We do not use cookies, analytics, or any tracking scripts, not even on the live website at bentopdf.com. We never know who you are or what you do with the tools."
|
||||
}
|
||||
```
|
||||
|
||||
@@ -401,7 +408,7 @@ When translating, **keep the HTML tags intact**:
|
||||
|
||||
```json
|
||||
{
|
||||
"faq.analytics.answer": "Wir schätzen Ihre Privatsphäre. BentoPDF verfolgt keine persönlichen Informationen. Wir verwenden <a href=\"https://simpleanalytics.com\" class=\"text-indigo-400 hover:underline\" target=\"_blank\" rel=\"noopener noreferrer\">Simple Analytics</a> ausschließlich, um anonyme Besucherzahlen zu sehen."
|
||||
"faq.analytics.answer": "Nein. BentoPDF verfolgt Sie in keiner Weise. Wir verwenden keine Cookies, keine Analysetools und keine Tracking-Skripte – auch nicht auf der Live-Website bentopdf.com. Wir wissen nie, wer Sie sind oder was Sie mit den Tools tun."
|
||||
}
|
||||
```
|
||||
|
||||
@@ -603,8 +610,15 @@ Current translation coverage:
|
||||
| Traditional Chinese | `zh-TW` | ✅ Complete | Community |
|
||||
| Korean | `ko` | ✅ Complete | Community |
|
||||
| Russian | `ru` | ✅ Complete | Community |
|
||||
| Ukrainian | `uk` | ✅ Complete | Community |
|
||||
| Slovak | `sk` | ✅ Complete | Community |
|
||||
| Arabic | `ar` | ✅ Complete | Community |
|
||||
| Dutch | `nl` | ✅ Complete | Community |
|
||||
| Danish | `da` | ✅ Complete | Community |
|
||||
| Swedish | `sv` | ✅ Complete | Community |
|
||||
| Japanese | `ja` | ✅ Complete | Community |
|
||||
| Your Language | `??` | 🚧 In Progress | You? |
|
||||
|
||||
---
|
||||
|
||||
**Last Updated**: January 2026
|
||||
**Last Updated**: June 2026
|
||||
|
||||
+253
-192
@@ -5,7 +5,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<!-- Primary Meta Tags -->
|
||||
<title>About BentoPDF - Privacy-First Free PDF Tools | Our Mission</title>
|
||||
<title>About BentoPDF - Privacy-First Free PDF Tools | Our Story</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Learn about BentoPDF - 100% free, privacy-first PDF toolkit. All tools run in your browser, no uploads, no signup. Fast, secure, and forever free."
|
||||
@@ -51,6 +51,7 @@
|
||||
<meta name="twitter:site" content="@BentoPDF" />
|
||||
|
||||
<link href="/src/css/styles.css" rel="stylesheet" />
|
||||
<link href="/src/css/landing.css" rel="stylesheet" />
|
||||
|
||||
<!-- Web App Manifest -->
|
||||
<link rel="manifest" href="/site.webmanifest" />
|
||||
@@ -77,220 +78,267 @@
|
||||
<link rel="icon" href="/favicon.ico" sizes="32x32" />
|
||||
</head>
|
||||
|
||||
<body class="antialiased bg-gray-900 text-gray-300">
|
||||
<body class="lp antialiased">
|
||||
{{> navbar }}
|
||||
|
||||
<div id="app" class="min-h-screen container mx-auto p-4 md:p-8">
|
||||
<section id="about-hero" class="text-center py-16 md:py-24">
|
||||
<h1 class="text-3xl md:text-6xl font-bold text-white mb-4">
|
||||
<span data-i18n="about.hero.title"
|
||||
>We believe PDF tools should be</span
|
||||
>
|
||||
<span class="marker-slanted" data-i18n="about.hero.subtitle"
|
||||
>fast, private, and free.</span
|
||||
>
|
||||
</h1>
|
||||
<p
|
||||
class="text-lg md:text-xl text-gray-400"
|
||||
data-i18n="about.hero.noCompromises"
|
||||
>
|
||||
No compromises.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<div class="section-divider"></div>
|
||||
|
||||
<section id="mission-section" class="py-16 max-w-4xl mx-auto">
|
||||
<div class="text-center">
|
||||
<i
|
||||
data-lucide="rocket"
|
||||
class="w-16 h-16 text-indigo-400 mx-auto mb-6"
|
||||
></i>
|
||||
<h2
|
||||
class="text-3xl md:text-4xl font-bold text-white mb-4"
|
||||
data-i18n="about.mission.title"
|
||||
>
|
||||
Our Mission
|
||||
</h2>
|
||||
<p
|
||||
class="text-lg text-gray-400 leading-relaxed"
|
||||
data-i18n="about.mission.description"
|
||||
>
|
||||
To provide the most comprehensive PDF toolbox that respects your
|
||||
privacy and never asks for payment. We believe essential document
|
||||
tools should be accessible to everyone, everywhere, without
|
||||
barriers.
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div
|
||||
class="bg-gray-800 rounded-xl p-8 md:p-12 my-16 border border-gray-700"
|
||||
>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-12 items-center">
|
||||
<div class="text-center md:text-left">
|
||||
<span
|
||||
class="text-indigo-400 font-bold uppercase"
|
||||
data-i18n="about.philosophy.label"
|
||||
>Our Core Philosophy</span
|
||||
<div id="app">
|
||||
<section id="story-section" class="lp-sec lp-sec--first">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-story">
|
||||
<div class="lp-story-head">
|
||||
<h1 class="lp-h2">
|
||||
<span class="line">Hi, I'm Alam.</span>
|
||||
<span class="line dim">I build BentoPDF.</span>
|
||||
</h1>
|
||||
<div class="lp-story-by">
|
||||
<img
|
||||
class="lp-avatar"
|
||||
src="/images/author-alam.jpg"
|
||||
alt="Alam"
|
||||
width="44"
|
||||
height="44"
|
||||
/>
|
||||
<a
|
||||
href="https://github.com/alam00000"
|
||||
target="_blank"
|
||||
rel="me noopener noreferrer"
|
||||
>GitHub</a
|
||||
>
|
||||
<a
|
||||
href="https://www.linkedin.com/in/abdullah-alam01/"
|
||||
target="_blank"
|
||||
rel="me noopener noreferrer"
|
||||
>LinkedIn</a
|
||||
>
|
||||
<a
|
||||
href="https://x.com/alamdraws"
|
||||
target="_blank"
|
||||
rel="me noopener noreferrer"
|
||||
>X</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lp-story-body">
|
||||
<p>
|
||||
BentoPDF started off as just a simple internal tool I used for
|
||||
quickly merging and splitting PDFs.
|
||||
</p>
|
||||
<p>
|
||||
At some point, I decided to
|
||||
<a
|
||||
href="https://www.reddit.com/r/webdev/comments/1nr937y/i_made_bentopdf_a_privacy_first_pdf_toolkit_that/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>share it on Reddit</a
|
||||
>. Someone in the comments
|
||||
<a
|
||||
href="https://www.reddit.com/r/webdev/comments/1nr937y/comment/ngdeqby/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>asked if it was open source</a
|
||||
>. I thought, “Why not?” So a couple of weeks later, I
|
||||
<a
|
||||
href="https://github.com/alam00000/bentopdf"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>put the code on GitHub</a
|
||||
>.
|
||||
</p>
|
||||
<p>
|
||||
I posted it on
|
||||
<a
|
||||
href="https://www.reddit.com/r/selfhosted/comments/1o5borw/bentopdf_is_a_self_hostable_pdf_toolkit/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>r/selfhosted</a
|
||||
>
|
||||
the next day, and that's when things really started to take off.
|
||||
</p>
|
||||
<p>
|
||||
I honestly never thought BentoPDF would grow into what it is
|
||||
today. It started as a little tool I made for myself, and
|
||||
somehow it turned into a much bigger project used by people all
|
||||
over the world.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lp-grid lp-grid--4 lp-cross">
|
||||
<div class="lp-cell lp-stat lp-cell--accent lp-reveal">
|
||||
<b>15K+</b><span>GitHub stars</span>
|
||||
</div>
|
||||
<div class="lp-cell lp-stat lp-cell--white lp-reveal">
|
||||
<b>10M+</b><span>Downloads</span>
|
||||
</div>
|
||||
<div class="lp-cell lp-stat lp-cell--hatch lp-reveal">
|
||||
<b>1.3K+</b><span>Forks</span>
|
||||
</div>
|
||||
<a
|
||||
href="https://github.com/alam00000/bentopdf/graphs/contributors"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="lp-cell lp-stat lp-cell--raised lp-reveal lp-stat-link"
|
||||
>
|
||||
<h2
|
||||
class="text-3xl md:text-4xl font-bold text-white mt-2 mb-4"
|
||||
data-i18n="about.philosophy.title"
|
||||
>
|
||||
Privacy First. Always.
|
||||
</h2>
|
||||
<p
|
||||
class="text-gray-400 leading-relaxed"
|
||||
data-i18n="about.philosophy.description"
|
||||
>
|
||||
In an era where data is a commodity, we take a different approach.
|
||||
All processing for Bentopdf tools happens locally in your browser.
|
||||
This means your files never touch our servers, we never see your
|
||||
documents, and we don't track what you do. Your documents remain
|
||||
completely and unequivocally private. It's not just a feature;
|
||||
it's our foundation.
|
||||
<b>60+</b
|
||||
><span>Contributors <i data-lucide="arrow-up-right"></i></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="lp-story-outro">
|
||||
<p>
|
||||
I don't build BentoPDF alone anymore. More than 60 people have
|
||||
contributed code, translations and fixes, and thousands more have
|
||||
starred it, shared it, reported bugs and asked for features. Thank
|
||||
you.
|
||||
</p>
|
||||
<p>Enough about me. Here's more about BentoPDF.</p>
|
||||
</div>
|
||||
<div class="flex justify-center">
|
||||
<div class="relative w-48 h-48">
|
||||
<div
|
||||
class="absolute inset-0 bg-indigo-500 rounded-full opacity-20 animate-pulse"
|
||||
></div>
|
||||
<div
|
||||
class="absolute inset-4 bg-indigo-500 rounded-full opacity-30 animate-pulse delay-500"
|
||||
></div>
|
||||
<i
|
||||
data-lucide="shield-check"
|
||||
class="w-48 h-48 text-indigo-400"
|
||||
></i>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="mission-section" class="lp-sec lp-band">
|
||||
<div class="lp-frame">
|
||||
<figure class="lp-manifesto lp-reveal">
|
||||
<h2 class="lp-h2">
|
||||
<span class="line" data-i18n="about.mission.title">Our</span>
|
||||
<span class="line dim" data-i18n="about.mission.titleDim"
|
||||
>Mission</span
|
||||
>
|
||||
</h2>
|
||||
<blockquote
|
||||
class="lp-manifesto-text"
|
||||
data-i18n="about.mission.description"
|
||||
>
|
||||
To provide the most comprehensive PDF toolbox that respects your
|
||||
privacy and never asks for payment. We believe essential document
|
||||
tools should be accessible to everyone, everywhere, without
|
||||
barriers.
|
||||
</blockquote>
|
||||
</figure>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="philosophy-section" class="lp-sec">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-head lp-head--center">
|
||||
<div>
|
||||
<h2 class="lp-h2">
|
||||
<span class="line" data-i18n="about.hero.title"
|
||||
>PDF tools should be</span
|
||||
>
|
||||
<span class="line dim" data-i18n="about.hero.subtitle"
|
||||
>fast, private, and free.</span
|
||||
>
|
||||
</h2>
|
||||
<p class="lp-head-p" data-i18n="about.hero.noCompromises">
|
||||
No compromises.
|
||||
</p>
|
||||
<p class="lp-head-p" data-i18n="about.philosophy.description">
|
||||
Every BentoPDF tool runs locally in your browser. Your files are
|
||||
never uploaded, nobody else sees your documents, and nothing
|
||||
tracks what you do.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lp-grid lp-grid--3 lp-cross">
|
||||
<div class="lp-cell lp-stat lp-cell--accent lp-reveal">
|
||||
<b>0</b
|
||||
><span data-i18n="features.noUploads.title">No Uploads</span>
|
||||
</div>
|
||||
<div class="lp-cell lp-stat lp-cell--white lp-reveal">
|
||||
<b>0</b><span data-i18n="hero.noSignups">No Signups</span>
|
||||
</div>
|
||||
<div class="lp-cell lp-stat lp-cell--hatch lp-reveal">
|
||||
<b>$0</b
|
||||
><span data-i18n="features.foreverFree.title">Forever Free</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="why-Bentopdf" class="py-16">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-center text-white mb-12">
|
||||
<span data-i18n="about.whyBentopdf.title">Why</span>
|
||||
<span class="marker-slanted">Bentopdf?</span>
|
||||
</h2>
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-8 max-w-5xl mx-auto">
|
||||
<div class="bg-gray-800 p-6 rounded-lg flex items-start gap-4">
|
||||
<i
|
||||
data-lucide="zap"
|
||||
class="w-10 h-10 text-indigo-400 flex-shrink-0 mt-1"
|
||||
></i>
|
||||
<section id="why-bentopdf" class="lp-sec lp-band">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-head lp-head--center">
|
||||
<div>
|
||||
<h3
|
||||
class="text-xl font-bold text-white"
|
||||
data-i18n="about.whyBentopdf.speed.title"
|
||||
>
|
||||
Built for Speed
|
||||
</h3>
|
||||
<p
|
||||
class="text-gray-400 mt-2"
|
||||
data-i18n="about.whyBentopdf.speed.description"
|
||||
>
|
||||
No waiting for uploads or downloads to a server. By processing
|
||||
files directly in your browser using modern web technologies
|
||||
like WebAssembly, we offer unparalleled speed for all our tools.
|
||||
</p>
|
||||
<h2 class="lp-h2">
|
||||
<span class="line" data-i18n="about.whyBentopdf.title"
|
||||
>Why</span
|
||||
>
|
||||
<span class="line dim">BentoPDF?</span>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-gray-800 p-6 rounded-lg flex items-start gap-4">
|
||||
<i
|
||||
data-lucide="badge-dollar-sign"
|
||||
class="w-10 h-10 text-indigo-400 flex-shrink-0 mt-1"
|
||||
></i>
|
||||
<div>
|
||||
<h3
|
||||
class="text-xl font-bold text-white"
|
||||
data-i18n="about.whyBentopdf.free.title"
|
||||
>
|
||||
Completely Free
|
||||
</h3>
|
||||
<p
|
||||
class="text-gray-400 mt-2"
|
||||
data-i18n="about.whyBentopdf.free.description"
|
||||
>
|
||||
No trials, no subscriptions, no hidden fees, and no "premium"
|
||||
features held hostage. We believe powerful PDF tools should be a
|
||||
public utility, not a profit center.
|
||||
<div class="lp-grid lp-grid--2 lp-cross">
|
||||
<div class="lp-cell lp-reveal">
|
||||
<span class="lp-tile"><i data-lucide="zap"></i></span>
|
||||
<h3 data-i18n="about.whyBentopdf.speed.title">Built for Speed</h3>
|
||||
<p data-i18n="about.whyBentopdf.speed.description">
|
||||
There's no upload or download step. Files are processed right in
|
||||
your browser using WebAssembly, so you're never waiting on a
|
||||
server.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-gray-800 p-6 rounded-lg flex items-start gap-4">
|
||||
<i
|
||||
data-lucide="user-plus"
|
||||
class="w-10 h-10 text-indigo-400 flex-shrink-0 mt-1"
|
||||
></i>
|
||||
<div>
|
||||
<h3
|
||||
class="text-xl font-bold text-white"
|
||||
data-i18n="about.whyBentopdf.noAccount.title"
|
||||
>
|
||||
<div class="lp-cell lp-reveal">
|
||||
<span class="lp-tile"
|
||||
><i data-lucide="badge-dollar-sign"></i
|
||||
></span>
|
||||
<h3 data-i18n="about.whyBentopdf.free.title">Free to Use</h3>
|
||||
<p data-i18n="about.whyBentopdf.free.description">
|
||||
Every tool is free, with no trials, no subscriptions and no
|
||||
watermarks. Development is funded by commercial licenses.
|
||||
</p>
|
||||
</div>
|
||||
<div class="lp-cell lp-reveal">
|
||||
<span class="lp-tile"><i data-lucide="user-plus"></i></span>
|
||||
<h3 data-i18n="about.whyBentopdf.noAccount.title">
|
||||
No Account Required
|
||||
</h3>
|
||||
<p
|
||||
class="text-gray-400 mt-2"
|
||||
data-i18n="about.whyBentopdf.noAccount.description"
|
||||
>
|
||||
Start using any tool immediately. We don't need your email, a
|
||||
password, or any personal information. Your workflow should be
|
||||
frictionless and anonymous.
|
||||
<p data-i18n="about.whyBentopdf.noAccount.description">
|
||||
Open any tool and start right away. No email, no password, no
|
||||
personal information.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-gray-800 p-6 rounded-lg flex items-start gap-4">
|
||||
<i
|
||||
data-lucide="code-2"
|
||||
class="w-10 h-10 text-indigo-400 flex-shrink-0 mt-1"
|
||||
></i>
|
||||
<div>
|
||||
<h3
|
||||
class="text-xl font-bold text-white"
|
||||
data-i18n="about.whyBentopdf.openSource.title"
|
||||
>
|
||||
Open Source Spirit
|
||||
<div class="lp-cell lp-reveal">
|
||||
<span class="lp-tile"><i data-lucide="code-2"></i></span>
|
||||
<h3 data-i18n="about.whyBentopdf.openSource.title">
|
||||
Open Source
|
||||
</h3>
|
||||
<p
|
||||
class="text-gray-400 mt-2"
|
||||
data-i18n="about.whyBentopdf.openSource.description"
|
||||
>
|
||||
Built with transparency in mind. We leverage incredible
|
||||
open-source libraries like PDF-lib and PDF.js, and believe in
|
||||
the community-driven effort to make powerful tools accessible to
|
||||
everyone.
|
||||
<p data-i18n="about.whyBentopdf.openSource.description">
|
||||
The code is public on GitHub under AGPL-3.0, so you can check
|
||||
exactly how your files are handled. It builds on open-source
|
||||
projects like PDF.js, pdf-lib, qpdf and LibreOffice.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="section-divider"></div>
|
||||
|
||||
<section id="cta-section" class="text-center py-16">
|
||||
<h2
|
||||
class="text-3xl font-bold text-white mb-4"
|
||||
data-i18n="about.cta.title"
|
||||
>
|
||||
Ready to get started?
|
||||
</h2>
|
||||
<p
|
||||
class="text-lg text-gray-400 mb-8 max-w-2xl mx-auto"
|
||||
data-i18n="about.cta.description"
|
||||
>
|
||||
Join thousands of users who trust Bentopdf for their daily document
|
||||
needs. Experience the difference that privacy and performance can
|
||||
make.
|
||||
</p>
|
||||
<a
|
||||
href="index.html#tools-header"
|
||||
class="inline-block px-8 py-3 rounded-full bg-gradient-to-b from-indigo-500 to-indigo-600 text-white font-semibold focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-900 focus:ring-indigo-400 hover:shadow-xl hover:shadow-indigo-500/30 transition-all duration-200 transform hover:-translate-y-1"
|
||||
data-i18n="about.cta.button"
|
||||
>
|
||||
Explore All Tools
|
||||
</a>
|
||||
<section id="cta-section" class="lp-sec">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-cta">
|
||||
<h2 class="lp-h2" data-i18n="about.cta.title">
|
||||
Ready to get started?
|
||||
</h2>
|
||||
<p data-i18n="about.cta.description">
|
||||
Join thousands of users who trust BentoPDF for their daily
|
||||
document needs. Experience the difference that privacy and
|
||||
performance can make.
|
||||
</p>
|
||||
<div class="lp-cta-actions">
|
||||
<span class="lp-brackets">
|
||||
<a
|
||||
href="index.html#tools-header"
|
||||
class="lp-btn lp-btn--primary"
|
||||
>
|
||||
<span data-i18n="about.cta.button">Explore All Tools</span>
|
||||
<i data-lucide="arrow-right"></i>
|
||||
</a>
|
||||
</span>
|
||||
<a href="https://bentopdf.com/docs/" class="lp-btn lp-btn--ghost">
|
||||
<i data-lucide="book-open"></i>
|
||||
<span data-i18n="nav.docs">Docs</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@@ -299,6 +347,7 @@
|
||||
<script type="module" src="src/js/utils/lucide-init.ts"></script>
|
||||
<script type="module" src="src/js/main.ts"></script>
|
||||
<script type="module" src="src/js/mobileMenu.ts"></script>
|
||||
<script type="module" src="src/js/landing.ts"></script>
|
||||
|
||||
<!-- JSON-LD Schema -->
|
||||
<script type="application/ld+json">
|
||||
@@ -306,8 +355,20 @@
|
||||
"@context": "https://schema.org",
|
||||
"@type": "AboutPage",
|
||||
"name": "About BentoPDF",
|
||||
"description": "Learn about BentoPDF's mission to provide free, privacy-first PDF tools",
|
||||
"url": "https://www.bentopdf.com/about"
|
||||
"description": "How BentoPDF started, told by its creator Alam",
|
||||
"url": "https://www.bentopdf.com/about",
|
||||
"mainEntity": {
|
||||
"@type": "Person",
|
||||
"name": "Alam",
|
||||
"url": "https://www.bentopdf.com/blog/author-alam",
|
||||
"image": "https://www.bentopdf.com/images/author-alam.jpg",
|
||||
"jobTitle": "Creator and maintainer of BentoPDF",
|
||||
"sameAs": [
|
||||
"https://github.com/alam00000",
|
||||
"https://www.linkedin.com/in/abdullah-alam01/",
|
||||
"https://x.com/alamdraws"
|
||||
]
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,149 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Alam, Creator of BentoPDF</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Alam builds BentoPDF, the open-source, privacy-first PDF toolkit that runs entirely in your browser. Every post on this blog is written by him."
|
||||
/>
|
||||
<meta name="robots" content="index, follow" />
|
||||
<link rel="canonical" href="https://www.bentopdf.com/blog/author-alam" />
|
||||
<meta property="og:type" content="profile" />
|
||||
<meta
|
||||
property="og:url"
|
||||
content="https://www.bentopdf.com/blog/author-alam"
|
||||
/>
|
||||
<meta property="og:title" content="Alam, Creator of BentoPDF" />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="The maintainer behind BentoPDF and the author of every post on this blog."
|
||||
/>
|
||||
<meta
|
||||
property="og:image"
|
||||
content="https://www.bentopdf.com/images/author-alam.jpg"
|
||||
/>
|
||||
<meta property="og:site_name" content="BentoPDF" />
|
||||
<meta name="twitter:card" content="summary" />
|
||||
<link rel="manifest" href="/site.webmanifest" />
|
||||
<link rel="icon" type="image/svg+xml" href="/images/favicon.svg" />
|
||||
<link rel="icon" href="/favicon.ico" sizes="32x32" />
|
||||
<link href="/src/css/styles.css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<body class="antialiased bg-gray-900">
|
||||
{{> navbar }}
|
||||
|
||||
<section class="max-w-3xl mx-auto px-4 py-12">
|
||||
<div class="flex items-center gap-5 mb-8">
|
||||
<img
|
||||
src="/images/author-alam.jpg"
|
||||
alt="Alam"
|
||||
width="80"
|
||||
height="80"
|
||||
class="rounded-full"
|
||||
/>
|
||||
<div>
|
||||
<h1 class="text-3xl font-bold text-white">Alam</h1>
|
||||
<p class="text-gray-400">Creator and maintainer of BentoPDF</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
I’m Alam, and I build
|
||||
<a href="/" class="text-indigo-300 hover:text-indigo-400">BentoPDF</a>,
|
||||
a free, open-source PDF toolkit with 100+ tools that run entirely in
|
||||
your browser.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
There’s no uploading your files to a server, no account to create, and
|
||||
no tracking. Your documents stay on your device. The
|
||||
<a
|
||||
href="https://github.com/alam00000/bentopdf"
|
||||
rel="noopener"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>source code</a
|
||||
>
|
||||
is public, so you can see how it works yourself. BentoPDF is
|
||||
AGPL-licensed and self-hostable.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
I write every post on this blog myself. I’ll write about PDFs, how they
|
||||
work, things I learn while building BentoPDF, and occasionally things
|
||||
that go wrong.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
When I compare BentoPDF with another PDF tool, I’ll link to its
|
||||
documentation so you can check what I’m saying. If there’s something
|
||||
BentoPDF doesn’t do well, I’ll say that too.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
And if I get something wrong, please
|
||||
<a
|
||||
href="https://github.com/alam00000/bentopdf/issues"
|
||||
rel="noopener"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>open an issue</a
|
||||
>. I’ll fix it and add a note to the post.
|
||||
</p>
|
||||
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
You can find me on
|
||||
<a
|
||||
href="https://github.com/alam00000"
|
||||
rel="me noopener"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>GitHub</a
|
||||
>,
|
||||
<a
|
||||
href="https://www.linkedin.com/in/abdullah-alam01/"
|
||||
rel="me noopener"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>LinkedIn</a
|
||||
>
|
||||
and
|
||||
<a
|
||||
href="https://x.com/alamdraws"
|
||||
rel="me noopener"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>X</a
|
||||
>.
|
||||
</p>
|
||||
|
||||
<p class="text-gray-300 leading-relaxed">
|
||||
<a
|
||||
href="/blog"
|
||||
class="inline-flex items-center gap-2 text-indigo-300 hover:text-indigo-400 font-semibold"
|
||||
>Read the blog <i class="ph ph-arrow-right" aria-hidden="true"></i
|
||||
></a>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
{{> footer }}
|
||||
<script type="module" src="/src/js/utils/lucide-init.ts"></script>
|
||||
<script type="module">
|
||||
import '@phosphor-icons/web/regular';
|
||||
</script>
|
||||
<script type="module" src="/src/js/mobileMenu.ts"></script>
|
||||
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "ProfilePage",
|
||||
"mainEntity": {
|
||||
"@type": "Person",
|
||||
"name": "Alam",
|
||||
"url": "https://www.bentopdf.com/blog/author-alam",
|
||||
"image": "https://www.bentopdf.com/images/author-alam.jpg",
|
||||
"jobTitle": "Creator and maintainer of BentoPDF",
|
||||
"sameAs": [
|
||||
"https://github.com/alam00000",
|
||||
"https://www.linkedin.com/in/abdullah-alam01/",
|
||||
"https://x.com/alamdraws"
|
||||
]
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,473 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>
|
||||
How to Edit a PDF Without Uploading It Anywhere | BentoPDF Blog
|
||||
</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Edit PDF text, fill forms, redact, and sign in your browser while the file stays on your device. Step by step, with the right tool for each job."
|
||||
/>
|
||||
<meta name="robots" content="index, follow, max-image-preview:large" />
|
||||
<link
|
||||
rel="canonical"
|
||||
href="https://www.bentopdf.com/blog/edit-pdf-without-uploading"
|
||||
/>
|
||||
<meta property="og:type" content="article" />
|
||||
<meta
|
||||
property="og:url"
|
||||
content="https://www.bentopdf.com/blog/edit-pdf-without-uploading"
|
||||
/>
|
||||
<meta
|
||||
property="og:title"
|
||||
content="How to Edit a PDF Without Uploading It Anywhere"
|
||||
/>
|
||||
<meta
|
||||
property="og:description"
|
||||
content="Edit PDF text, fill forms, redact, and sign in your browser while the file stays on your device. Step by step, with the right tool for each job."
|
||||
/>
|
||||
<meta
|
||||
property="og:image"
|
||||
content="https://www.bentopdf.com/images/og-tools.png"
|
||||
/>
|
||||
<meta property="og:site_name" content="BentoPDF" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<link rel="manifest" href="/site.webmanifest" />
|
||||
<link rel="icon" type="image/svg+xml" href="/images/favicon.svg" />
|
||||
<link rel="icon" href="/favicon.ico" sizes="32x32" />
|
||||
<link href="/src/css/styles.css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<body class="antialiased bg-gray-900">
|
||||
{{> navbar }}
|
||||
|
||||
<article class="max-w-3xl mx-auto px-4 py-12">
|
||||
<nav
|
||||
class="flex items-center gap-2 text-sm text-gray-400 mb-6"
|
||||
aria-label="Breadcrumb"
|
||||
>
|
||||
<a href="/blog" class="hover:text-indigo-300">Blog</a>
|
||||
<i class="ph ph-caret-right text-xs" aria-hidden="true"></i>
|
||||
<span class="text-gray-300">Edit a PDF without uploading</span>
|
||||
</nav>
|
||||
|
||||
<h1 class="text-3xl md:text-4xl font-bold text-white mb-4 leading-tight">
|
||||
How to edit a PDF without uploading it anywhere
|
||||
</h1>
|
||||
|
||||
<div class="flex items-center gap-3 mb-10 text-sm text-gray-400">
|
||||
<img
|
||||
src="/images/author-alam.jpg"
|
||||
alt="Alam"
|
||||
width="40"
|
||||
height="40"
|
||||
class="rounded-full"
|
||||
/>
|
||||
<div>
|
||||
<a
|
||||
href="/blog/author-alam"
|
||||
class="text-gray-200 font-semibold hover:text-indigo-300"
|
||||
>Alam</a
|
||||
>, builds BentoPDF ·
|
||||
<time datetime="2026-09-03">September 3, 2026</time>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
You can edit a PDF in your browser without uploading the file to a
|
||||
server.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
Open
|
||||
<a class="text-indigo-300 hover:text-indigo-400" href="/edit-pdf"
|
||||
>BentoPDF's PDF editor</a
|
||||
>, pick your file, make your changes, and download the result. The PDF
|
||||
stays on your device. There's no account and no watermark.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
But “edit a PDF” can mean a few different things. You might want to
|
||||
change existing text, fill out a form, add a signature, redact
|
||||
something, or just highlight a paragraph. The right tool depends on what
|
||||
you're trying to do.
|
||||
</p>
|
||||
<h2 class="text-2xl font-bold text-white mt-10 mb-4">
|
||||
Why edit a PDF without uploading it?
|
||||
</h2>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
Think about the PDFs you normally edit.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
Contracts. Bank statements. Tax documents. Forms with your address or ID
|
||||
number.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
Those aren't necessarily files you want to upload to a random “free
|
||||
PDF editor.”
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
With an on-device PDF editor, the file stays on your computer while
|
||||
you're working on it.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
You can even check this yourself. Open your browser's developer
|
||||
tools, go to the Network tab, and watch what happens while you edit. The
|
||||
PDF itself doesn't need to be sent to a server.
|
||||
</p>
|
||||
<h2 class="text-2xl font-bold text-white mt-10 mb-4">
|
||||
How to edit the actual text in a PDF
|
||||
</h2>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
If you want to change words that are already in the PDF, use
|
||||
<a class="text-indigo-300 hover:text-indigo-400" href="/edit-pdf-text"
|
||||
>Edit PDF Text</a
|
||||
>.
|
||||
</p>
|
||||
<ol
|
||||
class="list-decimal list-inside text-gray-300 leading-relaxed mb-5 space-y-2"
|
||||
>
|
||||
<li>Open the tool.</li>
|
||||
<li>Drop in your PDF.</li>
|
||||
<li>Click on the text you want to change.</li>
|
||||
<li>Type your changes.</li>
|
||||
<li>Download the edited PDF.</li>
|
||||
</ol>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
BentoPDF loads the PDF in your browser and does the editing on your
|
||||
device.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
This is one of the harder things to do with PDFs because PDF text
|
||||
doesn't work quite like text in a Word document. The PDF is mostly
|
||||
concerned with putting things at particular positions on a page, so
|
||||
changing a sentence can mean figuring out how the surrounding text
|
||||
should move.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
It works well for ordinary documents, but PDFs with unusual embedded
|
||||
fonts or very complicated layouts can be trickier. I'd always open
|
||||
the downloaded PDF and check it.
|
||||
</p>
|
||||
<h2 class="text-2xl font-bold text-white mt-10 mb-4">
|
||||
How to annotate a PDF
|
||||
</h2>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
If you don't need to change the existing text, annotating a PDF is
|
||||
much simpler.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
The
|
||||
<a class="text-indigo-300 hover:text-indigo-400" href="/edit-pdf"
|
||||
>PDF editor</a
|
||||
>
|
||||
lets you add highlights, comments, shapes, stamps, text boxes, and
|
||||
images.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
Open the PDF, add your annotations, and download the result.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
Again, the editing happens in your browser rather than on a remote
|
||||
server.
|
||||
</p>
|
||||
<h2 class="text-2xl font-bold text-white mt-10 mb-4">
|
||||
How to fill out a PDF form
|
||||
</h2>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
There are two common kinds of PDF forms.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
If the PDF has actual form fields, open it in
|
||||
<a class="text-indigo-300 hover:text-indigo-400" href="/form-filler"
|
||||
>PDF Form Filler</a
|
||||
>
|
||||
and type into the fields. It handles standard AcroForm fields, and also
|
||||
XFA forms, which are the legacy XML-based format. XFA is worth calling
|
||||
out because Chrome and most other viewers show those files as blank
|
||||
pages, which is why some government forms tell you to open them in Adobe
|
||||
Reader. Firefox and BentoPDF's form filler render them properly.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
If it's a scanned or flattened form, there aren't any fields to
|
||||
click. In that case, you can put text boxes over the blank spaces in the
|
||||
<a class="text-indigo-300 hover:text-indigo-400" href="/edit-pdf"
|
||||
>PDF editor</a
|
||||
>
|
||||
and type into them. If you'd rather have real fields,
|
||||
<a class="text-indigo-300 hover:text-indigo-400" href="/form-creator"
|
||||
>Create PDF Form</a
|
||||
>
|
||||
can add them to the document first.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
This is especially useful for government and HR forms, which often
|
||||
contain personal information I'd rather not upload somewhere just to
|
||||
fill in a few boxes.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
If the PDF is a scan and you actually need to edit the scanned text
|
||||
itself, you'll need OCR first.
|
||||
<a class="text-indigo-300 hover:text-indigo-400" href="/ocr-pdf"
|
||||
>BentoPDF's OCR tool</a
|
||||
>
|
||||
can recognize the text in the document while keeping the processing on
|
||||
your device.
|
||||
</p>
|
||||
<h2 class="text-2xl font-bold text-white mt-10 mb-4">
|
||||
How to redact a PDF properly
|
||||
</h2>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
This one is important because putting a black box over text isn't
|
||||
necessarily redaction.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
If you draw a rectangle over a name, the original name may still exist
|
||||
underneath it. It might still be selectable, searchable, or extractable.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
Proper redaction removes the underlying content.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
The
|
||||
<a class="text-indigo-300 hover:text-indigo-400" href="/edit-pdf"
|
||||
>PDF editor</a
|
||||
>
|
||||
has redaction tools that permanently remove the underlying content
|
||||
rather than drawing over it. For documents where you also want to strip
|
||||
metadata or other hidden content,
|
||||
<a class="text-indigo-300 hover:text-indigo-400" href="/sanitize-pdf"
|
||||
>Sanitize PDF</a
|
||||
>
|
||||
can help with that.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
There's also a privacy reason to do redaction locally: if you upload
|
||||
the original, unredacted PDF to a redaction service, that service has
|
||||
already received the information you're trying to hide.
|
||||
</p>
|
||||
<h2 class="text-2xl font-bold text-white mt-10 mb-4">
|
||||
How to sign a PDF without uploading it
|
||||
</h2>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
<a class="text-indigo-300 hover:text-indigo-400" href="/sign-pdf"
|
||||
>Sign PDF</a
|
||||
>
|
||||
lets you add a drawn, typed, or image signature to a PDF. Place it on
|
||||
the page, resize it, and optionally flatten it so it becomes part of the
|
||||
page instead of an annotation someone can drag away later.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
The signature is added on your device, so you don't need to upload
|
||||
the document to a signing service just to place a signature on it.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
One thing to keep in mind: adding a signature image to a PDF is not the
|
||||
same thing as applying a cryptographic digital signature. If the
|
||||
recipient needs a signature that can actually be verified, use
|
||||
<a
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
href="/digital-sign-pdf"
|
||||
>Digital Signature</a
|
||||
>
|
||||
instead. It signs the document with an X.509 certificate (PKCS#12 .pfx
|
||||
and .p12, or PEM), which proves who signed it and shows whether anything
|
||||
changed afterwards. You can also add a visible signature block on top of
|
||||
that. The certificate password and private key stay in your browser,
|
||||
same as the PDF.
|
||||
</p>
|
||||
<h2 class="text-2xl font-bold text-white mt-10 mb-4">
|
||||
Can you edit a PDF offline?
|
||||
</h2>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">Yes.</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
There's an easy way to test it: load the editor, turn off Wi-Fi, and
|
||||
edit a PDF.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
The PDF processing code runs in your browser using WebAssembly. Once the
|
||||
application has loaded, the actual PDF processing doesn't need a
|
||||
server.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
This is also something you can inspect yourself in your browser's
|
||||
developer tools. The website is how you get the software; it doesn't
|
||||
have to be where your PDF gets processed.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
If you want to run the whole thing yourself, BentoPDF is
|
||||
<a
|
||||
rel="noopener"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
href="https://github.com/alam00000/bentopdf"
|
||||
>open source and self-hostable</a
|
||||
>. You can run your own instance instead of relying on ours.
|
||||
</p>
|
||||
<h2 class="text-2xl font-bold text-white mt-10 mb-4">
|
||||
What about scanned PDFs?
|
||||
</h2>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
A scanned PDF is basically a collection of images.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
If you want to change the words in it, an ordinary PDF text editor
|
||||
can't simply edit them because there isn't any text there yet.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
You'll need OCR (optical character recognition) to turn the pixels
|
||||
into text.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
You can either OCR the PDF first and then edit the resulting text, or,
|
||||
if you're just filling out a scanned form, put text boxes on top of
|
||||
the existing page.
|
||||
</p>
|
||||
<h2 class="text-2xl font-bold text-white mt-10 mb-4">
|
||||
Is there a file size limit?
|
||||
</h2>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
There isn't an imposed file-size limit.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
The practical limit is your device's available memory. Normal PDFs
|
||||
are usually fine, but a thousand-page scanned archive is a very
|
||||
different workload from a five-page contract.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
For very large PDFs, a desktop application may be a better choice.
|
||||
</p>
|
||||
<h2 class="text-2xl font-bold text-white mt-10 mb-4">
|
||||
Will editing a digitally signed PDF break the signature?
|
||||
</h2>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">Yes.</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
Changing a digitally signed PDF will invalidate its existing signature.
|
||||
This isn't specific to BentoPDF; it's a consequence of changing
|
||||
a document that has already been signed.
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">So the usual order is:</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
<strong>Edit first. Sign last.</strong>
|
||||
</p>
|
||||
<p class="text-gray-300 leading-relaxed mb-5">
|
||||
If you need to make changes to a signed document, make sure you
|
||||
understand the signature requirements before doing so.
|
||||
</p>
|
||||
|
||||
<div class="bg-gray-800 border border-gray-700 rounded-xl p-6 my-10">
|
||||
<p class="text-white font-semibold mb-2">Edit your PDF now</p>
|
||||
<p class="text-gray-400 mb-4">
|
||||
Free, no signup. Your file stays on your device.
|
||||
</p>
|
||||
<a
|
||||
href="/edit-pdf"
|
||||
class="inline-block bg-indigo-600 hover:bg-indigo-700 text-white font-semibold px-5 py-2.5 rounded-lg"
|
||||
>Open the PDF editor</a
|
||||
>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
{{> footer }}
|
||||
<script type="module" src="/src/js/utils/lucide-init.ts"></script>
|
||||
<script type="module" src="/src/js/mobileMenu.ts"></script>
|
||||
<script type="module">
|
||||
import '@phosphor-icons/web/regular';
|
||||
</script>
|
||||
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "BlogPosting",
|
||||
"headline": "How to edit a PDF without uploading it anywhere",
|
||||
"description": "Edit PDF text, fill forms, redact, and sign in your browser while the file stays on your device. Step by step, with the right tool for each job.",
|
||||
"url": "https://www.bentopdf.com/blog/edit-pdf-without-uploading",
|
||||
"datePublished": "2026-09-03",
|
||||
"dateModified": "2026-09-03",
|
||||
"image": "https://www.bentopdf.com/images/og-tools.png",
|
||||
"author": {
|
||||
"@type": "Person",
|
||||
"name": "Alam",
|
||||
"url": "https://www.bentopdf.com/blog/author-alam",
|
||||
"sameAs": [
|
||||
"https://github.com/alam00000",
|
||||
"https://www.linkedin.com/in/abdullah-alam01/",
|
||||
"https://x.com/alamdraws"
|
||||
]
|
||||
},
|
||||
"publisher": {
|
||||
"@type": "Organization",
|
||||
"name": "BentoPDF",
|
||||
"url": "https://www.bentopdf.com"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "BreadcrumbList",
|
||||
"itemListElement": [
|
||||
{
|
||||
"@type": "ListItem",
|
||||
"position": 1,
|
||||
"name": "Blog",
|
||||
"item": "https://www.bentopdf.com/blog/"
|
||||
},
|
||||
{
|
||||
"@type": "ListItem",
|
||||
"position": 2,
|
||||
"name": "Edit a PDF without uploading",
|
||||
"item": "https://www.bentopdf.com/blog/edit-pdf-without-uploading"
|
||||
}
|
||||
]
|
||||
}
|
||||
</script>
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "FAQPage",
|
||||
"mainEntity": [
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "Why edit a PDF without uploading it?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Think about the PDFs you normally edit. Contracts. Bank statements. Tax documents. Forms with your address or ID number. Those aren't necessarily files you want to upload to a random “free PDF editor.” With an on-device PDF editor, the file stays on your computer while you're working on it. You can even check this yourself. Open your browser's developer tools, go to the Network tab, and watch what happens while you edit. The PDF itself doesn't need to be sent to a server."
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "Can you edit a PDF offline?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Yes. There's an easy way to test it: load the editor, turn off Wi-Fi, and edit a PDF. The PDF processing code runs in your browser using WebAssembly. Once the application has loaded, the actual PDF processing doesn't need a server. This is also something you can inspect yourself in your browser's developer tools. The website is how you get the software; it doesn't have to be where your PDF gets processed. If you want to run the whole thing yourself, BentoPDF is open source and self-hostable. You can run your own instance instead of relying on ours."
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "What about scanned PDFs?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "A scanned PDF is basically a collection of images. If you want to change the words in it, an ordinary PDF text editor can't simply edit them because there isn't any text there yet. You'll need OCR (optical character recognition) to turn the pixels into text. You can either OCR the PDF first and then edit the resulting text, or, if you're just filling out a scanned form, put text boxes on top of the existing page."
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "Is there a file size limit?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "There isn't an imposed file-size limit. The practical limit is your device's available memory. Normal PDFs are usually fine, but a thousand-page scanned archive is a very different workload from a five-page contract. For very large PDFs, a desktop application may be a better choice."
|
||||
}
|
||||
},
|
||||
{
|
||||
"@type": "Question",
|
||||
"name": "Will editing a digitally signed PDF break the signature?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Yes. Changing a digitally signed PDF will invalidate its existing signature. This isn't specific to BentoPDF; it's a consequence of changing a document that has already been signed. So the usual order is: Edit first. Sign last. If you need to make changes to a signed document, make sure you understand the signature requirements before doing so."
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,87 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>The BentoPDF Blog | Privacy-First PDF Guides</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Guides and honest comparisons from the maintainer of BentoPDF: how PDF tools handle your files, and how to get things done without uploading them."
|
||||
/>
|
||||
<meta name="robots" content="index, follow, max-image-preview:large" />
|
||||
<link rel="canonical" href="https://www.bentopdf.com/blog/" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="https://www.bentopdf.com/blog/" />
|
||||
<meta property="og:title" content="The BentoPDF Blog" />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="Guides and honest comparisons from the maintainer of BentoPDF."
|
||||
/>
|
||||
<meta
|
||||
property="og:image"
|
||||
content="https://www.bentopdf.com/images/og-tools.png"
|
||||
/>
|
||||
<meta property="og:site_name" content="BentoPDF" />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<link rel="manifest" href="/site.webmanifest" />
|
||||
<link rel="icon" type="image/svg+xml" href="/images/favicon.svg" />
|
||||
<link rel="icon" href="/favicon.ico" sizes="32x32" />
|
||||
<link href="/src/css/styles.css" rel="stylesheet" />
|
||||
</head>
|
||||
|
||||
<body class="antialiased bg-gray-900">
|
||||
{{> navbar }}
|
||||
|
||||
<section class="max-w-3xl mx-auto px-4 py-12">
|
||||
<h1 class="text-3xl md:text-4xl font-bold text-white mb-4">
|
||||
The BentoPDF Blog
|
||||
</h1>
|
||||
<p class="text-gray-300 leading-relaxed mb-2">
|
||||
I'm
|
||||
<a
|
||||
href="/blog/author-alam"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>Alam</a
|
||||
>. I build BentoPDF and write about PDFs, how they work, and the weird
|
||||
things I run into along the way.
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section class="max-w-3xl mx-auto px-4 pb-16">
|
||||
<div class="space-y-6">
|
||||
<a
|
||||
href="/blog/edit-pdf-without-uploading"
|
||||
class="block bg-gray-800 border border-gray-700 rounded-xl p-6 hover:border-indigo-500 transition-colors"
|
||||
>
|
||||
<h2 class="text-xl font-bold text-white mb-2">
|
||||
How to edit a PDF without uploading it anywhere
|
||||
</h2>
|
||||
<p class="text-gray-400 mb-3">
|
||||
Rewrite text, fill forms, redact properly, and sign, locally on your
|
||||
device.
|
||||
</p>
|
||||
<span class="text-sm text-gray-500">September 3, 2026</span>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{{> footer }}
|
||||
<script type="module" src="/src/js/utils/lucide-init.ts"></script>
|
||||
<script type="module" src="/src/js/mobileMenu.ts"></script>
|
||||
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "Blog",
|
||||
"name": "The BentoPDF Blog",
|
||||
"url": "https://www.bentopdf.com/blog/",
|
||||
"description": "Guides and honest comparisons from the maintainer of BentoPDF.",
|
||||
"publisher": {
|
||||
"@type": "Organization",
|
||||
"name": "BentoPDF",
|
||||
"url": "https://www.bentopdf.com"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,134 @@
|
||||
---
|
||||
{
|
||||
"title": "How to Edit a PDF Without Uploading It Anywhere | BentoPDF Blog",
|
||||
"h1": "How to edit a PDF without uploading it anywhere",
|
||||
"ogTitle": "How to Edit a PDF Without Uploading It Anywhere",
|
||||
"breadcrumb": "Edit a PDF without uploading",
|
||||
"description": "Edit PDF text, fill forms, redact, and sign in your browser while the file stays on your device. Step by step, with the right tool for each job.",
|
||||
"card": "Rewrite text, fill forms, redact properly, and sign, locally on your device.",
|
||||
"date": "2026-09-03",
|
||||
"cta": {
|
||||
"heading": "Edit your PDF now",
|
||||
"text": "Free, no signup. Your file stays on your device.",
|
||||
"href": "/edit-pdf",
|
||||
"label": "Open the PDF editor"
|
||||
}
|
||||
}
|
||||
---
|
||||
You can edit a PDF in your browser without uploading the file to a server.
|
||||
|
||||
Open [BentoPDF's PDF editor](/edit-pdf), pick your file, make your changes, and download the result. The PDF stays on your device. There's no account and no watermark.
|
||||
|
||||
But “edit a PDF” can mean a few different things. You might want to change existing text, fill out a form, add a signature, redact something, or just highlight a paragraph. The right tool depends on what you're trying to do.
|
||||
|
||||
## Why edit a PDF without uploading it?
|
||||
|
||||
Think about the PDFs you normally edit.
|
||||
|
||||
Contracts. Bank statements. Tax documents. Forms with your address or ID number.
|
||||
|
||||
Those aren't necessarily files you want to upload to a random “free PDF editor.”
|
||||
|
||||
With an on-device PDF editor, the file stays on your computer while you're working on it.
|
||||
|
||||
You can even check this yourself. Open your browser's developer tools, go to the Network tab, and watch what happens while you edit. The PDF itself doesn't need to be sent to a server.
|
||||
|
||||
## How to edit the actual text in a PDF
|
||||
|
||||
If you want to change words that are already in the PDF, use [Edit PDF Text](/edit-pdf-text).
|
||||
|
||||
1. Open the tool.
|
||||
2. Drop in your PDF.
|
||||
3. Click on the text you want to change.
|
||||
4. Type your changes.
|
||||
5. Download the edited PDF.
|
||||
|
||||
BentoPDF loads the PDF in your browser and does the editing on your device.
|
||||
|
||||
This is one of the harder things to do with PDFs because PDF text doesn't work quite like text in a Word document. The PDF is mostly concerned with putting things at particular positions on a page, so changing a sentence can mean figuring out how the surrounding text should move.
|
||||
|
||||
It works well for ordinary documents, but PDFs with unusual embedded fonts or very complicated layouts can be trickier. I'd always open the downloaded PDF and check it.
|
||||
|
||||
## How to annotate a PDF
|
||||
|
||||
If you don't need to change the existing text, annotating a PDF is much simpler.
|
||||
|
||||
The [PDF editor](/edit-pdf) lets you add highlights, comments, shapes, stamps, text boxes, and images.
|
||||
|
||||
Open the PDF, add your annotations, and download the result.
|
||||
|
||||
Again, the editing happens in your browser rather than on a remote server.
|
||||
|
||||
## How to fill out a PDF form
|
||||
|
||||
There are two common kinds of PDF forms.
|
||||
|
||||
If the PDF has actual form fields, open it in [PDF Form Filler](/form-filler) and type into the fields. It handles standard AcroForm fields, and also XFA forms, which are the legacy XML-based format. XFA is worth calling out because Chrome and most other viewers show those files as blank pages, which is why some government forms tell you to open them in Adobe Reader. Firefox and BentoPDF's form filler render them properly.
|
||||
|
||||
If it's a scanned or flattened form, there aren't any fields to click. In that case, you can put text boxes over the blank spaces in the [PDF editor](/edit-pdf) and type into them. If you'd rather have real fields, [Create PDF Form](/form-creator) can add them to the document first.
|
||||
|
||||
This is especially useful for government and HR forms, which often contain personal information I'd rather not upload somewhere just to fill in a few boxes.
|
||||
|
||||
If the PDF is a scan and you actually need to edit the scanned text itself, you'll need OCR first. [BentoPDF's OCR tool](/ocr-pdf) can recognize the text in the document while keeping the processing on your device.
|
||||
|
||||
## How to redact a PDF properly
|
||||
|
||||
This one is important because putting a black box over text isn't necessarily redaction.
|
||||
|
||||
If you draw a rectangle over a name, the original name may still exist underneath it. It might still be selectable, searchable, or extractable.
|
||||
|
||||
Proper redaction removes the underlying content.
|
||||
|
||||
The [PDF editor](/edit-pdf) has redaction tools that permanently remove the underlying content rather than drawing over it. For documents where you also want to strip metadata or other hidden content, [Sanitize PDF](/sanitize-pdf) can help with that.
|
||||
|
||||
There's also a privacy reason to do redaction locally: if you upload the original, unredacted PDF to a redaction service, that service has already received the information you're trying to hide.
|
||||
|
||||
## How to sign a PDF without uploading it
|
||||
|
||||
[Sign PDF](/sign-pdf) lets you add a drawn, typed, or image signature to a PDF. Place it on the page, resize it, and optionally flatten it so it becomes part of the page instead of an annotation someone can drag away later.
|
||||
|
||||
The signature is added on your device, so you don't need to upload the document to a signing service just to place a signature on it.
|
||||
|
||||
One thing to keep in mind: adding a signature image to a PDF is not the same thing as applying a cryptographic digital signature. If the recipient needs a signature that can actually be verified, use [Digital Signature](/digital-sign-pdf) instead. It signs the document with an X.509 certificate (PKCS#12 .pfx and .p12, or PEM), which proves who signed it and shows whether anything changed afterwards. You can also add a visible signature block on top of that. The certificate password and private key stay in your browser, same as the PDF.
|
||||
|
||||
## Can you edit a PDF offline?
|
||||
|
||||
Yes.
|
||||
|
||||
There's an easy way to test it: load the editor, turn off Wi-Fi, and edit a PDF.
|
||||
|
||||
The PDF processing code runs in your browser using WebAssembly. Once the application has loaded, the actual PDF processing doesn't need a server.
|
||||
|
||||
This is also something you can inspect yourself in your browser's developer tools. The website is how you get the software; it doesn't have to be where your PDF gets processed.
|
||||
|
||||
If you want to run the whole thing yourself, BentoPDF is [open source and self-hostable](https://github.com/alam00000/bentopdf). You can run your own instance instead of relying on ours.
|
||||
|
||||
## What about scanned PDFs?
|
||||
|
||||
A scanned PDF is basically a collection of images.
|
||||
|
||||
If you want to change the words in it, an ordinary PDF text editor can't simply edit them because there isn't any text there yet.
|
||||
|
||||
You'll need OCR (optical character recognition) to turn the pixels into text.
|
||||
|
||||
You can either OCR the PDF first and then edit the resulting text, or, if you're just filling out a scanned form, put text boxes on top of the existing page.
|
||||
|
||||
## Is there a file size limit?
|
||||
|
||||
There isn't an imposed file-size limit.
|
||||
|
||||
The practical limit is your device's available memory. Normal PDFs are usually fine, but a thousand-page scanned archive is a very different workload from a five-page contract.
|
||||
|
||||
For very large PDFs, a desktop application may be a better choice.
|
||||
|
||||
## Will editing a digitally signed PDF break the signature?
|
||||
|
||||
Yes.
|
||||
|
||||
Changing a digitally signed PDF will invalidate its existing signature. This isn't specific to BentoPDF; it's a consequence of changing a document that has already been signed.
|
||||
|
||||
So the usual order is:
|
||||
|
||||
**Edit first. Sign last.**
|
||||
|
||||
If you need to make changes to a signed document, make sure you understand the signature requirements before doing so.
|
||||
+2
-2
@@ -7,10 +7,10 @@ type: application
|
||||
# This is the chart version. This version number should be incremented each time you make changes
|
||||
# to the chart and its templates, including the app version.
|
||||
# Versions are expected to follow Semantic Versioning (https://semver.org/)
|
||||
version: 1.0.4
|
||||
version: 1.0.9
|
||||
|
||||
# This is the version number of the application being deployed. This version number should be
|
||||
# incremented each time you make changes to the application. Versions are not expected to
|
||||
# follow Semantic Versioning. They should reflect the version the application is using.
|
||||
# It is recommended to use it with quotes.
|
||||
appVersion: '2.8.5'
|
||||
appVersion: '2.8.10'
|
||||
|
||||
+1
-1
@@ -91,7 +91,7 @@ helm package .
|
||||
helm push bentopdf-*.tgz oci://ghcr.io/$GHCR_USERNAME/charts
|
||||
```
|
||||
|
||||
This could be automated as part of a Github workflow.
|
||||
This could be automated as part of a GitHub workflow.
|
||||
|
||||
### Deploy
|
||||
|
||||
|
||||
@@ -75,6 +75,8 @@ securityContext:
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
|
||||
resources: {}
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ npx wrangler deploy -c wasm-wrangler.toml
|
||||
## Security Features
|
||||
|
||||
- **Origin validation**: Only allows requests from configured origins
|
||||
- **Rate limiting**: 100 requests/minute per IP (requires KV namespace)
|
||||
- **Rate limiting**: 100 requests/minute per IP, per /64 for IPv6 (requires KV namespace; fails open on KV errors)
|
||||
- **File type restrictions**: Only WASM-related files (.js, .wasm, .data, etc.)
|
||||
- **Size limits**: Max 100MB per file
|
||||
- **Caching**: Reduces origin requests and improves performance
|
||||
|
||||
+245
-78
@@ -13,13 +13,11 @@
|
||||
*/
|
||||
|
||||
const ALLOWED_PATH_PATTERNS = [
|
||||
/\.crt$/i,
|
||||
/\.cer$/i,
|
||||
/\.pem$/i,
|
||||
/\/certs\//i,
|
||||
/\/ocsp/i,
|
||||
/\/crl/i,
|
||||
/caIssuers/i,
|
||||
/\.(crt|cer|pem|der|p7c|p7b)$/i,
|
||||
/(^|\/)certs(\/|$)/i,
|
||||
/(^|\/)ocsp(\/|$)/i,
|
||||
/(^|\/)crl(\/|$)/i,
|
||||
/(^|\/)caissuers(\/|$)/i,
|
||||
];
|
||||
|
||||
const ALLOWED_TSA_HOSTS = new Set([
|
||||
@@ -49,6 +47,8 @@ const RATE_LIMIT_WINDOW_MS = 60 * 1000;
|
||||
|
||||
const MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024;
|
||||
|
||||
let warnedNoProxySecret = false;
|
||||
|
||||
async function verifySignature(message, signature, secret) {
|
||||
try {
|
||||
const encoder = new TextEncoder();
|
||||
@@ -81,46 +81,154 @@ function isAllowedOrigin(origin) {
|
||||
return ALLOWED_ORIGINS.includes(origin);
|
||||
}
|
||||
|
||||
function parseIPv4(address) {
|
||||
const match = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/.exec(address);
|
||||
if (!match) return null;
|
||||
const octets = match.slice(1).map(Number);
|
||||
if (octets.some((octet) => octet > 255)) return null;
|
||||
return octets.reduce((value, octet) => value * 256 + octet, 0);
|
||||
}
|
||||
|
||||
function parseIPv6(address) {
|
||||
let text = address.toLowerCase();
|
||||
const embedded = /^(.*:)(\d+\.\d+\.\d+\.\d+)$/.exec(text);
|
||||
if (embedded) {
|
||||
const ipv4 = parseIPv4(embedded[2]);
|
||||
if (ipv4 === null) return null;
|
||||
text = `${embedded[1]}${Math.floor(ipv4 / 65536).toString(16)}:${(ipv4 % 65536).toString(16)}`;
|
||||
}
|
||||
const sections = text.split('::');
|
||||
if (sections.length > 2) return null;
|
||||
const head = sections[0] ? sections[0].split(':') : [];
|
||||
const tail =
|
||||
sections.length === 2 && sections[1] ? sections[1].split(':') : [];
|
||||
const missing = 8 - head.length - tail.length;
|
||||
if (sections.length === 1 ? missing !== 0 : missing < 1) return null;
|
||||
const groups = [...head, ...Array(missing).fill('0'), ...tail];
|
||||
if (!groups.every((group) => /^[0-9a-f]{1,4}$/.test(group))) return null;
|
||||
return groups.map((group) => parseInt(group, 16));
|
||||
}
|
||||
|
||||
const BLOCKED_IPV4_RANGES = [
|
||||
'0.0.0.0/8',
|
||||
'10.0.0.0/8',
|
||||
'100.64.0.0/10',
|
||||
'127.0.0.0/8',
|
||||
'169.254.0.0/16',
|
||||
'172.16.0.0/12',
|
||||
'192.0.0.0/24',
|
||||
'192.0.2.0/24',
|
||||
'192.168.0.0/16',
|
||||
'198.18.0.0/15',
|
||||
'198.51.100.0/24',
|
||||
'203.0.113.0/24',
|
||||
'224.0.0.0/4',
|
||||
'240.0.0.0/4',
|
||||
].map((cidr) => {
|
||||
const [address, prefixLength] = cidr.split('/');
|
||||
return { base: parseIPv4(address), size: 2 ** (32 - Number(prefixLength)) };
|
||||
});
|
||||
|
||||
const BLOCKED_IPV6_RANGES = [
|
||||
'::/128',
|
||||
'::1/128',
|
||||
'::/96',
|
||||
'::ffff:0:0/96',
|
||||
'64:ff9b::/96',
|
||||
'64:ff9b:1::/48',
|
||||
'100::/64',
|
||||
'2001::/32',
|
||||
'2001:db8::/32',
|
||||
'2002::/16',
|
||||
'fc00::/7',
|
||||
'fe80::/10',
|
||||
'fec0::/10',
|
||||
'ff00::/8',
|
||||
].map((cidr) => {
|
||||
const [address, prefixLength] = cidr.split('/');
|
||||
return { groups: parseIPv6(address), prefixLength: Number(prefixLength) };
|
||||
});
|
||||
|
||||
function isBlockedIPv4(value) {
|
||||
return BLOCKED_IPV4_RANGES.some(
|
||||
({ base, size }) => value >= base && value < base + size
|
||||
);
|
||||
}
|
||||
|
||||
function isBlockedIPv6(groups) {
|
||||
return BLOCKED_IPV6_RANGES.some((range) =>
|
||||
range.groups.every((group, index) => {
|
||||
const bitsInGroup = Math.min(
|
||||
16,
|
||||
Math.max(0, range.prefixLength - index * 16)
|
||||
);
|
||||
const groupMask = (0xffff << (16 - bitsInGroup)) & 0xffff;
|
||||
return (groups[index] & groupMask) === (group & groupMask);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
function isBlockedIp(address) {
|
||||
const ipv4 = parseIPv4(address);
|
||||
if (ipv4 !== null) return isBlockedIPv4(ipv4);
|
||||
const ipv6Groups = parseIPv6(address);
|
||||
if (ipv6Groups !== null) return isBlockedIPv6(ipv6Groups);
|
||||
return true;
|
||||
}
|
||||
|
||||
function isIpLiteral(host) {
|
||||
return /^[\d.]+$/.test(host) || host.includes(':');
|
||||
}
|
||||
|
||||
function getRateLimitKey(ip) {
|
||||
const ipv6Groups = ip.includes(':') ? parseIPv6(ip) : null;
|
||||
if (!ipv6Groups) return ip;
|
||||
return `${ipv6Groups
|
||||
.slice(0, 4)
|
||||
.map((group) => group.toString(16))
|
||||
.join(':')}::/64`;
|
||||
}
|
||||
|
||||
function isPrivateOrReservedHost(hostname) {
|
||||
if (
|
||||
/^10\./.test(hostname) ||
|
||||
/^172\.(1[6-9]|2[0-9]|3[0-1])\./.test(hostname) ||
|
||||
/^192\.168\./.test(hostname) ||
|
||||
/^169\.254\./.test(hostname) || // link-local (cloud metadata)
|
||||
/^100\.(6[4-9]|[7-9]\d|1[0-1]\d|12[0-7])\./.test(hostname) || // CGNAT
|
||||
/^127\./.test(hostname) ||
|
||||
/^0\./.test(hostname)
|
||||
) {
|
||||
const host = hostname
|
||||
.toLowerCase()
|
||||
.replace(/^\[|\]$/g, '')
|
||||
.replace(/\.$/, '');
|
||||
|
||||
if (['localhost', 'localhost.localdomain'].includes(host)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (/^\d+$/.test(hostname)) {
|
||||
return true;
|
||||
}
|
||||
return isIpLiteral(host) && isBlockedIp(host);
|
||||
}
|
||||
|
||||
const lower = hostname.toLowerCase().replace(/^\[|\]$/g, '');
|
||||
if (
|
||||
lower === '::1' ||
|
||||
lower.startsWith('::ffff:') ||
|
||||
lower.startsWith('fe80') ||
|
||||
lower.startsWith('fc') ||
|
||||
lower.startsWith('fd') ||
|
||||
lower.startsWith('ff')
|
||||
) {
|
||||
return true;
|
||||
async function hostnameResolvesToPrivate(hostname) {
|
||||
const clean = hostname
|
||||
.toLowerCase()
|
||||
.replace(/^\[|\]$/g, '')
|
||||
.replace(/\.$/, '');
|
||||
if (isPrivateOrReservedHost(clean)) return true;
|
||||
if (isIpLiteral(clean)) return false;
|
||||
const ips = [];
|
||||
for (const type of ['A', 'AAAA']) {
|
||||
try {
|
||||
const res = await fetch(
|
||||
`https://1.1.1.1/dns-query?name=${encodeURIComponent(clean)}&type=${type}`,
|
||||
{ headers: { accept: 'application/dns-json' } }
|
||||
);
|
||||
if (!res.ok) return true;
|
||||
const data = await res.json();
|
||||
for (const ans of data.Answer || []) {
|
||||
if (ans && (ans.type === 1 || ans.type === 28) && ans.data) {
|
||||
ips.push(String(ans.data));
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const blockedNames = [
|
||||
'localhost',
|
||||
'localhost.localdomain',
|
||||
'0.0.0.0',
|
||||
'[::1]',
|
||||
];
|
||||
if (blockedNames.includes(hostname.toLowerCase())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
if (ips.length === 0) return true;
|
||||
return ips.some((ip) => isBlockedIp(ip));
|
||||
}
|
||||
|
||||
function isValidCertificateUrl(urlString) {
|
||||
@@ -181,7 +289,7 @@ function handleOptions(request) {
|
||||
}
|
||||
|
||||
export default {
|
||||
async fetch(request, env, ctx) {
|
||||
async fetch(request, env) {
|
||||
const url = new URL(request.url);
|
||||
const origin = request.headers.get('Origin');
|
||||
|
||||
@@ -190,6 +298,10 @@ export default {
|
||||
}
|
||||
|
||||
// NOTE: If you are selfhosting this proxy, you can remove this check, or can set it to only accept requests from your own domain
|
||||
// SECURITY: The Origin allow-list and the optional PROXY_SECRET HMAC are anti-abuse controls, NOT a security boundary — the Origin
|
||||
// header is forgeable by non-browser clients and the HMAC secret ships in the public client bundle. The real SSRF defense is the
|
||||
// private/reserved-IP resolution check (hostnameResolvesToPrivate). Deployments running this off Cloudflare cannot fully close the
|
||||
// DNS-rebinding gap in code and MUST add network egress filtering (see docs/self-hosting/cors-proxy.md).
|
||||
if (!isAllowedOrigin(origin)) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
@@ -293,7 +405,8 @@ export default {
|
||||
const now = Date.now();
|
||||
if (
|
||||
isNaN(requestTime) ||
|
||||
Math.abs(now - requestTime) > MAX_TIMESTAMP_AGE_MS
|
||||
requestTime > now + 60000 ||
|
||||
now - requestTime > MAX_TIMESTAMP_AGE_MS
|
||||
) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
@@ -332,61 +445,99 @@ export default {
|
||||
}
|
||||
);
|
||||
}
|
||||
} else if (!warnedNoProxySecret) {
|
||||
warnedNoProxySecret = true;
|
||||
console.warn(
|
||||
'[CORS Proxy] PROXY_SECRET is not set — request signatures are not verified, so the proxy is callable by any client that can ' +
|
||||
'send an allowed Origin header. Set PROXY_SECRET to deter casual abuse (note: it ships in the public client bundle, so it is ' +
|
||||
'not a real authentication boundary), and add network egress filtering if running off Cloudflare.'
|
||||
);
|
||||
}
|
||||
|
||||
const clientIP = request.headers.get('CF-Connecting-IP') || 'unknown';
|
||||
const rateLimitKey = `ratelimit:${clientIP}`;
|
||||
const rateLimitKey = `ratelimit:${getRateLimitKey(clientIP)}`;
|
||||
const now = Date.now();
|
||||
|
||||
if (env.RATE_LIMIT_KV) {
|
||||
const rateLimitData = await env.RATE_LIMIT_KV.get(rateLimitKey, {
|
||||
type: 'json',
|
||||
});
|
||||
const requests = rateLimitData?.requests || [];
|
||||
try {
|
||||
const rateLimitData = await env.RATE_LIMIT_KV.get(rateLimitKey, {
|
||||
type: 'json',
|
||||
});
|
||||
const requests = rateLimitData?.requests || [];
|
||||
|
||||
const recentRequests = requests.filter(
|
||||
(t) => now - t < RATE_LIMIT_WINDOW_MS
|
||||
);
|
||||
const recentRequests = requests.filter(
|
||||
(t) => now - t < RATE_LIMIT_WINDOW_MS
|
||||
);
|
||||
|
||||
if (recentRequests.length >= RATE_LIMIT_MAX_REQUESTS) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
error: 'Rate limit exceeded',
|
||||
message: `Maximum ${RATE_LIMIT_MAX_REQUESTS} requests per minute. Please try again later.`,
|
||||
retryAfter: Math.ceil(
|
||||
(recentRequests[0] + RATE_LIMIT_WINDOW_MS - now) / 1000
|
||||
),
|
||||
}),
|
||||
{
|
||||
status: 429,
|
||||
headers: {
|
||||
...corsHeaders(origin),
|
||||
'Content-Type': 'application/json',
|
||||
'Retry-After': Math.ceil(
|
||||
if (recentRequests.length >= RATE_LIMIT_MAX_REQUESTS) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
error: 'Rate limit exceeded',
|
||||
message: `Maximum ${RATE_LIMIT_MAX_REQUESTS} requests per minute. Please try again later.`,
|
||||
retryAfter: Math.ceil(
|
||||
(recentRequests[0] + RATE_LIMIT_WINDOW_MS - now) / 1000
|
||||
).toString(),
|
||||
},
|
||||
),
|
||||
}),
|
||||
{
|
||||
status: 429,
|
||||
headers: {
|
||||
...corsHeaders(origin),
|
||||
'Content-Type': 'application/json',
|
||||
'Retry-After': Math.ceil(
|
||||
(recentRequests[0] + RATE_LIMIT_WINDOW_MS - now) / 1000
|
||||
).toString(),
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
recentRequests.push(now);
|
||||
await env.RATE_LIMIT_KV.put(
|
||||
rateLimitKey,
|
||||
JSON.stringify({ requests: recentRequests }),
|
||||
{
|
||||
expirationTtl: 120,
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(
|
||||
'[CORS Proxy] Rate limit KV error, allowing request:',
|
||||
error
|
||||
);
|
||||
}
|
||||
|
||||
recentRequests.push(now);
|
||||
await env.RATE_LIMIT_KV.put(
|
||||
rateLimitKey,
|
||||
JSON.stringify({ requests: recentRequests }),
|
||||
{
|
||||
expirationTtl: 120,
|
||||
}
|
||||
);
|
||||
} else {
|
||||
console.warn(
|
||||
'[CORS Proxy] RATE_LIMIT_KV not configured — rate limiting is disabled'
|
||||
);
|
||||
}
|
||||
|
||||
let targetHostname;
|
||||
try {
|
||||
targetHostname = new URL(targetUrl).hostname;
|
||||
} catch {
|
||||
targetHostname = '';
|
||||
}
|
||||
if (!targetHostname || (await hostnameResolvesToPrivate(targetHostname))) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
error: 'Forbidden destination',
|
||||
message: 'The requested host is not permitted',
|
||||
}),
|
||||
{
|
||||
status: 403,
|
||||
headers: {
|
||||
...corsHeaders(origin),
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
const upstreamInit = {
|
||||
method: request.method,
|
||||
redirect: 'manual',
|
||||
signal: AbortSignal.timeout(10000),
|
||||
headers: {
|
||||
'User-Agent': 'BentoPDF-CertProxy/1.0',
|
||||
},
|
||||
@@ -399,6 +550,22 @@ export default {
|
||||
|
||||
const response = await fetch(targetUrl, upstreamInit);
|
||||
|
||||
if (response.status >= 300 && response.status < 400) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
error: 'Redirect blocked',
|
||||
message: 'Upstream redirects are not allowed',
|
||||
}),
|
||||
{
|
||||
status: 502,
|
||||
headers: {
|
||||
...corsHeaders(origin),
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
@@ -480,7 +647,7 @@ export default {
|
||||
response.headers.get('Content-Type')
|
||||
),
|
||||
'Content-Length': totalSize.toString(),
|
||||
'Cache-Control': 'public, max-age=86400',
|
||||
'Cache-Control': 'no-store',
|
||||
'X-Content-Type-Options': 'nosniff',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -39,9 +39,38 @@ const ALLOWED_EXTENSIONS = [
|
||||
'.mem',
|
||||
'.asm.js',
|
||||
'.worker.js',
|
||||
'.html',
|
||||
'.whl',
|
||||
];
|
||||
|
||||
const SAFE_SUBPATH = /^\/[A-Za-z0-9._/-]*$/;
|
||||
|
||||
function isSafeSubpath(subpath) {
|
||||
return (
|
||||
SAFE_SUBPATH.test(subpath) &&
|
||||
!subpath.split('/').some((segment) => segment === '.' || segment === '..')
|
||||
);
|
||||
}
|
||||
|
||||
function getRateLimitKey(ip) {
|
||||
if (!ip.includes(':') || ip.includes('.')) return ip;
|
||||
const sections = ip.toLowerCase().split('::');
|
||||
if (sections.length > 2) return ip;
|
||||
const leadingGroups = sections[0] ? sections[0].split(':') : [];
|
||||
const trailingGroups = sections[1] ? sections[1].split(':') : [];
|
||||
const missing = 8 - leadingGroups.length - trailingGroups.length;
|
||||
if (sections.length === 1 ? missing !== 0 : missing < 1) return ip;
|
||||
const groups = [
|
||||
...leadingGroups,
|
||||
...Array(missing).fill('0'),
|
||||
...trailingGroups,
|
||||
];
|
||||
if (!groups.every((group) => /^[0-9a-f]{1,4}$/.test(group))) return ip;
|
||||
return `${groups
|
||||
.slice(0, 4)
|
||||
.map((group) => parseInt(group, 16).toString(16))
|
||||
.join(':')}::/64`;
|
||||
}
|
||||
|
||||
function isAllowedOrigin(origin) {
|
||||
if (!origin) return true; // Allow no-origin requests (e.g., direct browser navigation)
|
||||
return ALLOWED_ORIGINS.some((allowed) =>
|
||||
@@ -66,6 +95,7 @@ function corsHeaders(origin) {
|
||||
'Access-Control-Expose-Headers':
|
||||
'Content-Length, Content-Range, Content-Type',
|
||||
'Access-Control-Max-Age': '86400',
|
||||
'X-Content-Type-Options': 'nosniff',
|
||||
};
|
||||
}
|
||||
|
||||
@@ -89,7 +119,6 @@ function getContentType(pathname) {
|
||||
'.so': 'application/octet-stream',
|
||||
'.zip': 'application/zip',
|
||||
'.mem': 'application/octet-stream',
|
||||
'.html': 'text/html',
|
||||
};
|
||||
return contentTypes[ext] || 'application/octet-stream';
|
||||
}
|
||||
@@ -115,7 +144,34 @@ async function proxyRequest(request, env, sourceBaseUrl, subpath, origin) {
|
||||
? sourceBaseUrl.slice(0, -1)
|
||||
: sourceBaseUrl;
|
||||
const normalizedPath = subpath.startsWith('/') ? subpath : `/${subpath}`;
|
||||
const targetUrl = `${normalizedBase}${normalizedPath}`;
|
||||
|
||||
let targetUrl = null;
|
||||
if (isSafeSubpath(normalizedPath)) {
|
||||
try {
|
||||
const candidate = new URL(`${normalizedBase}${normalizedPath}`).href;
|
||||
if (candidate.startsWith(new URL(`${normalizedBase}/`).href)) {
|
||||
targetUrl = candidate;
|
||||
}
|
||||
} catch {
|
||||
targetUrl = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (!targetUrl) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
error: 'Invalid path',
|
||||
message: 'The requested path is not allowed.',
|
||||
}),
|
||||
{
|
||||
status: 400,
|
||||
headers: {
|
||||
...corsHeaders(origin),
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (!isAllowedFile(normalizedPath)) {
|
||||
return new Response(
|
||||
@@ -151,8 +207,6 @@ async function proxyRequest(request, env, sourceBaseUrl, subpath, origin) {
|
||||
JSON.stringify({
|
||||
error: 'Failed to fetch resource',
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
targetUrl: targetUrl,
|
||||
}),
|
||||
{
|
||||
status: response.status,
|
||||
@@ -204,14 +258,14 @@ async function proxyRequest(request, env, sourceBaseUrl, subpath, origin) {
|
||||
'Content-Type': getContentType(normalizedPath),
|
||||
'Content-Length': bodyData.byteLength.toString(),
|
||||
'Cache-Control': `public, max-age=${CACHE_TTL_SECONDS}`,
|
||||
'X-Proxied-From': new URL(targetUrl).hostname,
|
||||
},
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('[WASM Proxy] Fetch error:', error);
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
error: 'Proxy error',
|
||||
message: error.message,
|
||||
message: 'Failed to fetch the requested resource',
|
||||
}),
|
||||
{
|
||||
status: 500,
|
||||
@@ -260,42 +314,49 @@ export default {
|
||||
|
||||
if (env.RATE_LIMIT_KV) {
|
||||
const clientIP = request.headers.get('CF-Connecting-IP') || 'unknown';
|
||||
const rateLimitKey = `wasm-ratelimit:${clientIP}`;
|
||||
const rateLimitKey = `wasm-ratelimit:${getRateLimitKey(clientIP)}`;
|
||||
const now = Date.now();
|
||||
|
||||
const rateLimitData = await env.RATE_LIMIT_KV.get(rateLimitKey, {
|
||||
type: 'json',
|
||||
});
|
||||
const requests = rateLimitData?.requests || [];
|
||||
const recentRequests = requests.filter(
|
||||
(t) => now - t < RATE_LIMIT_WINDOW_MS
|
||||
);
|
||||
try {
|
||||
const rateLimitData = await env.RATE_LIMIT_KV.get(rateLimitKey, {
|
||||
type: 'json',
|
||||
});
|
||||
const requests = rateLimitData?.requests || [];
|
||||
const recentRequests = requests.filter(
|
||||
(t) => now - t < RATE_LIMIT_WINDOW_MS
|
||||
);
|
||||
|
||||
if (recentRequests.length >= RATE_LIMIT_MAX_REQUESTS) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
error: 'Rate limit exceeded',
|
||||
message: `Maximum ${RATE_LIMIT_MAX_REQUESTS} requests per minute.`,
|
||||
}),
|
||||
if (recentRequests.length >= RATE_LIMIT_MAX_REQUESTS) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
error: 'Rate limit exceeded',
|
||||
message: `Maximum ${RATE_LIMIT_MAX_REQUESTS} requests per minute.`,
|
||||
}),
|
||||
{
|
||||
status: 429,
|
||||
headers: {
|
||||
...corsHeaders(origin),
|
||||
'Content-Type': 'application/json',
|
||||
'Retry-After': '60',
|
||||
},
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
recentRequests.push(now);
|
||||
await env.RATE_LIMIT_KV.put(
|
||||
rateLimitKey,
|
||||
JSON.stringify({ requests: recentRequests }),
|
||||
{
|
||||
status: 429,
|
||||
headers: {
|
||||
...corsHeaders(origin),
|
||||
'Content-Type': 'application/json',
|
||||
'Retry-After': '60',
|
||||
},
|
||||
expirationTtl: 120,
|
||||
}
|
||||
);
|
||||
} catch (error) {
|
||||
console.error(
|
||||
'[WASM Proxy] Rate limit KV error, allowing request:',
|
||||
error
|
||||
);
|
||||
}
|
||||
|
||||
recentRequests.push(now);
|
||||
await env.RATE_LIMIT_KV.put(
|
||||
rateLimitKey,
|
||||
JSON.stringify({ requests: recentRequests }),
|
||||
{
|
||||
expirationTtl: 120,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
if (pathname.startsWith('/pymupdf/')) {
|
||||
|
||||
@@ -3,7 +3,7 @@ main = "cors-proxy-worker.js"
|
||||
compatibility_date = "2024-01-01"
|
||||
|
||||
# Deploy to Cloudflare's global network
|
||||
# If you are self hosting change the name to your worker name
|
||||
# If you are self-hosting, change the name to your worker name
|
||||
# Run: npx wrangler deploy
|
||||
|
||||
# =============================================================================
|
||||
|
||||
+70
-28
@@ -49,6 +49,7 @@
|
||||
<meta name="twitter:site" content="@BentoPDF" />
|
||||
|
||||
<link href="/src/css/styles.css" rel="stylesheet" />
|
||||
<link href="/src/css/landing.css" rel="stylesheet" />
|
||||
|
||||
<!-- Web App Manifest -->
|
||||
<link rel="manifest" href="/site.webmanifest" />
|
||||
@@ -75,38 +76,78 @@
|
||||
<link rel="icon" href="/favicon.ico" sizes="32x32" />
|
||||
</head>
|
||||
|
||||
<body class="antialiased bg-gray-900 text-gray-300">
|
||||
<body class="lp antialiased">
|
||||
{{> navbar }}
|
||||
|
||||
<div id="app" class="min-h-screen container mx-auto p-4 md:p-8">
|
||||
<section id="contact-hero" class="text-center py-16 md:py-24">
|
||||
<h1
|
||||
class="text-4xl md:text-5xl font-bold text-white mb-4"
|
||||
data-i18n="contact.title"
|
||||
>
|
||||
Get in Touch
|
||||
</h1>
|
||||
<p
|
||||
class="text-lg md:text-xl text-gray-400 max-w-3xl mx-auto"
|
||||
data-i18n="contact.subtitle"
|
||||
>
|
||||
We'd love to hear from you. Whether you have a question, feedback, or
|
||||
a feature request, please don't hesitate to reach out.
|
||||
</p>
|
||||
<div id="app">
|
||||
<section id="contact-hero" class="lp-sec lp-sec--first">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-cta">
|
||||
<div>
|
||||
<h1 class="lp-h2">
|
||||
<span class="line" data-i18n="contact.title">Get in Touch</span>
|
||||
</h1>
|
||||
<p class="lp-head-p" data-i18n="contact.subtitle">
|
||||
We'd love to hear from you. Whether you have a question,
|
||||
feedback, or a feature request, please don't hesitate to reach
|
||||
out.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="max-w-2xl mx-auto text-center py-8">
|
||||
<p class="text-lg text-gray-400">
|
||||
<span data-i18n="contact.email"
|
||||
>You can reach us directly by email at:</span
|
||||
>
|
||||
<a
|
||||
href="mailto:[email protected]"
|
||||
class="text-indigo-400 underline hover:text-indigo-300"
|
||||
>[email protected]</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
<section id="contact-channels" class="lp-sec lp-band">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-grid lp-grid--2 lp-cross">
|
||||
<a class="lp-cell lp-reveal" href="mailto:[email protected]">
|
||||
<span class="lp-tile"><i data-lucide="mail"></i></span>
|
||||
<h3 data-i18n="contact.emailTitle">Email</h3>
|
||||
<p data-i18n="contact.email">
|
||||
You can reach us directly by email at:
|
||||
</p>
|
||||
<b>[email protected]</b>
|
||||
</a>
|
||||
|
||||
<a
|
||||
class="lp-cell lp-reveal"
|
||||
href="https://github.com/alam00000/bentopdf/issues"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<span class="lp-tile"><i data-lucide="github"></i></span>
|
||||
<h3>GitHub</h3>
|
||||
<p data-i18n="contact.githubText">
|
||||
Report a bug, request a feature, or read the source.
|
||||
</p>
|
||||
<b>github.com/alam00000/bentopdf</b>
|
||||
</a>
|
||||
|
||||
<a
|
||||
class="lp-cell lp-reveal"
|
||||
href="https://discord.gg/Bgq3Ay3f2w"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<span class="lp-tile"><i data-lucide="message-circle"></i></span>
|
||||
<h3>Discord</h3>
|
||||
<p data-i18n="contact.discordText">
|
||||
Join the community to chat with us and other users.
|
||||
</p>
|
||||
<b>discord.gg/Bgq3Ay3f2w</b>
|
||||
</a>
|
||||
|
||||
<a class="lp-cell lp-reveal" href="faq.html">
|
||||
<span class="lp-tile"><i data-lucide="help-circle"></i></span>
|
||||
<h3 data-i18n="footer.faqLink">FAQ</h3>
|
||||
<p data-i18n="contact.faqText">
|
||||
Find quick answers to the questions we get most often.
|
||||
</p>
|
||||
<b data-i18n="contact.faqLink">Read the FAQ</b>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
{{> footer }}
|
||||
@@ -114,6 +155,7 @@
|
||||
<script type="module" src="src/js/utils/lucide-init.ts"></script>
|
||||
<script type="module" src="src/js/main.ts"></script>
|
||||
<script type="module" src="src/js/mobileMenu.ts"></script>
|
||||
<script type="module" src="src/js/landing.ts"></script>
|
||||
<!-- JSON-LD Schema -->
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@ export default defineConfig({
|
||||
description: "Documentation for BentoPDF - The free, open-source, privacy-first PDF toolkit",
|
||||
base: '/docs/',
|
||||
cleanUrls: true,
|
||||
metaChunk: true,
|
||||
|
||||
transformPageData(pageData) {
|
||||
const relPath = pageData.relativePath.replace(/\.md$/, '')
|
||||
@@ -115,7 +116,7 @@ export default defineConfig({
|
||||
{ text: 'PDF to Excel', link: '/tools/pdf-to-excel' },
|
||||
{ text: 'PDF to Greyscale', link: '/tools/pdf-to-greyscale' },
|
||||
{ text: 'PDF to JSON', link: '/tools/pdf-to-json' },
|
||||
{ text: 'PDF to Word', link: '/tools/pdf-to-docx' },
|
||||
{ text: 'PDF to Word', link: '/tools/pdf-to-word' },
|
||||
{ text: 'Extract Images', link: '/tools/extract-images' },
|
||||
{ text: 'PDF to Markdown', link: '/tools/pdf-to-markdown' },
|
||||
{ text: 'Prepare PDF for AI', link: '/tools/prepare-pdf-for-ai' },
|
||||
@@ -132,6 +133,7 @@ export default defineConfig({
|
||||
{ text: 'OCR PDF', link: '/tools/ocr-pdf' },
|
||||
{ text: 'Merge PDF', link: '/tools/merge-pdf' },
|
||||
{ text: 'Alternate & Mix Pages', link: '/tools/alternate-merge' },
|
||||
{ text: 'Duplex Collate', link: '/tools/duplex-collate' },
|
||||
{ text: 'Organize & Duplicate', link: '/tools/organize-pdf' },
|
||||
{ text: 'Add Attachments', link: '/tools/add-attachments' },
|
||||
{ text: 'Extract Attachments', link: '/tools/extract-attachments' },
|
||||
@@ -175,9 +177,9 @@ export default defineConfig({
|
||||
text: 'Secure PDF',
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ text: 'Encrypt PDF', link: '/tools/encrypt-pdf' },
|
||||
{ text: 'Protect PDF', link: '/tools/protect-pdf' },
|
||||
{ text: 'Sanitize PDF', link: '/tools/sanitize-pdf' },
|
||||
{ text: 'Decrypt PDF', link: '/tools/decrypt-pdf' },
|
||||
{ text: 'Unlock PDF', link: '/tools/unlock-pdf' },
|
||||
{ text: 'Flatten PDF', link: '/tools/flatten-pdf' },
|
||||
{ text: 'Remove Metadata', link: '/tools/remove-metadata' },
|
||||
{ text: 'Change Permissions', link: '/tools/change-permissions' },
|
||||
|
||||
@@ -123,9 +123,17 @@ The included Cloudflare Worker has several security measures:
|
||||
| **Private IP Blocking** | Blocks IPv4/IPv6 private ranges, link-local, loopback, decimal IPs, and cloud metadata |
|
||||
| **Content-Type Safety** | Only returns safe certificate MIME types, blocks upstream content-type injection |
|
||||
| **File Size Limit** | Streams response with 10MB limit, aborts mid-download if exceeded |
|
||||
| **Rate Limiting** | 60 requests per IP per minute (requires KV) |
|
||||
| **Rate Limiting** | 60 requests per minute per IP or IPv6 /64 (requires KV, fails open on KV errors) |
|
||||
| **HMAC Signatures** | Optional client-side signing (deters casual abuse) |
|
||||
|
||||
### DNS rebinding (self-hosting off Cloudflare)
|
||||
|
||||
The worker rejects any URL that resolves to a private or internal IP. It can't use a fixed allowlist of hosts, since certificate-chain URLs point to whatever CA issued the cert (FNMT, corporate CAs, and so on), so the destinations aren't known up front. That leaves a small rebinding window: someone running the DNS for their own domain could hand a public IP to the safety check and a private one to the real request a moment later.
|
||||
|
||||
On Cloudflare this isn't exploitable — Workers can't reach private IPs or the `169.254.169.254` metadata endpoint, so a rebind lands on nothing. Just don't give the worker a way in: don't attach a Tunnel, Service, or private-network binding (it only needs `RATE_LIMIT_KV`).
|
||||
|
||||
If you run this off Cloudflare (workerd, Node, and the like) inside a VPC, the runtime _can_ reach internal IPs. Put an egress firewall in front of it and block the private ranges — `10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`, `127.0.0.0/8`, `169.254.0.0/16`, and their IPv6 equivalents. App code can't enforce that once you're off Cloudflare.
|
||||
|
||||
## Disabling the Proxy
|
||||
|
||||
If you don't want to use a CORS proxy, set the environment variable to an empty string:
|
||||
|
||||
@@ -115,6 +115,7 @@ docker run -d -p 3000:8080 bentopdf:custom
|
||||
| `VITE_BRAND_LOGO` | Logo path relative to `public/` | `images/favicon-no-bg.svg` |
|
||||
| `VITE_FOOTER_TEXT` | Custom footer/copyright text | `© 2026 BentoPDF. All rights reserved.` |
|
||||
| `DISABLE_TOOLS` | Comma-separated tool IDs to hide | _(empty; all tools enabled)_ |
|
||||
| `DISABLE_GITHUB_STARS` | Skip the GitHub star-count fetch on page load and drop `api.github.com` from the CSP. Simple Mode builds always skip it. | `false` |
|
||||
|
||||
WASM module URLs are pre-configured with CDN defaults — all advanced features work out of the box. Override these for air-gapped or self-hosted deployments.
|
||||
|
||||
@@ -125,10 +126,11 @@ The nginx image ships with an enforcing `Content-Security-Policy` header. The CS
|
||||
As a result:
|
||||
|
||||
- If you override `VITE_CORS_PROXY_URL` or `VITE_WASM_*_URL` at build time, the CSP permits those origins automatically — no extra config needed.
|
||||
- If you configure custom WASM URLs at _runtime_ via the in-app Advanced Settings page, those origins are **not** in the CSP and the browser will block fetches to them. Runtime configuration is intended for experimentation; for permanent custom URLs set the matching `VITE_*` build arg.
|
||||
- Air-gapped deployments that override all three `VITE_WASM_*_URL` values also get the public `cdn.jsdelivr.net` removed from CSP (each default is replaced, not appended). Similarly, setting `VITE_CORS_PROXY_URL` replaces the public `bentopdf-cors-proxy.bentopdf.workers.dev` default.
|
||||
- For URLs on `cdn.jsdelivr.net`, `script-src` allows only the exact versioned package folder, for example `https://cdn.jsdelivr.net/npm/@bentopdf/[email protected]/`, not the whole CDN. jsDelivr serves any public npm package or GitHub repository, so allowing the whole host would let any of them run on your instance. URLs on any other host are allowed by origin.
|
||||
- If you configure custom WASM URLs at _runtime_ via the in-app Advanced Settings page, those origins are **not** in the CSP and the browser will block fetches to them. This also applies to a different version of the same package on `cdn.jsdelivr.net`, because only the version set at build time is allowed. Runtime configuration is intended for experimentation; for permanent custom URLs set the matching `VITE_*` build arg.
|
||||
- Air-gapped deployments that override all three `VITE_WASM_*_URL` values also get those `cdn.jsdelivr.net` package folders removed from CSP (each default is replaced, not appended). The Tesseract OCR defaults on `cdn.jsdelivr.net` stay in the policy until you also set the three `VITE_TESSERACT_*` values. Similarly, setting `VITE_CORS_PROXY_URL` replaces the public `bentopdf-cors-proxy.bentopdf.workers.dev` default.
|
||||
|
||||
The CSP includes `'unsafe-eval'` in `script-src` because the LibreOffice WASM runtime (used by Word/Excel/PowerPoint conversion tools) compiles internal dispatch code via `new Function()`. Removing it would break all LibreOffice-backed tools. If you build in `SIMPLE_MODE` (without LibreOffice), you can manually edit the generated `security-headers.conf` to drop `'unsafe-eval'` for a stricter policy.
|
||||
The CSP includes `'unsafe-eval'` in `script-src` because the LibreOffice WASM runtime (used by Word/Excel/PowerPoint conversion tools) and the wasm-vips image library (used by PDF to TIFF) compile internal dispatch code via `new Function()`. Removing it would break those tools. If you build in `SIMPLE_MODE` (without LibreOffice) and do not need PDF to TIFF, you can manually edit the generated `security-headers.conf` to drop `'unsafe-eval'` for a stricter policy.
|
||||
|
||||
For OCR, leave the `VITE_TESSERACT_*` variables empty to use the default online assets, or set all three together for self-hosted/offline OCR. Partial OCR overrides are rejected because the worker, core runtime, and traineddata directory must match. For fully offline searchable PDF output, also set `VITE_OCR_FONT_BASE_URL` so the OCR text-layer fonts are loaded from your internal server instead of the public Noto font URLs.
|
||||
|
||||
@@ -263,6 +265,16 @@ You can also disable specific features inside the PDF Editor (e.g., redaction, a
|
||||
|
||||
Categories are hierarchical — disabling a parent (e.g., `annotation`) disables all its children.
|
||||
|
||||
### Disabling the GitHub Star Counter
|
||||
|
||||
The navbar shows a live GitHub star count, fetched from `api.github.com` on page load. The only external request that isn't serving a PDF feature. Disable it at build time to remove the fetch code from the bundle and drop `api.github.com` from the Content-Security-Policy:
|
||||
|
||||
```bash
|
||||
docker build --build-arg DISABLE_GITHUB_STARS=true -t bentopdf .
|
||||
```
|
||||
|
||||
Simple Mode builds (`bentopdf-simple`) always skip the star counter — this flag is only needed on the Commercial build or custom full builds.
|
||||
|
||||
### Custom WASM URLs (Air-Gapped / Self-Hosted)
|
||||
|
||||
> [!IMPORTANT]
|
||||
|
||||
@@ -33,6 +33,13 @@ Add text or image watermarks to your PDF pages using a visual editor. You can po
|
||||
- **Opacity** -- Control image transparency.
|
||||
- **Scale** -- Resize the image watermark.
|
||||
|
||||
**Layout settings:**
|
||||
|
||||
- **Single** -- One watermark per page, positioned by dragging or with the position presets.
|
||||
- **Tiled** -- Repeats the watermark across the whole page in a diagonal grid that follows the rotation angle, so the mark covers the document from edge to edge.
|
||||
- **Horizontal gap** -- Spacing between tiles along the text direction, as a percentage of the watermark width (tiled mode only).
|
||||
- **Vertical gap** -- Spacing between tile rows, as a percentage of the watermark height (tiled mode only).
|
||||
|
||||
**General settings:**
|
||||
|
||||
- **Apply to all pages** -- When checked, the same watermark applies to every page. Uncheck to set individual watermarks per page.
|
||||
@@ -43,6 +50,7 @@ Add text or image watermarks to your PDF pages using a visual editor. You can po
|
||||
- Visual drag-and-drop positioning on a live PDF preview
|
||||
- Resizable watermark with corner handles
|
||||
- Text and image watermark modes
|
||||
- Single or full-page tiled (repeating) layout with adjustable spacing
|
||||
- Per-page or global watermark application
|
||||
- Page-by-page navigation in the preview
|
||||
- Opacity and rotation controls
|
||||
@@ -59,6 +67,7 @@ Add text or image watermarks to your PDF pages using a visual editor. You can po
|
||||
## Tips
|
||||
|
||||
- For diagonal watermarks across the page, set a rotation around 45 degrees and increase the font size.
|
||||
- Tiled mode makes a document much harder to reuse after cropping, since removing one mark still leaves dozens behind. Lower the opacity when tiling so the underlying text stays readable.
|
||||
- Image watermarks with transparent backgrounds (PNG format) blend more naturally with the document content.
|
||||
- If you need different watermark text on different pages, uncheck "Apply to all pages" and navigate page by page.
|
||||
|
||||
|
||||
@@ -56,6 +56,6 @@ If you set only an owner password (no user password), anyone can open the file b
|
||||
|
||||
## Related Tools
|
||||
|
||||
- [Encrypt PDF](./encrypt-pdf) -- simple password protection without granular permissions
|
||||
- [Decrypt PDF](./decrypt-pdf) -- remove encryption entirely
|
||||
- [Encrypt PDF](./protect-pdf) -- simple password protection without granular permissions
|
||||
- [Decrypt PDF](./unlock-pdf) -- remove encryption entirely
|
||||
- [Remove Restrictions](./remove-restrictions) -- strip all restrictions when you have the owner password
|
||||
|
||||
@@ -61,5 +61,5 @@ Signing may require an internet connection. The signing library fetches the cert
|
||||
|
||||
- [Validate Signature](./validate-signature-pdf) -- verify digital signatures in signed PDFs
|
||||
- [Flatten PDF](./flatten-pdf) -- flatten forms before signing to prevent modifications
|
||||
- [Encrypt PDF](./encrypt-pdf) -- add password protection on top of the digital signature
|
||||
- [Encrypt PDF](./protect-pdf) -- add password protection on top of the digital signature
|
||||
- [Remove Metadata](./remove-metadata) -- strip metadata before signing
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
---
|
||||
title: Duplex Collate
|
||||
description: Reorder duplex scan PDFs that contain front pages and back pages in separate blocks into proper front/back page order.
|
||||
---
|
||||
|
||||
# Duplex Collate
|
||||
|
||||
Duplex Collate is designed for ADF scan workflows where one PDF contains two blocks of pages:
|
||||
|
||||
- all front sides first
|
||||
- all back sides second
|
||||
|
||||
Instead of manually splitting and reassembling, this tool interleaves the two blocks into natural reading order: front1, back1, front2, back2, and so on.
|
||||
|
||||
## How It Works
|
||||
|
||||
1. Upload a single PDF created from duplex stack scanning.
|
||||
2. Set the split point where the front block ends.
|
||||
3. Choose back block handling:
|
||||
- **Reverse back block** (common when the stack is flipped before scanning backs)
|
||||
- **Keep back block as-is**
|
||||
4. Click **Collate PDF** to download the reordered result.
|
||||
|
||||
## Options
|
||||
|
||||
- **Auto-detect split (half)**: sets the split point to `ceil(totalPages / 2)`.
|
||||
- **Odd page warning**: warns when total pages are odd (often a scan mismatch).
|
||||
- **Uneven block confirmation**: asks for confirmation when front/back block sizes differ.
|
||||
- **Grouped export**: split the collated output into separate PDFs based on original document page count and download as ZIP.
|
||||
|
||||
## Output Behavior
|
||||
|
||||
- **Default**: one output PDF (single input PDF in, single output PDF out).
|
||||
- **Grouped mode**: output is chunked by your pages-per-document value; if multiple chunks are produced, they are downloaded as one ZIP, otherwise a single PDF is downloaded.
|
||||
|
||||
If block sizes are uneven, paired pages are collated first, and remaining unpaired pages are appended at the end.
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
- Restoring order after scanning a pile of double-sided forms in two passes.
|
||||
- Rebuilding front/back packets from office scanners that output all fronts then all backs.
|
||||
- Post-processing archive scans before splitting into per-document files.
|
||||
|
||||
## Tips
|
||||
|
||||
- Most duplex batches should have an even total page count.
|
||||
- If output looks inverted on backs, switch between **Reverse back block** and **Keep back block as-is**.
|
||||
- For 2-page originals (front+back), use grouped export with `2` pages per document.
|
||||
|
||||
## Related Tools
|
||||
|
||||
- [Alternate & Mix Pages](./alternate-merge)
|
||||
- [Split PDF](./split-pdf)
|
||||
- [Merge PDF](./merge-pdf)
|
||||
- [Organize & Duplicate](./organize-pdf)
|
||||
@@ -18,7 +18,7 @@ BentoPDF's PDF Editor lets you annotate, highlight, redact, comment, add shapes
|
||||
|
||||
- Full annotation toolbar with highlighting, underlining, strikethrough, and freehand drawing
|
||||
- Text insertion and commenting
|
||||
- Redaction tools for permanently removing sensitive content
|
||||
- Redaction tools that permanently remove marked content once you apply the redaction. If any marks haven't been applied when you click **Download Edited PDF**, the editor offers to apply them first.
|
||||
- Shape tools for rectangles, circles, lines, and arrows
|
||||
- Image insertion onto PDF pages
|
||||
- Built-in text search across the document
|
||||
@@ -37,6 +37,7 @@ BentoPDF's PDF Editor lets you annotate, highlight, redact, comment, add shapes
|
||||
|
||||
- You can open multiple PDFs at once and switch between them using the tab bar at the top of the editor.
|
||||
- The editor preserves the original PDF structure, so fonts, layouts, and form fields remain intact.
|
||||
- Marking text or an area for redaction doesn't remove anything until the redaction is applied. When you redact selected text, copies of it in the file's properties, bookmarks, comments, and attachments are also removed from the download, unless the file is encrypted.
|
||||
- For bulk watermarking or page numbering, use the dedicated tools instead for more control over formatting.
|
||||
|
||||
## Related Tools
|
||||
|
||||
@@ -48,4 +48,4 @@ The tool uses pdf-lib to flatten form fields (via `form.flatten()`) and a dedica
|
||||
- [Sanitize PDF](./sanitize-pdf) -- flatten forms plus remove metadata, scripts, and more
|
||||
- [Rasterize PDF](./rasterize-pdf) -- convert to image-based PDF for maximum flattening
|
||||
- [Font to Outline](./font-to-outline) -- flatten fonts to vector paths
|
||||
- [Encrypt PDF](./encrypt-pdf) -- lock the flattened PDF with a password
|
||||
- [Encrypt PDF](./protect-pdf) -- lock the flattened PDF with a password
|
||||
|
||||
+4
-3
@@ -95,7 +95,7 @@ Extract content from PDFs into images, documents, and data formats.
|
||||
- [**PDF to Excel**](./pdf-to-excel) — Extract tables from PDF and convert to Excel (XLSX).
|
||||
- [**PDF to Greyscale**](./pdf-to-greyscale) — Convert all colors to black and white.
|
||||
- [**PDF to JSON**](./pdf-to-json) — Convert PDF files to JSON format.
|
||||
- [**PDF to Word**](./pdf-to-docx) — Convert PDF files to editable Word documents.
|
||||
- [**PDF to Word**](./pdf-to-word) — Convert PDF files to editable Word documents.
|
||||
- [**Extract Images**](./extract-images) — Extract all embedded images from your PDF files.
|
||||
- [**PDF to Markdown**](./pdf-to-markdown) — Convert PDF text and tables to Markdown format.
|
||||
- [**Prepare PDF for AI**](./prepare-pdf-for-ai) — Extract PDF content as LlamaIndex JSON for RAG/LLM pipelines.
|
||||
@@ -117,6 +117,7 @@ Rearrange, combine, split, and manage your PDF pages and files.
|
||||
- [**OCR PDF**](./ocr-pdf) — Make a PDF searchable and copyable.
|
||||
- [**Merge PDF**](./merge-pdf) — Combine multiple PDFs into one file.
|
||||
- [**Alternate & Mix Pages**](./alternate-merge) — Merge PDFs by alternating pages from each PDF.
|
||||
- [**Duplex Collate**](./duplex-collate) — Reorder front/back scan blocks into proper page sequence.
|
||||
- [**Organize & Duplicate**](./organize-pdf) — Duplicate, reorder, and delete pages.
|
||||
- [**Add Attachments**](./add-attachments) — Embed one or more files into your PDF.
|
||||
- [**Extract Attachments**](./extract-attachments) — Extract all embedded files from PDF(s) as a ZIP.
|
||||
@@ -170,9 +171,9 @@ Protect, encrypt, and control access to your PDF documents.
|
||||
|
||||
<div class="tool-grid">
|
||||
|
||||
- [**Encrypt PDF**](./encrypt-pdf) — Lock your PDF by adding a password.
|
||||
- [**Encrypt PDF**](./protect-pdf) — Lock your PDF by adding a password.
|
||||
- [**Sanitize PDF**](./sanitize-pdf) — Remove metadata, annotations, scripts, and more.
|
||||
- [**Decrypt PDF**](./decrypt-pdf) — Unlock PDF by removing password protection.
|
||||
- [**Decrypt PDF**](./unlock-pdf) — Unlock PDF by removing password protection.
|
||||
- [**Flatten PDF**](./flatten-pdf) — Make form fields and annotations non-editable.
|
||||
- [**Remove Metadata**](./remove-metadata) — Strip hidden data from your PDF.
|
||||
- [**Change Permissions**](./change-permissions) — Set or change user permissions on a PDF.
|
||||
|
||||
@@ -39,5 +39,5 @@ Converts PDF files to Markdown (`.md`) format, preserving headings, paragraphs,
|
||||
## Related Tools
|
||||
|
||||
- [PDF to Text](./pdf-to-text)
|
||||
- [PDF to Word](./pdf-to-docx)
|
||||
- [PDF to Word](./pdf-to-word)
|
||||
- [Prepare PDF for AI](./prepare-pdf-for-ai)
|
||||
|
||||
@@ -40,4 +40,4 @@ This tool has no configurable options. All text content is extracted from every
|
||||
|
||||
- [PDF to Markdown](./pdf-to-markdown)
|
||||
- [Prepare PDF for AI](./prepare-pdf-for-ai)
|
||||
- [PDF to Word](./pdf-to-docx)
|
||||
- [PDF to Word](./pdf-to-word)
|
||||
|
||||
@@ -58,7 +58,7 @@ AES-256 is computationally infeasible to brute-force with current technology. Th
|
||||
|
||||
## Related Tools
|
||||
|
||||
- [Decrypt PDF](./decrypt-pdf) -- remove encryption when you know the password
|
||||
- [Decrypt PDF](./unlock-pdf) -- remove encryption when you know the password
|
||||
- [Change Permissions](./change-permissions) -- modify specific usage restrictions
|
||||
- [Remove Restrictions](./remove-restrictions) -- strip all security from a PDF
|
||||
- [Sanitize PDF](./sanitize-pdf) -- remove hidden content before encrypting
|
||||
@@ -46,5 +46,5 @@ No options to configure. The tool is thorough by design: it clears everything.
|
||||
## Related Tools
|
||||
|
||||
- [Sanitize PDF](./sanitize-pdf) -- remove metadata plus scripts, attachments, and more
|
||||
- [Encrypt PDF](./encrypt-pdf) -- protect the cleaned PDF with a password
|
||||
- [Encrypt PDF](./protect-pdf) -- protect the cleaned PDF with a password
|
||||
- [Compress PDF](./compress-pdf) -- removing metadata can slightly reduce file size; compress for more savings
|
||||
|
||||
@@ -40,6 +40,6 @@ The tool uses QPDF's `--decrypt` and `--remove-restrictions` flags to produce a
|
||||
|
||||
## Related Tools
|
||||
|
||||
- [Decrypt PDF](./decrypt-pdf) -- unlock a PDF when you know the user password
|
||||
- [Encrypt PDF](./encrypt-pdf) -- re-apply encryption with new settings
|
||||
- [Decrypt PDF](./unlock-pdf) -- unlock a PDF when you know the user password
|
||||
- [Encrypt PDF](./protect-pdf) -- re-apply encryption with new settings
|
||||
- [Change Permissions](./change-permissions) -- selectively modify which actions are allowed
|
||||
|
||||
@@ -49,5 +49,5 @@ All options are enabled by default. Uncheck any you want to preserve.
|
||||
|
||||
- [Remove Metadata](./remove-metadata) -- strip only metadata without touching other content
|
||||
- [Flatten PDF](./flatten-pdf) -- flatten forms and annotations specifically
|
||||
- [Encrypt PDF](./encrypt-pdf) -- add password protection after sanitizing
|
||||
- [Encrypt PDF](./protect-pdf) -- add password protection after sanitizing
|
||||
- [Rasterize PDF](./rasterize-pdf) -- the nuclear option: convert to images to eliminate all hidden content
|
||||
|
||||
@@ -41,6 +41,6 @@ If you have the password to an encrypted PDF, this tool removes the encryption e
|
||||
|
||||
## Related Tools
|
||||
|
||||
- [Encrypt PDF](./encrypt-pdf) -- re-apply encryption with a new password
|
||||
- [Encrypt PDF](./protect-pdf) -- re-apply encryption with a new password
|
||||
- [Remove Restrictions](./remove-restrictions) -- remove usage restrictions without full decryption
|
||||
- [Change Permissions](./change-permissions) -- modify specific permissions on an encrypted PDF
|
||||
@@ -35,6 +35,13 @@ chown -R "$PUID:$PGID" \
|
||||
/etc/nginx/nginx.conf
|
||||
|
||||
PORT=${PORT:-8080}
|
||||
case "$PORT" in
|
||||
''|*[!0-9]*) echo "ERROR: PORT must be a number, got '$PORT'" >&2; exit 1 ;;
|
||||
esac
|
||||
if [ "$PORT" -lt 1 ] || [ "$PORT" -gt 65535 ]; then
|
||||
echo "ERROR: PORT must be between 1 and 65535, got '$PORT'" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ "$PORT" != "8080" ]; then
|
||||
echo "Changing Nginx listen port to $PORT"
|
||||
sed -i "s/listen 8080/listen $PORT/g; s/listen \[::\]:8080/listen [::]:$PORT/g" /etc/nginx/nginx.conf
|
||||
|
||||
@@ -26,6 +26,7 @@ export default [
|
||||
],
|
||||
},
|
||||
{ languageOptions: { globals: { ...globals.browser, ...globals.node } } },
|
||||
|
||||
pluginJs.configs.recommended,
|
||||
...tseslint.configs.recommended,
|
||||
eslintConfigPrettier,
|
||||
@@ -89,4 +90,14 @@ export default [
|
||||
'no-misleading-character-class': 'warn',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['src/js/editcore/**/*.js'],
|
||||
rules: {
|
||||
'no-useless-assignment': 'off',
|
||||
'security/detect-unsafe-regex': 'off',
|
||||
'security/detect-object-injection': 'off',
|
||||
'no-unsanitized/property': 'off',
|
||||
'no-empty': 'off',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
@@ -49,6 +49,7 @@
|
||||
<meta name="twitter:site" content="@BentoPDF" />
|
||||
|
||||
<link href="/src/css/styles.css" rel="stylesheet" />
|
||||
<link href="/src/css/landing.css" rel="stylesheet" />
|
||||
|
||||
<!-- Web App Manifest -->
|
||||
<link rel="manifest" href="/site.webmanifest" />
|
||||
@@ -75,10 +76,13 @@
|
||||
<link rel="icon" href="/favicon.ico" sizes="32x32" />
|
||||
</head>
|
||||
|
||||
<body class="antialiased bg-gray-900 text-gray-300">
|
||||
<body class="lp antialiased bg-gray-900 text-gray-300">
|
||||
{{> navbar }}
|
||||
|
||||
<div id="app" class="min-h-screen container mx-auto p-4 md:p-8">
|
||||
<div
|
||||
id="app"
|
||||
class="min-h-screen container mx-auto px-4 pt-4 md:px-8 md:pt-8"
|
||||
>
|
||||
<section id="faq-hero" class="text-center py-16 md:py-24">
|
||||
<h1 class="text-4xl md:text-5xl font-bold text-white mb-4">
|
||||
Frequently Asked Questions
|
||||
@@ -89,42 +93,32 @@
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<div class="max-w-4xl mx-auto space-y-4">
|
||||
<details
|
||||
class="bg-gray-800 border border-gray-700 rounded-lg p-5 group"
|
||||
>
|
||||
<summary class="flex items-center justify-between cursor-pointer">
|
||||
<div class="faq-list">
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
<h3 class="font-semibold text-white text-lg">
|
||||
Are my files safe and private?
|
||||
</h3>
|
||||
<i
|
||||
data-lucide="plus"
|
||||
class="w-6 h-6 text-indigo-400 icon flex-shrink-0"
|
||||
></i>
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<div class="mt-4 text-gray-400">
|
||||
<div class="faq-d-a">
|
||||
<p>
|
||||
<strong>Absolutely.</strong> This is the most important feature of
|
||||
BentoPDF. All processing happens 100% locally in your web browser.
|
||||
Your files are never uploaded to any server, which means we—or
|
||||
anyone else—can never see them. Your privacy is guaranteed.
|
||||
Your files are never uploaded to any server, which means we, or
|
||||
anyone else, can never see them. Your privacy is guaranteed.
|
||||
</p>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details
|
||||
class="bg-gray-800 border border-gray-700 rounded-lg p-5 group"
|
||||
>
|
||||
<summary class="flex items-center justify-between cursor-pointer">
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
<h3 class="font-semibold text-white text-lg">
|
||||
Is BentoPDF really free? What's the catch?
|
||||
</h3>
|
||||
<i
|
||||
data-lucide="plus"
|
||||
class="w-6 h-6 text-indigo-400 icon flex-shrink-0"
|
||||
></i>
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<div class="mt-4 text-gray-400">
|
||||
<div class="faq-d-a">
|
||||
<p>
|
||||
Yes, it's completely free, and there's no catch. There are no
|
||||
hidden fees, no subscription plans, no usage limits, and no
|
||||
@@ -134,19 +128,14 @@
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details
|
||||
class="bg-gray-800 border border-gray-700 rounded-lg p-5 group"
|
||||
>
|
||||
<summary class="flex items-center justify-between cursor-pointer">
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
<h3 class="font-semibold text-white text-lg">
|
||||
Do I need an internet connection to use the tools?
|
||||
</h3>
|
||||
<i
|
||||
data-lucide="plus"
|
||||
class="w-6 h-6 text-indigo-400 icon flex-shrink-0"
|
||||
></i>
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<div class="mt-4 text-gray-400">
|
||||
<div class="faq-d-a">
|
||||
<p>
|
||||
After you load the website for the first time, most tools will
|
||||
work completely offline! Because all the processing libraries are
|
||||
@@ -158,19 +147,14 @@
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details
|
||||
class="bg-gray-800 border border-gray-700 rounded-lg p-5 group"
|
||||
>
|
||||
<summary class="flex items-center justify-between cursor-pointer">
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
<h3 class="font-semibold text-white text-lg">
|
||||
Are there any file size or usage limitations?
|
||||
</h3>
|
||||
<i
|
||||
data-lucide="plus"
|
||||
class="w-6 h-6 text-indigo-400 icon flex-shrink-0"
|
||||
></i>
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<div class="mt-4 text-gray-400">
|
||||
<div class="faq-d-a">
|
||||
<p>
|
||||
No, we do not impose any artificial limits on file size, the
|
||||
number of files, or how many times you can use a tool. The only
|
||||
@@ -181,19 +165,14 @@
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details
|
||||
class="bg-gray-800 border border-gray-700 rounded-lg p-5 group"
|
||||
>
|
||||
<summary class="flex items-center justify-between cursor-pointer">
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
<h3 class="font-semibold text-white text-lg">
|
||||
Why did my PDF fail to process?
|
||||
</h3>
|
||||
<i
|
||||
data-lucide="plus"
|
||||
class="w-6 h-6 text-indigo-400 icon flex-shrink-0"
|
||||
></i>
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<div class="mt-4 text-gray-400">
|
||||
<div class="faq-d-a">
|
||||
<p>Failures are rare but can happen for a few reasons:</p>
|
||||
<ul class="list-disc list-inside mt-2 space-y-1">
|
||||
<li>
|
||||
@@ -212,50 +191,31 @@
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details
|
||||
class="bg-gray-800 border border-gray-700 rounded-lg p-5 group"
|
||||
>
|
||||
<summary class="flex items-center justify-between cursor-pointer">
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
<h3 class="font-semibold text-white text-lg">
|
||||
Do you track my activity on BentoPDF?
|
||||
</h3>
|
||||
<i
|
||||
data-lucide="plus"
|
||||
class="w-6 h-6 text-indigo-400 icon flex-shrink-0"
|
||||
></i>
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<div class="mt-4 text-gray-400">
|
||||
<div class="faq-d-a">
|
||||
<p>
|
||||
We care about your privacy. BentoPDF does not track personal
|
||||
information. We use
|
||||
<a
|
||||
href="https://simpleanalytics.com"
|
||||
class="text-indigo-400 hover:underline"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>Simple Analytics</a
|
||||
>
|
||||
solely to see anonymous visit counts. This means we can know how
|
||||
many users visit our site, but
|
||||
<strong>we never know who you are</strong>. Simple Analytics is
|
||||
fully GDPR-compliant and respects your privacy.
|
||||
No. BentoPDF does not track you at all. We do not use cookies,
|
||||
analytics, or any tracking scripts, not even on the live website
|
||||
at bentopdf.com. We never know who you are or what you do with the
|
||||
tools.
|
||||
</p>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<details
|
||||
class="bg-gray-800 border border-gray-700 rounded-lg p-5 group"
|
||||
>
|
||||
<summary class="flex items-center justify-between cursor-pointer">
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
<h3 class="font-semibold text-white text-lg">
|
||||
What technology does BentoPDF use?
|
||||
</h3>
|
||||
<i
|
||||
data-lucide="plus"
|
||||
class="w-6 h-6 text-indigo-400 icon flex-shrink-0"
|
||||
></i>
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<div class="mt-4 text-gray-400">
|
||||
<div class="faq-d-a">
|
||||
<p>
|
||||
BentoPDF is built on the power of modern web technologies. We
|
||||
primarily use JavaScript libraries like
|
||||
@@ -268,22 +228,24 @@
|
||||
</details>
|
||||
</div>
|
||||
|
||||
<div class="section-divider mt-16"></div>
|
||||
|
||||
<section id="contact-section" class="text-center py-16">
|
||||
<h2 class="text-3xl font-bold text-white mb-4">
|
||||
Still have questions?
|
||||
</h2>
|
||||
<p class="text-lg text-gray-400 mb-8 max-w-2xl mx-auto">
|
||||
If you can't find the answer you're looking for, feel free to reach
|
||||
out to our support team. We're always Bento to help.
|
||||
</p>
|
||||
<a
|
||||
href="contact.html"
|
||||
class="inline-block px-8 py-3 rounded-full bg-gray-700 text-white font-semibold focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-900 focus:ring-indigo-400 hover:bg-gray-600 transition-colors duration-200"
|
||||
>
|
||||
Contact Us
|
||||
</a>
|
||||
<section id="contact-section" class="lp-sec">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-cta">
|
||||
<h2 class="lp-h2">Still have questions?</h2>
|
||||
<p>
|
||||
If you can't find the answer you're looking for, feel free to
|
||||
reach out. We're always happy to help.
|
||||
</p>
|
||||
<div class="lp-cta-actions">
|
||||
<span class="lp-brackets">
|
||||
<a href="contact.html" class="lp-btn lp-btn--primary">
|
||||
<span data-i18n="footer.contactUs">Contact Us</span>
|
||||
<i data-lucide="arrow-right"></i>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
@@ -302,7 +264,7 @@
|
||||
"name": "Are my files safe and private?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "Absolutely. This is the most important feature of BentoPDF. All processing happens 100% locally in your web browser. Your files are never uploaded to any server, which means we—or anyone else—can never see them. Your privacy is guaranteed."
|
||||
"text": "Absolutely. This is the most important feature of BentoPDF. All processing happens 100% locally in your web browser. Your files are never uploaded to any server, which means we, or anyone else, can never see them. Your privacy is guaranteed."
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -342,7 +304,7 @@
|
||||
"name": "Do you track my activity on BentoPDF?",
|
||||
"acceptedAnswer": {
|
||||
"@type": "Answer",
|
||||
"text": "We care about your privacy. BentoPDF does not track personal information. We use Simple Analytics solely to see anonymous visit counts. This means we can know how many users visit our site, but we never know who you are. Simple Analytics is fully GDPR-compliant and respects your privacy."
|
||||
"text": "No. BentoPDF does not track you at all. We do not use cookies, analytics, or any tracking scripts, not even on the live website at bentopdf.com. We never know who you are or what you do with the tools."
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
@@ -0,0 +1,692 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<!-- Primary Meta Tags -->
|
||||
<title>Hyper Compress - PDF Compression Engine | BentoPDF</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Hyper Compress is a content-preserving PDF compression engine. Free under the AGPL, commercial licenses from $99/year."
|
||||
/>
|
||||
<meta name="author" content="BentoPDF" />
|
||||
<meta name="robots" content="index, follow" />
|
||||
|
||||
<!-- Canonical URL -->
|
||||
<link rel="canonical" href="https://www.bentopdf.com/hyper-compress" />
|
||||
|
||||
<!-- Open Graph -->
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="https://www.bentopdf.com/hyper-compress" />
|
||||
<meta
|
||||
property="og:title"
|
||||
content="Hyper Compress - PDF Compression Engine | BentoPDF"
|
||||
/>
|
||||
<meta
|
||||
property="og:description"
|
||||
content="Hyper Compress is a content-preserving PDF compression engine. Free under the AGPL, commercial licenses from $99/year."
|
||||
/>
|
||||
<meta
|
||||
property="og:image"
|
||||
content="https://www.bentopdf.com/images/og-tools.png"
|
||||
/>
|
||||
<meta property="og:site_name" content="BentoPDF" />
|
||||
|
||||
<!-- Twitter Card -->
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta
|
||||
name="twitter:title"
|
||||
content="Hyper Compress - PDF Compression Engine | BentoPDF"
|
||||
/>
|
||||
<meta
|
||||
name="twitter:description"
|
||||
content="Hyper Compress is a content-preserving PDF compression engine. Free under the AGPL, commercial licenses from $99/year."
|
||||
/>
|
||||
<meta
|
||||
name="twitter:image"
|
||||
content="https://www.bentopdf.com/images/og-tools.png"
|
||||
/>
|
||||
<meta name="twitter:site" content="@BentoPDF" />
|
||||
|
||||
<link href="/src/css/styles.css" rel="stylesheet" />
|
||||
<link href="/src/css/landing.css" rel="stylesheet" />
|
||||
|
||||
<!-- Web App Manifest -->
|
||||
<link rel="manifest" href="/site.webmanifest" />
|
||||
|
||||
<!-- Favicons -->
|
||||
<link rel="icon" type="image/svg+xml" href="/images/favicon.svg" />
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="192x192"
|
||||
href="/images/favicon-192x192.png"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="512x512"
|
||||
href="/images/favicon-512x512.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
href="/images/apple-touch-icon.png"
|
||||
/>
|
||||
<link rel="icon" href="/favicon.ico" sizes="32x32" />
|
||||
</head>
|
||||
|
||||
<body class="lp antialiased">
|
||||
{{> navbar }}
|
||||
|
||||
<div id="app">
|
||||
<section id="hyper-compress-hero" class="lp-sec lp-sec--first">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-head lp-head--center">
|
||||
<div>
|
||||
<h1 class="lp-h1">
|
||||
<span class="line">Meet</span>
|
||||
<span class="line dim">Hyper Compress</span>
|
||||
</h1>
|
||||
<p class="lp-head-p">
|
||||
The best open source PDF compression engine. It never returns a
|
||||
file larger than the original, offers a true lossless mode, and
|
||||
posted the lowest corruption rate of every engine we
|
||||
benchmarked.
|
||||
</p>
|
||||
<p class="lp-head-p">
|
||||
Ships as a CLI, Node SDK, C library, self-hosted service and
|
||||
WebAssembly build.
|
||||
</p>
|
||||
<div class="lp-actions">
|
||||
<span class="lp-brackets">
|
||||
<a href="#pricing" class="lp-btn lp-btn--primary">
|
||||
<span>See pricing</span>
|
||||
<i data-lucide="arrow-right"></i>
|
||||
</a>
|
||||
</span>
|
||||
<a
|
||||
href="https://hyper.bentopdf.com"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
class="lp-btn lp-btn--ghost"
|
||||
>
|
||||
<i data-lucide="external-link"></i>
|
||||
<span>Visit website</span>
|
||||
</a>
|
||||
<a
|
||||
href="https://github.com/alam00000/bentopdf-hyper-compress"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
class="lp-btn lp-btn--ghost"
|
||||
>
|
||||
<i data-lucide="github"></i>
|
||||
<span>View on GitHub</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="lp-grid lp-grid--4">
|
||||
<div class="lp-cell lp-stat lp-cell--accent lp-reveal">
|
||||
<b>64.8%</b><span>median reduction, strongest preset</span>
|
||||
</div>
|
||||
<div class="lp-cell lp-stat lp-cell--white lp-reveal">
|
||||
<b>22.4%</b><span>median reduction, lossless</span>
|
||||
</div>
|
||||
<div class="lp-cell lp-stat lp-cell--hatch lp-reveal">
|
||||
<b>0.39%</b><span>corruption rate, lowest tested</span>
|
||||
</div>
|
||||
<div class="lp-cell lp-stat lp-cell--raised lp-reveal">
|
||||
<b>2,104</b><span>real-world PDFs benchmarked</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="lp-sec">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-pad--tight">
|
||||
<div class="lp-note lp-reveal">
|
||||
<i data-lucide="badge-check"></i>
|
||||
<p>
|
||||
<strong
|
||||
>Open source, self-hosting and internal use stay free.</strong
|
||||
>
|
||||
Hyper Compress is licensed under the AGPL-3.0. If your project
|
||||
is AGPL-compatible, or you run Hyper Compress as-is for
|
||||
yourself, you never need a commercial license. Commercial
|
||||
licenses are only for shipping Hyper Compress inside
|
||||
closed-source software.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="pricing" class="lp-sec lp-band">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-head lp-head--center">
|
||||
<div>
|
||||
<h2 class="lp-h2">
|
||||
<span class="line">Commercial</span>
|
||||
<span class="line dim">Licenses</span>
|
||||
</h2>
|
||||
<p class="lp-head-p">
|
||||
Per product, billed annually. Every tier includes all updates
|
||||
and new releases while active.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="lp-grid lp-grid--4">
|
||||
<div class="lp-cell lp-tier lp-reveal">
|
||||
<h3>Solo</h3>
|
||||
<p class="lp-tier-for">
|
||||
One developer, under $100k annual revenue
|
||||
</p>
|
||||
<div class="lp-tier-price"><b>$99</b><span>/ year</span></div>
|
||||
<ul>
|
||||
<li><i data-lucide="check"></i>One closed-source product</li>
|
||||
<li><i data-lucide="check"></i>All updates while active</li>
|
||||
<li><i data-lucide="check"></i>Email support</li>
|
||||
</ul>
|
||||
<a
|
||||
href="https://buy.polar.sh/polar_cl_38OODBtvzFt24gT3W2ibWPZmm5HVMdUuWOjBt3ImRJA"
|
||||
class="lp-btn lp-btn--ghost lp-btn--sm"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>Get Solo</a
|
||||
>
|
||||
</div>
|
||||
<div class="lp-cell lp-tier lp-cell--accent lp-reveal">
|
||||
<h3>Indie</h3>
|
||||
<p class="lp-tier-for">Companies under $1M annual revenue</p>
|
||||
<div class="lp-tier-price"><b>$199</b><span>/ year</span></div>
|
||||
<ul>
|
||||
<li><i data-lucide="check"></i>One closed-source product</li>
|
||||
<li><i data-lucide="check"></i>Unlimited developers</li>
|
||||
<li><i data-lucide="check"></i>All updates while active</li>
|
||||
<li><i data-lucide="check"></i>Email support</li>
|
||||
</ul>
|
||||
<a
|
||||
href="https://buy.polar.sh/polar_cl_SWybHH8hi4Yufhn6seVrlJnlXZfymvLQgCadU3pWjT9"
|
||||
class="lp-btn lp-btn--primary lp-btn--sm"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>Get Indie</a
|
||||
>
|
||||
</div>
|
||||
<div class="lp-cell lp-tier lp-reveal">
|
||||
<h3>Business</h3>
|
||||
<p class="lp-tier-for">Companies at $1M annual revenue or more</p>
|
||||
<div class="lp-tier-price"><b>$499</b><span>/ year</span></div>
|
||||
<ul>
|
||||
<li><i data-lucide="check"></i>One closed-source product</li>
|
||||
<li><i data-lucide="check"></i>Unlimited developers</li>
|
||||
<li><i data-lucide="check"></i>All updates while active</li>
|
||||
<li><i data-lucide="check"></i>Priority email support</li>
|
||||
</ul>
|
||||
<a
|
||||
href="https://buy.polar.sh/polar_cl_k2hYaoG49OZyB3WbAkmVyB55MRHqYQqex1bja0z7DfY"
|
||||
class="lp-btn lp-btn--ghost lp-btn--sm"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>Get Business</a
|
||||
>
|
||||
</div>
|
||||
<div class="lp-cell lp-tier lp-reveal">
|
||||
<h3>OEM</h3>
|
||||
<p class="lp-tier-for">
|
||||
Redistribution, reselling as an SDK, or offering Hyper Compress
|
||||
as a service
|
||||
</p>
|
||||
<div class="lp-tier-price">
|
||||
<span class="lp-tier-from">from</span><b>$1,999</b
|
||||
><span>/ year</span>
|
||||
</div>
|
||||
<ul>
|
||||
<li><i data-lucide="check"></i>Redistribution rights</li>
|
||||
<li><i data-lucide="check"></i>Terms shaped to your product</li>
|
||||
<li><i data-lucide="check"></i>Priority support</li>
|
||||
</ul>
|
||||
<a
|
||||
href="mailto:[email protected]?subject=Hyper%20Compress%20commercial%20license%20OEM"
|
||||
class="lp-btn lp-btn--ghost lp-btn--sm"
|
||||
>Contact us</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="license-details" class="lp-sec lp-band">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-head lp-head--center">
|
||||
<div>
|
||||
<h2 class="lp-h2">
|
||||
<span class="line">Commercial license</span>
|
||||
<span class="line dim">details</span>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lp-pad">
|
||||
<div class="grid grid-cols-1 gap-6">
|
||||
<div class="lp-panel">
|
||||
<h3
|
||||
class="text-xl font-semibold text-white mb-4 flex items-center gap-3"
|
||||
>
|
||||
<i data-lucide="package" class="w-6 h-6 text-indigo-400"></i>
|
||||
Delivery & licensing model
|
||||
</h3>
|
||||
<ul class="space-y-3 text-gray-400">
|
||||
<li class="flex items-start gap-3">
|
||||
<i
|
||||
data-lucide="check-circle"
|
||||
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
|
||||
></i>
|
||||
<span
|
||||
><strong class="text-white"
|
||||
>No license key is required or provided.</strong
|
||||
>
|
||||
Hyper Compress intentionally does not use license keys, to
|
||||
streamline deployment and reduce operational
|
||||
friction.</span
|
||||
>
|
||||
</li>
|
||||
<li class="flex items-start gap-3">
|
||||
<i
|
||||
data-lucide="check-circle"
|
||||
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
|
||||
></i>
|
||||
<span
|
||||
>Upon purchase you receive a ZIP archive containing the
|
||||
complete Hyper Compress source code.</span
|
||||
>
|
||||
</li>
|
||||
<li class="flex items-start gap-3">
|
||||
<i
|
||||
data-lucide="check-circle"
|
||||
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
|
||||
></i>
|
||||
<span
|
||||
>Because Hyper Compress is open source, every release and
|
||||
every update can always be downloaded from our
|
||||
<a
|
||||
href="https://github.com/alam00000/bentopdf-hyper-compress/releases"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="text-indigo-400 hover:underline"
|
||||
>GitHub releases page</a
|
||||
>.</span
|
||||
>
|
||||
</li>
|
||||
<li class="flex items-start gap-3">
|
||||
<i
|
||||
data-lucide="check-circle"
|
||||
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
|
||||
></i>
|
||||
<span
|
||||
>The source code provided is identical to the code
|
||||
published in our public open-source repository.</span
|
||||
>
|
||||
</li>
|
||||
<li class="flex items-start gap-3">
|
||||
<i
|
||||
data-lucide="x-circle"
|
||||
class="w-5 h-5 text-red-400 flex-shrink-0 mt-0.5"
|
||||
></i>
|
||||
<span
|
||||
><strong class="text-white">No refunds.</strong> Under no
|
||||
circumstances shall a refund be made after purchase.</span
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<p class="mt-4 text-gray-300">
|
||||
<strong class="text-white">GitHub repository:</strong>
|
||||
<a
|
||||
href="https://github.com/alam00000/bentopdf-hyper-compress"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="text-indigo-400 hover:underline"
|
||||
>github.com/alam00000/bentopdf-hyper-compress</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="lp-panel">
|
||||
<h3
|
||||
class="text-xl font-semibold text-white mb-4 flex items-center gap-3"
|
||||
>
|
||||
<i
|
||||
data-lucide="file-text"
|
||||
class="w-6 h-6 text-indigo-400"
|
||||
></i>
|
||||
Invoicing
|
||||
</h3>
|
||||
<ul class="space-y-3 text-gray-400">
|
||||
<li class="flex items-start gap-3">
|
||||
<i
|
||||
data-lucide="check-circle"
|
||||
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
|
||||
></i>
|
||||
<span
|
||||
>We use <strong class="text-white">Polar</strong> for
|
||||
payments, which
|
||||
<strong class="text-white"
|
||||
>automatically sends invoices</strong
|
||||
>
|
||||
via email after purchase.</span
|
||||
>
|
||||
</li>
|
||||
<li class="flex items-start gap-3">
|
||||
<i
|
||||
data-lucide="check-circle"
|
||||
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
|
||||
></i>
|
||||
<span
|
||||
>Polar handles
|
||||
<strong class="text-white">VAT invoices</strong> for
|
||||
businesses in applicable regions.</span
|
||||
>
|
||||
</li>
|
||||
<li class="flex items-start gap-3">
|
||||
<i
|
||||
data-lucide="info"
|
||||
class="w-5 h-5 text-blue-400 flex-shrink-0 mt-0.5"
|
||||
></i>
|
||||
<span
|
||||
>For VAT invoices, select
|
||||
<strong class="text-white"
|
||||
>"I'm purchasing as a business"</strong
|
||||
>
|
||||
during checkout and enter your billing address and Tax/VAT
|
||||
number.</span
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="compare" class="lp-sec">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-head lp-head--center">
|
||||
<div>
|
||||
<h2 class="lp-h2">
|
||||
<span class="line">What each tier</span>
|
||||
<span class="line dim">covers</span>
|
||||
</h2>
|
||||
<p class="lp-head-p">
|
||||
Every tier lets you ship Hyper Compress inside one closed-source
|
||||
product. The tiers differ by who you are, how many developers
|
||||
you have, and whether Hyper Compress is passed on to anyone
|
||||
else.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lp-pad--tight lp-reveal">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="lp-table lp-compare">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Solo</th>
|
||||
<th>Indie</th>
|
||||
<th>Business</th>
|
||||
<th>OEM</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">Who it's for</th>
|
||||
<td>One developer, under $100k annual revenue</td>
|
||||
<td>Companies under $1M annual revenue</td>
|
||||
<td>Companies at $1M annual revenue or more</td>
|
||||
<td>
|
||||
Anyone redistributing, reselling or hosting the engine
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Annual price</th>
|
||||
<td>$99</td>
|
||||
<td>$199</td>
|
||||
<td>$499</td>
|
||||
<td>from $1,999</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Developers covered</th>
|
||||
<td>One developer</td>
|
||||
<td>Unlimited</td>
|
||||
<td>Unlimited</td>
|
||||
<td>Discussed with you</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Closed-source products covered</th>
|
||||
<td>One</td>
|
||||
<td>One</td>
|
||||
<td>One</td>
|
||||
<td>Terms shaped to your product</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Updates while active</th>
|
||||
<td class="lp-yes"><i data-lucide="check"></i></td>
|
||||
<td class="lp-yes"><i data-lucide="check"></i></td>
|
||||
<td class="lp-yes"><i data-lucide="check"></i></td>
|
||||
<td class="lp-yes"><i data-lucide="check"></i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Support</th>
|
||||
<td>Email</td>
|
||||
<td>Email</td>
|
||||
<td>Priority email</td>
|
||||
<td>Priority</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
Redistribute inside someone else's product
|
||||
</th>
|
||||
<td class="lp-no"><i data-lucide="x"></i></td>
|
||||
<td class="lp-no"><i data-lucide="x"></i></td>
|
||||
<td class="lp-no"><i data-lucide="x"></i></td>
|
||||
<td class="lp-yes"><i data-lucide="check"></i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Resell as an SDK</th>
|
||||
<td class="lp-no"><i data-lucide="x"></i></td>
|
||||
<td class="lp-no"><i data-lucide="x"></i></td>
|
||||
<td class="lp-no"><i data-lucide="x"></i></td>
|
||||
<td class="lp-yes"><i data-lucide="check"></i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
Offer Hyper Compress as a hosted service
|
||||
</th>
|
||||
<td class="lp-no"><i data-lucide="x"></i></td>
|
||||
<td class="lp-no"><i data-lucide="x"></i></td>
|
||||
<td class="lp-no"><i data-lucide="x"></i></td>
|
||||
<td class="lp-yes"><i data-lucide="check"></i></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p class="lp-table-note">
|
||||
Redistribution, reselling and hosting are what separate OEM from
|
||||
the rest. If Hyper Compress only ships inside your own
|
||||
closed-source product, the choice between Solo, Indie and Business
|
||||
is purely a question of your size.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="lp-sec lp-band">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-head lp-head--center">
|
||||
<div>
|
||||
<h2 class="lp-h2">
|
||||
<span class="line">License</span>
|
||||
<span class="line dim">Terms</span>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lp-grid lp-grid--2">
|
||||
<div class="lp-cell lp-reveal">
|
||||
<span class="lp-tile"><i data-lucide="package"></i></span>
|
||||
<h3>Per product</h3>
|
||||
<p>
|
||||
A license covers one shipped product. A second product needs a
|
||||
second license, or ask about covering your whole catalogue at
|
||||
OEM.
|
||||
</p>
|
||||
</div>
|
||||
<div class="lp-cell lp-reveal">
|
||||
<span class="lp-tile"><i data-lucide="refresh-cw"></i></span>
|
||||
<h3>Updates included</h3>
|
||||
<p>
|
||||
Every release published while your license is active is yours.
|
||||
If you let it lapse, you keep a perpetual right to the last
|
||||
version you received.
|
||||
</p>
|
||||
</div>
|
||||
<div class="lp-cell lp-reveal">
|
||||
<span class="lp-tile"><i data-lucide="unlock"></i></span>
|
||||
<h3>No AGPL obligations</h3>
|
||||
<p>
|
||||
The commercial license replaces the AGPL for your product. You
|
||||
ship closed source, with no requirement to publish your changes
|
||||
or your application.
|
||||
</p>
|
||||
</div>
|
||||
<div class="lp-cell lp-reveal">
|
||||
<span class="lp-tile"><i data-lucide="shield-check"></i></span>
|
||||
<h3>Clean provenance</h3>
|
||||
<p>
|
||||
Hyper Compress is written and owned by BentoPDF, and every
|
||||
third-party component it bundles, including PDFium, qpdf, jpegli
|
||||
and Leptonica, is permissively licensed. No copyleft surprises
|
||||
in your supply chain.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="lp-sec">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-head lp-head--center">
|
||||
<div>
|
||||
<h2 class="lp-h2">
|
||||
<span class="line">Frequently Asked</span>
|
||||
<span class="line dim">Questions</span>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lp-faq-wrap">
|
||||
<div id="faq-accordion" class="lp-faq lp-reveal">
|
||||
<div class="faq-item">
|
||||
<button
|
||||
class="faq-question w-full flex justify-between items-center text-left"
|
||||
type="button"
|
||||
>
|
||||
<span>Do I need a commercial license?</span>
|
||||
<i data-lucide="plus" class="faq-icon"></i>
|
||||
</button>
|
||||
<div
|
||||
class="faq-answer max-h-0 overflow-hidden transition-all duration-300 ease-in-out"
|
||||
>
|
||||
<p>
|
||||
Only if you ship Hyper Compress inside closed-source
|
||||
software. Open-source projects under an AGPL-compatible
|
||||
license, self-hosting, and internal use are all free under
|
||||
the AGPL-3.0.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="faq-item">
|
||||
<button
|
||||
class="faq-question w-full flex justify-between items-center text-left"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
>Does the BentoPDF commercial license cover Hyper
|
||||
Compress?</span
|
||||
>
|
||||
<i data-lucide="plus" class="faq-icon"></i>
|
||||
</button>
|
||||
<div
|
||||
class="faq-answer max-h-0 overflow-hidden transition-all duration-300 ease-in-out"
|
||||
>
|
||||
<p>
|
||||
No. Hyper Compress is a separate project with its own
|
||||
license. The BentoPDF app license does not grant any rights
|
||||
to Hyper Compress, and a Hyper Compress license does not
|
||||
cover BentoPDF.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="faq-item">
|
||||
<button
|
||||
class="faq-question w-full flex justify-between items-center text-left"
|
||||
type="button"
|
||||
>
|
||||
<span>What happens if my company outgrows its tier?</span>
|
||||
<i data-lucide="plus" class="faq-icon"></i>
|
||||
</button>
|
||||
<div
|
||||
class="faq-answer max-h-0 overflow-hidden transition-all duration-300 ease-in-out"
|
||||
>
|
||||
<p>
|
||||
You move up to the matching tier at your next renewal.
|
||||
Nothing retroactive. Growing past a threshold mid-term never
|
||||
invalidates your current license.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="lp-sec">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-cta">
|
||||
<h2 class="lp-h2">Not sure which tier fits?</h2>
|
||||
<p>
|
||||
Tell us what you're building and we'll tell you what it costs. No
|
||||
calls required.
|
||||
</p>
|
||||
<div class="lp-cta-actions">
|
||||
<span class="lp-brackets">
|
||||
<a
|
||||
href="mailto:[email protected]?subject=Hyper%20Compress%20commercial%20license%20pricing"
|
||||
class="lp-btn lp-btn--primary"
|
||||
>
|
||||
<span>[email protected]</span>
|
||||
<i data-lucide="arrow-right"></i>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
{{> footer }}
|
||||
<script type="module" src="src/js/utils/lucide-init.ts"></script>
|
||||
<script type="module" src="src/js/main.ts"></script>
|
||||
<script type="module" src="src/js/mobileMenu.ts"></script>
|
||||
<script type="module" src="src/js/landing.ts"></script>
|
||||
<!-- JSON-LD Schema -->
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "WebPage",
|
||||
"name": "Hyper Compress - PDF Compression Engine | BentoPDF",
|
||||
"url": "https://www.bentopdf.com/hyper-compress"
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
+445
-555
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,683 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<!-- Primary Meta Tags -->
|
||||
<title>Kura - PDF/A, PDF/UA & PDF/X Conversion Engine | BentoPDF</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Kura converts any PDF to archival, print and accessibility standards. Free under the AGPL, commercial licenses from $99/year."
|
||||
/>
|
||||
<meta name="author" content="BentoPDF" />
|
||||
<meta name="robots" content="index, follow" />
|
||||
|
||||
<!-- Canonical URL -->
|
||||
<link rel="canonical" href="https://www.bentopdf.com/kura" />
|
||||
|
||||
<!-- Open Graph -->
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:url" content="https://www.bentopdf.com/kura" />
|
||||
<meta
|
||||
property="og:title"
|
||||
content="Kura - PDF/A, PDF/UA & PDF/X Conversion Engine | BentoPDF"
|
||||
/>
|
||||
<meta
|
||||
property="og:description"
|
||||
content="Kura converts any PDF to archival, print and accessibility standards. Free under the AGPL, commercial licenses from $99/year."
|
||||
/>
|
||||
<meta
|
||||
property="og:image"
|
||||
content="https://www.bentopdf.com/images/og-tools.png"
|
||||
/>
|
||||
<meta property="og:site_name" content="BentoPDF" />
|
||||
|
||||
<!-- Twitter Card -->
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta
|
||||
name="twitter:title"
|
||||
content="Kura - PDF/A, PDF/UA & PDF/X Conversion Engine | BentoPDF"
|
||||
/>
|
||||
<meta
|
||||
name="twitter:description"
|
||||
content="Kura converts any PDF to archival, print and accessibility standards. Free under the AGPL, commercial licenses from $99/year."
|
||||
/>
|
||||
<meta
|
||||
name="twitter:image"
|
||||
content="https://www.bentopdf.com/images/og-tools.png"
|
||||
/>
|
||||
<meta name="twitter:site" content="@BentoPDF" />
|
||||
|
||||
<link href="/src/css/styles.css" rel="stylesheet" />
|
||||
<link href="/src/css/landing.css" rel="stylesheet" />
|
||||
|
||||
<!-- Web App Manifest -->
|
||||
<link rel="manifest" href="/site.webmanifest" />
|
||||
|
||||
<!-- Favicons -->
|
||||
<link rel="icon" type="image/svg+xml" href="/images/favicon.svg" />
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="192x192"
|
||||
href="/images/favicon-192x192.png"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
type="image/png"
|
||||
sizes="512x512"
|
||||
href="/images/favicon-512x512.png"
|
||||
/>
|
||||
<link
|
||||
rel="apple-touch-icon"
|
||||
sizes="180x180"
|
||||
href="/images/apple-touch-icon.png"
|
||||
/>
|
||||
<link rel="icon" href="/favicon.ico" sizes="32x32" />
|
||||
</head>
|
||||
|
||||
<body class="lp antialiased">
|
||||
{{> navbar }}
|
||||
|
||||
<div id="app">
|
||||
<section id="kura-hero" class="lp-sec lp-sec--first">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-head lp-head--center">
|
||||
<div>
|
||||
<h1 class="lp-h1">
|
||||
<span class="line">Meet</span>
|
||||
<span class="line dim">Kura</span>
|
||||
</h1>
|
||||
<p class="lp-head-p">
|
||||
The PDF standards and preflight engine. Convert any PDF to every
|
||||
PDF/A level, PDF/UA, PDF/X, PDF/E and PDF/VT, then preflight the
|
||||
result against 396 bundled profiles to confirm it conforms.
|
||||
</p>
|
||||
<p class="lp-head-p">
|
||||
Ships as a CLI, npm package, browser WebAssembly build, Docker
|
||||
image and C library.
|
||||
</p>
|
||||
<div class="lp-actions">
|
||||
<span class="lp-brackets">
|
||||
<a href="#pricing" class="lp-btn lp-btn--primary">
|
||||
<span>See pricing</span>
|
||||
<i data-lucide="arrow-right"></i>
|
||||
</a>
|
||||
</span>
|
||||
<a
|
||||
href="https://kura.bentopdf.com"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
class="lp-btn lp-btn--ghost"
|
||||
>
|
||||
<i data-lucide="external-link"></i>
|
||||
<span>Visit website</span>
|
||||
</a>
|
||||
<a
|
||||
href="https://github.com/alam00000/bentopdf-kura"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
class="lp-btn lp-btn--ghost"
|
||||
>
|
||||
<i data-lucide="github"></i>
|
||||
<span>View on GitHub</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="lp-grid lp-grid--4">
|
||||
<div class="lp-cell lp-stat lp-cell--accent lp-reveal">
|
||||
<b>25</b><span>conformance targets</span>
|
||||
</div>
|
||||
<div class="lp-cell lp-stat lp-cell--white lp-reveal">
|
||||
<b>396</b><span>bundled preflight profiles</span>
|
||||
</div>
|
||||
<div class="lp-cell lp-stat lp-cell--hatch lp-reveal">
|
||||
<b>0</b><span>false findings in conformance testing</span>
|
||||
</div>
|
||||
<div class="lp-cell lp-stat lp-cell--raised lp-reveal">
|
||||
<b>5</b><span>form factors, one engine</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="lp-sec">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-pad--tight">
|
||||
<div class="lp-note lp-reveal">
|
||||
<i data-lucide="badge-check"></i>
|
||||
<p>
|
||||
<strong
|
||||
>Open source, self-hosting and internal use stay free.</strong
|
||||
>
|
||||
Kura is licensed under the AGPL-3.0. If your project is
|
||||
AGPL-compatible, or you run Kura as-is for yourself, you never
|
||||
need a commercial license. Commercial licenses are only for
|
||||
shipping Kura inside closed-source software.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="pricing" class="lp-sec lp-band">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-head lp-head--center">
|
||||
<div>
|
||||
<h2 class="lp-h2">
|
||||
<span class="line">Commercial</span>
|
||||
<span class="line dim">Licenses</span>
|
||||
</h2>
|
||||
<p class="lp-head-p">
|
||||
Per product, billed annually. Every tier includes all updates
|
||||
and new releases while active.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="lp-grid lp-grid--4">
|
||||
<div class="lp-cell lp-tier lp-reveal">
|
||||
<h3>Solo</h3>
|
||||
<p class="lp-tier-for">
|
||||
One developer, under $100k annual revenue
|
||||
</p>
|
||||
<div class="lp-tier-price"><b>$99</b><span>/ year</span></div>
|
||||
<ul>
|
||||
<li><i data-lucide="check"></i>One closed-source product</li>
|
||||
<li><i data-lucide="check"></i>All updates while active</li>
|
||||
<li><i data-lucide="check"></i>Email support</li>
|
||||
</ul>
|
||||
<a
|
||||
href="https://buy.polar.sh/polar_cl_NLuLBtXkHXyelWdxPy6zarYyNJqMd4NF1PWJI2sEeZa"
|
||||
class="lp-btn lp-btn--ghost lp-btn--sm"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>Get Solo</a
|
||||
>
|
||||
</div>
|
||||
<div class="lp-cell lp-tier lp-cell--accent lp-reveal">
|
||||
<h3>Indie</h3>
|
||||
<p class="lp-tier-for">Companies under $1M annual revenue</p>
|
||||
<div class="lp-tier-price"><b>$199</b><span>/ year</span></div>
|
||||
<ul>
|
||||
<li><i data-lucide="check"></i>One closed-source product</li>
|
||||
<li><i data-lucide="check"></i>Unlimited developers</li>
|
||||
<li><i data-lucide="check"></i>All updates while active</li>
|
||||
<li><i data-lucide="check"></i>Email support</li>
|
||||
</ul>
|
||||
<a
|
||||
href="https://buy.polar.sh/polar_cl_MMPcXzyyNvVfX3Fuvac1eGgG7pTgDiIDB2RCs4HUbxx"
|
||||
class="lp-btn lp-btn--primary lp-btn--sm"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>Get Indie</a
|
||||
>
|
||||
</div>
|
||||
<div class="lp-cell lp-tier lp-reveal">
|
||||
<h3>Business</h3>
|
||||
<p class="lp-tier-for">Companies at $1M annual revenue or more</p>
|
||||
<div class="lp-tier-price"><b>$499</b><span>/ year</span></div>
|
||||
<ul>
|
||||
<li><i data-lucide="check"></i>One closed-source product</li>
|
||||
<li><i data-lucide="check"></i>Unlimited developers</li>
|
||||
<li><i data-lucide="check"></i>All updates while active</li>
|
||||
<li><i data-lucide="check"></i>Priority email support</li>
|
||||
</ul>
|
||||
<a
|
||||
href="https://buy.polar.sh/polar_cl_r4HLyDK1rda9cERr31Jbg99m3GEVDC2K4ooFo4FtoFb"
|
||||
class="lp-btn lp-btn--ghost lp-btn--sm"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>Get Business</a
|
||||
>
|
||||
</div>
|
||||
<div class="lp-cell lp-tier lp-reveal">
|
||||
<h3>OEM</h3>
|
||||
<p class="lp-tier-for">
|
||||
Redistribution, reselling as an SDK, or offering Kura as a
|
||||
service
|
||||
</p>
|
||||
<div class="lp-tier-price">
|
||||
<span class="lp-tier-from">from</span><b>$1,999</b
|
||||
><span>/ year</span>
|
||||
</div>
|
||||
<ul>
|
||||
<li><i data-lucide="check"></i>Redistribution rights</li>
|
||||
<li><i data-lucide="check"></i>Terms shaped to your product</li>
|
||||
<li><i data-lucide="check"></i>Priority support</li>
|
||||
</ul>
|
||||
<a
|
||||
href="mailto:[email protected]?subject=Kura%20commercial%20license%20OEM"
|
||||
class="lp-btn lp-btn--ghost lp-btn--sm"
|
||||
>Contact us</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="license-details" class="lp-sec lp-band">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-head lp-head--center">
|
||||
<div>
|
||||
<h2 class="lp-h2">
|
||||
<span class="line">Commercial license</span>
|
||||
<span class="line dim">details</span>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lp-pad">
|
||||
<div class="grid grid-cols-1 gap-6">
|
||||
<div class="lp-panel">
|
||||
<h3
|
||||
class="text-xl font-semibold text-white mb-4 flex items-center gap-3"
|
||||
>
|
||||
<i data-lucide="package" class="w-6 h-6 text-indigo-400"></i>
|
||||
Delivery & licensing model
|
||||
</h3>
|
||||
<ul class="space-y-3 text-gray-400">
|
||||
<li class="flex items-start gap-3">
|
||||
<i
|
||||
data-lucide="check-circle"
|
||||
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
|
||||
></i>
|
||||
<span
|
||||
><strong class="text-white"
|
||||
>No license key is required or provided.</strong
|
||||
>
|
||||
Kura intentionally does not use license keys, to
|
||||
streamline deployment and reduce operational
|
||||
friction.</span
|
||||
>
|
||||
</li>
|
||||
<li class="flex items-start gap-3">
|
||||
<i
|
||||
data-lucide="check-circle"
|
||||
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
|
||||
></i>
|
||||
<span
|
||||
>Upon purchase you receive a ZIP archive containing the
|
||||
complete Kura source code.</span
|
||||
>
|
||||
</li>
|
||||
<li class="flex items-start gap-3">
|
||||
<i
|
||||
data-lucide="check-circle"
|
||||
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
|
||||
></i>
|
||||
<span
|
||||
>Because Kura is open source, every release and every
|
||||
update can always be downloaded from our
|
||||
<a
|
||||
href="https://github.com/alam00000/bentopdf-kura/releases"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="text-indigo-400 hover:underline"
|
||||
>GitHub releases page</a
|
||||
>.</span
|
||||
>
|
||||
</li>
|
||||
<li class="flex items-start gap-3">
|
||||
<i
|
||||
data-lucide="check-circle"
|
||||
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
|
||||
></i>
|
||||
<span
|
||||
>The source code provided is identical to the code
|
||||
published in our public open-source repository.</span
|
||||
>
|
||||
</li>
|
||||
<li class="flex items-start gap-3">
|
||||
<i
|
||||
data-lucide="x-circle"
|
||||
class="w-5 h-5 text-red-400 flex-shrink-0 mt-0.5"
|
||||
></i>
|
||||
<span
|
||||
><strong class="text-white">No refunds.</strong> Under no
|
||||
circumstances shall a refund be made after purchase.</span
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
<p class="mt-4 text-gray-300">
|
||||
<strong class="text-white">GitHub repository:</strong>
|
||||
<a
|
||||
href="https://github.com/alam00000/bentopdf-kura"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="text-indigo-400 hover:underline"
|
||||
>github.com/alam00000/bentopdf-kura</a
|
||||
>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="lp-panel">
|
||||
<h3
|
||||
class="text-xl font-semibold text-white mb-4 flex items-center gap-3"
|
||||
>
|
||||
<i
|
||||
data-lucide="file-text"
|
||||
class="w-6 h-6 text-indigo-400"
|
||||
></i>
|
||||
Invoicing
|
||||
</h3>
|
||||
<ul class="space-y-3 text-gray-400">
|
||||
<li class="flex items-start gap-3">
|
||||
<i
|
||||
data-lucide="check-circle"
|
||||
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
|
||||
></i>
|
||||
<span
|
||||
>We use <strong class="text-white">Polar</strong> for
|
||||
payments, which
|
||||
<strong class="text-white"
|
||||
>automatically sends invoices</strong
|
||||
>
|
||||
via email after purchase.</span
|
||||
>
|
||||
</li>
|
||||
<li class="flex items-start gap-3">
|
||||
<i
|
||||
data-lucide="check-circle"
|
||||
class="w-5 h-5 text-green-400 flex-shrink-0 mt-0.5"
|
||||
></i>
|
||||
<span
|
||||
>Polar handles
|
||||
<strong class="text-white">VAT invoices</strong> for
|
||||
businesses in applicable regions.</span
|
||||
>
|
||||
</li>
|
||||
<li class="flex items-start gap-3">
|
||||
<i
|
||||
data-lucide="info"
|
||||
class="w-5 h-5 text-blue-400 flex-shrink-0 mt-0.5"
|
||||
></i>
|
||||
<span
|
||||
>For VAT invoices, select
|
||||
<strong class="text-white"
|
||||
>"I'm purchasing as a business"</strong
|
||||
>
|
||||
during checkout and enter your billing address and Tax/VAT
|
||||
number.</span
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section id="compare" class="lp-sec">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-head lp-head--center">
|
||||
<div>
|
||||
<h2 class="lp-h2">
|
||||
<span class="line">What each tier</span>
|
||||
<span class="line dim">covers</span>
|
||||
</h2>
|
||||
<p class="lp-head-p">
|
||||
Every tier lets you ship Kura inside one closed-source product.
|
||||
The tiers differ by who you are, how many developers you have,
|
||||
and whether Kura is passed on to anyone else.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lp-pad--tight lp-reveal">
|
||||
<div class="overflow-x-auto">
|
||||
<table class="lp-table lp-compare">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Solo</th>
|
||||
<th>Indie</th>
|
||||
<th>Business</th>
|
||||
<th>OEM</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th scope="row">Who it's for</th>
|
||||
<td>One developer, under $100k annual revenue</td>
|
||||
<td>Companies under $1M annual revenue</td>
|
||||
<td>Companies at $1M annual revenue or more</td>
|
||||
<td>
|
||||
Anyone redistributing, reselling or hosting the engine
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Annual price</th>
|
||||
<td>$99</td>
|
||||
<td>$199</td>
|
||||
<td>$499</td>
|
||||
<td>from $1,999</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Developers covered</th>
|
||||
<td>One developer</td>
|
||||
<td>Unlimited</td>
|
||||
<td>Unlimited</td>
|
||||
<td>Discussed with you</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Closed-source products covered</th>
|
||||
<td>One</td>
|
||||
<td>One</td>
|
||||
<td>One</td>
|
||||
<td>Terms shaped to your product</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Updates while active</th>
|
||||
<td class="lp-yes"><i data-lucide="check"></i></td>
|
||||
<td class="lp-yes"><i data-lucide="check"></i></td>
|
||||
<td class="lp-yes"><i data-lucide="check"></i></td>
|
||||
<td class="lp-yes"><i data-lucide="check"></i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Support</th>
|
||||
<td>Email</td>
|
||||
<td>Email</td>
|
||||
<td>Priority email</td>
|
||||
<td>Priority</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">
|
||||
Redistribute inside someone else's product
|
||||
</th>
|
||||
<td class="lp-no"><i data-lucide="x"></i></td>
|
||||
<td class="lp-no"><i data-lucide="x"></i></td>
|
||||
<td class="lp-no"><i data-lucide="x"></i></td>
|
||||
<td class="lp-yes"><i data-lucide="check"></i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Resell as an SDK</th>
|
||||
<td class="lp-no"><i data-lucide="x"></i></td>
|
||||
<td class="lp-no"><i data-lucide="x"></i></td>
|
||||
<td class="lp-no"><i data-lucide="x"></i></td>
|
||||
<td class="lp-yes"><i data-lucide="check"></i></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Offer Kura as a hosted service</th>
|
||||
<td class="lp-no"><i data-lucide="x"></i></td>
|
||||
<td class="lp-no"><i data-lucide="x"></i></td>
|
||||
<td class="lp-no"><i data-lucide="x"></i></td>
|
||||
<td class="lp-yes"><i data-lucide="check"></i></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p class="lp-table-note">
|
||||
Redistribution, reselling and hosting are what separate OEM from
|
||||
the rest. If Kura only ships inside your own closed-source
|
||||
product, the choice between Solo, Indie and Business is purely a
|
||||
question of your size.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="lp-sec lp-band">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-head lp-head--center">
|
||||
<div>
|
||||
<h2 class="lp-h2">
|
||||
<span class="line">License</span>
|
||||
<span class="line dim">Terms</span>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lp-grid lp-grid--2">
|
||||
<div class="lp-cell lp-reveal">
|
||||
<span class="lp-tile"><i data-lucide="package"></i></span>
|
||||
<h3>Per product</h3>
|
||||
<p>
|
||||
A license covers one shipped product. A second product needs a
|
||||
second license, or ask about covering your whole catalogue at
|
||||
OEM.
|
||||
</p>
|
||||
</div>
|
||||
<div class="lp-cell lp-reveal">
|
||||
<span class="lp-tile"><i data-lucide="refresh-cw"></i></span>
|
||||
<h3>Updates included</h3>
|
||||
<p>
|
||||
Every release published while your license is active is yours.
|
||||
If you let it lapse, you keep a perpetual right to the last
|
||||
version you received.
|
||||
</p>
|
||||
</div>
|
||||
<div class="lp-cell lp-reveal">
|
||||
<span class="lp-tile"><i data-lucide="unlock"></i></span>
|
||||
<h3>No AGPL obligations</h3>
|
||||
<p>
|
||||
The commercial license replaces the AGPL for your product. You
|
||||
ship closed source, with no requirement to publish your changes
|
||||
or your application.
|
||||
</p>
|
||||
</div>
|
||||
<div class="lp-cell lp-reveal">
|
||||
<span class="lp-tile"><i data-lucide="shield-check"></i></span>
|
||||
<h3>Clean provenance</h3>
|
||||
<p>
|
||||
Kura is written and owned by BentoPDF, and every third-party
|
||||
component it links, including qpdf, PDFium and FreeType, is
|
||||
permissively licensed. No copyleft surprises in your supply
|
||||
chain.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="lp-sec">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-head lp-head--center">
|
||||
<div>
|
||||
<h2 class="lp-h2">
|
||||
<span class="line">Frequently Asked</span>
|
||||
<span class="line dim">Questions</span>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="lp-faq-wrap">
|
||||
<div id="faq-accordion" class="lp-faq lp-reveal">
|
||||
<div class="faq-item">
|
||||
<button
|
||||
class="faq-question w-full flex justify-between items-center text-left"
|
||||
type="button"
|
||||
>
|
||||
<span>Do I need a commercial license?</span>
|
||||
<i data-lucide="plus" class="faq-icon"></i>
|
||||
</button>
|
||||
<div
|
||||
class="faq-answer max-h-0 overflow-hidden transition-all duration-300 ease-in-out"
|
||||
>
|
||||
<p>
|
||||
Only if you ship Kura inside closed-source software.
|
||||
Open-source projects under an AGPL-compatible license,
|
||||
self-hosting, and internal use are all free under the
|
||||
AGPL-3.0.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="faq-item">
|
||||
<button
|
||||
class="faq-question w-full flex justify-between items-center text-left"
|
||||
type="button"
|
||||
>
|
||||
<span>Does the BentoPDF commercial license cover Kura?</span>
|
||||
<i data-lucide="plus" class="faq-icon"></i>
|
||||
</button>
|
||||
<div
|
||||
class="faq-answer max-h-0 overflow-hidden transition-all duration-300 ease-in-out"
|
||||
>
|
||||
<p>
|
||||
No. Kura is a separate project with its own license. The
|
||||
BentoPDF app license does not grant any rights to Kura, and
|
||||
a Kura license does not cover BentoPDF.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="faq-item">
|
||||
<button
|
||||
class="faq-question w-full flex justify-between items-center text-left"
|
||||
type="button"
|
||||
>
|
||||
<span>What happens if my company outgrows its tier?</span>
|
||||
<i data-lucide="plus" class="faq-icon"></i>
|
||||
</button>
|
||||
<div
|
||||
class="faq-answer max-h-0 overflow-hidden transition-all duration-300 ease-in-out"
|
||||
>
|
||||
<p>
|
||||
You move up to the matching tier at your next renewal.
|
||||
Nothing retroactive. Growing past a threshold mid-term never
|
||||
invalidates your current license.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="lp-sec">
|
||||
<div class="lp-frame">
|
||||
<div class="lp-cta">
|
||||
<h2 class="lp-h2">Not sure which tier fits?</h2>
|
||||
<p>
|
||||
Tell us what you're building and we'll tell you what it costs. No
|
||||
calls required.
|
||||
</p>
|
||||
<div class="lp-cta-actions">
|
||||
<span class="lp-brackets">
|
||||
<a
|
||||
href="mailto:[email protected]?subject=Kura%20commercial%20license%20pricing"
|
||||
class="lp-btn lp-btn--primary"
|
||||
>
|
||||
<span>[email protected]</span>
|
||||
<i data-lucide="arrow-right"></i>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
{{> footer }}
|
||||
<script type="module" src="src/js/utils/lucide-init.ts"></script>
|
||||
<script type="module" src="src/js/main.ts"></script>
|
||||
<script type="module" src="src/js/mobileMenu.ts"></script>
|
||||
<script type="module" src="src/js/landing.ts"></script>
|
||||
<!-- JSON-LD Schema -->
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@type": "WebPage",
|
||||
"name": "Kura - PDF/A, PDF/UA & PDF/X Conversion Engine | BentoPDF",
|
||||
"url": "https://www.bentopdf.com/kura"
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
+1141
-1029
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,13 @@ entrypoint_log() {
|
||||
}
|
||||
|
||||
PORT=${PORT:-8080}
|
||||
case "$PORT" in
|
||||
''|*[!0-9]*) echo "ERROR: PORT must be a number, got '$PORT'" >&2; exit 1 ;;
|
||||
esac
|
||||
if [ "$PORT" -lt 1 ] || [ "$PORT" -gt 65535 ]; then
|
||||
echo "ERROR: PORT must be between 1 and 65535, got '$PORT'" >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ "$PORT" != "8080" ]; then
|
||||
entrypoint_log "Changing Nginx listen port to $PORT"
|
||||
sed -i "s/listen 8080/listen $PORT/g; s/listen \[::\]:8080/listen [::]:$PORT/g" /etc/nginx/nginx.conf
|
||||
|
||||
+50
-4
@@ -43,6 +43,21 @@ http {
|
||||
return 301 /uk$1;
|
||||
}
|
||||
|
||||
if ($request_uri ~ ^/en/?(\?.*)?$) {
|
||||
return 301 /$1;
|
||||
}
|
||||
if ($request_uri ~ ^/en/([A-Za-z0-9].*)$) {
|
||||
return 301 /$1;
|
||||
}
|
||||
|
||||
if ($request_uri ~ ^(/(?:ar|be|da|de|es|fr|id|it|ko|nl|pl|pt|ru|sk|sv|tr|vi|zh|zh-TW|uk|ja))?/src/pages/([a-z0-9][a-z0-9-]*)\.html(\?.*)?$) {
|
||||
return 301 $1/$2$3;
|
||||
}
|
||||
|
||||
if ($request_uri ~ ^(/(?:ar|be|da|de|es|fr|id|it|ko|nl|pl|pt|ru|sk|sv|tr|vi|zh|zh-TW|uk|ja))?/change-text-color(?:\.html)?/?(\?.*)?$) {
|
||||
return 301 $1/text-color$2;
|
||||
}
|
||||
|
||||
if ($request_uri ~ ^/tools/$) {
|
||||
return 301 /tools;
|
||||
}
|
||||
@@ -68,18 +83,45 @@ http {
|
||||
return 301 /docs/$1$2;
|
||||
}
|
||||
|
||||
if ($request_uri ~ ^(/(?:en|ar|be|da|de|es|fr|id|it|ko|nl|pt|ru|sv|tr|vi|zh|zh-TW|uk|ja))?/index\.html(\?.*)?$) {
|
||||
if ($request_uri ~ ^/docs/tools/pdf-to-docx/?(\?.*)?$) {
|
||||
return 301 /docs/tools/pdf-to-word$1;
|
||||
}
|
||||
if ($request_uri ~ ^/docs/tools/decrypt-pdf/?(\?.*)?$) {
|
||||
return 301 /docs/tools/unlock-pdf$1;
|
||||
}
|
||||
if ($request_uri ~ ^/docs/tools/encrypt-pdf/?(\?.*)?$) {
|
||||
return 301 /docs/tools/protect-pdf$1;
|
||||
}
|
||||
|
||||
if ($request_uri ~ ^(/(?:en|ar|be|da|de|es|fr|id|it|ko|nl|pl|pt|ru|sk|sv|tr|vi|zh|zh-TW|uk|ja))?/index\.html(\?.*)?$) {
|
||||
return 301 $1/$2;
|
||||
}
|
||||
if ($request_uri ~ ^(/(?:en|ar|be|da|de|es|fr|id|it|ko|nl|pt|ru|sv|tr|vi|zh|zh-TW|uk|ja))?/([a-z0-9][a-z0-9-]*)\.html(\?.*)?$) {
|
||||
if ($request_uri ~ ^(/(?:en|ar|be|da|de|es|fr|id|it|ko|nl|pl|pt|ru|sk|sv|tr|vi|zh|zh-TW|uk|ja))?/pdf-to-docx(?:\.html)?/?(\?.*)?$) {
|
||||
return 301 $1/pdf-to-word$2;
|
||||
}
|
||||
if ($request_uri ~ ^(/(?:en|ar|be|da|de|es|fr|id|it|ko|nl|pl|pt|ru|sk|sv|tr|vi|zh|zh-TW|uk|ja))?/decrypt-pdf(?:\.html)?/?(\?.*)?$) {
|
||||
return 301 $1/unlock-pdf$2;
|
||||
}
|
||||
if ($request_uri ~ ^(/(?:en|ar|be|da|de|es|fr|id|it|ko|nl|pl|pt|ru|sk|sv|tr|vi|zh|zh-TW|uk|ja))?/encrypt-pdf(?:\.html)?/?(\?.*)?$) {
|
||||
return 301 $1/protect-pdf$2;
|
||||
}
|
||||
|
||||
if ($request_uri ~ ^(/(?:en|ar|be|da|de|es|fr|id|it|ko|nl|pl|pt|ru|sk|sv|tr|vi|zh|zh-TW|uk|ja))?/([a-z0-9][a-z0-9-]*)\.html(\?.*)?$) {
|
||||
return 301 $1/$2$3;
|
||||
}
|
||||
|
||||
if ($request_uri ~ ^(/(?:en|ar|be|da|de|es|fr|id|it|ko|nl|pl|pt|ru|sk|sv|tr|vi|zh|zh-TW|uk|ja))/([a-z0-9][a-z0-9-]*)/(\?.*)?$) {
|
||||
return 301 $1/$2$3;
|
||||
}
|
||||
if ($request_uri ~ ^/((?!(?:en|ar|be|da|de|es|fr|id|it|ko|nl|pl|pt|ru|sk|sv|tr|vi|zh|zh-TW|uk|ja|docs|blog)/)[a-z0-9][a-z0-9-]*)/(\?.*)?$) {
|
||||
return 301 /$1$2;
|
||||
}
|
||||
|
||||
location ~ /src/pages/ {
|
||||
return 404;
|
||||
}
|
||||
|
||||
location ~ ^/(en|ar|be|da|de|es|fr|id|it|ko|nl|pt|ru|sv|tr|vi|zh|zh-TW|uk|ja)(/.*)?$ {
|
||||
location ~ ^/(en|ar|be|da|de|es|fr|id|it|ko|nl|pl|pt|ru|sk|sv|tr|vi|zh|zh-TW|uk|ja)(/.*)?$ {
|
||||
try_files $uri $uri/ $uri.html =404;
|
||||
expires 5m;
|
||||
}
|
||||
@@ -106,6 +148,10 @@ http {
|
||||
expires 1y;
|
||||
}
|
||||
|
||||
location ~ ^/((sw\.js|coherentpdf\.browser\.min\.js|qpdf\.wasm)$|(workers|pdfjs-viewer|pdfjs-annotation-viewer)/) {
|
||||
expires epoch;
|
||||
}
|
||||
|
||||
location ~* \.(wasm|wasm\.gz|data|data\.gz)$ {
|
||||
expires 1y;
|
||||
}
|
||||
@@ -119,7 +165,7 @@ http {
|
||||
}
|
||||
|
||||
location ~* \.json$ {
|
||||
expires 1w;
|
||||
expires epoch;
|
||||
}
|
||||
|
||||
location ~* \.pdf$ {
|
||||
|
||||
Generated
+230
-935
File diff suppressed because it is too large
Load Diff
+12
-8
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "bento-pdf",
|
||||
"private": true,
|
||||
"version": "2.8.5",
|
||||
"version": "2.8.10",
|
||||
"license": "AGPL-3.0-only",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "tsc && vite build && NODE_OPTIONS='--max-old-space-size=3072' node scripts/generate-i18n-pages.mjs && node scripts/generate-sitemap.mjs && node scripts/generate-security-headers.mjs && node scripts/seo-audit.mjs",
|
||||
"build": "node scripts/generate-blog.mjs && node scripts/generate-static-tool-links.mjs && tsc && vite build && node scripts/enhance-seo-pages.mjs && NODE_OPTIONS='--max-old-space-size=3072' node scripts/generate-i18n-pages.mjs && node scripts/generate-sitemap.mjs && node scripts/generate-security-headers.mjs && node scripts/seo-audit.mjs",
|
||||
"seo-audit": "node scripts/seo-audit.mjs",
|
||||
"build:with-docs": "npm run build && npm run docs:build && node scripts/include-docs-in-dist.js",
|
||||
"build:gzip": "COMPRESSION_MODE=g npm run build",
|
||||
@@ -37,7 +37,8 @@
|
||||
"lint:security": "eslint . --no-inline-config --rule 'no-unsanitized/method:error' --rule 'no-unsanitized/property:error' --rule 'security/detect-eval-with-expression:error'",
|
||||
"security:codeql": "codeql database create ./codeql-db --language=javascript-typescript --source-root=. --overwrite --threads=0 && codeql database analyze ./codeql-db --format=sarif-latest --output=codeql-results.sarif --threads=0 codeql/javascript-queries:codeql-suites/javascript-security-extended.qls",
|
||||
"security:codeql:quick": "codeql database analyze ./codeql-db --format=csv --output=codeql-results.csv --threads=0 codeql/javascript-queries:codeql-suites/javascript-security-extended.qls",
|
||||
"security:audit": "npm audit --audit-level=high && npm run lint:security",
|
||||
"security:patterns": "node scripts/security-patterns-check.mjs",
|
||||
"security:audit": "npm audit --audit-level=high && npm run lint:security && npm run security:patterns",
|
||||
"prepare": "husky"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -59,10 +60,11 @@
|
||||
"husky": "^9.1.7",
|
||||
"jsdom": "^28.1.0",
|
||||
"lint-staged": "^16.3.1",
|
||||
"marked": "^16.4.2",
|
||||
"prettier": "^3.8.1",
|
||||
"typescript": "~5.9.3",
|
||||
"typescript-eslint": "^8.56.1",
|
||||
"vite": "^8.0.9",
|
||||
"vite": "^8.0.16",
|
||||
"vite-plugin-compression": "^0.5.1",
|
||||
"vite-plugin-handlebars": "^2.0.0",
|
||||
"vite-plugin-node-polyfills": "^0.26.0",
|
||||
@@ -89,12 +91,13 @@
|
||||
"@types/node-forge": "^1.3.14",
|
||||
"@types/papaparse": "^5.5.2",
|
||||
"archiver": "^7.0.1",
|
||||
"bentopdf-pdfium": "file:vendor/bentopdf-pdfium/bentopdf-pdfium-051abe5b72a9.tgz",
|
||||
"bentopdf-viewer": "file:vendor/bentopdf-viewer/bentopdf-viewer-051abe5b72a9.tgz",
|
||||
"blob-stream": "^0.1.3",
|
||||
"bwip-js": "^4.8.0",
|
||||
"cropperjs": "^1.6.2",
|
||||
"diff": "^8.0.3",
|
||||
"dompurify": "^3.4.0",
|
||||
"embedpdf-snippet": "file:vendor/embedpdf/embedpdf-snippet-2.9.1.tgz",
|
||||
"dompurify": "^3.4.12",
|
||||
"fast-xml-parser": "^5.7.1",
|
||||
"heic2any": "^0.0.4",
|
||||
"highlight.js": "^11.11.1",
|
||||
@@ -107,7 +110,7 @@
|
||||
"jszip": "^3.10.1",
|
||||
"lit": "^3.3.2",
|
||||
"lucide": "^0.575.0",
|
||||
"markdown-it": "^14.1.1",
|
||||
"markdown-it": "^14.2.0",
|
||||
"markdown-it-abbr": "^2.0.0",
|
||||
"markdown-it-anchor": "^9.2.0",
|
||||
"markdown-it-deflist": "^3.0.0",
|
||||
@@ -119,7 +122,7 @@
|
||||
"markdown-it-sup": "^2.0.0",
|
||||
"markdown-it-task-lists": "^2.1.1",
|
||||
"markdown-it-toc-done-right": "^4.2.0",
|
||||
"mermaid": "^11.15.0",
|
||||
"mermaid": "^11.16.1",
|
||||
"microdiff": "^1.5.0",
|
||||
"node-forge": "^1.4.0",
|
||||
"papaparse": "^5.5.3",
|
||||
@@ -154,6 +157,7 @@
|
||||
]
|
||||
},
|
||||
"overrides": {
|
||||
"uuid": "^14",
|
||||
"node-forge": "^1.4.0",
|
||||
"flatted": "^3.4.2",
|
||||
"react": "^18.3.1",
|
||||
|
||||
+132
-44
@@ -193,7 +193,7 @@
|
||||
<h3 class="font-semibold text-white">JSON to PDF</h3>
|
||||
<p class="text-gray-400 text-sm">Data to PDF</p>
|
||||
</a>
|
||||
<a href="/pdf-to-docx" class="tool-card">
|
||||
<a href="/pdf-to-word" class="tool-card">
|
||||
<i
|
||||
class="ph ph-microsoft-word-logo text-4xl text-indigo-400 mb-2"
|
||||
></i>
|
||||
@@ -422,59 +422,147 @@
|
||||
Frequently Asked Questions
|
||||
</h2>
|
||||
|
||||
<div class="space-y-4">
|
||||
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
|
||||
<summary
|
||||
class="cursor-pointer font-semibold text-white flex items-center justify-between"
|
||||
>
|
||||
Are these pdf converter tools really free?
|
||||
<i class="ph ph-caret-down text-xl"></i>
|
||||
<div class="faq-list">
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
Which file formats can I convert to PDF?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="mt-3 text-gray-400">
|
||||
Yes! All BentoPDF pdf converter tools are 100% free with no hidden
|
||||
fees, no premium tiers, and no subscription required. Use
|
||||
unlimited tools, unlimited times.
|
||||
<p class="faq-d-a">
|
||||
Word, Excel, and PowerPoint files (including the older DOC, XLS,
|
||||
and PPT formats), OpenDocument text, spreadsheets, presentations,
|
||||
and drawings, RTF, plain text, Markdown, CSV, XML, ebooks in EPUB,
|
||||
MOBI, FB2, and CBZ, XPS, Publisher, Visio, WordPerfect, Microsoft
|
||||
Works, Apple Pages, and images in JPG, PNG, HEIC, WebP, TIFF, BMP,
|
||||
SVG, and PSD. If you have a folder of mixed image types,
|
||||
<a
|
||||
href="/image-to-pdf"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>Images to PDF</a
|
||||
>
|
||||
accepts them all in one batch and puts each image on its own page.
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
|
||||
<summary
|
||||
class="cursor-pointer font-semibold text-white flex items-center justify-between"
|
||||
>
|
||||
Are my files private and secure?
|
||||
<i data-lucide="chevron-down" class="w-5 h-5"></i>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
What can I convert a PDF into?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="mt-3 text-gray-400">
|
||||
Absolutely! All processing happens entirely in your browser. Your
|
||||
files never leave your device, are never uploaded to servers.
|
||||
Complete privacy guaranteed.
|
||||
<p class="faq-d-a">
|
||||
Word (DOCX), Excel (XLSX), CSV, plain text, Markdown, SVG, and
|
||||
page images in JPG, PNG, WebP, TIFF, or BMP, with multi-page PDFs
|
||||
delivered as a ZIP holding one image per page. For long-term
|
||||
archiving,
|
||||
<a
|
||||
href="/pdf-to-pdfa"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>PDF to PDF/A</a
|
||||
>
|
||||
outputs PDF/A-1b, 2b, or 3b, and a separate tool turns a color PDF
|
||||
into a grayscale one.
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
|
||||
<summary
|
||||
class="cursor-pointer font-semibold text-white flex items-center justify-between"
|
||||
>
|
||||
Is there a file size limit?
|
||||
<i data-lucide="chevron-down" class="w-5 h-5"></i>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
Does PDF to Word keep the layout?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="mt-3 text-gray-400">
|
||||
No file size limits! Process files of any size. Browser-based
|
||||
processing means no artificial limitations.
|
||||
<p class="faq-d-a">
|
||||
<a
|
||||
href="/pdf-to-word"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>PDF to Word</a
|
||||
>
|
||||
rebuilds the document with its text, basic formatting, and general
|
||||
layout, and it can convert a batch of files in one run. Pages with
|
||||
multiple columns, embedded forms, or heavy graphics may not come
|
||||
across perfectly, so expect to tidy those up in your word
|
||||
processor.
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
|
||||
<summary
|
||||
class="cursor-pointer font-semibold text-white flex items-center justify-between"
|
||||
>
|
||||
Do I need to install software?
|
||||
<i data-lucide="chevron-down" class="w-5 h-5"></i>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
Why is my converted Word or text file empty?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="mt-3 text-gray-400">
|
||||
No installation required! All tools are web-based and work
|
||||
directly in your browser. Just open the page and start using -
|
||||
works on any device.
|
||||
<p class="faq-d-a">
|
||||
The PDF is almost certainly a scan, which stores each page as a
|
||||
picture with no text layer, so PDF to Word, PDF to Text, and the
|
||||
table converters have nothing to pull out. Run the file through
|
||||
<a href="/ocr-pdf" class="text-indigo-300 hover:text-indigo-400"
|
||||
>OCR PDF</a
|
||||
>
|
||||
first to add a searchable text layer, then convert the result.
|
||||
</p>
|
||||
</details>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
Can I get tables out of a PDF into Excel?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="faq-d-a">
|
||||
<a
|
||||
href="/pdf-to-excel"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>PDF to Excel</a
|
||||
>
|
||||
scans every page for tables and writes each one to its own
|
||||
worksheet, named after the page it came from. If it reports that
|
||||
no tables were found, the PDF lays the data out as loose text
|
||||
rather than a real table structure; PDF to CSV and Extract Tables
|
||||
rely on the same detection, so try PDF to Text to grab the raw
|
||||
content instead.
|
||||
</p>
|
||||
</details>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
Do I need Microsoft Office installed to convert Word, Excel, or
|
||||
PowerPoint files?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="faq-d-a">
|
||||
No. Those files, along with Publisher, Visio, RTF, and
|
||||
WordPerfect, are converted by a LibreOffice engine that runs
|
||||
inside your browser, so there's nothing to install;
|
||||
<a
|
||||
href="/word-to-pdf"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>Word to PDF</a
|
||||
>, for example, also takes DOC, ODT, and RTF directly. The engine
|
||||
downloads once per session, which makes the first conversion take
|
||||
a few seconds longer than the ones after it.
|
||||
</p>
|
||||
</details>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
Will converting a PDF to JPG or PNG lose quality?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="faq-d-a">
|
||||
Pages are rendered at twice their native size, so a letter-size
|
||||
page becomes an image of roughly 1,224 by 1,584 pixels.
|
||||
<a
|
||||
href="/pdf-to-jpg"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>PDF to JPG</a
|
||||
>
|
||||
is lossy with a quality slider that defaults to 90%, which keeps a
|
||||
good balance between sharpness and file size; PDF to PNG and PDF
|
||||
to TIFF are lossless, and PNG adds a scale control from 1x to 3x
|
||||
for print-quality output.
|
||||
</p>
|
||||
</details>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
Are my files uploaded to a server during conversion?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="faq-d-a">
|
||||
No. Every converter on this page, including the Office, ebook, and
|
||||
image converters, runs as WebAssembly inside your browser tab, so
|
||||
the file is read from your device and the result is written
|
||||
straight back to it. There's no upload queue, no server copy, and
|
||||
nothing to delete afterward.
|
||||
</p>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
+139
-46
@@ -5,7 +5,7 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
|
||||
<!-- Primary Meta Tags -->
|
||||
<title>PDF Editor - Free Online PDF Editor Tools | BentoPDF</title>
|
||||
<title>PDF Editing Tools - All Free Online PDF Editors | BentoPDF</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Edit, modify, and enhance your PDFs with 25+ free online tools. Compress, rotate, crop, add watermarks, page numbers, and more. Privacy-first PDF editing in your browser."
|
||||
@@ -25,7 +25,7 @@
|
||||
<meta property="og:url" content="https://www.bentopdf.com/pdf-editor" />
|
||||
<meta
|
||||
property="og:title"
|
||||
content="PDF Editor - Free Online PDF Editor Tools | BentoPDF"
|
||||
content="PDF Editing Tools - All Free Online PDF Editors | BentoPDF"
|
||||
/>
|
||||
<meta
|
||||
property="og:description"
|
||||
@@ -41,7 +41,10 @@
|
||||
|
||||
<!-- Twitter Card -->
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<meta name="twitter:title" content="PDF Editor - Free Online Tools" />
|
||||
<meta
|
||||
name="twitter:title"
|
||||
content="PDF Editing Tools - All Free Online PDF Editors | BentoPDF"
|
||||
/>
|
||||
<meta
|
||||
name="twitter:description"
|
||||
content="Edit, modify, and enhance your PDFs with 25+ free online tools. Compress, rotate, crop, add watermarks, page numbers, and more. Privacy-first PDF editing in your browser."
|
||||
@@ -116,6 +119,11 @@
|
||||
<h3 class="font-semibold text-white">Edit PDF</h3>
|
||||
<p class="text-gray-400 text-sm">Comprehensive editing</p>
|
||||
</a>
|
||||
<a href="/edit-pdf-text" class="tool-card">
|
||||
<i class="ph ph-cursor-text text-4xl text-indigo-400 mb-2"></i>
|
||||
<h3 class="font-semibold text-white">Edit PDF Text</h3>
|
||||
<p class="text-gray-400 text-sm">Rewrite text in place</p>
|
||||
</a>
|
||||
<a href="/compress-pdf" class="tool-card">
|
||||
<i class="ph ph-lightning text-4xl text-indigo-400 mb-2"></i>
|
||||
<h3 class="font-semibold text-white">Compress PDF</h3>
|
||||
@@ -291,59 +299,144 @@
|
||||
Frequently Asked Questions
|
||||
</h2>
|
||||
|
||||
<div class="space-y-4">
|
||||
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
|
||||
<summary
|
||||
class="cursor-pointer font-semibold text-white flex items-center justify-between"
|
||||
>
|
||||
Are these pdf editor tools really free?
|
||||
<i class="ph ph-caret-down text-xl"></i>
|
||||
<div class="faq-list">
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
Can I change the existing text in a PDF?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="mt-3 text-gray-400">
|
||||
Yes! All BentoPDF pdf editor tools are 100% free with no hidden
|
||||
fees, no premium tiers, and no subscription required. Use
|
||||
unlimited tools, unlimited times.
|
||||
<p class="faq-d-a">
|
||||
<a
|
||||
href="/edit-pdf-text"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>Edit PDF Text</a
|
||||
>
|
||||
lets you click any paragraph and rewrite it in place, with the
|
||||
surrounding text reflowing as you type and controls for fonts and
|
||||
styling. For adding new text boxes, comments, highlights, shapes,
|
||||
or images on top of the page, use the general Edit PDF tool
|
||||
instead.
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
|
||||
<summary
|
||||
class="cursor-pointer font-semibold text-white flex items-center justify-between"
|
||||
>
|
||||
Are my files private and secure?
|
||||
<i data-lucide="chevron-down" class="w-5 h-5"></i>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
What can I do in the Edit PDF tool?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="mt-3 text-gray-400">
|
||||
Absolutely! All processing happens entirely in your browser. Your
|
||||
files never leave your device, are never uploaded to servers.
|
||||
Complete privacy guaranteed.
|
||||
<p class="faq-d-a">
|
||||
The
|
||||
<a href="/edit-pdf" class="text-indigo-300 hover:text-indigo-400"
|
||||
>Edit PDF</a
|
||||
>
|
||||
toolbar covers highlighting, underlining, strikethrough, freehand
|
||||
drawing, text and comments, shapes and images, permanent
|
||||
redaction, and full-text search. It keeps the original PDF
|
||||
structure, so fonts, layouts, and form fields stay intact, and you
|
||||
can keep up to 10 documents open in tabs and switch between them.
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
|
||||
<summary
|
||||
class="cursor-pointer font-semibold text-white flex items-center justify-between"
|
||||
>
|
||||
Is there a file size limit?
|
||||
<i data-lucide="chevron-down" class="w-5 h-5"></i>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
How do I make a PDF smaller?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="mt-3 text-gray-400">
|
||||
No file size limits! Process files of any size. Browser-based
|
||||
processing means no artificial limitations.
|
||||
<p class="faq-d-a">
|
||||
<a
|
||||
href="/compress-pdf"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>Compress PDF</a
|
||||
>
|
||||
offers two methods. Condense strips unused structure, downsamples
|
||||
images to a target DPI, and subsets fonts while keeping text
|
||||
selectable and links working; Photon re-renders each page as a
|
||||
JPEG, which saves more on scans and photo-heavy files but leaves
|
||||
text unselectable. Start with the Balanced level and only step up
|
||||
to Aggressive or Extreme if the file is still too large.
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
|
||||
<summary
|
||||
class="cursor-pointer font-semibold text-white flex items-center justify-between"
|
||||
>
|
||||
Do I need to install software?
|
||||
<i data-lucide="chevron-down" class="w-5 h-5"></i>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
Which editing tools keep my text selectable?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="mt-3 text-gray-400">
|
||||
No installation required! All tools are web-based and work
|
||||
directly in your browser. Just open the page and start using -
|
||||
works on any device.
|
||||
<p class="faq-d-a">
|
||||
Page-level tools such as Rotate, Organize, Delete Pages,
|
||||
Background Color, and Remove Annotations work on the PDF structure
|
||||
and leave text searchable. Invert Colors, Change Text Color, and
|
||||
PDF to Greyscale re-render every page as an image, so text in
|
||||
their output can no longer be selected or searched, and the Photon
|
||||
compression mode does the same. If you need searchable text after
|
||||
one of those, run the result through
|
||||
<a href="/ocr-pdf" class="text-indigo-300 hover:text-indigo-400"
|
||||
>OCR PDF</a
|
||||
>.
|
||||
</p>
|
||||
</details>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
Can I add page numbers or a header and footer?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="faq-d-a">
|
||||
<a
|
||||
href="/page-numbers"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>Page Numbers</a
|
||||
>
|
||||
puts a number in any of six positions on every page, in plain or
|
||||
"page X of Y" style, with your choice of font size and color.
|
||||
Header and Footer adds text to six slots per page (left, center,
|
||||
and right at top and bottom), understands {page} and {total}
|
||||
placeholders so a footer like "Page {page} of {total}" fills in
|
||||
correctly on each page, and can be limited to a page range.
|
||||
</p>
|
||||
</details>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
Can I put a watermark on every page?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="faq-d-a">
|
||||
<a
|
||||
href="/add-watermark"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>Add Watermark</a
|
||||
>
|
||||
stamps text or an image onto your pages, and you position it by
|
||||
dragging on a live preview, then set opacity, rotation, and size.
|
||||
A tiled mode repeats the mark across the whole page so it's much
|
||||
harder to crop out, and you can apply one watermark to all pages,
|
||||
restrict it to a page range, or set a different watermark on each
|
||||
page.
|
||||
</p>
|
||||
</details>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
Can I rotate a single page, or fix a slightly tilted scan?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="faq-d-a">
|
||||
<a
|
||||
href="/rotate-pdf"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>Rotate PDF</a
|
||||
>
|
||||
shows a thumbnail of every page with its own left and right
|
||||
buttons for 90-degree turns, plus a bulk control for the whole
|
||||
document. For a scan that's off by a few degrees, Rotate by Custom
|
||||
Degrees accepts any angle, per page or for all pages at once.
|
||||
</p>
|
||||
</details>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
Does editing a PDF here upload it anywhere?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="faq-d-a">
|
||||
No. The editor and every other tool on this page run as
|
||||
WebAssembly inside your browser, so the file is opened, changed,
|
||||
and saved on your own device without a server in between. Nothing
|
||||
is stored, so there's no copy to delete when you're done.
|
||||
</p>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
+135
-44
@@ -14,7 +14,7 @@
|
||||
/>
|
||||
<meta
|
||||
name="keywords"
|
||||
content="pdf merge & split, merge pdf, split pdf, organize pdf, extract pages, delete pages, divide pages, add blank page, reverse pages, alternate merge, combine pages, compare pdfs, pdf booklet"
|
||||
content="pdf merge & split, merge pdf, split pdf, organize pdf, extract pages, delete pages, divide pages, add blank page, reverse pages, alternate merge, duplex collate, combine pages, compare pdfs, pdf booklet"
|
||||
/>
|
||||
<meta name="author" content="BentoPDF" />
|
||||
<meta name="robots" content="index, follow, max-image-preview:large" />
|
||||
@@ -164,6 +164,11 @@
|
||||
<h3 class="font-semibold text-white">Alternate Merge</h3>
|
||||
<p class="text-gray-400 text-sm">Interleave PDFs</p>
|
||||
</a>
|
||||
<a href="/duplex-collate" class="tool-card">
|
||||
<i class="ph ph-arrows-vertical text-4xl text-indigo-400 mb-2"></i>
|
||||
<h3 class="font-semibold text-white">Duplex Collate</h3>
|
||||
<p class="text-gray-400 text-sm">Front/back sort</p>
|
||||
</a>
|
||||
<a href="/combine-single-page" class="tool-card">
|
||||
<i
|
||||
class="ph ph-arrows-out-line-vertical text-4xl text-indigo-400 mb-2"
|
||||
@@ -246,59 +251,145 @@
|
||||
Frequently Asked Questions
|
||||
</h2>
|
||||
|
||||
<div class="space-y-4">
|
||||
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
|
||||
<summary
|
||||
class="cursor-pointer font-semibold text-white flex items-center justify-between"
|
||||
>
|
||||
Are these pdf merge & split tools really free?
|
||||
<i class="ph ph-caret-down text-xl"></i>
|
||||
<div class="faq-list">
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
How do I combine several PDFs into one file?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="mt-3 text-gray-400">
|
||||
Yes! All BentoPDF pdf merge & split tools are 100% free with no
|
||||
hidden fees, no premium tiers, and no subscription required. Use
|
||||
unlimited tools, unlimited times.
|
||||
<p class="faq-d-a">
|
||||
Add two or more files to
|
||||
<a href="/merge-pdf" class="text-indigo-300 hover:text-indigo-400"
|
||||
>Merge PDF</a
|
||||
>
|
||||
and drag them into the order you want. File Mode joins whole
|
||||
documents, with an optional page range per file such as 1-3, 5,
|
||||
while Page Mode lays out every page as a thumbnail so you can
|
||||
build the exact sequence. There's no cap on file count or total
|
||||
pages, and pages are copied without re-encoding, so quality
|
||||
doesn't change.
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
|
||||
<summary
|
||||
class="cursor-pointer font-semibold text-white flex items-center justify-between"
|
||||
>
|
||||
Are my files private and secure?
|
||||
<i data-lucide="chevron-down" class="w-5 h-5"></i>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
What are the different ways to split a PDF?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="mt-3 text-gray-400">
|
||||
Absolutely! All processing happens entirely in your browser. Your
|
||||
files never leave your device, are never uploaded to servers.
|
||||
Complete privacy guaranteed.
|
||||
<p class="faq-d-a">
|
||||
<a href="/split-pdf" class="text-indigo-300 hover:text-indigo-400"
|
||||
>Split PDF</a
|
||||
>
|
||||
has six modes: page ranges, visual selection from thumbnails, even
|
||||
or odd pages only, one file per page, splitting at bookmark
|
||||
boundaries with a choice of bookmark level, and fixed chunks of
|
||||
every N pages. A single range downloads as one PDF, while multiple
|
||||
ranges or per-page output arrive as a ZIP. Bookmark mode needs a
|
||||
PDF that actually contains bookmarks.
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
|
||||
<summary
|
||||
class="cursor-pointer font-semibold text-white flex items-center justify-between"
|
||||
>
|
||||
Is there a file size limit?
|
||||
<i data-lucide="chevron-down" class="w-5 h-5"></i>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
What's the difference between Split, Extract Pages, and Delete
|
||||
Pages?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="mt-3 text-gray-400">
|
||||
No file size limits! Process files of any size. Browser-based
|
||||
processing means no artificial limitations.
|
||||
<p class="faq-d-a">
|
||||
<a
|
||||
href="/extract-pages"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>Extract Pages</a
|
||||
>
|
||||
keeps only the pages you list and saves them as a new file, Delete
|
||||
Pages removes the pages you list and keeps everything else, and
|
||||
Split breaks one document into several files. Extract and Delete
|
||||
are inverses of each other, so pick whichever needs the shorter
|
||||
list of page numbers.
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
|
||||
<summary
|
||||
class="cursor-pointer font-semibold text-white flex items-center justify-between"
|
||||
>
|
||||
Do I need to install software?
|
||||
<i data-lucide="chevron-down" class="w-5 h-5"></i>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
Can I reorder pages or duplicate a page?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="mt-3 text-gray-400">
|
||||
No installation required! All tools are web-based and work
|
||||
directly in your browser. Just open the page and start using -
|
||||
works on any device.
|
||||
<p class="faq-d-a">
|
||||
<a
|
||||
href="/organize-pdf"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>Organize PDF</a
|
||||
>
|
||||
shows every page as a draggable thumbnail with a duplicate and a
|
||||
delete button on each one. You can also type a complete page order
|
||||
such as 3, 1, 2, 4 to rearrange everything in one step, and
|
||||
Reverse Pages flips an entire document, or a batch of them, in one
|
||||
click.
|
||||
</p>
|
||||
</details>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
My scanner put all the front pages first and all the backs after.
|
||||
How do I fix the order?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="faq-d-a">
|
||||
<a
|
||||
href="/duplex-collate"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>Duplex Collate</a
|
||||
>
|
||||
handles exactly that: it interleaves the two blocks into front 1,
|
||||
back 1, front 2, back 2 order, with an option to reverse the back
|
||||
block for stacks that were flipped before the second pass. If the
|
||||
fronts and backs are in two separate files, Alternate Merge
|
||||
interleaves pages from multiple PDFs the same way.
|
||||
</p>
|
||||
</details>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
How do I print a PDF as a folded booklet?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="faq-d-a">
|
||||
<a
|
||||
href="/pdf-booklet"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>PDF Booklet</a
|
||||
>
|
||||
reorders the pages into saddle-stitch imposition and shows a
|
||||
preview of each sheet before you download. Print the result
|
||||
double-sided with "flip on short edge", fold the stack in half,
|
||||
and staple at the spine; if the page count isn't a multiple of
|
||||
four, blank pages are added automatically to fill the last sheet.
|
||||
</p>
|
||||
</details>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
Can I see what changed between two versions of a PDF?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="faq-d-a">
|
||||
<a
|
||||
href="/compare-pdfs"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>Compare PDFs</a
|
||||
>
|
||||
pairs up the pages of two documents and highlights differences in
|
||||
text, images, annotations, headers and footers, and formatting, in
|
||||
either a side-by-side or an overlay view. Filters let you hide the
|
||||
change types you don't care about, OCR can be switched on for
|
||||
scanned documents, and the comparison can be exported as a PDF
|
||||
report.
|
||||
</p>
|
||||
</details>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
Are my files uploaded when I merge or split them?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="faq-d-a">
|
||||
No. Merging, splitting, and reordering run as WebAssembly inside
|
||||
your browser, so the files are read from your disk and the result
|
||||
is written back to it without passing through a server. That holds
|
||||
for large scans and multi-file batches too.
|
||||
</p>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
+143
-45
@@ -111,12 +111,12 @@
|
||||
<div
|
||||
class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4"
|
||||
>
|
||||
<a href="/encrypt-pdf" class="tool-card">
|
||||
<a href="/protect-pdf" class="tool-card">
|
||||
<i class="ph ph-lock text-4xl text-indigo-400 mb-2"></i>
|
||||
<h3 class="font-semibold text-white">Encrypt PDF</h3>
|
||||
<p class="text-gray-400 text-sm">Add password</p>
|
||||
</a>
|
||||
<a href="/decrypt-pdf" class="tool-card">
|
||||
<a href="/unlock-pdf" class="tool-card">
|
||||
<i class="ph ph-lock-open text-4xl text-indigo-400 mb-2"></i>
|
||||
<h3 class="font-semibold text-white">Decrypt PDF</h3>
|
||||
<p class="text-gray-400 text-sm">Remove password</p>
|
||||
@@ -226,59 +226,157 @@
|
||||
Frequently Asked Questions
|
||||
</h2>
|
||||
|
||||
<div class="space-y-4">
|
||||
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
|
||||
<summary
|
||||
class="cursor-pointer font-semibold text-white flex items-center justify-between"
|
||||
>
|
||||
Are these pdf security tools really free?
|
||||
<i class="ph ph-caret-down text-xl"></i>
|
||||
<div class="faq-list">
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
What's the difference between protecting a PDF with a password and
|
||||
restricting its permissions?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="mt-3 text-gray-400">
|
||||
Yes! All BentoPDF pdf security tools are 100% free with no hidden
|
||||
fees, no premium tiers, and no subscription required. Use
|
||||
unlimited tools, unlimited times.
|
||||
<p class="faq-d-a">
|
||||
A user password, set with
|
||||
<a
|
||||
href="/protect-pdf"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>Protect PDF</a
|
||||
>, is required to open the file at all. Permissions are flags
|
||||
stored inside the encryption that control what a reader can do
|
||||
after opening, such as printing, copying, editing, annotating, or
|
||||
filling forms, and they only take effect when an owner password is
|
||||
set. Change Permissions lets you allow or deny each action
|
||||
individually, while Protect PDF applies the strictest set as soon
|
||||
as you add an owner password.
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
|
||||
<summary
|
||||
class="cursor-pointer font-semibold text-white flex items-center justify-between"
|
||||
>
|
||||
Are my files private and secure?
|
||||
<i data-lucide="chevron-down" class="w-5 h-5"></i>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
How strong is the password protection?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="mt-3 text-gray-400">
|
||||
Absolutely! All processing happens entirely in your browser. Your
|
||||
files never leave your device, are never uploaded to servers.
|
||||
Complete privacy guaranteed.
|
||||
<p class="faq-d-a">
|
||||
Protect PDF and Change Permissions use 256-bit AES encryption, the
|
||||
PDF 2.0 standard, applied by QPDF running in your browser. The
|
||||
encryption itself isn't practical to brute-force, so the weak
|
||||
point is the password: use a long passphrase and send it through a
|
||||
different channel than the file. Permission flags are a separate
|
||||
matter, since they rely on the reader honoring them and some
|
||||
third-party tools ignore them.
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
|
||||
<summary
|
||||
class="cursor-pointer font-semibold text-white flex items-center justify-between"
|
||||
>
|
||||
Is there a file size limit?
|
||||
<i data-lucide="chevron-down" class="w-5 h-5"></i>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
Can I remove a password from a PDF if I don't know it?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="mt-3 text-gray-400">
|
||||
No file size limits! Process files of any size. Browser-based
|
||||
processing means no artificial limitations.
|
||||
<p class="faq-d-a">
|
||||
No.
|
||||
<a
|
||||
href="/unlock-pdf"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>Unlock PDF</a
|
||||
>
|
||||
needs the password and then saves a copy with no encryption or
|
||||
restrictions left, and none of the tools crack or brute-force
|
||||
passwords. For a file that opens fine but blocks printing or
|
||||
copying, use Remove Restrictions instead, which asks for the owner
|
||||
password if the file has one.
|
||||
</p>
|
||||
</details>
|
||||
|
||||
<details class="bg-gray-800 p-5 rounded-lg border border-gray-700">
|
||||
<summary
|
||||
class="cursor-pointer font-semibold text-white flex items-center justify-between"
|
||||
>
|
||||
Do I need to install software?
|
||||
<i data-lucide="chevron-down" class="w-5 h-5"></i>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
What's the difference between Sign PDF and a digital signature?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="mt-3 text-gray-400">
|
||||
No installation required! All tools are web-based and work
|
||||
directly in your browser. Just open the page and start using -
|
||||
works on any device.
|
||||
<p class="faq-d-a">
|
||||
Sign PDF places a drawn, typed, or uploaded signature image on the
|
||||
page, with an option to flatten it so nobody can move or delete it
|
||||
later.
|
||||
<a
|
||||
href="/digital-sign-pdf"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>Digital Signature</a
|
||||
>
|
||||
applies a cryptographic signature with your own X.509 certificate
|
||||
(.pfx, .p12, or .pem), which proves who signed and that the file
|
||||
hasn't changed since, and Validate Signature checks signatures
|
||||
already in a file. Certificate signing may need an internet
|
||||
connection to fetch the certificate chain, and self-signed
|
||||
certificates will show warnings in Adobe Reader.
|
||||
</p>
|
||||
</details>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
How do I redact text so it's actually gone?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="faq-d-a">
|
||||
Use the redaction tool in the
|
||||
<a href="/edit-pdf" class="text-indigo-300 hover:text-indigo-400"
|
||||
>PDF Editor</a
|
||||
>. Marking text or an area only flags it. Once you apply the
|
||||
redaction, the marked content is permanently removed from the page
|
||||
instead of just being covered with a box, and if you download with
|
||||
marks that haven't been applied yet, the editor offers to apply
|
||||
them first. When you redact selected text, copies of it in the
|
||||
file's properties, bookmarks, comments, and attachments are
|
||||
removed on download too, unless the file is encrypted. Area
|
||||
redactions have no text to search for, so if the file's
|
||||
properties, comments, or attachments could reveal the same
|
||||
information, run Remove Metadata or Sanitize PDF on the result as
|
||||
well.
|
||||
</p>
|
||||
</details>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
What's the difference between Remove Metadata and Sanitize PDF?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="faq-d-a">
|
||||
<a
|
||||
href="/remove-metadata"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>Remove Metadata</a
|
||||
>
|
||||
strips only the document properties: title, author, dates,
|
||||
producer, XMP data, document IDs, and application-specific data,
|
||||
and it leaves pages, forms, links, and bookmarks untouched.
|
||||
Sanitize PDF goes further and can also flatten forms and delete
|
||||
annotations, embedded JavaScript, attachments, layers, links, and
|
||||
structure tags, with each item selectable. Both are irreversible,
|
||||
so keep your original file.
|
||||
</p>
|
||||
</details>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
What does flattening a PDF do, and when should I use it?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="faq-d-a">
|
||||
<a
|
||||
href="/flatten-pdf"
|
||||
class="text-indigo-300 hover:text-indigo-400"
|
||||
>Flatten PDF</a
|
||||
>
|
||||
burns form fields and annotations (comments, highlights, stamps,
|
||||
sticky notes, signature fields) into the page content, so they
|
||||
look the same but can no longer be edited, moved, or removed. Use
|
||||
it after a form is filled in or a signature is placed and before
|
||||
you send the file, because there's no way to unflatten. Text stays
|
||||
selectable and searchable, and bookmarks are kept.
|
||||
</p>
|
||||
</details>
|
||||
<details class="faq-d">
|
||||
<summary class="faq-d-q">
|
||||
Are my passwords, certificates, or files sent to a server?
|
||||
<i data-lucide="plus" class="faq-d-icon"></i>
|
||||
</summary>
|
||||
<p class="faq-d-a">
|
||||
No. Encrypting, unlocking, sanitizing, and signing all run as
|
||||
WebAssembly in your browser, so the document, the password you
|
||||
type, and your certificate's private key stay on your device. The
|
||||
one network exception is Digital Signature, which may contact your
|
||||
certificate authority's servers to fetch the certificate chain;
|
||||
the document itself is still never sent.
|
||||
</p>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
+10
-39
@@ -83,9 +83,7 @@
|
||||
<h1 class="text-4xl md:text-5xl font-bold text-center text-white mb-4">
|
||||
Privacy Policy
|
||||
</h1>
|
||||
<p class="text-center text-gray-500">
|
||||
Last Updated: September 14, 2025
|
||||
</p>
|
||||
<p class="text-center text-gray-500">Last Updated: August 29, 2026</p>
|
||||
|
||||
<div class="legal-content mt-12">
|
||||
<h2>1. Our Commitment to Privacy</h2>
|
||||
@@ -127,44 +125,17 @@
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h2>3. Information We May Collect (Non-Personal Data)</h2>
|
||||
<h2>3. No Tracking or Analytics</h2>
|
||||
<p>
|
||||
To improve our website and services, we may collect anonymous,
|
||||
non-personally identifiable information. This type of data helps us
|
||||
understand how users interact with our site, which tools are most
|
||||
popular, and how we can improve the user experience. This includes:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<strong>Usage Analytics:</strong> Anonymized data such as which
|
||||
tools are used, how often they are used, and which features are
|
||||
accessed. This is aggregated and cannot be tied back to an
|
||||
individual user or document.
|
||||
</li>
|
||||
<li>
|
||||
<strong>Performance Data:</strong> Anonymized error reports or
|
||||
performance metrics to help us identify and fix bugs. This data
|
||||
contains no personal information or file content.
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
We use privacy-respecting analytics platforms for this purpose.
|
||||
Specifically, we use
|
||||
<a
|
||||
href="https://simpleanalytics.com"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="text-indigo-400 hover:underline"
|
||||
>Simple Analytics</a
|
||||
>
|
||||
to track anonymous visit counts. This means we can see how many
|
||||
users visit our site, but
|
||||
BentoPDF does not track you at all. We do not use cookies, analytics
|
||||
platforms, error-reporting services, or any tracking scripts, not
|
||||
even on the live website at bentopdf.com. We do not collect usage
|
||||
data, visit counts, performance metrics, or any other information
|
||||
about you or your session, anonymized or otherwise.
|
||||
<strong
|
||||
>we never collect personal information or identify individual
|
||||
users</strong
|
||||
>. Simple Analytics is fully GDPR-compliant and respects user
|
||||
privacy. We do not use tracking cookies for advertising or
|
||||
cross-site profiling.
|
||||
>We never know who you are, how many people use BentoPDF, or what
|
||||
you do with it.</strong
|
||||
>
|
||||
</p>
|
||||
|
||||
<h2>4. Third-Party Libraries</h2>
|
||||
|
||||
+2
-2
@@ -19,7 +19,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
||||
- Feature/reverse multi pdfs [`#58`](https://github.com/alam00000/bentopdf/pull/58)
|
||||
- added description to Unraid XML [`#65`](https://github.com/alam00000/bentopdf/pull/65)
|
||||
- Added hamburger Navbar [`#62`](https://github.com/alam00000/bentopdf/pull/62)
|
||||
- feat(versioning): Added version management sysytem [`#52`](https://github.com/alam00000/bentopdf/pull/52)
|
||||
- feat(versioning): Added version management system [`#52`](https://github.com/alam00000/bentopdf/pull/52)
|
||||
- Fix#20 : fixed the tesseract issue [`#60`](https://github.com/alam00000/bentopdf/pull/60)
|
||||
- feat: add search bar keyboard shortcut [`#49`](https://github.com/alam00000/bentopdf/pull/49)
|
||||
- feat(pdf-tools): add attachments feature to embed files in PDFs [`#53`](https://github.com/alam00000/bentopdf/pull/53)
|
||||
@@ -27,7 +27,7 @@ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
||||
- feat: add support for multiple blank pages insertion [`#42`](https://github.com/alam00000/bentopdf/pull/42)
|
||||
- Multiupload handle encrypted pdf [`#43`](https://github.com/alam00000/bentopdf/pull/43)
|
||||
- feat:Setup Prettier for code formatting [`#30`](https://github.com/alam00000/bentopdf/pull/30)
|
||||
- created png as unraid does not supprot svg [`#24`](https://github.com/alam00000/bentopdf/pull/24)
|
||||
- created png as unraid does not support svg [`#24`](https://github.com/alam00000/bentopdf/pull/24)
|
||||
- adding unraid template [`#23`](https://github.com/alam00000/bentopdf/pull/23)
|
||||
- feat(pdf-tools): add alternate merge tool for mixing pdf pages [`#21`](https://github.com/alam00000/bentopdf/pull/21)
|
||||
- feat: add remove blank pages tool with sensitivity control [`#19`](https://github.com/alam00000/bentopdf/pull/19)
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
Content-Security-Policy: default-src 'self'; script-src 'self' 'wasm-unsafe-eval' 'unsafe-eval' blob: https://cdn.jsdelivr.net/npm/@bentopdf/[email protected]/ https://cdn.jsdelivr.net/npm/@bentopdf/[email protected]/assets/ https://cdn.jsdelivr.net/npm/[email protected]/dist/ https://cdn.jsdelivr.net/npm/[email protected]/dist/ https://cdn.jsdelivr.net/npm/[email protected]/; worker-src 'self' blob:; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: blob: https:; font-src 'self' data: https://fonts.gstatic.com https://rawcdn.githack.com; connect-src 'self' blob: https://api.github.com https://fonts.gstatic.com https://cdn.jsdelivr.net https://bentopdf-cors-proxy.bentopdf.workers.dev https://rawcdn.githack.com; object-src 'none'; base-uri 'self'; frame-src 'self' blob:; frame-ancestors 'self'; form-action 'self'
|
||||
X-Frame-Options: SAMEORIGIN
|
||||
X-Content-Type-Options: nosniff
|
||||
X-XSS-Protection: 1; mode=block
|
||||
Referrer-Policy: strict-origin-when-cross-origin
|
||||
Permissions-Policy: geolocation=(), camera=(), microphone=(), payment=(), usb=(), interest-cohort=()
|
||||
Cross-Origin-Opener-Policy: same-origin
|
||||
Cross-Origin-Embedder-Policy: credentialless
|
||||
Cross-Origin-Resource-Policy: cross-origin
|
||||
|
||||
/docs
|
||||
! Content-Security-Policy
|
||||
Content-Security-Policy: default-src 'self'; script-src 'self' 'sha256-DQUgNM9X0iH2019NkUxeBvnBoEoRKkHBc/I0iLqPNPA=' 'sha256-La1r0VSk0Po4KFI0duEKhmPu+u0I416JW3oONqtdf4M='; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: blob: https:; font-src 'self' data: https://fonts.gstatic.com https://rawcdn.githack.com; connect-src 'self' https://api.github.com https://fonts.gstatic.com https://cdn.jsdelivr.net https://bentopdf-cors-proxy.bentopdf.workers.dev https://rawcdn.githack.com; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; form-action 'self'
|
||||
|
||||
/docs/*
|
||||
! Content-Security-Policy
|
||||
Content-Security-Policy: default-src 'self'; script-src 'self' 'sha256-DQUgNM9X0iH2019NkUxeBvnBoEoRKkHBc/I0iLqPNPA=' 'sha256-La1r0VSk0Po4KFI0duEKhmPu+u0I416JW3oONqtdf4M='; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: blob: https:; font-src 'self' data: https://fonts.gstatic.com https://rawcdn.githack.com; connect-src 'self' https://api.github.com https://fonts.gstatic.com https://cdn.jsdelivr.net https://bentopdf-cors-proxy.bentopdf.workers.dev https://rawcdn.githack.com; object-src 'none'; base-uri 'self'; frame-ancestors 'self'; form-action 'self'
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 7.5 KiB |
@@ -212,17 +212,17 @@
|
||||
},
|
||||
"browserBased": {
|
||||
"question": "كيف تحافظ المعالجة عبر المتصفح على أمانك؟",
|
||||
"answer": "بالعمل بالكامل داخل متصفحك، يضمن BentoPDF أن ملفاتك لا تغادر جهازك أبدًا. هذا يلغي مخاطر اختراق الخوادم أو تسريب البيانات أو الوصول غير المصرح به. ملفاتك تبقى ملكك — دائمًا."
|
||||
"answer": "بالعمل بالكامل داخل متصفحك، يضمن BentoPDF أن ملفاتك لا تغادر جهازك أبدًا. هذا يلغي مخاطر اختراق الخوادم أو تسريب البيانات أو الوصول غير المصرح به. ملفاتك تبقى ملكك، دائمًا."
|
||||
},
|
||||
"analytics": {
|
||||
"question": "هل تستخدمون ملفات تعريف الارتباط أو التحليلات لتتبعي؟",
|
||||
"answer": "نحن نهتم بخصوصيتك. BentoPDF لا يتتبع المعلومات الشخصية. نستخدم Simple Analytics فقط لرؤية عدد الزيارات المجهولة. هذا يعني أننا نعرف عدد المستخدمين الذين يزورون موقعنا، لكننا لا نعرف أبدًا من أنت. Simple Analytics متوافق تمامًا مع GDPR ويحترم خصوصيتك."
|
||||
"answer": "لا. لا يتتبعك BentoPDF على الإطلاق. لا نستخدم ملفات تعريف الارتباط أو أدوات التحليلات أو أي نصوص تتبع، ولا حتى على الموقع المباشر bentopdf.com. لا نعرف أبدًا من أنت أو ماذا تفعل بالأدوات."
|
||||
}
|
||||
},
|
||||
"testimonials": {
|
||||
"title": "ماذا يقول",
|
||||
"users": "مستخدمونا",
|
||||
"say": ""
|
||||
"say": " "
|
||||
},
|
||||
"support": {
|
||||
"title": "أعجبك عملنا؟",
|
||||
@@ -239,7 +239,9 @@
|
||||
"legal": "قانوني",
|
||||
"termsAndConditions": "الشروط والأحكام",
|
||||
"privacyPolicy": "سياسة الخصوصية",
|
||||
"followUs": "تابعنا"
|
||||
"followUs": "تابعنا",
|
||||
"privacyShort": "الخصوصية",
|
||||
"termsShort": "الشروط"
|
||||
},
|
||||
"merge": {
|
||||
"title": "دمج ملفات PDF",
|
||||
@@ -287,12 +289,13 @@
|
||||
},
|
||||
"mission": {
|
||||
"title": "مهمتنا",
|
||||
"titleDim": " ",
|
||||
"description": "تقديم أشمل مجموعة أدوات PDF تحترم خصوصيتك ولا تطلب أي مقابل. نؤمن بأن أدوات المستندات الأساسية يجب أن تكون متاحة للجميع، في كل مكان، بدون عوائق."
|
||||
},
|
||||
"philosophy": {
|
||||
"label": "فلسفتنا الأساسية",
|
||||
"title": "الخصوصية أولاً. دائمًا.",
|
||||
"description": "في عصر أصبحت فيه البيانات سلعة، نتبع نهجًا مختلفًا. تتم جميع معالجة أدوات Bentopdf محليًا في متصفحك. هذا يعني أن ملفاتك لا تلمس خوادمنا أبدًا، ولا نرى مستنداتك، ولا نتتبع ما تفعله. مستنداتك تبقى خاصة تمامًا وبشكل قاطع. إنها ليست مجرد ميزة؛ إنها أساسنا."
|
||||
"description": "في عصر أصبحت فيه البيانات سلعة، نتبع نهجًا مختلفًا. تتم جميع معالجة أدوات BentoPDF محليًا في متصفحك. هذا يعني أن ملفاتك لا تلمس خوادمنا أبدًا، ولا نرى مستنداتك، ولا نتتبع ما تفعله. مستنداتك تبقى خاصة تمامًا وبشكل قاطع. إنها ليست مجرد ميزة؛ إنها أساسنا."
|
||||
},
|
||||
"whyBentopdf": {
|
||||
"title": "لماذا",
|
||||
@@ -315,7 +318,7 @@
|
||||
},
|
||||
"cta": {
|
||||
"title": "مستعد للبدء؟",
|
||||
"description": "انضم إلى آلاف المستخدمين الذين يثقون بـ Bentopdf لاحتياجات مستنداتهم اليومية. اختبر الفرق الذي يمكن أن تحدثه الخصوصية والأداء.",
|
||||
"description": "انضم إلى آلاف المستخدمين الذين يثقون بـ BentoPDF لاحتياجات مستنداتهم اليومية. اختبر الفرق الذي يمكن أن تحدثه الخصوصية والأداء.",
|
||||
"button": "استكشف جميع الأدوات"
|
||||
}
|
||||
},
|
||||
@@ -350,9 +353,12 @@
|
||||
"download": "تنزيل:",
|
||||
"downloadSelected": "تنزيل المحدد",
|
||||
"exportPdf": "تصدير PDF",
|
||||
"uploadPdfFiles": "اختر ملفات PDF",
|
||||
"dragAndDrop": "اسحب وأفلت ملفات PDF هنا، أو انقر للاختيار",
|
||||
"uploadPdfFiles": "اختر ملفات PDF أو صور",
|
||||
"dragAndDrop": "اسحب وأفلت ملفات PDF أو الصور هنا، أو انقر للاختيار",
|
||||
"selectFiles": "اختر الملفات",
|
||||
"dropToAdd": "أفلت ملفات PDF أو الصور للإضافة",
|
||||
"convertingImages": "جارٍ تحويل الصور إلى PDF...",
|
||||
"failedToConvertImages": "فشل تحويل الصور إلى PDF.",
|
||||
"renderingPages": "جارٍ عرض الصفحات...",
|
||||
"actions": {
|
||||
"duplicatePage": "تكرار هذه الصفحة",
|
||||
|
||||
@@ -55,6 +55,124 @@
|
||||
"name": "محرر PDF",
|
||||
"subtitle": "تعليق، تمييز، تنقيح، تعليقات، إضافة أشكال/صور، بحث وعرض ملفات PDF."
|
||||
},
|
||||
"editPdfText": {
|
||||
"name": "تحرير نص PDF",
|
||||
"subtitle": "انقر على أي فقرة وحرّرها في مكانها مع إعادة تدفق فوري للنص والخطوط والأنماط.",
|
||||
"saved": "تم حفظ ملف PDF بنجاح! ({{size}} كيلوبايت)",
|
||||
"failedToLoad": "تعذّر تحميل محرّر نصوص PDF.",
|
||||
"loadingFonts": "جارٍ تحميل الخطوط...",
|
||||
"fontsUnavailable": "تعذّر تنزيل خط مطلوب لبعض الأحرف. تحقّق من اتصالك وحاول مرة أخرى، وإلا فقد لا تظهر هذه الأحرف بشكل صحيح في ملف PDF المحفوظ.",
|
||||
"howToUpload": "رفع ملف PDF",
|
||||
"howToClick": "انقر على فقرة",
|
||||
"howToRestyle": "غيّر تنسيق أي شيء",
|
||||
"relatedPdfEditor": "التعليق على ملفات PDF وتمييزها",
|
||||
"relatedSignPdf": "ارسم توقيعك أو اكتبه أو ارفعه",
|
||||
"relatedWatermark": "اطبع نصًا أو صورًا",
|
||||
"relatedStamps": "ضع أختامًا على الصفحات",
|
||||
"relatedCompress": "تقليل حجم الملف",
|
||||
"relatedOrganizeName": "تنظيم PDF",
|
||||
"relatedOrganize": "إعادة ترتيب الصفحات وإدارتها",
|
||||
"open": "فتح",
|
||||
"export": "تصدير",
|
||||
"filterAll": "الكل",
|
||||
"filterText": "نص",
|
||||
"filterImages": "صور",
|
||||
"filterShapes": "أشكال",
|
||||
"addText": "إضافة نص",
|
||||
"langAuto": "تلقائي",
|
||||
"change": "تغيير",
|
||||
"ignore": "تجاهل",
|
||||
"next": "التالي",
|
||||
"replace": "استبدال",
|
||||
"replaceAll": "استبدال الكل",
|
||||
"emptyState": "افتح ملف PDF لتحرير نصه وصوره وأشكاله.",
|
||||
"choosePdf": "اختر ملف PDF…",
|
||||
"font": "الخط",
|
||||
"systemFonts": "خطوط النظام",
|
||||
"color": "اللون",
|
||||
"alignment": "المحاذاة",
|
||||
"style": "النمط",
|
||||
"lists": "القوائم",
|
||||
"outline": "المخطط",
|
||||
"spacing": "التباعد",
|
||||
"direction": "الاتجاه",
|
||||
"dirAuto": "تلقائي",
|
||||
"pathStroke": "حد المسار",
|
||||
"tipBackToUpload": "العودة إلى الرفع",
|
||||
"tipOpenAnotherPdf": "فتح ملف PDF آخر",
|
||||
"tipExportS": "تصدير (⌘S)",
|
||||
"tipUndoZ": "تراجع (⌘Z)",
|
||||
"tipRedoZ": "إعادة (⇧⌘Z)",
|
||||
"tipFileDetails": "تفاصيل الملف",
|
||||
"tipEditExistingContent": "تحرير المحتوى الحالي",
|
||||
"tipWhatTheEditToolTouchesNarrowTheScopeOnBus": "ما تتأثر به أداة التحرير — ضيّق النطاق في الصفحات المزدحمة",
|
||||
"tipClickThePageToAddATextBox": "انقر على الصفحة لإضافة مربع نص",
|
||||
"tipSpellCheckLanguage": "لغة التدقيق الإملائي",
|
||||
"tipFindAndReplace": "بحث واستبدال",
|
||||
"tipAddAnImage": "إضافة صورة",
|
||||
"tipCopyThisPageSTextInReadingOrder": "نسخ نص هذه الصفحة بترتيب القراءة",
|
||||
"tipCheckTheSpellingOfThisPage": "تدقيق إملاء هذه الصفحة",
|
||||
"tipShowOrHideTheFormatPanel": "إظهار لوحة التنسيق أو إخفاؤها",
|
||||
"phReplaceWith": "استبدال بـ",
|
||||
"tipAddToYourDictionary": "إضافة إلى القاموس",
|
||||
"tipClose": "إغلاق",
|
||||
"phFind": "بحث",
|
||||
"tipPreviousMatch": "التطابق السابق",
|
||||
"tipNextMatch": "التطابق التالي",
|
||||
"tipRotateLeft90": "تدوير 90° لليسار",
|
||||
"tipRotateRight90": "تدوير 90° لليمين",
|
||||
"tipFlipHorizontal": "قلب أفقي",
|
||||
"tipFlipVertical": "قلب رأسي",
|
||||
"tipReplaceThisImageKeepingItsPlacement": "استبدال هذه الصورة مع الحفاظ على موضعها",
|
||||
"tipAlternateTextForAccessibilityTaggedPdfs": "نص بديل لإمكانية الوصول (ملفات PDF الموسومة)",
|
||||
"tipBringToFront": "إحضار إلى الأمام",
|
||||
"tipSendToBack": "إرسال إلى الخلف",
|
||||
"tipDuplicate": "تكرار",
|
||||
"tipDelete": "حذف",
|
||||
"tipAlignLeftEdges": "محاذاة الحواف اليسرى",
|
||||
"tipAlignHorizontalCenters": "توسيط أفقي",
|
||||
"tipAlignRightEdges": "محاذاة الحواف اليمنى",
|
||||
"tipAlignTops": "محاذاة الحواف العلوية",
|
||||
"tipAlignVerticalCenters": "توسيط رأسي",
|
||||
"tipAlignBottoms": "محاذاة الحواف السفلية",
|
||||
"tipDistributeHorizontally": "توزيع أفقي",
|
||||
"tipDistributeVertically": "توزيع رأسي",
|
||||
"tipFontSize": "حجم الخط",
|
||||
"tipListFontsInstalledOnThisDeviceChromium": "عرض الخطوط المثبتة على هذا الجهاز (Chromium)",
|
||||
"tipCustomTextColor": "لون نص مخصص",
|
||||
"tipAlignLeft": "محاذاة لليسار",
|
||||
"tipAlignCenter": "توسيط",
|
||||
"tipAlignRight": "محاذاة لليمين",
|
||||
"tipJustify": "ضبط",
|
||||
"tipBold": "عريض",
|
||||
"tipItalic": "مائل",
|
||||
"tipUnderline": "تسطير",
|
||||
"tipStrikethrough": "يتوسطه خط",
|
||||
"tipSuperscript": "حرف مرتفع",
|
||||
"tipSubscript": "حرف منخفض",
|
||||
"tipToggleBulletedItem": "تبديل عنصر نقطي",
|
||||
"tipToggleNumberedItem": "تبديل عنصر مرقّم",
|
||||
"tipNumberedListMarkerStyle": "نمط علامة القوائم المرقّمة",
|
||||
"tipDecreaseListIndentTab": "تقليل المسافة البادئة (⇧Tab)",
|
||||
"tipIncreaseListIndentTab": "زيادة المسافة البادئة (Tab)",
|
||||
"tipTextOutlineColor": "لون حد النص",
|
||||
"tipOutlineWidth0None": "عرض الحد (0 = بلا)",
|
||||
"tipFromContent": "من المحتوى",
|
||||
"tipLeftToRight": "من اليسار إلى اليمين",
|
||||
"tipRightToLeft": "من اليمين إلى اليسار",
|
||||
"tipStrokeColor": "لون الحد",
|
||||
"tipStrokeWidth": "عرض الحد",
|
||||
"tipZoomPresets": "إعدادات التكبير المسبقة",
|
||||
"tipZoomOut": "تصغير",
|
||||
"tipZoomIn": "تكبير",
|
||||
"tipFitPage": "ملاءمة الصفحة",
|
||||
"tipPreviousPage": "الصفحة السابقة",
|
||||
"tipTypeAPageNumberAndPressEnter": "اكتب رقم الصفحة ثم اضغط Enter",
|
||||
"tipNextPage": "الصفحة التالية",
|
||||
"tipDocumentProperties": "خصائص المستند",
|
||||
"tipHideBar": "إخفاء الشريط",
|
||||
"tipShowBar": "إظهار الشريط"
|
||||
},
|
||||
"jpgToPdf": {
|
||||
"name": "JPG إلى PDF",
|
||||
"subtitle": "إنشاء PDF من صور JPG وJPEG وJPEG2000 (JP2/JPX)."
|
||||
@@ -514,6 +632,51 @@
|
||||
"retainPageLabels": "الاحتفاظ بتسميات الصفحات الأصلية لكل ملف",
|
||||
"retainPageLabelsHint": "غير مفعّل (افتراضي): يستخدم ملف PDF المدمج ترقيمًا طبيعيًا من 1 إلى N. مفعّل: يتم الاحتفاظ بتسميات الصفحات الأصلية لكل ملف (قد ينتج عن ذلك تسميات مكررة)."
|
||||
},
|
||||
"duplexCollate": {
|
||||
"name": "ترتيب المسح على الوجهين",
|
||||
"subtitle": "أعد ترتيب ملف PDF ممسوح في كتلتين (كل الوجوه الأمامية أولًا، ثم كل الوجوه الخلفية) إلى ترتيب أمامي/خلفي صحيح.",
|
||||
"totalPagesLabel": "إجمالي الصفحات:",
|
||||
"splitAfterPageLabel": "التقسيم بعد الصفحة",
|
||||
"splitAfterPagePlaceholder": "مثال: 50",
|
||||
"backBlockOrderLabel": "ترتيب كتلة الوجه الخلفي",
|
||||
"backBlockReverseOption": "عكس كتلة الوجه الخلفي (شائع عند قلب الرزمة)",
|
||||
"backBlockKeepOption": "إبقاء كتلة الوجه الخلفي كما هي",
|
||||
"autoSplitButton": "اكتشاف نقطة التقسيم تلقائيًا (المنتصف)",
|
||||
"exportGroupedLabel": "تصدير ملفات مجمّعة حسب طول المستند الأصلي",
|
||||
"pagesPerDocumentLabel": "عدد الصفحات لكل مستند أصلي",
|
||||
"groupedHelp": "عند التفعيل، يكون الناتج ملف ZIP يحتوي على ملف PDF لكل مستند مجمّع.",
|
||||
"collateButton": "ترتيب ملف PDF",
|
||||
"invalidFileTitle": "ملف غير صالح",
|
||||
"invalidFileMessage": "يرجى اختيار ملف PDF.",
|
||||
"loadingPdf": "جارٍ تحميل ملف PDF...",
|
||||
"loadErrorMessage": "تعذّر تحميل ملف PDF.",
|
||||
"fileMeta": "{{size}} - {{count}} صفحة",
|
||||
"oddPageWarning": "عدد الصفحات فردي ({{count}}). يجب أن يكون عدد صفحات المسح على الوجهين زوجيًا؛ قد تكون هناك صفحة ناقصة أو زائدة.",
|
||||
"previewSummary": "كتلة الوجه الأمامي: {{frontCount}} صفحة، كتلة الوجه الخلفي: {{backCount}} صفحة. الناتج: {{outputCount}} صفحة بترتيب أمامي/خلفي.",
|
||||
"previewMismatchWarning": "طول كتلتي الوجه الأمامي والخلفي مختلف ({{frontCount}} أمامية مقابل {{backCount}} خلفية). ستُضاف الصفحات الزائدة ({{extraCount}}) من الكتلة الأطول في النهاية دون مقابل.",
|
||||
"missingFileTitle": "ملف مفقود",
|
||||
"missingFileMessage": "يرجى رفع ملف PDF يحتوي على صفحتين على الأقل قبل المعالجة.",
|
||||
"invalidSplitTitle": "نقطة تقسيم غير صالحة",
|
||||
"invalidSplitMessage": "يجب أن تكون نقطة التقسيم بين الصفحة 1 والصفحة {{maxSplit}}.",
|
||||
"unevenConfirmTitle": "كتل غير متساوية",
|
||||
"unevenConfirmMessage": "تحتوي كتلة الوجه الأمامي على {{frontCount}} صفحة وكتلة الوجه الخلفي على {{backCount}} صفحة.\nيعني ذلك عادةً أن صفحة مُسحت مرتين أو أنها مفقودة.\n\nستُضاف الصفحات غير المقترنة ({{extraCount}}) في النهاية.\n\nهل تريد المتابعة على أي حال؟",
|
||||
"invalidGroupTitle": "حجم مجموعة غير صالح",
|
||||
"invalidGroupMessage": "يرجى إدخال عدد صفحات صالح لكل مستند أصلي.",
|
||||
"collatingLoader": "جارٍ ترتيب المسح على الوجهين...",
|
||||
"successMessage": "تم إنشاء ملف PDF المرتَّب بنجاح.",
|
||||
"successGroupedMessage": "اكتمل الترتيب. تم إنشاء {{fileCount}} ملف مجمّع.",
|
||||
"processErrorMessage": "تعذّر ترتيب ملف PDF.",
|
||||
"howItWorksStep1Title": "ارفع الملف الممسوح",
|
||||
"howItWorksStep1": "أفلت ملف PDF واحدًا يحتوي على جميع الوجوه الأمامية يليها جميع الوجوه الخلفية.",
|
||||
"howItWorksStep2Title": "حدّد نقطة التقسيم",
|
||||
"howItWorksStep2": "حدّد أين تنتهي كتلة الوجوه الأمامية، ثم اختر ما إذا كانت كتلة الوجوه الخلفية بحاجة إلى عكس.",
|
||||
"howItWorksStep3Title": "رتّب ونزّل",
|
||||
"howItWorksStep3": "احصل على ملف PDF واحد بترتيب متعاقب، أو ملف ZIP يحتوي على ملف منفصل لكل مستند أصلي.",
|
||||
"faqOddPagesQuestion": "ماذا لو كان عدد صفحات الملف الممسوح فرديًا؟",
|
||||
"faqOddPagesAnswer": "يجب أن يكون عدد صفحات المسح على الوجهين زوجيًا. إذا لم يكن كذلك، فغالبًا مُسحت صفحة مرتين أو فُقدت صفحة. تنبّهك الأداة قبل المعالجة، وتُضاف الصفحات غير المقترنة في النهاية حتى لا يضيع أي شيء.",
|
||||
"faqBackOrderQuestion": "لماذا قد أُبقي كتلة الوجوه الخلفية كما هي؟",
|
||||
"faqBackOrderAnswer": "يعتمد ذلك على طريقة إدخال الرزمة في التمريرة الثانية. قلب الرزمة بالكامل ينتج وجوهًا خلفية بترتيب معكوس، وهو الإعداد الافتراضي. أما إذا أعادها الماسح الضوئي بالترتيب نفسه للوجوه الأمامية، فاختر إبقاء الكتلة كما هي."
|
||||
},
|
||||
"addAttachments": {
|
||||
"name": "إضافة مرفقات",
|
||||
"subtitle": "تضمين ملف واحد أو أكثر في PDF الخاص بك."
|
||||
@@ -1151,5 +1314,13 @@
|
||||
"faqSinglePageAnswer": "نعم! فعّل خيار \"التكرار\" وستتكرر صفحات التراكب على جميع صفحات الملف الأساسي. العلامة المائية ذات الصفحة الواحدة ستُطبق على كل صفحة.",
|
||||
"faqPrivacyQuestion": "هل ملفاتي خاصة وآمنة؟",
|
||||
"faqPrivacyAnswer": "بالتأكيد! تتم جميع المعالجة في متصفحك. لا تغادر ملفاتك جهازك أبداً، مما يضمن خصوصية كاملة."
|
||||
},
|
||||
"unlockPdf": {
|
||||
"name": "فك تشفير PDF",
|
||||
"subtitle": "فتح PDF بإزالة حماية كلمة المرور."
|
||||
},
|
||||
"protectPdf": {
|
||||
"name": "تشفير PDF",
|
||||
"subtitle": "قفل PDF بإضافة كلمة مرور."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"contact": "Кантакты",
|
||||
"licensing": "Ліцэнзія",
|
||||
"allTools": "Усе інструменты",
|
||||
"docs": "Docs",
|
||||
"docs": "Дакументацыя",
|
||||
"openMainMenu": "Адкрыць галоўнае меню",
|
||||
"language": "Мова",
|
||||
"searchLanguage": "Пошук мовы…",
|
||||
@@ -59,7 +59,7 @@
|
||||
"title": "Пачніце працу з",
|
||||
"toolsLabel": "інструментамі",
|
||||
"subtitle": "Націсніце на інструмент, каб адкрыць запампоўшчык",
|
||||
"searchPlaceholder": "Пошук (напр., \"выдаліць\", \"сціснуць\"...)",
|
||||
"searchPlaceholder": "Пошук (напр., «выдаліць», «сціснуць»...)",
|
||||
"backToTools": "Назад да інструментаў",
|
||||
"firstLoadNotice": "Першае адкрыццё займае крыху часу, пакуль загружаецца рухавік канвертацыі. Потым усё будзе адкрывацца імгненна."
|
||||
},
|
||||
@@ -100,11 +100,11 @@
|
||||
},
|
||||
"howItWorks": {
|
||||
"title": "Як гэта працуе",
|
||||
"step1Title": "Загрузіць файл",
|
||||
"step1Title": "Запампуйце файл",
|
||||
"step1": "Націсніце або перацягніце файл, каб пачаць",
|
||||
"step2Title": "Апрацоўка",
|
||||
"step2Title": "Апрацуйце",
|
||||
"step2": "Націсніце кнопку апрацоўкі",
|
||||
"step3Title": "Спампаваць",
|
||||
"step3Title": "Спампуйце",
|
||||
"step3": "Імгненна захавайце апрацаваны файл"
|
||||
},
|
||||
"relatedTools": {
|
||||
@@ -175,7 +175,7 @@
|
||||
},
|
||||
"ccpa": {
|
||||
"title": "Адпаведнасць CCPA",
|
||||
"description": "Дае жыхарам Каліфорніі правы ведаць, як збіраецца, выкарыстоўваецца і перадаецца іх персанальная інфармацыя."
|
||||
"description": "Дае жыхарам Каліфорніі правы адносна таго, як збіраецца, выкарыстоўваецца і перадаецца іх персанальная інфармацыя."
|
||||
},
|
||||
"hipaa": {
|
||||
"title": "Адпаведнасць HIPAA",
|
||||
@@ -211,12 +211,12 @@
|
||||
"answer": "Звычайна інструменты PDF запампоўваюць вашы файлы на сервер для апрацоўкі. BentoPDF ніколі так не робіць. Мы выкарыстоўваем бяспечныя сучасныя вэб-тэхналогіі, каб апрацоўваць вашы файлы непасрэдна ў браўзеры. Гэта азначае большую хуткасць, лепшую прыватнасць і поўны спакой."
|
||||
},
|
||||
"browserBased": {
|
||||
"question": "Чаму апрацоўка ў браўзеры - гэта бяспечна?",
|
||||
"question": "Чаму апрацоўка ў браўзеры — гэта бяспечна?",
|
||||
"answer": "Працуючы цалкам у браўзеры, BentoPDF гарантуе, што вашы файлы ніколі не пакінуць вашу прыладу. Гэта ліквідуе рызыкі ўзлому сервераў, уцечак даных або несанкцыянаванага доступу. Вашы файлы застаюцца вашымі — заўсёды."
|
||||
},
|
||||
"analytics": {
|
||||
"question": "Вы выкарыстоўваеце cookies або аналітыку, каб сачыць за мной?",
|
||||
"answer": "Мы дбаем пра вашу прыватнасць. BentoPDF не адсочвае персанальную інфармацыю. Мы выкарыстоўваем Simple Analytics, толькі каб бачыць ананімную статыстыку наведванняў. Гэта значыць, мы ведаем, колькі карыстальнікаў наведвае наш сайт, але ніколі не ведаем, хто вы. Simple Analytics цалкам адпавядае GDPR і шануе вашу прыватнасць."
|
||||
"answer": "Не. BentoPDF вас ніяк не адсочвае. Мы не выкарыстоўваем файлы cookie, аналітыку ці скрыпты адсочвання — нават на працоўным сайце bentopdf.com. Мы ніколі не ведаем, хто вы і што вы робіце з інструментамі."
|
||||
}
|
||||
},
|
||||
"testimonials": {
|
||||
@@ -239,7 +239,9 @@
|
||||
"legal": "Прававая інфармацыя",
|
||||
"termsAndConditions": "Умовы выкарыстання",
|
||||
"privacyPolicy": "Палітыка прыватнасці",
|
||||
"followUs": "Сачыце за намі"
|
||||
"followUs": "Сачыце за намі",
|
||||
"privacyShort": "Прыватнасць",
|
||||
"termsShort": "Умовы"
|
||||
},
|
||||
"merge": {
|
||||
"title": "Аб'яднаць PDF",
|
||||
@@ -286,7 +288,8 @@
|
||||
"noCompromises": "Без кампрамісаў."
|
||||
},
|
||||
"mission": {
|
||||
"title": "Наша місія",
|
||||
"title": "Наша",
|
||||
"titleDim": "місія",
|
||||
"description": "Даць найбольш поўны набор інструментаў PDF, які шануе вашу прыватнасць і ніколі не патрабуе аплаты. Мы лічым, што неабходныя інструменты для дакументаў павінны быць даступнымі ўсім, паўсюль, без бар'ераў."
|
||||
},
|
||||
"philosophy": {
|
||||
@@ -302,7 +305,7 @@
|
||||
},
|
||||
"free": {
|
||||
"title": "Цалкам бясплатна",
|
||||
"description": "Без пробных версій, падпісак, схаваных плацяжоў і без \"прэміум\" функцый. Мы верым, што магутныя інструменты PDF павінны быць грамадскай карысцю, а не цэнтрам прыбытку."
|
||||
"description": "Без пробных версій, падпісак, схаваных плацяжоў і без «прэміум» функцый. Мы верым, што магутныя інструменты PDF павінны быць грамадскай карысцю, а не цэнтрам прыбытку."
|
||||
},
|
||||
"noAccount": {
|
||||
"title": "Не патрэбны ўліковы запіс",
|
||||
@@ -350,9 +353,12 @@
|
||||
"download": "Спампаваць:",
|
||||
"downloadSelected": "Спампаваць выбранае",
|
||||
"exportPdf": "Экспартаваць PDF",
|
||||
"uploadPdfFiles": "Выбраць PDF файлы",
|
||||
"dragAndDrop": "Перацягніце PDF файлы сюды або націсніце, каб выбраць",
|
||||
"uploadPdfFiles": "Выбраць PDF або відарысы",
|
||||
"dragAndDrop": "Перацягніце PDF або відарысы сюды або націсніце, каб выбраць",
|
||||
"selectFiles": "Выбраць файлы",
|
||||
"dropToAdd": "Адпусціце PDF або відарысы, каб дадаць",
|
||||
"convertingImages": "Канвертаванне відарысаў у PDF...",
|
||||
"failedToConvertImages": "Не ўдалося канвертаваць відарысы ў PDF.",
|
||||
"renderingPages": "Апрацоўка старонак...",
|
||||
"actions": {
|
||||
"duplicatePage": "Дубляваць гэту старонку",
|
||||
|
||||
+395
-223
@@ -19,7 +19,8 @@
|
||||
"name": "Аб'яднаць PDF",
|
||||
"subtitle": "Аб'яднаць некалькі PDF у адзін файл. Закладкі захоўваюцца.",
|
||||
"retainPageLabels": "Захоўваць арыгінальныя пазнакі старонак з кожнага файла",
|
||||
"retainPageLabelsHint": "Выключана (па змаўчанні): аб’яднаны PDF выкарыстоўвае натуральную нумарацыю 1–N. Уключана: арыгінальныя пазнакі старонак кожнага файла захоўваюцца (могуць узнікнуць паўторы)."
|
||||
"retainPageLabelsHint": "Выключана (прадвызначана): аб'яднаны PDF выкарыстоўвае натуральную нумарацыю 1–N. Уключана: арыгінальныя пазнакі старонак кожнага файла захоўваюцца (могуць узнікнуць паўторы).",
|
||||
"removeDuplicateFonts": "Выдаліць дублікаты шрыфтоў"
|
||||
},
|
||||
"splitPdf": {
|
||||
"name": "Падзяліць PDF",
|
||||
@@ -32,7 +33,7 @@
|
||||
"condense": "Condense (Рэкамендуецца)",
|
||||
"photon": "Photon (Для PDF з вялікай колькасцю фота)",
|
||||
"condenseInfo": "Condense выкарыстоўвае прасунутае сцісканне: выдаляе лішняе, аптымізуе відарысы, паднаборы шрыфтоў. Найлепш пасуе для большасці PDF.",
|
||||
"photonInfo": "Photon ператварае старонкі ў відарысы. Для PDF з вялікай колькасцю фота або сканіраваных PDF.",
|
||||
"photonInfo": "Photon канвертуе старонкі ў відарысы. Для PDF з вялікай колькасцю фота або сканаваных PDF.",
|
||||
"photonWarning": "Папярэджанне: стане немагчыма вылучыць тэкст, і перастануць працаваць спасылкі.",
|
||||
"levelLabel": "Узровень сціскання",
|
||||
"light": "Лёгкі (Захаванне якасці)",
|
||||
@@ -55,6 +56,124 @@
|
||||
"name": "Рэдактар PDF",
|
||||
"subtitle": "Анатаваць, вылучыць, зацямніць, дадаць фігуры/відарысы, каментарыі, пошук і прагляд PDF."
|
||||
},
|
||||
"editPdfText": {
|
||||
"name": "Рэдагаваць тэкст PDF",
|
||||
"subtitle": "Рэдагаваць любы абзац на месцы — з імгненнай перакампаноўкай тэксту, шрыфтамі і стылямі.",
|
||||
"saved": "PDF паспяхова захаваны! ({{size}} КБ)",
|
||||
"failedToLoad": "Не ўдалося загрузіць рэдактар тэксту PDF.",
|
||||
"loadingFonts": "Загрузка шрыфтоў...",
|
||||
"fontsUnavailable": "Не ўдалося спампаваць шрыфт, патрэбны для некаторых сімвалаў. Праверце злучэнне і паспрабуйце яшчэ раз, інакш гэтыя сімвалы могуць адлюстроўвацца няправільна ў захаваным PDF.",
|
||||
"howToUpload": "Запампуйце PDF",
|
||||
"howToClick": "Націсніце на абзац",
|
||||
"howToRestyle": "Змяніце стыль",
|
||||
"relatedPdfEditor": "Анатаваць і размячаць PDF",
|
||||
"relatedSignPdf": "Намаляваць, увесці або запампаваць подпіс",
|
||||
"relatedWatermark": "Нанесці тэкст або відарысы",
|
||||
"relatedStamps": "Размясціць штампы на старонках",
|
||||
"relatedCompress": "Паменшыць памер файла",
|
||||
"relatedOrganizeName": "Упарадкаваць PDF",
|
||||
"relatedOrganize": "Змяніць парадак і кіраваць старонкамі",
|
||||
"open": "Адкрыць",
|
||||
"export": "Экспарт",
|
||||
"filterAll": "Усе",
|
||||
"filterText": "Тэкст",
|
||||
"filterImages": "Відарысы",
|
||||
"filterShapes": "Фігуры",
|
||||
"addText": "Дадаць тэкст",
|
||||
"langAuto": "Аўта",
|
||||
"change": "Змяніць",
|
||||
"ignore": "Прапусціць",
|
||||
"next": "Далей",
|
||||
"replace": "Замяніць",
|
||||
"replaceAll": "Замяніць усё",
|
||||
"emptyState": "Адкрыйце PDF, каб рэдагаваць тэкст, відарысы і фігуры.",
|
||||
"choosePdf": "Выберыце PDF…",
|
||||
"font": "Шрыфт",
|
||||
"systemFonts": "Сістэмныя шрыфты",
|
||||
"color": "Колер",
|
||||
"alignment": "Выраўноўванне",
|
||||
"style": "Стыль",
|
||||
"lists": "Спісы",
|
||||
"outline": "Абвядзенне",
|
||||
"spacing": "Інтэрвал",
|
||||
"direction": "Напрамак",
|
||||
"dirAuto": "Аўта",
|
||||
"pathStroke": "Абвядзенне контуру",
|
||||
"tipBackToUpload": "Назад да запампоўкі",
|
||||
"tipOpenAnotherPdf": "Адкрыць іншы PDF",
|
||||
"tipExportS": "Экспарт (⌘S)",
|
||||
"tipUndoZ": "Адрабіць (⌘Z)",
|
||||
"tipRedoZ": "Узнавіць (⇧⌘Z)",
|
||||
"tipFileDetails": "Звесткі пра файл",
|
||||
"tipEditExistingContent": "Рэдагаваць наяўнае змесціва",
|
||||
"tipWhatTheEditToolTouchesNarrowTheScopeOnBus": "На што дзейнічае інструмент рэдагавання — звузьце вобласць на насычаных старонках",
|
||||
"tipClickThePageToAddATextBox": "Націсніце на старонку, каб дадаць тэкставае поле",
|
||||
"tipSpellCheckLanguage": "Мова праверкі правапісу",
|
||||
"tipFindAndReplace": "Знайсці і замяніць",
|
||||
"tipAddAnImage": "Дадаць відарыс",
|
||||
"tipCopyThisPageSTextInReadingOrder": "Скапіраваць тэкст старонкі ў парадку чытання",
|
||||
"tipCheckTheSpellingOfThisPage": "Праверыць правапіс на гэтай старонцы",
|
||||
"tipShowOrHideTheFormatPanel": "Паказаць або схаваць панэль фарматавання",
|
||||
"phReplaceWith": "Замяніць на",
|
||||
"tipAddToYourDictionary": "Дадаць у слоўнік",
|
||||
"tipClose": "Закрыць",
|
||||
"phFind": "Знайсці",
|
||||
"tipPreviousMatch": "Папярэдняе супадзенне",
|
||||
"tipNextMatch": "Наступнае супадзенне",
|
||||
"tipRotateLeft90": "Павярнуць на 90° улева",
|
||||
"tipRotateRight90": "Павярнуць на 90° управа",
|
||||
"tipFlipHorizontal": "Адлюстраваць гарызантальна",
|
||||
"tipFlipVertical": "Адлюстраваць вертыкальна",
|
||||
"tipReplaceThisImageKeepingItsPlacement": "Замяніць відарыс, захаваўшы размяшчэнне",
|
||||
"tipAlternateTextForAccessibilityTaggedPdfs": "Альтэрнатыўны тэкст для даступнасці (тэгаваныя PDF)",
|
||||
"tipBringToFront": "На пярэдні план",
|
||||
"tipSendToBack": "На задні план",
|
||||
"tipDuplicate": "Дубляваць",
|
||||
"tipDelete": "Выдаліць",
|
||||
"tipAlignLeftEdges": "Выраўнаваць па левых краях",
|
||||
"tipAlignHorizontalCenters": "Цэнтраваць гарызантальна",
|
||||
"tipAlignRightEdges": "Выраўнаваць па правых краях",
|
||||
"tipAlignTops": "Выраўнаваць па верхніх краях",
|
||||
"tipAlignVerticalCenters": "Цэнтраваць вертыкальна",
|
||||
"tipAlignBottoms": "Выраўнаваць па ніжніх краях",
|
||||
"tipDistributeHorizontally": "Размеркаваць гарызантальна",
|
||||
"tipDistributeVertically": "Размеркаваць вертыкальна",
|
||||
"tipFontSize": "Памер шрыфта",
|
||||
"tipListFontsInstalledOnThisDeviceChromium": "Паказаць шрыфты, усталяваныя на гэтай прыладзе (Chromium)",
|
||||
"tipCustomTextColor": "Уласны колер тэксту",
|
||||
"tipAlignLeft": "Па левым краі",
|
||||
"tipAlignCenter": "Па цэнтры",
|
||||
"tipAlignRight": "Па правым краі",
|
||||
"tipJustify": "Па шырыні",
|
||||
"tipBold": "Тлусты",
|
||||
"tipItalic": "Курсіў",
|
||||
"tipUnderline": "Падкрэслены",
|
||||
"tipStrikethrough": "Закрэслены",
|
||||
"tipSuperscript": "Верхні індэкс",
|
||||
"tipSubscript": "Ніжні індэкс",
|
||||
"tipToggleBulletedItem": "Маркіраваны пункт",
|
||||
"tipToggleNumberedItem": "Нумараваны пункт",
|
||||
"tipNumberedListMarkerStyle": "Стыль маркера нумараваных спісаў",
|
||||
"tipDecreaseListIndentTab": "Паменшыць водступ (⇧Tab)",
|
||||
"tipIncreaseListIndentTab": "Павялічыць водступ (Tab)",
|
||||
"tipTextOutlineColor": "Колер контуру тэксту",
|
||||
"tipOutlineWidth0None": "Таўшчыня контуру (0 = няма)",
|
||||
"tipFromContent": "Са змесціва",
|
||||
"tipLeftToRight": "Злева направа",
|
||||
"tipRightToLeft": "Справа налева",
|
||||
"tipStrokeColor": "Колер абвядзення",
|
||||
"tipStrokeWidth": "Таўшчыня абвядзення",
|
||||
"tipZoomPresets": "Перадвызначаныя налады маштабу",
|
||||
"tipZoomOut": "Паменшыць",
|
||||
"tipZoomIn": "Павялічыць",
|
||||
"tipFitPage": "Па памеры старонкі",
|
||||
"tipPreviousPage": "Папярэдняя старонка",
|
||||
"tipTypeAPageNumberAndPressEnter": "Увядзіце нумар старонкі і націсніце Enter",
|
||||
"tipNextPage": "Наступная старонка",
|
||||
"tipDocumentProperties": "Уласцівасці дакумента",
|
||||
"tipHideBar": "Схаваць панэль",
|
||||
"tipShowBar": "Паказаць панэль"
|
||||
},
|
||||
"jpgToPdf": {
|
||||
"name": "JPG у PDF",
|
||||
"subtitle": "Стварыць PDF з відарысаў JPG, JPEG і JPEG2000 (JP2/JPX)."
|
||||
@@ -83,12 +202,12 @@
|
||||
"editBookmarks": {
|
||||
"name": "Рэдагаваць закладкі",
|
||||
"subtitle": "Дадаць, рэдагаваць, імпартаваць, выдаліць і выняць закладкі PDF.",
|
||||
"autoExtractExisting": "Аўтаматычна выманне існуючых закладак",
|
||||
"autoExtractExisting": "Аўтаматычнае выманне наяўных закладак",
|
||||
"importSectionTitle": "Або імпартаваць закладкі",
|
||||
"csvFormat": "Фармат CSV: загаловак,старонка,узровень",
|
||||
"jsonFormat": "Фармат JSON",
|
||||
"uploadCsvAction": "Націсніце, каб загрузіць CSV",
|
||||
"uploadJsonAction": "Націсніце, каб загрузіць JSON",
|
||||
"uploadCsvAction": "Націсніце, каб запампаваць CSV",
|
||||
"uploadJsonAction": "Націсніце, каб запампаваць JSON",
|
||||
"orDragHere": "або перацягніце сюды"
|
||||
},
|
||||
"tableOfContents": {
|
||||
@@ -97,15 +216,15 @@
|
||||
"titleLabel": "Загаловак зместу",
|
||||
"fontSize": "Памер шрыфта",
|
||||
"fontFamily": "Сямейства шрыфтоў",
|
||||
"addBookmark": "Додати закладку для сторінки змісту",
|
||||
"addBookmark": "Дадаць закладку для старонкі зместу",
|
||||
"generateButton": "Стварыць змест",
|
||||
"selectPdfFirst": "Спачатку выберыце PDF-файл.",
|
||||
"statusReadingFileMainThread": "Читання файлу (головний потік)...",
|
||||
"statusReadingFileMainThread": "Чытанне файла (галоўны паток)...",
|
||||
"statusGenerating": "Стварэнне зместу...",
|
||||
"errorReadingFileWithMessage": "Помилка читання файлу: {{message}}",
|
||||
"errorReadingFileWithMessage": "Памылка чытання файла: {{message}}",
|
||||
"successGeneratedDownloadStarted": "Змест паспяхова створаны! Спампоўванне распачалося.",
|
||||
"workerErrorWithMessage": "Помилка: {{message}}",
|
||||
"workerErrorOccurred": "Адбылася памылка працаўніка. Падрабязнасці ў кансолі."
|
||||
"workerErrorWithMessage": "Памылка: {{message}}",
|
||||
"workerErrorOccurred": "Адбылася памылка апрацоўшчыка. Падрабязнасці ў кансолі."
|
||||
},
|
||||
"pageNumbers": {
|
||||
"name": "Нумары старонак",
|
||||
@@ -122,18 +241,18 @@
|
||||
"howLabelsWorkStep4": "Уключыце працяг нумарацыі, калі адно правіла выкарыстоўвае разарваны дыяпазон, напрыклад 1-9,30-40 або няцотныя старонкі.",
|
||||
"labelRulesTitle": "Правілы пазнак",
|
||||
"addRule": "Дадаць правіла",
|
||||
"removeExistingLabels": "Выдаліць існуючыя пазнакі старонак перад прымяненнем гэтых правіл",
|
||||
"removeExistingLabels": "Выдаліць наяўныя пазнакі старонак перад прымяненнем гэтых правіл",
|
||||
"cpdfNote": "Гэты інструмент выкарыстоўвае CoherentPDF у вашым браўзеры. Калі CoherentPDF не наладжаны, вам будзе прапанавана наладзіць яго ў наладах WASM.",
|
||||
"processButton": "Дадаць пазнакі старонак",
|
||||
"howItWorksUploadTitle": "Запампаваць файл",
|
||||
"howItWorksUploadDescription": "Выберыце PDF, які хочаце перапазначыць.",
|
||||
"howItWorksDefineTitle": "Вызначыць правілы",
|
||||
"howItWorksUploadTitle": "Запампуйце файл",
|
||||
"howItWorksUploadDescription": "Выберыце PDF, у якім хочаце змяніць пазнакі.",
|
||||
"howItWorksDefineTitle": "Вызначце правілы",
|
||||
"howItWorksDefineDescription": "Наладзьце адно або некалькі правіл пазнак старонак з дыяпазонамі, стылямі, прэфіксамі і пачатковымі значэннямі.",
|
||||
"howItWorksDownloadTitle": "Спампаваць",
|
||||
"howItWorksDownloadTitle": "Спампуйце",
|
||||
"howItWorksDownloadDescription": "Захавайце абноўлены PDF з новымі пазнакамі старонак.",
|
||||
"relatedToolsTitle": "Звязаныя інструменты PDF",
|
||||
"faqWhatIsQuestion": "Што такое пазнака старонкі?",
|
||||
"faqWhatIsAnswer": "Пазнака старонкі - гэта нумарацыя, якую чытальнікі PDF паказваюць у мініяцюрах, навігацыі па старонках і дыялогах друку. Яна не друкуе новы тэкст на самой старонцы.",
|
||||
"faqWhatIsAnswer": "Пазнака старонкі — гэта нумарацыя, якую чытальнікі PDF паказваюць у мініяцюрах, навігацыі па старонках і дыялогах друку. Яна не друкуе новы тэкст на самой старонцы.",
|
||||
"faqMixQuestion": "Ці можна спалучаць рымскія і звычайныя лічбы?",
|
||||
"faqMixAnswer": "Так. Дадайце некалькі правіл, напрыклад 1-4 з LowercaseRoman і 5-20 з DecimalArabic.",
|
||||
"faqPrivacyQuestion": "Ці застаюцца мае файлы прыватнымі?",
|
||||
@@ -185,12 +304,12 @@
|
||||
},
|
||||
"invertColors": {
|
||||
"name": "Інвертаваць колеры",
|
||||
"subtitle": "Стварыць версію PDF у \"цёмнай тэме\"."
|
||||
"subtitle": "Стварыць версію PDF у «цёмнай тэме»."
|
||||
},
|
||||
"scannerEffect": {
|
||||
"name": "Эфект сканера",
|
||||
"subtitle": "Зрабіць PDF падобным да адсканаванага дакумента.",
|
||||
"scanSettings": "Налады сканіравання",
|
||||
"scanSettings": "Налады сканавання",
|
||||
"colorspace": "Каляровая прастора",
|
||||
"gray": "Градацыі шэрага",
|
||||
"border": "Рамка",
|
||||
@@ -215,7 +334,7 @@
|
||||
"temperature": "Тэмпература",
|
||||
"tint": "Адценне",
|
||||
"gamma": "Гама",
|
||||
"sepia": "Сэпія",
|
||||
"sepia": "Сепія",
|
||||
"processButton": "Ужыць рэгуліроўкі колеру"
|
||||
},
|
||||
"backgroundColor": {
|
||||
@@ -232,7 +351,7 @@
|
||||
"usernameLabel": "Імя для штампа",
|
||||
"usernamePlaceholder": "Увядзіце сваё імя (для штампаў)",
|
||||
"usernameHint": "Гэта імя з'явіцца на створаных вамі штампах.",
|
||||
"saveButton": "Захаваць PDF з пячаткай"
|
||||
"saveButton": "Захаваць PDF са штампамі"
|
||||
},
|
||||
"removeAnnotations": {
|
||||
"name": "Выдаліць анатацыі",
|
||||
@@ -241,9 +360,9 @@
|
||||
"pdfFormFiller": {
|
||||
"name": "Запоўніць форму PDF",
|
||||
"subtitle": "Запоўніць форму непасрэдна ў браўзеры. Таксама падтрымліваюцца формы XFA.",
|
||||
"uploadHint": "Завантажте PDF з полями форми. Заповніть їх безпосередньо у переглядачі нижче, потім натисніть кнопку, щоб зберегти та завантажити заповнену форму. Також підтримуються форми XFA.",
|
||||
"uploadHint": "Запампуйце PDF з палямі формы. Запоўніце іх непасрэдна ў праглядальніку ніжэй, а затым націсніце кнопку, каб захаваць і спампаваць запоўненую форму. Таксама падтрымліваюцца формы XFA.",
|
||||
"xfaNoteTitle": "Заўвага па формах XFA:",
|
||||
"xfaNoteDescription": "XFA (XML Forms Architecture) — застарілий формат, який підтримується лише певними PDF-переглядачами, такими як BentoPDF та Firefox. Якщо ви відкриваєте XFA PDF в іншому ПЗ і бачите порожні сторінки або відсутність полів форми, це означає, що цей переглядач не підтримує XFA. Щоб правильно переглядати та заповнювати форми XFA, використовуйте Firefox або заповнювач форм BentoPDF."
|
||||
"xfaNoteDescription": "XFA (XML Forms Architecture) — састарэлы фармат, што падтрымліваецца толькі некаторымі праглядальнікамі PDF, напрыклад BentoPDF і Firefox. Калі адкрыць PDF XFA ў іншай праграме і ўбачыць пустыя старонкі або адсутнасць палёў формы, гэта азначае, што праглядальнік не падтрымлівае XFA. Для правільнага прагляду і запаўнення XFA выкарыстоўвайце Firefox або праграму запаўнення формаў BentoPDF."
|
||||
},
|
||||
"createPdfForm": {
|
||||
"name": "Стварыць форму PDF",
|
||||
@@ -287,33 +406,33 @@
|
||||
"textToPdf": {
|
||||
"name": "Тэкст у PDF",
|
||||
"subtitle": "Канвертаваць звычайны тэкставы файл у PDF.",
|
||||
"uploadFiles": "Загрузіць файлы",
|
||||
"uploadFiles": "Запампаваць файлы",
|
||||
"typeText": "Увесці тэкст",
|
||||
"acceptedFormats": "Текстові файли (.txt)",
|
||||
"acceptedFormats": "Тэкставыя файлы (.txt)",
|
||||
"fontFamily": "Сямейства шрыфтоў",
|
||||
"fontSize": "Памер шрыфта",
|
||||
"textColor": "Колер тэксту",
|
||||
"pageSize": "Памер старонкі",
|
||||
"rtlAutoDetectNote": "Мови RTL (арабська, урду, перська тощо) автоматично визначаються, і напрямок тексту регулюється.",
|
||||
"rtlAutoDetectNote": "Мовы з напрамкам справа налева (арабская, урду, персідская і інш.) вызначаюцца аўтаматычна, і кірунак тэксту карэктуецца.",
|
||||
"createButton": "Стварыць PDF"
|
||||
},
|
||||
"jsonToPdf": {
|
||||
"name": "JSON у PDF",
|
||||
"subtitle": "Канвертаваць файлы JSON у фармат PDF.",
|
||||
"noteLabel": "Примітка:",
|
||||
"noteText": "Підтримуються лише JSON-файли, створені інструментом PDF→JSON. Стандартні JSON-файли від інших інструментів не працюють.",
|
||||
"acceptedFormats": "Кілька JSON-файлів",
|
||||
"noteLabel": "Нататка:",
|
||||
"noteText": "Падтрымліваюцца толькі файлы JSON, створаныя інструментам канвертавання PDF у JSON. Стандартныя файлы JSON з іншых інструментаў не будуць працаваць.",
|
||||
"acceptedFormats": "Некалькі файлаў JSON",
|
||||
"status": {
|
||||
"selectAtLeastOne": "Виберіть принаймні 1 JSON-файл",
|
||||
"selectedReady": "Вибрано {{count}} файл(ів). Готово до конвертації!",
|
||||
"readingFiles": "Читання файлів (головний потік)...",
|
||||
"converting": "Конвертація JSON-файлів у PDF...",
|
||||
"readError": "Помилка читання файлів: {{message}}",
|
||||
"creatingZip": "Створення ZIP-файлу...",
|
||||
"success": "JSON-файли успішно конвертовано в PDF! Завантаження ZIP розпочато.",
|
||||
"zipError": "Помилка створення ZIP: {{message}}",
|
||||
"workerError": "Помилка Worker: {{message}}",
|
||||
"getStarted": "Виберіть JSON-файли, щоб почати"
|
||||
"selectAtLeastOne": "Выберыце хаця б 1 файл JSON",
|
||||
"selectedReady": "Выбрана файлаў: {{count}}. Гатова да канвертавання!",
|
||||
"readingFiles": "Чытанне файлаў (галоўны паток)...",
|
||||
"converting": "Пераўтварэнне файлаў JSON у PDF...",
|
||||
"readError": "Памылка чытання файлаў: {{message}}",
|
||||
"creatingZip": "Стварэнне ZIP-файла...",
|
||||
"success": "Файлы JSON паспяхова пераўтвораны ў PDF! Пачалося спампоўванне ZIP.",
|
||||
"zipError": "Памылка стварэння ZIP: {{message}}",
|
||||
"workerError": "Памылка апрацоўшчыка: {{message}}",
|
||||
"getStarted": "Выберыце файлы JSON, каб пачаць"
|
||||
}
|
||||
},
|
||||
"pdfToJpg": {
|
||||
@@ -399,7 +518,8 @@
|
||||
"noFile": "Няма файла",
|
||||
"noFileExplanation": "Спачатку запампуйце файл PDF.",
|
||||
"conversionSuccess": "PDF паспяхова канвертаваны ў TIFFs!",
|
||||
"conversionError": "Не ўдалося канвертаваць PDF у TIFF. Файл можа быць пашкоджаны."
|
||||
"conversionError": "Не ўдалося канвертаваць PDF у TIFF. Файл можа быць пашкоджаны.",
|
||||
"conversionOutOfMemory": "У браўзеры скончылася памяць падчас канвертавання. Паспрабуйце знізіць DPI або адключыць параметр шматстаронкавага TIFF, каб канвертаваць старонкі па адной."
|
||||
}
|
||||
},
|
||||
"pdfToCbz": {
|
||||
@@ -439,19 +559,19 @@
|
||||
"pdfToJson": {
|
||||
"name": "PDF у JSON",
|
||||
"subtitle": "Канвертаваць файлы PDF у фармат JSON.",
|
||||
"convertButton": "Конвертувати у JSON",
|
||||
"convertButton": "Пераўтварыць у JSON",
|
||||
"status": {
|
||||
"selectAtLeastOne": "Виберіть принаймні 1 PDF-файл",
|
||||
"selectedReady": "Вибрано {{count}} файл(ів). Готово до конвертації!",
|
||||
"checkingEncrypted": "Перевірка зашифрованих PDF...",
|
||||
"readingFiles": "Читання файлів (головний потік)...",
|
||||
"converting": "Конвертація PDF у JSON...",
|
||||
"readError": "Помилка читання файлів: {{message}}",
|
||||
"creatingZip": "Створення ZIP-файлу...",
|
||||
"success": "PDF успішно конвертовано у JSON! Завантаження ZIP розпочато.",
|
||||
"zipError": "Помилка створення ZIP: {{message}}",
|
||||
"workerError": "Помилка Worker: {{message}}",
|
||||
"getStarted": "Виберіть PDF-файли, щоб почати"
|
||||
"selectAtLeastOne": "Выберыце хаця б 1 файл PDF",
|
||||
"selectedReady": "Выбрана файлаў: {{count}}. Гатова да канвертавання!",
|
||||
"checkingEncrypted": "Праверка зашыфраваных PDF...",
|
||||
"readingFiles": "Чытанне файлаў (галоўны паток)...",
|
||||
"converting": "Пераўтварэнне PDF у JSON...",
|
||||
"readError": "Памылка чытання файлаў: {{message}}",
|
||||
"creatingZip": "Стварэнне ZIP-файла...",
|
||||
"success": "PDF паспяхова пераўтвораны ў JSON! Пачалося спампоўванне ZIP.",
|
||||
"zipError": "Памылка стварэння ZIP: {{message}}",
|
||||
"workerError": "Памылка апрацоўшчыка: {{message}}",
|
||||
"getStarted": "Выберыце файлы PDF, каб пачаць"
|
||||
}
|
||||
},
|
||||
"ocrPdf": {
|
||||
@@ -461,58 +581,103 @@
|
||||
"searchLanguagesPlaceholder": "Пошук моў...",
|
||||
"selectedLabel": "Выбрана:",
|
||||
"none": "Няма",
|
||||
"advancedSettingsSummary": "Додаткові налаштування (рекомендовано для покращення точності)",
|
||||
"advancedSettingsSummary": "Пашыраныя налады (рэкамендуецца для павышэння дакладнасці)",
|
||||
"resolutionLabel": "Раздзяляльная здольнасць",
|
||||
"resolutionStandard": "Стандартная (192 DPI)",
|
||||
"resolutionHigh": "Высокая (288 DPI)",
|
||||
"resolutionUltra": "Ультра (384 DPI)",
|
||||
"binarizeLabel": "Бінаризувати зображення (покращити контраст для чистих сканів)",
|
||||
"embedFullFontsLabel": "Вбудувати повні шрифти (більший файл, краща сумісність)",
|
||||
"whitelistPresetLabel": "Передустановка білого списку символів",
|
||||
"whitelistNone": "Немає (усі символи)",
|
||||
"whitelistAlphanumeric": "Літери та цифри + базова пунктуація",
|
||||
"whitelistNumbersCurrency": "Числа + Символи валют",
|
||||
"whitelistLettersOnly": "Лише літери (A-Z, a-z)",
|
||||
"whitelistNumbersOnly": "Лише числа (0-9)",
|
||||
"whitelistInvoice": "Рахунок/Чек (числа, $, ., -, /)",
|
||||
"whitelistForms": "Форми (літери та цифри + загальні символи)",
|
||||
"whitelistCustom": "Користувацький...",
|
||||
"whitelistHelp": "Будуть розпізнані лише ці символи. Залиште порожнім для всіх символів.",
|
||||
"whitelistInputLabel": "Білий список символів (необов'язково)",
|
||||
"binarizeLabel": "Бінарызаваць відарыс (павысіць кантраст для чыстых сканаў)",
|
||||
"embedFullFontsLabel": "Убудаваць поўныя шрыфты (большы файл, лепшая сумяшчальнасць)",
|
||||
"whitelistPresetLabel": "Перадвызначаная налада спісу дазволеных сімвалаў",
|
||||
"whitelistNone": "Няма (усе сімвалы)",
|
||||
"whitelistAlphanumeric": "Лічбавыя і літарныя сімвалы + асноўныя знакі прыпынку",
|
||||
"whitelistNumbersCurrency": "Лічбы + сімвалы валют",
|
||||
"whitelistLettersOnly": "Толькі літары (A-Z, a-z)",
|
||||
"whitelistNumbersOnly": "Толькі лічбы (0-9)",
|
||||
"whitelistInvoice": "Рахунак/квітанцыя (лічбы, $, ., -, /)",
|
||||
"whitelistForms": "Формы (літары і лічбы + агульнаўжывальныя сімвалы)",
|
||||
"whitelistCustom": "Уласны…",
|
||||
"whitelistHelp": "Распазнаюцца толькі гэтыя сімвалы. Пакіньце поле пустым, каб дазволіць усе сімвалы.",
|
||||
"whitelistInputLabel": "Спіс дазволеных сімвалаў (неабавязкова)",
|
||||
"whitelistInputPlaceholder": "напр., abcdefghijklmnopqrstuvwxyz0123456789$.,",
|
||||
"startButton": "Запусціць OCR",
|
||||
"progressInitializing": "Ініцыялізацыя...",
|
||||
"resultsTitle": "OCR завершаны",
|
||||
"resultsDescription": "Ваш PDF з пошуком готовий. Ви також можете скопіювати або завантажити витягнутий текст нижче.",
|
||||
"copyToClipboard": "Капіяваць у буфер абмену",
|
||||
"resultsDescription": "PDF з магчымасцю пошуку гатовы. Ніжэй можна скапіраваць або спампаваць выняты тэкст.",
|
||||
"copyToClipboard": "Капіраваць у буфер абмену",
|
||||
"downloadTxt": "Спампаваць як .txt",
|
||||
"downloadSearchablePdf": "Спампаваць пошукавы PDF",
|
||||
"statusPrefix": "Статус: {{status}}",
|
||||
"availabilityInvalidConfig": "Цей реліз не надає дійсних мов OCR. Перебудуйте його з VITE_TESSERACT_AVAILABLE_LANGUAGES, встановленим на дійсні коди Tesseract.",
|
||||
"availabilityBundles": "Цей реліз містить OCR для: {{languages}}.",
|
||||
"availabilityInvalidConfig": "Гэта разгортванне не прапануе ніводнай дапушчальнай мовы OCR. Перазбярыце яго, задаўшы VITE_TESSERACT_AVAILABLE_LANGUAGES дапушчальнымі кодамі Tesseract.",
|
||||
"availabilityBundles": "Гэта разгортванне ўключае OCR для: {{languages}}.",
|
||||
"noLanguagesAvailable": "У гэтым выпуску няма даступных моў OCR.",
|
||||
"noLanguagesTitle": "Мовы не выбраны",
|
||||
"noLanguagesMessage": "Выберыце прынамсі адну мову для OCR.",
|
||||
"noFileTitle": "Няма файла",
|
||||
"noFileMessage": "Спачатку загрузіце PDF-файл.",
|
||||
"noFileMessage": "Спачатку запампуйце PDF-файл.",
|
||||
"languageUnavailableTitle": "Мова OCR недаступная",
|
||||
"ocrErrorTitle": "Памылка OCR",
|
||||
"ocrErrorMessage": "Падчас працэсу OCR адбылася памылка. Магчыма, працаўнік не загрузіўся. Паспрабуйце яшчэ раз.",
|
||||
"ocrErrorMessage": "Падчас працэсу OCR адбылася памылка. Магчыма, апрацоўшчык не загрузіўся. Паспрабуйце яшчэ раз.",
|
||||
"howItWorksTitle": "Як гэта працуе:",
|
||||
"extractTextLabel": "Витягти текст:",
|
||||
"extractTextDescription": "Використовує Tesseract OCR для розпізнавання тексту на сканованих зображеннях або PDF.",
|
||||
"searchableOutputLabel": "Вивід з можливістю пошуку:",
|
||||
"searchableOutputDescription": "Створює новий PDF з невидимим текстовим шаром, роблячи ваш документ повністю придатним для пошуку, зберігаючи оригінальний вигляд.",
|
||||
"characterFilteringLabel": "Фільтрація символів:",
|
||||
"characterFilteringDescription": "Використовуйте білі списки для фільтрації небажаних символів і покращення точності для конкретних типів документів (рахунки, форми тощо).",
|
||||
"multiLanguageSupportLabel": "Багатомовна підтримка:",
|
||||
"multiLanguageSupportDescription": "Виберіть кілька мов для документів зі змішаним мовним вмістом."
|
||||
"extractTextLabel": "Выняць тэкст:",
|
||||
"extractTextDescription": "Выкарыстоўвае OCR Tesseract для распазнавання тэксту са сканаваных відарысаў або PDF.",
|
||||
"searchableOutputLabel": "Вынік з магчымасцю пошуку:",
|
||||
"searchableOutputDescription": "Стварае новы PDF з нябачным тэкставым слоем, робячы дакумент цалкам даступным для пошуку і захоўваючы яго першапачатковы выгляд.",
|
||||
"characterFilteringLabel": "Фільтраванне сімвалаў:",
|
||||
"characterFilteringDescription": "Дазваляе адфільтроўваць непатрэбныя сімвалы праз спісы дазволеных і павышае дакладнасць для пэўных тыпаў дакументаў (рахункаў, формаў і інш.).",
|
||||
"multiLanguageSupportLabel": "Падтрымка некалькіх моў:",
|
||||
"multiLanguageSupportDescription": "Дазваляе выбраць некалькі моў для дакументаў з тэкстам на розных мовах."
|
||||
},
|
||||
"alternateMerge": {
|
||||
"name": "Чаргаваць і змяшаць старонкі",
|
||||
"subtitle": "Аб'яднаць PDF, чаргуючы старонкі з асобных PDF. Закладкі захоўваюцца.",
|
||||
"retainPageLabels": "Захоўваць арыгінальныя пазнакі старонак з кожнага файла",
|
||||
"retainPageLabelsHint": "Выключана (па змаўчанні): аб’яднаны PDF выкарыстоўвае натуральную нумарацыю 1–N. Уключана: арыгінальныя пазнакі старонак кожнага файла захоўваюцца (могуць узнікнуць паўторы)."
|
||||
"retainPageLabelsHint": "Выключана (прадвызначана): аб'яднаны PDF выкарыстоўвае натуральную нумарацыю 1–N. Уключана: арыгінальныя пазнакі старонак кожнага файла захоўваюцца (могуць узнікнуць паўторы)."
|
||||
},
|
||||
"duplexCollate": {
|
||||
"name": "Сартаванне двухбаковага сканавання",
|
||||
"subtitle": "Упарадкаваць PDF, адсканаваны двума блокамі (спачатку ўсе пярэднія бакі, потым усе адваротныя), у правільны парадак пярэдні/адваротны.",
|
||||
"totalPagesLabel": "Усяго старонак:",
|
||||
"splitAfterPageLabel": "Падзяліць пасля старонкі",
|
||||
"splitAfterPagePlaceholder": "напр. 50",
|
||||
"backBlockOrderLabel": "Парадак блока адваротных бакоў",
|
||||
"backBlockReverseOption": "Перавярнуць блок адваротных бакоў (звычайна пры перавернутым стосе)",
|
||||
"backBlockKeepOption": "Пакінуць блок адваротных бакоў без змен",
|
||||
"autoSplitButton": "Вызначыць падзел аўтаматычна (палова)",
|
||||
"exportGroupedLabel": "Экспартаваць файлы групамі паводле даўжыні зыходнага дакумента",
|
||||
"pagesPerDocumentLabel": "Старонак у зыходным дакуменце",
|
||||
"groupedHelp": "Калі ўключана, вынікам будзе ZIP-архіў з асобным PDF для кожнага згрупаванага дакумента.",
|
||||
"collateButton": "Сабраць PDF",
|
||||
"invalidFileTitle": "Памылковы файл",
|
||||
"invalidFileMessage": "Выберыце файл PDF.",
|
||||
"loadingPdf": "Загрузка PDF...",
|
||||
"loadErrorMessage": "Не ўдалося загрузіць файл PDF.",
|
||||
"fileMeta": "{{size}} - {{count}} стар.",
|
||||
"oddPageWarning": "Няцотная колькасць старонак ({{count}}). Двухбаковае сканаванне павінна мець цотную колькасць старонак; магчыма, старонкі не хапае або ёсць лішняя.",
|
||||
"previewSummary": "Блок пярэдніх бакоў: {{frontCount}} стар., блок адваротных: {{backCount}} стар. Вынік: {{outputCount}} стар. у парадку пярэдні/адваротны.",
|
||||
"previewMismatchWarning": "Даўжыня блокаў пярэдніх і адваротных бакоў адрозніваецца ({{frontCount}} пярэдніх супраць {{backCount}} адваротных). Лішнія старонкі ({{extraCount}}) з даўжэйшага блока будуць дададзены без пары ў канец.",
|
||||
"missingFileTitle": "Файл не выбраны",
|
||||
"missingFileMessage": "Перад апрацоўкай запампуйце PDF прынамсі з 2 старонкамі.",
|
||||
"invalidSplitTitle": "Памылковы пункт падзелу",
|
||||
"invalidSplitMessage": "Пункт падзелу павінен быць паміж старонкай 1 і старонкай {{maxSplit}}.",
|
||||
"unevenConfirmTitle": "Няроўныя блокі",
|
||||
"unevenConfirmMessage": "У блоку пярэдніх бакоў {{frontCount}} стар., у блоку адваротных — {{backCount}} стар.\nЗвычайна гэта азначае, што старонка адсканавана двойчы або яе не хапае.\n\nСтаронкі без пары ({{extraCount}}) будуць дададзены ў канец.\n\nУсё роўна працягнуць?",
|
||||
"invalidGroupTitle": "Памылковы памер групы",
|
||||
"invalidGroupMessage": "Увядзіце правільную колькасць старонак у зыходным дакуменце.",
|
||||
"collatingLoader": "Збор двухбаковага сканавання...",
|
||||
"successMessage": "Сабраны PDF паспяхова створаны.",
|
||||
"successGroupedMessage": "Збор завершаны. Створана файлаў: {{fileCount}}.",
|
||||
"processErrorMessage": "Не ўдалося сабраць PDF.",
|
||||
"howItWorksStep1Title": "Запампуйце скан",
|
||||
"howItWorksStep1": "Перацягніце адзін PDF, у якім спачатку ідуць усе пярэднія бакі, а потым усе адваротныя.",
|
||||
"howItWorksStep2Title": "Задайце пункт падзелу",
|
||||
"howItWorksStep2": "Пазначце, дзе заканчваецца блок пярэдніх бакоў, і выберыце, ці трэба перавярнуць блок адваротных.",
|
||||
"howItWorksStep3Title": "Сабярыце і спампуйце",
|
||||
"howItWorksStep3": "Вы атрымаеце адзін PDF з чаргаваннем старонак або ZIP-архіў з асобным файлам для кожнага зыходнага дакумента.",
|
||||
"faqOddPagesQuestion": "Што рабіць, калі ў скане няцотная колькасць старонак?",
|
||||
"faqOddPagesAnswer": "Двухбаковае сканаванне павінна мець цотную колькасць старонак. Калі гэта не так, старонка, хутчэй за ўсё, адсканавана двойчы або прапушчана. Інструмент папярэдзіць вас перад апрацоўкай, а старонкі без пары будуць дададзены ў канец, каб нічога не згубілася.",
|
||||
"faqBackOrderQuestion": "Навошта пакідаць блок адваротных бакоў без змен?",
|
||||
"faqBackOrderAnswer": "Гэта залежыць ад таго, як стос падавалі на другім праходзе. Калі перавярнуць увесь стос, адваротныя бакі ідуць у адваротным парадку — гэта прадвызначаны варыянт. Калі сканер выдаў іх у тым самым парадку, што і пярэднія бакі, выберыце пакінуць блок без змен."
|
||||
},
|
||||
"addAttachments": {
|
||||
"name": "Дадаць далучэнні",
|
||||
@@ -704,14 +869,14 @@
|
||||
"btnSettings": "Налады",
|
||||
"btnExportPdf": "Экспартаваць PDF",
|
||||
"settingsTitle": "Налады Markdown",
|
||||
"settingsPreset": "Набор налад",
|
||||
"settingsPreset": "Перадвызначаная налада",
|
||||
"presetDefault": "Прадвызначаны (як GFM)",
|
||||
"presetCommonmark": "CommonMark (строгі)",
|
||||
"presetZero": "Мінімальны (без функцый)",
|
||||
"settingsOptions": "Параметры Markdown",
|
||||
"optAllowHtml": "Дазволіць HTML-тэгі",
|
||||
"optBreaks": "Пераўтвараць пераносы радкоў у <br>",
|
||||
"optLinkify": "Аўтаматычна пераўтвараць URL-адрасы ў спасылкі",
|
||||
"optLinkify": "Аўтаматычна канвертаваць URL-адрасы ў спасылкі",
|
||||
"optTypographer": "Тыпограф (разумныя двукоссі і інш.)"
|
||||
},
|
||||
"pdfBooklet": {
|
||||
@@ -840,9 +1005,8 @@
|
||||
"name": "PDF у тэкст",
|
||||
"subtitle": "Выняць тэкст з файлаў PDF і захаваць як тэкставы файл (.txt). Падтрымлівае некалькі файлаў.",
|
||||
"noteLabel": "Заўвага:",
|
||||
"noteText": "Цей інструмент працює ТІЛЬКИ з PDF, створеними цифровим способом. Для сканованих документів або PDF на основі зображень використовуйте натомість наш інструмент OCR PDF.",
|
||||
"convertButton": "Выняць тэкст",
|
||||
"note": "Гэты інструмент працуе ТОЛЬКІ з PDF, створанымі лічбавым спосабам. Для сканіраваных дакументаў або PDF на аснове відарысаў выкарыстоўвайце інструмент OCR PDF."
|
||||
"noteText": "Гэты інструмент працуе ТОЛЬКІ з PDF, створанымі лічбавым спосабам. Для сканаваных дакументаў або PDF на аснове відарысаў выкарыстоўвайце наш інструмент OCR PDF.",
|
||||
"convertButton": "Выняць тэкст"
|
||||
},
|
||||
"digitalSignPdf": {
|
||||
"name": "Лічбавы подпіс PDF",
|
||||
@@ -851,7 +1015,7 @@
|
||||
"certificateSection": "Сертыфікат",
|
||||
"uploadCert": "Запампаваць сертыфікат (.pfx, .p12, .pem)",
|
||||
"certPassword": "Пароль сертыфіката",
|
||||
"privateKeyPassword": "Пароль приватного ключа",
|
||||
"privateKeyPassword": "Пароль прыватнага ключа",
|
||||
"certPasswordPlaceholder": "Увядзіце пароль сертыфіката",
|
||||
"certInfo": "Інфармацыя пра сертыфікат",
|
||||
"certSubject": "Суб'ект",
|
||||
@@ -864,71 +1028,71 @@
|
||||
"locationPlaceholder": "напрыклад, Мінск, Беларусь",
|
||||
"contactInfo": "Кантактная інфармацыя",
|
||||
"contactPlaceholder": "напрыклад, [email protected]",
|
||||
"visibleSignature": "Видимий підпис",
|
||||
"visibleSignatureDescription": "Якщо увімкнено, у PDF з'являється видиме поле підпису. Можна завантажити зображення/логотип або додати текст. Якщо не вказано жодного, ім'я підписанта автоматично відображається з сертифіката.",
|
||||
"signatureImage": "Зображення/логотип підпису (необов'язково)",
|
||||
"uploadSignatureImage": "Завантажити зображення (PNG, JPG, WebP)",
|
||||
"signaturePreviewAlt": "Попередній перегляд підпису",
|
||||
"remove": "Видалити",
|
||||
"page": "Сторінка",
|
||||
"firstPage": "Перша сторінка",
|
||||
"lastPage": "Остання сторінка",
|
||||
"allPages": "Усі сторінки",
|
||||
"customPage": "Користувацька сторінка #",
|
||||
"pageNumber": "Сторінка #",
|
||||
"xPosition": "Позиція X (зліва)",
|
||||
"yPosition": "Позиція Y (зверху)",
|
||||
"width": "Ширина",
|
||||
"height": "Висота",
|
||||
"addTextOverlay": "Додати текстове накладання",
|
||||
"text": "Текст",
|
||||
"textPlaceholder": "напр., Підписано в цифровій формі Іваном Петренком",
|
||||
"textColor": "Колір тексту",
|
||||
"fontSize": "Розмір шрифту",
|
||||
"invalidImageTitle": "Недійсне зображення",
|
||||
"invalidImageMessage": "Виберіть зображення PNG, JPG або WebP.",
|
||||
"invalidFileTitle": "Недійсний файл",
|
||||
"invalidFileMessage": "Виберіть PDF-файл.",
|
||||
"invalidCertificateTitle": "Недійсний сертифікат",
|
||||
"invalidCertificateMessage": "Виберіть файл сертифіката .pfx, .p12 або .pem.",
|
||||
"certificateLoaded": "Сертифікат завантажено",
|
||||
"certificateUnlocked": "Сертифікат розблоковано",
|
||||
"failedParsePem": "Не вдалося проаналізувати файл PEM",
|
||||
"enterPasswordToUnlock": "Введіть пароль для розблокування",
|
||||
"invalidPasswordOrCertificate": "Невірний пароль або сертифікат",
|
||||
"incorrectPassword": "Невірний пароль",
|
||||
"failedParseCertificate": "Не вдалося проаналізувати сертифікат",
|
||||
"missingDataTitle": "Відсутні дані",
|
||||
"missingDataMessage": "Завантажте і PDF, і дійсний сертифікат.",
|
||||
"applyingSignature": "Застосування цифрового підпису...",
|
||||
"signingFailedTitle": "Помилка підписання",
|
||||
"chainFetchFailed": "Не вдалося отримати ланцюг сертифікатів. Можливо, проблема з мережею або проксі сертифікатів недоступний. Перевірте підключення до Інтернету та повторіть спробу. Якщо проблема не зникає, зверніться до підтримки.",
|
||||
"failedToSignPdf": "Не вдалося підписати PDF: {{message}}",
|
||||
"defaultSignatureText": "Підписано в цифровій формі {{signer}}\n{{date}}",
|
||||
"pageCount": "{{count}} стор.",
|
||||
"howToStep1Title": "Завантажити PDF",
|
||||
"howToStep1Text": "Виберіть PDF-документ, який хочете підписати",
|
||||
"howToStep2Title": "Завантажити сертифікат",
|
||||
"howToStep2Text": "Надайте файл сертифіката .pfx або .p12 і пароль",
|
||||
"howToStep3Title": "Підписати та завантажити",
|
||||
"howToStep3Text": "Застосуйте цифровий підпис і завантажте підписаний PDF",
|
||||
"relatedEncryptDesc": "Захистити PDF паролем",
|
||||
"relatedDecryptDesc": "Видалити пароль PDF",
|
||||
"relatedFlattenDesc": "Зробити анотації постійними",
|
||||
"relatedSanitizeDesc": "Видалити приховані дані",
|
||||
"relatedPermissionsDesc": "Встановити дозволи PDF",
|
||||
"faqWhatIsQuestion": "Що таке цифровий підпис?",
|
||||
"faqWhatIsAnswer": "Цифровий підпис — це криптографічний механізм, який перевіряє автентичність і цілісність документа. На відміну від намальованого підпису, він використовує криптографію відкритого ключа (сертифікати X.509) для підтвердження особи підписанта.",
|
||||
"faqFormatsQuestion": "Які формати сертифікатів підтримуються?",
|
||||
"faqFormatsAnswer": "Ми підтримуємо сертифікати у форматі PKCS#12 (.pfx, .p12), які містять і ваш сертифікат, і приватний ключ в одному зашифрованому файлі. Зазвичай вони видаються центрами сертифікації.",
|
||||
"faqPrivateKeyQuestion": "Чи безпечний мій приватний ключ?",
|
||||
"faqPrivateKeyAnswer": "Так! Уся обробка відбувається повністю у вашому браузері. Ваш сертифікат, приватний ключ і файли PDF ніколи не залишають ваш пристрій і не завантажуються на жоден сервер.",
|
||||
"faqValidReadersQuestion": "Чи буде підпис дійсним у переглядачах PDF?",
|
||||
"faqValidReadersAnswer": "Так, інструмент створює стандартні відокремлені підписи PKCS#7, які розпізнаються всіма основними програмами для перегляду PDF. Для повної перевірки використовуйте сертифікат від довіреного центру сертифікації.",
|
||||
"visibleSignature": "Бачны подпіс",
|
||||
"visibleSignatureDescription": "Калі ўключана, у PDF з'яўляецца бачнае поле подпісу. Можна запампаваць відарыс або лагатып альбо дадаць тэкст. Калі нічога не дадзена, аўтаматычна будзе паказана імя падпісанта з сертыфіката.",
|
||||
"signatureImage": "Відарыс або лагатып подпісу (неабавязкова)",
|
||||
"uploadSignatureImage": "Запампаваць відарыс (PNG, JPG, WebP)",
|
||||
"signaturePreviewAlt": "Папярэдні прагляд подпісу",
|
||||
"remove": "Выдаліць",
|
||||
"page": "Старонка",
|
||||
"firstPage": "Першая старонка",
|
||||
"lastPage": "Апошняя старонка",
|
||||
"allPages": "Усе старонкі",
|
||||
"customPage": "Уласная старонка №",
|
||||
"pageNumber": "Старонка №",
|
||||
"xPosition": "Пазіцыя X (злева)",
|
||||
"yPosition": "Пазіцыя Y (зверху)",
|
||||
"width": "Шырыня",
|
||||
"height": "Вышыня",
|
||||
"addTextOverlay": "Дадаць накладзены тэкст",
|
||||
"text": "Тэкст",
|
||||
"textPlaceholder": "Напрыклад, падпісана лічбавым подпісам Джона Доу",
|
||||
"textColor": "Колер тэксту",
|
||||
"fontSize": "Памер шрыфта",
|
||||
"invalidImageTitle": "Памылковы відарыс",
|
||||
"invalidImageMessage": "Выберыце відарыс PNG, JPG або WebP.",
|
||||
"invalidFileTitle": "Памылковы файл",
|
||||
"invalidFileMessage": "Выберыце файл PDF.",
|
||||
"invalidCertificateTitle": "Памылковы сертыфікат",
|
||||
"invalidCertificateMessage": "Выберыце файл сертыфіката .pfx, .p12 або .pem.",
|
||||
"certificateLoaded": "Сертыфікат загружаны",
|
||||
"certificateUnlocked": "Сертыфікат разблакаваны",
|
||||
"failedParsePem": "Не ўдалося разабраць файл PEM",
|
||||
"enterPasswordToUnlock": "Увядзіце пароль, каб разблакаваць",
|
||||
"invalidPasswordOrCertificate": "Памылковы пароль або сертыфікат",
|
||||
"incorrectPassword": "Няправільны пароль",
|
||||
"failedParseCertificate": "Не ўдалося разабраць сертыфікат",
|
||||
"missingDataTitle": "Адсутнасць даных",
|
||||
"missingDataMessage": "Дадайце PDF і сапраўдны сертыфікат.",
|
||||
"applyingSignature": "Накладанне лічбавага подпісу...",
|
||||
"signingFailedTitle": "Не ўдалося падпісаць",
|
||||
"chainFetchFailed": "Не ўдалося атрымаць ланцужок сертыфікатаў. Гэта можа быць выклікана праблемамі з сеткай або недаступнасцю проксі-сервера сертыфікатаў. Праверце падлучэнне да інтэрнэту і паспрабуйце яшчэ раз. Калі праблема захоўваецца, звярніцеся ў службу падтрымкі.",
|
||||
"failedToSignPdf": "Не ўдалося падпісаць PDF: {{message}}",
|
||||
"defaultSignatureText": "Падпісана лічбавым подпісам {{signer}}\n{{date}}",
|
||||
"pageCount": "{{count}} стар.",
|
||||
"howToStep1Title": "Запампуйце PDF",
|
||||
"howToStep1Text": "Выберыце дакумент PDF, які хочаце падпісаць",
|
||||
"howToStep2Title": "Запампуйце сертыфікат",
|
||||
"howToStep2Text": "Дадайце файл сертыфіката .pfx або .p12 і пароль",
|
||||
"howToStep3Title": "Падпішыце і спампуйце",
|
||||
"howToStep3Text": "Накладзіце лічбавы подпіс і спампуйце падпісаны PDF",
|
||||
"relatedEncryptDesc": "Абараніць PDF паролем",
|
||||
"relatedDecryptDesc": "Выдаліць пароль PDF",
|
||||
"relatedFlattenDesc": "Зрабіць анатацыі сталымі",
|
||||
"relatedSanitizeDesc": "Выдаліць схаваныя даныя",
|
||||
"relatedPermissionsDesc": "Задаць дазволы PDF",
|
||||
"faqWhatIsQuestion": "Што такое лічбавы подпіс?",
|
||||
"faqWhatIsAnswer": "Лічбавы подпіс — гэта крыптаграфічны механізм, які правярае сапраўднасць і цэласнасць дакумента. У адрозненне ад намаляванага подпісу, ён выкарыстоўвае крыптаграфію з адкрытым ключом (сертыфікаты X.509), каб пацвердзіць асобу падпісанта.",
|
||||
"faqFormatsQuestion": "Якія фарматы сертыфікатаў падтрымліваюцца?",
|
||||
"faqFormatsAnswer": "Падтрымліваюцца сертыфікаты фармату PKCS#12 (.pfx, .p12), якія змяшчаюць сертыфікат і закрыты ключ карыстальніка ў адным зашыфраваным файле. Такія сертыфікаты звычайна выдаюцца цэнтрамі сертыфікацыі.",
|
||||
"faqPrivateKeyQuestion": "Ці ў бяспецы мой закрыты ключ?",
|
||||
"faqPrivateKeyAnswer": "Так! Уся апрацоўка адбываецца непасрэдна ў браўзеры. Сертыфікат, закрыты ключ і файлы PDF ніколі не пакідаюць прыладу карыстальніка і не запампоўваюцца на сервер.",
|
||||
"faqValidReadersQuestion": "Ці будзе подпіс сапраўдным у праглядальніках PDF?",
|
||||
"faqValidReadersAnswer": "Так, інструмент стварае стандартныя адасобленыя подпісы PKCS#7, якія распазнаюцца ўсімі асноўнымі праглядальнікамі PDF. Для поўнай праверкі выкарыстоўвайце сертыфікат ад даверанага цэнтра сертыфікацыі.",
|
||||
"applySignature": "Ужыць лічбавы подпіс",
|
||||
"successMessage": "PDF паспяхова падпісаны! Подпіс можна праверыць у любым PDF-чытальніку.",
|
||||
"internetRequiredTitle": "Потрібне інтернет-з'єднання",
|
||||
"internetRequiredDescription": "Для перевірки підпису може знадобитися отримати інформацію про ланцюг сертифікатів із сервера видавця сертифіката."
|
||||
"internetRequiredTitle": "Патрабуецца падлучэнне да інтэрнэту",
|
||||
"internetRequiredDescription": "Для падпісання можа спатрэбіцца атрымаць звесткі пра ланцужок сертыфікатаў з сервера выдаўца сертыфіката, каб праверыць подпіс."
|
||||
},
|
||||
"validateSignaturePdf": {
|
||||
"name": "Праверыць подпіс PDF",
|
||||
@@ -952,11 +1116,11 @@
|
||||
},
|
||||
"fontToOutline": {
|
||||
"name": "Шрыфт у контуры",
|
||||
"subtitle": "Ператварыць усе шрыфты ў вектарныя контуры для стабільнага адлюстравання на ўсіх прыладах."
|
||||
"subtitle": "Канвертаваць усе шрыфты ў вектарныя контуры для стабільнага адлюстравання на ўсіх прыладах."
|
||||
},
|
||||
"deskewPdf": {
|
||||
"name": "Выпрастаць PDF",
|
||||
"subtitle": "Аўтаматычна выраўняць нахіленыя адсканіраваныя старонкі з дапамогай OpenCV."
|
||||
"subtitle": "Аўтаматычна выраўняць нахіленыя адсканаваныя старонкі з дапамогай OpenCV."
|
||||
},
|
||||
"pdfToWord": {
|
||||
"name": "PDF у Word",
|
||||
@@ -1006,22 +1170,22 @@
|
||||
"cancel": "Скасаваць",
|
||||
"loadTemplate": "Загрузіць шаблон",
|
||||
"noTemplates": "Пакуль няма захаваных шаблонаў.",
|
||||
"ok": "OK",
|
||||
"ok": "ОК",
|
||||
"workflowCompleted": "Рабочы працэс завершаны",
|
||||
"errorDuringExecution": "Памылка падчас выканання",
|
||||
"addNodeError": "Дадайце хаця б адзін вузел для запуску рабочага працэсу.",
|
||||
"needInputOutput": "Для працы рабочага працэсу патрэбен хаця б адзін вузел уводу і адзін вузел вываду.",
|
||||
"needInputOutput": "Для працы рабочага працэсу патрэбны хаця б адзін вузел уводу і адзін вузел вываду.",
|
||||
"enterName": "Увядзіце назву.",
|
||||
"templateExists": "Шаблон з такой назвай ужо існуе.",
|
||||
"templateSaved": "Шаблон \"{{name}}\" захаваны.",
|
||||
"templateLoaded": "Шаблон \"{{name}}\" загружаны.",
|
||||
"templateSaved": "Шаблон «{{name}}» захаваны.",
|
||||
"templateLoaded": "Шаблон «{{name}}» загружаны.",
|
||||
"failedLoadTemplate": "Не ўдалося загрузіць шаблон.",
|
||||
"noSettings": "Няма налад для гэтага вузла.",
|
||||
"advancedSettings": "Пашыраныя налады",
|
||||
"specialNodes": {
|
||||
"pdfInput": {
|
||||
"name": "Увод PDF",
|
||||
"description": "Загрузіце адзін ці некалькі файлаў PDF"
|
||||
"description": "Запампуйце адзін ці некалькі файлаў PDF"
|
||||
},
|
||||
"download": {
|
||||
"name": "Спампаваць",
|
||||
@@ -1034,96 +1198,96 @@
|
||||
"expectedPdfInput": "Чакаўся ўвод PDF",
|
||||
"failedToRenderPage": "Не атрымалася адлюстраваць старонку {{page}}",
|
||||
"failedToGetCanvasContext": "Не атрымалася атрымаць кантэкст палатна для старонкі {{page}}",
|
||||
"failedToRenderPageToImage": "Не атрымалася адлюстраваць старонку {{page}} як выяву",
|
||||
"failedToRenderPageToImage": "Не атрымалася адлюстраваць старонку {{page}} як відарыс",
|
||||
"noPagesProcessed": "Ніводнай старонкі не апрацавана",
|
||||
"cpdfNotConfigured": "CoherentPDF не настроены. Настройце яго ў пашыраных параметрах.",
|
||||
"workerError": "Памылка воркера: {{message}}",
|
||||
"alternateMergeWorkerError": "Памылка воркера паслядоўнага зліцця: {{message}}",
|
||||
"noPdfFilesUploaded": "У вузел PDF Input не загружаны PDF-файлы",
|
||||
"failedToLoadFile": "Не атрымалася загрузіць \"{{file}}\" — файл можа быць пашкоджаны",
|
||||
"noImagesUploaded": "У вузел Image Input не загружаны выявы",
|
||||
"noWordDocsUploaded": "У вузел Word Input не загружаны дакументы",
|
||||
"noExcelUploaded": "У вузел Excel Input не загружаны табліцы",
|
||||
"noPowerPointUploaded": "У вузел PowerPoint Input не загружаны прэзентацыі",
|
||||
"noCbzUploaded": "У вузел CBZ Input не загружаны архівы коміксаў",
|
||||
"noEmailUploaded": "У вузел Email Input не загружаны файлы пошты",
|
||||
"noEpubUploaded": "У вузел EPUB Input не загружаны файлы EPUB",
|
||||
"noFb2Uploaded": "У вузел FB2 Input не загружаны файлы FB2",
|
||||
"noJsonUploaded": "У вузел JSON Input не загружаны файлы JSON",
|
||||
"noMarkdownUploaded": "У вузел Markdown Input не загружаны файлы Markdown",
|
||||
"noMobiUploaded": "У вузел MOBI Input не загружаны файлы MOBI",
|
||||
"noOdgUploaded": "У вузел ODG Input не загружаны файлы ODG",
|
||||
"noPagesUploaded": "У вузел Pages Input не загружаны файлы Pages",
|
||||
"noPubUploaded": "У вузел PUB Input не загружаны файлы PUB",
|
||||
"noSvgUploaded": "У вузел SVG Input не загружаны файлы SVG",
|
||||
"noTextUploaded": "У вузел Text Input не загружаны тэкставыя файлы",
|
||||
"noVsdUploaded": "У вузел VSD Input не загружаны файлы Visio",
|
||||
"noWpdUploaded": "У вузел WPD Input не загружаны файлы WPD",
|
||||
"noWpsUploaded": "У вузел WPS Input не загружаны файлы WPS",
|
||||
"noXmlUploaded": "У вузел XML Input не загружаны файлы XML",
|
||||
"noXpsUploaded": "У вузел XPS Input не загружаны файлы XPS",
|
||||
"cpdfNotConfigured": "CoherentPDF не сканфігураваны. Сканфігуруйце яго ў пашыраных наладах.",
|
||||
"workerError": "Памылка апрацоўшчыка: {{message}}",
|
||||
"alternateMergeWorkerError": "Памылка апрацоўшчыка паслядоўнага зліцця: {{message}}",
|
||||
"noPdfFilesUploaded": "У вузел «Увод PDF» не запампаваны PDF-файлы",
|
||||
"failedToLoadFile": "Не атрымалася загрузіць «{{file}}» — файл можа быць пашкоджаны",
|
||||
"noImagesUploaded": "У вузел уводу відарысаў не запампаваны відарысы",
|
||||
"noWordDocsUploaded": "У вузел уводу Word не запампаваны дакументы",
|
||||
"noExcelUploaded": "У вузел уводу Excel не запампаваны табліцы",
|
||||
"noPowerPointUploaded": "У вузел уводу PowerPoint не запампаваны прэзентацыі",
|
||||
"noCbzUploaded": "У вузел уводу CBZ не запампаваны архівы коміксаў",
|
||||
"noEmailUploaded": "У вузел уводу Email не запампаваны файлы пошты",
|
||||
"noEpubUploaded": "У вузел уводу EPUB не запампаваны файлы EPUB",
|
||||
"noFb2Uploaded": "У вузел уводу FB2 не запампаваны файлы FB2",
|
||||
"noJsonUploaded": "У вузел уводу JSON не запампаваны файлы JSON",
|
||||
"noMarkdownUploaded": "У вузел уводу Markdown не запампаваны файлы Markdown",
|
||||
"noMobiUploaded": "У вузел уводу MOBI не запампаваны файлы MOBI",
|
||||
"noOdgUploaded": "У вузел уводу ODG не запампаваны файлы ODG",
|
||||
"noPagesUploaded": "У вузел уводу Pages не запампаваны файлы Pages",
|
||||
"noPubUploaded": "У вузел уводу PUB не запампаваны файлы PUB",
|
||||
"noSvgUploaded": "У вузел уводу SVG не запампаваны файлы SVG",
|
||||
"noTextUploaded": "У вузел уводу тэксту не запампаваны тэкставыя файлы",
|
||||
"noVsdUploaded": "У вузел уводу VSD не запампаваны файлы Visio",
|
||||
"noWpdUploaded": "У вузел уводу WPD не запампаваны файлы WPD",
|
||||
"noWpsUploaded": "У вузел уводу WPS не запампаваны файлы WPS",
|
||||
"noXmlUploaded": "У вузел уводу XML не запампаваны файлы XML",
|
||||
"noXpsUploaded": "У вузел уводу XPS не запампаваны файлы XPS",
|
||||
"alternateMergeNeedsTwo": "Паслядоўнаму зліццю патрэбна як мінімум два PDF, падключаныя да ўваходу",
|
||||
"cropMarginsExceed": "Палі абрэзкі перавышаюць памеры старонкі. Паменшыце значэнні.",
|
||||
"digitalSignNoCertificate": "У вузле лічбавага подпісу не загружаны сертыфікат",
|
||||
"encryptUserPasswordRequired": "Для шыфравання патрэбны карыстальніцкі пароль",
|
||||
"extractImagesNoneFound": "У падключаных PDF не знойдзена выяў",
|
||||
"invertColorsFailedReadImage": "Не атрымалася прачытаць даныя выявы",
|
||||
"extractImagesNoneFound": "У падключаных PDF не знойдзена відарысаў",
|
||||
"invertColorsFailedReadImage": "Не атрымалася прачытаць даныя відарыса",
|
||||
"overlayRequiresPdf": "Вузел накладання патрабуе ўвод PDF для накладання.",
|
||||
"pdfToCsvNoTables": "У PDF не знойдзена табліц",
|
||||
"pdfToXlsxNoTables": "У {{file}} не знойдзена табліц",
|
||||
"posterizeFailedTileCanvas": "Не атрымалася атрымаць кантэкст палатна пліткі",
|
||||
"redactNoText": "Рэдагаванне: не вызначаны тэкст для рэдагавання",
|
||||
"redactNoText": "Зацямненне: не вызначаны тэкст для зацямнення",
|
||||
"removeBlankPagesAllBlank": "Усе старонкі пустыя",
|
||||
"svgFailedToConvert": "Не атрымалася канвертаваць SVG",
|
||||
"svgFailedToLoad": "Не атрымалася загрузіць SVG",
|
||||
"timestampFailed": "Не атрымалася паставіць метку часу праз TSA {{tsa}}: {{message}}",
|
||||
"noOutputNodes": "Не знойдзена вузлоў вываду. Дадайце вузел Download, каб завяршыць ваш працоўны працэс.",
|
||||
"circularDependency": "У працоўным працэсе выяўлена кругавая залежнасць. Выдаліце ўсе цыклы паміж вузламі.",
|
||||
"encryptOrdering": "Вузел шыфравання падае даныя ў \"{{target}}\", што можа збой на зашыфраваных даных. Перамясціце шыфраванне непасрэдна перад вузлом вываду.",
|
||||
"invalidWorkflowFile": "Несапраўдны файл працоўнага працэсу: адсутнічае масіў вузлоў або злучэнняў.",
|
||||
"storageQuotaExceeded": "Не атрымалася захаваць працоўны працэс: перавышана квота сховішча. Паспрабуйце выдаліць старыя шаблоны.",
|
||||
"failedToImport": "Не атрымалася імпартаваць працоўны працэс: {{message}}"
|
||||
"timestampFailed": "Не атрымалася паставіць пазнаку часу праз TSA {{tsa}}: {{message}}",
|
||||
"noOutputNodes": "Не знойдзена вузлоў вываду. Дадайце вузел «Спампаваць», каб завяршыць ваш рабочы працэс.",
|
||||
"circularDependency": "У рабочым працэсе выяўлена кругавая залежнасць. Выдаліце ўсе цыклы паміж вузламі.",
|
||||
"encryptOrdering": "Вузел шыфравання падае даныя ў «{{target}}», што можа даць збой на зашыфраваных даных. Перамясціце шыфраванне непасрэдна перад вузлом вываду.",
|
||||
"invalidWorkflowFile": "Памылковы файл рабочага працэсу: адсутнічае масіў вузлоў або злучэнняў.",
|
||||
"storageQuotaExceeded": "Не атрымалася захаваць рабочы працэс: перавышана квота сховішча. Паспрабуйце выдаліць старыя шаблоны.",
|
||||
"failedToImport": "Не атрымалася імпартаваць рабочы працэс: {{message}}"
|
||||
}
|
||||
},
|
||||
"wasmSettings": {
|
||||
"title": "Налады пашыраных функцый",
|
||||
"description": "Налаштуйте зовнішні модулі обробки для увімкнення розширених функцій PDF. Ці модулі необов'язкові і ліцензуються окремо.",
|
||||
"description": "Сканфігуруйце знешнія модулі апрацоўкі для ўключэння пашыраных магчымасцей PDF. Гэтыя модулі неабавязковыя і ліцэнзуюцца асобна.",
|
||||
"status": {
|
||||
"testing": "Перевірка...",
|
||||
"customOverride": "Користувацьке перевизначення",
|
||||
"preConfigured": "Попередньо налаштовано",
|
||||
"notConfigured": "Не налаштовано"
|
||||
"testing": "Праверка…",
|
||||
"customOverride": "Уласная замена",
|
||||
"preConfigured": "Папярэдне сканфігураваны",
|
||||
"notConfigured": "Не сканфігураваны"
|
||||
},
|
||||
"preconfiguredTitle": "Попередньо налаштовано і готово до використання.",
|
||||
"preconfiguredDescription": "Розширені модулі обробки автоматично завантажуються з CDN. Ви можете перевизначити URL нижче, якщо потрібно використовувати власне джерело (наприклад, для air-gapped або самостійно розміщених розгортань).",
|
||||
"usingDefault": "Використовується за замовчуванням: {{url}}",
|
||||
"pymupdfSubtitle": "Рушій обробки документів",
|
||||
"pymupdfFeatures": "Вмикає: PDF у текст, Markdown, SVG, DOCX, Excel • Витягти зображення/таблиці • Конвертацію формату",
|
||||
"preconfiguredTitle": "Папярэдне сканфігураваны і гатовы да выкарыстання",
|
||||
"preconfiguredDescription": "Пашыраныя модулі апрацоўкі аўтаматычна загружаюцца з CDN. Вы можаце перавызначыць URL ніжэй, калі вам трэба выкарыстоўваць уласную крыніцу (напрыклад, для разгортванняў у ізаляваным асяроддзі або з уласным хостынгам).",
|
||||
"usingDefault": "Выкарыстоўваецца прадвызначанае значэнне: {{url}}",
|
||||
"pymupdfSubtitle": "Рухавік апрацоўкі дакументаў",
|
||||
"pymupdfFeatures": "Уключае: канвертаванне PDF у тэкст, Markdown, SVG, DOCX, Excel • выманне відарысаў і табліц • канвертаванне фарматаў",
|
||||
"testButton": "Праверыць",
|
||||
"recommendedLabel": "Рекомендовано:",
|
||||
"copyTitle": "Копіювати в буфер обміну",
|
||||
"ghostscriptSubtitle": "Рушій конвертації PDF/A",
|
||||
"ghostscriptFeatures": "Вмикає: Конвертацію PDF/A-1b, PDF/A-2b, PDF/A-3b • Шрифт у контур",
|
||||
"cpdfSubtitle": "Рушій закладок і метаданих",
|
||||
"cpdfFeatures": "Вмикає: Розділити за закладками • Редагувати закладки • Метадані PDF",
|
||||
"recommendedLabel": "Рэкамендавана:",
|
||||
"copyTitle": "Капіраваць у буфер абмену",
|
||||
"ghostscriptSubtitle": "Рухавік канвертавання PDF/A",
|
||||
"ghostscriptFeatures": "Уключае: канвертаванне ў PDF/A-1b, PDF/A-2b, PDF/A-3b • канвертаванне шрыфтоў у контуры",
|
||||
"cpdfSubtitle": "Рухавік закладак і метаданых",
|
||||
"cpdfFeatures": "Уключае: раздзяленне паводле закладак • рэдагаванне закладак • метаданыя PDF",
|
||||
"saveConfiguration": "Захаваць канфігурацыю",
|
||||
"savingConfiguration": "Збереження конфігурації...",
|
||||
"savingConfiguration": "Захаванне канфігурацыі...",
|
||||
"savedTitle": "Захавана",
|
||||
"savedMessage": "Канфігурацыя паспяхова захавана!",
|
||||
"errorTitle": "Памылка",
|
||||
"failedSave": "Не вдалося зберегти конфігурацію: {{message}}",
|
||||
"emptyUrlTitle": "Порожній URL",
|
||||
"emptyUrlMessage": "Введіть URL для перевірки.",
|
||||
"testSuccessTitle": "Успіх",
|
||||
"connectionSuccess": "Підключення до {{package}} успішне!",
|
||||
"connectionFailedTitle": "Збій підключення",
|
||||
"connectionFailedMessage": "Не вдалося підключитися до URL.",
|
||||
"failedSave": "Не ўдалося захаваць канфігурацыю: {{message}}",
|
||||
"emptyUrlTitle": "Пусты URL",
|
||||
"emptyUrlMessage": "Увядзіце URL для праверкі.",
|
||||
"testSuccessTitle": "Поспех",
|
||||
"connectionSuccess": "Злучэнне з {{package}} паспяховае!",
|
||||
"connectionFailedTitle": "Не ўдалося ўсталяваць злучэнне",
|
||||
"connectionFailedMessage": "Не ўдалося злучыцца з URL.",
|
||||
"resetDefaults": "Скінуць да стандартных",
|
||||
"resetTitle": "Скід",
|
||||
"resetWithDefaults": "Користувацькі перевизначення очищено. Активні попередньо налаштовані значення за замовчуванням.",
|
||||
"resetNoDefaults": "Усі конфігурації та кешовані модулі очищено.",
|
||||
"licenseTitle": "Повідомлення про ліцензію:",
|
||||
"licenseDescription": "Зовнішні модулі (PyMuPDF, Ghostscript, CoherentPDF) ліцензовані під AGPL-3.0 або подібними copyleft-ліцензіями. Налаштовуючи та використовуючи ці модулі, ви погоджуєтеся з їхніми відповідними умовами ліцензії. BentoPDF сумісний з будь-якою реалізацією Ghostscript WASM і PyMuPDF WASM, що дотримується очікуваного інтерфейсу."
|
||||
"resetWithDefaults": "Уласныя перавызначэнні ачышчаныя. Актываваныя прадвызначаныя значэнні канфігурацыі.",
|
||||
"resetNoDefaults": "Усе канфігурацыі і кэшаваныя модулі ачышчаныя.",
|
||||
"licenseTitle": "Звесткі пра ліцэнзію:",
|
||||
"licenseDescription": "Знешнія модулі (PyMuPDF, Ghostscript, CoherentPDF) распаўсюджваюцца паводле AGPL-3.0 або падобных ліцэнзій з копілефтам. Канфігуруючы і выкарыстоўваючы гэтыя модулі, вы згаджаецеся з умовамі адпаведных ліцэнзій. BentoPDF сумяшчальны з любой рэалізацыяй Ghostscript WASM і PyMuPDF WASM, якая адпавядае чаканаму інтэрфейсу."
|
||||
},
|
||||
"pdfOverlay": {
|
||||
"name": "Накладанне PDF",
|
||||
@@ -1136,7 +1300,7 @@
|
||||
"overlayOption": "Накладанне (зверху старонак)",
|
||||
"underlayOption": "Падкладанне (за старонкамі)",
|
||||
"pageRangeLabel": "Прымяніць да старонак (неабавязкова)",
|
||||
"pageRangeHint": "Выкарыстоўвайце \"z\" для апошняй старонкі. Пакіньце пустым, каб прымяніць да ўсіх старонак.",
|
||||
"pageRangeHint": "Выкарыстоўвайце «z» для апошняй старонкі. Пакіньце пустым, каб прымяніць да ўсіх старонак.",
|
||||
"repeatLabel": "Паўтараць накладанне/падкладанне, калі базавы PDF даўжэйшы",
|
||||
"processButton": "Прымяніць накладанне / падкладанне",
|
||||
"howItWorksUploadTitle": "Запампуйце два PDF",
|
||||
@@ -1148,8 +1312,16 @@
|
||||
"faqDifferenceQuestion": "У чым розніца паміж накладаннем і падкладаннем?",
|
||||
"faqDifferenceAnswer": "Накладанне размяшчае старонкі зверху базавага PDF (як вадзяны знак). Падкладанне размяшчае старонкі за базавым PDF (як фірмовы бланк або фон).",
|
||||
"faqSinglePageQuestion": "Ці магу я выкарыстоўваць аднастаронкавы PDF як накладанне для ўсіх старонак?",
|
||||
"faqSinglePageAnswer": "Так! Уключыце опцыю \"Паўтараць\" і старонкі накладання будуць паўтарацца на ўсіх старонках базавага файла. Аднастаронкавы вадзяны знак будзе прымяняцца да кожнай старонкі.",
|
||||
"faqSinglePageAnswer": "Так! Уключыце опцыю «Паўтараць» і старонкі накладання будуць паўтарацца на ўсіх старонках базавага файла. Аднастаронкавы вадзяны знак будзе прымяняцца да кожнай старонкі.",
|
||||
"faqPrivacyQuestion": "Ці з'яўляюцца мае файлы прыватнымі і бяспечнымі?",
|
||||
"faqPrivacyAnswer": "Безумоўна! Уся апрацоўка адбываецца ў вашым браўзеры. Вашы файлы ніколі не пакідаюць вашу прыладу, забяспечваючы поўную прыватнасць."
|
||||
},
|
||||
"unlockPdf": {
|
||||
"name": "Расшыфраваць PDF",
|
||||
"subtitle": "Разблакіраваць PDF, выдаліўшы пароль."
|
||||
},
|
||||
"protectPdf": {
|
||||
"name": "Зашыфраваць PDF",
|
||||
"subtitle": "Заблакіраваць PDF, дадаўшы пароль."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@
|
||||
},
|
||||
"analytics": {
|
||||
"question": "Bruger I cookies eller analyseværktøjer?",
|
||||
"answer": "Vi bruger kun Simple Analytics til anonyme besøgsdata. Ingen personlige oplysninger indsamles."
|
||||
"answer": "Nej. BentoPDF sporer dig slet ikke. Vi bruger hverken cookies, analyseværktøjer eller sporingsscripts – heller ikke på den live hjemmeside bentopdf.com. Vi ved aldrig, hvem du er, eller hvad du bruger værktøjerne til."
|
||||
}
|
||||
},
|
||||
"testimonials": {
|
||||
@@ -239,7 +239,9 @@
|
||||
"legal": "Juridisk",
|
||||
"termsAndConditions": "Terms and Conditions",
|
||||
"privacyPolicy": "Privacy Policy",
|
||||
"followUs": "Følg os"
|
||||
"followUs": "Følg os",
|
||||
"privacyShort": "Privatliv",
|
||||
"termsShort": "Vilkår"
|
||||
},
|
||||
"merge": {
|
||||
"title": "Flet PDF'er",
|
||||
@@ -286,7 +288,8 @@
|
||||
"noCompromises": "Ingen kompromiser."
|
||||
},
|
||||
"mission": {
|
||||
"title": "Vores mission",
|
||||
"title": "Vores",
|
||||
"titleDim": "mission",
|
||||
"description": "At give den mest komplette PDF-værktøjskasse uden betaling og med fuldt fokus på privatliv."
|
||||
},
|
||||
"philosophy": {
|
||||
@@ -350,9 +353,12 @@
|
||||
"download": "Download:",
|
||||
"downloadSelected": "Download valgte",
|
||||
"exportPdf": "Eksportér PDF",
|
||||
"uploadPdfFiles": "Vælg PDF-filer",
|
||||
"dragAndDrop": "Træk og slip PDF-filer her, eller klik for at vælge",
|
||||
"uploadPdfFiles": "Vælg PDF- eller billedfiler",
|
||||
"dragAndDrop": "Træk og slip PDF- eller billedfiler her, eller klik for at vælge",
|
||||
"selectFiles": "Vælg filer",
|
||||
"dropToAdd": "Slip PDF- eller billedfiler for at tilføje",
|
||||
"convertingImages": "Konverterer billeder til PDF...",
|
||||
"failedToConvertImages": "Kunne ikke konvertere billeder til PDF.",
|
||||
"renderingPages": "Renderer sider...",
|
||||
"actions": {
|
||||
"duplicatePage": "Duplikér denne side",
|
||||
|
||||
@@ -55,6 +55,124 @@
|
||||
"name": "PDF-editor",
|
||||
"subtitle": "Annotér, fremhæv, redigér, kommentér, tilføj former/billeder, søg og vis PDF’er."
|
||||
},
|
||||
"editPdfText": {
|
||||
"name": "Redigér PDF-tekst",
|
||||
"subtitle": "Klik på et hvilket som helst afsnit, og redigér det direkte med live-ombrydning, skrifttyper og formatering.",
|
||||
"saved": "PDF blev gemt! ({{size}} KB)",
|
||||
"failedToLoad": "PDF-teksteditoren kunne ikke indlæses.",
|
||||
"loadingFonts": "Indlæser skrifttyper...",
|
||||
"fontsUnavailable": "En skrifttype, der er nødvendig for nogle tegn, kunne ikke downloades. Tjek din forbindelse, og prøv igen, ellers vises disse tegn muligvis ikke korrekt i den gemte PDF.",
|
||||
"howToUpload": "Upload PDF",
|
||||
"howToClick": "Klik på et afsnit",
|
||||
"howToRestyle": "Giv alt ny stil",
|
||||
"relatedPdfEditor": "Kommentér og markér PDF-filer",
|
||||
"relatedSignPdf": "Tegn, skriv eller upload en underskrift",
|
||||
"relatedWatermark": "Stempl tekst eller billeder",
|
||||
"relatedStamps": "Placer stempler på sider",
|
||||
"relatedCompress": "Reducer filstørrelsen",
|
||||
"relatedOrganizeName": "Organiser PDF",
|
||||
"relatedOrganize": "Omarranger og administrer sider",
|
||||
"open": "Åbn",
|
||||
"export": "Eksportér",
|
||||
"filterAll": "Alle",
|
||||
"filterText": "Tekst",
|
||||
"filterImages": "Billeder",
|
||||
"filterShapes": "Former",
|
||||
"addText": "Tilføj tekst",
|
||||
"langAuto": "Automatisk",
|
||||
"change": "Skift",
|
||||
"ignore": "Ignorér",
|
||||
"next": "Næste",
|
||||
"replace": "Erstat",
|
||||
"replaceAll": "Erstat alle",
|
||||
"emptyState": "Åbn en PDF for at redigere dens tekst, billeder og former.",
|
||||
"choosePdf": "Vælg en PDF…",
|
||||
"font": "Skrifttype",
|
||||
"systemFonts": "Systemskrifttyper",
|
||||
"color": "Farve",
|
||||
"alignment": "Justering",
|
||||
"style": "Stil",
|
||||
"lists": "Lister",
|
||||
"outline": "Kontur",
|
||||
"spacing": "Afstand",
|
||||
"direction": "Retning",
|
||||
"dirAuto": "Automatisk",
|
||||
"pathStroke": "Stikontur",
|
||||
"tipBackToUpload": "Tilbage til upload",
|
||||
"tipOpenAnotherPdf": "Åbn en anden PDF",
|
||||
"tipExportS": "Eksportér (⌘S)",
|
||||
"tipUndoZ": "Fortryd (⌘Z)",
|
||||
"tipRedoZ": "Gentag (⇧⌘Z)",
|
||||
"tipFileDetails": "Filoplysninger",
|
||||
"tipEditExistingContent": "Rediger eksisterende indhold",
|
||||
"tipWhatTheEditToolTouchesNarrowTheScopeOnBus": "Hvad Rediger-værktøjet berører — begræns omfanget på travle sider",
|
||||
"tipClickThePageToAddATextBox": "Klik på siden for at tilføje et tekstfelt",
|
||||
"tipSpellCheckLanguage": "Sprog for stavekontrol",
|
||||
"tipFindAndReplace": "Søg og erstat",
|
||||
"tipAddAnImage": "Tilføj et billede",
|
||||
"tipCopyThisPageSTextInReadingOrder": "Kopiér sidens tekst i læserækkefølge",
|
||||
"tipCheckTheSpellingOfThisPage": "Kontrollér stavningen på denne side",
|
||||
"tipShowOrHideTheFormatPanel": "Vis eller skjul formatpanelet",
|
||||
"phReplaceWith": "Erstat med",
|
||||
"tipAddToYourDictionary": "Føj til ordbogen",
|
||||
"tipClose": "Luk",
|
||||
"phFind": "Søg",
|
||||
"tipPreviousMatch": "Forrige match",
|
||||
"tipNextMatch": "Næste match",
|
||||
"tipRotateLeft90": "Rotér 90° mod venstre",
|
||||
"tipRotateRight90": "Rotér 90° mod højre",
|
||||
"tipFlipHorizontal": "Vend vandret",
|
||||
"tipFlipVertical": "Vend lodret",
|
||||
"tipReplaceThisImageKeepingItsPlacement": "Erstat dette billede, og behold placeringen",
|
||||
"tipAlternateTextForAccessibilityTaggedPdfs": "Alternativ tekst til tilgængelighed (taggede PDF-filer)",
|
||||
"tipBringToFront": "Placer forrest",
|
||||
"tipSendToBack": "Placer bagerst",
|
||||
"tipDuplicate": "Dublér",
|
||||
"tipDelete": "Slet",
|
||||
"tipAlignLeftEdges": "Justér venstre kanter",
|
||||
"tipAlignHorizontalCenters": "Centrér vandret",
|
||||
"tipAlignRightEdges": "Justér højre kanter",
|
||||
"tipAlignTops": "Justér øverste kanter",
|
||||
"tipAlignVerticalCenters": "Centrér lodret",
|
||||
"tipAlignBottoms": "Justér nederste kanter",
|
||||
"tipDistributeHorizontally": "Fordel vandret",
|
||||
"tipDistributeVertically": "Fordel lodret",
|
||||
"tipFontSize": "Skriftstørrelse",
|
||||
"tipListFontsInstalledOnThisDeviceChromium": "Vis skrifttyper installeret på denne enhed (Chromium)",
|
||||
"tipCustomTextColor": "Tilpasset tekstfarve",
|
||||
"tipAlignLeft": "Justér til venstre",
|
||||
"tipAlignCenter": "Centrér",
|
||||
"tipAlignRight": "Justér til højre",
|
||||
"tipJustify": "Lige margener",
|
||||
"tipBold": "Fed",
|
||||
"tipItalic": "Kursiv",
|
||||
"tipUnderline": "Understreget",
|
||||
"tipStrikethrough": "Gennemstreget",
|
||||
"tipSuperscript": "Hævet skrift",
|
||||
"tipSubscript": "Sænket skrift",
|
||||
"tipToggleBulletedItem": "Slå punktopstilling til/fra",
|
||||
"tipToggleNumberedItem": "Slå nummereret punkt til/fra",
|
||||
"tipNumberedListMarkerStyle": "Markeringstype for nummererede lister",
|
||||
"tipDecreaseListIndentTab": "Formindsk indrykning (⇧Tab)",
|
||||
"tipIncreaseListIndentTab": "Forøg indrykning (Tab)",
|
||||
"tipTextOutlineColor": "Farve på tekstkontur",
|
||||
"tipOutlineWidth0None": "Konturbredde (0 = ingen)",
|
||||
"tipFromContent": "Fra indhold",
|
||||
"tipLeftToRight": "Venstre mod højre",
|
||||
"tipRightToLeft": "Højre mod venstre",
|
||||
"tipStrokeColor": "Stregfarve",
|
||||
"tipStrokeWidth": "Stregbredde",
|
||||
"tipZoomPresets": "Zoomforudindstillinger",
|
||||
"tipZoomOut": "Zoom ud",
|
||||
"tipZoomIn": "Zoom ind",
|
||||
"tipFitPage": "Tilpas side",
|
||||
"tipPreviousPage": "Forrige side",
|
||||
"tipTypeAPageNumberAndPressEnter": "Skriv et sidetal, og tryk på Enter",
|
||||
"tipNextPage": "Næste side",
|
||||
"tipDocumentProperties": "Dokumentegenskaber",
|
||||
"tipHideBar": "Skjul bjælke",
|
||||
"tipShowBar": "Vis bjælke"
|
||||
},
|
||||
"jpgToPdf": {
|
||||
"name": "JPG til PDF",
|
||||
"subtitle": "Opret en PDF fra JPG, JPEG og JPEG2000 (JP2/JPX) billeder."
|
||||
@@ -514,6 +632,51 @@
|
||||
"retainPageLabels": "Behold de oprindelige sideetiketter fra hver fil",
|
||||
"retainPageLabelsHint": "Fra (standard): den sammenflettede PDF bruger naturlig sidenummerering 1–N. Til: hver fils oprindelige sideetiketter bevares (kan give dublerede etiketter)."
|
||||
},
|
||||
"duplexCollate": {
|
||||
"name": "Sortér dupleks-scanning",
|
||||
"subtitle": "Omarrangér en PDF, der er scannet i to blokke (først alle forsider, derefter alle bagsider), til den rigtige for-/bagsiderækkefølge.",
|
||||
"totalPagesLabel": "Sider i alt:",
|
||||
"splitAfterPageLabel": "Opdel efter side",
|
||||
"splitAfterPagePlaceholder": "f.eks. 50",
|
||||
"backBlockOrderLabel": "Rækkefølge for bagsideblok",
|
||||
"backBlockReverseOption": "Vend bagsideblokken om (almindeligt ved vendt stak)",
|
||||
"backBlockKeepOption": "Behold bagsideblokken, som den er",
|
||||
"autoSplitButton": "Find opdeling automatisk (halvdelen)",
|
||||
"exportGroupedLabel": "Eksportér grupperede filer efter det oprindelige dokuments længde",
|
||||
"pagesPerDocumentLabel": "Sider pr. oprindeligt dokument",
|
||||
"groupedHelp": "Når det er slået til, er resultatet en ZIP-fil med én PDF pr. grupperet dokument.",
|
||||
"collateButton": "Sortér PDF",
|
||||
"invalidFileTitle": "Ugyldig fil",
|
||||
"invalidFileMessage": "Vælg en PDF-fil.",
|
||||
"loadingPdf": "Indlæser PDF...",
|
||||
"loadErrorMessage": "PDF-filen kunne ikke indlæses.",
|
||||
"fileMeta": "{{size}} - {{count}} sider",
|
||||
"oddPageWarning": "Ulige sidetal ({{count}}). En dupleks-scanning bør have et lige antal sider; der mangler måske en side, eller der er en for meget.",
|
||||
"previewSummary": "Forsideblok: {{frontCount}} side(r), bagsideblok: {{backCount}} side(r). Resultat: {{outputCount}} side(r) i for-/bagsiderækkefølge.",
|
||||
"previewMismatchWarning": "For- og bagsideblokkene har forskellig længde ({{frontCount}} forsider mod {{backCount}} bagsider). De {{extraCount}} overskydende side(r) i den længste blok tilføjes uden makker til sidst.",
|
||||
"missingFileTitle": "Manglende fil",
|
||||
"missingFileMessage": "Upload en PDF med mindst 2 sider, før du behandler den.",
|
||||
"invalidSplitTitle": "Ugyldigt opdelingspunkt",
|
||||
"invalidSplitMessage": "Opdelingspunktet skal ligge mellem side 1 og side {{maxSplit}}.",
|
||||
"unevenConfirmTitle": "Ulige blokke",
|
||||
"unevenConfirmMessage": "Forsideblokken har {{frontCount}} side(r), og bagsideblokken har {{backCount}} side(r).\nDet betyder som regel, at en side er scannet to gange eller mangler.\n\nDe {{extraCount}} side(r) uden makker tilføjes til sidst.\n\nVil du fortsætte alligevel?",
|
||||
"invalidGroupTitle": "Ugyldig gruppestørrelse",
|
||||
"invalidGroupMessage": "Angiv et gyldigt antal sider pr. oprindeligt dokument.",
|
||||
"collatingLoader": "Sorterer dupleks-scanning...",
|
||||
"successMessage": "Den sorterede PDF blev oprettet.",
|
||||
"successGroupedMessage": "Sortering fuldført. Der blev oprettet {{fileCount}} grupperede filer.",
|
||||
"processErrorMessage": "PDF'en kunne ikke sorteres.",
|
||||
"howItWorksStep1Title": "Upload scanningen",
|
||||
"howItWorksStep1": "Slip den ene PDF, der indeholder alle forsider efterfulgt af alle bagsider.",
|
||||
"howItWorksStep2Title": "Angiv opdelingspunktet",
|
||||
"howItWorksStep2": "Markér, hvor forsideblokken slutter, og vælg, om bagsideblokken skal vendes om.",
|
||||
"howItWorksStep3Title": "Sortér og download",
|
||||
"howItWorksStep3": "Du får én PDF med sammenflettede sider eller en ZIP-fil med en separat fil pr. oprindeligt dokument.",
|
||||
"faqOddPagesQuestion": "Hvad hvis min scanning har et ulige antal sider?",
|
||||
"faqOddPagesAnswer": "En dupleks-scanning bør have et lige antal sider. Hvis den ikke har det, er en side sandsynligvis scannet to gange eller sprunget over. Værktøjet advarer dig før behandlingen, og sider uden makker tilføjes til sidst, så intet går tabt.",
|
||||
"faqBackOrderQuestion": "Hvorfor skulle jeg beholde bagsideblokken, som den er?",
|
||||
"faqBackOrderAnswer": "Det afhænger af, hvordan stakken blev lagt i ved anden kørsel. Hvis hele stakken vendes, kommer bagsiderne i omvendt rækkefølge, hvilket er standardindstillingen. Hvis din scanner leverede dem i samme rækkefølge som forsiderne, så vælg at beholde blokken, som den er."
|
||||
},
|
||||
"addAttachments": {
|
||||
"name": "Tilføj vedhæftninger",
|
||||
"subtitle": "Indlejr en eller flere filer i din PDF."
|
||||
@@ -1151,5 +1314,13 @@
|
||||
"faqSinglePageAnswer": "Ja! Aktivér \"Gentag\"-indstillingen, og dine overlejringssider vil gentage sig på alle basis-sider. Et enkeltsidigt vandmærke vil blive anvendt på hver side.",
|
||||
"faqPrivacyQuestion": "Er mine filer private og sikre?",
|
||||
"faqPrivacyAnswer": "Absolut! Al behandling sker i din browser. Dine filer forlader aldrig din enhed, hvilket sikrer fuldstændig privatliv."
|
||||
},
|
||||
"unlockPdf": {
|
||||
"name": "Dekryptér PDF",
|
||||
"subtitle": "Fjern adgangskodebeskyttelse."
|
||||
},
|
||||
"protectPdf": {
|
||||
"name": "Kryptér PDF",
|
||||
"subtitle": "Lås din PDF med en adgangskode."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@
|
||||
},
|
||||
"analytics": {
|
||||
"question": "Verwendet ihr Cookies oder Analysen, um mich zu verfolgen?",
|
||||
"answer": "Uns liegt deine Privatsphäre am Herzen. BentoPDF verfolgt keine persönlichen Informationen. Wir verwenden Simple Analytics ausschließlich, um anonyme Besucherzahlen zu sehen. Das bedeutet, wir können wissen, wie viele Benutzer unsere Seite besuchen, aber wir wissen nie, wer sie sind. Simple Analytics ist vollständig DSGVO-konform und respektiert deine Privatsphäre."
|
||||
"answer": "Nein. BentoPDF verfolgt Sie in keiner Weise. Wir verwenden keine Cookies, keine Analysetools und keine Tracking-Skripte – auch nicht auf der Live-Website bentopdf.com. Wir wissen nie, wer Sie sind oder was Sie mit den Tools tun."
|
||||
}
|
||||
},
|
||||
"testimonials": {
|
||||
@@ -239,7 +239,9 @@
|
||||
"legal": "Rechtliches",
|
||||
"termsAndConditions": "Nutzungsbedingungen",
|
||||
"privacyPolicy": "Datenschutzrichtlinie",
|
||||
"followUs": "Folge uns"
|
||||
"followUs": "Folge uns",
|
||||
"privacyShort": "Datenschutz",
|
||||
"termsShort": "AGB"
|
||||
},
|
||||
"merge": {
|
||||
"title": "PDFs zusammenführen",
|
||||
@@ -286,7 +288,8 @@
|
||||
"noCompromises": "Ohne Kompromisse."
|
||||
},
|
||||
"mission": {
|
||||
"title": "Unsere Mission",
|
||||
"title": "Unsere",
|
||||
"titleDim": "Mission",
|
||||
"description": "Die umfassendste PDF-Toolbox bereitzustellen, die deine Privatsphäre respektiert und niemals Geld kostet. Wir glauben, dass wichtige Dokumentenwerkzeuge für jede*n, überall und ohne Barrieren zugänglich sein sollten."
|
||||
},
|
||||
"philosophy": {
|
||||
@@ -350,9 +353,12 @@
|
||||
"download": "Download:",
|
||||
"downloadSelected": "Auswahl herunterladen",
|
||||
"exportPdf": "PDF exportieren",
|
||||
"uploadPdfFiles": "PDF-Dateien auswählen",
|
||||
"dragAndDrop": "PDF-Dateien hierhin ziehen oder klicken zum Auswählen",
|
||||
"uploadPdfFiles": "PDF- oder Bilddateien auswählen",
|
||||
"dragAndDrop": "PDF- oder Bilddateien hierhin ziehen oder klicken zum Auswählen",
|
||||
"selectFiles": "Dateien auswählen",
|
||||
"dropToAdd": "PDF- oder Bilddateien zum Hinzufügen ablegen",
|
||||
"convertingImages": "Bilder werden in PDF konvertiert...",
|
||||
"failedToConvertImages": "Bilder konnten nicht in PDF konvertiert werden.",
|
||||
"renderingPages": "Seiten werden gerendert...",
|
||||
"actions": {
|
||||
"duplicatePage": "Diese Seite duplizieren",
|
||||
|
||||
@@ -55,6 +55,124 @@
|
||||
"name": "PDF-Editor",
|
||||
"subtitle": "Annotieren, hervorheben, schwärzen, kommentieren, Formen/Bilder hinzufügen, suchen und PDFs anzeigen."
|
||||
},
|
||||
"editPdfText": {
|
||||
"name": "PDF-Text bearbeiten",
|
||||
"subtitle": "Auf einen beliebigen Absatz klicken und ihn direkt bearbeiten – mit Live-Umbruch, Schriftarten und Formatierung.",
|
||||
"saved": "PDF erfolgreich gespeichert! ({{size}} KB)",
|
||||
"failedToLoad": "Der PDF-Texteditor konnte nicht geladen werden.",
|
||||
"loadingFonts": "Schriftarten werden geladen...",
|
||||
"fontsUnavailable": "Eine für einige Zeichen benötigte Schriftart konnte nicht heruntergeladen werden. Prüfen Sie Ihre Verbindung und versuchen Sie es erneut, sonst werden diese Zeichen im gespeicherten PDF möglicherweise nicht korrekt angezeigt.",
|
||||
"howToUpload": "PDF hochladen",
|
||||
"howToClick": "Absatz anklicken",
|
||||
"howToRestyle": "Alles umgestalten",
|
||||
"relatedPdfEditor": "PDFs kommentieren und markieren",
|
||||
"relatedSignPdf": "Unterschrift zeichnen, tippen oder hochladen",
|
||||
"relatedWatermark": "Text oder Bilder aufbringen",
|
||||
"relatedStamps": "Stempel auf Seiten platzieren",
|
||||
"relatedCompress": "Dateigröße verringern",
|
||||
"relatedOrganizeName": "PDF organisieren",
|
||||
"relatedOrganize": "Seiten neu anordnen und verwalten",
|
||||
"open": "Öffnen",
|
||||
"export": "Exportieren",
|
||||
"filterAll": "Alle",
|
||||
"filterText": "Text",
|
||||
"filterImages": "Bilder",
|
||||
"filterShapes": "Formen",
|
||||
"addText": "Text hinzufügen",
|
||||
"langAuto": "Automatisch",
|
||||
"change": "Ändern",
|
||||
"ignore": "Ignorieren",
|
||||
"next": "Weiter",
|
||||
"replace": "Ersetzen",
|
||||
"replaceAll": "Alle ersetzen",
|
||||
"emptyState": "Öffnen Sie eine PDF, um Text, Bilder und Formen zu bearbeiten.",
|
||||
"choosePdf": "PDF auswählen …",
|
||||
"font": "Schriftart",
|
||||
"systemFonts": "Systemschriften",
|
||||
"color": "Farbe",
|
||||
"alignment": "Ausrichtung",
|
||||
"style": "Stil",
|
||||
"lists": "Listen",
|
||||
"outline": "Kontur",
|
||||
"spacing": "Abstand",
|
||||
"direction": "Richtung",
|
||||
"dirAuto": "Automatisch",
|
||||
"pathStroke": "Pfadkontur",
|
||||
"tipBackToUpload": "Zurück zum Upload",
|
||||
"tipOpenAnotherPdf": "Weitere PDF öffnen",
|
||||
"tipExportS": "Exportieren (⌘S)",
|
||||
"tipUndoZ": "Rückgängig (⌘Z)",
|
||||
"tipRedoZ": "Wiederherstellen (⇧⌘Z)",
|
||||
"tipFileDetails": "Dateidetails",
|
||||
"tipEditExistingContent": "Vorhandene Inhalte bearbeiten",
|
||||
"tipWhatTheEditToolTouchesNarrowTheScopeOnBus": "Was das Bearbeiten-Werkzeug erfasst – Umfang auf vollen Seiten eingrenzen",
|
||||
"tipClickThePageToAddATextBox": "Klicken Sie auf die Seite, um ein Textfeld hinzuzufügen",
|
||||
"tipSpellCheckLanguage": "Sprache der Rechtschreibprüfung",
|
||||
"tipFindAndReplace": "Suchen & ersetzen",
|
||||
"tipAddAnImage": "Bild hinzufügen",
|
||||
"tipCopyThisPageSTextInReadingOrder": "Text dieser Seite in Lesereihenfolge kopieren",
|
||||
"tipCheckTheSpellingOfThisPage": "Rechtschreibung dieser Seite prüfen",
|
||||
"tipShowOrHideTheFormatPanel": "Formatbereich ein- oder ausblenden",
|
||||
"phReplaceWith": "Ersetzen durch",
|
||||
"tipAddToYourDictionary": "Zum Wörterbuch hinzufügen",
|
||||
"tipClose": "Schließen",
|
||||
"phFind": "Suchen",
|
||||
"tipPreviousMatch": "Vorheriger Treffer",
|
||||
"tipNextMatch": "Nächster Treffer",
|
||||
"tipRotateLeft90": "90° nach links drehen",
|
||||
"tipRotateRight90": "90° nach rechts drehen",
|
||||
"tipFlipHorizontal": "Horizontal spiegeln",
|
||||
"tipFlipVertical": "Vertikal spiegeln",
|
||||
"tipReplaceThisImageKeepingItsPlacement": "Dieses Bild ersetzen, Position beibehalten",
|
||||
"tipAlternateTextForAccessibilityTaggedPdfs": "Alternativtext für Barrierefreiheit (getaggte PDFs)",
|
||||
"tipBringToFront": "In den Vordergrund",
|
||||
"tipSendToBack": "In den Hintergrund",
|
||||
"tipDuplicate": "Duplizieren",
|
||||
"tipDelete": "Löschen",
|
||||
"tipAlignLeftEdges": "Linke Kanten ausrichten",
|
||||
"tipAlignHorizontalCenters": "Horizontal zentrieren",
|
||||
"tipAlignRightEdges": "Rechte Kanten ausrichten",
|
||||
"tipAlignTops": "Oberkanten ausrichten",
|
||||
"tipAlignVerticalCenters": "Vertikal zentrieren",
|
||||
"tipAlignBottoms": "Unterkanten ausrichten",
|
||||
"tipDistributeHorizontally": "Horizontal verteilen",
|
||||
"tipDistributeVertically": "Vertikal verteilen",
|
||||
"tipFontSize": "Schriftgröße",
|
||||
"tipListFontsInstalledOnThisDeviceChromium": "Auf diesem Gerät installierte Schriften auflisten (Chromium)",
|
||||
"tipCustomTextColor": "Benutzerdefinierte Textfarbe",
|
||||
"tipAlignLeft": "Linksbündig",
|
||||
"tipAlignCenter": "Zentriert",
|
||||
"tipAlignRight": "Rechtsbündig",
|
||||
"tipJustify": "Blocksatz",
|
||||
"tipBold": "Fett",
|
||||
"tipItalic": "Kursiv",
|
||||
"tipUnderline": "Unterstrichen",
|
||||
"tipStrikethrough": "Durchgestrichen",
|
||||
"tipSuperscript": "Hochgestellt",
|
||||
"tipSubscript": "Tiefgestellt",
|
||||
"tipToggleBulletedItem": "Aufzählungspunkt umschalten",
|
||||
"tipToggleNumberedItem": "Nummerierten Punkt umschalten",
|
||||
"tipNumberedListMarkerStyle": "Markierungsstil für nummerierte Listen",
|
||||
"tipDecreaseListIndentTab": "Listeneinzug verringern (⇧Tab)",
|
||||
"tipIncreaseListIndentTab": "Listeneinzug vergrößern (Tab)",
|
||||
"tipTextOutlineColor": "Textkonturfarbe",
|
||||
"tipOutlineWidth0None": "Konturbreite (0 = keine)",
|
||||
"tipFromContent": "Aus Inhalt",
|
||||
"tipLeftToRight": "Von links nach rechts",
|
||||
"tipRightToLeft": "Von rechts nach links",
|
||||
"tipStrokeColor": "Linienfarbe",
|
||||
"tipStrokeWidth": "Linienbreite",
|
||||
"tipZoomPresets": "Zoom-Voreinstellungen",
|
||||
"tipZoomOut": "Verkleinern",
|
||||
"tipZoomIn": "Vergrößern",
|
||||
"tipFitPage": "Seite einpassen",
|
||||
"tipPreviousPage": "Vorherige Seite",
|
||||
"tipTypeAPageNumberAndPressEnter": "Seitenzahl eingeben und Enter drücken",
|
||||
"tipNextPage": "Nächste Seite",
|
||||
"tipDocumentProperties": "Dokumenteigenschaften",
|
||||
"tipHideBar": "Leiste ausblenden",
|
||||
"tipShowBar": "Leiste einblenden"
|
||||
},
|
||||
"jpgToPdf": {
|
||||
"name": "JPG zu PDF",
|
||||
"subtitle": "Eine PDF aus JPG, JPEG und JPEG2000 (JP2/JPX) Bildern erstellen."
|
||||
@@ -514,6 +632,51 @@
|
||||
"retainPageLabels": "Originale Seitenbeschriftungen jeder Datei beibehalten",
|
||||
"retainPageLabelsHint": "Aus (Standard): Das zusammengeführte PDF verwendet die natürliche Seitennummerierung 1–N. An: Die ursprünglichen Seitenbeschriftungen jeder Datei bleiben erhalten (kann zu doppelten Beschriftungen führen)."
|
||||
},
|
||||
"duplexCollate": {
|
||||
"name": "Seitenfolge für Duplex-Scans neu anordnen",
|
||||
"subtitle": "Ein PDF, das in zwei Blöcken gescannt wurde (erst alle Vorderseiten, dann alle Rückseiten), in die richtige Vorder-/Rückseiten-Reihenfolge bringen.",
|
||||
"totalPagesLabel": "Seiten gesamt:",
|
||||
"splitAfterPageLabel": "Teilen nach Seite",
|
||||
"splitAfterPagePlaceholder": "z. B. 50",
|
||||
"backBlockOrderLabel": "Reihenfolge des Rückseiten-Blocks",
|
||||
"backBlockReverseOption": "Rückseiten-Block umkehren (üblich bei umgedrehtem Stapel)",
|
||||
"backBlockKeepOption": "Rückseiten-Block unverändert lassen",
|
||||
"autoSplitButton": "Teilung automatisch erkennen (Hälfte)",
|
||||
"exportGroupedLabel": "Gruppierte Dateien nach ursprünglicher Dokumentlänge exportieren",
|
||||
"pagesPerDocumentLabel": "Seiten pro Originaldokument",
|
||||
"groupedHelp": "Wenn aktiviert, ist die Ausgabe eine ZIP-Datei mit einer PDF-Datei pro gruppiertem Dokument.",
|
||||
"collateButton": "PDF zusammenführen",
|
||||
"invalidFileTitle": "Ungültige Datei",
|
||||
"invalidFileMessage": "Bitte wählen Sie eine PDF-Datei aus.",
|
||||
"loadingPdf": "PDF wird geladen...",
|
||||
"loadErrorMessage": "PDF-Datei konnte nicht geladen werden.",
|
||||
"fileMeta": "{{size}} - {{count}} Seiten",
|
||||
"oddPageWarning": "Ungerade Seitenzahl ({{count}}). Ein Duplex-Scan sollte eine gerade Seitenzahl haben; möglicherweise fehlt eine Seite oder es ist eine zu viel.",
|
||||
"previewSummary": "Vorderseiten-Block: {{frontCount}} Seite(n), Rückseiten-Block: {{backCount}} Seite(n). Ausgabe: {{outputCount}} Seite(n) in Vorder-/Rückseiten-Reihenfolge.",
|
||||
"previewMismatchWarning": "Die Blocklängen von Vorder- und Rückseiten unterscheiden sich ({{frontCount}} Vorderseiten gegenüber {{backCount}} Rückseiten). Die {{extraCount}} überzähligen Seite(n) der längeren Seite werden ohne Gegenstück am Ende angehängt.",
|
||||
"missingFileTitle": "Fehlende Datei",
|
||||
"missingFileMessage": "Bitte laden Sie vor der Verarbeitung ein PDF mit mindestens 2 Seiten hoch.",
|
||||
"invalidSplitTitle": "Ungültiger Teilungspunkt",
|
||||
"invalidSplitMessage": "Der Teilungspunkt muss zwischen Seite 1 und Seite {{maxSplit}} liegen.",
|
||||
"unevenConfirmTitle": "Ungleiche Blöcke",
|
||||
"unevenConfirmMessage": "Der Vorderseiten-Block hat {{frontCount}} Seite(n) und der Rückseiten-Block {{backCount}} Seite(n).\nMeist bedeutet das, dass eine Seite doppelt gescannt wurde oder fehlt.\n\nDie {{extraCount}} Seite(n) ohne Gegenstück werden am Ende angehängt.\n\nTrotzdem fortfahren?",
|
||||
"invalidGroupTitle": "Ungültige Gruppengröße",
|
||||
"invalidGroupMessage": "Bitte geben Sie eine gültige Seitenzahl pro Originaldokument ein.",
|
||||
"collatingLoader": "Duplex-Scan wird zusammengeführt...",
|
||||
"successMessage": "Zusammengeführtes PDF wurde erfolgreich erstellt.",
|
||||
"successGroupedMessage": "Zusammenführung abgeschlossen. {{fileCount}} gruppierte Datei(en) erstellt.",
|
||||
"processErrorMessage": "PDF konnte nicht zusammengeführt werden.",
|
||||
"howItWorksStep1Title": "Scan hochladen",
|
||||
"howItWorksStep1": "Laden Sie das einzelne PDF hoch, das erst alle Vorderseiten und danach alle Rückseiten enthält.",
|
||||
"howItWorksStep2Title": "Teilungspunkt festlegen",
|
||||
"howItWorksStep2": "Geben Sie an, wo der Vorderseiten-Block endet, und wählen Sie, ob der Rückseiten-Block umgekehrt werden muss.",
|
||||
"howItWorksStep3Title": "Zusammenführen und herunterladen",
|
||||
"howItWorksStep3": "Sie erhalten ein ineinander sortiertes PDF oder eine ZIP-Datei mit einer eigenen Datei pro Originaldokument.",
|
||||
"faqOddPagesQuestion": "Was ist, wenn mein Scan eine ungerade Seitenzahl hat?",
|
||||
"faqOddPagesAnswer": "Ein Duplex-Scan sollte eine gerade Seitenzahl haben. Ist das nicht der Fall, wurde vermutlich eine Seite doppelt gescannt oder übersprungen. Das Werkzeug warnt Sie vor der Verarbeitung, und Seiten ohne Gegenstück werden am Ende angehängt, damit nichts verloren geht.",
|
||||
"faqBackOrderQuestion": "Warum sollte ich den Rückseiten-Block unverändert lassen?",
|
||||
"faqBackOrderAnswer": "Das hängt davon ab, wie der Stapel für den zweiten Durchgang eingelegt wurde. Wird der gesamte Stapel umgedreht, liegen die Rückseiten in umgekehrter Reihenfolge vor – das ist die Standardeinstellung. Hat Ihr Scanner sie in derselben Reihenfolge wie die Vorderseiten ausgegeben, lassen Sie den Block unverändert."
|
||||
},
|
||||
"addAttachments": {
|
||||
"name": "Anhänge hinzufügen",
|
||||
"subtitle": "Eine oder mehrere Dateien in Ihre PDF einbetten."
|
||||
@@ -1150,5 +1313,13 @@
|
||||
"faqSinglePageAnswer": "Ja! Aktivieren Sie die Option \"Wiederholen\" und Ihre Überlagerungsseiten werden auf allen Basisseiten wiederholt. Ein einseitiges Wasserzeichen wird auf jeder Seite angewendet.",
|
||||
"faqPrivacyQuestion": "Sind meine Dateien privat und sicher?",
|
||||
"faqPrivacyAnswer": "Absolut! Die gesamte Verarbeitung findet in Ihrem Browser statt. Ihre Dateien verlassen niemals Ihr Gerät, was vollständige Privatsphäre gewährleistet."
|
||||
},
|
||||
"unlockPdf": {
|
||||
"name": "PDF entschlüsseln",
|
||||
"subtitle": "PDF durch Entfernen des Passwortschutzes entsperren."
|
||||
},
|
||||
"protectPdf": {
|
||||
"name": "PDF verschlüsseln",
|
||||
"subtitle": "Ihre PDF durch Hinzufügen eines Passworts sperren."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,11 +212,11 @@
|
||||
},
|
||||
"browserBased": {
|
||||
"question": "How does browser-based processing keep me safe?",
|
||||
"answer": "By running entirely inside your browser, BentoPDF ensures that your files never leave your device. This eliminates the risks of server hacks, data breaches, or unauthorized access. Your files remain yours—always."
|
||||
"answer": "By running entirely inside your browser, BentoPDF ensures that your files never leave your device. This eliminates the risks of server hacks, data breaches, or unauthorized access. Your files remain yours, always."
|
||||
},
|
||||
"analytics": {
|
||||
"question": "Do you use cookies or analytics to track me?",
|
||||
"answer": "We care about your privacy. BentoPDF does not track personal information. We use Simple Analytics solely to see anonymous visit counts. This means we can know how many users visit our site, but we never know who you are. Simple Analytics is fully GDPR-compliant and respects your privacy."
|
||||
"answer": "No. BentoPDF does not track you at all. We do not use cookies, analytics, or any tracking scripts, not even on the live website at bentopdf.com. We never know who you are or what you do with the tools."
|
||||
}
|
||||
},
|
||||
"testimonials": {
|
||||
@@ -239,7 +239,9 @@
|
||||
"legal": "Legal",
|
||||
"termsAndConditions": "Terms and Conditions",
|
||||
"privacyPolicy": "Privacy Policy",
|
||||
"followUs": "Follow Us"
|
||||
"followUs": "Follow Us",
|
||||
"privacyShort": "Privacy",
|
||||
"termsShort": "Terms"
|
||||
},
|
||||
"merge": {
|
||||
"title": "Merge PDFs",
|
||||
@@ -281,41 +283,42 @@
|
||||
},
|
||||
"about": {
|
||||
"hero": {
|
||||
"title": "We believe PDF tools should be",
|
||||
"title": "PDF tools should be",
|
||||
"subtitle": "fast, private, and free.",
|
||||
"noCompromises": "No compromises."
|
||||
},
|
||||
"mission": {
|
||||
"title": "Our Mission",
|
||||
"title": "Our",
|
||||
"titleDim": "Mission",
|
||||
"description": "To provide the most comprehensive PDF toolbox that respects your privacy and never asks for payment. We believe essential document tools should be accessible to everyone, everywhere, without barriers."
|
||||
},
|
||||
"philosophy": {
|
||||
"label": "Our Core Philosophy",
|
||||
"title": "Privacy First. Always.",
|
||||
"description": "In an era where data is a commodity, we take a different approach. All processing for Bentopdf tools happens locally in your browser. This means your files never touch our servers, we never see your documents, and we don't track what you do. Your documents remain completely and unequivocally private. It's not just a feature; it's our foundation."
|
||||
"description": "Every BentoPDF tool runs locally in your browser. Your files are never uploaded, nobody else sees your documents, and nothing tracks what you do."
|
||||
},
|
||||
"whyBentopdf": {
|
||||
"title": "Why",
|
||||
"speed": {
|
||||
"title": "Built for Speed",
|
||||
"description": "No waiting for uploads or downloads to a server. By processing files directly in your browser using modern web technologies like WebAssembly, we offer unparalleled speed for all our tools."
|
||||
"description": "There's no upload or download step. Files are processed right in your browser using WebAssembly, so you're never waiting on a server."
|
||||
},
|
||||
"free": {
|
||||
"title": "Completely Free",
|
||||
"description": "No trials, no subscriptions, no hidden fees, and no \"premium\" features held hostage. We believe powerful PDF tools should be a public utility, not a profit center."
|
||||
"title": "Free to Use",
|
||||
"description": "Every tool is free, with no trials, no subscriptions and no watermarks. Development is funded by commercial licenses."
|
||||
},
|
||||
"noAccount": {
|
||||
"title": "No Account Required",
|
||||
"description": "Start using any tool immediately. We don't need your email, a password, or any personal information. Your workflow should be frictionless and anonymous."
|
||||
"description": "Open any tool and start right away. No email, no password, no personal information."
|
||||
},
|
||||
"openSource": {
|
||||
"title": "Open Source Spirit",
|
||||
"description": "Built with transparency in mind. We leverage incredible open-source libraries like PDF-lib and PDF.js, and believe in the community-driven effort to make powerful tools accessible to everyone."
|
||||
"title": "Open Source",
|
||||
"description": "The code is public on GitHub under AGPL-3.0, so you can check exactly how your files are handled. It builds on open-source projects like PDF.js, pdf-lib, qpdf and LibreOffice."
|
||||
}
|
||||
},
|
||||
"cta": {
|
||||
"title": "Ready to get started?",
|
||||
"description": "Join thousands of users who trust Bentopdf for their daily document needs. Experience the difference that privacy and performance can make.",
|
||||
"description": "Join thousands of users who trust BentoPDF for their daily document needs. Experience the difference that privacy and performance can make.",
|
||||
"button": "Explore All Tools"
|
||||
}
|
||||
},
|
||||
@@ -350,9 +353,12 @@
|
||||
"download": "Download:",
|
||||
"downloadSelected": "Download Selected",
|
||||
"exportPdf": "Export PDF",
|
||||
"uploadPdfFiles": "Select PDF Files",
|
||||
"dragAndDrop": "Drag and drop PDF files here, or click to select",
|
||||
"uploadPdfFiles": "Select PDF or image files",
|
||||
"dragAndDrop": "Drag and drop PDF or image files here, or click to select",
|
||||
"selectFiles": "Select Files",
|
||||
"dropToAdd": "Drop PDF or image files to add",
|
||||
"convertingImages": "Converting images to PDF...",
|
||||
"failedToConvertImages": "Failed to convert images to PDF.",
|
||||
"renderingPages": "Rendering pages...",
|
||||
"actions": {
|
||||
"duplicatePage": "Duplicate this page",
|
||||
|
||||
@@ -13,13 +13,14 @@
|
||||
"convertToPdf": "Convert to PDF",
|
||||
"pdfMultiTool": {
|
||||
"name": "PDF Multi Tool",
|
||||
"subtitle": "Merge, Split, Organize, Delete, Rotate, Add Blank Pages, Extract and Duplicate in an unified interface."
|
||||
"subtitle": "Merge, Split, Organize, Delete, Rotate, Add Blank Pages, Extract and Duplicate in a unified interface."
|
||||
},
|
||||
"mergePdf": {
|
||||
"name": "Merge PDF",
|
||||
"subtitle": "Combine multiple PDFs into one file. Preserves Bookmarks.",
|
||||
"retainPageLabels": "Keep original page labels from each file",
|
||||
"retainPageLabelsHint": "Off (default): the merged PDF uses natural page numbering 1–N. On: each file's original page labels are preserved (may produce duplicate labels)."
|
||||
"retainPageLabelsHint": "Off (default): the merged PDF uses natural page numbering 1–N. On: each file's original page labels are preserved (may produce duplicate labels).",
|
||||
"removeDuplicateFonts": "Remove duplicate fonts"
|
||||
},
|
||||
"splitPdf": {
|
||||
"name": "Split PDF",
|
||||
@@ -55,6 +56,124 @@
|
||||
"name": "PDF Editor",
|
||||
"subtitle": "Annotate, highlight, redact, comment, add shapes/images, search, and view PDFs."
|
||||
},
|
||||
"editPdfText": {
|
||||
"name": "Edit PDF Text",
|
||||
"subtitle": "Click any paragraph and edit it in place with live reflow, fonts, and styling.",
|
||||
"saved": "PDF saved successfully! ({{size}} KB)",
|
||||
"failedToLoad": "Failed to load the PDF Text Editor.",
|
||||
"loadingFonts": "Loading fonts...",
|
||||
"fontsUnavailable": "A font needed for some characters could not be downloaded. Check your connection and try again, or those characters may not appear correctly in the saved PDF.",
|
||||
"howToUpload": "Upload PDF",
|
||||
"howToClick": "Click a Paragraph",
|
||||
"howToRestyle": "Restyle Anything",
|
||||
"relatedPdfEditor": "Annotate and mark up PDFs",
|
||||
"relatedSignPdf": "Draw, type or upload a signature",
|
||||
"relatedWatermark": "Stamp text or images",
|
||||
"relatedStamps": "Place stamps on pages",
|
||||
"relatedCompress": "Shrink the file size",
|
||||
"relatedOrganizeName": "Organize PDF",
|
||||
"relatedOrganize": "Reorder and manage pages",
|
||||
"open": "Open",
|
||||
"export": "Export",
|
||||
"filterAll": "All",
|
||||
"filterText": "Text",
|
||||
"filterImages": "Images",
|
||||
"filterShapes": "Shapes",
|
||||
"addText": "Add Text",
|
||||
"langAuto": "Auto",
|
||||
"change": "Change",
|
||||
"ignore": "Ignore",
|
||||
"next": "Next",
|
||||
"replace": "Replace",
|
||||
"replaceAll": "Replace All",
|
||||
"emptyState": "Open a PDF to edit its text, images and shapes.",
|
||||
"choosePdf": "Choose a PDF…",
|
||||
"font": "Font",
|
||||
"systemFonts": "System fonts",
|
||||
"color": "Color",
|
||||
"alignment": "Alignment",
|
||||
"style": "Style",
|
||||
"lists": "Lists",
|
||||
"outline": "Outline",
|
||||
"spacing": "Spacing",
|
||||
"direction": "Direction",
|
||||
"dirAuto": "Auto",
|
||||
"pathStroke": "Path stroke",
|
||||
"tipBackToUpload": "Back to upload",
|
||||
"tipOpenAnotherPdf": "Open another PDF",
|
||||
"tipExportS": "Export (⌘S)",
|
||||
"tipUndoZ": "Undo (⌘Z)",
|
||||
"tipRedoZ": "Redo (⇧⌘Z)",
|
||||
"tipFileDetails": "File details",
|
||||
"tipEditExistingContent": "Edit existing content",
|
||||
"tipWhatTheEditToolTouchesNarrowTheScopeOnBus": "What the Edit tool touches — narrow the scope on busy pages",
|
||||
"tipClickThePageToAddATextBox": "Click the page to add a text box",
|
||||
"tipSpellCheckLanguage": "Spell-check language",
|
||||
"tipFindAndReplace": "Find & replace",
|
||||
"tipAddAnImage": "Add an image",
|
||||
"tipCopyThisPageSTextInReadingOrder": "Copy this page's text in reading order",
|
||||
"tipCheckTheSpellingOfThisPage": "Check the spelling of this page",
|
||||
"tipShowOrHideTheFormatPanel": "Show or hide the format panel",
|
||||
"phReplaceWith": "Replace with",
|
||||
"tipAddToYourDictionary": "Add to your dictionary",
|
||||
"tipClose": "Close",
|
||||
"phFind": "Find",
|
||||
"tipPreviousMatch": "Previous match",
|
||||
"tipNextMatch": "Next match",
|
||||
"tipRotateLeft90": "Rotate left 90°",
|
||||
"tipRotateRight90": "Rotate right 90°",
|
||||
"tipFlipHorizontal": "Flip horizontal",
|
||||
"tipFlipVertical": "Flip vertical",
|
||||
"tipReplaceThisImageKeepingItsPlacement": "Replace this image, keeping its placement",
|
||||
"tipAlternateTextForAccessibilityTaggedPdfs": "Alternate text for accessibility (tagged PDFs)",
|
||||
"tipBringToFront": "Bring to front",
|
||||
"tipSendToBack": "Send to back",
|
||||
"tipDuplicate": "Duplicate",
|
||||
"tipDelete": "Delete",
|
||||
"tipAlignLeftEdges": "Align left edges",
|
||||
"tipAlignHorizontalCenters": "Align horizontal centers",
|
||||
"tipAlignRightEdges": "Align right edges",
|
||||
"tipAlignTops": "Align tops",
|
||||
"tipAlignVerticalCenters": "Align vertical centers",
|
||||
"tipAlignBottoms": "Align bottoms",
|
||||
"tipDistributeHorizontally": "Distribute horizontally",
|
||||
"tipDistributeVertically": "Distribute vertically",
|
||||
"tipFontSize": "Font size",
|
||||
"tipListFontsInstalledOnThisDeviceChromium": "List fonts installed on this device (Chromium)",
|
||||
"tipCustomTextColor": "Custom text color",
|
||||
"tipAlignLeft": "Align left",
|
||||
"tipAlignCenter": "Align center",
|
||||
"tipAlignRight": "Align right",
|
||||
"tipJustify": "Justify",
|
||||
"tipBold": "Bold",
|
||||
"tipItalic": "Italic",
|
||||
"tipUnderline": "Underline",
|
||||
"tipStrikethrough": "Strikethrough",
|
||||
"tipSuperscript": "Superscript",
|
||||
"tipSubscript": "Subscript",
|
||||
"tipToggleBulletedItem": "Toggle bulleted item",
|
||||
"tipToggleNumberedItem": "Toggle numbered item",
|
||||
"tipNumberedListMarkerStyle": "Numbered-list marker style",
|
||||
"tipDecreaseListIndentTab": "Decrease list indent (⇧Tab)",
|
||||
"tipIncreaseListIndentTab": "Increase list indent (Tab)",
|
||||
"tipTextOutlineColor": "Text outline color",
|
||||
"tipOutlineWidth0None": "Outline width (0 = none)",
|
||||
"tipFromContent": "From content",
|
||||
"tipLeftToRight": "Left to right",
|
||||
"tipRightToLeft": "Right to left",
|
||||
"tipStrokeColor": "Stroke color",
|
||||
"tipStrokeWidth": "Stroke width",
|
||||
"tipZoomPresets": "Zoom presets",
|
||||
"tipZoomOut": "Zoom out",
|
||||
"tipZoomIn": "Zoom in",
|
||||
"tipFitPage": "Fit page",
|
||||
"tipPreviousPage": "Previous page",
|
||||
"tipTypeAPageNumberAndPressEnter": "Type a page number and press Enter",
|
||||
"tipNextPage": "Next page",
|
||||
"tipDocumentProperties": "Document properties",
|
||||
"tipHideBar": "Hide bar",
|
||||
"tipShowBar": "Show bar"
|
||||
},
|
||||
"jpgToPdf": {
|
||||
"name": "JPG to PDF",
|
||||
"subtitle": "Create a PDF from JPG, JPEG, and JPEG2000 (JP2/JPX) images."
|
||||
@@ -399,7 +518,8 @@
|
||||
"noFile": "No File",
|
||||
"noFileExplanation": "Please upload a PDF file first.",
|
||||
"conversionSuccess": "PDF converted to TIFFs successfully!",
|
||||
"conversionError": "Failed to convert PDF to TIFF. The file might be corrupted."
|
||||
"conversionError": "Failed to convert PDF to TIFF. The file might be corrupted.",
|
||||
"conversionOutOfMemory": "The browser ran out of memory while converting. Try a lower DPI, or uncheck the multi-page TIFF option to convert pages one at a time."
|
||||
}
|
||||
},
|
||||
"pdfToCbz": {
|
||||
@@ -514,6 +634,51 @@
|
||||
"retainPageLabels": "Keep original page labels from each file",
|
||||
"retainPageLabelsHint": "Off (default): the merged PDF uses natural page numbering 1–N. On: each file's original page labels are preserved (may produce duplicate labels)."
|
||||
},
|
||||
"duplexCollate": {
|
||||
"name": "Duplex Collate",
|
||||
"subtitle": "Reorder a PDF scanned as two blocks (all fronts, then all backs) into proper front/back order.",
|
||||
"totalPagesLabel": "Total pages:",
|
||||
"splitAfterPageLabel": "Split after page",
|
||||
"splitAfterPagePlaceholder": "e.g. 50",
|
||||
"backBlockOrderLabel": "Back block order",
|
||||
"backBlockReverseOption": "Reverse back block (common for flipped stacks)",
|
||||
"backBlockKeepOption": "Keep back block as-is",
|
||||
"autoSplitButton": "Auto-detect split (half)",
|
||||
"exportGroupedLabel": "Export grouped files by original document length",
|
||||
"pagesPerDocumentLabel": "Pages per original document",
|
||||
"groupedHelp": "If enabled, output is a ZIP containing one PDF per grouped document.",
|
||||
"collateButton": "Collate PDF",
|
||||
"invalidFileTitle": "Invalid File",
|
||||
"invalidFileMessage": "Please select a PDF file.",
|
||||
"loadingPdf": "Loading PDF...",
|
||||
"loadErrorMessage": "Failed to load PDF file.",
|
||||
"fileMeta": "{{size}} - {{count}} pages",
|
||||
"oddPageWarning": "Odd page count ({{count}}). A duplex scan should have an even number of pages; you may have a missing or extra page.",
|
||||
"previewSummary": "Front block: {{frontCount}} page(s), back block: {{backCount}} page(s). Output: {{outputCount}} page(s), in front/back sequence.",
|
||||
"previewMismatchWarning": "Front and back block lengths differ ({{frontCount}} front vs {{backCount}} back). The {{extraCount}} extra page(s) on the longer side will be appended unpaired at the end.",
|
||||
"missingFileTitle": "Missing File",
|
||||
"missingFileMessage": "Please upload a PDF with at least 2 pages before processing.",
|
||||
"invalidSplitTitle": "Invalid Split Point",
|
||||
"invalidSplitMessage": "Split point must be between page 1 and page {{maxSplit}}.",
|
||||
"unevenConfirmTitle": "Uneven Blocks",
|
||||
"unevenConfirmMessage": "The front block has {{frontCount}} page(s) and the back block has {{backCount}} page(s).\nThis usually means a page was scanned twice or is missing.\n\nThe {{extraCount}} unpaired page(s) will be appended at the end.\n\nContinue anyway?",
|
||||
"invalidGroupTitle": "Invalid Group Size",
|
||||
"invalidGroupMessage": "Please enter a valid number of pages per original document.",
|
||||
"collatingLoader": "Collating duplex scan...",
|
||||
"successMessage": "Collated PDF generated successfully.",
|
||||
"successGroupedMessage": "Collation complete. Generated {{fileCount}} grouped file(s).",
|
||||
"processErrorMessage": "Failed to collate PDF.",
|
||||
"howItWorksStep1Title": "Upload the scan",
|
||||
"howItWorksStep1": "Drop in the single PDF that holds all the front sides followed by all the back sides.",
|
||||
"howItWorksStep2Title": "Set the split point",
|
||||
"howItWorksStep2": "Mark where the front block ends, then choose whether the back block needs reversing.",
|
||||
"howItWorksStep3Title": "Collate and download",
|
||||
"howItWorksStep3": "Get one interleaved PDF, or a ZIP with a separate file per original document.",
|
||||
"faqOddPagesQuestion": "What if my scan has an odd number of pages?",
|
||||
"faqOddPagesAnswer": "A duplex scan should have an even page count. If it does not, a page was probably scanned twice or missed. The tool warns you before processing, and any unpaired pages are appended at the end so nothing is lost.",
|
||||
"faqBackOrderQuestion": "Why would I keep the back block as-is?",
|
||||
"faqBackOrderAnswer": "It depends on how the stack was fed for the second pass. Flipping the whole stack over produces back sides in reverse order, which is the default. If your scanner returned them in the same order as the fronts, choose to keep the block as-is."
|
||||
},
|
||||
"addAttachments": {
|
||||
"name": "Add Attachments",
|
||||
"subtitle": "Embed one or more files into your PDF."
|
||||
@@ -1150,5 +1315,13 @@
|
||||
"faqSinglePageAnswer": "Yes! Enable the \"Loop\" option and your overlay PDF pages will repeat across all base pages. A single-page watermark will apply to every page.",
|
||||
"faqPrivacyQuestion": "Are my files private and secure?",
|
||||
"faqPrivacyAnswer": "Absolutely! All processing happens in your browser. Your files never leave your device, ensuring complete privacy."
|
||||
},
|
||||
"unlockPdf": {
|
||||
"name": "Unlock PDF",
|
||||
"subtitle": "Remove the password from a PDF so it opens freely. Requires the current password."
|
||||
},
|
||||
"protectPdf": {
|
||||
"name": "Protect PDF",
|
||||
"subtitle": "Password protect a PDF with strong AES encryption."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@
|
||||
},
|
||||
"analytics": {
|
||||
"question": "¿Usan cookies o análisis para rastrearme?",
|
||||
"answer": "Nos preocupamos por tu privacidad. BentoPDF no rastrea información personal. Usamos Simple Analytics únicamente para ver recuentos de visitas anónimas. Esto significa que podemos saber cuántos usuarios visitan nuestro sitio, pero nunca sabemos quién eres. Simple Analytics cumple completamente con GDPR y respeta tu privacidad."
|
||||
"answer": "No. BentoPDF no te rastrea en absoluto. No usamos cookies, analíticas ni scripts de seguimiento, ni siquiera en el sitio web en vivo bentopdf.com. Nunca sabemos quién eres ni qué haces con las herramientas."
|
||||
}
|
||||
},
|
||||
"testimonials": {
|
||||
@@ -239,7 +239,9 @@
|
||||
"legal": "Legal",
|
||||
"termsAndConditions": "Términos y Condiciones",
|
||||
"privacyPolicy": "Política de Privacidad",
|
||||
"followUs": "Síguenos"
|
||||
"followUs": "Síguenos",
|
||||
"privacyShort": "Privacidad",
|
||||
"termsShort": "Términos"
|
||||
},
|
||||
"merge": {
|
||||
"title": "Fusionar PDFs",
|
||||
@@ -286,13 +288,14 @@
|
||||
"noCompromises": "Sin compromisos."
|
||||
},
|
||||
"mission": {
|
||||
"title": "Nuestra Misión",
|
||||
"title": "Nuestra",
|
||||
"titleDim": "Misión",
|
||||
"description": "Proporcionar la caja de herramientas PDF más completa que respete tu privacidad y nunca pida pago. Creemos que las herramientas de documentos esenciales deben ser accesibles para todos, en todas partes, sin barreras."
|
||||
},
|
||||
"philosophy": {
|
||||
"label": "Nuestra Filosofía Central",
|
||||
"title": "Privacidad Primero. Siempre.",
|
||||
"description": "En una era donde los datos son una mercancía, adoptamos un enfoque diferente. Todo el procesamiento de las herramientas de Bentopdf ocurre localmente en tu navegador. Esto significa que tus archivos nunca tocan nuestros servidores, nunca vemos tus documentos y no rastreamos lo que haces. Tus documentos permanecen completa e inequívocamente privados. No es solo una característica; es nuestra base."
|
||||
"description": "En una era donde los datos son una mercancía, adoptamos un enfoque diferente. Todo el procesamiento de las herramientas de BentoPDF ocurre localmente en tu navegador. Esto significa que tus archivos nunca tocan nuestros servidores, nunca vemos tus documentos y no rastreamos lo que haces. Tus documentos permanecen completa e inequívocamente privados. No es solo una característica; es nuestra base."
|
||||
},
|
||||
"whyBentopdf": {
|
||||
"title": "Por qué",
|
||||
@@ -315,7 +318,7 @@
|
||||
},
|
||||
"cta": {
|
||||
"title": "¿Listo para comenzar?",
|
||||
"description": "Únete a miles de usuarios que confían en Bentopdf para sus necesidades diarias de documentos. Experimenta la diferencia que la privacidad y el rendimiento pueden hacer.",
|
||||
"description": "Únete a miles de usuarios que confían en BentoPDF para sus necesidades diarias de documentos. Experimenta la diferencia que la privacidad y el rendimiento pueden hacer.",
|
||||
"button": "Explorar Todas las Herramientas"
|
||||
}
|
||||
},
|
||||
@@ -350,9 +353,12 @@
|
||||
"download": "Descargar:",
|
||||
"downloadSelected": "Descargar Seleccionados",
|
||||
"exportPdf": "Exportar PDF",
|
||||
"uploadPdfFiles": "Seleccionar Archivos PDF",
|
||||
"dragAndDrop": "Arrastra y suelta archivos PDF aquí, o haz clic para seleccionar",
|
||||
"uploadPdfFiles": "Seleccionar archivos PDF o imágenes",
|
||||
"dragAndDrop": "Arrastra y suelta archivos PDF o imágenes aquí, o haz clic para seleccionar",
|
||||
"selectFiles": "Seleccionar Archivos",
|
||||
"dropToAdd": "Suelta archivos PDF o imágenes para añadir",
|
||||
"convertingImages": "Convirtiendo imágenes a PDF...",
|
||||
"failedToConvertImages": "No se pudieron convertir las imágenes a PDF.",
|
||||
"renderingPages": "Renderizando páginas...",
|
||||
"actions": {
|
||||
"duplicatePage": "Duplicar esta página",
|
||||
|
||||
@@ -55,6 +55,124 @@
|
||||
"name": "Editor PDF",
|
||||
"subtitle": "Anotar, resaltar, redactar, comentar, agregar formas/imágenes, buscar y ver PDFs."
|
||||
},
|
||||
"editPdfText": {
|
||||
"name": "Editar texto PDF",
|
||||
"subtitle": "Haz clic en cualquier párrafo y edítalo directamente con reajuste de texto en vivo, fuentes y estilos.",
|
||||
"saved": "¡PDF guardado correctamente! ({{size}} KB)",
|
||||
"failedToLoad": "No se pudo cargar el editor de texto PDF.",
|
||||
"loadingFonts": "Cargando fuentes...",
|
||||
"fontsUnavailable": "No se pudo descargar una fuente necesaria para algunos caracteres. Comprueba tu conexión e inténtalo de nuevo; de lo contrario, es posible que esos caracteres no se vean correctamente en el PDF guardado.",
|
||||
"howToUpload": "Subir PDF",
|
||||
"howToClick": "Haz clic en un párrafo",
|
||||
"howToRestyle": "Cambia el estilo de todo",
|
||||
"relatedPdfEditor": "Anota y resalta PDF",
|
||||
"relatedSignPdf": "Dibuja, escribe o sube una firma",
|
||||
"relatedWatermark": "Estampa texto o imágenes",
|
||||
"relatedStamps": "Coloca sellos en las páginas",
|
||||
"relatedCompress": "Reduce el tamaño del archivo",
|
||||
"relatedOrganizeName": "Organizar PDF",
|
||||
"relatedOrganize": "Reordena y gestiona páginas",
|
||||
"open": "Abrir",
|
||||
"export": "Exportar",
|
||||
"filterAll": "Todo",
|
||||
"filterText": "Texto",
|
||||
"filterImages": "Imágenes",
|
||||
"filterShapes": "Formas",
|
||||
"addText": "Añadir texto",
|
||||
"langAuto": "Automático",
|
||||
"change": "Cambiar",
|
||||
"ignore": "Ignorar",
|
||||
"next": "Siguiente",
|
||||
"replace": "Reemplazar",
|
||||
"replaceAll": "Reemplazar todo",
|
||||
"emptyState": "Abre un PDF para editar su texto, imágenes y formas.",
|
||||
"choosePdf": "Elegir un PDF…",
|
||||
"font": "Fuente",
|
||||
"systemFonts": "Fuentes del sistema",
|
||||
"color": "Color",
|
||||
"alignment": "Alineación",
|
||||
"style": "Estilo",
|
||||
"lists": "Listas",
|
||||
"outline": "Contorno",
|
||||
"spacing": "Espaciado",
|
||||
"direction": "Dirección",
|
||||
"dirAuto": "Automático",
|
||||
"pathStroke": "Contorno del trazado",
|
||||
"tipBackToUpload": "Volver a la subida",
|
||||
"tipOpenAnotherPdf": "Abrir otro PDF",
|
||||
"tipExportS": "Exportar (⌘S)",
|
||||
"tipUndoZ": "Deshacer (⌘Z)",
|
||||
"tipRedoZ": "Rehacer (⇧⌘Z)",
|
||||
"tipFileDetails": "Detalles del archivo",
|
||||
"tipEditExistingContent": "Editar contenido existente",
|
||||
"tipWhatTheEditToolTouchesNarrowTheScopeOnBus": "Qué modifica la herramienta Editar: limita el alcance en páginas con mucho contenido",
|
||||
"tipClickThePageToAddATextBox": "Haz clic en la página para añadir un cuadro de texto",
|
||||
"tipSpellCheckLanguage": "Idioma del corrector ortográfico",
|
||||
"tipFindAndReplace": "Buscar y reemplazar",
|
||||
"tipAddAnImage": "Añadir una imagen",
|
||||
"tipCopyThisPageSTextInReadingOrder": "Copiar el texto de esta página en orden de lectura",
|
||||
"tipCheckTheSpellingOfThisPage": "Revisar la ortografía de esta página",
|
||||
"tipShowOrHideTheFormatPanel": "Mostrar u ocultar el panel de formato",
|
||||
"phReplaceWith": "Reemplazar con",
|
||||
"tipAddToYourDictionary": "Añadir al diccionario",
|
||||
"tipClose": "Cerrar",
|
||||
"phFind": "Buscar",
|
||||
"tipPreviousMatch": "Coincidencia anterior",
|
||||
"tipNextMatch": "Coincidencia siguiente",
|
||||
"tipRotateLeft90": "Girar 90° a la izquierda",
|
||||
"tipRotateRight90": "Girar 90° a la derecha",
|
||||
"tipFlipHorizontal": "Voltear horizontalmente",
|
||||
"tipFlipVertical": "Voltear verticalmente",
|
||||
"tipReplaceThisImageKeepingItsPlacement": "Reemplazar esta imagen conservando su posición",
|
||||
"tipAlternateTextForAccessibilityTaggedPdfs": "Texto alternativo para accesibilidad (PDF etiquetados)",
|
||||
"tipBringToFront": "Traer al frente",
|
||||
"tipSendToBack": "Enviar al fondo",
|
||||
"tipDuplicate": "Duplicar",
|
||||
"tipDelete": "Eliminar",
|
||||
"tipAlignLeftEdges": "Alinear bordes izquierdos",
|
||||
"tipAlignHorizontalCenters": "Centrar horizontalmente",
|
||||
"tipAlignRightEdges": "Alinear bordes derechos",
|
||||
"tipAlignTops": "Alinear bordes superiores",
|
||||
"tipAlignVerticalCenters": "Centrar verticalmente",
|
||||
"tipAlignBottoms": "Alinear bordes inferiores",
|
||||
"tipDistributeHorizontally": "Distribuir horizontalmente",
|
||||
"tipDistributeVertically": "Distribuir verticalmente",
|
||||
"tipFontSize": "Tamaño de fuente",
|
||||
"tipListFontsInstalledOnThisDeviceChromium": "Listar las fuentes instaladas en este dispositivo (Chromium)",
|
||||
"tipCustomTextColor": "Color de texto personalizado",
|
||||
"tipAlignLeft": "Alinear a la izquierda",
|
||||
"tipAlignCenter": "Centrar",
|
||||
"tipAlignRight": "Alinear a la derecha",
|
||||
"tipJustify": "Justificar",
|
||||
"tipBold": "Negrita",
|
||||
"tipItalic": "Cursiva",
|
||||
"tipUnderline": "Subrayado",
|
||||
"tipStrikethrough": "Tachado",
|
||||
"tipSuperscript": "Superíndice",
|
||||
"tipSubscript": "Subíndice",
|
||||
"tipToggleBulletedItem": "Alternar viñeta",
|
||||
"tipToggleNumberedItem": "Alternar elemento numerado",
|
||||
"tipNumberedListMarkerStyle": "Estilo de marcador de listas numeradas",
|
||||
"tipDecreaseListIndentTab": "Reducir sangría (⇧Tab)",
|
||||
"tipIncreaseListIndentTab": "Aumentar sangría (Tab)",
|
||||
"tipTextOutlineColor": "Color del contorno del texto",
|
||||
"tipOutlineWidth0None": "Grosor del contorno (0 = ninguno)",
|
||||
"tipFromContent": "Del contenido",
|
||||
"tipLeftToRight": "De izquierda a derecha",
|
||||
"tipRightToLeft": "De derecha a izquierda",
|
||||
"tipStrokeColor": "Color del trazo",
|
||||
"tipStrokeWidth": "Grosor del trazo",
|
||||
"tipZoomPresets": "Ajustes de zoom",
|
||||
"tipZoomOut": "Alejar",
|
||||
"tipZoomIn": "Acercar",
|
||||
"tipFitPage": "Ajustar página",
|
||||
"tipPreviousPage": "Página anterior",
|
||||
"tipTypeAPageNumberAndPressEnter": "Escribe un número de página y pulsa Intro",
|
||||
"tipNextPage": "Página siguiente",
|
||||
"tipDocumentProperties": "Propiedades del documento",
|
||||
"tipHideBar": "Ocultar barra",
|
||||
"tipShowBar": "Mostrar barra"
|
||||
},
|
||||
"jpgToPdf": {
|
||||
"name": "JPG a PDF",
|
||||
"subtitle": "Crea un PDF desde imágenes JPG, JPEG y JPEG2000 (JP2/JPX)."
|
||||
@@ -514,6 +632,51 @@
|
||||
"retainPageLabels": "Conservar las etiquetas de página originales de cada archivo",
|
||||
"retainPageLabelsHint": "Desactivado (predeterminado): el PDF combinado usa numeración natural 1–N. Activado: se conservan las etiquetas de página originales de cada archivo (puede producir etiquetas duplicadas)."
|
||||
},
|
||||
"duplexCollate": {
|
||||
"name": "Intercalar escaneo a doble cara",
|
||||
"subtitle": "Reordena un PDF escaneado en dos bloques (primero todos los anversos, luego todos los reversos) en el orden anverso/reverso correcto.",
|
||||
"totalPagesLabel": "Páginas totales:",
|
||||
"splitAfterPageLabel": "Dividir después de la página",
|
||||
"splitAfterPagePlaceholder": "p. ej. 50",
|
||||
"backBlockOrderLabel": "Orden del bloque de reversos",
|
||||
"backBlockReverseOption": "Invertir el bloque de reversos (habitual si se giró la pila)",
|
||||
"backBlockKeepOption": "Mantener el bloque de reversos tal cual",
|
||||
"autoSplitButton": "Detectar división automáticamente (mitad)",
|
||||
"exportGroupedLabel": "Exportar archivos agrupados según la longitud del documento original",
|
||||
"pagesPerDocumentLabel": "Páginas por documento original",
|
||||
"groupedHelp": "Si se activa, el resultado es un ZIP con un PDF por cada documento agrupado.",
|
||||
"collateButton": "Intercalar PDF",
|
||||
"invalidFileTitle": "Archivo no válido",
|
||||
"invalidFileMessage": "Selecciona un archivo PDF.",
|
||||
"loadingPdf": "Cargando PDF...",
|
||||
"loadErrorMessage": "No se pudo cargar el archivo PDF.",
|
||||
"fileMeta": "{{size}} - {{count}} páginas",
|
||||
"oddPageWarning": "Número de páginas impar ({{count}}). Un escaneo a doble cara debería tener un número par de páginas; puede que falte una página o sobre una.",
|
||||
"previewSummary": "Bloque de anversos: {{frontCount}} página(s), bloque de reversos: {{backCount}} página(s). Resultado: {{outputCount}} página(s), en secuencia anverso/reverso.",
|
||||
"previewMismatchWarning": "Los bloques de anversos y reversos tienen longitudes distintas ({{frontCount}} anversos frente a {{backCount}} reversos). Las {{extraCount}} página(s) sobrantes del bloque más largo se añadirán sin pareja al final.",
|
||||
"missingFileTitle": "Falta el archivo",
|
||||
"missingFileMessage": "Sube un PDF con al menos 2 páginas antes de procesarlo.",
|
||||
"invalidSplitTitle": "Punto de división no válido",
|
||||
"invalidSplitMessage": "El punto de división debe estar entre la página 1 y la página {{maxSplit}}.",
|
||||
"unevenConfirmTitle": "Bloques desiguales",
|
||||
"unevenConfirmMessage": "El bloque de anversos tiene {{frontCount}} página(s) y el de reversos {{backCount}} página(s).\nNormalmente esto significa que una página se escaneó dos veces o que falta alguna.\n\nLas {{extraCount}} página(s) sin pareja se añadirán al final.\n\n¿Continuar de todos modos?",
|
||||
"invalidGroupTitle": "Tamaño de grupo no válido",
|
||||
"invalidGroupMessage": "Introduce un número válido de páginas por documento original.",
|
||||
"collatingLoader": "Intercalando el escaneo a doble cara...",
|
||||
"successMessage": "PDF intercalado generado correctamente.",
|
||||
"successGroupedMessage": "Intercalado completado. Se han generado {{fileCount}} archivo(s) agrupado(s).",
|
||||
"processErrorMessage": "No se pudo intercalar el PDF.",
|
||||
"howItWorksStep1Title": "Sube el escaneo",
|
||||
"howItWorksStep1": "Suelta el PDF único que contiene todos los anversos seguidos de todos los reversos.",
|
||||
"howItWorksStep2Title": "Define el punto de división",
|
||||
"howItWorksStep2": "Indica dónde termina el bloque de anversos y elige si el bloque de reversos debe invertirse.",
|
||||
"howItWorksStep3Title": "Intercala y descarga",
|
||||
"howItWorksStep3": "Obtén un PDF intercalado o un ZIP con un archivo independiente por cada documento original.",
|
||||
"faqOddPagesQuestion": "¿Y si mi escaneo tiene un número impar de páginas?",
|
||||
"faqOddPagesAnswer": "Un escaneo a doble cara debería tener un número par de páginas. Si no es así, probablemente se escaneó una página dos veces o se omitió alguna. La herramienta te avisa antes de procesar y las páginas sin pareja se añaden al final para que no se pierda nada.",
|
||||
"faqBackOrderQuestion": "¿Por qué querría mantener el bloque de reversos tal cual?",
|
||||
"faqBackOrderAnswer": "Depende de cómo se colocó la pila en la segunda pasada. Girar la pila entera produce reversos en orden inverso, que es la opción predeterminada. Si tu escáner los devolvió en el mismo orden que los anversos, elige mantener el bloque tal cual."
|
||||
},
|
||||
"addAttachments": {
|
||||
"name": "Agregar Adjuntos",
|
||||
"subtitle": "Incrusta uno o más archivos en tu PDF."
|
||||
@@ -1151,5 +1314,13 @@
|
||||
"faqSinglePageAnswer": "¡Sí! Active la opción \"Repetir\" y las páginas de superposición se repetirán en todas las páginas base. Una marca de agua de una página se aplicará a cada página.",
|
||||
"faqPrivacyQuestion": "¿Mis archivos son privados y seguros?",
|
||||
"faqPrivacyAnswer": "¡Por supuesto! Todo el procesamiento ocurre en su navegador. Sus archivos nunca abandonan su dispositivo, garantizando total privacidad."
|
||||
},
|
||||
"unlockPdf": {
|
||||
"name": "Descifrar PDF",
|
||||
"subtitle": "Desbloquea PDF eliminando la protección por contraseña."
|
||||
},
|
||||
"protectPdf": {
|
||||
"name": "Cifrar PDF",
|
||||
"subtitle": "Bloquea tu PDF agregando una contraseña."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@
|
||||
"testimonials": {
|
||||
"title": "Ce que disent",
|
||||
"users": "nos utilisateurs",
|
||||
"say": ""
|
||||
"say": " "
|
||||
},
|
||||
"support": {
|
||||
"title": "Vous aimez ce projet ?",
|
||||
@@ -239,7 +239,9 @@
|
||||
"legal": "Mentions légales",
|
||||
"termsAndConditions": "Conditions générales",
|
||||
"privacyPolicy": "Politique de confidentialité",
|
||||
"followUs": "Nous suivre"
|
||||
"followUs": "Nous suivre",
|
||||
"privacyShort": "Confidentialité",
|
||||
"termsShort": "Conditions"
|
||||
},
|
||||
"merge": {
|
||||
"title": "Fusionner des PDF",
|
||||
@@ -286,7 +288,8 @@
|
||||
"noCompromises": "Sans compromis."
|
||||
},
|
||||
"mission": {
|
||||
"title": "Notre mission",
|
||||
"title": "Notre",
|
||||
"titleDim": "mission",
|
||||
"description": "Proposer la palette d’outils PDF la plus complète, tout en respectant votre vie privée et sans jamais demander de paiement. Les outils essentiels doivent être accessibles à tous, partout, sans barrières."
|
||||
},
|
||||
"philosophy": {
|
||||
@@ -350,9 +353,12 @@
|
||||
"download": "Téléchargement :",
|
||||
"downloadSelected": "Télécharger la sélection",
|
||||
"exportPdf": "Exporter en PDF",
|
||||
"uploadPdfFiles": "Sélectionner des fichiers PDF",
|
||||
"dragAndDrop": "Glissez-déposez vos fichiers PDF ici ou cliquez pour sélectionner",
|
||||
"uploadPdfFiles": "Sélectionner des fichiers PDF ou des images",
|
||||
"dragAndDrop": "Glissez-déposez vos fichiers PDF ou images ici, ou cliquez pour sélectionner",
|
||||
"selectFiles": "Sélectionner des fichiers",
|
||||
"dropToAdd": "Déposez des fichiers PDF ou images à ajouter",
|
||||
"convertingImages": "Conversion des images en PDF...",
|
||||
"failedToConvertImages": "Échec de la conversion des images en PDF.",
|
||||
"renderingPages": "Rendu des pages...",
|
||||
"actions": {
|
||||
"duplicatePage": "Dupliquer cette page",
|
||||
|
||||
@@ -55,6 +55,124 @@
|
||||
"name": "Éditeur PDF",
|
||||
"subtitle": "Annoter, surligner, masquer, commenter, ajouter des formes ou images, rechercher et afficher des PDF."
|
||||
},
|
||||
"editPdfText": {
|
||||
"name": "Modifier le texte d'un PDF",
|
||||
"subtitle": "Cliquer sur un paragraphe et le modifier directement, avec remise en page instantanée, polices et styles.",
|
||||
"saved": "PDF enregistré avec succès ! ({{size}} Ko)",
|
||||
"failedToLoad": "Impossible de charger l'éditeur de texte PDF.",
|
||||
"loadingFonts": "Chargement des polices...",
|
||||
"fontsUnavailable": "Impossible de télécharger une police nécessaire à certains caractères. Vérifiez votre connexion et réessayez, sinon ces caractères risquent de ne pas s'afficher correctement dans le PDF enregistré.",
|
||||
"howToUpload": "Importer un PDF",
|
||||
"howToClick": "Cliquer sur un paragraphe",
|
||||
"howToRestyle": "Tout restyler",
|
||||
"relatedPdfEditor": "Annoter et surligner des PDF",
|
||||
"relatedSignPdf": "Dessiner, saisir ou importer une signature",
|
||||
"relatedWatermark": "Apposer du texte ou des images",
|
||||
"relatedStamps": "Placer des tampons sur les pages",
|
||||
"relatedCompress": "Réduire la taille du fichier",
|
||||
"relatedOrganizeName": "Organiser le PDF",
|
||||
"relatedOrganize": "Réorganiser et gérer les pages",
|
||||
"open": "Ouvrir",
|
||||
"export": "Exporter",
|
||||
"filterAll": "Tout",
|
||||
"filterText": "Texte",
|
||||
"filterImages": "Images",
|
||||
"filterShapes": "Formes",
|
||||
"addText": "Ajouter du texte",
|
||||
"langAuto": "Auto",
|
||||
"change": "Modifier",
|
||||
"ignore": "Ignorer",
|
||||
"next": "Suivant",
|
||||
"replace": "Remplacer",
|
||||
"replaceAll": "Tout remplacer",
|
||||
"emptyState": "Ouvrez un PDF pour en modifier le texte, les images et les formes.",
|
||||
"choosePdf": "Choisir un PDF…",
|
||||
"font": "Police",
|
||||
"systemFonts": "Polices système",
|
||||
"color": "Couleur",
|
||||
"alignment": "Alignement",
|
||||
"style": "Style",
|
||||
"lists": "Listes",
|
||||
"outline": "Contour",
|
||||
"spacing": "Espacement",
|
||||
"direction": "Direction",
|
||||
"dirAuto": "Auto",
|
||||
"pathStroke": "Contour du tracé",
|
||||
"tipBackToUpload": "Retour à l'import",
|
||||
"tipOpenAnotherPdf": "Ouvrir un autre PDF",
|
||||
"tipExportS": "Exporter (⌘S)",
|
||||
"tipUndoZ": "Annuler (⌘Z)",
|
||||
"tipRedoZ": "Rétablir (⇧⌘Z)",
|
||||
"tipFileDetails": "Détails du fichier",
|
||||
"tipEditExistingContent": "Modifier le contenu existant",
|
||||
"tipWhatTheEditToolTouchesNarrowTheScopeOnBus": "Ce que l'outil Modifier affecte — restreindre la portée sur les pages chargées",
|
||||
"tipClickThePageToAddATextBox": "Cliquez sur la page pour ajouter une zone de texte",
|
||||
"tipSpellCheckLanguage": "Langue du correcteur orthographique",
|
||||
"tipFindAndReplace": "Rechercher et remplacer",
|
||||
"tipAddAnImage": "Ajouter une image",
|
||||
"tipCopyThisPageSTextInReadingOrder": "Copier le texte de cette page dans l'ordre de lecture",
|
||||
"tipCheckTheSpellingOfThisPage": "Vérifier l'orthographe de cette page",
|
||||
"tipShowOrHideTheFormatPanel": "Afficher ou masquer le panneau de mise en forme",
|
||||
"phReplaceWith": "Remplacer par",
|
||||
"tipAddToYourDictionary": "Ajouter au dictionnaire",
|
||||
"tipClose": "Fermer",
|
||||
"phFind": "Rechercher",
|
||||
"tipPreviousMatch": "Occurrence précédente",
|
||||
"tipNextMatch": "Occurrence suivante",
|
||||
"tipRotateLeft90": "Rotation 90° à gauche",
|
||||
"tipRotateRight90": "Rotation 90° à droite",
|
||||
"tipFlipHorizontal": "Miroir horizontal",
|
||||
"tipFlipVertical": "Miroir vertical",
|
||||
"tipReplaceThisImageKeepingItsPlacement": "Remplacer cette image en conservant sa position",
|
||||
"tipAlternateTextForAccessibilityTaggedPdfs": "Texte alternatif pour l'accessibilité (PDF balisés)",
|
||||
"tipBringToFront": "Mettre au premier plan",
|
||||
"tipSendToBack": "Mettre à l'arrière-plan",
|
||||
"tipDuplicate": "Dupliquer",
|
||||
"tipDelete": "Supprimer",
|
||||
"tipAlignLeftEdges": "Aligner les bords gauches",
|
||||
"tipAlignHorizontalCenters": "Centrer horizontalement",
|
||||
"tipAlignRightEdges": "Aligner les bords droits",
|
||||
"tipAlignTops": "Aligner les bords supérieurs",
|
||||
"tipAlignVerticalCenters": "Centrer verticalement",
|
||||
"tipAlignBottoms": "Aligner les bords inférieurs",
|
||||
"tipDistributeHorizontally": "Répartir horizontalement",
|
||||
"tipDistributeVertically": "Répartir verticalement",
|
||||
"tipFontSize": "Taille de police",
|
||||
"tipListFontsInstalledOnThisDeviceChromium": "Lister les polices installées sur cet appareil (Chromium)",
|
||||
"tipCustomTextColor": "Couleur de texte personnalisée",
|
||||
"tipAlignLeft": "Aligner à gauche",
|
||||
"tipAlignCenter": "Centrer",
|
||||
"tipAlignRight": "Aligner à droite",
|
||||
"tipJustify": "Justifier",
|
||||
"tipBold": "Gras",
|
||||
"tipItalic": "Italique",
|
||||
"tipUnderline": "Souligné",
|
||||
"tipStrikethrough": "Barré",
|
||||
"tipSuperscript": "Exposant",
|
||||
"tipSubscript": "Indice",
|
||||
"tipToggleBulletedItem": "Activer la puce",
|
||||
"tipToggleNumberedItem": "Activer la numérotation",
|
||||
"tipNumberedListMarkerStyle": "Style de puce des listes numérotées",
|
||||
"tipDecreaseListIndentTab": "Diminuer le retrait (⇧Tab)",
|
||||
"tipIncreaseListIndentTab": "Augmenter le retrait (Tab)",
|
||||
"tipTextOutlineColor": "Couleur du contour du texte",
|
||||
"tipOutlineWidth0None": "Épaisseur du contour (0 = aucune)",
|
||||
"tipFromContent": "À partir du contenu",
|
||||
"tipLeftToRight": "De gauche à droite",
|
||||
"tipRightToLeft": "De droite à gauche",
|
||||
"tipStrokeColor": "Couleur du trait",
|
||||
"tipStrokeWidth": "Épaisseur du trait",
|
||||
"tipZoomPresets": "Préréglages de zoom",
|
||||
"tipZoomOut": "Zoom arrière",
|
||||
"tipZoomIn": "Zoom avant",
|
||||
"tipFitPage": "Ajuster à la page",
|
||||
"tipPreviousPage": "Page précédente",
|
||||
"tipTypeAPageNumberAndPressEnter": "Saisissez un numéro de page et appuyez sur Entrée",
|
||||
"tipNextPage": "Page suivante",
|
||||
"tipDocumentProperties": "Propriétés du document",
|
||||
"tipHideBar": "Masquer la barre",
|
||||
"tipShowBar": "Afficher la barre"
|
||||
},
|
||||
"jpgToPdf": {
|
||||
"name": "JPG vers PDF",
|
||||
"subtitle": "Créer un PDF à partir d’une ou plusieurs images JPG."
|
||||
@@ -514,6 +632,51 @@
|
||||
"retainPageLabels": "Conserver les étiquettes de page d'origine de chaque fichier",
|
||||
"retainPageLabelsHint": "Désactivé (par défaut) : le PDF fusionné utilise une numérotation naturelle 1–N. Activé : les étiquettes de page d'origine de chaque fichier sont conservées (peut produire des étiquettes en double)."
|
||||
},
|
||||
"duplexCollate": {
|
||||
"name": "Assembler un scan recto/verso",
|
||||
"subtitle": "Réorganiser un PDF numérisé en deux blocs (tous les rectos, puis tous les versos) dans le bon ordre recto/verso.",
|
||||
"totalPagesLabel": "Pages au total :",
|
||||
"splitAfterPageLabel": "Séparer après la page",
|
||||
"splitAfterPagePlaceholder": "ex. 50",
|
||||
"backBlockOrderLabel": "Ordre du bloc verso",
|
||||
"backBlockReverseOption": "Inverser le bloc verso (courant si la pile a été retournée)",
|
||||
"backBlockKeepOption": "Conserver le bloc verso tel quel",
|
||||
"autoSplitButton": "Détecter la séparation (moitié)",
|
||||
"exportGroupedLabel": "Exporter des fichiers groupés selon la longueur du document d'origine",
|
||||
"pagesPerDocumentLabel": "Pages par document d'origine",
|
||||
"groupedHelp": "Si cette option est activée, la sortie est une archive ZIP contenant un PDF par document groupé.",
|
||||
"collateButton": "Assembler le PDF",
|
||||
"invalidFileTitle": "Fichier invalide",
|
||||
"invalidFileMessage": "Veuillez sélectionner un fichier PDF.",
|
||||
"loadingPdf": "Chargement du PDF...",
|
||||
"loadErrorMessage": "Échec du chargement du fichier PDF.",
|
||||
"fileMeta": "{{size}} - {{count}} pages",
|
||||
"oddPageWarning": "Nombre de pages impair ({{count}}). Un scan recto/verso doit comporter un nombre pair de pages ; il manque peut-être une page ou il y en a une en trop.",
|
||||
"previewSummary": "Bloc recto : {{frontCount}} page(s), bloc verso : {{backCount}} page(s). Sortie : {{outputCount}} page(s), en séquence recto/verso.",
|
||||
"previewMismatchWarning": "Les blocs recto et verso n'ont pas la même longueur ({{frontCount}} rectos contre {{backCount}} versos). Les {{extraCount}} page(s) en trop du bloc le plus long seront ajoutées sans paire à la fin.",
|
||||
"missingFileTitle": "Fichier manquant",
|
||||
"missingFileMessage": "Veuillez importer un PDF d'au moins 2 pages avant de lancer le traitement.",
|
||||
"invalidSplitTitle": "Point de séparation invalide",
|
||||
"invalidSplitMessage": "Le point de séparation doit être compris entre la page 1 et la page {{maxSplit}}.",
|
||||
"unevenConfirmTitle": "Blocs inégaux",
|
||||
"unevenConfirmMessage": "Le bloc recto contient {{frontCount}} page(s) et le bloc verso {{backCount}} page(s).\nCela signifie généralement qu'une page a été numérisée deux fois ou qu'il en manque une.\n\nLes {{extraCount}} page(s) sans paire seront ajoutées à la fin.\n\nContinuer quand même ?",
|
||||
"invalidGroupTitle": "Taille de groupe invalide",
|
||||
"invalidGroupMessage": "Veuillez saisir un nombre de pages valide par document d'origine.",
|
||||
"collatingLoader": "Assemblage du scan recto/verso...",
|
||||
"successMessage": "PDF assemblé généré avec succès.",
|
||||
"successGroupedMessage": "Assemblage terminé. {{fileCount}} fichier(s) groupé(s) généré(s).",
|
||||
"processErrorMessage": "Échec de l'assemblage du PDF.",
|
||||
"howItWorksStep1Title": "Importer le scan",
|
||||
"howItWorksStep1": "Déposez le PDF unique qui contient tous les rectos, suivis de tous les versos.",
|
||||
"howItWorksStep2Title": "Définir le point de séparation",
|
||||
"howItWorksStep2": "Indiquez où se termine le bloc recto, puis choisissez si le bloc verso doit être inversé.",
|
||||
"howItWorksStep3Title": "Assembler et télécharger",
|
||||
"howItWorksStep3": "Obtenez un PDF intercalé, ou une archive ZIP avec un fichier distinct par document d'origine.",
|
||||
"faqOddPagesQuestion": "Que faire si mon scan a un nombre de pages impair ?",
|
||||
"faqOddPagesAnswer": "Un scan recto/verso doit avoir un nombre pair de pages. Si ce n'est pas le cas, une page a probablement été numérisée deux fois ou oubliée. L'outil vous avertit avant le traitement, et les pages sans paire sont ajoutées à la fin afin que rien ne soit perdu.",
|
||||
"faqBackOrderQuestion": "Pourquoi conserverais-je le bloc verso tel quel ?",
|
||||
"faqBackOrderAnswer": "Cela dépend de la façon dont la pile a été insérée pour le second passage. Retourner la pile entière produit des versos en ordre inverse, ce qui correspond au réglage par défaut. Si votre scanner les a restitués dans le même ordre que les rectos, choisissez de conserver le bloc tel quel."
|
||||
},
|
||||
"addAttachments": {
|
||||
"name": "Ajouter des pièces jointes",
|
||||
"subtitle": "Intégrer un ou plusieurs fichiers dans le PDF."
|
||||
@@ -1151,5 +1314,13 @@
|
||||
"faqSinglePageAnswer": "Oui ! Activez l'option \"Répéter\" et vos pages de superposition se répéteront sur toutes les pages de base. Un filigrane d'une seule page s'appliquera à chaque page.",
|
||||
"faqPrivacyQuestion": "Mes fichiers sont-ils privés et sécurisés ?",
|
||||
"faqPrivacyAnswer": "Absolument ! Tout le traitement se fait dans votre navigateur. Vos fichiers ne quittent jamais votre appareil, garantissant une confidentialité totale."
|
||||
},
|
||||
"unlockPdf": {
|
||||
"name": "Déverrouiller un PDF",
|
||||
"subtitle": "Supprimer la protection par mot de passe."
|
||||
},
|
||||
"protectPdf": {
|
||||
"name": "Chiffrer un PDF",
|
||||
"subtitle": "Protéger le PDF en ajoutant un mot de passe."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,11 +212,11 @@
|
||||
},
|
||||
"browserBased": {
|
||||
"question": "Bagaimana pemrosesan berbasis browser menjaga keamanan saya?",
|
||||
"answer": "Dengan berjalan sepenuhnya di dalam browser Anda, BentoPDF memastikan file Anda tidak pernah meninggalkan perangkat Anda. Ini menghilangkan risiko peretasan server, pelanggaran data, atau akses tidak sah. File Anda tetap milik Anda—selalu."
|
||||
"answer": "Dengan berjalan sepenuhnya di dalam browser Anda, BentoPDF memastikan file Anda tidak pernah meninggalkan perangkat Anda. Ini menghilangkan risiko peretasan server, pelanggaran data, atau akses tidak sah. File Anda tetap milik Anda, selalu."
|
||||
},
|
||||
"analytics": {
|
||||
"question": "Apakah Anda menggunakan cookie atau analitik untuk melacak saya?",
|
||||
"answer": "Kami peduli dengan privasi Anda. BentoPDF tidak melacak informasi pribadi. Kami menggunakan Simple Analytics hanya untuk melihat jumlah kunjungan anonim. Ini berarti kami dapat mengetahui berapa banyak pengguna yang mengunjungi situs kami, tetapi kami tidak pernah tahu siapa Anda. Simple Analytics sepenuhnya patuh GDPR dan menghormati privasi Anda."
|
||||
"answer": "Tidak. BentoPDF sama sekali tidak melacak Anda. Kami tidak menggunakan cookie, analitik, atau skrip pelacakan apa pun, bahkan di situs web langsung bentopdf.com. Kami tidak pernah tahu siapa Anda atau apa yang Anda lakukan dengan alat-alat ini."
|
||||
}
|
||||
},
|
||||
"testimonials": {
|
||||
@@ -239,7 +239,9 @@
|
||||
"legal": "Hukum",
|
||||
"termsAndConditions": "Syarat dan Ketentuan",
|
||||
"privacyPolicy": "Kebijakan Privasi",
|
||||
"followUs": "Ikuti Kami"
|
||||
"followUs": "Ikuti Kami",
|
||||
"privacyShort": "Privasi",
|
||||
"termsShort": "Ketentuan"
|
||||
},
|
||||
"merge": {
|
||||
"title": "Gabung PDF",
|
||||
@@ -286,13 +288,14 @@
|
||||
"noCompromises": "Tidak ada kompromi."
|
||||
},
|
||||
"mission": {
|
||||
"title": "Misi Kami",
|
||||
"title": "Misi",
|
||||
"titleDim": "Kami",
|
||||
"description": "Untuk menyediakan toolbox PDF paling komprehensif yang menghormati privasi Anda dan tidak pernah meminta pembayaran. Kami percaya alat dokumen penting harus dapat diakses oleh semua orang, di mana saja, tanpa hambatan."
|
||||
},
|
||||
"philosophy": {
|
||||
"label": "Filosofi Inti Kami",
|
||||
"title": "Privasi Yang Utama. Selalu.",
|
||||
"description": "Di era di mana data adalah komoditas, kami mengambil pendekatan berbeda. Semua pemrosesan untuk alat Bentopdf terjadi secara lokal di browser Anda. Ini berarti file Anda tidak pernah menyentuh server kami, kami tidak pernah melihat dokumen Anda, dan kami tidak melacak apa yang Anda lakukan. Dokumen Anda tetap utuh dan privat secara tegas. Ini bukan hanya fitur; ini adalah fondasi kami."
|
||||
"description": "Di era di mana data adalah komoditas, kami mengambil pendekatan berbeda. Semua pemrosesan untuk alat BentoPDF terjadi secara lokal di browser Anda. Ini berarti file Anda tidak pernah menyentuh server kami, kami tidak pernah melihat dokumen Anda, dan kami tidak melacak apa yang Anda lakukan. Dokumen Anda tetap utuh dan privat secara tegas. Ini bukan hanya fitur; ini adalah fondasi kami."
|
||||
},
|
||||
"whyBentopdf": {
|
||||
"title": "Mengapa",
|
||||
@@ -315,7 +318,7 @@
|
||||
},
|
||||
"cta": {
|
||||
"title": "Siap untuk memulai?",
|
||||
"description": "Bergabunglah dengan ribuan pengguna yang percaya Bentopdf untuk kebutuhan dokumen harian mereka. Rasakan bedanya privasi dan performa yang ditawarkan.",
|
||||
"description": "Bergabunglah dengan ribuan pengguna yang percaya BentoPDF untuk kebutuhan dokumen harian mereka. Rasakan bedanya privasi dan performa yang ditawarkan.",
|
||||
"button": "Jelajahi Semua Alat"
|
||||
}
|
||||
},
|
||||
@@ -350,9 +353,12 @@
|
||||
"download": "Unduh:",
|
||||
"downloadSelected": "Unduh yang Dipilih",
|
||||
"exportPdf": "Ekspor PDF",
|
||||
"uploadPdfFiles": "Pilih File PDF",
|
||||
"dragAndDrop": "Seret dan jatuhkan file PDF di sini, atau klik untuk memilih",
|
||||
"uploadPdfFiles": "Pilih File PDF atau Gambar",
|
||||
"dragAndDrop": "Seret dan jatuhkan file PDF atau gambar di sini, atau klik untuk memilih",
|
||||
"selectFiles": "Pilih File",
|
||||
"dropToAdd": "Jatuhkan file PDF atau gambar untuk menambahkan",
|
||||
"convertingImages": "Mengonversi gambar ke PDF...",
|
||||
"failedToConvertImages": "Gagal mengonversi gambar ke PDF.",
|
||||
"renderingPages": "Merender halaman...",
|
||||
"actions": {
|
||||
"duplicatePage": "Duplikat halaman ini",
|
||||
|
||||
@@ -55,6 +55,124 @@
|
||||
"name": "Editor PDF",
|
||||
"subtitle": "Anotasi, sorot, redaksi, komentar, tambah bentuk/gambar, cari, dan lihat PDF."
|
||||
},
|
||||
"editPdfText": {
|
||||
"name": "Edit Teks PDF",
|
||||
"subtitle": "Klik paragraf mana pun dan edit langsung di tempat dengan penyusunan ulang teks secara langsung, font, dan gaya.",
|
||||
"saved": "PDF berhasil disimpan! ({{size}} KB)",
|
||||
"failedToLoad": "Gagal memuat Editor Teks PDF.",
|
||||
"loadingFonts": "Memuat font...",
|
||||
"fontsUnavailable": "Font yang diperlukan untuk beberapa karakter tidak dapat diunduh. Periksa koneksi Anda dan coba lagi, atau karakter tersebut mungkin tidak tampil dengan benar di PDF yang disimpan.",
|
||||
"howToUpload": "Unggah PDF",
|
||||
"howToClick": "Klik sebuah paragraf",
|
||||
"howToRestyle": "Ubah gaya apa pun",
|
||||
"relatedPdfEditor": "Beri anotasi dan tandai PDF",
|
||||
"relatedSignPdf": "Gambar, ketik, atau unggah tanda tangan",
|
||||
"relatedWatermark": "Bubuhkan teks atau gambar",
|
||||
"relatedStamps": "Tempatkan stempel di halaman",
|
||||
"relatedCompress": "Perkecil ukuran file",
|
||||
"relatedOrganizeName": "Atur PDF",
|
||||
"relatedOrganize": "Susun ulang dan kelola halaman",
|
||||
"open": "Buka",
|
||||
"export": "Ekspor",
|
||||
"filterAll": "Semua",
|
||||
"filterText": "Teks",
|
||||
"filterImages": "Gambar",
|
||||
"filterShapes": "Bentuk",
|
||||
"addText": "Tambah teks",
|
||||
"langAuto": "Otomatis",
|
||||
"change": "Ubah",
|
||||
"ignore": "Abaikan",
|
||||
"next": "Berikutnya",
|
||||
"replace": "Ganti",
|
||||
"replaceAll": "Ganti semua",
|
||||
"emptyState": "Buka PDF untuk mengedit teks, gambar, dan bentuknya.",
|
||||
"choosePdf": "Pilih PDF…",
|
||||
"font": "Font",
|
||||
"systemFonts": "Font sistem",
|
||||
"color": "Warna",
|
||||
"alignment": "Perataan",
|
||||
"style": "Gaya",
|
||||
"lists": "Daftar",
|
||||
"outline": "Garis luar",
|
||||
"spacing": "Jarak",
|
||||
"direction": "Arah",
|
||||
"dirAuto": "Otomatis",
|
||||
"pathStroke": "Goresan jalur",
|
||||
"tipBackToUpload": "Kembali ke unggahan",
|
||||
"tipOpenAnotherPdf": "Buka PDF lain",
|
||||
"tipExportS": "Ekspor (⌘S)",
|
||||
"tipUndoZ": "Urungkan (⌘Z)",
|
||||
"tipRedoZ": "Ulangi (⇧⌘Z)",
|
||||
"tipFileDetails": "Detail file",
|
||||
"tipEditExistingContent": "Edit konten yang ada",
|
||||
"tipWhatTheEditToolTouchesNarrowTheScopeOnBus": "Yang dipengaruhi alat Edit — persempit cakupan pada halaman yang padat",
|
||||
"tipClickThePageToAddATextBox": "Klik halaman untuk menambahkan kotak teks",
|
||||
"tipSpellCheckLanguage": "Bahasa pemeriksa ejaan",
|
||||
"tipFindAndReplace": "Cari dan ganti",
|
||||
"tipAddAnImage": "Tambahkan gambar",
|
||||
"tipCopyThisPageSTextInReadingOrder": "Salin teks halaman ini sesuai urutan baca",
|
||||
"tipCheckTheSpellingOfThisPage": "Periksa ejaan halaman ini",
|
||||
"tipShowOrHideTheFormatPanel": "Tampilkan atau sembunyikan panel format",
|
||||
"phReplaceWith": "Ganti dengan",
|
||||
"tipAddToYourDictionary": "Tambahkan ke kamus",
|
||||
"tipClose": "Tutup",
|
||||
"phFind": "Cari",
|
||||
"tipPreviousMatch": "Kecocokan sebelumnya",
|
||||
"tipNextMatch": "Kecocokan berikutnya",
|
||||
"tipRotateLeft90": "Putar 90° ke kiri",
|
||||
"tipRotateRight90": "Putar 90° ke kanan",
|
||||
"tipFlipHorizontal": "Balik horizontal",
|
||||
"tipFlipVertical": "Balik vertikal",
|
||||
"tipReplaceThisImageKeepingItsPlacement": "Ganti gambar ini dengan mempertahankan posisinya",
|
||||
"tipAlternateTextForAccessibilityTaggedPdfs": "Teks alternatif untuk aksesibilitas (PDF bertag)",
|
||||
"tipBringToFront": "Bawa ke depan",
|
||||
"tipSendToBack": "Kirim ke belakang",
|
||||
"tipDuplicate": "Duplikat",
|
||||
"tipDelete": "Hapus",
|
||||
"tipAlignLeftEdges": "Ratakan tepi kiri",
|
||||
"tipAlignHorizontalCenters": "Pusatkan horizontal",
|
||||
"tipAlignRightEdges": "Ratakan tepi kanan",
|
||||
"tipAlignTops": "Ratakan tepi atas",
|
||||
"tipAlignVerticalCenters": "Pusatkan vertikal",
|
||||
"tipAlignBottoms": "Ratakan tepi bawah",
|
||||
"tipDistributeHorizontally": "Distribusikan horizontal",
|
||||
"tipDistributeVertically": "Distribusikan vertikal",
|
||||
"tipFontSize": "Ukuran font",
|
||||
"tipListFontsInstalledOnThisDeviceChromium": "Daftar font yang terpasang di perangkat ini (Chromium)",
|
||||
"tipCustomTextColor": "Warna teks khusus",
|
||||
"tipAlignLeft": "Rata kiri",
|
||||
"tipAlignCenter": "Rata tengah",
|
||||
"tipAlignRight": "Rata kanan",
|
||||
"tipJustify": "Rata kanan-kiri",
|
||||
"tipBold": "Tebal",
|
||||
"tipItalic": "Miring",
|
||||
"tipUnderline": "Garis bawah",
|
||||
"tipStrikethrough": "Coret",
|
||||
"tipSuperscript": "Superskrip",
|
||||
"tipSubscript": "Subskrip",
|
||||
"tipToggleBulletedItem": "Alihkan butir",
|
||||
"tipToggleNumberedItem": "Alihkan item bernomor",
|
||||
"tipNumberedListMarkerStyle": "Gaya penanda daftar bernomor",
|
||||
"tipDecreaseListIndentTab": "Kurangi indentasi (⇧Tab)",
|
||||
"tipIncreaseListIndentTab": "Tambah indentasi (Tab)",
|
||||
"tipTextOutlineColor": "Warna garis luar teks",
|
||||
"tipOutlineWidth0None": "Lebar garis luar (0 = tidak ada)",
|
||||
"tipFromContent": "Dari konten",
|
||||
"tipLeftToRight": "Kiri ke kanan",
|
||||
"tipRightToLeft": "Kanan ke kiri",
|
||||
"tipStrokeColor": "Warna goresan",
|
||||
"tipStrokeWidth": "Lebar goresan",
|
||||
"tipZoomPresets": "Prasetel zoom",
|
||||
"tipZoomOut": "Perkecil",
|
||||
"tipZoomIn": "Perbesar",
|
||||
"tipFitPage": "Paskan halaman",
|
||||
"tipPreviousPage": "Halaman sebelumnya",
|
||||
"tipTypeAPageNumberAndPressEnter": "Ketik nomor halaman lalu tekan Enter",
|
||||
"tipNextPage": "Halaman berikutnya",
|
||||
"tipDocumentProperties": "Properti dokumen",
|
||||
"tipHideBar": "Sembunyikan bilah",
|
||||
"tipShowBar": "Tampilkan bilah"
|
||||
},
|
||||
"jpgToPdf": {
|
||||
"name": "JPG ke PDF",
|
||||
"subtitle": "Buat PDF dari gambar JPG, JPEG, dan JPEG2000 (JP2/JPX)."
|
||||
@@ -514,6 +632,51 @@
|
||||
"retainPageLabels": "Pertahankan label halaman asli dari setiap file",
|
||||
"retainPageLabelsHint": "Mati (default): PDF yang digabungkan menggunakan penomoran halaman alami 1–N. Aktif: label halaman asli setiap file dipertahankan (dapat menghasilkan label ganda)."
|
||||
},
|
||||
"duplexCollate": {
|
||||
"name": "Susun Ulang Pindaian Dupleks",
|
||||
"subtitle": "Susun ulang PDF yang dipindai dalam dua blok (semua halaman depan, lalu semua halaman belakang) menjadi urutan depan/belakang yang benar.",
|
||||
"totalPagesLabel": "Total halaman:",
|
||||
"splitAfterPageLabel": "Pisahkan setelah halaman",
|
||||
"splitAfterPagePlaceholder": "mis. 50",
|
||||
"backBlockOrderLabel": "Urutan blok halaman belakang",
|
||||
"backBlockReverseOption": "Balik blok halaman belakang (umum jika tumpukan dibalik)",
|
||||
"backBlockKeepOption": "Biarkan blok halaman belakang apa adanya",
|
||||
"autoSplitButton": "Deteksi pemisahan otomatis (setengah)",
|
||||
"exportGroupedLabel": "Ekspor file yang dikelompokkan sesuai panjang dokumen asli",
|
||||
"pagesPerDocumentLabel": "Halaman per dokumen asli",
|
||||
"groupedHelp": "Jika diaktifkan, hasilnya berupa ZIP berisi satu PDF untuk setiap dokumen yang dikelompokkan.",
|
||||
"collateButton": "Susun PDF",
|
||||
"invalidFileTitle": "File Tidak Valid",
|
||||
"invalidFileMessage": "Silakan pilih file PDF.",
|
||||
"loadingPdf": "Memuat PDF...",
|
||||
"loadErrorMessage": "Gagal memuat file PDF.",
|
||||
"fileMeta": "{{size}} - {{count}} halaman",
|
||||
"oddPageWarning": "Jumlah halaman ganjil ({{count}}). Pindaian dupleks seharusnya berjumlah genap; mungkin ada halaman yang hilang atau berlebih.",
|
||||
"previewSummary": "Blok depan: {{frontCount}} halaman, blok belakang: {{backCount}} halaman. Hasil: {{outputCount}} halaman, dalam urutan depan/belakang.",
|
||||
"previewMismatchWarning": "Panjang blok depan dan belakang berbeda ({{frontCount}} depan vs {{backCount}} belakang). {{extraCount}} halaman berlebih pada sisi yang lebih panjang akan ditambahkan tanpa pasangan di akhir.",
|
||||
"missingFileTitle": "File Tidak Ada",
|
||||
"missingFileMessage": "Unggah PDF dengan minimal 2 halaman sebelum diproses.",
|
||||
"invalidSplitTitle": "Titik Pemisah Tidak Valid",
|
||||
"invalidSplitMessage": "Titik pemisah harus antara halaman 1 dan halaman {{maxSplit}}.",
|
||||
"unevenConfirmTitle": "Blok Tidak Seimbang",
|
||||
"unevenConfirmMessage": "Blok depan memiliki {{frontCount}} halaman dan blok belakang {{backCount}} halaman.\nBiasanya ini berarti ada halaman yang terpindai dua kali atau hilang.\n\n{{extraCount}} halaman tanpa pasangan akan ditambahkan di akhir.\n\nTetap lanjutkan?",
|
||||
"invalidGroupTitle": "Ukuran Grup Tidak Valid",
|
||||
"invalidGroupMessage": "Masukkan jumlah halaman per dokumen asli yang valid.",
|
||||
"collatingLoader": "Menyusun pindaian dupleks...",
|
||||
"successMessage": "PDF tersusun berhasil dibuat.",
|
||||
"successGroupedMessage": "Penyusunan selesai. {{fileCount}} file kelompok dibuat.",
|
||||
"processErrorMessage": "Gagal menyusun PDF.",
|
||||
"howItWorksStep1Title": "Unggah hasil pindai",
|
||||
"howItWorksStep1": "Letakkan satu PDF yang berisi semua halaman depan diikuti semua halaman belakang.",
|
||||
"howItWorksStep2Title": "Tentukan titik pemisah",
|
||||
"howItWorksStep2": "Tandai di mana blok depan berakhir, lalu pilih apakah blok belakang perlu dibalik.",
|
||||
"howItWorksStep3Title": "Susun dan unduh",
|
||||
"howItWorksStep3": "Dapatkan satu PDF dengan halaman berselang-seling, atau ZIP berisi file terpisah untuk setiap dokumen asli.",
|
||||
"faqOddPagesQuestion": "Bagaimana jika jumlah halaman hasil pindai saya ganjil?",
|
||||
"faqOddPagesAnswer": "Pindaian dupleks seharusnya berjumlah halaman genap. Jika tidak, kemungkinan ada halaman yang terpindai dua kali atau terlewat. Alat ini memperingatkan Anda sebelum memproses, dan halaman tanpa pasangan ditambahkan di akhir sehingga tidak ada yang hilang.",
|
||||
"faqBackOrderQuestion": "Mengapa saya perlu membiarkan blok belakang apa adanya?",
|
||||
"faqBackOrderAnswer": "Itu tergantung cara tumpukan dimasukkan pada pemindaian kedua. Membalik seluruh tumpukan menghasilkan halaman belakang dalam urutan terbalik, dan itulah pengaturan bawaannya. Jika pemindai Anda mengembalikannya dalam urutan yang sama dengan halaman depan, pilih untuk membiarkan blok apa adanya."
|
||||
},
|
||||
"addAttachments": {
|
||||
"name": "Tambah Lampiran",
|
||||
"subtitle": "Sematkan satu atau lebih file ke PDF Anda."
|
||||
@@ -1151,5 +1314,13 @@
|
||||
"faqSinglePageAnswer": "Ya! Aktifkan opsi \"Ulangi\" dan halaman overlay Anda akan berulang di semua halaman dasar. Watermark satu halaman akan diterapkan ke setiap halaman.",
|
||||
"faqPrivacyQuestion": "Apakah file saya pribadi dan aman?",
|
||||
"faqPrivacyAnswer": "Tentu saja! Semua pemrosesan terjadi di browser Anda. File Anda tidak pernah meninggalkan perangkat Anda, memastikan privasi penuh."
|
||||
},
|
||||
"unlockPdf": {
|
||||
"name": "Dekripsi PDF",
|
||||
"subtitle": "Buka kunci PDF dengan menghapus perlindungan kata sandi."
|
||||
},
|
||||
"protectPdf": {
|
||||
"name": "Enkripsi PDF",
|
||||
"subtitle": "Kunci PDF Anda dengan menambahkan kata sandi."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@
|
||||
},
|
||||
"analytics": {
|
||||
"question": "Usate cookie o analytics per tracciarmi?",
|
||||
"answer": "Ci teniamo alla tua privacy. BentoPDF non traccia informazioni personali. Usiamo Simple Analytics solo per visualizzare conteggi di visite anonime. Questo significa che possiamo sapere quante persone visitano il sito, ma non chi sei. Simple Analytics è pienamente conforme al GDPR e rispetta la tua privacy."
|
||||
"answer": "No. BentoPDF non ti traccia in alcun modo. Non usiamo cookie, strumenti di analisi né script di tracciamento, nemmeno sul sito web live bentopdf.com. Non sappiamo mai chi sei né cosa fai con gli strumenti."
|
||||
}
|
||||
},
|
||||
"testimonials": {
|
||||
@@ -239,7 +239,9 @@
|
||||
"legal": "Legale",
|
||||
"termsAndConditions": "Termini e condizioni",
|
||||
"privacyPolicy": "Informativa sulla privacy",
|
||||
"followUs": "Seguici"
|
||||
"followUs": "Seguici",
|
||||
"privacyShort": "Privacy",
|
||||
"termsShort": "Termini"
|
||||
},
|
||||
"merge": {
|
||||
"title": "Unisci PDF",
|
||||
@@ -286,7 +288,8 @@
|
||||
"noCompromises": "Nessun compromesso."
|
||||
},
|
||||
"mission": {
|
||||
"title": "La nostra missione",
|
||||
"title": "La nostra",
|
||||
"titleDim": "missione",
|
||||
"description": "Fornire la cassetta degli attrezzi per PDF più completa che rispetti la tua privacy e non richieda mai pagamenti. Crediamo che gli strumenti essenziali per i documenti debbano essere accessibili a tutti, ovunque, senza barriere."
|
||||
},
|
||||
"philosophy": {
|
||||
@@ -350,9 +353,12 @@
|
||||
"download": "Scarica:",
|
||||
"downloadSelected": "Scarica selezionati",
|
||||
"exportPdf": "Esporta PDF",
|
||||
"uploadPdfFiles": "Seleziona file PDF",
|
||||
"dragAndDrop": "Trascina e rilascia i file PDF qui, oppure clicca per selezionare",
|
||||
"uploadPdfFiles": "Seleziona file PDF o immagini",
|
||||
"dragAndDrop": "Trascina e rilascia file PDF o immagini qui, oppure clicca per selezionare",
|
||||
"selectFiles": "Seleziona file",
|
||||
"dropToAdd": "Rilascia file PDF o immagini per aggiungere",
|
||||
"convertingImages": "Conversione delle immagini in PDF...",
|
||||
"failedToConvertImages": "Impossibile convertire le immagini in PDF.",
|
||||
"renderingPages": "Generazione anteprime pagine...",
|
||||
"actions": {
|
||||
"duplicatePage": "Duplica questa pagina",
|
||||
|
||||
@@ -55,6 +55,124 @@
|
||||
"name": "Editor PDF",
|
||||
"subtitle": "Annota, evidenzia, redigi, commenta, aggiungi forme/immagini, cerca e visualizza PDF."
|
||||
},
|
||||
"editPdfText": {
|
||||
"name": "Modifica testo PDF",
|
||||
"subtitle": "Clicca su un paragrafo qualsiasi e modificalo direttamente con ricomposizione del testo in tempo reale, caratteri e stili.",
|
||||
"saved": "PDF salvato correttamente! ({{size}} KB)",
|
||||
"failedToLoad": "Impossibile caricare l'editor di testo PDF.",
|
||||
"loadingFonts": "Caricamento dei font...",
|
||||
"fontsUnavailable": "Impossibile scaricare un font necessario per alcuni caratteri. Controlla la connessione e riprova, altrimenti questi caratteri potrebbero non essere visualizzati correttamente nel PDF salvato.",
|
||||
"howToUpload": "Carica PDF",
|
||||
"howToClick": "Fai clic su un paragrafo",
|
||||
"howToRestyle": "Ridefinisci lo stile",
|
||||
"relatedPdfEditor": "Annota ed evidenzia i PDF",
|
||||
"relatedSignPdf": "Disegna, digita o carica una firma",
|
||||
"relatedWatermark": "Applica testo o immagini",
|
||||
"relatedStamps": "Posiziona timbri sulle pagine",
|
||||
"relatedCompress": "Riduci le dimensioni del file",
|
||||
"relatedOrganizeName": "Organizza PDF",
|
||||
"relatedOrganize": "Riordina e gestisci le pagine",
|
||||
"open": "Apri",
|
||||
"export": "Esporta",
|
||||
"filterAll": "Tutto",
|
||||
"filterText": "Testo",
|
||||
"filterImages": "Immagini",
|
||||
"filterShapes": "Forme",
|
||||
"addText": "Aggiungi testo",
|
||||
"langAuto": "Automatico",
|
||||
"change": "Modifica",
|
||||
"ignore": "Ignora",
|
||||
"next": "Avanti",
|
||||
"replace": "Sostituisci",
|
||||
"replaceAll": "Sostituisci tutto",
|
||||
"emptyState": "Apri un PDF per modificarne testo, immagini e forme.",
|
||||
"choosePdf": "Scegli un PDF…",
|
||||
"font": "Carattere",
|
||||
"systemFonts": "Caratteri di sistema",
|
||||
"color": "Colore",
|
||||
"alignment": "Allineamento",
|
||||
"style": "Stile",
|
||||
"lists": "Elenchi",
|
||||
"outline": "Contorno",
|
||||
"spacing": "Spaziatura",
|
||||
"direction": "Direzione",
|
||||
"dirAuto": "Automatico",
|
||||
"pathStroke": "Contorno del tracciato",
|
||||
"tipBackToUpload": "Torna al caricamento",
|
||||
"tipOpenAnotherPdf": "Apri un altro PDF",
|
||||
"tipExportS": "Esporta (⌘S)",
|
||||
"tipUndoZ": "Annulla (⌘Z)",
|
||||
"tipRedoZ": "Ripristina (⇧⌘Z)",
|
||||
"tipFileDetails": "Dettagli file",
|
||||
"tipEditExistingContent": "Modifica contenuti esistenti",
|
||||
"tipWhatTheEditToolTouchesNarrowTheScopeOnBus": "Cosa modifica lo strumento Modifica: restringi l'ambito nelle pagine affollate",
|
||||
"tipClickThePageToAddATextBox": "Fai clic sulla pagina per aggiungere una casella di testo",
|
||||
"tipSpellCheckLanguage": "Lingua del correttore ortografico",
|
||||
"tipFindAndReplace": "Trova e sostituisci",
|
||||
"tipAddAnImage": "Aggiungi un'immagine",
|
||||
"tipCopyThisPageSTextInReadingOrder": "Copia il testo di questa pagina nell'ordine di lettura",
|
||||
"tipCheckTheSpellingOfThisPage": "Controlla l'ortografia di questa pagina",
|
||||
"tipShowOrHideTheFormatPanel": "Mostra o nascondi il pannello formato",
|
||||
"phReplaceWith": "Sostituisci con",
|
||||
"tipAddToYourDictionary": "Aggiungi al dizionario",
|
||||
"tipClose": "Chiudi",
|
||||
"phFind": "Trova",
|
||||
"tipPreviousMatch": "Corrispondenza precedente",
|
||||
"tipNextMatch": "Corrispondenza successiva",
|
||||
"tipRotateLeft90": "Ruota di 90° a sinistra",
|
||||
"tipRotateRight90": "Ruota di 90° a destra",
|
||||
"tipFlipHorizontal": "Capovolgi orizzontalmente",
|
||||
"tipFlipVertical": "Capovolgi verticalmente",
|
||||
"tipReplaceThisImageKeepingItsPlacement": "Sostituisci questa immagine mantenendone la posizione",
|
||||
"tipAlternateTextForAccessibilityTaggedPdfs": "Testo alternativo per l'accessibilità (PDF taggati)",
|
||||
"tipBringToFront": "Porta in primo piano",
|
||||
"tipSendToBack": "Porta in secondo piano",
|
||||
"tipDuplicate": "Duplica",
|
||||
"tipDelete": "Elimina",
|
||||
"tipAlignLeftEdges": "Allinea i bordi sinistri",
|
||||
"tipAlignHorizontalCenters": "Centra orizzontalmente",
|
||||
"tipAlignRightEdges": "Allinea i bordi destri",
|
||||
"tipAlignTops": "Allinea i bordi superiori",
|
||||
"tipAlignVerticalCenters": "Centra verticalmente",
|
||||
"tipAlignBottoms": "Allinea i bordi inferiori",
|
||||
"tipDistributeHorizontally": "Distribuisci orizzontalmente",
|
||||
"tipDistributeVertically": "Distribuisci verticalmente",
|
||||
"tipFontSize": "Dimensione carattere",
|
||||
"tipListFontsInstalledOnThisDeviceChromium": "Elenca i caratteri installati su questo dispositivo (Chromium)",
|
||||
"tipCustomTextColor": "Colore testo personalizzato",
|
||||
"tipAlignLeft": "Allinea a sinistra",
|
||||
"tipAlignCenter": "Centra",
|
||||
"tipAlignRight": "Allinea a destra",
|
||||
"tipJustify": "Giustifica",
|
||||
"tipBold": "Grassetto",
|
||||
"tipItalic": "Corsivo",
|
||||
"tipUnderline": "Sottolineato",
|
||||
"tipStrikethrough": "Barrato",
|
||||
"tipSuperscript": "Apice",
|
||||
"tipSubscript": "Pedice",
|
||||
"tipToggleBulletedItem": "Attiva/disattiva punto elenco",
|
||||
"tipToggleNumberedItem": "Attiva/disattiva elemento numerato",
|
||||
"tipNumberedListMarkerStyle": "Stile marcatore elenchi numerati",
|
||||
"tipDecreaseListIndentTab": "Riduci rientro (⇧Tab)",
|
||||
"tipIncreaseListIndentTab": "Aumenta rientro (Tab)",
|
||||
"tipTextOutlineColor": "Colore contorno testo",
|
||||
"tipOutlineWidth0None": "Spessore contorno (0 = nessuno)",
|
||||
"tipFromContent": "Dal contenuto",
|
||||
"tipLeftToRight": "Da sinistra a destra",
|
||||
"tipRightToLeft": "Da destra a sinistra",
|
||||
"tipStrokeColor": "Colore traccia",
|
||||
"tipStrokeWidth": "Spessore traccia",
|
||||
"tipZoomPresets": "Preimpostazioni zoom",
|
||||
"tipZoomOut": "Riduci zoom",
|
||||
"tipZoomIn": "Aumenta zoom",
|
||||
"tipFitPage": "Adatta pagina",
|
||||
"tipPreviousPage": "Pagina precedente",
|
||||
"tipTypeAPageNumberAndPressEnter": "Digita un numero di pagina e premi Invio",
|
||||
"tipNextPage": "Pagina successiva",
|
||||
"tipDocumentProperties": "Proprietà del documento",
|
||||
"tipHideBar": "Nascondi barra",
|
||||
"tipShowBar": "Mostra barra"
|
||||
},
|
||||
"jpgToPdf": {
|
||||
"name": "JPG in PDF",
|
||||
"subtitle": "Crea un PDF da immagini JPG, JPEG e JPEG2000 (JP2/JPX)."
|
||||
@@ -514,6 +632,51 @@
|
||||
"retainPageLabels": "Mantieni le etichette di pagina originali di ogni file",
|
||||
"retainPageLabelsHint": "Disattivato (predefinito): il PDF unito usa la numerazione naturale 1–N. Attivato: le etichette di pagina originali di ogni file vengono mantenute (può produrre etichette duplicate)."
|
||||
},
|
||||
"duplexCollate": {
|
||||
"name": "Fascicola scansione fronte/retro",
|
||||
"subtitle": "Riordina un PDF scansionato in due blocchi (prima tutti i fronti, poi tutti i retri) nel corretto ordine fronte/retro.",
|
||||
"totalPagesLabel": "Pagine totali:",
|
||||
"splitAfterPageLabel": "Dividi dopo la pagina",
|
||||
"splitAfterPagePlaceholder": "es. 50",
|
||||
"backBlockOrderLabel": "Ordine del blocco dei retri",
|
||||
"backBlockReverseOption": "Inverti il blocco dei retri (comune se la pila è stata girata)",
|
||||
"backBlockKeepOption": "Mantieni il blocco dei retri così com'è",
|
||||
"autoSplitButton": "Rileva divisione automaticamente (metà)",
|
||||
"exportGroupedLabel": "Esporta file raggruppati in base alla lunghezza del documento originale",
|
||||
"pagesPerDocumentLabel": "Pagine per documento originale",
|
||||
"groupedHelp": "Se attivo, il risultato è un file ZIP contenente un PDF per ogni documento raggruppato.",
|
||||
"collateButton": "Fascicola PDF",
|
||||
"invalidFileTitle": "File non valido",
|
||||
"invalidFileMessage": "Seleziona un file PDF.",
|
||||
"loadingPdf": "Caricamento del PDF...",
|
||||
"loadErrorMessage": "Impossibile caricare il file PDF.",
|
||||
"fileMeta": "{{size}} - {{count}} pagine",
|
||||
"oddPageWarning": "Numero di pagine dispari ({{count}}). Una scansione fronte/retro dovrebbe avere un numero pari di pagine: potrebbe mancarne una o essercene una in più.",
|
||||
"previewSummary": "Blocco fronti: {{frontCount}} pagina/e, blocco retri: {{backCount}} pagina/e. Risultato: {{outputCount}} pagina/e, in sequenza fronte/retro.",
|
||||
"previewMismatchWarning": "I blocchi fronte e retro hanno lunghezze diverse ({{frontCount}} fronti contro {{backCount}} retri). Le {{extraCount}} pagina/e in eccesso del blocco più lungo verranno aggiunte spaiate alla fine.",
|
||||
"missingFileTitle": "File mancante",
|
||||
"missingFileMessage": "Carica un PDF di almeno 2 pagine prima di procedere.",
|
||||
"invalidSplitTitle": "Punto di divisione non valido",
|
||||
"invalidSplitMessage": "Il punto di divisione deve essere compreso tra la pagina 1 e la pagina {{maxSplit}}.",
|
||||
"unevenConfirmTitle": "Blocchi disuguali",
|
||||
"unevenConfirmMessage": "Il blocco dei fronti ha {{frontCount}} pagina/e e quello dei retri {{backCount}} pagina/e.\nDi solito significa che una pagina è stata scansionata due volte o che ne manca una.\n\nLe {{extraCount}} pagina/e spaiate verranno aggiunte alla fine.\n\nContinuare comunque?",
|
||||
"invalidGroupTitle": "Dimensione del gruppo non valida",
|
||||
"invalidGroupMessage": "Inserisci un numero valido di pagine per documento originale.",
|
||||
"collatingLoader": "Fascicolazione della scansione fronte/retro...",
|
||||
"successMessage": "PDF fascicolato generato correttamente.",
|
||||
"successGroupedMessage": "Fascicolazione completata. Generati {{fileCount}} file raggruppati.",
|
||||
"processErrorMessage": "Impossibile fascicolare il PDF.",
|
||||
"howItWorksStep1Title": "Carica la scansione",
|
||||
"howItWorksStep1": "Trascina il PDF unico che contiene prima tutti i fronti e poi tutti i retri.",
|
||||
"howItWorksStep2Title": "Imposta il punto di divisione",
|
||||
"howItWorksStep2": "Indica dove finisce il blocco dei fronti, poi scegli se il blocco dei retri deve essere invertito.",
|
||||
"howItWorksStep3Title": "Fascicola e scarica",
|
||||
"howItWorksStep3": "Ottieni un PDF con le pagine alternate, oppure un file ZIP con un file separato per ogni documento originale.",
|
||||
"faqOddPagesQuestion": "E se la mia scansione ha un numero dispari di pagine?",
|
||||
"faqOddPagesAnswer": "Una scansione fronte/retro dovrebbe avere un numero pari di pagine. In caso contrario, probabilmente una pagina è stata scansionata due volte o saltata. Lo strumento ti avvisa prima di procedere e le pagine spaiate vengono aggiunte alla fine, così non si perde nulla.",
|
||||
"faqBackOrderQuestion": "Perché dovrei mantenere il blocco dei retri così com'è?",
|
||||
"faqBackOrderAnswer": "Dipende da come è stata inserita la pila nel secondo passaggio. Girando l'intera pila i retri risultano in ordine inverso, che è l'impostazione predefinita. Se il tuo scanner li ha restituiti nello stesso ordine dei fronti, scegli di mantenere il blocco così com'è."
|
||||
},
|
||||
"addAttachments": {
|
||||
"name": "Aggiungi Allegati",
|
||||
"subtitle": "Incorpora uno o più file nel tuo PDF."
|
||||
@@ -1151,5 +1314,13 @@
|
||||
"faqSinglePageAnswer": "Sì! Attiva l'opzione \"Ripeti\" e le pagine di sovrapposizione si ripeteranno su tutte le pagine base. Una filigrana di una pagina verrà applicata a ogni pagina.",
|
||||
"faqPrivacyQuestion": "I miei file sono privati e sicuri?",
|
||||
"faqPrivacyAnswer": "Assolutamente! Tutta l'elaborazione avviene nel tuo browser. I tuoi file non lasciano mai il tuo dispositivo, garantendo la massima privacy."
|
||||
},
|
||||
"unlockPdf": {
|
||||
"name": "Decrittografa PDF",
|
||||
"subtitle": "Sblocca il PDF rimuovendo la protezione tramite password."
|
||||
},
|
||||
"protectPdf": {
|
||||
"name": "Cripta PDF",
|
||||
"subtitle": "Proteggi il tuo PDF aggiungendo una password."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,7 +216,7 @@
|
||||
},
|
||||
"analytics": {
|
||||
"question": "私を追跡するためにCookieまたは分析を使用しますか?",
|
||||
"answer": "私たちはあなたのプライバシーを大切にしています。BentoPDFは個人情報を追跡しません。私たちは匿名の訪問数を確認するためにのみSimple Analyticsを使用します。これは私たちのサイトにアクセスしたユーザーの数を知ることはできますが、あなたが誰であるかは決して分からないことを意味します。 Simple AnalyticsはGDPRに完全に準拠しており、プライバシーを尊重します。"
|
||||
"answer": "いいえ。BentoPDF はあなたを一切追跡しません。Cookie、アナリティクス、トラッキングスクリプトは使用しておらず、公開サイト bentopdf.com でも同様です。あなたが誰で、ツールで何をしているかを私たちが知ることはありません。"
|
||||
}
|
||||
},
|
||||
"testimonials": {
|
||||
@@ -239,7 +239,9 @@
|
||||
"legal": "法的情報",
|
||||
"termsAndConditions": "利用規約",
|
||||
"privacyPolicy": "プライバシーポリシー",
|
||||
"followUs": "フォローする"
|
||||
"followUs": "フォローする",
|
||||
"privacyShort": "プライバシー",
|
||||
"termsShort": "利用規約"
|
||||
},
|
||||
"merge": {
|
||||
"title": "PDFの結合",
|
||||
@@ -287,6 +289,7 @@
|
||||
},
|
||||
"mission": {
|
||||
"title": "私たちの使命",
|
||||
"titleDim": " ",
|
||||
"description": "あなたのプライバシーを尊重し、決して支払いを要求しない、最も包括的なPDFツールボックスを提供すること。私たちは必須のドキュメントツールは誰でも、どこでも、障壁なくアクセスできるべきだと考えています。"
|
||||
},
|
||||
"philosophy": {
|
||||
@@ -350,9 +353,12 @@
|
||||
"download": "ダウンロード:",
|
||||
"downloadSelected": "選択したものをダウンロード",
|
||||
"exportPdf": "PDFをエクスポート",
|
||||
"uploadPdfFiles": "PDFファイルを選択",
|
||||
"dragAndDrop": "ここにPDFファイルをドラッグ&ドロップするかクリックして選択します",
|
||||
"uploadPdfFiles": "PDFまたは画像ファイルを選択",
|
||||
"dragAndDrop": "ここにPDFまたは画像ファイルをドラッグ&ドロップするかクリックして選択します",
|
||||
"selectFiles": "ファイルの選択",
|
||||
"dropToAdd": "PDFまたは画像ファイルをドロップして追加",
|
||||
"convertingImages": "画像をPDFに変換中...",
|
||||
"failedToConvertImages": "画像をPDFに変換できませんでした。",
|
||||
"renderingPages": "ページをレンダリング中...",
|
||||
"actions": {
|
||||
"duplicatePage": "このページを複製",
|
||||
|
||||
@@ -55,6 +55,124 @@
|
||||
"name": "PDFエディター",
|
||||
"subtitle": "PDFへの注釈追加、ハイライト、黒塗り、コメント、図形や画像の挿入、検索、および表示が可能です。"
|
||||
},
|
||||
"editPdfText": {
|
||||
"name": "PDFテキストの編集",
|
||||
"subtitle": "段落をクリックしてその場で編集。テキストは自動で再配置され、フォントやスタイルも変更できます。",
|
||||
"saved": "PDF を保存しました!({{size}} KB)",
|
||||
"failedToLoad": "PDF テキストエディタを読み込めませんでした。",
|
||||
"loadingFonts": "フォントを読み込み中...",
|
||||
"fontsUnavailable": "一部の文字に必要なフォントをダウンロードできませんでした。接続を確認してもう一度お試しください。このままでは、保存した PDF でそれらの文字が正しく表示されない可能性があります。",
|
||||
"howToUpload": "PDF をアップロード",
|
||||
"howToClick": "段落をクリック",
|
||||
"howToRestyle": "自由にスタイル変更",
|
||||
"relatedPdfEditor": "PDF に注釈やマークを追加",
|
||||
"relatedSignPdf": "署名を描く・入力・アップロード",
|
||||
"relatedWatermark": "テキストや画像を重ねる",
|
||||
"relatedStamps": "ページにスタンプを配置",
|
||||
"relatedCompress": "ファイルサイズを縮小",
|
||||
"relatedOrganizeName": "PDF を整理",
|
||||
"relatedOrganize": "ページの並べ替えと管理",
|
||||
"open": "開く",
|
||||
"export": "書き出し",
|
||||
"filterAll": "すべて",
|
||||
"filterText": "テキスト",
|
||||
"filterImages": "画像",
|
||||
"filterShapes": "図形",
|
||||
"addText": "テキストを追加",
|
||||
"langAuto": "自動",
|
||||
"change": "変更",
|
||||
"ignore": "無視",
|
||||
"next": "次へ",
|
||||
"replace": "置換",
|
||||
"replaceAll": "すべて置換",
|
||||
"emptyState": "PDF を開いて、テキスト・画像・図形を編集します。",
|
||||
"choosePdf": "PDF を選択…",
|
||||
"font": "フォント",
|
||||
"systemFonts": "システムフォント",
|
||||
"color": "色",
|
||||
"alignment": "配置",
|
||||
"style": "スタイル",
|
||||
"lists": "リスト",
|
||||
"outline": "アウトライン",
|
||||
"spacing": "間隔",
|
||||
"direction": "方向",
|
||||
"dirAuto": "自動",
|
||||
"pathStroke": "パスの線",
|
||||
"tipBackToUpload": "アップロードに戻る",
|
||||
"tipOpenAnotherPdf": "別の PDF を開く",
|
||||
"tipExportS": "書き出し (⌘S)",
|
||||
"tipUndoZ": "取り消す (⌘Z)",
|
||||
"tipRedoZ": "やり直す (⇧⌘Z)",
|
||||
"tipFileDetails": "ファイル情報",
|
||||
"tipEditExistingContent": "既存のコンテンツを編集",
|
||||
"tipWhatTheEditToolTouchesNarrowTheScopeOnBus": "編集ツールの対象範囲 — 要素の多いページでは範囲を絞り込みます",
|
||||
"tipClickThePageToAddATextBox": "ページをクリックしてテキストボックスを追加",
|
||||
"tipSpellCheckLanguage": "スペルチェックの言語",
|
||||
"tipFindAndReplace": "検索と置換",
|
||||
"tipAddAnImage": "画像を追加",
|
||||
"tipCopyThisPageSTextInReadingOrder": "このページのテキストを読み順でコピー",
|
||||
"tipCheckTheSpellingOfThisPage": "このページのスペルをチェック",
|
||||
"tipShowOrHideTheFormatPanel": "書式パネルの表示/非表示",
|
||||
"phReplaceWith": "置換後の文字列",
|
||||
"tipAddToYourDictionary": "辞書に追加",
|
||||
"tipClose": "閉じる",
|
||||
"phFind": "検索",
|
||||
"tipPreviousMatch": "前の一致",
|
||||
"tipNextMatch": "次の一致",
|
||||
"tipRotateLeft90": "左に 90° 回転",
|
||||
"tipRotateRight90": "右に 90° 回転",
|
||||
"tipFlipHorizontal": "左右反転",
|
||||
"tipFlipVertical": "上下反転",
|
||||
"tipReplaceThisImageKeepingItsPlacement": "配置を保ったままこの画像を置き換え",
|
||||
"tipAlternateTextForAccessibilityTaggedPdfs": "アクセシビリティ用の代替テキスト(タグ付き PDF)",
|
||||
"tipBringToFront": "最前面へ",
|
||||
"tipSendToBack": "最背面へ",
|
||||
"tipDuplicate": "複製",
|
||||
"tipDelete": "削除",
|
||||
"tipAlignLeftEdges": "左端を揃える",
|
||||
"tipAlignHorizontalCenters": "左右中央に揃える",
|
||||
"tipAlignRightEdges": "右端を揃える",
|
||||
"tipAlignTops": "上端を揃える",
|
||||
"tipAlignVerticalCenters": "上下中央に揃える",
|
||||
"tipAlignBottoms": "下端を揃える",
|
||||
"tipDistributeHorizontally": "左右に整列",
|
||||
"tipDistributeVertically": "上下に整列",
|
||||
"tipFontSize": "フォントサイズ",
|
||||
"tipListFontsInstalledOnThisDeviceChromium": "このデバイスにインストールされたフォントを一覧表示(Chromium)",
|
||||
"tipCustomTextColor": "カスタム文字色",
|
||||
"tipAlignLeft": "左揃え",
|
||||
"tipAlignCenter": "中央揃え",
|
||||
"tipAlignRight": "右揃え",
|
||||
"tipJustify": "両端揃え",
|
||||
"tipBold": "太字",
|
||||
"tipItalic": "斜体",
|
||||
"tipUnderline": "下線",
|
||||
"tipStrikethrough": "取り消し線",
|
||||
"tipSuperscript": "上付き文字",
|
||||
"tipSubscript": "下付き文字",
|
||||
"tipToggleBulletedItem": "箇条書き項目の切り替え",
|
||||
"tipToggleNumberedItem": "番号付き項目の切り替え",
|
||||
"tipNumberedListMarkerStyle": "番号付きリストの記号スタイル",
|
||||
"tipDecreaseListIndentTab": "インデントを減らす (⇧Tab)",
|
||||
"tipIncreaseListIndentTab": "インデントを増やす (Tab)",
|
||||
"tipTextOutlineColor": "文字の輪郭の色",
|
||||
"tipOutlineWidth0None": "輪郭の太さ(0 = なし)",
|
||||
"tipFromContent": "コンテンツから",
|
||||
"tipLeftToRight": "左から右",
|
||||
"tipRightToLeft": "右から左",
|
||||
"tipStrokeColor": "線の色",
|
||||
"tipStrokeWidth": "線の太さ",
|
||||
"tipZoomPresets": "ズームのプリセット",
|
||||
"tipZoomOut": "縮小",
|
||||
"tipZoomIn": "拡大",
|
||||
"tipFitPage": "ページに合わせる",
|
||||
"tipPreviousPage": "前のページ",
|
||||
"tipTypeAPageNumberAndPressEnter": "ページ番号を入力して Enter を押してください",
|
||||
"tipNextPage": "次のページ",
|
||||
"tipDocumentProperties": "ドキュメントのプロパティ",
|
||||
"tipHideBar": "バーを隠す",
|
||||
"tipShowBar": "バーを表示"
|
||||
},
|
||||
"jpgToPdf": {
|
||||
"name": "JPGからPDF",
|
||||
"subtitle": "JPG、JPEG、およびJPEG2000(JP2/JPX)形式の画像からPDFを作成します。"
|
||||
@@ -514,6 +632,51 @@
|
||||
"retainPageLabels": "各ファイルの元のページラベルを保持する",
|
||||
"retainPageLabelsHint": "オフ(デフォルト): マージされたPDFは1–Nの自然なページ番号を使用します。オン: 各ファイルの元のページラベルが保持されます(ラベルが重複する可能性があります)。"
|
||||
},
|
||||
"duplexCollate": {
|
||||
"name": "両面スキャンの並べ替え",
|
||||
"subtitle": "2つのブロック(先に表面すべて、次に裏面すべて)としてスキャンしたPDFを、正しい表面/裏面の順に並べ替えます。",
|
||||
"totalPagesLabel": "総ページ数:",
|
||||
"splitAfterPageLabel": "分割位置のページ",
|
||||
"splitAfterPagePlaceholder": "例: 50",
|
||||
"backBlockOrderLabel": "裏面ブロックの順序",
|
||||
"backBlockReverseOption": "裏面ブロックを逆順にする(束を裏返した場合に一般的)",
|
||||
"backBlockKeepOption": "裏面ブロックをそのままにする",
|
||||
"autoSplitButton": "分割位置を自動判定(半分)",
|
||||
"exportGroupedLabel": "元の文書のページ数ごとにファイルを分けて書き出す",
|
||||
"pagesPerDocumentLabel": "元の文書1件あたりのページ数",
|
||||
"groupedHelp": "有効にすると、分割された文書ごとに1つのPDFを含むZIPファイルが出力されます。",
|
||||
"collateButton": "PDFを並べ替え",
|
||||
"invalidFileTitle": "無効なファイル",
|
||||
"invalidFileMessage": "PDFファイルを選択してください。",
|
||||
"loadingPdf": "PDFを読み込んでいます...",
|
||||
"loadErrorMessage": "PDFファイルを読み込めませんでした。",
|
||||
"fileMeta": "{{size}} - {{count}} ページ",
|
||||
"oddPageWarning": "ページ数が奇数です({{count}} ページ)。両面スキャンのページ数は偶数になるはずです。ページの不足または重複の可能性があります。",
|
||||
"previewSummary": "表面ブロック: {{frontCount}} ページ、裏面ブロック: {{backCount}} ページ。出力: {{outputCount}} ページ(表面/裏面の順)。",
|
||||
"previewMismatchWarning": "表面と裏面のブロックのページ数が異なります(表面 {{frontCount}} ページ、裏面 {{backCount}} ページ)。多い側の余分な {{extraCount}} ページは、対にならないまま末尾に追加されます。",
|
||||
"missingFileTitle": "ファイルがありません",
|
||||
"missingFileMessage": "処理する前に、2ページ以上のPDFをアップロードしてください。",
|
||||
"invalidSplitTitle": "無効な分割位置",
|
||||
"invalidSplitMessage": "分割位置は1ページ目から{{maxSplit}}ページ目の間で指定してください。",
|
||||
"unevenConfirmTitle": "ブロックのページ数が不一致",
|
||||
"unevenConfirmMessage": "表面ブロックは {{frontCount}} ページ、裏面ブロックは {{backCount}} ページです。\n通常、これはページが二重にスキャンされたか、不足していることを意味します。\n\n対にならない {{extraCount}} ページは末尾に追加されます。\n\nこのまま続行しますか?",
|
||||
"invalidGroupTitle": "無効なグループサイズ",
|
||||
"invalidGroupMessage": "元の文書1件あたりの有効なページ数を入力してください。",
|
||||
"collatingLoader": "両面スキャンを並べ替えています...",
|
||||
"successMessage": "並べ替えたPDFを作成しました。",
|
||||
"successGroupedMessage": "並べ替えが完了しました。{{fileCount}} 個のファイルを作成しました。",
|
||||
"processErrorMessage": "PDFを並べ替えられませんでした。",
|
||||
"howItWorksStep1Title": "スキャンをアップロード",
|
||||
"howItWorksStep1": "表面すべての後に裏面すべてが並んだ1つのPDFをドロップします。",
|
||||
"howItWorksStep2Title": "分割位置を設定",
|
||||
"howItWorksStep2": "表面ブロックが終わる位置を指定し、裏面ブロックを逆順にする必要があるかを選びます。",
|
||||
"howItWorksStep3Title": "並べ替えてダウンロード",
|
||||
"howItWorksStep3": "ページを交互に並べた1つのPDF、または元の文書ごとにファイルを分けたZIPを取得できます。",
|
||||
"faqOddPagesQuestion": "スキャンのページ数が奇数の場合はどうなりますか?",
|
||||
"faqOddPagesAnswer": "両面スキャンのページ数は偶数になるはずです。そうでない場合は、ページが二重にスキャンされたか、読み取られなかった可能性があります。処理前に警告が表示され、対にならないページは末尾に追加されるため、失われるものはありません。",
|
||||
"faqBackOrderQuestion": "裏面ブロックをそのままにするのはどのような場合ですか?",
|
||||
"faqBackOrderAnswer": "2回目の読み取りで束をどのようにセットしたかによります。束全体を裏返すと裏面は逆順になり、これが既定の設定です。スキャナーが表面と同じ順序で出力した場合は、ブロックをそのままにする方を選んでください。"
|
||||
},
|
||||
"addAttachments": {
|
||||
"name": "添付ファイルの追加",
|
||||
"subtitle": "1つ以上のファイルをPDFに埋め込みます。"
|
||||
@@ -1151,5 +1314,13 @@
|
||||
"faqSinglePageAnswer": "はい! 「ループ」オプションを有効にすると、オーバーレイPDFページがすべてのベース ページにわたって繰り返されます。単一ページのウォーターマークはすべてのページに適用されます。",
|
||||
"faqPrivacyQuestion": "私のファイルは非公開で安全ですか?",
|
||||
"faqPrivacyAnswer": "絶対に!すべての処理はブラウザ内で行われます。ファイルがデバイスの外に出ることはなく、完全なプライバシーが確保されます。"
|
||||
},
|
||||
"unlockPdf": {
|
||||
"name": "PDFの復号化",
|
||||
"subtitle": "パスワード保護を解除してPDFのロックを解除します。"
|
||||
},
|
||||
"protectPdf": {
|
||||
"name": "PDFの暗号化",
|
||||
"subtitle": "パスワードを追加してPDFをロックします。"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -216,13 +216,13 @@
|
||||
},
|
||||
"analytics": {
|
||||
"question": "쿠키나 분석 도구로 사용자를 추적하나요?",
|
||||
"answer": "여러분의 프라이버시를 소중히 여깁니다. BentoPDF는 개인정보를 추적하지 않으며, 익명 방문 수 확인만을 위해 Simple Analytics를 사용합니다. 방문자 수는 알 수 있지만 누가 방문했는지는 절대 알 수 없습니다. Simple Analytics는 GDPR을 완전히 준수합니다."
|
||||
"answer": "아니요. BentoPDF는 사용자를 전혀 추적하지 않습니다. 쿠키, 분석 도구, 추적 스크립트를 사용하지 않으며, 실제 웹사이트 bentopdf.com에서도 마찬가지입니다. 저희는 사용자가 누구인지, 도구로 무엇을 하는지 결코 알 수 없습니다."
|
||||
}
|
||||
},
|
||||
"testimonials": {
|
||||
"title": "사용자",
|
||||
"users": "후기",
|
||||
"say": ""
|
||||
"say": " "
|
||||
},
|
||||
"support": {
|
||||
"title": "도움이 되셨나요?",
|
||||
@@ -239,7 +239,9 @@
|
||||
"legal": "법적 고지",
|
||||
"termsAndConditions": "이용약관",
|
||||
"privacyPolicy": "개인정보처리방침",
|
||||
"followUs": "팔로우"
|
||||
"followUs": "팔로우",
|
||||
"privacyShort": "개인정보",
|
||||
"termsShort": "이용약관"
|
||||
},
|
||||
"merge": {
|
||||
"title": "PDF 병합",
|
||||
@@ -286,7 +288,8 @@
|
||||
"noCompromises": "타협 없이."
|
||||
},
|
||||
"mission": {
|
||||
"title": "우리의 목표",
|
||||
"title": "우리의",
|
||||
"titleDim": "목표",
|
||||
"description": "프라이버시를 지키면서도 비용 부담 없는, 가장 완벽한 PDF 도구를 만드는 것입니다. 꼭 필요한 문서 도구는 누구나, 어디서든 자유롭게 쓸 수 있어야 합니다."
|
||||
},
|
||||
"philosophy": {
|
||||
@@ -350,9 +353,12 @@
|
||||
"download": "다운로드:",
|
||||
"downloadSelected": "선택 항목 다운로드",
|
||||
"exportPdf": "PDF 내보내기",
|
||||
"uploadPdfFiles": "PDF 파일 선택",
|
||||
"dragAndDrop": "PDF 파일을 여기에 끌어다 놓거나 클릭하여 선택하세요",
|
||||
"uploadPdfFiles": "PDF 또는 이미지 파일 선택",
|
||||
"dragAndDrop": "PDF 또는 이미지 파일을 여기에 끌어다 놓거나 클릭하여 선택하세요",
|
||||
"selectFiles": "파일 선택",
|
||||
"dropToAdd": "PDF 또는 이미지 파일을 놓아 추가",
|
||||
"convertingImages": "이미지를 PDF로 변환 중...",
|
||||
"failedToConvertImages": "이미지를 PDF로 변환하지 못했습니다.",
|
||||
"renderingPages": "페이지 렌더링 중...",
|
||||
"actions": {
|
||||
"duplicatePage": "이 페이지 복제",
|
||||
|
||||
@@ -55,6 +55,124 @@
|
||||
"name": "PDF 편집기",
|
||||
"subtitle": "주석, 하이라이트, 마스킹, 댓글, 도형/이미지 추가, 검색 및 보기."
|
||||
},
|
||||
"editPdfText": {
|
||||
"name": "PDF 텍스트 편집",
|
||||
"subtitle": "아무 단락이나 클릭해 실시간 리플로우, 글꼴, 스타일과 함께 바로 편집하세요.",
|
||||
"saved": "PDF를 저장했습니다! ({{size}} KB)",
|
||||
"failedToLoad": "PDF 텍스트 편집기를 불러오지 못했습니다.",
|
||||
"loadingFonts": "글꼴을 불러오는 중...",
|
||||
"fontsUnavailable": "일부 문자에 필요한 글꼴을 다운로드하지 못했습니다. 연결을 확인하고 다시 시도하세요. 그렇지 않으면 저장된 PDF에서 해당 문자가 올바르게 표시되지 않을 수 있습니다.",
|
||||
"howToUpload": "PDF 업로드",
|
||||
"howToClick": "문단 클릭",
|
||||
"howToRestyle": "무엇이든 스타일 변경",
|
||||
"relatedPdfEditor": "PDF에 주석 달고 표시하기",
|
||||
"relatedSignPdf": "서명 그리기, 입력 또는 업로드",
|
||||
"relatedWatermark": "텍스트나 이미지 찍기",
|
||||
"relatedStamps": "페이지에 스탬프 배치",
|
||||
"relatedCompress": "파일 크기 줄이기",
|
||||
"relatedOrganizeName": "PDF 정리",
|
||||
"relatedOrganize": "페이지 순서 변경 및 관리",
|
||||
"open": "열기",
|
||||
"export": "내보내기",
|
||||
"filterAll": "전체",
|
||||
"filterText": "텍스트",
|
||||
"filterImages": "이미지",
|
||||
"filterShapes": "도형",
|
||||
"addText": "텍스트 추가",
|
||||
"langAuto": "자동",
|
||||
"change": "변경",
|
||||
"ignore": "무시",
|
||||
"next": "다음",
|
||||
"replace": "바꾸기",
|
||||
"replaceAll": "모두 바꾸기",
|
||||
"emptyState": "PDF를 열어 텍스트, 이미지, 도형을 편집하세요.",
|
||||
"choosePdf": "PDF 선택…",
|
||||
"font": "글꼴",
|
||||
"systemFonts": "시스템 글꼴",
|
||||
"color": "색상",
|
||||
"alignment": "정렬",
|
||||
"style": "스타일",
|
||||
"lists": "목록",
|
||||
"outline": "윤곽선",
|
||||
"spacing": "간격",
|
||||
"direction": "방향",
|
||||
"dirAuto": "자동",
|
||||
"pathStroke": "패스 선",
|
||||
"tipBackToUpload": "업로드로 돌아가기",
|
||||
"tipOpenAnotherPdf": "다른 PDF 열기",
|
||||
"tipExportS": "내보내기 (⌘S)",
|
||||
"tipUndoZ": "실행 취소 (⌘Z)",
|
||||
"tipRedoZ": "다시 실행 (⇧⌘Z)",
|
||||
"tipFileDetails": "파일 정보",
|
||||
"tipEditExistingContent": "기존 콘텐츠 편집",
|
||||
"tipWhatTheEditToolTouchesNarrowTheScopeOnBus": "편집 도구가 적용되는 대상 — 복잡한 페이지에서는 범위를 좁히세요",
|
||||
"tipClickThePageToAddATextBox": "페이지를 클릭해 텍스트 상자를 추가하세요",
|
||||
"tipSpellCheckLanguage": "맞춤법 검사 언어",
|
||||
"tipFindAndReplace": "찾기 및 바꾸기",
|
||||
"tipAddAnImage": "이미지 추가",
|
||||
"tipCopyThisPageSTextInReadingOrder": "이 페이지의 텍스트를 읽기 순서대로 복사",
|
||||
"tipCheckTheSpellingOfThisPage": "이 페이지의 맞춤법 검사",
|
||||
"tipShowOrHideTheFormatPanel": "서식 패널 표시/숨기기",
|
||||
"phReplaceWith": "바꿀 내용",
|
||||
"tipAddToYourDictionary": "사전에 추가",
|
||||
"tipClose": "닫기",
|
||||
"phFind": "찾기",
|
||||
"tipPreviousMatch": "이전 일치 항목",
|
||||
"tipNextMatch": "다음 일치 항목",
|
||||
"tipRotateLeft90": "왼쪽으로 90° 회전",
|
||||
"tipRotateRight90": "오른쪽으로 90° 회전",
|
||||
"tipFlipHorizontal": "좌우 반전",
|
||||
"tipFlipVertical": "상하 반전",
|
||||
"tipReplaceThisImageKeepingItsPlacement": "위치를 유지한 채 이 이미지 바꾸기",
|
||||
"tipAlternateTextForAccessibilityTaggedPdfs": "접근성을 위한 대체 텍스트(태그된 PDF)",
|
||||
"tipBringToFront": "맨 앞으로 가져오기",
|
||||
"tipSendToBack": "맨 뒤로 보내기",
|
||||
"tipDuplicate": "복제",
|
||||
"tipDelete": "삭제",
|
||||
"tipAlignLeftEdges": "왼쪽 가장자리 정렬",
|
||||
"tipAlignHorizontalCenters": "가로 가운데 정렬",
|
||||
"tipAlignRightEdges": "오른쪽 가장자리 정렬",
|
||||
"tipAlignTops": "위쪽 가장자리 정렬",
|
||||
"tipAlignVerticalCenters": "세로 가운데 정렬",
|
||||
"tipAlignBottoms": "아래쪽 가장자리 정렬",
|
||||
"tipDistributeHorizontally": "가로로 균등 배분",
|
||||
"tipDistributeVertically": "세로로 균등 배분",
|
||||
"tipFontSize": "글꼴 크기",
|
||||
"tipListFontsInstalledOnThisDeviceChromium": "이 기기에 설치된 글꼴 목록 보기(Chromium)",
|
||||
"tipCustomTextColor": "사용자 지정 텍스트 색",
|
||||
"tipAlignLeft": "왼쪽 정렬",
|
||||
"tipAlignCenter": "가운데 정렬",
|
||||
"tipAlignRight": "오른쪽 정렬",
|
||||
"tipJustify": "양쪽 정렬",
|
||||
"tipBold": "굵게",
|
||||
"tipItalic": "기울임꼴",
|
||||
"tipUnderline": "밑줄",
|
||||
"tipStrikethrough": "취소선",
|
||||
"tipSuperscript": "위 첨자",
|
||||
"tipSubscript": "아래 첨자",
|
||||
"tipToggleBulletedItem": "글머리 기호 켜기/끄기",
|
||||
"tipToggleNumberedItem": "번호 매기기 켜기/끄기",
|
||||
"tipNumberedListMarkerStyle": "번호 매기기 기호 스타일",
|
||||
"tipDecreaseListIndentTab": "들여쓰기 줄이기 (⇧Tab)",
|
||||
"tipIncreaseListIndentTab": "들여쓰기 늘리기 (Tab)",
|
||||
"tipTextOutlineColor": "텍스트 윤곽선 색",
|
||||
"tipOutlineWidth0None": "윤곽선 두께(0 = 없음)",
|
||||
"tipFromContent": "콘텐츠에서",
|
||||
"tipLeftToRight": "왼쪽에서 오른쪽",
|
||||
"tipRightToLeft": "오른쪽에서 왼쪽",
|
||||
"tipStrokeColor": "선 색",
|
||||
"tipStrokeWidth": "선 두께",
|
||||
"tipZoomPresets": "확대/축소 사전 설정",
|
||||
"tipZoomOut": "축소",
|
||||
"tipZoomIn": "확대",
|
||||
"tipFitPage": "페이지 맞춤",
|
||||
"tipPreviousPage": "이전 페이지",
|
||||
"tipTypeAPageNumberAndPressEnter": "페이지 번호를 입력하고 Enter를 누르세요",
|
||||
"tipNextPage": "다음 페이지",
|
||||
"tipDocumentProperties": "문서 속성",
|
||||
"tipHideBar": "막대 숨기기",
|
||||
"tipShowBar": "막대 표시"
|
||||
},
|
||||
"jpgToPdf": {
|
||||
"name": "JPG를 PDF로",
|
||||
"subtitle": "JPG, JPEG, JPEG2000(JP2/JPX) 이미지로 PDF를 만듭니다."
|
||||
@@ -514,6 +632,51 @@
|
||||
"retainPageLabels": "각 파일의 원래 페이지 레이블 유지",
|
||||
"retainPageLabelsHint": "꺼짐(기본): 병합된 PDF는 1–N의 자연스러운 페이지 번호를 사용합니다. 켜짐: 각 파일의 원래 페이지 레이블이 유지됩니다(중복 레이블이 발생할 수 있음)."
|
||||
},
|
||||
"duplexCollate": {
|
||||
"name": "양면 스캔 정렬",
|
||||
"subtitle": "두 묶음(앞면 전체, 그다음 뒷면 전체)으로 스캔한 PDF를 올바른 앞/뒤 순서로 재정렬합니다.",
|
||||
"totalPagesLabel": "전체 페이지:",
|
||||
"splitAfterPageLabel": "분할 기준 페이지",
|
||||
"splitAfterPagePlaceholder": "예: 50",
|
||||
"backBlockOrderLabel": "뒷면 묶음 순서",
|
||||
"backBlockReverseOption": "뒷면 묶음 뒤집기 (용지를 뒤집어 스캔한 경우 일반적)",
|
||||
"backBlockKeepOption": "뒷면 묶음 그대로 두기",
|
||||
"autoSplitButton": "분할 지점 자동 감지 (절반)",
|
||||
"exportGroupedLabel": "원본 문서 길이에 따라 파일을 나누어 내보내기",
|
||||
"pagesPerDocumentLabel": "원본 문서당 페이지 수",
|
||||
"groupedHelp": "사용하면 나뉜 문서마다 PDF 하나씩 담긴 ZIP 파일로 저장됩니다.",
|
||||
"collateButton": "PDF 정렬",
|
||||
"invalidFileTitle": "잘못된 파일",
|
||||
"invalidFileMessage": "PDF 파일을 선택하세요.",
|
||||
"loadingPdf": "PDF 불러오는 중...",
|
||||
"loadErrorMessage": "PDF 파일을 불러오지 못했습니다.",
|
||||
"fileMeta": "{{size}} - {{count}}페이지",
|
||||
"oddPageWarning": "페이지 수가 홀수입니다({{count}}페이지). 양면 스캔은 페이지 수가 짝수여야 합니다. 페이지가 누락되었거나 중복되었을 수 있습니다.",
|
||||
"previewSummary": "앞면 묶음: {{frontCount}}페이지, 뒷면 묶음: {{backCount}}페이지. 결과: 앞/뒤 순서로 {{outputCount}}페이지.",
|
||||
"previewMismatchWarning": "앞면과 뒷면 묶음의 길이가 다릅니다(앞면 {{frontCount}}페이지, 뒷면 {{backCount}}페이지). 더 긴 쪽의 남은 {{extraCount}}페이지는 짝 없이 맨 뒤에 추가됩니다.",
|
||||
"missingFileTitle": "파일 없음",
|
||||
"missingFileMessage": "처리하기 전에 2페이지 이상인 PDF를 업로드하세요.",
|
||||
"invalidSplitTitle": "잘못된 분할 지점",
|
||||
"invalidSplitMessage": "분할 지점은 1페이지에서 {{maxSplit}}페이지 사이여야 합니다.",
|
||||
"unevenConfirmTitle": "묶음 길이 불일치",
|
||||
"unevenConfirmMessage": "앞면 묶음은 {{frontCount}}페이지, 뒷면 묶음은 {{backCount}}페이지입니다.\n보통 페이지가 두 번 스캔되었거나 누락되었다는 뜻입니다.\n\n짝이 없는 {{extraCount}}페이지는 맨 뒤에 추가됩니다.\n\n계속하시겠습니까?",
|
||||
"invalidGroupTitle": "잘못된 그룹 크기",
|
||||
"invalidGroupMessage": "원본 문서당 페이지 수를 올바르게 입력하세요.",
|
||||
"collatingLoader": "양면 스캔 정렬 중...",
|
||||
"successMessage": "정렬된 PDF를 만들었습니다.",
|
||||
"successGroupedMessage": "정렬이 완료되었습니다. {{fileCount}}개 파일을 만들었습니다.",
|
||||
"processErrorMessage": "PDF를 정렬하지 못했습니다.",
|
||||
"howItWorksStep1Title": "스캔 업로드",
|
||||
"howItWorksStep1": "앞면 전체 다음에 뒷면 전체가 들어 있는 PDF 한 개를 놓으세요.",
|
||||
"howItWorksStep2Title": "분할 지점 설정",
|
||||
"howItWorksStep2": "앞면 묶음이 끝나는 위치를 지정한 뒤, 뒷면 묶음을 뒤집어야 하는지 선택하세요.",
|
||||
"howItWorksStep3Title": "정렬 후 다운로드",
|
||||
"howItWorksStep3": "페이지가 번갈아 배치된 PDF 하나를 받거나, 원본 문서마다 파일이 나뉜 ZIP을 받으세요.",
|
||||
"faqOddPagesQuestion": "스캔한 페이지 수가 홀수이면 어떻게 되나요?",
|
||||
"faqOddPagesAnswer": "양면 스캔은 페이지 수가 짝수여야 합니다. 그렇지 않다면 한 페이지가 두 번 스캔되었거나 빠졌을 가능성이 큽니다. 처리 전에 경고가 표시되며, 짝이 없는 페이지는 맨 뒤에 추가되므로 사라지는 내용은 없습니다.",
|
||||
"faqBackOrderQuestion": "뒷면 묶음을 그대로 두는 경우는 언제인가요?",
|
||||
"faqBackOrderAnswer": "두 번째 스캔에서 용지를 어떻게 넣었는지에 따라 다릅니다. 전체 묶음을 뒤집으면 뒷면이 역순이 되며, 이것이 기본 설정입니다. 스캐너가 앞면과 같은 순서로 출력했다면 묶음을 그대로 두도록 선택하세요."
|
||||
},
|
||||
"addAttachments": {
|
||||
"name": "첨부파일 추가",
|
||||
"subtitle": "PDF에 파일을 첨부합니다."
|
||||
@@ -1151,5 +1314,13 @@
|
||||
"faqSinglePageAnswer": "네! \"반복\" 옵션을 활성화하면 오버레이 페이지가 모든 기본 페이지에 반복됩니다. 단일 페이지 워터마크가 모든 페이지에 적용됩니다.",
|
||||
"faqPrivacyQuestion": "내 파일은 비공개이고 안전한가요?",
|
||||
"faqPrivacyAnswer": "물론입니다! 모든 처리는 브라우저에서 이루어집니다. 파일이 기기를 떠나지 않아 완전한 개인정보 보호가 보장됩니다."
|
||||
},
|
||||
"unlockPdf": {
|
||||
"name": "PDF 복호화",
|
||||
"subtitle": "비밀번호를 제거하여 PDF 잠금을 해제합니다."
|
||||
},
|
||||
"protectPdf": {
|
||||
"name": "PDF 암호화",
|
||||
"subtitle": "비밀번호를 설정하여 PDF를 보호합니다."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"nav": {
|
||||
"home": "Thuis",
|
||||
"home": "Startpagina",
|
||||
"about": "Over",
|
||||
"contact": "Contact",
|
||||
"licensing": "Licentie",
|
||||
@@ -216,7 +216,7 @@
|
||||
},
|
||||
"analytics": {
|
||||
"question": "Gebruikt BentoPDF cookies of analytics om mij te volgen?",
|
||||
"answer": "We geven om je privacy. BentoPDF houdt geen persoonlijke gegevens bij. We gebruiken Simple Analytics alleen om anonieme bezoekersaantallen te zien. Dit betekent dat we kunnen weten hoeveel mensen onze site bezoeken, maar we weten nooit wie jij bent. Simple Analytics is volledig AVG-conform en respecteert je privacy."
|
||||
"answer": "Nee. BentoPDF volgt je helemaal niet. We gebruiken geen cookies, analytics of trackingscripts – ook niet op de live website bentopdf.com. We weten nooit wie je bent of wat je met de tools doet."
|
||||
}
|
||||
},
|
||||
"testimonials": {
|
||||
@@ -239,7 +239,9 @@
|
||||
"legal": "Juridisch",
|
||||
"termsAndConditions": "Algemene voorwaarden",
|
||||
"privacyPolicy": "Privacybeleid",
|
||||
"followUs": "Volgen"
|
||||
"followUs": "Volgen",
|
||||
"privacyShort": "Privacy",
|
||||
"termsShort": "Voorwaarden"
|
||||
},
|
||||
"merge": {
|
||||
"title": "PDF's samenvoegen",
|
||||
@@ -286,7 +288,8 @@
|
||||
"noCompromises": "Geen compromissen."
|
||||
},
|
||||
"mission": {
|
||||
"title": "Onze missie",
|
||||
"title": "Onze",
|
||||
"titleDim": "missie",
|
||||
"description": "Ons doel is om de meest complete PDF-toolbox te bieden die je privacy respecteert en nooit om betaling vraagt. Wij geloven dat essentiële documententools voor iedereen, overal en zonder obstakels toegankelijk moeten zijn."
|
||||
},
|
||||
"philosophy": {
|
||||
@@ -350,9 +353,12 @@
|
||||
"download": "Laden:",
|
||||
"downloadSelected": "Selectie laden",
|
||||
"exportPdf": "PDF exporteren",
|
||||
"uploadPdfFiles": "PDF-bestanden selecteren",
|
||||
"dragAndDrop": "Klik om een bestand te selecteren, of sleep er een hierheen",
|
||||
"uploadPdfFiles": "PDF- of afbeeldingsbestanden selecteren",
|
||||
"dragAndDrop": "Klik om een bestand te selecteren, of sleep een PDF of afbeelding hierheen",
|
||||
"selectFiles": "Bestanden selecteren",
|
||||
"dropToAdd": "Sleep PDF- of afbeeldingsbestanden om toe te voegen",
|
||||
"convertingImages": "Afbeeldingen omzetten naar PDF...",
|
||||
"failedToConvertImages": "Afbeeldingen omzetten naar PDF mislukt.",
|
||||
"renderingPages": "Pagina's verwerken…",
|
||||
"actions": {
|
||||
"duplicatePage": "Deze pagina dupliceren",
|
||||
@@ -379,6 +385,6 @@
|
||||
"title": "Tool niet beschikbaar",
|
||||
"heading": "Deze tool is uitgeschakeld",
|
||||
"message": "Deze tool is niet beschikbaar in deze implementatie. Neem contact op met de beheerder voor meer informatie.",
|
||||
"backHome": "Terug naar Thuis"
|
||||
"backHome": "Terug naar Startpagina"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,124 @@
|
||||
"name": "PDF Bewerken",
|
||||
"subtitle": "PDF's annoteren, markeren, redigeren, commentaar toevoegen, vormen/afbeelding toevoegen, doorzoeken and weergeven."
|
||||
},
|
||||
"editPdfText": {
|
||||
"name": "PDF-tekst Bewerken",
|
||||
"subtitle": "Klik op een alinea en bewerk deze direct, met live tekstomloop, lettertypen en opmaak.",
|
||||
"saved": "PDF is opgeslagen! ({{size}} KB)",
|
||||
"failedToLoad": "Kan de PDF-teksteditor niet laden.",
|
||||
"loadingFonts": "Lettertypen laden…",
|
||||
"fontsUnavailable": "Een lettertype dat nodig is voor sommige tekens kon niet worden gedownload. Controleer de verbinding en probeer het opnieuw, anders worden deze tekens mogelijk niet correct weergegeven in de opgeslagen PDF.",
|
||||
"howToUpload": "PDF uploaden",
|
||||
"howToClick": "Klik op een alinea",
|
||||
"howToRestyle": "Alles opnieuw vormgeven",
|
||||
"relatedPdfEditor": "PDF's annoteren en markeren",
|
||||
"relatedSignPdf": "Handtekening tekenen, typen of uploaden",
|
||||
"relatedWatermark": "Tekst of afbeeldingen stempelen",
|
||||
"relatedStamps": "Stempels op pagina's plaatsen",
|
||||
"relatedCompress": "Bestandsgrootte verkleinen",
|
||||
"relatedOrganizeName": "PDF ordenen",
|
||||
"relatedOrganize": "Pagina's herschikken en beheren",
|
||||
"open": "Openen",
|
||||
"export": "Exporteren",
|
||||
"filterAll": "Alles",
|
||||
"filterText": "Tekst",
|
||||
"filterImages": "Afbeeldingen",
|
||||
"filterShapes": "Vormen",
|
||||
"addText": "Tekst toevoegen",
|
||||
"langAuto": "Automatisch",
|
||||
"change": "Wijzigen",
|
||||
"ignore": "Negeren",
|
||||
"next": "Volgende",
|
||||
"replace": "Vervangen",
|
||||
"replaceAll": "Alles vervangen",
|
||||
"emptyState": "Open een PDF om de tekst, afbeeldingen en vormen te bewerken.",
|
||||
"choosePdf": "Kies een PDF…",
|
||||
"font": "Lettertype",
|
||||
"systemFonts": "Systeemlettertypen",
|
||||
"color": "Kleur",
|
||||
"alignment": "Uitlijning",
|
||||
"style": "Stijl",
|
||||
"lists": "Lijsten",
|
||||
"outline": "Omtrek",
|
||||
"spacing": "Afstand",
|
||||
"direction": "Richting",
|
||||
"dirAuto": "Automatisch",
|
||||
"pathStroke": "Padomtrek",
|
||||
"tipBackToUpload": "Terug naar uploaden",
|
||||
"tipOpenAnotherPdf": "Nog een PDF openen",
|
||||
"tipExportS": "Exporteren (⌘S)",
|
||||
"tipUndoZ": "Ongedaan maken (⌘Z)",
|
||||
"tipRedoZ": "Opnieuw (⇧⌘Z)",
|
||||
"tipFileDetails": "Bestandsgegevens",
|
||||
"tipEditExistingContent": "Bestaande inhoud bewerken",
|
||||
"tipWhatTheEditToolTouchesNarrowTheScopeOnBus": "Wat het hulpmiddel Bewerken raakt — beperk het bereik op drukke pagina's",
|
||||
"tipClickThePageToAddATextBox": "Klik op de pagina om een tekstvak toe te voegen",
|
||||
"tipSpellCheckLanguage": "Taal van de spellingcontrole",
|
||||
"tipFindAndReplace": "Zoeken en vervangen",
|
||||
"tipAddAnImage": "Een afbeelding toevoegen",
|
||||
"tipCopyThisPageSTextInReadingOrder": "Tekst van deze pagina in leesvolgorde kopiëren",
|
||||
"tipCheckTheSpellingOfThisPage": "Spelling van deze pagina controleren",
|
||||
"tipShowOrHideTheFormatPanel": "Opmaakpaneel tonen of verbergen",
|
||||
"phReplaceWith": "Vervangen door",
|
||||
"tipAddToYourDictionary": "Aan woordenboek toevoegen",
|
||||
"tipClose": "Sluiten",
|
||||
"phFind": "Zoeken",
|
||||
"tipPreviousMatch": "Vorige overeenkomst",
|
||||
"tipNextMatch": "Volgende overeenkomst",
|
||||
"tipRotateLeft90": "90° naar links draaien",
|
||||
"tipRotateRight90": "90° naar rechts draaien",
|
||||
"tipFlipHorizontal": "Horizontaal spiegelen",
|
||||
"tipFlipVertical": "Verticaal spiegelen",
|
||||
"tipReplaceThisImageKeepingItsPlacement": "Deze afbeelding vervangen met behoud van plaatsing",
|
||||
"tipAlternateTextForAccessibilityTaggedPdfs": "Alternatieve tekst voor toegankelijkheid (getagde PDF's)",
|
||||
"tipBringToFront": "Naar voorgrond",
|
||||
"tipSendToBack": "Naar achtergrond",
|
||||
"tipDuplicate": "Dupliceren",
|
||||
"tipDelete": "Verwijderen",
|
||||
"tipAlignLeftEdges": "Linkerranden uitlijnen",
|
||||
"tipAlignHorizontalCenters": "Horizontaal centreren",
|
||||
"tipAlignRightEdges": "Rechterranden uitlijnen",
|
||||
"tipAlignTops": "Bovenranden uitlijnen",
|
||||
"tipAlignVerticalCenters": "Verticaal centreren",
|
||||
"tipAlignBottoms": "Onderranden uitlijnen",
|
||||
"tipDistributeHorizontally": "Horizontaal verdelen",
|
||||
"tipDistributeVertically": "Verticaal verdelen",
|
||||
"tipFontSize": "Tekengrootte",
|
||||
"tipListFontsInstalledOnThisDeviceChromium": "Lettertypen op dit apparaat weergeven (Chromium)",
|
||||
"tipCustomTextColor": "Aangepaste tekstkleur",
|
||||
"tipAlignLeft": "Links uitlijnen",
|
||||
"tipAlignCenter": "Centreren",
|
||||
"tipAlignRight": "Rechts uitlijnen",
|
||||
"tipJustify": "Uitvullen",
|
||||
"tipBold": "Vet",
|
||||
"tipItalic": "Cursief",
|
||||
"tipUnderline": "Onderstrepen",
|
||||
"tipStrikethrough": "Doorhalen",
|
||||
"tipSuperscript": "Superscript",
|
||||
"tipSubscript": "Subscript",
|
||||
"tipToggleBulletedItem": "Opsommingsteken in-/uitschakelen",
|
||||
"tipToggleNumberedItem": "Genummerd item in-/uitschakelen",
|
||||
"tipNumberedListMarkerStyle": "Markeringsstijl voor genummerde lijsten",
|
||||
"tipDecreaseListIndentTab": "Inspringing verkleinen (⇧Tab)",
|
||||
"tipIncreaseListIndentTab": "Inspringing vergroten (Tab)",
|
||||
"tipTextOutlineColor": "Kleur tekstomtrek",
|
||||
"tipOutlineWidth0None": "Omtrekbreedte (0 = geen)",
|
||||
"tipFromContent": "Uit inhoud",
|
||||
"tipLeftToRight": "Van links naar rechts",
|
||||
"tipRightToLeft": "Van rechts naar links",
|
||||
"tipStrokeColor": "Lijnkleur",
|
||||
"tipStrokeWidth": "Lijndikte",
|
||||
"tipZoomPresets": "Zoomvoorinstellingen",
|
||||
"tipZoomOut": "Uitzoomen",
|
||||
"tipZoomIn": "Inzoomen",
|
||||
"tipFitPage": "Pagina passend maken",
|
||||
"tipPreviousPage": "Vorige pagina",
|
||||
"tipTypeAPageNumberAndPressEnter": "Typ een paginanummer en druk op Enter",
|
||||
"tipNextPage": "Volgende pagina",
|
||||
"tipDocumentProperties": "Documenteigenschappen",
|
||||
"tipHideBar": "Balk verbergen",
|
||||
"tipShowBar": "Balk tonen"
|
||||
},
|
||||
"jpgToPdf": {
|
||||
"name": "JPG naar PDF",
|
||||
"subtitle": "Een of meer JPG-afbeeldingen opslaan als PDF."
|
||||
@@ -103,7 +221,7 @@
|
||||
"statusReadingFileMainThread": "Bestand lezen (Hoofdthread)...",
|
||||
"statusGenerating": "Inhoudsopgave genereren...",
|
||||
"errorReadingFileWithMessage": "Fout bij lezen bestand: {{message}}",
|
||||
"successGeneratedDownloadStarted": "Inhoudsopgave succesvol gegenereerd! Download gestart.",
|
||||
"successGeneratedDownloadStarted": "Inhoudsopgave met succes gegenereerd! Download gestart.",
|
||||
"workerErrorWithMessage": "Fout: {{message}}",
|
||||
"workerErrorOccurred": "Er is een worker-fout opgetreden. Controleer de console voor details."
|
||||
},
|
||||
@@ -159,7 +277,7 @@
|
||||
"invalidRangeMessage": "Regel {{number}} heeft een ongeldig paginabereik: {{range}}",
|
||||
"allPages": "alle pagina's",
|
||||
"emptyOutputMessage": "CoherentPDF heeft een leeg bestand geproduceerd.",
|
||||
"successMessage": "Paginalabels zijn succesvol toegevoegd!",
|
||||
"successMessage": "Paginalabels zijn met succes toegevoegd!",
|
||||
"processErrorMessage": "Kon de paginalabels niet toevoegen.",
|
||||
"styleOptions": {
|
||||
"DecimalArabic": "Decimale cijfers",
|
||||
@@ -310,7 +428,7 @@
|
||||
"converting": "JSON-bestanden naar PDF converteren...",
|
||||
"readError": "Fout bij lezen bestanden: {{message}}",
|
||||
"creatingZip": "ZIP-bestand maken...",
|
||||
"success": "JSON-bestanden succesvol naar PDF geconverteerd! ZIP-download gestart.",
|
||||
"success": "JSON-bestanden met succes naar PDF geconverteerd! ZIP-download gestart.",
|
||||
"zipError": "Fout bij maken ZIP: {{message}}",
|
||||
"workerError": "Worker-fout: {{message}}",
|
||||
"getStarted": "Selecteer JSON-bestanden om te beginnen"
|
||||
@@ -428,7 +546,7 @@
|
||||
"invalidFileExplanation": "Upload een PDF-bestand.",
|
||||
"noFile": "Geen bestand",
|
||||
"noFileExplanation": "Upload eerst een PDF-bestand.",
|
||||
"conversionSuccess": "PDF succesvol geconverteerd naar CBZ!",
|
||||
"conversionSuccess": "PDF met succes geconverteerd naar CBZ!",
|
||||
"conversionError": "Kan PDF niet converteren naar CBZ. Het bestand is mogelijk beschadigd."
|
||||
}
|
||||
},
|
||||
@@ -448,7 +566,7 @@
|
||||
"converting": "PDF's naar JSON converteren...",
|
||||
"readError": "Fout bij lezen bestanden: {{message}}",
|
||||
"creatingZip": "ZIP-bestand maken...",
|
||||
"success": "PDF's succesvol naar JSON geconverteerd! ZIP-download gestart.",
|
||||
"success": "PDF's met succes naar JSON geconverteerd! ZIP-download gestart.",
|
||||
"zipError": "Fout bij maken ZIP: {{message}}",
|
||||
"workerError": "Worker-fout: {{message}}",
|
||||
"getStarted": "Selecteer PDF-bestanden om te beginnen"
|
||||
@@ -514,6 +632,51 @@
|
||||
"retainPageLabels": "Originele pagina-labels van elk bestand behouden",
|
||||
"retainPageLabelsHint": "Uit (standaard): de samengevoegde PDF gebruikt natuurlijke paginanummering 1–N. Aan: de originele pagina-labels van elk bestand blijven behouden (kan dubbele labels opleveren)."
|
||||
},
|
||||
"duplexCollate": {
|
||||
"name": "Dubbelzijdige scan sorteren",
|
||||
"subtitle": "Een PDF die in twee blokken is gescand (eerst alle voorkanten, dan alle achterkanten) in de juiste voor-/achterkantvolgorde zetten.",
|
||||
"totalPagesLabel": "Totaal aantal pagina's:",
|
||||
"splitAfterPageLabel": "Splitsen na pagina",
|
||||
"splitAfterPagePlaceholder": "bijv. 50",
|
||||
"backBlockOrderLabel": "Volgorde van achterkantblok",
|
||||
"backBlockReverseOption": "Achterkantblok omkeren (gebruikelijk bij een omgedraaide stapel)",
|
||||
"backBlockKeepOption": "Achterkantblok ongewijzigd laten",
|
||||
"autoSplitButton": "Splitsing automatisch bepalen (helft)",
|
||||
"exportGroupedLabel": "Gegroepeerde bestanden exporteren op lengte van het originele document",
|
||||
"pagesPerDocumentLabel": "Pagina's per origineel document",
|
||||
"groupedHelp": "Indien ingeschakeld is de uitvoer een ZIP-bestand met één PDF per gegroepeerd document.",
|
||||
"collateButton": "PDF sorteren",
|
||||
"invalidFileTitle": "Ongeldig bestand",
|
||||
"invalidFileMessage": "Selecteer een PDF-bestand.",
|
||||
"loadingPdf": "PDF laden...",
|
||||
"loadErrorMessage": "Kan het PDF-bestand niet laden.",
|
||||
"fileMeta": "{{size}} - {{count}} pagina's",
|
||||
"oddPageWarning": "Oneven aantal pagina's ({{count}}). Een dubbelzijdige scan hoort een even aantal pagina's te hebben; mogelijk ontbreekt er een pagina of is er een te veel.",
|
||||
"previewSummary": "Voorkantblok: {{frontCount}} pagina's, achterkantblok: {{backCount}} pagina's. Uitvoer: {{outputCount}} pagina's, in voor-/achterkantvolgorde.",
|
||||
"previewMismatchWarning": "De blokken met voor- en achterkanten verschillen in lengte ({{frontCount}} voorkanten tegenover {{backCount}} achterkanten). De {{extraCount}} extra pagina's van het langste blok worden zonder tegenhanger achteraan toegevoegd.",
|
||||
"missingFileTitle": "Bestand ontbreekt",
|
||||
"missingFileMessage": "Upload een PDF met minstens 2 pagina's voordat je verwerkt.",
|
||||
"invalidSplitTitle": "Ongeldig splitspunt",
|
||||
"invalidSplitMessage": "Het splitspunt moet tussen pagina 1 en pagina {{maxSplit}} liggen.",
|
||||
"unevenConfirmTitle": "Ongelijke blokken",
|
||||
"unevenConfirmMessage": "Het voorkantblok heeft {{frontCount}} pagina's en het achterkantblok {{backCount}} pagina's.\nMeestal betekent dit dat een pagina dubbel is gescand of ontbreekt.\n\nDe {{extraCount}} pagina's zonder tegenhanger worden achteraan toegevoegd.\n\nToch doorgaan?",
|
||||
"invalidGroupTitle": "Ongeldige groepsgrootte",
|
||||
"invalidGroupMessage": "Voer een geldig aantal pagina's per origineel document in.",
|
||||
"collatingLoader": "Dubbelzijdige scan sorteren...",
|
||||
"successMessage": "Gesorteerde PDF is aangemaakt.",
|
||||
"successGroupedMessage": "Sorteren voltooid. {{fileCount}} gegroepeerde bestanden aangemaakt.",
|
||||
"processErrorMessage": "Kan de PDF niet sorteren.",
|
||||
"howItWorksStep1Title": "Upload de scan",
|
||||
"howItWorksStep1": "Sleep de ene PDF met eerst alle voorkanten en daarna alle achterkanten naar binnen.",
|
||||
"howItWorksStep2Title": "Stel het splitspunt in",
|
||||
"howItWorksStep2": "Geef aan waar het voorkantblok eindigt en kies of het achterkantblok omgekeerd moet worden.",
|
||||
"howItWorksStep3Title": "Sorteer en download",
|
||||
"howItWorksStep3": "Je krijgt één PDF met afwisselende pagina's, of een ZIP met een apart bestand per origineel document.",
|
||||
"faqOddPagesQuestion": "Wat als mijn scan een oneven aantal pagina's heeft?",
|
||||
"faqOddPagesAnswer": "Een dubbelzijdige scan hoort een even aantal pagina's te hebben. Is dat niet zo, dan is er waarschijnlijk een pagina dubbel gescand of overgeslagen. De tool waarschuwt je voor het verwerken, en pagina's zonder tegenhanger worden achteraan toegevoegd zodat er niets verloren gaat.",
|
||||
"faqBackOrderQuestion": "Waarom zou ik het achterkantblok ongewijzigd laten?",
|
||||
"faqBackOrderAnswer": "Dat hangt af van hoe de stapel bij de tweede ronde is ingevoerd. De hele stapel omdraaien levert achterkanten in omgekeerde volgorde op; dat is de standaardinstelling. Gaf je scanner ze in dezelfde volgorde als de voorkanten terug, kies dan om het blok ongewijzigd te laten."
|
||||
},
|
||||
"addAttachments": {
|
||||
"name": "Bijlagen Toevoegen",
|
||||
"subtitle": "Een of meer bestanden toevoegen aan een PDF."
|
||||
@@ -942,7 +1105,7 @@
|
||||
"tsaSectionTitle": "Tijdstempelserver (TSA)",
|
||||
"selectTsa": "Selecteer een TSA-server",
|
||||
"applyTimestamp": "Tijdstempel toepassen",
|
||||
"successMessage": "PDF succesvol voorzien van tijdstempel! Het tijdstempel kan in elke PDF-lezer worden geverifieerd."
|
||||
"successMessage": "PDF met succes voorzien van tijdstempel! Het tijdstempel kan in elke PDF-lezer worden geverifieerd."
|
||||
},
|
||||
"emailToPdf": {
|
||||
"name": "E-mail naar PDF",
|
||||
@@ -1109,7 +1272,7 @@
|
||||
"saveConfiguration": "Configuratie opslaan",
|
||||
"savingConfiguration": "Configuratie opslaan...",
|
||||
"savedTitle": "Opgeslagen",
|
||||
"savedMessage": "Configuratie succesvol opgeslagen!",
|
||||
"savedMessage": "Configuratie met succes opgeslagen!",
|
||||
"errorTitle": "Fout",
|
||||
"failedSave": "Kon configuratie niet opslaan: {{message}}",
|
||||
"emptyUrlTitle": "Lege URL",
|
||||
@@ -1151,5 +1314,13 @@
|
||||
"faqSinglePageAnswer": "Ja! Schakel de optie \"Herhalen\" in en de overlay-pagina's worden herhaald over alle basispagina's. Een watermerk van één pagina wordt op elke pagina toegepast.",
|
||||
"faqPrivacyQuestion": "Zijn mijn bestanden privé en veilig?",
|
||||
"faqPrivacyAnswer": "Absoluut! Alle verwerking vindt plaats in jouw browser. Jouw bestanden verlaten nooit jouw apparaat, wat volledige privacy garandeert."
|
||||
},
|
||||
"unlockPdf": {
|
||||
"name": "PDF Ontgrendelen",
|
||||
"subtitle": "Een PDF ontgrendelen door het verwijderen van de wachtwoordbeveiliging."
|
||||
},
|
||||
"protectPdf": {
|
||||
"name": "PDF Versleutelen",
|
||||
"subtitle": "Een PDF vergrendelen door toevoeging van een toegangswachtwoord."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,387 @@
|
||||
{
|
||||
"nav": {
|
||||
"home": "Strona główna",
|
||||
"about": "O nas",
|
||||
"contact": "Kontakt",
|
||||
"licensing": "Licencjonowanie",
|
||||
"allTools": "Wszystkie narzędzia",
|
||||
"docs": "Dokumentacja",
|
||||
"openMainMenu": "Otwórz menu główne",
|
||||
"language": "Język",
|
||||
"searchLanguage": "Szukaj języka…",
|
||||
"noLanguagesFound": "Nie znaleziono języków"
|
||||
},
|
||||
"donation": {
|
||||
"message": "Uwielbiasz BentoPDF? Pomóż nam utrzymać go jako darmowe i otwarte oprogramowanie!",
|
||||
"button": "Wesprzyj"
|
||||
},
|
||||
"hero": {
|
||||
"title": "Twój",
|
||||
"pdfToolkit": "zestaw narzędzi PDF",
|
||||
"builtForPrivacy": "stworzony z myślą o prywatności",
|
||||
"noSignups": "Brak rejestracji",
|
||||
"unlimitedUse": "Nielimitowane korzystanie",
|
||||
"worksOffline": "Działa offline",
|
||||
"startUsing": "Zacznij używać teraz"
|
||||
},
|
||||
"usedBy": {
|
||||
"title": "Używane przez firmy i osoby pracujące w"
|
||||
},
|
||||
"features": {
|
||||
"title": "Dlaczego warto wybrać",
|
||||
"bentoPdf": "BentoPDF?",
|
||||
"noSignup": {
|
||||
"title": "Bez rejestracji",
|
||||
"description": "Zacznij od razu, bez kont i e-maili."
|
||||
},
|
||||
"noUploads": {
|
||||
"title": "Bez wysyłania na serwer",
|
||||
"description": "W 100% po stronie klienta, Twoje pliki nigdy nie opuszczają urządzenia."
|
||||
},
|
||||
"foreverFree": {
|
||||
"title": "Zawsze darmowe",
|
||||
"description": "Wszystkie narzędzia, bez okresów próbnych i ukrytych opłat."
|
||||
},
|
||||
"noLimits": {
|
||||
"title": "Bez limitów",
|
||||
"description": "Używaj bez ograniczeń, brak ukrytych limitów."
|
||||
},
|
||||
"batchProcessing": {
|
||||
"title": "Przetwarzanie wsadowe",
|
||||
"description": "Obsługuj nieograniczoną liczbę plików PDF za jednym razem."
|
||||
},
|
||||
"lightningFast": {
|
||||
"title": "Błyskawicznie",
|
||||
"description": "Przetwarzaj pliki PDF natychmiast, bez czekania i opóźnień."
|
||||
}
|
||||
},
|
||||
"tools": {
|
||||
"title": "Rozpocznij z",
|
||||
"toolsLabel": "Narzędzia",
|
||||
"subtitle": "Kliknij narzędzie, aby otworzyć przesyłanie plików",
|
||||
"searchPlaceholder": "Szukaj narzędzia (np. 'podziel', 'organizuj'...)",
|
||||
"backToTools": "Wróć do narzędzi",
|
||||
"firstLoadNotice": "Pierwsze wczytywanie potrwa chwilę, ponieważ pobieramy nasz silnik konwersji. Potem wszystkie ładowania będą natychmiastowe."
|
||||
},
|
||||
"upload": {
|
||||
"clickToSelect": "Kliknij, aby wybrać plik",
|
||||
"orDragAndDrop": "lub przeciągnij i upuść",
|
||||
"pdfOrImages": "Pliki PDF lub obrazy",
|
||||
"filesNeverLeave": "Twoje pliki nigdy nie opuszczają Twojego urządzenia.",
|
||||
"addMore": "Dodaj więcej plików",
|
||||
"clearAll": "Wyczyść wszystko",
|
||||
"clearFiles": "Wyczyść pliki",
|
||||
"hints": {
|
||||
"singlePdf": "Pojedynczy plik PDF",
|
||||
"pdfFile": "Plik PDF",
|
||||
"multiplePdfs2": "Wiele plików PDF (co najmniej 2)",
|
||||
"bmpImages": "Obrazy BMP",
|
||||
"oneOrMorePdfs": "Jeden lub więcej plików PDF",
|
||||
"pdfDocuments": "Dokumenty PDF",
|
||||
"oneOrMoreCsv": "Jeden lub więcej plików CSV",
|
||||
"multiplePdfsSupported": "Obsługiwane wiele plików PDF",
|
||||
"singleOrMultiplePdfs": "Obsługiwane pojedyncze lub wielokrotne pliki PDF",
|
||||
"singlePdfFile": "Pojedynczy plik PDF",
|
||||
"pdfWithForms": "Plik PDF z polami formularza",
|
||||
"heicImages": "Obrazy HEIC/HEIF",
|
||||
"jpgImages": "Obrazy JPG, JPEG, JP2, JPX",
|
||||
"pdfsOrImages": "Pliki PDF lub obrazy",
|
||||
"oneOrMoreOdt": "Jeden lub więcej plików ODT",
|
||||
"singlePdfOnly": "Tylko pojedynczy plik PDF",
|
||||
"pdfFiles": "Pliki PDF",
|
||||
"multiplePdfs": "Wiele plików PDF",
|
||||
"pngImages": "Obrazy PNG",
|
||||
"pdfFilesOneOrMore": "Pliki PDF (jeden lub więcej)",
|
||||
"oneOrMoreRtf": "Jeden lub więcej plików RTF",
|
||||
"svgGraphics": "Grafika SVG",
|
||||
"tiffImages": "Obrazy TIFF",
|
||||
"webpImages": "Obrazy WebP"
|
||||
}
|
||||
},
|
||||
"howItWorks": {
|
||||
"title": "Jak to działa",
|
||||
"step1Title": "Prześlij plik",
|
||||
"step1": "Kliknij lub przeciągnij i upuść plik, aby rozpocząć",
|
||||
"step2Title": "Przetwarzaj",
|
||||
"step2": "Kliknij przycisk przetwarzania, aby rozpocząć",
|
||||
"step3Title": "Pobierz",
|
||||
"step3": "Natychmiast zapisz przetworzony plik"
|
||||
},
|
||||
"relatedTools": {
|
||||
"title": "Powiązane narzędzia PDF"
|
||||
},
|
||||
"loader": {
|
||||
"processing": "Przetwarzanie..."
|
||||
},
|
||||
"alert": {
|
||||
"title": "Uwaga",
|
||||
"ok": "OK"
|
||||
},
|
||||
"preview": {
|
||||
"title": "Podgląd dokumentu",
|
||||
"downloadAsPdf": "Pobierz jako PDF",
|
||||
"close": "Zamknij"
|
||||
},
|
||||
"settings": {
|
||||
"title": "Ustawienia",
|
||||
"shortcuts": "Skróty",
|
||||
"preferences": "Preferencje",
|
||||
"displayPreferences": "Preferencje wyświetlania",
|
||||
"searchShortcuts": "Szukaj skrótów...",
|
||||
"shortcutsInfo": "Naciśnij i przytrzymaj klawisze, aby ustawić skrót. Zmiany są zapisywane automatycznie.",
|
||||
"shortcutsWarning": "⚠️ Unikaj popularnych skrótów przeglądarki (Cmd/Ctrl+W, Cmd/Ctrl+T, Cmd/Ctrl+N itp.), ponieważ mogą nie działać prawidłowo.",
|
||||
"import": "Importuj",
|
||||
"export": "Eksportuj",
|
||||
"resetToDefaults": "Przywróć domyślne",
|
||||
"fullWidthMode": "Tryb pełnej szerokości",
|
||||
"fullWidthDescription": "Używaj pełnej szerokości ekranu dla wszystkich narzędzi zamiast wyśrodkowanego kontenera",
|
||||
"compactMode": "Tryb kompaktowy",
|
||||
"compactModeDescription": "Wyświetlaj narzędzia jako kompaktową listę zamiast kart",
|
||||
"advancedSettings": "Ustawienia zaawansowane",
|
||||
"advancedSettingsDescription": "Skonfiguruj zewnętrzne moduły przetwarzania (PyMuPDF, Ghostscript, CoherentPDF)",
|
||||
"settingsAutoSaved": "Ustawienia są zapisywane automatycznie",
|
||||
"clickToSet": "Kliknij, aby ustawić",
|
||||
"pressKeys": "Naciśnij klawisze...",
|
||||
"warnings": {
|
||||
"alreadyInUse": "Skrót jest już w użyciu",
|
||||
"assignedTo": "jest już przypisany do:",
|
||||
"chooseDifferent": "Proszę wybrać inny skrót.",
|
||||
"reserved": "Ostrzeżenie o zarezerwowanym skrócie",
|
||||
"commonlyUsed": "jest powszechnie używany do:",
|
||||
"unreliable": "Ten skrót może nie działać niezawodnie lub może kolidować z działaniem przeglądarki/systemu.",
|
||||
"useAnyway": "Czy mimo to chcesz go użyć?",
|
||||
"resetTitle": "Zresetuj skróty",
|
||||
"resetMessage": "Czy na pewno chcesz zresetować wszystkie skróty do wartości domyślnych?<br><br>Tej akcji nie można cofnąć.",
|
||||
"importSuccessTitle": "Import zakończony sukcesem",
|
||||
"importSuccessMessage": "Skróty zostały pomyślnie zaimportowane!",
|
||||
"importFailTitle": "Import nie powiódł się",
|
||||
"importFailMessage": "Nie udało się zaimportować skrótów. Nieprawidłowy format pliku."
|
||||
}
|
||||
},
|
||||
"warning": {
|
||||
"title": "Ostrzeżenie",
|
||||
"cancel": "Anuluj",
|
||||
"proceed": "Kontynuuj"
|
||||
},
|
||||
"compliance": {
|
||||
"title": "Twoje dane nigdy nie opuszczają Twojego urządzenia",
|
||||
"weKeep": "Dbamy o",
|
||||
"yourInfoSafe": "bezpieczeństwo Twoich informacji",
|
||||
"byFollowingStandards": "przestrzegając globalnych standardów bezpieczeństwa.",
|
||||
"processingLocal": "Całe przetwarzanie odbywa się lokalnie na Twoim urządzeniu.",
|
||||
"gdpr": {
|
||||
"title": "Zgodność z RODO",
|
||||
"description": "Chroni dane osobowe i prywatność osób w Unii Europejskiej."
|
||||
},
|
||||
"ccpa": {
|
||||
"title": "Zgodność z CCPA",
|
||||
"description": "Daje mieszkańcom Kalifornii prawa do kontrolowania sposobu gromadzenia, wykorzystywania i udostępniania ich danych osobowych."
|
||||
},
|
||||
"hipaa": {
|
||||
"title": "Zgodność z HIPAA",
|
||||
"description": "Ustanawia zabezpieczenia w celu ochrony wrażliwych informacji zdrowotnych w systemie opieki zdrowotnej Stanów Zjednoczonych."
|
||||
}
|
||||
},
|
||||
"faq": {
|
||||
"title": "Często Zadawane",
|
||||
"questions": "Pytania",
|
||||
"sectionTitle": "Często Zadawane Pytania",
|
||||
"isFree": {
|
||||
"question": "Czy BentoPDF jest naprawdę darmowy?",
|
||||
"answer": "Tak, absolutnie. Wszystkie narzędzia w BentoPDF są w 100% darmowe do użytku, bez limitów plików, bez rejestracji i bez znaków wodnych. Wierzymy, że każdy zasługuje na dostęp do prostych, potężnych narzędzi PDF bez barier płatnych."
|
||||
},
|
||||
"areFilesSecure": {
|
||||
"question": "Czy moje pliki są bezpieczne? Gdzie są przetwarzane?",
|
||||
"answer": "Twoje pliki są maksymalnie bezpieczne, ponieważ nigdy nie opuszczają Twojego komputera. Całe przetwarzanie odbywa się bezpośrednio w Twojej przeglądarce internetowej (po stronie klienta). Nigdy nie wysyłamy Twoich plików na serwer, dzięki czemu zachowujesz pełną prywatność i kontrolę nad swoimi dokumentami."
|
||||
},
|
||||
"platforms": {
|
||||
"question": "Czy to działa na Macu, Windowsie i urządzeniach mobilnych?",
|
||||
"answer": "Tak! Ponieważ BentoPDF działa całkowicie w Twojej przeglądarce, obsługuje dowolny system operacyjny z nowoczesną przeglądarką internetową, w tym Windows, macOS, Linux, iOS oraz Android."
|
||||
},
|
||||
"gdprCompliant": {
|
||||
"question": "Czy BentoPDF jest zgodny z RODO?",
|
||||
"answer": "Tak. BentoPDF jest w pełni zgodny z RODO. Ponieważ całe przetwarzanie plików odbywa się lokalnie w Twojej przeglądarce, a my nigdy nie zbieramy ani nie wysyłamy Twoich plików na żaden serwer, nie mamy dostępu do Twoich danych. Gwarantuje to, że zawsze sprawujesz pełną kontrolę nad swoimi dokumentami."
|
||||
},
|
||||
"dataStorage": {
|
||||
"question": "Czy przechowujecie lub śledzicie jakiekolwiek moje pliki?",
|
||||
"answer": "Nie. Nigdy nie przechowujemy, nie śledzimy ani nie logujemy Twoich plików. Wszystko, co robisz w BentoPDF, odbywa się w pamięci Twojej przeglądarki i znika po zamknięciu strony. Nie ma żadnych transferów, logów historii ani serwerów."
|
||||
},
|
||||
"different": {
|
||||
"question": "Czym różni się BentoPDF od innych narzędzi PDF?",
|
||||
"answer": "Większość narzędzi PDF wysyła Twoje pliki na serwer w celu ich przetworzenia. BentoPDF nigdy tego nie robi. Wykorzystujemy bezpieczną, nowoczesną technologię internetową, aby przetwarzać Twoje pliki bezpośrednio w przeglądarce. Oznacza to większą wydajność, silniejszą prywatność i pełen spokój ducha."
|
||||
},
|
||||
"browserBased": {
|
||||
"question": "W jaki sposób przetwarzanie w oparciu o przeglądarkę zapewnia mi bezpieczeństwo?",
|
||||
"answer": "Działając całkowicie wewnątrz Twojej przeglądarki, BentoPDF gwarantuje, że Twoje pliki nigdy nie opuszczą Twojego urządzenia. Eliminuje to ryzyko ataków hakerskich na serwery, naruszeń bezpieczeństwa danych czy nieautoryzowanego dostępu. Twoje pliki pozostają Twoje — zawsze."
|
||||
},
|
||||
"analytics": {
|
||||
"question": "Czy używacie plików cookie lub analityki do mojego śledzenia?",
|
||||
"answer": "Dbamy o Twoją prywatność. BentoPDF nie śledzi danych osobowych. Używamy Simple Analytics wyłącznie w celu sprawdzenia anonimowej liczby wizyt. Oznacza to, że wiemy, ilu użytkowników odwiedza naszą stronę, ale nigdy nie wiemy, kim jesteś. Simple Analytics jest w pełni zgodne z RODO i szanuje Twoją prywatność."
|
||||
}
|
||||
},
|
||||
"testimonials": {
|
||||
"title": "Co Nasi",
|
||||
"users": "Użytkownicy",
|
||||
"say": "Mówią"
|
||||
},
|
||||
"support": {
|
||||
"title": "Podoba Ci się moja praca?",
|
||||
"description": "BentoPDF to projekt z pasji, stworzony po to, aby udostępnić darmowy, prywatny i potężny zestaw narzędzi PDF dla każdego. Jeśli uznasz go za przydatny, rozważ wsparcie jego rozwoju. Każda kawa pomaga!",
|
||||
"buyMeCoffee": "Postaw mi kawę"
|
||||
},
|
||||
"footer": {
|
||||
"copyright": "© 2026 BentoPDF. Wszelkie prawa zastrzeżone.",
|
||||
"version": "Wersja",
|
||||
"company": "Firma",
|
||||
"aboutUs": "O nas",
|
||||
"faqLink": "FAQ",
|
||||
"contactUs": "Kontakt",
|
||||
"legal": "Kwestie prawne",
|
||||
"termsAndConditions": "Zasady i warunki",
|
||||
"privacyPolicy": "Polityka prywatności",
|
||||
"followUs": "Śledź nas"
|
||||
},
|
||||
"merge": {
|
||||
"title": "Połącz pliki PDF",
|
||||
"description": "Połącz całe pliki lub wybierz konkretne strony do scalenia w nowy dokument.",
|
||||
"fileMode": "Tryb pliku",
|
||||
"pageMode": "Tryb strony",
|
||||
"howItWorks": "Jak to działa:",
|
||||
"fileModeInstructions": [
|
||||
"Kliknij i przeciągnij ikonę, aby zmienić kolejność plików.",
|
||||
"W polu \"Strony\" dla każdego pliku możesz określić zakresy (np. \"1-3, 5\"), aby połączyć tylko te strony.",
|
||||
"Pozostaw pole \"Strony\" puste, aby dołączyć wszystkie strony z tego pliku."
|
||||
],
|
||||
"pageModeInstructions": [
|
||||
"Poniżej widoczne są wszystkie strony z przesłanych plików PDF.",
|
||||
"Po prostu przeciągnij i upuść poszczególne miniatury stron, aby ułożyć je w dokładnej kolejności dla nowego pliku."
|
||||
],
|
||||
"mergePdfs": "Połącz PDF-y"
|
||||
},
|
||||
"common": {
|
||||
"page": "Strona",
|
||||
"pages": "Strony",
|
||||
"of": "z",
|
||||
"download": "Pobierz",
|
||||
"cancel": "Anuluj",
|
||||
"save": "Zapisz",
|
||||
"delete": "Usuń",
|
||||
"edit": "Edytuj",
|
||||
"add": "Dodaj",
|
||||
"remove": "Usuń",
|
||||
"loading": "Ładowanie...",
|
||||
"loadingPageCount": "Wczytywanie stron...",
|
||||
"error": "Błąd",
|
||||
"success": "Sukces",
|
||||
"file": "Plik",
|
||||
"files": "Pliki",
|
||||
"close": "Zamknij",
|
||||
"convert": "Konwertuj",
|
||||
"unknownError": "Nieznany błąd"
|
||||
},
|
||||
"about": {
|
||||
"hero": {
|
||||
"title": "Wierzymy, że narzędzia PDF powinny być",
|
||||
"subtitle": "szybkie, prywatne i darmowe.",
|
||||
"noCompromises": "Bez kompromisów."
|
||||
},
|
||||
"mission": {
|
||||
"title": "Nasza misja",
|
||||
"description": "Zapewnienie najbardziej wszechstronnego zestawu narzędzi PDF, który szanuje Twoją prywatność i nigdy nie prosi o płatność. Wierzymy, że podstawowe narzędzia do dokumentów powinny być dostępne dla każdego, wszędzie i bez barier."
|
||||
},
|
||||
"philosophy": {
|
||||
"label": "Nasza główna filozofia",
|
||||
"title": "Prywatność na pierwszym miejscu. Zawsze.",
|
||||
"description": "W czasach, gdy dane są towarem, my przyjmujemy inne podejście. Całe przetwarzanie w narzędziach BentoPDF odbywa się lokalnie w Twojej przeglądarce. Oznacza to, że Twoje pliki nigdy nie stykają się z naszymi serwerami, nigdy nie widzimy Twoich dokumentów i nie śledzimy tego, co robisz. Twoje dokumenty pozostają całkowicie i bezsprzecznie prywatne. To nie tylko funkcja; to nasz fundament."
|
||||
},
|
||||
"whyBentopdf": {
|
||||
"title": "Dlaczego",
|
||||
"speed": {
|
||||
"title": "Zbudowane dla szybkości",
|
||||
"description": "Bez czekania na wysłanie lub pobranie z serwera. Przetwarzając pliki bezpośrednio w Twojej przeglądarce przy użyciu nowoczesnych technologii internetowych, takich jak WebAssembly, oferujemy niezrównaną prędkość dla wszystkich naszych narzędzi."
|
||||
},
|
||||
"free": {
|
||||
"title": "Całkowicie darmowe",
|
||||
"description": "Bez wersji próbnych, bez subskrypcji, bez ukrytych opłat i bez „funkcji premium” wziętych jako zakładników. Wierzymy, że potężne narzędzia PDF powinny być dobrem publicznym, a nie centrum zysków."
|
||||
},
|
||||
"noAccount": {
|
||||
"title": "Konto nie jest wymagane",
|
||||
"description": "Zacznij natychmiast używać dowolnego narzędzia. Nie potrzebujemy Twojego e-maila, hasła ani żadnych danych osobowych. Twój przepływ pracy powinien być bezproblemowy i anonimowy."
|
||||
},
|
||||
"openSource": {
|
||||
"title": "Duch Open Source",
|
||||
"description": "Stworzone z myślą o przejrzystości. Korzystamy z niesamowitych bibliotek open-source, takich jak PDF-lib i PDF.js, oraz wierzymy w społeczny wysiłek, dzięki któremu potężne narzędzia są dostępne dla wszystkich."
|
||||
}
|
||||
},
|
||||
"cta": {
|
||||
"title": "Gotowy, aby zacząć?",
|
||||
"description": "Dołącz do tysięcy użytkowników, którzy ufają BentoPDF w codziennych zadaniach z dokumentami. Poczuj różnicę, jaką potrafią zrobić prywatność i wydajność.",
|
||||
"button": "Odkryj wszystkie narzędzia"
|
||||
}
|
||||
},
|
||||
"contact": {
|
||||
"title": "Bądźmy w kontakcie",
|
||||
"subtitle": "Z przyjemnością Cię wysłuchamy. Niezależnie od tego, czy masz pytanie, opinię, czy prośbę o nową funkcję, nie wahaj się do nas napisać.",
|
||||
"email": "Możesz się z nami skontaktować bezpośrednio poprzez e-mail na adres:"
|
||||
},
|
||||
"licensing": {
|
||||
"title": "Licencjonowanie dla",
|
||||
"subtitle": "Wybierz licencję, która odpowiada Twoim potrzebom."
|
||||
},
|
||||
"multiTool": {
|
||||
"uploadPdfs": "Prześlij pliki PDF",
|
||||
"upload": "Prześlij",
|
||||
"addBlankPage": "Dodaj pustą stronę",
|
||||
"edit": "Edytuj:",
|
||||
"undo": "Cofnij",
|
||||
"redo": "Ponów",
|
||||
"reset": "Zresetuj",
|
||||
"selection": "Wybór:",
|
||||
"selectAll": "Zaznacz wszystko",
|
||||
"deselectAll": "Odznacz wszystko",
|
||||
"rotate": "Obróć:",
|
||||
"rotateLeft": "W lewo",
|
||||
"rotateRight": "W prawo",
|
||||
"transform": "Przekształć:",
|
||||
"duplicate": "Powiel",
|
||||
"split": "Podziel",
|
||||
"clear": "Wyczyść:",
|
||||
"delete": "Usuń",
|
||||
"download": "Pobierz:",
|
||||
"downloadSelected": "Pobierz wybrane",
|
||||
"exportPdf": "Eksportuj PDF",
|
||||
"uploadPdfFiles": "Wybierz pliki PDF lub obrazy",
|
||||
"dragAndDrop": "Przeciągnij i upuść pliki PDF lub obrazy tutaj, albo kliknij, by wybrać",
|
||||
"selectFiles": "Wybierz pliki",
|
||||
"dropToAdd": "Upuść pliki PDF lub obrazy, aby dodać",
|
||||
"convertingImages": "Konwertowanie obrazów do formatu PDF...",
|
||||
"failedToConvertImages": "Nie udało się przekonwertować obrazów do pliku PDF.",
|
||||
"renderingPages": "Renderowanie stron...",
|
||||
"actions": {
|
||||
"duplicatePage": "Powiel tę stronę",
|
||||
"deletePage": "Usuń tę stronę",
|
||||
"insertPdf": "Wstaw PDF po tej stronie",
|
||||
"toggleSplit": "Przełącz podział po tej stronie"
|
||||
},
|
||||
"pleaseWait": "Proszę czekać",
|
||||
"pagesRendering": "Strony są nadal renderowane. Proszę czekać...",
|
||||
"noPagesSelected": "Nie wybrano stron",
|
||||
"selectOnePage": "Wybierz co najmniej jedną stronę do pobrania.",
|
||||
"noPages": "Brak stron",
|
||||
"noPagesToExport": "Nie ma stron do wyeksportowania.",
|
||||
"renderingTitle": "Renderowanie podglądów stron",
|
||||
"errorRendering": "Nie udało się wyrenderować miniatur stron",
|
||||
"error": "Błąd",
|
||||
"failedToLoad": "Nie udało się załadować"
|
||||
},
|
||||
"simpleMode": {
|
||||
"title": "Narzędzia PDF",
|
||||
"subtitle": "Wybierz narzędzie, aby rozpocząć"
|
||||
},
|
||||
"disabledTool": {
|
||||
"title": "Narzędzie niedostępne",
|
||||
"heading": "To narzędzie zostało wyłączone",
|
||||
"message": "To narzędzie nie jest dostępne w Twoim środowisku. Skontaktuj się z administratorem, aby uzyskać więcej informacji.",
|
||||
"backHome": "Powrót do strony głównej"
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -216,7 +216,7 @@
|
||||
},
|
||||
"analytics": {
|
||||
"question": "Vocês usam cookies ou rastreamento?",
|
||||
"answer": "Usamos apenas o Simple Analytics para contar visitas de forma anônima. Sabemos quantos usuários nos visitam, mas nunca quem você é. O sistema respeita totalmente a GDPR."
|
||||
"answer": "Não. O BentoPDF não rastreia você de forma alguma. Não usamos cookies, análises nem scripts de rastreamento, nem mesmo no site ao vivo bentopdf.com. Nunca sabemos quem você é ou o que faz com as ferramentas."
|
||||
}
|
||||
},
|
||||
"testimonials": {
|
||||
@@ -239,7 +239,9 @@
|
||||
"legal": "Jurídico",
|
||||
"termsAndConditions": "Termos e Condições",
|
||||
"privacyPolicy": "Política de Privacidade",
|
||||
"followUs": "Siga-nos"
|
||||
"followUs": "Siga-nos",
|
||||
"privacyShort": "Privacidade",
|
||||
"termsShort": "Termos"
|
||||
},
|
||||
"merge": {
|
||||
"title": "Mesclar PDFs",
|
||||
@@ -286,7 +288,8 @@
|
||||
"noCompromises": "Sem concessões."
|
||||
},
|
||||
"mission": {
|
||||
"title": "Nossa Missão",
|
||||
"title": "Nossa",
|
||||
"titleDim": "Missão",
|
||||
"description": "Fornecer o kit de ferramentas PDF mais completo, respeitando sua privacidade e sem cobrar por isso. Ferramentas essenciais devem ser acessíveis a todos, sem barreiras."
|
||||
},
|
||||
"philosophy": {
|
||||
@@ -350,9 +353,12 @@
|
||||
"download": "Baixar:",
|
||||
"downloadSelected": "Baixar Selecionadas",
|
||||
"exportPdf": "Exportar PDF",
|
||||
"uploadPdfFiles": "Selecionar Arquivos PDF",
|
||||
"dragAndDrop": "Arraste arquivos PDF aqui ou clique para selecionar",
|
||||
"uploadPdfFiles": "Selecionar Arquivos PDF ou Imagens",
|
||||
"dragAndDrop": "Arraste arquivos PDF ou imagens aqui ou clique para selecionar",
|
||||
"selectFiles": "Selecionar Arquivos",
|
||||
"dropToAdd": "Solte arquivos PDF ou imagens para adicionar",
|
||||
"convertingImages": "Convertendo imagens em PDF...",
|
||||
"failedToConvertImages": "Falha ao converter imagens em PDF.",
|
||||
"renderingPages": "Renderizando páginas...",
|
||||
"actions": {
|
||||
"duplicatePage": "Duplicar esta página",
|
||||
|
||||
@@ -55,6 +55,124 @@
|
||||
"name": "Editor de PDF",
|
||||
"subtitle": "Anotar, destacar, redigir, comentar, adicionar formas/imagens, pesquisar e visualizar PDFs."
|
||||
},
|
||||
"editPdfText": {
|
||||
"name": "Editar texto do PDF",
|
||||
"subtitle": "Clique em qualquer parágrafo e edite-o no local com reorganização do texto em tempo real, fontes e estilos.",
|
||||
"saved": "PDF salvo com sucesso! ({{size}} KB)",
|
||||
"failedToLoad": "Não foi possível carregar o editor de texto PDF.",
|
||||
"loadingFonts": "Carregando fontes...",
|
||||
"fontsUnavailable": "Não foi possível baixar uma fonte necessária para alguns caracteres. Verifique sua conexão e tente novamente; caso contrário, esses caracteres podem não aparecer corretamente no PDF salvo.",
|
||||
"howToUpload": "Enviar PDF",
|
||||
"howToClick": "Clique em um parágrafo",
|
||||
"howToRestyle": "Reestilize tudo",
|
||||
"relatedPdfEditor": "Anote e marque PDFs",
|
||||
"relatedSignPdf": "Desenhe, digite ou envie uma assinatura",
|
||||
"relatedWatermark": "Aplique texto ou imagens",
|
||||
"relatedStamps": "Coloque carimbos nas páginas",
|
||||
"relatedCompress": "Reduza o tamanho do arquivo",
|
||||
"relatedOrganizeName": "Organizar PDF",
|
||||
"relatedOrganize": "Reordene e gerencie páginas",
|
||||
"open": "Abrir",
|
||||
"export": "Exportar",
|
||||
"filterAll": "Tudo",
|
||||
"filterText": "Texto",
|
||||
"filterImages": "Imagens",
|
||||
"filterShapes": "Formas",
|
||||
"addText": "Adicionar texto",
|
||||
"langAuto": "Automático",
|
||||
"change": "Alterar",
|
||||
"ignore": "Ignorar",
|
||||
"next": "Próximo",
|
||||
"replace": "Substituir",
|
||||
"replaceAll": "Substituir tudo",
|
||||
"emptyState": "Abra um PDF para editar seu texto, imagens e formas.",
|
||||
"choosePdf": "Escolher um PDF…",
|
||||
"font": "Fonte",
|
||||
"systemFonts": "Fontes do sistema",
|
||||
"color": "Cor",
|
||||
"alignment": "Alinhamento",
|
||||
"style": "Estilo",
|
||||
"lists": "Listas",
|
||||
"outline": "Contorno",
|
||||
"spacing": "Espaçamento",
|
||||
"direction": "Direção",
|
||||
"dirAuto": "Automático",
|
||||
"pathStroke": "Contorno do traçado",
|
||||
"tipBackToUpload": "Voltar ao envio",
|
||||
"tipOpenAnotherPdf": "Abrir outro PDF",
|
||||
"tipExportS": "Exportar (⌘S)",
|
||||
"tipUndoZ": "Desfazer (⌘Z)",
|
||||
"tipRedoZ": "Refazer (⇧⌘Z)",
|
||||
"tipFileDetails": "Detalhes do arquivo",
|
||||
"tipEditExistingContent": "Editar conteúdo existente",
|
||||
"tipWhatTheEditToolTouchesNarrowTheScopeOnBus": "O que a ferramenta Editar afeta — restrinja o alcance em páginas cheias",
|
||||
"tipClickThePageToAddATextBox": "Clique na página para adicionar uma caixa de texto",
|
||||
"tipSpellCheckLanguage": "Idioma do corretor ortográfico",
|
||||
"tipFindAndReplace": "Localizar e substituir",
|
||||
"tipAddAnImage": "Adicionar uma imagem",
|
||||
"tipCopyThisPageSTextInReadingOrder": "Copiar o texto desta página na ordem de leitura",
|
||||
"tipCheckTheSpellingOfThisPage": "Verificar a ortografia desta página",
|
||||
"tipShowOrHideTheFormatPanel": "Mostrar ou ocultar o painel de formatação",
|
||||
"phReplaceWith": "Substituir por",
|
||||
"tipAddToYourDictionary": "Adicionar ao dicionário",
|
||||
"tipClose": "Fechar",
|
||||
"phFind": "Localizar",
|
||||
"tipPreviousMatch": "Ocorrência anterior",
|
||||
"tipNextMatch": "Próxima ocorrência",
|
||||
"tipRotateLeft90": "Girar 90° à esquerda",
|
||||
"tipRotateRight90": "Girar 90° à direita",
|
||||
"tipFlipHorizontal": "Inverter horizontalmente",
|
||||
"tipFlipVertical": "Inverter verticalmente",
|
||||
"tipReplaceThisImageKeepingItsPlacement": "Substituir esta imagem mantendo a posição",
|
||||
"tipAlternateTextForAccessibilityTaggedPdfs": "Texto alternativo para acessibilidade (PDFs marcados)",
|
||||
"tipBringToFront": "Trazer para a frente",
|
||||
"tipSendToBack": "Enviar para trás",
|
||||
"tipDuplicate": "Duplicar",
|
||||
"tipDelete": "Excluir",
|
||||
"tipAlignLeftEdges": "Alinhar bordas esquerdas",
|
||||
"tipAlignHorizontalCenters": "Centralizar horizontalmente",
|
||||
"tipAlignRightEdges": "Alinhar bordas direitas",
|
||||
"tipAlignTops": "Alinhar bordas superiores",
|
||||
"tipAlignVerticalCenters": "Centralizar verticalmente",
|
||||
"tipAlignBottoms": "Alinhar bordas inferiores",
|
||||
"tipDistributeHorizontally": "Distribuir horizontalmente",
|
||||
"tipDistributeVertically": "Distribuir verticalmente",
|
||||
"tipFontSize": "Tamanho da fonte",
|
||||
"tipListFontsInstalledOnThisDeviceChromium": "Listar as fontes instaladas neste dispositivo (Chromium)",
|
||||
"tipCustomTextColor": "Cor de texto personalizada",
|
||||
"tipAlignLeft": "Alinhar à esquerda",
|
||||
"tipAlignCenter": "Centralizar",
|
||||
"tipAlignRight": "Alinhar à direita",
|
||||
"tipJustify": "Justificar",
|
||||
"tipBold": "Negrito",
|
||||
"tipItalic": "Itálico",
|
||||
"tipUnderline": "Sublinhado",
|
||||
"tipStrikethrough": "Tachado",
|
||||
"tipSuperscript": "Sobrescrito",
|
||||
"tipSubscript": "Subscrito",
|
||||
"tipToggleBulletedItem": "Alternar item com marcador",
|
||||
"tipToggleNumberedItem": "Alternar item numerado",
|
||||
"tipNumberedListMarkerStyle": "Estilo de marcador de listas numeradas",
|
||||
"tipDecreaseListIndentTab": "Diminuir recuo (⇧Tab)",
|
||||
"tipIncreaseListIndentTab": "Aumentar recuo (Tab)",
|
||||
"tipTextOutlineColor": "Cor do contorno do texto",
|
||||
"tipOutlineWidth0None": "Espessura do contorno (0 = nenhum)",
|
||||
"tipFromContent": "Do conteúdo",
|
||||
"tipLeftToRight": "Da esquerda para a direita",
|
||||
"tipRightToLeft": "Da direita para a esquerda",
|
||||
"tipStrokeColor": "Cor do traço",
|
||||
"tipStrokeWidth": "Espessura do traço",
|
||||
"tipZoomPresets": "Predefinições de zoom",
|
||||
"tipZoomOut": "Reduzir zoom",
|
||||
"tipZoomIn": "Ampliar zoom",
|
||||
"tipFitPage": "Ajustar página",
|
||||
"tipPreviousPage": "Página anterior",
|
||||
"tipTypeAPageNumberAndPressEnter": "Digite um número de página e pressione Enter",
|
||||
"tipNextPage": "Próxima página",
|
||||
"tipDocumentProperties": "Propriedades do documento",
|
||||
"tipHideBar": "Ocultar barra",
|
||||
"tipShowBar": "Mostrar barra"
|
||||
},
|
||||
"jpgToPdf": {
|
||||
"name": "JPG para PDF",
|
||||
"subtitle": "Crie um PDF a partir de uma ou mais imagens JPG."
|
||||
@@ -514,6 +632,51 @@
|
||||
"retainPageLabels": "Manter os rótulos de página originais de cada ficheiro",
|
||||
"retainPageLabelsHint": "Desligado (padrão): o PDF mesclado usa numeração natural 1–N. Ligado: os rótulos de página originais de cada ficheiro são preservados (pode produzir rótulos duplicados)."
|
||||
},
|
||||
"duplexCollate": {
|
||||
"name": "Intercalar digitalização frente e verso",
|
||||
"subtitle": "Reorganize um PDF digitalizado em dois blocos (primeiro todas as frentes, depois todos os versos) na ordem frente/verso correta.",
|
||||
"totalPagesLabel": "Total de páginas:",
|
||||
"splitAfterPageLabel": "Dividir após a página",
|
||||
"splitAfterPagePlaceholder": "ex.: 50",
|
||||
"backBlockOrderLabel": "Ordem do bloco de versos",
|
||||
"backBlockReverseOption": "Inverter o bloco de versos (comum quando a pilha é virada)",
|
||||
"backBlockKeepOption": "Manter o bloco de versos como está",
|
||||
"autoSplitButton": "Detectar divisão automaticamente (metade)",
|
||||
"exportGroupedLabel": "Exportar arquivos agrupados pelo tamanho do documento original",
|
||||
"pagesPerDocumentLabel": "Páginas por documento original",
|
||||
"groupedHelp": "Se ativado, a saída é um ZIP contendo um PDF para cada documento agrupado.",
|
||||
"collateButton": "Intercalar PDF",
|
||||
"invalidFileTitle": "Arquivo inválido",
|
||||
"invalidFileMessage": "Selecione um arquivo PDF.",
|
||||
"loadingPdf": "Carregando PDF...",
|
||||
"loadErrorMessage": "Falha ao carregar o arquivo PDF.",
|
||||
"fileMeta": "{{size}} - {{count}} páginas",
|
||||
"oddPageWarning": "Número ímpar de páginas ({{count}}). Uma digitalização frente e verso deve ter um número par de páginas; pode haver uma página faltando ou sobrando.",
|
||||
"previewSummary": "Bloco de frentes: {{frontCount}} página(s), bloco de versos: {{backCount}} página(s). Saída: {{outputCount}} página(s), na sequência frente/verso.",
|
||||
"previewMismatchWarning": "Os blocos de frentes e versos têm tamanhos diferentes ({{frontCount}} frentes contra {{backCount}} versos). As {{extraCount}} página(s) excedentes do bloco maior serão anexadas sem par no final.",
|
||||
"missingFileTitle": "Arquivo ausente",
|
||||
"missingFileMessage": "Envie um PDF com pelo menos 2 páginas antes de processar.",
|
||||
"invalidSplitTitle": "Ponto de divisão inválido",
|
||||
"invalidSplitMessage": "O ponto de divisão deve estar entre a página 1 e a página {{maxSplit}}.",
|
||||
"unevenConfirmTitle": "Blocos desiguais",
|
||||
"unevenConfirmMessage": "O bloco de frentes tem {{frontCount}} página(s) e o de versos tem {{backCount}} página(s).\nNormalmente isso significa que uma página foi digitalizada duas vezes ou está faltando.\n\nAs {{extraCount}} página(s) sem par serão anexadas no final.\n\nContinuar mesmo assim?",
|
||||
"invalidGroupTitle": "Tamanho de grupo inválido",
|
||||
"invalidGroupMessage": "Informe um número válido de páginas por documento original.",
|
||||
"collatingLoader": "Intercalando a digitalização frente e verso...",
|
||||
"successMessage": "PDF intercalado gerado com sucesso.",
|
||||
"successGroupedMessage": "Intercalação concluída. {{fileCount}} arquivo(s) agrupado(s) gerado(s).",
|
||||
"processErrorMessage": "Falha ao intercalar o PDF.",
|
||||
"howItWorksStep1Title": "Envie a digitalização",
|
||||
"howItWorksStep1": "Solte o PDF único que contém todas as frentes seguidas de todos os versos.",
|
||||
"howItWorksStep2Title": "Defina o ponto de divisão",
|
||||
"howItWorksStep2": "Indique onde termina o bloco de frentes e escolha se o bloco de versos precisa ser invertido.",
|
||||
"howItWorksStep3Title": "Intercale e baixe",
|
||||
"howItWorksStep3": "Receba um PDF intercalado ou um ZIP com um arquivo separado para cada documento original.",
|
||||
"faqOddPagesQuestion": "E se a minha digitalização tiver um número ímpar de páginas?",
|
||||
"faqOddPagesAnswer": "Uma digitalização frente e verso deve ter um número par de páginas. Se não tiver, provavelmente uma página foi digitalizada duas vezes ou ficou de fora. A ferramenta avisa antes de processar, e as páginas sem par são anexadas no final para que nada se perca.",
|
||||
"faqBackOrderQuestion": "Por que eu manteria o bloco de versos como está?",
|
||||
"faqBackOrderAnswer": "Depende de como a pilha foi inserida na segunda passagem. Virar a pilha inteira produz versos em ordem invertida, que é a opção padrão. Se o seu scanner os devolveu na mesma ordem das frentes, escolha manter o bloco como está."
|
||||
},
|
||||
"addAttachments": {
|
||||
"name": "Adicionar Anexos",
|
||||
"subtitle": "Incorpore um ou mais arquivos dentro do seu PDF."
|
||||
@@ -1151,5 +1314,13 @@
|
||||
"faqSinglePageAnswer": "Sim! Ative a opção \"Repetir\" e as páginas de sobreposição se repetirão em todas as páginas base. Uma marca d'água de uma página será aplicada a cada página.",
|
||||
"faqPrivacyQuestion": "Os meus ficheiros são privados e seguros?",
|
||||
"faqPrivacyAnswer": "Com certeza! Todo o processamento acontece no seu navegador. Os seus ficheiros nunca saem do seu dispositivo, garantindo total privacidade."
|
||||
},
|
||||
"unlockPdf": {
|
||||
"name": "Descriptografar PDF",
|
||||
"subtitle": "Desbloqueie o PDF removendo a proteção por senha."
|
||||
},
|
||||
"protectPdf": {
|
||||
"name": "Criptografar PDF",
|
||||
"subtitle": "Bloqueie seu PDF adicionando uma senha."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,11 +212,11 @@
|
||||
},
|
||||
"browserBased": {
|
||||
"question": "Почему обработка в браузере - это безопасно?",
|
||||
"answer": "Работая целиком в браузере, BentoPDF гарантирует, что ваши файлы никогда не покидают ваше устройство. Это исключает риски взлома серверов, утечек данных или несанкционированного доступа. Ваши файлы остаются вашими — всегда."
|
||||
"answer": "Работая целиком в браузере, BentoPDF гарантирует, что ваши файлы никогда не покидают ваше устройство. Это исключает риски взлома серверов, утечек данных или несанкционированного доступа. Ваши файлы остаются вашими, всегда."
|
||||
},
|
||||
"analytics": {
|
||||
"question": "Вы используете cookies или аналитику для слежки за мной?",
|
||||
"answer": "Мы уважаем вашу приватность. BentoPDF не отслеживает персональную информацию. Мы используем Simple Analytics исключительно для анонимного подсчета посещений нашего сайта. Это означает, что мы знаем, как много посетителей зашло на наш сайт, но мы не знаем, кто они. Simple Analytics полностью соответствует GDPR."
|
||||
"answer": "Нет. BentoPDF вас никак не отслеживает. Мы не используем файлы cookie, аналитику или трекинговые скрипты, даже на действующем сайте bentopdf.com. Мы никогда не знаем, кто вы и что вы делаете с инструментами."
|
||||
}
|
||||
},
|
||||
"testimonials": {
|
||||
@@ -239,7 +239,9 @@
|
||||
"legal": "Правовая информация",
|
||||
"termsAndConditions": "Условия предоставления услуг",
|
||||
"privacyPolicy": "Политика приватности",
|
||||
"followUs": "Подпишитесь"
|
||||
"followUs": "Подпишитесь",
|
||||
"privacyShort": "Конфиденциальность",
|
||||
"termsShort": "Условия"
|
||||
},
|
||||
"merge": {
|
||||
"title": "Объединить PDF",
|
||||
@@ -286,13 +288,14 @@
|
||||
"noCompromises": "Без компромиссов."
|
||||
},
|
||||
"mission": {
|
||||
"title": "Наша миссия",
|
||||
"title": "Наша",
|
||||
"titleDim": "миссия",
|
||||
"description": "Создать самый полный набор инструментов для работы с PDF, который соблюдает вашу приватность и не просит от вас денег. Мы верим, что основные инструменты для работы с документами должны быть доступны всем, везде, без ограничений."
|
||||
},
|
||||
"philosophy": {
|
||||
"label": "Наша основная философия",
|
||||
"title": "Приватность на первом месте. Всегда.",
|
||||
"description": "В современном мире данные превратились в товар, но у нас иной подход. Вся обработка инструментами Bentopdf происходит локально, в вашем браузере. То есть ваши файлы никак не взаимодействуют с нашими серверами, мы не видим ваши документы и не отслеживаем ваши действия. Приватность ваших документов — полная и безоговорочная. Это не какая-то одна из наших фич, это — основа."
|
||||
"description": "В современном мире данные превратились в товар, но у нас иной подход. Вся обработка инструментами BentoPDF происходит локально, в вашем браузере. То есть ваши файлы никак не взаимодействуют с нашими серверами, мы не видим ваши документы и не отслеживаем ваши действия. Приватность ваших документов полная и безоговорочная. Это не какая-то одна из наших фич, это основа."
|
||||
},
|
||||
"whyBentopdf": {
|
||||
"title": "Почему",
|
||||
@@ -321,7 +324,7 @@
|
||||
},
|
||||
"contact": {
|
||||
"title": "Связаться с нами",
|
||||
"subtitle": "Мы с радостью прочитаем ваши сообщения. Неважно, хотите ли вы задать вопрос, оставить обратную связь или попросить добавить новую функцию — не стесняйтесь, напишите нам!",
|
||||
"subtitle": "Мы с радостью прочитаем ваши сообщения. Неважно, хотите ли вы задать вопрос, оставить обратную связь или попросить добавить новую функцию, не стесняйтесь, напишите нам!",
|
||||
"email": "Вы можете написать нам на электронную почту:"
|
||||
},
|
||||
"licensing": {
|
||||
@@ -350,9 +353,12 @@
|
||||
"download": "Скачать:",
|
||||
"downloadSelected": "Скачать выбранное",
|
||||
"exportPdf": "Экспортировать PDF",
|
||||
"uploadPdfFiles": "Выбрать PDF-файлы",
|
||||
"dragAndDrop": "Перетащите PDF-файлы сюда или нажмите, чтобы выбрать",
|
||||
"uploadPdfFiles": "Выбрать PDF-файлы или изображения",
|
||||
"dragAndDrop": "Перетащите PDF-файлы или изображения сюда или нажмите, чтобы выбрать",
|
||||
"selectFiles": "Выбрать файлы",
|
||||
"dropToAdd": "Отпустите PDF-файлы или изображения, чтобы добавить",
|
||||
"convertingImages": "Преобразование изображений в PDF...",
|
||||
"failedToConvertImages": "Не удалось преобразовать изображения в PDF.",
|
||||
"renderingPages": "Отрисовка страниц...",
|
||||
"actions": {
|
||||
"duplicatePage": "Дублировать эту страницу",
|
||||
|
||||
@@ -55,6 +55,124 @@
|
||||
"name": "Редактор PDF",
|
||||
"subtitle": "Добавить аннотации, выделения и комментарии, вымарать текст, добавить фигуры/изображения, найти в тексте, просмотреть документ."
|
||||
},
|
||||
"editPdfText": {
|
||||
"name": "Редактирование текста PDF",
|
||||
"subtitle": "Нажать на любой абзац и отредактировать его на месте — с мгновенной перекомпоновкой текста, шрифтами и стилями.",
|
||||
"saved": "PDF успешно сохранён! ({{size}} КБ)",
|
||||
"failedToLoad": "Не удалось загрузить редактор текста PDF.",
|
||||
"loadingFonts": "Загрузка шрифтов...",
|
||||
"fontsUnavailable": "Не удалось загрузить шрифт, необходимый для некоторых символов. Проверьте подключение и повторите попытку, иначе эти символы могут отображаться неправильно в сохранённом PDF.",
|
||||
"howToUpload": "Загрузить PDF",
|
||||
"howToClick": "Нажмите на абзац",
|
||||
"howToRestyle": "Измените стиль",
|
||||
"relatedPdfEditor": "Комментируйте и размечайте PDF",
|
||||
"relatedSignPdf": "Нарисуйте, введите или загрузите подпись",
|
||||
"relatedWatermark": "Нанесите текст или изображения",
|
||||
"relatedStamps": "Размещайте штампы на страницах",
|
||||
"relatedCompress": "Уменьшите размер файла",
|
||||
"relatedOrganizeName": "Упорядочить PDF",
|
||||
"relatedOrganize": "Меняйте порядок и управляйте страницами",
|
||||
"open": "Открыть",
|
||||
"export": "Экспорт",
|
||||
"filterAll": "Все",
|
||||
"filterText": "Текст",
|
||||
"filterImages": "Изображения",
|
||||
"filterShapes": "Фигуры",
|
||||
"addText": "Добавить текст",
|
||||
"langAuto": "Авто",
|
||||
"change": "Изменить",
|
||||
"ignore": "Пропустить",
|
||||
"next": "Далее",
|
||||
"replace": "Заменить",
|
||||
"replaceAll": "Заменить все",
|
||||
"emptyState": "Откройте PDF, чтобы редактировать текст, изображения и фигуры.",
|
||||
"choosePdf": "Выберите PDF…",
|
||||
"font": "Шрифт",
|
||||
"systemFonts": "Системные шрифты",
|
||||
"color": "Цвет",
|
||||
"alignment": "Выравнивание",
|
||||
"style": "Стиль",
|
||||
"lists": "Списки",
|
||||
"outline": "Обводка",
|
||||
"spacing": "Интервал",
|
||||
"direction": "Направление",
|
||||
"dirAuto": "Авто",
|
||||
"pathStroke": "Обводка контура",
|
||||
"tipBackToUpload": "Назад к загрузке",
|
||||
"tipOpenAnotherPdf": "Открыть другой PDF",
|
||||
"tipExportS": "Экспорт (⌘S)",
|
||||
"tipUndoZ": "Отменить (⌘Z)",
|
||||
"tipRedoZ": "Повторить (⇧⌘Z)",
|
||||
"tipFileDetails": "Сведения о файле",
|
||||
"tipEditExistingContent": "Редактировать существующее содержимое",
|
||||
"tipWhatTheEditToolTouchesNarrowTheScopeOnBus": "На что действует инструмент редактирования — сузьте область на насыщенных страницах",
|
||||
"tipClickThePageToAddATextBox": "Нажмите на страницу, чтобы добавить текстовое поле",
|
||||
"tipSpellCheckLanguage": "Язык проверки орфографии",
|
||||
"tipFindAndReplace": "Найти и заменить",
|
||||
"tipAddAnImage": "Добавить изображение",
|
||||
"tipCopyThisPageSTextInReadingOrder": "Скопировать текст страницы в порядке чтения",
|
||||
"tipCheckTheSpellingOfThisPage": "Проверить орфографию на этой странице",
|
||||
"tipShowOrHideTheFormatPanel": "Показать или скрыть панель форматирования",
|
||||
"phReplaceWith": "Заменить на",
|
||||
"tipAddToYourDictionary": "Добавить в словарь",
|
||||
"tipClose": "Закрыть",
|
||||
"phFind": "Найти",
|
||||
"tipPreviousMatch": "Предыдущее совпадение",
|
||||
"tipNextMatch": "Следующее совпадение",
|
||||
"tipRotateLeft90": "Повернуть на 90° влево",
|
||||
"tipRotateRight90": "Повернуть на 90° вправо",
|
||||
"tipFlipHorizontal": "Отразить по горизонтали",
|
||||
"tipFlipVertical": "Отразить по вертикали",
|
||||
"tipReplaceThisImageKeepingItsPlacement": "Заменить изображение, сохранив положение",
|
||||
"tipAlternateTextForAccessibilityTaggedPdfs": "Альтернативный текст для доступности (теговые PDF)",
|
||||
"tipBringToFront": "На передний план",
|
||||
"tipSendToBack": "На задний план",
|
||||
"tipDuplicate": "Дублировать",
|
||||
"tipDelete": "Удалить",
|
||||
"tipAlignLeftEdges": "Выровнять по левым краям",
|
||||
"tipAlignHorizontalCenters": "Центрировать по горизонтали",
|
||||
"tipAlignRightEdges": "Выровнять по правым краям",
|
||||
"tipAlignTops": "Выровнять по верхним краям",
|
||||
"tipAlignVerticalCenters": "Центрировать по вертикали",
|
||||
"tipAlignBottoms": "Выровнять по нижним краям",
|
||||
"tipDistributeHorizontally": "Распределить по горизонтали",
|
||||
"tipDistributeVertically": "Распределить по вертикали",
|
||||
"tipFontSize": "Размер шрифта",
|
||||
"tipListFontsInstalledOnThisDeviceChromium": "Показать шрифты, установленные на этом устройстве (Chromium)",
|
||||
"tipCustomTextColor": "Свой цвет текста",
|
||||
"tipAlignLeft": "По левому краю",
|
||||
"tipAlignCenter": "По центру",
|
||||
"tipAlignRight": "По правому краю",
|
||||
"tipJustify": "По ширине",
|
||||
"tipBold": "Полужирный",
|
||||
"tipItalic": "Курсив",
|
||||
"tipUnderline": "Подчёркнутый",
|
||||
"tipStrikethrough": "Зачёркнутый",
|
||||
"tipSuperscript": "Верхний индекс",
|
||||
"tipSubscript": "Нижний индекс",
|
||||
"tipToggleBulletedItem": "Маркированный пункт",
|
||||
"tipToggleNumberedItem": "Нумерованный пункт",
|
||||
"tipNumberedListMarkerStyle": "Стиль маркера нумерованных списков",
|
||||
"tipDecreaseListIndentTab": "Уменьшить отступ (⇧Tab)",
|
||||
"tipIncreaseListIndentTab": "Увеличить отступ (Tab)",
|
||||
"tipTextOutlineColor": "Цвет контура текста",
|
||||
"tipOutlineWidth0None": "Толщина контура (0 = нет)",
|
||||
"tipFromContent": "Из содержимого",
|
||||
"tipLeftToRight": "Слева направо",
|
||||
"tipRightToLeft": "Справа налево",
|
||||
"tipStrokeColor": "Цвет обводки",
|
||||
"tipStrokeWidth": "Толщина обводки",
|
||||
"tipZoomPresets": "Предустановки масштаба",
|
||||
"tipZoomOut": "Уменьшить",
|
||||
"tipZoomIn": "Увеличить",
|
||||
"tipFitPage": "По размеру страницы",
|
||||
"tipPreviousPage": "Предыдущая страница",
|
||||
"tipTypeAPageNumberAndPressEnter": "Введите номер страницы и нажмите Enter",
|
||||
"tipNextPage": "Следующая страница",
|
||||
"tipDocumentProperties": "Свойства документа",
|
||||
"tipHideBar": "Скрыть панель",
|
||||
"tipShowBar": "Показать панель"
|
||||
},
|
||||
"jpgToPdf": {
|
||||
"name": "JPG в PDF",
|
||||
"subtitle": "Создать PDF из JPG, JPEG или JPEG2000 (JP2/JPX)."
|
||||
@@ -514,6 +632,51 @@
|
||||
"retainPageLabels": "Сохранять исходные метки страниц из каждого файла",
|
||||
"retainPageLabelsHint": "Выкл (по умолчанию): объединённый PDF использует естественную нумерацию страниц 1–N. Вкл: исходные метки страниц каждого файла сохраняются (могут появиться дубликаты)."
|
||||
},
|
||||
"duplexCollate": {
|
||||
"name": "Сортировка двустороннего сканирования",
|
||||
"subtitle": "Переупорядочивает PDF, отсканированный двумя блоками (сначала все лицевые стороны, затем все обороты), в правильный порядок лицевая/оборот.",
|
||||
"totalPagesLabel": "Всего страниц:",
|
||||
"splitAfterPageLabel": "Разделить после страницы",
|
||||
"splitAfterPagePlaceholder": "напр. 50",
|
||||
"backBlockOrderLabel": "Порядок блока оборотов",
|
||||
"backBlockReverseOption": "Обратить блок оборотов (обычно при перевёрнутой стопке)",
|
||||
"backBlockKeepOption": "Оставить блок оборотов без изменений",
|
||||
"autoSplitButton": "Определить разделение автоматически (половина)",
|
||||
"exportGroupedLabel": "Экспортировать файлы группами по длине исходного документа",
|
||||
"pagesPerDocumentLabel": "Страниц в исходном документе",
|
||||
"groupedHelp": "Если включено, результатом будет ZIP-архив с отдельным PDF для каждого сгруппированного документа.",
|
||||
"collateButton": "Собрать PDF",
|
||||
"invalidFileTitle": "Недопустимый файл",
|
||||
"invalidFileMessage": "Выберите файл PDF.",
|
||||
"loadingPdf": "Загрузка PDF...",
|
||||
"loadErrorMessage": "Не удалось загрузить файл PDF.",
|
||||
"fileMeta": "{{size}} - {{count}} стр.",
|
||||
"oddPageWarning": "Нечётное число страниц ({{count}}). При двустороннем сканировании число страниц должно быть чётным; возможно, страница пропущена или лишняя.",
|
||||
"previewSummary": "Блок лицевых сторон: {{frontCount}} стр., блок оборотов: {{backCount}} стр. Результат: {{outputCount}} стр. в порядке лицевая/оборот.",
|
||||
"previewMismatchWarning": "Длина блоков лицевых и оборотных сторон различается ({{frontCount}} лицевых против {{backCount}} оборотов). Лишние страницы ({{extraCount}}) из более длинного блока будут добавлены без пары в конец.",
|
||||
"missingFileTitle": "Файл не выбран",
|
||||
"missingFileMessage": "Перед обработкой загрузите PDF не менее чем с 2 страницами.",
|
||||
"invalidSplitTitle": "Недопустимая точка разделения",
|
||||
"invalidSplitMessage": "Точка разделения должна быть между страницей 1 и страницей {{maxSplit}}.",
|
||||
"unevenConfirmTitle": "Неравные блоки",
|
||||
"unevenConfirmMessage": "В блоке лицевых сторон {{frontCount}} стр., в блоке оборотов — {{backCount}} стр.\nОбычно это означает, что страница отсканирована дважды или отсутствует.\n\nСтраницы без пары ({{extraCount}}) будут добавлены в конец.\n\nВсё равно продолжить?",
|
||||
"invalidGroupTitle": "Недопустимый размер группы",
|
||||
"invalidGroupMessage": "Введите допустимое число страниц в исходном документе.",
|
||||
"collatingLoader": "Сборка двустороннего сканирования...",
|
||||
"successMessage": "Собранный PDF успешно создан.",
|
||||
"successGroupedMessage": "Сборка завершена. Создано файлов: {{fileCount}}.",
|
||||
"processErrorMessage": "Не удалось собрать PDF.",
|
||||
"howItWorksStep1Title": "Загрузите скан",
|
||||
"howItWorksStep1": "Перетащите один PDF, в котором сначала идут все лицевые стороны, а затем все обороты.",
|
||||
"howItWorksStep2Title": "Задайте точку разделения",
|
||||
"howItWorksStep2": "Укажите, где заканчивается блок лицевых сторон, и выберите, нужно ли обращать блок оборотов.",
|
||||
"howItWorksStep3Title": "Соберите и скачайте",
|
||||
"howItWorksStep3": "Вы получите один PDF с чередованием страниц или ZIP-архив с отдельным файлом для каждого исходного документа.",
|
||||
"faqOddPagesQuestion": "Что делать, если в скане нечётное число страниц?",
|
||||
"faqOddPagesAnswer": "При двустороннем сканировании число страниц должно быть чётным. Если это не так, страница, скорее всего, отсканирована дважды или пропущена. Инструмент предупредит вас перед обработкой, а страницы без пары будут добавлены в конец, чтобы ничего не потерялось.",
|
||||
"faqBackOrderQuestion": "Зачем оставлять блок оборотов без изменений?",
|
||||
"faqBackOrderAnswer": "Это зависит от того, как стопка подавалась на втором проходе. Если перевернуть всю стопку целиком, обороты идут в обратном порядке — это вариант по умолчанию. Если сканер выдал их в том же порядке, что и лицевые стороны, выберите вариант «оставить без изменений»."
|
||||
},
|
||||
"addAttachments": {
|
||||
"name": "Добавление вложений",
|
||||
"subtitle": "Вложить один или несколько файлов в документ."
|
||||
@@ -1151,5 +1314,13 @@
|
||||
"faqSinglePageAnswer": "Да! Включите опцию \"Повтор\" и страницы наложения будут повторяться на всех страницах базового файла. Одностраничный водяной знак будет применён к каждой странице.",
|
||||
"faqPrivacyQuestion": "Мои файлы конфиденциальны и защищены?",
|
||||
"faqPrivacyAnswer": "Безусловно! Вся обработка происходит в вашем браузере. Ваши файлы никогда не покидают ваше устройство, обеспечивая полную конфиденциальность."
|
||||
},
|
||||
"unlockPdf": {
|
||||
"name": "Расшифровка документа",
|
||||
"subtitle": "Снять защиту документа, удалив пароль."
|
||||
},
|
||||
"protectPdf": {
|
||||
"name": "Шифрование документа",
|
||||
"subtitle": "Защитить документ с помощью пароля."
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user