From 2d69a5c33e168b39cfa287ee211f8e9539b96a0a Mon Sep 17 00:00:00 2001 From: V1ck3s Date: Sat, 13 Dec 2025 00:43:05 +0100 Subject: [PATCH] refactor: update comments and documentation to English for consistency --- octo-fiesta/Models/MusicModels.cs | 44 +++++++-------- octo-fiesta/Program.cs | 2 +- octo-fiesta/Services/DeezerDownloadService.cs | 56 +++++++++---------- octo-fiesta/Services/DeezerMetadataService.cs | 28 +++++----- octo-fiesta/Services/IDownloadService.cs | 26 ++++----- octo-fiesta/Services/IMusicMetadataService.cs | 24 ++++---- octo-fiesta/Services/LocalLibraryService.cs | 36 ++++++------ 7 files changed, 108 insertions(+), 108 deletions(-) diff --git a/octo-fiesta/Models/MusicModels.cs b/octo-fiesta/Models/MusicModels.cs index 9055b2d..0a0c48f 100644 --- a/octo-fiesta/Models/MusicModels.cs +++ b/octo-fiesta/Models/MusicModels.cs @@ -1,13 +1,13 @@ namespace octo_fiesta.Models; /// -/// Représente une chanson (locale ou externe) +/// Represents a song (local or external) /// public class Song { /// - /// ID unique. Pour les chansons externes, préfixé avec "ext-" + provider + "-" + id externe - /// Exemple: "ext-deezer-123456" ou "local-789" + /// Unique ID. For external songs, prefixed with "ext-" + provider + "-" + external id + /// Example: "ext-deezer-123456" or "local-789" /// public string Id { get; set; } = string.Empty; @@ -16,7 +16,7 @@ public class Song public string? ArtistId { get; set; } public string Album { get; set; } = string.Empty; public string? AlbumId { get; set; } - public int? Duration { get; set; } // En secondes + public int? Duration { get; set; } // In seconds public int? Track { get; set; } public int? DiscNumber { get; set; } public int? TotalTracks { get; set; } @@ -25,12 +25,12 @@ public class Song public string? CoverArtUrl { get; set; } /// - /// URL de la cover en haute résolution (pour embedding) + /// High-resolution cover art URL (for embedding) /// public string? CoverArtUrlLarge { get; set; } /// - /// BPM (beats per minute) si disponible + /// BPM (beats per minute) if available /// public int? Bpm { get; set; } @@ -40,22 +40,22 @@ public class Song public string? Isrc { get; set; } /// - /// Date de sortie complète (format: YYYY-MM-DD) + /// Full release date (format: YYYY-MM-DD) /// public string? ReleaseDate { get; set; } /// - /// Nom de l'album artiste (peut différer de l'artiste du track) + /// Album artist name (may differ from track artist) /// public string? AlbumArtist { get; set; } /// - /// Compositeur(s) + /// Composer(s) /// public string? Composer { get; set; } /// - /// Label de l'album + /// Album label /// public string? Label { get; set; } @@ -65,33 +65,33 @@ public class Song public string? Copyright { get; set; } /// - /// Artistes contributeurs (featurings, etc.) + /// Contributing artists (features, etc.) /// public List Contributors { get; set; } = new(); /// - /// Indique si la chanson est disponible localement ou doit être téléchargée + /// Indicates whether the song is available locally or needs to be downloaded /// public bool IsLocal { get; set; } /// - /// Provider externe (deezer, spotify, etc.) - null si local + /// External provider (deezer, spotify, etc.) - null if local /// public string? ExternalProvider { get; set; } /// - /// ID sur le provider externe (pour le téléchargement) + /// ID on the external provider (for downloading) /// public string? ExternalId { get; set; } /// - /// Chemin du fichier local (si disponible) + /// Local file path (if available) /// public string? LocalPath { get; set; } } /// -/// Représente un artiste +/// Represents an artist /// public class Artist { @@ -105,7 +105,7 @@ public class Artist } /// -/// Représente un album +/// Represents an album /// public class Album { @@ -124,7 +124,7 @@ public class Album } /// -/// Résultat de recherche combinant résultats locaux et externes +/// Search result combining local and external results /// public class SearchResult { @@ -134,7 +134,7 @@ public class SearchResult } /// -/// État du téléchargement d'une chanson +/// Download status of a song /// public enum DownloadStatus { @@ -145,7 +145,7 @@ public enum DownloadStatus } /// -/// Information sur un téléchargement en cours ou terminé +/// Information about an ongoing or completed download /// public class DownloadInfo { @@ -153,7 +153,7 @@ public class DownloadInfo public string ExternalId { get; set; } = string.Empty; public string ExternalProvider { get; set; } = string.Empty; public DownloadStatus Status { get; set; } - public double Progress { get; set; } // 0.0 à 1.0 + public double Progress { get; set; } // 0.0 to 1.0 public string? LocalPath { get; set; } public string? ErrorMessage { get; set; } public DateTime StartedAt { get; set; } @@ -161,7 +161,7 @@ public class DownloadInfo } /// -/// Statut du scan de bibliothèque Subsonic +/// Subsonic library scan status /// public class ScanStatus { diff --git a/octo-fiesta/Program.cs b/octo-fiesta/Program.cs index ea50164..dbbe5cc 100644 --- a/octo-fiesta/Program.cs +++ b/octo-fiesta/Program.cs @@ -14,7 +14,7 @@ builder.Services.AddSwaggerGen(); builder.Services.Configure( builder.Configuration.GetSection("Subsonic")); -// Services métier +// Business services builder.Services.AddSingleton(); builder.Services.AddScoped(); builder.Services.AddScoped(); diff --git a/octo-fiesta/Services/DeezerDownloadService.cs b/octo-fiesta/Services/DeezerDownloadService.cs index e0d7f16..85247a8 100644 --- a/octo-fiesta/Services/DeezerDownloadService.cs +++ b/octo-fiesta/Services/DeezerDownloadService.cs @@ -11,7 +11,7 @@ using IOFile = System.IO.File; namespace octo_fiesta.Services; /// -/// Configuration pour le téléchargeur Deezer +/// Configuration for the Deezer downloader /// public class DeezerDownloaderSettings { @@ -21,8 +21,8 @@ public class DeezerDownloaderSettings } /// -/// Port C# du DeezerDownloader JavaScript -/// Gère l'authentification Deezer, le téléchargement et le déchiffrement des pistes +/// C# port of the DeezerDownloader JavaScript +/// Handles Deezer authentication, track downloading and decryption /// public class DeezerDownloadService : IDownloadService { @@ -84,7 +84,7 @@ public class DeezerDownloadService : IDownloadService var songId = $"ext-{externalProvider}-{externalId}"; - // Vérifier si déjà téléchargé + // Check if already downloaded var existingPath = await _localLibraryService.GetLocalPathForExternalSongAsync(externalProvider, externalId); if (existingPath != null && IOFile.Exists(existingPath)) { @@ -92,7 +92,7 @@ public class DeezerDownloadService : IDownloadService return existingPath; } - // Vérifier si téléchargement en cours + // Check if download in progress if (_activeDownloads.TryGetValue(songId, out var activeDownload) && activeDownload.Status == DownloadStatus.InProgress) { _logger.LogInformation("Download already in progress for {SongId}", songId); @@ -112,7 +112,7 @@ public class DeezerDownloadService : IDownloadService await _downloadLock.WaitAsync(cancellationToken); try { - // Récupérer les métadonnées + // Get metadata var song = await _metadataService.GetSongAsync(externalProvider, externalId); if (song == null) { @@ -140,7 +140,7 @@ public class DeezerDownloadService : IDownloadService song.LocalPath = localPath; await _localLibraryService.RegisterDownloadedSongAsync(song, localPath); - // Déclencher un rescan de la bibliothèque Subsonic (avec debounce) + // Trigger a Subsonic library rescan (with debounce) _ = _localLibraryService.TriggerLibraryScanAsync(); _logger.LogInformation("Download completed: {Path}", localPath); @@ -362,7 +362,7 @@ public class DeezerDownloadService : IDownloadService _logger.LogInformation("Track token obtained for: {Title} - {Artist}", downloadInfo.Title, downloadInfo.Artist); _logger.LogInformation("Using format: {Format}", downloadInfo.Format); - // Déterminer l'extension basée sur le format + // Determine extension based on format var extension = downloadInfo.Format?.ToUpper() switch { "FLAC" => ".flac", @@ -379,7 +379,7 @@ public class DeezerDownloadService : IDownloadService // Resolve unique path if file already exists outputPath = PathHelper.ResolveUniquePath(outputPath); - // Télécharger le fichier chiffré + // Download the encrypted file var response = await RetryWithBackoffAsync(async () => { var request = new HttpRequestMessage(HttpMethod.Get, downloadInfo.DownloadUrl); @@ -391,23 +391,23 @@ public class DeezerDownloadService : IDownloadService response.EnsureSuccessStatusCode(); - // Télécharger et déchiffrer + // Download and decrypt await using var responseStream = await response.Content.ReadAsStreamAsync(cancellationToken); await using var outputFile = IOFile.Create(outputPath); await DecryptAndWriteStreamAsync(responseStream, outputFile, trackId, cancellationToken); - // Fermer le fichier avant d'écrire les métadonnées + // Close file before writing metadata await outputFile.DisposeAsync(); - // Écrire les métadonnées et la cover art + // Write metadata and cover art await WriteMetadataAsync(outputPath, song, cancellationToken); return outputPath; } /// - /// Écrit les métadonnées ID3/Vorbis et la cover art dans le fichier audio + /// Writes ID3/Vorbis metadata and cover art to the audio file /// private async Task WriteMetadataAsync(string filePath, Song song, CancellationToken cancellationToken) { @@ -417,12 +417,12 @@ public class DeezerDownloadService : IDownloadService using var tagFile = TagLib.File.Create(filePath); - // Métadonnées de base + // Basic metadata tagFile.Tag.Title = song.Title; tagFile.Tag.Performers = new[] { song.Artist }; tagFile.Tag.Album = song.Album; - // Album artist (peut différer de l'artiste du track pour les compilations) + // Album artist (may differ from track artist for compilations) if (!string.IsNullOrEmpty(song.AlbumArtist)) { tagFile.Tag.AlbumArtists = new[] { song.AlbumArtist }; @@ -432,25 +432,25 @@ public class DeezerDownloadService : IDownloadService tagFile.Tag.AlbumArtists = new[] { song.Artist }; } - // Numéro de piste + // Track number if (song.Track.HasValue) { tagFile.Tag.Track = (uint)song.Track.Value; } - // Nombre total de pistes + // Total track count if (song.TotalTracks.HasValue) { tagFile.Tag.TrackCount = (uint)song.TotalTracks.Value; } - // Numéro de disque + // Disc number if (song.DiscNumber.HasValue) { tagFile.Tag.Disc = (uint)song.DiscNumber.Value; } - // Année + // Year if (song.Year.HasValue) { tagFile.Tag.Year = (uint)song.Year.Value; @@ -468,15 +468,15 @@ public class DeezerDownloadService : IDownloadService tagFile.Tag.BeatsPerMinute = (uint)song.Bpm.Value; } - // ISRC (stocké dans le commentaire si pas de champ dédié, ou via MusicBrainz ID) - // TagLib ne supporte pas directement l'ISRC, mais on peut l'ajouter au commentaire + // ISRC (stored in comment if no dedicated field, or via MusicBrainz ID) + // TagLib doesn't directly support ISRC, but we can add it to comments var comments = new List(); if (!string.IsNullOrEmpty(song.Isrc)) { comments.Add($"ISRC: {song.Isrc}"); } - // Contributeurs dans le commentaire + // Contributors in comments if (song.Contributors.Count > 0) { tagFile.Tag.Composers = song.Contributors.ToArray(); @@ -488,13 +488,13 @@ public class DeezerDownloadService : IDownloadService tagFile.Tag.Copyright = song.Copyright; } - // Commentaire avec infos supplémentaires + // Comment with additional info if (comments.Count > 0) { tagFile.Tag.Comment = string.Join(" | ", comments); } - // Télécharger et intégrer la cover art + // Download and embed cover art var coverUrl = song.CoverArtUrlLarge ?? song.CoverArtUrl; if (!string.IsNullOrEmpty(coverUrl)) { @@ -521,19 +521,19 @@ public class DeezerDownloadService : IDownloadService } } - // Sauvegarder les modifications + // Save changes tagFile.Save(); _logger.LogInformation("Metadata written successfully to: {Path}", filePath); } catch (Exception ex) { _logger.LogError(ex, "Failed to write metadata to: {Path}", filePath); - // Ne pas propager l'erreur - le fichier est téléchargé, juste sans métadonnées + // Don't propagate the error - the file is downloaded, just without metadata } } /// - /// Télécharge la cover art depuis une URL + /// Downloads cover art from a URL /// private async Task DownloadCoverArtAsync(string url, CancellationToken cancellationToken) { @@ -587,7 +587,7 @@ public class DeezerDownloadService : IDownloadService var chunk = buffer.AsSpan(0, bytesRead).ToArray(); - // Chaque 3ème chunk (index % 3 == 0) est chiffré + // Every 3rd chunk (index % 3 == 0) is encrypted if (chunkIndex % 3 == 0 && bytesRead == 2048) { chunk = DecryptBlowfishCbc(chunk, bfKey, iv); diff --git a/octo-fiesta/Services/DeezerMetadataService.cs b/octo-fiesta/Services/DeezerMetadataService.cs index 57060e1..9cca74e 100644 --- a/octo-fiesta/Services/DeezerMetadataService.cs +++ b/octo-fiesta/Services/DeezerMetadataService.cs @@ -4,7 +4,7 @@ using System.Text.Json; namespace octo_fiesta.Services; /// -/// Implémentation du service de métadonnées utilisant l'API Deezer (gratuite, pas besoin de clé) +/// Metadata service implementation using the Deezer API (free, no key required) /// public class DeezerMetadataService : IMusicMetadataService { @@ -105,7 +105,7 @@ public class DeezerMetadataService : IMusicMetadataService public async Task SearchAllAsync(string query, int songLimit = 20, int albumLimit = 20, int artistLimit = 20) { - // Exécuter les recherches en parallèle + // Execute searches in parallel var songsTask = SearchSongsAsync(query, songLimit); var albumsTask = SearchAlbumsAsync(query, albumLimit); var artistsTask = SearchArtistsAsync(query, artistLimit); @@ -134,11 +134,11 @@ public class DeezerMetadataService : IMusicMetadataService if (track.TryGetProperty("error", out _)) return null; - // Pour un track individuel, on récupère les métadonnées complètes + // For an individual track, get full metadata var song = ParseDeezerTrackFull(track); - // Récupérer les infos supplémentaires depuis l'album (genre, nombre total de tracks, label, copyright) - if (track.TryGetProperty("album", out var albumRef) && + // Get additional info from album (genre, total track count, label, copyright) + if (track.TryGetProperty("album", out var albumRef) && albumRef.TryGetProperty("id", out var albumIdEl)) { var albumId = albumIdEl.GetInt64().ToString(); @@ -160,7 +160,7 @@ public class DeezerMetadataService : IMusicMetadataService song.Genre = genreName.GetString(); } - // Nombre total de tracks + // Total track count if (albumData.TryGetProperty("nb_tracks", out var nbTracks)) { song.TotalTracks = nbTracks.GetInt32(); @@ -172,7 +172,7 @@ public class DeezerMetadataService : IMusicMetadataService song.Label = label.GetString(); } - // Cover art XL si pas déjà définie + // Cover art XL if not already set if (string.IsNullOrEmpty(song.CoverArtUrlLarge)) { if (albumData.TryGetProperty("cover_xl", out var coverXl)) @@ -188,7 +188,7 @@ public class DeezerMetadataService : IMusicMetadataService } catch { - // Si on ne peut pas récupérer l'album, on continue avec les infos du track + // If we can't get the album, continue with track info only } } @@ -211,8 +211,8 @@ public class DeezerMetadataService : IMusicMetadataService var album = ParseDeezerAlbum(albumElement); - // Récupérer les chansons de l'album - if (albumElement.TryGetProperty("tracks", out var tracks) && + // Get album songs + if (albumElement.TryGetProperty("tracks", out var tracks) && tracks.TryGetProperty("data", out var tracksData)) { int trackIndex = 1; @@ -308,8 +308,8 @@ public class DeezerMetadataService : IMusicMetadataService } /// - /// Parse un track Deezer avec toutes les métadonnées disponibles - /// Utilisé pour GetSongAsync qui retourne des données complètes + /// Parses a Deezer track with all available metadata + /// Used for GetSongAsync which returns complete data /// private Song ParseDeezerTrackFull(JsonElement track) { @@ -371,7 +371,7 @@ public class DeezerMetadataService : IMusicMetadataService } } - // Album artist (premier artiste de l'album, ou artiste principal du track) + // Album artist (first artist from album, or main track artist) string? albumArtist = null; if (track.TryGetProperty("album", out var albumForArtist) && albumForArtist.TryGetProperty("artist", out var albumArtistEl)) @@ -381,7 +381,7 @@ public class DeezerMetadataService : IMusicMetadataService : null; } - // Cover art URLs (différentes tailles) + // Cover art URLs (different sizes) string? coverMedium = null; string? coverLarge = null; if (track.TryGetProperty("album", out var albumForCover)) diff --git a/octo-fiesta/Services/IDownloadService.cs b/octo-fiesta/Services/IDownloadService.cs index f6d2afd..e1095ff 100644 --- a/octo-fiesta/Services/IDownloadService.cs +++ b/octo-fiesta/Services/IDownloadService.cs @@ -3,35 +3,35 @@ using octo_fiesta.Models; namespace octo_fiesta.Services; /// -/// Interface pour le service de téléchargement de musique (Deezspot ou autre) +/// Interface for the music download service (Deezspot or other) /// public interface IDownloadService { /// - /// Télécharge une chanson depuis un provider externe + /// Downloads a song from an external provider /// - /// Le provider (deezer, spotify) - /// L'ID sur le provider externe - /// Token d'annulation - /// Le chemin du fichier téléchargé + /// The provider (deezer, spotify) + /// The ID on the external provider + /// Cancellation token + /// The path to the downloaded file Task DownloadSongAsync(string externalProvider, string externalId, CancellationToken cancellationToken = default); /// - /// Télécharge une chanson et stream le résultat au fur et à mesure + /// Downloads a song and streams the result progressively /// - /// Le provider (deezer, spotify) - /// L'ID sur le provider externe - /// Token d'annulation - /// Un stream du fichier audio + /// The provider (deezer, spotify) + /// The ID on the external provider + /// Cancellation token + /// A stream of the audio file Task DownloadAndStreamAsync(string externalProvider, string externalId, CancellationToken cancellationToken = default); /// - /// Vérifie si une chanson est en cours de téléchargement + /// Checks if a song is currently being downloaded /// DownloadInfo? GetDownloadStatus(string songId); /// - /// Vérifie si le service est correctement configuré et fonctionnel + /// Checks if the service is properly configured and functional /// Task IsAvailableAsync(); } diff --git a/octo-fiesta/Services/IMusicMetadataService.cs b/octo-fiesta/Services/IMusicMetadataService.cs index eca9f7c..8a9be13 100644 --- a/octo-fiesta/Services/IMusicMetadataService.cs +++ b/octo-fiesta/Services/IMusicMetadataService.cs @@ -3,51 +3,51 @@ using octo_fiesta.Models; namespace octo_fiesta.Services; /// -/// Interface pour le service de recherche de métadonnées musicales externes +/// Interface for external music metadata search service /// (Deezer API, Spotify API, MusicBrainz, etc.) /// public interface IMusicMetadataService { /// - /// Recherche des chansons sur les providers externes + /// Searches for songs on external providers /// - /// Terme de recherche - /// Nombre maximum de résultats - /// Liste des chansons trouvées + /// Search term + /// Maximum number of results + /// List of found songs Task> SearchSongsAsync(string query, int limit = 20); /// - /// Recherche des albums sur les providers externes + /// Searches for albums on external providers /// Task> SearchAlbumsAsync(string query, int limit = 20); /// - /// Recherche des artistes sur les providers externes + /// Searches for artists on external providers /// Task> SearchArtistsAsync(string query, int limit = 20); /// - /// Recherche combinée (chansons, albums, artistes) + /// Combined search (songs, albums, artists) /// Task SearchAllAsync(string query, int songLimit = 20, int albumLimit = 20, int artistLimit = 20); /// - /// Récupère les détails d'une chanson externe + /// Gets details of an external song /// Task GetSongAsync(string externalProvider, string externalId); /// - /// Récupère les détails d'un album externe avec ses chansons + /// Gets details of an external album with its songs /// Task GetAlbumAsync(string externalProvider, string externalId); /// - /// Récupère les détails d'un artiste externe + /// Gets details of an external artist /// Task GetArtistAsync(string externalProvider, string externalId); /// - /// Récupère les albums d'un artiste + /// Gets an artist's albums /// Task> GetArtistAlbumsAsync(string externalProvider, string externalId); } diff --git a/octo-fiesta/Services/LocalLibraryService.cs b/octo-fiesta/Services/LocalLibraryService.cs index 9cc3495..fb93134 100644 --- a/octo-fiesta/Services/LocalLibraryService.cs +++ b/octo-fiesta/Services/LocalLibraryService.cs @@ -6,51 +6,51 @@ using octo_fiesta.Models; namespace octo_fiesta.Services; /// -/// Interface pour la gestion de la bibliothèque locale de musiques +/// Interface for local music library management /// public interface ILocalLibraryService { /// - /// Vérifie si une chanson externe existe déjà localement + /// Checks if an external song already exists locally /// Task GetLocalPathForExternalSongAsync(string externalProvider, string externalId); /// - /// Enregistre une chanson téléchargée dans la bibliothèque locale + /// Registers a downloaded song in the local library /// Task RegisterDownloadedSongAsync(Song song, string localPath); /// - /// Récupère le mapping entre ID externe et ID local + /// Gets the mapping between external ID and local ID /// Task GetLocalIdForExternalSongAsync(string externalProvider, string externalId); /// - /// Parse un ID de chanson pour déterminer s'il est externe ou local + /// Parses a song ID to determine if it is external or local /// (bool isExternal, string? provider, string? externalId) ParseSongId(string songId); /// - /// Parse un ID externe pour extraire le provider, le type et l'ID - /// Format: ext-{provider}-{type}-{id} (ex: ext-deezer-artist-259, ext-deezer-album-96126, ext-deezer-song-12345) + /// Parses an external ID to extract the provider, type and ID + /// Format: ext-{provider}-{type}-{id} (e.g., ext-deezer-artist-259, ext-deezer-album-96126, ext-deezer-song-12345) /// Also supports legacy format: ext-{provider}-{id} (assumes song type) /// (bool isExternal, string? provider, string? type, string? externalId) ParseExternalId(string id); /// - /// Déclenche un scan de la bibliothèque Subsonic + /// Triggers a Subsonic library scan /// Task TriggerLibraryScanAsync(); /// - /// Récupère le statut actuel du scan + /// Gets the current scan status /// Task GetScanStatusAsync(); } /// -/// Implémentation du service de bibliothèque locale -/// Utilise un fichier JSON simple pour stocker les mappings (peut être remplacé par une BDD) +/// Local library service implementation +/// Uses a simple JSON file to store mappings (can be replaced with a database) /// public class LocalLibraryService : ILocalLibraryService { @@ -62,7 +62,7 @@ public class LocalLibraryService : ILocalLibraryService private Dictionary? _mappings; private readonly SemaphoreSlim _lock = new(1, 1); - // Debounce pour éviter de déclencher trop de scans + // Debounce to avoid triggering too many scans private DateTime _lastScanTrigger = DateTime.MinValue; private readonly TimeSpan _scanDebounceInterval = TimeSpan.FromSeconds(30); @@ -128,8 +128,8 @@ public class LocalLibraryService : ILocalLibraryService public async Task GetLocalIdForExternalSongAsync(string externalProvider, string externalId) { - // Pour l'instant, on retourne null car on n'a pas encore d'intégration - // avec le serveur Subsonic pour récupérer l'ID local après scan + // For now, return null as we don't yet have integration + // with the Subsonic server to retrieve local ID after scan await Task.CompletedTask; return null; } @@ -206,7 +206,7 @@ public class LocalLibraryService : ILocalLibraryService public async Task TriggerLibraryScanAsync() { - // Debounce: éviter de déclencher trop de scans successifs + // Debounce: avoid triggering too many successive scans var now = DateTime.UtcNow; if (now - _lastScanTrigger < _scanDebounceInterval) { @@ -219,8 +219,8 @@ public class LocalLibraryService : ILocalLibraryService try { - // Appel à l'API Subsonic pour déclencher un scan - // Note: Les credentials doivent être passés en paramètres (u, p ou t+s) + // Call Subsonic API to trigger a scan + // Note: Credentials must be passed as parameters (u, p or t+s) var url = $"{_subsonicSettings.Url}/rest/startScan?f=json"; _logger.LogInformation("Triggering Subsonic library scan..."); @@ -280,7 +280,7 @@ public class LocalLibraryService : ILocalLibraryService } /// -/// Représente le mapping entre une chanson externe et son fichier local +/// Represents the mapping between an external song and its local file /// public class LocalSongMapping {