Add translation support for website
All checks were successful
Queue Release Build / prepare (push) Successful in 1m20s
Deploy Web Apps / deploy (push) Successful in 17m37s
Queue Release Build / build-windows (push) Successful in 39m8s
Queue Release Build / build-linux (push) Successful in 1h3m53s
Queue Release Build / finalize (push) Successful in 5m43s

This commit is contained in:
2026-03-13 03:45:17 +01:00
parent 2b6e477c9a
commit 00adf39121
26 changed files with 788 additions and 286 deletions

View File

@@ -4,11 +4,11 @@
<div
class="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-purple-500/10 border border-purple-500/20 text-purple-400 text-sm font-medium mb-6"
>
Image Gallery
{{ 'pages.gallery.hero.badge' | translate }}
</div>
<h1 class="text-4xl md:text-6xl font-extrabold text-foreground mb-6">A closer look at <span class="gradient-text">Toju</span></h1>
<h1 class="text-4xl md:text-6xl font-extrabold text-foreground mb-6">{{ 'pages.gallery.hero.titlePrefix' | translate }} <span class="gradient-text">{{ 'common.brand' | translate }}</span></h1>
<p class="text-lg text-muted-foreground leading-relaxed">
Explore screenshots of the app experience, from voice chat and media sharing to servers, rooms, and full-screen collaboration.
{{ 'pages.gallery.hero.description' | translate }}
</p>
</div>
</section>
@@ -19,7 +19,7 @@
<div class="relative aspect-[16/9]">
<img
ngSrc="/images/screenshots/screenshot_main.png"
alt="Toju main application screenshot"
[attr.alt]="'pages.gallery.featured.imageAlt' | translate"
fill
priority
sizes="(min-width: 1536px) 75vw, (min-width: 1280px) 90vw, 100vw"
@@ -27,10 +27,10 @@
/>
</div>
<div class="absolute inset-x-0 bottom-0 bg-gradient-to-t from-background via-background/80 to-transparent p-6 md:p-8">
<p class="text-xs font-semibold uppercase tracking-[0.2em] text-purple-400 mb-2">Featured</p>
<h2 class="text-2xl md:text-3xl font-bold text-foreground mb-2">The full Toju workspace</h2>
<p class="text-xs font-semibold uppercase tracking-[0.2em] text-purple-400 mb-2">{{ 'pages.gallery.featured.label' | translate }}</p>
<h2 class="text-2xl md:text-3xl font-bold text-foreground mb-2">{{ 'pages.gallery.featured.title' | translate }}</h2>
<p class="max-w-2xl text-sm md:text-base text-muted-foreground">
See the main interface where rooms, messages, presence, and media all come together in one focused layout.
{{ 'pages.gallery.featured.description' | translate }}
</p>
</div>
</div>
@@ -52,15 +52,15 @@
<div class="relative aspect-video overflow-hidden">
<img
[ngSrc]="item.src"
[alt]="item.title"
[attr.alt]="item.titleKey | translate"
fill
sizes="(max-width: 768px) 100vw, (max-width: 1280px) 50vw, 33vw"
class="object-cover transition-transform duration-500 group-hover:scale-105"
/>
</div>
<div class="p-5">
<h3 class="text-lg font-semibold text-foreground mb-2">{{ item.title }}</h3>
<p class="text-sm text-muted-foreground leading-relaxed">{{ item.description }}</p>
<h3 class="text-lg font-semibold text-foreground mb-2">{{ item.titleKey | translate }}</h3>
<p class="text-sm text-muted-foreground leading-relaxed">{{ item.descriptionKey | translate }}</p>
</div>
</a>
}
@@ -72,14 +72,14 @@
<div
class="max-w-4xl mx-auto section-fade rounded-3xl border border-purple-500/20 bg-gradient-to-br from-purple-950/20 to-violet-950/20 p-8 md:p-10 text-center"
>
<h2 class="text-2xl md:text-3xl font-bold text-foreground mb-4">Want to see it in action?</h2>
<p class="text-muted-foreground leading-relaxed mb-6">Download Toju or jump into the browser experience and explore the interface yourself.</p>
<h2 class="text-2xl md:text-3xl font-bold text-foreground mb-4">{{ 'pages.gallery.cta.title' | translate }}</h2>
<p class="text-muted-foreground leading-relaxed mb-6">{{ 'pages.gallery.cta.description' | translate }}</p>
<div class="flex flex-col sm:flex-row items-center justify-center gap-4">
<a
routerLink="/downloads"
class="inline-flex items-center gap-2 px-6 py-3 rounded-xl bg-gradient-to-r from-purple-600 to-violet-600 text-white font-semibold hover:from-purple-500 hover:to-violet-500 transition-all shadow-lg shadow-purple-500/25"
>
Go to downloads
{{ 'common.actions.goToDownloads' | translate }}
</a>
<a
href="https://web.toju.app/"
@@ -87,7 +87,7 @@
rel="noopener"
class="inline-flex items-center gap-2 px-6 py-3 rounded-xl border border-border/50 bg-card/50 text-foreground font-medium hover:border-purple-500/30 transition-all"
>
Open web version
{{ 'common.actions.openWebVersion' | translate }}
</a>
</div>
</div>

