mirror of
https://github.com/ajnart/homarr.git
synced 2026-03-06 20:30:57 +01:00
Merge pull request #1505 from ajnart/dev
Co-authored-by: Thomas Camlong <thomascamlong@gmail.com> Co-authored-by: Tagaishi <Tagaishi@hotmail.ch> Co-authored-by: Manuel <manuel.ruwe@bluewin.ch> Co-authored-by: Meier Lukas <meierschlumpf@gmail.com> Co-authored-by: Manuel <30572287+manuel-rw@users.noreply.github.com> Co-authored-by: Tobias Stadler <28538704+devtobi@users.noreply.github.com> Co-authored-by: Henry Skrtich <1214484+hskrtich@users.noreply.github.com> Co-authored-by: AuthorShin <a.saneie@yahoo.com> Co-authored-by: Diogo Valentim <diogovalentte10@gmail.com> Co-authored-by: Someone <10882916+InterN0te@users.noreply.github.com> Co-authored-by: Spillebulle <46653946+Spillebulle@users.noreply.github.com> Co-authored-by: Justijn Depover <justijndepover@gmail.com> Fix locale for calendar and clock (#1330) fix (#1375) close modal on click when opened (#1396) fix (#1401) fix: stop triming traling slashes (#1435) fixes #777 fix: trim media server url (#1438) Fix miscellaneous console errors (#1418) fixes (#1419) Fix tiptap url CVE (#1459) Fix allow guest issue (#1472) Fix the leading slash when adding container via docker (#1478)
This commit is contained in:
@@ -7,3 +7,7 @@ npm-debug.log
|
||||
.github
|
||||
LICENSE
|
||||
docs/
|
||||
*.sqlite
|
||||
*.env
|
||||
.env
|
||||
.next/standalone/.env
|
||||
14
.env.example
Normal file
14
.env.example
Normal file
@@ -0,0 +1,14 @@
|
||||
DATABASE_URL="file:./database/db.sqlite"
|
||||
|
||||
# Next Auth
|
||||
# You can generate a new secret on the command line with:
|
||||
# openssl rand -base64 32
|
||||
# https://next-auth.js.org/configuration/options#secret
|
||||
NEXTAUTH_URL="http://localhost:3000"
|
||||
|
||||
NEXTAUTH_SECRET="anything"
|
||||
|
||||
# Disable analytics
|
||||
NEXT_PUBLIC_DISABLE_ANALYTICS="true"
|
||||
|
||||
DEFAULT_COLOR_SCHEME="light"
|
||||
21
.github/renovate.json
vendored
Normal file
21
.github/renovate.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base"
|
||||
],
|
||||
"commitMessagePrefix": "⬆️",
|
||||
"dependencyDashboard": true,
|
||||
"prCreation": "approval",
|
||||
"lockFileMaintenance": {
|
||||
"automerge": false
|
||||
},
|
||||
"minor": {
|
||||
"automerge": false
|
||||
},
|
||||
"patch": {
|
||||
"automerge": false
|
||||
},
|
||||
"pin": {
|
||||
"automerge": false
|
||||
}
|
||||
}
|
||||
8
.github/workflows/docker.yml
vendored
8
.github/workflows/docker.yml
vendored
@@ -63,9 +63,9 @@ jobs:
|
||||
restore-keys: |
|
||||
${{ runner.os }}-nextjs-${{ hashFiles('**/package-lock.json') }}-
|
||||
|
||||
- run: yarn install --immutable
|
||||
- run: yarn install
|
||||
|
||||
- run: yarn build
|
||||
- run: yarn turbo build
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
@@ -83,6 +83,9 @@ jobs:
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
with:
|
||||
driver: docker
|
||||
buildkitd-flags: --debug
|
||||
|
||||
- name: Login to GHCR
|
||||
uses: docker/login-action@v2
|
||||
@@ -101,3 +104,4 @@ jobs:
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
network: host
|
||||
|
||||
10
.github/workflows/docker_dev.yml
vendored
10
.github/workflows/docker_dev.yml
vendored
@@ -41,6 +41,7 @@ jobs:
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
pull-requests: write
|
||||
steps:
|
||||
|
||||
- name: Setup
|
||||
@@ -70,11 +71,15 @@ jobs:
|
||||
path: .next/cache
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}
|
||||
|
||||
- run: yarn install --immutable
|
||||
- run: yarn install
|
||||
|
||||
- run: yarn turbo build
|
||||
|
||||
- run: yarn test:run
|
||||
- run: yarn test:coverage
|
||||
|
||||
- name: Report coverage
|
||||
if: always()
|
||||
uses: davelosert/vitest-coverage-report-action@v2
|
||||
|
||||
- name: Docker meta
|
||||
if: github.event_name != 'pull_request'
|
||||
@@ -114,3 +119,4 @@ jobs:
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
network: host
|
||||
|
||||
10
.gitignore
vendored
10
.gitignore
vendored
@@ -55,4 +55,12 @@ data/configs
|
||||
|
||||
#Languages other than 'en'
|
||||
public/locales/*
|
||||
!public/locales/en
|
||||
!public/locales/en
|
||||
|
||||
#database
|
||||
sqlite.db
|
||||
database/*.sqlite
|
||||
WILL_BE_OVERWRITTEN.sqlite
|
||||
|
||||
# IDE
|
||||
.idea/*
|
||||
21
.vscode/settings.json
vendored
Normal file
21
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"i18n-ally.localesPaths": "public/locales",
|
||||
"i18n-ally.enabledFrameworks": [
|
||||
"react-i18next"
|
||||
],
|
||||
"i18n-ally.namespace": true,
|
||||
"i18n-ally.pathMatcher": "{locale}/{namespaces}.json",
|
||||
"i18n-ally.keystyle": "nested",
|
||||
"i18n-ally.keysInUse": [
|
||||
"modules.**",
|
||||
"layout.manage.navigation.**",
|
||||
],
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.organizeImports": true
|
||||
},
|
||||
"typescript.tsdk": "node_modules/typescript/lib",
|
||||
"explorer.fileNesting.patterns": {
|
||||
"package.json": "pnpm-lock.yaml, yarn.lock, package-lock.json",
|
||||
"*.tsx": "${capture}.module.css"
|
||||
},
|
||||
}
|
||||
35
Dockerfile
35
Dockerfile
@@ -1,21 +1,46 @@
|
||||
FROM node:20-alpine
|
||||
FROM node:20.5-slim
|
||||
WORKDIR /app
|
||||
|
||||
# Define node.js environment variables
|
||||
ARG PORT=7575
|
||||
|
||||
ENV NEXT_TELEMETRY_DISABLED 1
|
||||
ENV NODE_ENV production
|
||||
ENV NODE_OPTIONS '--no-experimental-fetch'
|
||||
|
||||
COPY next.config.js ./
|
||||
COPY public ./public
|
||||
COPY package.json ./package.json
|
||||
|
||||
COPY package.json ./temp_package.json
|
||||
COPY yarn.lock ./temp_yarn.lock
|
||||
# Automatically leverage output traces to reduce image size
|
||||
# https://nextjs.org/docs/advanced-features/output-file-tracing
|
||||
COPY .next/standalone ./
|
||||
COPY .next/static ./.next/static
|
||||
COPY ./scripts/run.sh ./scripts/run.sh
|
||||
COPY ./drizzle ./drizzle
|
||||
RUN mkdir /data
|
||||
COPY ./src/migrate.ts ./src/migrate.ts
|
||||
|
||||
EXPOSE 7575
|
||||
# Install dependencies
|
||||
RUN apt-get update -y && apt-get install -y openssl wget
|
||||
|
||||
# Required for migration
|
||||
RUN mv node_modules _node_modules
|
||||
RUN rm package.json
|
||||
RUN yarn add typescript ts-node dotenv drizzle-orm@0.28.6 better-sqlite3@8.6.0 @types/better-sqlite3
|
||||
RUN mv node_modules node_modules_migrate
|
||||
RUN mv _node_modules node_modules
|
||||
|
||||
# Expose the default application port
|
||||
EXPOSE $PORT
|
||||
ENV PORT=${PORT}
|
||||
|
||||
ENV DATABASE_URL "file:/data/db.sqlite"
|
||||
ENV NEXTAUTH_URL "http://localhost:3000"
|
||||
ENV PORT 7575
|
||||
ENV NEXTAUTH_SECRET NOT_IN_USE_BECAUSE_JWTS_ARE_UNUSED
|
||||
|
||||
CMD ["node", "server.js"]
|
||||
HEALTHCHECK --interval=10s --timeout=5s --start-period=5s --retries=3 \
|
||||
CMD wget --no-verbose --tries=1 --spider http://localhost:${PORT} || exit 1
|
||||
|
||||
CMD ["sh", "./scripts/run.sh"]
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<a href="https://github.com/ajnart/homarr/actions/workflows/docker.yml">
|
||||
<img title="Docker CI Status" src="https://github.com/ajnart/homarr/actions/workflows/docker.yml/badge.svg" alt="CI Status">
|
||||
</a>
|
||||
<a href=https://crowdin.com/project/homarr>
|
||||
<a href=https://translate.homarr.dev/>
|
||||
<img title="Translations" src="https://badges.crowdin.net/homarr/localized.svg" />
|
||||
</a>
|
||||
<a href="https://discord.gg/aCsmEV5RgA">
|
||||
@@ -28,7 +28,7 @@
|
||||
<a href="https://homarr.dev/docs/introduction/installation">
|
||||
<strong>Install 💻</strong>
|
||||
</a> •
|
||||
<a href="https://crowdin.com/project/homarr">
|
||||
<a href="https://translate.homarr.dev/">
|
||||
<strong>Translations 🈺</strong>
|
||||
</a> •
|
||||
<a href="https://discord.com/invite/aCsmEV5RgA">
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
project_id: "534422"
|
||||
api_token_env: "CROWDIN_PERSONAL_TOKEN"
|
||||
files:
|
||||
- source: /public/locales/en/**/*.json
|
||||
translation: /public/locales/%two_letters_code%/**/%original_file_name%
|
||||
|
||||
@@ -270,52 +270,6 @@
|
||||
}
|
||||
],
|
||||
"widgets": [
|
||||
{
|
||||
"id": "86b1921f-efa7-410f-92dd-79553bf3264d",
|
||||
"type": "notebook",
|
||||
"properties": {
|
||||
"showToolbar": true,
|
||||
"content": "<h2><strong>Homarr's</strong> notebook</h2><p>Use it as your Todo list, ideas to think about, as a \"getting-started\" guide for your users or even as your secret journal to confess your crushes, it stays private our your <strong>Homarr</strong> instance.</p><p>The <code>notebook</code> widget focuses on usability and is designed to be as simple as possible to bring a familiar editing experience to regular users. It is based on <a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://tiptap.dev/\">Tiptap.dev</a> and supports all of its features:</p><ul><li><p>General text formatting: <strong>bold</strong>, <em>italic</em>, underline, <s>strike-through</s></p></li><li><p>Headings (h1-h6)</p></li><li><p>Sub and super scripts (<sup /> and <sub /> tags)</p></li><li><p>Ordered and bullet lists</p></li><li><p>Text align</p></li></ul>"
|
||||
},
|
||||
"area": {
|
||||
"type": "wrapper",
|
||||
"properties": {
|
||||
"id": "default"
|
||||
}
|
||||
},
|
||||
"shape": {
|
||||
"sm": {
|
||||
"location": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"size": {
|
||||
"width": 3,
|
||||
"height": 2
|
||||
}
|
||||
},
|
||||
"md": {
|
||||
"location": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"size": {
|
||||
"width": 3,
|
||||
"height": 4
|
||||
}
|
||||
},
|
||||
"lg": {
|
||||
"location": {
|
||||
"x": 0,
|
||||
"y": 1
|
||||
},
|
||||
"size": {
|
||||
"width": 6,
|
||||
"height": 3
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "e3004052-6b83-480e-b458-56e8ccdca5f0",
|
||||
"type": "weather",
|
||||
@@ -472,6 +426,52 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "86b1921f-efa7-410f-92dd-79553bf3264d",
|
||||
"type": "notebook",
|
||||
"properties": {
|
||||
"showToolbar": true,
|
||||
"content": "<h2><strong>Welcome to Homarr 🚀👋</strong></h2><p>We're glad that you're here! Homarr is a <em>modern </em>and <em>easy to use</em> dashboard that helps you to <strong>organize and manage</strong> your home network from one place. Control is <strong>at your fingertips</strong>.</p><p>We recommend you to read the <a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://homarr.dev/docs/introduction/after-the-installation\">getting started guide</a> first. To edit this board you must enter the edit mode - only administrators can do this. Adding an app is the first step you should take. You can do this by clicking the <code>Add tile</code> button at the top right and select <code>App</code>. After you provided an internal URL, external URL and selected an icon you can drag it around when holding down the left mouse button. Make it bigger or smaller using the drag icon at the bottom right. When you're happy with it's position, you <strong>must exit edit mode to save your board</strong>. Adding widgets works the same way but may require additional configuration - read the documentation for more information.</p><p>To remove this widget, you must log in to your administrator account and click on the menu to delete it.</p><p><strong><u>Your TODO list:</u></strong></p><ul data-type=\"taskList\"><li data-checked=\"false\" data-type=\"taskItem\"><label><input type=\"checkbox\"><span></span></label><div><p>Read the <a target=\"_blank\" rel=\"noopener noreferrer nofollow\" href=\"https://homarr.dev\">documentation</a></p></div></li><li data-checked=\"false\" data-type=\"taskItem\"><label><input type=\"checkbox\"><span></span></label><div><p>Add your <em>first app</em></p></div></li><li data-checked=\"false\" data-type=\"taskItem\"><label><input type=\"checkbox\"><span></span></label><div><p><em>Resize </em>and <em>drag</em> your app to a different position</p></div></li><li data-checked=\"false\" data-type=\"taskItem\"><label><input type=\"checkbox\"><span></span></label><div><p>Add the <em>clock widget</em> to your dashboard</p></div></li><li data-checked=\"false\" data-type=\"taskItem\"><label><input type=\"checkbox\"><span></span></label><div><p>Create a <em>new user</em></p></div></li></ul>"
|
||||
},
|
||||
"area": {
|
||||
"type": "wrapper",
|
||||
"properties": {
|
||||
"id": "default"
|
||||
}
|
||||
},
|
||||
"shape": {
|
||||
"sm": {
|
||||
"location": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"size": {
|
||||
"width": 3,
|
||||
"height": 2
|
||||
}
|
||||
},
|
||||
"md": {
|
||||
"location": {
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"size": {
|
||||
"width": 3,
|
||||
"height": 4
|
||||
}
|
||||
},
|
||||
"lg": {
|
||||
"location": {
|
||||
"x": 0,
|
||||
"y": 1
|
||||
},
|
||||
"size": {
|
||||
"width": 6,
|
||||
"height": 3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
@@ -505,6 +505,9 @@
|
||||
"columnCountMedium": 6,
|
||||
"columnCountLarge": 10
|
||||
}
|
||||
},
|
||||
"access": {
|
||||
"allowGuests": false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,4 @@
|
||||
export const REPO_URL = 'ajnart/homarr';
|
||||
export const ICON_PICKER_SLICE_LIMIT = 36;
|
||||
export const COOKIE_LOCALE_KEY = 'config-locale';
|
||||
export const COOKIE_COLOR_SCHEME_KEY = 'color-scheme';
|
||||
|
||||
2732
data/crowdin-report.json
Normal file
2732
data/crowdin-report.json
Normal file
File diff suppressed because it is too large
Load Diff
0
database/.gitkeep
Normal file
0
database/.gitkeep
Normal file
11
drizzle.config.ts
Normal file
11
drizzle.config.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import 'dotenv';
|
||||
import { type Config } from 'drizzle-kit';
|
||||
|
||||
export default {
|
||||
schema: './src/server/db/schema.ts',
|
||||
driver: 'better-sqlite',
|
||||
out: './drizzle',
|
||||
dbCredentials: {
|
||||
url: process.env.DATABASE_URL!,
|
||||
},
|
||||
} satisfies Config;
|
||||
69
drizzle/0000_supreme_the_captain.sql
Normal file
69
drizzle/0000_supreme_the_captain.sql
Normal file
@@ -0,0 +1,69 @@
|
||||
CREATE TABLE `account` (
|
||||
`userId` text NOT NULL,
|
||||
`type` text NOT NULL,
|
||||
`provider` text NOT NULL,
|
||||
`providerAccountId` text NOT NULL,
|
||||
`refresh_token` text,
|
||||
`access_token` text,
|
||||
`expires_at` integer,
|
||||
`token_type` text,
|
||||
`scope` text,
|
||||
`id_token` text,
|
||||
`session_state` text,
|
||||
PRIMARY KEY(`provider`, `providerAccountId`),
|
||||
FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `invite` (
|
||||
`id` text PRIMARY KEY NOT NULL,
|
||||
`token` text NOT NULL,
|
||||
`expires` integer NOT NULL,
|
||||
`created_by_id` text NOT NULL,
|
||||
FOREIGN KEY (`created_by_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `session` (
|
||||
`sessionToken` text PRIMARY KEY NOT NULL,
|
||||
`userId` text NOT NULL,
|
||||
`expires` integer NOT NULL,
|
||||
FOREIGN KEY (`userId`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `user_setting` (
|
||||
`id` text PRIMARY KEY NOT NULL,
|
||||
`user_id` text NOT NULL,
|
||||
`color_scheme` text DEFAULT 'environment' NOT NULL,
|
||||
`language` text DEFAULT 'en' NOT NULL,
|
||||
`default_board` text DEFAULT 'default' NOT NULL,
|
||||
`first_day_of_week` text DEFAULT 'monday' NOT NULL,
|
||||
`search_template` text DEFAULT 'https://google.com/search?q=%s' NOT NULL,
|
||||
`open_search_in_new_tab` integer DEFAULT true NOT NULL,
|
||||
`disable_ping_pulse` integer DEFAULT false NOT NULL,
|
||||
`replace_ping_with_icons` integer DEFAULT false NOT NULL,
|
||||
`use_debug_language` integer DEFAULT false NOT NULL,
|
||||
`auto_focus_search` integer DEFAULT false NOT NULL,
|
||||
FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ON UPDATE no action ON DELETE cascade
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `user` (
|
||||
`id` text PRIMARY KEY NOT NULL,
|
||||
`name` text,
|
||||
`email` text,
|
||||
`emailVerified` integer,
|
||||
`image` text,
|
||||
`password` text,
|
||||
`salt` text,
|
||||
`is_admin` integer DEFAULT false NOT NULL,
|
||||
`is_owner` integer DEFAULT false NOT NULL
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE TABLE `verificationToken` (
|
||||
`identifier` text NOT NULL,
|
||||
`token` text NOT NULL,
|
||||
`expires` integer NOT NULL,
|
||||
PRIMARY KEY(`identifier`, `token`)
|
||||
);
|
||||
--> statement-breakpoint
|
||||
CREATE INDEX `userId_idx` ON `account` (`userId`);--> statement-breakpoint
|
||||
CREATE UNIQUE INDEX `invite_token_unique` ON `invite` (`token`);--> statement-breakpoint
|
||||
CREATE INDEX `user_id_idx` ON `session` (`userId`);
|
||||
468
drizzle/meta/0000_snapshot.json
Normal file
468
drizzle/meta/0000_snapshot.json
Normal file
@@ -0,0 +1,468 @@
|
||||
{
|
||||
"version": "5",
|
||||
"dialect": "sqlite",
|
||||
"id": "32c1bc91-e69f-4e1d-b53c-9c43f2e6c9d3",
|
||||
"prevId": "00000000-0000-0000-0000-000000000000",
|
||||
"tables": {
|
||||
"account": {
|
||||
"name": "account",
|
||||
"columns": {
|
||||
"userId": {
|
||||
"name": "userId",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"type": {
|
||||
"name": "type",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"provider": {
|
||||
"name": "provider",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"providerAccountId": {
|
||||
"name": "providerAccountId",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"refresh_token": {
|
||||
"name": "refresh_token",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"access_token": {
|
||||
"name": "access_token",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"expires_at": {
|
||||
"name": "expires_at",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"token_type": {
|
||||
"name": "token_type",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"scope": {
|
||||
"name": "scope",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"id_token": {
|
||||
"name": "id_token",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"session_state": {
|
||||
"name": "session_state",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"userId_idx": {
|
||||
"name": "userId_idx",
|
||||
"columns": [
|
||||
"userId"
|
||||
],
|
||||
"isUnique": false
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"account_userId_user_id_fk": {
|
||||
"name": "account_userId_user_id_fk",
|
||||
"tableFrom": "account",
|
||||
"tableTo": "user",
|
||||
"columnsFrom": [
|
||||
"userId"
|
||||
],
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {
|
||||
"account_provider_providerAccountId_pk": {
|
||||
"columns": [
|
||||
"provider",
|
||||
"providerAccountId"
|
||||
]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"invite": {
|
||||
"name": "invite",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"token": {
|
||||
"name": "token",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"expires": {
|
||||
"name": "expires",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"created_by_id": {
|
||||
"name": "created_by_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"invite_token_unique": {
|
||||
"name": "invite_token_unique",
|
||||
"columns": [
|
||||
"token"
|
||||
],
|
||||
"isUnique": true
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"invite_created_by_id_user_id_fk": {
|
||||
"name": "invite_created_by_id_user_id_fk",
|
||||
"tableFrom": "invite",
|
||||
"tableTo": "user",
|
||||
"columnsFrom": [
|
||||
"created_by_id"
|
||||
],
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"session": {
|
||||
"name": "session",
|
||||
"columns": {
|
||||
"sessionToken": {
|
||||
"name": "sessionToken",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"userId": {
|
||||
"name": "userId",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"expires": {
|
||||
"name": "expires",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {
|
||||
"user_id_idx": {
|
||||
"name": "user_id_idx",
|
||||
"columns": [
|
||||
"userId"
|
||||
],
|
||||
"isUnique": false
|
||||
}
|
||||
},
|
||||
"foreignKeys": {
|
||||
"session_userId_user_id_fk": {
|
||||
"name": "session_userId_user_id_fk",
|
||||
"tableFrom": "session",
|
||||
"tableTo": "user",
|
||||
"columnsFrom": [
|
||||
"userId"
|
||||
],
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"user_setting": {
|
||||
"name": "user_setting",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"user_id": {
|
||||
"name": "user_id",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"color_scheme": {
|
||||
"name": "color_scheme",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "'environment'"
|
||||
},
|
||||
"language": {
|
||||
"name": "language",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "'en'"
|
||||
},
|
||||
"default_board": {
|
||||
"name": "default_board",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "'default'"
|
||||
},
|
||||
"first_day_of_week": {
|
||||
"name": "first_day_of_week",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "'monday'"
|
||||
},
|
||||
"search_template": {
|
||||
"name": "search_template",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": "'https://google.com/search?q=%s'"
|
||||
},
|
||||
"open_search_in_new_tab": {
|
||||
"name": "open_search_in_new_tab",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": true
|
||||
},
|
||||
"disable_ping_pulse": {
|
||||
"name": "disable_ping_pulse",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": false
|
||||
},
|
||||
"replace_ping_with_icons": {
|
||||
"name": "replace_ping_with_icons",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": false
|
||||
},
|
||||
"use_debug_language": {
|
||||
"name": "use_debug_language",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": false
|
||||
},
|
||||
"auto_focus_search": {
|
||||
"name": "auto_focus_search",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {
|
||||
"user_setting_user_id_user_id_fk": {
|
||||
"name": "user_setting_user_id_user_id_fk",
|
||||
"tableFrom": "user_setting",
|
||||
"tableTo": "user",
|
||||
"columnsFrom": [
|
||||
"user_id"
|
||||
],
|
||||
"columnsTo": [
|
||||
"id"
|
||||
],
|
||||
"onDelete": "cascade",
|
||||
"onUpdate": "no action"
|
||||
}
|
||||
},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"user": {
|
||||
"name": "user",
|
||||
"columns": {
|
||||
"id": {
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"primaryKey": true,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"name": {
|
||||
"name": "name",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"email": {
|
||||
"name": "email",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"emailVerified": {
|
||||
"name": "emailVerified",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"image": {
|
||||
"name": "image",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"password": {
|
||||
"name": "password",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"salt": {
|
||||
"name": "salt",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": false,
|
||||
"autoincrement": false
|
||||
},
|
||||
"is_admin": {
|
||||
"name": "is_admin",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": false
|
||||
},
|
||||
"is_owner": {
|
||||
"name": "is_owner",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false,
|
||||
"default": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {},
|
||||
"uniqueConstraints": {}
|
||||
},
|
||||
"verificationToken": {
|
||||
"name": "verificationToken",
|
||||
"columns": {
|
||||
"identifier": {
|
||||
"name": "identifier",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"token": {
|
||||
"name": "token",
|
||||
"type": "text",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
},
|
||||
"expires": {
|
||||
"name": "expires",
|
||||
"type": "integer",
|
||||
"primaryKey": false,
|
||||
"notNull": true,
|
||||
"autoincrement": false
|
||||
}
|
||||
},
|
||||
"indexes": {},
|
||||
"foreignKeys": {},
|
||||
"compositePrimaryKeys": {
|
||||
"verificationToken_identifier_token_pk": {
|
||||
"columns": [
|
||||
"identifier",
|
||||
"token"
|
||||
]
|
||||
}
|
||||
},
|
||||
"uniqueConstraints": {}
|
||||
}
|
||||
},
|
||||
"enums": {},
|
||||
"_meta": {
|
||||
"schemas": {},
|
||||
"tables": {},
|
||||
"columns": {}
|
||||
}
|
||||
}
|
||||
13
drizzle/meta/_journal.json
Normal file
13
drizzle/meta/_journal.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"version": "5",
|
||||
"dialect": "sqlite",
|
||||
"entries": [
|
||||
{
|
||||
"idx": 0,
|
||||
"version": "5",
|
||||
"when": 1695874816934,
|
||||
"tag": "0000_supreme_the_captain",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
1
next-env.d.ts
vendored
1
next-env.d.ts
vendored
@@ -1,6 +1,5 @@
|
||||
/// <reference types="next" />
|
||||
/// <reference types="next/image-types/global" />
|
||||
/// <reference types="next/navigation-types/compat/navigation" />
|
||||
|
||||
// NOTE: This file should not be edited
|
||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||
|
||||
@@ -5,35 +5,37 @@ module.exports = {
|
||||
i18n: {
|
||||
defaultLocale: 'en',
|
||||
locales: [
|
||||
'en',
|
||||
'cn',
|
||||
'cr',
|
||||
'cs',
|
||||
'da',
|
||||
'he',
|
||||
'de',
|
||||
'el',
|
||||
'en',
|
||||
'es',
|
||||
'fr',
|
||||
'he',
|
||||
'hr',
|
||||
'hu',
|
||||
'it',
|
||||
'ja',
|
||||
'ko',
|
||||
'lol',
|
||||
'lv',
|
||||
'nl',
|
||||
'no',
|
||||
'pl',
|
||||
'pt',
|
||||
'ru',
|
||||
'sk',
|
||||
'sl',
|
||||
'sv',
|
||||
'vi',
|
||||
'uk',
|
||||
'zh',
|
||||
'el',
|
||||
'sk',
|
||||
'no',
|
||||
'tr',
|
||||
'lv',
|
||||
'hu',
|
||||
'hr'
|
||||
'tw',
|
||||
'uk',
|
||||
'vi',
|
||||
],
|
||||
|
||||
localeDetection: true,
|
||||
localeDetection: false,
|
||||
},
|
||||
returnEmptyString: false,
|
||||
appendNamespaceToCIMode: true,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
require('./src/env');
|
||||
const { i18n } = require('./next-i18next.config');
|
||||
|
||||
const withBundleAnalyzer = require('@next/bundle-analyzer')({
|
||||
@@ -12,4 +13,14 @@ module.exports = withBundleAnalyzer({
|
||||
output: 'standalone',
|
||||
i18n,
|
||||
transpilePackages: ['@jellyfin/sdk'],
|
||||
redirects: async () => [
|
||||
{
|
||||
source: '/',
|
||||
destination: '/board',
|
||||
permanent: false,
|
||||
},
|
||||
],
|
||||
env: {
|
||||
NEXTAUTH_URL_INTERNAL: process.env.NEXTAUTH_URL_INTERNAL || process.env.HOSTNAME || 'http://localhost:3000'
|
||||
},
|
||||
});
|
||||
|
||||
98
package.json
98
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "homarr",
|
||||
"version": "0.13.4",
|
||||
"version": "0.14.0",
|
||||
"description": "Homarr - A homepage for your server.",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
@@ -9,23 +9,25 @@
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
"build": "next build",
|
||||
"build": "NEXTAUTH_SECRET=WILL_BE_OVERWRITTEN next build",
|
||||
"analyze": "ANALYZE=true next build",
|
||||
"turbo": "turbo run build",
|
||||
"turbo": "DATABASE_URL=file:WILL_BE_OVERWRITTEN.sqlite NEXTAUTH_URL=http://WILL_BE_OVERWRITTEN turbo build",
|
||||
"start": "next start",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"export": "next build && next export",
|
||||
"lint": "next lint",
|
||||
"prettier:check": "prettier --check \"**/*.{ts,tsx}\"",
|
||||
"prettier:write": "prettier --write \"**/*.{ts,tsx}\"",
|
||||
"test": "vitest",
|
||||
"test:ui": "vitest --ui",
|
||||
"test:run": "vitest run",
|
||||
"test:coverage": "vitest run --coverage",
|
||||
"docker:build": "turbo build && docker build . -t homarr:dev",
|
||||
"docker:start": "docker run --env-file ./.env -p 7575:7575 homarr:dev "
|
||||
"test": "SKIP_ENV_VALIDATION=1 vitest",
|
||||
"test:ui": "SKIP_ENV_VALIDATION=1 vitest --ui",
|
||||
"test:run": "SKIP_ENV_VALIDATION=1 vitest run",
|
||||
"test:coverage": "SKIP_ENV_VALIDATION=1 vitest run --coverage",
|
||||
"docker:build": "turbo build && docker build . -t homarr:local-dev",
|
||||
"docker:start": "docker run -p 7575:7575 --name homarr-development homarr:local-dev",
|
||||
"db:migrate": "ts-node src/migrate.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@auth/drizzle-adapter": "^0.3.2",
|
||||
"@ctrl/deluge": "^4.1.0",
|
||||
"@ctrl/qbittorrent": "^6.0.0",
|
||||
"@ctrl/shared-torrent": "^4.1.1",
|
||||
@@ -35,45 +37,63 @@
|
||||
"@jellyfin/sdk": "^0.8.0",
|
||||
"@mantine/core": "^6.0.0",
|
||||
"@mantine/dates": "^6.0.0",
|
||||
"@mantine/dropzone": "^6.0.0",
|
||||
"@mantine/form": "^6.0.0",
|
||||
"@mantine/hooks": "^6.0.0",
|
||||
"@mantine/modals": "^6.0.0",
|
||||
"@mantine/next": "^6.0.0",
|
||||
"@mantine/notifications": "^6.0.0",
|
||||
"@mantine/prism": "^6.0.19",
|
||||
"@mantine/tiptap": "^6.0.17",
|
||||
"@nivo/core": "^0.83.0",
|
||||
"@nivo/line": "^0.83.0",
|
||||
"@react-native-async-storage/async-storage": "^1.18.1",
|
||||
"@t3-oss/env-nextjs": "^0.7.1",
|
||||
"@tabler/icons-react": "^2.20.0",
|
||||
"@tanstack/query-async-storage-persister": "^4.27.1",
|
||||
"@tanstack/query-sync-storage-persister": "^4.27.1",
|
||||
"@tanstack/react-query": "^4.2.1",
|
||||
"@tanstack/react-query-devtools": "^4.24.4",
|
||||
"@tanstack/react-query-persist-client": "^4.28.0",
|
||||
"@tiptap/extension-link": "^2.0.4",
|
||||
"@tiptap/pm": "^2.0.4",
|
||||
"@tiptap/react": "^2.0.4",
|
||||
"@tiptap/starter-kit": "^2.0.4",
|
||||
"@trpc/client": "^10.29.1",
|
||||
"@trpc/next": "^10.29.1",
|
||||
"@trpc/react-query": "^10.29.1",
|
||||
"@trpc/server": "^10.29.1",
|
||||
"@tiptap/extension-color": "^2.1.12",
|
||||
"@tiptap/extension-highlight": "^2.1.12",
|
||||
"@tiptap/extension-image": "^2.1.12",
|
||||
"@tiptap/extension-link": "^2.1.12",
|
||||
"@tiptap/extension-table": "^2.1.12",
|
||||
"@tiptap/extension-table-cell": "^2.1.12",
|
||||
"@tiptap/extension-table-header": "^2.1.12",
|
||||
"@tiptap/extension-table-row": "^2.1.12",
|
||||
"@tiptap/extension-task-item": "^2.1.12",
|
||||
"@tiptap/extension-task-list": "^2.1.12",
|
||||
"@tiptap/extension-text-align": "^2.1.12",
|
||||
"@tiptap/extension-text-style": "^2.1.12",
|
||||
"@tiptap/extension-underline": "^2.1.12",
|
||||
"@tiptap/pm": "^2.1.12",
|
||||
"@tiptap/react": "^2.1.12",
|
||||
"@tiptap/starter-kit": "^2.1.12",
|
||||
"@trpc/client": "^10.37.1",
|
||||
"@trpc/next": "^10.37.1",
|
||||
"@trpc/react-query": "^10.37.1",
|
||||
"@trpc/server": "^10.37.1",
|
||||
"@types/bcryptjs": "^2.4.2",
|
||||
"@vitejs/plugin-react": "^4.0.0",
|
||||
"axios": "^1.0.0",
|
||||
"bcryptjs": "^2.4.3",
|
||||
"better-sqlite3": "^8.6.0",
|
||||
"browser-geo-tz": "^0.0.4",
|
||||
"consola": "^3.0.0",
|
||||
"cookies": "^0.8.0",
|
||||
"cookies-next": "^2.1.1",
|
||||
"dayjs": "^1.11.7",
|
||||
"dockerode": "^3.3.2",
|
||||
"dotenv": "^16.3.1",
|
||||
"drizzle-kit": "^0.19.13",
|
||||
"drizzle-orm": "^0.28.6",
|
||||
"fily-publish-gridstack": "^0.0.13",
|
||||
"flag-icons": "^6.9.2",
|
||||
"framer-motion": "^10.0.0",
|
||||
"generate-password": "^1.7.0",
|
||||
"html-entities": "^2.3.3",
|
||||
"i18next": "^22.5.1",
|
||||
"immer": "^10.0.2",
|
||||
"js-file-download": "^0.4.12",
|
||||
"next": "13.4.12",
|
||||
"next-i18next": "^13.0.0",
|
||||
"next-auth": "^4.23.0",
|
||||
"next-i18next": "^14.0.0",
|
||||
"nzbget-api": "^0.0.3",
|
||||
"prismjs": "^1.29.0",
|
||||
"react": "^18.2.0",
|
||||
@@ -91,19 +111,22 @@
|
||||
"devDependencies": {
|
||||
"@next/bundle-analyzer": "^13.0.0",
|
||||
"@next/eslint-plugin-next": "^13.4.5",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^14.0.0",
|
||||
"@trivago/prettier-plugin-sort-imports": "^4.2.0",
|
||||
"@types/better-sqlite3": "^7.6.5",
|
||||
"@types/cookies": "^0.7.7",
|
||||
"@types/dockerode": "^3.3.9",
|
||||
"@types/node": "18.17.8",
|
||||
"@types/prismjs": "^1.26.0",
|
||||
"@types/react": "^18.2.11",
|
||||
"@types/umami": "^0.1.4",
|
||||
"@types/uuid": "^9.0.0",
|
||||
"@types/video.js": "^7.3.51",
|
||||
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
||||
"@typescript-eslint/parser": "^6.0.0",
|
||||
"@vitest/coverage-c8": "^0.33.0",
|
||||
"@vitest/ui": "^0.33.0",
|
||||
"@vitest/coverage-v8": "^0.34.5",
|
||||
"@vitest/ui": "^0.34.4",
|
||||
"eslint": "^8.0.1",
|
||||
"eslint-config-next": "^13.4.5",
|
||||
"eslint-plugin-promise": "^6.0.0",
|
||||
@@ -117,8 +140,8 @@
|
||||
"prettier": "^3.0.0",
|
||||
"sass": "^1.56.1",
|
||||
"ts-node": "latest",
|
||||
"turbo": "latest",
|
||||
"typescript": "^5.1.0",
|
||||
"turbo": "^1.10.12",
|
||||
"typescript": "5.1.6",
|
||||
"video.js": "^8.0.3",
|
||||
"vite-tsconfig-paths": "^4.2.0",
|
||||
"vitest": "^0.33.0",
|
||||
@@ -130,25 +153,6 @@
|
||||
"minimumChangeThreshold": 0,
|
||||
"showDetails": true
|
||||
},
|
||||
"renovate": {
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base"
|
||||
],
|
||||
"commitMessagePrefix": "⬆️",
|
||||
"lockFileMaintenance": {
|
||||
"automerge": true
|
||||
},
|
||||
"minor": {
|
||||
"automerge": true
|
||||
},
|
||||
"patch": {
|
||||
"automerge": true
|
||||
},
|
||||
"pin": {
|
||||
"automerge": true
|
||||
}
|
||||
},
|
||||
"prettier": {
|
||||
"printWidth": 100,
|
||||
"tabWidth": 2,
|
||||
|
||||
1
public/imgs/app-icons/truenas.svg
Normal file
1
public/imgs/app-icons/truenas.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 90 90" xmlns="http://www.w3.org/2000/svg"><g fill="none"><path fill="#31BEEC" d="M90 38.197v19.137L48.942 80.999V61.864z"/><path d="M41.086 61.863V81L0 57.333V38.197l18.566 10.687c.02.016.043.03.067.04l22.453 12.94Z" fill="#0095D5"/><path fill="#AEADAE" d="m61.621 45.506-16.607 9.576-16.622-9.576 16.622-9.575z"/><path fill="#0095D5" d="M86.086 31.416 69.464 40.99 48.942 29.15V10z"/><path fill="#31BEEC" d="M41.086 10v19.15l-20.55 11.827-16.621-9.561z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 484 B |
1
public/imgs/app-icons/unraid-alt.svg
Normal file
1
public/imgs/app-icons/unraid-alt.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><defs><linearGradient id="a" x1="100%" x2="0" y1="0" y2="100%" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#ff8d30"/><stop offset="1" stop-color="#e32929"/></linearGradient></defs><circle cx="50%" cy="50%" r="50%" fill="url(#a)"/><path fill="#fff" d="M246.6 200.8h18.7v110.6h-18.7zm-182.3 0H83v110.7H64.3zm91.1 123.9h18.7V367h-18.7zm-45.7-47.5h18.7v68.5h-18.7zm91.2 0h18.6v68.4h-18.6zm228.2-76.5h18.7v110.7h-18.7zM338 145.5h18.7v42.3H338zm45.7 21.2h18.7v68.2h-18.7zm-91.5 0h18.7v68.1h-18.7z"/></svg>
|
||||
|
After Width: | Height: | Size: 577 B |
35
public/locales/cn/authentication/invite.json
Normal file
35
public/locales/cn/authentication/invite.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"metaTitle": "创建账号",
|
||||
"title": "创建账号",
|
||||
"text": "请在下面定义您的凭据",
|
||||
"form": {
|
||||
"fields": {
|
||||
"username": {
|
||||
"label": "用户名"
|
||||
},
|
||||
"password": {
|
||||
"label": "密码"
|
||||
},
|
||||
"passwordConfirmation": {
|
||||
"label": "确认密码"
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"submit": "创建账号"
|
||||
}
|
||||
},
|
||||
"notifications": {
|
||||
"loading": {
|
||||
"title": "正在创建账号...",
|
||||
"text": "请稍等"
|
||||
},
|
||||
"success": {
|
||||
"title": "账号已创建",
|
||||
"text": "您的账号创建成功"
|
||||
},
|
||||
"error": {
|
||||
"title": "错误",
|
||||
"text": "出错了,出现以下错误: {{error}}"
|
||||
}
|
||||
}
|
||||
}
|
||||
20
public/locales/cn/authentication/login.json
Normal file
20
public/locales/cn/authentication/login.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"metaTitle": "登录",
|
||||
"title": "欢迎回来!",
|
||||
"text": "请确认您的凭证",
|
||||
"form": {
|
||||
"fields": {
|
||||
"username": {
|
||||
"label": "用户名"
|
||||
},
|
||||
"password": {
|
||||
"label": "密码"
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"submit": "登录"
|
||||
},
|
||||
"afterLoginRedirection": "登录后,您将被重定向到 {{url}}"
|
||||
},
|
||||
"alert": "您的凭据不正确或此账户不存在。请重试。"
|
||||
}
|
||||
5
public/locales/cn/boards/common.json
Normal file
5
public/locales/cn/boards/common.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"header": {
|
||||
"customize": "自定义面板"
|
||||
}
|
||||
}
|
||||
29
public/locales/cn/boards/customize.json
Normal file
29
public/locales/cn/boards/customize.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"metaTitle": "自定义 {{name}} 面板",
|
||||
"pageTitle": "自定义 {{name}} 面板",
|
||||
"backToBoard": "返回面板",
|
||||
"settings": {
|
||||
"appearance": {
|
||||
"primaryColor": "主体色",
|
||||
"secondaryColor": "辅助色"
|
||||
}
|
||||
},
|
||||
"save": {
|
||||
"button": "保存更改",
|
||||
"note": "小心,您有未保存的更改!"
|
||||
},
|
||||
"notifications": {
|
||||
"pending": {
|
||||
"title": "自定义保存中",
|
||||
"message": "请稍候,我们正在保存您的自定义"
|
||||
},
|
||||
"success": {
|
||||
"title": "已保存自定义",
|
||||
"message": "您的自定义已成功保存"
|
||||
},
|
||||
"error": {
|
||||
"title": "错误",
|
||||
"message": "无法保存更改"
|
||||
}
|
||||
}
|
||||
}
|
||||
55
public/locales/cn/common.json
Normal file
55
public/locales/cn/common.json
Normal file
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"save": "保存",
|
||||
"apply": "应用",
|
||||
"insert": "插入",
|
||||
"about": "关于",
|
||||
"cancel": "取消",
|
||||
"close": "关闭",
|
||||
"back": "返回",
|
||||
"delete": "删除",
|
||||
"ok": "确定",
|
||||
"edit": "编辑",
|
||||
"next": "下一步",
|
||||
"previous": "上一步",
|
||||
"confirm": "确认",
|
||||
"enabled": "已启用",
|
||||
"disabled": "已禁用",
|
||||
"enableAll": "全部启用",
|
||||
"disableAll": "全部禁用",
|
||||
"version": "版本",
|
||||
"changePosition": "换位",
|
||||
"remove": "删除",
|
||||
"removeConfirm": "你确定要删除 {{item}} 吗?",
|
||||
"createItem": "创建{{item}}",
|
||||
"sections": {
|
||||
"settings": "设置",
|
||||
"dangerZone": "危险"
|
||||
},
|
||||
"secrets": {
|
||||
"apiKey": "API密钥",
|
||||
"username": "用户名",
|
||||
"password": "密码"
|
||||
},
|
||||
"tip": "提示: ",
|
||||
"time": {
|
||||
"seconds": "秒",
|
||||
"minutes": "分钟",
|
||||
"hours": "小时"
|
||||
},
|
||||
"loading": "正在加载...",
|
||||
"breakPoints": {
|
||||
"small": "小",
|
||||
"medium": "中",
|
||||
"large": "大"
|
||||
},
|
||||
"seeMore": "查看更多...",
|
||||
"position": {
|
||||
"left": "左边",
|
||||
"center": "居中",
|
||||
"right": "右边"
|
||||
},
|
||||
"attributes": {
|
||||
"width": "宽度",
|
||||
"height": "高度"
|
||||
}
|
||||
}
|
||||
25
public/locales/cn/layout/common.json
Normal file
25
public/locales/cn/layout/common.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"modals": {
|
||||
"blockedPopups": {
|
||||
"title": "阻止弹出窗口",
|
||||
"text": "您的浏览器阻止了 Homarr 访问其 API。最常见的原因是广告拦截器或权限被拒绝。Homarr 无法自动请求权限。",
|
||||
"list": {
|
||||
"browserPermission": "点击链接旁的图标并检查权限,允许弹出窗口",
|
||||
"adBlockers": "禁用浏览器中的广告拦截器和安全工具",
|
||||
"otherBrowser": "尝试使用其它的浏览器"
|
||||
}
|
||||
}
|
||||
},
|
||||
"actions": {
|
||||
"category": {
|
||||
"openAllInNewTab": "在新标签页中打开全部内容"
|
||||
}
|
||||
},
|
||||
"menu": {
|
||||
"moveUp": "上移",
|
||||
"moveDown": "下移",
|
||||
"addCategory": "{{location}}添加分类",
|
||||
"addAbove": "在上方",
|
||||
"addBelow": "在下方"
|
||||
}
|
||||
}
|
||||
25
public/locales/cn/layout/element-selector/selector.json
Normal file
25
public/locales/cn/layout/element-selector/selector.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"modal": {
|
||||
"title": "添加新磁贴",
|
||||
"text": "磁贴是 Homarr 的主要组成元素。它们被用来显示你的应用程序和其他信息。您可以根据需要增加任意数量的磁贴。"
|
||||
},
|
||||
"widgetDescription": "组件与您的应用交互,为您提供更多的应用程序控制。它们在使用前通常需要额外的配置。",
|
||||
"goBack": "上一步",
|
||||
"actionIcon": {
|
||||
"tooltip": "添加磁贴"
|
||||
},
|
||||
"apps": "应用",
|
||||
"app": {
|
||||
"defaultName": "您的应用"
|
||||
},
|
||||
"widgets": "组件",
|
||||
"categories": "分类",
|
||||
"category": {
|
||||
"newName": "新分类名称",
|
||||
"defaultName": "新建分类",
|
||||
"created": {
|
||||
"title": "分类已创建",
|
||||
"message": "已创建分类\"{{name}}\""
|
||||
}
|
||||
}
|
||||
}
|
||||
5
public/locales/cn/layout/errors/access-denied.json
Normal file
5
public/locales/cn/layout/errors/access-denied.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"title": "拒绝访问",
|
||||
"text": "您没有足够的权限访问此页面。如果你相信, 这不是有意的, 请联系您的系统管理员。",
|
||||
"switchAccount": "切换到其他账户"
|
||||
}
|
||||
5
public/locales/cn/layout/errors/not-found.json
Normal file
5
public/locales/cn/layout/errors/not-found.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"title": "无法找到页面",
|
||||
"text": "找不到该页面。该页面的 URL 可能已过期、URL 无效或您现在没有访问该资源所需的权限。",
|
||||
"button": "返回首页"
|
||||
}
|
||||
30
public/locales/cn/layout/header.json
Normal file
30
public/locales/cn/layout/header.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"experimentalNote": {
|
||||
"label": "这是 Homarr 的一项实验性功能。请在 <gh>GitHub</gh> 或 <dc>Discord</dc>上报告任何问题。"
|
||||
},
|
||||
"search": {
|
||||
"label": "搜索",
|
||||
"engines": {
|
||||
"web": "在网上搜索 {{query}}",
|
||||
"youtube": "在 YouTube 上搜索 {{query}}",
|
||||
"torrent": "搜索 {{query}} Torrents",
|
||||
"movie": "在 {{app}} 上搜索 {{query}}"
|
||||
}
|
||||
},
|
||||
"actions": {
|
||||
"avatar": {
|
||||
"switchTheme": "切换主题",
|
||||
"preferences": "用户首选项",
|
||||
"defaultBoard": "默认仪表盘",
|
||||
"manage": "管理",
|
||||
"logout": "注销 {{username}}",
|
||||
"login": "登录"
|
||||
}
|
||||
},
|
||||
"modals": {
|
||||
"movie": {
|
||||
"title": "",
|
||||
"topResults": "最高 {{count}} 结果为 <b>{{search}}</b>。"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"description": "在编辑模式下,您可以调整磁贴和配置应用。在退出编辑模式之前不会保存更改。",
|
||||
"button": {
|
||||
"disabled": "进入编辑模式",
|
||||
"enabled": "退出并保存"
|
||||
},
|
||||
"popover": {
|
||||
"title": "启用 <1>{{size}}</1> 尺寸编辑模式",
|
||||
"text": "现在您可以调整和配置您的应用了,在退出编辑模式之前<strong>不会保存</strong>更改 。"
|
||||
},
|
||||
"unloadEvent": "退出编辑模式以保存更改"
|
||||
}
|
||||
35
public/locales/cn/layout/manage.json
Normal file
35
public/locales/cn/layout/manage.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"navigation": {
|
||||
"home": {
|
||||
"title": "首页"
|
||||
},
|
||||
"boards": {
|
||||
"title": "面板"
|
||||
},
|
||||
"users": {
|
||||
"title": "用户",
|
||||
"items": {
|
||||
"manage": "管理",
|
||||
"invites": "邀请"
|
||||
}
|
||||
},
|
||||
"help": {
|
||||
"title": "帮助",
|
||||
"items": {
|
||||
"documentation": "文档",
|
||||
"report": "报告问题 / bug",
|
||||
"discord": "Discord 社区",
|
||||
"contribute": "贡献"
|
||||
}
|
||||
},
|
||||
"tools": {
|
||||
"title": "工具",
|
||||
"items": {
|
||||
"docker": "Docker"
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
"title": "关于"
|
||||
}
|
||||
}
|
||||
}
|
||||
3
public/locales/cn/layout/mobile/drawer.json
Normal file
3
public/locales/cn/layout/mobile/drawer.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"title": "{{position}} 侧边栏"
|
||||
}
|
||||
30
public/locales/cn/layout/modals/about.json
Normal file
30
public/locales/cn/layout/modals/about.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"description": "Homarr是一个 <strong>顺滑</strong> <strong>现代化</strong> 的面板,它能将您所有的应用和服务汇于指尖。有了 Homarr,您可以在一个页面中访问和控制一切。Homarr 与您添加的应用无缝交互,为您提供有价值的信息并由您完全控制。安装 Homarr 轻松简单,并且 Homarr 支持多种部署方式。",
|
||||
"addToDashboard": "添加至面板",
|
||||
"tip": "Mod 指的是您的修饰键,它是 Ctrl 或 Command/Super/Windows 键",
|
||||
"key": "快捷键",
|
||||
"action": "操作",
|
||||
"keybinds": "热键绑定",
|
||||
"translators": "翻译 ({{count}})",
|
||||
"translatorsDescription": "感谢这些人,Homarr 现已支持 {{languages}} 种语言!想要帮助将 Homarr 翻译成您的语言吗?请阅读<a>此处</a>了解如何执行此操作 。",
|
||||
"contributors": "贡献者 ({{count}})",
|
||||
"contributorsDescription": "这些人构建了让 homarr 工作的代码!想帮助建造 Homarr 吗?请阅读<a>此处</a>了解如何操作",
|
||||
"actions": {
|
||||
"toggleTheme": "切换 白天/夜晚 模式",
|
||||
"focusSearchBar": "前往搜索栏",
|
||||
"openDocker": "打开 docker 组件",
|
||||
"toggleEdit": "切换编辑模式"
|
||||
},
|
||||
"metrics": {
|
||||
"configurationSchemaVersion": "配置模式版本",
|
||||
"version": "版本",
|
||||
"nodeEnvironment": "节点环境",
|
||||
"i18n": "I18n 翻译空间已加载",
|
||||
"locales": "I18n 本地语言已配置",
|
||||
"experimental_disableEditMode": "<b>实验性</b>: 关闭编辑模式"
|
||||
},
|
||||
"version": {
|
||||
"new": "新: {{newVersion}}",
|
||||
"dropdown": "版本 {{newVersion}} 可用!当前版本为 {{currentVersion}}"
|
||||
}
|
||||
}
|
||||
128
public/locales/cn/layout/modals/add-app.json
Normal file
128
public/locales/cn/layout/modals/add-app.json
Normal file
@@ -0,0 +1,128 @@
|
||||
{
|
||||
"tabs": {
|
||||
"general": "通用",
|
||||
"behaviour": "行为",
|
||||
"network": "网络",
|
||||
"appearance": "外观",
|
||||
"integration": "集成"
|
||||
},
|
||||
"general": {
|
||||
"appname": {
|
||||
"label": "应用名称",
|
||||
"description": "用于在面板上显示。"
|
||||
},
|
||||
"internalAddress": {
|
||||
"label": "内部地址",
|
||||
"description": "应用的内部IP地址。",
|
||||
"troubleshoot": {
|
||||
"label": "遇到问题了?",
|
||||
"header": "下面是一些常见的错误和解决方法:",
|
||||
"lines": {
|
||||
"nothingAfterPort": "在大多数情况下(不是所有情况),您不应该在端口之后输入任何路径。(即使是 pihole 的 '/admin' 或 plex 的 '/web')",
|
||||
"protocolCheck": "一定要确保URL前面是http或https,并确保你使用的是正确的URL。",
|
||||
"preferIP": "建议使用要与之通信的机器或容器的直接 Ip 地址。",
|
||||
"enablePings": "通过开启ping检查IP是否正确。 自定义面板 -> 布局 -> 启用 ping。应用磁贴上会出现一个红色或绿色的小泡泡,鼠标悬停在此就会显示相应代码(在大多数的情况下,绿色泡泡的代码为200)。",
|
||||
"wget": "为了确保homarr可以与其他应用程序通信,请使用wget/curl/ping应用程序的IP:port。",
|
||||
"iframe": "在使用 iframe 时,应始终使用与 Homarr 相同的协议 (http/s)。",
|
||||
"clearCache": "有些信息是在缓存中注册的,因此除非您在Homarr的一般选项中清除缓存,否则集成可能无法工作。"
|
||||
},
|
||||
"footer": "更多故障排除,请联系我们的{{discord}}。"
|
||||
}
|
||||
},
|
||||
"externalAddress": {
|
||||
"label": "外部地址",
|
||||
"description": "点击应用时打开的网址。"
|
||||
}
|
||||
},
|
||||
"behaviour": {
|
||||
"isOpeningNewTab": {
|
||||
"label": "在新标签页中打开",
|
||||
"description": "在新标签页中打开应用,而不是当前标签页。"
|
||||
},
|
||||
"tooltipDescription": {
|
||||
"label": "应用描述",
|
||||
"description": "将鼠标悬停在应用上时,将显示您输入的文本。\n它可以为用户提供更多关于应用的详细信息,留空以隐藏。"
|
||||
},
|
||||
"customProtocolWarning": "使用非标准协议。这可能需要预先安装应用程序,并可能带来安全风险。确保您的地址安全可靠。"
|
||||
},
|
||||
"network": {
|
||||
"statusChecker": {
|
||||
"label": "状态检测",
|
||||
"description": "使用简单的HTTP(S) 请求检查您的应用是否在线。"
|
||||
},
|
||||
"statusCodes": {
|
||||
"label": "HTTP状态码",
|
||||
"description": "被视为在线的 HTTP 状态码。"
|
||||
}
|
||||
},
|
||||
"appearance": {
|
||||
"icon": {
|
||||
"label": "应用图标",
|
||||
"description": "输入以搜索图标,也可以粘贴自定义图标的网址。",
|
||||
"autocomplete": {
|
||||
"title": "未找到结果",
|
||||
"text": "尝试使用一个更具体的搜索词。如果您找不到您想要的图标,可以在上方粘贴图片的网址,以获得一个自定义图标。"
|
||||
},
|
||||
"noItems": {
|
||||
"title": "正在加载外部图标",
|
||||
"text": "这可能需要几秒钟"
|
||||
}
|
||||
},
|
||||
"appNameFontSize": {
|
||||
"label": "应用名称大小",
|
||||
"description": "设置应用名称在磁贴上显示时的字体大小。"
|
||||
},
|
||||
"appNameStatus": {
|
||||
"label": "应用名称状态",
|
||||
"description": "如果您想要显示标题,请选择显示的位置。",
|
||||
"dropdown": {
|
||||
"normal": "仅在磁贴上显示标题",
|
||||
"hover": "仅在悬停时显示标题",
|
||||
"hidden": "完全不显示"
|
||||
}
|
||||
},
|
||||
"positionAppName": {
|
||||
"label": "应用名称位置",
|
||||
"description": "应用名称相对于图标的位置。",
|
||||
"dropdown": {
|
||||
"top": "上边",
|
||||
"right": "右边",
|
||||
"bottom": "下边",
|
||||
"left": "左边"
|
||||
}
|
||||
},
|
||||
"lineClampAppName": {
|
||||
"label": "应用名称行数",
|
||||
"description": "定义标题最多能容纳多少行。设置为 0 表示无限制。"
|
||||
}
|
||||
},
|
||||
"integration": {
|
||||
"type": {
|
||||
"label": "集成配置",
|
||||
"description": "集成配置将用于连接到您的应用。",
|
||||
"placeholder": "选择一个集成",
|
||||
"defined": "已定义",
|
||||
"undefined": "未定义",
|
||||
"public": "公开",
|
||||
"private": "私有",
|
||||
"explanationPrivate": "私有密钥仅会被发送到服务器一次。一旦您的浏览器刷新了页面,它将永远不会再次发送。",
|
||||
"explanationPublic": "公开的密钥将始终发送给客户端,并且可以通过API访问。它不应该包含任何机密值,如用户名、密码、令牌、证书等!"
|
||||
},
|
||||
"secrets": {
|
||||
"description": "输入值并点击保存以更新密钥。使用清除按钮以删除密钥。",
|
||||
"warning": "您的凭据作为集成的访问权限,您应该<strong>永远不</strong>与任何人共享它们。Homarr 团队永远不会索要证书。确保<strong>安全地存储和管理您的秘钥</strong>。",
|
||||
"clear": "清除密钥",
|
||||
"save": "保存密钥",
|
||||
"update": "更新密钥"
|
||||
}
|
||||
},
|
||||
"validation": {
|
||||
"popover": "您的表单包含无效数据,因此它不能被保存。请解决所有问题,并再次点击此按钮以保存您的更改。",
|
||||
"name": "名称为必填项",
|
||||
"noUrl": "地址为必填项",
|
||||
"invalidUrl": "不是有效的地址",
|
||||
"noIconUrl": "此字段为必填",
|
||||
"noExternalUri": "外部地址为必填项",
|
||||
"invalidExternalUri": "无效的外部地址"
|
||||
}
|
||||
}
|
||||
8
public/locales/cn/layout/modals/change-position.json
Normal file
8
public/locales/cn/layout/modals/change-position.json
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"xPosition": "X轴位置",
|
||||
"width": "宽度",
|
||||
"height": "高度",
|
||||
"yPosition": "Y轴位置",
|
||||
"zeroOrHigher": "0 或更高",
|
||||
"betweenXandY": "在 {{min}} 和 {{max}} 之间"
|
||||
}
|
||||
44
public/locales/cn/manage/boards.json
Normal file
44
public/locales/cn/manage/boards.json
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"metaTitle": "面板",
|
||||
"pageTitle": "面板",
|
||||
"cards": {
|
||||
"statistics": {
|
||||
"apps": "应用",
|
||||
"widgets": "组件",
|
||||
"categories": "分类"
|
||||
},
|
||||
"buttons": {
|
||||
"view": "查看面板"
|
||||
},
|
||||
"menu": {
|
||||
"setAsDefault": "设置为默认",
|
||||
"delete": {
|
||||
"label": "永久删除",
|
||||
"disabled": "删除功能被禁用,因为较旧的 Homarr 组件不允许删除默认配置。将来可能会删除。"
|
||||
}
|
||||
},
|
||||
"badges": {
|
||||
"fileSystem": "文件系统",
|
||||
"default": "默认"
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"create": "创建新面板"
|
||||
},
|
||||
"modals": {
|
||||
"delete": {
|
||||
"title": "删除面板",
|
||||
"text": "你确定要删除这个面板吗? 此操作无法撤消,您的数据将永久丢失。"
|
||||
},
|
||||
"create": {
|
||||
"title": "创建面板",
|
||||
"text": "面板创建成功后,不能修改名称。",
|
||||
"form": {
|
||||
"name": {
|
||||
"label": "名称"
|
||||
},
|
||||
"submit": "创建"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
23
public/locales/cn/manage/index.json
Normal file
23
public/locales/cn/manage/index.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"metaTitle": "管理",
|
||||
"hero": {
|
||||
"title": "欢迎回来,{{username}}!",
|
||||
"fallbackUsername": "匿名",
|
||||
"subtitle": "欢迎来到您的应用程序中心。组织、优化和征服!"
|
||||
},
|
||||
"quickActions": {
|
||||
"title": "快捷操作",
|
||||
"boards": {
|
||||
"title": "您的面板",
|
||||
"subtitle": "创建和管理您的面板"
|
||||
},
|
||||
"inviteUsers": {
|
||||
"title": "邀请新用户",
|
||||
"subtitle": "创建并发送注册邀请"
|
||||
},
|
||||
"manageUsers": {
|
||||
"title": "管理用户",
|
||||
"subtitle": "删除和管理您的用户"
|
||||
}
|
||||
}
|
||||
}
|
||||
36
public/locales/cn/manage/users.json
Normal file
36
public/locales/cn/manage/users.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"metaTitle": "用户",
|
||||
"pageTitle": "管理用户",
|
||||
"text": "通过账号,您可以配置谁可以编辑您的面板。Homarr的未来版本将对权限和面板进行更精细地控制。",
|
||||
"buttons": {
|
||||
"create": "创建"
|
||||
},
|
||||
"table": {
|
||||
"header": {
|
||||
"user": "用户"
|
||||
}
|
||||
},
|
||||
"tooltips": {
|
||||
"deleteUser": "删除用户",
|
||||
"demoteAdmin": "撤销管理员",
|
||||
"promoteToAdmin": "提升为管理员"
|
||||
},
|
||||
"modals": {
|
||||
"delete": {
|
||||
"title": "删除用户 {{name}}",
|
||||
"text": "您确定要删除用户 {{name}} 吗?这将删除与该账户相关的数据,但不会删除该用户创建的任何仪表盘。"
|
||||
},
|
||||
"change-role": {
|
||||
"promote": {
|
||||
"title": "将用户 {{name}} 提升为管理员",
|
||||
"text": "您确定要将用户{{name}} 提升为管理员吗? 这将允许用户访问Homarr实例上的所有资源。"
|
||||
},
|
||||
"demote": {
|
||||
"title": "将用户 {{name}} 降级为用户",
|
||||
"text": "您确定要将用户{{name}} 降级为用户吗? 这将删除用户对Homarr实例上所有资源的访问权限。"
|
||||
},
|
||||
"confirm": "确认"
|
||||
}
|
||||
},
|
||||
"searchDoesntMatch": "您的搜索与任何条目都不匹配。请调整您的过滤器。"
|
||||
}
|
||||
52
public/locales/cn/manage/users/create.json
Normal file
52
public/locales/cn/manage/users/create.json
Normal file
@@ -0,0 +1,52 @@
|
||||
{
|
||||
"metaTitle": "创建用户",
|
||||
"steps": {
|
||||
"account": {
|
||||
"title": "第一步",
|
||||
"text": "创建账号",
|
||||
"username": {
|
||||
"label": "用户名"
|
||||
},
|
||||
"email": {
|
||||
"label": "邮箱"
|
||||
}
|
||||
},
|
||||
"security": {
|
||||
"title": "第二步",
|
||||
"text": "密码",
|
||||
"password": {
|
||||
"label": "密码"
|
||||
}
|
||||
},
|
||||
"finish": {
|
||||
"title": "确认",
|
||||
"text": "保存到数据库",
|
||||
"card": {
|
||||
"title": "检查您的输入",
|
||||
"text": "将数据提交到数据库后,用户就可以登录了。您确定要将该用户存储在数据库中并激活登录吗?"
|
||||
},
|
||||
"table": {
|
||||
"header": {
|
||||
"property": "属性",
|
||||
"value": "参数值",
|
||||
"username": "用户名",
|
||||
"email": "邮箱",
|
||||
"password": "密码"
|
||||
},
|
||||
"notSet": "未设置",
|
||||
"valid": "有效"
|
||||
},
|
||||
"failed": "用户创建失败: {{error}}"
|
||||
},
|
||||
"completed": {
|
||||
"alert": {
|
||||
"title": "用户已创建",
|
||||
"text": "用户已在数据库中创建。他现在可以登录了。"
|
||||
}
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"generateRandomPassword": "随机生成",
|
||||
"createAnother": "创建另一个"
|
||||
}
|
||||
}
|
||||
48
public/locales/cn/manage/users/invites.json
Normal file
48
public/locales/cn/manage/users/invites.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"metaTitle": "用户邀请",
|
||||
"pageTitle": "管理用户邀请",
|
||||
"description": "使用邀请功能,可以邀请用户访问 Homarr 实例。邀请只在一定的时间范围内有效,并且只能使用一次。过期时间必须在创建后5分钟到12个月之间。",
|
||||
"button": {
|
||||
"createInvite": "创建邀请",
|
||||
"deleteInvite": "删除邀请"
|
||||
},
|
||||
"table": {
|
||||
"header": {
|
||||
"id": "ID",
|
||||
"creator": "创建者",
|
||||
"expires": "有效期",
|
||||
"action": "操作"
|
||||
},
|
||||
"data": {
|
||||
"expiresAt": "过期 {{at}}",
|
||||
"expiresIn": "{{in}}"
|
||||
}
|
||||
},
|
||||
"modals": {
|
||||
"create": {
|
||||
"title": "创建邀请",
|
||||
"description": "过期后,邀请会失效,被邀请的收件人将无法创建账号。",
|
||||
"form": {
|
||||
"expires": "过期时间",
|
||||
"submit": "创建"
|
||||
}
|
||||
},
|
||||
"copy": {
|
||||
"title": "复制邀请信息",
|
||||
"description": "您的邀请已生成。在此模式关闭后,<b>您将无法再复制此链接</b>。如果你不想再邀请这个人,你可以随时删除这个邀请。",
|
||||
"invitationLink": "邀请链接",
|
||||
"details": {
|
||||
"id": "ID",
|
||||
"token": "Token"
|
||||
},
|
||||
"button": {
|
||||
"close": "复制并关闭"
|
||||
}
|
||||
},
|
||||
"delete": {
|
||||
"title": "删除邀请",
|
||||
"description": "你确定要删除这个邀请吗? 使用此链接的用户将不能再使用该链接创建账号。"
|
||||
}
|
||||
},
|
||||
"noInvites": "还没有邀请。"
|
||||
}
|
||||
43
public/locales/cn/modules/bookmark.json
Normal file
43
public/locales/cn/modules/bookmark.json
Normal file
@@ -0,0 +1,43 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "书签",
|
||||
"description": "显示字符或链接的静态列表",
|
||||
"settings": {
|
||||
"title": "书签设置",
|
||||
"name": {
|
||||
"label": "组件标题",
|
||||
"info": "留空以隐藏标题。"
|
||||
},
|
||||
"items": {
|
||||
"label": "项目"
|
||||
},
|
||||
"layout": {
|
||||
"label": "显示布局",
|
||||
"data": {
|
||||
"autoGrid": "自动网格",
|
||||
"horizontal": "横向",
|
||||
"vertical": "垂直"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"card": {
|
||||
"noneFound": {
|
||||
"title": "书签列表为空",
|
||||
"text": "在编辑模式下为该列表添加新项目"
|
||||
}
|
||||
},
|
||||
"item": {
|
||||
"validation": {
|
||||
"length": "长度必须在 {{shortest}} 和 {{longest}} 之间",
|
||||
"invalidLink": "无效链接",
|
||||
"errorMsg": "由于存在验证错误,未保存。请调整您的输入"
|
||||
},
|
||||
"name": "名称",
|
||||
"url": "网址",
|
||||
"newTab": "在新标签页中打开",
|
||||
"hideHostname": "隐藏域名",
|
||||
"hideIcon": "隐藏图标",
|
||||
"delete": "删除"
|
||||
}
|
||||
}
|
||||
33
public/locales/cn/modules/calendar.json
Normal file
33
public/locales/cn/modules/calendar.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "日历",
|
||||
"description": "在日历中显示来自支持集成中的即将发布的版本。",
|
||||
"settings": {
|
||||
"title": "日历组件设置",
|
||||
"radarrReleaseType": {
|
||||
"label": "Radarr发布类型",
|
||||
"data": {
|
||||
"inCinemas": "影院放映",
|
||||
"physicalRelease": "实体",
|
||||
"digitalRelease": "数字"
|
||||
}
|
||||
},
|
||||
"hideWeekDays": {
|
||||
"label": "隐藏星期"
|
||||
},
|
||||
"showUnmonitored": {
|
||||
"label": "显示未监视项目"
|
||||
},
|
||||
"fontSize": {
|
||||
"label": "字体大小",
|
||||
"data": {
|
||||
"xs": "超小号",
|
||||
"sm": "小号",
|
||||
"md": "中号",
|
||||
"lg": "大号",
|
||||
"xl": "超大号"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
6
public/locales/cn/modules/common-media-cards.json
Normal file
6
public/locales/cn/modules/common-media-cards.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"buttons": {
|
||||
"play": "开始",
|
||||
"request": "请求"
|
||||
}
|
||||
}
|
||||
10
public/locales/cn/modules/common.json
Normal file
10
public/locales/cn/modules/common.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"settings": {
|
||||
"label": "设置"
|
||||
},
|
||||
"errors": {
|
||||
"unmappedOptions": {
|
||||
"text": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
118
public/locales/cn/modules/dashdot.json
Normal file
118
public/locales/cn/modules/dashdot.json
Normal file
@@ -0,0 +1,118 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Dash.",
|
||||
"description": "在 Homarr 中显示一个外部 Dash. 的图表。",
|
||||
"settings": {
|
||||
"title": "Dash. 组件设置",
|
||||
"dashName": {
|
||||
"label": "Dash. 名称"
|
||||
},
|
||||
"url": {
|
||||
"label": "Dash. 网址"
|
||||
},
|
||||
"usePercentages": {
|
||||
"label": "显示百分比"
|
||||
},
|
||||
"columns": {
|
||||
"label": "显示的列"
|
||||
},
|
||||
"graphHeight": {
|
||||
"label": "图表高度"
|
||||
},
|
||||
"graphsOrder": {
|
||||
"label": "图表(顺序)",
|
||||
"storage": {
|
||||
"label": "存储",
|
||||
"enabled": {
|
||||
"label": "在组件中显示"
|
||||
},
|
||||
"span": {
|
||||
"label": "列宽度"
|
||||
},
|
||||
"compactView": {
|
||||
"label": "显示为文本(紧凑型)"
|
||||
},
|
||||
"multiView": {
|
||||
"label": "显示为多驱动视图"
|
||||
}
|
||||
},
|
||||
"network": {
|
||||
"label": "网络",
|
||||
"enabled": {
|
||||
"label": "在组件中显示"
|
||||
},
|
||||
"span": {
|
||||
"label": "列宽度"
|
||||
},
|
||||
"compactView": {
|
||||
"label": "显示为文本(紧凑型)"
|
||||
}
|
||||
},
|
||||
"cpu": {
|
||||
"label": "CPU",
|
||||
"enabled": {
|
||||
"label": "在组件中显示"
|
||||
},
|
||||
"span": {
|
||||
"label": "列宽度"
|
||||
},
|
||||
"multiView": {
|
||||
"label": "显示为多核心视图"
|
||||
}
|
||||
},
|
||||
"ram": {
|
||||
"label": "内存",
|
||||
"enabled": {
|
||||
"label": "在组件中显示"
|
||||
},
|
||||
"span": {
|
||||
"label": "列宽度"
|
||||
}
|
||||
},
|
||||
"gpu": {
|
||||
"label": "GPU",
|
||||
"enabled": {
|
||||
"label": "在组件中显示"
|
||||
},
|
||||
"span": {
|
||||
"label": "列宽度"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"card": {
|
||||
"title": "Dash.",
|
||||
"errors": {
|
||||
"noService": "未找到 Dash. 服务。请在集成中将其添加到您的 Homarr 面板或在模块选项中设置 Dash. 网址",
|
||||
"noInformation": "无法从 Dash. 获取信息。- 你运行的是最新版本吗?",
|
||||
"protocolDowngrade": {
|
||||
"title": "检测到协议降级",
|
||||
"text": "与 Dash. 实例的连接使用的是HTTP。这是一个安全风险,因为HTTP是未加密的,攻击者可能会滥用此连接。确保 Dash. 使用的是HTTPS,或者将Homarr降级为HTTP(不推荐)。"
|
||||
}
|
||||
},
|
||||
"graphs": {
|
||||
"storage": {
|
||||
"title": "存储",
|
||||
"label": "存储:"
|
||||
},
|
||||
"network": {
|
||||
"title": "网络",
|
||||
"label": "网络:",
|
||||
"metrics": {
|
||||
"download": "下载",
|
||||
"upload": "上传"
|
||||
}
|
||||
},
|
||||
"cpu": {
|
||||
"title": "CPU"
|
||||
},
|
||||
"ram": {
|
||||
"title": "内存"
|
||||
},
|
||||
"gpu": {
|
||||
"title": "GPU"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
33
public/locales/cn/modules/date.json
Normal file
33
public/locales/cn/modules/date.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "日期和时间",
|
||||
"description": "显示当前的日期和时间。",
|
||||
"settings": {
|
||||
"title": "日期和时间组件设置",
|
||||
"display24HourFormat": {
|
||||
"label": "全时显示(24 小时)"
|
||||
},
|
||||
"dateFormat": {
|
||||
"label": "日期格式",
|
||||
"data": {
|
||||
"hide": "隐藏日期"
|
||||
}
|
||||
},
|
||||
"enableTimezone": {
|
||||
"label": "显示自定义时区"
|
||||
},
|
||||
"timezoneLocation": {
|
||||
"label": "时区位置"
|
||||
},
|
||||
"titleState": {
|
||||
"label": "城市名称",
|
||||
"info": "如果激活时区选项,则可显示城市名称和时区代码。<br/>您也可以只显示城市,甚至不显示。",
|
||||
"data": {
|
||||
"both": "城市和时区",
|
||||
"city": "仅城市",
|
||||
"none": "无"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
35
public/locales/cn/modules/dlspeed.json
Normal file
35
public/locales/cn/modules/dlspeed.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "下载速度",
|
||||
"description": "显示集成中支持的下载和上传速度。"
|
||||
},
|
||||
"card": {
|
||||
"table": {
|
||||
"header": {
|
||||
"name": "名称",
|
||||
"size": "大小",
|
||||
"download": "下载",
|
||||
"upload": "上传",
|
||||
"estimatedTimeOfArrival": "剩余时间",
|
||||
"progress": "进度"
|
||||
},
|
||||
"body": {
|
||||
"nothingFound": "没有找到种子"
|
||||
}
|
||||
},
|
||||
"lineChart": {
|
||||
"title": "当前下载速度",
|
||||
"download": "下载:{{download}}",
|
||||
"upload": "上传: {{upload}}",
|
||||
"timeSpan": "{{seconds}} 秒前",
|
||||
"totalDownload": "下载: {{download}}/秒",
|
||||
"totalUpload": "上传: {{upload}}/秒"
|
||||
},
|
||||
"errors": {
|
||||
"noDownloadClients": {
|
||||
"title": "没有找到支持的下载客户端!",
|
||||
"text": "添加下载服务以查看您当前的下载情况"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
18
public/locales/cn/modules/dns-hole-controls.json
Normal file
18
public/locales/cn/modules/dns-hole-controls.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "DNS漏洞控制",
|
||||
"description": "从您的面板控制 PiHole 或 AdGuard",
|
||||
"settings": {
|
||||
"title": "DNS 漏洞控制设置",
|
||||
"showToggleAllButtons": {
|
||||
"label": "显示 \"启用/禁用全部 \"按钮"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"general": {
|
||||
"title": "无法找到 DNS 漏洞",
|
||||
"text": "到DNS漏洞的连接有问题。请验证您的配置/集成设置。"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
28
public/locales/cn/modules/dns-hole-summary.json
Normal file
28
public/locales/cn/modules/dns-hole-summary.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "DNS漏洞统计",
|
||||
"description": "显示来自 PiHole 或 AdGuard 的重要数据",
|
||||
"settings": {
|
||||
"title": "DNS漏洞统计设置",
|
||||
"usePiHoleColors": {
|
||||
"label": "使用 PiHole 的颜色"
|
||||
},
|
||||
"layout": {
|
||||
"label": "显示布局",
|
||||
"data": {
|
||||
"grid": "2 x 2",
|
||||
"row": "横向",
|
||||
"column": "垂直"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"card": {
|
||||
"metrics": {
|
||||
"domainsOnAdlist": "广告列表中的域名",
|
||||
"queriesToday": "今日查询",
|
||||
"queriesBlockedTodayPercentage": "今日屏蔽",
|
||||
"queriesBlockedToday": "今日屏蔽"
|
||||
}
|
||||
}
|
||||
}
|
||||
83
public/locales/cn/modules/docker.json
Normal file
83
public/locales/cn/modules/docker.json
Normal file
@@ -0,0 +1,83 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Docker",
|
||||
"description": "允许您轻松查看和管理所有的Docker容器。"
|
||||
},
|
||||
"search": {
|
||||
"placeholder": "按容器或镜像名称搜索"
|
||||
},
|
||||
"table": {
|
||||
"header": {
|
||||
"name": "名称",
|
||||
"image": "镜像",
|
||||
"ports": "端口",
|
||||
"state": "状态"
|
||||
},
|
||||
"body": {
|
||||
"portCollapse": "{{ports}} 更多"
|
||||
},
|
||||
"states": {
|
||||
"running": "运行中",
|
||||
"created": "已创建",
|
||||
"stopped": "已停止",
|
||||
"unknown": "未知"
|
||||
}
|
||||
},
|
||||
"actionBar": {
|
||||
"addService": {
|
||||
"title": "添加应用",
|
||||
"message": "添加应用到 Homarr"
|
||||
},
|
||||
"restart": {
|
||||
"title": "重启"
|
||||
},
|
||||
"stop": {
|
||||
"title": "停止"
|
||||
},
|
||||
"start": {
|
||||
"title": "开始"
|
||||
},
|
||||
"refreshData": {
|
||||
"title": "刷新"
|
||||
},
|
||||
"remove": {
|
||||
"title": "删除"
|
||||
},
|
||||
"addToHomarr": {
|
||||
"title": "添加到 Homarr"
|
||||
}
|
||||
},
|
||||
"actions": {
|
||||
"start": {
|
||||
"start": "正在启动...",
|
||||
"end": "已启动"
|
||||
},
|
||||
"stop": {
|
||||
"start": "正在停止",
|
||||
"end": "已停止"
|
||||
},
|
||||
"restart": {
|
||||
"start": "正在重启",
|
||||
"end": "已重启"
|
||||
},
|
||||
"remove": {
|
||||
"start": "删除中",
|
||||
"end": "已删除"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"integrationFailed": {
|
||||
"title": "Docker 集成失败",
|
||||
"message": "你是不是忘了挂载docker socket?"
|
||||
},
|
||||
"unknownError": {
|
||||
"title": "出现了一个错误"
|
||||
},
|
||||
"oneServiceAtATime": {
|
||||
"title": "请每次只添加一个应用程序或服务!"
|
||||
}
|
||||
},
|
||||
"actionIcon": {
|
||||
"tooltip": "Docker"
|
||||
}
|
||||
}
|
||||
45
public/locales/cn/modules/iframe.json
Normal file
45
public/locales/cn/modules/iframe.json
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "iFrame",
|
||||
"description": "嵌入互联网上的任何内容。某些网站可能限制访问。",
|
||||
"settings": {
|
||||
"title": "iFrame设置",
|
||||
"embedUrl": {
|
||||
"label": "嵌入地址"
|
||||
},
|
||||
"allowFullScreen": {
|
||||
"label": "允许全屏"
|
||||
},
|
||||
"allowTransparency": {
|
||||
"label": "允许透明"
|
||||
},
|
||||
"allowScrolling": {
|
||||
"label": "允许滚动"
|
||||
},
|
||||
"allowPayment": {
|
||||
"label": "允许支付"
|
||||
},
|
||||
"allowAutoPlay": {
|
||||
"label": "允许自动播放"
|
||||
},
|
||||
"allowMicrophone": {
|
||||
"label": "允许麦克风"
|
||||
},
|
||||
"allowCamera": {
|
||||
"label": "允许摄像头"
|
||||
},
|
||||
"allowGeolocation": {
|
||||
"label": "允许地理位置"
|
||||
}
|
||||
}
|
||||
},
|
||||
"card": {
|
||||
"errors": {
|
||||
"noUrl": {
|
||||
"title": "无效链接",
|
||||
"text": "确保您在组件配置中输入了一个有效的地址"
|
||||
},
|
||||
"browserSupport": "您的浏览器不支持 iframe。请更新您的浏览器。"
|
||||
}
|
||||
}
|
||||
}
|
||||
33
public/locales/cn/modules/media-requests-list.json
Normal file
33
public/locales/cn/modules/media-requests-list.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "媒体请求",
|
||||
"description": "查看 Overr 或 Jellyseerr 实例中的所有媒体请求列表",
|
||||
"settings": {
|
||||
"title": "媒体请求列表",
|
||||
"replaceLinksWithExternalHost": {
|
||||
"label": "使用外部地址替换链接"
|
||||
},
|
||||
"openInNewTab": {
|
||||
"label": "在新标签页中打开链接"
|
||||
}
|
||||
}
|
||||
},
|
||||
"noRequests": "未找到请求。请确保您已正确配置您的应用。",
|
||||
"state": {
|
||||
"approved": "已批准",
|
||||
"pendingApproval": "待批准",
|
||||
"declined": "已拒绝"
|
||||
},
|
||||
"tooltips": {
|
||||
"approve": "批准请求",
|
||||
"decline": "拒绝请求",
|
||||
"approving": "正在批准请求..."
|
||||
},
|
||||
"mutation": {
|
||||
"approving": "正在批准",
|
||||
"declining": "拒绝中",
|
||||
"request": "请求...",
|
||||
"approved": "请求被批准!",
|
||||
"declined": "请求被拒绝!"
|
||||
}
|
||||
}
|
||||
27
public/locales/cn/modules/media-requests-stats.json
Normal file
27
public/locales/cn/modules/media-requests-stats.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "媒体请求状态",
|
||||
"description": "您的媒体请求统计",
|
||||
"settings": {
|
||||
"title": "媒体请求状态",
|
||||
"replaceLinksWithExternalHost": {
|
||||
"label": "使用外部地址替换链接"
|
||||
},
|
||||
"openInNewTab": {
|
||||
"label": "在新标签页中打开链接"
|
||||
}
|
||||
}
|
||||
},
|
||||
"mediaStats": {
|
||||
"title": "媒体统计",
|
||||
"pending": "等待批准",
|
||||
"tvRequests": "电视请求",
|
||||
"movieRequests": "电影请求",
|
||||
"approved": "已经批准",
|
||||
"totalRequests": "请求总计"
|
||||
},
|
||||
"userStats": {
|
||||
"title": "用户排行",
|
||||
"requests": "请求: {{number}}"
|
||||
}
|
||||
}
|
||||
25
public/locales/cn/modules/media-server.json
Normal file
25
public/locales/cn/modules/media-server.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "媒体服务",
|
||||
"description": "与您的 Jellyfin 或 Plex 媒体服务交互",
|
||||
"settings": {
|
||||
"title": "媒体服务组件设置"
|
||||
}
|
||||
},
|
||||
"loading": "正在载入流",
|
||||
"card": {
|
||||
"table": {
|
||||
"header": {
|
||||
"session": "会话",
|
||||
"user": "用户",
|
||||
"currentlyPlaying": "正在播放"
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"general": {
|
||||
"title": "无法加载内容",
|
||||
"text": "无法从服务器检索信息。请检查日志获取更多详细信息"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
59
public/locales/cn/modules/notebook.json
Normal file
59
public/locales/cn/modules/notebook.json
Normal file
@@ -0,0 +1,59 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "笔记本",
|
||||
"description": "一个基于 Markdown 的交互式组件,供您写下笔记!",
|
||||
"settings": {
|
||||
"title": "笔记本组件设置",
|
||||
"showToolbar": {
|
||||
"label": "显示帮助您写下 Markdown 的工具栏"
|
||||
},
|
||||
"allowReadOnlyCheck": {
|
||||
"label": "允许在只读模式中检查"
|
||||
},
|
||||
"content": {
|
||||
"label": "笔记本的内容"
|
||||
}
|
||||
}
|
||||
},
|
||||
"card": {
|
||||
"controls": {
|
||||
"bold": "粗体",
|
||||
"italic": "斜体",
|
||||
"strikethrough": "删除线",
|
||||
"underline": "下划线",
|
||||
"colorText": "文字颜色",
|
||||
"colorHighlight": "彩色高亮文本",
|
||||
"code": "代码",
|
||||
"clear": "清除格式",
|
||||
"heading": "标题 {{level}}",
|
||||
"align": "对齐文本: {{position}}",
|
||||
"blockquote": "引用",
|
||||
"horizontalLine": "横线",
|
||||
"bulletList": "符号列表",
|
||||
"orderedList": "顺序列表",
|
||||
"checkList": "检查列表",
|
||||
"increaseIndent": "增加缩进",
|
||||
"decreaseIndent": "减小缩进",
|
||||
"link": "链接",
|
||||
"unlink": "删除链接",
|
||||
"image": "嵌入图片",
|
||||
"addTable": "添加表格",
|
||||
"deleteTable": "删除表格",
|
||||
"colorCell": "单元格颜色",
|
||||
"mergeCell": "切换单元格合并",
|
||||
"addColumnLeft": "在前面添加列",
|
||||
"addColumnRight": "在后面添加列",
|
||||
"deleteColumn": "删除整列",
|
||||
"addRowTop": "在前面添加行",
|
||||
"addRowBelow": "在后面添加行",
|
||||
"deleteRow": "删除整行"
|
||||
},
|
||||
"modals": {
|
||||
"clearColor": "清除颜色",
|
||||
"source": "来源",
|
||||
"widthPlaceholder": "百分比或像素值",
|
||||
"columns": "列数",
|
||||
"rows": "行数"
|
||||
}
|
||||
}
|
||||
}
|
||||
30
public/locales/cn/modules/overseerr.json
Normal file
30
public/locales/cn/modules/overseerr.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Overseerr",
|
||||
"description": "允许您从Overseerr 或 Jellyseerr 搜索和添加媒体。"
|
||||
},
|
||||
"popup": {
|
||||
"item": {
|
||||
"buttons": {
|
||||
"askFor": "请求 {{title}}",
|
||||
"cancel": "取消",
|
||||
"request": "请求"
|
||||
},
|
||||
"alerts": {
|
||||
"automaticApproval": {
|
||||
"title": "使用 API key",
|
||||
"text": "此请求将被自动批准"
|
||||
}
|
||||
}
|
||||
},
|
||||
"seasonSelector": {
|
||||
"caption": "勾选您想要下载的季",
|
||||
"table": {
|
||||
"header": {
|
||||
"season": "季",
|
||||
"numberOfEpisodes": "集数"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
11
public/locales/cn/modules/ping.json
Normal file
11
public/locales/cn/modules/ping.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Ping",
|
||||
"description": "根据设定的URL的HTTP响应代码,显示一个状态指示器。"
|
||||
},
|
||||
"states": {
|
||||
"online": "在线 {{response}}",
|
||||
"offline": "离线 {{response}}",
|
||||
"loading": "正在加载..."
|
||||
}
|
||||
}
|
||||
31
public/locales/cn/modules/rss.json
Normal file
31
public/locales/cn/modules/rss.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "RSS 组件",
|
||||
"description": "RSS 组件允许您在面板上显示 RSS 源。",
|
||||
"settings": {
|
||||
"title": "RSS 组件设置",
|
||||
"rssFeedUrl": {
|
||||
"label": "RSS 订阅地址",
|
||||
"description": "您想要显示的 RSS 订阅的地址。"
|
||||
},
|
||||
"refreshInterval": {
|
||||
"label": "刷新间隔(分钟)"
|
||||
},
|
||||
"dangerousAllowSanitizedItemContent": {
|
||||
"label": "允许 HTML 格式化(危险)",
|
||||
"info": "允许从外部进行HTML格式化可能是危险的。<br/>请确保订阅来自信任的来源。"
|
||||
},
|
||||
"textLinesClamp": {
|
||||
"label": "文字线条"
|
||||
}
|
||||
},
|
||||
"card": {
|
||||
"errors": {
|
||||
"general": {
|
||||
"title": "无法获取 RSS 订阅",
|
||||
"text": "在获取 RSS 订阅时出现了问题。确保使用有效的 URL 正确配置了 RSS 订阅。URL 应与官方规范匹配。更新 RSS 订阅后,您可能需要刷新面板。"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
30
public/locales/cn/modules/search.json
Normal file
30
public/locales/cn/modules/search.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "搜索栏",
|
||||
"description": "一个搜索栏,允许你搜索你的自定义搜索引擎、YouTube和支持的集成。"
|
||||
},
|
||||
"input": {
|
||||
"placeholder": "在网上搜索..."
|
||||
},
|
||||
"switched-to": "切换到",
|
||||
"searchEngines": {
|
||||
"search": {
|
||||
"name": "网页",
|
||||
"description": "搜索..."
|
||||
},
|
||||
"youtube": {
|
||||
"name": "Youtube",
|
||||
"description": "在 Youtube 上搜索"
|
||||
},
|
||||
"torrents": {
|
||||
"name": "Torrents",
|
||||
"description": "搜索 Torrents"
|
||||
},
|
||||
"overseerr": {
|
||||
"name": "Overseerr",
|
||||
"description": "在 Overseer 上搜索电影和电视剧。"
|
||||
}
|
||||
},
|
||||
"tip": "您可以使用以下快捷键选择搜索栏 ",
|
||||
"switchedSearchEngine": "改用 {{searchEngine}} 进行搜索"
|
||||
}
|
||||
93
public/locales/cn/modules/torrents-status.json
Normal file
93
public/locales/cn/modules/torrents-status.json
Normal file
@@ -0,0 +1,93 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Torrent",
|
||||
"description": "显示支持的 Torrent 客户端的 Torrent 列表。",
|
||||
"settings": {
|
||||
"title": "Torrent 组件设置",
|
||||
"refreshInterval": {
|
||||
"label": "刷新间隔(秒)"
|
||||
},
|
||||
"displayCompletedTorrents": {
|
||||
"label": "显示已完成的种子"
|
||||
},
|
||||
"displayActiveTorrents": {
|
||||
"label": "显示正活跃的种子"
|
||||
},
|
||||
"speedLimitOfActiveTorrents": {
|
||||
"label": "将torrent视为活动的上传速度(kB/s)"
|
||||
},
|
||||
"displayStaleTorrents": {
|
||||
"label": "显示已过期的种子"
|
||||
},
|
||||
"labelFilterIsWhitelist": {
|
||||
"label": "标签列表是白名单 (而不是黑名单)"
|
||||
},
|
||||
"labelFilter": {
|
||||
"label": "标签列表",
|
||||
"description": "当选中 “白名单” 时,这将成为白名单。如果不选中,则是黑名单。为空时不会做任何事情。"
|
||||
},
|
||||
"displayRatioWithFilter": {
|
||||
"label": "显示过滤后的 torrents 列表比例",
|
||||
"info": "如果禁用,则只显示全局比率。如果设置为 \"禁用\",全局比率仍将使用标签。"
|
||||
}
|
||||
}
|
||||
},
|
||||
"card": {
|
||||
"footer": {
|
||||
"error": "错误",
|
||||
"lastUpdated": "最后更新于 {{time}} 前",
|
||||
"ratioGlobal": "全局比率",
|
||||
"ratioWithFilter": "含过滤后的比率"
|
||||
},
|
||||
"table": {
|
||||
"header": {
|
||||
"name": "名称",
|
||||
"size": "大小",
|
||||
"download": "下载",
|
||||
"upload": "上传",
|
||||
"estimatedTimeOfArrival": "剩余时间",
|
||||
"progress": "进度"
|
||||
},
|
||||
"item": {
|
||||
"text": "由 {{appName}}, {{ratio}} 管理的比率"
|
||||
},
|
||||
"body": {
|
||||
"nothingFound": "没有找到种子",
|
||||
"filterHidingItems": "您的过滤器隐藏了 {{count}} 条记录"
|
||||
}
|
||||
},
|
||||
"lineChart": {
|
||||
"title": "当前下载速度",
|
||||
"download": "下载:{{download}}",
|
||||
"upload": "上传: {{upload}}",
|
||||
"timeSpan": "{{seconds}} 秒前",
|
||||
"totalDownload": "下载: {{download}}/秒",
|
||||
"totalUpload": "上传: {{upload}}/秒"
|
||||
},
|
||||
"errors": {
|
||||
"noDownloadClients": {
|
||||
"title": "没有找到支持的Torrent客户端!",
|
||||
"text": "添加一个支持的 Torrent 客户端来查看您当前的下载情况"
|
||||
},
|
||||
"generic": {
|
||||
"title": "发生了一个意外的错误",
|
||||
"text": "无法与您的 Torrent 客户端通信。请检查您的配置"
|
||||
}
|
||||
},
|
||||
"loading": {
|
||||
"title": "加载中",
|
||||
"description": "建立连接中"
|
||||
},
|
||||
"popover": {
|
||||
"introductionPrefix": "管理方:",
|
||||
"metrics": {
|
||||
"queuePosition": "队列位置 - {{position}}",
|
||||
"progress": "进度 - {{progress}}%",
|
||||
"totalSelectedSize": "共计 - {{totalSize}}",
|
||||
"state": "状态 - {{state}}",
|
||||
"ratio": "比率 -",
|
||||
"completed": "已完成"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
49
public/locales/cn/modules/usenet.json
Normal file
49
public/locales/cn/modules/usenet.json
Normal file
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "Usenet",
|
||||
"description": "允许您查看和管理您的 Usenet 实例。"
|
||||
},
|
||||
"card": {
|
||||
"errors": {
|
||||
"noDownloadClients": {
|
||||
"title": "没有找到支持的下载客户端!",
|
||||
"text": "添加支持的 Usenet 下载客户端来查看当前下载情况"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tabs": {
|
||||
"queue": "队列",
|
||||
"history": "历史"
|
||||
},
|
||||
"info": {
|
||||
"sizeLeft": "左侧大小",
|
||||
"paused": "已暂停"
|
||||
},
|
||||
"queue": {
|
||||
"header": {
|
||||
"name": "名称",
|
||||
"size": "大小",
|
||||
"eta": "剩余时间",
|
||||
"progress": "进度"
|
||||
},
|
||||
"empty": "空",
|
||||
"error": {
|
||||
"title": "错误",
|
||||
"message": "出错了"
|
||||
},
|
||||
"paused": "已暂停"
|
||||
},
|
||||
"history": {
|
||||
"header": {
|
||||
"name": "名称",
|
||||
"size": "大小",
|
||||
"duration": "持续时间"
|
||||
},
|
||||
"empty": "空",
|
||||
"error": {
|
||||
"title": "错误",
|
||||
"message": "加载历史记录时出错"
|
||||
},
|
||||
"paused": "已暂停"
|
||||
}
|
||||
}
|
||||
24
public/locales/cn/modules/video-stream.json
Normal file
24
public/locales/cn/modules/video-stream.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "视频流",
|
||||
"description": "嵌入来自相机或网站的视频流或视频",
|
||||
"settings": {
|
||||
"title": "视频流组件设置",
|
||||
"FeedUrl": {
|
||||
"label": "订阅网址"
|
||||
},
|
||||
"autoPlay": {
|
||||
"label": "自动播放"
|
||||
},
|
||||
"muted": {
|
||||
"label": "静音"
|
||||
},
|
||||
"controls": {
|
||||
"label": "视频播放控件"
|
||||
}
|
||||
}
|
||||
},
|
||||
"errors": {
|
||||
"invalidStream": "无效数据流"
|
||||
}
|
||||
}
|
||||
37
public/locales/cn/modules/weather.json
Normal file
37
public/locales/cn/modules/weather.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"descriptor": {
|
||||
"name": "天气",
|
||||
"description": "显示指定位置的当前天气信息。",
|
||||
"settings": {
|
||||
"title": "天气组件设置",
|
||||
"displayInFahrenheit": {
|
||||
"label": "显示为华氏度"
|
||||
},
|
||||
"displayCityName": {
|
||||
"label": "显示城市名称"
|
||||
},
|
||||
"location": {
|
||||
"label": "天气位置"
|
||||
}
|
||||
}
|
||||
},
|
||||
"card": {
|
||||
"weatherDescriptions": {
|
||||
"clear": "晴朗",
|
||||
"mainlyClear": "晴朗为主",
|
||||
"fog": "雾",
|
||||
"drizzle": "细雨",
|
||||
"freezingDrizzle": "冻毛毛雨",
|
||||
"rain": "雨",
|
||||
"freezingRain": "冻雨",
|
||||
"snowFall": "降雪",
|
||||
"snowGrains": "霰",
|
||||
"rainShowers": "阵雨",
|
||||
"snowShowers": "阵雪",
|
||||
"thunderstorm": "雷暴",
|
||||
"thunderstormWithHail": "雷暴夹冰雹",
|
||||
"unknown": "未知"
|
||||
}
|
||||
},
|
||||
"error": "出现了一个错误"
|
||||
}
|
||||
7
public/locales/cn/password-requirements.json
Normal file
7
public/locales/cn/password-requirements.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"number": "包含数字",
|
||||
"lowercase": "包括小写字母",
|
||||
"uppercase": "包含大写字母",
|
||||
"special": "包含特殊符号",
|
||||
"length": "至少包含 {{count}} 个字符"
|
||||
}
|
||||
38
public/locales/cn/settings/common.json
Normal file
38
public/locales/cn/settings/common.json
Normal file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"title": "设置",
|
||||
"tooltip": "设置",
|
||||
"tabs": {
|
||||
"common": "常规",
|
||||
"customizations": "个性化"
|
||||
},
|
||||
"tips": {
|
||||
"configTip": "将配置文件拖放到页面上即可上传!"
|
||||
},
|
||||
"credits": {
|
||||
"madeWithLove": "用❤️创造 来自",
|
||||
"thirdPartyContent": "查看第三方内容",
|
||||
"thirdPartyContentTable": {
|
||||
"dependencyName": "依赖",
|
||||
"dependencyVersion": "版本"
|
||||
}
|
||||
},
|
||||
"grow": "放大网格 (占用所有空间)",
|
||||
"layout": {
|
||||
"preview": {
|
||||
"title": "预览",
|
||||
"subtitle": "更改会自动保存"
|
||||
},
|
||||
"divider": "布局选项",
|
||||
"main": "主要",
|
||||
"sidebar": "侧边栏",
|
||||
"cannotturnoff": "无法关闭",
|
||||
"dashboardlayout": "面板布局",
|
||||
"enablersidebar": "启用右侧栏",
|
||||
"enablelsidebar": "启用左侧栏",
|
||||
"enablesearchbar": "启用搜索栏",
|
||||
"enabledocker": "启用 docker 集成",
|
||||
"enableping": "启用 Ping 功能",
|
||||
"enablelsidebardesc": "可选项。只能用于应用和集成使用",
|
||||
"enablersidebardesc": "可选项。只能用于应用和集成使用"
|
||||
}
|
||||
}
|
||||
6
public/locales/cn/settings/customization/access.json
Normal file
6
public/locales/cn/settings/customization/access.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"allowGuests": {
|
||||
"label": "允许匿名用户",
|
||||
"description": "允许未登录的用户查看您的面板"
|
||||
}
|
||||
}
|
||||
29
public/locales/cn/settings/customization/general.json
Normal file
29
public/locales/cn/settings/customization/general.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"text": "个性化设置允许您根据自己的喜好配置和调整 Homarr 的使用体验。",
|
||||
"accordeon": {
|
||||
"layout": {
|
||||
"name": "显示布局",
|
||||
"description": "启用或禁用标题和面板上的元素"
|
||||
},
|
||||
"gridstack": {
|
||||
"name": "网格堆栈",
|
||||
"description": "自定义您的面板区域的行为和栏目"
|
||||
},
|
||||
"pageMetadata": {
|
||||
"name": "页面元数据",
|
||||
"description": "调整标题、Logo 和 PWA"
|
||||
},
|
||||
"appereance": {
|
||||
"name": "外观",
|
||||
"description": "自定义背景、颜色和应用的外观"
|
||||
},
|
||||
"accessibility": {
|
||||
"name": "无障碍服务",
|
||||
"description": "为残疾和残障人士配置 Homarr"
|
||||
},
|
||||
"access": {
|
||||
"name": "访问权限",
|
||||
"description": "配置谁有权访问您的面板"
|
||||
}
|
||||
}
|
||||
}
|
||||
10
public/locales/cn/settings/customization/gridstack.json
Normal file
10
public/locales/cn/settings/customization/gridstack.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"columnsCount": {
|
||||
"labelPreset": "列的大小为{{size}}",
|
||||
"descriptionPreset": "屏幕宽度小于 {{pixels}} 像素时的列数",
|
||||
"descriptionExceedsPreset": "屏幕宽度超过 {{pixels}} 像素时的列数"
|
||||
},
|
||||
"unsavedChanges": "您有未保存的更改。单击下面的 \"应用更改 \"按钮应用并保存。",
|
||||
"applyChanges": "应用更改",
|
||||
"defaultValues": "默认值"
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"label": "应用的不透明度"
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"pageTitle": {
|
||||
"label": "页面标题",
|
||||
"description": "面板中左上角的标题"
|
||||
},
|
||||
"metaTitle": {
|
||||
"label": "元标题",
|
||||
"description": "在您的浏览器标签页中显示的标题"
|
||||
},
|
||||
"logo": {
|
||||
"label": "Logo",
|
||||
"description": "显示在左上方的 Logo"
|
||||
},
|
||||
"favicon": {
|
||||
"label": "图标",
|
||||
"description": "在您的浏览器标签页中显示的图标"
|
||||
},
|
||||
"background": {
|
||||
"label": "背景"
|
||||
},
|
||||
"customCSS": {
|
||||
"label": "自定义 CSS",
|
||||
"description": "只推荐有经验的用户使用 CSS 自定义面板",
|
||||
"placeholder": "自定义 CSS 将在最后应用",
|
||||
"applying": "应用CSS中..."
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"label": "阴影"
|
||||
}
|
||||
24
public/locales/cn/settings/general/cache-buttons.json
Normal file
24
public/locales/cn/settings/general/cache-buttons.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"title": "清除缓存",
|
||||
"selector": {
|
||||
"label": "选择要清除的缓存",
|
||||
"data": {
|
||||
"ping": "Ping 查询",
|
||||
"repositoryIcons": "远程/本地图标",
|
||||
"calendar&medias": "日历中的媒体",
|
||||
"weather": "天气数据"
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"notificationTitle": "已清除缓存",
|
||||
"clearAll": {
|
||||
"text": "清除所有缓存",
|
||||
"notificationMessage": "已清除所有缓存"
|
||||
},
|
||||
"clearSelect": {
|
||||
"text": "清除所选缓存",
|
||||
"notificationMessageSingle": "{{value}} 的缓存已清除",
|
||||
"notificationMessageMulti": "{{values}} 的缓存已清除"
|
||||
}
|
||||
}
|
||||
}
|
||||
86
public/locales/cn/settings/general/config-changer.json
Normal file
86
public/locales/cn/settings/general/config-changer.json
Normal file
@@ -0,0 +1,86 @@
|
||||
{
|
||||
"configSelect": {
|
||||
"label": "配置更改",
|
||||
"description": "{{configCount}} 个可用的配置",
|
||||
"loadingNew": "正在加载您的配置...",
|
||||
"pleaseWait": "请等待您的新配置加载完成!"
|
||||
},
|
||||
"modal": {
|
||||
"copy": {
|
||||
"title": "选择新配置的名称",
|
||||
"form": {
|
||||
"configName": {
|
||||
"label": "配置名称",
|
||||
"validation": {
|
||||
"required": "配置名称是必填项",
|
||||
"notUnique": "配置名称已被使用"
|
||||
},
|
||||
"placeholder": "您的新配置名称"
|
||||
},
|
||||
"submitButton": "确认"
|
||||
},
|
||||
"events": {
|
||||
"configSaved": {
|
||||
"title": "配置已保存",
|
||||
"message": "配置保存为 {{configName}}"
|
||||
},
|
||||
"configCopied": {
|
||||
"title": "配置已复制",
|
||||
"message": "配置复制为 {{configName}}"
|
||||
},
|
||||
"configNotCopied": {
|
||||
"title": "无法复制配置",
|
||||
"message": "您的配置没有被复制为 {{configName}}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"confirmDeletion": {
|
||||
"title": "确认删除您的配置",
|
||||
"warningText": "您即将删除 '<b>{{configName}}</b>'",
|
||||
"text": "请注意:删除是不可逆的,您的数据将永久丢失。点击此按钮后,该文件将从你的磁盘中永久删除。请确保已为你的配置创建了一个合适的备份。",
|
||||
"buttons": {
|
||||
"confirm": "是的,删除 '<b>{{configName}}</b>' 。"
|
||||
}
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"download": "下载配置",
|
||||
"delete": {
|
||||
"text": "删除配置",
|
||||
"notifications": {
|
||||
"deleted": {
|
||||
"title": "配置已删除",
|
||||
"message": "配置已删除"
|
||||
},
|
||||
"deleteFailed": {
|
||||
"title": "配置删除失败",
|
||||
"message": "配置删除失败"
|
||||
},
|
||||
"deleteFailedDefaultConfig": {
|
||||
"title": "默认配置不能被删除",
|
||||
"message": "配置没有从文件系统中删除"
|
||||
}
|
||||
}
|
||||
},
|
||||
"saveCopy": "保存副本"
|
||||
},
|
||||
"dropzone": {
|
||||
"notifications": {
|
||||
"invalidConfig": {
|
||||
"title": "无法加载配置",
|
||||
"message": "无法加载您的配置。无效的 JSON 格式。"
|
||||
},
|
||||
"loadedSuccessfully": {
|
||||
"title": "配置 {{configName}} 已成功加载。"
|
||||
}
|
||||
},
|
||||
"accept": {
|
||||
"title": "上传配置",
|
||||
"text": "将文件拖动到这里上传配置。仅支持 JSON 文件。"
|
||||
},
|
||||
"reject": {
|
||||
"title": "拖放上传被拒绝",
|
||||
"text": "此文件格式不受支持。请只上传 JSON 文件。"
|
||||
}
|
||||
}
|
||||
}
|
||||
22
public/locales/cn/settings/general/edit-mode-toggle.json
Normal file
22
public/locales/cn/settings/general/edit-mode-toggle.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"menu": {
|
||||
"toggle": "切换编辑模式",
|
||||
"enable": "启用编辑模式",
|
||||
"disable": "关闭编辑模式"
|
||||
},
|
||||
"form": {
|
||||
"label": "编辑密码",
|
||||
"message": "要切换编辑模式,需要在名为 <Code>EDIT_MODE_PASSWORD</Code> 的环境变量中输入密码。如果未设置,则无法切换编辑模式。",
|
||||
"submit": "提交"
|
||||
},
|
||||
"notification": {
|
||||
"success": {
|
||||
"title": "成功",
|
||||
"message": "成功切换编辑模式,重新加载页面..."
|
||||
},
|
||||
"error": {
|
||||
"title": "错误",
|
||||
"message": "切换编辑模式失败,请重试。"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"label": "语言"
|
||||
}
|
||||
20
public/locales/cn/settings/general/search-engine.json
Normal file
20
public/locales/cn/settings/general/search-engine.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"title": "搜索引擎",
|
||||
"configurationName": "搜索引擎设置",
|
||||
"custom": "自定义",
|
||||
"tips": {
|
||||
"generalTip": "您可以使用多种前缀!将这些添加到您的查询前将过滤结果。:!s (网页), !t (Torrents), !y (YouTube), 和 !m (媒体)。",
|
||||
"placeholderTip": "%s 可以作为查询的占位符。"
|
||||
},
|
||||
"customEngine": {
|
||||
"title": "自定义搜索引擎",
|
||||
"label": "查询网址",
|
||||
"placeholder": "自定义查询网址"
|
||||
},
|
||||
"searchNewTab": {
|
||||
"label": "在新选项卡中打开搜索结果页"
|
||||
},
|
||||
"searchEnabled": {
|
||||
"label": "启用搜索"
|
||||
}
|
||||
}
|
||||
3
public/locales/cn/settings/general/widget-positions.json
Normal file
3
public/locales/cn/settings/general/widget-positions.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"label": "将组件放在左边"
|
||||
}
|
||||
32
public/locales/cn/tools/docker.json
Normal file
32
public/locales/cn/tools/docker.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"title": "Docker",
|
||||
"alerts": {
|
||||
"notConfigured": {
|
||||
"text": "您的 Homarr 实例未配置 Docker,或无法获取容器。请查看文档,了解如何设置集成。"
|
||||
}
|
||||
},
|
||||
"modals": {
|
||||
"selectBoard": {
|
||||
"title": "选择一个面板",
|
||||
"text": "选择您想要为选定的 Docker 容器添加应用的面板。",
|
||||
"form": {
|
||||
"board": {
|
||||
"label": "面板"
|
||||
},
|
||||
"submit": "添加应用"
|
||||
}
|
||||
}
|
||||
},
|
||||
"notifications": {
|
||||
"selectBoard": {
|
||||
"success": {
|
||||
"title": "添加应用到面板",
|
||||
"message": "选定的 Docker 容器的应用已添加到面板中。"
|
||||
},
|
||||
"error": {
|
||||
"title": "添加应用到面板失败",
|
||||
"message": "所选Docker容器的应用无法添加到面板中。"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
48
public/locales/cn/user/preferences.json
Normal file
48
public/locales/cn/user/preferences.json
Normal file
@@ -0,0 +1,48 @@
|
||||
{
|
||||
"metaTitle": "首选项",
|
||||
"pageTitle": "您的首选项",
|
||||
"boards": {
|
||||
"defaultBoard": {
|
||||
"label": "默认面板"
|
||||
}
|
||||
},
|
||||
"accessibility": {
|
||||
"title": "无障碍服务",
|
||||
"disablePulse": {
|
||||
"label": "禁用 Ping",
|
||||
"description": "默认情况下,Homarr 中的 Ping 指示器会一直工作。这可能会让人感到恼火。这个滑块将停用该动画。"
|
||||
},
|
||||
"replaceIconsWithDots": {
|
||||
"label": "用图标替换 Ping 点",
|
||||
"description": "对于色盲用户来说,Ping 点可能无法识别。 这将用图标替换指示器"
|
||||
}
|
||||
},
|
||||
"localization": {
|
||||
"language": {
|
||||
"label": "语言"
|
||||
},
|
||||
"firstDayOfWeek": {
|
||||
"label": "一周的第一天",
|
||||
"options": {
|
||||
"monday": "周一",
|
||||
"saturday": "周六",
|
||||
"sunday": "周日"
|
||||
}
|
||||
}
|
||||
},
|
||||
"searchEngine": {
|
||||
"title": "搜索引擎",
|
||||
"custom": "自定义",
|
||||
"newTab": {
|
||||
"label": "在新选项卡中打开搜索结果页"
|
||||
},
|
||||
"autoFocus": {
|
||||
"label": "页面加载时聚焦搜索栏。",
|
||||
"description": "当您导航到面板页面时,搜索栏会自动聚焦。该功能仅适用于桌面设备。"
|
||||
},
|
||||
"template": {
|
||||
"label": "查询网址",
|
||||
"description": "使用 %s 作为查询的占位符"
|
||||
}
|
||||
}
|
||||
}
|
||||
7
public/locales/cn/widgets/draggable-list.json
Normal file
7
public/locales/cn/widgets/draggable-list.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"noEntries": {
|
||||
"title": "没有条目",
|
||||
"text": "使用下方按钮添加更多条目"
|
||||
},
|
||||
"buttonAdd": "添加"
|
||||
}
|
||||
14
public/locales/cn/widgets/error-boundary.json
Normal file
14
public/locales/cn/widgets/error-boundary.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"card": {
|
||||
"title": "哎呀,出错了!",
|
||||
"buttons": {
|
||||
"details": "详情",
|
||||
"tryAgain": "请再试一次"
|
||||
}
|
||||
},
|
||||
"modal": {
|
||||
"text": "",
|
||||
"label": "您的错误",
|
||||
"reportButton": "报告该错误"
|
||||
}
|
||||
}
|
||||
22
public/locales/cn/zod.json
Normal file
22
public/locales/cn/zod.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"errors": {
|
||||
"default": "该字段无效",
|
||||
"required": "此字段为必填",
|
||||
"string": {
|
||||
"startsWith": "该字段必须以 {{startsWith}} 开头",
|
||||
"endsWith": "该字段必须以 {{endsWith}} 结尾",
|
||||
"includes": "该字段必须包含 {{includes}}"
|
||||
},
|
||||
"tooSmall": {
|
||||
"string": "该字段的长度必须至少为 {{minimum}} 个字符",
|
||||
"number": "该字段必须大于或等于 {{minimum}}"
|
||||
},
|
||||
"tooBig": {
|
||||
"string": "该字段的长度不得超过 {{maximum}} 个字符",
|
||||
"number": "该字段必须小于或等于 {{maximum}}"
|
||||
},
|
||||
"custom": {
|
||||
"passwordMatch": "两次输入的密码必须一致"
|
||||
}
|
||||
}
|
||||
}
|
||||
35
public/locales/cr/authentication/invite.json
Normal file
35
public/locales/cr/authentication/invite.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"metaTitle": "crwdns3635:0crwdne3635:0",
|
||||
"title": "crwdns3637:0crwdne3637:0",
|
||||
"text": "crwdns3639:0crwdne3639:0",
|
||||
"form": {
|
||||
"fields": {
|
||||
"username": {
|
||||
"label": "crwdns3641:0crwdne3641:0"
|
||||
},
|
||||
"password": {
|
||||
"label": "crwdns3643:0crwdne3643:0"
|
||||
},
|
||||
"passwordConfirmation": {
|
||||
"label": "crwdns3645:0crwdne3645:0"
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"submit": "crwdns3647:0crwdne3647:0"
|
||||
}
|
||||
},
|
||||
"notifications": {
|
||||
"loading": {
|
||||
"title": "crwdns3649:0crwdne3649:0",
|
||||
"text": "crwdns3651:0crwdne3651:0"
|
||||
},
|
||||
"success": {
|
||||
"title": "crwdns3653:0crwdne3653:0",
|
||||
"text": "crwdns3655:0crwdne3655:0"
|
||||
},
|
||||
"error": {
|
||||
"title": "crwdns3657:0crwdne3657:0",
|
||||
"text": "crwdns3659:0{{error}}crwdne3659:0"
|
||||
}
|
||||
}
|
||||
}
|
||||
20
public/locales/cr/authentication/login.json
Normal file
20
public/locales/cr/authentication/login.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"metaTitle": "crwdns3341:0crwdne3341:0",
|
||||
"title": "crwdns1868:0crwdne1868:0",
|
||||
"text": "crwdns3343:0crwdne3343:0",
|
||||
"form": {
|
||||
"fields": {
|
||||
"username": {
|
||||
"label": "crwdns3345:0crwdne3345:0"
|
||||
},
|
||||
"password": {
|
||||
"label": "crwdns1872:0crwdne1872:0"
|
||||
}
|
||||
},
|
||||
"buttons": {
|
||||
"submit": "crwdns1876:0crwdne1876:0"
|
||||
},
|
||||
"afterLoginRedirection": "crwdns3347:0{{url}}crwdne3347:0"
|
||||
},
|
||||
"alert": "crwdns3349:0crwdne3349:0"
|
||||
}
|
||||
5
public/locales/cr/boards/common.json
Normal file
5
public/locales/cr/boards/common.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"header": {
|
||||
"customize": "crwdns3477:0crwdne3477:0"
|
||||
}
|
||||
}
|
||||
29
public/locales/cr/boards/customize.json
Normal file
29
public/locales/cr/boards/customize.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"metaTitle": "crwdns3479:0{{name}}crwdne3479:0",
|
||||
"pageTitle": "crwdns3481:0{{name}}crwdne3481:0",
|
||||
"backToBoard": "crwdns3483:0crwdne3483:0",
|
||||
"settings": {
|
||||
"appearance": {
|
||||
"primaryColor": "crwdns3485:0crwdne3485:0",
|
||||
"secondaryColor": "crwdns3487:0crwdne3487:0"
|
||||
}
|
||||
},
|
||||
"save": {
|
||||
"button": "crwdns3489:0crwdne3489:0",
|
||||
"note": "crwdns3491:0crwdne3491:0"
|
||||
},
|
||||
"notifications": {
|
||||
"pending": {
|
||||
"title": "crwdns3493:0crwdne3493:0",
|
||||
"message": "crwdns3495:0crwdne3495:0"
|
||||
},
|
||||
"success": {
|
||||
"title": "crwdns3497:0crwdne3497:0",
|
||||
"message": "crwdns3499:0crwdne3499:0"
|
||||
},
|
||||
"error": {
|
||||
"title": "crwdns3501:0crwdne3501:0",
|
||||
"message": "crwdns3503:0crwdne3503:0"
|
||||
}
|
||||
}
|
||||
}
|
||||
55
public/locales/cr/common.json
Normal file
55
public/locales/cr/common.json
Normal file
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"save": "crwdns2009:0crwdne2009:0",
|
||||
"apply": "crwdns3900:0crwdne3900:0",
|
||||
"insert": "crwdns3902:0crwdne3902:0",
|
||||
"about": "crwdns2011:0crwdne2011:0",
|
||||
"cancel": "crwdns2013:0crwdne2013:0",
|
||||
"close": "crwdns2015:0crwdne2015:0",
|
||||
"back": "crwdns3371:0crwdne3371:0",
|
||||
"delete": "crwdns2017:0crwdne2017:0",
|
||||
"ok": "crwdns2019:0crwdne2019:0",
|
||||
"edit": "crwdns2021:0crwdne2021:0",
|
||||
"next": "crwdns3373:0crwdne3373:0",
|
||||
"previous": "crwdns3375:0crwdne3375:0",
|
||||
"confirm": "crwdns3377:0crwdne3377:0",
|
||||
"enabled": "crwdns2883:0crwdne2883:0",
|
||||
"disabled": "crwdns2885:0crwdne2885:0",
|
||||
"enableAll": "crwdns2887:0crwdne2887:0",
|
||||
"disableAll": "crwdns2889:0crwdne2889:0",
|
||||
"version": "crwdns2023:0crwdne2023:0",
|
||||
"changePosition": "crwdns2025:0crwdne2025:0",
|
||||
"remove": "crwdns2027:0crwdne2027:0",
|
||||
"removeConfirm": "crwdns2683:0{{item}}crwdne2683:0",
|
||||
"createItem": "crwdns2793:0{{item}}crwdne2793:0",
|
||||
"sections": {
|
||||
"settings": "crwdns2029:0crwdne2029:0",
|
||||
"dangerZone": "crwdns2031:0crwdne2031:0"
|
||||
},
|
||||
"secrets": {
|
||||
"apiKey": "crwdns2685:0crwdne2685:0",
|
||||
"username": "crwdns2035:0crwdne2035:0",
|
||||
"password": "crwdns2037:0crwdne2037:0"
|
||||
},
|
||||
"tip": "crwdns1260:0crwdne1260:0",
|
||||
"time": {
|
||||
"seconds": "crwdns1860:0crwdne1860:0",
|
||||
"minutes": "crwdns1862:0crwdne1862:0",
|
||||
"hours": "crwdns1864:0crwdne1864:0"
|
||||
},
|
||||
"loading": "crwdns2523:0crwdne2523:0",
|
||||
"breakPoints": {
|
||||
"small": "crwdns2525:0crwdne2525:0",
|
||||
"medium": "crwdns2527:0crwdne2527:0",
|
||||
"large": "crwdns2529:0crwdne2529:0"
|
||||
},
|
||||
"seeMore": "crwdns3019:0crwdne3019:0",
|
||||
"position": {
|
||||
"left": "crwdns3904:0crwdne3904:0",
|
||||
"center": "crwdns3906:0crwdne3906:0",
|
||||
"right": "crwdns3908:0crwdne3908:0"
|
||||
},
|
||||
"attributes": {
|
||||
"width": "crwdns3910:0crwdne3910:0",
|
||||
"height": "crwdns3912:0crwdne3912:0"
|
||||
}
|
||||
}
|
||||
25
public/locales/cr/layout/common.json
Normal file
25
public/locales/cr/layout/common.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"modals": {
|
||||
"blockedPopups": {
|
||||
"title": "crwdns2997:0crwdne2997:0",
|
||||
"text": "crwdns2999:0crwdne2999:0",
|
||||
"list": {
|
||||
"browserPermission": "crwdns3001:0crwdne3001:0",
|
||||
"adBlockers": "crwdns3003:0crwdne3003:0",
|
||||
"otherBrowser": "crwdns3005:0crwdne3005:0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"actions": {
|
||||
"category": {
|
||||
"openAllInNewTab": "crwdns3007:0crwdne3007:0"
|
||||
}
|
||||
},
|
||||
"menu": {
|
||||
"moveUp": "crwdns3213:0crwdne3213:0",
|
||||
"moveDown": "crwdns3215:0crwdne3215:0",
|
||||
"addCategory": "crwdns3251:0{{location}}crwdne3251:0",
|
||||
"addAbove": "crwdns3219:0crwdne3219:0",
|
||||
"addBelow": "crwdns3221:0crwdne3221:0"
|
||||
}
|
||||
}
|
||||
25
public/locales/cr/layout/element-selector/selector.json
Normal file
25
public/locales/cr/layout/element-selector/selector.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"modal": {
|
||||
"title": "crwdns1989:0crwdne1989:0",
|
||||
"text": "crwdns2293:0crwdne2293:0"
|
||||
},
|
||||
"widgetDescription": "crwdns2295:0crwdne2295:0",
|
||||
"goBack": "crwdns1995:0crwdne1995:0",
|
||||
"actionIcon": {
|
||||
"tooltip": "crwdns1997:0crwdne1997:0"
|
||||
},
|
||||
"apps": "crwdns3231:0crwdne3231:0",
|
||||
"app": {
|
||||
"defaultName": "crwdns3233:0crwdne3233:0"
|
||||
},
|
||||
"widgets": "crwdns3235:0crwdne3235:0",
|
||||
"categories": "crwdns3237:0crwdne3237:0",
|
||||
"category": {
|
||||
"newName": "crwdns3239:0crwdne3239:0",
|
||||
"defaultName": "crwdns3241:0crwdne3241:0",
|
||||
"created": {
|
||||
"title": "crwdns3243:0crwdne3243:0",
|
||||
"message": "crwdns3245:0{{name}}crwdne3245:0"
|
||||
}
|
||||
}
|
||||
}
|
||||
5
public/locales/cr/layout/errors/access-denied.json
Normal file
5
public/locales/cr/layout/errors/access-denied.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"title": "crwdns3866:0crwdne3866:0",
|
||||
"text": "crwdns3868:0crwdne3868:0",
|
||||
"switchAccount": "crwdns3870:0crwdne3870:0"
|
||||
}
|
||||
5
public/locales/cr/layout/errors/not-found.json
Normal file
5
public/locales/cr/layout/errors/not-found.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"title": "crwdns3049:0crwdne3049:0",
|
||||
"text": "crwdns3051:0crwdne3051:0",
|
||||
"button": "crwdns3053:0crwdne3053:0"
|
||||
}
|
||||
30
public/locales/cr/layout/header.json
Normal file
30
public/locales/cr/layout/header.json
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
"experimentalNote": {
|
||||
"label": "crwdns3445:0crwdne3445:0"
|
||||
},
|
||||
"search": {
|
||||
"label": "crwdns3447:0crwdne3447:0",
|
||||
"engines": {
|
||||
"web": "crwdns3449:0{{query}}crwdne3449:0",
|
||||
"youtube": "crwdns3451:0{{query}}crwdne3451:0",
|
||||
"torrent": "crwdns3453:0{{query}}crwdne3453:0",
|
||||
"movie": "crwdns3455:0{{query}}crwdnd3455:0{{app}}crwdne3455:0"
|
||||
}
|
||||
},
|
||||
"actions": {
|
||||
"avatar": {
|
||||
"switchTheme": "crwdns3457:0crwdne3457:0",
|
||||
"preferences": "crwdns3459:0crwdne3459:0",
|
||||
"defaultBoard": "crwdns3461:0crwdne3461:0",
|
||||
"manage": "crwdns3463:0crwdne3463:0",
|
||||
"logout": "crwdns3469:0{{username}}crwdne3469:0",
|
||||
"login": "crwdns3471:0crwdne3471:0"
|
||||
}
|
||||
},
|
||||
"modals": {
|
||||
"movie": {
|
||||
"title": "crwdns3473:0crwdne3473:0",
|
||||
"topResults": "crwdns3475:0{{count}}crwdnd3475:0{{search}}crwdne3475:0"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"description": "crwdns2297:0crwdne2297:0",
|
||||
"button": {
|
||||
"disabled": "crwdns2001:0crwdne2001:0",
|
||||
"enabled": "crwdns2003:0crwdne2003:0"
|
||||
},
|
||||
"popover": {
|
||||
"title": "crwdns2403:0{{size}}crwdne2403:0",
|
||||
"text": "crwdns2405:0crwdne2405:0"
|
||||
},
|
||||
"unloadEvent": "crwdns3275:0crwdne3275:0"
|
||||
}
|
||||
35
public/locales/cr/layout/manage.json
Normal file
35
public/locales/cr/layout/manage.json
Normal file
@@ -0,0 +1,35 @@
|
||||
{
|
||||
"navigation": {
|
||||
"home": {
|
||||
"title": "crwdns3505:0crwdne3505:0"
|
||||
},
|
||||
"boards": {
|
||||
"title": "crwdns3507:0crwdne3507:0"
|
||||
},
|
||||
"users": {
|
||||
"title": "crwdns3509:0crwdne3509:0",
|
||||
"items": {
|
||||
"manage": "crwdns3511:0crwdne3511:0",
|
||||
"invites": "crwdns3513:0crwdne3513:0"
|
||||
}
|
||||
},
|
||||
"help": {
|
||||
"title": "crwdns3515:0crwdne3515:0",
|
||||
"items": {
|
||||
"documentation": "crwdns3517:0crwdne3517:0",
|
||||
"report": "crwdns3519:0crwdne3519:0",
|
||||
"discord": "crwdns3521:0crwdne3521:0",
|
||||
"contribute": "crwdns3523:0crwdne3523:0"
|
||||
}
|
||||
},
|
||||
"tools": {
|
||||
"title": "crwdns3525:0crwdne3525:0",
|
||||
"items": {
|
||||
"docker": "crwdns3527:0crwdne3527:0"
|
||||
}
|
||||
},
|
||||
"about": {
|
||||
"title": "crwdns3990:0crwdne3990:0"
|
||||
}
|
||||
}
|
||||
}
|
||||
3
public/locales/cr/layout/mobile/drawer.json
Normal file
3
public/locales/cr/layout/mobile/drawer.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"title": "crwdns2211:0{{position}}crwdne2211:0"
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user