From ea1f45bbafc12777748b5ff0e910c17ef20540b3 Mon Sep 17 00:00:00 2001 From: Simon Caron <8635747+simoncaron@users.noreply.github.com> Date: Sun, 12 Jan 2025 21:30:57 -0500 Subject: [PATCH] More settings + language component spacing --- app/(auth)/(tabs)/(favorites)/_layout.tsx | 3 +- app/(auth)/(tabs)/(home)/intro/page.tsx | 8 ++- app/(auth)/(tabs)/(home)/settings.tsx | 7 +-- .../(home)/settings/hide-libraries/page.tsx | 6 ++- components/JellyfinServerDiscovery.tsx | 6 ++- components/library/LibraryItemCard.tsx | 11 +++-- components/settings/AudioToggles.tsx | 4 +- components/settings/DownloadSettings.tsx | 6 +-- components/settings/MediaToggles.tsx | 4 +- components/settings/OtherSettings.tsx | 4 +- components/settings/PluginSettings.tsx | 2 +- components/settings/QuickConnect.tsx | 6 +-- components/settings/SubtitleToggles.tsx | 8 +-- translations/en.json | 41 +++++++++++++--- translations/fr.json | 49 ++++++++++++++----- 15 files changed, 110 insertions(+), 55 deletions(-) diff --git a/app/(auth)/(tabs)/(favorites)/_layout.tsx b/app/(auth)/(tabs)/(favorites)/_layout.tsx index b408eab6..b4c4452e 100644 --- a/app/(auth)/(tabs)/(favorites)/_layout.tsx +++ b/app/(auth)/(tabs)/(favorites)/_layout.tsx @@ -1,10 +1,9 @@ import { nestedTabPageScreenOptions } from "@/components/stacks/NestedTabPageStack"; import { Stack } from "expo-router"; import { Platform } from "react-native"; -import { useTranslation } from "react-i18next"; +import { t } from "i18next"; export default function SearchLayout() { - const { t } = useTranslation(); return ( - Centralised Settings Plugin + {t("home.intro.centralised_settings_plugin_title")} - Configure settings from a centralised location on your Jellyfin - server. All client settings for all users will be synced - automatically.{" "} + {t("home.intro.centralised_settings_plugin_description")}{" "} { @@ -107,7 +105,7 @@ export default function page() { ); }} > - Read more + {t("home.intro.read_more")} diff --git a/app/(auth)/(tabs)/(home)/settings.tsx b/app/(auth)/(tabs)/(home)/settings.tsx index bc17faf0..80a515dc 100644 --- a/app/(auth)/(tabs)/(home)/settings.tsx +++ b/app/(auth)/(tabs)/(home)/settings.tsx @@ -66,24 +66,25 @@ export default function settings() { - + + { router.push("/intro/page"); }} - title={"Show intro"} + title={t("home.settings.intro.show_intro")} /> { storage.set("hasShownIntro", false); }} - title={"Reset intro"} + title={t("home.settings.intro.reset_intro")} /> diff --git a/app/(auth)/(tabs)/(home)/settings/hide-libraries/page.tsx b/app/(auth)/(tabs)/(home)/settings/hide-libraries/page.tsx index 35200bc1..5b96ddbc 100644 --- a/app/(auth)/(tabs)/(home)/settings/hide-libraries/page.tsx +++ b/app/(auth)/(tabs)/(home)/settings/hide-libraries/page.tsx @@ -8,6 +8,7 @@ import { getUserViewsApi } from "@jellyfin/sdk/lib/utils/api"; import { useQuery } from "@tanstack/react-query"; import { useAtomValue } from "jotai"; import { Switch, View } from "react-native"; +import { useTranslation } from "react-i18next"; import DisabledSetting from "@/components/settings/DisabledSetting"; export default function page() { @@ -15,6 +16,8 @@ export default function page() { const user = useAtomValue(userAtom); const api = useAtomValue(apiAtom); + const { t } = useTranslation(); + const { data, isLoading: isLoading } = useQuery({ queryKey: ["user-views", user?.Id], queryFn: async () => { @@ -57,8 +60,7 @@ export default function page() { ))} - Select the libraries you want to hide from the Library tab and home page - sections. + {t("home.settings.other.select_liraries_you_want_to_hide")} ); diff --git a/components/JellyfinServerDiscovery.tsx b/components/JellyfinServerDiscovery.tsx index 5c310d64..dc2c46ad 100644 --- a/components/JellyfinServerDiscovery.tsx +++ b/components/JellyfinServerDiscovery.tsx @@ -4,6 +4,7 @@ import { useJellyfinDiscovery } from "@/hooks/useJellyfinDiscovery"; import { Button } from "./Button"; import { ListGroup } from "./list/ListGroup"; import { ListItem } from "./list/ListItem"; +import { useTranslation } from "react-i18next"; interface Props { onServerSelect?: (server: { address: string; serverName?: string }) => void; @@ -11,17 +12,18 @@ interface Props { const JellyfinServerDiscovery: React.FC = ({ onServerSelect }) => { const { servers, isSearching, startDiscovery } = useJellyfinDiscovery(); + const { t } = useTranslation(); return ( {servers.length ? ( - + {servers.map((server) => ( = ({ library, ...props }) => { const [user] = useAtom(userAtom); const [settings] = useSettings(); + const { t } = useTranslation(); + const url = useMemo( () => getPrimaryImageUrl({ @@ -69,13 +72,13 @@ export const LibraryItemCard: React.FC = ({ library, ...props }) => { let nameStr: string; if (library.CollectionType === "movies") { - nameStr = "movies"; + nameStr = t("library.item_types.movies"); } else if (library.CollectionType === "tvshows") { - nameStr = "series"; + nameStr = t("library.item_types.series"); } else if (library.CollectionType === "boxsets") { - nameStr = "box sets"; + nameStr = t("library.item_types.boxsets"); } else { - nameStr = "items"; + nameStr = t("library.item_types.items"); } return nameStr; diff --git a/components/settings/AudioToggles.tsx b/components/settings/AudioToggles.tsx index c1f82d6c..44c1a2a8 100644 --- a/components/settings/AudioToggles.tsx +++ b/components/settings/AudioToggles.tsx @@ -47,7 +47,7 @@ export const AudioToggles: React.FC = ({ ...props }) => { - {settings?.defaultAudioLanguage?.DisplayName || "None"} + {settings?.defaultAudioLanguage?.DisplayName || t("home.settings.audio.none")} = ({ ...props }) => { collisionPadding={8} sideOffset={8} > - Languages + {t("home.settings.audio.language")} { diff --git a/components/settings/DownloadSettings.tsx b/components/settings/DownloadSettings.tsx index 3199e049..8e233f38 100644 --- a/components/settings/DownloadSettings.tsx +++ b/components/settings/DownloadSettings.tsx @@ -61,7 +61,7 @@ export const DownloadSettings: React.FC = ({ ...props }) => { collisionPadding={8} sideOffset={8} > - Methods + {t("home.settings.downloads.methods")} { @@ -69,7 +69,7 @@ export const DownloadSettings: React.FC = ({ ...props }) => { setProcesses([]); }} > - Default + {t("home.settings.downloads.default")} { queryClient.invalidateQueries({ queryKey: ["search"] }); }} > - Optimized + {t("home.settings.downloads.optimized")} diff --git a/components/settings/MediaToggles.tsx b/components/settings/MediaToggles.tsx index a187f6e0..ae431ffb 100644 --- a/components/settings/MediaToggles.tsx +++ b/components/settings/MediaToggles.tsx @@ -37,7 +37,7 @@ export const MediaToggles: React.FC = ({ ...props }) => { value={settings.forwardSkipTime} disabled={pluginSettings?.forwardSkipTime?.locked} step={5} - appendValue="s" + appendValue={t("home.settings.media_controls.seconds_unit")} min={0} max={60} onUpdate={(forwardSkipTime) => updateSettings({forwardSkipTime})} @@ -52,7 +52,7 @@ export const MediaToggles: React.FC = ({ ...props }) => { value={settings.rewindSkipTime} disabled={pluginSettings?.rewindSkipTime?.locked} step={5} - appendValue="s" + appendValue={t("home.settings.media_controls.seconds_unit")} min={0} max={60} onUpdate={(rewindSkipTime) => updateSettings({rewindSkipTime})} diff --git a/components/settings/OtherSettings.tsx b/components/settings/OtherSettings.tsx index ce772bbe..a7249d6c 100644 --- a/components/settings/OtherSettings.tsx +++ b/components/settings/OtherSettings.tsx @@ -147,11 +147,11 @@ export const OtherSettings: React.FC = () => { router.push("/settings/hide-libraries/page")} - title="Hide Libraries" + title={t("home.settings.other.hide_libraries")} showArrow /> { if (!settings) return null; return ( - + router.push("/settings/jellyseerr/page")} title={"Jellyseerr"} diff --git a/components/settings/QuickConnect.tsx b/components/settings/QuickConnect.tsx index 774935d9..c3559b62 100644 --- a/components/settings/QuickConnect.tsx +++ b/components/settings/QuickConnect.tsx @@ -65,7 +65,7 @@ export const QuickConnect: React.FC = ({ ...props }) => { return ( - + bottomSheetModalRef?.current?.present()} title={t("home.settings.quick_connect.authorize_button")} @@ -96,7 +96,7 @@ export const QuickConnect: React.FC = ({ ...props }) => { = ({ ...props }) => { onPress={authorizeQuickConnect} color="purple" > - Authorize + {t("home.settings.quick_connect.authorize")} diff --git a/components/settings/SubtitleToggles.tsx b/components/settings/SubtitleToggles.tsx index c84e058e..a22fcc99 100644 --- a/components/settings/SubtitleToggles.tsx +++ b/components/settings/SubtitleToggles.tsx @@ -43,7 +43,7 @@ export const SubtitleToggles: React.FC = ({ ...props }) => { > item?.ThreeLetterISOLanguageName ?? "unknown"} titleExtractor={(item) => item?.DisplayName} title={ @@ -58,7 +58,7 @@ export const SubtitleToggles: React.FC = ({ ...props }) => { /> } - label="Languages" + label={t("home.settings.subtitles.language")} onSelected={(defaultSubtitleLanguage) => updateSettings({ defaultSubtitleLanguage: defaultSubtitleLanguage.DisplayName === t("home.settings.subtitles.none") @@ -81,7 +81,7 @@ export const SubtitleToggles: React.FC = ({ ...props }) => { title={ - {settings?.subtitleMode || "Loading"} + {settings?.subtitleMode || t("home.settings.subtitles.loading")} = ({ ...props }) => { /> } - label="Subtitle Mode" + label={t("home.settings.subtitles.subtitle_mode")} onSelected={(subtitleMode) => updateSettings({subtitleMode}) } diff --git a/translations/en.json b/translations/en.json index 3e12745d..d64a3f8b 100644 --- a/translations/en.json +++ b/translations/en.json @@ -27,7 +27,10 @@ "server_url_placeholder": "http(s)://your-server.com", "connect_button": "Connect", "previous_servers": "previous servers", - "clear_button": "Clear" + "clear_button": "Clear", + "search_for_local_servers": "Search for local servers", + "searching": "Searching...", + "servers": "Servers" }, "home": { "no_internet": "No Internet", @@ -50,8 +53,11 @@ "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.", + "centralised_settings_plugin_title": "Centralised Settings Plugin", + "centralised_settings_plugin_description": "Configure settings from a centralised location on your Jellyfin server. All client settings for all users will be synced automatically.", "done_button": "Done", - "go_to_settings_button": "Go to settings" + "go_to_settings_button": "Go to settings", + "read_more": "Read more" }, "settings": { "settings_title": "Settings", @@ -66,23 +72,26 @@ "quick_connect": { "quick_connect_title": "Quick Connect", "authorize_button": "Authorize Quick Connect", - "enter_the_quick_connect_code": "Enter the Quick Connect code", + "enter_the_quick_connect_code": "Enter the quick connect code...", "success": "Success", "quick_connect_autorized": "Quick Connect authorized", "error": "Error", - "invalid_code": "Invalid code" + "invalid_code": "Invalid code", + "authorize": "Authorize" }, "media_controls": { "media_controls_title": "Media Controls", "forward_skip_length": "Forward skip length", - "rewind_length": "Rewind length" + "rewind_length": "Rewind length", + "seconds_unit": "s" }, "audio": { "audio_title": "Audio", "set_audio_track": "Set Audio Track From Previous Item", "audio_language": "Audio language", "audio_hint": "Choose a default audio language.", - "none": "None" + "none": "None", + "language": "Language" }, "subtitles": { "subtitle_title": "Subtitles", @@ -91,14 +100,19 @@ "set_subtitle_track": "Set Subtitle Track From Previous Item", "subtitle_size": "Subtitle Size", "subtitle_hint": "Configure subtitle preference.", - "none": "None" + "none": "None", + "language": "Language", + "loading": "Loading" }, "other": { "other_title": "Other", "auto_rotate": "Auto rotate", "video_orientation": "Video orientation", "safe_area_in_controls": "Safe area in controls", - "show_custom_menu_links": "Show Custom Menu Links" + "show_custom_menu_links": "Show Custom Menu Links", + "hide_libraries": "Hide Libraries", + "select_liraries_you_want_to_hide": "Select the libraries you want to hide from the Library tab and home page sections.", + "disable_haptic_feedback": "Disable Haptic Feedback" }, "downloads": { "downloads_title": "Downloads", @@ -162,6 +176,10 @@ "size_used": "{{used}} of {{total}} used", "delete_all_downloaded_files": "Delete All Downloaded Files" }, + "intro": { + "show_intro": "Show intro", + "reset_intro": "Reset intro" + }, "logs": { "logs_title": "Logs", "no_logs_available": "No logs available", @@ -203,6 +221,7 @@ "something_went_wrong": "Something went wrong", "could_not_get_stream_url_from_jellyfin": "Could not get stream URL from Jellyfin", "eta": "ETA {{eta}}", + "methods": "Methods", "toasts": { "you_are_not_allowed_to_download_files": "You are not allowed to download files.", "deleted_all_movies_successfully": "Deleted all movies successfully!", @@ -270,6 +289,12 @@ "no_items_found": "No items found", "no_results": "No results", "no_libraries_found": "No libraries found", + "item_types": { + "movies": "movies", + "series": "series", + "boxsets": "box sets", + "items": "items" + }, "options": { "display": "Display", "row": "Row", diff --git a/translations/fr.json b/translations/fr.json index 777f87ee..461c1e37 100644 --- a/translations/fr.json +++ b/translations/fr.json @@ -27,7 +27,10 @@ "server_url_placeholder": "http(s)://votre-serveur.com", "connect_button": "Connexion", "previous_servers": "Serveurs précédents", - "clear_button": "Effacer" + "clear_button": "Effacer", + "search_for_local_servers": "Rechercher des serveurs locaux", + "searching": "Recherche...", + "servers": "Serveurs" }, "home": { "no_internet": "Pas d'Internet", @@ -50,8 +53,11 @@ "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.", + "centralised_settings_plugin_title": "Plugin de paramètres centralisés", + "centralised_settings_plugin_description": "Configuration des paramètres d'un emplacement centralisé sur votre serveur Jellyfin. Tous les paramètres clients pour tous les utilisateurs seront synchronisés automatiquement.", "done_button": "Fait", - "go_to_settings_button": "Allez dans les paramètres" + "go_to_settings_button": "Allez dans les paramètres", + "read_more": "Lisez-en plus" }, "settings": { "settings_title": "Paramètres", @@ -66,23 +72,26 @@ "quick_connect": { "quick_connect_title": "Connexion Rapide", "authorize_button": "Autoriser Connexion Rapide", - "enter_the_quick_connect_code": "Entrez le code Connexion Rapide", + "enter_the_quick_connect_code": "Entrez le code Connexion Rapide...", "success": "Succès", "quick_connect_autorized": "Connexion Rapide autorisé", - "error": "Errur", - "invalid_code": "Code invalide" + "error": "Erreur", + "invalid_code": "Code invalide", + "authorize": "Autoriser" }, "media_controls": { "media_controls_title": "Contrôles Média", "forward_skip_length": "Durée de saut en avant", - "rewind_length": "Durée de retour arrière" + "rewind_length": "Durée de retour arrière", + "seconds_unit": "s" }, "audio": { "audio_title": "Audio", "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": "Aucune" + "none": "Aucune", + "language": "Langage" }, "subtitles": { "subtitle_title": "Sous-titres", @@ -91,14 +100,19 @@ "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": "Aucune" + "none": "Aucune", + "language": "Langage", + "loading": "Chargement" }, "other": { "other_title": "Autres", "auto_rotate": "Rotation automatique", "video_orientation": "Orientation vidéo", "safe_area_in_controls": "Zone de sécurité dans les contrôles", - "show_custom_menu_links": "Afficher les liens personnalisés" + "show_custom_menu_links": "Afficher les liens personnalisés", + "hide_libraries": "Cacher des bibliothèques", + "select_liraries_you_want_to_hide": "Sélectionnez les bibliothèques que vous souhaitez obtenir de la table de bibliothèque et de la page d'accueil des sections.", + "disable_haptic_feedback": "Désactiver le retour haptique" }, "downloads": { "downloads_title": "Téléchargements", @@ -109,7 +123,7 @@ "save_button": "Enregistrer", "optimized_server": "Serveur optimisé", "optimized": "Optimisé", - "default": "Défaut", + "default": "Par défaut", "optimized_version_hint": "Entrez l'URL du serveur de versions optimisées. L'URL devrait inclure http ou https et optionnellement le port.", "read_more_about_optimized_server": "Lisez-en plus sur le serveur de versions optimisées.", "url": "URL", @@ -121,7 +135,7 @@ "jellyseerr_warning": "Cette intégration est dans ses débuts. Attendez-vous à ce que des choses changent.", "server_url": "URL du serveur", "server_url_hint": "Exemple: http(s)://votre-domaine.url\n(ajouter le port si nécessaire)", - "server_url_placeholder": "URL Jellyseerr...", + "server_url_placeholder": "URL de Jellyseerr...", "password": "Mot de passe", "password_placeholder": "Entrez le mot de passe pour l'utilisateur Jellyfin {{username}}", "save_button": "Enregistrer", @@ -159,9 +173,13 @@ "storage_title": "Stockage", "app_usage": "App {{usedSpace}}%", "phone_usage": "Téléphone {{availableSpace}}%", - "size_used": "{{used}} de {{total}} utilisé", + "size_used": "{{used}} de {{total}} utilisés", "delete_all_downloaded_files": "Supprimer tous les fichiers téléchargés" }, + "intro": { + "show_intro": "Afficher l'intro", + "reset_intro": "Réinitialiser l'intro" + }, "logs": { "logs_title": "Journaux", "no_logs_available": "Aucun journal disponible", @@ -203,6 +221,7 @@ "something_went_wrong": "Quelque chose s'est mal passé", "could_not_get_stream_url_from_jellyfin": "Impossible d'obtenir l'URL du flux depuis Jellyfin", "eta": "ETA {{eta}}", + "methods": "Méthodes", "toasts": { "you_are_not_allowed_to_download_files": "Vous n'êtes pas autorisé à télécharger des fichiers", "deleted_all_movies_successfully": "Tous les films ont été supprimés avec succès!", @@ -270,6 +289,12 @@ "no_items_found": "Aucun item trouvé", "no_results": "Aucun résultat", "no_libraries_found": "Aucune bibliothèque trouvée", + "item_types": { + "movies": "films", + "series": "séries", + "boxsets": "coffrets", + "items": "items" + }, "options": { "display": "Affichage", "row": "Rangée",