Files
HC_APTBS/Resources/Strings.en.xaml
LucianoDev 69bfda54e1 feat: redesign Bench page with Fluent card layout and radial advance monitor
Three-column layout replacing the old HMI grid:
- BenchRpmCommandCard: inline numeric input, 2×4 preset grid, Start/Stop
- BenchActuatorsCard: direction toggle, oil pump, temperature PID, misc relays
  with FluentStateToggle showing checked state via AccentFillColor
- BenchLiveDataCard: 2×5 KPI tiles (RPM, P1, P2, Q-Delivery, Q-Over, temps)
- BenchChartsCard: 2×2 compact chart grid (Delivery, Over, P1, P2)
- AdvanceMonitorCard: RadialAngleGauge custom FrameworkElement + PSG/INJ readouts,
  Δ° lock offset input, Zero PSG / Zero INJ buttons

Supporting changes:
- AngleDisplayViewModel: promote _currentManualDegrees, _isLockSet to
  [ObservableProperty]; add PsgRelativeDegrees, InjEncoderDegreesValue,
  TargetLockAngle, IsRunningMode (29/31 hysteresis); computed PrimaryGaugeAngle,
  TargetAngleForGauge, SecondaryGaugeAngle
- BenchControlViewModel: add IsDirectionLeft computed property,
  SetDirectionRightCommand, SetDirectionLeftCommand, ApplyRpmCommand
- FlowmeterChartView: add IsCompact DP (false default) for 90px compact height
- Styles.xaml: add IsChecked trigger to FluentStateToggle (accent fill + white text)
- Strings.en/es.xaml: add all new card and actuator string keys

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 17:45:59 +02:00

