From 173408a1f269f09c724843ba087ef3f85b2832ad Mon Sep 17 00:00:00 2001 From: TheCatLady <52870424+TheCatLady@users.noreply.github.com> Date: Mon, 22 Mar 2021 21:03:02 -0400 Subject: [PATCH] fix(lang): allow proper localization of comma-delimited lists (#1264) * fix(lang): allow proper localization of comma-delimited lists * refactor: add string to globals instead, and remove unused strings --- src/components/CollectionDetails/index.tsx | 20 ++++++++++++-------- src/components/MovieDetails/index.tsx | 12 +++++------- src/components/PersonDetails/index.tsx | 9 ++++++--- src/components/TvDetails/index.tsx | 12 +++++------- src/i18n/globalMessages.ts | 1 + src/i18n/locale/en.json | 14 +------------- 6 files changed, 30 insertions(+), 38 deletions(-) diff --git a/src/components/CollectionDetails/index.tsx b/src/components/CollectionDetails/index.tsx index 251d8d953..b58bc5acf 100644 --- a/src/components/CollectionDetails/index.tsx +++ b/src/components/CollectionDetails/index.tsx @@ -1,4 +1,6 @@ import axios from 'axios'; +import { uniq } from 'lodash'; +import Link from 'next/link'; import { useRouter } from 'next/router'; import React, { useContext, useState } from 'react'; import { defineMessages, useIntl } from 'react-intl'; @@ -8,20 +10,19 @@ import { MediaStatus } from '../../../server/constants/media'; import type { MediaRequest } from '../../../server/entity/MediaRequest'; import type { Collection } from '../../../server/models/Collection'; import { LanguageContext } from '../../context/LanguageContext'; +import useSettings from '../../hooks/useSettings'; +import { Permission, useUser } from '../../hooks/useUser'; +import globalMessages from '../../i18n/globalMessages'; import Error from '../../pages/_error'; -import StatusBadge from '../StatusBadge'; import ButtonWithDropdown from '../Common/ButtonWithDropdown'; +import CachedImage from '../Common/CachedImage'; import LoadingSpinner from '../Common/LoadingSpinner'; import Modal from '../Common/Modal'; +import PageTitle from '../Common/PageTitle'; import Slider from '../Slider'; +import StatusBadge from '../StatusBadge'; import TitleCard from '../TitleCard'; import Transition from '../Transition'; -import PageTitle from '../Common/PageTitle'; -import { useUser, Permission } from '../../hooks/useUser'; -import useSettings from '../../hooks/useSettings'; -import Link from 'next/link'; -import { uniq } from 'lodash'; -import CachedImage from '../Common/CachedImage'; const messages = defineMessages({ overviewunavailable: 'Overview unavailable.', @@ -193,7 +194,10 @@ const CollectionDetails: React.FC = ({ )) .reduce((prev, curr) => ( <> - {prev}, {curr} + {intl.formatMessage(globalMessages.delimitedlist, { + a: prev, + b: curr, + })} )) ); diff --git a/src/components/MovieDetails/index.tsx b/src/components/MovieDetails/index.tsx index bd577f59c..3ab99f66f 100644 --- a/src/components/MovieDetails/index.tsx +++ b/src/components/MovieDetails/index.tsx @@ -15,6 +15,7 @@ import TmdbLogo from '../../assets/tmdb_logo.svg'; import { LanguageContext } from '../../context/LanguageContext'; import useSettings from '../../hooks/useSettings'; import { Permission, useUser } from '../../hooks/useUser'; +import globalMessages from '../../i18n/globalMessages'; import Error from '../../pages/_error'; import { sortCrewPriority } from '../../utils/creditHelpers'; import Button from '../Common/Button'; @@ -45,10 +46,6 @@ const messages = defineMessages({ cast: 'Cast', recommendations: 'Recommendations', similar: 'Similar Titles', - cancelrequest: 'Cancel Request', - available: 'Available', - unavailable: 'Unavailable', - pending: 'Pending', overviewunavailable: 'Overview unavailable.', manageModalTitle: 'Manage Movie', manageModalRequests: 'Requests', @@ -56,8 +53,6 @@ const messages = defineMessages({ manageModalClearMedia: 'Clear All Media Data', manageModalClearMediaWarning: '* This will irreversibly remove all data for this movie, including any requests. If this item exists in your Plex library, the media information will be recreated during the next scan.', - approve: 'Approve', - decline: 'Decline', studio: '{studioCount, plural, one {Studio} other {Studios}}', viewfullcrew: 'View Full Crew', view: 'View', @@ -191,7 +186,10 @@ const MovieDetails: React.FC = ({ movie }) => { )) .reduce((prev, curr) => ( <> - {prev}, {curr} + {intl.formatMessage(globalMessages.delimitedlist, { + a: prev, + b: curr, + })} )) ); diff --git a/src/components/PersonDetails/index.tsx b/src/components/PersonDetails/index.tsx index 7ed2ac14e..a0082c79c 100644 --- a/src/components/PersonDetails/index.tsx +++ b/src/components/PersonDetails/index.tsx @@ -8,6 +8,7 @@ import type { PersonCombinedCreditsResponse } from '../../../server/interfaces/a import type { PersonDetail } from '../../../server/models/Person'; import Ellipsis from '../../assets/ellipsis.svg'; import { LanguageContext } from '../../context/LanguageContext'; +import globalMessages from '../../i18n/globalMessages'; import Error from '../../pages/_error'; import CachedImage from '../Common/CachedImage'; import ImageFader from '../Common/ImageFader'; @@ -19,7 +20,6 @@ const messages = defineMessages({ birthdate: 'Born {birthdate}', lifespan: '{birthdate} – {deathdate}', alsoknownas: 'Also Known As: {names}', - namedelimiter: ', ', appearsin: 'Appearances', crewmember: 'Crew', ascharacter: 'as {character}', @@ -239,8 +239,11 @@ const PersonDetails: React.FC = () => { {(data.alsoKnownAs ?? []).length > 0 && (
{intl.formatMessage(messages.alsoknownas, { - names: (data.alsoKnownAs ?? []).join( - intl.formatMessage(messages.namedelimiter) + names: (data.alsoKnownAs ?? []).reduce((prev, curr) => + intl.formatMessage(globalMessages.delimitedlist, { + a: prev, + b: curr, + }) ), })}
diff --git a/src/components/TvDetails/index.tsx b/src/components/TvDetails/index.tsx index f3ef73a41..3402eeb61 100644 --- a/src/components/TvDetails/index.tsx +++ b/src/components/TvDetails/index.tsx @@ -17,6 +17,7 @@ import TmdbLogo from '../../assets/tmdb_logo.svg'; import { LanguageContext } from '../../context/LanguageContext'; import useSettings from '../../hooks/useSettings'; import { Permission, useUser } from '../../hooks/useUser'; +import globalMessages from '../../i18n/globalMessages'; import Error from '../../pages/_error'; import { sortCrewPriority } from '../../utils/creditHelpers'; import Button from '../Common/Button'; @@ -45,11 +46,7 @@ const messages = defineMessages({ cast: 'Cast', recommendations: 'Recommendations', similar: 'Similar Series', - cancelrequest: 'Cancel Request', watchtrailer: 'Watch Trailer', - available: 'Available', - unavailable: 'Unavailable', - pending: 'Pending', overviewunavailable: 'Overview unavailable.', manageModalTitle: 'Manage Series', manageModalRequests: 'Requests', @@ -57,8 +54,6 @@ const messages = defineMessages({ manageModalClearMedia: 'Clear All Media Data', manageModalClearMediaWarning: '* This will irreversibly remove all data for this TV series, including any requests. If this item exists in your Plex library, the media information will be recreated during the next scan.', - approve: 'Approve', - decline: 'Decline', showtype: 'Series Type', anime: 'Anime', network: '{networkCount, plural, one {Network} other {Networks}}', @@ -200,7 +195,10 @@ const TvDetails: React.FC = ({ tv }) => { )) .reduce((prev, curr) => ( <> - {prev}, {curr} + {intl.formatMessage(globalMessages.delimitedlist, { + a: prev, + b: curr, + })} )) ); diff --git a/src/i18n/globalMessages.ts b/src/i18n/globalMessages.ts index 7322994ed..077a23f38 100644 --- a/src/i18n/globalMessages.ts +++ b/src/i18n/globalMessages.ts @@ -26,6 +26,7 @@ const globalMessages = defineMessages({ loading: 'Loading…', settings: 'Settings', usersettings: 'User Settings', + delimitedlist: '{a}, {b}', }); export default globalMessages; diff --git a/src/i18n/locale/en.json b/src/i18n/locale/en.json index d5c4623a2..01ec36666 100644 --- a/src/i18n/locale/en.json +++ b/src/i18n/locale/en.json @@ -62,13 +62,9 @@ "components.MediaSlider.ShowMoreCard.seemore": "See More", "components.MovieDetails.MovieCast.fullcast": "Full Cast", "components.MovieDetails.MovieCrew.fullcrew": "Full Crew", - "components.MovieDetails.approve": "Approve", "components.MovieDetails.areyousure": "Are you sure?", - "components.MovieDetails.available": "Available", "components.MovieDetails.budget": "Budget", - "components.MovieDetails.cancelrequest": "Cancel Request", "components.MovieDetails.cast": "Cast", - "components.MovieDetails.decline": "Decline", "components.MovieDetails.downloadstatus": "Download Status", "components.MovieDetails.manageModalClearMedia": "Clear All Media Data", "components.MovieDetails.manageModalClearMediaWarning": "* This will irreversibly remove all data for this movie, including any requests. If this item exists in your Plex library, the media information will be recreated during the next scan.", @@ -82,7 +78,6 @@ "components.MovieDetails.originallanguage": "Original Language", "components.MovieDetails.overview": "Overview", "components.MovieDetails.overviewunavailable": "Overview unavailable.", - "components.MovieDetails.pending": "Pending", "components.MovieDetails.play4konplex": "Play 4K on Plex", "components.MovieDetails.playonplex": "Play on Plex", "components.MovieDetails.recommendations": "Recommendations", @@ -92,7 +87,6 @@ "components.MovieDetails.similar": "Similar Titles", "components.MovieDetails.status": "Status", "components.MovieDetails.studio": "{studioCount, plural, one {Studio} other {Studios}}", - "components.MovieDetails.unavailable": "Unavailable", "components.MovieDetails.view": "View", "components.MovieDetails.viewfullcrew": "View Full Crew", "components.MovieDetails.watchtrailer": "Watch Trailer", @@ -148,7 +142,6 @@ "components.PersonDetails.birthdate": "Born {birthdate}", "components.PersonDetails.crewmember": "Crew", "components.PersonDetails.lifespan": "{birthdate} – {deathdate}", - "components.PersonDetails.namedelimiter": ", ", "components.PlexLoginButton.loading": "Loading…", "components.PlexLoginButton.signingin": "Signing in…", "components.PlexLoginButton.signinwithplex": "Sign In", @@ -662,12 +655,8 @@ "components.TvDetails.TvCrew.fullseriescrew": "Full Series Crew", "components.TvDetails.allseasonsmarkedavailable": "* All seasons will be marked as available.", "components.TvDetails.anime": "Anime", - "components.TvDetails.approve": "Approve", "components.TvDetails.areyousure": "Are you sure?", - "components.TvDetails.available": "Available", - "components.TvDetails.cancelrequest": "Cancel Request", "components.TvDetails.cast": "Cast", - "components.TvDetails.decline": "Decline", "components.TvDetails.downloadstatus": "Download Status", "components.TvDetails.episodeRuntime": "Episode Runtime", "components.TvDetails.episodeRuntimeMinutes": "{runtime} minutes", @@ -686,7 +675,6 @@ "components.TvDetails.originallanguage": "Original Language", "components.TvDetails.overview": "Overview", "components.TvDetails.overviewunavailable": "Overview unavailable.", - "components.TvDetails.pending": "Pending", "components.TvDetails.play4konplex": "Play 4K on Plex", "components.TvDetails.playonplex": "Play on Plex", "components.TvDetails.recommendations": "Recommendations", @@ -694,7 +682,6 @@ "components.TvDetails.showtype": "Series Type", "components.TvDetails.similar": "Similar Series", "components.TvDetails.status": "Status", - "components.TvDetails.unavailable": "Unavailable", "components.TvDetails.viewfullcrew": "View Full Crew", "components.TvDetails.watchtrailer": "Watch Trailer", "components.UserList.accounttype": "Account Type", @@ -838,6 +825,7 @@ "i18n.declined": "Declined", "i18n.delete": "Delete", "i18n.deleting": "Deleting…", + "i18n.delimitedlist": "{a}, {b}", "i18n.edit": "Edit", "i18n.experimental": "Experimental", "i18n.failed": "Failed",