Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
| 🇵🇹 Português | [pdflince.com/pt](https://pdflince.com/pt?utm_source=github&utm_medium=readme&utm_campaign=pdflince_public) |
| 🇮🇹 Italiano | [pdflince.com/it](https://pdflince.com/it?utm_source=github&utm_medium=readme&utm_campaign=pdflince_public) |
| 🇷🇴 Română | [pdflince.com/ro](https://pdflince.com/ro?utm_source=github&utm_medium=readme&utm_campaign=pdflince_public) |
| 🇷🇺 Русский | [pdflince.com/ru](https://pdflince.com/ru?utm_source=github&utm_medium=readme&utm_campaign=pdflince_public) |
| 🇭🇺 Magyar | [pdflince.com/hu](https://pdflince.com/hu?utm_source=github&utm_medium=readme&utm_campaign=pdflince_public) |

## Why PDFLince?

Expand All @@ -38,7 +40,7 @@ Most online PDF tools require you to upload your sensitive documents to their cl
- **Crop**: Crop PDF pages manually with visual selection or by specifying precise values
- **Rotate**: Rotate selected pages and preview changes in real-time before exporting.
- **Secure**: 100% local processing verifiable via Network tab.
- **Multilingual**: Native support for English, Spanish, French, German, Portuguese, Italian, Romanian.
- **Multilingual**: Native support for 9 languages (English, Spanish, French, German, Portuguese, Italian, Romanian, Russian, Hungarian).

## Architecture

Expand Down
48 changes: 36 additions & 12 deletions content/i18n-route-map.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
"de": "/de",
"it": "/it",
"fr": "/fr",
"ro": "/ro"
"ro": "/ro",
"ru": "/ru",
"hu": "/hu"
},
"faq": {
"es": "/preguntas-frecuentes",
Expand All @@ -15,7 +17,9 @@
"de": "/de/haeufige-fragen",
"it": "/it/faq",
"fr": "/fr/faq",
"ro": "/ro/intrebari-frecvente"
"ro": "/ro/intrebari-frecvente",
"ru": "/ru/chasto-zadavaemye-voprosy",
"hu": "/hu/gyakran-ismetelt-kerdesek"
},
"support": {
"es": "/apoya",
Expand All @@ -24,7 +28,9 @@
"de": "/de/unterstuetzen",
"it": "/it/supporto",
"fr": "/fr/soutenir",
"ro": "/ro/sustine"
"ro": "/ro/sustine",
"ru": "/ru/podderzhka",
"hu": "/hu/tamogatas"
},
"operations": {
"compress": {
Expand All @@ -34,7 +40,9 @@
"de": "/de/komprimieren",
"it": "/it/comprimi",
"fr": "/fr/compresser",
"ro": "/ro/comprima"
"ro": "/ro/comprima",
"ru": "/ru/szhat",
"hu": "/hu/tomoriteni"
},
"merge": {
"es": "/unir",
Expand All @@ -43,7 +51,9 @@
"de": "/de/zusammenfuehren",
"it": "/it/unisci",
"fr": "/fr/fusionner",
"ro": "/ro/uneste"
"ro": "/ro/uneste",
"ru": "/ru/obedinit",
"hu": "/hu/osszefuzni"
},
"split": {
"es": "/dividir",
Expand All @@ -52,7 +62,9 @@
"de": "/de/teilen",
"it": "/it/dividi",
"fr": "/fr/diviser",
"ro": "/ro/divide"
"ro": "/ro/divide",
"ru": "/ru/razdelit",
"hu": "/hu/szetbontas"
},
"extract": {
"es": "/extraer",
Expand All @@ -61,7 +73,9 @@
"de": "/de/seiten-extrahieren",
"it": "/it/estrai",
"fr": "/fr/extraire",
"ro": "/ro/extrage"
"ro": "/ro/extrage",
"ru": "/ru/izvlech",
"hu": "/hu/kivalasztani"
},
"crop": {
"es": "/recortar",
Expand All @@ -70,7 +84,9 @@
"de": "/de/zuschneiden",
"it": "/it/ritaglia",
"fr": "/fr/recadrer",
"ro": "/ro/decupeaza"
"ro": "/ro/decupeaza",
"ru": "/ru/obrezat",
"hu": "/hu/korulvagas"
},
"rotate": {
"es": "/girar",
Expand All @@ -79,7 +95,9 @@
"de": "/de/drehen",
"it": "/it/ruota",
"fr": "/fr/faire-pivoter",
"ro": "/ro/roteste"
"ro": "/ro/roteste",
"ru": "/ru/povernut",
"hu": "/hu/forgatas"
},
"reorder": {
"es": "/reordenar",
Expand All @@ -88,7 +106,9 @@
"de": "/de/seiten-sortieren",
"it": "/it/riordina",
"fr": "/fr/reorganiser",
"ro": "/ro/reordoneaza"
"ro": "/ro/reordoneaza",
"ru": "/ru/pereupordochit",
"hu": "/hu/atrendezni"
},
"pdfToImages": {
"es": "/convertir-pdf-a-imagenes",
Expand All @@ -97,7 +117,9 @@
"de": "/de/pdf-zu-bildern",
"it": "/it/da-pdf-a-immagini",
"fr": "/fr/pdf-en-images",
"ro": "/ro/pdf-in-imagini"
"ro": "/ro/pdf-in-imagini",
"ru": "/ru/pdf-v-izobrazheniya",
"hu": "/hu/pdf-kepekbe"
},
"imagesToPdf": {
"es": "/crear-pdf-desde-imagenes",
Expand All @@ -106,7 +128,9 @@
"de": "/de/bilder-zu-pdf",
"it": "/it/da-immagini-a-pdf",
"fr": "/fr/creer-pdf-depuis-images",
"ro": "/ro/imagini-in-pdf"
"ro": "/ro/imagini-in-pdf",
"ru": "/ru/izobrazheniya-v-pdf",
"hu": "/hu/kepek-pdf-be"
}
}
}
4 changes: 4 additions & 0 deletions src/app/(es)/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ export const metadata = {
'it-IT': 'https://pdflince.com/it/',
'ro': 'https://pdflince.com/ro/',
'ro-RO': 'https://pdflince.com/ro/',
'ru': 'https://pdflince.com/ru/',
'ru-RU': 'https://pdflince.com/ru/',
'hu': 'https://pdflince.com/hu/',
'hu-HU': 'https://pdflince.com/hu/',
'x-default': 'https://pdflince.com/',
},
},
Expand Down
4 changes: 4 additions & 0 deletions src/app/de/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ export const metadata = {
'it-IT': 'https://pdflince.com/it/',
'ro': 'https://pdflince.com/ro/',
'ro-RO': 'https://pdflince.com/ro/',
'ru': 'https://pdflince.com/ru/',
'ru-RU': 'https://pdflince.com/ru/',
'hu': 'https://pdflince.com/hu/',
'hu-HU': 'https://pdflince.com/hu/',
'x-default': 'https://pdflince.com/',
},
},
Expand Down
4 changes: 4 additions & 0 deletions src/app/en/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ export const metadata = {
'it-IT': 'https://pdflince.com/it/',
'ro': 'https://pdflince.com/ro/',
'ro-RO': 'https://pdflince.com/ro/',
'ru': 'https://pdflince.com/ru/',
'ru-RU': 'https://pdflince.com/ru/',
'hu': 'https://pdflince.com/hu/',
'hu-HU': 'https://pdflince.com/hu/',
'x-default': 'https://pdflince.com/',
},
},
Expand Down
4 changes: 4 additions & 0 deletions src/app/fr/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ export const metadata = {
'it-IT': 'https://pdflince.com/it/',
'ro': 'https://pdflince.com/ro/',
'ro-RO': 'https://pdflince.com/ro/',
'ru': 'https://pdflince.com/ru/',
'ru-RU': 'https://pdflince.com/ru/',
'hu': 'https://pdflince.com/hu/',
'hu-HU': 'https://pdflince.com/hu/',
'x-default': 'https://pdflince.com/',
},
},
Expand Down
8 changes: 8 additions & 0 deletions src/app/hu/(operations)/[operation]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { createLocaleOperationHandlers } from "../../../(helpers)/operation-handlers";

