diff --git a/documentation/integrations/audible.md b/documentation/integrations/audible.md index 54c3cf7..8d6d706 100644 --- a/documentation/integrations/audible.md +++ b/documentation/integrations/audible.md @@ -33,6 +33,7 @@ Configurable Audible region for accurate metadata matching across different inte - India (`in`) - `audible.in` (English) - Germany (`de`) - `audible.de` (non-English) - Spain (`es`) - `audible.es` (non-English) +- French (`fr`) - `audible.fr` (non-English) **`isEnglish` Flag:** - Each region has `isEnglish: boolean` in `AudibleRegionConfig` diff --git a/documentation/settings-pages.md b/documentation/settings-pages.md index 45b51f0..393492b 100644 --- a/documentation/settings-pages.md +++ b/documentation/settings-pages.md @@ -271,7 +271,7 @@ src/app/admin/settings/ **PUT /api/admin/settings/audible** - Updates Audible region -- Body: `{ region: string }` (one of: us, ca, uk, au, in, es) +- Body: `{ region: string }` (one of: us, ca, uk, au, in, es, fr) - No validation required **PUT /api/admin/settings/prowlarr/indexers** diff --git a/src/lib/constants/language-config.ts b/src/lib/constants/language-config.ts index f7ab586..fc87b97 100644 --- a/src/lib/constants/language-config.ts +++ b/src/lib/constants/language-config.ts @@ -16,7 +16,7 @@ import type { AudibleRegion } from '../types/audible'; // Types // --------------------------------------------------------------------------- -export type SupportedLanguage = 'en' | 'de' | 'es'; +export type SupportedLanguage = 'en' | 'de' | 'es' | 'fr'; export interface ScrapingConfig { /** Audible locale query-param value (e.g. 'english', 'deutsch') */ @@ -170,6 +170,38 @@ const SPANISH_CONFIG: LanguageConfig = { }, }; +const FRENCH_CONFIG: LanguageConfig = { + code: 'fr', + annasArchiveLang: 'fr', + epubCode: 'fr', + stopWords: ['le', 'la', 'les','un', 'une', 'de', 'des', 'sur', 'dans', '\u00e0', 'et', 'par', 'pour'], + characterReplacements: {}, + scraping: { + audibleLocaleParam: 'français', + authorPrefixes: ['De :', '\u00c9crit par :', 'Auteur :'], + narratorPrefixes: ['Lu par :'], + lengthLabels: ['Dur\u00e9e :'], + languageLabels: ['Langue :'], + releaseDateLabels: ['Date de publication :'], + seriesLabels: ['S\u00e9rie :'], + acceptedLanguageValues: ['français', 'french'], + runtimeHourPatterns: [/(\d+)\s*h\b/i, /(\d+)\s*heures?/i], + runtimeMinutePatterns: [/(\d+)\s*min/i, /(\d+)\s*minutes?/i], + ratingPatterns: [/(\d+[.,]?\d*)\s*de\s*5/i], + releaseDatePatterns: [/Date de publication:\s*(.+)/i], + descriptionExcludePatterns: [ + /\$\d+\.\d+/, + /\d+,\d+\s*\u20ac/, + /Essayer pour/i, + /R\u00e9siliez \u00e0 tout moment/i, + /Acheter pour/i, + /^\s*de\s+[\w\s,]+$/i, + ], + durationDetectionPattern: /\d+\s*(h|heures?)\s*\d*\s*(min|minutes?)?/i, + ratingTextSelector: 'sur 5 étoiles', + }, +}; + // --------------------------------------------------------------------------- // Lookup Maps // --------------------------------------------------------------------------- @@ -178,6 +210,7 @@ export const LANGUAGE_CONFIGS: Record = { en: ENGLISH_CONFIG, de: GERMAN_CONFIG, es: SPANISH_CONFIG, + fr: FRENCH_CONFIG, }; /** @@ -192,6 +225,7 @@ export const REGION_LANGUAGE_MAP: Record = { in: 'en', de: 'de', es: 'es', + fr: 'fr', }; // --------------------------------------------------------------------------- diff --git a/src/lib/types/audible.ts b/src/lib/types/audible.ts index 871ec5a..5f6d4d3 100644 --- a/src/lib/types/audible.ts +++ b/src/lib/types/audible.ts @@ -5,7 +5,7 @@ import type { SupportedLanguage } from '../constants/language-config'; -export type AudibleRegion = 'us' | 'ca' | 'uk' | 'au' | 'in' | 'de' | 'es'; +export type AudibleRegion = 'us' | 'ca' | 'uk' | 'au' | 'in' | 'de' | 'es' | 'fr'; export interface AudibleRegionConfig { code: AudibleRegion; @@ -64,6 +64,13 @@ export const AUDIBLE_REGIONS: Record = { baseUrl: 'https://www.audible.es', audnexusParam: 'es', language: 'es', + }, + fr: { + code: 'fr', + name: 'French', + baseUrl: 'https://www.audible.fr', + audnexusParam: 'fr', + language: 'fr', } };