diff --git a/app/(auth)/(tabs)/(home)/intro/page.tsx b/app/(auth)/(tabs)/(home)/intro/page.tsx index cef9db31..59a315b0 100644 --- a/app/(auth)/(tabs)/(home)/intro/page.tsx +++ b/app/(auth)/(tabs)/(home)/intro/page.tsx @@ -6,9 +6,11 @@ import { Image } from "expo-image"; import { useFocusEffect, useRouter } from "expo-router"; import { useCallback } from "react"; import { TouchableOpacity, View } from "react-native"; +import {useTranslation } from "react-i18next"; export default function page() { const router = useRouter(); + const { t } = useTranslation(); useFocusEffect( useCallback(() => { @@ -20,18 +22,17 @@ export default function page() { - Welcome to Streamyfin + {t("home.intro.welcome_to_streamyfin")} - A free and open source client for Jellyfin. + {t("home.intro.a_free_and_open_source_client_for_jellyfin")} - Features + {t("home.intro.features_title")} - Streamyfin has a bunch of features and integrates with a wide array of - software which you can find in the settings menu, these include: + {t("home.intro.features_description")} Jellyseerr - Connect to your Jellyseerr instance and request movies directly in - the app. + {t("home.intro.jellyseerr_feature_description")} @@ -60,11 +60,9 @@ export default function page() { - Downloads + {t("home.intro.downloads_feature_title")} - Download movies and tv-shows to view offline. Use either the - default method or install the optimize server to download files in - the background. + {t("home.intro.downloads_feature_description")} @@ -81,7 +79,7 @@ export default function page() { Chromecast - Cast movies and tv-shows to your Chromecast devices. + {t("home.intro.chromecast_feature_description")} @@ -93,7 +91,7 @@ export default function page() { }} className="mt-4" > - Done + {t("home.intro.done_button")} { @@ -102,7 +100,7 @@ export default function page() { }} className="mt-4" > - Go to settings + {t("home.intro.go_to_settings_button")} ); diff --git a/app/(auth)/(tabs)/(home)/settings/marlin-search/page.tsx b/app/(auth)/(tabs)/(home)/settings/marlin-search/page.tsx index b263d857..4a907dd3 100644 --- a/app/(auth)/(tabs)/(home)/settings/marlin-search/page.tsx +++ b/app/(auth)/(tabs)/(home)/settings/marlin-search/page.tsx @@ -30,7 +30,7 @@ export default function page() { updateSettings({ marlinServerUrl: !val.endsWith("/") ? val : val.slice(0, -1), }); - toast.success("Saved"); + toast.success(t("home.settings.plugins.marlin_search.toasts.saved")); }; const handleOpenLink = () => { @@ -82,7 +82,7 @@ export default function page() { - Change server + {t("login.change_server")} ) : null, }); @@ -100,9 +100,9 @@ const CredentialsSchema = z.object({ } } catch (error) { if (error instanceof Error) { - Alert.alert("Connection failed", error.message); + Alert.alert(t("login.connection_failed"), error.message); } else { - Alert.alert("Connection failed", "An unexpected error occurred"); + Alert.alert(t("login.connection_failed"), t("login.an_unexpeted_error_occured")); } } finally { setLoading(false); diff --git a/components/SubtitleTrackSelector.tsx b/components/SubtitleTrackSelector.tsx index 887a26c8..f389e453 100644 --- a/components/SubtitleTrackSelector.tsx +++ b/components/SubtitleTrackSelector.tsx @@ -56,7 +56,7 @@ export const SubtitleTrackSelector: React.FC = ({ {selectedSubtitleSteam ? tc(selectedSubtitleSteam?.DisplayTitle, 7) - : "None"} + : t("item_card.none")} diff --git a/components/jellyseerr/discover/Slide.tsx b/components/jellyseerr/discover/Slide.tsx index 5a593b41..f110eb15 100644 --- a/components/jellyseerr/discover/Slide.tsx +++ b/components/jellyseerr/discover/Slide.tsx @@ -4,6 +4,7 @@ import { DiscoverSliderType } from "@/utils/jellyseerr/server/constants/discover import { Text } from "@/components/common/Text"; import { FlashList } from "@shopify/flash-list"; import {View, ViewProps} from "react-native"; +import { t } from "i18next"; export interface SlideProps { slide: DiscoverSlider; @@ -32,7 +33,7 @@ const Slide = ({ return ( - {DiscoverSliderType[slide.type].toString().toTitle()} + {t("search." + DiscoverSliderType[slide.type].toString().toLowerCase())} = ({ ...props }) => { }); }} > - t("home.settings.audio.none") + {t("home.settings.audio.none")} {cultures?.map((l) => ( = ({ ...props }) => { - {settings?.defaultSubtitleLanguage?.DisplayName || "None"} + {settings?.defaultSubtitleLanguage?.DisplayName || t("home.settings.subtitles.none")} = ({ const [jellyfin, setJellyfin] = useState(undefined); const [deviceId, setDeviceId] = useState(undefined); + const { t } = useTranslation(); + useEffect(() => { (async () => { const id = getOrSetDeviceId(); @@ -231,22 +234,22 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({ if (axios.isAxiosError(error)) { switch (error.response?.status) { case 401: - throw new Error("Invalid username or password"); + throw new Error(t("login.invalid_username_or_password")); case 403: - throw new Error("User does not have permission to log in"); + throw new Error(t("login.user_does_not_have_permission_to_log_in")); case 408: throw new Error( - "Server is taking too long to respond, try again later" + t("login.server_is_taking_too_long_to_respond_try_again_later") ); case 429: throw new Error( - "Server received too many requests, try again later" + t("login.server_received_too_many_requests_try_again_later") ); case 500: - throw new Error("There is a server error"); + throw new Error(t("login.there_is_a_server_error")); default: throw new Error( - "An unexpected error occurred. Did you enter the server URL correctly?" + t("login.an_unexpected_error_occured_did_you_enter_the_correct_url") ); } } diff --git a/translations/en.json b/translations/en.json index 74a13001..df44273d 100644 --- a/translations/en.json +++ b/translations/en.json @@ -12,7 +12,15 @@ "failed_to_initiate_quick_connect": "Failed to initiate Quick Connect", "got_it": "Got it", "connection_failed": "Connection failed", - "could_not_connect_to_server": "Could not connect to the server. Please check the URL and your network connection." + "could_not_connect_to_server": "Could not connect to the server. Please check the URL and your network connection.", + "an_unexpected_error_occured": "An unexpected error occurred", + "change_server": "Change server", + "invalid_username_or_password": "Invalid username or password", + "user_does_not_have_permission_to_log_in": "User does not have permission to log in", + "server_is_taking_too_long_to_respond_try_again_later": "Server is taking too long to respond, try again later", + "server_received_too_many_requests_try_again_later": "Server received too many requests, try again late.", + "there_is_a_server_error": "There is a server error", + "an_unexpected_error_occured_did_you_enter_the_correct_url": "An unexpected error occurred. Did you enter the server URL correctly?" }, "server": { "enter_url_to_jellyfin_server": "Enter the URL to your Jellyfin server", @@ -33,6 +41,18 @@ "recently_added_in": "Recently Added in {{libraryName}}", "suggested_movies": "Suggested Movies", "suggested_episodes": "Suggested Episodes", + "intro": { + "welcome_to_streamyfin": "Welcome to Streamyfin", + "a_free_and_open_source_client_for_jellyfin": "A free and open-source client for Jellyfin.", + "features_title": "Features", + "features_description": "Streamyfin has a bunch of features and integrates with a wide array of software which you can find in the settings menu, these include:", + "jellyseerr_feature_description": "Connect to your Jellyseerr instance and request movies directly in the app.", + "downloads_feature_title": "Downloads", + "downloads_feature_description": "Download movies and tv-shows to view offline. Use either the default method or install the optimize server to download files in the background.", + "chromecast_feature_description": "Cast movies and tv-shows to your Chromecast devices.", + "done_button": "Done", + "go_to_settings_button": "Go to settings" + }, "settings": { "settings_title": "Settings", "log_out_button": "Log out", @@ -121,7 +141,10 @@ "server_url_placeholder": "http(s)://domain.org:port", "marlin_search_hint": "Enter the URL for the Marlin server. The URL should include http or https and optionally the port.", "read_more_about_marlin": "Read more about Marlin.", - "save_button": "Save" + "save_button": "Save", + "toasts": { + "saved": "Saved" + } }, "popular_lists": { "enable_plugin": "Enable plugin", @@ -223,7 +246,28 @@ "albums": "Albums", "songs": "Songs", "request_movies": "Request Movies", - "request_series": "Request Series" + "request_series": "Request Series", + "recently_added": "Recently Added", + "recent_requests": "Recent Requests", + "plex_watchlist": "Plex Watchlist", + "trending": "Trending", + "popular_movies": "Popular Movies", + "movie_genres": "Movie Genres", + "upcoming_movies": "Upcoming Movies", + "studios": "Studios", + "popular_tv": "Popular TV", + "tv_genres": "TV Genres", + "upcoming_tv": "Upcoming TV", + "networks": "Networks", + "tmdb_movie_keyword": "TMDB Movie Keyword", + "tmdb_movie_genre": "TMDB Movie Genre", + "tmdb_tv_keyword": "TMDB TV Keyword", + "tmdb_tv_genre": "TMDB TV Genre", + "tmdb_search": "TMDB Search", + "tmdb_studio": "TMDB Studio", + "tmdb_network": "TMDB Network", + "tmdb_movie_streaming_services": "TMDB Movie Streaming Services", + "tmdb_tv_streaming_services": "TMDB TV Streaming Services" }, "library": { "no_items_found": "No items found", @@ -301,6 +345,7 @@ "x_albums": "{{count}} albums", "artists": "Artists", "could_not_load_item": "Could not load item", + "none": "None", "download": { "download_season": "Download Season", "download_x_item": "Download {{item_count}} items", diff --git a/translations/fr.json b/translations/fr.json index 02182ec2..a7b72412 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -12,7 +12,15 @@ "failed_to_initiate_quick_connect": "Échec de l'initialisation de Connexion Rapide", "got_it": "D'accord", "connection_failed": "La connection a échouée", - "could_not_connect_to_server": "Impossible de se connecter au serveur. Veuillez vérifier l'URL et votre connection réseau." + "could_not_connect_to_server": "Impossible de se connecter au serveur. Veuillez vérifier l'URL et votre connection réseau.", + "an_unexpected_error_occured": "Une erreur inattendue s'est produite", + "change_server": "Changer de serveur", + "invalid_username_or_password": "Nom d'utilisateur ou mot de passe invalide", + "user_does_not_have_permission_to_log_in": "L'utilisateur n'a pas la permission de se connecter", + "server_is_taking_too_long_to_respond_try_again_later": "Le serveur met trop de temps à répondre, réessayez plus tard", + "server_received_too_many_requests_try_again_later": "Le serveur a reçu trop de demandes, réessayez plus tard", + "there_is_a_server_error": "Il y a une erreur de serveur", + "an_unexpected_error_occured_did_you_enter_the_correct_url": "Une erreur inattendue s'est produite. Avez-vous entré la bonne URL?" }, "server": { "enter_url_to_jellyfin_server": "Entrez l'URL de votre serveur Jellyfin", @@ -33,6 +41,18 @@ "recently_added_in": "Ajoutés récemment dans {{libraryName}}", "suggested_movies": "Films suggérés", "suggested_episodes": "Épisodes suggérés", + "intro": { + "welcome_to_streamyfin": "Bienvenue sur Streamyfin", + "a_free_and_open_source_client_for_jellyfin": "Un client gratuit et open source pour Jellyfin", + "features_title": "Fonctionnalités", + "features_description": "Streamyfin possède de nombreuses fonctionnalités et s'intègre à un large éventail de logiciels que vous pouvez trouver dans le menu des paramètres, notamment:", + "jellyseerr_feature_description": "Connectez-vous à votre instance Jellyseerr et demandez des films directement dans l'application.", + "downloads_feature_title": "Téléchargements", + "downloads_feature_description": "Téléchargez des films et des émissions de télévision pour les regarder hors ligne. Utilisez la méthode par défaut ou installez le serveur d'optimisation pour télécharger les fichiers en arrière-plan.", + "chromecast_feature_description": "Diffusez des films et des émissions de télévision sur vos appareils Chromecast.", + "done_button": "Fait", + "go_to_settings_button": "Allez dans les paramètres" + }, "settings": { "settings_title": "Paramètres", "log_out_button": "Déconnexion", @@ -62,7 +82,7 @@ "set_audio_track": "Configurer la piste audio à partir de l'élément précédent", "audio_language": "Langue audio", "audio_hint": "Chosissez une langue audio par défaut.", - "none": "Aucun" + "none": "Aucune" }, "subtitles": { "subtitle_title": "Sous-titres", @@ -71,7 +91,7 @@ "set_subtitle_track": "Configurer la piste de sous-titres à partir de l'élément précédent", "subtitle_size": "Taille des sous-titres", "subtitle_hint": "Configurez les préférences des sous-titres.", - "none": "Aucun" + "none": "Aucune" }, "other": { "other_title": "Autres", @@ -121,7 +141,10 @@ "server_url_placeholder": "http(s)://domaine.org:port", "marlin_search_hint": "Entrez l'URL du serveur Marlin. L'URL devrait inclure http ou https et optionnellement le port.", "read_more_about_marlin": "Lisez-en plus sur Marlin.", - "save_button": "Enregistrer" + "save_button": "Enregistrer", + "toasts": { + "saved": "Enregistré" + } }, "popular_lists": { "enable_plugin": "Activer le plugiciel", @@ -223,7 +246,28 @@ "albums": "Albums", "songs": "Chansons", "request_movies": "Demander un film", - "request_series": "Demander une série" + "request_series": "Demander une série", + "recently_added": "Ajoutés récemment", + "recent_requests": "Demandes récentes", + "plex_watchlist": "Liste de lecture Plex", + "trending": "Tendance", + "popular_movies": "Films populaires", + "movie_genres": "Genres de films", + "upcoming_movies": "Films à venir", + "studios": "Studios", + "popular_tv": "TV populaire", + "tv_genres": "Genres TV", + "upcoming_tv": "TV à venir", + "networks": "Réseaux", + "tmdb_movie_keyword": "Mot-clé Films TMDB", + "tmdb_movie_genre": "Genre de film TMDB", + "tmdb_tv_keyword": "Mot-clé TV TMDB", + "tmdb_tv_genre": "Genre TV TMDB", + "tmdb_search": "Recherche TMDB", + "tmdb_studio": "Studio TMDB", + "tmdb_network": "Réseau TMDB", + "tmdb_movie_streaming_services": "Services de streaming de films TMDB", + "tmdb_tv_streaming_services": "Services de streaming TV TMDB" }, "library": { "no_items_found": "Aucun item trouvé", @@ -301,6 +345,7 @@ "x_albums": "{{count}} albums", "artists": "Artistes", "could_not_load_item": "Impossible de charger l'item", + "none": "Aucun", "download": { "download_season": "Télécharger la saison", "download_x_item": "Télécharger {{item_count}} items",