diff --git a/app/(auth)/(tabs)/(home)/settings.tsx b/app/(auth)/(tabs)/(home)/settings.tsx index 46aecbae..f28918c6 100644 --- a/app/(auth)/(tabs)/(home)/settings.tsx +++ b/app/(auth)/(tabs)/(home)/settings.tsx @@ -14,6 +14,7 @@ import { Alert, ScrollView, View } from "react-native"; import * as Progress from "react-native-progress"; import { useSafeAreaInsets } from "react-native-safe-area-context"; import { toast } from "sonner-native"; +import { useTranslation } from "react-i18next"; export default function settings() { const { logout } = useJellyfin(); @@ -25,6 +26,8 @@ export default function settings() { const insets = useSafeAreaInsets(); + const { t } = useTranslation(); + const { data: size, isLoading: appSizeLoading } = useQuery({ queryKey: ["appSize", appSizeUsage], queryFn: async () => { @@ -98,31 +101,31 @@ export default function settings() { registerBackgroundFetchAsync */} - User Info + {t("home.settings.user_info.user_info_title")} - - - + + + - Quick connect + {t("home.settings.quick_connect.quick_connect_title")} - Storage + {t("home.settings.storage.storage_title")} - {size && App usage: {size.app.bytesToReadable()}} + {size && {t("home.settings.storage.app_usage", {usedSpace: size.app.bytesToReadable()})}} {size && ( - Available: {size.remaining?.bytesToReadable()}, Total:{" "} - {size.total?.bytesToReadable()} + {t("home.settings.storage.available_total", {availableSpace: size.remaining?.bytesToReadable(), totalSpace: size.total?.bytesToReadable()})} + {} )} - Logs + {t("home.settings.logs.logs_title")} {logs?.map((log, index) => ( @@ -167,7 +170,7 @@ export default function settings() { ))} {logs?.length === 0 && ( - No logs available + {t("home.settings.logs.no_logs_available")} )} diff --git a/components/settings/AudioToggles.tsx b/components/settings/AudioToggles.tsx index ec9d71ce..d69f687d 100644 --- a/components/settings/AudioToggles.tsx +++ b/components/settings/AudioToggles.tsx @@ -3,6 +3,7 @@ import * as DropdownMenu from "zeego/dropdown-menu"; import { Text } from "../common/Text"; import { useMedia } from "./MediaContext"; import { Switch } from "react-native-gesture-handler"; +import { useTranslation } from "react-i18next"; interface Props extends ViewProps {} @@ -10,12 +11,13 @@ export const AudioToggles: React.FC = ({ ...props }) => { const media = useMedia(); const { settings, updateSettings } = media; const cultures = media.cultures; + const { t } = useTranslation(); if (!settings) return null; return ( - Audio + {t("home.settings.audio.audio_title")} = ({ ...props }) => { `} > - Audio language + {t("home.settings.audio.audio_language")} - Choose a default audio language. + {t("home.settings.audio.audio_language_hint")} @@ -76,9 +78,9 @@ export const AudioToggles: React.FC = ({ ...props }) => { - Use Default Audio + {t("home.settings.audio.use_default_audio")} - Play default audio track regardless of language. + {t("home.settings.audio.use_default_audio_hint")} = ({ ...props }) => { - Set Audio Track From Previous Item + {t("home.settings.audio.set_audio_track")} - Try to set the audio track to the closest match to the last - video. + {t("home.settings.audio.set_audio_track_hint")} { const { @@ -20,6 +21,8 @@ export const JellyseerrSettings = () => { clearAllJellyseerData, } = useJellyseerr(); + const { t } = useTranslation(); + const [user] = useAtom(userAtom); const [settings, updateSettings] = useSettings(); @@ -121,19 +124,16 @@ export const JellyseerrSettings = () => { ) : ( - This integration is in its early stages. Expect things to change. + {t("home.settings.jellyseer.jellyseer_warning")} - Server URL + {t("home.settings.jellyseer.server_url")} - Example: http(s)://your-host.url - - - (add port if required) + {t("home.settings.jellyseer.server_url_hint")} { marginBottom: 8, }} > - {promptForJellyseerrPass ? "Clear" : "Save"} + {promptForJellyseerrPass ? t("home.settings.jellyseer.clear_button") : t("home.settings.jellyseer.save_button")} { opacity: promptForJellyseerrPass ? 1 : 0.5, }} > - Password + {t("home.settings.jellyseer.password")} { className="h-12 mt-2" onPress={() => loginToJellyseerrMutation.mutate()} > - Login + {t("home.settings.jellyseer.login_button")} diff --git a/components/settings/MediaToggles.tsx b/components/settings/MediaToggles.tsx index c92902e2..6ef4cae4 100644 --- a/components/settings/MediaToggles.tsx +++ b/components/settings/MediaToggles.tsx @@ -1,17 +1,19 @@ import { useSettings } from "@/utils/atoms/settings"; import { TouchableOpacity, View, ViewProps } from "react-native"; import { Text } from "../common/Text"; +import { useTranslation } from "react-i18next"; interface Props extends ViewProps {} export const MediaToggles: React.FC = ({ ...props }) => { const [settings, updateSettings] = useSettings(); + const { t } = useTranslation(); if (!settings) return null; return ( - Media + {t("home.settings.media.media_title")} = ({ ...props }) => { `} > - Forward skip length + {t("home.settings.media.forward_skip_length")} - Choose length in seconds when skipping in video playback. + {t("home.settings.media.forward_skip_length_hint")} @@ -57,9 +59,9 @@ export const MediaToggles: React.FC = ({ ...props }) => { `} > - Rewind length + {t("home.settings.media.rewind_length")} - Choose length in seconds when skipping in video playback. + {t("home.settings.media.rewind_length_hint")} diff --git a/components/settings/SettingToggles.tsx b/components/settings/SettingToggles.tsx index a83f95f8..ef3ae116 100644 --- a/components/settings/SettingToggles.tsx +++ b/components/settings/SettingToggles.tsx @@ -43,6 +43,7 @@ import { AudioToggles } from "./AudioToggles"; import { JellyseerrApi, useJellyseerr } from "@/hooks/useJellyseerr"; import { ListItem } from "@/components/ListItem"; import { JellyseerrSettings } from "./Jellyseerr"; +import { useTranslation } from "react-i18next"; interface Props extends ViewProps {} @@ -59,6 +60,8 @@ export const SettingToggles: React.FC = ({ ...props }) => { const queryClient = useQueryClient(); + const { t } = useTranslation(); + /******************** * Background task *******************/ @@ -137,15 +140,14 @@ export const SettingToggles: React.FC = ({ ...props }) => { - Other + {t("home.settings.other.other_title")} - Auto rotate + {t("home.settings.other.auto_rotate")} - Important on android since the video player orientation is - locked to the app orientation. + {t("home.settings.other.auto_rotate_hint")} = ({ ...props }) => { `} > - Video orientation + {t("home.settings.other.video_orientation")} - Set the full screen video player orientation. + {t("home.settings.other.video_orientation_hint")} @@ -263,9 +265,9 @@ export const SettingToggles: React.FC = ({ ...props }) => { - Safe area in controls + {t("home.settings.other.safe_area_in_controls")} - Enable safe area in video player controls + {t("home.settings.other.safe_area_in_controls_hint")} = ({ ...props }) => { - Use popular lists plugin - Made by: lostb1t + {t("home.settings.other.use_popular_lists_plugin")} + {t("home.settings.other.use_popular_lists_plugin_hint")} { Linking.openURL( @@ -288,7 +290,7 @@ export const SettingToggles: React.FC = ({ ...props }) => { ); }} > - More info + {t("home.settings.other.more_info")} = ({ ...props }) => { `} > - Search engine + {t("home.settings.other.search_engine")} - Choose the search engine you want to use. + {t("home.settings.other.search_engine_hint")} @@ -421,7 +423,7 @@ export const SettingToggles: React.FC = ({ ...props }) => { }); }} > - Save + {t("home.settings.other.save_button")} @@ -436,10 +438,9 @@ export const SettingToggles: React.FC = ({ ...props }) => { - Show Custom Menu Links + {t("home.settings.other.show_custom_menu_links")} - Show custom menu links defined inside your Jellyfin web - config.json file + {t("home.settings.other.show_custom_menu_links_hint")} @@ -448,7 +449,7 @@ export const SettingToggles: React.FC = ({ ...props }) => { ) } > - More info + {t("home.settings.other.more_info")} = ({ ...props }) => { - Downloads + {t("home.settings.downloads.downloads_title")} = ({ ...props }) => { `} > - Download method + {t("home.settings.downloads.download_method")} - Choose the download method to use. Optimized requires the - optimized server. + {t("home.settings.downloads.download_method_hint")} @@ -531,10 +531,9 @@ export const SettingToggles: React.FC = ({ ...props }) => { }`} > - Remux max download + {t("home.settings.downloads.remux_max_download")} - This is the total media you want to be able to download at the - same time. + {t("home.settings.downloads.remux_max_download_hint")} = ({ ...props }) => { }`} > - Auto download + {t("home.settings.downloads.auto_download")} - This will automatically download the media file when it's - finished optimizing on the server. + {t("home.settings.downloads.auto_download_hint")} = ({ ...props }) => { - Optimized versions server + {t("home.settings.downloads.optimized_versions_server")} - Set the URL for the optimized versions server for downloads. + {t("home.settings.downloads.optimized_versions_server_hint")} @@ -629,7 +627,7 @@ export const SettingToggles: React.FC = ({ ...props }) => { } else toast.error("Could not connect"); }} > - Save + {t("home.settings.downloads.save_button")} diff --git a/components/settings/SubtitleToggles.tsx b/components/settings/SubtitleToggles.tsx index 93745df2..e5fcc54f 100644 --- a/components/settings/SubtitleToggles.tsx +++ b/components/settings/SubtitleToggles.tsx @@ -4,6 +4,7 @@ import { Text } from "../common/Text"; import { useMedia } from "./MediaContext"; import { Switch } from "react-native-gesture-handler"; import { SubtitlePlaybackMode } from "@jellyfin/sdk/lib/generated-client"; +import { useTranslation } from "react-i18next"; interface Props extends ViewProps {} @@ -11,6 +12,8 @@ export const SubtitleToggles: React.FC = ({ ...props }) => { const media = useMedia(); const { settings, updateSettings } = media; const cultures = media.cultures; + const { t } = useTranslation(); + if (!settings) return null; const subtitleModes = [ @@ -23,7 +26,7 @@ export const SubtitleToggles: React.FC = ({ ...props }) => { return ( - Subtitle + {t("home.settings.subtitles.subtitle_title")} = ({ ...props }) => { `} > - Subtitle language + {t("home.settings.subtitles.subtitle_language")} - Choose a default subtitle language. + {t("home.settings.subtitles.subtitle_language_hint")} @@ -88,11 +91,9 @@ export const SubtitleToggles: React.FC = ({ ...props }) => { `} > - Subtitle Mode + {t("home.settings.subtitles.subtitle_mode")} - Subtitles are loaded based on the default and forced flags in the - embedded metadata. Language preferences are considered when - multiple options are available. + {t("home.settings.subtitles.subtitle_mode_hint")} @@ -131,11 +132,10 @@ export const SubtitleToggles: React.FC = ({ ...props }) => { - Set Subtitle Track From Previous Item + {t("home.settings.subtitles.set_subtitle_track")} - Try to set the subtitle track to the closest match to the last - video. + {t("home.settings.subtitles.set_subtitle_track_hint")} = ({ ...props }) => { `} > - Subtitle Size + {t("home.settings.subtitles.subtitle_size")} - Choose a default subtitle size for direct play (only works for - some subtitle formats). + {t("home.settings.subtitles.subtitle_size_hint")} diff --git a/translations/en.json b/translations/en.json index ae1da178..337cf1fe 100644 --- a/translations/en.json +++ b/translations/en.json @@ -29,13 +29,16 @@ "suggested_episodes": "Suggested Episodes", "settings": { "settings_title": "Settings", - "user_info": "User Info", - "user": "User", - "server": "Server", - "token": "Token", - "log_out": "Log out", - "quick_connect": "Quick connect", - "authorize": "Authorize", + "user_info": { + "user_info_title": "User Info", + "user": "User", + "server": "Server", + "log_out_button": "Log out" + }, + "quick_connect": { + "quick_connect_title": "Quick connect", + "authorize_button": "Authorize" + }, "media":{ "media_title": "Media", "forward_skip_length": "Forward skip length", @@ -58,14 +61,15 @@ "subtitle_language_hint": "Choose a default subtitle language.", "subtitle_mode": "Subtitle Mode", "subtitle_mode_hint": "Subtitles are loaded based on the default and forced flags in the\nembedded metadata. Language preferences are considered when\nmultiple options are available.", - "set_subtitle_track": "Try to set the subtitle track to the closest match to the last\nvideo.", + "set_subtitle_track": "Set Subtitle Track From Previous Item", + "set_subtitle_track_hint" :"Try to set the subtitle track to the closest match to the last\nvideo.", "subtitle_size": "Subtitle Size", "subtitle_size_hint": "Choose a default subtitle size for direct play (only works for\nsome subtitle formats)." }, "other": { "other_title": "Other", "auto_rotate": "Auto rotate", - "auto_rotate_hint": "Important on android since the video player orientation is\nlocked to the app orientation.", + "auto_rotate_hint": "Important on android since the video player orientation is locked to the app orientation.", "video_orientation": "Video orientation", "video_orientation_hint": "Set the full screen video player orientation", "safe_area_in_controls": "Safe area in controls", @@ -76,18 +80,20 @@ "search_engine": "Search engine", "search_engine_hint": "Choose the search engine you want to use.", "show_custom_menu_links": "Show Custom Menu Links", - "show_custom_menu_links_hint": "Show custom menu links defined inside your Jellyfin web\nconfig.json file" + "show_custom_menu_links_hint": "Show custom menu links defined inside your Jellyfin web config.json file", + "save_button": "Save" }, "downloads": { "downloads_title": "Downloads", "download_method": "Download method", - "download_method_hint": "Choose the download method to use. Optimized requires the\noptimized server.", + "download_method_hint": "Choose the download method to use. Optimized requires the optimized server.", "remux_max_download": "Remux max download", - "remux_max_download_hint": "This is the total media you want to be able to download at the\nsame time.", + "remux_max_download_hint": "This is the total media you want to be able to download at the same time.", "auto_download": "Auto download", - "auto_download_hint": "This will automatically download the media file when it's\nfinished optimizing on the server.", + "auto_download_hint": "This will automatically download the media file when it's finished optimizing on the server.", "optimized_versions_server": "Optimized versions server", - "optimized_versions_server_hint": "TSet the URL for the optimized versions server for downloads." + "optimized_versions_server_hint": "Set the URL for the optimized versions server for downloads.", + "save_button": "Save" }, "jellyseer": { "jellyseer_warning": "This integration is in its early stages. Expect things to change.", @@ -95,7 +101,10 @@ "server_url_hint": "Example: http(s)://your-host.url\n(add port if required)", "server_url_placeholder": "Jellyseerr URL...", "password": "Password", - "password_placeholder": "Enter password for Jellyfin user {{username}}" + "password_placeholder": "Enter password for Jellyfin user {{username}}", + "save_button": "Save", + "clear_button": "Clear", + "login_button": "Login" }, "storage": { "storage_title": "Storage", @@ -107,9 +116,7 @@ "logs": { "logs_title": "Logs", "no_logs_available": "No logs available" - }, - "save_button": "Save", - "login_button": "Login" + } }, "downloads": { "downloads_title": "Downloads",