Compare commits

..

102 Commits

Author SHA1 Message Date
lollipopkit🏳️‍⚧️
aaa69f0f95 chore: bump version 2024-08-04 19:26:31 +08:00
lollipopkit🏳️‍⚧️
64676bc5cb chore: l10n 2024-08-04 13:05:29 +08:00
lollipopkit🏳️‍⚧️
a15c04956c opt.: TipText 2024-08-04 12:02:57 +08:00
lollipopkit🏳️‍⚧️
e3c885483b opt.: use ssh term to decompress (#519) 2024-08-04 11:40:38 +08:00
lollipopkit🏳️‍⚧️
493c86cacb fix: home widget url (#517) 2024-08-04 00:17:21 +08:00
lollipopkit🏳️‍⚧️
ea7c8caf14 bug: color seed setting not working (#516) 2024-08-03 23:17:18 +08:00
lollipopkit🏳️‍⚧️
9db04a60c2 opt.: l10n & fix: write script (#514) 2024-08-03 22:44:21 +08:00
lollipopkit🏳️‍⚧️
610f46da0d opt.: bulk import servers (#512) 2024-08-03 14:52:39 +08:00
lollipopkit🏳️‍⚧️
b8e5418ff2 feat: import snippets from network (#510)
Fixes #507
2024-08-03 14:25:58 +08:00
lollipopkit🏳️‍⚧️
0e21755acb opt.: remove internal SharePreference keys while using KvEditor (#509)
Fixes #508
2024-08-03 12:37:16 +08:00
lollipopkit🏳️‍⚧️
73248011a1 migrate: fl_lib 2024-08-01 13:44:32 +08:00
lollipopkit🏳️‍⚧️
969643d3df opt.: debug page copy logs 2024-07-28 22:12:07 +08:00
lollipopkit🏳️‍⚧️
c90d0e4b3b fix: manual restore 2024-07-28 20:37:34 +08:00
lollipopkit🏳️‍⚧️
f9aadc6b0f opt.: Btn 2024-07-28 20:26:08 +08:00
lollipopkit🏳️‍⚧️
8fd4cc1fe1 opt.: TagsEditor & Btn 2024-07-28 19:05:31 +08:00
lollipopkit🏳️‍⚧️
432d76f024 fix: builtin editor (#503) 2024-07-28 15:06:34 +08:00
𝗦𝗵𝗟𝗲𝗿𝗣
ca8211e1a4 Add TR Locales (#497) 2024-07-27 16:42:09 +08:00
lollipopkit🏳️‍⚧️
a3b48fc01c chore: bump version 2024-07-26 23:35:59 +08:00
lollipopkit🏳️‍⚧️
8be94aa09c feat: use $EDITOR to edit files (#496)
Fixes #489
2024-07-26 23:32:57 +08:00
lollipopkit🏳️‍⚧️
5db1253ab8 fix: termux compatibility (#495) 2024-07-26 22:31:17 +08:00
lollipopkit🏳️‍⚧️
ceedd86310 rm: pkg (#494)
Fixes #470
2024-07-26 21:31:45 +08:00
lollipopkit🏳️‍⚧️
6a0254623f opt.: json input experience 2024-07-26 20:22:30 +08:00
lollipopkit🏳️‍⚧️
1c6ec56032 Create FUNDING.yml 2024-07-25 10:42:18 +08:00
lollipopkit🏳️‍⚧️
287869ed45 opt.: simplify settings page (#488) 2024-07-24 00:30:17 +08:00
lollipopkit🏳️‍⚧️
e4dbc3ba12 feat: set envs in term (#485) 2024-07-23 21:34:34 +08:00
lollipopkit🏳️‍⚧️
426e5689f8 fix: uploaded file's path on windows (#484) 2024-07-23 19:59:58 +08:00
lollipopkit🏳️‍⚧️
afda5fd4a4 fix: bio auth (#482) 2024-07-23 19:26:03 +08:00
lollipopkit🏳️‍⚧️
0a21b2820c fix: letterCacheTip translation 2024-07-23 12:14:31 +08:00
lollipopkit🏳️‍⚧️
87b3b76b0b feat: display cpu model (#477) 2024-07-23 12:03:10 +08:00
lollipopkit🏳️‍⚧️
41ec46f1d3 opt.: show loading dialog 2024-07-22 23:33:21 +08:00
lollipopkit🏳️‍⚧️
7a359588db opt.: input field suggestion 2024-07-22 22:03:56 +08:00
lollipopkit🏳️‍⚧️
255abe8b11 rollback: write script to /dev/shm (#474) 2024-07-21 17:58:14 +08:00
lollipopkit🏳️‍⚧️
b0936c5e6e fix: termux compatibility (#472) 2024-07-20 20:35:30 +08:00
lollipopkit🏳️‍⚧️
2907ac74d4 chore: bump version 2024-07-18 23:44:01 +08:00
lollipopkit🏳️‍⚧️
ea678f37b0 chore: bump version 2024-07-18 23:15:40 +08:00
lollipopkit🏳️‍⚧️
076082c945 feat: sftp perm setting & path copy (#467) 2024-07-18 21:40:40 +08:00
lollipopkit🏳️‍⚧️
5ee98f90e8 fix: update changelog (#466) 2024-07-18 20:53:22 +08:00
lollipopkit🏳️‍⚧️
c988dd88d7 fix: linux duplicated title bar (#462)
Fixes #459
2024-07-15 17:38:30 +08:00
lollipopkit🏳️‍⚧️
f7d6c461dc fix: version display (#458)
Fixes #457
2024-07-10 15:12:05 +08:00
lollipopkit🏳️‍⚧️
14771ae946 chore: README 2024-07-09 14:36:04 +08:00
lollipopkit🏳️‍⚧️
7e9086b20e fix: chmod perm 2024-07-09 14:02:23 +08:00
Noo6
4b3c4870ba fix: desktop window appbar (#450) 2024-07-05 12:42:38 +08:00
Noo6
43cebd0c04 fix: window blink on startup (#447) 2024-07-04 12:23:20 +08:00
Noo6
5ce13109b0 fix: ssh card tap area (#448) 2024-07-04 12:22:19 +08:00
lollipopkit🏳️‍⚧️
6e428c91d1 feat: disable letter cache (#446)
Fixes #445
2024-07-03 19:55:33 +08:00
lollipopkit🏳️‍⚧️
4430045550 feat: write script into /dev/shm (#444)
Fixes #443
2024-07-03 19:14:27 +08:00
lollipopkit🏳️‍⚧️
282cb06091 fix: picker dialog (#442)
Fixes #440
2024-07-03 18:19:09 +08:00
lollipopkit🏳️‍⚧️
772c2743b5 fix: no appBar in server detail page (#441)
Fixes #435
2024-07-03 16:42:52 +08:00
lollipopkit🏳️‍⚧️
90199b89a5 chore: README 2024-07-03 00:52:28 +08:00
Integral
e1d2e3f3e5 l10n: fix remaining translations (#439)
* l10n: Url -> URL

* l10n: Logo Address -> Logo URL

* l10n: fix ttl translation

* l10n: fix all zh-tw translations

* l10n: fix all zh-cn translations

* l10n: fix all en translations
2024-07-02 15:02:49 +00:00
Integral
3f9fe1f2c6 l10n: alterUrl -> fallbackSshDest (#437) 2024-07-02 13:15:19 +00:00
Integral
c79bbc5756 l10n: fix two acronyms (MAC, URL) (#436)
* l10n: Mac Address -> MAC Address

* l10n: PVE addr -> URL
2024-07-01 14:56:38 +00:00
Integral
63e1bec2b9 l10n: fix translation of net/network (#433) 2024-07-01 07:01:51 +00:00
Integral
d26b7c6f75 l10n: add noLineChartForCpu field (#431) 2024-07-01 05:24:31 +00:00
Integral
da8dc4fa54 docs(README): add f-droid & reorganize other installation methods (#429)
* docs(README): add f-droid & reorganize other installation methods

* docs(README): update Chinese README from English
2024-06-30 11:51:36 +00:00
Integral
413b81c47f l10n: fix Japanese translations (#425) 2024-06-25 16:00:42 +00:00
Integral
9ef419e3df l10n: fix English translations (#424) 2024-06-25 16:00:26 +00:00
Integral
39893912d9 Merge pull request #423 from Integral-Tech/fix-fdroid-typo
chore: fix typo of "F-Droid"
2024-06-25 14:04:16 +00:00
Integral
49456ca6c3 chore: fix typo of "F-Droid" 2024-06-25 22:00:46 +08:00
lollipopkit🏳️‍⚧️
6b9b8f0dbb chore: bump version 2024-06-25 13:15:29 +08:00
lollipopkit🏳️‍⚧️
5eb48b2717 fix: linux build (#422)
Fixes #421
2024-06-25 11:48:56 +08:00
lollipopkit🏳️‍⚧️
5339cfca70 chore: lib vers bump (#420)
Fixes #419
2024-06-25 11:16:34 +08:00
lollipopkit🏳️‍⚧️
1462b2d0b8 fix: always enter intro page (#418)
Fixes #417
2024-06-24 16:32:37 +08:00
lollipopkit🏳️‍⚧️
3798a23183 chore: bump version 2024-06-24 00:56:45 +08:00
lollipopkit🏳️‍⚧️
ddaf916170 feat: intro page (#416)
Fixes #415
2024-06-24 00:43:52 +08:00
lollipopkit🏳️‍⚧️
d6e37b058f fix: docker parse (#414)
Fixes #395
2024-06-23 18:37:05 +08:00
lollipopkit🏳️‍⚧️
2e9ad7d7cb chore: missing l10n noLineChart (#413)
Fixes #412
2024-06-23 15:39:30 +08:00
lollipopkit🏳️‍⚧️
190da74f66 chore: add participants (#410)
Fixes #409
2024-06-23 00:27:26 +08:00
lollipopkit🏳️‍⚧️
f1315dda7f fix: batch delete servers (#408)
Fixes #393
2024-06-23 00:24:30 +08:00
lollipopkit🏳️‍⚧️
43e6105eb3 fix: hideTitleBar doesn't work (#407)
Fixes #406
2024-06-22 22:58:22 +08:00
lollipopkit🏳️‍⚧️
d785209eb6 opt.: share on desktop (#405) 2024-06-22 22:50:17 +08:00
lollipopkit🏳️‍⚧️
da8b6a9010 feat: remember window size (#404)
Fixes #398
2024-06-22 21:52:48 +08:00
lollipopkit🏳️‍⚧️
1fd68722da fix: watchos settings (#403)
Fixes #401
2024-06-22 21:09:05 +08:00
lollipopkit🏳️‍⚧️
c9a2c1d0e4 Android - default to English (#402) 2024-06-18 14:39:18 +08:00
lollipopkit
161f536a62 fix: conform fdroid version fmt
Signed-off-by: lollipopkit <10864310+lollipopkit@users.noreply.github.com>
2024-06-13 23:51:10 +08:00
lollipopkit
1a32e9944e opt.: put version logic somewhere else (#381)
Signed-off-by: lollipopkit <10864310+lollipopkit@users.noreply.github.com>
2024-06-13 22:40:18 +08:00
lollipopkit
6deb753198 fix: version change logic (#381) 2024-06-13 21:29:03 +08:00
lollipopkit
4e33a98631 chore: fl_build 2024-06-13 21:22:44 +08:00
lollipopkit
dcb9464d8f fix
Signed-off-by: lollipopkit <10864310+lollipopkit@users.noreply.github.com>
2024-06-13 20:39:06 +08:00
lollipopkit
b94936b29f fix: reproducible (#381)
Signed-off-by: lollipopkit <10864310+lollipopkit@users.noreply.github.com>
2024-06-13 20:28:22 +08:00
lollipopkit
108d0a5a5b chore: bump version
Signed-off-by: lollipopkit <10864310+lollipopkit@users.noreply.github.com>
2024-06-13 00:45:24 +08:00
Integral
4814a2de28 Merge pull request #391 from Integral-Tech/add-abiCodes
Add abiCodes
2024-06-12 16:21:13 +00:00
Integral
5d8eeff502 Add abiCodes 2024-06-13 00:18:04 +08:00
lollipopkit
0bc4087266 chore: correct version for fdroid 2024-06-13 00:00:20 +08:00
lollipopkit
921209b901 chore: specify flutter version (#381) 2024-06-12 19:51:04 +08:00
lollipopkit
fa9d754470 rm: android wear settings 2024-06-12 19:42:38 +08:00
Integral
1f50a1f0f4 Merge pull request #389 from Integral-Tech/clean-up-proguard-rules
fix: clean up proguard-rules to remove depends on google libraries
2024-06-11 18:03:44 +00:00
Integral
80e84c0421 fix: clean up proguard-rules to remove depends on google libraries 2024-06-12 01:36:29 +08:00
lollipopkit
5059872c3f chore: README 2024-06-11 22:54:48 +08:00
lollipopkit
8add244776 fix: fdroid version fmt 2024-06-11 22:47:48 +08:00
lollipopkit
04e23fd7e4 fix: pubspec version 2024-06-11 22:18:27 +08:00
lollipopkit
336b11b808 chore: change dart pkg id 2024-06-11 22:06:29 +08:00
lollipopkit
8d9dba361c chore: completely rm countly 2024-06-11 22:03:17 +08:00
Integral
64ce3638cb chore: add distributionSha256Sum in gradle (#385) 2024-06-11 18:43:41 +08:00
lollipopkit
f3ceb73f0e fix: rm gms (#379 #381) 2024-06-11 16:40:05 +08:00
Integral
131dbe934c chore: setup fastlane for F-Droid submission (#384) 2024-06-11 16:18:39 +08:00
lollipopkit
58288e89bd Merge branch 'main' of github.com:lollipopkit/flutter_server_box 2024-06-10 21:35:59 +08:00
lollipopkit🏳️‍⚧️
22c43c7124 Lollipopkit/issue382 (#383) 2024-06-10 21:34:56 +08:00
lollipopkit
2bf0b25ee5 fix: podman term 2024-06-10 21:32:45 +08:00
lollipopkit
3bc03c1364 opt.: add tip (#380 #382) 2024-06-10 21:29:41 +08:00
lollipopkit
490d71f8c9 feat: snippet with term ctrl (#380 #382) 2024-06-10 21:08:33 +08:00
lollipopkit
edceb5900e opt.: write script to server tip 2024-06-09 13:57:02 +08:00
153 changed files with 3739 additions and 4250 deletions

14
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,14 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: lollipopkit
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
custom: ['https://afdian.com/a/lollipopkit'] # Replace with up to 4 custom sponsorship URLs

View File

@@ -9,16 +9,17 @@ permissions:
contents: write
jobs:
releaseAL:
name: Release android and linux
releaseAndroid:
name: Release android
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: '0'
- name: Install Flutter
uses: subosito/flutter-action@v2
with:
channel: 'stable'
flutter-version: '3.22.3'
- uses: actions/setup-java@v4
with:
distribution: 'zulu'
@@ -28,14 +29,37 @@ jobs:
curl -u ${{ secrets.BASIC_AUTH }} -o android/app/app.key ${{ secrets.URL_PREFIX }}app.key
curl -u ${{ secrets.BASIC_AUTH }} -o android/key.properties ${{ secrets.URL_PREFIX }}key.properties
- name: Build
run: dart run fl_build -p android,linux
run: dart run fl_build -p android
- name: Rename for fdroid
run: |
mv build/app/outputs/flutter-apk/${{ env.APP_NAME }}_${{ env.BUILD_NUMBER }}_arm64.apk build/app/outputs/flutter-apk/${{ env.APP_NAME }}_v1.0.${{ env.BUILD_NUMBER }}_arm64.apk
mv build/app/outputs/flutter-apk/${{ env.APP_NAME }}_${{ env.BUILD_NUMBER }}_arm.apk build/app/outputs/flutter-apk/${{ env.APP_NAME }}_v1.0.${{ env.BUILD_NUMBER }}_arm.apk
mv build/app/outputs/flutter-apk/${{ env.APP_NAME }}_${{ env.BUILD_NUMBER }}_amd64.apk build/app/outputs/flutter-apk/${{ env.APP_NAME }}_v1.0.${{ env.BUILD_NUMBER }}_amd64.apk
- name: Create Release
uses: softprops/action-gh-release@v2
with:
files: |
build/app/outputs/flutter-apk/${{ env.APP_NAME }}_v1.0.${{ env.BUILD_NUMBER }}_arm64.apk
build/app/outputs/flutter-apk/${{ env.APP_NAME }}_v1.0.${{ env.BUILD_NUMBER }}_arm.apk
build/app/outputs/flutter-apk/${{ env.APP_NAME }}_v1.0.${{ env.BUILD_NUMBER }}_amd64.apk
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
releaseLinux:
name: Release linux
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install Flutter
uses: subosito/flutter-action@v2
- name: Build
run: |
dart run fl_build -p linux
- name: Create Release
uses: softprops/action-gh-release@v2
with:
files: |
build/app/outputs/flutter-apk/${{ env.APP_NAME }}_${{ env.BUILD_NUMBER }}_arm64.apk
build/app/outputs/flutter-apk/${{ env.APP_NAME }}_${{ env.BUILD_NUMBER }}_arm.apk
build/app/outputs/flutter-apk/${{ env.APP_NAME }}_${{ env.BUILD_NUMBER }}_amd64.apk
${{ env.APP_NAME }}_${{ env.BUILD_NUMBER }}_amd64.AppImage
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -46,8 +70,6 @@ jobs:
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: '0'
- name: Install Flutter
uses: subosito/flutter-action@v2
- name: Build
@@ -68,6 +90,9 @@ jobs:
# uses: actions/checkout@v4
# - name: Install Flutter
# uses: subosito/flutter-action@v2
# with:
# channel: 'stable'
# flutter-version: '3.22.2'
# - name: Build
# run: dart run fl_build -p ios,mac
# - name: Create Release

View File

@@ -4,7 +4,7 @@
# This file should be version controlled and should not be manually edited.
version:
revision: "bae5e49bc2a867403c43b2aae2de8f8c33b037e4"
revision: "761747bfc538b5af34aa0d3fac380f1bc331ec49"
channel: "stable"
project_type: app
@@ -13,26 +13,26 @@ project_type: app
migration:
platforms:
- platform: root
create_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4
base_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: android
create_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4
base_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: ios
create_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4
base_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: linux
create_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4
base_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: macos
create_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4
base_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: web
create_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4
base_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
- platform: windows
create_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4
base_revision: bae5e49bc2a867403c43b2aae2de8f8c33b037e4
create_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
base_revision: 761747bfc538b5af34aa0d3fac380f1bc331ec49
# User provided section

4
.vscode/launch.json vendored
View File

@@ -8,6 +8,10 @@
"name": "debug",
"request": "launch",
"type": "dart",
"env": {
// Comment this line to use the default display
"DISPLAY": ":1"
}
// "args": [
// "-v"
// ]

View File

@@ -4,7 +4,6 @@ English | [简体中文](README_zh.md)
<p align="center">
<img alt="lang" src="https://img.shields.io/badge/lang-dart-pink">
<img alt="countly" src="https://img.shields.io/badge/analysis-countly-pink">
<img alt="license" src="https://img.shields.io/badge/license-GPLv3-pink">
</p>
@@ -14,33 +13,38 @@ A Flutter project which provide charts to display <a href="../../issues/43">Linu
Especially thanks to <a href="https://github.com/TerminalStudio/dartssh2">dartssh2</a> & <a href="https://github.com/TerminalStudio/xterm.dart">xterm.dart</a>.
</p>
## ⬇️ Download
🎉 **The `Android / Linux / Windows` version are now built via GitHub Actions**
[iOS & macOS](https://apps.apple.com/app/id1586449703) / [Android & Linux & Windows](https://github.com/lollipopkit/flutter_server_box/releases)
## 📥 Install
All deprecated versions before `v930` can be found in [here](https://cdn.lolli.tech/serverbox/?sort=time&order=desc&layout=grid).
Platform | From
--- | ---
iOS / macOS | [AppStore](https://apps.apple.com/app/id1586449703)
Android | [GitHub](https://github.com/lollipopkit/flutter_server_box/releases) / [CDN](https://cdn.lolli.tech/serverbox/?sort=time&order=desc&layout=grid) / [F-Droid](https://f-droid.org/packages/tech.lolli.toolbox) / [OpenAPK](https://www.openapk.net/serverbox/tech.lolli.toolbox/)
Linux / Windows | [GitHub](https://github.com/lollipopkit/flutter_server_box/releases) / [CDN](https://cdn.lolli.tech/serverbox/?sort=time&order=desc&layout=grid)
**Please only download pkgs from the source that you trust!**
- `AppStore` & `CDN` packages are built by myself
- Github releases are built by Github Actions
- Other sources are built by themselves
## 🔖 Feature
- `Status chart` (CPU, Sensors, GPU...), `SSH` Term, `SFTP`, `Docker & Pkg & Process`...
- `Status chart` (CPU, Sensors, GPU...), `SSH` Term, `SFTP`, `Docker & Process`...
- Platform specific: `Bio auth``Msg push``Home widget``watchOS App`...
- English, 简体中文; Deutsch [@its-tom](https://github.com/its-tom), 繁體中文 [@kalashnikov](https://github.com/kalashnikov), Indonesian [@azkadev](https://github.com/azkadev), Français [@FrancXPT](https://github.com/FrancXPT), Dutch [@QazCetelic](https://github.com/QazCetelic); Español, Русский язык, Português, 日本語 (Generated by GPT)
- English, 简体中文; Deutsch [@its-tom](https://github.com/its-tom), 繁體中文 [@kalashnikov](https://github.com/kalashnikov), Indonesian [@azkadev](https://github.com/azkadev), Français [@FrancXPT](https://github.com/FrancXPT), Dutch [@QazCetelic](https://github.com/QazCetelic), Türkçe [@mikropsoft](https://github.com/mikropsoft); Español, Русский язык, Português, 日本語 (Generated by GPT)
## 🏙️ ScreenShots
<table>
<tr>
<td><img width="277px" src="imgs/server.png"></td>
<td><img width="277px" src="imgs/detail.png"></td>
<td><img width="277px" src="imgs/sftp.png"></td>
<td><img width="277px" src="https://cdn.lolli.tech/serverbox/screenshot/1.png"></td>
<td><img width="277px" src="https://cdn.lolli.tech/serverbox/screenshot/2.png"></td>
<td><img width="277px" src="https://cdn.lolli.tech/serverbox/screenshot/3.png"></td>
</tr>
</table>
<table>
<tr>
<td><img width="277px" src="imgs/editor.png"> </td>
<td><img width="277px" src="imgs/ssh.png"></td>
<td><img width="277px" src="imgs/docker.png"></td>
<td><img width="277px" src="https://cdn.lolli.tech/serverbox/screenshot/4.png"> </td>
<td><img width="277px" src="https://cdn.lolli.tech/serverbox/screenshot/5.png"></td>
<td><img width="277px" src="https://cdn.lolli.tech/serverbox/screenshot/6.png"></td>
</tr>
</table>
@@ -58,8 +62,16 @@ After you read the above, you can open an [issue](https://github.com/lollipopkit
## 🧱 Contribution
- Any positive contribution is welcome.
- [l10n guide](https://blog.lolli.tech/faq/) can be found in my blog.
Any positive contribution is welcome.
### Development
1. Setup [Flutter](https://flutter.dev/docs/get-started/install) environment.
2. Clone this repo, run `flutter run` to start the app.
3. Run `dart run fl_build -p PLATFORM` to build the app.
### Translation
- [Guide](https://blog.lpkt.cn/posts/faq/) can be found in my blog.
- We need your help! Just feel free to open a PR.
## 💡 My other apps

View File

@@ -4,7 +4,6 @@
<p align="center">
<img alt="lang" src="https://img.shields.io/badge/lang-dart-pink">
<img alt="countly" src="https://img.shields.io/badge/analysis-countly-pink">
<img alt="license" src="https://img.shields.io/badge/license-GPLv3-pink">
</p>
@@ -14,37 +13,40 @@
特别感谢 <a href="https://github.com/TerminalStudio/dartssh2">dartssh2</a> & <a href="https://github.com/TerminalStudio/xterm.dart">xterm.dart</a>
</p>
## 📥 安装
## ⬇️ Download
🎉 **现在 `Android / Linux / Windows` 版本使用 GitHub Actions 构建**
平台 | 下载
--- | ---
iOS / macOS | [AppStore](https://apps.apple.com/app/id1586449703)
Android | [GitHub](https://github.com/lollipopkit/flutter_server_box/releases) / [CDN](https://cdn.lolli.tech/serverbox/?sort=time&order=desc&layout=grid) / [F-Droid](https://f-droid.org/packages/tech.lolli.toolbox) / [OpenAPK](https://www.openapk.net/serverbox/tech.lolli.toolbox/)
Linux / Windows | [GitHub](https://github.com/lollipopkit/flutter_server_box/releases) / [CDN](https://cdn.lolli.tech/serverbox/?sort=time&order=desc&layout=grid)
[iOS & macOS](https://apps.apple.com/app/id1586449703) / [Android & Linux & Windows](https://github.com/lollipopkit/flutter_server_box/releases)
所有 `v930` 之前的版本可以在 [这里](https://cdn.lolli.tech/serverbox/?sort=time&order=desc&layout=grid) 找到。
**请不要从不受信任的来源下载!**
- `AppStore` & `CDN` 的包由我构建
- Github 的包由 Github Actions 构建
- 其他来源由其所有者构建
## 🔖 特点
- `状态图表`CPU、传感器、GPU 等), `SSH` 终端, `SFTP`, `Docker & 包 & 进程` 管理...
- `状态图表`CPU、传感器、GPU 等), `SSH` 终端, `SFTP`, `Docker & 进程` 管理...
- 特殊支持:`生物认证``推送``桌面小部件``watchOS App``跟随系统颜色`...
- 本地化
- English, 简体中文
- Español, Русский язык, Português, 日本語 (Generated by GPT)
- Deutsch (@its-tom) / 繁體中文 (@kalashnikov) / Indonesian (@azkadev) / Français (@FrancXPT) / Dutch (@QazCetelic)
- Deutsch [@its-tom](https://github.com/its-tom), 繁體中文 [@kalashnikov](https://github.com/kalashnikov), Indonesian [@azkadev](https://github.com/azkadev), Français [@FrancXPT](https://github.com/FrancXPT), Dutch [@QazCetelic](https://github.com/QazCetelic), Türkçe [@mikropsoft](https://github.com/mikropsoft);
## 🏙️ 截屏
<table>
<tr>
<td><img width="277px" src="imgs/server.png"></td>
<td><img width="277px" src="imgs/detail.png"></td>
<td><img width="277px" src="imgs/sftp.png"></td>
<td><img width="277px" src="https://cdn.lolli.tech/serverbox/screenshot/1.png"></td>
<td><img width="277px" src="https://cdn.lolli.tech/serverbox/screenshot/2.png"></td>
<td><img width="277px" src="https://cdn.lolli.tech/serverbox/screenshot/3.png"></td>
</tr>
</table>
<table>
<tr>
<td><img width="277px" src="imgs/editor.png"> </td>
<td><img width="277px" src="imgs/ssh.png"></td>
<td><img width="277px" src="imgs/docker.png"></td>
<td><img width="277px" src="https://cdn.lolli.tech/serverbox/screenshot/4.png"> </td>
<td><img width="277px" src="https://cdn.lolli.tech/serverbox/screenshot/5.png"></td>
<td><img width="277px" src="https://cdn.lolli.tech/serverbox/screenshot/6.png"></td>
</tr>
</table>
@@ -64,9 +66,15 @@
## 🧱 贡献
- 任何正面的贡献都欢迎。
- [本地化翻译指南](https://blog.lolli.tech/faq/) 可在我的博客中找到。
任何正面的贡献都欢迎。
### 开发
1. 安装 [Flutter](https://flutter.dev/docs/get-started/install)
2. 克隆这个仓库, 运行 `flutter run` 启动应用
3. 运行 `dart run fl_build -p PLATFORM` 构建应用
### 翻译
[指南](https://blog.lolli.tech/faq/) 可在我的博客中找到。
## 💡 我的其它 Apps
- [GPT Box](https://github.com/lollipopkit/flutter_gpt_box) - 支持 OpenAI API 的 第三方全平台客户端。

View File

@@ -100,3 +100,14 @@ flutter {
}
dependencies {}
ext.abiCodes = ["x86_64": 1, "armeabi-v7a": 2, "arm64-v8a": 3]
import com.android.build.OutputFile
android.applicationVariants.all { variant ->
variant.outputs.each { output ->
def abiVersionCode = project.ext.abiCodes.get(output.getFilter(OutputFile.ABI))
if (abiVersionCode != null) {
output.versionCodeOverride = variant.versionCode * 10 + abiVersionCode
}
}
}

View File

@@ -1,7 +1 @@
-keep class io.flutter.app.** { *; }
-keep class io.flutter.plugin.** { *; }
-keep class io.flutter.util.** { *; }
-keep class io.flutter.view.** { *; }
-keep class io.flutter.** { *; }
-keep class io.flutter.plugins.** { *; }
-keep class com.jcraft.** { *; }

View File

@@ -27,9 +27,12 @@ class HomeWidget : AppWidgetProvider() {
private fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) {
val views = RemoteViews(context.packageName, R.layout.home_widget)
val sp = context.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE)
var url = sp.getString("$appWidgetId", null)
val gUrl = sp.getString("*", null)
var url = sp.getString("widget_$appWidgetId", null)
if (url.isNullOrEmpty()) {
url = sp.getString("$appWidgetId", null)
}
if (url.isNullOrEmpty()) {
val gUrl = sp.getString("widget_*", null)
url = gUrl
}

View File

@@ -3,3 +3,4 @@ distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.3-all.zip
distributionSha256Sum=6001aba9b2204d26fa25a5800bb9382cf3ee01ccb78fe77317b2872336eb2f80

View File

@@ -0,0 +1,6 @@
A Flutter project which provide charts to display Linux server status and tools to manage server.
Especially thanks to dartssh2 & xterm.dart.
* Status chart (CPU, Sensors, GPU...), SSH Term, SFTP, Docker & Pkg & Process...
* Platform specific: Bio auth、Msg push、Home widget、watchOS App...
* English, 简体中文; Deutsch, 繁體中文, Indonesian, Français, Dutch; Español, Русский язык, Português, 日本語

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 135 KiB

View File

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 115 KiB

View File

Before

Width:  |  Height:  |  Size: 173 KiB

After

Width:  |  Height:  |  Size: 173 KiB

View File

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 135 KiB

View File

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 135 KiB

View File

Before

Width:  |  Height:  |  Size: 144 KiB

After

Width:  |  Height:  |  Size: 144 KiB

View File

@@ -0,0 +1 @@
A server status & toolbox app using Flutter

View File

@@ -0,0 +1 @@
ServerBox

View File

@@ -0,0 +1,7 @@
使用 Flutter 开发的 Linux 服务器工具箱,提供服务器状态图表和管理工具。
特别感谢 dartssh2 & xterm.dart。
特点:
* 状态图表CPU、传感器、GPU 等), SSH 终端, SFTP, Docker & 包 & 进程管理器...
* 特殊支持生物认证、推送、桌面小部件、watchOS App、跟随系统颜色...
* 本地化 (English, 简体中文, Español, Русский язык, Português, 日本語, Deutsch, 繁體中文, Indonesian, Français, Dutch

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 173 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 144 KiB

View File

@@ -0,0 +1 @@
使用 Flutter 开发的服务器状态和工具箱应用

View File

@@ -0,0 +1 @@
ServerBox

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 112 KiB

View File

@@ -1,6 +1,4 @@
PODS:
- countly_flutter (24.4.1):
- Flutter
- device_info_plus (0.0.1):
- Flutter
- file_picker (0.0.1):
@@ -36,7 +34,6 @@ PODS:
- Flutter
DEPENDENCIES:
- countly_flutter (from `.symlinks/plugins/countly_flutter/ios`)
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
- file_picker (from `.symlinks/plugins/file_picker/ios`)
- Flutter (from `Flutter`)
@@ -55,8 +52,6 @@ DEPENDENCIES:
- watch_connectivity (from `.symlinks/plugins/watch_connectivity/ios`)
EXTERNAL SOURCES:
countly_flutter:
:path: ".symlinks/plugins/countly_flutter/ios"
device_info_plus:
:path: ".symlinks/plugins/device_info_plus/ios"
file_picker:
@@ -91,7 +86,6 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/watch_connectivity/ios"
SPEC CHECKSUMS:
countly_flutter: 56233d921c6b4e0a720774a39b8ee8110d6f8d91
device_info_plus: 97af1d7e84681a90d0693e63169a5d50e0839a0d
file_picker: c79185e70b9b45728cde2a8d8da454e0cb43f287
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7

View File

@@ -690,7 +690,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 948;
CURRENT_PROJECT_VERSION = 1051;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -700,7 +700,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.948;
MARKETING_VERSION = 1.0.1051;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -826,7 +826,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 948;
CURRENT_PROJECT_VERSION = 1051;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -836,7 +836,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.948;
MARKETING_VERSION = 1.0.1051;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -854,7 +854,7 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
CURRENT_PROJECT_VERSION = 948;
CURRENT_PROJECT_VERSION = 1051;
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
@@ -864,7 +864,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.948;
MARKETING_VERSION = 1.0.1051;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
@@ -885,7 +885,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 948;
CURRENT_PROJECT_VERSION = 1051;
DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
@@ -898,7 +898,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.948;
MARKETING_VERSION = 1.0.1051;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
@@ -924,7 +924,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 948;
CURRENT_PROJECT_VERSION = 1051;
DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
@@ -937,7 +937,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.948;
MARKETING_VERSION = 1.0.1051;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -960,7 +960,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 948;
CURRENT_PROJECT_VERSION = 1051;
DEVELOPMENT_TEAM = BA88US33G6;
GCC_C_LANGUAGE_STANDARD = gnu11;
GENERATE_INFOPLIST_FILE = YES;
@@ -973,7 +973,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.0.948;
MARKETING_VERSION = 1.0.1051;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -996,7 +996,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 948;
CURRENT_PROJECT_VERSION = 1051;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_PREVIEWS = YES;
@@ -1008,7 +1008,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.948;
MARKETING_VERSION = 1.0.1051;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
@@ -1037,7 +1037,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 948;
CURRENT_PROJECT_VERSION = 1051;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_PREVIEWS = YES;
@@ -1049,7 +1049,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.948;
MARKETING_VERSION = 1.0.1051;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
PRODUCT_NAME = ServerBox;
@@ -1075,7 +1075,7 @@
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 948;
CURRENT_PROJECT_VERSION = 1051;
DEVELOPMENT_ASSET_PATHS = "";
DEVELOPMENT_TEAM = BA88US33G6;
ENABLE_PREVIEWS = YES;
@@ -1087,7 +1087,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0.948;
MARKETING_VERSION = 1.0.1051;
MTL_FAST_MATH = YES;
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.WatchEnd;
PRODUCT_NAME = ServerBox;

View File

@@ -3,10 +3,14 @@ import 'package:fl_lib/fl_lib.dart';
import 'package:fl_lib/l10n/gen_l10n/lib_l10n.dart';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:toolbox/data/res/build_data.dart';
import 'package:toolbox/data/res/rebuild.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:toolbox/view/page/home/home.dart';
import 'package:server_box/core/extension/context/locale.dart';
import 'package:server_box/data/res/build_data.dart';
import 'package:server_box/data/res/rebuild.dart';
import 'package:server_box/data/res/store.dart';
import 'package:server_box/view/page/home/home.dart';
import 'package:icons_plus/icons_plus.dart';
part 'intro.dart';
class MyApp extends StatelessWidget {
const MyApp({super.key});
@@ -18,8 +22,22 @@ class MyApp extends StatelessWidget {
listenable: RNodes.app,
builder: (context, _) {
if (!Stores.setting.useSystemPrimaryColor.fetch()) {
UIs.colorSeed = Color(Stores.setting.primaryColor.fetch());
return _buildApp(context);
final colorSeed = Color(Stores.setting.colorSeed.fetch());
UIs.colorSeed = colorSeed;
// Past code uses [UIs.primaryColor] as the primary color
UIs.primaryColor = colorSeed;
return _buildApp(
context,
light: ThemeData(
useMaterial3: true,
colorSchemeSeed: UIs.colorSeed,
),
dark: ThemeData(
useMaterial3: true,
brightness: Brightness.dark,
colorSchemeSeed: UIs.colorSeed,
),
);
}
return DynamicColorBuilder(
builder: (light, dark) {
@@ -32,10 +50,10 @@ class MyApp extends StatelessWidget {
brightness: Brightness.dark,
colorScheme: dark,
);
if (context.isDark && light != null) {
UIs.primaryColor = light.primary;
} else if (!context.isDark && dark != null) {
if (context.isDark && dark != null) {
UIs.primaryColor = dark.primary;
} else if (!context.isDark && light != null) {
UIs.primaryColor = light.primary;
}
return _buildApp(context, light: lightTheme, dark: darkTheme);
},
@@ -44,7 +62,8 @@ class MyApp extends StatelessWidget {
);
}
Widget _buildApp(BuildContext ctx, {ThemeData? light, ThemeData? dark}) {
Widget _buildApp(BuildContext ctx,
{required ThemeData light, required ThemeData dark}) {
final tMode = Stores.setting.themeMode.fetch();
// Issue #57
final themeMode = switch (tMode) {
@@ -54,16 +73,6 @@ class MyApp extends StatelessWidget {
};
final locale = Stores.setting.locale.fetch().toLocale;
light ??= ThemeData(
useMaterial3: true,
colorSchemeSeed: UIs.colorSeed,
);
dark ??= ThemeData(
useMaterial3: true,
brightness: Brightness.dark,
colorSchemeSeed: UIs.colorSeed,
);
return MaterialApp(
locale: locale,
localizationsDelegates: const [
@@ -71,17 +80,27 @@ class MyApp extends StatelessWidget {
...AppLocalizations.localizationsDelegates,
],
supportedLocales: AppLocalizations.supportedLocales,
localeListResolutionCallback: LocaleUtil.resolve,
navigatorObservers: [AppRouteObserver.instance],
title: BuildData.name,
themeMode: themeMode,
theme: light,
darkTheme: tMode < 3 ? dark : dark.toAmoled,
home: _buildAppContent(ctx),
);
}
theme: light.fixWindowsFont,
darkTheme: (tMode < 3 ? dark : dark.toAmoled).fixWindowsFont,
home: Builder(
builder: (context) {
context.setLibL10n();
final appL10n = AppLocalizations.of(context);
if (appL10n != null) l10n = appL10n;
Widget _buildAppContent(BuildContext ctx) {
//if (Pros.app.isWearOS) return const WearHome();
return const HomePage();
final intros = _IntroPage.builders;
if (intros.isNotEmpty) {
return _IntroPage(intros);
}
return const HomePage();
},
),
);
}
}

View File

@@ -1,5 +1,5 @@
import 'package:flutter/services.dart';
import 'package:toolbox/data/res/misc.dart';
import 'package:server_box/data/res/misc.dart';
abstract final class BgRunMC {
static const _channel = MethodChannel('${Miscs.pkgName}/app_retain');

View File

@@ -1,6 +1,6 @@
import 'package:flutter/services.dart';
import 'package:toolbox/data/res/misc.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:server_box/data/res/misc.dart';
import 'package:server_box/data/res/store.dart';
abstract final class HomeWidgetMC {
static const _channel = MethodChannel('${Miscs.pkgName}/home_widget');

View File

@@ -1,4 +1,4 @@
import 'package:toolbox/data/res/build_data.dart';
import 'package:server_box/data/res/build_data.dart';
extension BuildDataX on BuildData {
static const versionStr = 'v1.0.${BuildData.build}';

View File

@@ -1,4 +1,5 @@
import 'package:dartssh2/dartssh2.dart';
import 'package:server_box/view/widget/unix_perm.dart';
extension SftpFileX on SftpFileMode {
String get str {
@@ -8,6 +9,26 @@ extension SftpFileX on SftpFileMode {
return '$user$group$other';
}
UnixPerm toUnixPerm() {
return UnixPerm(
user: RWX(
r: userRead,
w: userWrite,
x: userExecute,
),
group: RWX(
r: groupRead,
w: groupWrite,
x: groupExecute,
),
other: RWX(
r: otherRead,
w: otherWrite,
x: otherExecute,
),
);
}
}
String _getRoleMode(bool r, bool w, bool x) {

View File

@@ -1,27 +1,26 @@
import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:toolbox/data/model/server/private_key_info.dart';
import 'package:toolbox/data/model/server/server_private_info.dart';
import 'package:toolbox/data/res/build_data.dart';
import 'package:toolbox/data/res/provider.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:toolbox/view/page/backup.dart';
import 'package:toolbox/view/page/container.dart';
import 'package:toolbox/view/page/home/home.dart';
import 'package:toolbox/view/page/iperf.dart';
import 'package:toolbox/view/page/ping.dart';
import 'package:toolbox/view/page/private_key/edit.dart';
import 'package:toolbox/view/page/private_key/list.dart';
import 'package:toolbox/view/page/pve.dart';
import 'package:toolbox/view/page/server/detail/view.dart';
import 'package:toolbox/view/page/setting/platform/android.dart';
import 'package:toolbox/view/page/setting/platform/ios.dart';
import 'package:toolbox/view/page/setting/seq/srv_func_seq.dart';
import 'package:toolbox/view/page/snippet/result.dart';
import 'package:toolbox/view/page/ssh/page.dart';
import 'package:toolbox/view/page/setting/seq/virt_key.dart';
import 'package:toolbox/view/page/storage/local.dart';
import 'package:server_box/data/model/server/private_key_info.dart';
import 'package:server_box/data/model/server/server_private_info.dart';
import 'package:server_box/data/res/build_data.dart';
import 'package:server_box/data/res/store.dart';
import 'package:server_box/view/page/backup.dart';
import 'package:server_box/view/page/container.dart';
import 'package:server_box/view/page/home/home.dart';
import 'package:server_box/view/page/iperf.dart';
import 'package:server_box/view/page/ping.dart';
import 'package:server_box/view/page/private_key/edit.dart';
import 'package:server_box/view/page/private_key/list.dart';
import 'package:server_box/view/page/pve.dart';
import 'package:server_box/view/page/server/detail/view.dart';
import 'package:server_box/view/page/setting/platform/android.dart';
import 'package:server_box/view/page/setting/platform/ios.dart';
import 'package:server_box/view/page/setting/seq/srv_func_seq.dart';
import 'package:server_box/view/page/snippet/result.dart';
import 'package:server_box/view/page/ssh/page.dart';
import 'package:server_box/view/page/setting/seq/virt_key.dart';
import 'package:server_box/view/page/storage/local.dart';
import '../data/model/server/snippet.dart';
import '../view/page/editor.dart';
@@ -102,12 +101,14 @@ class AppRoutes {
Key? key,
required ServerPrivateInfo spi,
String? initCmd,
Snippet? initSnippet,
}) {
return AppRoutes(
SSHPage(
key: key,
spi: spi,
initCmd: initCmd,
initSnippet: initSnippet,
),
'ssh_term',
);
@@ -155,11 +156,7 @@ class AppRoutes {
return AppRoutes(
DebugPage(
key: key,
args: DebugPageArgs(
notifier: Pros.debug.widgets,
onClear: Pros.debug.clear,
title: 'Logs(${BuildData.build})',
),
args: const DebugPageArgs(title: 'Logs(${BuildData.build})'),
),
'debug',
);
@@ -246,8 +243,4 @@ class AppRoutes {
static AppRoutes pve({Key? key, required ServerPrivateInfo spi}) {
return AppRoutes(PvePage(key: key, spi: spi), 'pve');
}
static AppRoutes kvEditor({Key? key, required Map<String, String> data}) {
return AppRoutes(KvEditor(key: key, data: data), 'kv_editor');
}
}

View File

@@ -2,14 +2,9 @@ import 'package:fl_lib/fl_lib.dart';
import 'package:plain_notification_token/plain_notification_token.dart';
Future<String?> getToken() async {
if (isIOS) {
final plainNotificationToken = PlainNotificationToken();
plainNotificationToken.requestPermission();
// If you want to wait until Permission dialog close,
// you need wait changing setting registered.
await plainNotificationToken.onIosSettingsRegistered.first;
return await plainNotificationToken.getToken();
}
return null;
if (!isIOS) return null;
final instance = ApnsToken()..requestPermission();
// Wait until Permission dialog closed
await instance.onIosSettingsRegistered.first;
return await instance.getToken();
}

View File

@@ -2,8 +2,8 @@ import 'dart:async';
import 'package:dartssh2/dartssh2.dart';
import 'package:flutter/foundation.dart';
import 'package:toolbox/data/model/app/error.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:server_box/data/model/app/error.dart';
import 'package:server_box/data/res/store.dart';
import '../../data/model/server/server_private_info.dart';

View File

@@ -2,9 +2,9 @@ import 'dart:async';
import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart';
import 'package:toolbox/core/extension/context/locale.dart';
import 'package:toolbox/data/model/server/server_private_info.dart';
import 'package:toolbox/data/res/provider.dart';
import 'package:server_box/core/extension/context/locale.dart';
import 'package:server_box/data/model/server/server_private_info.dart';
import 'package:server_box/data/res/provider.dart';
abstract final class KeybordInteractive {
static FutureOr<List<String>?> defaultHandle(

View File

@@ -5,9 +5,9 @@ import 'package:computer/computer.dart';
import 'package:fl_lib/fl_lib.dart';
import 'package:icloud_storage/icloud_storage.dart';
import 'package:logging/logging.dart';
import 'package:toolbox/data/model/app/backup.dart';
import 'package:toolbox/data/model/app/sync.dart';
import 'package:toolbox/data/res/misc.dart';
import 'package:server_box/data/model/app/backup.dart';
import 'package:server_box/data/model/app/sync.dart';
import 'package:server_box/data/res/misc.dart';
import '../../../data/model/app/error.dart';

View File

@@ -3,10 +3,10 @@ import 'dart:io';
import 'package:computer/computer.dart';
import 'package:fl_lib/fl_lib.dart';
import 'package:logging/logging.dart';
import 'package:toolbox/data/model/app/backup.dart';
import 'package:toolbox/data/model/app/error.dart';
import 'package:toolbox/data/res/misc.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:server_box/data/model/app/backup.dart';
import 'package:server_box/data/model/app/error.dart';
import 'package:server_box/data/res/misc.dart';
import 'package:server_box/data/res/store.dart';
import 'package:webdav_client/webdav_client.dart';
abstract final class Webdav {

View File

@@ -3,13 +3,13 @@ import 'dart:io';
import 'package:fl_lib/fl_lib.dart';
import 'package:logging/logging.dart';
import 'package:toolbox/data/model/server/private_key_info.dart';
import 'package:toolbox/data/model/server/server_private_info.dart';
import 'package:toolbox/data/model/server/snippet.dart';
import 'package:toolbox/data/res/misc.dart';
import 'package:toolbox/data/res/provider.dart';
import 'package:toolbox/data/res/rebuild.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:server_box/data/model/server/private_key_info.dart';
import 'package:server_box/data/model/server/server_private_info.dart';
import 'package:server_box/data/model/server/snippet.dart';
import 'package:server_box/data/res/misc.dart';
import 'package:server_box/data/res/provider.dart';
import 'package:server_box/data/res/rebuild.dart';
import 'package:server_box/data/res/store.dart';
const backupFormatVersion = 1;
@@ -90,87 +90,113 @@ class Backup {
}
// Snippets
final nowSnippets = Stores.snippet.box.keys.toSet();
final bakSnippets = snippets.map((e) => e.name).toSet();
final newSnippets = bakSnippets.difference(nowSnippets);
final delSnippets = nowSnippets.difference(bakSnippets);
final updateSnippets = nowSnippets.intersection(bakSnippets);
for (final s in newSnippets) {
Stores.snippet.box.put(s, snippets.firstWhere((e) => e.name == s));
}
for (final s in delSnippets) {
Stores.snippet.box.delete(s);
}
for (final s in updateSnippets) {
Stores.snippet.box.put(s, snippets.firstWhere((e) => e.name == s));
if (force) {
for (final s in snippets) {
Stores.snippet.box.put(s.name, s);
}
} else {
final nowSnippets = Stores.snippet.box.keys.toSet();
final bakSnippets = snippets.map((e) => e.name).toSet();
final newSnippets = bakSnippets.difference(nowSnippets);
final delSnippets = nowSnippets.difference(bakSnippets);
final updateSnippets = nowSnippets.intersection(bakSnippets);
for (final s in newSnippets) {
Stores.snippet.box.put(s, snippets.firstWhere((e) => e.name == s));
}
for (final s in delSnippets) {
Stores.snippet.box.delete(s);
}
for (final s in updateSnippets) {
Stores.snippet.box.put(s, snippets.firstWhere((e) => e.name == s));
}
}
// ServerPrivateInfo
final nowSpis = Stores.server.box.keys.toSet();
final bakSpis = spis.map((e) => e.id).toSet();
final newSpis = bakSpis.difference(nowSpis);
final delSpis = nowSpis.difference(bakSpis);
final updateSpis = nowSpis.intersection(bakSpis);
for (final s in newSpis) {
Stores.server.box.put(s, spis.firstWhere((e) => e.id == s));
}
for (final s in delSpis) {
Stores.server.box.delete(s);
}
for (final s in updateSpis) {
Stores.server.box.put(s, spis.firstWhere((e) => e.id == s));
if (force) {
for (final s in spis) {
Stores.server.box.put(s.id, s);
}
} else {
final nowSpis = Stores.server.box.keys.toSet();
final bakSpis = spis.map((e) => e.id).toSet();
final newSpis = bakSpis.difference(nowSpis);
final delSpis = nowSpis.difference(bakSpis);
final updateSpis = nowSpis.intersection(bakSpis);
for (final s in newSpis) {
Stores.server.box.put(s, spis.firstWhere((e) => e.id == s));
}
for (final s in delSpis) {
Stores.server.box.delete(s);
}
for (final s in updateSpis) {
Stores.server.box.put(s, spis.firstWhere((e) => e.id == s));
}
}
// PrivateKeyInfo
final nowKeys = Stores.key.box.keys.toSet();
final bakKeys = keys.map((e) => e.id).toSet();
final newKeys = bakKeys.difference(nowKeys);
final delKeys = nowKeys.difference(bakKeys);
final updateKeys = nowKeys.intersection(bakKeys);
for (final s in newKeys) {
Stores.key.box.put(s, keys.firstWhere((e) => e.id == s));
}
for (final s in delKeys) {
Stores.key.box.delete(s);
}
for (final s in updateKeys) {
Stores.key.box.put(s, keys.firstWhere((e) => e.id == s));
if (force) {
for (final s in keys) {
Stores.key.box.put(s.id, s);
}
} else {
final nowKeys = Stores.key.box.keys.toSet();
final bakKeys = keys.map((e) => e.id).toSet();
final newKeys = bakKeys.difference(nowKeys);
final delKeys = nowKeys.difference(bakKeys);
final updateKeys = nowKeys.intersection(bakKeys);
for (final s in newKeys) {
Stores.key.box.put(s, keys.firstWhere((e) => e.id == s));
}
for (final s in delKeys) {
Stores.key.box.delete(s);
}
for (final s in updateKeys) {
Stores.key.box.put(s, keys.firstWhere((e) => e.id == s));
}
}
// History
final nowHistory = Stores.history.box.keys.toSet();
final bakHistory = history.keys.toSet();
final newHistory = bakHistory.difference(nowHistory);
final delHistory = nowHistory.difference(bakHistory);
final updateHistory = nowHistory.intersection(bakHistory);
for (final s in newHistory) {
Stores.history.box.put(s, history[s]);
}
for (final s in delHistory) {
Stores.history.box.delete(s);
}
for (final s in updateHistory) {
Stores.history.box.put(s, history[s]);
if (force) {
Stores.history.box.putAll(history);
} else {
final nowHistory = Stores.history.box.keys.toSet();
final bakHistory = history.keys.toSet();
final newHistory = bakHistory.difference(nowHistory);
final delHistory = nowHistory.difference(bakHistory);
final updateHistory = nowHistory.intersection(bakHistory);
for (final s in newHistory) {
Stores.history.box.put(s, history[s]);
}
for (final s in delHistory) {
Stores.history.box.delete(s);
}
for (final s in updateHistory) {
Stores.history.box.put(s, history[s]);
}
}
// Container
final nowContainer = Stores.container.box.keys.toSet();
final bakContainer = container.keys.toSet();
final newContainer = bakContainer.difference(nowContainer);
final delContainer = nowContainer.difference(bakContainer);
final updateContainer = nowContainer.intersection(bakContainer);
for (final s in newContainer) {
Stores.container.box.put(s, container[s]);
}
for (final s in delContainer) {
Stores.container.box.delete(s);
}
for (final s in updateContainer) {
Stores.container.box.put(s, container[s]);
if (force) {
Stores.container.box.putAll(container);
} else {
final nowContainer = Stores.container.box.keys.toSet();
final bakContainer = container.keys.toSet();
final newContainer = bakContainer.difference(nowContainer);
final delContainer = nowContainer.difference(bakContainer);
final updateContainer = nowContainer.intersection(bakContainer);
for (final s in newContainer) {
Stores.container.box.put(s, container[s]);
}
for (final s in delContainer) {
Stores.container.box.delete(s);
}
for (final s in updateContainer) {
Stores.container.box.put(s, container[s]);
}
}
Pros.reload();
RNodes.app.build();
RNodes.app.notify();
_logger.info('Restore success');
}

View File

@@ -1,4 +1,4 @@
import 'package:toolbox/core/extension/context/locale.dart';
import 'package:server_box/core/extension/context/locale.dart';
enum ErrFrom {
unknown,

View File

@@ -1,5 +1,6 @@
import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart';
import 'package:toolbox/core/extension/context/locale.dart';
import 'package:server_box/core/extension/context/locale.dart';
enum ContainerMenu {
start,
@@ -21,46 +22,27 @@ enum ContainerMenu {
terminal,
//stats,
];
} else {
return [start, rm, logs];
}
return [start, rm, logs];
}
IconData get icon {
switch (this) {
case ContainerMenu.start:
return Icons.play_arrow;
case ContainerMenu.stop:
return Icons.stop;
case ContainerMenu.restart:
return Icons.restart_alt;
case ContainerMenu.rm:
return Icons.delete;
case ContainerMenu.logs:
return Icons.logo_dev;
case ContainerMenu.terminal:
return Icons.terminal;
// case DockerMenuType.stats:
// return Icons.bar_chart;
}
}
IconData get icon => switch (this) {
ContainerMenu.start => Icons.play_arrow,
ContainerMenu.stop => Icons.stop,
ContainerMenu.restart => Icons.restart_alt,
ContainerMenu.rm => Icons.delete,
ContainerMenu.logs => Icons.logo_dev,
ContainerMenu.terminal => Icons.terminal,
// DockerMenuType.stats => Icons.bar_chart,
};
String get toStr {
switch (this) {
case ContainerMenu.start:
return l10n.start;
case ContainerMenu.stop:
return l10n.stop;
case ContainerMenu.restart:
return l10n.restart;
case ContainerMenu.rm:
return l10n.delete;
case ContainerMenu.logs:
return l10n.log;
case ContainerMenu.terminal:
return l10n.terminal;
// case DockerMenuType.stats:
// return s.stats;
}
}
String get toStr => switch (this) {
ContainerMenu.start => l10n.start,
ContainerMenu.stop => l10n.stop,
ContainerMenu.restart => l10n.restart,
ContainerMenu.rm => libL10n.delete,
ContainerMenu.logs => libL10n.log,
ContainerMenu.terminal => l10n.terminal,
// DockerMenuType.stats => s.stats,
};
}

View File

@@ -1,7 +1,7 @@
import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:icons_plus/icons_plus.dart';
import 'package:toolbox/core/extension/context/locale.dart';
import 'package:server_box/core/extension/context/locale.dart';
part 'server_func.g.dart';
@@ -15,8 +15,8 @@ enum ServerFuncBtn {
container,
@HiveField(3)
process,
@HiveField(4)
pkg,
//@HiveField(4)
//pkg,
@HiveField(5)
snippet,
@HiveField(6)
@@ -30,14 +30,14 @@ enum ServerFuncBtn {
sftp,
container,
process,
pkg,
//pkg,
snippet,
].map((e) => e.index).toList();
IconData get icon => switch (this) {
sftp => Icons.insert_drive_file,
snippet => Icons.code,
pkg => Icons.system_security_update,
//pkg => Icons.system_security_update,
container => FontAwesome.docker_brand,
process => Icons.list_alt_outlined,
terminal => Icons.terminal,
@@ -47,7 +47,7 @@ enum ServerFuncBtn {
String get toStr => switch (this) {
sftp => 'SFTP',
snippet => l10n.snippet,
pkg => l10n.pkg,
//pkg => l10n.pkg,
container => l10n.container,
process => l10n.process,
terminal => l10n.terminal,

View File

@@ -21,8 +21,6 @@ class ServerFuncBtnAdapter extends TypeAdapter<ServerFuncBtn> {
return ServerFuncBtn.container;
case 3:
return ServerFuncBtn.process;
case 4:
return ServerFuncBtn.pkg;
case 5:
return ServerFuncBtn.snippet;
case 6:
@@ -47,9 +45,6 @@ class ServerFuncBtnAdapter extends TypeAdapter<ServerFuncBtn> {
case ServerFuncBtn.process:
writer.writeByte(3);
break;
case ServerFuncBtn.pkg:
writer.writeByte(4);
break;
case ServerFuncBtn.snippet:
writer.writeByte(5);
break;

View File

@@ -1,7 +1,8 @@
import 'package:fl_lib/fl_lib.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:toolbox/core/extension/context/locale.dart';
import 'package:toolbox/data/model/server/server.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:server_box/core/extension/context/locale.dart';
import 'package:server_box/data/model/server/server.dart';
import 'package:server_box/data/res/store.dart';
part 'net_view.g.dart';
@@ -14,27 +15,17 @@ enum NetViewType {
@HiveField(2)
traffic;
NetViewType get next {
switch (this) {
case conn:
return speed;
case speed:
return traffic;
case traffic:
return conn;
}
}
NetViewType get next => switch (this) {
conn => speed,
speed => traffic,
traffic => conn,
};
String get toStr {
switch (this) {
case NetViewType.conn:
return l10n.conn;
case NetViewType.traffic:
return l10n.traffic;
case NetViewType.speed:
return l10n.speed;
}
}
String get toStr => switch (this) {
NetViewType.conn => l10n.conn,
NetViewType.traffic => l10n.traffic,
NetViewType.speed => l10n.speed,
};
(String, String) build(ServerStatus ss) {
final ignoreLocal = Stores.setting.ignoreLocalNet.fetch();
@@ -42,7 +33,7 @@ enum NetViewType {
case NetViewType.conn:
return (
'${l10n.conn}:\n${ss.tcp.maxConn}',
'${l10n.failed}:\n${ss.tcp.fail}',
'${libL10n.fail}:\n${ss.tcp.fail}',
);
case NetViewType.speed:
if (ignoreLocal) {
@@ -69,25 +60,15 @@ enum NetViewType {
}
}
int toJson() {
switch (this) {
case NetViewType.conn:
return 0;
case NetViewType.speed:
return 1;
case NetViewType.traffic:
return 2;
}
}
int toJson() => switch (this) {
NetViewType.conn => 0,
NetViewType.speed => 1,
NetViewType.traffic => 2,
};
static NetViewType fromJson(int json) {
switch (json) {
case 0:
return NetViewType.conn;
case 2:
return NetViewType.traffic;
default:
return NetViewType.speed;
}
}
static NetViewType fromJson(int json) => switch (json) {
0 => NetViewType.conn,
1 => NetViewType.speed,
_ => NetViewType.traffic,
};
}

View File

@@ -1,8 +1,8 @@
import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart';
import 'package:icons_plus/icons_plus.dart';
import 'package:toolbox/core/extension/context/locale.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:server_box/core/extension/context/locale.dart';
import 'package:server_box/data/res/store.dart';
enum ServerDetailCards {
about(Icons.info),
@@ -31,7 +31,7 @@ enum ServerDetailCards {
static final names = values.map((e) => e.name).toList();
String get toStr => switch (this) {
about => l10n.about,
about => libL10n.about,
cpu => 'CPU',
mem => 'RAM',
swap => 'Swap',

View File

@@ -1,4 +1,4 @@
import 'package:toolbox/core/extension/context/locale.dart';
import 'package:server_box/core/extension/context/locale.dart';
import '../../res/build_data.dart';
import '../server/system.dart';
@@ -12,52 +12,58 @@ enum ShellFunc {
suspend,
;
static const _homeVar = '\$HOME';
static const seperator = 'SrvBoxSep';
/// The suffix `\t` is for formatting
static const cmdDivider = '\necho $seperator\n\t';
static const _srvBoxDir = '.config/server_box';
static const scriptFile = 'mobile_v${BuildData.script}.sh';
/// Issue #159
/// srvboxm -> ServerBox Mobile
static const scriptFile = 'srvboxm_v${BuildData.script}.sh';
static const scriptDirHome = '~/.config/server_box';
static const scriptDirTmp = '/tmp/server_box';
static final _scriptDirMap = <String, String>{};
/// Get the script directory for the given [id].
///
/// Use script commit count as version of shell script.
///
/// So different version of app can run at the same time.
///
/// **Can't** use it in SFTP, because SFTP can't recognize `$HOME`
static String getShellPath(String home) => '$home/$_srvBoxDir/$scriptFile';
static const srvBoxDir = '$_homeVar/$_srvBoxDir';
static const _installShellPath = '$_homeVar/$_srvBoxDir/$scriptFile';
// Issue #299, chmod ~/.config to avoid permission issue
static const installShellCmd = """
chmod +x ~/.config &> /dev/null
mkdir -p $_homeVar/$_srvBoxDir
cat > $_installShellPath
chmod +x $_installShellPath
""";
String get flag {
switch (this) {
case ShellFunc.status:
return 's';
// case ShellFunc.docker:
// return 'd';
case ShellFunc.process:
return 'p';
case ShellFunc.shutdown:
return 'sd';
case ShellFunc.reboot:
return 'r';
case ShellFunc.suspend:
return 'sp';
}
/// Default is [scriptDirTmp]/[scriptFile], if this path is not accessible,
/// it will be changed to [scriptDirHome]/[scriptFile].
static String getScriptDir(String id) {
return _scriptDirMap.putIfAbsent(id, () {
return scriptDirTmp;
});
}
String get exec => 'sh $_installShellPath -$flag';
static void switchScriptDir(String id) => switch (_scriptDirMap[id]) {
scriptDirTmp => _scriptDirMap[id] = scriptDirHome,
scriptDirHome => _scriptDirMap[id] = scriptDirTmp,
_ => _scriptDirMap[id] = scriptDirHome,
};
static String getScriptPath(String id) {
return '${getScriptDir(id)}/$scriptFile';
}
static String getInstallShellCmd(String id) {
final scriptDir = getScriptDir(id);
final scriptPath = '$scriptDir/$scriptFile';
return """
mkdir -p $scriptDir
cat > $scriptPath
chmod 744 $scriptPath
""";
}
String get flag => switch (this) {
ShellFunc.process => 'p',
ShellFunc.shutdown => 'sd',
ShellFunc.reboot => 'r',
ShellFunc.suspend => 'sp',
ShellFunc.status => 's',
// ShellFunc.docker=> 'd',
};
String exec(String id) => 'sh ${getScriptPath(id)} -$flag';
String get name {
switch (this) {
@@ -213,6 +219,7 @@ enum StatusCmdType {
'for f in /sys/class/power_supply/*/uevent; do cat "\$f"; echo; done'),
nvidia._('nvidia-smi -q -x'),
sensors._('sensors'),
cpuBrand._('cat /proc/cpuinfo | grep "model name"'),
;
final String cmd;
@@ -231,6 +238,7 @@ enum BSDStatusCmdType {
mem._('top -l 1 | grep PhysMem'),
//temp,
host._('hostname'),
cpuBrand._('sysctl -n machdep.cpu.brand_string'),
;
final String cmd;

View File

@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:toolbox/view/page/ping.dart';
import 'package:toolbox/view/page/server/tab.dart';
import 'package:toolbox/view/page/snippet/list.dart';
import 'package:toolbox/view/page/ssh/tab.dart';
import 'package:server_box/view/page/ping.dart';
import 'package:server_box/view/page/server/tab.dart';
import 'package:server_box/view/page/snippet/list.dart';
import 'package:server_box/view/page/ssh/tab.dart';
enum AppTab {
server,

View File

@@ -1,7 +1,7 @@
import 'dart:convert';
import 'package:fl_lib/fl_lib.dart';
import 'package:toolbox/data/model/container/type.dart';
import 'package:server_box/data/model/container/type.dart';
abstract final class ContainerImg {
final String? repository = null;
@@ -72,7 +72,7 @@ final class DockerImg implements ContainerImg {
final String repository;
final String size;
@override
final String tag;
final String? tag;
DockerImg({
required this.containers,
@@ -95,14 +95,30 @@ final class DockerImg implements ContainerImg {
String toRawJson() => json.encode(toJson());
factory DockerImg.fromJson(Map<String, dynamic> json) => DockerImg(
containers: json["Containers"],
createdAt: json["CreatedAt"],
id: json["ID"],
repository: json["Repository"],
size: json["Size"],
tag: json["Tag"],
);
factory DockerImg.fromJson(Map<String, dynamic> json) {
final containers = switch (json["Containers"]) {
final String a => a,
final Object? a => a.toString(),
};
final repo = switch (json["Repository"] ?? json["Names"]) {
final String a => a,
final List a => a.firstOrNull.toString(),
final Object? a => a.toString(),
};
final size = switch (json["Size"]) {
final String a => a,
final int a => a.bytes2Str,
final Object? a => a.toString(),
};
return DockerImg(
containers: containers,
createdAt: json["CreatedAt"],
id: json["ID"] ?? json["Id"] ?? '',
repository: repo,
size: size,
tag: json["Tag"],
);
}
Map<String, dynamic> toJson() => {
"Containers": containers,

View File

@@ -1,9 +1,9 @@
import 'dart:convert';
import 'package:fl_lib/fl_lib.dart';
import 'package:toolbox/core/extension/context/locale.dart';
import 'package:toolbox/data/model/container/type.dart';
import 'package:toolbox/data/res/misc.dart';
import 'package:server_box/core/extension/context/locale.dart';
import 'package:server_box/data/model/container/type.dart';
import 'package:server_box/data/res/misc.dart';
sealed class ContainerPs {
final String? id = null;

View File

@@ -1,5 +1,5 @@
import 'package:toolbox/data/model/container/image.dart';
import 'package:toolbox/data/model/container/ps.dart';
import 'package:server_box/data/model/container/image.dart';
import 'package:server_box/data/model/container/ps.dart';
enum ContainerType {
docker,

View File

@@ -1,4 +1,4 @@
import 'package:toolbox/data/model/server/dist.dart';
import 'package:server_box/data/model/server/dist.dart';
enum PkgManager {
apt,

View File

@@ -1,4 +1,4 @@
import 'package:toolbox/data/model/pkg/manager.dart';
import 'package:server_box/data/model/pkg/manager.dart';
class UpgradePkgInfo {
final PkgManager? _mgr;

View File

@@ -1,14 +1,16 @@
import 'dart:collection';
import 'package:fl_chart/fl_chart.dart';
import 'package:toolbox/data/model/server/time_seq.dart';
import 'package:toolbox/data/res/status.dart';
import 'package:fl_lib/fl_lib.dart';
import 'package:server_box/data/model/server/time_seq.dart';
import 'package:server_box/data/res/status.dart';
/// Capacity of the FIFO queue
const _kCap = 30;
class Cpus extends TimeSeq<List<SingleCpuCore>> {
Cpus(super.init1, super.init2);
final Map<String, int> brand = {};
@override
void onUpdate() {
_coresCount = now.length;
@@ -23,10 +25,16 @@ class Cpus extends TimeSeq<List<SingleCpuCore>> {
double usedPercent({int coreIdx = 0}) {
if (now.length != pre.length) return 0;
final idleDelta = now[coreIdx].idle - pre[coreIdx].idle;
final totalDelta = now[coreIdx].total - pre[coreIdx].total;
final used = idleDelta / totalDelta;
return used.isNaN ? 0 : 100 - used * 100;
if (now.isEmpty) return 0;
try {
final idleDelta = now[coreIdx].idle - pre[coreIdx].idle;
final totalDelta = now[coreIdx].total - pre[coreIdx].total;
final used = idleDelta / totalDelta;
return used.isNaN ? 0 : 100 - used * 100;
} catch (e, s) {
Loggers.app.warning('Cpus.usedPercent()', e, s);
return 0;
}
}
int _coresCount = 0;
@@ -175,6 +183,22 @@ class SingleCpuCore extends TimeSeqIface<SingleCpuCore> {
}
}
final class CpuBrand {
static Map<String, int> parse(String raw) {
final lines = raw.split('\n');
// {brand: count}
final brands = <String, int>{};
for (var line in lines) {
if (line.contains('model name')) {
final model = line.split(':').last.trim();
final count = brands[model] ?? 0;
brands[model] = count + 1;
}
}
return brands;
}
}
final _bsdCpuPercentReg = RegExp(r'(\d+\.\d+)%');
/// TODO: Change this implementation to parse cpu status on BSD system

View File

@@ -1,5 +1,5 @@
import 'package:fl_lib/fl_lib.dart';
import 'package:toolbox/data/model/server/time_seq.dart';
import 'package:server_box/data/model/server/time_seq.dart';
import '../../res/misc.dart';

View File

@@ -1,5 +1,5 @@
import 'package:fl_lib/fl_lib.dart';
import 'package:toolbox/core/extension/context/locale.dart';
import 'package:server_box/core/extension/context/locale.dart';
enum PveResType {
lxc,

View File

@@ -1,5 +1,4 @@
import 'package:fl_lib/fl_lib.dart';
import 'package:toolbox/core/extension/context/locale.dart';
final class SensorAdaptor {
final String raw;
@@ -37,7 +36,7 @@ final class SensorItem {
String get toMarkdown {
final sb = StringBuffer();
sb.writeln('| ${l10n.name} | ${l10n.content} |');
sb.writeln('| ${libL10n.name} | ${libL10n.content} |');
sb.writeln('| --- | --- |');
for (final entry in details.entries) {
sb.writeln('| ${entry.key} | ${entry.value} |');
@@ -80,9 +79,7 @@ final class SensorItem {
for (var idx = 2; idx < len; idx++) {
final part = sensorLines[idx];
final detailParts = part.split(':');
if (detailParts.length < 2) {
continue;
}
if (detailParts.length < 2) continue;
final key = detailParts[0].trim();
final value = detailParts[1].trim();
details[key] = value;

View File

@@ -1,23 +1,18 @@
import 'package:dartssh2/dartssh2.dart';
import 'package:fl_lib/fl_lib.dart';
import 'package:toolbox/core/extension/context/locale.dart';
import 'package:toolbox/data/model/app/error.dart';
import 'package:toolbox/data/model/app/shell_func.dart';
import 'package:toolbox/data/model/server/battery.dart';
import 'package:toolbox/data/model/server/conn.dart';
import 'package:toolbox/data/model/server/cpu.dart';
import 'package:toolbox/data/model/server/disk.dart';
import 'package:toolbox/data/model/server/memory.dart';
import 'package:toolbox/data/model/server/net_speed.dart';
import 'package:toolbox/data/model/server/nvdia.dart';
import 'package:toolbox/data/model/server/sensors.dart';
import 'package:toolbox/data/model/server/server_private_info.dart';
import 'package:toolbox/data/model/server/system.dart';
import 'package:toolbox/data/model/server/temp.dart';
import '../app/tag_pickable.dart';
part 'server.ext.dart';
import 'package:server_box/data/model/app/error.dart';
import 'package:server_box/data/model/app/shell_func.dart';
import 'package:server_box/data/model/app/tag_pickable.dart';
import 'package:server_box/data/model/server/battery.dart';
import 'package:server_box/data/model/server/conn.dart';
import 'package:server_box/data/model/server/cpu.dart';
import 'package:server_box/data/model/server/disk.dart';
import 'package:server_box/data/model/server/memory.dart';
import 'package:server_box/data/model/server/net_speed.dart';
import 'package:server_box/data/model/server/nvdia.dart';
import 'package:server_box/data/model/server/sensors.dart';
import 'package:server_box/data/model/server/server_private_info.dart';
import 'package:server_box/data/model/server/system.dart';
import 'package:server_box/data/model/server/temp.dart';
class Server implements TagPickable {
ServerPrivateInfo spi;

View File

@@ -1,58 +0,0 @@
part of 'server.dart';
extension ServerX on Server {
String getTopRightStr(ServerPrivateInfo spi) {
switch (conn) {
case ServerConn.disconnected:
return l10n.disconnected;
case ServerConn.finished:
// Highest priority of temperature display
final cmdTemp = () {
final val = status.customCmds['server_card_top_right'];
if (val == null) return null;
// This returned value is used on server card top right, so it should
// be a single line string.
return val.split('\n').lastOrNull;
}();
final temperatureVal = () {
// Second priority
final preferTempDev = spi.custom?.preferTempDev;
if (preferTempDev != null) {
final preferTemp = status.sensors
.firstWhereOrNull((e) => e.device == preferTempDev)
?.summary
?.split(' ')
.firstOrNull;
if (preferTemp != null) {
return double.tryParse(preferTemp.replaceFirst('°C', ''));
}
}
// Last priority
final temp = status.temps.first;
if (temp != null) {
return temp;
}
return null;
}();
final upTime = status.more[StatusCmdType.uptime];
final items = [
cmdTemp ??
(temperatureVal != null
? '${temperatureVal.toStringAsFixed(1)}°C'
: null),
upTime
];
final str = items.where((e) => e != null && e.isNotEmpty).join(' | ');
if (str.isEmpty) return l10n.noResult;
return str;
case ServerConn.loading:
return l10n.serverTabLoading;
case ServerConn.connected:
return l10n.connected;
case ServerConn.connecting:
return l10n.serverTabConnecting;
case ServerConn.failed:
return status.err != null ? l10n.viewErr : l10n.serverTabFailed;
}
}
}

View File

@@ -1,8 +1,8 @@
import 'package:hive_flutter/hive_flutter.dart';
import 'package:toolbox/data/model/server/custom.dart';
import 'package:toolbox/data/model/server/server.dart';
import 'package:toolbox/data/model/server/wol_cfg.dart';
import 'package:toolbox/data/res/provider.dart';
import 'package:server_box/data/model/server/custom.dart';
import 'package:server_box/data/model/server/server.dart';
import 'package:server_box/data/model/server/wol_cfg.dart';
import 'package:server_box/data/res/provider.dart';
import '../app/error.dart';
@@ -42,6 +42,10 @@ class ServerPrivateInfo {
@HiveField(11)
final WakeOnLanCfg? wolCfg;
/// It only applies to SSH terminal.
@HiveField(12)
final Map<String, String>? envs;
final String id;
const ServerPrivateInfo({
@@ -57,6 +61,7 @@ class ServerPrivateInfo {
this.jumpId,
this.custom,
this.wolCfg,
this.envs,
}) : id = '$user@$ip:$port';
static ServerPrivateInfo fromJson(Map<String, dynamic> json) {
@@ -76,6 +81,15 @@ class ServerPrivateInfo {
final wolCfg = json["wolCfg"] == null
? null
: WakeOnLanCfg.fromJson(json["wolCfg"].cast<String, dynamic>());
final envs_ = json["envs"] as Map<String, dynamic>?;
final envs = <String, String>{};
if (envs_ != null) {
envs_.forEach((key, value) {
if (value is String) {
envs[key] = value;
}
});
}
return ServerPrivateInfo(
name: name,
@@ -90,6 +104,7 @@ class ServerPrivateInfo {
jumpId: jumpId,
custom: custom,
wolCfg: wolCfg,
envs: envs.isEmpty ? null : envs,
);
}
@@ -123,6 +138,9 @@ class ServerPrivateInfo {
if (wolCfg != null) {
data["wolCfg"] = wolCfg?.toJson();
}
if (envs != null) {
data["envs"] = envs;
}
return data;
}
@@ -162,6 +180,28 @@ class ServerPrivateInfo {
String toString() {
return id;
}
static const example = ServerPrivateInfo(
name: 'name',
ip: 'ip',
port: 22,
user: 'root',
pwd: 'pwd',
keyId: 'private_key_id',
tags: ['tag1', 'tag2'],
alterUrl: 'user@ip:port',
autoConnect: true,
jumpId: 'jump_server_id',
custom: ServerCustom(
pveAddr: 'http://localhost:8006',
pveIgnoreCert: false,
cmds: {
'echo': 'echo hello',
},
preferTempDev: 'nvme-pci-0400',
logoUrl: 'https://example.com/logo.png',
),
);
}
class _IpPort {

View File

@@ -29,13 +29,14 @@ class ServerPrivateInfoAdapter extends TypeAdapter<ServerPrivateInfo> {
jumpId: fields[9] as String?,
custom: fields[10] as ServerCustom?,
wolCfg: fields[11] as WakeOnLanCfg?,
envs: (fields[12] as Map?)?.cast<String, String>(),
);
}
@override
void write(BinaryWriter writer, ServerPrivateInfo obj) {
writer
..writeByte(12)
..writeByte(13)
..writeByte(0)
..write(obj.name)
..writeByte(1)
@@ -59,7 +60,9 @@ class ServerPrivateInfoAdapter extends TypeAdapter<ServerPrivateInfo> {
..writeByte(10)
..write(obj.custom)
..writeByte(11)
..write(obj.wolCfg);
..write(obj.wolCfg)
..writeByte(12)
..write(obj.envs);
}
@override

View File

@@ -1,9 +1,9 @@
import 'package:fl_lib/fl_lib.dart';
import 'package:toolbox/data/model/server/battery.dart';
import 'package:toolbox/data/model/server/nvdia.dart';
import 'package:toolbox/data/model/server/sensors.dart';
import 'package:toolbox/data/model/server/server.dart';
import 'package:toolbox/data/model/server/system.dart';
import 'package:server_box/data/model/server/battery.dart';
import 'package:server_box/data/model/server/nvdia.dart';
import 'package:server_box/data/model/server/sensors.dart';
import 'package:server_box/data/model/server/server.dart';
import 'package:server_box/data/model/server/system.dart';
import '../app/shell_func.dart';
import 'cpu.dart';
@@ -71,6 +71,9 @@ Future<ServerStatus> _getLinuxStatus(ServerStatusUpdateReq req) async {
try {
final cpus = SingleCpuCore.parse(StatusCmdType.cpu.find(segments));
req.ss.cpu.update(cpus);
final brand = CpuBrand.parse(StatusCmdType.cpuBrand.find(segments));
req.ss.cpu.brand.clear();
req.ss.cpu.brand.addAll(brand);
} catch (e, s) {
Loggers.app.warning(e, s);
}

View File

@@ -1,5 +1,9 @@
import 'dart:async';
import 'package:fl_lib/fl_lib.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:toolbox/data/model/server/server_private_info.dart';
import 'package:server_box/data/model/server/server_private_info.dart';
import 'package:xterm/core.dart';
import '../app/tag_pickable.dart';
@@ -53,19 +57,116 @@ class Snippet implements TagPickable {
@override
String get tagName => name;
String fmtWith(ServerPrivateInfo spi) {
final fmted = script.replaceAllMapped(
RegExp(r'\${.+?}'),
static final fmtFinder = RegExp(r'\$\{[^{}]+\}');
String fmtWithSpi(ServerPrivateInfo spi) {
return script.replaceAllMapped(
fmtFinder,
(match) {
final key = match.group(0);
final func = fmtArgs[key];
if (func == null) {
return key!;
}
return func(spi);
if (func != null) return func(spi);
// If not found, return the original content for further processing
return key ?? '';
},
);
return fmted;
}
Future<void> runInTerm(
Terminal terminal,
ServerPrivateInfo spi, {
bool autoEnter = false,
}) async {
final argsFmted = fmtWithSpi(spi);
final matches = fmtFinder.allMatches(argsFmted);
/// There is no [TerminalKey] in the script
if (matches.isEmpty) {
terminal.textInput(argsFmted);
if (autoEnter) terminal.keyInput(TerminalKey.enter);
return;
}
// Records all start and end indexes of the matches
final (starts, ends) = matches.fold((<int>[], <int>[]), (pre, e) {
pre.$1.add(e.start);
pre.$2.add(e.end);
return pre;
});
// Check all indexes, `(idx + 1).start` must >= `idx.end`
for (var i = 0; i < starts.length - 1; i++) {
final lastEnd = ends[i];
final nextStart = starts[i + 1];
if (nextStart < lastEnd) {
throw 'Invalid format: $nextStart < $lastEnd';
}
}
// Start term input
if (starts.first > 0) {
terminal.textInput(argsFmted.substring(0, starts.first));
}
// Process matched
for (var idx = 0; idx < starts.length; idx++) {
final start = starts[idx];
final end = ends[idx];
final key = argsFmted.substring(start, end).toLowerCase();
// Special funcs
final special = _find(SnippetFuncs.specialCtrl, key);
if (special != null) {
final raw = key.substring(special.key.length + 1, key.length - 1);
await special.value((term: terminal, raw: raw));
}
// Term keys
final termKey = _find(fmtTermKeys, key);
if (termKey != null) await _doTermKeys(terminal, termKey, key);
}
// End term input
if (ends.last < argsFmted.length) {
terminal.textInput(argsFmted.substring(ends.last));
}
if (autoEnter) terminal.keyInput(TerminalKey.enter);
}
Future<void> _doTermKeys(
Terminal terminal,
MapEntry<String, TerminalKey> termKey,
String key,
) async {
if (termKey.value == TerminalKey.enter) {
terminal.keyInput(TerminalKey.enter);
return;
}
final ctrlAlt = switch (termKey.value) {
TerminalKey.control => (ctrl: true, alt: false),
TerminalKey.alt => (ctrl: false, alt: true),
_ => (ctrl: false, alt: false),
};
// `${ctrl+ad}` -> `ctrla + d`
final chars = key.substring(termKey.key.length + 1, key.length - 1);
if (chars.isEmpty) return;
final ok = terminal.charInput(
chars.codeUnitAt(0),
ctrl: ctrlAlt.ctrl,
alt: ctrlAlt.alt,
);
if (!ok) {
Loggers.app.warning('Failed to input: $key');
}
terminal.textInput(chars.substring(1));
}
MapEntry<String, T>? _find<T>(Map<String, T> map, String key) {
return map.entries.firstWhereOrNull((e) => key.startsWith(e.key));
}
static final fmtArgs = {
@@ -76,6 +177,20 @@ class Snippet implements TagPickable {
r'${id}': (ServerPrivateInfo spi) => spi.id,
r'${name}': (ServerPrivateInfo spi) => spi.name,
};
/// r'${ctrl+ad}' -> TerminalKey.control, a, d
static final fmtTermKeys = {
r'${ctrl': TerminalKey.control,
r'${alt': TerminalKey.alt,
};
static const example = Snippet(
name: 'example',
script: 'echo hello',
tags: ['tag'],
note: 'note',
autoRunOn: ['server_id'],
);
}
class SnippetResult {
@@ -89,3 +204,32 @@ class SnippetResult {
required this.time,
});
}
typedef SnippetFuncCtx = ({Terminal term, String raw});
abstract final class SnippetFuncs {
static final specialCtrl = {
// `${sleep 3}` -> sleep 3 seconds
r'${sleep': SnippetFuncs.sleep,
r'${enter': SnippetFuncs.enter,
};
static const help = {
'sleep': 'Sleep for a few seconds',
'enter': 'Enter a few times',
};
static FutureOr<void> sleep(SnippetFuncCtx ctx) async {
final seconds = int.tryParse(ctx.raw);
if (seconds == null) return;
final duration = Duration(seconds: seconds);
await Future.delayed(duration);
}
static FutureOr<void> enter(SnippetFuncCtx ctx) async {
final times = int.tryParse(ctx.raw) ?? 1;
for (var i = 0; i < times; i++) {
ctx.term.keyInput(TerminalKey.enter);
}
}
}

View File

@@ -1,4 +1,4 @@
import 'package:toolbox/data/model/app/shell_func.dart';
import 'package:server_box/data/model/app/shell_func.dart';
enum SystemType {
linux._(linuxSign),

View File

@@ -1,4 +1,4 @@
import 'package:toolbox/data/res/store.dart';
import 'package:server_box/data/res/store.dart';
class TryLimiter {
final Map<String, int> _triedTimes = {};

View File

@@ -1,5 +1,5 @@
import 'package:dartssh2/dartssh2.dart';
import 'package:toolbox/data/model/sftp/absolute_path.dart';
import 'package:server_box/data/model/sftp/absolute_path.dart';
class SftpBrowserStatus {
List<SftpName>? files;

View File

@@ -1,11 +1,4 @@
import 'dart:async';
import 'package:fl_lib/fl_lib.dart';
import 'package:toolbox/data/res/store.dart';
import '../../../core/utils/server.dart';
import '../server/server_private_info.dart';
import 'worker.dart';
part of 'worker.dart';
class SftpReq {
final ServerPrivateInfo spi;
@@ -69,9 +62,8 @@ class SftpReqStatus {
int get hashCode => id ^ super.hashCode;
void dispose() {
// ignore: deprecated_member_use_from_same_package
worker.dispose();
completer?.complete();
worker._dispose();
completer?.complete(true);
}
void onNotify(dynamic event) {

View File

@@ -5,9 +5,12 @@ import 'dart:typed_data';
import 'package:dartssh2/dartssh2.dart';
import 'package:easy_isolate/easy_isolate.dart';
import 'package:fl_lib/fl_lib.dart';
import 'package:server_box/core/utils/server.dart';
import 'package:server_box/data/model/server/server_private_info.dart';
import 'package:server_box/data/res/store.dart';
import '../../../core/utils/server.dart';
import 'req.dart';
part 'req.dart';
class SftpWorker {
final Function(Object event) onNotify;
@@ -20,14 +23,7 @@ class SftpWorker {
required this.req,
});
/// Use [@Deprecated] to prevent calling [SftpWorker.dispose] directly
///
/// Don't delete this method
@Deprecated(
"Use [SftpWorkerStatus.dispose] to dispose the worker, "
"instead of [SftpWorker.dispose]",
)
void dispose() {
void _dispose() {
worker.dispose();
}

View File

@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:toolbox/core/extension/context/locale.dart';
import 'package:server_box/core/extension/context/locale.dart';
import 'package:xterm/core.dart';
part 'virtual_key.g.dart';

View File

@@ -3,13 +3,6 @@ import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart';
class AppProvider extends ChangeNotifier {
int? _newestBuild;
int? get newestBuild => _newestBuild;
set newestBuild(int? build) {
_newestBuild = build;
notifyListeners();
}
BuildContext? ctx;
bool isWearOS = false;

View File

@@ -4,13 +4,13 @@ import 'dart:convert';
import 'package:dartssh2/dartssh2.dart';
import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart';
import 'package:toolbox/core/extension/ssh_client.dart';
import 'package:toolbox/data/model/app/shell_func.dart';
import 'package:toolbox/data/model/container/image.dart';
import 'package:toolbox/data/model/container/ps.dart';
import 'package:toolbox/data/model/app/error.dart';
import 'package:toolbox/data/model/container/type.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:server_box/core/extension/ssh_client.dart';
import 'package:server_box/data/model/app/shell_func.dart';
import 'package:server_box/data/model/container/image.dart';
import 'package:server_box/data/model/container/ps.dart';
import 'package:server_box/data/model/app/error.dart';
import 'package:server_box/data/model/container/type.dart';
import 'package:server_box/data/res/store.dart';
final _dockerNotFound =
RegExp(r"command not found|Unknown command|Command '\w+' not found");
@@ -160,11 +160,18 @@ class ContainerProvider extends ChangeNotifier {
}
// Parse images
final imageRaw = ContainerCmdType.images.find(segments);
final imageRaw = ContainerCmdType.images.find(segments).trim();
final isEntireJson = imageRaw.startsWith('[') && imageRaw.endsWith(']');
try {
final imgLines = imageRaw.split('\n');
imgLines.removeWhere((element) => element.isEmpty);
images = imgLines.map((e) => ContainerImg.fromRawJson(e, type)).toList();
if (isEntireJson) {
images = (json.decode(imageRaw) as List)
.map((e) => ContainerImg.fromRawJson(json.encode(e), type))
.toList();
} else {
final lines = imageRaw.split('\n');
lines.removeWhere((element) => element.isEmpty);
images = lines.map((e) => ContainerImg.fromRawJson(e, type)).toList();
}
} catch (e, trace) {
error = ContainerErr(
type: ContainerErrType.parseImages,
@@ -298,6 +305,6 @@ enum ContainerCmdType {
}) {
return ContainerCmdType.values
.map((e) => e.exec(type, sudo: sudo, includeStats: includeStats))
.join(' && echo ${ShellFunc.seperator} && ');
.join('\necho ${ShellFunc.seperator}\n');
}
}

View File

@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:toolbox/data/model/server/private_key_info.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:server_box/data/model/server/private_key_info.dart';
import 'package:server_box/data/res/store.dart';
class PrivateKeyProvider extends ChangeNotifier {
List<PrivateKeyInfo> get pkis => _pkis;

View File

@@ -6,10 +6,10 @@ import 'package:dio/dio.dart';
import 'package:dio/io.dart';
import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart';
import 'package:toolbox/core/extension/context/locale.dart';
import 'package:toolbox/data/model/app/error.dart';
import 'package:toolbox/data/model/server/pve.dart';
import 'package:toolbox/data/model/server/server_private_info.dart';
import 'package:server_box/core/extension/context/locale.dart';
import 'package:server_box/data/model/app/error.dart';
import 'package:server_box/data/model/server/pve.dart';
import 'package:server_box/data/model/server/server_private_info.dart';
import 'package:dartssh2/dartssh2.dart';
typedef PveCtrlFunc = Future<bool> Function(String node, String id);

View File

@@ -1,24 +1,23 @@
import 'dart:async';
import 'dart:io';
// import 'dart:io';
import 'package:computer/computer.dart';
import 'package:dartssh2/dartssh2.dart';
import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart';
import 'package:toolbox/core/extension/ssh_client.dart';
import 'package:toolbox/core/utils/ssh_auth.dart';
import 'package:toolbox/data/model/app/error.dart';
import 'package:toolbox/data/model/app/shell_func.dart';
import 'package:toolbox/data/model/server/system.dart';
import 'package:toolbox/data/model/sftp/req.dart';
import 'package:toolbox/data/res/provider.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:server_box/core/extension/ssh_client.dart';
import 'package:server_box/core/utils/ssh_auth.dart';
import 'package:server_box/data/model/app/error.dart';
import 'package:server_box/data/model/app/shell_func.dart';
import 'package:server_box/data/model/server/system.dart';
// import 'package:server_box/data/model/sftp/req.dart';
// import 'package:server_box/data/res/provider.dart';
import 'package:server_box/data/res/store.dart';
import '../../core/utils/server.dart';
import '../model/server/server.dart';
import '../model/server/server_private_info.dart';
import '../model/server/server_status_update_req.dart';
import '../model/server/snippet.dart';
import '../model/server/try_limiter.dart';
import '../res/status.dart';
@@ -27,8 +26,8 @@ class ServerProvider extends ChangeNotifier {
Iterable<Server> get servers => _servers.values;
final List<String> _serverOrder = [];
List<String> get serverOrder => _serverOrder;
final _tags = ValueNotifier(<String>[]);
ValueNotifier<List<String>> get tags => _tags;
final _tags = ValueNotifier(<String>{});
ValueNotifier<Set<String>> get tags => _tags;
Timer? _timer;
@@ -86,7 +85,6 @@ class ServerProvider extends ChangeNotifier {
}
void _updateTags() {
_tags.value.clear();
for (final s in _servers.values) {
if (s.spi.tags == null) continue;
for (final t in s.spi.tags!) {
@@ -95,21 +93,7 @@ class ServerProvider extends ChangeNotifier {
}
}
}
_tags.value.sort();
_tags.notifyListeners();
}
void renameTag(String old, String new_) {
for (final s in _servers.values) {
if (s.spi.tags == null) continue;
for (var i = 0; i < s.spi.tags!.length; i++) {
if (s.spi.tags![i] == old) {
s.spi.tags![i] = new_;
}
}
Stores.server.update(s.spi, s.spi);
}
_updateTags();
_tags.value = (_tags.value.toList()..sort()).toSet();
}
Server genServer(ServerPrivateInfo spi) {
@@ -314,62 +298,41 @@ class ServerProvider extends ChangeNotifier {
_setServerState(s, ServerConn.connected);
// Write script to server
// by ssh
final scriptRaw = ShellFunc.allScript(spi.custom?.cmds).uint8List;
try {
await s.client?.runForOutput(
ShellFunc.installShellCmd,
final writeScriptResult = await s.client!.runForOutput(
ShellFunc.getInstallShellCmd(spi.id),
action: (session) async {
session.stdin.add(scriptRaw);
session.stdin.close();
},
);
if (writeScriptResult.isNotEmpty) {
ShellFunc.switchScriptDir(spi.id);
throw String.fromCharCodes(writeScriptResult);
}
} on SSHAuthAbortError catch (e) {
TryLimiter.inc(sid);
s.status.err = SSHErr(type: SSHErrType.auth, message: e.toString());
final err = SSHErr(type: SSHErrType.auth, message: e.toString());
s.status.err = err;
Loggers.app.warning(err);
_setServerState(s, ServerConn.failed);
return;
} on SSHAuthFailError catch (e) {
TryLimiter.inc(sid);
s.status.err = SSHErr(type: SSHErrType.auth, message: e.toString());
final err = SSHErr(type: SSHErrType.auth, message: e.toString());
s.status.err = err;
Loggers.app.warning(err);
_setServerState(s, ServerConn.failed);
return;
} catch (e) {
Loggers.app.warning('Write script to ${spi.name} by shell', e);
/// by sftp
final localPath = Paths.doc.joinPath('install.sh');
final file = File(localPath);
try {
file.writeAsBytes(scriptRaw);
final completer = Completer();
final homePath = (await s.client?.run('echo \$HOME').string)?.trim();
if (homePath == null || homePath.isEmpty) {
throw Exception('Got empty home path');
}
final remotePath = ShellFunc.getShellPath(homePath);
final reqId = Pros.sftp.add(
SftpReq(spi, remotePath, localPath, SftpReqType.upload),
completer: completer,
);
await completer.future;
final err = Pros.sftp.get(reqId)?.error;
if (err != null) {
throw err;
}
} catch (ee) {
TryLimiter.inc(sid);
s.status.err = SSHErr(
type: SSHErrType.writeScript,
message: '$e\n\n$ee',
);
_setServerState(s, ServerConn.failed);
Loggers.app.warning('Write script to ${spi.name} by sftp', ee);
return;
} finally {
if (await file.exists()) await file.delete();
}
// If max try times < 2 and can't write script, this will stop the status getting and etc.
// TryLimiter.inc(sid);
final err = SSHErr(type: SSHErrType.writeScript, message: e.toString());
s.status.err = err;
Loggers.app.warning(err);
_setServerState(s, ServerConn.failed);
}
}
@@ -386,7 +349,7 @@ class ServerProvider extends ChangeNotifier {
String? raw;
try {
raw = await s.client?.run(ShellFunc.status.exec).string;
raw = await s.client?.run(ShellFunc.status.exec(spi.id)).string;
segments = raw?.split(ShellFunc.seperator).map((e) => e.trim()).toList();
if (raw == null || raw.isEmpty || segments == null || segments.isEmpty) {
if (Stores.setting.keepStatusWhenErr.fetch()) {
@@ -459,26 +422,4 @@ class ServerProvider extends ChangeNotifier {
// reset try times only after prepared successfully
TryLimiter.reset(sid);
}
Future<SnippetResult?> runSnippet(String id, Snippet snippet) async {
final server = _servers[id];
if (server == null) return null;
final watch = Stopwatch()..start();
final result = await server.client?.run(snippet.fmtWith(server.spi)).string;
final time = watch.elapsed;
watch.stop();
if (result == null) return null;
return SnippetResult(
dest: _servers[id]?.spi.name,
result: result,
time: time,
);
}
// Future<List<SnippetResult?>> runSnippetsMulti(
// List<String> ids,
// Snippet snippet,
// ) async {
// return await Future.wait(ids.map((id) async => runSnippet(id, snippet)));
// }
}

View File

@@ -1,8 +1,7 @@
import 'dart:async';
import 'package:flutter/material.dart';
import '../model/sftp/req.dart';
import 'package:server_box/data/model/sftp/worker.dart';
class SftpProvider extends ChangeNotifier {
final List<SftpReqStatus> _status = [];

View File

@@ -2,15 +2,14 @@ import 'dart:convert';
import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart';
import 'package:toolbox/data/model/server/snippet.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:server_box/data/model/server/snippet.dart';
import 'package:server_box/data/res/store.dart';
class SnippetProvider extends ChangeNotifier {
late List<Snippet> _snippets;
List<Snippet> get snippets => _snippets;
final _tags = ValueNotifier(<String>[]);
ValueNotifier<List<String>> get tags => _tags;
final tags = ValueNotifier(<String>{});
void load() {
_snippets = Stores.snippet.fetch();
@@ -29,16 +28,14 @@ class SnippetProvider extends ChangeNotifier {
}
void _updateTags() {
_tags.value.clear();
final tags = <String>{};
final tags_ = <String>{};
for (final s in _snippets) {
if (s.tags?.isEmpty ?? true) {
continue;
final t = s.tags;
if (t != null) {
tags_.addAll(t);
}
tags.addAll(s.tags!);
}
_tags.value.addAll(tags);
_tags.notifyListeners();
tags.value = tags_;
}
void add(Snippet snippet) {

View File

@@ -1,5 +1,5 @@
import 'package:flutter/widgets.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:server_box/data/res/store.dart';
import 'package:xterm/core.dart';
class VirtKeyProvider extends TerminalInputHandler with ChangeNotifier {

View File

@@ -2,9 +2,6 @@
class BuildData {
static const String name = "ServerBox";
static const int build = 948;
static const String engine = "3.22.1";
static const String buildAt = "2024-06-08 21:21:36";
static const int modifications = 3;
static const int script = 48;
static const int build = 1051;
static const int script = 56;
}

View File

@@ -3,21 +3,26 @@ abstract final class GithubIds {
// If you want to change your Github ID, please open an issue.
static const contributors = <GhId>{
'PaperCube',
'Integral-Tech',
'its-tom',
'leganck',
'azkadev',
'kalashnikov',
'FrancXPT',
'RainSunMe',
'calvinweb',
'No06',
'QazCetelic',
'RainSunMe',
'FrancXPT',
'Liloupar',
'dccif',
'QazCetelic',
'mikropsoft',
};
static const participants = <GhId>{
'jaychoubaby',
'fecture',
'Tao173',
'Jasonzhu1207',
'QingAnLe',
'wxdjs',
'Aeorq',
@@ -70,7 +75,28 @@ abstract final class GithubIds {
'pgs666',
'FHU-yezi',
'ZRY233',
'Jasonzhu1207',
'sakuraanzu',
'licaon-kter',
'77160860',
'mijjjj',
'muyunil',
'Hua159',
'jaydong2016',
'geol',
'Mooling0602',
'IllTamer',
'marlkiller',
'hlarc',
'itsandrewpao',
'StudyingLover',
'QJAG1024',
'Wuming-HUST',
'WolfCanglong',
'liwenjie119',
'logce',
'h-lyf',
'88484396',
'honggeigei',
};
}

View File

@@ -1,13 +1,11 @@
import 'package:fl_lib/fl_lib.dart';
import 'package:toolbox/data/provider/app.dart';
import 'package:toolbox/data/provider/private_key.dart';
import 'package:toolbox/data/provider/server.dart';
import 'package:toolbox/data/provider/sftp.dart';
import 'package:toolbox/data/provider/snippet.dart';
import 'package:server_box/data/provider/app.dart';
import 'package:server_box/data/provider/private_key.dart';
import 'package:server_box/data/provider/server.dart';
import 'package:server_box/data/provider/sftp.dart';
import 'package:server_box/data/provider/snippet.dart';
abstract final class Pros {
static final app = AppProvider();
static final debug = DebugProvider(maxLines: 177);
static final key = PrivateKeyProvider();
static final server = ServerProvider();
static final sftp = SftpProvider();

View File

@@ -1,5 +1,5 @@
import 'package:toolbox/data/model/server/server.dart';
import 'package:toolbox/data/model/server/temp.dart';
import 'package:server_box/data/model/server/server.dart';
import 'package:server_box/data/model/server/temp.dart';
import '../model/server/cpu.dart';
import '../model/server/disk.dart';

View File

@@ -1,10 +1,10 @@
import 'package:fl_lib/fl_lib.dart';
import 'package:toolbox/data/store/container.dart';
import 'package:toolbox/data/store/history.dart';
import 'package:toolbox/data/store/private_key.dart';
import 'package:toolbox/data/store/server.dart';
import 'package:toolbox/data/store/setting.dart';
import 'package:toolbox/data/store/snippet.dart';
import 'package:server_box/data/store/container.dart';
import 'package:server_box/data/store/history.dart';
import 'package:server_box/data/store/private_key.dart';
import 'package:server_box/data/store/server.dart';
import 'package:server_box/data/store/setting.dart';
import 'package:server_box/data/store/snippet.dart';
abstract final class Stores {
static final setting = SettingStore();

View File

@@ -2,7 +2,8 @@ abstract final class Urls {
static const cdnBase = 'https://cdn.lolli.tech/serverbox';
static const updateCfg = '$cdnBase/update2.json';
static const myGithub = 'https://github.com/lollipopkit';
static const appHelp = '$myGithub/flutter_server_box#-help';
static const appWiki = '$myGithub/flutter_server_box/wiki';
static const thisRepo = '$myGithub/flutter_server_box';
static const appHelp = '$thisRepo#-help';
static const appWiki = '$thisRepo/wiki';
static const analysis = 'https://countly.lolli.tech';
}

View File

@@ -1,6 +1,6 @@
import 'package:fl_lib/fl_lib.dart';
import 'package:toolbox/data/model/container/type.dart';
import 'package:toolbox/data/res/store.dart';
import 'package:server_box/data/model/container/type.dart';
import 'package:server_box/data/res/store.dart';
const _keyConfig = 'providerConfig';

View File

@@ -54,4 +54,7 @@ class HistoryStore extends PersistentStore {
late final sftpLastPath = _MapHistory(box: box, name: 'sftpLastPath');
late final sshCmds = _ListHistory(box: box, name: 'sshCmds');
/// Notify users that this app will write script to server to works properly
late final writeScriptTipShown = property('writeScriptTipShown', false);
}

View File

@@ -1,7 +1,7 @@
import 'package:fl_lib/fl_lib.dart';
import 'package:toolbox/data/model/app/menu/server_func.dart';
import 'package:toolbox/data/model/app/server_detail_card.dart';
import 'package:toolbox/data/model/ssh/virtual_key.dart';
import 'package:server_box/data/model/app/menu/server_func.dart';
import 'package:server_box/data/model/app/server_detail_card.dart';
import 'package:server_box/data/model/ssh/virtual_key.dart';
import '../model/app/net_view.dart';
import '../res/default.dart';
@@ -16,28 +16,16 @@ class SettingStore extends PersistentStore {
// item in the drawer of the home page)
/// Discussion #146
late final serverTabUseOldUI = property(
'serverTabUseOldUI',
false,
);
late final serverTabUseOldUI = property('serverTabUseOldUI', false);
/// Time out for server connect and more...
late final timeout = property(
'timeOut',
5,
);
late final timeout = property('timeOut', 5);
/// Record history of SFTP path and etc.
late final recordHistory = property(
'recordHistory',
true,
);
late final recordHistory = property('recordHistory', true);
/// Lanch page idx
late final launchPage = property(
'launchPage',
Defaults.launchPageIdx,
);
// late final launchPage = property('launchPage', Defaults.launchPageIdx);
/// Disk view: amount / IO
late final serverTabPreferDiskAmount = property(
@@ -50,15 +38,10 @@ class SettingStore extends PersistentStore {
/// Bigger for bigger font size
/// 1.0 means 100%
/// Warning: This may cause some UI issues
late final textFactor = property(
'textFactor',
1.0,
);
late final textFactor = property('textFactor', 1.0);
late final primaryColor = property(
'primaryColor',
4287106639,
);
/// The seed of color scheme
late final colorSeed = property('primaryColor', 4287106639);
late final serverStatusUpdateInterval = property(
'serverStatusUpdateInterval',
@@ -100,25 +83,14 @@ class SettingStore extends PersistentStore {
late final editorFontSize = property('editorFontSize', 12.5);
// Editor theme
late final editorTheme = property(
'editorTheme',
Defaults.editorTheme,
);
late final editorTheme = property('editorTheme', Defaults.editorTheme);
late final editorDarkTheme = property(
'editorDarkTheme',
Defaults.editorDarkTheme,
);
late final editorDarkTheme =
property('editorDarkTheme', Defaults.editorDarkTheme);
late final fullScreen = property(
'fullScreen',
false,
);
late final fullScreen = property('fullScreen', false);
late final fullScreenJitter = property(
'fullScreenJitter',
true,
);
late final fullScreenJitter = property('fullScreenJitter', true);
// late final fullScreenRotateQuarter = property(
// 'fullScreenRotateQuarter',
@@ -135,53 +107,29 @@ class SettingStore extends PersistentStore {
VirtKey.defaultOrder.map((e) => e.index).toList(),
);
late final netViewType = property(
'netViewType',
NetViewType.speed,
);
late final netViewType = property('netViewType', NetViewType.speed);
// Only valid on iOS
late final autoUpdateHomeWidget = property(
'autoUpdateHomeWidget',
isIOS,
);
late final autoUpdateHomeWidget = property('autoUpdateHomeWidget', isIOS);
late final autoCheckAppUpdate = property(
'autoCheckAppUpdate',
true,
);
late final autoCheckAppUpdate = property('autoCheckAppUpdate', true);
/// Display server tab function buttons on the bottom of each server card if [true]
///
/// Otherwise, display them on the top of server detail page
late final moveOutServerTabFuncBtns = property(
'moveOutServerTabFuncBtns',
true,
);
late final moveServerFuncs = property('moveOutServerTabFuncBtns', false);
/// Whether use `rm -r` to delete directory on SFTP
late final sftpRmrDir = property(
'sftpRmrDir',
false,
);
late final sftpRmrDir = property('sftpRmrDir', false);
/// Whether use system's primary color as the app's primary color
late final useSystemPrimaryColor = property(
'useSystemPrimaryColor',
false,
);
late final useSystemPrimaryColor = property('useSystemPrimaryColor', false);
/// Only valid on iOS and macOS
late final icloudSync = property(
'icloudSync',
false,
);
late final icloudSync = property('icloudSync', false);
/// Only valid on iOS / Android / Windows
late final useBioAuth = property(
'useBioAuth',
false,
);
late final useBioAuth = property('useBioAuth', false);
/// The performance of highlight is bad
late final editorHighlight = property('editorHighlight', true);
@@ -265,8 +213,6 @@ class SettingStore extends PersistentStore {
late final horizonVirtKey = property('horizonVirtKey', false);
late final collectUsage = property('collectUsage', true);
/// general wake lock
late final generalWakeLock = property('generalWakeLock', false);
@@ -278,6 +224,18 @@ class SettingStore extends PersistentStore {
late final betaTest = property('betaTest', false);
/// If it's empty, skip change window size.
/// Format: {width}x{height}
late final windowSize = property('windowSize', '');
late final introVer = property('introVer', 0);
late final letterCache = property('letterCache', false);
/// Set it to `$EDITOR`, `vim` and etc. to use remote system editor in SSH terminal.
/// Set it empty to use local editor GUI.
late final sftpEditor = property('sftpEditor', '');
// Never show these settings for users
//
// ------BEGIN------

102
lib/intro.dart Normal file
View File

@@ -0,0 +1,102 @@
part of 'app.dart';
final class _IntroPage extends StatelessWidget {
final List<IntroPageBuilder> pages;
const _IntroPage(this.pages);
static const _builders = {
1: _buildAppSettings,
};
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, cons) {
final padTop = cons.maxHeight * .16;
final pages_ = pages.map((e) => e(context, padTop)).toList();
return IntroPage(
args: IntroPageArgs(
pages: pages_,
onDone: (ctx) {
Stores.setting.introVer.put(BuildData.build);
Navigator.of(ctx).pushReplacement(
MaterialPageRoute(builder: (_) => const HomePage()),
);
},
),
);
},
);
}
static Widget _buildAppSettings(BuildContext ctx, double padTop) {
return ListView(
padding: _introListPad,
children: [
SizedBox(height: padTop),
IntroPage.title(text: l10n.init, big: true),
SizedBox(height: padTop),
ListTile(
leading: const Icon(IonIcons.language),
title: Text(libL10n.language),
onTap: () async {
final selected = await ctx.showPickSingleDialog(
title: libL10n.language,
items: AppLocalizations.supportedLocales,
name: (p0) => p0.nativeName,
initial: _setting.locale.fetch().toLocale,
);
if (selected != null) {
_setting.locale.put(selected.code);
RNodes.app.notify();
}
},
trailing: Text(
ctx.localeNativeName,
style: const TextStyle(fontSize: 15, color: Colors.grey),
),
).cardx,
ListTile(
leading: const Icon(Icons.update),
title: Text(libL10n.autoCheckUpdate),
subtitle: Text(l10n.fdroidReleaseTip, style: UIs.textGrey),
trailing: StoreSwitch(prop: _setting.autoCheckAppUpdate),
).cardx,
ListTile(
leading: const Icon(MingCute.delete_2_fill),
title: TipText('rm -r', l10n.sftpRmrDirSummary),
trailing: StoreSwitch(prop: _setting.sftpRmrDir),
).cardx,
ListTile(
leading: const Icon(MingCute.chart_line_line, size: _kIconSize),
title: TipText(l10n.stat, l10n.parseContainerStatsTip),
trailing: StoreSwitch(prop: _setting.containerParseStat),
).cardx,
ListTile(
leading: const Icon(OctIcons.cpu),
title: TipText(l10n.noLineChartForCpu, l10n.cpuViewAsProgressTip),
trailing: StoreSwitch(prop: _setting.cpuViewAsProgress),
).cardx,
ListTile(
leading: const Icon(Bootstrap.alphabet),
title: TipText(l10n.letterCache, l10n.letterCacheTip),
trailing: StoreSwitch(prop: _setting.letterCache),
).cardx,
UIs.height77,
],
);
}
static List<IntroPageBuilder> get builders {
final storedVer = _setting.introVer.fetch();
return _builders.entries
.where((e) => e.key > storedVer)
.map((e) => e.value)
.toList();
}
static final _setting = Stores.setting;
static const _kIconSize = 23.0;
static const _introListPad = EdgeInsets.symmetric(horizontal: 17);
}

View File

@@ -1,87 +1,42 @@
{
"@@locale": "de",
"about": "Über",
"aboutThanks": "Vielen Dank an die folgenden Personen, die daran teilgenommen haben.\n",
"acceptBeta": "Akzeptieren Sie Testversion-Updates",
"add": "Neu",
"addAServer": "Server hinzufügen",
"addPrivateKey": "Private key hinzufügen",
"addSystemPrivateKeyTip": "Derzeit haben Sie keinen privaten Schlüssel, fügen Sie den Schlüssel hinzu, der mit dem System geliefert wird (~/.ssh/id_rsa)?",
"added2List": "Zur Aufgabenliste hinzugefügt",
"addr": "Adresse",
"all": "Alle",
"alreadyLastDir": "Bereits im letzten Verzeichnis.",
"alterUrl": "Url ändern",
"askContinue": "{msg}. Weiter?",
"attention": "Achtung",
"authFailTip": "Authentifizierung fehlgeschlagen, bitte überprüfen Sie, ob das Passwort/Schlüssel/Host/Benutzer usw. falsch sind.",
"authRequired": "Autorisierung erforderlich",
"auto": "System folgen",
"autoBackupConflict": "Es kann nur eine automatische Sicherung gleichzeitig aktiviert werden.",
"autoCheckUpdate": "Aktualisierung automatisch prüfen",
"autoConnect": "Automatisch verbinden",
"autoRun": "Automatischer Start",
"autoUpdateHomeWidget": "Home-Widget automatisch aktualisieren",
"backup": "Backup",
"backupTip": "Das Backup wird nur einfach verschlüsselt.\nBitte bewahre die Datei sicher auf.",
"backupVersionNotMatch": "Die Backup-Version stimmt nicht überein.",
"battery": "Batterie",
"bgRun": "Hintergrundaktualisierung",
"bgRunTip": "Dieser Schalter bedeutet nur, dass die App versuchen wird, im Hintergrund zu laufen. Ob sie im Hintergrund laufen kann, hängt davon ab, ob die Berechtigungen aktiviert sind oder nicht. Bei nativem Android deaktivieren Sie bitte \"Batterieoptimierung\" in dieser App, und bei miui ändern Sie bitte die Energiesparrichtlinie auf \"Unbegrenzt\".",
"bioAuth": "Biozertifizierung",
"browser": "Browser",
"bulkImportServers": "Server im Batch importieren",
"bulkImportServersTip": "Sie können das [Format]({url}) hier finden.",
"canPullRefresh": "Danach: herunterziehen zum Aktualisieren",
"cancel": "Abbrechen",
"choose": "Auswählen",
"chooseFontFile": "Schriftart auswählen",
"choosePrivateKey": "Private key auswählen",
"clear": "Entfernen",
"clipboard": "Zwischenablage",
"close": "Schließen",
"cmd": "Command",
"cnKeyboardComp": "Kompatibilität mit chinesischem Android",
"cnKeyboardCompTip": "Wenn das Terminal ein sicheres Tastenfeld öffnet, können Sie es aktivieren.",
"collapseUI": "Zusammenbrechen",
"collapseUITip": "Ob lange Listen in der Benutzeroberfläche standardmäßig eingeklappt werden sollen oder nicht",
"collectUsage": "Nutzungsinformationen sammeln (unabhängig von der Privatsphäre).",
"conn": "Verbindung",
"connected": "in Verbindung gebracht",
"container": "Container",
"containerName": "Container Name",
"containerStatus": "Container Status",
"containerTrySudoTip": "Zum Beispiel: In der App ist der Benutzer auf aaa eingestellt, aber Docker ist unter dem Root-Benutzer installiert. In diesem Fall müssen Sie diese Option aktivieren",
"content": "Inhalt",
"convert": "Konvertieren",
"copy": "Kopieren",
"copyPath": "Pfad kopieren",
"cpuViewAsProgressTip": "Zeigen Sie die Auslastung jedes CPUs in einem Fortschrittsbalken-Stil an (alter Stil)",
"createFile": "Datei erstellen",
"createFolder": "Ordner erstellen",
"cursorType": "Cursor-Typ",
"customCmd": "Benutzerdefinierte Befehle",
"customCmdDocUrl": "https://github.com/lollipopkit/flutter_server_box/wiki#custom-commands",
"customCmdHint": "\"Befehlsname\": \"Befehl\"",
"dark": "Dunkel",
"day": "Tag",
"debug": "Debug",
"decode": "Decode",
"decompress": "Dekomprimieren",
"delete": "Löschen",
"deleteScripts": "Gleichzeitiges Löschen von Server-Skripten",
"deleteServers": "Batch-Löschung von Servern",
"deviceName": "Gerätename",
"dirEmpty": "Stelle sicher, dass der Ordner leer ist.",
"disabled": "Behinderte",
"disconnected": "Disconnected",
"disk": "Festplatte",
"diskIgnorePath": "Pfad für Datenträger ignorieren",
"displayCpuIndex": "Zeigen Sie den CPU-Index an",
"displayName": "Name anzeigen",
"dl2Local": "Datei \"{fileName}\" herunterladen?",
"doc": "Dokumentation",
"dockerEditHost": "DOCKER_HOST bearbeiten",
"dockerEmptyRunningItems": "Es gibt keine laufenden Container.\nDas könnte daran liegen:\n- Der Docker-Installationsbenutzer ist nicht mit dem in der App konfigurierten Benutzernamen identisch.\n- Die Umgebungsvariable DOCKER_HOST wurde nicht korrekt gelesen. Sie können sie ermitteln, indem Sie `echo $DOCKER_HOST` im Terminal ausführen.",
"dockerImagesFmt": "{count} Image(s)",
"dockerNotInstalled": "Docker ist nicht installiert",
@@ -89,36 +44,24 @@
"dockerStatusRunningFmt": "{count} Container aktiv",
"doubleColumnMode": "Doppelspaltiger Modus",
"doubleColumnTip": "Diese Option aktiviert nur die Funktion, ob sie tatsächlich aktiviert werden kann, hängt auch von der Breite des Geräts ab",
"download": "Download",
"edit": "Bearbeiten",
"editVirtKeys": "Virtuelle Tasten bearbeiten",
"editor": "Editor",
"editorHighlightTip": "Die Leistung der aktuellen Codehervorhebung ist schlechter und kann zur Verbesserung optional ausgeschaltet werden.",
"encode": "Encode",
"error": "Fehler",
"exampleName": "Servername",
"envVars": "Umgebungsvariable",
"experimentalFeature": "Experimentelles Feature",
"export": "Export",
"extraArgs": "Extra args",
"failed": "Failed",
"feedback": "Feedback",
"feedbackOnGithub": "Wenn du Fragen hast, stelle diese bitte auf Github.",
"fieldMustNotEmpty": "Die Eingabefelder dürfen nicht leer sein.",
"fileNotExist": "{file} existiert nicht",
"fallbackSshDest": "SSH-Fallback-Ziel",
"fdroidReleaseTip": "Wenn Sie diese App von F-Droid heruntergeladen haben, wird empfohlen, diese Option zu deaktivieren.",
"fileTooLarge": "Datei '{file}' ist zu groß {size}, max {sizeMax}",
"files": "Dateien",
"finished": "fertiggestellt",
"followSystem": "System verfolgen",
"font": "Schriftarten",
"fontSize": "Schriftgröße",
"force": "freiwillig",
"foundNUpdate": "Update {count} gefunden",
"fullScreen": "Vollbildmodus",
"fullScreenJitter": "Jitter im Vollbildmodus",
"fullScreenJitterHelp": "Einbrennen des Bildschirms verhindern",
"fullScreenTip": "Soll der Vollbildmodus aktiviert werden, wenn das Gerät in den Quermodus gedreht wird? Diese Option gilt nur für die Server-Registerkarte.",
"getPushTokenFailed": "Push-Token kann nicht abgerufen werden",
"gettingToken": "Getting token...",
"goBackQ": "Zurückkommen?",
"goto": "Pfad öffnen",
"hideTitleBar": "Titelleiste ausblenden",
@@ -126,37 +69,24 @@
"highlight": "Code highlight",
"homeWidgetUrlConfig": "Home-Widget-Link konfigurieren",
"host": "Host",
"hour": "Stunde",
"httpFailedWithCode": "Anfrage fehlgeschlagen, Statuscode: {code}",
"icloudSynced": "iCloud wird synchronisiert und einige Einstellungen erfordern möglicherweise einen Neustart der App, um wirksam zu werden.",
"ignoreCert": "Zertifikat ignorieren",
"image": "Image",
"imagesList": "Images",
"import": "Importieren",
"inAppUpdate": "Im App aktualisieren? Andernfalls mit einem Browser herunterladen.",
"init": "Initialisieren",
"inner": "Eingebaut",
"inputDomainHere": "Domain eingeben",
"install": "install",
"installDockerWithUrl": "Bitte installiere docker zuerst. https://docs.docker.com/engine/install",
"invalid": "Ungültig",
"invalidJson": "Ungültige JSON",
"invalidVersion": "Ungültige Version",
"invalidVersionHelp": "Bitte stelle sicher, dass Docker korrekt installiert ist oder dass du eine nicht selbstkompilierte Version verwendest. Wenn du die oben genannten Probleme nicht hast, melde bitte einen Fehler auf {url}.",
"isBusy": "Is busy now",
"jumpServer": "Server springen",
"keepForeground": "Stelle sicher, dass die App geöffnet bleibt.",
"keepStatusWhenErr": "Den letzten Serverstatus beibehalten",
"keepStatusWhenErrTip": "Nur im Fehlerfall während der Ausführung des Skripts",
"keyAuth": "Schlüsselauthentifzierung",
"language": "Sprache",
"languageName": "Deutsch",
"lastTry": "Letzter Versuch",
"launchPage": "Startseite",
"letterCache": "Buchstaben-Caching",
"letterCacheTip": "Empfohlen, zu deaktivieren, aber nach dem Deaktivieren können keine CJK-Zeichen eingegeben werden.",
"license": "Lizenzen",
"light": "Hell",
"loadingFiles": "Lädt Dateien...",
"location": "Standort",
"log": "Log",
"loss": "loss",
"madeWithLove": "Erstellt mit ❤️ von {myGithub}",
"manual": "Handbuch",
@@ -164,60 +94,36 @@
"maxRetryCount": "Anzahl an Verbindungsversuchen",
"maxRetryCountEqual0": "Unbegrenzte Verbindungsversuche zum Server",
"min": "min",
"minute": "Minute",
"mission": "Mission",
"more": "Mehr",
"moveOutServerFuncBtnsHelp": "Ein: kann unter jeder Karte auf der Registerkarte \"Server\" angezeigt werden. Aus: kann oben auf der Seite \"Serverdetails\" angezeigt werden.",
"ms": "ms",
"name": "Name",
"needHomeDir": "Wenn Sie ein Synology-Benutzer sind, [sehen Sie hier](https://kb.synology.com/DSM/tutorial/user_enable_home_service). Benutzer anderer Systeme müssen suchen, wie man ein Home-Verzeichnis erstellt.",
"needRestart": "App muss neugestartet werden",
"net": "Netz",
"net": "Netzwerk",
"netViewType": "Netzwerkansicht Typ",
"newContainer": "Neuer Container",
"noClient": "Kein Client",
"noInterface": "Kein Interface",
"noLineChart": "Verwenden Sie keine Liniendiagramme",
"noNotiPerm": "Keine Benachrichtigungsrechte, möglicherweise keine Fortschrittsanzeige beim Herunterladen von App-Updates.",
"noOptions": "Keine Optionen verfügbar",
"noLineChartForCpu": "Verwenden Sie keine Liniendiagramme für CPU",
"noPrivateKeyTip": "Der private Schlüssel existiert nicht, möglicherweise wurde er gelöscht oder es liegt ein Konfigurationsfehler vor.",
"noPromptAgain": "Nicht mehr nachfragen",
"noResult": "Kein Ergebnis",
"noSavedPrivateKey": "Keine gespeicherten Private Keys",
"noSavedSnippet": "Keine gespeicherten Snippets.",
"noServerAvailable": "Kein Server verfügbar.",
"noTask": "Nicht fragen",
"noUpdateAvailable": "Kein Update verfügbar",
"node": "Knoten",
"notAvailable": "Nicht verfügbar",
"notSelected": "Nicht ausgewählt",
"note": "Hinweis",
"nullToken": "Null token",
"ok": "OK",
"onServerDetailPage": "in Detailansicht des Servers",
"onlyOneLine": "Nur als eine Zeile anzeigen (scrollbar)",
"onlyWhenCoreBiggerThan8": "Wirksam nur, wenn die Anzahl der Kerne > 8 ist.",
"open": "Öffnen",
"openLastPath": "Öffnen Sie den letzten Pfad",
"openLastPathTip": "Verschiedene Server haben unterschiedliche Einträge, und der Eintrag ist der Pfad zum Ausgang",
"parseContainerStats": "Den Status der Container-Belegung analysieren",
"parseContainerStatsTip": "Das Analysieren des Belegungsstatus durch Docker ist relativ langsam",
"paste": "Einfügen",
"path": "Pfad",
"percentOfSize": "{percent}% von {size}",
"pickFile": "Datei wählen",
"permission": "Berechtigungen",
"pingAvg": "Avg:",
"pingInputIP": "Bitte gib eine Ziel-IP/Domain ein.",
"pingNoServer": "Kein Server zum Anpingen.\nBitte füge einen Server hinzu.",
"pkg": "Pkg",
"pkgUpgradeTip": "Bitte sichern Sie Ihr System vor dem Update.",
"platformNotSupportUpdate": "Die aktuelle Plattform unterstützt keine In-App-Updates.\nBitte kompiliere vom Quellcode und installiere sie.",
"plugInType": "Einfügetyp",
"plzEnterHost": "Bitte Host eingeben.",
"plzSelectKey": "Wähle einen Key.",
"port": "Port",
"preview": "Vorschau",
"primaryColorSeed": "Farbschema",
"privateKey": "Private Key",
"process": "Prozess",
"pushToken": "Push Token",
@@ -227,15 +133,11 @@
"pwd": "Passwort",
"read": "Lesen",
"reboot": "Neustart",
"rememberChoice": "Auswahl merken",
"rememberPwdInMem": "Passwort im Speicher behalten",
"rememberPwdInMemTip": "Für Container, Aufhängen usw.",
"rememberWindowSize": "Fenstergröße merken",
"remotePath": "Entfernte Pfade",
"rename": "Umbenennen",
"reportBugsOnGithubIssue": "Bitte Bugs auf {url} melden",
"restart": "Neustart",
"restore": "Wiederherstellen",
"restoreSuccess": "Wiederherstellung erfolgreich. App neustarten um Änderungen anzuwenden.",
"result": "Result",
"rotateAngel": "Rotationswinkel",
"route": "Routen",
@@ -250,14 +152,8 @@
"serverDetailOrder": "Reihenfolge der Widgets auf der Detailseite",
"serverFuncBtns": "Server-Funktionsschaltflächen",
"serverOrder": "Server-Bestellung",
"serverTabConnecting": "Verbinden...",
"serverTabEmpty": "Keine Server vorhanden.",
"serverTabFailed": "Fehlgeschlagen",
"serverTabLoading": "Lädt...",
"serverTabPlzSave": "Bitte 'speichere' diesen privaten Schlüssel erneut.",
"serverTabUnkown": "Unbekannter Status",
"setting": "Einstellungen",
"sftpDlPrepare": "Verbindung vorbereiten...",
"sftpEditorTip": "Wenn leer, verwenden Sie den im App integrierten Dateieditor. Wenn ein Wert vorhanden ist, wird der Editor des Remote-Servers verwendet, z.B. `vim` (es wird empfohlen, automatisch gemäß `EDITOR` zu ermitteln).",
"sftpRmrDirSummary": "Verwenden Sie \"rm -r\", um das Verzeichnis in SFTP zu löschen.",
"sftpSSHConnected": "SFTP Verbunden",
"sftpShowFoldersFirst": "Ordner zuerst anzeigen",
@@ -272,11 +168,11 @@
"sshTip": "Diese Funktion befindet sich jetzt in der Experimentierphase.\n\nBitte melde Bugs auf {url} oder mach mit bei der Entwicklung.",
"sshVirtualKeyAutoOff": "Automatische Umschaltung der virtuellen Tasten",
"start": "Start",
"stat": "Statistik",
"stats": "Statistik",
"stop": "Stop",
"stopped": "Ausgelaufen",
"storage": "Speicher",
"success": "Erfolgreich",
"supportFmtArgs": "Die folgenden Formatierungsparameter werden unterstützt:",
"suspend": "Suspend",
"suspendTip": "Die Suspend-Funktion erfordert Root-Rechte und systemd-Unterstützung.",
@@ -292,35 +188,25 @@
"textScaler": "Skalierung der Schriftart",
"textScalerTip": "1.0 => 100% (Originalgröße), funktioniert nur auf der Serverseite Teil der Schrift, nicht empfohlen zu ändern.",
"theme": "Themen",
"themeMode": "Themen-Modus",
"time": "Zeit",
"times": "x",
"total": "Total",
"traffic": "Durchflussmenge",
"trySudo": "Versuche es mit sudo",
"ttl": "ttl",
"ttl": "TTL",
"unknown": "Unbekannt",
"unknownError": "Unbekannter Fehler",
"unkownConvertMode": "Unbekannter Konvertierungsmodus",
"update": "Update",
"updateAll": "Alle aktualisieren",
"updateIntervalEqual0": "Wenn du den Wert 0 einstellst, wird nicht automatisch aktualisiert.\nDer CPU-Status kann nicht berechnet werden.",
"updateServerStatusInterval": "Aktualisierungsintervall des Serverstatus",
"updateTip": "Update: v1.0.{newest}",
"updateTipTooLow": "Aktuelle Version ist zu alt, bitte update auf v1.0.{newest}",
"upload": "Hochladen",
"upsideDown": "Upside Down",
"uptime": "Betriebszeit",
"urlOrJson": "URL oder JSON",
"useCdn": "Verwenden von CDN",
"useCdnTip": "Nicht-chinesischen Benutzern wird die Verwendung eines CDN empfohlen. Möchten Sie es verwenden?",
"useNoPwd": "Es wird kein Passwort verwendet",
"usePodmanByDefault": "Standardmäßige Verwendung von Podman",
"used": "Gebraucht",
"user": "Benutzer",
"versionHaveUpdate": "Gefunden: v1.0.{build}, klicke zum Aktualisieren",
"versionUnknownUpdate": "Aktuell: v1.0.{build}. Klicken Sie hier, um nach Updates zu suchen",
"versionUpdated": "v1.0.{build} ist bereits die neueste Version",
"view": "Ansicht",
"viewErr": "Fehler anzeigen",
"virtKeyHelpClipboard": "In die Zwischenablage kopieren, wenn das ausgewählte Terminal nicht leer ist, andernfalls den Inhalt der Zwischenablage in das Terminal einfügen.",
@@ -331,8 +217,8 @@
"watchNotPaired": "Keine gekoppelte Apple Watch",
"webdavSettingEmpty": "Webdav-Einstellungen sind leer",
"whenOpenApp": "Beim Öffnen der App",
"willTakEeffectImmediately": "Wird sofort angewendet",
"wolTip": "Nach der Konfiguration von WOL (Wake-on-LAN) wird jedes Mal, wenn der Server verbunden wird, eine WOL-Anfrage gesendet.",
"write": "Schreiben",
"writeScriptFailTip": "Das Schreiben des Skripts ist fehlgeschlagen, möglicherweise aufgrund fehlender Berechtigungen oder das Verzeichnis existiert nicht."
"writeScriptFailTip": "Das Schreiben des Skripts ist fehlgeschlagen, möglicherweise aufgrund fehlender Berechtigungen oder das Verzeichnis existiert nicht.",
"writeScriptTip": "Nach der Verbindung mit dem Server wird ein Skript in ~/.config/server_box geschrieben, um den Systemstatus zu überwachen. Sie können den Skriptinhalt überprüfen."
}

View File

@@ -1,87 +1,42 @@
{
"@@locale": "en",
"about": "About",
"aboutThanks": "Thanks to the following people who participated in.",
"acceptBeta": "Accept test version updates",
"add": "Add",
"addAServer": "add a server",
"addPrivateKey": "Add private key",
"addSystemPrivateKeyTip": "Currently don't have any private key, do you add the one that comes with the system (~/.ssh/id_rsa)?",
"acceptBeta": "Accept beta version updates",
"addSystemPrivateKeyTip": "Currently private keys don't exist, do you want to add the one that comes with the system (~/.ssh/id_rsa)?",
"added2List": "Added to task list",
"addr": "Address",
"all": "All",
"alreadyLastDir": "Already in last directory.",
"alterUrl": "Alter url",
"askContinue": "{msg}. Continue?",
"attention": "Attention",
"authFailTip": "Authentication failed, please check if the password/key/host/user, etc., are incorrect.",
"authRequired": "Auth required",
"auto": "Auto",
"authFailTip": "Authentication failed, please check whether credentials are correct",
"autoBackupConflict": "Only one automatic backup can be turned on at the same time.",
"autoCheckUpdate": "Auto check update",
"autoConnect": "Auto connect",
"autoRun": "Automatic Run",
"autoUpdateHomeWidget": "Auto update home widget",
"backup": "Backup",
"backupTip": "The exported data is simply encrypted. \nPlease keep it safe.",
"autoRun": "Auto run",
"autoUpdateHomeWidget": "Automatic home widget update",
"backupTip": "The exported data is weakly encrypted. \nPlease keep it safe.",
"backupVersionNotMatch": "Backup version is not match.",
"battery": "Battery",
"bgRun": "Run in backgroud",
"bgRunTip": "This switch only means the program will try to run in the background, whether it can run in the background depends on whether the permission is enabled or not. For native Android, please disable \"Battery Optimization\" in this app, and for miui, please change the power saving policy to \"Unlimited\".",
"bioAuth": "Biometric auth",
"browser": "Browser",
"bulkImportServers": "Batch import servers",
"bulkImportServersTip": "You can find the [format]({url}) here.",
"canPullRefresh": "You can pull to refresh.",
"cancel": "Cancel",
"choose": "Choose",
"chooseFontFile": "Choose a font file",
"choosePrivateKey": "Choose private key",
"clear": "Clear",
"clipboard": "Clipboard",
"close": "Close",
"bgRun": "Run in background",
"bgRunTip": "This switch only means the program will try to run in the background. Whether it can run in the background depends on whether the permission is enabled or not. For AOSP-based Android ROMs, please disable \"Battery Optimization\" in this app. For MIUI / HyperOS, please change the power saving policy to \"Unlimited\".",
"cmd": "Command",
"cnKeyboardComp": "Compatibility with Chinese Android",
"cnKeyboardCompTip": "If the terminal pops up a secure keyboard, you can enable it.",
"collapseUI": "Collapse",
"collapseUITip": "Whether to collapse long lists present in the UI by default",
"collectUsage": "Collect usage information (unrelated to privacy).",
"conn": "Connection",
"connected": "Connected",
"container": "Container",
"containerName": "Container name",
"containerStatus": "Container status",
"containerTrySudoTip": "For example: In the app, the user is set to aaa, but Docker is installed under the root user. In this case, you need to enable this option.",
"content": "Content",
"convert": "Convert",
"copy": "Copy",
"copyPath": "Copy path",
"cpuViewAsProgressTip": "Display the usage rate of each CPU in a progress bar style (old style)",
"createFile": "Create file",
"createFolder": "Create folder",
"cpuViewAsProgressTip": "Display the usage of each CPU in a progress bar style (old style)",
"cursorType": "Cursor type",
"customCmd": "Custom commands",
"customCmdDocUrl": "https://github.com/lollipopkit/flutter_server_box/wiki#custom-commands",
"customCmdHint": "\"Command Name\": \"Command\"",
"dark": "Dark",
"day": "Day",
"debug": "Debug",
"decode": "Decode",
"decompress": "Decompress",
"delete": "Delete",
"deleteScripts": "Delete server scripts at the same time",
"deleteServers": "Batch delete servers",
"deviceName": "Device name",
"dirEmpty": "Make sure dir is empty.",
"disabled": "Disabled",
"dirEmpty": "Make sure the folder is empty.",
"disconnected": "Disconnected",
"disk": "Disk",
"diskIgnorePath": "Ignore path for disk",
"displayCpuIndex": "Display CPU index",
"displayName": "Display name",
"dl2Local": "Download {fileName} to local?",
"doc": "Documentation",
"dockerEditHost": "Edit DOCKER_HOST",
"dockerEmptyRunningItems": "There are no running containers.\nThis could be because:\n- The Docker installation user is not the same as the username configured within the App.\n- The environment variable DOCKER_HOST was not read correctly. You can get it by running `echo $DOCKER_HOST` in the terminal.",
"dockerImagesFmt": "{count} images",
"dockerNotInstalled": "Docker not installed",
@@ -89,135 +44,86 @@
"dockerStatusRunningFmt": "{count} container running.",
"doubleColumnMode": "Double column mode",
"doubleColumnTip": "This option only enables the feature, whether it can actually be enabled depends on the width of the device",
"download": "Download",
"edit": "Edit",
"editVirtKeys": "Edit virtual keys",
"editor": "Editor",
"editorHighlightTip": "The current code highlighting performance is worse and can be optionally turned off to improve.",
"editorHighlightTip": "The current code highlighting performance is not ideal and can be optionally turned off to improve.",
"encode": "Encode",
"error": "Error",
"exampleName": "Example name",
"envVars": "Environment variable",
"experimentalFeature": "Experimental feature",
"export": "Export",
"extraArgs": "Extra args",
"failed": "Failed",
"feedback": "Feedback",
"feedbackOnGithub": "If you have any questions, please feedback on Github.",
"fieldMustNotEmpty": "These fields must not be empty.",
"fileNotExist": "{file} not exist",
"extraArgs": "Extra arguments",
"fallbackSshDest": "Fallback SSH destination",
"fdroidReleaseTip": "If you downloaded this app from F-Droid, it is recommended to turn off this option.",
"fileTooLarge": "File '{file}' too large {size}, max {sizeMax}",
"files": "Files",
"finished": "Finished",
"followSystem": "Follow system",
"font": "Font",
"fontSize": "Font size",
"force": "Force",
"foundNUpdate": "Found {count} update",
"fullScreen": "Full screen mode",
"fullScreenJitter": "Full screen jitter",
"fullScreenJitterHelp": "To avoid screen burn-in",
"fullScreenTip": "Should full-screen mode be enabled when the device is rotated to landscape mode? This option only applies to the server tab.",
"getPushTokenFailed": "Can't fetch push token",
"gettingToken": "Getting token...",
"goBackQ": "Go back?",
"goto": "Go to",
"hideTitleBar": "Hide title bar",
"hideTitleBarTip": "After turning it on, please hold down the three buttons in the top right corner to drag.",
"highlight": "Code highlight",
"highlight": "Code highlighting",
"homeWidgetUrlConfig": "Config home widget url",
"host": "Host",
"hour": "Hour",
"httpFailedWithCode": "request failed, status code: {code}",
"icloudSynced": "iCloud wird synchronisiert und einige Einstellungen erfordern möglicherweise einen Neustart der App, um wirksam zu werden.",
"ignoreCert": "Ignore certificate",
"image": "Image",
"imagesList": "Images list",
"import": "Import",
"inAppUpdate": "Update within the app? Otherwise, download using a browser.",
"init": "Initialize",
"inner": "Inner",
"inputDomainHere": "Input Domain here",
"install": "install",
"installDockerWithUrl": "Please https://docs.docker.com/engine/install docker first.",
"invalid": "Invalid",
"invalidJson": "Invalid JSON",
"invalidVersion": "Invalid version",
"invalidVersionHelp": "Please make sure that docker is installed correctly, or that you are using a non-self-compiled version. If you don't have the above issues, please submit an issue on {url}.",
"isBusy": "Is busy now",
"jumpServer": "Jump server",
"keepForeground": "Keep app foreground!",
"keepStatusWhenErr": "Preserve the last server state",
"keepStatusWhenErrTip": "Only in the event of an error during script execution",
"keyAuth": "Key Auth",
"language": "Language",
"languageName": "English",
"lastTry": "Last try",
"launchPage": "Launch page",
"letterCache": "Letter caching",
"letterCacheTip": "Recommended to disable, but after disabling, it will be impossible to input CJK characters.",
"license": "License",
"light": "Light",
"loadingFiles": "Loading files...",
"location": "Location",
"log": "Log",
"loss": "loss",
"madeWithLove": "Made with ❤️ by {myGithub}",
"manual": "Manual",
"max": "max",
"maxRetryCount": "Number of server reconnection",
"maxRetryCount": "Number of server reconnections",
"maxRetryCountEqual0": "Will retry again and again.",
"min": "min",
"minute": "Minute",
"mission": "Mission",
"more": "More",
"moveOutServerFuncBtnsHelp": "On: can be displayed below each card on the Server Tab page. Off: can be displayed at the top of the Server Details page.",
"ms": "ms",
"name": "Name",
"needHomeDir": "If you are a Synology user, [see here](https://kb.synology.com/DSM/tutorial/user_enable_home_service). Users of other systems need to search for how to create a home directory.",
"needRestart": "Need to restart app",
"net": "Net",
"netViewType": "Net view type",
"needRestart": "App needs to be restarted",
"net": "Network",
"netViewType": "Network view type",
"newContainer": "New container",
"noClient": "No client",
"noInterface": "No interface",
"noLineChart": "Do not use line charts",
"noNotiPerm": "No notification permissions, possibly no progress indication when downloading app updates.",
"noOptions": "No options",
"noLineChartForCpu": "Do not use line charts for CPU",
"noPrivateKeyTip": "The private key does not exist, it may have been deleted or there is a configuration error.",
"noPromptAgain": "Do not prompt again",
"noResult": "No result",
"noSavedPrivateKey": "No saved private keys.",
"noSavedSnippet": "No saved snippets.",
"noServerAvailable": "No server available.",
"noTask": "No task",
"noUpdateAvailable": "No update available",
"node": "Node",
"notAvailable": "Unavailable",
"notSelected": "Not selected",
"note": "Note",
"nullToken": "Null token",
"ok": "OK",
"onServerDetailPage": "On server detail page",
"onlyOneLine": "Only display as one line (scrollable)",
"onlyWhenCoreBiggerThan8": "Works only when the number of cores > 8",
"open": "Open",
"onlyWhenCoreBiggerThan8": "Works only when the number of cores is greater than 8",
"openLastPath": "Open the last path",
"openLastPathTip": "Different servers will have different logs, and the log is the path to the exit",
"parseContainerStats": "Parse the container occupancy status",
"parseContainerStatsTip": "Docker parsing the occupancy status is relatively slow.",
"paste": "Paste",
"path": "Path",
"parseContainerStatsTip": "Parsing the occupancy status of Docker is relatively slow.",
"percentOfSize": "{percent}% of {size}",
"pickFile": "Pick file",
"permission": "Permissions",
"pingAvg": "Avg:",
"pingInputIP": "Please input a target IP / domain.",
"pingNoServer": "No server to ping.\nPlease add a server in server tab.",
"pkg": "Pkg",
"pkgUpgradeTip": "Please backup your system before updating.",
"platformNotSupportUpdate": "Current platform does not support in app update.\nPlease build from source and install it.",
"plugInType": "Insertion Type",
"plzEnterHost": "Please enter host.",
"plzSelectKey": "Please select a key.",
"port": "Port",
"preview": "Preview",
"primaryColorSeed": "Primary color seed",
"privateKey": "Private Key",
"process": "Process",
"pushToken": "Push token",
@@ -227,15 +133,11 @@
"pwd": "Password",
"read": "Read",
"reboot": "Reboot",
"rememberChoice": "Remember the selection",
"rememberPwdInMem": "Remember password in memory",
"rememberPwdInMemTip": "Used for containers, suspending, etc.",
"rememberWindowSize": "Remember window size",
"remotePath": "Remote path",
"rename": "Rename",
"reportBugsOnGithubIssue": "Please report bugs on {url}",
"restart": "Restart",
"restore": "Restore",
"restoreSuccess": "Restore success. Restart app to apply.",
"result": "Result",
"rotateAngel": "Rotation angle",
"route": "Routing",
@@ -248,16 +150,10 @@
"sequence": "Sequence",
"server": "Server",
"serverDetailOrder": "Detail page widget order",
"serverFuncBtns": "Server func buttons",
"serverFuncBtns": "Server function buttons",
"serverOrder": "Server order",
"serverTabConnecting": "Connecting...",
"serverTabEmpty": "There is no server.\nClick the fab to add one.",
"serverTabFailed": "Failed",
"serverTabLoading": "Loading...",
"serverTabPlzSave": "Please 'save' this private key again.",
"serverTabUnkown": "Unknown state",
"setting": "Settings",
"sftpDlPrepare": "Preparing to connect...",
"sftpEditorTip": "If empty, use the built-in file editor of the app. If a value is present, use the remote servers editor, e.g., `vim` (recommended to automatically detect according to `EDITOR`).",
"sftpRmrDirSummary": "Use `rm -r` to delete a folder in SFTP.",
"sftpSSHConnected": "SFTP Connected",
"sftpShowFoldersFirst": "Display folders first",
@@ -272,14 +168,14 @@
"sshTip": "This function is now in the experimental stage.\n\nPlease report bugs on {url} or join our development.",
"sshVirtualKeyAutoOff": "Auto switching of virtual keys",
"start": "Start",
"stats": "Stats",
"stat": "Statistics",
"stats": "Statistics",
"stop": "Stop",
"stopped": "Stopped",
"storage": "Storage",
"success": "Success",
"supportFmtArgs": "The following formatting parameters are supported:",
"suspend": "Suspend",
"suspendTip": "The suspend function requires root privileges and systemd support.",
"suspendTip": "The suspend function requires root permission and systemd support.",
"switchTo": "Switch to {val}",
"sync": "Sync",
"syncTip": "A restart may be required for some changes to take effect.",
@@ -292,47 +188,37 @@
"textScaler": "Text scaler",
"textScalerTip": "1.0 => 100% (original size), only works on server page part of the font, not recommended to change.",
"theme": "Theme",
"themeMode": "Theme mode",
"time": "Time",
"times": "Times",
"total": "Total",
"traffic": "Traffic",
"trySudo": "Try using sudo",
"ttl": "ttl",
"ttl": "TTL",
"unknown": "Unknown",
"unknownError": "Unknown error",
"unkownConvertMode": "Unknown convert mode",
"unkownConvertMode": "Unknown conversion mode",
"update": "Update",
"updateAll": "Update all",
"updateIntervalEqual0": "You set to 0, will not update automatically.\nCan't calculate CPU status.",
"updateServerStatusInterval": "Server status update interval",
"updateTip": "Update: v1.0.{newest}",
"updateTipTooLow": "Current version is too low, please update to v1.0.{newest}",
"upload": "Upload",
"upsideDown": "Upside Down",
"uptime": "Uptime",
"urlOrJson": "URL or JSON",
"useCdn": "Using CDN",
"useCdnTip": "Non-Chinese users are recommended to use CDN. Would you like to use it?",
"useNoPwd": "No password will be used",
"usePodmanByDefault": "Defaulting to Podman",
"usePodmanByDefault": "Use Podman by default",
"used": "Used",
"user": "User",
"versionHaveUpdate": "Found: v1.0.{build}, click to update",
"versionUnknownUpdate": "Current: v1.0.{build}, click to check updates",
"versionUpdated": "Current: v1.0.{build}, is up to date",
"view": "View",
"viewErr": "See error",
"virtKeyHelpClipboard": "Copy to the clipboard if terminal selected is not empty, otherwise paste the contents of the clipboard to the terminal.",
"virtKeyHelpClipboard": "Copy to the clipboard if the selected terminal is not empty, otherwise paste the content of the clipboard to the terminal.",
"virtKeyHelpIME": "Turn on/off the keyboard",
"virtKeyHelpSFTP": "Open current directory in SFTP.",
"waitConnection": "Please wait for the connection to be established.",
"wakeLock": "Keep awake",
"watchNotPaired": "No paired Apple Watch",
"webdavSettingEmpty": "Webdav setting is empty",
"webdavSettingEmpty": "WebDav setting is empty",
"whenOpenApp": "When opening the app",
"willTakEeffectImmediately": "Will take effect immediately",
"wolTip": "After configuring WOL (Wake-on-LAN), a WOL request is sent each time the server is connected.",
"write": "Write",
"writeScriptFailTip": "Writing to the script failed, possibly due to lack of permissions or the directory does not exist."
"writeScriptFailTip": "Writing to the script failed, possibly due to lack of permissions or the directory does not exist.",
"writeScriptTip": "After connecting to the server, a script will be written to ~/.config/server_box to monitor the system status. You can review the script content."
}

View File

@@ -1,87 +1,42 @@
{
"@@locale": "es",
"about": "Acerca de",
"aboutThanks": "Gracias a los siguientes participantes.",
"acceptBeta": "Aceptar actualizaciones de la versión de prueba",
"add": "Añadir",
"addAServer": "Agregar un servidor",
"addPrivateKey": "Agregar una llave privada",
"addSystemPrivateKeyTip": "Actualmente no hay ninguna llave privada, ¿quieres agregar la que viene por defecto en el sistema (~/.ssh/id_rsa)?",
"added2List": "Añadido a la lista de tareas",
"addr": "Dirección",
"all": "Todos",
"alreadyLastDir": "Ya estás en el directorio superior",
"alterUrl": "URL alternativa",
"askContinue": "{msg}, ¿continuar?",
"attention": "Atención",
"authFailTip": "La autenticación ha fallado, por favor verifica si la contraseña/llave/host/usuario, etc., son incorrectos.",
"authRequired": "Autenticación requerida",
"auto": "Automático",
"autoBackupConflict": "Solo se puede activar una copia de seguridad automática a la vez",
"autoCheckUpdate": "Verificación automática de actualizaciones",
"autoConnect": "Conexión automática",
"autoRun": "Ejecución automática",
"autoUpdateHomeWidget": "Actualizar automáticamente el widget del escritorio",
"backup": "Respaldo",
"backupTip": "Los datos exportados solo están encriptados de manera básica, por favor guárdalos en un lugar seguro.",
"backupVersionNotMatch": "La versión de la copia de seguridad no coincide, no se puede restaurar",
"battery": "Batería",
"bgRun": "Ejecución en segundo plano",
"bgRunTip": "Este interruptor solo indica que la aplicación intentará correr en segundo plano, si puede hacerlo o no depende de si tiene el permiso correspondiente. En Android puro, por favor desactiva la “optimización de batería” para esta app, en MIUI por favor cambia la estrategia de ahorro de energía a “Sin restricciones”.",
"bioAuth": "Autenticación biométrica",
"browser": "Navegador",
"bulkImportServers": "Importar servidores en masa",
"bulkImportServersTip": "Puede encontrar el [formato]]({url}) aquí.",
"canPullRefresh": "Se puede deslizar hacia abajo para refrescar",
"cancel": "Cancelar",
"choose": "Elegir",
"chooseFontFile": "Seleccionar archivo de fuente",
"choosePrivateKey": "Elegir llave privada",
"clear": "Limpiar",
"clipboard": "Portapapeles",
"close": "Cerrar",
"cmd": "Comando",
"cnKeyboardComp": "Compatibilidad con Android chino",
"cnKeyboardCompTip": "Si el terminal muestra un teclado seguro, puedes activarlo.",
"collapseUI": "Colapsar",
"collapseUITip": "¿Colapsar por defecto las listas largas en la UI?",
"collectUsage": "Recopilar información de uso (no relacionada con la privacidad).",
"conn": "Conectar",
"connected": "Conectado",
"container": "Contenedor",
"containerName": "Nombre del contenedor",
"containerStatus": "Estado del contenedor",
"containerTrySudoTip": "Por ejemplo: si configuras el usuario dentro de la app como aaa, pero Docker está instalado bajo el usuario root, entonces necesitarás habilitar esta opción",
"content": "Contenido",
"convert": "Convertir",
"copy": "Copiar",
"copyPath": "Copiar ruta",
"cpuViewAsProgressTip": "Muestre la tasa de uso de cada CPU en estilo de barra de progreso (estilo antiguo)",
"createFile": "Crear archivo",
"createFolder": "Crear carpeta",
"cursorType": "Tipo de cursor",
"customCmd": "Comandos personalizados",
"customCmdDocUrl": "https://github.com/lollipopkit/flutter_server_box/wiki#custom-commands",
"customCmdHint": "\"Nombre del comando\": \"Comando\"",
"dark": "Oscuro",
"day": "Día",
"debug": "Depurar",
"decode": "Decodificar",
"decompress": "Descomprimir",
"delete": "Eliminar",
"deleteScripts": "Eliminar scripts del servidor simultáneamente",
"deleteServers": "Eliminar servidores en lote",
"deviceName": "Nombre del dispositivo",
"dirEmpty": "Asegúrate de que el directorio esté vacío",
"disabled": "Deshabilitado",
"disconnected": "Desconectado",
"disk": "Disco",
"diskIgnorePath": "Rutas de disco ignoradas",
"displayCpuIndex": "Muestre el índice de CPU",
"displayName": "Nombre a mostrar",
"dl2Local": "¿Descargar {fileName} a local?",
"doc": "Documentación",
"dockerEditHost": "Editar DOCKER_HOST",
"dockerEmptyRunningItems": "No hay contenedores en ejecución.\nEsto podría deberse a que:\n- El usuario con el que se instaló Docker es diferente al configurado en la app\n- La variable de entorno DOCKER_HOST no se ha leído correctamente. Puedes obtenerla ejecutando `echo $DOCKER_HOST` en el terminal.",
"dockerImagesFmt": "Total de {count} imágenes",
"dockerNotInstalled": "Docker no está instalado",
@@ -89,36 +44,24 @@
"dockerStatusRunningFmt": "{count} contenedores en ejecución",
"doubleColumnMode": "Modo de doble columna",
"doubleColumnTip": "Esta opción solo habilita la función, si se puede activar o no depende del ancho del dispositivo",
"download": "Descargar",
"edit": "Editar",
"editVirtKeys": "Editar teclas virtuales",
"editor": "Editor",
"editorHighlightTip": "El rendimiento del resaltado de código es bastante pobre actualmente, puedes elegir desactivarlo para mejorar.",
"encode": "Codificar",
"error": "Error",
"exampleName": "Ejemplo de nombre",
"envVars": "Variable de entorno",
"experimentalFeature": "Función experimental",
"export": "Exportar",
"extraArgs": "Argumentos extra",
"failed": "Fallido",
"feedback": "Retroalimentación",
"feedbackOnGithub": "Si tienes algún problema, por favor informa en GitHub",
"fieldMustNotEmpty": "Estos campos no pueden estar vacíos.",
"fileNotExist": "{file} no existe",
"fallbackSshDest": "Destino SSH alternativo",
"fdroidReleaseTip": "Si descargaste esta aplicación desde F-Droid, se recomienda desactivar esta opción.",
"fileTooLarge": "El archivo '{file}' es demasiado grande '{size}', supera el {sizeMax}",
"files": "Archivos",
"finished": "Finalizado",
"followSystem": "Seguir al sistema",
"font": "Fuente",
"fontSize": "Tamaño de fuente",
"force": "Forzar",
"foundNUpdate": "Encontradas {count} actualizaciones",
"fullScreen": "Modo pantalla completa",
"fullScreenJitter": "Temblores en modo pantalla completa",
"fullScreenJitterHelp": "Prevención de quemaduras de pantalla",
"fullScreenTip": "¿Debe habilitarse el modo de pantalla completa cuando el dispositivo se rote al modo horizontal? Esta opción solo se aplica a la pestaña del servidor.",
"getPushTokenFailed": "No se pudo obtener el token de notificación",
"gettingToken": "Obteniendo Token...",
"goBackQ": "¿Regresar?",
"goto": "Ir a",
"hideTitleBar": "Ocultar barra de título",
@@ -126,37 +69,24 @@
"highlight": "Resaltar código",
"homeWidgetUrlConfig": "Configuración de URL del widget de inicio",
"host": "Anfitrión",
"hour": "Hora",
"httpFailedWithCode": "Fallo en la solicitud, código de estado: {code}",
"icloudSynced": "iCloud sincronizado, algunos ajustes pueden requerir reiniciar para tomar efecto.",
"ignoreCert": "Ignorar certificado",
"image": "Imagen",
"imagesList": "Lista de imágenes",
"import": "Importar",
"inAppUpdate": "¿Actualizar dentro de la app? De lo contrario, descargar usando un navegador.",
"init": "Inicializar",
"inner": "Interno",
"inputDomainHere": "Introduce el dominio aquí",
"install": "Instalar",
"installDockerWithUrl": "Por favor instala Docker primero desde https://docs.docker.com/engine/install",
"invalid": "Inválido",
"invalidJson": "JSON inválido",
"invalidVersion": "Versión no soportada",
"invalidVersionHelp": "Por favor asegúrate de haber instalado Docker correctamente o que no estés usando una versión compilada por ti mismo. Si no tienes estos problemas, informa en {url}.",
"isBusy": "Está ocupado",
"jumpServer": "Servidor de salto",
"keepForeground": "¡Por favor, mantén la app en primer plano!",
"keepStatusWhenErr": "Mantener el estado anterior del servidor",
"keepStatusWhenErrTip": "Solo aplica cuando hay errores al ejecutar scripts",
"keyAuth": "Autenticación con llave",
"language": "Idioma",
"languageName": "Español",
"lastTry": "Último intento",
"launchPage": "Página de lanzamiento",
"letterCache": "Caché de letras",
"letterCacheTip": "Recomendado desactivar, pero después de desactivarlo, no se podrán ingresar caracteres CJK.",
"license": "Licencia de código abierto",
"light": "Claro",
"loadingFiles": "Cargando directorio...",
"location": "Ubicación",
"log": "Registro",
"loss": "Tasa de pérdida",
"madeWithLove": "Hecho con ❤️ por {myGithub}",
"manual": "Manual",
@@ -164,60 +94,36 @@
"maxRetryCount": "Número máximo de reintentos de conexión al servidor",
"maxRetryCountEqual0": "Reintentará infinitamente",
"min": "Mínimo",
"minute": "Minuto",
"mission": "Misión",
"more": "Más",
"moveOutServerFuncBtnsHelp": "Activado: se mostrará debajo de cada tarjeta en la página de servidores. Desactivado: se mostrará en la parte superior de los detalles del servidor.",
"ms": "milisegundos",
"name": "Nombre",
"needHomeDir": "Si eres usuario de Synology, [consulta aquí](https://kb.synology.com/DSM/tutorial/user_enable_home_service). Los usuarios de otros sistemas deben buscar cómo crear un directorio home.",
"needRestart": "Necesita reiniciar la app",
"net": "Red",
"netViewType": "Tipo de vista de red",
"newContainer": "Crear contenedor nuevo",
"noClient": "No hay conexión SSH",
"noInterface": "No hay interfaz disponible",
"noLineChart": "No utilice gráficos de líneas",
"noNotiPerm": "Sin permisos de notificación, posiblemente sin indicación de progreso al descargar actualizaciones de la aplicación.",
"noOptions": "Sin opciones disponibles",
"noLineChartForCpu": "No utilice gráficos lineales para la CPU",
"noPrivateKeyTip": "La clave privada no existe, puede haber sido eliminada o hay un error de configuración.",
"noPromptAgain": "No volver a preguntar",
"noResult": "Sin resultados",
"noSavedPrivateKey": "No hay llaves privadas guardadas.",
"noSavedSnippet": "No hay fragmentos de código guardados.",
"noServerAvailable": "No hay servidores disponibles.",
"noTask": "Sin tareas",
"noUpdateAvailable": "No hay actualizaciones disponibles",
"node": "Nodo",
"notAvailable": "No disponible",
"notSelected": "No seleccionado",
"note": "Nota",
"nullToken": "Token nulo",
"ok": "Ok",
"onServerDetailPage": "En la página de detalles del servidor",
"onlyOneLine": "Mostrar solo en una línea (desplazable)",
"onlyWhenCoreBiggerThan8": "Efectivo solo cuando el número de núcleos > 8",
"open": "Abrir",
"openLastPath": "Abrir el último camino",
"openLastPathTip": "Los diferentes servidores tendrán diferentes registros, y lo que se registra es la ruta de salida",
"parseContainerStats": "Analizar estado de uso del contenedor",
"parseContainerStatsTip": "El análisis del estado de uso de Docker es bastante lento",
"paste": "Pegar",
"path": "Ruta",
"percentOfSize": "El {percent}% de {size}",
"pickFile": "Seleccionar archivo",
"permission": "Permisos",
"pingAvg": "Promedio:",
"pingInputIP": "Por favor, introduce la IP de destino o el dominio",
"pingNoServer": "No hay servidores disponibles para hacer Ping\nPor favor, añade un servidor en la pestaña de servidores y vuelve a intentarlo",
"pkg": "Gestión de paquetes",
"pkgUpgradeTip": "Realice una copia de seguridad de su sistema antes de actualizar.",
"platformNotSupportUpdate": "La plataforma actual no soporta actualizaciones, por favor instala manualmente la última versión del código fuente",
"plugInType": "Tipo de inserción",
"plzEnterHost": "Por favor, introduce el host",
"plzSelectKey": "Por favor, selecciona una llave privada",
"port": "Puerto",
"preview": "Vista previa",
"primaryColorSeed": "Semilla de color primario",
"privateKey": "Llave privada",
"process": "Proceso",
"pushToken": "Token de notificaciones",
@@ -227,15 +133,11 @@
"pwd": "Contraseña",
"read": "Leer",
"reboot": "Reiniciar",
"rememberChoice": "Recordar la selección",
"rememberPwdInMem": "Recordar contraseña en la memoria",
"rememberPwdInMemTip": "Utilizado para contenedores, suspensión, etc.",
"rememberWindowSize": "Recordar el tamaño de la ventana",
"remotePath": "Ruta remota",
"rename": "Renombrar",
"reportBugsOnGithubIssue": "Por favor, informa los problemas en {url}",
"restart": "Reiniciar",
"restore": "Restaurar",
"restoreSuccess": "Restauración exitosa, necesitas reiniciar la App para aplicar cambios",
"result": "Resultado",
"rotateAngel": "Ángulo de rotación",
"route": "Enrutamiento",
@@ -250,14 +152,8 @@
"serverDetailOrder": "Orden de los componentes en la página de detalles del servidor",
"serverFuncBtns": "Botones de función del servidor",
"serverOrder": "Orden del servidor",
"serverTabConnecting": "Conectando...",
"serverTabEmpty": "No hay servidores por ahora.\nHaz clic en el botón de la esquina inferior derecha para añadir uno.",
"serverTabFailed": "Fallo",
"serverTabLoading": "Cargando...",
"serverTabPlzSave": "Por favor, guarda la llave privada nuevamente",
"serverTabUnkown": "Estado desconocido",
"setting": "Configuración",
"sftpDlPrepare": "Preparando para conectar al servidor...",
"sftpEditorTip": "Si está vacío, use el editor de archivos incorporado de la aplicación. Si hay un valor, use el editor del servidor remoto, por ejemplo, `vim` (se recomienda detectar automáticamente según `EDITOR`).",
"sftpRmrDirSummary": "Usar `rm -r` en SFTP para eliminar directorios",
"sftpSSHConnected": "SFTP conectado...",
"sftpShowFoldersFirst": "Mostrar carpetas primero",
@@ -272,11 +168,11 @@
"sshTip": "Esta función está en fase de pruebas.\n\nPor favor, informa los problemas en {url}, o únete a nuestro desarrollo.",
"sshVirtualKeyAutoOff": "Desactivación automática de teclas virtuales",
"start": "Iniciar",
"stat": "Estadísticas",
"stats": "Estadísticas",
"stop": "Detener",
"stopped": "Detenido",
"storage": "Almacenamiento",
"success": "Éxito",
"supportFmtArgs": "Soporta los siguientes argumentos de formato:",
"suspend": "Suspender",
"suspendTip": "La función de suspender necesita permisos de root y soporte de systemd.",
@@ -292,35 +188,25 @@
"textScaler": "Escalar texto",
"textScalerTip": "1.0 => 100% (tamaño original), solo afecta a ciertas fuentes en la página del servidor, no se recomienda modificar.",
"theme": "Tema",
"themeMode": "Modo de tema",
"time": "Tiempo",
"times": "Veces",
"total": "Total",
"traffic": "Tráfico",
"trySudo": "Intentar con sudo",
"ttl": "Tiempo de vida (TTL)",
"ttl": "TTL",
"unknown": "Desconocido",
"unknownError": "Error desconocido",
"unkownConvertMode": "Modo de conversión desconocido",
"update": "Actualizar",
"updateAll": "Actualizar todo",
"updateIntervalEqual0": "Si configuras esto a 0, el estado del servidor no se refrescará automáticamente.\nY no se podrá calcular el uso de CPU.",
"updateServerStatusInterval": "Intervalo de actualización del estado del servidor",
"updateTip": "Nueva versión: v1.0.{newest}",
"updateTipTooLow": "La versión actual es demasiado baja, por favor actualiza a v1.0.{newest}",
"upload": "Subir",
"upsideDown": "Invertir arriba por abajo",
"uptime": "Tiempo de actividad",
"urlOrJson": "URL o JSON",
"useCdn": "Usando CDN",
"useCdnTip": "Se recomienda a los usuarios no chinos utilizar CDN. ¿Le gustaría utilizarlo?",
"useNoPwd": "Se usará sin contraseña",
"usePodmanByDefault": "Usar Podman por defecto",
"used": "Usado",
"user": "Usuario",
"versionHaveUpdate": "Nueva versión encontrada: v1.0.{build}, haz clic para actualizar",
"versionUnknownUpdate": "Actual: v1.0.{build}, haz clic para verificar actualizaciones",
"versionUpdated": "Actual: v1.0.{build}, ya estás en la última versión",
"view": "Vista",
"viewErr": "Ver error",
"virtKeyHelpClipboard": "Si el terminal tiene caracteres seleccionados, entonces copiará los caracteres seleccionados al portapapeles, de lo contrario, pegará el contenido del portapapeles al terminal.",
@@ -331,8 +217,8 @@
"watchNotPaired": "No hay un Apple Watch emparejado",
"webdavSettingEmpty": "La configuración de Webdav está vacía",
"whenOpenApp": "Al abrir la App",
"willTakEeffectImmediately": "Los cambios tendrán efecto inmediatamente",
"wolTip": "Después de configurar WOL (Wake-on-LAN), se envía una solicitud de WOL cada vez que se conecta el servidor.",
"write": "Escribir",
"writeScriptFailTip": "La escritura en el script falló, posiblemente por falta de permisos o porque el directorio no existe."
"writeScriptFailTip": "La escritura en el script falló, posiblemente por falta de permisos o porque el directorio no existe.",
"writeScriptTip": "Después de conectarse al servidor, se escribirá un script en ~/.config/server_box para monitorear el estado del sistema. Puedes revisar el contenido del script."
}

View File

@@ -1,87 +1,42 @@
{
"@@locale": "fr",
"about": "À propos",
"aboutThanks": "Merci aux personnes suivantes qui ont participé.",
"acceptBeta": "Accepter les mises à jour de la version de test",
"add": "Ajouter",
"addAServer": "Ajouter un serveur",
"addPrivateKey": "Ajouter une clé privée",
"addSystemPrivateKeyTip": "Actuellement, vous n'avez aucune clé privée. Souhaitez-vous ajouter celle qui vient avec le système (~/.ssh/id_rsa) ?",
"added2List": "Ajouté à la liste des tâches",
"addr": "Adresse",
"all": "Tous",
"alreadyLastDir": "Déjà dans le dernier répertoire.",
"alterUrl": "Modifier l'URL",
"askContinue": "{msg}. Continuer ?",
"attention": "Attention",
"authFailTip": "Échec de l'authentification. Veuillez vérifier si le mot de passe/clé/hôte/utilisateur, etc., est incorrect.",
"authRequired": "Authentification requise",
"auto": "Automatique",
"autoBackupConflict": "Un seul sauvegarde automatique peut être activé en même temps.",
"autoCheckUpdate": "Vérification automatique des mises à jour",
"autoConnect": "Connexion automatique",
"autoRun": "Exécution automatique",
"autoUpdateHomeWidget": "Mise à jour automatique du widget d'accueil",
"backup": "Sauvegarde",
"backupTip": "Les données exportées sont simplement chiffrées. \nVeuillez les garder en sécurité.",
"backupVersionNotMatch": "La version de sauvegarde ne correspond pas.",
"battery": "Batterie",
"bgRun": "Exécution en arrière-plan",
"bgRunTip": "Cette option signifie seulement que le programme essaiera de s'exécuter en arrière-plan, que cela soit possible dépend de l'autorisation activée ou non. Pour Android natif, veuillez désactiver l'« Optimisation de la batterie » dans cette application, et pour MIUI, veuillez changer la politique d'économie d'énergie en « Illimité ».",
"bioAuth": "Authentification biométrique",
"browser": "Navigateur",
"bulkImportServers": "Importation groupée des serveurs",
"bulkImportServersTip": "Vous pouvez trouver le [format]({url}) ici.",
"canPullRefresh": "Vous pouvez tirer pour rafraîchir.",
"cancel": "Annuler",
"choose": "Choisir",
"chooseFontFile": "Choisir un fichier de police",
"choosePrivateKey": "Choisir une clé privée",
"clear": "Effacer",
"clipboard": "Presse-papiers",
"close": "Fermer",
"cmd": "Commande",
"cnKeyboardComp": "Compatibilité avec Android chinois",
"cnKeyboardCompTip": "Si le terminal affiche un clavier sécurisé, vous pouvez l'activer.",
"collapseUI": "Réduire",
"collapseUITip": "Indique si les longues listes présentées dans l'interface utilisateur doivent être réduites par défaut.",
"collectUsage": "Collecter des informations d'utilisation (sans rapport avec la confidentialité).",
"conn": "Connexion",
"connected": "Connecté",
"container": "Conteneur",
"containerName": "Nom du conteneur",
"containerStatus": "État du conteneur",
"containerTrySudoTip": "Par exemple : Dans l'application, l'utilisateur est défini comme aaa, mais Docker est installé sous l'utilisateur root. Dans ce cas, vous devez activer cette option.",
"content": "Contenu",
"convert": "Convertir",
"copy": "Copier",
"copyPath": "Copier le chemin",
"cpuViewAsProgressTip": "Afficher le taux d'utilisation de chaque CPU sous forme de barre de progression (ancien style)",
"createFile": "Créer un fichier",
"createFolder": "Créer un dossier",
"cursorType": "Type de curseur",
"customCmd": "Commandes personnalisées",
"customCmdDocUrl": "https://github.com/lollipopkit/flutter_server_box/wiki#custom-commands",
"customCmdHint": "\"Nom de la commande\": \"Commande\"",
"dark": "Sombre",
"day": "Jour",
"debug": "Débogage",
"decode": "Décoder",
"decompress": "Décompresser",
"delete": "Supprimer",
"deleteScripts": "Supprimer les scripts du serveur en même temps",
"deleteServers": "Supprimer des serveurs en lot",
"deviceName": "Nom de l'appareil",
"dirEmpty": "Assurez-vous que le répertoire est vide.",
"disabled": "Désactivé",
"disconnected": "Déconnecté",
"disk": "Disque",
"diskIgnorePath": "Chemin à ignorer pour le disque",
"displayCpuIndex": "Afficher l'index CPU",
"displayName": "Nom d'affichage",
"dl2Local": "Télécharger {fileName} localement ?",
"doc": "Documentation",
"dockerEditHost": "Modifier DOCKER_HOST",
"dockerEmptyRunningItems": "Aucun conteneur en cours d'exécution.\nCela peut être dû à :\n- L'utilisateur d'installation de Docker n'est pas le même que celui configuré dans l'application.\n- La variable d'environnement DOCKER_HOST n'a pas été lue correctement. Vous pouvez l'obtenir en exécutant `echo $DOCKER_HOST` dans le terminal.",
"dockerImagesFmt": "{count} images",
"dockerNotInstalled": "Docker non installé",
@@ -89,36 +44,24 @@
"dockerStatusRunningFmt": "{count} conteneur en cours d'exécution.",
"doubleColumnMode": "Mode double colonne",
"doubleColumnTip": "Cette option n'active que la fonctionnalité, qu'elle puisse être activée dépend de la largeur de l'appareil.",
"download": "Télécharger",
"edit": "Éditer",
"editVirtKeys": "Modifier les touches virtuelles",
"editor": "Éditeur",
"editorHighlightTip": "La performance actuelle de mise en surbrillance du code est pire et peut être désactivée en option pour s'améliorer.",
"encode": "Encoder",
"error": "Erreur",
"exampleName": "Nom de l'exemple",
"envVars": "Variable denvironnement",
"experimentalFeature": "Fonctionnalité expérimentale",
"export": "Exporter",
"extraArgs": "Arguments supplémentaires",
"failed": "Échoué",
"feedback": "Retour",
"feedbackOnGithub": "Si vous avez des questions, veuillez donner votre avis sur Github.",
"fieldMustNotEmpty": "Ces champs ne doivent pas être vides.",
"fileNotExist": "{file} n'existe pas",
"fallbackSshDest": "Destino SSH alternativo",
"fdroidReleaseTip": "Si vous avez téléchargé cette application depuis F-Droid, il est recommandé de désactiver cette option.",
"fileTooLarge": "Fichier '{file}' trop volumineux {size}, max {sizeMax}",
"files": "Fichiers",
"finished": "Terminé",
"followSystem": "Suivre le système",
"font": "Police",
"fontSize": "Taille de la police",
"force": "Forcer",
"foundNUpdate": "{count} mise à jour trouvée",
"fullScreen": "Mode plein écran",
"fullScreenJitter": "Secousse en plein écran",
"fullScreenJitterHelp": "Pour éviter les brûlures d'écran",
"fullScreenTip": "Le mode plein écran doit-il être activé lorsque l'appareil est orienté en mode paysage ? Cette option s'applique uniquement à l'onglet serveur.",
"getPushTokenFailed": "Impossible de récupérer le jeton de notification",
"gettingToken": "Récupération du jeton...",
"goBackQ": "Revenir en arrière ?",
"goto": "Aller à",
"hideTitleBar": "Masquer la barre de titre",
@@ -126,37 +69,24 @@
"highlight": "Mise en surbrillance du code",
"homeWidgetUrlConfig": "Configurer l'URL du widget d'accueil",
"host": "Hôte",
"hour": "Heure",
"httpFailedWithCode": "Échec de la requête, code d'état : {code}",
"icloudSynced": "iCloud est en cours de synchronisation et certains paramètres peuvent nécessiter un redémarrage de l'application pour prendre effet.",
"ignoreCert": "Ignorer le certificat",
"image": "Image",
"imagesList": "Liste des images",
"import": "Importer",
"inAppUpdate": "Mettre à jour dans l'application ? Sinon, téléchargez en utilisant un navigateur.",
"init": "Initialiser",
"inner": "Interne",
"inputDomainHere": "Saisissez le domaine ici",
"install": "Installer",
"installDockerWithUrl": "Veuillez d'abord installer docker depuis https://docs.docker.com/engine/install.",
"invalid": "Invalide",
"invalidJson": "JSON invalide",
"invalidVersion": "Version invalide",
"invalidVersionHelp": "Assurez-vous que docker est correctement installé, ou que vous utilisez une version non compilée par vous-même. Si vous n'avez pas les problèmes ci-dessus, veuillez soumettre un problème sur {url}.",
"isBusy": "Est occupé maintenant",
"jumpServer": "Aller au serveur",
"keepForeground": "Garder l'application en premier plan !",
"keepStatusWhenErr": "Conserver l'état du dernier serveur",
"keepStatusWhenErrTip": "Uniquement en cas d'erreur lors de l'exécution du script",
"keyAuth": "Authentification par clé",
"language": "Langue",
"languageName": "Français",
"lastTry": "Dernière tentative",
"launchPage": "Page de lancement",
"letterCache": "Mise en cache des lettres",
"letterCacheTip": "Recommandé de désactiver, mais après désactivation, il sera impossible de saisir des caractères CJK.",
"license": "Licence",
"light": "Clair",
"loadingFiles": "Chargement des fichiers...",
"location": "Emplacement",
"log": "Journal",
"loss": "Perte",
"madeWithLove": "Fabriqué avec ❤️ par {myGithub}",
"manual": "Manuel",
@@ -164,60 +94,36 @@
"maxRetryCount": "Nombre de reconnexions au serveur",
"maxRetryCountEqual0": "Il va réessayer encore et encore.",
"min": "min",
"minute": "Minute",
"mission": "Mission",
"more": "Plus",
"moveOutServerFuncBtnsHelp": "Activé : peut être affiché sous chaque carte sur la page de l'onglet Serveur. Désactivé : peut être affiché en haut de la page de détails du serveur.",
"ms": "ms",
"name": "Nom",
"needHomeDir": "Si vous êtes utilisateur Synology, [consultez ici](https://kb.synology.com/DSM/tutorial/user_enable_home_service). Les utilisateurs d'autres systèmes doivent rechercher comment créer un répertoire personnel.",
"needRestart": "Nécessite un redémarrage de l'application",
"net": "Réseau",
"netViewType": "Type de vue réseau",
"newContainer": "Nouveau conteneur",
"noClient": "Pas de client",
"noInterface": "Pas d'interface",
"noLineChart": "Ne pas utiliser de graphiques linéaires",
"noNotiPerm": "Pas de permissions de notification, peut-être pas d'indication de progression lors de la mise à jour des applications.",
"noOptions": "Pas d'options",
"noLineChartForCpu": "Ne pas utiliser de graphiques linéaires pour l'unité centrale",
"noPrivateKeyTip": "La clé privée n'existe pas, elle a peut-être été supprimée ou il y a une erreur de configuration.",
"noPromptAgain": "Ne pas demander à nouveau",
"noResult": "Pas de résultat",
"noSavedPrivateKey": "Aucune clé privée enregistrée.",
"noSavedSnippet": "Aucun extrait de code enregistré.",
"noServerAvailable": "Aucun serveur disponible.",
"noTask": "Pas de tâche",
"noUpdateAvailable": "Pas de mise à jour disponible",
"node": "Nœud",
"notAvailable": "Indisponible",
"notSelected": "Non sélectionné",
"note": "Note",
"nullToken": "Jeton nul",
"ok": "OK",
"onServerDetailPage": "Sur la page de détails du serveur",
"onlyOneLine": "Afficher uniquement en une seule ligne (défilement)",
"onlyWhenCoreBiggerThan8": "Fonctionne uniquement lorsque le nombre de cœurs est > 8",
"open": "Ouvrir",
"openLastPath": "Ouvrir le dernier chemin",
"openLastPathTip": "Les différents serveurs auront des journaux différents, et le journal est le chemin vers la sortie",
"parseContainerStats": "Analyser l'état d'occupation du conteneur",
"parseContainerStatsTip": "L'analyse de l'occupation des conteneurs Docker est relativement lente.",
"paste": "Coller",
"path": "Chemin",
"percentOfSize": "{percent}% de {size}",
"pickFile": "Choisir un fichier",
"permission": "Permissions",
"pingAvg": "Moy.:",
"pingInputIP": "Veuillez saisir une adresse IP / un domaine cible.",
"pingNoServer": "Aucun serveur à pinger.\nVeuillez ajouter un serveur dans l'onglet serveur.",
"pkg": "Pkg",
"pkgUpgradeTip": "Veuillez sauvegarder votre système avant de procéder à la mise à jour.",
"platformNotSupportUpdate": "La plateforme actuelle ne prend pas en charge la mise à jour dans l'application.\nVeuillez le compiler depuis les sources et l'installer.",
"plugInType": "Type d'insertion",
"plzEnterHost": "Veuillez saisir l'hôte.",
"plzSelectKey": "Veuillez sélectionner une clé.",
"port": "Port",
"preview": "Aperçu",
"primaryColorSeed": "Graine de couleur primaire",
"privateKey": "Clé privée",
"process": "Processus",
"pushToken": "Jeton d'identification",
@@ -227,15 +133,11 @@
"pwd": "Mot de passe",
"read": "Lire",
"reboot": "Redémarrer",
"rememberChoice": "Se souvenir du choix",
"rememberPwdInMem": "Mémoriser le mot de passe en mémoire",
"rememberPwdInMemTip": "Utilisé pour les conteneurs, la suspension, etc.",
"rememberWindowSize": "Se souvenir de la taille de la fenêtre",
"remotePath": "Chemin distant",
"rename": "Renommer",
"reportBugsOnGithubIssue": "Veuillez signaler les bugs sur {url}",
"restart": "Redémarrer",
"restore": "Restaurer",
"restoreSuccess": "Restauration réussie. Redémarrez l'application pour appliquer.",
"result": "Résultat",
"rotateAngel": "Angle de rotation",
"route": "Routage",
@@ -250,14 +152,8 @@
"serverDetailOrder": "Ordre des widgets de la page de détails du serveur",
"serverFuncBtns": "Boutons de fonction du serveur",
"serverOrder": "Ordre du serveur",
"serverTabConnecting": "Connexion en cours...",
"serverTabEmpty": "Aucun serveur.\nCliquez sur le fab pour en ajouter un.",
"serverTabFailed": "Échec",
"serverTabLoading": "Chargement...",
"serverTabPlzSave": "Veuillez 'enregistrer' cette clé privée à nouveau.",
"serverTabUnkown": "État inconnu",
"setting": "Paramètres",
"sftpDlPrepare": "Préparation de la connexion...",
"sftpEditorTip": "Si vide, utilisez léditeur de fichiers intégré de lapplication. Si une valeur est présente, utilisez léditeur du serveur distant, par exemple `vim` (il est recommandé de détecter automatiquement selon `EDITOR`).",
"sftpRmrDirSummary": "Utilisez `rm -r` pour supprimer un dossier en SFTP.",
"sftpSSHConnected": "SFTP Connecté",
"sftpShowFoldersFirst": "Afficher d'abord les dossiers",
@@ -272,11 +168,11 @@
"sshTip": "Cette fonctionnalité est actuellement à l'étape expérimentale.\n\nVeuillez signaler les bugs sur {url} ou rejoindre notre développement.",
"sshVirtualKeyAutoOff": "Activation automatique des touches virtuelles",
"start": "Démarrer",
"stat": "Statistiques",
"stats": "Statistiques",
"stop": "Arrêter",
"stopped": "Arrêté",
"storage": "Stockage",
"success": "Succès",
"supportFmtArgs": "Les paramètres de mise en forme suivants sont pris en charge :",
"suspend": "Suspendre",
"suspendTip": "La fonction de suspension nécessite des privilèges root et le support de systemd.",
@@ -292,35 +188,25 @@
"textScaler": "Mise à l'échelle du texte",
"textScalerTip": "1.0 => 100% (taille originale), fonctionne uniquement sur la partie de la police de la page du serveur, il est déconseillé de la modifier.",
"theme": "Thème",
"themeMode": "Mode thème",
"time": "Temps",
"times": "Fois",
"total": "Total",
"traffic": "Trafic",
"trySudo": "Essayer d'utiliser sudo",
"ttl": "ttl",
"ttl": "TTL",
"unknown": "Inconnu",
"unknownError": "Erreur inconnue",
"unkownConvertMode": "Mode de conversion inconnu",
"update": "Mettre à jour",
"updateAll": "Tout mettre à jour",
"updateIntervalEqual0": "Vous avez défini à 0, la mise à jour ne se fera pas automatiquement.\nImpossible de calculer l'état du CPU.",
"updateServerStatusInterval": "Intervalle de mise à jour de l'état du serveur",
"updateTip": "Mise à jour : v1.0.{newest}",
"updateTipTooLow": "La version actuelle est trop ancienne, veuillez mettre à jour vers v1.0.{newest}",
"upload": "Télécharger",
"upsideDown": "À l'envers",
"uptime": "Temps d'activité",
"urlOrJson": "URL ou JSON",
"useCdn": "Utiliser CDN",
"useCdnTip": "Il est recommandé aux utilisateurs non chinois d'utiliser le CDN. Souhaitez-vous l'utiliser ?",
"useNoPwd": "Aucun mot de passe ne sera utilisé",
"usePodmanByDefault": "Par défaut avec Podman",
"used": "Utilisé",
"user": "Utilisateur",
"versionHaveUpdate": "Trouvé : v1.0.{build}, cliquez pour mettre à jour",
"versionUnknownUpdate": "Actuelle : v1.0.{build}, cliquez pour vérifier les mises à jour",
"versionUpdated": "Actuelle : v1.0.{build}, est à jour",
"view": "Vue",
"viewErr": "Voir erreur",
"virtKeyHelpClipboard": "Copiez dans le presse-papiers si le terminal sélectionné n'est pas vide, sinon collez le contenu du presse-papiers dans le terminal.",
@@ -331,8 +217,8 @@
"watchNotPaired": "Aucune Apple Watch associée",
"webdavSettingEmpty": "Le paramètre Webdav est vide",
"whenOpenApp": "À l'ouverture de l'application",
"willTakEeffectImmediately": "Prendra effet immédiatement",
"wolTip": "Après avoir configuré le WOL (Wake-on-LAN), une requête WOL est envoyée chaque fois que le serveur est connecté.",
"write": "Écrire",
"writeScriptFailTip": "Échec de l'écriture dans le script, probablement en raison d'un manque de permissions ou que le répertoire n'existe pas."
"writeScriptFailTip": "Échec de l'écriture dans le script, probablement en raison d'un manque de permissions ou que le répertoire n'existe pas.",
"writeScriptTip": "Après la connexion au serveur, un script sera écrit dans ~/.config/server_box pour surveiller létat du système. Vous pouvez examiner le contenu du script."
}

View File

@@ -1,87 +1,42 @@
{
"@@locale": "id",
"about": "Tentang",
"aboutThanks": "Terima kasih kepada orang -orang berikut yang berpartisipasi.",
"acceptBeta": "Terima pembaruan versi uji coba",
"add": "Menambahkan",
"addAServer": "tambahkan server",
"addPrivateKey": "Tambahkan kunci pribadi",
"addSystemPrivateKeyTip": "Saat ini tidak memiliki kunci privat, apakah Anda menambahkan kunci yang disertakan dengan sistem (~/.ssh/id_rsa)?",
"added2List": "Ditambahkan ke Daftar Tugas",
"addr": "Alamat",
"all": "Semua",
"alreadyLastDir": "Sudah di direktori terakhir.",
"alterUrl": "Alter url",
"askContinue": "{msg}, lanjutkan?",
"attention": "Perhatian",
"authFailTip": "Otentikasi gagal, silakan periksa apakah kata sandi/kunci/host/pengguna, dll, salah.",
"authRequired": "Auth diperlukan",
"auto": "Auto",
"autoBackupConflict": "Hanya satu pencadangan otomatis yang dapat diaktifkan pada saat yang bersamaan.",
"autoCheckUpdate": "Periksa pembaruan otomatis",
"autoConnect": "Hubungkan otomatis",
"autoRun": "Berjalan Otomatis",
"autoUpdateHomeWidget": "Widget Rumah Pembaruan Otomatis",
"backup": "Cadangan",
"backupTip": "Data yang diekspor hanya dienkripsi.\nTolong jaga keamanannya.",
"backupVersionNotMatch": "Versi cadangan tidak cocok.",
"battery": "Baterai",
"bgRun": "Jalankan di Backgroud",
"bgRunTip": "Sakelar ini hanya berarti aplikasi akan mencoba berjalan di latar belakang, apakah aplikasi dapat berjalan di latar belakang tergantung pada apakah izin diaktifkan atau tidak. Untuk Android asli, nonaktifkan \"Pengoptimalan Baterai\" di aplikasi ini, dan untuk miui, ubah kebijakan penghematan daya ke \"Tidak Terbatas\".",
"bioAuth": "Biosertifikasi",
"browser": "Peramban",
"bulkImportServers": "Impor server secara massal",
"bulkImportServersTip": "Anda dapat menemukan [format]({url}) di sini.",
"canPullRefresh": "Anda dapat menarik untuk menyegarkan.",
"cancel": "Membatalkan",
"choose": "Memilih",
"chooseFontFile": "Pilih file font",
"choosePrivateKey": "Pilih Kunci Pribadi",
"clear": "Jernih",
"clipboard": "papan klip",
"close": "Menutup",
"cmd": "Memerintah",
"cnKeyboardComp": "Kompatibilitas dengan Android China",
"cnKeyboardCompTip": "Jika terminal munculkan keyboard aman, Anda bisa mengaktifkannya.",
"collapseUI": "Runtuh",
"collapseUITip": "Apakah akan menciutkan daftar panjang yang ada di UI secara default atau tidak",
"collectUsage": "Mengumpulkan informasi penggunaan (tidak terkait dengan privasi).",
"conn": "Koneksi",
"connected": "Terhubung",
"container": "Wadah",
"containerName": "Nama kontainer",
"containerStatus": "Status wadah",
"containerTrySudoTip": "Contohnya: Di dalam aplikasi, pengguna diatur sebagai aaa, tetapi Docker diinstal di bawah pengguna root. Dalam kasus ini, Anda perlu mengaktifkan opsi ini.",
"content": "Konten",
"convert": "Mengubah",
"copy": "Menyalin",
"copyPath": "Path Copy",
"cpuViewAsProgressTip": "Tampilkan tingkat penggunaan setiap CPU dalam gaya bilah kemajuan (gaya lama)",
"createFile": "Buat file",
"createFolder": "Membuat folder",
"cursorType": "Jenis kursor",
"customCmd": "Perintah kustom",
"customCmdDocUrl": "https://github.com/lollipopkit/flutter_server_box/wiki#custom-commands",
"customCmdHint": "\"Nama Perintah\": \"Perintah\"",
"dark": "Gelap",
"day": "Hari",
"debug": "Debug",
"decode": "Membaca sandi",
"decompress": "Dekompresi",
"delete": "Menghapus",
"deleteScripts": "Menghapus skrip server secara bersamaan",
"deleteServers": "Penghapusan server secara batch",
"deviceName": "Nama perangkat",
"dirEmpty": "Pastikan dir kosong.",
"disabled": "Dengan disabilitas",
"disconnected": "Terputus",
"disk": "Disk",
"diskIgnorePath": "Abaikan jalan untuk disk",
"displayCpuIndex": "Tampilkan indeks CPU",
"displayName": "Nama tampilan",
"dl2Local": "Unduh {fileName} ke lokal?",
"doc": "Dokumentasi",
"dockerEditHost": "Edit Docker_host",
"dockerEmptyRunningItems": "Tidak ada wadah yang sedang berjalan.\nHal ini dapat terjadi karena:\n- Pengguna instalasi Docker tidak sama dengan nama pengguna yang dikonfigurasi di dalam Aplikasi.\n- Variabel lingkungan DOCKER_HOST tidak terbaca dengan benar. Anda bisa mendapatkannya dengan menjalankan `echo $DOCKER_HOST` di terminal.",
"dockerImagesFmt": "{count} gambar",
"dockerNotInstalled": "Docker tidak terpasang",
@@ -89,36 +44,24 @@
"dockerStatusRunningFmt": "{count} wadah berjalan.",
"doubleColumnMode": "Mode kolom ganda",
"doubleColumnTip": "Opsi ini hanya mengaktifkan fitur, apakah itu benar-benar dapat diaktifkan tergantung pada lebar perangkat",
"download": "Unduh",
"edit": "Edit",
"editVirtKeys": "Edit kunci virtual",
"editor": "Editor",
"editorHighlightTip": "Performa penyorotan kode saat ini lebih buruk, dan dapat dimatikan secara opsional untuk perbaikan.",
"encode": "Menyandi",
"error": "Kesalahan",
"exampleName": "Nama contoh",
"envVars": "Variabel lingkungan",
"experimentalFeature": "Fitur eksperimental",
"export": "Ekspor",
"extraArgs": "Args ekstra",
"failed": "Gagal",
"feedback": "Masukan",
"feedbackOnGithub": "Jika Anda memiliki pertanyaan, silakan umpan balik tentang GitHub.",
"fieldMustNotEmpty": "Bidang -bidang ini tidak boleh kosong.",
"fileNotExist": "{file} tidak ada",
"fallbackSshDest": "Tujuan SSH mundur",
"fdroidReleaseTip": "Jika Anda mengunduh aplikasi ini dari F-Droid, disarankan untuk mematikan opsi ini.",
"fileTooLarge": "File '{file}' terlalu besar {size}, max {sizeMax}",
"files": "File",
"finished": "Selesai",
"followSystem": "Ikuti sistem",
"font": "Font",
"fontSize": "Ukuran huruf",
"force": "sukarela",
"foundNUpdate": "Menemukan {count} pembaruan",
"fullScreen": "Mode Layar Penuh",
"fullScreenJitter": "Jitter layar penuh",
"fullScreenJitterHelp": "Untuk menghindari pembakaran layar",
"fullScreenTip": "Apakah mode layar penuh diaktifkan ketika perangkat diputar ke modus lanskap? Opsi ini hanya berlaku untuk tab server.",
"getPushTokenFailed": "Tidak bisa mengambil token dorong",
"gettingToken": "Mendapatkan token ...",
"goBackQ": "Datang kembali?",
"goto": "Pergi ke",
"hideTitleBar": "Sembunyikan bilah judul",
@@ -126,37 +69,24 @@
"highlight": "Sorotan kode",
"homeWidgetUrlConfig": "Konfigurasi URL Widget Rumah",
"host": "Host",
"hour": "Jam",
"httpFailedWithCode": "Permintaan gagal, kode status: {code}",
"icloudSynced": "iCloud disinkronkan dan beberapa pengaturan mungkin memerlukan pengaktifan ulang aplikasi agar dapat diterapkan.",
"ignoreCert": "Abaikan sertifikat",
"image": "Gambar",
"imagesList": "Daftar gambar",
"import": "Impor",
"inAppUpdate": "Perbarui di dalam aplikasi? Jika tidak, unduh menggunakan browser.",
"init": "Menginisialisasi",
"inner": "Batin",
"inputDomainHere": "Input domain di sini",
"install": "Install",
"installDockerWithUrl": "Silakan https://docs.docker.com/engine/install Docker pertama.",
"invalid": "Tidak valid",
"invalidJson": "JSON tidak valid",
"invalidVersion": "Versi tidak valid",
"invalidVersionHelp": "Pastikan Docker diinstal dengan benar, atau Anda menggunakan versi yang tidak dikompilasi. Jika Anda tidak memiliki masalah di atas, silakan kirimkan masalah pada {url}.",
"isBusy": "Sibuk sekarang",
"jumpServer": "Lompat server",
"keepForeground": "Simpan Aplikasi Foreground!",
"keepStatusWhenErr": "Menyimpan status server terakhir",
"keepStatusWhenErrTip": "Hanya ketika terjadi kesalahan saat menjalankan skrip",
"keyAuth": "Auth kunci",
"language": "Bahasa",
"languageName": "Indonesia",
"lastTry": "Percobaan terakhir",
"launchPage": "Halaman peluncuran",
"letterCache": "Caching huruf",
"letterCacheTip": "Direkomendasikan untuk menonaktifkan, tetapi setelah dinonaktifkan, tidak mungkin untuk memasukkan karakter CJK.",
"license": "Lisensi",
"light": "Terang",
"loadingFiles": "Memuat file ...",
"location": "Lokasi",
"log": "Catatan",
"loss": "kehilangan",
"madeWithLove": "Dibuat dengan ❤️ oleh {myGithub}",
"manual": "Manual",
@@ -164,60 +94,36 @@
"maxRetryCount": "Jumlah penyambungan kembali server",
"maxRetryCountEqual0": "Akan mencoba lagi lagi dan lagi.",
"min": "Min",
"minute": "Menit",
"mission": "Misi",
"more": "Lebih Banyak",
"moveOutServerFuncBtnsHelp": "Aktif: dapat ditampilkan di bawah setiap kartu pada halaman Tab Server. Nonaktif: dapat ditampilkan di bagian atas halaman Rincian Server.",
"ms": "MS",
"name": "Nama",
"needHomeDir": "Jika Anda pengguna Synology, [lihat di sini](https://kb.synology.com/DSM/tutorial/user_enable_home_service). Pengguna sistem lain perlu mencari cara membuat direktori home.",
"needRestart": "Perlu memulai ulang aplikasi",
"net": "Net",
"net": "Jaringan",
"netViewType": "Jenis tampilan bersih",
"newContainer": "Wadah baru",
"noClient": "Tidak ada klien",
"noInterface": "Tidak ada antarmuka",
"noLineChart": "Jangan gunakan grafik garis",
"noNotiPerm": "Tidak ada izin notifikasi, mungkin tidak ada indikasi kemajuan saat mengunduh pembaruan aplikasi.",
"noOptions": "Tidak ada opsi",
"noLineChartForCpu": "Jangan gunakan diagram garis untuk CPU",
"noPrivateKeyTip": "Kunci privat tidak ada, mungkin telah dihapus atau ada kesalahan konfigurasi.",
"noPromptAgain": "Jangan tanya lagi",
"noResult": "Tidak ada hasil",
"noSavedPrivateKey": "Tidak ada kunci pribadi yang disimpan.",
"noSavedSnippet": "Tidak ada cuplikan yang disimpan.",
"noServerAvailable": "Tidak ada server yang tersedia.",
"noTask": "Tidak bertanya",
"noUpdateAvailable": "Tidak ada pembaruan yang tersedia",
"node": "Node",
"notAvailable": "Tidak tersedia",
"notSelected": "Tidak terpilih",
"note": "Catatan",
"nullToken": "Token NULL",
"ok": "OKE",
"onServerDetailPage": "Di halaman detail server",
"onlyOneLine": "Hanya tampilkan sebagai satu baris (dapat digulir)",
"onlyWhenCoreBiggerThan8": "Berlaku hanya ketika jumlah inti > 8",
"open": "Membuka",
"openLastPath": "Buka jalur terakhir",
"openLastPathTip": "Server yang berbeda akan memiliki catatan yang berbeda, dan catatan tersebut adalah jalur menuju pintu keluar",
"parseContainerStats": "Memecahkan status okupansi kontainer",
"parseContainerStatsTip": "Parsing status okupansi oleh Docker agak lambat",
"paste": "Tempel",
"path": "Jalur",
"percentOfSize": "{percent}% dari {size}",
"pickFile": "Pilih file",
"permission": "Izin",
"pingAvg": "Rata -rata:",
"pingInputIP": "Harap masukkan IP / domain target.",
"pingNoServer": "Tidak ada server untuk melakukan ping.\nHarap tambahkan server di tab Server.",
"pkg": "Pkg",
"pkgUpgradeTip": "Harap cadangkan sistem Anda sebelum memperbarui.",
"platformNotSupportUpdate": "Platform saat ini tidak mendukung pembaruan aplikasi.\nSilakan bangun dari sumber dan instal.",
"plugInType": "Jenis Penyisipan",
"plzEnterHost": "Harap masukkan host.",
"plzSelectKey": "Pilih kunci.",
"port": "Port",
"preview": "Pratinjau",
"primaryColorSeed": "Warna utama",
"privateKey": "Kunci Pribadi",
"process": "Proses",
"pushToken": "Dorong token",
@@ -227,15 +133,11 @@
"pwd": "Kata sandi",
"read": "Baca",
"reboot": "Reboot",
"rememberChoice": "Ingat pilihan",
"rememberPwdInMem": "Ingat kata sandi di dalam memori",
"rememberPwdInMemTip": "Digunakan untuk kontainer, menangguhkan, dll.",
"rememberWindowSize": "Ingat ukuran jendela",
"remotePath": "Jalur jarak jauh",
"rename": "Ganti nama",
"reportBugsOnGithubIssue": "Harap laporkan bug di {url}",
"restart": "Mengulang kembali",
"restore": "Memulihkan",
"restoreSuccess": "Kembalikan kesuksesan. Mulai ulang aplikasi untuk diterapkan.",
"result": "Hasil",
"rotateAngel": "Sudut rotasi",
"route": "Routing",
@@ -250,14 +152,8 @@
"serverDetailOrder": "Detail pesanan widget halaman",
"serverFuncBtns": "Tombol fungsi server",
"serverOrder": "Pesanan server",
"serverTabConnecting": "Menghubungkan ...",
"serverTabEmpty": "Tidak ada server.\nKlik fab untuk menambahkan satu.",
"serverTabFailed": "Gagal",
"serverTabLoading": "Memuat...",
"serverTabPlzSave": "Harap 'simpan' kunci pribadi ini lagi.",
"serverTabUnkown": "Negara yang tidak diketahui",
"setting": "Pengaturan",
"sftpDlPrepare": "Bersiap untuk terhubung ...",
"sftpEditorTip": "Jika kosong, gunakan editor file bawaan aplikasi. Jika ada nilai, gunakan editor server jarak jauh, misalnya `vim` (disarankan untuk mendeteksi secara otomatis sesuai `EDITOR`).",
"sftpRmrDirSummary": "Gunakan `rm -r` untuk menghapus dir di SFTP",
"sftpSSHConnected": "Sftp terhubung",
"sftpShowFoldersFirst": "Folder ditampilkan lebih dulu",
@@ -272,11 +168,11 @@
"sshTip": "Fungsi ini sekarang dalam tahap eksperimen.\n\nHarap laporkan bug di {url} atau bergabunglah dengan pengembangan kami.",
"sshVirtualKeyAutoOff": "Switching Otomatis Kunci Virtual",
"start": "Awal",
"stat": "Statistik",
"stats": "Statistik",
"stop": "Berhenti",
"stopped": "dihentikan",
"storage": "Penyimpanan",
"success": "Kesuksesan",
"supportFmtArgs": "Parameter pemformatan berikut ini didukung:",
"suspend": "Suspend",
"suspendTip": "Fungsi penangguhan memerlukan hak akses root dan dukungan systemd.",
@@ -292,35 +188,25 @@
"textScaler": "Penskalaan font",
"textScalerTip": "1.0 => 100% (ukuran asli), hanya berfungsi pada bagian halaman server font, tidak disarankan untuk diubah.",
"theme": " Tema",
"themeMode": "Mode tema",
"time": "Waktu",
"times": "Waktu",
"total": "Total",
"traffic": "Lalu lintas",
"trySudo": "Cobalah menggunakan sudo",
"ttl": "ttl",
"ttl": "TTL",
"unknown": "Tidak dikenal",
"unknownError": "Kesalahan yang tidak diketahui",
"unkownConvertMode": "Mode Konversi Tidak Diketahui",
"update": "Memperbarui",
"updateAll": "Perbarui semua",
"updateIntervalEqual0": "Anda mengatur ke 0, tidak akan memperbarui secara otomatis.\nTidak dapat menghitung status CPU.",
"updateServerStatusInterval": "Interval Pembaruan Status Server",
"updateTip": "UPDATE: v1.0.{newest}",
"updateTipTooLow": "Versi saat ini terlalu rendah, harap perbarui ke v1.0.{newest}",
"upload": "Mengunggah",
"upsideDown": "Terbalik",
"uptime": "Uptime",
"urlOrJson": "URL atau JSON",
"useCdn": "Menggunakan CDN",
"useCdnTip": "Pengguna non-Cina disarankan menggunakan CDN. Apakah Anda ingin menggunakannya?",
"useNoPwd": "Tidak ada kata sandi yang akan digunakan",
"usePodmanByDefault": "Menggunakan Podman sebagai bawaan",
"used": "Digunakan",
"user": "Username",
"versionHaveUpdate": "Ditemukan: v1.0.{build}, klik untuk memperbarui",
"versionUnknownUpdate": "Saat ini: v1.0.{build}. Klik untuk memeriksa pembaruan.",
"versionUpdated": "Saat ini: v1.0.{build}, mutakhir",
"view": "Tampilan",
"viewErr": "Lihat kesalahan",
"virtKeyHelpClipboard": "Salin ke clipboard jika terminal yang dipilih tidak kosong, jika tidak, tempel isi clipboard ke terminal.",
@@ -331,8 +217,8 @@
"watchNotPaired": "Tidak ada Apple Watch yang dipasangkan",
"webdavSettingEmpty": "Pengaturan webdav kosong",
"whenOpenApp": "Saat membuka aplikasi",
"willTakEeffectImmediately": "Akan segera berlaku",
"wolTip": "Setelah mengonfigurasi WOL (Wake-on-LAN), permintaan WOL dikirim setiap kali server terhubung.",
"write": "Tulis",
"writeScriptFailTip": "Penulisan ke skrip gagal, mungkin karena tidak ada izin atau direktori tidak ada."
"writeScriptFailTip": "Penulisan ke skrip gagal, mungkin karena tidak ada izin atau direktori tidak ada.",
"writeScriptTip": "Setelah terhubung ke server, sebuah skrip akan ditulis ke ~/.config/server_box untuk memantau status sistem. Anda dapat meninjau konten skrip tersebut."
}

View File

@@ -1,87 +1,42 @@
{
"@@locale": "ja",
"about": "約",
"aboutThanks": "以下の参加者に感謝します。",
"acceptBeta": "テストバージョンの更新を受け入れる",
"add": "追加",
"addAServer": "サーバーを追加する",
"addPrivateKey": "プライベートキーを追加",
"addSystemPrivateKeyTip": "現在プライベートキーがありません。システムのデフォルト(~/.ssh/id_rsa)を追加しますか?",
"addSystemPrivateKeyTip": "現在秘密鍵がありません。システムのデフォルト(~/.ssh/id_rsa)を追加しますか?",
"added2List": "タスクリストに追加されました",
"addr": "住所",
"all": "すべて",
"addr": "アドレス",
"alreadyLastDir": "すでに最上位のディレクトリです",
"alterUrl": "代替リンク",
"askContinue": "{msg}、続行しますか?",
"attention": "注意",
"authFailTip": "認証に失敗しました。パスワード/鍵/ホスト/ユーザーなどが間違っていないか確認してください。",
"authRequired": "認証が必要",
"auto": "自動",
"autoBackupConflict": "自動バックアップは一度に一つしか開始できません",
"autoCheckUpdate": "自動的に更新をチェック",
"autoConnect": "自動接続",
"autoRun": "自動実行",
"autoUpdateHomeWidget": "ホームウィジェットを自動更新",
"backup": "バックアップ",
"backupTip": "エクスポートされたデータは簡単に暗号化されています。適切に保管してください。",
"backupVersionNotMatch": "バックアップバージョンが一致しないため、復元できません",
"battery": "バッテリー",
"bgRun": "バックグラウンド実行",
"bgRunTip": "このスイッチはプログラムがバックグラウンドで実行を試みることを意味しますが、実際にバックグラウンドで実行できるかどうかは、権限が有効になっているかに依存します。ネイティブAndroidでは、このアプリの「バッテリー最適化」をオフにしてください。MIUIでは、省エネモードを「無制限」に変更してください。",
"bioAuth": "生体認証",
"browser": "ブラウザ",
"bulkImportServers": "サーバーを一括インポートする",
"bulkImportServersTip": "[こちら]({url})でフォーマットを見つけることができます",
"canPullRefresh": "引っ張って更新できます",
"cancel": "キャンセル",
"choose": "選択",
"chooseFontFile": "フォントファイルを選択",
"choosePrivateKey": "プライベートキーを選択",
"clear": "クリア",
"clipboard": "クリップボード",
"close": "閉じる",
"bgRunTip": "このスイッチはプログラムがバックグラウンドで実行を試みることを意味しますが、実際にバックグラウンドで実行できるかどうかは、権限が有効になっているかに依存します。AOSPベースのAndroid ROMでは、このアプリの「バッテリー最適化」をオフにしてください。MIUIでは、省エネモードを「無制限」に変更してください。",
"cmd": "コマンド",
"cnKeyboardComp": "中国のAndroidとの互換性",
"cnKeyboardCompTip": "ターミナルがセキュアキーボードを表示した場合、それを有効にできます。",
"collapseUI": "UIを折りたたむ",
"collapseUITip": "UIの長いリストをデフォルトで折りたたむかどうか",
"collectUsage": "使用情報を収集する(プライバシーとは関係ない)。",
"conn": "接続",
"connected": "接続済み",
"container": "コンテナ",
"containerName": "コンテナ名",
"containerStatus": "コンテナの状態",
"containerTrySudoTip": "例アプリ内でユーザーをaaaに設定しているが、Dockerがrootユーザーでインストールされている場合、このオプションを有効にする必要があります",
"content": "コンテンツ",
"convert": "変換",
"copy": "コピー",
"copyPath": "パスをコピー",
"cpuViewAsProgressTip": "各CPUの使用率をプログレスバースタイルで表示する旧スタイル",
"createFile": "ファイルを作成",
"createFolder": "フォルダーを作成",
"cursorType": "カーソルタイプ",
"customCmd": "カスタムコマンド",
"customCmdDocUrl": "https://github.com/lollipopkit/flutter_server_box/wiki#custom-commands",
"customCmdHint": "\"コマンド名\": \"コマンド\"",
"dark": "ダーク",
"day": "日",
"debug": "デバッグ",
"decode": "デコード",
"decompress": "解凍",
"delete": "削除",
"deleteScripts": "サーバースクリプトも削除",
"deleteServers": "サーバーを一括削除",
"deviceName": "デバイス名",
"dirEmpty": "フォルダーが空であることを確認してください",
"disabled": "無効",
"disconnected": "接続が切断されました",
"disk": "ディスク",
"diskIgnorePath": "無視されたディスクパス",
"displayCpuIndex": "CPUインデックスを表示する",
"displayName": "表示名",
"dl2Local": "{fileName}をローカルにダウンロードしますか?",
"doc": "ドキュメント",
"dockerEditHost": "DOCKER_HOSTを編集",
"dockerEmptyRunningItems": "実行中のコンテナがありません。\nこれは次の理由による可能性があります\n- Dockerのインストールユーザーとアプリ内の設定されたユーザー名が異なる\n- 環境変数DOCKER_HOSTが正しく読み込まれていない。ターミナルで`echo $DOCKER_HOST`を実行して取得できます。",
"dockerImagesFmt": "合計{count}イメージ",
"dockerNotInstalled": "Dockerがインストールされていません",
@@ -89,36 +44,24 @@
"dockerStatusRunningFmt": "{count}個のコンテナが実行中",
"doubleColumnMode": "ダブルカラムモード",
"doubleColumnTip": "このオプションは機能を有効にするだけで、実際に有効にできるかどうかはデバイスの幅に依存します",
"download": "ダウンロード",
"edit": "編集",
"editVirtKeys": "仮想キーを編集",
"editor": "エディター",
"editorHighlightTip": "現在のコードハイライトのパフォーマンスはかなり悪いため、改善するために無効にすることを選択できます。",
"encode": "エンコード",
"error": "エラー",
"exampleName": "名前例",
"envVars": "環境変数",
"experimentalFeature": "実験的な機能",
"export": "エクスポート",
"extraArgs": "追加引数",
"failed": "失敗しました",
"feedback": "フィードバック",
"feedbackOnGithub": "問題がある場合は、GitHubでフィードバックしてください",
"fieldMustNotEmpty": "これらの入力フィールドは空にできません。",
"fileNotExist": "{file}は存在しません",
"fallbackSshDest": "フォールバックSSH宛先",
"fdroidReleaseTip": "このアプリをF-Droidからダウンロードした場合、このオプションをオフにすることをお勧めします。",
"fileTooLarge": "ファイル '{file}' は大きすぎます '{size}'、{sizeMax} を超えています",
"files": "ファイル",
"finished": "完了しました",
"followSystem": "システムに従う",
"font": "フォント",
"fontSize": "フォントサイズ",
"force": "強制",
"foundNUpdate": "{count}個の更新が見つかりました",
"fullScreen": "フルスクリーンモード",
"fullScreenJitter": "フルスクリーンモードのジッター",
"fullScreenJitterHelp": "焼き付き防止",
"fullScreenTip": "デバイスが横向きに回転したときにフルスクリーンモードを有効にしますか?このオプションはサーバータブにのみ適用されます。",
"getPushTokenFailed": "プッシュトークンを取得できませんでした",
"gettingToken": "トークンを取得しています...",
"goBackQ": "戻りますか?",
"goto": "移動",
"hideTitleBar": "タイトルバーを非表示にする",
@@ -126,37 +69,24 @@
"highlight": "コードハイライト",
"homeWidgetUrlConfig": "ホームウィジェットURL設定",
"host": "ホスト",
"hour": "時間",
"httpFailedWithCode": "リクエスト失敗、ステータスコード: {code}",
"icloudSynced": "iCloudが同期されました。一部の設定はアプリを再起動する必要があります。",
"ignoreCert": "証明書を無視する",
"image": "イメージ",
"imagesList": "イメージリスト",
"import": "インポート",
"inAppUpdate": "アプリ内で更新しますか?それ以外の場合は、ブラウザを使用してダウンロードしてください。",
"init": "初期化する",
"inner": "内蔵",
"inputDomainHere": "ここにドメインを入力",
"install": "インストール",
"installDockerWithUrl": "最初に https://docs.docker.com/engine/install dockerをインストールしてください",
"invalid": "無効",
"invalidJson": "無効なJSON",
"invalidVersion": "サポートされていないバージョン",
"invalidVersionHelp": "dockerが正しくインストールされていること、または自己コンパイルされたバージョンを使用していないことを確認してください。問題がない場合は、{url}で問題を報告してください。",
"isBusy": "現在忙しいです",
"jumpServer": "ジャンプサーバー",
"keepForeground": "アプリを前面に保ってください!",
"keepStatusWhenErr": "エラー時に前回のサーバーステータスを保持",
"keepStatusWhenErrTip": "スクリプトの実行エラーに限ります",
"keyAuth": "キー認証",
"language": "言語",
"languageName": "日本語",
"lastTry": "最後の試み",
"launchPage": "起動ページ",
"letterCache": "文字キャッシング",
"letterCacheTip": "無効にすることを推奨しますが、無効にした後はCJK文字を入力することができなくなります。",
"license": "オープンソースライセンス",
"light": "ライト",
"loadingFiles": "ディレクトリを読み込んでいます...",
"location": "場所",
"log": "ログ",
"loss": "パケットロス",
"madeWithLove": "❤️で作成された {myGithub}",
"manual": "マニュアル",
@@ -164,61 +94,37 @@
"maxRetryCount": "サーバーの再接続試行回数",
"maxRetryCountEqual0": "無限に再試行します",
"min": "最小",
"minute": "分",
"mission": "ミッション",
"more": "もっと",
"moveOutServerFuncBtnsHelp": "有効にする:サーバータブの各カードの下に表示されます。無効にする:サーバーの詳細ページの上部に表示されます。",
"ms": "ミリ秒",
"name": "名前",
"needHomeDir": "Synologyユーザーの場合は、[こちらをご覧ください](https://kb.synology.com/DSM/tutorial/user_enable_home_service)。他のシステムのユーザーは、ホームディレクトリの作成方法を検索する必要があります。",
"needRestart": "アプリを再起動する必要があります",
"net": "ネットワーク",
"netViewType": "ネットワークビュータイプ",
"newContainer": "新しいコンテナを作成",
"noClient": "SSH接続がありません",
"noInterface": "使用可能なインターフェースがありません",
"noLineChart": "折れ線グラフを使用しない",
"noNotiPerm": "通知の権限がないため、アプリの更新のダウンロード中に進行状況が表示されない場合があります。",
"noOptions": "選択肢がありません",
"noPrivateKeyTip": "私有鍵が存在しません。削除されたか、設定ミスがある可能性があります。",
"noLineChartForCpu": "CPUに折れ線グラフを使わない",
"noPrivateKeyTip": "秘密鍵が存在しません。削除されたか、設定ミスがある可能性があります。",
"noPromptAgain": "再度確認しない",
"noResult": "結果なし",
"noSavedPrivateKey": "保存されたプライベートキーがありません。",
"noSavedSnippet": "保存されたスニペットがありません。",
"noServerAvailable": "使用可能なサーバーがありません。",
"noTask": "タスクがありません",
"noUpdateAvailable": "利用可能な更新はありません",
"node": "ノード",
"notAvailable": "利用不可",
"notSelected": "選択されていません",
"note": "メモ",
"nullToken": "トークンなし",
"ok": "OK",
"onServerDetailPage": "サーバーの詳細ページで",
"onlyOneLine": "一行のみ表示(スクロール可能)",
"onlyWhenCoreBiggerThan8": "コア数が8より大きい場合にのみ有効",
"open": "開く",
"openLastPath": "最後のパスを開く",
"openLastPathTip": "異なるサーバーには異なる記録があり、記録されているのは退出時のパスです",
"parseContainerStats": "コンテナ使用状況を解析",
"parseContainerStatsTip": "Dockerの使用状況の解析は比較的遅いです",
"paste": "貼り付け",
"path": "パス",
"percentOfSize": "{size} の {percent}%",
"pickFile": "ファイルを選択",
"permission": "権限",
"pingAvg": "平均:",
"pingInputIP": "対象のIPまたはドメインを入力してください",
"pingNoServer": "Pingに使用するサーバーがありません\nサーバータブでサーバーを追加してから再試行してください",
"pkg": "パッケージ管理",
"pkgUpgradeTip": "アップデートする前にシステムのバックアップを取ってください。",
"platformNotSupportUpdate": "現在のプラットフォームは更新をサポートしていません。最新のソースコードをコンパイルして手動でインストールしてください",
"plugInType": "挿入タイプ",
"plzEnterHost": "ホストを入力してください",
"plzSelectKey": "プライベートキーを選択してください",
"port": "ポート",
"preview": "プレビュー",
"primaryColorSeed": "プライマリーカラーシード",
"privateKey": "プライベートキー",
"privateKey": "秘密鍵",
"process": "プロセス",
"pushToken": "プッシュトークン",
"pveIgnoreCertTip": "オプションを有効にすることは推奨されません、セキュリティリスクに注意してくださいPVEのデフォルト証明書を使用している場合は、このオプションを有効にする必要があります。",
@@ -227,15 +133,11 @@
"pwd": "パスワード",
"read": "読み取り",
"reboot": "再起動",
"rememberChoice": "選択を記憶する",
"rememberPwdInMem": "メモリにパスワードを記憶する",
"rememberPwdInMemTip": "コンテナ、一時停止などに使用されます。",
"rememberWindowSize": "ウィンドウサイズを記憶する",
"remotePath": "リモートパス",
"rename": "名前を変更",
"reportBugsOnGithubIssue": "{url}で問題を報告してください",
"restart": "再開",
"restore": "復元",
"restoreSuccess": "復元に成功しました。変更を適用するためにアプリを再起動する必要があります",
"result": "結果",
"rotateAngel": "回転角度",
"route": "ルーティング",
@@ -250,14 +152,8 @@
"serverDetailOrder": "詳細ページのウィジェット順序",
"serverFuncBtns": "サーバー機能ボタン",
"serverOrder": "サーバー順序",
"serverTabConnecting": "接続中...",
"serverTabEmpty": "現在サーバーはありません。\n右下のボタンをクリックして追加してください。",
"serverTabFailed": "失敗",
"serverTabLoading": "読み込み中...",
"serverTabPlzSave": "このプライベートキーを再保存してください",
"serverTabUnkown": "不明な状態",
"setting": "設定",
"sftpDlPrepare": "サーバーへの接続を準備中...",
"sftpEditorTip": "空の場合は、アプリ内蔵のファイルエディタを使用します。値がある場合は、リモートサーバーのエディタ(例:`vim`)を使用します(`EDITOR` に従って自動検出することをお勧めします)。",
"sftpRmrDirSummary": "SFTPで`rm -r`を使用してフォルダーを削除",
"sftpSSHConnected": "SFTPに接続されました...",
"sftpShowFoldersFirst": "フォルダーを先に表示",
@@ -272,11 +168,11 @@
"sshTip": "この機能は現在テスト段階にあります。\n\n問題がある場合は、{url}でフィードバックしてください。",
"sshVirtualKeyAutoOff": "仮想キーの自動オフ",
"start": "開始",
"stat": "統計",
"stats": "統計",
"stop": "停止",
"stopped": "停止しました",
"storage": "ストレージ",
"success": "成功",
"supportFmtArgs": "以下のフォーマット引数がサポートされています:",
"suspend": "中断",
"suspendTip": "suspend機能はroot権限とsystemdのサポートが必要です。",
@@ -292,7 +188,6 @@
"textScaler": "テキストスケーラー",
"textScalerTip": "1.0 => 100%(デフォルトサイズ)。サーバーページの一部のテキストにのみ適用されます。変更をお勧めしません。",
"theme": "テーマ",
"themeMode": "テーマモード",
"time": "時間",
"times": "回",
"total": "合計",
@@ -300,27 +195,18 @@
"trySudo": "sudoを試みる",
"ttl": "TTL",
"unknown": "不明",
"unknownError": "未知のエラー",
"unkownConvertMode": "未知の変換モード",
"update": "更新",
"updateAll": "すべて更新",
"updateIntervalEqual0": "0に設定すると、サーバーの状態は自動的に更新されず、CPU使用率も計算できません。",
"updateServerStatusInterval": "サーバー状態の更新間隔",
"updateTip": "新バージョン: v1.0.{newest}",
"updateTipTooLow": "現在のバージョンが古すぎます。v1.0.{newest}にアップグレードしてください",
"upload": "アップロード",
"upsideDown": "上下逆転",
"uptime": "稼働時間",
"urlOrJson": "URLまたはJSON",
"useCdn": "CDNの使用",
"useCdnTip": "中国以外のユーザーにはCDNの使用が推奨されています。ご利用しますか",
"useNoPwd": "パスワードなしで使用します",
"usePodmanByDefault": "デフォルトでPodmanを使用",
"used": "使用済み",
"user": "ユーザー",
"versionHaveUpdate": "新しいバージョンが見つかりましたv1.0.{build}、クリックして更新",
"versionUnknownUpdate": "現在v1.0.{build}、更新をチェックするためにクリック",
"versionUpdated": "現在v1.0.{build}、最新バージョンです",
"view": "ビュー",
"viewErr": "エラーを表示",
"virtKeyHelpClipboard": "端末に選択された文字がある場合は、選択された文字をクリップボードにコピーします。そうでない場合は、クリップボードの内容を端末に貼り付けます。",
@@ -331,8 +217,8 @@
"watchNotPaired": "ペアリングされたApple Watchがありません",
"webdavSettingEmpty": "Webdavの設定が空です",
"whenOpenApp": "アプリを開くとき",
"willTakEeffectImmediately": "変更は即座に有効になります",
"wolTip": "WOLWake-on-LANを設定した後、サーバーに接続するたびにWOLリクエストが送信されます。",
"write": "書き込み",
"writeScriptFailTip": "スクリプトの書き込みに失敗しました。権限がないかディレクトリが存在しない可能性があります。"
"writeScriptFailTip": "スクリプトの書き込みに失敗しました。権限がないかディレクトリが存在しない可能性があります。",
"writeScriptTip": "サーバーに接続すると、システムの状態を監視するためのスクリプトが ~/.config/server_box に書き込まれます。スクリプトの内容を確認できます。"
}

View File

@@ -1,87 +1,42 @@
{
"@@locale": "nl",
"about": "Over",
"aboutThanks": "Met dank aan de volgende mensen die hebben deelgenomen aan.",
"acceptBeta": "Accepteer testversie-updates",
"add": "Toevoegen",
"addAServer": "een server toevoegen",
"addPrivateKey": "Privésleutel toevoegen",
"addSystemPrivateKeyTip": "Er is momenteel geen privésleutel, wilt u degene toevoegen die bij het systeem wordt geleverd (~/.ssh/id_rsa)?",
"added2List": "Toegevoegd aan takenlijst",
"addr": "Adres",
"all": "Alle",
"alreadyLastDir": "Al in de laatst gebruikte map.",
"alterUrl": "Url wijzigen",
"askContinue": "{msg}. Doorgaan?",
"attention": "Let op",
"authFailTip": "Authenticatie mislukt, controleer of het wachtwoord/sleutel/host/gebruiker, enz., incorrect zijn.",
"authRequired": "Authenticatie vereist",
"auto": "Auto",
"autoBackupConflict": "Er kan slechts één automatische back-up tegelijk worden ingeschakeld.",
"autoCheckUpdate": "Automatisch controleren op update",
"autoConnect": "Automatisch verbinden",
"autoRun": "Automatisch uitvoeren",
"autoUpdateHomeWidget": "Automatische update van home-widget",
"backup": "Back-up",
"backupTip": "De geëxporteerde gegevens zijn simpelweg versleuteld. \nBewaar deze aub veilig.",
"backupVersionNotMatch": "Back-upversie komt niet overeen.",
"battery": "Batterij",
"bgRun": "Uitvoeren op de achtergrond",
"bgRunTip": "Deze schakelaar betekent alleen dat het programma zal proberen op de achtergrond uit te voeren, of het in de achtergrond kan worden uitgevoerd, hangt af van of de toestemming is ingeschakeld of niet. Voor native Android, schakel \"Batterijoptimalisatie\" uit in deze app, en voor miui, wijzig de energiebesparingsbeleid naar \"Onbeperkt\".",
"bioAuth": "Biometrische authenticatie",
"browser": "Browser",
"bulkImportServers": "Servers batchgewijs importeren",
"bulkImportServersTip": "U kunt het [formaat]({url}) hier vinden.",
"canPullRefresh": "Je kunt verversen door te slepen.",
"cancel": "Annuleren",
"choose": "Kiezen",
"chooseFontFile": "Kies een font bestand",
"choosePrivateKey": "Privésleutel kiezen",
"clear": "Wissen",
"clipboard": "Klembord",
"close": "Sluiten",
"cmd": "Opdracht",
"cnKeyboardComp": "Compatibiliteit met Chinese Android",
"cnKeyboardCompTip": "Als de terminal een beveiligd toetsenbord weergeeft, kunt u dit inschakelen.",
"collapseUI": "Inklappen",
"collapseUITip": "Of lange lijsten in de UI standaard moeten worden ingeklapt",
"collectUsage": "Gebruiksinformatie verzamelen (niet gerelateerd aan privacy).",
"conn": "Verbinding",
"connected": "Verbonden",
"container": "Container",
"containerName": "Container naam",
"containerStatus": "Containerstatus",
"containerTrySudoTip": "Bijvoorbeeld: in de app is de gebruiker ingesteld op aaa, maar Docker is geïnstalleerd onder de rootgebruiker. In dit geval moet u deze optie inschakelen.",
"content": "Inhoud",
"convert": "Converteren",
"copy": "Kopiëren",
"copyPath": "Pad kopiëren",
"cpuViewAsProgressTip": "Toon het gebruik van elke CPU in een voortgangsbalkstijl (oude stijl)",
"createFile": "Bestand aanmaken",
"createFolder": "Map aanmaken",
"cursorType": "Cursortype",
"customCmd": "Aangepaste opdrachten",
"customCmdDocUrl": "https://github.com/lollipopkit/flutter_server_box/wiki#custom-commands",
"customCmdHint": "\"Opdrachtnaam\": \"Opdracht\"",
"dark": "Donker",
"day": "Dag",
"debug": "Debuggen",
"decode": "Decoderen",
"decompress": "Decomprimeren",
"delete": "Verwijderen",
"deleteScripts": "Verwijder tegelijkertijd serverscripts",
"deleteServers": "Servers batchgewijs verwijderen",
"deviceName": "Apparaatnaam",
"dirEmpty": "Zorg ervoor dat de map leeg is.",
"disabled": "Uitgeschakeld",
"disconnected": "Verbroken",
"disk": "Schijf",
"diskIgnorePath": "Pad negeren voor schijf",
"displayCpuIndex": "Toon de CPU-index",
"displayName": "Weergavenaam",
"dl2Local": "Download {fileName} naar lokaal?",
"doc": "Documentatie",
"dockerEditHost": "DOCKER_HOST bewerken",
"dockerEmptyRunningItems": "Er zijn geen actieve containers.\nDit kan komen doordat:\n- De Docker-installatiegebruiker niet overeenkomt met de gebruikersnaam die is geconfigureerd binnen de app.\n- De omgevingsvariabele DOCKER_HOST is niet correct gelezen. U kunt deze krijgen door `echo $DOCKER_HOST` in de terminal uit te voeren.",
"dockerImagesFmt": "{count} afbeeldingen",
"dockerNotInstalled": "Docker niet geïnstalleerd",
@@ -89,36 +44,24 @@
"dockerStatusRunningFmt": "{count} container actief.",
"doubleColumnMode": "Dubbele kolommodus",
"doubleColumnTip": "Deze optie schakelt alleen de functie in, of deze daadwerkelijk kan worden ingeschakeld, hangt af van de breedte van het apparaat",
"download": "Downloaden",
"edit": "Bewerken",
"editVirtKeys": "Virtuele toetsen bewerken",
"editor": "Editor",
"editorHighlightTip": "De huidige codehighlighting-prestaties zijn slechter en kunnen optioneel worden uitgeschakeld om te verbeteren.",
"encode": "Coderen",
"error": "Fout",
"exampleName": "Voorbeeldnaam",
"envVars": "Omgevingsvariabele",
"experimentalFeature": "Experimentele functie",
"export": "Exporteren",
"extraArgs": "Extra argumenten",
"failed": "Mislukt",
"feedback": "Feedback",
"feedbackOnGithub": "Als je vragen hebt, geef dan feedback op Github.",
"fieldMustNotEmpty": "Deze velden mogen niet leeg zijn.",
"fileNotExist": "{file} bestaat niet",
"fallbackSshDest": "Fallback SSH-bestemming",
"fdroidReleaseTip": "Als u deze app van F-Droid heeft gedownload, wordt aanbevolen deze optie uit te schakelen.",
"fileTooLarge": "Bestand '{file}' te groot {size}, max {sizeMax}",
"files": "Bestanden",
"finished": "Voltooid",
"followSystem": "Volg systeem",
"font": "Lettertype",
"fontSize": "Lettergrootte",
"force": "Forceer",
"foundNUpdate": "{count} update gevonden",
"fullScreen": "Volledig schermmodus",
"fullScreenJitter": "Volledig scherm trilling",
"fullScreenJitterHelp": "Om inbranden van het scherm te voorkomen",
"fullScreenTip": "Moet de volledig schermmodus worden ingeschakeld wanneer het apparaat naar de liggende modus wordt gedraaid? Deze optie is alleen van toepassing op het servertabblad.",
"getPushTokenFailed": "Kan push-token niet ophalen",
"gettingToken": "Token ophalen...",
"goBackQ": "Terug gaan?",
"goto": "Ga naar",
"hideTitleBar": "Titelbalk verbergen",
@@ -126,37 +69,24 @@
"highlight": "Code-highlight",
"homeWidgetUrlConfig": "Home-widget-url configureren",
"host": "Host",
"hour": "Uur",
"httpFailedWithCode": "verzoek mislukt, statuscode: {code}",
"icloudSynced": "iCloud wordt gesynchroniseerd en sommige instellingen vereisen mogelijk een herstart van de app om van kracht te worden.",
"ignoreCert": "Certificaat negeren",
"image": "Afbeelding",
"imagesList": "Lijst met afbeeldingen",
"import": "Importeren",
"inAppUpdate": "Bijwerken binnen de app? Anders downloaden via een browser.",
"init": "Initialiseren",
"inner": "Intern",
"inputDomainHere": "Voer hier domein in",
"install": "Installeren",
"installDockerWithUrl": "Installeer eerst docker via https://docs.docker.com/engine/install.",
"invalid": "Ongeldig",
"invalidJson": "Ongeldige JSON",
"invalidVersion": "Ongeldige versie",
"invalidVersionHelp": "Zorg ervoor dat docker correct is geïnstalleerd, of dat u een niet-zelf-gecompileerde versie gebruikt. Als dat niet het geval is, meld dan een probleem op {url}.",
"isBusy": "Is momenteel bezig",
"jumpServer": "Spring naar server",
"keepForeground": "Houd de app op de voorgrond!",
"keepStatusWhenErr": "Behoud de laatste serverstatus",
"keepStatusWhenErrTip": "Alleen in geval van een fout tijdens de scriptuitvoering",
"keyAuth": "Sleutelauthenticatie",
"language": "Taal",
"languageName": "Nederlands",
"lastTry": "Laatste poging",
"launchPage": "Startpagina",
"letterCache": "Lettercaching",
"letterCacheTip": "Aanbevolen om uit te schakelen, maar na het uitschakelen is het niet mogelijk om CJK-tekens in te voeren.",
"license": "Licentie",
"light": "Licht",
"loadingFiles": "Bestanden laden...",
"location": "Locatie",
"log": "Logboek",
"loss": "verlies",
"madeWithLove": "Gemaakt met ❤️ door {myGithub}",
"manual": "Handleiding",
@@ -164,59 +94,36 @@
"maxRetryCount": "Aantal serverherverbindingen",
"maxRetryCountEqual0": "Zal opnieuw blijven proberen.",
"min": "min",
"minute": "Minuut",
"mission": "Missie",
"more": "Meer",
"moveOutServerFuncBtnsHelp": "Aan: kan worden weergegeven onder elke kaart op de Server-tabbladpagina. Uit: kan worden weergegeven bovenaan de Serverdetails-pagina.",
"ms": "ms",
"name": "Naam",
"needHomeDir": "Als u een Synology-gebruiker bent, [zie hier](https://kb.synology.com/DSM/tutorial/user_enable_home_service). Gebruikers van andere systemen moeten zoeken hoe ze een home directory kunnen creëren.",
"needRestart": "App moet opnieuw worden gestart",
"net": "Netwerk",
"netViewType": "Netweergavetype",
"newContainer": "Nieuwe container",
"noClient": "Geen client",
"noInterface": "Geen interface",
"noNotiPerm": "Geen meldingsmachtigingen, mogelijk geen voortgangsindicatie bij het downloaden van app-updates.",
"noOptions": "Geen opties",
"noLineChart": "lijndiagrammen gebruiken",
"noLineChartForCpu": "Gebruik geen lijndiagrammen voor CPU",
"noPrivateKeyTip": "De privésleutel bestaat niet, deze is mogelijk verwijderd of er is een configuratiefout.",
"noPromptAgain": "Niet meer vragen",
"noResult": "Geen resultaat",
"noSavedPrivateKey": "Geen opgeslagen privésleutels.",
"noSavedSnippet": "Geen opgeslagen fragmenten.",
"noServerAvailable": "Geen server beschikbaar.",
"noTask": "Geen taak",
"noUpdateAvailable": "Geen update beschikbaar",
"node": "Node",
"notAvailable": "Niet beschikbaar",
"notSelected": "Niet geselecteerd",
"note": "Opmerking",
"nullToken": "Null-token",
"ok": "OK",
"onServerDetailPage": "Op serverdetailspagina",
"onlyOneLine": "Alleen als één regel weergeven (scrollbaar)",
"onlyWhenCoreBiggerThan8": "Alleen effectief wanneer het aantal cores > 8",
"open": "Openen",
"openLastPath": "Open het laatste pad",
"openLastPathTip": "Verschillende servers hebben verschillende logs, en de log is het pad naar de uitgang",
"parseContainerStats": "Parseer de containerbezettingstatus",
"parseContainerStatsTip": "Het parsen van de bezettingsstatus van Docker is relatief langzaam.",
"paste": "Plakken",
"path": "Pad",
"percentOfSize": "{percent}% van {size}",
"pickFile": "Bestand kiezen",
"permission": "Machtigingen",
"pingAvg": "Gem:",
"pingInputIP": "Voer een doel-IP / domein in.",
"pingNoServer": "Geen server om te pingen.\nVoeg een server toe in het servertabblad.",
"pkg": "Pkg",
"pkgUpgradeTip": "Maak een back-up van uw systeem voordat u een update uitvoert.",
"platformNotSupportUpdate": "Huidig platform ondersteunt geen updates in de app.\nBouw het alstublieft uit bron en installeer het.",
"plugInType": "Invoegingstype",
"plzEnterHost": "Voer host in a.u.b.",
"plzSelectKey": "Selecteer a.u.b. een sleutel.",
"port": "Poort",
"preview": "Voorbeeld",
"primaryColorSeed": "Basis kleurzaad",
"privateKey": "Privésleutel",
"process": "Proces",
"pushToken": "Push-token",
@@ -226,15 +133,11 @@
"pwd": "Wachtwoord",
"read": "Lezen",
"reboot": "Herstart",
"rememberChoice": "Selectie onthouden",
"rememberPwdInMem": "Wachtwoord onthouden in geheugen",
"rememberPwdInMemTip": "Gebruikt voor containers, opschorting, enz.",
"rememberWindowSize": "Venstergrootte onthouden",
"remotePath": "Extern pad",
"rename": "Hernoemen",
"reportBugsOnGithubIssue": "Meld alstublieft bugs op {url}",
"restart": "Herstarten",
"restore": "Herstellen",
"restoreSuccess": "Herstellen geslaagd. App herstarten om toe te passen.",
"result": "Resultaat",
"rotateAngel": "Rotatiehoek",
"route": "Route",
@@ -249,14 +152,8 @@
"serverDetailOrder": "Volgorde van widget op detailpagina",
"serverFuncBtns": "Server functieknoppen",
"serverOrder": "Servervolgorde",
"serverTabConnecting": "Verbinding maken...",
"serverTabEmpty": "Er is geen server.\nKlik op fab om er een toe te voegen.",
"serverTabFailed": "Mislukt",
"serverTabLoading": "Laden...",
"serverTabPlzSave": "Sla deze privésleutel opnieuw op.",
"serverTabUnkown": "Onbekende status",
"setting": "Instellingen",
"sftpDlPrepare": "Voorbereiden om verbinding te maken...",
"sftpEditorTip": "Indien leeg, gebruik de ingebouwde bestandseditor van de app. Indien een waarde aanwezig is, gebruik de editor van de externe server, bijvoorbeeld `vim` (aanbevolen om automatisch te detecteren volgens `EDITOR`).",
"sftpRmrDirSummary": "Gebruik `rm -r` om een map te verwijderen in SFTP.",
"sftpSSHConnected": "SFTP Verbonden",
"sftpShowFoldersFirst": "Mappen eerst weergeven",
@@ -271,11 +168,11 @@
"sshTip": "Deze functie bevindt zich momenteel in de experimentele fase.\n\nMeld alstublieft bugs op {url} of sluit je aan bij onze ontwikkeling.",
"sshVirtualKeyAutoOff": "Automatisch schakelen van virtuele toetsen",
"start": "Starten",
"stat": "Statistieken",
"stats": "Statistieken",
"stop": "Stoppen",
"stopped": "Gestopt",
"storage": "Opslag",
"success": "Succes",
"supportFmtArgs": "De volgende opmaakparameters worden ondersteund:",
"suspend": "Ophangen",
"suspendTip": "De opschortfunctie vereist rootrechten en systemd-ondersteuning.",
@@ -291,35 +188,25 @@
"textScaler": "Tekstschaler",
"textScalerTip": "1.0 => 100% (oorspronkelijke grootte), werkt alleen op het gedeelte van de serverpagina van het lettertype, niet aanbevolen om te wijzigen.",
"theme": "Thema",
"themeMode": "Themamodus",
"time": "Tijd",
"times": "Keer",
"total": "Totaal",
"traffic": "Verkeer",
"trySudo": "Probeer sudo te gebruiken",
"ttl": "ttl",
"ttl": "TTL",
"unknown": "Onbekend",
"unknownError": "Onbekende fout",
"unkownConvertMode": "Onbekende conversiemodus",
"update": "Bijwerken",
"updateAll": "Alles bijwerken",
"updateIntervalEqual0": "Het staat op 0, het zal niet automatisch bijwerken\nCPU status kan niet berekend worden.",
"updateServerStatusInterval": "Interne server status bijwerking interval",
"updateTip": "Bijwerking: v1.0.{newest}",
"updateTipTooLow": "Huidige versie is te oud, werk aub bij naar versie v1.0.{newest}",
"upload": "Upload",
"upsideDown": "Ondersteboven",
"uptime": "Uptime",
"urlOrJson": "URL of JSON",
"useCdn": "Gebruikt CDN",
"useCdnTip": "Niet-chinese gebruikers worden aangeraden om deze CDN te gebruiken. Wil je dat?",
"useNoPwd": "Er zal geen wachtwoord gebruikt worden",
"usePodmanByDefault": "Valt terug op Podman",
"used": "Gebruikt",
"user": "Gebruiker",
"versionHaveUpdate": "Gevonden: v1.0.{build}, klik om bij te werken",
"versionUnknownUpdate": "Huidig: v1.0.{build}, klik om te kijken naar een nieuwere versie",
"versionUpdated": "Huidig: v1.0.{build}, is bijgewerkt naar de laatste versie",
"view": "Weergave",
"viewErr": "Zie foutmelding",
"virtKeyHelpClipboard": "Kopiëren naar het klembord als de geselecteerde terminal niet leeg is, anders de inhoud van het klembord plakken in de terminal.",
@@ -330,8 +217,8 @@
"watchNotPaired": "Geen gekoppelde Apple Watch",
"webdavSettingEmpty": "Webdav-instelling is leeg",
"whenOpenApp": "Bij het openen van de app",
"willTakEeffectImmediately": "Zal onmiddellijk van kracht worden",
"wolTip": "Na het configureren van WOL (Wake-on-LAN), wordt elke keer dat de server wordt verbonden een WOL-verzoek verzonden.",
"write": "Schrijven",
"writeScriptFailTip": "Het schrijven naar het script is mislukt, mogelijk door gebrek aan rechten of omdat de map niet bestaat."
"writeScriptFailTip": "Het schrijven naar het script is mislukt, mogelijk door gebrek aan rechten of omdat de map niet bestaat.",
"writeScriptTip": "Na het verbinden met de server wordt een script geschreven naar ~/.config/server_box om de systeemstatus te monitoren. U kunt de inhoud van het script controleren."
}

View File

@@ -1,87 +1,42 @@
{
"@@locale": "pt",
"about": "Sobre",
"aboutThanks": "Agradecimentos a todos os participantes.",
"acceptBeta": "Aceitar atualizações da versão de teste",
"add": "Adicionar",
"addAServer": "Adicionar um servidor",
"addPrivateKey": "Adicionar uma chave privada",
"addSystemPrivateKeyTip": "Atualmente, não há nenhuma chave privada. Gostaria de adicionar a chave do sistema (~/.ssh/id_rsa)?",
"added2List": "Adicionado à lista de tarefas",
"addr": "Endereço",
"all": "Todos",
"alreadyLastDir": "Já é o diretório mais alto",
"alterUrl": "URL alternativa",
"askContinue": "{msg}, continuar?",
"attention": "Atenção",
"authFailTip": "Autenticação falhou, por favor verifique se a senha/chave/host/usuário, etc., estão incorretos.",
"authRequired": "Autenticação necessária",
"auto": "Automático",
"autoBackupConflict": "Apenas um backup automático pode ser ativado por vez",
"autoCheckUpdate": "Verificação automática de atualização",
"autoConnect": "Conexão automática",
"autoRun": "Execução automática",
"autoUpdateHomeWidget": "Atualização automática do widget da tela inicial",
"backup": "Backup",
"backupTip": "Os dados exportados são criptografados de forma simples, por favor, guarde-os com segurança.",
"backupVersionNotMatch": "Versão de backup não compatível, não é possível restaurar",
"battery": "Bateria",
"bgRun": "Execução em segundo plano",
"bgRunTip": "Este interruptor indica que o programa tentará rodar em segundo plano, mas a capacidade de fazer isso depende das permissões concedidas. No Android nativo, desative a 'Otimização de bateria' para este app, no MIUI, altere a estratégia de economia de energia para 'Sem restrições'.",
"bioAuth": "Autenticação biométrica",
"browser": "Navegador",
"bulkImportServers": "Importar servidores em lote",
"bulkImportServersTip": "Você pode encontrar o [formato]({url}) aqui.",
"canPullRefresh": "Pode puxar para atualizar",
"cancel": "Cancelar",
"choose": "Escolher",
"chooseFontFile": "Escolher arquivo de fonte",
"choosePrivateKey": "Escolher chave privada",
"clear": "Limpar",
"clipboard": "Área de transferência",
"close": "Fechar",
"cmd": "Comando",
"cnKeyboardComp": "Compatibilidade com Android chinês",
"cnKeyboardCompTip": "Se o terminal abrir um teclado seguro, você pode ativá-lo.",
"collapseUI": "Colapsar",
"collapseUITip": "Deve colapsar listas longas na UI por padrão?",
"collectUsage": "Coletar informações de uso (não relacionadas à privacidade).",
"conn": "Conectar",
"connected": "Conectado",
"container": "Contêiner",
"containerName": "Nome do contêiner",
"containerStatus": "Estado do contêiner",
"containerTrySudoTip": "Por exemplo: se o usuário for definido como aaa dentro do app, mas o Docker estiver instalado sob o usuário root, esta opção precisará ser ativada",
"content": "Conteúdo",
"convert": "Converter",
"copy": "Copiar",
"copyPath": "Copiar caminho",
"cpuViewAsProgressTip": "Exiba a taxa de uso de cada CPU em estilo de barra de progresso (estilo antigo)",
"createFile": "Criar arquivo",
"createFolder": "Criar pasta",
"cursorType": "Tipo de cursor",
"customCmd": "Comandos personalizados",
"customCmdDocUrl": "https://github.com/lollipopkit/flutter_server_box/wiki#custom-commands",
"customCmdHint": "\"Nome do comando\": \"Comando\"",
"dark": "Escuro",
"day": "Dia",
"debug": "Debugar",
"decode": "Decodificar",
"decompress": "Descomprimir",
"delete": "Excluir",
"deleteScripts": "Excluir scripts do servidor simultaneamente",
"deleteServers": "Excluir servidores em lote",
"deviceName": "Nome do dispositivo",
"dirEmpty": "Certifique-se de que a pasta está vazia",
"disabled": "Desativado",
"disconnected": "Desconectado",
"disk": "Disco",
"diskIgnorePath": "Caminhos de disco ignorados",
"displayCpuIndex": "Exiba o índice de CPU",
"displayName": "Nome de exibição",
"dl2Local": "Baixar {fileName} para o local?",
"doc": "Documentação",
"dockerEditHost": "Editar DOCKER_HOST",
"dockerEmptyRunningItems": "Não há contêineres em execução.\nIsso pode ser porque:\n- O usuário que instalou o Docker difere do usuário configurado no app\n- A variável de ambiente DOCKER_HOST não foi lida corretamente. Você pode verificar isso executando `echo $DOCKER_HOST` no terminal.",
"dockerImagesFmt": "Total de {count} imagens",
"dockerNotInstalled": "Docker não instalado",
@@ -89,36 +44,24 @@
"dockerStatusRunningFmt": "{count} contêiner(es) em execução",
"doubleColumnMode": "Modo de coluna dupla",
"doubleColumnTip": "Esta opção apenas ativa a funcionalidade, se ela será ativada depende também da largura do dispositivo",
"download": "Baixar",
"edit": "Editar",
"editVirtKeys": "Editar teclas virtuais",
"editor": "Editor",
"editorHighlightTip": "O desempenho do destaque de código atualmente é ruim, pode optar por desativá-lo para melhorar.",
"encode": "Codificar",
"error": "Erro",
"exampleName": "Exemplo de nome",
"envVars": "Variável de ambiente",
"experimentalFeature": "Recurso experimental",
"export": "Exportar",
"extraArgs": "Argumentos extras",
"failed": "Falhou",
"feedback": "Feedback",
"feedbackOnGithub": "Se você tem qualquer problema, por favor, dê feedback no GitHub",
"fieldMustNotEmpty": "Estes campos não podem estar vazios.",
"fileNotExist": "{file} não existe",
"fallbackSshDest": "Destino SSH de fallback",
"fdroidReleaseTip": "Se você baixou este aplicativo do F-Droid, é recomendado desativar esta opção.",
"fileTooLarge": "Arquivo '{file}' muito grande '{size}', excedendo {sizeMax}",
"files": "Arquivos",
"finished": "Finalizado",
"followSystem": "Seguir sistema",
"font": "Fonte",
"fontSize": "Tamanho da fonte",
"force": "Forçar",
"foundNUpdate": "Encontradas {count} atualizações",
"fullScreen": "Modo tela cheia",
"fullScreenJitter": "Tremulação em tela cheia",
"fullScreenJitterHelp": "Prevenir burn-in de tela",
"fullScreenTip": "Deve ser ativado o modo de tela cheia quando o dispositivo é girado para o modo paisagem? Esta opção aplica-se apenas à aba do servidor.",
"getPushTokenFailed": "Não foi possível obter token de notificação",
"gettingToken": "Obtendo Token...",
"goBackQ": "Voltar?",
"goto": "Ir para",
"hideTitleBar": "Ocultar barra de título",
@@ -126,37 +69,24 @@
"highlight": "Destaque de código",
"homeWidgetUrlConfig": "Configuração de URL do widget da tela inicial",
"host": "Host",
"hour": "Hora",
"httpFailedWithCode": "Falha na solicitação, código de status: {code}",
"icloudSynced": "iCloud sincronizado, algumas configurações podem precisar de reinicialização do app para serem aplicadas.",
"ignoreCert": "Ignorar certificado",
"image": "Imagem",
"imagesList": "Lista de imagens",
"import": "Importar",
"inAppUpdate": "Atualizar dentro do app? Caso contrário, baixe usando um navegador.",
"init": "Inicializar",
"inner": "Interno",
"inputDomainHere": "Insira o domínio aqui",
"install": "Instalar",
"installDockerWithUrl": "Por favor, instale o Docker primeiro em https://docs.docker.com/engine/install",
"invalid": "Inválido",
"invalidJson": "JSON inválido",
"invalidVersion": "Versão não suportada",
"invalidVersionHelp": "Por favor, assegure que o Docker está corretamente instalado, ou que não está usando uma versão compilada por si mesmo. Se não houver problemas, por favor, reporte em {url}.",
"isBusy": "Ocupado no momento",
"jumpServer": "Servidor de salto",
"keepForeground": "Por favor, mantenha o app em primeiro plano!",
"keepStatusWhenErr": "Manter o status anterior do servidor",
"keepStatusWhenErrTip": "Limitado a erros de execução de scripts",
"keyAuth": "Autenticação por chave",
"language": "Idioma",
"languageName": "Português",
"lastTry": "Última tentativa",
"launchPage": "Página de lançamento",
"letterCache": "Cache de letras",
"letterCacheTip": "Recomendado desativar, mas após desativar, será impossível inserir caracteres CJK.",
"license": "Licença de código aberto",
"light": "Claro",
"loadingFiles": "Carregando diretórios...",
"location": "Localização",
"log": "Log",
"loss": "Taxa de perda",
"madeWithLove": "Feito com ❤️ por {myGithub}",
"manual": "Manual",
@@ -164,60 +94,36 @@
"maxRetryCount": "Número de tentativas de reconexão com o servidor",
"maxRetryCountEqual0": "Irá tentar indefinidamente",
"min": "Mínimo",
"minute": "Minuto",
"mission": "Missão",
"more": "Mais",
"moveOutServerFuncBtnsHelp": "Ativado: Mostra abaixo de cada cartão na aba do servidor. Desativado: Mostra no topo da página de detalhes do servidor.",
"ms": "ms",
"name": "Nome",
"needHomeDir": "Se você é usuário de Synology, [veja aqui](https://kb.synology.com/DSM/tutorial/user_enable_home_service). Usuários de outros sistemas precisam pesquisar como criar um diretório home.",
"needRestart": "Necessita reiniciar o app",
"net": "Rede",
"netViewType": "Tipo de visualização de rede",
"newContainer": "Novo contêiner",
"noClient": "Sem conexão SSH",
"noInterface": "Sem interface disponível",
"noLineChart": "Gebruik geen lijndiagrammen",
"noNotiPerm": "Sem permissão de notificação, possivelmente sem indicação de progresso ao baixar atualizações de aplicativos.",
"noOptions": "Sem opções",
"noLineChart": "Não usar gráficos de linha",
"noLineChartForCpu": "Não utilizar gráficos de linhas para a CPU",
"noPrivateKeyTip": "A chave privada não existe, pode ter sido deletada ou há um erro de configuração.",
"noPromptAgain": "Não perguntar novamente",
"noResult": "Sem resultados",
"noSavedPrivateKey": "Nenhuma chave privada salva.",
"noSavedSnippet": "Nenhum snippet de código salvo.",
"noServerAvailable": "Nenhum servidor disponível.",
"noTask": "Sem tarefas",
"noUpdateAvailable": "Sem atualizações disponíveis",
"node": "Nó",
"notAvailable": "Indisponível",
"notSelected": "Não selecionado",
"note": "Nota",
"nullToken": "Token nulo",
"ok": "OK",
"onServerDetailPage": "Na página de detalhes do servidor",
"onlyOneLine": "Exibir apenas como uma linha (rolável)",
"onlyWhenCoreBiggerThan8": "Efetivo apenas quando o número de núcleos > 8",
"open": "Abrir",
"openLastPath": "Abrir o último caminho",
"openLastPathTip": "Registros diferentes para servidores diferentes, e registra o caminho ao sair",
"parseContainerStats": "Analisar status de uso do contêiner",
"parseContainerStatsTip": "Análise de status do Docker pode ser lenta",
"paste": "Colar",
"path": "Caminho",
"percentOfSize": "{percent}% de {size}",
"pickFile": "Escolher arquivo",
"permission": "Permissões",
"pingAvg": "Média:",
"pingInputIP": "Por favor, insira o IP ou domínio alvo",
"pingNoServer": "Nenhum servidor disponível para Ping\nPor favor, adicione um servidor na aba de servidores e tente novamente",
"pkg": "Gerenciamento de pacotes",
"pkgUpgradeTip": "Por favor, faça backup do seu sistema antes de atualizar.",
"platformNotSupportUpdate": "Atualização não suportada na plataforma atual, por favor, instale manualmente a versão mais recente do código-fonte",
"plugInType": "Tipo de Inserção",
"plzEnterHost": "Por favor, insira o host",
"plzSelectKey": "Por favor, selecione uma chave privada",
"port": "Porta",
"preview": "Pré-visualização",
"primaryColorSeed": "Semente da cor primária",
"privateKey": "Chave privada",
"process": "Processo",
"pushToken": "Token de notificação push",
@@ -227,15 +133,11 @@
"pwd": "Senha",
"read": "Leitura",
"reboot": "Reiniciar",
"rememberChoice": "Lembrar da seleção",
"rememberPwdInMem": "Lembrar senha na memória",
"rememberPwdInMemTip": "Usado para contêineres, suspensão, etc.",
"rememberWindowSize": "Lembrar o tamanho da janela",
"remotePath": "Caminho remoto",
"rename": "Renomear",
"reportBugsOnGithubIssue": "Por favor, reporte problemas em {url}",
"restart": "Reiniciar",
"restore": "Restaurar",
"restoreSuccess": "Restauração bem-sucedida, é necessário reiniciar o app para aplicar as mudanças",
"result": "Resultado",
"rotateAngel": "Ângulo de rotação",
"route": "Roteamento",
@@ -250,14 +152,8 @@
"serverDetailOrder": "Ordem dos componentes na página de detalhes do servidor",
"serverFuncBtns": "Botões de função do servidor",
"serverOrder": "Ordem do servidor",
"serverTabConnecting": "Conectando...",
"serverTabEmpty": "Não há servidores no momento.\nClique no botão inferior direito para adicionar um.",
"serverTabFailed": "Falha",
"serverTabLoading": "Carregando...",
"serverTabPlzSave": "Por favor, salve esta chave privada novamente",
"serverTabUnkown": "Estado desconhecido",
"setting": "Configurações",
"sftpDlPrepare": "Preparando para conectar ao servidor...",
"sftpEditorTip": "Se vazio, use o editor de arquivos integrado do aplicativo. Se houver um valor, use o editor do servidor remoto, por exemplo, `vim` (recomendado detectar automaticamente de acordo com `EDITOR`).",
"sftpRmrDirSummary": "Usar `rm -r` em SFTP para excluir pastas",
"sftpSSHConnected": "SFTP conectado...",
"sftpShowFoldersFirst": "Mostrar pastas primeiro",
@@ -272,11 +168,11 @@
"sshTip": "Esta funcionalidade está em fase de teste.\n\nPor favor, reporte problemas em {url} ou junte-se a nós no desenvolvimento.",
"sshVirtualKeyAutoOff": "Desativação automática das teclas virtuais",
"start": "Iniciar",
"stat": "Estatísticas",
"stats": "Estatísticas",
"stop": "Parar",
"stopped": "Parado",
"storage": "Armazenamento",
"success": "Sucesso",
"supportFmtArgs": "Suporta os seguintes argumentos formatados:",
"suspend": "Suspender",
"suspendTip": "A função de suspensão requer permissões de root e suporte do systemd.",
@@ -292,35 +188,25 @@
"textScaler": "Escala de texto",
"textScalerTip": "1.0 => 100% (tamanho original), afeta apenas algumas fontes na página do servidor, não é recomendado alterar.",
"theme": "Tema",
"themeMode": "Modo do tema",
"time": "Tempo",
"times": "Vezes",
"total": "Total",
"traffic": "Tráfego",
"trySudo": "Tentar usar sudo",
"ttl": "Tempo de vida do cache",
"ttl": "TTL",
"unknown": "Desconhecido",
"unknownError": "Erro desconhecido",
"unkownConvertMode": "Modo de conversão desconhecido",
"update": "Atualizar",
"updateAll": "Atualizar tudo",
"updateIntervalEqual0": "Se definido como 0, o estado do servidor não será atualizado automaticamente.\nE o uso da CPU não poderá ser calculado.",
"updateServerStatusInterval": "Intervalo de atualização do estado do servidor",
"updateTip": "Nova versão: v1.0.{newest}",
"updateTipTooLow": "Versão atual muito antiga, por favor, atualize para v1.0.{newest}",
"upload": "Upload",
"upsideDown": "Inverter verticalmente",
"uptime": "Tempo de atividade",
"urlOrJson": "URL ou JSON",
"useCdn": "Utilizando CDN",
"useCdnTip": "Recomenda-se que usuários não chineses usem CDN. Gostaria de usá-lo?",
"useNoPwd": "Será usado sem senha",
"usePodmanByDefault": "Usar Podman por padrão",
"used": "Usado",
"user": "Usuário",
"versionHaveUpdate": "Nova versão encontrada: v1.0.{build}, clique para atualizar",
"versionUnknownUpdate": "Versão atual: v1.0.{build}, clique para verificar atualizações",
"versionUpdated": "Versão atual: v1.0.{build}, já está atualizado",
"view": "Visualização",
"viewErr": "Ver erro",
"virtKeyHelpClipboard": "Se houver texto selecionado no terminal, copia para a área de transferência, caso contrário, cola o conteúdo da área de transferência no terminal.",
@@ -331,8 +217,8 @@
"watchNotPaired": "Não há Apple Watch pareado",
"webdavSettingEmpty": "Configurações de Webdav estão vazias",
"whenOpenApp": "Ao abrir o app",
"willTakEeffectImmediately": "As alterações serão aplicadas imediatamente",
"wolTip": "Após configurar o WOL (Wake-on-LAN), um pedido de WOL é enviado cada vez que o servidor é conectado.",
"write": "Escrita",
"writeScriptFailTip": "Falha ao escrever no script, possivelmente devido à falta de permissões ou o diretório não existe."
"writeScriptFailTip": "Falha ao escrever no script, possivelmente devido à falta de permissões ou o diretório não existe.",
"writeScriptTip": "Após conectar ao servidor, um script será escrito em ~/.config/server_box para monitorar o status do sistema. Você pode revisar o conteúdo do script."
}

Some files were not shown because too many files have changed in this diff Show More