mirror of
https://github.com/mue/mue.git
synced 2026-07-02 12:43:35 +02:00
feat(translation): integrate useT hook for improved translation handling across components
This commit is contained in:
@@ -7,15 +7,17 @@ const TranslationContext = createContext();
|
||||
|
||||
export function TranslationProvider({ children, 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(() => {
|
||||
i18nInstance.current = initTranslations(currentLanguage);
|
||||
if (currentLanguage !== initialLanguage) {
|
||||
i18nInstance.current = initTranslations(currentLanguage);
|
||||
}
|
||||
variables.language = i18nInstance.current;
|
||||
variables.languagecode = currentLanguage;
|
||||
document.documentElement.lang = currentLanguage.replace('_', '-');
|
||||
}, [currentLanguage]);
|
||||
}, [currentLanguage, initialLanguage]);
|
||||
|
||||
// Change language function
|
||||
const changeLanguage = useCallback((newLanguage) => {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import variables from 'config/variables';
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { useT } from 'contexts';
|
||||
|
||||
import { MdSettings } from 'react-icons/md';
|
||||
|
||||
@@ -10,34 +11,36 @@ import EventBus from 'utils/eventbus';
|
||||
|
||||
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 t = useT();
|
||||
const navbarContainer = useRef();
|
||||
const [classList] = useState(
|
||||
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 [refreshEnabled, setRefreshEnabled] = useState(localStorage.getItem('refresh'));
|
||||
const [refreshOption, setRefreshOption] = useState(localStorage.getItem('refreshOption') || '');
|
||||
@@ -99,16 +102,16 @@ const Navbar = ({ openModal }) => {
|
||||
{refreshEnabled !== 'false' && <Refresh fontSize={zoomFontSize} />}
|
||||
|
||||
<Tooltip
|
||||
title={variables.getMessage('modals.main.navbar.settings', {
|
||||
type: variables.getMessage('modals.main.navbar.tooltips.refresh_' + refreshOption),
|
||||
title={t('modals.main.navbar.settings', {
|
||||
type: t('modals.main.navbar.tooltips.refresh_' + refreshOption),
|
||||
})}
|
||||
>
|
||||
<button
|
||||
className="navbarButton"
|
||||
onClick={() => openModal('mainModal')}
|
||||
style={{ fontSize: zoomFontSize }}
|
||||
aria-label={variables.getMessage('modals.main.navbar.settings', {
|
||||
type: variables.getMessage('modals.main.navbar.tooltips.refresh_' + refreshOption),
|
||||
aria-label={t('modals.main.navbar.settings', {
|
||||
type: t('modals.main.navbar.tooltips.refresh_' + refreshOption),
|
||||
})}
|
||||
>
|
||||
<MdSettings className="settings-icon topicons" />
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import variables from 'config/variables';
|
||||
import { memo, useState, useEffect } from 'react';
|
||||
import { useT } from 'contexts';
|
||||
|
||||
import { MdContentCopy, MdAssignment, MdPushPin, MdDownload } from 'react-icons/md';
|
||||
import { useFloating, shift } from '@floating-ui/react-dom';
|
||||
@@ -11,6 +12,7 @@ import { saveFile } from 'utils/saveFile';
|
||||
import EventBus from 'utils/eventbus';
|
||||
|
||||
const Notes = ({ notesRef, floatRef, position, xPosition, yPosition }) => {
|
||||
const t = useT();
|
||||
const [notes, setNotes] = useState(localStorage.getItem('notes') || '');
|
||||
const [showNotes, setShowNotes] = useState(localStorage.getItem('notesPinned') === 'true');
|
||||
const [zoomFontSize, setZoomFontSize] = useState('1.2rem');
|
||||
@@ -53,7 +55,7 @@ const Notes = ({ notesRef, floatRef, position, xPosition, yPosition }) => {
|
||||
const handleCopy = () => {
|
||||
variables.stats.postEvent('feature', 'Notes copied');
|
||||
navigator.clipboard.writeText(notes);
|
||||
toast(variables.getMessage('toasts.notes'));
|
||||
toast(t('toasts.notes'));
|
||||
};
|
||||
|
||||
const handleDownload = () => {
|
||||
@@ -74,7 +76,7 @@ const Notes = ({ notesRef, floatRef, position, xPosition, yPosition }) => {
|
||||
onBlur={handleHideNotes}
|
||||
ref={notesRef}
|
||||
style={{ fontSize: zoomFontSize }}
|
||||
aria-label={variables.getMessage('widgets.navbar.notes.title')}
|
||||
aria-label={t('widgets.navbar.notes.title')}
|
||||
>
|
||||
<MdAssignment className="topicons" />
|
||||
</button>
|
||||
@@ -91,27 +93,27 @@ const Notes = ({ notesRef, floatRef, position, xPosition, yPosition }) => {
|
||||
<div className="flexNotes">
|
||||
<div className="topBarNotes" style={{ display: 'flex' }}>
|
||||
<MdAssignment />
|
||||
<span>{variables.getMessage('widgets.navbar.notes.title')}</span>
|
||||
<span>{t('widgets.navbar.notes.title')}</span>
|
||||
</div>
|
||||
<div className="notes-buttons">
|
||||
<Tooltip title={variables.getMessage('widgets.navbar.todo.pin')}>
|
||||
<Tooltip title={t('widgets.navbar.todo.pin')}>
|
||||
<button onClick={handlePin}>
|
||||
<MdPushPin />
|
||||
</button>
|
||||
</Tooltip>
|
||||
<Tooltip title={variables.getMessage('widgets.quote.copy')}>
|
||||
<Tooltip title={t('widgets.quote.copy')}>
|
||||
<button onClick={handleCopy} disabled={notes === ''}>
|
||||
<MdContentCopy />
|
||||
</button>
|
||||
</Tooltip>
|
||||
<Tooltip title={variables.getMessage('widgets.background.download')}>
|
||||
<Tooltip title={t('widgets.background.download')}>
|
||||
<button onClick={handleDownload} disabled={notes === ''}>
|
||||
<MdDownload />
|
||||
</button>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<TextareaAutosize
|
||||
placeholder={variables.getMessage('widgets.navbar.notes.placeholder')}
|
||||
placeholder={t('widgets.navbar.notes.placeholder')}
|
||||
value={notes}
|
||||
onChange={handleSetNotes}
|
||||
minRows={5}
|
||||
|
||||
@@ -70,11 +70,11 @@ function Refresh() {
|
||||
}
|
||||
|
||||
return (
|
||||
<Tooltip title={variables.getMessage('widgets.navbar.tooltips.refresh')} subtitle={refreshText}>
|
||||
<Tooltip title={t('widgets.navbar.tooltips.refresh')} subtitle={refreshText}>
|
||||
<button
|
||||
className="navbarButton"
|
||||
onClick={refresh}
|
||||
aria-label={variables.getMessage('widgets.navbar.tooltips.refresh')}
|
||||
aria-label={t('widgets.navbar.tooltips.refresh')}
|
||||
>
|
||||
<MdRefresh className="refreshicon topicons" />
|
||||
</button>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import variables from 'config/variables';
|
||||
import { PureComponent, memo, useState } from 'react';
|
||||
import { memo, useState, useEffect } from 'react';
|
||||
import { useT } from 'contexts';
|
||||
|
||||
import {
|
||||
MdChecklist,
|
||||
@@ -65,206 +66,180 @@ const SortableList = ({ items, onDragEnd, children }) => {
|
||||
);
|
||||
};
|
||||
|
||||
class Todo extends PureComponent {
|
||||
constructor() {
|
||||
super();
|
||||
this.state = {
|
||||
todo: JSON.parse(localStorage.getItem('todo')) || [],
|
||||
visibility: localStorage.getItem('todoPinned') === 'true' ? 'visible' : 'hidden',
|
||||
marginLeft: localStorage.getItem('refresh') === 'false' ? '-200px' : '-130px',
|
||||
showTodo: localStorage.getItem('todoPinned') === 'true',
|
||||
};
|
||||
}
|
||||
function Todo({ todoRef, floatRef, position, xPosition, yPosition }) {
|
||||
const t = useT();
|
||||
const [todo, setTodo] = useState(JSON.parse(localStorage.getItem('todo')) || []);
|
||||
const [showTodo, setShowTodo] = useState(localStorage.getItem('todoPinned') === 'true');
|
||||
const [zoomFontSize, setZoomFontSize] = useState('1.2rem');
|
||||
|
||||
setZoom() {
|
||||
this.setState({
|
||||
zoomFontSize: Number(((localStorage.getItem('zoomNavbar') || 100) / 100) * 1.2) + 'rem',
|
||||
});
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
EventBus.on('refresh', (data) => {
|
||||
useEffect(() => {
|
||||
const handleRefresh = (data) => {
|
||||
if (data === 'navbar') {
|
||||
this.forceUpdate();
|
||||
try {
|
||||
this.setZoom();
|
||||
} catch {
|
||||
// Ignore errors
|
||||
}
|
||||
setZoomFontSize(Number(((localStorage.getItem('zoomNavbar') || 100) / 100) * 1.2) + 'rem');
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
this.setZoom();
|
||||
}
|
||||
setZoomFontSize(Number(((localStorage.getItem('zoomNavbar') || 100) / 100) * 1.2) + 'rem');
|
||||
|
||||
componentWillUnmount() {
|
||||
EventBus.off('refresh');
|
||||
}
|
||||
EventBus.on('refresh', handleRefresh);
|
||||
return () => {
|
||||
EventBus.off('refresh', handleRefresh);
|
||||
};
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* It takes an array, removes an item from it, and then inserts it at a new index.
|
||||
* @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);
|
||||
const handleShowTodo = () => {
|
||||
setShowTodo(true);
|
||||
};
|
||||
|
||||
return result;
|
||||
}
|
||||
const handleHideTodo = () => {
|
||||
setShowTodo(localStorage.getItem('todoPinned') === 'true');
|
||||
};
|
||||
|
||||
handleDragEnd = (event) => {
|
||||
const handleDragEnd = (event) => {
|
||||
const { active, over } = event;
|
||||
|
||||
if (over && active.id !== over.id) {
|
||||
const oldIndex = Number(active.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.
|
||||
* @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 {Object} data The data to use for the action.
|
||||
*/
|
||||
updateTodo(action, index, data) {
|
||||
const todo = this.state.todo;
|
||||
switch (action) {
|
||||
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;
|
||||
}
|
||||
const updateTodo = (action, index, data) => {
|
||||
setTodo((currentTodo) => {
|
||||
const newTodo = [...currentTodo];
|
||||
|
||||
localStorage.setItem('todo', JSON.stringify(todo));
|
||||
this.setState({ todo });
|
||||
this.forceUpdate();
|
||||
}
|
||||
switch (action) {
|
||||
case 'add':
|
||||
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');
|
||||
const todoPinned = localStorage.getItem('todoPinned') === 'true';
|
||||
localStorage.setItem('todoPinned', !todoPinned);
|
||||
this.setState({ showTodo: !todoPinned });
|
||||
}
|
||||
setShowTodo(!todoPinned);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="notes" onMouseLeave={() => this.hideTodo()} onFocus={() => this.showTodo()}>
|
||||
<button
|
||||
className="navbarButton"
|
||||
onMouseEnter={() => this.showTodo()}
|
||||
onFocus={() => this.hideTodo()}
|
||||
onBlur={() => this.showTodo()}
|
||||
ref={this.props.todoRef}
|
||||
style={{ fontSize: this.state.zoomFontSize }}
|
||||
return (
|
||||
<div className="notes" onMouseLeave={handleHideTodo} onFocus={handleShowTodo}>
|
||||
<button
|
||||
className="navbarButton"
|
||||
onMouseEnter={handleShowTodo}
|
||||
onFocus={handleHideTodo}
|
||||
onBlur={handleShowTodo}
|
||||
ref={todoRef}
|
||||
style={{ fontSize: zoomFontSize }}
|
||||
>
|
||||
<MdChecklist className="topicons" />
|
||||
</button>
|
||||
{showTodo && (
|
||||
<span
|
||||
className="notesContainer"
|
||||
ref={floatRef}
|
||||
style={{
|
||||
position: position,
|
||||
top: yPosition ?? '44px',
|
||||
left: xPosition ?? '',
|
||||
}}
|
||||
>
|
||||
<MdChecklist className="topicons" />
|
||||
</button>
|
||||
{this.state.showTodo && (
|
||||
<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 className="flexTodo">
|
||||
<div className="topBarNotes" style={{ display: 'flex' }}>
|
||||
<MdChecklist />
|
||||
<span>{t('widgets.navbar.todo.title')}</span>
|
||||
</div>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
<div className="notes-buttons">
|
||||
<Tooltip title={t('widgets.navbar.todo.pin')}>
|
||||
<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() {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import variables from 'config/variables';
|
||||
|
||||
import { useState } from 'react';
|
||||
import { useT } from 'contexts';
|
||||
|
||||
import Modal from 'react-modal';
|
||||
import EventBus from 'utils/eventbus';
|
||||
@@ -15,6 +16,7 @@ import { getTitleFromUrl, isValidUrl } from 'utils/links';
|
||||
import { QuickLink } from 'features/quicklinks/options/QuickLink';
|
||||
|
||||
function AppsOptions({ appsEnabled }) {
|
||||
const t = useT();
|
||||
const [appsModalInfo, setAppsModalInfo] = useState({
|
||||
newLink: false,
|
||||
edit: false,
|
||||
@@ -34,14 +36,14 @@ function AppsOptions({ appsEnabled }) {
|
||||
if (url.length <= 0 || isValidUrl(url) === false) {
|
||||
return setAppsModalInfo((oldState) => ({
|
||||
...oldState,
|
||||
urlError: variables.getMessage('widgets.quicklinks.url_error'),
|
||||
urlError: t('widgets.quicklinks.url_error'),
|
||||
}));
|
||||
}
|
||||
|
||||
if (icon.length > 0 && isValidUrl(icon) === false) {
|
||||
return setAppsModalInfo((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}>
|
||||
<Content
|
||||
title={variables.getMessage('widgets.navbar.apps.title')}
|
||||
subtitle={variables.getMessage(
|
||||
title={t('widgets.navbar.apps.title')}
|
||||
subtitle={t(
|
||||
'modals.main.settings.sections.appearance.navbar.apps_subtitle',
|
||||
)}
|
||||
/>
|
||||
@@ -124,7 +126,7 @@ function AppsOptions({ appsEnabled }) {
|
||||
type="settings"
|
||||
onClick={() => setAppsModalInfo((oldState) => ({ ...oldState, newLink: true }))}
|
||||
icon={<MdAddLink />}
|
||||
label={variables.getMessage('modals.main.settings.sections.quicklinks.add_link')}
|
||||
label={t('modals.main.settings.sections.quicklinks.add_link')}
|
||||
/>
|
||||
</Action>
|
||||
</Row>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import variables from 'config/variables';
|
||||
|
||||
import { useState, memo } from 'react';
|
||||
import { useT } from 'contexts';
|
||||
|
||||
import { MdAssignment, MdCropFree, MdRefresh, MdChecklist, MdOutlineApps } from 'react-icons/md';
|
||||
|
||||
@@ -13,6 +14,7 @@ import { Header } from 'components/Layout/Settings';
|
||||
import AppsOptions from './AppsOptions';
|
||||
|
||||
function NavbarOptions() {
|
||||
const t = useT();
|
||||
const [showRefreshOptions, setShowRefreshOptions] = useState(
|
||||
localStorage.getItem('refresh') === 'true',
|
||||
);
|
||||
@@ -26,15 +28,15 @@ function NavbarOptions() {
|
||||
return (
|
||||
<Row final={false}>
|
||||
<Content
|
||||
title={variables.getMessage('modals.main.settings.additional_settings')}
|
||||
subtitle={variables.getMessage(
|
||||
title={t('modals.main.settings.additional_settings')}
|
||||
subtitle={t(
|
||||
'modals.main.settings.sections.appearance.navbar.additional',
|
||||
)}
|
||||
/>
|
||||
<Action>
|
||||
<Checkbox
|
||||
name="navbarHover"
|
||||
text={variables.getMessage(`${NAVBAR_SECTION}.hover`)}
|
||||
text={t(`${NAVBAR_SECTION}.hover`)}
|
||||
category="navbar"
|
||||
/>
|
||||
</Action>
|
||||
@@ -70,7 +72,7 @@ function NavbarOptions() {
|
||||
className={`navbarButtonOption ${isDisabled === true ? 'disabled' : ''}`}
|
||||
>
|
||||
{icon}
|
||||
<span className="subtitle">{variables.getMessage(messageKey)}</span>
|
||||
<span className="subtitle">{t(messageKey)}</span>
|
||||
</button>
|
||||
);
|
||||
};
|
||||
@@ -106,7 +108,7 @@ function NavbarOptions() {
|
||||
return (
|
||||
<Row>
|
||||
<Content
|
||||
title={variables.getMessage('modals.main.settings.sections.appearance.navbar.widgets')}
|
||||
title={t('modals.main.settings.sections.appearance.navbar.widgets')}
|
||||
/>
|
||||
<Action>
|
||||
<div className="navbarButtonOptions">
|
||||
@@ -123,8 +125,8 @@ function NavbarOptions() {
|
||||
return (
|
||||
<Row final={false} inactive={!showRefreshOptions}>
|
||||
<Content
|
||||
title={variables.getMessage(`${NAVBAR_SECTION}.refresh`)}
|
||||
subtitle={variables.getMessage(
|
||||
title={t(`${NAVBAR_SECTION}.refresh`)}
|
||||
subtitle={t(
|
||||
'modals.main.settings.sections.appearance.navbar.refresh_subtitle',
|
||||
)}
|
||||
/>
|
||||
@@ -135,24 +137,24 @@ function NavbarOptions() {
|
||||
items={[
|
||||
{
|
||||
value: 'page',
|
||||
text: variables.getMessage(
|
||||
text: t(
|
||||
'modals.main.settings.sections.appearance.navbar.refresh_options.page',
|
||||
),
|
||||
},
|
||||
{
|
||||
value: 'background',
|
||||
text: variables.getMessage('modals.main.settings.sections.background.title'),
|
||||
text: t('modals.main.settings.sections.background.title'),
|
||||
},
|
||||
{
|
||||
value: 'quote',
|
||||
text: variables.getMessage('modals.main.settings.sections.quote.title'),
|
||||
text: t('modals.main.settings.sections.quote.title'),
|
||||
},
|
||||
{
|
||||
value: 'quotebackground',
|
||||
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 (
|
||||
<>
|
||||
<Header
|
||||
title={variables.getMessage(`${NAVBAR_SECTION}.title`)}
|
||||
title={t(`${NAVBAR_SECTION}.title`)}
|
||||
setting="navbar"
|
||||
category="widgets"
|
||||
zoomSetting="zoomNavbar"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { MdPerson, MdOpenInNew } from 'react-icons/md';
|
||||
import { Tooltip } from 'components/Elements';
|
||||
import variables from 'config/variables';
|
||||
import { useT } from 'contexts';
|
||||
import QuoteButtons from './QuoteButtons';
|
||||
|
||||
/**
|
||||
@@ -17,9 +17,10 @@ export default function AuthorInfo({
|
||||
onShare,
|
||||
isFavourited,
|
||||
}) {
|
||||
const t = useT();
|
||||
const showAuthorImg = localStorage.getItem('authorImg') !== 'false';
|
||||
const hasLink = authorOccupation !== 'Unknown' && authorlink !== null;
|
||||
const trimmedLicense = authorimglicense?.substring(0, 40) +
|
||||
const trimmedLicense = authorimglicense?.substring(0, 40) +
|
||||
(authorimglicense?.length > 40 ? '…' : '');
|
||||
|
||||
return (
|
||||
@@ -30,7 +31,7 @@ export default function AuthorInfo({
|
||||
{!authorimg && authorimg !== undefined && <MdPerson />}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
{author ? (
|
||||
<div className="author-content">
|
||||
<span className="title">{author}</span>
|
||||
@@ -49,10 +50,10 @@ export default function AuthorInfo({
|
||||
<span className="subtitle pulse">loading</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
<div className="quote-buttons">
|
||||
{hasLink && (
|
||||
<Tooltip title={variables.getMessage('widgets.quote.link_tooltip')}>
|
||||
<Tooltip title={t('widgets.quote.link_tooltip')}>
|
||||
<a
|
||||
href={authorlink}
|
||||
className="quoteAuthorLink"
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
import { MdContentCopy, MdStarBorder, MdStar, MdIosShare } from 'react-icons/md';
|
||||
import { Tooltip } from 'components/Elements';
|
||||
import { useT } from 'contexts';
|
||||
import variables from 'config/variables';
|
||||
|
||||
/**
|
||||
* Quote action buttons component
|
||||
*/
|
||||
export default function QuoteButtons({
|
||||
onCopy,
|
||||
onFavourite,
|
||||
onShare,
|
||||
export default function QuoteButtons({
|
||||
onCopy,
|
||||
onFavourite,
|
||||
onShare,
|
||||
isFavourited,
|
||||
}) {
|
||||
const t = useT();
|
||||
const showCopy = localStorage.getItem('copyButton') !== 'false';
|
||||
const showShare = localStorage.getItem('quoteShareButton') !== 'false';
|
||||
const showFavourite = localStorage.getItem('favouriteQuoteEnabled') === 'true';
|
||||
@@ -18,39 +20,39 @@ export default function QuoteButtons({
|
||||
return (
|
||||
<>
|
||||
{showCopy && (
|
||||
<Tooltip title={variables.getMessage('widgets.quote.copy')}>
|
||||
<Tooltip title={t('widgets.quote.copy')}>
|
||||
<button
|
||||
onClick={onCopy}
|
||||
aria-label={variables.getMessage('widgets.quote.copy')}
|
||||
aria-label={t('widgets.quote.copy')}
|
||||
>
|
||||
<MdContentCopy className="copyButton" />
|
||||
</button>
|
||||
</Tooltip>
|
||||
)}
|
||||
{showShare && (
|
||||
<Tooltip title={variables.getMessage('widgets.quote.share')}>
|
||||
<Tooltip title={t('widgets.quote.share')}>
|
||||
<button
|
||||
onClick={onShare}
|
||||
aria-label={variables.getMessage('widgets.quote.share')}
|
||||
aria-label={t('widgets.quote.share')}
|
||||
>
|
||||
<MdIosShare className="copyButton" />
|
||||
</button>
|
||||
</Tooltip>
|
||||
)}
|
||||
{showFavourite && (
|
||||
<Tooltip
|
||||
<Tooltip
|
||||
title={
|
||||
isFavourited
|
||||
? variables.getMessage('widgets.quote.unfavourite')
|
||||
: variables.getMessage('widgets.quote.favourite')
|
||||
? t('widgets.quote.unfavourite')
|
||||
: t('widgets.quote.favourite')
|
||||
}
|
||||
>
|
||||
<button
|
||||
onClick={onFavourite}
|
||||
aria-label={
|
||||
isFavourited
|
||||
? variables.getMessage('widgets.quote.unfavourite')
|
||||
: variables.getMessage('widgets.quote.favourite')
|
||||
? t('widgets.quote.unfavourite')
|
||||
: t('widgets.quote.favourite')
|
||||
}
|
||||
>
|
||||
{isFavourited ? (
|
||||
|
||||
@@ -1,38 +1,38 @@
|
||||
import I18n from '@eartharoid/i18n';
|
||||
|
||||
import * as ar from 'translations/ar.json';
|
||||
import * as arz from 'translations/arz.json';
|
||||
import * as az from 'translations/az.json';
|
||||
import * as azb from 'translations/azb.json';
|
||||
import * as bn from 'translations/bn.json';
|
||||
import * as de_DE from 'translations/de_DE.json';
|
||||
import * as el from 'translations/el.json';
|
||||
import * as en_GB from 'translations/en_GB.json';
|
||||
import * as en_US from 'translations/en_US.json';
|
||||
import * as es from 'translations/es.json';
|
||||
import * as es_419 from 'translations/es_419.json';
|
||||
import * as et from 'translations/et.json';
|
||||
import * as fa from 'translations/fa.json';
|
||||
import * as fr from 'translations/fr.json';
|
||||
import * as hu from 'translations/hu.json';
|
||||
import * as id_ID from 'translations/id_ID.json';
|
||||
import * as ja from 'translations/ja.json';
|
||||
import * as lt from 'translations/lt.json';
|
||||
import * as lv from 'translations/lv.json';
|
||||
import * as nl from 'translations/nl.json';
|
||||
import * as no from 'translations/no.json';
|
||||
import * as peo from 'translations/peo.json';
|
||||
import * as pt from 'translations/pt.json';
|
||||
import * as pt_BR from 'translations/pt_BR.json';
|
||||
import * as ru from 'translations/ru.json';
|
||||
import * as sl from 'translations/sl.json';
|
||||
import * as sv from 'translations/sv.json';
|
||||
import * as ta from 'translations/ta.json';
|
||||
import * as tr_TR from 'translations/tr_TR.json';
|
||||
import * as uk from 'translations/uk.json';
|
||||
import * as vi from 'translations/vi.json';
|
||||
import * as zh_CN from 'translations/zh_CN.json';
|
||||
import * as zh_Hant from 'translations/zh_Hant.json';
|
||||
import ar from 'translations/ar.json';
|
||||
import arz from 'translations/arz.json';
|
||||
import az from 'translations/az.json';
|
||||
import azb from 'translations/azb.json';
|
||||
import bn from 'translations/bn.json';
|
||||
import de_DE from 'translations/de_DE.json';
|
||||
import el from 'translations/el.json';
|
||||
import en_GB from 'translations/en_GB.json';
|
||||
import en_US from 'translations/en_US.json';
|
||||
import es from 'translations/es.json';
|
||||
import es_419 from 'translations/es_419.json';
|
||||
import et from 'translations/et.json';
|
||||
import fa from 'translations/fa.json';
|
||||
import fr from 'translations/fr.json';
|
||||
import hu from 'translations/hu.json';
|
||||
import id_ID from 'translations/id_ID.json';
|
||||
import ja from 'translations/ja.json';
|
||||
import lt from 'translations/lt.json';
|
||||
import lv from 'translations/lv.json';
|
||||
import nl from 'translations/nl.json';
|
||||
import no from 'translations/no.json';
|
||||
import peo from 'translations/peo.json';
|
||||
import pt from 'translations/pt.json';
|
||||
import pt_BR from 'translations/pt_BR.json';
|
||||
import ru from 'translations/ru.json';
|
||||
import sl from 'translations/sl.json';
|
||||
import sv from 'translations/sv.json';
|
||||
import ta from 'translations/ta.json';
|
||||
import tr_TR from 'translations/tr_TR.json';
|
||||
import uk from 'translations/uk.json';
|
||||
import vi from 'translations/vi.json';
|
||||
import zh_CN from 'translations/zh_CN.json';
|
||||
import zh_Hant from 'translations/zh_Hant.json';
|
||||
|
||||
/**
|
||||
* Initialise the i18n object.
|
||||
|
||||
Reference in New Issue
Block a user