Merge pull request #97 from Tazi0/feature/dutch-translations

feat: Dutch translations
This commit is contained in:
edde746
2025-11-13 10:56:19 +01:00
committed by GitHub
7 changed files with 1364 additions and 45 deletions
+944 -3
View File
File diff suppressed because it is too large Load Diff
+4 -2
View File
@@ -132,7 +132,9 @@
},
"search": {
"hint": "Search movies, shows, music...",
"tryDifferentTerm": "Try a different search term"
"tryDifferentTerm": "Try a different search term",
"searchYourMedia": "Search your media",
"enterTitleActorOrKeyword": "Enter a title, actor, or keyword"
},
"hotkeys": {
"setShortcutFor": "Set Shortcut for ${actionName}",
@@ -363,4 +365,4 @@
"libraries": "Libraries",
"settings": "Settings"
}
}
}
+3 -1
View File
@@ -132,7 +132,9 @@
},
"search": {
"hint": "Cerca film. spettacoli, musica...",
"tryDifferentTerm": "Prova altri termini di ricerca"
"tryDifferentTerm": "Prova altri termini di ricerca",
"searchYourMedia": "Cerca nei tuoi media",
"enterTitleActorOrKeyword": "Inserisci un titolo, attore o parola chiave"
},
"hotkeys": {
"setShortcutFor": "Imposta scorciatoia per ${actionName}",
+368
View File
@@ -0,0 +1,368 @@
{
"app": {
"title": "Plezy",
"loading": "Laden..."
},
"auth": {
"signInWithPlex": "Inloggen met Plex",
"showQRCode": "Toon QR-code",
"cancel": "Annuleren",
"authenticate": "Authenticeren",
"retry": "Opnieuw proberen",
"debugEnterToken": "Debug: Voer Plex Token in",
"plexTokenLabel": "Plex Auth Token",
"plexTokenHint": "Voer je Plex.tv token in",
"authenticationTimeout": "Authenticatie verlopen. Probeer opnieuw.",
"scanQRCodeInstruction": "Scan deze QR-code met een apparaat dat is ingelogd op Plex om te authenticeren.",
"waitingForAuth": "Wachten op authenticatie...\nVoltooi het inloggen in je browser."
},
"common": {
"cancel": "Annuleren",
"save": "Opslaan",
"close": "Sluiten",
"clear": "Wissen",
"reset": "Resetten",
"later": "Later",
"submit": "Verzenden",
"confirm": "Bevestigen",
"retry": "Opnieuw proberen",
"playNow": "Nu afspelen",
"logout": "Uitloggen",
"online": "Online",
"offline": "Offline",
"owned": "Eigendom",
"shared": "Gedeeld",
"current": "HUIDIG",
"unknown": "Onbekend",
"refresh": "Vernieuwen",
"yes": "Ja",
"no": "Nee",
"server": "Server"
},
"screens": {
"licenses": "Licenties",
"selectServer": "Selecteer server",
"switchProfile": "Wissel van profiel",
"subtitleStyling": "Ondertitel opmaak",
"search": "Zoeken",
"logs": "Logs"
},
"update": {
"available": "Update beschikbaar",
"versionAvailable": "Versie ${version} is beschikbaar",
"currentVersion": "Huidig: ${version}",
"skipVersion": "Deze versie overslaan",
"viewRelease": "Bekijk release",
"latestVersion": "Je hebt de nieuwste versie",
"checkFailed": "Kon niet controleren op updates"
},
"settings": {
"title": "Instellingen",
"language": "Taal",
"theme": "Thema",
"appearance": "Uiterlijk",
"videoPlayback": "Video afspelen",
"shufflePlay": "Willekeurig afspelen",
"advanced": "Geavanceerd",
"useSeasonPostersDescription": "Toon seizoenposter in plaats van serieposter voor afleveringen",
"showHeroSectionDescription": "Toon uitgelichte inhoud carrousel op startscherm",
"secondsLabel": "Seconden",
"minutesLabel": "Minuten",
"secondsShort": "s",
"minutesShort": "m",
"durationHint": "Voer duur in (${min}-${max})",
"systemTheme": "Systeem",
"systemThemeDescription": "Volg systeeminstellingen",
"lightTheme": "Licht",
"darkTheme": "Donker",
"libraryDensity": "Bibliotheek dichtheid",
"compact": "Compact",
"compactDescription": "Kleinere kaarten, meer items zichtbaar",
"normal": "Normaal",
"normalDescription": "Standaard grootte",
"comfortable": "Comfortabel",
"comfortableDescription": "Grotere kaarten, minder items zichtbaar",
"viewMode": "Weergavemodus",
"gridView": "Raster",
"gridViewDescription": "Items weergeven in een rasterindeling",
"listView": "Lijst",
"listViewDescription": "Items weergeven in een lijstindeling",
"useSeasonPosters": "Gebruik seizoenposters",
"showHeroSection": "Toon hoofdsectie",
"hardwareDecoding": "Hardware decodering",
"hardwareDecodingDescription": "Gebruik hardware versnelling indien beschikbaar",
"bufferSize": "Buffer grootte",
"bufferSizeMB": "${size}MB",
"subtitleStyling": "Ondertitel opmaak",
"subtitleStylingDescription": "Pas ondertitel uiterlijk aan",
"smallSkipDuration": "Korte skip duur",
"largeSkipDuration": "Lange skip duur",
"secondsUnit": "${seconds} seconden",
"defaultSleepTimer": "Standaard slaap timer",
"minutesUnit": "bij ${minutes} minuten",
"unwatchedOnly": "Alleen ongekeken",
"unwatchedOnlyDescription": "Alleen ongekeken afleveringen opnemen in willekeurige wachtrij",
"shuffleOrderNavigation": "Willekeurige volgorde navigatie",
"shuffleOrderNavigationDescription": "Volgende/vorige knoppen volgen willekeurige volgorde",
"loopShuffleQueue": "Herhaal willekeurige wachtrij",
"loopShuffleQueueDescription": "Start wachtrij opnieuw bij het einde",
"videoPlayerControls": "Videospeler bediening",
"keyboardShortcuts": "Toetsenbord sneltoetsen",
"keyboardShortcutsDescription": "Pas toetsenbord sneltoetsen aan",
"debugLogging": "Debug logging",
"debugLoggingDescription": "Schakel gedetailleerde logging in voor probleemoplossing",
"viewLogs": "Bekijk logs",
"viewLogsDescription": "Bekijk applicatie logs",
"clearCache": "Cache wissen",
"clearCacheDescription": "Dit wist alle gecachte afbeeldingen en gegevens. De app kan langer duren om inhoud te laden na het wissen van de cache.",
"clearCacheSuccess": "Cache succesvol gewist",
"resetSettings": "Instellingen resetten",
"resetSettingsDescription": "Dit reset alle instellingen naar hun standaard waarden. Deze actie kan niet ongedaan gemaakt worden.",
"resetSettingsSuccess": "Instellingen succesvol gereset",
"shortcutsReset": "Sneltoetsen gereset naar standaard",
"about": "Over",
"aboutDescription": "App informatie en licenties",
"updates": "Updates",
"updateAvailable": "Update beschikbaar",
"checkForUpdates": "Controleer op updates",
"validationErrorEnterNumber": "Voer een geldig nummer in",
"validationErrorDuration": "Duur moet tussen ${min} en ${max} ${unit} zijn",
"shortcutAlreadyAssigned": "Sneltoets al toegewezen aan ${action}",
"shortcutUpdated": "Sneltoets bijgewerkt voor ${action}"
},
"search": {
"hint": "Zoek films, series, muziek...",
"tryDifferentTerm": "Probeer een andere zoekterm",
"searchYourMedia": "Zoek in je media",
"enterTitleActorOrKeyword": "Voer een titel, acteur of trefwoord in"
},
"hotkeys": {
"setShortcutFor": "Stel sneltoets in voor ${actionName}",
"clearShortcut": "Wis sneltoets"
},
"pinEntry": {
"enterPin": "Voer PIN in",
"showPin": "Toon PIN",
"hidePin": "Verberg PIN"
},
"fileInfo": {
"title": "Bestand info",
"video": "Video",
"audio": "Audio",
"file": "Bestand",
"advanced": "Geavanceerd",
"codec": "Codec",
"resolution": "Resolutie",
"bitrate": "Bitrate",
"frameRate": "Frame rate",
"aspectRatio": "Beeldverhouding",
"profile": "Profiel",
"bitDepth": "Bit diepte",
"colorSpace": "Kleurruimte",
"colorRange": "Kleurbereik",
"colorPrimaries": "Kleurprimaires",
"chromaSubsampling": "Chroma subsampling",
"channels": "Kanalen",
"path": "Pad",
"size": "Grootte",
"container": "Container",
"duration": "Duur",
"optimizedForStreaming": "Geoptimaliseerd voor streaming",
"has64bitOffsets": "64-bit Offsets"
},
"mediaMenu": {
"markAsWatched": "Markeer als gekeken",
"markAsUnwatched": "Markeer als ongekeken",
"goToSeries": "Ga naar serie",
"goToSeason": "Ga naar seizoen",
"shufflePlay": "Willekeurig afspelen",
"fileInfo": "Bestand info"
},
"tooltips": {
"shufflePlay": "Willekeurig afspelen",
"markAsWatched": "Markeer als gekeken",
"markAsUnwatched": "Markeer als ongekeken"
},
"videoControls": {
"audioLabel": "Audio",
"subtitlesLabel": "Ondertitels",
"resetToZero": "Reset naar 0ms",
"addTime": "+${amount}${unit}",
"minusTime": "-${amount}${unit}",
"playsLater": "${label} speelt later af",
"playsEarlier": "${label} speelt eerder af",
"noOffset": "Geen offset",
"letterbox": "Letterbox",
"fillScreen": "Vul scherm",
"stretch": "Uitrekken",
"lockRotation": "Vergrendel rotatie",
"unlockRotation": "Ontgrendel rotatie"
},
"userStatus": {
"admin": "Beheerder",
"restricted": "Beperkt",
"protected": "Beschermd"
},
"messages": {
"markedAsWatched": "Gemarkeerd als gekeken",
"markedAsUnwatched": "Gemarkeerd als ongekeken",
"errorLoading": "Fout: ${error}",
"fileInfoNotAvailable": "Bestand informatie niet beschikbaar",
"errorLoadingFileInfo": "Fout bij laden bestand info: ${error}",
"errorLoadingSeries": "Fout bij laden serie",
"errorLoadingSeason": "Fout bij laden seizoen",
"musicNotSupported": "Muziek afspelen wordt nog niet ondersteund",
"logsCleared": "Logs gewist",
"logsCopied": "Logs gekopieerd naar klembord",
"noLogsAvailable": "Geen logs beschikbaar",
"libraryScanning": "Scannen \"${title}\"...",
"libraryScanStarted": "Bibliotheek scan gestart voor \"${title}\"",
"libraryScanFailed": "Kon bibliotheek niet scannen: ${error}",
"metadataRefreshing": "Metadata vernieuwen voor \"${title}\"...",
"metadataRefreshStarted": "Metadata vernieuwen gestart voor \"${title}\"",
"metadataRefreshFailed": "Kon metadata niet vernieuwen: ${error}",
"noPlexToken": "Geen Plex token gevonden. Log opnieuw in.",
"logoutConfirm": "Weet je zeker dat je wilt uitloggen?",
"noSeasonsFound": "Geen seizoenen gevonden",
"noEpisodesFound": "Geen afleveringen gevonden in eerste seizoen",
"noEpisodesFoundGeneral": "Geen afleveringen gevonden",
"noResultsFound": "Geen resultaten gevonden",
"sleepTimerSet": "Slaap timer ingesteld voor ${label}",
"failedToSwitchProfile": "Kon niet wisselen naar ${displayName}"
},
"profile": {
"noUsersAvailable": "Geen gebruikers beschikbaar"
},
"subtitlingStyling": {
"stylingOptions": "Opmaak opties",
"fontSize": "Lettergrootte",
"textColor": "Tekstkleur",
"borderSize": "Rand grootte",
"borderColor": "Randkleur",
"backgroundOpacity": "Achtergrond transparantie",
"backgroundColor": "Achtergrondkleur"
},
"dialog": {
"confirmAction": "Bevestig actie",
"areYouSure": "Weet je zeker dat je deze actie wilt uitvoeren?",
"cancel": "Annuleren",
"playNow": "Nu afspelen"
},
"discover": {
"title": "Ontdekken",
"switchProfile": "Wissel van profiel",
"switchServer": "Wissel van server",
"logout": "Uitloggen",
"noContentAvailable": "Geen inhoud beschikbaar",
"addMediaToLibraries": "Voeg wat media toe aan je bibliotheken",
"continueWatching": "Verder kijken",
"recentlyAdded": "Recent toegevoegd",
"play": "Afspelen",
"resume": "Hervatten",
"playEpisode": "Speel S${season}, E${episode}",
"resumeEpisode": "Hervat S${season}, E${episode}",
"pause": "Pauzeren",
"overview": "Overzicht",
"cast": "Cast",
"episodeCount": "${count} afleveringen",
"watchedProgress": "${watched}/${total} gekeken",
"movie": "Film",
"tvShow": "TV Serie",
"minutesLeft": "${minutes} min over"
},
"errors": {
"searchFailed": "Zoeken mislukt: ${error}",
"connectionTimeout": "Verbinding time-out tijdens laden ${context}",
"connectionFailed": "Kan geen verbinding maken met Plex server",
"failedToLoad": "Kon ${context} niet laden: ${error}",
"noClientAvailable": "Geen client beschikbaar",
"authenticationFailed": "Authenticatie mislukt: ${error}",
"couldNotLaunchUrl": "Kon auth URL niet openen",
"pleaseEnterToken": "Voer een token in",
"invalidToken": "Ongeldig token",
"failedToVerifyToken": "Kon token niet verifiëren: ${error}",
"failedToSwitchProfile": "Kon niet wisselen naar ${displayName}",
"connectionFailedGeneric": "Verbinding mislukt"
},
"libraries": {
"title": "Bibliotheken",
"scanLibraryFiles": "Scan bibliotheek bestanden",
"scanLibrary": "Scan bibliotheek",
"analyze": "Analyseren",
"analyzeLibrary": "Analyseer bibliotheek",
"refreshMetadata": "Vernieuw metadata",
"emptyTrash": "Prullenbak legen",
"emptyingTrash": "Prullenbak legen voor \"${title}\"...",
"trashEmptied": "Prullenbak geleegd voor \"${title}\"",
"failedToEmptyTrash": "Kon prullenbak niet legen: ${error}",
"analyzing": "Analyseren \"${title}\"...",
"analysisStarted": "Analyse gestart voor \"${title}\"",
"failedToAnalyze": "Kon bibliotheek niet analyseren: ${error}",
"noLibrariesFound": "Geen bibliotheken gevonden",
"thisLibraryIsEmpty": "Deze bibliotheek is leeg",
"all": "Alles",
"clearAll": "Alles wissen",
"scanLibraryConfirm": "Weet je zeker dat je \"${title}\" wilt scannen?",
"analyzeLibraryConfirm": "Weet je zeker dat je \"${title}\" wilt analyseren?",
"refreshMetadataConfirm": "Weet je zeker dat je metadata wilt vernieuwen voor \"${title}\"?",
"emptyTrashConfirm": "Weet je zeker dat je de prullenbak wilt legen voor \"${title}\"?",
"manageLibraries": "Beheer bibliotheken",
"sort": "Sorteren",
"sortBy": "Sorteer op",
"filters": "Filters",
"loadingLibraryWithCount": "Bibliotheek laden... (${count} items geladen)",
"confirmActionMessage": "Weet je zeker dat je deze actie wilt uitvoeren?",
"showLibrary": "Toon bibliotheek",
"hideLibrary": "Verberg bibliotheek",
"libraryOptions": "Bibliotheek opties"
},
"about": {
"title": "Over",
"openSourceLicenses": "Open Source licenties",
"versionLabel": "Versie ${version}",
"appDescription": "Een mooie Plex client voor Flutter",
"viewLicensesDescription": "Bekijk licenties van third-party bibliotheken"
},
"serverSelection": {
"connectingToServer": "Verbinden met server...",
"serverDebugCopied": "Server debug gegevens gekopieerd naar klembord",
"copyDebugData": "Kopieer debug gegevens",
"noServersFound": "Geen servers gevonden",
"malformedServerData": "${count} server(s) gevonden met verkeerde data. Geen geldige servers beschikbaar.",
"incompleteServerInfo": "Sommige servers hebben incomplete informatie en zijn overgeslagen. Controleer je Plex.tv account.",
"incompleteConnectionInfo": "Server verbinding informatie is incompleet. Probeer opnieuw.",
"malformedServerInfo": "Server informatie is verkeerd geformatteerd: ${message}",
"networkConnectionFailed": "Netwerkverbinding mislukt. Controleer je internetverbinding en probeer opnieuw.",
"authenticationFailed": "Authenticatie mislukt. Log opnieuw in.",
"plexServiceUnavailable": "Plex service niet beschikbaar. Probeer later opnieuw.",
"failedToLoadServers": "Kon servers niet laden: ${error}"
},
"hubDetail": {
"title": "Titel",
"releaseYear": "Uitgavejaar",
"dateAdded": "Datum toegevoegd",
"rating": "Beoordeling",
"noItemsFound": "Geen items gevonden"
},
"logs": {
"title": "Logs",
"clearLogs": "Wis logs",
"copyLogs": "Kopieer logs",
"exportLogs": "Exporteer logs",
"noLogsToShow": "Geen logs om te tonen",
"error": "Fout:",
"stackTrace": "Stack Trace:"
},
"licenses": {
"relatedPackages": "Gerelateerde pakketten",
"license": "Licentie",
"licenseNumber": "Licentie ${number}",
"licensesCount": "${count} licenties"
},
"navigation": {
"home": "Home",
"search": "Zoeken",
"libraries": "Bibliotheken",
"settings": "Instellingen"
}
}
+4 -2
View File
@@ -132,7 +132,9 @@
},
"search": {
"hint": "Sök filmer, serier, musik...",
"tryDifferentTerm": "Prova en annan sökterm"
"tryDifferentTerm": "Prova en annan sökterm",
"searchYourMedia": "Sök i dina media",
"enterTitleActorOrKeyword": "Ange en titel, skådespelare eller nyckelord"
},
"hotkeys": {
"setShortcutFor": "Sätt genväg för ${actionName}",
@@ -363,4 +365,4 @@
"libraries": "Bibliotek",
"settings": "Inställningar"
}
}
}
+27 -26
View File
@@ -1,17 +1,19 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import '../client/plex_client.dart';
import '../models/plex_metadata.dart';
import '../services/settings_service.dart';
import '../providers/settings_provider.dart';
import '../utils/provider_extensions.dart';
import '../utils/app_logger.dart';
import '../widgets/media_card.dart';
import '../widgets/desktop_app_bar.dart';
import '../mixins/refreshable.dart';
import '../mixins/item_updatable.dart';
import '../i18n/strings.g.dart';
import '../mixins/item_updatable.dart';
import '../mixins/refreshable.dart';
import '../models/plex_metadata.dart';
import '../providers/settings_provider.dart';
import '../services/settings_service.dart';
import '../utils/app_logger.dart';
import '../utils/provider_extensions.dart';
import '../widgets/desktop_app_bar.dart';
import '../widgets/media_card.dart';
class SearchScreen extends StatefulWidget {
const SearchScreen({super.key});
@@ -107,9 +109,9 @@ class _SearchScreenState extends State<SearchScreen>
setState(() {
_isSearching = false;
});
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text(t.errors.searchFailed(error: e))));
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(t.errors.searchFailed(error: e))),
);
}
}
}
@@ -124,7 +126,9 @@ class _SearchScreenState extends State<SearchScreen>
// Public method to fully reload all content (for profile switches)
void fullRefresh() {
appLogger.d('SearchScreen.fullRefresh() called - clearing search and reloading');
appLogger.d(
'SearchScreen.fullRefresh() called - clearing search and reloading',
);
// Clear search results and search text for new profile
_searchController.clear();
setState(() {
@@ -186,14 +190,14 @@ class _SearchScreenState extends State<SearchScreen>
Icon(Icons.search, size: 80, color: Colors.grey.shade400),
const SizedBox(height: 16),
Text(
'Search your media',
t.search.searchYourMedia,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: Colors.grey.shade600,
),
),
const SizedBox(height: 8),
Text(
'Enter a title, actor, or keyword',
t.search.enterTitleActorOrKeyword,
style: TextStyle(color: Colors.grey.shade600),
),
],
@@ -234,17 +238,14 @@ class _SearchScreenState extends State<SearchScreen>
return SliverPadding(
padding: const EdgeInsets.all(16),
sliver: SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
final item = _searchResults[index];
return MediaCard(
key: Key(item.ratingKey),
item: item,
onRefresh: updateItem,
);
},
childCount: _searchResults.length,
),
delegate: SliverChildBuilderDelegate((context, index) {
final item = _searchResults[index];
return MediaCard(
key: Key(item.ratingKey),
item: item,
onRefresh: updateItem,
);
}, childCount: _searchResults.length),
),
);
} else {
+14 -11
View File
@@ -1,15 +1,16 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:hotkey_manager/hotkey_manager.dart';
import 'package:provider/provider.dart';
import 'package:url_launcher/url_launcher.dart';
import '../providers/theme_provider.dart';
import '../i18n/strings.g.dart';
import '../providers/settings_provider.dart';
import '../services/settings_service.dart' as settings;
import '../providers/theme_provider.dart';
import '../services/keyboard_shortcuts_service.dart';
import '../services/settings_service.dart' as settings;
import '../services/update_service.dart';
import '../widgets/desktop_app_bar.dart';
import '../widgets/hotkey_recorder_widget.dart';
import '../i18n/strings.g.dart';
import 'about_screen.dart';
import 'logs_screen.dart';
import 'subtitle_styling_screen.dart';
@@ -868,6 +869,8 @@ class _SettingsScreenState extends State<SettingsScreen> {
return 'Svenska';
case AppLocale.it:
return 'Italiano';
case AppLocale.nl:
return 'Nederlands';
}
}
@@ -887,10 +890,14 @@ class _SettingsScreenState extends State<SettingsScreen> {
isSelected
? Icons.radio_button_checked
: Icons.radio_button_unchecked,
color: isSelected ? Theme.of(context).colorScheme.primary : null,
color: isSelected
? Theme.of(context).colorScheme.primary
: null,
),
tileColor: isSelected
? Theme.of(context).colorScheme.primaryContainer.withValues(alpha: 0.3)
? Theme.of(
context,
).colorScheme.primaryContainer.withValues(alpha: 0.3)
: null,
onTap: () async {
// Save the locale to settings
@@ -925,11 +932,7 @@ class _SettingsScreenState extends State<SettingsScreen> {
void _restartApp() {
// Navigate to the root and remove all previous routes
Navigator.pushNamedAndRemoveUntil(
context,
'/',
(route) => false,
);
Navigator.pushNamedAndRemoveUntil(context, '/', (route) => false);
}
Future<void> _checkForUpdates() async {