mirror of
https://github.com/sct/overseerr.git
synced 2025-09-17 17:24:35 +02:00
feat: add language-filtered Discover pages (#1111)
This commit is contained in:
@@ -3332,6 +3332,53 @@ paths:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/MovieResult'
|
||||
/discover/movies/language/{language}:
|
||||
get:
|
||||
summary: Discover movies by original language
|
||||
description: Returns a list of movies based on the provided ISO 639-1 language code in a JSON object.
|
||||
tags:
|
||||
- search
|
||||
parameters:
|
||||
- in: path
|
||||
name: language
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
example: en
|
||||
- in: query
|
||||
name: page
|
||||
schema:
|
||||
type: number
|
||||
example: 1
|
||||
default: 1
|
||||
- in: query
|
||||
name: language
|
||||
schema:
|
||||
type: string
|
||||
example: en
|
||||
responses:
|
||||
'200':
|
||||
description: Results
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
page:
|
||||
type: number
|
||||
example: 1
|
||||
totalPages:
|
||||
type: number
|
||||
example: 20
|
||||
totalResults:
|
||||
type: number
|
||||
example: 200
|
||||
language:
|
||||
$ref: '#/components/schemas/SpokenLanguage'
|
||||
results:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/MovieResult'
|
||||
/discover/movies/studio/{studioId}:
|
||||
get:
|
||||
summary: Discover movies by studio
|
||||
@@ -3467,6 +3514,53 @@ paths:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/TvResult'
|
||||
/discover/tv/language/{language}:
|
||||
get:
|
||||
summary: Discover TV shows by original language
|
||||
description: Returns a list of TV shows based on the provided ISO 639-1 language code in a JSON object.
|
||||
tags:
|
||||
- search
|
||||
parameters:
|
||||
- in: path
|
||||
name: language
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
example: en
|
||||
- in: query
|
||||
name: page
|
||||
schema:
|
||||
type: number
|
||||
example: 1
|
||||
default: 1
|
||||
- in: query
|
||||
name: language
|
||||
schema:
|
||||
type: string
|
||||
example: en
|
||||
responses:
|
||||
'200':
|
||||
description: Results
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
page:
|
||||
type: number
|
||||
example: 1
|
||||
totalPages:
|
||||
type: number
|
||||
example: 20
|
||||
totalResults:
|
||||
type: number
|
||||
example: 200
|
||||
language:
|
||||
$ref: '#/components/schemas/SpokenLanguage'
|
||||
results:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/TvResult'
|
||||
/discover/tv/genre/{genreId}:
|
||||
get:
|
||||
summary: Discover TV shows by genre
|
||||
|
@@ -34,6 +34,7 @@ interface DiscoverMovieOptions {
|
||||
language?: string;
|
||||
primaryReleaseDateGte?: string;
|
||||
primaryReleaseDateLte?: string;
|
||||
originalLanguage?: string;
|
||||
genre?: number;
|
||||
studio?: number;
|
||||
sortBy?:
|
||||
@@ -59,6 +60,7 @@ interface DiscoverTvOptions {
|
||||
firstAirDateGte?: string;
|
||||
firstAirDateLte?: string;
|
||||
includeEmptyReleaseDate?: boolean;
|
||||
originalLanguage?: string;
|
||||
genre?: number;
|
||||
network?: number;
|
||||
sortBy?:
|
||||
@@ -368,6 +370,7 @@ class TheMovieDb extends ExternalAPI {
|
||||
language = 'en',
|
||||
primaryReleaseDateGte,
|
||||
primaryReleaseDateLte,
|
||||
originalLanguage,
|
||||
genre,
|
||||
studio,
|
||||
}: DiscoverMovieOptions = {}): Promise<TmdbSearchMovieResponse> => {
|
||||
@@ -379,7 +382,7 @@ class TheMovieDb extends ExternalAPI {
|
||||
include_adult: includeAdult,
|
||||
language,
|
||||
region: this.region,
|
||||
with_original_language: this.originalLanguage,
|
||||
with_original_language: originalLanguage ?? this.originalLanguage,
|
||||
'primary_release_date.gte': primaryReleaseDateGte,
|
||||
'primary_release_date.lte': primaryReleaseDateLte,
|
||||
with_genres: genre,
|
||||
@@ -400,6 +403,7 @@ class TheMovieDb extends ExternalAPI {
|
||||
firstAirDateGte,
|
||||
firstAirDateLte,
|
||||
includeEmptyReleaseDate = false,
|
||||
originalLanguage,
|
||||
genre,
|
||||
network,
|
||||
}: DiscoverTvOptions = {}): Promise<TmdbSearchTvResponse> => {
|
||||
@@ -412,7 +416,7 @@ class TheMovieDb extends ExternalAPI {
|
||||
region: this.region,
|
||||
'first_air_date.gte': firstAirDateGte,
|
||||
'first_air_date.lte': firstAirDateLte,
|
||||
with_original_language: this.originalLanguage,
|
||||
with_original_language: originalLanguage ?? this.originalLanguage,
|
||||
include_null_first_air_dates: includeEmptyReleaseDate,
|
||||
with_genres: genre,
|
||||
with_networks: network,
|
||||
|
@@ -63,9 +63,52 @@ discoverRoutes.get('/movies', async (req, res) => {
|
||||
});
|
||||
});
|
||||
|
||||
discoverRoutes.get<{ language: string }>(
|
||||
'/movies/language/:language',
|
||||
async (req, res, next) => {
|
||||
const tmdb = createTmdbWithRegionLanaguage(req.user);
|
||||
|
||||
const languages = await tmdb.getLanguages();
|
||||
|
||||
const language = languages.find(
|
||||
(lang) => lang.iso_639_1 === req.params.language
|
||||
);
|
||||
|
||||
if (!language) {
|
||||
return next({ status: 404, message: 'Unable to retrieve language' });
|
||||
}
|
||||
|
||||
const data = await tmdb.getDiscoverMovies({
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
originalLanguage: req.params.language,
|
||||
});
|
||||
|
||||
const media = await Media.getRelatedMedia(
|
||||
data.results.map((result) => result.id)
|
||||
);
|
||||
|
||||
return res.status(200).json({
|
||||
page: data.page,
|
||||
totalPages: data.total_pages,
|
||||
totalResults: data.total_results,
|
||||
language,
|
||||
results: data.results.map((result) =>
|
||||
mapMovieResult(
|
||||
result,
|
||||
media.find(
|
||||
(req) =>
|
||||
req.tmdbId === result.id && req.mediaType === MediaType.MOVIE
|
||||
)
|
||||
)
|
||||
),
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
discoverRoutes.get<{ genreId: string }>(
|
||||
'/movies/genre/:genreId',
|
||||
async (req, res) => {
|
||||
async (req, res, next) => {
|
||||
const tmdb = createTmdbWithRegionLanaguage(req.user);
|
||||
|
||||
const genres = await tmdb.getMovieGenres({
|
||||
@@ -76,6 +119,10 @@ discoverRoutes.get<{ genreId: string }>(
|
||||
(genre) => genre.id === Number(req.params.genreId)
|
||||
);
|
||||
|
||||
if (!genre) {
|
||||
return next({ status: 404, message: 'Unable to retrieve genre' });
|
||||
}
|
||||
|
||||
const data = await tmdb.getDiscoverMovies({
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
@@ -106,36 +153,40 @@ discoverRoutes.get<{ genreId: string }>(
|
||||
|
||||
discoverRoutes.get<{ studioId: string }>(
|
||||
'/movies/studio/:studioId',
|
||||
async (req, res) => {
|
||||
async (req, res, next) => {
|
||||
const tmdb = new TheMovieDb();
|
||||
|
||||
const studio = await tmdb.getStudio(Number(req.params.studioId));
|
||||
try {
|
||||
const studio = await tmdb.getStudio(Number(req.params.studioId));
|
||||
|
||||
const data = await tmdb.getDiscoverMovies({
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
studio: Number(req.params.studioId),
|
||||
});
|
||||
const data = await tmdb.getDiscoverMovies({
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
studio: Number(req.params.studioId),
|
||||
});
|
||||
|
||||
const media = await Media.getRelatedMedia(
|
||||
data.results.map((result) => result.id)
|
||||
);
|
||||
const media = await Media.getRelatedMedia(
|
||||
data.results.map((result) => result.id)
|
||||
);
|
||||
|
||||
return res.status(200).json({
|
||||
page: data.page,
|
||||
totalPages: data.total_pages,
|
||||
totalResults: data.total_results,
|
||||
studio: mapProductionCompany(studio),
|
||||
results: data.results.map((result) =>
|
||||
mapMovieResult(
|
||||
result,
|
||||
media.find(
|
||||
(req) =>
|
||||
req.tmdbId === result.id && req.mediaType === MediaType.MOVIE
|
||||
return res.status(200).json({
|
||||
page: data.page,
|
||||
totalPages: data.total_pages,
|
||||
totalResults: data.total_results,
|
||||
studio: mapProductionCompany(studio),
|
||||
results: data.results.map((result) =>
|
||||
mapMovieResult(
|
||||
result,
|
||||
media.find(
|
||||
(med) =>
|
||||
med.tmdbId === result.id && med.mediaType === MediaType.MOVIE
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
});
|
||||
),
|
||||
});
|
||||
} catch (e) {
|
||||
return next({ status: 404, message: 'Unable to retrieve studio' });
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -202,9 +253,51 @@ discoverRoutes.get('/tv', async (req, res) => {
|
||||
});
|
||||
});
|
||||
|
||||
discoverRoutes.get<{ language: string }>(
|
||||
'/tv/language/:language',
|
||||
async (req, res, next) => {
|
||||
const tmdb = createTmdbWithRegionLanaguage(req.user);
|
||||
|
||||
const languages = await tmdb.getLanguages();
|
||||
|
||||
const language = languages.find(
|
||||
(lang) => lang.iso_639_1 === req.params.language
|
||||
);
|
||||
|
||||
if (!language) {
|
||||
return next({ status: 404, message: 'Unable to retrieve language' });
|
||||
}
|
||||
|
||||
const data = await tmdb.getDiscoverTv({
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
originalLanguage: req.params.language,
|
||||
});
|
||||
|
||||
const media = await Media.getRelatedMedia(
|
||||
data.results.map((result) => result.id)
|
||||
);
|
||||
|
||||
return res.status(200).json({
|
||||
page: data.page,
|
||||
totalPages: data.total_pages,
|
||||
totalResults: data.total_results,
|
||||
language,
|
||||
results: data.results.map((result) =>
|
||||
mapTvResult(
|
||||
result,
|
||||
media.find(
|
||||
(med) => med.tmdbId === result.id && med.mediaType === MediaType.TV
|
||||
)
|
||||
)
|
||||
),
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
discoverRoutes.get<{ genreId: string }>(
|
||||
'/tv/genre/:genreId',
|
||||
async (req, res) => {
|
||||
async (req, res, next) => {
|
||||
const tmdb = createTmdbWithRegionLanaguage(req.user);
|
||||
|
||||
const genres = await tmdb.getTvGenres({
|
||||
@@ -215,6 +308,10 @@ discoverRoutes.get<{ genreId: string }>(
|
||||
(genre) => genre.id === Number(req.params.genreId)
|
||||
);
|
||||
|
||||
if (!genre) {
|
||||
return next({ status: 404, message: 'Unable to retrieve genre' });
|
||||
}
|
||||
|
||||
const data = await tmdb.getDiscoverTv({
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
@@ -244,35 +341,40 @@ discoverRoutes.get<{ genreId: string }>(
|
||||
|
||||
discoverRoutes.get<{ networkId: string }>(
|
||||
'/tv/network/:networkId',
|
||||
async (req, res) => {
|
||||
async (req, res, next) => {
|
||||
const tmdb = new TheMovieDb();
|
||||
|
||||
const network = await tmdb.getNetwork(Number(req.params.networkId));
|
||||
try {
|
||||
const network = await tmdb.getNetwork(Number(req.params.networkId));
|
||||
|
||||
const data = await tmdb.getDiscoverTv({
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
network: Number(req.params.networkId),
|
||||
});
|
||||
const data = await tmdb.getDiscoverTv({
|
||||
page: Number(req.query.page),
|
||||
language: req.query.language as string,
|
||||
network: Number(req.params.networkId),
|
||||
});
|
||||
|
||||
const media = await Media.getRelatedMedia(
|
||||
data.results.map((result) => result.id)
|
||||
);
|
||||
const media = await Media.getRelatedMedia(
|
||||
data.results.map((result) => result.id)
|
||||
);
|
||||
|
||||
return res.status(200).json({
|
||||
page: data.page,
|
||||
totalPages: data.total_pages,
|
||||
totalResults: data.total_results,
|
||||
network: mapNetwork(network),
|
||||
results: data.results.map((result) =>
|
||||
mapTvResult(
|
||||
result,
|
||||
media.find(
|
||||
(med) => med.tmdbId === result.id && med.mediaType === MediaType.TV
|
||||
return res.status(200).json({
|
||||
page: data.page,
|
||||
totalPages: data.total_pages,
|
||||
totalResults: data.total_results,
|
||||
network: mapNetwork(network),
|
||||
results: data.results.map((result) =>
|
||||
mapTvResult(
|
||||
result,
|
||||
media.find(
|
||||
(med) =>
|
||||
med.tmdbId === result.id && med.mediaType === MediaType.TV
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
});
|
||||
),
|
||||
});
|
||||
} catch (e) {
|
||||
return next({ status: 404, message: 'Unable to retrieve network' });
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
@@ -331,15 +433,18 @@ discoverRoutes.get('/trending', async (req, res) => {
|
||||
? mapMovieResult(
|
||||
result,
|
||||
media.find(
|
||||
(req) =>
|
||||
req.tmdbId === result.id && req.mediaType === MediaType.MOVIE
|
||||
(med) =>
|
||||
med.tmdbId === result.id && med.mediaType === MediaType.MOVIE
|
||||
)
|
||||
)
|
||||
: isPerson(result)
|
||||
? mapPersonResult(result)
|
||||
: mapTvResult(
|
||||
result,
|
||||
media.find((req) => req.tmdbId === result.id && MediaType.TV)
|
||||
media.find(
|
||||
(med) =>
|
||||
med.tmdbId === result.id && med.mediaType === MediaType.TV
|
||||
)
|
||||
)
|
||||
),
|
||||
});
|
||||
@@ -368,8 +473,8 @@ discoverRoutes.get<{ keywordId: string }>(
|
||||
mapMovieResult(
|
||||
result,
|
||||
media.find(
|
||||
(req) =>
|
||||
req.tmdbId === result.id && req.mediaType === MediaType.MOVIE
|
||||
(med) =>
|
||||
med.tmdbId === result.id && med.mediaType === MediaType.MOVIE
|
||||
)
|
||||
)
|
||||
),
|
||||
|
71
src/components/Discover/DiscoverMovieLanguage/index.tsx
Normal file
71
src/components/Discover/DiscoverMovieLanguage/index.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
import React from 'react';
|
||||
import type { MovieResult } from '../../../../server/models/Search';
|
||||
import ListView from '../../Common/ListView';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
import Header from '../../Common/Header';
|
||||
import PageTitle from '../../Common/PageTitle';
|
||||
import { useRouter } from 'next/router';
|
||||
import globalMessages from '../../../i18n/globalMessages';
|
||||
import useDiscover from '../../../hooks/useDiscover';
|
||||
import Error from '../../../pages/_error';
|
||||
|
||||
const messages = defineMessages({
|
||||
languageMovies: '{language} Movies',
|
||||
});
|
||||
|
||||
const DiscoverMovieLanguage: React.FC = () => {
|
||||
const router = useRouter();
|
||||
const intl = useIntl();
|
||||
|
||||
const {
|
||||
isLoadingInitialData,
|
||||
isEmpty,
|
||||
isLoadingMore,
|
||||
isReachingEnd,
|
||||
titles,
|
||||
fetchMore,
|
||||
error,
|
||||
} = useDiscover<
|
||||
MovieResult,
|
||||
{
|
||||
originalLanguage: {
|
||||
iso_639_1: string;
|
||||
english_name: string;
|
||||
name: string;
|
||||
};
|
||||
}
|
||||
>(`/api/v1/discover/movies/language/${router.query.language}`);
|
||||
|
||||
if (error) {
|
||||
return <Error statusCode={500} />;
|
||||
}
|
||||
|
||||
const title = isLoadingInitialData
|
||||
? intl.formatMessage(globalMessages.loading)
|
||||
: intl.formatMessage(messages.languageMovies, {
|
||||
language: intl.formatDisplayName(router.query.language as string, {
|
||||
type: 'language',
|
||||
fallback: 'none',
|
||||
}),
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageTitle title={title} />
|
||||
<div className="mt-1 mb-5">
|
||||
<Header>{title}</Header>
|
||||
</div>
|
||||
<ListView
|
||||
items={titles}
|
||||
isEmpty={isEmpty}
|
||||
isLoading={
|
||||
isLoadingInitialData || (isLoadingMore && (titles?.length ?? 0) > 0)
|
||||
}
|
||||
isReachingEnd={isReachingEnd}
|
||||
onScrollBottom={fetchMore}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DiscoverMovieLanguage;
|
71
src/components/Discover/DiscoverTvLanguage/index.tsx
Normal file
71
src/components/Discover/DiscoverTvLanguage/index.tsx
Normal file
@@ -0,0 +1,71 @@
|
||||
import React from 'react';
|
||||
import type { TvResult } from '../../../../server/models/Search';
|
||||
import ListView from '../../Common/ListView';
|
||||
import { defineMessages, useIntl } from 'react-intl';
|
||||
import Header from '../../Common/Header';
|
||||
import PageTitle from '../../Common/PageTitle';
|
||||
import { useRouter } from 'next/router';
|
||||
import globalMessages from '../../../i18n/globalMessages';
|
||||
import useDiscover from '../../../hooks/useDiscover';
|
||||
import Error from '../../../pages/_error';
|
||||
|
||||
const messages = defineMessages({
|
||||
languageSeries: '{language} Series',
|
||||
});
|
||||
|
||||
const DiscoverTvLanguage: React.FC = () => {
|
||||
const router = useRouter();
|
||||
const intl = useIntl();
|
||||
|
||||
const {
|
||||
isLoadingInitialData,
|
||||
isEmpty,
|
||||
isLoadingMore,
|
||||
isReachingEnd,
|
||||
titles,
|
||||
fetchMore,
|
||||
error,
|
||||
} = useDiscover<
|
||||
TvResult,
|
||||
{
|
||||
originalLanguage: {
|
||||
iso_639_1: string;
|
||||
english_name: string;
|
||||
name: string;
|
||||
};
|
||||
}
|
||||
>(`/api/v1/discover/tv/language/${router.query.language}`);
|
||||
|
||||
if (error) {
|
||||
return <Error statusCode={500} />;
|
||||
}
|
||||
|
||||
const title = isLoadingInitialData
|
||||
? intl.formatMessage(globalMessages.loading)
|
||||
: intl.formatMessage(messages.languageSeries, {
|
||||
language: intl.formatDisplayName(router.query.language as string, {
|
||||
type: 'language',
|
||||
fallback: 'none',
|
||||
}),
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageTitle title={title} />
|
||||
<div className="mt-1 mb-5">
|
||||
<Header>{title}</Header>
|
||||
</div>
|
||||
<ListView
|
||||
items={titles}
|
||||
isEmpty={isEmpty}
|
||||
isLoading={
|
||||
isLoadingInitialData || (isLoadingMore && (titles?.length ?? 0) > 0)
|
||||
}
|
||||
isReachingEnd={isReachingEnd}
|
||||
onScrollBottom={fetchMore}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default DiscoverTvLanguage;
|
@@ -651,19 +651,23 @@ const MovieDetails: React.FC<MovieDetailsProps> = ({ movie }) => {
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{data.spokenLanguages.some(
|
||||
(lng) => lng.iso_639_1 === data.originalLanguage
|
||||
) && (
|
||||
{data.originalLanguage && (
|
||||
<div className="flex px-4 py-2 border-b border-gray-800 last:border-b-0">
|
||||
<span className="text-sm">
|
||||
{intl.formatMessage(messages.originallanguage)}
|
||||
</span>
|
||||
<span className="flex-1 text-sm text-right text-gray-400">
|
||||
{
|
||||
data.spokenLanguages.find(
|
||||
(lng) => lng.iso_639_1 === data.originalLanguage
|
||||
)?.name
|
||||
}
|
||||
<Link href={`/discover/tv/language/${data.originalLanguage}`}>
|
||||
<a className="hover:underline">
|
||||
{intl.formatDisplayName(data.originalLanguage, {
|
||||
type: 'language',
|
||||
fallback: 'none',
|
||||
}) ??
|
||||
data.spokenLanguages.find(
|
||||
(lng) => lng.iso_639_1 === data.originalLanguage
|
||||
)?.name}
|
||||
</a>
|
||||
</Link>
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
@@ -675,19 +675,23 @@ const TvDetails: React.FC<TvDetailsProps> = ({ tv }) => {
|
||||
{data.status}
|
||||
</span>
|
||||
</div>
|
||||
{data.spokenLanguages.some(
|
||||
(lng) => lng.iso_639_1 === data.originalLanguage
|
||||
) && (
|
||||
{data.originalLanguage && (
|
||||
<div className="flex px-4 py-2 border-b border-gray-800 last:border-b-0">
|
||||
<span className="text-sm">
|
||||
{intl.formatMessage(messages.originallanguage)}
|
||||
</span>
|
||||
<span className="flex-1 text-sm text-right text-gray-400">
|
||||
{
|
||||
data.spokenLanguages.find(
|
||||
(lng) => lng.iso_639_1 === data.originalLanguage
|
||||
)?.name
|
||||
}
|
||||
<Link href={`/discover/tv/language/${data.originalLanguage}`}>
|
||||
<a className="hover:underline">
|
||||
{intl.formatDisplayName(data.originalLanguage, {
|
||||
type: 'language',
|
||||
fallback: 'none',
|
||||
}) ??
|
||||
data.spokenLanguages.find(
|
||||
(lng) => lng.iso_639_1 === data.originalLanguage
|
||||
)?.name}
|
||||
</a>
|
||||
</Link>
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
@@ -15,9 +15,11 @@
|
||||
"components.CollectionDetails.requestswillbecreated4k": "The following titles will have 4K requests created for them:",
|
||||
"components.Common.ListView.noresults": "No results.",
|
||||
"components.Discover.DiscoverMovieGenre.genreMovies": "{genre} Movies",
|
||||
"components.Discover.DiscoverMovieLanguage.languageMovies": "{language} Movies",
|
||||
"components.Discover.DiscoverNetwork.networkSeries": "{network} Series",
|
||||
"components.Discover.DiscoverStudio.studioMovies": "{studio} Movies",
|
||||
"components.Discover.DiscoverTvGenre.genreSeries": "{genre} Series",
|
||||
"components.Discover.DiscoverTvLanguage.languageSeries": "{language} Series",
|
||||
"components.Discover.NetworkSlider.networks": "Networks",
|
||||
"components.Discover.StudioSlider.studios": "Studios",
|
||||
"components.Discover.discover": "Discover",
|
||||
|
9
src/pages/discover/movies/language/[language]/index.tsx
Normal file
9
src/pages/discover/movies/language/[language]/index.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
import { NextPage } from 'next';
|
||||
import DiscoverMovieLanguage from '../../../../../components/Discover/DiscoverMovieLanguage';
|
||||
|
||||
const DiscoverMovieLanguagePage: NextPage = () => {
|
||||
return <DiscoverMovieLanguage />;
|
||||
};
|
||||
|
||||
export default DiscoverMovieLanguagePage;
|
9
src/pages/discover/tv/language/[language]/index.tsx
Normal file
9
src/pages/discover/tv/language/[language]/index.tsx
Normal file
@@ -0,0 +1,9 @@
|
||||
import React from 'react';
|
||||
import { NextPage } from 'next';
|
||||
import DiscoverTvLanguage from '../../../../../components/Discover/DiscoverTvLanguage';
|
||||
|
||||
const DiscoverTvLanguagePage: NextPage = () => {
|
||||
return <DiscoverTvLanguage />;
|
||||
};
|
||||
|
||||
export default DiscoverTvLanguagePage;
|
Reference in New Issue
Block a user