diff --git a/overseerr-api.yml b/overseerr-api.yml index 00e1cf03..f8be0895 100644 --- a/overseerr-api.yml +++ b/overseerr-api.yml @@ -909,6 +909,15 @@ components: type: array items: $ref: '#/components/schemas/ProductionCompany' + productionCountries: + type: array + items: + type: object + properties: + iso_3166_1: + type: string + name: + type: string spokenLanguages: type: array items: diff --git a/server/api/themoviedb/interfaces.ts b/server/api/themoviedb/interfaces.ts index bd3c2d8b..7892fe46 100644 --- a/server/api/themoviedb/interfaces.ts +++ b/server/api/themoviedb/interfaces.ts @@ -251,6 +251,10 @@ export interface TmdbTvDetails { name: string; origin_country: string; }[]; + production_countries: { + iso_3166_1: string; + name: string; + }[]; spoken_languages: { english_name: string; iso_639_1: string; diff --git a/server/models/Tv.ts b/server/models/Tv.ts index 9f6b2568..b596b1d2 100644 --- a/server/models/Tv.ts +++ b/server/models/Tv.ts @@ -90,6 +90,10 @@ export interface TvDetails { overview: string; popularity: number; productionCompanies: ProductionCompany[]; + productionCountries: { + iso_3166_1: string; + name: string; + }[]; spokenLanguages: SpokenLanguage[]; seasons: Season[]; status: string; @@ -187,6 +191,7 @@ export const mapTvDetails = ( originCountry: company.origin_country, logoPath: company.logo_path, })), + productionCountries: show.production_countries, contentRatings: show.content_ratings, spokenLanguages: show.spoken_languages.map((language) => ({ englishName: language.english_name, diff --git a/src/components/MovieDetails/index.tsx b/src/components/MovieDetails/index.tsx index ee0ee872..44398169 100644 --- a/src/components/MovieDetails/index.tsx +++ b/src/components/MovieDetails/index.tsx @@ -11,6 +11,8 @@ import { ChevronDoubleDownIcon, ChevronDoubleUpIcon, } from '@heroicons/react/solid'; +import { hasFlag } from 'country-flag-icons'; +import 'country-flag-icons/3x2/flags.css'; import { uniqBy } from 'lodash'; import Link from 'next/link'; import { useRouter } from 'next/router'; @@ -69,6 +71,8 @@ const messages = defineMessages({ showmore: 'Show More', showless: 'Show Less', streamingproviders: 'Currently Streaming On', + productioncountries: + 'Production {countryCount, plural, one {Country} other {Countries}}', }); interface MovieDetailsProps { @@ -596,6 +600,37 @@ const MovieDetails: React.FC = ({ movie }) => { )} + {data.productionCountries.length > 0 && ( +
+ + {intl.formatMessage(messages.productioncountries, { + countryCount: data.productionCountries.length, + })} + + + {data.productionCountries.map((c) => { + return ( + + {hasFlag(c.iso_3166_1) && ( + + )} + + {intl.formatDisplayName(c.iso_3166_1, { + type: 'region', + fallback: 'none', + }) ?? c.name} + + + ); + })} + +
+ )} {data.productionCompanies.length > 0 && (
diff --git a/src/components/TvDetails/index.tsx b/src/components/TvDetails/index.tsx index 7365ba9a..4de23164 100644 --- a/src/components/TvDetails/index.tsx +++ b/src/components/TvDetails/index.tsx @@ -5,6 +5,8 @@ import { FilmIcon, PlayIcon, } from '@heroicons/react/outline'; +import { hasFlag } from 'country-flag-icons'; +import 'country-flag-icons/3x2/flags.css'; import Link from 'next/link'; import { useRouter } from 'next/router'; import React, { useMemo, useState } from 'react'; @@ -63,6 +65,8 @@ const messages = defineMessages({ episodeRuntime: 'Episode Runtime', episodeRuntimeMinutes: '{runtime} minutes', streamingproviders: 'Currently Streaming On', + productioncountries: + 'Production {countryCount, plural, one {Country} other {Countries}}', }); interface TvDetailsProps { @@ -533,6 +537,37 @@ const TvDetails: React.FC = ({ tv }) => {
)} + {data.productionCountries.length > 0 && ( +
+ + {intl.formatMessage(messages.productioncountries, { + countryCount: data.productionCountries.length, + })} + + + {data.productionCountries.map((c) => { + return ( + + {hasFlag(c.iso_3166_1) && ( + + )} + + {intl.formatDisplayName(c.iso_3166_1, { + type: 'region', + fallback: 'none', + }) ?? c.name} + + + ); + })} + +
+ )} {data.networks.length > 0 && (
@@ -552,7 +587,10 @@ const TvDetails: React.FC = ({ tv }) => { )) .reduce((prev, curr) => ( <> - {prev}, {curr} + {intl.formatMessage(globalMessages.delimitedlist, { + a: prev, + b: curr, + })} ))} diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json index 10b9a897..f87026de 100644 --- a/src/i18n/locale/en.json +++ b/src/i18n/locale/en.json @@ -155,6 +155,7 @@ "components.MovieDetails.overviewunavailable": "Overview unavailable.", "components.MovieDetails.play4konplex": "Play in 4K on Plex", "components.MovieDetails.playonplex": "Play on Plex", + "components.MovieDetails.productioncountries": "Production {countryCount, plural, one {Country} other {Countries}}", "components.MovieDetails.recommendations": "Recommendations", "components.MovieDetails.releasedate": "{releaseCount, plural, one {Release Date} other {Release Dates}}", "components.MovieDetails.revenue": "Revenue", @@ -793,6 +794,7 @@ "components.TvDetails.overviewunavailable": "Overview unavailable.", "components.TvDetails.play4konplex": "Play in 4K on Plex", "components.TvDetails.playonplex": "Play on Plex", + "components.TvDetails.productioncountries": "Production {countryCount, plural, one {Country} other {Countries}}", "components.TvDetails.recommendations": "Recommendations", "components.TvDetails.seasons": "{seasonCount, plural, one {# Season} other {# Seasons}}", "components.TvDetails.showtype": "Series Type",