diff --git a/src/components/Discover/DiscoverMovies.tsx b/src/components/Discover/DiscoverMovies.tsx index fe5b365e9..5a814976d 100644 --- a/src/components/Discover/DiscoverMovies.tsx +++ b/src/components/Discover/DiscoverMovies.tsx @@ -1,7 +1,13 @@ -import React from 'react'; +import React, { useContext } from 'react'; import { useSWRInfinite } from 'swr'; -import { MovieResult } from '../../../server/models/Search'; +import type { MovieResult } from '../../../server/models/Search'; import ListView from '../Common/ListView'; +import { LanguageContext } from '../../context/LanguageContext'; +import { defineMessages, FormattedMessage } from 'react-intl'; + +const messages = defineMessages({ + discovermovies: 'Discover Movies', +}); interface SearchResult { page: number; @@ -11,13 +17,14 @@ interface SearchResult { } const DiscoverMovies: React.FC = () => { + const { locale } = useContext(LanguageContext); const { data, error, size, setSize } = useSWRInfinite( (pageIndex: number, previousPageData: SearchResult | null) => { if (previousPageData && pageIndex + 1 > previousPageData.totalPages) { return null; } - return `/api/v1/discover/movies?page=${pageIndex + 1}`; + return `/api/v1/discover/movies?page=${pageIndex + 1}&language=${locale}`; }, { initialSize: 3, @@ -47,7 +54,7 @@ const DiscoverMovies: React.FC = () => {

- Discover Movies +

diff --git a/src/components/Discover/DiscoverTv.tsx b/src/components/Discover/DiscoverTv.tsx index ee76e5ecc..8c0bc86ba 100644 --- a/src/components/Discover/DiscoverTv.tsx +++ b/src/components/Discover/DiscoverTv.tsx @@ -1,7 +1,13 @@ -import React from 'react'; +import React, { useContext } from 'react'; import { useSWRInfinite } from 'swr'; import { TvResult } from '../../../server/models/Search'; import ListView from '../Common/ListView'; +import { defineMessages, FormattedMessage } from 'react-intl'; +import { LanguageContext } from '../../context/LanguageContext'; + +const messages = defineMessages({ + discovertv: 'Discover Series', +}); interface SearchResult { page: number; @@ -11,13 +17,14 @@ interface SearchResult { } const DiscoverTv: React.FC = () => { + const { locale } = useContext(LanguageContext); const { data, error, size, setSize } = useSWRInfinite( (pageIndex: number, previousPageData: SearchResult | null) => { if (previousPageData && pageIndex + 1 > previousPageData.totalPages) { return null; } - return `/api/v1/discover/tv?page=${pageIndex + 1}`; + return `/api/v1/discover/tv?page=${pageIndex + 1}&language=${locale}`; }, { initialSize: 3, @@ -44,7 +51,7 @@ const DiscoverTv: React.FC = () => {

- Discover Series +

diff --git a/src/components/Layout/SearchInput/index.tsx b/src/components/Layout/SearchInput/index.tsx index be3cf0b5f..9f5ab7889 100644 --- a/src/components/Layout/SearchInput/index.tsx +++ b/src/components/Layout/SearchInput/index.tsx @@ -1,7 +1,13 @@ import React from 'react'; import useSearchInput from '../../../hooks/useSearchInput'; +import { defineMessages, useIntl } from 'react-intl'; + +const messages = defineMessages({ + searchPlaceholder: 'Search Movies & TV', +}); const SearchInput: React.FC = () => { + const intl = useIntl(); const { searchValue, setSearchValue, setIsOpen } = useSearchInput(); return (
@@ -22,7 +28,7 @@ const SearchInput: React.FC = () => { setSearchValue(e.target.value)} diff --git a/src/components/Layout/Sidebar/index.tsx b/src/components/Layout/Sidebar/index.tsx index c9f291f6e..19daaaedd 100644 --- a/src/components/Layout/Sidebar/index.tsx +++ b/src/components/Layout/Sidebar/index.tsx @@ -2,6 +2,13 @@ import React, { ReactNode } from 'react'; import Transition from '../../Transition'; import Link from 'next/link'; import { useRouter } from 'next/router'; +import { defineMessages, FormattedMessage } from 'react-intl'; + +const messages = defineMessages({ + dashboard: 'Dashboard', + requests: 'Requests', + settings: 'Settings', +}); interface SidebarProps { open?: boolean; @@ -11,7 +18,7 @@ interface SidebarProps { interface SidebarLinkProps { href: string; svgIcon: ReactNode; - name: string; + messagesKey: keyof typeof messages; activeRegExp: RegExp; as?: string; } @@ -19,7 +26,7 @@ interface SidebarLinkProps { const SidebarLinks: SidebarLinkProps[] = [ { href: '/', - name: 'Dashboard', + messagesKey: 'dashboard', svgIcon: ( = ({ open, setClosed }) => { {SidebarLinks.map((sidebarLink) => { return ( setClosed()} + onKeyDown={(e) => { + if (e.key === 'Enter') { + setClosed(); + } + }} + role="button" + tabIndex={0} className={`group flex items-center px-2 py-2 text-base leading-6 font-medium rounded-md text-white focus:outline-none focus:bg-gray-700 transition ease-in-out duration-150 ${ router.pathname.match( @@ -164,7 +179,9 @@ const Sidebar: React.FC = ({ open, setClosed }) => { `} > {sidebarLink.svgIcon} - {sidebarLink.name} + ); @@ -192,7 +209,7 @@ const Sidebar: React.FC = ({ open, setClosed }) => { {SidebarLinks.map((sidebarLink) => { return ( @@ -208,7 +225,9 @@ const Sidebar: React.FC = ({ open, setClosed }) => { `} > {sidebarLink.svgIcon} - {sidebarLink.name} + ); diff --git a/src/components/MovieDetails/index.tsx b/src/components/MovieDetails/index.tsx index 1031d7372..3f9053de5 100644 --- a/src/components/MovieDetails/index.tsx +++ b/src/components/MovieDetails/index.tsx @@ -30,6 +30,8 @@ const messages = defineMessages({ overview: 'Overview', runtime: '{minutes} minutes', cast: 'Cast', + recommendations: 'Recommendations', + similar: 'Similar Titles', }); interface MovieDetailsProps { @@ -280,14 +282,16 @@ const MovieDetails: React.FC = ({ movie }) => {
-
- - - - - {data.voteAverage}/10 - -
+ {data.voteCount > 0 && ( +
+ + + + + {data.voteAverage}/10 + +
+ )}
@@ -309,30 +313,34 @@ const MovieDetails: React.FC = ({ movie }) => { {data.status}
-
- - - - - - -
-
- - - - - - -
+ {data.revenue > 0 && ( +
+ + + + + + +
+ )} + {data.budget > 0 && ( +
+ + + + + + +
+ )}
@@ -389,7 +397,9 @@ const MovieDetails: React.FC = ({ movie }) => { as={`/movie/${data.id}/recommendations`} > - Recommendations + + + = ({ movie }) => { as={`/movie/${data.id}/similar`} > - Similar Titles + + + = ({ movie }) => {
( diff --git a/src/components/RequestModal/MovieRequestModal.tsx b/src/components/RequestModal/MovieRequestModal.tsx index c4c9ba8f0..ab2f061d3 100644 --- a/src/components/RequestModal/MovieRequestModal.tsx +++ b/src/components/RequestModal/MovieRequestModal.tsx @@ -2,6 +2,14 @@ import React from 'react'; import Modal from '../Common/Modal'; import { useUser } from '../../hooks/useUser'; import { Permission } from '../../../server/lib/permissions'; +import { defineMessages, useIntl } from 'react-intl'; + +const messages = defineMessages({ + requestadmin: + 'Your request will be immediately approved. Do you wish to continue?', + cancelrequest: + 'This will remove your request. Are you sure you want to continue?', +}); interface RequestModalProps { type: 'request' | 'cancel'; @@ -18,14 +26,15 @@ const MovieRequestModal: React.FC = ({ onOk, title, }) => { + const intl = useIntl(); const { hasPermission } = useUser(); let text = hasPermission(Permission.MANAGE_REQUESTS) - ? 'Your request will be immediately approved. Do you wish to continue?' + ? intl.formatMessage(messages.requestadmin) : undefined; if (type === 'cancel') { - text = 'This will remove your request. Are you sure you want to continue?'; + text = intl.formatMessage(messages.cancelrequest); } return ( diff --git a/src/components/Search/index.tsx b/src/components/Search/index.tsx index 8ec33c630..41f9cf4c6 100644 --- a/src/components/Search/index.tsx +++ b/src/components/Search/index.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useContext } from 'react'; import { useRouter } from 'next/router'; import { TvResult, @@ -7,6 +7,7 @@ import { } from '../../../server/models/Search'; import { useSWRInfinite } from 'swr'; import ListView from '../Common/ListView'; +import { LanguageContext } from '../../context/LanguageContext'; interface SearchResult { page: number; @@ -16,6 +17,7 @@ interface SearchResult { } const Search: React.FC = () => { + const { locale } = useContext(LanguageContext); const router = useRouter(); const { data, error, size, setSize } = useSWRInfinite( (pageIndex: number, previousPageData: SearchResult | null) => { @@ -25,7 +27,7 @@ const Search: React.FC = () => { return `/api/v1/search/?query=${router.query.query}&page=${ pageIndex + 1 - }`; + }&language=${locale}`; }, { initialSize: 3, diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json index 010869690..37cfb45c4 100644 --- a/src/i18n/locale/en.json +++ b/src/i18n/locale/en.json @@ -1,15 +1,25 @@ { + "components.Discover.discovermovies": "Discover Movies", + "components.Discover.discovertv": "Discover Series", "components.Discover.popularmovies": "Popular Movies", "components.Discover.populartv": "Popular Series", "components.Discover.recentrequests": "Recent Requests", "components.Layout.LanguagePicker.changelanguage": "Change Language", + "components.Layout.SearchInput.searchPlaceholder": "Search Movies & TV", + "components.Layout.Sidebar.dashboard": "Dashboard", + "components.Layout.Sidebar.requests": "Requests", + "components.Layout.Sidebar.settings": "Settings", "components.MovieDetails.budget": "Budget", "components.MovieDetails.cast": "Cast", "components.MovieDetails.originallanguage": "Original Language", "components.MovieDetails.overview": "Overview", + "components.MovieDetails.recommendations": "Recommendations", "components.MovieDetails.releasedate": "Release Date", "components.MovieDetails.revenue": "Revenue", "components.MovieDetails.runtime": "{minutes} minutes", + "components.MovieDetails.similar": "Similar Titles", "components.MovieDetails.status": "Status", - "components.MovieDetails.userrating": "User Rating" + "components.MovieDetails.userrating": "User Rating", + "components.RequestModal.cancelrequest": "This will remove your request. Are you sure you want to continue?", + "components.RequestModal.requestadmin": "Your request will be immediately approved. Do you wish to continue?" } diff --git a/src/i18n/locale/ja.json b/src/i18n/locale/ja.json index 58ab84dbc..78bd888a8 100644 --- a/src/i18n/locale/ja.json +++ b/src/i18n/locale/ja.json @@ -1,15 +1,25 @@ { - "components.Discover.popularmovies": "人気映画", - "components.Discover.populartv": "人気テレビ番組", + "components.Discover.discovermovies": "人気の映画", + "components.Discover.discovertv": "人気のテレビ番組", + "components.Discover.popularmovies": "人気の映画", + "components.Discover.populartv": "人気のテレビ番組", "components.Discover.recentrequests": "最近のリクエスト", "components.Layout.LanguagePicker.changelanguage": "言語", + "components.Layout.SearchInput.searchPlaceholder": "作品名で検索", + "components.Layout.Sidebar.dashboard": "ホーム", + "components.Layout.Sidebar.requests": "リクエスト", + "components.Layout.Sidebar.settings": "設定", "components.MovieDetails.budget": "興行収入", "components.MovieDetails.cast": "キャスト", "components.MovieDetails.originallanguage": "言語", "components.MovieDetails.overview": "ストーリー", + "components.MovieDetails.recommendations": "オススメの作品", "components.MovieDetails.releasedate": "公開日", "components.MovieDetails.revenue": "製作費", "components.MovieDetails.runtime": "{minutes}分", + "components.MovieDetails.similar": "関連作品", "components.MovieDetails.status": "状態", - "components.MovieDetails.userrating": "ユーザー評価" + "components.MovieDetails.userrating": "ユーザー評価", + "components.RequestModal.cancelrequest": "このリクエストをキャンセルしてよろしいですか?", + "components.RequestModal.requestadmin": "このリクエストが今すぐ承認致します。よろしいですか?" } diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 9552e3792..ad4a5a94b 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -85,22 +85,12 @@ const CoreApp: Omit = ({ }; CoreApp.getInitialProps = async (initialProps) => { - // Run the default getInitialProps for the main nextjs initialProps - const appInitialProps: AppInitialProps = await App.getInitialProps( - initialProps - ); const { ctx, router } = initialProps; let user = undefined; let locale = 'en'; if (ctx.res) { - const cookies = parseCookies(ctx); - - if (cookies.locale) { - locale = cookies.locale; - } - try { // Attempt to get the user by running a request to the local api const response = await axios.get( @@ -126,8 +116,19 @@ CoreApp.getInitialProps = async (initialProps) => { ctx.res.end(); } } + + const cookies = parseCookies(ctx); + + if (!!cookies.locale) { + locale = cookies.locale; + } } + // Run the default getInitialProps for the main nextjs initialProps + const appInitialProps: AppInitialProps = await App.getInitialProps( + initialProps + ); + const messages = await loadLocaleData(locale); return { ...appInitialProps, user, messages, locale }; diff --git a/src/pages/movie/[movieId]/index.tsx b/src/pages/movie/[movieId]/index.tsx index 1a97edcf8..a656ad7ed 100644 --- a/src/pages/movie/[movieId]/index.tsx +++ b/src/pages/movie/[movieId]/index.tsx @@ -19,8 +19,12 @@ MoviePage.getInitialProps = async (ctx) => { const response = await axios.get( `http://localhost:${process.env.PORT || 3000}/api/v1/movie/${ ctx.query.movieId - }?language=${cookies.locale}`, - { headers: ctx.req ? { cookie: ctx.req.headers.cookie } : undefined } + }${cookies.locale ? `?language=${cookies.locale}` : ''}`, + { + headers: ctx.req?.headers?.cookie + ? { cookie: ctx.req.headers.cookie } + : undefined, + } ); return {