const LOCALE = "hu" as const;

const { generateStaticParams, generateMetadata, OperationPage } = createLocaleOperationHandlers(LOCALE);

export { generateStaticParams, generateMetadata };
export default OperationPage;
12 changes: 12 additions & 0 deletions src/app/hu/gyakran-ismetelt-kerdesek/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { FaqPageContent } from "../../../components/FaqPageContent";
import { getDictionary } from "../../../i18n/get-dictionary";
import { createFaqMetadata } from "../../(helpers)/locale-metadata";

const LOCALE = "hu" as const;

export const generateMetadata = createFaqMetadata(LOCALE);

export default function HuFaqPage() {
const dictionary = getDictionary(LOCALE);
return <FaqPageContent dictionary={dictionary} />;
}
85 changes: 85 additions & 0 deletions src/app/hu/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
import "../../styles/globals.css";
import { Suspense, type ReactNode } from "react";
import { GeistSans } from "geist/font/sans";
import { GeistMono } from "geist/font/mono";
import NavMenu from "../../components/NavMenu";
import Footer from "../../components/Footer";
import FotoLinceBanner from "../../components/FotoLinceBanner";
import { LocaleProvider } from "../../i18n/LocaleProvider";
import { GoogleAnalyticsScripts } from "../../components/analytics/GoogleAnalyticsScripts";
import { GaPageViewTracker } from "../../components/analytics/GaPageViewTracker";
import { WebVitalsReporter } from "../../components/analytics/WebVitalsReporter";
import CookieBanner from "../../components/CookieBanner";
import { SchemaOrg } from "../../components/SchemaOrg";

