diff --git a/apps/web/src/assets/i18n/ar.json b/apps/web/src/assets/i18n/ar.json index 833bd2075..6010740a3 100644 --- a/apps/web/src/assets/i18n/ar.json +++ b/apps/web/src/assets/i18n/ar.json @@ -783,6 +783,8 @@ "ACTORS": "الممثلون", "DIRECTOR": "المخرج", "SIMILAR": "مشابه", + "CREW_JOB_DIRECTOR": "المخرج", + "CREW_JOB_CREATOR": "المبتكر", "ACTOR_FILMOGRAPHY": "الأعمال الفنية", "ACTOR_FILTER_ALL": "الكل", "ACTOR_SCOPE_THIS_PORTAL": "هذه البوابة", diff --git a/apps/web/src/assets/i18n/ary.json b/apps/web/src/assets/i18n/ary.json index 27188b4e8..ee374f10d 100644 --- a/apps/web/src/assets/i18n/ary.json +++ b/apps/web/src/assets/i18n/ary.json @@ -783,6 +783,8 @@ "ACTORS": "الممثلون", "DIRECTOR": "المخرج", "SIMILAR": "بحال هادو", + "CREW_JOB_DIRECTOR": "المخرج", + "CREW_JOB_CREATOR": "المبتكر", "ACTOR_FILMOGRAPHY": "الأفلام ديالو", "ACTOR_FILTER_ALL": "كلشي", "ACTOR_SCOPE_THIS_PORTAL": "هاد البوابة", diff --git a/apps/web/src/assets/i18n/by.json b/apps/web/src/assets/i18n/by.json index ac6cd8081..38b110ac9 100644 --- a/apps/web/src/assets/i18n/by.json +++ b/apps/web/src/assets/i18n/by.json @@ -783,6 +783,8 @@ "ACTORS": "Акцёры", "DIRECTOR": "Рэжысёр", "SIMILAR": "Падобнае", + "CREW_JOB_DIRECTOR": "Рэжысёр", + "CREW_JOB_CREATOR": "Стваральнік", "ACTOR_FILMOGRAPHY": "Фільмаграфія", "ACTOR_FILTER_ALL": "Усе", "ACTOR_SCOPE_THIS_PORTAL": "Гэты партал", diff --git a/apps/web/src/assets/i18n/de.json b/apps/web/src/assets/i18n/de.json index b9a3c2d9f..d9cfaa05f 100644 --- a/apps/web/src/assets/i18n/de.json +++ b/apps/web/src/assets/i18n/de.json @@ -783,6 +783,8 @@ "ACTORS": "Schauspieler", "DIRECTOR": "Regisseur", "SIMILAR": "Ähnliche Titel", + "CREW_JOB_DIRECTOR": "Regisseur", + "CREW_JOB_CREATOR": "Schöpfer", "ACTOR_FILMOGRAPHY": "Filmografie", "ACTOR_FILTER_ALL": "Alle", "ACTOR_SCOPE_THIS_PORTAL": "Dieses Portal", diff --git a/apps/web/src/assets/i18n/el.json b/apps/web/src/assets/i18n/el.json index 335cc47bb..25d8a343f 100644 --- a/apps/web/src/assets/i18n/el.json +++ b/apps/web/src/assets/i18n/el.json @@ -783,6 +783,8 @@ "ACTORS": "Ηθοποιοί", "DIRECTOR": "Σκηνοθέτης", "SIMILAR": "Παρόμοια", + "CREW_JOB_DIRECTOR": "Σκηνοθέτης", + "CREW_JOB_CREATOR": "Δημιουργός", "ACTOR_FILMOGRAPHY": "Φιλμογραφία", "ACTOR_FILTER_ALL": "Όλα", "ACTOR_SCOPE_THIS_PORTAL": "Αυτή η πύλη", diff --git a/apps/web/src/assets/i18n/en.json b/apps/web/src/assets/i18n/en.json index 92d396baa..0912214c2 100644 --- a/apps/web/src/assets/i18n/en.json +++ b/apps/web/src/assets/i18n/en.json @@ -783,6 +783,8 @@ "ACTORS": "Actors", "DIRECTOR": "Director", "SIMILAR": "Similar", + "CREW_JOB_DIRECTOR": "Director", + "CREW_JOB_CREATOR": "Creator", "ACTOR_FILMOGRAPHY": "Filmography", "ACTOR_FILTER_ALL": "All", "ACTOR_SCOPE_THIS_PORTAL": "This portal", diff --git a/apps/web/src/assets/i18n/es.json b/apps/web/src/assets/i18n/es.json index c7cef836c..f8bd90d41 100644 --- a/apps/web/src/assets/i18n/es.json +++ b/apps/web/src/assets/i18n/es.json @@ -783,6 +783,8 @@ "ACTORS": "Actores", "DIRECTOR": "Director", "SIMILAR": "Similares", + "CREW_JOB_DIRECTOR": "Director", + "CREW_JOB_CREATOR": "Creador", "ACTOR_FILMOGRAPHY": "Filmografía", "ACTOR_FILTER_ALL": "Todas", "ACTOR_SCOPE_THIS_PORTAL": "Este portal", diff --git a/apps/web/src/assets/i18n/fr.json b/apps/web/src/assets/i18n/fr.json index 79e523fff..ba869a727 100644 --- a/apps/web/src/assets/i18n/fr.json +++ b/apps/web/src/assets/i18n/fr.json @@ -783,6 +783,8 @@ "ACTORS": "Acteurs", "DIRECTOR": "Réalisateur", "SIMILAR": "Similaires", + "CREW_JOB_DIRECTOR": "Réalisateur", + "CREW_JOB_CREATOR": "Créateur", "ACTOR_FILMOGRAPHY": "Filmographie", "ACTOR_FILTER_ALL": "Tout", "ACTOR_SCOPE_THIS_PORTAL": "Ce portail", diff --git a/apps/web/src/assets/i18n/it.json b/apps/web/src/assets/i18n/it.json index 0421f61d8..bd9aefbf1 100644 --- a/apps/web/src/assets/i18n/it.json +++ b/apps/web/src/assets/i18n/it.json @@ -783,6 +783,8 @@ "ACTORS": "Attori", "DIRECTOR": "Regista", "SIMILAR": "Simili", + "CREW_JOB_DIRECTOR": "Regista", + "CREW_JOB_CREATOR": "Ideatore", "ACTOR_FILMOGRAPHY": "Filmografia", "ACTOR_FILTER_ALL": "Tutti", "ACTOR_SCOPE_THIS_PORTAL": "Questo portale", diff --git a/apps/web/src/assets/i18n/ja.json b/apps/web/src/assets/i18n/ja.json index 73ea0138e..7361326f3 100644 --- a/apps/web/src/assets/i18n/ja.json +++ b/apps/web/src/assets/i18n/ja.json @@ -783,6 +783,8 @@ "ACTORS": "出演者", "DIRECTOR": "監督", "SIMILAR": "類似作品", + "CREW_JOB_DIRECTOR": "監督", + "CREW_JOB_CREATOR": "クリエイター", "ACTOR_FILMOGRAPHY": "出演作品", "ACTOR_FILTER_ALL": "すべて", "ACTOR_SCOPE_THIS_PORTAL": "このポータル", diff --git a/apps/web/src/assets/i18n/ko.json b/apps/web/src/assets/i18n/ko.json index e43ddc6b3..d77cca393 100644 --- a/apps/web/src/assets/i18n/ko.json +++ b/apps/web/src/assets/i18n/ko.json @@ -783,6 +783,8 @@ "ACTORS": "배우", "DIRECTOR": "감독", "SIMILAR": "비슷한 콘텐츠", + "CREW_JOB_DIRECTOR": "감독", + "CREW_JOB_CREATOR": "크리에이터", "ACTOR_FILMOGRAPHY": "출연 작품", "ACTOR_FILTER_ALL": "전체", "ACTOR_SCOPE_THIS_PORTAL": "현재 포털", diff --git a/apps/web/src/assets/i18n/nl.json b/apps/web/src/assets/i18n/nl.json index 6d05aab79..90db26c23 100644 --- a/apps/web/src/assets/i18n/nl.json +++ b/apps/web/src/assets/i18n/nl.json @@ -783,6 +783,8 @@ "ACTORS": "Acteurs", "DIRECTOR": "Regisseur", "SIMILAR": "Vergelijkbaar", + "CREW_JOB_DIRECTOR": "Regisseur", + "CREW_JOB_CREATOR": "Bedenker", "ACTOR_FILMOGRAPHY": "Filmografie", "ACTOR_FILTER_ALL": "Alles", "ACTOR_SCOPE_THIS_PORTAL": "Dit portaal", diff --git a/apps/web/src/assets/i18n/pl.json b/apps/web/src/assets/i18n/pl.json index 14758b632..14851a2cb 100644 --- a/apps/web/src/assets/i18n/pl.json +++ b/apps/web/src/assets/i18n/pl.json @@ -783,6 +783,8 @@ "ACTORS": "Aktorzy", "DIRECTOR": "Reżyser", "SIMILAR": "Podobne", + "CREW_JOB_DIRECTOR": "Reżyser", + "CREW_JOB_CREATOR": "Twórca", "ACTOR_FILMOGRAPHY": "Filmografia", "ACTOR_FILTER_ALL": "Wszystkie", "ACTOR_SCOPE_THIS_PORTAL": "Ten portal", diff --git a/apps/web/src/assets/i18n/pt.json b/apps/web/src/assets/i18n/pt.json index 89f58e2ec..541edfdb4 100644 --- a/apps/web/src/assets/i18n/pt.json +++ b/apps/web/src/assets/i18n/pt.json @@ -783,6 +783,8 @@ "ACTORS": "Atores", "DIRECTOR": "Diretor", "SIMILAR": "Semelhantes", + "CREW_JOB_DIRECTOR": "Diretor", + "CREW_JOB_CREATOR": "Criador", "ACTOR_FILMOGRAPHY": "Filmografia", "ACTOR_FILTER_ALL": "Todos", "ACTOR_SCOPE_THIS_PORTAL": "Este portal", diff --git a/apps/web/src/assets/i18n/ru.json b/apps/web/src/assets/i18n/ru.json index f0c007b9d..1cdc23312 100644 --- a/apps/web/src/assets/i18n/ru.json +++ b/apps/web/src/assets/i18n/ru.json @@ -783,6 +783,8 @@ "ACTORS": "Актеры", "DIRECTOR": "Режиссёр", "SIMILAR": "Похожее", + "CREW_JOB_DIRECTOR": "Режиссёр", + "CREW_JOB_CREATOR": "Создатель", "ACTOR_FILMOGRAPHY": "Фильмография", "ACTOR_FILTER_ALL": "Все", "ACTOR_SCOPE_THIS_PORTAL": "Этот портал", diff --git a/apps/web/src/assets/i18n/tr.json b/apps/web/src/assets/i18n/tr.json index d89dbad45..8f2f81762 100644 --- a/apps/web/src/assets/i18n/tr.json +++ b/apps/web/src/assets/i18n/tr.json @@ -783,6 +783,8 @@ "ACTORS": "Oyuncular", "DIRECTOR": "Yönetmen", "SIMILAR": "Benzerler", + "CREW_JOB_DIRECTOR": "Yönetmen", + "CREW_JOB_CREATOR": "Yaratıcı", "ACTOR_FILMOGRAPHY": "Filmografi", "ACTOR_FILTER_ALL": "Tümü", "ACTOR_SCOPE_THIS_PORTAL": "Bu portal", diff --git a/apps/web/src/assets/i18n/zh.json b/apps/web/src/assets/i18n/zh.json index 17ccb0b36..26afe5757 100644 --- a/apps/web/src/assets/i18n/zh.json +++ b/apps/web/src/assets/i18n/zh.json @@ -783,6 +783,8 @@ "ACTORS": "演员", "DIRECTOR": "导演", "SIMILAR": "类似影片", + "CREW_JOB_DIRECTOR": "导演", + "CREW_JOB_CREATOR": "主创", "ACTOR_FILMOGRAPHY": "参演作品", "ACTOR_FILTER_ALL": "全部", "ACTOR_SCOPE_THIS_PORTAL": "当前门户", diff --git a/apps/web/src/assets/i18n/zhtw.json b/apps/web/src/assets/i18n/zhtw.json index 87d93aa43..4490ed506 100644 --- a/apps/web/src/assets/i18n/zhtw.json +++ b/apps/web/src/assets/i18n/zhtw.json @@ -783,6 +783,8 @@ "ACTORS": "演員", "DIRECTOR": "導演", "SIMILAR": "類似作品", + "CREW_JOB_DIRECTOR": "導演", + "CREW_JOB_CREATOR": "主創", "ACTOR_FILMOGRAPHY": "參演作品", "ACTOR_FILTER_ALL": "全部", "ACTOR_SCOPE_THIS_PORTAL": "目前入口", diff --git a/libs/portal/stalker/feature/src/lib/stalker-series-view/stalker-series-view.component.html b/libs/portal/stalker/feature/src/lib/stalker-series-view/stalker-series-view.component.html index 95ff1df99..af79c3b2f 100644 --- a/libs/portal/stalker/feature/src/lib/stalker-series-view/stalker-series-view.component.html +++ b/libs/portal/stalker/feature/src/lib/stalker-series-view/stalker-series-view.component.html @@ -37,7 +37,7 @@
@for ( member of serial.info.tmdb_cast; - track member.name + track member.tmdbPersonId ? 'p' + member.tmdbPersonId : 'i' + $index ) { {{ 'XTREAM.DIRECTOR' | translate }} @if (serial.info.tmdb_directors?.length) {
- @for (member of serial.info.tmdb_directors; track member.name) { + @for (member of serial.info.tmdb_directors; track member.tmdbPersonId ? 'p' + member.tmdbPersonId : 'i' + $index) { {{ 'XTREAM.CAST' | translate }} @if (info.tmdb_cast?.length) {
- @for (member of info.tmdb_cast; track member.name) { + @for (member of info.tmdb_cast; track member.tmdbPersonId ? 'p' + member.tmdbPersonId : 'i' + $index) { {{ 'XTREAM.DIRECTOR' | translate }} @if (info.tmdb_directors?.length) {
- @for (member of info.tmdb_directors; track member.name) { + @for (member of info.tmdb_directors; track member.tmdbPersonId ? 'p' + member.tmdbPersonId : 'i' + $index) { {{ 'XTREAM.ACTORS' | translate }} @if (info.tmdb_cast?.length) {
- @for (member of info.tmdb_cast; track member.name) { + @for (member of info.tmdb_cast; track member.tmdbPersonId ? 'p' + member.tmdbPersonId : 'i' + $index) { {{ 'XTREAM.DIRECTOR' | translate }} @if (info.tmdb_directors?.length) {
- @for (member of info.tmdb_directors; track member.name) { + @for (member of info.tmdb_directors; track member.tmdbPersonId ? 'p' + member.tmdbPersonId : 'i' + $index) { ([ + 'Director', + 'Creator', +] satisfies ActorCrewJob[]); export function mapPersonProfile(person: TmdbPersonDetails): ActorProfile { return { @@ -48,7 +59,7 @@ export function mapPersonProfile(person: TmdbPersonDetails): ActorProfile { * first (undated entries last), capped at {@link MAX_FILMOGRAPHY_CREDITS}. * Acting credits win the dedup so "Actor — Character" survives when a * person both starred in and directed the same title; directing-only - * titles show the job ("Director") in the character slot. + * titles carry the crew role in `crewJob` for translated rendering. */ export function mapPersonFilmography( person: TmdbPersonDetails @@ -56,12 +67,14 @@ export function mapPersonFilmography( const seen = new Set(); const credits: ActorFilmographyCredit[] = []; - const castCredits = person.combined_credits?.cast ?? []; - const crewCredits = (person.combined_credits?.crew ?? []).filter( - (credit) => credit.job && FILMOGRAPHY_CREW_JOBS.has(credit.job) + const castCredits = (person.combined_credits?.cast ?? []).map( + (credit) => ({ credit, crewJob: null as ActorCrewJob | null }) ); + const crewCredits = (person.combined_credits?.crew ?? []) + .filter((credit) => credit.job && FILMOGRAPHY_CREW_JOBS.has(credit.job)) + .map((credit) => ({ credit, crewJob: credit.job as ActorCrewJob })); - for (const credit of [...castCredits, ...crewCredits]) { + for (const { credit, crewJob } of [...castCredits, ...crewCredits]) { const mediaType = credit.media_type === 'movie' || credit.media_type === 'tv' ? credit.media_type @@ -79,7 +92,8 @@ export function mapPersonFilmography( title, year: extractYear(credit.release_date ?? credit.first_air_date), posterUrl: tmdbPosterUrl(credit.poster_path), - character: credit.character?.trim() || credit.job?.trim() || null, + character: credit.character?.trim() || null, + crewJob, }); } diff --git a/libs/ui/playback/src/lib/vod-details/vod-details.component.html b/libs/ui/playback/src/lib/vod-details/vod-details.component.html index 588f5a350..7e578926c 100644 --- a/libs/ui/playback/src/lib/vod-details/vod-details.component.html +++ b/libs/ui/playback/src/lib/vod-details/vod-details.component.html @@ -37,7 +37,7 @@ {{ 'XTREAM.ACTORS' | translate }} @if (meta.tmdbCast?.length) {
- @for (member of meta.tmdbCast; track member.name) { + @for (member of meta.tmdbCast; track member.tmdbPersonId ? 'p' + member.tmdbPersonId : 'i' + $index) { {{ 'XTREAM.DIRECTOR' | translate }} @if (meta.tmdbDirectors?.length) {
- @for (member of meta.tmdbDirectors; track member.name) { + @for (member of meta.tmdbDirectors; track member.tmdbPersonId ? 'p' + member.tmdbPersonId : 'i' + $index) { this.showAvailabilityFilter() && this.filterMode() === 'available' ? this.items().filter((item) => item.available)