diff --git a/.claude/settings.local.json b/.claude/settings.local.json index f8f0a98c..0a94ef78 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -1,8 +1,5 @@ { "permissions": { - "allow": [ - "Bash(perl -i -pe:*)", - "Bash(bun run:*)" - ] + "allow": ["Bash(perl -i -pe:*)", "Bash(bun run:*)"] } } diff --git a/src/components/Elements/AddModal/AddModal.jsx b/src/components/Elements/AddModal/AddModal.jsx index d506d7a5..5bf506f5 100644 --- a/src/components/Elements/AddModal/AddModal.jsx +++ b/src/components/Elements/AddModal/AddModal.jsx @@ -1,4 +1,4 @@ -import variables from 'config/variables'; +import { useT } from 'contexts'; import { useState, memo, useEffect } from 'react'; import { MdAddLink, MdClose } from 'react-icons/md'; @@ -10,6 +10,7 @@ import { IconService } from 'utils/quicklinks'; import './AddModal.scss'; function AddModal({ urlError, iconError, addLink, closeModal, edit, editData, editLink }) { + const t = useT(); const [name, setName] = useState(edit ? editData.name : ''); const [url, setUrl] = useState(edit ? editData.url : ''); const [icon, setIcon] = useState(edit ? editData.icon : ''); @@ -102,11 +103,9 @@ function AddModal({ urlError, iconError, addLink, closeModal, edit, editData, ed
- {edit - ? variables.getMessage('widgets.quicklinks.edit') - : variables.getMessage('widgets.quicklinks.new')} + {edit ? t('widgets.quicklinks.edit') : t('widgets.quicklinks.new')} - +
closeModal()}>
@@ -116,12 +115,10 @@ function AddModal({ urlError, iconError, addLink, closeModal, edit, editData, ed
- + {suggestedName && !name && ( - {variables.getMessage('widgets.quicklinks.suggested', { name: suggestedName })} + {t('widgets.quicklinks.suggested', { name: suggestedName })} )}
@@ -130,12 +127,12 @@ function AddModal({ urlError, iconError, addLink, closeModal, edit, editData, ed name="quicklink_modal_name" noSetting={true} onChange={(value) => setName(value)} - placeholder={suggestedName || variables.getMessage('widgets.quicklinks.name_placeholder')} + placeholder={suggestedName || t('widgets.quicklinks.name_placeholder')} />
setIconType(value)} items={[ - { value: 'auto', text: variables.getMessage('widgets.quicklinks.icon_type_auto') }, - { value: 'custom_url', text: variables.getMessage('widgets.quicklinks.icon_type_custom_url') }, - { value: 'custom_upload', text: variables.getMessage('widgets.quicklinks.icon_type_upload') }, - { value: 'emoji', text: variables.getMessage('widgets.quicklinks.icon_type_emoji') }, - { value: 'letter', text: variables.getMessage('widgets.quicklinks.icon_type_letter') }, + { value: 'auto', text: t('widgets.quicklinks.icon_type_auto') }, + { value: 'custom_url', text: t('widgets.quicklinks.icon_type_custom_url') }, + { value: 'custom_upload', text: t('widgets.quicklinks.icon_type_upload') }, + { value: 'emoji', text: t('widgets.quicklinks.icon_type_emoji') }, + { value: 'letter', text: t('widgets.quicklinks.icon_type_letter') }, ]} />
@@ -177,7 +174,7 @@ function AddModal({ urlError, iconError, addLink, closeModal, edit, editData, ed name="quicklink_modal_icon_url" noSetting={true} onChange={(value) => setIcon(value)} - placeholder={variables.getMessage('widgets.quicklinks.icon_url_placeholder')} + placeholder={t('widgets.quicklinks.icon_url_placeholder')} />
)} @@ -192,7 +189,7 @@ function AddModal({ urlError, iconError, addLink, closeModal, edit, editData, ed {iconPreview && ( {variables.getMessage('common.alt_text.preview')} )} @@ -224,9 +221,7 @@ function AddModal({ urlError, iconError, addLink, closeModal, edit, editData, ed onClick={handleSubmit} icon={} label={ - edit - ? variables.getMessage('modals.main.settings.sections.quicklinks.edit') - : variables.getMessage('widgets.quicklinks.add') + edit ? t('modals.main.settings.sections.quicklinks.edit') : t('widgets.quicklinks.add') } />
diff --git a/src/components/Elements/MainModal/Main.jsx b/src/components/Elements/MainModal/Main.jsx index f0c3a0a5..93b5da2d 100644 --- a/src/components/Elements/MainModal/Main.jsx +++ b/src/components/Elements/MainModal/Main.jsx @@ -1,5 +1,5 @@ import { Suspense, lazy, useState, memo, useEffect } from 'react'; -import variables from 'config/variables'; +import { useT } from 'contexts'; import './scss/index.scss'; import ModalLoader from './components/ModalLoader'; @@ -18,6 +18,7 @@ const TAB_COMPONENTS = { }; function MainModal({ modalClose, deepLinkData }) { + const t = useT(); const initialTab = deepLinkData?.tab || TAB_TYPES.SETTINGS; const [currentTab, setCurrentTab] = useState(initialTab); const [currentSection, setCurrentSection] = useState(''); @@ -141,11 +142,11 @@ function MainModal({ modalClose, deepLinkData }) { setCurrentSubSection(null); if (currentTab === TAB_TYPES.DISCOVER) { const sectionMap = { - [variables.getMessage('modals.main.marketplace.all')]: 'all', - [variables.getMessage('modals.main.marketplace.photo_packs')]: 'photo_packs', - [variables.getMessage('modals.main.marketplace.quote_packs')]: 'quote_packs', - [variables.getMessage('modals.main.marketplace.preset_settings')]: 'preset_settings', - [variables.getMessage('modals.main.marketplace.collections')]: 'collections', + [t('modals.main.marketplace.all')]: 'all', + [t('modals.main.marketplace.photo_packs')]: 'photo_packs', + [t('modals.main.marketplace.quote_packs')]: 'quote_packs', + [t('modals.main.marketplace.preset_settings')]: 'preset_settings', + [t('modals.main.marketplace.collections')]: 'collections', }; const sectionKey = sectionMap[section]; if (sectionKey) { diff --git a/src/components/Elements/MainModal/components/ModalLoader.jsx b/src/components/Elements/MainModal/components/ModalLoader.jsx index 7241ff03..a01ea51e 100644 --- a/src/components/Elements/MainModal/components/ModalLoader.jsx +++ b/src/components/Elements/MainModal/components/ModalLoader.jsx @@ -1,4 +1,4 @@ -import variables from 'config/variables'; +import { useT } from 'contexts'; import SidebarSkeleton from './SidebarSkeleton'; const ModalLoader = ({ currentTab }) => ( @@ -11,7 +11,7 @@ const ModalLoader = ({ currentTab }) => (
- {variables.getMessage('modals.main.loading')} + {t('modals.main.loading')}
diff --git a/src/components/Elements/MainModal/components/ModalTopBar.jsx b/src/components/Elements/MainModal/components/ModalTopBar.jsx index f24c3910..e281a90e 100644 --- a/src/components/Elements/MainModal/components/ModalTopBar.jsx +++ b/src/components/Elements/MainModal/components/ModalTopBar.jsx @@ -131,8 +131,7 @@ function ModalTopBar({ if (typeParam) { updateHash(`#discover/${typeParam}`); } - } - else if (href.includes('/collections')) { + } else if (href.includes('/collections')) { updateHash('#discover/collections'); } else if (href.includes('/collection/')) { const collectionId = href.split('/collection/')[1]?.split('?')[0]; @@ -143,8 +142,7 @@ function ModalTopBar({ updateHash(`#discover/${categoryKey}`); } else if (href === '/marketplace' || href === '/marketplace/') { updateHash('#discover/all'); - } - else { + } else { const stepsBack = relevantCrumbs.length - index - 1; for (let i = 0; i < stepsBack; i++) { window.history.back(); diff --git a/src/components/Elements/MainModal/components/ReminderInfo.jsx b/src/components/Elements/MainModal/components/ReminderInfo.jsx index f652173b..0d210804 100644 --- a/src/components/Elements/MainModal/components/ReminderInfo.jsx +++ b/src/components/Elements/MainModal/components/ReminderInfo.jsx @@ -1,7 +1,8 @@ -import variables from 'config/variables'; +import { useT } from 'contexts'; import { MdRefresh, MdClose } from 'react-icons/md'; const ReminderInfo = ({ isVisible, onHide }) => { + const t = useT(); if (!isVisible) { return null; } @@ -9,17 +10,15 @@ const ReminderInfo = ({ isVisible, onHide }) => { return (
- {variables.getMessage('modals.main.settings.reminder.title')} + {t('modals.main.settings.reminder.title')}
- - {variables.getMessage('modals.main.settings.reminder.message')} - + {t('modals.main.settings.reminder.message')}
); diff --git a/src/components/Elements/MainModal/constants/tabConfig.js b/src/components/Elements/MainModal/constants/tabConfig.js index 547cbc2a..6ca36c83 100644 --- a/src/components/Elements/MainModal/constants/tabConfig.js +++ b/src/components/Elements/MainModal/constants/tabConfig.js @@ -1,3 +1,4 @@ +import variables from 'config/variables'; import { MdTune, MdBookmarks, diff --git a/src/components/Elements/ResetModal/ResetModal.jsx b/src/components/Elements/ResetModal/ResetModal.jsx index bdeeb816..56005698 100644 --- a/src/components/Elements/ResetModal/ResetModal.jsx +++ b/src/components/Elements/ResetModal/ResetModal.jsx @@ -1,10 +1,12 @@ import { memo } from 'react'; +import { useT } from 'contexts'; import variables from 'config/variables'; import { MdClose, MdRestartAlt } from 'react-icons/md'; import { setDefaultSettings } from 'utils/settings'; import { Tooltip, Button } from 'components/Elements'; function ResetModal({ modalClose }) { + const t = useT(); const reset = () => { variables.stats.postEvent('setting', 'Reset'); setDefaultSettings('reset'); @@ -15,34 +17,32 @@ function ResetModal({ modalClose }) {
- {variables.getMessage('modals.main.settings.sections.advanced.reset_modal.title')} + {t('modals.main.settings.sections.advanced.reset_modal.title')} - +
- {variables.getMessage('modals.main.settings.sections.advanced.reset_modal.question')} + {t('modals.main.settings.sections.advanced.reset_modal.question')} - {variables.getMessage('modals.main.settings.sections.advanced.reset_modal.information')} + {t('modals.main.settings.sections.advanced.reset_modal.information')}
diff --git a/src/components/Elements/ShareModal/ShareModal.jsx b/src/components/Elements/ShareModal/ShareModal.jsx index 94f270ce..e2c2fdb7 100644 --- a/src/components/Elements/ShareModal/ShareModal.jsx +++ b/src/components/Elements/ShareModal/ShareModal.jsx @@ -1,5 +1,5 @@ import { memo } from 'react'; -import variables from 'config/variables'; +import { useT } from 'contexts'; import { MdClose, MdEmail, MdContentCopy } from 'react-icons/md'; import { FaFacebookF } from 'react-icons/fa'; import { AiFillWechat } from 'react-icons/ai'; @@ -12,37 +12,34 @@ import { Button } from 'components/Elements'; import './sharemodal.scss'; function ShareModal({ modalClose, data }) { + const t = useT(); if (data.startsWith('https://cdn.')) { data = { url: data, - name: variables.getMessage('modals.share.item_type.image'), + name: t('modals.share.item_type.image'), }; } else if (data.startsWith('"')) { data = { url: data, - name: variables.getMessage('modals.share.item_type.quote'), + name: t('modals.share.item_type.quote'), }; } else { data = { url: data, - name: variables.getMessage('modals.share.item_type.marketplace_item'), + name: t('modals.share.item_type.marketplace_item'), }; } const copyLink = () => { navigator.clipboard.writeText(data.url); - toast( - data.startsWith('"') - ? variables.getMessage('toasts.quote') - : variables.getMessage('toasts.link_copied'), - ); + toast(data.startsWith('"') ? t('toasts.quote') : t('toasts.link_copied')); }; return (
- {variables.getMessage('widgets.quote.share')} - + {t('widgets.quote.share')} +
@@ -53,13 +50,13 @@ function ShareModal({ modalClose, data }) { onClick={() => window .open( - `https://x.com/intent/tweet?text=${variables.getMessage('modals.share.twitter_message', { name: data.name })}: ${data.url}`, + `https://x.com/intent/tweet?text=${t('modals.share.twitter_message', { name: data.name })}: ${data.url}`, '_blank', ) .focus() } icon={} - tooltipTitle={variables.getMessage('modals.share.social.twitter')} + tooltipTitle={t('modals.share.social.twitter')} type="icon" />
@@ -114,7 +111,7 @@ function ShareModal({ modalClose, data }) {
diff --git a/src/components/Form/Settings/Dropdown/Dropdown.jsx b/src/components/Form/Settings/Dropdown/Dropdown.jsx index 73fc0028..7ef3dead 100644 --- a/src/components/Form/Settings/Dropdown/Dropdown.jsx +++ b/src/components/Form/Settings/Dropdown/Dropdown.jsx @@ -1,3 +1,4 @@ +import { useT } from 'contexts'; import variables from 'config/variables'; import { memo, useState, useCallback, useRef, useEffect, useMemo } from 'react'; import { createPortal } from 'react-dom'; @@ -33,6 +34,7 @@ const Dropdown = memo((props) => { useEffect(() => { const handleClickOutside = (event) => { + const t = useT(); if ( containerRef.current && !containerRef.current.contains(event.target) && @@ -155,7 +157,7 @@ const Dropdown = memo((props) => { const onChange = useCallback( (newValue) => { - if (newValue === variables.getMessage('modals.main.loading')) { + if (newValue === t('modals.main.loading')) { return; } @@ -238,7 +240,7 @@ const Dropdown = memo((props) => { e?.stopPropagation(); const defaultValue = props.default || props.items[0]?.value; onChange(defaultValue); - toast(variables.getMessage('toasts.reset')); + toast(t('toasts.reset')); }, [onChange, props.default, props.items], ); @@ -281,7 +283,7 @@ const Dropdown = memo((props) => { - {variables.getMessage('modals.main.settings.buttons.reset')} + {t('modals.main.settings.buttons.reset')} )} @@ -369,7 +371,7 @@ const Dropdown = memo((props) => { {item.value === defaultValue && ( {' '} - ({variables.getMessage('modals.main.settings.buttons.default')}) + ({t('modals.main.settings.buttons.default')}) )} diff --git a/src/components/Form/Settings/FileUpload/FileUpload.jsx b/src/components/Form/Settings/FileUpload/FileUpload.jsx index 11571285..e9f54dbc 100644 --- a/src/components/Form/Settings/FileUpload/FileUpload.jsx +++ b/src/components/Form/Settings/FileUpload/FileUpload.jsx @@ -1,4 +1,4 @@ -import variables from 'config/variables'; +import { useT } from 'contexts'; import { memo, useEffect } from 'react'; import { toast } from 'react-toastify'; import { compressAccurately, filetoDataURL } from 'image-conversion'; @@ -12,6 +12,7 @@ const FileUpload = memo(({ id, type, accept, loadFunction, multiple }) => { } const handleChange = (e) => { + const t = useT(); const files = Array.from(e.target.files); if (type === 'settings') { @@ -36,7 +37,7 @@ const FileUpload = memo(({ id, type, accept, loadFunction, multiple }) => { files.forEach((file, index) => { if (videoCheck(file.type) === true) { if (settingsSize + file.size > 4850000) { - return toast(variables.getMessage('toasts.no_storage')); + return toast(t('toasts.no_storage')); } return loadFunction(file, index); @@ -47,7 +48,7 @@ const FileUpload = memo(({ id, type, accept, loadFunction, multiple }) => { accuracy: 0.9, }).then(async (res) => { if (settingsSize + res.size > 4850000) { - return toast(variables.getMessage('toasts.no_storage')); + return toast(t('toasts.no_storage')); } loadFunction( diff --git a/src/components/Form/Settings/LocationSearch/LocationSearch.jsx b/src/components/Form/Settings/LocationSearch/LocationSearch.jsx index 080eb2dd..2b27160a 100644 --- a/src/components/Form/Settings/LocationSearch/LocationSearch.jsx +++ b/src/components/Form/Settings/LocationSearch/LocationSearch.jsx @@ -1,3 +1,4 @@ +import { useT } from 'contexts'; import variables from 'config/variables'; import { memo, useState, useCallback, useRef, useEffect, useMemo } from 'react'; import { createPortal } from 'react-dom'; @@ -51,6 +52,7 @@ const LocationSearch = memo((props) => { useEffect(() => { const handleClickOutside = (event) => { + const t = useT(); if ( containerRef.current && !containerRef.current.contains(event.target) && @@ -219,7 +221,7 @@ const LocationSearch = memo((props) => { ); const handleAutoLocation = useCallback(() => { - setSearchQuery(variables.getMessage('modals.main.loading')); + setSearchQuery(t('modals.main.loading')); setSuggestions([]); navigator.geolocation.getCurrentPosition( @@ -334,7 +336,7 @@ const LocationSearch = memo((props) => { - {variables.getMessage('modals.main.settings.sections.weather.auto')} + {t('modals.main.settings.sections.weather.auto')} )} @@ -408,12 +410,10 @@ const LocationSearch = memo((props) => { )) ) : searchQuery.length >= 2 && !loading ? ( -
- {variables.getMessage('widgets.weather.not_found')} -
+
{t('widgets.weather.not_found')}
) : searchQuery.length < 2 && searchQuery.length > 0 ? (
- {variables.getMessage('modals.main.settings.sections.weather.location')}... + {t('modals.main.settings.sections.weather.location')}...
) : null} , diff --git a/src/components/Form/Settings/Slider/Slider.jsx b/src/components/Form/Settings/Slider/Slider.jsx index 32a89474..cc21be78 100644 --- a/src/components/Form/Settings/Slider/Slider.jsx +++ b/src/components/Form/Settings/Slider/Slider.jsx @@ -1,4 +1,4 @@ -import variables from 'config/variables'; +import { useT } from 'contexts'; import { memo, useState, useCallback, useRef } from 'react'; import { toast } from 'react-toastify'; import { MdRefresh } from 'react-icons/md'; @@ -53,6 +53,7 @@ const SliderComponent = memo((props) => { const startTime = performance.now(); const animate = (currentTime) => { + const t = useT(); const elapsed = currentTime - startTime; const progress = Math.min(elapsed / duration, 1); @@ -75,7 +76,7 @@ const SliderComponent = memo((props) => { }; animationRef.current = requestAnimationFrame(animate); - toast(variables.getMessage('toasts.reset')); + toast(t('toasts.reset')); }, [value, props]); const handleMouseMove = useCallback( @@ -111,7 +112,7 @@ const SliderComponent = memo((props) => { {Number(value)} - {variables.getMessage('modals.main.settings.buttons.reset')} + {t('modals.main.settings.buttons.reset')}
diff --git a/src/components/Form/Settings/Text/Text.jsx b/src/components/Form/Settings/Text/Text.jsx index 86113c2a..08b38984 100644 --- a/src/components/Form/Settings/Text/Text.jsx +++ b/src/components/Form/Settings/Text/Text.jsx @@ -1,4 +1,4 @@ -import variables from 'config/variables'; +import { useT } from 'contexts'; import { memo, useState, useCallback } from 'react'; import { toast } from 'react-toastify'; import { MdRefresh } from 'react-icons/md'; @@ -8,6 +8,7 @@ import EventBus from 'utils/eventbus'; import './Text.scss'; const Text = memo((props) => { + const t = useT(); const { name, upperCaseFirst, @@ -55,7 +56,7 @@ const Text = memo((props) => { value: defaultValue || '', }, }); - toast(variables.getMessage('toasts.reset')); + toast(t('toasts.reset')); }, [handleChange, defaultValue]); return ( @@ -67,7 +68,7 @@ const Text = memo((props) => { - {variables.getMessage('modals.main.settings.buttons.reset')} + {t('modals.main.settings.buttons.reset')}
)} @@ -86,7 +87,7 @@ const Text = memo((props) => { - {variables.getMessage('modals.main.settings.buttons.reset')} + {t('modals.main.settings.buttons.reset')} )} diff --git a/src/components/Layout/Settings/Header/Header.jsx b/src/components/Layout/Settings/Header/Header.jsx index bad40688..f0805176 100644 --- a/src/components/Layout/Settings/Header/Header.jsx +++ b/src/components/Layout/Settings/Header/Header.jsx @@ -1,3 +1,4 @@ +import { useT } from 'contexts'; import variables from 'config/variables'; import { useState, useEffect } from 'react'; import { @@ -14,6 +15,7 @@ export const CustomActions = ({ children }) => { }; function Header(props) { + const t = useT(); const [setting, setSetting] = useState(localStorage.getItem(props.setting) === 'true'); useEffect(() => { @@ -62,7 +64,7 @@ function Header(props) { window.open(variables.constants.BUG_REPORT + props.title.split(' ').join('+'), '_blank') } icon={} - label={variables.getMessage('modals.main.settings.sections.header.report_issue')} + label={t('modals.main.settings.sections.header.report_issue')} /> ); }; diff --git a/src/components/Layout/Settings/PreferencesWrapper/PreferencesWrapper.jsx b/src/components/Layout/Settings/PreferencesWrapper/PreferencesWrapper.jsx index 1b0bfa21..cb2e5af7 100644 --- a/src/components/Layout/Settings/PreferencesWrapper/PreferencesWrapper.jsx +++ b/src/components/Layout/Settings/PreferencesWrapper/PreferencesWrapper.jsx @@ -1,12 +1,13 @@ import React, { useState } from 'react'; import { Row, Content, Action } from 'components/Layout/Settings/Item'; -import variables from 'config/variables'; +import { useT } from 'contexts'; import Slider from '../../../Form/Settings/Slider/Slider'; import values from 'utils/data/slider_values.json'; import EventBus from 'utils/eventbus'; const PreferencesWrapper = ({ children, ...props }) => { + const t = useT(); const [shown, setShown] = useState(localStorage.getItem(props.setting) === 'true'); EventBus.on('toggle', (setting) => { @@ -20,10 +21,8 @@ const PreferencesWrapper = ({ children, ...props }) => { {props.zoomSetting && ( refreshInterval || - cached.photos.length < 3; + !cached || Date.now() - cached.last_fetched > refreshInterval || cached.photos.length < 3; if (needsRefresh) { refreshAPIPackCache(packId).catch((error) => { diff --git a/src/features/background/components/BackgroundImage.jsx b/src/features/background/components/BackgroundImage.jsx index 71a52fc0..9484c4e4 100644 --- a/src/features/background/components/BackgroundImage.jsx +++ b/src/features/background/components/BackgroundImage.jsx @@ -1,6 +1,6 @@ import { memo, useState, useEffect } from 'react'; +import { useT } from 'contexts'; import PhotoInformation from './PhotoInformation'; -import variables from 'config/variables'; import { updateHash } from 'utils/deepLinking'; import EventBus from 'utils/eventbus'; import { getAllBackgrounds } from 'utils/customBackgroundDB'; @@ -9,6 +9,7 @@ import { getAllBackgrounds } from 'utils/customBackgroundDB'; * BackgroundImage component for rendering image backgrounds */ function BackgroundImage({ photoInfo, currentAPI, url }) { + const t = useT(); const isCustomType = localStorage.getItem('backgroundType') === 'custom'; const [customBackgrounds, setCustomBackgrounds] = useState([]); const [loading, setLoading] = useState(true); @@ -55,10 +56,10 @@ function BackgroundImage({ photoInfo, currentAPI, url }) { }} >

- {variables.getMessage('widgets.background.no_images_title') || 'No Custom Images'} + {t('widgets.background.no_images_title') || 'No Custom Images'}

- {variables.getMessage('widgets.background.no_images_description') || + {t('widgets.background.no_images_description') || 'Please add custom images in the Background settings'}

)} diff --git a/src/features/background/components/ExcludeModal.jsx b/src/features/background/components/ExcludeModal.jsx index f7a921db..8f7dc728 100644 --- a/src/features/background/components/ExcludeModal.jsx +++ b/src/features/background/components/ExcludeModal.jsx @@ -1,4 +1,4 @@ -import variables from 'config/variables'; +import { useT } from 'contexts'; import { memo } from 'react'; import EventBus from 'utils/eventbus'; import { Tooltip, Button } from 'components/Elements'; @@ -6,6 +6,7 @@ import { Tooltip, Button } from 'components/Elements'; import { MdClose, MdDone } from 'react-icons/md'; function ExcludeModal({ modalClose, info }) { + const t = useT(); const excludeImage = async () => { let backgroundExclude = JSON.parse(localStorage.getItem('backgroundExclude')); backgroundExclude.push(info.pun); @@ -19,31 +20,29 @@ function ExcludeModal({ modalClose, info }) {
- {variables.getMessage('modals.main.settings.sections.advanced.reset_modal.title')} + {t('modals.main.settings.sections.advanced.reset_modal.title')} - +
- {variables.getMessage('widgets.background.exclude_confirm', { category: info.category })} + {t('widgets.background.exclude_confirm', { category: info.category })}
diff --git a/src/features/background/components/Favourite.jsx b/src/features/background/components/Favourite.jsx index f8c43d95..4566d553 100644 --- a/src/features/background/components/Favourite.jsx +++ b/src/features/background/components/Favourite.jsx @@ -1,8 +1,10 @@ import variables from 'config/variables'; +import { useT } from 'contexts'; import { memo, useState, useCallback, useEffect, useRef } from 'react'; import { MdStar, MdStarBorder } from 'react-icons/md'; const Favourite = memo(({ tooltipText, credit, offline, pun }) => { + const t = useT(); const getInitialButton = () => { return localStorage.getItem('favourite') ? 'favourited' : 'unfavourited'; }; @@ -14,7 +16,7 @@ const Favourite = memo(({ tooltipText, credit, offline, pun }) => { if (localStorage.getItem('favourite')) { localStorage.removeItem('favourite'); setFavourited('unfavourited'); - tooltipText(variables.getMessage('widgets.quote.favourite')); + tooltipText(t('widgets.quote.favourite')); variables.stats.postEvent('feature', 'Background favourite'); } else { const type = localStorage.getItem('backgroundType'); @@ -78,7 +80,7 @@ const Favourite = memo(({ tooltipText, credit, offline, pun }) => { } setFavourited('favourited'); - tooltipText(variables.getMessage('widgets.quote.unfavourite')); + tooltipText(t('widgets.quote.unfavourite')); variables.stats.postEvent('feature', 'Background unfavourite'); } }, [tooltipText, credit, offline, pun]); @@ -87,8 +89,8 @@ const Favourite = memo(({ tooltipText, credit, offline, pun }) => { if (tooltipText) { tooltipText( localStorage.getItem('favourite') - ? variables.getMessage('widgets.quote.unfavourite') - : variables.getMessage('widgets.quote.favourite'), + ? t('widgets.quote.unfavourite') + : t('widgets.quote.favourite'), ); } }, [tooltipText]); diff --git a/src/features/background/components/PhotoInformation.jsx b/src/features/background/components/PhotoInformation.jsx index 96e2721c..896642a9 100644 --- a/src/features/background/components/PhotoInformation.jsx +++ b/src/features/background/components/PhotoInformation.jsx @@ -134,7 +134,12 @@ function PhotoInformation({ info, url, api }) { target="_blank" rel="noopener noreferrer" > - {t('common.alt_text.location')} + {t('common.alt_text.location')} ); }; @@ -250,11 +255,9 @@ function PhotoInformation({ info, url, api }) { try { setPhotoMap(true); setMapIcon(false); - } catch { - } + } catch {} }; - } catch { - } + } catch {} const widgetStyle = localStorage.getItem('widgetStyle'); diff --git a/src/features/background/hooks/useBackgroundEvents.js b/src/features/background/hooks/useBackgroundEvents.js index 00508fd4..4c34981f 100644 --- a/src/features/background/hooks/useBackgroundEvents.js +++ b/src/features/background/hooks/useBackgroundEvents.js @@ -16,12 +16,16 @@ export function useBackgroundEvents(backgroundData, refreshBackground) { if (!isEnabled) { element?.style.setProperty('display', 'none'); - if (!backgroundData.photoInfo?.hidden) {photoInfo?.style.setProperty('display', 'none');} + if (!backgroundData.photoInfo?.hidden) { + photoInfo?.style.setProperty('display', 'none'); + } return; } element?.style.setProperty('display', 'block'); - if (!backgroundData.photoInfo?.hidden) {photoInfo?.style.setProperty('display', 'flex');} + if (!backgroundData.photoInfo?.hidden) { + photoInfo?.style.setProperty('display', 'flex'); + } const type = localStorage.getItem('backgroundType'); const needsRefresh = @@ -35,14 +39,18 @@ export function useBackgroundEvents(backgroundData, refreshBackground) { backgroundData.photoInfo.pun, )); - if (needsRefresh) {refreshBackground();} + if (needsRefresh) { + refreshBackground(); + } }; const applyFilters = () => { if (backgroundData.video) { const filter = getBackgroundFilterStyle(); const element = document.getElementById('backgroundVideo'); - if (element) {element.style.webkitFilter = filter;} + if (element) { + element.style.webkitFilter = filter; + } } else { const overlayElement = document.getElementById('backgroundFilterOverlay'); if (overlayElement) { diff --git a/src/features/background/hooks/useBackgroundLoader.js b/src/features/background/hooks/useBackgroundLoader.js index ea6bf126..eba327de 100644 --- a/src/features/background/hooks/useBackgroundLoader.js +++ b/src/features/background/hooks/useBackgroundLoader.js @@ -9,7 +9,9 @@ export function useBackgroundLoader(updateBackground, resetBackground) { const isLoadingRef = useRef(false); const loadBackground = useCallback(async () => { - if (isLoadingRef.current) {return;} + if (isLoadingRef.current) { + return; + } isLoadingRef.current = true; try { diff --git a/src/features/background/hooks/useBackgroundRenderer.js b/src/features/background/hooks/useBackgroundRenderer.js index 796ab17e..1914e0da 100644 --- a/src/features/background/hooks/useBackgroundRenderer.js +++ b/src/features/background/hooks/useBackgroundRenderer.js @@ -13,10 +13,14 @@ export function useBackgroundRenderer(backgroundData) { const abortControllerRef = useRef(null); useEffect(() => { - if (backgroundData.video) {return;} + if (backgroundData.video) { + return; + } const element = document.getElementById('backgroundImage'); - if (!element) {return;} + if (!element) { + return; + } if (abortControllerRef.current) { abortControllerRef.current.abort(); diff --git a/src/features/background/options/BackgroundOptions.jsx b/src/features/background/options/BackgroundOptions.jsx index ec6b2469..281af5a9 100644 --- a/src/features/background/options/BackgroundOptions.jsx +++ b/src/features/background/options/BackgroundOptions.jsx @@ -1,4 +1,5 @@ import variables from 'config/variables'; +import { useT } from 'contexts'; import { memo, useState, useEffect, useCallback, useRef } from 'react'; import { MdSource, MdOutlineAutoAwesome } from 'react-icons/md'; import { toast } from 'react-toastify'; @@ -21,6 +22,7 @@ import NavigationCard from './sections/NavigationCard'; import { getBackgroundOptionItems } from './optionTypes'; const BackgroundOptions = memo(({ currentSubSection, onSubSectionChange, sectionName }) => { + const t = useT(); const [backgroundType, setBackgroundType] = useState( localStorage.getItem('backgroundType') || 'api', ); @@ -29,9 +31,9 @@ const BackgroundOptions = memo(({ currentSubSection, onSubSectionChange, section ); const [backgroundCategories, setBackgroundCategories] = useState(() => { if (navigator.onLine === false || localStorage.getItem('offlineMode') === 'true') { - return [variables.getMessage('modals.update.offline.title')]; + return [t('modals.update.offline.title')]; } - return [variables.getMessage('modals.main.loading')]; + return [t('modals.main.loading')]; }); const [backgroundCategoriesOG, setBackgroundCategoriesOG] = useState([]); const [backgroundAPI, setBackgroundAPI] = useState( @@ -134,7 +136,7 @@ const BackgroundOptions = memo(({ currentSubSection, onSubSectionChange, section const handlePhotoPackUninstall = (type, name) => { uninstall(type, name); - toast(variables.getMessage('toasts.uninstalled')); + toast(t('toasts.uninstalled')); variables.stats.postEvent('marketplace-item', `${name} uninstalled`); setInstalledPhotoPacks(getInstalledPhotoPacks()); window.dispatchEvent(new window.Event('installedAddonsChanged')); @@ -204,10 +206,8 @@ const BackgroundOptions = memo(({ currentSubSection, onSubSectionChange, section if (currentSubSection === 'effects') { return (
onSubSectionChange(null, sectionName)} /> ); @@ -216,10 +216,8 @@ const BackgroundOptions = memo(({ currentSubSection, onSubSectionChange, section if (currentSubSection === 'source') { return (
onSubSectionChange(null, sectionName)} /> ); @@ -227,7 +225,7 @@ const BackgroundOptions = memo(({ currentSubSection, onSubSectionChange, section return (
onSubSectionChange('source', sectionName)} action={ { clearQueuesOnSettingChange('backgroundType'); @@ -268,10 +264,8 @@ const BackgroundOptions = memo(({ currentSubSection, onSubSectionChange, section {showEffects && ( onSubSectionChange('effects', sectionName)} /> )} diff --git a/src/features/background/options/Colour.jsx b/src/features/background/options/Colour.jsx index a48a200f..6bbbb373 100644 --- a/src/features/background/options/Colour.jsx +++ b/src/features/background/options/Colour.jsx @@ -1,4 +1,4 @@ -import variables from 'config/variables'; +import { useT } from 'contexts'; import { useState } from 'react'; import ColorPicker from 'react-best-gradient-color-picker'; import { toast } from 'react-toastify'; @@ -9,6 +9,7 @@ import EventBus from 'utils/eventbus'; import '../scss/_colourpicker.scss'; const ColourOptions = () => { + const t = useT(); const [colour, setColour] = useState( localStorage.getItem('customBackgroundColour') || 'rgba(0, 0, 0, 100)', ); @@ -22,17 +23,13 @@ const ColourOptions = () => { const resetColour = () => { setColour('rgba(0, 0, 0, 0)'); localStorage.setItem('customBackgroundColour', 'rgba(0, 0, 0, 100)'); - toast(variables.getMessage('toasts.reset')); + toast(t('toasts.reset')); EventBus.emit('refresh', 'background'); }; return ( - + {
resetColour()}> - {variables.getMessage('modals.main.settings.buttons.reset')} + {t('modals.main.settings.buttons.reset')}
diff --git a/src/features/background/options/Custom.jsx b/src/features/background/options/Custom.jsx index 329bf028..ff4bbab2 100644 --- a/src/features/background/options/Custom.jsx +++ b/src/features/background/options/Custom.jsx @@ -1,4 +1,5 @@ import variables from 'config/variables'; +import { useT } from 'contexts'; import { memo, useRef, useState, useEffect, useCallback } from 'react'; import { toast } from 'react-toastify'; import { @@ -46,6 +47,7 @@ import CustomURLModal from './CustomURLModal'; import FolderTaggingModal from './FolderTaggingModal'; const CustomSettings = memo(() => { + const t = useT(); const [customBackground, setCustomBackground] = useState([]); const [customURLModal, setCustomURLModal] = useState(false); const [folderTaggingModal, setFolderTaggingModal] = useState(false); @@ -107,7 +109,7 @@ const CustomSettings = memo(() => { }); } catch (error) { console.error('Error loading backgrounds:', error); - toast(variables.getMessage('toasts.error')); + toast(t('toasts.error')); } finally { setLoading(false); } @@ -147,7 +149,7 @@ const CustomSettings = memo(() => { } } catch (error) { console.error('Error saving background:', error); - toast(variables.getMessage('toasts.error')); + toast(t('toasts.error')); } }, [], @@ -258,7 +260,7 @@ const CustomSettings = memo(() => { setUploadProgress({ current: i + 1, total: files.length }); } catch (error) { if (error.message === 'no_storage') { - toast(variables.getMessage('toasts.no_storage')); + toast(t('toasts.no_storage')); break; } errors.push(files[i].name); @@ -266,7 +268,7 @@ const CustomSettings = memo(() => { } if (errors.length > 0) { - toast(variables.getMessage('toasts.error') + `: ${errors.join(', ')}`); + toast(t('toasts.error') + `: ${errors.join(', ')}`); } EventBus.emit('refresh', 'background'); @@ -302,7 +304,7 @@ const CustomSettings = memo(() => { EventBus.emit('refresh', 'background'); } catch (error) { console.error('Error modifying background:', error); - toast(variables.getMessage('toasts.error')); + toast(t('toasts.error')); } }, []); @@ -326,10 +328,10 @@ const CustomSettings = memo(() => { } EventBus.emit('refresh', 'background'); - toast(variables.getMessage('toasts.deleted')); + toast(t('toasts.deleted')); } catch (error) { console.error('Error batch deleting:', error); - toast(variables.getMessage('toasts.error')); + toast(t('toasts.error')); } }; @@ -358,7 +360,7 @@ const CustomSettings = memo(() => { const urlRegex = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._~#=]{1,256}\.[a-zA-Z0-9()]{1,63}\b([-a-zA-Z0-9()!@:%_.~#?&=]*)/; if (urlRegex.test(e) === false) { - return setUrlError(variables.getMessage('widgets.quicklinks.url_error')); + return setUrlError(t('widgets.quicklinks.url_error')); } setCustomURLModal(false); @@ -391,14 +393,11 @@ const CustomSettings = memo(() => { setCustomBackground(backgrounds); } catch (error) { console.error('Error adding URL:', error); - toast(variables.getMessage('toasts.error')); + toast(t('toasts.error')); } try { - localStorage.setItem( - 'customBackground', - JSON.stringify(backgrounds.map((bg) => bg.url)), - ); + localStorage.setItem('customBackground', JSON.stringify(backgrounds.map((bg) => bg.url))); } catch (_quotaError) { localStorage.setItem('customBackgroundCount', backgrounds.length.toString()); } @@ -518,7 +517,7 @@ const CustomSettings = memo(() => {
- {variables.getMessage('modals.main.loading')} + {t('modals.main.loading')}
); @@ -530,7 +529,7 @@ const CustomSettings = memo(() => {
- {variables.getMessage('modals.main.settings.sections.background.source.uploading', { + {t('modals.main.settings.sections.background.source.uploading', { current: uploadProgress.current, total: uploadProgress.total, })} @@ -564,14 +563,10 @@ const CustomSettings = memo(() => {
- {variables.getMessage( - 'modals.main.settings.sections.background.source.custom_title', - )} + {t('modals.main.settings.sections.background.source.custom_title')} - {variables.getMessage( - 'modals.main.settings.sections.background.source.custom_description', - )} + {t('modals.main.settings.sections.background.source.custom_description')}
@@ -580,7 +575,7 @@ const CustomSettings = memo(() => { type="settings" onClick={uploadCustomBackground} icon={} - label={variables.getMessage('modals.main.settings.sections.background.source.upload')} + label={t('modals.main.settings.sections.background.source.upload')} /> @@ -593,7 +588,11 @@ const CustomSettings = memo(() => { {' '} · {formatBytes(storageUsed)} / {formatBytes(availableStorageLimit)} {storagePercent > 80 && navigator.storage && navigator.storage.persist && ( - + + {t('modals.main.settings.reminder.title')} + {t('modals.welcome.preview.description')} + ); } diff --git a/src/features/marketplace/components/Elements/Lightbox/Lightbox.jsx b/src/features/marketplace/components/Elements/Lightbox/Lightbox.jsx index 110a8a49..297b15a1 100644 --- a/src/features/marketplace/components/Elements/Lightbox/Lightbox.jsx +++ b/src/features/marketplace/components/Elements/Lightbox/Lightbox.jsx @@ -1,8 +1,10 @@ import { memo } from 'react'; +import { useT } from 'contexts'; import variables from 'config/variables'; import { getProxiedImageUrl } from 'utils/marketplace'; function Lightbox({ modalClose, img }) { + const t = useT(); variables.stats.postEvent('modal', 'Opened lightbox'); return ( @@ -14,7 +16,7 @@ function Lightbox({ modalClose, img }) { src={getProxiedImageUrl(img)} className="lightboximg" draggable={false} - alt={variables.getMessage('common.alt_text.screenshot')} + alt={t('common.alt_text.screenshot')} /> ); diff --git a/src/features/marketplace/components/Elements/SideloadFailedModal/SideloadFailedModal.jsx b/src/features/marketplace/components/Elements/SideloadFailedModal/SideloadFailedModal.jsx index c6e0de37..8057ebb8 100644 --- a/src/features/marketplace/components/Elements/SideloadFailedModal/SideloadFailedModal.jsx +++ b/src/features/marketplace/components/Elements/SideloadFailedModal/SideloadFailedModal.jsx @@ -1,22 +1,21 @@ import { memo } from 'react'; -import variables from 'config/variables'; +import { useT } from 'contexts'; import { MdClose } from 'react-icons/md'; import { Tooltip } from 'components/Elements'; function SideloadFailedModal({ modalClose, reason }) { + const t = useT(); return (
- {variables.getMessage('modals.main.error_boundary.title')} - + {t('modals.main.error_boundary.title')} +
- {variables.getMessage('modals.main.addons.sideload.failed')} + {t('modals.main.addons.sideload.failed')} {reason}
); diff --git a/src/features/marketplace/components/Items/Items.jsx b/src/features/marketplace/components/Items/Items.jsx index 33a34b8d..c6dd6570 100644 --- a/src/features/marketplace/components/Items/Items.jsx +++ b/src/features/marketplace/components/Items/Items.jsx @@ -1,4 +1,4 @@ -import variables from 'config/variables'; +import { useT } from 'contexts'; import React, { memo, useState, useMemo } from 'react'; import { MdCheckCircle, MdOutlineUploadFile, MdClose, MdSettings } from 'react-icons/md'; import placeholderIcon from 'assets/icons/marketplace-placeholder.png'; @@ -12,6 +12,7 @@ import { getProxiedImageUrl } from 'utils/marketplace'; import ItemSettingsModal from '../Modals/ItemSettingsModal'; function filterItems(item, filter, categoryFilter) { + const t = useT(); const lowerCaseFilter = filter.toLowerCase(); const textMatch = item.name?.toLowerCase().includes(lowerCaseFilter) || @@ -140,9 +141,7 @@ function ItemCard({ width: '52px', height: '32px', borderRadius: '16px', - backgroundColor: enabled - ? 'var(--linkColor, #ff5c25)' - : 'rgba(128, 128, 128, 0.3)', + backgroundColor: enabled ? 'var(--linkColor, #ff5c25)' : 'rgba(128, 128, 128, 0.3)', position: 'relative', transition: 'background-color 0.2s', cursor: 'pointer', @@ -168,7 +167,7 @@ function ItemCard({ )} {isSideloaded && (
@@ -201,7 +200,7 @@ function ItemCard({ {item.display_name || item.name} {!isCurator ? ( - {variables.getMessage('modals.main.marketplace.by', { author: item.author })} + {t('modals.main.marketplace.by', { author: item.author })} ) : ( '' @@ -211,9 +210,7 @@ function ItemCard({
{item.type && ( - {variables.getMessage( - 'modals.main.marketplace.' + getTypeTranslationKey(item.type), - )} + {t('modals.main.marketplace.' + getTypeTranslationKey(item.type))} )} {item.in_collections && item.in_collections.length > 0 && !onCollection && !isAdded && ( @@ -316,12 +313,12 @@ function Items({ ))}
handleSortChange(value)} items={[ - { value: 'a-z', text: variables.getMessage('modals.main.addons.sort.a_z') }, - { value: 'z-a', text: variables.getMessage('modals.main.addons.sort.z_a') }, + { value: 'a-z', text: t('modals.main.addons.sort.a_z') }, + { value: 'z-a', text: t('modals.main.addons.sort.z_a') }, ]} />
diff --git a/src/features/marketplace/components/Modals/ItemSettingsModal.jsx b/src/features/marketplace/components/Modals/ItemSettingsModal.jsx index 73a080e4..12d99f98 100644 --- a/src/features/marketplace/components/Modals/ItemSettingsModal.jsx +++ b/src/features/marketplace/components/Modals/ItemSettingsModal.jsx @@ -1,5 +1,6 @@ import { useState, useEffect, useCallback } from 'react'; import Modal from 'react-modal'; +import { useT } from 'contexts'; import variables from 'config/variables'; import EventBus from 'utils/eventbus'; import { Dropdown, Switch, Slider, ChipSelect } from 'components/Form/Settings'; @@ -146,9 +147,7 @@ const ItemSettingsModal = ({ pack, isOpen, onClose, isEnabled }) => { placeholder={field.placeholder || ''} className="itemSettings-field-input" /> - {field.help_text && ( -

{field.help_text}

- )} + {field.help_text &&

{field.help_text}

} ); @@ -222,7 +221,11 @@ const ItemSettingsModal = ({ pack, isOpen, onClose, isEnabled }) => { - @@ -250,7 +253,7 @@ const ItemSettingsModal = ({ pack, isOpen, onClose, isEnabled }) => {
@@ -263,27 +261,30 @@ const Added = memo(() => { }} > sortAddons(value)} items={[ - { value: 'newest', text: variables.getMessage('modals.main.addons.sort.newest') }, - { value: 'a-z', text: variables.getMessage('modals.main.addons.sort.a_z') }, - { value: 'recently-updated', text: variables.getMessage('modals.main.marketplace.addons.recently_updated') }, + { value: 'newest', text: t('modals.main.addons.sort.newest') }, + { value: 'a-z', text: t('modals.main.addons.sort.a_z') }, + { + value: 'recently-updated', + text: t('modals.main.marketplace.addons.recently_updated'), + }, ]} />
diff --git a/src/features/message/options/MessageOptions.jsx b/src/features/message/options/MessageOptions.jsx index fbad7f00..417348ea 100644 --- a/src/features/message/options/MessageOptions.jsx +++ b/src/features/message/options/MessageOptions.jsx @@ -1,4 +1,4 @@ -import variables from 'config/variables'; +import { useT } from 'contexts'; import { useState } from 'react'; import { MdCancel, MdAdd, MdOutlineTextsms } from 'react-icons/md'; import { toast } from 'react-toastify'; @@ -9,12 +9,13 @@ import { Button } from 'components/Elements'; import EventBus from 'utils/eventbus'; const MessageOptions = () => { + const t = useT(); const [messages, setMessages] = useState(JSON.parse(localStorage.getItem('messages')) || []); const reset = () => { localStorage.setItem('messages', '[]'); setMessages([]); - toast(variables.getMessage('toasts.reset')); + toast(t('toasts.reset')); EventBus.emit('refresh', 'message'); }; @@ -47,7 +48,7 @@ const MessageOptions = () => { return ( <>
{ zoomSetting="zoomMessage" > - +
- - {variables.getMessage(`${MESSAGE_SECTION}.title`)} - + {t(`${MESSAGE_SECTION}.title`)}