import { METADATA_BASE, SHARED_ICONS, SHARED_OPEN_GRAPH, SHARED_TWITTER } from "../../lib/metadata-shared";

const LOCALE = "hu" as const;

export const metadata = {
metadataBase: METADATA_BASE,
title: "PDFLince - PDF tömörítése, egyesítése, felosztása és konvertálása",
description: "Ingyenes online PDF-eszközök: tömörítés, egyesítés, felosztás, kinyerés és konvertálás. 100% privát, helyi feldolgozás a böngésződben.",
icons: SHARED_ICONS,
alternates: {
canonical: "https://pdflince.com/hu/",
languages: {
'es-ES': 'https://pdflince.com/',
'es-MX': 'https://pdflince.com/',
'es-CO': 'https://pdflince.com/',
'es-AR': 'https://pdflince.com/',
'es': 'https://pdflince.com/',
'en': 'https://pdflince.com/en/',
'en-US': 'https://pdflince.com/en/',
'fr': 'https://pdflince.com/fr/',
'fr-FR': 'https://pdflince.com/fr/',
'pt': 'https://pdflince.com/pt/',
'pt-BR': 'https://pdflince.com/pt/',
'pt-PT': 'https://pdflince.com/pt/',
'de': 'https://pdflince.com/de/',
'de-DE': 'https://pdflince.com/de/',
'it': 'https://pdflince.com/it/',
'it-IT': 'https://pdflince.com/it/',
'ro': 'https://pdflince.com/ro/',
'ro-RO': 'https://pdflince.com/ro/',
'ru': 'https://pdflince.com/ru/',
'ru-RU': 'https://pdflince.com/ru/',
'hu': 'https://pdflince.com/hu/',
'hu-HU': 'https://pdflince.com/hu/',
'x-default': 'https://pdflince.com/',
},
},
openGraph: {
...SHARED_OPEN_GRAPH,
title: "PDFLince - Ingyenes és privát PDF-eszközök a böngésződben",
description: "Egyesítsd, tömörítsd, oszd fel és konvertáld a PDF-eket szerverre feltöltés nélkül. Biztonságos és 100% privát.",
url: "https://pdflince.com/hu/",
locale: "hu_HU",
type: "website",
},
twitter: SHARED_TWITTER,
};

