diff --git a/web/public/static/langs/de.json b/web/public/static/langs/de.json new file mode 100644 index 00000000..ef6b3a17 --- /dev/null +++ b/web/public/static/langs/de.json @@ -0,0 +1,3 @@ +{ + "nav_button_subscribe": "Thema abonnieren" +} diff --git a/web/src/components/App.js b/web/src/components/App.js index 25e4983d..d7a251f1 100644 --- a/web/src/components/App.js +++ b/web/src/components/App.js @@ -22,6 +22,7 @@ import {useAutoSubscribe, useBackgroundProcesses, useConnectionListeners} from " import SendDialog from "./SendDialog"; import Messaging from "./Messaging"; import "./i18n"; // Translations! +import {Backdrop, CircularProgress} from "@mui/material"; // TODO races when two tabs are open // TODO investigate service workers @@ -48,12 +49,6 @@ const App = () => { ); } -const Loader = () => ( -
-
loading...
-
-); - const AllSubscriptions = () => { const { subscriptions } = useOutletContext(); return ; @@ -132,6 +127,18 @@ const Main = (props) => { ); }; +const Loader = () => ( + theme.palette.mode === 'light' ? theme.palette.grey[100] : theme.palette.grey[900] + }} + > + + +); + const updateTitle = (newNotificationsCount) => { document.title = (newNotificationsCount > 0) ? `(${newNotificationsCount}) ntfy` : "ntfy"; } diff --git a/web/src/components/Preferences.js b/web/src/components/Preferences.js index ef4b7fcb..ab1406ac 100644 --- a/web/src/components/Preferences.js +++ b/web/src/components/Preferences.js @@ -33,6 +33,7 @@ import DialogContent from "@mui/material/DialogContent"; import DialogActions from "@mui/material/DialogActions"; import userManager from "../app/UserManager"; import {playSound} from "../app/utils"; +import {useTranslation} from "react-i18next"; const Preferences = () => { return ( @@ -40,6 +41,7 @@ const Preferences = () => { + ); @@ -60,7 +62,6 @@ const Notifications = () => { ); }; - const Sound = () => { const sound = useLiveQuery(async () => prefs.sound()); const handleChange = async (ev) => { @@ -362,4 +363,31 @@ const UserDialog = (props) => { ); }; +const Appearance = () => { + return ( + + + Appearance + + + + + + ); +}; + +const Language = () => { + const { t, i18n } = useTranslation(); + return ( + + + + + + ) +}; + export default Preferences; diff --git a/web/src/components/i18n.js b/web/src/components/i18n.js index 7400a998..42eb5721 100644 --- a/web/src/components/i18n.js +++ b/web/src/components/i18n.js @@ -3,10 +3,13 @@ import Backend from 'i18next-http-backend'; import LanguageDetector from 'i18next-browser-languagedetector'; import { initReactI18next } from 'react-i18next'; -// init i18next -// for all options read: https://www.i18next.com/overview/configuration-options -// learn more: https://github.com/i18next/i18next-browser-languageDetector -// learn more: https://github.com/i18next/i18next-http-backend +// Translations using i18next +// - Options: https://www.i18next.com/overview/configuration-options +// - Browser Language Detector: https://github.com/i18next/i18next-browser-languageDetector +// - HTTP Backend (load files via fetch): https://github.com/i18next/i18next-http-backend +// +// See example project here: +// https://github.com/i18next/react-i18next/tree/master/example/react i18n .use(Backend) diff --git a/web/src/index.js b/web/src/index.js index e439fe5c..659bcb8f 100644 --- a/web/src/index.js +++ b/web/src/index.js @@ -1,8 +1,6 @@ import * as React from 'react'; -import ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; import App from './components/App'; -ReactDOM.render( - , - document.querySelector('#root') -); +const root = createRoot(document.querySelector('#root')); +root.render();