Compare commits

...
31 Commits
Author SHA1 Message Date
Releases Homarr 3506f875e3 chore(release): 1.4.0 [skip ci] 2025-01-31 19:13:04 +00:00
homarr-releases[bot] e30e4b8cb7 chore(release): automatic release v1.4.0 2025-01-31 19:12:20 +00:00
homarr-renovate[bot] 9662e1abba fix(deps): update tiptap monorepo to v2.11.5 (#2203)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-01-31 09:33:25 +00:00
homarr-renovate[bot] e44c3a7bc8 fix(deps): update tanstack-query monorepo to ^5.66.0 (#2202)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-01-31 09:16:43 +00:00
homarr-renovate[bot] c287e9965f fix(deps): update dependency jotai to ^2.11.2 (#2201)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-01-31 02:14:23 +00:00
homarr-crowdin[bot] bea0124e3f chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2025-01-31 00:44:11 +00:00
Manuel d4154d259f fix: respect certificates for app ping (#2198) 2025-01-30 23:12:45 +01:00
Meier Lukas 77746278a3 fix(docker): missing production env variable (#2188) 2025-01-30 22:14:52 +01:00
Meier Lukas c75d4f0f58 fix: negative curve radius system health (#2197) 2025-01-30 22:14:26 +01:00
Meier Lukas 96fd5cc35e fix: use hostname for suspense query url (#2187) 2025-01-30 22:14:14 +01:00
Meier Lukas bd0b7c9518 fix: board crashes with empty string favicon (#2192) 2025-01-30 20:15:05 +01:00
homarr-renovate[bot] c05c51856b fix(deps): update tiptap monorepo to v2.11.4 (#2195)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-01-30 16:18:52 +00:00
homarr-crowdin[bot] dac1646ecc chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2025-01-30 00:43:11 +00:00
Yossi Hillali c19a4009f3 feat: weather widget - add wind speed, option to disable decimals for temperature & redesign dropdown forecast (#2099) 2025-01-29 23:02:13 +02:00
homarr-renovate[bot] 5657384d2a chore(deps): update dependency @types/swagger-ui-react to v5 (#2181)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-01-29 21:30:45 +01:00
homarr-renovate[bot] 4c72a34daf fix(deps): update dependency drizzle-orm to ^0.39.1 (#2186)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-01-29 16:39:45 +00:00
homarr-renovate[bot] de48ef21e9 chore(deps): update dependency @types/chroma-js to v3.1.1 (#2185)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-01-29 16:18:59 +00:00
homarr-renovate[bot] 37ccfab89a fix(deps): update dependency drizzle-kit to ^0.30.4 (#2183)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-01-29 15:43:18 +00:00
homarr-crowdin[bot] 07d60fe13e chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2025-01-29 00:44:09 +00:00
Meier Lukas bbd1b0c5d0 chore: remove node-options from example env 2025-01-28 22:26:44 +01:00
Meier Lukas c130e92661 chore(issue-template): add missing homarr version 1.3.1 2025-01-28 22:24:58 +01:00
Releases Homarr 0de853ff37 chore(release): 1.3.1 [skip ci] 2025-01-28 21:20:02 +00:00
homarr-releases[bot] a438a23f4e chore(release): automatic release v1.3.1 2025-01-28 21:19:19 +00:00
Manuel 8dd7fe297c fix: automatic search engine creation (#2172) 2025-01-28 22:18:31 +01:00
Manuel 780efab80c fix: app url line clamp (#2170) 2025-01-28 20:33:04 +01:00
homarr-renovate[bot] a4e9abcda1 fix(deps): update dependency swagger-ui-react to ^5.18.3 (#2164)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-01-28 13:00:40 +00:00
homarr-renovate[bot] 55b1afbb21 fix(deps): update tanstack-query monorepo to ^5.65.1 (#2161)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-01-28 09:17:32 +00:00
homarr-renovate[bot] b447fc9fe4 chore(deps): update dependency @types/node to ^22.12.0 (#2159)
Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
2025-01-28 02:15:44 +00:00
homarr-crowdin[bot] 51ebaba399 chore(lang): updated translations from crowdin
Co-authored-by: Crowdin Homarr <190541745+homarr-crowdin[bot]@users.noreply.github.com>
2025-01-28 00:44:31 +00:00
homarr-renovate[bot]andMeier Lukas 9d4aea2c41 fix(deps): update dependency typescript-eslint to ^8.22.0 (#2149)
* fix(deps): update dependency typescript-eslint to ^8.22.0

* fix: lint issues

---------

Co-authored-by: homarr-renovate[bot] <158783068+homarr-renovate[bot]@users.noreply.github.com>
Co-authored-by: Meier Lukas <meierschlumpf@gmail.com>
2025-01-27 22:32:23 +01:00
Meier Lukas 4dcdac6621 chore(issue-template): add missing homarr version 1.3.0 2025-01-27 21:22:18 +01:00
63 changed files with 5252 additions and 1361 deletions

No files matched your search

+1 -4
View File
@@ -32,7 +32,4 @@ DB_URL='FULL_PATH_TO_YOUR_SQLITE_DB_FILE'
# If it is used, please use the full path to the directory where the certificates are stored. # If it is used, please use the full path to the directory where the certificates are stored.
# LOCAL_CERTIFICATE_PATH='FULL_PATH_TO_CERTIFICATES' # LOCAL_CERTIFICATE_PATH='FULL_PATH_TO_CERTIFICATES'
TURBO_TELEMETRY_DISABLED=1 TURBO_TELEMETRY_DISABLED=1
# Configure logging to use winston logger
NODE_OPTIONS='-r @homarr/log/override'
+2
View File
@@ -31,6 +31,8 @@ body:
label: Version label: Version
description: What version of Homarr are you running? description: What version of Homarr are you running?
options: options:
- 1.3.1
- 1.3.0
- 1.2.0 - 1.2.0
- 1.1.0 - 1.1.0
- 1.0.1 - 1.0.1
+30
View File
@@ -1,3 +1,33 @@
## [1.4.0](https://github.com/homarr-labs/homarr/compare/v1.3.1...v1.4.0) (2025-01-31)
### Features
* weather widget - add wind speed, option to disable decimals for temperature & redesign dropdown forecast ([#2099](https://github.com/homarr-labs/homarr/issues/2099)) ([c19a400](https://github.com/homarr-labs/homarr/commit/c19a4009f37ec2aba8d4edd2d19819605ecb9575))
### Bug Fixes
* board crashes with empty string favicon ([#2192](https://github.com/homarr-labs/homarr/issues/2192)) ([bd0b7c9](https://github.com/homarr-labs/homarr/commit/bd0b7c9518af88e0a329ea6286cb5ef97098782a))
* **deps:** update dependency drizzle-kit to ^0.30.4 ([#2183](https://github.com/homarr-labs/homarr/issues/2183)) ([37ccfab](https://github.com/homarr-labs/homarr/commit/37ccfab89a7843c65d6f354bef2b0537b20ea757))
* **deps:** update dependency drizzle-orm to ^0.39.1 ([#2186](https://github.com/homarr-labs/homarr/issues/2186)) ([4c72a34](https://github.com/homarr-labs/homarr/commit/4c72a34daf06c5e00fc4ece6d990148c1cd6d87f))
* **deps:** update dependency jotai to ^2.11.2 ([#2201](https://github.com/homarr-labs/homarr/issues/2201)) ([c287e99](https://github.com/homarr-labs/homarr/commit/c287e9965f008b6ac6f3bac56057b94c412a3779))
* **deps:** update tanstack-query monorepo to ^5.66.0 ([#2202](https://github.com/homarr-labs/homarr/issues/2202)) ([e44c3a7](https://github.com/homarr-labs/homarr/commit/e44c3a7bc8be5b67d78096d5daa53ad23ccdea5d))
* **deps:** update tiptap monorepo to v2.11.4 ([#2195](https://github.com/homarr-labs/homarr/issues/2195)) ([c05c518](https://github.com/homarr-labs/homarr/commit/c05c51856baff5222b0abda56e1c11d9bc9bd6f9))
* **deps:** update tiptap monorepo to v2.11.5 ([#2203](https://github.com/homarr-labs/homarr/issues/2203)) ([9662e1a](https://github.com/homarr-labs/homarr/commit/9662e1abba3e105fd549d25ee0a0efc48cf293a1))
* **docker:** missing production env variable ([#2188](https://github.com/homarr-labs/homarr/issues/2188)) ([7774627](https://github.com/homarr-labs/homarr/commit/77746278a36f2b9d39c780eada25195121cc0803))
* negative curve radius system health ([#2197](https://github.com/homarr-labs/homarr/issues/2197)) ([c75d4f0](https://github.com/homarr-labs/homarr/commit/c75d4f0f58136a0499a51494eb54c78c745f0b3f))
* respect certificates for app ping ([#2198](https://github.com/homarr-labs/homarr/issues/2198)) ([d4154d2](https://github.com/homarr-labs/homarr/commit/d4154d259fa50bfd754e7ea98b872df78864e014))
* use hostname for suspense query url ([#2187](https://github.com/homarr-labs/homarr/issues/2187)) ([96fd5cc](https://github.com/homarr-labs/homarr/commit/96fd5cc35e9ca85aba48670860e6bf2a4a2caaa9))
## [1.3.1](https://github.com/homarr-labs/homarr/compare/v1.3.0...v1.3.1) (2025-01-28)
### Bug Fixes
* app url line clamp ([#2170](https://github.com/homarr-labs/homarr/issues/2170)) ([780efab](https://github.com/homarr-labs/homarr/commit/780efab80cdc5446a6468d60afe2c1d9ecca0f1e))
* automatic search engine creation ([#2172](https://github.com/homarr-labs/homarr/issues/2172)) ([8dd7fe2](https://github.com/homarr-labs/homarr/commit/8dd7fe297c431bbe448bc47b381370ade7c4d3d9))
* **deps:** update dependency swagger-ui-react to ^5.18.3 ([#2164](https://github.com/homarr-labs/homarr/issues/2164)) ([a4e9abc](https://github.com/homarr-labs/homarr/commit/a4e9abcda192a96754078eece4343c2c1c9fa032))
* **deps:** update dependency typescript-eslint to ^8.22.0 ([#2149](https://github.com/homarr-labs/homarr/issues/2149)) ([9d4aea2](https://github.com/homarr-labs/homarr/commit/9d4aea2c4187ddda6a0484d0f6a0403c04961dde))
* **deps:** update tanstack-query monorepo to ^5.65.1 ([#2161](https://github.com/homarr-labs/homarr/issues/2161)) ([55b1afb](https://github.com/homarr-labs/homarr/commit/55b1afbb2167ccb6f5115cbb1291dfe561a5aa05))
## [1.3.0](https://github.com/homarr-labs/homarr/compare/v1.2.0...v1.3.0) (2025-01-27) ## [1.3.0](https://github.com/homarr-labs/homarr/compare/v1.2.0...v1.3.0) (2025-01-27)
### Features ### Features
+1
View File
@@ -63,6 +63,7 @@ ENV DB_URL='/appdata/db/db.sqlite'
ENV DB_DIALECT='sqlite' ENV DB_DIALECT='sqlite'
ENV DB_DRIVER='better-sqlite3' ENV DB_DRIVER='better-sqlite3'
ENV AUTH_PROVIDERS='credentials' ENV AUTH_PROVIDERS='credentials'
ENV NODE_ENV='production'
ENTRYPOINT [ "/app/entrypoint.sh" ] ENTRYPOINT [ "/app/entrypoint.sh" ]
CMD ["sh", "run.sh"] CMD ["sh", "run.sh"]
+8 -8
View File
@@ -51,9 +51,9 @@
"@million/lint": "1.0.14", "@million/lint": "1.0.14",
"@t3-oss/env-nextjs": "^0.12.0", "@t3-oss/env-nextjs": "^0.12.0",
"@tabler/icons-react": "^3.29.0", "@tabler/icons-react": "^3.29.0",
"@tanstack/react-query": "^5.65.0", "@tanstack/react-query": "^5.66.0",
"@tanstack/react-query-devtools": "^5.65.0", "@tanstack/react-query-devtools": "^5.66.0",
"@tanstack/react-query-next-experimental": "^5.65.0", "@tanstack/react-query-next-experimental": "^5.66.0",
"@trpc/client": "next", "@trpc/client": "next",
"@trpc/next": "next", "@trpc/next": "next",
"@trpc/react-query": "next", "@trpc/react-query": "next",
@@ -67,7 +67,7 @@
"dotenv": "^16.4.7", "dotenv": "^16.4.7",
"flag-icons": "^7.3.2", "flag-icons": "^7.3.2",
"glob": "^11.0.1", "glob": "^11.0.1",
"jotai": "^2.11.1", "jotai": "^2.11.2",
"mantine-react-table": "2.0.0-beta.8", "mantine-react-table": "2.0.0-beta.8",
"next": "15.1.6", "next": "15.1.6",
"postcss-preset-mantine": "^1.17.0", "postcss-preset-mantine": "^1.17.0",
@@ -78,7 +78,7 @@
"react-simple-code-editor": "^0.14.1", "react-simple-code-editor": "^0.14.1",
"sass": "^1.83.4", "sass": "^1.83.4",
"superjson": "2.2.2", "superjson": "2.2.2",
"swagger-ui-react": "^5.18.2", "swagger-ui-react": "^5.18.3",
"use-deep-compare-effect": "^1.8.1", "use-deep-compare-effect": "^1.8.1",
"zod": "^3.24.1" "zod": "^3.24.1"
}, },
@@ -86,12 +86,12 @@
"@homarr/eslint-config": "workspace:^0.2.0", "@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0", "@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0", "@homarr/tsconfig": "workspace:^0.1.0",
"@types/chroma-js": "3.1.0", "@types/chroma-js": "3.1.1",
"@types/node": "^22.10.10", "@types/node": "^22.12.0",
"@types/prismjs": "^1.26.5", "@types/prismjs": "^1.26.5",
"@types/react": "19.0.8", "@types/react": "19.0.8",
"@types/react-dom": "19.0.3", "@types/react-dom": "19.0.3",
"@types/swagger-ui-react": "^4.19.0", "@types/swagger-ui-react": "^5.18.0",
"concurrently": "^9.1.2", "concurrently": "^9.1.2",
"eslint": "^9.19.0", "eslint": "^9.19.0",
"node-loader": "^2.1.0", "node-loader": "^2.1.0",
@@ -18,8 +18,8 @@ import superjson from "superjson";
import type { SuperJSONResult } from "superjson"; import type { SuperJSONResult } from "superjson";
import type { AppRouter } from "@homarr/api"; import type { AppRouter } from "@homarr/api";
import { clientApi, getTrpcUrl } from "@homarr/api/client"; import { clientApi } from "@homarr/api/client";
import { createHeadersCallbackForSource } from "@homarr/api/shared"; import { createHeadersCallbackForSource, getTrpcUrl } from "@homarr/api/shared";
import { env } from "~/env"; import { env } from "~/env";
@@ -7,6 +7,7 @@ import "~/styles/gridstack.scss";
import { IntegrationProvider } from "@homarr/auth/client"; import { IntegrationProvider } from "@homarr/auth/client";
import { auth } from "@homarr/auth/next"; import { auth } from "@homarr/auth/next";
import { getIntegrationsWithPermissionsAsync } from "@homarr/auth/server"; import { getIntegrationsWithPermissionsAsync } from "@homarr/auth/server";
import { isNullOrWhitespace } from "@homarr/common";
import { getI18n } from "@homarr/translation/server"; import { getI18n } from "@homarr/translation/server";
import { createMetaTitle } from "~/metadata"; import { createMetaTitle } from "~/metadata";
@@ -48,11 +49,13 @@ export const createBoardContentPage = <TParams extends Record<string, unknown>>(
return { return {
title: board.metaTitle ?? createMetaTitle(t("board.content.metaTitle", { boardName: board.name })), title: board.metaTitle ?? createMetaTitle(t("board.content.metaTitle", { boardName: board.name })),
icons: { icons: {
icon: board.faviconImageUrl ? board.faviconImageUrl : undefined, icon: !isNullOrWhitespace(board.faviconImageUrl) ? board.faviconImageUrl : undefined,
apple: board.faviconImageUrl ? board.faviconImageUrl : undefined, apple: !isNullOrWhitespace(board.faviconImageUrl) ? board.faviconImageUrl : undefined,
}, },
appleWebApp: { appleWebApp: {
startupImage: { url: board.faviconImageUrl ? board.faviconImageUrl : "/logo/logo.png" }, startupImage: {
url: !isNullOrWhitespace(board.faviconImageUrl) ? board.faviconImageUrl : "/logo/logo.png",
},
}, },
}; };
} catch (error) { } catch (error) {
@@ -80,7 +80,7 @@ const AppCard = async ({ app }: AppCardProps) => {
return ( return (
<Card withBorder> <Card withBorder>
<Group justify="space-between" wrap="nowrap"> <Group justify="space-between" wrap="nowrap">
<Group align="top" justify="start" wrap="nowrap"> <Group align="top" justify="start" wrap="nowrap" style={{ flex: "1" }}>
<Avatar <Avatar
size="sm" size="sm"
src={app.iconUrl} src={app.iconUrl}
@@ -91,7 +91,7 @@ const AppCard = async ({ app }: AppCardProps) => {
}, },
}} }}
/> />
<Stack gap={0}> <Stack gap={0} style={{ flex: "1" }}>
<Text fw={500} lineClamp={1}> <Text fw={500} lineClamp={1}>
{app.name} {app.name}
</Text> </Text>
@@ -101,7 +101,7 @@ const AppCard = async ({ app }: AppCardProps) => {
</Text> </Text>
)} )}
{app.href && ( {app.href && (
<Anchor href={app.href} lineClamp={1} size="sm" w="min-content"> <Anchor href={app.href} lineClamp={1} size="sm" style={{ wordBreak: "break-all" }}>
{app.href} {app.href}
</Anchor> </Anchor>
)} )}
@@ -70,9 +70,9 @@ export const EditIntegrationForm = ({ integration }: EditIntegrationForm) => {
if (testConnectionError) { if (testConnectionError) {
showErrorNotification({ showErrorNotification({
title: t(`integration.testConnection.notification.${testConnectionError.key}.title`), title: t(`integration.testConnection.notification.${testConnectionError.key}.title`),
message: testConnectionError.message message:
? testConnectionError.message testConnectionError.message ??
: t(`integration.testConnection.notification.${testConnectionError.key}.message`), t(`integration.testConnection.notification.${testConnectionError.key}.message`),
}); });
return; return;
} }
@@ -63,9 +63,9 @@ export const NewIntegrationForm = ({ searchParams }: NewIntegrationFormProps) =>
if (testConnectionError) { if (testConnectionError) {
showErrorNotification({ showErrorNotification({
title: t(`integration.testConnection.notification.${testConnectionError.key}.title`), title: t(`integration.testConnection.notification.${testConnectionError.key}.title`),
message: testConnectionError.message message:
? testConnectionError.message testConnectionError.message ??
: t(`integration.testConnection.notification.${testConnectionError.key}.message`), t(`integration.testConnection.notification.${testConnectionError.key}.message`),
}); });
return; return;
} }
+2 -1
View File
@@ -1,6 +1,7 @@
import { fetchRequestHandler } from "@trpc/server/adapters/fetch"; import { fetchRequestHandler } from "@trpc/server/adapters/fetch";
import { appRouter, createTRPCContext } from "@homarr/api"; import { appRouter, createTRPCContext } from "@homarr/api";
import { trpcPath } from "@homarr/api/shared";
import { auth } from "@homarr/auth/next"; import { auth } from "@homarr/auth/next";
import { logger } from "@homarr/log"; import { logger } from "@homarr/log";
@@ -25,7 +26,7 @@ export function OPTIONS() {
const handler = auth(async (req) => { const handler = auth(async (req) => {
const response = await fetchRequestHandler({ const response = await fetchRequestHandler({
endpoint: "/api/trpc", endpoint: trpcPath,
router: appRouter, router: appRouter,
req, req,
createContext: () => createTRPCContext({ session: req.auth, headers: req.headers }), createContext: () => createTRPCContext({ session: req.auth, headers: req.headers }),
+2 -2
View File
@@ -4,7 +4,7 @@ import { createTRPCClient, httpLink } from "@trpc/client";
import SuperJSON from "superjson"; import SuperJSON from "superjson";
import type { AppRouter } from "@homarr/api"; import type { AppRouter } from "@homarr/api";
import { createHeadersCallbackForSource } from "@homarr/api/shared"; import { createHeadersCallbackForSource, getTrpcUrl } from "@homarr/api/shared";
import { createI18nMiddleware } from "@homarr/translation/middleware"; import { createI18nMiddleware } from "@homarr/translation/middleware";
export async function middleware(request: NextRequest) { export async function middleware(request: NextRequest) {
@@ -34,7 +34,7 @@ export const config = {
export const serverFetchApi = createTRPCClient<AppRouter>({ export const serverFetchApi = createTRPCClient<AppRouter>({
links: [ links: [
httpLink({ httpLink({
url: `http://${process.env.HOSTNAME ?? "localhost"}:3000/api/trpc`, url: getTrpcUrl(),
transformer: SuperJSON, transformer: SuperJSON,
headers: createHeadersCallbackForSource("server-fetch"), headers: createHeadersCallbackForSource("server-fetch"),
}), }),
+1 -1
View File
@@ -44,7 +44,7 @@
"@homarr/eslint-config": "workspace:^0.2.0", "@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0", "@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0", "@homarr/tsconfig": "workspace:^0.1.0",
"@types/node": "^22.10.10", "@types/node": "^22.12.0",
"dotenv-cli": "^8.0.0", "dotenv-cli": "^8.0.0",
"eslint": "^9.19.0", "eslint": "^9.19.0",
"prettier": "^3.4.2", "prettier": "^3.4.2",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "homarr", "name": "homarr",
"version": "1.3.0", "version": "1.4.0",
"private": true, "private": true,
"scripts": { "scripts": {
"build": "cross-env CI=true turbo build", "build": "cross-env CI=true turbo build",
+1 -14
View File
@@ -5,7 +5,7 @@ import { createTRPCReact } from "@trpc/react-query";
import SuperJSON from "superjson"; import SuperJSON from "superjson";
import type { AppRouter } from "."; import type { AppRouter } from ".";
import { createHeadersCallbackForSource } from "./shared"; import { createHeadersCallbackForSource, getTrpcUrl } from "./shared";
export const clientApi = createTRPCReact<AppRouter>(); export const clientApi = createTRPCReact<AppRouter>();
export const fetchApi = createTRPCClient<AppRouter>({ export const fetchApi = createTRPCClient<AppRouter>({
@@ -17,16 +17,3 @@ export const fetchApi = createTRPCClient<AppRouter>({
}), }),
], ],
}); });
function getBaseUrl() {
if (typeof window !== "undefined") return window.location.origin;
return `http://localhost:${process.env.PORT ?? 3000}`;
}
/**
* Creates the full url for the trpc api endpoint
* @returns
*/
export function getTrpcUrl() {
return `${getBaseUrl()}/api/trpc`;
}
@@ -206,7 +206,10 @@ export const integrationRouter = createTRPCRouter({
); );
} }
if (input.attemptSearchEngineCreation) { if (
input.attemptSearchEngineCreation &&
integrationDefs[input.kind].category.flatMap((category) => category).includes("search")
) {
const icon = getIconUrl(input.kind); const icon = getIconUrl(input.kind);
await ctx.db.insert(searchEngines).values({ await ctx.db.insert(searchEngines).values({
id: createId(), id: createId(),
+5 -1
View File
@@ -6,7 +6,7 @@ import { createTRPCRouter, publicProcedure } from "../../trpc";
export const weatherRouter = createTRPCRouter({ export const weatherRouter = createTRPCRouter({
atLocation: publicProcedure.input(validation.widget.weather.atLocationInput).query(async ({ input }) => { atLocation: publicProcedure.input(validation.widget.weather.atLocationInput).query(async ({ input }) => {
const res = await fetchWithTimeout( const res = await fetchWithTimeout(
`https://api.open-meteo.com/v1/forecast?latitude=${input.latitude}&longitude=${input.longitude}&daily=weathercode,temperature_2m_max,temperature_2m_min&current_weather=true&timezone=auto`, `https://api.open-meteo.com/v1/forecast?latitude=${input.latitude}&longitude=${input.longitude}&daily=weathercode,temperature_2m_max,temperature_2m_min,sunrise,sunset,wind_speed_10m_max,wind_gusts_10m_max&current_weather=true&timezone=auto`,
); );
const json: unknown = await res.json(); const json: unknown = await res.json();
const weather = await validation.widget.weather.atLocationOutput.parseAsync(json); const weather = await validation.widget.weather.atLocationOutput.parseAsync(json);
@@ -18,6 +18,10 @@ export const weatherRouter = createTRPCRouter({
weatherCode: weather.daily.weathercode[index] ?? 404, weatherCode: weather.daily.weathercode[index] ?? 404,
maxTemp: weather.daily.temperature_2m_max[index], maxTemp: weather.daily.temperature_2m_max[index],
minTemp: weather.daily.temperature_2m_min[index], minTemp: weather.daily.temperature_2m_min[index],
sunrise: weather.daily.sunrise[index],
sunset: weather.daily.sunset[index],
maxWindSpeed: weather.daily.wind_speed_10m_max[index],
maxWindGusts: weather.daily.wind_gusts_10m_max[index],
}; };
}), }),
}; };
+15
View File
@@ -36,3 +36,18 @@ async function importCookiesAsync() {
.map(({ name, value }) => `${name}=${value}`) .map(({ name, value }) => `${name}=${value}`)
.join(";"); .join(";");
} }
function getBaseUrl() {
if (typeof window !== "undefined") return window.location.origin;
return `http://${process.env.HOSTNAME ?? "localhost"}:3000`;
}
export const trpcPath = "/api/trpc";
/**
* Creates the full url for the trpc api endpoint
* @returns
*/
export function getTrpcUrl() {
return `${getBaseUrl()}${trpcPath}`;
}
+4
View File
@@ -1,3 +1,7 @@
export const capitalize = <T extends string>(str: T) => { export const capitalize = <T extends string>(str: T) => {
return (str.charAt(0).toUpperCase() + str.slice(1)) as Capitalize<T>; return (str.charAt(0).toUpperCase() + str.slice(1)) as Capitalize<T>;
}; };
export const isNullOrWhitespace = (value: string | null): value is null => {
return value == null || value.trim() === "";
};
+2 -2
View File
@@ -47,8 +47,8 @@
"@testcontainers/mysql": "^10.17.2", "@testcontainers/mysql": "^10.17.2",
"better-sqlite3": "^11.8.1", "better-sqlite3": "^11.8.1",
"dotenv": "^16.4.7", "dotenv": "^16.4.7",
"drizzle-kit": "^0.30.3", "drizzle-kit": "^0.30.4",
"drizzle-orm": "^0.39.0", "drizzle-orm": "^0.39.1",
"drizzle-zod": "^0.7.0", "drizzle-zod": "^0.7.0",
"mysql2": "3.12.0" "mysql2": "3.12.0"
}, },
@@ -77,6 +77,8 @@ const optionMapping: OptionMapping = {
forecastDayCount: (oldOptions) => oldOptions.forecastDays, forecastDayCount: (oldOptions) => oldOptions.forecastDays,
hasForecast: (oldOptions) => oldOptions.displayWeekly, hasForecast: (oldOptions) => oldOptions.displayWeekly,
isFormatFahrenheit: (oldOptions) => oldOptions.displayInFahrenheit, isFormatFahrenheit: (oldOptions) => oldOptions.displayInFahrenheit,
disableTemperatureDecimals: () => undefined,
showCurrentWindSpeed: () => undefined,
location: (oldOptions) => oldOptions.location, location: (oldOptions) => oldOptions.location,
showCity: (oldOptions) => oldOptions.displayCityName, showCity: (oldOptions) => oldOptions.displayCityName,
dateFormat: (oldOptions) => (oldOptions.dateFormat === "hide" ? undefined : oldOptions.dateFormat), dateFormat: (oldOptions) => (oldOptions.dateFormat === "hide" ? undefined : oldOptions.dateFormat),
+3 -1
View File
@@ -22,8 +22,10 @@
}, },
"prettier": "@homarr/prettier-config", "prettier": "@homarr/prettier-config",
"dependencies": { "dependencies": {
"@homarr/certificates": "workspace:^0.1.0",
"@homarr/common": "workspace:^0.1.0", "@homarr/common": "workspace:^0.1.0",
"@homarr/log": "workspace:^0.1.0" "@homarr/log": "workspace:^0.1.0",
"pretty-print-error": "^1.1.2"
}, },
"devDependencies": { "devDependencies": {
"@homarr/eslint-config": "workspace:^0.2.0", "@homarr/eslint-config": "workspace:^0.2.0",
+25 -4
View File
@@ -1,13 +1,34 @@
import { extractErrorMessage, fetchWithTimeout } from "@homarr/common"; import { formatError } from "pretty-print-error";
import type { fetch } from "undici";
import { fetchWithTrustedCertificatesAsync } from "@homarr/certificates/server";
import { logger } from "@homarr/log"; import { logger } from "@homarr/log";
export const sendPingRequestAsync = async (url: string) => { export const sendPingRequestAsync = async (url: string) => {
try { try {
return await fetchWithTimeout(url).then((response) => ({ statusCode: response.status })); return await fetchWithTimeoutAndCertificates(url).then((response) => ({ statusCode: response.status }));
} catch (error) { } catch (error) {
logger.error("packages/ping/src/index.ts:", error); logger.error("packages/ping/src/index.ts:", formatError(error));
return { return {
error: extractErrorMessage(error), error: formatError(error),
}; };
} }
}; };
/**
* Same as fetch, but with a timeout of 10 seconds.
* Also respects certificates.
* https://stackoverflow.com/questions/46946380/fetch-api-request-timeout
* @param param0 fetch arguments
* @returns fetch response
*/
export const fetchWithTimeoutAndCertificates = (...[url, requestInit]: Parameters<typeof fetch>) => {
const controller = new AbortController();
// 10 seconds timeout:
const timeoutId = setTimeout(() => controller.abort(), 10000);
return fetchWithTrustedCertificatesAsync(url, { signal: controller.signal, ...requestInit }).finally(() => {
clearTimeout(timeoutId);
});
};
+1 -1
View File
@@ -37,7 +37,7 @@
"@mantine/hooks": "^7.16.2", "@mantine/hooks": "^7.16.2",
"@mantine/spotlight": "^7.16.2", "@mantine/spotlight": "^7.16.2",
"@tabler/icons-react": "^3.29.0", "@tabler/icons-react": "^3.29.0",
"jotai": "^2.11.1", "jotai": "^2.11.2",
"next": "15.1.6", "next": "15.1.6",
"react": "19.0.0", "react": "19.0.0",
"react-dom": "19.0.0", "react-dom": "19.0.0",
File diff suppressed because it is too large. Load diff
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "华氏温度" "label": "华氏温度"
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "天气位置" "label": "天气位置"
}, },
@@ -1391,6 +1398,13 @@
"description": "日期应该是什么样的" "description": "日期应该是什么样的"
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "晴朗", "clear": "晴朗",
"mainlyClear": "晴朗为主", "mainlyClear": "晴朗为主",
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "Teplota ve Fahrenheitech" "label": "Teplota ve Fahrenheitech"
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "Lokalita pro počasí" "label": "Lokalita pro počasí"
}, },
@@ -1391,6 +1398,13 @@
"description": "Jak by datum mělo vypadat" "description": "Jak by datum mělo vypadat"
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "Jasno", "clear": "Jasno",
"mainlyClear": "Převážně jasno", "mainlyClear": "Převážně jasno",
+20 -6
View File
@@ -28,7 +28,7 @@
}, },
"boardSelection": { "boardSelection": {
"title": "Fundet {count} tavler", "title": "Fundet {count} tavler",
"description": "Vælg alle tavler med deres størrelser du vil importere", "description": "Vælg alle tavler med den størrelse, du vil importere",
"action": { "action": {
"selectAll": "Vælg alle", "selectAll": "Vælg alle",
"unselectAll": "Fravælg alle" "unselectAll": "Fravælg alle"
@@ -153,10 +153,10 @@
"label": "Brug ikoner til pings" "label": "Brug ikoner til pings"
}, },
"defaultSearchEngine": { "defaultSearchEngine": {
"label": "" "label": "Standardsøgemaskine"
}, },
"openSearchInNewTab": { "openSearchInNewTab": {
"label": "" "label": "Åben søgeresultater i en ny fane"
} }
}, },
"error": { "error": {
@@ -219,10 +219,10 @@
"changeSearchPreferences": { "changeSearchPreferences": {
"notification": { "notification": {
"success": { "success": {
"message": "" "message": "Søgeindstillingerne blev ændret"
}, },
"error": { "error": {
"message": "" "message": "Kan ikke ændre søgeindstillinger"
} }
} }
}, },
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "Temperatur i Fahrenheit" "label": "Temperatur i Fahrenheit"
}, },
"disableTemperatureDecimals": {
"label": "Deaktiver temperaturdecimaler"
},
"showCurrentWindSpeed": {
"label": "Vis aktuel vindhastighed",
"description": "Kun på nuværende vejr"
},
"location": { "location": {
"label": "Vejr lokation" "label": "Vejr lokation"
}, },
@@ -1391,6 +1398,13 @@
"description": "Hvordan datoen skal se ud" "description": "Hvordan datoen skal se ud"
} }
}, },
"currentWindSpeed": "{currentWindSpeed} km/t",
"dailyForecast": {
"sunrise": "Solopgang",
"sunset": "Solnedgang",
"maxWindSpeed": "Maks. vindhastighed: {maxWindSpeed} km/t",
"maxWindGusts": "Maks. vindstød {maxWindGusts} km/t"
},
"kind": { "kind": {
"clear": "Skyfrit", "clear": "Skyfrit",
"mainlyClear": "Hovedsageligt skyfrit", "mainlyClear": "Hovedsageligt skyfrit",
@@ -2287,7 +2301,7 @@
"mobile": "Mobil" "mobile": "Mobil"
} }
}, },
"search": "", "search": "Søg",
"firstDayOfWeek": "Første ugedag", "firstDayOfWeek": "Første ugedag",
"accessibility": "Hjælpefunktioner" "accessibility": "Hjælpefunktioner"
} }
File diff suppressed because it is too large. Load diff
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "" "label": ""
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "Τοποθεσία καιρού" "label": "Τοποθεσία καιρού"
}, },
@@ -1391,6 +1398,13 @@
"description": "" "description": ""
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "Καθαρός", "clear": "Καθαρός",
"mainlyClear": "Κυρίως καθαρός", "mainlyClear": "Κυρίως καθαρός",
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "Temperature in Fahrenheit" "label": "Temperature in Fahrenheit"
}, },
"disableTemperatureDecimals": {
"label": "Disable temperature decimals"
},
"showCurrentWindSpeed": {
"label": "Show current wind speed",
"description": "Only on current weather"
},
"location": { "location": {
"label": "Weather location" "label": "Weather location"
}, },
@@ -1391,6 +1398,13 @@
"description": "How the date should look like" "description": "How the date should look like"
} }
}, },
"currentWindSpeed": "{currentWindSpeed} km/h",
"dailyForecast": {
"sunrise": "Sunrise",
"sunset": "Sunset",
"maxWindSpeed": "Max wind speed: {maxWindSpeed} km/h",
"maxWindGusts": "Max wind gusts: {maxWindGusts} km/h"
},
"kind": { "kind": {
"clear": "Clear", "clear": "Clear",
"mainlyClear": "Mainly clear", "mainlyClear": "Mainly clear",
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "" "label": ""
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "Ubicación" "label": "Ubicación"
}, },
@@ -1391,6 +1398,13 @@
"description": "" "description": ""
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "Despejado", "clear": "Despejado",
"mainlyClear": "Mayormente despejado", "mainlyClear": "Mayormente despejado",
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "" "label": ""
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "" "label": ""
}, },
@@ -1391,6 +1398,13 @@
"description": "" "description": ""
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "", "clear": "",
"mainlyClear": "", "mainlyClear": "",
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "" "label": ""
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "Lieu de la météo" "label": "Lieu de la météo"
}, },
@@ -1391,6 +1398,13 @@
"description": "" "description": ""
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "Clair", "clear": "Clair",
"mainlyClear": "Principalement clair", "mainlyClear": "Principalement clair",
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "טמפרטורה בפרנהייט" "label": "טמפרטורה בפרנהייט"
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "מיקום מזג האוויר" "label": "מיקום מזג האוויר"
}, },
@@ -1391,6 +1398,13 @@
"description": "איך צריך להיראות התאריך" "description": "איך צריך להיראות התאריך"
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "בהיר", "clear": "בהיר",
"mainlyClear": "בהיר בעיקר", "mainlyClear": "בהיר בעיקר",
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "" "label": ""
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "Lokacija vremenske prognoze" "label": "Lokacija vremenske prognoze"
}, },
@@ -1391,6 +1398,13 @@
"description": "" "description": ""
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "Vedro", "clear": "Vedro",
"mainlyClear": "Uglavnom vedro", "mainlyClear": "Uglavnom vedro",
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "" "label": ""
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "Időjárás helye" "label": "Időjárás helye"
}, },
@@ -1391,6 +1398,13 @@
"description": "Hogyan nézzen ki a dátum" "description": "Hogyan nézzen ki a dátum"
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "Tiszta", "clear": "Tiszta",
"mainlyClear": "Főként tiszta", "mainlyClear": "Főként tiszta",
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "" "label": ""
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "Località meteo" "label": "Località meteo"
}, },
@@ -1391,6 +1398,13 @@
"description": "" "description": ""
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "Sereno", "clear": "Sereno",
"mainlyClear": "Per lo più sereno", "mainlyClear": "Per lo più sereno",
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "" "label": ""
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "天候の場所" "label": "天候の場所"
}, },
@@ -1391,6 +1398,13 @@
"description": "" "description": ""
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "クリア", "clear": "クリア",
"mainlyClear": "主なクリア事項", "mainlyClear": "主なクリア事項",
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "" "label": ""
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "날씨 위치" "label": "날씨 위치"
}, },
@@ -1391,6 +1398,13 @@
"description": "" "description": ""
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "맑음", "clear": "맑음",
"mainlyClear": "대체로 맑음", "mainlyClear": "대체로 맑음",
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "" "label": ""
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "" "label": ""
}, },
@@ -1391,6 +1398,13 @@
"description": "" "description": ""
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "", "clear": "",
"mainlyClear": "", "mainlyClear": "",
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "" "label": ""
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "Laikapstākļu atrašānās vieta" "label": "Laikapstākļu atrašānās vieta"
}, },
@@ -1391,6 +1398,13 @@
"description": "" "description": ""
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "Skaidrs", "clear": "Skaidrs",
"mainlyClear": "Galvenokārt skaidrs", "mainlyClear": "Galvenokārt skaidrs",
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "Temperatuur in fahrenheit" "label": "Temperatuur in fahrenheit"
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "Weerlocatie" "label": "Weerlocatie"
}, },
@@ -1391,6 +1398,13 @@
"description": "Hoe de datum eruit moet zien" "description": "Hoe de datum eruit moet zien"
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "Wissen", "clear": "Wissen",
"mainlyClear": "Overwegend helder", "mainlyClear": "Overwegend helder",
+250 -236
View File
@@ -52,7 +52,7 @@
"field": { "field": {
"token": { "token": {
"label": "Token", "label": "Token",
"description": "Angi vist import-token for din forrige homarr forekomst" "description": "Angi vist import-token for din forrige Homarr forekomst"
} }
}, },
"notification": { "notification": {
@@ -153,10 +153,10 @@
"label": "Bruk ikoner for pinger" "label": "Bruk ikoner for pinger"
}, },
"defaultSearchEngine": { "defaultSearchEngine": {
"label": "" "label": "Standard søkemotor"
}, },
"openSearchInNewTab": { "openSearchInNewTab": {
"label": "" "label": "Åpne søkeresultater i ny fane"
} }
}, },
"error": { "error": {
@@ -219,10 +219,10 @@
"changeSearchPreferences": { "changeSearchPreferences": {
"notification": { "notification": {
"success": { "success": {
"message": "" "message": "Søkeinnstillingene endret"
}, },
"error": { "error": {
"message": "" "message": "Kunne ikke endre søkeinnstillingene"
} }
} }
}, },
@@ -742,23 +742,23 @@
}, },
"tokenId": { "tokenId": {
"label": "Token ID", "label": "Token ID",
"newLabel": "" "newLabel": "Ny token ID"
}, },
"realm": { "realm": {
"label": "", "label": "Område",
"newLabel": "" "newLabel": "Nytt område"
} }
} }
}, },
"permission": { "permission": {
"use": "", "use": "Velg integrasjon i elementer",
"interact": "", "interact": "Samhandle med integrasjoner",
"full": "" "full": "Full integrasjons-tilgang"
} }
}, },
"media": { "media": {
"plural": "", "plural": "Medier",
"search": "", "search": "Finn et medie",
"field": { "field": {
"name": "Navn", "name": "Navn",
"size": "Størrelse", "size": "Størrelse",
@@ -766,115 +766,115 @@
}, },
"action": { "action": {
"upload": { "upload": {
"label": "", "label": "Last opp medie",
"file": "", "file": "Velg fil",
"notification": { "notification": {
"success": { "success": {
"message": "" "message": "Medie lastet opp"
}, },
"error": { "error": {
"message": "" "message": "Mediet kunne ikke lastes opp"
} }
} }
}, },
"delete": { "delete": {
"label": "", "label": "Slett medie",
"description": "", "description": "Er du sikker på at du vil slette mediet <bName></bName>?",
"notification": { "notification": {
"success": { "success": {
"message": "" "message": "Mediet slettet"
}, },
"error": { "error": {
"message": "" "message": "Mediet kunne ikke slettes"
} }
} }
}, },
"copy": { "copy": {
"label": "" "label": "Kopier URL"
}, },
"open": { "open": {
"label": "" "label": "Åpne medie"
} }
} }
}, },
"common": { "common": {
"beta": "", "beta": "Beta",
"error": "Feil", "error": "Feil",
"action": { "action": {
"add": "Legg til", "add": "Legg til",
"apply": "Bruk", "apply": "Bruk",
"backToOverview": "", "backToOverview": "Tilbake til oversikt",
"create": "Opprett", "create": "Opprett",
"edit": "Rediger", "edit": "Rediger",
"import": "", "import": "Import",
"insert": "Sett inn", "insert": "Sett inn",
"remove": "Fjern", "remove": "Fjern",
"save": "Lagre", "save": "Lagre",
"saveChanges": "Lagre endringer", "saveChanges": "Lagre endringer",
"cancel": "Avbryt", "cancel": "Avbryt",
"delete": "Slett", "delete": "Slett",
"discard": "", "discard": "Forkast",
"confirm": "Bekreft", "confirm": "Bekreft",
"continue": "", "continue": "Fortsett",
"previous": "Tidligere", "previous": "Tidligere",
"next": "Neste", "next": "Neste",
"checkoutDocs": "", "checkoutDocs": "Les dokumentasjonen",
"checkLogs": "", "checkLogs": "Sjekk loggene for mer informasjon",
"tryAgain": "Prøv igjen", "tryAgain": "Prøv igjen",
"loading": "" "loading": "Laster"
}, },
"here": "", "here": "her",
"iconPicker": { "iconPicker": {
"label": "", "label": "Ikon-URL",
"header": "" "header": "Skriv navn eller objekt å filtrere for ikoner... Homarr vil søke gjennom {countIcons} ikoner for deg."
}, },
"colorScheme": { "colorScheme": {
"options": { "options": {
"light": "", "light": "Lys",
"dark": "" "dark": "Mørk"
} }
}, },
"information": { "information": {
"min": "", "min": "Min",
"max": "", "max": "Maks",
"days": "", "days": "Dager",
"hours": "", "hours": "Timer",
"minutes": "" "minutes": "Minutter"
}, },
"notification": { "notification": {
"create": { "create": {
"success": "", "success": "Opprettelse vellykket",
"error": "" "error": "Opprettelse mislyktes"
}, },
"delete": { "delete": {
"success": "", "success": "Sletting vellykket",
"error": "" "error": "Sletting feilet"
}, },
"update": { "update": {
"success": "", "success": "Endringer fullført",
"error": "" "error": "Kunne ikke fullføre endringer"
}, },
"transfer": { "transfer": {
"success": "", "success": "Overføring vellykket",
"error": "" "error": "Overføring feilet"
} }
}, },
"multiSelect": { "multiSelect": {
"placeholder": "" "placeholder": "Velg en eller flere verdier"
}, },
"multiText": { "multiText": {
"placeholder": "", "placeholder": "Legg til flere verdier",
"addLabel": "" "addLabel": "Legg til {value}"
}, },
"select": { "select": {
"placeholder": "", "placeholder": "Velg verdi",
"badge": { "badge": {
"recommended": "" "recommended": "Anbefalt"
} }
}, },
"userAvatar": { "userAvatar": {
"menu": { "menu": {
"switchToDarkMode": "", "switchToDarkMode": "Bytt til mørk modus",
"switchToLightMode": "Bytt til lys modus", "switchToLightMode": "Bytt til lys modus",
"management": "Administrasjon", "management": "Administrasjon",
"preferences": "Dine innstillinger", "preferences": "Dine innstillinger",
@@ -1020,44 +1020,44 @@
} }
}, },
"remove": { "remove": {
"title": "", "title": "Slett element",
"message": "" "message": "Er du sikker på at du vil slette dette elementet?"
} }
}, },
"widget": { "widget": {
"app": { "app": {
"name": "", "name": "App",
"description": "", "description": "Bygger inn en app i tavlen.",
"option": { "option": {
"appId": { "appId": {
"label": "" "label": "Velg app"
}, },
"openInNewTab": { "openInNewTab": {
"label": "Åpne i ny fane" "label": "Åpne i ny fane"
}, },
"showTitle": { "showTitle": {
"label": "" "label": "Vis app navn"
}, },
"showDescriptionTooltip": { "showDescriptionTooltip": {
"label": "" "label": "Vis beskrivelse verktøytips"
}, },
"pingEnabled": { "pingEnabled": {
"label": "" "label": "Aktiver enkel ping"
} }
}, },
"error": { "error": {
"notFound": { "notFound": {
"label": "", "label": "Ingen app",
"tooltip": "" "tooltip": "Du har ikke valgt en gyldig app"
} }
} }
}, },
"bookmarks": { "bookmarks": {
"name": "", "name": "Bokmerke",
"description": "", "description": "Viser flere applinker",
"option": { "option": {
"title": { "title": {
"label": "" "label": "Tittel"
}, },
"layout": { "layout": {
"label": "Oppsett", "label": "Oppsett",
@@ -1069,28 +1069,28 @@
"label": "Vertikal" "label": "Vertikal"
}, },
"grid": { "grid": {
"label": "" "label": "Rutenettet"
} }
} }
}, },
"hideIcon": { "hideIcon": {
"label": "" "label": "Skjul ikoner"
}, },
"hideHostname": { "hideHostname": {
"label": "" "label": "Skjul vertsnavn"
}, },
"openNewTab": { "openNewTab": {
"label": "" "label": "Åpne i ny fane"
}, },
"items": { "items": {
"label": "", "label": "Bokmerke",
"add": "" "add": "Legg til bokmerke"
} }
} }
}, },
"dnsHoleSummary": { "dnsHoleSummary": {
"name": "", "name": "DNS Hole Sammendrag",
"description": "", "description": "Viser sammendrag av DNS Hole",
"option": { "option": {
"layout": { "layout": {
"label": "Oppsett", "label": "Oppsett",
@@ -1102,28 +1102,28 @@
"label": "Vertikal" "label": "Vertikal"
}, },
"grid": { "grid": {
"label": "" "label": "Rutenett"
} }
} }
}, },
"usePiHoleColors": { "usePiHoleColors": {
"label": "" "label": "Bruk farger fra Pi-Hole"
} }
}, },
"error": { "error": {
"internalServerError": "", "internalServerError": "Kunne ikke hente DNS Hole Sammendrag",
"integrationsDisconnected": "" "integrationsDisconnected": "Ingen data er tilgjengelig, alle integrasjoner frakoblet"
}, },
"data": { "data": {
"adsBlockedToday": "Blokkert i dag", "adsBlockedToday": "Blokkert i dag",
"adsBlockedTodayPercentage": "Blokkert i dag", "adsBlockedTodayPercentage": "Blokkert i dag",
"dnsQueriesToday": "Spørringer i dag", "dnsQueriesToday": "Spørringer i dag",
"domainsBeingBlocked": "" "domainsBeingBlocked": "Domener på blokkliste"
}, },
"domainsTooltip": "" "domainsTooltip": "På grunn av flere integrasjons Homarr kan ikke kalkulere nøyaktig antall domener som blokkeres"
}, },
"dnsHoleControls": { "dnsHoleControls": {
"name": "", "name": "DNS Hole kontroller",
"description": "Kontroller PiHole eller AdGuard fra dashbordet", "description": "Kontroller PiHole eller AdGuard fra dashbordet",
"option": { "option": {
"layout": { "layout": {
@@ -1136,58 +1136,58 @@
"label": "Vertikal" "label": "Vertikal"
}, },
"grid": { "grid": {
"label": "" "label": "Rutenett"
} }
} }
}, },
"showToggleAllButtons": { "showToggleAllButtons": {
"label": "" "label": "Vis av/på alle knapper"
} }
}, },
"error": { "error": {
"internalServerError": "" "internalServerError": "Kunne ikke kontrollere DNS Hole"
}, },
"controls": { "controls": {
"enableAll": "", "enableAll": "Aktiver alle",
"disableAll": "", "disableAll": "Deaktiver Alle",
"setTimer": "", "setTimer": "Sett tidtaker",
"set": "", "set": "Angi",
"enabled": "Aktivert", "enabled": "Aktivert",
"disabled": "Deaktivert", "disabled": "Deaktivert",
"processing": "", "processing": "Prosesserer",
"disconnected": "", "disconnected": "Frakoblet",
"hours": "", "hours": "Timer",
"minutes": "", "minutes": "Minutter",
"unlimited": "" "unlimited": "Blank for ubegrenset"
} }
}, },
"clock": { "clock": {
"name": "", "name": "Dato og tid",
"description": "Viser gjeldende dato og klokkeslett.", "description": "Viser gjeldende dato og klokkeslett.",
"option": { "option": {
"customTitleToggle": { "customTitleToggle": {
"label": "", "label": "Tilpasset Tittel/By visning",
"description": "" "description": "Vis av en egendefinert tittel eller navnet på byen/landet øverst i klokken."
}, },
"customTitle": { "customTitle": {
"label": "" "label": "Tittel"
}, },
"is24HourFormat": { "is24HourFormat": {
"label": "", "label": "24-timersformat",
"description": "" "description": "Bruk 24-timers format i stedet for 12-timers format"
}, },
"showSeconds": { "showSeconds": {
"label": "" "label": "Vis sekunder"
}, },
"useCustomTimezone": { "useCustomTimezone": {
"label": "" "label": "Bruk en fast tidssone"
}, },
"timezone": { "timezone": {
"label": "Tidssone", "label": "Tidssone",
"description": "" "description": "Velg tidssonen etter IANA-standarden"
}, },
"showDate": { "showDate": {
"label": "" "label": "Vis dato"
}, },
"dateFormat": { "dateFormat": {
"label": "Datoformat", "label": "Datoformat",
@@ -1315,25 +1315,25 @@
}, },
"smartHome-entityState": { "smartHome-entityState": {
"name": "Enhet status", "name": "Enhet status",
"description": "", "description": "Vis status for en enhet og aktiver det valgfritt",
"option": { "option": {
"entityId": { "entityId": {
"label": "Enhets-ID" "label": "Enhets-ID"
}, },
"displayName": { "displayName": {
"label": "" "label": "Visningsnavn"
}, },
"entityUnit": { "entityUnit": {
"label": "" "label": "Enhet målingsenhet"
}, },
"clickable": { "clickable": {
"label": "" "label": "Klikkbar"
} }
} }
}, },
"smartHome-executeAutomation": { "smartHome-executeAutomation": {
"name": "", "name": "Kjør automatisering",
"description": "", "description": "Utløs en automatisering med ett klikk",
"option": { "option": {
"displayName": { "displayName": {
"label": "Visningsnavn" "label": "Visningsnavn"
@@ -1343,26 +1343,26 @@
} }
}, },
"spotlightAction": { "spotlightAction": {
"run": "" "run": "Kjør {name}"
} }
}, },
"calendar": { "calendar": {
"name": "Kalender", "name": "Kalender",
"description": "", "description": "Vis hendelser fra integrasjonene dine i en kalendervisning innenfor en bestemt relativ tidsperiode",
"option": { "option": {
"releaseType": { "releaseType": {
"label": "Radarr utgivelsestype", "label": "Radarr utgivelsestype",
"options": { "options": {
"inCinemas": "", "inCinemas": "På Kino",
"digitalRelease": "", "digitalRelease": "Digital utgivelse",
"physicalRelease": "" "physicalRelease": "Fysisk utgivelse"
} }
}, },
"filterPastMonths": { "filterPastMonths": {
"label": "" "label": "Start fra"
}, },
"filterFutureMonths": { "filterFutureMonths": {
"label": "" "label": "Slutt på"
} }
} }
}, },
@@ -1371,26 +1371,40 @@
"description": "Viser gjeldende værinformasjon for en angitt plassering.", "description": "Viser gjeldende værinformasjon for en angitt plassering.",
"option": { "option": {
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "Temperatur i Fahrenheit"
},
"disableTemperatureDecimals": {
"label": "" "label": ""
}, },
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "Vær plassering" "label": "Vær plassering"
}, },
"showCity": { "showCity": {
"label": "" "label": "Vis by"
}, },
"hasForecast": { "hasForecast": {
"label": "" "label": "Vis værmelding"
}, },
"forecastDayCount": { "forecastDayCount": {
"label": "", "label": "Antall dagers værvarsel",
"description": "" "description": "Når widget ikke er bred nok, blir færre dager vist"
}, },
"dateFormat": { "dateFormat": {
"label": "", "label": "Datoformat",
"description": "" "description": "Hvordan datoen skal se ut"
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "Tøm", "clear": "Tøm",
"mainlyClear": "Klar himmel", "mainlyClear": "Klar himmel",
@@ -1410,24 +1424,24 @@
}, },
"indexerManager": { "indexerManager": {
"name": "Indekserings-behandler status", "name": "Indekserings-behandler status",
"description": "", "description": "Status for indekserere",
"option": { "option": {
"openIndexerSiteInNewTab": { "openIndexerSiteInNewTab": {
"label": "" "label": "Åpne indekserer-side i ny fane"
} }
}, },
"title": "Indekserings-behandler", "title": "Indekserings-behandler",
"testAll": "Test alle", "testAll": "Test alle",
"error": { "error": {
"internalServerError": "" "internalServerError": "Kunne ikke hente indekser status"
} }
}, },
"healthMonitoring": { "healthMonitoring": {
"name": "Systemhelseovervåking", "name": "Systemhelseovervåking",
"description": "Viser informasjon som viser helsen og statusen til systemet(e).", "description": "Viser informasjon som viser helsen og statusen til systemet(e).",
"tab": { "tab": {
"system": "", "system": "System",
"cluster": "" "cluster": "Cluster"
}, },
"option": { "option": {
"fahrenheit": { "fahrenheit": {
@@ -1443,80 +1457,80 @@
"label": "Vis filsysteminfo" "label": "Vis filsysteminfo"
}, },
"defaultTab": { "defaultTab": {
"label": "" "label": "Standard fane"
}, },
"sectionIndicatorRequirement": { "sectionIndicatorRequirement": {
"label": "" "label": "Krav til seksjonsindikator"
} }
}, },
"popover": { "popover": {
"information": "", "information": "Informasjon",
"processor": "", "processor": "Prosessor: {cpuModelName}",
"memory": "", "memory": "Minne: {memory}GiB",
"memoryAvailable": "", "memoryAvailable": "Tilgjengelig: {memoryAvailable}GiB ({percent}%)",
"version": "", "version": "Versjon: {version}",
"uptime": "", "uptime": "Oppetid: {months} Måneder, {days} Dager, {hours} Timer, {minutes} Minutter",
"loadAverage": "", "loadAverage": "Gjennomsnittsbelastning:",
"minute": "", "minute": "1 minutt",
"minutes": "", "minutes": "{count} minutter",
"used": "", "used": "Brukt",
"available": "Tilgjengelig", "available": "Tilgjengelig",
"lastSeen": "" "lastSeen": "Siste statusoppdatering: {lastSeen}"
}, },
"memory": {}, "memory": {},
"error": { "error": {
"internalServerError": "" "internalServerError": "Kunne ikke hente helse status"
}, },
"cluster": { "cluster": {
"summary": { "summary": {
"cpu": "", "cpu": "CPU",
"memory": "" "memory": "RAM"
}, },
"resource": { "resource": {
"node": { "node": {
"name": "" "name": "Noder"
}, },
"qemu": { "qemu": {
"name": "" "name": "VMer"
}, },
"lxc": { "lxc": {
"name": "" "name": "LXCer"
}, },
"storage": { "storage": {
"name": "" "name": "Lagring"
} }
}, },
"popover": { "popover": {
"rightSection": { "rightSection": {
"node": "", "node": "Node",
"vmId": "", "vmId": "VM ID",
"plugin": "" "plugin": "Plugin"
}, },
"detail": { "detail": {
"cpu": "", "cpu": "Kjerner",
"memory": "", "memory": "Minne",
"storage": "", "storage": "Lagring",
"uptime": "", "uptime": "Oppetid",
"haState": "", "haState": "HA status",
"storageType": { "storageType": {
"local": "", "local": "Lokal lagring",
"shared": "" "shared": "Delt lagring"
} }
} }
}, },
"table": { "table": {
"header": { "header": {
"name": "", "name": "Navn",
"cpu": "", "cpu": "CPU",
"memory": "", "memory": "RAM",
"node": "" "node": "Node"
} }
} }
} }
}, },
"common": { "common": {
"location": { "location": {
"query": "", "query": "By / Postnummer",
"latitude": "", "latitude": "",
"longitude": "", "longitude": "",
"disabledTooltip": "", "disabledTooltip": "",
@@ -1613,119 +1627,119 @@
"label": "" "label": ""
}, },
"filterIsWhitelist": { "filterIsWhitelist": {
"label": "" "label": "Filtrer som hvitliste"
}, },
"applyFilterToRatio": { "applyFilterToRatio": {
"label": "" "label": "Bruk filter for å beregne ratio"
} }
}, },
"errors": { "errors": {
"noColumns": "", "noColumns": "Velg kolonner i elementer",
"noCommunications": "" "noCommunications": "Kan ikke laste inn data fra integrasjon"
}, },
"items": { "items": {
"actions": { "actions": {
"columnTitle": "" "columnTitle": "Kontroller"
}, },
"added": { "added": {
"columnTitle": "", "columnTitle": "Lagt til",
"detailsTitle": "Dato lagt til" "detailsTitle": "Dato lagt til"
}, },
"category": { "category": {
"columnTitle": "", "columnTitle": "Ekstra",
"detailsTitle": "" "detailsTitle": "Kategorier (eller ekstra informasjon)"
}, },
"downSpeed": { "downSpeed": {
"columnTitle": "Ned", "columnTitle": "Ned",
"detailsTitle": "Nedlastings- hastighet" "detailsTitle": "Nedlastings- hastighet"
}, },
"index": { "index": {
"columnTitle": "", "columnTitle": "#",
"detailsTitle": "" "detailsTitle": "Gjeldende indeks i klienten"
}, },
"id": { "id": {
"columnTitle": "" "columnTitle": "Id"
}, },
"integration": { "integration": {
"columnTitle": "Integrasjon" "columnTitle": "Integrasjon"
}, },
"name": { "name": {
"columnTitle": "" "columnTitle": "Jobb navn"
}, },
"progress": { "progress": {
"columnTitle": "Fremgang", "columnTitle": "Fremgang",
"detailsTitle": "" "detailsTitle": "Nedlastings fremdrift"
}, },
"ratio": { "ratio": {
"columnTitle": "Forhold", "columnTitle": "Forhold",
"detailsTitle": "" "detailsTitle": "Torrent-ratio (mottatt/sendt)"
}, },
"received": { "received": {
"columnTitle": "", "columnTitle": "Totalt ned",
"detailsTitle": "" "detailsTitle": "Totalt nedlastet"
}, },
"sent": { "sent": {
"columnTitle": "", "columnTitle": "Totalt opp",
"detailsTitle": "" "detailsTitle": "Totalt opplastet"
}, },
"size": { "size": {
"columnTitle": "", "columnTitle": "Filstørrelse",
"detailsTitle": "" "detailsTitle": "Total størrelse for utvalg/filer"
}, },
"state": { "state": {
"columnTitle": "Status", "columnTitle": "Status",
"detailsTitle": "" "detailsTitle": "Jobb status"
}, },
"time": { "time": {
"columnTitle": "", "columnTitle": "Fullfør tid",
"detailsTitle": "" "detailsTitle": "Tid siden/til fullførelse"
}, },
"type": { "type": {
"columnTitle": "", "columnTitle": "Type",
"detailsTitle": "" "detailsTitle": "Nedlastings-klient type"
}, },
"upSpeed": { "upSpeed": {
"columnTitle": "Opp", "columnTitle": "Opp",
"detailsTitle": "" "detailsTitle": "Opplastnings hastighet"
} }
}, },
"states": { "states": {
"downloading": "Laster ned", "downloading": "Laster ned",
"queued": "", "queued": "I kø",
"paused": "Pauset", "paused": "Pauset",
"completed": "Fullført", "completed": "Fullført",
"failed": "", "failed": "Feilet",
"processing": "", "processing": "Behandler",
"leeching": "", "leeching": "Laster ned",
"stalled": "", "stalled": "Stanset",
"unknown": "Ukjent", "unknown": "Ukjent",
"seeding": "" "seeding": "Deler"
}, },
"actions": { "actions": {
"clients": { "clients": {
"modalTitle": "", "modalTitle": "Nedlastings-klient liste",
"pause": "", "pause": "Pause alle klienter/elementer",
"resume": "" "resume": "Fortsett alle klienter/elementer"
}, },
"client": { "client": {
"pause": "", "pause": "Pause klient",
"resume": "" "resume": "Fortsett klient"
}, },
"item": { "item": {
"pause": "", "pause": "Pause element",
"resume": "", "resume": "Fortsett element",
"delete": { "delete": {
"title": "", "title": "Slett element",
"modalTitle": "", "modalTitle": "Er du sikker på at du vil slette denne jobben?",
"entry": "", "entry": "Slett oppføring",
"entryAndFiles": "" "entryAndFiles": "Slett oppføring og fil(er)"
} }
} }
}, },
"globalRatio": "" "globalRatio": "Global ratio"
}, },
"mediaRequests-requestList": { "mediaRequests-requestList": {
"name": "", "name": "Liste over mediaspillforespørsler",
"description": "Se en liste over alle medieforespørsler fra din Overseerr eller Jellyseerr instans", "description": "Se en liste over alle medieforespørsler fra din Overseerr eller Jellyseerr instans",
"option": { "option": {
"linksTargetNewTab": { "linksTargetNewTab": {
@@ -1733,21 +1747,21 @@
} }
}, },
"pending": { "pending": {
"approve": "", "approve": "Godkjenn forespørsel",
"approving": "", "approving": "Godkjenner forespørsel...",
"decline": "" "decline": "Avslå forespørsel"
}, },
"availability": { "availability": {
"unknown": "Ukjent", "unknown": "Ukjent",
"pending": "", "pending": "Pågår",
"processing": "", "processing": "Prosesserer",
"partiallyAvailable": "Delvis", "partiallyAvailable": "Delvis",
"available": "Tilgjengelig" "available": "Tilgjengelig"
}, },
"toBeDetermined": "" "toBeDetermined": "Uavklart"
}, },
"mediaRequests-requestStats": { "mediaRequests-requestStats": {
"name": "", "name": "Statistikk for mediaforespørsler",
"description": "Statistikk om dine medieforespørsler", "description": "Statistikk om dine medieforespørsler",
"option": {}, "option": {},
"titles": { "titles": {
@@ -1755,52 +1769,52 @@
"main": "Media statistikk", "main": "Media statistikk",
"approved": "Allerede godkjent", "approved": "Allerede godkjent",
"pending": "Venter på godkjenning", "pending": "Venter på godkjenning",
"processing": "", "processing": "Prosesseres",
"declined": "", "declined": "Allerede avslått",
"available": "", "available": "Allerede tilgjengelig",
"tv": "TV forespørsler", "tv": "TV forespørsler",
"movie": "Film forespørsler", "movie": "Film forespørsler",
"total": "Totalt" "total": "Totalt"
}, },
"users": { "users": {
"main": "Topp brukere", "main": "Topp brukere",
"requests": "" "requests": "Forespørsler"
} }
} }
}, },
"mediaTranscoding": { "mediaTranscoding": {
"name": "", "name": "Konvertering av medier",
"description": "", "description": "Statistikk, gjeldende kø- og arbeidstakerstatus på din media transkoding",
"option": { "option": {
"defaultView": { "defaultView": {
"label": "" "label": "Standardvisning"
}, },
"queuePageSize": { "queuePageSize": {
"label": "" "label": "Sidestørrelse i kø"
} }
}, },
"tab": { "tab": {
"workers": "", "workers": "Arbeidere",
"queue": "Kø", "queue": "Kø",
"statistics": "" "statistics": "Statistikk"
}, },
"currentIndex": "", "currentIndex": "{start}-{end} av {total}",
"healthCheck": { "healthCheck": {
"title": "", "title": "Helsesjekk",
"queued": "", "queued": "I kø",
"status": { "status": {
"healthy": "", "healthy": "Frisk",
"unhealthy": "" "unhealthy": "Ustabil"
} }
}, },
"panel": { "panel": {
"statistics": { "statistics": {
"empty": "Tøm", "empty": "Tøm",
"transcodes": "", "transcodes": "Transkoder",
"transcodesCount": "", "transcodesCount": "Transkoder: {value}",
"healthChecksCount": "", "healthChecksCount": "Helsesjekker: {value}",
"filesCount": "", "filesCount": "Filer: {value}",
"savedSpace": "", "savedSpace": "Diskplass spart: {value}",
"healthChecks": "", "healthChecks": "",
"videoCodecs": "", "videoCodecs": "",
"videoContainers": "", "videoContainers": "",
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "Temperatura w Fahrenheit" "label": "Temperatura w Fahrenheit"
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "Lokalizacja pogody" "label": "Lokalizacja pogody"
}, },
@@ -1391,6 +1398,13 @@
"description": "Jak powinna wyglądać data" "description": "Jak powinna wyglądać data"
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "Bezchmurnie", "clear": "Bezchmurnie",
"mainlyClear": "Częściowe zachmurzenie", "mainlyClear": "Częściowe zachmurzenie",
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "" "label": ""
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "Localização do tempo" "label": "Localização do tempo"
}, },
@@ -1391,6 +1398,13 @@
"description": "" "description": ""
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "Limpar", "clear": "Limpar",
"mainlyClear": "Principalmente claro", "mainlyClear": "Principalmente claro",
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "" "label": ""
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "Locație meteo" "label": "Locație meteo"
}, },
@@ -1391,6 +1398,13 @@
"description": "" "description": ""
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "Senin", "clear": "Senin",
"mainlyClear": "Parțial noros", "mainlyClear": "Parțial noros",
+19 -5
View File
@@ -153,10 +153,10 @@
"label": "Использовать индикаторы доступности" "label": "Использовать индикаторы доступности"
}, },
"defaultSearchEngine": { "defaultSearchEngine": {
"label": "" "label": "Поисковая система по умолчанию"
}, },
"openSearchInNewTab": { "openSearchInNewTab": {
"label": "" "label": "Открыть результаты поиска в новой вкладке"
} }
}, },
"error": { "error": {
@@ -219,10 +219,10 @@
"changeSearchPreferences": { "changeSearchPreferences": {
"notification": { "notification": {
"success": { "success": {
"message": "" "message": "Настройки поиска успешно изменены"
}, },
"error": { "error": {
"message": "" "message": "Не удается изменить настройки поиска"
} }
} }
}, },
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "Температура в градусах Фаренгейта" "label": "Температура в градусах Фаренгейта"
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "Местоположение" "label": "Местоположение"
}, },
@@ -1391,6 +1398,13 @@
"description": "Как должна отображаться дата" "description": "Как должна отображаться дата"
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "Ясно", "clear": "Ясно",
"mainlyClear": "Преимущественно ясно", "mainlyClear": "Преимущественно ясно",
@@ -2287,7 +2301,7 @@
"mobile": "Мобильная" "mobile": "Мобильная"
} }
}, },
"search": "", "search": "Поиск",
"firstDayOfWeek": "Первый день недели", "firstDayOfWeek": "Первый день недели",
"accessibility": "Специальные возможности" "accessibility": "Специальные возможности"
} }
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "Teplota vo stupňoch Fahrenheita" "label": "Teplota vo stupňoch Fahrenheita"
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "Poloha počasia" "label": "Poloha počasia"
}, },
@@ -1391,6 +1398,13 @@
"description": "Ako by mal dátum vyzerať" "description": "Ako by mal dátum vyzerať"
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "Jasno", "clear": "Jasno",
"mainlyClear": "Prevažne jasno", "mainlyClear": "Prevažne jasno",
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "" "label": ""
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "Lokacija vremena" "label": "Lokacija vremena"
}, },
@@ -1391,6 +1398,13 @@
"description": "" "description": ""
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "Počisti", "clear": "Počisti",
"mainlyClear": "Večinoma jasno", "mainlyClear": "Večinoma jasno",
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "" "label": ""
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "Plats för väder" "label": "Plats för väder"
}, },
@@ -1391,6 +1398,13 @@
"description": "" "description": ""
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "Klart", "clear": "Klart",
"mainlyClear": "Främst klart", "mainlyClear": "Främst klart",
+19 -5
View File
@@ -153,10 +153,10 @@
"label": "Pingler İçin Simgeler Kullanın" "label": "Pingler İçin Simgeler Kullanın"
}, },
"defaultSearchEngine": { "defaultSearchEngine": {
"label": "" "label": "Öntanımlı arama motoru"
}, },
"openSearchInNewTab": { "openSearchInNewTab": {
"label": "" "label": "Arama sonucunu yeni sekmede aç"
} }
}, },
"error": { "error": {
@@ -219,10 +219,10 @@
"changeSearchPreferences": { "changeSearchPreferences": {
"notification": { "notification": {
"success": { "success": {
"message": "" "message": "Arama tercihleri ​​başarıyla değiştirildi"
}, },
"error": { "error": {
"message": "" "message": "Arama tercihleri ​​değiştirilemiyor"
} }
} }
}, },
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "Fahrenheit cinsinden sıcaklık" "label": "Fahrenheit cinsinden sıcaklık"
}, },
"disableTemperatureDecimals": {
"label": "Sıcaklık ondalıklarını devre dışı bırak"
},
"showCurrentWindSpeed": {
"label": "Mevcut rüzgar hızını göster",
"description": "Yalnızca mevcut hava durumunda"
},
"location": { "location": {
"label": "Hava durumu konumu" "label": "Hava durumu konumu"
}, },
@@ -1391,6 +1398,13 @@
"description": "Tarihin nasıl görüneceği" "description": "Tarihin nasıl görüneceği"
} }
}, },
"currentWindSpeed": "{currentWindSpeed} km/s",
"dailyForecast": {
"sunrise": "Gün Doğumu",
"sunset": "Gün Batımı",
"maxWindSpeed": "Maks. Rüzgar Hızı: {maxWindSpeed} km/s",
"maxWindGusts": "Maks. Rüzgar Hamlesi: {maxWindGusts} km/h"
},
"kind": { "kind": {
"clear": "Temiz", "clear": "Temiz",
"mainlyClear": "Genel olarak açık", "mainlyClear": "Genel olarak açık",
@@ -2287,7 +2301,7 @@
"mobile": "Mobil" "mobile": "Mobil"
} }
}, },
"search": "", "search": "Ara",
"firstDayOfWeek": "Haftanın ilk günü", "firstDayOfWeek": "Haftanın ilk günü",
"accessibility": "Erişilebilirlik" "accessibility": "Erişilebilirlik"
} }
+94 -80
View File
@@ -153,10 +153,10 @@
"label": "Використовувати значки для ping" "label": "Використовувати значки для ping"
}, },
"defaultSearchEngine": { "defaultSearchEngine": {
"label": "" "label": "Стандартна система пошуку"
}, },
"openSearchInNewTab": { "openSearchInNewTab": {
"label": "" "label": "Відкрити результати пошуку в новій вкладці"
} }
}, },
"error": { "error": {
@@ -222,7 +222,7 @@
"message": "" "message": ""
}, },
"error": { "error": {
"message": "" "message": "Не вдалося змінити налаштування пошуку"
} }
} }
}, },
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "Температура за Фаренгейтом" "label": "Температура за Фаренгейтом"
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "Погодна локація" "label": "Погодна локація"
}, },
@@ -1391,6 +1398,13 @@
"description": "" "description": ""
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "Ясно", "clear": "Ясно",
"mainlyClear": "Здебільшого ясно", "mainlyClear": "Здебільшого ясно",
@@ -1575,8 +1589,8 @@
} }
}, },
"mediaServer": { "mediaServer": {
"name": "", "name": "Поточні потоки медіасервера",
"description": "", "description": "Показує поточні потоки з ваших медіасерверів",
"option": {}, "option": {},
"items": { "items": {
"user": "Користувач", "user": "Користувач",
@@ -1674,7 +1688,7 @@
}, },
"state": { "state": {
"columnTitle": "Стан", "columnTitle": "Стан",
"detailsTitle": "" "detailsTitle": "Стан"
}, },
"time": { "time": {
"columnTitle": "Час завершення", "columnTitle": "Час завершення",
@@ -1682,7 +1696,7 @@
}, },
"type": { "type": {
"columnTitle": "Тип", "columnTitle": "Тип",
"detailsTitle": "" "detailsTitle": "Тип клієнта"
}, },
"upSpeed": { "upSpeed": {
"columnTitle": "Віддача", "columnTitle": "Віддача",
@@ -1696,10 +1710,10 @@
"completed": "Завершено", "completed": "Завершено",
"failed": "Невдало", "failed": "Невдало",
"processing": "В обробці", "processing": "В обробці",
"leeching": "", "leeching": "Завантажується",
"stalled": "", "stalled": "",
"unknown": "Невідомо", "unknown": "Невідомо",
"seeding": "" "seeding": "Роздається"
}, },
"actions": { "actions": {
"clients": { "clients": {
@@ -1828,7 +1842,7 @@
} }
}, },
"rssFeed": { "rssFeed": {
"name": "", "name": "RSS-канали",
"description": "", "description": "",
"option": { "option": {
"feedUrls": { "feedUrls": {
@@ -2079,20 +2093,20 @@
"rename": { "rename": {
"label": "Перейменувати дошку", "label": "Перейменувати дошку",
"description": "", "description": "",
"button": "", "button": "Змінити назву",
"modal": { "modal": {
"title": "" "title": "Перейменувати дошку"
} }
}, },
"visibility": { "visibility": {
"label": "", "label": "Змінити видимість дошки",
"description": { "description": {
"public": "", "public": "Ця дошка є загальнодоступною.",
"private": "" "private": "Ця дошка є приватною."
}, },
"button": { "button": {
"public": "", "public": "Зробити приватною",
"private": "" "private": "Зробити загальнодоступною"
}, },
"confirm": { "confirm": {
"public": { "public": {
@@ -2281,13 +2295,13 @@
"item": { "item": {
"language": "Мова та Регіон", "language": "Мова та Регіон",
"board": { "board": {
"title": "", "title": "Домашня дошка",
"type": { "type": {
"general": "", "general": "",
"mobile": "" "mobile": "Мобільна"
} }
}, },
"search": "", "search": "Пошук",
"firstDayOfWeek": "Перший день тижня", "firstDayOfWeek": "Перший день тижня",
"accessibility": "Доступність" "accessibility": "Доступність"
} }
@@ -2304,11 +2318,11 @@
"title": "Користувачі" "title": "Користувачі"
}, },
"edit": { "edit": {
"metaTitle": "" "metaTitle": "Редагувати користувача {username}"
}, },
"create": { "create": {
"metaTitle": "Створити користувача", "metaTitle": "Створити користувача",
"title": "", "title": "Створити нового користувача",
"step": { "step": {
"personalInformation": { "personalInformation": {
"label": "" "label": ""
@@ -2317,23 +2331,23 @@
"label": "Безпека" "label": "Безпека"
}, },
"groups": { "groups": {
"label": "", "label": "Групи",
"title": "", "title": "Виберіть усі групи, учасником яких має бути користувач",
"description": "" "description": ""
}, },
"review": { "review": {
"label": "" "label": ""
}, },
"completed": { "completed": {
"title": "" "title": "Користувача створено"
}, },
"error": { "error": {
"title": "" "title": "Не вдалося створити користувача"
} }
}, },
"action": { "action": {
"createAnother": "", "createAnother": "Створити іншого користувача",
"back": "" "back": "Повернутися до списку користувачів"
} }
}, },
"invite": { "invite": {
@@ -2371,23 +2385,23 @@
} }
}, },
"group": { "group": {
"back": "", "back": "Назад до груп",
"setting": { "setting": {
"general": { "general": {
"title": "Загальне", "title": "Загальне",
"owner": "Власник", "owner": "Власник",
"ownerOfGroup": "", "ownerOfGroup": "Власник цієї групи",
"ownerOfGroupDeleted": "" "ownerOfGroupDeleted": "Власника цієї групи видалено. Наразі не має власника."
}, },
"members": { "members": {
"title": "", "title": "Учасники",
"search": "", "search": "Знайти учасника",
"notFound": "" "notFound": "Учасників не знайдено"
}, },
"permissions": { "permissions": {
"title": "", "title": "Дозволи",
"form": { "form": {
"unsavedChanges": "" "unsavedChanges": "У вас є незбережені зміни!"
} }
} }
} }
@@ -2477,7 +2491,7 @@
}, },
"tool": { "tool": {
"tasks": { "tasks": {
"title": "", "title": "Завдання",
"status": { "status": {
"idle": "", "idle": "",
"running": "Запущено", "running": "Запущено",
@@ -2485,13 +2499,13 @@
}, },
"job": { "job": {
"minecraftServerStatus": { "minecraftServerStatus": {
"label": "" "label": "Статус сервера Minecraft"
}, },
"iconsUpdater": { "iconsUpdater": {
"label": "" "label": ""
}, },
"analytics": { "analytics": {
"label": "" "label": "Аналітика"
}, },
"smartHomeEntityState": { "smartHomeEntityState": {
"label": "" "label": ""
@@ -2591,7 +2605,7 @@
"table": { "table": {
"updated": "Оновлено {when}", "updated": "Оновлено {when}",
"search": "", "search": "",
"selected": "" "selected": "Вибрано {selectCount} із {totalCount} контейнерів"
}, },
"field": { "field": {
"name": { "name": {
@@ -2852,25 +2866,25 @@
} }
}, },
"integration": { "integration": {
"title": "" "title": "Інтеграції"
} }
} }
}, },
"command": { "command": {
"help": "", "help": "Активувати командний режим",
"group": { "group": {
"localCommand": { "localCommand": {
"title": "" "title": "Локальні команди"
}, },
"globalCommand": { "globalCommand": {
"title": "", "title": "",
"option": { "option": {
"colorScheme": { "colorScheme": {
"light": "", "light": "Перемикнути на світлу тему",
"dark": "" "dark": "Перемикнути на темну тему"
}, },
"language": { "language": {
"label": "", "label": "Змінити мову",
"children": { "children": {
"detail": { "detail": {
"title": "" "title": ""
@@ -2881,53 +2895,53 @@
"label": "Створити нову дошку" "label": "Створити нову дошку"
}, },
"importBoard": { "importBoard": {
"label": "" "label": "Імпортувати дошку"
}, },
"newApp": { "newApp": {
"label": "" "label": "Створити новий додаток"
}, },
"newIntegration": { "newIntegration": {
"label": "", "label": "Створити нову інтеграцію",
"children": { "children": {
"detail": { "detail": {
"title": "" "title": "Виберіть тип інтеграції, який потрібно створити"
} }
} }
}, },
"newUser": { "newUser": {
"label": "" "label": "Створити нового користувача"
}, },
"newInvite": { "newInvite": {
"label": "Створити нове запрошення" "label": "Створити нове запрошення"
}, },
"newGroup": { "newGroup": {
"label": "" "label": "Створити нову групу"
} }
} }
} }
} }
}, },
"media": { "media": {
"requestMovie": "", "requestMovie": "Запросити фільм",
"requestSeries": "", "requestSeries": "Запросити серіал",
"openIn": "" "openIn": "Відкрити в {kind}"
}, },
"external": { "external": {
"help": "Використовувати зовнішню пошукову систему", "help": "Використовувати зовнішню пошукову систему",
"group": { "group": {
"searchEngine": { "searchEngine": {
"title": "", "title": "Пошукові системи",
"children": { "children": {
"action": { "action": {
"search": { "search": {
"label": "" "label": "Шукати з {name}"
} }
}, },
"detail": { "detail": {
"title": "" "title": "Виберіть дію для пошукової системи"
}, },
"searchResults": { "searchResults": {
"title": "" "title": "Виберіть результат пошуку для дій"
} }
}, },
"option": { "option": {
@@ -3053,7 +3067,7 @@
"label": "Про програму" "label": "Про програму"
}, },
"homeBoard": { "homeBoard": {
"label": "" "label": "Домашня дошка"
}, },
"preferences": { "preferences": {
"label": "Ваші уподобання" "label": "Ваші уподобання"
@@ -3139,21 +3153,21 @@
} }
}, },
"edit": { "edit": {
"title": "", "title": "Редагувати систему пошуку",
"notification": { "notification": {
"success": { "success": {
"title": "", "title": "Зміни успішно застосовано",
"message": "" "message": "Пошукову систему успішно збережено"
}, },
"error": { "error": {
"title": "", "title": "Не вдалося застосувати зміни",
"message": "" "message": "Не вдалося зберегти пошукову систему"
} }
}, },
"configControl": "", "configControl": "Конфігурація",
"searchEngineType": { "searchEngineType": {
"generic": "", "generic": "",
"fromIntegration": "" "fromIntegration": "З інтеграції"
} }
}, },
"delete": { "delete": {
@@ -3182,7 +3196,7 @@
} }
}, },
"button": { "button": {
"send": "" "send": "Надіслати запит"
} }
} }
} }
@@ -3195,36 +3209,36 @@
"title": "", "title": "",
"description": "", "description": "",
"noResults": { "noResults": {
"title": "" "title": "Сертифікати відсутні"
}, },
"expires": "" "expires": ""
} }
}, },
"action": { "action": {
"create": { "create": {
"label": "", "label": "Додати сертифікат",
"notification": { "notification": {
"success": { "success": {
"title": "", "title": "Додано сертифікат",
"message": "" "message": "Сертифікат було успішно додано"
}, },
"error": { "error": {
"title": "", "title": "Не вдалося додати сертифікат",
"message": "" "message": "Не вдалося додати сертифікат"
} }
} }
}, },
"remove": { "remove": {
"label": "", "label": "Видалити сертифікат",
"confirm": "", "confirm": "Ви впевнені, що хочете видалити сертифікат?",
"notification": { "notification": {
"success": { "success": {
"title": "", "title": "Сертифікат видалено",
"message": "" "message": "Сертифікат успішно видалено"
}, },
"error": { "error": {
"title": "", "title": "Сертификат не видалено",
"message": "" "message": "Не вдалося видалити сертифікат"
} }
} }
} }
+14
View File
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "" "label": ""
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "Vị trí thời tiết" "label": "Vị trí thời tiết"
}, },
@@ -1391,6 +1398,13 @@
"description": "" "description": ""
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "Quang đãng", "clear": "Quang đãng",
"mainlyClear": "Thông thoáng", "mainlyClear": "Thông thoáng",
+21 -7
View File
@@ -153,10 +153,10 @@
"label": "為 Pings 使用 icon" "label": "為 Pings 使用 icon"
}, },
"defaultSearchEngine": { "defaultSearchEngine": {
"label": "" "label": "預設搜尋引擎"
}, },
"openSearchInNewTab": { "openSearchInNewTab": {
"label": "" "label": "於新分頁中開啟搜尋結果"
} }
}, },
"error": { "error": {
@@ -219,10 +219,10 @@
"changeSearchPreferences": { "changeSearchPreferences": {
"notification": { "notification": {
"success": { "success": {
"message": "" "message": "搜尋設定更改成功"
}, },
"error": { "error": {
"message": "" "message": "無法更改搜尋設定"
} }
} }
}, },
@@ -1373,6 +1373,13 @@
"isFormatFahrenheit": { "isFormatFahrenheit": {
"label": "華氏溫度" "label": "華氏溫度"
}, },
"disableTemperatureDecimals": {
"label": ""
},
"showCurrentWindSpeed": {
"label": "",
"description": ""
},
"location": { "location": {
"label": "天氣位置" "label": "天氣位置"
}, },
@@ -1391,6 +1398,13 @@
"description": "日期應該是什麼樣式" "description": "日期應該是什麼樣式"
} }
}, },
"currentWindSpeed": "",
"dailyForecast": {
"sunrise": "",
"sunset": "",
"maxWindSpeed": "",
"maxWindGusts": ""
},
"kind": { "kind": {
"clear": "晴朗", "clear": "晴朗",
"mainlyClear": "大多晴朗", "mainlyClear": "大多晴朗",
@@ -1426,8 +1440,8 @@
"name": "系統健康監測", "name": "系統健康監測",
"description": "顯示系統運行狀態", "description": "顯示系統運行狀態",
"tab": { "tab": {
"system": "", "system": "系統",
"cluster": "" "cluster": "叢集"
}, },
"option": { "option": {
"fahrenheit": { "fahrenheit": {
@@ -2287,7 +2301,7 @@
"mobile": "移動裝置" "mobile": "移動裝置"
} }
}, },
"search": "", "search": "搜尋",
"firstDayOfWeek": "一周的第一天", "firstDayOfWeek": "一周的第一天",
"accessibility": "無障礙服務" "accessibility": "無障礙服務"
} }
@@ -9,12 +9,17 @@ export const atLocationOutput = z.object({
current_weather: z.object({ current_weather: z.object({
weathercode: z.number(), weathercode: z.number(),
temperature: z.number(), temperature: z.number(),
windspeed: z.number(),
}), }),
daily: z.object({ daily: z.object({
time: z.array(z.string()), time: z.array(z.string()),
weathercode: z.array(z.number()), weathercode: z.array(z.number()),
temperature_2m_max: z.array(z.number()), temperature_2m_max: z.array(z.number()),
temperature_2m_min: z.array(z.number()), temperature_2m_min: z.array(z.number()),
sunrise: z.array(z.string()),
sunset: z.array(z.string()),
wind_speed_10m_max: z.array(z.number()),
wind_gusts_10m_max: z.array(z.number()),
}), }),
}); });
+15 -15
View File
@@ -44,21 +44,21 @@
"@mantine/core": "^7.16.2", "@mantine/core": "^7.16.2",
"@mantine/hooks": "^7.16.2", "@mantine/hooks": "^7.16.2",
"@tabler/icons-react": "^3.29.0", "@tabler/icons-react": "^3.29.0",
"@tiptap/extension-color": "2.11.3", "@tiptap/extension-color": "2.11.5",
"@tiptap/extension-highlight": "2.11.3", "@tiptap/extension-highlight": "2.11.5",
"@tiptap/extension-image": "2.11.3", "@tiptap/extension-image": "2.11.5",
"@tiptap/extension-link": "^2.11.3", "@tiptap/extension-link": "^2.11.5",
"@tiptap/extension-table": "2.11.3", "@tiptap/extension-table": "2.11.5",
"@tiptap/extension-table-cell": "2.11.3", "@tiptap/extension-table-cell": "2.11.5",
"@tiptap/extension-table-header": "2.11.3", "@tiptap/extension-table-header": "2.11.5",
"@tiptap/extension-table-row": "2.11.3", "@tiptap/extension-table-row": "2.11.5",
"@tiptap/extension-task-item": "2.11.3", "@tiptap/extension-task-item": "2.11.5",
"@tiptap/extension-task-list": "2.11.3", "@tiptap/extension-task-list": "2.11.5",
"@tiptap/extension-text-align": "2.11.3", "@tiptap/extension-text-align": "2.11.5",
"@tiptap/extension-text-style": "2.11.3", "@tiptap/extension-text-style": "2.11.5",
"@tiptap/extension-underline": "2.11.3", "@tiptap/extension-underline": "2.11.5",
"@tiptap/react": "^2.11.3", "@tiptap/react": "^2.11.5",
"@tiptap/starter-kit": "^2.11.3", "@tiptap/starter-kit": "^2.11.5",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"dayjs": "^1.11.13", "dayjs": "^1.11.13",
"mantine-react-table": "2.0.0-beta.8", "mantine-react-table": "2.0.0-beta.8",
@@ -318,14 +318,15 @@ export const matchFileSystemAndSmart = (fileSystems: FileSystem[], smartData: Sm
const CpuRing = ({ cpuUtilization }: { cpuUtilization: number }) => { const CpuRing = ({ cpuUtilization }: { cpuUtilization: number }) => {
const { width, ref } = useElementSize(); const { width, ref } = useElementSize();
const fallbackWidth = width || 1; // See https://github.com/homarr-labs/homarr/issues/2196
return ( return (
<Box ref={ref} w="100%" h="100%" className="health-monitoring-cpu"> <Box ref={ref} w="100%" h="100%" className="health-monitoring-cpu">
<RingProgress <RingProgress
className="health-monitoring-cpu-utilization" className="health-monitoring-cpu-utilization"
roundCaps roundCaps
size={width * 0.95} size={fallbackWidth * 0.95}
thickness={width / 10} thickness={fallbackWidth / 10}
label={ label={
<Center style={{ flexDirection: "column" }}> <Center style={{ flexDirection: "column" }}>
<Text <Text
@@ -348,13 +349,14 @@ const CpuRing = ({ cpuUtilization }: { cpuUtilization: number }) => {
const CpuTempRing = ({ fahrenheit, cpuTemp }: { fahrenheit: boolean; cpuTemp: number }) => { const CpuTempRing = ({ fahrenheit, cpuTemp }: { fahrenheit: boolean; cpuTemp: number }) => {
const { width, ref } = useElementSize(); const { width, ref } = useElementSize();
const fallbackWidth = width || 1; // See https://github.com/homarr-labs/homarr/issues/2196
return ( return (
<Box ref={ref} w="100%" h="100%" className="health-monitoring-cpu-temperature"> <Box ref={ref} w="100%" h="100%" className="health-monitoring-cpu-temperature">
<RingProgress <RingProgress
className="health-monitoring-cpu-temp" className="health-monitoring-cpu-temp"
roundCaps roundCaps
size={width * 0.95} size={fallbackWidth * 0.95}
thickness={width / 10} thickness={fallbackWidth / 10}
label={ label={
<Center style={{ flexDirection: "column" }}> <Center style={{ flexDirection: "column" }}>
<Text className="health-monitoring-cpu-temp-value" size="3cqmin"> <Text className="health-monitoring-cpu-temp-value" size="3cqmin">
@@ -376,6 +378,7 @@ const CpuTempRing = ({ fahrenheit, cpuTemp }: { fahrenheit: boolean; cpuTemp: nu
const MemoryRing = ({ available, used }: { available: string; used: string }) => { const MemoryRing = ({ available, used }: { available: string; used: string }) => {
const { width, ref } = useElementSize(); const { width, ref } = useElementSize();
const fallbackWidth = width || 1; // See https://github.com/homarr-labs/homarr/issues/2196
const memoryUsage = formatMemoryUsage(available, used); const memoryUsage = formatMemoryUsage(available, used);
return ( return (
@@ -383,8 +386,8 @@ const MemoryRing = ({ available, used }: { available: string; used: string }) =>
<RingProgress <RingProgress
className="health-monitoring-memory-use" className="health-monitoring-memory-use"
roundCaps roundCaps
size={width * 0.95} size={fallbackWidth * 0.95}
thickness={width / 10} thickness={fallbackWidth / 10}
label={ label={
<Center style={{ flexDirection: "column" }}> <Center style={{ flexDirection: "column" }}>
<Text className="health-monitoring-memory-value" size="3cqmin"> <Text className="health-monitoring-memory-value" size="3cqmin">
+53 -10
View File
@@ -1,12 +1,13 @@
"use client"; "use client";
import { Box, Group, HoverCard, Space, Stack, Text } from "@mantine/core"; import { Box, Group, HoverCard, Space, Stack, Text } from "@mantine/core";
import { IconArrowDownRight, IconArrowUpRight, IconMapPin } from "@tabler/icons-react"; import { IconArrowDownRight, IconArrowUpRight, IconMapPin, IconWind } from "@tabler/icons-react";
import combineClasses from "clsx"; import combineClasses from "clsx";
import dayjs from "dayjs"; import dayjs from "dayjs";
import type { RouterOutputs } from "@homarr/api"; import type { RouterOutputs } from "@homarr/api";
import { clientApi } from "@homarr/api/client"; import { clientApi } from "@homarr/api/client";
import { useScopedI18n } from "@homarr/translation/client";
import type { WidgetComponentProps } from "../definition"; import type { WidgetComponentProps } from "../definition";
import { WeatherDescription, WeatherIcon } from "./icon"; import { WeatherDescription, WeatherIcon } from "./icon";
@@ -47,6 +48,7 @@ interface WeatherProps extends Pick<WidgetComponentProps<"weather">, "options">
} }
const DailyWeather = ({ options, weather }: WeatherProps) => { const DailyWeather = ({ options, weather }: WeatherProps) => {
const t = useScopedI18n("widget.weather");
return ( return (
<> <>
<Group className="weather-day-group" gap="1cqmin"> <Group className="weather-day-group" gap="1cqmin">
@@ -60,15 +62,32 @@ const DailyWeather = ({ options, weather }: WeatherProps) => {
<WeatherDescription weatherOnly weatherCode={weather.current.weathercode} /> <WeatherDescription weatherOnly weatherCode={weather.current.weathercode} />
</HoverCard.Dropdown> </HoverCard.Dropdown>
</HoverCard> </HoverCard>
<Text fz="17.5cqmin">{getPreferredUnit(weather.current.temperature, options.isFormatFahrenheit)}</Text> <Text fz="17.5cqmin">
{getPreferredUnit(
weather.current.temperature,
options.isFormatFahrenheit,
options.disableTemperatureDecimals,
)}
</Text>
</Group> </Group>
<Space h="1cqmin" /> <Space h="1cqmin" />
{options.showCurrentWindSpeed && (
<Group className="weather-current-wind-speed-group" wrap="nowrap" gap="1cqmin">
<IconWind size="12.5cqmin" />
<Text fz="10cqmin">{t("currentWindSpeed", { currentWindSpeed: weather.current.windspeed })}</Text>
</Group>
)}
<Space h="1cqmin" />
<Group className="weather-max-min-temp-group" wrap="nowrap" gap="1cqmin"> <Group className="weather-max-min-temp-group" wrap="nowrap" gap="1cqmin">
<IconArrowUpRight size="12.5cqmin" /> <IconArrowUpRight size="12.5cqmin" />
<Text fz="10cqmin">{getPreferredUnit(weather.daily[0]?.maxTemp, options.isFormatFahrenheit)}</Text> <Text fz="10cqmin">
{getPreferredUnit(weather.daily[0]?.maxTemp, options.isFormatFahrenheit, options.disableTemperatureDecimals)}
</Text>
<Space w="2.5cqmin" /> <Space w="2.5cqmin" />
<IconArrowDownRight size="12.5cqmin" /> <IconArrowDownRight size="12.5cqmin" />
<Text fz="10cqmin">{getPreferredUnit(weather.daily[0]?.minTemp, options.isFormatFahrenheit)}</Text> <Text fz="10cqmin">
{getPreferredUnit(weather.daily[0]?.minTemp, options.isFormatFahrenheit, options.disableTemperatureDecimals)}
</Text>
</Group> </Group>
{options.showCity && ( {options.showCity && (
<> <>
@@ -108,7 +127,13 @@ const WeeklyForecast = ({ options, weather }: WeatherProps) => {
<WeatherDescription weatherOnly weatherCode={weather.current.weathercode} /> <WeatherDescription weatherOnly weatherCode={weather.current.weathercode} />
</HoverCard.Dropdown> </HoverCard.Dropdown>
</HoverCard> </HoverCard>
<Text fz="20cqmin">{getPreferredUnit(weather.current.temperature, options.isFormatFahrenheit)}</Text> <Text fz="20cqmin">
{getPreferredUnit(
weather.current.temperature,
options.isFormatFahrenheit,
options.disableTemperatureDecimals,
)}
</Text>
</Group> </Group>
<Space h="2.5cqmin" /> <Space h="2.5cqmin" />
<Forecast weather={weather} options={options} /> <Forecast weather={weather} options={options} />
@@ -134,7 +159,9 @@ function Forecast({ weather, options }: WeatherProps) {
> >
<Text fz="10cqmin">{dayjs(dayWeather.time).format("dd")}</Text> <Text fz="10cqmin">{dayjs(dayWeather.time).format("dd")}</Text>
<WeatherIcon size="15cqmin" code={dayWeather.weatherCode} /> <WeatherIcon size="15cqmin" code={dayWeather.weatherCode} />
<Text fz="10cqmin">{getPreferredUnit(dayWeather.maxTemp, options.isFormatFahrenheit)}</Text> <Text fz="10cqmin">
{getPreferredUnit(dayWeather.maxTemp, options.isFormatFahrenheit, options.disableTemperatureDecimals)}
</Text>
</Stack> </Stack>
</HoverCard.Target> </HoverCard.Target>
<HoverCard.Dropdown> <HoverCard.Dropdown>
@@ -142,8 +169,20 @@ function Forecast({ weather, options }: WeatherProps) {
dateFormat={dateFormat} dateFormat={dateFormat}
time={dayWeather.time} time={dayWeather.time}
weatherCode={dayWeather.weatherCode} weatherCode={dayWeather.weatherCode}
maxTemp={getPreferredUnit(dayWeather.maxTemp, options.isFormatFahrenheit)} maxTemp={getPreferredUnit(
minTemp={getPreferredUnit(dayWeather.minTemp, options.isFormatFahrenheit)} dayWeather.maxTemp,
options.isFormatFahrenheit,
options.disableTemperatureDecimals,
)}
minTemp={getPreferredUnit(
dayWeather.minTemp,
options.isFormatFahrenheit,
options.disableTemperatureDecimals,
)}
sunrise={dayjs(dayWeather.sunrise).format("HH:mm")}
sunset={dayjs(dayWeather.sunset).format("HH:mm")}
maxWindSpeed={dayWeather.maxWindSpeed}
maxWindGusts={dayWeather.maxWindGusts}
/> />
</HoverCard.Dropdown> </HoverCard.Dropdown>
</HoverCard> </HoverCard>
@@ -152,5 +191,9 @@ function Forecast({ weather, options }: WeatherProps) {
); );
} }
const getPreferredUnit = (value?: number, isFahrenheit = false): string => const getPreferredUnit = (value?: number, isFahrenheit = false, disableTemperatureDecimals = false): string =>
value ? (isFahrenheit ? `${(value * (9 / 5) + 32).toFixed(1)}°F` : `${value.toFixed(1)}°C`) : "?"; value
? isFahrenheit
? `${(value * (9 / 5) + 32).toFixed(disableTemperatureDecimals ? 0 : 1)}°F`
: `${value.toFixed(disableTemperatureDecimals ? 0 : 1)}°C`
: "?";
+25 -3
View File
@@ -1,13 +1,17 @@
import { Stack, Text } from "@mantine/core"; import { List, Stack, Text } from "@mantine/core";
import { import {
IconCloud, IconCloud,
IconCloudFog, IconCloudFog,
IconCloudRain, IconCloudRain,
IconCloudSnow, IconCloudSnow,
IconCloudStorm, IconCloudStorm,
IconMoon,
IconQuestionMark, IconQuestionMark,
IconSnowflake, IconSnowflake,
IconSun, IconSun,
IconTemperatureMinus,
IconTemperaturePlus,
IconWind,
} from "@tabler/icons-react"; } from "@tabler/icons-react";
import dayjs from "dayjs"; import dayjs from "dayjs";
@@ -41,6 +45,10 @@ interface WeatherDescriptionProps {
weatherCode: number; weatherCode: number;
maxTemp?: string; maxTemp?: string;
minTemp?: string; minTemp?: string;
sunrise?: string;
sunset?: string;
maxWindSpeed?: number;
maxWindGusts?: number;
} }
/** /**
@@ -50,6 +58,10 @@ interface WeatherDescriptionProps {
* @param weatherCode weather code from api * @param weatherCode weather code from api
* @param maxTemp preformatted string for max temperature * @param maxTemp preformatted string for max temperature
* @param minTemp preformatted string for min temperature * @param minTemp preformatted string for min temperature
* @param sunrise preformatted string for sunrise time
* @param sunset preformatted string for sunset time
* @param maxWindSpeed maximum wind speed
* @param maxWindGusts maximum wind gusts
* @returns Content for a HoverCard dropdown presenting weather information * @returns Content for a HoverCard dropdown presenting weather information
*/ */
export const WeatherDescription = ({ export const WeatherDescription = ({
@@ -59,6 +71,10 @@ export const WeatherDescription = ({
weatherCode, weatherCode,
maxTemp, maxTemp,
minTemp, minTemp,
sunrise,
sunset,
maxWindSpeed,
maxWindGusts,
}: WeatherDescriptionProps) => { }: WeatherDescriptionProps) => {
const t = useScopedI18n("widget.weather"); const t = useScopedI18n("widget.weather");
const tCommon = useScopedI18n("common"); const tCommon = useScopedI18n("common");
@@ -73,8 +89,14 @@ export const WeatherDescription = ({
<Stack align="center" gap="0"> <Stack align="center" gap="0">
<Text fz="24px">{dayjs(time).format(dateFormat)}</Text> <Text fz="24px">{dayjs(time).format(dateFormat)}</Text>
<Text fz="16px">{t(`kind.${name}`)}</Text> <Text fz="16px">{t(`kind.${name}`)}</Text>
<Text fz="16px">{`${tCommon("information.max")}: ${maxTemp}`}</Text> <List>
<Text fz="16px">{`${tCommon("information.min")}: ${minTemp}`}</Text> <List.Item icon={<IconTemperaturePlus size={15} />}>{`${tCommon("information.max")}: ${maxTemp}`}</List.Item>
<List.Item icon={<IconTemperatureMinus size={15} />}>{`${tCommon("information.min")}: ${minTemp}`}</List.Item>
<List.Item icon={<IconSun size={15} />}>{`${t("dailyForecast.sunrise")}: ${sunrise}`}</List.Item>
<List.Item icon={<IconMoon size={15} />}>{`${t("dailyForecast.sunset")}: ${sunset}`}</List.Item>
<List.Item icon={<IconWind size={15} />}>{t("dailyForecast.maxWindSpeed", { maxWindSpeed })}</List.Item>
<List.Item icon={<IconWind size={15} />}>{t("dailyForecast.maxWindGusts", { maxWindGusts })}</List.Item>
</List>
</Stack> </Stack>
); );
}; };
+2
View File
@@ -10,6 +10,8 @@ export const { definition, componentLoader } = createWidgetDefinition("weather",
options: optionsBuilder.from( options: optionsBuilder.from(
(factory) => ({ (factory) => ({
isFormatFahrenheit: factory.switch(), isFormatFahrenheit: factory.switch(),
disableTemperatureDecimals: factory.switch(),
showCurrentWindSpeed: factory.switch({ withDescription: true }),
location: factory.location({ location: factory.location({
defaultValue: { defaultValue: {
name: "Paris", name: "Paris",
+738 -661
View File
File diff suppressed because it is too large. Load diff
+1 -1
View File
@@ -24,7 +24,7 @@
"eslint-plugin-jsx-a11y": "^6.10.2", "eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-react": "^7.37.4", "eslint-plugin-react": "^7.37.4",
"eslint-plugin-react-hooks": "^5.1.0", "eslint-plugin-react-hooks": "^5.1.0",
"typescript-eslint": "^8.21.0" "typescript-eslint": "^8.22.0"
}, },
"devDependencies": { "devDependencies": {
"@homarr/prettier-config": "workspace:^0.1.0", "@homarr/prettier-config": "workspace:^0.1.0",