View File

@@ -7,6 +7,7 @@ import {
inject
} from '@angular/core';
import { isPlatformBrowser, NgOptimizedImage } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { RouterLink } from '@angular/router';
import { AdSlotComponent } from '../../components/ad-slot/ad-slot.component';
import { ScrollAnimationService } from '../../services/scroll-animation.service';
@@ -14,8 +15,8 @@ import { SeoService } from '../../services/seo.service';
interface GalleryItem {
src: string;
title: string;
description: string;
titleKey: string;
descriptionKey: string;
}
@Component({
@@ -23,6 +24,7 @@ interface GalleryItem {
standalone: true,
imports: [
NgOptimizedImage,
TranslateModule,
RouterLink,
AdSlotComponent
],
@@ -32,38 +34,38 @@ export class GalleryComponent implements OnInit, AfterViewInit, OnDestroy {
readonly galleryItems: GalleryItem[] = [
{
src: '/images/screenshots/screenshot_main.png',
title: 'Main chat view',
description: 'The core Toju experience with channels, messages, and direct communication tools.'
titleKey: 'pages.gallery.items.mainChatView.title',
descriptionKey: 'pages.gallery.items.mainChatView.description'
},
{
src: '/images/screenshots/screenshare_gaming.png',
title: 'Gaming screen share',
description: 'Share gameplay, guides, and live moments with smooth full-resolution screen sharing.'
titleKey: 'pages.gallery.items.gamingScreenShare.title',
descriptionKey: 'pages.gallery.items.gamingScreenShare.description'
},
{
src: '/images/screenshots/serverViewScreen.png',
title: 'Server overview',
description: 'Navigate servers and rooms with a layout designed for clarity and speed.'
titleKey: 'pages.gallery.items.serverOverview.title',
descriptionKey: 'pages.gallery.items.serverOverview.description'
},
{
src: '/images/screenshots/music.png',
title: 'Music and voice',
description: 'Stay in sync with voice and media features in a focused, low-friction interface.'
titleKey: 'pages.gallery.items.musicAndVoice.title',
descriptionKey: 'pages.gallery.items.musicAndVoice.description'
},
{
src: '/images/screenshots/videos.png',
title: 'Video sharing',
description: 'Preview and share visual content directly with your friends and communities.'
titleKey: 'pages.gallery.items.videoSharing.title',
descriptionKey: 'pages.gallery.items.videoSharing.description'
},
{
src: '/images/screenshots/filedownload.png',
title: 'File transfers',
description: 'Move files quickly without artificial size limits or unnecessary hoops.'
titleKey: 'pages.gallery.items.fileTransfers.title',
descriptionKey: 'pages.gallery.items.fileTransfers.description'
},
{
src: '/images/screenshots/gif.png',
title: 'Rich media chat',
description: 'Conversations stay lively with visual media support built right in.'
titleKey: 'pages.gallery.items.richMediaChat.title',
descriptionKey: 'pages.gallery.items.richMediaChat.description'
}
];
@@ -72,9 +74,7 @@ export class GalleryComponent implements OnInit, AfterViewInit, OnDestroy {
private readonly platformId = inject(PLATFORM_ID);
ngOnInit(): void {
this.seoService.update({
title: 'Toju Image Gallery',
description: 'Browse screenshots of Toju and explore the interface for chat, file sharing, voice, and screen sharing.',
this.seoService.updateFromTranslations('pages.gallery.seo', {
url: 'https://toju.app/gallery'
});
}