feat(translation): integrate useT hook for improved translation handling across components

This commit is contained in:
alexsparkes
2026-01-24 18:07:25 +00:00
parent 30aa53fdd7
commit 6ca19fc48d
10 changed files with 268 additions and 279 deletions

View File

@@ -7,15 +7,17 @@ const TranslationContext = createContext();
export function TranslationProvider({ children, initialLanguage }) { export function TranslationProvider({ children, initialLanguage }) {
const [currentLanguage, setCurrentLanguage] = useState(initialLanguage); const [currentLanguage, setCurrentLanguage] = useState(initialLanguage);
const i18nInstance = useRef(null); const i18nInstance = useRef(initTranslations(initialLanguage));
// Initialize i18n instance once // Update i18n instance when language changes
useEffect(() => { useEffect(() => {
i18nInstance.current = initTranslations(currentLanguage); if (currentLanguage !== initialLanguage) {
i18nInstance.current = initTranslations(currentLanguage);
}
variables.language = i18nInstance.current; variables.language = i18nInstance.current;
variables.languagecode = currentLanguage; variables.languagecode = currentLanguage;
document.documentElement.lang = currentLanguage.replace('_', '-'); document.documentElement.lang = currentLanguage.replace('_', '-');
}, [currentLanguage]); }, [currentLanguage, initialLanguage]);
// Change language function // Change language function
const changeLanguage = useCallback((newLanguage) => { const changeLanguage = useCallback((newLanguage) => {

View File

@@ -1,5 +1,6 @@
import variables from 'config/variables'; import variables from 'config/variables';
import { useState, useEffect, useRef } from 'react'; import { useState, useEffect, useRef } from 'react';
import { useT } from 'contexts';
import { MdSettings } from 'react-icons/md'; import { MdSettings } from 'react-icons/md';
@@ -10,34 +11,36 @@ import EventBus from 'utils/eventbus';
import './scss/index.scss'; import './scss/index.scss';
const getRefreshText = () => {
switch (localStorage.getItem('refreshOption')) {
case 'background':
return variables.getMessage('modals.main.settings.sections.background.title');
case 'quote':
return variables.getMessage('modals.main.settings.sections.quote.title');
case 'quotebackground':
return (
variables.getMessage('modals.main.settings.sections.quote.title') +
' ' +
variables.getMessage('modals.main.settings.sections.background.title')
);
default:
return variables.getMessage(
'modals.main.settings.sections.appearance.navbar.refresh_options.page',
);
}
};
const getZoomFontSize = () => {
return Number(((localStorage.getItem('zoomNavbar') || 100) / 100) * 1.2) + 'rem';
};
const Navbar = ({ openModal }) => { const Navbar = ({ openModal }) => {
const t = useT();
const navbarContainer = useRef(); const navbarContainer = useRef();
const [classList] = useState( const [classList] = useState(
localStorage.getItem('widgetStyle') === 'legacy' ? 'navbar old' : 'navbar new', localStorage.getItem('widgetStyle') === 'legacy' ? 'navbar old' : 'navbar new',
); );
const getRefreshText = () => {
switch (localStorage.getItem('refreshOption')) {
case 'background':
return t('modals.main.settings.sections.background.title');
case 'quote':
return t('modals.main.settings.sections.quote.title');
case 'quotebackground':
return (
t('modals.main.settings.sections.quote.title') +
' ' +
t('modals.main.settings.sections.background.title')
);
default:
return t(
'modals.main.settings.sections.appearance.navbar.refresh_options.page',
);
}
};
const getZoomFontSize = () => {
return Number(((localStorage.getItem('zoomNavbar') || 100) / 100) * 1.2) + 'rem';
};
const [refreshText, setRefreshText] = useState(getRefreshText()); const [refreshText, setRefreshText] = useState(getRefreshText());
const [refreshEnabled, setRefreshEnabled] = useState(localStorage.getItem('refresh')); const [refreshEnabled, setRefreshEnabled] = useState(localStorage.getItem('refresh'));
const [refreshOption, setRefreshOption] = useState(localStorage.getItem('refreshOption') || ''); const [refreshOption, setRefreshOption] = useState(localStorage.getItem('refreshOption') || '');
@@ -99,16 +102,16 @@ const Navbar = ({ openModal }) => {
{refreshEnabled !== 'false' && <Refresh fontSize={zoomFontSize} />} {refreshEnabled !== 'false' && <Refresh fontSize={zoomFontSize} />}
<Tooltip <Tooltip
title={variables.getMessage('modals.main.navbar.settings', { title={t('modals.main.navbar.settings', {
type: variables.getMessage('modals.main.navbar.tooltips.refresh_' + refreshOption), type: t('modals.main.navbar.tooltips.refresh_' + refreshOption),
})} })}
> >
<button <button
className="navbarButton" className="navbarButton"
onClick={() => openModal('mainModal')} onClick={() => openModal('mainModal')}
style={{ fontSize: zoomFontSize }} style={{ fontSize: zoomFontSize }}
aria-label={variables.getMessage('modals.main.navbar.settings', { aria-label={t('modals.main.navbar.settings', {
type: variables.getMessage('modals.main.navbar.tooltips.refresh_' + refreshOption), type: t('modals.main.navbar.tooltips.refresh_' + refreshOption),
})} })}
> >
<MdSettings className="settings-icon topicons" /> <MdSettings className="settings-icon topicons" />

View File

@@ -1,5 +1,6 @@
import variables from 'config/variables'; import variables from 'config/variables';
import { memo, useState, useEffect } from 'react'; import { memo, useState, useEffect } from 'react';
import { useT } from 'contexts';
import { MdContentCopy, MdAssignment, MdPushPin, MdDownload } from 'react-icons/md'; import { MdContentCopy, MdAssignment, MdPushPin, MdDownload } from 'react-icons/md';
import { useFloating, shift } from '@floating-ui/react-dom'; import { useFloating, shift } from '@floating-ui/react-dom';
@@ -11,6 +12,7 @@ import { saveFile } from 'utils/saveFile';
import EventBus from 'utils/eventbus'; import EventBus from 'utils/eventbus';
const Notes = ({ notesRef, floatRef, position, xPosition, yPosition }) => { const Notes = ({ notesRef, floatRef, position, xPosition, yPosition }) => {
const t = useT();
const [notes, setNotes] = useState(localStorage.getItem('notes') || ''); const [notes, setNotes] = useState(localStorage.getItem('notes') || '');
const [showNotes, setShowNotes] = useState(localStorage.getItem('notesPinned') === 'true'); const [showNotes, setShowNotes] = useState(localStorage.getItem('notesPinned') === 'true');
const [zoomFontSize, setZoomFontSize] = useState('1.2rem'); const [zoomFontSize, setZoomFontSize] = useState('1.2rem');
@@ -53,7 +55,7 @@ const Notes = ({ notesRef, floatRef, position, xPosition, yPosition }) => {
const handleCopy = () => { const handleCopy = () => {
variables.stats.postEvent('feature', 'Notes copied'); variables.stats.postEvent('feature', 'Notes copied');
navigator.clipboard.writeText(notes); navigator.clipboard.writeText(notes);
toast(variables.getMessage('toasts.notes')); toast(t('toasts.notes'));
}; };
const handleDownload = () => { const handleDownload = () => {
@@ -74,7 +76,7 @@ const Notes = ({ notesRef, floatRef, position, xPosition, yPosition }) => {
onBlur={handleHideNotes} onBlur={handleHideNotes}
ref={notesRef} ref={notesRef}
style={{ fontSize: zoomFontSize }} style={{ fontSize: zoomFontSize }}
aria-label={variables.getMessage('widgets.navbar.notes.title')} aria-label={t('widgets.navbar.notes.title')}
> >
<MdAssignment className="topicons" /> <MdAssignment className="topicons" />
</button> </button>
@@ -91,27 +93,27 @@ const Notes = ({ notesRef, floatRef, position, xPosition, yPosition }) => {
<div className="flexNotes"> <div className="flexNotes">
<div className="topBarNotes" style={{ display: 'flex' }}> <div className="topBarNotes" style={{ display: 'flex' }}>
<MdAssignment /> <MdAssignment />
<span>{variables.getMessage('widgets.navbar.notes.title')}</span> <span>{t('widgets.navbar.notes.title')}</span>
</div> </div>
<div className="notes-buttons"> <div className="notes-buttons">
<Tooltip title={variables.getMessage('widgets.navbar.todo.pin')}> <Tooltip title={t('widgets.navbar.todo.pin')}>
<button onClick={handlePin}> <button onClick={handlePin}>
<MdPushPin /> <MdPushPin />
</button> </button>
</Tooltip> </Tooltip>
<Tooltip title={variables.getMessage('widgets.quote.copy')}> <Tooltip title={t('widgets.quote.copy')}>
<button onClick={handleCopy} disabled={notes === ''}> <button onClick={handleCopy} disabled={notes === ''}>
<MdContentCopy /> <MdContentCopy />
</button> </button>
</Tooltip> </Tooltip>
<Tooltip title={variables.getMessage('widgets.background.download')}> <Tooltip title={t('widgets.background.download')}>
<button onClick={handleDownload} disabled={notes === ''}> <button onClick={handleDownload} disabled={notes === ''}>
<MdDownload /> <MdDownload />
</button> </button>
</Tooltip> </Tooltip>
</div> </div>
<TextareaAutosize <TextareaAutosize
placeholder={variables.getMessage('widgets.navbar.notes.placeholder')} placeholder={t('widgets.navbar.notes.placeholder')}
value={notes} value={notes}
onChange={handleSetNotes} onChange={handleSetNotes}
minRows={5} minRows={5}

View File

@@ -70,11 +70,11 @@ function Refresh() {
} }
return ( return (
<Tooltip title={variables.getMessage('widgets.navbar.tooltips.refresh')} subtitle={refreshText}> <Tooltip title={t('widgets.navbar.tooltips.refresh')} subtitle={refreshText}>
<button <button
className="navbarButton" className="navbarButton"
onClick={refresh} onClick={refresh}
aria-label={variables.getMessage('widgets.navbar.tooltips.refresh')} aria-label={t('widgets.navbar.tooltips.refresh')}
> >
<MdRefresh className="refreshicon topicons" /> <MdRefresh className="refreshicon topicons" />
</button> </button>

View File

@@ -1,5 +1,6 @@
import variables from 'config/variables'; import variables from 'config/variables';
import { PureComponent, memo, useState } from 'react'; import { memo, useState, useEffect } from 'react';
import { useT } from 'contexts';
import { import {
MdChecklist, MdChecklist,
@@ -65,206 +66,180 @@ const SortableList = ({ items, onDragEnd, children }) => {
); );
}; };
class Todo extends PureComponent { function Todo({ todoRef, floatRef, position, xPosition, yPosition }) {
constructor() { const t = useT();
super(); const [todo, setTodo] = useState(JSON.parse(localStorage.getItem('todo')) || []);
this.state = { const [showTodo, setShowTodo] = useState(localStorage.getItem('todoPinned') === 'true');
todo: JSON.parse(localStorage.getItem('todo')) || [], const [zoomFontSize, setZoomFontSize] = useState('1.2rem');
visibility: localStorage.getItem('todoPinned') === 'true' ? 'visible' : 'hidden',
marginLeft: localStorage.getItem('refresh') === 'false' ? '-200px' : '-130px',
showTodo: localStorage.getItem('todoPinned') === 'true',
};
}
setZoom() { useEffect(() => {
this.setState({ const handleRefresh = (data) => {
zoomFontSize: Number(((localStorage.getItem('zoomNavbar') || 100) / 100) * 1.2) + 'rem',
});
}
componentDidMount() {
EventBus.on('refresh', (data) => {
if (data === 'navbar') { if (data === 'navbar') {
this.forceUpdate(); setZoomFontSize(Number(((localStorage.getItem('zoomNavbar') || 100) / 100) * 1.2) + 'rem');
try {
this.setZoom();
} catch {
// Ignore errors
}
} }
}); };
this.setZoom(); setZoomFontSize(Number(((localStorage.getItem('zoomNavbar') || 100) / 100) * 1.2) + 'rem');
}
componentWillUnmount() { EventBus.on('refresh', handleRefresh);
EventBus.off('refresh'); return () => {
} EventBus.off('refresh', handleRefresh);
};
}, []);
/** const handleShowTodo = () => {
* It takes an array, removes an item from it, and then inserts it at a new index. setShowTodo(true);
* @param {Array} array The array to move the item in. };
* @param {Number} oldIndex The index of the item to move.
* @param {Number} newIndex The index to move the item to.
* @returns The result of the splice method.
*/
arrayMove(array, oldIndex, newIndex) {
const result = Array.from(array);
const [removed] = result.splice(oldIndex, 1);
result.splice(newIndex, 0, removed);
return result; const handleHideTodo = () => {
} setShowTodo(localStorage.getItem('todoPinned') === 'true');
};
handleDragEnd = (event) => { const handleDragEnd = (event) => {
const { active, over } = event; const { active, over } = event;
if (over && active.id !== over.id) { if (over && active.id !== over.id) {
const oldIndex = Number(active.id); const oldIndex = Number(active.id);
const newIndex = Number(over.id); const newIndex = Number(over.id);
this.setState({ todo: arrayMove(this.state.todo, oldIndex, newIndex) }); setTodo((currentTodo) => {
const newTodo = arrayMove(currentTodo, oldIndex, newIndex);
localStorage.setItem('todo', JSON.stringify(newTodo));
return newTodo;
});
} }
}; };
showTodo() {
this.setState({ showTodo: true });
}
hideTodo() {
this.setState({ showTodo: localStorage.getItem('todoPinned') === 'true' });
}
/** /**
* This function takes in an action, an index, and data, and then updates the todo list accordingly. * This function takes in an action, an index, and data, and then updates the todo list accordingly.
* @param {String} action The action to perform. Can be 'add', 'remove', 'set', or 'done'. * @param {String} action The action to perform. Can be 'add', 'remove', 'set', or 'done'.
* @param {Number} index The index of the item to perform the action on. * @param {Number} index The index of the item to perform the action on.
* @param {Object} data The data to use for the action. * @param {Object} data The data to use for the action.
*/ */
updateTodo(action, index, data) { const updateTodo = (action, index, data) => {
const todo = this.state.todo; setTodo((currentTodo) => {
switch (action) { const newTodo = [...currentTodo];
case 'add':
todo.push({ value: '', done: false });
break;
case 'remove':
todo.splice(index, 1);
break;
case 'set':
todo[index] = { value: data.target.value, done: todo[index].done };
break;
case 'done':
todo[index].done = !todo[index].done;
break;
default:
break;
}
localStorage.setItem('todo', JSON.stringify(todo)); switch (action) {
this.setState({ todo }); case 'add':
this.forceUpdate(); newTodo.push({ value: '', done: false });
} break;
case 'remove':
newTodo.splice(index, 1);
break;
case 'set':
newTodo[index] = { value: data.target.value, done: newTodo[index].done };
break;
case 'done':
newTodo[index].done = !newTodo[index].done;
break;
default:
break;
}
pin() { localStorage.setItem('todo', JSON.stringify(newTodo));
return newTodo;
});
};
const handlePin = () => {
variables.stats.postEvent('feature', 'Todo pin'); variables.stats.postEvent('feature', 'Todo pin');
const todoPinned = localStorage.getItem('todoPinned') === 'true'; const todoPinned = localStorage.getItem('todoPinned') === 'true';
localStorage.setItem('todoPinned', !todoPinned); localStorage.setItem('todoPinned', !todoPinned);
this.setState({ showTodo: !todoPinned }); setShowTodo(!todoPinned);
} };
render() { return (
return ( <div className="notes" onMouseLeave={handleHideTodo} onFocus={handleShowTodo}>
<div className="notes" onMouseLeave={() => this.hideTodo()} onFocus={() => this.showTodo()}> <button
<button className="navbarButton"
className="navbarButton" onMouseEnter={handleShowTodo}
onMouseEnter={() => this.showTodo()} onFocus={handleHideTodo}
onFocus={() => this.hideTodo()} onBlur={handleShowTodo}
onBlur={() => this.showTodo()} ref={todoRef}
ref={this.props.todoRef} style={{ fontSize: zoomFontSize }}
style={{ fontSize: this.state.zoomFontSize }} >
<MdChecklist className="topicons" />
</button>
{showTodo && (
<span
className="notesContainer"
ref={floatRef}
style={{
position: position,
top: yPosition ?? '44px',
left: xPosition ?? '',
}}
> >
<MdChecklist className="topicons" /> <div className="flexTodo">
</button> <div className="topBarNotes" style={{ display: 'flex' }}>
{this.state.showTodo && ( <MdChecklist />
<span <span>{t('widgets.navbar.todo.title')}</span>
className="notesContainer"
ref={this.props.floatRef}
style={{
position: this.props.position,
top: this.props.yPosition ?? '44px',
left: this.props.xPosition ?? '',
}}
>
<div className="flexTodo">
<div className="topBarNotes" style={{ display: 'flex' }}>
<MdChecklist />
<span>{variables.getMessage('widgets.navbar.todo.title')}</span>
</div>
<div className="notes-buttons">
<Tooltip title={variables.getMessage('widgets.navbar.todo.pin')}>
<button onClick={() => this.pin()}>
<MdPushPin />
</button>
</Tooltip>
<Tooltip title={variables.getMessage('widgets.navbar.todo.add')}>
<button onClick={() => this.updateTodo('add')}>
<MdPlaylistAdd />
</button>
</Tooltip>
</div>
<div className={'todoRows'}>
{this.state.todo.length === 0 ? (
<div className="todosEmpty">
<div className="emptyNewMessage">
<MdPlaylistRemove />
<span className="title">
{variables.getMessage('widgets.navbar.todo.no_todos')}
</span>
<span className="subtitle">
{variables.getMessage('modals.main.settings.sections.message.add_some')}
</span>
</div>
</div>
) : (
<SortableList
items={this.state.todo.map((_, index) => index)}
onDragEnd={this.handleDragEnd}
>
{this.state.todo.map((todo, index) => (
<SortableItem key={index} id={index}>
{({ attributes, listeners }) => (
<div className={'todoRow' + (todo.done ? ' done' : '')}>
<Checkbox
checked={todo.done}
onClick={() => this.updateTodo('done', index)}
/>
<TextareaAutosize
placeholder={variables.getMessage('widgets.navbar.notes.placeholder')}
value={todo.value}
onChange={(data) => this.updateTodo('set', index, data)}
readOnly={todo.done}
/>
<Tooltip
title={variables.getMessage(
'modals.main.marketplace.product.buttons.remove',
)}
>
<MdDelete onClick={() => this.updateTodo('remove', index)} />
</Tooltip>
<DragHandle {...attributes} {...listeners} />
</div>
)}
</SortableItem>
))}
</SortableList>
)}
</div>
</div> </div>
</span> <div className="notes-buttons">
)} <Tooltip title={t('widgets.navbar.todo.pin')}>
</div> <button onClick={handlePin}>
); <MdPushPin />
} </button>
</Tooltip>
<Tooltip title={t('widgets.navbar.todo.add')}>
<button onClick={() => updateTodo('add')}>
<MdPlaylistAdd />
</button>
</Tooltip>
</div>
<div className={'todoRows'}>
{todo.length === 0 ? (
<div className="todosEmpty">
<div className="emptyNewMessage">
<MdPlaylistRemove />
<span className="title">
{t('widgets.navbar.todo.no_todos')}
</span>
<span className="subtitle">
{t('modals.main.settings.sections.message.add_some')}
</span>
</div>
</div>
) : (
<SortableList
items={todo.map((_, index) => index)}
onDragEnd={handleDragEnd}
>
{todo.map((todoItem, index) => (
<SortableItem key={index} id={index}>
{({ attributes, listeners }) => (
<div className={'todoRow' + (todoItem.done ? ' done' : '')}>
<Checkbox
checked={todoItem.done}
onClick={() => updateTodo('done', index)}
/>
<TextareaAutosize
placeholder={t('widgets.navbar.notes.placeholder')}
value={todoItem.value}
onChange={(data) => updateTodo('set', index, data)}
readOnly={todoItem.done}
/>
<Tooltip
title={t(
'modals.main.marketplace.product.buttons.remove',
)}
>
<MdDelete onClick={() => updateTodo('remove', index)} />
</Tooltip>
<DragHandle {...attributes} {...listeners} />
</div>
)}
</SortableItem>
))}
</SortableList>
)}
</div>
</div>
</span>
)}
</div>
);
} }
function TodoWrapper() { function TodoWrapper() {

View File

@@ -1,6 +1,7 @@
import variables from 'config/variables'; import variables from 'config/variables';
import { useState } from 'react'; import { useState } from 'react';
import { useT } from 'contexts';
import Modal from 'react-modal'; import Modal from 'react-modal';
import EventBus from 'utils/eventbus'; import EventBus from 'utils/eventbus';
@@ -15,6 +16,7 @@ import { getTitleFromUrl, isValidUrl } from 'utils/links';
import { QuickLink } from 'features/quicklinks/options/QuickLink'; import { QuickLink } from 'features/quicklinks/options/QuickLink';
function AppsOptions({ appsEnabled }) { function AppsOptions({ appsEnabled }) {
const t = useT();
const [appsModalInfo, setAppsModalInfo] = useState({ const [appsModalInfo, setAppsModalInfo] = useState({
newLink: false, newLink: false,
edit: false, edit: false,
@@ -34,14 +36,14 @@ function AppsOptions({ appsEnabled }) {
if (url.length <= 0 || isValidUrl(url) === false) { if (url.length <= 0 || isValidUrl(url) === false) {
return setAppsModalInfo((oldState) => ({ return setAppsModalInfo((oldState) => ({
...oldState, ...oldState,
urlError: variables.getMessage('widgets.quicklinks.url_error'), urlError: t('widgets.quicklinks.url_error'),
})); }));
} }
if (icon.length > 0 && isValidUrl(icon) === false) { if (icon.length > 0 && isValidUrl(icon) === false) {
return setAppsModalInfo((oldState) => ({ return setAppsModalInfo((oldState) => ({
...oldState, ...oldState,
iconError: variables.getMessage('widgets.quicklinks.icon_error'), iconError: t('widgets.quicklinks.icon_error'),
})); }));
} }
@@ -114,8 +116,8 @@ function AppsOptions({ appsEnabled }) {
<> <>
<Row final={true} inactive={!appsEnabled}> <Row final={true} inactive={!appsEnabled}>
<Content <Content
title={variables.getMessage('widgets.navbar.apps.title')} title={t('widgets.navbar.apps.title')}
subtitle={variables.getMessage( subtitle={t(
'modals.main.settings.sections.appearance.navbar.apps_subtitle', 'modals.main.settings.sections.appearance.navbar.apps_subtitle',
)} )}
/> />
@@ -124,7 +126,7 @@ function AppsOptions({ appsEnabled }) {
type="settings" type="settings"
onClick={() => setAppsModalInfo((oldState) => ({ ...oldState, newLink: true }))} onClick={() => setAppsModalInfo((oldState) => ({ ...oldState, newLink: true }))}
icon={<MdAddLink />} icon={<MdAddLink />}
label={variables.getMessage('modals.main.settings.sections.quicklinks.add_link')} label={t('modals.main.settings.sections.quicklinks.add_link')}
/> />
</Action> </Action>
</Row> </Row>

View File

@@ -1,6 +1,7 @@
import variables from 'config/variables'; import variables from 'config/variables';
import { useState, memo } from 'react'; import { useState, memo } from 'react';
import { useT } from 'contexts';
import { MdAssignment, MdCropFree, MdRefresh, MdChecklist, MdOutlineApps } from 'react-icons/md'; import { MdAssignment, MdCropFree, MdRefresh, MdChecklist, MdOutlineApps } from 'react-icons/md';
@@ -13,6 +14,7 @@ import { Header } from 'components/Layout/Settings';
import AppsOptions from './AppsOptions'; import AppsOptions from './AppsOptions';
function NavbarOptions() { function NavbarOptions() {
const t = useT();
const [showRefreshOptions, setShowRefreshOptions] = useState( const [showRefreshOptions, setShowRefreshOptions] = useState(
localStorage.getItem('refresh') === 'true', localStorage.getItem('refresh') === 'true',
); );
@@ -26,15 +28,15 @@ function NavbarOptions() {
return ( return (
<Row final={false}> <Row final={false}>
<Content <Content
title={variables.getMessage('modals.main.settings.additional_settings')} title={t('modals.main.settings.additional_settings')}
subtitle={variables.getMessage( subtitle={t(
'modals.main.settings.sections.appearance.navbar.additional', 'modals.main.settings.sections.appearance.navbar.additional',
)} )}
/> />
<Action> <Action>
<Checkbox <Checkbox
name="navbarHover" name="navbarHover"
text={variables.getMessage(`${NAVBAR_SECTION}.hover`)} text={t(`${NAVBAR_SECTION}.hover`)}
category="navbar" category="navbar"
/> />
</Action> </Action>
@@ -70,7 +72,7 @@ function NavbarOptions() {
className={`navbarButtonOption ${isDisabled === true ? 'disabled' : ''}`} className={`navbarButtonOption ${isDisabled === true ? 'disabled' : ''}`}
> >
{icon} {icon}
<span className="subtitle">{variables.getMessage(messageKey)}</span> <span className="subtitle">{t(messageKey)}</span>
</button> </button>
); );
}; };
@@ -106,7 +108,7 @@ function NavbarOptions() {
return ( return (
<Row> <Row>
<Content <Content
title={variables.getMessage('modals.main.settings.sections.appearance.navbar.widgets')} title={t('modals.main.settings.sections.appearance.navbar.widgets')}
/> />
<Action> <Action>
<div className="navbarButtonOptions"> <div className="navbarButtonOptions">
@@ -123,8 +125,8 @@ function NavbarOptions() {
return ( return (
<Row final={false} inactive={!showRefreshOptions}> <Row final={false} inactive={!showRefreshOptions}>
<Content <Content
title={variables.getMessage(`${NAVBAR_SECTION}.refresh`)} title={t(`${NAVBAR_SECTION}.refresh`)}
subtitle={variables.getMessage( subtitle={t(
'modals.main.settings.sections.appearance.navbar.refresh_subtitle', 'modals.main.settings.sections.appearance.navbar.refresh_subtitle',
)} )}
/> />
@@ -135,24 +137,24 @@ function NavbarOptions() {
items={[ items={[
{ {
value: 'page', value: 'page',
text: variables.getMessage( text: t(
'modals.main.settings.sections.appearance.navbar.refresh_options.page', 'modals.main.settings.sections.appearance.navbar.refresh_options.page',
), ),
}, },
{ {
value: 'background', value: 'background',
text: variables.getMessage('modals.main.settings.sections.background.title'), text: t('modals.main.settings.sections.background.title'),
}, },
{ {
value: 'quote', value: 'quote',
text: variables.getMessage('modals.main.settings.sections.quote.title'), text: t('modals.main.settings.sections.quote.title'),
}, },
{ {
value: 'quotebackground', value: 'quotebackground',
text: text:
variables.getMessage('modals.main.settings.sections.quote.title') + t('modals.main.settings.sections.quote.title') +
' + ' + ' + ' +
variables.getMessage('modals.main.settings.sections.background.title'), t('modals.main.settings.sections.background.title'),
}, },
]} ]}
/> />
@@ -164,7 +166,7 @@ function NavbarOptions() {
return ( return (
<> <>
<Header <Header
title={variables.getMessage(`${NAVBAR_SECTION}.title`)} title={t(`${NAVBAR_SECTION}.title`)}
setting="navbar" setting="navbar"
category="widgets" category="widgets"
zoomSetting="zoomNavbar" zoomSetting="zoomNavbar"

View File

@@ -1,6 +1,6 @@
import { MdPerson, MdOpenInNew } from 'react-icons/md'; import { MdPerson, MdOpenInNew } from 'react-icons/md';
import { Tooltip } from 'components/Elements'; import { Tooltip } from 'components/Elements';
import variables from 'config/variables'; import { useT } from 'contexts';
import QuoteButtons from './QuoteButtons'; import QuoteButtons from './QuoteButtons';
/** /**
@@ -17,6 +17,7 @@ export default function AuthorInfo({
onShare, onShare,
isFavourited, isFavourited,
}) { }) {
const t = useT();
const showAuthorImg = localStorage.getItem('authorImg') !== 'false'; const showAuthorImg = localStorage.getItem('authorImg') !== 'false';
const hasLink = authorOccupation !== 'Unknown' && authorlink !== null; const hasLink = authorOccupation !== 'Unknown' && authorlink !== null;
const trimmedLicense = authorimglicense?.substring(0, 40) + const trimmedLicense = authorimglicense?.substring(0, 40) +
@@ -52,7 +53,7 @@ export default function AuthorInfo({
<div className="quote-buttons"> <div className="quote-buttons">
{hasLink && ( {hasLink && (
<Tooltip title={variables.getMessage('widgets.quote.link_tooltip')}> <Tooltip title={t('widgets.quote.link_tooltip')}>
<a <a
href={authorlink} href={authorlink}
className="quoteAuthorLink" className="quoteAuthorLink"

View File

@@ -1,5 +1,6 @@
import { MdContentCopy, MdStarBorder, MdStar, MdIosShare } from 'react-icons/md'; import { MdContentCopy, MdStarBorder, MdStar, MdIosShare } from 'react-icons/md';
import { Tooltip } from 'components/Elements'; import { Tooltip } from 'components/Elements';
import { useT } from 'contexts';
import variables from 'config/variables'; import variables from 'config/variables';
/** /**
@@ -11,6 +12,7 @@ export default function QuoteButtons({
onShare, onShare,
isFavourited, isFavourited,
}) { }) {
const t = useT();
const showCopy = localStorage.getItem('copyButton') !== 'false'; const showCopy = localStorage.getItem('copyButton') !== 'false';
const showShare = localStorage.getItem('quoteShareButton') !== 'false'; const showShare = localStorage.getItem('quoteShareButton') !== 'false';
const showFavourite = localStorage.getItem('favouriteQuoteEnabled') === 'true'; const showFavourite = localStorage.getItem('favouriteQuoteEnabled') === 'true';
@@ -18,20 +20,20 @@ export default function QuoteButtons({
return ( return (
<> <>
{showCopy && ( {showCopy && (
<Tooltip title={variables.getMessage('widgets.quote.copy')}> <Tooltip title={t('widgets.quote.copy')}>
<button <button
onClick={onCopy} onClick={onCopy}
aria-label={variables.getMessage('widgets.quote.copy')} aria-label={t('widgets.quote.copy')}
> >
<MdContentCopy className="copyButton" /> <MdContentCopy className="copyButton" />
</button> </button>
</Tooltip> </Tooltip>
)} )}
{showShare && ( {showShare && (
<Tooltip title={variables.getMessage('widgets.quote.share')}> <Tooltip title={t('widgets.quote.share')}>
<button <button
onClick={onShare} onClick={onShare}
aria-label={variables.getMessage('widgets.quote.share')} aria-label={t('widgets.quote.share')}
> >
<MdIosShare className="copyButton" /> <MdIosShare className="copyButton" />
</button> </button>
@@ -41,16 +43,16 @@ export default function QuoteButtons({
<Tooltip <Tooltip
title={ title={
isFavourited isFavourited
? variables.getMessage('widgets.quote.unfavourite') ? t('widgets.quote.unfavourite')
: variables.getMessage('widgets.quote.favourite') : t('widgets.quote.favourite')
} }
> >
<button <button
onClick={onFavourite} onClick={onFavourite}
aria-label={ aria-label={
isFavourited isFavourited
? variables.getMessage('widgets.quote.unfavourite') ? t('widgets.quote.unfavourite')
: variables.getMessage('widgets.quote.favourite') : t('widgets.quote.favourite')
} }
> >
{isFavourited ? ( {isFavourited ? (

View File

@@ -1,38 +1,38 @@
import I18n from '@eartharoid/i18n'; import I18n from '@eartharoid/i18n';
import * as ar from 'translations/ar.json'; import ar from 'translations/ar.json';
import * as arz from 'translations/arz.json'; import arz from 'translations/arz.json';
import * as az from 'translations/az.json'; import az from 'translations/az.json';
import * as azb from 'translations/azb.json'; import azb from 'translations/azb.json';
import * as bn from 'translations/bn.json'; import bn from 'translations/bn.json';
import * as de_DE from 'translations/de_DE.json'; import de_DE from 'translations/de_DE.json';
import * as el from 'translations/el.json'; import el from 'translations/el.json';
import * as en_GB from 'translations/en_GB.json'; import en_GB from 'translations/en_GB.json';
import * as en_US from 'translations/en_US.json'; import en_US from 'translations/en_US.json';
import * as es from 'translations/es.json'; import es from 'translations/es.json';
import * as es_419 from 'translations/es_419.json'; import es_419 from 'translations/es_419.json';
import * as et from 'translations/et.json'; import et from 'translations/et.json';
import * as fa from 'translations/fa.json'; import fa from 'translations/fa.json';
import * as fr from 'translations/fr.json'; import fr from 'translations/fr.json';
import * as hu from 'translations/hu.json'; import hu from 'translations/hu.json';
import * as id_ID from 'translations/id_ID.json'; import id_ID from 'translations/id_ID.json';
import * as ja from 'translations/ja.json'; import ja from 'translations/ja.json';
import * as lt from 'translations/lt.json'; import lt from 'translations/lt.json';
import * as lv from 'translations/lv.json'; import lv from 'translations/lv.json';
import * as nl from 'translations/nl.json'; import nl from 'translations/nl.json';
import * as no from 'translations/no.json'; import no from 'translations/no.json';
import * as peo from 'translations/peo.json'; import peo from 'translations/peo.json';
import * as pt from 'translations/pt.json'; import pt from 'translations/pt.json';
import * as pt_BR from 'translations/pt_BR.json'; import pt_BR from 'translations/pt_BR.json';
import * as ru from 'translations/ru.json'; import ru from 'translations/ru.json';
import * as sl from 'translations/sl.json'; import sl from 'translations/sl.json';
import * as sv from 'translations/sv.json'; import sv from 'translations/sv.json';
import * as ta from 'translations/ta.json'; import ta from 'translations/ta.json';
import * as tr_TR from 'translations/tr_TR.json'; import tr_TR from 'translations/tr_TR.json';
import * as uk from 'translations/uk.json'; import uk from 'translations/uk.json';
import * as vi from 'translations/vi.json'; import vi from 'translations/vi.json';
import * as zh_CN from 'translations/zh_CN.json'; import zh_CN from 'translations/zh_CN.json';
import * as zh_Hant from 'translations/zh_Hant.json'; import zh_Hant from 'translations/zh_Hant.json';
/** /**
* Initialise the i18n object. * Initialise the i18n object.