embystream 0.0.33

Another Emby streaming application (frontend/backend separation) written in Rust.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
{
  "nav": {
    "home": "Home",
    "login": "Login",
    "register": "Register",
    "dashboard": "Dashboard",
    "wizard": "Wizard",
    "drafts": "Drafts",
    "configSets": "Configs",
    "settings": "Settings",
    "docs": "Docs Wiki",
    "logs": "Logs",
    "users": "Users",
    "account": "Account"
  },
  "common": {
    "preview": "Preview",
    "openPreview": "Open preview",
    "close": "Close",
    "download": "Download",
    "copy": "Copy",
    "copied": "Copied",
    "continue": "Continue",
    "duplicate": "Duplicate",
    "rename": "Rename",
    "delete": "Delete",
    "loading": "Loading",
    "newDraft": "New draft",
    "logout": "Logout",
    "cancel": "Cancel",
    "confirmLogout": "Are you sure you want to log out?",
    "noDrafts": "No drafts yet",
    "noLogs": "No logs yet",
    "previous": "Previous",
    "next": "Next",
    "collapse": "Collapse",
    "expand": "Expand",
    "forbidden": "Forbidden",
    "confirmDeleteConfigSet": "Delete this config set?",
    "promptRenameDraft": "Rename this draft",
    "promptRenameConfigSet": "Rename this config set",
    "themeLight": "Light",
    "themeDark": "Dark",
    "themeSystem": "Follow system",
    "themeCurrent": "Current theme: {mode}",
    "themeSwitchTo": "Switch to {mode}",
    "help": "Help",
    "notifications": "Activity",
    "more": "More",
    "workspace": "Workspace",
    "system": "System",
    "support": "Support",
    "accountActions": "Account",
    "disclaimer": "Disclaimer",
    "openMenu": "Open menu",
    "closeMenu": "Close menu",
    "collapseSidebar": "Collapse sidebar",
    "expandSidebar": "Expand sidebar",
    "language": "Language",
    "private": "Private",
    "adminOnly": "Admin only",
    "routeHint": "This is a scaffold view, Real API wiring comes next"
  },
  "auth": {
    "storyLabel": "EmbyStream",
    "wallTitle": "Deploy config, step by step",
    "wallBody": "From draft to artifacts, the flow stays clear and resumable",
    "panelTitle": "Built for real deployments",
    "panelBody": "Keep recovery, feedback, and reviewable artifacts visible",
    "signals": [
      "guided steps",
      "autosaved drafts",
      "five artifacts",
      "admin logs"
    ],
    "login": {
      "eyebrow": "EmbyStream",
      "title": "Continue your config workspace",
      "body": "Resume drafts, review output, and generate configs in one place",
      "loginLabel": "Username or email",
      "passwordLabel": "Password",
      "helper": "Use your account to continue current work",
      "submit": "Enter workspace",
      "switch": "Need an account? Register",
      "backgroundCount": "{count} frames loaded"
    },
    "register": {
      "eyebrow": "First Run",
      "title": "Create a local account",
      "body": "A new account manages its own drafts and artifacts, and the admin account stays system-owned",
      "usernameLabel": "Username",
      "emailLabel": "Email",
      "passwordLabel": "Password",
      "helper": "Use a stable email so the workspace stays easy to identify",
      "submit": "Create account",
      "switch": "Already have one? Login"
    },
    "registerClosedToast": "Registration is currently closed"
  },
  "wizard": {
    "eyebrow": "Guided Flow",
    "title": "Fill the real deployment config in stages, then review and generate once",
    "body": "The flow now covers frontend and backend routing, nodes, proxy modes, rate limits, and rewrite testing instead of only collecting a few entry values",
    "stepRailTitle": "Stages",
    "chooseMode": "Pick the running shape first",
    "backToConfigs": "Back to configs",
    "saveDraft": "Save draft",
    "generateFiles": "Generate files",
    "saving": "Saving",
    "generating": "Generating",
    "autosaving": "Autosaving",
    "deferDraftCreation": "This draft stays local for now, It will be created on the server when you generate the final config",
    "nameLabel": "Name",
    "nameHint": "This is only for your own list view",
    "embyUrlLabel": "Emby URL",
    "embyUrlHint": "Use the real Emby base URL without the trailing slash",
    "embyPortLabel": "Emby Port",
    "embyPortHint": "Usually 8096 unless your instance uses another port",
    "embyTokenLabel": "Emby Token",
    "embyTokenHint": "The frontend proxy uses this to access Emby APIs safely",
    "logRootLabel": "Log root",
    "logRootHint": "Start here when something breaks, The admin log page reads runtime logs from here too",
    "logLevelLabel": "Log level",
    "logLevelHint": "Use debug while validating, Keep info for normal production runs",
    "logPrefixLabel": "Log prefix",
    "logPrefixHint": "Useful when several instances share the same log directory",
    "memoryModeLabel": "Cache profile",
    "memoryModeHint": "Low saves memory, Middle stays balanced, High leans toward performance",
    "encipherKeyLabel": "Signature key",
    "encipherKeyHint": "Do not ship the template default, Replace it before production",
    "encipherIvLabel": "Signature IV",
    "encipherIvHint": "Rotate this together with the signature key",
    "frontendPortLabel": "Frontend port",
    "frontendPortHint": "Users hit this first, It proxies Emby and rewrites the entry flow",
    "backendPortLabel": "Backend port",
    "backendPortHint": "Real media leaves from here, In dual mode it must differ from the frontend port",
    "backendBaseUrlLabel": "Backend public URL",
    "backendBaseUrlHint": "Use the final public base URL clients should see, not the upstream node address",
    "backendPublicPortLabel": "Backend public port",
    "backendPublicPortHint": "Fill this when the public entry is not 80 or 443",
    "backendPathLabel": "Backend public path",
    "backendPathHint": "The path segment clients should reach for streaming, Leave blank for root",
    "problematicClientsLabel": "Problematic clients",
    "problematicClientsHint": "One keyword per line, These clients skip some aggressive optimizations",
    "userAgentModeLabel": "UA policy",
    "userAgentModeHint": "Pick allow-list or deny-list first, then fill the matching rules",
    "userAgentRulesLabel": "UA rules",
    "userAgentRulesHint": "One keyword per line",
    "fallbackPathLabel": "Fallback video path",
    "fallbackPathHint": "Optional, Use this when the requested file is missing",
    "sslCertLabel": "SSL certificate",
    "sslCertHint": "Only useful for backend HTTPS, Leave blank to keep default discovery",
    "sslKeyLabel": "SSL private key",
    "sslKeyHint": "Pair this with the certificate path",
    "deployNginxTitle": "Nginx Artifact Settings",
    "deployNginxBody": "These fields control the generated nginx.conf domain, TLS paths, and DNS resolver, without changing the app runtime HTTP2 config",
    "nginxFrontendServerNameLabel": "Frontend server_name",
    "nginxFrontendServerNameHint": "Domain written into nginx.conf for frontend or dual-mode output",
    "nginxFrontendSslCertLabel": "Frontend certificate path",
    "nginxFrontendSslCertHint": "Leave blank to emit only a reminder comment, then fill the real path yourself",
    "nginxFrontendSslKeyLabel": "Frontend private key path",
    "nginxFrontendSslKeyHint": "Leave blank to emit only a reminder comment, then pair it with the certificate path",
    "nginxBackendServerNameLabel": "Backend server_name",
    "nginxBackendServerNameHint": "Domain written into nginx.conf for the backend streaming entry",
    "nginxBackendSslCertLabel": "Backend certificate path",
    "nginxBackendSslCertHint": "Leave blank to emit only a reminder comment, then fill the real path yourself",
    "nginxBackendSslKeyLabel": "Backend private key path",
    "nginxBackendSslKeyHint": "Leave blank to emit only a reminder comment, then pair it with the certificate path",
    "nginxResolverProviderLabel": "DNS resolver provider",
    "nginxResolverProviderHint": "Resolver is only needed when backend Nginx proxies upstream HTTPS. No provider is preselected by default",
    "nginxCustomResolversLabel": "Custom DNS resolvers",
    "nginxCustomResolversHint": "Use nginx resolver syntax and separate multiple addresses with spaces",
    "resolverProvidernone": "Do not prefill",
    "resolverProvidercloudflare": "Cloudflare",
    "resolverProviderdnspod": "DNSPod",
    "resolverProvidergoogle": "Google",
    "resolverProvideraliyun": "Alibaba Cloud",
    "resolverProvidertencent": "Tencent",
    "resolverProvidercustom": "Custom",
    "deployRuntimeTitle": "Runtime Script Paths",
    "deployRuntimeBody": "These fields control generated systemd.service and pm2.config.cjs paths so the defaults do not carry unrelated project names",
    "systemdBinaryPathLabel": "systemd binary path",
    "systemdBinaryPathHint": "Default is /usr/bin/embystream. If yours is different, run which embystream first and paste the real path here",
    "systemdWorkingDirectoryLabel": "systemd working directory",
    "systemdWorkingDirectoryHint": "Defaults to /opt/stream. Change it to match your deployment layout",
    "systemdConfigPathLabel": "systemd config path",
    "systemdConfigPathHint": "Defaults to /opt/stream/config.toml. Keep it aligned with your real mounted config",
    "pm2BinaryPathLabel": "PM2 binary path",
    "pm2BinaryPathHint": "Default is /usr/bin/embystream. If yours is different, run which embystream first and paste the real path here",
    "pm2WorkingDirectoryLabel": "PM2 working directory",
    "pm2WorkingDirectoryHint": "Defaults to /opt/stream, /opt/stream-frontend, or /opt/stream-backend based on the selected mode",
    "pm2ConfigPathLabel": "PM2 config path",
    "pm2ConfigPathHint": "Defaults to config.toml inside the working directory, but you can point it elsewhere",
    "pm2OutFileLabel": "PM2 stdout log",
    "pm2OutFileHint": "Defaults to logs/pm2.out.log inside the working directory",
    "pm2ErrorFileLabel": "PM2 stderr log",
    "pm2ErrorFileHint": "Defaults to logs/pm2.err.log inside the working directory",
    "frontendAntiReverseLabel": "Frontend host guard",
    "frontendAntiReverseHint": "Enable host validation when the frontend entry is exposed to the internet",
    "frontendAntiHostLabel": "Trusted frontend host",
    "frontendAntiHostHint": "Use host or host:port only, Do not include the scheme",
    "enableProtection": "Enable protection",
    "frontendRewriteTitle": "Frontend path rewrite",
    "frontendRewriteBody": "These rules rewrite the public entry path before forwarding traffic to Emby or the backend",
    "addRewrite": "Add rewrite",
    "rewriteEnabled": "Enable this rule",
    "rewritePatternLabel": "Match regex",
    "rewritePatternHint": "Start from a concrete path sample and tighten only when needed",
    "rewriteReplacementLabel": "Replacement",
    "rewriteReplacementHint": "Capture groups such as $1 are supported",
    "rewriteRegexInvalid": "Regex error",
    "rewriteRegexMatched": "Matched, result {output}",
    "rewriteRegexNoMatch": "The current sample did not match",
    "noRewriteRules": "No rewrite rules are configured yet",
    "routeTestHint": "Paste a real media path here and check the rewrite result before generating",
    "routeTestInputLabel": "Test path",
    "routeTestResultLabel": "Test result",
    "routeTestNoMatch": "No enabled rewrite rule matched this sample",
    "routeChecklistTitle": "Rewrite test flow",
    "routeChecklistItem1": "Validate a real sample path here before you save the draft",
    "routeChecklistItem2": "After generation, inspect Frontend.PathRewrite and BackendNode.PathRewrite in config.toml directly",
    "routeChecklistItem3": "Before production, hit one real media link from a client and confirm routing, node selection, and delivery mode",
    "nodeFlowTitle": "Backend node layout",
    "nodeFlowBody": "Every backend node needs its own match scope, proxy strategy, rate limit, and rewrite rules, The backend should not stop at a single listener port",
    "addNode": "Add node",
    "nodeLabel": "Node",
    "nodeNameLabel": "Node name",
    "nodeNameHint": "Mainly for config readability and troubleshooting",
    "nodePatternLabel": "Match path",
    "nodePatternHint": "Usually the decrypted file path prefix or regex",
    "nodeBaseUrlLabel": "Node upstream URL",
    "nodeBaseUrlHint": "This is the real upstream target: NAS, OpenList, WebDAV, and so on",
    "nodePortLabel": "Node port",
    "nodePortHint": "Fill this when the upstream port is not the default one",
    "nodePathLabel": "Node path prefix",
    "nodePathHint": "Use this when the upstream service does not live at root",
    "nodePriorityLabel": "Node priority",
    "nodePriorityHint": "Lower numbers win first, Set this explicitly when several nodes can match",
    "nodeProxyModeLabel": "Delivery mode",
    "nodeProxyModeHint": "redirect, proxy, and accel_redirect change both security and bandwidth behavior",
    "nodeSpeedLimitLabel": "Rate limit KB/s",
    "nodeSpeedLimitHint": "0 means unlimited, The limiter applies per device",
    "nodeBurstLimitLabel": "Burst KB/s",
    "nodeBurstLimitHint": "Give players some short burst budget so startup does not stutter immediately",
    "nodeAntiReverseLabel": "Node host guard",
    "nodeAntiReverseHint": "Only enable this when a node needs its own host validation",
    "nodeAntiHostLabel": "Trusted node host",
    "nodeAntiHostHint": "Leave blank unless the node has a dedicated public host",
    "nodeRewriteTitle": "Node rewrite and test",
    "nodeRouteTestHint": "This test shows the rewrite result after traffic has already matched the node",
    "nodeSettingsTitle": "Node-specific settings",
    "backendNodeRequired": "Add at least one backend node before moving to the next step",
    "diskDescriptionLabel": "Disk note",
    "diskDescriptionHint": "Describe the mount point or disk purpose for future maintenance",
    "openListBaseUrlLabel": "OpenList URL",
    "openListBaseUrlHint": "The real OpenList/Alist endpoint",
    "openListPortLabel": "OpenList port",
    "openListPortHint": "Leave blank if the port already lives inside the URL",
    "openListTokenLabel": "OpenList token",
    "openListTokenHint": "Used when the node calls the OpenList API directly",
    "directLinkUserAgentLabel": "Direct-link UA",
    "directLinkUserAgentHint": "Some upstream CDNs only accept a fixed User-Agent",
    "googleNodeUuidLabel": "Google node UUID",
    "googleNodeUuidHint": "Token cache and refresh state depend on this stable ID",
    "googleClientIdLabel": "Google client ID",
    "googleClientIdHint": "The OAuth client ID for the desktop or web app you created",
    "googleClientSecretLabel": "Google client secret",
    "googleClientSecretHint": "Required together with the client ID to refresh tokens",
    "googleDriveIdLabel": "Shared drive ID",
    "googleDriveIdHint": "Preferred over drive_name when both exist",
    "googleDriveNameLabel": "Shared drive name",
    "googleDriveNameHint": "Used as the fallback lookup key when drive_id is absent",
    "googleAccessTokenLabel": "Access token",
    "googleAccessTokenHint": "Can stay blank at first if refresh_token is available",
    "googleRefreshTokenLabel": "Refresh token",
    "googleRefreshTokenHint": "This is the long-lived credential the node really needs",
    "webdavNodeUuidLabel": "WebDAV node UUID",
    "webdavNodeUuidHint": "Must stay stable and unique when accel_redirect is used",
    "webdavUrlModeLabel": "WebDAV URL mode",
    "webdavUrlModeHint": "Controls how the final file path is assembled for upstream requests",
    "webdavQueryParamLabel": "Query parameter",
    "webdavQueryParamHint": "Used only when url_mode is query_path",
    "webdavUrlTemplateLabel": "URL template",
    "webdavUrlTemplateHint": "Required only for url_template mode and must include {file_path}",
    "webdavUsernameLabel": "WebDAV username",
    "webdavUsernameHint": "Fill this when the upstream expects Basic Auth",
    "webdavPasswordLabel": "WebDAV password",
    "webdavPasswordHint": "Pair this with the username",
    "webdavUserAgentLabel": "WebDAV UA",
    "webdavUserAgentHint": "Some WebDAV servers restrict the accepted user agent",
    "savedAt": "Saved at {timestamp}",
    "generatedCount": "Generated {count} files",
    "restoreBanner": "Recovered draft {name}",
    "reviewTitle": "Final review",
    "reviewBody": "This is the last technical pass over ports, nodes, rewrites, and testing steps before generation",
    "reviewName": "Draft",
    "reviewMode": "Mode",
    "reviewFrontendPort": "Frontend port",
    "reviewBackendPort": "Backend port",
    "reviewNodes": "Backend nodes",
    "reviewRewrites": "Enabled rewrites (frontend / nodes)",
    "reviewArtifacts": "Files",
    "reviewChecklistTitle": "Pre-generation checks",
    "reviewChecklistItem1": "Confirm the public ports, base URLs, and path segments match the target environment",
    "reviewChecklistItem2": "Confirm every backend node has its own match rule, delivery mode, and required credentials",
    "reviewChecklistItem3": "Confirm every enabled rewrite rule has been validated with a sample path",
    "reviewChecklistItem4": "Confirm the rate limits, host guards, and fallback behavior match production expectations",
    "purposeLabel": "What this step does",
    "effectLabel": "What it changes",
    "questionLabel": "Current question",
    "helperLabel": "How this answer changes the generated result",
    "modeFrontendBody": "Use this when you only need a proxy entry in front of Emby",
    "modeBackendBody": "Use this when the media edge should run on a separate host",
    "modeDualBody": "Use this when you want one service to cover both sides first",
    "memoryLow": "Low",
    "memoryMiddle": "Balanced",
    "memoryHigh": "High",
    "uaAllow": "Allow matching items only",
    "uaDeny": "Block matching items",
    "steps": [
      "pick mode",
      "general setup",
      "network entry",
      "guardrails",
      "path rewrite",
      "backend nodes",
      "final review"
    ],
    "stepCards": [
      {
        "title": "Start with the running shape",
        "purpose": "Pick whether you want only the proxy, only the media edge, or both sides together",
        "effect": "This choice controls which ports and deployment files matter later"
      },
      {
        "title": "Fill the shared runtime basics first",
        "purpose": "Name the draft, set logging, choose the cache profile, and rotate the signing secrets",
        "effect": "This stage affects troubleshooting, runtime behavior, and whether you accidentally ship template defaults"
      },
      {
        "title": "Wire the real entry and public backend address",
        "purpose": "This stage covers the real Emby target, the frontend listener, the backend public address, and problematic clients",
        "effect": "These values control how clients enter the system and what the generated deployment artifacts expose"
      },
      {
        "title": "Apply guardrails and fallback behavior",
        "purpose": "Control UA policy, host validation, TLS paths, and the fallback media response",
        "effect": "This changes abuse resistance, HTTPS wiring, and what users see when playback fails"
      },
      {
        "title": "Validate rewrite logic before generation",
        "purpose": "Do not leave rewrites as untested config text, Run a sample path through the rules first",
        "effect": "You can catch bad regexes, wrong replacements, and broken public path assumptions before deployment"
      },
      {
        "title": "Create and finish every backend node",
        "purpose": "Each node should own its own match rule, delivery mode, rate limit, rewrites, and upstream-specific credentials",
        "effect": "The backend becomes deployable and debuggable instead of stopping at a single listener section"
      },
      {
        "title": "Review once before generation",
        "purpose": "Run through the key deployment values, node count, and test actions one more time",
        "effect": "The generated snapshot and artifacts are created from this exact version"
      }
    ],
    "noBackendNodesNeeded": "This mode does not start a backend service, so this stage can be skipped",
    "previewTitle": "Generated output",
    "previewBody": "Every file can be expanded, collapsed, and downloaded on its own"
  },
  "drafts": {
    "eyebrow": "Workspace",
    "title": "Drafts and progress stay here",
    "body": "Resume, rename, or clear drafts without starting over",
    "backToConfigs": "Back to configs",
    "queueLabel": "Current queue",
    "queueTitle": "Focus on work in progress",
    "queueBody": "Drafts stay editable and generated results move into the config library",
    "statsDrafts": "Drafts",
    "statsGenerated": "Generated",
    "statsConfigs": "Config sets",
    "loadingTitle": "Syncing drafts",
    "loadingBody": "Drafts and config-set counts load before the workspace appears",
    "errorTitle": "Drafts are unavailable right now",
    "emptyTitle": "No active configuration yet",
    "emptyBody": "Start a new draft and come back when you need it",
    "updatedAt": "Updated {time}",
    "statusDraft": "Draft",
    "statusGenerated": "Generated"
  },
  "account": {
    "eyebrow": "Profile",
    "title": "Account and shortcuts",
    "body": "See the current account, role, and common entry points",
    "username": "Username",
    "email": "Email",
    "role": "Role",
    "roleAdmin": "Admin",
    "roleUser": "User",
    "roleAdminBody": "Includes logs and the full workspace, and final access is still enforced by the API",
    "roleUserBody": "Scoped to personal drafts and generated artifacts",
    "emailFallback": "No email provided",
    "aboutOpen": "About EmbyStream",
    "aboutLabel": "About",
    "aboutTitle": "About EmbyStream",
    "aboutBody": "Open the project page, check the current version, and read release notes",
    "aboutVersion": "Current version {version}",
    "aboutGithub": "GitHub project",
    "aboutChangelog": "Changelog",
    "fontsLabel": "Typography",
    "fontsTitle": "Choose the Chinese and Latin fonts you actually want to read",
    "fontsBody": "Chinese and English preferences are saved locally and applied to the full workspace immediately",
    "fontZhLabel": "Chinese font",
    "fontEnLabel": "English font",
    "fontCodeLabel": "Code font",
    "fontPreviewZh": "Use this line to judge rhythm, density, and the overall feel of Chinese copy",
    "fontPreviewEn": "Preview the Latin font pairing across labels, headings, and mixed-language content",
    "fontPreviewCode": "stream_mode = \"proxy\"\nfont_family = \"Fira Code\"\ntheme = \"catppuccin\"",
    "fontZhSourceHanSans": "Source Han Sans SC",
    "fontZhWenkai": "LXGW WenKai",
    "fontZhPingfang": "PingFang SC",
    "fontEnSourceSerif": "Source Serif 4",
    "fontEnSourceSans": "Source Sans 3",
    "fontEnInter": "Inter",
    "fontEnPlusJakartaSans": "Plus Jakarta Sans",
    "fontEnSourceCodePro": "Source Code Pro",
    "fontCodeMenlo": "Menlo",
    "fontCodeFiraCode": "Fira Code",
    "quickLinks": "Quick links",
    "quickLinksTitle": "Open common actions fast",
    "quickLinksBody": "Keep frequent pages close and navigation quiet",
    "securityTitle": "The permission boundary stays server-side",
    "securityBody": "The client guides the flow and access control is still enforced by the API",
    "passwordCardTitle": "Change password",
    "passwordCardBody": "Regular users can only change their own login password here, and a successful change signs out the current session and requires a fresh login",
    "passwordDialogBody": "Enter your current password and set a new login password, and the two new-password entries must match exactly",
    "passwordCurrentLabel": "Current password",
    "passwordCurrentPlaceholder": "Enter your current login password",
    "passwordCurrentRequired": "Enter your current password first",
    "passwordNewLabel": "New password",
    "passwordNewPlaceholder": "Enter a new login password",
    "passwordNewRequired": "Enter a new password",
    "passwordRepeatLabel": "Repeat new password",
    "passwordRepeatPlaceholder": "Enter the new password again",
    "passwordRepeatMismatch": "The two new passwords do not match"
  },
  "settings": {
    "eyebrow": "Preferences",
    "title": "Workspace settings",
    "body": "Manage interface language and typography in one place",
    "themeLabel": "Theme mode",
    "themeTitle": "Light and dark theme",
    "themeBody": "Lock the UI to light or dark, or follow the phone or desktop system theme automatically",
    "themeCurrent": "Currently active: {mode}",
    "languageLabel": "Language",
    "languageTitle": "Interface language",
    "languageBody": "Updates apply immediately to copy and time formatting",
    "registrationLabel": "Registration",
    "registrationTitle": "Public registration",
    "registrationBody": "Control whether visitors can create local accounts from the login screen",
    "registrationStateOpen": "Open",
    "registrationStateClosed": "Closed",
    "registrationCurrent": "Current state: {state}",
    "registrationSaved": "Registration is now {state}",
    "registrationLoadFailed": "Failed to load registration settings",
    "registrationSaveFailed": "Failed to update registration settings",
    "renderFontLabel": "Render font",
    "renderWeightLabel": "Render weight",
    "renderWeightNormal": "Normal",
    "renderFontMenlo": "Menlo",
    "renderFontSans": "Source Sans 3",
    "renderFontSerif": "Source Serif 4",
    "renderWeightRegular": "Regular",
    "renderWeightSemibold": "Semibold",
    "renderWeightBold": "Bold",
    "zhWeightLabel": "Chinese weight",
    "enWeightLabel": "English weight",
    "codeWeightLabel": "Code weight",
    "localeZhCn": "Simplified Chinese",
    "localeZhTw": "Traditional Chinese",
    "localeEn": "English"
  },
  "dashboard": {
    "eyebrow": "Overview",
    "title": "Runtime overview",
    "body": "Monitor disk, CPU, memory, and uptime",
    "statusLabel": "Status",
    "refreshTitle": "System metrics refresh automatically",
    "refreshBody": "Last updated {time}",
    "refreshHint": "These metrics are derived from the EmbyStream main process and related files, not the full machine state",
    "refreshAction": "Refresh now",
    "loadingTitle": "Loading system metrics",
    "loadingBody": "Metrics will appear here once they are ready",
    "errorTitle": "System metrics are unavailable",
    "errorBody": "Failed to load system metrics",
    "cpu": "CPU usage",
    "memory": "Memory usage",
    "disk": "Disk usage",
    "uptime": "Uptime",
    "cpuMeta": "{count} cores",
    "memoryMeta": "Total RAM {total}",
    "diskMeta": "Total disk {total}"
  },
  "more": {
    "eyebrow": "More",
    "title": "More",
    "body": "Browse additional entry points by function group, and move into each page like a native app"
  },
  "docs": {
    "eyebrow": "Wiki",
    "title": "Docs Wiki",
    "body": "Browse runtime docs and Web admin deployment notes in one place",
    "readmeLabel": "README",
    "readmeTitle": "Runtime usage guide",
    "readmeBody": "Read the main runtime guide and parameter reference",
    "nginxLabel": "Nginx",
    "nginxTitle": "Web admin reverse proxy example",
    "nginxBody": "Use a reverse proxy to forward your domain to the Web admin page, then access EmbyStream through that domain",
    "openLink": "Open docs",
    "issueLink": "Open an issue for doc feedback"
  },
  "configSets": {
    "eyebrow": "Artifacts",
    "title": "Configs",
    "body": "Review, duplicate, and download generated configs",
    "libraryLabel": "Artifact library",
    "libraryTitle": "Generated output should stay visible",
    "libraryBody": "Browse configs as a clean list, then open details only when you need the generated files",
    "createAction": "Add config",
    "draftsAction": "Drafts",
    "detailAction": "Details",
    "detailEyebrow": "Config detail",
    "detailTitle": "Config detail",
    "detailBody": "Browse generated artifacts for this config and expand each file only when needed",
    "backToList": "Back to configs",
    "loadingTitle": "Loading config sets",
    "loadingBody": "The latest results appear as a collapsible list once loading finishes",
    "detailLoadingTitle": "Loading config detail",
    "detailLoadingBody": "Artifacts will appear here once this config is ready",
    "detailMissingTitle": "This config is unavailable",
    "detailMissingBody": "The requested config could not be found or loaded",
    "errorTitle": "The config library is unavailable right now",
    "emptyTitle": "No artifacts to preview yet",
    "emptyBody": "Generate a config first, then inspect and download it here",
    "updatedAt": "Updated {time}",
    "countLabel": "{count} config sets"
  },
  "logs": {
    "eyebrow": "Restricted",
    "title": "Runtime logs are admin-only",
    "body": "The client shows access state clearly and the server remains the control point",
    "consoleLabel": "Runtime console",
    "consoleTitle": "View recent logs in one place",
    "consoleBody": "Filter recent records by source, level, and keyword to find issues faster",
    "levelLabel": "Log level",
    "levelAll": "All levels",
    "keywordLabel": "Keyword",
    "keywordPlaceholder": "Search message / source / level",
    "filteredLabel": "Filtered result",
    "filteredTitle": "No logs match the current filters",
    "filteredBody": "Try a broader level or keyword",
    "securityNote": "Frontend guards improve flow, but the real boundary stays in the API",
    "forbiddenTitle": "This page is locked",
    "forbiddenBody": "The backend still says no",
    "errorTitle": "Logs are unavailable right now",
    "emptyTitle": "No log lines yet",
    "emptyBody": "Runtime, stream, and audit records will appear here once the service starts writing logs",
    "sourceLabel": "Source guide",
    "filterAll": "All",
    "filterStream": "Stream",
    "filterRuntime": "Runtime",
    "filterAudit": "Audit",
    "filterAllHint": "Shows stream logs, Web admin runtime logs, and audit records together for a quick recent overview.",
    "filterStreamHint": "Covers EmbyStream runtime activity such as gateway, proxy, forwarding, and streaming pipeline behavior.",
    "filterRuntimeHint": "Covers the Web Studio itself, including bootstrap, listening, initialization, and API runtime state rather than stream traffic.",
    "filterAuditHint": "Covers sign-in, user management, and config changes so you can see who changed what and when.",
    "statusConnecting": "Connecting",
    "statusConnectingBody": "Opening the live log stream.",
    "statusLive": "Live",
    "statusLiveBody": "New logs appear automatically.",
    "statusReconnecting": "Reconnecting",
    "statusReconnectingBody": "Trying to recover the live log stream.",
    "statusOffline": "Offline",
    "statusOfflineBody": "Live updates are paused until the page reconnects.",
    "followLive": "Auto-following latest logs",
    "followLiveBody": "The console stays pinned to the newest log entries.",
    "followPaused": "Auto-follow paused",
    "followPausedBody": "Scroll back to the top or resume to follow new entries again.",
    "followPausedCount": "{count} new log entries are waiting above.",
    "pauseFollow": "Pause auto-follow",
    "resumeFollow": "Jump to latest",
    "reconnectNow": "Reconnect now"
  },
  "users": {
    "eyebrow": "Admin",
    "title": "User management",
    "body": "Manage registered users, roles, status, and passwords",
    "filterLabel": "Filter",
    "filterTitle": "Find users by username or email",
    "keywordLabel": "Keyword",
    "keywordPlaceholder": "Search username / email / role",
    "statusLabel": "Status",
    "loadingTitle": "Loading users",
    "loadingBody": "Users will appear here once the list is ready",
    "errorTitle": "User list is unavailable",
    "errorBody": "Failed to load users",
    "emptyLabel": "Empty result",
    "emptyTitle": "No users match the current filter",
    "emptyBody": "Adjust the keyword and try again",
    "disabled": "Disabled",
    "promote": "Promote",
    "demote": "Demote",
    "enable": "Enable",
    "disable": "Disable",
    "changePassword": "Change password",
    "passwordPrompt": "Enter a new password with at least 8 characters",
    "passwordLabel": "New password",
    "passwordDialogTitle": "Change user password",
    "passwordDialogBody": "Set a new password for {username}, and the user will need to sign in again",
    "deleteDialogTitle": "Delete user",
    "deleteConfirm": "Delete user {username}?",
    "updatedAt": "Updated {time}"
  },
  "disclaimer": {
    "title": "Disclaimer",
    "body": "The web style is inspired by Claude Code, and the code was written with OpenAI Codex. If this causes an issue, please file a GitHub issue",
    "claude": "Claude Code",
    "codex": "OpenAI Codex",
    "github": "GitHub"
  },
  "errors": {
    "signInFailed": "Sign-in failed",
    "registerFailed": "Registration failed",
    "draftsLoadFailed": "Drafts failed to load",
    "configsLoadFailed": "Configs failed to load",
    "logsLoadFailed": "Logs failed to load",
    "templateLoadFailed": "Template failed to load",
    "draftCreateFailed": "Draft creation failed",
    "draftSaveFailed": "Draft save failed",
    "generationFailed": "Generation failed"
  },
  "modes": {
    "frontend": "Frontend",
    "backend": "Backend",
    "dual": "Dual"
  }
}