7e415c4ae9
- What:
1. **回放里一键重算**:`ui/toolbar.py` 的 replay 组新增 `btn_recompute`(可选中的"由视频重算…",
信号 `recompute_clicked`、`set_recompute_enabled/checked`、tooltip 说明"2D 面板会显示处理后的图像,
录像本身只存了原始相机图像");`app_window` 把它接到 `act_recompute`(同一个开关,所以菜单、rail 与
`_on_recompute_toggled` 不会各走一套),并在 `_refresh_replay_state`/`_sync_replay_actions` 里同步
可用与选中状态。
2. **实时界面禁止回放入口**:新增 `_sync_replay_actions()`——`act_open_video`/`act_playback`/
`act_playback_latest` 只在 `_view_preset == "replay"` 时可用,否则禁用并把原因写进 tooltip
(`toolbar.replay_view_only` = "请在「历史回放」视图里打开录像");`_load_replay_video()` 与
`_open_latest_recording()` 在非 replay 预设下**直接拒绝并提示**,不再改动 `source_mode`/`video_path`
(原来打开一段没有 forces.csv 的视频会走到 `_load_replay_video` 的裸视频分支,把采集源切成文件而 2D
面板什么都没变)。rail 的回放按钮本来就在 replay 分组(`toolbar.py:476/598`),不改动;空格键原本就按
`run_role == "playback"` 收口,加了断言。
3. locale:新增 `toolbar.recompute`/`toolbar.recompute_tip`/`toolbar.replay_view_only`(中英各一套)。
- Why: 用户报的第二个 bug——「实时检测界面还是可以回放视频,建议回放会自动切到历史回放上面」,并在两个
选项里选了"实时界面禁止回放入口(反向做法)"。核对确认:`_on_browse_video`/`_load_replay_video` 在实时
预设下可用且只设 `source_mode="video"` + `video_path`,不切视图预设;随后 `_render_replay_frame()` 因
`_view_preset != "replay"` 直接返回、`_can_recompute()` 同因返回 False,于是界面停在"实时"却已经把采集源
换成了视频——按运行键就"在实时界面跑视频"。配套地,回放里"看不到处理后的图像"这一个用户期待,由
「由视频重算」给出:它现在就在回放视图的 rail 上,点一下即可,2D 面板与实时共用同一个后端(见上一提交)。
注意区分:实时视图用视频**当采集源**(`source_mode == "video"` 显示"回到摄像机")是另一项既有能力,保留
不变,只是不再由回放路径隐式设置。
- Verification:
· `test_ui_smoke.py` +1(`test_the_replay_entries_exist_only_in_the_replay_view`):实时预设下三个文件
菜单动作禁用且 tooltip 带原因、rail 无回放/重算按钮、`_load_replay_video()` 返回 False 且
`replay.has_video()`/`source_mode()`/播放定时器都不变、空格不启动回放;切到历史回放后三者可用、裸视频
仍能打开(`plan_modes() == ("recorded",)`)、rail 的重算按钮可点并同步 `act_recompute`。
· 既有用例继续通过:`test_a_bare_video_plays_even_though_it_is_not_a_recording`(先切到历史回放再打开,
播放与逐帧解码不受影响)、`test_depth_view_...`、三维与记录相关用例。
· 全量:apps/studio 237 项 0 失败 14 跳过;ui_check 587 项 0 失败;locale_check 0 缺失(zh/en 键集合
仍一致)。
- Not in this change: 没有改成"打开视频时自动切视图"(按用户选择,改为禁止 + 说明);`source_mode == "video"`
在实时视图的既有行为未动("由视频当相机"仍可用,只是入口不再是回放路径);阶段 8(界面与有效控制)与
阶段 9(限速/统计/保护包)未开始。
437 lines
26 KiB
JSON
437 lines
26 KiB
JSON
{
|
||
"app": {
|
||
"title": "Orisys Studio",
|
||
"about_title": "About",
|
||
"about_body": "Orisys Studio desktop application\nVersion: {app_version}",
|
||
"scaffold_hint": "Scaffold shell — acquisition coming later"
|
||
},
|
||
"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",
|
||
"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",
|
||
"show_fps": "Show FPS",
|
||
"settings": "Settings area",
|
||
"plot_settings": "Plot settings…",
|
||
"rotate_arrows": "Rotate arrows 90°",
|
||
"recompute": "Recompute forces from the video",
|
||
"recompute_tip": "Off: the charts read the recorded forces.csv. On: re-run the vision pipeline over the recorded video (an algorithm check, forward-only).",
|
||
"run": "Run / Stop",
|
||
"stop": "Cancel acquisition",
|
||
"preview": "Preview / Stop preview",
|
||
"reset": "Reset tracker",
|
||
"help": "Help",
|
||
"about": "About"
|
||
},
|
||
"dialog": {
|
||
"plot_settings_title": "Plot settings",
|
||
"plot_window": "Time window",
|
||
"plot_window_tip": "Force plot time window (seconds)",
|
||
"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_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",
|
||
"reset_defaults": "Reset to defaults",
|
||
"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": "Temporal smoothing of the optical flow. 1.00 = off. It changes what is *measured* (contact statistics and forces along with it), so two recordings with different α are not comparable — only use it when the flow jitter really has to go",
|
||
"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"
|
||
},
|
||
"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": "Recompute from video…",
|
||
"recompute_tip": "Run the pipeline over this recording again: the 2D panel then shows the processed image (the recording itself stores only the raw camera image) and the charts and 3D view use the recomputed values. You can press Stop at any time.",
|
||
"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_disabled_video": "Select a video file first",
|
||
"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 use View ▸ Recompute forces from the video",
|
||
"playback_video_only": "Play this video (no recording beside it: the picture plays, the force charts are empty)",
|
||
"reset": "Reset",
|
||
"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"
|
||
},
|
||
"panels": {
|
||
"arrow": "2D image",
|
||
"view_arrows_pure": "Arrows",
|
||
"view_arrows_stitched": "Arrows / Captured",
|
||
"view_depth": "Depth map",
|
||
"view_recorded": "Recorded image",
|
||
"view_mode_tip": "Image display mode while running",
|
||
"replay_pipeline": "Recorded video (raw camera image)",
|
||
"replay_pipeline_tip": "Replay shows the recorded raw camera image with no live arrow overlay; to check the algorithm, use View → Recompute forces from the video",
|
||
"replay_raw_note": "A recording stores only the raw camera image: there is no flow or depth to draw. Use “Recompute from the video” for the algorithm's output",
|
||
"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 recording open\nPress “Open recording…” below",
|
||
"arrow_empty": "No image yet\nPick a video or camera, then press Run",
|
||
"arrow_empty_tip": "The deformation arrow image appears here while running or previewing",
|
||
"depth_unavailable": "No depth data for this frame\n(not a depth of zero, and no silent fallback to the processed image)",
|
||
"depth_scale": "Depth scale {low} – {high}",
|
||
"arrow_scale": "Arrows: displacement ×{factor}",
|
||
"arrow_scale_tip": "Display magnification of the relative displacement: the arrows are drawn from the algorithm output of the captured image, with the measured displacement multiplied by this factor and capped at 0.8 of the grid spacing (a capped arrow no longer shows its true factor).",
|
||
"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.",
|
||
"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."
|
||
},
|
||
"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",
|
||
"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": "Selection {duration}s / {samples} samples — {detail}",
|
||
"selection_summary": "Selection {duration}s / {samples} samples",
|
||
"selection_detail": "mean {mean} · σ {std}",
|
||
"selection_peak_tip": "The large number is the selection's peak; the line under it is its mean",
|
||
"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)",
|
||
"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": {
|
||
"title": "Replay recording",
|
||
"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": "“{name}” is not a recording: its folder has no forces.csv (a recording is the video plus forces.csv and session.json). Replay needs a recording; to just watch this video, use “Recompute forces from the video”.",
|
||
"video_only_opened": "“{name}” has no recording beside it (no forces.csv), so it is playing as a video: the picture and the timeline work, the force charts are empty. For forces and deformation use View ▸ Recompute forces from the video.",
|
||
"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 View ▸ Recompute forces from the 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"
|
||
},
|
||
"record": {
|
||
"label": "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…",
|
||
"failed_state": "The recording failed (see the summary and the log)",
|
||
"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",
|
||
"col_raw": "Raw mean",
|
||
"col_n": "n",
|
||
"col_std": "σ",
|
||
"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",
|
||
"col_actions": "",
|
||
"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_local": "Also wrote {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 file: {name}",
|
||
"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": "The camera delivers less than the configured frame rate: {detail}. The recording keeps the real rate. This is a capture-side (camera/driver) matter that software cannot change: use a camera that really does deliver 30 fps — after checking that the cable or port is not slowing this one down — and measure again.",
|
||
"video_ended": "Video ended",
|
||
"camera_disconnected": "Camera disconnected",
|
||
"reset_ok": "Tracker reset",
|
||
"reset_pending": "Zeroing requested; waiting for the acquisition thread to confirm…",
|
||
"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": "Calibration unavailable — showing raw units",
|
||
"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.",
|
||
"scale": "Colour scale",
|
||
"scale_range": "Range",
|
||
"scale_range_tip": "Bounds of the colour scale in fixed mode. In automatic mode the range comes from the valid samples of the frame on screen, so a quantity whose size differs by orders of magnitude is still readable.",
|
||
"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",
|
||
"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 “Recompute forces from the video” and this pane will show the deformation recomputed from the recording.",
|
||
"source_recompute": "Recomputed from the recording — not the recorded values",
|
||
"source_recompute_tip": "This is what the current algorithm version says about the recorded footage: it is a check on the algorithm, not the measurement that was recorded at the time.",
|
||
"severity_info": "Note",
|
||
"severity_warning": "Warning",
|
||
"severity_error": "Error",
|
||
"stats": "shown {displayed} · dropped {dropped} · compose {compose} ms · paint {paint} ms"
|
||
}
|
||
}
|