export default function HuLayout({ children }: { children: ReactNode }) {
return (
<html lang={LOCALE}>
<head>
<GoogleAnalyticsScripts />
<SchemaOrg />
</head>
<body className={`font-sans ${GeistSans.variable} ${GeistMono.variable}`}>
<LocaleProvider locale={LOCALE}>
<WebVitalsReporter />
<Suspense fallback={null}>
<GaPageViewTracker />
</Suspense>
<NavMenu />
<main>{children}</main>
<FotoLinceBanner />
<Footer />
<CookieBanner />
</LocaleProvider>
</body>
</html>
);
}
12 changes: 12 additions & 0 deletions src/app/hu/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { HomePageContent } from "../../components/HomePageContent";
import { getDictionary } from "../../i18n/get-dictionary";
import { createHomeMetadata } from "../(helpers)/locale-metadata";

const LOCALE = "hu" as const;

export const generateMetadata = createHomeMetadata(LOCALE);

export default function HuHomePage() {
const dictionary = getDictionary(LOCALE);
return <HomePageContent dictionary={dictionary} />;
}
10 changes: 10 additions & 0 deletions src/app/hu/tamogatas/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { SupportPageContent } from "../../../components/SupportPageContent";
import { createSupportMetadata } from "../../(helpers)/locale-metadata";

const LOCALE = "hu" as const;

export const generateMetadata = createSupportMetadata(LOCALE);

export default function HuSupportPage() {
return <SupportPageContent />;
}
4 changes: 4 additions & 0 deletions src/app/it/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ export const metadata = {
'it-IT': 'https://pdflince.com/it/',
'ro': 'https://pdflince.com/ro/',
'ro-RO': 'https://pdflince.com/ro/',
'ru': 'https://pdflince.com/ru/',
'ru-RU': 'https://pdflince.com/ru/',
'hu': 'https://pdflince.com/hu/',
'hu-HU': 'https://pdflince.com/hu/',
'x-default': 'https://pdflince.com/',
},
},
Expand Down
4 changes: 4 additions & 0 deletions src/app/pt/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ export const metadata = {
'it-IT': 'https://pdflince.com/it/',
'ro': 'https://pdflince.com/ro/',
'ro-RO': 'https://pdflince.com/ro/',
'ru': 'https://pdflince.com/ru/',
'ru-RU': 'https://pdflince.com/ru/',
'hu': 'https://pdflince.com/hu/',
'hu-HU': 'https://pdflince.com/hu/',
'x-default': 'https://pdflince.com/',
},
},
Expand Down
9 changes: 7 additions & 2 deletions src/app/ro/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { WebVitalsReporter } from "../../components/analytics/WebVitalsReporter"
import CookieBanner from "../../components/CookieBanner";
import { SchemaOrg } from "../../components/SchemaOrg";

import { METADATA_BASE, SHARED_ICONS, SHARED_OPEN_GRAPH } from "../../lib/metadata-shared";
import { METADATA_BASE, SHARED_ICONS, SHARED_OPEN_GRAPH, SHARED_TWITTER } from "../../lib/metadata-shared";

const LOCALE = "ro" as const;

Expand Down Expand Up @@ -42,17 +42,22 @@ export const metadata = {
'it-IT': 'https://pdflince.com/it/',
'ro': 'https://pdflince.com/ro/',
'ro-RO': 'https://pdflince.com/ro/',
'ru': 'https://pdflince.com/ru/',
'ru-RU': 'https://pdflince.com/ru/',
'hu': 'https://pdflince.com/hu/',
'hu-HU': 'https://pdflince.com/hu/',
'x-default': 'https://pdflince.com/',
},
},
openGraph: {
...SHARED_OPEN_GRAPH,
title: "PDFLince - Instrumente PDF gratuite și private în browserul tău",
description: "Unește, comprimă, divide și convertește PDF-uri fără a încărca fișierele pe server. Securizat și 100% privat.",
url: "https://pdflince.com/ro",
url: "https://pdflince.com/ro/",
locale: "ro_RO",
type: "website",
},
twitter: SHARED_TWITTER,
};

export default function RoLayout({ children }: { children: ReactNode }) {
Expand Down
8 changes: 8 additions & 0 deletions src/app/ru/(operations)/[operation]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { createLocaleOperationHandlers } from "../../../(helpers)/operation-handlers";

const LOCALE = "ru" as const;

const { generateStaticParams, generateMetadata, OperationPage } = createLocaleOperationHandlers(LOCALE);

export { generateStaticParams, generateMetadata };
export default OperationPage;
Loading
Loading