mirror of
https://github.com/mue/mue.git
synced 2026-07-17 22:14:13 +02:00
feat(translation): refactor translation system to use useT hook for reactive updates
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import variables from 'config/variables';
|
||||
import { useState, memo } from 'react';
|
||||
import { useT } from 'contexts';
|
||||
import Favourite from './Favourite';
|
||||
import {
|
||||
MdInfo,
|
||||
@@ -54,6 +55,7 @@ const downloadImage = async (info) => {
|
||||
};
|
||||
|
||||
function PhotoInformation({ info, url, api }) {
|
||||
const t = useT();
|
||||
const [width, setWidth] = useState(0);
|
||||
const [height, setHeight] = useState(0);
|
||||
const [usePhotoMap, setPhotoMap] = useState(false);
|
||||
@@ -64,7 +66,7 @@ function PhotoInformation({ info, url, api }) {
|
||||
const [shareModal, openShareModal] = useState(false);
|
||||
const [excludeModal, openExcludeModal] = useState(false);
|
||||
const [favouriteTooltipText, setFavouriteTooltipText] = useState(
|
||||
variables.getMessage('widgets.quote.favourite'),
|
||||
t('widgets.quote.favourite'),
|
||||
);
|
||||
|
||||
if (info.hidden === true || !info.credit) {
|
||||
@@ -72,7 +74,7 @@ function PhotoInformation({ info, url, api }) {
|
||||
}
|
||||
|
||||
let credit = info.credit;
|
||||
let photo = variables.getMessage('widgets.background.credit');
|
||||
let photo = t('widgets.background.credit');
|
||||
|
||||
// unsplash credit
|
||||
if (info.photographerURL && info.photographerURL !== '' && !info.offline && api) {
|
||||
@@ -142,31 +144,31 @@ function PhotoInformation({ info, url, api }) {
|
||||
return (
|
||||
<div className="extra-content">
|
||||
{info.location && info.location !== 'N/A' ? (
|
||||
<div className="row" title={variables.getMessage('widgets.background.location')}>
|
||||
<div className="row" title={t('widgets.background.location')}>
|
||||
<MdLocationOn />
|
||||
<span id="infoLocation">{info.location}</span>
|
||||
</div>
|
||||
) : null}
|
||||
{info.camera && info.camera !== 'N/A' ? (
|
||||
<div className="row" title={variables.getMessage('widgets.background.camera')}>
|
||||
<div className="row" title={t('widgets.background.camera')}>
|
||||
<MdPhotoCamera />
|
||||
<span id="infoCamera">{info.camera}</span>
|
||||
</div>
|
||||
) : null}
|
||||
<div className="row" title={variables.getMessage('widgets.background.resolution')}>
|
||||
<div className="row" title={t('widgets.background.resolution')}>
|
||||
<Resolution />
|
||||
<span id="infoResolution">
|
||||
{width}x{height}
|
||||
</span>
|
||||
</div>
|
||||
{info.category && (
|
||||
<div className="row" title={variables.getMessage('widgets.background.category')}>
|
||||
<div className="row" title={t('widgets.background.category')}>
|
||||
<Category />
|
||||
<span id="infoCategory">{info.category[0].toUpperCase() + info.category.slice(1)}</span>
|
||||
</div>
|
||||
)}
|
||||
{api && (
|
||||
<div className="row" title={variables.getMessage('widgets.background.source')}>
|
||||
<div className="row" title={t('widgets.background.source')}>
|
||||
<Source />
|
||||
<span id="infoSource">
|
||||
{info.photoURL ? (
|
||||
@@ -189,7 +191,7 @@ function PhotoInformation({ info, url, api }) {
|
||||
return (
|
||||
<div className="buttons">
|
||||
{!info.offline && (
|
||||
<Tooltip title={variables.getMessage('widgets.quote.share')} key="share" placement="top">
|
||||
<Tooltip title={t('widgets.quote.share')} key="share" placement="top">
|
||||
<Share onClick={() => openShareModal(true)} />
|
||||
</Tooltip>
|
||||
)}
|
||||
@@ -204,7 +206,7 @@ function PhotoInformation({ info, url, api }) {
|
||||
</Tooltip>
|
||||
{!info.offline && (
|
||||
<Tooltip
|
||||
title={variables.getMessage('widgets.background.download')}
|
||||
title={t('widgets.background.download')}
|
||||
key="download"
|
||||
placement="top"
|
||||
>
|
||||
@@ -213,7 +215,7 @@ function PhotoInformation({ info, url, api }) {
|
||||
)}
|
||||
{info.pun && info.category && (
|
||||
<Tooltip
|
||||
title={variables.getMessage('widgets.background.exclude')}
|
||||
title={t('widgets.background.exclude')}
|
||||
key="exclude"
|
||||
placement="top"
|
||||
>
|
||||
@@ -227,16 +229,16 @@ function PhotoInformation({ info, url, api }) {
|
||||
const UnsplashStats = () => {
|
||||
return (
|
||||
<div className="unsplashStats">
|
||||
<div title={variables.getMessage('widgets.background.views')}>
|
||||
<div title={t('widgets.background.views')}>
|
||||
<Views />
|
||||
<span>{info.views.toLocaleString()}</span>
|
||||
</div>
|
||||
<div title={variables.getMessage('widgets.background.downloads')}>
|
||||
<div title={t('widgets.background.downloads')}>
|
||||
<Download />
|
||||
<span>{info.downloads.toLocaleString()}</span>
|
||||
</div>
|
||||
{info.likes ? (
|
||||
<div title={variables.getMessage('widgets.background.likes')}>
|
||||
<div title={t('widgets.background.likes')}>
|
||||
<MdFavourite />
|
||||
<span>{info.likes.toLocaleString()}</span>
|
||||
</div>
|
||||
@@ -366,7 +368,7 @@ function PhotoInformation({ info, url, api }) {
|
||||
{(showExtraInfo || other) && excludeModal === false ? (
|
||||
<>
|
||||
<span className="subtitle">
|
||||
{variables.getMessage('widgets.background.information')}
|
||||
{t('widgets.background.information')}
|
||||
</span>
|
||||
<InformationItems />
|
||||
<ActionButtons />
|
||||
|
||||
@@ -2,6 +2,7 @@ import { useState, useEffect, useRef } from 'react';
|
||||
import variables from 'config/variables';
|
||||
import { nth, convertTimezone } from 'utils/date';
|
||||
import EventBus from 'utils/eventbus';
|
||||
import { useT } from 'contexts';
|
||||
import './greeting.scss';
|
||||
|
||||
/**
|
||||
@@ -44,6 +45,7 @@ const calculateAge = (date) => {
|
||||
};
|
||||
|
||||
const Greeting = () => {
|
||||
const t = useT();
|
||||
const [greeting, setGreeting] = useState('');
|
||||
const [display, setDisplay] = useState('block');
|
||||
const [fontSize, setFontSize] = useState('1.6em');
|
||||
@@ -63,13 +65,13 @@ const Greeting = () => {
|
||||
let message;
|
||||
switch (true) {
|
||||
case hour < 12:
|
||||
message = variables.getMessage('widgets.greeting.morning');
|
||||
message = t('widgets.greeting.morning');
|
||||
break;
|
||||
case hour < 18:
|
||||
message = variables.getMessage('widgets.greeting.afternoon');
|
||||
message = t('widgets.greeting.afternoon');
|
||||
break;
|
||||
default:
|
||||
message = variables.getMessage('widgets.greeting.evening');
|
||||
message = t('widgets.greeting.evening');
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -103,10 +105,10 @@ const Greeting = () => {
|
||||
|
||||
if (birth.getDate() === now.getDate() && birth.getMonth() === now.getMonth()) {
|
||||
if (localStorage.getItem('birthdayage') === 'true' && calculateAge(birth) !== 0) {
|
||||
const text = variables.getMessage('widgets.greeting.birthday').split(' ');
|
||||
const text = t('widgets.greeting.birthday').split(' ');
|
||||
message = `${text[0]} ${nth(calculateAge(birth))} ${text[1]}`;
|
||||
} else {
|
||||
message = variables.getMessage('widgets.greeting.birthday');
|
||||
message = t('widgets.greeting.birthday');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -149,7 +151,7 @@ const Greeting = () => {
|
||||
clearTimeout(timerRef.current);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
}, [t]);
|
||||
|
||||
return (
|
||||
<span className="greeting" ref={greetingRef} style={{ display, fontSize }}>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import variables from 'config/variables';
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { useMessage } from 'contexts/TranslationContext';
|
||||
import { useT } from 'contexts/TranslationContext';
|
||||
import variables from 'config/variables';
|
||||
|
||||
import { MdOutlineOpenInNew } from 'react-icons/md';
|
||||
|
||||
@@ -9,10 +9,11 @@ import { Radio } from 'components/Form/Settings';
|
||||
import languages from '@/i18n/languages.json';
|
||||
|
||||
const LanguageOptions = () => {
|
||||
const loadingText = useMessage('modals.main.loading');
|
||||
const offlineText = useMessage('modals.main.marketplace.offline.description');
|
||||
const languageTitle = useMessage('modals.main.settings.sections.language.title');
|
||||
const quoteTitle = useMessage('modals.main.settings.sections.language.quote');
|
||||
const t = useT();
|
||||
const loadingText = t('modals.main.loading');
|
||||
const offlineText = t('modals.main.marketplace.offline.description');
|
||||
const languageTitle = t('modals.main.settings.sections.language.title');
|
||||
const quoteTitle = t('modals.main.settings.sections.language.quote');
|
||||
|
||||
const [quoteLanguages, setQuoteLanguages] = useState([
|
||||
{
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import variables from 'config/variables';
|
||||
import { memo, useMemo } from 'react';
|
||||
import { useTranslation } from 'contexts/TranslationContext';
|
||||
import { useT } from 'contexts/TranslationContext';
|
||||
|
||||
import Tabs from 'components/Elements/MainModal/backend/Tabs';
|
||||
|
||||
@@ -90,15 +89,15 @@ const sections = [
|
||||
];
|
||||
|
||||
function Settings(props) {
|
||||
const { languagecode } = useTranslation();
|
||||
const t = useT();
|
||||
|
||||
// Recalculate section labels when language changes
|
||||
const translatedSections = useMemo(() =>
|
||||
sections.map(section => ({
|
||||
...section,
|
||||
translatedLabel: variables.getMessage(section.label)
|
||||
translatedLabel: t(section.label)
|
||||
})),
|
||||
[languagecode]
|
||||
[t]
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import variables from 'config/variables';
|
||||
import { memo, useState, useCallback } from 'react';
|
||||
import { useT } from 'contexts';
|
||||
|
||||
import { MdCropFree } from 'react-icons/md';
|
||||
|
||||
import { Tooltip } from 'components/Elements';
|
||||
|
||||
const Maximise = memo(({ fontSize }) => {
|
||||
const t = useT();
|
||||
const [hidden, setHidden] = useState(false);
|
||||
|
||||
const setAttribute = useCallback((blur, brightness, filter) => {
|
||||
@@ -44,7 +46,7 @@ const Maximise = memo(({ fontSize }) => {
|
||||
const maximise = useCallback(() => {
|
||||
// hide widgets
|
||||
const widgets = document.getElementById('widgets');
|
||||
|
||||
|
||||
if (!hidden) {
|
||||
widgets.style.display = 'none';
|
||||
setHidden(true);
|
||||
@@ -60,13 +62,13 @@ const Maximise = memo(({ fontSize }) => {
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
title={variables.getMessage('modals.main.settings.sections.background.buttons.view')}
|
||||
title={t('modals.main.settings.sections.background.buttons.view')}
|
||||
>
|
||||
<button
|
||||
className="navbarButton"
|
||||
style={{ fontSize }}
|
||||
onClick={maximise}
|
||||
aria-label={variables.getMessage('modals.main.settings.sections.background.buttons.view')}
|
||||
aria-label={t('modals.main.settings.sections.background.buttons.view')}
|
||||
>
|
||||
<MdCropFree className="topicons" />
|
||||
</button>
|
||||
|
||||
@@ -1,34 +1,39 @@
|
||||
import { useState, useEffect } from 'react';
|
||||
import variables from 'config/variables';
|
||||
import { useT } from 'contexts/TranslationContext';
|
||||
import { MdRefresh } from 'react-icons/md';
|
||||
import { Tooltip } from 'components/Elements';
|
||||
import EventBus from 'utils/eventbus';
|
||||
import { useTranslation } from 'contexts/TranslationContext';
|
||||
import variables from 'config/variables';
|
||||
|
||||
function Refresh() {
|
||||
const { languagecode } = useTranslation();
|
||||
const t = useT();
|
||||
const [refreshText, setRefreshText] = useState('');
|
||||
const [refreshOption, setRefreshOption] = useState(localStorage.getItem('refreshOption') || '');
|
||||
|
||||
useEffect(() => {
|
||||
EventBus.on('refresh', (data) => {
|
||||
const handleRefresh = (data) => {
|
||||
if (data === 'navbar' || data === 'background' || data === 'language') {
|
||||
setRefreshOption(localStorage.getItem('refreshOption'));
|
||||
updateRefreshText();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
EventBus.on('refresh', handleRefresh);
|
||||
updateRefreshText();
|
||||
}, [languagecode]);
|
||||
|
||||
return () => {
|
||||
EventBus.off('refresh', handleRefresh);
|
||||
};
|
||||
}, [t]);
|
||||
|
||||
function updateRefreshText() {
|
||||
let text;
|
||||
switch (localStorage.getItem('refreshOption')) {
|
||||
case 'background':
|
||||
text = variables.getMessage('modals.main.settings.sections.background.title');
|
||||
text = t('modals.main.settings.sections.background.title');
|
||||
break;
|
||||
case 'quote':
|
||||
text = variables.getMessage('modals.main.settings.sections.quote.title');
|
||||
text = t('modals.main.settings.sections.quote.title');
|
||||
break;
|
||||
case 'quotebackground':
|
||||
text = new Intl.ListFormat(
|
||||
@@ -38,14 +43,12 @@ function Refresh() {
|
||||
type: 'conjunction',
|
||||
},
|
||||
).format([
|
||||
variables.getMessage('modals.main.settings.sections.quote.title'),
|
||||
variables.getMessage('modals.main.settings.sections.background.title'),
|
||||
t('modals.main.settings.sections.quote.title'),
|
||||
t('modals.main.settings.sections.background.title'),
|
||||
]);
|
||||
break;
|
||||
default:
|
||||
text = variables.getMessage(
|
||||
'modals.main.settings.sections.appearance.navbar.refresh_options.page',
|
||||
);
|
||||
text = t('modals.main.settings.sections.appearance.navbar.refresh_options.page');
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,12 +3,14 @@ import variables from 'config/variables';
|
||||
import { memo, useRef, useEffect, useState, useCallback } from 'react';
|
||||
import { MdSearch, MdMic } from 'react-icons/md';
|
||||
import { Tooltip } from 'components/Elements';
|
||||
import { useT } from 'contexts';
|
||||
|
||||
import EventBus from 'utils/eventbus';
|
||||
|
||||
import './search.scss';
|
||||
|
||||
function Search() {
|
||||
const t = useT();
|
||||
const [microphone, setMicrophone] = useState(null);
|
||||
const [classList] = useState(
|
||||
localStorage.getItem('widgetStyle') === 'legacy' ? 'searchIcons old' : 'searchIcons',
|
||||
@@ -113,14 +115,14 @@ function Search() {
|
||||
<div className="searchMain">
|
||||
<div className={classList}>
|
||||
<Tooltip
|
||||
title={variables.getMessage('modals.main.settings.sections.search.voice_search')}
|
||||
title={t('modals.main.settings.sections.search.voice_search')}
|
||||
>
|
||||
{microphone}
|
||||
</Tooltip>
|
||||
</div>
|
||||
<form onSubmit={searchButton} className="searchBar">
|
||||
<div className={classList}>
|
||||
<Tooltip title={variables.getMessage('widgets.search')}>
|
||||
<Tooltip title={t('widgets.search')}>
|
||||
<button className="navbarButton" onClick={searchButton} aria-label="Search">
|
||||
<MdSearch />
|
||||
</button>
|
||||
@@ -128,7 +130,7 @@ function Search() {
|
||||
</div>
|
||||
<input
|
||||
type="text"
|
||||
placeholder={variables.getMessage('widgets.search')}
|
||||
placeholder={t('widgets.search')}
|
||||
id="searchtext"
|
||||
className="searchInput"
|
||||
/>
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import variables from 'config/variables';
|
||||
import { MdOutlineOpenInNew } from 'react-icons/md';
|
||||
import languages from '@/i18n/languages.json';
|
||||
import { useMessage } from 'contexts/TranslationContext';
|
||||
import { useT } from 'contexts/TranslationContext';
|
||||
import variables from 'config/variables';
|
||||
|
||||
import { Radio } from 'components/Form/Settings';
|
||||
import { Header, Content } from '../Layout';
|
||||
|
||||
function ChooseLanguage() {
|
||||
const title = useMessage('modals.welcome.sections.language.title');
|
||||
const description = useMessage('modals.welcome.sections.language.description');
|
||||
const t = useT();
|
||||
const title = t('modals.welcome.sections.language.title');
|
||||
const description = t('modals.welcome.sections.language.description');
|
||||
|
||||
return (
|
||||
<Content>
|
||||
|
||||
Reference in New Issue
Block a user