Skip to content

Commit 4f6e8e5

Browse files
author
root
committed
improve i18n
1 parent 82b0be5 commit 4f6e8e5

154 files changed

Lines changed: 12470 additions & 3412 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Note.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,10 @@ onlyoffice 存放在哪里的问题
130130

131131
assets memory
132132

133+
## Tests
134+
135+
1. tests/e2e/fixtures/appos.ts 的真实资源 helper
136+
2. 第一批 server / connector / smtp 的 acceptance 用例
137+
138+
登录页增加一个背景图片
139+

specs/implementation-artifacts/epic37-storage.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,10 @@ The adapter layer should own:
106106
- mapping root/path semantics that are not simple backend options
107107
- backend-specific overrides when AppOS intentionally narrows the surface
108108

109+
Secret classification must remain an AppOS policy decision.
110+
111+
`fs.Option` sensitivity metadata is an input, not the final authority for whether a field belongs in AppOS Secrets.
112+
109113
Decision:
110114

111115
- `fs.Option` is the upstream schema source
@@ -128,6 +132,12 @@ This gives AppOS a practical balance:
128132
- stable AppOS-facing contracts
129133
- explicit room to hide, rename, or constrain fields when product needs differ from backend flexibility
130134

135+
For MVP, this adapter should stay intentionally narrow.
136+
137+
- do not attempt full runtime projection of every `rclone` backend into a user-facing form system
138+
- start with curated support for `s3`, `r2`, and `sftp`
139+
- treat `r2` as a product preset on top of the `s3` backend family, not as a separate execution model
140+
131141
## Secret Delivery and Execution Boundary
132142

133143
AppOS secrets remain the source of truth for credential material.
@@ -147,6 +157,11 @@ Execution direction:
147157
- pass cancellation and timeout control through AppOS-managed context boundaries
148158
- map backend errors into stable AppOS operation errors and status phases
149159

160+
For SFTP authentication:
161+
162+
- prefer in-memory secret injection paths such as raw key content when supported by the backend
163+
- use temporary key files only as a compatibility fallback, not as the primary design
164+
150165
If a backend requires temporary files for execution, such as an SSH private key file for a specific auth path, the file must be:
151166

152167
- created under AppOS-managed runtime paths
@@ -168,6 +183,12 @@ Implications:
168183
- AppOS owns retries, cancellation semantics, timeout policy, and progress projection into operation logs/status
169184
- `rclone` is a blocking execution dependency inside an AppOS-managed job, not a competing job system
170185

186+
MVP simplification:
187+
188+
- keep async execution for directory-level or long-running sync work
189+
- prefer synchronous request/stream handling for connection tests, browse/list, and simple single-file transfer paths when feasible
190+
- do not require detailed real-time transfer progress as an MVP blocker
191+
171192
## Product Guardrails
172193

173194
To keep the integration maintainable:
@@ -199,13 +220,19 @@ Phase 1 should stay intentionally small:
199220
- top-level `storage` resource family
200221
- template-driven backend definitions for `s3`, `r2`, and `sftp`
201222
- credential-backed connection configuration
223+
- limited MVP auth modes: access key + secret key for `s3`/`r2`; password or private key for `sftp`
202224
- `test connection`
203225
- `list files`
204226
- `upload`
205227
- `download`
206228
- async `sync`
207229
- operation status and basic logs
208230

231+
MVP path semantics:
232+
233+
- AppOS exposes paths relative to the configured storage root
234+
- backend-specific root semantics such as bucket or base path are absorbed by the adapter layer
235+
209236
## Out of Scope
210237

211238
- mount as a core phase-1 capability

web/dist/index.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@
55
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
77
<title>dashboard</title>
8-
<script type="module" crossorigin src="/assets/index-He8RwnCj.js"></script>
8+
<script type="module" crossorigin src="/assets/index-Dx80lPGM.js"></script>
99
<link rel="modulepreload" crossorigin href="/assets/monaco-vendor-w6PwaWGP.js">
1010
<link rel="modulepreload" crossorigin href="/assets/react-vendor-CyLYFFU7.js">
1111
<link rel="modulepreload" crossorigin href="/assets/tanstack-vendor-16w7NIl8.js">
12-
<link rel="modulepreload" crossorigin href="/assets/i18n-vendor-B43YAj0g.js">
12+
<link rel="modulepreload" crossorigin href="/assets/i18n-vendor-BTk3hSHe.js">
1313
<link rel="modulepreload" crossorigin href="/assets/pb-vendor-CPBlzd7X.js">
14-
<link rel="modulepreload" crossorigin href="/assets/icons-vendor-Dn-hqeL4.js">
14+
<link rel="modulepreload" crossorigin href="/assets/icons-vendor-C4qntwEe.js">
1515
<link rel="modulepreload" crossorigin href="/assets/markdown-vendor-CO4KSbdr.js">
16-
<link rel="stylesheet" crossorigin href="/assets/index-BnIQgU2Z.css">
16+
<link rel="stylesheet" crossorigin href="/assets/index-C9WJJHxP.css">
1717
</head>
1818
<body>
1919
<div id="root"></div>

web/src/components/docker/CommandTab.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { useState, useRef, useEffect } from 'react'
2+
import { useTranslation } from 'react-i18next'
23
import { pb } from '@/lib/pb'
34
import { Button } from '@/components/ui/button'
45
import { Play, Loader2 } from 'lucide-react'
@@ -13,6 +14,7 @@ interface HistoryEntry {
1314
}
1415

1516
export function CommandTab({ serverId = 'local' }: { serverId?: string }) {
17+
const { t } = useTranslation('docker')
1618
const [command, setCommand] = useState('')
1719
const [running, setRunning] = useState(false)
1820
const [history, setHistory] = useState<HistoryEntry[]>([])
@@ -71,7 +73,7 @@ export function CommandTab({ serverId = 'local' }: { serverId?: string }) {
7173
<span className="text-sm font-mono text-muted-foreground select-none">docker</span>
7274
<input
7375
type="text"
74-
placeholder="ps -a --format json"
76+
placeholder={t('command.placeholder', { defaultValue: 'ps -a --format json' })}
7577
className="flex-1 border rounded-md px-3 py-1.5 text-sm font-mono bg-background"
7678
value={command}
7779
onChange={e => setCommand(e.target.value)}
@@ -80,16 +82,19 @@ export function CommandTab({ serverId = 'local' }: { serverId?: string }) {
8082
/>
8183
<Button size="sm" onClick={runCommand} disabled={running || !command.trim()}>
8284
{running ? <Loader2 className="h-4 w-4 animate-spin" /> : <Play className="h-4 w-4" />}
83-
<span className="ml-1">Run</span>
85+
<span className="ml-1">{t('command.run', { defaultValue: 'Run' })}</span>
8486
</Button>
8587
</div>
8688

8789
<div className="bg-muted rounded-md p-4 min-h-[300px] max-h-[65vh] overflow-auto font-mono text-xs">
8890
{history.length === 0 && (
8991
<p className="text-muted-foreground">
90-
Enter a docker subcommand above and press Enter or click Run.
92+
{t('command.emptyPrompt', {
93+
defaultValue: 'Enter a docker subcommand above and press Enter or click Run.',
94+
})}
9195
<br />
92-
Example: <code>ps -a</code>, <code>images</code>, <code>compose ls</code>,{' '}
96+
{t('command.exampleLabel', { defaultValue: 'Example:' })} <code>ps -a</code>,{' '}
97+
<code>images</code>, <code>compose ls</code>,{' '}
9398
<code>network ls</code>
9499
</p>
95100
)}

0 commit comments

Comments
 (0)