578 lines
41 KiB
XML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=System.Runtime">
<!-- ══════════════════════════════════════════════════════════════════
English (ENG)
══════════════════════════════════════════════════════════════════ -->
<!-- ── App ──────────────────────────────────────────────────────────── -->
<sys:String x:Key="App.Title">HC_APTBS — Herlic Test Bench</sys:String>
<!-- ── Navigation rail ──────────────────────────────────────────────── -->
<sys:String x:Key="Nav.Dashboard">Dashboard</sys:String>
<sys:String x:Key="Nav.Bench">Bench</sys:String>
<sys:String x:Key="Nav.Pump">Pump</sys:String>
<sys:String x:Key="Nav.Tests">Tests</sys:String>
<sys:String x:Key="Nav.Results">Results</sys:String>
<sys:String x:Key="Nav.Settings">Settings</sys:String>
<!-- ── Dashboard page ───────────────────────────────────────────────── -->
<sys:String x:Key="Dashboard.Readings">Bench readings</sys:String>
<sys:String x:Key="Dashboard.Connections">Connections</sys:String>
<sys:String x:Key="Dashboard.Conn.Can">CAN bus</sys:String>
<sys:String x:Key="Dashboard.Conn.Bench">Bench controller</sys:String>
<sys:String x:Key="Dashboard.Conn.Pump">Pump ECU</sys:String>
<sys:String x:Key="Dashboard.Conn.KLine">K-Line session</sys:String>
<sys:String x:Key="Dashboard.StateOnline">ONLINE</sys:String>
<sys:String x:Key="Dashboard.StateOffline">OFFLINE</sys:String>
<sys:String x:Key="Dashboard.StateOpen">OPEN</sys:String>
<sys:String x:Key="Dashboard.StateClosed">CLOSED</sys:String>
<sys:String x:Key="Dashboard.StateFailed">FAILED</sys:String>
<sys:String x:Key="Dashboard.Alarms">Active alarms</sys:String>
<sys:String x:Key="Dashboard.AlarmsNone">System OK — no active alarms</sys:String>
<sys:String x:Key="Dashboard.TestSummary">Test summary</sys:String>
<sys:String x:Key="Dashboard.TestActive">Active:</sys:String>
<sys:String x:Key="Dashboard.TestPhase">Phase:</sys:String>
<sys:String x:Key="Dashboard.NoTestRunning">No test is currently running.</sys:String>
<sys:String x:Key="Dashboard.LastTestPass">Last test: PASS</sys:String>
<sys:String x:Key="Dashboard.LastTestFail">Last test: FAIL</sys:String>
<sys:String x:Key="Dashboard.Action.StartTest">Start Test</sys:String>
<sys:String x:Key="Dashboard.Action.StartTest.Tip">Requires a selected pump and an open CAN connection.</sys:String>
<sys:String x:Key="Dashboard.Action.Stop">Stop</sys:String>
<sys:String x:Key="Dashboard.Action.EmergencyStop">EMERGENCY STOP</sys:String>
<!-- ── Dashboard KPI tile labels ──────────────────────────────────────── -->
<sys:String x:Key="Dashboard.Kpi.Rpm">Bench RPM</sys:String>
<sys:String x:Key="Dashboard.Kpi.Qdelivery">Q delivery</sys:String>
<sys:String x:Key="Dashboard.Kpi.P1">Pressure P1</sys:String>
<sys:String x:Key="Dashboard.Kpi.P2">Pressure P2</sys:String>
<sys:String x:Key="Dashboard.Kpi.Tin">Oil in T</sys:String>
<sys:String x:Key="Dashboard.Kpi.Tout">Oil out T</sys:String>
<sys:String x:Key="Dashboard.Kpi.Unit.Rpm">rpm</sys:String>
<sys:String x:Key="Dashboard.Kpi.Unit.CcS">cc/s</sys:String>
<sys:String x:Key="Dashboard.Kpi.Unit.Bar">bar</sys:String>
<sys:String x:Key="Dashboard.Kpi.Unit.Celsius">°C</sys:String>
<!-- Dashboard test summary extras -->
<sys:String x:Key="Dashboard.TestSummary.Elapsed">Elapsed:</sys:String>
<!-- Dashboard connection chip extras -->
<sys:String x:Key="Dashboard.Conn.Pump.Label">Pump:</sys:String>
<sys:String x:Key="Dashboard.Conn.NoPump">No pump</sys:String>
<!-- ── Dashboard Devices column ─────────────────────────────────────── -->
<sys:String x:Key="Dashboard.Devices">Devices</sys:String>
<sys:String x:Key="Dashboard.Devices.Can">CAN</sys:String>
<sys:String x:Key="Dashboard.Devices.Kline">K-Line</sys:String>
<sys:String x:Key="Dashboard.Devices.Bench">Bench</sys:String>
<sys:String x:Key="Dashboard.Devices.Refresh">Refresh</sys:String>
<sys:String x:Key="Dashboard.Devices.State.Idle">Available</sys:String>
<sys:String x:Key="Dashboard.Devices.State.Connected">Connected</sys:String>
<sys:String x:Key="Dashboard.Devices.State.Active">Session active</sys:String>
<sys:String x:Key="Dashboard.Devices.State.Failed">Error</sys:String>
<sys:String x:Key="Dashboard.Devices.None">No devices found</sys:String>
<sys:String x:Key="Dashboard.Devices.BenchRow">Bench controller</sys:String>
<!-- Confirmation dialogs -->
<sys:String x:Key="Devices.Confirm.Title">Confirm device change</sys:String>
<sys:String x:Key="Devices.Confirm.Body.Active">The {0} session is active. Disconnect?</sys:String>
<sys:String x:Key="Devices.Confirm.Body.TestRunning">A test is running. Changing device state may abort it. Continue?</sys:String>
<!-- ── Status bar / connection indicators ───────────────────────────── -->
<sys:String x:Key="Status.Label">Status:</sys:String>
<sys:String x:Key="Status.Can">CAN</sys:String>
<sys:String x:Key="Status.Bench">Bench</sys:String>
<sys:String x:Key="Status.Pump">Pump</sys:String>
<sys:String x:Key="Status.KLine">K-Line</sys:String>
<sys:String x:Key="Status.Connected">Connected</sys:String>
<sys:String x:Key="Status.ConnectionFailed">Connection failed</sys:String>
<sys:String x:Key="Status.Disconnected">Disconnected</sys:String>
<!-- ── Bench section ────────────────────────────────────────────────── -->
<sys:String x:Key="Bench.ConnectCan">Connect CAN</sys:String>
<sys:String x:Key="Bench.DisconnectCan">Disconnect CAN</sys:String>
<sys:String x:Key="Bench.Rpm">rpm</sys:String>
<sys:String x:Key="Bench.Target">Target:</sys:String>
<sys:String x:Key="Bench.Voltage">V:</sys:String>
<sys:String x:Key="Bench.TempIn">T. In:</sys:String>
<sys:String x:Key="Bench.TempOut">T. Out:</sys:String>
<sys:String x:Key="Bench.Temp4">T. 4:</sys:String>
<sys:String x:Key="Bench.TempTank">T. Tank:</sys:String>
<sys:String x:Key="Bench.P1">P1:</sys:String>
<sys:String x:Key="Bench.P2">P2:</sys:String>
<sys:String x:Key="Bench.QDelivery">Q-Del.:</sys:String>
<sys:String x:Key="Bench.QOver">Q-Over:</sys:String>
<sys:String x:Key="Bench.CcStroke">cc/stroke</sys:String>
<sys:String x:Key="Bench.PumpRpm">P-RPM:</sys:String>
<sys:String x:Key="Bench.PumpTemp">P-Temp:</sys:String>
<sys:String x:Key="Bench.PumpMe">P-ME:</sys:String>
<sys:String x:Key="Bench.PumpFbkw">P-FBkW:</sys:String>
<sys:String x:Key="Bench.PsgEncoder">PSG Encoder:</sys:String>
<!-- ── Bench controls ───────────────────────────────────────────────── -->
<sys:String x:Key="Bench.Direction">Direction</sys:String>
<sys:String x:Key="Bench.Left">LEFT</sys:String>
<sys:String x:Key="Bench.Right">RIGHT</sys:String>
<sys:String x:Key="Bench.Motor">Bench Motor</sys:String>
<sys:String x:Key="Bench.Start">START</sys:String>
<sys:String x:Key="Bench.Stop">STOP</sys:String>
<sys:String x:Key="Bench.SetRpm">Set RPM:</sys:String>
<sys:String x:Key="Bench.Go">GO</sys:String>
<sys:String x:Key="Bench.OilPump">Oil Pump</sys:String>
<sys:String x:Key="Bench.OilOff">OIL OFF</sys:String>
<sys:String x:Key="Bench.OilOn">OIL ON</sys:String>
<sys:String x:Key="Bench.Counter">Counter</sys:String>
<sys:String x:Key="Bench.Turns">Turns:</sys:String>
<sys:String x:Key="Bench.Send">Send</sys:String>
<sys:String x:Key="Bench.Relays">Relays</sys:String>
<sys:String x:Key="Bench.Electronic">Electronic</sys:String>
<sys:String x:Key="Bench.DepositCooler">Deposit Cooler</sys:String>
<sys:String x:Key="Bench.DepositHeater">Deposit Heater</sys:String>
<sys:String x:Key="Bench.TinCooler">T-in Cooler</sys:String>
<sys:String x:Key="Bench.Flasher">Flasher</sys:String>
<sys:String x:Key="Bench.Pulse4Signal">4-Pulse Signal</sys:String>
<sys:String x:Key="Bench.RelayOn">ON</sys:String>
<sys:String x:Key="Bench.RelayOff">OFF</sys:String>
<sys:String x:Key="Bench.TempControl">Temperature</sys:String>
<sys:String x:Key="Bench.Setpoint">Setpoint</sys:String>
<sys:String x:Key="Bench.Tolerance">Tolerance</sys:String>
<sys:String x:Key="Bench.ApplySetpoint">Apply setpoint</sys:String>
<!-- ── Pump page sub-nav / banners ──────────────────────────────────── -->
<sys:String x:Key="PumpSub.Identification">Identification</sys:String>
<sys:String x:Key="PumpSub.Dtcs">Fault Codes</sys:String>
<sys:String x:Key="PumpSub.LiveData">Live Data</sys:String>
<sys:String x:Key="PumpSub.Adaptation">Adaptation</sys:String>
<sys:String x:Key="PumpSub.Unlock">Immobilizer Unlock</sys:String>
<sys:String x:Key="Pump.KLineClosed">K-Line session is not open. Identify a pump to begin diagnostics.</sys:String>
<sys:String x:Key="Pump.NoPumpSelected">Select a pump on the Identification tab to enable diagnostics.</sys:String>
<sys:String x:Key="Pump.NoUnlockActive">No immobilizer unlock is currently in progress for this pump.</sys:String>
<sys:String x:Key="PumpLive.Engineering">Engineering values (raw)</sys:String>
<!-- ── DTC list ─────────────────────────────────────────────────────── -->
<sys:String x:Key="Dtc.Read">Read DTCs</sys:String>
<sys:String x:Key="Dtc.Clear">Clear DTCs</sys:String>
<sys:String x:Key="Dtc.NoFaults">No fault codes reported by the ECU.</sys:String>
<sys:String x:Key="Dtc.LastRead">Last read:</sys:String>
<sys:String x:Key="Dtc.Cleared">Fault codes cleared.</sys:String>
<!-- ── Auth gate ────────────────────────────────────────────────────── -->
<sys:String x:Key="AuthGate.LockedTitle">Authentication required</sys:String>
<sys:String x:Key="AuthGate.LockedMessage">This section can modify pump parameters. Sign in to unlock.</sys:String>
<sys:String x:Key="AuthGate.Authenticate">Authenticate…</sys:String>
<sys:String x:Key="AuthGate.UnlockedAs">Unlocked as</sys:String>
<sys:String x:Key="AuthGate.Lock">Lock</sys:String>
<!-- ── Pump live data ───────────────────────────────────────────────── -->
<sys:String x:Key="Pump.THyb">T-hyb</sys:String>
<sys:String x:Key="Pump.Rpm">RPM</sys:String>
<sys:String x:Key="Pump.TEin">T-ein</sys:String>
<sys:String x:Key="Pump.UnitRpm">1/min</sys:String>
<sys:String x:Key="Pump.UnitCelsius">°C</sys:String>
<sys:String x:Key="Pump.UnitUs">µs</sys:String>
<sys:String x:Key="Pump.Commands.Title">Pump Commands</sys:String>
<sys:String x:Key="Pump.Commands.Me">ME</sys:String>
<sys:String x:Key="Pump.Commands.Fbkw">FBKW</sys:String>
<sys:String x:Key="Pump.Commands.PreIn">Pre-inj</sys:String>
<sys:String x:Key="Pump.LiveData.Title">Live Data</sys:String>
<sys:String x:Key="Pump.LiveData.RPM">Pump RPM</sys:String>
<sys:String x:Key="Pump.LiveData.THyb">T-hyb</sys:String>
<sys:String x:Key="Pump.LiveData.TEin">T-ein</sys:String>
<sys:String x:Key="Pump.LiveData.Me">ME</sys:String>
<sys:String x:Key="Pump.LiveData.Fbkw">FBKW</sys:String>
<sys:String x:Key="Pump.LiveData.RpmChart">RPM trend</sys:String>
<sys:String x:Key="Pump.Status.Active">Active</sys:String>
<sys:String x:Key="Pump.Dfi.Title">Idling Calibration</sys:String>
<sys:String x:Key="Pump.Dfi.Version">Version</sys:String>
<sys:String x:Key="Pump.Dfi.Current">Current DFI</sys:String>
<sys:String x:Key="Pump.Dtcs.Title">Fault Codes</sys:String>
<sys:String x:Key="Pump.Identification.Title">Identification</sys:String>
<sys:String x:Key="Pump.TopStrip.Brand">Brand</sys:String>
<sys:String x:Key="Pump.TopStrip.NoPump">No pump selected</sys:String>
<sys:String x:Key="Pump.TopStrip.Can">CAN</sys:String>
<sys:String x:Key="Pump.TopStrip.KLine">K-Line</sys:String>
<sys:String x:Key="Pump.NoPumpBanner">No pump selected — select a pump to enable diagnostics.</sys:String>
<sys:String x:Key="Pump.FastUnlock">Fast unlock attempt...</sys:String>
<!-- ── Pump identification ──────────────────────────────────────────── -->
<sys:String x:Key="PumpId.Label">Pump:</sys:String>
<sys:String x:Key="PumpId.Dfi">DFI:</sys:String>
<sys:String x:Key="PumpId.PumpId">Pump ID:</sys:String>
<sys:String x:Key="PumpId.SerialNo">Serial No:</sys:String>
<sys:String x:Key="PumpId.ModelRef">Model Ref:</sys:String>
<sys:String x:Key="PumpId.DataRecord">Data Record:</sys:String>
<sys:String x:Key="PumpId.PumpCtrl">Pump Ctrl:</sys:String>
<sys:String x:Key="PumpId.ModelIndex">Model Index:</sys:String>
<sys:String x:Key="PumpId.SwVer1">SW Ver 1:</sys:String>
<sys:String x:Key="PumpId.SwVer2">SW Ver 2:</sys:String>
<sys:String x:Key="PumpId.Errors">Errors:</sys:String>
<sys:String x:Key="PumpId.Error">Error:</sys:String>
<sys:String x:Key="PumpId.ReadKLine">Read K-Line</sys:String>
<sys:String x:Key="PumpId.Disconnect">Disconnect</sys:String>
<sys:String x:Key="PumpId.NoKLineDevice">No K-Line device found</sys:String>
<!-- ── DFI management ───────────────────────────────────────────────── -->
<sys:String x:Key="Dfi.Read">READ</sys:String>
<sys:String x:Key="Dfi.Write">WRITE</sys:String>
<sys:String x:Key="Dfi.Label">DFI:</sys:String>
<sys:String x:Key="Dfi.Auto">AUTO</sys:String>
<!-- ── Pump control sliders ─────────────────────────────────────────── -->
<sys:String x:Key="PumpCtrl.Fbkw">FBKW - Advance Control</sys:String>
<sys:String x:Key="PumpCtrl.Me">ME - Quantity Control</sys:String>
<sys:String x:Key="PumpCtrl.PreInj">ME - Pre-inj Quantity</sys:String>
<sys:String x:Key="PumpCtrl.MinStepMax">Min / Step / Max</sys:String>
<sys:String x:Key="PumpCtrl.Min">Min</sys:String>
<sys:String x:Key="PumpCtrl.Step">Step</sys:String>
<sys:String x:Key="PumpCtrl.Max">Max</sys:String>
<!-- ── Bench parameter config ───────────────────────────────────────── -->
<sys:String x:Key="BenchParam.CanBusId">CAN-Bus ID (0x)</sys:String>
<sys:String x:Key="BenchParam.ByteL">Byte L</sys:String>
<sys:String x:Key="BenchParam.ByteH">Byte H</sys:String>
<sys:String x:Key="BenchParam.FilterAlpha">Filter α</sys:String>
<sys:String x:Key="BenchParam.EnableFormula">Enable formula</sys:String>
<!-- ── Angle display ────────────────────────────────────────────────── -->
<sys:String x:Key="Angle.Header">ADVANCE MONITORING</sys:String>
<sys:String x:Key="Angle.Psg">PSG:</sys:String>
<sys:String x:Key="Angle.Inj">INJ:</sys:String>
<sys:String x:Key="Angle.AbsDeg">ABS °:</sys:String>
<sys:String x:Key="Angle.LockDeg">LOCK °:</sys:String>
<sys:String x:Key="Angle.SetPsgZero">Set PSG zero reference</sys:String>
<sys:String x:Key="Angle.SetInjZero">Set INJ zero reference</sys:String>
<!-- ── Bench page — Fluent redesign cards ───────────────────────────── -->
<sys:String x:Key="Bench.RpmCommand.Title">RPM Command</sys:String>
<sys:String x:Key="Bench.RpmCommand.Actual">Actual</sys:String>
<sys:String x:Key="Bench.RpmCommand.Target">Target</sys:String>
<sys:String x:Key="Bench.RpmCommand.Apply">Apply</sys:String>
<sys:String x:Key="Bench.Actuators.Title">Actuators &amp; Relays</sys:String>
<sys:String x:Key="Bench.Actuators.Direction">Direction</sys:String>
<sys:String x:Key="Bench.Actuators.DirRight">Right</sys:String>
<sys:String x:Key="Bench.Actuators.DirLeft">Left</sys:String>
<sys:String x:Key="Bench.Actuators.OilPump">Oil Pump</sys:String>
<sys:String x:Key="Bench.Actuators.Counter">Counter</sys:String>
<sys:String x:Key="Bench.Actuators.Set">Set</sys:String>
<sys:String x:Key="Bench.Actuators.Temperature">Temperature</sys:String>
<sys:String x:Key="Bench.Actuators.Setpoint">Setpoint °C</sys:String>
<sys:String x:Key="Bench.Actuators.Tolerance">Tolerance ±°C</sys:String>
<sys:String x:Key="Bench.Actuators.Heater">Heater</sys:String>
<sys:String x:Key="Bench.Actuators.DepositCooler">Dep. Cool.</sys:String>
<sys:String x:Key="Bench.Actuators.TinCooler">T-In Cool.</sys:String>
<sys:String x:Key="Bench.Actuators.Relays">Misc Relays</sys:String>
<sys:String x:Key="Bench.Actuators.Electronic">Electronic</sys:String>
<sys:String x:Key="Bench.Actuators.Flasher">Flasher</sys:String>
<sys:String x:Key="Bench.Actuators.Pulse4">Pulse 4</sys:String>
<sys:String x:Key="Bench.LiveData.Title">Live Data</sys:String>
<sys:String x:Key="Bench.Charts.Title">Live Charts</sys:String>
<sys:String x:Key="Bench.Advance.Title">Advance Monitor</sys:String>
<sys:String x:Key="Bench.Advance.Delta">Lock Offset Δ°</sys:String>
<sys:String x:Key="Bench.Advance.ZeroPsg">Zero PSG</sys:String>
<sys:String x:Key="Bench.Advance.ZeroInj">Zero INJ</sys:String>
<sys:String x:Key="Bench.Advance.Lock">Lock</sys:String>
<sys:String x:Key="Bench.Kpi.Rpm">Bench RPM</sys:String>
<sys:String x:Key="Bench.Kpi.P1">Pressure P1</sys:String>
<sys:String x:Key="Bench.Kpi.P2">Pressure P2</sys:String>
<sys:String x:Key="Bench.Kpi.QDelivery">Q Delivery</sys:String>
<sys:String x:Key="Bench.Kpi.QOver">Q Over</sys:String>
<sys:String x:Key="Bench.Kpi.TIn">T-In</sys:String>
<sys:String x:Key="Bench.Kpi.TOut">T-Out</sys:String>
<sys:String x:Key="Bench.Kpi.T4">T4</sys:String>
<sys:String x:Key="Bench.Kpi.TTank">T-Tank</sys:String>
<sys:String x:Key="Bench.Kpi.BenchTemp">Bench Temp</sys:String>
<sys:String x:Key="Bench.Kpi.Unit.Bar">bar</sys:String>
<sys:String x:Key="Bench.Kpi.Unit.CcS">cc/s</sys:String>
<sys:String x:Key="Bench.Chart.Delivery">Q Delivery</sys:String>
<sys:String x:Key="Bench.Chart.Over">Q Over</sys:String>
<sys:String x:Key="Bench.Chart.P1">Pressure P1</sys:String>
<sys:String x:Key="Bench.Chart.P2">Pressure P2</sys:String>
<!-- ── Test panel ───────────────────────────────────────────────────── -->
<sys:String x:Key="Test.StartTest">▶ START TEST</sys:String>
<sys:String x:Key="Test.Stop">■ STOP</sys:String>
<sys:String x:Key="Test.Report">📄 Report</sys:String>
<sys:String x:Key="Test.ShowValues">Show values</sys:String>
<sys:String x:Key="Test.CheckAll">Check All</sys:String>
<sys:String x:Key="Test.SecondsRemaining">s remaining</sys:String>
<sys:String x:Key="Test.Condition">Cond:</sys:String>
<sys:String x:Key="Test.Measurement">Meas:</sys:String>
<sys:String x:Key="Test.MeasPerSec">M/s:</sys:String>
<sys:String x:Key="Test.Required">Required:</sys:String>
<sys:String x:Key="Test.TestLabel">Test:</sys:String>
<sys:String x:Key="Test.Critical">Critical</sys:String>
<sys:String x:Key="Test.Started">Test started...</sys:String>
<sys:String x:Key="Test.Stopped">Test stopped.</sys:String>
<!-- ── Tests-page wizard ──────────────────────────────────────────────── -->
<sys:String x:Key="Test.Wizard.Plan">1. Plan</sys:String>
<sys:String x:Key="Test.Wizard.Preconditions">2. Preconditions</sys:String>
<sys:String x:Key="Test.Wizard.Running">3. Running</sys:String>
<sys:String x:Key="Test.Wizard.Done">4. Done</sys:String>
<sys:String x:Key="Test.Wizard.Next">Next ▶</sys:String>
<sys:String x:Key="Test.Wizard.Back">◀ Back</sys:String>
<!-- ── Preconditions checklist ────────────────────────────────────────── -->
<sys:String x:Key="Test.Precheck.Title">Preconditions</sys:String>
<sys:String x:Key="Test.Precheck.PumpSelected">Pump selected</sys:String>
<sys:String x:Key="Test.Precheck.CanLive">CAN bus live</sys:String>
<sys:String x:Key="Test.Precheck.KLineOpen">K-Line session open</sys:String>
<sys:String x:Key="Test.Precheck.RpmZero">Bench RPM at zero</sys:String>
<sys:String x:Key="Test.Precheck.OilPumpOn">Oil pump running</sys:String>
<sys:String x:Key="Test.Precheck.NoCriticalAlarms">No critical alarms</sys:String>
<sys:String x:Key="Test.Precheck.UserAuth">User authenticated</sys:String>
<sys:String x:Key="Test.Precheck.FixButton">Fix</sys:String>
<sys:String x:Key="Test.Precheck.Ready">All preconditions met. Ready to start.</sys:String>
<sys:String x:Key="Test.Precheck.NotReady">Resolve the items above before starting.</sys:String>
<sys:String x:Key="Test.Precheck.AuthBanner">This test requires operator authentication.</sys:String>
<sys:String x:Key="Test.Precheck.AuthButton">Authenticate…</sys:String>
<sys:String x:Key="Test.Precheck.Remediation.SelectPump">Go to Pump page to select a pump.</sys:String>
<sys:String x:Key="Test.Precheck.Remediation.CheckCan">Open the Dashboard to check CAN connection.</sys:String>
<sys:String x:Key="Test.Precheck.Remediation.OpenKLine">Open a K-Line session on the Pump page.</sys:String>
<sys:String x:Key="Test.Precheck.Remediation.StopBench">Stop the bench from the Bench page.</sys:String>
<sys:String x:Key="Test.Precheck.Remediation.StartOilPump">Start the oil pump from the Bench page.</sys:String>
<sys:String x:Key="Test.Precheck.Remediation.ClearAlarms">Clear critical alarms on the Dashboard.</sys:String>
<sys:String x:Key="Test.Precheck.Remediation.Authenticate">Authenticate the operator above.</sys:String>
<!-- ── Running step controls ──────────────────────────────────────────── -->
<sys:String x:Key="Test.Running.Abort">■ Abort</sys:String>
<sys:String x:Key="Test.Running.Pause">Pause</sys:String>
<sys:String x:Key="Test.Running.Resume">Resume</sys:String>
<sys:String x:Key="Test.Running.Retry">Retry phase</sys:String>
<sys:String x:Key="Test.Running.Skip">Skip phase</sys:String>
<sys:String x:Key="Test.Running.ComingSoon">Coming soon</sys:String>
<!-- ── Done step ──────────────────────────────────────────────────────── -->
<sys:String x:Key="Test.Done.Passed">PASSED</sys:String>
<sys:String x:Key="Test.Done.Failed">FAILED</sys:String>
<sys:String x:Key="Test.Done.ViewFullResults">View full results</sys:String>
<sys:String x:Key="Test.Done.RunAgain">Run again</sys:String>
<!-- ── Abort confirmation ─────────────────────────────────────────────── -->
<sys:String x:Key="Test.Abort.Title">Abort test?</sys:String>
<sys:String x:Key="Test.Abort.Message">Stopping the test now will end the current phase and return partial results. Continue?</sys:String>
<sys:String x:Key="Test.Abort.Confirm">Abort</sys:String>
<sys:String x:Key="Test.Abort.Cancel">Keep running</sys:String>
<!-- ── Test types ───────────────────────────────────────────────────── -->
<sys:String x:Key="TestType.Warmup">Warm-up</sys:String>
<sys:String x:Key="TestType.Adjustment">Adjustment</sys:String>
<sys:String x:Key="TestType.Flow">Flow</sys:String>
<sys:String x:Key="TestType.ServoValve">Servo valve</sys:String>
<sys:String x:Key="TestType.Upstroke">Upstroke</sys:String>
<sys:String x:Key="TestType.PreInjection">Pre-injection</sys:String>
<!-- ── Result display ───────────────────────────────────────────────── -->
<sys:String x:Key="Result.Phase">Phase</sys:String>
<sys:String x:Key="Result.Parameter">Parameter</sys:String>
<sys:String x:Key="Result.Target">Target</sys:String>
<sys:String x:Key="Result.Tolerance">Tol ±</sys:String>
<sys:String x:Key="Result.Average">Average</sys:String>
<sys:String x:Key="Result.ResultHeader">Result</sys:String>
<sys:String x:Key="Result.AllTests">All Tests</sys:String>
<!-- ── Results page (§5) ────────────────────────────────────────────── -->
<sys:String x:Key="Results.PageTitle">Results</sys:String>
<sys:String x:Key="Results.HistoryHeader">Test history (session)</sys:String>
<sys:String x:Key="Results.DetailHeader">Run detail</sys:String>
<sys:String x:Key="Results.ObservationsLabel">Observations / Notes</sys:String>
<sys:String x:Key="Results.ExportButton">Export PDF…</sys:String>
<sys:String x:Key="Results.EmptyState">No completed tests yet. Finish a test on the Tests page to see it here.</sys:String>
<sys:String x:Key="Results.NoSelection">Select a run on the left to view its details.</sys:String>
<sys:String x:Key="Results.InterruptedLabel">INTERRUPTED</sys:String>
<sys:String x:Key="Results.DeleteTooltip">Remove this entry</sys:String>
<sys:String x:Key="Results.ClearSessionButton">Clear session</sys:String>
<sys:String x:Key="Results.ClearSessionConfirm">Clear all history entries for this session?</sys:String>
<!-- ── Common strings ───────────────────────────────────────────────── -->
<sys:String x:Key="Common.Pass">PASS</sys:String>
<sys:String x:Key="Common.Fail">FAIL</sys:String>
<sys:String x:Key="Common.Accept">Accept</sys:String>
<sys:String x:Key="Common.Cancel">Cancel</sys:String>
<sys:String x:Key="Common.Close">Close</sys:String>
<sys:String x:Key="Common.Save">Save</sys:String>
<sys:String x:Key="Common.Ok">OK</sys:String>
<sys:String x:Key="Common.Yes">Yes</sys:String>
<sys:String x:Key="Common.No">No</sys:String>
<sys:String x:Key="Common.Warning">WARNING</sys:String>
<sys:String x:Key="Common.Disabled">disabled</sys:String>
<sys:String x:Key="Common.Dismiss">Dismiss</sys:String>
<!-- ── Dialog: Report ───────────────────────────────────────────────── -->
<sys:String x:Key="Dialog.Report.Title">Generate Report</sys:String>
<sys:String x:Key="Dialog.Report.ClientList">Client List</sys:String>
<sys:String x:Key="Dialog.Report.ClientData">Client Data</sys:String>
<sys:String x:Key="Dialog.Report.CompanyData">Company Data</sys:String>
<sys:String x:Key="Dialog.Report.Name">Name:</sys:String>
<sys:String x:Key="Dialog.Report.ClientInfo">Client information</sys:String>
<sys:String x:Key="Dialog.Report.Observations">Observations</sys:String>
<sys:String x:Key="Dialog.Report.Operator">Operator:</sys:String>
<sys:String x:Key="Dialog.Report.Company">Company:</sys:String>
<sys:String x:Key="Dialog.Report.CompanyInfo">Company information</sys:String>
<sys:String x:Key="Dialog.Report.DeleteClient">Delete Client</sys:String>
<sys:String x:Key="Dialog.Report.Generate">Generate</sys:String>
<!-- ── Dialog: User authentication ──────────────────────────────────── -->
<sys:String x:Key="Dialog.UserCheck.Title">User Authentication</sys:String>
<sys:String x:Key="Dialog.UserCheck.Username">Username:</sys:String>
<sys:String x:Key="Dialog.UserCheck.Password">Password:</sys:String>
<!-- ── Dialog: Voltage warning ──────────────────────────────────────── -->
<sys:String x:Key="Dialog.Voltage.Title">Power Supply Warning</sys:String>
<sys:String x:Key="Dialog.Voltage.VoltageLabel">VOLTAGE: </sys:String>
<sys:String x:Key="Dialog.Voltage.PumpRequires">The selected pump requires </sys:String>
<sys:String x:Key="Dialog.Voltage.PowerSupply"> power supply.</sys:String>
<sys:String x:Key="Dialog.Voltage.SwitchTo">SWITCH THE POWER SUPPLY TO </sys:String>
<!-- ── Dialog: Oil pump confirmation ────────────────────────────────── -->
<sys:String x:Key="Dialog.OilPump.Title">Oil Pump Activation</sys:String>
<sys:String x:Key="Dialog.OilPump.Message">You are about to activate the oil pump. Confirm that the oil level is adequate and all connections are secure before proceeding.</sys:String>
<sys:String x:Key="Dialog.OilPump.LeaksChecked">I have checked — no leaks, connections are ready</sys:String>
<!-- ── Dialog: RPM safety warning ───────────────────────────────────── -->
<sys:String x:Key="Dialog.RpmSafety.Title">RPM Safety Warning</sys:String>
<sys:String x:Key="Dialog.RpmSafety.Message">The oil pump is OFF. Running the bench motor without oil circulation can cause bearing damage to the pump.</sys:String>
<sys:String x:Key="Dialog.RpmSafety.OilAndProceed">Turn on oil pump and start the bench</sys:String>
<sys:String x:Key="Dialog.RpmSafety.ProceedWithout">I know what I'm doing — start without oil</sys:String>
<!-- ── Dialog: Unlock progress ──────────────────────────────────────── -->
<sys:String x:Key="Dialog.Unlock.Title">Immobilizer Unlock</sys:String>
<sys:String x:Key="Dialog.Unlock.Progress">PROGRESS</sys:String>
<sys:String x:Key="Dialog.Unlock.Phase1">Phase 1: Sending unlock signals</sys:String>
<sys:String x:Key="Dialog.Unlock.Phase2Testing">Phase 2: Testing</sys:String>
<sys:String x:Key="Dialog.Unlock.Phase2Sending">Phase 2: Sending...</sys:String>
<sys:String x:Key="Dialog.Unlock.Cancelled">CANCELLED</sys:String>
<sys:String x:Key="Dialog.Unlock.Unlocked">UNLOCKED</sys:String>
<sys:String x:Key="Dialog.Unlock.Failed">UNLOCK FAILED</sys:String>
<sys:String x:Key="Dialog.Unlock.TypeLabel">Type {0}</sys:String>
<!-- ── Dialog: K-Line errors ────────────────────────────────────────── -->
<sys:String x:Key="Dialog.KlineErrors.Title">K-Line Fault Codes</sys:String>
<sys:String x:Key="Dialog.KlineErrors.Header">Fault codes:</sys:String>
<sys:String x:Key="Dialog.KlineErrors.Read">Read</sys:String>
<sys:String x:Key="Dialog.KlineErrors.Clear">Clear</sys:String>
<!-- ── Dialog: Settings ───────────────────────────────────────────────── -->
<sys:String x:Key="Dialog.Settings.Title">Settings</sys:String>
<sys:String x:Key="Dialog.Settings.Tab.General">General</sys:String>
<sys:String x:Key="Dialog.Settings.Tab.Safety">Safety</sys:String>
<sys:String x:Key="Dialog.Settings.Tab.Pid">PID</sys:String>
<sys:String x:Key="Dialog.Settings.Tab.Motor">Motor</sys:String>
<sys:String x:Key="Dialog.Settings.Tab.Report">Report</sys:String>
<sys:String x:Key="Dialog.Settings.Tab.KLine">K-Line</sys:String>
<sys:String x:Key="Dialog.Settings.Tab.Advanced">Advanced</sys:String>
<sys:String x:Key="Dialog.Settings.Language">Language:</sys:String>
<sys:String x:Key="Dialog.Settings.DaysKeepLogs">Days to keep logs:</sys:String>
<sys:String x:Key="Dialog.Settings.TempMax">Max. temperature (°C):</sys:String>
<sys:String x:Key="Dialog.Settings.TempMin">Min. temperature (°C):</sys:String>
<sys:String x:Key="Dialog.Settings.SecurityRpmLimit">Safety RPM limit:</sys:String>
<sys:String x:Key="Dialog.Settings.MaxPressureBar">Max. pressure (bar):</sys:String>
<sys:String x:Key="Dialog.Settings.ToleranceUp">UP tolerance extension:</sys:String>
<sys:String x:Key="Dialog.Settings.TolerancePfp">PFP tolerance extension:</sys:String>
<sys:String x:Key="Dialog.Settings.IgnoreTin">Ignore T-in by default</sys:String>
<sys:String x:Key="Dialog.Settings.PidP">Proportional (P):</sys:String>
<sys:String x:Key="Dialog.Settings.PidI">Integral (I):</sys:String>
<sys:String x:Key="Dialog.Settings.PidD">Derivative (D):</sys:String>
<sys:String x:Key="Dialog.Settings.PidLoopMs">Loop period (ms):</sys:String>
<sys:String x:Key="Dialog.Settings.EncoderRes">Encoder resolution:</sys:String>
<sys:String x:Key="Dialog.Settings.VoltMaxRpm">Voltage for max RPM (V):</sys:String>
<sys:String x:Key="Dialog.Settings.MaxRpm">Max RPM:</sys:String>
<sys:String x:Key="Dialog.Settings.RightRelay">Right = relay ON</sys:String>
<sys:String x:Key="Dialog.Settings.Relations">RPM-Voltage Table</sys:String>
<sys:String x:Key="Dialog.Settings.RelRpm">RPM</sys:String>
<sys:String x:Key="Dialog.Settings.RelVoltage">Voltage (V)</sys:String>
<sys:String x:Key="Dialog.Settings.AddRow">Add</sys:String>
<sys:String x:Key="Dialog.Settings.RemoveRow">Remove</sys:String>
<sys:String x:Key="Dialog.Settings.CompanyName">Company name:</sys:String>
<sys:String x:Key="Dialog.Settings.CompanyInfo">Company information:</sys:String>
<sys:String x:Key="Dialog.Settings.ReportLogo">Report logo path:</sys:String>
<sys:String x:Key="Dialog.Settings.BrowseLogoTitle">Select Logo Image</sys:String>
<sys:String x:Key="Dialog.Settings.KLinePort">K-Line port (FTDI):</sys:String>
<sys:String x:Key="Dialog.Settings.RefreshPorts">Refresh</sys:String>
<sys:String x:Key="Dialog.Settings.KLineHint">Select an FTDI device or type the serial number manually.</sys:String>
<sys:String x:Key="Dialog.Settings.RefreshBench">Bench interface (ms):</sys:String>
<sys:String x:Key="Dialog.Settings.RefreshReading">While reading K-Line (ms):</sys:String>
<sys:String x:Key="Dialog.Settings.RefreshCanBus">CAN bus read (ms):</sys:String>
<sys:String x:Key="Dialog.Settings.RefreshPumpReq">Pump request (ms):</sys:String>
<sys:String x:Key="Dialog.Settings.RefreshPumpParams">Pump params (ms):</sys:String>
<sys:String x:Key="Dialog.Settings.BlinkInterval">Blink interval (ms):</sys:String>
<sys:String x:Key="Dialog.Settings.FlasherInterval">Flasher interval (ms):</sys:String>
<sys:String x:Key="Dialog.Settings.UsersHeader">Users</sys:String>
<sys:String x:Key="Dialog.Settings.ManageUsers">Manage Users...</sys:String>
<!-- ── Dialog: User management ──────────────────────────────────────── -->
<sys:String x:Key="Dialog.UserManage.Title">User Management</sys:String>
<sys:String x:Key="Dialog.UserManage.ColumnUsername">Username</sys:String>
<sys:String x:Key="Dialog.UserManage.Add">Add...</sys:String>
<sys:String x:Key="Dialog.UserManage.Remove">Remove</sys:String>
<sys:String x:Key="Dialog.UserManage.ChangePassword">Change Password...</sys:String>
<sys:String x:Key="Dialog.UserManage.Close">Close</sys:String>
<sys:String x:Key="Dialog.UserManage.Prompt.AddTitle">Add User</sys:String>
<sys:String x:Key="Dialog.UserManage.Prompt.ChangeTitle">Change password for '{0}'</sys:String>
<sys:String x:Key="Dialog.UserManage.Confirm.RemoveTitle">Remove User</sys:String>
<sys:String x:Key="Dialog.UserManage.Confirm.Remove">Remove user '{0}'?</sys:String>
<sys:String x:Key="Dialog.UserManage.Error.EmptyTitle">Invalid Input</sys:String>
<sys:String x:Key="Dialog.UserManage.Error.Empty">Username and password cannot be empty.</sys:String>
<sys:String x:Key="Dialog.UserManage.Error.InvalidCharsTitle">Invalid Input</sys:String>
<sys:String x:Key="Dialog.UserManage.Error.InvalidChars">Username must not contain ':' or ','.</sys:String>
<sys:String x:Key="Dialog.UserManage.Error.DuplicateTitle">Duplicate User</sys:String>
<sys:String x:Key="Dialog.UserManage.Error.Duplicate">A user with that name already exists.</sys:String>
<sys:String x:Key="Dialog.UserManage.Error.LastUserTitle">Cannot Remove</sys:String>
<sys:String x:Key="Dialog.UserManage.Error.LastUser">Cannot remove the last remaining user.</sys:String>
<!-- ── Error messages ───────────────────────────────────────────────── -->
<sys:String x:Key="Error.ReportGeneration">Failed to generate report:\n{0}</sys:String>
<sys:String x:Key="Error.ReportTitle">Report Error</sys:String>
<sys:String x:Key="Error.PsgSync">PSG sync pulse not detected. Check encoder connection.</sys:String>
<sys:String x:Key="Error.PsgTitle">PSG Error</sys:String>
<sys:String x:Key="Error.EmergencyStop">EMERGENCY STOP: {0}</sys:String>
<sys:String x:Key="Error.KLineNotFound">K-Line device not found. Check that the FTDI adapter is connected.</sys:String>
<sys:String x:Key="Error.KLineTitle">K-Line Error</sys:String>
<sys:String x:Key="Error.AuthInvalid">Invalid username or password.\n(Both are case-sensitive.)</sys:String>
<sys:String x:Key="Error.AuthTitle">Authentication Error</sys:String>
<!-- ── PDF Report ───────────────────────────────────────────────────── -->
<sys:String x:Key="Pdf.ReportTitle">VP44 INJECTION PUMP TEST REPORT</sys:String>
<sys:String x:Key="Pdf.GeneratedBy">Generated by HC-APTBS</sys:String>
<sys:String x:Key="Pdf.Page">Page </sys:String>
<sys:String x:Key="Pdf.Of"> of </sys:String>
<sys:String x:Key="Pdf.Date">Date: {0:dd/MM/yyyy HH:mm}</sys:String>
<sys:String x:Key="Pdf.Operator">Operator: {0}</sys:String>
<sys:String x:Key="Pdf.Client">Client: {0}</sys:String>
<sys:String x:Key="Pdf.PumpIdentification">PUMP IDENTIFICATION</sys:String>
<sys:String x:Key="Pdf.PumpId">Pump ID:</sys:String>
<sys:String x:Key="Pdf.Model">Model:</sys:String>
<sys:String x:Key="Pdf.SerialNo">Serial No.:</sys:String>
<sys:String x:Key="Pdf.Injector">Injector:</sys:String>
<sys:String x:Key="Pdf.Tube">Tube:</sys:String>
<sys:String x:Key="Pdf.Valve">Valve:</sys:String>
<sys:String x:Key="Pdf.Tension">Tension:</sys:String>
<sys:String x:Key="Pdf.Rotation">Rotation:</sys:String>
<sys:String x:Key="Pdf.LockAngle">Lock Angle:</sys:String>
<sys:String x:Key="Pdf.Measured">Measured:</sys:String>
<sys:String x:Key="Pdf.Chaveta">Chaveta:</sys:String>
<sys:String x:Key="Pdf.PreInj">Pre-Inj.:</sys:String>
<sys:String x:Key="Pdf.EcuData">ECU DATA (K-Line)</sys:String>
<sys:String x:Key="Pdf.OverallResult">OVERALL TEST RESULT</sys:String>
<sys:String x:Key="Pdf.TestsExecuted">Tests executed: {0} of {1}</sys:String>
<sys:String x:Key="Pdf.ParamsEvaluated">Parameters evaluated: {0} / {1} passed</sys:String>
<sys:String x:Key="Pdf.TestHeader">TEST: {0}</sys:String>
<sys:String x:Key="Pdf.Phase">Phase</sys:String>
<sys:String x:Key="Pdf.Parameter">Parameter</sys:String>
<sys:String x:Key="Pdf.Target">Target</sys:String>
<sys:String x:Key="Pdf.ToleranceHeader">Tolerance ±</sys:String>
<sys:String x:Key="Pdf.Average">Average</sys:String>
<sys:String x:Key="Pdf.Result">Result</sys:String>
<sys:String x:Key="Pdf.ErrorBits"> ⚠ Error bits: {0}</sys:String>
<sys:String x:Key="Pdf.NoSampleData">No sample data available for graphical display.</sys:String>
<sys:String x:Key="Pdf.ChartSamples">Samples: {0} | Target: {1} ± {2} | Average: {3} | Result: {4}</sys:String>
<sys:String x:Key="Pdf.Observations">OBSERVATIONS</sys:String>
</ResourceDictionary>