Files
orisys-app/apps/studio/config/locales/en_US.json
T
ykcheungab 433b76e43c 修复 Studio 失败测试并新增合并门禁
把丢失的 box 录像放回 apps/studio/tests/data/,修掉第 3 节 3–10 号与两处过时测试桩,
注册 timing 标记并让根目录收集零错误;新增 tools/gate.ps1 与可选的 pre-push 钩子。
验证:studio 524 通过 19 跳过、shared 467 通过 18 跳过、ui_check 632 项 0 失败、gate.ps1 退出码 0。
细节见 docs/test-repair-plan.zh.md。
2026-10-18 19:24:31 +08:00

593 lines
36 KiB
JSON
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.
{
"app": {
"title": "Orisys Studio",
"about_title": "About",
"about_body": "Orisys Studio desktop application\nVersion: {app_version}"
},
"brand": {
"name": "ORISYS",
"tagline": "DieDong Technology",
"nav_live": "Live",
"nav_live_tip": "Current view: live monitoring. Click to leave history browsing.",
"nav_playback": "Replay",
"nav_playback_tip": "Open a recording: video, curves and one shared cursor",
"nav_calibration": "Calibration",
"nav_calibration_tip": "Show the calibration panel"
},
"menu": {
"file": "File",
"open_video": "Open video…",
"reveal_config": "Reveal sensor config…",
"playback": "Open recording replay…",
"playback_latest": "Replay most recent recording",
"session": "Session",
"analysis": "Analysis",
"view": "View",
"theme": "Theme",
"theme_dark": "Dark",
"theme_light": "Light",
"language": "Language",
"lang_zh": "简体中文",
"lang_en": "English",
"calibration_panel": "Calibration panel",
"finger_3d": "Finger 3D view",
"scene3d_settings": "3D display settings…",
"show_fps": "Show FPS",
"show_diagnostics": "Diagnostics",
"settings": "Settings area",
"plot_settings": "Plot settings…",
"rotate_arrows": "Rotate arrows 90°",
"recompute": "Analyze video",
"recompute_tip": "Use a result if there is one; otherwise analyse. Change settings in Analysis setup.",
"analysis_setup": "Analysis setup…",
"analysis_setup_tip": "Choose the profile, calibration and reference frame for this video, then run (or re-run) the analysis pass.",
"run": "Run / Stop",
"stop": "Cancel acquisition",
"preview": "Preview / Stop preview",
"reset": "Reset sensor tracker",
"reset_display": "Reset display",
"reset_view": "Reset views",
"reset_view_tip": "Put the chart window, cursor and 3D camera back to their defaults (F8). Touches neither the device nor the zero estimate.",
"pause": "Pause / resume (F7)",
"help": "Help",
"about": "About"
},
"dialog": {
"plot_settings_title": "Plot settings",
"plot_tab_curves": "Curves",
"plot_tab_filters": "Filters",
"plot_window": "Time window",
"plot_window_tip": "Force plot time window (seconds)",
"plot_fn_min": "FN min",
"plot_fn_min_tip": "Normal-force axis minimum (Newton mode); fixed at 0",
"plot_fn_max": "FN max",
"plot_fn_max_tip": "Normal force axis max (Newton mode)",
"plot_shear_max": "Shear max",
"plot_shear_max_tip": "Shear force axis ±max for FX/FY (Newton mode)",
"plot_fn_raw_min": "FN raw min",
"plot_fn_raw_min_tip": "Normal-force axis minimum in raw (uncalibrated) mode; may be negative",
"plot_fn_raw_max": "FN raw max",
"plot_fn_raw_max_tip": "Normal-force axis max in raw (uncalibrated) mode. 0 = auto range on the data; the default is sized so idle jitter is invisible in the plot",
"plot_shear_raw_max": "Shear raw max",
"plot_shear_raw_max_tip": "Shear-force axis ±max for FX/FY in raw (uncalibrated) mode. 0 = auto range",
"plot_deadband_n": "Zero threshold (N)",
"plot_deadband_n_tip": "Absolute per-axis zero threshold in N. Values within the threshold become 0; 0 disables it. Recordings retain acquired and processed values",
"plot_deadband_raw": "Zero threshold (raw)",
"plot_deadband_raw_tip": "Absolute per-axis zero threshold in raw counts. Values within the threshold become 0; 0 disables it. Calibration fitting still uses acquired samples",
"plot_value_decimals": "Value decimals",
"reset_defaults": "Reset to defaults",
"plot_orientation_group": "Finger 2D presentation (2D only; the 3D view keeps the design frame)",
"plot_orientation": "Orientation",
"plot_orientation_tip": "Affects the 2D view only; default rotation is 180°.",
"plot_orientation_note": "Affects the 2D view only; default rotation is 180°.",
"orientation_identity": "As drawn (no rotation)",
"orientation_rotate180": "Rotate 180° (default)",
"orientation_mirror_h": "Mirror horizontally",
"orientation_mirror_v": "Mirror vertically",
"plot_filters": "Filters (applied while acquiring; screen and record agree)",
"filter_preset": "Preset",
"filter_preset_tip": "A ready-made combination; editing any value below switches to Custom",
"filter_preset_custom": "Custom",
"filter_flow_ema": "Flow EMA α",
"filter_flow_ema_tip": "1.00 is off. Changing it changes the measured force.",
"filter_median": "Median window",
"filter_median_tip": "Sliding-median window over the force readings (samples). 1 = off. Removes single-sample spikes at the cost of about half a window of delay",
"filter_lowpass": "Low-pass cutoff",
"filter_lowpass_tip": "Low-pass cutoff for the force readings (Hz). 0 = off. Must stay below Nyquist (half the frame rate) or the device will not filter at all",
"filter_order": "Low-pass order",
"filter_order_tip": "Low-pass filter order (1–6). Steeper, with more phase distortion",
"filter_rate": "Sample rate",
"filter_rate_tip": "The rate the low-pass coefficients are designed for (Hz)",
"filter_rate_auto": "Follow the measured frame rate",
"filter_rate_auto_tip": "Design the low-pass for the device's measured rate; clear it to pin a number",
"filter_measurement_note": "The flow EMA is a *measurement* setting: changing it makes this recording incomparable with earlier ones.",
"filter_locked": "Filters cannot change while recording; this applies to the next session.",
"filter_nyquist": "Note: a {cutoff} Hz cutoff is at or above the Nyquist frequency of {nyquist} Hz (sample rate {rate} Hz) — the device would not filter. Lower the cutoff or pin a higher sample rate.",
"filter_off": "Not filtering (raw readings)",
"ok": "OK",
"cancel": "Cancel",
"save": "Save",
"close": "Close"
},
"toolbar": {
"search_cameras": "Search",
"cam_id": "Camera",
"use_camera": "Use camera",
"use_camera_tip": "Go back to acquiring from a camera (the data source is a video file)",
"choose_video": "Choose a recorded video…",
"choose_video_tip": "Open a recorded video: the 2D panel plays it and the charts read the forces.csv beside it",
"recompute": "Analyze video…",
"recompute_tip": "Use a result if there is one; otherwise analyse. Change settings in Analysis setup.",
"replay_view_only": "Open a recording from the History replay view",
"preview": "Preview",
"preview_stop": "Stop preview",
"run": "Run",
"stop": "Stop",
"run_label": "▶ Run",
"stop_label": "■ Stop",
"cancel_label": "■ Cancel",
"cancel_tip": "Abort the connection (always available while connecting, shortcut Esc)",
"run_unavailable": "Not available yet",
"run_video_in_replay": "Live uses a camera: press Use camera",
"run_disabled_sensor": "Run is not available for this sensor type",
"playback": "▶ Play",
"playback_pause": "⏸ Pause",
"playback_tip": "Play this recording at 1× (space bar does the same); dragging the cursor pauses",
"playback_pause_tip": "Pause playback (dragging the cursor, box zoom or the wheel also pauses)",
"playback_disabled": "Open a recorded video first (“Choose a recorded video…” at the top left)",
"playback_needs_recording": "This video has no recording beside it (no forces.csv): replay needs a recording; to just watch the video open it as a video, or use Analysis ▸ Analyze video",
"playback_video_only": "Play this video (no recording beside it: the picture plays, the force charts are empty)",
"reset_sensor": "Reset sensor",
"reset_sensor_tip": "Reset the sensor tracker and its reference frame. Force thresholds remain as configured; chart history is kept.",
"reset_sensor_unavailable": "Zero the sensor tracker — available while a session is running (start a run first).",
"reset_display": "Reset display",
"reset_display_tip": "Clear the accumulated display: the curves, cursor and value cards go back to their defaults and the replay returns to the start of the recording. There is no device session in this view, so nothing of the device is touched; the 3D camera is View ▸ Reset views (F8).",
"pause": "⏸ Pause",
"pause_tip": "Pause computation; the picture holds and the device stays connected (F7). A pause leaves a gap in the recording.",
"resume_tip": "Resume the computation and the display (F7), from the newest frame.",
"resume_label": "▶ Resume",
"resume_label_tip": "Resume the computation and the display (F7): it carries on from the newest frame with the device still connected.",
"stop_playback": "Stop",
"stop_playback_tip": "Stop the replay: plain playback and a “recompute from the video” pass both stop here (Esc does the same).",
"stopped": "Stopped: {what}",
"stopped_playback": "playback",
"stopped_pass": "the recompute pass",
"nothing_to_stop": "Nothing is playing or recomputing",
"units": "Units",
"units_newton": "Newton",
"units_raw": "Raw",
"settings": "Settings",
"settings_tip": "Show or hide the unit, record-mode and preview controls"
},
"units": {
"newton_short": "N",
"raw_short": "raw"
},
"sensor": {
"type": "Sensor",
"config": "Sensor config",
"type_tip": "Pick the product/sensor: box, mini or finger. It decides which config files and algorithm parameters exist.",
"config_tip": "The algorithm config file (config/*.json) this sensor uses. Switching the sensor switches the available configs with it.",
"summary": "{type} · {config}",
"dialog_title": "Sensor and calibration",
"dialog_tip": "Pick the sensor type and config, and read the calibration in effect and the last exported coefficients",
"calib_section": "Calibration in effect",
"calib_version": "Version confirmed by the device",
"calib_axes": "Calibrated axes",
"calib_config": "Config",
"calib_none": "the device has not confirmed a calibration",
"export_section": "Last exported coefficients",
"export_none": "No coefficients exported yet",
"export_file": "file {name} ({size} KB, {time})",
"export_identity": "file identity type {sensor_type} · SN {sn} · config {config}",
"thumb_placeholder": "Product model",
"family_unidentified": "Unidentified",
"catalog_name": "name {name} · folder {folder}",
"catalog_profile": "Profile {profile_id} · {shape} · from {origin}",
"catalog_root": "root {origin}: {path}",
"catalog_state": "SDK validation: {state} ({note})",
"catalog_state_ok": "processing can start",
"catalog_state_degraded": "processing can start; something optional is missing",
"catalog_state_failed": "processing cannot start",
"catalog_state_invalid": "no bundle could be read here",
"catalog_state_unknown": "verdict not recognised",
"catalog_calibration_selected": "Calibration selected: {name}",
"catalog_calibration_none": "No calibration selected — raw force",
"live_calibration_section": "Live calibration",
"live_calibration_raw_tip": "Run will open with raw force. Apply while running only remembers the choice; restart to drop loaded coefficients.",
"live_calibration_default_tip": "Run will load the profile default {name}.",
"live_calibration_file_tip": "Run will load {name}; Apply while running hot-updates the device.",
"live_calibration_apply_tip": "Remember this choice; hot-update the device if a session is running",
"live_calibration_remembered": "Calibration choice remembered; it loads on the next run",
"live_calibration_applied": "Requested hot-update of calibration: {name}",
"live_calibration_invalid": "That calibration choice is not valid: {reason}",
"catalog_duplicate": "Also provided by {refs}",
"catalog_shape_descriptor": "descriptor bundle",
"catalog_shape_compatibility": "compatibility bundle, no descriptor",
"catalog_shape_unreadable": "no readable bundle",
"catalog_blocked": "Cannot start: {reason}",
"catalog_warning": "Warning: {sentence}",
"catalog_error": "Error: {sentence}"
},
"panels": {
"arrow": "2D image",
"view_arrows_pure": "Arrows",
"view_arrows_stitched": "Arrows / Captured",
"view_depth": "Depth map",
"view_depth_arrows": "Depth + arrows",
"view_recorded": "Recorded image",
"view_mode_tip": "Image display mode while running",
"arrow_settings_tip": "Finger 2D presentation (orientation; display only)",
"replay_pipeline": "Recorded video (raw camera image)",
"replay_pipeline_tip": "This is the recorded camera image. For arrows and depth use Analysis ▸ Analyze video.",
"replay_raw_note": "No analysis result yet; use Analysis ▸ Analyze video.",
"frame_missing_note": "This frame carries no {fields}: there is nothing for this view to draw",
"field_flow": "flow",
"field_depth": "depth",
"recompute_pipeline": "Recomputed from the recording (not the recorded value)",
"recompute_pipeline_tip": "This frame is what the current algorithm version computes for that footage — not the measurement that was recorded at the time.",
"replay_empty": "No video open\nPress “Choose a recorded video…” above",
"arrow_empty": "No image yet\nConnect a camera, then press Run above\nOpen recorded videos in Replay",
"arrow_empty_tip": "The deformation arrow image appears here while running or previewing",
"arrow_render_failed": "Flow arrows could not be drawn for this frame\nTry another view, or reload the video",
"arrow_capture_unavailable": "The captured frame is not available for this overlay\nThe raw camera view is still one selection away",
"depth_unavailable": "No depth data for this frame",
"depth_scale": "Depth scale {low} – {high}",
"arrow_scale": "Arrows: displacement ×{factor}",
"arrow_scale_tip": "Arrow length is magnified by displacement.",
"arrow_pipeline": "Captured image → algorithm output",
"arrow_pipeline_tip": "Arrows are drawn over the algorithm output, not over the raw camera frame: points below the threshold get no arrow",
"arrow_area_masked": "Valid area",
"arrow_area_full": "Full frame",
"depth_scale_tip": "Fixed for this session: the range is latched to the first frame that carried depth so frames stay comparable. Grey marks samples with no depth.",
"depth_scale_tip_adaptive": "Per-frame adaptive scale: the range follows this frame's valid depth, and the 2D and 3D views share it. Grey marks samples with no depth.",
"depth_scale_tip_fixed": "Fixed scale: both the 2D and 3D views use the bounds typed in settings. Grey marks samples with no depth.",
"plots": "Force Charts",
"cal": "Calibration",
"mesh3d": "3D mesh",
"mesh3d_empty": "3D surface view",
"mesh3d_empty_tip": "3D surface view for finger sensors (coloured by the live deformation field)",
"mesh3d_no_scene": "No 3D scene for this sensor type",
"mesh3d_no_asset": "No compiled 3D scene installed.\nA scene package (*.oryscene) is looked for in:\n{directory}\nBuild one with tools/scene_assets/compile_scene.py — the names of the files it needs are in its --help. Only the 3D view is affected; measuring, recording and the charts work as usual.",
"mesh3d_loading": "Loading 3D scene {name}…",
"mesh3d_rejected": "The 3D scene was refused: {message}\nOnly the 3D view is affected; measuring, recording and the charts work as usual.",
"mesh3d_unavailable_gl_reason": "3D is not available on this machine: {reason}\nMeasuring, recording and the charts work as usual.",
"mesh3d_settings_tip": "3D display settings (view, housing, colour scale, frame rate)",
"mesh3d_reset_tip": "Reset view: back to the framing the scene itself uses",
"replay_analysis_running": "Analysing; arrows and depth appear when it finishes.",
"replay_analysis_failed": "Analysis failed: {reason}.",
"replay_analysis_unavailable": "No analysis setup yet; use Analysis ▸ Analyze video."
},
"chart": {
"fn": "FN",
"fx": "FX",
"fy": "FY",
"fn_name": "Normal force",
"fx_name": "Shear X",
"fy_name": "Shear Y",
"window_readout": "{start} – {end} s / {total} s total",
"window_tip": "Drag the highlighted region to move the window: this strip is the timeline of the whole session",
"no_data": "—",
"mode_follow": "Following live",
"mode_follow_tip": "The charts follow the newest sample and the window scrolls with it",
"mode_browse": "Browsing history",
"mode_browse_tip": "Display paused, capture and recording continue; drag or scroll to move the window, “back to latest” returns to live",
"mode_replay": "Replaying a recording (browsing)",
"mode_replay_tip": "The charts read the open recording; capture and recording continue",
"mode_recomputed": "Recomputed from this video (browsing)",
"mode_recomputed_tip": "Curves come from this analysis, not forces.csv.",
"mode_no_trace": "No force trace — {reason}",
"mode_no_trace_tip": "There is nothing to plot, and the reason is a fact about the input rather than a loading state",
"trace_not_analysed": "this video has not been analysed yet",
"trace_no_force": "this profile's chain produced no force for this video",
"return_latest": "Back to latest",
"return_latest_tip": "Leave history browsing and follow the newest data again",
"overview": "Whole session",
"overview_tip": "Fit the entire session; drag the overview strip to move the window",
"box_zoom": "Box zoom",
"box_zoom_tip": "Switch to rubber-band zoom (drag a region on the chart)",
"settings": "Chart settings",
"settings_tip": "Time window, axis ranges, and the acquisition filters (screen and record use the same data)",
"selection_summary": "Selection {duration}s / {samples} samples",
"selection_empty": "No valid samples in the selection",
"value_unavailable": "n/a",
"value_unavailable_tip": "No curve is loaded for {channel}, so it has no value in this unit (raw counts are never shown in its place)",
"zero_zone": "zero zone",
"zero_zone_tip": "This value is within the configured threshold; curves and output columns also show zero. Original samples are retained.",
"unit_toggle": "Switch unit",
"unit_toggle_tip": "Click to switch the three curves and readouts between newton and raw units",
"browse_only_tip": "Drag or scroll on the chart to browse history"
},
"playback": {
"open": "Open a recorded video…",
"video_filter": "Recorded video (*.mp4 *.avi *.mov *.mkv);;All files (*)",
"no_video": "This recording has no usable video segment",
"open_failed": "Could not open that recording: {error}",
"not_a_recording": "No forces.csv beside it; cannot open as a recording.",
"video_only_opened": "Opened “{name}”; no analysis result yet. Choose Analyze video… above to generate one.",
"video_only_notice": "This video has no recording beside it (no forces.csv): it plays, but the force charts and the recording details are empty.",
"video_only_panel": "This is not a recording, and this video cannot be decoded (no forces.csv beside it, and it does not read as playable video)\nYou can still try Analysis ▸ Analyze video",
"empty_recording": "This recording has no playable picture (no raw_*.mp4 segment), so it cannot be replayed",
"none_found": "No recording found under outputs/recordings",
"frame_dropped": "This frame never reached the video (the record queue overflowed)",
"frame_unreadable": "This frame could not be decoded from the video",
"warnings": "Replay notes: {detail}",
"decimated": "This recording is long, so the curves are a decimated view ({shown} of {total} rows; intervals are read from disk on demand)",
"warn_config_changed": "the config differs from recording time, so recomputing from the video may differ",
"warn_sdk_changed": "the SDK version differs from recording time, so recomputing may differ",
"warn_config_missing": "no config hash was recorded, so recomputation cannot be verified",
"warn_rows_skipped": "some unparsable CSV rows were skipped",
"warn_frames_dropped": "frames were lost to a full queue; only their index rows remain (shown as \"not recorded\")",
"warn_out_of_order": "this recording was written by an older version: its rows are not in time order, so the replay re-sorts them and window edges may differ",
"analysis_empty": "this analysis result holds no frame to show",
"analysis_unreadable": "this frame cannot be read ({error})",
"analysis_cancelled": "the analysis was cancelled: no complete result was written, so no playback is served",
"analysis_no_source": "this recording has no video segment to analyse",
"analysis_busy": "an analysis is already running: wait for it, or cancel it",
"analysis_no_chain": "this recording does not say which sensor and configuration produced it ({error}), so no result can be read and no pass can be run",
"analysis_setup_declined": "no analysis was set up for this video: the setup prompt was dismissed, so there is nothing to draw from. Use Analysis ▸ Analysis setup… or open the video again"
},
"video_analysis": {
"title": "Analyse this video",
"video": "{name} — {frames} frames at {fps} fps",
"profile": "Processing profile",
"calibration": "Calibration",
"calibration_default": "Profile default — {name}",
"calibration_none": "No calibration — raw force",
"calibration_file": "Chosen file — {name}",
"calibration_browse": "Choose a file…",
"calibration_filter": "Force calibration (*.json);;All files (*)",
"device": "Device id",
"device_tip": "Must match the SN in the calibration file",
"device_required": "A Finger calibration needs the device id of the sensor in this video",
"device_missing_sn": "This calibration file has no SN, so it cannot be matched to a sensor",
"device_mismatch": "The calibration file's SN is {sn}, which is not the device id entered",
"device_family": "This calibration belongs to {family}, not Finger",
"reference": "Reference frame",
"reference_time": "{seconds} s",
"blocked": "This profile cannot be used: {reason}"
},
"record": {
"mode_video_data": "Video + data",
"mode_data_only": "Data only",
"mode_tip": "Video records the pre-processing camera input (no arrows or text overlays). MP4 is a lossy container, not a lossless copy of the raw data.",
"start_label": "● Start recording",
"stop_label": "■ Stop recording",
"start_tip": "Record this experiment: video, force data and metadata into one directory",
"stop_tip": "Stop recording and write session.json (always available)",
"requires_run": "Press Run to start acquisition before recording",
"started": "Recording started ({mode})",
"start_failed": "Could not start recording: {error}",
"finished": "Recording finished — {frames} frames / {segments} segment(s) in {path}",
"finished_with_problems": "Recording finished with problems: {detail}",
"closing": "Closing the recording files…",
"alarm": "Recording problem: {detail}",
"state_idle": "No recording",
"state_recording": "Recording {duration}",
"state_closing": "Closing files…",
"state_error": "Write error ({count})",
"state_done": "Last recording: {frames} frames",
"dropped": "{count} dropped",
"strip_idle": "This session has not started a recording yet",
"strip_no_error": "none",
"strip_no_path": "not created yet",
"strip_tip": "Recording state: {state}\nFrames {frames} / segments {segments} / duration {duration}\nDropped {dropped} (data {dropped_data}, video {dropped_video}, gaps {dropped_gaps})\nWrite errors {errors}\nLast error: {detail}\nOutput directory {path}"
},
"cal": {
"weight": "Weight (N)",
"duration": "Record duration",
"record": "Record",
"recording_stop": "Stop",
"record_disabled": "Press Run to start acquisition before recording samples",
"record_cancelled": "Recording cancelled",
"empty_hint": "No samples for this channel yet: run, pick a channel and press Record.",
"delete_row": "Delete row",
"clear_channel": "Clear channel",
"clear_all": "Clear all",
"export": "Export coefficients…",
"export_tip": "Write the SDK coefficient file only; the running device is untouched",
"apply": "Apply to device",
"apply_tip": "Push the last export to the running device (confirmed again)",
"apply_no_export": "No exported coefficients yet — export them first",
"save_record": "Save record…",
"save_record_tip": "Save every point of this session with its full three-axis samples (audit data), independently of the coefficient file",
"save_record_empty": "No calibration points to save yet",
"save_record_ok": "Saved the calibration record to {path}\n{points} point(s), {samples} three-axis samples",
"save_record_failed": "Could not save the calibration record: {error}",
"open_record": "Open record…",
"open_record_tip": "Reopen a saved calibration session to inspect every point's samples and diagnostics",
"open_record_filter": "Calibration records (*.json)",
"open_record_ok": "Loaded {path} ({points} point(s))",
"open_record_device": "Recorded on: {device}",
"open_record_warnings": "Note: {detail}",
"open_record_failed": "Could not open the calibration record: {error}",
"apply_mismatch_title": "Calibration does not match the target device",
"apply_mismatch": "This coefficient file belongs to: {device}\nMismatch: {detail}\n\nCurrent target: {sensor_type} / {config}\n\nApplying it would load coefficients that were not measured on this device.",
"apply_mismatch_skipped": "Apply cancelled (the calibration belongs to another device)",
"sn": "SN",
"sn_placeholder": "Serial number (optional)",
"live_raw_label": "Live raw",
"live_raw": "Live raw FN={fn} FX={fx} FY={fy}",
"col_weight": "Reference load",
"col_fn": "FN mean",
"col_fx": "FX mean",
"col_fy": "FY mean",
"col_stability": "Stability",
"col_state": "State",
"state_ok": "OK",
"state_excluded": "Excluded",
"state_validation": "Validation",
"state_exclude": "Exclude",
"state_exclude_tip": "Drop the selected point from the fit and the export (kept on record, reversible)",
"state_restore": "Restore",
"mark_validation": "Mark validation",
"mark_validation_tip": "Hold the selected point out of the fit and use it to test the fit",
"excluded": "Point excluded from the fit",
"restored": "Point restored",
"marked_validation": "Point marked as a validation point",
"unmarked_validation": "Validation mark removed",
"fit_insufficient": "A fit needs at least 2 usable points (currently {count})",
"fit_summary": "Exported model {channel}: {method} ({count} points / {breakpoints} breakpoints, max residual {residual} N)",
"fit_validation": "Independent validation on {count} point(s), max deviation {error} N",
"method_piecewise_linear": "piecewise linear",
"method_linear": "linear",
"point_title": "Calibration point {channel} @ {load} N",
"point_channel": "Loaded axis",
"point_direction": "Direction",
"point_round": "Round",
"point_duration": "Actual sampling time",
"point_duration_value": "{actual} s (requested {requested} s)",
"point_samples": "Samples",
"point_samples_value": "{valid} valid / {total} total",
"point_axes": "Three-axis mean ± std",
"point_residual": "Fit residual",
"recording": "Recording calibration samples…",
"recording_stop_tip": "Click to cancel this calibration recording (always available)",
"record_ok": "Recorded weight={weight} raw={raw}",
"record_failed_few": "Recording failed — too few samples",
"export_ok": "Exported {path}",
"export_warnings": "Skipped: {detail}",
"export_failed": "Export failed: {error}",
"export_no_model": "Nothing to export: {detail}",
"apply_title": "Apply calibration",
"apply_confirm": "Apply the calibration just exported to the current device?\n\nSensor type: {sensor_type}\nConfig: {config}\n\nChoosing No keeps the exported file and leaves the running device untouched.",
"apply_skipped": "Exported; not applied to the device",
"apply_pending": "Requested calibration for {sensor_type}; waiting for the device to confirm…",
"applied": "Device confirmed the calibration is in effect (version {version})",
"applied_none": "Device confirmed: no calibration is loaded (the column stays empty)",
"export_only": "Exported coefficients to {path} (not applied to the device)",
"apply_no_target": "No device to apply to (run an acquisition first)"
},
"status": {
"phase_idle": "Idle",
"phase_connecting": "Connecting",
"phase_running": "Acquiring",
"phase_error": "Error",
"rail_video_name": "Video: {name}",
"rail_recent_video": "Previous video: {name}",
"rail_result_profile": "Result: {type}",
"rail_result_reused": "Stored result",
"rail_result_complete": "Analysis complete",
"rail_result_running": "Analysing…",
"rail_result_ready": "Result ready",
"data_valid": "Data valid",
"data_invalid": "{count} invalid sample(s)",
"calibrated": "Calibrated",
"calibrated_all": "Calibrated · 3 axes",
"calibrated_axes": "Calibrated · {axes}",
"uncalibrated": "Uncalibrated",
"config_none": "no config",
"camera_none": "No cameras found",
"camera_found": "Found {count} camera(s): {names}",
"preview_started": "Preview started (camera {camera_id})",
"preview_stopped": "Preview stopped",
"preview_failed": "Preview failed: {error}",
"connect_slow": "This is taking a while — click “Cancel” or press Esc to abort",
"run_stopped": "Stopped",
"run_stopping": "Stopping… (releasing the device)",
"run_stopping_cancelled": "Connection cancelled (releasing the device)",
"sample_invalid": "Invalid sample (#{count}): {reason} — marked invalid and excluded from the curves and from calibration",
"samples_dropped": "Record buffer is full; the oldest {count} samples were released (the full session is no longer complete)",
"run_failed": "Run failed: {error}",
"filters_saved": "Filter settings saved: {describe} (applies to the next session)",
"rail_camera_fps": "camera {fps}",
"capture_slow": "Camera frame rate is below the configured value: {detail}.",
"video_ended": "Video ended",
"camera_disconnected": "Camera disconnected",
"reset_ok": "Sensor tracker reset",
"reset_pending": "Sensor tracker reset requested; waiting for acquisition-thread confirmation…",
"reset_display": "Display reset: curves back to their defaults, replay at the start",
"view_reset": "Views reset",
"paused": "Paused: nothing is computed, the device stays connected",
"resumed": "Resumed",
"finger_run_unavailable": "Run is not available for this sensor type",
"video_required": "Select a video file first",
"config_missing": "Sensor config not found for {type}",
"units_raw_fallback": "No usable calibration; showing raw for now",
"reveal_failed": "Could not reveal config: {error}"
},
"scene3d": {
"enable": "Show the 3D view",
"preset": "View",
"housing": "Housing",
"deform": "Exaggerate",
"deform_tip": "Display-only magnification of the measured deformation. It changes the picture and nothing else: the recorded data, the calibration and the camera are not touched.",
"deform_unavailable": "This data has no 3D displacement; exaggeration is unavailable.",
"field": "Colour by",
"field_tip": "Colour the surface by depth or optical flow.",
"field_depth": "Depth response",
"field_flow": "Optical flow magnitude",
"field_substituted": "This frame shows {shown}, not the chosen {chosen}.",
"flow_arrows": "Surface flow arrows",
"flow_arrows_tip": "Draw optical-flow arrows on the sensing surface using the same sample points as the 2D view.",
"flow_arrows_unavailable": "This scene cannot draw flow arrows.",
"contact_arrow": "Contact normal arrow",
"contact_arrow_tip": "Draw a yellow local-normal arrow at the contact centre (length from the normal response, capped — not a calibrated force vector).",
"contact_arrow_unavailable": "This scene cannot draw the contact arrow.",
"flow_threshold": "Arrow threshold",
"flow_threshold_tip": "Arrows below this displacement (px) are not drawn; shared by 2D and 3D.",
"depth_threshold": "Depth display threshold",
"depth_threshold_tip": "Values below this relative depth response use the base ramp colour; 0 disables it. Shared by 2D and 3D without changing measurements.",
"quantity_flow_magnitude": "Optical flow magnitude",
"quantity_depth_response": "Depth response",
"preset_default": "Default view",
"legend_effective": "{quantity} [{unit}] · {mode} scale {lower} – {upper} · {quality}",
"legend_auto": "automatic",
"legend_fixed": "fixed",
"scale": "Colour scale",
"scale_range": "Range",
"scale_range_tip": "Bounds used when the colour scale is fixed. In automatic mode the depth scale stays latched to the first frame of the session, unless Per-frame adaptive is on — then both the 2D and 3D views refit to the current frame's valid depth.",
"depth_adaptive": "Per-frame adaptive",
"depth_adaptive_tip": "When on, the 2D depth view and the 3D surface both refit the colour scale to the current frame's valid depth. When off, the scale stays latched to the first depth frame of the session so frames stay comparable. This switch does nothing while the colour scale is fixed.",
"scale_fixed": "Fixed",
"scale_auto": "Automatic",
"max_fps": "Display rate",
"max_fps_tip": "How many frames per second the 3D view draws. A display budget only: the camera and the recording are unaffected, and a dropped frame here is never a dropped sample.",
"reset_view": "Reset view",
"settings_title": "3D display settings",
"settings_hint": "Depth display threshold and per-frame adaptive apply to both 2D and 3D.",
"legend": "{quantity} [{unit}] · {quality}",
"legend_none": "No measurement on screen — the surface model is shown uncoloured",
"quality_calibrated": "calibrated",
"quality_approximate": "relative deformation, illustration",
"quality_display_only": "display only",
"state_disabled": "3D view is off",
"state_loading": "Loading the scene…",
"state_ready": "Ready — waiting for the first frame",
"state_live": "Live",
"state_no_data": "No valid measurement in this frame — showing the surface model",
"state_suspended": "Suspended (the view is hidden)",
"state_stale": "Measurement expired — the last frame is still shown but is not current",
"state_unavailable": "3D is unavailable",
"source_live": "Live acquisition",
"source_live_tip": "The picture comes from the data being acquired right now.",
"source_replay": "Replay: the recording stores no 3D field",
"source_replay_tip": "A recording stores the raw camera image and the forces, not a per-frame deformation field. Turn on Analyze video and this pane will show the deformation from the analysis result.",
"source_recompute": "From the analysis result — not the recorded values",
"source_recompute_tip": "This is what the current algorithm version says about the footage in the stored analysis result: it is not the measurement that was recorded at the time.",
"severity_info": "Note",
"severity_warning": "Warning",
"severity_error": "Error",
"stats": "shown {displayed} · frames not shown in time {dropped} · compose {compose} ms · paint {paint} ms",
"source_analysis": "Analysis result: read by frame",
"source_analysis_tip": "The picture comes from a stored analysis result. Changing a threshold or colour does not recompute."
},
"analysis": {
"title": "Analysing the recording",
"title_reused": "Using a stored analysis result",
"title_complete": "Analysis complete",
"title_cancelled": "Analysis cancelled",
"title_failed": "Analysis failed",
"frames": "{written} / {expected} frames",
"segment": "segment {index} / {count}",
"elapsed": "{seconds:.1f} s elapsed",
"cancel": "Cancel",
"cancelling": "Cancelling…",
"cancel_tip": "Cancel this pass: the frames already written stay, but the result is marked incomplete and is never played back as if it were whole",
"complete": "analysis finished: {frames} frames in {seconds:.1f} s",
"cancelled": "analysis cancelled ({frames} frames written; the result is marked incomplete)",
"failed": "analysis failed: {reason}",
"blocked": "a session is running: stop it before analysing"
}
}