{ "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" }, "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", "plot_settings": "Plot settings…", "rotate_arrows": "Rotate arrows 90°", "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", "ok": "OK", "cancel": "Cancel" }, "toolbar": { "source": "Source", "source_camera": "Camera", "source_video": "Video file", "search_cameras": "Search", "cam_id": "Cam ID", "browse_video": "Browse…", "video_placeholder": "No video selected", "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", "reset": "Reset", "units": "Units", "units_newton": "Newton", "units_raw": "Raw" }, "units": { "newton_short": "N", "raw_short": "raw" }, "sensor": { "type": "Product", "config": "Config", "thumb_placeholder": "Product model" }, "panels": { "arrow": "2D arrows", "view_arrows_pure": "Arrows", "view_arrows_stitched": "Arrows / Captured", "view_depth": "Depth map", "view_mode_tip": "Image display mode while running", "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}", "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": "Finger 3D view placeholder —\nOpen3D mesh coming later", "mesh3d_empty_tip": "3D mesh preview for finger sensors" }, "chart": { "fn": "FN", "fx": "FX", "fy": "FY", "no_data": "—", "mode_follow": "Following live", "mode_browse": "Browsing history (display paused; 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)", "selection": "Selection {duration}s / {samples} samples — {detail}", "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)", "browse_only_tip": "Drag or scroll on the chart to browse history" }, "layout": { "default": "Free layout", "preset_2d_name": "2D mode (depth + charts)", "preset_2d": "2D mode: depth map on the left, force charts on the right, one shared time axis", "preset_default": "Free layout restored" }, "playback": { "title": "Replay recording", "open": "Open recording directory…", "open_failed": "Could not open that recording: {error}", "none_found": "No recording found under outputs/recordings", "loaded": "{name} — {frames} frames / {duration} s", "empty": "Pick a recording directory to start replay", "position": "{position} / {duration} s", "show_newton": "Show newtons", "show_raw": "Show raw", "recompute_depth": "Recompute depth", "recompute_depth_tip": "Depth is not stored with a recording; recompute this frame offline from the video and the config", "frame_dropped": "This frame never reached the video (the record queue overflowed)", "frame_unreadable": "This frame could not be decoded from the video", "depth_hint": "Depth is not stored: press Recompute depth to rebuild it from the video and the config", "depth_running": "Recomputing depth… (on a worker thread)", "depth_busy": "The previous recomputation is still running", "depth_empty": "No depth data for this frame", "depth_failed": "Depth recomputation failed: {detail}", "depth_sdk_unavailable": "Cannot recompute: the SDK is not available", "depth_config_missing": "Cannot recompute: the recording has no sensor config reference", "depth_config_file_missing": "Cannot recompute: the config file no longer exists at that path", "depth_no_video": "Cannot recompute: this recording has no video segment", "depth_not_recomputed": "Depth has not been recomputed for this cursor position\n(the previous frame's map is not reused)", "depth_recomputing": "Recomputing depth for the current cursor position…", "depth_frame_not_recorded": "This frame was not recorded: its data row was lost to a full queue and only the index row remains", "depth_frame_not_in_video": "This frame never reached the video, so its depth cannot be recomputed", "depth_state_across_segment": "Replay cannot carry the algorithm state across segments: this one restarts at its first frame", "depth_state_approximate": "No reset or pre-roll history for this segment: the algorithm state is an approximation", "depth_warnings": "Recomputation notes: {detail}", "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 the recomputed depth may differ", "warn_sdk_changed": "the SDK version differs from recording time, so the recomputation may differ", "warn_config_missing": "no config hash was recorded, so recomputation cannot be verified", "warn_depth_recomputed": "depth comes from offline recomputation, not from stored data", "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", "warn_state_across_segment": "the algorithm state cannot be carried across a segment", "warn_state_approximate": "the algorithm state is an approximation", "warn_state_approximate_after_rewind": "the video was reopened to reach an earlier frame, so the state may differ", "warn_state_too_far_back": "the zeroing is too far back: reading there would exceed the replay budget, so the state is approximate", "warn_reset_frame_not_indexed": "the zeroing frame is not in the frame index, so the state cannot be rebuilt from it", "warn_reset_frame_not_in_video": "the zeroing frame never reached the video, so the state cannot be rebuilt from it", "warn_reset_not_applied": "the replay could not re-apply the zeroing, so the state 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}" }, "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": { "ready": "Ready", "phase_idle": "Idle", "phase_connecting": "Connecting", "phase_running": "Running", "phase_error": "Error", "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}", "connecting": "Connecting…", "connect_slow": "This is taking a while — click “Cancel” or press Esc to abort", "run_started": "Running ({source})", "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}", "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}" } }