implement i18n

This commit is contained in:
Ben Phelps 2022-09-08 11:48:16 +03:00
parent d25148c8ae
commit c08d4b7b9c
29 changed files with 431 additions and 139 deletions

View file

@ -1,10 +1,15 @@
import useSWR from "swr";
import { BiError } from "react-icons/bi";
import { useTranslation } from "react-i18next";
import Icon from "./icon";
export default function OpenWeatherMap({ options }) {
const { data, error } = useSWR(`/api/widgets/openweathermap?${new URLSearchParams(options).toString()}`);
const { t, i18n } = useTranslation();
const { data, error } = useSWR(
`/api/widgets/openweathermap?${new URLSearchParams({ lang: i18n.language, ...options }).toString()}`
);
if (error || data?.cod === 401) {
return (
@ -30,6 +35,8 @@ export default function OpenWeatherMap({ options }) {
return <div className="flex flex-row items-center" />;
}
const unit = options.units === "metric" ? "celsius" : "fahrenheit";
return (
<div className="flex flex-col justify-center">
<div className="flex flex-row items-center justify-end">
@ -42,11 +49,9 @@ export default function OpenWeatherMap({ options }) {
<div className="flex flex-col ml-3 text-left">
<span className="text-theme-800 dark:text-theme-200 text-sm">
{options.label && `${options.label}, `}
{data.main.temp.toFixed(1)}&deg;
</span>
<span className="text-theme-800 dark:text-theme-200 text-xs">
{data.weather[0].description.charAt(0).toUpperCase() + data.weather[0].description.slice(1)}
{t("common.number", { value: data.main.temp, style: "unit", unit })}
</span>
<span className="text-theme-800 dark:text-theme-200 text-xs">{data.weather[0].description}</span>
</div>
</div>
</div>

View file

@ -1,8 +1,11 @@
import useSWR from "swr";
import { FiCpu } from "react-icons/fi";
import { BiError } from "react-icons/bi";
import { useTranslation } from "react-i18next";
export default function Cpu() {
const { t } = useTranslation();
const { data, error } = useSWR(`/api/widgets/resources?type=cpu`, {
refreshInterval: 1500,
});
@ -12,7 +15,7 @@ export default function Cpu() {
<div className="flex-none flex flex-row items-center justify-center">
<BiError className="text-theme-800 dark:text-theme-200 w-5 h-5" />
<div className="flex flex-col ml-3 text-left">
<span className="text-theme-800 dark:text-theme-200 text-xs">API Error</span>
<span className="text-theme-800 dark:text-theme-200 text-xs">{t("widget.api_error")}</span>
</div>
</div>
);
@ -23,7 +26,7 @@ export default function Cpu() {
<div className="flex-none flex flex-row items-center justify-center">
<FiCpu className="text-theme-800 dark:text-theme-200 w-5 h-5" />
<div className="flex flex-col ml-3 text-left">
<span className="text-theme-800 dark:text-theme-200 text-xs">- Usage</span>
<span className="text-theme-800 dark:text-theme-200 text-xs">-</span>
</div>
</div>
);
@ -35,7 +38,9 @@ export default function Cpu() {
<div className="flex-none flex flex-row items-center justify-center">
<FiCpu className="text-theme-800 dark:text-theme-200 w-5 h-5" />
<div className="flex flex-col ml-3 text-left font-mono min-w-[50px]">
<div className="text-theme-800 dark:text-theme-200 text-xs">{`${Math.round(data.cpu.usage)}%`}</div>
<div className="text-theme-800 dark:text-theme-200 text-xs">
{t("common.number", { value: data.cpu.usage, style: "unit", unit: "percent", maximumFractionDigits: 0 })}
</div>
<div className="w-full bg-gray-200 rounded-full h-1 dark:bg-gray-700">
<div
className="bg-theme-600 h-1 rounded-full dark:bg-theme-500"

View file

@ -1,10 +1,11 @@
import useSWR from "swr";
import { FiHardDrive } from "react-icons/fi";
import { BiError } from "react-icons/bi";
import { formatBytes } from "utils/stats-helpers";
import { useTranslation } from "react-i18next";
export default function Disk({ options }) {
const { t } = useTranslation();
const { data, error } = useSWR(`/api/widgets/resources?type=disk&target=${options.disk}`, {
refreshInterval: 1500,
});
@ -14,7 +15,7 @@ export default function Disk({ options }) {
<div className="flex-none flex flex-row items-center justify-center">
<BiError className="text-theme-800 dark:text-theme-200 w-5 h-5" />
<div className="flex flex-col ml-3 text-left font-mono">
<span className="text-theme-800 dark:text-theme-200 text-xs">API Error</span>
<span className="text-theme-800 dark:text-theme-200 text-xs">{t("widget.api_error")}</span>
</div>
</div>
);
@ -38,10 +39,10 @@ export default function Disk({ options }) {
<FiHardDrive className="text-theme-800 dark:text-theme-200 w-5 h-5" />
<div className="flex flex-col ml-3 text-left font-mono ">
<span className="text-theme-800 dark:text-theme-200 text-xs group-hover:hidden">
{formatBytes(data.drive.freeGb * 1024 * 1024 * 1024, 0)} Free
{t("common.bytes", { value: data.drive.freeGb * 1024 * 1024 * 1024 })} {t("resources.free")}
</span>
<span className="text-theme-800 dark:text-theme-200 text-xs hidden group-hover:block">
{formatBytes(data.drive.totalGb * 1024 * 1024 * 1024, 0)} Total
{t("common.bytes", { value: data.drive.totalGb * 1024 * 1024 * 1024 })} {t("resources.total")}
</span>
<div className="w-full bg-gray-200 rounded-full h-1 dark:bg-gray-700">
<div

View file

@ -1,10 +1,11 @@
import useSWR from "swr";
import { FaMemory } from "react-icons/fa";
import { BiError } from "react-icons/bi";
import { formatBytes } from "utils/stats-helpers";
import { useTranslation } from "react-i18next";
export default function Memory() {
const { t } = useTranslation();
const { data, error } = useSWR(`/api/widgets/resources?type=memory`, {
refreshInterval: 1500,
});
@ -14,7 +15,7 @@ export default function Memory() {
<div className="flex-none flex flex-row items-center justify-center">
<BiError className="text-theme-800 dark:text-theme-200 w-5 h-5" />
<div className="flex flex-col ml-3 text-left font-mono">
<span className="text-theme-800 dark:text-theme-200 text-xs">API Error</span>
<span className="text-theme-800 dark:text-theme-200 text-xs">{t("widget.api_error")}</span>
</div>
</div>
);
@ -38,10 +39,10 @@ export default function Memory() {
<FaMemory className="text-theme-800 dark:text-theme-200 w-5 h-5" />
<div className="flex flex-col ml-3 text-left font-mono">
<span className="text-theme-800 dark:text-theme-200 text-xs group-hover:hidden">
{formatBytes(data.memory.freeMemMb * 1024 * 1024)} Free
{t("common.bytes", { value: data.memory.freeMemMb * 1024 * 1024 })} {t("resources.free")}
</span>
<span className="text-theme-800 dark:text-theme-200 text-xs hidden group-hover:block">
{formatBytes(data.memory.usedMemMb * 1024 * 1024)} Used
{t("common.bytes", { value: data.memory.usedMemMb * 1024 * 1024 })} {t("resources.used")}
</span>
<div className="w-full bg-gray-200 rounded-full h-1 dark:bg-gray-700">
<div

View file

@ -1,4 +1,5 @@
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { FiSearch } from "react-icons/fi";
import { SiDuckduckgo, SiMicrosoftbing, SiGoogle } from "react-icons/si";
@ -26,6 +27,8 @@ const providers = {
};
export default function Search({ options }) {
const { t } = useTranslation();
const provider = providers[options.provider];
const [query, setQuery] = useState("");
@ -53,7 +56,7 @@ export default function Search({ options }) {
<input
type="search"
className="overflow-hidden w-full placeholder-theme-900 text-xs text-theme-900 bg-theme-50 rounded-md border border-theme-300 focus:ring-theme-500 focus:border-theme-500 dark:bg-theme-800 dark:border-theme-600 dark:placeholder-theme-400 dark:text-white dark:focus:ring-theme-500 dark:focus:border-theme-500 h-full"
placeholder="Search..."
placeholder={t("search.placeholder")}
onChange={(s) => setQuery(s.currentTarget.value)}
required
/>

View file

@ -1,10 +1,15 @@
import useSWR from "swr";
import { BiError } from "react-icons/bi";
import { useTranslation } from "react-i18next";
import Icon from "./icon";
export default function WeatherApi({ options }) {
const { data, error } = useSWR(`/api/widgets/weather?${new URLSearchParams(options).toString()}`);
const { t, i18n } = useTranslation();
const { data, error } = useSWR(
`/api/widgets/weather?${new URLSearchParams({ lang: i18n.language, ...options }).toString()}`
);
if (error) {
return (
@ -30,6 +35,8 @@ export default function WeatherApi({ options }) {
return <div className="flex flex-row items-center justify-end" />;
}
const unit = options.units === "metric" ? "celsius" : "fahrenheit";
return (
<div className="flex flex-col justify-center">
<div className="flex flex-row items-center justify-end">
@ -39,7 +46,11 @@ export default function WeatherApi({ options }) {
<div className="flex flex-col ml-3 text-left">
<span className="text-theme-800 dark:text-theme-200 text-sm">
{options.label && `${options.label}, `}
{options.units === "metric" ? data.current.temp_c : data.current.temp_f}&deg;
{t("common.number", {
value: options.units === "metric" ? data.current.temp_c : data.current.temp_f,
style: "unit",
unit,
})}
</span>
<span className="text-theme-800 dark:text-theme-200 text-xs">{data.current.condition.text}</span>
</div>