feat(preferences): section langues a telecharger (defaut fr+en), transcripts filtres cote serveur et watch
CI / build-and-test (push) Successful in 13m50s

This commit is contained in:
2026-09-26 11:49:56 -04:00
parent 1b0a7eb3ce
commit 655061ba2c
46 changed files with 2018 additions and 380 deletions
@@ -50,6 +50,29 @@
</div>
</div>
</div>
<!-- Langues à télécharger (sous-titres/transcripts) -->
<div class="bg-slate-800/50 rounded-xl border border-slate-700 overflow-hidden">
<div class="px-5 py-4 border-b border-slate-700">
<h3 class="text-lg font-semibold text-slate-100">{{ 'preferences.download_languages' | t : 'Langues à télécharger' }}</h3>
<p class="text-sm text-slate-400">{{ 'preferences.download_languages_hint' | t : 'Seules les langues activées sont affichées et téléchargées (sous-titres/transcriptions). Français et anglais par défaut.' }}</p>
</div>
<div class="p-5">
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-3">
<label *ngFor="let opt of downloadLanguageOptions"
class="flex items-center gap-2 rounded-lg border border-slate-700 bg-slate-900 px-3 py-2 cursor-pointer hover:border-slate-500">
<input type="checkbox"
class="h-4 w-4 accent-red-600"
[checked]="isDownloadLanguageEnabled(opt.code)"
(change)="toggleDownloadLanguage(opt.code)"
[name]="'dl-' + opt.code" />
<span class="text-sm text-slate-200">{{ opt.label }}</span>
<span class="text-xs text-slate-500 uppercase">{{ opt.code }}</span>
</label>
</div>
<p *ngIf="downloadLanguages().length === 0" class="mt-3 text-sm text-red-300">{{ 'preferences.download_languages_empty' | t : 'Sélectionnez au moins une langue.' }}</p>
</div>
</div>
</form>
<!-- PeerTube Instances (below general) -->
@@ -35,6 +35,27 @@ export class PreferencesComponent {
themes = ['system', 'light', 'dark', 'black', 'blue'];
qualities = ['auto', '720p', '1080p'];
// Langues de sous-titres/transcripts à télécharger (défaut fr+en).
// Seules les langues activées sont affichées et téléchargées.
readonly DEFAULT_DOWNLOAD_LANGUAGES = ['fr', 'en'];
downloadLanguageOptions: Array<{ code: string; label: string }> = [
{ code: 'fr', label: 'Français' },
{ code: 'en', label: 'English' },
{ code: 'es', label: 'Español' },
{ code: 'de', label: 'Deutsch' },
{ code: 'it', label: 'Italiano' },
{ code: 'pt', label: 'Português' },
{ code: 'nl', label: 'Nederlands' },
{ code: 'pl', label: 'Polski' },
{ code: 'ru', label: 'Русский' },
{ code: 'ar', label: 'العربية' },
{ code: 'zh', label: '中文' },
{ code: 'ja', label: '日本語' },
{ code: 'hi', label: 'हिन्दी' },
{ code: 'ko', label: '한국어' },
];
downloadLanguages = signal<string[]>([...this.DEFAULT_DOWNLOAD_LANGUAGES]);
// PeerTube instances management
newPeerTubeInstance = signal<string>('');
peerTubeInstances = this.instances.peerTubeInstances; // signal<string[]>
@@ -51,6 +72,12 @@ export class PreferencesComponent {
// apply language immediately
if (p.language) this.i18n.setLanguage(p.language);
if (p.defaultProvider) this.defaultProvider.set(p.defaultProvider as Provider);
if (Array.isArray(p.downloadLanguages)) {
const cleaned = p.downloadLanguages
.map(v => String(v || '').trim().toLowerCase().split('-')[0])
.filter(v => this.downloadLanguageOptions.some(o => o.code === v));
this.downloadLanguages.set(Array.from(new Set(cleaned)));
}
if (p.theme) this.theme.set(p.theme);
if (p.videoQuality) this.videoQuality.set(p.videoQuality);
if (p.region) this.region.set(p.region);
@@ -61,14 +88,36 @@ export class PreferencesComponent {
} catch {}
}
isDownloadLanguageEnabled(code: string): boolean {
return this.downloadLanguages().includes(code);
}
toggleDownloadLanguage(code: string): void {
const current = [...this.downloadLanguages()];
const idx = current.indexOf(code);
if (idx >= 0) current.splice(idx, 1);
else current.push(code);
// Garde l'ordre du catalogue pour une persistance stable
const order = new Map(this.downloadLanguageOptions.map((o, i) => [o.code, i]));
current.sort((a, b) => (order.get(a) ?? 99) - (order.get(b) ?? 99));
this.downloadLanguages.set(current);
this.error.set(null);
}
async onSave(ev: Event) {
ev.preventDefault();
const langs = this.downloadLanguages();
if (!langs.length) {
this.error.set('Sélectionnez au moins une langue à télécharger.');
return;
}
this.saving.set(true);
this.notice.set(null);
try {
const patch: Partial<UserPreferences> = {
language: this.language(),
defaultProvider: this.defaultProvider(),
downloadLanguages: [...langs],
theme: this.theme(),
videoQuality: this.videoQuality(),
region: this.region(),